From 8cbcd48461deaa4753c91ff5b9dabf00bb7374d6 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 24 Mar 2016 16:07:17 -0400 Subject: [PATCH 001/693] Backport EQEmu::GetSkillUseTypesMap() methodology to VS2012 compatibility - VS2013 code left in situ --- common/skills.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/common/skills.cpp b/common/skills.cpp index 987004a2a..bc5942fcd 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -109,6 +109,7 @@ bool EQEmu::IsBardInstrumentSkill(SkillUseTypes skill) const std::map& EQEmu::GetSkillUseTypesMap() { + /* VS2013 code static const std::map skill_use_types_map = { { Skill1HBlunt, "1H Blunt" }, { Skill1HSlashing, "1H Slashing" }, @@ -189,6 +190,99 @@ const std::map& EQEmu::GetSkillUseTypesMap() { SkillTripleAttack, "Triple Attack" }, { Skill2HPiercing, "2H Piercing" } }; + */ + + /* VS2012 code - begin */ + + static const char* skill_use_names[_EmuSkillCount] = { + "1H Blunt", + "1H Slashing", + "2H Blunt", + "2H Slashing", + "Abjuration", + "Alteration", + "Apply Poison", + "Archery", + "Backstab", + "Bind Wound", + "Bash", + "Block", + "Brass Instruments", + "Channeling", + "Conjuration", + "Defense", + "Disarm", + "Disarm Traps", + "Divination", + "Dodge", + "Double Attack", + "Dragon Punch", + "Dual Wield", + "Eagle Strike", + "Evocation", + "Feign Death", + "Flying Kick", + "Forage", + "Hand to Hand", + "Hide", + "Kick", + "Meditate", + "Mend", + "Offense", + "Parry", + "Pick Lock", + "1H Piercing", + "Riposte", + "Round Kick", + "Safe Fall", + "Sense Heading", + "Singing", + "Sneak", + "Specialize Abjuration", + "Specialize Alteration", + "Specialize Conjuration", + "Specialize Divination", + "Specialize Evocation", + "Pick Pockets", + "Stringed Instruments", + "Swimming", + "Throwing", + "Tiger Claw", + "Tracking", + "Wind Instruments", + "Fishing", + "Make Poison", + "Tinkering", + "Research", + "Alchemy", + "Baking", + "Tailoring", + "Sense Traps", + "Blacksmithing", + "Fletching", + "Brewing", + "Alcohol Tolerance", + "Begging", + "Jewelry Making", + "Pottery", + "Percussion Instruments", + "Intimidation", + "Berserking", + "Taunt", + "Frenzy", + "Remove Traps", + "Triple Attack", + "2H Piercing" + }; + + static std::map skill_use_types_map; + + skill_use_types_map.clear(); + + for (int i = Skill1HBlunt; i < _EmuSkillCount; ++i) + skill_use_types_map[(SkillUseTypes)i] = skill_use_names[i]; + + /* VS2012 code - end */ return skill_use_types_map; } From fc5d6bd79235ec3ad756563a26b2b4a19e19b946 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 24 Mar 2016 16:26:29 -0400 Subject: [PATCH 002/693] Fix for AE taunt to use correct range and hate modifier. Fix for spell effect version of taunt to use correct range. --- changelog.txt | 4 ++++ zone/effects.cpp | 6 +++--- zone/entity.h | 2 +- zone/mob.h | 2 +- zone/special_attacks.cpp | 6 +++--- zone/spell_effects.cpp | 18 ++++++++---------- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/changelog.txt b/changelog.txt index e3762b3dd..cd25aa82c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/24/2016 == +Kayen: Fix for AE taunt to use correct range and hate modifier. + Fix for spell effect version of taunt to use correct range. + == 03/05/2016 == mackal: Implement extra bind points (secondary recall) For SE_Gate, base2 is which bind to use (starting at 1) diff --git a/zone/effects.cpp b/zone/effects.cpp index 05f6cd927..52b148fc9 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -712,10 +712,10 @@ void Client::SendDisciplineTimer(uint32 timer_id, uint32 duration) } } -void EntityList::AETaunt(Client* taunter, float range) +void EntityList::AETaunt(Client* taunter, float range, int32 bonus_hate) { if (range == 0) - range = 100; //arbitrary default... + range = 40; //Live AE taunt range - Hardcoded. range = range * range; @@ -729,7 +729,7 @@ void EntityList::AETaunt(Client* taunter, float range) && taunter->IsAttackAllowed(them) && DistanceSquaredNoZ(taunter->GetPosition(), them->GetPosition()) <= range) { if (taunter->CheckLosFN(them)) { - taunter->Taunt(them, true); + taunter->Taunt(them, true,0,true,bonus_hate); } } ++it; diff --git a/zone/entity.h b/zone/entity.h index 0b9521179..df0b327a5 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -323,7 +323,7 @@ public: void QueueManaged(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, bool ackreq = true); void AEAttack(Mob *attacker, float dist, int Hand = MainPrimary, int count = 0, bool IsFromSpell = false); - void AETaunt(Client *caster, float range = 0); + void AETaunt(Client *caster, float range=0, int32 bonus_hate=0); void AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true, int16 resist_adjust = 0); void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true); void AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true); diff --git a/zone/mob.h b/zone/mob.h index 11c11573f..c4a75b5aa 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -799,7 +799,7 @@ public: void StartEnrage(); void ProcessEnrage(); bool IsEnraged(); - void Taunt(NPC* who, bool always_succeed, float chance_bonus = 0); + void Taunt(NPC* who, bool always_succeed, float chance_bonus=0, bool FromSpell=false, int32 bonus_hate=0); virtual void AI_Init(); virtual void AI_Start(uint32 iMoveDelay = 0); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 6c6177d29..27a72f62c 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -2103,7 +2103,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) } } -void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) { +void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus, bool FromSpell, int32 bonus_hate) { if (who == nullptr) return; @@ -2111,7 +2111,7 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) { if(DivineAura()) return; - if(!CombatRange(who)) + if(!FromSpell && !CombatRange(who)) return; if(!always_succeed && IsClient()) @@ -2167,7 +2167,7 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) { if (tauntchance > zone->random.Real(0, 1)) { if (hate_top && hate_top != this){ - newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1; + newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1 + bonus_hate; who->CastToNPC()->AddToHateList(this, newhate); Success = true; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ca10259a1..ecf2bb7ba 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2230,17 +2230,18 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_AETaunt://Dook- slapped it in the spell effect so client does the animations - { // and incase there are similar spells we havent found yet + case SE_AETaunt: + { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "AE Taunt"); #endif if(caster && caster->IsClient()){ - float range = 0.0f; - if (spells[spell_id].base2[i]) - range = (float)spells[spell_id].base[i]; + //Live AE Taunt range is hardcoded at 40 (Spells for AE taunt all use zero range) Target type should be self only. + float range = 40; + if (spells[spell_id].max[i])//custom support if you want to alter range of AE Taunt. + range = spells[spell_id].max[i]; - entity_list.AETaunt(caster->CastToClient(), range); + entity_list.AETaunt(caster->CastToClient(), range, spells[spell_id].base[i]); } break; } @@ -2650,10 +2651,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_Taunt: { if (IsNPC()){ - caster->Taunt(this->CastToNPC(), false, static_cast(spell.base[i])); - - if (spell.base2[i] > 0) - CastToNPC()->SetHateAmountOnEnt(caster, (CastToNPC()->GetHateAmount(caster) + spell.base2[i])); + caster->Taunt(this->CastToNPC(), false, static_cast(spell.base[i]), true, spell.base2[i]); } break; } From b327da7092b2ae3af360064482da9b4d3ae88516 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 24 Mar 2016 18:50:31 -0400 Subject: [PATCH 003/693] Activation of the new 'Bots' command system --- changelog.txt | 5 + common/classes.cpp | 841 +- common/classes.h | 142 +- common/database.h | 4 +- common/eq_constants.h | 92 +- common/item.cpp | 4 +- common/patches/ss_define.h | 23 + common/races.cpp | 910 +- common/races.h | 186 +- common/ruletypes.h | 19 + common/shareddb.cpp | 38 +- common/shareddb.h | 23 +- common/spdat.h | 6 +- common/version.h | 4 +- utils/scripts/opcode_handlers.py | 1 + .../sql/git/bots/bots_db_update_manifest.txt | 2 + .../2016_03_24_bots_command_rules.sql | 5 + .../2016_03_24_bots_command_settings.sql | 102 + world/client.cpp | 20 +- world/clientlist.cpp | 9 +- world/eqw.cpp | 6 +- zone/CMakeLists.txt | 6 + zone/aa.cpp | 4 +- zone/bot.cpp | 5245 ++---------- zone/bot.h | 221 +- zone/bot_command.cpp | 7312 +++++++++++++++++ zone/bot_command.h | 667 ++ zone/bot_database.cpp | 732 ++ zone/bot_database.h | 87 + zone/bot_structs.h | 19 + zone/botspellsai.cpp | 26 +- zone/client.cpp | 32 +- zone/client_mods.cpp | 6 +- zone/client_packet.cpp | 3 +- zone/command.cpp | 48 +- zone/command.h | 2 +- zone/embparser.cpp | 10 +- zone/embxs.cpp | 30 +- zone/entity.h | 3 +- zone/groups.cpp | 62 +- zone/groups.h | 10 +- zone/heal_rotation.cpp | 882 ++ zone/heal_rotation.h | 148 + zone/inventory.cpp | 7 +- zone/mob.cpp | 374 +- zone/mob.h | 25 +- zone/net.cpp | 30 +- zone/worldserver.cpp | 4 +- 48 files changed, 12821 insertions(+), 5616 deletions(-) create mode 100644 utils/sql/git/bots/required/2016_03_24_bots_command_rules.sql create mode 100644 utils/sql/git/bots/required/2016_03_24_bots_command_settings.sql create mode 100644 zone/bot_command.cpp create mode 100644 zone/bot_command.h create mode 100644 zone/bot_database.cpp create mode 100644 zone/bot_database.h create mode 100644 zone/heal_rotation.cpp create mode 100644 zone/heal_rotation.h diff --git a/changelog.txt b/changelog.txt index cd25aa82c..174196c4f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 03/24/2016 == Kayen: Fix for AE taunt to use correct range and hate modifier. Fix for spell effect version of taunt to use correct range. +Uleat: Activation of new 'Bots' command system + - You will need to re-run cmake to capture the file additions and then re-compile your server binaries + - You will also need to manually run eqemu_update.pl and select the bots update option - you should have 2 pending updates: 9001 & 9002 + - The new command system is accessed with the '^' character - start with '^help' and see where that takes you + - More information can be found on the eqemu forums == 03/05/2016 == mackal: Implement extra bind points (secondary recall) diff --git a/common/classes.cpp b/common/classes.cpp index 1f54c9234..58aa56602 100644 --- a/common/classes.cpp +++ b/common/classes.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,275 +18,576 @@ #include "../common/global_define.h" #include "../common/classes.h" -const char* GetEQClassName(uint8 class_, uint8 level) { - switch(class_) { - case WARRIOR: - if (level >= 70) - return "Vanquisher"; - else if (level >= 65) - return "Overlord"; //Baron-Sprite: LEAVE MY CLASSES ALONE. - else if (level >= 60) - return "Warlord"; - else if (level >= 55) - return "Myrmidon"; - else if (level >= 51) - return "Champion"; - else - return "Warrior"; - case CLERIC: - if (level >= 70) - return "Prelate"; - else if (level >= 65) - return "Archon"; - else if (level >= 60) - return "High Priest"; - else if (level >= 55) - return "Templar"; - else if (level >= 51) - return "Vicar"; - else - return "Cleric"; - case PALADIN: - if (level >= 70) - return "Lord"; - else if (level >= 65) - return "Lord Protector"; - else if (level >= 60) - return "Crusader"; - else if (level >= 55) - return "Knight"; - else if (level >= 51) - return "Cavalier"; - else - return "Paladin"; - case RANGER: - if (level >= 70) - return "Plainswalker"; - else if (level >= 65) - return "Forest Stalker"; - else if (level >= 60) - return "Warder"; - else if (level >= 55) - return "Outrider"; - else if (level >= 51) - return "Pathfinder"; - else - return "Ranger"; - case SHADOWKNIGHT: - if (level >= 70) - return "Scourge Knight"; - else if (level >= 65) - return "Dread Lord"; - else if (level >= 60) - return "Grave Lord"; - else if (level >= 55) - return "Revenant"; - else if (level >= 51) - return "Reaver"; - else - return "Shadowknight"; - case DRUID: - if (level >= 70) - return "Natureguard"; - else if (level >= 65) - return "Storm Warden"; - else if (level >= 60) - return "Hierophant"; - else if (level >= 55) - return "Preserver"; - else if (level >= 51) - return "Wanderer"; - else - return "Druid"; - case MONK: - if (level >= 70) - return "Stone Fist"; - else if (level >= 65) - return "Transcendent"; - else if (level >= 60) - return "Grandmaster"; - else if (level >= 55) - return "Master"; - else if (level >= 51) - return "Disciple"; - else - return "Monk"; - case BARD: - if (level >= 70) - return "Performer"; - else if (level >= 65) - return "Maestro"; - else if (level >= 60) - return "Virtuoso"; - else if (level >= 55) - return "Troubadour"; - else if (level >= 51) - return "Minstrel"; - else - return "Bard"; - case ROGUE: - if (level >= 70) - return "Nemesis"; - else if (level >= 65) - return "Deceiver"; - else if (level >= 60) - return "Assassin"; - else if (level >= 55) - return "Blackguard"; - else if (level >= 51) - return "Rake"; - else - return "Rogue"; - case SHAMAN: - if (level >= 70) - return "Soothsayer"; - else if (level >= 65) - return "Prophet"; - else if (level >= 60) - return "Oracle"; - else if (level >= 55) - return "Luminary"; - else if (level >= 51) - return "Mystic"; - else - return "Shaman"; - case NECROMANCER: - if (level >= 70) - return "Wraith"; - else if (level >= 65) - return "Arch Lich"; - else if (level >= 60) - return "Warlock"; - else if (level >= 55) - return "Defiler"; - else if (level >= 51) - return "Heretic"; - else - return "Necromancer"; - case WIZARD: - if (level >= 70) - return "Grand Arcanist"; - else if (level >= 65) - return "Arcanist"; - else if (level >= 60) - return "Sorcerer"; - else if (level >= 55) - return "Evoker"; - else if (level >= 51) - return "Channeler"; - else - return "Wizard"; - case MAGICIAN: - if (level >= 70) - return "Arch Magus"; - else if (level >= 65) - return "Arch Convoker"; - else if (level >= 60) - return "Arch Mage"; - else if (level >= 55) - return "Conjurer"; - if (level >= 51) - return "Elementalist"; - else - return "Magician"; - case ENCHANTER: - if (level >= 70) - return "Bedazzler"; - else if (level >= 65) - return "Coercer"; - else if (level >= 60) - return "Phantasmist"; - else if (level >= 55) - return "Beguiler"; - else if (level >= 51) - return "Illusionist"; - else - return "Enchanter"; - case BEASTLORD: - if (level >= 70) - return "Wildblood"; - else if (level >= 65) - return "Feral Lord"; - else if (level >= 60) - return "Savage Lord"; - else if (level >= 55) - return "Animist"; - else if (level >= 51) - return "Primalist"; - else - return "Beastlord"; - case BERSERKER: - if (level >= 70) - return "Ravager"; - else if (level >= 65) - return "Fury"; - else if (level >= 60) - return "Rager"; - else if (level >= 55) - return "Vehement"; - else if (level >= 51) - return "Brawler"; - else - return "Berserker"; - case BANKER: - if (level >= 70) - return "Master Banker"; - else if (level >= 65) - return "Elder Banker"; - else if (level >= 60) - return "Oldest Banker"; - else if (level >= 55) - return "Older Banker"; - else if (level >= 51) - return "Old Banker"; - else - return "Banker"; - case WARRIORGM: - return "Warrior Guildmaster"; - case CLERICGM: - return "Cleric Guildmaster"; - case PALADINGM: - return "Paladin Guildmaster"; - case RANGERGM: - return "Ranger Guildmaster"; - case SHADOWKNIGHTGM: - return "Shadowknight Guildmaster"; - case DRUIDGM: - return "Druid Guildmaster"; - case MONKGM: - return "Monk Guildmaster"; - case BARDGM: - return "Bard Guildmaster"; - case ROGUEGM: - return "Rogue Guildmaster"; - case SHAMANGM: - return "Shaman Guildmaster"; - case NECROMANCERGM: - return "Necromancer Guildmaster"; - case WIZARDGM: - return "Wizard Guildmaster"; - case MAGICIANGM: - return "Magician Guildmaster"; - case ENCHANTERGM: - return "Enchanter Guildmaster"; - case BEASTLORDGM: - return "Beastlord Guildmaster"; - case BERSERKERGM: - return "Berserker Guildmaster"; - case MERCHANT: - return "Merchant"; - case ADVENTURERECRUITER: - return "Adventure Recruiter"; - case ADVENTUREMERCHANT: - return "Adventure Merchant"; - case CORPSE_CLASS: - return "Corpse Class"; - case TRIBUTE_MASTER: - return "Tribute Master"; - case GUILD_TRIBUTE_MASTER: - return "Guild Tribute Master"; - default: - return "Unknown"; +const char* GetClassIDName(uint8 class_id, uint8 level) +{ + switch (class_id) { + case WARRIOR: + if (level >= 70) + return "Vanquisher"; + else if (level >= 65) + return "Overlord"; //Baron-Sprite: LEAVE MY CLASSES ALONE. + else if (level >= 60) + return "Warlord"; + else if (level >= 55) + return "Myrmidon"; + else if (level >= 51) + return "Champion"; + else + return "Warrior"; + case CLERIC: + if (level >= 70) + return "Prelate"; + else if (level >= 65) + return "Archon"; + else if (level >= 60) + return "High Priest"; + else if (level >= 55) + return "Templar"; + else if (level >= 51) + return "Vicar"; + else + return "Cleric"; + case PALADIN: + if (level >= 70) + return "Lord"; + else if (level >= 65) + return "Lord Protector"; + else if (level >= 60) + return "Crusader"; + else if (level >= 55) + return "Knight"; + else if (level >= 51) + return "Cavalier"; + else + return "Paladin"; + case RANGER: + if (level >= 70) + return "Plainswalker"; + else if (level >= 65) + return "Forest Stalker"; + else if (level >= 60) + return "Warder"; + else if (level >= 55) + return "Outrider"; + else if (level >= 51) + return "Pathfinder"; + else + return "Ranger"; + case SHADOWKNIGHT: + if (level >= 70) + return "Scourge Knight"; + else if (level >= 65) + return "Dread Lord"; + else if (level >= 60) + return "Grave Lord"; + else if (level >= 55) + return "Revenant"; + else if (level >= 51) + return "Reaver"; + else + return "Shadowknight"; + case DRUID: + if (level >= 70) + return "Natureguard"; + else if (level >= 65) + return "Storm Warden"; + else if (level >= 60) + return "Hierophant"; + else if (level >= 55) + return "Preserver"; + else if (level >= 51) + return "Wanderer"; + else + return "Druid"; + case MONK: + if (level >= 70) + return "Stone Fist"; + else if (level >= 65) + return "Transcendent"; + else if (level >= 60) + return "Grandmaster"; + else if (level >= 55) + return "Master"; + else if (level >= 51) + return "Disciple"; + else + return "Monk"; + case BARD: + if (level >= 70) + return "Performer"; + else if (level >= 65) + return "Maestro"; + else if (level >= 60) + return "Virtuoso"; + else if (level >= 55) + return "Troubadour"; + else if (level >= 51) + return "Minstrel"; + else + return "Bard"; + case ROGUE: + if (level >= 70) + return "Nemesis"; + else if (level >= 65) + return "Deceiver"; + else if (level >= 60) + return "Assassin"; + else if (level >= 55) + return "Blackguard"; + else if (level >= 51) + return "Rake"; + else + return "Rogue"; + case SHAMAN: + if (level >= 70) + return "Soothsayer"; + else if (level >= 65) + return "Prophet"; + else if (level >= 60) + return "Oracle"; + else if (level >= 55) + return "Luminary"; + else if (level >= 51) + return "Mystic"; + else + return "Shaman"; + case NECROMANCER: + if (level >= 70) + return "Wraith"; + else if (level >= 65) + return "Arch Lich"; + else if (level >= 60) + return "Warlock"; + else if (level >= 55) + return "Defiler"; + else if (level >= 51) + return "Heretic"; + else + return "Necromancer"; + case WIZARD: + if (level >= 70) + return "Grand Arcanist"; + else if (level >= 65) + return "Arcanist"; + else if (level >= 60) + return "Sorcerer"; + else if (level >= 55) + return "Evoker"; + else if (level >= 51) + return "Channeler"; + else + return "Wizard"; + case MAGICIAN: + if (level >= 70) + return "Arch Magus"; + else if (level >= 65) + return "Arch Convoker"; + else if (level >= 60) + return "Arch Mage"; + else if (level >= 55) + return "Conjurer"; + if (level >= 51) + return "Elementalist"; + else + return "Magician"; + case ENCHANTER: + if (level >= 70) + return "Bedazzler"; + else if (level >= 65) + return "Coercer"; + else if (level >= 60) + return "Phantasmist"; + else if (level >= 55) + return "Beguiler"; + else if (level >= 51) + return "Illusionist"; + else + return "Enchanter"; + case BEASTLORD: + if (level >= 70) + return "Wildblood"; + else if (level >= 65) + return "Feral Lord"; + else if (level >= 60) + return "Savage Lord"; + else if (level >= 55) + return "Animist"; + else if (level >= 51) + return "Primalist"; + else + return "Beastlord"; + case BERSERKER: + if (level >= 70) + return "Ravager"; + else if (level >= 65) + return "Fury"; + else if (level >= 60) + return "Rager"; + else if (level >= 55) + return "Vehement"; + else if (level >= 51) + return "Brawler"; + else + return "Berserker"; + case BANKER: + if (level >= 70) + return "Master Banker"; + else if (level >= 65) + return "Elder Banker"; + else if (level >= 60) + return "Oldest Banker"; + else if (level >= 55) + return "Older Banker"; + else if (level >= 51) + return "Old Banker"; + else + return "Banker"; + case WARRIORGM: + return "Warrior Guildmaster"; + case CLERICGM: + return "Cleric Guildmaster"; + case PALADINGM: + return "Paladin Guildmaster"; + case RANGERGM: + return "Ranger Guildmaster"; + case SHADOWKNIGHTGM: + return "Shadowknight Guildmaster"; + case DRUIDGM: + return "Druid Guildmaster"; + case MONKGM: + return "Monk Guildmaster"; + case BARDGM: + return "Bard Guildmaster"; + case ROGUEGM: + return "Rogue Guildmaster"; + case SHAMANGM: + return "Shaman Guildmaster"; + case NECROMANCERGM: + return "Necromancer Guildmaster"; + case WIZARDGM: + return "Wizard Guildmaster"; + case MAGICIANGM: + return "Magician Guildmaster"; + case ENCHANTERGM: + return "Enchanter Guildmaster"; + case BEASTLORDGM: + return "Beastlord Guildmaster"; + case BERSERKERGM: + return "Berserker Guildmaster"; + case MERCHANT: + return "Merchant"; + case ADVENTURERECRUITER: + return "Adventure Recruiter"; + case ADVENTUREMERCHANT: + return "Adventure Merchant"; + case CORPSE_CLASS: + return "Corpse Class"; + case TRIBUTE_MASTER: + return "Tribute Master"; + case GUILD_TRIBUTE_MASTER: + return "Guild Tribute Master"; + default: + return "Unknown"; } } +const char* GetPlayerClassName(uint32 player_class_value, uint8 level) +{ + return GetClassIDName(GetClassIDFromPlayerClassValue(player_class_value), level); +} + +uint32 GetPlayerClassValue(uint8 class_id) +{ + switch (class_id) { + case WARRIOR: + case CLERIC: + case PALADIN: + case RANGER: + case SHADOWKNIGHT: + case DRUID: + case MONK: + case BARD: + case ROGUE: + case SHAMAN: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + case BEASTLORD: + case BERSERKER: + return class_id; + default: + return PLAYER_CLASS_UNKNOWN; // watch + } +} + +uint32 GetPlayerClassBit(uint8 class_id) +{ + switch (class_id) { + case WARRIOR: + return PLAYER_CLASS_WARRIOR_BIT; + case CLERIC: + return PLAYER_CLASS_CLERIC_BIT; + case PALADIN: + return PLAYER_CLASS_PALADIN_BIT; + case RANGER: + return PLAYER_CLASS_RANGER_BIT; + case SHADOWKNIGHT: + return PLAYER_CLASS_SHADOWKNIGHT_BIT; + case DRUID: + return PLAYER_CLASS_DRUID_BIT; + case MONK: + return PLAYER_CLASS_MONK_BIT; + case BARD: + return PLAYER_CLASS_BARD_BIT; + case ROGUE: + return PLAYER_CLASS_ROGUE_BIT; + case SHAMAN: + return PLAYER_CLASS_SHAMAN_BIT; + case NECROMANCER: + return PLAYER_CLASS_NECROMANCER_BIT; + case WIZARD: + return PLAYER_CLASS_WIZARD_BIT; + case MAGICIAN: + return PLAYER_CLASS_MAGICIAN_BIT; + case ENCHANTER: + return PLAYER_CLASS_ENCHANTER_BIT; + case BEASTLORD: + return PLAYER_CLASS_BEASTLORD_BIT; + case BERSERKER: + return PLAYER_CLASS_BERSERKER_BIT; + default: + return PLAYER_CLASS_UNKNOWN_BIT; + } +} + +uint8 GetClassIDFromPlayerClassValue(uint32 player_class_value) +{ + switch (player_class_value) { + case PLAYER_CLASS_WARRIOR: + case PLAYER_CLASS_CLERIC: + case PLAYER_CLASS_PALADIN: + case PLAYER_CLASS_RANGER: + case PLAYER_CLASS_SHADOWKNIGHT: + case PLAYER_CLASS_DRUID: + case PLAYER_CLASS_MONK: + case PLAYER_CLASS_BARD: + case PLAYER_CLASS_ROGUE: + case PLAYER_CLASS_SHAMAN: + case PLAYER_CLASS_NECROMANCER: + case PLAYER_CLASS_WIZARD: + case PLAYER_CLASS_MAGICIAN: + case PLAYER_CLASS_ENCHANTER: + case PLAYER_CLASS_BEASTLORD: + case PLAYER_CLASS_BERSERKER: + return player_class_value; + default: + return PLAYER_CLASS_UNKNOWN; // watch + } +} + +uint8 GetClassIDFromPlayerClassBit(uint32 player_class_bit) +{ + switch (player_class_bit) { + case PLAYER_CLASS_WARRIOR_BIT: + return WARRIOR; + case PLAYER_CLASS_CLERIC_BIT: + return CLERIC; + case PLAYER_CLASS_PALADIN_BIT: + return PALADIN; + case PLAYER_CLASS_RANGER_BIT: + return RANGER; + case PLAYER_CLASS_SHADOWKNIGHT_BIT: + return SHADOWKNIGHT; + case PLAYER_CLASS_DRUID_BIT: + return DRUID; + case PLAYER_CLASS_MONK_BIT: + return MONK; + case PLAYER_CLASS_BARD_BIT: + return BARD; + case PLAYER_CLASS_ROGUE_BIT: + return ROGUE; + case PLAYER_CLASS_SHAMAN_BIT: + return SHAMAN; + case PLAYER_CLASS_NECROMANCER_BIT: + return NECROMANCER; + case PLAYER_CLASS_WIZARD_BIT: + return WIZARD; + case PLAYER_CLASS_MAGICIAN_BIT: + return MAGICIAN; + case PLAYER_CLASS_ENCHANTER_BIT: + return ENCHANTER; + case PLAYER_CLASS_BEASTLORD_BIT: + return BEASTLORD; + case PLAYER_CLASS_BERSERKER_BIT: + return BERSERKER; + default: + return PLAYER_CLASS_UNKNOWN; // watch + } +} + +bool IsFighterClass(uint8 class_id) +{ + switch (class_id) { + case WARRIOR: + case PALADIN: + case RANGER: + case SHADOWKNIGHT: + case MONK: + case BARD: + case ROGUE: + case BEASTLORD: + case BERSERKER: + return true; + default: + return false; + } +} + +bool IsSpellFighterClass(uint8 class_id) +{ + switch (class_id) { + case PALADIN: + case RANGER: + case SHADOWKNIGHT: + case BEASTLORD: + return true; + default: + return false; + } +} + +bool IsNonSpellFighterClass(uint8 class_id) +{ + switch (class_id) { + case WARRIOR: + case MONK: + case BARD: + case ROGUE: + case BERSERKER: + return true; + default: + return false; + } +} + +bool IsCasterClass(uint8 class_id) +{ + switch (class_id) { + case CLERIC: + case DRUID: + case SHAMAN: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + default: + return false; + } +} + +bool IsINTCasterClass(uint8 class_id) +{ + switch (class_id) { + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + default: + return false; + } +} + +bool IsWISCasterClass(uint8 class_id) +{ + switch (class_id) { + case CLERIC: + case DRUID: + case SHAMAN: + return true; + default: + return false; + } +} + +bool IsPlateClass(uint8 class_id) +{ + switch (class_id) { + case WARRIOR: + case CLERIC: + case PALADIN: + case SHADOWKNIGHT: + case BARD: + return true; + default: + return false; + } +} + +bool IsChainClass(uint8 class_id) +{ + switch (class_id) { + case RANGER: + case ROGUE: + case SHAMAN: + case BERSERKER: + return true; + default: + return false; + } +} + +bool IsLeatherClass(uint8 class_id) +{ + switch (class_id) { + case DRUID: + case MONK: + case BEASTLORD: + return true; + default: + return false; + } +} + +bool IsClothClass(uint8 class_id) +{ + switch (class_id) { + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + default: + return false; + } +} + +uint8 ClassArmorType(uint8 class_id) +{ + switch (class_id) { + case WARRIOR: + case CLERIC: + case PALADIN: + case SHADOWKNIGHT: + case BARD: + return ARMOR_TYPE_PLATE; + case RANGER: + case ROGUE: + case SHAMAN: + case BERSERKER: + return ARMOR_TYPE_CHAIN; + case DRUID: + case MONK: + case BEASTLORD: + return ARMOR_TYPE_LEATHER; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return ARMOR_TYPE_CLOTH; + default: + return ARMOR_TYPE_UNKNOWN; + } +} diff --git a/common/classes.h b/common/classes.h index c2f0c8acf..2ca9a3c4d 100644 --- a/common/classes.h +++ b/common/classes.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,26 +17,25 @@ */ #ifndef CLASSES_CH #define CLASSES_CH + #include "../common/types.h" -#define Array_Class_UNKNOWN 0 -#define WARRIOR 1 -#define CLERIC 2 -#define PALADIN 3 -#define RANGER 4 -#define SHADOWKNIGHT 5 -#define DRUID 6 -#define MONK 7 -#define BARD 8 -#define ROGUE 9 -#define SHAMAN 10 -#define NECROMANCER 11 -#define WIZARD 12 -#define MAGICIAN 13 -#define ENCHANTER 14 -#define BEASTLORD 15 -#define BERSERKER 16 -#define PLAYER_CLASS_COUNT 16 // used for array defines, must be the count of playable classes +#define WARRIOR 1 +#define CLERIC 2 +#define PALADIN 3 +#define RANGER 4 +#define SHADOWKNIGHT 5 +#define DRUID 6 +#define MONK 7 +#define BARD 8 +#define ROGUE 9 +#define SHAMAN 10 +#define NECROMANCER 11 +#define WIZARD 12 +#define MAGICIAN 13 +#define ENCHANTER 14 +#define BEASTLORD 15 +#define BERSERKER 16 #define WARRIORGM 20 #define CLERICGM 21 #define PALADINGM 22 @@ -58,33 +57,92 @@ #define DISCORD_MERCHANT 59 #define ADVENTURERECRUITER 60 #define ADVENTUREMERCHANT 61 -#define LDON_TREASURE 62 //objects you can use /open on first seen in LDONs -#define CORPSE_CLASS 62 //only seen on Danvi's Corpse in Akheva so far.. -#define TRIBUTE_MASTER 63 -#define GUILD_TRIBUTE_MASTER 64 //not sure +#define LDON_TREASURE 62 // objects you can use /open on first seen in LDONs +#define CORPSE_CLASS 62 // only seen on Danvi's Corpse in Akheva so far.. +#define TRIBUTE_MASTER 63 +#define GUILD_TRIBUTE_MASTER 64 // not sure #define NORRATHS_KEEPERS_MERCHANT 67 #define DARK_REIGN_MERCHANT 68 #define FELLOWSHIP_MASTER 69 #define ALT_CURRENCY_MERCHANT 70 #define MERCERNARY_MASTER 71 -#define warrior_1 1 -#define monk_1 64 -#define paladin_1 4 -#define shadow_1 16 -#define bard_1 128 -#define cleric_1 2 -#define necromancer_1 1024 -#define ranger_1 8 -#define druid_1 32 -#define mage_1 4096 -#define wizard_1 2048 -#define enchanter_1 8192 -#define rogue_1 256 -#define shaman_1 512 -#define beastlord_1 16384 -#define berserker_1 32768 -#define call_1 65536 -const char* GetEQClassName(uint8 class_, uint8 level = 0); + +// player class values +#define PLAYER_CLASS_UNKNOWN 0 +#define PLAYER_CLASS_WARRIOR 1 +#define PLAYER_CLASS_CLERIC 2 +#define PLAYER_CLASS_PALADIN 3 +#define PLAYER_CLASS_RANGER 4 +#define PLAYER_CLASS_SHADOWKNIGHT 5 +#define PLAYER_CLASS_DRUID 6 +#define PLAYER_CLASS_MONK 7 +#define PLAYER_CLASS_BARD 8 +#define PLAYER_CLASS_ROGUE 9 +#define PLAYER_CLASS_SHAMAN 10 +#define PLAYER_CLASS_NECROMANCER 11 +#define PLAYER_CLASS_WIZARD 12 +#define PLAYER_CLASS_MAGICIAN 13 +#define PLAYER_CLASS_ENCHANTER 14 +#define PLAYER_CLASS_BEASTLORD 15 +#define PLAYER_CLASS_BERSERKER 16 + +#define PLAYER_CLASS_COUNT 16 + + +// player class bits +#define PLAYER_CLASS_UNKNOWN_BIT 0 +#define PLAYER_CLASS_WARRIOR_BIT 1 +#define PLAYER_CLASS_CLERIC_BIT 2 +#define PLAYER_CLASS_PALADIN_BIT 4 +#define PLAYER_CLASS_RANGER_BIT 8 +#define PLAYER_CLASS_SHADOWKNIGHT_BIT 16 +#define PLAYER_CLASS_DRUID_BIT 32 +#define PLAYER_CLASS_MONK_BIT 64 +#define PLAYER_CLASS_BARD_BIT 128 +#define PLAYER_CLASS_ROGUE_BIT 256 +#define PLAYER_CLASS_SHAMAN_BIT 512 +#define PLAYER_CLASS_NECROMANCER_BIT 1024 +#define PLAYER_CLASS_WIZARD_BIT 2048 +#define PLAYER_CLASS_MAGICIAN_BIT 4096 +#define PLAYER_CLASS_ENCHANTER_BIT 8192 +#define PLAYER_CLASS_BEASTLORD_BIT 16384 +#define PLAYER_CLASS_BERSERKER_BIT 32768 + +#define PLAYER_CLASS_ALL_MASK 65535 // was 65536 + + +#define ARMOR_TYPE_UNKNOWN 0 +#define ARMOR_TYPE_CLOTH 1 +#define ARMOR_TYPE_LEATHER 2 +#define ARMOR_TYPE_CHAIN 3 +#define ARMOR_TYPE_PLATE 4 + +#define ARMOR_TYPE_FIRST ARMOR_TYPE_UNKNOWN +#define ARMOR_TYPE_LAST ARMOR_TYPE_PLATE +#define ARMOR_TYPE_COUNT 5 + + +const char* GetClassIDName(uint8 class_id, uint8 level = 0); +const char* GetPlayerClassName(uint32 player_class_value, uint8 level = 0); + +uint32 GetPlayerClassValue(uint8 class_id); +uint32 GetPlayerClassBit(uint8 class_id); + +uint8 GetClassIDFromPlayerClassValue(uint32 player_class_value); +uint8 GetClassIDFromPlayerClassBit(uint32 player_class_bit); + +bool IsFighterClass(uint8 class_id); +bool IsSpellFighterClass(uint8 class_id); +bool IsNonSpellFighterClass(uint8 class_id); +bool IsCasterClass(uint8 class_id); +bool IsINTCasterClass(uint8 class_id); +bool IsWISCasterClass(uint8 class_id); + +bool IsPlateClass(uint8 class_id); +bool IsChainClass(uint8 class_id); +bool IsLeatherClass(uint8 class_id); +bool IsClothClass(uint8 class_id); +uint8 ClassArmorType(uint8 class_id); + #endif - diff --git a/common/database.h b/common/database.h index 02110b9a6..68197811f 100644 --- a/common/database.h +++ b/common/database.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -88,7 +88,7 @@ class Database : public DBcore { public: Database(); Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port); - bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port); + bool Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port); ~Database(); /* Character Creation */ diff --git a/common/eq_constants.h b/common/eq_constants.h index 728013eba..222d5802f 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -390,30 +390,47 @@ enum { ET_Scroll = 7 }; -//SpawnAppearance types: -#define AT_Die 0 // this causes the client to keel over and zone to bind point -#define AT_WhoLevel 1 // the level that shows up on /who -#define AT_Invis 3 // 0 = visible, 1 = invisible -#define AT_PVP 4 // 0 = blue, 1 = pvp (red) -#define AT_Light 5 // light type emitted by player (lightstone, shiny shield) -#define AT_Anim 14 // 100=standing, 110=sitting, 111=ducking, 115=feigned, 105=looting -#define AT_Sneak 15 // 0 = normal, 1 = sneaking -#define AT_SpawnID 16 // server to client, sets player spawn id -#define AT_HP 17 // Client->Server, my HP has changed (like regen tic) -#define AT_Linkdead 18 // 0 = normal, 1 = linkdead -#define AT_Levitate 19 // 0=off, 1=flymode, 2=levitate -#define AT_GM 20 // 0 = normal, 1 = GM - all odd numbers seem to make it GM -#define AT_Anon 21 // 0 = normal, 1 = anon, 2 = roleplay -#define AT_GuildID 22 -#define AT_GuildRank 23 // 0=member, 1=officer, 2=leader -#define AT_AFK 24 // 0 = normal, 1 = afk -#define AT_Pet 25 // Param is EntityID of owner, or 0 for when charm breaks -#define AT_Split 28 // 0 = normal, 1 = autosplit on -#define AT_Size 29 // spawn's size -#define AT_NPCName 31 // change PC's name's color to NPC color 0 = normal, 1 = npc name -#define AT_ShowHelm 43 // 0 = do not show helmet graphic, 1 = show graphic -#define AT_DamageState 44 // The damage state of a destructible object (0 through 4) -//#define AT_Trader 300 // Bazzar Trader Mode +//SpawnAppearance types: (compared two clients for server-originating types: SoF & RoF2) +#define AT_Die 0 // this causes the client to keel over and zone to bind point (default action) +#define AT_WhoLevel 1 // the level that shows up on /who +//#define AT_2 2 // unknown +#define AT_Invis 3 // 0 = visible, 1 = invisible +#define AT_PVP 4 // 0 = blue, 1 = pvp (red) +#define AT_Light 5 // light type emitted by player (lightstone, shiny shield) +#define AT_Anim 14 // 100=standing, 110=sitting, 111=ducking, 115=feigned, 105=looting +#define AT_Sneak 15 // 0 = normal, 1 = sneaking +#define AT_SpawnID 16 // server to client, sets player spawn id +#define AT_HP 17 // Client->Server, my HP has changed (like regen tic) +#define AT_Linkdead 18 // 0 = normal, 1 = linkdead +#define AT_Levitate 19 // 0=off, 1=flymode, 2=levitate +#define AT_GM 20 // 0 = normal, 1 = GM - all odd numbers seem to make it GM +#define AT_Anon 21 // 0 = normal, 1 = anon, 2 = roleplay +#define AT_GuildID 22 +#define AT_GuildRank 23 // 0=member, 1=officer, 2=leader +#define AT_AFK 24 // 0 = normal, 1 = afk +#define AT_Pet 25 // Param is EntityID of owner, or 0 for when charm breaks +//#define AT_27 27 // unknown +#define AT_Split 28 // 0 = normal, 1 = autosplit on (not showing in SoF+) (client-to-server only) +#define AT_Size 29 // spawn's size (present: SoF, absent: RoF2) +//#define AT_30 30 // unknown +#define AT_NPCName 31 // change PC's name's color to NPC color 0 = normal, 1 = npc name +//#define AT_32 32 // unknown +//#define AT_33 33 // unknown +//#define AT_34 34 // unknown (present: SoF, absent: RoF2) +//#define AT_35 35 // unknown +//#define AT_36 36 // unknown +//#define AT_37 37 // unknown +//#define AT_38 38 // unknown +//#define AT_39 39 // unknown +#define AT_ShowHelm 43 // 0 = hide graphic, 1 = show graphic +#define AT_DamageState 44 // The damage state of a destructible object (0 through 4) +//#define AT_46 46 // unknown +//#define AT_48 48 // unknown +//#define AT_49 49 // unknown +//#define AT_52 52 // (absent: SoF, present: RoF2) (not a replacement for RoF absent 29 or 34) +//#define AT_53 53 // (absent: SoF, present: RoF2) (not a replacement for RoF absent 29 or 34) + +//#define AT_Trader 300 // Bazaar Trader Mode (not present in SoF or RoF2) // animations for AT_Anim #define ANIM_FREEZE 102 @@ -519,15 +536,40 @@ typedef enum { #define MT_StrikeThrough 339 #define MT_Stun 340 +// TODO: Really should combine above and below into one + //from showeq enum ChatColor { + /* CC_Default = 0, CC_DarkGrey = 1, CC_DarkGreen = 2, CC_DarkBlue = 3, CC_Purple = 5, CC_LightGrey = 6, + */ + + CC_WhiteSmoke = 0, // FF|F0F0F0 + CC_Green = 2, // FF|008000 + CC_BrightBlue = 3, // FF|0040FF + CC_Magenta = 5, // FF|F000F0 + CC_Gray = 6, // FF|808080 + CC_LightGray = 7, // FF|E0E0E0 + //CC_WhiteSmoke2 = 10, // FF|F0F0F0 + CC_DarkGray = 12, // FF|A0A0A0 + CC_Red = 13, // FF|F00000 + CC_Lime = 14, // FF|00F000 + CC_Yellow = 15, // FF|F0F000 + CC_Blue = 16, // FF|0000F0 + CC_LightNavy = 17, // FF|0000AF + CC_Cyan = 18, // FF|00F0F0 + CC_Black = 20, // FF|000000 + + // any index <= 255 that is not defined above + CC_DimGray = 1, // FF|606060 + CC_Default = 1, + CC_User_Say = 256, CC_User_Tell = 257, CC_User_Group = 258, diff --git a/common/item.cpp b/common/item.cpp index 5d1142d2c..2bbc4d306 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3063,7 +3063,7 @@ bool Item_Struct::IsEquipable(uint16 Race, uint16 Class_) const uint32 Classes_ = Classes; uint32 Races_ = Races; - uint32 Race_ = GetArrayRace(Race); + uint32 Race_ = GetPlayerRaceValue(Race); for (int CurrentClass = 1; CurrentClass <= PLAYER_CLASS_COUNT; ++CurrentClass) { if (Classes_ & 1) { diff --git a/common/patches/ss_define.h b/common/patches/ss_define.h index 8502d02dd..3b2afb5b1 100644 --- a/common/patches/ss_define.h +++ b/common/patches/ss_define.h @@ -1,3 +1,20 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ #define ENCODE(x) void Strategy::Encode_##x(EQApplicationPacket **p, std::shared_ptr dest, bool ack_req) #define DECODE(x) void Strategy::Decode_##x(EQApplicationPacket *__packet) @@ -116,6 +133,12 @@ //a shorter assignment for direct mode #undef IN #define IN(x) emu->x = eq->x; +#define IN_str(x) \ + strncpy(emu->x, eq->x, sizeof(emu->x)); \ + emu->x[sizeof(emu->x)-1] = '\0'; +#define IN_array(x, n) \ + for(__i = 0; __i < n; __i++) \ + emu->x[__i] = eq->x[__i]; //call before any premature returns in an encoder using SETUP_DIRECT_DECODE #define FAIL_DIRECT_DECODE() \ diff --git a/common/races.cpp b/common/races.cpp index 6322b50af..7fd88911b 100644 --- a/common/races.cpp +++ b/common/races.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,95 +18,831 @@ #include "../common/races.h" -const char* GetRaceName(uint16 race) { - switch(race) { - case HUMAN: - return "Human"; - case BARBARIAN: - return "Barbarian"; - case ERUDITE: - return "Erudite"; - case WOOD_ELF: - return "Wood Elf"; - case HIGH_ELF: - return "High Elf"; - case DARK_ELF: - return "Dark Elf"; - case HALF_ELF: - return "Half Elf"; - case DWARF: - return "Dwarf"; - case TROLL: - return "Troll"; - case OGRE: - return "Ogre"; - case HALFLING: - return "Halfling"; - case GNOME: - return "Gnome"; - case IKSAR: - return "Iksar"; - case WEREWOLF: - return "Werewolf"; - case SKELETON: - return "Skeleton"; - case ELEMENTAL: - return "Elemental"; - case EYE_OF_ZOMM: - return "Eye of Zomm"; - case WOLF_ELEMENTAL: - return "Wolf Elemental"; - case IKSAR_SKELETON: - return "Iksar Skeleton"; - case VAHSHIR: - return "Vah Shir"; - case FROGLOK: - case FROGLOK2: - return "Froglok"; - case DRAKKIN: - return "Drakkin"; - default: - return "Unknown"; +const char* GetRaceIDName(uint16 race_id) +{ + switch (race_id) { + case HUMAN: + return "Human"; + case BARBARIAN: + return "Barbarian"; + case ERUDITE: + return "Erudite"; + case WOOD_ELF: + return "Wood Elf"; + case HIGH_ELF: + return "High Elf"; + case DARK_ELF: + return "Dark Elf"; + case HALF_ELF: + return "Half Elf"; + case DWARF: + return "Dwarf"; + case TROLL: + return "Troll"; + case OGRE: + return "Ogre"; + case HALFLING: + return "Halfling"; + case GNOME: + return "Gnome"; + case IKSAR: + return "Iksar"; + case WEREWOLF: + return "Werewolf"; + case SKELETON: + return "Skeleton"; + case ELEMENTAL: + return "Elemental"; + case EYE_OF_ZOMM: + return "Eye of Zomm"; + case WOLF_ELEMENTAL: + return "Wolf Elemental"; + case IKSAR_SKELETON: + return "Iksar Skeleton"; + case VAHSHIR: + return "Vah Shir"; + case FROGLOK: + case FROGLOK2: + return "Froglok"; + case DRAKKIN: + return "Drakkin"; + default: + return "Unknown"; } } -uint32 GetArrayRace(uint16 race) { - switch(race) { - case HUMAN: - return Array_Race_HUMAN; - case BARBARIAN: - return Array_Race_BARBARIAN; - case ERUDITE: - return Array_Race_ERUDITE; - case WOOD_ELF: - return Array_Race_WOOD_ELF; - case HIGH_ELF: - return Array_Race_HIGH_ELF; - case DARK_ELF: - return Array_Race_DARK_ELF; - case HALF_ELF: - return Array_Race_HALF_ELF; - case DWARF: - return Array_Race_DWARF; - case TROLL: - return Array_Race_TROLL; - case OGRE: - return Array_Race_OGRE; - case HALFLING: - return Array_Race_HALFLING; - case GNOME: - return Array_Race_GNOME; - case IKSAR: - return Array_Race_IKSAR; - case VAHSHIR: - return Array_Race_VAHSHIR; - case FROGLOK: - case FROGLOK2: - return Array_Race_FROGLOK; - case DRAKKIN: - return Array_Race_DRAKKIN; - default: - return Array_Race_UNKNOWN; +const char* GetPlayerRaceName(uint32 player_race_value) +{ + return GetRaceIDName(GetRaceIDFromPlayerRaceValue(player_race_value)); +} + +uint32 GetPlayerRaceValue(uint16 race_id) +{ + switch (race_id) { + case HUMAN: + case BARBARIAN: + case ERUDITE: + case WOOD_ELF: + case HIGH_ELF: + case DARK_ELF: + case HALF_ELF: + case DWARF: + case TROLL: + case OGRE: + case HALFLING: + case GNOME: + return race_id; + case IKSAR: + return PLAYER_RACE_IKSAR; + case VAHSHIR: + return PLAYER_RACE_VAHSHIR; + case FROGLOK: + case FROGLOK2: + return PLAYER_RACE_FROGLOK; + case DRAKKIN: + return PLAYER_RACE_DRAKKIN; + default: + return PLAYER_RACE_UNKNOWN; // watch } } +uint32 GetPlayerRaceBit(uint16 race_id) +{ + switch (race_id) { + case HUMAN: + return PLAYER_RACE_HUMAN_BIT; + case BARBARIAN: + return PLAYER_RACE_BARBARIAN_BIT; + case ERUDITE: + return PLAYER_RACE_ERUDITE_BIT; + case WOOD_ELF: + return PLAYER_RACE_WOOD_ELF_BIT; + case HIGH_ELF: + return PLAYER_RACE_HIGH_ELF_BIT; + case DARK_ELF: + return PLAYER_RACE_DARK_ELF_BIT; + case HALF_ELF: + return PLAYER_RACE_HALF_ELF_BIT; + case DWARF: + return PLAYER_RACE_DWARF_BIT; + case TROLL: + return PLAYER_RACE_TROLL_BIT; + case OGRE: + return PLAYER_RACE_OGRE_BIT; + case HALFLING: + return PLAYER_RACE_HALFLING_BIT; + case GNOME: + return PLAYER_RACE_GNOME_BIT; + case IKSAR: + return PLAYER_RACE_IKSAR_BIT; + case VAHSHIR: + return PLAYER_RACE_VAHSHIR_BIT; + case FROGLOK: + return PLAYER_RACE_FROGLOK_BIT; + case DRAKKIN: + return PLAYER_RACE_DRAKKIN_BIT; + default: + return PLAYER_RACE_UNKNOWN_BIT; + } +} + +uint16 GetRaceIDFromPlayerRaceValue(uint32 player_race_value) +{ + switch (player_race_value) { + case PLAYER_RACE_HUMAN: + case PLAYER_RACE_BARBARIAN: + case PLAYER_RACE_ERUDITE: + case PLAYER_RACE_WOOD_ELF: + case PLAYER_RACE_HIGH_ELF: + case PLAYER_RACE_DARK_ELF: + case PLAYER_RACE_HALF_ELF: + case PLAYER_RACE_DWARF: + case PLAYER_RACE_TROLL: + case PLAYER_RACE_OGRE: + case PLAYER_RACE_HALFLING: + case PLAYER_RACE_GNOME: + return player_race_value; + case PLAYER_RACE_IKSAR: + return IKSAR; + case PLAYER_RACE_VAHSHIR: + return VAHSHIR; + case PLAYER_RACE_FROGLOK: + return FROGLOK; + case PLAYER_RACE_DRAKKIN: + return DRAKKIN; + default: + return PLAYER_RACE_UNKNOWN; // watch + } +} + +uint16 GetRaceIDFromPlayerRaceBit(uint32 player_race_bit) +{ + switch (player_race_bit) { + case PLAYER_RACE_HUMAN_BIT: + return HUMAN; + case PLAYER_RACE_BARBARIAN_BIT: + return BARBARIAN; + case PLAYER_RACE_ERUDITE_BIT: + return ERUDITE; + case PLAYER_RACE_WOOD_ELF_BIT: + return WOOD_ELF; + case PLAYER_RACE_HIGH_ELF_BIT: + return HIGH_ELF; + case PLAYER_RACE_DARK_ELF_BIT: + return DARK_ELF; + case PLAYER_RACE_HALF_ELF_BIT: + return HALF_ELF; + case PLAYER_RACE_DWARF_BIT: + return DWARF; + case PLAYER_RACE_TROLL_BIT: + return TROLL; + case PLAYER_RACE_OGRE_BIT: + return OGRE; + case PLAYER_RACE_HALFLING_BIT: + return HALFLING; + case PLAYER_RACE_GNOME_BIT: + return GNOME; + case PLAYER_RACE_IKSAR_BIT: + return IKSAR; + case PLAYER_RACE_VAHSHIR_BIT: + return VAHSHIR; + case PLAYER_RACE_FROGLOK_BIT: + return FROGLOK; + case PLAYER_RACE_DRAKKIN_BIT: + return DRAKKIN; + default: + return PLAYER_RACE_UNKNOWN; // watch + } +} + + +// PlayerAppearance prep +#define HUMAN_MALE ((HUMAN << 8) | MALE) +#define HUMAN_FEMALE ((HUMAN << 8) | FEMALE) +#define BARBARIAN_MALE ((BARBARIAN << 8) | MALE) +#define BARBARIAN_FEMALE ((BARBARIAN << 8) | FEMALE) +#define ERUDITE_MALE ((ERUDITE << 8) | MALE) +#define ERUDITE_FEMALE ((ERUDITE << 8) | FEMALE) +#define WOOD_ELF_MALE ((WOOD_ELF << 8) | MALE) +#define WOOD_ELF_FEMALE ((WOOD_ELF << 8) | FEMALE) +#define HIGH_ELF_MALE ((HIGH_ELF << 8) | MALE) +#define HIGH_ELF_FEMALE ((HIGH_ELF << 8) | FEMALE) +#define DARK_ELF_MALE ((DARK_ELF << 8) | MALE) +#define DARK_ELF_FEMALE ((DARK_ELF << 8) | FEMALE) +#define HALF_ELF_MALE ((HALF_ELF << 8) | MALE) +#define HALF_ELF_FEMALE ((HALF_ELF << 8) | FEMALE) +#define DWARF_MALE ((DWARF << 8) | MALE) +#define DWARF_FEMALE ((DWARF << 8) | FEMALE) +#define TROLL_MALE ((TROLL << 8) | MALE) +#define TROLL_FEMALE ((TROLL << 8) | FEMALE) +#define OGRE_MALE ((OGRE << 8) | MALE) +#define OGRE_FEMALE ((OGRE << 8) | FEMALE) +#define HALFLING_MALE ((HALFLING << 8) | MALE) +#define HALFLING_FEMALE ((HALFLING << 8) | FEMALE) +#define GNOME_MALE ((GNOME << 8) | MALE) +#define GNOME_FEMALE ((GNOME << 8) | FEMALE) +#define IKSAR_MALE ((IKSAR << 8) | MALE) +#define IKSAR_FEMALE ((IKSAR << 8) | FEMALE) +#define VAHSHIR_MALE ((VAHSHIR << 8) | MALE) +#define VAHSHIR_FEMALE ((VAHSHIR << 8) | FEMALE) +#define FROGLOK_MALE ((FROGLOK << 8) | MALE) +#define FROGLOK_FEMALE ((FROGLOK << 8) | FEMALE) +#define DRAKKIN_MALE ((DRAKKIN << 8) | MALE) +#define DRAKKIN_FEMALE ((DRAKKIN << 8) | FEMALE) + +#define BINDRG(r, g) (((int)r << 8) | g) + + +bool PlayerAppearance::IsValidBeard(uint16 race_id, uint8 gender_id, uint8 beard_value, bool use_luclin) +{ + if (beard_value == 0xFF) + return true; + + if (use_luclin) { + switch (BINDRG(race_id, gender_id)) { + case DWARF_FEMALE: + if (beard_value <= 1) + return true; + break; + case HIGH_ELF_MALE: + case DARK_ELF_MALE: + case HALF_ELF_MALE: + case DRAKKIN_FEMALE: + if (beard_value <= 3) + return true; + break; + case HUMAN_MALE: + case BARBARIAN_MALE: + case ERUDITE_MALE: + case DWARF_MALE: + case HALFLING_MALE: + case GNOME_MALE: + if (beard_value <= 5) + return true; + break; + case DRAKKIN_MALE: + if (beard_value <= 11) + return true; + break; + default: + break; + } + return false; + } + else { + switch (BINDRG(race_id, gender_id)) { + case DRAKKIN_FEMALE: + if (beard_value <= 3) + return true; + break; + case DRAKKIN_MALE: + if (beard_value <= 11) + return true; + break; + default: + break; + } + return false; + } +} + +bool PlayerAppearance::IsValidBeardColor(uint16 race_id, uint8 gender_id, uint8 beard_color_value, bool use_luclin) +{ + if (beard_color_value == 0xFF) + return true; + + switch (BINDRG(race_id, gender_id)) { + case GNOME_MALE: + if (beard_color_value <= 24) + return true; + break; + case HUMAN_MALE: + case BARBARIAN_MALE: + case ERUDITE_MALE: + case HALF_ELF_MALE: + case DWARF_MALE: + case DWARF_FEMALE: + case HALFLING_MALE: + if (beard_color_value <= 19) + return true; + break; + case DARK_ELF_MALE: + if (beard_color_value >= 13 && beard_color_value <= 18) + return true; + break; + case HIGH_ELF_MALE: + if (beard_color_value <= 14) + return true; + break; + case FROGLOK_MALE: + case FROGLOK_FEMALE: + case DRAKKIN_MALE: + case DRAKKIN_FEMALE: + if (beard_color_value <= 3) + return true; + break; + default: + break; + } + return false; +} + +bool PlayerAppearance::IsValidDetail(uint16 race_id, uint8 gender_id, uint32 detail_value, bool use_luclin) +{ + if (detail_value == 0xFFFFFFFF) + return true; + + switch (BINDRG(race_id, gender_id)) { + case DRAKKIN_MALE: + case DRAKKIN_FEMALE: + if (detail_value <= 7) + return true; + break; + default: + break; + } + return false; +} + +bool PlayerAppearance::IsValidEyeColor(uint16 race_id, uint8 gender_id, uint8 eye_color_value, bool use_luclin) +{ + return true; // need valid criteria + + switch (BINDRG(race_id, gender_id)) { + case HUMAN_MALE: + case HUMAN_FEMALE: + case BARBARIAN_MALE: + case BARBARIAN_FEMALE: + case ERUDITE_MALE: + case ERUDITE_FEMALE: + case WOOD_ELF_MALE: + case WOOD_ELF_FEMALE: + case HIGH_ELF_MALE: + case HIGH_ELF_FEMALE: + case DARK_ELF_MALE: + case DARK_ELF_FEMALE: + case HALF_ELF_MALE: + case HALF_ELF_FEMALE: + case DWARF_MALE: + case DWARF_FEMALE: + case OGRE_MALE: + case OGRE_FEMALE: + case HALFLING_MALE: + case HALFLING_FEMALE: + case GNOME_MALE: + case GNOME_FEMALE: + case IKSAR_MALE: + case IKSAR_FEMALE: + case VAHSHIR_MALE: + case VAHSHIR_FEMALE: + if (eye_color_value <= 9) + return true; + break; + case TROLL_MALE: + case TROLL_FEMALE: + if (eye_color_value <= 10) + return true; + break; + case FROGLOK_MALE: + case FROGLOK_FEMALE: + case DRAKKIN_MALE: + case DRAKKIN_FEMALE: + if (eye_color_value <= 11) + return true; + break; + default: + break; + } + return false; +} + +bool PlayerAppearance::IsValidFace(uint16 race_id, uint8 gender_id, uint8 face_value, bool use_luclin) +{ + if (face_value == 0xFF) + return true; + + switch (BINDRG(race_id, gender_id)) { + case DRAKKIN_MALE: + case DRAKKIN_FEMALE: + if (face_value <= 6) + return true; + break; + case HUMAN_MALE: + case HUMAN_FEMALE: + case BARBARIAN_MALE: + case BARBARIAN_FEMALE: + case ERUDITE_MALE: + case ERUDITE_FEMALE: + case WOOD_ELF_MALE: + case WOOD_ELF_FEMALE: + case HIGH_ELF_MALE: + case HIGH_ELF_FEMALE: + case DARK_ELF_MALE: + case DARK_ELF_FEMALE: + case HALF_ELF_MALE: + case HALF_ELF_FEMALE: + case DWARF_MALE: + case DWARF_FEMALE: + case TROLL_MALE: + case TROLL_FEMALE: + case OGRE_MALE: + case OGRE_FEMALE: + case HALFLING_MALE: + case HALFLING_FEMALE: + case GNOME_MALE: + case GNOME_FEMALE: + case IKSAR_MALE: + case IKSAR_FEMALE: + case VAHSHIR_MALE: + case VAHSHIR_FEMALE: + if (face_value <= 7) + return true; + break; + case FROGLOK_MALE: + case FROGLOK_FEMALE: + if (face_value <= 9) + return true; + break; + default: + break; + } + return false; +} + +bool PlayerAppearance::IsValidHair(uint16 race_id, uint8 gender_id, uint8 hair_value, bool use_luclin) +{ + if (hair_value == 0xFF) + return true; + + if (use_luclin) { + switch (BINDRG(race_id, gender_id)) { + case HUMAN_MALE: + case HUMAN_FEMALE: + case BARBARIAN_MALE: + case BARBARIAN_FEMALE: + case WOOD_ELF_MALE: + case WOOD_ELF_FEMALE: + case HIGH_ELF_MALE: + case HIGH_ELF_FEMALE: + case DARK_ELF_MALE: + case DARK_ELF_FEMALE: + case HALF_ELF_MALE: + case HALF_ELF_FEMALE: + case DWARF_MALE: + case DWARF_FEMALE: + case TROLL_FEMALE: + case OGRE_FEMALE: + case HALFLING_MALE: + case HALFLING_FEMALE: + case GNOME_MALE: + case GNOME_FEMALE: + if (hair_value <= 3) + return true; + break; + case ERUDITE_MALE: + if (hair_value <= 5) + return true; + break; + case DRAKKIN_FEMALE: + if (hair_value <= 7) + return true; + break; + case ERUDITE_FEMALE: + case DRAKKIN_MALE: + if (hair_value <= 8) + return true; + break; + default: + break; + } + return false; + } + else { + switch (BINDRG(race_id, gender_id)) { + case DRAKKIN_FEMALE: + if (hair_value <= 7) + return true; + break; + case DRAKKIN_MALE: + if (hair_value <= 8) + return true; + break; + default: + break; + } + return false; + } +} + +bool PlayerAppearance::IsValidHairColor(uint16 race_id, uint8 gender_id, uint8 hair_color_value, bool use_luclin) +{ + if (hair_color_value == 0xFF) + return true; + + switch (BINDRG(race_id, gender_id)) { + case GNOME_MALE: + case GNOME_FEMALE: + if (hair_color_value <= 24) + return true; + break; + case TROLL_FEMALE: + case OGRE_FEMALE: + if (hair_color_value <= 23) + return true; + break; + case HUMAN_MALE: + case HUMAN_FEMALE: + case BARBARIAN_MALE: + case BARBARIAN_FEMALE: + case WOOD_ELF_MALE: + case WOOD_ELF_FEMALE: + case HALF_ELF_MALE: + case HALF_ELF_FEMALE: + case DWARF_MALE: + case DWARF_FEMALE: + case HALFLING_MALE: + case HALFLING_FEMALE: + if (hair_color_value <= 19) + return true; + break; + case DARK_ELF_MALE: + case DARK_ELF_FEMALE: + if (hair_color_value >= 13 && hair_color_value <= 18) + return true; + break; + case HIGH_ELF_MALE: + case HIGH_ELF_FEMALE: + if (hair_color_value <= 14) + return true; + break; + case FROGLOK_MALE: + case FROGLOK_FEMALE: + case DRAKKIN_MALE: + case DRAKKIN_FEMALE: + if (hair_color_value <= 3) + return true; + break; + default: + break; + } + return false; +} + +bool PlayerAppearance::IsValidHead(uint16 race_id, uint8 gender_id, uint8 head_value, bool use_luclin) +{ + if (head_value == 0xFF) + return true; + + if (use_luclin) { + switch (BINDRG(race_id, gender_id)) { + case HUMAN_MALE: + case HUMAN_FEMALE: + case BARBARIAN_MALE: + case BARBARIAN_FEMALE: + case WOOD_ELF_MALE: + case WOOD_ELF_FEMALE: + case HIGH_ELF_MALE: + case HIGH_ELF_FEMALE: + case DARK_ELF_MALE: + case DARK_ELF_FEMALE: + case HALF_ELF_MALE: + case HALF_ELF_FEMALE: + case DWARF_MALE: + case DWARF_FEMALE: + case TROLL_MALE: + case TROLL_FEMALE: + case OGRE_MALE: + case OGRE_FEMALE: + case HALFLING_MALE: + case HALFLING_FEMALE: + case GNOME_MALE: + case GNOME_FEMALE: + case IKSAR_MALE: + case IKSAR_FEMALE: + case VAHSHIR_MALE: + case VAHSHIR_FEMALE: + case FROGLOK_MALE: + case FROGLOK_FEMALE: + case DRAKKIN_MALE: + case DRAKKIN_FEMALE: + if (head_value <= 3) + return true; + break; + case ERUDITE_MALE: + case ERUDITE_FEMALE: + if (head_value <= 4) + return true; + break; + default: + break; + } + return false; + } + else { + switch (BINDRG(race_id, gender_id)) { + case HUMAN_MALE: + case HUMAN_FEMALE: + case BARBARIAN_MALE: + case BARBARIAN_FEMALE: + case ERUDITE_MALE: + case ERUDITE_FEMALE: + case WOOD_ELF_MALE: + case WOOD_ELF_FEMALE: + case HIGH_ELF_MALE: + case HIGH_ELF_FEMALE: + case DARK_ELF_MALE: + case DARK_ELF_FEMALE: + case HALF_ELF_MALE: + case HALF_ELF_FEMALE: + case DWARF_MALE: + case DWARF_FEMALE: + case TROLL_MALE: + case TROLL_FEMALE: + case OGRE_MALE: + case OGRE_FEMALE: + case HALFLING_MALE: + case HALFLING_FEMALE: + case IKSAR_MALE: + case IKSAR_FEMALE: + case VAHSHIR_MALE: + case VAHSHIR_FEMALE: + case FROGLOK_MALE: + case FROGLOK_FEMALE: + case DRAKKIN_MALE: + case DRAKKIN_FEMALE: + if (head_value <= 3) + return true; + break; + case GNOME_MALE: + case GNOME_FEMALE: + if (head_value <= 4) + return true; + break; + default: + break; + } + return false; + } +} + +bool PlayerAppearance::IsValidHeritage(uint16 race_id, uint8 gender_id, uint32 heritage_value, bool use_luclin) +{ + if (heritage_value == 0xFFFFFFFF) + return true; + + switch (BINDRG(race_id, gender_id)) { + case DRAKKIN_MALE: + case DRAKKIN_FEMALE: + if (heritage_value <= 7) // > 5 seems to jumble other features..else, some heritages have 'specialized' features + return true; + break; + default: + break; + } + return false; +} + +bool PlayerAppearance::IsValidTattoo(uint16 race_id, uint8 gender_id, uint32 tattoo_value, bool use_luclin) +{ + if (tattoo_value == 0xFFFFFFFF) + return true; + + switch (BINDRG(race_id, gender_id)) { + case DRAKKIN_MALE: + case DRAKKIN_FEMALE: + if (tattoo_value <= 7) + return true; + break; + default: + break; + } + return false; +} + +bool PlayerAppearance::IsValidTexture(uint16 race_id, uint8 gender_id, uint8 texture_value, bool use_luclin) +{ + if (texture_value == 0xFF) + return true; + + if (use_luclin) { + switch (BINDRG(race_id, gender_id)) { + case HUMAN_MALE: + case HUMAN_FEMALE: + case IKSAR_MALE: + case IKSAR_FEMALE: + case DRAKKIN_MALE: + case DRAKKIN_FEMALE: + if ((texture_value >= 10 && texture_value <= 16) || texture_value <= 4) + return true; + break; + case ERUDITE_MALE: + case ERUDITE_FEMALE: + case HIGH_ELF_MALE: + case HIGH_ELF_FEMALE: + case DARK_ELF_MALE: + case DARK_ELF_FEMALE: + case GNOME_MALE: + case GNOME_FEMALE: + case FROGLOK_MALE: + case FROGLOK_FEMALE: + if ((texture_value >= 10 && texture_value <= 16) || texture_value <= 3) + return true; + break; + case BARBARIAN_MALE: + case BARBARIAN_FEMALE: + case WOOD_ELF_MALE: + case WOOD_ELF_FEMALE: + case HALF_ELF_MALE: + case HALF_ELF_FEMALE: + case DWARF_MALE: + case DWARF_FEMALE: + case TROLL_MALE: + case TROLL_FEMALE: + case OGRE_MALE: + case OGRE_FEMALE: + case HALFLING_MALE: + case HALFLING_FEMALE: + case VAHSHIR_MALE: + case VAHSHIR_FEMALE: + if (texture_value <= 3) + return true; + break; + default: + break; + } + return false; + } + else { + switch (BINDRG(race_id, gender_id)) { + case HUMAN_MALE: + case HUMAN_FEMALE: + case ERUDITE_MALE: + case ERUDITE_FEMALE: + case DRAKKIN_MALE: + case DRAKKIN_FEMALE: + if ((texture_value >= 10 && texture_value <= 16) || texture_value <= 4) + return true; + break; + case HIGH_ELF_MALE: + case HIGH_ELF_FEMALE: + case DARK_ELF_MALE: + case DARK_ELF_FEMALE: + case GNOME_MALE: + case GNOME_FEMALE: + case FROGLOK_MALE: + case FROGLOK_FEMALE: + if ((texture_value >= 10 && texture_value <= 16) || texture_value <= 3) + return true; + break; + case VAHSHIR_MALE: + case VAHSHIR_FEMALE: + if (texture_value == 50 || texture_value <= 3) + return true; + break; + case IKSAR_MALE: + case IKSAR_FEMALE: + if (texture_value == 10 || texture_value <= 4) + return true; + break; + case BARBARIAN_MALE: + case BARBARIAN_FEMALE: + case WOOD_ELF_MALE: + case WOOD_ELF_FEMALE: + case HALF_ELF_MALE: + case HALF_ELF_FEMALE: + case DWARF_MALE: + case DWARF_FEMALE: + case TROLL_MALE: + case TROLL_FEMALE: + case OGRE_MALE: + case OGRE_FEMALE: + case HALFLING_MALE: + case HALFLING_FEMALE: + if (texture_value <= 3) + return true; + break; + default: + break; + } + return false; + } +} + +bool PlayerAppearance::IsValidWoad(uint16 race_id, uint8 gender_id, uint8 woad_value, bool use_luclin) +{ + if (woad_value == 0xFF) + return true; + + if (use_luclin) { + switch (BINDRG(race_id, gender_id)) { + case BARBARIAN_MALE: + case BARBARIAN_FEMALE: + if (woad_value <= 8) + return true; + break; + default: + break; + } + } + return false; +} diff --git a/common/races.h b/common/races.h index 68add5cca..050b2fd78 100644 --- a/common/races.h +++ b/common/races.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,92 +15,130 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef RACES_H #define RACES_H #include "../common/types.h" -#include + +#define MALE 0 +#define FEMALE 1 +#define NEUTER 2 //theres a big list straight from the client below. -#define HUMAN 1 -#define BARBARIAN 2 -#define ERUDITE 3 -#define WOOD_ELF 4 -#define HIGH_ELF 5 -#define DARK_ELF 6 -#define HALF_ELF 7 -#define DWARF 8 -#define TROLL 9 -#define OGRE 10 -#define HALFLING 11 -#define GNOME 12 -#define WEREWOLF 14 -#define WOLF 42 -#define BEAR 43 -#define SKELETON 60 -#define TIGER 63 -#define ELEMENTAL 75 -#define ALLIGATOR 91 -#define EYE_OF_ZOMM 108 -#define WOLF_ELEMENTAL 120 -#define INVISIBLE_MAN 127 -#define IKSAR 128 -#define VAHSHIR 130 +#define HUMAN 1 +#define BARBARIAN 2 +#define ERUDITE 3 +#define WOOD_ELF 4 +#define HIGH_ELF 5 +#define DARK_ELF 6 +#define HALF_ELF 7 +#define DWARF 8 +#define TROLL 9 +#define OGRE 10 +#define HALFLING 11 +#define GNOME 12 +#define WEREWOLF 14 +#define WOLF 42 +#define BEAR 43 +#define SKELETON 60 +#define TIGER 63 +#define ELEMENTAL 75 +#define ALLIGATOR 91 +#define EYE_OF_ZOMM 108 +#define WOLF_ELEMENTAL 120 +#define INVISIBLE_MAN 127 +#define IKSAR 128 +#define VAHSHIR 130 #define CONTROLLED_BOAT 141 -#define MINOR_ILL_OBJ 142 -#define TREE 143 -#define IKSAR_SKELETON 161 -#define FROGLOK 330 -#define FROGLOK2 74 // Not sure why /who all reports race as 74 for frogloks -#define DRAKKIN 522 // 32768 -#define EMU_RACE_NPC 131069 // was 65533 -#define EMU_RACE_PET 131070 // was 65534 +#define MINOR_ILL_OBJ 142 +#define TREE 143 +#define IKSAR_SKELETON 161 +#define FROGLOK 330 +// TODO: check all clients for (BYTE) usage of '/who all' class and remove FROGLOK2, if possible (330 - 74 = 256 .. WORD->BYTE conversion loss...) +#define FROGLOK2 74 // Not sure why /who all reports race as 74 for frogloks +#define FAIRY 473 +#define DRAKKIN 522 // 32768 +#define EMU_RACE_NPC 131069 // was 65533 +#define EMU_RACE_PET 131070 // was 65534 #define EMU_RACE_UNKNOWN 131071 // was 65535 -#define human_1 1 -#define barbarian_1 2 -#define erudite_1 4 -#define woodelf_1 8 -#define highelf_1 16 -#define darkelf_1 32 -#define halfelf_1 64 -#define dwarf_1 128 -#define troll_1 256 -#define ogre_1 512 -#define halfling_1 1024 -#define gnome_1 2048 -#define iksar_1 4096 -#define vahshir_1 8192 -#define rall_1 16384 //froglok? -#define drakkin_1 32768 +// player race values +#define PLAYER_RACE_UNKNOWN 0 +#define PLAYER_RACE_HUMAN 1 +#define PLAYER_RACE_BARBARIAN 2 +#define PLAYER_RACE_ERUDITE 3 +#define PLAYER_RACE_WOOD_ELF 4 +#define PLAYER_RACE_HIGH_ELF 5 +#define PLAYER_RACE_DARK_ELF 6 +#define PLAYER_RACE_HALF_ELF 7 +#define PLAYER_RACE_DWARF 8 +#define PLAYER_RACE_TROLL 9 +#define PLAYER_RACE_OGRE 10 +#define PLAYER_RACE_HALFLING 11 +#define PLAYER_RACE_GNOME 12 +#define PLAYER_RACE_IKSAR 13 +#define PLAYER_RACE_VAHSHIR 14 +#define PLAYER_RACE_FROGLOK 15 +#define PLAYER_RACE_DRAKKIN 16 -const char* GetRaceName(uint16 race); +#define PLAYER_RACE_COUNT 16 -uint32 GetArrayRace(uint16 race); -inline uint32 GetRaceBitmask(uint16 race) { return uint32(pow(2.0f, float(GetArrayRace(race) - 1))); } -#define Array_Race_UNKNOWN 0 -#define Array_Race_HUMAN 1 -#define Array_Race_BARBARIAN 2 -#define Array_Race_ERUDITE 3 -#define Array_Race_WOOD_ELF 4 -#define Array_Race_HIGH_ELF 5 -#define Array_Race_DARK_ELF 6 -#define Array_Race_HALF_ELF 7 -#define Array_Race_DWARF 8 -#define Array_Race_TROLL 9 -#define Array_Race_OGRE 10 -#define Array_Race_HALFLING 11 -#define Array_Race_GNOME 12 -#define Array_Race_IKSAR 13 -#define Array_Race_VAHSHIR 14 -#define Array_Race_FROGLOK 15 -#define Array_Race_DRAKKIN 16 -#define Array_Race_NPC 17 -#define Array_Race_PET 18 -#define Count_Array_Race 19 // used for array defines, must be the max + 1 -#define PLAYER_RACE_COUNT 16 // The count of all player races +#define PLAYER_RACE_EMU_NPC 17 +#define PLAYER_RACE_EMU_PET 18 +#define PLAYER_RACE_EMU_COUNT 19 + + +// player race bits +#define PLAYER_RACE_UNKNOWN_BIT 0 +#define PLAYER_RACE_HUMAN_BIT 1 +#define PLAYER_RACE_BARBARIAN_BIT 2 +#define PLAYER_RACE_ERUDITE_BIT 4 +#define PLAYER_RACE_WOOD_ELF_BIT 8 +#define PLAYER_RACE_HIGH_ELF_BIT 16 +#define PLAYER_RACE_DARK_ELF_BIT 32 +#define PLAYER_RACE_HALF_ELF_BIT 64 +#define PLAYER_RACE_DWARF_BIT 128 +#define PLAYER_RACE_TROLL_BIT 256 +#define PLAYER_RACE_OGRE_BIT 512 +#define PLAYER_RACE_HALFLING_BIT 1024 +#define PLAYER_RACE_GNOME_BIT 2048 +#define PLAYER_RACE_IKSAR_BIT 4096 +#define PLAYER_RACE_VAHSHIR_BIT 8192 +#define PLAYER_RACE_FROGLOK_BIT 16384 +#define PLAYER_RACE_DRAKKIN_BIT 32768 + +#define PLAYER_RACE_ALL_MASK 65535 + + +const char* GetRaceIDName(uint16 race_id); +const char* GetPlayerRaceName(uint32 player_race_value); + +uint32 GetPlayerRaceValue(uint16 race_id); +uint32 GetPlayerRaceBit(uint16 race_id); + +uint16 GetRaceIDFromPlayerRaceValue(uint32 player_race_value); +uint16 GetRaceIDFromPlayerRaceBit(uint32 player_race_bit); + + +// player race-/gender-based model feature validators +namespace PlayerAppearance +{ + bool IsValidBeard(uint16 race_id, uint8 gender_id, uint8 beard_value, bool use_luclin = true); + bool IsValidBeardColor(uint16 race_id, uint8 gender_id, uint8 beard_color_value, bool use_luclin = true); + bool IsValidDetail(uint16 race_id, uint8 gender_id, uint32 detail_value, bool use_luclin = true); + bool IsValidEyeColor(uint16 race_id, uint8 gender_id, uint8 eye_color_value, bool use_luclin = true); + bool IsValidFace(uint16 race_id, uint8 gender_id, uint8 face_value, bool use_luclin = true); + bool IsValidHair(uint16 race_id, uint8 gender_id, uint8 hair_value, bool use_luclin = true); + bool IsValidHairColor(uint16 race_id, uint8 gender_id, uint8 hair_color_value, bool use_luclin = true); + bool IsValidHead(uint16 race_id, uint8 gender_id, uint8 head_value, bool use_luclin = true); + bool IsValidHeritage(uint16 race_id, uint8 gender_id, uint32 heritage_value, bool use_luclin = true); + bool IsValidTattoo(uint16 race_id, uint8 gender_id, uint32 tattoo_value, bool use_luclin = true); + bool IsValidTexture(uint16 race_id, uint8 gender_id, uint8 texture_value, bool use_luclin = true); + bool IsValidWoad(uint16 race_id, uint8 gender_id, uint8 woad_value, bool use_luclin = true); +} /* diff --git a/common/ruletypes.h b/common/ruletypes.h index 641266b2f..6c253722a 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -1,5 +1,20 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ #ifndef RULE_CATEGORY #define RULE_CATEGORY(name) @@ -516,10 +531,14 @@ RULE_CATEGORY_END() #ifdef BOTS RULE_CATEGORY(Bots) RULE_INT(Bots, AAExpansion, 8) // Bots get AAs through this expansion +RULE_INT(Bots, CommandSpellRank, 1) // Filters bot command spells by rank (1, 2 and 3 are valid filters - any other number allows all ranks) RULE_INT(Bots, CreationLimit, 150) // Number of bots that each account can create RULE_BOOL(Bots, FinishBuffing, false) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat. RULE_BOOL(Bots, GroupBuffing, false) // Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB. +RULE_INT(Bots, HealRotationMaxMembers, 24) // Maximum number of heal rotation members +RULE_INT(Bots, HealRotationMaxTargets, 12) // Maximum number of heal rotation targets RULE_REAL(Bots, ManaRegen, 2.0) // Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players. +RULE_BOOL(Bots, PreferNoManaCommandSpells, true) // Give sorting priority to newer no-mana spells (i.e., 'Bind Affinity') RULE_BOOL(Bots, QuestableSpawnLimit, false) // Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl RULE_BOOL(Bots, QuestableSpells, false) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests. RULE_INT(Bots, SpawnLimit, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 79bac527e..efe7358db 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1,3 +1,21 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #include #include @@ -1647,6 +1665,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].short_buff_box = atoi(row[154]); sp[tempid].descnum = atoi(row[155]); + sp[tempid].typedescnum = atoi(row[156]); sp[tempid].effectdescnum = atoi(row[157]); sp[tempid].npc_no_los = atoi(row[159]) != 0; @@ -2025,22 +2044,3 @@ void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const Insp std::string query = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message) VALUES (%u, '%s')", character_id, EscapeString(message->text).c_str()); auto results = QueryDatabase(query); } - -#ifdef BOTS -void SharedDatabase::GetBotInspectMessage(uint32 bot_id, InspectMessage_Struct* message) -{ - std::string query = StringFormat("SELECT `inspect_message` FROM `bot_inspect_messages` WHERE `bot_id` = %i LIMIT 1", bot_id); - auto results = QueryDatabase(query); - auto row = results.begin(); - memset(message, '\0', sizeof(InspectMessage_Struct)); - for (auto row = results.begin(); row != results.end(); ++row) { - memcpy(message, row[0], sizeof(InspectMessage_Struct)); - } -} - -void SharedDatabase::SetBotInspectMessage(uint32 bot_id, const InspectMessage_Struct* message) -{ - std::string query = StringFormat("REPLACE INTO `bot_inspect_messages` (bot_id, inspect_message) VALUES (%u, '%s')", bot_id, EscapeString(message->text).c_str()); - auto results = QueryDatabase(query); -} -#endif diff --git a/common/shareddb.h b/common/shareddb.h index ebb2ae961..45db3e3c0 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -1,3 +1,21 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #ifndef SHAREDDB_H_ #define SHAREDDB_H_ @@ -126,11 +144,6 @@ class SharedDatabase : public Database void LoadBaseData(void *data, int max_level); const BaseDataStruct* GetBaseData(int lvl, int cl); -#ifdef BOTS - void GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message); - void SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message); -#endif - protected: std::unique_ptr skill_caps_mmf; diff --git a/common/spdat.h b/common/spdat.h index 555ea67ef..0e9096f1a 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -639,7 +639,7 @@ typedef enum { // number. note that the id field is counted as 0, this way the numbers // here match the numbers given to sep in the loading function net.cpp // -#define SPELL_LOAD_FIELD_COUNT 231 +#define SPELL_LOAD_FIELD_COUNT 236 struct SPDat_Spell_Struct { @@ -707,7 +707,7 @@ struct SPDat_Spell_Struct // 152 & 153: all set to 0 /* 154 */ int8 short_buff_box; // != 0, goes to short buff box. /* 155 */ int descnum; // eqstr of description of spell -/* 156 */ //int typedescnum; // eqstr of type description +/* 156 */ int typedescnum; // eqstr of type description /* 157 */ int effectdescnum; // eqstr of effect description /* 158 */ //Category Desc ID 3 /* 159 */ bool npc_no_los; diff --git a/common/version.h b/common/version.h index 04bf9189c..64c063917 100644 --- a/common/version.h +++ b/common/version.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9096 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9002 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/scripts/opcode_handlers.py b/utils/scripts/opcode_handlers.py index d428046ba..fb3923209 100644 --- a/utils/scripts/opcode_handlers.py +++ b/utils/scripts/opcode_handlers.py @@ -745,6 +745,7 @@ def discoverserverhandlers(): locations['Zone'].append('/zone/aa.cpp') locations['Zone'].append('/zone/attack.cpp') locations['Zone'].append('/zone/bot.cpp') + locations['Zone'].append('/zone/bot_command.cpp') locations['Zone'].append('/zone/client.cpp') locations['Zone'].append('/zone/client_packet.cpp') locations['Zone'].append('/zone/client_process.cpp') diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 1612046dd..12e5996f2 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -1,4 +1,6 @@ 9000|2015_09_30_bots.sql|SHOW TABLES LIKE 'bot_data'|empty| +9001|2016_03_24_bots_command_settings.sql|SHOW TABLES LIKE 'bot_command_settings'|empty| +9002|2016_03_24_bots_command_rules.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CommandSpellRank'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2016_03_24_bots_command_rules.sql b/utils/sql/git/bots/required/2016_03_24_bots_command_rules.sql new file mode 100644 index 000000000..be3009944 --- /dev/null +++ b/utils/sql/git/bots/required/2016_03_24_bots_command_rules.sql @@ -0,0 +1,5 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES +(1, 'Bots:CommandSpellRank', '1', 'Filters bot command spells by rank (1, 2 and 3 are valid filters - any other number allows all ranks)'), +(1, 'Bots:HealRotationMaxMembers', '24', 'Maximum number of heal rotation members'), +(1, 'Bots:HealRotationMaxTargets', '12', 'Maximum number of heal rotation targets'), +(1, 'Bots:PreferNoManaCommandSpells', 'true', 'Give sorting priority to newer no-mana spells (i.e., \'Bind Affinity\')'); diff --git a/utils/sql/git/bots/required/2016_03_24_bots_command_settings.sql b/utils/sql/git/bots/required/2016_03_24_bots_command_settings.sql new file mode 100644 index 000000000..7b37e466f --- /dev/null +++ b/utils/sql/git/bots/required/2016_03_24_bots_command_settings.sql @@ -0,0 +1,102 @@ +CREATE TABLE `bot_command_settings` ( + `bot_command` varchar(128) NOT NULL DEFAULT '', + `access` int(11) NOT NULL DEFAULT '0', + `aliases` varchar(256) NOT NULL DEFAULT '', + PRIMARY KEY (`bot_command`), + UNIQUE KEY `UK_bot_command_settings_1` (`bot_command`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO `bot_command_settings` VALUES +('actionable', 0, ''), +('aggressive', 0, 'agg'), +('attack', 0, 'atk'), +('bindaffinity', 0, 'bind'), +('bot', 0, 'b'), +('botappearance', 0, 'app|appearance'), +('botbeardcolor', 0, 'bc|beardcolor'), +('botbeardstyle', 0, 'bs|beardstyle'), +('botcamp', 0, 'camp'), +('botclone', 200, 'clone'), +('botcreate', 0, 'create'), +('botdelete', 0, 'delete'), +('botdetails', 0, 'details'), +('botdyearmor', 0, 'dyearmor'), +('boteyes', 0, 'eyes'), +('botface', 0, 'face'), +('botfollowdistance', 0, 'followd'), +('botgroup', 0, 'bg'), +('botgroupaddmember', 0, 'bgadd'), +('botgroupcreate', 0, 'bgcreate'), +('botgroupdelete', 0, 'bgdelete'), +('botgrouplist', 0, 'bglist'), +('botgroupload', 0, 'bgload'), +('botgroupremovemember', 0, 'bgremove'), +('bothaircolor', 0, 'hc|haircolor'), +('bothairstyle', 0, 'hs|hairstyle'), +('botheritage', 0, 'her|heritage'), +('botinspectmessage', 0, 'inspect'), +('botlist', 0, 'list'), +('botoutofcombat', 0, 'ooc|outofcombat'), +('botreport', 0, 'report|health|mana'), +('botspawn', 0, 'spawn'), +('botstance', 0, 'stance'), +('botsummon', 0, 'summon'), +('bottattoo', 0, 'tattoo'), +('bottogglearcher', 0, 'archer|togglearcher'), +('bottogglehelm', 0, 'helm|togglehelm'), +('botupdate', 0, 'update'), +('botwoad', 0, 'woad'), +('charm', 0, ''), +('circle', 0, 'cir'), +('cure', 0, ''), +('defensive', 0, 'def'), +('depart', 0, 'dep'), +('escape', 0, 'evac|succor'), +('findaliases', 0, 'alias'), +('follow', 0, ''), +('guard', 0, ''), +('healrotation', 0, 'hr'), +('healrotationadaptivetargeting', 0, 'hradapt'), +('healrotationaddmember', 0, 'hraddm'), +('healrotationaddtarget', 0, 'hraddt'), +('healrotationadjustcritical', 0, 'hrcrit'), +('healrotationadjustsafe', 0, 'hrsafe'), +('healrotationcastingoverride', 0, 'hroverride'), +('healrotationchangeinterval', 0, 'hrinterval'), +('healrotationcleartargets', 0, 'hrclear'), +('healrotationcreate', 0, 'hrcreate'), +('healrotationfastheals', 0, 'hrfastheals'), +('healrotationlist', 0, 'hrlist'), +('healrotationremovemember', 0, 'hrremm'), +('healrotationremovetarget', 0, 'hrremt'), +('healrotationresetlimits', 0, 'hrreset'), +('healrotationstart', 0, 'hrstart'), +('healrotationstop', 0, 'hrstop'), +('help', 0, '?'), +('hold', 0, ''), +('identify', 0, 'lore'), +('inventory', 0, 'inv'), +('inventorygive', 0, 'invgive'), +('inventorylist', 0, 'invlist'), +('inventoryremove', 0, 'invremove'), +('invisibility', 0, 'invis'), +('levitation', 0, 'lev'), +('lull', 0, 'calm|pacify'), +('mesmerize', 0, 'mez'), +('movementspeed', 0, 'sow'), +('pet', 0, 'p'), +('petremove', 0, 'prem'), +('petsettype', 0, 'pset'), +('picklock', 0, 'pl'), +('portal', 0, 'port'), +('pull', 0, ''), +('release', 0, ''), +('resistance', 0, 'resist'), +('resurrect', 0, 'revive'), +('rune', 0, ''), +('sendhome', 0, 'gate'), +('size', 0, ''), +('summoncorpse', 0, 'scorpse'), +('taunt', 0, ''), +('track', 0, ''), +('waterbreathing', 0, 'wb|eb'); diff --git a/world/client.cpp b/world/client.cpp index dc17d7b4d..d0ecac3c2 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1,3 +1,21 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #include "../common/global_define.h" #include "../common/eq_packet.h" #include "../common/eq_stream_intf.h" @@ -498,7 +516,7 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) uchar race = app->pBuffer[64]; uchar clas = app->pBuffer[68]; - Log.Out(Logs::Detail, Logs::World_Server, "Name approval request. Name=%s, race=%s, class=%s", char_name, GetRaceName(race), GetEQClassName(clas)); + Log.Out(Logs::Detail, Logs::World_Server, "Name approval request. Name=%s, race=%s, class=%s", char_name, GetRaceIDName(race), GetClassIDName(clas)); EQApplicationPacket *outapp; outapp = new EQApplicationPacket; diff --git a/world/clientlist.cpp b/world/clientlist.cpp index b6b22a6d4..84da0fb08 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2005 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,6 +15,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #include "../common/global_define.h" #include "clientlist.h" #include "zoneserver.h" @@ -1064,7 +1065,7 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct* if (cle->Anon() == 2) { // Roleplay if (admin >= 100 && admin >= cle->Admin()) - sprintf(line, " %s[RolePlay %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetEQClassName(cle->class_(),cle->level()), cle->name(), GetRaceName(cle->race()), tmpguild, tmpZone, LFG, accinfo); + sprintf(line, " %s[RolePlay %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(),cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo); else if (cle->Admin() >= 80 && admin < 80 && cle->GetGM()) { iterator.Advance(); continue; @@ -1074,7 +1075,7 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct* } else if (cle->Anon() == 1) { // Anon if (admin >= 100 && admin >= cle->Admin()) - sprintf(line, " %s[ANON %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetEQClassName(cle->class_(),cle->level()), cle->name(), GetRaceName(cle->race()), tmpguild, tmpZone, LFG, accinfo); + sprintf(line, " %s[ANON %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(),cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo); else if (cle->Admin() >= 80 && cle->GetGM()) { iterator.Advance(); continue; @@ -1083,7 +1084,7 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct* sprintf(line, " %s[ANONYMOUS] %s%s%s", tmpgm, cle->name(), LFG, accinfo); } else - sprintf(line, " %s[%i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetEQClassName(cle->class_(),cle->level()), cle->name(), GetRaceName(cle->race()), tmpguild, tmpZone, LFG, accinfo); + sprintf(line, " %s[%i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(),cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo); AppendAnyLenString(&output, &outsize, &outlen, line); if (outlen >= 3584) { diff --git a/world/eqw.cpp b/world/eqw.cpp index 04d5d4c8b..2bed01919 100644 --- a/world/eqw.cpp +++ b/world/eqw.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -193,9 +193,9 @@ std::map EQW::GetPlayerDetails(Const_char *char_name) { res["location_id"] = itoa(cle->zone()); res["ip"] = long2ip(cle->GetIP()); res["level"] = itoa(cle->level()); - res["race"] = GetRaceName(cle->race()); + res["race"] = GetRaceIDName(cle->race()); res["race_id"] = itoa(cle->race()); - res["class"] = GetEQClassName(cle->class_()); + res["class"] = GetClassIDName(cle->class_()); res["class_id"] = itoa(cle->class_()); res["guild_id"] = itoa(cle->GuildID()); res["guild"] = guild_mgr.GetGuildName(cle->GuildID()); diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index ba9aa8620..532cc86cd 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -8,6 +8,8 @@ SET(zone_sources beacon.cpp bonuses.cpp bot.cpp + bot_command.cpp + bot_database.cpp botspellsai.cpp client.cpp client_mods.cpp @@ -30,6 +32,7 @@ SET(zone_sources guild.cpp guild_mgr.cpp hate_list.cpp + heal_rotation.cpp horse.cpp inventory.cpp loottables.cpp @@ -131,6 +134,8 @@ SET(zone_headers basic_functions.h beacon.h bot.h + bot_command.h + bot_database.h bot_structs.h client.h client_packet.h @@ -149,6 +154,7 @@ SET(zone_headers groups.h guild_mgr.h hate_list.h + heal_rotation.h horse.h lua_bit.h lua_client.h diff --git a/zone/aa.cpp b/zone/aa.cpp index 7e00da07c..403f9755d 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) +Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1428,7 +1428,7 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { } } - auto race = GetArrayRace(GetBaseRace()); + auto race = GetPlayerRaceValue(GetBaseRace()); race = race > 16 ? 1 : race; if(!(ability->races & (1 << (race - 1)))) { return false; diff --git a/zone/bot.cpp b/zone/bot.cpp index dee437849..447f38834 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1,3 +1,21 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #ifdef BOTS #include "bot.h" @@ -53,17 +71,10 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm SetHasBeenSummoned(false); SetTaunting(GetClass() == WARRIOR); SetDefaultBotStance(); - SetInHealRotation(false); - SetHealRotationActive(false); - SetHasHealedThisCycle(false); - ClearHealRotationLeader(); - ClearHealRotationTargets(); - ClearHealRotationMembers(); - SetHealRotationNextHealTime(0); - SetHealRotationTimer(0); - SetNumHealRotationMembers(0); - SetBardUseOutOfCombatSongs(GetClass() == BARD); + + SetAltOutOfCombatBehavior(GetClass() == BARD); // will need to be updated if more classes make use of this flag SetShowHelm(true); + SetPauseAI(false); CalcChanceToCast(); rest_timer.Disable(); SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE); @@ -81,9 +92,6 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm for (int i = 0; i < MaxTimer; i++) timers[i] = 0; - for(int i = 0; i < MaxHealRotationTargets; i++) - _healRotationTargets[i] = 0; - strcpy(this->name, this->GetCleanName()); memset(&m_Light, 0, sizeof(LightProfile_Struct)); } @@ -132,21 +140,13 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SetHasBeenSummoned(false); LoadStance(); SetTaunting((GetClass() == WARRIOR || GetClass() == PALADIN || GetClass() == SHADOWKNIGHT) && (GetBotStance() == BotStanceAggressive)); - SetInHealRotation(false); - SetHealRotationActive(false); - SetHasHealedThisCycle(false); - SetHealRotationUseFastHeals(false); - ClearHealRotationLeader(); - ClearHealRotationTargets(); - ClearHealRotationMembers(); - SetHealRotationNextHealTime(0); - SetHealRotationTimer(0); - SetNumHealRotationMembers(0); + SetPauseAI(false); + CalcChanceToCast(); rest_timer.Disable(); SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE); strcpy(this->name, this->GetCleanName()); - database.GetBotInspectMessage(this->GetBotID(), &_botInspectMessage); + botdb.GetInspectMessage(this->GetBotID(), &_botInspectMessage); LoadGuildMembership(&_guildId, &_guildRank, &_guildName); std::string TempErrorMessage; EquipBot(&TempErrorMessage); @@ -158,9 +158,6 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to for (int i = 0; i < MaxTimer; i++) timers[i] = 0; - for(int i = 0; i < MaxHealRotationTargets; i++) - _healRotationTargets[i] = 0; - GenerateBaseStats(); LoadTimers(); LoadAAs(); @@ -187,6 +184,8 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to Bot::~Bot() { AI_Stop(); + LeaveHealRotationMemberPool(); + if(HasGroup()) Bot::RemoveBotFromGroup(this, GetGroup()); @@ -226,18 +225,18 @@ void Bot::ChangeBotArcherWeapons(bool isArcher) { BotAddEquipItem(MainPrimary, GetBotItemBySlot(MainPrimary)); BotAddEquipItem(MainSecondary, GetBotItemBySlot(MainSecondary)); SetAttackTimer(); - BotGroupSay(this, "My blade is ready."); + BotGroupSay(this, "My blade is ready"); } else { BotRemoveEquipItem(MainPrimary); BotRemoveEquipItem(MainSecondary); BotAddEquipItem(MainAmmo, GetBotItemBySlot(MainAmmo)); BotAddEquipItem(MainSecondary, GetBotItemBySlot(MainRange)); SetAttackTimer(); - BotGroupSay(this, "My bow is true and ready."); + BotGroupSay(this, "My bow is true and ready"); } } else - BotGroupSay(this, "I don't know how to use a bow."); + BotGroupSay(this, "I don't know how to use a bow"); } void Bot::Sit() { @@ -1302,236 +1301,236 @@ void Bot::LoadAAs() { } } -bool Bot::IsValidRaceClassCombo() { - bool Result = false; - - switch(GetRace()) { - case 1: // Human - switch(GetClass()) { - case 1: // Warrior - case 2: // Cleric - case 3: // Paladin - case 4: // Ranger - case 5: // Shadowknight - case 6: // Druid - case 7: // Monk - case 8: // Bard - case 9: // Rogue - case 11: // Necromancer - case 12: // Wizard - case 13: // Magician - case 14: // Enchanter - Result = true; - break; - } - break; - case 2: // Barbarian - switch(GetClass()) { - case 1: // Warrior - case 9: // Rogue - case 10: // Shaman - case 15: // Beastlord - case 16: // Berserker - Result = true; - break; - } - break; - case 3: // Erudite - switch(GetClass()) { - case 2: // Cleric - case 3: // Paladin - case 5: // Shadowknight - case 11: // Necromancer - case 12: // Wizard - case 13: // Magician - case 14: // Enchanter - Result = true; - break; - } - break; - case 4: // Wood Elf - switch(GetClass()) { - case 1: // Warrior - case 4: // Ranger - case 6: // Druid - case 8: // Bard - case 9: // Rogue - Result = true; - break; - } - break; - case 5: // High Elf - switch(GetClass()) { - case 2: // Cleric - case 3: // Paladin - case 12: // Wizard - case 13: // Magician - case 14: // Enchanter - Result = true; - break; - } - break; - case 6: // Dark Elf - switch(GetClass()) { - case 1: // Warrior - case 2: // Cleric - case 5: // Shadowknight - case 9: // Rogue - case 11: // Necromancer - case 12: // Wizard - case 13: // Magician - case 14: // Enchanter - Result = true; - break; - } - break; - case 7: // Half Elf - switch(GetClass()) { - case 1: // Warrior - case 3: // Paladin - case 4: // Ranger - case 6: // Druid - case 8: // Bard - case 9: // Rogue - Result = true; - break; - } - break; - case 8: // Dwarf - switch(GetClass()) { - case 1: // Warrior - case 2: // Cleric - case 3: // Paladin - case 9: // Rogue - case 16: // Berserker - Result = true; - break; - } - break; - case 9: // Troll - switch(GetClass()) { - case 1: // Warrior - case 5: // Shadowknight - case 10: // Shaman - case 15: // Beastlord - case 16: // Berserker - Result = true; - break; - } - break; - case 10: // Ogre - switch(GetClass()) { - case 1: // Warrior - case 5: // Shadowknight - case 10: // Shaman - case 15: // Beastlord - case 16: // Berserker - Result = true; - break; - } - break; - case 11: // Halfling - switch(GetClass()) { - case 1: // Warrior - case 2: // Cleric - case 3: // Paladin - case 4: // Ranger - case 6: // Druid - case 9: // Rogue - Result = true; - break; - } - break; - case 12: // Gnome - switch(GetClass()) { - case 1: // Warrior - case 2: // Cleric - case 3: // Paladin - case 5: // Shadowknight - case 9: // Rogue - case 11: // Necromancer - case 12: // Wizard - case 13: // Magician - case 14: // Enchanter - Result = true; - break; - } - break; - case 128: // Iksar - switch(GetClass()) { - case 1: // Warrior - case 5: // Shadowknight - case 7: // Monk - case 10: // Shaman - case 11: // Necromancer - case 15: // Beastlord - Result = true; - break; - } - break; - case 130: // Vah Shir - switch(GetClass()) { - case 1: // Warrior - case 8: // Bard - case 9: // Rogue - case 10: // Shaman - case 15: // Beastlord - case 16: // Berserker - Result = true; - break; - } - break; - case 330: // Froglok - switch(GetClass()) { - case 1: // Warrior - case 2: // Cleric - case 3: // Paladin - case 5: // Shadowknight - case 9: // Rogue - case 10: // Shaman - case 11: // Necromancer - case 12: // Wizard - Result = true; - break; - } - break; - case 522: // Drakkin - switch(GetClass()) { - case 1: // Warrior - case 2: // Cleric - case 3: // Paladin - case 4: // Ranger - case 5: // Shadowknight - case 6: // Druid - case 7: // Monk - case 8: // Bard - case 9: // Rogue - case 11: // Necromancer - case 12: // Wizard - case 13: // Magician - case 14: // Enchanter - Result = true; - break; - } - break; - } - - return Result; +bool Bot::IsValidRaceClassCombo() +{ + return Bot::IsValidRaceClassCombo(GetRace(), GetClass()); } -bool Bot::IsValidName() { - bool Result = false; - std::string TempBotName = std::string(this->GetCleanName()); - - for(int iCounter = 0; iCounter < TempBotName.length(); iCounter++) { - if(isalpha(TempBotName[iCounter]) || TempBotName[iCounter] == '_') - Result = true; +bool Bot::IsValidRaceClassCombo(uint16 r, uint8 c) +{ + switch (r) { + case HUMAN: + switch (c) { + case WARRIOR: + case CLERIC: + case PALADIN: + case RANGER: + case SHADOWKNIGHT: + case DRUID: + case MONK: + case BARD: + case ROGUE: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + } + break; + case BARBARIAN: + switch (c) { + case WARRIOR: + case ROGUE: + case SHAMAN: + case BEASTLORD: + case BERSERKER: + return true; + } + break; + case ERUDITE: + switch (c) { + case CLERIC: + case PALADIN: + case SHADOWKNIGHT: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + } + break; + case WOOD_ELF: + switch (c) { + case WARRIOR: + case RANGER: + case DRUID: + case BARD: + case ROGUE: + return true; + } + break; + case HIGH_ELF: + switch (c) { + case CLERIC: + case PALADIN: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + } + break; + case DARK_ELF: + switch (c) { + case WARRIOR: + case CLERIC: + case SHADOWKNIGHT: + case ROGUE: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + } + break; + case HALF_ELF: + switch (c) { + case WARRIOR: + case PALADIN: + case RANGER: + case DRUID: + case BARD: + case ROGUE: + return true; + } + break; + case DWARF: + switch (c) { + case WARRIOR: + case CLERIC: + case PALADIN: + case ROGUE: + case BERSERKER: + return true; + } + break; + case TROLL: + switch (c) { + case WARRIOR: + case SHADOWKNIGHT: + case SHAMAN: + case BEASTLORD: + case BERSERKER: + return true; + } + break; + case OGRE: + switch (c) { + case WARRIOR: + case SHADOWKNIGHT: + case SHAMAN: + case BEASTLORD: + case BERSERKER: + return true; + } + break; + case HALFLING: + switch (c) { + case WARRIOR: + case CLERIC: + case PALADIN: + case RANGER: + case DRUID: + case ROGUE: + return true; + } + break; + case GNOME: + switch (c) { + case WARRIOR: + case CLERIC: + case PALADIN: + case SHADOWKNIGHT: + case ROGUE: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + } + break; + case IKSAR: + switch (c) { + case WARRIOR: + case SHADOWKNIGHT: + case MONK: + case SHAMAN: + case NECROMANCER: + case BEASTLORD: + return true; + } + break; + case VAHSHIR: + switch (c) { + case WARRIOR: + case BARD: + case ROGUE: + case SHAMAN: + case BEASTLORD: + case BERSERKER: + return true; + } + break; + case FROGLOK: + switch (c) { + case WARRIOR: + case CLERIC: + case PALADIN: + case SHADOWKNIGHT: + case ROGUE: + case SHAMAN: + case NECROMANCER: + case WIZARD: + return true; + } + break; + case DRAKKIN: + switch (c) { + case WARRIOR: + case CLERIC: + case PALADIN: + case RANGER: + case SHADOWKNIGHT: + case DRUID: + case MONK: + case BARD: + case ROGUE: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + } + break; + default: + break; } - return Result; + return false; } -bool Bot::IsBotNameAvailable(char *botName, std::string* errorMessage) { +bool Bot::IsValidName() +{ + std::string name = this->GetCleanName(); + return Bot::IsValidName(name); +} + +bool Bot::IsValidName(std::string& name) +{ + if (name.length() < 4) + return false; + if (!IsCharUpper(name[0])) + return false; + + for (int i = 1; i < name.length(); ++i) { + if (!IsCharLower(name[i]) && name[i] != '_') { + return false; + } + } + + return true; +} + +bool Bot::IsBotNameAvailable(const char *botName, std::string* errorMessage) { if (botName == "" || strlen(botName) > 15 || !database.CheckNameFilter(botName) || !database.CheckUsedName(botName)) return false; @@ -2386,7 +2385,9 @@ void Bot::BotRangedAttack(Mob* other) { return; SendItemAnimation(other, Ammo, SkillArchery); - DoArcheryAttackDmg(GetTarget(), rangedItem, ammoItem); + //DoArcheryAttackDmg(GetTarget(), rangedItem, ammoItem); + DoArcheryAttackDmg(other, rangedItem, ammoItem); // watch + //break invis when you attack if(invisible) { Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility due to melee attack."); @@ -2655,13 +2656,30 @@ float Bot::GetMaxMeleeRangeToTarget(Mob* target) { // AI Processing for the Bot object void Bot::AI_Process() { - if(!IsAIControlled()) + if (!IsAIControlled()) + return; + if (GetPauseAI()) return; uint8 botClass = GetClass(); uint8 botLevel = GetLevel(); - if(IsCasting() && (botClass != BARD)) - return; + + if (IsCasting()) { + if ( + IsHealRotationMember() && + m_member_of_heal_rotation->CastingOverride() && + m_member_of_heal_rotation->CastingTarget() != nullptr && + m_member_of_heal_rotation->CastingReady() && + m_member_of_heal_rotation->CastingMember() == this && + !m_member_of_heal_rotation->MemberIsCasting(this) + ) + InterruptSpell(); + else if (botClass != BARD) + return; + } + else if (IsHealRotationMember()) { + m_member_of_heal_rotation->SetMemberIsCasting(this, false); + } // A bot wont start its AI if not grouped if(!GetBotOwner() || !IsGrouped() || GetAppearance() == eaDead) @@ -2684,13 +2702,23 @@ void Bot::AI_Process() { return; } - if(GetHealRotationActive() && GetHealRotationTarget() && !GetHasHealedThisCycle() && GetHealRotationNextHealTime() < Timer::GetCurrentTime()) { - if(AIHealRotation(GetHealRotationTarget(), GetHealRotationUseFastHeals())) { - SetHasHealedThisCycle(true); - NotifyNextHealRotationMember(); + if(IsMyHealRotationSet()) { + Mob* delete_me = HealRotationTarget(); + if (AIHealRotation(HealRotationTarget(), UseHealRotationFastHeals())) { +#if (EQDEBUG >= 12) + Log.Out(Logs::General, Logs::Error, "Bot::AI_Process() - Casting succeeded (m: %s, t: %s) : AdvHR(true)", GetCleanName(), ((delete_me) ? (delete_me->GetCleanName()) : ("nullptr"))); +#endif + m_member_of_heal_rotation->SetMemberIsCasting(this); + m_member_of_heal_rotation->UpdateTargetHealingStats(HealRotationTarget()); + AdvanceHealRotation(); + } + else { +#if (EQDEBUG >= 12) + Log.Out(Logs::General, Logs::Error, "Bot::AI_Process() - Casting failed (m: %s, t: %s) : AdvHR(false)", GetCleanName(), ((delete_me) ? (delete_me->GetCleanName()) : ("nullptr"))); +#endif + m_member_of_heal_rotation->SetMemberIsCasting(this, false); + AdvanceHealRotation(false); } - else - NotifyNextHealRotationMember(true); } if(GetHasBeenSummoned()) { @@ -3584,48 +3612,6 @@ uint32 Bot::GetBotItemsCount(std::string *errorMessage) { return atoi(row[0]); } -bool Bot::MesmerizeTarget(Mob* target) { - bool Result = false; - if(target) { - int mezid = 0; - int mezlevel = GetLevel(); - if(mezlevel >= 69) - mezid = 5520; - else if(mezlevel == 68) - mezid = 8035; - else if(mezlevel == 67) - mezid = 5503; - else if(mezlevel >= 64) - mezid = 3358; - else if(mezlevel == 63) - mezid = 3354; - else if(mezlevel >= 61) - mezid = 3341; - else if(mezlevel == 60) - mezid = 2120; - else if(mezlevel == 59) - mezid = 1692; - else if(mezlevel >= 54) - mezid = 1691; - else if(mezlevel >= 47) - mezid = 190; - else if(mezlevel >= 30) - mezid = 188; - else if(mezlevel >= 13) - mezid = 187; - else if(mezlevel >= 2) - mezid = 292; - if(mezid > 0) { - uint32 DontRootMeBeforeTime = 0; - CastSpell(mezid, target->GetID(), 1, -1, -1, &DontRootMeBeforeTime); - target->SetDontRootMeBefore(DontRootMeBeforeTime); - Result = true; - } - } - - return Result; -} - void Bot::SetLevel(uint8 in_level, bool command) { if(in_level > 0) Mob::SetLevel(in_level, command); @@ -3911,7 +3897,7 @@ std::list Bot::GetBotList(uint32 botOwnerCharacterID, std::st if(botOwnerCharacterID == 0) return ownersBots; - std::string query = StringFormat("SELECT `bot_id`, `name`, `class`, `level`, `race` FROM `bot_data` WHERE `owner_id` = '%u'", botOwnerCharacterID); + std::string query = StringFormat("SELECT `bot_id`, `name`, `class`, `level`, `race`, `gender` FROM `bot_data` WHERE `owner_id` = '%u'", botOwnerCharacterID); auto results = database.QueryDatabase(query); if(!results.Success()) { *errorMessage = std::string(results.ErrorMessage()); @@ -3925,6 +3911,7 @@ std::list Bot::GetBotList(uint32 botOwnerCharacterID, std::st availableBot.BotClass = atoi(row[2]); availableBot.BotLevel = atoi(row[3]); availableBot.BotRace = atoi(row[4]); + availableBot.BotGender = atoi(row[5]); ownersBots.push_back(availableBot); } return ownersBots; @@ -3954,182 +3941,6 @@ std::list Bot::ListSpawnedBots(uint32 characterID, std::string* return spawnedBots; } -void Bot::SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* errorMessage) -{ - if(!botGroup || botGroupName.empty()) - return; - - Mob* tempGroupLeader = botGroup->GetLeader(); - if(!tempGroupLeader->IsBot()) - return; - - uint32 botGroupId = 0; - uint32 botGroupLeaderBotId = tempGroupLeader->CastToBot()->GetBotID(); - std::string query = StringFormat("INSERT INTO `bot_groups` (`group_leader_id`, `group_name`) VALUES (%u, '%s')", botGroupLeaderBotId, botGroupName.c_str()); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return; - } - - botGroupId = results.LastInsertedID(); - if(botGroupId == 0) - return; - - for(int groupMemberIndex = 0; groupMemberIndex < botGroup->GroupCount(); groupMemberIndex++) { - Mob* tempBot = botGroup->members[groupMemberIndex]; - if(!tempBot || !tempBot->IsBot()) - continue; - - uint32 botGroupMemberBotId = tempBot->CastToBot()->GetBotID(); - query = StringFormat("INSERT INTO `bot_group_members` (`groups_index`, `bot_id`) VALUES (%u, %u)", botGroupId, botGroupMemberBotId); - results = database.QueryDatabase(query); - if(!results.Success()) - *errorMessage = std::string(results.ErrorMessage()); - } -} - -void Bot::DeleteBotGroup(std::string botGroupName, std::string* errorMessage) { - if(botGroupName.empty()) - return; - - uint32 botGroupId = GetBotGroupIdByBotGroupName(botGroupName, errorMessage); - if(!errorMessage->empty() || botGroupId== 0) - return; - - std::string query = StringFormat("DELETE FROM `bot_group_members` WHERE `groups_index` = %u", botGroupId); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return; - } - - query = StringFormat("DELETE FROM `bot_groups` WHERE `groups_index` = %u", botGroupId); - results = database.QueryDatabase(query); - if(!results.Success()) - *errorMessage = std::string(results.ErrorMessage()); -} - -std::list Bot::LoadBotGroup(std::string botGroupName, std::string* errorMessage) { - std::list botGroup; - if(botGroupName.empty()) - return botGroup; - - uint32 botGroupId = GetBotGroupIdByBotGroupName(botGroupName, errorMessage); - if(botGroupId == 0) - return botGroup; - - std::string query = StringFormat("SELECT `bot_id` FROM `bot_group_members` WHERE `groups_index` = %u", botGroupId); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return botGroup; - } - - for(auto row = results.begin(); row != results.end(); ++row) { - BotGroup tempBotGroup; - tempBotGroup.BotGroupID = botGroupId; - tempBotGroup.BotID = atoi(row[0]); - botGroup.push_back(tempBotGroup); - } - return botGroup; -} - -std::list Bot::GetBotGroupListByBotOwnerCharacterId(uint32 botOwnerCharacterId, std::string* errorMessage) { - std::list botGroups; - if(botOwnerCharacterId == 0) - return botGroups; - - std::string query = StringFormat("SELECT `group_name`, `group_leader_name` FROM `vw_bot_groups` WHERE `owner_id` = %u", botOwnerCharacterId); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return botGroups; - } - - for(auto row = results.begin(); row != results.end(); ++row) { - BotGroupList botGroupList; - botGroupList.BotGroupName = std::string(row[0]); - botGroupList.BotGroupLeaderName = std::string(row[1]); - botGroups.push_back(botGroupList); - } - return botGroups; -} - -bool Bot::DoesBotGroupNameExist(std::string botGroupName) { - if(botGroupName.empty()) - return false; - - std::string query = StringFormat("SELECT `groups_index` FROM `vw_bot_groups` WHERE `group_name` = '%s'", botGroupName.c_str()); - auto results = database.QueryDatabase(query); - if (!results.Success() || results.RowCount() == 0) - return false; - - for(auto row = results.begin(); row != results.end(); ++row) { - uint32 tempBotGroupId = atoi(row[0]); - std::string tempBotGroupName = std::string(row[1]); - if (botGroupName == tempBotGroupName && tempBotGroupId != 0) - return true; - } - - return false; -} - -uint32 Bot::CanLoadBotGroup(uint32 botOwnerCharacterId, std::string botGroupName, std::string* errorMessage) { - if(botOwnerCharacterId == 0 || botGroupName.empty()) - return 0; - - std::string query = StringFormat("SELECT `groups_index`, `group_name` FROM `vw_bot_groups` WHERE `owner_id` = %u", botOwnerCharacterId); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return 0; - } - - if(results.RowCount() == 0) - return 0; - - for(auto row = results.begin(); row != results.end(); ++row) { - uint32 tempBotGroupId = atoi(row[0]); - std::string tempBotGroupName = std::string(row[1]); - if(botGroupName == tempBotGroupName) - return tempBotGroupId; - } - - return 0; -} - -uint32 Bot::GetBotGroupIdByBotGroupName(std::string botGroupName, std::string* errorMessage) { - if(botGroupName.empty()) - return 0; - - std::string query = StringFormat("SELECT `groups_index` FROM `vw_bot_groups` WHERE `group_name` = '%s'", botGroupName.c_str()); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return 0; - } - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - return atoi(row[0]); -} - -uint32 Bot::GetBotGroupLeaderIdByBotGroupName(std::string botGroupName) { - if(botGroupName.empty()) - return 0; - - std::string query = StringFormat("SELECT `group_leader_id` FROM `vw_bot_groups` WHERE `group_name` = '%s'", botGroupName.c_str()); - auto results = database.QueryDatabase(query); - if (!results.Success() || results.RowCount() == 0) - return 0; - - auto row = results.begin(); - return atoi(row[0]); -} - uint32 Bot::AllowedBotSpawns(uint32 botOwnerCharacterID, std::string* errorMessage) { if(botOwnerCharacterID == 0) return 0; @@ -4424,120 +4235,6 @@ void Bot::BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 this->BotAddEquipItem(lootSlot, id); } -bool Bot::Bot_Command_Resist(int resisttype, int level) { - int resistid = 0; - switch(resisttype) { - case 1: // Poison Cleric - if(level >= 30) - resistid = 62; - else if(level >= 6) - resistid = 227; - break; - case 2: // Disease Cleric - if(level >= 36) - resistid = 63; - else if(level >= 11) - resistid = 226; - break; - case 3: // Fire Cleric - if(level >= 33) - resistid = 60; - else if(level >= 8) - resistid = 224; - break; - case 4: // Cold Cleric - if(level >= 38) - resistid = 61; - else if(level >= 13) - resistid = 225; - break; - case 5: // Magic Cleric - if(level >= 43) - resistid = 64; - else if(level >= 16) - resistid = 228; - break; - case 6: // Magic Enchanter - if(level >= 37) - resistid = 64; - else if(level >= 17) - resistid = 228; - break; - case 7: // Poison Druid - if(level >= 44) - resistid = 62; - else if(level >= 19) - resistid = 227; - break; - case 8: // Disease Druid - if(level >= 44) - resistid = 63; - else if(level >= 19) - resistid = 226; - break; - case 9: // Fire Druid - if(level >= 20) - resistid = 60; - else if(level >= 1) - resistid = 224; - break; - case 10: // Cold Druid - if(level >= 30) - resistid = 61; - else if(level >= 9) - resistid = 225; - break; - case 11: // Magic Druid - if(level >= 49) - resistid = 64; - else if(level >= 34) - resistid = 228; - break; - case 12: // Poison Shaman - if(level >= 35) - resistid = 62; - else if(level >= 20) - resistid = 227; - break; - case 13: // Disease Shaman - if(level >= 30) - resistid = 63; - else if(level >= 8) - resistid = 226; - break; - case 14: // Fire Shaman - if(level >= 27) - resistid = 60; - else if(level >= 5) - resistid = 224; - break; - case 15: // Cold Shaman - if(level >= 24) - resistid = 61; - else if(level >= 1) - resistid = 225; - break; - case 16: // Magic Shaman - if(level >= 43) - resistid = 64; - else if(level >= 19) - resistid = 228; - break; - } - - if(resistid > 0) { - Group* g = GetGroup(); - if(g) { - for(int k = 0; k < MAX_GROUP_MEMBERS; k++) { - if(g->members[k]) - SpellOnTarget(resistid, g->members[k]); - } - return true; - } - } - return false; -} - bool Bot::RemoveBotFromGroup(Bot* bot, Group* group) { bool Result = false; if(bot && group) { @@ -4584,230 +4281,6 @@ bool Bot::AddBotToGroup(Bot* bot, Group* group) { return Result; } -bool Bot::BotGroupCreate(std::string botGroupLeaderName) { - bool Result = false; - if(!botGroupLeaderName.empty()) { - Bot* botGroupLeader = entity_list.GetBotByBotName(botGroupLeaderName); - if(botGroupLeader) - Result = BotGroupCreate(botGroupLeader); - } - return Result; -} - -bool Bot::BotGroupCreate(Bot* botGroupLeader) { - bool Result = false; - if(botGroupLeader && !botGroupLeader->HasGroup()) { - Group* newGroup = new Group(botGroupLeader); - if(newGroup) { - entity_list.AddGroup(newGroup); - database.SetGroupID(botGroupLeader->GetName(), newGroup->GetID(), botGroupLeader->GetBotID()); - database.SetGroupLeaderName(newGroup->GetID(), botGroupLeader->GetName()); - botGroupLeader->SetFollowID(botGroupLeader->GetBotOwner()->GetID()); - Result = true; - } - } - return Result; -} - -bool Bot::Bot_Command_CharmTarget(int charmtype, Mob *target) { - int charmid = 0; - int charmlevel = GetLevel(); - if(target) { - switch(charmtype) { - case 1: // Enchanter - if((charmlevel >= 64) && (charmlevel <= 75)) - charmid = 3355; - else if((charmlevel >= 62) && (charmlevel <= 63)) - charmid = 3347; - else if((charmlevel >= 60) && (charmlevel <= 61)) - charmid = 1707; - else if((charmlevel >= 53) && (charmlevel <= 59)) - charmid = 1705; - else if((charmlevel >= 37) && (charmlevel <= 52)) - charmid = 183; - else if((charmlevel >= 23) && (charmlevel <= 36)) - charmid = 182; - else if((charmlevel >= 11) && (charmlevel <= 22)) - charmid = 300; - break; - case 2: // Necromancer - if((charmlevel >= 60) && (charmlevel <= 75)) - charmid = 1629; - else if((charmlevel >=47) && (charmlevel <= 59)) - charmid = 198; - else if((charmlevel >= 31) && (charmlevel <= 46)) - charmid = 197; - else if((charmlevel >= 18) && (charmlevel <= 30)) - charmid = 196; - break; - case 3: // Druid - if((charmlevel >= 63) && (charmlevel <= 75)) - charmid = 3445; - else if((charmlevel >= 55) && (charmlevel <= 62)) - charmid = 1556; - else if((charmlevel >= 52) && (charmlevel <= 54)) - charmid = 1553; - else if((charmlevel >= 43) && (charmlevel <= 51)) - charmid = 142; - else if((charmlevel >= 33) && (charmlevel <= 42)) - charmid = 141; - else if((charmlevel >= 23) && (charmlevel <= 32)) - charmid = 260; - else if((charmlevel >= 13) && (charmlevel <= 22)) - charmid = 242; - break; - } - if(charmid > 0) { - uint32 DontRootMeBeforeTime = 0; - CastSpell(charmid, target->GetID(), 1, -1, -1, &DontRootMeBeforeTime); - target->SetDontRootMeBefore(DontRootMeBeforeTime); - return true; - } - } - return false; -} - -bool Bot::Bot_Command_DireTarget(int diretype, Mob *target) { - int direid = 0; - int direlevel = GetLevel(); - if(target) { - switch(diretype) { - case 1: // Enchanter - if(direlevel >= 65) - direid = 5874; - else if(direlevel >= 55) - direid = 2761; - break; - case 2: // Necromancer - if(direlevel >= 65) - direid = 5876; - else if(direlevel >= 55) - direid = 2759; - break; - case 3: // Druid - if(direlevel >= 65) - direid = 5875; - else if(direlevel >= 55) - direid = 2760; - break; - } - if(direid > 0) { - uint32 DontRootMeBeforeTime = 0; - CastSpell(direid, target->GetID(), 1, -1, -1, &DontRootMeBeforeTime); - target->SetDontRootMeBefore(DontRootMeBeforeTime); - return true; - } - } - return false; -} - -bool Bot::Bot_Command_CalmTarget(Mob *target) { - if(target) { - int calmid = 0; - int calmlevel = GetLevel(); - if((calmlevel >= 67) && (calmlevel <= 75)) - calmid = 5274; - else if((calmlevel >= 62) && (calmlevel <= 66)) - calmid = 3197; - else if((calmlevel >= 35) && (calmlevel <= 61)) - calmid = 45; - else if((calmlevel >= 18) && (calmlevel <= 34)) - calmid = 47; - else if((calmlevel >= 6) && (calmlevel <= 17)) - calmid = 501; - else if((calmlevel >= 1) && (calmlevel <= 5)) - calmid = 208; - if(calmid > 0) { - uint32 DontRootMeBeforeTime = 0; - CastSpell(calmid, target->GetID(), 1, -1, -1, &DontRootMeBeforeTime); - target->SetDontRootMeBefore(DontRootMeBeforeTime); - return true; - } - } - return false; -} - -bool Bot::Bot_Command_RezzTarget(Mob *target) { - if(target) { - int rezid = 0; - int rezlevel = GetLevel(); - if(rezlevel >= 56) - rezid = 1524; - else if(rezlevel >= 47) - rezid = 392; - else if(rezlevel >= 42) - rezid = 2172; - else if(rezlevel >= 37) - rezid = 388; - else if(rezlevel >= 32) - rezid = 2171; - else if(rezlevel >= 27) - rezid = 391; - else if(rezlevel >= 22) - rezid = 2170; - else if(rezlevel >= 18) - rezid = 2169; - if(rezid > 0) { - uint32 DontRootMeBeforeTime = 0; - CastSpell(rezid, target->GetID(), 1, -1, -1, &DontRootMeBeforeTime); - target->SetDontRootMeBefore(DontRootMeBeforeTime); - return true; - } - } - return false; -} - -bool Bot::Bot_Command_Cure(int curetype, int level) { - int cureid = 0; - switch(curetype) { - case 1: // Poison - if(level >= 58) - cureid = 1525; - else if(level >= 48) - cureid = 97; - else if(level >= 22) - cureid = 95; - else if(level >= 1) - cureid = 203; - break; - case 2: // Disease - if(level >= 51) - cureid = 3693; - else if(level >= 28) - cureid = 96; - else if(level >= 4) - cureid = 213; - break; - case 3: // Curse - if(level >= 54) - cureid = 2880; - else if(level >= 38) - cureid = 2946; - else if(level >= 23) - cureid = 4057; - else if(level >= 8) - cureid = 4056; - break; - case 4: // Blindness - if(level >= 3) - cureid = 212; - break; - } - - if(cureid > 0) { - Group* g = GetGroup(); - if(g) { - for(int k = 0; k < MAX_GROUP_MEMBERS; k++) { - if(g->members[k]) - SpellOnTarget(cureid, g->members[k]); - } - return true; - } - } - - return false; -} - // Completes a trade with a client bot owner void Bot::FinishTrade(Client* client, BotTradeType tradeType) { if(client && !client->GetTradeskillObject() && (client->trade->state != Trading)) { @@ -5117,8 +4590,7 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att } } - if(GetInHealRotation()) - GetHealRotationLeader()->RemoveHealRotationMember(this); + LeaveHealRotationMemberPool(); entity_list.RemoveBot(this->GetID()); return true; @@ -8164,7 +7636,7 @@ void Bot::CalcRestState() { int32 Bot::LevelRegen() { int level = GetLevel(); - bool bonus = GetRaceBitmask(_baseRace) & RuleI(Character, BaseHPRegenBonusRaces); + bool bonus = GetPlayerRaceBit(_baseRace) & RuleI(Character, BaseHPRegenBonusRaces); uint8 multiplier1 = bonus ? 2 : 1; int32 hp = 0; if (level < 51) { @@ -8429,8 +7901,7 @@ void Bot::Camp(bool databaseSave) { if(IsGrouped()) RemoveBotFromGroup(this, GetGroup()); - if(GetInHealRotation()) - GetHealRotationLeader()->RemoveHealRotationMember(this); + LeaveHealRotationMemberPool(); if(databaseSave) Save(); @@ -8562,91 +8033,6 @@ bool Bot::CalculateNewPosition2(float x, float y, float z, float speed, bool che return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ); } -void Bot::BotGroupOrderFollow(Group* group, Client* client) { - if(group && client) { - Mob* groupLeader = group->GetLeader(); - if(groupLeader) { - for(int i = 0; i< MAX_GROUP_MEMBERS; i++) { - if(group->members[i] && group->members[i]->IsBot()) { - Bot* botGroupMember = group->members[i]->CastToBot(); - if(botGroupMember && botGroupMember->GetBotOwnerCharacterID() == client->CharacterID()) { - if(group->IsLeader(botGroupMember) && botGroupMember->GetBotOwner()) { - botGroupMember->SetFollowID(botGroupMember->GetBotOwner()->GetID()); - if(botGroupMember->GetBotOwner()) - botGroupMember->BotGroupSay(botGroupMember, "Following %s.", botGroupMember->GetBotOwner()->GetName()); - } else { - botGroupMember->SetFollowID(groupLeader->GetID()); - botGroupMember->BotGroupSay(botGroupMember, "Following %s.", groupLeader->GetCleanName()); - } - - botGroupMember->WipeHateList(); - if(botGroupMember->HasPet() && botGroupMember->GetPet()) - botGroupMember->GetPet()->WipeHateList(); - } - } - } - } - } -} - -void Bot::BotGroupOrderGuard(Group* group, Client* client) { - if(group && client) { - for(int i = 0; i< MAX_GROUP_MEMBERS; i++) { - if(group->members[i] && group->members[i]->IsBot()) { - Bot* botGroupMember = group->members[i]->CastToBot(); - if(botGroupMember && botGroupMember->GetBotOwnerCharacterID() == client->CharacterID()) { - botGroupMember->SetFollowID(0); - botGroupMember->BotGroupSay(botGroupMember, "Guarding here."); - botGroupMember->WipeHateList(); - if(botGroupMember->HasPet() && botGroupMember->GetPet()) - botGroupMember->GetPet()->WipeHateList(); - } - } - } - } -} - -void Bot::BotGroupOrderAttack(Group* group, Mob* target, Client* client) { - if(group && target) { - Mob* groupLeader = group->GetLeader(); - if(groupLeader) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(group->members[i] && group->members[i]->IsBot()) { - Bot* botGroupMember = group->members[i]->CastToBot(); - if(botGroupMember->GetBotOwnerCharacterID() == client->CharacterID()) { - botGroupMember->WipeHateList(); - botGroupMember->AddToHateList(target, 1); - if(botGroupMember->HasPet() && botGroupMember->GetPet()) { - botGroupMember->GetPet()->WipeHateList(); - botGroupMember->GetPet()->AddToHateList(target, 1); - } - } - } - } - } - } -} - -void Bot::BotGroupSummon(Group* group, Client* client) { - if(group) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(group->members[i] && group->members[i]->IsBot()) { - Bot* botMember = group->members[i]->CastToBot(); - if(botMember->GetBotOwnerCharacterID() == client->CharacterID()) { - botMember->SetTarget(botMember->GetBotOwner()); - botMember->WipeHateList(); - botMember->Warp(glm::vec3(botMember->GetBotOwner()->GetPosition())); - if(botMember->HasPet() && botMember->GetPet()) { - botMember->GetPet()->SetTarget(botMember); - botMember->GetPet()->WipeHateList(); - botMember->GetPet()->Warp(glm::vec3(botMember->GetBotOwner()->GetPosition())); - } - } - } - } - } -} - Bot* Bot::GetBotByBotClientOwnerAndBotName(Client* c, std::string botName) { Bot* Result = 0; if(c) { @@ -9157,11 +8543,11 @@ void Bot::CalcBotStats(bool showtext) { return; if(showtext) { - GetBotOwner()->Message(15, "Bot updating..."); + GetBotOwner()->Message(15, "Updating %s...", GetCleanName()); } if(!IsValidRaceClassCombo()) { - GetBotOwner()->Message(15, "A %s - %s bot was detected. Is this Race/Class combination allowed?.", GetRaceName(GetRace()), GetEQClassName(GetClass(), GetLevel())); + GetBotOwner()->Message(15, "A %s - %s bot was detected. Is this Race/Class combination allowed?.", GetRaceIDName(GetRace()), GetClassIDName(GetClass(), GetLevel())); GetBotOwner()->Message(15, "Previous Bots Code releases did not check Race/Class combinations during create."); GetBotOwner()->Message(15, "Unless you are experiencing heavy lag, you should delete and remake this bot."); } @@ -9191,7 +8577,7 @@ void Bot::CalcBotStats(bool showtext) { AI_AddNPCSpells(this->GetBotSpellID()); if(showtext) { - GetBotOwner()->Message(15, "I'm updated."); + GetBotOwner()->Message(15, "%s has been updated.", GetCleanName()); GetBotOwner()->Message(15, "Level: %i HP: %i AC: %i Mana: %i STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetLevel(), max_hp, GetAC(), max_mana, GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA()); GetBotOwner()->Message(15, "Resists-- Magic: %i, Poison: %i, Fire: %i, Cold: %i, Disease: %i, Corruption: %i.",GetMR(),GetPR(),GetFR(),GetCR(),GetDR(),GetCorrup()); // Test Code @@ -9233,3588 +8619,6 @@ bool Bot::GroupHasClass(Group* group, uint8 classId) { return result; } -void Bot::ProcessBotCommands(Client *c, const Seperator *sep) { - // All bot command processing occurs here now instead of in command.cpp - - // TODO: Log any possible error messages as most of these will be MySQL error messages. - std::string TempErrorMessage; - - if(sep->arg[1][0] == '\0') { - c->Message(13, "Bad argument, type #bot help"); - return; - } - if(!strcasecmp( sep->arg[1], "help") && !strcasecmp( sep->arg[2], "\0")){ - c->Message(0, "List of commands availables for bots:"); - c->Message(0, "#bot help - show this"); - c->Message(0, "#bot create [name] [class (id)] [race (id)] [model (male/female)] - create a permanent bot. See #bot help create."); - c->Message(0, "#bot help create - show all the race/class id. (make it easier to create bots)"); - c->Message(0, "#bot delete - completely destroy forever the targeted bot and all its items."); - c->Message(0, "#bot list [all/class(1-16)] - list all of your bots or list by class. Classes: 1(WAR), 2(CLR), 3(PAL), 4(RNG), 5(SHD), 6(DRU), 7(MNK), 8(BRD), 9(ROG), 10(SHM), 11(NEC), 12(WIZ), 13(MAG), 14(ENC), 15(BST), 16(BER)"); - c->Message(0, "#bot spawn [bot name] - spawn a bot from it's name (use list to see all the bots). "); - c->Message(0, "#bot inventory list - show the inventory (and the slots IDs) of the targeted bot."); - c->Message(0, "#bot inventory remove [slotid] - remove the item at the given slot in the inventory of the targeted bot."); - c->Message(0, "#bot update - you must type that command once you gain a level."); - c->Message(0, "#bot summon - It will summon your targeted bot to you."); - c->Message(0, "#bot mez - If you're grouped with an Enchanter, he will mesmerize your target."); - c->Message(0, "#bot picklock - You must have a targeted Rogue bot in your group and be right on the door."); - c->Message(0, "#bot cure [poison|disease|curse|blindness] Cleric has most options"); - c->Message(0, "#bot bind - You must have a Cleric in your group to get Bind Affinity cast on you."); - c->Message(0, "#bot track - look at mobs in the zone (Ranger has options)"); - c->Message(0, "#bot target calm - attempts to pacify your target mob."); - c->Message(0, "#bot evac - transports your group to safe location in the current zone (bots are lost)"); - c->Message(0, "#bot resurrect - Your Cleric bot will resurrect your targeted player corpse."); - c->Message(0, "#bot corpse summon - Necromancers summon your targeted player's corpses."); - c->Message(0, "#bot lore - cast Identify on the item on your mouse pointer."); - c->Message(0, "#bot speed - Bots will cast Spirit of Wolf on you (Druid has options)"); - c->Message(0, "#bot invis - Bot invisiblity (must have proper class in group)"); - c->Message(0, "#bot levitate - Bot levitation (must have proper class in group)"); - c->Message(0, "#bot resist - Bot resist buffs (must have proper class in group)"); - c->Message(0, "#bot rune - Enchanter bot casts Rune spell on you"); - c->Message(0, "#bot shrink - Shaman or Beastlord will shrink target"); - c->Message(0, "#bot endureb - Bot enduring breath (must have proper class in group)"); - c->Message(0, "#bot charm - (must have proper class in group)"); - c->Message(0, "#bot dire charm - (must have proper class in group)"); - c->Message(0, "#bot pet remove - (remove pet before charm)"); - c->Message(0, "#bot gate - Druid or Wizard bot will cast gate."); - c->Message(0, "#bot archery - Toggle Archery Skilled bots between using a Bow or using Melee weapons."); - c->Message(0, "#bot setpet [earth|water|air|fire|monster] - Select the pet type you want your Magician bot to use."); - c->Message(0, "#bot [giveitem|gi] - Gives your targeted bot the item you have on your cursor."); - c->Message(0, "#bot [augmentitem|ai] - Allows you to augment items for other classes. (You MUST have the Augmentation Sealer window filled)"); - c->Message(0, "#bot camp - Tells your bot to camp out of the game."); - c->Message(0, "#bot group help - Displays the commands available to manage any bots in your group."); - c->Message(0, "#bot botgroup help - Displays the commands available to manage bot ONLY groups."); - c->Message(0, "#bot mana [ | all] - Displays a mana report for all your spawned bots."); - c->Message(0, "#bot setfollowdistance ### - sets target bots follow distance to ### (ie 30 or 250)."); - c->Message(0, "#bot clearfollowdistance [ | spawned | all] - clears user-defined follow distance setting for bot target, spawned or all - includes spawned and unspawned."); - c->Message(0, "#bot [hair|haircolor|beard|beardcolor|face|eyes|heritage|tattoo|details ] - Change your bot's appearance."); - c->Message(0, "#bot armorcolor - #bot help armorcolor for info"); - c->Message(0, "#bot taunt [on|off] - Determines whether or not your targeted bot will taunt."); - c->Message(0, "#bot stance [name] [stance (id)|list] - Sets/lists stance for named bot (Passive = 0, Balanced = 1, Efficient = 2, Reactive = 3, Aggressive = 4, Burn = 5, BurnAE = 6)"); - c->Message(0, "#bot defensive [bot name] - Causes Warrior, Shadow Knight, or Paladin bot to use their defensive discipline or buff."); - c->Message(0, "#bot healrotation help - Displays the commands available to manage bot heal rotations."); - c->Message(0, "#bot pull [] [target] - Bot will attempt to pull your target NPC."); - c->Message(0, "#bot setinspectmessage - Copies your inspect message to a targeted bot that you own."); - c->Message(0, "#bot bardoutofcombat [on|off] - Determines whether Bard bots use out of combat songs."); - c->Message(0, "#bot showhelm [on|off] - Determines whether or not your targeted bot's helmet will show. (Requires a respawn to take effect)"); - return; - } - - // pull - if(!strcasecmp(sep->arg[1], "pull")) { - Mob *target = c->GetTarget(); - if(target == nullptr || target == c || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { - c->Message(15, "You must select a monster"); - return; - } - - if(c->IsGrouped()) { - bool haspuller = false; - Group *g = c->GetGroup(); - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g && g->members[i] && g->members[i]->IsBot() && !strcasecmp(g->members[i]->GetName() , sep->arg[2])) { - haspuller = true; - Mob *puller = g->members[i]; - if (puller->CastToBot()->IsArcheryRange(target)) { - puller->CastToBot()->BotGroupSay(puller->CastToBot(), "Trying to pull %s.", target->GetCleanName()); - puller->CastToBot()->BotRangedAttack(target); - } else { - puller->CastToBot()->BotGroupSay(puller->CastToBot(), "%s is out of range.", target->GetCleanName()); - } - } - } - if(!haspuller) { - c->Message(15, "You must have an Puller in your group."); - } - } - return; - } - - // added Bot follow distance - SetFollowDistance - if(!strcasecmp(sep->arg[1], "setfollowdistance")) { - if((c->GetTarget() == nullptr) || (c->GetTarget() == c) || (!c->GetTarget()->IsBot()) || (c->GetTarget()->CastToBot()->GetBotOwner() != c)) { - c->Message(15, "You must target a bot you own!"); - } - else { - uint32 BotFollowDistance = atoi(sep->arg[2]); - c->GetTarget()->SetFollowDistance(BotFollowDistance); - } - - return; - } - - if (!strcasecmp(sep->arg[1], "clearfollowdistance")) { - bool case_all = !strcasecmp(sep->arg[2], "all"); - bool case_spawned = !strcasecmp(sep->arg[2], "spawned"); - if (case_all || case_spawned) { - if (case_all) { - std::string query = StringFormat( - "UPDATE `bot_data`" - " SET `follow_distance` = '%u'" - " WHERE `owner_id` = '%u'", - BOT_DEFAULT_FOLLOW_DISTANCE, - c->CharacterID() - ); - auto results = database.QueryDatabase(query); - if (!results.Success()) - return; - } - - std::list spawnedBots = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - if (!spawnedBots.empty()) { - for (std::list::iterator botsListItr = spawnedBots.begin(); botsListItr != spawnedBots.end(); ++botsListItr) { - Bot* tempBot = *botsListItr; - if (tempBot) { - tempBot->SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE); - } - } - } - } - else if ((c->GetTarget() == nullptr) || (c->GetTarget() == c) || (!c->GetTarget()->IsBot()) || (c->GetTarget()->CastToBot()->GetBotOwner() != c)) { - c->Message(15, "You must target a bot you own!"); - } - else { - c->GetTarget()->SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE); - } - - return; - } - - //bot armor colors - if(!strcasecmp(sep->arg[1], "armorcolor")) { - if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner() == c)) { - - if(sep->arg[2][0] == '\0' || sep->arg[3][0] == '\0' || sep->arg[4][0] == '\0' || sep->arg[5][0] == '\0') { - c->Message(0, "Usage: #bot armorcolor [slot] [red] [green] [blue] - use #bot help armorcolor for info"); - return; - } - - uint32 botid = c->GetTarget()->CastToBot()->GetBotID(); - std::string errorMessage; - - int setslot = atoi(sep->arg[2]); - uint8 red = atoi(sep->arg[3]); - uint8 green = atoi(sep->arg[4]); - uint8 blue = atoi(sep->arg[5]); - uint32 setcolor = (red << 16) | (green << 8) | blue; - std::string query; - if (setslot == -1) { - query = StringFormat( - "UPDATE `bot_inventories`" - " SET `inst_color` = %u" - " WHERE `slot_id`" - " IN (%u, %u, %u, %u, %u, %u, %u)" - " AND `bot_id` = %u", - setcolor, - MainHead, - MainArms, - MainWrist1, - MainHands, - MainChest, - MainLegs, - MainFeet, - botid - ); - auto results = database.QueryDatabase(query); - if (!results.Success()) - return; - - for (int i = MaterialHead; i <= MaterialFeet; ++i) { - c->GetTarget()->CastToBot()->SendWearChange(i); - } - } else { - query = StringFormat("UPDATE `bot_inventories` SET `inst_color` = %u WHERE `slot_id` = %i AND `bot_id` = %u", setcolor, setslot, botid); - auto results = database.QueryDatabase(query); - if (!results.Success()) - return; - - c->GetTarget()->CastToBot()->SendWearChange(Inventory::CalcMaterialFromSlot(setslot)); - } - - } - else { - c->Message(15, "You must target a bot you own to do this."); - } - return; - } - - if(!strcasecmp(sep->arg[1], "help") && !strcasecmp(sep->arg[2], "armorcolor")){ - c->Message(0, "-----------------#bot armorcolor help-----------------------------"); - c->Message(0, "Armor: -1(All), %u(Helm), %u(Arms), %u(Bracer), %u(Hands), %u(Chest/Robe), %u(Legs), %u(Boots)", - MainHead, MainArms, MainWrist1, MainHands, MainChest, MainLegs, MainFeet); - c->Message(0, "------------------------------------------------------------------"); - c->Message(0, "Color: [red] [green] [blue] (enter a number from 0-255 for each"); - c->Message(0, "------------------------------------------------------------------"); - c->Message(0, "Example: #bot armorcolor %u 0 255 0 - this would make the chest bright green", MainChest); - return; - } - - if(!strcasecmp(sep->arg[1], "augmentitem") || !strcasecmp(sep->arg[1], "ai")) { - AugmentItem_Struct* in_augment = new AugmentItem_Struct[sizeof(AugmentItem_Struct)]; - in_augment->container_slot = 1000; // - in_augment->augment_slot = -1; - Object::HandleAugmentation(c, in_augment, c->GetTradeskillObject()); - return; - } - - if(!strcasecmp(sep->arg[1], "giveitem") || !strcasecmp(sep->arg[1], "gi")) { - if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner() == c)) { - Bot* targetedBot = c->GetTarget()->CastToBot(); - if(targetedBot) - targetedBot->FinishTrade(c, BotTradeClientNoDropNoTrade); - } - else - c->Message(15, "You must target a bot you own to do this."); - - return; - } - - if(!strcasecmp(sep->arg[1], "camp")) { - if(!strcasecmp(sep->arg[2], "all")) { - BotOrderCampAll(c); - } else { - if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner()->CastToClient() == c)) { - Bot* targetedBot = c->GetTarget()->CastToBot(); - if(targetedBot) - targetedBot->Camp(); - } - else - c->Message(15, "You must target a bot you own to do this."); - } - - return; - } - - if(!strcasecmp(sep->arg[1], "create")) { - if(sep->arg[2][0] == '\0' || sep->arg[3][0] == '\0' || sep->arg[4][0] == '\0' || sep->arg[5][0] == '\0' || sep->arg[6][0] != '\0') { - c->Message(0, "Usage: #bot create [name] [class(id)] [race(id)] [gender (male/female|0/1)]"); - return; - } else if(strcasecmp(sep->arg[3],"1") && strcasecmp(sep->arg[3],"2") && strcasecmp(sep->arg[3],"3") && strcasecmp(sep->arg[3],"4") && strcasecmp(sep->arg[3],"5") && strcasecmp(sep->arg[3],"6") && strcasecmp(sep->arg[3],"7") && strcasecmp(sep->arg[3],"8") && strcasecmp(sep->arg[3],"9") && strcasecmp(sep->arg[3],"10") && strcasecmp(sep->arg[3],"11") && strcasecmp(sep->arg[3],"12") && strcasecmp(sep->arg[3],"13") && strcasecmp(sep->arg[3],"14") && strcasecmp(sep->arg[3],"15") && strcasecmp(sep->arg[3],"16")) { - c->Message(0, "Usage: #bot create [name] [class(id)] [race(id)] [gender (male/female|0/1)]"); - return; - } else if(strcasecmp(sep->arg[4],"1") && strcasecmp(sep->arg[4],"2") && strcasecmp(sep->arg[4],"3") && strcasecmp(sep->arg[4],"4") && strcasecmp(sep->arg[4],"5") && strcasecmp(sep->arg[4],"6") && strcasecmp(sep->arg[4],"7") && strcasecmp(sep->arg[4],"8") && strcasecmp(sep->arg[4],"9") && strcasecmp(sep->arg[4],"10") && strcasecmp(sep->arg[4],"11") && strcasecmp(sep->arg[4],"12") && strcasecmp(sep->arg[4],"330") && strcasecmp(sep->arg[4],"128") && strcasecmp(sep->arg[4],"130") && strcasecmp(sep->arg[4],"522")) { - c->Message(0, "Usage: #bot create [name] [class(1-16)] [race(1-12,128,130,330,522)] [gender (male/female|0/1)]"); - return; - } else if(strcasecmp(sep->arg[5],"male") && strcasecmp(sep->arg[5],"0") && strcasecmp(sep->arg[5],"female") && strcasecmp(sep->arg[5],"1")) { - c->Message(0, "Usage: #bot create [name] [class(1-16)] [race(1-12,128,130,330,522)] [gender (male/female|0/1)]"); - return; - } - - uint32 MaxBotCreate = RuleI(Bots, CreationLimit); - if(CreatedBotCount(c->CharacterID(), &TempErrorMessage) >= MaxBotCreate) { - c->Message(0, "You cannot create more than %i bots.", MaxBotCreate); - return; - } - - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - int gender = 0; - if(!strcasecmp(sep->arg[5], "female") || !strcasecmp(sep->arg[5], "1")) - gender = 1; - - if(!IsBotNameAvailable(sep->arg[2],&TempErrorMessage)) { - c->Message(0, "The name %s is already being used or is invalid. Please choose a different name.", sep->arg[2]); - return; - } - - NPCType DefaultNPCTypeStruct = CreateDefaultNPCTypeStructForBot(std::string(sep->arg[2]), std::string(), c->GetLevel(), atoi(sep->arg[4]), atoi(sep->arg[3]), gender); - Bot* NewBot = new Bot(DefaultNPCTypeStruct, c); - - if(NewBot) { - if(!NewBot->IsValidRaceClassCombo()) { - c->Message(0, "That Race/Class combination cannot be created."); - return; - } - - if(!NewBot->IsValidName()) { - c->Message(0, "%s has invalid characters. You can use only the A-Z, a-z and _ characters in a bot name.", NewBot->GetCleanName()); - return; - } - - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - if(!NewBot->Save()) - c->Message(0, "Unable to save %s as a bot.", NewBot->GetCleanName()); - else - c->Message(0, "%s saved as bot %u.", NewBot->GetCleanName(), NewBot->GetBotID()); - } - else - Log.Out(Logs::General, Logs::Error, "Error in #bot create, cannot find NewBot"); - return; - } - - if(!strcasecmp(sep->arg[1], "help") && !strcasecmp(sep->arg[2], "create") ){ - c->Message(0, "Classes: 1(WAR), 2(CLR), 3(PAL), 4(RNG), 5(SHD), 6(DRU), 7(MNK), 8(BRD), 9(ROG), 10(SHM), 11(NEC), 12(WIZ), 13(MAG), 14(ENC), 15(BST), 16(BER)"); - c->Message(0, "------------------------------------------------------------------"); - c->Message(0, "Races: 1(Human), 2(Barbarian), 3(Erudite), 4(Wood Elf), 5(High Elf), 6(Dark Elf), 7(Half Elf), 8(Dwarf), 9(Troll), 10(Ogre), 11(Halfling), 12(Gnome), 128(Iksar), 130(Vah Shir), 330(Froglok), 522(Drakkin)"); - c->Message(0, "------------------------------------------------------------------"); - c->Message(0, "Usage: #bot create [name] [class(1-16)] [race(1-12,128,130,330,522)] [gender(male/female)]"); - c->Message(0, "Example: #bot create Sneaky 9 6 male"); - return; - } - - if(!strcasecmp(sep->arg[1], "delete") ) { - if((c->GetTarget() == nullptr) || !c->GetTarget()->IsBot()) { - c->Message(15, "You must target a bot!"); - return; - } else if(c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() != c->CharacterID()) { - c->Message(15, "You can't delete a bot that you don't own."); - return; - } - - if(c->GetTarget()->IsBot()) { - Bot* BotTargeted = c->GetTarget()->CastToBot(); - if(BotTargeted) { - BotTargeted->DeleteBot(&TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - BotTargeted->Camp(false); - } - } - - return; - } - - if(!strcasecmp(sep->arg[1], "list")) { - bool listAll = true; - int iClass = atoi(sep->arg[2]); - if(iClass > 0 && iClass < 17) - listAll = false; - - std::list AvailableBots = GetBotList(c->CharacterID(), &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - if(!AvailableBots.empty()) { - for(std::list::iterator TempAvailableBotsList = AvailableBots.begin(); TempAvailableBotsList != AvailableBots.end(); ++TempAvailableBotsList) { - if(!listAll && TempAvailableBotsList->BotClass != iClass) - continue; - - c->Message(0, "Name: %s -- Class: %s -- Level: %u -- Race: %s", TempAvailableBotsList->BotName, ClassIdToString(TempAvailableBotsList->BotClass).c_str(), TempAvailableBotsList->BotLevel, RaceIdToString(TempAvailableBotsList->BotRace).c_str()); - } - } - else - c->Message(0, "You have no bots created. Use the #bot create command to create a bot."); - } - - if(!strcasecmp(sep->arg[1], "mana")) { - bool listAll = false; - Bot* bot = 0; - if(sep->argnum == 2) { - if(std::string(sep->arg[2]).compare("all") == 0) - listAll = true; - else { - std::string botName = std::string(sep->arg[2]); - Bot* tempBot = entity_list.GetBotByBotName(botName); - if(tempBot && tempBot->GetBotOwner() == c) - bot = tempBot; - } - } else { - if(c->GetTarget() && c->GetTarget()->IsBot()) - bot = c->GetTarget()->CastToBot(); - } - - if(bot && !listAll) { - if(bot->GetClass() != WARRIOR && bot->GetClass() != MONK && bot->GetClass() != BARD && bot->GetClass() != BERSERKER && bot->GetClass() != ROGUE) - c->Message(0, "Name: %s -- Class: %s -- Mana: %3.1f%%", bot->GetCleanName(), ClassIdToString(bot->GetClass()).c_str(), bot->GetManaRatio()); - } else { - std::list spawnedBots = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - if(!spawnedBots.empty()) { - for(std::list::iterator botsListItr = spawnedBots.begin(); botsListItr != spawnedBots.end(); ++botsListItr) { - Bot* tempBot = *botsListItr; - if(tempBot) { - if(tempBot->GetClass() != WARRIOR && tempBot->GetClass() != MONK && tempBot->GetClass() != BARD && tempBot->GetClass() != BERSERKER && tempBot->GetClass() != ROGUE) - c->Message(0, "Name: %s -- Class: %s -- Mana: %3.1f%%", tempBot->GetCleanName(), ClassIdToString(tempBot->GetClass()).c_str(), tempBot->GetManaRatio()); - } - } - } - else - c->Message(0, "You have no spawned bots in this zone."); - } - return; - } - - if(!strcasecmp(sep->arg[1], "spawn") ) { - if (RuleB(Bots, BotCharacterLevelEnabled)) { - if (c->GetLevel() < RuleI(Bots, BotCharacterLevel)) { - c->Message(0, "You are only level %d, you must be level %d to spawn a bot!", c->GetLevel(), RuleI(Bots, BotCharacterLevel)); - return; - } - } - - uint32 botId = GetBotIDByBotName(std::string(sep->arg[2])); - if(GetBotOwnerCharacterID(botId, &TempErrorMessage) != c->CharacterID()) { - c->Message(0, "You can't spawn a bot that you don't own."); - return; - } - - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - if(c->GetFeigned()) { - c->Message(0, "You can't summon bots while you are feigned."); - return; - } - - if(c->IsGrouped()) { - Group *g = entity_list.GetGroupByClient(c); - for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g && g->members[i] && !g->members[i]->qglobal && (g->members[i]->GetAppearance() != eaDead) - && (g->members[i]->IsEngaged() || (g->members[i]->IsClient() && g->members[i]->CastToClient()->GetAggroCount()))) { - c->Message(0, "You can't summon bots while you are engaged."); - return; - } - - if(g && g->members[i] && g->members[i]->qglobal) - return; - } - } else { - if(c->GetAggroCount() > 0) { - c->Message(0, "You can't spawn bots while you are engaged."); - return; - } - } - - Mob* TempBotMob = entity_list.GetMobByBotID(botId); - if(TempBotMob) { - c->Message(0, "This bot is already in the zone."); - return; - } - - int spawnedBotCount = SpawnedBotCount(c->CharacterID(), &TempErrorMessage); - - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - if(RuleB(Bots, QuestableSpawnLimit) && !c->GetGM()) { - const int allowedBots = AllowedBotSpawns(c->CharacterID(), &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - if(allowedBots == 0) { - c->Message(0, "You cannot spawn any bots."); - return; - } - - if(spawnedBotCount >= allowedBots) { - c->Message(0, "You cannot spawn more than %i bots.", spawnedBotCount); - return; - } - - } - - if(spawnedBotCount >= RuleI(Bots, SpawnLimit) && !c->GetGM()) { - c->Message(0, "You cannot spawn more than %i bots.", spawnedBotCount); - return; - } - - Bot* TempBot = LoadBot(botId, &TempErrorMessage); - - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - safe_delete(TempBot); - return; - } - - if(TempBot) { - TempBot->Spawn(c, &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - safe_delete(TempBot); - return; - } - - TempBot->BotGroupSay(TempBot, "I am ready for battle."); - } - else - c->Message(0, "BotID: %i not found", atoi(sep->arg[2])); - - return; - } - - if(!strcasecmp(sep->arg[1], "archery")) { - if((c->GetTarget() == nullptr) || (c->GetTarget() == c) || !c->GetTarget()->IsBot()) { - c->Message(15, "You must target a bot!"); - return; - } - - Bot* archerBot = c->GetTarget()->CastToBot(); - if(archerBot) { - if(archerBot->IsBotArcher()) - archerBot->SetBotArcher(false); - else - archerBot->SetBotArcher(true); - - archerBot->ChangeBotArcherWeapons(archerBot->IsBotArcher()); - if(archerBot->GetClass() == RANGER && archerBot->GetLevel() >= 61) - archerBot->SetRangerAutoWeaponSelect(archerBot->IsBotArcher()); - } - - return; - } - - if(!strcasecmp(sep->arg[1], "picklock")) { - if((c->GetTarget() == nullptr) || (c->GetTarget() == c) || !c->GetTarget()->IsBot() || (c->GetTarget()->GetClass() != ROGUE)) - c->Message(15, "You must target a Rogue bot!"); - else - entity_list.BotPickLock(c->GetTarget()->CastToBot()); - - return; - } - - if(!strcasecmp(sep->arg[1], "summon")) { - if((c->GetTarget() == nullptr) || (c->GetTarget() == c) || !c->GetTarget()->IsBot() || c->GetTarget()->IsPet()) - c->Message(15, "You must target a bot!"); - else if(c->GetTarget()->IsMob() && !c->GetTarget()->IsPet()) { - Mob *b = c->GetTarget(); - if(b) { - if(!b->IsBot()) - c->Message(15, "You must target a bot!"); - else if((b->CastToBot()->GetBotOwnerCharacterID() != c->CharacterID())) - b->CastToBot()->BotGroupSay(b->CastToBot(), "You can only summon your own bots."); - else { - b->SetTarget(c->CastToMob()); - b->Warp(glm::vec3(c->GetPosition())); - } - } - } - - return; - } - - if(!strcasecmp(sep->arg[1], "inventory") && !strcasecmp(sep->arg[2], "list")) { - if(c->GetTarget() != nullptr) { - if(c->GetTarget()->IsBot() && c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID()) { - Mob* b = c->GetTarget(); - int x = c->GetTarget()->CastToBot()->GetBotItemsCount(&TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - const char* equipped[EmuConstants::EQUIPMENT_SIZE + 1] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", - "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", - "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; - - const ItemInst* inst = nullptr; - const Item_Struct* item = nullptr; - bool is2Hweapon = false; - - std::string item_link; - Client::TextLink linker; - linker.SetLinkType(linker.linkItemInst); - - for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= (EmuConstants::EQUIPMENT_END + 1); ++i) { - if((i == MainSecondary) && is2Hweapon) - continue; - - inst = b->CastToBot()->GetBotItem(i == 22 ? 9999 : i); - if (inst) - item = inst->GetItem(); - else - item = nullptr; - - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - if(item == nullptr) { - c->Message(15, "I need something for my %s (Item %i)", equipped[i], (i == 22 ? 9999 : i)); - continue; - } - - if((i == MainPrimary) && ((item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HPiercing))) { - is2Hweapon = true; - } - - linker.SetItemInst(inst); - item_link = linker.GenerateLink(); - c->Message(15, "Using %s in my %s (Item %i)", item_link.c_str(), equipped[i], (i == 22 ? 9999 : i)); - } - } - else - c->Message(15, "You must group your bot first."); - } - else - c->Message(15, "You must target a bot first."); - - return; - } - - if(!strcasecmp(sep->arg[1], "inventory") && !strcasecmp(sep->arg[2], "remove")) { - if((c->GetTarget() == nullptr) || (sep->arg[3][0] == '\0') || !c->GetTarget()->IsBot()) { - c->Message(15, "Usage: #bot inventory remove [slotid] (You must have a bot targeted) "); - return; - } else if(c->GetTarget()->IsBot() && c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID()) { - if(c->GetTradeskillObject() || (c->trade->state == Trading)) - return; - - int slotId = atoi(sep->arg[3]); - if((slotId > EmuConstants::EQUIPMENT_END || slotId < EmuConstants::EQUIPMENT_BEGIN) && slotId != 9999) { - c->Message(15, "A bot has 22 slots in its inventory, please choose a slot between 0 and 21 or 9999."); - return; - } - - const char* equipped[EmuConstants::EQUIPMENT_SIZE + 1] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", - "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", - "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; - - const Item_Struct* itm = nullptr; - const ItemInst* itminst = c->GetTarget()->CastToBot()->GetBotItem(slotId); - if(itminst) - itm = itminst->GetItem(); - - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - // Don't allow the player to remove a lore item they already possess and cause a crash - bool failedLoreCheck = false; - if(itminst) { - for (int m = AUG_BEGIN; m < EmuConstants::ITEM_COMMON_SIZE; ++m) { - ItemInst *itma = itminst->GetAugment(m); - if(itma) { - if(c->CheckLoreConflict(itma->GetItem())) - failedLoreCheck = true; - } - } - - if(c->CheckLoreConflict(itm)) - failedLoreCheck = true; - } - if(!failedLoreCheck) { - if(itm) { - c->PushItemOnCursor(*itminst, true); - Bot *gearbot = c->GetTarget()->CastToBot(); - if((slotId == MainRange)||(slotId == MainAmmo)||(slotId == MainPrimary)||(slotId == MainSecondary)) - gearbot->SetBotArcher(false); - - gearbot->RemoveBotItemBySlot(slotId, &TempErrorMessage); - - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - gearbot->BotRemoveEquipItem(slotId); - gearbot->CalcBotStats(); - switch(slotId) { - case MainCharm: - case MainEar1: - case MainHead: - case MainFace: - case MainEar2: - case MainNeck: - case MainBack: - case MainWrist1: - case MainWrist2: - case MainRange: - case MainPrimary: - case MainSecondary: - case MainFinger1: - case MainFinger2: - case MainChest: - case MainWaist: - case MainPowerSource: - case MainAmmo: - gearbot->BotGroupSay(gearbot, "My %s is now unequipped.", equipped[slotId]); - break; - case MainShoulders: - case MainArms: - case MainHands: - case MainLegs: - case MainFeet: - gearbot->BotGroupSay(gearbot, "My %s are now unequipped.", equipped[slotId]); - break; - default: - break; - } - } - else { - switch(slotId) { - case MainCharm: - case MainEar1: - case MainHead: - case MainFace: - case MainEar2: - case MainNeck: - case MainBack: - case MainWrist1: - case MainWrist2: - case MainRange: - case MainPrimary: - case MainSecondary: - case MainFinger1: - case MainFinger2: - case MainChest: - case MainWaist: - case MainPowerSource: - case MainAmmo: - c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "My %s is already unequipped.", equipped[slotId]); - break; - case MainShoulders: - case MainArms: - case MainHands: - case MainLegs: - case MainFeet: - c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "My %s are already unequipped.", equipped[slotId]); - break; - default: - break; - } - } - } - else { - c->Message_StringID(0, PICK_LORE); - } - } - return; - } - - if(!strcasecmp(sep->arg[1], "update")) { - if((c->GetTarget() != nullptr) && c->GetTarget()->IsBot()) { - if(c->GetLevel() <= c->GetTarget()->GetLevel()) { - c->Message(15, "This bot has already been updated."); - return; - } - - if(c->IsGrouped()) { - Group *g = entity_list.GetGroupByClient(c); - for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g && g->members[i] && g->members[i]->IsEngaged()) { - c->Message(15, "You can't update bots while you are engaged."); - return; - } - } - } - - if((c->GetTarget()->CastToBot()->GetBotOwner() == c->CastToMob()) && !c->GetFeigned()) { - Bot* bot = c->GetTarget()->CastToBot(); - bot->SetPetChooser(false); - bot->CalcBotStats(); - } else { - if(c->GetFeigned()) - c->Message(15, "You cannot update bots while feigned."); - else - c->Message(15, "You must target your bot first."); - } - } - else - c->Message(15, "You must target a bot first."); - - return; - } - - //Bind - if(!strcasecmp(sep->arg[1], "bind")) { - Mob *binder = nullptr; - bool hasbinder = false; - if(c->IsGrouped()) { - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == CLERIC)) { - hasbinder = true; - binder = g->members[i]; - } - } - - if(!hasbinder) - c->Message(15, "You must have a Cleric in your group."); - } - } - - if(hasbinder) { - binder->CastToBot()->BotGroupSay(binder->CastToBot(), "Attempting to bind you %s.", c->GetName()); - binder->CastToNPC()->CastSpell(35, c->GetID(), 1, -1, -1); - } - return; - } - - // Rune - if(!strcasecmp(sep->arg[1], "rune")) { - Mob *runeer = nullptr; - bool hasruneer = false; - if(c->IsGrouped()) { - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) { - hasruneer = true; - runeer = g->members[i]; - } - } - - if(!hasruneer) - c->Message(15, "You must have an Enchanter in your group."); - } - } - - if(hasruneer) { - if (c->GetLevel() <= 12) - runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "I need to be level 13 or higher for this..."); - else if ((c->GetLevel() >= 13) && (c->GetLevel() <= 21)) { - runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune I..."); - runeer->CastSpell(481, c->GetID(), 1, -1, -1); - } else if ((c->GetLevel() >= 22) && (c->GetLevel() <= 32)) { - runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune II..."); - runeer->CastSpell(482, c->GetID(), 1, -1, -1); - } else if ((c->GetLevel() >= 33) && (c->GetLevel() <= 39)) { - runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune III..."); - runeer->CastSpell(483, c->GetID(), 1, -1, -1); - } else if ((c->GetLevel() >= 40) && (c->GetLevel() <= 51)) { - runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune IV..."); - runeer->CastSpell(484, c->GetID(), 1, -1, -1); - } else if ((c->GetLevel() >= 52) && (c->GetLevel() <= 60)) { - runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune V..."); - runeer->CastSpell(1689, c->GetID(), 1, -1, -1); - } else if (c->GetLevel() >= 61){ - runeer->CastToBot()->BotGroupSay(runeer->CastToBot(), "Casting Rune of Zebuxoruk..."); - runeer->CastSpell(3343, c->GetID(), 1, -1, -1); - } - } - return; - } - - //Tracking - if(!strcasecmp(sep->arg[1], "track") && c->IsGrouped()) { - Mob *Tracker; - uint32 TrackerClass = 0; - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g->members[i] && g->members[i]->IsBot()) { - switch(g->members[i]->GetClass()) { - case RANGER: - Tracker = g->members[i]; - TrackerClass = RANGER; - break; - case DRUID: - if(TrackerClass != RANGER) { - Tracker = g->members[i]; - TrackerClass = DRUID; - } - break; - case BARD: - if(TrackerClass == 0) { - Tracker = g->members[i]; - TrackerClass = BARD; - } - break; - default: - break; - } - } - } - - int Level = (c->GetLevel()); - int RangeR = (Level * 80); //Ranger - int RangeD = (Level * 30); //Druid - int RangeB = (Level * 20); //Bard - switch(TrackerClass) { - case RANGER: - if(!strcasecmp(sep->arg[2], "all")) { - Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking everything."); - entity_list.ShowSpawnWindow(c, RangeR, false); - } else if(!strcasecmp(sep->arg[2], "rare")) { - Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Selective tracking."); - entity_list.ShowSpawnWindow(c, RangeR, true); - } else if(!strcasecmp(sep->arg[2], "near")) { - Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking mobs nearby."); - entity_list.ShowSpawnWindow(c, RangeD, false); - } else - Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Do you want to %s, %s, or %s?", Tracker->CastToBot()->CreateSayLink(c, "#bot track all", "track all").c_str(), Tracker->CastToBot()->CreateSayLink(c, "#bot track near", "track near").c_str(), Tracker->CastToBot()->CreateSayLink(c, "#bot track rare", "track rare").c_str()); - - break; - case BARD: - if(TrackerClass != RANGER) - Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking up."); - entity_list.ShowSpawnWindow(c, RangeB, false); - break; - case DRUID: - if(TrackerClass = BARD) - Tracker->CastToBot()->BotGroupSay(Tracker->CastToBot(), "Tracking up."); - entity_list.ShowSpawnWindow(c, RangeD, false); - break; - default: - c->Message(15, "You must have a Ranger, Druid, or Bard in your group."); - break; - } - } - } - - //Cure - if ((!strcasecmp(sep->arg[1], "cure")) && (c->IsGrouped())) { - Mob *Curer; - uint32 CurerClass = 0; - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++){ - if(g->members[i] && g->members[i]->IsBot()) { - switch(g->members[i]->GetClass()) { - case CLERIC: - Curer = g->members[i]; - CurerClass = CLERIC; - break; - case SHAMAN: - if(CurerClass != CLERIC){ - Curer = g->members[i]; - CurerClass = SHAMAN; - } - break; - case DRUID: - if (CurerClass == 0){ - Curer = g->members[i]; - CurerClass = DRUID; - } - break; - default: - break; - } - } - } - switch(CurerClass) { - case CLERIC: - if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 1)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); - Curer->CastToBot()->Bot_Command_Cure(1, Curer->GetLevel()); - } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 4)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); - Curer->CastToBot()->Bot_Command_Cure(2, Curer->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "curse") && (c->GetLevel() >= 8)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); - Curer->CastToBot()->Bot_Command_Cure(3, Curer->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 3)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); - Curer->CastToBot()->Bot_Command_Cure(4, Curer->GetLevel()); - } else if (!strcasecmp(sep->arg[2], "curse") && (c->GetLevel() <= 8) - || !strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() <= 3) - || !strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 4) - || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 1)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I am not the required level yet."); - } else - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want to cure %s, %s, %s, or %s?", Curer->CastToBot()->CreateSayLink(c, "#bot cure poison", "poison").c_str(), Curer->CastToBot()->CreateSayLink(c, "#bot cure disease", "disease").c_str(), Curer->CastToBot()->CreateSayLink(c, "#bot cure curse", "curse").c_str(), Curer->CastToBot()->CreateSayLink(c, "#bot cure blindness", "blindness").c_str()); - - break; - case SHAMAN: - if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 2)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); - Curer->CastToBot()->Bot_Command_Cure(1, Curer->GetLevel()); - } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 1)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); - Curer->CastToBot()->Bot_Command_Cure(2, Curer->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "curse")) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell."); - } else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 7)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); - Curer->CastToBot()->Bot_Command_Cure(4, Curer->GetLevel()); - } else if (!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() <= 7) - || !strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 1) - || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 2)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I am not the required level yet."); - } else - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want to cure %s, %s, or %s?", Curer->CastToBot()->CreateSayLink(c, "#bot cure poison", "poison").c_str(), Curer->CastToBot()->CreateSayLink(c, "#bot cure disease", "disease").c_str(), Curer->CastToBot()->CreateSayLink(c, "#bot cure blindness", "blindness").c_str()); - - break; - case DRUID: - if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 5)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); - Curer->CastToBot()->Bot_Command_Cure(1, Curer->GetLevel()); - } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 4)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Trying to cure us of %s.", sep->arg[2]); - Curer->CastToBot()->Bot_Command_Cure(2, Curer->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "curse")) { // Fire level 1 - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell."); - } else if(!strcasecmp(sep->arg[2], "blindness") && (c->GetLevel() >= 13)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I don't have that spell."); - } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 4) - || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 5)) { - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "I am not the required level yet."); - } else - Curer->CastToBot()->BotGroupSay(Curer->CastToBot(), "Do you want to cure %s or %s?", Curer->CastToBot()->CreateSayLink(c, "#bot cure poison", "poison").c_str(), Curer->CastToBot()->CreateSayLink(c, "#bot cure disease", "disease").c_str()); - break; - default: - c->Message(15, "You must have a Cleric, Shaman, or Druid in your group."); - break; - } - } - } - - //Mez - if(!strcasecmp(sep->arg[1], "mez")) { - Mob *target = c->GetTarget(); - if(target == nullptr || target == c || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { - c->Message(15, "You must select a monster"); - return; - } - - if(c->IsGrouped()) { - bool hasmezzer = false; - Group *g = c->GetGroup(); - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g && g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) { - hasmezzer = true; - Mob *mezzer = g->members[i]; - mezzer->CastToBot()->BotGroupSay(mezzer->CastToBot(), "Trying to mesmerize %s.", target->GetCleanName()); - mezzer->CastToBot()->MesmerizeTarget(target); - } - } - - if(!hasmezzer) - c->Message(15, "You must have an Enchanter in your group."); - } - return; - } - - //Lore (Identify item) - if(!strcasecmp(sep->arg[1], "lore")) { - if(c->IsGrouped()) { - bool hascaster = false; - Group *g = c->GetGroup(); - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g && g->members[i] && g->members[i]->IsBot()) { - uint8 casterlevel = g->members[i]->GetLevel(); - switch(g->members[i]->GetClass()) { - case ENCHANTER: - if(casterlevel >= 15) - hascaster = true; - - break; - case WIZARD: - if(casterlevel >= 14) - hascaster = true; - - break; - case NECROMANCER: - if(casterlevel >= 17) - hascaster = true; - - break; - case MAGICIAN: - if(casterlevel >= 13) - hascaster = true; - - break; - default: - break; - } - if(hascaster) { - g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "Trying to Identify your item..."); - g->members[i]->CastSpell(305, c->GetID(), 1, -1, -1); - break; - } - } - } - - if(!hascaster) - c->Message(15, "You don't see anyone in your group that can cast Identify."); - } else - c->Message(15, "You don't see anyone in your group that can cast Identify."); - - return; - } - - //Resurrect - if(!strcasecmp(sep->arg[1], "resurrect")) { - Mob *target = c->GetTarget(); - if(target == nullptr || !target->IsPlayerCorpse()) { - c->Message(15, "You must select a corpse!"); - return; - } - - if(c->IsGrouped()) { - bool hasrezzer = false; - Group *g = c->GetGroup(); - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g && g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == CLERIC)) { - hasrezzer = true; - Mob *rezzer = g->members[i]; - rezzer->CastToBot()->BotGroupSay(rezzer->CastToBot(), "Trying to resurrect %s.", target->GetCleanName()); - rezzer->CastToBot()->Bot_Command_RezzTarget(target); - break; - } - } - - if(!hasrezzer) - c->Message(15, "You must have a Cleric in your group!"); - } else - c->Message(15, "You must have a Cleric in your group!"); - - return; - } - - if(!strcasecmp(sep->arg[1], "setpet")) { - if(c->GetTarget() && c->GetTarget()->IsBot() && (c->GetTarget()->GetClass() == MAGICIAN)) { - if(c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID()) { - int botlevel = c->GetTarget()->GetLevel(); - c->GetTarget()->CastToBot()->SetPetChooser(true); - if(botlevel == 1) { - c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have any pets yet."); - return; - } - - if(!strcasecmp(sep->arg[2], "water")) { - c->GetTarget()->CastToBot()->SetPetChooserID(0); - } else if(!strcasecmp(sep->arg[2], "fire")) { - if(botlevel < 3) { - c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); - return; - } else - c->GetTarget()->CastToBot()->SetPetChooserID(1); - } else if(!strcasecmp(sep->arg[2], "air")) { - if(botlevel < 4) { - c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); - return; - } else - c->GetTarget()->CastToBot()->SetPetChooserID(2); - } else if(!strcasecmp(sep->arg[2], "earth")) { - if(botlevel < 5) { - c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); - return; - } else - c->GetTarget()->CastToBot()->SetPetChooserID(3); - } else if(!strcasecmp(sep->arg[2], "monster")) { - if(botlevel < 30) { - c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "I don't have that pet yet."); - return; - } else - c->GetTarget()->CastToBot()->SetPetChooserID(4); - } - - if(c->GetTarget()->GetPet()) { - uint16 id = c->GetTarget()->GetPetID(); - c->GetTarget()->SetPetID(0); - c->GetTarget()->CastSpell(331, id); - } - } - } else - c->Message(15, "You must target your Magician bot!"); - - return; - } - - //Summon Corpse - if(!strcasecmp(sep->arg[1], "corpse") && !strcasecmp(sep->arg[2], "summon")) { - if(c->GetTarget() == nullptr) { - c->Message(15, "You must select player with his corpse in the zone!"); - return; - } - - if(c->IsGrouped()) { - bool hassummoner = false; - Mob *t = c->GetTarget(); - Group *g = c->GetGroup(); - int summonerlevel = 0; - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(g && g->members[i] && g->members[i]->IsBot() && ((g->members[i]->GetClass() == NECROMANCER)||(g->members[i]->GetClass() == SHADOWKNIGHT))) { - hassummoner = true; - summonerlevel = g->members[i]->GetLevel(); - g->members[i]->InterruptSpell(); - if(!t->IsClient()) { - g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "You have to target a player with a corpse in the zone!"); - return; - } else { - g->members[i]->SetTarget(t); - if(summonerlevel < 12) { - g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "I don't have that spell yet."); - } else if((summonerlevel > 11) && (summonerlevel < 35)) { - g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "Attempting to summon %s\'s corpse.", t->GetCleanName()); - g->members[i]->CastSpell(2213, t->GetID(), 1, -1, -1); - return; - } else if((summonerlevel > 34) && (summonerlevel < 71)) { - g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "Attempting to summon %s\'s corpse.", t->GetCleanName()); - g->members[i]->CastSpell(3, t->GetID(), 1, -1, -1); - return; - } else if(summonerlevel > 70) { - g->members[i]->CastToBot()->BotGroupSay(g->members[i]->CastToBot(), "Attempting to summon %s\'s corpse.", t->GetCleanName()); - g->members[i]->CastSpell(10042, t->GetID(), 1, -1, -1); - return; - } - } - } - } - - if (!hassummoner) - c->Message(15, "You must have a Necromancer or Shadow Knight in your group."); - - return; - } - } - - //Pacify - if(!strcasecmp(sep->arg[1], "target") && !strcasecmp(sep->arg[2], "calm")) { - Mob *target = c->GetTarget(); - if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) - c->Message(15, "You must select a monster!"); - else { - if(c->IsGrouped()) { - Group *g = c->GetGroup(); - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - // seperated cleric and chanter so chanter is primary - if(g && g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == ENCHANTER)) { - Bot *pacer = g->members[i]->CastToBot(); - pacer->BotGroupSay(pacer, "Trying to pacify %s.", target->GetCleanName()); - if(pacer->Bot_Command_CalmTarget(target)) { - if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_InstantHate)) - c->Message(0, "I have successfully pacified %s.", target->GetCleanName()); - - return; - } - else - c->Message(0, "I failed to pacify %s.", target->GetCleanName()); - } - // seperated cleric and chanter so chanter is primary - if(g && g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == CLERIC) && (GroupHasEnchanterClass(g) == false)) { - Bot *pacer = g->members[i]->CastToBot(); - pacer->BotGroupSay(pacer, "Trying to pacify %s.", target->GetCleanName()); - - if(pacer->Bot_Command_CalmTarget(target)) { - if(target->FindType(SE_Lull) || target->FindType(SE_Harmony) || target->FindType(SE_InstantHate)) - c->Message(0, "I have successfully pacified %s.", target->GetCleanName()); - - return; - } - else - c->Message(0, "I failed to pacify %s.", target->GetCleanName()); - } - } - } - } - - return; - } - - //Charm - if(!strcasecmp(sep->arg[1], "charm")) { - Mob *target = c->GetTarget(); - if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { - c->Message(15, "You must select a monster!"); - return; - } - - uint32 DBtype = c->GetTarget()->GetBodyType(); - Mob *Charmer; - uint32 CharmerClass = 0; - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++){ - if(g->members[i] && g->members[i]->IsBot()) { - switch(g->members[i]->GetClass()) { - case ENCHANTER: - Charmer = g->members[i]; - CharmerClass = ENCHANTER; - break; - case NECROMANCER: - if(CharmerClass != ENCHANTER){ - Charmer = g->members[i]; - CharmerClass = NECROMANCER; - } - break; - case DRUID: - if (CharmerClass == 0){ - Charmer = g->members[i]; - CharmerClass = DRUID; - } - break; - default: - break; - } - } - } - switch(CharmerClass) { - case ENCHANTER: - if (c->GetLevel() >= 11) { - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s.", target->GetCleanName()); - Charmer->CastToBot()->Bot_Command_CharmTarget(1, target); - } - else if (c->GetLevel() <= 10) - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I am not the required level yet."); - else - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob level is too high or can't be charmed."); - break; - case NECROMANCER: - if ((c->GetLevel() >= 18) && (DBtype == 3)) { - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s.", target->GetCleanName()); - Charmer->CastToBot()->Bot_Command_CharmTarget(2, target); - } - else if (c->GetLevel() <= 17) - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I am not the required level yet."); - else - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob is not undead."); - break; - case DRUID: - if ((c->GetLevel() >= 13) && (DBtype == 21)) { - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Trying to charm %s.", target->GetCleanName()); - Charmer->CastToBot()->Bot_Command_CharmTarget(3, target); - } - else if (c->GetLevel() <= 12) - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "I am not the required level yet."); - else - Charmer->CastToBot()->BotGroupSay(Charmer->CastToBot(), "Mob is not an animal."); - break; - default: - c->Message(15, "You must have an Enchanter, Necromancer, or Druid in your group."); - break; - } - } - } - - // Remove Bot's Pet - if(!strcasecmp(sep->arg[1], "pet") && !strcasecmp(sep->arg[2], "remove")) { - if(c->GetTarget() != nullptr) { - if (c->IsGrouped() && c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner() == c) && - ((c->GetTarget()->GetClass() == NECROMANCER) || (c->GetTarget()->GetClass() == ENCHANTER) || (c->GetTarget()->GetClass() == DRUID))) { - if(c->GetTarget()->CastToBot()->IsBotCharmer()) { - c->GetTarget()->CastToBot()->SetBotCharmer(false); - c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "Using a summoned pet."); - } else { - if(c->GetTarget()->GetPet()) { - c->GetTarget()->GetPet()->Say_StringID(PET_GETLOST_STRING); - c->GetTarget()->GetPet()->Depop(false); - c->GetTarget()->SetPetID(0); - } - c->GetTarget()->CastToBot()->SetBotCharmer(true); - c->GetTarget()->CastToBot()->BotGroupSay(c->GetTarget()->CastToBot(), "Available for Dire Charm command."); - } - } - else - c->Message(15, "You must target your Enchanter, Necromancer, or Druid bot."); - } - else - c->Message(15, "You must target an Enchanter, Necromancer, or Druid bot."); - - return; - } - - //Dire Charm - if(!strcasecmp(sep->arg[1], "Dire") && !strcasecmp(sep->arg[2], "Charm")) { - Mob *target = c->GetTarget(); - if(target == nullptr || target->IsClient() || target->IsBot() || (target->IsPet() && target->GetOwner() && target->GetOwner()->IsBot())) { - c->Message(15, "You must select a monster"); - return; - } - uint32 DBtype = c->GetTarget()->GetBodyType(); - Mob *Direr; - uint32 DirerClass = 0; - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++){ - if(g->members[i] && g->members[i]->IsBot()) { - switch(g->members[i]->GetClass()) { - case ENCHANTER: - Direr = g->members[i]; - DirerClass = ENCHANTER; - break; - case NECROMANCER: - if(DirerClass != ENCHANTER){ - Direr = g->members[i]; - DirerClass = NECROMANCER; - } - break; - case DRUID: - if (DirerClass == 0){ - Direr = g->members[i]; - DirerClass = DRUID; - } - break; - default: - break; - } - } - } - switch(DirerClass) { - case ENCHANTER: - if (c->GetLevel() >= 55) { - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s.", target->GetCleanName()); - Direr->CastToBot()->Bot_Command_DireTarget (1,target); - } - else if (c->GetLevel() <= 55) - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I am not the required level yet."); - else - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob level is too high or can't be charmed."); - break; - case NECROMANCER: - if ((c->GetLevel() >= 55) && (DBtype == 3)) { - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s.", target->GetCleanName()); - Direr->CastToBot()->Bot_Command_DireTarget (2,target); - } - else if (c->GetLevel() <= 55) - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I am not the required level yet."); - else - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob is not undead."); - break; - case DRUID: - if ((c->GetLevel() >= 55) && (DBtype == 21)) { - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Trying to dire charm %s.", target->GetCleanName()); - Direr->CastToBot()->Bot_Command_DireTarget (3,target); - } - else if (c->GetLevel() <= 55) - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "I am not the required level yet."); - else - Direr->CastToBot()->BotGroupSay(Direr->CastToBot(), "Mob is not an animal."); - break; - default: - c->Message(15, "You must have an Enchanter, Necromancer, or Druid in your group."); - break; - } - } - } - - // Evacuate - if(!strcasecmp(sep->arg[1], "evac")) { - Mob *evac = nullptr; - bool hasevac = false; - if(c->IsGrouped()) { - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if((g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == DRUID)) || (g->members[i] && g->members[i]->IsBot() && (g->members[i]->GetClass() == WIZARD))) { - hasevac = true; - evac = g->members[i]; - } - } - - if(!hasevac) - c->Message(15, "You must have a Druid in your group."); - } - } - - if((hasevac) && (c->GetLevel() >= 18)) { - evac->CastToBot()->BotGroupSay(evac->CastToBot(), "Attempting to evacuate you, %s.", c->GetName()); - evac->CastToClient()->CastSpell(2183, c->GetID(), 1, -1, -1); - } - else if((hasevac) && (c->GetLevel() <= 17)) - evac->CastToBot()->BotGroupSay(evac->CastToBot(), "I'm not level 18 yet."); - - return; - } - - // Sow - if ((!strcasecmp(sep->arg[1], "speed")) && (c->IsGrouped())) { - Mob *Sower; - uint32 SowerClass = 0; - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++){ - if(g->members[i] && g->members[i]->IsBot()) { - switch(g->members[i]->GetClass()) { - case DRUID: - Sower = g->members[i]; - SowerClass = DRUID; - break; - case SHAMAN: - if (SowerClass != DRUID){ - Sower = g->members[i]; - SowerClass = SHAMAN; - } - break; - case RANGER: - if (SowerClass == 0){ - Sower = g->members[i]; - SowerClass = RANGER; - } - break; - case BEASTLORD: - if (SowerClass == 0){ - Sower = g->members[i]; - SowerClass = BEASTLORD; - } - break; - default: - break; - } - } - } - switch(SowerClass) { - case DRUID: - if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() >= 10)) { - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting Spirit of Wolf."); - Sower->CastSpell(278, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "regular")) && (zone->CanCastOutdoor()) && (c->GetLevel() <= 10)) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 10 yet."); - else if ((!strcasecmp(sep->arg[2], "wolf")) && zone->CanCastOutdoor() && (c->GetLevel() >= 20)) { - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting group Spirit of Wolf."); - Sower->CastSpell(428, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "wolf")) && (c->GetLevel() <= 20)) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 20 yet."); - else if ((!strcasecmp(sep->arg[2], "feral")) && (c->GetLevel() >= 50)) { - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting Feral Pack."); - Sower->CastSpell(4058, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "feral")) && (c->GetLevel() <= 50)) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 50 yet."); - else if ((!strcasecmp(sep->arg[2], "shrew")) && (c->GetLevel() >= 35)) { - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting Pack Shrew."); - Sower->CastSpell(4055, c->GetID(), 1, -1, -1); - } - else if ((!strcasecmp(sep->arg[2], "wolf")) && (c->GetLevel() <= 35)) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 35 yet."); - else if ((!zone->CanCastOutdoor()) && (!strcasecmp(sep->arg[2], "regular")) || (!zone->CanCastOutdoor()) && (!strcasecmp(sep->arg[2], "wolf"))) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try %s if you're 35 or higher, or %s if you're 50 or higher.", Sower->CastToBot()->CreateSayLink(c, "#bot speed shrew", "Pack Shrew").c_str(), Sower->CastToBot()->CreateSayLink(c, "#bot speed feral", "Feral Pack").c_str()); - else if (!zone->CanCastOutdoor()) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try 5s if you're 35 or higher, or %s if you're 50 or higher.", Sower->CastToBot()->CreateSayLink(c, "#bot speed shrew", "Pack Shrew").c_str(), Sower->CastToBot()->CreateSayLink(c, "#bot speed feral", "Feral Pack").c_str()); - else if (zone->CanCastOutdoor()) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Do you want %s or %s?", Sower->CastToBot()->CreateSayLink(c, "#bot speed regular", "Spirit of Wolf").c_str(), Sower->CastToBot()->CreateSayLink(c, "#bot speed wolf", "Group Spirit of Wolf").c_str()); - else if (!zone->CanCastOutdoor()) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors, try %s if you're 35 or higher, or %s if you're 50 or higher.", Sower->CastToBot()->CreateSayLink(c, "#bot speed shrew", "Pack Shrew").c_str(), Sower->CastToBot()->CreateSayLink(c, "#bot speed feral", "Feral").c_str()); - break; - case SHAMAN: - if ((zone->CanCastOutdoor()) && (c->GetLevel() >= 9)) { - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting Spirit of Wolf."); - Sower->CastToClient()->CastSpell(278, c->GetID(), 1, -1, -1); - } - else if (!zone->CanCastOutdoor()) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors."); - else if (c->GetLevel() <= 9) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 9 yet."); - break; - case RANGER: - if ((zone->CanCastOutdoor()) && (c->GetLevel() >= 28)){ - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting Spirit of Wolf."); - Sower->CastToClient()->CastSpell(278, c->GetID(), 1, -1, -1); - } - else if (!zone->CanCastOutdoor()) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors."); - else if (c->GetLevel() <= 28) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 28 yet."); - break; - case BEASTLORD: - if((zone->CanCastOutdoor()) && (c->GetLevel() >= 24)) { - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "Casting Spirit of Wolf."); - Sower->CastToClient()->CastSpell(278, c->GetID(), 1, -1, -1); - } - else if (!zone->CanCastOutdoor()) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I can't cast this spell indoors."); - else if (c->GetLevel() <= 24) - Sower->CastToBot()->BotGroupSay(Sower->CastToBot(), "I'm not level 24 yet."); - break; - default: - c->Message(15, "You must have a Druid, Shaman, Ranger, or Beastlord in your group."); - break; - } - } - } - - // Shrink - if ((!strcasecmp(sep->arg[1], "shrink")) && (c->IsGrouped())) { - Mob *Shrinker; - uint32 ShrinkerClass = 0; - Group *g = c->GetGroup(); - Mob *target = c->GetTarget(); - if(target == nullptr || (!target->IsClient() && (c->GetTarget()->CastToBot()->GetBotOwner() != c))) - c->Message(15, "You must select a player or bot you own!"); - - else if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++){ - if(g->members[i] && g->members[i]->IsBot()) { - switch(g->members[i]->GetClass()) { - case SHAMAN: - Shrinker = g->members[i]; - ShrinkerClass = SHAMAN; - break; - case BEASTLORD: - if (ShrinkerClass != SHAMAN){ - Shrinker = g->members[i]; - ShrinkerClass = BEASTLORD; - } - break; - default: - break; - } - } - } - switch(ShrinkerClass) { - case SHAMAN: - if (c->GetLevel() >= 15) { - Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "Casting Shrink."); - Shrinker->CastToBot()->SpellOnTarget(345, target); - } - else if (c->GetLevel() <= 14) - Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "I'm not level 15 yet."); - break; - case BEASTLORD: - if (c->GetLevel() >= 23) { - Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "Casting Shrink."); - Shrinker->CastToBot()->SpellOnTarget(345, target); - } - else if (c->GetLevel() <= 22) - Shrinker->CastToBot()->BotGroupSay(Shrinker->CastToBot(), "I'm not level 23 yet."); - break; - default: - c->Message(15, "You must have a Shaman or Beastlord in your group."); - break; - } - } - } - - // Gate - if ((!strcasecmp(sep->arg[1], "gate")) && (c->IsGrouped())) { - const char* druidgate[25][4] = { { "#bot gate karana", "karana", "North Karana", "550" }, { "#bot gate commons", "commons", "West Commonlands", "551" }, - { "#bot gate tox", "tox", "Toxxulia Forest", "552" }, { "#bot gate butcher", "butcher", "Butcherblock Mountains", "553" }, { "#bot gate lava", "lava", "Lavastorm Mountains", "554" }, - { "#bot gate ro", "ro", "South Ro", "555" }, { "#bot gate feerott", "feerrott", "Feerrott", "556" }, { "#bot gate steamfont", "steamfont", "Steamfont Mountains", "557" }, - { "#bot gate misty", "misty", "Misty Thicket", "558" }, { "#bot gate wakening", "wakening", "Wakening Lands", "1398" }, { "#bot gate iceclad", "iceclad", "Ieclad Ocean", "1434" }, - { "#bot gate divide", "divide", "The Great Divide", "1438" }, { "#bot gate cobalt", "cobalt", "Cobalt Scar", "1440" }, { "#bot gate combines", "combines", "The Combines", "1517" }, - { "#bot gate surefall", "surefall", "Surefall Glade", "2020" }, { "#bot gate grimling", "grimling", "Grimling Forest", "2419" }, { "#bot gate twilight", "twilight", "The Twilight Sea", "2424" }, - { "#bot gate dawnshroud", "dawnshroud", "Dawnshroud Peak", "2429" }, { "#bot gate nexus", "nexus", "The Nexus", "2432" }, { "#bot gate pok", "pok", "Plane of Knowledge", "3184" }, - { "#bot gate stonebrunt", "stonebrunt", "Stonebrunt Mountains", "3792" }, { "#bot gate bloodfields", "bloodfields", "Bloodfields", "6184" }, - { "#bot gate emerald", "emerald", "The Emerald Jungle", "1737" }, { "#bot gate skyfire", "skyfire", "Skyfire Mountains", "1736" }, { "#bot gate slaughter", "slaughter", "Wall of Slaughter", "6179" } }; - const char* wizardgate[24][4] = { { "#bot gate commons", "commons", "West Commonlands", "566" }, { "#bot gate fay", "fay", "Greater Faydark", "563" }, - { "#bot gate ro", "ro", "South Ro", "567" }, { "#bot gate tox", "tox", "Toxxulia Forest", "561" }, { "#bot gate nk", "nk", "North Karana", "562" }, - { "#bot gate nek", "nek", "Nektulos Forest", "564" }, { "#bot gate wakening", "wakening", "Wakening Lands", "1399" }, { "#bot gate iceclad", "iceclad", "Iceclad Ocean", "1418" }, - { "#bot gate divide", "divide", "The Great Divide", "1423" }, { "#bot gate cobalt", "cobalt", "Cobaltscar", "1425" }, { "#bot gate dreadlands", "dreadlands", "Dreadlands", "1516" }, - { "#bot gate wk", "wk", "West Karana", "568" }, { "#bot gate twilight", "twilight", "Twilight Sea", "2425" }, { "#bot gate dawnshroud", "dawnshroud", "Dawnshroud Peak", "2430" }, - { "#bot gate nexus", "nexus", "Nexus", "2944" }, { "#bot gate pok", "pok", "Plane of Knowledge", "3180" }, { "#bot gate wos", "wos", "Wall of Slaughter", "6178" }, - { "#bot gate grimling", "grimling", "Grimling Forest", "2420" }, { "#bot gate emerald", "emerald", "Emerald Jungle", "1739" }, { "#bot gate hateplane", "hateplane", "Plane of Hate", "666" }, - { "#bot gate airplane", "airplane", "Plane of Sky", "674" }, { "#bot gate skyfire", "skyfire", "Skyfire Mountains", "1738" }, - { "#bot gate bloodfields", "bloodfields", "Bloodfields", "6183" }, { "#bot gate stonebrunt", "stonebrunt", "Stonebrunt Mountains", "3793" } }; - bool valid = false; - Mob *Gater; - uint32 GaterClass = 0; - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++){ - if(g->members[i] && g->members[i]->IsBot()) { - switch(g->members[i]->GetClass()) { - case DRUID: - Gater = g->members[i]; - GaterClass = DRUID; - break; - case WIZARD: - if (GaterClass == 0){ - Gater = g->members[i]; - GaterClass = WIZARD; - } - break; - default: - break; - } - } - } - switch(GaterClass) { - case DRUID: { - for (int i = 0; i < 25; i++) { - if (!strcasecmp(sep->arg[2], druidgate[i][1])) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Gating to %s!", druidgate[i][2]); - Gater->CastSpell(atoi(druidgate[i][3]), c->GetID(), 1, -1, -1); - valid = true; - } - } - if (!valid) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can gate you to all of the following zones:"); - for (int i = 0; i < 25; i++) - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "%s", Gater->CastToBot()->CreateSayLink(c, druidgate[i][0], druidgate[i][2]).c_str()); - } - break; - } - case WIZARD: { - for (int i = 0; i < 24; i++) { - if (!strcasecmp(sep->arg[2], wizardgate[i][1])) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "Gating to %s!", wizardgate[i][2]); - Gater->CastSpell(atoi(wizardgate[i][3]), c->GetID(), 1, -1, -1); - valid = true; - } - } - if (!valid) { - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "With the proper level I can gate you to all of the following zones:"); - for (int i = 0; i < 24; i++) - Gater->CastToBot()->BotGroupSay(Gater->CastToBot(), "%s", Gater->CastToBot()->CreateSayLink(c, wizardgate[i][0], wizardgate[i][2]).c_str()); - } - break; - } - default: - c->Message(15, "You must have a Druid or Wizard in your group."); - break; - } - } - } - - //Endure Breath - if ((!strcasecmp(sep->arg[1], "endureb")) && (c->IsGrouped())) { - Mob *Endurer; - uint32 EndurerClass = 0; - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++){ - if(g->members[i] && g->members[i]->IsBot()) { - switch(g->members[i]->GetClass()) { - case DRUID: - Endurer = g->members[i]; - EndurerClass = DRUID; - break; - case SHAMAN: - if (EndurerClass != DRUID){ - Endurer = g->members[i]; - EndurerClass = SHAMAN; - } - break; - case ENCHANTER: - if(EndurerClass == 0){ - Endurer = g->members[i]; - EndurerClass = ENCHANTER; - } - break; - case RANGER: - if(EndurerClass == 0) { - Endurer = g->members[i]; - EndurerClass = RANGER; - } - break; - case BEASTLORD: - if(EndurerClass == 0) { - Endurer = g->members[i]; - EndurerClass = BEASTLORD; - } - break; - default: - break; - } - } - } - switch(EndurerClass) { - case DRUID: - if (c->GetLevel() < 6) - Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 6 yet."); - else { - Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); - Endurer->CastSpell(86, c->GetID(), 1, -1, -1); - break; - } - break; - case SHAMAN: - if (c->GetLevel() < 12) - Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 12 yet."); - else { - Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); - Endurer->CastSpell(86, c->GetID(), 1, -1, -1); - } - break; - case RANGER: - if (c->GetLevel() < 20) - Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 20 yet."); - else { - Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); - Endurer->CastSpell(86, c->GetID(), 1, -1, -1); - } - break; - case ENCHANTER: - if (c->GetLevel() < 12) - Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 12 yet."); - else { - Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); - Endurer->CastSpell(86, c->GetID(), 1, -1, -1); - } - break; - case BEASTLORD: - if (c->GetLevel() < 25) - Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "I'm not level 25 yet."); - else { - Endurer->CastToBot()->BotGroupSay(Endurer->CastToBot(), "Casting Enduring Breath."); - Endurer->CastSpell(86, c->GetID(), 1, -1, -1); - } - break; - default: - c->Message(15, "You must have a Druid, Shaman, Ranger, Enchanter, or Beastlord in your group."); - break; - } - } - } - - //Invisible - if ((!strcasecmp(sep->arg[1], "invis")) && (c->IsGrouped())) { - Mob *Inviser; - uint32 InviserClass = 0; - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++){ - if(g->members[i] && g->members[i]->IsBot()) { - switch(g->members[i]->GetClass()) { - case ENCHANTER: - Inviser = g->members[i]; - InviserClass = ENCHANTER; - break; - case MAGICIAN: - if (InviserClass != ENCHANTER){ - Inviser = g->members[i]; - InviserClass = MAGICIAN; - } - break; - case WIZARD: - if((InviserClass != ENCHANTER) && (InviserClass != MAGICIAN)){ - Inviser = g->members[i]; - InviserClass = WIZARD; - } - break; - case NECROMANCER: - if(InviserClass == 0){ - Inviser = g->members[i]; - InviserClass = NECROMANCER; - } - break; - case DRUID: - if((InviserClass != ENCHANTER) && (InviserClass != WIZARD) - || (InviserClass != MAGICIAN)){ - Inviser = g->members[i]; - InviserClass = DRUID; - } - break; - default: - break; - } - } - } - switch(InviserClass) { - case ENCHANTER: - if ((c->GetLevel() <= 14) && (!strcasecmp(sep->arg[2], "undead"))) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 14 yet."); - else if ((!c->IsInvisible(c)) && (!c->invisible_undead) && (c->GetLevel() >= 14) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting Invisibility vs. Undead."); - Inviser->CastSpell(235, c->GetID(), 1, -1, -1); - } - else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "live"))) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 4 yet."); - else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 4) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting Invisibilty."); - Inviser->CastSpell(42, c->GetID(), 1, -1, -1); - } - else if ((c->GetLevel() <= 6) && (!strcasecmp(sep->arg[2], "see"))) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 6 yet."); - else if ((c->GetLevel() >= 6) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting See Invisibility."); - Inviser->CastSpell(80, c->GetID(), 1, -1, -1); - } - else if ((c->IsInvisible(c)) || (c->invisible_undead)) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed."); - else - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want %s, %s, or %s?", Inviser->CastToBot()->CreateSayLink(c, "#bot invis live", "Invisibility").c_str(), Inviser->CastToBot()->CreateSayLink(c, "#bot invis undead", "Invisibility vs. Undead").c_str(), Inviser->CastToBot()->CreateSayLink(c, "#bot invis see", "See Invisibility").c_str()); - break; - case MAGICIAN: - if (!strcasecmp(sep->arg[2], "undead")) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell."); - else if ((c->GetLevel() <= 8) && (!strcasecmp(sep->arg[2], "live"))) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 8 yet."); - else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 8) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting Invisibilty."); - Inviser->CastSpell(42, c->GetID(), 1, -1, -1); - } - else if ((c->GetLevel() <= 16) && (!strcasecmp(sep->arg[2], "see"))) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 16 yet."); - else if ((c->GetLevel() >= 16) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting See Invisibility."); - Inviser->CastSpell(80, c->GetID(), 1, -1, -1); - } - else if ((c->IsInvisible(c)) || (c->invisible_undead)) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed."); - else - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want %s or %s?", Inviser->CastToBot()->CreateSayLink(c, "#bot invis live", "Invisibility").c_str(), Inviser->CastToBot()->CreateSayLink(c, "#bot invis see", "see Invisibility").c_str()); - break; - case WIZARD: - if ((c->GetLevel() <= 39) && (!strcasecmp(sep->arg[2], "undead"))) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 39 yet."); - else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 39) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting Invisibility vs. Undead."); - Inviser->CastSpell(235, c->GetID(), 1, -1, -1); - } - else if ((c->GetLevel() <= 16) && (!strcasecmp(sep->arg[2], "live"))) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 16 yet."); - else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 16) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting Invisibilty."); - Inviser->CastSpell(42, c->GetID(), 1, -1, -1); - } - else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "see"))) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 6 yet."); - else if ((c->GetLevel() >= 4) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting See Invisibility."); - Inviser->CastSpell(80, c->GetID(), 1, -1, -1); - } - else if ((c->IsInvisible(c)) || (c->invisible_undead)) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed."); - else - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want %s, %s, or %s?", Inviser->CastToBot()->CreateSayLink(c, "#bot invis undead", "Invisibility vs. Undead").c_str(), Inviser->CastToBot()->CreateSayLink(c, "#bot invis live", "Invisibility").c_str(), Inviser->CastToBot()->CreateSayLink(c, "#bot invis see", "See Invisibility").c_str()); - break; - case NECROMANCER: - if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (!strcasecmp(sep->arg[2], "undead"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting Invisibility vs. Undead."); - Inviser->CastSpell(235, c->GetID(), 1, -1, -1); - } - else if (!strcasecmp(sep->arg[2], "see")) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell."); - else if (!strcasecmp(sep->arg[2], "live")) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell."); - else if ((c->IsInvisible(c))|| (c->invisible_undead)) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed."); - else - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I only have %s.", Inviser->CastToBot()->CreateSayLink(c, "#bot invis undead", "Invisibility vs. Undead").c_str()); - break; - case DRUID: - if (!strcasecmp(sep->arg[2], "undead")) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I don't have that spell."); - else if ((c->GetLevel() <= 4) && (!strcasecmp(sep->arg[2], "live"))) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 4 yet."); - else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 18) && (!strcasecmp(sep->arg[2], "live"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting Superior Camouflage."); - Inviser->CastSpell(34, c->GetID(), 1, -1, -1); - } else if ((!c->IsInvisible(c))&& (!c->invisible_undead) && (c->GetLevel() >= 4) && (!strcasecmp(sep->arg[2], "live")) && (zone->CanCastOutdoor())) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting Camouflage."); - Inviser->CastSpell(247, c->GetID(), 1, -1, -1); - } - else if ((c->GetLevel() >= 4) && (!strcasecmp(sep->arg[2], "live")) && (!zone->CanCastOutdoor())) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this spell indoors."); - else if ((c->GetLevel() <= 13) && (!strcasecmp(sep->arg[2], "see"))) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I'm not level 13 yet."); - else if ((c->GetLevel() >= 13) && (!strcasecmp(sep->arg[2], "see"))) { - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Casting See Invisibility."); - Inviser->CastSpell(80, c->GetID(), 1, -1, -1); - } - else if ((c->IsInvisible(c)) || (c->invisible_undead)) - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "I can't cast this if you're already invis-buffed."); - else - Inviser->CastToBot()->BotGroupSay(Inviser->CastToBot(), "Do you want %s or %s?", Inviser->CastToBot()->CreateSayLink(c, "#bot invis live", "Invisibility").c_str(), Inviser->CastToBot()->CreateSayLink(c, "#bot invis see", "See Invisibility").c_str()); - break; - default: - c->Message(15, "You must have a Enchanter, Magician, Wizard, Druid, or Necromancer in your group."); - break; - } - } - } - - //Levitate - if ((!strcasecmp(sep->arg[1], "levitate")) && (c->IsGrouped())) { - Mob *Lever; - uint32 LeverClass = 0; - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++){ - if(g->members[i] && g->members[i]->IsBot()) { - switch(g->members[i]->GetClass()) { - case DRUID: - Lever = g->members[i]; - LeverClass = DRUID; - break; - case SHAMAN: - if (LeverClass != DRUID){ - Lever = g->members[i]; - LeverClass = SHAMAN; - } - break; - case WIZARD: - if(LeverClass == 0){ - Lever = g->members[i]; - LeverClass = WIZARD; - } - break; - case ENCHANTER: - if (LeverClass == 0) { - Lever = g->members[i]; - LeverClass = ENCHANTER; - } - break; - default: - break; - } - } - } - switch(LeverClass) { - case DRUID: - if (c->GetLevel() <= 14) - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 14 yet."); - else if (zone->CanCastOutdoor()) { - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate."); - Lever->CastSpell(261, c->GetID(), 1, -1, -1); - break; - } - else if (!zone->CanCastOutdoor()) - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors."); - break; - case SHAMAN: - if ((zone->CanCastOutdoor()) && (c->GetLevel() >= 10)) { - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate."); - Lever->CastToClient()->CastSpell(261, c->GetID(), 1, -1, -1); - } - else if (!zone->CanCastOutdoor()) - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors."); - else if (c->GetLevel() <= 10) - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 10 yet."); - break; - case WIZARD: - if((zone->CanCastOutdoor()) && (c->GetLevel() >= 22)) { - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate."); - Lever->CastToClient()->CastSpell(261, c->GetID(), 1, -1, -1); - } - else if (!zone->CanCastOutdoor()) - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors."); - else if (c->GetLevel() <= 22) - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 22 yet."); - break; - case ENCHANTER: - if((zone->CanCastOutdoor()) && (c->GetLevel() >= 15)) { - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "Casting Levitate."); - Lever->CastToClient()->CastSpell(261, c->GetID(), 1, -1, -1); - } - else if (!zone->CanCastOutdoor()) - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I can't cast this spell indoors."); - else if (c->GetLevel() <= 15) - Lever->CastToBot()->BotGroupSay(Lever->CastToBot(), "I'm not level 15 yet."); - break; - default: - c->Message(15, "You must have a Druid, Shaman, Wizard, or Enchanter in your group."); - break; - } - } - } - - //Resists - if ((!strcasecmp(sep->arg[1], "resist")) && (c->IsGrouped())) { - Mob *Resister; - uint32 ResisterClass = 0; - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++){ - if(g->members[i] && g->members[i]->IsBot()) { - switch(g->members[i]->GetClass()) { - case CLERIC: - Resister = g->members[i]; - ResisterClass = CLERIC; - break; - case SHAMAN: - if(ResisterClass != CLERIC){ - Resister = g->members[i]; - ResisterClass = SHAMAN; - } - break; - case DRUID: - if (ResisterClass == 0){ - Resister = g->members[i]; - ResisterClass = DRUID; - } - break; - default: - break; - } - } - } - switch(ResisterClass) { - case CLERIC: - if(!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 6)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Poison protection."); - Resister->CastToBot()->Bot_Command_Resist(1, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 11)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Disease protection."); - Resister->CastToBot()->Bot_Command_Resist(2, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "fire") && (c->GetLevel() >= 8)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Fire protection."); - Resister->CastToBot()->Bot_Command_Resist(3, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 13)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Cold protection."); - Resister->CastToBot()->Bot_Command_Resist(4, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 16)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Magic protection."); - Resister->CastToBot()->Bot_Command_Resist(5, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() <= 16) - || !strcasecmp(sep->arg[2], "cold") && (c->GetLevel() <= 13) - || !strcasecmp(sep->arg[2], "fire") && (c->GetLevel() <= 8) - || !strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 11) - || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 6)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I am not the required level yet."); - } else - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want %s, %s, %s, %s, or %s?", Resister->CastToBot()->CreateSayLink(c, "#bot resist poison", "Resist Poison").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist disease", "Resist Disease").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist magic", "Resist Magic").c_str()); - - break; - case SHAMAN: - if(!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 20)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Poison protection."); - Resister->CastToBot()->Bot_Command_Resist(12, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 8)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Disease protection."); - Resister->CastToBot()->Bot_Command_Resist(13, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "fire") && (c->GetLevel() >= 5)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Fire protection."); - Resister->CastToBot()->Bot_Command_Resist(14, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 1)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Cold protection."); - Resister->CastToBot()->Bot_Command_Resist(15, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 19)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Magic protection."); - Resister->CastToBot()->Bot_Command_Resist(16, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() <= 19) - || !strcasecmp(sep->arg[2], "cold") && (c->GetLevel() <= 1) - || !strcasecmp(sep->arg[2], "fire") && (c->GetLevel() <= 5) - || !strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 8) - || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 20)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I am not the required level yet."); - } else - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want %s, %s, %s, %s, or %s?", Resister->CastToBot()->CreateSayLink(c, "#bot resist poison", "Resist Poison").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist disease", "Resist Disease").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist magic", "Resist Magic").c_str()); - - break; - case DRUID: - if (!strcasecmp(sep->arg[2], "poison") && (c->GetLevel() >= 19)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Poison protection."); - Resister->CastToBot()->Bot_Command_Resist(7, Resister->GetLevel()); - } else if (!strcasecmp(sep->arg[2], "disease") && (c->GetLevel() >= 19)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Disease protection."); - Resister->CastToBot()->Bot_Command_Resist(8, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "fire")) { // Fire level 1 - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Fire protection."); - Resister->CastToBot()->Bot_Command_Resist(9, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "cold") && (c->GetLevel() >= 13)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Cold protection."); - Resister->CastToBot()->Bot_Command_Resist(10, Resister->GetLevel()); - } else if(!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() >= 16)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Casting Magic protection."); - Resister->CastToBot()->Bot_Command_Resist(11, Resister->GetLevel()); - } else if (!strcasecmp(sep->arg[2], "magic") && (c->GetLevel() <= 16) - || !strcasecmp(sep->arg[2], "cold") && (c->GetLevel() <= 9) - || !strcasecmp(sep->arg[2], "disease") && (c->GetLevel() <= 19) - || !strcasecmp(sep->arg[2], "poison") && (c->GetLevel() <= 19)) { - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "I am not the required level yet.") ; - } else - Resister->CastToBot()->BotGroupSay(Resister->CastToBot(), "Do you want %s, %s, %s, %s, or %s?", Resister->CastToBot()->CreateSayLink(c, "#bot resist poison", "Resist Poison").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist disease", "Resist Disease").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist fire", "Resist Fire").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist cold", "Resist Cold").c_str(), Resister->CastToBot()->CreateSayLink(c, "#bot resist magic", "Resist Magic").c_str()); - break; - default: - c->Message(15, "You must have a Cleric, Shaman, or Druid in your group."); - break; - } - } - } - - // #bot group ... - if(!strcasecmp(sep->arg[1], "group") && !strcasecmp(sep->arg[2], "help")) { - c->Message(0, "#bot group help - will show this help."); - c->Message(0, "#bot group summon . Summons the bot group to your location."); - c->Message(0, "#bot group follow "); - c->Message(0, "#bot group guard "); - c->Message(0, "#bot group attack "); - return; - } - - if(!strcasecmp(sep->arg[1], "group")) { - if(!strcasecmp(sep->arg[2], "follow")) { - if(c->IsGrouped()) - BotGroupOrderFollow(c->GetGroup(), c); - } else if(!strcasecmp(sep->arg[2], "guard")) { - if(c->IsGrouped()) - BotGroupOrderGuard(c->GetGroup(), c); - } else if(!strcasecmp(sep->arg[2], "attack")) { - if(c->IsGrouped() && (c->GetTarget() != nullptr) && c->IsAttackAllowed(c->GetTarget())) - BotGroupOrderAttack(c->GetGroup(), c->GetTarget(), c); - else - c->Message(15, "You must target a monster."); - } else if(!strcasecmp(sep->arg[2], "summon")) { - if(c->IsGrouped()) - BotGroupSummon(c->GetGroup(), c); - } - return; - } - - // #bot botgroup ... - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "help")) { - c->Message(0, "#bot botgroup help - will show this help."); - c->Message(0, "#bot botgroup create . This will designate a bot to be a bot group leader."); - c->Message(0, "#bot botgroup add "); - c->Message(0, "#bot botgroup remove "); - c->Message(0, "#bot botgroup disband . Disbands the designated bot group leader's bot group."); - c->Message(0, "#bot botgroup summon . Summons the bot group to your location."); - c->Message(0, "#bot botgroup follow "); - c->Message(0, "#bot botgroup guard "); - c->Message(0, "#bot botgroup attack "); - c->Message(0, "#bot botgroup list"); - c->Message(0, "#bot botgroup load "); - c->Message(0, "#bot botgroup save "); - c->Message(0, "#bot botgroup delete "); - - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "create")) { - Mob* targetMob = c->GetTarget(); - std::string targetName = std::string(sep->arg[3]); - Bot* botGroupLeader = 0; - if(!targetName.empty()) - botGroupLeader = entity_list.GetBotByBotName(targetName); - else if(targetMob) { - if(targetMob->IsBot()) - botGroupLeader = targetMob->CastToBot(); - } - - if(botGroupLeader) { - if(Bot::BotGroupCreate(botGroupLeader)) - botGroupLeader->BotGroupSay(botGroupLeader, "I am prepared to lead."); - else - botGroupLeader->BotGroupSay(botGroupLeader, "I cannot lead."); - } - else - c->Message(13, "You must target a spawned bot first."); - - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "add")) { - int argCount = 0; - argCount = sep->argnum; - std::string botGroupLeaderName; - std::string botGroupMemberName; - if(argCount >= 3) - botGroupMemberName = std::string(sep->arg[3]); - - Bot* botGroupMember = entity_list.GetBotByBotName(botGroupMemberName); - if(!botGroupMember) { - if(botGroupMemberName.empty()) - c->Message(13, "You must target a bot in this zone. Please try again."); - else - c->Message(13, "%s is not a bot in this zone. Please try again.", botGroupMemberName.c_str()); - - return; - } - - Bot* botGroupLeader = 0; - if(argCount == 4) { - botGroupLeaderName = std::string(sep->arg[4]); - botGroupLeader = entity_list.GetBotByBotName(botGroupLeaderName); - } else if(c->GetTarget() && c->GetTarget()->IsBot()) - botGroupLeader = c->GetTarget()->CastToBot(); - - if(!botGroupLeader) { - if(botGroupLeaderName.empty()) - c->Message(13, "You must target a bot in this zone. Please try again."); - else - c->Message(13, "%s is not a bot in this zone. Please try again.", botGroupLeaderName.c_str()); - - return; - } - - if(botGroupLeader->HasGroup()) { - Group* g = botGroupLeader->GetGroup(); - - if(g) { - if(g->IsLeader(botGroupLeader)) { - if(g->GroupCount() < MAX_GROUP_MEMBERS) { - if(!botGroupMemberName.empty() && botGroupMember) { - botGroupMember = entity_list.GetBotByBotName(botGroupMemberName); - } - - if(botGroupMember) { - if(!botGroupMember->HasGroup()) { - if(Bot::AddBotToGroup(botGroupMember, g)) { - database.SetGroupID(botGroupMember->GetName(), g->GetID(), botGroupMember->GetBotID()); - botGroupMember->BotGroupSay(botGroupMember, "I have joined %s\'s group.", botGroupLeader->GetName()); - } - else - botGroupMember->BotGroupSay(botGroupMember, "I can not join %s\'s group.", botGroupLeader->GetName()); - } else { - Group* tempGroup = botGroupMember->GetGroup(); - if(tempGroup) - botGroupMember->BotGroupSay(botGroupMember, "I can not join %s\'s group. I am already a member in %s\'s group.", botGroupLeader->GetName(), tempGroup->GetLeaderName()); - } - } - else - c->Message(13, "You must target a spawned bot first."); - } - else - botGroupLeader->BotGroupSay(botGroupMember, "I have no more openings in my group, %s.", c->GetName()); - } else { - Group* tempGroup = botGroupLeader->GetGroup(); - if(tempGroup) - botGroupLeader->BotGroupSay(botGroupLeader, "I can not lead anyone because I am a member in %s\'s group.", tempGroup->GetLeaderName()); - } - } - } - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "remove")) { - Mob* targetMob = c->GetTarget(); - std::string targetName = std::string(sep->arg[3]); - Bot* botGroupMember = 0; - - if(!targetName.empty()) - botGroupMember = entity_list.GetBotByBotName(targetName); - else if(targetMob) { - if(targetMob->IsBot()) - botGroupMember = targetMob->CastToBot(); - } - - if(botGroupMember) { - if(botGroupMember->HasGroup()) { - Group* g = botGroupMember->GetGroup(); - if(Bot::RemoveBotFromGroup(botGroupMember, g)) - botGroupMember->BotGroupSay(botGroupMember, "I am no longer in a group."); - else - botGroupMember->BotGroupSay(botGroupMember, "I can not leave %s\'s group.", g->GetLeaderName()); - } - else - botGroupMember->BotGroupSay(botGroupMember, "I am not in a group."); - } - else - c->Message(13, "You must target a spawned bot first."); - - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "disband")) { - Mob* targetMob = c->GetTarget(); - std::string targetName = std::string(sep->arg[3]); - Bot* botGroupLeader = 0; - if(!targetName.empty()) - botGroupLeader = entity_list.GetBotByBotName(targetName); - else if(targetMob) { - if(targetMob->IsBot()) - botGroupLeader = targetMob->CastToBot(); - } - - if(botGroupLeader) { - if(botGroupLeader->HasGroup()) { - Group* g = botGroupLeader->GetGroup(); - if(g->IsLeader(botGroupLeader)) { - if(Bot::RemoveBotFromGroup(botGroupLeader, g)) - botGroupLeader->BotGroupSay(botGroupLeader, "I have disbanded my group, %s.", c->GetName()); - else - botGroupLeader->BotGroupSay(botGroupLeader, "I was not able to disband my group, %s.", c->GetName()); - } - else - botGroupLeader->BotGroupSay(botGroupLeader, "I can not disband my group, %s, because I am not the leader. %s is the leader of my group.", c->GetName(), g->GetLeaderName()); - } else - botGroupLeader->BotGroupSay(botGroupLeader, "I am not a group leader, %s.", c->GetName()); - } else - c->Message(13, "You must target a spawned bot group leader first."); - - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "summon") ) { - Mob* targetMob = c->GetTarget(); - std::string targetName = std::string(sep->arg[3]); - Bot* botGroupLeader = 0; - - if(!targetName.empty()) - botGroupLeader = entity_list.GetBotByBotName(targetName); - else if(targetMob) { - if(targetMob->IsBot()) - botGroupLeader = targetMob->CastToBot(); - } - - if(botGroupLeader) { - if(botGroupLeader->HasGroup()) { - Group* g = botGroupLeader->GetGroup(); - if(g->IsLeader(botGroupLeader)) - BotGroupSummon(g, c); - } - } - else if(c->HasGroup()) - BotGroupSummon(c->GetGroup(), c); - - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "follow") ) { - Mob* targetMob = c->GetTarget(); - std::string targetName = std::string(sep->arg[3]); - Bot* botGroupLeader = 0; - if(!targetName.empty()) - botGroupLeader = entity_list.GetBotByBotName(targetName); - else if(targetMob) { - if(targetMob->IsBot()) - botGroupLeader = targetMob->CastToBot(); - } - - if(botGroupLeader) { - if(botGroupLeader->HasGroup()) { - Group* g = botGroupLeader->GetGroup(); - if(g->IsLeader(botGroupLeader)) - BotGroupOrderFollow(g, c); - } - } - else if(c->HasGroup()) - BotGroupOrderFollow(c->GetGroup(), c); - - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "guard") ) { - Mob* targetMob = c->GetTarget(); - std::string targetName = std::string(sep->arg[3]); - Bot* botGroupLeader = 0; - if(!targetName.empty()) - botGroupLeader = entity_list.GetBotByBotName(targetName); - else if(targetMob) { - if(targetMob->IsBot()) - botGroupLeader = targetMob->CastToBot(); - } - - if(botGroupLeader) { - if(botGroupLeader->HasGroup()) { - Group* g = botGroupLeader->GetGroup(); - if(g->IsLeader(botGroupLeader)) - BotGroupOrderGuard(g, c); - } - } - else if(c->HasGroup()) - BotGroupOrderGuard(c->GetGroup(), c); - - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "attack")) { - Mob* targetMob = c->GetTarget(); - Bot* botGroupLeader = 0; - std::string botGroupLeaderName = std::string(sep->arg[3]); - std::string targetName = std::string(sep->arg[4]); - if(!botGroupLeaderName.empty()) { - botGroupLeader = entity_list.GetBotByBotName(botGroupLeaderName); - if(botGroupLeader) { - if(!targetName.empty()) - targetMob = entity_list.GetMob(targetName.c_str()); - - if(targetMob) { - if(c->IsAttackAllowed(targetMob)) { - if(botGroupLeader->HasGroup()) { - Group* g = botGroupLeader->GetGroup(); - if(g) { - if(g->IsLeader(botGroupLeader)) - BotGroupOrderAttack(g, targetMob, c); - } - } - else if(c->HasGroup()) - BotGroupOrderAttack(c->GetGroup(), targetMob, c); - } - else - c->Message(13, "You must target a monster."); - } - else - c->Message(13, "You must target a monster."); - } - else - c->Message(13, "You must target a spawned bot group leader first."); - } - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "list")) { - std::list botGroupList = GetBotGroupListByBotOwnerCharacterId(c->CharacterID(), &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - if(!botGroupList.empty()) { - for(std::list::iterator botGroupListItr = botGroupList.begin(); botGroupListItr != botGroupList.end(); ++botGroupListItr) - c->Message(0, "Bot Group Name: %s -- Bot Group Leader: %s", botGroupListItr->BotGroupName.c_str(), botGroupListItr->BotGroupLeaderName.c_str()); - } - else - c->Message(0, "You have no bot groups created. Use the #bot botgroup save command to save bot groups."); - - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "load")) { - Group *g = c->GetGroup(); - if(g) { - for(int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(!g->members[i]) - continue; - - if((g->members[i]->IsClient() && g->members[i]->CastToClient()->GetAggroCount()) || g->members[i]->IsEngaged()) { - c->Message(0, "You can't spawn bots while your group is engaged."); - return; - } - } - } else { - if(c->GetAggroCount() > 0) { - c->Message(0, "You can't spawn bots while you are engaged."); - return; - } - } - - std::string botGroupName = std::string(sep->arg[3]); - if(botGroupName.empty()) { - c->Message(13, "Invalid botgroup name supplied."); - return; - } - - uint32 botGroupID = CanLoadBotGroup(c->CharacterID(), botGroupName, &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - if(botGroupID <= 0) { - c->Message(13, "Invalid botgroup id found."); - return; - } - - std::list botGroup = LoadBotGroup(botGroupName, &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - int spawnedBots = SpawnedBotCount(c->CharacterID(), &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - if(RuleB(Bots, QuestableSpawnLimit)) { - const int allowedBotsBQ = AllowedBotSpawns(c->CharacterID(), &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - if(allowedBotsBQ == 0) { - c->Message(0, "You can't spawn any bots."); - return; - } - - if(spawnedBots >= allowedBotsBQ || spawnedBots + (int)botGroup.size() > allowedBotsBQ) { - c->Message(0, "You can't spawn more than %i bot(s).", allowedBotsBQ); - return; - } - } - - const int allowedBotsSBC = RuleI(Bots, SpawnLimit); - if(spawnedBots >= allowedBotsSBC || spawnedBots + (int)botGroup.size() > allowedBotsSBC) { - c->Message(0, "You can't spawn more than %i bots.", allowedBotsSBC); - return; - } - - uint32 botGroupLeaderBotID = GetBotGroupLeaderIdByBotGroupName(botGroupName); - Bot *botGroupLeader = LoadBot(botGroupLeaderBotID, &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - safe_delete(botGroupLeader); - return; - } - if(!botGroupLeader) { - c->Message(13, "Failed to load botgroup leader."); - safe_delete(botGroupLeader); - return; - } - - botGroupLeader->Spawn(c, &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - safe_delete(botGroupLeader); - return; - } - - if(!BotGroupCreate(botGroupLeader)) { - c->Message(13, "Unable to create botgroup."); - return; - } - - Group *newBotGroup = botGroupLeader->GetGroup(); - if(!newBotGroup) { - c->Message(13, "Unable to find valid botgroup"); - return; - } - - for(auto botGroupItr = botGroup.begin(); botGroupItr != botGroup.end(); ++botGroupItr) { - if(botGroupItr->BotID == botGroupLeader->GetBotID()) - continue; - - Bot *botGroupMember = LoadBot(botGroupItr->BotID, &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - safe_delete(botGroupMember); - return; - } - - if(!botGroupMember) { - safe_delete(botGroupMember); - continue; - } - - botGroupMember->Spawn(c, &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - safe_delete(botGroupMember); - return; - } - - AddBotToGroup(botGroupMember, newBotGroup); - } - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "delete")) { - std::string botGroupName = std::string(sep->arg[3]); - if(!botGroupName.empty()) { - uint32 botGroupId = CanLoadBotGroup(c->CharacterID(), botGroupName, &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - - if(botGroupId > 0) { - DeleteBotGroup(botGroupName, &TempErrorMessage); - if(!TempErrorMessage.empty()) { - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - } - } - return; - } - - if(!strcasecmp(sep->arg[1], "botgroup") && !strcasecmp(sep->arg[2], "save")) { - std::string botGroupName = std::string(sep->arg[3]); - if(!botGroupName.empty()) { - if(!DoesBotGroupNameExist(botGroupName)) { - Bot* groupLeader = 0; - if(c->GetTarget() && c->GetTarget()->IsBot()) - groupLeader = c->GetTarget()->CastToBot(); - else - groupLeader = entity_list.GetBotByBotName(std::string(sep->arg[4])); - - if(groupLeader) { - if(groupLeader->HasGroup() && groupLeader->GetGroup()->IsLeader(groupLeader)) { - SaveBotGroup(groupLeader->GetGroup(), botGroupName, &TempErrorMessage); - if(!TempErrorMessage.empty()) - c->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - else - c->Message(0, "%s's bot group has been saved as %s.", groupLeader->GetName(), botGroupName.c_str()); - } - else - c->Message(0, "You must target a bot group leader only."); - } - else - c->Message(0, "You must target a bot that is in the same zone as you."); - } - else - c->Message(0, "The bot group name already exists. Please choose another name to save your bot group as."); - } - return; - } - - if(!strcasecmp(sep->arg[1], "haircolor") || !strcasecmp(sep->arg[1], "hair") || !strcasecmp(sep->arg[1], "beard") || !strcasecmp(sep->arg[1], "beardcolor") || !strcasecmp(sep->arg[1], "face") - || !strcasecmp(sep->arg[1], "eyes") || !strcasecmp(sep->arg[1], "heritage") || !strcasecmp(sep->arg[1], "tattoo") || !strcasecmp(sep->arg[1], "details")) { - if(c->GetTarget() && c->GetTarget()->IsBot()) { - if (sep->IsNumber(2)) { - if (c->GetTarget()->CastToBot()->GetBotOwnerCharacterID() == c->CharacterID()) { - Bot *target = c->GetTarget()->CastToBot(); - uint16 Race = target->GetRace(); - uint8 Gender = target->GetGender(); - uint8 Texture = 0xFF; - uint8 HelmTexture = 0xFF; - uint8 HairStyle = target->GetHairStyle(); - uint8 HairColor = target->GetHairColor(); - uint8 BeardColor = target->GetBeardColor(); - uint8 EyeColor1 = target->GetEyeColor1(); - uint8 EyeColor2 = target->GetEyeColor2(); - uint8 LuclinFace = target->GetLuclinFace(); - uint8 Beard = target->GetBeard(); - uint32 DrakkinHeritage = target->GetDrakkinHeritage(); - uint32 DrakkinTattoo = target->GetDrakkinTattoo(); - uint32 DrakkinDetails = target->GetDrakkinDetails(); - float Size = target->GetSize(); - if (!strcasecmp(sep->arg[1], "hair")) - HairStyle = atoi(sep->arg[2]); - - if (!strcasecmp(sep->arg[1], "haircolor")) - HairColor = atoi(sep->arg[2]); - - if (!strcasecmp(sep->arg[1], "beard") || !strcasecmp(sep->arg[1], "beardcolor")) { - if (!Gender || Race == 8) { - if (!strcasecmp(sep->arg[1], "beard")) - Beard = atoi(sep->arg[2]); - - if (!strcasecmp(sep->arg[1], "beardcolor")) - BeardColor = atoi(sep->arg[2]); - } else { - c->Message(0, "Must be a male bot, or dwarf."); - return; - } - } - - if (!strcasecmp(sep->arg[1], "face")) - LuclinFace = atoi(sep->arg[2]); - - if (!strcasecmp(sep->arg[1], "eyes")) { - EyeColor1 = EyeColor2 = atoi(sep->arg[2]); - c->Message(0, "Eye Values = 0 - 11"); - } - - if(!strcasecmp(sep->arg[1], "heritage") || !strcasecmp(sep->arg[1], "tattoo") || !strcasecmp(sep->arg[1], "details")) { - if(Race == 522) { - if(!strcasecmp(sep->arg[1], "heritage")) { - DrakkinHeritage = atoi(sep->arg[2]); - c->Message(0, "Heritage Values = 0 - 6"); - } - - if(!strcasecmp(sep->arg[1], "tattoo")) { - DrakkinTattoo = atoi(sep->arg[2]); - c->Message(0, "Tattoo Values = 0 - 7"); - } - - if(!strcasecmp(sep->arg[1], "details")) { - DrakkinDetails = atoi(sep->arg[2]); - c->Message(0, "Details Values = 0 - 7"); - } - } else { - c->Message(0, "Drakkin only."); - return; - } - } - - target->SendIllusionPacket(Race, Gender, Texture, HelmTexture, HairColor, BeardColor, EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF, DrakkinHeritage, DrakkinTattoo, DrakkinDetails, Size); - if(target->CastToBot()->Save()) - c->Message(0, "%s saved.", target->GetCleanName()); - else - c->Message(13, "%s save failed!", target->GetCleanName()); - - c->Message(0, "Feature changed."); - } - else - c->Message(0, "You must own the bot to make changes."); - } - else - c->Message(0, "Requires a value."); - } - else - c->Message(0, "A bot needs to be targeted."); - return; - } - - if(!strcasecmp(sep->arg[1], "taunt")) { - bool taunt = false; - bool toggle = false; - - if(sep->arg[2]){ - if(!strcasecmp(sep->arg[2], "on")) - taunt = true; - else if (!strcasecmp(sep->arg[2], "off")) - taunt = false; - else { - c->Message(0, "Usage #bot taunt [on|off]"); - return; - } - - Bot *targetedBot = nullptr; - if(c->GetTarget() != nullptr) { - if (c->GetTarget()->IsBot() && (c->GetTarget()->CastToBot()->GetBotOwner() == c)) - targetedBot = c->GetTarget()->CastToBot(); - else - c->Message(13, "You must target a bot that you own."); - - if(targetedBot) { - if(targetedBot->GetSkill(SkillTaunt) > 0) { - if(toggle) - taunt = !targetedBot->taunting; - - if(taunt) { - if(!targetedBot->taunting) - targetedBot->BotGroupSay(targetedBot, "I am now taunting."); - } else { - if(targetedBot->taunting) - targetedBot->BotGroupSay(targetedBot, "I am no longer taunting."); - } - - targetedBot->SetTaunting(taunt); - } - else - c->Message(13, "You must select a bot with the taunt skill."); - } - else - c->Message(13, "You must target a spawned bot."); - } - } - else - c->Message(0, "Usage #bot taunt [on|off]"); - - return; - } - - if(!strcasecmp(sep->arg[1], "stance")) { - if(sep->argnum == 3){ - Bot* tempBot = nullptr; - std::string botName = std::string(sep->arg[2]); - if(!botName.empty()) - tempBot = entity_list.GetBotByBotName(botName); - else - c->Message(13, "You must name a valid bot."); - - if(tempBot) { - std::string stanceName; - BotStanceType botStance; - if (tempBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - if(!strcasecmp(sep->arg[3], "list")) - botStance = tempBot->GetBotStance(); - else { - int stance = atoi(sep->arg[3]); - if(stance >= MaxStances || stance < 0){ - c->Message(0, "Usage #bot stance [name] [stance (id)] (Passive = 0, Balanced = 1, Efficient = 2, Reactive = 3, Aggressive = 4, Burn = 5, BurnAE = 6)"); - return; - } else { - botStance = (BotStanceType)stance; - if(botStance != tempBot->GetBotStance()) { - tempBot->SetBotStance(botStance); - tempBot->CalcChanceToCast(); - tempBot->Save(); - } - } - } - - switch(botStance) { - case BotStancePassive: { - stanceName = "Passive"; - break; - } - case BotStanceBalanced: { - stanceName = "Balanced"; - break; - } - case BotStanceEfficient: { - stanceName = "Efficient"; - break; - } - case BotStanceReactive: { - stanceName = "Reactive"; - break; - } - case BotStanceAggressive: { - stanceName = "Aggressive"; - break; - } - case BotStanceBurn: { - stanceName = "Burn"; - break; - } - case BotStanceBurnAE: { - stanceName = "BurnAE"; - break; - } - default: { - stanceName = "None"; - break; - } - } - c->Message(0, "Stance for %s: %s.", tempBot->GetCleanName(), stanceName.c_str()); - } - else - c->Message(13, "You must name a valid bot."); - } - else - c->Message(0, "Usage #bot stance [name] [stance (id)] (Passive = 0, Balanced = 1, Efficient = 2, Reactive = 3, Aggressive = 4, Burn = 5, BurnAE = 6)"); - - return; - } - - if(!strcasecmp(sep->arg[1], "defensive")) { - Bot* tempBot; - std::string botName = std::string(sep->arg[2]); - if(!botName.empty()) - tempBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid bot."); - return; - } - - if(tempBot) { - uint8 botlevel = tempBot->GetLevel(); - uint32 defensiveSpellID = 0; - if (tempBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - switch (tempBot->GetClass()) { - case WARRIOR: - if(botlevel >= 72) - defensiveSpellID = 10965; //Final Stand discipline - else if(botlevel >= 65) - defensiveSpellID = 4688; //Stonewall discipline - else if(botlevel >= 55) - defensiveSpellID = 4499; //Defensive discipline - else if(botlevel >= 52) - defensiveSpellID = 4503; //Evasive discipline - else - c->Message(0, "Warrior must be level 52 or higher."); - break; - case PALADIN: - if(botlevel >= 73) - defensiveSpellID = 11854; //Armor of Righteousness - else if(botlevel >= 69) - defensiveSpellID = 6663; //Guard of Righteousness - else if(botlevel >= 61) - defensiveSpellID = 6731; //Guard of Humility - else if(botlevel >= 56) - defensiveSpellID = 7004; //Guard of Piety - else - c->Message(0, "Paladin must be level 56 or higher."); - break; - case SHADOWKNIGHT: - if(botlevel >= 73) - defensiveSpellID = 11866; //Soul Carapace - else if(botlevel >= 69) - defensiveSpellID = 6673; //Soul shield - else if(botlevel >= 61) - defensiveSpellID = 6741; //Soul guard - else if(botlevel >= 56) - defensiveSpellID = 7005; //Ichor guard - else - c->Message(0, "Shadow Knight must be level 56 or higher."); - break; - default: - c->Message(0, "You must select a Warrior, Paladin, or Shadow Knight."); - break; - } - - if(defensiveSpellID > 0) - tempBot->UseDiscipline(defensiveSpellID, tempBot->GetID()); - } - else - c->Message(13, "You must name a valid bot."); - - return; - } - - // #bot healrotation ... - if(!strcasecmp(sep->arg[1], "healrotation")) { - if(!strcasecmp(sep->arg[2], "help")) { - c->Message(0, "#bot healrotation help - will show this help."); - c->Message(0, "#bot healrotation create [target]. This will create a heal rotation with the designated leader."); - c->Message(0, "#bot healrotation addmember "); - c->Message(0, "#bot healrotation removemember "); - c->Message(0, "#bot healrotation addtarget [bot healrotation target name to add] "); - c->Message(0, "#bot healrotation removetarget "); - c->Message(0, "#bot healrotation cleartargets "); - c->Message(0, "#bot healrotation fastheals "); - c->Message(0, "#bot healrotation start "); - c->Message(0, "#bot healrotation stop "); - c->Message(0, "#bot healrotation list "); - return; - } - - if(!strcasecmp(sep->arg[2], "create")) { - if(sep->argnum == 5 || sep->argnum == 6) { - Bot* leaderBot; - std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) - leaderBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid heal rotation leader."); - return; - } - - if(leaderBot) { - Mob* target = nullptr; - uint32 timer; - bool fastHeals = false; - if (!sep->IsNumber(4)) { - c->Message(0, "Usage #bot healrotation create [target]."); - return; - } - - timer = (uint32)(atof(sep->arg[4]) * 1000); - if (leaderBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - if (!(leaderBot->IsBotCaster() && leaderBot->CanHeal())) { - c->Message(13, "Heal rotation members must be able to heal."); - return; - } - - if(!strcasecmp(sep->arg[5], "fasthealson")) - fastHeals = true; - else if(strcasecmp(sep->arg[5], "fasthealsoff")) { - c->Message(0, "Usage #bot healrotation create [target]."); - return; - } - - if(!leaderBot->GetInHealRotation()) { - if(sep->argnum == 6) { - std::string targetName = std::string(sep->arg[6]); - if(!targetName.empty()) - target = entity_list.GetMob(targetName.c_str()); - else { - c->Message(13, "You must name a valid target."); - return; - } - - if(!target) { - c->Message(13, "You must name a valid target."); - return; - } - } - leaderBot->CreateHealRotation(target, timer); - leaderBot->SetHealRotationUseFastHeals(fastHeals); - c->Message(0, "Bot heal rotation created successfully."); - } else { - c->Message(13, "That bot is already in a heal rotation."); - return; - } - } else { - c->Message(13, "You must name a valid bot."); - return; - } - } else { - c->Message(0, "Usage #bot healrotation create [target]."); - return; - } - } - - if(!strcasecmp(sep->arg[2], "addmember")) { - if(sep->argnum == 4) { - Bot* leaderBot; - std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) - leaderBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid bot."); - return; - } - - if(leaderBot) { - Bot* healer; - std::string healerName = std::string(sep->arg[4]); - if (leaderBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - if(!healerName.empty()) - healer = entity_list.GetBotByBotName(healerName); - else { - c->Message(13, "You must name a valid bot."); - return; - } - - if(healer) { - if (healer->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - if (!(healer->IsBotCaster() && healer->CanHeal())) { - c->Message(13, "Heal rotation members must be able to heal."); - return; - } - - if(leaderBot->AddHealRotationMember(healer)) - c->Message(0, "Bot heal rotation member added successfully."); - else - c->Message(13, "Unable to add bot to rotation."); - } - } else { - c->Message(13, "You must name a valid bot."); - return; - } - } else { - c->Message(0, "#bot healrotation addmember "); - return; - } - } - - if(!strcasecmp(sep->arg[2], "removemember")) { - if(sep->argnum == 4) { - Bot* leaderBot; - std::string botName = std::string(sep->arg[3]); - - if(!botName.empty()) - leaderBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid bot."); - return; - } - - if(leaderBot) { - if (leaderBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - Bot* healer; - std::string healerName = std::string(sep->arg[4]); - if(!healerName.empty()) - healer = entity_list.GetBotByBotName(healerName); - else { - c->Message(13, "You must name a valid bot."); - return; - } - - if(healer) { - if (healer->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - if(leaderBot->RemoveHealRotationMember(healer)) - c->Message(0, "Bot heal rotation member removed successfully."); - else - c->Message(13, "Unable to remove bot from rotation."); - } else { - c->Message(13, "You must name a valid bot."); - return; - } - } else { - c->Message(13, "You must name a valid bot."); - return; - } - } else { - c->Message(0, "#bot healrotation removemember "); - return; - } - } - - if(!strcasecmp(sep->arg[2], "addtarget")) { - if(sep->argnum == 3 || sep->argnum == 4) { - Bot* leaderBot; - std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) - leaderBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid heal rotation leader."); - return; - } - - if(leaderBot) { - if (leaderBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - Mob* target = nullptr; - std::string targetName = std::string(sep->arg[4]); - if(!targetName.empty()) - target = entity_list.GetMob(targetName.c_str()); - else { - if(c->GetTarget() != nullptr) - target = c->GetTarget(); - } - - if(target) { - if(leaderBot->AddHealRotationTarget(target)) - c->Message(0, "Bot heal rotation target added successfully."); - else - c->Message(13, "Unable to add rotation target."); - } else { - c->Message(13, "Invalid target."); - return; - } - } else { - c->Message(13, "You must name a valid bot."); - return; - } - } else { - c->Message(0, "#bot healrotation addtarget [bot healrotation target name to add] "); - return; - } - } - - if(!strcasecmp(sep->arg[2], "removetarget")) { - if(sep->argnum == 4) { - Bot* leaderBot; - std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) - leaderBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid heal rotation leader."); - return; - } - - if(leaderBot) { - if (leaderBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - Mob* target; - std::string targetName = std::string(sep->arg[4]); - if(!targetName.empty()) - target = entity_list.GetMob(targetName.c_str()); - else { - c->Message(13, "You must name a valid target."); - return; - } - - if(target) { - if(leaderBot->RemoveHealRotationTarget(target)) - c->Message(0, "Bot heal rotation target removed successfully."); - else - c->Message(13, "Unable to remove rotation target."); - } - } else { - c->Message(13, "You must name a valid bot."); - return; - } - } else { - c->Message(0, "#bot healrotation removetarget "); - return; - } - } - - if(!strcasecmp(sep->arg[2], "start")) { - if(sep->argnum == 3) { - if(!strcasecmp(sep->arg[3], "all")) { - std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { - Bot* leaderBot = *botListItr; - if(leaderBot->GetInHealRotation() && leaderBot->GetHealRotationLeader() == leaderBot) { - std::list rotationMemberList; - int index = 0; - rotationMemberList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator rotationMemberItr = rotationMemberList.begin(); rotationMemberItr != rotationMemberList.end(); ++rotationMemberItr) { - Bot* tempBot = *rotationMemberItr; - if(tempBot) { - tempBot->SetHealRotationActive(true); - tempBot->SetHealRotationNextHealTime(Timer::GetCurrentTime() + index * leaderBot->GetHealRotationTimer() * 1000); - tempBot->SetHasHealedThisCycle(false); - } - index++; - } - c->Message(0, "Bot heal rotation started successfully."); - } - } - } else { - Bot* leaderBot; - std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) - leaderBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid heal rotation leader."); - return; - } - - if(leaderBot) { - std::list botList; - int index = 0; - if (leaderBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - botList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot) { - tempBot->SetHealRotationActive(true); - tempBot->SetHealRotationNextHealTime(Timer::GetCurrentTime() + index * leaderBot->GetHealRotationTimer() * 1000); - tempBot->SetHasHealedThisCycle(false); - } - index++; - } - c->Message(0, "Bot heal rotation started successfully."); - } else { - c->Message(13, "You must name a valid bot."); - return; - } - } - } else { - c->Message(0, "#bot healrotation start "); - return; - } - } - - if(!strcasecmp(sep->arg[2], "stop")) { - if(sep->argnum == 3) { - if(!strcasecmp(sep->arg[3], "all")) { - std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { - Bot* leaderBot = *botListItr; - if(leaderBot->GetInHealRotation() && leaderBot->GetHealRotationLeader() == leaderBot) { - std::list rotationMemberList; - rotationMemberList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator rotationMemberItr = rotationMemberList.begin(); rotationMemberItr != rotationMemberList.end(); ++rotationMemberItr) { - Bot* tempBot = *rotationMemberItr; - if(tempBot) { - tempBot->SetHealRotationActive(false); - tempBot->SetHasHealedThisCycle(false); - } - } - c->Message(0, "Bot heal rotation started successfully."); - } - } - } else { - Bot* leaderBot; - std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) - leaderBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid heal rotation leader."); - return; - } - - if(leaderBot) { - std::list botList; - if (leaderBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - botList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotOwnerCharacterID() == c->CharacterID()) { - tempBot->SetHealRotationActive(false); - tempBot->SetHasHealedThisCycle(false); - } - } - - c->Message(0, "Bot heal rotation stopped successfully."); - } else { - c->Message(13, "You must name a valid bot."); - return; - } - } - } else { - c->Message(0, "#bot healrotation stop "); - return; - } - } - - if(!strcasecmp(sep->arg[2], "list")) { - if(sep->argnum == 3) { - bool showAll = false; - Bot* leaderBot; - std::string botName = std::string(sep->arg[3]); - if(!strcasecmp(sep->arg[3], "all")) { - std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot->GetInHealRotation() && tempBot->GetHealRotationLeader() == tempBot) - c->Message(0, "Bot Heal Rotation- Leader: %s, Number of Members: %i, Timer: %1.1f", tempBot->GetCleanName(), tempBot->GetNumHealRotationMembers(), (float)(tempBot->GetHealRotationTimer()/1000)); - } - } else { - std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) - leaderBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid heal rotation leader."); - return; - } - - if(leaderBot) { - std::list botList; - if (leaderBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - botList = GetBotsInHealRotation(leaderBot); - c->Message(0, "Bot Heal Rotation- Leader: %s", leaderBot->GetCleanName()); - c->Message(0, "Bot Heal Rotation- Timer: %1.1f", ((float)leaderBot->GetHealRotationTimer()/1000.0f)); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotOwnerCharacterID() == c->CharacterID()) - c->Message(0, "Bot Heal Rotation- Member: %s", tempBot->GetCleanName()); - } - - for(int i = 0; i < MaxHealRotationTargets; i++) { - if(leaderBot->GetHealRotationTarget(i)) { - Mob* tempTarget = leaderBot->GetHealRotationTarget(i); - if(tempTarget) { - std::string targetInfo = ""; - targetInfo += tempTarget->GetHPRatio() < 0 ? "(dead) " : ""; - targetInfo += tempTarget->GetZoneID() != leaderBot->GetZoneID() ? "(not in zone) " : ""; - c->Message(0, "Bot Heal Rotation- Target: %s %s", tempTarget->GetCleanName(), targetInfo.c_str()); - } - } - } - } else { - c->Message(13, "You must name a valid bot."); - return; - } - } - } else { - c->Message(0, "#bot healrotation list "); - return; - } - } - - if(!strcasecmp(sep->arg[2], "cleartargets")) { - if(sep->argnum == 3) { - Bot* leaderBot; - std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) - leaderBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid heal rotation leader."); - return; - } - - if(leaderBot) { - std::list botList; - if (leaderBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - botList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotOwnerCharacterID() == c->CharacterID()) - tempBot->ClearHealRotationTargets(); - } - } else { - c->Message(13, "You must name a valid bot."); - return; - } - } else { - c->Message(0, "#bot healrotation cleartargets "); - return; - } - } - - if(!strcasecmp(sep->arg[2], "fastheals")) { - if(sep->argnum == 3) { - Bot* leaderBot; - std::string botName = std::string(sep->arg[3]); - if(!botName.empty()) - leaderBot = entity_list.GetBotByBotName(botName); - else { - c->Message(13, "You must name a valid heal rotation leader."); - return; - } - - if(leaderBot) { - bool fastHeals = false; - std::list botList; - if (leaderBot->GetBotOwner() != c) { - c->Message(13, "You must target a bot that you own."); - return; - } - - if(!strcasecmp(sep->arg[4], "on")) - fastHeals = true; - else if(strcasecmp(sep->arg[4], "off")) { - c->Message(0, "Usage #bot healrotation fastheals ."); - return; - } - - botList = GetBotsInHealRotation(leaderBot); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot && tempBot->GetBotOwnerCharacterID() == c->CharacterID()) - tempBot->SetHealRotationUseFastHeals(fastHeals); - } - } else { - c->Message(13, "You must name a valid bot."); - return; - } - } else { - c->Message(0, "#bot healrotation fastheals "); - return; - } - } - } - - if(!strcasecmp(sep->arg[1], "setinspectmessage")) { - if(!strcasecmp(sep->arg[2], "help")) { - c->Message(0, "[Titanium clients:]"); - c->Message(0, "- Self-inspect and type your bot's inspect message"); - c->Message(0, "- Close the self-inspect window"); - c->Message(0, "- Self-inspect again to update the server"); - c->Message(0, "- Target a bot that you own and wish to update"); - c->Message(0, "- type #bot setinspectmessage to set the bot's message"); - c->Message(0, "[Secrets of Faydwer and higher clients:]"); - c->Message(0, "- Self-inspect and type your bot's inspect message"); - c->Message(0, "- Close the self-inspect window to update the server"); - c->Message(0, "- Target a bot that you own and wish to update"); - c->Message(0, "- type #bot setinspectmessage to set the bot's message"); - } else { - Mob *target = c->GetTarget(); - if(target && target->IsBot() && (c == target->GetOwner()->CastToClient())) { - const InspectMessage_Struct& playermessage = c->GetInspectMessage(); - InspectMessage_Struct& botmessage = target->CastToBot()->GetInspectMessage(); - memcpy(&botmessage, &playermessage, sizeof(InspectMessage_Struct)); - database.SetBotInspectMessage(target->CastToBot()->GetBotID(), &botmessage); - c->Message(0, "Bot %s's inspect message now reflects your inspect message.", target->GetName()); - } else { - c->Message(0, "Your target must be a bot that you own."); - } - } - } - - if(!strcasecmp(sep->arg[1], "bardoutofcombat")) { - bool useOutOfCombatSongs = false; - if(sep->arg[2] && sep->arg[3]){ - if(!strcasecmp(sep->arg[2], "on")) - useOutOfCombatSongs = true; - else if (!strcasecmp(sep->arg[2], "off")) - useOutOfCombatSongs = false; - else { - c->Message(0, "Usage #bot bardoutofcombat [on|off]"); - return; - } - - Mob *target = c->GetTarget(); - if(target && target->IsBot() && (c == target->GetOwner()->CastToClient())) { - Bot* bardBot = target->CastToBot(); - if(bardBot) { - bardBot->SetBardUseOutOfCombatSongs(useOutOfCombatSongs); - c->Message(0, "Bard use of out of combat songs updated."); - } - } else - c->Message(0, "Your target must be a bot that you own."); - } else - c->Message(0, "Usage #bot bardoutofcombat [on|off]"); - return; - } - - if(!strcasecmp(sep->arg[1], "showhelm")) { - bool showhelm = true; - if (sep->arg[2]) { - if (!strcasecmp(sep->arg[2], "on")) - showhelm = true; - else if (!strcasecmp(sep->arg[2], "off")) - showhelm = false; - else { - c->Message(0, "Usage #bot showhelm [on|off]"); - return; - } - - Mob *target = c->GetTarget(); - if (target && target->IsBot() && (c == target->GetOwner()->CastToClient())) { - Bot* b = target->CastToBot(); - if (b) { - b->SetShowHelm(showhelm); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; - /* - [10-16-2015 :: 14:58:02] [Packet :: Client -> Server (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10] - 0: A4 02 [2B 00] 00 00 00 00 - showhelm = false - [10-16-2015 :: 14:57:56] [Packet :: Client -> Server (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10] - 0: A4 02 [2B 00] 01 00 00 00 - showhelm = true - */ - sa_out->spawn_id = b->GetID(); - sa_out->type = AT_ShowHelm; // value = 43 (0x002B) - sa_out->parameter = (showhelm ? 1 : 0); - entity_list.QueueClients(b, outapp, true); - safe_delete(outapp); - c->Message(0, "Your bot will %s show their helmet.", (showhelm ? "now" : "no longer")); - } - } - } else - c->Message(0, "Usage #bot showhelm [on|off]"); - - return; - } -} - bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint16 iSpellTypes) { if((iSpellTypes&SpellTypes_Detrimental) != 0) { Log.Out(Logs::General, Logs::Error, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!"); @@ -13044,37 +8848,6 @@ std::list EntityList::GetBotsByBotOwnerCharacterID(uint32 botOwnerCharacte return Result; } -void EntityList::BotPickLock(Bot* rogue) { - for (auto it = door_list.begin(); it != door_list.end(); ++it) { - Doors *cdoor = it->second; - if(!cdoor || cdoor->IsDoorOpen()) - continue; - - auto diff = (rogue->GetPosition() - cdoor->GetPosition()); - float curdist = ((diff.x * diff.x) + (diff.y * diff.y)); - if(((diff.z * diff.z) >= 10) || curdist > 130) - continue; - - const ItemInst* item1 = rogue->GetBotItem(MainHands); - const ItemInst* item2 = rogue->GetBotItem(MainPrimary); - float bonus1 = 0.0f; - float bonus2 = 0.0f; - float skill = rogue->GetSkill(SkillPickLock); - if(item1) - if(item1->GetItem()->SkillModType == SkillPickLock) - bonus1 = (skill * (((float)item1->GetItem()->SkillModValue) / 100.0f)); - - if(item2) - if(item2->GetItem()->SkillModType == SkillPickLock) - bonus2 = (skill * (((float)item2->GetItem()->SkillModValue) / 100.0f)); - - if((skill + bonus1 + bonus2) >= cdoor->GetLockpick()) - cdoor->ForceOpen(rogue); - else - rogue->BotGroupSay(rogue, "I am not skilled enough for this lock."); - } -} - bool EntityList::RemoveBot(uint16 entityID) { bool Result = false; if(entityID > 0) { @@ -13222,7 +8995,8 @@ uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { return needHealed; } -uint32 Bot::GetEquipmentColor(uint8 material_slot) const { +uint32 Bot::GetEquipmentColor(uint8 material_slot) const +{ int16 slotid = 0; uint32 botid = this->GetBotID(); slotid = Inventory::CalcSlotFromMaterial(material_slot); @@ -13460,288 +9234,213 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) { return true; } -void Bot::CreateHealRotation( Mob* target, uint32 timer ) { - SetInHealRotation(true); - SetHealRotationActive(false); - SetNumHealRotationMembers(GetNumHealRotationMembers()+1); - SetHealRotationLeader(this); - SetNextHealRotationMember(this); - SetPrevHealRotationMember(this); - SetHealRotationTimer(timer); - SetHasHealedThisCycle(false); - if(target) - AddHealRotationTarget(target); +// new healrotation code +bool Bot::CreateHealRotation(uint32 interval_ms, bool fast_heals, bool adaptive_targeting, bool casting_override) +{ + if (IsHealRotationMember()) + return false; + if (!HealRotation::IsMemberClass(GetClass())) + return false; + + m_member_of_heal_rotation = std::make_shared(this, interval_ms, fast_heals, adaptive_targeting, casting_override); + + return IsHealRotationMember(); } -bool Bot::AddHealRotationMember( Bot* healer ) { - if(healer) { - if(GetNumHealRotationMembers() > 0 && GetNumHealRotationMembers() < MaxHealRotationMembers) { - Bot* tempBot = GetPrevHealRotationMember(); - if(tempBot) { - for(int i = 0; i < 3; i++){ - healer->ClearHealRotationMembers(); - healer->ClearHealRotationTargets(); - healer->AddHealRotationTarget(entity_list.GetMob(_healRotationTargets[i])); - } - healer->SetHealRotationTimer(tempBot->GetHealRotationTimer()); - healer->SetHealRotationLeader(this); - healer->SetNextHealRotationMember(this); - healer->SetPrevHealRotationMember(tempBot); - healer->SetInHealRotation(true); - healer->SetHasHealedThisCycle(false); - healer->SetHealRotationUseFastHeals(tempBot->GetHealRotationUseFastHeals()); - tempBot->SetNextHealRotationMember(healer); - SetPrevHealRotationMember(healer); - std::list botList = GetBotsInHealRotation(this); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot) - tempBot->SetNumHealRotationMembers(GetNumHealRotationMembers()+1); - } - return true; - } - } - } - return false; +bool Bot::DestroyHealRotation() +{ + if (!IsHealRotationMember()) + return true; + + m_member_of_heal_rotation->ClearTargetPool(); + m_member_of_heal_rotation->ClearMemberPool(); + + return !IsHealRotationMember(); } -bool Bot::RemoveHealRotationMember( Bot* healer ) { - if(healer && GetNumHealRotationMembers() > 0) { - Bot* leader = healer->GetHealRotationLeader(); - Bot* prevBot = healer->GetPrevHealRotationMember(); - Bot* nextBot = healer->GetNextHealRotationMember(); - if(healer == this) { - if(nextBot != this) - leader = nextBot; - } +bool Bot::JoinHealRotationMemberPool(std::shared_ptr* heal_rotation) +{ + if (IsHealRotationMember()) + return false; + if (!heal_rotation->use_count()) + return false; + if (!(*heal_rotation)) + return false; + if (!HealRotation::IsMemberClass(GetClass())) + return false; - healer->SetHealRotationTimer(0); - healer->ClearHealRotationMembers(); - healer->ClearHealRotationTargets(); - healer->ClearHealRotationLeader(); - healer->SetHasHealedThisCycle(false); - healer->SetHealRotationActive(false); - healer->SetInHealRotation(false); - if(prevBot && nextBot && GetNumHealRotationMembers() > 1) { - prevBot->SetNextHealRotationMember(nextBot); - nextBot->SetPrevHealRotationMember(prevBot); - } + if (!(*heal_rotation)->AddMemberToPool(this)) + return false; - std::list botList = GetBotsInHealRotation(leader); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot) { - tempBot->SetNumHealRotationMembers(GetNumHealRotationMembers() - 1); - if(tempBot->GetHealRotationLeader() != leader) - tempBot->SetHealRotationLeader(leader); - } - } + m_member_of_heal_rotation = *heal_rotation; + + return true; +} + +bool Bot::LeaveHealRotationMemberPool() +{ + if (!IsHealRotationMember()) { + m_member_of_heal_rotation.reset(); return true; } - return false; + + m_member_of_heal_rotation->RemoveMemberFromPool(this); + m_member_of_heal_rotation.reset(); + + return !IsHealRotationMember(); } -void Bot::SetHealRotationLeader( Bot* leader ) { - _healRotationLeader = leader->GetBotID(); +bool Bot::UseHealRotationFastHeals() +{ + if (!IsHealRotationMember()) + return false; + + return m_member_of_heal_rotation->FastHeals(); } -void Bot::SetNextHealRotationMember( Bot* healer ) { - _healRotationMemberNext = healer->GetBotID(); +bool Bot::UseHealRotationAdaptiveTargeting() +{ + if (!IsHealRotationMember()) + return false; + + return m_member_of_heal_rotation->AdaptiveTargeting(); } -void Bot::SetPrevHealRotationMember( Bot* healer ) { - _healRotationMemberPrev = healer->GetBotID(); +bool Bot::IsHealRotationActive() +{ + if (!IsHealRotationMember()) + return false; + + return m_member_of_heal_rotation->IsActive(); } -Bot* Bot::GetHealRotationLeader( ) { - if(_healRotationLeader) - return entity_list.GetBotByBotID(_healRotationLeader); +bool Bot::IsHealRotationReady() +{ + if (!IsHealRotationMember()) + return false; - return 0; + return m_member_of_heal_rotation->CastingReady(); } -Bot* Bot::GetNextHealRotationMember( ) { - if(_healRotationMemberNext) - return entity_list.GetBotByBotID(_healRotationMemberNext); +bool Bot::IsHealRotationCaster() +{ + if (!IsHealRotationMember()) + return false; - return 0; + return (m_member_of_heal_rotation->CastingMember() == this); } -Bot* Bot::GetPrevHealRotationMember( ) { - if(_healRotationMemberNext) - return entity_list.GetBotByBotID(_healRotationMemberPrev); +bool Bot::HealRotationPokeTarget() +{ + if (!IsHealRotationMember()) + return false; - return 0; + return m_member_of_heal_rotation->PokeCastingTarget(); } -bool Bot::AddHealRotationTarget( Mob* target ) { - if(target) { - for (int i = 0; i < MaxHealRotationTargets; ++i) { - if(_healRotationTargets[i] > 0) { - Mob* tempTarget = entity_list.GetMob(_healRotationTargets[i]); - if(!tempTarget) { - _healRotationTargets[i] = 0; - } else if(!strcasecmp(tempTarget->GetCleanName(), target->GetCleanName())) { - if(tempTarget->GetID() != target->GetID()) - _healRotationTargets[i] = target->GetID(); +Mob* Bot::HealRotationTarget() +{ + if (!IsHealRotationMember()) + return nullptr; - return false; - } - } + return m_member_of_heal_rotation->CastingTarget(); +} - if (_healRotationTargets[i] == 0) { - std::list botList = GetBotsInHealRotation(this); - _healRotationTargets[i] = target->GetID(); - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot && tempBot != this) - tempBot->AddHealRotationTarget(target, i); - } - return true; - } +bool Bot::AdvanceHealRotation(bool use_interval) +{ + if (!IsHealRotationMember()) + return false; + + return m_member_of_heal_rotation->AdvanceRotation(use_interval); +} + +bool Bot::IsMyHealRotationSet() +{ + if (!IsHealRotationMember()) + return false; + if (!m_member_of_heal_rotation->IsActive()) + return false; + if (!m_member_of_heal_rotation->CastingReady()) + return false; + if (m_member_of_heal_rotation->CastingMember() != this) + return false; + if (!m_member_of_heal_rotation->PokeCastingTarget()) + return false; + + return true; +} + +bool Bot::AmICastingForHealRotation() +{ + if (!IsHealRotationMember()) + return false; + + return m_member_of_heal_rotation->MemberIsCasting(this); +} + +void Bot::SetMyCastingForHealRotation(bool flag) +{ + if (!IsHealRotationMember()) + return; + + m_member_of_heal_rotation->SetMemberIsCasting(this, flag); +} + +bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) +{ + if (all_flag) { + if (slot_id != INVALID_INDEX) + return false; + + for (uint8 i = 0; i < MaterialPrimary; ++i) { + uint8 inv_slot = Inventory::CalcSlotFromMaterial(i); + ItemInst* inst = m_inv.GetItem(inv_slot); + if (!inst) + continue; + + inst->SetColor(rgb); + SendWearChange(i); } } - return false; -} + else { + uint8 mat_slot = Inventory::CalcMaterialFromSlot(slot_id); + if (mat_slot == _MaterialInvalid || mat_slot >= MaterialPrimary) + return false; -bool Bot::AddHealRotationTarget( Mob *target, int index ) { - if (target && index < MaxHealRotationTargets) { - _healRotationTargets[index] = target->GetID(); - return true; + ItemInst* inst = m_inv.GetItem(slot_id); + if (!inst) + return false; + + inst->SetColor(rgb); + SendWearChange(mat_slot); } - return false; -} -bool Bot::RemoveHealRotationTarget( Mob* target ) { - int index = 0; - bool removed = false; - if(target) { - for(int i = 0; i < MaxHealRotationTargets; i++){ - if(_healRotationTargets[i] == target->GetID()) { - std::list botList = GetBotsInHealRotation(this); - _healRotationTargets[i] = 0; - index = i; - removed = true; - for(std::list::iterator botListItr = botList.begin(); botListItr != botList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot) - tempBot->RemoveHealRotationTarget(i); - } - } - } - } - return removed; -} + if (save_flag) { + std::string where_clause; + if (all_flag) + where_clause = StringFormat(" WHERE `slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u')", + MainHead, MainArms, MainWrist1, MainHands, MainChest, MainLegs, MainFeet); + else + where_clause = StringFormat(" WHERE `slot_id` = '%u'", slot_id); -bool Bot::RemoveHealRotationTarget( int index ) { - if(index >= 0) { - _healRotationTargets[index] = 0; - if(index < MaxHealRotationTargets) { - for(int i = index; i < MaxHealRotationTargets; i++){ - _healRotationTargets[i] = _healRotationTargets[i + 1]; - _healRotationTargets[i + 1] = 0; - } - return true; - } - } - return false; -} + std::string query = StringFormat( + "UPDATE `bot_inventories`" + " SET `inst_color` = '%u'" + " %s" + " AND `bot_id` = '%u'", + rgb, + where_clause.c_str(), + GetBotID() + ); -void Bot::ClearHealRotationMembers() { - _healRotationMemberPrev = 0; - _healRotationMemberNext = 0; -} - -void Bot::ClearHealRotationTargets() { - for(int i = 0; i < MaxHealRotationTargets; i++) { - _healRotationTargets[i] = 0; - } -} - -Mob* Bot::GetHealRotationTarget( ) { - Mob* tank = nullptr; - Mob* first = nullptr; - Mob* target = nullptr; - int removeIndex = 0; - int count = 0; - for(int i = 0; i < MaxHealRotationTargets; i++) { - if(_healRotationTargets[i] > 0) { - target = entity_list.GetMob(_healRotationTargets[i]); - if(target) { - if(target->GetZoneID() == GetZoneID() && !(target->GetAppearance() == eaDead && !(target->IsClient() && target->CastToClient()->GetFeigned()))) { - count++; - if(!first) - first = target; - - if(!tank) { - Group* g = target->GetGroup(); - if(g && !strcasecmp(g->GetMainTankName(), target->GetCleanName())) - tank = target; - } - } - } else { - if(removeIndex == 0) - removeIndex = i; - } + auto results = database.QueryDatabase(query); + if (!results.Success() && GetOwner() && GetOwner()->IsClient()) { + GetOwner()->CastToClient()->Message(15, "Failed to save dye armor changes for %s due to unknown cause", GetCleanName()); + return false; } } - if (removeIndex > 0) - RemoveHealRotationTarget(removeIndex); - - if(tank) - return tank; - - return first; -} - -Mob* Bot::GetHealRotationTarget( uint8 index ) { - Mob* target = nullptr; - if(_healRotationTargets[index] > 0) - target = entity_list.GetMob(_healRotationTargets[index]); - - return target; -} - -std::list Bot::GetBotsInHealRotation(Bot* rotationLeader) { - std::list Result; - if(rotationLeader != nullptr) { - Result.push_back(rotationLeader); - Bot* rotationMember = rotationLeader->GetNextHealRotationMember(); - while(rotationMember && rotationMember != rotationLeader) { - Result.push_back(rotationMember); - rotationMember = rotationMember->GetNextHealRotationMember(); - } - } - return Result; -} - -void Bot::NotifyNextHealRotationMember(bool notifyNow) { - uint32 nextHealTime = notifyNow ? Timer::GetCurrentTime() : Timer::GetCurrentTime() + GetHealRotationTimer(); - Bot* nextMember = GetNextHealRotationMember(); - if(nextMember && nextMember != this) { - nextMember->SetHealRotationNextHealTime(nextHealTime); - nextMember->SetHasHealedThisCycle(false); - } -} - -void Bot::BotHealRotationsClear(Client* c) { - if(c) { - std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); - for(std::list::iterator botListItr = BotList.begin(); botListItr != BotList.end(); ++botListItr) { - Bot* tempBot = *botListItr; - if(tempBot->GetInHealRotation()) { - tempBot->SetInHealRotation(false); - tempBot->SetHealRotationActive(false); - tempBot->SetHasHealedThisCycle(false); - tempBot->SetHealRotationTimer(0); - tempBot->ClearHealRotationMembers(); - tempBot->ClearHealRotationTargets(); - tempBot->SetNumHealRotationMembers(0); - tempBot->ClearHealRotationLeader(); - } - } - } + return true; } std::string Bot::CreateSayLink(Client* c, const char* message, const char* name) { diff --git a/zone/bot.h b/zone/bot.h index c35fd1f7b..89759cd91 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -1,3 +1,21 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #ifndef BOT_H #define BOT_H @@ -7,9 +25,11 @@ #include "mob.h" #include "client.h" #include "pets.h" +#include "heal_rotation.h" #include "groups.h" #include "corpse.h" #include "zonedb.h" +#include "bot_database.h" #include "string_ids.h" #include "../common/misc_functions.h" #include "../common/global_define.h" @@ -29,8 +49,6 @@ const int DisciplineReuseStart = MaxSpellTimer + 1; const int MaxTimer = MaxSpellTimer + MaxDisciplineTimer; const int MaxStances = 7; const int MaxSpellTypes = 16; -const int MaxHealRotationMembers = 6; -const int MaxHealRotationTargets = 3; enum BotStanceType { BotStancePassive, @@ -39,9 +57,58 @@ enum BotStanceType { BotStanceReactive, BotStanceAggressive, BotStanceBurn, - BotStanceBurnAE + BotStanceBurnAE, + BotStanceUnknown }; +#define BOT_STANCE_COUNT 8 +#define VALIDBOTSTANCE(x) ((x >= (int)BotStancePassive && x <= (int)BotStanceBurnAE) ? ((BotStanceType)x) : (BotStanceUnknown)) + +static const std::string bot_stance_name[BOT_STANCE_COUNT] = { + "Passive", // 0 + "Balanced", // 1 + "Efficient", // 2 + "Reactive", // 3 + "Aggressive", // 4 + "Burn", // 5 + "BurnAE", // 6 + "Unknown" // 7 +}; + +static const char* GetBotStanceName(int stance_id) { return bot_stance_name[VALIDBOTSTANCE(stance_id)].c_str(); } + +#define VALIDBOTEQUIPSLOT(x) ((x >= EmuConstants::EQUIPMENT_BEGIN && x <= EmuConstants::EQUIPMENT_END) ? (x) : ((x == MainPowerSource) ? (22) : (23))) + +static std::string bot_equip_slot_name[EmuConstants::EQUIPMENT_SIZE + 2] = +{ + "Charm", // MainCharm + "Left Ear", // MainEar1 + "Head", // MainHead + "Face", // MainFace + "Right Ear", // MainEar2 + "Neck", // MainNeck + "Shoulders", // MainShoulders + "Arms", // MainArms + "Back", // MainBack + "Left Wrist", // MainWrist1 + "Right Wrist", // MainWrist2 + "Range", // MainRange + "Hands", // MainHands + "Primary Hand", // MainPrimary + "Secondary Hand", // MainSecondary + "Left Finger", // MainFinger1 + "Right Finger", // MainFinger2 + "Chest", // MainChest + "Legs", // MainLegs + "Feet", // MainFeet + "Waist", // MainWaist + "Ammo", // MainAmmo + "Power Source", // 22 (MainPowerSource = 9999) + "Unknown" +}; + +static const char* GetBotEquipSlotName(int slot_id) { return bot_equip_slot_name[VALIDBOTEQUIPSLOT(slot_id)].c_str(); } + enum SpellTypeIndex { SpellType_NukeIndex, SpellType_HealIndex, @@ -110,7 +177,7 @@ public: BotRoleRaidHealer }; - enum EqExpansions { + enum EqExpansions { // expansions are off..EQ should be '0' ExpansionNone, ExpansionEQ, ExpansionRoK, @@ -156,8 +223,10 @@ public: // Class Methods bool IsValidRaceClassCombo(); + static bool IsValidRaceClassCombo(uint16 r, uint8 c); bool IsValidName(); - static bool IsBotNameAvailable(char *botName, std::string* errorMessage); + static bool IsValidName(std::string& name); + static bool IsBotNameAvailable(const char *botName, std::string* errorMessage); bool DeleteBot(std::string* errorMessage); void Spawn(Client* botCharacterOwner, std::string* errorMessage); virtual void SetLevel(uint8 in_level, bool command = false); @@ -230,18 +299,7 @@ public: bool HasOrMayGetAggro(); void SetDefaultBotStance(); void CalcChanceToCast(); - void CreateHealRotation( Mob* target, uint32 timer = 10000 ); - bool AddHealRotationMember( Bot* healer ); - bool RemoveHealRotationMember( Bot* healer ); - bool AddHealRotationTarget( Mob* target ); - //bool AddHealRotationTarget( const char *targetName, int index); - bool AddHealRotationTarget( Mob* target, int index); - bool RemoveHealRotationTarget( Mob* target ); - bool RemoveHealRotationTarget( int index); - void NotifyNextHealRotationMember( bool notifyNow = false ); - void ClearHealRotationLeader() { _healRotationLeader = 0; } - void ClearHealRotationMembers(); - void ClearHealRotationTargets(); + inline virtual int32 GetMaxStat(); inline virtual int32 GetMaxResist(); inline virtual int32 GetMaxSTR(); @@ -299,6 +357,9 @@ public: virtual bool AI_PursueCastCheck(); virtual bool AI_IdleCastCheck(); bool AIHealRotation(Mob* tar, bool useFastHeals); + bool GetPauseAI() { return _pauseAI; } + void SetPauseAI(bool pause_flag) { _pauseAI = pause_flag; } + // Mob AI Virtual Override Methods virtual void AI_Process(); @@ -322,15 +383,6 @@ public: virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction); virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0); - // Bot Action Command Methods - bool MesmerizeTarget(Mob* target); - bool Bot_Command_Resist(int resisttype, int level); - bool Bot_Command_DireTarget(int diretype, Mob *target); - bool Bot_Command_CharmTarget(int charmtype, Mob *target); - bool Bot_Command_CalmTarget(Mob *target); - bool Bot_Command_RezzTarget(Mob *target); - bool Bot_Command_Cure(int curetype, int level); - // Bot Equipment & Inventory Class Methods void BotTradeSwapItem(Client* client, int16 lootSlot, const ItemInst* inst, const ItemInst* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap = true); void BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true); @@ -339,20 +391,11 @@ public: uint32 GetEquipmentColor(uint8 material_slot) const; virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); } - // Static Class Methods - static void SaveBotGroup(Group* botGroup, std::string botGroupName, std::string* errorMessage); - static void DeleteBotGroup(std::string botGroupName, std::string* errorMessage); - static std::list LoadBotGroup(std::string botGroupName, std::string* errorMessage); - static uint32 CanLoadBotGroup(uint32 botOwnerCharacterId, std::string botGroupName, std::string* errorMessage); - static uint32 GetBotGroupIdByBotGroupName(std::string botGroupName, std::string* errorMessage); - static uint32 GetBotGroupLeaderIdByBotGroupName(std::string botGroupName); - static std::list GetBotGroupListByBotOwnerCharacterId(uint32 botOwnerCharacterId, std::string* errorMessage); - static bool DoesBotGroupNameExist(std::string botGroupName); + // Static Class Methods //static void DestroyBotRaidObjects(Client* client); // Can be removed after bot raids are dumped static uint32 GetBotIDByBotName(std::string botName); static Bot* LoadBot(uint32 botID, std::string* errorMessage); static std::list GetBotList(uint32 botOwnerCharacterID, std::string* errorMessage); - static void ProcessBotCommands(Client *c, const Seperator *sep); static std::list ListSpawnedBots(uint32 characterID, std::string* errorMessage); static uint32 SpawnedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage); static uint32 CreatedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage); @@ -363,15 +406,10 @@ public: static std::string ClassIdToString(uint16 classId); static std::string RaceIdToString(uint16 raceId); static bool IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined); - static void BotGroupOrderFollow(Group* group, Client* client); - static void BotGroupOrderGuard(Group* group, Client* client); - static void BotGroupOrderAttack(Group* group, Mob* target, Client* client); - static void BotGroupSummon(Group* group, Client* client); static Bot* GetBotByBotClientOwnerAndBotName(Client* c, std::string botName); static void ProcessBotGroupInvite(Client* c, std::string botName); static void ProcessBotGroupDisband(Client* c, std::string botName); static void BotOrderCampAll(Client* c); - static void BotHealRotationsClear( Client* c ); static void ProcessBotInspectionRequest(Bot* inspectedBot, Client* client); static std::list GetGroupedBotsByGroupId(uint32 groupId, std::string* errorMessage); static void LoadAndSpawnAllZonedBots(Client* botOwner); @@ -411,13 +449,10 @@ public: static BotSpell GetBestBotSpellForCure(Bot* botCaster, Mob* target); static BotSpell GetBestBotSpellForResistDebuff(Bot* botCaster, Mob* target); static NPCType CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender); - static std::list GetBotsInHealRotation( Bot* leader ); // Static Bot Group Methods static bool AddBotToGroup(Bot* bot, Group* group); static bool RemoveBotFromGroup(Bot* bot, Group* group); - static bool BotGroupCreate(std::string botGroupLeaderName); - static bool BotGroupCreate(Bot* botGroupLeader); static bool GroupHasClass(Group* group, uint8 classId); static bool GroupHasClericClass(Group* group) { return GroupHasClass(group, CLERIC); } static bool GroupHasDruidClass(Group* group) { return GroupHasClass(group, DRUID); } @@ -445,26 +480,38 @@ public: uint8 GetChanceToCastBySpellType(uint16 spellType); bool IsGroupPrimaryHealer(); bool IsGroupPrimarySlower(); - bool IsBotCaster() { return (GetClass() == CLERIC || GetClass() == DRUID || GetClass() == SHAMAN || GetClass() == NECROMANCER || GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == ENCHANTER); } - bool IsBotINTCaster() { return (GetClass() == NECROMANCER || GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == ENCHANTER); } - bool IsBotWISCaster() { return (GetClass() == CLERIC || GetClass() == DRUID || GetClass() == SHAMAN); } + bool IsBotCaster() { return IsCasterClass(GetClass()); } + bool IsBotINTCaster() { return IsINTCasterClass(GetClass()); } + bool IsBotWISCaster() { return IsWISCasterClass(GetClass()); } bool CanHeal(); int GetRawACNoShield(int &shield_ac); bool GetHasBeenSummoned() { return _hasBeenSummoned; } const glm::vec3 GetPreSummonLocation() const { return m_PreSummonLocation; } - bool GetInHealRotation() { return _isInHealRotation; } - bool GetHealRotationActive() { return (GetInHealRotation() && _isHealRotationActive); } - bool GetHealRotationUseFastHeals() { return _healRotationUseFastHeals; } - bool GetHasHealedThisCycle() { return _hasHealedThisCycle; } - Mob* GetHealRotationTarget(); - Mob* GetHealRotationTarget(uint8 index); - Bot* GetHealRotationLeader(); - Bot* GetNextHealRotationMember(); - Bot* GetPrevHealRotationMember(); - uint8 GetNumHealRotationMembers () { return _numHealRotationMembers; } - uint32 GetHealRotationNextHealTime() { return _healRotationNextHeal; } - uint32 GetHealRotationTimer () { return _healRotationTimer; } - bool GetBardUseOutOfCombatSongs() { return _bardUseOutOfCombatSongs;} + + // new heal rotation code + bool CreateHealRotation(uint32 cycle_duration_ms = 5000, bool fast_heals = false, bool adaptive_targeting = false, bool casting_override = false); + bool DestroyHealRotation(); + bool JoinHealRotationMemberPool(std::shared_ptr* heal_rotation); + bool LeaveHealRotationMemberPool(); + + bool IsHealRotationMember() { return (m_member_of_heal_rotation.use_count() && m_member_of_heal_rotation.get()); } + bool UseHealRotationFastHeals(); + bool UseHealRotationAdaptiveTargeting(); + + bool IsHealRotationActive(); + bool IsHealRotationReady(); + bool IsHealRotationCaster(); + bool HealRotationPokeTarget(); + Mob* HealRotationTarget(); + bool AdvanceHealRotation(bool use_interval = true); + + bool IsMyHealRotationSet(); + bool AmICastingForHealRotation(); + void SetMyCastingForHealRotation(bool flag = true); + + std::shared_ptr* MemberOfHealRotation() { return &m_member_of_heal_rotation; } + + bool GetAltOutOfCombatBehavior() { return _altoutofcombatbehavior;} bool GetShowHelm() { return _showhelm; } inline virtual int32 GetAC() const { return AC; } inline virtual int32 GetSTR() const { return STR; } @@ -532,34 +579,41 @@ public: // void SetBotOwnerCharacterID(uint32 botOwnerCharacterID) { _botOwnerCharacterID = botOwnerCharacterID; } void SetRangerAutoWeaponSelect(bool enable) { GetClass() == RANGER ? _rangerAutoWeaponSelect = enable : _rangerAutoWeaponSelect = false; } void SetBotRole(BotRoleType botRole) { _botRole = botRole; } - void SetBotStance(BotStanceType botStance) { _botStance = botStance; } + void SetBotStance(BotStanceType botStance) { _botStance = ((botStance != BotStanceUnknown) ? (botStance) : (BotStancePassive)); } void SetSpellRecastTimer(int timer_index, int32 recast_delay); void SetDisciplineRecastTimer(int timer_index, int32 recast_delay); void SetHasBeenSummoned(bool s); void SetPreSummonLocation(const glm::vec3& location) { m_PreSummonLocation = location; } - void SetInHealRotation( bool inRotation ) { _isInHealRotation = inRotation; } - void SetHealRotationActive( bool isActive ) { _isHealRotationActive = isActive; } - void SetHealRotationUseFastHeals( bool useFastHeals ) { _healRotationUseFastHeals = useFastHeals; } - void SetHasHealedThisCycle( bool hasHealed ) { _hasHealedThisCycle = hasHealed; } - void SetHealRotationLeader( Bot* leader ); - void SetNextHealRotationMember( Bot* healer ); - void SetPrevHealRotationMember( Bot* healer ); - void SetHealRotationNextHealTime( uint32 nextHealTime ) { _healRotationNextHeal = nextHealTime; } - void SetHealRotationTimer( uint32 timer ) { _healRotationTimer = timer; } - void SetNumHealRotationMembers( uint8 numMembers ) { _numHealRotationMembers = numMembers; } - void SetBardUseOutOfCombatSongs(bool useOutOfCombatSongs) { _bardUseOutOfCombatSongs = useOutOfCombatSongs;} + + void SetAltOutOfCombatBehavior(bool behavior_flag) { _altoutofcombatbehavior = behavior_flag;} void SetShowHelm(bool showhelm) { _showhelm = showhelm; } + void SetBeardColor(uint8 value) { beardcolor = value; } + void SetBeard(uint8 value) { beard = value; } + void SetEyeColor1(uint8 value) { eyecolor1 = value; } + void SetEyeColor2(uint8 value) { eyecolor2 = value; } + void SetLuclinFace(uint8 value) { luclinface = value; } + void SetHairColor(uint8 value) { haircolor = value; } + void SetHairStyle(uint8 value) { hairstyle = value; } + void SetDrakkinDetails(uint32 value) { drakkin_details = value; } + void SetDrakkinHeritage(uint32 value) { drakkin_heritage = value; } + void SetDrakkinTattoo(uint32 value) { drakkin_tattoo = value; } + bool DyeArmor(int16 slot_id, uint32 rgb, bool all_flag = false, bool save_flag = true); std::string CreateSayLink(Client* botOwner, const char* message, const char* name); // Class Destructors virtual ~Bot(); + // Publicized protected/private functions + virtual void BotRangedAttack(Mob* other); // protected + uint32 GetBotItemsCount(std::string* errorMessage); // private + void BotRemoveEquipItem(int slot); // private + void RemoveBotItemBySlot(uint32 slotID, std::string* errorMessage); // private + protected: virtual void PetAIProcess(); static NPCType FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack); virtual void BotMeditate(bool isSitting); - virtual void BotRangedAttack(Mob* other); virtual bool CheckBotDoubleAttack(bool Triple = false); virtual int32 GetBotFocusEffect(BotfocusType bottype, uint16 spell_id); virtual int32 CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus=false); @@ -607,22 +661,14 @@ private: bool _hasBeenSummoned; glm::vec3 m_PreSummonLocation; uint8 _spellCastingChances[MaxStances][MaxSpellTypes]; - bool _isInHealRotation; - bool _isHealRotationActive; - bool _healRotationUseFastHeals; - bool _hasHealedThisCycle; - uint32 _healRotationTimer; - uint32 _healRotationNextHeal; - //char _healRotationTargets[MaxHealRotationTargets][64]; - uint16 _healRotationTargets[MaxHealRotationTargets]; - uint32 _healRotationLeader; - uint32 _healRotationMemberNext; - uint32 _healRotationMemberPrev; - uint8 _numHealRotationMembers; + + std::shared_ptr m_member_of_heal_rotation; + std::map botAAs; InspectMessage_Struct _botInspectMessage; - bool _bardUseOutOfCombatSongs; + bool _altoutofcombatbehavior; bool _showhelm; + bool _pauseAI; // Private "base stats" Members int32 _baseMR; @@ -656,12 +702,9 @@ private: // Private "Inventory" Methods void GetBotItems(std::string* errorMessage, Inventory &inv); - void BotRemoveEquipItem(int slot); void BotAddEquipItem(int slot, uint32 id); uint32 GetBotItemBySlot(uint32 slotID); - void RemoveBotItemBySlot(uint32 slotID, std::string* errorMessage); void SetBotItemInSlot(uint32 slotID, uint32 itemID, const ItemInst* inst, std::string* errorMessage); - uint32 GetBotItemsCount(std::string* errorMessage); uint32 GetTotalPlayTime(); void SaveBuffs(); // Saves existing buffs to the database to persist zoning and camping void LoadBuffs(); // Retrieves saved buffs from the database on spawning diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp new file mode 100644 index 000000000..0c09c6f31 --- /dev/null +++ b/zone/bot_command.cpp @@ -0,0 +1,7312 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + + To add a new bot command 3 things must be done: + + 1. At the bottom of bot_command.h you must add a prototype for it. + 2. Add the function in this file. + 3. In the bot_command_init function you must add a call to bot_command_add + for your function. + + Notes: If you want an alias for your bot command, add an entry to the + `bot_command_settings` table in your database. The access level you + set with bot_command_add is the default setting if the bot command isn't + listed in the `bot_command_settings` db table. + +*/ + +#include +#include +#include +#include +#include +#include + +#ifdef _WINDOWS +#define strcasecmp _stricmp +#endif + +#include "../common/global_define.h" +#include "../common/eq_packet.h" +#include "../common/features.h" +#include "../common/guilds.h" +#include "../common/patches/patches.h" +#include "../common/ptimer.h" +#include "../common/rulesys.h" +#include "../common/serverinfo.h" +#include "../common/string_util.h" +#include "../common/eqemu_logsys.h" + + +#include "bot_command.h" +#include "bot_database.h" +#include "guild_mgr.h" +#include "map.h" +#include "doors.h" +#include "pathing.h" +#include "qglobals.h" +#include "queryserv.h" +#include "quest_parser_collection.h" +#include "string_ids.h" +#include "titles.h" +#include "water_map.h" +#include "worldserver.h" + +extern QueryServ* QServ; +extern WorldServer worldserver; +extern TaskManager *taskmanager; +void CatchSignal(int sig_num); + + +/* + * file-scope helper objects + */ +namespace +{ +//#define BCSTSPELLDUMP // only needed if you're adding/tailoring bot command spells and need a file dump + +#define m_message CC_WhiteSmoke +#define m_action CC_Yellow +#define m_note CC_Gray +#define m_usage CC_Cyan +#define m_fail CC_Red +#define m_unknown CC_Magenta + +#define HP_RATIO_DELTA 5.0f + + enum { EffectIDFirst = 1, EffectIDLast = 12 }; + +#define CLASSIDTOINDEX(x) ((x >= WARRIOR && x <= BERSERKER) ? (x - 1) : (0)) +#define EFFECTIDTOINDEX(x) ((x >= EffectIDFirst && x <= EffectIDLast) ? (x - 1) : (0)) +#define AILMENTIDTOINDEX(x) ((x >= BCEnum::AT_Blindness && x <= BCEnum::AT_Corruption) ? (x - 1) : (0)) +#define RESISTANCEIDTOINDEX(x) ((x >= BCEnum::RT_Fire && x <= BCEnum::RT_Corruption) ? (x - 1) : (0)) + + // ActionableTarget action_type +#define FRIENDLY true +#define ENEMY false +} + +bcst_map bot_command_spells; +bcst_required_bot_classes_map required_bots_map; +bcst_required_bot_classes_map_by_class required_bots_map_by_class; + + +class BCSpells +{ +public: + // + static void Load() { + bot_command_spells.clear(); + bcst_levels_map bot_levels_map; + + for (int i = BCEnum::SpellTypeFirst; i <= BCEnum::SpellTypeLast; ++i) { + bot_command_spells[static_cast(i)]; + bot_levels_map[static_cast(i)]; + } + + for (int spell_id = 2; spell_id < SPDAT_RECORDS; ++spell_id) { + if (spells[spell_id].player_1[0] == '\0') + continue; + if (spells[spell_id].targettype != ST_Target && spells[spell_id].CastRestriction != 0) // watch + continue; + + auto target_type = BCEnum::TT_None; + switch (spells[spell_id].targettype) { + case ST_GroupTeleport: + target_type = BCEnum::TT_GroupV1; + break; + case ST_AECaster: + // Disabled until bot code works correctly + //target_type = BCEnum::TT_AECaster; + break; + case ST_AEBard: + // Disabled until bot code works correctly + //target_type = BCEnum::TT_AEBard; + break; + case ST_Target: + switch (spells[spell_id].CastRestriction) { + case 0: + target_type = BCEnum::TT_Single; + break; + case 104: + target_type = BCEnum::TT_Animal; + break; + case 105: + target_type = BCEnum::TT_Plant; + break; + case 118: + target_type = BCEnum::TT_Summoned; + break; + case 120: + target_type = BCEnum::TT_Undead; + break; + default: + break; + } + break; + case ST_Self: + target_type = BCEnum::TT_Self; + break; + case ST_AETarget: + // Disabled until bot code works correctly + //target_type = BCEnum::TT_AETarget; + break; + case ST_Animal: + target_type = BCEnum::TT_Animal; + break; + case ST_Undead: + target_type = BCEnum::TT_Undead; + break; + case ST_Summoned: + target_type = BCEnum::TT_Summoned; + break; + case ST_Corpse: + target_type = BCEnum::TT_Corpse; + break; + case ST_Plant: + target_type = BCEnum::TT_Plant; + break; + case ST_Group: + target_type = BCEnum::TT_GroupV2; + break; + default: + break; + } + if (target_type == BCEnum::TT_None) + continue; + + uint8 class_levels[16] = { 0 }; + bool player_spell = false; + for (int class_type = WARRIOR; class_type <= BERSERKER; ++class_type) { + int class_index = CLASSIDTOINDEX(class_type); + if (spells[spell_id].classes[class_index] == 0 || spells[spell_id].classes[class_index] > HARD_LEVEL_CAP) + continue; + + class_levels[class_index] = spells[spell_id].classes[class_index]; + player_spell = true; + } + if (!player_spell) + continue; + + STBaseEntry* entry_prototype = nullptr; + while (true) { + switch (spells[spell_id].effectid[EFFECTIDTOINDEX(1)]) { + case SE_BindAffinity: + entry_prototype = new STBaseEntry(BCEnum::SpT_BindAffinity); + break; + case SE_Charm: + if (spells[spell_id].SpellAffectIndex != 12) + break; + entry_prototype = new STCharmEntry(); + if (spells[spell_id].ResistDiff <= -1000) + entry_prototype->SafeCastToCharm()->dire = true; + break; + case SE_Teleport: + entry_prototype = new STDepartEntry; + entry_prototype->SafeCastToDepart()->single = !BCSpells::IsGroupType(target_type); + break; + case SE_Succor: + if (!strcmp(spells[spell_id].teleport_zone, "same")) { + entry_prototype = new STEscapeEntry; + } + else { + entry_prototype = new STDepartEntry; + entry_prototype->SafeCastToDepart()->single = !BCSpells::IsGroupType(target_type); + } + break; + case SE_Translocate: + if (spells[spell_id].teleport_zone[0] == '\0') { + entry_prototype = new STSendHomeEntry(); + entry_prototype->SafeCastToSendHome()->group = BCSpells::IsGroupType(target_type); + } + else { + entry_prototype = new STDepartEntry; + entry_prototype->SafeCastToDepart()->single = !BCSpells::IsGroupType(target_type); + } + break; + case SE_ModelSize: + if (spells[spell_id].base[EFFECTIDTOINDEX(1)] > 100) { + entry_prototype = new STSizeEntry; + entry_prototype->SafeCastToSize()->size_type = BCEnum::SzT_Enlarge; + } + else if (spells[spell_id].base[EFFECTIDTOINDEX(1)] > 0 && spells[spell_id].base[EFFECTIDTOINDEX(1)] < 100) { + entry_prototype = new STSizeEntry; + entry_prototype->SafeCastToSize()->size_type = BCEnum::SzT_Reduce; + } + break; + case SE_Identify: + entry_prototype = new STBaseEntry(BCEnum::SpT_Identify); + break; + case SE_Invisibility: + if (spells[spell_id].SpellAffectIndex != 9) + break; + entry_prototype = new STInvisibilityEntry; + entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_Living; + break; + case SE_SeeInvis: + if (spells[spell_id].SpellAffectIndex != 5) + break; + entry_prototype = new STInvisibilityEntry; + entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_See; + break; + case SE_InvisVsUndead: + if (spells[spell_id].SpellAffectIndex != 9) + break; + entry_prototype = new STInvisibilityEntry; + entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_Undead; + break; + case SE_InvisVsAnimals: + if (spells[spell_id].SpellAffectIndex != 9) + break; + entry_prototype = new STInvisibilityEntry; + entry_prototype->SafeCastToInvisibility()->invis_type = BCEnum::IT_Animal; + break; + case SE_Mez: + if (spells[spell_id].SpellAffectIndex != 12) + break; + entry_prototype = new STBaseEntry(BCEnum::SpT_Mesmerize); + break; + case SE_Revive: + if (spells[spell_id].SpellAffectIndex != 1) + break; + entry_prototype = new STResurrectEntry(); + entry_prototype->SafeCastToResurrect()->aoe = BCSpells::IsCasterCentered(target_type); + break; + case SE_Rune: + if (spells[spell_id].SpellAffectIndex != 2) + break; + entry_prototype = new STBaseEntry(BCEnum::SpT_Rune); + break; + case SE_SummonCorpse: + entry_prototype = new STBaseEntry(BCEnum::SpT_SummonCorpse); + break; + case SE_WaterBreathing: + entry_prototype = new STBaseEntry(BCEnum::SpT_WaterBreathing); + break; + default: + break; + } + if (entry_prototype) + break; + + switch (spells[spell_id].effectid[EFFECTIDTOINDEX(2)]) { + case SE_Succor: + entry_prototype = new STEscapeEntry; + std::string is_lesser = spells[spell_id].name; + if (is_lesser.find("Lesser") != std::string::npos) + entry_prototype->SafeCastToEscape()->lesser = true; + break; + } + if (entry_prototype) + break; + + switch (spells[spell_id].effectid[EFFECTIDTOINDEX(3)]) { + case SE_Lull: + entry_prototype = new STBaseEntry(BCEnum::SpT_Lull); + break; + case SE_Levitate: // needs more criteria + entry_prototype = new STBaseEntry(BCEnum::SpT_Levitation); + break; + default: + break; + } + if (entry_prototype) + break; + + while (spells[spell_id].typedescnum == 27) { + if (!spells[spell_id].goodEffect) + break; + if (spells[spell_id].skill != SkillOffense && spells[spell_id].skill != SkillDefense) + break; + + entry_prototype = new STStanceEntry(); + if (spells[spell_id].skill == SkillOffense) + entry_prototype->SafeCastToStance()->stance_type = BCEnum::StT_Aggressive; + else + entry_prototype->SafeCastToStance()->stance_type = BCEnum::StT_Defensive; + + break; + } + if (entry_prototype) + break; + + switch (spells[spell_id].SpellAffectIndex) { + case 1: { + bool valid_spell = false; + entry_prototype = new STCureEntry; + + for (int i = EffectIDFirst; i <= EffectIDLast; ++i) { + int effect_index = EFFECTIDTOINDEX(i); + if (spells[spell_id].effectid[effect_index] != SE_Blind && spells[spell_id].base[effect_index] >= 0) + continue; + else if (spells[spell_id].effectid[effect_index] == SE_Blind && !spells[spell_id].goodEffect) + continue; + + switch (spells[spell_id].effectid[effect_index]) { + case SE_Blind: + entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX(BCEnum::AT_Blindness)] += spells[spell_id].base[effect_index]; + break; + case SE_DiseaseCounter: + entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX(BCEnum::AT_Disease)] += spells[spell_id].base[effect_index]; + break; + case SE_PoisonCounter: + entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX(BCEnum::AT_Poison)] += spells[spell_id].base[effect_index]; + break; + case SE_CurseCounter: + entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX(BCEnum::AT_Curse)] += spells[spell_id].base[effect_index]; + break; + case SE_CorruptionCounter: + entry_prototype->SafeCastToCure()->cure_value[AILMENTIDTOINDEX(BCEnum::AT_Corruption)] += spells[spell_id].base[effect_index]; + break; + default: + continue; + } + entry_prototype->SafeCastToCure()->cure_total += spells[spell_id].base[effect_index]; + valid_spell = true; + } + if (!valid_spell) { + safe_delete(entry_prototype); + entry_prototype = nullptr; + } + + break; + } + case 2: { + bool valid_spell = false; + entry_prototype = new STResistanceEntry; + + for (int i = EffectIDFirst; i <= EffectIDLast; ++i) { + int effect_index = EFFECTIDTOINDEX(i); + if (spells[spell_id].base[effect_index] <= 0) + continue; + + switch (spells[spell_id].effectid[effect_index]) { + case SE_ResistFire: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Fire)] += spells[spell_id].base[effect_index]; + break; + case SE_ResistCold: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Cold)] += spells[spell_id].base[effect_index]; + break; + case SE_ResistPoison: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Poison)] += spells[spell_id].base[effect_index]; + break; + case SE_ResistDisease: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Disease)] += spells[spell_id].base[effect_index]; + break; + case SE_ResistMagic: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Magic)] += spells[spell_id].base[effect_index]; + break; + case SE_ResistCorruption: + entry_prototype->SafeCastToResistance()->resist_value[RESISTANCEIDTOINDEX(BCEnum::RT_Corruption)] += spells[spell_id].base[effect_index]; + break; + default: + continue; + } + entry_prototype->SafeCastToResistance()->resist_total += spells[spell_id].base[effect_index]; + valid_spell = true; + } + if (!valid_spell) { + safe_delete(entry_prototype); + entry_prototype = nullptr; + } + + break; + } + case 7: + case 10: + if (spells[spell_id].effectdescnum != 65) + break; + entry_prototype = new STMovementSpeedEntry(); + entry_prototype->SafeCastToMovementSpeed()->group = BCSpells::IsGroupType(target_type); + break; + default: + break; + } + if (entry_prototype) + break; + + break; + } + if (!entry_prototype) + continue; + + if (target_type == BCEnum::TT_Self && (entry_prototype->BCST() != BCEnum::SpT_Stance && entry_prototype->BCST() != BCEnum::SpT_SummonCorpse)) { +#ifdef BCSTSPELLDUMP + Log.Out(Logs::General, Logs::Error, "DELETING entry_prototype (primary clause) - name: %s, target_type: %s, BCST: %s", + spells[spell_id].name, BCEnum::TargetTypeEnumToString(target_type).c_str(), BCEnum::SpellTypeEnumToString(entry_prototype->BCST()).c_str()); +#endif + safe_delete(entry_prototype); + continue; + } + if (entry_prototype->BCST() == BCEnum::SpT_Stance && target_type != BCEnum::TT_Self) { +#ifdef BCSTSPELLDUMP + Log.Out(Logs::General, Logs::Error, "DELETING entry_prototype (secondary clause) - name: %s, BCST: %s, target_type: %s", + spells[spell_id].name, BCEnum::SpellTypeEnumToString(entry_prototype->BCST()).c_str(), BCEnum::TargetTypeEnumToString(target_type).c_str()); +#endif + safe_delete(entry_prototype); + continue; + } + + assert(entry_prototype->BCST() != BCEnum::SpT_None); + + entry_prototype->spell_id = spell_id; + entry_prototype->target_type = target_type; + + bcst_levels& bot_levels = bot_levels_map[entry_prototype->BCST()]; + for (int class_type = WARRIOR; class_type <= BERSERKER; ++class_type) { + int class_index = CLASSIDTOINDEX(class_type); + if (!class_levels[class_index]) + continue; + + STBaseEntry* spell_entry = nullptr; + switch (entry_prototype->BCST()) { + case BCEnum::SpT_Charm: + if (entry_prototype->IsCharm()) + spell_entry = new STCharmEntry(entry_prototype->SafeCastToCharm()); + break; + case BCEnum::SpT_Cure: + if (entry_prototype->IsCure()) + spell_entry = new STCureEntry(entry_prototype->SafeCastToCure()); + break; + case BCEnum::SpT_Depart: + if (entry_prototype->IsDepart()) + spell_entry = new STDepartEntry(entry_prototype->SafeCastToDepart()); + break; + case BCEnum::SpT_Escape: + if (entry_prototype->IsEscape()) + spell_entry = new STEscapeEntry(entry_prototype->SafeCastToEscape()); + break; + case BCEnum::SpT_Invisibility: + if (entry_prototype->IsInvisibility()) + spell_entry = new STInvisibilityEntry(entry_prototype->SafeCastToInvisibility()); + break; + case BCEnum::SpT_MovementSpeed: + if (entry_prototype->IsMovementSpeed()) + spell_entry = new STMovementSpeedEntry(entry_prototype->SafeCastToMovementSpeed()); + break; + case BCEnum::SpT_Resistance: + if (entry_prototype->IsResistance()) + spell_entry = new STResistanceEntry(entry_prototype->SafeCastToResistance()); + break; + case BCEnum::SpT_Resurrect: + if (entry_prototype->IsResurrect()) + spell_entry = new STResurrectEntry(entry_prototype->SafeCastToResurrect()); + break; + case BCEnum::SpT_SendHome: + if (entry_prototype->IsSendHome()) + spell_entry = new STSendHomeEntry(entry_prototype->SafeCastToSendHome()); + break; + case BCEnum::SpT_Size: + if (entry_prototype->IsSize()) + spell_entry = new STSizeEntry(entry_prototype->SafeCastToSize()); + break; + case BCEnum::SpT_Stance: + if (entry_prototype->IsStance()) + spell_entry = new STStanceEntry(entry_prototype->SafeCastToStance()); + break; + default: + spell_entry = new STBaseEntry(entry_prototype); + break; + } + + assert(spell_entry); + + spell_entry->caster_class = class_type; + spell_entry->spell_level = class_levels[class_index]; + + bot_command_spells[spell_entry->BCST()].push_back(spell_entry); + + if (bot_levels.find(class_type) == bot_levels.end() || bot_levels[class_type] > class_levels[class_index]) + bot_levels[class_type] = class_levels[class_index]; + } + + delete(entry_prototype); + } + + remove_inactive(); + order_all(); + load_teleport_zone_names(); + build_strings(bot_levels_map); + status_report(); + +#ifdef BCSTSPELLDUMP + spell_dump(); +#endif + + } + + static void Unload() { + for (auto map_iter : bot_command_spells) { + if (map_iter.second.empty()) + continue; + for (auto list_iter : map_iter.second) + safe_delete(list_iter); + map_iter.second.clear(); + } + bot_command_spells.clear(); + required_bots_map.clear(); + required_bots_map_by_class.clear(); + } + + static bool IsCasterCentered(BCEnum::TType target_type) { + switch (target_type) { + case BCEnum::TT_AECaster: + case BCEnum::TT_AEBard: + return true; + default: + return false; + } + } + + static bool IsGroupType(BCEnum::TType target_type) { + switch (target_type) { + case BCEnum::TT_GroupV1: + case BCEnum::TT_GroupV2: + return true; + default: + return false; + } + } + +private: + static void remove_inactive() { + if (bot_command_spells.empty()) + return; + + for (auto map_iter = bot_command_spells.begin(); map_iter != bot_command_spells.end(); ++map_iter) { + if (map_iter->second.empty()) + continue; + + bcst_list* spells_list = &map_iter->second; + bcst_list* removed_spells_list = new bcst_list; + + spells_list->remove(nullptr); + spells_list->remove_if([removed_spells_list](STBaseEntry* l) { + if (l->spell_id < 2 || l->spell_id >= SPDAT_RECORDS || strlen(spells[l->spell_id].name) < 3) { + removed_spells_list->push_back(l); + return true; + } + else { + return false; + } + }); + + for (auto del_iter : *removed_spells_list) + safe_delete(del_iter); + removed_spells_list->clear(); + + if (RuleI(Bots, CommandSpellRank) == 1) { + spells_list->sort([](STBaseEntry* l, STBaseEntry* r) { + if (spells[l->spell_id].spellgroup < spells[r->spell_id].spellgroup) + return true; + if (spells[l->spell_id].spellgroup == spells[r->spell_id].spellgroup && l->caster_class < r->caster_class) + return true; + if (spells[l->spell_id].spellgroup == spells[r->spell_id].spellgroup && l->caster_class == r->caster_class && spells[l->spell_id].rank < spells[r->spell_id].rank) + return true; + + return false; + }); + spells_list->unique([removed_spells_list](STBaseEntry* l, STBaseEntry* r) { + std::string r_name = spells[r->spell_id].name; + if (spells[l->spell_id].spellgroup == spells[r->spell_id].spellgroup && l->caster_class == r->caster_class && spells[l->spell_id].rank < spells[r->spell_id].rank) { + removed_spells_list->push_back(r); + return true; + } + + return false; + }); + + for (auto del_iter : *removed_spells_list) + safe_delete(del_iter); + removed_spells_list->clear(); + } + + if (RuleI(Bots, CommandSpellRank) == 2) { + spells_list->remove_if([removed_spells_list](STBaseEntry* l) { + std::string l_name = spells[l->spell_id].name; + if (spells[l->spell_id].rank == 10) { + removed_spells_list->push_back(l); + return true; + } + if (l_name.find("III") == (l_name.size() - 3)) { + removed_spells_list->push_back(l); + return true; + } + if (l_name.find("III ") == (l_name.size() - 4)) { + removed_spells_list->push_back(l); + return true; + } + + return false; + }); + + for (auto del_iter : *removed_spells_list) + safe_delete(del_iter); + removed_spells_list->clear(); + } + + // needs rework + if (RuleI(Bots, CommandSpellRank) == 2 || RuleI(Bots, CommandSpellRank) == 3) { + spells_list->sort([](STBaseEntry* l, STBaseEntry* r) { + if (spells[l->spell_id].spellgroup < spells[r->spell_id].spellgroup) + return true; + if (spells[l->spell_id].spellgroup == spells[r->spell_id].spellgroup && l->caster_class < r->caster_class) + return true; + if (spells[l->spell_id].spellgroup == spells[r->spell_id].spellgroup && l->caster_class == r->caster_class && spells[l->spell_id].rank > spells[r->spell_id].rank) + return true; + + return false; + }); + spells_list->unique([removed_spells_list](STBaseEntry* l, STBaseEntry* r) { + std::string l_name = spells[l->spell_id].name; + if (spells[l->spell_id].spellgroup == spells[r->spell_id].spellgroup && l->caster_class == r->caster_class && spells[l->spell_id].rank > spells[r->spell_id].rank) { + removed_spells_list->push_back(r); + return true; + } + + return false; + }); + + for (auto del_iter : *removed_spells_list) + safe_delete(del_iter); + removed_spells_list->clear(); + } + + safe_delete(removed_spells_list); + } + } + + static void order_all() { + // Example of a macro'd lambda using anonymous property dereference: + // #define XXX(p) ([](const <_Ty>* l, const <_Ty>* r) { return (l->p < r->p); }) + + +#define LT_STBASE(l, r, p) (l->p < r->p) +#define LT_STCHARM(l, r, p) (l->SafeCastToCharm()->p < r->SafeCastToCharm()->p) +#define LT_STCURE(l, r, p) (l->SafeCastToCure()->p < r->SafeCastToCure()->p) +#define LT_STCURE_VAL_ID(l, r, p, ctid) (l->SafeCastToCure()->p[AILMENTIDTOINDEX(ctid)] < r->SafeCastToCure()->p[AILMENTIDTOINDEX(ctid)]) +#define LT_STDEPART(l, r, p) (l->SafeCastToDepart()->p < r->SafeCastToDepart()->p) +#define LT_STESCAPE(l, r, p) (l->SafeCastToEscape()->p < r->SafeCastToEscape()->p) +#define LT_STINVISIBILITY(l, r, p) (l->SafeCastToInvisibility()->p < r->SafeCastToInvisibility()->p) +#define LT_STRESISTANCE(l, r, p) (l->SafeCastToResistance()->p < r->SafeCastToResistance()->p) +#define LT_STRESISTANCE_VAL_ID(l, r, p, rtid) (l->SafeCastToResistance()->p[RESISTANCEIDTOINDEX(rtid)] < r->SafeCastToResistance()->p[RESISTANCEIDTOINDEX(rtid)) +#define LT_STSTANCE(l, r, p) (l->SafeCastToStance()->p < r->SafeCastToStance()->p) +#define LT_SPELLS(l, r, p) (spells[l->spell_id].p < spells[r->spell_id].p) +#define LT_SPELLS_EFFECT_ID(l, r, p, eid) (spells[l->spell_id].p[EFFECTIDTOINDEX(eid)] < spells[r->spell_id].p[EFFECTIDTOINDEX(eid)]) +#define LT_SPELLS_STR(l, r, s) (strcasecmp(spells[l->spell_id].s, spells[r->spell_id].s) < 0) + +#define EQ_STBASE(l, r, p) (l->p == r->p) +#define EQ_STCHARM(l, r, p) (l->SafeCastToCharm()->p == r->SafeCastToCharm()->p) +#define EQ_STCURE(l, r, p) (l->SafeCastToCure()->p == r->SafeCastToCure()->p) +#define EQ_STCURE_VAL_ID(l, r, p, ctid) (l->SafeCastToCure()->p[AILMENTIDTOINDEX(ctid)] == r->SafeCastToCure()->p[AILMENTIDTOINDEX(ctid)]) +#define EQ_STDEPART(l, r, p) (l->SafeCastToDepart()->p == r->SafeCastToDepart()->p) +#define EQ_STESCAPE(l, r, p) (l->SafeCastToEscape()->p == r->SafeCastToEscape()->p) +#define EQ_STINVISIBILITY(l, r, p) (l->SafeCastToInvisibility()->p == r->SafeCastToInvisibility()->p) +#define EQ_STRESISTANCE(l, r, p) (l->SafeCastToResistance()->p == r->SafeCastToResistance()->p) +#define EQ_STRESISTANCE_VAL_ID(l, r, p, rtid) (l->SafeCastToResistance()->p[RESISTANCEIDTOINDEX(rtid)] == r->SafeCastToResistance()->p[RESISTANCEIDTOINDEX(rtid)) +#define EQ_STSTANCE(l, r, p) (l->SafeCastToStance()->p == r->SafeCastToStance()->p) +#define EQ_SPELLS(l, r, p) (spells[l->spell_id].p == spells[r->spell_id].p) +#define EQ_SPELLS_EFFECT_ID(l, r, p, eid) (spells[l->spell_id].p[EFFECTIDTOINDEX(eid)] == spells[r->spell_id].p[EFFECTIDTOINDEX(eid)]) +#define EQ_SPELLS_STR(l, r, s) (strcasecmp(spells[l->spell_id].s, spells[r->spell_id].s) == 0) + +#define GT_STBASE(l, r, p) (l->p > r->p) +#define GT_STCHARM(l, r, p) (l->SafeCastToCharm()->p > r->SafeCastToCharm()->p) +#define GT_STCURE(l, r, p) (l->SafeCastToCure()->p > r->SafeCastToCure()->p) +#define GT_STCURE_VAL_ID(l, r, p, ctid) (l->SafeCastToCure()->p[AILMENTIDTOINDEX(ctid)] > r->SafeCastToCure()->p[AILMENTIDTOINDEX(ctid)]) +#define GT_STDEPART(l, r, p) (l->SafeCastToDepart()->p > r->SafeCastToDepart()->p) +#define GT_STESCAPE(l, r, p) (l->SafeCastToEscape()->p > r->SafeCastToEscape()->p) +#define GT_STINVISIBILITY(l, r, p) (l->SafeCastToInvisibility()->p > r->SafeCastToInvisibility()->p) +#define GT_STRESISTANCE(l, r, p) (l->SafeCastToResistance()->p > r->SafeCastToResistance()->p) +#define GT_STRESISTANCE_VAL_ID(l, r, p, rtid) (l->SafeCastToResistance()->p[RESISTANCEIDTOINDEX(rtid)] > r->SafeCastToResistance()->p[RESISTANCEIDTOINDEX(rtid)) +#define GT_STSTANCE(l, r, p) (l->SafeCastToStance()->p > r->SafeCastToStance()->p) +#define GT_SPELLS(l, r, p) (spells[l->spell_id].p > spells[r->spell_id].p) +#define GT_SPELLS_EFFECT_ID(l, r, p, eid) (spells[l->spell_id].p[EFFECTIDTOINDEX(eid)] > spells[r->spell_id].p[EFFECTIDTOINDEX(eid)]) +#define GT_SPELLS_STR(l, r, s) (strcasecmp(spells[l->spell_id].s, spells[r->spell_id].s) > 0) + + + for (auto map_iter = bot_command_spells.begin(); map_iter != bot_command_spells.end(); ++map_iter) { + if (map_iter->second.size() < 2) + continue; + + auto spell_type = map_iter->first; + bcst_list* spell_list = &map_iter->second; + switch (spell_type) { + case BCEnum::SpT_BindAffinity: + if (RuleB(Bots, PreferNoManaCommandSpells)) { + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_SPELLS(l, r, mana)) + return true; + if (EQ_SPELLS(l, r, mana) && LT_STBASE(l, r, target_type)) + return true; + if (EQ_SPELLS(l, r, mana) && EQ_STBASE(l, r, target_type) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_SPELLS(l, r, mana) && EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + } + else { + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_STBASE(l, r, target_type)) + return true; + if (EQ_STBASE(l, r, target_type) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + } + continue; + case BCEnum::SpT_Charm: + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_SPELLS(l, r, ResistDiff)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && LT_STBASE(l, r, target_type)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && EQ_STBASE(l, r, target_type) && GT_SPELLS_EFFECT_ID(l, r, max, 1)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, max, 1) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, max, 1) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_Cure: // per-use sorting in command handler + spell_list->sort([](STBaseEntry* l, STBaseEntry* r) { + if (l->spell_id < r->spell_id) + return true; + if (l->spell_id == r->spell_id && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_Depart: + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_STBASE(l, r, target_type)) + return true; + if (EQ_STBASE(l, r, target_type) && LT_STBASE(l, r, caster_class)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, caster_class) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, caster_class) && EQ_STBASE(l, r, spell_level) && LT_SPELLS_STR(l, r, name)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_Escape: + spell_list->sort([](STBaseEntry* l, STBaseEntry* r) { + if (LT_STESCAPE(l, r, lesser)) + return true; + if (EQ_STESCAPE(l, r, lesser) && LT_STBASE(l, r, target_type)) + return true; + if (EQ_STESCAPE(l, r, lesser) && EQ_STBASE(l, r, target_type) && GT_STBASE(l, r, spell_level)) + return true; + if (EQ_STESCAPE(l, r, lesser) && EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_Identify: +#ifdef PREFER_NO_MANA_COST_SPELLS + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_SPELLS(l, r, mana)) + return true; + if (EQ_SPELLS(l, r, mana) && LT_STBASE(l, r, target_type)) + return true; + if (EQ_SPELLS(l, r, mana) && EQ_STBASE(l, r, target_type) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_SPELLS(l, r, mana) && EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); +#else + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_STBASE(l, r, target_type)) + return true; + if (EQ_STBASE(l, r, target_type) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); +#endif + continue; + case BCEnum::SpT_Invisibility: + spell_list->sort([](STBaseEntry* l, STBaseEntry* r) { + if (LT_STINVISIBILITY(l, r, invis_type)) + return true; + if (EQ_STINVISIBILITY(l, r, invis_type) && LT_STBASE(l, r, target_type)) + return true; + if (EQ_STINVISIBILITY(l, r, invis_type) && EQ_STBASE(l, r, target_type) && GT_STBASE(l, r, spell_level)) + return true; + if (EQ_STINVISIBILITY(l, r, invis_type) && EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + return false; + }); + continue; + case BCEnum::SpT_Levitation: + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_STBASE(l, r, target_type)) + return true; + if (EQ_STBASE(l, r, target_type) && LT_SPELLS(l, r, zonetype)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS(l, r, zonetype) && GT_STBASE(l, r, spell_level)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS(l, r, zonetype) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_Lull: + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_SPELLS(l, r, ResistDiff)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && LT_STBASE(l, r, target_type)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && EQ_STBASE(l, r, target_type) && GT_SPELLS_EFFECT_ID(l, r, max, 3)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, max, 3) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, max, 3) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_Mesmerize: + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (GT_SPELLS(l, r, ResistDiff)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && LT_STBASE(l, r, target_type)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && EQ_STBASE(l, r, target_type) && GT_SPELLS_EFFECT_ID(l, r, max, 1)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, max, 1) && GT_STBASE(l, r, spell_level)) + return true; + if (EQ_SPELLS(l, r, ResistDiff) && EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, max, 1) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_MovementSpeed: + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_STBASE(l, r, target_type)) + return true; + if (EQ_STBASE(l, r, target_type) && GT_SPELLS_EFFECT_ID(l, r, base, 2)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, base, 2) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, base, 2) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_Resistance: // per-use sorting in command handler + spell_list->sort([](STBaseEntry* l, STBaseEntry* r) { + if (l->spell_id < r->spell_id) + return true; + if (l->spell_id == r->spell_id && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_Resurrect: + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (GT_SPELLS_EFFECT_ID(l, r, base, 1)) + return true; + if (EQ_SPELLS_EFFECT_ID(l, r, base, 1) && LT_STBASE(l, r, target_type)) + return true; + if (EQ_SPELLS_EFFECT_ID(l, r, base, 1) && EQ_STBASE(l, r, target_type) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_SPELLS_EFFECT_ID(l, r, base, 1) && EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_Rune: + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_STBASE(l, r, target_type)) + return true; + if (EQ_STBASE(l, r, target_type) && GT_SPELLS_EFFECT_ID(l, r, max, 1)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, max, 1) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, max, 1) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_SendHome: + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_STBASE(l, r, target_type)) + return true; + if (EQ_STBASE(l, r, target_type) && GT_STBASE(l, r, spell_level)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_Size: + spell_list->sort([](STBaseEntry* l, STBaseEntry* r) { + if (LT_STBASE(l, r, target_type)) + return true; + + auto l_size_type = l->SafeCastToSize()->size_type; + auto r_size_type = r->SafeCastToSize()->size_type; + if (l_size_type < r_size_type) + return true; + if (l_size_type == BCEnum::SzT_Enlarge && r_size_type == BCEnum::SzT_Enlarge) { + if (EQ_STBASE(l, r, target_type) && GT_SPELLS(l, r, base, 1)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS(l, r, base, 1) && GT_STBASE(l, r, spell_level)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS(l, r, base, 1) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + } + if (l_size_type == BCEnum::SzT_Reduce && r_size_type == BCEnum::SzT_Reduce) { + if (EQ_STBASE(l, r, target_type) && LT_SPELLS(l, r, base, 1)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS(l, r, base, 1) && GT_STBASE(l, r, spell_level)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS(l, r, base, 1) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + } + + return false; + }); + continue; + case BCEnum::SpT_Stance: + spell_list->sort([](STBaseEntry* l, STBaseEntry* r) { + if (LT_STSTANCE(l, r, stance_type)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_SummonCorpse: + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (GT_SPELLS_EFFECT_ID(l, r, base, 1)) + return true; + if (EQ_SPELLS_EFFECT_ID(l, r, base, 1) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_SPELLS_EFFECT_ID(l, r, base, 1) && EQ_STBASE(l, r, spell_level) && EQ_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + case BCEnum::SpT_WaterBreathing: + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_STBASE(l, r, target_type)) + return true; + if (EQ_STBASE(l, r, target_type) && GT_STBASE(l, r, spell_level)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; + + return false; + }); + continue; + default: + continue; + } + } + } + + static void load_teleport_zone_names() { + auto depart_list = &bot_command_spells[BCEnum::SpT_Depart]; + if (depart_list->empty()) + return; + + std::string query = "SELECT `short_name`, `long_name` FROM `zone` WHERE '' NOT IN (`short_name`, `long_name`)"; + auto results = database.QueryDatabase(query); + if (!results.Success()) { + Log.Out(Logs::General, Logs::Error, "load_teleport_zone_names() - Error in zone names query: %s", results.ErrorMessage().c_str()); + return; + } + + std::map zone_names; + for (auto row = results.begin(); row != results.end(); ++row) + zone_names[row[0]] = row[1]; + + for (auto list_iter = depart_list->begin(); list_iter != depart_list->end();) { + auto test_iter = zone_names.find(spells[(*list_iter)->spell_id].teleport_zone); + if (test_iter == zone_names.end()) { + list_iter = depart_list->erase(list_iter); + continue; + } + + (*list_iter)->SafeCastToDepart()->long_name = test_iter->second; + ++list_iter; + } + + } + + static void build_strings(bcst_levels_map& bot_levels_map) { + for (int i = BCEnum::SpellTypeFirst; i <= BCEnum::SpellTypeLast; ++i) + helper_bots_string(static_cast(i), bot_levels_map[static_cast(i)]); + } + + static void status_report() { + Log.Out(Logs::General, Logs::Commands, "load_bot_command_spells(): - 'RuleI(Bots, CommandSpellRank)' set to %i.", RuleI(Bots, CommandSpellRank)); + if (bot_command_spells.empty()) { + Log.Out(Logs::General, Logs::Error, "load_bot_command_spells() - 'bot_command_spells' is empty."); + return; + } + + for (int i = BCEnum::SpellTypeFirst; i <= BCEnum::SpellTypeLast; ++i) + Log.Out(Logs::General, Logs::Commands, "load_bot_command_spells(): - '%s' returned %u spell entries.", + BCEnum::SpellTypeEnumToString(static_cast(i)).c_str(), bot_command_spells[static_cast(i)].size()); + } + + static void helper_bots_string(BCEnum::SpType type_index, bcst_levels& bot_levels) { + for (int i = WARRIOR; i <= BERSERKER; ++i) + required_bots_map_by_class[type_index][i] = "Unavailable..."; + + if (bot_levels.empty()) { + required_bots_map[type_index] = "This command is currently unavailable..."; + return; + } + + required_bots_map[type_index] = ""; + + auto map_size = bot_levels.size(); + while (bot_levels.size()) { + bcst_levels::iterator test_iter = bot_levels.begin(); + for (bcst_levels::iterator levels_iter = bot_levels.begin(); levels_iter != bot_levels.end(); ++levels_iter) { + if (levels_iter->second < test_iter->second) + test_iter = levels_iter; + if (strcasecmp(Bot::ClassIdToString(levels_iter->first).c_str(), Bot::ClassIdToString(test_iter->first).c_str()) < 0 && levels_iter->second <= test_iter->second) + test_iter = levels_iter; + } + + std::string bot_segment; + if (bot_levels.size() == map_size) + bot_segment = "%s(%u)"; + else if (bot_levels.size() > 1) + bot_segment = ", %s(%u)"; + else + bot_segment = " or %s(%u)"; + + required_bots_map[type_index].append(StringFormat(bot_segment.c_str(), Bot::ClassIdToString(test_iter->first).c_str(), test_iter->second)); + required_bots_map_by_class[type_index][test_iter->first] = StringFormat("%s(%u)", Bot::ClassIdToString(test_iter->first).c_str(), test_iter->second); + bot_levels.erase(test_iter); + } + } + +#ifdef BCSTSPELLDUMP + static void spell_dump() { + std::ofstream spell_dump; + spell_dump.open(StringFormat("bcs_dump/spell_dump_%i.txt", getpid()), std::ios_base::app | std::ios_base::out); + + if (bot_command_spells.empty()) { + spell_dump << "BCSpells::spell_dump() - 'bot_command_spells' map is empty.\n"; + spell_dump.close(); + return; + } + + int entry_count = 0; + for (int i = BCEnum::SpellTypeFirst; i <= BCEnum::SpellTypeLast; ++i) { + auto bcst_id = static_cast(i); + spell_dump << StringFormat("BCSpells::spell_dump(): - '%s' returned %u spells:\n", + BCEnum::SpellTypeEnumToString(bcst_id).c_str(), bot_command_spells[bcst_id].size()); + + bcst_list& map_entry = bot_command_spells[bcst_id]; + for (auto list_iter = map_entry.begin(); list_iter != map_entry.end(); ++list_iter) { + STBaseEntry* list_entry = *list_iter; + int spell_id = list_entry->spell_id; + spell_dump << StringFormat("\"%20s\" tt:%02u/cc:%02u/cl:%03u", + ((strlen(spells[spell_id].name) > 20) ? (std::string(spells[spell_id].name).substr(0, 20).c_str()) : (spells[spell_id].name)), + list_entry->target_type, + list_entry->caster_class, + list_entry->spell_level + ); + + spell_dump << StringFormat(" /mn:%05u/RD:%06i/zt:%02i/d#:%06i/td#:%05i/ed#:%05i/SAI:%03u", + spells[spell_id].mana, + spells[spell_id].ResistDiff, + spells[spell_id].zonetype, + spells[spell_id].descnum, + spells[spell_id].typedescnum, + spells[spell_id].effectdescnum, + spells[spell_id].SpellAffectIndex + ); + + for (int i = EffectIDFirst; i <= 3/*EffectIDLast*/; ++i) { + int effect_index = EFFECTIDTOINDEX(i); + spell_dump << StringFormat(" /e%02i:%04i/b%02i:%06i/m%02i:%06i", + i, spells[spell_id].effectid[effect_index], i, spells[spell_id].base[effect_index], i, spells[spell_id].max[effect_index]); + } + + switch (list_entry->BCST()) { + case BCEnum::SpT_Charm: + spell_dump << StringFormat(" /d:%c", ((list_entry->SafeCastToCharm()->dire) ? ('T') : ('F'))); + break; + case BCEnum::SpT_Cure: + spell_dump << ' '; + for (int i = 0; i < BCEnum::AilmentTypeCount; ++i) { + spell_dump << StringFormat("/cv%02i:%03i", i, list_entry->SafeCastToCure()->cure_value[i]); + } + break; + case BCEnum::SpT_Depart: { + std::string long_name = list_entry->SafeCastToDepart()->long_name.c_str(); + spell_dump << StringFormat(" /ln:%20s", ((long_name.size() > 20) ? (long_name.substr(0, 20).c_str()) : (long_name.c_str()))); + break; + } + case BCEnum::SpT_Escape: + spell_dump << StringFormat(" /l:%c", ((list_entry->SafeCastToEscape()->lesser) ? ('T') : ('F'))); + break; + case BCEnum::SpT_Invisibility: + spell_dump << StringFormat(" /it:%02i", list_entry->SafeCastToInvisibility()->invis_type); + break; + case BCEnum::SpT_MovementSpeed: + spell_dump << StringFormat(" /g:%c", ((list_entry->SafeCastToMovementSpeed()->group) ? ('T') : ('F'))); + break; + case BCEnum::SpT_Resistance: + spell_dump << ' '; + for (int i = 0; i < BCEnum::ResistanceTypeCount; ++i) { + spell_dump << StringFormat("/rv%02i:%03i", i, list_entry->SafeCastToResistance()->resist_value[i]); + } + break; + case BCEnum::SpT_Resurrect: + spell_dump << StringFormat(" /aoe:%c", ((list_entry->SafeCastToResurrect()->aoe) ? ('T') : ('F'))); + break; + case BCEnum::SpT_SendHome: + spell_dump << StringFormat(" /g:%c", ((list_entry->SafeCastToSendHome()->group) ? ('T') : ('F'))); + break; + case BCEnum::SpT_Size: + spell_dump << StringFormat(" /st:%02i", list_entry->SafeCastToSize()->size_type); + break; + case BCEnum::SpT_Stance: + spell_dump << StringFormat(" /st:%02i", list_entry->SafeCastToStance()->stance_type); + break; + default: + break; + } + + spell_dump << "\n"; + ++entry_count; + } + + spell_dump << StringFormat("required_bots_map[%s] = \"%s\"\n", + BCEnum::SpellTypeEnumToString(static_cast(i)).c_str(), required_bots_map[static_cast(i)].c_str()); + + spell_dump << "\n"; + } + + spell_dump << StringFormat("Total bcs entry count: %i\n", entry_count); + spell_dump.close(); + } +#endif +}; + + +//struct bcl_struct *bot_command_list; // the actual linked list of bot commands +int bot_command_count; // how many bot commands we have + +// this is the pointer to the dispatch function, updated once +// init has been performed to point at the real function +int (*bot_command_dispatch)(Client *,char const *) = bot_command_not_avail; + +// TODO: Find out what these are for... +void bot_command_bestz(Client *c, const Seperator *message); +void bot_command_pf(Client *c, const Seperator *message); + +std::map bot_command_list; +std::map bot_command_aliases; + +// All allocated BotCommandRecords get put in here so they get deleted on shutdown +LinkedList cleanup_bot_command_list; + + +/* + * bot_command_not_avail + * This is the default dispatch function when commands aren't loaded. + * + * Parameters: + * not used + * + */ +int bot_command_not_avail(Client *c, const char *message) +{ + c->Message(m_fail, "Bot commands not available."); + return -1; +} + + +/************************************************************************** +/* the rest below here could be in a dynamically loaded module eventually * +/*************************************************************************/ + +/* + +Access Levels: + +0 Normal +10 * Steward * +20 * Apprentice Guide * +50 * Guide * +80 * QuestTroupe * +81 * Senior Guide * +85 * GM-Tester * +90 * EQ Support * +95 * GM-Staff * +100 * GM-Admin * +150 * GM-Lead Admin * +160 * QuestMaster * +170 * GM-Areas * +180 * GM-Coder * +200 * GM-Mgmt * +250 * GM-Impossible * + +*/ + +/* + * bot_command_init + * initializes the bot command list, call at startup + * + * Parameters: + * none + * + * When adding a new bot command, only hard-code 'real' bot commands - + * all command aliases are added later through a database call + * + */ +int bot_command_init(void) +{ + bot_command_aliases.clear(); + + if ( + bot_command_add("actionable", "Lists actionable command arguments and use descriptions", 0, bot_command_actionable) || + bot_command_add("aggressive", "Orders a bot to use a aggressive discipline", 0, bot_command_aggressive) || + bot_command_add("attack", "Orders bots to attack a designated target", 0, bot_command_attack) || + bot_command_add("bindaffinity", "Orders a bot to attempt an affinity binding", 0, bot_command_bind_affinity) || + bot_command_add("bot", "Lists the available bot management [subcommands]", 0, bot_command_bot) || + bot_command_add("botappearance", "Lists the available bot appearance [subcommands]", 0, bot_subcommand_bot_appearance) || + bot_command_add("botbeardcolor", "Changes the beard color of a bot", 0, bot_subcommand_bot_beard_color) || + bot_command_add("botbeardstyle", "Changes the beard style of a bot", 0, bot_subcommand_bot_beard_style) || + bot_command_add("botcamp", "Orders a bot(s) to camp", 0, bot_subcommand_bot_camp) || + bot_command_add("botclone", "Creates a copy of a bot", 200, bot_subcommand_bot_clone) || + bot_command_add("botcreate", "Creates a new bot", 0, bot_subcommand_bot_create) || + bot_command_add("botdelete", "Deletes all record of a bot", 0, bot_subcommand_bot_delete) || + bot_command_add("botdetails", "Changes the Drakkin details of a bot", 0, bot_subcommand_bot_details) || + bot_command_add("botdyearmor", "Changes the color of a bot's (bots') armor", 0, bot_subcommand_bot_dye_armor) || + bot_command_add("boteyes", "Changes the eye colors of a bot", 0, bot_subcommand_bot_eyes) || + bot_command_add("botface", "Changes the facial appearance of your bot", 0, bot_subcommand_bot_face) || + bot_command_add("botfollowdistance", "Changes the follow distance(s) of a bot(s)", 0, bot_subcommand_bot_follow_distance) || + bot_command_add("botgroup", "Lists the available bot-group [subcommands]", 0, bot_command_botgroup) || + bot_command_add("botgroupaddmember", "Adds a member to a bot-group", 0, bot_subcommand_botgroup_add_member) || + bot_command_add("botgroupcreate", "Creates a bot-group and designates a leader", 0, bot_subcommand_botgroup_create) || + bot_command_add("botgroupdelete", "Deletes a bot-group and releases its members", 0, bot_subcommand_botgroup_delete) || + bot_command_add("botgrouplist", "Lists all of your existing bot-groups", 0, bot_subcommand_botgroup_list) || + bot_command_add("botgroupload", "Loads all members of a bot-group", 0, bot_subcommand_botgroup_load) || + bot_command_add("botgroupremovemember", "Removes a bot from its bot-group", 0, bot_subcommand_botgroup_remove_member) || + bot_command_add("bothaircolor", "Changes the hair color of a bot", 0, bot_subcommand_bot_hair_color) || + bot_command_add("bothairstyle", "Changes the hairstyle of a bot", 0, bot_subcommand_bot_hairstyle) || + bot_command_add("botheritage", "Changes the Drakkin heritage of a bot", 0, bot_subcommand_bot_heritage) || + bot_command_add("botinspectmessage", "Changes the inspect message of a bot", 0, bot_subcommand_bot_inspect_message) || + bot_command_add("botlist", "Lists the bots that you own", 0, bot_subcommand_bot_list) || + bot_command_add("botoutofcombat", "Toggles your bot between standard and out-of-combat spell/skill use - if any specialized behaviors exist", 0, bot_subcommand_bot_out_of_combat) || + bot_command_add("botreport", "Orders a bot to report its readiness", 0, bot_subcommand_bot_report) || + bot_command_add("botspawn", "Spawns a created bot", 0, bot_subcommand_bot_spawn) || + bot_command_add("botstance", "Changes the stance of a bot", 0, bot_subcommand_bot_stance) || + bot_command_add("botsummon", "Summons bot(s) to your location", 0, bot_subcommand_bot_summon) || + bot_command_add("bottattoo", "Changes the Drakkin tattoo of a bot", 0, bot_subcommand_bot_tattoo) || + bot_command_add("bottogglearcher", "Toggles a archer bot between melee and ranged weapon use", 0, bot_subcommand_bot_toggle_archer) || + bot_command_add("bottogglehelm", "Toggles the helm visibility of a bot between shown and hidden", 0, bot_subcommand_bot_toggle_helm) || + bot_command_add("botupdate", "Updates a bot to reflect any level changes that you have experienced", 0, bot_subcommand_bot_update) || + bot_command_add("botwoad", "Changes the Barbarian woad of a bot", 0, bot_subcommand_bot_woad) || + bot_command_add("charm", "Attempts to have a bot charm your target", 0, bot_command_charm) || + bot_command_add("circle", "Orders a Druid bot to open a magical doorway to a specified destination", 0, bot_subcommand_circle) || + bot_command_add("cure", "Orders a bot to remove any ailments", 0, bot_command_cure) || + bot_command_add("defensive", "Orders a bot to use a defensive discipline", 0, bot_command_defensive) || + bot_command_add("depart", "Orders a bot to open a magical doorway to a specified destination", 0, bot_command_depart) || + bot_command_add("escape", "Orders a bot to send a target group to a safe location within the zone", 0, bot_command_escape) || + bot_command_add("findaliases", "Find available aliases for a bot command", 0, bot_command_find_aliases) || + bot_command_add("follow", "Orders bots to follow a designated target", 0, bot_command_follow) || + bot_command_add("guard", "Orders bots to guard their current positions", 0, bot_command_guard) || + bot_command_add("healrotation", "Lists the available bot heal rotation [subcommands]", 0, bot_command_heal_rotation) || + bot_command_add("healrotationadaptivetargeting", "Enables or disables adaptive targeting within the heal rotation instance", 0, bot_subcommand_heal_rotation_adaptive_targeting) || + bot_command_add("healrotationaddmember", "Adds a bot to a heal rotation instance", 0, bot_subcommand_heal_rotation_add_member) || + bot_command_add("healrotationaddtarget", "Adds target to a heal rotation instance", 0, bot_subcommand_heal_rotation_add_target) || + bot_command_add("healrotationadjustcritical", "Adjusts the critial HP limit of the heal rotation instance's Class Armor Type criteria", 0, bot_subcommand_heal_rotation_adjust_critical) || + bot_command_add("healrotationadjustsafe", "Adjusts the safe HP limit of the heal rotation instance's Class Armor Type criteria", 0, bot_subcommand_heal_rotation_adjust_safe) || + bot_command_add("healrotationcastingoverride", "Enables or disables casting overrides within the heal rotation instance", 0, bot_subcommand_heal_rotation_casting_override) || + bot_command_add("healrotationchangeinterval", "Changes casting interval between members within the heal rotation instance", 0, bot_subcommand_heal_rotation_change_interval) || + bot_command_add("healrotationcleartargets", "Removes all targets from a heal rotation instance", 0, bot_subcommand_heal_rotation_clear_targets) || + bot_command_add("healrotationcreate", "Creates a bot heal rotation instance and designates a leader", 0, bot_subcommand_heal_rotation_create) || + bot_command_add("healrotationfastheals", "Enables or disables fast heals within the heal rotation instance", 0, bot_subcommand_heal_rotation_fast_heals) || + bot_command_add("healrotationlist", "Reports heal rotation instance(s) information", 0, bot_subcommand_heal_rotation_list) || + bot_command_add("healrotationremovemember", "Removes a bot from a heal rotation instance", 0, bot_subcommand_heal_rotation_remove_member) || + bot_command_add("healrotationremovetarget", "Removes target from a heal rotations instance", 0, bot_subcommand_heal_rotation_remove_target) || + bot_command_add("healrotationresetlimits", "Resets all Class Armor Type HP limit criteria in a heal rotation to its default value", 0, bot_subcommand_heal_rotation_reset_limits) || + bot_command_add("healrotationstart", "Starts a heal rotation", 0, bot_subcommand_heal_rotation_start) || + bot_command_add("healrotationstop", "Stops a heal rotation", 0, bot_subcommand_heal_rotation_stop) || + bot_command_add("help", "List available commands and their description - specify partial command as argument to search", 0, bot_command_help) || + bot_command_add("hold", "Suspends a bot's AI processing until released", 0, bot_command_hold) || + bot_command_add("identify", "Orders a bot to cast an item identification spell", 0, bot_command_identify) || + bot_command_add("inventory", "Lists the available bot inventory [subcommands]", 0, bot_command_inventory) || + bot_command_add("inventorygive", "Gives the item on your cursor to a bot", 0, bot_subcommand_inventory_give) || + bot_command_add("inventorylist", "Lists all items in a bot's inventory", 0, bot_subcommand_inventory_list) || + bot_command_add("inventoryremove", "Removes an item from a bot's inventory", 0, bot_subcommand_inventory_remove) || + bot_command_add("invisibility", "Orders a bot to cast a cloak of invisibility, or allow them to be seen", 0, bot_command_invisibility) || + bot_command_add("levitation", "Orders a bot to cast a levitation spell", 0, bot_command_levitation) || + bot_command_add("lull", "Orders a bot to cast a pacification spell", 0, bot_command_lull) || + bot_command_add("mesmerize", "Orders a bot to cast a mesmerization spell", 0, bot_command_mesmerize) || + bot_command_add("movementspeed", "Orders a bot to cast a movement speed enhancement spell", 0, bot_command_movement_speed) || + bot_command_add("pet", "Lists the available bot pet [subcommands]", 0, bot_command_pet) || + bot_command_add("petremove", "Orders a bot to remove its pet", 0, bot_subcommand_pet_remove) || + bot_command_add("petsettype", "Orders a Magician bot to use a specified pet type", 0, bot_subcommand_pet_set_type) || + bot_command_add("picklock", "Orders a capable bot to pick the lock of the closest door", 0, bot_command_pick_lock) || + bot_command_add("portal", "Orders a Wizard bot to open a magical doorway to a specified destination", 0, bot_subcommand_portal) || + bot_command_add("pull", "Orders a designated bot to 'pull' an enemy", 0, bot_command_pull) || + bot_command_add("release", "Releases a suspended bot's AI processing (with hate list wipe)", 0, bot_command_release) || + bot_command_add("resistance", "Orders a bot to cast a specified resistance buff", 0, bot_command_resistance) || + bot_command_add("resurrect", "Orders a bot to resurrect a player's (players') corpse(s)", 0, bot_command_resurrect) || + bot_command_add("rune", "Orders a bot to cast a rune of protection", 0, bot_command_rune) || + bot_command_add("sendhome", "Orders a bot to open a magical doorway home", 0, bot_command_send_home) || + bot_command_add("size", "Orders a bot to change a player's size", 0, bot_command_size) || + bot_command_add("summoncorpse", "Orders a bot to summon a corpse to its feet", 0, bot_command_summon_corpse) || + bot_command_add("taunt", "Toggles taunt use by a bot", 0, bot_command_taunt) || + bot_command_add("track", "Orders a capable bot to track enemies", 0, bot_command_track) || + bot_command_add("waterbreathing", "Orders a bot to cast a water breathing spell", 0, bot_command_water_breathing) + ) { + bot_command_deinit(); + return -1; + } + + std::map>> bot_command_settings; + botdb.GetCommandSettings(bot_command_settings); + + auto working_bcl = bot_command_list; + for (auto working_bcl_iter : working_bcl) { + auto bot_command_settings_iter = bot_command_settings.find(working_bcl_iter.first); + if (bot_command_settings_iter == bot_command_settings.end()) { + if (working_bcl_iter.second->access == 0) + Log.Out(Logs::General, Logs::Commands, "bot_command_init(): Warning: Bot Command '%s' defaulting to access level 0!", working_bcl_iter.first.c_str()); + continue; + } + + working_bcl_iter.second->access = bot_command_settings_iter->second.first; + Log.Out(Logs::General, Logs::Commands, "bot_command_init(): - Bot Command '%s' set to access level %d.", working_bcl_iter.first.c_str(), bot_command_settings_iter->second.first); + if (bot_command_settings_iter->second.second.empty()) + continue; + + for (auto alias_iter : bot_command_settings_iter->second.second) { + if (alias_iter.empty()) + continue; + if (bot_command_list.find(alias_iter) != bot_command_list.end()) { + Log.Out(Logs::General, Logs::Commands, "bot_command_init(): Warning: Alias '%s' already exists as a bot command - skipping!", alias_iter.c_str()); + continue; + } + + bot_command_list[alias_iter] = working_bcl_iter.second; + bot_command_aliases[alias_iter] = working_bcl_iter.first; + + Log.Out(Logs::General, Logs::Commands, "bot_command_init(): - Alias '%s' added to bot command '%s'.", alias_iter.c_str(), bot_command_aliases[alias_iter].c_str()); + } + } + + bot_command_dispatch = bot_command_real_dispatch; + + BCSpells::Load(); + + return bot_command_count; +} + + +/* + * bot_command_deinit + * clears the bot command list, freeing resources + * + * Parameters: + * none + * + */ +void bot_command_deinit(void) +{ + bot_command_list.clear(); + bot_command_aliases.clear(); + + bot_command_dispatch = bot_command_not_avail; + bot_command_count = 0; + + BCSpells::Unload(); +} + + +/* + * bot_command_add + * adds a bot command to the bot command list; used by bot_command_init + * + * Parameters: + * bot_command_string - the command ex: "spawn" + * desc - text description of bot command for #help + * access - default access level required to use command + * function - pointer to function that handles command + * + */ +int bot_command_add(std::string bot_command_name, const char *desc, int access, BotCmdFuncPtr function) +{ + if (bot_command_name.empty()) { + Log.Out(Logs::General, Logs::Error, "bot_command_add() - Bot command added with empty name string - check bot_command.cpp."); + return -1; + } + if (function == nullptr) { + Log.Out(Logs::General, Logs::Error, "bot_command_add() - Bot command '%s' added without a valid function pointer - check bot_command.cpp.", bot_command_name.c_str()); + return -1; + } + if (bot_command_list.count(bot_command_name) != 0) { + Log.Out(Logs::General, Logs::Error, "bot_command_add() - Bot command '%s' is a duplicate bot command name - check bot_command.cpp.", bot_command_name.c_str()); + return -1; + } + for (auto iter : bot_command_list) { + if (iter.second->function != function) + continue; + Log.Out(Logs::General, Logs::Error, "bot_command_add() - Bot command '%s' equates to an alias of '%s' - check bot_command.cpp.", bot_command_name.c_str(), iter.first.c_str()); + return -1; + } + + BotCommandRecord *bcr = new BotCommandRecord; + bcr->access = access; + bcr->desc = desc; + bcr->function = function; + + bot_command_list[bot_command_name] = bcr; + bot_command_aliases[bot_command_name] = bot_command_name; + cleanup_bot_command_list.Append(bcr); + bot_command_count++; + + return 0; +} + + +/* + * + * bot_command_real_dispatch + * Calls the correct function to process the client's command string. + * Called from Client::ChannelMessageReceived if message starts with + * bot command character (^). + * + * Parameters: + * c - pointer to the calling client object + * message - what the client typed + * + */ +int bot_command_real_dispatch(Client *c, const char *message) +{ + Seperator sep(message, ' ', 10, 100, true); // "three word argument" should be considered 1 arg + + bot_command_log_command(c, message); + + std::string cstr(sep.arg[0]+1); + + if(bot_command_list.count(cstr) != 1) { + return(-2); + } + + BotCommandRecord *cur = bot_command_list[cstr]; + if(c->Admin() < cur->access){ + c->Message(m_fail, "Your access level is not high enough to use this bot command."); + return(-1); + } + + /* QS: Player_Log_Issued_Commands */ + if (RuleB(QueryServ, PlayerLogIssuedCommandes)){ + std::string event_desc = StringFormat("Issued bot command :: '%s' in zoneid:%i instid:%i", message, c->GetZoneID(), c->GetInstanceID()); + QServ->PlayerLogEvent(Player_Log_Issued_Commands, c->CharacterID(), event_desc); + } + + if(cur->access >= COMMANDS_LOGGING_MIN_STATUS) { + Log.Out(Logs::General, Logs::Commands, "%s (%s) used bot command: %s (target=%s)", c->GetName(), c->AccountName(), message, c->GetTarget()?c->GetTarget()->GetName():"NONE"); + } + + if(cur->function == nullptr) { + Log.Out(Logs::General, Logs::Error, "Bot command '%s' has a null function\n", cstr.c_str()); + return(-1); + } else { + //dispatch C++ bot command + cur->function(c, &sep); // dispatch bot command + } + return 0; + +} + +void bot_command_log_command(Client *c, const char *message) +{ + int admin = c->Admin(); + + bool continueevents = false; + switch (zone->loglevelvar) { //catch failsafe + case 9: // log only LeadGM + if ((admin >= 150) && (admin <200)) + continueevents = true; + break; + case 8: // log only GM + if ((admin >= 100) && (admin <150)) + continueevents = true; + break; + case 1: + if ((admin >= 200)) + continueevents = true; + break; + case 2: + if ((admin >= 150)) + continueevents = true; + break; + case 3: + if ((admin >= 100)) + continueevents = true; + break; + case 4: + if ((admin >= 80)) + continueevents = true; + break; + case 5: + if ((admin >= 20)) + continueevents = true; + break; + case 6: + if ((admin >= 10)) + continueevents = true; + break; + case 7: + continueevents = true; + break; + default: + break; + } + + if (continueevents) + database.logevents(c->AccountName(), c->AccountID(), admin,c->GetName(), c->GetTarget()?c->GetTarget()->GetName():"None", "BotCommand", message, 1); +} + + +/* + * helper functions by use + */ +namespace MyBots +{ + static bool IsMyBot(Client *bot_owner, Mob *my_bot) { + if (!bot_owner || !my_bot || !my_bot->IsBot()) + return false; + + auto test_bot = my_bot->CastToBot(); + if (!test_bot->GetOwner() || !test_bot->GetOwner()->IsClient() || test_bot->GetOwner()->CastToClient() != bot_owner) + return false; + + return true; + } + + static bool IsMyBotInTargetsGroup(Client *bot_owner, Mob *grouped_bot) { + if (!bot_owner || !grouped_bot || !grouped_bot->GetGroup() || !IsMyBot(bot_owner, grouped_bot)) + return false; + + auto target_mob = bot_owner->GetTarget(); + if (!target_mob) + return false; + + if (!target_mob->GetGroup() || (!target_mob->IsClient() && !target_mob->IsBot())) + return false; + + return (grouped_bot->GetGroup() == target_mob->GetGroup()); + } + + static bool IsMyBotInPlayerGroup(Client *bot_owner, Mob *grouped_bot, Client *grouped_player) { + if (!bot_owner || !grouped_player || !grouped_player->GetGroup() || !grouped_bot || !grouped_bot->GetGroup() || !IsMyBot(bot_owner, grouped_bot)) + return false; + + return (grouped_player->GetGroup() == grouped_bot->GetGroup()); + } + + static void UniquifySBL(std::list &sbl) { + sbl.remove(nullptr); + sbl.sort(); + sbl.unique(); + } + + static void PopulateSBL_ByTargetedBot(Client *bot_owner, std::list &sbl, bool clear_list = true) { + if (clear_list) + sbl.clear(); + + if (IsMyBot(bot_owner, bot_owner->GetTarget())) + sbl.push_back(bot_owner->GetTarget()->CastToBot()); + + if (!clear_list) + UniquifySBL(sbl); + } + + static void PopulateSBL_ByNamedBot(Client *bot_owner, std::list &sbl, const char* name, bool clear_list = true) { + if (clear_list) + sbl.clear(); + if (!bot_owner || !name) + return; + + auto selectable_bot_list = entity_list.GetBotsByBotOwnerCharacterID(bot_owner->CharacterID()); + for (auto bot_iter : selectable_bot_list) { + if (!strcasecmp(bot_iter->GetCleanName(), name)) { + sbl.push_back(bot_iter); + return; + } + } + + if (!clear_list) + UniquifySBL(sbl); + } + + static void PopulateSBL_ByMyGroupedBots(Client *bot_owner, std::list &sbl, bool clear_list = true) { + if (clear_list) + sbl.clear(); + if (!bot_owner) + return; + + if (!bot_owner->GetGroup()) + return; + + std::list group_list; + bot_owner->GetGroup()->GetBotList(group_list); + for (auto member_iter : group_list) { + if (IsMyBot(bot_owner, member_iter)) + sbl.push_back(member_iter); + } + + if (!clear_list) + UniquifySBL(sbl); + } + + static void PopulateSBL_ByBotGroup(Client *bot_owner, std::list &sbl, const char* name, bool clear_list = true) { + if (clear_list) + sbl.clear(); + if (!bot_owner) + return; + + std::list selectable_bot_list; + if (name) + PopulateSBL_ByNamedBot(bot_owner, selectable_bot_list, name); + else if (IsMyBot(bot_owner, bot_owner->GetTarget())) + selectable_bot_list.push_back(bot_owner->GetTarget()->CastToBot()); + + if (selectable_bot_list.empty()) + return; + if (!selectable_bot_list.front()->GetGroup() || !IsMyBot(bot_owner, selectable_bot_list.front()->GetGroup()->GetLeader())) + return; + + std::list group_list; + selectable_bot_list.front()->GetGroup()->GetMemberList(group_list); + for (auto member_iter : group_list) { + if (IsMyBot(bot_owner, member_iter)) + sbl.push_back(member_iter->CastToBot()); + } + + if (!clear_list) + UniquifySBL(sbl); + } + + static void PopulateSBL_ByTargetsGroupedBots(Client *bot_owner, std::list &sbl, bool clear_list = true) { + if (clear_list) + sbl.clear(); + if (!bot_owner) + return; + + auto target_mob = bot_owner->GetTarget(); + if (!target_mob || !target_mob->GetGroup() || (!target_mob->IsClient() && !target_mob->IsBot())) + return; + + std::list group_list; + target_mob->GetGroup()->GetBotList(group_list); + for (auto member_iter : group_list) { + if (IsMyBot(bot_owner, member_iter)) + sbl.push_back(member_iter); + } + + if (!clear_list) + UniquifySBL(sbl); + } + + static void PopulateSBL_ByNamesGroupedBots(Client *bot_owner, std::list &sbl, const char* name, bool clear_list = true) { + if (clear_list) + sbl.clear(); + if (!bot_owner || !name) + return; + + Mob* named_mob = nullptr; + std::list l_mob_list; + entity_list.GetMobList(l_mob_list); + for (auto mob_iter : l_mob_list) { + if (!strcasecmp(mob_iter->GetCleanName(), name)) { + named_mob = mob_iter; + break; + } + } + if (!named_mob || !named_mob->GetGroup() || (!named_mob->IsClient() && !named_mob->IsBot())) + return; + + std::list group_list; + named_mob->GetGroup()->GetBotList(group_list); + for (auto member_iter : group_list) { + if (IsMyBot(bot_owner, member_iter)) + sbl.push_back(member_iter); + } + + if (!clear_list) + UniquifySBL(sbl); + } + + static void PopulateSBL_ByHealRotation(Client *bot_owner, std::list &sbl, const char* name, bool clear_list = true) { + if (clear_list) + sbl.clear(); + if (!bot_owner || (!name && !bot_owner->GetTarget())) + return; + + std::list selectable_bot_list; + if (name) + PopulateSBL_ByNamedBot(bot_owner, selectable_bot_list, name); + else + PopulateSBL_ByTargetedBot(bot_owner, selectable_bot_list); + + if (selectable_bot_list.empty() || !selectable_bot_list.front()->IsHealRotationMember()) + return; + + auto hrm = (*selectable_bot_list.front()->MemberOfHealRotation())->MemberList(); + for (auto hrm_iter : *hrm) { + if (IsMyBot(bot_owner, hrm_iter)) + sbl.push_back(hrm_iter); + } + + auto hrt = (*selectable_bot_list.front()->MemberOfHealRotation())->TargetList(); + for (auto hrt_iter : *hrt) { + if (IsMyBot(bot_owner, hrt_iter)) + sbl.push_back(hrt_iter->CastToBot()); + } + + UniquifySBL(sbl); + } + + static void PopulateSBL_ByHealRotationMembers(Client *bot_owner, std::list &sbl, const char* name, bool clear_list = true) { + if (clear_list) + sbl.clear(); + if (!bot_owner || (!name && !bot_owner->GetTarget())) + return; + + std::list selectable_bot_list; + if (name) + PopulateSBL_ByNamedBot(bot_owner, selectable_bot_list, name); + else + PopulateSBL_ByTargetedBot(bot_owner, selectable_bot_list); + + if (selectable_bot_list.empty() || !selectable_bot_list.front()->IsHealRotationMember()) + return; + + auto hrm = (*selectable_bot_list.front()->MemberOfHealRotation())->MemberList(); + for (auto hrm_iter : *hrm) { + if (IsMyBot(bot_owner, hrm_iter)) + sbl.push_back(hrm_iter); + } + + if (!clear_list) + UniquifySBL(sbl); + } + + static void PopulateSBL_ByHealRotationTargets(Client *bot_owner, std::list &sbl, const char* name, bool clear_list = true) { + if (clear_list) + sbl.clear(); + if (!bot_owner || (!name && !bot_owner->GetTarget())) + return; + + std::list selectable_bot_list; + if (name) + PopulateSBL_ByNamedBot(bot_owner, selectable_bot_list, name); + else + PopulateSBL_ByTargetedBot(bot_owner, selectable_bot_list); + + if (selectable_bot_list.empty() || !selectable_bot_list.front()->IsHealRotationMember()) + return; + + auto hrm = (*selectable_bot_list.front()->MemberOfHealRotation())->TargetList(); + for (auto hrm_iter : *hrm) { + if (IsMyBot(bot_owner, hrm_iter)) + sbl.push_back(static_cast(hrm_iter)); + } + + if (!clear_list) + UniquifySBL(sbl); + } + + static void PopulateSBL_BySpawnedBots(Client *bot_owner, std::list &sbl) { // should be used for most spell casting commands + sbl.clear(); + if (!bot_owner) + return; + + sbl = entity_list.GetBotsByBotOwnerCharacterID(bot_owner->CharacterID()); + sbl.remove(nullptr); + } +}; + +namespace ActionableTarget +{ + static bool AmIInPlayerGroup(Client *bot_owner, Client *grouped_player) { + if (!bot_owner || !grouped_player || !bot_owner->GetGroup() || !grouped_player->GetGroup()) + return false; + + return (bot_owner->GetGroup() == grouped_player->GetGroup()); + } + + static Client* AsSingle_ByPlayer(Client *bot_owner, bool return_me_on_null_target = true) { + if (!bot_owner) + return nullptr; + + if (!bot_owner->GetTarget()) { + if (return_me_on_null_target) + return bot_owner; + else + return nullptr; + } + + if (!bot_owner->GetTarget()->IsClient()) + return nullptr; + + return bot_owner->GetTarget()->CastToClient(); + } + + static Client* AsGroupMember_ByPlayer(Client *bot_owner, bool return_me_on_null_target = true) { + if (!bot_owner) + return nullptr; + + if (!bot_owner->GetTarget()) { + if (return_me_on_null_target) + return bot_owner; + else + return nullptr; + } + + if (!bot_owner->GetTarget()->IsClient() || !AmIInPlayerGroup(bot_owner, bot_owner->GetTarget()->CastToClient())) + return nullptr; + + return bot_owner->GetTarget()->CastToClient(); + } + + static Corpse* AsCorpse_ByPlayer(Client *bot_owner) { + if (!bot_owner || !bot_owner->GetTarget() || !bot_owner->GetTarget()->IsPlayerCorpse()) + return nullptr; + + return bot_owner->GetTarget()->CastToCorpse(); + } + + static Mob* AsSingle_ByAttackable(Client *bot_owner) { + if (!bot_owner || !bot_owner->IsAttackAllowed(bot_owner->GetTarget())) + return nullptr; + + return bot_owner->GetTarget(); + } + + static bool IsFriendlyAllowed(Mob* target_mob) { + if (!target_mob || target_mob->IsClient() || target_mob->IsBot() || (target_mob->IsPet() && target_mob->GetOwner() && (target_mob->GetOwner()->IsClient() || target_mob->GetOwner()->IsBot())) || target_mob->IsPlayerCorpse()) + return true; + + return false; + } + + static Mob* VerifyFriendly(Client* bot_owner, BCEnum::TType target_type, bool return_me_on_null_target = true) { + if (!bot_owner || target_type == BCEnum::TT_None) + return nullptr; + + auto target_mob = bot_owner->GetTarget(); + if (!IsFriendlyAllowed(target_mob)) + return nullptr; + + Mob* verified_friendly = nullptr; + switch (target_type) { + case BCEnum::TT_Single: + case BCEnum::TT_GroupV1: + case BCEnum::TT_GroupV2: + case BCEnum::TT_AETarget: + verified_friendly = target_mob; + break; + case BCEnum::TT_Animal: + if (target_mob && target_mob->GetBodyType() == BT_Animal) + verified_friendly = target_mob; + break; + case BCEnum::TT_Undead: + if (target_mob && target_mob->GetBodyType() == BT_Undead) + verified_friendly = target_mob; + break; + case BCEnum::TT_Summoned: + if (target_mob && target_mob->GetBodyType() == BT_Summoned) + verified_friendly = target_mob; + break; + case BCEnum::TT_Plant: + if (target_mob && target_mob->GetBodyType() == BT_Plant) + verified_friendly = target_mob; + break; + case BCEnum::TT_Corpse: + if (target_mob && target_mob->IsCorpse()) + verified_friendly = target_mob; + break; + default: + return nullptr; + } + + if (return_me_on_null_target && !target_mob && !verified_friendly) { + switch (target_type) { + case BCEnum::TT_Single: + case BCEnum::TT_GroupV1: + case BCEnum::TT_GroupV2: + case BCEnum::TT_AETarget: + verified_friendly = bot_owner; + break; + default: + break; + } + } + + return verified_friendly; + } + + static Mob* VerifyEnemy(Client* bot_owner, BCEnum::TType target_type) { + if (!bot_owner || target_type == BCEnum::TT_None) + return nullptr; + + auto target_mob = bot_owner->GetTarget(); + if (!target_mob || !bot_owner->IsAttackAllowed(target_mob)) + return nullptr; + + Mob* verified_enemy = nullptr; + switch (target_type) { + case BCEnum::TT_Animal: + if (target_mob->GetBodyType() == BT_Animal) + verified_enemy = target_mob; + break; + case BCEnum::TT_Undead: + if (target_mob->GetBodyType() == BT_Undead) + verified_enemy = target_mob; + break; + case BCEnum::TT_Summoned: + if (target_mob->GetBodyType() == BT_Summoned) + verified_enemy = target_mob; + break; + case BCEnum::TT_Plant: + if (target_mob->GetBodyType() == BT_Plant) + verified_enemy = target_mob; + break; + case BCEnum::TT_Single: + case BCEnum::TT_GroupV1: + case BCEnum::TT_GroupV2: + case BCEnum::TT_AETarget: + verified_enemy = target_mob; + break; + case BCEnum::TT_Corpse: + if (target_mob->IsCorpse()) + verified_enemy = target_mob; + break; + default: + return nullptr; + } + + return verified_enemy; + } + + class Types { + Mob* target[BCEnum::TargetTypeCount]; + bool target_set[BCEnum::TargetTypeCount]; + + public: + Types() { Clear(); } + + void Clear() { + for (int i = BCEnum::TT_None; i <= BCEnum::TargetTypeLast; ++i) { + target[i] = nullptr; + target_set[i] = false; + } + target_set[BCEnum::TT_None] = true; + } + + Mob* Select(Client* bot_owner, BCEnum::TType target_type, bool action_type, bool return_me_on_null_target = true) { + if (target_set[target_type]) + return target[target_type]; + + if (action_type == FRIENDLY) + target[target_type] = VerifyFriendly(bot_owner, target_type, return_me_on_null_target); + else + target[target_type] = VerifyEnemy(bot_owner, target_type); + target_set[target_type] = true; + + return target[target_type]; + } + }; +}; + +namespace ActionableBots +{ + enum ABType { + ABT_None = 0, + ABT_Target, + ABT_ByName, + ABT_OwnerGroup, + ABT_BotGroup, + ABT_TargetGroup, + ABT_NamesGroup, + ABT_HealRotation, + ABT_HealRotationMembers, + ABT_HealRotationTargets, + ABT_Spawned, + ABT_All + }; + + enum ABMask { + ABM_None = 0, + ABM_Target = (1 << (ABT_Target - 1)), + ABM_ByName = (1 << (ABT_ByName - 1)), + ABM_OwnerGroup = (1 << (ABT_OwnerGroup - 1)), + ABM_BotGroup = (1 << (ABT_BotGroup - 1)), + ABM_TargetGroup = (1 << (ABT_TargetGroup - 1)), + ABM_NamesGroup = (1 << (ABT_NamesGroup - 1)), + ABM_HealRotation = (1 << (ABT_HealRotation - 1)), + ABM_HealRotationMembers = (1 << (ABT_HealRotationMembers - 1)), + ABM_HealRotationTargets = (1 << (ABT_HealRotationTargets - 1)), + ABM_Spawned = (1 << (ABT_Spawned - 1)), + ABM_All = (1 << (ABT_All - 1)), + ABM_Spawned_All = (3 << (ABT_Spawned - 1)), + ABM_NoFilter = ~0, + // grouped values + ABM_Type1 = (ABM_Target | ABM_ByName | ABM_OwnerGroup | ABM_BotGroup | ABM_TargetGroup | ABM_NamesGroup | ABM_HealRotationTargets | ABM_Spawned), + ABM_Type2 = (ABM_ByName | ABM_OwnerGroup | ABM_BotGroup | ABM_NamesGroup | ABM_HealRotation | ABM_Spawned) + }; + + // Populates 'sbl' + static ABType PopulateSBL(Client* bot_owner, std::string ab_type_arg, std::list &sbl, int ab_mask, const char* name = nullptr, bool clear_list = true, bool suppress_message = false) { + if (clear_list) + sbl.clear(); + if (!bot_owner) + return ABT_None; + + auto ab_type = ABT_None; + if (!ab_type_arg.compare("target") || ab_type_arg.empty()) + ab_type = ABT_Target; + else if (!ab_type_arg.compare("byname")) + ab_type = ABT_ByName; + else if (!ab_type_arg.compare("ownergroup")) + ab_type = ABT_OwnerGroup; + else if (!ab_type_arg.compare("botgroup")) + ab_type = ABT_BotGroup; + else if (!ab_type_arg.compare("targetgroup")) + ab_type = ABT_TargetGroup; + else if (!ab_type_arg.compare("namesgroup")) + ab_type = ABT_NamesGroup; + else if (!ab_type_arg.compare("healrotation")) + ab_type = ABT_HealRotation; + else if (!ab_type_arg.compare("healrotationmembers")) + ab_type = ABT_HealRotationMembers; + else if (!ab_type_arg.compare("healrotationtargets")) + ab_type = ABT_HealRotationTargets; + else if (!ab_type_arg.compare("spawned")) + ab_type = ABT_Spawned; + else if (!ab_type_arg.compare("all")) + ab_type = ABT_All; + + if (ab_type_arg.empty()) + ab_type_arg = "target"; + + switch (ab_type) { + case ABT_Target: + if (ab_mask & ABM_Target) + MyBots::PopulateSBL_ByTargetedBot(bot_owner, sbl, clear_list); + break; + case ABT_ByName: + if (ab_mask & ABM_ByName) + MyBots::PopulateSBL_ByNamedBot(bot_owner, sbl, name, clear_list); + break; + case ABT_OwnerGroup: + if (ab_mask & ABM_OwnerGroup) + MyBots::PopulateSBL_ByMyGroupedBots(bot_owner, sbl, clear_list); + break; + case ABT_BotGroup: + if (ab_mask & ABM_BotGroup) + MyBots::PopulateSBL_ByBotGroup(bot_owner, sbl, name, clear_list); + break; + case ABT_TargetGroup: + if (ab_mask & ABM_TargetGroup) + MyBots::PopulateSBL_ByTargetsGroupedBots(bot_owner, sbl, clear_list); + break; + case ABT_NamesGroup: + if (ab_mask & ABM_NamesGroup) + MyBots::PopulateSBL_ByNamesGroupedBots(bot_owner, sbl, name, clear_list); + break; + case ABT_HealRotation: + if (ab_mask & ABM_HealRotation) + MyBots::PopulateSBL_ByHealRotation(bot_owner, sbl, name, clear_list); + break; + case ABT_HealRotationMembers: + if (ab_mask & ABM_HealRotationMembers) + MyBots::PopulateSBL_ByHealRotationMembers(bot_owner, sbl, name, clear_list); + break; + case ABT_HealRotationTargets: + if (ab_mask & ABM_HealRotationTargets) + MyBots::PopulateSBL_ByHealRotationTargets(bot_owner, sbl, name, clear_list); + break; + case ABT_Spawned: + case ABT_All: + if (ab_mask & ABM_Spawned_All) + MyBots::PopulateSBL_BySpawnedBots(bot_owner, sbl); + break; + default: + break; + } + if (sbl.empty() && ab_type != ABT_All) { + if (suppress_message) + return ABT_None; + + if (!ab_mask) + bot_owner->Message(m_fail, "Command passed null 'ActionableBot' criteria"); + else if (ab_mask & ab_type) + bot_owner->Message(m_fail, "You have no spawned bots meeting this criteria - type: '%s', name: '%s'", ab_type_arg.c_str(), ((name) ? (name) : (""))); + else + bot_owner->Message(m_fail, "This command does not allow 'ActionableBot' criteria '%s'", ab_type_arg.c_str()); + return ABT_None; + } + + return ab_type; + } + + // Returns single, scoped bot + static Bot* AsGroupMember_ByClass(Client *bot_owner, Client *bot_grouped_player, uint8 cls, bool petless = false) { + if (!bot_owner || !bot_grouped_player) + return nullptr; + if (!bot_grouped_player->GetGroup()) + return nullptr; + + std::list group_list; + bot_grouped_player->GetGroup()->GetMemberList(group_list); + for (auto member_iter : group_list) { + if (!MyBots::IsMyBot(bot_owner, member_iter)) + continue; + if (member_iter->GetClass() != cls) + continue; + if (petless && member_iter->GetPet()) + continue; + + return static_cast(member_iter); + } + + return nullptr; + } + + static Bot* AsGroupMember_ByMinLevelAndClass(Client *bot_owner, Client *bot_grouped_player, uint8 minlvl, uint8 cls, bool petless = false) { + // This function can be nixed if we can enforce bot level as owner level..and the level check can then be moved to the spell loop in the command function + if (!bot_owner || !bot_grouped_player) + return nullptr; + if (!bot_grouped_player->GetGroup()) + return nullptr; + + std::list group_list; + bot_grouped_player->GetGroup()->GetMemberList(group_list); + for (auto member_iter : group_list) { + if (!MyBots::IsMyBot(bot_owner, member_iter)) + continue; + if (member_iter->GetLevel() < minlvl || member_iter->GetClass() != cls) + continue; + if (petless && member_iter->GetPet()) + continue; + + return static_cast(member_iter); + } + + return nullptr; + } + + static Bot* AsSpawned_ByClass(Client *bot_owner, std::list &sbl, uint8 cls, bool petless = false) { + if (!bot_owner) + return nullptr; + + for (auto bot_iter : sbl) { + if (!MyBots::IsMyBot(bot_owner, bot_iter)) + continue; + if (bot_iter->GetClass() != cls) + continue; + if (petless && bot_iter->GetPet()) + continue; + + return bot_iter; + } + + return nullptr; + } + + static Bot* AsSpawned_ByMinLevelAndClass(Client *bot_owner, std::list &sbl, uint8 minlvl, uint8 cls, bool petless = false) { + // This function can be nixed if we can enforce bot level as owner level..and the level check can then be moved to the spell loop in the command function + if (!bot_owner) + return nullptr; + + for (auto bot_iter : sbl) { + if (!MyBots::IsMyBot(bot_owner, bot_iter)) + continue; + if (bot_iter->GetLevel() < minlvl || bot_iter->GetClass() != cls) + continue; + if (petless && bot_iter->GetPet()) + continue; + + return bot_iter; + } + + return nullptr; + } + + static Bot* AsTarget_ByBot(Client *bot_owner) { + if (!bot_owner || !MyBots::IsMyBot(bot_owner, bot_owner->GetTarget())) + return nullptr; + + return bot_owner->GetTarget()->CastToBot(); + } + + static Bot* AsNamed_ByBot(Client *bot_owner, std::string bot_name) { + if (!bot_owner || bot_name.empty()) + return nullptr; + + std::list selectable_bot_list; + MyBots::PopulateSBL_BySpawnedBots(bot_owner, selectable_bot_list); + for (auto bot_iter : selectable_bot_list) { + if (!bot_name.compare(bot_iter->GetCleanName())) + return bot_iter; + } + + return nullptr; + } + + static Bot* Select_ByClass(Client* bot_owner, BCEnum::TType target_type, std::list& sbl, uint8 cls, Mob* target_mob = nullptr, bool petless = false) { + if (!bot_owner || sbl.empty()) + return nullptr; + + for (auto bot_iter : sbl) { + if (!MyBots::IsMyBot(bot_owner, bot_iter)) + continue; + if (bot_iter->GetClass() != cls) + continue; + if (petless && bot_iter->GetPet()) + continue; + if (target_type == BCEnum::TT_GroupV1) { + if (!target_mob) + return nullptr; + else if (bot_iter->GetGroup() != target_mob->GetGroup()) + continue; + } + + return bot_iter; + } + + return nullptr; + } + + static Bot* Select_ByMinLevelAndClass(Client* bot_owner, BCEnum::TType target_type, std::list& sbl, uint8 minlvl, uint8 cls, Mob* target_mob = nullptr, bool petless = false) { + if (!bot_owner || sbl.empty()) + return nullptr; + + for (auto bot_iter : sbl) { + if (!MyBots::IsMyBot(bot_owner, bot_iter)) + continue; + if (bot_iter->GetLevel() < minlvl || bot_iter->GetClass() != cls) + continue; + if (petless && bot_iter->GetPet()) + continue; + if (target_type == BCEnum::TT_GroupV1) { + if (!target_mob) + return nullptr; + else if (bot_iter->GetGroup() != target_mob->GetGroup()) + continue; + } + + return bot_iter; + } + + return nullptr; + } + + // Filters actual 'sbl' list + static void Filter_ByClasses(Client* bot_owner, std::list& sbl, uint16 class_mask) { + sbl.remove_if([bot_owner](Bot* l) { return (!MyBots::IsMyBot(bot_owner, l)); }); + sbl.remove_if([class_mask](const Bot* l) { return (GetPlayerClassBit(l->GetClass()) & (~class_mask)); }); + } + + static void Filter_ByMinLevel(Client* bot_owner, std::list& sbl, uint8 min_level) { + sbl.remove_if([bot_owner](Bot* l) { return (!MyBots::IsMyBot(bot_owner, l)); }); + sbl.remove_if([min_level](const Bot* l) { return (l->GetLevel() < min_level); }); + } + + static void Filter_ByArcher(Client* bot_owner, std::list& sbl) { + sbl.remove_if([bot_owner](Bot* l) { return (!MyBots::IsMyBot(bot_owner, l)); }); + sbl.remove_if([bot_owner](Bot* l) { return (!l->IsBotArcher()); }); + } + + static void Filter_ByHighestSkill(Client* bot_owner, std::list& sbl, SkillUseTypes skill_type, float& skill_value) { + sbl.remove_if([bot_owner](Bot* l) { return (!MyBots::IsMyBot(bot_owner, l)); }); + skill_value = 0.0f; + + float mod_skill_value = 0.0f; + const Bot* skilled_bot = nullptr; + for (auto bot_iter : sbl) { + float base_skill_value = bot_iter->GetSkill(skill_type); + if (base_skill_value == 0.0f) + continue; + + mod_skill_value = base_skill_value; + for (int16 index = EmuConstants::EQUIPMENT_BEGIN; index <= EmuConstants::EQUIPMENT_END; ++index) { + const ItemInst* indexed_item = bot_iter->GetBotItem(index); + if (indexed_item && indexed_item->GetItem()->SkillModType == skill_type) + mod_skill_value += (base_skill_value * (((float)indexed_item->GetItem()->SkillModValue) / 100.0f)); + } + + if (!skilled_bot) { + skill_value = mod_skill_value; + skilled_bot = bot_iter; + } + else if (mod_skill_value > skill_value) { + skill_value = mod_skill_value; + skilled_bot = bot_iter; + } + } + + sbl.remove_if([skilled_bot](const Bot* l) { return (l != skilled_bot); }); + } + + static void Filter_ByHighestPickLock(Client* bot_owner, std::list& sbl, float& pick_lock_value) { + sbl.remove_if([bot_owner](Bot* l) { return (!MyBots::IsMyBot(bot_owner, l)); }); + sbl.remove_if([bot_owner](const Bot* l) { return (l->GetClass() != ROGUE && l->GetClass() != BARD); }); + sbl.remove_if([bot_owner](const Bot* l) { return (l->GetClass() == ROGUE && l->GetLevel() < 5); }); + sbl.remove_if([bot_owner](const Bot* l) { return (l->GetClass() == BARD && l->GetLevel() < 40); }); + + ActionableBots::Filter_ByHighestSkill(bot_owner, sbl, SkillPickLock, pick_lock_value); + } +}; + + +/* + * bot commands go below here + */ +void bot_command_actionable(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_actionable", sep->arg[0], "actionable")) + return; + + c->Message(m_message, "Actionable command arguments:"); + + c->Message(m_usage, "target: selects target as single bot - use ^command' [target] or imply by empty actionable argument"); + c->Message(m_usage, "byname [name]: selects single bot by name"); + c->Message(m_usage, "ownergroup: selects all bots in the owner's group"); + c->Message(m_usage, "botgroup [name]: NEEDS REWORK???"); + c->Message(m_usage, "targetgroup: selects all bots in target's group"); + c->Message(m_usage, "namesgroup [name]: selects all bots in name's group"); + c->Message(m_usage, "healrotation [name]: selects all member and target bots of a heal rotation where name is a member"); + c->Message(m_usage, "healrotationmembers [name]: selects all member bots of a heal rotation where name is a member"); + c->Message(m_usage, "healrotationtargets [name]: selects all target bots of a heal rotation where name is a member"); + c->Message(m_usage, "spawned: selects all spawned bots"); + c->Message(m_usage, "all: selects all spawned bots - argument use indicates en masse database updating"); + + c->Message(m_message, "You may only select your bots as actionable"); +} + +void bot_command_aggressive(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Stance]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Stance) || helper_command_alias_fail(c, "bot_command_aggressive", sep->arg[0], "aggressive")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Stance); + return; + } + const int ab_mask = ActionableBots::ABM_Type1; + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + sbl.remove(nullptr); + + int success_count = 0; + int candidate_count = sbl.size(); + for (auto list_iter : *local_list) { + if (sbl.empty()) + break; + + auto local_entry = list_iter->SafeCastToStance(); + if (helper_spell_check_fail(local_entry)) + continue; + if (local_entry->stance_type != BCEnum::StT_Aggressive) + continue; + + for (auto bot_iter = sbl.begin(); bot_iter != sbl.end(); ) { + Bot* my_bot = *bot_iter; + if (local_entry->caster_class != my_bot->GetClass()) { + ++bot_iter; + continue; + } + if (local_entry->spell_level > my_bot->GetLevel()) { + ++bot_iter; + continue; + } + + my_bot->InterruptSpell(); + if (candidate_count == 1) + Bot::BotGroupSay(my_bot, "Using '%s'", spells[local_entry->spell_id].name); + my_bot->UseDiscipline(local_entry->spell_id, my_bot->GetID()); + ++success_count; + + bot_iter = sbl.erase(bot_iter); + } + } + + c->Message(m_action, "%i of %i bots have used aggressive disciplines", success_count, candidate_count); +} + +void bot_command_attack(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_attack", sep->arg[0], "attack")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [actionable: byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]); + return; + } + const int ab_mask = ActionableBots::ABM_Type2; + + Mob* target_mob = ActionableTarget::AsSingle_ByAttackable(c); + if (!target_mob) { + c->Message(m_fail, "You must an enemy to use this command"); + return; + } + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + + sbl.remove(nullptr); + for (auto bot_iter : sbl) { + bot_iter->WipeHateList(); + bot_iter->AddToHateList(target_mob, 1); + if (!bot_iter->GetPet()) + continue; + + bot_iter->GetPet()->WipeHateList(); + bot_iter->GetPet()->AddToHateList(target_mob, 1); + } + if (sbl.size() == 1) + Bot::BotGroupSay(sbl.front(), "Attacking %s", target_mob->GetCleanName()); + else + c->Message(m_action, "%i of your bots are attacking %s", sbl.size(), target_mob->GetCleanName()); +} + +void bot_command_bind_affinity(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_BindAffinity]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_BindAffinity) || helper_command_alias_fail(c, "bot_command_bind_affinity", sep->arg[0], "bindaffinity")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_BindAffinity); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + for (auto list_iter : *local_list) { + auto local_entry = list_iter; + if (helper_spell_check_fail(local_entry)) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + // Cast effect message is not being generated + if (helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id)) + c->Message(m_action, "Successfully bound %s to this location", target_mob->GetCleanName()); + else + c->Message(m_fail, "Failed to bind %s to this location", target_mob->GetCleanName()); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_bot(Client *c, const Seperator *sep) +{ + const std::list subcommand_list = { + "botappearance", "botcamp", "botclone", "botcreate", "botdelete", "botdetails", "botdyearmor", "botinspectmessage", "botfollowdistance", + "botlist", "botoutofcombat", "botreport", "botspawn", "botstance", "botsummon", "bottogglearcher", "bottogglehelm", "botupdate" + }; + + if (helper_command_alias_fail(c, "bot_command_bot", sep->arg[0], "bot")) + return; + + helper_send_available_subcommands(c, "bot", subcommand_list); +} + +void bot_command_botgroup(Client *c, const Seperator *sep) +{ + const std::list subcommand_list = { + "botgroupaddmember", "botgroupcreate", "botgroupdelete", "botgrouplist", "botgroupload", "botgroupremovemember" + }; + + if (helper_command_alias_fail(c, "bot_command_botgroup", sep->arg[0], "botgroup")) + return; + + helper_send_available_subcommands(c, "bot-group", subcommand_list); +} + +void bot_command_charm(Client *c, const Seperator *sep) +{ + auto local_list = &bot_command_spells[BCEnum::SpT_Charm]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Charm) || helper_command_alias_fail(c, "bot_command_charm", sep->arg[0], "charm")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([option: dire])", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Charm); + return; + } + + bool dire = false; + std::string dire_arg = sep->arg[1]; + if (!dire_arg.compare("dire")) + dire = true; + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToCharm(); + if (helper_spell_check_fail(local_entry)) + continue; + if (local_entry->dire != dire) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, ENEMY); + if (!target_mob) + continue; + if (target_mob->IsCharmed()) { + c->Message(m_fail, "Your is already charmed"); + return; + } + + if (spells[local_entry->spell_id].max[EFFECTIDTOINDEX(1)] < target_mob->GetLevel()) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob, true); + if (!my_bot) + continue; + + uint32 dont_root_before = 0; + if (helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id, true, &dont_root_before)) + target_mob->SetDontRootMeBefore(dont_root_before); + + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_cure(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Cure]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Cure) || helper_command_alias_fail(c, "bot_command_cure", sep->arg[0], "cure")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [ailment: blindness | disease | poison | curse | corruption]", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Cure); + return; + } + + std::string ailment_arg = sep->arg[1]; + + auto ailment_type = BCEnum::AT_None; + if (!ailment_arg.compare("blindness")) + ailment_type = BCEnum::AT_Blindness; + else if (!ailment_arg.compare("disease")) + ailment_type = BCEnum::AT_Disease; + else if (!ailment_arg.compare("poison")) + ailment_type = BCEnum::AT_Poison; + else if (!ailment_arg.compare("curse")) + ailment_type = BCEnum::AT_Curse; + else if (!ailment_arg.compare("corruption")) + ailment_type = BCEnum::AT_Corruption; + + if (ailment_type == BCEnum::AT_None) { + c->Message(m_fail, "You must specify a cure [ailment] to use this command"); + return; + } + + local_list->sort([ailment_type](STBaseEntry* l, STBaseEntry* r) { + auto _l = l->SafeCastToCure(), _r = r->SafeCastToCure(); + if (_l->cure_value[AILMENTIDTOINDEX(ailment_type)] < _r->cure_value[AILMENTIDTOINDEX(ailment_type)]) + return true; + if (_l->cure_value[AILMENTIDTOINDEX(ailment_type)] == _r->cure_value[AILMENTIDTOINDEX(ailment_type)] && spells[_l->spell_id].mana < spells[_r->spell_id].mana) + return true; + if (_l->cure_value[AILMENTIDTOINDEX(ailment_type)] == _r->cure_value[AILMENTIDTOINDEX(ailment_type)] && spells[_l->spell_id].mana == spells[_r->spell_id].mana && _l->cure_total < _r->cure_total) + return true; + + return false; + }); + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToCure(); + if (helper_spell_check_fail(local_entry)) + continue; + if (!local_entry->cure_value[AILMENTIDTOINDEX(ailment_type)]) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_defensive(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Stance]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Stance) || helper_command_alias_fail(c, "bot_command_defensive", sep->arg[0], "defensive")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Stance); + return; + } + const int ab_mask = ActionableBots::ABM_Type1; + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + sbl.remove(nullptr); + + int success_count = 0; + int candidate_count = sbl.size(); + for (auto list_iter : *local_list) { + if (sbl.empty()) + break; + + auto local_entry = list_iter->SafeCastToStance(); + if (helper_spell_check_fail(local_entry)) + continue; + if (local_entry->stance_type != BCEnum::StT_Aggressive) + continue; + + for (auto bot_iter = sbl.begin(); bot_iter != sbl.end(); ) { + Bot* my_bot = *bot_iter; + if (local_entry->caster_class != my_bot->GetClass()) { + ++bot_iter; + continue; + } + if (local_entry->spell_level > my_bot->GetLevel()) { + ++bot_iter; + continue; + } + + my_bot->InterruptSpell(); + if (candidate_count == 1) + Bot::BotGroupSay(my_bot, "Using '%s'", spells[local_entry->spell_id].name); + my_bot->UseDiscipline(local_entry->spell_id, my_bot->GetID()); + ++success_count; + + bot_iter = sbl.erase(bot_iter); + } + } + + c->Message(m_action, "%i of %i bots have used defensive disciplines", success_count, candidate_count); +} + +void bot_command_depart(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Depart]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Depart) || helper_command_alias_fail(c, "bot_command_depart", sep->arg[0], "depart")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [list | destination] ([option: single])", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Depart); + return; + } + + bool single = false; + std::string single_arg = sep->arg[2]; + if (!single_arg.compare("single")) + single = true; + + std::string destination = sep->arg[1]; + if (!destination.compare("list")) { + Bot* my_druid_bot = ActionableBots::AsGroupMember_ByClass(c, c, DRUID); + Bot* my_wizard_bot = ActionableBots::AsGroupMember_ByClass(c, c, WIZARD); + helper_command_depart_list(c, my_druid_bot, my_wizard_bot, local_list, single); + return; + } + else if (destination.empty()) { + c->Message(m_fail, "A [destination] or [list] argument is required to use this command"); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToDepart(); + if (helper_spell_check_fail(local_entry)) + continue; + if (local_entry->single != single) + continue; + if (destination.compare(spells[local_entry->spell_id].teleport_zone)) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_escape(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Escape]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Escape) || helper_command_alias_fail(c, "bot_command_escape", sep->arg[0], "escape")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([option: lesser])", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Escape); + return; + } + + bool use_lesser = false; + if (!strcasecmp(sep->arg[1], "lesser")) + use_lesser = true; + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToEscape(); + if (helper_spell_check_fail(local_entry)) + continue; + if (local_entry->lesser != use_lesser) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_find_aliases(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_find_aliases", sep->arg[0], "findaliases")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [alias | command]", sep->arg[0]); + return; + } + + auto find_iter = bot_command_aliases.find(sep->arg[1]); + if (find_iter == bot_command_aliases.end()) { + c->Message(m_fail, "No bot commands or aliases match '%s'", sep->arg[1]); + return; + } + + auto command_iter = bot_command_list.find(find_iter->second); + if (find_iter->second.empty() || command_iter == bot_command_list.end()) { + c->Message(m_unknown, "An unknown condition has occurred..."); + return; + } + + c->Message(m_message, "Available bot command aliases for '%s':", command_iter->first.c_str()); + + int bot_command_aliases_shown = 0; + for (auto alias_iter : bot_command_aliases) { + if (strcasecmp(find_iter->second.c_str(), alias_iter.second.c_str()) || c->Admin() < command_iter->second->access) + continue; + + c->Message(m_usage, "%c%s", BOT_COMMAND_CHAR, alias_iter.first.c_str()); + ++bot_command_aliases_shown; + } + c->Message(m_message, "%d bot command alias%s listed.", bot_command_aliases_shown, bot_command_aliases_shown != 1 ? "es" : ""); +} + +void bot_command_follow(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_follow", sep->arg[0], "follow")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([option: reset]) [actionable: byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]); + return; + } + const int ab_mask = ActionableBots::ABM_Type2; + + bool reset = false; + int ab_arg = 1; + int name_arg = 2; + Mob* target_mob = nullptr; + + std::string reset_arg = sep->arg[1]; + if (!reset_arg.compare("reset")) { + reset = true; + ab_arg = 2; + name_arg = 3; + } + else { + if (c->GetTarget()) { + if (c->IsAttackAllowed(c->GetTarget())) { + c->Message(m_fail, "You must a friendly mob to use this command"); + return; + } + target_mob = c->GetTarget(); + } + else { + target_mob = c; + } + } + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[name_arg]) == ActionableBots::ABT_None) + return; + + sbl.remove(nullptr); + for (auto bot_iter : sbl) { + bot_iter->WipeHateList(); + auto my_group = bot_iter->GetGroup(); + if (my_group) { + if (reset) { + if (!my_group->GetLeader() || my_group->GetLeader() == bot_iter) + bot_iter->SetFollowID(c->GetID()); + else + bot_iter->SetFollowID(my_group->GetLeader()->GetID()); + } + else { + bot_iter->SetFollowID(target_mob->GetID()); + } + } + else { + bot_iter->SetFollowID(0); + } + if (!bot_iter->GetPet()) + continue; + + bot_iter->GetPet()->WipeHateList(); + bot_iter->GetPet()->SetFollowID(bot_iter->GetID()); + } + if (sbl.size() == 1) { + Mob* follow_mob = entity_list.GetMob(sbl.front()->GetFollowID()); + Bot::BotGroupSay(sbl.front(), "Following %s", ((follow_mob) ? (follow_mob->GetCleanName()) : ("'nullptr'"))); + } + else { + if (reset) + c->Message(m_action, "%i of your bots are following their default assignments", sbl.size()); + else + c->Message(m_action, "%i of your bots are following %s", sbl.size(), target_mob->GetCleanName()); + } +} + +void bot_command_guard(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_guard", sep->arg[0], "guard")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [actionable: target | byname | ownergroup | botgroup | namesgroup | healrotation | spawned] ([actionable_name])", sep->arg[0]); + return; + } + const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_Type2); + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + + sbl.remove(nullptr); + for (auto bot_iter : sbl) { + bot_iter->WipeHateList(); + bot_iter->SetFollowID(0); + if (!bot_iter->GetPet()) + continue; + + bot_iter->GetPet()->WipeHateList(); + bot_iter->GetPet()->SetFollowID(0); + } + if (sbl.size() == 1) + Bot::BotGroupSay(sbl.front(), "Guarding this position"); + else + c->Message(m_action, "%i of your bots are guarding their positions", sbl.size()); +} + +void bot_command_heal_rotation(Client *c, const Seperator *sep) +{ + const std::list subcommand_list = { + "healrotationadaptivetargeting", "healrotationaddmember", "healrotationaddtarget", "healrotationadjustcritical", "healrotationadjustsafe", + "healrotationcastoverride", "healrotationchangeinterval", "healrotationcleartargets", "healrotationcreate", "healrotationfastheals", + "healrotationlist", "healrotationremovemember", "healrotationremovetarget", "healrotationresetlimits", "healrotationstart", "healrotationstop" + }; + + if (helper_command_alias_fail(c, "bot_command_heal_rotation", sep->arg[0], "healrotation")) + return; + +#if (EQDEBUG >= 12) + while (c->Admin() >= 250) { + if (strcasecmp(sep->arg[1], "shone")) { break; } + Bot* my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot || !(my_bot->IsHealRotationMember())) { break; } + auto tlist = (*my_bot->MemberOfHealRotation())->TargetList(); + if (tlist->empty()) { break; } + for (auto tlist_iter : *tlist) { + if (tlist_iter) + tlist_iter->SetHP((tlist_iter->GetMaxHP() / 100 + 1)); + } + return; + } +#endif + + helper_send_available_subcommands(c, "bot heal rotation", subcommand_list); +} + +void bot_command_help(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_help", sep->arg[0], "help")) + return; + + c->Message(m_message, "Available EQEMu bot commands:"); + + int bot_commands_shown = 0; + for (auto command_iter : bot_command_list) { + if (sep->arg[1][0] && command_iter.first.find(sep->arg[1]) == std::string::npos) + continue; + if (c->Admin() < command_iter.second->access) + continue; + + c->Message(m_usage, "%c%s - %s", BOT_COMMAND_CHAR, command_iter.first.c_str(), command_iter.second->desc == nullptr ? "[no description]" : command_iter.second->desc); + ++bot_commands_shown; + } + c->Message(m_message, "%d bot command%s listed.", bot_commands_shown, bot_commands_shown != 1 ? "s" : ""); + c->Message(m_note, "type %ccommand [help | usage] for more information", BOT_COMMAND_CHAR); +} + +void bot_command_hold(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_hold", sep->arg[0], "hold")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([actionable: ] ([actionable_name]))", sep->arg[0]); + return; + } + const int ab_mask = ActionableBots::ABM_NoFilter; + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + + sbl.remove(nullptr); + for (auto bot_iter : sbl) + bot_iter->SetPauseAI(true); + + c->Message(m_action, "%i of your bots %s suspended", sbl.size(), ((sbl.size() != 1) ? ("are") : ("is"))); +} + +void bot_command_identify(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Identify]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Identify) || helper_command_alias_fail(c, "bot_command_identify", sep->arg[0], "identify")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Identify); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter; + if (helper_spell_check_fail(local_entry)) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_inventory(Client *c, const Seperator *sep) +{ + const std::list subcommand_list = { "inventorygive", "inventorylist", "inventoryremove" }; + + if (helper_command_alias_fail(c, "bot_command_inventory", sep->arg[0], "inventory")) + return; + + helper_send_available_subcommands(c, "bot inventory", subcommand_list); +} + +void bot_command_invisibility(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Invisibility]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Invisibility) || helper_command_alias_fail(c, "bot_command_invisibility", sep->arg[0], "invisibility")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [invisibility: living | undead | animal | see]", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Invisibility); + return; + } + + std::string invisibility = sep->arg[1]; + + BCEnum::IType invisibility_type = BCEnum::IT_None; + if (!invisibility.compare("living")) + invisibility_type = BCEnum::IT_Living; + else if (!invisibility.compare("undead")) + invisibility_type = BCEnum::IT_Undead; + else if (!invisibility.compare("animal")) + invisibility_type = BCEnum::IT_Animal; + else if (!invisibility.compare("see")) + invisibility_type = BCEnum::IT_See; + + if (invisibility_type == BCEnum::IT_None) { + c->Message(m_fail, "You must specify an [invisibility]"); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToInvisibility(); + if (helper_spell_check_fail(local_entry)) + continue; + if (local_entry->invis_type != invisibility_type) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_levitation(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Levitation]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Levitation) || helper_command_alias_fail(c, "bot_command_levitation", sep->arg[0], "levitation")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Levitation); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter; + if (helper_spell_check_fail(local_entry)) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_lull(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Lull]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Lull) || helper_command_alias_fail(c, "bot_command_lull", sep->arg[0], "lull")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Lull); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + for (auto list_iter : *local_list) { + auto local_entry = list_iter; + if (helper_spell_check_fail(local_entry)) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, ENEMY); + if (!target_mob) + continue; + + //if (spells[local_entry->spell_id].max[EFFECTIDTOINDEX(3)] && spells[local_entry->spell_id].max[EFFECTIDTOINDEX(3)] < target_mob->GetLevel()) + // continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + uint32 dont_root_before = 0; + if (helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id, true, &dont_root_before)) + target_mob->SetDontRootMeBefore(dont_root_before); + + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_mesmerize(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Mesmerize]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Mesmerize) || helper_command_alias_fail(c, "bot_command_mesmerize", sep->arg[0], "mesmerize")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Mesmerize); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + for (auto list_iter : *local_list) { + auto local_entry = list_iter; + if (helper_spell_check_fail(local_entry)) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, ENEMY); + if (!target_mob) + continue; + + if (spells[local_entry->spell_id].max[EFFECTIDTOINDEX(1)] < target_mob->GetLevel()) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + uint32 dont_root_before = 0; + if (helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id, true, &dont_root_before)) + target_mob->SetDontRootMeBefore(dont_root_before); + + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_movement_speed(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_MovementSpeed]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_MovementSpeed) || helper_command_alias_fail(c, "bot_command_movement_speed", sep->arg[0], "movementspeed")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([group])", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_MovementSpeed); + return; + } + + bool group = false; + std::string group_arg = sep->arg[1]; + if (!group_arg.compare("group")) + group = true; + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToMovementSpeed(); + if (helper_spell_check_fail(local_entry)) + continue; + if (local_entry->group != group) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_pet(Client *c, const Seperator *sep) +{ + const std::list subcommand_list = { "petremove", "petsettype" }; + + if (helper_command_alias_fail(c, "bot_command_pet", sep->arg[0], "pet")) + return; + + helper_send_available_subcommands(c, "bot pet", subcommand_list); +} + +void bot_command_pick_lock(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_pick_lock", sep->arg[0], "picklock")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s", sep->arg[0]); + c->Message(m_note, "requires one of the following bot classes:"); + c->Message(m_message, "Rogue(5) or Bard(40)"); + return; + } + + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + float pick_lock_value = 0.0f; + ActionableBots::Filter_ByHighestPickLock(c, sbl, pick_lock_value); + if (sbl.empty()) { + c->Message(m_fail, "No bots are capable of performing this action"); + return; + } + + Bot* my_bot = sbl.front(); + + my_bot->InterruptSpell(); + Bot::BotGroupSay(my_bot, "Attempting to pick the lock.."); + + std::list door_list; + entity_list.GetDoorsList(door_list); + + int door_count = 0, open_count = 0; + for (auto door_iter : door_list) { + if (!door_iter || door_iter->IsDoorOpen()) + continue; + + glm::tvec4 diff = (c->GetPosition() - door_iter->GetPosition()); + + float curdist = ((diff.x * diff.x) + (diff.y * diff.y)); + float curelev = (diff.z * diff.z); +#if (EQDEBUG >= 11) + if (curdist <= 130 && curelev <= 65 && curelev >= 25) // 2D limit is '130' (x^2 + y^2), 1D theoretically should be '65' (z^2) + Log.Out(Logs::Detail, Logs::Doors, "bot_command_pick_lock(): DoorID: %i - Elevation difference failure within theoretical limit (%f <= 65.0)", door_iter->GetDoorID(), curelev); +#endif + if (curelev >= 25 || curdist > 130) // changed curelev from '10' to '25' - requiring diff.z to be less than '5' + continue; + + ++door_count; + if (pick_lock_value >= door_iter->GetLockpick()) { + door_iter->ForceOpen(my_bot); + ++open_count; + } + else { + Bot::BotGroupSay(my_bot, "I am not skilled enough for this lock..."); + } + } + c->Message(m_action, "%i door%s attempted - %i door%s successful", door_count, ((door_count != 1) ? ("s") : ("")), open_count, ((open_count != 1) ? ("s") : (""))); +} + +void bot_command_pull(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_pull", sep->arg[0], "pull")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s", sep->arg[0]); + return; + } + int ab_mask = ActionableBots::ABM_OwnerGroup; // existing behavior - need to add c->IsGrouped() check and modify code if different behavior is desired + + std::list sbl; + if (ActionableBots::PopulateSBL(c, "ownergroup", sbl, ab_mask) == ActionableBots::ABT_None) + return; + sbl.remove(nullptr); + + auto target_mob = ActionableTarget::VerifyEnemy(c, BCEnum::TT_Single); + if (!target_mob) { + c->Message(m_fail, "Your current target is not attackable"); + return; + } + + Bot* bot_puller = nullptr; + for (auto bot_iter : sbl) { + if (!bot_iter->IsArcheryRange(target_mob)) + continue; + + Bot::BotGroupSay(bot_iter, "Attempting to pull %s..", target_mob->GetCleanName()); + bot_iter->InterruptSpell(); + bot_iter->BotRangedAttack(target_mob); + bot_puller = bot_iter; + break; + } + + helper_no_available_bots(c, bot_puller); +} + +void bot_command_release(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_release", sep->arg[0], "release")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([actionable: ] ([actionable_name]))", sep->arg[0]); + return; + } + const int ab_mask = ActionableBots::ABM_NoFilter; + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + + sbl.remove(nullptr); + for (auto bot_iter : sbl) { + bot_iter->WipeHateList(); + bot_iter->SetPauseAI(false); + } + + c->Message(m_action, "%i of your bots %s unsuspended", sbl.size(), ((sbl.size() != 1) ? ("are") : ("is"))); +} + +void bot_command_resistance(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Resistance]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Resistance) || helper_command_alias_fail(c, "bot_command_resistance", sep->arg[0], "resistance")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [resistance: fire | cold | poison | disease | magic | corruption]", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Resistance); + return; + } + + std::string resistance_arg = sep->arg[1]; + + auto resistance_type = BCEnum::RT_None; + if (!resistance_arg.compare("fire")) + resistance_type = BCEnum::RT_Fire; + else if (!resistance_arg.compare("cold")) + resistance_type = BCEnum::RT_Cold; + else if (!resistance_arg.compare("poison")) + resistance_type = BCEnum::RT_Poison; + else if (!resistance_arg.compare("disease")) + resistance_type = BCEnum::RT_Disease; + else if (!resistance_arg.compare("magic")) + resistance_type = BCEnum::RT_Magic; + else if (!resistance_arg.compare("corruption")) + resistance_type = BCEnum::RT_Corruption; + + if (resistance_type == BCEnum::RT_None) { + c->Message(m_fail, "You must specify a [resistance]"); + return; + } + + local_list->sort([resistance_type](STBaseEntry* l, STBaseEntry* r) { + auto _l = l->SafeCastToResistance(), _r = r->SafeCastToResistance(); + if (_l->resist_value[RESISTANCEIDTOINDEX(resistance_type)] > _r->resist_value[RESISTANCEIDTOINDEX(resistance_type)]) + return true; + if (_l->resist_value[RESISTANCEIDTOINDEX(resistance_type)] == _r->resist_value[RESISTANCEIDTOINDEX(resistance_type)] && spells[_l->spell_id].mana < spells[_r->spell_id].mana) + return true; + if (_l->resist_value[RESISTANCEIDTOINDEX(resistance_type)] == _r->resist_value[RESISTANCEIDTOINDEX(resistance_type)] && spells[_l->spell_id].mana == spells[_r->spell_id].mana && _l->resist_total > _r->resist_total) + return true; + + return false; + }); + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToResistance(); + if (helper_spell_check_fail(local_entry)) + continue; + if (!local_entry->resist_value[RESISTANCEIDTOINDEX(resistance_type)]) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_resurrect(Client *c, const Seperator *sep) +{ + // Obscure bot spell code prohibits the aoe portion from working correctly... + + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Resurrect]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Resurrect) || helper_command_alias_fail(c, "bot_command_resurrect", sep->arg[0], "resurrect")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + //c->Message(m_usage, "usage: %s ([option: aoe])", sep->arg[0]); + c->Message(m_usage, "usage: %s", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Resurrect); + return; + } + + bool aoe = false; + //std::string aoe_arg = sep->arg[1]; + //if (!aoe_arg.compare("aoe")) + // aoe = true; + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToResurrect(); + if (helper_spell_check_fail(local_entry)) + continue; + //if (local_entry->aoe != aoe) + // continue; + if (local_entry->aoe) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + //if (!target_mob && !local_entry->aoe) + // continue; + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + //if (local_entry->aoe) + // target_mob = my_bot; + + uint32 dont_root_before = 0; + if (helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id, true, &dont_root_before)) + target_mob->SetDontRootMeBefore(dont_root_before); + + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_rune(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Rune]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Rune) || helper_command_alias_fail(c, "bot_command_rune", sep->arg[0], "rune")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Rune); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter; + if (helper_spell_check_fail(local_entry)) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_send_home(Client *c, const Seperator *sep) +{ + // Obscure bot spell code prohibits the aoe portion from working correctly... + + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_SendHome]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_SendHome) || helper_command_alias_fail(c, "bot_command_send_home", sep->arg[0], "sendhome")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([option: group])", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_SendHome); + return; + } + + bool group = false; + std::string group_arg = sep->arg[1]; + if (!group_arg.compare("group")) + group = true; + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToSendHome(); + if (helper_spell_check_fail(local_entry)) + continue; + if (local_entry->group != group) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_size(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Size]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Size) || helper_command_alias_fail(c, "bot_command_size", sep->arg[0], "size")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [grow | shrink]", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Size); + return; + } + + std::string size_arg = sep->arg[1]; + auto size_type = BCEnum::SzT_Reduce; + if (!size_arg.compare("grow")) { + size_type = BCEnum::SzT_Enlarge; + } + else if (size_arg.compare("shrink")) { + c->Message(m_fail, "This command requires a [grow | shrink] argument"); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToSize(); + if (helper_spell_check_fail(local_entry)) + continue; + if (local_entry->size_type != size_type) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_summon_corpse(Client *c, const Seperator *sep) +{ + // Same methodology as old command..but, does not appear to work... (note: didn't work there, either...) + + // temp + c->Message(m_fail, "This command is currently unavailable..."); + return; + + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_SummonCorpse]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_SummonCorpse) || helper_command_alias_fail(c, "bot_command_summon_corpse", sep->arg[0], "summoncorpse")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_SummonCorpse); + return; + } + + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter; + if (helper_spell_check_fail(local_entry)) + continue; + + auto target_mob = ActionableTarget::AsSingle_ByPlayer(c); + if (!target_mob) + continue; + + if (spells[local_entry->spell_id].base[EFFECTIDTOINDEX(1)] < target_mob->GetLevel()) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_command_taunt(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_taunt", sep->arg[0], "taunt")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotationtargets | spawned] ([actionable_name]))", sep->arg[0]); + return; + } + const int ab_mask = ActionableBots::ABM_Type1; + + std::string arg1 = sep->arg[1]; + + bool taunt_state = false; + bool toggle_taunt = true; + int ab_arg = 1; + if (!arg1.compare("on")) { + taunt_state = true; + toggle_taunt = false; + ab_arg = 2; + } + else if (!arg1.compare("off")) { + toggle_taunt = false; + ab_arg = 2; + } + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None) + return; + sbl.remove(nullptr); + + int taunting_count = 0; + for (auto bot_iter : sbl) { + if (!bot_iter->GetSkill(SkillTaunt)) + continue; + + if (toggle_taunt) + bot_iter->SetTaunting(!bot_iter->IsTaunting()); + else + bot_iter->SetTaunting(taunt_state); + + if (sbl.size() == 1) + Bot::BotGroupSay(bot_iter, "I am %s taunting", bot_iter->IsTaunting() ? "now" : "no longer"); + + ++taunting_count; + } + + if (taunting_count) { + if (toggle_taunt) + c->Message(m_action, "%i of your bots %s toggled their taunting state", taunting_count, ((taunting_count != 1) ? ("have") : ("has"))); + else + c->Message(m_action, "%i of your bots %s %s taunting", taunting_count, ((taunting_count != 1) ? ("have") : ("has")), ((taunt_state) ? ("started") : ("stopped"))); + } + else { + c->Message(m_fail, "None of your bots are able to taunt"); + } +} + +void bot_command_track(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_command_track", sep->arg[0], "track")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s (Ranger: [option=all: all | rare | local])", sep->arg[0]); + c->Message(m_note, "requires one of the following bot classes:"); + c->Message(m_message, "Ranger(1), Druid(20) or Bard(35)"); + return; + } + + std::string tracking_scope = sep->arg[1]; + + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + uint16 class_mask = (PLAYER_CLASS_RANGER_BIT | PLAYER_CLASS_DRUID_BIT | PLAYER_CLASS_BARD_BIT); + ActionableBots::Filter_ByClasses(c, sbl, class_mask); + + Bot* my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 1, RANGER); + if (tracking_scope.empty()) { + if (!my_bot) + my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 20, DRUID); + if (!my_bot) + my_bot = ActionableBots::AsSpawned_ByMinLevelAndClass(c, sbl, 35, BARD); + } + if (!my_bot) { + c->Message(m_fail, "No bots are capable of performing this action"); + return; + } + + int base_distance = 0; + bool track_named = false; + std::string tracking_msg; + switch (my_bot->GetClass()) { + case RANGER: + if (!tracking_scope.compare("local")) { + base_distance = 30; + tracking_msg = "Local tracking..."; + } + else if (!tracking_scope.compare("rare")) { + base_distance = 80; + bool track_named = true; + tracking_msg = "Master tracking..."; + } + else { // default to 'all' + base_distance = 80; + tracking_msg = "Advanced tracking..."; + } + break; + case DRUID: + base_distance = 30; + tracking_msg = "Local tracking..."; + break; + case BARD: + base_distance = 20; + tracking_msg = "Near tracking..."; + break; + default: + return; + } + if (!base_distance) { + c->Message(m_unknown, "An unknown codition has occurred"); + return; + } + + my_bot->InterruptSpell(); + Bot::BotGroupSay(my_bot, tracking_msg.c_str()); + entity_list.ShowSpawnWindow(c, (c->GetLevel() * base_distance), track_named); +} + +void bot_command_water_breathing(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_WaterBreathing]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_WaterBreathing) || helper_command_alias_fail(c, "bot_command_water_breathing", sep->arg[0], "waterbreathing")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_WaterBreathing); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter; + if (helper_spell_check_fail(local_entry)) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + + +/* + * bot subcommands go below here + */ +void bot_subcommand_bot_appearance(Client *c, const Seperator *sep) +{ + const std::list subcommand_list = { + "botbeardcolor", "botbeardstyle", "botdetails", "boteyes", "botface", + "bothaircolor", "bothairstyle", "botheritage", "bottattoo", "botwoad" + }; + + if (helper_command_alias_fail(c, "bot_subcommand_bot_appearance", sep->arg[0], "botappearance")) + return; + + helper_send_available_subcommands(c, "bot appearance", subcommand_list); +} + +void bot_subcommand_bot_beard_color(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_beard_color", sep->arg[0], "botbeardcolor")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [value: 0-n] (Dwarves or male bots only)", sep->arg[0]); + c->Message(m_note, "note: Actual limit is filter-based"); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + + if (!sep->IsNumber(1)) { + c->Message(m_fail, "A numeric [value] is required to use this command"); + return; + } + + uint8 uvalue = atoi(sep->arg[1]); + + auto fail_type = BCEnum::AFT_None; + if (my_bot->GetGender() != MALE && my_bot->GetRace() != DWARF) + fail_type = BCEnum::AFT_GenderRace; + else if (!PlayerAppearance::IsValidBeardColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + fail_type = BCEnum::AFT_Value; + else + my_bot->SetBeardColor(uvalue); + + if (helper_bot_appearance_fail(c, my_bot, fail_type, "beard color")) + return; + + helper_bot_appearance_form_final(c, my_bot); +} + +void bot_subcommand_bot_beard_style(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_beard_style", sep->arg[0], "botbeardstyle")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [value: 0-n] (Dwarves or male bots only)", sep->arg[0]); + c->Message(m_note, "note: Actual limit is filter-based"); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + + if (!sep->IsNumber(1)) { + c->Message(m_fail, "A numeric [value] is required to use this command"); + return; + } + + uint8 uvalue = atoi(sep->arg[1]); + + auto fail_type = BCEnum::AFT_None; + if (my_bot->GetGender() != MALE && my_bot->GetRace() != DWARF) + fail_type = BCEnum::AFT_GenderRace; + else if (!PlayerAppearance::IsValidBeard(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + fail_type = BCEnum::AFT_Value; + else + my_bot->SetBeard(uvalue); + + if (helper_bot_appearance_fail(c, my_bot, fail_type, "beard style")) + return; + + helper_bot_appearance_form_final(c, my_bot); +} + +void bot_subcommand_bot_camp(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_camp", sep->arg[0], "botcamp")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + return; + } + const int ab_mask = ActionableBots::ABM_NoFilter; + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + + for (auto bot_iter : sbl) + bot_iter->Camp(); +} + +void bot_subcommand_bot_clone(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_clone", sep->arg[0], "botclone")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [clone_name]", sep->arg[0]); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + if (!my_bot->GetBotID()) { + c->Message(m_unknown, "An unknown error has occured - BotName: %s, BotID: %u", my_bot->GetCleanName(), my_bot->GetBotID()); + Log.Out(Logs::General, Logs::Commands, "bot_command_clone(): - Error: Active bot reported invalid ID (BotName: %s, BotID: %u, OwnerName: %s, OwnerID: %u, AcctName: %s, AcctID: %u)", + my_bot->GetCleanName(), my_bot->GetBotID(), c->GetCleanName(), c->CharacterID(), c->AccountName(), c->AccountID()); + return; + } + + if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) { + c->Message(m_fail, "You must [name] your bot clone"); + return; + } + std::string bot_name = sep->arg[1]; + + if (!Bot::IsValidName(bot_name)) { + c->Message(m_fail, "'%s' is an invalid name. You may only use characters 'A-Z', 'a-z' and '_'", bot_name.c_str()); + return; + } + + std::string TempErrorMessage; + + if (!Bot::IsBotNameAvailable(bot_name.c_str(), &TempErrorMessage)) { + if (!TempErrorMessage.empty()) + c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + c->Message(m_fail, "The name %s is already being used. Please choose a different name", bot_name.c_str()); + return; + } + + uint32 mbc = RuleI(Bots, CreationLimit); + if (Bot::CreatedBotCount(c->CharacterID(), &TempErrorMessage) >= mbc) { + if (!TempErrorMessage.empty()) + c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + c->Message(m_fail, "You have reached the maximum limit of %i bots", mbc); + return; + } + + auto clone_id = botdb.Clone(c->CharacterID(), my_bot->GetBotID(), bot_name.c_str()); + if (!clone_id) { + c->Message(m_fail, "Clone creation of bot '%s' failed...", my_bot->GetCleanName()); + return; + } + + if (!botdb.CloneInventory(c->CharacterID(), my_bot->GetBotID(), clone_id)) { + c->Message(m_fail, "Inventory import for bot clone '%s' failed...", bot_name.c_str()); + return; + } + + c->Message(m_action, "Bot '%s' was successfully cloned to bot '%s'", my_bot->GetCleanName(), bot_name.c_str()); +} + +void bot_subcommand_bot_create(Client *c, const Seperator *sep) +{ + const std::string msg_class = StringFormat("class: %u(WAR), %u(CLR), %u(PAL), %u(RNG), %u(SHD), %u(DRU), %u(MNK), %u(BRD), %u(ROG), %u(SHM), %u(NEC), %u(WIZ), %u(MAG), %u(ENC), %u(BST), %u(BER)", + WARRIOR, CLERIC, PALADIN, RANGER, SHADOWKNIGHT, DRUID, MONK, BARD, ROGUE, SHAMAN, NECROMANCER, WIZARD, MAGICIAN, ENCHANTER, BEASTLORD, BERSERKER); + const std::string msg_race = StringFormat("race: %u(HUM), %u(BAR), %u(ERU), %u(ELF), %u(HIE), %u(DEF), %u(HEF), %u(DWF), %u(TRL), %u(OGR), %u(HFL), %u(GNM), %u(IKS), %u(VAH), %u(FRG), %u(DRK)", + HUMAN, BARBARIAN, ERUDITE, WOOD_ELF, HIGH_ELF, DARK_ELF, HALF_ELF, DWARF, TROLL, OGRE, HALFLING, GNOME, IKSAR, VAHSHIR, FROGLOK, DRAKKIN); + const std::string msg_gender = StringFormat("gender: %u(M), %u(F)", MALE, FEMALE); + + if (helper_command_alias_fail(c, "bot_subcommand_bot_create", sep->arg[0], "botcreate")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [bot_name] [bot_class] [bot_race] [bot_gender]", sep->arg[0]); + c->Message(m_note, msg_class.c_str()); + c->Message(m_note, msg_race.c_str()); + c->Message(m_note, msg_gender.c_str()); + return; + } + + if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) { + c->Message(m_fail, "You must [name] your bot"); + return; + } + std::string bot_name = sep->arg[1]; + + if (sep->arg[2][0] == '\0' || !sep->IsNumber(2)) { + c->Message(m_fail, msg_class.c_str()); + return; + } + uint8 bot_class = atoi(sep->arg[2]); + + if (sep->arg[3][0] == '\0' || !sep->IsNumber(3)) { + c->Message(m_fail, msg_race.c_str()); + return; + } + uint16 bot_race = atoi(sep->arg[3]); + + if (sep->arg[4][0] == '\0') { + c->Message(m_fail, msg_gender.c_str()); + return; + } + uint8 bot_gender = atoi(sep->arg[4]); + + helper_bot_create(c, bot_name, bot_class, bot_race, bot_gender); +} + +void bot_subcommand_bot_delete(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_delete", sep->arg[0], "botdelete")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s", sep->arg[0]); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + + std::string TempErrorMessage; + + my_bot->DeleteBot(&TempErrorMessage); + if (!TempErrorMessage.empty()) { + c->Message(m_unknown, "Failed to delete '%s' due to database error: %s", my_bot->GetCleanName(), TempErrorMessage.c_str()); + return; + } + + auto bid = my_bot->GetBotID(); + std::string bot_name = my_bot->GetCleanName(); + + my_bot->Camp(false); + + c->Message(m_action, "Successfully deleted bot '%s' (id: %i)", bot_name.c_str(), bid); +} + +void bot_subcommand_bot_details(Client *c, const Seperator *sep) +{ + // TODO: Trouble-shoot model update issue + + if (helper_command_alias_fail(c, "bot_subcommand_bot_details", sep->arg[0], "botdetails")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [value: 0-n] (Drakkin bots only)", sep->arg[0]); + c->Message(m_note, "note: Actual limit is filter-based"); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + + if (!sep->IsNumber(1)) { + c->Message(m_fail, "A numeric [value] is required to use this command"); + return; + } + + uint32 uvalue = atoi(sep->arg[1]); + + auto fail_type = BCEnum::AFT_None; + if (my_bot->GetRace() != DRAKKIN) + fail_type = BCEnum::AFT_Race; + else if (!PlayerAppearance::IsValidDetail(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + fail_type = BCEnum::AFT_Value; + else + my_bot->SetDrakkinDetails(uvalue); + + if (helper_bot_appearance_fail(c, my_bot, fail_type, "details")) + return; + + helper_bot_appearance_form_final(c, my_bot); +} + +void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) +{ + // TODO: Trouble-shoot model update issue + + const std::string msg_matslot = StringFormat("mat_slot: %c(All), %i(Head), %i(Chest), %i(Arms), %i(Wrists), %i(Hands), %i(Legs), %i(Feet)", + '*', MaterialHead, MaterialChest, MaterialArms, MaterialWrist, MaterialHands, MaterialLegs, MaterialFeet); + + if (helper_command_alias_fail(c, "bot_subcommand_bot_dye_armor", sep->arg[0], "botdyearmor")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [mat_slot] [red: 0-255] [green: 0-255] [blue: 0-255] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(m_note, msg_matslot.c_str()); + return; + } + const int ab_mask = ActionableBots::ABM_NoFilter; + + uint8 material_slot = _MaterialInvalid; + int16 slot_id = INVALID_INDEX; + + bool dye_all = (sep->arg[1][0] == '*'); + if (!dye_all) { + material_slot = atoi(sep->arg[1]); + slot_id = Inventory::CalcSlotFromMaterial(material_slot); + + if (!sep->IsNumber(1) || slot_id == INVALID_INDEX || material_slot > MaterialFeet) { + c->Message(m_fail, "Valid [mat_slot]s for this command are:"); + c->Message(m_fail, msg_matslot.c_str()); + return; + } + } + + uint32 red_value = atoi(sep->arg[2]); + if (!sep->IsNumber(2) || red_value > 255) { + c->Message(m_fail, "Valid [red] values for this command are [0-255]"); + return; + } + + uint32 green_value = atoi(sep->arg[3]); + if (!sep->IsNumber(3) || green_value > 255) { + c->Message(m_fail, "Valid [green] values for this command are [0-255]"); + return; + } + + uint32 blue_value = atoi(sep->arg[4]); + if (!sep->IsNumber(4) || blue_value > 255) { + c->Message(m_fail, "Valid [blue] values for this command are [0-255]"); + return; + } + + uint32 rgb_value = ((0xFF) | (red_value << 16) | (green_value << 8) | (blue_value)); // watch the leading '(0xFF) | ' + + std::list sbl; + auto ab_type = ActionableBots::PopulateSBL(c, sep->arg[5], sbl, ab_mask); + if (ab_type == ActionableBots::ABT_None) + return; + + for (auto bot_iter : sbl) { + if (!bot_iter) + continue; + + if (!bot_iter->DyeArmor(slot_id, rgb_value, dye_all, (ab_type != ActionableBots::ABT_All))) { + c->Message(m_fail, "Failed to change armor color for '%s' due to unknown cause", bot_iter->GetCleanName()); + return; + } + + //if (dye_all) + // helper_bot_appearance_form_update(bot_iter); + } + + if (ab_type == ActionableBots::ABT_All) { + bool action_success = false; + if (dye_all) + action_success = botdb.SetAllArmorColors(c->CharacterID(), rgb_value); + else + action_success = botdb.SetAllArmorColorBySlot(c->CharacterID(), slot_id, rgb_value); + + if (!action_success) + c->Message(m_unknown, "Failed to save dye armor changes for your bots due to unknown cause"); + } +} + +void bot_subcommand_bot_eyes(Client *c, const Seperator *sep) +{ + // TODO: Trouble-shoot model update issue + + // not sure if left/right bias is allowed in pc-type entities (something is keeping them from being different) + if (helper_command_alias_fail(c, "bot_subcommand_bot_eyes", sep->arg[0], "boteyes")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + //c->Message(m_usage, "usage: %s [value:0-n] ([option: left | right])", sep->arg[0]); + c->Message(m_usage, "usage: %s [value: 0-n]", sep->arg[0]); + c->Message(m_note, "note: Actual limit is filter-based"); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + + if (!sep->IsNumber(1)) { + c->Message(m_fail, "A numeric [value] is required to use this command"); + return; + } + + uint8 uvalue = atoi(sep->arg[1]); + + //uint8 eye_bias = 0; + //std::string arg2 = sep->arg[2]; + //if (!arg2.compare("left")) + // eye_bias = 1; + //else if (!arg2.compare("right")) + // eye_bias = 2; + + auto fail_type = BCEnum::AFT_None; + if (!PlayerAppearance::IsValidEyeColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) { + fail_type = BCEnum::AFT_Value; + } + else { + //if (eye_bias == 1) { + // my_bot->SetEyeColor1(uvalue); + //} + //else if (eye_bias == 2) { + // my_bot->SetEyeColor2(uvalue); + //} + //else { + my_bot->SetEyeColor1(uvalue); + my_bot->SetEyeColor2(uvalue); + //} + } + + if (helper_bot_appearance_fail(c, my_bot, fail_type, "eyes")) + return; + + c->Message(m_action, "This feature will update the next time your bot is spawned"); + //helper_bot_appearance_form_final(c, my_bot); +} + +void bot_subcommand_bot_face(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_face", sep->arg[0], "botface")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [value: 0-n]", sep->arg[0]); + c->Message(m_note, "note: Actual limit is filter-based"); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + + if (!sep->IsNumber(1)) { + c->Message(m_fail, "A numeric [value] is required to use this command"); + return; + } + + uint8 uvalue = atoi(sep->arg[1]); + + auto fail_type = BCEnum::AFT_None; + if (!PlayerAppearance::IsValidFace(my_bot->GetRace(), my_bot->GetGender(), uvalue)) { + fail_type = BCEnum::AFT_Value; + } + else { + uint8 old_woad = 0; + if (my_bot->GetRace() == BARBARIAN) + old_woad = ((my_bot->GetLuclinFace() / 10) * 10); + my_bot->SetLuclinFace((old_woad + uvalue)); + } + + if (helper_bot_appearance_fail(c, my_bot, fail_type, "face")) + return; + + helper_bot_appearance_form_final(c, my_bot); +} + +void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_follow_distance", sep->arg[0], "botfollowdistance")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [set] [distance] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(m_usage, "usage: %s [clear] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + return; + } + const int ab_mask = ActionableBots::ABM_NoFilter; + + uint32 bfd = BOT_DEFAULT_FOLLOW_DISTANCE; + bool set_flag = false; + int ab_arg = 2; + + if (!strcasecmp(sep->arg[1], "set")) { + if (!sep->IsNumber(2)) { + c->Message(m_fail, "A numeric [distance] is required to use this command"); + return; + } + + bfd = atoi(sep->arg[2]); + set_flag = true; + ab_arg = 3; + } + else if (strcasecmp(sep->arg[1], "clear")) { + c->Message(m_fail, "This command requires a [set | clear] argument"); + return; + } + + std::list sbl; + auto ab_type = ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]); + if (ab_type == ActionableBots::ABT_None) + return; + + int bot_count = 0; + for (auto bot_iter : sbl) { + if (!bot_iter) + continue; + + bot_iter->SetFollowDistance(bfd); + if (ab_type != ActionableBots::ABT_All && !botdb.SetFollowDistance(c->CharacterID(), bot_iter->GetBotID(), bfd)) { + c->Message(m_unknown, "DATABASE ERROR: Could not change follow distance for bot %s", bot_iter->GetCleanName()); + return; + } + + ++bot_count; + } + + if (ab_type == ActionableBots::ABT_All) { + if (!botdb.SetAllFollowDistances(c->CharacterID(), bfd)) { + c->Message(m_unknown, "Failed to save follow distance changes for your bots due to unknown cause"); + return; + } + + c->Message(m_action, "%s all of your bot follow distances", set_flag ? "Set" : "Cleared"); + } + else { + c->Message(m_action, "%s %i of your spawned bot follow distances", (set_flag ? "Set" : "Cleared"), bot_count); + } +} + +void bot_subcommand_bot_hair_color(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_hair_color", sep->arg[0], "bothaircolor")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [value: 0-n]", sep->arg[0]); + c->Message(m_note, "note: Actual limit is filter-based"); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + + if (!sep->IsNumber(1)) { + c->Message(m_fail, "A numeric [value] is required to use this command"); + return; + } + + uint8 uvalue = atoi(sep->arg[1]); + + auto fail_type = BCEnum::AFT_None; + if (!PlayerAppearance::IsValidHairColor(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + fail_type = BCEnum::AFT_Value; + else + my_bot->SetHairColor(uvalue); + + if (helper_bot_appearance_fail(c, my_bot, fail_type, "hair color")) + return; + + helper_bot_appearance_form_final(c, my_bot); +} + +void bot_subcommand_bot_hairstyle(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_hairstyle", sep->arg[0], "bothairstyle")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [value: 0-n]", sep->arg[0]); + c->Message(m_note, "note: Actual limit is filter-based"); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + + if (!sep->IsNumber(1)) { + c->Message(m_fail, "A numeric [value] is required to use this command"); + return; + } + + uint8 uvalue = atoi(sep->arg[1]); + + auto fail_type = BCEnum::AFT_None; + if (!PlayerAppearance::IsValidHair(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + fail_type = BCEnum::AFT_Value; + else + my_bot->SetHairStyle(uvalue); + + if (helper_bot_appearance_fail(c, my_bot, fail_type, "hair style")) + return; + + helper_bot_appearance_form_final(c, my_bot); +} + +void bot_subcommand_bot_heritage(Client *c, const Seperator *sep) +{ + // TODO: Trouble-shoot model update issue + + if (helper_command_alias_fail(c, "bot_subcommand_bot_heritage", sep->arg[0], "botheritage")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [value: 0-n] (Drakkin bots only)", sep->arg[0]); + c->Message(m_note, "note: Actual limit is filter-based"); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + + if (!sep->IsNumber(1)) { + c->Message(m_fail, "A numeric [value] is required to use this command"); + return; + } + + uint32 uvalue = atoi(sep->arg[1]); + + auto fail_type = BCEnum::AFT_None; + if (my_bot->GetRace() != DRAKKIN) + fail_type = BCEnum::AFT_Race; + else if (!PlayerAppearance::IsValidHeritage(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + fail_type = BCEnum::AFT_Value; + else + my_bot->SetDrakkinHeritage(uvalue); + + if (helper_bot_appearance_fail(c, my_bot, fail_type, "heritage")) + return; + + helper_bot_appearance_form_final(c, my_bot); +} + +void bot_subcommand_bot_inspect_message(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_inspect_message", sep->arg[0], "botinspectmessage")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [set | clear] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + c->Message(m_note, "Notes:"); + if (c->GetClientVersion() >= ClientVersion::SoF) { + c->Message(m_message, "- Self-inspect and type your bot's inspect message"); + c->Message(m_message, "- Close the self-inspect window to update the server"); + c->Message(m_message, "- Type '%s set' to set the bot's inspect message", sep->arg[0]); + } + else { + c->Message(m_message, "- Self-inspect and type your bot's inspect message"); + c->Message(m_message, "- Close the self-inspect window"); + c->Message(m_message, "- Self-inspect again to update the server"); + c->Message(m_message, "- Type '%s set' to set the bot's inspect message", sep->arg[0]); + } + return; + } + const int ab_mask = ActionableBots::ABM_NoFilter; + + bool set_flag = false; + if (!strcasecmp(sep->arg[1], "set")) { + set_flag = true; + } + else if (strcasecmp(sep->arg[1], "clear")) { + c->Message(15, "This command requires a [set | clear] argument"); + return; + } + + std::list sbl; + auto ab_type = ActionableBots::PopulateSBL(c, sep->arg[2], sbl, ab_mask, sep->arg[3]); + if (ab_type == ActionableBots::ABT_None) + return; + + const auto cms = &c->GetInspectMessage(); + + int bot_count = 0; + for (auto bot_iter : sbl) { + if (!bot_iter) + continue; + + auto bms = &bot_iter->GetInspectMessage(); + memset(bms, 0, sizeof(InspectMessage_Struct)); + if (set_flag) + memcpy(bms, cms, sizeof(InspectMessage_Struct)); + + if (ab_type != ActionableBots::ABT_All) + botdb.SetInspectMessage(bot_iter->GetBotID(), bms); + + ++bot_count; + } + + if (ab_type == ActionableBots::ABT_All) { + InspectMessage_Struct bms; + memset(&bms, 0, sizeof(InspectMessage_Struct)); + if (set_flag) + memcpy(&bms, cms, sizeof(InspectMessage_Struct)); + + if (!botdb.SetAllInspectMessages(c->CharacterID(), &bms)) { + c->Message(m_fail, "Failed to save inspect message changes for your bots due to unknown cause"); + return; + } + + c->Message(m_action, "%s all of your bot inspect messages", set_flag ? "Set" : "Cleared"); + } + else { + c->Message(m_action, "%s %i of your spawned bot inspect messages", set_flag ? "Set" : "Cleared", bot_count); + } +} + +void bot_subcommand_bot_list(Client *c, const Seperator *sep) +{ + // TODO: Consider re-working to use player race values instead of actual race + + enum { FilterClass, FilterRace, FilterName, FilterCount, MaskClass = (1 << FilterClass), MaskRace = (1 << FilterRace), MaskName = (1 << FilterName) }; + + if (helper_command_alias_fail(c, "bot_subcommand_bot_list", sep->arg[0], "botlist")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([class] [value]) ([race] [value]) ([name] [partial-full])", sep->arg[0]); + c->Message(m_note, "Note: filter criteria is orderless and optional"); + return; + } + + uint32 filter_value[FilterCount]; + int name_criteria_arg = 0; + memset(&filter_value, 0, sizeof(uint32) * FilterCount); + + int filter_mask = 0; + for (int i = 1; i < (FilterCount * 2); i += 2) { + if (sep->arg[i][0] == '\0') + break; + + if (!strcasecmp(sep->arg[i], "class")) { + filter_mask |= MaskClass; + filter_value[FilterClass] = atoi(sep->arg[i + 1]); + continue; + } + if (!strcasecmp(sep->arg[i], "race")) { + filter_mask |= MaskRace; + filter_value[FilterRace] = atoi(sep->arg[i + 1]); + continue; + } + if (!strcasecmp(sep->arg[i], "name")) { + filter_mask |= MaskName; + name_criteria_arg = (i + 1); + continue; + } + + c->Message(m_fail, "A numeric value or name is required to use the filter property of this command (f: '%s', v: '%s')", sep->arg[i], sep->arg[i + 1]); + return; + } + + std::string TempErrorMessage; + auto dbbl = Bot::GetBotList(c->CharacterID(), &TempErrorMessage); + + if (!TempErrorMessage.empty()) { + c->Message(m_fail, "Failed to load 'BotsAvailableList' due to unknown cause"); + return; + } + if (dbbl.empty()) { + c->Message(m_fail, "You have no bots"); + return; + } + + int bot_count = 0; + for (auto dbbl_iter : dbbl) { + if (filter_mask) { + if ((filter_mask & MaskClass) && filter_value[FilterClass] != dbbl_iter.BotClass) + continue; + if ((filter_mask & MaskRace) && filter_value[FilterRace] != dbbl_iter.BotRace) + continue; + if (filter_mask & MaskName) { + std::string name_criteria = sep->arg[name_criteria_arg]; + std::transform(name_criteria.begin(), name_criteria.end(), name_criteria.begin(), ::tolower); + std::string name_check = dbbl_iter.BotName; + std::transform(name_check.begin(), name_check.end(), name_check.begin(), ::tolower); + if (name_check.find(name_criteria) == std::string::npos) + continue; + } + } + + c->Message(m_message, "%s is a level %u %s %s %s", + dbbl_iter.BotName, + dbbl_iter.BotLevel, + Bot::RaceIdToString(dbbl_iter.BotRace).c_str(), + ((dbbl_iter.BotGender == FEMALE) ? ("Female") : ((dbbl_iter.BotGender == MALE) ? ("Male") : ("Neuter"))), + Bot::ClassIdToString(dbbl_iter.BotClass).c_str() + ); + + ++bot_count; + } + if (!bot_count) { + c->Message(m_fail, "You have no bots meeting this criteria"); + } + else { + c->Message(m_action, "%i of %i bot%s shown", bot_count, dbbl.size(), ((bot_count != 1) ? ("s") : (""))); + c->Message(m_message, "Your limit is %i bot%s", RuleI(Bots, CreationLimit), ((RuleI(Bots, CreationLimit) != 1) ? ("s") : (""))); + } +} + +void bot_subcommand_bot_out_of_combat(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_out_of_combat", sep->arg[0], "botoutofcombat")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + return; + } + const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); + + std::string arg1 = sep->arg[1]; + + bool behavior_state = false; + bool toggle_behavior = true; + int ab_arg = 1; + if (!arg1.compare("on")) { + behavior_state = true; + toggle_behavior = false; + ab_arg = 2; + } + else if (!arg1.compare("off")) { + toggle_behavior = false; + ab_arg = 2; + } + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None) + return; + + for (auto bot_iter : sbl) { + if (!bot_iter) + continue; + + if (toggle_behavior) + bot_iter->SetAltOutOfCombatBehavior(!bot_iter->GetAltOutOfCombatBehavior()); + else + bot_iter->SetAltOutOfCombatBehavior(behavior_state); + + helper_bot_out_of_combat(c, bot_iter); + } +} + +void bot_subcommand_bot_report(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_report", sep->arg[0], "botreport")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + return; + } + const int ab_mask = ActionableBots::ABM_NoFilter; + + std::string ab_type_arg = sep->arg[1]; + if (ab_type_arg.empty()) { + if (c->GetTarget()) { + if (c->GetTarget()->IsClient() && c->GetTarget()->CastToClient() == c) + ab_type_arg = "ownergroup"; + else if (c->GetTarget()->IsClient() && c->GetTarget()->CastToClient() != c) + ab_type_arg = "targetgroup"; + } + else { + ab_type_arg = "spawned"; + } + } + + std::list sbl; + if (ActionableBots::PopulateSBL(c, ab_type_arg.c_str(), sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + + for (auto bot_iter : sbl) { + if (!bot_iter) + continue; + + std::string report_msg = StringFormat("%s %s reports", Bot::ClassIdToString(bot_iter->GetClass()).c_str(), bot_iter->GetCleanName()); + report_msg.append(StringFormat(": %3.1f%% health", bot_iter->GetHPRatio())); + if (!IsNonSpellFighterClass(bot_iter->GetClass())) + report_msg.append(StringFormat(": %3.1f%% mana", bot_iter->GetManaRatio())); + + c->Message(m_message, "%s", report_msg.c_str()); + } +} + +void bot_subcommand_bot_spawn(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_spawn", sep->arg[0], "botspawn")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [bot_name]", sep->arg[0]); + return; + } + + int rule_level = RuleI(Bots, BotCharacterLevel); + if (c->GetLevel() < rule_level) { + c->Message(m_fail, "You must be level %i to use bots", rule_level); + return; + } + + if (c->GetFeigned()) { + c->Message(m_fail, "You can not spawn a bot while feigned"); + return; + } + + std::string TempErrorMessage; + + int sbc = Bot::SpawnedBotCount(c->CharacterID(), &TempErrorMessage); + if (!TempErrorMessage.empty()) { + c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + return; + } + + int rule_limit = RuleI(Bots, SpawnLimit); + if (sbc >= rule_limit && !c->GetGM()) { + c->Message(m_fail, "You can not have more than %i spawned bots", rule_limit); + return; + } + + if (RuleB(Bots, QuestableSpawnLimit) && !c->GetGM()) { + int abc = Bot::AllowedBotSpawns(c->CharacterID(), &TempErrorMessage); + if (!TempErrorMessage.empty()) { + c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + return; + } + if (!abc) { + c->Message(m_fail, "You are not currently allowed any spawned bots"); + return; + } + if (sbc >= abc) { + c->Message(m_fail, "You have reached your current limit of %i spawned bots", abc); + return; + } + } + + if (sep->arg[1][0] == '\0' || sep->IsNumber(1)) { + c->Message(m_fail, "You must specify a [name] to use this command"); + return; + } + std::string bot_name = sep->arg[1]; + + auto bot_id = Bot::GetBotIDByBotName(bot_name); + if (Bot::GetBotOwnerCharacterID(bot_id, &TempErrorMessage) != c->CharacterID()) { + if (!TempErrorMessage.empty()) + c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + c->Message(m_fail, "You don't own a bot named '%s'", bot_name.c_str()); + return; + } + + if (entity_list.GetMobByBotID(bot_id)) { + c->Message(m_fail, "'%s' is already spawned in zone", bot_name.c_str()); + return; + } + + // this probably needs work... + if (c->GetGroup()) { + std::list group_list; + c->GetGroup()->GetMemberList(group_list); + for (auto member_iter : group_list) { + if (!member_iter) + continue; + if (member_iter->qglobal) // what is this?? really should have had a message to describe failure... (can't spawn bots if you are assigned to a task/instance?) + return; + if (!member_iter->qglobal && (member_iter->GetAppearance() != eaDead) && (member_iter->IsEngaged() || (member_iter->IsClient() && member_iter->CastToClient()->GetAggroCount()))) { + c->Message(m_fail, "You can't summon bots while you are engaged."); + return; + } + } + } + else if (c->GetAggroCount() > 0) { + c->Message(m_fail, "You can't spawn bots while you are engaged."); + return; + } + + //if (c->IsEngaged()) { + // c->Message(m_fail, "You can't spawn bots while you are engaged."); + // return; + //} + + auto my_bot = Bot::LoadBot(bot_id, &TempErrorMessage); + if (!TempErrorMessage.empty()) { + c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + safe_delete(my_bot); + return; + } + if (!my_bot) { + c->Message(m_fail, "No valid bot '%s' (id: %i) exists", bot_name.c_str(), bot_id); + return; + } + + my_bot->Spawn(c, &TempErrorMessage); // 'TempErrorMessage' not used... + + static const char* bot_spawn_message[16] = { + "A solid weapon is my ally!", // WARRIOR / 'generic' + "The pious shall never die!", // CLERIC + "I am the symbol of Light!", // PALADIN + "There are enemies near!", // RANGER + "Out of the shadows, I step!", // SHADOWKNIGHT + "Nature's fury shall be wrought!", // DRUID + "Your punishment will be my fist!", // MONK + "Music is the overture of battle! ", // BARD + "Daggers into the backs of my enemies!", // ROGUE + "More bones to grind!", // SHAMAN + "Death is only the beginning!", // NECROMANCER + "I am the harbinger of demise!", // WIZARD + "The elements are at my command!", // MAGICIAN + "No being can resist my charm!", // ENCHANTER + "Battles are won by hand and paw!", // BEASTLORD + "My bloodthirst shall not be quenched!" // BERSERKER + }; + + Bot::BotGroupSay(my_bot, "%s", bot_spawn_message[CLASSIDTOINDEX(my_bot->GetClass())]); +} + +void bot_subcommand_bot_stance(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_stance", sep->arg[0], "botstance")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [current | value: 0-6] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + c->Message(m_note, "value: %u(%s), %u(%s), %u(%s), %u(%s), %u(%s), %u(%s), %u(%s)", + BotStancePassive, GetBotStanceName(BotStancePassive), + BotStanceBalanced, GetBotStanceName(BotStanceBalanced), + BotStanceEfficient, GetBotStanceName(BotStanceEfficient), + BotStanceReactive, GetBotStanceName(BotStanceReactive), + BotStanceAggressive, GetBotStanceName(BotStanceAggressive), + BotStanceBurn, GetBotStanceName(BotStanceBurn), + BotStanceBurnAE, GetBotStanceName(BotStanceBurnAE) + ); + return; + } + int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); + + bool current_flag = false; + auto bst = BotStanceUnknown; + + if (!strcasecmp(sep->arg[1], "current")) + current_flag = true; + else if (sep->IsNumber(1)) + bst = VALIDBOTSTANCE(atoi(sep->arg[1])); + + if (!current_flag && bst == BotStanceUnknown) { + c->Message(m_fail, "A [current] argument or valid numeric [value] is required to use this command"); + return; + } + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[2], sbl, ab_mask, sep->arg[3]) == ActionableBots::ABT_None) + return; + + for (auto bot_iter : sbl) { + if (!bot_iter) + continue; + + if (!current_flag) { + bot_iter->SetBotStance(bst); + bot_iter->CalcChanceToCast(); + bot_iter->Save(); + } + + Bot::BotGroupSay(bot_iter, "My current stance is '%s' (%u)", GetBotStanceName(bot_iter->GetBotStance()), bot_iter->GetBotStance()); + } +} + +void bot_subcommand_bot_summon(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_summon", sep->arg[0], "botsummon")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + return; + } + const int ab_mask = ActionableBots::ABM_NoFilter; + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + + for (auto bot_iter : sbl) { + if (!bot_iter) + continue; + + Bot::BotGroupSay(bot_iter, "Whee!"); + + bot_iter->WipeHateList(); + bot_iter->SetTarget(bot_iter->GetBotOwner()); + bot_iter->Warp(glm::vec3(c->GetPosition())); + + if (!bot_iter->HasPet()) + continue; + + bot_iter->GetPet()->WipeHateList(); + bot_iter->GetPet()->SetTarget(bot_iter); + bot_iter->GetPet()->Warp(glm::vec3(c->GetPosition())); + } + + if (sbl.size() == 1) + c->Message(m_action, "Summoned %s to you", ((sbl.front()) ? (sbl.front()->GetCleanName()) : ("'nullptr'"))); + else + c->Message(m_action, "Summoned %i bots to you", sbl.size()); +} + +void bot_subcommand_bot_tattoo(Client *c, const Seperator *sep) +{ + // TODO: Trouble-shoot model update issue + + if (helper_command_alias_fail(c, "bot_subcommand_bot_tattoo", sep->arg[0], "bottattoo")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [value: 0-n] (Drakkin bots only)", sep->arg[0]); + c->Message(m_note, "note: Actual limit is filter-based"); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + + if (!sep->IsNumber(1)) { + c->Message(m_fail, "A numeric [value] is required to use this command"); + return; + } + + uint32 uvalue = atoi(sep->arg[1]); + + auto fail_type = BCEnum::AFT_None; + if (my_bot->GetRace() != DRAKKIN) + fail_type = BCEnum::AFT_Race; + else if (!PlayerAppearance::IsValidTattoo(my_bot->GetRace(), my_bot->GetGender(), uvalue)) + fail_type = BCEnum::AFT_Value; + else + my_bot->SetDrakkinTattoo(uvalue); + + if (helper_bot_appearance_fail(c, my_bot, fail_type, "tattoo")) + return; + + helper_bot_appearance_form_final(c, my_bot); +} + +void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_toggle_archer", sep->arg[0], "bottogglearcher")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([option: on | off]) ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + return; + } + const int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); + + std::string arg1 = sep->arg[1]; + + bool archer_state = false; + bool toggle_archer = true; + int ab_arg = 1; + if (!arg1.compare("on")) { + archer_state = true; + toggle_archer = false; + ab_arg = 2; + } + else if (!arg1.compare("off")) { + toggle_archer = false; + ab_arg = 2; + } + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]) == ActionableBots::ABT_None) + return; + + for (auto bot_iter : sbl) { + if (!bot_iter) + continue; + + if (toggle_archer) + bot_iter->SetBotArcher(!bot_iter->IsBotArcher()); + else + bot_iter->SetBotArcher(archer_state); + bot_iter->ChangeBotArcherWeapons(bot_iter->IsBotArcher()); + + if (bot_iter->GetClass() == RANGER && bot_iter->GetLevel() >= 61) + bot_iter->SetRangerAutoWeaponSelect(bot_iter->IsBotArcher()); + } +} + +void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_toggle_helm", sep->arg[0], "bottogglehelm")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([option: on | off]) ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); + return; + } + const int ab_mask = ActionableBots::ABM_NoFilter; + + std::string arg1 = sep->arg[1]; + + bool helm_state = false; + bool toggle_helm = true; + int ab_arg = 1; + if (!arg1.compare("on")) { + helm_state = true; + toggle_helm = false; + ab_arg = 2; + } + else if (!arg1.compare("off")) { + toggle_helm = false; + ab_arg = 2; + } + + std::list sbl; + auto ab_type = ActionableBots::PopulateSBL(c, sep->arg[ab_arg], sbl, ab_mask, sep->arg[(ab_arg + 1)]); + if (ab_type == ActionableBots::ABT_None) + return; + + int bot_count = 0; + for (auto bot_iter : sbl) { + if (!bot_iter) + continue; + + if (toggle_helm) + bot_iter->SetShowHelm(!bot_iter->GetShowHelm()); + else + bot_iter->SetShowHelm(helm_state); + + if (ab_type != ActionableBots::ABT_All) { + if (!botdb.SetHelmAppearance(c->CharacterID(), bot_iter->GetBotID(), bot_iter->GetShowHelm())) { + c->Message(m_unknown, "DATABASE ERROR: Could not change helm appearance for bot %s", bot_iter->GetCleanName()); + return; + } + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + SpawnAppearance_Struct* saptr = (SpawnAppearance_Struct*)outapp->pBuffer; + saptr->spawn_id = bot_iter->GetID(); + saptr->type = AT_ShowHelm; + saptr->parameter = bot_iter->GetShowHelm(); + + entity_list.QueueClients(bot_iter, outapp); + safe_delete(outapp); + + //helper_bot_appearance_form_update(bot_iter); + } + ++bot_count; + } + + if (ab_type == ActionableBots::ABT_All) { + bool action_success = false; + std::string query; + if (toggle_helm) + action_success = botdb.ToggleAllHelmAppearances(c->CharacterID()); + else + action_success = botdb.SetAllHelmAppearances(c->CharacterID(), helm_state); + if (!action_success) { + c->Message(m_unknown, "Failed to save helm changes for your bots due to unknown cause"); + return; + } + + c->Message(m_action, "%s all of your bot show helm flags", toggle_helm ? "Toggled" : (helm_state ? "Set" : "Cleared")); + } + else { + c->Message(m_action, "%s %i of your spawned bot show helm flags", toggle_helm ? "Toggled" : (helm_state ? "Set" : "Cleared"), bot_count); + } + + // Notes: + /* + [CLIENT OPCODE TEST] + [10-16-2015 :: 14:57:56] [Packet :: Client -> Server (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10] + 0: A4 02 [2B 00] 01 00 00 00 - showhelm = true (client) + [10-16-2015 :: 14:57:56] [Packet :: Server -> Client (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10] + 0: A4 02 [2B 00] 01 00 00 00 - showhelm = true (client) + + [10-16-2015 :: 14:58:02] [Packet :: Client -> Server (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10] + 0: A4 02 [2B 00] 00 00 00 00 - showhelm = false (client) + [10-16-2015 :: 14:58:02] [Packet :: Server -> Client (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10] + 0: A4 02 [2B 00] 00 00 00 00 - showhelm = false (client) + + [BOT OPCODE TEST] + [10-16-2015 :: 22:15:34] [Packet :: Client -> Server (Dump)] [OP_ChannelMessage - 0x0045] [Size: 167] + 0: 43 6C 65 72 69 63 62 6F - 74 00 00 00 00 00 00 00 | Clericbot....... + 16: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 32: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 48: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 64: 43 6C 65 72 69 63 62 6F - 74 00 00 00 00 00 00 00 | Clericbot....... + 80: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 96: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 112: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 128: 00 00 00 00 08 00 00 00 - CD CD CD CD CD CD CD CD | ................ + 144: 64 00 00 00 23 62 6F 74 - 20 73 68 6F 77 68 65 6C | d...#bot showhel + 160: 6D 20 6F 6E 00 | m on. + + [10-16-2015 :: 22:15:34] [Packet :: Server -> Client (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10] + 0: A2 02 2B 00 01 00 00 00 - showhelm = true + + [10-16-2015 :: 22:15:40] [Packet :: Client -> Server (Dump)] [OP_ChannelMessage - 0x0045] [Size: 168] + 0: 43 6C 65 72 69 63 62 6F - 74 00 00 00 00 00 00 00 | Clericbot....... + 16: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 32: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 48: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 64: 43 6C 65 72 69 63 62 6F - 74 00 00 00 00 00 00 00 | Clericbot....... + 80: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 96: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 112: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 | ................ + 128: 00 00 00 00 08 00 00 00 - CD CD CD CD CD CD CD CD | ................ + 144: 64 00 00 00 23 62 6F 74 - 20 73 68 6F 77 68 65 6C | d...#bot showhel + 160: 6D 20 6F 66 66 00 | m off. + + [10-16-2015 :: 22:15:40] [Packet :: Server -> Client (Dump)] [OP_SpawnAppearance - 0x01d1] [Size: 10] + 0: A2 02 2B 00 00 00 00 00 - showhelm = false + + *** Bot did not update using the OP_SpawnAppearance packet with AT_ShowHelm appearance type *** + */ +} + +void bot_subcommand_bot_update(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_update", sep->arg[0], "botupdate")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You currently have no spawned bots"); + return; + } + + int bot_count = 0; + for (auto bot_iter : sbl) { + if (!bot_iter || bot_iter->IsEngaged() || bot_iter->GetLevel() == c->GetLevel()) + continue; + + bot_iter->SetPetChooser(false); + bot_iter->CalcBotStats((sbl.size() == 1)); + ++bot_count; + } + + c->Message(m_action, "Updated %i of your %i spawned bots", bot_count, sbl.size()); +} + +void bot_subcommand_bot_woad(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_bot_woad", sep->arg[0], "botwoad")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [value: 0-n] (Barbarian bots only)", sep->arg[0]); + c->Message(m_note, "note: Actual limit is filter-based"); + return; + } + + auto my_bot = ActionableBots::AsTarget_ByBot(c); + if (!my_bot) { + c->Message(m_fail, "You must a bot that you own to use this command"); + return; + } + + if (!sep->IsNumber(1)) { + c->Message(m_fail, "A numeric [value] is required to use this command"); + return; + } + + uint8 uvalue = atoi(sep->arg[1]); + + auto fail_type = BCEnum::AFT_None; + if (my_bot->GetRace() != BARBARIAN) { + fail_type = BCEnum::AFT_Race; + } + else if (!PlayerAppearance::IsValidWoad(my_bot->GetRace(), my_bot->GetGender(), uvalue)) { + fail_type = BCEnum::AFT_Value; + } + else { + uint8 old_face = (my_bot->GetLuclinFace() % 10); + my_bot->SetLuclinFace(((uvalue * 10) + old_face)); + } + + if (helper_bot_appearance_fail(c, my_bot, fail_type, "woad")) + return; + + helper_bot_appearance_form_final(c, my_bot); +} + +void bot_subcommand_botgroup_add_member(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_add_member", sep->arg[0], "botgroupaddmember")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [member_name] ([leader_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (sbl.empty()) { + c->Message(m_fail, "You must [name] a new member as a bot that you own to use this command"); + return; + } + + auto new_member = sbl.front(); + if (!new_member) { + c->Message(m_unknown, "Error: New member bot dereferenced to nullptr"); + return; + } + + if (new_member->HasGroup()) { + c->Message(m_fail, "%s is already a current member of a group and can not join another one", new_member->GetCleanName()); + return; + } + + std::string error_message; + if (botdb.GetGroupIDByMemberID(new_member->GetBotID(), error_message)) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "%s is already a current member of a bot-group", new_member->GetCleanName()); + return; + } + + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[2]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a group leader as a bot that you own to use this command"); + return; + } + + auto group_leader = sbl.front(); + if (!group_leader) { + c->Message(m_unknown, "Error: Group leader bot dereferenced to nullptr"); + return; + } + + Group* group_inst = group_leader->GetGroup(); + if (!group_inst || group_inst->GetLeader() != group_leader) { + c->Message(m_fail, "%s is not the current leader of a group", group_leader->GetCleanName()); + return; + } + + if (!botdb.GetGroupIDByLeaderID(group_leader->GetBotID(), error_message)) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "%s is not the current leader of a bot-group", group_leader->GetCleanName()); + return; + } + + if (!Bot::AddBotToGroup(new_member, group_inst)) { + c->Message(m_fail, "Could not add %s as a new member to %s's group", new_member->GetCleanName(), group_leader->GetCleanName()); + return; + } + + database.SetGroupID(new_member->GetName(), group_inst->GetID(), new_member->GetBotID()); + botdb.AddMemberToBotGroup(group_leader->GetBotID(), new_member->GetBotID(), error_message); + + std::string botgroup_name = botdb.GetGroupNameByLeaderID(group_leader->GetBotID(), error_message); + + c->Message(m_action, "Successfully added %s to bot-group %s", new_member->GetCleanName(), botgroup_name.c_str()); +} + +void bot_subcommand_botgroup_create(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_create", sep->arg[0], "botgroupcreate")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [group_name] ([leader_name])", sep->arg[0]); + return; + } + + std::string group_name_arg = sep->arg[1]; + if (group_name_arg.empty()) { + c->Message(m_fail, "You must specify a [name] for this bot-group to use this command"); + return; + } + if (botdb.DoesBotGroupExist(group_name_arg)) { + c->Message(m_fail, "The [name] %s already exists for a bot-group. Please choose another", group_name_arg.c_str()); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[2]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a group leader as a bot that you own to use this command"); + return; + } + + auto group_leader = sbl.front(); + if (!group_leader) { + c->Message(m_unknown, "Error: Group leader bot dereferenced to nullptr"); + return; + } + + if (group_leader->HasGroup()) { + c->Message(m_fail, "%s is already a current member of a group", group_leader->GetCleanName()); + return; + } + + std::string error_message; + if (botdb.GetGroupIDByLeaderID(group_leader->GetBotID(), error_message)) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "%s is already the current leader of a bot-group", group_leader->GetCleanName()); + return; + } + if (botdb.GetGroupIDByMemberID(group_leader->GetBotID(), error_message)) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "%s is already a current member of a bot-group", group_leader->GetCleanName()); + return; + } + + Group* group_inst = new Group(group_leader); + if (!group_inst) { + c->Message(m_unknown, "Could not create a new group instance"); + return; + } + + if (!botdb.CreateBotGroup(group_name_arg, group_leader->GetBotID(), error_message)) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "Could not create bot-group %s", group_name_arg.c_str()); + safe_delete(group_inst); + return; + } + entity_list.AddGroup(group_inst); + database.SetGroupID(group_leader->GetCleanName(), group_inst->GetID(), group_leader->GetBotID()); + database.SetGroupLeaderName(group_inst->GetID(), group_leader->GetCleanName()); + group_leader->SetFollowID(c->GetID()); + + c->Message(m_action, "Successfully created bot-group %s with %s as its leader", group_name_arg.c_str(), group_leader->GetCleanName()); +} + +void bot_subcommand_botgroup_delete(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_delete", sep->arg[0], "botgroupdelete")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [botgroup_name]", sep->arg[0]); + return; + } + + std::string group_name_arg = sep->arg[1]; + if (group_name_arg.empty()) { + c->Message(m_fail, "You must specify a [name] for this bot-group to use this command"); + return; + } + + std::string error_message; + uint32 group_id = botdb.GetGroupIDForLoadGroup(c->CharacterID(), group_name_arg, error_message); + if (!group_id) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "Could not locate group id for %s", group_name_arg.c_str()); + return; + } + + uint32 leader_id = botdb.GetLeaderIDByGroupID(group_id, error_message); + if (!leader_id) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "Could not locate leader id for %s", group_name_arg.c_str()); + return; + } + + std::list gbl; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + std::map> groups_list = botdb.LoadGroup(group_name_arg, error_message); + + for (auto bot_iter : sbl) { + for (auto group_iter : groups_list[group_id]) { + if (bot_iter->GetBotID() == group_iter) { + gbl.push_back(bot_iter); + break; + } + } + } + gbl.unique(); + + for (auto group_member : gbl) { + if (group_member->HasGroup()) + Bot::RemoveBotFromGroup(group_member, group_member->GetGroup()); + } + + if (!botdb.DeleteBotGroup(leader_id, error_message)) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "Failed to delete bot-group %s", group_name_arg.c_str()); + return; + } + + c->Message(m_action, "Successfully deleted bot-group %s", group_name_arg.c_str()); +} + +void bot_subcommand_botgroup_list(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_list", sep->arg[0], "botgrouplist")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s", sep->arg[0]); + return; + } + + std::string error_message; + auto groups_list = botdb.GetGroupsListByOwnerID(c->CharacterID(), error_message); + if (groups_list.empty()) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "You have no saved bot-groups"); + return; + } + + int botgroup_count = 0; + for (auto groups_iter : groups_list) + c->Message(m_message, "(%i) Bot-group name: %s | Leader: %s", (++botgroup_count), groups_iter.first.c_str(), groups_iter.second.c_str()); + + c->Message(m_action, "%i bot-groups listed", botgroup_count); +} + +void bot_subcommand_botgroup_load(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_load", sep->arg[0], "botgroupload")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [botgroup_name]", sep->arg[0]); + return; + } + + std::string group_name_arg = sep->arg[1]; + if (group_name_arg.empty()) { + c->Message(m_fail, "You must specify the [name] of a bot-group to load to use this command"); + return; + } + if (!botdb.DoesBotGroupExist(group_name_arg)) { + c->Message(m_fail, "Bot-group %s does not exist", group_name_arg.c_str()); + return; + } + + Group* owner_group = c->GetGroup(); + if (owner_group) { + std::list member_list; + owner_group->GetClientList(member_list); + member_list.remove(nullptr); + + for (auto member_iter : member_list) { + if (member_iter->IsEngaged() || member_iter->GetAggroCount() > 0) { + c->Message(m_fail, "You can't spawn bots while your group is engaged"); + return; + } + } + } + else { + if (c->GetAggroCount() > 0) { + c->Message(m_fail, "You can't spawn bots while you are engaged"); + return; + } + } + + std::string error_message; + uint32 group_id = botdb.GetGroupIDForLoadGroup(c->CharacterID(), group_name_arg, error_message); + if (!group_id) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "Can not resolve bot-group %s to a valid id", group_name_arg.c_str()); + return; + } + + std::map> group_list = botdb.LoadGroup(group_name_arg, error_message); + if (group_list.empty()) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "Database returned an empty list for got-group %s", group_name_arg.c_str()); + return; + } + + int spawned_bot_count = Bot::SpawnedBotCount(c->CharacterID(), &error_message); + if (!error_message.empty()) { + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + return; + } + + if (RuleB(Bots, QuestableSpawnLimit)) { + const int allowed_bot_count = Bot::AllowedBotSpawns(c->CharacterID(), &error_message); + if (!error_message.empty()) { + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + return; + } + + if (!allowed_bot_count) { + c->Message(m_fail, "You can not spawn any bots"); + return; + } + + if (spawned_bot_count >= allowed_bot_count || (spawned_bot_count + group_list.begin()->second.size()) > allowed_bot_count) { + c->Message(m_fail, "You can not spawn more than %i bot%s (quest-limit)", allowed_bot_count, ((allowed_bot_count == 1) ? ("") : ("s"))); + return; + } + } + + const int allowed_bot_limit = RuleI(Bots, SpawnLimit); + if (spawned_bot_count >= allowed_bot_limit || (spawned_bot_count + group_list.begin()->second.size()) > allowed_bot_limit) { + c->Message(m_fail, "You can not spawn more than %i bot%s (hard-limit)", allowed_bot_limit, ((allowed_bot_limit == 1) ? ("") : ("s"))); + return; + } + + uint32 leader_id = botdb.GetLeaderIDByGroupName(group_name_arg, error_message); + if (!leader_id) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "Can not locate bot-group leader id for %s", group_name_arg.c_str()); + return; + } + + auto group_leader = Bot::LoadBot(leader_id, &error_message); + if (!group_leader) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "Could not spawn bot-group leader for %s", group_name_arg.c_str()); + safe_delete(group_leader); + return; + } + + group_leader->Spawn(c, &error_message); + // No error_message code in Bot::Spawn() + + Group* group_inst = new Group(group_leader); + + entity_list.AddGroup(group_inst); + database.SetGroupID(group_leader->GetCleanName(), group_inst->GetID(), group_leader->GetBotID()); + database.SetGroupLeaderName(group_inst->GetID(), group_leader->GetCleanName()); + group_leader->SetFollowID(c->GetID()); + + group_list[group_id].remove(0); + group_list[group_id].remove(group_leader->GetBotID()); + for (auto member_iter : group_list[group_id]) { + auto group_member = Bot::LoadBot(member_iter, &error_message); + if (!group_member) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "Could not load bot id %i", member_iter); + safe_delete(group_member); + return; + } + + group_member->Spawn(c, &error_message); + // No error_message code in Bot::Spawn() + Bot::AddBotToGroup(group_member, group_inst); + } + + c->Message(m_action, "Successfully loaded bot-group %s", group_name_arg.c_str()); +} + +void bot_subcommand_botgroup_remove_member(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_botgroup_remove_member", sep->arg[0], "botgroupremovemember")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a group member as a bot that you own to use this command"); + return; + } + + auto group_member = sbl.front(); + if (!group_member) { + c->Message(m_unknown, "Error: Group member bot dereferenced to nullptr"); + return; + } + + if (!group_member->HasGroup()) { + c->Message(m_fail, "%s is not a current member of a group", group_member->GetCleanName()); + return; + } + + if (!Bot::RemoveBotFromGroup(group_member, group_member->GetGroup())) { + c->Message(m_fail, "Could not remove %s from their group", group_member->GetCleanName()); + return; + } + + std::string error_message; + if (!botdb.RemoveMemberFromBotGroup(group_member->GetBotID(), error_message)) { + if (!error_message.empty()) + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + c->Message(m_fail, "Could not remove %s from their bot-group", group_member->GetCleanName()); + return; + } + + c->Message(m_action, "Successfully removed %s from their bot-group", group_member->GetCleanName()); +} + +void bot_subcommand_circle(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Depart]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Depart) || helper_command_alias_fail(c, "bot_subcommand_circle", sep->arg[0], "circle")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [list | destination] ([option: single])", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Depart, DRUID); + return; + } + + bool single = false; + std::string single_arg = sep->arg[2]; + if (!single_arg.compare("single")) + single = true; + + std::string destination = sep->arg[1]; + if (!destination.compare("list")) { + auto my_druid_bot = ActionableBots::AsGroupMember_ByClass(c, c, DRUID); + helper_command_depart_list(c, my_druid_bot, nullptr, local_list, single); + return; + } + else if (destination.empty()) { + c->Message(m_fail, "A [destination] or [list] argument is required to use this command"); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToDepart(); + if (helper_spell_check_fail(local_entry)) + continue; + if (local_entry->caster_class != DRUID) + continue; + if (local_entry->single != single) + continue; + if (destination.compare(spells[local_entry->spell_id].teleport_zone)) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + +void bot_subcommand_heal_rotation_adaptive_targeting(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_adaptive_targeting", sep->arg[0], "healrotationadaptivetargeting")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name]) ([option: on | off])", sep->arg[0]); + return; + } + + std::string adaptive_targeting_arg; + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (!sbl.empty()) { + adaptive_targeting_arg = sep->arg[2]; + } + else { + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + adaptive_targeting_arg = sep->arg[1]; + } + + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + bool hr_adaptive_targeting = false; + + if (!adaptive_targeting_arg.compare("on")) { + hr_adaptive_targeting = true; + } + else if (adaptive_targeting_arg.compare("off")) { + c->Message(m_action, "Adaptive targeting is currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->AdaptiveTargeting()) ? ("on") : ("off")), current_member->GetCleanName()); + return; + } + + (*current_member->MemberOfHealRotation())->SetAdaptiveTargeting(hr_adaptive_targeting); + + c->Message(m_action, "Adaptive targeting is now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->AdaptiveTargeting()) ? ("on") : ("off")), current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_add_member(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_add_member", sep->arg[0], "healrotationaddmember")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [new_member_name] ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (sbl.empty()) { + c->Message(m_fail, "You must [name] a new member as a bot that you own to use this command"); + return; + } + + auto new_member = sbl.front(); + if (!new_member) { + c->Message(m_unknown, "Error: New member bot dereferenced to nullptr"); + return; + } + + if (new_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is already a current member of a Heal Rotation and can not join another one", new_member->GetCleanName()); + return; + } + + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[2]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + if (!new_member->JoinHealRotationMemberPool(current_member->MemberOfHealRotation())) { + c->Message(m_fail, "Failed to add %s as a current member of this Heal Rotation", new_member->GetCleanName()); + return; + } + + c->Message(m_action, "Successfully added %s as a current member of this Heal Rotation", new_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_add_target(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_add_target", sep->arg[0], "healrotationaddtarget")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [heal_target_name] ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[2]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + auto heal_target = entity_list.GetMob(sep->arg[1]); + if (!heal_target) { + c->Message(m_fail, "No target exists by the name '%s'", sep->arg[1]); + return; + } + + if ((!heal_target->IsClient() && !heal_target->IsBot() && !heal_target->IsPet()) || + (heal_target->IsPet() && (!heal_target->GetOwner() || (!heal_target->GetOwner()->IsClient() && !heal_target->GetOwner()->IsBot())))) + { + c->Message(m_fail, "%s's entity type is not an allowable heal target", heal_target->GetCleanName()); + return; + } + + if (!heal_target->JoinHealRotationTargetPool(current_member->MemberOfHealRotation())) { + c->Message(m_fail, "Failed to add heal target with a name of '%s'", heal_target->GetCleanName()); + return; + } + + c->Message(m_action, "Successfully added heal target %s to %s's Heal Rotation", heal_target->GetCleanName(), current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_adjust_critical", sep->arg[0], "healrotationadjustcritical")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [armor_type] [value: %3.1f-%3.1f | + | -] ([member_name])", sep->arg[0], CRITICAL_HP_RATIO_BASE, SAFE_HP_RATIO_BASE); + c->Message(m_note, "armor_types: %u(Base), %u(Cloth), %u(Leather), %u(Chain), %u(Plate)", + ARMOR_TYPE_UNKNOWN, ARMOR_TYPE_CLOTH, ARMOR_TYPE_LEATHER, ARMOR_TYPE_CHAIN, ARMOR_TYPE_PLATE); + return; + } + + std::string armor_type_arg = sep->arg[1]; + std::string critical_arg = sep->arg[2]; + + uint8 armor_type_value = 255; + if (sep->IsNumber(1)) + armor_type_value = atoi(armor_type_arg.c_str()); + + if (armor_type_value > ARMOR_TYPE_LAST) { + c->Message(m_fail, "You must specify a valid [armor_type: %u-%u] to use this command", ARMOR_TYPE_FIRST, ARMOR_TYPE_LAST); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[3]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + float critical_ratio = CRITICAL_HP_RATIO_BASE; + if (sep->IsNumber(2)) + critical_ratio = atof(critical_arg.c_str()); + else if (!critical_arg.compare("+")) + critical_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(armor_type_value) + HP_RATIO_DELTA; + else if (!critical_arg.compare("-")) + critical_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(armor_type_value) - HP_RATIO_DELTA; + + if (critical_ratio > SAFE_HP_RATIO_BASE) + critical_ratio = SAFE_HP_RATIO_BASE; + if (critical_ratio < CRITICAL_HP_RATIO_BASE) + critical_ratio = CRITICAL_HP_RATIO_BASE; + + if (!(*current_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(armor_type_value, critical_ratio)) { + c->Message(m_fail, "Critical value %3.1f%%(%u) exceeds safe value %3.1f%%(%u) for %s's Heal Rotation", + critical_ratio, armor_type_value, (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(armor_type_value), armor_type_value, current_member->GetCleanName()); + return; + } + + c->Message(m_action, "Class Armor Type %u critical value %3.1f%% set for %s's Heal Rotation", + armor_type_value, (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(armor_type_value), current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_adjust_safe", sep->arg[0], "healrotationadjustsafe")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [value: %3.1f-%3.1f | + | -] ([member_name])", sep->arg[0], CRITICAL_HP_RATIO_BASE, SAFE_HP_RATIO_BASE); + c->Message(m_note, "armor_types: %u(Base), %u(Cloth), %u(Leather), %u(Chain), %u(Plate)", + ARMOR_TYPE_UNKNOWN, ARMOR_TYPE_CLOTH, ARMOR_TYPE_LEATHER, ARMOR_TYPE_CHAIN, ARMOR_TYPE_PLATE); + return; + } + + std::string armor_type_arg = sep->arg[1]; + std::string safe_arg = sep->arg[2]; + + uint8 armor_type_value = 255; + if (sep->IsNumber(1)) + armor_type_value = atoi(armor_type_arg.c_str()); + + if (armor_type_value > ARMOR_TYPE_LAST) { + c->Message(m_fail, "You must specify a valid [armor_type: %u-%u] to use this command", ARMOR_TYPE_FIRST, ARMOR_TYPE_LAST); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[3]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + float safe_ratio = SAFE_HP_RATIO_BASE; + if (sep->IsNumber(2)) + safe_ratio = atof(safe_arg.c_str()); + else if (!safe_arg.compare("+")) + safe_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(armor_type_value) + HP_RATIO_DELTA; + else if (!safe_arg.compare("-")) + safe_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(armor_type_value) - HP_RATIO_DELTA; + + if (safe_ratio > SAFE_HP_RATIO_BASE) + safe_ratio = SAFE_HP_RATIO_BASE; + if (safe_ratio < CRITICAL_HP_RATIO_BASE) + safe_ratio = CRITICAL_HP_RATIO_BASE; + + if (!(*current_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(armor_type_value, safe_ratio)) { + c->Message(m_fail, "Safe value %3.1f%%(%u) does not exceed critical value %3.1f%%(%u) for %s's Heal Rotation", + safe_ratio, armor_type_value, (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(armor_type_value), armor_type_value, current_member->GetCleanName()); + return; + } + + c->Message(m_action, "Class Armor Type %u safe value %3.1f%% set for %s's Heal Rotation", + armor_type_value, (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(armor_type_value), current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_casting_override(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_casting_override", sep->arg[0], "healrotationcastingoverride")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name]) ([option: on | off])", sep->arg[0]); + return; + } + + std::string casting_override_arg; + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (!sbl.empty()) { + casting_override_arg = sep->arg[2]; + } + else { + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + casting_override_arg = sep->arg[1]; + } + + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + bool hr_casting_override = false; + + if (!casting_override_arg.compare("on")) { + hr_casting_override = true; + } + else if (casting_override_arg.compare("off")) { + c->Message(m_action, "Fast heals are currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName()); + return; + } + + (*current_member->MemberOfHealRotation())->SetCastingOverride(hr_casting_override); + + c->Message(m_action, "Fast heals are now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_change_interval", sep->arg[0], "healrotationchangeinterval")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name]) ([interval=%u: %u-%u(seconds)])", + sep->arg[0], CASTING_CYCLE_DEFAULT_INTERVAL_S, CASTING_CYCLE_MINIMUM_INTERVAL_S, CASTING_CYCLE_MAXIMUM_INTERVAL_S); + return; + } + + std::string change_interval_arg; + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (!sbl.empty()) { + change_interval_arg = sep->arg[2]; + } + else { + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + change_interval_arg = sep->arg[1]; + } + + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + uint32 hr_change_interval_s = CASTING_CYCLE_DEFAULT_INTERVAL_S; + + if (!change_interval_arg.empty()) { + hr_change_interval_s = atoi(change_interval_arg.c_str()); + } + else { + hr_change_interval_s = (*current_member->MemberOfHealRotation())->IntervalS(); + c->Message(m_action, "Casting interval is currently '%i' second%s for %s's Heal Rotation", hr_change_interval_s, ((hr_change_interval_s == 1) ? ("") : ("s")), current_member->GetCleanName()); + return; + } + + if (hr_change_interval_s < CASTING_CYCLE_MINIMUM_INTERVAL_S || hr_change_interval_s > CASTING_CYCLE_MAXIMUM_INTERVAL_S) + hr_change_interval_s = CASTING_CYCLE_DEFAULT_INTERVAL_S; + + (*current_member->MemberOfHealRotation())->SetIntervalS(hr_change_interval_s); + + hr_change_interval_s = (*current_member->MemberOfHealRotation())->IntervalS(); + c->Message(m_action, "Casting interval is now '%i' second%s for %s's Heal Rotation", hr_change_interval_s, ((hr_change_interval_s == 1) ? ("") : ("s")), current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_clear_targets(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_clear_targets", sep->arg[0], "healrotationcleartargets")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + if (!(*current_member->MemberOfHealRotation())->ClearTargetPool()) { + c->Message(m_fail, "Failed to clear all targets from %s's Heal Rotation", current_member->GetCleanName()); + return; + } + + c->Message(m_action, "All targets have been cleared from %s's Heal Rotation", current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_create", sep->arg[0], "healrotationcreate")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([creator_name]) ([interval=%u: %u-%u(seconds)] [fastheals=off: on | off] [adaptivetargeting=off: on | off] [castingoverride=off: on | off])", + sep->arg[0], CASTING_CYCLE_DEFAULT_INTERVAL_S, CASTING_CYCLE_MINIMUM_INTERVAL_S, CASTING_CYCLE_MAXIMUM_INTERVAL_S); + return; + } + + std::string interval_arg; + std::string fast_heals_arg; + std::string adaptive_targeting_arg; + std::string casting_override_arg; + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (!sbl.empty()) { + interval_arg = sep->arg[2]; + fast_heals_arg = sep->arg[3]; + adaptive_targeting_arg = sep->arg[4]; + casting_override_arg = sep->arg[5]; + } + else { + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + interval_arg = sep->arg[1]; + fast_heals_arg = sep->arg[2]; + adaptive_targeting_arg = sep->arg[3]; + casting_override_arg = sep->arg[4]; + } + + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a creator as a bot that you own to use this command"); + return; + } + + auto creator_member = sbl.front(); + if (!creator_member) { + c->Message(m_unknown, "Error: Creator bot dereferenced to nullptr"); + return; + } + + if (creator_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is already a current member of a Heal Rotation", creator_member->GetCleanName()); + return; + } + + uint32 hr_interval_s = CASTING_CYCLE_DEFAULT_INTERVAL_S; + bool hr_fast_heals = false; + bool hr_adaptive_targeting = false; + bool hr_casting_override = false; + + if (!casting_override_arg.compare("on")) { + hr_casting_override = true; + if (!adaptive_targeting_arg.compare("on")) + hr_adaptive_targeting = true; + if (!fast_heals_arg.compare("on")) + hr_fast_heals = true; + hr_interval_s = atoi(interval_arg.c_str()); + } + else if (!casting_override_arg.compare("off")) { + if (!adaptive_targeting_arg.compare("on")) + hr_adaptive_targeting = true; + if (!fast_heals_arg.compare("on")) + hr_fast_heals = true; + hr_interval_s = atoi(interval_arg.c_str()); + } + + if (hr_interval_s < CASTING_CYCLE_MINIMUM_INTERVAL_S || hr_interval_s > CASTING_CYCLE_MAXIMUM_INTERVAL_S) + hr_interval_s = CASTING_CYCLE_DEFAULT_INTERVAL_S; + + hr_interval_s *= 1000; // convert to milliseconds for Bot/HealRotation constructor + + if (!creator_member->CreateHealRotation(hr_interval_s, hr_fast_heals, hr_adaptive_targeting, hr_casting_override)) { + c->Message(m_fail, "Failed to add %s as a current member to a new Heal Rotation", creator_member->GetCleanName()); + return; + } + + c->Message(m_action, "Successfully added %s as a current member to a new Heal Rotation", creator_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_fast_heals(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_fast_heals", sep->arg[0], "healrotationfastheals")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name]) ([option: on | off])", sep->arg[0]); + return; + } + + std::string fast_heals_arg; + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (!sbl.empty()) { + fast_heals_arg = sep->arg[2]; + } + else { + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + fast_heals_arg = sep->arg[1]; + } + + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + bool hr_fast_heals = false; + + if (!fast_heals_arg.compare("on")) { + hr_fast_heals = true; + } + else if (fast_heals_arg.compare("off")) { + c->Message(m_action, "Fast heals are currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->FastHeals()) ? ("on") : ("off")), current_member->GetCleanName()); + return; + } + + (*current_member->MemberOfHealRotation())->SetFastHeals(hr_fast_heals); + + c->Message(m_action, "Fast heals are now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->FastHeals()) ? ("on") : ("off")), current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_list(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_list", sep->arg[0], "healrotationlist")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + c->Message(m_note, "Heal Rotation Settings:"); + + c->Message(m_message, "Current state: %s", (((*current_member->MemberOfHealRotation())->IsActive()) ? ("active") : ("inactive"))); + c->Message(m_message, "Casting interval: %i seconds", (*current_member->MemberOfHealRotation())->IntervalS()); + c->Message(m_message, "Fast heals: '%s'", (((*current_member->MemberOfHealRotation())->FastHeals()) ? ("on") : ("off"))); + c->Message(m_message, "Adaptive targeting: '%s'", (((*current_member->MemberOfHealRotation())->AdaptiveTargeting()) ? ("on") : ("off"))); + c->Message(m_message, "Casting override: '%s'", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off"))); + + c->Message(m_message, "Base hp limits - critical: %3.1f%%, safe: %3.1f%%", + (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_UNKNOWN), + (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_UNKNOWN)); + c->Message(m_message, "Cloth hp limits - critical: %3.1f%%, safe: %3.1f%%", + (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_CLOTH), + (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_CLOTH)); + c->Message(m_message, "Leather hp limits - critical: %3.1f%%, safe: %3.1f%%", + (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_LEATHER), + (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_LEATHER)); + c->Message(m_message, "Chain hp limits - critical: %3.1f%%, safe: %3.1f%%", + (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_CHAIN), + (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_CHAIN)); + c->Message(m_message, "Plate hp limits - critical: %3.1f%%, safe: %3.1f%%", + (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_PLATE), + (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_PLATE)); + + c->Message(m_note, "Heal Rotation Members:"); + + int member_index = 0; + auto member_pool = (*current_member->MemberOfHealRotation())->MemberList(); + for (auto member_iter : *member_pool) { + if (!member_iter) + continue; + + c->Message(m_message, "(%i) %s", (++member_index), member_iter->GetCleanName()); + } + if (!member_index) + c->Message(m_fail, "(0) None"); + + c->Message(m_note, "Heal Rotation Targets:"); + + int target_index = 0; + auto target_pool = (*current_member->MemberOfHealRotation())->TargetList(); + for (auto target_iter : *target_pool) { + if (!target_iter) + continue; + + c->Message(m_message, "(%i) %s", (++target_index), target_iter->GetCleanName()); + } + if (!target_index) + c->Message(m_message, "(0) None"); +} + +void bot_subcommand_heal_rotation_remove_member(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_remove_member", sep->arg[0], "healrotationremovemember")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + if (!current_member->LeaveHealRotationMemberPool()) { + c->Message(m_fail, "Failed to remove %s from their Heal Rotation", current_member->GetCleanName()); + return; + } + + c->Message(m_action, "%s has been removed from their Heal Rotation", current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_remove_target(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_remove_target", sep->arg[0], "healrotationremovetarget")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [heal_target_name] ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[2]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + auto heal_target = entity_list.GetMob(sep->arg[1]); + if (!heal_target) { + c->Message(m_fail, "No target exists by the name '%s'", sep->arg[1]); + return; + } + + if (!current_member->MemberOfHealRotation()->get()->IsTargetInPool(heal_target) || !heal_target->LeaveHealRotationTargetPool()) { + c->Message(m_fail, "Failed to remove heal target with a name of '%s'", heal_target->GetCleanName()); + return; + } + + c->Message(m_action, "Successfully removed heal target %s from %s's Heal Rotation", heal_target->GetCleanName(), current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_reset_limits(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_reset_limits", sep->arg[0], "healrotationresetlimits")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + (*current_member->MemberOfHealRotation())->ResetArmorTypeHPLimits(); + + c->Message(m_action, "Class Armor Type HP limit criteria has been set to default values for %s's Heal Rotation", current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_start(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_start", sep->arg[0], "healrotationstart")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + if ((*current_member->MemberOfHealRotation())->IsActive()) { + c->Message(m_fail, "%s's Heal Rotation is already active", current_member->GetCleanName()); + return; + } + + if (!current_member->MemberOfHealRotation()->get()->Start()) { + c->Message(m_fail, "Failed to start %s's Heal Rotation", current_member->GetCleanName()); + return; + } + + c->Message(m_action, "%s's Heal Rotation is now active", current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_stop(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_stop", sep->arg[0], "healrotationstop")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + if (!(*current_member->MemberOfHealRotation())->IsActive()) { + c->Message(m_fail, "%s's Heal Rotation is already inactive", current_member->GetCleanName()); + return; + } + + if (!current_member->MemberOfHealRotation()->get()->Stop()) { + c->Message(m_fail, "Failed to stop %s's Heal Rotation", current_member->GetCleanName()); + return; + } + + c->Message(m_action, "%s's Heal Rotation is now inactive", current_member->GetCleanName()); +} + +void bot_subcommand_inventory_give(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_inventory_give", sep->arg[0], "inventorygive")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + return; + } + int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + + auto my_bot = sbl.front(); + if (!my_bot) { + c->Message(m_unknown, "ActionableBots returned 'nullptr'"); + return; + } + + my_bot->FinishTrade(c, Bot::BotTradeClientNoDropNoTrade); +} + +void bot_subcommand_inventory_list(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_inventory_list", sep->arg[0], "inventorylist")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + return; + } + int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + + auto my_bot = sbl.front(); + if (!my_bot) { + c->Message(m_unknown, "ActionableBots returned 'nullptr'"); + return; + } + + std::string TempErrorMessage; + my_bot->GetBotItemsCount(&TempErrorMessage); // database check to avoid false 'vacancy' reporting? + if (!TempErrorMessage.empty()) { + c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + return; + } + + const ItemInst* inst = nullptr; + const Item_Struct* item = nullptr; + bool is2Hweapon = false; + + std::string item_link; + Client::TextLink linker; + linker.SetLinkType(linker.linkItemInst); + + for (int i = EmuConstants::EQUIPMENT_BEGIN; i <= (EmuConstants::EQUIPMENT_END + 1); ++i) { + if ((i == MainSecondary) && is2Hweapon) + continue; + + inst = my_bot->CastToBot()->GetBotItem(i == 22 ? 9999 : i); + if (!inst || !inst->GetItem()) { + c->Message(m_message, "I need something for my %s (slot %i)", GetBotEquipSlotName(i), (i == 22 ? 9999 : i)); + continue; + } + + item = inst->GetItem(); + if ((i == MainPrimary) && ((item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HPiercing))) { + is2Hweapon = true; + } + + linker.SetItemInst(inst); + item_link = linker.GenerateLink(); + c->Message(m_message, "Using %s in my %s (slot %i)", item_link.c_str(), GetBotEquipSlotName(i), (i == 22 ? 9999 : i)); + } +} + +void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_inventory_remove", sep->arg[0], "inventoryremove")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [slotid: 0-22] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + return; + } + int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); + + if (c->GetTradeskillObject() || (c->trade->state == Trading)) { + c->Message_StringID(MT_Tell, MERCHANT_BUSY); + return; + } + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[2], sbl, ab_mask, sep->arg[3]) == ActionableBots::ABT_None) + return; + + auto my_bot = sbl.front(); + if (!my_bot) { + c->Message(m_unknown, "ActionableBots returned 'nullptr'"); + return; + } + + std::string TempErrorMessage; + my_bot->GetBotItemsCount(&TempErrorMessage); // added same check as in bot_subcommand_inventory_list() - same note + if (!TempErrorMessage.empty()) { + c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + return; + } + + int slotId = atoi(sep->arg[1]); + if (!sep->IsNumber(1) || ((slotId > EmuConstants::EQUIPMENT_END || slotId < EmuConstants::EQUIPMENT_BEGIN) && slotId != 9999)) { + c->Message(m_fail, "Valid slots are 0-21 or 9999"); + return; + } + + const Item_Struct* itm = nullptr; + const ItemInst* itminst = my_bot->GetBotItem(slotId); + if (itminst) + itm = itminst->GetItem(); + + if (itminst && itm && c->CheckLoreConflict(itm)) { + c->Message_StringID(0, PICK_LORE); + return; + } + + for (int m = AUG_BEGIN; m < EmuConstants::ITEM_COMMON_SIZE; ++m) { + if (!itminst) + break; + + ItemInst *itma = itminst->GetAugment(m); + if (!itma) + continue; + if (!c->CheckLoreConflict(itma->GetItem())) + continue; + + c->Message_StringID(0, PICK_LORE); + return; + } + + if (itm) { + c->PushItemOnCursor(*itminst, true); + if ((slotId == MainRange) || (slotId == MainAmmo) || (slotId == MainPrimary) || (slotId == MainSecondary)) + my_bot->SetBotArcher(false); + + my_bot->RemoveBotItemBySlot(slotId, &TempErrorMessage); + if (!TempErrorMessage.empty()) { + c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + return; + } + + my_bot->BotRemoveEquipItem(slotId); + my_bot->CalcBotStats(); + } + + switch (slotId) { + case MainCharm: + case MainEar1: + case MainHead: + case MainFace: + case MainEar2: + case MainNeck: + case MainBack: + case MainWrist1: + case MainWrist2: + case MainRange: + case MainPrimary: + case MainSecondary: + case MainFinger1: + case MainFinger2: + case MainChest: + case MainWaist: + case MainPowerSource: + case MainAmmo: + c->Message(m_message, "My %s is %s unequipped", GetBotEquipSlotName(slotId), ((itm) ? ("now") : ("already"))); + break; + case MainShoulders: + case MainArms: + case MainHands: + case MainLegs: + case MainFeet: + c->Message(m_message, "My %s are %s unequipped", GetBotEquipSlotName(slotId), ((itm) ? ("now") : ("already"))); + break; + default: + c->Message(m_fail, "I'm soo confused..."); + break; + } +} + +void bot_subcommand_pet_remove(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_pet_remove", sep->arg[0], "petremove")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + return; + } + int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + + uint16 class_mask = (PLAYER_CLASS_DRUID_BIT | PLAYER_CLASS_NECROMANCER_BIT | PLAYER_CLASS_ENCHANTER_BIT); + ActionableBots::Filter_ByClasses(c, sbl, class_mask); + if (sbl.empty()) { + c->Message(m_fail, "You have no spawned bots capable of charming"); + return; + } + sbl.remove(nullptr); + + int charmed_pet = 0; + int summoned_pet = 0; + for (auto bot_iter : sbl) { // Probably needs some work to release charmed pets + if (bot_iter->IsBotCharmer()) { + bot_iter->SetBotCharmer(false); + if (sbl.size() == 1) + Bot::BotGroupSay(bot_iter, "Using a summoned pet"); + ++summoned_pet; + continue; + } + + if (bot_iter->GetPet()) { + bot_iter->GetPet()->Say_StringID(PET_GETLOST_STRING); + bot_iter->GetPet()->Depop(false); + bot_iter->SetPetID(0); + } + bot_iter->SetBotCharmer(true); + if (sbl.size() == 1) + Bot::BotGroupSay(bot_iter, "Available for Charming"); + ++charmed_pet; + } + + if (sbl.size() != 1) + c->Message(m_action, "%i of your bots set for charming, %i of your bots set for summoned pet use", charmed_pet, summoned_pet); +} + +void bot_subcommand_pet_set_type(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_pet_set_type", sep->arg[0], "petsettype")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [type: water | fire | air | earth | monster] ([actionable: target | byname] ([actionable_name]))", sep->arg[0]); + c->Message(m_note, "requires one of the following bot classes:"); + c->Message(m_message, "Magician(1)"); + return; + } + int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); // this can be expanded without code modification + + std::string pet_arg = sep->arg[1]; + + uint8 pet_type = 255; + uint8 level_req = 255; + if (!pet_arg.compare("water")) { + pet_type = 0; + level_req = 1; + } + else if (!pet_arg.compare("fire")) { + pet_type = 1; + level_req = 3; + } + else if (!pet_arg.compare("air")) { + pet_type = 2; + level_req = 4; + } + else if (!pet_arg.compare("earth")) { + pet_type = 3; + level_req = 5; + } + else if (!pet_arg.compare("monster")) { + pet_type = 4; + level_req = 30; + } + + if (pet_type == 255) { + c->Message(m_fail, "You must specify a pet [type: water | fire | air | earth | monster]"); + return; + } + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[2], sbl, ab_mask, sep->arg[3]) == ActionableBots::ABT_None) + return; + + uint16 class_mask = PLAYER_CLASS_MAGICIAN_BIT; + ActionableBots::Filter_ByClasses(c, sbl, class_mask); + if (sbl.empty()) { + c->Message(m_fail, "You have no spawned Magician bots"); + return; + } + + ActionableBots::Filter_ByMinLevel(c, sbl, level_req); + if (sbl.empty()) { + c->Message(m_fail, "You have no spawned Magician bots capable of using this pet type: '%s'", pet_arg.c_str()); + return; + } + + uint16 reclaim_energy_id = 331; + for (auto bot_iter : sbl) { + if (!bot_iter) + continue; + + bot_iter->SetPetChooser(true); + bot_iter->SetPetChooserID(pet_type); + if (bot_iter->GetPet()) { + auto pet_id = bot_iter->GetPetID(); + bot_iter->SetPetID(0); + bot_iter->CastSpell(reclaim_energy_id, pet_id); + } + } +} + +void bot_subcommand_portal(Client *c, const Seperator *sep) +{ + bcst_list* local_list = &bot_command_spells[BCEnum::SpT_Depart]; + if (helper_spell_list_fail(c, local_list, BCEnum::SpT_Depart) || helper_command_alias_fail(c, "bot_subcommand_portal", sep->arg[0], "portal")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [list | destination] ([option: single])", sep->arg[0]); + helper_send_usage_required_bots(c, BCEnum::SpT_Depart, WIZARD); + return; + } + + bool single = false; + std::string single_arg = sep->arg[2]; + if (!single_arg.compare("single")) + single = true; + + std::string destination = sep->arg[1]; + if (!destination.compare("list")) { + auto my_wizard_bot = ActionableBots::AsGroupMember_ByClass(c, c, WIZARD); + helper_command_depart_list(c, nullptr, my_wizard_bot, local_list, single); + return; + } + else if (destination.empty()) { + c->Message(m_fail, "A [destination] or [list] argument is required to use this command"); + return; + } + + ActionableTarget::Types actionable_targets; + Bot* my_bot = nullptr; + std::list sbl; + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + + bool cast_success = false; + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToDepart(); + if (helper_spell_check_fail(local_entry)) + continue; + if (local_entry->caster_class != WIZARD) + continue; + if (local_entry->single != single) + continue; + if (destination.compare(spells[local_entry->spell_id].teleport_zone)) + continue; + + auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); + if (!target_mob) + continue; + + my_bot = ActionableBots::Select_ByMinLevelAndClass(c, local_entry->target_type, sbl, local_entry->spell_level, local_entry->caster_class, target_mob); + if (!my_bot) + continue; + + cast_success = helper_cast_standard_spell(my_bot, target_mob, local_entry->spell_id); + break; + } + + helper_no_available_bots(c, my_bot); +} + + +/* + * bot command helpers go below here + */ +bool helper_bot_appearance_fail(Client *bot_owner, Bot *my_bot, BCEnum::AFType fail_type, const char* type_desc) +{ + switch (fail_type) { + case BCEnum::AFT_Value: + bot_owner->Message(m_fail, "Failed to change '%s' for %s due to invalid value for this command", type_desc, my_bot->GetCleanName()); + return true; + case BCEnum::AFT_GenderRace: + bot_owner->Message(m_fail, "Failed to change '%s' for %s due to invalid bot gender and/or race for this command", type_desc, my_bot->GetCleanName()); + return true; + case BCEnum::AFT_Race: + bot_owner->Message(m_fail, "Failed to change '%s' for %s due to invalid bot race for this command", type_desc, my_bot->GetCleanName()); + return true; + default: + return false; + } +} + +void helper_bot_appearance_form_final(Client *bot_owner, Bot *my_bot) +{ + if (!MyBots::IsMyBot(bot_owner, my_bot)) + return; + if (!my_bot->Save()) { + bot_owner->Message(m_unknown, "Failed to save appearance change for %s due to unknown cause...", my_bot->GetCleanName()); + return; + } + + helper_bot_appearance_form_update(my_bot); + bot_owner->Message(m_action, "Successfully changed appearance for %s!", my_bot->GetCleanName()); +} + +void helper_bot_appearance_form_update(Bot *my_bot) +{ + if (!my_bot) + return; + + my_bot->SendIllusionPacket( + my_bot->GetRace(), + my_bot->GetGender(), + 0xFF, //my_bot->GetTexture(), // 0xFF - change back if issues arise + 0xFF, //my_bot->GetHelmTexture(), // 0xFF - change back if issues arise + my_bot->GetHairColor(), + my_bot->GetBeardColor(), + my_bot->GetEyeColor1(), + my_bot->GetEyeColor2(), + my_bot->GetHairStyle(), + my_bot->GetLuclinFace(), + my_bot->GetBeard(), + 0xFF, // aa_title (0xFF) + my_bot->GetDrakkinHeritage(), + my_bot->GetDrakkinTattoo(), + my_bot->GetDrakkinDetails(), + my_bot->GetSize() + ); +} + +uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_class, uint16 bot_race, uint8 bot_gender) +{ + uint32 bot_id = 0; + if (!bot_owner) + return bot_id; + if (!Bot::IsValidName(bot_name)) { + bot_owner->Message(m_fail, "'%s' is an invalid name. You may only use characters 'A-Z', 'a-z' and '_'", bot_name.c_str()); + return bot_id; + } + + std::string TempErrorMessage; + + if (!Bot::IsBotNameAvailable(bot_name.c_str(), &TempErrorMessage)) { + if (!TempErrorMessage.empty()) + bot_owner->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + bot_owner->Message(m_fail, "The name %s is already being used. Please choose a different name", bot_name.c_str()); + return bot_id; + } + + if (!Bot::IsValidRaceClassCombo(bot_race, bot_class)) { + bot_owner->Message(m_fail, "'%s'(%u):'%s'(%u) is an invalid race-class combination", + Bot::RaceIdToString(bot_race).c_str(), bot_race, Bot::ClassIdToString(bot_class).c_str(), bot_class); + return bot_id; + } + + if (bot_gender > FEMALE) { + bot_owner->Message(m_fail, "gender: %u(M), %u(F)", MALE, FEMALE); + return bot_id; + } + + uint32 mbc = RuleI(Bots, CreationLimit); + if (Bot::CreatedBotCount(bot_owner->CharacterID(), &TempErrorMessage) >= mbc) { + if (!TempErrorMessage.empty()) + bot_owner->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + bot_owner->Message(m_fail, "You have reached the maximum limit of %i bots", mbc); + return bot_id; + } + + auto DefaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot( + bot_name.c_str(), + "", + bot_owner->GetLevel(), + bot_race, + bot_class, + bot_gender + ); + + auto my_bot = new Bot(DefaultNPCTypeStruct, bot_owner); + + if (!my_bot->Save()) { + bot_owner->Message(m_unknown, "Failed to create '%s' due to unknown cause", my_bot->GetCleanName()); + return bot_id; + } + + bot_owner->Message(m_action, "Successfully created '%s' (id: %u)", my_bot->GetCleanName(), my_bot->GetBotID()); + + bot_id = my_bot->GetBotID(); + safe_delete(my_bot); + + return bot_id; +} + +void helper_bot_out_of_combat(Client *bot_owner, Bot *my_bot) +{ + if (!bot_owner || !my_bot) + return; + + switch (my_bot->GetClass()) { + case WARRIOR: + case CLERIC: + case PALADIN: + case RANGER: + case SHADOWKNIGHT: + case DRUID: + case MONK: + bot_owner->Message(m_unknown, "%s has no out-of-combat behavior defined", my_bot->GetCleanName()); + break; + case BARD: + bot_owner->Message(m_action, "%s will %s use out-of-combat behavior for bard songs", my_bot->GetCleanName(), ((my_bot->GetAltOutOfCombatBehavior()) ? ("now") : ("no longer"))); + break; + case ROGUE: + case SHAMAN: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + case BEASTLORD: + case BERSERKER: + bot_owner->Message(m_unknown, "%s has no out-of-combat behavior defined", my_bot->GetCleanName()); + break; + default: + break; + bot_owner->Message(m_fail, "Undefined bot class for %s", my_bot->GetCleanName()); + } +} + +bool helper_cast_standard_spell(Bot* casting_bot, Mob* target_mob, int spell_id, bool annouce_cast, uint32* dont_root_before) +{ + if (!casting_bot || !target_mob) + return false; + + casting_bot->InterruptSpell(); + if (annouce_cast) + Bot::BotGroupSay(casting_bot, "Attempting to cast '%s' on %s", spells[spell_id].name, target_mob->GetCleanName()); + + return casting_bot->CastSpell(spell_id, target_mob->GetID(), 1, -1, -1, dont_root_before); +} + +bool helper_command_alias_fail(Client *bot_owner, const char* command_handler, const char *alias, const char *command) +{ + auto alias_iter = bot_command_aliases.find(&alias[1]); + if (alias_iter == bot_command_aliases.end() || alias_iter->second.compare(command)) { + bot_owner->Message(m_fail, "Undefined linker usage in %s (%s)", command_handler, &alias[1]); + return true; + } + + return false; +} + +void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_bot, bcst_list* local_list, bool single_flag) +{ + if (!bot_owner) + return; + + if (!MyBots::IsMyBot(bot_owner, druid_bot)) + druid_bot = nullptr; + if (!MyBots::IsMyBot(bot_owner, wizard_bot)) + wizard_bot = nullptr; + if (!druid_bot && !wizard_bot) { + bot_owner->Message(m_fail, "No bots are capable of performing this action"); + return; + } + + bot_owner->Message(m_message, "The following destinations are available:"); + if (!local_list) { + bot_owner->Message(m_fail, "None"); + return; + } + + std::string msg; + std::string text_link; + + int destinations = 0; + for (auto list_iter : *local_list) { + auto local_entry = list_iter->SafeCastToDepart(); + if (!local_entry) + continue; + + if (druid_bot && druid_bot->GetClass() == local_entry->caster_class && druid_bot->GetLevel() >= local_entry->spell_level) { + if (local_entry->single != single_flag) + continue; + msg = StringFormat("%ccircle %s%s", BOT_COMMAND_CHAR, spells[local_entry->spell_id].teleport_zone, ((single_flag) ? (" single") : (""))); + text_link = druid_bot->CreateSayLink(bot_owner, msg.c_str(), local_entry->long_name.c_str()); + Bot::BotGroupSay(druid_bot, "dest: '%s' click: %s", spells[local_entry->spell_id].teleport_zone, text_link.c_str()); + ++destinations; + continue; + } + if (wizard_bot && wizard_bot->GetClass() == local_entry->caster_class && wizard_bot->GetLevel() >= local_entry->spell_level) { + if (local_entry->single != single_flag) + continue; + msg = StringFormat("%cportal %s%s", BOT_COMMAND_CHAR, spells[local_entry->spell_id].teleport_zone, ((single_flag) ? (" single") : (""))); + text_link = wizard_bot->CreateSayLink(bot_owner, msg.c_str(), local_entry->long_name.c_str()); + Bot::BotGroupSay(wizard_bot, "dest: '%s' click: %s", spells[local_entry->spell_id].teleport_zone, text_link.c_str()); + ++destinations; + continue; + } + } + if (!destinations) + bot_owner->Message(m_fail, "None"); +} + +bool helper_is_help_or_usage(const char* arg) +{ + if (!arg) + return false; + if (strcasecmp(arg, "help") && strcasecmp(arg, "usage")) + return false; + + return true; +} + +bool helper_no_available_bots(Client *bot_owner, Bot *my_bot) +{ + if (!bot_owner) + return true; + if (!my_bot) { + bot_owner->Message(m_fail, "No bots are capable of performing this action"); + return true; + } + + return false; +} + +void helper_send_available_subcommands(Client *bot_owner, const char* command_simile, const std::list& subcommand_list) +{ + bot_owner->Message(m_message, "Available %s management subcommands:", command_simile); + + int bot_subcommands_shown = 0; + for (const auto subcommand_iter : subcommand_list) { + auto find_iter = bot_command_list.find(subcommand_iter); + if (find_iter == bot_command_list.end()) + continue; + if (bot_owner->Admin() < find_iter->second->access) + continue; + + bot_owner->Message(m_usage, "%c%s - %s", BOT_COMMAND_CHAR, subcommand_iter, ((find_iter != bot_command_list.end()) ? (find_iter->second->desc) : ("[no description]"))); + ++bot_subcommands_shown; + } + + bot_owner->Message(m_message, "%d bot subcommand%s listed.", bot_subcommands_shown, bot_subcommands_shown != 1 ? "s" : ""); +} + +void helper_send_usage_required_bots(Client *bot_owner, BCEnum::SpType spell_type, uint8 bot_class) +{ + bot_owner->Message(m_note, "requires one of the following bot classes:"); + if (bot_class) + bot_owner->Message(m_message, "%s", required_bots_map_by_class[spell_type][bot_class].c_str()); + else + bot_owner->Message(m_message, "%s", required_bots_map[spell_type].c_str()); +} + +bool helper_spell_check_fail(STBaseEntry* local_entry) +{ + if (!local_entry) + return true; + if (spells[local_entry->spell_id].zonetype && zone->GetZoneType() && !(spells[local_entry->spell_id].zonetype & zone->GetZoneType())) + return true; + + return false; +} + +bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::SpType spell_type) +{ + if (!spell_list || spell_list->empty()) { + bot_owner->Message(m_fail, "%s", required_bots_map[spell_type].c_str()); + return true; + } + + return false; +} diff --git a/zone/bot_command.h b/zone/bot_command.h new file mode 100644 index 000000000..5d4be85fd --- /dev/null +++ b/zone/bot_command.h @@ -0,0 +1,667 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef BOT_COMMAND_H +#define BOT_COMMAND_H + +class Client; +class Seperator; + +#include "../common/types.h" +#include "bot.h" + + +class BCEnum +{ +public: + typedef enum SpellType { + SpT_None = 0, + SpT_BindAffinity, + SpT_Charm, + SpT_Cure, + SpT_Depart, + SpT_Escape, + SpT_Identify, + SpT_Invisibility, + SpT_Levitation, + SpT_Lull, + SpT_Mesmerize, + SpT_MovementSpeed, + SpT_Resistance, + SpT_Resurrect, + SpT_Rune, + SpT_SendHome, + SpT_Size, + SpT_Stance, + SpT_SummonCorpse, + SpT_WaterBreathing + } SpType; + static const int SpellTypeFirst = SpT_BindAffinity; + static const int SpellTypeLast = SpT_WaterBreathing; + + typedef enum TargetType { + TT_None = 0, + TT_Corpse, + TT_Self, + TT_Animal, + TT_Undead, + TT_Summoned, + TT_Plant, + TT_Single, + TT_GroupV1, + TT_GroupV2, + TT_AECaster, + TT_AEBard, + TT_AETarget + } TType; + static const int TargetTypeFirst = TT_Corpse; + static const int TargetTypeLast = TT_AETarget; + static const int TargetTypeCount = 13; + + typedef enum TargetMask { + TM_None = 0, + TM_Corpse = 1, + TM_Self = 2, + TM_Animal = 4, + TM_Undead = 8, + TM_Summoned = 16, + TM_Plant = 32, + TM_Single = 124, // currently, 2^6 + 2^{2..5}) -or- (64+32+16+8+4) + TM_GroupV1 = 128, + TM_GroupV2 = 256, + TM_AECaster = 512, + TM_AEBard = 1024, + TM_AETarget = 2048 + } TMask; + + typedef enum AppearanceFailType { + AFT_None = 0, + AFT_Value, + AFT_GenderRace, + AFT_Race + } AFType; + + typedef enum AilmentType { + AT_None = 0, + AT_Blindness, // SE: 20 + AT_Disease, // SE: 35 + AT_Poison, // SE: 36 + AT_Curse, // SE: 116 + AT_Corruption // SE: 369 + } AType; + static const int AilmentTypeCount = 5; + + typedef enum InvisibilityType { + IT_None = 0, + IT_Animal, + IT_Undead, + IT_Living, + IT_See + } IType; + + typedef enum ResistanceType { + RT_None = 0, + RT_Fire, // SE: 46 + RT_Cold, // SE: 47 + RT_Poison, // SE: 48 + RT_Disease, // SE: 49 + RT_Magic, // SE: 50 + RT_Corruption // SE: 370 + } RType; + static const int ResistanceTypeCount = 6; + + typedef enum SizeType { + SzT_None = 0, + SzT_Enlarge, + SzT_Reduce + } SzType; + + typedef enum StanceType { + StT_None = 0, + StT_Aggressive, + StT_Defensive + } StType; + + static std::string SpellTypeEnumToString(BCEnum::SpType spell_type) { + switch (spell_type) { + case SpT_BindAffinity: + return "SpT_BindAffinity"; + case SpT_Charm: + return "SpT_Charm"; + case SpT_Cure: + return "SpT_Cure"; + case SpT_Depart: + return "SpT_Depart"; + case SpT_Escape: + return "SpT_Escape"; + case SpT_Identify: + return "SpT_Identify"; + case SpT_Invisibility: + return "SpT_Invisibility"; + case SpT_Levitation: + return "SpT_Levitation"; + case SpT_Lull: + return "SpT_Lull"; + case SpT_Mesmerize: + return "SpT_Mesmerize"; + case SpT_MovementSpeed: + return "SpT_MovementSpeed"; + case SpT_Resistance: + return "SpT_Resistance"; + case SpT_Resurrect: + return "SpT_Resurrect"; + case SpT_Rune: + return "SpT_Rune"; + case SpT_SendHome: + return "SpT_SendHome"; + case SpT_Size: + return "SpT_Size"; + case SpT_Stance: + return "SpT_Stance"; + case SpT_SummonCorpse: + return "SpT_SummonCorpse"; + case SpT_WaterBreathing: + return "SpT_WaterBreathing"; + default: + return "SpT_None"; + } + } + + static std::string TargetTypeEnumToString(BCEnum::TType target_type) { + switch (target_type) { + case TT_Self: + return "TT_Self"; + case TT_Animal: + return "TT_Animal"; + case TT_Undead: + return "TT_Undead"; + case TT_Summoned: + return "TT_Summoned"; + case TT_Plant: + return "TT_Plant"; + case TT_Single: + return "TT_Single"; + case TT_GroupV1: + return "TT_GroupV1"; + case TT_GroupV2: + return "TT_GroupV2"; + case TT_AECaster: + return "TT_AECaster"; + case TT_AEBard: + return "TT_AEBard"; + case TT_AETarget: + return "TT_AETarget"; + case TT_Corpse: + return "TT_Corpse"; + default: + return "TT_None"; + } + } +}; + + +class STBaseEntry; +class STCharmEntry; +class STCureEntry; +class STDepartEntry; +class STEscapeEntry; +class STInvisibilityEntry; +class STMovementSpeedEntry; +class STResistanceEntry; +class STResurrectEntry; +class STSendHomeEntry; +class STSizeEntry; +class STStanceEntry; + +class STBaseEntry +{ +protected: + BCEnum::SpType m_bcst; + +public: + int spell_id; + uint8 spell_level; + uint8 caster_class; + BCEnum::TType target_type; + + // A non-polymorphic constructor requires an appropriate, non-'ST_None' BCEnum::SType + STBaseEntry(BCEnum::SpType init_bcst = BCEnum::SpT_None) { + spell_id = 0; + spell_level = 255; + caster_class = 255; + target_type = BCEnum::TT_None; + m_bcst = init_bcst; + } + STBaseEntry(STBaseEntry* prototype) { + spell_id = prototype->spell_id; + spell_level = 255; + caster_class = 255; + target_type = prototype->target_type; + m_bcst = prototype->BCST(); + } + virtual ~STBaseEntry() { return; }; + + BCEnum::SpType BCST() { return m_bcst; } + + virtual bool IsDerived() { return false; } + + bool IsCharm() const { return (m_bcst == BCEnum::SpT_Charm); } + bool IsCure() const { return (m_bcst == BCEnum::SpT_Cure); } + bool IsDepart() const { return (m_bcst == BCEnum::SpT_Depart); } + bool IsEscape() const { return (m_bcst == BCEnum::SpT_Escape); } + bool IsInvisibility() const { return (m_bcst == BCEnum::SpT_Invisibility); } + bool IsMovementSpeed() const { return (m_bcst == BCEnum::SpT_MovementSpeed); } + bool IsResistance() const { return (m_bcst == BCEnum::SpT_Resistance); } + bool IsResurrect() const { return (m_bcst == BCEnum::SpT_Resurrect); } + bool IsSendHome() const { return (m_bcst == BCEnum::SpT_SendHome); } + bool IsSize() const { return (m_bcst == BCEnum::SpT_Size); } + bool IsStance() const { return (m_bcst == BCEnum::SpT_Stance); } + + virtual STCharmEntry* SafeCastToCharm() { return nullptr; } + virtual STCureEntry* SafeCastToCure() { return nullptr; } + virtual STDepartEntry* SafeCastToDepart() { return nullptr; } + virtual STEscapeEntry* SafeCastToEscape() { return nullptr; } + virtual STInvisibilityEntry* SafeCastToInvisibility() { return nullptr; } + virtual STMovementSpeedEntry* SafeCastToMovementSpeed() { return nullptr; } + virtual STResistanceEntry* SafeCastToResistance() { return nullptr; } + virtual STResurrectEntry* SafeCastToResurrect() { return nullptr; } + virtual STSendHomeEntry* SafeCastToSendHome() { return nullptr; } + virtual STSizeEntry* SafeCastToSize() { return nullptr; } + virtual STStanceEntry* SafeCastToStance() { return nullptr; } +}; + +class STCharmEntry : public STBaseEntry +{ +public: + bool dire; + + STCharmEntry() { + m_bcst = BCEnum::SpT_Charm; + dire = false; + } + STCharmEntry(STCharmEntry* prototype) : STBaseEntry(prototype) { + m_bcst = BCEnum::SpT_Charm; + dire = prototype->dire; + } + virtual ~STCharmEntry() { return; }; + + virtual bool IsDerived() { return true; } + + virtual STCharmEntry* SafeCastToCharm() { return ((m_bcst == BCEnum::SpT_Charm) ? (static_cast(this)) : (nullptr)); } +}; + +class STCureEntry : public STBaseEntry +{ +public: + int cure_value[BCEnum::AilmentTypeCount]; + int cure_total; + + STCureEntry() { + m_bcst = BCEnum::SpT_Cure; + memset(&cure_value, 0, (sizeof(int) * BCEnum::AilmentTypeCount)); + cure_total = 0; + } + STCureEntry(STCureEntry* prototype) : STBaseEntry(prototype) { + m_bcst = BCEnum::SpT_Cure; + memcpy(&cure_value, prototype->cure_value, (sizeof(int) * BCEnum::AilmentTypeCount)); + cure_total = prototype->cure_total; + } + virtual ~STCureEntry() { return; }; + + virtual bool IsDerived() { return true; } + + virtual STCureEntry* SafeCastToCure() { return ((m_bcst == BCEnum::SpT_Cure) ? (static_cast(this)) : (nullptr)); } +}; + +class STDepartEntry : public STBaseEntry +{ +public: + bool single; + std::string long_name; + + STDepartEntry() { + m_bcst = BCEnum::SpT_Depart; + single = false; + long_name.clear(); + } + STDepartEntry(STDepartEntry* prototype) : STBaseEntry(prototype) { + m_bcst = BCEnum::SpT_Depart; + single = prototype->single; + long_name = prototype->long_name; + } + virtual ~STDepartEntry() { return; }; + + virtual bool IsDerived() { return true; } + + virtual STDepartEntry* SafeCastToDepart() { return ((m_bcst == BCEnum::SpT_Depart) ? (static_cast(this)) : (nullptr)); } +}; + +class STEscapeEntry : public STBaseEntry +{ +public: + bool lesser; + + STEscapeEntry() { + m_bcst = BCEnum::SpT_Escape; + lesser = false; + } + STEscapeEntry(STEscapeEntry* prototype) : STBaseEntry(prototype) { + m_bcst = BCEnum::SpT_Escape; + lesser = prototype->lesser; + } + virtual ~STEscapeEntry() { return; }; + + virtual bool IsDerived() { return true; } + + virtual STEscapeEntry* SafeCastToEscape() { return ((m_bcst == BCEnum::SpT_Escape) ? (static_cast(this)) : (nullptr)); } +}; + +class STInvisibilityEntry : public STBaseEntry +{ +public: + BCEnum::IType invis_type; + + STInvisibilityEntry() { + m_bcst = BCEnum::SpT_Invisibility; + invis_type = BCEnum::IT_None; + } + STInvisibilityEntry(STInvisibilityEntry* prototype) : STBaseEntry(prototype) { + m_bcst = BCEnum::SpT_Invisibility; + invis_type = prototype->invis_type; + } + virtual ~STInvisibilityEntry() { return; }; + + virtual bool IsDerived() { return true; } + + virtual STInvisibilityEntry* SafeCastToInvisibility() { return ((m_bcst == BCEnum::SpT_Invisibility) ? (static_cast(this)) : (nullptr)); } +}; + +class STMovementSpeedEntry : public STBaseEntry +{ +public: + bool group; + + STMovementSpeedEntry() { + m_bcst = BCEnum::SpT_MovementSpeed; + group = false; + } + STMovementSpeedEntry(STMovementSpeedEntry* prototype) : STBaseEntry(prototype) { + m_bcst = BCEnum::SpT_MovementSpeed; + group = prototype->group; + } + virtual ~STMovementSpeedEntry() { return; }; + + virtual bool IsDerived() { return true; } + + virtual STMovementSpeedEntry* SafeCastToMovementSpeed() { return ((m_bcst == BCEnum::SpT_MovementSpeed) ? (static_cast(this)) : (nullptr)); } +}; + +class STResistanceEntry : public STBaseEntry +{ +public: + int resist_value[BCEnum::ResistanceTypeCount]; + int resist_total; + + STResistanceEntry() { + m_bcst = BCEnum::SpT_Resistance; + memset(&resist_value, 0, (sizeof(int) * BCEnum::ResistanceTypeCount)); + resist_total = 0; + } + STResistanceEntry(STResistanceEntry* prototype) : STBaseEntry(prototype) { + m_bcst = BCEnum::SpT_Resistance; + memcpy(&resist_value, prototype->resist_value, (sizeof(int) * BCEnum::ResistanceTypeCount)); + resist_total = prototype->resist_total; + } + virtual ~STResistanceEntry() { return; }; + + virtual bool IsDerived() { return true; } + + virtual STResistanceEntry* SafeCastToResistance() { return ((m_bcst == BCEnum::SpT_Resistance) ? (static_cast(this)) : (nullptr)); } +}; + +class STResurrectEntry : public STBaseEntry +{ +public: + bool aoe; + + STResurrectEntry() { + m_bcst = BCEnum::SpT_Resurrect; + aoe = false; + } + STResurrectEntry(STResurrectEntry* prototype) : STBaseEntry(prototype) { + m_bcst = BCEnum::SpT_Resurrect; + aoe = prototype->aoe; + } + virtual ~STResurrectEntry() { return; }; + + virtual bool IsDerived() { return true; } + + virtual STResurrectEntry* SafeCastToResurrect() { return ((m_bcst == BCEnum::SpT_Resurrect) ? (static_cast(this)) : (nullptr)); } +}; + +class STSendHomeEntry : public STBaseEntry +{ +public: + bool group; + + STSendHomeEntry() { + m_bcst = BCEnum::SpT_SendHome; + group = false; + } + STSendHomeEntry(STSendHomeEntry* prototype) : STBaseEntry(prototype) { + m_bcst = BCEnum::SpT_SendHome; + group = prototype->group; + } + virtual ~STSendHomeEntry() { return; }; + + virtual bool IsDerived() { return true; } + + virtual STSendHomeEntry* SafeCastToSendHome() { return ((m_bcst == BCEnum::SpT_SendHome) ? (static_cast(this)) : (nullptr)); } +}; + +class STSizeEntry : public STBaseEntry +{ +public: + BCEnum::SzType size_type; + + STSizeEntry() { + m_bcst = BCEnum::SpT_Size; + size_type = BCEnum::SzT_None; + } + STSizeEntry(STSizeEntry* prototype) : STBaseEntry(prototype) { + m_bcst = BCEnum::SpT_Size; + size_type = prototype->size_type; + } + virtual ~STSizeEntry() { return; }; + + virtual bool IsDerived() { return true; } + + virtual STSizeEntry* SafeCastToSize() { return ((m_bcst == BCEnum::SpT_Size) ? (static_cast(this)) : (nullptr)); } +}; + +class STStanceEntry : public STBaseEntry { +public: + BCEnum::StType stance_type; + + STStanceEntry() { + m_bcst = BCEnum::SpT_Stance; + stance_type = BCEnum::StT_None; + } + STStanceEntry(STStanceEntry* prototype) : STBaseEntry(prototype) { + m_bcst = BCEnum::SpT_Stance; + stance_type = prototype->stance_type; + } + virtual ~STStanceEntry() { return; }; + + virtual bool IsDerived() { return true; } + + virtual STStanceEntry* SafeCastToStance() { return ((m_bcst == BCEnum::SpT_Stance) ? (static_cast(this)) : (nullptr)); } +}; + + +typedef std::list bcst_list; +typedef std::map bcst_map; + +typedef std::map bcst_required_bot_classes_map; +typedef std::map> bcst_required_bot_classes_map_by_class; + +typedef std::map bcst_levels; +typedef std::map bcst_levels_map; + + +#define BOT_COMMAND_CHAR '^' + +typedef void (*BotCmdFuncPtr)(Client *,const Seperator *); + +typedef struct { + int access; + const char *desc; // description of bot command + BotCmdFuncPtr function; // null means perl function +} BotCommandRecord; + +extern int (*bot_command_dispatch)(Client *,char const*); +extern int bot_command_count; // number of bot commands loaded + + +// the bot command system: +int bot_command_init(void); +void bot_command_deinit(void); +int bot_command_add(std::string bot_command_name, const char *desc, int access, BotCmdFuncPtr function); +int bot_command_not_avail(Client *c, const char *message); +int bot_command_real_dispatch(Client *c, char const *message); +void bot_command_log_command(Client *c, const char *message); + + +// bot commands +void bot_command_actionable(Client *c, const Seperator *sep); +void bot_command_aggressive(Client *c, const Seperator *sep); +void bot_command_attack(Client *c, const Seperator *sep); +void bot_command_bind_affinity(Client *c, const Seperator *sep); +void bot_command_bot(Client *c, const Seperator *sep); +void bot_command_botgroup(Client *c, const Seperator *sep); +void bot_command_charm(Client *c, const Seperator *sep); +void bot_command_cure(Client *c, const Seperator *sep); +void bot_command_defensive(Client *c, const Seperator *sep); +void bot_command_depart(Client *c, const Seperator *sep); +void bot_command_escape(Client *c, const Seperator *sep); +void bot_command_find_aliases(Client *c, const Seperator *sep); +void bot_command_follow(Client *c, const Seperator *sep); +void bot_command_guard(Client *c, const Seperator *sep); +void bot_command_heal_rotation(Client *c, const Seperator *sep); +void bot_command_help(Client *c, const Seperator *sep); +void bot_command_hold(Client *c, const Seperator *sep); +void bot_command_identify(Client *c, const Seperator *sep); +void bot_command_inventory(Client *c, const Seperator *sep); +void bot_command_invisibility(Client *c, const Seperator *sep); +void bot_command_levitation(Client *c, const Seperator *sep); +void bot_command_lull(Client *c, const Seperator *sep); +void bot_command_mesmerize(Client *c, const Seperator *sep); +void bot_command_movement_speed(Client *c, const Seperator *sep); +void bot_command_pet(Client *c, const Seperator *sep); +void bot_command_pick_lock(Client *c, const Seperator *sep); +void bot_command_pull(Client *c, const Seperator *sep); +void bot_command_release(Client *c, const Seperator *sep); +void bot_command_resistance(Client *c, const Seperator *sep); +void bot_command_resurrect(Client *c, const Seperator *sep); +void bot_command_rune(Client *c, const Seperator *sep); +void bot_command_send_home(Client *c, const Seperator *sep); +void bot_command_size(Client *c, const Seperator *sep); +void bot_command_summon_corpse(Client *c, const Seperator *sep); +void bot_command_taunt(Client *c, const Seperator *sep); +void bot_command_track(Client *c, const Seperator *sep); +void bot_command_water_breathing(Client *c, const Seperator *sep); + + +// bot subcommands +void bot_subcommand_bot_appearance(Client *c, const Seperator *sep); +void bot_subcommand_bot_beard_color(Client *c, const Seperator *sep); +void bot_subcommand_bot_beard_style(Client *c, const Seperator *sep); +void bot_subcommand_bot_camp(Client *c, const Seperator *sep); +void bot_subcommand_bot_clone(Client *c, const Seperator *sep); +void bot_subcommand_bot_create(Client *c, const Seperator *sep); +void bot_subcommand_bot_delete(Client *c, const Seperator *sep); +void bot_subcommand_bot_details(Client *c, const Seperator *sep); +void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep); +void bot_subcommand_bot_eyes(Client *c, const Seperator *sep); +void bot_subcommand_bot_face(Client *c, const Seperator *sep); +void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep); +void bot_subcommand_bot_hair_color(Client *c, const Seperator *sep); +void bot_subcommand_bot_hairstyle(Client *c, const Seperator *sep); +void bot_subcommand_bot_heritage(Client *c, const Seperator *sep); +void bot_subcommand_bot_inspect_message(Client *c, const Seperator *sep); +void bot_subcommand_bot_list(Client *c, const Seperator *sep); +void bot_subcommand_bot_out_of_combat(Client *c, const Seperator *sep); +void bot_subcommand_bot_report(Client *c, const Seperator *sep); +void bot_subcommand_bot_spawn(Client *c, const Seperator *sep); +void bot_subcommand_bot_stance(Client *c, const Seperator *sep); +void bot_subcommand_bot_summon(Client *c, const Seperator *sep); +void bot_subcommand_bot_tattoo(Client *c, const Seperator *sep); +void bot_subcommand_bot_toggle_archer(Client *c, const Seperator *sep); +void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep); +void bot_subcommand_bot_update(Client *c, const Seperator *sep); +void bot_subcommand_bot_woad(Client *c, const Seperator *sep); +void bot_subcommand_botgroup_add_member(Client *c, const Seperator *sep); +void bot_subcommand_botgroup_create(Client *c, const Seperator *sep); +void bot_subcommand_botgroup_delete(Client *c, const Seperator *sep); +void bot_subcommand_botgroup_list(Client *c, const Seperator *sep); +void bot_subcommand_botgroup_load(Client *c, const Seperator *sep); +void bot_subcommand_botgroup_remove_member(Client *c, const Seperator *sep); +void bot_subcommand_circle(Client *c, const Seperator *sep); +void bot_subcommand_evacuate(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_adaptive_targeting(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_add_member(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_add_target(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_casting_override(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_clear_targets(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_fast_heals(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_list(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_remove_member(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_remove_target(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_reset_limits(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_start(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_stop(Client *c, const Seperator *sep); +void bot_subcommand_inventory_give(Client *c, const Seperator *sep); +void bot_subcommand_inventory_list(Client *c, const Seperator *sep); +void bot_subcommand_inventory_remove(Client *c, const Seperator *sep); +void bot_subcommand_pet_remove(Client *c, const Seperator *sep); +void bot_subcommand_pet_set_type(Client *c, const Seperator *sep); +void bot_subcommand_portal(Client *c, const Seperator *sep); +void bot_subcommand_succor(Client *c, const Seperator *sep); + + +// bot command helpers +bool helper_bot_appearance_fail(Client *bot_owner, Bot *my_bot, BCEnum::AFType fail_type, const char* type_desc); +void helper_bot_appearance_form_final(Client *bot_owner, Bot *my_bot); +void helper_bot_appearance_form_update(Bot *my_bot); +uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_class, uint16 bot_race, uint8 bot_gender); +void helper_bot_out_of_combat(Client *bot_owner, Bot *my_bot); +bool helper_cast_standard_spell(Bot* casting_bot, Mob* target_mob, int spell_id, bool annouce_cast = true, uint32* dont_root_before = nullptr); +bool helper_command_alias_fail(Client *bot_owner, const char* command_handler, const char *alias, const char *command); +void helper_command_depart_list(Client* bot_owner, Bot* druid_bot, Bot* wizard_bot, bcst_list* local_list, bool single_flag = false); +bool helper_is_help_or_usage(const char* arg); +bool helper_no_available_bots(Client *bot_owner, Bot *my_bot = nullptr); +void helper_send_available_subcommands(Client *bot_owner, const char* command_simile, const std::list& subcommand_list); +void helper_send_usage_required_bots(Client *bot_owner, BCEnum::SpType spell_type, uint8 bot_class = 0); +bool helper_spell_check_fail(STBaseEntry* local_entry); +bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::SpType spell_type); +#endif diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp new file mode 100644 index 000000000..c15d583ae --- /dev/null +++ b/zone/bot_database.cpp @@ -0,0 +1,732 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "../common/global_define.h" +#include "../common/rulesys.h" +#include "../common/string_util.h" +#include "../common/eqemu_logsys.h" + +#include "bot_database.h" +#include "bot.h" + +BotDatabase botdb; + + +BotDatabase::BotDatabase() +{ + +} + +BotDatabase::BotDatabase(const char* host, const char* user, const char* passwd, const char* database, uint32 port) +{ + Connect(host, user, passwd, database, port); +} + +BotDatabase::~BotDatabase() +{ + +} + +bool BotDatabase::Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port) { + uint32 errnum = 0; + char errbuf[MYSQL_ERRMSG_SIZE]; + if (!Open(host, user, passwd, database, port, &errnum, errbuf)) { + Log.Out(Logs::General, Logs::Error, "Failed to connect to bot database: Error: %s", errbuf); + return false; + } + else { + Log.Out(Logs::General, Logs::Status, "Using bot database '%s' at %s:%d", database, host, port); + return true; + } +} + +bool BotDatabase::GetCommandSettings(std::map>> &bot_command_settings) +{ + bot_command_settings.clear(); + + std::string query = "SELECT `bot_command`, `access`, `aliases` FROM `bot_command_settings`"; + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + for (auto row = results.begin(); row != results.end(); ++row) { + bot_command_settings[row[0]].first = atoi(row[1]); + if (row[2][0] == 0) + continue; + + auto aliases = SplitString(row[2], '|'); + for (auto iter : aliases) { + if (!iter.empty()) + bot_command_settings[row[0]].second.push_back(iter); + } + } + + return true; +} + + +// Bot command functions +bool BotDatabase::GetInspectMessage(uint32 bot_id, InspectMessage_Struct* message) +{ + std::string query = StringFormat("SELECT `inspect_message` FROM `bot_inspect_messages` WHERE `bot_id` = %i LIMIT 1", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + auto row = results.begin(); + memset(message, '\0', sizeof(InspectMessage_Struct)); + for (auto row = results.begin(); row != results.end(); ++row) { + memcpy(message, row[0], sizeof(InspectMessage_Struct)); + } + + return true; +} + +bool BotDatabase::SetInspectMessage(uint32 bot_id, const InspectMessage_Struct* message) +{ + std::string query = StringFormat("REPLACE INTO `bot_inspect_messages` (bot_id, inspect_message) VALUES (%u, '%s')", bot_id, EscapeString(message->text).c_str()); + auto results = QueryDatabase(query); + + return results.Success(); +} + +bool BotDatabase::SetAllInspectMessages(uint32 owner_id, const InspectMessage_Struct* message) +{ + std::string query = StringFormat( + "UPDATE `bot_inspect_messages`" + " SET `inspect_message` = '%s'" + " WHERE `bot_id`" + " IN (SELECT `bot_id` FROM `bot_data` WHERE `owner_id` = '%u')", + EscapeString(message->text).c_str(), owner_id + ); + auto results = QueryDatabase(query); + + return results.Success(); +} + +bool BotDatabase::SetAllArmorColorBySlot(uint32 owner_id, int16 slot_id, uint32 rgb_value) +{ + if (!owner_id) + return false; + + std::string query = StringFormat( + "UPDATE `bot_inventories` bi" + " INNER JOIN `bot_data` bd" + " ON bd.`owner_id` = '%u'" + " SET bi.`inst_color` = '%u'" + " WHERE bi.`bot_id` = bd.`bot_id`" + " AND bi.`slot_id` IN (%u, %u, %u, %u, %u, %u, %u, %u)" + " AND bi.`slot_id` = '%i'", + owner_id, + rgb_value, + MainHead, MainChest, MainArms, MainWrist1, MainWrist2, MainHands, MainLegs, MainFeet, + slot_id + ); + auto results = QueryDatabase(query); + + return results.Success(); +} + +bool BotDatabase::SetAllArmorColors(uint32 owner_id, uint32 rgb_value) +{ + if (!owner_id) + return false; + + std::string query = StringFormat( + "UPDATE `bot_inventories` bi" + " INNER JOIN `bot_data` bd" + " ON bd.`owner_id` = '%u'" + " SET bi.`inst_color` = '%u'" + " WHERE bi.`bot_id` = bd.`bot_id`" + " AND bi.`slot_id` IN (%u, %u, %u, %u, %u, %u, %u, %u)", + owner_id, + rgb_value, + MainHead, MainChest, MainArms, MainWrist1, MainWrist2, MainHands, MainLegs, MainFeet + ); + auto results = QueryDatabase(query); + + return results.Success(); +} + +bool BotDatabase::SetHelmAppearance(uint32 owner_id, uint32 bot_id, bool show_flag) +{ + if (!owner_id || !bot_id) + return false; + + std::string query = StringFormat( + "UPDATE `bot_data`" + " SET `show_helm` = '%u'" + " WHERE `owner_id` = '%u'" + " AND `bot_id` = '%u'", + (show_flag ? 1 : 0), + owner_id, + bot_id + ); + auto results = QueryDatabase(query); + + return results.Success(); +} + +bool BotDatabase::SetAllHelmAppearances(uint32 owner_id, bool show_flag) +{ + if (!owner_id) + return false; + + std::string query = StringFormat( + "UPDATE `bot_data`" + " SET `show_helm` = '%u'" + " WHERE `owner_id` = '%u'", + (show_flag ? 1 : 0), + owner_id + ); + auto results = QueryDatabase(query); + + return results.Success(); +} + +bool BotDatabase::ToggleHelmAppearance(uint32 owner_id, uint32 bot_id) +{ + if (!owner_id || !bot_id) + return false; + + std::string query = StringFormat( + "UPDATE `bot_data`" + " SET `show_helm` = (`show_helm` XOR '1')" + " WHERE `owner_id` = '%u'" + " AND `bot_id` = '%u'", + owner_id, + bot_id + ); + auto results = QueryDatabase(query); + + return results.Success(); +} + +bool BotDatabase::ToggleAllHelmAppearances(uint32 owner_id) +{ + if (!owner_id) + return false; + + std::string query = StringFormat( + "UPDATE `bot_data`" + " SET `show_helm` = (`show_helm` XOR '1')" + " WHERE `owner_id` = '%u'", + owner_id + ); + auto results = QueryDatabase(query); + + return results.Success(); +} + +bool BotDatabase::SetFollowDistance(uint32 owner_id, uint32 bot_id, uint32 follow_distance) +{ + if (!owner_id || !bot_id || !follow_distance) + return false; + + std::string query = StringFormat( + "UPDATE `bot_data`" + " SET `follow_distance` = '%u'" + " WHERE `owner_id` = '%u'" + " AND `bot_id` = '%u'", + follow_distance, + owner_id, + bot_id + ); + auto results = QueryDatabase(query); + + return results.Success(); +} + +bool BotDatabase::SetAllFollowDistances(uint32 owner_id, uint32 follow_distance) +{ + if (!owner_id || !follow_distance) + return false; + + std::string query = StringFormat( + "UPDATE `bot_data`" + " SET `follow_distance` = '%u'" + " WHERE `owner_id` = '%u'", + follow_distance, + owner_id + ); + auto results = QueryDatabase(query); + + return results.Success(); +} + +uint32 BotDatabase::Clone(uint32 owner_id, uint32 bot_id, const char* clone_name) +{ + if (!owner_id || !bot_id || !clone_name) + return 0; + + std::string data_query = StringFormat( + "INSERT INTO `bot_data`" + " (" + "`owner_id`," + " `spells_id`," + " `name`," + " `last_name`," + " `title`," + " `suffix`," + " `zone_id`," + " `gender`," + " `race`," + " `class`," + " `level`," + " `deity`," + " `creation_day`," + " `last_spawn`," + " `time_spawned`," + " `size`," + " `face`," + " `hair_color`," + " `hair_style`," + " `beard`," + " `beard_color`," + " `eye_color_1`," + " `eye_color_2`," + " `drakkin_heritage`," + " `drakkin_tattoo`," + " `drakkin_details`," + " `ac`," + " `atk`," + " `hp`," + " `mana`," + " `str`," + " `sta`," + " `cha`," + " `dex`," + " `int`," + " `agi`," + " `wis`," + " `fire`," + " `cold`," + " `magic`," + " `poison`," + " `disease`," + " `corruption`," + " `show_helm`," + " `follow_distance`" + ")" + " SELECT" + " bd.`owner_id`," + " bd.`spells_id`," + " '%s'," + " ''," + " bd.`title`," + " bd.`suffix`," + " bd.`zone_id`," + " bd.`gender`," + " bd.`race`," + " bd.`class`," + " bd.`level`," + " bd.`deity`," + " UNIX_TIMESTAMP()," + " UNIX_TIMESTAMP()," + " '0'," + " bd.`size`," + " bd.`face`," + " bd.`hair_color`," + " bd.`hair_style`," + " bd.`beard`," + " bd.`beard_color`," + " bd.`eye_color_1`," + " bd.`eye_color_2`," + " bd.`drakkin_heritage`," + " bd.`drakkin_tattoo`," + " bd.`drakkin_details`," + " bd.`ac`," + " bd.`atk`," + " bd.`hp`," + " bd.`mana`," + " bd.`str`," + " bd.`sta`," + " bd.`cha`," + " bd.`dex`," + " bd.`int`," + " bd.`agi`," + " bd.`wis`," + " bd.`fire`," + " bd.`cold`," + " bd.`magic`," + " bd.`poison`," + " bd.`disease`," + " bd.`corruption`," + " bd.`show_helm`," + " bd.`follow_distance`" + " FROM `bot_data` bd" + " WHERE" + " bd.`owner_id` = '%u'" + " AND" + " bd.`bot_id` = '%u'", + clone_name, + owner_id, + bot_id + ); + auto results = QueryDatabase(data_query); + if (!results.Success()) + return 0; + + return results.LastInsertedID(); +} + +bool BotDatabase::CloneInventory(uint32 owner_id, uint32 bot_id, uint32 clone_id) +{ + if (!owner_id || !bot_id || !clone_id) + return false; + + std::string inv_query = StringFormat( + "INSERT INTO `bot_inventories`" + " (" + "bot_id," + " `slot_id`," + " `item_id`," + " `inst_charges`," + " `inst_color`," + " `inst_no_drop`," + " `inst_custom_data`," + " `ornament_icon`," + " `ornament_id_file`," + " `ornament_hero_model`," + " `augment_1`," + " `augment_2`," + " `augment_3`," + " `augment_4`," + " `augment_5`," + " `augment_6`" + ")" + " SELECT" + " '%u' bot_id," + " bi.`slot_id`," + " bi.`item_id`," + " bi.`inst_charges`," + " bi.`inst_color`," + " bi.`inst_no_drop`," + " bi.`inst_custom_data`," + " bi.`ornament_icon`," + " bi.`ornament_id_file`," + " bi.`ornament_hero_model`," + " bi.`augment_1`," + " bi.`augment_2`," + " bi.`augment_3`," + " bi.`augment_4`," + " bi.`augment_5`," + " bi.`augment_6`" + " FROM `bot_inventories` bi" + " WHERE" + " bi.`bot_id` = '%u'" + " AND" + " '%u' = (SELECT `owner_id` FROM `bot_data` WHERE `bot_id` = '%u')", + clone_id, + bot_id, + owner_id, + bot_id + ); + auto results = QueryDatabase(inv_query); + + return results.Success(); +} + + +// Bot-group functions +bool BotDatabase::DoesBotGroupExist(std::string& group_name) +{ + if (group_name.empty()) + return false; + + std::string query = StringFormat("SELECT `group_name` FROM `vw_bot_groups` WHERE `group_name` LIKE '%s' LIMIT 1", group_name.c_str()); + auto results = QueryDatabase(query); + if (!results.Success() || results.RowCount() == 0) + return false; + + auto row = results.begin(); + if (!group_name.compare(row[0])) + return true; + + return false; +} + +uint32 BotDatabase::GetGroupIDByGroupName(std::string& group_name, std::string& error_message) +{ + if (group_name.empty()) + return 0; + + std::string query = StringFormat("SELECT `groups_index` FROM `bot_groups` WHERE `group_name` = '%s'", group_name.c_str()); + auto results = QueryDatabase(query); + if (!results.Success() || !results.RowCount()) { + error_message = results.ErrorMessage(); + return 0; + } + auto row = results.begin(); + + return atoi(row[0]); +} + +uint32 BotDatabase::GetLeaderIDByGroupName(std::string& group_name, std::string& error_message) +{ + if (group_name.empty()) + return 0; + + std::string query = StringFormat("SELECT `group_leader_id` FROM `bot_groups` WHERE `group_name` = '%s'", group_name.c_str()); + auto results = QueryDatabase(query); + if (!results.Success() || !results.RowCount()) { + error_message = results.ErrorMessage(); + return 0; + } + auto row = results.begin(); + + return atoi(row[0]); +} + +std::string BotDatabase::GetGroupNameByGroupID(uint32 group_id, std::string& error_message) +{ + if (!group_id) + return std::string(); + + std::string query = StringFormat("SELECT `group_name` FROM `bot_groups` WHERE `groups_index` = '%u'", group_id); + auto results = QueryDatabase(query); + if (!results.Success() || !results.RowCount()) { + error_message = results.ErrorMessage(); + return std::string(); + } + auto row = results.begin(); + + return std::string(row[0]); +} + +std::string BotDatabase::GetGroupNameByLeaderID(uint32 leader_id, std::string& error_message) +{ + if (!leader_id) + return std::string(); + + std::string query = StringFormat("SELECT `group_name` FROM `bot_groups` WHERE `group_leader_id` = '%u'", leader_id); + auto results = QueryDatabase(query); + if (!results.Success() || !results.RowCount()) { + error_message = results.ErrorMessage(); + return std::string(); + } + auto row = results.begin(); + + return std::string(row[0]); +} + +uint32 BotDatabase::GetGroupIDByLeaderID(uint32 leader_id, std::string& error_message) +{ + if (!leader_id) + return 0; + + std::string query = StringFormat("SELECT `groups_index` FROM `bot_groups` WHERE `group_leader_id` = '%u'", leader_id); + auto results = QueryDatabase(query); + if (!results.Success() || !results.RowCount()) { + error_message = results.ErrorMessage(); + return 0; + } + auto row = results.begin(); + + return atoi(row[0]); +} + +uint32 BotDatabase::GetLeaderIDByGroupID(uint32 group_id, std::string& error_message) +{ + if (!group_id) + return 0; + + std::string query = StringFormat("SELECT `group_leader_id` FROM `bot_groups` WHERE `groups_index` = '%u'", group_id); + auto results = QueryDatabase(query); + if (!results.Success() || !results.RowCount()) { + error_message = results.ErrorMessage(); + return 0; + } + auto row = results.begin(); + + return atoi(row[0]); +} + +uint32 BotDatabase::GetGroupIDByMemberID(uint32 member_id, std::string& error_message) +{ + if (!member_id) + return 0; + + std::string query = StringFormat("SELECT `groups_index` FROM `bot_group_members` WHERE `bot_id` = '%u'", member_id); + auto results = QueryDatabase(query); + if (!results.Success() || !results.RowCount()) { + error_message = results.ErrorMessage(); + return 0; + } + auto row = results.begin(); + + return atoi(row[0]); +} + +bool BotDatabase::CreateBotGroup(std::string& group_name, uint32 leader_id, std::string& error_message) +{ + if (group_name.empty() || !leader_id) + return false; + + if (DoesBotGroupExist(group_name)) + return false; + + std::string query = StringFormat("INSERT INTO `bot_groups` (`group_leader_id`, `group_name`) VALUES ('%u', '%s')", leader_id, group_name.c_str()); + auto results = QueryDatabase(query); + if (!results.Success()) { + error_message = results.ErrorMessage(); + return false; + } + + auto group_id = results.LastInsertedID(); + if (!group_id) + return false; + + query = StringFormat("INSERT INTO `bot_group_members` (`groups_index`, `bot_id`) VALUES ('%u', '%u')", group_id, leader_id); + results = QueryDatabase(query); + if (!results.Success()) { + error_message = results.ErrorMessage(); + return false; + } + + return true; +} + +bool BotDatabase::DeleteBotGroup(uint32 leader_id, std::string& error_message) +{ + if (!leader_id) + return false; + + uint32 group_id = GetGroupIDByLeaderID(leader_id, error_message); + if (!group_id || !error_message.empty()) + return false; + + std::string query = StringFormat("DELETE FROM `bot_group_members` WHERE `groups_index` = '%u'", group_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + error_message = results.ErrorMessage(); + return false; + } + + query = StringFormat("DELETE FROM `bot_groups` WHERE `groups_index` = '%u'", group_id); + results = QueryDatabase(query); + if (!results.Success()) { + error_message = results.ErrorMessage(); + return false; + } + + return true; +} + +bool BotDatabase::AddMemberToBotGroup(uint32 leader_id, uint32 member_id, std::string& error_message) +{ + if (!leader_id || !member_id) + return false; + + uint32 group_id = GetGroupIDByLeaderID(leader_id, error_message); + if (!group_id || !error_message.empty()) + return false; + + std::string query = StringFormat("INSERT INTO `bot_group_members` (`groups_index`, `bot_id`) VALUES ('%u', '%u')", group_id, member_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + error_message = results.ErrorMessage(); + return false; + } + + return true; +} + +bool BotDatabase::RemoveMemberFromBotGroup(uint32 member_id, std::string& error_message) +{ + if (!member_id) + return false; + + if (GetGroupIDByLeaderID(member_id, error_message)) + return DeleteBotGroup(member_id, error_message); + + if (!error_message.empty()) + return false; + + std::string query = StringFormat("DELETE FROM `bot_group_members` WHERE `bot_id` = '%u'", member_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + error_message = results.ErrorMessage(); + return false; + } + + return true; +} + +uint32 BotDatabase::GetGroupIDForLoadGroup(uint32 owner_id, std::string& group_name, std::string& error_message) +{ + if (!owner_id || group_name.empty()) + return 0; + + std::string query = StringFormat("SELECT `groups_index`, `group_name` FROM `vw_bot_groups` WHERE `owner_id` = '%u'", owner_id); + auto results = QueryDatabase(query); + if (!results.Success() || !results.RowCount()) { + error_message = results.ErrorMessage(); + return 0; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + if (!group_name.compare(row[1])) + return atoi(row[0]); + } + + return 0; +} + +std::map> BotDatabase::LoadGroup(std::string& group_name, std::string& error_message) +{ + std::map> group_list; + if (group_name.empty()) + return group_list; + + uint32 group_id = GetGroupIDByGroupName(group_name, error_message); + if (!group_id || !error_message.empty()) + return group_list; + + std::string query = StringFormat("SELECT `bot_id` FROM `bot_group_members` WHERE `groups_index` = '%u'", group_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + error_message = results.ErrorMessage(); + return group_list; + } + + for (auto row = results.begin(); row != results.end(); ++row) + group_list[group_id].push_back(atoi(row[0])); + + return group_list; +} + +std::list> BotDatabase::GetGroupsListByOwnerID(uint32 owner_id, std::string& error_message) +{ + std::list> groups_list; + if (!owner_id) + return groups_list; + + std::string query = StringFormat("SELECT `group_name`, `group_leader_name` FROM `vw_bot_groups` WHERE `owner_id` = '%u'", owner_id); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + error_message = results.ErrorMessage(); + return groups_list; + } + + for (auto row = results.begin(); row != results.end(); ++row) + groups_list.push_back(std::pair(row[0], row[1])); + + return groups_list; +} diff --git a/zone/bot_database.h b/zone/bot_database.h new file mode 100644 index 000000000..e98388716 --- /dev/null +++ b/zone/bot_database.h @@ -0,0 +1,87 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef BOT_DATABASE_H +#define BOT_DATABASE_H + +#include "../common/dbcore.h" +#include "../common/eq_packet_structs.h" + +#include +#include +#include + +class BotDatabase : public DBcore +{ + +public: + BotDatabase(); + BotDatabase(const char* host, const char* user, const char* passwd, const char* database, uint32 port); + virtual ~BotDatabase(); + + bool Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port); + + bool GetCommandSettings(std::map>> &bot_command_settings); + + // Bot command functions + bool GetInspectMessage(uint32 bot_id, InspectMessage_Struct* message); + bool SetInspectMessage(uint32 bot_id, const InspectMessage_Struct* message); + bool SetAllInspectMessages(uint32 owner_id, const InspectMessage_Struct* message); + + bool SetAllArmorColorBySlot(uint32 owner_id, int16 slot_id, uint32 rgb_value); + bool SetAllArmorColors(uint32 owner_id, uint32 rgb_value); + + bool SetHelmAppearance(uint32 owner_id, uint32 bot_id, bool show_flag = true); + bool SetAllHelmAppearances(uint32 owner_id, bool show_flag = true); + + bool ToggleHelmAppearance(uint32 owner_id, uint32 bot_id); + bool ToggleAllHelmAppearances(uint32 owner_id); + + bool SetFollowDistance(uint32 owner_id, uint32 bot_id, uint32 follow_distance); + bool SetAllFollowDistances(uint32 owner_id, uint32 follow_distance); + + uint32 Clone(uint32 owner_id, uint32 bot_id, const char* clone_name); + bool CloneInventory(uint32 owner_id, uint32 bot_id, uint32 clone_id); + + // Bot-group functions + bool DoesBotGroupExist(std::string& group_name); + + uint32 GetGroupIDByGroupName(std::string& group_name, std::string& error_message); + uint32 GetLeaderIDByGroupName(std::string& group_name, std::string& error_message); + std::string GetGroupNameByGroupID(uint32 group_id, std::string& error_message); + std::string GetGroupNameByLeaderID(uint32 leader_id, std::string& error_message); + uint32 GetGroupIDByLeaderID(uint32 leader_id, std::string& error_message); + uint32 GetLeaderIDByGroupID(uint32 group_id, std::string& error_message); + + uint32 GetGroupIDByMemberID(uint32 member_id, std::string& error_message); + + bool CreateBotGroup(std::string& group_name, uint32 leader_id, std::string& error_message); + bool DeleteBotGroup(uint32 leader_id, std::string& error_message); + bool AddMemberToBotGroup(uint32 leader_id, uint32 member_id, std::string& error_message); + bool RemoveMemberFromBotGroup(uint32 member_id, std::string& error_message); + + uint32 GetGroupIDForLoadGroup(uint32 owner_id, std::string& group_name, std::string& error_message); + std::map> LoadGroup(std::string& group_name, std::string& error_message); + + std::list> GetGroupsListByOwnerID(uint32 owner_id, std::string& error_message); +}; + +extern BotDatabase botdb; + +#endif diff --git a/zone/bot_structs.h b/zone/bot_structs.h index 09140ae60..c8b9623eb 100644 --- a/zone/bot_structs.h +++ b/zone/bot_structs.h @@ -1,3 +1,21 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #ifndef BOT_STRUCTS #define BOT_STRUCTS @@ -13,6 +31,7 @@ struct BotsAvailableList { uint16 BotClass; uint8 BotLevel; uint16 BotRace; + uint8 BotGender; }; struct BotGroup { diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 66afc345d..46d10c36f 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -1,3 +1,21 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #ifdef BOTS #include "bot.h" @@ -1025,7 +1043,7 @@ bool Bot::AI_IdleCastCheck() { // bard bots if(!AICastSpell(this, 100, SpellType_Cure)) { if(!AICastSpell(this, 100, SpellType_Heal)) { - if((!RuleB(Bots, BotBardUseOutOfCombatSongs) || !GetBardUseOutOfCombatSongs()) || !AICastSpell(this, 100, SpellType_Buff)) { // skips if rule is false + if((!RuleB(Bots, BotBardUseOutOfCombatSongs) || !GetAltOutOfCombatBehavior()) || !AICastSpell(this, 100, SpellType_Buff)) { // skips if rule is false if(!AICastSpell(this, 100, SpellType_InCombatBuff)) { // this tries to keep some combat buffs on the group until engaged code can pick up the buffing // } @@ -1261,7 +1279,7 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { return false; } - if(!AI_HasSpells()) + if (!AI_HasSpells()) return false; if(tar->GetAppearance() == eaDead) { @@ -1303,11 +1321,11 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { } // If there is still no spell id, then there isn't going to be one so we are done - if(botSpell.SpellId == 0) + if (botSpell.SpellId == 0) return false; // Can we cast this spell on this target? - if(!(spells[botSpell.SpellId].targettype==ST_GroupTeleport || spells[botSpell.SpellId].targettype == ST_Target || tar == this) + if (!(spells[botSpell.SpellId].targettype == ST_GroupTeleport || spells[botSpell.SpellId].targettype == ST_Target || tar == this) && !(tar->CanBuffStack(botSpell.SpellId, botLevel, true) >= 0)) return false; diff --git a/zone/client.cpp b/zone/client.cpp index f41e35bd2..6836b2a02 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,6 +44,9 @@ extern volatile bool RunLoops; #include "zonedb.h" #include "petitions.h" #include "command.h" +#ifdef BOTS +#include "bot_command.h" +#endif #include "string_ids.h" #include "guild_mgr.h" @@ -1046,6 +1049,24 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s break; } +#ifdef BOTS + if (message[0] == BOT_COMMAND_CHAR) { + if (bot_command_dispatch(this, message) == -2) { + if (parse->PlayerHasQuestSub(EVENT_COMMAND)) { + int i = parse->EventPlayer(EVENT_COMMAND, this, message, 0); + if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) { + Message(13, "Bot command '%s' not recognized.", message); + } + } + else { + if (!RuleB(Chat, SuppressCommandErrors)) + Message(13, "Bot command '%s' not recognized.", message); + } + } + break; + } +#endif + Mob* sender = this; if (GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); @@ -3561,7 +3582,7 @@ void Client::Insight(uint32 t_id) } strcat(resists," to disease."); - Message(0,"Your target is a level %i %s. It appears %s and %s for its level. It seems %s",who->GetLevel(),GetEQClassName(who->GetClass(),1),dmg,hitpoints,resists); + Message(0,"Your target is a level %i %s. It appears %s and %s for its level. It seems %s",who->GetLevel(),GetClassIDName(who->GetClass(),1),dmg,hitpoints,resists); } void Client::GetGroupAAs(GroupLeadershipAA_Struct *into) const { @@ -7546,9 +7567,14 @@ void Client::GarbleMessage(char *message, uint8 variance) int delimiter_count = 0; // Don't garble # commands - if (message[0] == '#') + if (message[0] == COMMAND_CHAR) return; +#ifdef BOTS + if (message[0] == BOT_COMMAND_CHAR) + return; +#endif + for (size_t i = 0; i < strlen(message); i++) { // Client expects hex values inside of a text link body if (message[i] == delimiter) { diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 9fc36a57e..adf477538 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1,5 +1,5 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -160,7 +160,7 @@ int32 Client::LevelRegen() bool sitting = IsSitting(); bool feigned = GetFeigned(); int level = GetLevel(); - bool bonus = GetRaceBitmask(GetBaseRace()) & RuleI(Character, BaseHPRegenBonusRaces); + bool bonus = GetPlayerRaceBit(GetBaseRace()) & RuleI(Character, BaseHPRegenBonusRaces); uint8 multiplier1 = bonus ? 2 : 1; int32 hp = 0; //these calculations should match up with the info from Monkly Business, which was last updated ~05/2008: http://www.monkly-business.net/index.php?pageid=abilities diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7aa4c0de5..fb7216b86 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2009 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3896,7 +3896,6 @@ void Client::Handle_OP_Camp(const EQApplicationPacket *app) { #ifdef BOTS // This block is necessary to clean up any bot objects owned by a Client - Bot::BotHealRotationsClear(this); Bot::BotOrderCampAll(this); #endif if (IsLFP()) diff --git a/zone/command.cpp b/zone/command.cpp index b5d060f87..dbbed07db 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemulator.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -86,7 +86,7 @@ void command_pf(Client *c, const Seperator *message); std::map commandlist; std::map commandaliases; -//All allocated CommandRecords get put in here so they get deleted on shutdown +// All allocated CommandRecords get put in here so they get deleted on shutdown LinkedList cleanup_commandlist; /* @@ -103,9 +103,9 @@ int command_notavail(Client *c, const char *message) return -1; } -/*****************************************************************************/ -/* the rest below here could be in a dynamically loaded module eventually */ -/*****************************************************************************/ +/************************************************************************** +/* the rest below here could be in a dynamically loaded module eventually * +/*************************************************************************/ /* @@ -163,7 +163,7 @@ int command_init(void) command_add("bind", "- Sets your targets bind spot to their current location", 200, command_bind) || #ifdef BOTS - command_add("bot", "- Type \"#bot help\" to the see the list of available commands for bots.", 0, command_bot) || + command_add("bot", "- Type \"#bot help\" or \"^help\" to the see the list of available commands for bots.", 0, command_bot) || #endif command_add("camerashake", "Shakes the camera on everyone's screen globally.", 80, command_camerashake) || @@ -9665,14 +9665,6 @@ void command_showspellslist(Client *c, const Seperator *sep) return; } -// All new code added to command.cpp ought to be BEFORE this comment line. Do no append code to this file below the BOTS code block. -#ifdef BOTS -// Function delegate to support the command interface for Bots with the client. -void command_bot(Client *c, const Seperator *sep) { - Bot::ProcessBotCommands(c, sep); -} -#endif - void command_raidloot(Client *c, const Seperator *sep) { if(!sep->arg[1][0]) { @@ -10842,4 +10834,30 @@ void command_reloadperlexportsettings(Client *c, const Seperator *sep) safe_delete(pack); } -} \ No newline at end of file +} + + +// All new code added to command.cpp should be BEFORE this comment line. Do no append code to this file below the BOTS code block. +#ifdef BOTS +#include "bot_command.h" +// Function delegate to support the command interface for Bots with the client. +void command_bot(Client *c, const Seperator *sep) +{ + std::string bot_message = sep->msg; + bot_message = bot_message.substr(bot_message.find_first_not_of("#bot")); + bot_message[0] = BOT_COMMAND_CHAR; + + if (bot_command_dispatch(c, bot_message.c_str()) == -2) { + if (parse->PlayerHasQuestSub(EVENT_COMMAND)) { + int i = parse->EventPlayer(EVENT_COMMAND, c, bot_message, 0); + if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) { + c->Message(13, "Bot command '%s' not recognized.", bot_message.c_str()); + } + } + else { + if (!RuleB(Chat, SuppressCommandErrors)) + c->Message(13, "Bot command '%s' not recognized.", bot_message.c_str()); + } + } +} +#endif diff --git a/zone/command.h b/zone/command.h index eb3633f57..987adf674 100644 --- a/zone/command.h +++ b/zone/command.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 12501b089..037649366 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -9,11 +9,11 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef EMBPERL @@ -1052,8 +1052,8 @@ void PerlembParser::ExportMobVariables(bool isPlayerQuest, bool isGlobalPlayerQu if(mob) { ExportVar(package_name.c_str(), "name", mob->GetName()); - ExportVar(package_name.c_str(), "race", GetRaceName(mob->GetRace())); - ExportVar(package_name.c_str(), "class", GetEQClassName(mob->GetClass())); + ExportVar(package_name.c_str(), "race", GetRaceIDName(mob->GetRace())); + ExportVar(package_name.c_str(), "class", GetClassIDName(mob->GetClass())); ExportVar(package_name.c_str(), "ulevel", mob->GetLevel()); ExportVar(package_name.c_str(), "userid", mob->GetID()); } diff --git a/zone/embxs.cpp b/zone/embxs.cpp index 664416587..8a1bde544 100644 --- a/zone/embxs.cpp +++ b/zone/embxs.cpp @@ -1,26 +1,30 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifdef EMBPERL #include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include "masterentity.h" #include "command.h" +#ifdef BOTS +#include "bot_command.h" +#endif #include "embperl.h" #include "embxs.h" diff --git a/zone/entity.h b/zone/entity.h index df0b327a5..986a60d99 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -466,7 +466,6 @@ private: #ifdef BOTS public: void AddBot(Bot* newBot, bool SendSpawnPacket = true, bool dontqueue = false); - void BotPickLock(Bot* rogue); bool RemoveBot(uint16 entityID); Mob* GetMobByBotID(uint32 botID); Bot* GetBotByBotID(uint32 botID); diff --git a/zone/groups.cpp b/zone/groups.cpp index d65bafcfe..353751b5b 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,6 +15,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #include "../common/global_define.h" #include "../common/eqemu_logsys.h" #include "masterentity.h" @@ -938,6 +939,41 @@ void Group::DisbandGroup() { safe_delete(outapp); } +void Group::GetMemberList(std::list& member_list, bool clear_list) +{ + if (clear_list) + member_list.clear(); + + for (auto member_iter : members) { + if (member_iter) + member_list.push_back(member_iter); + } +} + +void Group::GetClientList(std::list& client_list, bool clear_list) +{ + if (clear_list) + client_list.clear(); + + for (auto client_iter : members) { + if (client_iter && client_iter->IsClient()) + client_list.push_back(client_iter->CastToClient()); + } +} + +#ifdef BOTS +void Group::GetBotList(std::list& bot_list, bool clear_list) +{ + if (clear_list) + bot_list.clear(); + + for (auto bot_iter : members) { + if (bot_iter && bot_iter->IsBot()) + bot_list.push_back(bot_iter->CastToBot()); + } +} +#endif + bool Group::Process() { if(disbandcheck && !GroupCount()) return false; @@ -2294,6 +2330,30 @@ void Group::SetPuller(const char *NewPullerName) } } +bool Group::AmIMainTank(const char *mob_name) +{ + if (!mob_name) + return false; + + return !((bool)MainTankName.compare(mob_name)); +} + +bool Group::AmIMainAssist(const char *mob_name) +{ + if (!mob_name) + return false; + + return !((bool)MainTankName.compare(mob_name)); +} + +bool Group::AmIPuller(const char *mob_name) +{ + if (!mob_name) + return false; + + return !((bool)PullerName.compare(mob_name)); +} + bool Group::HasRole(Mob *m, uint8 Role) { if(!m) diff --git a/zone/groups.h b/zone/groups.h index 7dcbd848b..3da2aae54 100644 --- a/zone/groups.h +++ b/zone/groups.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -59,6 +59,11 @@ public: bool DelMemberOOZ(const char *Name); bool DelMember(Mob* oldmember,bool ignoresender = false); void DisbandGroup(); + void GetMemberList(std::list& member_list, bool clear_list = true); + void GetClientList(std::list& client_list, bool clear_list = true); +#ifdef BOTS + void GetBotList(std::list& bot_list, bool clear_list = true); +#endif bool IsGroupMember(Mob* client); bool IsGroupMember(const char *Name); bool Process(); @@ -123,6 +128,9 @@ public: const char *GetMainTankName() { return MainTankName.c_str(); } const char *GetMainAssistName() { return MainAssistName.c_str(); } const char *GetPullerName() { return PullerName.c_str(); } + bool AmIMainTank(const char *mob_name); + bool AmIMainAssist(const char *mob_name); + bool AmIPuller(const char *mob_name); void SetNPCMarker(const char *NewNPCMarkerName); void UnMarkNPC(uint16 ID); void SendMarkedNPCsToMember(Client *c, bool Clear = false); diff --git a/zone/heal_rotation.cpp b/zone/heal_rotation.cpp new file mode 100644 index 000000000..465f66f00 --- /dev/null +++ b/zone/heal_rotation.cpp @@ -0,0 +1,882 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "bot.h" + +#define SAFE_HP_RATIO_CLOTH 95.0f +#define SAFE_HP_RATIO_LEATHER 90.0f +#define SAFE_HP_RATIO_CHAIN 80.0f +#define SAFE_HP_RATIO_PLATE 75.0f + +#define CRITICAL_HP_RATIO_CLOTH 30.0f +#define CRITICAL_HP_RATIO_LEATHER 25.0f +#define CRITICAL_HP_RATIO_CHAIN 15.0f +#define CRITICAL_HP_RATIO_PLATE 10.0f + +HealRotation::HealRotation(Bot* hr_creator, uint32 interval_ms, bool fast_heals, bool adaptive_targeting, bool casting_override) +{ + m_member_pool.push_back(hr_creator); + + m_creation_time_ms = Timer::GetCurrentTime(); + m_last_heal_time_ms = m_creation_time_ms; + m_interval_ms = ((interval_ms >= CASTING_CYCLE_MINIMUM_INTERVAL) ? (interval_ms) : (CASTING_CYCLE_MINIMUM_INTERVAL)); + m_next_cast_time_ms = m_creation_time_ms; + m_next_poke_time_ms = m_creation_time_ms; + m_healing_stats_begin_ms = m_creation_time_ms; + m_fast_heals = fast_heals; + m_adaptive_targeting = adaptive_targeting; + m_casting_override = casting_override; + m_casting_target_poke = true; + m_active_heal_target = false; + + ResetArmorTypeHPLimits(); + + m_is_active = false; +} + +void HealRotation::SetIntervalMS(uint32 interval_ms) +{ + if (interval_ms > CASTING_CYCLE_MAXIMUM_INTERVAL) + interval_ms = CASTING_CYCLE_MAXIMUM_INTERVAL; + else if (interval_ms < CASTING_CYCLE_MINIMUM_INTERVAL) + interval_ms = CASTING_CYCLE_MINIMUM_INTERVAL; + + m_interval_ms = interval_ms; +} + +void HealRotation::SetIntervalS(uint32 interval_s) +{ + interval_s *= 1000; + if (interval_s > CASTING_CYCLE_MAXIMUM_INTERVAL) + interval_s = CASTING_CYCLE_MAXIMUM_INTERVAL; + else if (interval_s < CASTING_CYCLE_MINIMUM_INTERVAL) + interval_s = CASTING_CYCLE_MINIMUM_INTERVAL; + + m_interval_ms = interval_s; +} + +bool HealRotation::AddMemberToPool(Bot* hr_member) +{ + if (!hr_member) + return false; + if (!IsMemberClass(hr_member->GetClass())) + return false; + if (m_member_pool.size() >= RuleI(Bots, HealRotationMaxMembers)) + return false; + + for (auto find_iter : m_member_pool) { + if (find_iter == hr_member) + return false; + } + + m_member_pool.push_back(hr_member); + valid_state(); + + return true; +} + +bool HealRotation::AddTargetToPool(Mob* hr_target) +{ + if (!hr_target) + return false; + if (!valid_state()) + return false; + if (!IsTargetMobType(hr_target)) + return false; + if (m_target_pool.size() >= RuleI(Bots, HealRotationMaxTargets)) + return false; + + for (auto find_iter : m_target_pool) { + if (find_iter == hr_target) + return false; + } + + m_target_pool.push_back(hr_target); + + return true; +} + +bool HealRotation::RemoveMemberFromPool(Bot* hr_member) +{ + if (!hr_member) + return true; + + for (auto member_iter : m_member_pool) { + if (member_iter != hr_member) + continue; + + m_member_is_casting.erase(hr_member); + m_member_pool.remove(hr_member); + valid_state(); + return true; + } + return false; +} + +bool HealRotation::RemoveTargetFromPool(Mob* hr_target) +{ + if (!hr_target) + return true; + if (!valid_state()) + return true; + + for (auto target_iter : m_target_pool) { + if (target_iter != hr_target) + continue; + + m_target_healing_stats_2.erase(hr_target); + m_target_healing_stats_1.erase(hr_target); + m_target_pool.remove(hr_target); + m_casting_target_poke = false; + bias_targets(); + return true; + } + + return false; +} + +bool HealRotation::ClearMemberPool() +{ + m_is_active = false; + m_cycle_pool.clear(); + m_casting_target_poke = false; + m_active_heal_target = false; + + ClearTargetPool(); + + auto clear_list = m_member_pool; + for (auto member_iter : clear_list) + member_iter->LeaveHealRotationMemberPool(); + + return true; +} + +bool HealRotation::ClearTargetPool() +{ + m_is_active = false; + + auto clear_list = m_target_pool; + for (auto target_iter : clear_list) + target_iter->LeaveHealRotationTargetPool(); + + m_casting_target_poke = false; + bias_targets(); + + return m_target_pool.empty(); +} + +bool HealRotation::Start() +{ + m_is_active = false; + if (m_member_pool.empty() || m_target_pool.empty()) + return false; + + m_cycle_pool = m_member_pool; + m_is_active = true; + + return true; +} + +bool HealRotation::Stop() +{ + m_is_active = false; + m_active_heal_target = false; + m_cycle_pool.clear(); + + return true; +} + +Bot* HealRotation::CastingMember() +{ + if (!m_is_active) + return nullptr; + + if (m_cycle_pool.empty()) { + cycle_refresh(); + + if (m_cycle_pool.empty()) + return nullptr; + } + + return m_cycle_pool.front(); +} + +bool HealRotation::PokeCastingTarget() +{ + if (!m_is_active) + return false; + + uint32 current_time = Timer::GetCurrentTime(); + + if (current_time < m_next_poke_time_ms) { + auto hr_target = CastingTarget(); + if (hr_target && hr_target->DontHealMeBefore() > current_time) + m_next_poke_time_ms = current_time; + else + return m_active_heal_target; + } + + m_next_poke_time_ms = (current_time + POKE_PROPAGATION_DELAY); + + if (m_healing_stats_begin_ms + HEALING_STATS_RESET_INTERVAL <= current_time) + StartNewTargetHealingStatsCycle(current_time); + + m_casting_target_poke = false; + bias_targets(); + + return m_active_heal_target; +} + +Mob* HealRotation::CastingTarget() +{ + if (!m_is_active) + return nullptr; + if (!m_active_heal_target) + return nullptr; + + return m_target_pool.front(); +} + +bool HealRotation::AdvanceRotation(bool use_interval) +{ + m_cycle_pool.pop_front(); + m_next_cast_time_ms = Timer::GetCurrentTime(); + if (use_interval) { + m_next_poke_time_ms = m_next_cast_time_ms; + m_next_cast_time_ms += m_interval_ms; + } + else { + m_next_cast_time_ms += ADVANCE_ROTATION_MINIMUM_INTERVAL; + } + + if (m_cycle_pool.empty()) + cycle_refresh(); + + return (!m_cycle_pool.empty()); +} + +bool HealRotation::IsMemberInPool(Bot* hr_member) +{ + if (!hr_member) + return false; + if (m_member_pool.empty()) + return false; + + for (auto find_iter : m_member_pool) { + if (find_iter == hr_member) + return true; + } + + return false; +} + +bool HealRotation::IsTargetInPool(Mob* hr_target) +{ + if (!hr_target) + return false; + if (m_target_pool.empty()) + return false; + + for (auto find_iter : m_target_pool) { + if (find_iter == hr_target) + return true; + } + + return false; +} + +void HealRotation::SetMemberIsCasting(Bot* hr_member, bool flag) +{ + if (!hr_member) + return; + if (!IsMemberInPool(hr_member)) + return; + + m_member_is_casting[hr_member] = flag; +} + +bool HealRotation::MemberIsCasting(Bot* hr_member) +{ + if (!hr_member) + return false; + if (m_member_is_casting.find(hr_member) == m_member_is_casting.end()) + return false; + + return m_member_is_casting[hr_member]; +} + +void HealRotation::UpdateTargetHealingStats(Mob* hr_target) +{ + if (!hr_target) + return; + if (!IsTargetInPool(hr_target)) + return; + + m_last_heal_time_ms = Timer::GetCurrentTime(); + + m_target_healing_stats_1[hr_target].last_heal_time_ms = m_last_heal_time_ms; + ++m_target_healing_stats_1[hr_target].heal_count; +} + +void HealRotation::StartNewTargetHealingStatsCycle(uint32 current_time) +{ + m_target_healing_stats_2 = m_target_healing_stats_1; + m_target_healing_stats_1.clear(); + + m_healing_stats_begin_ms = current_time; +} + +uint32 HealRotation::HealCount(Mob* hr_target) +{ + if (!hr_target) + return 0; + + uint32 heal_count = 0; + if (m_target_healing_stats_1.find(hr_target) != m_target_healing_stats_1.end()) + heal_count += m_target_healing_stats_1[hr_target].heal_count; + + return heal_count; +} + +uint32 HealRotation::ExtendedHealCount(Mob* hr_target) +{ + if (!hr_target) + return 0; + + uint32 heal_count = 0; + if (m_target_healing_stats_1.find(hr_target) != m_target_healing_stats_1.end()) + heal_count += m_target_healing_stats_1[hr_target].heal_count; + if (m_target_healing_stats_2.find(hr_target) != m_target_healing_stats_2.end()) + heal_count += m_target_healing_stats_2[hr_target].heal_count; + + return heal_count; +} + +float HealRotation::HealFrequency(Mob* hr_target) +{ + if (!hr_target) + return 0.0f; + + float time_base = 0; + uint32 heal_count = 0; + if (m_target_healing_stats_1.find(hr_target) != m_target_healing_stats_1.end()) { + heal_count += m_target_healing_stats_1[hr_target].heal_count; + time_base = (Timer::GetCurrentTime() - m_target_healing_stats_1[hr_target].last_heal_time_ms); + } + + time_base /= 1000; + if (!time_base) + time_base = HEALING_STATS_RESET_INTERVAL_S; + + if (heal_count) + return ((float)1 / (time_base / heal_count)); + else + return ((float)1 / time_base); +} + +float HealRotation::ExtendedHealFrequency(Mob* hr_target) +{ + if (!hr_target) + return 0.0f; + + uint32 current_time = Timer::GetCurrentTime(); + uint32 heal_count = 0; + float time_base = 0; + if (m_target_healing_stats_1.find(hr_target) != m_target_healing_stats_1.end()) { + heal_count += m_target_healing_stats_1[hr_target].heal_count; + time_base = (current_time - m_target_healing_stats_1[hr_target].last_heal_time_ms + HEALING_STATS_RESET_INTERVAL); + } + if (m_target_healing_stats_2.find(hr_target) != m_target_healing_stats_2.end()) { + heal_count += m_target_healing_stats_2[hr_target].heal_count; + time_base = (current_time - m_target_healing_stats_2[hr_target].last_heal_time_ms); + } + + time_base /= 1000; + if (!time_base) + time_base = (HEALING_STATS_RESET_INTERVAL_S * 2); + + if (heal_count) + return ((float)1 / (time_base / heal_count)); + else + return ((float)1 / time_base); +} + +HealingStats* HealRotation::TargetHealingStats1(Mob* hr_target) +{ + if (!hr_target) + return nullptr; + if (m_target_healing_stats_1.find(hr_target) == m_target_healing_stats_1.end()) + return nullptr; + + return &m_target_healing_stats_1[hr_target]; +} + +HealingStats* HealRotation::TargetHealingStats2(Mob* hr_target) +{ + if (!hr_target) + return nullptr; + if (m_target_healing_stats_2.find(hr_target) == m_target_healing_stats_2.end()) + return nullptr; + + return &m_target_healing_stats_2[hr_target]; +} + +bool HealRotation::SetArmorTypeSafeHPRatio(uint8 armor_type, float hp_ratio) +{ + if (armor_type >= ARMOR_TYPE_COUNT) + return false; + if (hp_ratio < CRITICAL_HP_RATIO_BASE || hp_ratio > SAFE_HP_RATIO_BASE) + return false; + if (hp_ratio < m_critical_hp_ratio[armor_type]) + return false; + + m_safe_hp_ratio[armor_type] = hp_ratio; + + return true; +} + +bool HealRotation::SetArmorTypeCriticalHPRatio(uint8 armor_type, float hp_ratio) +{ + if (armor_type >= ARMOR_TYPE_COUNT) + return false; + if (hp_ratio < CRITICAL_HP_RATIO_BASE || hp_ratio > SAFE_HP_RATIO_BASE) + return false; + if (hp_ratio > m_safe_hp_ratio[armor_type]) + return false; + + m_critical_hp_ratio[armor_type] = hp_ratio; + + return true; +} + +float HealRotation::ArmorTypeSafeHPRatio(uint8 armor_type) +{ + if (armor_type < ARMOR_TYPE_COUNT) + return m_safe_hp_ratio[armor_type]; + else + return m_safe_hp_ratio[ARMOR_TYPE_UNKNOWN]; +} + +float HealRotation::ArmorTypeCriticalHPRatio(uint8 armor_type) +{ + if (armor_type < ARMOR_TYPE_COUNT) + return m_critical_hp_ratio[armor_type]; + else + return m_critical_hp_ratio[ARMOR_TYPE_UNKNOWN]; +} + +void HealRotation::ResetArmorTypeHPLimits() +{ + m_safe_hp_ratio[ARMOR_TYPE_UNKNOWN] = SAFE_HP_RATIO_BASE; + m_safe_hp_ratio[ARMOR_TYPE_CLOTH] = SAFE_HP_RATIO_CLOTH; + m_safe_hp_ratio[ARMOR_TYPE_LEATHER] = SAFE_HP_RATIO_LEATHER; + m_safe_hp_ratio[ARMOR_TYPE_CHAIN] = SAFE_HP_RATIO_CHAIN; + m_safe_hp_ratio[ARMOR_TYPE_PLATE] = SAFE_HP_RATIO_PLATE; + + m_critical_hp_ratio[ARMOR_TYPE_UNKNOWN] = CRITICAL_HP_RATIO_BASE; + m_critical_hp_ratio[ARMOR_TYPE_CLOTH] = CRITICAL_HP_RATIO_CLOTH; + m_critical_hp_ratio[ARMOR_TYPE_LEATHER] = CRITICAL_HP_RATIO_LEATHER; + m_critical_hp_ratio[ARMOR_TYPE_CHAIN] = CRITICAL_HP_RATIO_CHAIN; + m_critical_hp_ratio[ARMOR_TYPE_PLATE] = CRITICAL_HP_RATIO_PLATE; +} + +bool HealRotation::valid_state() +{ + m_member_pool.remove(nullptr); + m_member_pool.remove_if([](Mob* l) {return (!IsMemberClass(l->GetClass())); }); + + cycle_refresh(); + + if (m_member_pool.empty()) + ClearTargetPool(); // Consumes HealRotation at this point + + return (!m_member_pool.empty()); +} + +void HealRotation::cycle_refresh() +{ + m_is_active = false; + m_cycle_pool.clear(); + if (m_member_pool.empty()) + return; + + m_cycle_pool = m_member_pool; + + m_is_active = true; +} + +bool HealRotation::healable_target(bool use_class_at, bool critical_only) +{ + if (m_target_pool.empty()) + return false; + + auto healable_target = m_target_pool.front(); + if (!healable_target) + return false; + if (healable_target->DontHealMeBefore() > Timer::GetCurrentTime()) + return false; + if (healable_target->GetAppearance() == eaDead) + return false; + + if (use_class_at) { + if (critical_only && healable_target->GetHPRatio() > m_critical_hp_ratio[ClassArmorType(healable_target->GetClass())]) + return false; + if (healable_target->GetHPRatio() > m_safe_hp_ratio[ClassArmorType(healable_target->GetClass())]) + return false; + if (healable_target->IsBerserk() && (healable_target->GetClass() == WARRIOR || healable_target->GetClass() == BERSERKER)) { + if (healable_target->GetHPRatio() <= RuleI(Combat, BerserkerFrenzyEnd) && healable_target->GetHPRatio() > m_critical_hp_ratio[ClassArmorType(healable_target->GetClass())]) + return false; + } + } + else { + if (critical_only && healable_target->GetHPRatio() > CRITICAL_HP_RATIO_BASE) + return false; + if (healable_target->GetHPRatio() > SAFE_HP_RATIO_BASE) + return false; + if (healable_target->IsBerserk() && (healable_target->GetClass() == WARRIOR || healable_target->GetClass() == BERSERKER)) { + if (healable_target->GetHPRatio() <= RuleI(Combat, BerserkerFrenzyEnd) && healable_target->GetHPRatio() > CRITICAL_HP_RATIO_BASE) + return false; + } + } + + return true; +} + +void HealRotation::bias_targets() +{ +#define LT_HPRATIO(l, r) (l->GetHPRatio() < r->GetHPRatio()) +#define LT_ARMTYPE(l, r) (ClassArmorType(l->GetClass()) < ClassArmorType(r->GetClass())) + +#define EQ_ALIVE(l, r) (l->GetAppearance() != eaDead && r->GetAppearance() != eaDead) +#define EQ_READY(l, r, ct) (l->DontHealMeBefore() <= ct && r->DontHealMeBefore() <= ct) +#define EQ_TANK(l, r) ((l->HasGroup() && l->GetGroup()->AmIMainTank(l->GetCleanName())) && (r->HasGroup() && r->GetGroup()->AmIMainTank(r->GetCleanName()))) +#define EQ_HEALER(l, r) (IsMemberClass(l->GetClass()) && IsMemberClass(r->GetClass())) +#define EQ_ARMTYPE(l, r) (ClassArmorType(l->GetClass()) == ClassArmorType(r->GetClass())) +#define EQ_ATCRIT(l, r) (l->GetHPRatio() <= (*l->TargetOfHealRotation())->ArmorTypeCriticalHPRatio(ClassArmorType(l->GetClass())) && \ + r->GetHPRatio() <= (*r->TargetOfHealRotation())->ArmorTypeCriticalHPRatio(ClassArmorType(r->GetClass()))) +#define EQ_ATWOUND(l, r) (l->GetHPRatio() <= (*l->TargetOfHealRotation())->ArmorTypeSafeHPRatio(ClassArmorType(l->GetClass())) && \ + r->GetHPRatio() <= (*r->TargetOfHealRotation())->ArmorTypeSafeHPRatio(ClassArmorType(r->GetClass()))) + +#define GT_ALIVE(l, r) (l->GetAppearance() != eaDead && r->GetAppearance() == eaDead) +#define GT_READY(l, r, ct) (l->DontHealMeBefore() <= ct && r->DontHealMeBefore() > ct) +#define GT_TANK(l, r) ((l->HasGroup() && l->GetGroup()->AmIMainTank(l->GetCleanName())) && (!r->HasGroup() || !r->GetGroup()->AmIMainTank(r->GetCleanName()))) +#define GT_HEALER(l, r) (IsMemberClass(l->GetClass()) && !IsMemberClass(r->GetClass())) +#define GT_HEALFREQ(l, r) (l->HealRotationHealFrequency() > r->HealRotationHealFrequency()) +#define GT_HEALCNT(l, r) (l->HealRotationHealCount() > r->HealRotationHealCount()) +#define GT_ATCRIT(l, r) (l->GetHPRatio() <= (*l->TargetOfHealRotation())->ArmorTypeCriticalHPRatio(ClassArmorType(l->GetClass())) && \ + r->GetHPRatio() > (*r->TargetOfHealRotation())->ArmorTypeCriticalHPRatio(ClassArmorType(r->GetClass()))) +#define GT_XHEALFREQ(l, r) (l->HealRotationExtendedHealFrequency() > r->HealRotationExtendedHealFrequency()) +#define GT_XHEALCNT(l, r) (l->HealRotationExtendedHealCount() > r->HealRotationExtendedHealCount()) +#define GT_ATWOUND(l, r) (l->GetHPRatio() <= (*l->TargetOfHealRotation())->ArmorTypeSafeHPRatio(ClassArmorType(l->GetClass())) && \ + r->GetHPRatio() > (*r->TargetOfHealRotation())->ArmorTypeSafeHPRatio(ClassArmorType(r->GetClass()))) + + if (m_target_pool.empty()) { + m_casting_target_poke = true; + m_active_heal_target = false; + return; + } + + // attempt to clear invalid target pool entries + m_target_pool.remove(nullptr); + m_target_pool.remove_if([](Mob* l) { return (!IsTargetMobType(l)); }); + + uint32 sort_type = 0; // debug + + while (m_target_pool.size() > 1 && !m_casting_target_poke && !m_adaptive_targeting) { // standard behavior + sort_type = 1; + m_target_pool.sort([](Mob* l, Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && GT_TANK(l, r)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && EQ_TANK(l, r) && LT_HPRATIO(l, r)) + return true; + + return false; + }); + if (m_target_pool.front()->HasGroup() && m_target_pool.front()->GetGroup()->AmIMainTank(m_target_pool.front()->GetCleanName()) && healable_target(false)) + break; + + sort_type = 2; + m_target_pool.sort([](Mob* l, Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && GT_HEALER(l, r)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && EQ_HEALER(l, r) && LT_HPRATIO(l, r)) + return true; + + return false; + }); + if (IsMemberClass(m_target_pool.front()->GetClass()) && healable_target(false)) + break; + + sort_type = 3; // default + m_target_pool.sort([](const Mob* l, const Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && LT_HPRATIO(l, r)) + return true; + + return false; + }); + + break; + } + + while (m_target_pool.size() > 1 && !m_casting_target_poke && m_adaptive_targeting) { // adaptive targeting behavior + sort_type = 101; + m_target_pool.sort([](Mob* l, Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && GT_HEALFREQ(l, r)) + return true; + + return false; + }); + if (healable_target(true, true)) + break; + + sort_type = 102; + m_target_pool.sort([](Mob* l, Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && GT_HEALCNT(l, r)) + return true; + + return false; + }); + if (healable_target(true, true)) + break; + + sort_type = 103; + m_target_pool.sort([](Mob* l, Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && GT_TANK(l, r)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && EQ_TANK(l, r) && LT_HPRATIO(l, r)) + return true; + + return false; + }); + if (m_target_pool.front()->HasGroup() && m_target_pool.front()->GetGroup()->AmIMainTank(m_target_pool.front()->GetCleanName()) && healable_target(true, true)) + break; + + sort_type = 104; + m_target_pool.sort([](const Mob* l, const Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && GT_HEALER(l, r)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && EQ_HEALER(l, r) && LT_HPRATIO(l, r)) + return true; + + return false; + }); + if (IsMemberClass(m_target_pool.front()->GetClass()) && healable_target(true, true)) + break; + + sort_type = 105; + m_target_pool.sort([](const Mob* l, const Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && GT_ATCRIT(l, r)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && EQ_ATCRIT(l, r) && LT_ARMTYPE(l, r)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && EQ_ATCRIT(l, r) && EQ_ARMTYPE(l, r) && LT_HPRATIO(l, r)) + return true; + + return false; + }); + if (healable_target(true, true)) + break; + + sort_type = 106; + m_target_pool.sort([](Mob* l, Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && GT_XHEALFREQ(l, r)) + return true; + + return false; + }); + if (healable_target(true)) + break; + + sort_type = 107; + m_target_pool.sort([](Mob* l, Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && GT_XHEALCNT(l, r)) + return true; + + return false; + }); + if (healable_target(true)) + break; + + sort_type = 108; + m_target_pool.sort([](const Mob* l, const Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && GT_ATWOUND(l, r)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && EQ_ATWOUND(l, r) && LT_ARMTYPE(l, r)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && EQ_ATWOUND(l, r) && EQ_ARMTYPE(l, r) && LT_HPRATIO(l, r)) + return true; + + return false; + }); + if (healable_target()) + break; + + sort_type = 109; // default + m_target_pool.sort([](const Mob* l, const Mob* r) { + if (GT_ALIVE(l, r)) + return true; + uint32 current_time = Timer::GetCurrentTime(); + if (EQ_ALIVE(l, r) && GT_READY(l, r, current_time)) + return true; + if (EQ_ALIVE(l, r) && EQ_READY(l, r, current_time) && LT_HPRATIO(l, r)) + return true; + + return false; + }); + + break; + } + + m_active_heal_target = healable_target(false); + if (!m_active_heal_target) + m_active_heal_target = healable_target(); + + m_casting_target_poke = true; + +#if (EQDEBUG >= 12) + Log.Out(Logs::General, Logs::Error, "HealRotation::bias_targets() - *** Post-processing state ***"); + Log.Out(Logs::General, Logs::Error, "HealRotation Settings:"); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_interval_ms = %u", m_interval_ms); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_next_cast_time_ms = %u (current_time: %u, time_diff: %i)", m_next_cast_time_ms, Timer::GetCurrentTime(), ((int32)Timer::GetCurrentTime() - (int32)m_next_cast_time_ms)); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_next_poke_time_ms = %u (current_time: %u, time_diff: %i)", m_next_poke_time_ms, Timer::GetCurrentTime(), ((int32)Timer::GetCurrentTime() - (int32)m_next_poke_time_ms)); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_fast_heals = %s", ((m_fast_heals) ? ("true") : ("false"))); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_adaptive_targeting = %s", ((m_adaptive_targeting) ? ("true") : ("false"))); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_casting_override = %s", ((m_casting_override) ? ("true") : ("false"))); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_casting_target_poke = %s", ((m_casting_target_poke) ? ("true") : ("false"))); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_active_heal_target = %s", ((m_active_heal_target) ? ("true") : ("false"))); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_is_active = %s", ((m_is_active) ? ("true") : ("false"))); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_member_list.size() = %i", m_member_pool.size()); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_cycle_list.size() = %i", m_cycle_pool.size()); + Log.Out(Logs::General, Logs::Error, "HealRotation::m_target_list.size() = %i", m_target_pool.size()); + if (m_member_pool.size()) { Log.Out(Logs::General, Logs::Error, "(std::shared_ptr::use_count() = %i", m_member_pool.front()->MemberOfHealRotation()->use_count()); } + else { Log.Out(Logs::General, Logs::Error, "(std::shared_ptr::use_count() = unknown (0)"); } + Log.Out(Logs::General, Logs::Error, "HealRotation Members:"); + int member_index = 0; + for (auto mlist_iter : m_member_pool) { + if (!mlist_iter) { continue; } + Log.Out(Logs::General, Logs::Error, "(%i) %s (hrcast: %c)", (++member_index), mlist_iter->GetCleanName(), ((mlist_iter->AmICastingForHealRotation())?('T'):('F'))); + } + if (!member_index) { Log.Out(Logs::General, Logs::Error, "(0) None"); } + Log.Out(Logs::General, Logs::Error, "HealRotation Cycle:"); + int cycle_index = 0; + for (auto clist_iter : m_cycle_pool) { + if (!clist_iter) { continue; } + Log.Out(Logs::General, Logs::Error, "(%i) %s", (++cycle_index), clist_iter->GetCleanName()); + } + if (!cycle_index) { Log.Out(Logs::General, Logs::Error, "(0) None"); } + Log.Out(Logs::General, Logs::Error, "HealRotation Targets: (sort type: %u)", sort_type); + int target_index = 0; + + for (auto tlist_iter : m_target_pool) { + if (!tlist_iter) { continue; } + Log.Out(Logs::General, Logs::Error, "(%i) %s (hp: %3.1f%%, at: %u, dontheal: %c, crit(base): %c(%c), safe(base): %c(%c), hcnt(ext): %u(%u), hfreq(ext): %f(%f))", + (++target_index), tlist_iter->GetCleanName(), + tlist_iter->GetHPRatio(), + ClassArmorType(tlist_iter->GetClass()), + ((tlist_iter->DontHealMeBefore() > Timer::GetCurrentTime()) ? ('T') : ('F')), + ((tlist_iter->GetHPRatio()>m_critical_hp_ratio[ClassArmorType(tlist_iter->GetClass())]) ? ('F') : ('T')), + ((tlist_iter->GetHPRatio()>m_critical_hp_ratio[ARMOR_TYPE_UNKNOWN]) ? ('F') : ('T')), + ((tlist_iter->GetHPRatio()>m_safe_hp_ratio[ClassArmorType(tlist_iter->GetClass())]) ? ('T') : ('F')), + ((tlist_iter->GetHPRatio()>m_safe_hp_ratio[ARMOR_TYPE_UNKNOWN]) ? ('T') : ('F')), + tlist_iter->HealRotationHealCount(), + tlist_iter->HealRotationExtendedHealCount(), + tlist_iter->HealRotationHealFrequency(), + tlist_iter->HealRotationExtendedHealFrequency()); + } + if (!target_index) { Log.Out(Logs::General, Logs::Error, "(0) None (hp: 0.0\%, at: 0, dontheal: F, crit(base): F(F), safe(base): F(F), hcnt(ext): 0(0), hfreq(ext): 0.0(0.0))"); } +#endif +} + +bool HealRotation::IsMemberClass(uint8 class_id) +{ + switch (class_id) { + case CLERIC: + case DRUID: + case SHAMAN: + return true; + default: + return false; + } +} + +bool HealRotation::IsTargetMobType(Mob* target_mob) +{ + if (!target_mob) + return false; + if (!target_mob->IsClient() && !target_mob->IsBot() && !target_mob->IsPet()) + return false; + if (target_mob->IsPet() && (!target_mob->GetOwner() || (!target_mob->GetOwner()->IsClient() && !target_mob->GetOwner()->IsBot()))) + return false; + + return true; +} diff --git a/zone/heal_rotation.h b/zone/heal_rotation.h new file mode 100644 index 000000000..cfe0b0d5d --- /dev/null +++ b/zone/heal_rotation.h @@ -0,0 +1,148 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef HEAL_ROTATION_H +#define HEAL_ROTATION_H + +#include "mob.h" + +#define CASTING_CYCLE_MINIMUM_INTERVAL 1000 +#define CASTING_CYCLE_MINIMUM_INTERVAL_S 1 +#define CASTING_CYCLE_MAXIMUM_INTERVAL 30000 +#define CASTING_CYCLE_MAXIMUM_INTERVAL_S 30 +#define CASTING_CYCLE_DEFAULT_INTERVAL 5000 +#define CASTING_CYCLE_DEFAULT_INTERVAL_S 5 +#define POKE_PROPAGATION_DELAY 250 +#define ADVANCE_ROTATION_MINIMUM_INTERVAL 100 +#define HEALING_STATS_RESET_INTERVAL 60000 +#define HEALING_STATS_RESET_INTERVAL_S 60 + +#define SAFE_HP_RATIO_BASE 95.0f +#define CRITICAL_HP_RATIO_BASE 10.0f + +struct HealingStats +{ + uint32 last_heal_time_ms; + uint32 heal_count; +}; + +// Both members and targets use a shared_ptr to keep track of their HealRotation instance +class HealRotation +{ +public: + HealRotation(Bot* hr_creator, uint32 interval_ms = CASTING_CYCLE_DEFAULT_INTERVAL, bool fast_heals = false, bool adaptive_targeting = false, bool casting_override = false); + + void SetIntervalMS(uint32 interval_ms); + void SetIntervalS(uint32 interval_s); + void SetFastHeals(bool flag) { m_fast_heals = flag; } + void SetAdaptiveTargeting(bool flag) { m_adaptive_targeting = flag; } + void SetCastingOverride(bool flag) { m_casting_override = flag; } + bool AddMemberToPool(Bot* hr_member); + bool AddTargetToPool(Mob* hr_target); + + uint32 CreationTimeMS() { return m_creation_time_ms; } + uint32 LastHealTimeMS() { return m_last_heal_time_ms; } + uint32 IntervalMS() { return m_interval_ms; } + uint32 IntervalS() { return (m_interval_ms / 1000); } + bool FastHeals() { return m_fast_heals; } + bool AdaptiveTargeting() { return m_adaptive_targeting; } + bool CastingOverride() { return m_casting_override; } + bool RemoveMemberFromPool(Bot* hr_member); + bool RemoveTargetFromPool(Mob* hr_target); + + bool ClearMemberPool(); + bool ClearTargetPool(); + + bool Start(); + bool Stop(); + + bool IsActive() { return m_is_active; } + bool CastingReady() { return (Timer::GetCurrentTime() >= m_next_cast_time_ms); } + Bot* CastingMember(); + bool PokeCastingTarget(); + Mob* CastingTarget(); + bool AdvanceRotation(bool use_interval = true); + + std::list* MemberList() { return &m_member_pool; } + std::list* CycleList() { return &m_cycle_pool; } + std::list* TargetList() { return &m_target_pool; } + + bool IsMemberInPool(Bot* hr_member); + bool IsTargetInPool(Mob* hr_target); + + void SetMemberIsCasting(Bot* hr_member, bool flag = true); + bool MemberIsCasting(Bot* hr_member); + + void UpdateTargetHealingStats(Mob* hr_target); + void StartNewTargetHealingStatsCycle(uint32 current_time); + uint32 HealCount(Mob* hr_target); + uint32 ExtendedHealCount(Mob* hr_target); + float HealFrequency(Mob* hr_target); + float ExtendedHealFrequency(Mob* hr_target); + HealingStats* TargetHealingStats1(Mob* hr_target); + HealingStats* TargetHealingStats2(Mob* hr_target); + + bool SetArmorTypeSafeHPRatio(uint8 armor_type, float hp_ratio); + bool SetArmorTypeCriticalHPRatio(uint8 armor_type, float hp_ratio); + + float ArmorTypeSafeHPRatio(uint8 armor_type); + float ArmorTypeCriticalHPRatio(uint8 armor_type); + + void ResetArmorTypeHPLimits(); + + static bool IsMemberClass(uint8 class_id); + static bool IsTargetMobType(Mob* target_mob); + +private: + bool valid_state(); + void cycle_refresh(); + bool healable_target(bool use_class_at = true, bool critical_only = false); + void bias_targets(); + + uint32 m_creation_time_ms; + uint32 m_last_heal_time_ms; + uint32 m_interval_ms; + uint32 m_next_cast_time_ms; + uint32 m_next_poke_time_ms; + uint32 m_healing_stats_begin_ms; + bool m_fast_heals; + bool m_adaptive_targeting; + bool m_casting_override; + bool m_casting_target_poke; + bool m_active_heal_target; + + bool m_is_active; + + std::list m_member_pool; + std::list m_cycle_pool; + std::list m_target_pool; + + std::map m_member_is_casting; + + std::map m_target_healing_stats_1; + std::map m_target_healing_stats_2; + + float m_safe_hp_ratio[ARMOR_TYPE_COUNT]; + float m_critical_hp_ratio[ARMOR_TYPE_COUNT]; + + friend class std::_Ref_count_obj; + HealRotation(HealRotation* allocator_shunt) {}; +}; + +#endif diff --git a/zone/inventory.cpp b/zone/inventory.cpp index e1904d59f..9f7f061a0 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2020,10 +2020,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { void Client::DyeArmor(DyeStruct* dye){ int16 slot=0; for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_TINT_END; i++) { - if (m_pp.item_tint[i].RGB.Blue != dye->dye[i].RGB.Blue || - m_pp.item_tint[i].RGB.Red != dye->dye[i].RGB.Red || - m_pp.item_tint[i].RGB.Green != dye->dye[i].RGB.Green - ) { + if ((m_pp.item_tint[i].Color & 0x00FFFFFF) != (dye->dye[i].Color & 0x00FFFFFF)) { slot = m_inv.HasItem(32557, 1, invWherePersonal); if (slot != INVALID_INDEX){ DeleteItemInInventory(slot,1,true); diff --git a/zone/mob.cpp b/zone/mob.cpp index 0e2cd7d88..21458a2d7 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -473,6 +473,10 @@ Mob::~Mob() safe_delete(PathingRouteUpdateTimerShort); safe_delete(PathingRouteUpdateTimerLong); UninitializeBuffSlots(); + +#ifdef BOTS + LeaveHealRotationTargetPool(); +#endif } uint32 Mob::GetAppearanceValue(EmuAppearance iAppearance) { @@ -1766,8 +1770,7 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture, bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) { - if (IsPlayerRace(GetRace())) - { + if (IsPlayerRace(GetRace())) { uint8 Gender = GetGender(); uint8 Texture = 0xFF; uint8 HelmTexture = 0xFF; @@ -1788,160 +1791,158 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) LuclinFace = zone->random.Int(0, 7); // Adjust all settings based on the min and max for each feature of each race and gender - switch (GetRace()) - { - case 1: // Human - HairColor = zone->random.Int(0, 19); - if (Gender == 0) { - BeardColor = HairColor; - HairStyle = zone->random.Int(0, 3); - Beard = zone->random.Int(0, 5); - } - if (Gender == 1) { - HairStyle = zone->random.Int(0, 2); - } - break; - case 2: // Barbarian - HairColor = zone->random.Int(0, 19); + switch (GetRace()) { + case HUMAN: + HairColor = zone->random.Int(0, 19); + if (Gender == MALE) { + BeardColor = HairColor; + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); + } + if (Gender == FEMALE) { + HairStyle = zone->random.Int(0, 2); + } + break; + case BARBARIAN: + HairColor = zone->random.Int(0, 19); + LuclinFace = zone->random.Int(0, 87); + if (Gender == MALE) { + BeardColor = HairColor; + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); + } + if (Gender == FEMALE) { + HairStyle = zone->random.Int(0, 2); + } + break; + case ERUDITE: + if (Gender == MALE) { + BeardColor = zone->random.Int(0, 19); + Beard = zone->random.Int(0, 5); + LuclinFace = zone->random.Int(0, 57); + } + if (Gender == FEMALE) { LuclinFace = zone->random.Int(0, 87); - if (Gender == 0) { - BeardColor = HairColor; - HairStyle = zone->random.Int(0, 3); - Beard = zone->random.Int(0, 5); - } - if (Gender == 1) { - HairStyle = zone->random.Int(0, 2); - } - break; - case 3: // Erudite - if (Gender == 0) { - BeardColor = zone->random.Int(0, 19); - Beard = zone->random.Int(0, 5); - LuclinFace = zone->random.Int(0, 57); - } - if (Gender == 1) { - LuclinFace = zone->random.Int(0, 87); - } - break; - case 4: // WoodElf - HairColor = zone->random.Int(0, 19); - if (Gender == 0) { - HairStyle = zone->random.Int(0, 3); - } - if (Gender == 1) { - HairStyle = zone->random.Int(0, 2); - } - break; - case 5: // HighElf - HairColor = zone->random.Int(0, 14); - if (Gender == 0) { - HairStyle = zone->random.Int(0, 3); - LuclinFace = zone->random.Int(0, 37); - BeardColor = HairColor; - } - if (Gender == 1) { - HairStyle = zone->random.Int(0, 2); - } - break; - case 6: // DarkElf - HairColor = zone->random.Int(13, 18); - if (Gender == 0) { - HairStyle = zone->random.Int(0, 3); - LuclinFace = zone->random.Int(0, 37); - BeardColor = HairColor; - } - if (Gender == 1) { - HairStyle = zone->random.Int(0, 2); - } - break; - case 7: // HalfElf - HairColor = zone->random.Int(0, 19); - if (Gender == 0) { - HairStyle = zone->random.Int(0, 3); - LuclinFace = zone->random.Int(0, 37); - BeardColor = HairColor; - } - if (Gender == 1) { - HairStyle = zone->random.Int(0, 2); - } - break; - case 8: // Dwarf - HairColor = zone->random.Int(0, 19); + } + break; + case WOOD_ELF: + HairColor = zone->random.Int(0, 19); + if (Gender == MALE) { + HairStyle = zone->random.Int(0, 3); + } + if (Gender == FEMALE) { + HairStyle = zone->random.Int(0, 2); + } + break; + case HIGH_ELF: + HairColor = zone->random.Int(0, 14); + if (Gender == MALE) { + HairStyle = zone->random.Int(0, 3); + LuclinFace = zone->random.Int(0, 37); BeardColor = HairColor; - if (Gender == 0) { - HairStyle = zone->random.Int(0, 3); - Beard = zone->random.Int(0, 5); - } - if (Gender == 1) { - HairStyle = zone->random.Int(0, 2); - LuclinFace = zone->random.Int(0, 17); - } - break; - case 9: // Troll - EyeColor1 = zone->random.Int(0, 10); - EyeColor2 = zone->random.Int(0, 10); - if (Gender == 1) { - HairStyle = zone->random.Int(0, 3); - HairColor = zone->random.Int(0, 23); - } - break; - case 10: // Ogre - if (Gender == 1) { - HairStyle = zone->random.Int(0, 3); - HairColor = zone->random.Int(0, 23); - } - break; - case 11: // Halfling - HairColor = zone->random.Int(0, 19); - if (Gender == 0) { - BeardColor = HairColor; - HairStyle = zone->random.Int(0, 3); - Beard = zone->random.Int(0, 5); - } - if (Gender == 1) { - HairStyle = zone->random.Int(0, 2); - } - break; - case 12: // Gnome - HairColor = zone->random.Int(0, 24); - if (Gender == 0) { - BeardColor = HairColor; - HairStyle = zone->random.Int(0, 3); - Beard = zone->random.Int(0, 5); - } - if (Gender == 1) { - HairStyle = zone->random.Int(0, 2); - } - break; - case 128: // Iksar - case 130: // VahShir - break; - case 330: // Froglok - LuclinFace = zone->random.Int(0, 9); - case 522: // Drakkin - HairColor = zone->random.Int(0, 3); + } + if (Gender == FEMALE) { + HairStyle = zone->random.Int(0, 2); + } + break; + case DARK_ELF: + HairColor = zone->random.Int(13, 18); + if (Gender == MALE) { + HairStyle = zone->random.Int(0, 3); + LuclinFace = zone->random.Int(0, 37); BeardColor = HairColor; - EyeColor1 = zone->random.Int(0, 11); - EyeColor2 = zone->random.Int(0, 11); - LuclinFace = zone->random.Int(0, 6); - DrakkinHeritage = zone->random.Int(0, 6); - DrakkinTattoo = zone->random.Int(0, 7); - DrakkinDetails = zone->random.Int(0, 7); - if (Gender == 0) { - Beard = zone->random.Int(0, 12); - HairStyle = zone->random.Int(0, 8); - } - if (Gender == 1) { - Beard = zone->random.Int(0, 3); - HairStyle = zone->random.Int(0, 7); - } - break; - default: - break; + } + if (Gender == FEMALE) { + HairStyle = zone->random.Int(0, 2); + } + break; + case HALF_ELF: + HairColor = zone->random.Int(0, 19); + if (Gender == MALE) { + HairStyle = zone->random.Int(0, 3); + LuclinFace = zone->random.Int(0, 37); + BeardColor = HairColor; + } + if (Gender == FEMALE) { + HairStyle = zone->random.Int(0, 2); + } + break; + case DWARF: + HairColor = zone->random.Int(0, 19); + BeardColor = HairColor; + if (Gender == MALE) { + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); + } + if (Gender == FEMALE) { + HairStyle = zone->random.Int(0, 2); + LuclinFace = zone->random.Int(0, 17); + } + break; + case TROLL: + EyeColor1 = zone->random.Int(0, 10); + EyeColor2 = zone->random.Int(0, 10); + if (Gender == FEMALE) { + HairStyle = zone->random.Int(0, 3); + HairColor = zone->random.Int(0, 23); + } + break; + case OGRE: + if (Gender == FEMALE) { + HairStyle = zone->random.Int(0, 3); + HairColor = zone->random.Int(0, 23); + } + break; + case HALFLING: + HairColor = zone->random.Int(0, 19); + if (Gender == MALE) { + BeardColor = HairColor; + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); + } + if (Gender == FEMALE) { + HairStyle = zone->random.Int(0, 2); + } + break; + case GNOME: + HairColor = zone->random.Int(0, 24); + if (Gender == MALE) { + BeardColor = HairColor; + HairStyle = zone->random.Int(0, 3); + Beard = zone->random.Int(0, 5); + } + if (Gender == FEMALE) { + HairStyle = zone->random.Int(0, 2); + } + break; + case IKSAR: + case VAHSHIR: + break; + case FROGLOK: + LuclinFace = zone->random.Int(0, 9); + case DRAKKIN: + HairColor = zone->random.Int(0, 3); + BeardColor = HairColor; + EyeColor1 = zone->random.Int(0, 11); + EyeColor2 = zone->random.Int(0, 11); + LuclinFace = zone->random.Int(0, 6); + DrakkinHeritage = zone->random.Int(0, 6); + DrakkinTattoo = zone->random.Int(0, 7); + DrakkinDetails = zone->random.Int(0, 7); + if (Gender == MALE) { + Beard = zone->random.Int(0, 12); + HairStyle = zone->random.Int(0, 8); + } + if (Gender == FEMALE) { + Beard = zone->random.Int(0, 3); + HairStyle = zone->random.Int(0, 7); + } + break; + default: + break; } - if (set_variables) - { + if (set_variables) { haircolor = HairColor; beardcolor = BeardColor; eyecolor1 = EyeColor1; @@ -1954,8 +1955,7 @@ bool Mob::RandomizeFeatures(bool send_illusion, bool set_variables) drakkin_details = DrakkinDetails; } - if (send_illusion) - { + if (send_illusion) { SendIllusionPacket(GetRace(), Gender, Texture, HelmTexture, HairColor, BeardColor, EyeColor1, EyeColor2, HairStyle, LuclinFace, Beard, 0xFF, DrakkinHeritage, DrakkinTattoo, DrakkinDetails); @@ -5861,3 +5861,69 @@ int Mob::CheckBaneDamage(const ItemInst *item) return damage; } + +#ifdef BOTS +bool Mob::JoinHealRotationTargetPool(std::shared_ptr* heal_rotation) +{ + if (IsHealRotationTarget()) + return false; + if (!heal_rotation->use_count()) + return false; + if (!(*heal_rotation)) + return false; + if (!HealRotation::IsTargetMobType(this)) + return false; + + if (!(*heal_rotation)->AddTargetToPool(this)) + return false; + + m_target_of_heal_rotation = *heal_rotation; + + return IsHealRotationTarget(); +} + +bool Mob::LeaveHealRotationTargetPool() +{ + if (!IsHealRotationTarget()) { + m_target_of_heal_rotation.reset(); + return true; + } + + m_target_of_heal_rotation->RemoveTargetFromPool(this); + m_target_of_heal_rotation.reset(); + + return !IsHealRotationTarget(); +} + +uint32 Mob::HealRotationHealCount() +{ + if (!IsHealRotationTarget()) + return 0; + + return m_target_of_heal_rotation->HealCount(this); +} + +uint32 Mob::HealRotationExtendedHealCount() +{ + if (!IsHealRotationTarget()) + return 0; + + return m_target_of_heal_rotation->ExtendedHealCount(this); +} + +float Mob::HealRotationHealFrequency() +{ + if (!IsHealRotationTarget()) + return 0.0f; + + return m_target_of_heal_rotation->HealFrequency(this); +} + +float Mob::HealRotationExtendedHealFrequency() +{ + if (!IsHealRotationTarget()) + return 0.0f; + + return m_target_of_heal_rotation->ExtendedHealFrequency(this); +} +#endif diff --git a/zone/mob.h b/zone/mob.h index c4a75b5aa..dd8a36c89 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,10 @@ #include #include +#ifdef BOTS +#include "heal_rotation.h" +#endif + char* strn0cpy(char* dest, const char* source, uint32 size); #define MAX_SPECIAL_ATTACK_PARAMS 8 @@ -1005,6 +1009,20 @@ public: void DelAssistCap() { --npc_assist_cap; } void ResetAssistCap() { npc_assist_cap = 0; } + // Bots HealRotation methods +#ifdef BOTS + bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); } + bool JoinHealRotationTargetPool(std::shared_ptr* heal_rotation); + bool LeaveHealRotationTargetPool(); + + uint32 HealRotationHealCount(); + uint32 HealRotationExtendedHealCount(); + float HealRotationHealFrequency(); + float HealRotationExtendedHealFrequency(); + + const std::shared_ptr* TargetOfHealRotation() const { return &m_target_of_heal_rotation; } +#endif + protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special = 0); static uint16 GetProcID(uint16 spell_id, uint8 effect_index); @@ -1373,6 +1391,11 @@ protected: private: void _StopSong(); //this is not what you think it is Mob* target; + +#ifdef BOTS + std::shared_ptr m_target_of_heal_rotation; +#endif + }; #endif diff --git a/zone/net.cpp b/zone/net.cpp index 0d5d546d6..194e017fe 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -52,6 +52,10 @@ #include "zone.h" #include "queryserv.h" #include "command.h" +#ifdef BOTS +#include "bot_command.h" +#include "bot_database.h" +#endif #include "zone_config.h" #include "titles.h" #include "guild_mgr.h" @@ -203,6 +207,18 @@ int main(int argc, char** argv) { return 1; } +#ifdef BOTS + if (!botdb.Connect( + Config->DatabaseHost.c_str(), + Config->DatabaseUsername.c_str(), + Config->DatabasePassword.c_str(), + Config->DatabaseDB.c_str(), + Config->DatabasePort)) { + Log.Out(Logs::General, Logs::Error, "Cannot continue without a bots database connection."); + return 1; + } +#endif + /* Register Log System and Settings */ Log.OnLogHookCallBackZone(&Zone::GMSayHookCallBackProcess); database.LoadLogSettings(Log.log_settings); @@ -325,6 +341,15 @@ int main(int argc, char** argv) { } } +#ifdef BOTS + Log.Out(Logs::General, Logs::Zone_Server, "Loading bot commands"); + int botretval = bot_command_init(); + if (botretval<0) + Log.Out(Logs::General, Logs::Error, "Bot command loading FAILED"); + else + Log.Out(Logs::General, Logs::Zone_Server, "%d bot commands loaded", botretval); +#endif + if(RuleB(TaskSystem, EnableTaskSystem)) { Log.Out(Logs::General, Logs::Tasks, "[INIT] Loading Tasks"); taskmanager = new TaskManager; @@ -524,6 +549,9 @@ int main(int argc, char** argv) { worldserver.Disconnect(); safe_delete(taskmanager); command_deinit(); +#ifdef BOTS + bot_command_deinit(); +#endif safe_delete(parse); Log.Out(Logs::General, Logs::Zone_Server, "Proper zone shutdown complete."); Log.CloseFileLogs(); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 5f32992bc..9914fd15d 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1994,7 +1994,7 @@ bool WorldServer::SendVoiceMacro(Client* From, uint32 Type, char* Target, uint32 svm->Type = Type; - svm->Voice = (GetArrayRace(From->GetRace()) * 2) + From->GetGender(); + svm->Voice = (GetPlayerRaceValue(From->GetRace()) * 2) + From->GetGender(); svm->MacroNumber = MacroNumber; From 90c87a05e622cece6aad198707f005f35561ce19 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 24 Mar 2016 19:23:12 -0400 Subject: [PATCH 004/693] Fix for implementation reference failure --- zone/heal_rotation.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zone/heal_rotation.h b/zone/heal_rotation.h index cfe0b0d5d..54b089ed3 100644 --- a/zone/heal_rotation.h +++ b/zone/heal_rotation.h @@ -47,6 +47,7 @@ class HealRotation { public: HealRotation(Bot* hr_creator, uint32 interval_ms = CASTING_CYCLE_DEFAULT_INTERVAL, bool fast_heals = false, bool adaptive_targeting = false, bool casting_override = false); + HealRotation(HealRotation* allocator_shunt) {}; void SetIntervalMS(uint32 interval_ms); void SetIntervalS(uint32 interval_s); @@ -140,9 +141,6 @@ private: float m_safe_hp_ratio[ARMOR_TYPE_COUNT]; float m_critical_hp_ratio[ARMOR_TYPE_COUNT]; - - friend class std::_Ref_count_obj; - HealRotation(HealRotation* allocator_shunt) {}; }; #endif From 698ef56df96174e824c788c2de71497ea3f55a97 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 24 Mar 2016 19:35:23 -0400 Subject: [PATCH 005/693] Few more portability fixes --- zone/bot.cpp | 4 ++-- zone/bot_command.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 447f38834..93803d978 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1518,11 +1518,11 @@ bool Bot::IsValidName(std::string& name) { if (name.length() < 4) return false; - if (!IsCharUpper(name[0])) + if (!isupper(name[0])) return false; for (int i = 1; i < name.length(); ++i) { - if (!IsCharLower(name[i]) && name[i] != '_') { + if (!islower(name[i]) && name[i] != '_') { return false; } } diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 0c09c6f31..75ca8a6ff 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -990,19 +990,19 @@ private: if (l_size_type < r_size_type) return true; if (l_size_type == BCEnum::SzT_Enlarge && r_size_type == BCEnum::SzT_Enlarge) { - if (EQ_STBASE(l, r, target_type) && GT_SPELLS(l, r, base, 1)) + if (EQ_STBASE(l, r, target_type) && GT_SPELLS_EFFECT_ID(l, r, base, 1)) return true; - if (EQ_STBASE(l, r, target_type) && EQ_SPELLS(l, r, base, 1) && GT_STBASE(l, r, spell_level)) + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, base, 1) && GT_STBASE(l, r, spell_level)) return true; - if (EQ_STBASE(l, r, target_type) && EQ_SPELLS(l, r, base, 1) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, base, 1) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) return true; } if (l_size_type == BCEnum::SzT_Reduce && r_size_type == BCEnum::SzT_Reduce) { - if (EQ_STBASE(l, r, target_type) && LT_SPELLS(l, r, base, 1)) + if (EQ_STBASE(l, r, target_type) && LT_SPELLS_EFFECT_ID(l, r, base, 1)) return true; - if (EQ_STBASE(l, r, target_type) && EQ_SPELLS(l, r, base, 1) && GT_STBASE(l, r, spell_level)) + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, base, 1) && GT_STBASE(l, r, spell_level)) return true; - if (EQ_STBASE(l, r, target_type) && EQ_SPELLS(l, r, base, 1) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + if (EQ_STBASE(l, r, target_type) && EQ_SPELLS_EFFECT_ID(l, r, base, 1) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) return true; } From 66ca522e620115d2a10045e9a0ca85e9bc39a7dc Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 24 Mar 2016 20:33:37 -0400 Subject: [PATCH 006/693] Another fix for portability issues --- zone/bot.cpp | 4 ++-- zone/heal_rotation.cpp | 20 ++++++++++---------- zone/heal_rotation.h | 6 +++--- zone/mob.cpp | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 93803d978..8cd82f9f6 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -9239,7 +9239,7 @@ bool Bot::CreateHealRotation(uint32 interval_ms, bool fast_heals, bool adaptive_ { if (IsHealRotationMember()) return false; - if (!HealRotation::IsMemberClass(GetClass())) + if (!IsHealRotationMemberClass(GetClass())) return false; m_member_of_heal_rotation = std::make_shared(this, interval_ms, fast_heals, adaptive_targeting, casting_override); @@ -9266,7 +9266,7 @@ bool Bot::JoinHealRotationMemberPool(std::shared_ptr* heal_rotatio return false; if (!(*heal_rotation)) return false; - if (!HealRotation::IsMemberClass(GetClass())) + if (!IsHealRotationMemberClass(GetClass())) return false; if (!(*heal_rotation)->AddMemberToPool(this)) diff --git a/zone/heal_rotation.cpp b/zone/heal_rotation.cpp index 465f66f00..e99b6560d 100644 --- a/zone/heal_rotation.cpp +++ b/zone/heal_rotation.cpp @@ -74,7 +74,7 @@ bool HealRotation::AddMemberToPool(Bot* hr_member) { if (!hr_member) return false; - if (!IsMemberClass(hr_member->GetClass())) + if (!IsHealRotationMemberClass(hr_member->GetClass())) return false; if (m_member_pool.size() >= RuleI(Bots, HealRotationMaxMembers)) return false; @@ -96,7 +96,7 @@ bool HealRotation::AddTargetToPool(Mob* hr_target) return false; if (!valid_state()) return false; - if (!IsTargetMobType(hr_target)) + if (!IsHealRotationTargetMobType(hr_target)) return false; if (m_target_pool.size() >= RuleI(Bots, HealRotationMaxTargets)) return false; @@ -498,7 +498,7 @@ void HealRotation::ResetArmorTypeHPLimits() bool HealRotation::valid_state() { m_member_pool.remove(nullptr); - m_member_pool.remove_if([](Mob* l) {return (!IsMemberClass(l->GetClass())); }); + m_member_pool.remove_if([](Mob* l) {return (!IsHealRotationMemberClass(l->GetClass())); }); cycle_refresh(); @@ -565,7 +565,7 @@ void HealRotation::bias_targets() #define EQ_ALIVE(l, r) (l->GetAppearance() != eaDead && r->GetAppearance() != eaDead) #define EQ_READY(l, r, ct) (l->DontHealMeBefore() <= ct && r->DontHealMeBefore() <= ct) #define EQ_TANK(l, r) ((l->HasGroup() && l->GetGroup()->AmIMainTank(l->GetCleanName())) && (r->HasGroup() && r->GetGroup()->AmIMainTank(r->GetCleanName()))) -#define EQ_HEALER(l, r) (IsMemberClass(l->GetClass()) && IsMemberClass(r->GetClass())) +#define EQ_HEALER(l, r) (IsHealRotationMemberClass(l->GetClass()) && IsHealRotationMemberClass(r->GetClass())) #define EQ_ARMTYPE(l, r) (ClassArmorType(l->GetClass()) == ClassArmorType(r->GetClass())) #define EQ_ATCRIT(l, r) (l->GetHPRatio() <= (*l->TargetOfHealRotation())->ArmorTypeCriticalHPRatio(ClassArmorType(l->GetClass())) && \ r->GetHPRatio() <= (*r->TargetOfHealRotation())->ArmorTypeCriticalHPRatio(ClassArmorType(r->GetClass()))) @@ -575,7 +575,7 @@ void HealRotation::bias_targets() #define GT_ALIVE(l, r) (l->GetAppearance() != eaDead && r->GetAppearance() == eaDead) #define GT_READY(l, r, ct) (l->DontHealMeBefore() <= ct && r->DontHealMeBefore() > ct) #define GT_TANK(l, r) ((l->HasGroup() && l->GetGroup()->AmIMainTank(l->GetCleanName())) && (!r->HasGroup() || !r->GetGroup()->AmIMainTank(r->GetCleanName()))) -#define GT_HEALER(l, r) (IsMemberClass(l->GetClass()) && !IsMemberClass(r->GetClass())) +#define GT_HEALER(l, r) (IsHealRotationMemberClass(l->GetClass()) && !IsHealRotationMemberClass(r->GetClass())) #define GT_HEALFREQ(l, r) (l->HealRotationHealFrequency() > r->HealRotationHealFrequency()) #define GT_HEALCNT(l, r) (l->HealRotationHealCount() > r->HealRotationHealCount()) #define GT_ATCRIT(l, r) (l->GetHPRatio() <= (*l->TargetOfHealRotation())->ArmorTypeCriticalHPRatio(ClassArmorType(l->GetClass())) && \ @@ -593,7 +593,7 @@ void HealRotation::bias_targets() // attempt to clear invalid target pool entries m_target_pool.remove(nullptr); - m_target_pool.remove_if([](Mob* l) { return (!IsTargetMobType(l)); }); + m_target_pool.remove_if([](Mob* l) { return (!IsHealRotationTargetMobType(l)); }); uint32 sort_type = 0; // debug @@ -629,7 +629,7 @@ void HealRotation::bias_targets() return false; }); - if (IsMemberClass(m_target_pool.front()->GetClass()) && healable_target(false)) + if (IsHealRotationMemberClass(m_target_pool.front()->GetClass()) && healable_target(false)) break; sort_type = 3; // default @@ -710,7 +710,7 @@ void HealRotation::bias_targets() return false; }); - if (IsMemberClass(m_target_pool.front()->GetClass()) && healable_target(true, true)) + if (IsHealRotationMemberClass(m_target_pool.front()->GetClass()) && healable_target(true, true)) break; sort_type = 105; @@ -857,7 +857,7 @@ void HealRotation::bias_targets() #endif } -bool HealRotation::IsMemberClass(uint8 class_id) +bool IsHealRotationMemberClass(uint8 class_id) { switch (class_id) { case CLERIC: @@ -869,7 +869,7 @@ bool HealRotation::IsMemberClass(uint8 class_id) } } -bool HealRotation::IsTargetMobType(Mob* target_mob) +bool IsHealRotationTargetMobType(Mob* target_mob) { if (!target_mob) return false; diff --git a/zone/heal_rotation.h b/zone/heal_rotation.h index 54b089ed3..460179719 100644 --- a/zone/heal_rotation.h +++ b/zone/heal_rotation.h @@ -107,9 +107,6 @@ public: void ResetArmorTypeHPLimits(); - static bool IsMemberClass(uint8 class_id); - static bool IsTargetMobType(Mob* target_mob); - private: bool valid_state(); void cycle_refresh(); @@ -143,4 +140,7 @@ private: float m_critical_hp_ratio[ARMOR_TYPE_COUNT]; }; +bool IsHealRotationMemberClass(uint8 class_id); +bool IsHealRotationTargetMobType(Mob* target_mob); + #endif diff --git a/zone/mob.cpp b/zone/mob.cpp index 21458a2d7..746f68b5f 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5871,7 +5871,7 @@ bool Mob::JoinHealRotationTargetPool(std::shared_ptr* heal_rotatio return false; if (!(*heal_rotation)) return false; - if (!HealRotation::IsTargetMobType(this)) + if (!IsHealRotationTargetMobType(this)) return false; if (!(*heal_rotation)->AddTargetToPool(this)) From 3b6889d5d36c2f05619a7d8193eb6d6c2b7798ce Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 25 Mar 2016 00:39:11 -0400 Subject: [PATCH 007/693] Changed PreferNoManaCommandSpells check from pre-processor to rules-based criteria --- zone/bot_command.cpp | 47 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 75ca8a6ff..bd155421e 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -831,31 +831,32 @@ private: }); continue; case BCEnum::SpT_Identify: -#ifdef PREFER_NO_MANA_COST_SPELLS - spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { - if (LT_SPELLS(l, r, mana)) - return true; - if (EQ_SPELLS(l, r, mana) && LT_STBASE(l, r, target_type)) - return true; - if (EQ_SPELLS(l, r, mana) && EQ_STBASE(l, r, target_type) && LT_STBASE(l, r, spell_level)) - return true; - if (EQ_SPELLS(l, r, mana) && EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) - return true; + if (RuleB(Bots, PreferNoManaCommandSpells)) { + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_SPELLS(l, r, mana)) + return true; + if (EQ_SPELLS(l, r, mana) && LT_STBASE(l, r, target_type)) + return true; + if (EQ_SPELLS(l, r, mana) && EQ_STBASE(l, r, target_type) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_SPELLS(l, r, mana) && EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; - return false; - }); -#else - spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { - if (LT_STBASE(l, r, target_type)) - return true; - if (EQ_STBASE(l, r, target_type) && LT_STBASE(l, r, spell_level)) - return true; - if (EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) - return true; + return false; + }); + } + else { + spell_list->sort([](const STBaseEntry* l, const STBaseEntry* r) { + if (LT_STBASE(l, r, target_type)) + return true; + if (EQ_STBASE(l, r, target_type) && LT_STBASE(l, r, spell_level)) + return true; + if (EQ_STBASE(l, r, target_type) && EQ_STBASE(l, r, spell_level) && LT_STBASE(l, r, caster_class)) + return true; - return false; - }); -#endif + return false; + }); + } continue; case BCEnum::SpT_Invisibility: spell_list->sort([](STBaseEntry* l, STBaseEntry* r) { From 817d8ceb64e44e86b82d4998e2e6b4c08330745e Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 25 Mar 2016 02:04:25 -0400 Subject: [PATCH 008/693] Fix for heal rotation 'Stack Overflow' error --- changelog.txt | 3 +++ zone/heal_rotation.cpp | 8 ++++++-- zone/heal_rotation.h | 2 ++ zone/mob.cpp | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index 174196c4f..09ba48d3b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/25/2016 == +Uleat: Fix for heal rotation 'Stack Overflow' error + == 03/24/2016 == Kayen: Fix for AE taunt to use correct range and hate modifier. Fix for spell effect version of taunt to use correct range. diff --git a/zone/heal_rotation.cpp b/zone/heal_rotation.cpp index e99b6560d..a88cdd1ed 100644 --- a/zone/heal_rotation.cpp +++ b/zone/heal_rotation.cpp @@ -47,6 +47,8 @@ HealRotation::HealRotation(Bot* hr_creator, uint32 interval_ms, bool fast_heals, ResetArmorTypeHPLimits(); m_is_active = false; + + m_consumed = false; } void HealRotation::SetIntervalMS(uint32 interval_ms) @@ -502,8 +504,10 @@ bool HealRotation::valid_state() cycle_refresh(); - if (m_member_pool.empty()) - ClearTargetPool(); // Consumes HealRotation at this point + if (m_member_pool.empty() && !m_consumed) { // Consumes HealRotation at this point + m_consumed = true; + ClearTargetPool(); + } return (!m_member_pool.empty()); } diff --git a/zone/heal_rotation.h b/zone/heal_rotation.h index 460179719..3c3006c87 100644 --- a/zone/heal_rotation.h +++ b/zone/heal_rotation.h @@ -127,6 +127,8 @@ private: bool m_is_active; + bool m_consumed; + std::list m_member_pool; std::list m_cycle_pool; std::list m_target_pool; diff --git a/zone/mob.cpp b/zone/mob.cpp index 746f68b5f..0429cc973 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5891,7 +5891,7 @@ bool Mob::LeaveHealRotationTargetPool() m_target_of_heal_rotation->RemoveTargetFromPool(this); m_target_of_heal_rotation.reset(); - + return !IsHealRotationTarget(); } From a99befebfeb4e6d8a374de795e010fda7b182075 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 25 Mar 2016 12:29:31 -0400 Subject: [PATCH 009/693] Added code blocks for non-BOTS build failures --- zone/bot_command.cpp | 4 ++++ zone/bot_command.h | 4 ++++ zone/bot_database.cpp | 5 ++++- zone/bot_database.h | 4 ++++ zone/heal_rotation.cpp | 4 ++++ zone/heal_rotation.h | 4 ++++ 6 files changed, 24 insertions(+), 1 deletion(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index bd155421e..89462cbc4 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -32,6 +32,8 @@ */ +#ifdef BOTS + #include #include #include @@ -7311,3 +7313,5 @@ bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::Sp return false; } + +#endif // BOTS diff --git a/zone/bot_command.h b/zone/bot_command.h index 5d4be85fd..bc8558ff1 100644 --- a/zone/bot_command.h +++ b/zone/bot_command.h @@ -20,6 +20,8 @@ #ifndef BOT_COMMAND_H #define BOT_COMMAND_H +#ifdef BOTS + class Client; class Seperator; @@ -665,3 +667,5 @@ void helper_send_usage_required_bots(Client *bot_owner, BCEnum::SpType spell_typ bool helper_spell_check_fail(STBaseEntry* local_entry); bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::SpType spell_type); #endif + +#endif // BOTS diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index c15d583ae..3e7e18c1e 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -16,6 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifdef BOTS #include "../common/global_define.h" #include "../common/rulesys.h" @@ -719,7 +720,7 @@ std::list> BotDatabase::GetGroupsListByOwner return groups_list; std::string query = StringFormat("SELECT `group_name`, `group_leader_name` FROM `vw_bot_groups` WHERE `owner_id` = '%u'", owner_id); - auto results = database.QueryDatabase(query); + auto results = QueryDatabase(query); if (!results.Success()) { error_message = results.ErrorMessage(); return groups_list; @@ -730,3 +731,5 @@ std::list> BotDatabase::GetGroupsListByOwner return groups_list; } + +#endif // BOTS diff --git a/zone/bot_database.h b/zone/bot_database.h index e98388716..5e9d02880 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -20,6 +20,8 @@ #ifndef BOT_DATABASE_H #define BOT_DATABASE_H +#ifdef BOTS + #include "../common/dbcore.h" #include "../common/eq_packet_structs.h" @@ -85,3 +87,5 @@ public: extern BotDatabase botdb; #endif + +#endif // BOTS diff --git a/zone/heal_rotation.cpp b/zone/heal_rotation.cpp index a88cdd1ed..4e22e5188 100644 --- a/zone/heal_rotation.cpp +++ b/zone/heal_rotation.cpp @@ -16,6 +16,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifdef BOTS + #include "bot.h" #define SAFE_HP_RATIO_CLOTH 95.0f @@ -884,3 +886,5 @@ bool IsHealRotationTargetMobType(Mob* target_mob) return true; } + +#endif // BOTS diff --git a/zone/heal_rotation.h b/zone/heal_rotation.h index 3c3006c87..4b7426623 100644 --- a/zone/heal_rotation.h +++ b/zone/heal_rotation.h @@ -20,6 +20,8 @@ #ifndef HEAL_ROTATION_H #define HEAL_ROTATION_H +#ifdef BOTS + #include "mob.h" #define CASTING_CYCLE_MINIMUM_INTERVAL 1000 @@ -146,3 +148,5 @@ bool IsHealRotationMemberClass(uint8 class_id); bool IsHealRotationTargetMobType(Mob* target_mob); #endif + +#endif // BOTS From b369bb17933580658c3723e6c31337a5b010f002 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 25 Mar 2016 13:02:59 -0400 Subject: [PATCH 010/693] Fixed defensive procs so they now only trigger once per attack round like live. Added live like proc chance modifer based on level difference to target. "Anything above your level will receive full mod. Starting 6 levels below PC level there is a negative 10 % mod applied each level until it reaches 0 and will not proc on anything 15 levels below you or lower." Thanks to Huffin from PEQ for the parse data --- changelog.txt | 2 ++ zone/attack.cpp | 46 +++++++++++++++++++++++++++------------------- zone/bot.cpp | 3 ++- zone/mob.cpp | 5 +++-- zone/mob.h | 4 ++-- zone/mob_ai.cpp | 1 + 6 files changed, 37 insertions(+), 24 deletions(-) diff --git a/changelog.txt b/changelog.txt index 09ba48d3b..6ee721e64 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 03/25/2016 == Uleat: Fix for heal rotation 'Stack Overflow' error +Kayen: Defensive procs will now only proc once per attack round (instead of every attack chance). + Live like modifier added that decreases defensive proc chance if you are higher level then your attacker. == 03/24/2016 == Kayen: Fix for AE taunt to use correct range and hate modifier. diff --git a/zone/attack.cpp b/zone/attack.cpp index 858e6aee9..786eb128a 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1255,7 +1255,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b CommonBreakInvisibleFromCombat(); if(GetTarget()) - TriggerDefensiveProcs(weapon, other, Hand, damage); + TriggerDefensiveProcs(other, Hand, true, damage); if (damage > 0) return true; @@ -1822,7 +1822,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool } if(GetHP() > 0 && !other->HasDied()) - TriggerDefensiveProcs(nullptr, other, Hand, damage); + TriggerDefensiveProcs(other, Hand, true, damage); if (damage > 0) return true; @@ -3516,7 +3516,7 @@ float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 h } // argument 'weapon' not used -void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) { +void Mob::TryDefensiveProc(Mob *on, uint16 hand) { if (!on) { SetTarget(nullptr); @@ -3524,29 +3524,37 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) { return; } - bool bDefensiveProc = HasDefensiveProcs(); - - if (!bDefensiveProc) + if (!HasDefensiveProcs()) return; - float ProcChance, ProcBonus; - on->GetDefensiveProcChances(ProcBonus, ProcChance, hand , this); + if (!on->HasDied() && on->GetHP() > 0){ - if(hand != MainPrimary) - ProcChance /= 2; + float ProcChance, ProcBonus; + on->GetDefensiveProcChances(ProcBonus, ProcChance, hand , this); - if (bDefensiveProc){ - for (int i = 0; i < MAX_PROCS; i++) { - if (IsValidSpell(DefensiveProcs[i].spellID)) { - float chance = ProcChance * (static_cast(DefensiveProcs[i].chance)/100.0f); - if (zone->random.Roll(chance)) { - ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on); - CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0, - DefensiveProcs[i].base_spellID); - } + if(hand != MainPrimary) + ProcChance /= 2; + + int level_penalty = 0; + int level_diff = GetLevel() - on->GetLevel(); + if (level_diff > 6)//10% penalty per level if > 6 levels over target. + level_penalty = (level_diff - 6) * 10; + + ProcChance -= ProcChance*level_penalty/100; + + if (ProcChance < 0) + return; + + for (int i = 0; i < MAX_PROCS; i++) { + if (IsValidSpell(DefensiveProcs[i].spellID)) { + float chance = ProcChance * (static_cast(DefensiveProcs[i].chance)/100.0f); + if (zone->random.Roll(chance)) { + ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on); + CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0,DefensiveProcs[i].base_spellID); } } } + } } void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { diff --git a/zone/bot.cpp b/zone/bot.cpp index 8cd82f9f6..6cb27f8e7 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2911,6 +2911,7 @@ void Bot::AI_Process() { DoClassAttacks(GetTarget()); if(attack_timer.Check()) { Attack(GetTarget(), MainPrimary); + TriggerDefensiveProcs(GetTarget(), MainPrimary, false); ItemInst *wpn = GetBotItem(MainPrimary); TryWeaponProc(wpn, GetTarget(), MainPrimary); bool tripleSuccess = false; @@ -4865,7 +4866,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b BuffFadeByEffect(SE_NegateIfCombat); if(GetTarget()) - TriggerDefensiveProcs(weapon, other, Hand, damage); + TriggerDefensiveProcs(other, Hand, true, damage); if (damage > 0) return true; diff --git a/zone/mob.cpp b/zone/mob.cpp index 0429cc973..c91ae404f 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3399,12 +3399,13 @@ int Mob::GetSnaredAmount() return worst_snare; } -void Mob::TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand, int damage) +void Mob::TriggerDefensiveProcs(Mob *on, uint16 hand, bool FromSkillProc, int damage) { if (!on) return; - on->TryDefensiveProc(weapon, this, hand); + if (!FromSkillProc) + on->TryDefensiveProc(this, hand); //Defensive Skill Procs if (damage < 0 && damage >= -4) { diff --git a/zone/mob.h b/zone/mob.h index dd8a36c89..0407ecd3a 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -152,7 +152,6 @@ public: bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) = 0; int MonkSpecialAttack(Mob* other, uint8 skill_used); virtual void TryBackstab(Mob *other,int ReuseTime = 10); - void TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary, int damage = 0); bool AvoidDamage(Mob* attacker, int32 &damage, int hand); virtual bool CheckHitChance(Mob* attacker, SkillUseTypes skillinuse, int Hand, int16 chance_mod = 0); virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts = nullptr); @@ -564,6 +563,7 @@ public: bool lookForAftArc = true); //Procs + void TriggerDefensiveProcs(Mob *on, uint16 hand = MainPrimary, bool SkillProc=false, int damage = 0); bool AddRangedProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); bool RemoveRangedProc(uint16 spell_id, bool bAll = false); bool HasRangedProcs() const; @@ -1142,7 +1142,7 @@ protected: void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand = MainCharm? bool PassLimitToSkill(uint16 spell_id, uint16 skill); bool PassLimitClass(uint32 Classes_, uint16 Class_); - void TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary); + void TryDefensiveProc(Mob *on, uint16 hand = MainPrimary); void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = MainPrimary); void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = MainPrimary); void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 79c4493ea..918c8afde 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1107,6 +1107,7 @@ void Mob::AI_Process() { //try main hand first if(attack_timer.Check()) { DoMainHandAttackRounds(target); + TriggerDefensiveProcs(target, MainPrimary, false); bool specialed = false; // NPCs can only do one of these a round if (GetSpecialAbility(SPECATK_FLURRY)) { From cdf5293ee2f8b373746a49675686879aa9fd20c3 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 25 Mar 2016 13:19:36 -0400 Subject: [PATCH 011/693] Backport subcommand_list methodology to VS2012 compatibility - VS2013 code left in situ --- zone/bot_command.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 89462cbc4..de07e6a1f 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -2570,10 +2570,34 @@ void bot_command_bind_affinity(Client *c, const Seperator *sep) void bot_command_bot(Client *c, const Seperator *sep) { + /* VS2012 code - begin */ + std::list subcommand_list; + subcommand_list.push_back("botappearance"); + subcommand_list.push_back("botcamp"); + subcommand_list.push_back("botclone"); + subcommand_list.push_back("botcreate"); + subcommand_list.push_back("botdelete"); + subcommand_list.push_back("botdetails"); + subcommand_list.push_back("botdyearmor"); + subcommand_list.push_back("botinspectmessage"); + subcommand_list.push_back("botfollowdistance"); + subcommand_list.push_back("botlist"); + subcommand_list.push_back("botoutofcombat"); + subcommand_list.push_back("botreport"); + subcommand_list.push_back("botspawn"); + subcommand_list.push_back("botstance"); + subcommand_list.push_back("botsummon"); + subcommand_list.push_back("bottogglearcher"); + subcommand_list.push_back("bottogglehelm"); + subcommand_list.push_back("botupdate"); + /* VS2012 code - end */ + + /* VS2013 code const std::list subcommand_list = { "botappearance", "botcamp", "botclone", "botcreate", "botdelete", "botdetails", "botdyearmor", "botinspectmessage", "botfollowdistance", "botlist", "botoutofcombat", "botreport", "botspawn", "botstance", "botsummon", "bottogglearcher", "bottogglehelm", "botupdate" }; + */ if (helper_command_alias_fail(c, "bot_command_bot", sep->arg[0], "bot")) return; @@ -2583,9 +2607,21 @@ void bot_command_bot(Client *c, const Seperator *sep) void bot_command_botgroup(Client *c, const Seperator *sep) { + /* VS2012 code - begin */ + std::list subcommand_list; + subcommand_list.push_back("botgroupaddmember"); + subcommand_list.push_back("botgroupcreate"); + subcommand_list.push_back("botgroupdelete"); + subcommand_list.push_back("botgrouplist"); + subcommand_list.push_back("botgroupload"); + subcommand_list.push_back("botgroupremovemember"); + /* VS2012 code - end */ + + /* VS2013 code const std::list subcommand_list = { "botgroupaddmember", "botgroupcreate", "botgroupdelete", "botgrouplist", "botgroupload", "botgroupremovemember" }; + */ if (helper_command_alias_fail(c, "bot_command_botgroup", sep->arg[0], "botgroup")) return; @@ -3010,11 +3046,33 @@ void bot_command_guard(Client *c, const Seperator *sep) void bot_command_heal_rotation(Client *c, const Seperator *sep) { + /* VS2012 code - begin */ + std::list subcommand_list; + subcommand_list.push_back("healrotationadaptivetargeting"); + subcommand_list.push_back("healrotationaddmember"); + subcommand_list.push_back("healrotationaddtarget"); + subcommand_list.push_back("healrotationadjustcritical"); + subcommand_list.push_back("healrotationadjustsafe"); + subcommand_list.push_back("healrotationcastoverride"); + subcommand_list.push_back("healrotationchangeinterval"); + subcommand_list.push_back("healrotationcleartargets"); + subcommand_list.push_back("healrotationcreate"); + subcommand_list.push_back("healrotationfastheals"); + subcommand_list.push_back("healrotationlist"); + subcommand_list.push_back("healrotationremovemember"); + subcommand_list.push_back("healrotationremovetarget"); + subcommand_list.push_back("healrotationresetlimits"); + subcommand_list.push_back("healrotationstart"); + subcommand_list.push_back("healrotationstop"); + /* VS2012 code - end */ + + /* VS2013 code const std::list subcommand_list = { "healrotationadaptivetargeting", "healrotationaddmember", "healrotationaddtarget", "healrotationadjustcritical", "healrotationadjustsafe", "healrotationcastoverride", "healrotationchangeinterval", "healrotationcleartargets", "healrotationcreate", "healrotationfastheals", "healrotationlist", "healrotationremovemember", "healrotationremovetarget", "healrotationresetlimits", "healrotationstart", "healrotationstop" }; + */ if (helper_command_alias_fail(c, "bot_command_heal_rotation", sep->arg[0], "healrotation")) return; @@ -3118,8 +3176,17 @@ void bot_command_identify(Client *c, const Seperator *sep) void bot_command_inventory(Client *c, const Seperator *sep) { + /* VS2012 code - begin */ + std::list subcommand_list; + subcommand_list.push_back("inventorygive"); + subcommand_list.push_back("inventorylist"); + subcommand_list.push_back("inventoryremove"); + /* VS2012 code - end */ + + /* VS2013 code const std::list subcommand_list = { "inventorygive", "inventorylist", "inventoryremove" }; - + */ + if (helper_command_alias_fail(c, "bot_command_inventory", sep->arg[0], "inventory")) return; @@ -3349,8 +3416,16 @@ void bot_command_movement_speed(Client *c, const Seperator *sep) void bot_command_pet(Client *c, const Seperator *sep) { - const std::list subcommand_list = { "petremove", "petsettype" }; + /* VS2012 code - begin */ + std::list subcommand_list; + subcommand_list.push_back("petremove"); + subcommand_list.push_back("petsettype"); + /* VS2012 code - end */ + /* VS2013 code + const std::list subcommand_list = { "petremove", "petsettype" }; + */ + if (helper_command_alias_fail(c, "bot_command_pet", sep->arg[0], "pet")) return; @@ -3950,10 +4025,26 @@ void bot_command_water_breathing(Client *c, const Seperator *sep) */ void bot_subcommand_bot_appearance(Client *c, const Seperator *sep) { + /* VS2012 code - begin */ + std::list subcommand_list; + subcommand_list.push_back("botbeardcolor"); + subcommand_list.push_back("botbeardstyle"); + subcommand_list.push_back("botdetails"); + subcommand_list.push_back("boteyes"); + subcommand_list.push_back("botface"); + subcommand_list.push_back("bothaircolor"); + subcommand_list.push_back("bothairstyle"); + subcommand_list.push_back("botheritage"); + subcommand_list.push_back("bottattoo"); + subcommand_list.push_back("botwoad"); + /* VS2012 code - end */ + + /* VS2013 code const std::list subcommand_list = { "botbeardcolor", "botbeardstyle", "botdetails", "boteyes", "botface", "bothaircolor", "bothairstyle", "botheritage", "bottattoo", "botwoad" }; + */ if (helper_command_alias_fail(c, "bot_subcommand_bot_appearance", sep->arg[0], "botappearance")) return; From d36ec8c06634956cb08b3923152ed7387f6aed71 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 25 Mar 2016 14:19:49 -0400 Subject: [PATCH 012/693] Fix for certain Berserker characters not being able to train Piercing skill --- zone/client.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 6836b2a02..837306d99 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2377,7 +2377,11 @@ uint16 Client::MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) cons return(database.GetSkillCap(class_, skillid, level)); } -uint8 Client::SkillTrainLevel(SkillUseTypes skillid, uint16 class_){ +uint8 Client::SkillTrainLevel(SkillUseTypes skillid, uint16 class_) +{ + if (GetClientVersion() < ClientVersion::RoF2 && class_ == BERSERKER && skillid == Skill1HPiercing) + skillid = Skill2HPiercing; + return(database.GetTrainLevel(class_, skillid, RuleI(Character, MaxLevel))); } From 1cfd1d478a30285251051ae42d0e351c76fa0485 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 25 Mar 2016 18:25:54 -0400 Subject: [PATCH 013/693] Fix to have better sync server side spell range check to client check. --- zone/mob.h | 2 +- zone/spells.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/mob.h b/zone/mob.h index 0407ecd3a..7083e45ca 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -563,7 +563,7 @@ public: bool lookForAftArc = true); //Procs - void TriggerDefensiveProcs(Mob *on, uint16 hand = MainPrimary, bool SkillProc=false, int damage = 0); + void TriggerDefensiveProcs(Mob *on, uint16 hand = MainPrimary, bool FromSkillProc=false, int damage = 0); bool AddRangedProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); bool RemoveRangedProc(uint16 spell_id, bool bAll = false); bool HasRangedProcs() const; diff --git a/zone/spells.cpp b/zone/spells.cpp index 90efd791f..c386f81bb 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2011,7 +2011,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 } //range check our target, if we have one and it is not us - float range = spells[spell_id].range; + float range = spells[spell_id].range + GetRangeDistTargetSizeMod(spell_target); if(IsClient() && CastToClient()->TGB() && IsTGBCompatibleSpell(spell_id) && IsGroupSpell(spell_id)) range = spells[spell_id].aoerange; From 5585ddb80b72ffeb072265429d29632aff3bdc77 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 25 Mar 2016 20:26:21 -0400 Subject: [PATCH 014/693] Add OP_Fling stuff so devs can play with --- common/emu_oplist.h | 1 + common/eq_packet_structs.h | 14 ++++++++++++++ utils/patches/patch_RoF.conf | 1 + utils/patches/patch_RoF2.conf | 1 + utils/patches/patch_SoD.conf | 1 + utils/patches/patch_UF.conf | 1 + 6 files changed, 19 insertions(+) diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 223491ecd..936595afa 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -164,6 +164,7 @@ N(OP_FinishTrade), N(OP_FinishWindow), N(OP_FinishWindow2), N(OP_Fishing), +N(OP_Fling), N(OP_FloatListThing), N(OP_Forage), N(OP_ForceFindPerson), diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 74eb9536e..0022aa347 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -5359,6 +5359,20 @@ struct TextLinkBody_Struct { int hash; /* %08X */ }; + +struct fling_struct { +/* 00 */ uint32 unk1; +/* 04 */ int32 travel_time; // ms -- UF we need to calc this, RoF+ -1 auto calcs +/* 08 */ char unk3; // bool, set to 1 has something to do with z-axis or something +/* 09 */ char disable_fall_damage; // 1 you take no fall damage, 0 you take fall damage +/* 10 */ uint8 padding[2]; +/* 12 */ float speed_z; +/* 16 */ float new_y; +/* 20 */ float new_x; +/* 24 */ float new_z; +/* 28 */ +}; + // Restore structure packing to default #pragma pack() diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index 7a33eb459..466043c39 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -356,6 +356,7 @@ OP_Weblink=0x7cce #OP_OpenInventory=0x0000 # Likely does not exist in RoF -U OP_OpenContainer=0x654f OP_Marquee=0x288a +OP_Fling=0x6b8e OP_DzQuit=0x5fc8 OP_DzListTimers=0x67b9 diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 8ae8a1a69..8582ab503 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -357,6 +357,7 @@ OP_Marquee=0x502e OP_ItemRecastDelay=0x15a9 #OP_OpenInventory=0x0000 # Likely does not exist in RoF -U OP_ResetAA=0x1669 +OP_Fling=0x6f80 # Expeditions OP_DzAddPlayer=0x4701 diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index 2f01ef89b..1c362111b 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -351,6 +351,7 @@ OP_InspectMessageUpdate=0x53a3 # C OP_OpenInventory=0x1003 OP_OpenContainer=0x3278 OP_Marquee=0x7dc9 +OP_Fling=0x2b88 # Expedition OP_DzQuit=0x054e diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index 1e57a202d..cb7d11851 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -361,6 +361,7 @@ OP_InspectMessageUpdate=0x7fa1 # C #OP_OpenInventory=0x0000 # Likely does not exist in UF -U OP_OpenContainer=0x041a OP_Marquee=0x3675 +OP_Fling=0x51b1 OP_DzQuit=0x1539 OP_DzListTimers=0x21e9 From 51879e02767a91ac88ec4ff6e86fd24d3239397a Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 26 Mar 2016 18:09:09 -0400 Subject: [PATCH 015/693] Missed a rework for actionable criteria botgroup --- zone/bot_command.cpp | 66 +++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index de07e6a1f..e8b1dcd1c 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -1711,34 +1711,6 @@ namespace MyBots UniquifySBL(sbl); } - static void PopulateSBL_ByBotGroup(Client *bot_owner, std::list &sbl, const char* name, bool clear_list = true) { - if (clear_list) - sbl.clear(); - if (!bot_owner) - return; - - std::list selectable_bot_list; - if (name) - PopulateSBL_ByNamedBot(bot_owner, selectable_bot_list, name); - else if (IsMyBot(bot_owner, bot_owner->GetTarget())) - selectable_bot_list.push_back(bot_owner->GetTarget()->CastToBot()); - - if (selectable_bot_list.empty()) - return; - if (!selectable_bot_list.front()->GetGroup() || !IsMyBot(bot_owner, selectable_bot_list.front()->GetGroup()->GetLeader())) - return; - - std::list group_list; - selectable_bot_list.front()->GetGroup()->GetMemberList(group_list); - for (auto member_iter : group_list) { - if (IsMyBot(bot_owner, member_iter)) - sbl.push_back(member_iter->CastToBot()); - } - - if (!clear_list) - UniquifySBL(sbl); - } - static void PopulateSBL_ByTargetsGroupedBots(Client *bot_owner, std::list &sbl, bool clear_list = true) { if (clear_list) sbl.clear(); @@ -1877,6 +1849,42 @@ namespace MyBots sbl = entity_list.GetBotsByBotOwnerCharacterID(bot_owner->CharacterID()); sbl.remove(nullptr); } + + static void PopulateSBL_ByBotGroup(Client *bot_owner, std::list &sbl, const char* name, bool clear_list = true) { + if (clear_list) + sbl.clear(); + if (!bot_owner || !name) + return; + + std::string group_name = name; + std::string error_message; + uint32 group_id = botdb.GetGroupIDForLoadGroup(bot_owner->CharacterID(), group_name, error_message); + if (!group_id || error_message.size()) + return; + + std::map> group_list = botdb.LoadGroup(group_name, error_message); + if (group_list.find(group_id) == group_list.end() || !group_list[group_id].size() || error_message.size()) + return; + + std::list selectable_bot_list; + PopulateSBL_BySpawnedBots(bot_owner, selectable_bot_list); + if (selectable_bot_list.empty()) + return; + + selectable_bot_list.remove(nullptr); + for (auto group_iter : group_list[group_id]) { + for (auto bot_iter : selectable_bot_list) { + if (bot_iter->GetBotID() != group_iter) + continue; + + if (IsMyBot(bot_owner, bot_iter)) + sbl.push_back(bot_iter); + } + } + + if (!clear_list) + UniquifySBL(sbl); + } }; namespace ActionableTarget @@ -2427,7 +2435,7 @@ void bot_command_actionable(Client *c, const Seperator *sep) c->Message(m_usage, "target: selects target as single bot - use ^command' [target] or imply by empty actionable argument"); c->Message(m_usage, "byname [name]: selects single bot by name"); c->Message(m_usage, "ownergroup: selects all bots in the owner's group"); - c->Message(m_usage, "botgroup [name]: NEEDS REWORK???"); + c->Message(m_usage, "botgroup [name]: selects members of a bot-group by it's name"); c->Message(m_usage, "targetgroup: selects all bots in target's group"); c->Message(m_usage, "namesgroup [name]: selects all bots in name's group"); c->Message(m_usage, "healrotation [name]: selects all member and target bots of a heal rotation where name is a member"); From dc09d6dfbd27c3d85985dc87c3ce6122e77b97ca Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 26 Mar 2016 18:18:40 -0400 Subject: [PATCH 016/693] Added positive evaluation break --- zone/bot_command.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index e8b1dcd1c..12b50e9d2 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -1877,8 +1877,10 @@ namespace MyBots if (bot_iter->GetBotID() != group_iter) continue; - if (IsMyBot(bot_owner, bot_iter)) + if (IsMyBot(bot_owner, bot_iter)) { sbl.push_back(bot_iter); + break; + } } } From 84460e3a1ffba6bc7c5eb7875fed185253c2ab08 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 26 Mar 2016 20:14:22 -0400 Subject: [PATCH 017/693] Fix for self-targeting issue in bot_command_follow --- zone/bot_command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 12b50e9d2..558889962 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -2973,7 +2973,7 @@ void bot_command_follow(Client *c, const Seperator *sep) } else { if (c->GetTarget()) { - if (c->IsAttackAllowed(c->GetTarget())) { + if (c != c->GetTarget() && c->IsAttackAllowed(c->GetTarget())) { c->Message(m_fail, "You must a friendly mob to use this command"); return; } From ebbc6b3f6a3d5a91e215cb797f843973d215e50f Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 26 Mar 2016 21:46:33 -0400 Subject: [PATCH 018/693] Cosmetic update for bot_command_actionable --- zone/bot_command.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 558889962..124bd7205 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -2434,17 +2434,17 @@ void bot_command_actionable(Client *c, const Seperator *sep) c->Message(m_message, "Actionable command arguments:"); - c->Message(m_usage, "target: selects target as single bot - use ^command' [target] or imply by empty actionable argument"); - c->Message(m_usage, "byname [name]: selects single bot by name"); - c->Message(m_usage, "ownergroup: selects all bots in the owner's group"); - c->Message(m_usage, "botgroup [name]: selects members of a bot-group by it's name"); - c->Message(m_usage, "targetgroup: selects all bots in target's group"); - c->Message(m_usage, "namesgroup [name]: selects all bots in name's group"); - c->Message(m_usage, "healrotation [name]: selects all member and target bots of a heal rotation where name is a member"); - c->Message(m_usage, "healrotationmembers [name]: selects all member bots of a heal rotation where name is a member"); - c->Message(m_usage, "healrotationtargets [name]: selects all target bots of a heal rotation where name is a member"); - c->Message(m_usage, "spawned: selects all spawned bots"); - c->Message(m_usage, "all: selects all spawned bots - argument use indicates en masse database updating"); + c->Message(m_usage, "target - selects target as single bot .. use ^command [target] or imply by empty actionable argument"); + c->Message(m_usage, "byname [name] - selects single bot by name"); + c->Message(m_usage, "ownergroup - selects all bots in the owner's group"); + c->Message(m_usage, "botgroup [name] - selects members of a bot-group by it's name"); + c->Message(m_usage, "targetgroup - selects all bots in target's group"); + c->Message(m_usage, "namesgroup [name] - selects all bots in name's group"); + c->Message(m_usage, "healrotation [name] - selects all member and target bots of a heal rotation where name is a member"); + c->Message(m_usage, "healrotationmembers [name] - selects all member bots of a heal rotation where name is a member"); + c->Message(m_usage, "healrotationtargets [name] - selects all target bots of a heal rotation where name is a member"); + c->Message(m_usage, "spawned - selects all spawned bots"); + c->Message(m_usage, "all - selects all spawned bots .. argument use indicates en masse database updating"); c->Message(m_message, "You may only select your bots as actionable"); } From 5d9ec0c4bfa82422c662aaa1b8879b3837e9840f Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 27 Mar 2016 10:27:23 -0400 Subject: [PATCH 019/693] Removed unneccessary entitylist check from ApplySpellBonuses Fixed an issue with FCBaseEffects not applying bonus when cast on targets from runes. --- Server | 1 + common/shareddbx.cpp | 2162 +++++++ common/spdat.h | 2 +- .../required/2014_02_12_spells_new_update.sql | 13 + ...014_04_10_No_Target_With_Hotkey - Copy.sql | 3 + .../git/required/2014_06_22_MetabolismAAs.sql | 6 + zone/AA_base.cpp | 1990 +++++++ zone/AA_v1.cpp | 2032 +++++++ zone/MobAI_M.cpp | 2760 +++++++++ zone/attackx.cpp | 4663 +++++++++++++++ zone/bonuses.cpp | 6 +- zone/bonusesxx.cpp | 4337 ++++++++++++++ zone/groupsx.cpp | 2194 +++++++ zone/mob.h | 4 +- zone/mobx.cpp | 5148 +++++++++++++++++ zone/mobx.h | 1236 ++++ zone/net_Fix.cpp | 644 +++ zone/npcx.cpp | 2492 ++++++++ zone/perl_npcX.cpp | 2487 ++++++++ zone/spell_effects.cpp | 17 +- 20 files changed, 32184 insertions(+), 13 deletions(-) create mode 160000 Server create mode 100644 common/shareddbx.cpp create mode 100644 utils/sql/git/required/2014_02_12_spells_new_update.sql create mode 100644 utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql create mode 100644 utils/sql/git/required/2014_06_22_MetabolismAAs.sql create mode 100644 zone/AA_base.cpp create mode 100644 zone/AA_v1.cpp create mode 100644 zone/MobAI_M.cpp create mode 100644 zone/attackx.cpp create mode 100644 zone/bonusesxx.cpp create mode 100644 zone/groupsx.cpp create mode 100644 zone/mobx.cpp create mode 100644 zone/mobx.h create mode 100644 zone/net_Fix.cpp create mode 100644 zone/npcx.cpp create mode 100644 zone/perl_npcX.cpp diff --git a/Server b/Server new file mode 160000 index 000000000..9d78eec48 --- /dev/null +++ b/Server @@ -0,0 +1 @@ +Subproject commit 9d78eec485fb73c8d61ce035590474556390783e diff --git a/common/shareddbx.cpp b/common/shareddbx.cpp new file mode 100644 index 000000000..60e29cccb --- /dev/null +++ b/common/shareddbx.cpp @@ -0,0 +1,2162 @@ +#include +#include +#include + +#include "shareddb.h" +#include "mysql.h" +#include "Item.h" +#include "classes.h" +#include "rulesys.h" +#include "seperator.h" +#include "StringUtil.h" +#include "eq_packet_structs.h" +#include "guilds.h" +#include "extprofile.h" +#include "memory_mapped_file.h" +#include "ipc_mutex.h" +#include "eqemu_exception.h" +#include "loottable.h" +#include "faction.h" +#include "features.h" + +SharedDatabase::SharedDatabase() +: Database(), skill_caps_mmf(nullptr), items_mmf(nullptr), items_hash(nullptr), faction_mmf(nullptr), faction_hash(nullptr), + loot_table_mmf(nullptr), loot_table_hash(nullptr), loot_drop_mmf(nullptr), loot_drop_hash(nullptr), base_data_mmf(nullptr) +{ +} + +SharedDatabase::SharedDatabase(const char* host, const char* user, const char* passwd, const char* database, uint32 port) +: Database(host, user, passwd, database, port), skill_caps_mmf(nullptr), items_mmf(nullptr), items_hash(nullptr), + faction_mmf(nullptr), faction_hash(nullptr), loot_table_mmf(nullptr), loot_table_hash(nullptr), loot_drop_mmf(nullptr), + loot_drop_hash(nullptr), base_data_mmf(nullptr) +{ +} + +SharedDatabase::~SharedDatabase() { + safe_delete(skill_caps_mmf); + safe_delete(items_mmf); + safe_delete(items_hash); + safe_delete(faction_mmf); + safe_delete(faction_hash); + safe_delete(loot_table_mmf); + safe_delete(loot_drop_mmf); + safe_delete(loot_table_hash); + safe_delete(loot_drop_hash); + safe_delete(base_data_mmf); +} + +bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme) +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET hideme = %i where id = %i", hideme, account_id), errbuf)) { + std::cerr << "Error in SetGMSpeed query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return false; + } + + safe_delete_array(query); + return true; + +} + +uint8 SharedDatabase::GetGMSpeed(uint32 account_id) +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT gmspeed FROM account where id='%i'", account_id), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) + { + row = mysql_fetch_row(result); + uint8 gmspeed = atoi(row[0]); + mysql_free_result(result); + return gmspeed; + } + else + { + mysql_free_result(result); + return 0; + } + mysql_free_result(result); + } + else + { + + std::cerr << "Error in GetGMSpeed query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return false; + } + + return 0; + + +} + +bool SharedDatabase::SetGMSpeed(uint32 account_id, uint8 gmspeed) +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET gmspeed = %i where id = %i", gmspeed, account_id), errbuf)) { + std::cerr << "Error in SetGMSpeed query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return false; + } + + safe_delete_array(query); + return true; + +} + +uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) { + + uint32 EntitledTime = 0; + + const char *EntitledQuery = "select sum(ascii(substring(profile, 237, 1)) + (ascii(substring(profile, 238, 1)) * 256) +" + "(ascii(substring(profile, 239, 1)) * 65536) + (ascii(substring(profile, 240, 1)) * 16777216))" + "from character_ where account_id = %i"; + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + if (RunQuery(query, MakeAnyLenString(&query, EntitledQuery, AccountID), errbuf, &result)) { + + if (mysql_num_rows(result) == 1) { + + row = mysql_fetch_row(result); + + EntitledTime = atoi(row[0]); + } + + mysql_free_result(result); + } + + safe_delete_array(query); + + return EntitledTime; +} + +bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iterator &start, std::list::const_iterator &end) +{ +iter_queue it; +int i; +bool ret=true; + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + // Delete cursor items + if ((ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND ( (slotid >=8000 and slotid<=8999) or slotid=30 or (slotid>=331 and slotid<=340))", char_id), errbuf))) { + for(it=start,i=8000;it!=end;++it,i++) { + ItemInst *inst=*it; + if (!(ret=SaveInventory(char_id,inst,(i==8000) ? 30 : i))) + break; + } + } else { + std::cout << "Clearing cursor failed: " << errbuf << std::endl; + } + safe_delete_array(query); + + return ret; +} + +bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const ItemInst* inst) +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + // Delete cursor items + if (!RunQuery(query, MakeAnyLenString(&query, + "SELECT itemid,charges FROM sharedbank " + "WHERE acctid=%d AND slotid=%d", + account_id, slot_id), errbuf, &result)) { + LogFile->write(EQEMuLog::Error, "Error runing inventory verification query '%s': %s", query, errbuf); + safe_delete_array(query); + //returning true is less harmful in the face of a query error + return(true); + } + safe_delete_array(query); + + row = mysql_fetch_row(result); + bool found = false; + if(row) { + uint32 id = atoi(row[0]); + uint16 charges = atoi(row[1]); + + uint16 expect_charges = 0; + if(inst->GetCharges() >= 0) + expect_charges = inst->GetCharges(); + else + expect_charges = 0x7FFF; + + if(id == inst->GetItem()->ID && charges == expect_charges) + found = true; + } + mysql_free_result(result); + return(found); +} + +bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 slot_id) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + bool ret = false; + uint32 augslot[5] = { 0, 0, 0, 0, 0 }; + + //never save tribute slots: + if(slot_id >= 400 && slot_id <= 404) + return(true); + + if (inst && inst->IsType(ItemClassCommon)) { + for(int i=0;i<5;i++) { + ItemInst *auginst=inst->GetItem(i); + augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; + } + } + + if (slot_id>=2500 && slot_id<=2600) { // Shared bank inventory + if (!inst) { + // Delete item + uint32 account_id = GetAccountIDByChar(char_id); + uint32 len_query = MakeAnyLenString(&query, "DELETE FROM sharedbank WHERE acctid=%i AND slotid=%i", + account_id, slot_id); + + ret = RunQuery(query, len_query, errbuf); + + // Delete bag slots, if need be + if (ret && Inventory::SupportsContainers(slot_id)) { + safe_delete_array(query); + int16 base_slot_id = Inventory::CalcSlotId(slot_id, 0); + ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM sharedbank WHERE acctid=%i AND slotid>=%i AND slotid<%i", + account_id, base_slot_id, (base_slot_id+10)), errbuf); + } + + // @merth: need to delete augments here + } + else { + // Update/Insert item + uint32 account_id = GetAccountIDByChar(char_id); + uint16 charges = 0; + if(inst->GetCharges() >= 0) + charges = inst->GetCharges(); + else + charges = 0x7FFF; + + uint32 len_query = MakeAnyLenString(&query, + "REPLACE INTO sharedbank " + " (acctid,slotid,itemid,charges,custom_data," + " augslot1,augslot2,augslot3,augslot4,augslot5)" + " VALUES(%lu,%lu,%lu,%lu,'%s'," + " %lu,%lu,%lu,%lu,%lu)", + (unsigned long)account_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, (unsigned long)charges, + inst->GetCustomDataString().c_str(), + (unsigned long)augslot[0],(unsigned long)augslot[1],(unsigned long)augslot[2],(unsigned long)augslot[3],(unsigned long)augslot[4]); + + + ret = RunQuery(query, len_query, errbuf); + } + } + else { // All other inventory + if (!inst) { + // Delete item + ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND slotid=%i", + char_id, slot_id), errbuf); + + // Delete bag slots, if need be + if (ret && Inventory::SupportsContainers(slot_id)) { + safe_delete_array(query); + int16 base_slot_id = Inventory::CalcSlotId(slot_id, 0); + ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND slotid>=%i AND slotid<%i", + char_id, base_slot_id, (base_slot_id+10)), errbuf); + } + + // @merth: need to delete augments here + } + else { + uint16 charges = 0; + if(inst->GetCharges() >= 0) + charges = inst->GetCharges(); + else + charges = 0x7FFF; + // Update/Insert item + uint32 len_query = MakeAnyLenString(&query, + "REPLACE INTO inventory " + " (charid,slotid,itemid,charges,instnodrop,custom_data,color," + " augslot1,augslot2,augslot3,augslot4,augslot5)" + " VALUES(%lu,%lu,%lu,%lu,%lu,'%s',%lu," + " %lu,%lu,%lu,%lu,%lu)", + (unsigned long)char_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, (unsigned long)charges, + (unsigned long)(inst->IsInstNoDrop() ? 1:0),inst->GetCustomDataString().c_str(),(unsigned long)inst->GetColor(), + (unsigned long)augslot[0],(unsigned long)augslot[1],(unsigned long)augslot[2],(unsigned long)augslot[3],(unsigned long)augslot[4] ); + + ret = RunQuery(query, len_query, errbuf); + } + } + + if (!ret) + LogFile->write(EQEMuLog::Error, "SaveInventory query '%s': %s", query, errbuf); + safe_delete_array(query); + + // Save bag contents, if slot supports bag contents + if (inst && inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) { + for (uint8 idx=0; idx<10; idx++) { + const ItemInst* baginst = inst->GetItem(idx); + SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); + } + } + + // @merth: need to save augments here + + return ret; +} + +int32 SharedDatabase::GetSharedPlatinum(uint32 account_id) +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT sharedplat FROM account WHERE id='%i'", account_id), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) + { + row = mysql_fetch_row(result); + uint32 shared_platinum = atoi(row[0]); + mysql_free_result(result); + return shared_platinum; + } + else + { + mysql_free_result(result); + return 0; + } + mysql_free_result(result); + } + else + { + std::cerr << "Error in GetSharedPlatinum query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return false; + } + + return 0; +} + +bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id), errbuf)) { + std::cerr << "Error in SetSharedPlatinum query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return false; + } + + safe_delete_array(query); + return true; +} + +bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + const Item_Struct* myitem; + + RunQuery + ( + query, + MakeAnyLenString + ( + &query, + "SELECT itemid, item_charges, slot FROM starting_items " + "WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND " + "(deityid = %i or deityid=0) AND (zoneid = %i or zoneid = 0) AND " + "gm <= %i ORDER BY id", + si_race, si_class, si_deity, si_current_zone, admin_level + ), + errbuf, + &result + ); + safe_delete_array(query); + + while((row = mysql_fetch_row(result))) { + int itemid = atoi(row[0]); + int charges = atoi(row[1]); + int slot = atoi(row[2]); + myitem = GetItem(itemid); + if(!myitem) + continue; + ItemInst* myinst = CreateBaseItem(myitem, charges); + if(slot < 0) + slot = inv->FindFreeSlot(0,0); + inv->PutItem(slot, *myinst); + safe_delete(myinst); + } + + if(result) mysql_free_result(result); + + return true; +} + + +// Retrieve shared bank inventory based on either account or character +bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + uint32 len_query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + bool ret = false; + + if (is_charid) { + len_query = MakeAnyLenString(&query, + "SELECT sb.slotid,sb.itemid,sb.charges,sb.augslot1,sb.augslot2,sb.augslot3,sb.augslot4,sb.augslot5,sb.custom_data from sharedbank sb " + "INNER JOIN character_ ch ON ch.account_id=sb.acctid " + "WHERE ch.id=%i", id); + } + else { + len_query = MakeAnyLenString(&query, + "SELECT slotid,itemid,charges,augslot1,augslot2,augslot3,augslot4,augslot5,custom_data from sharedbank WHERE acctid=%i", id); + } + + if (RunQuery(query, len_query, errbuf, &result)) { + while ((row = mysql_fetch_row(result))) { + int16 slot_id = (int16)atoi(row[0]); + uint32 item_id = (uint32)atoi(row[1]); + int8 charges = (int8)atoi(row[2]); + uint32 aug[5]; + aug[0] = (uint32)atoi(row[3]); + aug[1] = (uint32)atoi(row[4]); + aug[2] = (uint32)atoi(row[5]); + aug[3] = (uint32)atoi(row[6]); + aug[4] = (uint32)atoi(row[7]); + const Item_Struct* item = GetItem(item_id); + + if (item) { + int16 put_slot_id = INVALID_INDEX; + + ItemInst* inst = CreateBaseItem(item, charges); + if (item->ItemClass == ItemClassCommon) { + for(int i=0;i<5;i++) { + if (aug[i]) { + inst->PutAugment(this, i, aug[i]); + } + } + } + if(row[8]) { + std::string data_str(row[8]); + std::string id; + std::string value; + bool use_id = true; + + for(int i = 0; i < data_str.length(); ++i) { + if(data_str[i] == '^') { + if(!use_id) { + inst->SetCustomData(id, value); + id.clear(); + value.clear(); + } + use_id = !use_id; + } + else { + char v = data_str[i]; + if(use_id) { + id.push_back(v); + } else { + value.push_back(v); + } + } + } + } + + put_slot_id = inv->PutItem(slot_id, *inst); + safe_delete(inst); + + // Save ptr to item in inventory + if (put_slot_id == INVALID_INDEX) { + LogFile->write(EQEMuLog::Error, + "Warning: Invalid slot_id for item in shared bank inventory: %s=%i, item_id=%i, slot_id=%i", + ((is_charid==true) ? "charid" : "acctid"), id, item_id, slot_id); + + if(is_charid) + SaveInventory(id,nullptr,slot_id); + } + } + else { + LogFile->write(EQEMuLog::Error, + "Warning: %s %i has an invalid item_id %i in inventory slot %i", + ((is_charid==true) ? "charid" : "acctid"), id, item_id, slot_id); + } + } + + mysql_free_result(result); + ret = true; + } + else { + LogFile->write(EQEMuLog::Error, "Database::GetSharedBank(uint32 account_id): %s", errbuf); + } + + safe_delete_array(query); + return ret; +} + + +// Overloaded: Retrieve character inventory based on character id +bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES* result; + MYSQL_ROW row; + bool ret = false; + + // Retrieve character inventory + if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5," + "instnodrop,custom_data FROM inventory WHERE charid=%i ORDER BY slotid", char_id), errbuf, &result)) { + + while ((row = mysql_fetch_row(result))) { + int16 slot_id = atoi(row[0]); + uint32 item_id = atoi(row[1]); + uint16 charges = atoi(row[2]); + uint32 color = atoul(row[3]); + uint32 aug[5]; + aug[0] = (uint32)atoul(row[4]); + aug[1] = (uint32)atoul(row[5]); + aug[2] = (uint32)atoul(row[6]); + aug[3] = (uint32)atoul(row[7]); + aug[4] = (uint32)atoul(row[8]); + bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false; + + const Item_Struct* item = GetItem(item_id); + + if (item) { + int16 put_slot_id = INVALID_INDEX; + + ItemInst* inst = CreateBaseItem(item, charges); + + if(row[10]) { + std::string data_str(row[10]); + std::string id; + std::string value; + bool use_id = true; + + for(int i = 0; i < data_str.length(); ++i) { + if(data_str[i] == '^') { + if(!use_id) { + inst->SetCustomData(id, value); + id.clear(); + value.clear(); + } + use_id = !use_id; + } + else { + char v = data_str[i]; + if(use_id) { + id.push_back(v); + } else { + value.push_back(v); + } + } + } + } + + if (instnodrop || (slot_id >= 0 && slot_id <= 21 && inst->GetItem()->Attuneable)) + inst->SetInstNoDrop(true); + if (color > 0) + inst->SetColor(color); + if(charges==0x7FFF) + inst->SetCharges(-1); + else + inst->SetCharges(charges); + + if (item->ItemClass == ItemClassCommon) { + for(int i=0;i<5;i++) { + if (aug[i]) { + inst->PutAugment(this, i, aug[i]); + } + } + } + + if (slot_id>=8000 && slot_id <= 8999) + put_slot_id = inv->PushCursor(*inst); + else + put_slot_id = inv->PutItem(slot_id, *inst); + safe_delete(inst); + + // Save ptr to item in inventory + if (put_slot_id == INVALID_INDEX) { + LogFile->write(EQEMuLog::Error, + "Warning: Invalid slot_id for item in inventory: charid=%i, item_id=%i, slot_id=%i", + char_id, item_id, slot_id); + } + } + else { + LogFile->write(EQEMuLog::Error, + "Warning: charid %i has an invalid item_id %i in inventory slot %i", + char_id, item_id, slot_id); + } + } + mysql_free_result(result); + + // Retrieve shared inventory + ret = GetSharedBank(char_id, inv, true); + } + else { + LogFile->write(EQEMuLog::Error, "GetInventory query '%s' %s", query, errbuf); + LogFile->write(EQEMuLog::Error, "If you got an error related to the 'instnodrop' field, run the following SQL Queries:\nalter table inventory add instnodrop tinyint(1) unsigned default 0 not null;\n"); + } + + safe_delete_array(query); + return ret; +} + +// Overloaded: Retrieve character inventory based on account_id and character name +bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES* result; + MYSQL_ROW row; + bool ret = false; + + // Retrieve character inventory + if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5," + "instnodrop,custom_data FROM inventory INNER JOIN character_ ch ON ch.id=charid WHERE ch.name='%s' AND ch.account_id=%i ORDER BY slotid", + name, account_id), errbuf, &result)) + { + while ((row = mysql_fetch_row(result))) { + int16 slot_id = atoi(row[0]); + uint32 item_id = atoi(row[1]); + int8 charges = atoi(row[2]); + uint32 color = atoul(row[3]); + uint32 aug[5]; + aug[0] = (uint32)atoi(row[4]); + aug[1] = (uint32)atoi(row[5]); + aug[2] = (uint32)atoi(row[6]); + aug[3] = (uint32)atoi(row[7]); + aug[4] = (uint32)atoi(row[8]); + bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false; + const Item_Struct* item = GetItem(item_id); + int16 put_slot_id = INVALID_INDEX; + if(!item) + continue; + + ItemInst* inst = CreateBaseItem(item, charges); + inst->SetInstNoDrop(instnodrop); + + if(row[10]) { + std::string data_str(row[10]); + std::string id; + std::string value; + bool use_id = true; + + for(int i = 0; i < data_str.length(); ++i) { + if(data_str[i] == '^') { + if(!use_id) { + inst->SetCustomData(id, value); + id.clear(); + value.clear(); + } + use_id = !use_id; + } + else { + char v = data_str[i]; + if(use_id) { + id.push_back(v); + } else { + value.push_back(v); + } + } + } + } + + if (color > 0) + inst->SetColor(color); + inst->SetCharges(charges); + + if (item->ItemClass == ItemClassCommon) { + for(int i=0;i<5;i++) { + if (aug[i]) { + inst->PutAugment(this, i, aug[i]); + } + } + } + if (slot_id>=8000 && slot_id <= 8999) + put_slot_id = inv->PushCursor(*inst); + else + put_slot_id = inv->PutItem(slot_id, *inst); + safe_delete(inst); + + // Save ptr to item in inventory + if (put_slot_id == INVALID_INDEX) { + LogFile->write(EQEMuLog::Error, + "Warning: Invalid slot_id for item in inventory: name=%s, acctid=%i, item_id=%i, slot_id=%i", + name, account_id, item_id, slot_id); + } + } + mysql_free_result(result); + + // Retrieve shared inventory + ret = GetSharedBank(account_id, inv, false); + } + else { + LogFile->write(EQEMuLog::Error, "GetInventory query '%s' %s", query, errbuf); + LogFile->write(EQEMuLog::Error, "If you got an error related to the 'instnodrop' field, run the following SQL Queries:\nalter table inventory add instnodrop tinyint(1) unsigned default 0 not null;\n"); + } + + safe_delete_array(query); + return ret; +} + + +void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id) { + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + item_count = -1; + max_id = 0; + + char query[] = "SELECT MAX(id), count(*) FROM items"; + if (RunQuery(query, static_cast(strlen(query)), errbuf, &result)) { + row = mysql_fetch_row(result); + if (row != nullptr && row[1] != 0) { + item_count = atoi(row[1]); + if(row[0]) + max_id = atoi(row[0]); + } + mysql_free_result(result); + } + else { + LogFile->write(EQEMuLog::Error, "Error in GetItemsCount '%s': '%s'", query, errbuf); + } +} + +bool SharedDatabase::LoadItems() { + if(items_mmf) { + return true; + } + + try { + EQEmu::IPCMutex mutex("items"); + mutex.Lock(); + items_mmf = new EQEmu::MemoryMappedFile("shared/items"); + + int32 items = -1; + uint32 max_item = 0; + GetItemsCount(items, max_item); + if(items == -1) { + EQ_EXCEPT("SharedDatabase", "Database returned no result"); + } + uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); + if(items_mmf->Size() != size) { + EQ_EXCEPT("SharedDatabase", "Couldn't load items because items_mmf->Size() != size"); + } + + items_hash = new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), size); + mutex.Unlock(); + } catch(std::exception& ex) { + LogFile->write(EQEMuLog::Error, "Error Loading Items: %s", ex.what()); + return false; + } + + return true; +} + +void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id) { + EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + + char ndbuffer[4]; + bool disableNoRent = false; + if(GetVariable("disablenorent", ndbuffer, 4)) { + if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { + disableNoRent = true; + } + } + bool disableNoDrop = false; + if(GetVariable("disablenodrop", ndbuffer, 4)) { + if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { + disableNoDrop = true; + } + } + bool disableLoreGroup = false; + if(GetVariable("disablelore", ndbuffer, 4)) { + if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { + disableLoreGroup = true; + } + } + bool disableNoTransfer = false; + if(GetVariable("disablenotransfer", ndbuffer, 4)) { + if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { + disableNoTransfer = true; + } + } + + char query[] = "select source," +#define F(x) "`"#x"`," +#include "item_fieldlist.h" +#undef F + "updated" + " from items order by id"; + Item_Struct item; + if(RunQuery(query, sizeof(query), errbuf, &result)) { + while((row = mysql_fetch_row(result))) { + memset(&item, 0, sizeof(Item_Struct)); + + item.ItemClass = (uint8)atoi(row[ItemField::itemclass]); + strcpy(item.Name,row[ItemField::name]); + strcpy(item.Lore,row[ItemField::lore]); + strcpy(item.IDFile,row[ItemField::idfile]); + item.ID = (uint32)atoul(row[ItemField::id]); + item.Weight = (uint8)atoi(row[ItemField::weight]); + item.NoRent = disableNoRent ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::norent]); + item.NoDrop = disableNoDrop ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::nodrop]); + item.Size = (uint8)atoi(row[ItemField::size]); + item.Slots = (uint32)atoul(row[ItemField::slots]); + item.Price = (uint32)atoul(row[ItemField::price]); + item.Icon = (uint32)atoul(row[ItemField::icon]); + item.BenefitFlag = (atoul(row[ItemField::benefitflag]) != 0); + item.Tradeskills = (atoi(row[ItemField::tradeskills])==0) ? false : true; + item.CR = (int8)atoi(row[ItemField::cr]); + item.DR = (int8)atoi(row[ItemField::dr]); + item.PR = (int8)atoi(row[ItemField::pr]); + item.MR = (int8)atoi(row[ItemField::mr]); + item.FR = (int8)atoi(row[ItemField::fr]); + item.AStr = (int8)atoi(row[ItemField::astr]); + item.ASta = (int8)atoi(row[ItemField::asta]); + item.AAgi = (int8)atoi(row[ItemField::aagi]); + item.ADex = (int8)atoi(row[ItemField::adex]); + item.ACha = (int8)atoi(row[ItemField::acha]); + item.AInt = (int8)atoi(row[ItemField::aint]); + item.AWis = (int8)atoi(row[ItemField::awis]); + item.HP = (int32)atoul(row[ItemField::hp]); + item.Mana = (int32)atoul(row[ItemField::mana]); + item.AC = (int32)atoul(row[ItemField::ac]); + item.Deity = (uint32)atoul(row[ItemField::deity]); + item.SkillModValue = (int32)atoul(row[ItemField::skillmodvalue]); + //item.Unk033 = (int32)atoul(row[ItemField::UNK033]); + item.SkillModType = (uint32)atoul(row[ItemField::skillmodtype]); + item.BaneDmgRace = (uint32)atoul(row[ItemField::banedmgrace]); + item.BaneDmgAmt = (int8)atoi(row[ItemField::banedmgamt]); + item.BaneDmgBody = (uint32)atoul(row[ItemField::banedmgbody]); + item.Magic = (atoi(row[ItemField::magic])==0) ? false : true; + item.CastTime_ = (int32)atoul(row[ItemField::casttime_]); + item.ReqLevel = (uint8)atoi(row[ItemField::reqlevel]); + item.BardType = (uint32)atoul(row[ItemField::bardtype]); + item.BardValue = (int32)atoul(row[ItemField::bardvalue]); + item.Light = (int8)atoi(row[ItemField::light]); + item.Delay = (uint8)atoi(row[ItemField::delay]); + item.RecLevel = (uint8)atoi(row[ItemField::reclevel]); + item.RecSkill = (uint8)atoi(row[ItemField::recskill]); + item.ElemDmgType = (uint8)atoi(row[ItemField::elemdmgtype]); + item.ElemDmgAmt = (uint8)atoi(row[ItemField::elemdmgamt]); + item.Range = (uint8)atoi(row[ItemField::range]); + item.Damage = (uint32)atoi(row[ItemField::damage]); + item.Color = (uint32)atoul(row[ItemField::color]); + item.Classes = (uint32)atoul(row[ItemField::classes]); + item.Races = (uint32)atoul(row[ItemField::races]); + //item.Unk054 = (uint32)atoul(row[ItemField::UNK054]); + item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]); + item.ItemType = (uint8)atoi(row[ItemField::itemtype]); + item.Material = (uint8)atoi(row[ItemField::material]); + item.SellRate = (float)atof(row[ItemField::sellrate]); + //item.Unk059 = (uint32)atoul(row[ItemField::UNK059]); + item.CastTime = (uint32)atoul(row[ItemField::casttime]); + item.EliteMaterial = (uint32)atoul(row[ItemField::elitematerial]); + item.ProcRate = (int32)atoi(row[ItemField::procrate]); + item.CombatEffects = (int8)atoi(row[ItemField::combateffects]); + item.Shielding = (int8)atoi(row[ItemField::shielding]); + item.StunResist = (int8)atoi(row[ItemField::stunresist]); + item.StrikeThrough = (int8)atoi(row[ItemField::strikethrough]); + item.ExtraDmgSkill = (uint32)atoul(row[ItemField::extradmgskill]); + item.ExtraDmgAmt = (uint32)atoul(row[ItemField::extradmgamt]); + item.SpellShield = (int8)atoi(row[ItemField::spellshield]); + item.Avoidance = (int8)atoi(row[ItemField::avoidance]); + item.Accuracy = (int8)atoi(row[ItemField::accuracy]); + item.CharmFileID = (uint32)atoul(row[ItemField::charmfileid]); + item.FactionMod1 = (int32)atoul(row[ItemField::factionmod1]); + item.FactionMod2 = (int32)atoul(row[ItemField::factionmod2]); + item.FactionMod3 = (int32)atoul(row[ItemField::factionmod3]); + item.FactionMod4 = (int32)atoul(row[ItemField::factionmod4]); + item.FactionAmt1 = (int32)atoul(row[ItemField::factionamt1]); + item.FactionAmt2 = (int32)atoul(row[ItemField::factionamt2]); + item.FactionAmt3 = (int32)atoul(row[ItemField::factionamt3]); + item.FactionAmt4 = (int32)atoul(row[ItemField::factionamt4]); + strcpy(item.CharmFile,row[ItemField::charmfile]); + item.AugType = (uint32)atoul(row[ItemField::augtype]); + item.AugSlotType[0] = (uint8)atoi(row[ItemField::augslot1type]); + item.AugSlotVisible[0] = (uint8)atoi(row[ItemField::augslot1visible]); + item.AugSlotUnk2[0] = 0; + item.AugSlotType[1] = (uint8)atoi(row[ItemField::augslot2type]); + item.AugSlotVisible[1] = (uint8)atoi(row[ItemField::augslot2visible]); + item.AugSlotUnk2[1] = 0; + item.AugSlotType[2] = (uint8)atoi(row[ItemField::augslot3type]); + item.AugSlotVisible[2] = (uint8)atoi(row[ItemField::augslot3visible]); + item.AugSlotUnk2[2] = 0; + item.AugSlotType[3] = (uint8)atoi(row[ItemField::augslot4type]); + item.AugSlotVisible[3] = (uint8)atoi(row[ItemField::augslot4visible]); + item.AugSlotUnk2[3] = 0; + item.AugSlotType[4] = (uint8)atoi(row[ItemField::augslot5type]); + item.AugSlotVisible[4] = (uint8)atoi(row[ItemField::augslot5visible]); + item.AugSlotUnk2[4] = 0; + item.LDoNTheme = (uint32)atoul(row[ItemField::ldontheme]); + item.LDoNPrice = (uint32)atoul(row[ItemField::ldonprice]); + item.LDoNSold = (uint32)atoul(row[ItemField::ldonsold]); + item.BagType = (uint8)atoi(row[ItemField::bagtype]); + item.BagSlots = (uint8)atoi(row[ItemField::bagslots]); + item.BagSize = (uint8)atoi(row[ItemField::bagsize]); + item.BagWR = (uint8)atoi(row[ItemField::bagwr]); + item.Book = (uint8)atoi(row[ItemField::book]); + item.BookType = (uint32)atoul(row[ItemField::booktype]); + strcpy(item.Filename,row[ItemField::filename]); + item.BaneDmgRaceAmt = (uint32)atoul(row[ItemField::banedmgraceamt]); + item.AugRestrict = (uint32)atoul(row[ItemField::augrestrict]); + item.LoreGroup = disableLoreGroup ? (uint8)atoi("0") : atoi(row[ItemField::loregroup]); + item.LoreFlag = item.LoreGroup!=0; + item.PendingLoreFlag = (atoi(row[ItemField::pendingloreflag])==0) ? false : true; + item.ArtifactFlag = (atoi(row[ItemField::artifactflag])==0) ? false : true; + item.SummonedFlag = (atoi(row[ItemField::summonedflag])==0) ? false : true; + item.Favor = (uint32)atoul(row[ItemField::favor]); + item.FVNoDrop = (atoi(row[ItemField::fvnodrop])==0) ? false : true; + item.Endur = (uint32)atoul(row[ItemField::endur]); + item.DotShielding = (uint32)atoul(row[ItemField::dotshielding]); + item.Attack = (uint32)atoul(row[ItemField::attack]); + item.Regen = (uint32)atoul(row[ItemField::regen]); + item.ManaRegen = (uint32)atoul(row[ItemField::manaregen]); + item.EnduranceRegen = (uint32)atoul(row[ItemField::enduranceregen]); + item.Haste = (uint32)atoul(row[ItemField::haste]); + item.DamageShield = (uint32)atoul(row[ItemField::damageshield]); + item.RecastDelay = (uint32)atoul(row[ItemField::recastdelay]); + item.RecastType = (uint32)atoul(row[ItemField::recasttype]); + item.GuildFavor = (uint32)atoul(row[ItemField::guildfavor]); + item.AugDistiller = (uint32)atoul(row[ItemField::augdistiller]); + item.Attuneable = (atoi(row[ItemField::attuneable])==0) ? false : true; + item.NoPet = (atoi(row[ItemField::nopet])==0) ? false : true; + item.PointType = (uint32)atoul(row[ItemField::pointtype]); + item.PotionBelt = (atoi(row[ItemField::potionbelt])==0) ? false : true; + item.PotionBeltSlots = (atoi(row[ItemField::potionbeltslots])==0) ? false : true; + item.StackSize = (uint16)atoi(row[ItemField::stacksize]); + item.NoTransfer = disableNoTransfer ? false : (atoi(row[ItemField::notransfer])==0) ? false : true; + item.Stackable = (atoi(row[ItemField::stackable])==0) ? false : true; + item.Click.Effect = (uint32)atoul(row[ItemField::clickeffect]); + item.Click.Type = (uint8)atoul(row[ItemField::clicktype]); + item.Click.Level = (uint8)atoul(row[ItemField::clicklevel]); + item.Click.Level2 = (uint8)atoul(row[ItemField::clicklevel2]); + strcpy(item.CharmFile,row[ItemField::charmfile]); + item.Proc.Effect = (uint16)atoul(row[ItemField::proceffect]); + item.Proc.Type = (uint8)atoul(row[ItemField::proctype]); + item.Proc.Level = (uint8)atoul(row[ItemField::proclevel]); + item.Proc.Level2 = (uint8)atoul(row[ItemField::proclevel2]); + item.Worn.Effect = (uint16)atoul(row[ItemField::worneffect]); + item.Worn.Type = (uint8)atoul(row[ItemField::worntype]); + item.Worn.Level = (uint8)atoul(row[ItemField::wornlevel]); + item.Worn.Level2 = (uint8)atoul(row[ItemField::wornlevel2]); + item.Focus.Effect = (uint16)atoul(row[ItemField::focuseffect]); + item.Focus.Type = (uint8)atoul(row[ItemField::focustype]); + item.Focus.Level = (uint8)atoul(row[ItemField::focuslevel]); + item.Focus.Level2 = (uint8)atoul(row[ItemField::focuslevel2]); + item.Scroll.Effect = (uint16)atoul(row[ItemField::scrolleffect]); + item.Scroll.Type = (uint8)atoul(row[ItemField::scrolltype]); + item.Scroll.Level = (uint8)atoul(row[ItemField::scrolllevel]); + item.Scroll.Level2 = (uint8)atoul(row[ItemField::scrolllevel2]); + item.Bard.Effect = (uint16)atoul(row[ItemField::bardeffect]); + item.Bard.Type = (uint8)atoul(row[ItemField::bardtype]); + item.Bard.Level = (uint8)atoul(row[ItemField::bardlevel]); + item.Bard.Level2 = (uint8)atoul(row[ItemField::bardlevel2]); + item.QuestItemFlag = (atoi(row[ItemField::questitemflag])==0) ? false : true; + item.SVCorruption = (int32)atoi(row[ItemField::svcorruption]); + item.Purity = (uint32)atoul(row[ItemField::purity]); + item.BackstabDmg = (uint32)atoul(row[ItemField::backstabdmg]); + item.DSMitigation = (uint32)atoul(row[ItemField::dsmitigation]); + item.HeroicStr = (int32)atoi(row[ItemField::heroic_str]); + item.HeroicInt = (int32)atoi(row[ItemField::heroic_int]); + item.HeroicWis = (int32)atoi(row[ItemField::heroic_wis]); + item.HeroicAgi = (int32)atoi(row[ItemField::heroic_agi]); + item.HeroicDex = (int32)atoi(row[ItemField::heroic_dex]); + item.HeroicSta = (int32)atoi(row[ItemField::heroic_sta]); + item.HeroicCha = (int32)atoi(row[ItemField::heroic_cha]); + item.HeroicMR = (int32)atoi(row[ItemField::heroic_mr]); + item.HeroicFR = (int32)atoi(row[ItemField::heroic_fr]); + item.HeroicCR = (int32)atoi(row[ItemField::heroic_cr]); + item.HeroicDR = (int32)atoi(row[ItemField::heroic_dr]); + item.HeroicPR = (int32)atoi(row[ItemField::heroic_pr]); + item.HeroicSVCorrup = (int32)atoi(row[ItemField::heroic_svcorrup]); + item.HealAmt = (int32)atoi(row[ItemField::healamt]); + item.SpellDmg = (int32)atoi(row[ItemField::spelldmg]); + item.LDoNSellBackRate = (uint32)atoul(row[ItemField::ldonsellbackrate]); + item.ScriptFileID = (uint32)atoul(row[ItemField::scriptfileid]); + item.ExpendableArrow = (uint16)atoul(row[ItemField::expendablearrow]); + item.Clairvoyance = (uint32)atoul(row[ItemField::clairvoyance]); + strcpy(item.ClickName,row[ItemField::clickname]); + strcpy(item.ProcName,row[ItemField::procname]); + strcpy(item.WornName,row[ItemField::wornname]); + strcpy(item.FocusName,row[ItemField::focusname]); + strcpy(item.ScrollName,row[ItemField::scrollname]); + + try { + hash.insert(item.ID, item); + } catch(std::exception &ex) { + LogFile->write(EQEMuLog::Error, "Database::LoadItems: %s", ex.what()); + break; + } + } + + mysql_free_result(result); + } + else { + LogFile->write(EQEMuLog::Error, "LoadItems '%s', %s", query, errbuf); + } +} + +const Item_Struct* SharedDatabase::GetItem(uint32 id) { + if(!items_hash || id > items_hash->max_key()) { + return nullptr; + } + + if(items_hash->exists(id)) { + return &(items_hash->at(id)); + } + + return nullptr; +} + +const Item_Struct* SharedDatabase::IterateItems(uint32* id) { + if(!items_hash || !id) { + return nullptr; + } + + for(;;) { + if(*id > items_hash->max_key()) { + break; + } + + if(items_hash->exists(*id)) { + return &(items_hash->at((*id)++)); + } else { + ++(*id); + } + } + + return nullptr; +} + +std::string SharedDatabase::GetBook(const char *txtfile) +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + char txtfile2[20]; + std::string txtout; + strcpy(txtfile2,txtfile); + if (!RunQuery(query, MakeAnyLenString(&query, "SELECT txtfile FROM books where name='%s'", txtfile2), errbuf, &result)) { + std::cerr << "Error in GetBook query '" << query << "' " << errbuf << std::endl; + if (query != 0) + safe_delete_array(query); + txtout.assign(" ",1); + return txtout; + } + else { + safe_delete_array(query); + if (mysql_num_rows(result) == 0) { + mysql_free_result(result); + LogFile->write(EQEMuLog::Error, "No book to send, (%s)", txtfile); + txtout.assign(" ",1); + return txtout; + } + else { + row = mysql_fetch_row(result); + txtout.assign(row[0],strlen(row[0])); + mysql_free_result(result); + return txtout; + } + } +} + +void SharedDatabase::GetFactionListInfo(uint32 &list_count, uint32 &max_lists) { + list_count = 0; + max_lists = 0; + const char *query = "SELECT COUNT(*), MAX(id) FROM npc_faction"; + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + + if(RunQuery(query, strlen(query), errbuf, &result)) { + if(row = mysql_fetch_row(result)) { + list_count = static_cast(atoul(row[0])); + max_lists = static_cast(atoul(row[1])); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error getting npc faction info from database: %s, %s", query, errbuf); + } +} + +const NPCFactionList* SharedDatabase::GetNPCFactionEntry(uint32 id) { + if(!faction_hash) { + return nullptr; + } + + if(faction_hash->exists(id)) { + return &(faction_hash->at(id)); + } + + return nullptr; +} + +void SharedDatabase::LoadNPCFactionLists(void *data, uint32 size, uint32 list_count, uint32 max_lists) { + EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, list_count, max_lists); + const char *query = "SELECT npc_faction.id, npc_faction.primaryfaction, npc_faction.ignore_primary_assist, " + "npc_faction_entries.faction_id, npc_faction_entries.value, npc_faction_entries.npc_value, npc_faction_entries.temp " + "FROM npc_faction LEFT JOIN npc_faction_entries ON npc_faction.id = npc_faction_entries.npc_faction_id ORDER BY " + "npc_faction.id;"; + + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + NPCFactionList faction; + + if(RunQuery(query, strlen(query), errbuf, &result)) { + uint32 current_id = 0; + uint32 current_entry = 0; + while(row = mysql_fetch_row(result)) { + uint32 id = static_cast(atoul(row[0])); + if(id != current_id) { + if(current_id != 0) { + hash.insert(current_id, faction); + } + + memset(&faction, 0, sizeof(faction)); + current_entry = 0; + current_id = id; + faction.id = id; + faction.primaryfaction = static_cast(atoul(row[1])); + faction.assistprimaryfaction = (atoi(row[2]) == 0); + } + + if(!row[3]) { + continue; + } + + if(current_entry >= MAX_NPC_FACTIONS) { + continue; + } + + faction.factionid[current_entry] = static_cast(atoul(row[3])); + faction.factionvalue[current_entry] = static_cast(atoi(row[4])); + faction.factionnpcvalue[current_entry] = static_cast(atoi(row[5])); + faction.factiontemp[current_entry] = static_cast(atoi(row[6])); + ++current_entry; + } + + if(current_id != 0) { + hash.insert(current_id, faction); + } + + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error getting npc faction info from database: %s, %s", query, errbuf); +} +} + +bool SharedDatabase::LoadNPCFactionLists() { + if(faction_hash) { + return true; + } + + try { + EQEmu::IPCMutex mutex("faction"); + mutex.Lock(); + faction_mmf = new EQEmu::MemoryMappedFile("shared/faction"); + + uint32 list_count = 0; + uint32 max_lists = 0; + GetFactionListInfo(list_count, max_lists); + if(list_count == 0) { + EQ_EXCEPT("SharedDatabase", "Database returned no result"); + } + uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size( + list_count, max_lists)); + + if(faction_mmf->Size() != size) { + EQ_EXCEPT("SharedDatabase", "Couldn't load npc factions because faction_mmf->Size() != size"); + } + + faction_hash = new EQEmu::FixedMemoryHashSet(reinterpret_cast(faction_mmf->Get()), size); + mutex.Unlock(); + } catch(std::exception& ex) { + LogFile->write(EQEMuLog::Error, "Error Loading npc factions: %s", ex.what()); + return false; + } + + return true; +} + +// Get the player profile and inventory for the given account "account_id" and +// character name "name". Return true if the character was found, otherwise false. +// False will also be returned if there is a database error. +bool SharedDatabase::GetPlayerProfile(uint32 account_id, char* name, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, char* current_zone, uint32 *current_instance) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES* result; + MYSQL_ROW row; + bool ret = false; + + unsigned long* lengths; + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile,zonename,x,y,z,extprofile,instanceid FROM character_ WHERE account_id=%i AND name='%s'", account_id, name), errbuf, &result)) { + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + lengths = mysql_fetch_lengths(result); + if (lengths[0] == sizeof(PlayerProfile_Struct)) { + memcpy(pp, row[0], sizeof(PlayerProfile_Struct)); + + if (current_zone) + strcpy(current_zone, row[1]); + pp->zone_id = GetZoneID(row[1]); + pp->x = atof(row[2]); + pp->y = atof(row[3]); + pp->z = atof(row[4]); + pp->zoneInstance = atoi(row[6]); + if (pp->x == -1 && pp->y == -1 && pp->z == -1) + GetSafePoints(pp->zone_id, GetInstanceVersion(pp->zoneInstance), &pp->x, &pp->y, &pp->z); + + if(current_instance) + *current_instance = pp->zoneInstance; + + if(ext) { + //SetExtendedProfile handles any conversion + SetExtendedProfile(ext, row[5], lengths[5]); + } + + // Retrieve character inventory + ret = GetInventory(account_id, name, inv); + } + else { + LogFile->write(EQEMuLog::Error, "Player profile length mismatch in GetPlayerProfile. Found: %i, Expected: %i", + lengths[0], sizeof(PlayerProfile_Struct)); + } + } + + mysql_free_result(result); + } + else { + LogFile->write(EQEMuLog::Error, "GetPlayerProfile query '%s' %s", query, errbuf); + } + + safe_delete_array(query); + return ret; +} + +bool SharedDatabase::SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + uint32 affected_rows = 0; + bool ret = false; + + if (RunQuery(query, SetPlayerProfile_MQ(&query, account_id, charid, pp, inv, ext, current_zone, current_instance, MaxXTargets), errbuf, 0, &affected_rows)) { + ret = (affected_rows != 0); + } + + if (!ret) { + LogFile->write(EQEMuLog::Error, "SetPlayerProfile query '%s' %s", query, errbuf); + } + + safe_delete_array(query); + return ret; +} + +// Generate SQL for updating player profile +uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { + *query = new char[396 + sizeof(PlayerProfile_Struct)*2 + sizeof(ExtendedProfile_Struct)*2 + 4]; + char* end = *query; + if (!current_zone) + current_zone = pp->zone_id; + + if (!current_instance) + current_instance = pp->zoneInstance; + + if(strlen(pp->name) == 0) // Sanity check in case pp never loaded + return false; + + end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, profile=\'", pp->name, GetZoneName(current_zone), current_zone, current_instance, pp->x, pp->y, pp->z); + end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct)); + end += sprintf(end,"\', extprofile=\'"); + end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); + end += sprintf(end,"\',class=%d,level=%d,xtargets=%u WHERE id=%u", pp->class_, pp->level, MaxXTargets, charid); + + return (uint32) (end - (*query)); +} + + + +// Create appropriate ItemInst class +ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) +{ + const Item_Struct* item = nullptr; + ItemInst* inst = nullptr; + item = GetItem(item_id); + if (item) { + inst = CreateBaseItem(item, charges); + inst->PutAugment(this, 0, aug1); + inst->PutAugment(this, 1, aug2); + inst->PutAugment(this, 2, aug3); + inst->PutAugment(this, 3, aug4); + inst->PutAugment(this, 4, aug5); + } + + return inst; +} + + +// Create appropriate ItemInst class +ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) +{ + ItemInst* inst = nullptr; + if (item) { + inst = CreateBaseItem(item, charges); + inst->PutAugment(this, 0, aug1); + inst->PutAugment(this, 1, aug2); + inst->PutAugment(this, 2, aug3); + inst->PutAugment(this, 3, aug4); + inst->PutAugment(this, 4, aug5); + } + + return inst; +} + +ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges) { + ItemInst* inst = nullptr; + if (item) { + // if maxcharges is -1 that means it is an unlimited use item. + // set it to 1 charge so that it is usable on creation + if (charges == 0 && item->MaxCharges == -1) + charges = 1; + + inst = new ItemInst(item, charges); + + if(item->CharmFileID != 0 || (item->LoreGroup >= 1000 && item->LoreGroup != -1)) { + inst->Initialize(this); + } + } + return inst; +} + +int32 SharedDatabase::DeleteStalePlayerCorpses() { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + uint32 affected_rows = 0; + + if(RuleB(Zone, EnableShadowrest)) + { + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE player_corpses SET IsBurried = 1 WHERE IsBurried=0 and " + "(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timeofdeath)) > %d and not timeofdeath=0", + (RuleI(Character, CorpseDecayTimeMS) / 1000)), errbuf, 0, &affected_rows)) + { + safe_delete_array(query); + return -1; + } + } + else + { + if (!RunQuery(query, MakeAnyLenString(&query, "Delete from player_corpses where (UNIX_TIMESTAMP() - " + "UNIX_TIMESTAMP(timeofdeath)) > %d and not timeofdeath=0", (RuleI(Character, CorpseDecayTimeMS) / 1000)), + errbuf, 0, &affected_rows)) + { + safe_delete_array(query); + return -1; + } + } + + safe_delete_array(query); + return affected_rows; +} + +int32 SharedDatabase::DeleteStalePlayerBackups() { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + uint32 affected_rows = 0; + + // 1209600 seconds = 2 weeks + if (!RunQuery(query, MakeAnyLenString(&query, "Delete from player_corpses_backup where (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timeofdeath)) > 1209600"), errbuf, 0, &affected_rows)) { + safe_delete_array(query); + return -1; + } + safe_delete_array(query); + + return affected_rows; +} + +bool SharedDatabase::GetCommandSettings(std::map &commands) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + query = new char[256]; + strcpy(query, "SELECT command,access from commands"); + commands.clear(); + if (RunQuery(query, strlen(query), errbuf, &result)) { + safe_delete_array(query); + while((row = mysql_fetch_row(result))) { + commands[row[0]]=atoi(row[1]); + } + mysql_free_result(result); + return true; + } else { + std::cerr << "Error in GetCommands query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return false; + } + + return false; +} + +bool SharedDatabase::LoadSkillCaps() { + if(skill_caps_mmf) + return true; + + uint32 class_count = PLAYER_CLASS_COUNT; + uint32 skill_count = HIGHEST_SKILL + 1; + uint32 level_count = HARD_LEVEL_CAP + 1; + uint32 size = (class_count * skill_count * level_count * sizeof(uint16)); + + try { + EQEmu::IPCMutex mutex("skill_caps"); + mutex.Lock(); + skill_caps_mmf = new EQEmu::MemoryMappedFile("shared/skill_caps"); + if(skill_caps_mmf->Size() != size) { + EQ_EXCEPT("SharedDatabase", "Unable to load skill caps: skill_caps_mmf->Size() != size"); + } + + mutex.Unlock(); + } catch(std::exception &ex) { + LogFile->write(EQEMuLog::Error, "Error loading skill caps: %s", ex.what()); + return false; + } + + return true; +} + +void SharedDatabase::LoadSkillCaps(void *data) { + uint32 class_count = PLAYER_CLASS_COUNT; + uint32 skill_count = HIGHEST_SKILL + 1; + uint32 level_count = HARD_LEVEL_CAP + 1; + uint16 *skill_caps_table = reinterpret_cast(data); + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + if(RunQuery(query, MakeAnyLenString(&query, + "SELECT skillID, class, level, cap FROM skill_caps ORDER BY skillID, class, level"), + errbuf, &result)) { + safe_delete_array(query); + + while((row = mysql_fetch_row(result))) { + uint8 skillID = atoi(row[0]); + uint8 class_ = atoi(row[1]) - 1; + uint8 level = atoi(row[2]); + uint16 cap = atoi(row[3]); + if(skillID >= skill_count || class_ >= class_count || level >= level_count) + continue; + + uint32 index = (((class_ * skill_count) + skillID) * level_count) + level; + skill_caps_table[index] = cap; + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error loading skill caps from database: %s", errbuf); + safe_delete_array(query); + } +} + +uint16 SharedDatabase::GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Level) { + if(!skill_caps_mmf) { + return 0; + } + + if(Class_ == 0) + return 0; + + int SkillMaxLevel = RuleI(Character, SkillCapMaxLevel); + if(SkillMaxLevel < 1) { + SkillMaxLevel = RuleI(Character, MaxLevel); + } + + uint32 class_count = PLAYER_CLASS_COUNT; + uint32 skill_count = HIGHEST_SKILL + 1; + uint32 level_count = HARD_LEVEL_CAP + 1; + if(Class_ > class_count || static_cast(Skill) > skill_count || Level > level_count) { + return 0; + } + + if(Level > static_cast(SkillMaxLevel)){ + Level = static_cast(SkillMaxLevel); + } + + uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count) + Level; + uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); + return skill_caps_table[index]; +} + +uint8 SharedDatabase::GetTrainLevel(uint8 Class_, SkillUseTypes Skill, uint8 Level) { + if(!skill_caps_mmf) { + return 0; + } + + if(Class_ == 0) + return 0; + + int SkillMaxLevel = RuleI(Character, SkillCapMaxLevel); + if (SkillMaxLevel < 1) { + SkillMaxLevel = RuleI(Character, MaxLevel); + } + + uint32 class_count = PLAYER_CLASS_COUNT; + uint32 skill_count = HIGHEST_SKILL + 1; + uint32 level_count = HARD_LEVEL_CAP + 1; + if(Class_ > class_count || static_cast(Skill) > skill_count || Level > level_count) { + return 0; + } + + uint8 ret = 0; + if(Level > static_cast(SkillMaxLevel)) { + uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count); + uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); + for(uint8 x = 0; x < Level; x++){ + if(skill_caps_table[index + x]){ + ret = x; + break; + } + } + } + else + { + uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count); + uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); + for(int x = 0; x < SkillMaxLevel; x++){ + if(skill_caps_table[index + x]){ + ret = x; + break; + } + } + } + + if(ret > GetSkillCap(Class_, Skill, Level)) + ret = static_cast(GetSkillCap(Class_, Skill, Level)); + + return ret; +} + +void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID) { + + const char *DSQuery = "SELECT `spellid`, `type` from `damageshieldtypes` WHERE `spellid` > 0 " + "AND `spellid` <= %i"; + + const char *ERR_MYSQLERROR = "Error in LoadDamageShieldTypes: %s %s"; + + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if(RunQuery(query,MakeAnyLenString(&query,DSQuery,iMaxSpellID),errbuf,&result)) { + + while((row = mysql_fetch_row(result))) { + + int SpellID = atoi(row[0]); + if((SpellID > 0) && (SpellID <= iMaxSpellID)) { + sp[SpellID].DamageShieldType = atoi(row[1]); + } + } + mysql_free_result(result); + safe_delete_array(query); + } + else { + LogFile->write(EQEMuLog::Error, ERR_MYSQLERROR, query, errbuf); + safe_delete_array(query); + } +} + +const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) { + return nullptr; // nothing here for now... database and/or sharemem pulls later +} + +int SharedDatabase::GetMaxSpellID() { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = nullptr; + MYSQL_RES *result; + MYSQL_ROW row; + int32 ret = 0; + if(RunQuery(query, MakeAnyLenString(&query, "SELECT MAX(id) FROM spells_new"), + errbuf, &result)) { + safe_delete_array(query); + row = mysql_fetch_row(result); + ret = atoi(row[0]); + mysql_free_result(result); + } else { + _log(SPELLS__LOAD_ERR, "Error in GetMaxSpellID query '%s' %s", query, errbuf); + safe_delete_array(query); + ret = -1; + } + return ret; +} + +void SharedDatabase::LoadSpells(void *data, int max_spells) { + SPDat_Spell_Struct *sp = reinterpret_cast(data); + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if(RunQuery(query, MakeAnyLenString(&query, + "SELECT * FROM spells_new ORDER BY id ASC"), + errbuf, &result)) { + safe_delete_array(query); + + int tempid = 0; + int counter = 0; + while (row = mysql_fetch_row(result)) { + tempid = atoi(row[0]); + if(tempid >= max_spells) { + _log(SPELLS__LOAD_ERR, "Non fatal error: spell.id >= max_spells, ignoring."); + continue; + } + + ++counter; + sp[tempid].id = tempid; + strn0cpy(sp[tempid].name, row[1], sizeof(sp[tempid].name)); + strn0cpy(sp[tempid].player_1, row[2], sizeof(sp[tempid].player_1)); + strn0cpy(sp[tempid].teleport_zone, row[3], sizeof(sp[tempid].teleport_zone)); + strn0cpy(sp[tempid].you_cast, row[4], sizeof(sp[tempid].you_cast)); + strn0cpy(sp[tempid].other_casts, row[5], sizeof(sp[tempid].other_casts)); + strn0cpy(sp[tempid].cast_on_you, row[6], sizeof(sp[tempid].cast_on_you)); + strn0cpy(sp[tempid].cast_on_other, row[7], sizeof(sp[tempid].cast_on_other)); + strn0cpy(sp[tempid].spell_fades, row[8], sizeof(sp[tempid].spell_fades)); + + sp[tempid].range=static_cast(atof(row[9])); + sp[tempid].aoerange=static_cast(atof(row[10])); + sp[tempid].pushback=static_cast(atof(row[11])); + sp[tempid].pushup=static_cast(atof(row[12])); + sp[tempid].cast_time=atoi(row[13]); + sp[tempid].recovery_time=atoi(row[14]); + sp[tempid].recast_time=atoi(row[15]); + sp[tempid].buffdurationformula=atoi(row[16]); + sp[tempid].buffduration=atoi(row[17]); + sp[tempid].AEDuration=atoi(row[18]); + sp[tempid].mana=atoi(row[19]); + + int y=0; + for(y=0; y< EFFECT_COUNT;y++) + sp[tempid].base[y]=atoi(row[20+y]); // effect_base_value + for(y=0; y < EFFECT_COUNT; y++) + sp[tempid].base2[y]=atoi(row[32+y]); // effect_limit_value + for(y=0; y< EFFECT_COUNT;y++) + sp[tempid].max[y]=atoi(row[44+y]); + + for(y=0; y< 4;y++) + sp[tempid].components[y]=atoi(row[58+y]); + + for(y=0; y< 4;y++) + sp[tempid].component_counts[y]=atoi(row[62+y]); + + for(y=0; y< 4;y++) + sp[tempid].NoexpendReagent[y]=atoi(row[66+y]); + + for(y=0; y< EFFECT_COUNT;y++) + sp[tempid].formula[y]=atoi(row[70+y]); + + sp[tempid].goodEffect=atoi(row[83]); + sp[tempid].Activated=atoi(row[84]); + sp[tempid].resisttype=atoi(row[85]); + + for(y=0; y< EFFECT_COUNT;y++) + sp[tempid].effectid[y]=atoi(row[86+y]); + + sp[tempid].targettype = (SpellTargetType) atoi(row[98]); + sp[tempid].basediff=atoi(row[99]); + int tmp_skill = atoi(row[100]);; + if(tmp_skill < 0 || tmp_skill > HIGHEST_SKILL) + sp[tempid].skill = SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated + else + sp[tempid].skill = (SkillUseTypes) tmp_skill; + sp[tempid].zonetype=atoi(row[101]); + sp[tempid].EnvironmentType=atoi(row[102]); + sp[tempid].TimeOfDay=atoi(row[103]); + + for(y=0; y < PLAYER_CLASS_COUNT;y++) + sp[tempid].classes[y]=atoi(row[104+y]); + + sp[tempid].CastingAnim=atoi(row[120]); + sp[tempid].SpellAffectIndex=atoi(row[123]); + sp[tempid].disallow_sit=atoi(row[124]); + + for (y = 0; y < 16; y++) + sp[tempid].deities[y]=atoi(row[126+y]); + + sp[tempid].uninterruptable=atoi(row[146]); + sp[tempid].ResistDiff=atoi(row[147]); + sp[tempid].dot_stacking_exempt=atoi(row[148]); + sp[tempid].RecourseLink = atoi(row[150]); + sp[tempid].no_partial_resist = atoi(row[151]) != 0; + + sp[tempid].short_buff_box = atoi(row[154]); + sp[tempid].descnum = atoi(row[155]); + sp[tempid].effectdescnum = atoi(row[157]); + + sp[tempid].reflectable = atoi(row[161]) != 0; + sp[tempid].bonushate=atoi(row[162]); + + sp[tempid].EndurCost=atoi(row[166]); + sp[tempid].EndurTimerIndex=atoi(row[167]); + sp[tempid].HateAdded=atoi(row[173]); + sp[tempid].EndurUpkeep=atoi(row[174]); + sp[tempid].numhitstype = atoi(row[175]); + sp[tempid].numhits = atoi(row[176]); + sp[tempid].pvpresistbase=atoi(row[177]); + sp[tempid].pvpresistcalc=atoi(row[178]); + sp[tempid].pvpresistcap=atoi(row[179]); + sp[tempid].spell_category=atoi(row[180]); + sp[tempid].can_mgb=atoi(row[185]); + sp[tempid].dispel_flag = atoi(row[186]); + sp[tempid].MinResist = atoi(row[189]); + sp[tempid].MaxResist = atoi(row[190]); + sp[tempid].viral_targets = atoi(row[191]); + sp[tempid].viral_timer = atoi(row[192]); + sp[tempid].NimbusEffect = atoi(row[193]); + sp[tempid].directional_start = (float)atoi(row[194]); + sp[tempid].directional_end = (float)atoi(row[195]); + sp[tempid].not_extendable = atoi(row[197]) != 0; + sp[tempid].suspendable = atoi(row[200]) != 0; + sp[tempid].spellgroup=atoi(row[207]); + sp[tempid].powerful_flag=atoi(row[209]); + sp[tempid].CastRestriction = atoi(row[211]); + sp[tempid].AllowRest = atoi(row[212]) != 0; + sp[tempid].NotOutofCombat = atoi(row[213]) != 0; + sp[tempid].NotInCombat = atoi(row[214]) != 0; + sp[tempid].aemaxtargets = atoi(row[218]); + sp[tempid].maxtargets = atoi(row[219]); + sp[tempid].persistdeath = atoi(row[224]) != 0; + sp[tempid].DamageShieldType = 0; + } + mysql_free_result(result); + + LoadDamageShieldTypes(sp, max_spells); + } else { + _log(SPELLS__LOAD_ERR, "Error in LoadSpells query '%s' %s", query, errbuf); + safe_delete_array(query); + } +} + +int SharedDatabase::GetMaxBaseDataLevel() { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = "SELECT MAX(level) FROM base_data"; + MYSQL_RES *result; + MYSQL_ROW row; + int32 ret = 0; + if(RunQuery(query, strlen(query), errbuf, &result)) { + row = mysql_fetch_row(result); + if(row) { + ret = atoi(row[0]); + mysql_free_result(result); + } else { + ret = -1; + mysql_free_result(result); + } + } else { + LogFile->write(EQEMuLog::Error, "Error in GetMaxBaseDataLevel query '%s' %s", query, errbuf); + ret = -1; + } + return ret; +} + +bool SharedDatabase::LoadBaseData() { + if(base_data_mmf) { + return true; + } + + try { + EQEmu::IPCMutex mutex("base_data"); + mutex.Lock(); + base_data_mmf = new EQEmu::MemoryMappedFile("shared/base_data"); + + int size = 16 * (GetMaxBaseDataLevel() + 1) * sizeof(BaseDataStruct); + if(size == 0) { + EQ_EXCEPT("SharedDatabase", "Base Data size is zero"); + } + + if(base_data_mmf->Size() != size) { + EQ_EXCEPT("SharedDatabase", "Couldn't load base data because base_data_mmf->Size() != size"); + } + + mutex.Unlock(); + } catch(std::exception& ex) { + LogFile->write(EQEMuLog::Error, "Error Loading Base Data: %s", ex.what()); + return false; + } + + return true; +} + +void SharedDatabase::LoadBaseData(void *data, int max_level) { + char *base_ptr = reinterpret_cast(data); + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = "SELECT * FROM base_data ORDER BY level, class ASC"; + MYSQL_RES *result; + MYSQL_ROW row; + + if(RunQuery(query, strlen(query), errbuf, &result)) { + + int lvl = 0; + int cl = 0; + while (row = mysql_fetch_row(result)) { + lvl = atoi(row[0]); + cl = atoi(row[1]); + if(lvl <= 0) { + LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.level <= 0, ignoring."); + continue; + } + + if(lvl >= max_level) { + LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.level >= max_level, ignoring."); + continue; + } + + if(cl <= 0) { + LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.cl <= 0, ignoring."); + continue; + } + + if(cl > 16) { + LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.class > 16, ignoring."); + continue; + } + + BaseDataStruct *bd = reinterpret_cast(base_ptr + (((16 * (lvl - 1)) + (cl - 1)) * sizeof(BaseDataStruct))); + bd->base_hp = atof(row[2]); + bd->base_mana = atof(row[3]); + bd->base_end = atof(row[4]); + bd->unk1 = atof(row[5]); + bd->unk2 = atof(row[6]); + bd->hp_factor = atof(row[7]); + bd->mana_factor = atof(row[8]); + bd->endurance_factor = atof(row[9]); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in LoadBaseData query '%s' %s", query, errbuf); + safe_delete_array(query); + } +} + +const BaseDataStruct* SharedDatabase::GetBaseData(int lvl, int cl) { + if(!base_data_mmf) { + return nullptr; + } + + if(lvl <= 0) { + return nullptr; + } + + if(cl <= 0) { + return nullptr; + } + + if(cl > 16) { + return nullptr; + } + + char *base_ptr = reinterpret_cast(base_data_mmf->Get()); + + uint32 offset = ((16 * (lvl - 1)) + (cl - 1)) * sizeof(BaseDataStruct); + + if(offset >= base_data_mmf->Size()) { + return nullptr; + } + + BaseDataStruct *bd = reinterpret_cast(base_ptr + offset); + return bd; +} + +void SharedDatabase::GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot_table, uint32 &loot_table_entries) { + loot_table_count = 0; + max_loot_table = 0; + loot_table_entries = 0; + const char *query = "SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM loottable_entries) FROM loottable"; + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + + if(RunQuery(query, strlen(query), errbuf, &result)) { + if(row = mysql_fetch_row(result)) { + loot_table_count = static_cast(atoul(row[0])); + max_loot_table = static_cast(atoul(row[1])); + loot_table_entries = static_cast(atoul(row[2])); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", query, errbuf); + } +} + +void SharedDatabase::GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_drop, uint32 &loot_drop_entries) { + loot_drop_count = 0; + max_loot_drop = 0; + loot_drop_entries = 0; + const char *query = "SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM lootdrop_entries) FROM lootdrop"; + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + + if(RunQuery(query, strlen(query), errbuf, &result)) { + if(row = mysql_fetch_row(result)) { + loot_drop_count = static_cast(atoul(row[0])); + max_loot_drop = static_cast(atoul(row[1])); + loot_drop_entries = static_cast(atoul(row[2])); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", query, errbuf); + } +} + +void SharedDatabase::LoadLootTables(void *data, uint32 size) { + EQEmu::FixedMemoryVariableHashSet hash(reinterpret_cast(data), size); + const char *query = "SELECT loottable.id, loottable.mincash, loottable.maxcash, loottable.avgcoin," + " loottable_entries.lootdrop_id, loottable_entries.multiplier, loottable_entries.droplimit, " + "loottable_entries.mindrop, loottable_entries.probability FROM loottable LEFT JOIN loottable_entries" + " ON loottable.id = loottable_entries.loottable_id ORDER BY id"; + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + uint8 loot_table[sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128)]; + LootTable_Struct *lt = reinterpret_cast(loot_table); + + if(RunQuery(query, strlen(query), errbuf, &result)) { + uint32 current_id = 0; + uint32 current_entry = 0; + while(row = mysql_fetch_row(result)) { + uint32 id = static_cast(atoul(row[0])); + if(id != current_id) { + if(current_id != 0) { + hash.insert(current_id, loot_table, (sizeof(LootTable_Struct) + + (sizeof(LootTableEntries_Struct) * lt->NumEntries))); + } + + memset(loot_table, 0, sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128)); + current_entry = 0; + current_id = id; + lt->mincash = static_cast(atoul(row[1])); + lt->maxcash = static_cast(atoul(row[2])); + lt->avgcoin = static_cast(atoul(row[3])); + } + + if(current_entry > 128) { + continue; + } + + if(!row[4]) { + continue; + } + + lt->Entries[current_entry].lootdrop_id = static_cast(atoul(row[4])); + lt->Entries[current_entry].multiplier = static_cast(atoi(row[5])); + lt->Entries[current_entry].droplimit = static_cast(atoi(row[6])); + lt->Entries[current_entry].mindrop = static_cast(atoi(row[7])); + lt->Entries[current_entry].probability = static_cast(atof(row[8])); + + ++(lt->NumEntries); + ++current_entry; + } + if(current_id != 0) { + hash.insert(current_id, loot_table, (sizeof(LootTable_Struct) + + (sizeof(LootTableEntries_Struct) * lt->NumEntries))); + } + + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", query, errbuf); + } +} + +void SharedDatabase::LoadLootDrops(void *data, uint32 size) { + EQEmu::FixedMemoryVariableHashSet hash(reinterpret_cast(data), size); + const char *query = "SELECT lootdrop.id, lootdrop_entries.item_id, lootdrop_entries.item_charges, " + "lootdrop_entries.equip_item, lootdrop_entries.chance, lootdrop_entries.minlevel, " + "lootdrop_entries.maxlevel, lootdrop_entries.multiplier FROM lootdrop JOIN lootdrop_entries " + "ON lootdrop.id = lootdrop_entries.lootdrop_id ORDER BY lootdrop_id"; + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + + uint8 loot_drop[sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * 1260)]; + LootDrop_Struct *ld = reinterpret_cast(loot_drop); + if(RunQuery(query, strlen(query), errbuf, &result)) { + uint32 current_id = 0; + uint32 current_entry = 0; + while(row = mysql_fetch_row(result)) { + uint32 id = static_cast(atoul(row[0])); + if(id != current_id) { + if(current_id != 0) { + hash.insert(current_id, loot_drop, (sizeof(LootDrop_Struct) + + (sizeof(LootDropEntries_Struct) * ld->NumEntries))); + } + + memset(loot_drop, 0, sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * 1260)); + current_entry = 0; + current_id = id; + } + + if(current_entry >= 1260) { + continue; + } + + ld->Entries[current_entry].item_id = static_cast(atoul(row[1])); + ld->Entries[current_entry].item_charges = static_cast(atoi(row[2])); + ld->Entries[current_entry].equip_item = static_cast(atoi(row[3])); + ld->Entries[current_entry].chance = static_cast(atof(row[4])); + ld->Entries[current_entry].minlevel = static_cast(atoi(row[5])); + ld->Entries[current_entry].maxlevel = static_cast(atoi(row[6])); + ld->Entries[current_entry].multiplier = static_cast(atoi(row[7])); + + ++(ld->NumEntries); + ++current_entry; + } + if(current_id != 0) { + hash.insert(current_id, loot_drop, (sizeof(LootDrop_Struct) + + (sizeof(LootDropEntries_Struct) * ld->NumEntries))); + } + + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error getting loot drop info from database: %s, %s", query, errbuf); + } +} + +bool SharedDatabase::LoadLoot() { + if(loot_table_mmf || loot_drop_mmf) + return true; + + try { + EQEmu::IPCMutex mutex("loot"); + mutex.Lock(); + loot_table_mmf = new EQEmu::MemoryMappedFile("shared/loot_table"); + loot_table_hash = new EQEmu::FixedMemoryVariableHashSet( + reinterpret_cast(loot_table_mmf->Get()), + loot_table_mmf->Size()); + loot_drop_mmf = new EQEmu::MemoryMappedFile("shared/loot_drop"); + loot_drop_hash = new EQEmu::FixedMemoryVariableHashSet( + reinterpret_cast(loot_drop_mmf->Get()), + loot_drop_mmf->Size()); + mutex.Unlock(); + } catch(std::exception &ex) { + LogFile->write(EQEMuLog::Error, "Error loading loot: %s", ex.what()); + return false; + } + + return true; +} + +const LootTable_Struct* SharedDatabase::GetLootTable(uint32 loottable_id) { + if(!loot_table_hash) + return nullptr; + + try { + if(loot_table_hash->exists(loottable_id)) { + return &loot_table_hash->at(loottable_id); + } + } catch(std::exception &ex) { + LogFile->write(EQEMuLog::Error, "Could not get loot table: %s", ex.what()); + } + return nullptr; +} + +const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) { + if(!loot_drop_hash) + return nullptr; + + try { + if(loot_drop_hash->exists(lootdrop_id)) { + return &loot_drop_hash->at(lootdrop_id); + } + } catch(std::exception &ex) { + LogFile->write(EQEMuLog::Error, "Could not get loot drop: %s", ex.what()); + } + return nullptr; +} + +void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) { + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT inspectmessage FROM character_ WHERE name='%s'", playername), errbuf, &result)) { + safe_delete_array(query); + + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + memcpy(message, row[0], sizeof(InspectMessage_Struct)); + } + + mysql_free_result(result); + } + else { + std::cerr << "Error in GetPlayerInspectMessage query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + } +} + +void SharedDatabase::SetPlayerInspectMessage(char* playername, const InspectMessage_Struct* message) { + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET inspectmessage='%s' WHERE name='%s'", message->text, playername), errbuf)) { + std::cerr << "Error in SetPlayerInspectMessage query '" << query << "' " << errbuf << std::endl; + } + + safe_delete_array(query); +} + +void SharedDatabase::GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message) { + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT BotInspectMessage FROM bots WHERE BotID=%i", botid), errbuf, &result)) { + safe_delete_array(query); + + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + memcpy(message, row[0], sizeof(InspectMessage_Struct)); + } + + mysql_free_result(result); + } + else { + std::cerr << "Error in GetBotInspectMessage query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + } +} + +void SharedDatabase::SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message) { + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE bots SET BotInspectMessage='%s' WHERE BotID=%i", message->text, botid), errbuf)) { + std::cerr << "Error in SetBotInspectMessage query '" << query << "' " << errbuf << std::endl; + } + + safe_delete_array(query); +} diff --git a/common/spdat.h b/common/spdat.h index 0e9096f1a..5bb29b8c4 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -529,7 +529,7 @@ typedef enum { #define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades. #define SE_ApplyEffect 374 // implemented #define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount -//#define SE_Fling 376 // *not implemented - used in 2 test spells (12945 | Movement Test Spell 1) +#define SE_Fling 376 // *not implemented - used in 2 test spells (12945 | Movement Test Spell 1) #define SE_CastOnFadeEffectNPC 377 // implemented - Triggers only if fades after natural duration (On live these are usually players spells that effect an NPC). #define SE_SpellEffectResistChance 378 // implemented - Increase chance to resist specific spell effect (base1=value, base2=spell effect id) #define SE_ShadowStepDirectional 379 // implemented - handled by client diff --git a/utils/sql/git/required/2014_02_12_spells_new_update.sql b/utils/sql/git/required/2014_02_12_spells_new_update.sql new file mode 100644 index 000000000..ba552e1ed --- /dev/null +++ b/utils/sql/git/required/2014_02_12_spells_new_update.sql @@ -0,0 +1,13 @@ +ALTER TABLE `spells_new` CHANGE `field161` `not_reflectable` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field151` `no_partial_resist` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field189` `MinResist` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field190` `MaxResist` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field194` `ConeStartAngle` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field195` `ConeStopAngle` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field208` `rank` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field159` `npc_no_los` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field213` `NotOutofCombat` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field214` `NotInCombat` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field168` `IsDiscipline` INT(11) NOT NULL DEFAULT '0'; +ALTER TABLE `spells_new` CHANGE `field211` `CastRestrict` INT(11) NOT NULL DEFAULT '0'; + diff --git a/utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql b/utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql new file mode 100644 index 000000000..12e9963a5 --- /dev/null +++ b/utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql @@ -0,0 +1,3 @@ +ALTER TABLE `npc_types` ADD `no_target_hotkey` tinyint( 1 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `healscale`; + + diff --git a/utils/sql/git/required/2014_06_22_MetabolismAAs.sql b/utils/sql/git/required/2014_06_22_MetabolismAAs.sql new file mode 100644 index 000000000..3a957edb2 --- /dev/null +++ b/utils/sql/git/required/2014_06_22_MetabolismAAs.sql @@ -0,0 +1,6 @@ +-- Innate Metabolism +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('68', '1', '233', '110', '0'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('69', '1', '233', '125', '0'); +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('70', '1', '233', '150', '0'); + + diff --git a/zone/AA_base.cpp b/zone/AA_base.cpp new file mode 100644 index 000000000..8566c09b5 --- /dev/null +++ b/zone/AA_base.cpp @@ -0,0 +1,1990 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +// Test 1 + +#include "../common/debug.h" +#include "AA.h" +#include "mob.h" +#include "client.h" +#include "groups.h" +#include "raids.h" +#include "../common/spdat.h" +#include "object.h" +#include "doors.h" +#include "beacon.h" +#include "corpse.h" +#include "titles.h" +#include "../common/races.h" +#include "../common/classes.h" +#include "../common/eq_packet_structs.h" +#include "../common/packet_dump.h" +#include "../common/StringUtil.h" +#include "../common/logsys.h" +#include "zonedb.h" +#include "StringIDs.h" + +//static data arrays, really not big enough to warrant shared mem. +AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank] +std::mapaas_send; +std::map > aa_effects; //stores the effects from the aa_effects table in memory +std::map AARequiredLevelAndCost; + +/* + + +Schema: + +spell_id is spell to cast, SPELL_UNKNOWN == no spell +nonspell_action is action to preform on activation which is not a spell, 0=none +nonspell_mana is mana that the nonspell action consumes +nonspell_duration is a duration which may be used by the nonspell action +redux_aa is the aa which reduces the reuse timer of the skill +redux_rate is the multiplier of redux_aa, as a percentage of total rate (10 == 10% faster) + +CREATE TABLE aa_actions ( + aaid mediumint unsigned not null, + rank tinyint unsigned not null, + reuse_time mediumint unsigned not null, + spell_id mediumint unsigned not null, + target tinyint unsigned not null, + nonspell_action tinyint unsigned not null, + nonspell_mana mediumint unsigned not null, + nonspell_duration mediumint unsigned not null, + redux_aa mediumint unsigned not null, + redux_rate tinyint not null, + + PRIMARY KEY(aaid, rank) +); + +CREATE TABLE aa_swarmpets ( + spell_id mediumint unsigned not null, + count tinyint unsigned not null, + npc_id int not null, + duration mediumint unsigned not null, + PRIMARY KEY(spell_id) +); +*/ + +/* + +Credits for this function: + -FatherNitwit: Structure and mechanism + -Wiz: Initial set of AAs, original function contents + -Branks: Much updated info and a bunch of higher-numbered AAs + +*/ +int Client::GetAATimerID(aaID activate) +{ + SendAA_Struct* aa2 = zone->FindAA(activate); + + if(!aa2) + { + for(int i = 1;i < MAX_AA_ACTION_RANKS; ++i) + { + int a = activate - i; + + if(a <= 0) + break; + + aa2 = zone->FindAA(a); + + if(aa2 != nullptr) + break; + } + } + + if(aa2) + return aa2->spell_type; + + return 0; +} + +int Client::CalcAAReuseTimer(const AA_DBAction *caa) { + + if(!caa) + return 0; + + int ReuseTime = caa->reuse_time; + + if(ReuseTime > 0) + { + int ReductionPercentage; + + if(caa->redux_aa > 0 && caa->redux_aa < aaHighestID) + { + ReductionPercentage = GetAA(caa->redux_aa) * caa->redux_rate; + + if(caa->redux_aa2 > 0 && caa->redux_aa2 < aaHighestID) + ReductionPercentage += (GetAA(caa->redux_aa2) * caa->redux_rate2); + + ReuseTime = caa->reuse_time * (100 - ReductionPercentage) / 100; + } + + } + return ReuseTime; +} + +void Client::ActivateAA(aaID activate){ + if(activate < 0 || activate >= aaHighestID) + return; + if(IsStunned() || IsFeared() || IsMezzed() || IsSilenced() || IsPet() || IsSitting() || GetFeigned()) + return; + + int AATimerID = GetAATimerID(activate); + + SendAA_Struct* aa2 = nullptr; + aaID aaid = activate; + uint8 activate_val = GetAA(activate); + //this wasn't taking into acct multi tiered act talents before... + if(activate_val == 0){ + aa2 = zone->FindAA(activate); + if(!aa2){ + int i; + int a; + for(i=1;iFindAA(a); + if(aa2 != nullptr) + break; + } + } + if(aa2){ + aaid = (aaID) aa2->id; + activate_val = GetAA(aa2->id); + } + } + + if (activate_val == 0){ + return; + } + + if(aa2) + { + if(aa2->account_time_required) + { + if((Timer::GetTimeSeconds() + account_creation) < aa2->account_time_required) + { + return; + } + } + } + + if(!p_timers.Expired(&database, AATimerID + pTimerAAStart)) + { + uint32 aaremain = p_timers.GetRemainingTime(AATimerID + pTimerAAStart); + uint32 aaremain_hr = aaremain / (60 * 60); + uint32 aaremain_min = (aaremain / 60) % 60; + uint32 aaremain_sec = aaremain % 60; + + if(aa2) { + if (aaremain_hr >= 1) //1 hour or more + Message(13, "You can use the ability %s again in %u hour(s) %u minute(s) %u seconds", + aa2->name, aaremain_hr, aaremain_min, aaremain_sec); + else //less than an hour + Message(13, "You can use the ability %s again in %u minute(s) %u seconds", + aa2->name, aaremain_min, aaremain_sec); + } else { + if (aaremain_hr >= 1) //1 hour or more + Message(13, "You can use this ability again in %u hour(s) %u minute(s) %u seconds", + aaremain_hr, aaremain_min, aaremain_sec); + else //less than an hour + Message(13, "You can use this ability again in %u minute(s) %u seconds", + aaremain_min, aaremain_sec); + } + return; + } + + if(activate_val > MAX_AA_ACTION_RANKS) + activate_val = MAX_AA_ACTION_RANKS; + activate_val--; //to get array index. + + //get our current node, now that the indices are well bounded + const AA_DBAction *caa = &AA_Actions[aaid][activate_val]; + + if((aaid == aaImprovedHarmTouch || aaid == aaLeechTouch) && !p_timers.Expired(&database, pTimerHarmTouch)){ + Message(13,"Ability recovery time not yet met."); + return; + } + + //everything should be configured out now + + uint16 target_id = 0; + + //figure out our target + switch(caa->target) { + case aaTargetUser: + case aaTargetGroup: + target_id = GetID(); + break; + case aaTargetCurrent: + case aaTargetCurrentGroup: + if(GetTarget() == nullptr) { + Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! + p_timers.Clear(&database, AATimerID + pTimerAAStart); + return; + } + target_id = GetTarget()->GetID(); + break; + case aaTargetPet: + if(GetPet() == nullptr) { + Message(0, "A pet is required for this skill."); + return; + } + target_id = GetPetID(); + break; + } + + //handle non-spell action + if(caa->action != aaActionNone) { + if(caa->mana_cost > 0) { + if(GetMana() < caa->mana_cost) { + Message_StringID(13, INSUFFICIENT_MANA); + return; + } + SetMana(GetMana() - caa->mana_cost); + } + if(caa->reuse_time > 0) + { + uint32 timer_base = CalcAAReuseTimer(caa); + if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) + { + p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); + } + p_timers.Start(AATimerID + pTimerAAStart, timer_base); + SendAATimer(AATimerID, 0, 0); + } + HandleAAAction(aaid); + } + + //cast the spell, if we have one + if(caa->spell_id > 0 && caa->spell_id < SPDAT_RECORDS) { + + if(caa->reuse_time > 0) + { + uint32 timer_base = CalcAAReuseTimer(caa); + SendAATimer(AATimerID, 0, 0); + p_timers.Start(AATimerID + pTimerAAStart, timer_base); + if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) + { + p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); + } + // Bards can cast instant cast AAs while they are casting another song + if (spells[caa->spell_id].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { + if(!SpellFinished(caa->spell_id, entity_list.GetMob(target_id), 10, -1, -1, spells[caa->spell_id].ResistDiff, false)) { + //Reset on failed cast + SendAATimer(AATimerID, 0, 0xFFFFFF); + Message_StringID(15,ABILITY_FAILED); + p_timers.Clear(&database, AATimerID + pTimerAAStart); + return; + } + } else { + if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { + //Reset on failed cast + SendAATimer(AATimerID, 0, 0xFFFFFF); + Message_StringID(15,ABILITY_FAILED); + p_timers.Clear(&database, AATimerID + pTimerAAStart); + return; + } + } + } + else + { + if(!CastSpell(caa->spell_id, target_id)) + return; + } + } + // Check if AA is expendable + if (aas_send[activate - activate_val]->special_category == 7) + { + // Add the AA cost to the extended profile to track overall total + m_epp.expended_aa += aas_send[activate]->cost; + SetAA(activate, 0); + + Save(); + SendAA(activate); + SendAATable(); + } +} + +void Client::HandleAAAction(aaID activate) { + if(activate < 0 || activate >= aaHighestID) + return; + + uint8 activate_val = GetAA(activate); + + if (activate_val == 0) + return; + + if(activate_val > MAX_AA_ACTION_RANKS) + activate_val = MAX_AA_ACTION_RANKS; + activate_val--; //to get array index. + + //get our current node, now that the indices are well bounded + const AA_DBAction *caa = &AA_Actions[activate][activate_val]; + + uint16 timer_id = 0; + uint16 timer_duration = caa->duration; + aaTargetType target = aaTargetUser; + + uint16 spell_id = SPELL_UNKNOWN; //gets cast at the end if not still unknown + + switch(caa->action) { + case aaActionAETaunt: + entity_list.AETaunt(this); + break; + + case aaActionMassBuff: + EnableAAEffect(aaEffectMassGroupBuff, 3600); + Message_StringID(MT_Disciplines, MGB_STRING); //The next group buff you cast will hit all targets in range. + break; + + case aaActionFlamingArrows: + //toggle it + if(CheckAAEffect(aaEffectFlamingArrows)) + EnableAAEffect(aaEffectFlamingArrows); + else + DisableAAEffect(aaEffectFlamingArrows); + break; + + case aaActionFrostArrows: + if(CheckAAEffect(aaEffectFrostArrows)) + EnableAAEffect(aaEffectFrostArrows); + else + DisableAAEffect(aaEffectFrostArrows); + break; + + case aaActionRampage: + EnableAAEffect(aaEffectRampage, 10); + break; + + case aaActionSharedHealth: + if(CheckAAEffect(aaEffectSharedHealth)) + EnableAAEffect(aaEffectSharedHealth); + else + DisableAAEffect(aaEffectSharedHealth); + break; + + case aaActionCelestialRegen: { + //special because spell_id depends on a different AA + switch (GetAA(aaCelestialRenewal)) { + case 1: + spell_id = 3250; + break; + case 2: + spell_id = 3251; + break; + default: + spell_id = 2740; + break; + } + target = aaTargetCurrent; + break; + } + + case aaActionDireCharm: { + //special because spell_id depends on class + switch (GetClass()) + { + case DRUID: + spell_id = 2760; //2644? + break; + case NECROMANCER: + spell_id = 2759; //2643? + break; + case ENCHANTER: + spell_id = 2761; //2642? + break; + } + target = aaTargetCurrent; + break; + } + + case aaActionImprovedFamiliar: { + //Spell IDs might be wrong... + if (GetAA(aaAllegiantFamiliar)) + spell_id = 3264; //1994? + else + spell_id = 2758; //2155? + break; + } + + case aaActionActOfValor: + if(GetTarget() != nullptr) { + int curhp = GetTarget()->GetHP(); + target = aaTargetCurrent; + GetTarget()->HealDamage(curhp, this); + Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); + } + break; + + case aaActionSuspendedMinion: + if (GetPet()) { + target = aaTargetPet; + switch (GetAA(aaSuspendedMinion)) { + case 1: + spell_id = 3248; + break; + case 2: + spell_id = 3249; + break; + } + //do we really need to cast a spell? + + Message(0,"You call your pet to your side."); + GetPet()->WipeHateList(); + GetPet()->GMMove(GetX(),GetY(),GetZ()); + if (activate_val > 1) + entity_list.ClearFeignAggro(GetPet()); + } else { + Message(0,"You have no pet to call."); + } + break; + + case aaActionProjectIllusion: + EnableAAEffect(aaEffectProjectIllusion, 3600); + Message(10, "The power of your next illusion spell will flow to your grouped target in your place."); + break; + + + case aaActionEscape: + Escape(); + break; + + // Don't think this code is used any longer for Bestial Alignment as the AA has a spell_id and no nonspell_action. + case aaActionBeastialAlignment: + switch(GetBaseRace()) { + case BARBARIAN: + spell_id = AA_Choose3(activate_val, 4521, 4522, 4523); + break; + case TROLL: + spell_id = AA_Choose3(activate_val, 4524, 4525, 4526); + break; + case OGRE: + spell_id = AA_Choose3(activate_val, 4527, 4527, 4529); + break; + case IKSAR: + spell_id = AA_Choose3(activate_val, 4530, 4531, 4532); + break; + case VAHSHIR: + spell_id = AA_Choose3(activate_val, 4533, 4534, 4535); + break; + } + + case aaActionLeechTouch: + target = aaTargetCurrent; + spell_id = SPELL_HARM_TOUCH2; + EnableAAEffect(aaEffectLeechTouch, 1000); + break; + + case aaActionFadingMemories: + // Do nothing since spell effect works correctly, but mana isn't used. + break; + + default: + LogFile->write(EQEMuLog::Error, "Unknown AA nonspell action type %d", caa->action); + return; + } + + + uint16 target_id = 0; + //figure out our target + switch(target) { + case aaTargetUser: + case aaTargetGroup: + target_id = GetID(); + break; + case aaTargetCurrent: + case aaTargetCurrentGroup: + if(GetTarget() == nullptr) { + Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! + p_timers.Clear(&database, timer_id + pTimerAAEffectStart); + return; + } + target_id = GetTarget()->GetID(); + break; + case aaTargetPet: + if(GetPet() == nullptr) { + Message(0, "A pet is required for this skill."); + return; + } + target_id = GetPetID(); + break; + } + + //cast the spell, if we have one + if(IsValidSpell(spell_id)) { + int aatid = GetAATimerID(activate); + if(!CastSpell(spell_id, target_id , 10, -1, -1, 0, -1, pTimerAAStart + aatid , CalcAAReuseTimer(caa), 1)) { + SendAATimer(aatid, 0, 0xFFFFFF); + Message_StringID(15,ABILITY_FAILED); + p_timers.Clear(&database, pTimerAAStart + aatid); + return; + } + } + + //handle the duration timer if we have one. + if(timer_id > 0 && timer_duration > 0) { + p_timers.Start(pTimerAAEffectStart + timer_id, timer_duration); + } +} + + +//Originally written by Branks +//functionality rewritten by Father Nitwit +void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override) { + + //It might not be a bad idea to put these into the database, eventually.. + + //Dook- swarms and wards + + PetRecord record; + if(!database.GetPetEntry(spells[spell_id].teleport_zone, &record)) + { + LogFile->write(EQEMuLog::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id); + Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone); + return; + } + + AA_SwarmPet pet; + pet.count = 1; + pet.duration = 1; + + for(int x = 0; x < 12; x++) + { + if(spells[spell_id].effectid[x] == SE_TemporaryPets) + { + pet.count = spells[spell_id].base[x]; + pet.duration = spells[spell_id].max[x]; + } + } + + if(IsClient()) + pet.duration += (CastToClient()->GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000); + + pet.npc_id = record.npc_type; + + NPCType *made_npc = nullptr; + + const NPCType *npc_type = database.GetNPCType(pet.npc_id); + if(npc_type == nullptr) { + //log write + LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet spell id: %d", spell_id); + Message(0,"Unable to find pet!"); + return; + } + + if(name_override != nullptr) { + //we have to make a custom NPC type for this name change + made_npc = new NPCType; + memcpy(made_npc, npc_type, sizeof(NPCType)); + strcpy(made_npc->name, name_override); + npc_type = made_npc; + } + + int summon_count = 0; + summon_count = pet.count; + + if(summon_count > MAX_SWARM_PETS) + summon_count = MAX_SWARM_PETS; + + static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, + 10, -10, 10, -10, + 8, -8, 8, -8 }; + static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, + 10, 10, -10, -10, + 8, 8, -8, -8 }; + TempPets(true); + + while(summon_count > 0) { + int pet_duration = pet.duration; + if(duration_override > 0) + pet_duration = duration_override; + + //this is a little messy, but the only way to do it right + //it would be possible to optimize out this copy for the last pet, but oh well + NPCType *npc_dup = nullptr; + if(made_npc != nullptr) { + npc_dup = new NPCType; + memcpy(npc_dup, made_npc, sizeof(NPCType)); + } + + NPC* npca = new NPC( + (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer + 0, + GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], + GetZ(), GetHeading(), FlyMode3); + + if((spell_id == 6882) || (spell_id == 6884)) + npca->SetFollowID(GetID()); + + if(!npca->GetSwarmInfo()){ + AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; + npca->SetSwarmInfo(nSI); + npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); + } + else{ + npca->GetSwarmInfo()->duration->Start(pet_duration*1000); + } + + //removing this prevents the pet from attacking + npca->GetSwarmInfo()->owner_id = GetID(); + + //give the pets somebody to "love" + if(targ != nullptr){ + npca->AddToHateList(targ, 1000, 1000); + npca->GetSwarmInfo()->target = targ->GetID(); + } + + //we allocated a new NPC type object, give the NPC ownership of that memory + if(npc_dup != nullptr) + npca->GiveNPCTypeData(npc_dup); + + entity_list.AddNPC(npca, true, true); + summon_count--; + } + + //the target of these swarm pets will take offense to being cast on... + if(targ != nullptr) + targ->AddToHateList(this, 1, 0); +} + +void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_override, uint32 duration_override, bool followme) { + + AA_SwarmPet pet; + pet.count = 1; + pet.duration = 1; + + pet.npc_id = typesid; + + NPCType *made_npc = nullptr; + + const NPCType *npc_type = database.GetNPCType(typesid); + if(npc_type == nullptr) { + //log write + LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet type id: %d", typesid); + Message(0,"Unable to find pet!"); + return; + } + + if(name_override != nullptr) { + //we have to make a custom NPC type for this name change + made_npc = new NPCType; + memcpy(made_npc, npc_type, sizeof(NPCType)); + strcpy(made_npc->name, name_override); + npc_type = made_npc; + } + + int summon_count = 0; + summon_count = pet.count; + + if(summon_count > MAX_SWARM_PETS) + summon_count = MAX_SWARM_PETS; + + static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, + 10, -10, 10, -10, + 8, -8, 8, -8 }; + static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, + 10, 10, -10, -10, + 8, 8, -8, -8 }; + TempPets(true); + + while(summon_count > 0) { + int pet_duration = pet.duration; + if(duration_override > 0) + pet_duration = duration_override; + + //this is a little messy, but the only way to do it right + //it would be possible to optimize out this copy for the last pet, but oh well + NPCType *npc_dup = nullptr; + if(made_npc != nullptr) { + npc_dup = new NPCType; + memcpy(npc_dup, made_npc, sizeof(NPCType)); + } + + NPC* npca = new NPC( + (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer + 0, + GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], + GetZ(), GetHeading(), FlyMode3); + + if(!npca->GetSwarmInfo()){ + AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; + npca->SetSwarmInfo(nSI); + npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); + } + else{ + npca->GetSwarmInfo()->duration->Start(pet_duration*1000); + } + + //removing this prevents the pet from attacking + npca->GetSwarmInfo()->owner_id = GetID(); + + //give the pets somebody to "love" + if(targ != nullptr){ + npca->AddToHateList(targ, 1000, 1000); + npca->GetSwarmInfo()->target = targ->GetID(); + } + + //we allocated a new NPC type object, give the NPC ownership of that memory + if(npc_dup != nullptr) + npca->GiveNPCTypeData(npc_dup); + + entity_list.AddNPC(npca, true, true); + summon_count--; + } +} + +void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) +{ + Corpse *CorpseToUse = nullptr; + CorpseToUse = entity_list.GetClosestCorpse(this, nullptr); + + if(!CorpseToUse) + return; + + //assuming we have pets in our table; we take the first pet as a base type. + const NPCType *base_type = database.GetNPCType(500); + NPCType *make_npc = new NPCType; + memcpy(make_npc, base_type, sizeof(NPCType)); + + //combat stats + make_npc->AC = ((GetLevel() * 7) + 550); + make_npc->ATK = GetLevel(); + make_npc->max_dmg = (GetLevel() * 4) + 2; + make_npc->min_dmg = 1; + + //base stats + make_npc->cur_hp = (GetLevel() * 55); + make_npc->max_hp = (GetLevel() * 55); + make_npc->STR = 85 + (GetLevel() * 3); + make_npc->STA = 85 + (GetLevel() * 3); + make_npc->DEX = 85 + (GetLevel() * 3); + make_npc->AGI = 85 + (GetLevel() * 3); + make_npc->INT = 85 + (GetLevel() * 3); + make_npc->WIS = 85 + (GetLevel() * 3); + make_npc->CHA = 85 + (GetLevel() * 3); + make_npc->MR = 25; + make_npc->FR = 25; + make_npc->CR = 25; + make_npc->DR = 25; + make_npc->PR = 25; + + //level class and gender + make_npc->level = GetLevel(); + make_npc->class_ = CorpseToUse->class_; + make_npc->race = CorpseToUse->race; + make_npc->gender = CorpseToUse->gender; + make_npc->loottable_id = 0; + //name + char NewName[64]; + sprintf(NewName, "%s`s Animated Corpse", GetCleanName()); + strcpy(make_npc->name, NewName); + + //appearance + make_npc->beard = CorpseToUse->beard; + make_npc->beardcolor = CorpseToUse->beardcolor; + make_npc->eyecolor1 = CorpseToUse->eyecolor1; + make_npc->eyecolor2 = CorpseToUse->eyecolor2; + make_npc->haircolor = CorpseToUse->haircolor; + make_npc->hairstyle = CorpseToUse->hairstyle; + make_npc->helmtexture = CorpseToUse->helmtexture; + make_npc->luclinface = CorpseToUse->luclinface; + make_npc->size = CorpseToUse->size; + make_npc->texture = CorpseToUse->texture; + + //cast stuff.. based off of PEQ's if you want to change + //it you'll have to mod this code, but most likely + //most people will be using PEQ style for the first + //part of their spell list; can't think of any smooth + //way to do this + //some basic combat mods here too since it's convienent + switch(CorpseToUse->class_) + { + case CLERIC: + make_npc->npc_spells_id = 1; + break; + case WIZARD: + make_npc->npc_spells_id = 2; + break; + case NECROMANCER: + make_npc->npc_spells_id = 3; + break; + case MAGICIAN: + make_npc->npc_spells_id = 4; + break; + case ENCHANTER: + make_npc->npc_spells_id = 5; + break; + case SHAMAN: + make_npc->npc_spells_id = 6; + break; + case DRUID: + make_npc->npc_spells_id = 7; + break; + case PALADIN: + //SPECATK_TRIPLE + strcpy(make_npc->special_abilities, "6,1"); + make_npc->cur_hp = make_npc->cur_hp * 150 / 100; + make_npc->max_hp = make_npc->max_hp * 150 / 100; + make_npc->npc_spells_id = 8; + break; + case SHADOWKNIGHT: + strcpy(make_npc->special_abilities, "6,1"); + make_npc->cur_hp = make_npc->cur_hp * 150 / 100; + make_npc->max_hp = make_npc->max_hp * 150 / 100; + make_npc->npc_spells_id = 9; + break; + case RANGER: + strcpy(make_npc->special_abilities, "7,1"); + make_npc->cur_hp = make_npc->cur_hp * 135 / 100; + make_npc->max_hp = make_npc->max_hp * 135 / 100; + make_npc->npc_spells_id = 10; + break; + case BARD: + strcpy(make_npc->special_abilities, "6,1"); + make_npc->cur_hp = make_npc->cur_hp * 110 / 100; + make_npc->max_hp = make_npc->max_hp * 110 / 100; + make_npc->npc_spells_id = 11; + break; + case BEASTLORD: + strcpy(make_npc->special_abilities, "7,1"); + make_npc->cur_hp = make_npc->cur_hp * 110 / 100; + make_npc->max_hp = make_npc->max_hp * 110 / 100; + make_npc->npc_spells_id = 12; + break; + case ROGUE: + strcpy(make_npc->special_abilities, "7,1"); + make_npc->max_dmg = make_npc->max_dmg * 150 /100; + make_npc->cur_hp = make_npc->cur_hp * 110 / 100; + make_npc->max_hp = make_npc->max_hp * 110 / 100; + break; + case MONK: + strcpy(make_npc->special_abilities, "7,1"); + make_npc->max_dmg = make_npc->max_dmg * 150 /100; + make_npc->cur_hp = make_npc->cur_hp * 135 / 100; + make_npc->max_hp = make_npc->max_hp * 135 / 100; + break; + case WARRIOR: + case BERSERKER: + strcpy(make_npc->special_abilities, "7,1"); + make_npc->max_dmg = make_npc->max_dmg * 150 /100; + make_npc->cur_hp = make_npc->cur_hp * 175 / 100; + make_npc->max_hp = make_npc->max_hp * 175 / 100; + break; + default: + make_npc->npc_spells_id = 0; + break; + } + + make_npc->loottable_id = 0; + make_npc->merchanttype = 0; + make_npc->d_meele_texture1 = 0; + make_npc->d_meele_texture2 = 0; + + TempPets(true); + + NPC* npca = new NPC(make_npc, 0, GetX(), GetY(), GetZ(), GetHeading(), FlyMode3); + + if(!npca->GetSwarmInfo()){ + AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; + npca->SetSwarmInfo(nSI); + npca->GetSwarmInfo()->duration = new Timer(duration*1000); + } + else{ + npca->GetSwarmInfo()->duration->Start(duration*1000); + } + + npca->GetSwarmInfo()->owner_id = GetID(); + + //give the pet somebody to "love" + if(target != nullptr){ + npca->AddToHateList(target, 100000); + npca->GetSwarmInfo()->target = target->GetID(); + } + + //gear stuff, need to make sure there's + //no situation where this stuff can be duped + for(int x = 0; x < 21; x++) + { + uint32 sitem = 0; + sitem = CorpseToUse->GetWornItem(x); + if(sitem){ + const Item_Struct * itm = database.GetItem(sitem); + npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 127, true, true); + } + } + + //we allocated a new NPC type object, give the NPC ownership of that memory + if(make_npc != nullptr) + npca->GiveNPCTypeData(make_npc); + + entity_list.AddNPC(npca, true, true); + + //the target of these swarm pets will take offense to being cast on... + if(target != nullptr) + target->AddToHateList(this, 1, 0); +} + +//turn on an AA effect +//duration == 0 means no time limit, used for one-shot deals, etc.. +void Client::EnableAAEffect(aaEffectType type, uint32 duration) { + if(type > 32) + return; //for now, special logic needed. + m_epp.aa_effects |= 1 << (type-1); + + if(duration > 0) { + p_timers.Start(pTimerAAEffectStart + type, duration); + } else { + p_timers.Clear(&database, pTimerAAEffectStart + type); + } +} + +void Client::DisableAAEffect(aaEffectType type) { + if(type > 32) + return; //for now, special logic needed. + uint32 bit = 1 << (type-1); + if(m_epp.aa_effects & bit) { + m_epp.aa_effects ^= bit; + } + p_timers.Clear(&database, pTimerAAEffectStart + type); +} + +/* +By default an AA effect is a one shot deal, unless +a duration timer is set. +*/ +bool Client::CheckAAEffect(aaEffectType type) { + if(type > 32) + return(false); //for now, special logic needed. + if(m_epp.aa_effects & (1 << (type-1))) { //is effect enabled? + //has our timer expired? + if(p_timers.Expired(&database, pTimerAAEffectStart + type)) { + DisableAAEffect(type); + return(false); + } + return(true); + } + return(false); +} + +void Client::SendAAStats() { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); + AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer; + aps->experience = m_pp.expAA; + aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP); + aps->unspent = m_pp.aapoints; + aps->percentage = m_epp.perAA; + QueuePacket(outapp); + safe_delete(outapp); +} + +void Client::BuyAA(AA_Action* action) +{ + mlog(AA__MESSAGE, "Starting to buy AA %d", action->ability); + + //find the AA information from the database + SendAA_Struct* aa2 = zone->FindAA(action->ability); + if(!aa2) { + //hunt for a lower level... + int i; + int a; + for(i=1;iability - i; + if(a <= 0) + break; + mlog(AA__MESSAGE, "Could not find AA %d, trying potential parent %d", action->ability, a); + aa2 = zone->FindAA(a); + if(aa2 != nullptr) + break; + } + } + if(aa2 == nullptr) + return; //invalid ability... + + if(aa2->special_category == 1 || aa2->special_category == 2) + return; // Not purchasable progression style AAs + + if(aa2->special_category == 8 && aa2->cost == 0) + return; // Not purchasable racial AAs(set a cost to make them purchasable) + + uint32 cur_level = GetAA(aa2->id); + if((aa2->id + cur_level) != action->ability) { //got invalid AA + mlog(AA__ERROR, "Unable to find or match AA %d (found %d + lvl %d)", action->ability, aa2->id, cur_level); + return; + } + + if(aa2->account_time_required) + { + if((Timer::GetTimeSeconds() - account_creation) < aa2->account_time_required) + { + return; + } + } + + uint32 real_cost; + std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); + + if(RequiredLevel != AARequiredLevelAndCost.end()) + { + real_cost = RequiredLevel->second.Cost; + } + else + real_cost = aa2->cost + (aa2->cost_inc * cur_level); + + if(m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { + SetAA(aa2->id, cur_level+1); + + mlog(AA__MESSAGE, "Set AA %d to level %d", aa2->id, cur_level+1); + + m_pp.aapoints -= real_cost; + + Save(); + if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u)) + && ((aa2->max_level == (cur_level+1)) && aa2->sof_next_id)){ + SendAA(aa2->id); + SendAA(aa2->sof_next_id); + } + else + SendAA(aa2->id); + + SendAATable(); + + //we are building these messages ourself instead of using the stringID to work around patch discrepencies + //these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2 + if(cur_level<1) + Message(15,"You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1)?"points":"point"); + else + Message(15,"You have improved %s %d at a cost of %d ability %s.", aa2->name, cur_level+1, real_cost, (real_cost>1)?"points":"point"); + + + SendAAStats(); + + CalcBonuses(); + if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) + NotifyNewTitlesAvailable(); + } +} + +void Client::SendAATimer(uint32 ability, uint32 begin, uint32 end) { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); + UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; + uaaout->ability = ability; + uaaout->begin = begin; + uaaout->end = end; + QueuePacket(outapp); + safe_delete(outapp); +} + +//sends all AA timers. +void Client::SendAATimers() { + //we dont use SendAATimer because theres no reason to allocate the EQApplicationPacket every time + EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); + UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; + + PTimerList::iterator c,e; + c = p_timers.begin(); + e = p_timers.end(); + for(; c != e; ++c) { + PersistentTimer *cur = c->second; + if(cur->GetType() < pTimerAAStart || cur->GetType() > pTimerAAEnd) + continue; //not an AA timer + //send timer + uaaout->begin = cur->GetStartTime(); + uaaout->end = static_cast(time(nullptr)); + uaaout->ability = cur->GetType() - pTimerAAStart; // uuaaout->ability is really a shared timer number + QueuePacket(outapp); + } + + safe_delete(outapp); +} + +void Client::SendAATable() { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); + + AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; + aa2->aa_spent = GetAAPointsSpent(); + + uint32 i; + for(i=0;i < MAX_PP_AA_ARRAY;i++){ + aa2->aa_list[i].aa_skill = aa[i]->AA; + aa2->aa_list[i].aa_value = aa[i]->value; + aa2->aa_list[i].unknown08 = 0; + } + QueuePacket(outapp); + safe_delete(outapp); +} + +void Client::SendPreviousAA(uint32 id, int seq){ + uint32 value=0; + SendAA_Struct* saa2 = nullptr; + if(id==0) + saa2 = zone->GetAABySequence(seq); + else + saa2 = zone->FindAA(id); + if(!saa2) + return; + int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; + uchar* buffer = new uchar[size]; + SendAA_Struct* saa=(SendAA_Struct*)buffer; + value = GetAA(saa2->id); + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); + outapp->size=size; + outapp->pBuffer=(uchar*)saa; + value--; + memcpy(saa,saa2,size); + + if(value>0){ + if(saa->spellid==0) + saa->spellid=0xFFFFFFFF; + saa->id+=value; + saa->next_id=saa->id+1; + if(value==1) + saa->last_id=saa2->id; + else + saa->last_id=saa->id-1; + saa->current_level=value+1; + saa->cost2 = 0; //cost 2 is what the client uses to calc how many points we've spent, so we have to add up the points in order + for(uint32 i = 0; i < (value+1); i++) { + saa->cost2 += saa->cost + (saa->cost_inc * i); + } + } + + database.FillAAEffects(saa); + QueuePacket(outapp); + safe_delete(outapp); +} + +void Client::SendAA(uint32 id, int seq) { + + uint32 value=0; + SendAA_Struct* saa2 = nullptr; + SendAA_Struct* qaa = nullptr; + SendAA_Struct* saa_pp = nullptr; + bool IsBaseLevel = true; + bool aa_stack = false; + + if(id==0) + saa2 = zone->GetAABySequence(seq); + else + saa2 = zone->FindAA(id); + if(!saa2) + return; + + uint16 classes = saa2->classes; + if(!(classes & (1 << GetClass())) && (GetClass()!=BERSERKER || saa2->berserker==0)){ + return; + } + + if(saa2->account_time_required) + { + if((Timer::GetTimeSeconds() - account_creation) < saa2->account_time_required) + { + return; + } + } + + // Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). + if (saa2->special_category == 1 || saa2->special_category == 2 ) { + if(GetAA(saa2->id) == 0) + return; + // For Quest line AA(demiplane AEs) where only 1 is visible at a time, check to make sure only the highest level obtained is shown + if(saa2->aa_expansion > 0) { + qaa = zone->FindAA(saa2->id+1); + if(qaa && (saa2->aa_expansion == qaa->aa_expansion) && GetAA(qaa->id) > 0) + return; + } + } + +/* Beginning of Shroud AAs, these categories are for Passive and Active Shroud AAs + Eventually with a toggle we could have it show player list or shroud list + if (saa2->special_category == 3 || saa2->special_category == 4) + return; +*/ + // Check for racial/Drakkin blood line AAs + if (saa2->special_category == 8) + { + uint32 client_race = this->GetBaseRace(); + + // Drakkin Bloodlines + if (saa2->aa_expansion > 522) + { + if (client_race != 522) + return; // Check for Drakkin Race + + int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline + + if (heritage != saa2->aa_expansion) + return; + } + // Racial AAs + else if (client_race != saa2->aa_expansion) + { + return; + } + } + + /* + AA stacking on SoF+ clients. + + Note: There were many ways to achieve this effect - The method used proved to be the most straight forward and consistent. + Stacking does not currently work ideally for AA's that use hotkeys, therefore they will be excluded at this time. + + TODO: Problem with AA hotkeys - When you reach max rank of an AA tier (ie 5/5), it automatically displays the next AA in + the series and you can not transfer the hotkey to the next AA series. To the best of the my ability and through many + different variations of coding I could not find an ideal solution to this issue. + + How stacking works: + Utilizes two new fields: sof_next_id (which is the next id in the series), sof_current_level (ranks the AA's as the current level) + 1) If no AA's purchased only display the base levels of each AA series. + 2) When you purchase an AA and its rank is maxed it sends the packet for the completed AA, and the packet + for the next aa in the series. The previous tier is removed from your window, and the new AA is displayed. + 3) When you zone/buy your player profile will be checked and determine what AA can be displayed base on what you have already. + */ + + if (RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (saa2->hotkey_sid == 4294967295u)) + aa_stack = true; + + if (aa_stack){ + uint32 aa_AA = 0; + uint32 aa_value = 0; + for (int i = 0; i < MAX_PP_AA_ARRAY; i++) { + if (aa[i]) { + aa_AA = aa[i]->AA; + aa_value = aa[i]->value; + + if (aa_AA){ + + if (aa_value > 0) + aa_AA -= aa_value-1; + + saa_pp = zone->FindAA(aa_AA); + + if (saa_pp){ + + if (saa_pp->sof_next_skill == saa2->sof_next_skill){ + + if (saa_pp->id == saa2->id) + break; //You already have this in the player profile. + else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value < saa_pp->max_level)) + return; //DISABLE DISPLAY HIGHER - You have not reached max level yet of your current AA. + else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value == saa_pp->max_level) && (saa_pp->sof_next_id == saa2->id)) + IsBaseLevel = false; //ALLOW DISPLAY HIGHER + } + } + } + } + } + } + + //Hide higher tiers of multi tiered AA's if the base level is not fully purchased. + if (aa_stack && IsBaseLevel && saa2->sof_current_level > 0) + return; + + int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; + + if(size == 0) + return; + + uchar* buffer = new uchar[size]; + SendAA_Struct* saa=(SendAA_Struct*)buffer; + memcpy(saa,saa2,size); + + if(saa->spellid==0) + saa->spellid=0xFFFFFFFF; + + value=GetAA(saa->id); + uint32 orig_val = value; + + if(value && saa->id){ + + if(value < saa->max_level){ + saa->id+=value; + saa->next_id=saa->id+1; + value++; + } + + else if (aa_stack && saa->sof_next_id){ + saa->id+=value-1; + saa->next_id=saa->sof_next_id; + + //Prevent removal of previous AA from window if next AA belongs to a higher client version. + SendAA_Struct* saa_next = nullptr; + saa_next = zone->FindAA(saa->sof_next_id); + if (saa_next && + (((GetClientVersionBit() == 4) && (saa_next->clientver > 4)) + || ((GetClientVersionBit() == 8) && (saa_next->clientver > 5)) + || ((GetClientVersionBit() == 16) && (saa_next->clientver > 6)))){ + saa->next_id=0xFFFFFFFF; + } + } + + else{ + saa->id+=value-1; + saa->next_id=0xFFFFFFFF; + } + + uint32 current_level_mod = 0; + if (aa_stack) + current_level_mod = saa->sof_current_level; + + saa->last_id=saa->id-1; + saa->current_level=value+(current_level_mod); + saa->cost = saa2->cost + (saa2->cost_inc*(value-1)); + saa->cost2 = 0; + for(uint32 i = 0; i < value; i++) { + saa->cost2 += saa2->cost + (saa2->cost_inc * i); + } + saa->class_type = saa2->class_type + (saa2->level_inc*(value-1)); + } + + if (aa_stack){ + + if (saa->sof_current_level >= 1 && value == 0) + saa->current_level = saa->sof_current_level+1; + + saa->max_level = saa->sof_max_level; + } + + database.FillAAEffects(saa); + + if(value > 0) + { + // AA_Action stores the base ID + const AA_DBAction *caa = &AA_Actions[saa->id - value + 1][value - 1]; + + if(caa && caa->reuse_time > 0) + saa->spell_refresh = CalcAAReuseTimer(caa); + } + + //You can now use the level_inc field in the altadv_vars table to accomplish this, though still needed + //for special cases like LOH/HT due to inability to implement correct stacking of AA's that use hotkeys. + std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(saa->id); + + if(RequiredLevel != AARequiredLevelAndCost.end()) + { + saa->class_type = RequiredLevel->second.Level; + saa->cost = RequiredLevel->second.Cost; + } + + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); + outapp->size=size; + outapp->pBuffer=(uchar*)saa; + if(id==0 && value && (orig_val < saa->max_level)) //send previous AA only on zone in + SendPreviousAA(id, seq); + + QueuePacket(outapp); + safe_delete(outapp); + //will outapp delete the buffer for us even though it didnt make it? --- Yes, it should +} + +void Client::SendAAList(){ + int total = zone->GetTotalAAs(); + for(int i=0;i < total;i++){ + SendAA(0,i); + } +} + +uint32 Client::GetAA(uint32 aa_id) const { + std::map::const_iterator res; + res = aa_points.find(aa_id); + if(res != aa_points.end()) { + return(res->second); + } + return(0); +} + +bool Client::SetAA(uint32 aa_id, uint32 new_value) { + aa_points[aa_id] = new_value; + uint32 cur; + for(cur=0;cur < MAX_PP_AA_ARRAY;cur++){ + if((aa[cur]->value > 1) && ((aa[cur]->AA - aa[cur]->value + 1)== aa_id)){ + aa[cur]->value = new_value; + if(new_value > 0) + aa[cur]->AA++; + else + aa[cur]->AA = 0; + return true; + } + else if((aa[cur]->value == 1) && (aa[cur]->AA == aa_id)){ + aa[cur]->value = new_value; + if(new_value > 0) + aa[cur]->AA++; + else + aa[cur]->AA = 0; + return true; + } + else if(aa[cur]->AA==0){ //end of list + aa[cur]->AA = aa_id; + aa[cur]->value = new_value; + return true; + } + } + return false; +} + +SendAA_Struct* Zone::FindAA(uint32 id) { + return aas_send[id]; +} + +void Zone::LoadAAs() { + LogFile->write(EQEMuLog::Status, "Loading AA information..."); + totalAAs = database.CountAAs(); + if(totalAAs == 0) { + LogFile->write(EQEMuLog::Error, "Failed to load AAs!"); + aas = nullptr; + return; + } + aas = new SendAA_Struct *[totalAAs]; + + database.LoadAAs(aas); + + int i; + for(i=0; i < totalAAs; i++){ + SendAA_Struct* aa = aas[i]; + aas_send[aa->id] = aa; + } + + //load AA Effects into aa_effects + LogFile->write(EQEMuLog::Status, "Loading AA Effects..."); + if (database.LoadAAEffects2()) + LogFile->write(EQEMuLog::Status, "Loaded %d AA Effects.", aa_effects.size()); + else + LogFile->write(EQEMuLog::Error, "Failed to load AA Effects!"); +} + +bool ZoneDatabase::LoadAAEffects2() { + aa_effects.clear(); //start fresh + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT aaid, slot, effectid, base1, base2 FROM aa_effects ORDER BY aaid ASC, slot ASC"), errbuf, &result)) { + int count = 0; + while((row = mysql_fetch_row(result))!= nullptr) { + int aaid = atoi(row[0]); + int slot = atoi(row[1]); + int effectid = atoi(row[2]); + int base1 = atoi(row[3]); + int base2 = atoi(row[4]); + aa_effects[aaid][slot].skill_id = effectid; + aa_effects[aaid][slot].base1 = base1; + aa_effects[aaid][slot].base2 = base2; + aa_effects[aaid][slot].slot = slot; //not really needed, but we'll populate it just in case + count++; + } + mysql_free_result(result); + if (count < 1) //no results + LogFile->write(EQEMuLog::Error, "Error loading AA Effects, none found in the database."); + } else { + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAEffects2 query: '%s': %s", query, errbuf); + return false; + } + safe_delete_array(query); + return true; +} +void Client::ResetAA(){ + uint32 i; + for(i=0;iAA = 0; + aa[i]->value = 0; + } + std::map::iterator itr; + for(itr=aa_points.begin();itr!=aa_points.end();++itr) + aa_points[itr->first] = 0; + + for(int i = 0; i < _maxLeaderAA; ++i) + m_pp.leader_abilities.ranks[i] = 0; + + m_pp.group_leadership_points = 0; + m_pp.raid_leadership_points = 0; + m_pp.group_leadership_exp = 0; + m_pp.raid_leadership_exp = 0; +} + +int Client::GroupLeadershipAAHealthEnhancement() +{ + Group *g = GetGroup(); + + if(!g || (g->GroupCount() < 3)) + return 0; + + switch(g->GetLeadershipAA(groupAAHealthEnhancement)) + { + case 0: + return 0; + case 1: + return 30; + case 2: + return 60; + case 3: + return 100; + } + + return 0; +} + +int Client::GroupLeadershipAAManaEnhancement() +{ + Group *g = GetGroup(); + + if(!g || (g->GroupCount() < 3)) + return 0; + + switch(g->GetLeadershipAA(groupAAManaEnhancement)) + { + case 0: + return 0; + case 1: + return 30; + case 2: + return 60; + case 3: + return 100; + } + + return 0; +} + +int Client::GroupLeadershipAAHealthRegeneration() +{ + Group *g = GetGroup(); + + if(!g || (g->GroupCount() < 3)) + return 0; + + switch(g->GetLeadershipAA(groupAAHealthRegeneration)) + { + case 0: + return 0; + case 1: + return 4; + case 2: + return 6; + case 3: + return 8; + } + + return 0; +} + +int Client::GroupLeadershipAAOffenseEnhancement() +{ + Group *g = GetGroup(); + + if(!g || (g->GroupCount() < 3)) + return 0; + + switch(g->GetLeadershipAA(groupAAOffenseEnhancement)) + { + case 0: + return 0; + case 1: + return 10; + case 2: + return 19; + case 3: + return 28; + case 4: + return 34; + case 5: + return 40; + } + return 0; +} + +void Client::InspectBuffs(Client* Inspector, int Rank) +{ + if(!Inspector || (Rank == 0)) return; + + Inspector->Message_StringID(0, CURRENT_SPELL_EFFECTS, GetName()); + uint32 buff_count = GetMaxTotalSlots(); + for (uint32 i = 0; i < buff_count; ++i) + { + if (buffs[i].spellid != SPELL_UNKNOWN) + { + if(Rank == 1) + Inspector->Message(0, "%s", spells[buffs[i].spellid].name); + else + { + if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) + Inspector->Message(0, "%s (Permanent)", spells[buffs[i].spellid].name); + else { + char *TempString = nullptr; + MakeAnyLenString(&TempString, "%.1f", static_cast(buffs[i].ticsremaining) / 10.0f); + Inspector->Message_StringID(0, BUFF_MINUTES_REMAINING, spells[buffs[i].spellid].name, TempString); + safe_delete_array(TempString); + } + } + } + } +} + +//this really need to be renamed to LoadAAActions() +bool ZoneDatabase::LoadAAEffects() { + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + + memset(AA_Actions, 0, sizeof(AA_Actions)); //I hope the compiler is smart about this size... + + const char *query = "SELECT aaid,rank,reuse_time,spell_id,target,nonspell_action,nonspell_mana,nonspell_duration," + "redux_aa,redux_rate,redux_aa2,redux_rate2 FROM aa_actions"; + + if(RunQuery(query, static_cast(strlen(query)), errbuf, &result)) { + //safe_delete_array(query); + int r; + while ((row = mysql_fetch_row(result))) { + r = 0; + int aaid = atoi(row[r++]); + int rank = atoi(row[r++]); + if(aaid < 0 || aaid >= aaHighestID || rank < 0 || rank >= MAX_AA_ACTION_RANKS) + continue; + AA_DBAction *caction = &AA_Actions[aaid][rank]; + + caction->reuse_time = atoi(row[r++]); + caction->spell_id = atoi(row[r++]); + caction->target = (aaTargetType) atoi(row[r++]); + caction->action = (aaNonspellAction) atoi(row[r++]); + caction->mana_cost = atoi(row[r++]); + caction->duration = atoi(row[r++]); + caction->redux_aa = (aaID) atoi(row[r++]); + caction->redux_rate = atoi(row[r++]); + caction->redux_aa2 = (aaID) atoi(row[r++]); + caction->redux_rate2 = atoi(row[r++]); + + } + mysql_free_result(result); + } + else { + LogFile->write(EQEMuLog::Error, "Error in LoadAAEffects query '%s': %s", query, errbuf);; + //safe_delete_array(query); + return false; + } + + return true; +} + +//Returns the number effects an AA has when we send them to the client +//For the purposes of sizing a packet because every skill does not +//have the same number effects, they can range from none to a few depending on AA. +//counts the # of effects by counting the different slots of an AAID in the DB. + +//AndMetal: this may now be obsolete since we have Zone::GetTotalAALevels() +uint8 ZoneDatabase::GetTotalAALevels(uint32 skill_id) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + int total=0; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(slot) from aa_effects where aaid=%i", skill_id), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + total=atoi(row[0]); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in GetTotalAALevels '%s: %s", query, errbuf); + safe_delete_array(query); + } + return total; +} + +//this will allow us to count the number of effects for an AA by pulling the info from memory instead of the database. hopefully this will same some CPU cycles +uint8 Zone::GetTotalAALevels(uint32 skill_id) { + size_t sz = aa_effects[skill_id].size(); + return sz >= 255 ? 255 : static_cast(sz); +} + +/* +Every AA can send the client effects, which are purely for client side effects. +Essentially it's like being able to attach a very simple version of a spell to +Any given AA, it has 4 fields: +skill_id = spell effect id +slot = ID slot, doesn't appear to have any impact on stacking like real spells, just needs to be unique. +base1 = the base field of a spell +base2 = base field 2 of a spell, most AAs do not utilize this +example: + skill_id = SE_STA + slot = 1 + base1 = 15 + This would if you filled the abilities struct with this make the client show if it had + that AA an additional 15 stamina on the client's stats +*/ +void ZoneDatabase::FillAAEffects(SendAA_Struct* aa_struct){ + if(!aa_struct) + return; + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT effectid, base1, base2, slot from aa_effects where aaid=%i order by slot asc", aa_struct->id), errbuf, &result)) { + int ndx=0; + while((row = mysql_fetch_row(result))!=nullptr) { + aa_struct->abilities[ndx].skill_id=atoi(row[0]); + aa_struct->abilities[ndx].base1=atoi(row[1]); + aa_struct->abilities[ndx].base2=atoi(row[2]); + aa_struct->abilities[ndx].slot=atoi(row[3]); + ndx++; + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in Client::FillAAEffects query: '%s': %s", query, errbuf); + } + safe_delete_array(query); +} + +uint32 ZoneDatabase::CountAAs(){ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + int count=0; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(title_sid) from altadv_vars"), errbuf, &result)) { + if((row = mysql_fetch_row(result))!=nullptr) + count = atoi(row[0]); + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAAs query '%s': %s", query, errbuf); + } + safe_delete_array(query); + return count; +} + +uint32 ZoneDatabase::CountAAEffects(){ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + int count=0; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(id) from aa_effects"), errbuf, &result)) { + if((row = mysql_fetch_row(result))!=nullptr){ + count = atoi(row[0]); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAALevels query '%s': %s", query, errbuf); + } + safe_delete_array(query); + return count; +} + +uint32 ZoneDatabase::GetSizeAA(){ + int size=CountAAs()*sizeof(SendAA_Struct); + if(size>0) + size+=CountAAEffects()*sizeof(AA_Ability); + return size; +} + +void ZoneDatabase::LoadAAs(SendAA_Struct **load){ + if(!load) + return; + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id from altadv_vars order by skill_id"), errbuf, &result)) { + int skill=0,ndx=0; + while((row = mysql_fetch_row(result))!=nullptr) { + skill=atoi(row[0]); + load[ndx] = GetAASkillVars(skill); + load[ndx]->seq = ndx+1; + ndx++; + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); + } + safe_delete_array(query); + + AARequiredLevelAndCost.clear(); + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id, level, cost from aa_required_level_cost order by skill_id"), errbuf, &result)) + { + AALevelCost_Struct aalcs; + while((row = mysql_fetch_row(result))!=nullptr) + { + aalcs.Level = atoi(row[1]); + aalcs.Cost = atoi(row[2]); + AARequiredLevelAndCost[atoi(row[0])] = aalcs; + } + mysql_free_result(result); + } + else + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); + + safe_delete_array(query); +} + +SendAA_Struct* ZoneDatabase::GetAASkillVars(uint32 skill_id) +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + SendAA_Struct* sendaa = nullptr; + uchar* buffer; + if (RunQuery(query, MakeAnyLenString(&query, "SET @row = 0"), errbuf)) { //initialize "row" variable in database for next query + safe_delete_array(query); + MYSQL_RES *result; //we don't really need these unless we get to this point, so why bother? + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, + "SELECT " + "a.cost, " + "a.max_level, " + "a.hotkey_sid, " + "a.hotkey_sid2, " + "a.title_sid, " + "a.desc_sid, " + "a.type, " + "COALESCE(" //so we can return 0 if it's null + "(" //this is our derived table that has the row # that we can SELECT from, because the client is stupid + "SELECT " + "p.prereq_index_num " + "FROM " + "(" + "SELECT " + "a2.skill_id, " + "@row := @row + 1 AS prereq_index_num " + "FROM " + "altadv_vars a2" + ") AS p " + "WHERE " + "p.skill_id = a.prereq_skill" + "), " + "0) AS prereq_skill_index, " + "a.prereq_minpoints, " + "a.spell_type, " + "a.spell_refresh, " + "a.classes, " + "a.berserker, " + "a.spellid, " + "a.class_type, " + "a.name, " + "a.cost_inc, " + "a.aa_expansion, " + "a.special_category, " + "a.sof_type, " + "a.sof_cost_inc, " + "a.sof_max_level, " + "a.sof_next_skill, " + "a.clientver, " // Client Version 0 = None, 1 = All, 2 = Titanium/6.2, 4 = SoF 5 = SOD 6 = UF + "a.account_time_required, " + "a.sof_current_level," + "a.sof_next_id, " + "a.level_inc " + " FROM altadv_vars a WHERE skill_id=%i", skill_id), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) { + int total_abilities = GetTotalAALevels(skill_id); //eventually we'll want to use zone->GetTotalAALevels(skill_id) since it should save queries to the DB + int totalsize = total_abilities * sizeof(AA_Ability) + sizeof(SendAA_Struct); + + buffer = new uchar[totalsize]; + memset(buffer,0,totalsize); + sendaa = (SendAA_Struct*)buffer; + + row = mysql_fetch_row(result); + + //ATOI IS NOT UNISGNED LONG-SAFE!!! + + sendaa->cost = atoul(row[0]); + sendaa->cost2 = sendaa->cost; + sendaa->max_level = atoul(row[1]); + sendaa->hotkey_sid = atoul(row[2]); + sendaa->id = skill_id; + sendaa->hotkey_sid2 = atoul(row[3]); + sendaa->title_sid = atoul(row[4]); + sendaa->desc_sid = atoul(row[5]); + sendaa->type = atoul(row[6]); + sendaa->prereq_skill = atoul(row[7]); + sendaa->prereq_minpoints = atoul(row[8]); + sendaa->spell_type = atoul(row[9]); + sendaa->spell_refresh = atoul(row[10]); + sendaa->classes = static_cast(atoul(row[11])); + sendaa->berserker = static_cast(atoul(row[12])); + sendaa->last_id = 0xFFFFFFFF; + sendaa->current_level=1; + sendaa->spellid = atoul(row[13]); + sendaa->class_type = atoul(row[14]); + strcpy(sendaa->name,row[15]); + + sendaa->total_abilities=total_abilities; + if(sendaa->max_level > 1) + sendaa->next_id=skill_id+1; + else + sendaa->next_id=0xFFFFFFFF; + + sendaa->cost_inc = atoi(row[16]); + // Begin SoF Specific/Adjusted AA Fields + sendaa->aa_expansion = atoul(row[17]); + sendaa->special_category = atoul(row[18]); + sendaa->sof_type = atoul(row[19]); + sendaa->sof_cost_inc = atoi(row[20]); + sendaa->sof_max_level = atoul(row[21]); + sendaa->sof_next_skill = atoul(row[22]); + sendaa->clientver = atoul(row[23]); + sendaa->account_time_required = atoul(row[24]); + //Internal use only - not sent to client + sendaa->sof_current_level = atoul(row[25]); + sendaa->sof_next_id = atoul(row[26]); + sendaa->level_inc = static_cast(atoul(row[27])); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); + safe_delete_array(query); + } + } else { + LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); + safe_delete_array(query); + } + return sendaa; +} + +void Client::DurationRampage(uint32 duration) +{ + if(duration) { + m_epp.aa_effects |= 1 << (aaEffectRampage-1); + p_timers.Start(pTimerAAEffectStart + aaEffectRampage, duration); + } +} + +AA_SwarmPetInfo::AA_SwarmPetInfo() +{ + target = 0; + owner_id = 0; + duration = nullptr; +} + +AA_SwarmPetInfo::~AA_SwarmPetInfo() +{ + target = 0; + owner_id = 0; + safe_delete(duration); +} + +Mob *AA_SwarmPetInfo::GetOwner() +{ + return entity_list.GetMobID(owner_id); +} diff --git a/zone/AA_v1.cpp b/zone/AA_v1.cpp new file mode 100644 index 000000000..fb1413927 --- /dev/null +++ b/zone/AA_v1.cpp @@ -0,0 +1,2032 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +// Test 1 + +#include "../common/debug.h" +#include "AA.h" +#include "mob.h" +#include "client.h" +#include "groups.h" +#include "raids.h" +#include "../common/spdat.h" +#include "object.h" +#include "doors.h" +#include "beacon.h" +#include "corpse.h" +#include "titles.h" +#include "../common/races.h" +#include "../common/classes.h" +#include "../common/eq_packet_structs.h" +#include "../common/packet_dump.h" +#include "../common/StringUtil.h" +#include "../common/logsys.h" +#include "zonedb.h" +#include "StringIDs.h" + +//static data arrays, really not big enough to warrant shared mem. +AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank] +std::mapaas_send; +std::map > aa_effects; //stores the effects from the aa_effects table in memory +std::map AARequiredLevelAndCost; + +/* + + +Schema: + +spell_id is spell to cast, SPELL_UNKNOWN == no spell +nonspell_action is action to preform on activation which is not a spell, 0=none +nonspell_mana is mana that the nonspell action consumes +nonspell_duration is a duration which may be used by the nonspell action +redux_aa is the aa which reduces the reuse timer of the skill +redux_rate is the multiplier of redux_aa, as a percentage of total rate (10 == 10% faster) + +CREATE TABLE aa_actions ( + aaid mediumint unsigned not null, + rank tinyint unsigned not null, + reuse_time mediumint unsigned not null, + spell_id mediumint unsigned not null, + target tinyint unsigned not null, + nonspell_action tinyint unsigned not null, + nonspell_mana mediumint unsigned not null, + nonspell_duration mediumint unsigned not null, + redux_aa mediumint unsigned not null, + redux_rate tinyint not null, + + PRIMARY KEY(aaid, rank) +); + +CREATE TABLE aa_swarmpets ( + spell_id mediumint unsigned not null, + count tinyint unsigned not null, + npc_id int not null, + duration mediumint unsigned not null, + PRIMARY KEY(spell_id) +); +*/ + +/* + +Credits for this function: + -FatherNitwit: Structure and mechanism + -Wiz: Initial set of AAs, original function contents + -Branks: Much updated info and a bunch of higher-numbered AAs + +*/ +int Client::GetAATimerID(aaID activate) +{ + SendAA_Struct* aa2 = zone->FindAA(activate); + + if(!aa2) + { + for(int i = 1;i < MAX_AA_ACTION_RANKS; ++i) + { + int a = activate - i; + + if(a <= 0) + break; + + aa2 = zone->FindAA(a); + + if(aa2 != nullptr) + break; + } + } + + if(aa2) + return aa2->spell_type; + + return 0; +} + +int Client::CalcAAReuseTimer(const AA_DBAction *caa) { + + if(!caa) + return 0; + + int ReuseTime = caa->reuse_time; + + if(ReuseTime > 0) + { + int ReductionPercentage; + + if(caa->redux_aa > 0 && caa->redux_aa < aaHighestID) + { + ReductionPercentage = GetAA(caa->redux_aa) * caa->redux_rate; + + if(caa->redux_aa2 > 0 && caa->redux_aa2 < aaHighestID) + ReductionPercentage += (GetAA(caa->redux_aa2) * caa->redux_rate2); + + ReuseTime = caa->reuse_time * (100 - ReductionPercentage) / 100; + } + + } + return ReuseTime; +} + +void Client::ActivateAA(aaID activate){ + if(activate < 0 || activate >= aaHighestID) + return; + if(IsStunned() || IsFeared() || IsMezzed() || IsSilenced() || IsPet() || IsSitting() || GetFeigned()) + return; + + int AATimerID = GetAATimerID(activate); + + SendAA_Struct* aa2 = nullptr; + aaID aaid = activate; + uint8 activate_val = GetAA(activate); + //this wasn't taking into acct multi tiered act talents before... + if(activate_val == 0){ + aa2 = zone->FindAA(activate); + if(!aa2){ + int i; + int a; + for(i=1;iFindAA(a); + if(aa2 != nullptr) + break; + } + } + if(aa2){ + aaid = (aaID) aa2->id; + activate_val = GetAA(aa2->id); + } + } + + if (activate_val == 0){ + return; + } + + if(aa2) + { + if(aa2->account_time_required) + { + if((Timer::GetTimeSeconds() + account_creation) < aa2->account_time_required) + { + return; + } + } + } + + if(!p_timers.Expired(&database, AATimerID + pTimerAAStart)) + { + uint32 aaremain = p_timers.GetRemainingTime(AATimerID + pTimerAAStart); + uint32 aaremain_hr = aaremain / (60 * 60); + uint32 aaremain_min = (aaremain / 60) % 60; + uint32 aaremain_sec = aaremain % 60; + + if(aa2) { + if (aaremain_hr >= 1) //1 hour or more + Message(13, "You can use the ability %s again in %u hour(s) %u minute(s) %u seconds", + aa2->name, aaremain_hr, aaremain_min, aaremain_sec); + else //less than an hour + Message(13, "You can use the ability %s again in %u minute(s) %u seconds", + aa2->name, aaremain_min, aaremain_sec); + } else { + if (aaremain_hr >= 1) //1 hour or more + Message(13, "You can use this ability again in %u hour(s) %u minute(s) %u seconds", + aaremain_hr, aaremain_min, aaremain_sec); + else //less than an hour + Message(13, "You can use this ability again in %u minute(s) %u seconds", + aaremain_min, aaremain_sec); + } + return; + } + + if(activate_val > MAX_AA_ACTION_RANKS) + activate_val = MAX_AA_ACTION_RANKS; + activate_val--; //to get array index. + + //get our current node, now that the indices are well bounded + const AA_DBAction *caa = &AA_Actions[aaid][activate_val]; + + if((aaid == aaImprovedHarmTouch || aaid == aaLeechTouch) && !p_timers.Expired(&database, pTimerHarmTouch)){ + Message(13,"Ability recovery time not yet met."); + return; + } + Shout("spell id %i", caa->spell_id); + //everything should be configured out now + + uint16 target_id = 0; + + //figure out our target + switch(caa->target) { + case aaTargetUser: + case aaTargetGroup: + target_id = GetID(); + break; + case aaTargetCurrent: + case aaTargetCurrentGroup: + if(GetTarget() == nullptr) { + Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! + p_timers.Clear(&database, AATimerID + pTimerAAStart); + return; + } + target_id = GetTarget()->GetID(); + break; + case aaTargetPet: + if(GetPet() == nullptr) { + Message(0, "A pet is required for this skill."); + return; + } + target_id = GetPetID(); + break; + } + + //handle non-spell action + if(caa->action != aaActionNone) { + if(caa->mana_cost > 0) { + if(GetMana() < caa->mana_cost) { + Message_StringID(13, INSUFFICIENT_MANA); + return; + } + SetMana(GetMana() - caa->mana_cost); + } + if(caa->reuse_time > 0) + { + uint32 timer_base = CalcAAReuseTimer(caa); + if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) + { + p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); + } + p_timers.Start(AATimerID + pTimerAAStart, timer_base); + SendAATimer(AATimerID, 0, 0); + } + HandleAAAction(aaid); + } + Shout("1 spell id %i", caa->spell_id); + //cast the spell, if we have one + if(caa->spell_id > 0 && caa->spell_id < SPDAT_RECORDS) { + Shout("2 spell id %i", caa->spell_id); + if(caa->reuse_time > 0) + { + uint32 timer_base = CalcAAReuseTimer(caa); + SendAATimer(AATimerID, 0, 0); + p_timers.Start(AATimerID + pTimerAAStart, timer_base); + if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) + { + p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); + } + // Bards can cast instant cast AAs while they are casting another song + if (spells[caa->spell_id].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { + if(!SpellFinished(caa->spell_id, entity_list.GetMob(target_id), 10, -1, -1, spells[caa->spell_id].ResistDiff, false)) { + //Reset on failed cast + SendAATimer(AATimerID, 0, 0xFFFFFF); + Message_StringID(15,ABILITY_FAILED); + p_timers.Clear(&database, AATimerID + pTimerAAStart); + return; + } + } else { + if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { + //Reset on failed cast + SendAATimer(AATimerID, 0, 0xFFFFFF); + Message_StringID(15,ABILITY_FAILED); + p_timers.Clear(&database, AATimerID + pTimerAAStart); + return; + } + } + } + else + { + if(!CastSpell(caa->spell_id, target_id)) + return; + } + } + // Check if AA is expendable + if (aas_send[activate - activate_val]->special_category == 7) + { + // Add the AA cost to the extended profile to track overall total + m_epp.expended_aa += aas_send[activate]->cost; + SetAA(activate, 0); + + Save(); + SendAA(activate); + SendAATable(); + } +} + +void Client::HandleAAAction(aaID activate) { + if(activate < 0 || activate >= aaHighestID) + return; + + uint8 activate_val = GetAA(activate); + + if (activate_val == 0) + return; + + if(activate_val > MAX_AA_ACTION_RANKS) + activate_val = MAX_AA_ACTION_RANKS; + activate_val--; //to get array index. + + //get our current node, now that the indices are well bounded + const AA_DBAction *caa = &AA_Actions[activate][activate_val]; + + uint16 timer_id = 0; + uint16 timer_duration = caa->duration; + aaTargetType target = aaTargetUser; + + uint16 spell_id = SPELL_UNKNOWN; //gets cast at the end if not still unknown + + switch(caa->action) { + case aaActionAETaunt: + entity_list.AETaunt(this); + break; + + case aaActionMassBuff: + EnableAAEffect(aaEffectMassGroupBuff, 3600); + Message_StringID(MT_Disciplines, MGB_STRING); //The next group buff you cast will hit all targets in range. + break; + + case aaActionFlamingArrows: + //toggle it + if(CheckAAEffect(aaEffectFlamingArrows)) + EnableAAEffect(aaEffectFlamingArrows); + else + DisableAAEffect(aaEffectFlamingArrows); + break; + + case aaActionFrostArrows: + if(CheckAAEffect(aaEffectFrostArrows)) + EnableAAEffect(aaEffectFrostArrows); + else + DisableAAEffect(aaEffectFrostArrows); + break; + + case aaActionRampage: + EnableAAEffect(aaEffectRampage, 10); + break; + + case aaActionSharedHealth: + if(CheckAAEffect(aaEffectSharedHealth)) + EnableAAEffect(aaEffectSharedHealth); + else + DisableAAEffect(aaEffectSharedHealth); + break; + + case aaActionCelestialRegen: { + //special because spell_id depends on a different AA + switch (GetAA(aaCelestialRenewal)) { + case 1: + spell_id = 3250; + break; + case 2: + spell_id = 3251; + break; + default: + spell_id = 2740; + break; + } + target = aaTargetCurrent; + break; + } + + case aaActionDireCharm: { + //special because spell_id depends on class + switch (GetClass()) + { + case DRUID: + spell_id = 2760; //2644? + break; + case NECROMANCER: + spell_id = 2759; //2643? + break; + case ENCHANTER: + spell_id = 2761; //2642? + break; + } + target = aaTargetCurrent; + break; + } + + case aaActionImprovedFamiliar: { + //Spell IDs might be wrong... + if (GetAA(aaAllegiantFamiliar)) + spell_id = 3264; //1994? + else + spell_id = 2758; //2155? + break; + } + + case aaActionActOfValor: + if(GetTarget() != nullptr) { + int curhp = GetTarget()->GetHP(); + target = aaTargetCurrent; + GetTarget()->HealDamage(curhp, this); + Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); + } + break; + + case aaActionSuspendedMinion: + if (GetPet()) { + target = aaTargetPet; + switch (GetAA(aaSuspendedMinion)) { + case 1: + spell_id = 3248; + break; + case 2: + spell_id = 3249; + break; + } + //do we really need to cast a spell? + + Message(0,"You call your pet to your side."); + GetPet()->WipeHateList(); + GetPet()->GMMove(GetX(),GetY(),GetZ()); + if (activate_val > 1) + entity_list.ClearFeignAggro(GetPet()); + } else { + Message(0,"You have no pet to call."); + } + break; + + case aaActionProjectIllusion: + EnableAAEffect(aaEffectProjectIllusion, 3600); + Message(10, "The power of your next illusion spell will flow to your grouped target in your place."); + break; + + + case aaActionEscape: + Escape(); + break; + + // Don't think this code is used any longer for Bestial Alignment as the AA has a spell_id and no nonspell_action. + case aaActionBeastialAlignment: + switch(GetBaseRace()) { + case BARBARIAN: + spell_id = AA_Choose3(activate_val, 4521, 4522, 4523); + break; + case TROLL: + spell_id = AA_Choose3(activate_val, 4524, 4525, 4526); + break; + case OGRE: + spell_id = AA_Choose3(activate_val, 4527, 4527, 4529); + break; + case IKSAR: + spell_id = AA_Choose3(activate_val, 4530, 4531, 4532); + break; + case VAHSHIR: + spell_id = AA_Choose3(activate_val, 4533, 4534, 4535); + break; + } + + case aaActionLeechTouch: + target = aaTargetCurrent; + spell_id = SPELL_HARM_TOUCH2; + EnableAAEffect(aaEffectLeechTouch, 1000); + break; + + case aaActionFadingMemories: + // Do nothing since spell effect works correctly, but mana isn't used. + break; + + default: + LogFile->write(EQEMuLog::Error, "Unknown AA nonspell action type %d", caa->action); + return; + } + + + uint16 target_id = 0; + //figure out our target + switch(target) { + case aaTargetUser: + case aaTargetGroup: + target_id = GetID(); + break; + case aaTargetCurrent: + case aaTargetCurrentGroup: + if(GetTarget() == nullptr) { + Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! + p_timers.Clear(&database, timer_id + pTimerAAEffectStart); + return; + } + target_id = GetTarget()->GetID(); + break; + case aaTargetPet: + if(GetPet() == nullptr) { + Message(0, "A pet is required for this skill."); + return; + } + target_id = GetPetID(); + break; + } + + //cast the spell, if we have one + if(IsValidSpell(spell_id)) { + int aatid = GetAATimerID(activate); + if(!CastSpell(spell_id, target_id , 10, -1, -1, 0, -1, pTimerAAStart + aatid , CalcAAReuseTimer(caa), 1)) { + SendAATimer(aatid, 0, 0xFFFFFF); + Message_StringID(15,ABILITY_FAILED); + p_timers.Clear(&database, pTimerAAStart + aatid); + return; + } + } + + //handle the duration timer if we have one. + if(timer_id > 0 && timer_duration > 0) { + p_timers.Start(pTimerAAEffectStart + timer_id, timer_duration); + } +} + + +//Originally written by Branks +//functionality rewritten by Father Nitwit +void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override) { + + //It might not be a bad idea to put these into the database, eventually.. + + //Dook- swarms and wards + + PetRecord record; + if(!database.GetPetEntry(spells[spell_id].teleport_zone, &record)) + { + LogFile->write(EQEMuLog::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id); + Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone); + return; + } + + AA_SwarmPet pet; + pet.count = 1; + pet.duration = 1; + + for(int x = 0; x < 12; x++) + { + if(spells[spell_id].effectid[x] == SE_TemporaryPets) + { + pet.count = spells[spell_id].base[x]; + pet.duration = spells[spell_id].max[x]; + } + } + + if(IsClient()) + pet.duration += (CastToClient()->GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000); + + pet.npc_id = record.npc_type; + + NPCType *made_npc = nullptr; + + const NPCType *npc_type = database.GetNPCType(pet.npc_id); + if(npc_type == nullptr) { + //log write + LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet spell id: %d", spell_id); + Message(0,"Unable to find pet!"); + return; + } + + if(name_override != nullptr) { + //we have to make a custom NPC type for this name change + made_npc = new NPCType; + memcpy(made_npc, npc_type, sizeof(NPCType)); + strcpy(made_npc->name, name_override); + npc_type = made_npc; + } + + int summon_count = 0; + summon_count = pet.count; + + if(summon_count > MAX_SWARM_PETS) + summon_count = MAX_SWARM_PETS; + + static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, + 10, -10, 10, -10, + 8, -8, 8, -8 }; + static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, + 10, 10, -10, -10, + 8, 8, -8, -8 }; + TempPets(true); + + while(summon_count > 0) { + int pet_duration = pet.duration; + if(duration_override > 0) + pet_duration = duration_override; + + //this is a little messy, but the only way to do it right + //it would be possible to optimize out this copy for the last pet, but oh well + NPCType *npc_dup = nullptr; + if(made_npc != nullptr) { + npc_dup = new NPCType; + memcpy(npc_dup, made_npc, sizeof(NPCType)); + } + + NPC* npca = new NPC( + (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer + 0, + GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], + GetZ(), GetHeading(), FlyMode3); + + if((spell_id == 6882) || (spell_id == 6884)) + npca->SetFollowID(GetID()); + + if(!npca->GetSwarmInfo()){ + AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; + npca->SetSwarmInfo(nSI); + npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); + } + else{ + npca->GetSwarmInfo()->duration->Start(pet_duration*1000); + } + + //removing this prevents the pet from attacking + npca->GetSwarmInfo()->owner_id = GetID(); + + //give the pets somebody to "love" + if(targ != nullptr){ + npca->AddToHateList(targ, 1000, 1000); + npca->GetSwarmInfo()->target = targ->GetID(); + } + + //we allocated a new NPC type object, give the NPC ownership of that memory + if(npc_dup != nullptr) + npca->GiveNPCTypeData(npc_dup); + + entity_list.AddNPC(npca, true, true); + summon_count--; + } + + //the target of these swarm pets will take offense to being cast on... + if(targ != nullptr) + targ->AddToHateList(this, 1, 0); +} + +void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_override, uint32 duration_override, bool followme) { + + AA_SwarmPet pet; + pet.count = 1; + pet.duration = 1; + + pet.npc_id = typesid; + + NPCType *made_npc = nullptr; + + const NPCType *npc_type = database.GetNPCType(typesid); + if(npc_type == nullptr) { + //log write + LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet type id: %d", typesid); + Message(0,"Unable to find pet!"); + return; + } + + if(name_override != nullptr) { + //we have to make a custom NPC type for this name change + made_npc = new NPCType; + memcpy(made_npc, npc_type, sizeof(NPCType)); + strcpy(made_npc->name, name_override); + npc_type = made_npc; + } + + int summon_count = 0; + summon_count = pet.count; + + if(summon_count > MAX_SWARM_PETS) + summon_count = MAX_SWARM_PETS; + + static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, + 10, -10, 10, -10, + 8, -8, 8, -8 }; + static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, + 10, 10, -10, -10, + 8, 8, -8, -8 }; + TempPets(true); + + while(summon_count > 0) { + int pet_duration = pet.duration; + if(duration_override > 0) + pet_duration = duration_override; + + //this is a little messy, but the only way to do it right + //it would be possible to optimize out this copy for the last pet, but oh well + NPCType *npc_dup = nullptr; + if(made_npc != nullptr) { + npc_dup = new NPCType; + memcpy(npc_dup, made_npc, sizeof(NPCType)); + } + + NPC* npca = new NPC( + (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer + 0, + GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], + GetZ(), GetHeading(), FlyMode3); + + if(!npca->GetSwarmInfo()){ + AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; + npca->SetSwarmInfo(nSI); + npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); + } + else{ + npca->GetSwarmInfo()->duration->Start(pet_duration*1000); + } + + //removing this prevents the pet from attacking + npca->GetSwarmInfo()->owner_id = GetID(); + + //give the pets somebody to "love" + if(targ != nullptr){ + npca->AddToHateList(targ, 1000, 1000); + npca->GetSwarmInfo()->target = targ->GetID(); + } + + //we allocated a new NPC type object, give the NPC ownership of that memory + if(npc_dup != nullptr) + npca->GiveNPCTypeData(npc_dup); + + entity_list.AddNPC(npca, true, true); + summon_count--; + } +} + +void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) +{ + Corpse *CorpseToUse = nullptr; + CorpseToUse = entity_list.GetClosestCorpse(this, nullptr); + + if(!CorpseToUse) + return; + + //assuming we have pets in our table; we take the first pet as a base type. + const NPCType *base_type = database.GetNPCType(500); + NPCType *make_npc = new NPCType; + memcpy(make_npc, base_type, sizeof(NPCType)); + + //combat stats + make_npc->AC = ((GetLevel() * 7) + 550); + make_npc->ATK = GetLevel(); + make_npc->max_dmg = (GetLevel() * 4) + 2; + make_npc->min_dmg = 1; + + //base stats + make_npc->cur_hp = (GetLevel() * 55); + make_npc->max_hp = (GetLevel() * 55); + make_npc->STR = 85 + (GetLevel() * 3); + make_npc->STA = 85 + (GetLevel() * 3); + make_npc->DEX = 85 + (GetLevel() * 3); + make_npc->AGI = 85 + (GetLevel() * 3); + make_npc->INT = 85 + (GetLevel() * 3); + make_npc->WIS = 85 + (GetLevel() * 3); + make_npc->CHA = 85 + (GetLevel() * 3); + make_npc->MR = 25; + make_npc->FR = 25; + make_npc->CR = 25; + make_npc->DR = 25; + make_npc->PR = 25; + + //level class and gender + make_npc->level = GetLevel(); + make_npc->class_ = CorpseToUse->class_; + make_npc->race = CorpseToUse->race; + make_npc->gender = CorpseToUse->gender; + make_npc->loottable_id = 0; + //name + char NewName[64]; + sprintf(NewName, "%s`s Animated Corpse", GetCleanName()); + strcpy(make_npc->name, NewName); + + //appearance + make_npc->beard = CorpseToUse->beard; + make_npc->beardcolor = CorpseToUse->beardcolor; + make_npc->eyecolor1 = CorpseToUse->eyecolor1; + make_npc->eyecolor2 = CorpseToUse->eyecolor2; + make_npc->haircolor = CorpseToUse->haircolor; + make_npc->hairstyle = CorpseToUse->hairstyle; + make_npc->helmtexture = CorpseToUse->helmtexture; + make_npc->luclinface = CorpseToUse->luclinface; + make_npc->size = CorpseToUse->size; + make_npc->texture = CorpseToUse->texture; + + //cast stuff.. based off of PEQ's if you want to change + //it you'll have to mod this code, but most likely + //most people will be using PEQ style for the first + //part of their spell list; can't think of any smooth + //way to do this + //some basic combat mods here too since it's convienent + switch(CorpseToUse->class_) + { + case CLERIC: + make_npc->npc_spells_id = 1; + break; + case WIZARD: + make_npc->npc_spells_id = 2; + break; + case NECROMANCER: + make_npc->npc_spells_id = 3; + break; + case MAGICIAN: + make_npc->npc_spells_id = 4; + break; + case ENCHANTER: + make_npc->npc_spells_id = 5; + break; + case SHAMAN: + make_npc->npc_spells_id = 6; + break; + case DRUID: + make_npc->npc_spells_id = 7; + break; + case PALADIN: + //SPECATK_TRIPLE + strcpy(make_npc->special_abilities, "6,1"); + make_npc->cur_hp = make_npc->cur_hp * 150 / 100; + make_npc->max_hp = make_npc->max_hp * 150 / 100; + make_npc->npc_spells_id = 8; + break; + case SHADOWKNIGHT: + strcpy(make_npc->special_abilities, "6,1"); + make_npc->cur_hp = make_npc->cur_hp * 150 / 100; + make_npc->max_hp = make_npc->max_hp * 150 / 100; + make_npc->npc_spells_id = 9; + break; + case RANGER: + strcpy(make_npc->special_abilities, "7,1"); + make_npc->cur_hp = make_npc->cur_hp * 135 / 100; + make_npc->max_hp = make_npc->max_hp * 135 / 100; + make_npc->npc_spells_id = 10; + break; + case BARD: + strcpy(make_npc->special_abilities, "6,1"); + make_npc->cur_hp = make_npc->cur_hp * 110 / 100; + make_npc->max_hp = make_npc->max_hp * 110 / 100; + make_npc->npc_spells_id = 11; + break; + case BEASTLORD: + strcpy(make_npc->special_abilities, "7,1"); + make_npc->cur_hp = make_npc->cur_hp * 110 / 100; + make_npc->max_hp = make_npc->max_hp * 110 / 100; + make_npc->npc_spells_id = 12; + break; + case ROGUE: + strcpy(make_npc->special_abilities, "7,1"); + make_npc->max_dmg = make_npc->max_dmg * 150 /100; + make_npc->cur_hp = make_npc->cur_hp * 110 / 100; + make_npc->max_hp = make_npc->max_hp * 110 / 100; + break; + case MONK: + strcpy(make_npc->special_abilities, "7,1"); + make_npc->max_dmg = make_npc->max_dmg * 150 /100; + make_npc->cur_hp = make_npc->cur_hp * 135 / 100; + make_npc->max_hp = make_npc->max_hp * 135 / 100; + break; + case WARRIOR: + case BERSERKER: + strcpy(make_npc->special_abilities, "7,1"); + make_npc->max_dmg = make_npc->max_dmg * 150 /100; + make_npc->cur_hp = make_npc->cur_hp * 175 / 100; + make_npc->max_hp = make_npc->max_hp * 175 / 100; + break; + default: + make_npc->npc_spells_id = 0; + break; + } + + make_npc->loottable_id = 0; + make_npc->merchanttype = 0; + make_npc->d_meele_texture1 = 0; + make_npc->d_meele_texture2 = 0; + + TempPets(true); + + NPC* npca = new NPC(make_npc, 0, GetX(), GetY(), GetZ(), GetHeading(), FlyMode3); + + if(!npca->GetSwarmInfo()){ + AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; + npca->SetSwarmInfo(nSI); + npca->GetSwarmInfo()->duration = new Timer(duration*1000); + } + else{ + npca->GetSwarmInfo()->duration->Start(duration*1000); + } + + npca->GetSwarmInfo()->owner_id = GetID(); + + //give the pet somebody to "love" + if(target != nullptr){ + npca->AddToHateList(target, 100000); + npca->GetSwarmInfo()->target = target->GetID(); + } + + //gear stuff, need to make sure there's + //no situation where this stuff can be duped + for(int x = 0; x < 21; x++) + { + uint32 sitem = 0; + sitem = CorpseToUse->GetWornItem(x); + if(sitem){ + const Item_Struct * itm = database.GetItem(sitem); + npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 127, true, true); + } + } + + //we allocated a new NPC type object, give the NPC ownership of that memory + if(make_npc != nullptr) + npca->GiveNPCTypeData(make_npc); + + entity_list.AddNPC(npca, true, true); + + //the target of these swarm pets will take offense to being cast on... + if(target != nullptr) + target->AddToHateList(this, 1, 0); +} + +//turn on an AA effect +//duration == 0 means no time limit, used for one-shot deals, etc.. +void Client::EnableAAEffect(aaEffectType type, uint32 duration) { + if(type > 32) + return; //for now, special logic needed. + m_epp.aa_effects |= 1 << (type-1); + + if(duration > 0) { + p_timers.Start(pTimerAAEffectStart + type, duration); + } else { + p_timers.Clear(&database, pTimerAAEffectStart + type); + } +} + +void Client::DisableAAEffect(aaEffectType type) { + if(type > 32) + return; //for now, special logic needed. + uint32 bit = 1 << (type-1); + if(m_epp.aa_effects & bit) { + m_epp.aa_effects ^= bit; + } + p_timers.Clear(&database, pTimerAAEffectStart + type); +} + +/* +By default an AA effect is a one shot deal, unless +a duration timer is set. +*/ +bool Client::CheckAAEffect(aaEffectType type) { + if(type > 32) + return(false); //for now, special logic needed. + if(m_epp.aa_effects & (1 << (type-1))) { //is effect enabled? + //has our timer expired? + if(p_timers.Expired(&database, pTimerAAEffectStart + type)) { + DisableAAEffect(type); + return(false); + } + return(true); + } + return(false); +} + +void Client::SendAAStats() { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); + AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer; + aps->experience = m_pp.expAA; + aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP); + aps->unspent = m_pp.aapoints; + aps->percentage = m_epp.perAA; + QueuePacket(outapp); + safe_delete(outapp); +} + +void Client::BuyAA(AA_Action* action) +{ + mlog(AA__MESSAGE, "Starting to buy AA %d", action->ability); + + //find the AA information from the database + SendAA_Struct* aa2 = zone->FindAA(action->ability); + if(!aa2) { + //hunt for a lower level... + int i; + int a; + for(i=1;iability - i; + if(a <= 0) + break; + mlog(AA__MESSAGE, "Could not find AA %d, trying potential parent %d", action->ability, a); + aa2 = zone->FindAA(a); + if(aa2 != nullptr) + break; + } + } + if(aa2 == nullptr) + return; //invalid ability... + + if(aa2->special_category == 1 || aa2->special_category == 2) + return; // Not purchasable progression style AAs + + if(aa2->special_category == 8 && aa2->cost == 0) + return; // Not purchasable racial AAs(set a cost to make them purchasable) + + uint32 cur_level = GetAA(aa2->id); + if((aa2->id + cur_level) != action->ability) { //got invalid AA + mlog(AA__ERROR, "Unable to find or match AA %d (found %d + lvl %d)", action->ability, aa2->id, cur_level); + return; + } + + if(aa2->account_time_required) + { + if((Timer::GetTimeSeconds() - account_creation) < aa2->account_time_required) + { + return; + } + } + + uint32 real_cost; + std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); + + if(RequiredLevel != AARequiredLevelAndCost.end()) + { + real_cost = RequiredLevel->second.Cost; + } + else + real_cost = aa2->cost + (aa2->cost_inc * cur_level); + + if(m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { + SetAA(aa2->id, cur_level+1); + + mlog(AA__MESSAGE, "Set AA %d to level %d", aa2->id, cur_level+1); + + m_pp.aapoints -= real_cost; + + Save(); + //if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u)) + if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4)) + && ((aa2->max_level == (cur_level+1)) && aa2->sof_next_id)){ + SendAA(aa2->id); + SendAA(aa2->sof_next_id); + } + //else if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && cur_level == 0 && aa2->hotkey_sid != 4294967295u)) + //{ + //Shout("Current lv 0 for AA hot key %i %i", cur_level, aa2->hotkey_sid); + //} + + else + SendAA(aa2->id); + + SendAATable(); + + //we are building these messages ourself instead of using the stringID to work around patch discrepencies + //these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2 + if(cur_level<1) + Message(15,"You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1)?"points":"point"); + else + Message(15,"You have improved %s %d at a cost of %d ability %s.", aa2->name, cur_level+1, real_cost, (real_cost>1)?"points":"point"); + + + SendAAStats(); + + //SendAAList(true); + //SendAATable(); + CalcBonuses(); + if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) + NotifyNewTitlesAvailable(); + } +} + +void Client::SendAATimer(uint32 ability, uint32 begin, uint32 end) { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); + UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; + uaaout->ability = ability; + uaaout->begin = begin; + uaaout->end = end; + QueuePacket(outapp); + safe_delete(outapp); +} + +//sends all AA timers. +void Client::SendAATimers() { + //we dont use SendAATimer because theres no reason to allocate the EQApplicationPacket every time + EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); + UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; + + PTimerList::iterator c,e; + c = p_timers.begin(); + e = p_timers.end(); + for(; c != e; ++c) { + PersistentTimer *cur = c->second; + if(cur->GetType() < pTimerAAStart || cur->GetType() > pTimerAAEnd) + continue; //not an AA timer + //send timer + uaaout->begin = cur->GetStartTime(); + uaaout->end = static_cast(time(nullptr)); + uaaout->ability = cur->GetType() - pTimerAAStart; // uuaaout->ability is really a shared timer number + QueuePacket(outapp); + } + + safe_delete(outapp); +} + +void Client::SendAATable() { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); + + AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; + aa2->aa_spent = GetAAPointsSpent(); + + uint32 i; + for(i=0;i < MAX_PP_AA_ARRAY;i++){ + aa2->aa_list[i].aa_skill = aa[i]->AA; + aa2->aa_list[i].aa_value = aa[i]->value; + aa2->aa_list[i].unknown08 = 0; + } + QueuePacket(outapp); + safe_delete(outapp); +} + +void Client::SendPreviousAA(uint32 id, int seq){ + uint32 value=0; + SendAA_Struct* saa2 = nullptr; + if(id==0) + saa2 = zone->GetAABySequence(seq); + else + saa2 = zone->FindAA(id); + if(!saa2) + return; + int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; + uchar* buffer = new uchar[size]; + SendAA_Struct* saa=(SendAA_Struct*)buffer; + value = GetAA(saa2->id); + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); + outapp->size=size; + outapp->pBuffer=(uchar*)saa; + value--; + memcpy(saa,saa2,size); + + if(value>0){ + if(saa->spellid==0) + saa->spellid=0xFFFFFFFF; + saa->id+=value; + saa->next_id=saa->id+1; + if(value==1) + saa->last_id=saa2->id; + else + saa->last_id=saa->id-1; + saa->current_level=value+1; + saa->cost2 = 0; //cost 2 is what the client uses to calc how many points we've spent, so we have to add up the points in order + for(uint32 i = 0; i < (value+1); i++) { + saa->cost2 += saa->cost + (saa->cost_inc * i); + } + } + + database.FillAAEffects(saa); + QueuePacket(outapp); + safe_delete(outapp); +} + +void Client::SendAA(uint32 id, int seq, bool seqrest) { + + uint32 value=0; + SendAA_Struct* saa2 = nullptr; + SendAA_Struct* qaa = nullptr; + SendAA_Struct* saa_pp = nullptr; + bool IsBaseLevel = true; + bool aa_stack = false; + + Shout("Reset: %i", seqrest); + + if(id==0){ + saa2 = zone->GetAABySequence(seq); + //Shout("SAA2 %i x seq %i", GetAA(saa2->id), seq); + } + else + saa2 = zone->FindAA(id); + if(!saa2) + return; + + uint16 classes = saa2->classes; + if(!(classes & (1 << GetClass())) && (GetClass()!=BERSERKER || saa2->berserker==0)){ + return; + } + + if(saa2->account_time_required) + { + if((Timer::GetTimeSeconds() - account_creation) < saa2->account_time_required) + { + return; + } + } + + // Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). + if (saa2->special_category == 1 || saa2->special_category == 2 ) { + if(GetAA(saa2->id) == 0) + return; + // For Quest line AA(demiplane AEs) where only 1 is visible at a time, check to make sure only the highest level obtained is shown + if(saa2->aa_expansion > 0) { + qaa = zone->FindAA(saa2->id+1); + if(qaa && (saa2->aa_expansion == qaa->aa_expansion) && GetAA(qaa->id) > 0) + return; + } + } + +/* Beginning of Shroud AAs, these categories are for Passive and Active Shroud AAs + Eventually with a toggle we could have it show player list or shroud list + if (saa2->special_category == 3 || saa2->special_category == 4) + return; +*/ + // Check for racial/Drakkin blood line AAs + if (saa2->special_category == 8) + { + uint32 client_race = this->GetBaseRace(); + + // Drakkin Bloodlines + if (saa2->aa_expansion > 522) + { + if (client_race != 522) + return; // Check for Drakkin Race + + int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline + + if (heritage != saa2->aa_expansion) + return; + } + // Racial AAs + else if (client_race != saa2->aa_expansion) + { + return; + } + } + + /* + AA stacking on SoF+ clients. + + Note: There were many ways to achieve this effect - The method used proved to be the most straight forward and consistent. + Stacking does not currently work ideally for AA's that use hotkeys, therefore they will be excluded at this time. + + TODO: Problem with AA hotkeys - When you reach max rank of an AA tier (ie 5/5), it automatically displays the next AA in + the series and you can not transfer the hotkey to the next AA series. To the best of the my ability and through many + different variations of coding I could not find an ideal solution to this issue. + + How stacking works: + Utilizes two new fields: sof_next_id (which is the next id in the series), sof_current_level (ranks the AA's as the current level) + 1) If no AA's purchased only display the base levels of each AA series. + 2) When you purchase an AA and its rank is maxed it sends the packet for the completed AA, and the packet + for the next aa in the series. The previous tier is removed from your window, and the new AA is displayed. + 3) When you zone/buy your player profile will be checked and determine what AA can be displayed base on what you have already. + */ + + //if (RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (saa2->hotkey_sid == 4294967295u)) + if (RuleB(AA, Stacking) && (GetClientVersionBit() >= 4)) + aa_stack = true; + + if (aa_stack){ + uint32 aa_AA = 0; + uint32 aa_value = 0; + for (int i = 0; i < MAX_PP_AA_ARRAY; i++) { + if (aa[i]) { + aa_AA = aa[i]->AA; + aa_value = aa[i]->value; + + if (aa_AA){ + + if (aa_value > 0) + aa_AA -= aa_value-1; + + saa_pp = zone->FindAA(aa_AA); + + if (saa_pp){ + + if (saa_pp->sof_next_skill == saa2->sof_next_skill){ + + if (saa_pp->id == saa2->id) + break; //You already have this in the player profile. + else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value < saa_pp->max_level)) + return; //DISABLE DISPLAY HIGHER - You have not reached max level yet of your current AA. + else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value == saa_pp->max_level) && (saa_pp->sof_next_id == saa2->id)) + IsBaseLevel = false; //ALLOW DISPLAY HIGHER + } + } + } + } + } + } + + //Hide higher tiers of multi tiered AA's if the base level is not fully purchased. + if (aa_stack && IsBaseLevel && saa2->sof_current_level > 0) + return; + + int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; + + if(size == 0) + return; + + uchar* buffer = new uchar[size]; + SendAA_Struct* saa=(SendAA_Struct*)buffer; + memcpy(saa,saa2,size); + Shout("[AA ID %i] SEQ %i SEQLIVE %i",saa->id, saa->seq, saa->seqlive); + if(saa->spellid==0) + saa->spellid=0xFFFFFFFF; + + value=GetAA(saa->id); + uint32 orig_val = value; + + if(value && saa->id){ + + if(value < saa->max_level){ + saa->id+=value; + saa->next_id=saa->id+1; + value++; + } + + else if (aa_stack && saa->sof_next_id){ + //Max value of current tier reached. + saa->id+=value-1; + saa->next_id=saa->sof_next_id; + + //Prevent removal of previous AA from window if next AA belongs to a higher client version. + SendAA_Struct* saa_next = nullptr; + saa_next = zone->FindAA(saa->sof_next_id); + if (saa_next && + (((GetClientVersionBit() == 4) && (saa_next->clientver > 4)) + || ((GetClientVersionBit() == 8) && (saa_next->clientver > 5)) + || ((GetClientVersionBit() == 16) && (saa_next->clientver > 6)))){ + saa->next_id=0xFFFFFFFF; + } + + //if (saa->id == 131) { + // saa->seq = 1; + // Shout("SET SEQ 1"); + //} + Shout("AA Completed: Next"); + } + + else{ + saa->id+=value-1; + saa->next_id=0xFFFFFFFF; + Shout("AA Completed: Final"); + } + + uint32 current_level_mod = 0; + if (aa_stack) + current_level_mod = saa->sof_current_level; + + saa->last_id=saa->id-1; + Shout("1 Current level %i + Value %i",saa->sof_current_level, value); + saa->current_level=value+(current_level_mod); + saa->cost = saa2->cost + (saa2->cost_inc*(value-1)); + saa->cost2 = 0; + for(uint32 i = 0; i < value; i++) { + saa->cost2 += saa2->cost + (saa2->cost_inc * i); + } + saa->class_type = saa2->class_type + (saa2->level_inc*(value-1)); + + } + + if (aa_stack){ + Shout("2 Current level %i VALUE %i",saa->sof_current_level, value); + //After finishing an AA tier transfer over the current level to the next tier to display. + if (saa->sof_current_level >= 1 && value == 0){ + saa->current_level = saa->sof_current_level+1; + + Shout("value = 0 SET LAST AND SEQ"); + saa->last_id = 131; + //saa->seq = 38; + if (saa->seqlive) + saa->seq = saa->seqlive; + } + + saa->max_level = saa->sof_max_level; + } + + + if(seqrest) { + //saa->seq = 0; + saa->id+= saa->max_level-1; + saa->next_id=1; + saa->seq = 0; + Shout("reset"); + } + + database.FillAAEffects(saa); + + if(value > 0) + { + // AA_Action stores the base ID + const AA_DBAction *caa = &AA_Actions[saa->id - value + 1][value - 1]; + + if(caa && caa->reuse_time > 0) + saa->spell_refresh = CalcAAReuseTimer(caa); + } + + //You can now use the level_inc field in the altadv_vars table to accomplish this, though still needed + //for special cases like LOH/HT due to inability to implement correct stacking of AA's that use hotkeys. + std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(saa->id); + + if(RequiredLevel != AARequiredLevelAndCost.end()) + { + saa->class_type = RequiredLevel->second.Level; + saa->cost = RequiredLevel->second.Cost; + } + + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); + outapp->size=size; + outapp->pBuffer=(uchar*)saa; + if(id==0 && value && (orig_val < saa->max_level)) //send previous AA only on zone in + SendPreviousAA(id, seq); + + QueuePacket(outapp); + safe_delete(outapp); + //will outapp delete the buffer for us even though it didnt make it? --- Yes, it should +} + +void Client::SendAAList(bool seqrest){ + int total = zone->GetTotalAAs(); + for(int i=0;i < total;i++){ + SendAA(0,i, seqrest); + } +} + +uint32 Client::GetAA(uint32 aa_id) const { + std::map::const_iterator res; + res = aa_points.find(aa_id); + if(res != aa_points.end()) { + return(res->second); + } + return(0); +} + +bool Client::SetAA(uint32 aa_id, uint32 new_value) { + aa_points[aa_id] = new_value; + uint32 cur; + for(cur=0;cur < MAX_PP_AA_ARRAY;cur++){ + if((aa[cur]->value > 1) && ((aa[cur]->AA - aa[cur]->value + 1)== aa_id)){ + aa[cur]->value = new_value; + if(new_value > 0) + aa[cur]->AA++; + else + aa[cur]->AA = 0; + return true; + } + else if((aa[cur]->value == 1) && (aa[cur]->AA == aa_id)){ + aa[cur]->value = new_value; + if(new_value > 0) + aa[cur]->AA++; + else + aa[cur]->AA = 0; + return true; + } + else if(aa[cur]->AA==0){ //end of list + aa[cur]->AA = aa_id; + aa[cur]->value = new_value; + return true; + } + } + return false; +} + +SendAA_Struct* Zone::FindAA(uint32 id) { + return aas_send[id]; +} + +void Zone::LoadAAs() { + LogFile->write(EQEMuLog::Status, "Loading AA information..."); + totalAAs = database.CountAAs(); + if(totalAAs == 0) { + LogFile->write(EQEMuLog::Error, "Failed to load AAs!"); + aas = nullptr; + return; + } + aas = new SendAA_Struct *[totalAAs]; + + database.LoadAAs(aas); + + int i; + for(i=0; i < totalAAs; i++){ + SendAA_Struct* aa = aas[i]; + aas_send[aa->id] = aa; + } + + //load AA Effects into aa_effects + LogFile->write(EQEMuLog::Status, "Loading AA Effects..."); + if (database.LoadAAEffects2()) + LogFile->write(EQEMuLog::Status, "Loaded %d AA Effects.", aa_effects.size()); + else + LogFile->write(EQEMuLog::Error, "Failed to load AA Effects!"); +} + +bool ZoneDatabase::LoadAAEffects2() { + aa_effects.clear(); //start fresh + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT aaid, slot, effectid, base1, base2 FROM aa_effects ORDER BY aaid ASC, slot ASC"), errbuf, &result)) { + int count = 0; + while((row = mysql_fetch_row(result))!= nullptr) { + int aaid = atoi(row[0]); + int slot = atoi(row[1]); + int effectid = atoi(row[2]); + int base1 = atoi(row[3]); + int base2 = atoi(row[4]); + aa_effects[aaid][slot].skill_id = effectid; + aa_effects[aaid][slot].base1 = base1; + aa_effects[aaid][slot].base2 = base2; + aa_effects[aaid][slot].slot = slot; //not really needed, but we'll populate it just in case + count++; + } + mysql_free_result(result); + if (count < 1) //no results + LogFile->write(EQEMuLog::Error, "Error loading AA Effects, none found in the database."); + } else { + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAEffects2 query: '%s': %s", query, errbuf); + return false; + } + safe_delete_array(query); + return true; +} +void Client::ResetAA(){ + uint32 i; + for(i=0;iAA = 0; + aa[i]->value = 0; + } + std::map::iterator itr; + for(itr=aa_points.begin();itr!=aa_points.end();++itr) + aa_points[itr->first] = 0; + + for(int i = 0; i < _maxLeaderAA; ++i) + m_pp.leader_abilities.ranks[i] = 0; + + m_pp.group_leadership_points = 0; + m_pp.raid_leadership_points = 0; + m_pp.group_leadership_exp = 0; + m_pp.raid_leadership_exp = 0; +} + +int Client::GroupLeadershipAAHealthEnhancement() +{ + Group *g = GetGroup(); + + if(!g || (g->GroupCount() < 3)) + return 0; + + switch(g->GetLeadershipAA(groupAAHealthEnhancement)) + { + case 0: + return 0; + case 1: + return 30; + case 2: + return 60; + case 3: + return 100; + } + + return 0; +} + +int Client::GroupLeadershipAAManaEnhancement() +{ + Group *g = GetGroup(); + + if(!g || (g->GroupCount() < 3)) + return 0; + + switch(g->GetLeadershipAA(groupAAManaEnhancement)) + { + case 0: + return 0; + case 1: + return 30; + case 2: + return 60; + case 3: + return 100; + } + + return 0; +} + +int Client::GroupLeadershipAAHealthRegeneration() +{ + Group *g = GetGroup(); + + if(!g || (g->GroupCount() < 3)) + return 0; + + switch(g->GetLeadershipAA(groupAAHealthRegeneration)) + { + case 0: + return 0; + case 1: + return 4; + case 2: + return 6; + case 3: + return 8; + } + + return 0; +} + +int Client::GroupLeadershipAAOffenseEnhancement() +{ + Group *g = GetGroup(); + + if(!g || (g->GroupCount() < 3)) + return 0; + + switch(g->GetLeadershipAA(groupAAOffenseEnhancement)) + { + case 0: + return 0; + case 1: + return 10; + case 2: + return 19; + case 3: + return 28; + case 4: + return 34; + case 5: + return 40; + } + return 0; +} + +void Client::InspectBuffs(Client* Inspector, int Rank) +{ + if(!Inspector || (Rank == 0)) return; + + Inspector->Message_StringID(0, CURRENT_SPELL_EFFECTS, GetName()); + uint32 buff_count = GetMaxTotalSlots(); + for (uint32 i = 0; i < buff_count; ++i) + { + if (buffs[i].spellid != SPELL_UNKNOWN) + { + if(Rank == 1) + Inspector->Message(0, "%s", spells[buffs[i].spellid].name); + else + { + if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) + Inspector->Message(0, "%s (Permanent)", spells[buffs[i].spellid].name); + else { + char *TempString = nullptr; + MakeAnyLenString(&TempString, "%.1f", static_cast(buffs[i].ticsremaining) / 10.0f); + Inspector->Message_StringID(0, BUFF_MINUTES_REMAINING, spells[buffs[i].spellid].name, TempString); + safe_delete_array(TempString); + } + } + } + } +} + +//this really need to be renamed to LoadAAActions() +bool ZoneDatabase::LoadAAEffects() { + char errbuf[MYSQL_ERRMSG_SIZE]; + MYSQL_RES *result; + MYSQL_ROW row; + + memset(AA_Actions, 0, sizeof(AA_Actions)); //I hope the compiler is smart about this size... + + const char *query = "SELECT aaid,rank,reuse_time,spell_id,target,nonspell_action,nonspell_mana,nonspell_duration," + "redux_aa,redux_rate,redux_aa2,redux_rate2 FROM aa_actions"; + + if(RunQuery(query, static_cast(strlen(query)), errbuf, &result)) { + //safe_delete_array(query); + int r; + while ((row = mysql_fetch_row(result))) { + r = 0; + int aaid = atoi(row[r++]); + int rank = atoi(row[r++]); + if(aaid < 0 || aaid >= aaHighestID || rank < 0 || rank >= MAX_AA_ACTION_RANKS) + continue; + AA_DBAction *caction = &AA_Actions[aaid][rank]; + + caction->reuse_time = atoi(row[r++]); + caction->spell_id = atoi(row[r++]); + caction->target = (aaTargetType) atoi(row[r++]); + caction->action = (aaNonspellAction) atoi(row[r++]); + caction->mana_cost = atoi(row[r++]); + caction->duration = atoi(row[r++]); + caction->redux_aa = (aaID) atoi(row[r++]); + caction->redux_rate = atoi(row[r++]); + caction->redux_aa2 = (aaID) atoi(row[r++]); + caction->redux_rate2 = atoi(row[r++]); + + } + mysql_free_result(result); + } + else { + LogFile->write(EQEMuLog::Error, "Error in LoadAAEffects query '%s': %s", query, errbuf);; + //safe_delete_array(query); + return false; + } + + return true; +} + +//Returns the number effects an AA has when we send them to the client +//For the purposes of sizing a packet because every skill does not +//have the same number effects, they can range from none to a few depending on AA. +//counts the # of effects by counting the different slots of an AAID in the DB. + +//AndMetal: this may now be obsolete since we have Zone::GetTotalAALevels() +uint8 ZoneDatabase::GetTotalAALevels(uint32 skill_id) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + int total=0; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(slot) from aa_effects where aaid=%i", skill_id), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + total=atoi(row[0]); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in GetTotalAALevels '%s: %s", query, errbuf); + safe_delete_array(query); + } + return total; +} + +//this will allow us to count the number of effects for an AA by pulling the info from memory instead of the database. hopefully this will same some CPU cycles +uint8 Zone::GetTotalAALevels(uint32 skill_id) { + size_t sz = aa_effects[skill_id].size(); + return sz >= 255 ? 255 : static_cast(sz); +} + +/* +Every AA can send the client effects, which are purely for client side effects. +Essentially it's like being able to attach a very simple version of a spell to +Any given AA, it has 4 fields: +skill_id = spell effect id +slot = ID slot, doesn't appear to have any impact on stacking like real spells, just needs to be unique. +base1 = the base field of a spell +base2 = base field 2 of a spell, most AAs do not utilize this +example: + skill_id = SE_STA + slot = 1 + base1 = 15 + This would if you filled the abilities struct with this make the client show if it had + that AA an additional 15 stamina on the client's stats +*/ +void ZoneDatabase::FillAAEffects(SendAA_Struct* aa_struct){ + if(!aa_struct) + return; + + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT effectid, base1, base2, slot from aa_effects where aaid=%i order by slot asc", aa_struct->id), errbuf, &result)) { + int ndx=0; + while((row = mysql_fetch_row(result))!=nullptr) { + aa_struct->abilities[ndx].skill_id=atoi(row[0]); + aa_struct->abilities[ndx].base1=atoi(row[1]); + aa_struct->abilities[ndx].base2=atoi(row[2]); + aa_struct->abilities[ndx].slot=atoi(row[3]); + ndx++; + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in Client::FillAAEffects query: '%s': %s", query, errbuf); + } + safe_delete_array(query); +} + +uint32 ZoneDatabase::CountAAs(){ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + int count=0; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(title_sid) from altadv_vars"), errbuf, &result)) { + if((row = mysql_fetch_row(result))!=nullptr) + count = atoi(row[0]); + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAAs query '%s': %s", query, errbuf); + } + safe_delete_array(query); + return count; +} + +uint32 ZoneDatabase::CountAAEffects(){ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + int count=0; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(id) from aa_effects"), errbuf, &result)) { + if((row = mysql_fetch_row(result))!=nullptr){ + count = atoi(row[0]); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAALevels query '%s': %s", query, errbuf); + } + safe_delete_array(query); + return count; +} + +uint32 ZoneDatabase::GetSizeAA(){ + int size=CountAAs()*sizeof(SendAA_Struct); + if(size>0) + size+=CountAAEffects()*sizeof(AA_Ability); + return size; +} + +void ZoneDatabase::LoadAAs(SendAA_Struct **load){ + if(!load) + return; + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id from altadv_vars order by skill_id"), errbuf, &result)) { + int skill=0,ndx=0; + while((row = mysql_fetch_row(result))!=nullptr) { + skill=atoi(row[0]); + load[ndx] = GetAASkillVars(skill); + load[ndx]->seq = ndx+1; + ndx++; + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); + } + safe_delete_array(query); + + AARequiredLevelAndCost.clear(); + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id, level, cost from aa_required_level_cost order by skill_id"), errbuf, &result)) + { + AALevelCost_Struct aalcs; + while((row = mysql_fetch_row(result))!=nullptr) + { + aalcs.Level = atoi(row[1]); + aalcs.Cost = atoi(row[2]); + AARequiredLevelAndCost[atoi(row[0])] = aalcs; + } + mysql_free_result(result); + } + else + LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); + + safe_delete_array(query); +} + +SendAA_Struct* ZoneDatabase::GetAASkillVars(uint32 skill_id) +{ + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + SendAA_Struct* sendaa = nullptr; + uchar* buffer; + if (RunQuery(query, MakeAnyLenString(&query, "SET @row = 0"), errbuf)) { //initialize "row" variable in database for next query + safe_delete_array(query); + MYSQL_RES *result; //we don't really need these unless we get to this point, so why bother? + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, + "SELECT " + "a.cost, " + "a.max_level, " + "a.hotkey_sid, " + "a.hotkey_sid2, " + "a.title_sid, " + "a.desc_sid, " + "a.type, " + "COALESCE(" //so we can return 0 if it's null + "(" //this is our derived table that has the row # that we can SELECT from, because the client is stupid + "SELECT " + "p.prereq_index_num " + "FROM " + "(" + "SELECT " + "a2.skill_id, " + "@row := @row + 1 AS prereq_index_num " + "FROM " + "altadv_vars a2" + ") AS p " + "WHERE " + "p.skill_id = a.prereq_skill" + "), " + "0) AS prereq_skill_index, " + "a.prereq_minpoints, " + "a.spell_type, " + "a.spell_refresh, " + "a.classes, " + "a.berserker, " + "a.spellid, " + "a.class_type, " + "a.name, " + "a.cost_inc, " + "a.aa_expansion, " + "a.special_category, " + "a.sof_type, " + "a.sof_cost_inc, " + "a.sof_max_level, " + "a.sof_next_skill, " + "a.clientver, " // Client Version 0 = None, 1 = All, 2 = Titanium/6.2, 4 = SoF 5 = SOD 6 = UF + "a.account_time_required, " + "a.sof_current_level," + "a.sof_next_id, " + "a.level_inc, " + "a.seqlive " + " FROM altadv_vars a WHERE skill_id=%i", skill_id), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) { + int total_abilities = GetTotalAALevels(skill_id); //eventually we'll want to use zone->GetTotalAALevels(skill_id) since it should save queries to the DB + int totalsize = total_abilities * sizeof(AA_Ability) + sizeof(SendAA_Struct); + + buffer = new uchar[totalsize]; + memset(buffer,0,totalsize); + sendaa = (SendAA_Struct*)buffer; + + row = mysql_fetch_row(result); + + //ATOI IS NOT UNISGNED LONG-SAFE!!! + + sendaa->cost = atoul(row[0]); + sendaa->cost2 = sendaa->cost; + sendaa->max_level = atoul(row[1]); + sendaa->hotkey_sid = atoul(row[2]); + sendaa->id = skill_id; + sendaa->hotkey_sid2 = atoul(row[3]); + sendaa->title_sid = atoul(row[4]); + sendaa->desc_sid = atoul(row[5]); + sendaa->type = atoul(row[6]); + sendaa->prereq_skill = atoul(row[7]); + sendaa->prereq_minpoints = atoul(row[8]); + sendaa->spell_type = atoul(row[9]); + sendaa->spell_refresh = atoul(row[10]); + sendaa->classes = static_cast(atoul(row[11])); + sendaa->berserker = static_cast(atoul(row[12])); + sendaa->last_id = 0xFFFFFFFF; + sendaa->current_level=1; + sendaa->spellid = atoul(row[13]); + sendaa->class_type = atoul(row[14]); + strcpy(sendaa->name,row[15]); + + sendaa->total_abilities=total_abilities; + if(sendaa->max_level > 1) + sendaa->next_id=skill_id+1; + else + sendaa->next_id=0xFFFFFFFF; + + sendaa->cost_inc = atoi(row[16]); + // Begin SoF Specific/Adjusted AA Fields + sendaa->aa_expansion = atoul(row[17]); + sendaa->special_category = atoul(row[18]); + sendaa->sof_type = atoul(row[19]); + sendaa->sof_cost_inc = atoi(row[20]); + sendaa->sof_max_level = atoul(row[21]); + sendaa->sof_next_skill = atoul(row[22]); + sendaa->clientver = atoul(row[23]); + sendaa->account_time_required = atoul(row[24]); + //Internal use only - not sent to client + sendaa->sof_current_level = atoul(row[25]); + sendaa->sof_next_id = atoul(row[26]); + sendaa->level_inc = static_cast(atoul(row[27])); + sendaa->seqlive = (atoul(row[28])); + } + mysql_free_result(result); + } else { + LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); + safe_delete_array(query); + } + } else { + LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); + safe_delete_array(query); + } + return sendaa; +} + +void Client::DurationRampage(uint32 duration) +{ + if(duration) { + m_epp.aa_effects |= 1 << (aaEffectRampage-1); + p_timers.Start(pTimerAAEffectStart + aaEffectRampage, duration); + } +} + +AA_SwarmPetInfo::AA_SwarmPetInfo() +{ + target = 0; + owner_id = 0; + duration = nullptr; +} + +AA_SwarmPetInfo::~AA_SwarmPetInfo() +{ + target = 0; + owner_id = 0; + safe_delete(duration); +} + +Mob *AA_SwarmPetInfo::GetOwner() +{ + return entity_list.GetMobID(owner_id); +} diff --git a/zone/MobAI_M.cpp b/zone/MobAI_M.cpp new file mode 100644 index 000000000..7574f19ad --- /dev/null +++ b/zone/MobAI_M.cpp @@ -0,0 +1,2760 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "../common/debug.h" +#include +#include +#include +#include +#include +#include "npc.h" +#include "masterentity.h" +#include "NpcAI.h" +#include "map.h" +#include "../common/moremath.h" +#include "StringIDs.h" +#include "../common/MiscFunctions.h" +#include "../common/StringUtil.h" +#include "../common/rulesys.h" +#include "../common/features.h" +#include "QuestParserCollection.h" +#include "watermap.h" + +extern EntityList entity_list; + +extern Zone *zone; + +#ifdef _EQDEBUG + #define MobAI_DEBUG_Spells -1 +#else + #define MobAI_DEBUG_Spells -1 +#endif +#define ABS(x) ((x)<0?-(x):(x)) + +//NOTE: do NOT pass in beneficial and detrimental spell types into the same call here! +bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { + if (!tar) + return false; + + if (IsNoCast()) + return false; + + if(AI_HasSpells() == false) + return false; + + if (iChance < 100) { + if (MakeRandomInt(0, 100) >= iChance) + return false; + } + + float dist2; + + if (iSpellTypes & SpellType_Escape) { + dist2 = 0; //DistNoRoot(*this); //WTF was up with this... + } + else + dist2 = DistNoRoot(*tar); + + bool checked_los = false; //we do not check LOS until we are absolutely sure we need to, and we only do it once. + + float manaR = GetManaRatio(); + for (int i = static_cast(AIspells.size()) - 1; i >= 0; i--) { + if (AIspells[i].spellid <= 0 || AIspells[i].spellid >= SPDAT_RECORDS) { + // this is both to quit early to save cpu and to avoid casting bad spells + // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here + //return false; + continue; + } + if (iSpellTypes & AIspells[i].type) { + // manacost has special values, -1 is no mana cost, -2 is instant cast (no mana) + int32 mana_cost = AIspells[i].manacost; + if (mana_cost == -1) + mana_cost = spells[AIspells[i].spellid].mana; + else if (mana_cost == -2) + mana_cost = 0; + if ( + (( + (spells[AIspells[i].spellid].targettype==ST_AECaster || spells[AIspells[i].spellid].targettype==ST_AEBard) + && dist2 <= spells[AIspells[i].spellid].aoerange*spells[AIspells[i].spellid].aoerange + ) || + dist2 <= spells[AIspells[i].spellid].range*spells[AIspells[i].spellid].range + ) + && (mana_cost <= GetMana() || GetMana() == GetMaxMana()) + && (AIspells[i].time_cancast + (MakeRandomInt(0, 4) * 1000)) <= Timer::GetCurrentTime() //break up the spelling casting over a period of time. + ) { + +#if MobAI_DEBUG_Spells >= 21 + std::cout << "Mob::AICastSpell: Casting: spellid=" << AIspells[i].spellid + << ", tar=" << tar->GetName() + << ", dist2[" << dist2 << "]<=" << spells[AIspells[i].spellid].range *spells[AIspells[i].spellid].range + << ", mana_cost[" << mana_cost << "]<=" << GetMana() + << ", cancast[" << AIspells[i].time_cancast << "]<=" << Timer::GetCurrentTime() + << ", type=" << AIspells[i].type << std::endl; +#endif + + switch (AIspells[i].type) { + case SpellType_Heal: { + if ( + (spells[AIspells[i].spellid].targettype == ST_Target || tar == this) + && tar->DontHealMeBefore() < Timer::GetCurrentTime() + && !(tar->IsPet() && tar->GetOwner()->IsClient()) //no buffing PC's pets + ) { + uint8 hpr = (uint8)tar->GetHPRatio(); + + if(hpr <= 35 || (!IsEngaged() && hpr <= 50) || (tar->IsClient() && hpr <= 99)) { + uint32 tempTime = 0; + AIDoSpellCast(i, tar, mana_cost, &tempTime); + tar->SetDontHealMeBefore(tempTime); + return true; + } + } + break; + } + case SpellType_Root: { + Mob *rootee = GetHateRandom(); + if (rootee && !rootee->IsRooted() && MakeRandomInt(0, 99) < 50 + && rootee->DontRootMeBefore() < Timer::GetCurrentTime() + && rootee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 + ) { + if(!checked_los) { + if(!CheckLosFN(rootee)) + return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call + checked_los = true; + } + uint32 tempTime = 0; + AIDoSpellCast(i, rootee, mana_cost, &tempTime); + rootee->SetDontRootMeBefore(tempTime); + return true; + } + break; + } + case SpellType_Buff: { + if ( + (spells[AIspells[i].spellid].targettype == ST_Target || tar == this) + && tar->DontBuffMeBefore() < Timer::GetCurrentTime() + && !tar->IsImmuneToSpell(AIspells[i].spellid, this) + && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 + && !(tar->IsPet() && tar->GetOwner()->IsClient() && this != tar) //no buffing PC's pets, but they can buff themself + ) + { + if(!checked_los) { + if(!CheckLosFN(tar)) + return(false); + checked_los = true; + } + uint32 tempTime = 0; + AIDoSpellCast(i, tar, mana_cost, &tempTime); + tar->SetDontBuffMeBefore(tempTime); + return true; + } + break; + } + + case SpellType_InCombatBuff: { + if(MakeRandomInt(0, 99) < 50) + { + AIDoSpellCast(i, tar, mana_cost); + return true; + } + break; + } + + case SpellType_Escape: { + if (GetHPRatio() <= 5 ) + { + AIDoSpellCast(i, tar, mana_cost); + return true; + } + break; + } + case SpellType_Slow: + case SpellType_Debuff: { + Mob * debuffee = GetHateRandom(); + if (debuffee && manaR >= 10 && MakeRandomInt(0, 99 < 70) && + debuffee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) { + if (!checked_los) { + if (!CheckLosFN(debuffee)) + return false; + checked_los = true; + } + AIDoSpellCast(i, debuffee, mana_cost); + return true; + } + break; + } + case SpellType_Nuke: { + if ( + manaR >= 10 && MakeRandomInt(0, 99) < 70 + && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 + ) { + if(!checked_los) { + if(!CheckLosFN(tar)) + return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call + checked_los = true; + } + AIDoSpellCast(i, tar, mana_cost); + return true; + } + break; + } + case SpellType_Dispel: { + if(MakeRandomInt(0, 99) < 15) + { + if(!checked_los) { + if(!CheckLosFN(tar)) + return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call + checked_los = true; + } + if(tar->CountDispellableBuffs() > 0) + { + AIDoSpellCast(i, tar, mana_cost); + return true; + } + } + break; + } + case SpellType_Mez: { + if(MakeRandomInt(0, 99) < 20) + { + Mob * mezTar = nullptr; + mezTar = entity_list.GetTargetForMez(this); + + if(mezTar && mezTar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) + { + AIDoSpellCast(i, mezTar, mana_cost); + return true; + } + } + break; + } + + case SpellType_Charm: + { + if(!IsPet() && MakeRandomInt(0, 99) < 20) + { + Mob * chrmTar = GetHateRandom(); + if(chrmTar && chrmTar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) + { + AIDoSpellCast(i, chrmTar, mana_cost); + return true; + } + } + break; + } + + case SpellType_Pet: { + //keep mobs from recasting pets when they have them. + if (!IsPet() && !GetPetID() && MakeRandomInt(0, 99) < 25) { + AIDoSpellCast(i, tar, mana_cost); + return true; + } + break; + } + case SpellType_Lifetap: { + if (GetHPRatio() <= 95 + && MakeRandomInt(0, 99) < 50 + && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 + ) { + if(!checked_los) { + if(!CheckLosFN(tar)) + return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call + checked_los = true; + } + AIDoSpellCast(i, tar, mana_cost); + return true; + } + break; + } + case SpellType_Snare: { + if ( + !tar->IsRooted() + && MakeRandomInt(0, 99) < 50 + && tar->DontSnareMeBefore() < Timer::GetCurrentTime() + && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 + ) { + if(!checked_los) { + if(!CheckLosFN(tar)) + return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call + checked_los = true; + } + uint32 tempTime = 0; + AIDoSpellCast(i, tar, mana_cost, &tempTime); + tar->SetDontSnareMeBefore(tempTime); + return true; + } + break; + } + case SpellType_DOT: { + if ( + MakeRandomInt(0, 99) < 60 + && tar->DontDotMeBefore() < Timer::GetCurrentTime() + && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 + ) { + if(!checked_los) { + if(!CheckLosFN(tar)) + return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call + checked_los = true; + } + uint32 tempTime = 0; + AIDoSpellCast(i, tar, mana_cost, &tempTime); + tar->SetDontDotMeBefore(tempTime); + return true; + } + break; + } + default: { + std::cout << "Error: Unknown spell type in AICastSpell. caster:" << this->GetName() << " type:" << AIspells[i].type << " slot:" << i << std::endl; + break; + } + } + } +#if MobAI_DEBUG_Spells >= 21 + else { + std::cout << "Mob::AICastSpell: NotCasting: spellid=" << AIspells[i].spellid << ", tar=" << tar->GetName() << ", dist2[" << dist2 << "]<=" << spells[AIspells[i].spellid].range*spells[AIspells[i].spellid].range << ", mana_cost[" << mana_cost << "]<=" << GetMana() << ", cancast[" << AIspells[i].time_cancast << "]<=" << Timer::GetCurrentTime() << std::endl; + } +#endif + } + } + return false; +} + +bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore) { +#if MobAI_DEBUG_Spells >= 1 + std::cout << "Mob::AIDoSpellCast: spellid=" << AIspells[i].spellid << ", tar=" << tar->GetName() << ", mana=" << mana_cost << ", Name: " << spells[AIspells[i].spellid].name << std::endl; +#endif + casting_spell_AIindex = i; + + //stop moving if were casting a spell and were not a bard... + if(!IsBardSong(AIspells[i].spellid)) { + SetRunAnimSpeed(0); + SendPosition(); + SetMoving(false); + } + + return CastSpell(AIspells[i].spellid, tar->GetID(), 1, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0, &(AIspells[i].resist_adjust)); +} + +bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint16 iSpellTypes) { + if((iSpellTypes&SpellTypes_Detrimental) != 0) { + //according to live, you can buff and heal through walls... + //now with PCs, this only applies if you can TARGET the target, but + // according to Rogean, Live NPCs will just cast through walls/floors, no problem.. + // + // This check was put in to address an idle-mob CPU issue + _log(AI__ERROR, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!"); + return(false); + } + + if(!caster) + return false; + + if(caster->AI_HasSpells() == false) + return false; + + if(caster->GetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS)) + return false; + + if (iChance < 100) { + uint8 tmp = MakeRandomInt(0, 99); + if (tmp >= iChance) + return false; + } + if (caster->GetPrimaryFaction() == 0 ) + return(false); // well, if we dont have a faction set, we're gonna be indiff to everybody + + float iRange2 = iRange*iRange; + + float t1, t2, t3; + + + //Only iterate through NPCs + for (auto it = npc_list.begin(); it != npc_list.end(); ++it) { + NPC* mob = it->second; + + //Since >90% of mobs will always be out of range, try to + //catch them with simple bounding box checks first. These + //checks are about 6X faster than DistNoRoot on my athlon 1Ghz + t1 = mob->GetX() - caster->GetX(); + t2 = mob->GetY() - caster->GetY(); + t3 = mob->GetZ() - caster->GetZ(); + //cheap ABS() + if(t1 < 0) + t1 = 0 - t1; + if(t2 < 0) + t2 = 0 - t2; + if(t3 < 0) + t3 = 0 - t3; + if (t1 > iRange + || t2 > iRange + || t3 > iRange + || mob->DistNoRoot(*caster) > iRange2 + //this call should seem backwards: + || !mob->CheckLosFN(caster) + || mob->GetReverseFactionCon(caster) >= FACTION_KINDLY + ) { + continue; + } + + //since we assume these are beneficial spells, which do not + //require LOS, we just go for it. + // we have a winner! + if((iSpellTypes & SpellType_Buff) && !RuleB(NPC, BuffFriends)){ + if (mob != caster) + iSpellTypes = SpellType_Heal; + } + + if (caster->AICastSpell(mob, 100, iSpellTypes)) + return true; + } + return false; +} + +void Mob::AI_Init() { + pAIControlled = false; + AIthink_timer = 0; + AIwalking_timer = 0; + AImovement_timer = 0; + AItarget_check_timer = 0; + AIfeignremember_timer = nullptr; + AIscanarea_timer = 0; + minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin); + maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax); + + pDontHealMeBefore = 0; + pDontBuffMeBefore = 0; + pDontDotMeBefore = 0; + pDontRootMeBefore = 0; + pDontSnareMeBefore = 0; + pDontCureMeBefore = 0; +} + +void NPC::AI_Init() { + Mob::AI_Init(); + + AIautocastspell_timer = 0; + casting_spell_AIindex = static_cast(AIspells.size()); + + roambox_max_x = 0; + roambox_max_y = 0; + roambox_min_x = 0; + roambox_min_y = 0; + roambox_distance = 0; + roambox_movingto_x = 0; + roambox_movingto_y = 0; + roambox_min_delay = 2500; + roambox_delay = 2500; +} + +void Client::AI_Init() { + Mob::AI_Init(); + minLastFightingDelayMoving = CLIENT_LD_TIMEOUT; + maxLastFightingDelayMoving = CLIENT_LD_TIMEOUT; +} + +void Mob::AI_Start(uint32 iMoveDelay) { + if (pAIControlled) + return; + + if (iMoveDelay) + pLastFightingDelayMoving = Timer::GetCurrentTime() + iMoveDelay; + else + pLastFightingDelayMoving = 0; + + pAIControlled = true; + AIthink_timer = new Timer(AIthink_duration); + AIthink_timer->Trigger(); + AIwalking_timer = new Timer(0); + AImovement_timer = new Timer(AImovement_duration); + AItarget_check_timer = new Timer(AItarget_check_duration); + AIfeignremember_timer = new Timer(AIfeignremember_delay); + AIscanarea_timer = new Timer(AIscanarea_delay); +#ifdef REVERSE_AGGRO + if(IsNPC() && !CastToNPC()->WillAggroNPCs()) + AIscanarea_timer->Disable(); +#endif + + if (GetAggroRange() == 0) + pAggroRange = 70; + if (GetAssistRange() == 0) + pAssistRange = 70; + hate_list.Wipe(); + + delta_heading = 0; + delta_x = 0; + delta_y = 0; + delta_z = 0; + pRunAnimSpeed = 0; + pLastChange = Timer::GetCurrentTime(); +} + +void Client::AI_Start(uint32 iMoveDelay) { + Mob::AI_Start(iMoveDelay); + + if (!pAIControlled) + return; + + pClientSideTarget = GetTarget() ? GetTarget()->GetID() : 0; + SendAppearancePacket(AT_Anim, ANIM_FREEZE); // this freezes the client + SendAppearancePacket(AT_Linkdead, 1); // Sending LD packet so *LD* appears by the player name when charmed/feared -Kasai + SetAttackTimer(); + SetFeigned(false); +} + +void NPC::AI_Start(uint32 iMoveDelay) { + Mob::AI_Start(iMoveDelay); + if (!pAIControlled) + return; + + if (AIspells.size() == 0) { + AIautocastspell_timer = new Timer(1000); + AIautocastspell_timer->Disable(); + } else { + AIautocastspell_timer = new Timer(750); + AIautocastspell_timer->Start(RandomTimer(0, 15000), false); + } + + if (NPCTypedata) { + AI_AddNPCSpells(NPCTypedata->npc_spells_id); + ProcessSpecialAbilities(NPCTypedata->special_abilities); + AI_AddNPCSpellsEffects(NPCTypedata->npc_spells_effects_id); + } + + SendTo(GetX(), GetY(), GetZ()); + SetChanged(); + SaveGuardSpot(); +} + +void Mob::AI_Stop() { + if (!IsAIControlled()) + return; + pAIControlled = false; + safe_delete(AIthink_timer); + safe_delete(AIwalking_timer); + safe_delete(AImovement_timer); + safe_delete(AItarget_check_timer) + safe_delete(AIscanarea_timer); + safe_delete(AIfeignremember_timer); + hate_list.Wipe(); +} + +void NPC::AI_Stop() { + Waypoints.clear(); + safe_delete(AIautocastspell_timer); +} + +void Client::AI_Stop() { + Mob::AI_Stop(); + this->Message_StringID(13,PLAYER_REGAIN); + + EQApplicationPacket *app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); + Charm_Struct *ps = (Charm_Struct*)app->pBuffer; + ps->owner_id = 0; + ps->pet_id = this->GetID(); + ps->command = 0; + entity_list.QueueClients(this, app); + safe_delete(app); + + SetTarget(entity_list.GetMob(pClientSideTarget)); + SendAppearancePacket(AT_Anim, GetAppearanceValue(GetAppearance())); + SendAppearancePacket(AT_Linkdead, 0); // Removing LD packet so *LD* no longer appears by the player name when charmed/feared -Kasai + if (!auto_attack) { + attack_timer.Disable(); + attack_dw_timer.Disable(); + } + if (IsLD()) + { + Save(); + Disconnect(); + } +} + +//todo: expand the logic here to cover: +//redundant debuffs +//buffing owner +//certain types of det spells that need special behavior. +void Client::AI_SpellCast() +{ + if(!charm_cast_timer.Check()) + return; + + Mob *targ = GetTarget(); + if(!targ) + return; + + float dist = DistNoRootNoZ(*targ); + + std::vector valid_spells; + std::vector slots; + + for(uint32 x = 0; x < 9; ++x) + { + uint32 current_spell = m_pp.mem_spells[x]; + if(!IsValidSpell(current_spell)) + continue; + + if(IsBeneficialSpell(current_spell)) + { + continue; + } + + if(dist > spells[current_spell].range*spells[current_spell].range) + { + continue; + } + + if(GetMana() < spells[current_spell].mana) + { + continue; + } + + if(IsEffectInSpell(current_spell, SE_Charm)) + { + continue; + } + + if(!GetPTimers().Expired(&database, pTimerSpellStart + current_spell, false)) + { + continue; + } + + if(targ->CanBuffStack(current_spell, GetLevel(), true) < 0) + { + continue; + } + + //bard songs cause trouble atm + if(IsBardSong(current_spell)) + continue; + + valid_spells.push_back(current_spell); + slots.push_back(x); + } + + uint32 spell_to_cast = 0xFFFFFFFF; + uint32 slot_to_use = 10; + if(valid_spells.size() == 1) + { + spell_to_cast = valid_spells[0]; + slot_to_use = slots[0]; + } + else if(valid_spells.size() == 0) + { + return; + } + else + { + uint32 idx = MakeRandomInt(0, (valid_spells.size()-1)); + spell_to_cast = valid_spells[idx]; + slot_to_use = slots[idx]; + } + + if(IsMezSpell(spell_to_cast) || IsFearSpell(spell_to_cast)) + { + Mob *tar = entity_list.GetTargetForMez(this); + if(!tar) + { + tar = GetTarget(); + if(tar && IsFearSpell(spell_to_cast)) + { + if(!IsBardSong(spell_to_cast)) + { + SetRunAnimSpeed(0); + SendPosition(); + SetMoving(false); + } + CastSpell(spell_to_cast, tar->GetID(), slot_to_use); + return; + } + } + } + else + { + Mob *tar = GetTarget(); + if(tar) + { + if(!IsBardSong(spell_to_cast)) + { + SetRunAnimSpeed(0); + SendPosition(); + SetMoving(false); + } + CastSpell(spell_to_cast, tar->GetID(), slot_to_use); + return; + } + } + + +} + +void Client::AI_Process() +{ + if (!IsAIControlled()) + return; + + if (!(AIthink_timer->Check() || attack_timer.Check(false))) + return; + + if (IsCasting()) + return; + + bool engaged = IsEngaged(); + + Mob *ow = GetOwner(); + if(!engaged) + { + if(ow) + { + if(ow->IsEngaged()) + { + Mob *tar = ow->GetTarget(); + if(tar) + { + AddToHateList(tar, 1, 0, false); + } + } + } + } + + if(!ow) + { + if(!IsFeared() && !IsLD()) + { + BuffFadeByEffect(SE_Charm); + return; + } + } + + if(RuleB(Combat, EnableFearPathing)){ + if(curfp) { + if(IsRooted()) { + //make sure everybody knows were not moving, for appearance sake + if(IsMoving()) + { + if(GetTarget()) + SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); + SetRunAnimSpeed(0); + SendPosition(); + SetMoving(false); + moved=false; + } + //continue on to attack code, ensuring that we execute the engaged code + engaged = true; + } else { + if(AImovement_timer->Check()) { + animation = GetRunspeed() * 21; + // Check if we have reached the last fear point + if((ABS(GetX()-fear_walkto_x) < 0.1) && (ABS(GetY()-fear_walkto_y) <0.1)) { + // Calculate a new point to run to + CalculateNewFearpoint(); + } + if(!RuleB(Pathing, Fear) || !zone->pathing) + CalculateNewPosition2(fear_walkto_x, fear_walkto_y, fear_walkto_z, GetFearSpeed(), true); + else + { + bool WaypointChanged, NodeReached; + + VERTEX Goal = UpdatePath(fear_walkto_x, fear_walkto_y, fear_walkto_z, + GetFearSpeed(), WaypointChanged, NodeReached); + + if(WaypointChanged) + tar_ndx = 20; + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetFearSpeed()); + } + } + return; + } + } + } + + if (engaged) + { + if (IsRooted()) + SetTarget(hate_list.GetClosest(this)); + else + { + if(AItarget_check_timer->Check()) + { + SetTarget(hate_list.GetTop(this)); + } + } + + if (!GetTarget()) + return; + + if (GetTarget()->IsCorpse()) { + RemoveFromHateList(this); + return; + } + + if(DivineAura()) + return; + + bool is_combat_range = CombatRange(GetTarget()); + + if(is_combat_range) { + if(charm_class_attacks_timer.Check()) { + DoClassAttacks(GetTarget()); + } + + if (AImovement_timer->Check()) { + SetRunAnimSpeed(0); + } + if(IsMoving()) { + SetMoving(false); + moved=false; + SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); + SendPosition(); + tar_ndx =0; + } + + if(GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) { + if(attack_timer.Check()) { + Attack(GetTarget(), 13); + if(GetTarget()) { + if(CheckDoubleAttack()) { + Attack(GetTarget(), 13); + if(GetTarget()) { + bool triple_attack_success = false; + if((((GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER) + && GetLevel() >= 60) || GetSpecialAbility(SPECATK_TRIPLE)) + && CheckDoubleAttack(true)) + { + Attack(GetTarget(), 13, true); + triple_attack_success = true; + } + + if(GetTarget()) + { + //Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). + int16 flurrychance = aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance; + + if (flurrychance) + { + if(MakeRandomInt(0, 100) < flurrychance) + { + Message_StringID(MT_NPCFlurry, YOU_FLURRY); + Attack(GetTarget(), 13, false); + Attack(GetTarget(), 13, false); + } + } + + int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance; + + if (ExtraAttackChanceBonus && GetTarget()) { + ItemInst *wpn = GetInv().GetItem(SLOT_PRIMARY); + if(wpn){ + if(wpn->GetItem()->ItemType == ItemType2HSlash || + wpn->GetItem()->ItemType == ItemType2HBlunt || + wpn->GetItem()->ItemType == ItemType2HPiercing ) + { + if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus) + { + Attack(GetTarget(), 13, false); + } + } + } + } + + if (GetClass() == WARRIOR || GetClass() == BERSERKER) + { + if(!dead && !berserk && this->GetHPRatio() < 30) + { + entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_START, GetName()); + berserk = true; + } + else if (berserk && this->GetHPRatio() > 30) + { + entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_END, GetName()); + berserk = false; + } + } + } + } + } + } + } + } + + if(CanThisClassDualWield() && attack_dw_timer.Check()) + { + if(GetTarget()) + { + float DualWieldProbability = 0.0f; + + int16 Ambidexterity = aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity; + DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f; // 78.0 max + int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance; + DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f; + + if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability) + { + Attack(GetTarget(), 14); + if(CheckDoubleAttack()) + { + Attack(GetTarget(), 14); + } + + } + } + } + } + else + { + if(!IsRooted()) + { + animation = 21 * GetRunspeed(); + if(!RuleB(Pathing, Aggro) || !zone->pathing) + CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed()); + else + { + bool WaypointChanged, NodeReached; + VERTEX Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), + GetRunspeed(), WaypointChanged, NodeReached); + + if(WaypointChanged) + tar_ndx = 20; + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); + } + } + else if(IsMoving()) + { + SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); + SetRunAnimSpeed(0); + SendPosition(); + SetMoving(false); + moved=false; + } + } + AI_SpellCast(); + } + else + { + if(AIfeignremember_timer->Check()) { + std::set::iterator RememberedCharID; + RememberedCharID = feign_memory_list.begin(); + while (RememberedCharID != feign_memory_list.end()) { + Client* remember_client = entity_list.GetClientByCharID(*RememberedCharID); + if (remember_client == nullptr) { + //they are gone now... + RememberedCharID = feign_memory_list.erase(RememberedCharID); + } else if (!remember_client->GetFeigned()) { + AddToHateList(remember_client->CastToMob(),1); + RememberedCharID = feign_memory_list.erase(RememberedCharID); + break; + } else { + //they are still feigned, carry on... + ++RememberedCharID; + } + } + } + + if(IsPet()) + { + Mob* owner = GetOwner(); + if(owner == nullptr) + return; + + float dist = DistNoRoot(*owner); + if (dist >= 100) + { + float speed = dist >= 225 ? GetRunspeed() : GetWalkspeed(); + animation = 21 * speed; + CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); + } + else + { + SetHeading(owner->GetHeading()); + if(moved) + { + moved=false; + SetMoving(false); + SendPosition(); + SetRunAnimSpeed(0); + } + } + } + } +} + +void Mob::AI_Process() { + if (!IsAIControlled()) + return; + + if (!(AIthink_timer->Check() || attack_timer.Check(false))) + return; + + if (IsCasting()) + return; + + bool engaged = IsEngaged(); + bool doranged = false; + + // Begin: Additions for Wiz Fear Code + // + if(RuleB(Combat, EnableFearPathing)){ + if(curfp) { + if(IsRooted()) { + //make sure everybody knows were not moving, for appearance sake + if(IsMoving()) + { + if(target) + SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); + SetRunAnimSpeed(0); + SendPosition(); + SetMoving(false); + moved=false; + } + //continue on to attack code, ensuring that we execute the engaged code + engaged = true; + } else { + if(AImovement_timer->Check()) { + // Check if we have reached the last fear point + if((ABS(GetX()-fear_walkto_x) < 0.1) && (ABS(GetY()-fear_walkto_y) <0.1)) { + // Calculate a new point to run to + CalculateNewFearpoint(); + } + if(!RuleB(Pathing, Fear) || !zone->pathing) + CalculateNewPosition2(fear_walkto_x, fear_walkto_y, fear_walkto_z, GetFearSpeed(), true); + else + { + bool WaypointChanged, NodeReached; + + VERTEX Goal = UpdatePath(fear_walkto_x, fear_walkto_y, fear_walkto_z, + GetFearSpeed(), WaypointChanged, NodeReached); + + if(WaypointChanged) + tar_ndx = 20; + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetFearSpeed()); + } + } + return; + } + } + } + + // trigger EVENT_SIGNAL if required + if(IsNPC()) { + CastToNPC()->CheckSignal(); + } + + if (engaged) + { + if (IsRooted()) + SetTarget(hate_list.GetClosest(this)); + else + { + if(AItarget_check_timer->Check()) + { + if (IsFocused()) { + if (!target) { + SetTarget(hate_list.GetTop(this)); + } + } else { + if (!ImprovedTaunt()) + SetTarget(hate_list.GetTop(this)); + } + + } + } + + if (!target) + return; + + if (target->IsCorpse()) + { + RemoveFromHateList(this); + return; + } + +#ifdef BOTS + if (IsPet() && GetOwner()->IsBot() && target == GetOwner()) + { + // this blocks all pet attacks against owner..bot pet test (copied above check) + RemoveFromHateList(this); + return; + } +#endif //BOTS + + if(DivineAura()) + return; + + if(GetSpecialAbility(TETHER)) { + float tether_range = static_cast(GetSpecialAbilityParam(TETHER, 0)); + tether_range = tether_range > 0.0f ? tether_range * tether_range : pAggroRange * pAggroRange; + + if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > tether_range) { + GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH()); + } + } else if(GetSpecialAbility(LEASH)) { + float leash_range = static_cast(GetSpecialAbilityParam(LEASH, 0)); + leash_range = leash_range > 0.0f ? leash_range * leash_range : pAggroRange * pAggroRange; + + if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > leash_range) { + GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH()); + SetHP(GetMaxHP()); + BuffFadeAll(); + WipeHateList(); + return; + } + } + + StartEnrage(); + + bool is_combat_range = CombatRange(target); + + if (is_combat_range) + { + if (AImovement_timer->Check()) + { + SetRunAnimSpeed(0); + } + if(IsMoving()) + { + SetMoving(false); + moved=false; + SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); + SendPosition(); + tar_ndx =0; + } + + //casting checked above... + if(target && !IsStunned() && !IsMezzed() && GetAppearance() != eaDead && !IsMeleeDisabled()) { + + //we should check to see if they die mid-attacks, previous + //crap of checking target for null was not gunna cut it + + //try main hand first + if(attack_timer.Check()) { + if(IsNPC()) { + int16 n_atk = CastToNPC()->GetNumberOfAttacks(); + if(n_atk <= 1) { + Attack(target, 13); + } else { + for(int i = 0; i < n_atk; ++i) { + Attack(target, 13); + } + } + } else { + Attack(target, 13); + } + + if (target) { + //we use this random value in three comparisons with different + //thresholds, and if its truely random, then this should work + //out reasonably and will save us compute resources. + int32 RandRoll = MakeRandomInt(0, 99); + if ((CanThisClassDoubleAttack() || GetSpecialAbility(SPECATK_TRIPLE) + || GetSpecialAbility(SPECATK_QUAD)) + //check double attack, this is NOT the same rules that clients use... + && RandRoll < (GetLevel() + NPCDualAttackModifier)) { + Attack(target, 13); + // lets see if we can do a triple attack with the main hand + //pets are excluded from triple and quads... + if ((GetSpecialAbility(SPECATK_TRIPLE) || GetSpecialAbility(SPECATK_QUAD)) + && !IsPet() && RandRoll < (GetLevel() + NPCTripleAttackModifier)) { + Attack(target, 13); + // now lets check the quad attack + if (GetSpecialAbility(SPECATK_QUAD) + && RandRoll < (GetLevel() + NPCQuadAttackModifier)) { + Attack(target, 13); + } + } + } + } + + if (GetSpecialAbility(SPECATK_FLURRY)) { + int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0); + flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance); + + if (MakeRandomInt(0, 99) < flurry_chance) { + ExtraAttackOptions opts; + int cur = GetSpecialAbilityParam(SPECATK_FLURRY, 2); + if (cur > 0) + opts.damage_percent = cur / 100.0f; + + cur = GetSpecialAbilityParam(SPECATK_FLURRY, 3); + if (cur > 0) + opts.damage_flat = cur; + + cur = GetSpecialAbilityParam(SPECATK_FLURRY, 4); + if (cur > 0) + opts.armor_pen_percent = cur / 100.0f; + + cur = GetSpecialAbilityParam(SPECATK_FLURRY, 5); + if (cur > 0) + opts.armor_pen_flat = cur; + + cur = GetSpecialAbilityParam(SPECATK_FLURRY, 6); + if (cur > 0) + opts.crit_percent = cur / 100.0f; + + cur = GetSpecialAbilityParam(SPECATK_FLURRY, 7); + if (cur > 0) + opts.crit_flat = cur; + + Flurry(&opts); + } + } + + if (IsPet()) { + Mob *owner = GetOwner(); + if (owner) { + int16 flurry_chance = owner->aabonuses.PetFlurry + + owner->spellbonuses.PetFlurry + owner->itembonuses.PetFlurry; + if (flurry_chance && (MakeRandomInt(0, 99) < flurry_chance)) + Flurry(nullptr); + } + } + + if (GetSpecialAbility(SPECATK_RAMPAGE)) + { + int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0); + rampage_chance = rampage_chance > 0 ? rampage_chance : 20; + if(MakeRandomInt(0, 99) < rampage_chance) { + ExtraAttackOptions opts; + int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2); + if(cur > 0) { + opts.damage_percent = cur / 100.0f; + } + + cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 3); + if(cur > 0) { + opts.damage_flat = cur; + } + + cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 4); + if(cur > 0) { + opts.armor_pen_percent = cur / 100.0f; + } + + cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 5); + if(cur > 0) { + opts.armor_pen_flat = cur; + } + + cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 6); + if(cur > 0) { + opts.crit_percent = cur / 100.0f; + } + + cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 7); + if(cur > 0) { + opts.crit_flat = cur; + } + Rampage(&opts); + } + } + + if (GetSpecialAbility(SPECATK_AREA_RAMPAGE)) + { + int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0); + rampage_chance = rampage_chance > 0 ? rampage_chance : 20; + if(MakeRandomInt(0, 99) < rampage_chance) { + ExtraAttackOptions opts; + int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2); + if(cur > 0) { + opts.damage_percent = cur / 100.0f; + } + + cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 3); + if(cur > 0) { + opts.damage_flat = cur; + } + + cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 4); + if(cur > 0) { + opts.armor_pen_percent = cur / 100.0f; + } + + cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 5); + if(cur > 0) { + opts.armor_pen_flat = cur; + } + + cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 6); + if(cur > 0) { + opts.crit_percent = cur / 100.0f; + } + + cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 7); + if(cur > 0) { + opts.crit_flat = cur; + } + + AreaRampage(&opts); + } + } + } + + //now off hand + if (attack_dw_timer.Check() && CanThisClassDualWield()) + { + int myclass = GetClass(); + //can only dual wield without a weapon if your a monk + if(GetSpecialAbility(SPECATK_INNATE_DW) || (GetEquipment(MaterialSecondary) != 0 && GetLevel() > 29) || myclass == MONK || myclass == MONKGM) { + float DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel()) / 400.0f; + if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability) + { + Attack(target, 14); + if (CanThisClassDoubleAttack()) + { + int32 RandRoll = MakeRandomInt(0, 99); + if (RandRoll < (GetLevel() + 20)) + { + Attack(target, 14); + } + } + } + } + } + + //now special attacks (kick, etc) + if(IsNPC()) + CastToNPC()->DoClassAttacks(target); + } + AI_EngagedCastCheck(); + } //end is within combat range + else { + //we cannot reach our target... + //underwater stuff only works with water maps in the zone! + if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { + if(!zone->watermap->InLiquid(target->GetX(), target->GetY(), target->GetZ())) { + Mob *tar = hate_list.GetTop(this); + if(tar == target) { + WipeHateList(); + Heal(); + BuffFadeAll(); + AIwalking_timer->Start(100); + pLastFightingDelayMoving = Timer::GetCurrentTime(); + return; + } else if(tar != nullptr) { + SetTarget(tar); + return; + } + } + } + + // See if we can summon the mob to us + if (!HateSummon()) + { + //could not summon them, check ranged... + if(GetSpecialAbility(SPECATK_RANGED_ATK)) + doranged = true; + + // Now pursue + // TODO: Check here for another person on hate list with close hate value + if(AI_PursueCastCheck()){ + //we did something, so do not process movement. + } + else if (AImovement_timer->Check()) + { + if(!IsRooted()) { + mlog(AI__WAYPOINTS, "Pursuing %s while engaged.", target->GetName()); + if(!RuleB(Pathing, Aggro) || !zone->pathing) + CalculateNewPosition2(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed()); + else + { + bool WaypointChanged, NodeReached; + + VERTEX Goal = UpdatePath(target->GetX(), target->GetY(), target->GetZ(), + GetRunspeed(), WaypointChanged, NodeReached); + + if(WaypointChanged) + tar_ndx = 20; + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); + } + + } + else if(IsMoving()) { + SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); + SetRunAnimSpeed(0); + SendPosition(); + SetMoving(false); + moved=false; + + } + } + } + } + } + else + { + if(AIfeignremember_timer->Check()) { + // EverHood - 6/14/06 + // Improved Feign Death Memory + // check to see if any of our previous feigned targets have gotten up. + std::set::iterator RememberedCharID; + RememberedCharID = feign_memory_list.begin(); + while (RememberedCharID != feign_memory_list.end()) { + Client* remember_client = entity_list.GetClientByCharID(*RememberedCharID); + if (remember_client == nullptr) { + //they are gone now... + RememberedCharID = feign_memory_list.erase(RememberedCharID); + } else if (!remember_client->GetFeigned()) { + AddToHateList(remember_client->CastToMob(),1); + RememberedCharID = feign_memory_list.erase(RememberedCharID); + break; + } else { + //they are still feigned, carry on... + ++RememberedCharID; + } + } + } + if (AI_IdleCastCheck()) + { + //we processed a spell action, so do nothing else. + } + else if (AIscanarea_timer->Check()) + { + /* + * This is where NPCs look around to see if they want to attack anybody. + * + * if REVERSE_AGGRO is enabled, then this timer is disabled unless they + * have the npc_aggro flag on them, and aggro against clients is checked + * by the clients. + * + */ + + Mob* tmptar = entity_list.AICheckCloseAggro(this, GetAggroRange(), GetAssistRange()); + if (tmptar) + AddToHateList(tmptar); + } + else if (AImovement_timer->Check() && !IsRooted()) + { + SetRunAnimSpeed(0); + if (IsPet()) + { + // we're a pet, do as we're told + switch (pStandingPetOrder) + { + case SPO_Follow: + { + + Mob* owner = GetOwner(); + if(owner == nullptr) + break; + + //if(owner->IsClient()) + // printf("Pet start pos: (%f, %f, %f)\n", GetX(), GetY(), GetZ()); + + float dist = DistNoRoot(*owner); + if (dist >= 400) + { + float speed = GetWalkspeed(); + if (dist >= 5625) + speed = GetRunspeed(); + CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); + } + else + { + if(moved) + { + moved=false; + SetMoving(false); + SendPosition(); + } + } + + /* + //fix up Z + float zdiff = GetZ() - owner->GetZ(); + if(zdiff < 0) + zdiff = 0 - zdiff; + if(zdiff > 2.0f) { + SendTo(GetX(), GetY(), owner->GetZ()); + SendPosition(); + } + + if(owner->IsClient()) + printf("Pet pos: (%f, %f, %f)\n", GetX(), GetY(), GetZ()); + */ + + break; + } + case SPO_Sit: + { + SetAppearance(eaSitting, false); + break; + } + case SPO_Guard: + { + //only NPCs can guard stuff. (forced by where the guard movement code is in the AI) + if(IsNPC()) { + CastToNPC()->NextGuardPosition(); + } + break; + } + } + } + else if (GetFollowID()) + { + Mob* follow = entity_list.GetMob(GetFollowID()); + if (!follow) SetFollowID(0); + else + { + float dist2 = DistNoRoot(*follow); + int followdist = GetFollowDistance(); + + if (dist2 >= followdist) // Default follow distance is 100 + { + float speed = GetWalkspeed(); + if (dist2 >= followdist + 150) + speed = GetRunspeed(); + CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); + } + else + { + if(moved) + { + SendPosition(); + moved=false; + SetMoving(false); + } + } + } + } + else //not a pet, and not following somebody... + { + // dont move till a bit after you last fought + if (pLastFightingDelayMoving < Timer::GetCurrentTime()) + { + if (this->IsClient()) + { + // LD timer expired, drop out of world + if (this->CastToClient()->IsLD()) + this->CastToClient()->Disconnect(); + return; + } + + if(IsNPC()) + { + if(RuleB(NPC, SmartLastFightingDelayMoving) && !feign_memory_list.empty()) + { + minLastFightingDelayMoving = 0; + maxLastFightingDelayMoving = 0; + } + CastToNPC()->AI_DoMovement(); + } + } + + } + } // else if (AImovement_timer->Check()) + } + + //Do Ranged attack here + if(doranged) + { + int attacks = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0); + attacks = attacks > 0 ? attacks : 1; + for(int i = 0; i < attacks; ++i) { + RangedAttack(target); + } + } +} + +void NPC::AI_DoMovement() { + float walksp = GetMovespeed(); + if(walksp <= 0.0f) + return; //this is idle movement at walk speed, and we are unable to walk right now. + + if (roambox_distance > 0) { + if ( + roambox_movingto_x > roambox_max_x + || roambox_movingto_x < roambox_min_x + || roambox_movingto_y > roambox_max_y + || roambox_movingto_y < roambox_min_y + ) + { + float movedist = roambox_distance*roambox_distance; + float movex = MakeRandomFloat(0, movedist); + float movey = movedist - movex; + movex = sqrtf(movex); + movey = sqrtf(movey); + movex *= MakeRandomInt(0, 1) ? 1 : -1; + movey *= MakeRandomInt(0, 1) ? 1 : -1; + roambox_movingto_x = GetX() + movex; + roambox_movingto_y = GetY() + movey; + //Try to calculate new coord using distance. + if (roambox_movingto_x > roambox_max_x || roambox_movingto_x < roambox_min_x) + roambox_movingto_x -= movex * 2; + if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y) + roambox_movingto_y -= movey * 2; + //New coord is still invalid, ignore distance and just pick a new random coord. + //If we're here we may have a roambox where one side is shorter than the specified distance. Commons, Wkarana, etc. + if (roambox_movingto_x > roambox_max_x || roambox_movingto_x < roambox_min_x) + roambox_movingto_x = MakeRandomFloat(roambox_min_x+1,roambox_max_x-1); + if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y) + roambox_movingto_y = MakeRandomFloat(roambox_min_y+1,roambox_max_y-1); + } + + mlog(AI__WAYPOINTS, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)", + roambox_distance, roambox_min_x, roambox_max_x, roambox_min_y, roambox_max_y, roambox_movingto_x, roambox_movingto_y); + if (!CalculateNewPosition2(roambox_movingto_x, roambox_movingto_y, GetZ(), walksp, true)) + { + roambox_movingto_x = roambox_max_x + 1; // force update + pLastFightingDelayMoving = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay); + SetMoving(false); + SendPosition(); // makes mobs stop clientside + } + } + else if (roamer) + { + if (AIwalking_timer->Check()) + { + movetimercompleted=true; + AIwalking_timer->Disable(); + } + + + int16 gridno = CastToNPC()->GetGrid(); + + if (gridno > 0 || cur_wp==-2) { + if (movetimercompleted==true) { // time to pause at wp is over + + int32 spawn_id = this->GetSpawnPointID(); + LinkedListIterator iterator(zone->spawn2_list); + iterator.Reset(); + Spawn2 *found_spawn = nullptr; + + while(iterator.MoreElements()) + { + Spawn2* cur = iterator.GetData(); + iterator.Advance(); + if(cur->GetID() == spawn_id) + { + found_spawn = cur; + break; + } + } + + if (wandertype == 4 && cur_wp == CastToNPC()->GetMaxWp()) { + CastToNPC()->Depop(true); //depop and resart spawn timer + if(found_spawn) + found_spawn->SetNPCPointerNull(); + } + else if (wandertype == 6 && cur_wp == CastToNPC()->GetMaxWp()) { + CastToNPC()->Depop(false);//depop without spawn timer + if(found_spawn) + found_spawn->SetNPCPointerNull(); + } + else { + movetimercompleted=false; + + mlog(QUESTS__PATHING, "We are departing waypoint %d.", cur_wp); + + //if we were under quest control (with no grid), we are done now.. + if(cur_wp == -2) { + mlog(QUESTS__PATHING, "Non-grid quest mob has reached its quest ordered waypoint. Leaving pathing mode."); + roamer = false; + cur_wp = 0; + } + + if(GetAppearance() != eaStanding) + SetAppearance(eaStanding, false); + + entity_list.OpenDoorsNear(CastToNPC()); + + if(!DistractedFromGrid) { + //kick off event_waypoint depart + char temp[16]; + sprintf(temp, "%d", cur_wp); + parse->EventNPC(EVENT_WAYPOINT_DEPART, CastToNPC(), nullptr, temp, 0); + + //setup our next waypoint, if we are still on our normal grid + //remember that the quest event above could have done anything it wanted with our grid + if(gridno > 0) { + CastToNPC()->CalculateNewWaypoint(); + } + } + else { + DistractedFromGrid = false; + } + } + } // endif (movetimercompleted==true) + else if (!(AIwalking_timer->Enabled())) + { // currently moving + if (cur_wp_x == GetX() && cur_wp_y == GetY()) + { // are we there yet? then stop + mlog(AI__WAYPOINTS, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid()); + SetWaypointPause(); + if(GetAppearance() != eaStanding) + SetAppearance(eaStanding, false); + SetMoving(false); + if (cur_wp_heading >= 0.0) { + SetHeading(cur_wp_heading); + } + SendPosition(); + + //kick off event_waypoint arrive + char temp[16]; + sprintf(temp, "%d", cur_wp); + parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0); + + // wipe feign memory since we reached our first waypoint + if(cur_wp == 1) + ClearFeignMemory(); + } + else + { // not at waypoint yet, so keep moving + if(!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0)) + CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, walksp, true); + else + { + bool WaypointChanged; + bool NodeReached; + VERTEX Goal = UpdatePath(cur_wp_x, cur_wp_y, cur_wp_z, walksp, WaypointChanged, NodeReached); + if(WaypointChanged) + tar_ndx = 20; + + if(NodeReached) + entity_list.OpenDoorsNear(CastToNPC()); + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, walksp, true); + } + + } + } + } // endif (gridno > 0) +// handle new quest grid command processing + else if (gridno < 0) + { // this mob is under quest control + if (movetimercompleted==true) + { // time to pause has ended + SetGrid( 0 - GetGrid()); // revert to AI control + mlog(QUESTS__PATHING, "Quest pathing is finished. Resuming on grid %d", GetGrid()); + + if(GetAppearance() != eaStanding) + SetAppearance(eaStanding, false); + + CalculateNewWaypoint(); + } + } + + } + else if (IsGuarding()) + { + bool CP2Moved; + if(!RuleB(Pathing, Guard) || !zone->pathing) + CP2Moved = CalculateNewPosition2(guard_x, guard_y, guard_z, walksp); + else + { + if(!((x_pos == guard_x) && (y_pos == guard_y) && (z_pos == guard_z))) + { + bool WaypointChanged, NodeReached; + VERTEX Goal = UpdatePath(guard_x, guard_y, guard_z, walksp, WaypointChanged, NodeReached); + if(WaypointChanged) + tar_ndx = 20; + + if(NodeReached) + entity_list.OpenDoorsNear(CastToNPC()); + + CP2Moved = CalculateNewPosition2(Goal.x, Goal.y, Goal.z, walksp); + } + else + CP2Moved = false; + + } + if (!CP2Moved) + { + if(moved) { + mlog(AI__WAYPOINTS, "Reached guard point (%.3f,%.3f,%.3f)", guard_x, guard_y, guard_z); + ClearFeignMemory(); + moved=false; + SetMoving(false); + if (GetTarget() == nullptr || DistNoRoot(*GetTarget()) >= 5*5 ) + { + SetHeading(guard_heading); + } else { + FaceTarget(GetTarget()); + } + SendPosition(); + SetAppearance(GetGuardPointAnim()); + } + } + } +} + +// Note: Mob that caused this may not get added to the hate list until after this function call completes +void Mob::AI_Event_Engaged(Mob* attacker, bool iYellForHelp) { + if (!IsAIControlled()) + return; + + if(GetAppearance() != eaStanding) + { + SetAppearance(eaStanding); + } + + if (iYellForHelp) { + if(IsPet()) { + GetOwner()->AI_Event_Engaged(attacker, iYellForHelp); + } else { + entity_list.AIYellForHelp(this, attacker); + } + } + + if(IsNPC()) + { + if(CastToNPC()->GetGrid() > 0) + { + DistractedFromGrid = true; + } + if(attacker && !attacker->IsCorpse()) + { + //Because sometimes the AIYellForHelp triggers another engaged and then immediately a not engaged + //if the target dies before it goes off + if(attacker->GetHP() > 0) + { + if(!CastToNPC()->GetCombatEvent() && GetHP() > 0) + { + parse->EventNPC(EVENT_COMBAT, CastToNPC(), attacker, "1", 0); + uint16 emoteid = GetEmoteID(); + if(emoteid != 0) + CastToNPC()->DoNPCEmote(ENTERCOMBAT,emoteid); + CastToNPC()->SetCombatEvent(true); + } + } + } + } +} + +// Note: Hate list may not be actually clear until after this function call completes +void Mob::AI_Event_NoLongerEngaged() { + if (!IsAIControlled()) + return; + this->AIwalking_timer->Start(RandomTimer(3000,20000)); + pLastFightingDelayMoving = Timer::GetCurrentTime(); + if (minLastFightingDelayMoving == maxLastFightingDelayMoving) + pLastFightingDelayMoving += minLastFightingDelayMoving; + else + pLastFightingDelayMoving += MakeRandomInt(minLastFightingDelayMoving, maxLastFightingDelayMoving); + // EverHood - So mobs don't keep running as a ghost until AIwalking_timer fires + // if they were moving prior to losing all hate + if(IsMoving()){ + SetRunAnimSpeed(0); + SetMoving(false); + SendPosition(); + } + ClearRampage(); + + if(IsNPC()) + { + if(CastToNPC()->GetCombatEvent() && GetHP() > 0) + { + if(entity_list.GetNPCByID(this->GetID())) + { + uint16 emoteid = CastToNPC()->GetEmoteID(); + parse->EventNPC(EVENT_COMBAT, CastToNPC(), nullptr, "0", 0); + if(emoteid != 0) + CastToNPC()->DoNPCEmote(LEAVECOMBAT,emoteid); + CastToNPC()->SetCombatEvent(false); + } + } + } +} + +//this gets called from InterruptSpell() for failure or SpellFinished() for success +void NPC::AI_Event_SpellCastFinished(bool iCastSucceeded, uint8 slot) { + if (slot == 1) { + uint32 recovery_time = 0; + if (iCastSucceeded) { + if (casting_spell_AIindex < AIspells.size()) { + recovery_time += spells[AIspells[casting_spell_AIindex].spellid].recovery_time; + if (AIspells[casting_spell_AIindex].recast_delay >= 0) + { + if (AIspells[casting_spell_AIindex].recast_delay < 10000) + AIspells[casting_spell_AIindex].time_cancast = Timer::GetCurrentTime() + (AIspells[casting_spell_AIindex].recast_delay*1000); + } + else + AIspells[casting_spell_AIindex].time_cancast = Timer::GetCurrentTime() + spells[AIspells[casting_spell_AIindex].spellid].recast_time; + } + if (recovery_time < AIautocastspell_timer->GetSetAtTrigger()) + recovery_time = AIautocastspell_timer->GetSetAtTrigger(); + AIautocastspell_timer->Start(recovery_time, false); + } + else + AIautocastspell_timer->Start(800, false); + casting_spell_AIindex = AIspells.size(); + } +} + + +bool NPC::AI_EngagedCastCheck() { + if (AIautocastspell_timer->Check(false)) { + AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. + + mlog(AI__SPELLS, "Engaged autocast check triggered. Trying to cast healing spells then maybe offensive spells."); + Shout("KAYEN"); + // try casting a heal or gate + if (!AICastSpell(this, 100, SpellType_Heal | SpellType_Escape | SpellType_InCombatBuff)) { + // try casting a heal on nearby + if (!entity_list.AICheckCloseBeneficialSpells(this, 25, MobAISpellRange, SpellType_Heal)) { + //nobody to heal, try some detrimental spells. + if(!AICastSpell(GetTarget(), 20, SpellType_Nuke | SpellType_Lifetap | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff | SpellType_Charm | SpellType_Root)) { + //no spell to cast, try again soon. + AIautocastspell_timer->Start(RandomTimer(500, 1000), false); + } + } + } + return(true); + } + + return(false); +} + +bool NPC::AI_PursueCastCheck() { + if (AIautocastspell_timer->Check(false)) { + AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. + + mlog(AI__SPELLS, "Engaged (pursuing) autocast check triggered. Trying to cast offensive spells."); + if(!AICastSpell(GetTarget(), 90, SpellType_Root | SpellType_Nuke | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff)) { + //no spell cast, try again soon. + AIautocastspell_timer->Start(RandomTimer(500, 2000), false); + } //else, spell casting finishing will reset the timer. + return(true); + } + return(false); +} + +bool NPC::AI_IdleCastCheck() { + if (AIautocastspell_timer->Check(false)) { +#if MobAI_DEBUG_Spells >= 25 + std::cout << "Non-Engaged autocast check triggered: " << this->GetName() << std::endl; +#endif + AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. + if (!AICastSpell(this, 100, SpellType_Heal | SpellType_Buff | SpellType_Pet)) { + if(!entity_list.AICheckCloseBeneficialSpells(this, 33, MobAISpellRange, SpellType_Heal | SpellType_Buff)) { + //if we didnt cast any spells, our autocast timer just resets to the + //last duration it was set to... try to put up a more reasonable timer... + AIautocastspell_timer->Start(RandomTimer(1000, 5000), false); + } //else, spell casting finishing will reset the timer. + } //else, spell casting finishing will reset the timer. + return(true); + } + return(false); +} + +void Mob::StartEnrage() +{ + // dont continue if already enraged + if (bEnraged) + return; + + if(!GetSpecialAbility(SPECATK_ENRAGE)) + return; + + int hp_ratio = GetSpecialAbilityParam(SPECATK_ENRAGE, 0); + hp_ratio = hp_ratio > 0 ? hp_ratio : RuleI(NPC, StartEnrageValue); + if(GetHPRatio() > static_cast(hp_ratio)) { + return; + } + + if(RuleB(NPC, LiveLikeEnrage) && !((IsPet() && !IsCharmed() && GetOwner() && GetOwner()->IsClient()) || + (CastToNPC()->GetSwarmOwner() && entity_list.GetMob(CastToNPC()->GetSwarmOwner())->IsClient()))) { + return; + } + + Timer *timer = GetSpecialAbilityTimer(SPECATK_ENRAGE); + if (timer && !timer->Check()) + return; + + int enraged_duration = GetSpecialAbilityParam(SPECATK_ENRAGE, 1); + enraged_duration = enraged_duration > 0 ? enraged_duration : EnragedDurationTimer; + StartSpecialAbilityTimer(SPECATK_ENRAGE, enraged_duration); + + // start the timer. need to call IsEnraged frequently since we dont have callback timers :-/ + bEnraged = true; + entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_START, GetCleanName()); +} + +void Mob::ProcessEnrage(){ + if(IsEnraged()){ + Timer *timer = GetSpecialAbilityTimer(SPECATK_ENRAGE); + if(timer && timer->Check()){ + entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_END, GetCleanName()); + + int enraged_cooldown = GetSpecialAbilityParam(SPECATK_ENRAGE, 2); + enraged_cooldown = enraged_cooldown > 0 ? enraged_cooldown : EnragedTimer; + StartSpecialAbilityTimer(SPECATK_ENRAGE, enraged_cooldown); + bEnraged = false; + } + } +} + +bool Mob::IsEnraged() +{ + return bEnraged; +} + +bool Mob::Flurry(ExtraAttackOptions *opts) +{ + // this is wrong, flurry is extra attacks on the current target + Mob *target = GetTarget(); + if (target) { + if (!IsPet()) { + entity_list.MessageClose_StringID(this, true, 200, MT_NPCFlurry, NPC_FLURRY, GetCleanName(), target->GetCleanName()); + } else { + entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, NPC_FLURRY, GetCleanName(), target->GetCleanName()); + } + + int num_attacks = GetSpecialAbilityParam(SPECATK_FLURRY, 1); + num_attacks = num_attacks > 0 ? num_attacks : RuleI(Combat, MaxFlurryHits); + for (int i = 0; i < num_attacks; i++) + Attack(target, 13, false, false, false, opts); + } + return true; +} + +bool Mob::AddRampage(Mob *mob) +{ + if (!mob) + return false; + + if (!GetSpecialAbility(SPECATK_RAMPAGE)) + return false; + + for (int i = 0; i < RampageArray.size(); i++) { + // if Entity ID is already on the list don't add it again + if (mob->GetID() == RampageArray[i]) + return false; + } + RampageArray.push_back(mob->GetID()); + return true; +} + +void Mob::ClearRampage() +{ + RampageArray.clear(); +} + +bool Mob::Rampage(ExtraAttackOptions *opts) +{ + int index_hit = 0; + if (!IsPet()) + entity_list.MessageClose_StringID(this, true, 200, MT_NPCRampage, NPC_RAMPAGE, GetCleanName()); + else + entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, NPC_RAMPAGE, GetCleanName()); + + int rampage_targets = GetSpecialAbilityParam(SPECATK_RAMPAGE, 1); + if (rampage_targets == 0) // if set to 0 or not set in the DB + rampage_targets = RuleI(Combat, DefaultRampageTargets); + if (rampage_targets > RuleI(Combat, MaxRampageTargets)) + rampage_targets = RuleI(Combat, MaxRampageTargets); + for (int i = 0; i < RampageArray.size(); i++) { + if (index_hit >= rampage_targets) + break; + // range is important + Mob *m_target = entity_list.GetMob(RampageArray[i]); + if (m_target) { + if (m_target == GetTarget()) + continue; + if (CombatRange(m_target)) { + Attack(m_target, 13, false, false, false, opts); + index_hit++; + } + } + } + + if (RuleB(Combat, RampageHitsTarget) && index_hit < rampage_targets) + Attack(GetTarget(), 13, false, false, false, opts); + + return true; +} + +void Mob::AreaRampage(ExtraAttackOptions *opts) +{ + int index_hit = 0; + if (!IsPet()) { // do not know every pet AA so thought it safer to add this + entity_list.MessageClose_StringID(this, true, 200, MT_NPCRampage, AE_RAMPAGE, GetCleanName()); + } else { + entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, AE_RAMPAGE, GetCleanName()); + } + + int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1); + rampage_targets = rampage_targets > 0 ? rampage_targets : 1; + index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts); + + if(index_hit == 0) { + Attack(GetTarget(), 13, false, false, false, opts); + } +} + +uint32 Mob::GetLevelCon(uint8 mylevel, uint8 iOtherLevel) { + int16 diff = iOtherLevel - mylevel; + uint32 conlevel=0; + + if (diff == 0) + return CON_WHITE; + else if (diff >= 1 && diff <= 2) + return CON_YELLOW; + else if (diff >= 3) + return CON_RED; + + if (mylevel <= 8) + { + if (diff <= -4) + conlevel = CON_GREEN; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 9) + { + if (diff <= -6) + conlevel = CON_GREEN; + else if (diff <= -4) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 13) + { + if (diff <= -7) + conlevel = CON_GREEN; + else if (diff <= -5) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 15) + { + if (diff <= -7) + conlevel = CON_GREEN; + else if (diff <= -5) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 17) + { + if (diff <= -8) + conlevel = CON_GREEN; + else if (diff <= -6) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 21) + { + if (diff <= -9) + conlevel = CON_GREEN; + else if (diff <= -7) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 25) + { + if (diff <= -10) + conlevel = CON_GREEN; + else if (diff <= -8) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 29) + { + if (diff <= -11) + conlevel = CON_GREEN; + else if (diff <= -9) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 31) + { + if (diff <= -12) + conlevel = CON_GREEN; + else if (diff <= -9) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 33) + { + if (diff <= -13) + conlevel = CON_GREEN; + else if (diff <= -10) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 37) + { + if (diff <= -14) + conlevel = CON_GREEN; + else if (diff <= -11) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 41) + { + if (diff <= -16) + conlevel = CON_GREEN; + else if (diff <= -12) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 45) + { + if (diff <= -17) + conlevel = CON_GREEN; + else if (diff <= -13) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 49) + { + if (diff <= -18) + conlevel = CON_GREEN; + else if (diff <= -14) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 53) + { + if (diff <= -19) + conlevel = CON_GREEN; + else if (diff <= -15) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else if (mylevel <= 55) + { + if (diff <= -20) + conlevel = CON_GREEN; + else if (diff <= -15) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + else + { + if (diff <= -21) + conlevel = CON_GREEN; + else if (diff <= -16) + conlevel = CON_LIGHTBLUE; + else + conlevel = CON_BLUE; + } + return conlevel; +} + +void NPC::CheckSignal() { + if (!signal_q.empty()) { + int signal_id = signal_q.front(); + signal_q.pop_front(); + char buf[32]; + snprintf(buf, 31, "%d", signal_id); + buf[31] = '\0'; + parse->EventNPC(EVENT_SIGNAL, this, nullptr, buf, 0); + } +} + + + +/* +alter table npc_types drop column usedspells; +alter table npc_types add column npc_spells_id int(11) unsigned not null default 0 after merchant_id; +Create Table npc_spells ( + id int(11) unsigned not null auto_increment primary key, + name tinytext, + parent_list int(11) unsigned not null default 0, + attack_proc smallint(5) not null default -1, + proc_chance tinyint(3) not null default 3 + ); +create table npc_spells_entries ( + id int(11) unsigned not null auto_increment primary key, + npc_spells_id int(11) not null, + spellid smallint(5) not null default 0, + type smallint(5) unsigned not null default 0, + minlevel tinyint(3) unsigned not null default 0, + maxlevel tinyint(3) unsigned not null default 255, + manacost smallint(5) not null default '-1', + recast_delay int(11) not null default '-1', + priority smallint(5) not null default 0, + index npc_spells_id (npc_spells_id) + ); +*/ + +bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID); +bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSpellEffectID, int32 base, int32 limit, int32 max); +bool Compare_AI_Spells(AISpells_Struct i, AISpells_Struct j); + +bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { + // ok, this function should load the list, and the parent list then shove them into the struct and sort + npc_spells_id = iDBSpellsID; + AIspells.clear(); + if (iDBSpellsID == 0) { + AIautocastspell_timer->Disable(); + return false; + } + DBnpcspells_Struct* spell_list = database.GetNPCSpells(iDBSpellsID); + if (!spell_list) { + AIautocastspell_timer->Disable(); + return false; + } + DBnpcspells_Struct* parentlist = database.GetNPCSpells(spell_list->parent_list); + uint32 i; +#if MobAI_DEBUG_Spells >= 10 + std::cout << "Loading NPCSpells onto " << this->GetName() << ": dbspellsid=" << iDBSpellsID; + if (spell_list) { + std::cout << " (found, " << spell_list->numentries << "), parentlist=" << spell_list->parent_list; + if (spell_list->parent_list) { + if (parentlist) { + std::cout << " (found, " << parentlist->numentries << ")"; + } + else + std::cout << " (not found)"; + } + } + else + std::cout << " (not found)"; + std::cout << std::endl; +#endif + int16 attack_proc_spell = -1; + int8 proc_chance = 3; + if (parentlist) { + attack_proc_spell = parentlist->attack_proc; + proc_chance = parentlist->proc_chance; + for (i=0; inumentries; i++) { + if (GetLevel() >= parentlist->entries[i].minlevel && GetLevel() <= parentlist->entries[i].maxlevel && parentlist->entries[i].spellid > 0) { + if (!IsSpellInList(spell_list, parentlist->entries[i].spellid)) + { + AddSpellToNPCList(parentlist->entries[i].priority, + parentlist->entries[i].spellid, parentlist->entries[i].type, + parentlist->entries[i].manacost, parentlist->entries[i].recast_delay, + parentlist->entries[i].resist_adjust); + } + } + } + } + if (spell_list->attack_proc >= 0) { + attack_proc_spell = spell_list->attack_proc; + proc_chance = spell_list->proc_chance; + } + for (i=0; inumentries; i++) { + if (GetLevel() >= spell_list->entries[i].minlevel && GetLevel() <= spell_list->entries[i].maxlevel && spell_list->entries[i].spellid > 0) { + AddSpellToNPCList(spell_list->entries[i].priority, + spell_list->entries[i].spellid, spell_list->entries[i].type, + spell_list->entries[i].manacost, spell_list->entries[i].recast_delay, + spell_list->entries[i].resist_adjust); + } + } + std::sort(AIspells.begin(), AIspells.end(), Compare_AI_Spells); + + if (attack_proc_spell > 0) + AddProcToWeapon(attack_proc_spell, true, proc_chance); + + if (AIspells.size() == 0) + AIautocastspell_timer->Disable(); + else + AIautocastspell_timer->Trigger(); + return true; +} + +bool NPC::AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID) { + + npc_spells_effects_id = iDBSpellsEffectsID; + AIspellsEffects.clear(); + + if (iDBSpellsEffectsID == 0) + return false; + + DBnpcspellseffects_Struct* spell_effects_list = database.GetNPCSpellsEffects(iDBSpellsEffectsID); + + if (!spell_effects_list) { + return false; + } + + DBnpcspellseffects_Struct* parentlist = database.GetNPCSpellsEffects(spell_effects_list->parent_list); + + uint32 i; +#if MobAI_DEBUG_Spells >= 10 + std::cout << "Loading NPCSpellsEffects onto " << this->GetName() << ": dbspellseffectsid=" << iDBSpellsEffectsID; + if (spell_effects_list) { + std::cout << " (found, " << spell_effects_list->numentries << "), parentlist=" << spell_effects)list->parent_list; + if (spell_effects_list->parent_list) { + if (parentlist) { + std::cout << " (found, " << parentlist->numentries << ")"; + } + else + std::cout << " (not found)"; + } + } + else + std::cout << " (not found)"; + std::cout << std::endl; +#endif + + if (parentlist) { + for (i=0; inumentries; i++) { + if (GetLevel() >= parentlist->entries[i].minlevel && GetLevel() <= parentlist->entries[i].maxlevel && parentlist->entries[i].spelleffectid > 0) { + if (!IsSpellEffectInList(spell_effects_list, parentlist->entries[i].spelleffectid, parentlist->entries[i].base, + parentlist->entries[i].limit, parentlist->entries[i].max)) + { + AddSpellEffectToNPCList(parentlist->entries[i].spelleffectid, + parentlist->entries[i].base, parentlist->entries[i].limit, + parentlist->entries[i].max); + } + } + } + } + + for (i=0; inumentries; i++) { + if (GetLevel() >= spell_effects_list->entries[i].minlevel && GetLevel() <= spell_effects_list->entries[i].maxlevel && spell_effects_list->entries[i].spelleffectid > 0) { + AddSpellEffectToNPCList(spell_effects_list->entries[i].spelleffectid, + spell_effects_list->entries[i].base, spell_effects_list->entries[i].limit, + spell_effects_list->entries[i].max); + } + } + + return true; +} + +void NPC::ApplyAISpellEffects(StatBonuses* newbon) +{ + if (!AI_HasSpellsEffects()) + return; + + + + for(int i=0; i < AIspellsEffects.size(); i++) + { + Shout("ApplyAISpellEffects %i %i %i %i", AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); + ApplySpellsBonuses(0, 0, newbon, 0, false, 0,-1, + true, AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); + } + + return; +} + +// adds a spell to the list, taking into account priority and resorting list as needed. +void NPC::AddSpellEffectToNPCList(uint16 iSpellEffectID, int32 base, int32 limit, int32 max) +{ + + if(!iSpellEffectID) + return; + + + HasAISpellEffects = true; + AISpellsEffects_Struct t; + + t.spelleffectid = iSpellEffectID; + t.base = base; + t.limit = limit; + t.max = max; + Shout("AddSpellEffectToNPCList %i %i %i %i", iSpellEffectID,base, limit, max ); + AIspellsEffects.push_back(t); +} + +bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSpellEffectID, int32 base, int32 limit, int32 max) { + for (uint32 i=0; i < spelleffect_list->numentries; i++) { + if (spelleffect_list->entries[i].spelleffectid == iSpellEffectID && spelleffect_list->entries[i].base == base + && spelleffect_list->entries[i].limit == limit && spelleffect_list->entries[i].max == max) + return true; + } + return false; +} + +bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID) { + for (uint32 i=0; i < spell_list->numentries; i++) { + if (spell_list->entries[i].spellid == iSpellID) + return true; + } + return false; +} + +bool Compare_AI_Spells(AISpells_Struct i, AISpells_Struct j) +{ + return(i.priority > j.priority); +} + +// adds a spell to the list, taking into account priority and resorting list as needed. +void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint16 iType, + int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust) +{ + + if(!IsValidSpell(iSpellID)) + return; + + HasAISpell = true; + AISpells_Struct t; + + t.priority = iPriority; + t.spellid = iSpellID; + t.type = iType; + t.manacost = iManaCost; + t.recast_delay = iRecastDelay; + t.time_cancast = 0; + t.resist_adjust = iResistAdjust; + + AIspells.push_back(t); +} + +void NPC::RemoveSpellFromNPCList(int16 spell_id) +{ + std::vector::iterator iter = AIspells.begin(); + while(iter != AIspells.end()) + { + if((*iter).spellid == spell_id) + { + iter = AIspells.erase(iter); + continue; + } + ++iter; + } +} + +void NPC::AISpellsList(Client *c) +{ + if (!c) + return; + + for (std::vector::iterator it = AIspells.begin(); it != AIspells.end(); ++it) + c->Message(0, "%s (%d): Type %d, Priority %d", + spells[it->spellid].name, it->spellid, it->type, it->priority); + + return; +} + +DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { + if (iDBSpellsID == 0) + return 0; + + if (!npc_spells_cache) { + npc_spells_maxid = GetMaxNPCSpellsID(); + npc_spells_cache = new DBnpcspells_Struct*[npc_spells_maxid+1]; + npc_spells_loadtried = new bool[npc_spells_maxid+1]; + for (uint32 i=0; i<=npc_spells_maxid; i++) { + npc_spells_cache[i] = 0; + npc_spells_loadtried[i] = false; + } + } + + if (iDBSpellsID > npc_spells_maxid) + return 0; + if (npc_spells_cache[iDBSpellsID]) { // it's in the cache, easy =) + return npc_spells_cache[iDBSpellsID]; + } + + else if (!npc_spells_loadtried[iDBSpellsID]) { // no reason to ask the DB again if we have failed once already + npc_spells_loadtried[iDBSpellsID] = true; + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list, attack_proc, proc_chance from npc_spells where id=%d", iDBSpellsID), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + uint32 tmpparent_list = atoi(row[1]); + int16 tmpattack_proc = atoi(row[2]); + uint8 tmpproc_chance = atoi(row[3]); + mysql_free_result(result); + if (RunQuery(query, MakeAnyLenString(&query, "SELECT spellid, type, minlevel, maxlevel, manacost, recast_delay, priority, resist_adjust from npc_spells_entries where npc_spells_id=%d ORDER BY minlevel", iDBSpellsID), errbuf, &result)) { + safe_delete_array(query); + uint32 tmpSize = sizeof(DBnpcspells_Struct) + (sizeof(DBnpcspells_entries_Struct) * mysql_num_rows(result)); + npc_spells_cache[iDBSpellsID] = (DBnpcspells_Struct*) new uchar[tmpSize]; + memset(npc_spells_cache[iDBSpellsID], 0, tmpSize); + npc_spells_cache[iDBSpellsID]->parent_list = tmpparent_list; + npc_spells_cache[iDBSpellsID]->attack_proc = tmpattack_proc; + npc_spells_cache[iDBSpellsID]->proc_chance = tmpproc_chance; + npc_spells_cache[iDBSpellsID]->numentries = mysql_num_rows(result); + int j = 0; + while ((row = mysql_fetch_row(result))) { + int spell_id = atoi(row[0]); + npc_spells_cache[iDBSpellsID]->entries[j].spellid = spell_id; + npc_spells_cache[iDBSpellsID]->entries[j].type = atoi(row[1]); + npc_spells_cache[iDBSpellsID]->entries[j].minlevel = atoi(row[2]); + npc_spells_cache[iDBSpellsID]->entries[j].maxlevel = atoi(row[3]); + npc_spells_cache[iDBSpellsID]->entries[j].manacost = atoi(row[4]); + npc_spells_cache[iDBSpellsID]->entries[j].recast_delay = atoi(row[5]); + npc_spells_cache[iDBSpellsID]->entries[j].priority = atoi(row[6]); + if(row[7]) + { + npc_spells_cache[iDBSpellsID]->entries[j].resist_adjust = atoi(row[7]); + } + else + { + if(IsValidSpell(spell_id)) + { + npc_spells_cache[iDBSpellsID]->entries[j].resist_adjust = spells[spell_id].ResistDiff; + } + } + j++; + } + mysql_free_result(result); + return npc_spells_cache[iDBSpellsID]; + } + else { + std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return 0; + } + } + else { + mysql_free_result(result); + } + } + else { + std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return 0; + } + + return 0; + } + return 0; +} + +uint32 ZoneDatabase::GetMaxNPCSpellsID() { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id) from npc_spells"), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + uint32 ret = 0; + if (row[0]) + ret = atoi(row[0]); + mysql_free_result(result); + return ret; + } + mysql_free_result(result); + } + else { + std::cerr << "Error in GetMaxNPCSpellsID query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return 0; + } + + return 0; +} + +DBnpcspellseffects_Struct* ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEffectsID) { + if (iDBSpellsEffectsID == 0) + return 0; + + if (!npc_spellseffects_cache) { + npc_spellseffects_maxid = GetMaxNPCSpellsEffectsID(); + npc_spellseffects_cache = new DBnpcspellseffects_Struct*[npc_spellseffects_maxid+1]; + npc_spellseffects_loadtried = new bool[npc_spellseffects_maxid+1]; + for (uint32 i=0; i<=npc_spellseffects_maxid; i++) { + npc_spellseffects_cache[i] = 0; + npc_spellseffects_loadtried[i] = false; + } + } + + if (iDBSpellsEffectsID > npc_spellseffects_maxid) + return 0; + if (npc_spellseffects_cache[iDBSpellsEffectsID]) { // it's in the cache, easy =) + return npc_spellseffects_cache[iDBSpellsEffectsID]; + } + + else if (!npc_spellseffects_loadtried[iDBSpellsEffectsID]) { // no reason to ask the DB again if we have failed once already + npc_spellseffects_loadtried[iDBSpellsEffectsID] = true; + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list from npc_spells_effects where id=%d", iDBSpellsEffectsID), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + uint32 tmpparent_list = atoi(row[1]); + mysql_free_result(result); + if (RunQuery(query, MakeAnyLenString(&query, "SELECT spell_effect_id, minlevel, maxlevel,se_base, se_limit, se_max from npc_spells_effects_entries where npc_spells_effects_id=%d ORDER BY minlevel", iDBSpellsEffectsID), errbuf, &result)) { + safe_delete_array(query); + uint32 tmpSize = sizeof(DBnpcspellseffects_Struct) + (sizeof(DBnpcspellseffects_Struct) * mysql_num_rows(result)); + npc_spellseffects_cache[iDBSpellsEffectsID] = (DBnpcspellseffects_Struct*) new uchar[tmpSize]; + memset(npc_spellseffects_cache[iDBSpellsEffectsID], 0, tmpSize); + npc_spellseffects_cache[iDBSpellsEffectsID]->parent_list = tmpparent_list; + npc_spellseffects_cache[iDBSpellsEffectsID]->numentries = mysql_num_rows(result); + int j = 0; + while ((row = mysql_fetch_row(result))) { + int spell_effect_id = atoi(row[0]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].spelleffectid = spell_effect_id; + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].minlevel = atoi(row[1]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].maxlevel = atoi(row[2]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].base = atoi(row[3]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].limit = atoi(row[4]); + npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].max = atoi(row[5]); + j++; + } + mysql_free_result(result); + return npc_spellseffects_cache[iDBSpellsEffectsID]; + } + else { + std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return 0; + } + } + else { + mysql_free_result(result); + } + } + else { + std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return 0; + } + return 0; + } + return 0; +} + +uint32 ZoneDatabase::GetMaxNPCSpellsEffectsID() { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id) from npc_spells_effects"), errbuf, &result)) { + safe_delete_array(query); + if (mysql_num_rows(result) == 1) { + row = mysql_fetch_row(result); + uint32 ret = 0; + if (row[0]) + ret = atoi(row[0]); + mysql_free_result(result); + return ret; + } + mysql_free_result(result); + } + else { + std::cerr << "Error in GetMaxNPCSpellsEffectsID query '" << query << "' " << errbuf << std::endl; + safe_delete_array(query); + return 0; + } + + return 0; +} + diff --git a/zone/attackx.cpp b/zone/attackx.cpp new file mode 100644 index 000000000..3f96399be --- /dev/null +++ b/zone/attackx.cpp @@ -0,0 +1,4663 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2002 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#if EQDEBUG >= 5 +//#define ATTACK_DEBUG 20 +#endif + +#include "../common/debug.h" +#include +#include +#include +#include +#include +#include + +#include "masterentity.h" +#include "NpcAI.h" +#include "../common/packet_dump.h" +#include "../common/eq_packet_structs.h" +#include "../common/eq_constants.h" +#include "../common/skills.h" +#include "../common/spdat.h" +#include "zone.h" +#include "StringIDs.h" +#include "../common/StringUtil.h" +#include "../common/rulesys.h" +#include "QuestParserCollection.h" +#include "watermap.h" +#include "worldserver.h" +extern WorldServer worldserver; + +#ifdef _WINDOWS +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + +extern EntityList entity_list; +extern Zone* zone; + +bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* weapon) +{ + // Determine animation + int type = 0; + if (weapon && weapon->IsType(ItemClassCommon)) { + const Item_Struct* item = weapon->GetItem(); +#if EQDEBUG >= 11 + LogFile->write(EQEMuLog::Debug, "Weapon skill:%i", item->ItemType); +#endif + switch (item->ItemType) + { + case ItemType1HSlash: // 1H Slashing + { + skillinuse = Skill1HSlashing; + type = anim1HWeapon; + break; + } + case ItemType2HSlash: // 2H Slashing + { + skillinuse = Skill2HSlashing; + type = anim2HSlashing; + break; + } + case ItemType1HPiercing: // Piercing + { + skillinuse = Skill1HPiercing; + type = animPiercing; + break; + } + case ItemType1HBlunt: // 1H Blunt + { + skillinuse = Skill1HBlunt; + type = anim1HWeapon; + break; + } + case ItemType2HBlunt: // 2H Blunt + { + skillinuse = Skill2HBlunt; + type = anim2HWeapon; + break; + } + case ItemType2HPiercing: // 2H Piercing + { + skillinuse = Skill1HPiercing; // change to Skill2HPiercing once activated + type = anim2HWeapon; + break; + } + case ItemTypeMartial: + { + skillinuse = SkillHandtoHand; + type = animHand2Hand; + break; + } + default: + { + skillinuse = SkillHandtoHand; + type = animHand2Hand; + break; + } + }// switch + } + else if(IsNPC()) { + + switch (skillinuse) + { + case Skill1HSlashing: // 1H Slashing + { + type = anim1HWeapon; + break; + } + case Skill2HSlashing: // 2H Slashing + { + type = anim2HSlashing; + break; + } + case Skill1HPiercing: // Piercing + { + type = animPiercing; + break; + } + case Skill1HBlunt: // 1H Blunt + { + type = anim1HWeapon; + break; + } + case Skill2HBlunt: // 2H Blunt + { + type = anim2HWeapon; + break; + } + case 99: // 2H Piercing // change to Skill2HPiercing once activated + { + type = anim2HWeapon; + break; + } + case SkillHandtoHand: + { + type = animHand2Hand; + break; + } + default: + { + type = animHand2Hand; + break; + } + }// switch + } + else { + skillinuse = SkillHandtoHand; + type = animHand2Hand; + } + + // If we're attacking with the secondary hand, play the dual wield anim + if (Hand == 14) // DW anim + type = animDualWield; + + DoAnim(type); + return true; +} + +// called when a mob is attacked, does the checks to see if it's a hit +// and does other mitigation checks. 'this' is the mob being attacked. +bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 chance_mod) +{ +/*/ + //Reworked a lot of this code to achieve better balance at higher levels. + //The old code basically meant that any in high level (50+) combat, + //both parties always had 95% chance to hit the other one. +/*/ + + Mob *attacker=other; + Mob *defender=this; + float chancetohit = RuleR(Combat, BaseHitChance); + + if(attacker->IsNPC() && !attacker->IsPet()) + chancetohit += RuleR(Combat, NPCBonusHitChance); + +#if ATTACK_DEBUG>=11 + LogFile->write(EQEMuLog::Debug, "CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName()); +#endif + mlog(COMBAT__TOHIT,"CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName()); + + bool pvpmode = false; + if(IsClient() && other->IsClient()) + pvpmode = true; + + if (chance_mod >= 10000) + return true; + + float bonus; + + //////////////////////////////////////////////////////// + // To hit calcs go here + //////////////////////////////////////////////////////// + + uint8 attacker_level = attacker->GetLevel() ? attacker->GetLevel() : 1; + uint8 defender_level = defender->GetLevel() ? defender->GetLevel() : 1; + + //Calculate the level difference + + mlog(COMBAT__TOHIT, "Chance to hit before level diff calc %.2f", chancetohit); + double level_difference = attacker_level - defender_level; + double range = defender->GetLevel(); + range = ((range / 4) + 3); + + if(level_difference < 0) + { + if(level_difference >= -range) + { + chancetohit += (level_difference / range) * RuleR(Combat,HitFalloffMinor); //5 + } + else if (level_difference >= -(range+3.0)) + { + chancetohit -= RuleR(Combat,HitFalloffMinor); + chancetohit += ((level_difference+range) / (3.0)) * RuleR(Combat,HitFalloffModerate); //7 + } + else + { + chancetohit -= (RuleR(Combat,HitFalloffMinor) + RuleR(Combat,HitFalloffModerate)); + chancetohit += ((level_difference+range+3.0)/12.0) * RuleR(Combat,HitFalloffMajor); //50 + } + } + else + { + chancetohit += (RuleR(Combat,HitBonusPerLevel) * level_difference); + } + + mlog(COMBAT__TOHIT, "Chance to hit after level diff calc %.2f", chancetohit); + + chancetohit -= ((float)defender->GetAGI() * RuleR(Combat, AgiHitFactor)); + + mlog(COMBAT__TOHIT, "Chance to hit after agil calc %.2f", chancetohit); + + if(attacker->IsClient()) + { + chancetohit -= (RuleR(Combat,WeaponSkillFalloff) * (attacker->CastToClient()->MaxSkill(skillinuse) - attacker->GetSkill(skillinuse))); + mlog(COMBAT__TOHIT, "Chance to hit after weapon falloff calc (attack) %.2f", chancetohit); + } + + if(defender->IsClient()) + { + chancetohit += (RuleR(Combat,WeaponSkillFalloff) * (defender->CastToClient()->MaxSkill(SkillDefense) - defender->GetSkill(SkillDefense))); + mlog(COMBAT__TOHIT, "Chance to hit after weapon falloff calc (defense) %.2f", chancetohit); + } + + //I dont think this is 100% correct, but at least it does something... + if(attacker->spellbonuses.MeleeSkillCheckSkill == skillinuse || attacker->spellbonuses.MeleeSkillCheckSkill == 255) { + chancetohit += attacker->spellbonuses.MeleeSkillCheck; + mlog(COMBAT__TOHIT, "Applied spell melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit); + } + if(attacker->itembonuses.MeleeSkillCheckSkill == skillinuse || attacker->itembonuses.MeleeSkillCheckSkill == 255) { + chancetohit += attacker->itembonuses.MeleeSkillCheck; + mlog(COMBAT__TOHIT, "Applied item melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit); + } + + //subtract off avoidance by the defender. (Live AA - Combat Agility) + bonus = defender->spellbonuses.AvoidMeleeChance + defender->itembonuses.AvoidMeleeChance + (defender->aabonuses.AvoidMeleeChance * 10); + + //AA Live - Elemental Agility + if (IsPet()) { + Mob *owner = defender->GetOwner(); + if (!owner)return false; + bonus += (owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance)*10; + } + + if(bonus > 0) { + chancetohit -= ((bonus * chancetohit) / 1000); + mlog(COMBAT__TOHIT, "Applied avoidance chance %.2f/10, yeilding %.2f", bonus, chancetohit); + } + + if(attacker->IsNPC()) + chancetohit += (chancetohit * attacker->CastToNPC()->GetAccuracyRating() / 1000); + + mlog(COMBAT__TOHIT, "Chance to hit after accuracy rating calc %.2f", chancetohit); + + float hitBonus = 0; + + /* + Kayen: Unknown if the HitChance and Accuracy effect's should modify 'chancetohit' + cumulatively or successively. For now all hitBonuses are cumulative. + */ + + hitBonus += attacker->itembonuses.HitChanceEffect[skillinuse] + + attacker->spellbonuses.HitChanceEffect[skillinuse]+ + attacker->itembonuses.HitChanceEffect[HIGHEST_SKILL+1] + + attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1]; + + //Accuracy = Spell Effect , HitChance = 'Accuracy' from Item Effect + //Only AA derived accuracy can be skill limited. ie (Precision of the Pathfinder, Dead Aim) + hitBonus += (attacker->itembonuses.Accuracy[HIGHEST_SKILL+1] + + attacker->spellbonuses.Accuracy[HIGHEST_SKILL+1] + + attacker->aabonuses.Accuracy[HIGHEST_SKILL+1] + + attacker->aabonuses.Accuracy[skillinuse] + + attacker->itembonuses.HitChance) / 15.0f; + + hitBonus += chance_mod; //Modifier applied from casted/disc skill attacks. + + chancetohit += ((chancetohit * hitBonus) / 100.0f); + + if(skillinuse == SkillArchery) + chancetohit -= (chancetohit * RuleR(Combat, ArcheryHitPenalty)) / 100.0f; + + chancetohit = mod_hit_chance(chancetohit, skillinuse, attacker); + + // Chance to hit; Max 95%, Min 30% + if(chancetohit > 1000) { + //if chance to hit is crazy high, that means a discipline is in use, and let it stay there + } + else if(chancetohit > 95) { + chancetohit = 95; + } + else if(chancetohit < 5) { + chancetohit = 5; + } + + //I dont know the best way to handle a garunteed hit discipline being used + //agains a garunteed riposte (for example) discipline... for now, garunteed hit wins + + + #if EQDEBUG>=11 + LogFile->write(EQEMuLog::Debug, "3 FINAL calculated chance to hit is: %5.2f", chancetohit); + #endif + + // + // Did we hit? + // + + float tohit_roll = MakeRandomFloat(0, 100); + + mlog(COMBAT__TOHIT, "Final hit chance: %.2f%%. Hit roll %.2f", chancetohit, tohit_roll); + + return(tohit_roll <= chancetohit); +} + + +bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) +{ + /* solar: called when a mob is attacked, does the checks to see if it's a hit + * and does other mitigation checks. 'this' is the mob being attacked. + * + * special return values: + * -1 - block + * -2 - parry + * -3 - riposte + * -4 - dodge + * + */ + float skill; + float bonus; + float RollTable[4] = {0,0,0,0}; + float roll; + Mob *attacker=other; + Mob *defender=this; + + //garunteed hit + bool ghit = false; + if((attacker->spellbonuses.MeleeSkillCheck + attacker->itembonuses.MeleeSkillCheck) > 500) + ghit = true; + + ////////////////////////////////////////////////////////// + // make enrage same as riposte + ///////////////////////////////////////////////////////// + if (IsEnraged() && other->InFrontMob(this, other->GetX(), other->GetY())) { + damage = -3; + mlog(COMBAT__DAMAGE, "I am enraged, riposting frontal attack."); + } + + ///////////////////////////////////////////////////////// + // riposte + ///////////////////////////////////////////////////////// + float riposte_chance = 0.0f; + if (CanRiposte && damage > 0 && CanThisClassRiposte() && other->InFrontMob(this, other->GetX(), other->GetY())) + { + riposte_chance = (100.0f + (float)defender->aabonuses.RiposteChance + (float)defender->spellbonuses.RiposteChance + (float)defender->itembonuses.RiposteChance) / 100.0f; + skill = GetSkill(SkillRiposte); + if (IsClient()) { + CastToClient()->CheckIncreaseSkill(SkillRiposte, other, -10); + } + + if (!ghit) { //if they are not using a garunteed hit discipline + bonus = 2.0 + skill/60.0 + (GetDEX()/200); + bonus *= riposte_chance; + bonus = mod_riposte_chance(bonus, attacker); + RollTable[0] = bonus + (itembonuses.HeroicDEX / 25); // 25 heroic = 1%, applies to ripo, parry, block + } + } + + /////////////////////////////////////////////////////// + // block + /////////////////////////////////////////////////////// + + bool bBlockFromRear = false; + bool bShieldBlockFromRear = false; + + if (this->IsClient()) { + int aaChance = 0; + + // a successful roll on this does not mean a successful block is forthcoming. only that a chance to block + // from a direction other than the rear is granted. + + //Live AA - HightenedAwareness + int BlockBehindChance = aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind; + + if (BlockBehindChance && (BlockBehindChance > MakeRandomInt(1, 100))){ + bBlockFromRear = true; + + if (spellbonuses.BlockBehind || itembonuses.BlockBehind) + bShieldBlockFromRear = true; //This bonus should allow a chance to Shield Block from behind. + } + } + + float block_chance = 0.0f; + if (damage > 0 && CanThisClassBlock() && (other->InFrontMob(this, other->GetX(), other->GetY()) || bBlockFromRear)) { + block_chance = (100.0f + (float)spellbonuses.IncreaseBlockChance + (float)itembonuses.IncreaseBlockChance) / 100.0f; + skill = CastToClient()->GetSkill(SkillBlock); + if (IsClient()) { + CastToClient()->CheckIncreaseSkill(SkillBlock, other, -10); + } + + if (!ghit) { //if they are not using a garunteed hit discipline + bonus = 2.0 + skill/35.0 + (GetDEX()/200); + bonus = mod_block_chance(bonus, attacker); + RollTable[1] = RollTable[0] + (bonus * block_chance); + } + } + else{ + RollTable[1] = RollTable[0]; + } + + if(damage > 0 && HasShieldEquiped() && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) + && (other->InFrontMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) { + + float bonusShieldBlock = 0.0f; + bonusShieldBlock = aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock; + RollTable[1] += bonusShieldBlock; + } + + if(damage > 0 && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) + && (other->InFrontMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) { + bool equiped2 = CastToClient()->m_inv.GetItem(13); + if(equiped2) { + uint8 TwoHandBlunt = CastToClient()->m_inv.GetItem(13)->GetItem()->ItemType; + float bonusStaffBlock = 0.0f; + if(TwoHandBlunt == ItemType2HBlunt) { + + bonusStaffBlock = aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock; + RollTable[1] += bonusStaffBlock; + } + } + } + + ////////////////////////////////////////////////////// + // parry + ////////////////////////////////////////////////////// + float parry_chance = 0.0f; + if (damage > 0 && CanThisClassParry() && other->InFrontMob(this, other->GetX(), other->GetY())) + { + parry_chance = (100.0f + (float)defender->spellbonuses.ParryChance + (float)defender->itembonuses.ParryChance) / 100.0f; + skill = CastToClient()->GetSkill(SkillParry); + if (IsClient()) { + CastToClient()->CheckIncreaseSkill(SkillParry, other, -10); + } + + if (!ghit) { //if they are not using a garunteed hit discipline + bonus = 2.0 + skill/60.0 + (GetDEX()/200); + bonus *= parry_chance; + bonus = mod_parry_chance(bonus, attacker); + RollTable[2] = RollTable[1] + bonus; + } + } + else{ + RollTable[2] = RollTable[1]; + } + + //////////////////////////////////////////////////////// + // dodge + //////////////////////////////////////////////////////// + float dodge_chance = 0.0f; + if (damage > 0 && CanThisClassDodge() && other->InFrontMob(this, other->GetX(), other->GetY())) + { + dodge_chance = (100.0f + (float)defender->spellbonuses.DodgeChance + (float)defender->itembonuses.DodgeChance) / 100.0f; + skill = CastToClient()->GetSkill(SkillDodge); + if (IsClient()) { + CastToClient()->CheckIncreaseSkill(SkillDodge, other, -10); + } + + if (!ghit) { //if they are not using a garunteed hit discipline + bonus = 2.0 + skill/60.0 + (GetAGI()/200); + bonus *= dodge_chance; + //DCBOOMKAR + bonus = mod_dodge_chance(bonus, attacker); + RollTable[3] = RollTable[2] + bonus - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25); + } + } + else{ + RollTable[3] = RollTable[2]; + } + + if(damage > 0){ + roll = MakeRandomFloat(0,100); + if(roll <= RollTable[0]){ + damage = -3; + } + else if(roll <= RollTable[1]){ + damage = -1; + } + else if(roll <= RollTable[2]){ + damage = -2; + } + else if(roll <= RollTable[3]){ + damage = -4; + } + } + + mlog(COMBAT__DAMAGE, "Final damage after all avoidances: %d", damage); + + if (damage < 0) + return true; + return false; +} + +void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts) +{ + if (damage <= 0) + return; + + Mob* defender = this; + float aa_mit = (aabonuses.CombatStability + itembonuses.CombatStability + + spellbonuses.CombatStability) / 100.0f; + + if (RuleB(Combat, UseIntervalAC)) { + float softcap = (GetSkill(SkillDefense) + GetLevel()) * + RuleR(Combat, SoftcapFactor) * (1.0 + aa_mit); + float mitigation_rating = 0.0; + float attack_rating = 0.0; + int shield_ac = 0; + int armor = 0; + float weight = 0.0; + + float monkweight = RuleI(Combat, MonkACBonusWeight); + monkweight = mod_monk_weight(monkweight, attacker); + + if (IsClient()) { + armor = CastToClient()->GetRawACNoShield(shield_ac); + weight = (CastToClient()->CalcCurrentWeight() / 10.0); + } else if (IsNPC()) { + armor = CastToNPC()->GetRawAC(); + + if (!IsPet()) + armor = (armor / RuleR(Combat, NPCACFactor)); + + armor += spellbonuses.AC + itembonuses.AC + 1; + } + + if (opts) { + armor *= (1.0f - opts->armor_pen_percent); + armor -= opts->armor_pen_flat; + } + + if (RuleB(Combat, OldACSoftcapRules)) { + if (GetClass() == WIZARD || GetClass() == MAGICIAN || + GetClass() == NECROMANCER || GetClass() == ENCHANTER) + softcap = RuleI(Combat, ClothACSoftcap); + else if (GetClass() == MONK && weight <= monkweight) + softcap = RuleI(Combat, MonkACSoftcap); + else if(GetClass() == DRUID || GetClass() == BEASTLORD || GetClass() == MONK) + softcap = RuleI(Combat, LeatherACSoftcap); + else if(GetClass() == SHAMAN || GetClass() == ROGUE || + GetClass() == BERSERKER || GetClass() == RANGER) + softcap = RuleI(Combat, ChainACSoftcap); + else + softcap = RuleI(Combat, PlateACSoftcap); + } + + softcap += shield_ac; + armor += shield_ac; + if (RuleB(Combat, OldACSoftcapRules)) + softcap += (softcap * (aa_mit * RuleR(Combat, AAMitigationACFactor))); + if (armor > softcap) { + int softcap_armor = armor - softcap; + if (RuleB(Combat, OldACSoftcapRules)) { + if (GetClass() == WARRIOR) + softcap_armor = softcap_armor * RuleR(Combat, WarriorACSoftcapReturn); + else if (GetClass() == SHADOWKNIGHT || GetClass() == PALADIN || + (GetClass() == MONK && weight <= monkweight)) + softcap_armor = softcap_armor * RuleR(Combat, KnightACSoftcapReturn); + else if (GetClass() == CLERIC || GetClass() == BARD || + GetClass() == BERSERKER || GetClass() == ROGUE || + GetClass() == SHAMAN || GetClass() == MONK) + softcap_armor = softcap_armor * RuleR(Combat, LowPlateChainACSoftcapReturn); + else if (GetClass() == RANGER || GetClass() == BEASTLORD) + softcap_armor = softcap_armor * RuleR(Combat, LowChainLeatherACSoftcapReturn); + else if (GetClass() == WIZARD || GetClass() == MAGICIAN || + GetClass() == NECROMANCER || GetClass() == ENCHANTER || + GetClass() == DRUID) + softcap_armor = softcap_armor * RuleR(Combat, CasterACSoftcapReturn); + else + softcap_armor = softcap_armor * RuleR(Combat, MiscACSoftcapReturn); + } else { + if (GetClass() == WARRIOR) + softcap_armor *= RuleR(Combat, WarACSoftcapReturn); + else if (GetClass() == PALADIN || GetClass() == SHADOWKNIGHT) + softcap_armor *= RuleR(Combat, PalShdACSoftcapReturn); + else if (GetClass() == CLERIC || GetClass() == RANGER || + GetClass() == MONK || GetClass() == BARD) + softcap_armor *= RuleR(Combat, ClrRngMnkBrdACSoftcapReturn); + else if (GetClass() == DRUID || GetClass() == NECROMANCER || + GetClass() == WIZARD || GetClass() == ENCHANTER || + GetClass() == MAGICIAN) + softcap_armor *= RuleR(Combat, DruNecWizEncMagACSoftcapReturn); + else if (GetClass() == ROGUE || GetClass() == SHAMAN || + GetClass() == BEASTLORD || GetClass() == BERSERKER) + softcap_armor *= RuleR(Combat, RogShmBstBerACSoftcapReturn); + else + softcap_armor *= RuleR(Combat, MiscACSoftcapReturn); + } + armor = softcap + softcap_armor; + } + + if (GetClass() == WIZARD || GetClass() == MAGICIAN || + GetClass() == NECROMANCER || GetClass() == ENCHANTER) + mitigation_rating = ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10) / 4.0) + armor + 1; + else + mitigation_rating = ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10) / 3.0) + (armor * 1.333333) + 1; + mitigation_rating *= 0.847; + + mitigation_rating = mod_mitigation_rating(mitigation_rating, attacker); + + if (attacker->IsClient()) + attack_rating = (attacker->CastToClient()->CalcATK() + ((attacker->GetSTR()-66) * 0.9) + (attacker->GetSkill(SkillOffense)*1.345)); + else + attack_rating = (attacker->GetATK() + (attacker->GetSkill(SkillOffense)*1.345) + ((attacker->GetSTR()-66) * 0.9)); + + attack_rating = attacker->mod_attack_rating(attack_rating, this); + + damage = GetMeleeMitDmg(attacker, damage, minhit, mitigation_rating, attack_rating); + } else { + //////////////////////////////////////////////////////// + // Scorpious2k: Include AC in the calculation + // use serverop variables to set values + int myac = GetAC(); + if(opts) { + myac *= (1.0f - opts->armor_pen_percent); + myac -= opts->armor_pen_flat; + } + + if (damage > 0 && myac > 0) { + int acfail=1000; + char tmp[10]; + + if (database.GetVariable("ACfail", tmp, 9)) { + acfail = (int) (atof(tmp) * 100); + if (acfail>100) acfail=100; + } + + if (acfail<=0 || MakeRandomInt(0, 100)>acfail) { + float acreduction=1; + int acrandom=300; + if (database.GetVariable("ACreduction", tmp, 9)) + { + acreduction=atof(tmp); + if (acreduction>100) acreduction=100; + } + + if (database.GetVariable("ACrandom", tmp, 9)) + { + acrandom = (int) ((atof(tmp)+1) * 100); + if (acrandom>10100) acrandom=10100; + } + + if (acreduction>0) { + damage -= (int) (GetAC() * acreduction/100.0f); + } + if (acrandom>0) { + damage -= (myac * MakeRandomInt(0, acrandom) / 10000); + } + if (damage<1) damage=1; + mlog(COMBAT__DAMAGE, "AC Damage Reduction: fail chance %d%%. Failed. Reduction %.3f%%, random %d. Resulting damage %d.", acfail, acreduction, acrandom, damage); + } else { + mlog(COMBAT__DAMAGE, "AC Damage Reduction: fail chance %d%%. Did not fail.", acfail); + } + } + + damage -= (aa_mit * damage); + + if(damage != 0 && damage < minhit) + damage = minhit; + //reduce the damage from shielding item and aa based on the min dmg + //spells offer pure mitigation + damage -= (minhit * defender->itembonuses.MeleeMitigation / 100); + damage -= (damage * defender->spellbonuses.MeleeMitigation / 100); + } + + if (damage < 0) + damage = 0; +} + +// This is called when the Mob is the one being hit +int32 Mob::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, + float mit_rating, float atk_rating) +{ + float d = 10.0; + float mit_roll = MakeRandomFloat(0, mit_rating); + float atk_roll = MakeRandomFloat(0, atk_rating); + + if (atk_roll > mit_roll) { + float a_diff = atk_roll - mit_roll; + float thac0 = atk_rating * RuleR(Combat, ACthac0Factor); + float thac0cap = attacker->GetLevel() * 9 + 20; + if (thac0 > thac0cap) + thac0 = thac0cap; + + d -= 10.0 * (a_diff / thac0); + } else if (mit_roll > atk_roll) { + float m_diff = mit_roll - atk_roll; + float thac20 = mit_rating * RuleR(Combat, ACthac20Factor); + float thac20cap = GetLevel() * 9 + 20; + if (thac20 > thac20cap) + thac20 = thac20cap; + + d += 10.0 * (m_diff / thac20); + } + + if (d < 0.0) + d = 0.0; + else if (d > 20.0) + d = 20.0; + + float interval = (damage - minhit) / 20.0; + damage -= ((int)d * interval); + + damage -= (minhit * itembonuses.MeleeMitigation / 100); + damage -= (damage * spellbonuses.MeleeMitigation / 100); + return damage; +} + +// This is called when the Client is the one being hit +int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, + float mit_rating, float atk_rating) +{ + if (!attacker->IsNPC() || RuleB(Combat, UseOldDamageIntervalRules)) + return Mob::GetMeleeMitDmg(attacker, damage, minhit, mit_rating, atk_rating); + int d = 10; + // floats for the rounding issues + float dmg_interval = (damage - minhit) / 19.0; + float dmg_bonus = minhit - dmg_interval; + float spellMeleeMit = spellbonuses.MeleeMitigation / 100.0; + if (GetClass() == WARRIOR) + spellMeleeMit += 0.05; + dmg_bonus -= dmg_bonus * (itembonuses.MeleeMitigation / 100.0); + dmg_interval -= dmg_interval * spellMeleeMit; + + float mit_roll = MakeRandomFloat(0, mit_rating); + float atk_roll = MakeRandomFloat(0, atk_rating); + + if (atk_roll > mit_roll) { + float a_diff = atk_roll - mit_roll; + float thac0 = atk_rating * RuleR(Combat, ACthac0Factor); + float thac0cap = attacker->GetLevel() * 9 + 20; + if (thac0 > thac0cap) + thac0 = thac0cap; + + d += 10 * (a_diff / thac0); + } else if (mit_roll > atk_roll) { + float m_diff = mit_roll - atk_roll; + float thac20 = mit_rating * RuleR(Combat, ACthac20Factor); + float thac20cap = GetLevel() * 9 + 20; + if (thac20 > thac20cap) + thac20 = thac20cap; + + d -= 10 * (m_diff / thac20); + } + + if (d < 1) + d = 1; + else if (d > 20) + d = 20; + + return static_cast((dmg_bonus + dmg_interval * d)); +} + +//Returns the weapon damage against the input mob +//if we cannot hit the mob with the current weapon we will get a value less than or equal to zero +//Else we know we can hit. +//GetWeaponDamage(mob*, const Item_Struct*) is intended to be used for mobs or any other situation where we do not have a client inventory item +//GetWeaponDamage(mob*, const ItemInst*) is intended to be used for situations where we have a client inventory item +int Mob::GetWeaponDamage(Mob *against, const Item_Struct *weapon_item) { + int dmg = 0; + int banedmg = 0; + + //can't hit invulnerable stuff with weapons. + if(against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)){ + return 0; + } + + //check to see if our weapons or fists are magical. + if(against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)){ + if(weapon_item){ + if(weapon_item->Magic){ + dmg = weapon_item->Damage; + + //this is more for non weapon items, ex: boots for kick + //they don't have a dmg but we should be able to hit magical + dmg = dmg <= 0 ? 1 : dmg; + } + else + return 0; + } + else{ + if((GetClass() == MONK || GetClass() == BEASTLORD) && GetLevel() >= 30){ + dmg = GetMonkHandToHandDamage(); + } + else if(GetOwner() && GetLevel() >= RuleI(Combat, PetAttackMagicLevel)){ + //pets wouldn't actually use this but... + //it gives us an idea if we can hit due to the dual nature of this function + dmg = 1; + } + else if(GetSpecialAbility(SPECATK_MAGICAL)) + { + dmg = 1; + } + else + return 0; + } + } + else{ + if(weapon_item){ + dmg = weapon_item->Damage; + + dmg = dmg <= 0 ? 1 : dmg; + } + else{ + if(GetClass() == MONK || GetClass() == BEASTLORD){ + dmg = GetMonkHandToHandDamage(); + } + else{ + dmg = 1; + } + } + } + + int eledmg = 0; + if(!against->GetSpecialAbility(IMMUNE_MAGIC)){ + if(weapon_item && weapon_item->ElemDmgAmt){ + //we don't check resist for npcs here + eledmg = weapon_item->ElemDmgAmt; + dmg += eledmg; + } + } + + if(against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)){ + if(weapon_item){ + if(weapon_item->BaneDmgBody == against->GetBodyType()){ + banedmg += weapon_item->BaneDmgAmt; + } + + if(weapon_item->BaneDmgRace == against->GetRace()){ + banedmg += weapon_item->BaneDmgRaceAmt; + } + } + + if(!eledmg && !banedmg){ + if(!GetSpecialAbility(SPECATK_BANE)) + return 0; + else + return 1; + } + else + dmg += banedmg; + } + else{ + if(weapon_item){ + if(weapon_item->BaneDmgBody == against->GetBodyType()){ + banedmg += weapon_item->BaneDmgAmt; + } + + if(weapon_item->BaneDmgRace == against->GetRace()){ + banedmg += weapon_item->BaneDmgRaceAmt; + } + } + + dmg += (banedmg + eledmg); + } + + if(dmg <= 0){ + return 0; + } + else + return dmg; +} + +int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate) +{ + int dmg = 0; + int banedmg = 0; + + if(!against || against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)){ + return 0; + } + + //check for items being illegally attained + if(weapon_item){ + const Item_Struct *mWeaponItem = weapon_item->GetItem(); + if(mWeaponItem){ + if(mWeaponItem->ReqLevel > GetLevel()){ + return 0; + } + + if(!weapon_item->IsEquipable(GetBaseRace(), GetClass())){ + return 0; + } + } + else{ + return 0; + } + } + + if(against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)){ + if(weapon_item){ + // check to see if the weapon is magic + bool MagicWeapon = false; + if(weapon_item->GetItem() && weapon_item->GetItem()->Magic) + MagicWeapon = true; + else { + if(spellbonuses.MagicWeapon || itembonuses.MagicWeapon) + MagicWeapon = true; + } + + if(MagicWeapon) { + + if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ + dmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->Damage); + } + else{ + dmg = weapon_item->GetItem()->Damage; + } + + for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ + if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ + dmg += weapon_item->GetAugment(x)->GetItem()->Damage; + if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt; + } + } + dmg = dmg <= 0 ? 1 : dmg; + } + else + return 0; + } + else{ + if((GetClass() == MONK || GetClass() == BEASTLORD) && GetLevel() >= 30){ + dmg = GetMonkHandToHandDamage(); + if (hate) *hate += dmg; + } + else if(GetOwner() && GetLevel() >= RuleI(Combat, PetAttackMagicLevel)){ //pets wouldn't actually use this but... + dmg = 1; //it gives us an idea if we can hit + } + else if(GetSpecialAbility(SPECATK_MAGICAL)){ + dmg = 1; + } + else + return 0; + } + } + else{ + if(weapon_item){ + if(weapon_item->GetItem()){ + + if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ + dmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->Damage); + } + else{ + dmg = weapon_item->GetItem()->Damage; + } + + for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ + if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ + dmg += weapon_item->GetAugment(x)->GetItem()->Damage; + if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt; + } + } + dmg = dmg <= 0 ? 1 : dmg; + } + } + else{ + if(GetClass() == MONK || GetClass() == BEASTLORD){ + dmg = GetMonkHandToHandDamage(); + if (hate) *hate += dmg; + } + else{ + dmg = 1; + } + } + } + + int eledmg = 0; + if(!against->GetSpecialAbility(IMMUNE_MAGIC)){ + if(weapon_item && weapon_item->GetItem() && weapon_item->GetItem()->ElemDmgAmt){ + if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ + eledmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->ElemDmgAmt); + } + else{ + eledmg = weapon_item->GetItem()->ElemDmgAmt; + } + + if(eledmg) + { + eledmg = (eledmg * against->ResistSpell(weapon_item->GetItem()->ElemDmgType, 0, this) / 100); + } + } + + if(weapon_item){ + for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ + if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ + if(weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt) + eledmg += (weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt * against->ResistSpell(weapon_item->GetAugment(x)->GetItem()->ElemDmgType, 0, this) / 100); + } + } + } + } + + if(against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)){ + if(weapon_item && weapon_item->GetItem()){ + if(weapon_item->GetItem()->BaneDmgBody == against->GetBodyType()){ + if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ + banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgAmt); + } + else{ + banedmg += weapon_item->GetItem()->BaneDmgAmt; + } + } + + if(weapon_item->GetItem()->BaneDmgRace == against->GetRace()){ + if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ + banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgRaceAmt); + } + else{ + banedmg += weapon_item->GetItem()->BaneDmgRaceAmt; + } + } + + for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ + if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ + if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){ + banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt; + } + + if(weapon_item->GetAugment(x)->GetItem()->BaneDmgRace == against->GetRace()){ + banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgRaceAmt; + } + } + } + } + + if(!eledmg && !banedmg) + { + if(!GetSpecialAbility(SPECATK_BANE)) + return 0; + else + return 1; + } + else { + dmg += (banedmg + eledmg); + if (hate) *hate += banedmg; + } + } + else{ + if(weapon_item && weapon_item->GetItem()){ + if(weapon_item->GetItem()->BaneDmgBody == against->GetBodyType()){ + if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ + banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgAmt); + } + else{ + banedmg += weapon_item->GetItem()->BaneDmgAmt; + } + } + + if(weapon_item->GetItem()->BaneDmgRace == against->GetRace()){ + if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ + banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgRaceAmt); + } + else{ + banedmg += weapon_item->GetItem()->BaneDmgRaceAmt; + } + } + + for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ + if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ + if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){ + banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt; + } + + if(weapon_item->GetAugment(x)->GetItem()->BaneDmgRace == against->GetRace()){ + banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgRaceAmt; + } + } + } + } + dmg += (banedmg + eledmg); + if (hate) *hate += banedmg; + } + + if(dmg <= 0){ + return 0; + } + else + return dmg; +} + +//note: throughout this method, setting `damage` to a negative is a way to +//stop the attack calculations +// IsFromSpell added to allow spell effects to use Attack. (Mainly for the Rampage AA right now.) +bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) +{ + if (!other) { + SetTarget(nullptr); + LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Client::Attack() for evaluation!"); + return false; + } + + if(!GetTarget()) + SetTarget(other); + + mlog(COMBAT__ATTACKS, "Attacking %s with hand %d %s", other?other->GetName():"(nullptr)", Hand, bRiposte?"(this is a riposte)":""); + + //SetAttackTimer(); + if ( + (IsCasting() && GetClass() != BARD && !IsFromSpell) + || other == nullptr + || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) + || (GetHP() < 0) + || (!IsAttackAllowed(other)) + ) { + mlog(COMBAT__ATTACKS, "Attack canceled, invalid circumstances."); + return false; // Only bards can attack while casting + } + + if(DivineAura() && !GetGM()) {//cant attack while invulnerable unless your a gm + mlog(COMBAT__ATTACKS, "Attack canceled, Divine Aura is in effect."); + Message_StringID(MT_DefaultText, DIVINE_AURA_NO_ATK); //You can't attack while invulnerable! + return false; + } + + if (GetFeigned()) + return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code. + + + ItemInst* weapon; + if (Hand == 14){ // Kaiyodo - Pick weapon from the attacking hand + weapon = GetInv().GetItem(SLOT_SECONDARY); + OffHandAtk(true); + } + else{ + weapon = GetInv().GetItem(SLOT_PRIMARY); + OffHandAtk(false); + } + + if(weapon != nullptr) { + if (!weapon->IsWeapon()) { + mlog(COMBAT__ATTACKS, "Attack canceled, Item %s (%d) is not a weapon.", weapon->GetItem()->Name, weapon->GetID()); + return(false); + } + mlog(COMBAT__ATTACKS, "Attacking with weapon: %s (%d)", weapon->GetItem()->Name, weapon->GetID()); + } else { + mlog(COMBAT__ATTACKS, "Attacking without a weapon."); + } + + // calculate attack_skill and skillinuse depending on hand and weapon + // also send Packet to near clients + SkillUseTypes skillinuse; + AttackAnimation(skillinuse, Hand, weapon); + mlog(COMBAT__ATTACKS, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse); + + /// Now figure out damage + int damage = 0; + uint8 mylevel = GetLevel() ? GetLevel() : 1; + uint32 hate = 0; + if (weapon) hate = weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt; + int weapon_damage = GetWeaponDamage(other, weapon, &hate); + if (hate == 0 && weapon_damage > 1) hate = weapon_damage; + + //if weapon damage > 0 then we know we can hit the target with this weapon + //otherwise we cannot and we set the damage to -5 later on + if(weapon_damage > 0){ + + //Berserker Berserk damage bonus + if(IsBerserk() && GetClass() == BERSERKER){ + int bonus = 3 + GetLevel()/10; //unverified + weapon_damage = weapon_damage * (100+bonus) / 100; + mlog(COMBAT__DAMAGE, "Berserker damage bonus increases DMG to %d", weapon_damage); + } + + //try a finishing blow.. if successful end the attack + if(TryFinishingBlow(other, skillinuse)) + return (true); + + int min_hit = 1; + int max_hit = (2*weapon_damage*GetDamageTable(skillinuse)) / 100; + + if(GetLevel() < 10 && max_hit > RuleI(Combat, HitCapPre10)) + max_hit = (RuleI(Combat, HitCapPre10)); + else if(GetLevel() < 20 && max_hit > RuleI(Combat, HitCapPre20)) + max_hit = (RuleI(Combat, HitCapPre20)); + + CheckIncreaseSkill(skillinuse, other, -15); + CheckIncreaseSkill(SkillOffense, other, -15); + + + // *************************************************************** + // *** Calculate the damage bonus, if applicable, for this hit *** + // *************************************************************** + +#ifndef EQEMU_NO_WEAPON_DAMAGE_BONUS + + // If you include the preprocessor directive "#define EQEMU_NO_WEAPON_DAMAGE_BONUS", that indicates that you do not + // want damage bonuses added to weapon damage at all. This feature was requested by ChaosSlayer on the EQEmu Forums. + // + // This is not recommended for normal usage, as the damage bonus represents a non-trivial component of the DPS output + // of weapons wielded by higher-level melee characters (especially for two-handed weapons). + + int ucDamageBonus = 0; + + if( Hand == 13 && GetLevel() >= 28 && IsWarriorClass() ) + { + // Damage bonuses apply only to hits from the main hand (Hand == 13) by characters level 28 and above + // who belong to a melee class. If we're here, then all of these conditions apply. + + ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); + + min_hit += (int) ucDamageBonus; + max_hit += (int) ucDamageBonus; + hate += ucDamageBonus; + } +#endif + //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. + if (Hand==14) { + if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ + + ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); + + min_hit += (int) ucDamageBonus; + max_hit += (int) ucDamageBonus; + hate += ucDamageBonus; + } + } + + min_hit += min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100; + + if(max_hit < min_hit) + max_hit = min_hit; + + if(RuleB(Combat, UseIntervalAC)) + damage = max_hit; + else + damage = MakeRandomInt(min_hit, max_hit); + + damage = mod_client_damage(damage, skillinuse, Hand, weapon, other); + + mlog(COMBAT__DAMAGE, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)", + damage, min_hit, max_hit, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel); + + if(opts) { + damage *= opts->damage_percent; + damage += opts->damage_flat; + hate *= opts->hate_percent; + hate += opts->hate_flat; + } + + //check to see if we hit.. + if(!other->CheckHitChance(this, skillinuse, Hand)) { + mlog(COMBAT__ATTACKS, "Attack missed. Damage set to 0."); + damage = 0; + } else { //we hit, try to avoid it + other->AvoidDamage(this, damage); + other->MeleeMitigation(this, damage, min_hit, opts); + if(damage > 0) { + ApplyMeleeDamageBonus(skillinuse, damage); + damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); + TryCriticalHit(other, skillinuse, damage, opts); + } + mlog(COMBAT__DAMAGE, "Final damage after all reductions: %d", damage); + } + + //riposte + bool slippery_attack = false; // Part of hack to allow riposte to become a miss, but still allow a Strikethrough chance (like on Live) + if (damage == -3) { + if (bRiposte) return false; + else { + if (Hand == 14) {// Do we even have it & was attack with mainhand? If not, don't bother with other calculations + //Live AA - SlipperyAttacks + //This spell effect most likely directly modifies the actual riposte chance when using offhand attack. + int16 OffhandRiposteFail = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail; + OffhandRiposteFail *= -1; //Live uses a negative value for this. + + if (OffhandRiposteFail && + (OffhandRiposteFail > 99 || (MakeRandomInt(0, 100) < OffhandRiposteFail))) { + damage = 0; // Counts as a miss + slippery_attack = true; + } else + DoRiposte(other); + if (IsDead()) return false; + } + else + DoRiposte(other); + if (IsDead()) return false; + } + } + + if (((damage < 0) || slippery_attack) && !bRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA + int16 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; + + if(bonusStrikeThrough && (MakeRandomInt(0, 100) < bonusStrikeThrough)) { + Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses! + Attack(other, Hand, false, true); // Strikethrough only gives another attempted hit + return false; + } + } + } + else{ + damage = -5; + } + + // Hate Generation is on a per swing basis, regardless of a hit, miss, or block, its always the same. + // If we are this far, this means we are atleast making a swing. + + if (!bRiposte) // Ripostes never generate any aggro. + other->AddToHateList(this, hate); + + /////////////////////////////////////////////////////////// + ////// Send Attack Damage + /////////////////////////////////////////////////////////// + other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); + + if (IsDead()) return false; + + MeleeLifeTap(damage); + + if (damage > 0) + CheckNumHitsRemaining(5); + + //break invis when you attack + if(invisible) { + mlog(COMBAT__ATTACKS, "Removing invisibility due to melee attack."); + BuffFadeByEffect(SE_Invisibility); + BuffFadeByEffect(SE_Invisibility2); + invisible = false; + } + if(invisible_undead) { + mlog(COMBAT__ATTACKS, "Removing invisibility vs. undead due to melee attack."); + BuffFadeByEffect(SE_InvisVsUndead); + BuffFadeByEffect(SE_InvisVsUndead2); + invisible_undead = false; + } + if(invisible_animals){ + mlog(COMBAT__ATTACKS, "Removing invisibility vs. animals due to melee attack."); + BuffFadeByEffect(SE_InvisVsAnimals); + invisible_animals = false; + } + + if(hidden || improved_hidden){ + hidden = false; + improved_hidden = false; + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; + sa_out->spawn_id = GetID(); + sa_out->type = 0x03; + sa_out->parameter = 0; + entity_list.QueueClients(this, outapp, true); + safe_delete(outapp); + } + + if(GetTarget()) + TriggerDefensiveProcs(weapon, other, Hand, damage); + + if (damage > 0) + return true; + + else + return false; +} + +//used by complete heal and #heal +void Mob::Heal() +{ + SetMaxHP(); + SendHPUpdate(); +} + +void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) +{ + if(dead || IsCorpse()) + return; + + if(spell_id==0) + spell_id = SPELL_UNKNOWN; + + if(spell_id!=0 && spell_id != SPELL_UNKNOWN && other && damage > 0) + { + if(other->IsNPC() && !other->IsPet()) + { + float npcspellscale = other->CastToNPC()->GetSpellScale(); + damage = ((float)damage * npcspellscale) / (float)100; + } + } + + // cut all PVP spell damage to 2/3 -solar + // EverHood - Blasting ourselfs is considered PvP + //Don't do PvP mitigation if the caster is damaging himself + if(other && other->IsClient() && (other != this) && damage > 0) { + int PvPMitigation = 100; + if(attack_skill == SkillArchery) + PvPMitigation = 80; + else + PvPMitigation = 67; + damage = (damage * PvPMitigation) / 100; + } + + if(!ClientFinishedLoading()) + damage = -5; + + //do a majority of the work... + CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); + + if (damage > 0) { + + if (spell_id == SPELL_UNKNOWN) + CheckIncreaseSkill(SkillDefense, other, -15); + } +} + +bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) +{ + if(!ClientFinishedLoading()) + return false; + + if(dead) + return false; //cant die more than once... + + if(!spell) + spell = SPELL_UNKNOWN; + + char buffer[48] = { 0 }; + snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); + if(parse->EventPlayer(EVENT_DEATH, this, buffer, 0) != 0) { + if(GetHP() < 0) { + SetHP(0); + } + return false; + } + + if(killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { + char val1[20]={0}; + entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE, + killerMob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); + } + + int exploss = 0; + mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob ? killerMob->GetName() : "Unknown", damage, spell, attack_skill); + + // + // #1: Send death packet to everyone + // + uint8 killed_level = GetLevel(); + + SendLogoutPackets(); + + //make our become corpse packet, and queue to ourself before OP_Death. + EQApplicationPacket app2(OP_BecomeCorpse, sizeof(BecomeCorpse_Struct)); + BecomeCorpse_Struct* bc = (BecomeCorpse_Struct*)app2.pBuffer; + bc->spawn_id = GetID(); + bc->x = GetX(); + bc->y = GetY(); + bc->z = GetZ(); + QueuePacket(&app2); + + // make death packet + EQApplicationPacket app(OP_Death, sizeof(Death_Struct)); + Death_Struct* d = (Death_Struct*)app.pBuffer; + d->spawn_id = GetID(); + d->killer_id = killerMob ? killerMob->GetID() : 0; + d->corpseid=GetID(); + d->bindzoneid = m_pp.binds[0].zoneId; + d->spell_id = spell == SPELL_UNKNOWN ? 0xffffffff : spell; + d->attack_skill = spell != SPELL_UNKNOWN ? 0xe7 : attack_skill; + d->damage = damage; + app.priority = 6; + entity_list.QueueClients(this, &app); + + // + // #2: figure out things that affect the player dying and mark them dead + // + + InterruptSpell(); + SetPet(0); + SetHorseId(0); + dead = true; + + if(GetMerc()) { + GetMerc()->Suspend(); + } + + if (killerMob != nullptr) + { + if (killerMob->IsNPC()) { + parse->EventNPC(EVENT_SLAY, killerMob->CastToNPC(), this, "", 0); + + mod_client_death_npc(killerMob); + + uint16 emoteid = killerMob->GetEmoteID(); + if(emoteid != 0) + killerMob->CastToNPC()->DoNPCEmote(KILLEDPC,emoteid); + killerMob->TrySpellOnKill(killed_level,spell); + } + + if(killerMob->IsClient() && (IsDueling() || killerMob->CastToClient()->IsDueling())) { + SetDueling(false); + SetDuelTarget(0); + if (killerMob->IsClient() && killerMob->CastToClient()->IsDueling() && killerMob->CastToClient()->GetDuelTarget() == GetID()) + { + //if duel opponent killed us... + killerMob->CastToClient()->SetDueling(false); + killerMob->CastToClient()->SetDuelTarget(0); + entity_list.DuelMessage(killerMob,this,false); + + mod_client_death_duel(killerMob); + + } else { + //otherwise, we just died, end the duel. + Mob* who = entity_list.GetMob(GetDuelTarget()); + if(who && who->IsClient()) { + who->CastToClient()->SetDueling(false); + who->CastToClient()->SetDuelTarget(0); + } + } + } + } + + entity_list.RemoveFromTargets(this); + hate_list.RemoveEnt(this); + RemoveAutoXTargets(); + + + //remove ourself from all proximities + ClearAllProximities(); + + // + // #3: exp loss and corpse generation + // + + // figure out if they should lose exp + if(RuleB(Character, UseDeathExpLossMult)){ + float GetNum [] = {0.005f,0.015f,0.025f,0.035f,0.045f,0.055f,0.065f,0.075f,0.085f,0.095f,0.110f }; + int Num = RuleI(Character, DeathExpLossMultiplier); + if((Num < 0) || (Num > 10)) + Num = 3; + float loss = GetNum[Num]; + exploss=(int)((float)GetEXP() * (loss)); //loose % of total XP pending rule (choose 0-10) + } + + if(!RuleB(Character, UseDeathExpLossMult)){ + exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000); + } + + if( (GetLevel() < RuleI(Character, DeathExpLossLevel)) || (GetLevel() > RuleI(Character, DeathExpLossMaxLevel)) || IsBecomeNPC() ) + { + exploss = 0; + } + else if( killerMob ) + { + if( killerMob->IsClient() ) + { + exploss = 0; + } + else if( killerMob->GetOwner() && killerMob->GetOwner()->IsClient() ) + { + exploss = 0; + } + } + + if(spell != SPELL_UNKNOWN) + { + uint32 buff_count = GetMaxTotalSlots(); + for(uint16 buffIt = 0; buffIt < buff_count; buffIt++) + { + if(buffs[buffIt].spellid == spell && buffs[buffIt].client) + { + exploss = 0; // no exp loss for pvp dot + break; + } + } + } + + bool LeftCorpse = false; + + // now we apply the exp loss, unmem their spells, and make a corpse + // unless they're a GM (or less than lvl 10 + if(!GetGM()) + { + if(exploss > 0) { + int32 newexp = GetEXP(); + if(exploss > newexp) { + //lost more than we have... wtf.. + newexp = 1; + } else { + newexp -= exploss; + } + SetEXP(newexp, GetAAXP()); + //m_epp.perAA = 0; //reset to no AA exp on death. + } + + //this generates a lot of 'updates' to the client that the client does not need + BuffFadeNonPersistDeath(); + if((GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover)) + UnmemSpellAll(true); + else + UnmemSpellAll(false); + + if(RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel) || RuleB(Character, LeaveNakedCorpses)) + { + // creating the corpse takes the cash/items off the player too + Corpse *new_corpse = new Corpse(this, exploss); + + char tmp[20]; + database.GetVariable("ServerType", tmp, 9); + if(atoi(tmp)==1 && killerMob != nullptr && killerMob->IsClient()){ + char tmp2[10] = {0}; + database.GetVariable("PvPreward", tmp, 9); + int reward = atoi(tmp); + if(reward==3){ + database.GetVariable("PvPitem", tmp2, 9); + int pvpitem = atoi(tmp2); + if(pvpitem>0 && pvpitem<200000) + new_corpse->SetPKItem(pvpitem); + } + else if(reward==2) + new_corpse->SetPKItem(-1); + else if(reward==1) + new_corpse->SetPKItem(1); + else + new_corpse->SetPKItem(0); + if(killerMob->CastToClient()->isgrouped) { + Group* group = entity_list.GetGroupByClient(killerMob->CastToClient()); + if(group != 0) + { + for(int i=0;i<6;i++) + { + if(group->members[i] != nullptr) + { + new_corpse->AllowMobLoot(group->members[i],i); + } + } + } + } + } + + entity_list.AddCorpse(new_corpse, GetID()); + SetID(0); + + //send the become corpse packet to everybody else in the zone. + entity_list.QueueClients(this, &app2, true); + + LeftCorpse = true; + } + +// if(!IsLD())//Todo: make it so an LDed client leaves corpse if its enabled +// MakeCorpse(exploss); + } else { + BuffFadeDetrimental(); + } + + // + // Finally, send em home + // + + // we change the mob variables, not pp directly, because Save() will copy + // from these and overwrite what we set in pp anyway + // + + if(LeftCorpse && (GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover)) + { + ClearDraggedCorpses(); + + RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000); + + SendRespawnBinds(); + } + else + { + if(isgrouped) + { + Group *g = GetGroup(); + if(g) + g->MemberZoned(this); + } + + Raid* r = entity_list.GetRaidByClient(this); + + if(r) + r->MemberZoned(this); + + dead_timer.Start(5000, true); + + m_pp.zone_id = m_pp.binds[0].zoneId; + m_pp.zoneInstance = 0; + database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id)); + + Save(); + + GoToDeath(); + } + + parse->EventPlayer(EVENT_DEATH_COMPLETE, this, buffer, 0); + return true; +} + +bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) +{ + int damage = 0; + + if (!other) { + SetTarget(nullptr); + LogFile->write(EQEMuLog::Error, "A null Mob object was passed to NPC::Attack() for evaluation!"); + return false; + } + + if(DivineAura()) + return(false); + + if(!GetTarget()) + SetTarget(other); + + //Check that we can attack before we calc heading and face our target + if (!IsAttackAllowed(other)) { + if (this->GetOwnerID()) + this->Say_StringID(NOT_LEGAL_TARGET); + if(other) { + if (other->IsClient()) + other->CastToClient()->RemoveXTarget(this, false); + RemoveFromHateList(other); + mlog(COMBAT__ATTACKS, "I am not allowed to attack %s", other->GetName()); + } + return false; + } + + FaceTarget(GetTarget()); + + SkillUseTypes skillinuse = SkillHandtoHand; + if (Hand == 13) { + skillinuse = static_cast(GetPrimSkill()); + OffHandAtk(false); + } + if (Hand == 14) { + skillinuse = static_cast(GetSecSkill()); + OffHandAtk(true); + } + + //figure out what weapon they are using, if any + const Item_Struct* weapon = nullptr; + if (Hand == 13 && equipment[SLOT_PRIMARY] > 0) + weapon = database.GetItem(equipment[SLOT_PRIMARY]); + else if (equipment[SLOT_SECONDARY]) + weapon = database.GetItem(equipment[SLOT_SECONDARY]); + + //We dont factor much from the weapon into the attack. + //Just the skill type so it doesn't look silly using punching animations and stuff while wielding weapons + if(weapon) { + mlog(COMBAT__ATTACKS, "Attacking with weapon: %s (%d) (too bad im not using it for much)", weapon->Name, weapon->ID); + + if(Hand == 14 && weapon->ItemType == ItemTypeShield){ + mlog(COMBAT__ATTACKS, "Attack with shield canceled."); + return false; + } + + switch(weapon->ItemType){ + case ItemType1HSlash: + skillinuse = Skill1HSlashing; + break; + case ItemType2HSlash: + skillinuse = Skill2HSlashing; + break; + case ItemType1HPiercing: + //skillinuse = Skill1HPiercing; + //break; + case ItemType2HPiercing: + skillinuse = Skill1HPiercing; // change to Skill2HPiercing once activated + break; + case ItemType1HBlunt: + skillinuse = Skill1HBlunt; + break; + case ItemType2HBlunt: + skillinuse = Skill2HBlunt; + break; + case ItemTypeBow: + skillinuse = SkillArchery; + break; + case ItemTypeLargeThrowing: + case ItemTypeSmallThrowing: + skillinuse = SkillThrowing; + break; + default: + skillinuse = SkillHandtoHand; + break; + } + } + + int weapon_damage = GetWeaponDamage(other, weapon); + + //do attack animation regardless of whether or not we can hit below + int16 charges = 0; + ItemInst weapon_inst(weapon, charges); + AttackAnimation(skillinuse, Hand, &weapon_inst); + + // Remove this once Skill2HPiercing is activated + //Work-around for there being no 2HP skill - We use 99 for the 2HB animation and 36 for pierce messages + if(skillinuse == 99) + skillinuse = static_cast(36); + + //basically "if not immune" then do the attack + if((weapon_damage) > 0) { + + //ele and bane dmg too + //NPCs add this differently than PCs + //if NPCs can't inheriently hit the target we don't add bane/magic dmg which isn't exactly the same as PCs + uint16 eleBane = 0; + if(weapon){ + if(weapon->BaneDmgBody == other->GetBodyType()){ + eleBane += weapon->BaneDmgAmt; + } + + if(weapon->BaneDmgRace == other->GetRace()){ + eleBane += weapon->BaneDmgRaceAmt; + } + + if(weapon->ElemDmgAmt){ + eleBane += (weapon->ElemDmgAmt * other->ResistSpell(weapon->ElemDmgType, 0, this) / 100); + } + } + + if(!RuleB(NPC, UseItemBonusesForNonPets)){ + if(!GetOwner()){ + eleBane = 0; + } + } + + uint8 otherlevel = other->GetLevel(); + uint8 mylevel = this->GetLevel(); + + otherlevel = otherlevel ? otherlevel : 1; + mylevel = mylevel ? mylevel : 1; + + //instead of calcing damage in floats lets just go straight to ints + if(RuleB(Combat, UseIntervalAC)) + damage = (max_dmg+eleBane); + else + damage = MakeRandomInt((min_dmg+eleBane),(max_dmg+eleBane)); + + + //check if we're hitting above our max or below it. + if((min_dmg+eleBane) != 0 && damage < (min_dmg+eleBane)) { + mlog(COMBAT__DAMAGE, "Damage (%d) is below min (%d). Setting to min.", damage, (min_dmg+eleBane)); + damage = (min_dmg+eleBane); + } + if((max_dmg+eleBane) != 0 && damage > (max_dmg+eleBane)) { + mlog(COMBAT__DAMAGE, "Damage (%d) is above max (%d). Setting to max.", damage, (max_dmg+eleBane)); + damage = (max_dmg+eleBane); + } + + damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other); + + int32 hate = damage; + if(IsPet()) + { + hate = hate * 100 / GetDamageTable(skillinuse); + } + + if(other->IsClient() && other->CastToClient()->IsSitting()) { + mlog(COMBAT__DAMAGE, "Client %s is sitting. Hitting for max damage (%d).", other->GetName(), (max_dmg+eleBane)); + damage = (max_dmg+eleBane); + damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); + + if(opts) { + damage *= opts->damage_percent; + damage += opts->damage_flat; + hate *= opts->hate_percent; + hate += opts->hate_flat; + } + + mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, GetName()); + // now add done damage to the hate list + other->AddToHateList(this, hate); + + } else { + if(opts) { + damage *= opts->damage_percent; + damage += opts->damage_flat; + hate *= opts->hate_percent; + hate += opts->hate_flat; + } + + if(!other->CheckHitChance(this, skillinuse, Hand)) { + damage = 0; //miss + } else { //hit, check for damage avoidance + other->AvoidDamage(this, damage); + other->MeleeMitigation(this, damage, min_dmg+eleBane, opts); + if(damage > 0) { + ApplyMeleeDamageBonus(skillinuse, damage); + damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); + TryCriticalHit(other, skillinuse, damage, opts); + } + mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, GetName()); + // now add done damage to the hate list + if(damage > 0) + { + other->AddToHateList(this, hate); + } + else + other->AddToHateList(this, 0); + } + } + + mlog(COMBAT__DAMAGE, "Final damage against %s: %d", other->GetName(), damage); + + if(other->IsClient() && IsPet() && GetOwner()->IsClient()) { + //pets do half damage to clients in pvp + damage=damage/2; + } + } + else + damage = -5; + + //cant riposte a riposte + if (bRiposte && damage == -3) { + mlog(COMBAT__DAMAGE, "Riposte of riposte canceled."); + return false; + } + + int16 DeathHP = 0; + DeathHP = other->GetDelayDeath() * -1; + + if(GetHP() > 0 && other->GetHP() >= DeathHP) { + other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, false); // Not avoidable client already had thier chance to Avoid + } else + return false; + + if (HasDied()) //killed by damage shield ect + return false; + + MeleeLifeTap(damage); + + if (damage > 0) + CheckNumHitsRemaining(5); + + //break invis when you attack + if(invisible) { + mlog(COMBAT__ATTACKS, "Removing invisibility due to melee attack."); + BuffFadeByEffect(SE_Invisibility); + BuffFadeByEffect(SE_Invisibility2); + invisible = false; + } + if(invisible_undead) { + mlog(COMBAT__ATTACKS, "Removing invisibility vs. undead due to melee attack."); + BuffFadeByEffect(SE_InvisVsUndead); + BuffFadeByEffect(SE_InvisVsUndead2); + invisible_undead = false; + } + if(invisible_animals){ + mlog(COMBAT__ATTACKS, "Removing invisibility vs. animals due to melee attack."); + BuffFadeByEffect(SE_InvisVsAnimals); + invisible_animals = false; + } + + if(hidden || improved_hidden) + { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; + sa_out->spawn_id = GetID(); + sa_out->type = 0x03; + sa_out->parameter = 0; + entity_list.QueueClients(this, outapp, true); + safe_delete(outapp); + } + + + hidden = false; + improved_hidden = false; + + //I doubt this works... + if (!GetTarget()) + return true; //We killed them + + if(!bRiposte && other->GetHP() > 0 ) { + TryWeaponProc(nullptr, weapon, other, Hand); //no weapon + TrySpellProc(nullptr, weapon, other, Hand); + } + + TriggerDefensiveProcs(nullptr, other, Hand, damage); + + // now check ripostes + if (damage == -3) { // riposting + DoRiposte(other); + } + + if (damage > 0) + return true; + + else + return false; +} + +void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) { + if(spell_id==0) + spell_id = SPELL_UNKNOWN; + + //handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds + if(attacked_timer.Check()) + { + mlog(COMBAT__HITS, "Triggering EVENT_ATTACK due to attack by %s", other->GetName()); + parse->EventNPC(EVENT_ATTACK, this, other, "", 0); + } + attacked_timer.Start(CombatEventTimer_expire); + + if (!IsEngaged()) + zone->AddAggroMob(); + + if(GetClass() == LDON_TREASURE) + { + if(IsLDoNLocked() && GetLDoNLockedSkill() != LDoNTypeMechanical) + { + damage = -5; + } + else + { + if(IsLDoNTrapped()) + { + Message_StringID(13, LDON_ACCIDENT_SETOFF2); + SpellFinished(GetLDoNTrapSpellID(), other, 10, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false); + SetLDoNTrapSpellID(0); + SetLDoNTrapped(false); + SetLDoNTrapDetected(false); + } + } + } + + //do a majority of the work... + CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); + + if(damage > 0) { + //see if we are gunna start fleeing + if(!IsPet()) CheckFlee(); + } +} + +bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) { + mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob->GetName(), damage, spell, attack_skill); + + Mob *oos = nullptr; + if(killerMob) { + oos = killerMob->GetOwnerOrSelf(); + + char buffer[48] = { 0 }; + snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); + if(parse->EventNPC(EVENT_DEATH, this, oos, buffer, 0) != 0) + { + if(GetHP() < 0) { + SetHP(0); + } + return false; + } + + if(killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { + char val1[20]={0}; + entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE, + killerMob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); + } + } else { + + char buffer[48] = { 0 }; + snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); + if(parse->EventNPC(EVENT_DEATH, this, nullptr, buffer, 0) != 0) + { + if(GetHP() < 0) { + SetHP(0); + } + return false; + } + } + + if (IsEngaged()) + { + zone->DelAggroMob(); +#if EQDEBUG >= 11 + LogFile->write(EQEMuLog::Debug,"NPC::Death() Mobs currently Aggro %i", zone->MobsAggroCount()); +#endif + } + SetHP(0); + SetPet(0); + Mob* killer = GetHateDamageTop(this); + + entity_list.RemoveFromTargets(this, p_depop); + + if(p_depop == true) + return false; + + BuffFadeAll(); + uint8 killed_level = GetLevel(); + + EQApplicationPacket* app= new EQApplicationPacket(OP_Death,sizeof(Death_Struct)); + Death_Struct* d = (Death_Struct*)app->pBuffer; + d->spawn_id = GetID(); + d->killer_id = killerMob ? killerMob->GetID() : 0; + d->bindzoneid = 0; + d->spell_id = spell == SPELL_UNKNOWN ? 0xffffffff : spell; + d->attack_skill = SkillDamageTypes[attack_skill]; + d->damage = damage; + app->priority = 6; + entity_list.QueueClients(killerMob, app, false); + + if(respawn2) { + respawn2->DeathReset(1); + } + + if (killerMob) { + if(GetClass() != LDON_TREASURE) + hate_list.Add(killerMob, damage); + } + + safe_delete(app); + + Mob *give_exp = hate_list.GetDamageTop(this); + + if(give_exp == nullptr) + give_exp = killer; + + if(give_exp && give_exp->HasOwner()) { + + bool ownerInGroup = false; + if((give_exp->HasGroup() && give_exp->GetGroup()->IsGroupMember(give_exp->GetUltimateOwner())) + || (give_exp->IsPet() && (give_exp->GetOwner()->IsClient() + || ( give_exp->GetOwner()->HasGroup() && give_exp->GetOwner()->GetGroup()->IsGroupMember(give_exp->GetOwner()->GetUltimateOwner()))))) + ownerInGroup = true; + + give_exp = give_exp->GetUltimateOwner(); + +#ifdef BOTS + if(!RuleB(Bots, BotGroupXP) && !ownerInGroup) { + give_exp = nullptr; + } +#endif //BOTS + } + + int PlayerCount = 0; // QueryServ Player Counting + + Client *give_exp_client = nullptr; + if(give_exp && give_exp->IsClient()) + give_exp_client = give_exp->CastToClient(); + + bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE); + if (give_exp_client && !IsCorpse() && MerchantType == 0) + { + Group *kg = entity_list.GetGroupByClient(give_exp_client); + Raid *kr = entity_list.GetRaidByClient(give_exp_client); + + int32 finalxp = EXP_FORMULA; + finalxp = give_exp_client->mod_client_xp(finalxp, this); + + if(kr) + { + if(!IsLdonTreasure) { + kr->SplitExp((finalxp), this); + if(killerMob && (kr->IsRaidMember(killerMob->GetName()) || kr->IsRaidMember(killerMob->GetUltimateOwner()->GetName()))) + killerMob->TrySpellOnKill(killed_level,spell); + } + /* Send the EVENT_KILLED_MERIT event for all raid members */ + for (int i = 0; i < MAX_RAID_MEMBERS; i++) { + if (kr->members[i].member != nullptr) { // If Group Member is Client + parse->EventNPC(EVENT_KILLED_MERIT, this, kr->members[i].member, "killed", 0); + + mod_npc_killed_merit(kr->members[i].member); + + if(RuleB(TaskSystem, EnableTaskSystem)) + kr->members[i].member->UpdateTasksOnKill(GetNPCTypeID()); + PlayerCount++; + } + } + + // QueryServ Logging - Raid Kills + if(RuleB(QueryServ, PlayerLogNPCKills)){ + ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); + PlayerCount = 0; + QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; + QS->s1.NPCID = this->GetNPCTypeID(); + QS->s1.ZoneID = this->GetZoneID(); + QS->s1.Type = 2; // Raid Fight + for (int i = 0; i < MAX_RAID_MEMBERS; i++) { + if (kr->members[i].member != nullptr) { // If Group Member is Client + Client *c = kr->members[i].member; + QS->Chars[PlayerCount].char_id = c->CharacterID(); + PlayerCount++; + } + } + worldserver.SendPacket(pack); // Send Packet to World + safe_delete(pack); + } + // End QueryServ Logging + + } + else if (give_exp_client->IsGrouped() && kg != nullptr) + { + if(!IsLdonTreasure) { + kg->SplitExp((finalxp), this); + if(killerMob && (kg->IsGroupMember(killerMob->GetName()) || kg->IsGroupMember(killerMob->GetUltimateOwner()->GetName()))) + killerMob->TrySpellOnKill(killed_level,spell); + } + /* Send the EVENT_KILLED_MERIT event and update kill tasks + * for all group members */ + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (kg->members[i] != nullptr && kg->members[i]->IsClient()) { // If Group Member is Client + Client *c = kg->members[i]->CastToClient(); + parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); + + mod_npc_killed_merit(c); + + if(RuleB(TaskSystem, EnableTaskSystem)) + c->UpdateTasksOnKill(GetNPCTypeID()); + + PlayerCount++; + } + } + + // QueryServ Logging - Group Kills + if(RuleB(QueryServ, PlayerLogNPCKills)){ + ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); + PlayerCount = 0; + QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; + QS->s1.NPCID = this->GetNPCTypeID(); + QS->s1.ZoneID = this->GetZoneID(); + QS->s1.Type = 1; // Group Fight + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (kg->members[i] != nullptr && kg->members[i]->IsClient()) { // If Group Member is Client + Client *c = kg->members[i]->CastToClient(); + QS->Chars[PlayerCount].char_id = c->CharacterID(); + PlayerCount++; + } + } + worldserver.SendPacket(pack); // Send Packet to World + safe_delete(pack); + } + // End QueryServ Logging + } + else + { + if(!IsLdonTreasure) { + int conlevel = give_exp->GetLevelCon(GetLevel()); + if (conlevel != CON_GREEN) + { + if(GetOwner() && GetOwner()->IsClient()){ + } + else { + give_exp_client->AddEXP((finalxp), conlevel); // Pyro: Comment this if NPC death crashes zone + if(killerMob && (killerMob->GetID() == give_exp_client->GetID() || killerMob->GetUltimateOwner()->GetID() == give_exp_client->GetID())) + killerMob->TrySpellOnKill(killed_level,spell); + } + } + } + /* Send the EVENT_KILLED_MERIT event */ + parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); + + mod_npc_killed_merit(give_exp_client); + + if(RuleB(TaskSystem, EnableTaskSystem)) + give_exp_client->UpdateTasksOnKill(GetNPCTypeID()); + + // QueryServ Logging - Solo + if(RuleB(QueryServ, PlayerLogNPCKills)){ + ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1)); + QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; + QS->s1.NPCID = this->GetNPCTypeID(); + QS->s1.ZoneID = this->GetZoneID(); + QS->s1.Type = 0; // Solo Fight + Client *c = give_exp_client; + QS->Chars[0].char_id = c->CharacterID(); + PlayerCount++; + worldserver.SendPacket(pack); // Send Packet to World + safe_delete(pack); + } + // End QueryServ Logging + } + } + + //do faction hits even if we are a merchant, so long as a player killed us + if(give_exp_client) + hate_list.DoFactionHits(GetNPCFactionID()); + + if (!HasOwner() && !IsMerc() && class_ != MERCHANT && class_ != ADVENTUREMERCHANT && !GetSwarmInfo() + && MerchantType == 0 && killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) || + (killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient()))) + { + if(killer != 0) + { + if(killer->GetOwner() != 0 && killer->GetOwner()->IsClient()) + killer = killer->GetOwner(); + + if(!killer->CastToClient()->GetGM() && killer->IsClient()) + this->CheckMinMaxLevel(killer); + } + entity_list.RemoveFromAutoXTargets(this); + uint16 emoteid = this->GetEmoteID(); + Corpse* corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata,level>54?RuleI(NPC,MajorNPCCorpseDecayTimeMS):RuleI(NPC,MinorNPCCorpseDecayTimeMS)); + entity_list.LimitRemoveNPC(this); + entity_list.AddCorpse(corpse, GetID()); + + entity_list.UnMarkNPC(GetID()); + entity_list.RemoveNPC(GetID()); + this->SetID(0); + if(killer != 0 && emoteid != 0) + corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid); + if(killer != 0 && killer->IsClient()) { + corpse->AllowMobLoot(killer, 0); + if(killer->IsGrouped()) { + Group* group = entity_list.GetGroupByClient(killer->CastToClient()); + if(group != 0) { + for(int i=0;i<6;i++) { // Doesnt work right, needs work + if(group->members[i] != nullptr) { + corpse->AllowMobLoot(group->members[i],i); + } + } + } + } + else if(killer->IsRaidGrouped()){ + Raid* r = entity_list.GetRaidByClient(killer->CastToClient()); + if(r){ + int i = 0; + for(int x = 0; x < MAX_RAID_MEMBERS; x++) + { + switch(r->GetLootType()) + { + case 0: + case 1: + if(r->members[x].member && r->members[x].IsRaidLeader){ + corpse->AllowMobLoot(r->members[x].member, i); + i++; + } + break; + case 2: + if(r->members[x].member && r->members[x].IsRaidLeader){ + corpse->AllowMobLoot(r->members[x].member, i); + i++; + } + else if(r->members[x].member && r->members[x].IsGroupLeader){ + corpse->AllowMobLoot(r->members[x].member, i); + i++; + } + break; + case 3: + if(r->members[x].member && r->members[x].IsLooter){ + corpse->AllowMobLoot(r->members[x].member, i); + i++; + } + break; + case 4: + if(r->members[x].member) + { + corpse->AllowMobLoot(r->members[x].member, i); + i++; + } + break; + } + } + } + } + } + + if(zone && zone->adv_data) + { + ServerZoneAdventureDataReply_Struct *sr = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; + if(sr->type == Adventure_Kill) + { + zone->DoAdventureCountIncrease(); + } + else if(sr->type == Adventure_Assassinate) + { + if(sr->data_id == GetNPCTypeID()) + { + zone->DoAdventureCountIncrease(); + } + else + { + zone->DoAdventureAssassinationCountIncrease(); + } + } + } + } + else + entity_list.RemoveFromXTargets(this); + + // Parse quests even if we're killed by an NPC + if(oos) { + mod_npc_killed(oos); + + uint16 emoteid = this->GetEmoteID(); + if(emoteid != 0) + this->DoNPCEmote(ONDEATH, emoteid); + if(oos->IsNPC()) + { + parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0); + uint16 emoteid = oos->GetEmoteID(); + if(emoteid != 0) + oos->CastToNPC()->DoNPCEmote(KILLEDNPC, emoteid); + killerMob->TrySpellOnKill(killed_level, spell); + } + } + + WipeHateList(); + p_depop = true; + if(killerMob && killerMob->GetTarget() == this) //we can kill things without having them targeted + killerMob->SetTarget(nullptr); //via AE effects and such.. + + entity_list.UpdateFindableNPCState(this, true); + + char buffer[48] = { 0 }; + snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); + parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, buffer, 0); + return true; +} + +void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) { + + assert(other != nullptr); + + if (other == this) + return; + + if(damage < 0){ + hate = 1; + } + + bool wasengaged = IsEngaged(); + Mob* owner = other->GetOwner(); + Mob* mypet = this->GetPet(); + Mob* myowner = this->GetOwner(); + Mob* targetmob = this->GetTarget(); + + if(other){ + AddRampage(other); + int hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod; + + int16 shieldhatemod = other->spellbonuses.ShieldEquipHateMod + other->itembonuses.ShieldEquipHateMod + other->aabonuses.ShieldEquipHateMod; + + if (shieldhatemod && other->HasShieldEquiped()) + hatemod += shieldhatemod; + + if(hatemod < 1) + hatemod = 1; + hate = ((hate * (hatemod))/100); + } + + if(IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && !IsFocused()) { //ignore aggro if hold and !focus + return; + } + + if(IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && GetOwner()->GetAA(aaAdvancedPetDiscipline) >= 1 && IsFocused()) { + if (!targetmob) + return; + } + + if (other->IsNPC() && (other->IsPet() || other->CastToNPC()->GetSwarmOwner() > 0)) + TryTriggerOnValueAmount(false, false, false, true); + + if(IsClient() && !IsAIControlled()) + return; + + if(IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO)) + return; + + if (other == myowner) + return; + + if(other->GetSpecialAbility(IMMUNE_AGGRO_ON)) + return; + + if(GetSpecialAbility(NPC_TUNNELVISION)) { + int tv_mod = GetSpecialAbilityParam(NPC_TUNNELVISION, 0); + + Mob *top = GetTarget(); + if(top && top != other) { + if(tv_mod) { + float tv = tv_mod / 100.0f; + hate *= tv; + } else { + hate *= RuleR(Aggro, TunnelVisionAggroMod); + } + } + } + + if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { + if(!zone->watermap->InLiquid(other->GetX(), other->GetY(), other->GetZ())) { + return; + } + } + // first add self + + // The damage on the hate list is used to award XP to the killer. This check is to prevent Killstealing. + // e.g. Mob has 5000 hit points, Player A melees it down to 500 hp, Player B executes a headshot (10000 damage). + // If we add 10000 damage, Player B would get the kill credit, so we only award damage credit to player B of the + // amount of HP the mob had left. + // + if(damage > GetHP()) + damage = GetHP(); + + if (spellbonuses.ImprovedTaunt[1] && (GetLevel() < spellbonuses.ImprovedTaunt[0]) + && other && (buffs[spellbonuses.ImprovedTaunt[2]].casterid != other->GetID())) + hate = (hate*spellbonuses.ImprovedTaunt[1])/100; + + hate_list.Add(other, hate, damage, bFrenzy, !iBuffTic); + + if(other->IsClient()) + other->CastToClient()->AddAutoXTarget(this); + +#ifdef BOTS + // if other is a bot, add the bots client to the hate list + if(other->IsBot()) { + if(other->CastToBot()->GetBotOwner() && other->CastToBot()->GetBotOwner()->CastToClient()->GetFeigned()) { + AddFeignMemory(other->CastToBot()->GetBotOwner()->CastToClient()); + } + else { + if(!hate_list.IsOnHateList(other->CastToBot()->GetBotOwner())) + hate_list.Add(other->CastToBot()->GetBotOwner(), 0, 0, false, true); + } + } +#endif //BOTS + + + // if other is a merc, add the merc client to the hate list + if(other->IsMerc()) { + if(other->CastToMerc()->GetMercOwner() && other->CastToMerc()->GetMercOwner()->CastToClient()->GetFeigned()) { + AddFeignMemory(other->CastToMerc()->GetMercOwner()->CastToClient()); + } + else { + if(!hate_list.IsOnHateList(other->CastToMerc()->GetMercOwner())) + hate_list.Add(other->CastToMerc()->GetMercOwner(), 0, 0, false, true); + } + } //MERC + + // then add pet owner if there's one + if (owner) { // Other is a pet, add him and it + // EverHood 6/12/06 + // Can't add a feigned owner to hate list + if(owner->IsClient() && owner->CastToClient()->GetFeigned()) { + //they avoid hate due to feign death... + } else { + // cb:2007-08-17 + // owner must get on list, but he's not actually gained any hate yet + if(!owner->GetSpecialAbility(IMMUNE_AGGRO)) + { + hate_list.Add(owner, 0, 0, false, !iBuffTic); + if(owner->IsClient()) + owner->CastToClient()->AddAutoXTarget(this); + } + } + } + + if (mypet && (!(GetAA(aaPetDiscipline) && mypet->IsHeld()))) { // I have a pet, add other to it + if(!mypet->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO)) + mypet->hate_list.Add(other, 0, 0, bFrenzy); + } else if (myowner) { // I am a pet, add other to owner if it's NPC/LD + if (myowner->IsAIControlled() && !myowner->GetSpecialAbility(IMMUNE_AGGRO)) + myowner->hate_list.Add(other, 0, 0, bFrenzy); + } + if (!wasengaged) { + if(IsNPC() && other->IsClient() && other->CastToClient()) + parse->EventNPC(EVENT_AGGRO, this->CastToNPC(), other, "", 0); + AI_Event_Engaged(other, iYellForHelp); + } +} + +// solar: this is called from Damage() when 'this' is attacked by 'other. +// 'this' is the one being attacked +// 'other' is the attacker +// a damage shield causes damage (or healing) to whoever attacks the wearer +// a reverse ds causes damage to the wearer whenever it attack someone +// given this, a reverse ds must be checked each time the wearer is attacking +// and not when they're attacked +//a damage shield on a spell is a negative value but on an item it's a positive value so add the spell value and subtract the item value to get the end ds value +void Mob::DamageShield(Mob* attacker, bool spell_ds) { + + if(!attacker || this == attacker) + return; + + int DS = 0; + int rev_ds = 0; + uint16 spellid = 0; + + if(!spell_ds) + { + DS = spellbonuses.DamageShield; + rev_ds = attacker->spellbonuses.ReverseDamageShield; + + if(spellbonuses.DamageShieldSpellID != 0 && spellbonuses.DamageShieldSpellID != SPELL_UNKNOWN) + spellid = spellbonuses.DamageShieldSpellID; + } + else { + DS = spellbonuses.SpellDamageShield; + rev_ds = 0; + // This ID returns "you are burned", seemed most appropriate for spell DS + spellid = 2166; + } + + if(DS == 0 && rev_ds == 0) + return; + + mlog(COMBAT__HITS, "Applying Damage Shield of value %d to %s", DS, attacker->GetName()); + + //invert DS... spells yield negative values for a true damage shield + if(DS < 0) { + if(!spell_ds) { + + DS += aabonuses.DamageShield; //Live AA - coat of thistles. (negative value) + DS -= itembonuses.DamageShield; //+Damage Shield should only work when you already have a DS spell + + //Spell data for damage shield mitigation shows a negative value for spells for clients and positive + //value for spells that effect pets. Unclear as to why. For now will convert all positive to be consistent. + if (attacker->IsOffHandAtk()){ + int16 mitigation = attacker->itembonuses.DSMitigationOffHand + + attacker->spellbonuses.DSMitigationOffHand + + attacker->aabonuses.DSMitigationOffHand; + DS -= DS*mitigation/100; + } + DS -= DS * attacker->itembonuses.DSMitigation / 100; + } + attacker->Damage(this, -DS, spellid, SkillAbjuration/*hackish*/, false); + //we can assume there is a spell now + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); + CombatDamage_Struct* cds = (CombatDamage_Struct*)outapp->pBuffer; + cds->target = attacker->GetID(); + cds->source = GetID(); + cds->type = spellbonuses.DamageShieldType; + cds->spellid = 0x0; + cds->damage = DS; + entity_list.QueueCloseClients(this, outapp); + safe_delete(outapp); + } else if (DS > 0 && !spell_ds) { + //we are healing the attacker... + attacker->HealDamage(DS); + //TODO: send a packet??? + } + + //Reverse DS + //this is basically a DS, but the spell is on the attacker, not the attackee + //if we've gotten to this point, we know we know "attacker" hit "this" (us) for damage & we aren't invulnerable + uint16 rev_ds_spell_id = SPELL_UNKNOWN; + + if(spellbonuses.ReverseDamageShieldSpellID != 0 && spellbonuses.ReverseDamageShieldSpellID != SPELL_UNKNOWN) + rev_ds_spell_id = spellbonuses.ReverseDamageShieldSpellID; + + if(rev_ds < 0) { + mlog(COMBAT__HITS, "Applying Reverse Damage Shield of value %d to %s", rev_ds, attacker->GetName()); + attacker->Damage(this, -rev_ds, rev_ds_spell_id, SkillAbjuration/*hackish*/, false); //"this" (us) will get the hate, etc. not sure how this works on Live, but it'll works for now, and tanks will love us for this + //do we need to send a damage packet here also? + } +} + +uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) +{ + // This function calculates and returns the damage bonus for the weapon identified by the parameter "Weapon". + // Modified 9/21/2008 by Cantus + + + // Assert: This function should only be called for hits by the mainhand, as damage bonuses apply only to the + // weapon in the primary slot. Be sure to check that Hand == 13 before calling. + + // Assert: The caller should ensure that Weapon is actually a weapon before calling this function. + // The ItemInst::IsWeapon() method can be used to quickly determine this. + + // Assert: This function should not be called if the player's level is below 28, as damage bonuses do not begin + // to apply until level 28. + + // Assert: This function should not be called unless the player is a melee class, as casters do not receive a damage bonus. + + + if( Weapon == nullptr || Weapon->ItemType == ItemType1HSlash || Weapon->ItemType == ItemType1HBlunt || Weapon->ItemType == ItemTypeMartial || Weapon->ItemType == ItemType1HPiercing ) + { + // The weapon in the player's main (primary) hand is a one-handed weapon, or there is no item equipped at all. + // + // According to player posts on Allakhazam, 1H damage bonuses apply to bare fists (nothing equipped in the mainhand, + // as indicated by Weapon == nullptr). + // + // The following formula returns the correct damage bonus for all 1H weapons: + + return (uint8) ((GetLevel() - 25) / 3); + } + + // If we've gotten to this point, the weapon in the mainhand is a two-handed weapon. + // Calculating damage bonuses for 2H weapons is more complicated, as it's based on PC level AND the delay of the weapon. + // The formula to calculate 2H bonuses is HIDEOUS. It's a huge conglomeration of ternary operators and multiple operations. + // + // The following is a hybrid approach. In cases where the Level and Delay merit a formula that does not use many operators, + // the formula is used. In other cases, lookup tables are used for speed. + // Though the following code may look bloated and ridiculous, it's actually a very efficient way of calculating these bonuses. + + // Player Level is used several times in the code below, so save it into a variable. + // If GetLevel() were an ordinary function, this would DEFINITELY make sense, as it'd cut back on all of the function calling + // overhead involved with multiple calls to GetLevel(). But in this case, GetLevel() is a simple, inline accessor method. + // So it probably doesn't matter. If anyone knows for certain that there is no overhead involved with calling GetLevel(), + // as I suspect, then please feel free to delete the following line, and replace all occurences of "ucPlayerLevel" with "GetLevel()". + uint8 ucPlayerLevel = (uint8) GetLevel(); + + + // The following may look cleaner, and would certainly be easier to understand, if it was + // a simple 53x150 cell matrix. + // + // However, that would occupy 7,950 Bytes of memory (7.76 KB), and would likely result + // in "thrashing the cache" when performing lookups. + // + // Initially, I thought the best approach would be to reverse-engineer the formula used by + // Sony/Verant to calculate these 2H weapon damage bonuses. But the more than Reno and I + // worked on figuring out this formula, the more we're concluded that the formula itself ugly + // (that is, it contains so many operations and conditionals that it's fairly CPU intensive). + // Because of that, we're decided that, in most cases, a lookup table is the most efficient way + // to calculate these damage bonuses. + // + // The code below is a hybrid between a pure formulaic approach and a pure, brute-force + // lookup table. In cases where a formula is the best bet, I use a formula. In other places + // where a formula would be ugly, I use a lookup table in the interests of speed. + + + if( Weapon->Delay <= 27 ) + { + // Damage Bonuses for all 2H weapons with delays of 27 or less are identical. + // They are the same as the damage bonus would be for a corresponding 1H weapon, plus one. + // This formula applies to all levels 28-80, and will probably continue to apply if + + // the level cap on Live ever is increased beyond 80. + + return (ucPlayerLevel - 22) / 3; + } + + + if( ucPlayerLevel == 65 && Weapon->Delay <= 59 ) + { + // Consider these two facts: + // * Level 65 is the maximum level on many EQ Emu servers. + // * If you listed the levels of all characters logged on to a server, odds are that the number you'll + // see most frequently is level 65. That is, there are more level 65 toons than any other single level. + // + // Therefore, if we can optimize this function for level 65 toons, we're speeding up the server! + // + // With that goal in mind, I create an array of Damage Bonuses for level 65 characters wielding 2H weapons with + // delays between 28 and 59 (inclusive). I suspect that this one small lookup array will therefore handle + // many of the calls to this function. + + static const uint8 ucLevel65DamageBonusesForDelays28to59[] = {35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 42, 42, 42, 45, 45, 47, 48, 49, 49, 51, 51, 52, 53, 54, 54, 56, 56, 57, 58, 59}; + + return ucLevel65DamageBonusesForDelays28to59[Weapon->Delay-28]; + } + + + if( ucPlayerLevel > 65 ) + { + if( ucPlayerLevel > 80 ) + { + // As level 80 is currently the highest achievable level on Live, we only include + // damage bonus information up to this level. + // + // If there is a custom EQEmu server that allows players to level beyond 80, the + // damage bonus for their 2H weapons will simply not increase beyond their damage + // bonus at level 80. + + ucPlayerLevel = 80; + } + + // Lucy does not list a chart of damage bonuses for players levels 66+, + // so my original version of this function just applied the level 65 damage + // bonus for level 66+ toons. That sucked for higher level toons, as their + // 2H weapons stopped ramping up in DPS as they leveled past 65. + // + // Thanks to the efforts of two guys, this is no longer the case: + // + // Janusd (Zetrakyl) ran a nifty query against the PEQ item database to list + // the name of an example 2H weapon that represents each possible unique 2H delay. + // + // Romai then wrote an excellent script to automatically look up each of those + // weapons, open the Lucy item page associated with it, and iterate through all + // levels in the range 66 - 80. He saved the damage bonus for that weapon for + // each level, and that forms the basis of the lookup tables below. + + if( Weapon->Delay <= 59 ) + { + static const uint8 ucDelay28to59Levels66to80[32][15]= + { + /* Level: */ + /* 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 */ + + {36, 37, 38, 39, 41, 42, 43, 44, 45, 47, 49, 49, 49, 50, 53}, /* Delay = 28 */ + {36, 38, 38, 39, 42, 43, 43, 45, 46, 48, 49, 50, 51, 52, 54}, /* Delay = 29 */ + {37, 38, 39, 40, 43, 43, 44, 46, 47, 48, 50, 51, 52, 53, 55}, /* Delay = 30 */ + {37, 39, 40, 40, 43, 44, 45, 46, 47, 49, 51, 52, 52, 52, 54}, /* Delay = 31 */ + {38, 39, 40, 41, 44, 45, 45, 47, 48, 48, 50, 52, 53, 55, 57}, /* Delay = 32 */ + {38, 40, 41, 41, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 58}, /* Delay = 33 */ + {39, 40, 41, 42, 45, 46, 47, 48, 49, 51, 53, 54, 55, 57, 58}, /* Delay = 34 */ + {39, 41, 42, 43, 46, 46, 47, 49, 50, 52, 54, 55, 56, 57, 59}, /* Delay = 35 */ + {40, 41, 42, 43, 46, 47, 48, 50, 51, 53, 55, 55, 56, 58, 60}, /* Delay = 36 */ + {40, 42, 43, 44, 47, 48, 49, 50, 51, 53, 55, 56, 57, 59, 61}, /* Delay = 37 */ + {41, 42, 43, 44, 47, 48, 49, 51, 52, 54, 56, 57, 58, 60, 62}, /* Delay = 38 */ + {41, 43, 44, 45, 48, 49, 50, 52, 53, 55, 57, 58, 59, 61, 63}, /* Delay = 39 */ + {43, 45, 46, 47, 50, 51, 52, 54, 55, 57, 59, 60, 61, 63, 65}, /* Delay = 40 */ + {43, 45, 46, 47, 50, 51, 52, 54, 55, 57, 59, 60, 61, 63, 65}, /* Delay = 41 */ + {44, 46, 47, 48, 51, 52, 53, 55, 56, 58, 60, 61, 62, 64, 66}, /* Delay = 42 */ + {46, 48, 49, 50, 53, 54, 55, 58, 59, 61, 63, 64, 65, 67, 69}, /* Delay = 43 */ + {47, 49, 50, 51, 54, 55, 56, 58, 59, 61, 64, 65, 66, 68, 70}, /* Delay = 44 */ + {48, 50, 51, 52, 56, 57, 58, 60, 61, 63, 65, 66, 68, 70, 72}, /* Delay = 45 */ + {50, 52, 53, 54, 57, 58, 59, 62, 63, 65, 67, 68, 69, 71, 74}, /* Delay = 46 */ + {50, 52, 53, 55, 58, 59, 60, 62, 63, 66, 68, 69, 70, 72, 74}, /* Delay = 47 */ + {51, 53, 54, 55, 58, 60, 61, 63, 64, 66, 69, 69, 71, 73, 75}, /* Delay = 48 */ + {52, 54, 55, 57, 60, 61, 62, 65, 66, 68, 70, 71, 73, 75, 77}, /* Delay = 49 */ + {53, 55, 56, 57, 61, 62, 63, 65, 67, 69, 71, 72, 74, 76, 78}, /* Delay = 50 */ + {53, 55, 57, 58, 61, 62, 64, 66, 67, 69, 72, 73, 74, 77, 79}, /* Delay = 51 */ + {55, 57, 58, 59, 63, 64, 65, 68, 69, 71, 74, 75, 76, 78, 81}, /* Delay = 52 */ + {57, 55, 59, 60, 63, 65, 66, 68, 70, 72, 74, 76, 77, 79, 82}, /* Delay = 53 */ + {56, 58, 59, 61, 64, 65, 67, 69, 70, 73, 75, 76, 78, 80, 82}, /* Delay = 54 */ + {57, 59, 61, 62, 66, 67, 68, 71, 72, 74, 77, 78, 80, 82, 84}, /* Delay = 55 */ + {58, 60, 61, 63, 66, 68, 69, 71, 73, 75, 78, 79, 80, 83, 85}, /* Delay = 56 */ + + /* Important Note: Janusd's search for 2H weapons did not find */ + /* any 2H weapon with a delay of 57. Therefore the values below */ + /* are interpolated, not exact! */ + {59, 61, 62, 64, 67, 69, 70, 72, 74, 76, 77, 78, 81, 84, 86}, /* Delay = 57 INTERPOLATED */ + + {60, 62, 63, 65, 68, 70, 71, 74, 75, 78, 80, 81, 83, 85, 88}, /* Delay = 58 */ + + /* Important Note: Janusd's search for 2H weapons did not find */ + /* any 2H weapon with a delay of 59. Therefore the values below */ + /* are interpolated, not exact! */ + {60, 62, 64, 65, 69, 70, 72, 74, 76, 78, 81, 82, 84, 86, 89}, /* Delay = 59 INTERPOLATED */ + }; + + return ucDelay28to59Levels66to80[Weapon->Delay-28][ucPlayerLevel-66]; + } + else + { + // Delay is 60+ + + const static uint8 ucDelayOver59Levels66to80[6][15] = + { + /* Level: */ + /* 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 */ + + {61, 63, 65, 66, 70, 71, 73, 75, 77, 79, 82, 83, 85, 87, 90}, /* Delay = 60 */ + {65, 68, 69, 71, 75, 76, 78, 80, 82, 85, 87, 89, 91, 93, 96}, /* Delay = 65 */ + + /* Important Note: Currently, the only 2H weapon with a delay */ + /* of 66 is not player equippable (it's None/None). So I'm */ + /* leaving it commented out to keep this table smaller. */ + //{66, 68, 70, 71, 75, 77, 78, 81, 83, 85, 88, 90, 91, 94, 97}, /* Delay = 66 */ + + {70, 72, 74, 76, 80, 81, 83, 86, 88, 88, 90, 95, 97, 99, 102}, /* Delay = 70 */ + {82, 85, 87, 89, 89, 94, 98, 101, 103, 106, 109, 111, 114, 117, 120}, /* Delay = 85 */ + {90, 93, 96, 98, 103, 105, 107, 111, 113, 116, 120, 122, 125, 128, 131}, /* Delay = 95 */ + + /* Important Note: Currently, the only 2H weapons with delay */ + /* 100 are GM-only items purchased from vendors in Sunset Home */ + /* (cshome). Because they are highly unlikely to be used in */ + /* combat, I'm commenting it out to keep the table smaller. */ + //{95, 98, 101, 103, 108, 110, 113, 116, 119, 122, 126, 128, 131, 134, 138},/* Delay = 100 */ + + {136, 140, 144, 148, 154, 157, 161, 166, 170, 174, 179, 183, 187, 191, 196} /* Delay = 150 */ + }; + + if( Weapon->Delay < 65 ) + { + return ucDelayOver59Levels66to80[0][ucPlayerLevel-66]; + } + else if( Weapon->Delay < 70 ) + { + return ucDelayOver59Levels66to80[1][ucPlayerLevel-66]; + } + else if( Weapon->Delay < 85 ) + { + return ucDelayOver59Levels66to80[2][ucPlayerLevel-66]; + } + else if( Weapon->Delay < 95 ) + { + return ucDelayOver59Levels66to80[3][ucPlayerLevel-66]; + } + else if( Weapon->Delay < 150 ) + { + return ucDelayOver59Levels66to80[4][ucPlayerLevel-66]; + } + else + { + return ucDelayOver59Levels66to80[5][ucPlayerLevel-66]; + } + } + } + + + // If we've gotten to this point in the function without hitting a return statement, + // we know that the character's level is between 28 and 65, and that the 2H weapon's + // delay is 28 or higher. + + // The Damage Bonus values returned by this function (in the level 28-65 range) are + // based on a table of 2H Weapon Damage Bonuses provided by Lucy at the following address: + // http://lucy.allakhazam.com/dmgbonus.html + + if( Weapon->Delay <= 39 ) + { + if( ucPlayerLevel <= 53) + { + // The Damage Bonus for all 2H weapons with delays between 28 and 39 (inclusive) is the same for players level 53 and below... + static const uint8 ucDelay28to39LevelUnder54[] = {1, 1, 2, 3, 3, 3, 4, 5, 5, 6, 6, 6, 8, 8, 8, 9, 9, 10, 11, 11, 11, 12, 13, 14, 16, 17}; + + // As a note: The following formula accurately calculates damage bonuses for 2H weapons with delays in the range 28-39 (inclusive) + // for characters levels 28-50 (inclusive): + // return ( (ucPlayerLevel - 22) / 3 ) + ( (ucPlayerLevel - 25) / 5 ); + // + // However, the small lookup array used above is actually much faster. So we'll just use it instead of the formula + // + // (Thanks to Reno for helping figure out the above formula!) + + return ucDelay28to39LevelUnder54[ucPlayerLevel-28]; + } + else + { + // Use a matrix to look up the damage bonus for 2H weapons with delays between 28 and 39 wielded by characters level 54 and above. + static const uint8 ucDelay28to39Level54to64[12][11] = + { + /* Level: */ + /* 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 */ + + {17, 21, 21, 23, 25, 26, 28, 30, 31, 31, 33}, /* Delay = 28 */ + {17, 21, 22, 23, 25, 26, 29, 30, 31, 32, 34}, /* Delay = 29 */ + {18, 21, 22, 23, 25, 27, 29, 31, 32, 32, 34}, /* Delay = 30 */ + {18, 21, 22, 23, 25, 27, 29, 31, 32, 33, 34}, /* Delay = 31 */ + {18, 21, 22, 24, 26, 27, 30, 32, 32, 33, 35}, /* Delay = 32 */ + {18, 21, 22, 24, 26, 27, 30, 32, 33, 34, 35}, /* Delay = 33 */ + {18, 22, 22, 24, 26, 28, 30, 32, 33, 34, 36}, /* Delay = 34 */ + {18, 22, 23, 24, 26, 28, 31, 33, 34, 34, 36}, /* Delay = 35 */ + {18, 22, 23, 25, 27, 28, 31, 33, 34, 35, 37}, /* Delay = 36 */ + {18, 22, 23, 25, 27, 29, 31, 33, 34, 35, 37}, /* Delay = 37 */ + {18, 22, 23, 25, 27, 29, 32, 34, 35, 36, 38}, /* Delay = 38 */ + {18, 22, 23, 25, 27, 29, 32, 34, 35, 36, 38} /* Delay = 39 */ + }; + + return ucDelay28to39Level54to64[Weapon->Delay-28][ucPlayerLevel-54]; + } + } + else if( Weapon->Delay <= 59 ) + { + if( ucPlayerLevel <= 52 ) + { + if( Weapon->Delay <= 45 ) + { + static const uint8 ucDelay40to45Levels28to52[6][25] = + { + /* Level: */ + /* 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52 */ + + {2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 7, 7, 9, 9, 9, 10, 10, 11, 12, 12, 12, 13, 14, 16, 18}, /* Delay = 40 */ + {2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 7, 7, 9, 9, 9, 10, 10, 11, 12, 12, 12, 13, 14, 16, 18}, /* Delay = 41 */ + {2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 7, 7, 9, 9, 9, 10, 10, 11, 12, 12, 12, 13, 14, 16, 18}, /* Delay = 42 */ + {4, 4, 5, 6, 6, 6, 7, 8, 8, 9, 9, 9, 11, 11, 11, 12, 12, 13, 14, 14, 14, 15, 16, 18, 20}, /* Delay = 43 */ + {4, 4, 5, 6, 6, 6, 7, 8, 8, 9, 9, 9, 11, 11, 11, 12, 12, 13, 14, 14, 14, 15, 16, 18, 20}, /* Delay = 44 */ + {5, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 10, 12, 12, 12, 13, 13, 14, 15, 15, 15, 16, 17, 19, 21} /* Delay = 45 */ + }; + + return ucDelay40to45Levels28to52[Weapon->Delay-40][ucPlayerLevel-28]; + } + else + { + static const uint8 ucDelay46Levels28to52[] = {6, 6, 7, 8, 8, 8, 9, 10, 10, 11, 11, 11, 13, 13, 13, 14, 14, 15, 16, 16, 16, 17, 18, 20, 22}; + + return ucDelay46Levels28to52[ucPlayerLevel-28] + ((Weapon->Delay-46) / 3); + } + } + else + { + // Player is in the level range 53 - 64 + + // Calculating damage bonus for 2H weapons with a delay between 40 and 59 (inclusive) involves, unforunately, a brute-force matrix lookup. + static const uint8 ucDelay40to59Levels53to64[20][37] = + { + /* Level: */ + /* 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 */ + + {19, 20, 24, 25, 27, 29, 31, 34, 36, 37, 38, 40}, /* Delay = 40 */ + {19, 20, 24, 25, 27, 29, 31, 34, 36, 37, 38, 40}, /* Delay = 41 */ + {19, 20, 24, 25, 27, 29, 31, 34, 36, 37, 38, 40}, /* Delay = 42 */ + {21, 22, 26, 27, 29, 31, 33, 37, 39, 40, 41, 43}, /* Delay = 43 */ + {21, 22, 26, 27, 29, 32, 34, 37, 39, 40, 41, 43}, /* Delay = 44 */ + {22, 23, 27, 28, 31, 33, 35, 38, 40, 42, 43, 45}, /* Delay = 45 */ + {23, 24, 28, 30, 32, 34, 36, 40, 42, 43, 44, 46}, /* Delay = 46 */ + {23, 24, 29, 30, 32, 34, 37, 40, 42, 43, 44, 47}, /* Delay = 47 */ + {23, 24, 29, 30, 32, 35, 37, 40, 43, 44, 45, 47}, /* Delay = 48 */ + {24, 25, 30, 31, 34, 36, 38, 42, 44, 45, 46, 49}, /* Delay = 49 */ + {24, 26, 30, 31, 34, 36, 39, 42, 44, 46, 47, 49}, /* Delay = 50 */ + {24, 26, 30, 31, 34, 36, 39, 42, 45, 46, 47, 49}, /* Delay = 51 */ + {25, 27, 31, 33, 35, 38, 40, 44, 46, 47, 49, 51}, /* Delay = 52 */ + {25, 27, 31, 33, 35, 38, 40, 44, 46, 48, 49, 51}, /* Delay = 53 */ + {26, 27, 32, 33, 36, 38, 41, 44, 47, 48, 49, 52}, /* Delay = 54 */ + {27, 28, 33, 34, 37, 39, 42, 46, 48, 50, 51, 53}, /* Delay = 55 */ + {27, 28, 33, 34, 37, 40, 42, 46, 49, 50, 51, 54}, /* Delay = 56 */ + {27, 28, 33, 34, 37, 40, 43, 46, 49, 50, 52, 54}, /* Delay = 57 */ + {28, 29, 34, 36, 39, 41, 44, 48, 50, 52, 53, 56}, /* Delay = 58 */ + {28, 29, 34, 36, 39, 41, 44, 48, 51, 52, 54, 56} /* Delay = 59 */ + }; + + return ucDelay40to59Levels53to64[Weapon->Delay-40][ucPlayerLevel-53]; + } + } + else + { + // The following table allows us to look up Damage Bonuses for weapons with delays greater than or equal to 60. + // + // There aren't a lot of 2H weapons with a delay greater than 60. In fact, both a database and Lucy search run by janusd confirm + // that the only unique 2H delays greater than 60 are: 65, 70, 85, 95, and 150. + // + // To be fair, there are also weapons with delays of 66 and 100. But they are either not equippable (None/None), or are + // only available to GMs from merchants in Sunset Home (cshome). In order to keep this table "lean and mean", I will not + // include the values for delays 66 and 100. If they ever are wielded, the 66 delay weapon will use the 65 delay bonuses, + // and the 100 delay weapon will use the 95 delay bonuses. So it's not a big deal. + // + // Still, if someone in the future decides that they do want to include them, here are the tables for these two delays: + // + // {12, 12, 13, 14, 14, 14, 15, 16, 16, 17, 17, 17, 19, 19, 19, 20, 20, 21, 22, 22, 22, 23, 24, 26, 29, 30, 32, 37, 39, 42, 45, 48, 53, 55, 57, 59, 61, 64} /* Delay = 66 */ + // {24, 24, 25, 26, 26, 26, 27, 28, 28, 29, 29, 29, 31, 31, 31, 32, 32, 33, 34, 34, 34, 35, 36, 39, 43, 45, 48, 55, 57, 62, 66, 71, 77, 80, 83, 85, 89, 92} /* Delay = 100 */ + // + // In case there are 2H weapons added in the future with delays other than those listed above (and until the damage bonuses + // associated with that new delay are added to this function), this function is designed to do the following: + // + // For weapons with delays in the range 60-64, use the Damage Bonus that would apply to a 2H weapon with delay 60. + // For weapons with delays in the range 65-69, use the Damage Bonus that would apply to a 2H weapon with delay 65 + // For weapons with delays in the range 70-84, use the Damage Bonus that would apply to a 2H weapon with delay 70. + // For weapons with delays in the range 85-94, use the Damage Bonus that would apply to a 2H weapon with delay 85. + // For weapons with delays in the range 95-149, use the Damage Bonus that would apply to a 2H weapon with delay 95. + // For weapons with delays 150 or higher, use the Damage Bonus that would apply to a 2H weapon with delay 150. + + static const uint8 ucDelayOver59Levels28to65[6][38] = + { + /* Level: */ + /* 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64. 65 */ + + {10, 10, 11, 12, 12, 12, 13, 14, 14, 15, 15, 15, 17, 17, 17, 18, 18, 19, 20, 20, 20, 21, 22, 24, 27, 28, 30, 35, 36, 39, 42, 45, 49, 51, 53, 54, 57, 59}, /* Delay = 60 */ + {12, 12, 13, 14, 14, 14, 15, 16, 16, 17, 17, 17, 19, 19, 19, 20, 20, 21, 22, 22, 22, 23, 24, 26, 29, 30, 32, 37, 39, 42, 45, 48, 52, 55, 57, 58, 61, 63}, /* Delay = 65 */ + {14, 14, 15, 16, 16, 16, 17, 18, 18, 19, 19, 19, 21, 21, 21, 22, 22, 23, 24, 24, 24, 25, 26, 28, 31, 33, 35, 40, 42, 45, 48, 52, 56, 59, 61, 62, 65, 68}, /* Delay = 70 */ + {19, 19, 20, 21, 21, 21, 22, 23, 23, 24, 24, 24, 26, 26, 26, 27, 27, 28, 29, 29, 29, 30, 31, 34, 37, 39, 41, 47, 49, 54, 57, 61, 66, 69, 72, 74, 77, 80}, /* Delay = 85 */ + {22, 22, 23, 24, 24, 24, 25, 26, 26, 27, 27, 27, 29, 29, 29, 30, 30, 31, 32, 32, 32, 33, 34, 37, 40, 43, 45, 52, 54, 59, 62, 67, 73, 76, 79, 81, 84, 88}, /* Delay = 95 */ + {40, 40, 41, 42, 42, 42, 43, 44, 44, 45, 45, 45, 47, 47, 47, 48, 48, 49, 50, 50, 50, 51, 52, 56, 61, 65, 69, 78, 82, 89, 94, 102, 110, 115, 119, 122, 127, 132} /* Delay = 150 */ + }; + + if( Weapon->Delay < 65 ) + { + return ucDelayOver59Levels28to65[0][ucPlayerLevel-28]; + } + else if( Weapon->Delay < 70 ) + { + return ucDelayOver59Levels28to65[1][ucPlayerLevel-28]; + } + else if( Weapon->Delay < 85 ) + { + return ucDelayOver59Levels28to65[2][ucPlayerLevel-28]; + } + else if( Weapon->Delay < 95 ) + { + return ucDelayOver59Levels28to65[3][ucPlayerLevel-28]; + } + else if( Weapon->Delay < 150 ) + { + return ucDelayOver59Levels28to65[4][ucPlayerLevel-28]; + } + else + { + return ucDelayOver59Levels28to65[5][ucPlayerLevel-28]; + } + } +} + +int Mob::GetMonkHandToHandDamage(void) +{ + // Kaiyodo - Determine a monk's fist damage. Table data from www.monkly-business.com + // saved as static array - this should speed this function up considerably + static int damage[66] = { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + 99, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 9, 9, 9, 9, 9,10,10,10,10,10,11,11,11,11,11, + 12,12,12,12,12,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14, + 14,14,15,15,15,15 }; + + // Have a look to see if we have epic fists on + + if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652) + return(9); + else + { + int Level = GetLevel(); + if (Level > 65) + return(19); + else + return damage[Level]; + } +} + +int Mob::GetMonkHandToHandDelay(void) +{ + // Kaiyodo - Determine a monk's fist delay. Table data from www.monkly-business.com + // saved as static array - this should speed this function up considerably + static int delayshuman[66] = { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + 99,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, + 36,36,36,36,36,35,35,35,35,35,34,34,34,34,34,33,33,33,33,33, + 32,32,32,32,32,31,31,31,31,31,30,30,30,29,29,29,28,28,28,27, + 26,24,22,20,20,20 }; + static int delaysiksar[66] = { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + 99,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, + 36,36,36,36,36,36,36,36,36,36,35,35,35,35,35,34,34,34,34,34, + 33,33,33,33,33,32,32,32,32,32,31,31,31,30,30,30,29,29,29,28, + 27,24,22,20,20,20 }; + + // Have a look to see if we have epic fists on + if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652) + return(16); + else + { + int Level = GetLevel(); + if (GetRace() == HUMAN) + { + if (Level > 65) + return(24); + else + return delayshuman[Level]; + } + else //heko: iksar table + { + if (Level > 65) + return(25); + else + return delaysiksar[Level]; + } + } +} + + +int32 Mob::ReduceDamage(int32 damage) +{ + if(damage <= 0) + return damage; + + int32 slot = -1; + bool DisableMeleeRune = false; + + if (spellbonuses.NegateAttacks[0]){ + slot = spellbonuses.NegateAttacks[1]; + if(slot >= 0) { + if(--buffs[slot].numhits == 0) { + + if(!TryFadeEffect(slot)) + BuffFadeBySlot(slot , true); + } + return -6; + } + } + + //Only mitigate if damage is above the minimium specified. + if (spellbonuses.MeleeThresholdGuard[0]){ + slot = spellbonuses.MeleeThresholdGuard[1]; + + if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) + { + DisableMeleeRune = true; + int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[0] / 100; + if(damage_to_reduce > buffs[slot].melee_rune) + { + mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d" + " damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune); + damage -= damage_to_reduce; + if(!TryFadeEffect(slot)) + BuffFadeBySlot(slot); + } + else + { + mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d" + " damage remaining.", damage_to_reduce, buffs[slot].melee_rune); + buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); + damage -= damage_to_reduce; + } + } + } + + + if (spellbonuses.MitigateMeleeRune[0] && !DisableMeleeRune){ + slot = spellbonuses.MitigateMeleeRune[1]; + if(slot >= 0) + { + int damage_to_reduce = damage * spellbonuses.MitigateMeleeRune[0] / 100; + if(damage_to_reduce > buffs[slot].melee_rune) + { + mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" + " damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune); + damage -= damage_to_reduce; + if(!TryFadeEffect(slot)) + BuffFadeBySlot(slot); + } + else + { + mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" + " damage remaining.", damage_to_reduce, buffs[slot].melee_rune); + buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); + damage -= damage_to_reduce; + } + } + } + + if (spellbonuses.TriggerMeleeThreshold[2]){ + slot = spellbonuses.TriggerMeleeThreshold[1]; + + if (slot >= 0) { + if(damage > buffs[slot].melee_rune) { + if(!TryFadeEffect(slot)) + BuffFadeBySlot(slot); + } + else{ + buffs[slot].melee_rune = (buffs[slot].melee_rune - damage); + } + } + } + + if(damage < 1) + return -6; + + if (spellbonuses.MeleeRune[0] && spellbonuses.MeleeRune[1] >= 0) + damage = RuneAbsorb(damage, SE_Rune); + + if(damage < 1) + return -6; + + return(damage); +} + +int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker) +{ + if(damage <= 0) + return damage; + + bool DisableSpellRune = false; + int32 slot = -1; + + // See if we block the spell outright first + if (spellbonuses.NegateAttacks[0]){ + slot = spellbonuses.NegateAttacks[1]; + if(slot >= 0) { + if(--buffs[slot].numhits == 0) { + + if(!TryFadeEffect(slot)) + BuffFadeBySlot(slot , true); + } + return 0; + } + } + + // If this is a DoT, use DoT Shielding... + if(iBuffTic) { + damage -= (damage * itembonuses.DoTShielding / 100); + + if (spellbonuses.MitigateDotRune[0]){ + slot = spellbonuses.MitigateDotRune[1]; + if(slot >= 0) + { + int damage_to_reduce = damage * spellbonuses.MitigateDotRune[0] / 100; + if(damage_to_reduce > buffs[slot].dot_rune) + { + damage -= damage_to_reduce; + if(!TryFadeEffect(slot)) + BuffFadeBySlot(slot); + } + else + { + buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce); + damage -= damage_to_reduce; + } + } + } + } + + // This must be a DD then so lets apply Spell Shielding and runes. + else + { + // Reduce damage by the Spell Shielding first so that the runes don't take the raw damage. + damage -= (damage * itembonuses.SpellShield / 100); + + + //Only mitigate if damage is above the minimium specified. + if (spellbonuses.SpellThresholdGuard[0]){ + slot = spellbonuses.SpellThresholdGuard[1]; + + if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) + { + DisableSpellRune = true; + int damage_to_reduce = damage * spellbonuses.SpellThresholdGuard[0] / 100; + if(damage_to_reduce > buffs[slot].magic_rune) + { + damage -= damage_to_reduce; + if(!TryFadeEffect(slot)) + BuffFadeBySlot(slot); + } + else + { + buffs[slot].melee_rune = (buffs[slot].magic_rune - damage_to_reduce); + damage -= damage_to_reduce; + } + } + } + + + // Do runes now. + if (spellbonuses.MitigateSpellRune[0] && !DisableSpellRune){ + slot = spellbonuses.MitigateSpellRune[1]; + if(slot >= 0) + { + int damage_to_reduce = damage * spellbonuses.MitigateSpellRune[0] / 100; + if(damage_to_reduce > buffs[slot].magic_rune) + { + mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d" + " damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune); + damage -= damage_to_reduce; + if(!TryFadeEffect(slot)) + BuffFadeBySlot(slot); + } + else + { + mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" + " damage remaining.", damage_to_reduce, buffs[slot].magic_rune); + buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce); + damage -= damage_to_reduce; + } + } + } + + if (spellbonuses.TriggerSpellThreshold[2]){ + slot = spellbonuses.TriggerSpellThreshold[1]; + + if (slot >= 0) { + if(damage > buffs[slot].magic_rune) { + if(!TryFadeEffect(slot)) + BuffFadeBySlot(slot); + } + else{ + buffs[slot].magic_rune = (buffs[slot].magic_rune - damage); + } + } + } + + if(damage < 1) + return 0; + + + if (spellbonuses.AbsorbMagicAtt[0] && spellbonuses.AbsorbMagicAtt[1] >= 0) + damage = RuneAbsorb(damage, SE_AbsorbMagicAtt); + + if(damage < 1) + return 0; + } + return damage; +} + +int32 Mob::ReduceAllDamage(int32 damage) +{ + if(damage <= 0) + return damage; + + if(spellbonuses.ManaAbsorbPercentDamage[0] && (GetMana() > damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100)) { + damage -= (damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100); + SetMana(GetMana() - damage); + TryTriggerOnValueAmount(false, true); + } + + CheckNumHitsRemaining(8); + + return(damage); +} + +bool Mob::HasProcs() const +{ + for (int i = 0; i < MAX_PROCS; i++) + if (PermaProcs[i].spellID != SPELL_UNKNOWN || SpellProcs[i].spellID != SPELL_UNKNOWN) + return true; + return false; +} + +bool Mob::HasDefensiveProcs() const +{ + for (int i = 0; i < MAX_PROCS; i++) + if (DefensiveProcs[i].spellID != SPELL_UNKNOWN) + return true; + return false; +} + +bool Mob::HasSkillProcs() const +{ + for (int i = 0; i < MAX_PROCS; i++) + if (SkillProcs[i].spellID != SPELL_UNKNOWN) + return true; + return false; +} + +bool Mob::HasRangedProcs() const +{ + for (int i = 0; i < MAX_PROCS; i++) + if (RangedProcs[i].spellID != SPELL_UNKNOWN) + return true; + return false; +} + +bool Client::CheckDoubleAttack(bool tripleAttack) { + + //Check for bonuses that give you a double attack chance regardless of skill (ie Bestial Frenzy/Harmonious Attack AA) + uint16 bonusGiveDA = aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack; + + if(!HasSkill(SkillDoubleAttack) && !bonusGiveDA) + return false; + + float chance = 0.0f; + + uint16 skill = GetSkill(SkillDoubleAttack); + + int16 bonusDA = aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance; + + //Use skill calculations otherwise, if you only have AA applied GiveDoubleAttack chance then use that value as the base. + if (skill) + chance = (float(skill+GetLevel()) * (float(100.0f+bonusDA+bonusGiveDA) /100.0f)) /500.0f; + else + chance = (float(bonusGiveDA) * (float(100.0f+bonusDA)/100.0f) ) /100.0f; + + //Live now uses a static Triple Attack skill (lv 46 = 2% lv 60 = 20%) - We do not have this skill on EMU ATM. + //A reasonable forumla would then be TA = 20% * chance + //AA's can also give triple attack skill over cap. (ie Burst of Power) NOTE: Skill ID in spell data is 76 (Triple Attack) + //Kayen: Need to decide if we can implement triple attack skill before working in over the cap effect. + if(tripleAttack) { + // Only some Double Attack classes get Triple Attack [This is already checked in client_processes.cpp] + int16 triple_bonus = spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance; + chance *= 0.2f; //Baseline chance is 20% of your double attack chance. + chance *= float(100.0f+triple_bonus)/100.0f; //Apply modifiers. + } + + if((MakeRandomFloat(0, 1) < chance)) + return true; + + return false; +} + +bool Client::CheckDoubleRangedAttack() { + + int16 chance = spellbonuses.DoubleRangedAttack + itembonuses.DoubleRangedAttack + aabonuses.DoubleRangedAttack; + + if(chance && (MakeRandomInt(0, 100) < chance)) + return true; + + return false; +} + +void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, const SkillUseTypes skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic) { + // This method is called with skill_used=ABJURE for Damage Shield damage. + bool FromDamageShield = (skill_used == SkillAbjuration); + + mlog(COMBAT__HITS, "Applying damage %d done by %s with skill %d and spell %d, avoidable? %s, is %sa buff tic in slot %d", + damage, attacker?attacker->GetName():"NOBODY", skill_used, spell_id, avoidable?"yes":"no", iBuffTic?"":"not ", buffslot); + + if (GetInvul() || DivineAura()) { + mlog(COMBAT__DAMAGE, "Avoiding %d damage due to invulnerability.", damage); + damage = -5; + } + + if( spell_id != SPELL_UNKNOWN || attacker == nullptr ) + avoidable = false; + + // only apply DS if physical damage (no spell damage) + // damage shield calls this function with spell_id set, so its unavoidable + if (attacker && damage > 0 && spell_id == SPELL_UNKNOWN && skill_used != SkillArchery && skill_used != SkillThrowing) { + DamageShield(attacker); + } + + if (spell_id == SPELL_UNKNOWN && skill_used) { + CheckNumHitsRemaining(1); //Incoming Hit Attempts + + if (attacker) + attacker->CheckNumHitsRemaining(2); //Outgoing Hit Attempts + } + + if(attacker){ + if(attacker->IsClient()){ + if(!RuleB(Combat, EXPFromDmgShield)) { + // Damage shield damage shouldn't count towards who gets EXP + if(!attacker->CastToClient()->GetFeigned() && !FromDamageShield) + AddToHateList(attacker, 0, damage, true, false, iBuffTic); + } + else { + if(!attacker->CastToClient()->GetFeigned()) + AddToHateList(attacker, 0, damage, true, false, iBuffTic); + } + } + else + AddToHateList(attacker, 0, damage, true, false, iBuffTic); + } + + if(damage > 0) { + //if there is some damage being done and theres an attacker involved + if(attacker) { + if(spell_id == SPELL_HARM_TOUCH2 && attacker->IsClient() && attacker->CastToClient()->CheckAAEffect(aaEffectLeechTouch)){ + int healed = damage; + healed = attacker->GetActSpellHealing(spell_id, healed); + attacker->HealDamage(healed); + entity_list.MessageClose(this, true, 300, MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName() ); + attacker->CastToClient()->DisableAAEffect(aaEffectLeechTouch); + } + + // if spell is lifetap add hp to the caster + if (spell_id != SPELL_UNKNOWN && IsLifetapSpell( spell_id )) { + int healed = damage; + + healed = attacker->GetActSpellHealing(spell_id, healed); + mlog(COMBAT__DAMAGE, "Applying lifetap heal of %d to %s", healed, attacker->GetName()); + attacker->HealDamage(healed); + + //we used to do a message to the client, but its gone now. + // emote goes with every one ... even npcs + entity_list.MessageClose(this, true, 300, MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName() ); + } + } //end `if there is some damage being done and theres anattacker person involved` + + Mob *pet = GetPet(); + if (pet && !pet->IsFamiliar() && !pet->GetSpecialAbility(IMMUNE_AGGRO) && !pet->IsEngaged() && attacker && attacker != this && !attacker->IsCorpse()) + { + if (!pet->IsHeld()) { + mlog(PETS__AGGRO, "Sending pet %s into battle due to attack.", pet->GetName()); + pet->AddToHateList(attacker, 1); + pet->SetTarget(attacker); + Message_StringID(10, PET_ATTACKING, pet->GetCleanName(), attacker->GetCleanName()); + } + } + + //see if any runes want to reduce this damage + if(spell_id == SPELL_UNKNOWN) { + damage = ReduceDamage(damage); + mlog(COMBAT__HITS, "Melee Damage reduced to %d", damage); + } else { + int32 origdmg = damage; + damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker); + if (origdmg != damage && attacker && attacker->IsClient()) { + if(attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide) + attacker->Message(15, "The Spellshield absorbed %d of %d points of damage", origdmg - damage, origdmg); + } + if (damage == 0 && attacker && origdmg != damage && IsClient()) { + //Kayen: Probably need to add a filter for this - Not sure if this msg is correct but there should be a message for spell negate/runes. + Message(263, "%s tries to cast on YOU, but YOUR magical skin absorbs the spell.",attacker->GetCleanName()); + } + + } + + if (skill_used) + CheckNumHitsRemaining(6); //Incomming Hit Success on Defender + + ReduceAllDamage(damage); + + if(IsClient() && CastToClient()->sneaking){ + CastToClient()->sneaking = false; + SendAppearancePacket(AT_Sneak, 0); + } + if(attacker && attacker->IsClient() && attacker->CastToClient()->sneaking){ + attacker->CastToClient()->sneaking = false; + attacker->SendAppearancePacket(AT_Sneak, 0); + } + + //final damage has been determined. + + SetHP(GetHP() - damage); + + if(HasDied()) { + bool IsSaved = false; + + if(TryDivineSave()) + IsSaved = true; + + if(!IsSaved && !TrySpellOnDeath()) { + SetHP(-500); + + if(Death(attacker, damage, spell_id, skill_used)) { + return; + } + } + } + else{ + if(GetHPRatio() < 16) + TryDeathSave(); + } + + TryTriggerOnValueAmount(true); + + //fade mez if we are mezzed + if (IsMezzed()) { + mlog(COMBAT__HITS, "Breaking mez due to attack."); + BuffFadeByEffect(SE_Mez); + } + + //check stun chances if bashing + if (damage > 0 && ((skill_used == SkillBash || skill_used == SkillKick) && attacker)) { + // NPCs can stun with their bash/kick as soon as they receive it. + // Clients can stun mobs under level 56 with their kick when they get level 55 or greater. + // Clients have a chance to stun if the mob is 56+ + + // Calculate the chance to stun + int stun_chance = 0; + if (!GetSpecialAbility(UNSTUNABLE)) { + if (attacker->IsNPC()) { + stun_chance = RuleI(Combat, NPCBashKickStunChance); + } else if (attacker->IsClient()) { + // Less than base immunity + // Client vs. Client always uses the chance + if (!IsClient() && GetLevel() <= RuleI(Spells, BaseImmunityLevel)) { + if (skill_used == SkillBash) // Bash always will + stun_chance = 100; + else if (attacker->GetLevel() >= RuleI(Combat, ClientStunLevel)) + stun_chance = 100; // only if you're over level 55 and using kick + } else { // higher than base immunity or Client vs. Client + // not sure on this number, use same as NPC for now + if (skill_used == SkillKick && attacker->GetLevel() < RuleI(Combat, ClientStunLevel)) + stun_chance = RuleI(Combat, NPCBashKickStunChance); + else if (skill_used == SkillBash) + stun_chance = RuleI(Combat, NPCBashKickStunChance) + + attacker->spellbonuses.StunBashChance + + attacker->itembonuses.StunBashChance + + attacker->aabonuses.StunBashChance; + } + } + } + + if (stun_chance && MakeRandomInt(0, 99) < stun_chance) { + // Passed stun, try to resist now + int stun_resist = itembonuses.StunResist + spellbonuses.StunResist; + int frontal_stun_resist = itembonuses.FrontalStunResist + spellbonuses.FrontalStunResist; + + mlog(COMBAT__HITS, "Stun passed, checking resists. Was %d chance.", stun_chance); + if (IsClient()) { + stun_resist += aabonuses.StunResist; + frontal_stun_resist += aabonuses.FrontalStunResist; + } + + // frontal stun check for ogres/bonuses + if (((GetBaseRace() == OGRE && IsClient()) || + (frontal_stun_resist && MakeRandomInt(0, 99) < frontal_stun_resist)) && + !attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) { + mlog(COMBAT__HITS, "Frontal stun resisted. %d chance.", frontal_stun_resist); + } else { + // Normal stun resist check. + if (stun_resist && MakeRandomInt(0, 99) < stun_resist) { + if (IsClient()) + Message_StringID(MT_Stun, SHAKE_OFF_STUN); + mlog(COMBAT__HITS, "Stun Resisted. %d chance.", stun_resist); + } else { + mlog(COMBAT__HITS, "Stunned. %d resist chance.", stun_resist); + Stun(MakeRandomInt(0, 2) * 1000); // 0-2 seconds + } + } + } else { + mlog(COMBAT__HITS, "Stun failed. %d chance.", stun_chance); + } + } + + if(spell_id != SPELL_UNKNOWN && !iBuffTic) { + //see if root will break + if (IsRooted() && !FromDamageShield) // neotoyko: only spells cancel root + TryRootFadeByDamage(buffslot, attacker); + } + else if(spell_id == SPELL_UNKNOWN) + { + //increment chances of interrupting + if(IsCasting()) { //shouldnt interrupt on regular spell damage + attacked_count++; + mlog(COMBAT__HITS, "Melee attack while casting. Attack count %d", attacked_count); + } + } + + //send an HP update if we are hurt + if(GetHP() < GetMaxHP()) + SendHPUpdate(); + } //end `if damage was done` + + //send damage packet... + if(!iBuffTic) { //buff ticks do not send damage, instead they just call SendHPUpdate(), which is done below + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); + CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer; + a->target = GetID(); + if (attacker == nullptr) + a->source = 0; + else if (attacker->IsClient() && attacker->CastToClient()->GMHideMe()) + a->source = 0; + else + a->source = attacker->GetID(); + a->type = SkillDamageTypes[skill_used]; // was 0x1c + a->damage = damage; + a->spellid = spell_id; + + //Note: if players can become pets, they will not receive damage messages of their own + //this was done to simplify the code here (since we can only effectively skip one mob on queue) + eqFilterType filter; + Mob *skip = attacker; + if(attacker && attacker->GetOwnerID()) { + //attacker is a pet, let pet owners see their pet's damage + Mob* owner = attacker->GetOwner(); + if (owner && owner->IsClient()) { + if (((spell_id != SPELL_UNKNOWN) || (FromDamageShield)) && damage>0) { + //special crap for spell damage, looks hackish to me + char val1[20]={0}; + owner->Message_StringID(MT_NonMelee,OTHER_HIT_NONMELEE,GetCleanName(),ConvertArray(damage,val1)); + } else { + if(damage > 0) { + if(spell_id != SPELL_UNKNOWN) + filter = iBuffTic ? FilterDOT : FilterSpellDamage; + else + filter = FilterPetHits; + } else if(damage == -5) + filter = FilterNone; //cant filter invulnerable + else + filter = FilterPetMisses; + + if(!FromDamageShield) + owner->CastToClient()->QueuePacket(outapp,true,CLIENT_CONNECTED,filter); + } + } + skip = owner; + } else { + //attacker is not a pet, send to the attacker + + //if the attacker is a client, try them with the correct filter + if(attacker && attacker->IsClient()) { + if (((spell_id != SPELL_UNKNOWN)||(FromDamageShield)) && damage>0) { + //special crap for spell damage, looks hackish to me + char val1[20]={0}; + if (FromDamageShield) + { + if(!attacker->CastToClient()->GetFilter(FilterDamageShields) == FilterHide) + { + attacker->Message_StringID(MT_DS,OTHER_HIT_NONMELEE,GetCleanName(),ConvertArray(damage,val1)); + } + } + else + entity_list.MessageClose_StringID(this, true, 100, MT_NonMelee,HIT_NON_MELEE,attacker->GetCleanName(),GetCleanName(),ConvertArray(damage,val1)); + } else { + if(damage > 0) { + if(spell_id != SPELL_UNKNOWN) + filter = iBuffTic ? FilterDOT : FilterSpellDamage; + else + filter = FilterNone; //cant filter our own hits + } else if(damage == -5) + filter = FilterNone; //cant filter invulnerable + else + filter = FilterMyMisses; + + attacker->CastToClient()->QueuePacket(outapp, true, CLIENT_CONNECTED, filter); + } + } + skip = attacker; + } + + //send damage to all clients around except the specified skip mob (attacker or the attacker's owner) and ourself + if(damage > 0) { + if(spell_id != SPELL_UNKNOWN) + filter = iBuffTic ? FilterDOT : FilterSpellDamage; + else + filter = FilterOthersHit; + } else if(damage == -5) + filter = FilterNone; //cant filter invulnerable + else + filter = FilterOthersMiss; + //make attacker (the attacker) send the packet so we can skip them and the owner + //this call will send the packet to `this` as well (using the wrong filter) (will not happen until PC charm works) + // If this is Damage Shield damage, the correct OP_Damage packets will be sent from Mob::DamageShield, so + // we don't send them here. + if(!FromDamageShield) { + entity_list.QueueCloseClients(this, outapp, true, 200, skip, true, filter); + //send the damage to ourself if we are a client + if(IsClient()) { + //I dont think any filters apply to damage affecting us + CastToClient()->QueuePacket(outapp); + } + } + + safe_delete(outapp); + } else { + //else, it is a buff tic... + // Everhood - So we can see our dot dmg like live shows it. + if(spell_id != SPELL_UNKNOWN && damage > 0 && attacker && attacker != this && attacker->IsClient()) { + //might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it + attacker->FilteredMessage_StringID(attacker, MT_DoTDamage, FilterDOT, + YOUR_HIT_DOT, GetCleanName(), itoa(damage), spells[spell_id].name); + // older clients don't have the below String ID, but it will be filtered + entity_list.FilteredMessageClose_StringID(attacker, true, 200, + MT_DoTDamage, FilterDOT, OTHER_HIT_DOT, GetCleanName(), + itoa(damage), attacker->GetCleanName(), spells[spell_id].name); + } + } //end packet sending + +} + + +void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id) +{ + int32 maxhp = GetMaxHP(); + int32 curhp = GetHP(); + uint32 acthealed = 0; + + if (caster && amount > 0) { + if (caster->IsNPC() && !caster->IsPet()) { + float npchealscale = caster->CastToNPC()->GetHealScale(); + amount = (static_cast(amount) * npchealscale) / 100.0f; + } + } + + if (amount > (maxhp - curhp)) + acthealed = (maxhp - curhp); + else + acthealed = amount; + + if (acthealed > 100) { + if (caster) { + if (IsBuffSpell(spell_id)) { // hots + // message to caster + if (caster->IsClient() && caster == this) { + if (caster->CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) + FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, + HOT_HEAL_SELF, itoa(acthealed), spells[spell_id].name); + else + FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, + YOU_HEALED, GetCleanName(), itoa(acthealed)); + } else if (caster->IsClient() && caster != this) { + if (caster->CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) + caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, + HOT_HEAL_OTHER, GetCleanName(), itoa(acthealed), + spells[spell_id].name); + else + caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, + YOU_HEAL, GetCleanName(), itoa(acthealed)); + } + // message to target + if (IsClient() && caster != this) { + if (CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) + FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime, + HOT_HEALED_OTHER, caster->GetCleanName(), + itoa(acthealed), spells[spell_id].name); + else + FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime, + YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); + } + } else { // normal heals + FilteredMessage_StringID(caster, MT_NonMelee, FilterSpellDamage, + YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); + if (caster != this) + caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterSpellDamage, + YOU_HEAL, GetCleanName(), itoa(acthealed)); + } + } else { + Message(MT_NonMelee, "You have been healed for %d points of damage.", acthealed); + } + } + + if (curhp < maxhp) { + if ((curhp + amount) > maxhp) + curhp = maxhp; + else + curhp += amount; + SetHP(curhp); + + SendHPUpdate(); + } +} + +//proc chance includes proc bonus +float Mob::GetProcChances(float ProcBonus, uint16 weapon_speed, uint16 hand) +{ + int mydex = GetDEX(); + float ProcChance = 0.0f; + + switch (hand) { + case 13: + weapon_speed = attack_timer.GetDuration(); + break; + case 14: + weapon_speed = attack_dw_timer.GetDuration(); + break; + case 11: + weapon_speed = ranged_timer.GetDuration(); + break; + } + + //calculate the weapon speed in ms, so we can use the rule to compare against. + // fast as a client can swing, so should be the floor of the proc chance + if (weapon_speed < RuleI(Combat, MinHastedDelay)) + weapon_speed = RuleI(Combat, MinHastedDelay); + + if (RuleB(Combat, AdjustProcPerMinute)) { + ProcChance = (static_cast(weapon_speed) * + RuleR(Combat, AvgProcsPerMinute) / 60000.0f); // compensate for weapon_speed being in ms + ProcBonus += static_cast(mydex) * RuleR(Combat, ProcPerMinDexContrib); + ProcChance += ProcChance * ProcBonus / 100.0f; + } else { + ProcChance = RuleR(Combat, BaseProcChance) + + static_cast(mydex) / RuleR(Combat, ProcDexDivideBy); + ProcChance += ProcChance * ProcBonus / 100.0f; + } + + mlog(COMBAT__PROCS, "Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus); + return ProcChance; +} + +float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed, uint16 hand) { + int myagi = GetAGI(); + ProcBonus = 0; + ProcChance = 0; + + switch(hand){ + case 13: + weapon_speed = attack_timer.GetDuration(); + break; + case 14: + weapon_speed = attack_dw_timer.GetDuration(); + break; + case 11: + return 0; + break; + } + + //calculate the weapon speed in ms, so we can use the rule to compare against. + //weapon_speed = ((int)(weapon_speed*(100.0f+attack_speed)*PermaHaste)); + if(weapon_speed < RuleI(Combat, MinHastedDelay)) // fast as a client can swing, so should be the floor of the proc chance + weapon_speed = RuleI(Combat, MinHastedDelay); + + ProcChance = ((float)weapon_speed * RuleR(Combat, AvgDefProcsPerMinute) / 60000.0f); // compensate for weapon_speed being in ms + ProcBonus += float(myagi) * RuleR(Combat, DefProcPerMinAgiContrib) / 100.0f; + ProcChance = ProcChance + (ProcChance * ProcBonus); + + mlog(COMBAT__PROCS, "Defensive Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus); + return ProcChance; +} + +void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand, int damage) { + + if (!on) { + SetTarget(nullptr); + LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryDefensiveProc for evaluation!"); + return; + } + + bool bSkillProc = HasSkillProcs(); + bool bDefensiveProc = HasDefensiveProcs(); + + if (!bDefensiveProc && !bSkillProc) + return; + + if (!bDefensiveProc && (bSkillProc && damage >= 0)) + return; + + float ProcChance, ProcBonus; + if(weapon!=nullptr) + on->GetDefensiveProcChances(ProcBonus, ProcChance, weapon->GetItem()->Delay, hand); + else + on->GetDefensiveProcChances(ProcBonus, ProcChance); + if(hand != 13) + ProcChance /= 2; + + if (bDefensiveProc){ + for (int i = 0; i < MAX_PROCS; i++) { + if (DefensiveProcs[i].spellID != SPELL_UNKNOWN) { + int chance = ProcChance * (DefensiveProcs[i].chance); + if ((MakeRandomInt(0, 100) < chance)) { + ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on); + CheckNumHitsRemaining(10,0,DefensiveProcs[i].base_spellID); + } + } + } + } + + if (bSkillProc && damage < 0){ + + if (damage == -1) + TrySkillProc(on, SkillBlock, ProcChance); + + if (damage == -2) + TrySkillProc(on, SkillParry, ProcChance); + + if (damage == -3) + TrySkillProc(on, SkillRiposte, ProcChance); + + if (damage == -4) + TrySkillProc(on, SkillDodge, ProcChance); + } +} + +void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { + if(!on) { + SetTarget(nullptr); + LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryWeaponProc for evaluation!"); + return; + } + + if (!IsAttackAllowed(on)) { + mlog(COMBAT__PROCS, "Preventing procing off of unattackable things."); + return; + } + + if(!weapon_g) { + TrySpellProc(nullptr, (const Item_Struct*)nullptr, on); + return; + } + + if(!weapon_g->IsType(ItemClassCommon)) { + TrySpellProc(nullptr, (const Item_Struct*)nullptr, on); + return; + } + + // Innate + aug procs from weapons + // TODO: powersource procs + TryWeaponProc(weapon_g, weapon_g->GetItem(), on, hand); + // Procs from Buffs and AA both melee and range + TrySpellProc(weapon_g, weapon_g->GetItem(), on, hand); + + return; +} + +void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand) +{ + if (!weapon) + return; + uint16 skillinuse = 28; + int ourlevel = GetLevel(); + float ProcBonus = static_cast(aabonuses.ProcChanceSPA + + spellbonuses.ProcChanceSPA + itembonuses.ProcChanceSPA); + ProcBonus += static_cast(itembonuses.ProcChance) / 10.0f; // Combat Effects + float ProcChance = GetProcChances(ProcBonus, weapon->Delay, hand); + + if (hand != 13) //Is Archery intened to proc at 50% rate? + ProcChance /= 2; + + // Try innate proc on weapon + // We can proc once here, either weapon or one aug + bool proced = false; // silly bool to prevent augs from going if weapon does + skillinuse = GetSkillByItemType(weapon->ItemType); + if (weapon->Proc.Type == ET_CombatProc) { + float WPC = ProcChance * (100.0f + // Proc chance for this weapon + static_cast(weapon->ProcRate)) / 100.0f; + if (MakeRandomFloat(0, 1) <= WPC) { // 255 dex = 0.084 chance of proc. No idea what this number should be really. + if (weapon->Proc.Level > ourlevel) { + mlog(COMBAT__PROCS, + "Tried to proc (%s), but our level (%d) is lower than required (%d)", + weapon->Name, ourlevel, weapon->Proc.Level); + if (IsPet()) { + Mob *own = GetOwner(); + if (own) + own->Message_StringID(13, PROC_PETTOOLOW); + } else { + Message_StringID(13, PROC_TOOLOW); + } + } else { + mlog(COMBAT__PROCS, + "Attacking weapon (%s) successfully procing spell %d (%.2f percent chance)", + weapon->Name, weapon->Proc.Effect, WPC * 100); + ExecWeaponProc(inst, weapon->Proc.Effect, on); + proced = true; + } + } + } + + if (!proced && inst) { + for (int r = 0; r < MAX_AUGMENT_SLOTS; r++) { + const ItemInst *aug_i = inst->GetAugment(r); + if (!aug_i) // no aug, try next slot! + continue; + const Item_Struct *aug = aug_i->GetItem(); + if (!aug) + continue; + + if (aug->Proc.Type == ET_CombatProc) { + float APC = ProcChance * (100.0f + // Proc chance for this aug + static_cast(aug->ProcRate)) / 100.0f; + if (MakeRandomFloat(0, 1) <= APC) { + if (aug->Proc.Level > ourlevel) { + if (IsPet()) { + Mob *own = GetOwner(); + if (own) + own->Message_StringID(13, PROC_PETTOOLOW); + } else { + Message_StringID(13, PROC_TOOLOW); + } + } else { + ExecWeaponProc(aug_i, aug->Proc.Effect, on); + break; + } + } + } + } + } + // TODO: Powersource procs + if (HasSkillProcs()) + TrySkillProc(on, skillinuse, ProcChance); + + return; +} + +void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand) +{ + float ProcBonus = static_cast(spellbonuses.SpellProcChance + + itembonuses.SpellProcChance + aabonuses.SpellProcChance); + float ProcChance = 0.0f; + if (weapon) + ProcChance = GetProcChances(ProcBonus, weapon->Delay, hand); + else + ProcChance = GetProcChances(ProcBonus); + + if (hand != 13) //Is Archery intened to proc at 50% rate? + ProcChance /= 2; + + bool rangedattk = false; + if (weapon && hand == 11) { + if (weapon->ItemType == ItemTypeArrow || + weapon->ItemType == ItemTypeLargeThrowing || + weapon->ItemType == ItemTypeSmallThrowing || + weapon->ItemType == ItemTypeBow) + rangedattk = true; + } + + for (uint32 i = 0; i < MAX_PROCS; i++) { + if (IsPet() && hand != 13) //Pets can only proc spell procs from their primay hand (ie; beastlord pets) + continue; // If pets ever can proc from off hand, this will need to change + + // Not ranged + if (!rangedattk) { + // Perma procs (AAs) + if (PermaProcs[i].spellID != SPELL_UNKNOWN) { + if (MakeRandomInt(0, 99) < PermaProcs[i].chance) { // TODO: Do these get spell bonus? + mlog(COMBAT__PROCS, + "Permanent proc %d procing spell %d (%d percent chance)", + i, PermaProcs[i].spellID, PermaProcs[i].chance); + ExecWeaponProc(nullptr, PermaProcs[i].spellID, on); + } else { + mlog(COMBAT__PROCS, + "Permanent proc %d failed to proc %d (%d percent chance)", + i, PermaProcs[i].spellID, PermaProcs[i].chance); + } + } + + // Spell procs (buffs) + if (SpellProcs[i].spellID != SPELL_UNKNOWN) { + float chance = ProcChance * (SpellProcs[i].chance / 100.0f); + if (MakeRandomFloat(0, 1) <= chance) { + mlog(COMBAT__PROCS, + "Spell proc %d procing spell %d (%.2f percent chance)", + i, SpellProcs[i].spellID, chance); + ExecWeaponProc(nullptr, SpellProcs[i].spellID, on); + CheckNumHitsRemaining(11, 0, SpellProcs[i].base_spellID); + } else { + mlog(COMBAT__PROCS, + "Spell proc %d failed to proc %d (%.2f percent chance)", + i, SpellProcs[i].spellID, chance); + } + } + } else if (rangedattk) { // ranged only + // ranged spell procs (buffs) + if (RangedProcs[i].spellID != SPELL_UNKNOWN) { + float chance = ProcChance * (RangedProcs[i].chance / 100.0f); + if (MakeRandomFloat(0, 1) <= chance) { + mlog(COMBAT__PROCS, + "Ranged proc %d procing spell %d (%.2f percent chance)", + i, RangedProcs[i].spellID, chance); + ExecWeaponProc(nullptr, RangedProcs[i].spellID, on); + CheckNumHitsRemaining(11, 0, RangedProcs[i].base_spellID); + } else { + mlog(COMBAT__PROCS, + "Ranged proc %d failed to proc %d (%.2f percent chance)", + i, RangedProcs[i].spellID, chance); + } + } + } + } + + return; +} + +void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage) +{ + if(damage < 1) + return; + + //Allows pets to perform critical hits. + //Each rank adds an additional 1% chance for any melee hit (primary, secondary, kick, bash, etc) to critical, + //dealing up to 63% more damage. http://www.magecompendium.com/aa-short-library.html + + Mob *owner = nullptr; + float critChance = 0.0f; + critChance += RuleI(Combat, MeleeBaseCritChance); + uint16 critMod = 163; + + if (damage < 1) //We can't critical hit if we don't hit. + return; + + if (!IsPet()) + return; + + owner = GetOwner(); + + if (!owner) + return; + + int16 CritPetChance = owner->aabonuses.PetCriticalHit + owner->itembonuses.PetCriticalHit + owner->spellbonuses.PetCriticalHit; + int16 CritChanceBonus = GetCriticalChanceBonus(skill); + + if (CritPetChance || critChance) { + + //For pets use PetCriticalHit for base chance, pets do not innately critical with without it + //even if buffed with a CritChanceBonus effects. + critChance += CritPetChance; + critChance += critChance*CritChanceBonus/100.0f; + } + + if(critChance > 0){ + + critChance /= 100; + + if(MakeRandomFloat(0, 1) < critChance) + { + critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100 + damage = (damage * critMod) / 100; + entity_list.FilteredMessageClose_StringID(this, false, 200, + MT_CritMelee, FilterMeleeCrits, CRITICAL_HIT, + GetCleanName(), itoa(damage)); + } + } +} + +void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts) +{ + if(damage < 1) + return; + + // decided to branch this into it's own function since it's going to be duplicating a lot of the + // code in here, but could lead to some confusion otherwise + if (IsPet() && GetOwner()->IsClient()) { + TryPetCriticalHit(defender,skill,damage); + return; + } + +#ifdef BOTS + if (this->IsPet() && this->GetOwner()->IsBot()) { + this->TryPetCriticalHit(defender,skill,damage); + return; + } +#endif //BOTS + + + float critChance = 0.0f; + + //1: Try Slay Undead + if(defender && defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire){ + + int16 SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0]; + + if (SlayRateBonus) { + + critChance += (float(SlayRateBonus)/100.0f); + critChance /= 100.0f; + + if(MakeRandomFloat(0, 1) < critChance){ + int16 SlayDmgBonus = aabonuses.SlayUndead[1] + itembonuses.SlayUndead[1] + spellbonuses.SlayUndead[1]; + damage = (damage*SlayDmgBonus*2.25)/100; + entity_list.MessageClose(this, false, 200, MT_CritMelee, "%s cleanses %s target!(%d)", GetCleanName(), this->GetGender() == 0 ? "his" : this->GetGender() == 1 ? "her" : "its", damage); + return; + } + } + } + + //2: Try Melee Critical + + //Base critical rate for all classes is dervived from DEX stat, this rate is then augmented + //by item,spell and AA bonuses allowing you a chance to critical hit. If the following rules + //are defined you will have an innate chance to hit at Level 1 regardless of bonuses. + //Warning: Do not define these rules if you want live like critical hits. + critChance += RuleI(Combat, MeleeBaseCritChance); + + if (IsClient()) { + critChance += RuleI(Combat, ClientBaseCritChance); + + if ((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) { + if (IsBerserk()) + critChance += RuleI(Combat, BerserkBaseCritChance); + else + critChance += RuleI(Combat, WarBerBaseCritChance); + } + } + + int deadlyChance = 0; + int deadlyMod = 0; + if(skill == SkillArchery && GetClass() == RANGER && GetSkill(SkillArchery) >= 65) + critChance += 6; + + if (skill == SkillThrowing && GetClass() == ROGUE && GetSkill(SkillThrowing) >= 65) { + critChance += RuleI(Combat, RogueCritThrowingChance); + deadlyChance = RuleI(Combat, RogueDeadlyStrikeChance); + deadlyMod = RuleI(Combat, RogueDeadlyStrikeMod); + } + + int CritChanceBonus = GetCriticalChanceBonus(skill); + + if (CritChanceBonus || critChance) { + + //Get Base CritChance from Dex. (200 = ~1.6%, 255 = ~2.0%, 355 = ~2.20%) Fall off rate > 255 + //http://giline.versus.jp/shiden/su.htm , http://giline.versus.jp/shiden/damage_e.htm + if (GetDEX() <= 255) + critChance += (float(GetDEX()) / 125.0f); + else if (GetDEX() > 255) + critChance += (float(GetDEX()-255)/ 500.0f) + 2.0f; + critChance += critChance*(float)CritChanceBonus /100.0f; + } + + if(opts) { + critChance *= opts->crit_percent; + critChance += opts->crit_flat; + } + + if(critChance > 0) { + + critChance /= 100; + + if(MakeRandomFloat(0, 1) < critChance) + { + uint16 critMod = 200; + bool crip_success = false; + int16 CripplingBlowChance = GetCrippBlowChance(); + + //Crippling Blow Chance: The percent value of the effect is applied + //to the your Chance to Critical. (ie You have 10% chance to critical and you + //have a 200% Chance to Critical Blow effect, therefore you have a 20% Chance to Critical Blow. + if (CripplingBlowChance || IsBerserk()) { + if (!IsBerserk()) + critChance *= float(CripplingBlowChance)/100.0f; + + if (IsBerserk() || MakeRandomFloat(0, 1) < critChance) { + critMod = 400; + crip_success = true; + } + } + + critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100 + damage = damage * critMod / 100; + + bool deadlySuccess = false; + if (deadlyChance && MakeRandomFloat(0, 1) < static_cast(deadlyChance) / 100.0f) { + if (BehindMob(defender, GetX(), GetY())) { + damage *= deadlyMod; + deadlySuccess = true; + } + } + + if (crip_success) { + entity_list.FilteredMessageClose_StringID(this, false, 200, + MT_CritMelee, FilterMeleeCrits, CRIPPLING_BLOW, + GetCleanName(), itoa(damage)); + // Crippling blows also have a chance to stun + //Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a staggers message. + if (defender->GetLevel() <= 55 && !defender->GetSpecialAbility(IMMUNE_STUN)){ + defender->Emote("staggers."); + defender->Stun(0); + } + } else if (deadlySuccess) { + entity_list.FilteredMessageClose_StringID(this, false, 200, + MT_CritMelee, FilterMeleeCrits, DEADLY_STRIKE, + GetCleanName(), itoa(damage)); + } else { + entity_list.FilteredMessageClose_StringID(this, false, 200, + MT_CritMelee, FilterMeleeCrits, CRITICAL_HIT, + GetCleanName(), itoa(damage)); + } + } + } +} + + +bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) +{ + + if (!defender) + return false; + + if (aabonuses.FinishingBlow[1] && !defender->IsClient() && defender->GetHPRatio() < 10){ + + uint32 chance = aabonuses.FinishingBlow[0]/10; //500 = 5% chance. + uint32 damage = aabonuses.FinishingBlow[1]; + uint16 levelreq = aabonuses.FinishingBlowLvl[0]; + + if(defender->GetLevel() <= levelreq && (chance >= MakeRandomInt(0, 1000))){ + mlog(COMBAT__ATTACKS, "Landed a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); + entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); + defender->Damage(this, damage, SPELL_UNKNOWN, skillinuse); + return true; + } + else + { + mlog(COMBAT__ATTACKS, "FAILED a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); + return false; + } + } + return false; +} + +void Mob::DoRiposte(Mob* defender) { + mlog(COMBAT__ATTACKS, "Preforming a riposte"); + + if (!defender) + return; + + defender->Attack(this, SLOT_PRIMARY, true); + if (HasDied()) return; + + int16 DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[0] + + defender->spellbonuses.GiveDoubleRiposte[0] + + defender->itembonuses.GiveDoubleRiposte[0]; + + //Live AA - Double Riposte + if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) { + mlog(COMBAT__ATTACKS, "Preforming a double riposed (%d percent chance)", DoubleRipChance); + defender->Attack(this, SLOT_PRIMARY, true); + if (HasDied()) return; + } + + //Double Riposte effect, allows for a chance to do RIPOSTE with a skill specfic special attack (ie Return Kick). + //Coded narrowly: Limit to one per client. Limit AA only. [1 = Skill Attack Chance, 2 = Skill] + DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[1]; + + if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) { + mlog(COMBAT__ATTACKS, "Preforming a return SPECIAL ATTACK (%d percent chance)", DoubleRipChance); + + if (defender->GetClass() == MONK) + defender->MonkSpecialAttack(this, defender->aabonuses.GiveDoubleRiposte[2]); + else if (defender->IsClient()) + defender->CastToClient()->DoClassAttacks(this,defender->aabonuses.GiveDoubleRiposte[2], true); + } +} + +void Mob::ApplyMeleeDamageBonus(uint16 skill, int32 &damage){ + + if(!RuleB(Combat, UseIntervalAC)){ + if(IsNPC()){ //across the board NPC damage bonuses. + //only account for STR here, assume their base STR was factored into their DB damages + int dmgbonusmod = 0; + dmgbonusmod += (100*(itembonuses.STR + spellbonuses.STR))/3; + dmgbonusmod += (100*(spellbonuses.ATK + itembonuses.ATK))/5; + mlog(COMBAT__DAMAGE, "Damage bonus: %d percent from ATK and STR bonuses.", (dmgbonusmod/100)); + damage += (damage*dmgbonusmod/10000); + } + } + + damage += damage * GetMeleeDamageMod_SE(skill) / 100; +} + +bool Mob::HasDied() { + bool Result = false; + int16 hp_below = 0; + + hp_below = (GetDelayDeath() * -1); + + if((GetHP()) <= (hp_below)) + Result = true; + + return Result; +} + +uint16 Mob::GetDamageTable(SkillUseTypes skillinuse) +{ + if(GetLevel() <= 51) + { + uint16 ret_table = 0; + int str_over_75 = 0; + if(GetSTR() > 75) + str_over_75 = GetSTR() - 75; + if(str_over_75 > 255) + ret_table = (GetSkill(skillinuse)+255)/2; + else + ret_table = (GetSkill(skillinuse)+str_over_75)/2; + + if(ret_table < 100) + return 100; + + return ret_table; + } + else if(GetLevel() >= 90) + { + if(GetClass() == MONK) + return 379; + else + return 345; + } + else + { + uint16 dmg_table[] = { + 275, 275, 275, 275, 275, + 280, 280, 280, 280, 285, + 285, 285, 290, 290, 295, + 295, 300, 300, 300, 305, + 305, 305, 310, 310, 315, + 315, 320, 320, 320, 325, + 325, 325, 330, 330, 335, + 335, 340, 340, 340, + }; + if(GetClass() == MONK) + return (dmg_table[GetLevel()-51]*(100+RuleI(Combat,MonkDamageTableBonus))/100); + else + return dmg_table[GetLevel()-51]; + } +} + +void Mob::TrySkillProc(Mob *on, uint16 skill, float chance) +{ + + if (!on) { + SetTarget(nullptr); + LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TrySkillProc for evaluation!"); + return; + } + + for (int i = 0; i < MAX_PROCS; i++) { + if (SkillProcs[i].spellID != SPELL_UNKNOWN){ + if (PassLimitToSkill(SkillProcs[i].base_spellID,skill)){ + int ProcChance = chance * (float)SkillProcs[i].chance; + if ((MakeRandomInt(0, 100) < ProcChance)) { + ExecWeaponProc(nullptr, SkillProcs[i].spellID, on); + CheckNumHitsRemaining(11,0, SkillProcs[i].base_spellID); + } + } + } + } +} + +bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) +{ + /*Dev Quote 2010: http://forums.station.sony.com/eq/posts/list.m?topic_id=161443 + The Viscid Roots AA does the following: Reduces the chance for root to break by X percent. + There is no distinction of any kind between the caster inflicted damage, or anyone + else's damage. There is also no distinction between Direct and DOT damage in the root code. + There is however, a provision that if the damage inflicted is greater than 500 per hit, the + chance to break root is increased. My guess is when this code was put in place, the devs at + the time couldn't imagine DOT damage getting that high. + */ + + /* General Mechanics + - Check buffslot to make sure damage from a root does not cancel the root + - If multiple roots on target, always and only checks first root slot and if broken only removes that slots root. + - Only roots on determental spells can be broken by damage. + - Root break chance values obtained from live parses. + */ + + if (!attacker || !spellbonuses.Root[0] || spellbonuses.Root[1] < 0) + return false; + + if (IsDetrimentalSpell(spellbonuses.Root[1]) && spellbonuses.Root[1] != buffslot){ + + int BreakChance = RuleI(Spells, RootBreakFromSpells); + BreakChance -= BreakChance*buffs[spellbonuses.Root[1]].RootBreakChance/100; + int level_diff = attacker->GetLevel() - GetLevel(); + + attacker->Shout("%i ATTACKER LV %i",attacker->GetLevel(), level_diff); + Shout("%i DEF LEVEL %i", GetLevel(), level_diff); + //Use baseline if level difference <= 1 (ie. If target is (1) level less than you, or equal or greater level) + + if (level_diff == 2) + BreakChance = (BreakChance * 80) /100; //Decrease by 20%; + + else if (level_diff >= 3 && level_diff <= 20) + BreakChance = (BreakChance * 60) /100; //Decrease by 40%; + + else if (level_diff > 21) + BreakChance = (BreakChance * 20) /100; //Decrease by 80%; + + Shout("Root Break Chance %i Lv diff %i base %i ", BreakChance, level_diff, RuleI(Spells, RootBreakFromSpells)); + + if (BreakChance < 1) + BreakChance = 1; + + if (MakeRandomInt(0, 99) < BreakChance) { + + if (!TryFadeEffect(spellbonuses.Root[1])) { + BuffFadeBySlot(spellbonuses.Root[1]); + mlog(COMBAT__HITS, "Spell broke root! BreakChance percent chance"); + return true; + } + } + } + + mlog(COMBAT__HITS, "Spell did not break root. BreakChance percent chance"); + return false; +} + +int32 Mob::RuneAbsorb(int32 damage, uint16 type) +{ + uint32 buff_max = GetMaxTotalSlots(); + if (type == SE_Rune){ + for(uint32 slot = 0; slot < buff_max; slot++) { + if(slot == spellbonuses.MeleeRune[1] && spellbonuses.MeleeRune[0] && buffs[slot].melee_rune && IsValidSpell(buffs[slot].spellid)){ + uint32 melee_rune_left = buffs[slot].melee_rune; + + if(melee_rune_left > damage) + { + melee_rune_left -= damage; + buffs[slot].melee_rune = melee_rune_left; + return -6; + } + + else + { + if(melee_rune_left > 0) + damage -= melee_rune_left; + + if(!TryFadeEffect(slot)) + BuffFadeBySlot(slot); + } + } + } + } + + + else{ + for(uint32 slot = 0; slot < buff_max; slot++) { + if(slot == spellbonuses.AbsorbMagicAtt[1] && spellbonuses.AbsorbMagicAtt[0] && buffs[slot].magic_rune && IsValidSpell(buffs[slot].spellid)){ + uint32 magic_rune_left = buffs[slot].magic_rune; + if(magic_rune_left > damage) + { + magic_rune_left -= damage; + buffs[slot].magic_rune = magic_rune_left; + return 0; + } + + else + { + if(magic_rune_left > 0) + damage -= magic_rune_left; + + if(!TryFadeEffect(slot)) + BuffFadeBySlot(slot); + } + } + } + } + + return damage; +} + diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 413b8d6c6..f57e92247 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1543,14 +1543,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne { int i, effect_value, base2, max, effectid; bool AdditiveWornBonus = false; - Mob *caster = nullptr; if(!IsAISpellEffect && !IsValidSpell(spell_id)) return; - if(casterId > 0) - caster = entity_list.GetMob(casterId); - for (i = 0; i < EFFECT_COUNT; i++) { //Buffs/Item effects @@ -1577,7 +1573,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne AdditiveWornBonus = true; effectid = spells[spell_id].effectid[i]; - effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, instrument_mod, caster, ticsremaining); + effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, instrument_mod, nullptr, ticsremaining, casterId); base2 = spells[spell_id].base2[i]; max = spells[spell_id].max[i]; } diff --git a/zone/bonusesxx.cpp b/zone/bonusesxx.cpp new file mode 100644 index 000000000..8e23eb5fb --- /dev/null +++ b/zone/bonusesxx.cpp @@ -0,0 +1,4337 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "../common/debug.h" +#include "../common/spdat.h" +#include "masterentity.h" +#include "../common/packet_dump.h" +#include "../common/moremath.h" +#include "../common/Item.h" +#include "worldserver.h" +#include "../common/skills.h" +#include "../common/bodytypes.h" +#include "../common/classes.h" +#include "../common/rulesys.h" +#include "QuestParserCollection.h" +#include +#include +#include +#ifndef WIN32 +#include +#include "../common/unix.h" +#endif + +#include "StringIDs.h" + +void Mob::CalcBonuses() +{ + CalcSpellBonuses(&spellbonuses); + CalcMaxHP(); + CalcMaxMana(); + SetAttackTimer(); + + rooted = FindType(SE_Root); +} + +void NPC::CalcBonuses() +{ + Mob::CalcBonuses(); + memset(&aabonuses, 0, sizeof(StatBonuses)); + + if(RuleB(NPC, UseItemBonusesForNonPets)){ + memset(&itembonuses, 0, sizeof(StatBonuses)); + CalcItemBonuses(&itembonuses); + } + else{ + if(GetOwner()){ + memset(&itembonuses, 0, sizeof(StatBonuses)); + CalcItemBonuses(&itembonuses); + } + } + + // This has to happen last, so we actually take the item bonuses into account. + Mob::CalcBonuses(); +} + +void Client::CalcBonuses() +{ + memset(&itembonuses, 0, sizeof(StatBonuses)); + CalcItemBonuses(&itembonuses); + CalcEdibleBonuses(&itembonuses); + + CalcSpellBonuses(&spellbonuses); + + _log(AA__BONUSES, "Calculating AA Bonuses for %s.", this->GetCleanName()); + CalcAABonuses(&aabonuses); //we're not quite ready for this + _log(AA__BONUSES, "Finished calculating AA Bonuses for %s.", this->GetCleanName()); + + RecalcWeight(); + + CalcAC(); + CalcATK(); + CalcHaste(); + + CalcSTR(); + CalcSTA(); + CalcDEX(); + CalcAGI(); + CalcINT(); + CalcWIS(); + CalcCHA(); + + CalcMR(); + CalcFR(); + CalcDR(); + CalcPR(); + CalcCR(); + CalcCorrup(); + + CalcMaxHP(); + CalcMaxMana(); + CalcMaxEndurance(); + + rooted = FindType(SE_Root); + + XPRate = 100 + spellbonuses.XPRateMod; +} + +int Client::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat) +{ + if( (reclevel > 0) && (level < reclevel) ) + { + int32 statmod = (level * 10000 / reclevel) * basestat; + + if( statmod < 0 ) + { + statmod -= 5000; + return (statmod/10000); + } + else + { + statmod += 5000; + return (statmod/10000); + } + } + + return 0; +} + +void Client::CalcItemBonuses(StatBonuses* newbon) { + //memset assumed to be done by caller. + + // Clear item faction mods + ClearItemFactionBonuses(); + ShieldEquiped(false); + + unsigned int i; + //should not include 21 (SLOT_AMMO) + for (i=0; i<21; i++) { + const ItemInst* inst = m_inv[i]; + if(inst == 0) + continue; + AddItemBonuses(inst, newbon); + + //Check if item is secondary slot is a 'shield'. Required for multiple spelll effects. + if (i == 14 && (m_inv.GetItem(14)->GetItem()->ItemType == ItemTypeShield)) + ShieldEquiped(true); + } + + //Power Source Slot + if (GetClientVersion() >= EQClientSoF) + { + const ItemInst* inst = m_inv[9999]; + if(inst) + AddItemBonuses(inst, newbon); + } + + //tribute items + for (i = 0; i < MAX_PLAYER_TRIBUTES; i++) { + const ItemInst* inst = m_inv[TRIBUTE_SLOT_START + i]; + if(inst == 0) + continue; + AddItemBonuses(inst, newbon, false, true); + } + // Caps + if(newbon->HPRegen > CalcHPRegenCap()) + newbon->HPRegen = CalcHPRegenCap(); + + if(newbon->ManaRegen > CalcManaRegenCap()) + newbon->ManaRegen = CalcManaRegenCap(); + + if(newbon->EnduranceRegen > CalcEnduranceRegenCap()) + newbon->EnduranceRegen = CalcEnduranceRegenCap(); + + SetAttackTimer(); +} + +void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute) { + if(!inst || !inst->IsType(ItemClassCommon)) + { + return; + } + + if(inst->GetAugmentType()==0 && isAug == true) + { + return; + } + + const Item_Struct *item = inst->GetItem(); + + if(!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass())) + { + if(item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink) + return; + } + + if(GetLevel() < item->ReqLevel) + { + return; + } + + if(GetLevel() >= item->RecLevel) + { + newbon->AC += item->AC; + newbon->HP += item->HP; + newbon->Mana += item->Mana; + newbon->Endurance += item->Endur; + newbon->STR += (item->AStr + item->HeroicStr); + newbon->STA += (item->ASta + item->HeroicSta); + newbon->DEX += (item->ADex + item->HeroicDex); + newbon->AGI += (item->AAgi + item->HeroicAgi); + newbon->INT += (item->AInt + item->HeroicInt); + newbon->WIS += (item->AWis + item->HeroicWis); + newbon->CHA += (item->ACha + item->HeroicCha); + + newbon->MR += (item->MR + item->HeroicMR); + newbon->FR += (item->FR + item->HeroicFR); + newbon->CR += (item->CR + item->HeroicCR); + newbon->PR += (item->PR + item->HeroicPR); + newbon->DR += (item->DR + item->HeroicDR); + newbon->Corrup += (item->SVCorruption + item->HeroicSVCorrup); + + newbon->STRCapMod += item->HeroicStr; + newbon->STACapMod += item->HeroicSta; + newbon->DEXCapMod += item->HeroicDex; + newbon->AGICapMod += item->HeroicAgi; + newbon->INTCapMod += item->HeroicInt; + newbon->WISCapMod += item->HeroicWis; + newbon->CHACapMod += item->HeroicCha; + newbon->MRCapMod += item->HeroicMR; + newbon->CRCapMod += item->HeroicFR; + newbon->FRCapMod += item->HeroicCR; + newbon->PRCapMod += item->HeroicPR; + newbon->DRCapMod += item->HeroicDR; + newbon->CorrupCapMod += item->HeroicSVCorrup; + + newbon->HeroicSTR += item->HeroicStr; + newbon->HeroicSTA += item->HeroicSta; + newbon->HeroicDEX += item->HeroicDex; + newbon->HeroicAGI += item->HeroicAgi; + newbon->HeroicINT += item->HeroicInt; + newbon->HeroicWIS += item->HeroicWis; + newbon->HeroicCHA += item->HeroicCha; + newbon->HeroicMR += item->HeroicMR; + newbon->HeroicFR += item->HeroicFR; + newbon->HeroicCR += item->HeroicCR; + newbon->HeroicPR += item->HeroicPR; + newbon->HeroicDR += item->HeroicDR; + newbon->HeroicCorrup += item->HeroicSVCorrup; + + } + else + { + int lvl = GetLevel(); + int reclvl = item->RecLevel; + + newbon->AC += CalcRecommendedLevelBonus( lvl, reclvl, item->AC ); + newbon->HP += CalcRecommendedLevelBonus( lvl, reclvl, item->HP ); + newbon->Mana += CalcRecommendedLevelBonus( lvl, reclvl, item->Mana ); + newbon->Endurance += CalcRecommendedLevelBonus( lvl, reclvl, item->Endur ); + newbon->STR += CalcRecommendedLevelBonus( lvl, reclvl, (item->AStr + item->HeroicStr) ); + newbon->STA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ASta + item->HeroicSta) ); + newbon->DEX += CalcRecommendedLevelBonus( lvl, reclvl, (item->ADex + item->HeroicDex) ); + newbon->AGI += CalcRecommendedLevelBonus( lvl, reclvl, (item->AAgi + item->HeroicAgi) ); + newbon->INT += CalcRecommendedLevelBonus( lvl, reclvl, (item->AInt + item->HeroicInt) ); + newbon->WIS += CalcRecommendedLevelBonus( lvl, reclvl, (item->AWis + item->HeroicWis) ); + newbon->CHA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ACha + item->HeroicCha) ); + + newbon->MR += CalcRecommendedLevelBonus( lvl, reclvl, (item->MR + item->HeroicMR) ); + newbon->FR += CalcRecommendedLevelBonus( lvl, reclvl, (item->FR + item->HeroicFR) ); + newbon->CR += CalcRecommendedLevelBonus( lvl, reclvl, (item->CR + item->HeroicCR) ); + newbon->PR += CalcRecommendedLevelBonus( lvl, reclvl, (item->PR + item->HeroicPR) ); + newbon->DR += CalcRecommendedLevelBonus( lvl, reclvl, (item->DR + item->HeroicDR) ); + newbon->Corrup += CalcRecommendedLevelBonus( lvl, reclvl, (item->SVCorruption + item->HeroicSVCorrup) ); + + newbon->STRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr ); + newbon->STACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta ); + newbon->DEXCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex ); + newbon->AGICapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi ); + newbon->INTCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt ); + newbon->WISCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis ); + newbon->CHACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha ); + newbon->MRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR ); + newbon->CRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR ); + newbon->FRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR ); + newbon->PRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR ); + newbon->DRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR ); + newbon->CorrupCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup ); + + newbon->HeroicSTR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr ); + newbon->HeroicSTA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta ); + newbon->HeroicDEX += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex ); + newbon->HeroicAGI += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi ); + newbon->HeroicINT += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt ); + newbon->HeroicWIS += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis ); + newbon->HeroicCHA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha ); + newbon->HeroicMR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR ); + newbon->HeroicFR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR ); + newbon->HeroicCR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR ); + newbon->HeroicPR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR ); + newbon->HeroicDR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR ); + newbon->HeroicCorrup += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup ); + } + + //FatherNitwit: New style haste, shields, and regens + if(newbon->haste < (int16)item->Haste) { + newbon->haste = item->Haste; + } + if(item->Regen > 0) + newbon->HPRegen += item->Regen; + + if(item->ManaRegen > 0) + newbon->ManaRegen += item->ManaRegen; + + if(item->EnduranceRegen > 0) + newbon->EnduranceRegen += item->EnduranceRegen; + + if(item->Attack > 0) { + + int cap = RuleI(Character, ItemATKCap); + cap += itembonuses.ItemATKCap + spellbonuses.ItemATKCap + aabonuses.ItemATKCap; + + if((newbon->ATK + item->Attack) > cap) + newbon->ATK = RuleI(Character, ItemATKCap); + else + newbon->ATK += item->Attack; + } + if(item->DamageShield > 0) { + if((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap)) + newbon->DamageShield = RuleI(Character, ItemDamageShieldCap); + else + newbon->DamageShield += item->DamageShield; + } + if(item->SpellShield > 0) { + if((newbon->SpellShield + item->SpellShield) > RuleI(Character, ItemSpellShieldingCap)) + newbon->SpellShield = RuleI(Character, ItemSpellShieldingCap); + else + newbon->SpellShield += item->SpellShield; + } + if(item->Shielding > 0) { + if((newbon->MeleeMitigation + item->Shielding) > RuleI(Character, ItemShieldingCap)) + newbon->MeleeMitigation = RuleI(Character, ItemShieldingCap); + else + newbon->MeleeMitigation += item->Shielding; + } + if(item->StunResist > 0) { + if((newbon->StunResist + item->StunResist) > RuleI(Character, ItemStunResistCap)) + newbon->StunResist = RuleI(Character, ItemStunResistCap); + else + newbon->StunResist += item->StunResist; + } + if(item->StrikeThrough > 0) { + if((newbon->StrikeThrough + item->StrikeThrough) > RuleI(Character, ItemStrikethroughCap)) + newbon->StrikeThrough = RuleI(Character, ItemStrikethroughCap); + else + newbon->StrikeThrough += item->StrikeThrough; + } + if(item->Avoidance > 0) { + if((newbon->AvoidMeleeChance + item->Avoidance) > RuleI(Character, ItemAvoidanceCap)) + newbon->AvoidMeleeChance = RuleI(Character, ItemAvoidanceCap); + else + newbon->AvoidMeleeChance += item->Avoidance; + } + if(item->Accuracy > 0) { + if((newbon->HitChance + item->Accuracy) > RuleI(Character, ItemAccuracyCap)) + newbon->HitChance = RuleI(Character, ItemAccuracyCap); + else + newbon->HitChance += item->Accuracy; + } + if(item->CombatEffects > 0) { + if((newbon->ProcChance + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap)) + newbon->ProcChance = RuleI(Character, ItemCombatEffectsCap); + else + newbon->ProcChance += item->CombatEffects; + } + if(item->DotShielding > 0) { + if((newbon->DoTShielding + item->DotShielding) > RuleI(Character, ItemDoTShieldingCap)) + newbon->DoTShielding = RuleI(Character, ItemDoTShieldingCap); + else + newbon->DoTShielding += item->DotShielding; + } + + if(item->HealAmt > 0) { + if((newbon->HealAmt + item->HealAmt) > RuleI(Character, ItemHealAmtCap)) + newbon->HealAmt = RuleI(Character, ItemHealAmtCap); + else + newbon->HealAmt += item->HealAmt; + } + if(item->SpellDmg > 0) { + if((newbon->SpellDmg + item->SpellDmg) > RuleI(Character, ItemSpellDmgCap)) + newbon->SpellDmg = RuleI(Character, ItemSpellDmgCap); + else + newbon->SpellDmg += item->SpellDmg; + } + if(item->Clairvoyance > 0) { + if((newbon->Clairvoyance + item->Clairvoyance) > RuleI(Character, ItemClairvoyanceCap)) + newbon->Clairvoyance = RuleI(Character, ItemClairvoyanceCap); + else + newbon->Clairvoyance += item->Clairvoyance; + } + + if(item->DSMitigation > 0) { + if((newbon->DSMitigation + item->DSMitigation) > RuleI(Character, ItemDSMitigationCap)) + newbon->DSMitigation = RuleI(Character, ItemDSMitigationCap); + else + newbon->DSMitigation += item->DSMitigation; + } + if (item->Worn.Effect>0 && (item->Worn.Type == ET_WornEffect)) { // latent effects + ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, true); + } + + if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects + ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0, true); + } + + switch(item->BardType) + { + case 51: /* All (e.g. Singing Short Sword) */ + { + if(item->BardValue > newbon->singingMod) + newbon->singingMod = item->BardValue; + if(item->BardValue > newbon->brassMod) + newbon->brassMod = item->BardValue; + if(item->BardValue > newbon->stringedMod) + newbon->stringedMod = item->BardValue; + if(item->BardValue > newbon->percussionMod) + newbon->percussionMod = item->BardValue; + if(item->BardValue > newbon->windMod) + newbon->windMod = item->BardValue; + break; + } + case 50: /* Singing */ + { + if(item->BardValue > newbon->singingMod) + newbon->singingMod = item->BardValue; + break; + } + case 23: /* Wind */ + { + if(item->BardValue > newbon->windMod) + newbon->windMod = item->BardValue; + break; + } + case 24: /* stringed */ + { + if(item->BardValue > newbon->stringedMod) + newbon->stringedMod = item->BardValue; + break; + } + case 25: /* brass */ + { + if(item->BardValue > newbon->brassMod) + newbon->brassMod = item->BardValue; + break; + } + case 26: /* Percussion */ + { + if(item->BardValue > newbon->percussionMod) + newbon->percussionMod = item->BardValue; + break; + } + } + + if (item->SkillModValue != 0 && item->SkillModType <= HIGHEST_SKILL){ + if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) || + (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) + { + newbon->skillmod[item->SkillModType] = item->SkillModValue; + } + } + + // Add Item Faction Mods + if (item->FactionMod1) + { + if (item->FactionAmt1 > 0 && item->FactionAmt1 > GetItemFactionBonus(item->FactionMod1)) + { + AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); + } + else if (item->FactionAmt1 < 0 && item->FactionAmt1 < GetItemFactionBonus(item->FactionMod1)) + { + AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); + } + } + if (item->FactionMod2) + { + if (item->FactionAmt2 > 0 && item->FactionAmt2 > GetItemFactionBonus(item->FactionMod2)) + { + AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); + } + else if (item->FactionAmt2 < 0 && item->FactionAmt2 < GetItemFactionBonus(item->FactionMod2)) + { + AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); + } + } + if (item->FactionMod3) + { + if (item->FactionAmt3 > 0 && item->FactionAmt3 > GetItemFactionBonus(item->FactionMod3)) + { + AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); + } + else if (item->FactionAmt3 < 0 && item->FactionAmt3 < GetItemFactionBonus(item->FactionMod3)) + { + AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); + } + } + if (item->FactionMod4) + { + if (item->FactionAmt4 > 0 && item->FactionAmt4 > GetItemFactionBonus(item->FactionMod4)) + { + AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); + } + else if (item->FactionAmt4 < 0 && item->FactionAmt4 < GetItemFactionBonus(item->FactionMod4)) + { + AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); + } + } + + if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= HIGHEST_SKILL) { + if((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) + newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); + else + newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt; + } + + if (!isAug) + { + int i; + for(i = 0; i < MAX_AUGMENT_SLOTS; i++) { + AddItemBonuses(inst->GetAugment(i),newbon,true); + } + } + +} + +void Client::CalcEdibleBonuses(StatBonuses* newbon) { +#if EQDEBUG >= 11 + std::cout<<"Client::CalcEdibleBonuses(StatBonuses* newbon)"<GetItem() && inst->IsType(ItemClassCommon)) { + const Item_Struct *item=inst->GetItem(); + if (item->ItemType == ItemTypeFood && !food) + food = true; + else if (item->ItemType == ItemTypeDrink && !drink) + drink = true; + else + continue; + AddItemBonuses(inst, newbon); + } + } + for (i = 251; i <= 330; i++) + { + if (food && drink) + break; + const ItemInst* inst = GetInv().GetItem(i); + if (inst && inst->GetItem() && inst->IsType(ItemClassCommon)) { + const Item_Struct *item=inst->GetItem(); + if (item->ItemType == ItemTypeFood && !food) + food = true; + else if (item->ItemType == ItemTypeDrink && !drink) + drink = true; + else + continue; + AddItemBonuses(inst, newbon); + } + } +} + +void Client::CalcAABonuses(StatBonuses* newbon) { + memset(newbon, 0, sizeof(StatBonuses)); //start fresh + + int i; + uint32 slots = 0; + uint32 aa_AA = 0; + uint32 aa_value = 0; + if(this->aa) { + for (i = 0; i < MAX_PP_AA_ARRAY; i++) { //iterate through all of the client's AAs + if (this->aa[i]) { // make sure aa exists or we'll crash zone + aa_AA = this->aa[i]->AA; //same as aaid from the aa_effects table + aa_value = this->aa[i]->value; //how many points in it + if (aa_AA > 0 || aa_value > 0) { //do we have the AA? if 1 of the 2 is set, we can assume we do + //slots = database.GetTotalAALevels(aa_AA); //find out how many effects from aa_effects table + slots = zone->GetTotalAALevels(aa_AA); //find out how many effects from aa_effects, which is loaded into memory + if (slots > 0) //and does it have any effects? may be able to put this above, not sure if it runs on each iteration + ApplyAABonuses(aa_AA, slots, newbon); //add the bonuses + } + } + } + } +} + + +//A lot of the normal spell functions (IsBlankSpellEffect, etc) are set for just spells (in common/spdat.h). +//For now, we'll just put them directly into the code and comment with the corresponding normal function +//Maybe we'll fix it later? :-D +void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) +{ + if(slots == 0) //sanity check. why bother if no slots to fill? + return; + + //from AA_Ability struct + uint32 effect = 0; + int32 base1 = 0; + int32 base2 = 0; //only really used for SE_RaiseStatCap & SE_ReduceSkillTimer in aa_effects table + uint32 slot = 0; + + std::map >::const_iterator find_iter = aa_effects.find(aaid); + if(find_iter == aa_effects.end()) + { + return; + } + + for (std::map::const_iterator iter = aa_effects[aaid].begin(); iter != aa_effects[aaid].end(); ++iter) { + effect = iter->second.skill_id; + base1 = iter->second.base1; + base2 = iter->second.base2; + slot = iter->second.slot; + + //we default to 0 (SE_CurrentHP) for the effect, so if there aren't any base1/2 values, we'll just skip it + if (effect == 0 && base1 == 0 && base2 == 0) + continue; + + //IsBlankSpellEffect() + if (effect == SE_Blank || (effect == SE_CHA && base1 == 0) || effect == SE_StackingCommand_Block || effect == SE_StackingCommand_Overwrite) + continue; + + _log(AA__BONUSES, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName()); + + uint8 focus = IsFocusEffect(0, 0, true,effect); + if (focus) + { + newbon->FocusEffects[focus] = effect; + continue; + } + + switch (effect) + { + //Note: AA effects that use accuracy are skill limited, while spell effect is not. + case SE_Accuracy: + if ((base2 == -1) && (newbon->Accuracy[HIGHEST_SKILL+1] < base1)) + newbon->Accuracy[HIGHEST_SKILL+1] = base1; + else if (newbon->Accuracy[base2] < base1) + newbon->Accuracy[base2] += base1; + break; + case SE_CurrentHP: //regens + newbon->HPRegen += base1; + break; + case SE_CurrentEndurance: + newbon->EnduranceRegen += base1; + break; + case SE_MovementSpeed: + newbon->movementspeed += base1; //should we let these stack? + /*if (base1 > newbon->movementspeed) //or should we use a total value? + newbon->movementspeed = base1;*/ + break; + case SE_STR: + newbon->STR += base1; + break; + case SE_DEX: + newbon->DEX += base1; + break; + case SE_AGI: + newbon->AGI += base1; + break; + case SE_STA: + newbon->STA += base1; + break; + case SE_INT: + newbon->INT += base1; + break; + case SE_WIS: + newbon->WIS += base1; + break; + case SE_CHA: + newbon->CHA += base1; + break; + case SE_WaterBreathing: + //handled by client + break; + case SE_CurrentMana: + newbon->ManaRegen += base1; + break; + case SE_ItemManaRegenCapIncrease: + newbon->ItemManaRegenCap += base1; + break; + case SE_ResistFire: + newbon->FR += base1; + break; + case SE_ResistCold: + newbon->CR += base1; + break; + case SE_ResistPoison: + newbon->PR += base1; + break; + case SE_ResistDisease: + newbon->DR += base1; + break; + case SE_ResistMagic: + newbon->MR += base1; + break; + case SE_ResistCorruption: + newbon->Corrup += base1; + break; + case SE_IncreaseSpellHaste: + break; + case SE_IncreaseRange: + break; + case SE_MaxHPChange: + newbon->MaxHP += base1; + break; + case SE_Packrat: + newbon->Packrat += base1; + break; + case SE_TwoHandBash: + break; + case SE_SetBreathLevel: + break; + case SE_RaiseStatCap: + switch(base2) + { + //are these #define'd somewhere? + case 0: //str + newbon->STRCapMod += base1; + break; + case 1: //sta + newbon->STACapMod += base1; + break; + case 2: //agi + newbon->AGICapMod += base1; + break; + case 3: //dex + newbon->DEXCapMod += base1; + break; + case 4: //wis + newbon->WISCapMod += base1; + break; + case 5: //int + newbon->INTCapMod += base1; + break; + case 6: //cha + newbon->CHACapMod += base1; + break; + case 7: //mr + newbon->MRCapMod += base1; + break; + case 8: //cr + newbon->CRCapMod += base1; + break; + case 9: //fr + newbon->FRCapMod += base1; + break; + case 10: //pr + newbon->PRCapMod += base1; + break; + case 11: //dr + newbon->DRCapMod += base1; + break; + case 12: //corruption + newbon->CorrupCapMod += base1; + break; + } + break; + case SE_PetDiscipline2: + break; + case SE_SpellSlotIncrease: + break; + case SE_MysticalAttune: + newbon->BuffSlotIncrease += base1; + break; + case SE_TotalHP: + newbon->HP += base1; + break; + case SE_StunResist: + newbon->StunResist += base1; + break; + case SE_SpellCritChance: + newbon->CriticalSpellChance += base1; + break; + case SE_SpellCritDmgIncrease: + newbon->SpellCritDmgIncrease += base1; + break; + case SE_DotCritDmgIncrease: + newbon->DotCritDmgIncrease += base1; + break; + case SE_ResistSpellChance: + newbon->ResistSpellChance += base1; + break; + case SE_CriticalHealChance: + newbon->CriticalHealChance += base1; + break; + case SE_CriticalHealOverTime: + newbon->CriticalHealOverTime += base1; + break; + case SE_CriticalDoTChance: + newbon->CriticalDoTChance += base1; + break; + case SE_ReduceSkillTimer: + newbon->SkillReuseTime[base2] += base1; + break; + case SE_Fearless: + newbon->Fearless = true; + break; + case SE_PersistantCasting: + newbon->PersistantCasting += base1; + break; + case SE_DelayDeath: + newbon->DelayDeath += base1; + break; + case SE_FrontalStunResist: + newbon->FrontalStunResist += base1; + break; + case SE_ImprovedBindWound: + newbon->BindWound += base1; + break; + case SE_MaxBindWound: + newbon->MaxBindWound += base1; + break; + case SE_ExtraAttackChance: + newbon->ExtraAttackChance += base1; + break; + case SE_SeeInvis: + newbon->SeeInvis = base1; + break; + case SE_BaseMovementSpeed: + newbon->BaseMovementSpeed += base1; + break; + case SE_IncreaseRunSpeedCap: + newbon->IncreaseRunSpeedCap += base1; + break; + case SE_ConsumeProjectile: + newbon->ConsumeProjectile += base1; + break; + case SE_ForageAdditionalItems: + newbon->ForageAdditionalItems += base1; + break; + case SE_Salvage: + newbon->SalvageChance += base1; + break; + case SE_ArcheryDamageModifier: + newbon->ArcheryDamageModifier += base1; + break; + case SE_DoubleRangedAttack: + newbon->DoubleRangedAttack += base1; + break; + case SE_DamageShield: + newbon->DamageShield += base1; + break; + case SE_CharmBreakChance: + newbon->CharmBreakChance += base1; + break; + case SE_OffhandRiposteFail: + newbon->OffhandRiposteFail += base1; + break; + case SE_ItemAttackCapIncrease: + newbon->ItemATKCap += base1; + break; + case SE_GivePetGroupTarget: + newbon->GivePetGroupTarget = true; + break; + case SE_ItemHPRegenCapIncrease: + newbon->ItemHPRegenCap = +base1; + break; + case SE_Ambidexterity: + newbon->Ambidexterity += base1; + break; + case SE_PetMaxHP: + newbon->PetMaxHP += base1; + break; + case SE_AvoidMeleeChance: + newbon->AvoidMeleeChance += base1; + break; + case SE_CombatStability: + newbon->CombatStability += base1; + break; + case SE_AddSingingMod: + switch (base2) + { + case ItemTypeWindInstrument: + newbon->windMod += base1; + break; + case ItemTypeStringedInstrument: + newbon->stringedMod += base1; + break; + case ItemTypeBrassInstrument: + newbon->brassMod += base1; + break; + case ItemTypePercussionInstrument: + newbon->percussionMod += base1; + break; + case ItemTypeSinging: + newbon->singingMod += base1; + break; + } + break; + case SE_SongModCap: + newbon->songModCap += base1; + break; + case SE_PetCriticalHit: + newbon->PetCriticalHit += base1; + break; + case SE_PetAvoidance: + newbon->PetAvoidance += base1; + break; + case SE_ShieldBlock: + newbon->ShieldBlock += base1; + break; + case SE_ShieldEquipHateMod: + newbon->ShieldEquipHateMod += base1; + break; + case SE_ShieldEquipDmgMod: + newbon->ShieldEquipDmgMod[0] += base1; + newbon->ShieldEquipDmgMod[1] += base2; + break; + case SE_SecondaryDmgInc: + newbon->SecondaryDmgInc = true; + break; + case SE_ChangeAggro: + newbon->hatemod += base1; + break; + case SE_EndurancePool: + newbon->Endurance += base1; + break; + case SE_ChannelChanceItems: + newbon->ChannelChanceItems += base1; + break; + case SE_ChannelChanceSpells: + newbon->ChannelChanceSpells += base1; + break; + case SE_DoubleSpecialAttack: + newbon->DoubleSpecialAttack += base1; + break; + case SE_TripleBackstab: + newbon->TripleBackstab += base1; + break; + case SE_FrontalBackstabMinDmg: + newbon->FrontalBackstabMinDmg = true; + break; + case SE_FrontalBackstabChance: + newbon->FrontalBackstabChance += base1; + break; + case SE_BlockBehind: + newbon->BlockBehind += base1; + break; + + case SE_StrikeThrough: + case SE_StrikeThrough2: + newbon->StrikeThrough += base1; + break; + case SE_DoubleAttackChance: + newbon->DoubleAttackChance += base1; + break; + case SE_GiveDoubleAttack: + newbon->GiveDoubleAttack += base1; + break; + case SE_ProcChance: + newbon->ProcChanceSPA += base1; + break; + case SE_RiposteChance: + newbon->RiposteChance += base1; + break; + case SE_Flurry: + newbon->FlurryChance += base1; + break; + case SE_PetFlurry: + newbon->PetFlurry = base1; + break; + case SE_BardSongRange: + newbon->SongRange += base1; + break; + case SE_RootBreakChance: + newbon->RootBreakChance += base1; + break; + case SE_UnfailingDivinity: + newbon->UnfailingDivinity += base1; + break; + case SE_CrippBlowChance: + newbon->CrippBlowChance += base1; + break; + + case SE_ProcOnKillShot: + for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) + { + if(!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == base2) && (newbon->SpellOnKill[i+1] < base1))) + { + //base1 = chance, base2 = SpellID to be triggered, base3 = min npc level + newbon->SpellOnKill[i] = base2; + newbon->SpellOnKill[i+1] = base1; + + if (GetLevel() > 15) + newbon->SpellOnKill[i+2] = GetLevel() - 15; //AA specifiy "non-trivial" + else + newbon->SpellOnKill[i+2] = 0; + + break; + } + } + break; + + case SE_SpellOnDeath: + for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) + { + if(!newbon->SpellOnDeath[i]) + { + // base1 = SpellID to be triggered, base2 = chance to fire + newbon->SpellOnDeath[i] = base1; + newbon->SpellOnDeath[i+1] = base2; + break; + } + } + break; + + case SE_TriggerOnCast: + + for(int i = 0; i < MAX_SPELL_TRIGGER; i++) + { + if (newbon->SpellTriggers[i] == aaid) + break; + + if(!newbon->SpellTriggers[i]) + { + //Save the 'aaid' of each triggerable effect to an array + newbon->SpellTriggers[i] = aaid; + break; + } + } + break; + + case SE_CriticalHitChance: + { + if(base2 == -1) + newbon->CriticalHitChance[HIGHEST_SKILL+1] += base1; + else + newbon->CriticalHitChance[base2] += base1; + } + break; + + case SE_CriticalDamageMob: + { + // base1 = effect value, base2 = skill restrictions(-1 for all) + if(base2 == -1) + newbon->CritDmgMob[HIGHEST_SKILL+1] += base1; + else + newbon->CritDmgMob[base2] += base1; + break; + } + + case SE_CriticalSpellChance: + { + newbon->CriticalSpellChance += base1; + + if (base2 > newbon->SpellCritDmgIncNoStack) + newbon->SpellCritDmgIncNoStack = base2; + + break; + } + + case SE_ResistFearChance: + { + if(base1 == 100) // If we reach 100% in a single spell/item then we should be immune to negative fear resist effects until our immunity is over + newbon->Fearless = true; + + newbon->ResistFearChance += base1; // these should stack + break; + } + + case SE_SkillDamageAmount: + { + if(base2 == -1) + newbon->SkillDamageAmount[HIGHEST_SKILL+1] += base1; + else + newbon->SkillDamageAmount[base2] += base1; + break; + } + + case SE_SpecialAttackKBProc: + { + //You can only have one of these per client. [AA Dragon Punch] + newbon->SpecialAttackKBProc[0] = base1; //Chance base 100 = 25% proc rate + newbon->SpecialAttackKBProc[1] = base2; //Skill to KB Proc Off + break; + } + + case SE_DamageModifier: + { + if(base2 == -1) + newbon->DamageModifier[HIGHEST_SKILL+1] += base1; + else + newbon->DamageModifier[base2] += base1; + break; + } + + case SE_DamageModifier2: + { + if(base2 == -1) + newbon->DamageModifier2[HIGHEST_SKILL+1] += base1; + else + newbon->DamageModifier2[base2] += base1; + break; + } + + case SE_SlayUndead: + { + if(newbon->SlayUndead[1] < base1) + newbon->SlayUndead[0] = base1; // Rate + newbon->SlayUndead[1] = base2; // Damage Modifier + break; + } + + case SE_DoubleRiposte: + { + newbon->DoubleRiposte += base1; + } + + case SE_GiveDoubleRiposte: + { + //0=Regular Riposte 1=Skill Attack Riposte 2=Skill + if(base2 == 0){ + if(newbon->GiveDoubleRiposte[0] < base1) + newbon->GiveDoubleRiposte[0] = base1; + } + //Only for special attacks. + else if(base2 > 0 && (newbon->GiveDoubleRiposte[1] < base1)){ + newbon->GiveDoubleRiposte[1] = base1; + newbon->GiveDoubleRiposte[2] = base2; + } + + break; + } + + //Kayen: Not sure best way to implement this yet. + //Physically raises skill cap ie if 55/55 it will raise to 55/60 + case SE_RaiseSkillCap: + { + if(newbon->RaiseSkillCap[0] < base1){ + newbon->RaiseSkillCap[0] = base1; //value + newbon->RaiseSkillCap[1] = base2; //skill + } + break; + } + + case SE_MasteryofPast: + { + if(newbon->MasteryofPast < base1) + newbon->MasteryofPast = base1; + break; + } + + case SE_CastingLevel2: + case SE_CastingLevel: + { + newbon->effective_casting_level += base1; + break; + } + + case SE_DivineSave: + { + if(newbon->DivineSaveChance[0] < base1) + { + newbon->DivineSaveChance[0] = base1; + newbon->DivineSaveChance[1] = base2; + } + break; + } + + + case SE_SpellEffectResistChance: + { + for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) + { + if(newbon->SEResist[e+1] && (newbon->SEResist[e] == base2) && (newbon->SEResist[e+1] < base1)){ + newbon->SEResist[e] = base2; //Spell Effect ID + newbon->SEResist[e+1] = base1; //Resist Chance + break; + } + else if (!newbon->SEResist[e+1]){ + newbon->SEResist[e] = base2; //Spell Effect ID + newbon->SEResist[e+1] = base1; //Resist Chance + break; + } + } + break; + } + + case SE_MitigateDamageShield: + { + if (base1 < 0) + base1 = base1*(-1); + + newbon->DSMitigationOffHand += base1; + break; + } + + case SE_FinishingBlow: + { + //base1 = chance, base2 = damage + if (newbon->FinishingBlow[1] < base2){ + newbon->FinishingBlow[0] = base1; + newbon->FinishingBlow[1] = base2; + } + break; + } + + case SE_FinishingBlowLvl: + { + //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) + if (newbon->FinishingBlowLvl[0] < base1){ + newbon->FinishingBlowLvl[0] = base1; + newbon->FinishingBlowLvl[1] = base2; + } + break; + } + + case SE_StunBashChance: + newbon->StunBashChance += base1; + break; + + case SE_IncreaseChanceMemwipe: + newbon->IncreaseChanceMemwipe += base1; + break; + + case SE_CriticalMend: + newbon->CriticalMend += base1; + break; + + case SE_HealRate: + newbon->HealRate += base1; + break; + + case SE_MeleeLifetap: + { + + if((base1 < 0) && (newbon->MeleeLifetap > base1)) + newbon->MeleeLifetap = base1; + + else if(newbon->MeleeLifetap < base1) + newbon->MeleeLifetap = base1; + break; + } + + case SE_Vampirism: + newbon->Vampirism += base1; + break; + + case SE_FrenziedDevastation: + newbon->FrenziedDevastation += base2; + break; + + case SE_SpellProcChance: + newbon->SpellProcChance += base1; + break; + + case SE_Berserk: + newbon->BerserkSPA = true; + break; + + case SE_Metabolism: + newbon->Metabolism += base1; + break; + + case SE_ImprovedReclaimEnergy: + { + if((base1 < 0) && (newbon->ImprovedReclaimEnergy > base1)) + newbon->ImprovedReclaimEnergy = base1; + + else if(newbon->ImprovedReclaimEnergy < base1) + newbon->ImprovedReclaimEnergy = base1; + break; + } + + case SE_HeadShot: + { + if(newbon->HeadShot[1] < base2){ + newbon->HeadShot[0] = base1; + newbon->HeadShot[1] = base2; + } + break; + } + + case SE_HeadShotLevel: + { + if(newbon->HSLevel < base1) + newbon->HSLevel = base1; + break; + } + + case SE_Assassinate: + { + if(newbon->Assassinate[1] < base2){ + newbon->Assassinate[0] = base1; + newbon->Assassinate[1] = base2; + } + break; + } + + case SE_AssassinateLevel: + { + if(newbon->AssassinateLevel < base1) + newbon->AssassinateLevel = base1; + break; + } + + case SE_PetMeleeMitigation: + newbon->PetMeleeMitigation += base1; + break; + + } + } +} + +void Mob::CalcSpellBonuses(StatBonuses* newbon) +{ + int i; + + memset(newbon, 0, sizeof(StatBonuses)); + newbon->AggroRange = -1; + newbon->AssistRange = -1; + + uint32 buff_count = GetMaxTotalSlots(); + for(i = 0; i < buff_count; i++) { + if(buffs[i].spellid != SPELL_UNKNOWN){ + ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, false, buffs[i].ticsremaining,i); + + if (buffs[i].numhits > 0) + Numhits(true); + } + } + + //Applies any perma NPC spell bonuses from npc_spells_effects table. + if (IsNPC()) + CastToNPC()->ApplyAISpellEffects(newbon); + + //Removes the spell bonuses that are effected by a 'negate' debuff. + if (spellbonuses.NegateEffects){ + for(i = 0; i < buff_count; i++) { + if( (buffs[i].spellid != SPELL_UNKNOWN) && (IsEffectInSpell(buffs[i].spellid, SE_NegateSpellEffect)) ) + NegateSpellsBonuses(buffs[i].spellid); + } + } + //this prolly suffer from roundoff error slightly... + newbon->AC = newbon->AC * 10 / 34; //ratio determined impirically from client. + if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. +} + +void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterId, bool item_bonus, uint32 ticsremaining, int buffslot, + bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) +{ + int i, effect_value, base2, max, effectid; + Mob *caster = nullptr; + + if(!IsAISpellEffect && !IsValidSpell(spell_id)) + return; + + if(casterId > 0) + caster = entity_list.GetMob(casterId); + + for (i = 0; i < EFFECT_COUNT; i++) + { + //Buffs/Item effects + if (!IsAISpellEffect) { + + if(IsBlankSpellEffect(spell_id, i)) + continue; + + uint8 focus = IsFocusEffect(spell_id, i); + if (focus) + { + newbon->FocusEffects[focus] = spells[spell_id].effectid[i]; + continue; + } + + + effectid = spells[spell_id].effectid[i]; + effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, caster, ticsremaining); + base2 = spells[spell_id].base2[i]; + max = spells[spell_id].max[i]; + } + //Use AISpellEffects + else { + effectid = effect_id; + effect_value = se_base; + base2 = se_limit; + max = se_max; + i = EFFECT_COUNT; //End the loop + } + + switch (effectid) + { + case SE_CurrentHP: //regens + if(effect_value > 0) { + newbon->HPRegen += effect_value; + } + break; + + case SE_CurrentEndurance: + newbon->EnduranceRegen += effect_value; + break; + + case SE_ChangeFrenzyRad: + { + // redundant to have level check here + if(newbon->AggroRange == -1 || effect_value < newbon->AggroRange) + { + newbon->AggroRange = effect_value; + } + break; + } + + case SE_Harmony: + { + // neotokyo: Harmony effect as buff - kinda tricky + // harmony could stack with a lull spell, which has better aggro range + // take the one with less range in any case + if(newbon->AssistRange == -1 || effect_value < newbon->AssistRange) + { + newbon->AssistRange = effect_value; + } + break; + } + + case SE_AttackSpeed: + { + if ((effect_value - 100) > 0) { // Haste + if (newbon->haste < 0) break; // Slowed - Don't apply haste + if ((effect_value - 100) > newbon->haste) { + newbon->haste = effect_value - 100; + } + } + else if ((effect_value - 100) < 0) { // Slow + int real_slow_value = (100 - effect_value) * -1; + real_slow_value -= ((real_slow_value * GetSlowMitigation()/100)); + if (real_slow_value < newbon->haste) + newbon->haste = real_slow_value; + } + break; + } + + case SE_AttackSpeed2: + { + if ((effect_value - 100) > 0) { // Haste V2 - Stacks with V1 but does not Overcap + if (newbon->hastetype2 < 0) break; //Slowed - Don't apply haste2 + if ((effect_value - 100) > newbon->hastetype2) { + newbon->hastetype2 = effect_value - 100; + } + } + else if ((effect_value - 100) < 0) { // Slow + int real_slow_value = (100 - effect_value) * -1; + real_slow_value -= ((real_slow_value * GetSlowMitigation()/100)); + if (real_slow_value < newbon->hastetype2) + newbon->hastetype2 = real_slow_value; + } + break; + } + + case SE_AttackSpeed3: + { + if (effect_value < 0){ //Slow + effect_value -= ((effect_value * GetSlowMitigation()/100)); + if (effect_value < newbon->hastetype3) + newbon->hastetype3 = effect_value; + } + + else if (effect_value > 0) { // Haste V3 - Stacks and Overcaps + if (effect_value > newbon->hastetype3) { + newbon->hastetype3 = effect_value; + } + } + break; + } + + case SE_AttackSpeed4: + { + if (effect_value < 0) //A few spells use negative values(Descriptions all indicate it should be a slow) + effect_value = effect_value * -1; + + if (effect_value > 0 && effect_value > newbon->inhibitmelee) { + effect_value -= ((effect_value * GetSlowMitigation()/100)); + if (effect_value > newbon->inhibitmelee) + newbon->inhibitmelee = effect_value; + } + + break; + } + + case SE_TotalHP: + { + newbon->HP += effect_value; + break; + } + + case SE_ManaRegen_v2: + case SE_CurrentMana: + { + newbon->ManaRegen += effect_value; + break; + } + + case SE_ManaPool: + { + newbon->Mana += effect_value; + break; + } + + case SE_Stamina: + { + newbon->EnduranceReduction += effect_value; + break; + } + + case SE_ACv2: + case SE_ArmorClass: + { + newbon->AC += effect_value; + break; + } + + case SE_ATK: + { + newbon->ATK += effect_value; + break; + } + + case SE_STR: + { + newbon->STR += effect_value; + break; + } + + case SE_DEX: + { + newbon->DEX += effect_value; + break; + } + + case SE_AGI: + { + newbon->AGI += effect_value; + break; + } + + case SE_STA: + { + newbon->STA += effect_value; + break; + } + + case SE_INT: + { + newbon->INT += effect_value; + break; + } + + case SE_WIS: + { + newbon->WIS += effect_value; + break; + } + + case SE_CHA: + { + if (spells[spell_id].base[i] != 0) { + newbon->CHA += effect_value; + } + break; + } + + case SE_AllStats: + { + newbon->STR += effect_value; + newbon->DEX += effect_value; + newbon->AGI += effect_value; + newbon->STA += effect_value; + newbon->INT += effect_value; + newbon->WIS += effect_value; + newbon->CHA += effect_value; + break; + } + + case SE_ResistFire: + { + newbon->FR += effect_value; + break; + } + + case SE_ResistCold: + { + newbon->CR += effect_value; + break; + } + + case SE_ResistPoison: + { + newbon->PR += effect_value; + break; + } + + case SE_ResistDisease: + { + newbon->DR += effect_value; + break; + } + + case SE_ResistMagic: + { + newbon->MR += effect_value; + break; + } + + case SE_ResistAll: + { + newbon->MR += effect_value; + newbon->DR += effect_value; + newbon->PR += effect_value; + newbon->CR += effect_value; + newbon->FR += effect_value; + break; + } + + case SE_ResistCorruption: + { + newbon->Corrup += effect_value; + break; + } + + case SE_RaiseStatCap: + { + switch(spells[spell_id].base2[i]) + { + //are these #define'd somewhere? + case 0: //str + newbon->STRCapMod += effect_value; + break; + case 1: //sta + newbon->STACapMod += effect_value; + break; + case 2: //agi + newbon->AGICapMod += effect_value; + break; + case 3: //dex + newbon->DEXCapMod += effect_value; + break; + case 4: //wis + newbon->WISCapMod += effect_value; + break; + case 5: //int + newbon->INTCapMod += effect_value; + break; + case 6: //cha + newbon->CHACapMod += effect_value; + break; + case 7: //mr + newbon->MRCapMod += effect_value; + break; + case 8: //cr + newbon->CRCapMod += effect_value; + break; + case 9: //fr + newbon->FRCapMod += effect_value; + break; + case 10: //pr + newbon->PRCapMod += effect_value; + break; + case 11: //dr + newbon->DRCapMod += effect_value; + break; + case 12: // corruption + newbon->CorrupCapMod += effect_value; + break; + } + break; + } + + case SE_CastingLevel2: + case SE_CastingLevel: // Brilliance of Ro + { + newbon->effective_casting_level += effect_value; + break; + } + + case SE_MovementSpeed: + newbon->movementspeed += effect_value; + break; + + case SE_SpellDamageShield: + newbon->SpellDamageShield += effect_value; + break; + + case SE_DamageShield: + { + newbon->DamageShield += effect_value; + newbon->DamageShieldSpellID = spell_id; + //When using npc_spells_effects MAX value can be set to determine DS Type + if (IsAISpellEffect && max) + newbon->DamageShieldType = GetDamageShieldType(spell_id, max); + else + newbon->DamageShieldType = GetDamageShieldType(spell_id); + + break; + } + + case SE_ReverseDS: + { + newbon->ReverseDamageShield += effect_value; + newbon->ReverseDamageShieldSpellID = spell_id; + + if (IsAISpellEffect && max) + newbon->ReverseDamageShieldType = GetDamageShieldType(spell_id, max); + else + newbon->ReverseDamageShieldType = GetDamageShieldType(spell_id); + break; + } + + case SE_Reflect: + newbon->reflect_chance += effect_value; + break; + + case SE_Amplification: + newbon->Amplification += effect_value; + break; + + case SE_ChangeAggro: + newbon->hatemod += effect_value; + break; + + case SE_MeleeMitigation: + //for some reason... this value is negative for increased mitigation + newbon->MeleeMitigation -= effect_value; + break; + + case SE_CriticalHitChance: + { + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) { + if(base2 == -1) + newbon->CriticalHitChance[HIGHEST_SKILL+1] += effect_value; + else + newbon->CriticalHitChance[base2] += effect_value; + } + + else if(effect_value < 0) { + + if(base2 == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] > effect_value) + newbon->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; + else if(base2 != -1 && newbon->CriticalHitChance[base2] > effect_value) + newbon->CriticalHitChance[base2] = effect_value; + } + + + else if(base2 == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] < effect_value) + newbon->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; + else if(base2 != -1 && newbon->CriticalHitChance[base2] < effect_value) + newbon->CriticalHitChance[base2] = effect_value; + + break; + } + + case SE_CrippBlowChance: + { + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + newbon->CrippBlowChance += effect_value; + + else if((effect_value < 0) && (newbon->CrippBlowChance > effect_value)) + newbon->CrippBlowChance = effect_value; + + else if(newbon->CrippBlowChance < effect_value) + newbon->CrippBlowChance = effect_value; + + break; + } + + case SE_AvoidMeleeChance: + { + //multiplier is to be compatible with item effects, watching for overflow too + effect_value = effect_value<3000? effect_value * 10 : 30000; + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + newbon->AvoidMeleeChance += effect_value; + + else if((effect_value < 0) && (newbon->AvoidMeleeChance > effect_value)) + newbon->AvoidMeleeChance = effect_value; + + else if(newbon->AvoidMeleeChance < effect_value) + newbon->AvoidMeleeChance = effect_value; + break; + } + + case SE_RiposteChance: + { + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + newbon->RiposteChance += effect_value; + + else if((effect_value < 0) && (newbon->RiposteChance > effect_value)) + newbon->RiposteChance = effect_value; + + else if(newbon->RiposteChance < effect_value) + newbon->RiposteChance = effect_value; + break; + } + + case SE_DodgeChance: + { + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + newbon->DodgeChance += effect_value; + + else if((effect_value < 0) && (newbon->DodgeChance > effect_value)) + newbon->DodgeChance = effect_value; + + if(newbon->DodgeChance < effect_value) + newbon->DodgeChance = effect_value; + break; + } + + case SE_ParryChance: + { + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + newbon->ParryChance += effect_value; + + else if((effect_value < 0) && (newbon->ParryChance > effect_value)) + newbon->ParryChance = effect_value; + + if(newbon->ParryChance < effect_value) + newbon->ParryChance = effect_value; + break; + } + + case SE_DualWieldChance: + { + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + newbon->DualWieldChance += effect_value; + + else if((effect_value < 0) && (newbon->DualWieldChance > effect_value)) + newbon->DualWieldChance = effect_value; + + if(newbon->DualWieldChance < effect_value) + newbon->DualWieldChance = effect_value; + break; + } + + case SE_DoubleAttackChance: + { + + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + newbon->DoubleAttackChance += effect_value; + + else if((effect_value < 0) && (newbon->DoubleAttackChance > effect_value)) + newbon->DoubleAttackChance = effect_value; + + if(newbon->DoubleAttackChance < effect_value) + newbon->DoubleAttackChance = effect_value; + break; + } + + case SE_TripleAttackChance: + { + + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + newbon->TripleAttackChance += effect_value; + + else if((effect_value < 0) && (newbon->TripleAttackChance > effect_value)) + newbon->TripleAttackChance = effect_value; + + if(newbon->TripleAttackChance < effect_value) + newbon->TripleAttackChance = effect_value; + break; + } + + case SE_MeleeLifetap: + { + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + newbon->MeleeLifetap += spells[spell_id].base[i]; + + else if((effect_value < 0) && (newbon->MeleeLifetap > effect_value)) + newbon->MeleeLifetap = effect_value; + + else if(newbon->MeleeLifetap < effect_value) + newbon->MeleeLifetap = effect_value; + break; + } + + case SE_Vampirism: + newbon->Vampirism += effect_value; + break; + + case SE_AllInstrumentMod: + { + if(effect_value > newbon->singingMod) + newbon->singingMod = effect_value; + if(effect_value > newbon->brassMod) + newbon->brassMod = effect_value; + if(effect_value > newbon->percussionMod) + newbon->percussionMod = effect_value; + if(effect_value > newbon->windMod) + newbon->windMod = effect_value; + if(effect_value > newbon->stringedMod) + newbon->stringedMod = effect_value; + break; + } + + case SE_ResistSpellChance: + newbon->ResistSpellChance += effect_value; + break; + + case SE_ResistFearChance: + { + if(effect_value == 100) // If we reach 100% in a single spell/item then we should be immune to negative fear resist effects until our immunity is over + newbon->Fearless = true; + + newbon->ResistFearChance += effect_value; // these should stack + break; + } + + case SE_Fearless: + newbon->Fearless = true; + break; + + case SE_HundredHands: + { + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + newbon->HundredHands += effect_value; + + if (effect_value > 0 && effect_value > newbon->HundredHands) + newbon->HundredHands = effect_value; //Increase Weapon Delay + else if (effect_value < 0 && effect_value < newbon->HundredHands) + newbon->HundredHands = effect_value; //Decrease Weapon Delay + break; + } + + case SE_MeleeSkillCheck: + { + if(newbon->MeleeSkillCheck < effect_value) { + newbon->MeleeSkillCheck = effect_value; + newbon->MeleeSkillCheckSkill = base2==-1?255:base2; + } + break; + } + + case SE_HitChance: + { + + if (RuleB(Spells, AdditiveBonusValues) && item_bonus){ + if(base2 == -1) + newbon->HitChanceEffect[HIGHEST_SKILL+1] += effect_value; + else + newbon->HitChanceEffect[base2] += effect_value; + } + + else if(base2 == -1){ + + if ((effect_value < 0) && (newbon->HitChanceEffect[HIGHEST_SKILL+1] > effect_value)) + newbon->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; + + else if (!newbon->HitChanceEffect[HIGHEST_SKILL+1] || + ((newbon->HitChanceEffect[HIGHEST_SKILL+1] > 0) && (newbon->HitChanceEffect[HIGHEST_SKILL+1] < effect_value))) + newbon->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; + } + + else { + + if ((effect_value < 0) && (newbon->HitChanceEffect[base2] > effect_value)) + newbon->HitChanceEffect[base2] = effect_value; + + else if (!newbon->HitChanceEffect[base2] || + ((newbon->HitChanceEffect[base2] > 0) && (newbon->HitChanceEffect[base2] < effect_value))) + newbon->HitChanceEffect[base2] = effect_value; + } + + break; + + } + + case SE_DamageModifier: + { + if(base2 == -1) + newbon->DamageModifier[HIGHEST_SKILL+1] += effect_value; + else + newbon->DamageModifier[base2] += effect_value; + break; + } + + case SE_DamageModifier2: + { + if(base2 == -1) + newbon->DamageModifier2[HIGHEST_SKILL+1] += effect_value; + else + newbon->DamageModifier2[base2] += effect_value; + break; + } + + case SE_MinDamageModifier: + { + if(base2 == -1) + newbon->MinDamageModifier[HIGHEST_SKILL+1] += effect_value; + else + newbon->MinDamageModifier[base2] += effect_value; + break; + } + + case SE_StunResist: + { + if(newbon->StunResist < effect_value) + newbon->StunResist = effect_value; + break; + } + + case SE_ProcChance: + { + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) + newbon->ProcChanceSPA += effect_value; + + else if((effect_value < 0) && (newbon->ProcChanceSPA > effect_value)) + newbon->ProcChanceSPA = effect_value; + + if(newbon->ProcChanceSPA < effect_value) + newbon->ProcChanceSPA = effect_value; + + break; + } + + case SE_ExtraAttackChance: + newbon->ExtraAttackChance += effect_value; + break; + + case SE_PercentXPIncrease: + { + if(newbon->XPRateMod < effect_value) + newbon->XPRateMod = effect_value; + break; + } + + case SE_DeathSave: + { + if(newbon->DeathSave[0] < effect_value) + { + newbon->DeathSave[0] = effect_value; //1='Partial' 2='Full' + newbon->DeathSave[1] = buffslot; + //These are used in later expansion spell effects. + newbon->DeathSave[2] = base2;//Min level for HealAmt + newbon->DeathSave[3] = max;//HealAmt + } + break; + } + + case SE_DivineSave: + { + if (RuleB(Spells, AdditiveBonusValues) && item_bonus) { + newbon->DivineSaveChance[0] += effect_value; + newbon->DivineSaveChance[1] = 0; + } + + else if(newbon->DivineSaveChance[0] < effect_value) + { + newbon->DivineSaveChance[0] = effect_value; + newbon->DivineSaveChance[1] = base2; + //SetDeathSaveChance(true); + } + break; + } + + case SE_Flurry: + newbon->FlurryChance += effect_value; + break; + + case SE_Accuracy: + { + if ((effect_value < 0) && (newbon->Accuracy[HIGHEST_SKILL+1] > effect_value)) + newbon->Accuracy[HIGHEST_SKILL+1] = effect_value; + + else if (!newbon->Accuracy[HIGHEST_SKILL+1] || + ((newbon->Accuracy[HIGHEST_SKILL+1] > 0) && (newbon->Accuracy[HIGHEST_SKILL+1] < effect_value))) + newbon->Accuracy[HIGHEST_SKILL+1] = effect_value; + break; + } + + case SE_MaxHPChange: + newbon->MaxHPChange += effect_value; + break; + + case SE_EndurancePool: + newbon->Endurance += effect_value; + break; + + case SE_HealRate: + newbon->HealRate += effect_value; + break; + + case SE_SkillDamageTaken: + { + //When using npc_spells_effects if MAX value set, use stackable quest based modifier. + if (IsAISpellEffect && max){ + if(base2 == -1) + SkillDmgTaken_Mod[HIGHEST_SKILL+1] = effect_value; + else + SkillDmgTaken_Mod[base2] = effect_value; + } + else { + + if(base2 == -1) + newbon->SkillDmgTaken[HIGHEST_SKILL+1] += effect_value; + else + newbon->SkillDmgTaken[base2] += effect_value; + + } + break; + } + + case SE_TriggerOnCast: + { + for(int e = 0; e < MAX_SPELL_TRIGGER; e++) + { + if(!newbon->SpellTriggers[e]) + { + newbon->SpellTriggers[e] = spell_id; + break; + } + } + break; + } + + case SE_SpellCritChance: + newbon->CriticalSpellChance += effect_value; + break; + + case SE_CriticalSpellChance: + { + newbon->CriticalSpellChance += effect_value; + + if (base2 > newbon->SpellCritDmgIncNoStack) + newbon->SpellCritDmgIncNoStack = base2; + break; + } + + case SE_SpellCritDmgIncrease: + newbon->SpellCritDmgIncrease += effect_value; + break; + + case SE_DotCritDmgIncrease: + newbon->DotCritDmgIncrease += effect_value; + break; + + case SE_CriticalHealChance: + newbon->CriticalHealChance += effect_value; + break; + + case SE_CriticalHealOverTime: + newbon->CriticalHealOverTime += effect_value; + break; + + case SE_CriticalHealDecay: + newbon->CriticalHealDecay = true; + break; + + case SE_CriticalRegenDecay: + newbon->CriticalRegenDecay = true; + break; + + case SE_CriticalDotDecay: + newbon->CriticalDotDecay = true; + break; + + case SE_MitigateDamageShield: + { + if (effect_value < 0) + effect_value = effect_value*-1; + + newbon->DSMitigationOffHand += effect_value; + break; + } + + case SE_CriticalDoTChance: + newbon->CriticalDoTChance += effect_value; + break; + + case SE_ProcOnKillShot: + { + for(int e = 0; e < MAX_SPELL_TRIGGER*3; e+=3) + { + if(!newbon->SpellOnKill[e]) + { + // Base2 = Spell to fire | Base1 = % chance | Base3 = min level + newbon->SpellOnKill[e] = base2; + newbon->SpellOnKill[e+1] = effect_value; + newbon->SpellOnKill[e+2] = max; + break; + } + } + break; + } + + case SE_SpellOnDeath: + { + for(int e = 0; e < MAX_SPELL_TRIGGER; e+=2) + { + if(!newbon->SpellOnDeath[e]) + { + // Base2 = Spell to fire | Base1 = % chance + newbon->SpellOnDeath[e] = base2; + newbon->SpellOnDeath[e+1] = effect_value; + break; + } + } + break; + } + + case SE_CriticalDamageMob: + { + if(base2 == -1) + newbon->CritDmgMob[HIGHEST_SKILL+1] += effect_value; + else + newbon->CritDmgMob[base2] += effect_value; + break; + } + + case SE_ReduceSkillTimer: + { + if(newbon->SkillReuseTime[base2] < effect_value) + newbon->SkillReuseTime[base2] = effect_value; + break; + } + + case SE_SkillDamageAmount: + { + if(base2 == -1) + newbon->SkillDamageAmount[HIGHEST_SKILL+1] += effect_value; + else + newbon->SkillDamageAmount[base2] += effect_value; + break; + } + + case SE_GravityEffect: + newbon->GravityEffect = 1; + break; + + case SE_AntiGate: + newbon->AntiGate = true; + break; + + case SE_MagicWeapon: + newbon->MagicWeapon = true; + break; + + case SE_IncreaseBlockChance: + newbon->IncreaseBlockChance += effect_value; + break; + + case SE_PersistantCasting: + newbon->PersistantCasting += effect_value; + break; + + case SE_LimitHPPercent: + { + if(newbon->HPPercCap[0] != 0 && newbon->HPPercCap[0] > effect_value){ + newbon->HPPercCap[0] = effect_value; + newbon->HPPercCap[1] = base2; + } + else if(newbon->HPPercCap[0] == 0){ + newbon->HPPercCap[0] = effect_value; + newbon->HPPercCap[1] = base2; + } + break; + } + case SE_LimitManaPercent: + { + if(newbon->ManaPercCap[0] != 0 && newbon->ManaPercCap[0] > effect_value){ + newbon->ManaPercCap[0] = effect_value; + newbon->ManaPercCap[1] = base2; + } + else if(newbon->ManaPercCap[0] == 0) { + newbon->ManaPercCap[0] = effect_value; + newbon->ManaPercCap[1] = base2; + } + + break; + } + case SE_LimitEndPercent: + { + if(newbon->EndPercCap[0] != 0 && newbon->EndPercCap[0] > effect_value) { + newbon->EndPercCap[0] = effect_value; + newbon->EndPercCap[1] = base2; + } + + else if(newbon->EndPercCap[0] == 0){ + newbon->EndPercCap[0] = effect_value; + newbon->EndPercCap[1] = base2; + } + + break; + } + + case SE_BlockNextSpellFocus: + newbon->BlockNextSpell = true; + break; + + case SE_NegateSpellEffect: + newbon->NegateEffects = true; + break; + + case SE_ImmuneFleeing: + newbon->ImmuneToFlee = true; + break; + + case SE_DelayDeath: + newbon->DelayDeath += effect_value; + break; + + case SE_SpellProcChance: + newbon->SpellProcChance += effect_value; + break; + + case SE_CharmBreakChance: + newbon->CharmBreakChance += effect_value; + break; + + case SE_BardSongRange: + newbon->SongRange += effect_value; + break; + + case SE_HPToMana: + { + //Lower the ratio the more favorable + if((!newbon->HPToManaConvert) || (newbon->HPToManaConvert >= effect_value)) + newbon->HPToManaConvert = spells[spell_id].base[i]; + break; + } + + case SE_SkillDamageAmount2: + { + if(base2 == -1) + newbon->SkillDamageAmount2[HIGHEST_SKILL+1] += effect_value; + else + newbon->SkillDamageAmount2[base2] += effect_value; + break; + } + + case SE_NegateAttacks: + { + if (!newbon->NegateAttacks[0] || + ((newbon->NegateAttacks[0] && newbon->NegateAttacks[2]) && (newbon->NegateAttacks[2] < max))){ + newbon->NegateAttacks[0] = 1; + newbon->NegateAttacks[1] = buffslot; + newbon->NegateAttacks[2] = max; + } + break; + } + + case SE_MitigateMeleeDamage: + { + if (newbon->MitigateMeleeRune[0] < effect_value){ + newbon->MitigateMeleeRune[0] = effect_value; + newbon->MitigateMeleeRune[1] = buffslot; + newbon->MitigateMeleeRune[2] = base2; + newbon->MitigateMeleeRune[3] = max; + } + break; + } + + + case SE_MeleeThresholdGuard: + { + if (newbon->MeleeThresholdGuard[0] < effect_value){ + newbon->MeleeThresholdGuard[0] = effect_value; + newbon->MeleeThresholdGuard[1] = buffslot; + newbon->MeleeThresholdGuard[2] = base2; + } + break; + } + + case SE_SpellThresholdGuard: + { + if (newbon->SpellThresholdGuard[0] < effect_value){ + newbon->SpellThresholdGuard[0] = effect_value; + newbon->SpellThresholdGuard[1] = buffslot; + newbon->SpellThresholdGuard[2] = base2; + } + break; + } + + case SE_MitigateSpellDamage: + { + if (newbon->MitigateSpellRune[0] < effect_value){ + newbon->MitigateSpellRune[0] = effect_value; + newbon->MitigateSpellRune[1] = buffslot; + newbon->MitigateSpellRune[2] = base2; + newbon->MitigateSpellRune[3] = max; + } + break; + } + + case SE_MitigateDotDamage: + { + if (newbon->MitigateDotRune[0] < effect_value){ + newbon->MitigateDotRune[0] = effect_value; + newbon->MitigateDotRune[1] = buffslot; + newbon->MitigateDotRune[2] = base2; + newbon->MitigateDotRune[3] = max; + } + break; + } + + case SE_ManaAbsorbPercentDamage: + { + if (newbon->ManaAbsorbPercentDamage[0] < effect_value){ + newbon->ManaAbsorbPercentDamage[0] = effect_value; + newbon->ManaAbsorbPercentDamage[1] = buffslot; + } + break; + } + + case SE_TriggerMeleeThreshold: + { + if (newbon->TriggerMeleeThreshold[2] < base2){ + newbon->TriggerMeleeThreshold[0] = effect_value; + newbon->TriggerMeleeThreshold[1] = buffslot; + newbon->TriggerMeleeThreshold[2] = base2; + } + break; + } + + case SE_TriggerSpellThreshold: + { + if (newbon->TriggerSpellThreshold[2] < base2){ + newbon->TriggerSpellThreshold[0] = effect_value; + newbon->TriggerSpellThreshold[1] = buffslot; + newbon->TriggerSpellThreshold[2] = base2; + } + break; + } + + case SE_ShieldBlock: + newbon->ShieldBlock += effect_value; + break; + + case SE_ShieldEquipHateMod: + newbon->ShieldEquipHateMod += effect_value; + break; + + case SE_ShieldEquipDmgMod: + newbon->ShieldEquipDmgMod[0] += effect_value; + newbon->ShieldEquipDmgMod[1] += base2; + break; + + case SE_BlockBehind: + newbon->BlockBehind += effect_value; + break; + + case SE_Fear: + newbon->IsFeared = true; + break; + + //AA bonuses - implemented broadly into spell/item effects + case SE_FrontalStunResist: + newbon->FrontalStunResist += effect_value; + break; + + case SE_ImprovedBindWound: + newbon->BindWound += effect_value; + break; + + case SE_MaxBindWound: + newbon->MaxBindWound += effect_value; + break; + + case SE_BaseMovementSpeed: + newbon->BaseMovementSpeed += effect_value; + break; + + case SE_IncreaseRunSpeedCap: + newbon->IncreaseRunSpeedCap += effect_value; + break; + + case SE_DoubleSpecialAttack: + newbon->DoubleSpecialAttack += effect_value; + break; + + case SE_TripleBackstab: + newbon->TripleBackstab += effect_value; + break; + + case SE_FrontalBackstabMinDmg: + newbon->FrontalBackstabMinDmg = true; + break; + + case SE_FrontalBackstabChance: + newbon->FrontalBackstabChance += effect_value; + break; + + case SE_ConsumeProjectile: + newbon->ConsumeProjectile += effect_value; + break; + + case SE_ForageAdditionalItems: + newbon->ForageAdditionalItems += effect_value; + break; + + case SE_Salvage: + newbon->SalvageChance += effect_value; + break; + + case SE_ArcheryDamageModifier: + newbon->ArcheryDamageModifier += effect_value; + break; + + case SE_DoubleRangedAttack: + newbon->DoubleRangedAttack += effect_value; + break; + + case SE_SecondaryDmgInc: + newbon->SecondaryDmgInc = true; + break; + + case SE_StrikeThrough: + case SE_StrikeThrough2: + newbon->StrikeThrough += effect_value; + break; + + case SE_GiveDoubleAttack: + newbon->GiveDoubleAttack += effect_value; + break; + + case SE_PetCriticalHit: + newbon->PetCriticalHit += effect_value; + break; + + case SE_CombatStability: + newbon->CombatStability += effect_value; + break; + + case SE_AddSingingMod: + switch (base2) + { + case ItemTypeWindInstrument: + newbon->windMod += effect_value; + break; + case ItemTypeStringedInstrument: + newbon->stringedMod += effect_value; + break; + case ItemTypeBrassInstrument: + newbon->brassMod += effect_value; + break; + case ItemTypePercussionInstrument: + newbon->percussionMod += effect_value; + break; + case ItemTypeSinging: + newbon->singingMod += effect_value; + break; + } + break; + + case SE_SongModCap: + newbon->songModCap += effect_value; + break; + + case SE_PetAvoidance: + newbon->PetAvoidance += effect_value; + break; + + case SE_Ambidexterity: + newbon->Ambidexterity += effect_value; + break; + + case SE_PetMaxHP: + newbon->PetMaxHP += effect_value; + break; + + case SE_PetFlurry: + newbon->PetFlurry += effect_value; + break; + + case SE_GivePetGroupTarget: + newbon->GivePetGroupTarget = true; + break; + + case SE_RootBreakChance: + newbon->RootBreakChance += effect_value; + break; + + case SE_ChannelChanceItems: + newbon->ChannelChanceItems += effect_value; + break; + + case SE_ChannelChanceSpells: + newbon->ChannelChanceSpells += effect_value; + break; + + case SE_UnfailingDivinity: + newbon->UnfailingDivinity += effect_value; + break; + + + case SE_ItemHPRegenCapIncrease: + newbon->ItemHPRegenCap += effect_value; + break; + + case SE_OffhandRiposteFail: + newbon->OffhandRiposteFail += effect_value; + break; + + case SE_ItemAttackCapIncrease: + newbon->ItemATKCap += effect_value; + break; + + case SE_TwoHandBluntBlock: + newbon->TwoHandBluntBlock += effect_value; + break; + + case SE_StunBashChance: + newbon->StunBashChance += effect_value; + break; + + case SE_IncreaseChanceMemwipe: + newbon->IncreaseChanceMemwipe += effect_value; + break; + + case SE_CriticalMend: + newbon->CriticalMend += effect_value; + break; + + case SE_SpellEffectResistChance: + { + for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) + { + if(newbon->SEResist[e+1] && (newbon->SEResist[e] == base2) && (newbon->SEResist[e+1] < effect_value)){ + newbon->SEResist[e] = base2; //Spell Effect ID + newbon->SEResist[e+1] = effect_value; //Resist Chance + break; + } + else if (!newbon->SEResist[e+1]){ + newbon->SEResist[e] = base2; //Spell Effect ID + newbon->SEResist[e+1] = effect_value; //Resist Chance + break; + } + } + break; + } + + case SE_MasteryofPast: + { + if(newbon->MasteryofPast < effect_value) + newbon->MasteryofPast = effect_value; + break; + } + + case SE_DoubleRiposte: + { + newbon->DoubleRiposte += effect_value; + } + + case SE_GiveDoubleRiposte: + { + //Only allow for regular double riposte chance. + if(newbon->GiveDoubleRiposte[base2] == 0){ + if(newbon->GiveDoubleRiposte[0] < effect_value) + newbon->GiveDoubleRiposte[0] = effect_value; + } + break; + } + + case SE_SlayUndead: + { + if(newbon->SlayUndead[1] < effect_value) + newbon->SlayUndead[0] = effect_value; // Rate + newbon->SlayUndead[1] = base2; // Damage Modifier + break; + } + + case SE_TriggerOnReqTarget: + case SE_TriggerOnReqCaster: + newbon->TriggerOnValueAmount = true; + break; + + case SE_DivineAura: + newbon->DivineAura = true; + break; + + case SE_ImprovedTaunt: + if (newbon->ImprovedTaunt[0] < effect_value) { + newbon->ImprovedTaunt[0] = effect_value; + newbon->ImprovedTaunt[1] = base2; + newbon->ImprovedTaunt[2] = buffslot; + } + break; + + + case SE_DistanceRemoval: + newbon->DistanceRemoval = true; + break; + + case SE_FrenziedDevastation: + newbon->FrenziedDevastation += base2; + break; + + case SE_Root: + if (newbon->Root[0] && (newbon->Root[1] > buffslot)){ + newbon->Root[0] = 1; + newbon->Root[1] = buffslot; + } + else if (!newbon->Root[0]){ + newbon->Root[0] = 1; + newbon->Root[1] = buffslot; + } + break; + + case SE_Rune: + + if (newbon->MeleeRune[0] && (newbon->MeleeRune[1] > buffslot)){ + + newbon->MeleeRune[0] = effect_value; + newbon->MeleeRune[1] = buffslot; + } + else if (!newbon->MeleeRune[0]){ + newbon->MeleeRune[0] = effect_value; + newbon->MeleeRune[1] = buffslot; + } + + break; + + case SE_AbsorbMagicAtt: + if (newbon->AbsorbMagicAtt[0] && (newbon->AbsorbMagicAtt[1] > buffslot)){ + newbon->AbsorbMagicAtt[0] = effect_value; + newbon->AbsorbMagicAtt[1] = buffslot; + } + else if (!newbon->AbsorbMagicAtt[0]){ + newbon->AbsorbMagicAtt[0] = effect_value; + newbon->AbsorbMagicAtt[1] = buffslot; + } + break; + + case SE_NegateIfCombat: + newbon->NegateIfCombat = true; + break; + + case SE_Screech: + newbon->Screech = effect_value; + break; + + case SE_AlterNPCLevel: + + if (IsNPC()){ + if (!newbon->AlterNPCLevel + || ((effect_value < 0) && (newbon->AlterNPCLevel > effect_value)) + || ((effect_value > 0) && (newbon->AlterNPCLevel < effect_value))) { + + int16 tmp_lv = GetOrigLevel() + effect_value; + if (tmp_lv < 1) + tmp_lv = 1; + else if (tmp_lv > 255) + tmp_lv = 255; + if ((GetLevel() != tmp_lv)){ + newbon->AlterNPCLevel = effect_value; + SetLevel(tmp_lv); + } + } + } + break; + + case SE_AStacker: + newbon->AStacker[0] = 1; + newbon->AStacker[1] = effect_value; + break; + + case SE_BStacker: + newbon->BStacker[0] = 1; + newbon->BStacker[1] = effect_value; + break; + + case SE_CStacker: + newbon->CStacker[0] = 1; + newbon->CStacker[1] = effect_value; + break; + + case SE_DStacker: + newbon->DStacker[0] = 1; + newbon->DStacker[1] = effect_value; + break; + + case SE_Berserk: + newbon->BerserkSPA = true; + break; + + + case SE_Metabolism: + newbon->Metabolism += effect_value; + break; + + case SE_ImprovedReclaimEnergy: + { + if((effect_value < 0) && (newbon->ImprovedReclaimEnergy > effect_value)) + newbon->ImprovedReclaimEnergy = effect_value; + + else if(newbon->ImprovedReclaimEnergy < effect_value) + newbon->ImprovedReclaimEnergy = effect_value; + break; + } + + case SE_HeadShot: + { + if(newbon->HeadShot[1] < base2){ + newbon->HeadShot[0] = effect_value; + newbon->HeadShot[1] = base2; + } + break; + } + + case SE_HeadShotLevel: + { + if(newbon->HSLevel < effect_value) + newbon->HSLevel = effect_value; + break; + } + + case SE_Assassinate: + { + if(newbon->Assassinate[1] < base2){ + newbon->Assassinate[0] = effect_value; + newbon->Assassinate[1] = base2; + } + break; + } + + case SE_AssassinateLevel: + { + if(newbon->AssassinateLevel < effect_value) + newbon->AssassinateLevel = effect_value; + break; + } + + case SE_FinishingBlow: + { + //base1 = chance, base2 = damage + if (newbon->FinishingBlow[1] < base2){ + newbon->FinishingBlow[0] = effect_value; + newbon->FinishingBlow[1] = base2; + } + break; + } + + case SE_FinishingBlowLvl: + { + //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) + if (newbon->FinishingBlowLvl[0] < effect_value){ + newbon->FinishingBlowLvl[0] = effect_value; + newbon->FinishingBlowLvl[1] = base2; + } + break; + } + + case SE_PetMeleeMitigation: + newbon->PetMeleeMitigation += effect_value; + break; + + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table + if (IsAISpellEffect) { + + //Non-Focused Effect to modify incomming spell damage by resist type. + case SE_FcSpellVulnerability: + ModVulnerability(base2, effect_value); + break; + } + } + } +} + +void NPC::CalcItemBonuses(StatBonuses *newbon) +{ + if(newbon){ + + for(int i = 0; i < MAX_WORN_INVENTORY; i++){ + const Item_Struct *cur = database.GetItem(equipment[i]); + if(cur){ + //basic stats + newbon->AC += cur->AC; + newbon->HP += cur->HP; + newbon->Mana += cur->Mana; + newbon->Endurance += cur->Endur; + newbon->STR += (cur->AStr + cur->HeroicStr); + newbon->STA += (cur->ASta + cur->HeroicSta); + newbon->DEX += (cur->ADex + cur->HeroicDex); + newbon->AGI += (cur->AAgi + cur->HeroicAgi); + newbon->INT += (cur->AInt + cur->HeroicInt); + newbon->WIS += (cur->AWis + cur->HeroicWis); + newbon->CHA += (cur->ACha + cur->HeroicCha); + newbon->MR += (cur->MR + cur->HeroicMR); + newbon->FR += (cur->FR + cur->HeroicFR); + newbon->CR += (cur->CR + cur->HeroicCR); + newbon->PR += (cur->PR + cur->HeroicPR); + newbon->DR += (cur->DR + cur->HeroicDR); + newbon->Corrup += (cur->SVCorruption + cur->HeroicSVCorrup); + + //more complex stats + if(cur->Regen > 0) { + newbon->HPRegen += cur->Regen; + } + if(cur->ManaRegen > 0) { + newbon->ManaRegen += cur->ManaRegen; + } + if(cur->Attack > 0) { + newbon->ATK += cur->Attack; + } + if(cur->DamageShield > 0) { + newbon->DamageShield += cur->DamageShield; + } + if(cur->SpellShield > 0) { + newbon->SpellDamageShield += cur->SpellShield; + } + if(cur->Shielding > 0) { + newbon->MeleeMitigation += cur->Shielding; + } + if(cur->StunResist > 0) { + newbon->StunResist += cur->StunResist; + } + if(cur->StrikeThrough > 0) { + newbon->StrikeThrough += cur->StrikeThrough; + } + if(cur->Avoidance > 0) { + newbon->AvoidMeleeChance += cur->Avoidance; + } + if(cur->Accuracy > 0) { + newbon->HitChance += cur->Accuracy; + } + if(cur->CombatEffects > 0) { + newbon->ProcChance += cur->CombatEffects; + } + if (cur->Worn.Effect>0 && (cur->Worn.Type == ET_WornEffect)) { // latent effects + ApplySpellsBonuses(cur->Worn.Effect, cur->Worn.Level, newbon); + } + if (cur->Haste > newbon->haste) + newbon->haste = cur->Haste; + } + } + + } +} + +void Client::CalcItemScale() +{ + bool changed = false; + + if(CalcItemScale(0, 21)) + changed = true; + + if(CalcItemScale(22, 30)) + changed = true; + + if(CalcItemScale(251, 341)) + changed = true; + + if(CalcItemScale(400, 405)) + changed = true; + + //Power Source Slot + if (GetClientVersion() >= EQClientSoF) + { + if(CalcItemScale(9999, 10000)) + changed = true; + } + + if(changed) + { + CalcBonuses(); + } +} + +bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) +{ + bool changed = false; + int i; + for (i = slot_x; i < slot_y; i++) { + ItemInst* inst = m_inv.GetItem(i); + if(inst == 0) + continue; + + bool update_slot = false; + if(inst->IsScaling()) + { + uint16 oldexp = inst->GetExp(); + parse->EventItem(EVENT_SCALE_CALC, this, inst, nullptr, "", 0); + + if (inst->GetExp() != oldexp) { // if the scaling factor changed, rescale the item and update the client + inst->ScaleItem(); + changed = true; + update_slot = true; + } + } + + //iterate all augments + for(int x = 0; x < MAX_AUGMENT_SLOTS; ++x) + { + ItemInst * a_inst = inst->GetAugment(x); + if(!a_inst) + continue; + + if(a_inst->IsScaling()) + { + uint16 oldexp = a_inst->GetExp(); + parse->EventItem(EVENT_SCALE_CALC, this, a_inst, nullptr, "", 0); + + if (a_inst->GetExp() != oldexp) + { + a_inst->ScaleItem(); + changed = true; + update_slot = true; + } + } + } + + if(update_slot) + { + SendItemPacket(i, inst, ItemPacketCharmUpdate); + } + } + return changed; +} + +void Client::DoItemEnterZone() { + bool changed = false; + + if(DoItemEnterZone(0, 21)) + changed = true; + + if(DoItemEnterZone(22, 30)) + changed = true; + + if(DoItemEnterZone(251, 341)) + changed = true; + + if(DoItemEnterZone(400, 405)) + changed = true; + + //Power Source Slot + if (GetClientVersion() >= EQClientSoF) + { + if(DoItemEnterZone(9999, 10000)) + changed = true; + } + + if(changed) + { + CalcBonuses(); + } +} + +bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { + bool changed = false; + for(int i = slot_x; i < slot_y; i++) { + ItemInst* inst = m_inv.GetItem(i); + if(!inst) + continue; + + bool update_slot = false; + if(inst->IsScaling()) + { + uint16 oldexp = inst->GetExp(); + + parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); + if(i < 22 || i == 9999) { + parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); + } + + if (inst->GetExp() != oldexp) { // if the scaling factor changed, rescale the item and update the client + inst->ScaleItem(); + changed = true; + update_slot = true; + } + } else { + if(i < 22 || i == 9999) { + parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); + } + + parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); + } + + //iterate all augments + for(int x = 0; x < MAX_AUGMENT_SLOTS; ++x) + { + ItemInst *a_inst = inst->GetAugment(x); + if(!a_inst) + continue; + + if(a_inst->IsScaling()) + { + uint16 oldexp = a_inst->GetExp(); + + parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, a_inst, nullptr, "", 0); + + if (a_inst->GetExp() != oldexp) + { + a_inst->ScaleItem(); + changed = true; + update_slot = true; + } + } else { + parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, a_inst, nullptr, "", 0); + } + } + + if(update_slot) + { + SendItemPacket(i, inst, ItemPacketCharmUpdate); + } + } + return changed; +} + +uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_effect) +{ + uint16 effect = 0; + + if (!AA) + effect = spells[spell_id].effectid[effect_index]; + else + effect = aa_effect; + + switch (effect) + { + case SE_ImprovedDamage: + return focusImprovedDamage; + case SE_ImprovedHeal: + return focusImprovedHeal; + case SE_ReduceManaCost: + return focusManaCost; + case SE_IncreaseSpellHaste: + return focusSpellHaste; + case SE_IncreaseSpellDuration: + return focusSpellDuration; + case SE_SpellDurationIncByTic: + return focusSpellDurByTic; + case SE_SwarmPetDuration: + return focusSwarmPetDuration; + case SE_IncreaseRange: + return focusRange; + case SE_ReduceReagentCost: + return focusReagentCost; + case SE_PetPowerIncrease: + return focusPetPower; + case SE_SpellResistReduction: + return focusResistRate; + case SE_SpellHateMod: + return focusSpellHateMod; + case SE_ReduceReuseTimer: + return focusReduceRecastTime; + case SE_TriggerOnCast: + //return focusTriggerOnCast; + return 0; //This is calculated as an actual bonus + case SE_FcSpellVulnerability: + return focusSpellVulnerability; + case SE_BlockNextSpellFocus: + //return focusBlockNextSpell; + return 0; //This is calculated as an actual bonus + case SE_FcTwincast: + return focusTwincast; + case SE_SympatheticProc: + return focusSympatheticProc; + case SE_FcDamageAmt: + return focusFcDamageAmt; + case SE_FcDamageAmtCrit: + return focusFcDamageAmtCrit; + case SE_FcDamagePctCrit: + return focusFcDamagePctCrit; + case SE_FcDamageAmtIncoming: + return focusFcDamageAmtIncoming; + case SE_FcHealAmtIncoming: + return focusFcHealAmtIncoming; + case SE_FcHealPctIncoming: + return focusFcHealPctIncoming; + case SE_FcBaseEffects: + return focusFcBaseEffects; + case SE_FcIncreaseNumHits: + return focusIncreaseNumHits; + case SE_FcLimitUse: + return focusFcLimitUse; + case SE_FcMute: + return focusFcMute; + case SE_FcTimerRefresh: + return focusFcTimerRefresh; + case SE_FcStunTimeMod: + return focusFcStunTimeMod; + case SE_FcHealPctCritIncoming: + return focusFcHealPctCritIncoming; + case SE_FcHealAmt: + return focusFcHealAmt; + case SE_FcHealAmtCrit: + return focusFcHealAmtCrit; + } + return 0; +} + +void Mob::NegateSpellsBonuses(uint16 spell_id) +{ + if(!IsValidSpell(spell_id)) + return; + + int effect_value = 0; + + for (int i = 0; i < EFFECT_COUNT; i++) + { + if (spells[spell_id].effectid[i] == SE_NegateSpellEffect){ + + //Negate focus effects + for(int e = 0; e < HIGHEST_FOCUS+1; e++) + { + if (spellbonuses.FocusEffects[e] == spells[spell_id].base2[i]) + { + spellbonuses.FocusEffects[e] = effect_value; + continue; + } + } + + //Negate bonuses + switch (spells[spell_id].base2[i]) + { + case SE_CurrentHP: + if(spells[spell_id].base[i] == 1) { + spellbonuses.HPRegen = effect_value; + aabonuses.HPRegen = effect_value; + itembonuses.HPRegen = effect_value; + } + break; + + case SE_CurrentEndurance: + spellbonuses.EnduranceRegen = effect_value; + aabonuses.EnduranceRegen = effect_value; + itembonuses.EnduranceRegen = effect_value; + break; + + case SE_ChangeFrenzyRad: + spellbonuses.AggroRange = effect_value; + aabonuses.AggroRange = effect_value; + itembonuses.AggroRange = effect_value; + break; + + case SE_Harmony: + spellbonuses.AssistRange = effect_value; + aabonuses.AssistRange = effect_value; + itembonuses.AssistRange = effect_value; + break; + + case SE_AttackSpeed: + spellbonuses.haste = effect_value; + aabonuses.haste = effect_value; + itembonuses.haste = effect_value; + break; + + case SE_AttackSpeed2: + spellbonuses.hastetype2 = effect_value; + aabonuses.hastetype2 = effect_value; + itembonuses.hastetype2 = effect_value; + break; + + case SE_AttackSpeed3: + { + if (effect_value > 0) { + spellbonuses.hastetype3 = effect_value; + aabonuses.hastetype3 = effect_value; + itembonuses.hastetype3 = effect_value; + + } + break; + } + + case SE_AttackSpeed4: + spellbonuses.inhibitmelee = effect_value; + aabonuses.inhibitmelee = effect_value; + itembonuses.inhibitmelee = effect_value; + break; + + case SE_TotalHP: + spellbonuses.HP = effect_value; + aabonuses.HP = effect_value; + itembonuses.HP = effect_value; + break; + + case SE_ManaRegen_v2: + case SE_CurrentMana: + spellbonuses.ManaRegen = effect_value; + aabonuses.ManaRegen = effect_value; + itembonuses.ManaRegen = effect_value; + break; + + case SE_ManaPool: + spellbonuses.Mana = effect_value; + itembonuses.Mana = effect_value; + aabonuses.Mana = effect_value; + break; + + case SE_Stamina: + spellbonuses.EnduranceReduction = effect_value; + itembonuses.EnduranceReduction = effect_value; + aabonuses.EnduranceReduction = effect_value; + break; + + case SE_ACv2: + case SE_ArmorClass: + spellbonuses.AC = effect_value; + aabonuses.AC = effect_value; + itembonuses.AC = effect_value; + break; + + case SE_ATK: + spellbonuses.ATK = effect_value; + aabonuses.ATK = effect_value; + itembonuses.ATK = effect_value; + break; + + case SE_STR: + spellbonuses.STR = effect_value; + itembonuses.STR = effect_value; + aabonuses.STR = effect_value; + break; + + case SE_DEX: + spellbonuses.DEX = effect_value; + aabonuses.DEX = effect_value; + itembonuses.DEX = effect_value; + break; + + case SE_AGI: + itembonuses.AGI = effect_value; + aabonuses.AGI = effect_value; + spellbonuses.AGI = effect_value; + break; + + case SE_STA: + spellbonuses.STA = effect_value; + itembonuses.STA = effect_value; + aabonuses.STA = effect_value; + break; + + case SE_INT: + spellbonuses.INT = effect_value; + aabonuses.INT = effect_value; + itembonuses.INT = effect_value; + break; + + case SE_WIS: + spellbonuses.WIS = effect_value; + aabonuses.WIS = effect_value; + itembonuses.WIS = effect_value; + break; + + case SE_CHA: + itembonuses.CHA = effect_value; + spellbonuses.CHA = effect_value; + aabonuses.CHA = effect_value; + break; + + case SE_AllStats: + { + spellbonuses.STR = effect_value; + spellbonuses.DEX = effect_value; + spellbonuses.AGI = effect_value; + spellbonuses.STA = effect_value; + spellbonuses.INT = effect_value; + spellbonuses.WIS = effect_value; + spellbonuses.CHA = effect_value; + + itembonuses.STR = effect_value; + itembonuses.DEX = effect_value; + itembonuses.AGI = effect_value; + itembonuses.STA = effect_value; + itembonuses.INT = effect_value; + itembonuses.WIS = effect_value; + itembonuses.CHA = effect_value; + + aabonuses.STR = effect_value; + aabonuses.DEX = effect_value; + aabonuses.AGI = effect_value; + aabonuses.STA = effect_value; + aabonuses.INT = effect_value; + aabonuses.WIS = effect_value; + aabonuses.CHA = effect_value; + break; + } + + case SE_ResistFire: + spellbonuses.FR = effect_value; + itembonuses.FR = effect_value; + aabonuses.FR = effect_value; + break; + + case SE_ResistCold: + spellbonuses.CR = effect_value; + aabonuses.CR = effect_value; + itembonuses.CR = effect_value; + break; + + case SE_ResistPoison: + spellbonuses.PR = effect_value; + aabonuses.PR = effect_value; + itembonuses.PR = effect_value; + break; + + case SE_ResistDisease: + spellbonuses.DR = effect_value; + itembonuses.DR = effect_value; + aabonuses.DR = effect_value; + break; + + case SE_ResistMagic: + spellbonuses.MR = effect_value; + aabonuses.MR = effect_value; + itembonuses.MR = effect_value; + break; + + case SE_ResistAll: + { + spellbonuses.MR = effect_value; + spellbonuses.DR = effect_value; + spellbonuses.PR = effect_value; + spellbonuses.CR = effect_value; + spellbonuses.FR = effect_value; + + aabonuses.MR = effect_value; + aabonuses.DR = effect_value; + aabonuses.PR = effect_value; + aabonuses.CR = effect_value; + aabonuses.FR = effect_value; + + itembonuses.MR = effect_value; + itembonuses.DR = effect_value; + itembonuses.PR = effect_value; + itembonuses.CR = effect_value; + itembonuses.FR = effect_value; + break; + } + + case SE_ResistCorruption: + spellbonuses.Corrup = effect_value; + itembonuses.Corrup = effect_value; + aabonuses.Corrup = effect_value; + break; + + case SE_CastingLevel2: + case SE_CastingLevel: // Brilliance of Ro + spellbonuses.effective_casting_level = effect_value; + aabonuses.effective_casting_level = effect_value; + itembonuses.effective_casting_level = effect_value; + break; + + + case SE_MovementSpeed: + spellbonuses.movementspeed = effect_value; + aabonuses.movementspeed = effect_value; + itembonuses.movementspeed = effect_value; + break; + + case SE_SpellDamageShield: + spellbonuses.SpellDamageShield = effect_value; + aabonuses.SpellDamageShield = effect_value; + itembonuses.SpellDamageShield = effect_value; + break; + + case SE_DamageShield: + spellbonuses.DamageShield = effect_value; + aabonuses.DamageShield = effect_value; + itembonuses.DamageShield = effect_value; + break; + + case SE_ReverseDS: + spellbonuses.ReverseDamageShield = effect_value; + aabonuses.ReverseDamageShield = effect_value; + itembonuses.ReverseDamageShield = effect_value; + break; + + case SE_Reflect: + spellbonuses.reflect_chance = effect_value; + aabonuses.reflect_chance = effect_value; + itembonuses.reflect_chance = effect_value; + break; + + case SE_Amplification: + spellbonuses.Amplification = effect_value; + itembonuses.Amplification = effect_value; + aabonuses.Amplification = effect_value; + break; + + case SE_ChangeAggro: + spellbonuses.hatemod = effect_value; + itembonuses.hatemod = effect_value; + aabonuses.hatemod = effect_value; + break; + + case SE_MeleeMitigation: + spellbonuses.MeleeMitigation = effect_value; + itembonuses.MeleeMitigation = effect_value; + aabonuses.MeleeMitigation = effect_value; + break; + + case SE_CriticalHitChance: + { + for(int e = 0; e < HIGHEST_SKILL+1; e++) + { + spellbonuses.CriticalHitChance[e] = effect_value; + aabonuses.CriticalHitChance[e] = effect_value; + itembonuses.CriticalHitChance[e] = effect_value; + } + } + + case SE_CrippBlowChance: + spellbonuses.CrippBlowChance = effect_value; + aabonuses.CrippBlowChance = effect_value; + itembonuses.CrippBlowChance = effect_value; + break; + + case SE_AvoidMeleeChance: + spellbonuses.AvoidMeleeChance = effect_value; + aabonuses.AvoidMeleeChance = effect_value; + itembonuses.AvoidMeleeChance = effect_value; + break; + + case SE_RiposteChance: + spellbonuses.RiposteChance = effect_value; + aabonuses.RiposteChance = effect_value; + itembonuses.RiposteChance = effect_value; + break; + + case SE_DodgeChance: + spellbonuses.DodgeChance = effect_value; + aabonuses.DodgeChance = effect_value; + itembonuses.DodgeChance = effect_value; + break; + + case SE_ParryChance: + spellbonuses.ParryChance = effect_value; + aabonuses.ParryChance = effect_value; + itembonuses.ParryChance = effect_value; + break; + + case SE_DualWieldChance: + spellbonuses.DualWieldChance = effect_value; + aabonuses.DualWieldChance = effect_value; + itembonuses.DualWieldChance = effect_value; + break; + + case SE_DoubleAttackChance: + spellbonuses.DoubleAttackChance = effect_value; + aabonuses.DoubleAttackChance = effect_value; + itembonuses.DoubleAttackChance = effect_value; + break; + + case SE_TripleAttackChance: + spellbonuses.TripleAttackChance = effect_value; + aabonuses.TripleAttackChance = effect_value; + itembonuses.TripleAttackChance = effect_value; + break; + + case SE_MeleeLifetap: + spellbonuses.MeleeLifetap = effect_value; + aabonuses.MeleeLifetap = effect_value; + itembonuses.MeleeLifetap = effect_value; + break; + + case SE_AllInstrumentMod: + { + spellbonuses.singingMod = effect_value; + spellbonuses.brassMod = effect_value; + spellbonuses.percussionMod = effect_value; + spellbonuses.windMod = effect_value; + spellbonuses.stringedMod = effect_value; + + itembonuses.singingMod = effect_value; + itembonuses.brassMod = effect_value; + itembonuses.percussionMod = effect_value; + itembonuses.windMod = effect_value; + itembonuses.stringedMod = effect_value; + + aabonuses.singingMod = effect_value; + aabonuses.brassMod = effect_value; + aabonuses.percussionMod = effect_value; + aabonuses.windMod = effect_value; + aabonuses.stringedMod = effect_value; + break; + } + + case SE_ResistSpellChance: + spellbonuses.ResistSpellChance = effect_value; + aabonuses.ResistSpellChance = effect_value; + itembonuses.ResistSpellChance = effect_value; + break; + + case SE_ResistFearChance: + spellbonuses.Fearless = false; + spellbonuses.ResistFearChance = effect_value; + aabonuses.ResistFearChance = effect_value; + itembonuses.ResistFearChance = effect_value; + break; + + case SE_Fearless: + spellbonuses.Fearless = false; + aabonuses.Fearless = false; + itembonuses.Fearless = false; + break; + + case SE_HundredHands: + spellbonuses.HundredHands = effect_value; + aabonuses.HundredHands = effect_value; + itembonuses.HundredHands = effect_value; + break; + + case SE_MeleeSkillCheck: + { + spellbonuses.MeleeSkillCheck = effect_value; + spellbonuses.MeleeSkillCheckSkill = effect_value; + break; + } + + case SE_HitChance: + { + for(int e = 0; e < HIGHEST_SKILL+1; e++) + { + spellbonuses.HitChanceEffect[e] = effect_value; + aabonuses.HitChanceEffect[e] = effect_value; + itembonuses.HitChanceEffect[e] = effect_value; + } + break; + } + + case SE_DamageModifier: + { + for(int e = 0; e < HIGHEST_SKILL+1; e++) + { + spellbonuses.DamageModifier[e] = effect_value; + aabonuses.DamageModifier[e] = effect_value; + itembonuses.DamageModifier[e] = effect_value; + } + break; + } + + case SE_DamageModifier2: + { + for(int e = 0; e < HIGHEST_SKILL+1; e++) + { + spellbonuses.DamageModifier2[e] = effect_value; + aabonuses.DamageModifier2[e] = effect_value; + itembonuses.DamageModifier2[e] = effect_value; + } + break; + } + + case SE_MinDamageModifier: + { + for(int e = 0; e < HIGHEST_SKILL+1; e++) + { + spellbonuses.MinDamageModifier[e] = effect_value; + aabonuses.MinDamageModifier[e] = effect_value; + itembonuses.MinDamageModifier[e] = effect_value; + } + break; + } + + case SE_StunResist: + spellbonuses.StunResist = effect_value; + aabonuses.StunResist = effect_value; + itembonuses.StunResist = effect_value; + break; + + case SE_ProcChance: + spellbonuses.ProcChanceSPA = effect_value; + aabonuses.ProcChanceSPA = effect_value; + itembonuses.ProcChanceSPA = effect_value; + break; + + case SE_ExtraAttackChance: + spellbonuses.ExtraAttackChance = effect_value; + aabonuses.ExtraAttackChance = effect_value; + itembonuses.ExtraAttackChance = effect_value; + break; + + case SE_PercentXPIncrease: + spellbonuses.XPRateMod = effect_value; + aabonuses.XPRateMod = effect_value; + itembonuses.XPRateMod = effect_value; + break; + + case SE_Flurry: + spellbonuses.FlurryChance = effect_value; + aabonuses.FlurryChance = effect_value; + itembonuses.FlurryChance = effect_value; + break; + + case SE_Accuracy: + { + spellbonuses.Accuracy[HIGHEST_SKILL+1] = effect_value; + itembonuses.Accuracy[HIGHEST_SKILL+1] = effect_value; + + for(int e = 0; e < HIGHEST_SKILL+1; e++) + { + aabonuses.Accuracy[e] = effect_value; + } + break; + } + + case SE_MaxHPChange: + spellbonuses.MaxHPChange = effect_value; + aabonuses.MaxHPChange = effect_value; + itembonuses.MaxHPChange = effect_value; + break; + + case SE_EndurancePool: + spellbonuses.Endurance = effect_value; + aabonuses.Endurance = effect_value; + itembonuses.Endurance = effect_value; + break; + + case SE_HealRate: + spellbonuses.HealRate = effect_value; + aabonuses.HealRate = effect_value; + itembonuses.HealRate = effect_value; + break; + + case SE_SkillDamageTaken: + { + for(int e = 0; e < HIGHEST_SKILL+1; e++) + { + spellbonuses.SkillDmgTaken[e] = effect_value; + aabonuses.SkillDmgTaken[e] = effect_value; + itembonuses.SkillDmgTaken[e] = effect_value; + + } + break; + } + + case SE_TriggerOnCast: + { + for(int e = 0; e < MAX_SPELL_TRIGGER; e++) + { + spellbonuses.SpellTriggers[e] = effect_value; + aabonuses.SpellTriggers[e] = effect_value; + itembonuses.SpellTriggers[e] = effect_value; + } + break; + } + + case SE_SpellCritChance: + spellbonuses.CriticalSpellChance = effect_value; + aabonuses.CriticalSpellChance = effect_value; + itembonuses.CriticalSpellChance = effect_value; + break; + + case SE_CriticalSpellChance: + spellbonuses.CriticalSpellChance = effect_value; + spellbonuses.SpellCritDmgIncrease = effect_value; + aabonuses.CriticalSpellChance = effect_value; + aabonuses.SpellCritDmgIncrease = effect_value; + itembonuses.CriticalSpellChance = effect_value; + itembonuses.SpellCritDmgIncrease = effect_value; + break; + + case SE_SpellCritDmgIncrease: + spellbonuses.SpellCritDmgIncrease = effect_value; + aabonuses.SpellCritDmgIncrease = effect_value; + itembonuses.SpellCritDmgIncrease = effect_value; + break; + + case SE_DotCritDmgIncrease: + spellbonuses.DotCritDmgIncrease = effect_value; + aabonuses.DotCritDmgIncrease = effect_value; + itembonuses.DotCritDmgIncrease = effect_value; + break; + + case SE_CriticalHealChance: + spellbonuses.CriticalHealChance = effect_value; + aabonuses.CriticalHealChance = effect_value; + itembonuses.CriticalHealChance = effect_value; + break; + + case SE_CriticalHealOverTime: + spellbonuses.CriticalHealOverTime = effect_value; + aabonuses.CriticalHealOverTime = effect_value; + itembonuses.CriticalHealOverTime = effect_value; + break; + + case SE_MitigateDamageShield: + spellbonuses.DSMitigationOffHand = effect_value; + itembonuses.DSMitigationOffHand = effect_value; + aabonuses.DSMitigationOffHand = effect_value; + break; + + case SE_CriticalDoTChance: + spellbonuses.CriticalDoTChance = effect_value; + aabonuses.CriticalDoTChance = effect_value; + itembonuses.CriticalDoTChance = effect_value; + break; + + case SE_ProcOnKillShot: + { + for(int e = 0; e < MAX_SPELL_TRIGGER*3; e=3) + { + spellbonuses.SpellOnKill[e] = effect_value; + spellbonuses.SpellOnKill[e+1] = effect_value; + spellbonuses.SpellOnKill[e+2] = effect_value; + + aabonuses.SpellOnKill[e] = effect_value; + aabonuses.SpellOnKill[e+1] = effect_value; + aabonuses.SpellOnKill[e+2] = effect_value; + + itembonuses.SpellOnKill[e] = effect_value; + itembonuses.SpellOnKill[e+1] = effect_value; + itembonuses.SpellOnKill[e+2] = effect_value; + } + break; + } + + /* + case SE_SpellOnDeath: + { + for(int e = 0; e < MAX_SPELL_TRIGGER; e=2) + { + spellbonuses.SpellOnDeath[e] = SPELL_UNKNOWN; + spellbonuses.SpellOnDeath[e+1] = effect_value; + } + break; + } + */ + + case SE_CriticalDamageMob: + { + for(int e = 0; e < HIGHEST_SKILL+1; e++) + { + spellbonuses.CritDmgMob[e] = effect_value; + aabonuses.CritDmgMob[e] = effect_value; + itembonuses.CritDmgMob[e] = effect_value; + } + break; + } + + case SE_SkillDamageAmount: + { + for(int e = 0; e < HIGHEST_SKILL+1; e++) + { + spellbonuses.SkillDamageAmount[e] = effect_value; + aabonuses.SkillDamageAmount[e] = effect_value; + itembonuses.SkillDamageAmount[e] = effect_value; + } + break; + } + + case SE_IncreaseBlockChance: + spellbonuses.IncreaseBlockChance = effect_value; + aabonuses.IncreaseBlockChance = effect_value; + itembonuses.IncreaseBlockChance = effect_value; + break; + + case SE_PersistantCasting: + spellbonuses.PersistantCasting = effect_value; + itembonuses.PersistantCasting = effect_value; + aabonuses.PersistantCasting = effect_value; + break; + + case SE_ImmuneFleeing: + spellbonuses.ImmuneToFlee = false; + break; + + case SE_DelayDeath: + spellbonuses.DelayDeath = effect_value; + aabonuses.DelayDeath = effect_value; + itembonuses.DelayDeath = effect_value; + break; + + case SE_SpellProcChance: + spellbonuses.SpellProcChance = effect_value; + itembonuses.SpellProcChance = effect_value; + aabonuses.SpellProcChance = effect_value; + break; + + case SE_CharmBreakChance: + spellbonuses.CharmBreakChance = effect_value; + aabonuses.CharmBreakChance = effect_value; + itembonuses.CharmBreakChance = effect_value; + break; + + case SE_BardSongRange: + spellbonuses.SongRange = effect_value; + aabonuses.SongRange = effect_value; + itembonuses.SongRange = effect_value; + break; + + case SE_SkillDamageAmount2: + { + for(int e = 0; e < HIGHEST_SKILL+1; e++) + { + spellbonuses.SkillDamageAmount2[e] = effect_value; + aabonuses.SkillDamageAmount2[e] = effect_value; + itembonuses.SkillDamageAmount2[e] = effect_value; + } + break; + } + + case SE_NegateAttacks: + spellbonuses.NegateAttacks[0] = effect_value; + spellbonuses.NegateAttacks[1] = effect_value; + break; + + case SE_MitigateMeleeDamage: + spellbonuses.MitigateMeleeRune[0] = effect_value; + spellbonuses.MitigateMeleeRune[1] = -1; + break; + + case SE_MeleeThresholdGuard: + spellbonuses.MeleeThresholdGuard[0] = effect_value; + spellbonuses.MeleeThresholdGuard[1] = -1; + spellbonuses.MeleeThresholdGuard[1] = effect_value; + break; + + case SE_SpellThresholdGuard: + spellbonuses.SpellThresholdGuard[0] = effect_value; + spellbonuses.SpellThresholdGuard[1] = -1; + spellbonuses.SpellThresholdGuard[1] = effect_value; + break; + + case SE_MitigateSpellDamage: + spellbonuses.MitigateSpellRune[0] = effect_value; + spellbonuses.MitigateSpellRune[1] = -1; + break; + + case SE_MitigateDotDamage: + spellbonuses.MitigateDotRune[0] = effect_value; + spellbonuses.MitigateDotRune[1] = -1; + break; + + case SE_ManaAbsorbPercentDamage: + spellbonuses.ManaAbsorbPercentDamage[0] = effect_value; + spellbonuses.ManaAbsorbPercentDamage[1] = -1; + break; + + case SE_ShieldBlock: + spellbonuses.ShieldBlock = effect_value; + aabonuses.ShieldBlock = effect_value; + itembonuses.ShieldBlock = effect_value; + + case SE_BlockBehind: + spellbonuses.BlockBehind = effect_value; + aabonuses.BlockBehind = effect_value; + itembonuses.BlockBehind = effect_value; + break; + + case SE_Fear: + spellbonuses.IsFeared = false; + break; + + case SE_FrontalStunResist: + spellbonuses.FrontalStunResist = effect_value; + aabonuses.FrontalStunResist = effect_value; + itembonuses.FrontalStunResist = effect_value; + break; + + case SE_ImprovedBindWound: + aabonuses.BindWound = effect_value; + itembonuses.BindWound = effect_value; + spellbonuses.BindWound = effect_value; + break; + + case SE_MaxBindWound: + spellbonuses.MaxBindWound = effect_value; + aabonuses.MaxBindWound = effect_value; + itembonuses.MaxBindWound = effect_value; + break; + + case SE_BaseMovementSpeed: + spellbonuses.BaseMovementSpeed = effect_value; + aabonuses.BaseMovementSpeed = effect_value; + itembonuses.BaseMovementSpeed = effect_value; + break; + + case SE_IncreaseRunSpeedCap: + itembonuses.IncreaseRunSpeedCap = effect_value; + aabonuses.IncreaseRunSpeedCap = effect_value; + spellbonuses.IncreaseRunSpeedCap = effect_value; + break; + + case SE_DoubleSpecialAttack: + spellbonuses.DoubleSpecialAttack = effect_value; + aabonuses.DoubleSpecialAttack = effect_value; + itembonuses.DoubleSpecialAttack = effect_value; + break; + + case SE_TripleBackstab: + spellbonuses.TripleBackstab = effect_value; + aabonuses.TripleBackstab = effect_value; + itembonuses.TripleBackstab = effect_value; + break; + + case SE_FrontalBackstabMinDmg: + spellbonuses.FrontalBackstabMinDmg = false; + break; + + case SE_FrontalBackstabChance: + spellbonuses.FrontalBackstabChance = effect_value; + aabonuses.FrontalBackstabChance = effect_value; + itembonuses.FrontalBackstabChance = effect_value; + break; + + case SE_ConsumeProjectile: + spellbonuses.ConsumeProjectile = effect_value; + aabonuses.ConsumeProjectile = effect_value; + itembonuses.ConsumeProjectile = effect_value; + break; + + case SE_ForageAdditionalItems: + spellbonuses.ForageAdditionalItems = effect_value; + aabonuses.ForageAdditionalItems = effect_value; + itembonuses.ForageAdditionalItems = effect_value; + break; + + case SE_Salvage: + spellbonuses.SalvageChance = effect_value; + aabonuses.SalvageChance = effect_value; + itembonuses.SalvageChance = effect_value; + break; + + case SE_ArcheryDamageModifier: + spellbonuses.ArcheryDamageModifier = effect_value; + aabonuses.ArcheryDamageModifier = effect_value; + itembonuses.ArcheryDamageModifier = effect_value; + break; + + case SE_SecondaryDmgInc: + spellbonuses.SecondaryDmgInc = false; + aabonuses.SecondaryDmgInc = false; + itembonuses.SecondaryDmgInc = false; + break; + + case SE_StrikeThrough: + spellbonuses.StrikeThrough = effect_value; + aabonuses.StrikeThrough = effect_value; + itembonuses.StrikeThrough = effect_value; + break; + + case SE_StrikeThrough2: + spellbonuses.StrikeThrough = effect_value; + aabonuses.StrikeThrough = effect_value; + itembonuses.StrikeThrough = effect_value; + break; + + case SE_GiveDoubleAttack: + spellbonuses.GiveDoubleAttack = effect_value; + aabonuses.GiveDoubleAttack = effect_value; + itembonuses.GiveDoubleAttack = effect_value; + break; + + case SE_PetCriticalHit: + spellbonuses.PetCriticalHit = effect_value; + aabonuses.PetCriticalHit = effect_value; + itembonuses.PetCriticalHit = effect_value; + break; + + case SE_CombatStability: + spellbonuses.CombatStability = effect_value; + aabonuses.CombatStability = effect_value; + itembonuses.CombatStability = effect_value; + break; + + case SE_PetAvoidance: + spellbonuses.PetAvoidance = effect_value; + aabonuses.PetAvoidance = effect_value; + itembonuses.PetAvoidance = effect_value; + break; + + case SE_Ambidexterity: + spellbonuses.Ambidexterity = effect_value; + aabonuses.Ambidexterity = effect_value; + itembonuses.Ambidexterity = effect_value; + break; + + case SE_PetMaxHP: + spellbonuses.PetMaxHP = effect_value; + aabonuses.PetMaxHP = effect_value; + itembonuses.PetMaxHP = effect_value; + break; + + case SE_PetFlurry: + spellbonuses.PetFlurry = effect_value; + aabonuses.PetFlurry = effect_value; + itembonuses.PetFlurry = effect_value; + break; + + case SE_GivePetGroupTarget: + spellbonuses.GivePetGroupTarget = false; + aabonuses.GivePetGroupTarget = false; + itembonuses.GivePetGroupTarget = false; + break; + + case SE_PetMeleeMitigation: + spellbonuses.PetMeleeMitigation = effect_value; + itembonuses.PetMeleeMitigation = effect_value; + aabonuses.PetMeleeMitigation = effect_value; + break; + + case SE_RootBreakChance: + spellbonuses.RootBreakChance = effect_value; + aabonuses.RootBreakChance = effect_value; + itembonuses.RootBreakChance = effect_value; + break; + + case SE_ChannelChanceItems: + spellbonuses.ChannelChanceItems = effect_value; + aabonuses.ChannelChanceItems = effect_value; + itembonuses.ChannelChanceItems = effect_value; + break; + + case SE_ChannelChanceSpells: + spellbonuses.ChannelChanceSpells = effect_value; + aabonuses.ChannelChanceSpells = effect_value; + itembonuses.ChannelChanceSpells = effect_value; + break; + + case SE_UnfailingDivinity: + spellbonuses.UnfailingDivinity = effect_value; + aabonuses.UnfailingDivinity = effect_value; + itembonuses.UnfailingDivinity = effect_value; + break; + + case SE_ItemHPRegenCapIncrease: + spellbonuses.ItemHPRegenCap = effect_value; + aabonuses.ItemHPRegenCap = effect_value; + itembonuses.ItemHPRegenCap = effect_value; + break; + + case SE_OffhandRiposteFail: + spellbonuses.OffhandRiposteFail = effect_value; + aabonuses.OffhandRiposteFail = effect_value; + itembonuses.OffhandRiposteFail = effect_value; + break; + + case SE_ItemAttackCapIncrease: + aabonuses.ItemATKCap = effect_value; + itembonuses.ItemATKCap = effect_value; + spellbonuses.ItemATKCap = effect_value; + break; + + case SE_SpellEffectResistChance: + { + for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) + { + spellbonuses.SEResist[e] = effect_value; + spellbonuses.SEResist[e+1] = effect_value; + } + break; + } + + case SE_MasteryofPast: + spellbonuses.MasteryofPast = effect_value; + aabonuses.MasteryofPast = effect_value; + itembonuses.MasteryofPast = effect_value; + break; + + case SE_DoubleRiposte: + spellbonuses.DoubleRiposte = effect_value; + itembonuses.DoubleRiposte = effect_value; + aabonuses.DoubleRiposte = effect_value; + break; + + case SE_GiveDoubleRiposte: + spellbonuses.GiveDoubleRiposte[0] = effect_value; + itembonuses.GiveDoubleRiposte[0] = effect_value; + aabonuses.GiveDoubleRiposte[0] = effect_value; + break; + + case SE_SlayUndead: + spellbonuses.SlayUndead[0] = effect_value; + spellbonuses.SlayUndead[1] = effect_value; + itembonuses.SlayUndead[0] = effect_value; + itembonuses.SlayUndead[1] = effect_value; + aabonuses.SlayUndead[0] = effect_value; + aabonuses.SlayUndead[1] = effect_value; + break; + + case SE_DoubleRangedAttack: + spellbonuses.DoubleRangedAttack = effect_value; + aabonuses.DoubleRangedAttack = effect_value; + itembonuses.DoubleRangedAttack = effect_value; + break; + + case SE_ShieldEquipHateMod: + spellbonuses.ShieldEquipHateMod = effect_value; + aabonuses.ShieldEquipHateMod = effect_value; + itembonuses.ShieldEquipHateMod = effect_value; + break; + + case SE_ShieldEquipDmgMod: + spellbonuses.ShieldEquipDmgMod[0] = effect_value; + spellbonuses.ShieldEquipDmgMod[1] = effect_value; + aabonuses.ShieldEquipDmgMod[0] = effect_value; + aabonuses.ShieldEquipDmgMod[1] = effect_value; + itembonuses.ShieldEquipDmgMod[0] = effect_value; + itembonuses.ShieldEquipDmgMod[1] = effect_value; + break; + + case SE_TriggerMeleeThreshold: + spellbonuses.TriggerMeleeThreshold[0] = effect_value; + spellbonuses.TriggerMeleeThreshold[1] = effect_value; + spellbonuses.TriggerMeleeThreshold[2] = effect_value; + break; + + case SE_TriggerSpellThreshold: + spellbonuses.TriggerSpellThreshold[0] = effect_value; + spellbonuses.TriggerSpellThreshold[1] = effect_value; + spellbonuses.TriggerSpellThreshold[2] = effect_value; + break; + + case SE_DivineAura: + spellbonuses.DivineAura = false; + break; + + case SE_StunBashChance: + spellbonuses.StunBashChance = effect_value; + itembonuses.StunBashChance = effect_value; + aabonuses.StunBashChance = effect_value; + break; + + case SE_IncreaseChanceMemwipe: + spellbonuses.IncreaseChanceMemwipe = effect_value; + itembonuses.IncreaseChanceMemwipe = effect_value; + aabonuses.IncreaseChanceMemwipe = effect_value; + break; + + case SE_CriticalMend: + spellbonuses.CriticalMend = effect_value; + itembonuses.CriticalMend = effect_value; + aabonuses.CriticalMend = effect_value; + break; + + case SE_DistanceRemoval: + spellbonuses.DistanceRemoval = effect_value; + break; + + case SE_ImprovedTaunt: + spellbonuses.ImprovedTaunt[0] = effect_value; + spellbonuses.ImprovedTaunt[1] = effect_value; + spellbonuses.ImprovedTaunt[2] = -1; + break; + + case SE_FrenziedDevastation: + spellbonuses.FrenziedDevastation = effect_value; + aabonuses.FrenziedDevastation = effect_value; + itembonuses.FrenziedDevastation = effect_value; + break; + + case SE_Root: + spellbonuses.Root[0] = effect_value; + spellbonuses.Root[1] = -1; + break; + + case SE_Rune: + spellbonuses.MeleeRune[0] = effect_value; + spellbonuses.MeleeRune[1] = -1; + break; + + case SE_AbsorbMagicAtt: + spellbonuses.AbsorbMagicAtt[0] = effect_value; + spellbonuses.AbsorbMagicAtt[1] = -1; + break; + + case SE_Berserk: + spellbonuses.BerserkSPA = false; + aabonuses.BerserkSPA = false; + itembonuses.BerserkSPA = false; + break; + + case SE_Vampirism: + spellbonuses.Vampirism = effect_value; + aabonuses.Vampirism = effect_value; + itembonuses.Vampirism = effect_value; + break; + + case SE_Metabolism: + spellbonuses.Metabolism = effect_value; + aabonuses.Metabolism = effect_value; + itembonuses.Metabolism = effect_value; + break; + + case SE_ImprovedReclaimEnergy: + spellbonuses.ImprovedReclaimEnergy = effect_value; + aabonuses.ImprovedReclaimEnergy = effect_value; + itembonuses.ImprovedReclaimEnergy = effect_value; + break; + + case SE_HeadShot: + spellbonuses.HeadShot[0] = effect_value; + aabonuses.HeadShot[0] = effect_value; + itembonuses.HeadShot[0] = effect_value; + spellbonuses.HeadShot[1] = effect_value; + aabonuses.HeadShot[1] = effect_value; + itembonuses.HeadShot[1] = effect_value; + break; + + case SE_HeadShotLevel: + spellbonuses.HSLevel = effect_value; + aabonuses.HSLevel = effect_value; + itembonuses.HSLevel = effect_value; + break; + + case SE_Assassinate: + spellbonuses.Assassinate[0] = effect_value; + aabonuses.Assassinate[0] = effect_value; + itembonuses.Assassinate[0] = effect_value; + spellbonuses.Assassinate[1] = effect_value; + aabonuses.Assassinate[1] = effect_value; + itembonuses.Assassinate[1] = effect_value; + break; + + case SE_AssassinateLevel: + spellbonuses.AssassinateLevel = effect_value; + aabonuses.AssassinateLevel = effect_value; + itembonuses.AssassinateLevel = effect_value; + break; + + case SE_FinishingBlow: + spellbonuses.FinishingBlow[0] = effect_value; + aabonuses.FinishingBlow[0] = effect_value; + itembonuses.FinishingBlow[0] = effect_value; + spellbonuses.FinishingBlow[1] = effect_value; + aabonuses.FinishingBlow[1] = effect_value; + itembonuses.FinishingBlow[1] = effect_value; + break; + + case SE_FinishingBlowLvl: + spellbonuses.FinishingBlowLvl[0] = effect_value; + aabonuses.FinishingBlowLvl[0] = effect_value; + itembonuses.FinishingBlowLvl[0] = effect_value; + spellbonuses.FinishingBlowLvl[1] = effect_value; + aabonuses.FinishingBlowLvl[1] = effect_value; + itembonuses.FinishingBlowLvl[1] = effect_value; + break; + + } + } + } +} + diff --git a/zone/groupsx.cpp b/zone/groupsx.cpp new file mode 100644 index 000000000..6aee5f38b --- /dev/null +++ b/zone/groupsx.cpp @@ -0,0 +1,2194 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "../common/debug.h" +#include "masterentity.h" +#include "NpcAI.h" +#include "../common/packet_functions.h" +#include "../common/packet_dump.h" +#include "../common/StringUtil.h" +#include "worldserver.h" +extern EntityList entity_list; +extern WorldServer worldserver; + +// +// Xorlac: This will need proper synchronization to make it work correctly. +// Also, should investigate client ack for packet to ensure proper synch. +// + +/* + +note about how groups work: +A group contains 2 list, a list of pointers to members and a +list of member names. All members of a group should have their +name in the membername array, wether they are in the zone or not. +Only members in this zone will have non-null pointers in the +members array. + +*/ + +//create a group which should allready exist in the database +Group::Group(uint32 gid) +: GroupIDConsumer(gid) +{ + leader = nullptr; + memset(members,0,sizeof(Mob*) * MAX_GROUP_MEMBERS); + AssistTargetID = 0; + TankTargetID = 0; + PullerTargetID = 0; + + memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct)); + uint32 i; + for(i=0;iSetGrouped(true); + SetLeader(leader); + AssistTargetID = 0; + TankTargetID = 0; + PullerTargetID = 0; + memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct)); + uint32 i; + for(i=0;iGetName()); + + if(leader->IsClient()) + strcpy(leader->CastToClient()->GetPP().groupMembers[0],leader->GetName()); + + for(int i = 0; i < MAX_MARKED_NPCS; ++i) + MarkedNPCs[i] = 0; + + NPCMarkerID = 0; +} + +Group::~Group() +{ + for(int i = 0; i < MAX_MARKED_NPCS; ++i) + if(MarkedNPCs[i]) + { + Mob* m = entity_list.GetMob(MarkedNPCs[i]); + if(m) + m->IsTargeted(-1); + } +} + +//Cofruben:Split money used in OP_Split. +//Rewritten by Father Nitwit +void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter) { + //avoid unneeded work + if(copper == 0 && silver == 0 && gold == 0 && platinum == 0) + return; + + uint32 i; + uint8 membercount = 0; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] != nullptr) { + membercount++; + } + } + + if (membercount == 0) + return; + + uint32 mod; + //try to handle round off error a little better + if(membercount > 1) { + mod = platinum % membercount; + if((mod) > 0) { + platinum -= mod; + gold += 10 * mod; + } + mod = gold % membercount; + if((mod) > 0) { + gold -= mod; + silver += 10 * mod; + } + mod = silver % membercount; + if((mod) > 0) { + silver -= mod; + copper += 10 * mod; + } + } + + //calculate the splits + //We can still round off copper pieces, but I dont care + uint32 sc; + uint32 cpsplit = copper / membercount; + sc = copper % membercount; + uint32 spsplit = silver / membercount; + uint32 gpsplit = gold / membercount; + uint32 ppsplit = platinum / membercount; + + char buf[128]; + buf[63] = '\0'; + std::string msg = "You receive"; + bool one = false; + + if(ppsplit > 0) { + snprintf(buf, 63, " %u platinum", ppsplit); + msg += buf; + one = true; + } + if(gpsplit > 0) { + if(one) + msg += ","; + snprintf(buf, 63, " %u gold", gpsplit); + msg += buf; + one = true; + } + if(spsplit > 0) { + if(one) + msg += ","; + snprintf(buf, 63, " %u silver", spsplit); + msg += buf; + one = true; + } + if(cpsplit > 0) { + if(one) + msg += ","; + //this message is not 100% accurate for the splitter + //if they are receiving any roundoff + snprintf(buf, 63, " %u copper", cpsplit); + msg += buf; + one = true; + } + msg += " as your split"; + + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] != nullptr && members[i]->IsClient()) { // If Group Member is Client + Client *c = members[i]->CastToClient(); + //I could not get MoneyOnCorpse to work, so we use this + c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true); + + c->Message(2, msg.c_str()); + } + } +} + +bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 CharacterID) +{ + bool InZone = true; + bool ismerc = false; + + // This method should either be passed a Mob*, if the new member is in this zone, or a nullptr Mob* + // and the name and CharacterID of the new member, if they are out of zone. + // + if(!newmember && !NewMemberName) + return false; + + if(GroupCount() >= MAX_GROUP_MEMBERS) //Sanity check for merging groups together. + return false; + + if(!newmember) + InZone = false; + else + { + NewMemberName = newmember->GetCleanName(); + + if(newmember->IsClient()) + CharacterID = newmember->CastToClient()->CharacterID(); + if(newmember->IsMerc()) + { + Client* owner = newmember->CastToMerc()->GetMercOwner(); + if(owner) + { + CharacterID = owner->CastToClient()->CharacterID(); + NewMemberName = newmember->GetName(); + ismerc = true; + } + } + } + + uint32 i = 0; + + // See if they are already in the group + // + for (i = 0; i < MAX_GROUP_MEMBERS; ++i) + if(!strcasecmp(membername[i], NewMemberName)) + return false; + + // Put them in the group + for (i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if (membername[i][0] == '\0') + { + if(InZone) + members[i] = newmember; + + break; + } + } + + if (i == MAX_GROUP_MEMBERS) + return false; + + strcpy(membername[i], NewMemberName); + MemberRoles[i] = 0; + + int x=1; + + //build the template join packet + EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); + GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer; + strcpy(gj->membername, NewMemberName); + gj->action = groupActJoin; + + gj->leader_aas = LeaderAbilities; + + for (i = 0;i < MAX_GROUP_MEMBERS; i++) { + if (members[i] != nullptr && members[i] != newmember) { + //fill in group join & send it + if(members[i]->IsMerc()) + { + strcpy(gj->yourname, members[i]->GetName()); + } + else + { + strcpy(gj->yourname, members[i]->GetCleanName()); + } + if(members[i]->IsClient()) { + members[i]->CastToClient()->QueuePacket(outapp); + + //put new member into existing person's list + strcpy(members[i]->CastToClient()->GetPP().groupMembers[this->GroupCount()-1], NewMemberName); + } + + //put this existing person into the new member's list + if(InZone && newmember->IsClient()) { + if(IsLeader(members[i])) + strcpy(newmember->CastToClient()->GetPP().groupMembers[0], members[i]->GetCleanName()); + else { + strcpy(newmember->CastToClient()->GetPP().groupMembers[x], members[i]->GetCleanName()); + x++; + } + } + } + } + + if(InZone) + { + //put new member in his own list. + newmember->SetGrouped(true); + + if(newmember->IsClient()) + { + strcpy(newmember->CastToClient()->GetPP().groupMembers[x], NewMemberName); + newmember->CastToClient()->Save(); + database.SetGroupID(NewMemberName, GetID(), newmember->CastToClient()->CharacterID(), false); + SendMarkedNPCsToMember(newmember->CastToClient()); + + NotifyMainTank(newmember->CastToClient(), 1); + NotifyMainAssist(newmember->CastToClient(), 1); + NotifyPuller(newmember->CastToClient(), 1); + } + + if(newmember->IsMerc()) + { + Client* owner = newmember->CastToMerc()->GetMercOwner(); + if(owner) + { + database.SetGroupID(newmember->GetName(), GetID(), owner->CharacterID(), true); + } + } +#ifdef BOTS + for (i = 0;i < MAX_GROUP_MEMBERS; i++) { + if (members[i] != nullptr && members[i]->IsBot()) { + members[i]->CastToBot()->CalcChanceToCast(); + } + } +#endif //BOTS + } + else + database.SetGroupID(NewMemberName, GetID(), CharacterID, ismerc); + + safe_delete(outapp); + + return true; +} + +void Group::AddMember(const char *NewMemberName) +{ + // This method should be called when both the new member and the group leader are in a different zone to this one. + // + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + if(!strcasecmp(membername[i], NewMemberName)) + { + return; + } + + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if (membername[i][0] == '\0') + { + strcpy(membername[i], NewMemberName); + MemberRoles[i] = 0; + break; + } + } +} + + +void Group::QueuePacket(const EQApplicationPacket *app, bool ack_req) +{ + uint32 i; + for(i = 0; i < MAX_GROUP_MEMBERS; i++) + if(members[i] && members[i]->IsClient()) + members[i]->CastToClient()->QueuePacket(app, ack_req); +} + +// solar: sends the rest of the group's hps to member. this is useful when +// someone first joins a group, but otherwise there shouldn't be a need to +// call it +void Group::SendHPPacketsTo(Mob *member) +{ + if(member && member->IsClient()) + { + EQApplicationPacket hpapp; + EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); + + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) + { + if(members[i] && members[i] != member) + { + members[i]->CreateHPPacket(&hpapp); + member->CastToClient()->QueuePacket(&hpapp, false); + if(member->CastToClient()->GetClientVersion() >= EQClientSoD) + { + outapp.SetOpcode(OP_MobManaUpdate); + MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; + mmus->spawn_id = members[i]->GetID(); + mmus->mana = members[i]->GetManaPercent(); + member->CastToClient()->QueuePacket(&outapp, false); + MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + outapp.SetOpcode(OP_MobEnduranceUpdate); + meus->endurance = members[i]->GetEndurancePercent(); + member->CastToClient()->QueuePacket(&outapp, false); + } + } + } + } +} + +void Group::SendHPPacketsFrom(Mob *member) +{ + EQApplicationPacket hp_app; + if(!member) + return; + + member->CreateHPPacket(&hp_app); + EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); + + uint32 i; + for(i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(members[i] && members[i] != member && members[i]->IsClient()) + { + members[i]->CastToClient()->QueuePacket(&hp_app); + if(members[i]->CastToClient()->GetClientVersion() >= EQClientSoD) + { + outapp.SetOpcode(OP_MobManaUpdate); + MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; + mmus->spawn_id = member->GetID(); + mmus->mana = member->GetManaPercent(); + members[i]->CastToClient()->QueuePacket(&outapp, false); + MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + outapp.SetOpcode(OP_MobEnduranceUpdate); + meus->endurance = member->GetEndurancePercent(); + members[i]->CastToClient()->QueuePacket(&outapp, false); + } + } + } +} + +//updates a group member's client pointer when they zone in +//if the group was in the zone allready +bool Group::UpdatePlayer(Mob* update){ + + VerifyGroup(); + + uint32 i=0; + if(update->IsClient()) { + //update their player profile + PlayerProfile_Struct &pp = update->CastToClient()->GetPP(); + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(membername[i][0] == '\0') + memset(pp.groupMembers[i], 0, 64); + else + strn0cpy(pp.groupMembers[i], membername[i], 64); + } + if(IsNPCMarker(update->CastToClient())) + { + NPCMarkerID = update->GetID(); + SendLeadershipAAUpdate(); + } + } + + for (i = 0; i < MAX_GROUP_MEMBERS; i++) + { + if (!strcasecmp(membername[i],update->GetName())) + { + members[i] = update; + members[i]->SetGrouped(true); + return true; + } + } + return false; +} + + +void Group::MemberZoned(Mob* removemob) { + uint32 i; + + if (removemob == nullptr) + return; + + if(removemob == GetLeader()) + SetLeader(nullptr); + + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] == removemob) { + members[i] = nullptr; + //should NOT clear the name, it is used for world communication. + break; + } +#ifdef BOTS + if (members[i] != nullptr && members[i]->IsBot()) { + members[i]->CastToBot()->CalcChanceToCast(); + } +#endif //BOTS + } + if(removemob->IsClient() && HasRole(removemob, RoleAssist)) + SetGroupAssistTarget(0); + + if(removemob->IsClient() && HasRole(removemob, RoleTank)) + SetGroupTankTarget(0); + + if(removemob->IsClient() && HasRole(removemob, RolePuller)) + SetGroupPullerTarget(0); +} + +bool Group::DelMemberOOZ(const char *Name) { + + if(!Name) return false; + + // If a member out of zone has disbanded, clear out their name. + // + for(unsigned int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(!strcasecmp(Name, membername[i])) + // This shouldn't be called if the member is in this zone. + if(!members[i]) { + if(!strncmp(GetLeaderName(), Name, 64)) + { + //TODO: Transfer leadership if leader disbands OOZ. + UpdateGroupAAs(); + } + + memset(membername[i], 0, 64); + MemberRoles[i] = 0; + if(GroupCount() < 3) + { + UnDelegateMarkNPC(NPCMarkerName.c_str()); + if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < EQClientSoD) { + UnDelegateMainAssist(MainAssistName.c_str()); + } + ClearAllNPCMarks(); + } + return true; + } + } + + return false; +} + +bool Group::DelMember(Mob* oldmember,bool ignoresender) +{ + if (oldmember == nullptr){ + return false; + } + + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] == oldmember) { + members[i] = nullptr; + membername[i][0] = '\0'; + memset(membername[i],0,64); + MemberRoles[i] = 0; + break; + } + } + + //handle leader quitting group gracefully + if (oldmember == GetLeader() && GroupCount() >= 2) { + for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) { + if(members[nl]) { + ChangeLeader(members[nl]); + break; + } + } + } + + ServerPacket* pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct)); + ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer; + gl->gid = GetID(); + gl->zoneid = zone->GetZoneID(); + gl->instance_id = zone->GetInstanceID(); + strcpy(gl->member_name, oldmember->GetName()); + worldserver.SendPacket(pack); + safe_delete(pack); + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); + GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer; + gu->action = groupActLeave; + strcpy(gu->membername, oldmember->GetCleanName()); + strcpy(gu->yourname, oldmember->GetCleanName()); + + gu->leader_aas = LeaderAbilities; + + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] == nullptr) { + //if (DEBUG>=5) LogFile->write(EQEMuLog::Debug, "Group::DelMember() null member at slot %i", i); + continue; + } + if (members[i] != oldmember) { + strcpy(gu->yourname, members[i]->GetCleanName()); + if(members[i]->IsClient()) + members[i]->CastToClient()->QueuePacket(outapp); + } +#ifdef BOTS + if (members[i] != nullptr && members[i]->IsBot()) { + members[i]->CastToBot()->CalcChanceToCast(); + } +#endif //BOTS + } + + if (!ignoresender) { + strcpy(gu->yourname,oldmember->GetCleanName()); + strcpy(gu->membername,oldmember->GetCleanName()); + gu->action = groupActLeave; + + if(oldmember->IsClient()) + oldmember->CastToClient()->QueuePacket(outapp); + } + + if(oldmember->IsClient()) + database.SetGroupID(oldmember->GetCleanName(), 0, oldmember->CastToClient()->CharacterID()); + + oldmember->SetGrouped(false); + disbandcheck = true; + + safe_delete(outapp); + + if(HasRole(oldmember, RoleTank)) + { + SetGroupTankTarget(0); + UnDelegateMainTank(oldmember->GetName()); + } + + if(HasRole(oldmember, RoleAssist)) + { + SetGroupAssistTarget(0); + UnDelegateMainAssist(oldmember->GetName()); + } + + if(HasRole(oldmember, RolePuller)) + { + SetGroupPullerTarget(0); + UnDelegatePuller(oldmember->GetName()); + } + + if(oldmember->IsClient()) + SendMarkedNPCsToMember(oldmember->CastToClient(), true); + + if(GroupCount() < 3) + { + UnDelegateMarkNPC(NPCMarkerName.c_str()); + if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < EQClientSoD) { + UnDelegateMainAssist(MainAssistName.c_str()); + } + ClearAllNPCMarks(); + } + + return true; +} + +// does the caster + group +void Group::CastGroupSpell(Mob* caster, uint16 spell_id) { + uint32 z; + float range, distance; + + if(!caster) + return; + + castspell = true; + range = caster->GetAOERange(spell_id); + + float range2 = range*range; + +// caster->SpellOnTarget(spell_id, caster); + + for(z=0; z < MAX_GROUP_MEMBERS; z++) + { + if(members[z] == caster) { + caster->SpellOnTarget(spell_id, caster); +#ifdef GROUP_BUFF_PETS + if(caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed()) + caster->SpellOnTarget(spell_id, caster->GetPet()); +#endif + } + else if(members[z] != nullptr) + { + distance = caster->DistNoRoot(*members[z]); + if(distance <= range2) { + caster->SpellOnTarget(spell_id, members[z]); +#ifdef GROUP_BUFF_PETS + if(members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed()) + caster->SpellOnTarget(spell_id, members[z]->GetPet()); +#endif + } else + _log(SPELLS__CASTING, "Group spell: %s is out of range %f at distance %f from %s", members[z]->GetName(), range, distance, caster->GetName()); + } + } + + castspell = false; + disbandcheck = true; +} + +// does the caster + group +void Group::GroupBardPulse(Mob* caster, uint16 spell_id) { + uint32 z; + float range, distance; + + if(!caster) + return; + + castspell = true; + range = caster->GetAOERange(spell_id); + + float range2 = range*range; + + for(z=0; z < MAX_GROUP_MEMBERS; z++) { + if(members[z] == caster) { + caster->BardPulse(spell_id, caster); +#ifdef GROUP_BUFF_PETS + if(caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed()) + caster->BardPulse(spell_id, caster->GetPet()); +#endif + } + else if(members[z] != nullptr) + { + distance = caster->DistNoRoot(*members[z]); + if(distance <= range2) { + members[z]->BardPulse(spell_id, caster); +#ifdef GROUP_BUFF_PETS + if(members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed()) + members[z]->GetPet()->BardPulse(spell_id, caster); +#endif + } else + _log(SPELLS__BARDS, "Group bard pulse: %s is out of range %f at distance %f from %s", members[z]->GetName(), range, distance, caster->GetName()); + } + } +} + +bool Group::IsGroupMember(Mob* client) +{ + bool Result = false; + + if(client) { + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] == client) + Result = true; + } + } + + return Result; +} + +bool Group::IsGroupMember(const char *Name) +{ + if(Name) + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) + if((strlen(Name) == strlen(membername[i])) && !strncmp(membername[i], Name, strlen(Name))) + return true; + + return false; +} + +void Group::GroupMessage(Mob* sender, uint8 language, uint8 lang_skill, const char* message) { + uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(!members[i]) + continue; + + if (members[i]->IsClient() && members[i]->CastToClient()->GetFilter(FilterGroupChat)!=0) + members[i]->CastToClient()->ChannelMessageSend(sender->GetName(),members[i]->GetName(),2,language,lang_skill,message); + } + + ServerPacket* pack = new ServerPacket(ServerOP_OOZGroupMessage, sizeof(ServerGroupChannelMessage_Struct) + strlen(message) + 1); + ServerGroupChannelMessage_Struct* gcm = (ServerGroupChannelMessage_Struct*)pack->pBuffer; + gcm->zoneid = zone->GetZoneID(); + gcm->groupid = GetID(); + gcm->instanceid = zone->GetInstanceID(); + strcpy(gcm->from, sender->GetName()); + strcpy(gcm->message, message); + worldserver.SendPacket(pack); + safe_delete(pack); +} + +uint32 Group::GetTotalGroupDamage(Mob* other) { + uint32 total = 0; + + uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(!members[i]) + continue; + if (other->CheckAggro(members[i])) + total += other->GetHateAmount(members[i],true); + } + return total; +} + +void Group::DisbandGroup() { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupUpdate_Struct)); + + GroupUpdate_Struct* gu = (GroupUpdate_Struct*) outapp->pBuffer; + gu->action = groupActDisband; + + Client *Leader = nullptr; + + uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] == nullptr) { + continue; + } + + if (members[i]->IsClient()) { + if(IsLeader(members[i])) + Leader = members[i]->CastToClient(); + + strcpy(gu->yourname, members[i]->GetName()); + database.SetGroupID(members[i]->GetName(), 0, members[i]->CastToClient()->CharacterID()); + members[i]->CastToClient()->QueuePacket(outapp); + SendMarkedNPCsToMember(members[i]->CastToClient(), true); + + } + + members[i]->SetGrouped(false); + members[i] = nullptr; + membername[i][0] = '\0'; + } + + ClearAllNPCMarks(); + + ServerPacket* pack = new ServerPacket(ServerOP_DisbandGroup, sizeof(ServerDisbandGroup_Struct)); + ServerDisbandGroup_Struct* dg = (ServerDisbandGroup_Struct*)pack->pBuffer; + dg->zoneid = zone->GetZoneID(); + dg->groupid = GetID(); + dg->instance_id = zone->GetInstanceID(); + worldserver.SendPacket(pack); + safe_delete(pack); + + entity_list.RemoveGroup(GetID()); + if(GetID() != 0) + database.ClearGroup(GetID()); + + if(Leader && (Leader->IsLFP())) { + Leader->UpdateLFP(); + } + + safe_delete(outapp); +} + +bool Group::Process() { + if(disbandcheck && !GroupCount()) + return false; + else if(disbandcheck && GroupCount()) + disbandcheck = false; + return true; +} + +void Group::SendUpdate(uint32 type, Mob* member) +{ + if(!member->IsClient()) + return; + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate2_Struct)); + GroupUpdate2_Struct* gu = (GroupUpdate2_Struct*)outapp->pBuffer; + gu->action = type; + strcpy(gu->yourname,member->GetName()); + + int x = 0; + + gu->leader_aas = LeaderAbilities; + + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + if((members[i] != nullptr) && IsLeader(members[i])) + { + strcpy(gu->leadersname, members[i]->GetName()); + break; + } + + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + if (members[i] != nullptr && members[i] != member) + strcpy(gu->membername[x++], members[i]->GetName()); + + member->CastToClient()->QueuePacket(outapp); + + safe_delete(outapp); +} + +void Group::SendLeadershipAAUpdate() +{ + // This method updates other members of the group in the current zone with the Leader's group leadership AAs. + // + // It is called when the leader purchases a leadership AA or enters a zone. + // + // If a group member is not in the same zone as the leader when the leader purchases a new AA, they will not become + // aware of it until they are next in the same zone as the leader. + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); + + GroupJoin_Struct* gu = (GroupJoin_Struct*)outapp->pBuffer; + + gu->action = groupActAAUpdate; + + uint32 i = 0; + + gu->leader_aas = LeaderAbilities; + + gu->NPCMarkerID = GetNPCMarkerID(); + + for (i = 0;i < MAX_GROUP_MEMBERS; ++i) + if(members[i] && members[i]->IsClient()) + { + strcpy(gu->yourname, members[i]->GetName()); + strcpy(gu->membername, members[i]->GetName()); + members[i]->CastToClient()->QueuePacket(outapp); + } + + safe_delete(outapp); +} + +uint8 Group::GroupCount() { + + uint8 MemberCount = 0; + + for(uint8 i = 0; i < MAX_GROUP_MEMBERS; ++i) + if(membername[i][0]) + ++MemberCount; + + return MemberCount; +} + +uint32 Group::GetHighestLevel() +{ +uint32 level = 1; +uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) + { + if (members[i]) + { + if(members[i]->GetLevel() > level) + level = members[i]->GetLevel(); + } + } + return level; +} +uint32 Group::GetLowestLevel() +{ +uint32 level = 255; +uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) + { + if (members[i]) + { + if(members[i]->GetLevel() < level) + level = members[i]->GetLevel(); + } + } + return level; +} + +void Group::TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float x, float y, float z, float heading) +{ + uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) + { + if (members[i] != nullptr && members[i]->IsClient() && members[i] != sender) + { + members[i]->CastToClient()->MovePC(zoneID, instance_id, x, y, z, heading, 0, ZoneSolicited); + } + } +} + +bool Group::LearnMembers() { + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + if (database.RunQuery(query,MakeAnyLenString(&query, "SELECT name FROM group_id WHERE groupid=%lu", (unsigned long)GetID()), + errbuf,&result)){ + safe_delete_array(query); + if(mysql_num_rows(result) < 1) { //could prolly be 2 + mysql_free_result(result); + LogFile->write(EQEMuLog::Error, "Error getting group members for group %lu: %s", (unsigned long)GetID(), errbuf); + return(false); + } + int i = 0; + while((row = mysql_fetch_row(result))) { + if(!row[0]) + continue; + members[i] = nullptr; + strn0cpy(membername[i], row[0], 64); + + i++; + } + mysql_free_result(result); + } + + return(true); +} + +void Group::VerifyGroup() { + /* + The purpose of this method is to make sure that a group + is in a valid state, to prevent dangling pointers. + Only called every once in a while (on member re-join for now). + */ + + uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (membername[i][0] == '\0') { +#if EQDEBUG >= 7 +LogFile->write(EQEMuLog::Debug, "Group %lu: Verify %d: Empty.\n", (unsigned long)GetID(), i); +#endif + members[i] = nullptr; + continue; + } + + //it should be safe to use GetClientByName, but Group is trying + //to be generic, so we'll go for general Mob + Mob *them = entity_list.GetMob(membername[i]); + if(them == nullptr && members[i] != nullptr) { //they arnt here anymore.... +#if EQDEBUG >= 6 + LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' has disappeared!!", (unsigned long)GetID(), membername[i]); +#endif + membername[i][0] = '\0'; + members[i] = nullptr; + continue; + } + + if(them != nullptr && members[i] != them) { //our pointer is out of date... not so good. +#if EQDEBUG >= 5 + LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' had an out of date pointer!!", (unsigned long)GetID(), membername[i]); +#endif + members[i] = them; + continue; + } +#if EQDEBUG >= 8 + LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' is valid.", (unsigned long)GetID(), membername[i]); +#endif + } +} + + +void Group::GroupMessage_StringID(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2,const char* message3,const char* message4,const char* message5,const char* message6,const char* message7,const char* message8,const char* message9, uint32 distance) { + uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(members[i] == nullptr) + continue; + + if(members[i] == sender) + continue; + + members[i]->Message_StringID(type, string_id, message, message2, message3, message4, message5, message6, message7, message8, message9, 0); + } +} + + + +void Client::LeaveGroup() { + Group *g = GetGroup(); + + if(g) { + if(g->GroupCount() < 3) + g->DisbandGroup(); + else + g->DelMember(this); + } else { + //force things a little + database.SetGroupID(GetName(), 0, CharacterID()); + } + + isgrouped = false; +} + +void Group::HealGroup(uint32 heal_amt, Mob* caster, int32 range) +{ + if (!caster) + return; + + if (!range) + range = 200; + + float distance; + float range2 = range*range; + + + int numMem = 0; + unsigned int gi = 0; + for(; gi < MAX_GROUP_MEMBERS; gi++) + { + if(members[gi]){ + distance = caster->DistNoRoot(*members[gi]); + if(distance <= range2){ + numMem += 1; + } + } + } + + heal_amt /= numMem; + for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++) + { + if(members[gi]){ + distance = caster->DistNoRoot(*members[gi]); + if(distance <= range2){ + members[gi]->HealDamage(heal_amt, caster); + members[gi]->SendHPUpdate(); + } + } + } +} + + +void Group::BalanceHP(int32 penalty, int32 range, Mob* caster, int32 limit) +{ + if (!caster) + return; + + if (!range) + range = 200; + + int dmgtaken = 0, numMem = 0, dmgtaken_tmp = 0; + + float distance; + float range2 = range*range; + + unsigned int gi = 0; + for(; gi < MAX_GROUP_MEMBERS; gi++) + { + if(members[gi]){ + distance = caster->DistNoRoot(*members[gi]); + if(distance <= range2){ + + dmgtaken_tmp = members[gi]->GetMaxHP() - members[gi]->GetHP(); + if (limit && (dmgtaken_tmp > limit)) + dmgtaken_tmp = limit; + + dmgtaken += (dmgtaken_tmp); + numMem += 1; + } + } + } + + dmgtaken += dmgtaken * penalty / 100; + dmgtaken /= numMem; + for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++) + { + if(members[gi]){ + distance = caster->DistNoRoot(*members[gi]); + if(distance <= range2){ + if((members[gi]->GetMaxHP() - dmgtaken) < 1){ //this way the ability will never kill someone + members[gi]->SetHP(1); //but it will come darn close + members[gi]->SendHPUpdate(); + } + else{ + members[gi]->SetHP(members[gi]->GetMaxHP() - dmgtaken); + members[gi]->SendHPUpdate(); + } + } + } + } +} + +void Group::BalanceMana(int32 penalty, int32 range, Mob* caster, int32 limit) +{ + if (!caster) + return; + + if (!range) + range = 200; + + float distance; + float range2 = range*range; + + int manataken = 0, numMem = 0, manataken_tmp = 0; + unsigned int gi = 0; + for(; gi < MAX_GROUP_MEMBERS; gi++) + { + if(members[gi] && (members[gi]->GetMaxMana() > 0)){ + distance = caster->DistNoRoot(*members[gi]); + if(distance <= range2){ + + manataken_tmp = members[gi]->GetMaxMana() - members[gi]->GetMana(); + if (limit && (manataken_tmp > limit)) + manataken_tmp = limit; + + manataken += (manataken_tmp); + numMem += 1; + } + } + } + + manataken += manataken * penalty / 100; + manataken /= numMem; + + if (limit && (manataken > limit)) + manataken = limit; + + for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++) + { + if(members[gi]){ + distance = caster->DistNoRoot(*members[gi]); + if(distance <= range2){ + if((members[gi]->GetMaxMana() - manataken) < 1){ + members[gi]->SetMana(1); + if (members[gi]->IsClient()) + members[gi]->CastToClient()->SendManaUpdate(); + } + else{ + members[gi]->SetMana(members[gi]->GetMaxMana() - manataken); + if (members[gi]->IsClient()) + members[gi]->CastToClient()->SendManaUpdate(); + } + } + } + } +} + +uint16 Group::GetAvgLevel() +{ + double levelHolder = 0; + uint8 i = 0; + uint8 numMem = 0; + while(i < MAX_GROUP_MEMBERS) + { + if (members[i]) + { + numMem++; + levelHolder = levelHolder + (members[i]->GetLevel()); + } + i++; + } + levelHolder = ((levelHolder/numMem)+.5); // total levels divided by num of characters + return (uint16(levelHolder)); +} + +void Group::MarkNPC(Mob* Target, int Number) +{ + // Send a packet to all group members in this zone causing the client to prefix the Target mob's name + // with the specified Number. + // + if(!Target || Target->IsClient()) + return; + + if((Number < 1) || (Number > MAX_MARKED_NPCS)) + return; + + bool AlreadyMarked = false; + + uint16 EntityID = Target->GetID(); + + for(int i = 0; i < MAX_MARKED_NPCS; ++i) + if(MarkedNPCs[i] == EntityID) + { + if(i == (Number - 1)) + return; + + UpdateXTargetMarkedNPC(i+1, nullptr); + MarkedNPCs[i] = 0; + + AlreadyMarked = true; + + break; + } + + if(!AlreadyMarked) + { + if(MarkedNPCs[Number - 1]) + { + Mob* m = entity_list.GetMob(MarkedNPCs[Number-1]); + if(m) + m->IsTargeted(-1); + + UpdateXTargetMarkedNPC(Number, nullptr); + } + + if(EntityID) + { + Mob* m = entity_list.GetMob(Target->GetID()); + if(m) + m->IsTargeted(1); + } + } + + MarkedNPCs[Number - 1] = EntityID; + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct)); + + MarkNPC_Struct* mnpcs = (MarkNPC_Struct *)outapp->pBuffer; + + mnpcs->TargetID = EntityID; + + mnpcs->Number = Number; + + Mob *m = entity_list.GetMob(EntityID); + + if(m) + sprintf(mnpcs->Name, "%s", m->GetCleanName()); + + QueuePacket(outapp); + + safe_delete(outapp); + + UpdateXTargetMarkedNPC(Number, m); +} + +void Group::DelegateMainTank(const char *NewMainTankName, uint8 toggle) +{ + // This method is called when the group leader Delegates the Main Tank role to a member of the group + // (or himself). All group members in the zone are notified of the new Main Tank and it is recorded + // in the group_leaders table so as to persist across zones. + // + + bool updateDB = false; + + if(!NewMainTankName) + return; + + Mob *m = entity_list.GetMob(NewMainTankName); + + if(!m) + return; + + if(MainTankName != NewMainTankName || !toggle) + updateDB = true; + + if(m->GetTarget()) + TankTargetID = m->GetTarget()->GetID(); + else + TankTargetID = 0; + + Mob *mtt = TankTargetID ? entity_list.GetMob(TankTargetID) : 0; + + SetMainTank(NewMainTankName); + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if(members[i] && members[i]->IsClient()) + { + NotifyMainTank(members[i]->CastToClient(), toggle); + members[i]->CastToClient()->UpdateXTargetType(GroupTank, m, NewMainTankName); + members[i]->CastToClient()->UpdateXTargetType(GroupTankTarget, mtt); + } + } + + if(updateDB) { + char errbuff[MYSQL_ERRMSG_SIZE]; + + char *Query = nullptr; + + if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET maintank='%s' WHERE gid=%i LIMIT 1", + MainTankName.c_str(), GetID()), errbuff)) + LogFile->write(EQEMuLog::Error, "Unable to set group main tank: %s\n", errbuff); + + safe_delete_array(Query); + } +} + +void Group::DelegateMainAssist(const char *NewMainAssistName, uint8 toggle) +{ + // This method is called when the group leader Delegates the Main Assist role to a member of the group + // (or himself). All group members in the zone are notified of the new Main Assist and it is recorded + // in the group_leaders table so as to persist across zones. + // + + bool updateDB = false; + + if(!NewMainAssistName) + return; + + Mob *m = entity_list.GetMob(NewMainAssistName); + + if(!m) + return; + + if(MainAssistName != NewMainAssistName || !toggle) + updateDB = true; + + if(m->GetTarget()) + AssistTargetID = m->GetTarget()->GetID(); + else + AssistTargetID = 0; + + SetMainAssist(NewMainAssistName); + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { + if(members[i] && members[i]->IsClient()) + { + NotifyMainAssist(members[i]->CastToClient(), toggle); + members[i]->CastToClient()->UpdateXTargetType(GroupAssist, m, NewMainAssistName); + members[i]->CastToClient()->UpdateXTargetType(GroupAssistTarget, m->GetTarget()); + } + } + + if(updateDB) { + char errbuff[MYSQL_ERRMSG_SIZE]; + + char *Query = nullptr; + + if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET assist='%s' WHERE gid=%i LIMIT 1", + MainAssistName.c_str(), GetID()), errbuff)) + LogFile->write(EQEMuLog::Error, "Unable to set group main assist: %s\n", errbuff); + + safe_delete_array(Query); + } +} + +void Group::DelegatePuller(const char *NewPullerName, uint8 toggle) +{ + // This method is called when the group leader Delegates the Puller role to a member of the group + // (or himself). All group members in the zone are notified of the new Puller and it is recorded + // in the group_leaders table so as to persist across zones. + // + + bool updateDB = false; + + if(!NewPullerName) + return; + + Mob *m = entity_list.GetMob(NewPullerName); + + if(!m) + return; + + if(PullerName != NewPullerName || !toggle) + updateDB = true; + + if(m->GetTarget()) + PullerTargetID = m->GetTarget()->GetID(); + else + PullerTargetID = 0; + + SetPuller(NewPullerName); + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { + if(members[i] && members[i]->IsClient()) + { + NotifyPuller(members[i]->CastToClient(), toggle); + members[i]->CastToClient()->UpdateXTargetType(Puller, m, NewPullerName); + members[i]->CastToClient()->UpdateXTargetType(PullerTarget, m->GetTarget()); + } + } + + if(updateDB) { + char errbuff[MYSQL_ERRMSG_SIZE]; + + char *Query = nullptr; + + if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET puller='%s' WHERE gid=%i LIMIT 1", + PullerName.c_str(), GetID()), errbuff)) + LogFile->write(EQEMuLog::Error, "Unable to set group main puller: %s\n", errbuff); + + safe_delete_array(Query); + } + +} + +void Group::NotifyMainTank(Client *c, uint8 toggle) +{ + // Send a packet to the specified Client notifying them who the new Main Tank is. This causes the client to display + // a message with the name of the Main Tank. + // + + if(!c) + return; + + if(!MainTankName.size()) + return; + + if(c->GetClientVersion() < EQClientSoD) + { + if(toggle) + c->Message(0, "%s is now Main Tank.", MainTankName.c_str()); + else + c->Message(0, "%s is no longer Main Tank.", MainTankName.c_str()); + } + else + { + EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); + + GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; + + strn0cpy(grs->Name1, MainTankName.c_str(), sizeof(grs->Name1)); + + strn0cpy(grs->Name2, GetLeaderName(), sizeof(grs->Name2)); + + grs->RoleNumber = 1; + + grs->Toggle = toggle; + + c->QueuePacket(outapp); + + safe_delete(outapp); + } + +} + +void Group::NotifyMainAssist(Client *c, uint8 toggle) +{ + // Send a packet to the specified Client notifying them who the new Main Assist is. This causes the client to display + // a message with the name of the Main Assist. + // + + if(!c) + return; + + if(!MainAssistName.size()) + return; + + if(c->GetClientVersion() < EQClientSoD) + { + EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); + + DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; + + das->DelegateAbility = 0; + + das->MemberNumber = 0; + + das->Action = 0; + + das->EntityID = 0; + + strn0cpy(das->Name, MainAssistName.c_str(), sizeof(das->Name)); + + c->QueuePacket(outapp); + + safe_delete(outapp); + } + else + { + EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); + + GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; + + strn0cpy(grs->Name1, MainAssistName.c_str(), sizeof(grs->Name1)); + + strn0cpy(grs->Name2, GetLeaderName(), sizeof(grs->Name2)); + + grs->RoleNumber = 2; + + grs->Toggle = toggle; + + c->QueuePacket(outapp); + + safe_delete(outapp); + } + + NotifyAssistTarget(c); + +} + +void Group::NotifyPuller(Client *c, uint8 toggle) +{ + // Send a packet to the specified Client notifying them who the new Puller is. This causes the client to display + // a message with the name of the Puller. + // + + if(!c) + return; + + if(!PullerName.size()) + return; + + if(c->GetClientVersion() < EQClientSoD) + { + if(toggle) + c->Message(0, "%s is now Puller.", PullerName.c_str()); + else + c->Message(0, "%s is no longer Puller.", PullerName.c_str()); + } + else + { + EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); + + GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; + + strn0cpy(grs->Name1, PullerName.c_str(), sizeof(grs->Name1)); + + strn0cpy(grs->Name2, GetLeaderName(), sizeof(grs->Name2)); + + grs->RoleNumber = 3; + + grs->Toggle = toggle; + + c->QueuePacket(outapp); + + safe_delete(outapp); + } + +} + +void Group::UnDelegateMainTank(const char *OldMainTankName, uint8 toggle) +{ + // Called when the group Leader removes the Main Tank delegation. Sends a packet to each group member in the zone + // informing them of the change and update the group_leaders table. + // + if(OldMainTankName == MainTankName) { + char errbuff[MYSQL_ERRMSG_SIZE]; + + char *Query = 0; + + if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET maintank='' WHERE gid=%i LIMIT 1", + GetID()), errbuff)) + LogFile->write(EQEMuLog::Error, "Unable to clear group main tank: %s\n", errbuff); + + safe_delete_array(Query); + + if(!toggle) { + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { + if(members[i] && members[i]->IsClient()) + { + NotifyMainTank(members[i]->CastToClient(), toggle); + members[i]->CastToClient()->UpdateXTargetType(GroupTank, nullptr, ""); + members[i]->CastToClient()->UpdateXTargetType(GroupTankTarget, nullptr); + } + } + } + + SetMainTank(""); + } +} + +void Group::UnDelegateMainAssist(const char *OldMainAssistName, uint8 toggle) +{ + // Called when the group Leader removes the Main Assist delegation. Sends a packet to each group member in the zone + // informing them of the change and update the group_leaders table. + // + if(OldMainAssistName == MainAssistName) { + EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); + + DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; + + das->DelegateAbility = 0; + + das->MemberNumber = 0; + + das->Action = 1; + + das->EntityID = 0; + + strn0cpy(das->Name, OldMainAssistName, sizeof(das->Name)); + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + if(members[i] && members[i]->IsClient()) + { + members[i]->CastToClient()->QueuePacket(outapp); + members[i]->CastToClient()->UpdateXTargetType(GroupAssist, nullptr, ""); + } + + safe_delete(outapp); + + char errbuff[MYSQL_ERRMSG_SIZE]; + + char *Query = 0; + + if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET assist='' WHERE gid=%i LIMIT 1", + GetID()), errbuff)) + LogFile->write(EQEMuLog::Error, "Unable to clear group main assist: %s\n", errbuff); + + safe_delete_array(Query); + + if(!toggle) + { + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if(members[i] && members[i]->IsClient()) + { + NotifyMainAssist(members[i]->CastToClient(), toggle); + members[i]->CastToClient()->UpdateXTargetType(GroupAssistTarget, nullptr); + } + } + } + + SetMainAssist(""); + } +} + +void Group::UnDelegatePuller(const char *OldPullerName, uint8 toggle) +{ + // Called when the group Leader removes the Puller delegation. Sends a packet to each group member in the zone + // informing them of the change and update the group_leaders table. + // + if(OldPullerName == PullerName) { + char errbuff[MYSQL_ERRMSG_SIZE]; + + char *Query = 0; + + if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET puller='' WHERE gid=%i LIMIT 1", + GetID()), errbuff)) + LogFile->write(EQEMuLog::Error, "Unable to clear group main puller: %s\n", errbuff); + + safe_delete_array(Query); + + if(!toggle) { + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { + if(members[i] && members[i]->IsClient()) + { + NotifyPuller(members[i]->CastToClient(), toggle); + members[i]->CastToClient()->UpdateXTargetType(Puller, nullptr, ""); + members[i]->CastToClient()->UpdateXTargetType(PullerTarget, nullptr); + } + } + } + + SetPuller(""); + } +} + +bool Group::IsNPCMarker(Client *c) +{ + // Returns true if the specified client has been delegated the NPC Marker Role + // + if(!c) + return false; + + if(NPCMarkerName.size()) + return(c->GetName() == NPCMarkerName); + + return false; + +} + +void Group::SetGroupAssistTarget(Mob *m) +{ + // Notify all group members in the zone of the new target the Main Assist has selected. + // + AssistTargetID = m ? m->GetID() : 0; + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if(members[i] && members[i]->IsClient()) + { + NotifyAssistTarget(members[i]->CastToClient()); + } + } +} + +void Group::SetGroupTankTarget(Mob *m) +{ + TankTargetID = m ? m->GetID() : 0; + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if(members[i] && members[i]->IsClient()) + { + members[i]->CastToClient()->UpdateXTargetType(GroupTankTarget, m); + } + } +} + +void Group::SetGroupPullerTarget(Mob *m) +{ + PullerTargetID = m ? m->GetID() : 0; + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if(members[i] && members[i]->IsClient()) + { + members[i]->CastToClient()->UpdateXTargetType(PullerTarget, m); + } + } +} + +void Group::NotifyAssistTarget(Client *c) +{ + // Send a packet to the specified client notifying them of the group target selected by the Main Assist. + + if(!c) + return; + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SetGroupTarget, sizeof(MarkNPC_Struct)); + + MarkNPC_Struct* mnpcs = (MarkNPC_Struct *)outapp->pBuffer; + + mnpcs->TargetID = AssistTargetID; + + mnpcs->Number = 0; + + c->QueuePacket(outapp); + + safe_delete(outapp); + + Mob *m = entity_list.GetMob(AssistTargetID); + + c->UpdateXTargetType(GroupAssistTarget, m); + +} + +void Group::NotifyTankTarget(Client *c) +{ + if(!c) + return; + + Mob *m = entity_list.GetMob(TankTargetID); + + c->UpdateXTargetType(GroupTankTarget, m); +} + +void Group::NotifyPullerTarget(Client *c) +{ + if(!c) + return; + + Mob *m = entity_list.GetMob(PullerTargetID); + + c->UpdateXTargetType(PullerTarget, m); +} + +void Group::DelegateMarkNPC(const char *NewNPCMarkerName) +{ + // Called when the group leader has delegated the Mark NPC ability to a group member. + // Notify all group members in the zone of the change and save the change in the group_leaders + // table to persist across zones. + // + if(NPCMarkerName.size() > 0) + UnDelegateMarkNPC(NPCMarkerName.c_str()); + + if(!NewNPCMarkerName) + return; + + SetNPCMarker(NewNPCMarkerName); + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + if(members[i] && members[i]->IsClient()) + NotifyMarkNPC(members[i]->CastToClient()); + + char errbuff[MYSQL_ERRMSG_SIZE]; + + char *Query = 0; + + if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET marknpc='%s' WHERE gid=%i LIMIT 1", + NewNPCMarkerName, GetID()), errbuff)) + LogFile->write(EQEMuLog::Error, "Unable to set group mark npc: %s\n", errbuff); + + safe_delete_array(Query); + +} + +void Group::NotifyMarkNPC(Client *c) +{ + // Notify the specified client who the group member is who has been delgated the Mark NPC ability. + + if(!c) + return; + + if(!NPCMarkerName.size()) + return; + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); + + DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; + + das->DelegateAbility = 1; + + das->MemberNumber = 0; + + das->Action = 0; + + das->EntityID = NPCMarkerID; + + strn0cpy(das->Name, NPCMarkerName.c_str(), sizeof(das->Name)); + + c->QueuePacket(outapp); + + safe_delete(outapp); + +} +void Group::SetNPCMarker(const char *NewNPCMarkerName) +{ + NPCMarkerName = NewNPCMarkerName; + + Client *m = entity_list.GetClientByName(NPCMarkerName.c_str()); + + if(!m) + NPCMarkerID = 0; + else + NPCMarkerID = m->GetID(); +} + +void Group::UnDelegateMarkNPC(const char *OldNPCMarkerName) +{ + // Notify all group members in the zone that the Mark NPC ability has been rescinded from the specified + // group member. + + if(!OldNPCMarkerName) + return; + + if(!NPCMarkerName.size()) + return; + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); + + DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; + + das->DelegateAbility = 1; + + das->MemberNumber = 0; + + das->Action = 1; + + das->EntityID = 0; + + strn0cpy(das->Name, OldNPCMarkerName, sizeof(das->Name)); + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + if(members[i] && members[i]->IsClient()) + members[i]->CastToClient()->QueuePacket(outapp); + + safe_delete(outapp); + + NPCMarkerName.clear(); + + char errbuff[MYSQL_ERRMSG_SIZE]; + + char *Query = 0; + + if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET marknpc='' WHERE gid=%i LIMIT 1", + GetID()), errbuff)) + LogFile->write(EQEMuLog::Error, "Unable to clear group marknpc: %s\n", errbuff); + + safe_delete_array(Query); +} + +void Group::SaveGroupLeaderAA() +{ + // Stores the Group Leaders Leadership AA data from the Player Profile as a blob in the group_leaders table. + // This is done so that group members not in the same zone as the Leader still have access to this information. + + char *Query = new char[200 + sizeof(GroupLeadershipAA_Struct)*2]; + + char *End = Query; + + End += sprintf(End, "UPDATE group_leaders SET leadershipaa='"); + + End += database.DoEscapeString(End, (char*)&LeaderAbilities, sizeof(GroupLeadershipAA_Struct)); + + End += sprintf(End,"' WHERE gid=%i LIMIT 1", GetID()); + + char errbuff[MYSQL_ERRMSG_SIZE]; + if (!database.RunQuery(Query, End - Query, errbuff)) + LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", errbuff); + + safe_delete_array(Query); +} + +void Group::UnMarkNPC(uint16 ID) +{ + // Called from entity_list when the mob with the specified ID is being destroyed. + // + // If the given mob has been marked by this group, it is removed from the list of marked NPCs. + // The primary reason for doing this is so that when a new group member joins or zones in, we + // send them correct details of which NPCs are currently marked. + + if(AssistTargetID == ID) + AssistTargetID = 0; + + + if(TankTargetID == ID) + TankTargetID = 0; + + if(PullerTargetID == ID) + PullerTargetID = 0; + + for(int i = 0; i < MAX_MARKED_NPCS; ++i) + { + if(MarkedNPCs[i] == ID) + { + MarkedNPCs[i] = 0; + UpdateXTargetMarkedNPC(i + 1, nullptr); + } + } +} + +void Group::SendMarkedNPCsToMember(Client *c, bool Clear) +{ + // Send the Entity IDs of the NPCs marked by the Group Leader or delegate to the specified client. + // If Clear == true, then tell the client to unmark the NPCs (when a member disbands). + // + // + if(!c) + return; + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct)); + + MarkNPC_Struct *mnpcs = (MarkNPC_Struct *)outapp->pBuffer; + + for(int i = 0; i < MAX_MARKED_NPCS; ++i) + { + if(MarkedNPCs[i]) + { + mnpcs->TargetID = MarkedNPCs[i]; + + Mob *m = entity_list.GetMob(MarkedNPCs[i]); + + if(m) + sprintf(mnpcs->Name, "%s", m->GetCleanName()); + + if(!Clear) + mnpcs->Number = i + 1; + else + mnpcs->Number = 0; + + c->QueuePacket(outapp); + c->UpdateXTargetType((mnpcs->Number == 1) ? GroupMarkTarget1 : ((mnpcs->Number == 2) ? GroupMarkTarget2 : GroupMarkTarget3), m); + } + } + + safe_delete(outapp); +} + +void Group::ClearAllNPCMarks() +{ + // This method is designed to be called when the number of members in the group drops below 3 and leadership AA + // may no longer be used. It removes all NPC marks. + // + for(uint8 i = 0; i < MAX_GROUP_MEMBERS; ++i) + if(members[i] && members[i]->IsClient()) + SendMarkedNPCsToMember(members[i]->CastToClient(), true); + + for(int i = 0; i < MAX_MARKED_NPCS; ++i) + { + if(MarkedNPCs[i]) + { + Mob* m = entity_list.GetMob(MarkedNPCs[i]); + + if(m) + m->IsTargeted(-1); + } + + MarkedNPCs[i] = 0; + } + +} + +int8 Group::GetNumberNeedingHealedInGroup(int8 hpr, bool includePets) { + int8 needHealed = 0; + + for( int i = 0; iqglobal) { + + if(members[i]->GetHPRatio() <= hpr) + needHealed++; + + if(includePets) { + if(members[i]->GetPet() && members[i]->GetPet()->GetHPRatio() <= hpr) { + needHealed++; + } + } + } + } + + + return needHealed; +} + +void Group::UpdateGroupAAs() +{ + // This method updates the Groups Leadership abilities from the Player Profile of the Leader. + // + Mob *m = GetLeader(); + + if(m && m->IsClient()) + m->CastToClient()->GetGroupAAs(&LeaderAbilities); + else + memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct)); + + SaveGroupLeaderAA(); +} + +void Group::QueueHPPacketsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app) +{ + // Send a mobs HP packets to group members if the leader has the NPC Health AA and the mob is the + // target of the group's main assist, or is marked, and the member doesn't already have the mob targeted. + + if(!sender || !app || !GetLeadershipAA(groupAANPCHealth)) + return; + + uint16 SenderID = sender->GetID(); + + if(SenderID != AssistTargetID) + { + bool Marked = false; + + for(int i = 0; i < MAX_MARKED_NPCS; ++i) + { + if(MarkedNPCs[i] == SenderID) + { + Marked = true; + break; + } + } + + if(!Marked) + return; + + } + + for(unsigned int i = 0; i < MAX_GROUP_MEMBERS; ++i) + if(members[i] && members[i]->IsClient()) + { + if(!members[i]->GetTarget() || (members[i]->GetTarget()->GetID() != SenderID)) + { + members[i]->CastToClient()->QueuePacket(app); + } + } + +} + +void Group::ChangeLeader(Mob* newleader) +{ + // this changes the current group leader, notifies other members, and updates leadship AA + + // if the new leader is invalid, do nothing + if (!newleader) + return; + + Mob* oldleader = GetLeader(); + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); + GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer; + gu->action = groupActMakeLeader; + + strcpy(gu->membername, newleader->GetName()); + strcpy(gu->yourname, oldleader->GetName()); + SetLeader(newleader); + database.SetGroupLeaderName(GetID(), newleader->GetName()); + UpdateGroupAAs(); + gu->leader_aas = LeaderAbilities; + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] && members[i]->IsClient()) + { + if(members[i]->CastToClient()->GetClientVersion() >= EQClientSoD) + members[i]->CastToClient()->SendGroupLeaderChangePacket(newleader->GetName()); + + members[i]->CastToClient()->QueuePacket(outapp); + } + } + safe_delete(outapp); +} + +const char *Group::GetClientNameByIndex(uint8 index) +{ + return membername[index]; +} + +void Group::UpdateXTargetMarkedNPC(uint32 Number, Mob *m) +{ + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if(members[i] && members[i]->IsClient()) + { + members[i]->CastToClient()->UpdateXTargetType((Number == 1) ? GroupMarkTarget1 : ((Number == 2) ? GroupMarkTarget2 : GroupMarkTarget3), m); + } + } + +} + +void Group::SetMainTank(const char *NewMainTankName) +{ + MainTankName = NewMainTankName; + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if(!strncasecmp(membername[i], NewMainTankName, 64)) + MemberRoles[i] |= RoleTank; + else + MemberRoles[i] &= ~RoleTank; + } +} + +void Group::SetMainAssist(const char *NewMainAssistName) +{ + MainAssistName = NewMainAssistName; + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if(!strncasecmp(membername[i], NewMainAssistName, 64)) + MemberRoles[i] |= RoleAssist; + else + MemberRoles[i] &= ~RoleAssist; + } +} + +void Group::SetPuller(const char *NewPullerName) +{ + PullerName = NewPullerName; + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if(!strncasecmp(membername[i], NewPullerName, 64)) + MemberRoles[i] |= RolePuller; + else + MemberRoles[i] &= ~RolePuller; + } +} + +bool Group::HasRole(Mob *m, uint8 Role) +{ + if(!m) + return false; + + for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) + { + if((m == members[i]) && (MemberRoles[i] & Role)) + return true; + } + return false; +} + diff --git a/zone/mob.h b/zone/mob.h index 7083e45ca..97b75a4fb 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -662,7 +662,7 @@ public: bool TryReflectSpell(uint32 spell_id); bool CanBlockSpell() const { return(spellbonuses.BlockNextSpell); } bool DoHPToManaCovert(uint16 mana_cost = 0); - int32 ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard = false); + int32 ApplySpellEffectiveness(int16 spell_id, int32 value, bool IsBard = false, uint16 caster_id=0); int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect); int32 GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg); void MeleeLifeTap(int32 damage); @@ -898,7 +898,7 @@ public: virtual int32 CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possible = 0); uint32 GetInstrumentMod(uint16 spell_id) const; - int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0); + int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0,uint16 casterid=0); int CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining = 0); virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1); uint32 GetCastedSpellInvSlot() const { return casting_spell_inventory_slot; } diff --git a/zone/mobx.cpp b/zone/mobx.cpp new file mode 100644 index 000000000..340dfdfea --- /dev/null +++ b/zone/mobx.cpp @@ -0,0 +1,5148 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "../common/debug.h" +#include "masterentity.h" +#include "../common/spdat.h" +#include "StringIDs.h" +#include "worldserver.h" +#include "QuestParserCollection.h" +#include "../common/StringUtil.h" + +#include +#include +#include + +extern EntityList entity_list; + +extern Zone* zone; +extern WorldServer worldserver; + +Mob::Mob(const char* in_name, + const char* in_lastname, + int32 in_cur_hp, + int32 in_max_hp, + uint8 in_gender, + uint16 in_race, + uint8 in_class, + bodyType in_bodytype, + uint8 in_deity, + uint8 in_level, + uint32 in_npctype_id, + float in_size, + float in_runspeed, + float in_heading, + float in_x_pos, + float in_y_pos, + float in_z_pos, + + uint8 in_light, + uint8 in_texture, + uint8 in_helmtexture, + uint16 in_ac, + uint16 in_atk, + uint16 in_str, + uint16 in_sta, + uint16 in_dex, + uint16 in_agi, + uint16 in_int, + uint16 in_wis, + uint16 in_cha, + uint8 in_haircolor, + uint8 in_beardcolor, + uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye? + uint8 in_eyecolor2, + uint8 in_hairstyle, + uint8 in_luclinface, + uint8 in_beard, + uint32 in_drakkin_heritage, + uint32 in_drakkin_tattoo, + uint32 in_drakkin_details, + uint32 in_armor_tint[_MaterialCount], + + uint8 in_aa_title, + uint8 in_see_invis, // see through invis/ivu + uint8 in_see_invis_undead, + uint8 in_see_hide, + uint8 in_see_improved_hide, + int32 in_hp_regen, + int32 in_mana_regen, + uint8 in_qglobal, + uint8 in_maxlevel, + uint32 in_scalerate + ) : + attack_timer(2000), + attack_dw_timer(2000), + ranged_timer(2000), + tic_timer(6000), + mana_timer(2000), + spellend_timer(0), + rewind_timer(30000), //Timer used for determining amount of time between actual player position updates for /rewind. + bindwound_timer(10000), + stunned_timer(0), + spun_timer(0), + bardsong_timer(6000), + gravity_timer(1000), + viral_timer(0), + flee_timer(FLEE_CHECK_TIMER) + +{ + targeted = 0; + tar_ndx=0; + tar_vector=0; + tar_vx=0; + tar_vy=0; + tar_vz=0; + tarx=0; + tary=0; + tarz=0; + fear_walkto_x = -999999; + fear_walkto_y = -999999; + fear_walkto_z = -999999; + curfp = false; + + AI_Init(); + SetMoving(false); + moved=false; + rewind_x = 0; //Stored x_pos for /rewind + rewind_y = 0; //Stored y_pos for /rewind + rewind_z = 0; //Stored z_pos for /rewind + move_tic_count = 0; + + _egnode = nullptr; + name[0]=0; + orig_name[0]=0; + clean_name[0]=0; + lastname[0]=0; + if(in_name) { + strn0cpy(name,in_name,64); + strn0cpy(orig_name,in_name,64); + } + if(in_lastname) + strn0cpy(lastname,in_lastname,64); + cur_hp = in_cur_hp; + max_hp = in_max_hp; + base_hp = in_max_hp; + gender = in_gender; + race = in_race; + base_gender = in_gender; + base_race = in_race; + class_ = in_class; + bodytype = in_bodytype; + orig_bodytype = in_bodytype; + deity = in_deity; + level = in_level; + orig_level = in_level; + npctype_id = in_npctype_id; + size = in_size; + base_size = size; + runspeed = in_runspeed; + + + // sanity check + if (runspeed < 0 || runspeed > 20) + runspeed = 1.25f; + + heading = in_heading; + x_pos = in_x_pos; + y_pos = in_y_pos; + z_pos = in_z_pos; + light = in_light; + texture = in_texture; + helmtexture = in_helmtexture; + haircolor = in_haircolor; + beardcolor = in_beardcolor; + eyecolor1 = in_eyecolor1; + eyecolor2 = in_eyecolor2; + hairstyle = in_hairstyle; + luclinface = in_luclinface; + beard = in_beard; + drakkin_heritage = in_drakkin_heritage; + drakkin_tattoo = in_drakkin_tattoo; + drakkin_details = in_drakkin_details; + attack_speed= 0; + slow_mitigation= 0; + findable = false; + trackable = true; + has_shieldequiped = false; + has_numhits = false; + has_MGB = false; + has_ProjectIllusion = false; + + if(in_aa_title>0) + aa_title = in_aa_title; + else + aa_title =0xFF; + AC = in_ac; + ATK = in_atk; + STR = in_str; + STA = in_sta; + DEX = in_dex; + AGI = in_agi; + INT = in_int; + WIS = in_wis; + CHA = in_cha; + MR = CR = FR = DR = PR = Corrup = 0; + + ExtraHaste = 0; + bEnraged = false; + + shield_target = nullptr; + cur_mana = 0; + max_mana = 0; + hp_regen = in_hp_regen; + mana_regen = in_mana_regen; + oocregen = RuleI(NPC, OOCRegen); //default Out of Combat Regen + maxlevel = in_maxlevel; + scalerate = in_scalerate; + invisible = false; + invisible_undead = false; + invisible_animals = false; + sneaking = false; + hidden = false; + improved_hidden = false; + invulnerable = false; + IsFullHP = (cur_hp == max_hp); + qglobal=0; + + InitializeBuffSlots(); + + // clear the proc arrays + int i; + int j; + for (j = 0; j < MAX_PROCS; j++) + { + PermaProcs[j].spellID = SPELL_UNKNOWN; + PermaProcs[j].chance = 0; + PermaProcs[j].base_spellID = SPELL_UNKNOWN; + SpellProcs[j].spellID = SPELL_UNKNOWN; + SpellProcs[j].chance = 0; + SpellProcs[j].base_spellID = SPELL_UNKNOWN; + DefensiveProcs[j].spellID = SPELL_UNKNOWN; + DefensiveProcs[j].chance = 0; + DefensiveProcs[j].base_spellID = SPELL_UNKNOWN; + RangedProcs[j].spellID = SPELL_UNKNOWN; + RangedProcs[j].chance = 0; + RangedProcs[j].base_spellID = SPELL_UNKNOWN; + SkillProcs[j].spellID = SPELL_UNKNOWN; + SkillProcs[j].chance = 0; + SkillProcs[j].base_spellID = SPELL_UNKNOWN; + } + + for (i = 0; i < _MaterialCount; i++) + { + if (in_armor_tint) + { + armor_tint[i] = in_armor_tint[i]; + } + else + { + armor_tint[i] = 0; + } + } + + delta_heading = 0; + delta_x = 0; + delta_y = 0; + delta_z = 0; + animation = 0; + + logging_enabled = false; + isgrouped = false; + israidgrouped = false; + islooting = false; + _appearance = eaStanding; + pRunAnimSpeed = 0; + + spellend_timer.Disable(); + bardsong_timer.Disable(); + bardsong = 0; + bardsong_target_id = 0; + casting_spell_id = 0; + casting_spell_timer = 0; + casting_spell_timer_duration = 0; + casting_spell_type = 0; + casting_spell_inventory_slot = 0; + target = 0; + + for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_spell_id[i] = 0; } + for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_target_id[i] = 0; } + for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_increment[i] = 0; } + for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_x[i] = 0; } + for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_y[i] = 0; } + for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_z[i] = 0; } + projectile_timer.Disable(); + + memset(&itembonuses, 0, sizeof(StatBonuses)); + memset(&spellbonuses, 0, sizeof(StatBonuses)); + memset(&aabonuses, 0, sizeof(StatBonuses)); + spellbonuses.AggroRange = -1; + spellbonuses.AssistRange = -1; + pLastChange = 0; + SetPetID(0); + SetOwnerID(0); + typeofpet = petCharmed; //default to charmed... + petpower = 0; + held = false; + nocast = false; + focused = false; + + attacked_count = 0; + mezzed = false; + stunned = false; + silenced = false; + amnesiad = false; + inWater = false; + int m; + for (m = 0; m < MAX_SHIELDERS; m++) + { + shielder[m].shielder_id = 0; + shielder[m].shielder_bonus = 0; + } + + destructibleobject = false; + wandertype=0; + pausetype=0; + cur_wp = 0; + cur_wp_x = 0; + cur_wp_y = 0; + cur_wp_z = 0; + cur_wp_pause = 0; + patrol=0; + follow=0; + follow_dist = 100; // Default Distance for Follow + flee_mode = false; + fear_walkto_x = -999999; + fear_walkto_y = -999999; + fear_walkto_z = -999999; + curfp = false; + flee_timer.Start(); + + permarooted = (runspeed > 0) ? false : true; + + movetimercompleted = false; + roamer = false; + rooted = false; + charmed = false; + has_virus = false; + for (i=0; iCharmed()) + GetPet()->BuffFadeByEffect(SE_Charm); + else + SetPet(0); + } + + EQApplicationPacket app; + CreateDespawnPacket(&app, !IsCorpse()); + Corpse* corpse = entity_list.GetCorpseByID(GetID()); + if(!corpse || (corpse && !corpse->IsPlayerCorpse())) + entity_list.QueueClients(this, &app, true); + + entity_list.RemoveFromTargets(this, true); + + if(trade) { + Mob *with = trade->With(); + if(with && with->IsClient()) { + with->CastToClient()->FinishTrade(with); + with->trade->Reset(); + } + delete trade; + } + + if(HadTempPets()){ + entity_list.DestroyTempPets(this); + } + entity_list.UnMarkNPC(GetID()); + safe_delete(PathingLOSCheckTimer); + safe_delete(PathingRouteUpdateTimerShort); + safe_delete(PathingRouteUpdateTimerLong); + UninitializeBuffSlots(); +} + +uint32 Mob::GetAppearanceValue(EmuAppearance iAppearance) { + switch (iAppearance) { + // 0 standing, 1 sitting, 2 ducking, 3 lieing down, 4 looting + case eaStanding: { + return ANIM_STAND; + } + case eaSitting: { + return ANIM_SIT; + } + case eaCrouching: { + return ANIM_CROUCH; + } + case eaDead: { + return ANIM_DEATH; + } + case eaLooting: { + return ANIM_LOOT; + } + //to shup up compiler: + case _eaMaxAppearance: + break; + } + return(ANIM_STAND); +} + +void Mob::SetInvisible(uint8 state) +{ + invisible = state; + SendAppearancePacket(AT_Invis, invisible); + // Invis and hide breaks charms + + if ((this->GetPetType() == petCharmed) && (invisible || hidden || improved_hidden)) + { + Mob* formerpet = this->GetPet(); + + if(formerpet) + formerpet->BuffFadeByEffect(SE_Charm); + } +} + +//check to see if `this` is invisible to `other` +bool Mob::IsInvisible(Mob* other) const +{ + if(!other) + return(false); + + uint8 SeeInvisBonus = 0; + if (IsClient()) + SeeInvisBonus = aabonuses.SeeInvis; + + //check regular invisibility + if (invisible && invisible > (other->SeeInvisible())) + return true; + + //check invis vs. undead + if (other->GetBodyType() == BT_Undead || other->GetBodyType() == BT_SummonedUndead) { + if(invisible_undead && !other->SeeInvisibleUndead()) + return true; + } + + //check invis vs. animals... + if (other->GetBodyType() == BT_Animal){ + if(invisible_animals && !other->SeeInvisible()) + return true; + } + + if(hidden){ + if(!other->see_hide && !other->see_improved_hide){ + return true; + } + } + + if(improved_hidden){ + if(!other->see_improved_hide){ + return true; + } + } + + //handle sneaking + if(sneaking) { + if(BehindMob(other, GetX(), GetY()) ) + return true; + } + + return(false); +} + +float Mob::_GetMovementSpeed(int mod) const +{ + // List of movement speed modifiers, including AAs & spells: + // http://everquest.allakhazam.com/db/item.html?item=1721;page=1;howmany=50#m10822246245352 + if (IsRooted()) + return 0.0f; + + float speed_mod = runspeed; + + // These two cases ignore the cap, be wise in the DB for horses. + if (IsClient()) { + if (CastToClient()->GetGMSpeed()) { + speed_mod = 3.125f; + if (mod != 0) + speed_mod += speed_mod * static_cast(mod) / 100.0f; + return speed_mod; + } else { + Mob *horse = entity_list.GetMob(CastToClient()->GetHorseId()); + if (horse) { + speed_mod = horse->GetBaseRunspeed(); + if (mod != 0) + speed_mod += speed_mod * static_cast(mod) / 100.0f; + return speed_mod; + } + } + } + + int aa_mod = 0; + int spell_mod = 0; + int runspeedcap = RuleI(Character,BaseRunSpeedCap); + int movemod = 0; + float frunspeedcap = 0.0f; + + runspeedcap += itembonuses.IncreaseRunSpeedCap + spellbonuses.IncreaseRunSpeedCap + aabonuses.IncreaseRunSpeedCap; + aa_mod += itembonuses.BaseMovementSpeed + spellbonuses.BaseMovementSpeed + aabonuses.BaseMovementSpeed; + spell_mod += spellbonuses.movementspeed + itembonuses.movementspeed; + + // hard cap + if (runspeedcap > 225) + runspeedcap = 225; + + if (spell_mod < 0) + movemod += spell_mod; + else if (spell_mod > aa_mod) + movemod = spell_mod; + else + movemod = aa_mod; + + // cap negative movemods from snares mostly + if (movemod < -85) + movemod = -85; + + if (movemod != 0) + speed_mod += speed_mod * static_cast(movemod) / 100.0f; + + // runspeed caps + frunspeedcap = static_cast(runspeedcap) / 100.0f; + if (IsClient() && speed_mod > frunspeedcap) + speed_mod = frunspeedcap; + + // apply final mod such as the -47 for walking + // use runspeed since it should stack with snares + // and if we get here, we know runspeed was the initial + // value before we applied movemod. + if (mod != 0) + speed_mod += runspeed * static_cast(mod) / 100.0f; + + if (speed_mod <= 0.0f) + speed_mod = IsClient() ? 0.0001f : 0.0f; + + return speed_mod; +} + +int32 Mob::CalcMaxMana() { + switch (GetCasterClass()) { + case 'I': + max_mana = (((GetINT()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana; + break; + case 'W': + max_mana = (((GetWIS()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana; + break; + case 'N': + default: + max_mana = 0; + break; + } + if (max_mana < 0) { + max_mana = 0; + } + + return max_mana; +} + +int32 Mob::CalcMaxHP() { + max_hp = (base_hp + itembonuses.HP + spellbonuses.HP); + max_hp += max_hp * ((aabonuses.MaxHPChange + spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f); + return max_hp; +} + +int32 Mob::GetItemHPBonuses() { + int32 item_hp = 0; + item_hp = itembonuses.HP; + item_hp += item_hp * itembonuses.MaxHPChange / 10000; + return item_hp; +} + +int32 Mob::GetSpellHPBonuses() { + int32 spell_hp = 0; + spell_hp = spellbonuses.HP; + spell_hp += spell_hp * spellbonuses.MaxHPChange / 10000; + return spell_hp; +} + +char Mob::GetCasterClass() const { + switch(class_) + { + case CLERIC: + case PALADIN: + case RANGER: + case DRUID: + case SHAMAN: + case BEASTLORD: + case CLERICGM: + case PALADINGM: + case RANGERGM: + case DRUIDGM: + case SHAMANGM: + case BEASTLORDGM: + return 'W'; + break; + + case SHADOWKNIGHT: + case BARD: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + case SHADOWKNIGHTGM: + case BARDGM: + case NECROMANCERGM: + case WIZARDGM: + case MAGICIANGM: + case ENCHANTERGM: + return 'I'; + break; + + default: + return 'N'; + break; + } +} + +uint8 Mob::GetArchetype() const { + switch(class_) + { + case PALADIN: + case RANGER: + case SHADOWKNIGHT: + case BARD: + case BEASTLORD: + case PALADINGM: + case RANGERGM: + case SHADOWKNIGHTGM: + case BARDGM: + case BEASTLORDGM: + return ARCHETYPE_HYBRID; + break; + case CLERIC: + case DRUID: + case SHAMAN: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + case CLERICGM: + case DRUIDGM: + case SHAMANGM: + case NECROMANCERGM: + case WIZARDGM: + case MAGICIANGM: + case ENCHANTERGM: + return ARCHETYPE_CASTER; + break; + case WARRIOR: + case MONK: + case ROGUE: + case BERSERKER: + case WARRIORGM: + case MONKGM: + case ROGUEGM: + case BERSERKERGM: + return ARCHETYPE_MELEE; + break; + default: + return ARCHETYPE_HYBRID; + break; + } +} + +void Mob::CreateSpawnPacket(EQApplicationPacket* app, Mob* ForWho) { + app->SetOpcode(OP_NewSpawn); + app->size = sizeof(NewSpawn_Struct); + app->pBuffer = new uchar[app->size]; + memset(app->pBuffer, 0, app->size); + NewSpawn_Struct* ns = (NewSpawn_Struct*)app->pBuffer; + FillSpawnStruct(ns, ForWho); + + if(strlen(ns->spawn.lastName) == 0) { + switch(ns->spawn.class_) + { + case TRIBUTE_MASTER: + strcpy(ns->spawn.lastName, "Tribute Master"); + break; + case ADVENTURERECRUITER: + strcpy(ns->spawn.lastName, "Adventure Recruiter"); + break; + case BANKER: + strcpy(ns->spawn.lastName, "Banker"); + break; + case ADVENTUREMERCHANT: + strcpy(ns->spawn.lastName,"Adventure Merchant"); + break; + case WARRIORGM: + strcpy(ns->spawn.lastName, "GM Warrior"); + break; + case PALADINGM: + strcpy(ns->spawn.lastName, "GM Paladin"); + break; + case RANGERGM: + strcpy(ns->spawn.lastName, "GM Ranger"); + break; + case SHADOWKNIGHTGM: + strcpy(ns->spawn.lastName, "GM Shadowknight"); + break; + case DRUIDGM: + strcpy(ns->spawn.lastName, "GM Druid"); + break; + case BARDGM: + strcpy(ns->spawn.lastName, "GM Bard"); + break; + case ROGUEGM: + strcpy(ns->spawn.lastName, "GM Rogue"); + break; + case SHAMANGM: + strcpy(ns->spawn.lastName, "GM Shaman"); + break; + case NECROMANCERGM: + strcpy(ns->spawn.lastName, "GM Necromancer"); + break; + case WIZARDGM: + strcpy(ns->spawn.lastName, "GM Wizard"); + break; + case MAGICIANGM: + strcpy(ns->spawn.lastName, "GM Magician"); + break; + case ENCHANTERGM: + strcpy(ns->spawn.lastName, "GM Enchanter"); + break; + case BEASTLORDGM: + strcpy(ns->spawn.lastName, "GM Beastlord"); + break; + case BERSERKERGM: + strcpy(ns->spawn.lastName, "GM Berserker"); + break; + case MERCERNARY_MASTER: + strcpy(ns->spawn.lastName, "Mercenary Recruiter"); + break; + default: + break; + } + } +} + +void Mob::CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns) { + app->SetOpcode(OP_NewSpawn); + app->size = sizeof(NewSpawn_Struct); + + app->pBuffer = new uchar[sizeof(NewSpawn_Struct)]; + + // Copy ns directly into packet + memcpy(app->pBuffer, ns, sizeof(NewSpawn_Struct)); + + // Custom packet data + NewSpawn_Struct* ns2 = (NewSpawn_Struct*)app->pBuffer; + strcpy(ns2->spawn.name, ns->spawn.name); + switch(ns->spawn.class_) + { + case TRIBUTE_MASTER: + strcpy(ns2->spawn.lastName, "Tribute Master"); + break; + case ADVENTURERECRUITER: + strcpy(ns2->spawn.lastName, "Adventure Recruiter"); + break; + case BANKER: + strcpy(ns2->spawn.lastName, "Banker"); + break; + case ADVENTUREMERCHANT: + strcpy(ns->spawn.lastName,"Adventure Merchant"); + break; + case WARRIORGM: + strcpy(ns2->spawn.lastName, "GM Warrior"); + break; + case PALADINGM: + strcpy(ns2->spawn.lastName, "GM Paladin"); + break; + case RANGERGM: + strcpy(ns2->spawn.lastName, "GM Ranger"); + break; + case SHADOWKNIGHTGM: + strcpy(ns2->spawn.lastName, "GM Shadowknight"); + break; + case DRUIDGM: + strcpy(ns2->spawn.lastName, "GM Druid"); + break; + case BARDGM: + strcpy(ns2->spawn.lastName, "GM Bard"); + break; + case ROGUEGM: + strcpy(ns2->spawn.lastName, "GM Rogue"); + break; + case SHAMANGM: + strcpy(ns2->spawn.lastName, "GM Shaman"); + break; + case NECROMANCERGM: + strcpy(ns2->spawn.lastName, "GM Necromancer"); + break; + case WIZARDGM: + strcpy(ns2->spawn.lastName, "GM Wizard"); + break; + case MAGICIANGM: + strcpy(ns2->spawn.lastName, "GM Magician"); + break; + case ENCHANTERGM: + strcpy(ns2->spawn.lastName, "GM Enchanter"); + break; + case BEASTLORDGM: + strcpy(ns2->spawn.lastName, "GM Beastlord"); + break; + case BERSERKERGM: + strcpy(ns2->spawn.lastName, "GM Berserker"); + break; + case MERCERNARY_MASTER: + strcpy(ns->spawn.lastName, "Mercenary Recruiter"); + break; + default: + strcpy(ns2->spawn.lastName, ns->spawn.lastName); + break; + } + + memset(&app->pBuffer[sizeof(Spawn_Struct)-7], 0xFF, 7); +} + +void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) +{ + int i; + + strcpy(ns->spawn.name, name); + if(IsClient()) { + strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName)); + } + + ns->spawn.heading = FloatToEQ19(heading); + ns->spawn.x = FloatToEQ19(x_pos);//((int32)x_pos)<<3; + ns->spawn.y = FloatToEQ19(y_pos);//((int32)y_pos)<<3; + ns->spawn.z = FloatToEQ19(z_pos);//((int32)z_pos)<<3; + ns->spawn.spawnId = GetID(); + ns->spawn.curHp = static_cast(GetHPRatio()); + ns->spawn.max_hp = 100; //this field needs a better name + ns->spawn.race = race; + ns->spawn.runspeed = runspeed; + ns->spawn.walkspeed = runspeed * 0.5f; + ns->spawn.class_ = class_; + ns->spawn.gender = gender; + ns->spawn.level = level; + ns->spawn.deity = deity; + ns->spawn.animation = 0; + ns->spawn.findable = findable?1:0; + ns->spawn.light = light; + ns->spawn.showhelm = 1; + + ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players + ns->spawn.NPC = IsClient() ? 0 : 1; + ns->spawn.IsMercenary = (IsMerc() || no_target_hotkey) ? 1 : 0; + + ns->spawn.petOwnerId = ownerid; + + ns->spawn.haircolor = haircolor; + ns->spawn.beardcolor = beardcolor; + ns->spawn.eyecolor1 = eyecolor1; + ns->spawn.eyecolor2 = eyecolor2; + ns->spawn.hairstyle = hairstyle; + ns->spawn.face = luclinface; + ns->spawn.beard = beard; + ns->spawn.StandState = GetAppearanceValue(_appearance); + ns->spawn.drakkin_heritage = drakkin_heritage; + ns->spawn.drakkin_tattoo = drakkin_tattoo; + ns->spawn.drakkin_details = drakkin_details; + ns->spawn.equip_chest2 = texture; + +// ns->spawn.invis2 = 0xff;//this used to be labeled beard.. if its not FF it will turn mob invis + + if(helmtexture && helmtexture != 0xFF) + { + ns->spawn.helm=helmtexture; + } else { + ns->spawn.helm = 0; + } + + ns->spawn.guildrank = 0xFF; + ns->spawn.size = size; + ns->spawn.bodytype = bodytype; + // The 'flymode' settings have the following effect: + // 0 - Mobs in water sink like a stone to the bottom + // 1 - Same as #flymode 1 + // 2 - Same as #flymode 2 + // 3 - Mobs in water do not sink. A value of 3 in this field appears to be the default setting for all mobs + // (in water or not) according to 6.2 era packet collects. + if(IsClient()) + { + ns->spawn.flymode = FindType(SE_Levitate) ? 2 : 0; + } + else + ns->spawn.flymode = flymode; + + ns->spawn.lastName[0] = '\0'; + + strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName)); + + for(i = 0; i < _MaterialCount; i++) + { + ns->spawn.equipment[i] = GetEquipmentMaterial(i); + if (armor_tint[i]) + { + ns->spawn.colors[i].color = armor_tint[i]; + } + else + { + ns->spawn.colors[i].color = GetEquipmentColor(i); + } + } + + memset(ns->spawn.set_to_0xFF, 0xFF, sizeof(ns->spawn.set_to_0xFF)); + if(IsNPC() && IsDestructibleObject()) + { + ns->spawn.DestructibleObject = true; + + // Changing the first string made it vanish, so it has some significance. + if(lastname) + sprintf(ns->spawn.DestructibleModel, "%s", lastname); + // Changing the second string made no visible difference + sprintf(ns->spawn.DestructibleName2, "%s", ns->spawn.name); + // Putting a string in the final one that was previously empty had no visible effect. + sprintf(ns->spawn.DestructibleString, ""); + + // Sets damage appearance level of the object. + ns->spawn.DestructibleAppearance = luclinface; // Was 0x00000000 + //ns->spawn.DestructibleAppearance = static_cast(_appearance); + // #appearance 44 1 makes it jump but no visible damage + // #appearance 44 2 makes it look completely broken but still visible + // #appearnace 44 3 makes it jump but not visible difference to 3 + // #appearance 44 4 makes it disappear altogether + // #appearance 44 5 makes the client crash. + + ns->spawn.DestructibleUnk1 = 0x00000224; // Was 0x000001f5; + // These next 4 are mostly always sequential + // Originally they were 633, 634, 635, 636 + // Changing them all to 633 - no visible effect. + // Changing them all to 636 - no visible effect. + // Reversing the order of these four numbers and then using #appearance gain had no visible change. + // Setting these four ids to zero had no visible effect when the catapult spawned, nor when #appearance was used. + ns->spawn.DestructibleID1 = 1968; + ns->spawn.DestructibleID2 = 1969; + ns->spawn.DestructibleID3 = 1970; + ns->spawn.DestructibleID4 = 1971; + // Next one was originally 0x1ce45008, changing it to 0x00000000 made no visible difference + ns->spawn.DestructibleUnk2 = 0x13f79d00; + // Next one was originally 0x1a68fe30, changing it to 0x00000000 made no visible difference + ns->spawn.DestructibleUnk3 = 0x00000000; + // Next one was already 0x00000000 + ns->spawn.DestructibleUnk4 = 0x13f79d58; + // Next one was originally 0x005a69ec, changing it to 0x00000000 made no visible difference. + ns->spawn.DestructibleUnk5 = 0x13c55b00; + // Next one was originally 0x1a68fe30, changing it to 0x00000000 made no visible difference. + ns->spawn.DestructibleUnk6 = 0x00128860; + // Next one was originally 0x0059de6d, changing it to 0x00000000 made no visible difference. + ns->spawn.DestructibleUnk7 = 0x005a8f66; + // Next one was originally 0x00000201, changing it to 0x00000000 made no visible difference. + // For the Minohten tents, 0x00000000 had them up in the air, while 0x201 put them on the ground. + // Changing it it 0x00000001 makes the tent sink into the ground. + ns->spawn.DestructibleUnk8 = 0x01; // Needs to be 1 for tents? + ns->spawn.DestructibleUnk9 = 0x00000002; // Needs to be 2 for tents? + + ns->spawn.flymode = 0; + } +} + +void Mob::CreateDespawnPacket(EQApplicationPacket* app, bool Decay) +{ + app->SetOpcode(OP_DeleteSpawn); + app->size = sizeof(DeleteSpawn_Struct); + app->pBuffer = new uchar[app->size]; + memset(app->pBuffer, 0, app->size); + DeleteSpawn_Struct* ds = (DeleteSpawn_Struct*)app->pBuffer; + ds->spawn_id = GetID(); + // The next field only applies to corpses. If 0, they vanish instantly, otherwise they 'decay' + ds->Decay = Decay ? 1 : 0; +} + +void Mob::CreateHPPacket(EQApplicationPacket* app) +{ + this->IsFullHP=(cur_hp>=max_hp); + app->SetOpcode(OP_MobHealth); + app->size = sizeof(SpawnHPUpdate_Struct2); + app->pBuffer = new uchar[app->size]; + memset(app->pBuffer, 0, sizeof(SpawnHPUpdate_Struct2)); + SpawnHPUpdate_Struct2* ds = (SpawnHPUpdate_Struct2*)app->pBuffer; + + ds->spawn_id = GetID(); + // they don't need to know the real hp + ds->hp = (int)GetHPRatio(); + + // hp event + if (IsNPC() && (GetNextHPEvent() > 0)) + { + if (ds->hp < GetNextHPEvent()) + { + char buf[10]; + snprintf(buf, 9, "%i", GetNextHPEvent()); + buf[9] = '\0'; + SetNextHPEvent(-1); + parse->EventNPC(EVENT_HP, CastToNPC(), nullptr, buf, 0); + } + } + + if (IsNPC() && (GetNextIncHPEvent() > 0)) + { + if (ds->hp > GetNextIncHPEvent()) + { + char buf[10]; + snprintf(buf, 9, "%i", GetNextIncHPEvent()); + buf[9] = '\0'; + SetNextIncHPEvent(-1); + parse->EventNPC(EVENT_HP, CastToNPC(), nullptr, buf, 1); + } + } +} + +// sends hp update of this mob to people who might care +void Mob::SendHPUpdate() +{ + EQApplicationPacket hp_app; + Group *group; + + // destructor will free the pBuffer + CreateHPPacket(&hp_app); + + // send to people who have us targeted + entity_list.QueueClientsByTarget(this, &hp_app, false, 0, false, true, BIT_AllClients); + entity_list.QueueClientsByXTarget(this, &hp_app, false); + entity_list.QueueToGroupsForNPCHealthAA(this, &hp_app); + + // send to group + if(IsGrouped()) + { + group = entity_list.GetGroupByMob(this); + if(group) //not sure why this might be null, but it happens + group->SendHPPacketsFrom(this); + } + + if(IsClient()){ + Raid *r = entity_list.GetRaidByClient(CastToClient()); + if(r){ + r->SendHPPacketsFrom(this); + } + } + + // send to master + if(GetOwner() && GetOwner()->IsClient()) + { + GetOwner()->CastToClient()->QueuePacket(&hp_app, false); + group = entity_list.GetGroupByClient(GetOwner()->CastToClient()); + if(group) + group->SendHPPacketsFrom(this); + Raid *r = entity_list.GetRaidByClient(GetOwner()->CastToClient()); + if(r) + r->SendHPPacketsFrom(this); + } + + // send to pet + if(GetPet() && GetPet()->IsClient()) + { + GetPet()->CastToClient()->QueuePacket(&hp_app, false); + } + + // Update the damage state of destructible objects + if(IsNPC() && IsDestructibleObject()) + { + if (GetHPRatio() > 74) + { + if (GetAppearance() != eaStanding) + { + SendAppearancePacket(AT_DamageState, eaStanding); + _appearance = eaStanding; + } + } + else if (GetHPRatio() > 49) + { + if (GetAppearance() != eaSitting) + { + SendAppearancePacket(AT_DamageState, eaSitting); + _appearance = eaSitting; + } + } + else if (GetHPRatio() > 24) + { + if (GetAppearance() != eaCrouching) + { + SendAppearancePacket(AT_DamageState, eaCrouching); + _appearance = eaCrouching; + } + } + else if (GetHPRatio() > 0) + { + if (GetAppearance() != eaDead) + { + SendAppearancePacket(AT_DamageState, eaDead); + _appearance = eaDead; + } + } + else if (GetAppearance() != eaLooting) + { + SendAppearancePacket(AT_DamageState, eaLooting); + _appearance = eaLooting; + } + } + + // send to self - we need the actual hps here + if(IsClient()) + { + EQApplicationPacket* hp_app2 = new EQApplicationPacket(OP_HPUpdate,sizeof(SpawnHPUpdate_Struct)); + SpawnHPUpdate_Struct* ds = (SpawnHPUpdate_Struct*)hp_app2->pBuffer; + ds->cur_hp = CastToClient()->GetHP() - itembonuses.HP; + ds->spawn_id = GetID(); + ds->max_hp = CastToClient()->GetMaxHP() - itembonuses.HP; + CastToClient()->QueuePacket(hp_app2); + safe_delete(hp_app2); + } +} + +// this one just warps the mob to the current location +void Mob::SendPosition() +{ + EQApplicationPacket* app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; + MakeSpawnUpdateNoDelta(spu); + move_tic_count = 0; + entity_list.QueueClients(this, app, true); + safe_delete(app); +} + +// this one is for mobs on the move, with deltas - this makes them walk +void Mob::SendPosUpdate(uint8 iSendToSelf) { + EQApplicationPacket* app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; + MakeSpawnUpdate(spu); + + if (iSendToSelf == 2) { + if (this->IsClient()) + this->CastToClient()->FastQueuePacket(&app,false); + } + else + { + if(move_tic_count == RuleI(Zone, NPCPositonUpdateTicCount)) + { + entity_list.QueueClients(this, app, (iSendToSelf==0), false); + move_tic_count = 0; + } + else + { + entity_list.QueueCloseClients(this, app, (iSendToSelf==0), 800, nullptr, false); + move_tic_count++; + } + } + safe_delete(app); +} + +// this is for SendPosition() +void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu){ + memset(spu,0xff,sizeof(PlayerPositionUpdateServer_Struct)); + spu->spawn_id = GetID(); + spu->x_pos = FloatToEQ19(x_pos); + spu->y_pos = FloatToEQ19(y_pos); + spu->z_pos = FloatToEQ19(z_pos); + spu->delta_x = NewFloatToEQ13(0); + spu->delta_y = NewFloatToEQ13(0); + spu->delta_z = NewFloatToEQ13(0); + spu->heading = FloatToEQ19(heading); + spu->animation = 0; + spu->delta_heading = NewFloatToEQ13(0); + spu->padding0002 =0; + spu->padding0006 =7; + spu->padding0014 =0x7f; + spu->padding0018 =0x5df27; + +} + +// this is for SendPosUpdate() +void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) { + spu->spawn_id = GetID(); + spu->x_pos = FloatToEQ19(x_pos); + spu->y_pos = FloatToEQ19(y_pos); + spu->z_pos = FloatToEQ19(z_pos); + spu->delta_x = NewFloatToEQ13(delta_x); + spu->delta_y = NewFloatToEQ13(delta_y); + spu->delta_z = NewFloatToEQ13(delta_z); + spu->heading = FloatToEQ19(heading); + spu->padding0002 =0; + spu->padding0006 =7; + spu->padding0014 =0x7f; + spu->padding0018 =0x5df27; + if(this->IsClient()) + spu->animation = animation; + else + spu->animation = pRunAnimSpeed;//animation; + spu->delta_heading = NewFloatToEQ13(static_cast(delta_heading)); +} + +void Mob::ShowStats(Client* client) +{ + if (IsClient()) { + CastToClient()->SendStatsWindow(client, RuleB(Character, UseNewStatsWindow)); + } + else if (IsCorpse()) { + if (IsPlayerCorpse()) { + client->Message(0, " CharID: %i PlayerCorpse: %i", CastToCorpse()->GetCharID(), CastToCorpse()->GetDBID()); + } + else { + client->Message(0, " NPCCorpse", GetID()); + } + } + else { + client->Message(0, " Level: %i AC: %i Class: %i Size: %1.1f Haste: %i", GetLevel(), GetAC(), GetClass(), GetSize(), GetHaste()); + client->Message(0, " HP: %i Max HP: %i",GetHP(), GetMaxHP()); + client->Message(0, " Mana: %i Max Mana: %i", GetMana(), GetMaxMana()); + client->Message(0, " Total ATK: %i Worn/Spell ATK (Cap %i): %i", GetATK(), RuleI(Character, ItemATKCap), GetATKBonus()); + client->Message(0, " STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA()); + client->Message(0, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup()); + client->Message(0, " Race: %i BaseRace: %i Texture: %i HelmTexture: %i Gender: %i BaseGender: %i", GetRace(), GetBaseRace(), GetTexture(), GetHelmTexture(), GetGender(), GetBaseGender()); + if (client->Admin() >= 100) + client->Message(0, " EntityID: %i PetID: %i OwnerID: %i AIControlled: %i Targetted: %i", GetID(), GetPetID(), GetOwnerID(), IsAIControlled(), targeted); + + if (IsNPC()) { + NPC *n = CastToNPC(); + uint32 spawngroupid = 0; + if(n->respawn2 != 0) + spawngroupid = n->respawn2->SpawnGroupID(); + client->Message(0, " NPCID: %u SpawnGroupID: %u Grid: %i LootTable: %u FactionID: %i SpellsID: %u ", GetNPCTypeID(),spawngroupid, n->GetGrid(), n->GetLoottableID(), n->GetNPCFactionID(), n->GetNPCSpellsID()); + client->Message(0, " Accuracy: %i MerchantID: %i EmoteID: %i Runspeed: %f Walkspeed: %f", n->GetAccuracyRating(), n->MerchantType, n->GetEmoteID(), n->GetRunspeed(), n->GetWalkspeed()); + n->QueryLoot(client); + } + if (IsAIControlled()) { + client->Message(0, " AggroRange: %1.0f AssistRange: %1.0f", GetAggroRange(), GetAssistRange()); + } + } +} + +void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter) { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); + Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer; + anim->spawnid = GetID(); + if(type == 0){ + anim->action = 10; + anim->value=animnum; + } + else{ + anim->action = animnum; + anim->value=type; + } + entity_list.QueueCloseClients(this, outapp, false, 200, 0, ackreq, filter); + safe_delete(outapp); +} + +void Mob::ShowBuffs(Client* client) { + if(SPDAT_RECORDS <= 0) + return; + client->Message(0, "Buffs on: %s", this->GetName()); + uint32 i; + uint32 buff_count = GetMaxTotalSlots(); + for (i=0; i < buff_count; i++) { + if (buffs[i].spellid != SPELL_UNKNOWN) { + if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) + client->Message(0, " %i: %s: Permanent", i, spells[buffs[i].spellid].name); + else + client->Message(0, " %i: %s: %i tics left", i, spells[buffs[i].spellid].name, buffs[i].ticsremaining); + + } + } + if (IsClient()){ + client->Message(0, "itembonuses:"); + client->Message(0, "Atk:%i Ac:%i HP(%i):%i Mana:%i", itembonuses.ATK, itembonuses.AC, itembonuses.HPRegen, itembonuses.HP, itembonuses.Mana); + client->Message(0, "Str:%i Sta:%i Dex:%i Agi:%i Int:%i Wis:%i Cha:%i", + itembonuses.STR,itembonuses.STA,itembonuses.DEX,itembonuses.AGI,itembonuses.INT,itembonuses.WIS,itembonuses.CHA); + client->Message(0, "SvMagic:%i SvFire:%i SvCold:%i SvPoison:%i SvDisease:%i", + itembonuses.MR,itembonuses.FR,itembonuses.CR,itembonuses.PR,itembonuses.DR); + client->Message(0, "DmgShield:%i Haste:%i", itembonuses.DamageShield, itembonuses.haste ); + client->Message(0, "spellbonuses:"); + client->Message(0, "Atk:%i Ac:%i HP(%i):%i Mana:%i", spellbonuses.ATK, spellbonuses.AC, spellbonuses.HPRegen, spellbonuses.HP, spellbonuses.Mana); + client->Message(0, "Str:%i Sta:%i Dex:%i Agi:%i Int:%i Wis:%i Cha:%i", + spellbonuses.STR,spellbonuses.STA,spellbonuses.DEX,spellbonuses.AGI,spellbonuses.INT,spellbonuses.WIS,spellbonuses.CHA); + client->Message(0, "SvMagic:%i SvFire:%i SvCold:%i SvPoison:%i SvDisease:%i", + spellbonuses.MR,spellbonuses.FR,spellbonuses.CR,spellbonuses.PR,spellbonuses.DR); + client->Message(0, "DmgShield:%i Haste:%i", spellbonuses.DamageShield, spellbonuses.haste ); + } +} + +void Mob::ShowBuffList(Client* client) { + if(SPDAT_RECORDS <= 0) + return; + + client->Message(0, "Buffs on: %s", this->GetCleanName()); + uint32 i; + uint32 buff_count = GetMaxTotalSlots(); + for (i=0; i < buff_count; i++) { + if (buffs[i].spellid != SPELL_UNKNOWN) { + if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) + client->Message(0, " %i: %s: Permanent", i, spells[buffs[i].spellid].name); + else + client->Message(0, " %i: %s: %i tics left", i, spells[buffs[i].spellid].name, buffs[i].ticsremaining); + } + } +} + +void Mob::GMMove(float x, float y, float z, float heading, bool SendUpdate) { + + Route.clear(); + + if(IsNPC()) { + entity_list.ProcessMove(CastToNPC(), x, y, z); + } + + x_pos = x; + y_pos = y; + z_pos = z; + if (heading != 0.01) + this->heading = heading; + if(IsNPC()) + CastToNPC()->SaveGuardSpot(true); + if(SendUpdate) + SendPosition(); +} + +void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture, uint8 in_helmtexture, uint8 in_haircolor, uint8 in_beardcolor, uint8 in_eyecolor1, uint8 in_eyecolor2, uint8 in_hairstyle, uint8 in_luclinface, uint8 in_beard, uint8 in_aa_title, uint32 in_drakkin_heritage, uint32 in_drakkin_tattoo, uint32 in_drakkin_details, float in_size) { + + uint16 BaseRace = GetBaseRace(); + + if (in_race == 0) { + this->race = BaseRace; + if (in_gender == 0xFF) + this->gender = GetBaseGender(); + else + this->gender = in_gender; + } + else { + this->race = in_race; + if (in_gender == 0xFF) { + uint8 tmp = Mob::GetDefaultGender(this->race, gender); + if (tmp == 2) + gender = 2; + else if (gender == 2 && GetBaseGender() == 2) + gender = tmp; + else if (gender == 2) + gender = GetBaseGender(); + } + else + gender = in_gender; + } + if (in_texture == 0xFF) { + if (in_race <= 12 || in_race == 128 || in_race == 130 || in_race == 330 || in_race == 522) + this->texture = 0xFF; + else + this->texture = GetTexture(); + } + else + this->texture = in_texture; + + if (in_helmtexture == 0xFF) { + if (in_race <= 12 || in_race == 128 || in_race == 130 || in_race == 330 || in_race == 522) + this->helmtexture = 0xFF; + else if (in_texture != 0xFF) + this->helmtexture = in_texture; + else + this->helmtexture = GetHelmTexture(); + } + else + this->helmtexture = in_helmtexture; + + if (in_haircolor == 0xFF) + this->haircolor = GetHairColor(); + else + this->haircolor = in_haircolor; + + if (in_beardcolor == 0xFF) + this->beardcolor = GetBeardColor(); + else + this->beardcolor = in_beardcolor; + + if (in_eyecolor1 == 0xFF) + this->eyecolor1 = GetEyeColor1(); + else + this->eyecolor1 = in_eyecolor1; + + if (in_eyecolor2 == 0xFF) + this->eyecolor2 = GetEyeColor2(); + else + this->eyecolor2 = in_eyecolor2; + + if (in_hairstyle == 0xFF) + this->hairstyle = GetHairStyle(); + else + this->hairstyle = in_hairstyle; + + if (in_luclinface == 0xFF) + this->luclinface = GetLuclinFace(); + else + this->luclinface = in_luclinface; + + if (in_beard == 0xFF) + this->beard = GetBeard(); + else + this->beard = in_beard; + + this->aa_title = 0xFF; + + if (in_drakkin_heritage == 0xFFFFFFFF) + this->drakkin_heritage = GetDrakkinHeritage(); + else + this->drakkin_heritage = in_drakkin_heritage; + + if (in_drakkin_tattoo == 0xFFFFFFFF) + this->drakkin_tattoo = GetDrakkinTattoo(); + else + this->drakkin_tattoo = in_drakkin_tattoo; + + if (in_drakkin_details == 0xFFFFFFFF) + this->drakkin_details = GetDrakkinDetails(); + else + this->drakkin_details = in_drakkin_details; + + if (in_size == 0xFFFFFFFF) + this->size = GetSize(); + else + this->size = in_size; + + // Forces the feature information to be pulled from the Player Profile + if (this->IsClient() && in_race == 0) { + this->race = CastToClient()->GetBaseRace(); + this->gender = CastToClient()->GetBaseGender(); + this->texture = 0xFF; + this->helmtexture = 0xFF; + this->haircolor = CastToClient()->GetBaseHairColor(); + this->beardcolor = CastToClient()->GetBaseBeardColor(); + this->eyecolor1 = CastToClient()->GetBaseEyeColor(); + this->eyecolor2 = CastToClient()->GetBaseEyeColor(); + this->hairstyle = CastToClient()->GetBaseHairStyle(); + this->luclinface = CastToClient()->GetBaseFace(); + this->beard = CastToClient()->GetBaseBeard(); + this->aa_title = 0xFF; + this->drakkin_heritage = CastToClient()->GetBaseHeritage(); + this->drakkin_tattoo = CastToClient()->GetBaseTattoo(); + this->drakkin_details = CastToClient()->GetBaseDetails(); + switch(race){ + case OGRE: + this->size = 9; + break; + case TROLL: + this->size = 8; + break; + case VAHSHIR: + case BARBARIAN: + this->size = 7; + break; + case HALF_ELF: + case WOOD_ELF: + case DARK_ELF: + case FROGLOK: + this->size = 5; + break; + case DWARF: + this->size = 4; + break; + case HALFLING: + case GNOME: + this->size = 3; + break; + default: + this->size = 6; + break; + } + } + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Illusion, sizeof(Illusion_Struct)); + memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); + Illusion_Struct* is = (Illusion_Struct*) outapp->pBuffer; + is->spawnid = this->GetID(); + strcpy(is->charname, GetCleanName()); + is->race = this->race; + is->gender = this->gender; + is->texture = this->texture; + is->helmtexture = this->helmtexture; + is->haircolor = this->haircolor; + is->beardcolor = this->beardcolor; + is->beard = this->beard; + is->eyecolor1 = this->eyecolor1; + is->eyecolor2 = this->eyecolor2; + is->hairstyle = this->hairstyle; + is->face = this->luclinface; + //is->aa_title = this->aa_title; + is->drakkin_heritage = this->drakkin_heritage; + is->drakkin_tattoo = this->drakkin_tattoo; + is->drakkin_details = this->drakkin_details; + is->size = this->size; + + entity_list.QueueClients(this, outapp); + safe_delete(outapp); + mlog(CLIENT__SPELLS, "Illusion: Race = %i, Gender = %i, Texture = %i, HelmTexture = %i, HairColor = %i, BeardColor = %i, EyeColor1 = %i, EyeColor2 = %i, HairStyle = %i, Face = %i, DrakkinHeritage = %i, DrakkinTattoo = %i, DrakkinDetails = %i, Size = %f", + this->race, this->gender, this->texture, this->helmtexture, this->haircolor, this->beardcolor, this->eyecolor1, this->eyecolor2, this->hairstyle, this->luclinface, this->drakkin_heritage, this->drakkin_tattoo, this->drakkin_details, this->size); +} + +uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) { +//std::cout << "Gender in: " << (int)in_gender << std::endl; // undefined cout [CODEBUG] + if ((in_race > 0 && in_race <= GNOME ) + || in_race == IKSAR || in_race == VAHSHIR || in_race == FROGLOK || in_race == DRAKKIN + || in_race == 15 || in_race == 50 || in_race == 57 || in_race == 70 || in_race == 98 || in_race == 118) { + if (in_gender >= 2) { + // Female default for PC Races + return 1; + } + else + return in_gender; + } + else if (in_race == 44 || in_race == 52 || in_race == 55 || in_race == 65 || in_race == 67 || in_race == 88 || in_race == 117 || in_race == 127 || + in_race == 77 || in_race == 78 || in_race == 81 || in_race == 90 || in_race == 92 || in_race == 93 || in_race == 94 || in_race == 106 || in_race == 112 || in_race == 471) { + // Male only races + return 0; + + } + else if (in_race == 25 || in_race == 56) { + // Female only races + return 1; + } + else { + // Neutral default for NPC Races + return 2; + } +} + +void Mob::SendAppearancePacket(uint32 type, uint32 value, bool WholeZone, bool iIgnoreSelf, Client *specific_target) { + if (!GetID()) + return; + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + SpawnAppearance_Struct* appearance = (SpawnAppearance_Struct*)outapp->pBuffer; + appearance->spawn_id = this->GetID(); + appearance->type = type; + appearance->parameter = value; + if (WholeZone) + entity_list.QueueClients(this, outapp, iIgnoreSelf); + else if(specific_target != nullptr) + specific_target->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); + else if (this->IsClient()) + this->CastToClient()->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); + safe_delete(outapp); +} + +void Mob::SendLevelAppearance(){ + EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); + LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer; + la->parm1 = 0x4D; + la->parm2 = la->parm1 + 1; + la->parm3 = la->parm2 + 1; + la->parm4 = la->parm3 + 1; + la->parm5 = la->parm4 + 1; + la->spawn_id = GetID(); + la->value1a = 1; + la->value2a = 2; + la->value3a = 1; + la->value3b = 1; + la->value4a = 1; + la->value4b = 1; + la->value5a = 2; + entity_list.QueueCloseClients(this,outapp); + safe_delete(outapp); +} + +void Mob::SendStunAppearance() +{ + EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); + LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer; + la->parm1 = 58; + la->parm2 = 60; + la->spawn_id = GetID(); + la->value1a = 2; + la->value1b = 0; + la->value2a = 2; + la->value2b = 0; + entity_list.QueueCloseClients(this,outapp); + safe_delete(outapp); +} + +void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target){ + EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); + LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer; + la->spawn_id = GetID(); + la->parm1 = parm1; + la->parm2 = parm2; + la->parm3 = parm3; + la->parm4 = parm4; + la->parm5 = parm5; + // Note that setting the b values to 0 will disable the related effect from the corresponding parameter. + // Setting the a value appears to have no affect at all.s + la->value1a = 1; + la->value1b = 1; + la->value2a = 1; + la->value2b = 1; + la->value3a = 1; + la->value3b = 1; + la->value4a = 1; + la->value4b = 1; + la->value5a = 1; + la->value5b = 1; + if(specific_target == nullptr) { + entity_list.QueueClients(this,outapp); + } + else if (specific_target->IsClient()) { + specific_target->CastToClient()->QueuePacket(outapp, false); + } + safe_delete(outapp); +} + +void Mob::SendTargetable(bool on, Client *specific_target) { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Untargetable, sizeof(Untargetable_Struct)); + Untargetable_Struct *ut = (Untargetable_Struct*)outapp->pBuffer; + ut->id = GetID(); + ut->targetable_flag = on == true ? 1 : 0; + + if(specific_target == nullptr) { + entity_list.QueueClients(this, outapp); + } + else if (specific_target->IsClient()) { + specific_target->CastToClient()->QueuePacket(outapp, false); + } + safe_delete(outapp); +} + +void Mob::QuestReward(Client *c, uint32 silver, uint32 gold, uint32 platinum) { + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct)); + memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); + QuestReward_Struct* qr = (QuestReward_Struct*) outapp->pBuffer; + + qr->from_mob = GetID(); // Entity ID for the from mob name + qr->silver = silver; + qr->gold = gold; + qr->platinum = platinum; + + if(c) + c->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); + + safe_delete(outapp); +} + +void Mob::CameraEffect(uint32 duration, uint32 intensity, Client *c, bool global) { + + + if(global == true) + { + ServerPacket* pack = new ServerPacket(ServerOP_CameraShake, sizeof(ServerCameraShake_Struct)); + memset(pack->pBuffer, 0, sizeof(pack->pBuffer)); + ServerCameraShake_Struct* scss = (ServerCameraShake_Struct*) pack->pBuffer; + scss->duration = duration; + scss->intensity = intensity; + worldserver.SendPacket(pack); + safe_delete(pack); + return; + } + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_CameraEffect, sizeof(Camera_Struct)); + memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); + Camera_Struct* cs = (Camera_Struct*) outapp->pBuffer; + cs->duration = duration; // Duration in milliseconds + cs->intensity = ((intensity * 6710886) + 1023410176); // Intensity ranges from 1023410176 to 1090519040, so simplify it from 0 to 10. + + if(c) + c->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); + else + entity_list.QueueClients(this, outapp); + + safe_delete(outapp); +} + +void Mob::SendSpellEffect(uint32 effectid, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk020, bool perm_effect, Client *c) { + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpellEffect, sizeof(SpellEffect_Struct)); + memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); + SpellEffect_Struct* se = (SpellEffect_Struct*) outapp->pBuffer; + se->EffectID = effectid; // ID of the Particle Effect + se->EntityID = GetID(); + se->EntityID2 = GetID(); // EntityID again + se->Duration = duration; // In Milliseconds + se->FinishDelay = finish_delay; // Seen 0 + se->Unknown020 = unk020; // Seen 3000 + se->Unknown024 = 1; // Seen 1 for SoD + se->Unknown025 = 1; // Seen 1 for Live + se->Unknown026 = 0; // Seen 1157 + + if(c) + c->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); + else if(zone_wide) + entity_list.QueueClients(this, outapp); + else + entity_list.QueueCloseClients(this, outapp); + + safe_delete(outapp); + + if (perm_effect) { + if(!IsNimbusEffectActive(effectid)) { + SetNimbusEffect(effectid); + } + } + +} + +void Mob::TempName(const char *newname) +{ + char temp_name[64]; + char old_name[64]; + strn0cpy(old_name, GetName(), 64); + + if(newname) + strn0cpy(temp_name, newname, 64); + + // Reset the name to the original if left null. + if(!newname) { + strn0cpy(temp_name, GetOrigName(), 64); + SetName(temp_name); + //CleanMobName(GetName(), temp_name); + strn0cpy(temp_name, GetCleanName(), 64); + } + + // Make the new name unique and set it + strn0cpy(temp_name, entity_list.MakeNameUnique(temp_name), 64); + + + // Send the new name to all clients + EQApplicationPacket* outapp = new EQApplicationPacket(OP_MobRename, sizeof(MobRename_Struct)); + memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); + MobRename_Struct* mr = (MobRename_Struct*) outapp->pBuffer; + strn0cpy(mr->old_name, old_name, 64); + strn0cpy(mr->old_name_again, old_name, 64); + strn0cpy(mr->new_name, temp_name, 64); + mr->unknown192 = 0; + mr->unknown196 = 1; + entity_list.QueueClients(this, outapp); + safe_delete(outapp); + + SetName(temp_name); +} + +void Mob::SetTargetable(bool on) { + if(m_targetable != on) { + m_targetable = on; + SendTargetable(on); + } +} + +const int32& Mob::SetMana(int32 amount) +{ + CalcMaxMana(); + int32 mmana = GetMaxMana(); + cur_mana = amount < 0 ? 0 : (amount > mmana ? mmana : amount); +/* + if(IsClient()) + LogFile->write(EQEMuLog::Debug, "Setting mana for %s to %d (%4.1f%%)", GetName(), amount, GetManaRatio()); +*/ + + return cur_mana; +} + + +void Mob::SetAppearance(EmuAppearance app, bool iIgnoreSelf) { + if (_appearance != app) { + _appearance = app; + SendAppearancePacket(AT_Anim, GetAppearanceValue(app), true, iIgnoreSelf); + if (this->IsClient() && this->IsAIControlled()) + SendAppearancePacket(AT_Anim, ANIM_FREEZE, false, false); + } +} + +void Mob::ChangeSize(float in_size = 0, bool bNoRestriction) { + // Size Code + if (!bNoRestriction) + { + if (this->IsClient() || this->petid != 0) + if (in_size < 3.0) + in_size = 3.0; + + + if (this->IsClient() || this->petid != 0) + if (in_size > 15.0) + in_size = 15.0; + } + + + if (in_size < 1.0) + in_size = 1.0; + + if (in_size > 255.0) + in_size = 255.0; + //End of Size Code + this->size = in_size; + SendAppearancePacket(AT_Size, (uint32) in_size); +} + +Mob* Mob::GetOwnerOrSelf() { + if (!GetOwnerID()) + return this; + Mob* owner = entity_list.GetMob(this->GetOwnerID()); + if (!owner) { + SetOwnerID(0); + return(this); + } + if (owner->GetPetID() == this->GetID()) { + return owner; + } + if(IsNPC() && CastToNPC()->GetSwarmInfo()){ + return (CastToNPC()->GetSwarmInfo()->GetOwner()); + } + SetOwnerID(0); + return this; +} + +Mob* Mob::GetOwner() { + Mob* owner = entity_list.GetMob(this->GetOwnerID()); + if (owner && owner->GetPetID() == this->GetID()) { + + return owner; + } + if(IsNPC() && CastToNPC()->GetSwarmInfo()){ + return (CastToNPC()->GetSwarmInfo()->GetOwner()); + } + SetOwnerID(0); + return 0; +} + +Mob* Mob::GetUltimateOwner() +{ + Mob* Owner = GetOwner(); + + if(!Owner) + return this; + + while(Owner && Owner->HasOwner()) + Owner = Owner->GetOwner(); + + return Owner ? Owner : this; +} + +void Mob::SetOwnerID(uint16 NewOwnerID) { + if (NewOwnerID == GetID() && NewOwnerID != 0) // ok, no charming yourself now =p + return; + ownerid = NewOwnerID; + if (ownerid == 0 && this->IsNPC() && this->GetPetType() != petCharmed) + this->Depop(); +} + +// used in checking for behind (backstab) and checking in front (melee LoS) +float Mob::MobAngle(Mob *other, float ourx, float oury) const { + if (!other || other == this) + return 0.0f; + + float angle, lengthb, vectorx, vectory, dotp; + float mobx = -(other->GetX()); // mob xloc (inverse because eq) + float moby = other->GetY(); // mob yloc + float heading = other->GetHeading(); // mob heading + heading = (heading * 360.0f) / 256.0f; // convert to degrees + if (heading < 270) + heading += 90; + else + heading -= 270; + + heading = heading * 3.1415f / 180.0f; // convert to radians + vectorx = mobx + (10.0f * cosf(heading)); // create a vector based on heading + vectory = moby + (10.0f * sinf(heading)); // of mob length 10 + + // length of mob to player vector + lengthb = (float) sqrtf(((-ourx - mobx) * (-ourx - mobx)) + ((oury - moby) * (oury - moby))); + + // calculate dot product to get angle + // Handle acos domain errors due to floating point rounding errors + dotp = ((vectorx - mobx) * (-ourx - mobx) + + (vectory - moby) * (oury - moby)) / (10 * lengthb); + // I haven't seen any errors that cause problems that weren't slightly + // larger/smaller than 1/-1, so only handle these cases for now + if (dotp > 1) + return 0.0f; + else if (dotp < -1) + return 180.0f; + + angle = acosf(dotp); + angle = angle * 180.0f / 3.1415f; + + return angle; +} + +void Mob::SetZone(uint32 zone_id, uint32 instance_id) +{ + if(IsClient()) + { + CastToClient()->GetPP().zone_id = zone_id; + CastToClient()->GetPP().zoneInstance = instance_id; + } + Save(); +} + +void Mob::Kill() { + Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); +} + +void Mob::SetAttackTimer() { + float PermaHaste; + if(GetHaste() > 0) + PermaHaste = 1 / (1 + (float)GetHaste()/100); + else if(GetHaste() < 0) + PermaHaste = 1 * (1 - (float)GetHaste()/100); + else + PermaHaste = 1.0f; + + //default value for attack timer in case they have + //an invalid weapon equipped: + attack_timer.SetAtTrigger(4000, true); + + Timer* TimerToUse = nullptr; + const Item_Struct* PrimaryWeapon = nullptr; + + for (int i=SLOT_RANGE; i<=SLOT_SECONDARY; i++) { + + //pick a timer + if (i == SLOT_PRIMARY) + TimerToUse = &attack_timer; + else if (i == SLOT_RANGE) + TimerToUse = &ranged_timer; + else if(i == SLOT_SECONDARY) + TimerToUse = &attack_dw_timer; + else //invalid slot (hands will always hit this) + continue; + + const Item_Struct* ItemToUse = nullptr; + + //find our item + if (IsClient()) { + ItemInst* ci = CastToClient()->GetInv().GetItem(i); + if (ci) + ItemToUse = ci->GetItem(); + } else if(IsNPC()) + { + //The code before here was fundementally flawed because equipment[] + //isn't the same as PC inventory and also: + //NPCs don't use weapon speed to dictate how fast they hit anyway. + ItemToUse = nullptr; + } + + //special offhand stuff + if(i == SLOT_SECONDARY) { + //if we have a 2H weapon in our main hand, no dual + if(PrimaryWeapon != nullptr) { + if( PrimaryWeapon->ItemClass == ItemClassCommon + && (PrimaryWeapon->ItemType == ItemType2HSlash + || PrimaryWeapon->ItemType == ItemType2HBlunt + || PrimaryWeapon->ItemType == ItemType2HPiercing)) { + attack_dw_timer.Disable(); + continue; + } + } + + //clients must have the skill to use it... + if(IsClient()) { + //if we cant dual wield, skip it + if (!CanThisClassDualWield()) { + attack_dw_timer.Disable(); + continue; + } + } else { + //NPCs get it for free at 13 + if(GetLevel() < 13) { + attack_dw_timer.Disable(); + continue; + } + } + } + + //see if we have a valid weapon + if(ItemToUse != nullptr) { + //check type and damage/delay + if(ItemToUse->ItemClass != ItemClassCommon + || ItemToUse->Damage == 0 + || ItemToUse->Delay == 0) { + //no weapon + ItemToUse = nullptr; + } + // Check to see if skill is valid + else if((ItemToUse->ItemType > ItemTypeLargeThrowing) && (ItemToUse->ItemType != ItemTypeMartial) && (ItemToUse->ItemType != ItemType2HPiercing)) { + //no weapon + ItemToUse = nullptr; + } + } + + int16 DelayMod = itembonuses.HundredHands + spellbonuses.HundredHands; + if (DelayMod < -99) + DelayMod = -99; + + //if we have no weapon.. + if (ItemToUse == nullptr) { + //above checks ensure ranged weapons do not fall into here + // Work out if we're a monk + if ((GetClass() == MONK) || (GetClass() == BEASTLORD)) { + //we are a monk, use special delay + int speed = (int)( (GetMonkHandToHandDelay()*(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste); + // 1200 seemed too much, with delay 10 weapons available + if(speed < RuleI(Combat, MinHastedDelay)) //lower bound + speed = RuleI(Combat, MinHastedDelay); + TimerToUse->SetAtTrigger(speed, true); // Hand to hand, delay based on level or epic + } else { + //not a monk... using fist, regular delay + int speed = (int)((36 *(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste); + if(speed < RuleI(Combat, MinHastedDelay) && IsClient()) //lower bound + speed = RuleI(Combat, MinHastedDelay); + TimerToUse->SetAtTrigger(speed, true); // Hand to hand, non-monk 2/36 + } + } else { + //we have a weapon, use its delay + // Convert weapon delay to timer resolution (milliseconds) + //delay * 100 + int speed = (int)((ItemToUse->Delay*(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste); + if(speed < RuleI(Combat, MinHastedDelay)) + speed = RuleI(Combat, MinHastedDelay); + + if(ItemToUse && (ItemToUse->ItemType == ItemTypeBow || ItemToUse->ItemType == ItemTypeLargeThrowing)) + { + if(IsClient()) + { + float max_quiver = 0; + for(int r = SLOT_PERSONAL_BEGIN; r <= SLOT_PERSONAL_END; r++) + { + const ItemInst *pi = CastToClient()->GetInv().GetItem(r); + if(!pi) + continue; + if(pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == BagTypeQuiver) + { + float temp_wr = ( pi->GetItem()->BagWR / RuleI(Combat, QuiverWRHasteDiv) ); + if(temp_wr > max_quiver) + { + max_quiver = temp_wr; + } + } + } + if(max_quiver > 0) + { + float quiver_haste = 1 / (1 + max_quiver / 100); + speed *= quiver_haste; + } + } + } + TimerToUse->SetAtTrigger(speed, true); + } + + if(i == SLOT_PRIMARY) + PrimaryWeapon = ItemToUse; + } + +} + +bool Mob::CanThisClassDualWield(void) const { + if(!IsClient()) { + return(GetSkill(SkillDualWield) > 0); + } + else if(CastToClient()->HasSkill(SkillDualWield)) { + const ItemInst* pinst = CastToClient()->GetInv().GetItem(SLOT_PRIMARY); + const ItemInst* sinst = CastToClient()->GetInv().GetItem(SLOT_SECONDARY); + + // 2HS, 2HB, or 2HP + if(pinst && pinst->IsWeapon()) { + const Item_Struct* item = pinst->GetItem(); + + if((item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HPiercing)) + return false; + } + + // OffHand Weapon + if(sinst && !sinst->IsWeapon()) + return false; + + // Dual-Wielding Empty Fists + if(!pinst && !sinst) + if(class_ != MONK && class_ != MONKGM && class_ != BEASTLORD && class_ != BEASTLORDGM) + return false; + + return true; + } + + return false; +} + +bool Mob::CanThisClassDoubleAttack(void) const +{ + if(!IsClient()) { + return(GetSkill(SkillDoubleAttack) > 0); + } else { + if(aabonuses.GiveDoubleAttack || itembonuses.GiveDoubleAttack || spellbonuses.GiveDoubleAttack) { + return true; + } + return(CastToClient()->HasSkill(SkillDoubleAttack)); + } +} + +bool Mob::IsWarriorClass(void) const +{ + switch(GetClass()) + { + case WARRIOR: + case WARRIORGM: + case ROGUE: + case ROGUEGM: + case MONK: + case MONKGM: + case PALADIN: + case PALADINGM: + case SHADOWKNIGHT: + case SHADOWKNIGHTGM: + case RANGER: + case RANGERGM: + case BEASTLORD: + case BEASTLORDGM: + case BERSERKER: + case BERSERKERGM: + case BARD: + case BARDGM: + { + return true; + } + default: + { + return false; + } + } + +} + +bool Mob::CanThisClassParry(void) const +{ + if(!IsClient()) { + return(GetSkill(SkillParry) > 0); + } else { + return(CastToClient()->HasSkill(SkillParry)); + } +} + +bool Mob::CanThisClassDodge(void) const +{ + if(!IsClient()) { + return(GetSkill(SkillDodge) > 0); + } else { + return(CastToClient()->HasSkill(SkillDodge)); + } +} + +bool Mob::CanThisClassRiposte(void) const +{ + if(!IsClient()) { + return(GetSkill(SkillRiposte) > 0); + } else { + return(CastToClient()->HasSkill(SkillRiposte)); + } +} + +bool Mob::CanThisClassBlock(void) const +{ + if(!IsClient()) { + return(GetSkill(SkillBlock) > 0); + } else { + return(CastToClient()->HasSkill(SkillBlock)); + } +} + +float Mob::Dist(const Mob &other) const { + float xDiff = other.x_pos - x_pos; + float yDiff = other.y_pos - y_pos; + float zDiff = other.z_pos - z_pos; + + return sqrtf( (xDiff * xDiff) + + (yDiff * yDiff) + + (zDiff * zDiff) ); +} + +float Mob::DistNoZ(const Mob &other) const { + float xDiff = other.x_pos - x_pos; + float yDiff = other.y_pos - y_pos; + + return sqrtf( (xDiff * xDiff) + + (yDiff * yDiff) ); +} + +float Mob::DistNoRoot(const Mob &other) const { + float xDiff = other.x_pos - x_pos; + float yDiff = other.y_pos - y_pos; + float zDiff = other.z_pos - z_pos; + + return ( (xDiff * xDiff) + + (yDiff * yDiff) + + (zDiff * zDiff) ); +} + +float Mob::DistNoRoot(float x, float y, float z) const { + float xDiff = x - x_pos; + float yDiff = y - y_pos; + float zDiff = z - z_pos; + + return ( (xDiff * xDiff) + + (yDiff * yDiff) + + (zDiff * zDiff) ); +} + +float Mob::DistNoRootNoZ(float x, float y) const { + float xDiff = x - x_pos; + float yDiff = y - y_pos; + + return ( (xDiff * xDiff) + (yDiff * yDiff) ); +} + +float Mob::DistNoRootNoZ(const Mob &other) const { + float xDiff = other.x_pos - x_pos; + float yDiff = other.y_pos - y_pos; + + return ( (xDiff * xDiff) + (yDiff * yDiff) ); +} + +float Mob::GetReciprocalHeading(Mob* target) { + float Result = 0; + + if(target) { + // Convert to radians + float h = (target->GetHeading() / 256.0f) * 6.283184f; + + // Calculate the reciprocal heading in radians + Result = h + 3.141592f; + + // Convert back to eq heading from radians + Result = (Result / 6.283184f) * 256.0f; + } + + return Result; +} + +bool Mob::PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest, bool lookForAftArc) { + bool Result = false; + + if(target) { + float look_heading = 0; + + if(lookForAftArc) + look_heading = GetReciprocalHeading(target); + else + look_heading = target->GetHeading(); + + // Convert to sony heading to radians + look_heading = (look_heading / 256.0f) * 6.283184f; + + float tempX = 0; + float tempY = 0; + float tempZ = 0; + float tempSize = 0; + const float rangeCreepMod = 0.25; + const uint8 maxIterationsAllowed = 4; + uint8 counter = 0; + float rangeReduction= 0; + + tempSize = target->GetSize(); + rangeReduction = (tempSize * rangeCreepMod); + + while(tempSize > 0 && counter != maxIterationsAllowed) { + tempX = GetX() + (tempSize * static_cast(sin(double(look_heading)))); + tempY = GetY() + (tempSize * static_cast(cos(double(look_heading)))); + tempZ = target->GetZ(); + + if(!CheckLosFN(tempX, tempY, tempZ, tempSize)) { + tempSize -= rangeReduction; + } + else { + Result = true; + break; + } + + counter++; + } + + if(!Result) { + // Try to find an attack arc to position at from the opposite direction. + look_heading += (3.141592 / 2); + + tempSize = target->GetSize(); + counter = 0; + + while(tempSize > 0 && counter != maxIterationsAllowed) { + tempX = GetX() + (tempSize * static_cast(sin(double(look_heading)))); + tempY = GetY() + (tempSize * static_cast(cos(double(look_heading)))); + tempZ = target->GetZ(); + + if(!CheckLosFN(tempX, tempY, tempZ, tempSize)) { + tempSize -= rangeReduction; + } + else { + Result = true; + break; + } + + counter++; + } + } + + if(Result) { + x_dest = tempX; + y_dest = tempY; + z_dest = tempZ; + } + } + + return Result; +} + +bool Mob::HateSummon() { + // check if mob has ability to summon + // 97% is the offical % that summoning starts on live, not 94 + // if the mob can summon and is charmed, it can only summon mobs it has LoS to + Mob* mob_owner = nullptr; + if(GetOwnerID()) + mob_owner = entity_list.GetMob(GetOwnerID()); + + int summon_level = GetSpecialAbility(SPECATK_SUMMON); + if(summon_level == 1 || summon_level == 2) { + if(!GetTarget() || (mob_owner && mob_owner->IsClient() && !CheckLosFN(GetTarget()))) { + return false; + } + } else { + //unsupported summon level or OFF + return false; + } + + // validate hp + int hp_ratio = GetSpecialAbilityParam(SPECATK_SUMMON, 1); + hp_ratio = hp_ratio > 0 ? hp_ratio : 97; + if(GetHPRatio() > static_cast(hp_ratio)) { + return false; + } + + // now validate the timer + int summon_timer_duration = GetSpecialAbilityParam(SPECATK_SUMMON, 0); + summon_timer_duration = summon_timer_duration > 0 ? summon_timer_duration : 6000; + Timer *timer = GetSpecialAbilityTimer(SPECATK_SUMMON); + if (!timer) + { + StartSpecialAbilityTimer(SPECATK_SUMMON, summon_timer_duration); + } else { + if(!timer->Check()) + return false; + + timer->Start(summon_timer_duration); + } + + // get summon target + SetTarget(GetHateTop()); + if(target) + { + if(summon_level == 1) { + entity_list.MessageClose(this, true, 500, MT_Say, "%s says,'You will not evade me, %s!' ", GetCleanName(), target->GetCleanName() ); + + if (target->IsClient()) { + target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), x_pos, y_pos, z_pos, target->GetHeading(), 0, SummonPC); + } + else { +#ifdef BOTS + if(target && target->IsBot()) { + // set pre summoning info to return to (to get out of melee range for caster) + target->CastToBot()->SetHasBeenSummoned(true); + target->CastToBot()->SetPreSummonX(target->GetX()); + target->CastToBot()->SetPreSummonY(target->GetY()); + target->CastToBot()->SetPreSummonZ(target->GetZ()); + + } +#endif //BOTS + target->GMMove(x_pos, y_pos, z_pos, target->GetHeading()); + } + + return true; + } else if(summon_level == 2) { + entity_list.MessageClose(this, true, 500, MT_Say, "%s says,'You will not evade me, %s!'", GetCleanName(), target->GetCleanName()); + GMMove(target->GetX(), target->GetY(), target->GetZ()); + } + } + return false; +} + +void Mob::FaceTarget(Mob* MobToFace) { + Mob* facemob = MobToFace; + if(!facemob) { + if(!GetTarget()) { + return; + } + else { + facemob = GetTarget(); + } + } + + float oldheading = GetHeading(); + float newheading = CalculateHeadingToTarget(facemob->GetX(), facemob->GetY()); + if(oldheading != newheading) { + SetHeading(newheading); + if(moving) + SendPosUpdate(); + else + { + SendPosition(); + } + } + + if(IsNPC() && !IsEngaged()) { + CastToNPC()->GetRefaceTimer()->Start(15000); + CastToNPC()->GetRefaceTimer()->Enable(); + } +} + +bool Mob::RemoveFromHateList(Mob* mob) +{ + SetRunAnimSpeed(0); + bool bFound = false; + if(IsEngaged()) + { + bFound = hate_list.RemoveEnt(mob); + if(hate_list.IsEmpty()) + { + AI_Event_NoLongerEngaged(); + zone->DelAggroMob(); + } + } + if(GetTarget() == mob) + { + SetTarget(hate_list.GetTop(this)); + } + + return bFound; +} + +void Mob::WipeHateList() +{ + if(IsEngaged()) + { + hate_list.Wipe(); + AI_Event_NoLongerEngaged(); + } + else + { + hate_list.Wipe(); + } +} + +uint32 Mob::RandomTimer(int min,int max) { + int r = 14000; + if(min != 0 && max != 0 && min < max) + { + r = MakeRandomInt(min, max); + } + return r; +} + +uint32 NPC::GetEquipment(uint8 material_slot) const +{ + if(material_slot > 8) + return 0; + int invslot = Inventory::CalcSlotFromMaterial(material_slot); + if (invslot == -1) + return 0; + return equipment[invslot]; +} + +void Mob::SendWearChange(uint8 material_slot) +{ + EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); + WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; + + wc->spawn_id = GetID(); + wc->material = GetEquipmentMaterial(material_slot); + wc->elite_material = IsEliteMaterialItem(material_slot); + wc->color.color = GetEquipmentColor(material_slot); + wc->wear_slot_id = material_slot; + + entity_list.QueueClients(this, outapp); + safe_delete(outapp); +} + +void Mob::SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model, uint32 elite_material, uint32 unknown06, uint32 unknown18) +{ + EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); + WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; + + wc->spawn_id = this->GetID(); + wc->material = texture; + if (this->IsClient()) + wc->color.color = GetEquipmentColor(slot); + else + wc->color.color = this->GetArmorTint(slot); + wc->wear_slot_id = slot; + + wc->unknown06 = unknown06; + wc->elite_material = elite_material; + wc->hero_forge_model = hero_forge_model; + wc->unknown18 = unknown18; + + + entity_list.QueueClients(this, outapp); + safe_delete(outapp); +} + +void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint) +{ + uint32 color; + color = (red_tint & 0xFF) << 16; + color |= (green_tint & 0xFF) << 8; + color |= (blue_tint & 0xFF); + color |= (color) ? (0xFF << 24) : 0; + armor_tint[material_slot] = color; + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); + WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; + + wc->spawn_id = this->GetID(); + wc->material = GetEquipmentMaterial(material_slot); + wc->color.color = color; + wc->wear_slot_id = material_slot; + + entity_list.QueueClients(this, outapp); + safe_delete(outapp); +} + +void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color) +{ + armor_tint[material_slot] = color; + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); + WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; + + wc->spawn_id = this->GetID(); + wc->material = texture; + wc->color.color = color; + wc->wear_slot_id = material_slot; + + entity_list.QueueClients(this, outapp); + safe_delete(outapp); +} + +int32 Mob::GetEquipmentMaterial(uint8 material_slot) const +{ + const Item_Struct *item; + + item = database.GetItem(GetEquipment(material_slot)); + if(item != 0) + { + if // for primary and secondary we need the model, not the material + ( + material_slot == MaterialPrimary || + material_slot == MaterialSecondary + ) + { + if(strlen(item->IDFile) > 2) + return atoi(&item->IDFile[2]); + else //may as well try this, since were going to 0 anyways + return item->Material; + } + else + { + return item->Material; + } + } + + return 0; +} + +uint32 Mob::GetEquipmentColor(uint8 material_slot) const +{ + const Item_Struct *item; + + item = database.GetItem(GetEquipment(material_slot)); + if(item != 0) + { + return item->Color; + } + + return 0; +} + +uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const +{ + const Item_Struct *item; + + item = database.GetItem(GetEquipment(material_slot)); + if(item != 0) + { + return item->EliteMaterial; + } + + return 0; +} + +// works just like a printf +void Mob::Say(const char *format, ...) +{ + char buf[1000]; + va_list ap; + + va_start(ap, format); + vsnprintf(buf, 1000, format, ap); + va_end(ap); + + Mob* talker = this; + if(spellbonuses.VoiceGraft != 0) { + if(spellbonuses.VoiceGraft == GetPetID()) + talker = entity_list.GetMob(spellbonuses.VoiceGraft); + else + spellbonuses.VoiceGraft = 0; + } + + if(!talker) + talker = this; + + entity_list.MessageClose_StringID(talker, false, 200, 10, + GENERIC_SAY, GetCleanName(), buf); +} + +// +// solar: this is like the above, but the first parameter is a string id +// +void Mob::Say_StringID(uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9) +{ + char string_id_str[10]; + + snprintf(string_id_str, 10, "%d", string_id); + + entity_list.MessageClose_StringID(this, false, 200, 10, + GENERIC_STRINGID_SAY, GetCleanName(), string_id_str, message3, message4, message5, + message6, message7, message8, message9 + ); +} + +void Mob::Say_StringID(uint32 type, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9) +{ + char string_id_str[10]; + + snprintf(string_id_str, 10, "%d", string_id); + + entity_list.MessageClose_StringID(this, false, 200, type, + GENERIC_STRINGID_SAY, GetCleanName(), string_id_str, message3, message4, message5, + message6, message7, message8, message9 + ); +} + +void Mob::Shout(const char *format, ...) +{ + char buf[1000]; + va_list ap; + + va_start(ap, format); + vsnprintf(buf, 1000, format, ap); + va_end(ap); + + entity_list.Message_StringID(this, false, MT_Shout, + GENERIC_SHOUT, GetCleanName(), buf); +} + +void Mob::Emote(const char *format, ...) +{ + char buf[1000]; + va_list ap; + + va_start(ap, format); + vsnprintf(buf, 1000, format, ap); + va_end(ap); + + entity_list.MessageClose_StringID(this, false, 200, 10, + GENERIC_EMOTE, GetCleanName(), buf); +} + +void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str) +{ + entity_list.QuestJournalledSayClose(this, QuestInitiator, 200, GetCleanName(), str); +} + +const char *Mob::GetCleanName() +{ + if(!strlen(clean_name)) + { + CleanMobName(GetName(), clean_name); + } + + return clean_name; +} + +// hp event +void Mob::SetNextHPEvent( int hpevent ) +{ + nexthpevent = hpevent; +} + +void Mob::SetNextIncHPEvent( int inchpevent ) +{ + nextinchpevent = inchpevent; +} +//warp for quest function,from sandy +void Mob::Warp( float x, float y, float z ) +{ + if(IsNPC()) { + entity_list.ProcessMove(CastToNPC(), x, y, z); + } + + x_pos = x; + y_pos = y; + z_pos = z; + + Mob* target = GetTarget(); + if (target) { + FaceTarget( target ); + } + + SendPosition(); +} + +int16 Mob::GetResist(uint8 type) const +{ + if (IsNPC()) + { + if (type == 1) + return MR + spellbonuses.MR + itembonuses.MR; + else if (type == 2) + return FR + spellbonuses.FR + itembonuses.FR; + else if (type == 3) + return CR + spellbonuses.CR + itembonuses.CR; + else if (type == 4) + return PR + spellbonuses.PR + itembonuses.PR; + else if (type == 5) + return DR + spellbonuses.DR + itembonuses.DR; + } + else if (IsClient()) + { + if (type == 1) + return CastToClient()->GetMR(); + else if (type == 2) + return CastToClient()->GetFR(); + else if (type == 3) + return CastToClient()->GetCR(); + else if (type == 4) + return CastToClient()->GetPR(); + else if (type == 5) + return CastToClient()->GetDR(); + } + return 25; +} + +uint32 Mob::GetLevelHP(uint8 tlevel) +{ + //std::cout<<"Tlevel: "<<(int)tlevel<= 60 && casttime > 1000) + { + casttime = casttime / 2; + if (casttime < 1000) + casttime = 1000; + } else if (level >= 50 && casttime > 1000) { + int32 cast_deduction = (casttime*(level - 49))/5; + if (cast_deduction > casttime/2) + casttime /= 2; + else + casttime -= cast_deduction; + } + return(casttime); +} + +void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) { + // Changed proc targets to look up based on the spells goodEffect flag. + // This should work for the majority of weapons. + if(spell_id == SPELL_UNKNOWN || on->GetSpecialAbility(NO_HARM_FROM_CLIENT)) { + //This is so 65535 doesn't get passed to the client message and to logs because it is not relavant information for debugging. + return; + } + + if (IsNoCast()) + return; + + if(!IsValidSpell(spell_id)) { // Check for a valid spell otherwise it will crash through the function + if(IsClient()){ + Message(0, "Invalid spell proc %u", spell_id); + mlog(CLIENT__SPELLS, "Player %s, Weapon Procced invalid spell %u", this->GetName(), spell_id); + } + return; + } + + if(inst && IsClient()) { + //const cast is dirty but it would require redoing a ton of interfaces at this point + //It should be safe as we don't have any truly const ItemInst floating around anywhere. + //So we'll live with it for now + int i = parse->EventItem(EVENT_WEAPON_PROC, CastToClient(), const_cast(inst), on, "", spell_id); + if(i != 0) { + return; + } + } + + bool twinproc = false; + int32 twinproc_chance = 0; + + if(IsClient()) + twinproc_chance = CastToClient()->GetFocusEffect(focusTwincast, spell_id); + + if(twinproc_chance && (MakeRandomInt(0,99) < twinproc_chance)) + twinproc = true; + + if (IsBeneficialSpell(spell_id)) { + SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff, true); + if(twinproc) + SpellOnTarget(spell_id, this, false, false, 0, true); + } + else if(!(on->IsClient() && on->CastToClient()->dead)) { //dont proc on dead clients + SpellFinished(spell_id, on, 10, 0, -1, spells[spell_id].ResistDiff, true); + if(twinproc) + SpellOnTarget(spell_id, on, false, false, 0, true); + } + return; +} + +uint32 Mob::GetZoneID() const { + return(zone->GetZoneID()); +} + +int Mob::GetHaste() { + int h = spellbonuses.haste + spellbonuses.hastetype2; + int cap = 0; + int overhaste = 0; + int level = GetLevel(); + + // 26+ no cap, 1-25 10 + if (level > 25) // 26+ + h += itembonuses.haste; + else // 1-25 + h += itembonuses.haste > 10 ? 10 : itembonuses.haste; + + // 60+ 100, 51-59 85, 1-50 level+25 + if (level > 59) // 60+ + cap = RuleI(Character, HasteCap); + else if (level > 50) // 51-59 + cap = 85; + else // 1-50 + cap = level + 25; + + if(h > cap) + h = cap; + + // 51+ 25 (despite there being higher spells...), 1-50 10 + if (level > 50) // 51+ + overhaste = spellbonuses.hastetype3 > 25 ? 25 : spellbonuses.hastetype3; + else // 1-50 + overhaste = spellbonuses.hastetype3 > 10 ? 10 : spellbonuses.hastetype3; + + h += overhaste; + h += ExtraHaste; //GM granted haste. + + if (spellbonuses.inhibitmelee) { + if (h >= 0) + h -= spellbonuses.inhibitmelee; + else + h -= ((100 + h) * spellbonuses.inhibitmelee / 100); + } + + return(h); +} + +void Mob::SetTarget(Mob* mob) { + if (target == mob) return; + target = mob; + entity_list.UpdateHoTT(this); + if(IsNPC()) + parse->EventNPC(EVENT_TARGET_CHANGE, CastToNPC(), mob, "", 0); + else if (IsClient()) + parse->EventPlayer(EVENT_TARGET_CHANGE, CastToClient(), "", 0); + + if(IsPet() && GetOwner() && GetOwner()->IsClient()) + GetOwner()->CastToClient()->UpdateXTargetType(MyPetTarget, mob); +} + +float Mob::FindGroundZ(float new_x, float new_y, float z_offset) +{ + float ret = -999999; + if (zone->zonemap != nullptr) + { + Map::Vertex me; + me.x = new_x; + me.y = new_y; + me.z = z_pos+z_offset; + Map::Vertex hit; + float best_z = zone->zonemap->FindBestZ(me, &hit); + if (best_z != -999999) + { + ret = best_z; + } + } + return ret; +} + +// Copy of above function that isn't protected to be exported to Perl::Mob +float Mob::GetGroundZ(float new_x, float new_y, float z_offset) +{ + float ret = -999999; + if (zone->zonemap != 0) + { + Map::Vertex me; + me.x = new_x; + me.y = new_y; + me.z = z_pos+z_offset; + Map::Vertex hit; + float best_z = zone->zonemap->FindBestZ(me, &hit); + if (best_z != -999999) + { + ret = best_z; + } + } + return ret; +} + +//helper function for npc AI; needs to be mob:: cause we need to be able to count buffs on other clients and npcs +int Mob::CountDispellableBuffs() +{ + int val = 0; + int buff_count = GetMaxTotalSlots(); + for(int x = 0; x < buff_count; x++) + { + if(!IsValidSpell(buffs[x].spellid)) + continue; + + if(buffs[x].counters) + continue; + + if(spells[buffs[x].spellid].goodEffect == 0) + continue; + + if(buffs[x].spellid != SPELL_UNKNOWN && spells[buffs[x].spellid].buffdurationformula != DF_Permanent) + val++; + } + return val; +} + +// Returns the % that a mob is snared (as a positive value). -1 means not snared +int Mob::GetSnaredAmount() +{ + int worst_snare = -1; + + int buff_count = GetMaxTotalSlots(); + for (int i = 0; i < buff_count; i++) + { + if (!IsValidSpell(buffs[i].spellid)) + continue; + + for(int j = 0; j < EFFECT_COUNT; j++) + { + if (spells[buffs[i].spellid].effectid[j] == SE_MovementSpeed) + { + int val = CalcSpellEffectValue_formula(spells[buffs[i].spellid].formula[j], spells[buffs[i].spellid].base[j], spells[buffs[i].spellid].max[j], buffs[i].casterlevel, buffs[i].spellid); + //int effect = CalcSpellEffectValue(buffs[i].spellid, spells[buffs[i].spellid].effectid[j], buffs[i].casterlevel); + if (val < 0 && abs(val) > worst_snare) + worst_snare = abs(val); + } + } + } + + return worst_snare; +} + +void Mob::TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand, int damage) +{ + if (!on) + return; + + on->TryDefensiveProc(weapon, this, hand, damage); + + //Defensive Skill Procs + if (damage < 0 && damage >= -4) { + uint16 skillinuse = 0; + switch (damage) { + case (-1): + skillinuse = SkillBlock; + break; + + case (-2): + skillinuse = SkillParry; + break; + + case (-3): + skillinuse = SkillRiposte; + break; + + case (-4): + skillinuse = SkillDodge; + break; + } + + if (on->HasSkillProcs()) + on->TrySkillProc(this, skillinuse, 0, false, hand, true); + + if (on->HasSkillProcSuccess()) + on->TrySkillProc(this, skillinuse, 0, true, hand, true); + } +} + +void Mob::SetDeltas(float dx, float dy, float dz, float dh) { + delta_x = dx; + delta_y = dy; + delta_z = dz; + delta_heading = static_cast(dh); +} + +void Mob::SetEntityVariable(const char *id, const char *m_var) +{ + std::string n_m_var = m_var; + m_EntityVariables[id] = n_m_var; +} + +const char* Mob::GetEntityVariable(const char *id) +{ + std::map::iterator iter = m_EntityVariables.find(id); + if(iter != m_EntityVariables.end()) + { + return iter->second.c_str(); + } + return nullptr; +} + +bool Mob::EntityVariableExists(const char *id) +{ + std::map::iterator iter = m_EntityVariables.find(id); + if(iter != m_EntityVariables.end()) + { + return true; + } + return false; +} + +void Mob::SetFlyMode(uint8 flymode) +{ + if(IsClient() && flymode >= 0 && flymode < 3) + { + this->SendAppearancePacket(AT_Levitate, flymode); + } + else if(IsNPC() && flymode >= 0 && flymode <= 3) + { + this->SendAppearancePacket(AT_Levitate, flymode); + this->CastToNPC()->SetFlyMode(flymode); + } +} + +bool Mob::IsNimbusEffectActive(uint32 nimbus_effect) +{ + if(nimbus_effect1 == nimbus_effect || nimbus_effect2 == nimbus_effect || nimbus_effect3 == nimbus_effect) + { + return true; + } + return false; +} + +void Mob::SetNimbusEffect(uint32 nimbus_effect) +{ + if(nimbus_effect1 == 0) + { + nimbus_effect1 = nimbus_effect; + } + else if(nimbus_effect2 == 0) + { + nimbus_effect2 = nimbus_effect; + } + else + { + nimbus_effect3 = nimbus_effect; + } +} + +void Mob::TryTriggerOnCast(uint32 spell_id, bool aa_trigger) +{ + if(!IsValidSpell(spell_id)) + return; + + if (aabonuses.SpellTriggers[0] || spellbonuses.SpellTriggers[0] || itembonuses.SpellTriggers[0]){ + + for(int i = 0; i < MAX_SPELL_TRIGGER; i++){ + + if(aabonuses.SpellTriggers[i] && IsClient()) + TriggerOnCast(aabonuses.SpellTriggers[i], spell_id,1); + + if(spellbonuses.SpellTriggers[i]) + TriggerOnCast(spellbonuses.SpellTriggers[i], spell_id,0); + + if(itembonuses.SpellTriggers[i]) + TriggerOnCast(spellbonuses.SpellTriggers[i], spell_id,0); + } + } +} + + +void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger) +{ + if(!IsValidSpell(focus_spell) || !IsValidSpell(spell_id)) + return; + + uint32 trigger_spell_id = 0; + + if (aa_trigger && IsClient()){ + //focus_spell = aaid + trigger_spell_id = CastToClient()->CalcAAFocus(focusTriggerOnCast, focus_spell, spell_id); + + if(IsValidSpell(trigger_spell_id) && GetTarget()) + SpellFinished(trigger_spell_id, GetTarget(), 10, 0, -1, spells[trigger_spell_id].ResistDiff); + } + + else{ + trigger_spell_id = CalcFocusEffect(focusTriggerOnCast, focus_spell, spell_id); + + if(IsValidSpell(trigger_spell_id) && GetTarget()){ + SpellFinished(trigger_spell_id, GetTarget(),10, 0, -1, spells[trigger_spell_id].ResistDiff); + CheckNumHitsRemaining(NUMHIT_MatchingSpells,0, focus_spell); + } + } +} + +void Mob::TrySpellTrigger(Mob *target, uint32 spell_id) +{ + if(target == nullptr || !IsValidSpell(spell_id)) + { + return; + } + int spell_trig = 0; + // Count all the percentage chances to trigger for all effects + for(int i = 0; i < EFFECT_COUNT; i++) + { + if (spells[spell_id].effectid[i] == SE_SpellTrigger) + spell_trig += spells[spell_id].base[i]; + } + // If all the % add to 100, then only one of the effects can fire but one has to fire. + if (spell_trig == 100) + { + int trig_chance = 100; + for(int i = 0; i < EFFECT_COUNT; i++) + { + if (spells[spell_id].effectid[i] == SE_SpellTrigger) + { + if(MakeRandomInt(0, trig_chance) <= spells[spell_id].base[i]) + { + // If we trigger an effect then its over. + SpellFinished(spells[spell_id].base2[i], target, 10, 0, -1, spells[spell_id].ResistDiff); + break; + } + else + { + // Increase the chance to fire for the next effect, if all effects fail, the final effect will fire. + trig_chance -= spells[spell_id].base[i]; + } + } + + } + } + // if the chances don't add to 100, then each effect gets a chance to fire, chance for no trigger as well. + else + { + for(int i = 0; i < EFFECT_COUNT; i++) + { + if (spells[spell_id].effectid[i] == SE_SpellTrigger) + { + if(MakeRandomInt(0, 100) <= spells[spell_id].base[i]) + { + SpellFinished(spells[spell_id].base2[i], target, 10, 0, -1, spells[spell_id].ResistDiff); + } + } + } + } +} + +void Mob::TryApplyEffect(Mob *target, uint32 spell_id) +{ + if(target == nullptr || !IsValidSpell(spell_id)) + { + return; + } + + for(int i = 0; i < EFFECT_COUNT; i++) + { + if (spells[spell_id].effectid[i] == SE_ApplyEffect) + { + if(MakeRandomInt(0, 100) <= spells[spell_id].base[i]) + { + if(target) + SpellFinished(spells[spell_id].base2[i], target, 10, 0, -1, spells[spell_id].ResistDiff); + } + } + } +} + +void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsPet) +{ + /* + At present time there is no obvious difference between ReqTarget and ReqCaster + ReqTarget is typically used in spells cast on a target where the trigger occurs on that target. + ReqCaster is typically self only spells where the triggers on self. + Regardless both trigger on the owner of the buff. + */ + + /* + Base2 Range: 1004 = Below < 80% HP + Base2 Range: 500-520 = Below (base2 - 500)*5 HP + Base2 Range: 521 = Below (?) Mana UKNOWN - Will assume its 20% unless proven otherwise + Base2 Range: 522 = Below (40%) Endurance + Base2 Range: 523 = Below (40%) Mana + Base2 Range: 220-? = Number of pets on hatelist to trigger (base2 - 220) (Set at 30 pets max for now) + 38311 = < 10% mana; + */ + + if (!spellbonuses.TriggerOnValueAmount) + return; + + if (spellbonuses.TriggerOnValueAmount){ + + int buff_count = GetMaxTotalSlots(); + + for(int e = 0; e < buff_count; e++){ + + uint32 spell_id = buffs[e].spellid; + + if (IsValidSpell(spell_id)){ + + for(int i = 0; i < EFFECT_COUNT; i++){ + + if ((spells[spell_id].effectid[i] == SE_TriggerOnReqTarget) || (spells[spell_id].effectid[i] == SE_TriggerOnReqCaster)) { + + int base2 = spells[spell_id].base2[i]; + bool use_spell = false; + + if (IsHP){ + if ((base2 >= 500 && base2 <= 520) && GetHPRatio() < (base2 - 500)*5) + use_spell = true; + + else if (base2 = 1004 && GetHPRatio() < 80) + use_spell = true; + } + + else if (IsMana){ + if ( (base2 = 521 && GetManaRatio() < 20) || (base2 = 523 && GetManaRatio() < 40)) + use_spell = true; + + else if (base2 = 38311 && GetManaRatio() < 10) + use_spell = true; + } + + else if (IsEndur){ + if (base2 = 522 && GetEndurancePercent() < 40){ + use_spell = true; + } + } + + else if (IsPet){ + int count = hate_list.SummonedPetCount(this); + if ((base2 >= 220 && base2 <= 250) && count >= (base2 - 220)){ + use_spell = true; + } + } + + if (use_spell){ + SpellFinished(spells[spell_id].base[i], this, 10, 0, -1, spells[spell_id].ResistDiff); + + if(!TryFadeEffect(e)) + BuffFadeBySlot(e); + } + } + } + } + } + } +} + + +//Twincast Focus effects should stack across different types (Spell, AA - when implemented ect) +void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id) +{ + if(!IsValidSpell(spell_id)) + return; + + if(IsClient()) + { + int32 focus = CastToClient()->GetFocusEffect(focusTwincast, spell_id); + + if (focus > 0) + { + if(MakeRandomInt(0, 100) <= focus) + { + Message(MT_Spells,"You twincast %s!",spells[spell_id].name); + SpellFinished(spell_id, target, 10, 0, -1, spells[spell_id].ResistDiff); + } + } + } + + //Retains function for non clients + else if (spellbonuses.FocusEffects[focusTwincast] || itembonuses.FocusEffects[focusTwincast]) + { + int buff_count = GetMaxTotalSlots(); + for(int i = 0; i < buff_count; i++) + { + if(IsEffectInSpell(buffs[i].spellid, SE_FcTwincast)) + { + int32 focus = CalcFocusEffect(focusTwincast, buffs[i].spellid, spell_id); + if(focus > 0) + { + if(MakeRandomInt(0, 100) <= focus) + { + SpellFinished(spell_id, target, 10, 0, -1, spells[spell_id].ResistDiff); + } + } + } + } + } +} + +int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining) +{ + if (!IsValidSpell(spell_id)) + return 0; + + if (!caster) + return 0; + + int32 value = 0; + + //Apply innate vulnerabilities + if (Vulnerability_Mod[GetSpellResistType(spell_id)] != 0) + value = Vulnerability_Mod[GetSpellResistType(spell_id)]; + + + else if (Vulnerability_Mod[HIGHEST_RESIST+1] != 0) + value = Vulnerability_Mod[HIGHEST_RESIST+1]; + + //Apply spell derived vulnerabilities + if (spellbonuses.FocusEffects[focusSpellVulnerability]){ + + int32 tmp_focus = 0; + int tmp_buffslot = -1; + + int buff_count = GetMaxTotalSlots(); + for(int i = 0; i < buff_count; i++) { + + if((IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, SE_FcSpellVulnerability))){ + + int32 focus = caster->CalcFocusEffect(focusSpellVulnerability, buffs[i].spellid, spell_id); + + if (!focus) + continue; + + if (tmp_focus && focus > tmp_focus){ + tmp_focus = focus; + tmp_buffslot = i; + } + + else if (!tmp_focus){ + tmp_focus = focus; + tmp_buffslot = i; + } + + } + } + + if (tmp_focus < -99) + tmp_focus = -99; + + value += tmp_focus; + + if (tmp_buffslot >= 0) + CheckNumHitsRemaining(NUMHIT_MatchingSpells, tmp_buffslot); + } + return value; +} + +int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used) +{ + int skilldmg_mod = 0; + + int16 MeleeVuln = spellbonuses.MeleeVulnerability + itembonuses.MeleeVulnerability + aabonuses.MeleeVulnerability; + + // All skill dmg mod + Skill specific + skilldmg_mod += itembonuses.SkillDmgTaken[HIGHEST_SKILL+1] + spellbonuses.SkillDmgTaken[HIGHEST_SKILL+1] + + itembonuses.SkillDmgTaken[skill_used] + spellbonuses.SkillDmgTaken[skill_used]; + + //Innate SetSkillDamgeTaken(skill,value) + if ((SkillDmgTaken_Mod[skill_used]) || (SkillDmgTaken_Mod[HIGHEST_SKILL+1])) + skilldmg_mod += SkillDmgTaken_Mod[skill_used] + SkillDmgTaken_Mod[HIGHEST_SKILL+1]; + + skilldmg_mod += MeleeVuln; + + if(skilldmg_mod < -100) + skilldmg_mod = -100; + + return skilldmg_mod; +} + +int16 Mob::GetHealRate(uint16 spell_id, Mob* caster) { + + int16 heal_rate = 0; + + heal_rate += itembonuses.HealRate + spellbonuses.HealRate + aabonuses.HealRate; + heal_rate += GetFocusIncoming(focusFcHealPctIncoming, SE_FcHealPctIncoming, caster, spell_id); + + if(heal_rate < -99) + heal_rate = -99; + + return heal_rate; +} + +bool Mob::TryFadeEffect(int slot) +{ + if(IsValidSpell(buffs[slot].spellid)) + { + for(int i = 0; i < EFFECT_COUNT; i++) + { + if (spells[buffs[slot].spellid].effectid[i] == SE_CastOnFadeEffectAlways || + spells[buffs[slot].spellid].effectid[i] == SE_CastOnRuneFadeEffect) + { + uint16 spell_id = spells[buffs[slot].spellid].base[i]; + BuffFadeBySlot(slot); + + if(spell_id) + { + + if(spell_id == SPELL_UNKNOWN) + return false; + + if(IsValidSpell(spell_id)) + { + if (IsBeneficialSpell(spell_id)) { + SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff); + } + else if(!(IsClient() && CastToClient()->dead)) { + SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff); + } + return true; + } + } + } + } + } + return false; +} + +void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) +{ + if(target == nullptr || !IsValidSpell(spell_id)) + return; + + int focus_spell = CastToClient()->GetSympatheticFocusEffect(focusSympatheticProc,spell_id); + + if(IsValidSpell(focus_spell)){ + int focus_trigger = spells[focus_spell].base2[0]; + // For beneficial spells, if the triggered spell is also beneficial then proc it on the target + // if the triggered spell is detrimental, then it will trigger on the caster(ie cursed items) + if(IsBeneficialSpell(spell_id)) + { + if(IsBeneficialSpell(focus_trigger)) + SpellFinished(focus_trigger, target); + + else + SpellFinished(focus_trigger, this, 10, 0, -1, spells[focus_trigger].ResistDiff); + } + // For detrimental spells, if the triggered spell is beneficial, then it will land on the caster + // if the triggered spell is also detrimental, then it will land on the target + else + { + if(IsBeneficialSpell(focus_trigger)) + SpellFinished(focus_trigger, this); + + else + SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff); + } + + CheckNumHitsRemaining(NUMHIT_MatchingSpells, 0, focus_spell); + } +} + +uint32 Mob::GetItemStat(uint32 itemid, const char *identifier) +{ + const ItemInst* inst = database.CreateItem(itemid); + if (!inst) + return 0; + + const Item_Struct* item = inst->GetItem(); + if (!item) + return 0; + + if (!identifier) + return 0; + + uint32 stat = 0; + + std::string id = identifier; + for(int i = 0; i < id.length(); ++i) + { + id[i] = tolower(id[i]); + } + + if (id == "itemclass") + stat = uint32(item->ItemClass); + if (id == "id") + stat = uint32(item->ID); + if (id == "weight") + stat = uint32(item->Weight); + if (id == "norent") + stat = uint32(item->NoRent); + if (id == "nodrop") + stat = uint32(item->NoDrop); + if (id == "size") + stat = uint32(item->Size); + if (id == "slots") + stat = uint32(item->Slots); + if (id == "price") + stat = uint32(item->Price); + if (id == "icon") + stat = uint32(item->Icon); + if (id == "loregroup") + stat = uint32(item->LoreGroup); + if (id == "loreflag") + stat = uint32(item->LoreFlag); + if (id == "pendingloreflag") + stat = uint32(item->PendingLoreFlag); + if (id == "artifactflag") + stat = uint32(item->ArtifactFlag); + if (id == "summonedflag") + stat = uint32(item->SummonedFlag); + if (id == "fvnodrop") + stat = uint32(item->FVNoDrop); + if (id == "favor") + stat = uint32(item->Favor); + if (id == "guildfavor") + stat = uint32(item->GuildFavor); + if (id == "pointtype") + stat = uint32(item->PointType); + if (id == "bagtype") + stat = uint32(item->BagType); + if (id == "bagslots") + stat = uint32(item->BagSlots); + if (id == "bagsize") + stat = uint32(item->BagSize); + if (id == "bagwr") + stat = uint32(item->BagWR); + if (id == "benefitflag") + stat = uint32(item->BenefitFlag); + if (id == "tradeskills") + stat = uint32(item->Tradeskills); + if (id == "cr") + stat = uint32(item->CR); + if (id == "dr") + stat = uint32(item->DR); + if (id == "pr") + stat = uint32(item->PR); + if (id == "mr") + stat = uint32(item->MR); + if (id == "fr") + stat = uint32(item->FR); + if (id == "astr") + stat = uint32(item->AStr); + if (id == "asta") + stat = uint32(item->ASta); + if (id == "aagi") + stat = uint32(item->AAgi); + if (id == "adex") + stat = uint32(item->ADex); + if (id == "acha") + stat = uint32(item->ACha); + if (id == "aint") + stat = uint32(item->AInt); + if (id == "awis") + stat = uint32(item->AWis); + if (id == "hp") + stat = uint32(item->HP); + if (id == "mana") + stat = uint32(item->Mana); + if (id == "ac") + stat = uint32(item->AC); + if (id == "deity") + stat = uint32(item->Deity); + if (id == "skillmodvalue") + stat = uint32(item->SkillModValue); + if (id == "skillmodtype") + stat = uint32(item->SkillModType); + if (id == "banedmgrace") + stat = uint32(item->BaneDmgRace); + if (id == "banedmgamt") + stat = uint32(item->BaneDmgAmt); + if (id == "banedmgbody") + stat = uint32(item->BaneDmgBody); + if (id == "magic") + stat = uint32(item->Magic); + if (id == "casttime_") + stat = uint32(item->CastTime_); + if (id == "reqlevel") + stat = uint32(item->ReqLevel); + if (id == "bardtype") + stat = uint32(item->BardType); + if (id == "bardvalue") + stat = uint32(item->BardValue); + if (id == "light") + stat = uint32(item->Light); + if (id == "delay") + stat = uint32(item->Delay); + if (id == "reclevel") + stat = uint32(item->RecLevel); + if (id == "recskill") + stat = uint32(item->RecSkill); + if (id == "elemdmgtype") + stat = uint32(item->ElemDmgType); + if (id == "elemdmgamt") + stat = uint32(item->ElemDmgAmt); + if (id == "range") + stat = uint32(item->Range); + if (id == "damage") + stat = uint32(item->Damage); + if (id == "color") + stat = uint32(item->Color); + if (id == "classes") + stat = uint32(item->Classes); + if (id == "races") + stat = uint32(item->Races); + if (id == "maxcharges") + stat = uint32(item->MaxCharges); + if (id == "itemtype") + stat = uint32(item->ItemType); + if (id == "material") + stat = uint32(item->Material); + if (id == "casttime") + stat = uint32(item->CastTime); + if (id == "elitematerial") + stat = uint32(item->EliteMaterial); + if (id == "procrate") + stat = uint32(item->ProcRate); + if (id == "combateffects") + stat = uint32(item->CombatEffects); + if (id == "shielding") + stat = uint32(item->Shielding); + if (id == "stunresist") + stat = uint32(item->StunResist); + if (id == "strikethrough") + stat = uint32(item->StrikeThrough); + if (id == "extradmgskill") + stat = uint32(item->ExtraDmgSkill); + if (id == "extradmgamt") + stat = uint32(item->ExtraDmgAmt); + if (id == "spellshield") + stat = uint32(item->SpellShield); + if (id == "avoidance") + stat = uint32(item->Avoidance); + if (id == "accuracy") + stat = uint32(item->Accuracy); + if (id == "charmfileid") + stat = uint32(item->CharmFileID); + if (id == "factionmod1") + stat = uint32(item->FactionMod1); + if (id == "factionmod2") + stat = uint32(item->FactionMod2); + if (id == "factionmod3") + stat = uint32(item->FactionMod3); + if (id == "factionmod4") + stat = uint32(item->FactionMod4); + if (id == "factionamt1") + stat = uint32(item->FactionAmt1); + if (id == "factionamt2") + stat = uint32(item->FactionAmt2); + if (id == "factionamt3") + stat = uint32(item->FactionAmt3); + if (id == "factionamt4") + stat = uint32(item->FactionAmt4); + if (id == "augtype") + stat = uint32(item->AugType); + if (id == "ldontheme") + stat = uint32(item->LDoNTheme); + if (id == "ldonprice") + stat = uint32(item->LDoNPrice); + if (id == "ldonsold") + stat = uint32(item->LDoNSold); + if (id == "banedmgraceamt") + stat = uint32(item->BaneDmgRaceAmt); + if (id == "augrestrict") + stat = uint32(item->AugRestrict); + if (id == "endur") + stat = uint32(item->Endur); + if (id == "dotshielding") + stat = uint32(item->DotShielding); + if (id == "attack") + stat = uint32(item->Attack); + if (id == "regen") + stat = uint32(item->Regen); + if (id == "manaregen") + stat = uint32(item->ManaRegen); + if (id == "enduranceregen") + stat = uint32(item->EnduranceRegen); + if (id == "haste") + stat = uint32(item->Haste); + if (id == "damageshield") + stat = uint32(item->DamageShield); + if (id == "recastdelay") + stat = uint32(item->RecastDelay); + if (id == "recasttype") + stat = uint32(item->RecastType); + if (id == "augdistiller") + stat = uint32(item->AugDistiller); + if (id == "attuneable") + stat = uint32(item->Attuneable); + if (id == "nopet") + stat = uint32(item->NoPet); + if (id == "potionbelt") + stat = uint32(item->PotionBelt); + if (id == "stackable") + stat = uint32(item->Stackable); + if (id == "notransfer") + stat = uint32(item->NoTransfer); + if (id == "questitemflag") + stat = uint32(item->QuestItemFlag); + if (id == "stacksize") + stat = uint32(item->StackSize); + if (id == "potionbeltslots") + stat = uint32(item->PotionBeltSlots); + if (id == "book") + stat = uint32(item->Book); + if (id == "booktype") + stat = uint32(item->BookType); + if (id == "svcorruption") + stat = uint32(item->SVCorruption); + if (id == "purity") + stat = uint32(item->Purity); + if (id == "backstabdmg") + stat = uint32(item->BackstabDmg); + if (id == "dsmitigation") + stat = uint32(item->DSMitigation); + if (id == "heroicstr") + stat = uint32(item->HeroicStr); + if (id == "heroicint") + stat = uint32(item->HeroicInt); + if (id == "heroicwis") + stat = uint32(item->HeroicWis); + if (id == "heroicagi") + stat = uint32(item->HeroicAgi); + if (id == "heroicdex") + stat = uint32(item->HeroicDex); + if (id == "heroicsta") + stat = uint32(item->HeroicSta); + if (id == "heroiccha") + stat = uint32(item->HeroicCha); + if (id == "heroicmr") + stat = uint32(item->HeroicMR); + if (id == "heroicfr") + stat = uint32(item->HeroicFR); + if (id == "heroiccr") + stat = uint32(item->HeroicCR); + if (id == "heroicdr") + stat = uint32(item->HeroicDR); + if (id == "heroicpr") + stat = uint32(item->HeroicPR); + if (id == "heroicsvcorrup") + stat = uint32(item->HeroicSVCorrup); + if (id == "healamt") + stat = uint32(item->HealAmt); + if (id == "spelldmg") + stat = uint32(item->SpellDmg); + if (id == "ldonsellbackrate") + stat = uint32(item->LDoNSellBackRate); + if (id == "scriptfileid") + stat = uint32(item->ScriptFileID); + if (id == "expendablearrow") + stat = uint32(item->ExpendableArrow); + if (id == "clairvoyance") + stat = uint32(item->Clairvoyance); + // Begin Effects + if (id == "clickeffect") + stat = uint32(item->Click.Effect); + if (id == "clicktype") + stat = uint32(item->Click.Type); + if (id == "clicklevel") + stat = uint32(item->Click.Level); + if (id == "clicklevel2") + stat = uint32(item->Click.Level2); + if (id == "proceffect") + stat = uint32(item->Proc.Effect); + if (id == "proctype") + stat = uint32(item->Proc.Type); + if (id == "proclevel") + stat = uint32(item->Proc.Level); + if (id == "proclevel2") + stat = uint32(item->Proc.Level2); + if (id == "worneffect") + stat = uint32(item->Worn.Effect); + if (id == "worntype") + stat = uint32(item->Worn.Type); + if (id == "wornlevel") + stat = uint32(item->Worn.Level); + if (id == "wornlevel2") + stat = uint32(item->Worn.Level2); + if (id == "focuseffect") + stat = uint32(item->Focus.Effect); + if (id == "focustype") + stat = uint32(item->Focus.Type); + if (id == "focuslevel") + stat = uint32(item->Focus.Level); + if (id == "focuslevel2") + stat = uint32(item->Focus.Level2); + if (id == "scrolleffect") + stat = uint32(item->Scroll.Effect); + if (id == "scrolltype") + stat = uint32(item->Scroll.Type); + if (id == "scrolllevel") + stat = uint32(item->Scroll.Level); + if (id == "scrolllevel2") + stat = uint32(item->Scroll.Level2); + + safe_delete(inst); + return stat; +} + +void Mob::SetGlobal(const char *varname, const char *newvalue, int options, const char *duration, Mob *other) { + + int qgZoneid = zone->GetZoneID(); + int qgCharid = 0; + int qgNpcid = 0; + + if (this->IsNPC()) + { + qgNpcid = this->GetNPCTypeID(); + } + else if (other && other->IsNPC()) + { + qgNpcid = other->GetNPCTypeID(); + } + + if (this->IsClient()) + { + qgCharid = this->CastToClient()->CharacterID(); + } + else if (other && other->IsClient()) + { + qgCharid = other->CastToClient()->CharacterID(); + } + else + { + qgCharid = -qgNpcid; // make char id negative npc id as a fudge + } + + if (options < 0 || options > 7) + { + //cerr << "Invalid options for global var " << varname << " using defaults" << endl; + options = 0; // default = 0 (only this npcid,player and zone) + } + else + { + if (options & 1) + qgNpcid=0; + if (options & 2) + qgCharid=0; + if (options & 4) + qgZoneid=0; + } + + InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, newvalue, QGVarDuration(duration)); +} + +void Mob::TarGlobal(const char *varname, const char *value, const char *duration, int qgNpcid, int qgCharid, int qgZoneid) +{ + InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, value, QGVarDuration(duration)); +} + +void Mob::DelGlobal(const char *varname) { + // delglobal(varname) + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + int qgZoneid=zone->GetZoneID(); + int qgCharid=0; + int qgNpcid=0; + + if (this->IsNPC()) + { + qgNpcid = this->GetNPCTypeID(); + } + + if (this->IsClient()) + { + qgCharid = this->CastToClient()->CharacterID(); + } + else + { + qgCharid = -qgNpcid; // make char id negative npc id as a fudge + } + + if (!database.RunQuery(query, + MakeAnyLenString(&query, + "DELETE FROM quest_globals WHERE name='%s'" + " && (npcid=0 || npcid=%i) && (charid=0 || charid=%i) && (zoneid=%i || zoneid=0)", + varname,qgNpcid,qgCharid,qgZoneid),errbuf)) + { + //_log(QUESTS, "DelGlobal error deleting %s : %s", varname, errbuf); + } + safe_delete_array(query); + + if(zone) + { + ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); + ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct*)pack->pBuffer; + + qgu->npc_id = qgNpcid; + qgu->char_id = qgCharid; + qgu->zone_id = qgZoneid; + strcpy(qgu->name, varname); + + entity_list.DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); + zone->DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); + + worldserver.SendPacket(pack); + safe_delete(pack); + } +} + +// Inserts global variable into quest_globals table +void Mob::InsertQuestGlobal(int charid, int npcid, int zoneid, const char *varname, const char *varvalue, int duration) { + + char *query = 0; + char errbuf[MYSQL_ERRMSG_SIZE]; + + // Make duration string either "unix_timestamp(now()) + xxx" or "NULL" + std::stringstream duration_ss; + + if (duration == INT_MAX) + { + duration_ss << "NULL"; + } + else + { + duration_ss << "unix_timestamp(now()) + " << duration; + } + + //NOTE: this should be escaping the contents of arglist + //npcwise a malicious script can arbitrarily alter the DB + uint32 last_id = 0; + if (!database.RunQuery(query, MakeAnyLenString(&query, + "REPLACE INTO quest_globals (charid, npcid, zoneid, name, value, expdate)" + "VALUES (%i, %i, %i, '%s', '%s', %s)", + charid, npcid, zoneid, varname, varvalue, duration_ss.str().c_str() + ), errbuf)) + { + //_log(QUESTS, "SelGlobal error inserting %s : %s", varname, errbuf); + } + safe_delete_array(query); + + if(zone) + { + //first delete our global + ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); + ServerQGlobalDelete_Struct *qgd = (ServerQGlobalDelete_Struct*)pack->pBuffer; + qgd->npc_id = npcid; + qgd->char_id = charid; + qgd->zone_id = zoneid; + qgd->from_zone_id = zone->GetZoneID(); + qgd->from_instance_id = zone->GetInstanceID(); + strcpy(qgd->name, varname); + + entity_list.DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); + zone->DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); + + worldserver.SendPacket(pack); + safe_delete(pack); + + //then create a new one with the new id + pack = new ServerPacket(ServerOP_QGlobalUpdate, sizeof(ServerQGlobalUpdate_Struct)); + ServerQGlobalUpdate_Struct *qgu = (ServerQGlobalUpdate_Struct*)pack->pBuffer; + qgu->npc_id = npcid; + qgu->char_id = charid; + qgu->zone_id = zoneid; + if(duration == INT_MAX) + { + qgu->expdate = 0xFFFFFFFF; + } + else + { + qgu->expdate = Timer::GetTimeSeconds() + duration; + } + strcpy((char*)qgu->name, varname); + strcpy((char*)qgu->value, varvalue); + qgu->id = last_id; + qgu->from_zone_id = zone->GetZoneID(); + qgu->from_instance_id = zone->GetInstanceID(); + + QGlobal temp; + temp.npc_id = npcid; + temp.char_id = charid; + temp.zone_id = zoneid; + temp.expdate = qgu->expdate; + temp.name.assign(qgu->name); + temp.value.assign(qgu->value); + entity_list.UpdateQGlobal(qgu->id, temp); + zone->UpdateQGlobal(qgu->id, temp); + + worldserver.SendPacket(pack); + safe_delete(pack); + } + +} + +// Converts duration string to duration value (in seconds) +// Return of INT_MAX indicates infinite duration +int Mob::QGVarDuration(const char *fmt) +{ + int duration = 0; + + // format: Y#### or D## or H## or M## or S## or T###### or C####### + + int len = static_cast(strlen(fmt)); + + // Default to no duration + if (len < 1) + return 0; + + // Set val to value after type character + // e.g., for "M3924", set to 3924 + int val = atoi(&fmt[0] + 1); + + switch (fmt[0]) + { + // Forever + case 'F': + case 'f': + duration = INT_MAX; + break; + // Years + case 'Y': + case 'y': + duration = val * 31556926; + break; + case 'D': + case 'd': + duration = val * 86400; + break; + // Hours + case 'H': + case 'h': + duration = val * 3600; + break; + // Minutes + case 'M': + case 'm': + duration = val * 60; + break; + // Seconds + case 'S': + case 's': + duration = val; + break; + // Invalid + default: + duration = 0; + break; + } + + return duration; +} + +void Mob::DoKnockback(Mob *caster, uint32 pushback, uint32 pushup) +{ + if(IsClient()) + { + CastToClient()->SetKnockBackExemption(true); + + EQApplicationPacket* outapp_push = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp_push->pBuffer; + + double look_heading = caster->CalculateHeadingToTarget(GetX(), GetY()); + look_heading /= 256; + look_heading *= 360; + if(look_heading > 360) + look_heading -= 360; + + //x and y are crossed mkay + double new_x = pushback * sin(double(look_heading * 3.141592 / 180.0)); + double new_y = pushback * cos(double(look_heading * 3.141592 / 180.0)); + + spu->spawn_id = GetID(); + spu->x_pos = FloatToEQ19(GetX()); + spu->y_pos = FloatToEQ19(GetY()); + spu->z_pos = FloatToEQ19(GetZ()); + spu->delta_x = NewFloatToEQ13(static_cast(new_x)); + spu->delta_y = NewFloatToEQ13(static_cast(new_y)); + spu->delta_z = NewFloatToEQ13(static_cast(pushup)); + spu->heading = FloatToEQ19(GetHeading()); + spu->padding0002 =0; + spu->padding0006 =7; + spu->padding0014 =0x7f; + spu->padding0018 =0x5df27; + spu->animation = 0; + spu->delta_heading = NewFloatToEQ13(0); + outapp_push->priority = 6; + entity_list.QueueClients(this, outapp_push, true); + CastToClient()->FastQueuePacket(&outapp_push); + } +} + +void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) +{ + if (spell_id != SPELL_UNKNOWN) + { + if(IsEffectInSpell(spell_id, SE_ProcOnSpellKillShot)) { + for (int i = 0; i < EFFECT_COUNT; i++) { + if (spells[spell_id].effectid[i] == SE_ProcOnSpellKillShot) + { + if (IsValidSpell(spells[spell_id].base2[i]) && spells[spell_id].max[i] <= level) + { + if(MakeRandomInt(0,99) < spells[spell_id].base[i]) + SpellFinished(spells[spell_id].base2[i], this, 10, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); + } + } + } + } + } + + if (!aabonuses.SpellOnKill[0] && !itembonuses.SpellOnKill[0] && !spellbonuses.SpellOnKill[0]) + return; + + // Allow to check AA, items and buffs in all cases. Base2 = Spell to fire | Base1 = % chance | Base3 = min level + for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) { + + if(aabonuses.SpellOnKill[i] && IsValidSpell(aabonuses.SpellOnKill[i]) && (level >= aabonuses.SpellOnKill[i + 2])) { + if(MakeRandomInt(0, 99) < static_cast(aabonuses.SpellOnKill[i + 1])) + SpellFinished(aabonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); + } + + if(itembonuses.SpellOnKill[i] && IsValidSpell(itembonuses.SpellOnKill[i]) && (level >= itembonuses.SpellOnKill[i + 2])){ + if(MakeRandomInt(0, 99) < static_cast(itembonuses.SpellOnKill[i + 1])) + SpellFinished(itembonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); + } + + if(spellbonuses.SpellOnKill[i] && IsValidSpell(spellbonuses.SpellOnKill[i]) && (level >= spellbonuses.SpellOnKill[i + 2])) { + if(MakeRandomInt(0, 99) < static_cast(spellbonuses.SpellOnKill[i + 1])) + SpellFinished(spellbonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); + } + + } +} + +bool Mob::TrySpellOnDeath() +{ + if (IsNPC() && !spellbonuses.SpellOnDeath[0] && !itembonuses.SpellOnDeath[0]) + return false; + + if (IsClient() && !aabonuses.SpellOnDeath[0] && !spellbonuses.SpellOnDeath[0] && !itembonuses.SpellOnDeath[0]) + return false; + + for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) { + if(IsClient() && aabonuses.SpellOnDeath[i] && IsValidSpell(aabonuses.SpellOnDeath[i])) { + if(MakeRandomInt(0, 99) < static_cast(aabonuses.SpellOnDeath[i + 1])) { + SpellFinished(aabonuses.SpellOnDeath[i], this, 10, 0, -1, spells[aabonuses.SpellOnDeath[i]].ResistDiff); + } + } + + if(itembonuses.SpellOnDeath[i] && IsValidSpell(itembonuses.SpellOnDeath[i])) { + if(MakeRandomInt(0, 99) < static_cast(itembonuses.SpellOnDeath[i + 1])) { + SpellFinished(itembonuses.SpellOnDeath[i], this, 10, 0, -1, spells[itembonuses.SpellOnDeath[i]].ResistDiff); + } + } + + if(spellbonuses.SpellOnDeath[i] && IsValidSpell(spellbonuses.SpellOnDeath[i])) { + if(MakeRandomInt(0, 99) < static_cast(spellbonuses.SpellOnDeath[i + 1])) { + SpellFinished(spellbonuses.SpellOnDeath[i], this, 10, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff); + } + } + } + + BuffFadeAll(); + return false; + //You should not be able to use this effect and survive (ALWAYS return false), + //attempting to place a heal in these effects will still result + //in death because the heal will not register before the script kills you. +} + +int16 Mob::GetCritDmgMob(uint16 skill) +{ + int critDmg_mod = 0; + + // All skill dmg mod + Skill specific + critDmg_mod += itembonuses.CritDmgMob[HIGHEST_SKILL+1] + spellbonuses.CritDmgMob[HIGHEST_SKILL+1] + aabonuses.CritDmgMob[HIGHEST_SKILL+1] + + itembonuses.CritDmgMob[skill] + spellbonuses.CritDmgMob[skill] + aabonuses.CritDmgMob[skill]; + + if(critDmg_mod < -100) + critDmg_mod = -100; + + return critDmg_mod; +} + +void Mob::SetGrouped(bool v) +{ + if(v) + { + israidgrouped = false; + } + isgrouped = v; + + if(IsClient()) + { + parse->EventPlayer(EVENT_GROUP_CHANGE, CastToClient(), "", 0); + + if(!v) + CastToClient()->RemoveGroupXTargets(); + } +} + +void Mob::SetRaidGrouped(bool v) +{ + if(v) + { + isgrouped = false; + } + israidgrouped = v; + + if(IsClient()) + { + parse->EventPlayer(EVENT_GROUP_CHANGE, CastToClient(), "", 0); + } +} + +int16 Mob::GetCriticalChanceBonus(uint16 skill) +{ + int critical_chance = 0; + + // All skills + Skill specific + critical_chance += itembonuses.CriticalHitChance[HIGHEST_SKILL+1] + spellbonuses.CriticalHitChance[HIGHEST_SKILL+1] + aabonuses.CriticalHitChance[HIGHEST_SKILL+1] + + itembonuses.CriticalHitChance[skill] + spellbonuses.CriticalHitChance[skill] + aabonuses.CriticalHitChance[skill]; + + if(critical_chance < -100) + critical_chance = -100; + + return critical_chance; +} + +int16 Mob::GetMeleeDamageMod_SE(uint16 skill) +{ + int dmg_mod = 0; + + // All skill dmg mod + Skill specific + dmg_mod += itembonuses.DamageModifier[HIGHEST_SKILL+1] + spellbonuses.DamageModifier[HIGHEST_SKILL+1] + aabonuses.DamageModifier[HIGHEST_SKILL+1] + + itembonuses.DamageModifier[skill] + spellbonuses.DamageModifier[skill] + aabonuses.DamageModifier[skill]; + + dmg_mod += itembonuses.DamageModifier2[HIGHEST_SKILL+1] + spellbonuses.DamageModifier2[HIGHEST_SKILL+1] + aabonuses.DamageModifier2[HIGHEST_SKILL+1] + + itembonuses.DamageModifier2[skill] + spellbonuses.DamageModifier2[skill] + aabonuses.DamageModifier2[skill]; + + if (HasShieldEquiped() && !IsOffHandAtk()) + dmg_mod += itembonuses.ShieldEquipDmgMod[0] + spellbonuses.ShieldEquipDmgMod[0] + aabonuses.ShieldEquipDmgMod[0]; + + if(dmg_mod < -100) + dmg_mod = -100; + + return dmg_mod; +} + +int16 Mob::GetMeleeMinDamageMod_SE(uint16 skill) +{ + int dmg_mod = 0; + + dmg_mod = itembonuses.MinDamageModifier[skill] + spellbonuses.MinDamageModifier[skill] + + itembonuses.MinDamageModifier[HIGHEST_SKILL+1] + spellbonuses.MinDamageModifier[HIGHEST_SKILL+1]; + + if(dmg_mod < -100) + dmg_mod = -100; + + return dmg_mod; +} + +int16 Mob::GetCrippBlowChance() +{ + int16 crip_chance = 0; + + crip_chance += itembonuses.CrippBlowChance + spellbonuses.CrippBlowChance + aabonuses.CrippBlowChance; + + if(crip_chance < 0) + crip_chance = 0; + + return crip_chance; +} + +int16 Mob::GetSkillReuseTime(uint16 skill) +{ + int skill_reduction = this->itembonuses.SkillReuseTime[skill] + this->spellbonuses.SkillReuseTime[skill] + this->aabonuses.SkillReuseTime[skill]; + + return skill_reduction; +} + +int16 Mob::GetSkillDmgAmt(uint16 skill) +{ + int skill_dmg = 0; + + // All skill dmg(only spells do this) + Skill specific + skill_dmg += spellbonuses.SkillDamageAmount[HIGHEST_SKILL+1] + itembonuses.SkillDamageAmount[HIGHEST_SKILL+1] + aabonuses.SkillDamageAmount[HIGHEST_SKILL+1] + + itembonuses.SkillDamageAmount[skill] + spellbonuses.SkillDamageAmount[skill] + aabonuses.SkillDamageAmount[skill]; + + skill_dmg += spellbonuses.SkillDamageAmount2[HIGHEST_SKILL+1] + itembonuses.SkillDamageAmount2[HIGHEST_SKILL+1] + + itembonuses.SkillDamageAmount2[skill] + spellbonuses.SkillDamageAmount2[skill]; + + return skill_dmg; +} + +void Mob::MeleeLifeTap(int32 damage) { + + int16 lifetap_amt = 0; + lifetap_amt = spellbonuses.MeleeLifetap + itembonuses.MeleeLifetap + aabonuses.MeleeLifetap + + spellbonuses.Vampirism + itembonuses.Vampirism + aabonuses.Vampirism; + + if(lifetap_amt && damage > 0){ + + lifetap_amt = damage * lifetap_amt / 100; + mlog(COMBAT__DAMAGE, "Melee lifetap healing for %d damage.", damage); + + if (lifetap_amt > 0) + HealDamage(lifetap_amt); //Heal self for modified damage amount. + else + Damage(this, -lifetap_amt,0, SkillEvocation,false); //Dmg self for modified damage amount. + } +} + +bool Mob::TryReflectSpell(uint32 spell_id) +{ + if (!spells[spell_id].reflectable) + return false; + + int chance = itembonuses.reflect_chance + spellbonuses.reflect_chance + aabonuses.reflect_chance; + + if(chance && MakeRandomInt(0, 99) < chance) + return true; + + return false; +} + +void Mob::SpellProjectileEffect() +{ + bool time_disable = false; + + for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { + + if (projectile_increment[i] == 0){ + continue; + } + + Mob* target = entity_list.GetMobID(projectile_target_id[i]); + + float dist = 0; + + if (target) + dist = target->CalculateDistance(projectile_x[i], projectile_y[i], projectile_z[i]); + + int increment_end = 0; + increment_end = (dist / 10) - 1; //This pretty accurately determines end time for speed for 1.5 and timer of 250 ms + + if (increment_end <= projectile_increment[i]){ + + if (target && IsValidSpell(projectile_spell_id[i])) + SpellOnTarget(projectile_spell_id[i], target, false, true, spells[projectile_spell_id[i]].ResistDiff, true); + + projectile_spell_id[i] = 0; + projectile_target_id[i] = 0; + projectile_x[i] = 0, projectile_y[i] = 0, projectile_z[i] = 0; + projectile_increment[i] = 0; + time_disable = true; + } + + else { + projectile_increment[i]++; + time_disable = false; + } + } + + if (time_disable) + projectile_timer.Disable(); +} + + +void Mob::DoGravityEffect() +{ + Mob *caster = nullptr; + int away = -1; + float caster_x, caster_y, amount, value, cur_x, my_x, cur_y, my_y, x_vector, y_vector, hypot; + + // Set values so we can run through all gravity effects and then apply the culmative move at the end + // instead of many small moves if the mob/client had more than 1 gravity effect on them + cur_x = my_x = GetX(); + cur_y = my_y = GetY(); + + int buff_count = GetMaxTotalSlots(); + for (int slot = 0; slot < buff_count; slot++) + { + if (buffs[slot].spellid != SPELL_UNKNOWN && IsEffectInSpell(buffs[slot].spellid, SE_GravityEffect)) + { + for (int i = 0; i < EFFECT_COUNT; i++) + { + if(spells[buffs[slot].spellid].effectid[i] == SE_GravityEffect) { + + int casterId = buffs[slot].casterid; + if(casterId) + caster = entity_list.GetMob(casterId); + + if(!caster || casterId == this->GetID()) + continue; + + caster_x = caster->GetX(); + caster_y = caster->GetY(); + + value = static_cast(spells[buffs[slot].spellid].base[i]); + if(value == 0) + continue; + + if(value > 0) + away = 1; + + amount = fabs(value) / (100.0f); // to bring the values in line, arbitarily picked + + x_vector = cur_x - caster_x; + y_vector = cur_y - caster_y; + hypot = sqrt(x_vector*x_vector + y_vector*y_vector); + + if(hypot <= 5) // dont want to be inside the mob, even though we can, it looks bad + continue; + + x_vector /= hypot; + y_vector /= hypot; + + cur_x = cur_x + (x_vector * amount * away); + cur_y = cur_y + (y_vector * amount * away); + } + } + } + } + + if((fabs(my_x - cur_x) > 0.01) || (fabs(my_y - cur_y) > 0.01)) { + float new_ground = GetGroundZ(cur_x, cur_y); + // If we cant get LoS on our new spot then keep checking up to 5 units up. + if(!CheckLosFN(cur_x, cur_y, new_ground, GetSize())) { + for(float z_adjust = 0.1f; z_adjust < 5; z_adjust += 0.1f) { + if(CheckLosFN(cur_x, cur_y, new_ground+z_adjust, GetSize())) { + new_ground += z_adjust; + break; + } + } + // If we still fail, then lets only use the x portion(ie sliding around a wall) + if(!CheckLosFN(cur_x, my_y, new_ground, GetSize())) { + // If that doesnt work, try the y + if(!CheckLosFN(my_x, cur_y, new_ground, GetSize())) { + // If everything fails, then lets do nothing + return; + } + else { + cur_x = my_x; + } + } + else { + cur_y = my_y; + } + } + + if(IsClient()) + this->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), cur_x, cur_y, new_ground, GetHeading()*2); // I know the heading thing is weird(chance of movepc to halve the heading value, too lazy to figure out why atm) + else + this->GMMove(cur_x, cur_y, new_ground, GetHeading()); + } +} + +void Mob::SpreadVirus(uint16 spell_id, uint16 casterID) +{ + int num_targs = spells[spell_id].viral_targets; + + Mob* caster = entity_list.GetMob(casterID); + Mob* target = nullptr; + // Only spread in zones without perm buffs + if(!zone->BuffTimersSuspended()) { + for(int i = 0; i < num_targs; i++) { + target = entity_list.GetTargetForVirus(this); + if(target) { + // Only spreads to the uninfected + if(!target->FindBuff(spell_id)) { + if(caster) + caster->SpellOnTarget(spell_id, target); + + } + } + } + } +} + +void Mob::RemoveNimbusEffect(int effectid) +{ + EQApplicationPacket* outapp = new EQApplicationPacket(OP_RemoveNimbusEffect, sizeof(RemoveNimbusEffect_Struct)); + RemoveNimbusEffect_Struct* rne = (RemoveNimbusEffect_Struct*)outapp->pBuffer; + rne->spawnid = GetID(); + rne->nimbus_effect = effectid; + entity_list.QueueClients(this, outapp); + safe_delete(outapp); +} + +bool Mob::IsBoat() const { + return (race == 72 || race == 73 || race == 114 || race == 404 || race == 550 || race == 551 || race == 552); +} + +void Mob::SetBodyType(bodyType new_body, bool overwrite_orig) { + bool needs_spawn_packet = false; + if(bodytype == 11 || bodytype >= 65 || new_body == 11 || new_body >= 65) { + needs_spawn_packet = true; + } + + if(overwrite_orig) { + orig_bodytype = new_body; + } + bodytype = new_body; + + if(needs_spawn_packet) { + EQApplicationPacket* app = new EQApplicationPacket; + CreateDespawnPacket(app, true); + entity_list.QueueClients(this, app); + CreateSpawnPacket(app, this); + entity_list.QueueClients(this, app); + safe_delete(app); + } +} + + +void Mob::ModSkillDmgTaken(SkillUseTypes skill_num, int value) +{ + if (skill_num <= HIGHEST_SKILL) + SkillDmgTaken_Mod[skill_num] = value; + + + else if (skill_num == 255 || skill_num == -1) + SkillDmgTaken_Mod[HIGHEST_SKILL+1] = value; +} + +int16 Mob::GetModSkillDmgTaken(const SkillUseTypes skill_num) +{ + if (skill_num <= HIGHEST_SKILL) + return SkillDmgTaken_Mod[skill_num]; + + else if (skill_num == 255 || skill_num == -1) + return SkillDmgTaken_Mod[HIGHEST_SKILL+1]; + + return 0; +} + +void Mob::ModVulnerability(uint8 resist, int16 value) +{ + if (resist < HIGHEST_RESIST+1) + Vulnerability_Mod[resist] = value; + + else if (resist == 255) + Vulnerability_Mod[HIGHEST_RESIST+1] = value; +} + +int16 Mob::GetModVulnerability(const uint8 resist) +{ + if (resist < HIGHEST_RESIST+1) + return Vulnerability_Mod[resist]; + + else if (resist == 255) + return Vulnerability_Mod[HIGHEST_RESIST+1]; + + return 0; +} + +void Mob::CastOnCurer(uint32 spell_id) +{ + for(int i = 0; i < EFFECT_COUNT; i++) + { + if (spells[spell_id].effectid[i] == SE_CastOnCurer) + { + if(IsValidSpell(spells[spell_id].base[i])) + { + SpellFinished(spells[spell_id].base[i], this); + } + } + } +} + +void Mob::CastOnCure(uint32 spell_id) +{ + for(int i = 0; i < EFFECT_COUNT; i++) + { + if (spells[spell_id].effectid[i] == SE_CastOnCure) + { + if(IsValidSpell(spells[spell_id].base[i])) + { + SpellFinished(spells[spell_id].base[i], this); + } + } + } +} + +void Mob::CastOnNumHitFade(uint32 spell_id) +{ + if(!IsValidSpell(spell_id)) + return; + + for(int i = 0; i < EFFECT_COUNT; i++) + { + if (spells[spell_id].effectid[i] == SE_CastonNumHitFade) + { + if(IsValidSpell(spells[spell_id].base[i])) + { + SpellFinished(spells[spell_id].base[i], this); + } + } + } +} + +void Mob::SlowMitigation(Mob* caster) +{ + if (GetSlowMitigation() && caster && caster->IsClient()) + { + if ((GetSlowMitigation() > 0) && (GetSlowMitigation() < 26)) + caster->Message_StringID(MT_SpellFailure, SLOW_MOSTLY_SUCCESSFUL); + + else if ((GetSlowMitigation() >= 26) && (GetSlowMitigation() < 74)) + caster->Message_StringID(MT_SpellFailure, SLOW_PARTIALLY_SUCCESSFUL); + + else if ((GetSlowMitigation() >= 74) && (GetSlowMitigation() < 101)) + caster->Message_StringID(MT_SpellFailure, SLOW_SLIGHTLY_SUCCESSFUL); + + else if (GetSlowMitigation() > 100) + caster->Message_StringID(MT_SpellFailure, SPELL_OPPOSITE_EFFECT); + } +} + +uint16 Mob::GetSkillByItemType(int ItemType) +{ + switch (ItemType) + { + case ItemType1HSlash: + return Skill1HSlashing; + case ItemType2HSlash: + return Skill2HSlashing; + case ItemType1HPiercing: + return Skill1HPiercing; + case ItemType1HBlunt: + return Skill1HBlunt; + case ItemType2HBlunt: + return Skill2HBlunt; + case ItemType2HPiercing: + return Skill1HPiercing; // change to 2HPiercing once activated + case ItemTypeMartial: + return SkillHandtoHand; + default: + return SkillHandtoHand; + } + return SkillHandtoHand; + } + + +bool Mob::PassLimitToSkill(uint16 spell_id, uint16 skill) { + + if (!IsValidSpell(spell_id)) + return false; + + for (int i = 0; i < EFFECT_COUNT; i++) { + if (spells[spell_id].effectid[i] == SE_LimitToSkill){ + if (spells[spell_id].base[i] == skill){ + return true; + } + } + } + return false; +} + +uint16 Mob::GetWeaponSpeedbyHand(uint16 hand) { + + uint16 weapon_speed = 0; + switch (hand) { + + case 13: + weapon_speed = attack_timer.GetDuration(); + break; + case 14: + weapon_speed = attack_dw_timer.GetDuration(); + break; + case 11: + weapon_speed = ranged_timer.GetDuration(); + break; + } + + if (weapon_speed < RuleI(Combat, MinHastedDelay)) + weapon_speed = RuleI(Combat, MinHastedDelay); + + return weapon_speed; +} + +int8 Mob::GetDecayEffectValue(uint16 spell_id, uint16 spelleffect) { + + if (!IsValidSpell(spell_id)) + return false; + + int spell_level = spells[spell_id].classes[(GetClass()%16) - 1]; + int effect_value = 0; + int lvlModifier = 100; + + int buff_count = GetMaxTotalSlots(); + for (int slot = 0; slot < buff_count; slot++){ + if (IsValidSpell(buffs[slot].spellid)){ + for (int i = 0; i < EFFECT_COUNT; i++){ + if(spells[buffs[slot].spellid].effectid[i] == spelleffect) { + + int critchance = spells[buffs[slot].spellid].base[i]; + int decay = spells[buffs[slot].spellid].base2[i]; + int lvldiff = spell_level - spells[buffs[slot].spellid].max[i]; + + if(lvldiff > 0 && decay > 0) + { + lvlModifier -= decay*lvldiff; + if (lvlModifier > 0){ + critchance = (critchance*lvlModifier)/100; + effect_value += critchance; + } + } + + else + effect_value += critchance; + } + } + } + } + + return effect_value; +} + +// Faction Mods for Alliance type spells +void Mob::AddFactionBonus(uint32 pFactionID,int32 bonus) { + std::map :: const_iterator faction_bonus; + typedef std::pair NewFactionBonus; + + faction_bonus = faction_bonuses.find(pFactionID); + if(faction_bonus == faction_bonuses.end()) + { + faction_bonuses.insert(NewFactionBonus(pFactionID,bonus)); + } + else + { + if(faction_bonus->second :: const_iterator faction_bonus; + typedef std::pair NewFactionBonus; + + faction_bonus = item_faction_bonuses.find(pFactionID); + if(faction_bonus == item_faction_bonuses.end()) + { + item_faction_bonuses.insert(NewFactionBonus(pFactionID,bonus)); + } + else + { + if((bonus > 0 && faction_bonus->second < bonus) || (bonus < 0 && faction_bonus->second > bonus)) + { + item_faction_bonuses.erase(pFactionID); + item_faction_bonuses.insert(NewFactionBonus(pFactionID,bonus)); + } + } +} + +int32 Mob::GetFactionBonus(uint32 pFactionID) { + std::map :: const_iterator faction_bonus; + faction_bonus = faction_bonuses.find(pFactionID); + if(faction_bonus != faction_bonuses.end()) + { + return (*faction_bonus).second; + } + return 0; +} + +int32 Mob::GetItemFactionBonus(uint32 pFactionID) { + std::map :: const_iterator faction_bonus; + faction_bonus = item_faction_bonuses.find(pFactionID); + if(faction_bonus != item_faction_bonuses.end()) + { + return (*faction_bonus).second; + } + return 0; +} + +void Mob::ClearItemFactionBonuses() { + item_faction_bonuses.clear(); +} + +FACTION_VALUE Mob::GetSpecialFactionCon(Mob* iOther) { + if (!iOther) + return FACTION_INDIFFERENT; + + iOther = iOther->GetOwnerOrSelf(); + Mob* self = this->GetOwnerOrSelf(); + + bool selfAIcontrolled = self->IsAIControlled(); + bool iOtherAIControlled = iOther->IsAIControlled(); + int selfPrimaryFaction = self->GetPrimaryFaction(); + int iOtherPrimaryFaction = iOther->GetPrimaryFaction(); + + if (selfPrimaryFaction >= 0 && selfAIcontrolled) + return FACTION_INDIFFERENT; + if (iOther->GetPrimaryFaction() >= 0) + return FACTION_INDIFFERENT; +/* special values: + -2 = indiff to player, ally to AI on special values, indiff to AI + -3 = dub to player, ally to AI on special values, indiff to AI + -4 = atk to player, ally to AI on special values, indiff to AI + -5 = indiff to player, indiff to AI + -6 = dub to player, indiff to AI + -7 = atk to player, indiff to AI + -8 = indiff to players, ally to AI on same value, indiff to AI + -9 = dub to players, ally to AI on same value, indiff to AI + -10 = atk to players, ally to AI on same value, indiff to AI + -11 = indiff to players, ally to AI on same value, atk to AI + -12 = dub to players, ally to AI on same value, atk to AI + -13 = atk to players, ally to AI on same value, atk to AI +*/ + switch (iOtherPrimaryFaction) { + case -2: // -2 = indiff to player, ally to AI on special values, indiff to AI + if (selfAIcontrolled && iOtherAIControlled) + return FACTION_ALLY; + else + return FACTION_INDIFFERENT; + case -3: // -3 = dub to player, ally to AI on special values, indiff to AI + if (selfAIcontrolled && iOtherAIControlled) + return FACTION_ALLY; + else + return FACTION_DUBIOUS; + case -4: // -4 = atk to player, ally to AI on special values, indiff to AI + if (selfAIcontrolled && iOtherAIControlled) + return FACTION_ALLY; + else + return FACTION_SCOWLS; + case -5: // -5 = indiff to player, indiff to AI + return FACTION_INDIFFERENT; + case -6: // -6 = dub to player, indiff to AI + if (selfAIcontrolled && iOtherAIControlled) + return FACTION_INDIFFERENT; + else + return FACTION_DUBIOUS; + case -7: // -7 = atk to player, indiff to AI + if (selfAIcontrolled && iOtherAIControlled) + return FACTION_INDIFFERENT; + else + return FACTION_SCOWLS; + case -8: // -8 = indiff to players, ally to AI on same value, indiff to AI + if (selfAIcontrolled && iOtherAIControlled) { + if (selfPrimaryFaction == iOtherPrimaryFaction) + return FACTION_ALLY; + else + return FACTION_INDIFFERENT; + } + else + return FACTION_INDIFFERENT; + case -9: // -9 = dub to players, ally to AI on same value, indiff to AI + if (selfAIcontrolled && iOtherAIControlled) { + if (selfPrimaryFaction == iOtherPrimaryFaction) + return FACTION_ALLY; + else + return FACTION_INDIFFERENT; + } + else + return FACTION_DUBIOUS; + case -10: // -10 = atk to players, ally to AI on same value, indiff to AI + if (selfAIcontrolled && iOtherAIControlled) { + if (selfPrimaryFaction == iOtherPrimaryFaction) + return FACTION_ALLY; + else + return FACTION_INDIFFERENT; + } + else + return FACTION_SCOWLS; + case -11: // -11 = indiff to players, ally to AI on same value, atk to AI + if (selfAIcontrolled && iOtherAIControlled) { + if (selfPrimaryFaction == iOtherPrimaryFaction) + return FACTION_ALLY; + else + return FACTION_SCOWLS; + } + else + return FACTION_INDIFFERENT; + case -12: // -12 = dub to players, ally to AI on same value, atk to AI + if (selfAIcontrolled && iOtherAIControlled) { + if (selfPrimaryFaction == iOtherPrimaryFaction) + return FACTION_ALLY; + else + return FACTION_SCOWLS; + + + } + else + return FACTION_DUBIOUS; + case -13: // -13 = atk to players, ally to AI on same value, atk to AI + if (selfAIcontrolled && iOtherAIControlled) { + if (selfPrimaryFaction == iOtherPrimaryFaction) + return FACTION_ALLY; + else + return FACTION_SCOWLS; + } + else + return FACTION_SCOWLS; + default: + return FACTION_INDIFFERENT; + } +} + +bool Mob::HasSpellEffect(int effectid) +{ + int i; + + uint32 buff_count = GetMaxTotalSlots(); + for(i = 0; i < buff_count; i++) + { + if(buffs[i].spellid == SPELL_UNKNOWN) { continue; } + + if(IsEffectInSpell(buffs[i].spellid, effectid)) + { + return(1); + } + } + return(0); +} + +int Mob::GetSpecialAbility(int ability) { + if(ability >= MAX_SPECIAL_ATTACK || ability < 0) { + return 0; + } + + return SpecialAbilities[ability].level; +} + +int Mob::GetSpecialAbilityParam(int ability, int param) { + if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0 || ability >= MAX_SPECIAL_ATTACK || ability < 0) { + return 0; + } + + return SpecialAbilities[ability].params[param]; +} + +void Mob::SetSpecialAbility(int ability, int level) { + if(ability >= MAX_SPECIAL_ATTACK || ability < 0) { + return; + } + + SpecialAbilities[ability].level = level; +} + +void Mob::SetSpecialAbilityParam(int ability, int param, int value) { + if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0 || ability >= MAX_SPECIAL_ATTACK || ability < 0) { + return; + } + + SpecialAbilities[ability].params[param] = value; +} + +void Mob::StartSpecialAbilityTimer(int ability, uint32 time) { + if (ability >= MAX_SPECIAL_ATTACK || ability < 0) { + return; + } + + if(SpecialAbilities[ability].timer) { + SpecialAbilities[ability].timer->Start(time); + } else { + SpecialAbilities[ability].timer = new Timer(time); + SpecialAbilities[ability].timer->Start(); + } +} + +void Mob::StopSpecialAbilityTimer(int ability) { + if (ability >= MAX_SPECIAL_ATTACK || ability < 0) { + return; + } + + safe_delete(SpecialAbilities[ability].timer); +} + +Timer *Mob::GetSpecialAbilityTimer(int ability) { + if (ability >= MAX_SPECIAL_ATTACK || ability < 0) { + return nullptr; + } + + return SpecialAbilities[ability].timer; +} + +void Mob::ClearSpecialAbilities() { + for(int a = 0; a < MAX_SPECIAL_ATTACK; ++a) { + SpecialAbilities[a].level = 0; + safe_delete(SpecialAbilities[a].timer); + for(int p = 0; p < MAX_SPECIAL_ATTACK_PARAMS; ++p) { + SpecialAbilities[a].params[p] = 0; + } + } +} + +void Mob::ProcessSpecialAbilities(const std::string str) { + ClearSpecialAbilities(); + + std::vector sp = SplitString(str, '^'); + for(auto iter = sp.begin(); iter != sp.end(); ++iter) { + std::vector sub_sp = SplitString((*iter), ','); + if(sub_sp.size() >= 2) { + int ability = std::stoi(sub_sp[0]); + int value = std::stoi(sub_sp[1]); + + SetSpecialAbility(ability, value); + switch(ability) { + case SPECATK_QUAD: + if(value > 0) { + SetSpecialAbility(SPECATK_TRIPLE, 1); + } + break; + case DESTRUCTIBLE_OBJECT: + if(value == 0) { + SetDestructibleObject(false); + } else { + SetDestructibleObject(true); + } + break; + default: + break; + } + + for(size_t i = 2, p = 0; i < sub_sp.size(); ++i, ++p) { + if(p >= MAX_SPECIAL_ATTACK_PARAMS) { + break; + } + + SetSpecialAbilityParam(ability, p, std::stoi(sub_sp[i])); + } + } + } +} + +// derived from client to keep these functions more consistent +// if anything seems weird, blame SoE +bool Mob::IsFacingMob(Mob *other) +{ + if (!other) + return false; + float angle = HeadingAngleToMob(other); + // what the client uses appears to be 2x our internal heading + float heading = GetHeading() * 2.0; + + if (angle > 472.0 && heading < 40.0) + angle = heading; + if (angle < 40.0 && heading > 472.0) + angle = heading; + + if (fabs(angle - heading) <= 80.0) + return true; + + return false; +} + +// All numbers derived from the client +float Mob::HeadingAngleToMob(Mob *other) +{ + float mob_x = other->GetX(); + float mob_y = other->GetY(); + float this_x = GetX(); + float this_y = GetY(); + + float y_diff = fabs(this_y - mob_y); + float x_diff = fabs(this_x - mob_x); + if (y_diff < 0.0000009999999974752427) + y_diff = 0.0000009999999974752427; + + float angle = atan2(x_diff, y_diff) * 180.0 * 0.3183099014828645; // angle, nice "pi" + + // return the right thing based on relative quadrant + // I'm sure this could be improved for readability, but whatever + if (this_y >= mob_y) { + if (mob_x >= this_x) + return (90.0 - angle + 90.0) * 511.5 * 0.0027777778; + if (mob_x <= this_x) + return (angle + 180.0) * 511.5 * 0.0027777778; + } + if (this_y > mob_y || mob_x > this_x) + return angle * 511.5 * 0.0027777778; + else + return (90.0 - angle + 270.0) * 511.5 * 0.0027777778; +} + diff --git a/zone/mobx.h b/zone/mobx.h new file mode 100644 index 000000000..4cd6d5f49 --- /dev/null +++ b/zone/mobx.h @@ -0,0 +1,1236 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef MOB_H +#define MOB_H + +#include "../common/features.h" +#include "common.h" +#include "entity.h" +#include "hate_list.h" +#include "pathing.h" +#include +#include +#include + +char* strn0cpy(char* dest, const char* source, uint32 size); + +#define MAX_SPECIAL_ATTACK_PARAMS 8 + +class EGNode; +class MobFearState; +class Mob : public Entity { +public: + enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD, + CLIENT_KICKED, DISCONNECTED, CLIENT_ERROR, CLIENT_CONNECTINGALL }; + enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard }; + + struct SpecialAbility { + SpecialAbility() { + level = 0; + timer = nullptr; + for(int i = 0; i < MAX_SPECIAL_ATTACK_PARAMS; ++i) { + params[i] = 0; + } + } + + ~SpecialAbility() { + safe_delete(timer); + } + + int level; + Timer *timer; + int params[MAX_SPECIAL_ATTACK_PARAMS]; + }; + + Mob(const char* in_name, + const char* in_lastname, + int32 in_cur_hp, + int32 in_max_hp, + uint8 in_gender, + uint16 in_race, + uint8 in_class, + bodyType in_bodytype, + uint8 in_deity, + uint8 in_level, + uint32 in_npctype_id, + float in_size, + float in_runspeed, + float in_heading, + float in_x_pos, + float in_y_pos, + float in_z_pos, + uint8 in_light, + uint8 in_texture, + uint8 in_helmtexture, + uint16 in_ac, + uint16 in_atk, + uint16 in_str, + uint16 in_sta, + uint16 in_dex, + uint16 in_agi, + uint16 in_int, + uint16 in_wis, + uint16 in_cha, + uint8 in_haircolor, + uint8 in_beardcolor, + uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye? + uint8 in_eyecolor2, + uint8 in_hairstyle, + uint8 in_luclinface, + uint8 in_beard, + uint32 in_drakkin_heritage, + uint32 in_drakkin_tattoo, + uint32 in_drakkin_details, + uint32 in_armor_tint[_MaterialCount], + uint8 in_aa_title, + uint8 in_see_invis, // see through invis + uint8 in_see_invis_undead, // see through invis vs. undead + uint8 in_see_hide, + uint8 in_see_improved_hide, + int32 in_hp_regen, + int32 in_mana_regen, + uint8 in_qglobal, + uint8 in_maxlevel, + uint32 in_scalerate + ); + virtual ~Mob(); + + inline virtual bool IsMob() const { return true; } + inline virtual bool InZone() const { return true; } + + //Somewhat sorted: needs documenting! + + //Attack + virtual void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10); + virtual void RogueAssassinate(Mob* other); // solar + float MobAngle(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const; + // greater than 90 is behind + inline bool BehindMob(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const + { return (!other || other == this) ? true : MobAngle(other, ourx, oury) > 90.0f; } + // less than 56 is in front, greater than 56 is usually where the client generates the messages + inline bool InFrontMob(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const + { return (!other || other == this) ? true : MobAngle(other, ourx, oury) < 56.0f; } + bool IsFacingMob(Mob *other); // kind of does the same as InFrontMob, but derived from client + float HeadingAngleToMob(Mob *other); // to keep consistent with client generated messages + virtual void RangedAttack(Mob* other) { } + virtual void ThrowingAttack(Mob* other) { } + uint16 GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg); + // 13 = Primary (default), 14 = secondary + virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = false, + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) = 0; + int MonkSpecialAttack(Mob* other, uint8 skill_used); + virtual void TryBackstab(Mob *other,int ReuseTime = 10); + void TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand = 13, int damage = 0); + virtual bool AvoidDamage(Mob* attacker, int32 &damage, bool CanRiposte = true); + virtual bool CheckHitChance(Mob* attacker, SkillUseTypes skillinuse, int Hand, int16 chance_mod = 0); + virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts = nullptr); + void TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage); + virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse); + uint32 TryHeadShot(Mob* defender, SkillUseTypes skillInUse); + uint32 TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 ReuseTime); + virtual void DoRiposte(Mob* defender); + void ApplyMeleeDamageBonus(uint16 skill, int32 &damage); + virtual void MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts = nullptr); + virtual int32 GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating); + bool CombatRange(Mob* other); + virtual inline bool IsBerserk() { return false; } // only clients + void RogueEvade(Mob *other); + + //Appearance + void SendLevelAppearance(); + void SendStunAppearance(); + void SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, + Client *specific_target=nullptr); + void SendTargetable(bool on, Client *specific_target = nullptr); + virtual void SendWearChange(uint8 material_slot); + virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, + uint32 unknown06 = 0, uint32 unknown18 = 0); + virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint); + virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color); + void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone); + void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0, + float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr); + void ChangeSize(float in_size, bool bNoRestriction = false); + inline uint8 SeeInvisible() const { return see_invis; } + inline bool SeeInvisibleUndead() const { return see_invis_undead; } + inline bool SeeHide() const { return see_hide; } + inline bool SeeImprovedHide() const { return see_improved_hide; } + bool IsInvisible(Mob* other = 0) const; + void SetInvisible(uint8 state); + bool AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* weapon); + + //Song + bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1); + bool ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, uint16 slot); + void BardPulse(uint16 spell_id, Mob *caster); + + //Spell + void SendSpellEffect(uint32 effectid, uint32 duration, uint32 finish_delay, bool zone_wide, + uint32 unk020, bool perm_effect = false, Client *c = nullptr); + bool IsBeneficialAllowed(Mob *target); + virtual int GetCasterLevel(uint16 spell_id); + void ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterID = 0, + bool item_bonus = false, uint32 ticsremaining = 0, int buffslot = -1, + bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0); + void NegateSpellsBonuses(uint16 spell_id); + virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false) { return range;} + virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr) { return value; } + virtual int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr) { return value; } + virtual int32 GetActSpellCost(uint16 spell_id, int32 cost){ return cost;} + virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration){ return duration;} + virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime); + float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false, + int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false); + int ResistPhysical(int level_diff, uint8 caster_level); + uint16 GetSpecializeSkillValue(uint16 spell_id) const; + void SendSpellBarDisable(); + void SendSpellBarEnable(uint16 spellid); + void ZeroCastingVars(); + virtual void SpellProcess(); + virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, + int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, + uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 *resist_adjust = nullptr); + virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, + int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, + uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 resist_adjust = 0); + void CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, uint16 mana_used, + uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0); + bool SpellFinished(uint16 spell_id, Mob *target, uint16 slot = 10, uint16 mana_used = 0, + uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false); + virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect = false, + bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false); + virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100); + virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, + CastAction_type &CastAction); + virtual bool CheckFizzle(uint16 spell_id); + virtual bool CheckSpellLevelRestriction(uint16 spell_id); + virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); + virtual float GetAOERange(uint16 spell_id); + void InterruptSpell(uint16 spellid = SPELL_UNKNOWN); + void InterruptSpell(uint16, uint16, uint16 spellid = SPELL_UNKNOWN); + inline bool IsCasting() const { return((casting_spell_id != 0)); } + uint16 CastingSpellID() const { return casting_spell_id; } + bool DoCastingChecks(); + bool TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier); + void SpellProjectileEffect(); + bool TrySpellProjectile(Mob* spell_target, uint16 spell_id); + void ResourceTap(int32 damage, uint16 spell_id); + void TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker); + bool CheckSpellCategory(uint16 spell_id, int category_id, int effect_id); + + + //Buff + void BuffProcess(); + virtual void DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0); + void BuffFadeBySpellID(uint16 spell_id); + void BuffFadeByEffect(int effectid, int skipslot = -1); + void BuffFadeAll(); + void BuffFadeNonPersistDeath(); + void BuffFadeDetrimental(); + void BuffFadeBySlot(int slot, bool iRecalcBonuses = true); + void BuffFadeDetrimentalByCaster(Mob *caster); + void BuffFadeBySitModifier(); + void BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration); + int AddBuff(Mob *caster, const uint16 spell_id, int duration = 0, int32 level_override = -1); + int CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite = false); + int CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caster_level_override = -1); + void SendPetBuffsToClient(); + virtual int GetCurrentBuffSlots() const { return 0; } + virtual int GetCurrentSongSlots() const { return 0; } + virtual int GetCurrentDiscSlots() const { return 0; } + virtual int GetMaxBuffSlots() const { return 0; } + virtual int GetMaxSongSlots() const { return 0; } + virtual int GetMaxDiscSlots() const { return 0; } + virtual int GetMaxTotalSlots() const { return 0; } + virtual void InitializeBuffSlots() { buffs = nullptr; current_buff_count = 0; } + virtual void UninitializeBuffSlots() { } + EQApplicationPacket *MakeBuffsPacket(bool for_target = true); + void SendBuffsToClient(Client *c); + inline Buffs_Struct* GetBuffs() { return buffs; } + void DoGravityEffect(); + void DamageShield(Mob* other, bool spell_ds = false); + int32 RuneAbsorb(int32 damage, uint16 type); + bool FindBuff(uint16 spellid); + bool FindType(uint16 type, bool bOffensive = false, uint16 threshold = 100); + int16 GetBuffSlotFromType(uint16 type); + uint16 GetSpellIDFromSlot(uint8 slot); + int CountDispellableBuffs(); + void CheckNumHitsRemaining(uint8 type, uint32 buff_slot=0, uint16 spell_id=SPELL_UNKNOWN); + bool HasNumhits() const { return has_numhits; } + inline void Numhits(bool val) { has_numhits = val; } + bool HasMGB() const { return has_MGB; } + inline void SetMGB(bool val) { has_MGB = val; } + bool HasProjectIllusion() const { return has_ProjectIllusion ; } + inline void SetProjectIllusion(bool val) { has_ProjectIllusion = val; } + void SpreadVirus(uint16 spell_id, uint16 casterID); + bool IsNimbusEffectActive(uint32 nimbus_effect); + void SetNimbusEffect(uint32 nimbus_effect); + inline virtual uint32 GetNimbusEffect1() const { return nimbus_effect1; } + inline virtual uint32 GetNimbusEffect2() const { return nimbus_effect2; } + inline virtual uint32 GetNimbusEffect3() const { return nimbus_effect3; } + void RemoveNimbusEffect(int effectid); + + //Basic Stats/Inventory + virtual void SetLevel(uint8 in_level, bool command = false) { level = in_level; } + void TempName(const char *newname = nullptr); + void SetTargetable(bool on); + bool IsTargetable() const { return m_targetable; } + bool HasShieldEquiped() const { return has_shieldequiped; } + inline void ShieldEquiped(bool val) { has_shieldequiped = val; } + virtual uint16 GetSkill(SkillUseTypes skill_num) const { return 0; } + virtual uint32 GetEquipment(uint8 material_slot) const { return(0); } + virtual int32 GetEquipmentMaterial(uint8 material_slot) const; + virtual uint32 GetEquipmentColor(uint8 material_slot) const; + virtual uint32 IsEliteMaterialItem(uint8 material_slot) const; + bool AffectedBySpellExcludingSlot(int slot, int effect); + virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) = 0; + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, + bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) = 0; + inline virtual void SetHP(int32 hp) { if (hp >= max_hp) cur_hp = max_hp; else cur_hp = hp;} + bool ChangeHP(Mob* other, int32 amount, uint16 spell_id = 0, int8 buffslot = -1, bool iBuffTic = false); + inline void SetOOCRegen(int32 newoocregen) {oocregen = newoocregen;} + virtual void Heal(); + virtual void HealDamage(uint32 ammount, Mob* caster = nullptr, uint16 spell_id = SPELL_UNKNOWN); + virtual void SetMaxHP() { cur_hp = max_hp; } + virtual inline uint16 GetBaseRace() const { return base_race; } + virtual inline uint8 GetBaseGender() const { return base_gender; } + virtual inline uint16 GetDeity() const { return deity; } + inline uint16 GetRace() const { return race; } + inline uint8 GetGender() const { return gender; } + inline uint8 GetTexture() const { return texture; } + inline uint8 GetHelmTexture() const { return helmtexture; } + inline uint8 GetHairColor() const { return haircolor; } + inline uint8 GetBeardColor() const { return beardcolor; } + inline uint8 GetEyeColor1() const { return eyecolor1; } + inline uint8 GetEyeColor2() const { return eyecolor2; } + inline uint8 GetHairStyle() const { return hairstyle; } + inline uint8 GetLuclinFace() const { return luclinface; } + inline uint8 GetBeard() const { return beard; } + inline uint8 GetDrakkinHeritage() const { return drakkin_heritage; } + inline uint8 GetDrakkinTattoo() const { return drakkin_tattoo; } + inline uint8 GetDrakkinDetails() const { return drakkin_details; } + inline uint32 GetArmorTint(uint8 i) const { return armor_tint[(i < _MaterialCount) ? i : 0]; } + inline uint8 GetClass() const { return class_; } + inline uint8 GetLevel() const { return level; } + inline uint8 GetOrigLevel() const { return orig_level; } + inline const char* GetName() const { return name; } + inline const char* GetOrigName() const { return orig_name; } + inline const char* GetLastName() const { return lastname; } + const char *GetCleanName(); + virtual void SetName(const char *new_name = nullptr) { new_name ? strn0cpy(name, new_name, 64) : + strn0cpy(name, GetName(), 64); return; }; + inline Mob* GetTarget() const { return target; } + virtual void SetTarget(Mob* mob); + virtual inline float GetHPRatio() const { return max_hp == 0 ? 0 : ((float)cur_hp/max_hp*100); } + inline virtual int16 GetAC() const { return AC + itembonuses.AC + spellbonuses.AC; } + inline virtual int16 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK; } + inline virtual int16 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } + inline virtual int16 GetSTR() const { return STR + itembonuses.STR + spellbonuses.STR; } + inline virtual int16 GetSTA() const { return STA + itembonuses.STA + spellbonuses.STA; } + inline virtual int16 GetDEX() const { return DEX + itembonuses.DEX + spellbonuses.DEX; } + inline virtual int16 GetAGI() const { return AGI + itembonuses.AGI + spellbonuses.AGI; } + inline virtual int16 GetINT() const { return INT + itembonuses.INT + spellbonuses.INT; } + inline virtual int16 GetWIS() const { return WIS + itembonuses.WIS + spellbonuses.WIS; } + inline virtual int16 GetCHA() const { return CHA + itembonuses.CHA + spellbonuses.CHA; } + inline virtual int16 GetMR() const { return MR + itembonuses.MR + spellbonuses.MR; } + inline virtual int16 GetFR() const { return FR + itembonuses.FR + spellbonuses.FR; } + inline virtual int16 GetDR() const { return DR + itembonuses.DR + spellbonuses.DR; } + inline virtual int16 GetPR() const { return PR + itembonuses.PR + spellbonuses.PR; } + inline virtual int16 GetCR() const { return CR + itembonuses.CR + spellbonuses.CR; } + inline virtual int16 GetCorrup() const { return Corrup + itembonuses.Corrup + spellbonuses.Corrup; } + inline virtual int16 GetPhR() const { return PhR; } + inline StatBonuses GetItemBonuses() const { return itembonuses; } + inline StatBonuses GetSpellBonuses() const { return spellbonuses; } + inline StatBonuses GetAABonuses() const { return aabonuses; } + inline virtual int16 GetMaxSTR() const { return GetSTR(); } + inline virtual int16 GetMaxSTA() const { return GetSTA(); } + inline virtual int16 GetMaxDEX() const { return GetDEX(); } + inline virtual int16 GetMaxAGI() const { return GetAGI(); } + inline virtual int16 GetMaxINT() const { return GetINT(); } + inline virtual int16 GetMaxWIS() const { return GetWIS(); } + inline virtual int16 GetMaxCHA() const { return GetCHA(); } + inline virtual int16 GetMaxMR() const { return 255; } + inline virtual int16 GetMaxPR() const { return 255; } + inline virtual int16 GetMaxDR() const { return 255; } + inline virtual int16 GetMaxCR() const { return 255; } + inline virtual int16 GetMaxFR() const { return 255; } + inline virtual int16 GetDelayDeath() const { return 0; } + inline int32 GetHP() const { return cur_hp; } + inline int32 GetMaxHP() const { return max_hp; } + virtual int32 CalcMaxHP(); + inline int32 GetMaxMana() const { return max_mana; } + inline int32 GetMana() const { return cur_mana; } + int32 GetItemHPBonuses(); + int32 GetSpellHPBonuses(); + virtual const int32& SetMana(int32 amount); + inline float GetManaRatio() const { return max_mana == 0 ? 100 : + ((static_cast(cur_mana) / max_mana) * 100); } + virtual int32 CalcMaxMana(); + uint32 GetNPCTypeID() const { return npctype_id; } + inline const float GetX() const { return x_pos; } + inline const float GetY() const { return y_pos; } + inline const float GetZ() const { return z_pos; } + inline const float GetHeading() const { return heading; } + inline const float GetSize() const { return size; } + inline const float GetBaseSize() const { return base_size; } + inline const float GetTarX() const { return tarx; } + inline const float GetTarY() const { return tary; } + inline const float GetTarZ() const { return tarz; } + inline const float GetTarVX() const { return tar_vx; } + inline const float GetTarVY() const { return tar_vy; } + inline const float GetTarVZ() const { return tar_vz; } + inline const float GetTarVector() const { return tar_vector; } + inline const uint8 GetTarNDX() const { return tar_ndx; } + bool IsBoat() const; + + //Group + virtual bool HasRaid() = 0; + virtual bool HasGroup() = 0; + virtual Raid* GetRaid() = 0; + virtual Group* GetGroup() = 0; + + //Faction + virtual inline int32 GetPrimaryFaction() const { return 0; } + + //Movement + void Warp( float x, float y, float z ); + inline bool IsMoving() const { return moving; } + virtual void SetMoving(bool move) { moving = move; delta_x = 0; delta_y = 0; delta_z = 0; delta_heading = 0; } + virtual void GoToBind(uint8 bindnum = 0) { } + virtual void Gate(); + float GetWalkspeed() const { return(_GetMovementSpeed(-47)); } + float GetRunspeed() const { return(_GetMovementSpeed(0)); } + float GetBaseRunspeed() const { return runspeed; } + float GetMovespeed() const { return IsRunning() ? GetRunspeed() : GetWalkspeed(); } + bool IsRunning() const { return m_is_running; } + void SetRunning(bool val) { m_is_running = val; } + virtual void GMMove(float x, float y, float z, float heading = 0.01, bool SendUpdate = true); + void SetDeltas(float delta_x, float delta_y, float delta_z, float delta_h); + void SetTargetDestSteps(uint8 target_steps) { tar_ndx = target_steps; } + void SendPosUpdate(uint8 iSendToSelf = 0); + void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu); + void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu); + void SendPosition(); + void SetFlyMode(uint8 flymode); + inline void Teleport(Map::Vertex NewPosition) { x_pos = NewPosition.x; y_pos = NewPosition.y; + z_pos = NewPosition.z; }; + + //AI + static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel); + inline uint32 GetLevelCon(uint8 iOtherLevel) const { + return this ? GetLevelCon(GetLevel(), iOtherLevel) : CON_GREEN; } + virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true, + bool bFrenzy = false, bool iBuffTic = false); + bool RemoveFromHateList(Mob* mob); + void SetHate(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.Set(other,hate,damage);} + void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHate(other, (in_hate > 1 ? in_hate / 2 : 1)); } + void DoubleAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHate(other, (in_hate ? in_hate * 2 : 1)); } + uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHate(tmob,is_dam);} + uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHate(tmob, true);} + Mob* GetHateTop() { return hate_list.GetTop(this);} + Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTop(other);} + Mob* GetHateRandom() { return hate_list.GetRandom();} + Mob* GetHateMost() { return hate_list.GetMostHate();} + bool IsEngaged() { return(!hate_list.IsEmpty()); } + bool HateSummon(); + void FaceTarget(Mob* MobToFace = 0); + void SetHeading(float iHeading) { if(heading != iHeading) { pLastChange = Timer::GetCurrentTime(); + heading = iHeading; } } + void WipeHateList(); + void AddFeignMemory(Client* attacker); + void RemoveFromFeignMemory(Client* attacker); + void ClearFeignMemory(); + void PrintHateListToClient(Client *who) { hate_list.PrintToClient(who); } + std::list& GetHateList() { return hate_list.GetHateList(); } + bool CheckLosFN(Mob* other); + bool CheckLosFN(float posX, float posY, float posZ, float mobSize); + inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); } + inline const uint32 LastChange() const { return pLastChange; } + + //Quest + void QuestReward(Client *c = nullptr, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0); + void CameraEffect(uint32 duration, uint32 intensity, Client *c = nullptr, bool global = false); + inline bool GetQglobal() const { return qglobal; } + + //Other Packet + void CreateDespawnPacket(EQApplicationPacket* app, bool Decay); + void CreateHorseSpawnPacket(EQApplicationPacket* app, const char* ownername, uint16 ownerid, Mob* ForWho = 0); + void CreateSpawnPacket(EQApplicationPacket* app, Mob* ForWho = 0); + static void CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns); + virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); + void CreateHPPacket(EQApplicationPacket* app); + void SendHPUpdate(); + + //Util + static uint32 RandomTimer(int min, int max); + static uint8 GetDefaultGender(uint16 in_race, uint8 in_gender = 0xFF); + uint16 GetSkillByItemType(int ItemType); + virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr); + virtual void MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, const char *petname = nullptr, float in_size = 0.0f); + bool IsWarriorClass() const; + char GetCasterClass() const; + uint8 GetArchetype() const; + void SetZone(uint32 zone_id, uint32 instance_id); + void ShowStats(Client* client); + void ShowBuffs(Client* client); + void ShowBuffList(Client* client); + float Dist(const Mob &) const; + float DistNoZ(const Mob &) const; + float DistNoRoot(const Mob &) const; + float DistNoRoot(float x, float y, float z) const; + float DistNoRootNoZ(float x, float y) const; + float DistNoRootNoZ(const Mob &) const; + static float GetReciprocalHeading(Mob* target); + bool PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest, + bool lookForAftArc = true); + + //Procs + bool AddRangedProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); + bool RemoveRangedProc(uint16 spell_id, bool bAll = false); + bool HasRangedProcs() const; + bool AddDefensiveProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); + bool RemoveDefensiveProc(uint16 spell_id, bool bAll = false); + bool HasDefensiveProcs() const; + bool HasSkillProcs() const; + bool HasSkillProcSuccess() const; + bool AddProcToWeapon(uint16 spell_id, bool bPerma = false, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); + bool RemoveProcFromWeapon(uint16 spell_id, bool bAll = false); + bool HasProcs() const; + bool IsCombatProc(uint16 spell_id); + + //Logging + bool IsLoggingEnabled() const { return(logging_enabled); } + void EnableLogging() { logging_enabled = true; } + void DisableLogging() { logging_enabled = false; } + + + //More stuff to sort: + virtual bool IsAttackAllowed(Mob *target, bool isSpellAttack = false); + bool IsTargeted() const { return (targeted > 0); } + inline void IsTargeted(int in_tar) { targeted += in_tar; if(targeted < 0) targeted = 0;} + void SetFollowID(uint32 id) { follow = id; } + void SetFollowDistance(uint32 dist) { follow_dist = dist; } + uint32 GetFollowID() const { return follow; } + uint32 GetFollowDistance() const { return follow_dist; } + + virtual void Message(uint32 type, const char* message, ...) { } + virtual void Message_StringID(uint32 type, uint32 string_id, uint32 distance = 0) { } + virtual void Message_StringID(uint32 type, uint32 string_id, const char* message, const char* message2 = 0, + const char* message3 = 0, const char* message4 = 0, const char* message5 = 0, const char* message6 = 0, + const char* message7 = 0, const char* message8 = 0, const char* message9 = 0, uint32 distance = 0) { } + virtual void FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType filter, uint32 string_id) { } + virtual void FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType filter, + uint32 string_id, const char *message1, const char *message2 = nullptr, + const char *message3 = nullptr, const char *message4 = nullptr, + const char *message5 = nullptr, const char *message6 = nullptr, + const char *message7 = nullptr, const char *message8 = nullptr, + const char *message9 = nullptr) { } + void Say(const char *format, ...); + void Say_StringID(uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0, + const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); + void Say_StringID(uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0, + const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); + void Shout(const char *format, ...); + void Emote(const char *format, ...); + void QuestJournalledSay(Client *QuestInitiator, const char *str); + uint32 GetItemStat(uint32 itemid, const char *identifier); + + int16 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false); + uint8 IsFocusEffect(uint16 spellid, int effect_index, bool AA=false,uint32 aa_effect=0); + void SendIllusionPacket(uint16 in_race, uint8 in_gender = 0xFF, uint8 in_texture = 0xFF, uint8 in_helmtexture = 0xFF, + uint8 in_haircolor = 0xFF, uint8 in_beardcolor = 0xFF, uint8 in_eyecolor1 = 0xFF, uint8 in_eyecolor2 = 0xFF, + uint8 in_hairstyle = 0xFF, uint8 in_luclinface = 0xFF, uint8 in_beard = 0xFF, uint8 in_aa_title = 0xFF, + uint32 in_drakkin_heritage = 0xFFFFFFFF, uint32 in_drakkin_tattoo = 0xFFFFFFFF, + uint32 in_drakkin_details = 0xFFFFFFFF, float in_size = 0xFFFFFFFF); + virtual void Stun(int duration); + virtual void UnStun(); + inline void Silence(bool newval) { silenced = newval; } + inline void Amnesia(bool newval) { amnesiad = newval; } + void TemporaryPets(uint16 spell_id, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0); + void TypesTemporaryPets(uint32 typesid, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0, bool followme = false); + void WakeTheDead(uint16 spell_id, Mob *target, uint32 duration); + void Spin(); + void Kill(); + bool PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id); + bool TryDeathSave(); + bool TryDivineSave(); + void DoBuffWearOffEffect(uint32 index); + void TryTriggerOnCast(uint32 spell_id, bool aa_trigger); + void TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger); + void TrySpellTrigger(Mob *target, uint32 spell_id); + void TryApplyEffect(Mob *target, uint32 spell_id); + void TryTriggerOnValueAmount(bool IsHP = false, bool IsMana = false, bool IsEndur = false, bool IsPet = false); + void TryTwincast(Mob *caster, Mob *target, uint32 spell_id); + void TrySympatheticProc(Mob *target, uint32 spell_id); + bool TryFadeEffect(int slot); + uint16 GetSpellEffectResistChance(uint16 spell_id); + int16 GetHealRate(uint16 spell_id, Mob* caster = nullptr); + int32 GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining); + int32 GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill = false, uint16 skill=0); + int32 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id); + int16 GetSkillDmgTaken(const SkillUseTypes skill_used); + void DoKnockback(Mob *caster, uint32 pushback, uint32 pushup); + int16 CalcResistChanceBonus(); + int16 CalcFearResistChance(); + void TrySpellOnKill(uint8 level, uint16 spell_id); + bool TrySpellOnDeath(); + void CastOnCurer(uint32 spell_id); + void CastOnCure(uint32 spell_id); + void CastOnNumHitFade(uint32 spell_id); + void SlowMitigation(Mob* caster); + int16 GetCritDmgMob(uint16 skill); + int16 GetMeleeDamageMod_SE(uint16 skill); + int16 GetMeleeMinDamageMod_SE(uint16 skill); + int16 GetCrippBlowChance(); + int16 GetSkillReuseTime(uint16 skill); + int16 GetCriticalChanceBonus(uint16 skill); + int16 GetSkillDmgAmt(uint16 skill); + bool TryReflectSpell(uint32 spell_id); + bool CanBlockSpell() const { return(spellbonuses.BlockNextSpell); } + bool DoHPToManaCovert(uint16 mana_cost = 0); + int32 ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard = false); + int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect); + int32 GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg); + void MeleeLifeTap(int32 damage); + bool PassCastRestriction(bool UseCastRestriction = true, int16 value = 0, bool IsDamage = true); + bool ImprovedTaunt(); + bool TryRootFadeByDamage(int buffslot, Mob* attacker); + int16 GetSlowMitigation() const {return slow_mitigation;} + + void ModSkillDmgTaken(SkillUseTypes skill_num, int value); + int16 GetModSkillDmgTaken(const SkillUseTypes skill_num); + void ModVulnerability(uint8 resist, int16 value); + int16 GetModVulnerability(const uint8 resist); + + void SetAllowBeneficial(bool value) { m_AllowBeneficial = value; } + bool GetAllowBeneficial() { if (m_AllowBeneficial || GetSpecialAbility(ALLOW_BENEFICIAL)){return true;} return false; } + void SetDisableMelee(bool value) { m_DisableMelee = value; } + bool IsMeleeDisabled() { if (m_DisableMelee || GetSpecialAbility(DISABLE_MELEE)){return true;} return false; } + + bool IsOffHandAtk() const { return offhand; } + inline void OffHandAtk(bool val) { offhand = val; } + + void SetFlurryChance(uint8 value) { SetSpecialAbilityParam(SPECATK_FLURRY, 0, value); } + uint8 GetFlurryChance() { return GetSpecialAbilityParam(SPECATK_FLURRY, 0); } + + static uint32 GetAppearanceValue(EmuAppearance iAppearance); + void SendAppearancePacket(uint32 type, uint32 value, bool WholeZone = true, bool iIgnoreSelf = false, Client *specific_target=nullptr); + void SetAppearance(EmuAppearance app, bool iIgnoreSelf = true); + inline EmuAppearance GetAppearance() const { return _appearance; } + inline const uint8 GetRunAnimSpeed() const { return pRunAnimSpeed; } + inline void SetRunAnimSpeed(int8 in) { if (pRunAnimSpeed != in) { pRunAnimSpeed = in; pLastChange = Timer::GetCurrentTime(); } } + bool IsDestructibleObject() { return destructibleobject; } + void SetDestructibleObject(bool in) { destructibleobject = in; } + + Mob* GetPet(); + void SetPet(Mob* newpet); + virtual Mob* GetOwner(); + virtual Mob* GetOwnerOrSelf(); + Mob* GetUltimateOwner(); + void SetPetID(uint16 NewPetID); + inline uint16 GetPetID() const { return petid; } + inline PetType GetPetType() const { return typeofpet; } + void SetPetType(PetType p) { typeofpet = p; } + inline int16 GetPetPower() const { return (petpower < 0) ? 0 : petpower; } + void SetPetPower(int16 p) { if (p < 0) petpower = 0; else petpower = p; } + bool IsFamiliar() const { return(typeofpet == petFamiliar); } + bool IsAnimation() const { return(typeofpet == petAnimation); } + bool IsCharmed() const { return(typeofpet == petCharmed); } + void SetOwnerID(uint16 NewOwnerID); + inline uint16 GetOwnerID() const { return ownerid; } + inline virtual bool HasOwner() { if(GetOwnerID()==0){return false;} return( entity_list.GetMob(GetOwnerID()) != 0); } + inline virtual bool IsPet() { return(HasOwner() && !IsMerc()); } + inline bool HasPet() const { if(GetPetID()==0){return false;} return (entity_list.GetMob(GetPetID()) != 0);} + bool HadTempPets() const { return(hasTempPet); } + void TempPets(bool i) { hasTempPet = i; } + bool HasPetAffinity() { if (aabonuses.GivePetGroupTarget || itembonuses.GivePetGroupTarget || spellbonuses.GivePetGroupTarget) return true; return false; } + + inline const bodyType GetBodyType() const { return bodytype; } + inline const bodyType GetOrigBodyType() const { return orig_bodytype; } + void SetBodyType(bodyType new_body, bool overwrite_orig); + + uint8 invisible, see_invis; + bool invulnerable, invisible_undead, invisible_animals, sneaking, hidden, improved_hidden; + bool see_invis_undead, see_hide, see_improved_hide; + bool qglobal; + + virtual void SetAttackTimer(); + inline void SetInvul(bool invul) { invulnerable=invul; } + inline bool GetInvul(void) { return invulnerable; } + inline void SetExtraHaste(int Haste) { ExtraHaste = Haste; } + virtual int GetHaste(); + + uint8 GetWeaponDamageBonus(const Item_Struct* Weapon); + uint16 GetDamageTable(SkillUseTypes skillinuse); + virtual int GetMonkHandToHandDamage(void); + + bool CanThisClassDoubleAttack(void) const; + bool CanThisClassDualWield(void) const; + bool CanThisClassRiposte(void) const; + bool CanThisClassDodge(void) const; + bool CanThisClassParry(void) const; + bool CanThisClassBlock(void) const; + + int GetMonkHandToHandDelay(void); + uint16 GetClassLevelFactor(); + void Mesmerize(); + inline bool IsMezzed() const { return mezzed; } + inline bool IsStunned() const { return stunned; } + inline bool IsSilenced() const { return silenced; } + inline bool IsAmnesiad() const { return amnesiad; } + + int32 ReduceDamage(int32 damage); + int32 AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker); + int32 ReduceAllDamage(int32 damage); + + virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true); + virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* item=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0); + virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime=0); + virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0); + bool CanDoSpecialAttack(Mob *other); + bool Flurry(ExtraAttackOptions *opts); + bool Rampage(ExtraAttackOptions *opts); + bool AddRampage(Mob*); + void ClearRampage(); + void AreaRampage(ExtraAttackOptions *opts); + + void StartEnrage(); + void ProcessEnrage(); + bool IsEnraged(); + void Taunt(NPC* who, bool always_succeed, float chance_bonus = 0); + + virtual void AI_Init(); + virtual void AI_Start(uint32 iMoveDelay = 0); + virtual void AI_Stop(); + virtual void AI_Process(); + + const char* GetEntityVariable(const char *id); + void SetEntityVariable(const char *id, const char *m_var); + bool EntityVariableExists(const char *id); + + void AI_Event_Engaged(Mob* attacker, bool iYellForHelp = true); + void AI_Event_NoLongerEngaged(); + + FACTION_VALUE GetSpecialFactionCon(Mob* iOther); + inline const bool IsAIControlled() const { return pAIControlled; } + inline const float GetAggroRange() const { return (spellbonuses.AggroRange == -1) ? pAggroRange : spellbonuses.AggroRange; } + inline const float GetAssistRange() const { return (spellbonuses.AssistRange == -1) ? pAssistRange : spellbonuses.AssistRange; } + + + inline void SetPetOrder(eStandingPetOrder i) { pStandingPetOrder = i; } + inline const eStandingPetOrder GetPetOrder() const { return pStandingPetOrder; } + inline void SetHeld(bool nState) { held = nState; } + inline const bool IsHeld() const { return held; } + inline void SetNoCast(bool nState) { nocast = nState; } + inline const bool IsNoCast() const { return nocast; } + inline void SetFocused(bool nState) { focused = nState; } + inline const bool IsFocused() const { return focused; } + inline const bool IsRoamer() const { return roamer; } + inline const bool IsRooted() const { return rooted || permarooted; } + inline const bool HasVirus() const { return has_virus; } + int GetSnaredAmount(); + + + int GetCurWp() { return cur_wp; } + + //old fear function + //void SetFeared(Mob *caster, uint32 duration, bool flee = false); + float GetFearSpeed(); + bool IsFeared() { return curfp; } // This returns true if the mob is feared or fleeing due to low HP + //old fear: inline void StartFleeing() { SetFeared(GetHateTop(), FLEE_RUN_DURATION, true); } + inline void StartFleeing() { flee_mode = true; CalculateNewFearpoint(); } + void ProcessFlee(); + void CheckFlee(); + + inline bool CheckAggro(Mob* other) {return hate_list.IsOnHateList(other);} + float CalculateHeadingToTarget(float in_x, float in_y); + bool CalculateNewPosition(float x, float y, float z, float speed, bool checkZ = false); + virtual bool CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ = true); + float CalculateDistance(float x, float y, float z); + float GetGroundZ(float new_x, float new_y, float z_offset=0.0); + void SendTo(float new_x, float new_y, float new_z); + void SendToFixZ(float new_x, float new_y, float new_z); + void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false); + inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; } + inline uint32 DontBuffMeBefore() const { return pDontBuffMeBefore; } + inline uint32 DontDotMeBefore() const { return pDontDotMeBefore; } + inline uint32 DontRootMeBefore() const { return pDontRootMeBefore; } + inline uint32 DontSnareMeBefore() const { return pDontSnareMeBefore; } + inline uint32 DontCureMeBefore() const { return pDontCureMeBefore; } + void SetDontRootMeBefore(uint32 time) { pDontRootMeBefore = time; } + void SetDontHealMeBefore(uint32 time) { pDontHealMeBefore = time; } + void SetDontBuffMeBefore(uint32 time) { pDontBuffMeBefore = time; } + void SetDontDotMeBefore(uint32 time) { pDontDotMeBefore = time; } + void SetDontSnareMeBefore(uint32 time) { pDontSnareMeBefore = time; } + void SetDontCureMeBefore(uint32 time) { pDontCureMeBefore = time; } + + // calculate interruption of spell via movement of mob + void SaveSpellLoc() {spell_x = x_pos; spell_y = y_pos; spell_z = z_pos; } + inline float GetSpellX() const {return spell_x;} + inline float GetSpellY() const {return spell_y;} + inline float GetSpellZ() const {return spell_z;} + inline bool IsGrouped() const { return isgrouped; } + void SetGrouped(bool v); + inline bool IsRaidGrouped() const { return israidgrouped; } + void SetRaidGrouped(bool v); + inline bool IsLooting() const { return islooting; } + void SetLooting(bool val) { islooting = val; } + + bool CheckWillAggro(Mob *mob); + + void InstillDoubt(Mob *who); + int16 GetResist(uint8 type) const; + Mob* GetShieldTarget() const { return shield_target; } + void SetShieldTarget(Mob* mob) { shield_target = mob; } + bool HasActiveSong() const { return(bardsong != 0); } + bool Charmed() const { return charmed; } + static uint32 GetLevelHP(uint8 tlevel); + uint32 GetZoneID() const; //for perl + virtual int32 CheckAggroAmount(uint16 spell_id, bool isproc = false); + virtual int32 CheckHealAggroAmount(uint16 spell_id, uint32 heal_possible = 0); + virtual uint32 GetAA(uint32 aa_id) const { return(0); } + + uint16 GetInstrumentMod(uint16 spell_id) const; + int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, Mob *caster = nullptr, int ticsremaining = 0); + int CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining = 0); + virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1); + uint32 GetCastedSpellInvSlot() const { return casting_spell_inventory_slot; } + + // HP Event + inline int GetNextHPEvent() const { return nexthpevent; } + void SetNextHPEvent( int hpevent ); + void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse); + inline int& GetNextIncHPEvent() { return nextinchpevent; } + void SetNextIncHPEvent( int inchpevent ); + + inline bool DivineAura() const { return spellbonuses.DivineAura; } + inline bool Sanctuary() const { return spellbonuses.Sanctuary; } + + bool HasNPCSpecialAtk(const char* parse); + int GetSpecialAbility(int ability); + int GetSpecialAbilityParam(int ability, int param); + void SetSpecialAbility(int ability, int level); + void SetSpecialAbilityParam(int ability, int param, int value); + void StartSpecialAbilityTimer(int ability, uint32 time); + void StopSpecialAbilityTimer(int ability); + Timer *GetSpecialAbilityTimer(int ability); + void ClearSpecialAbilities(); + void ProcessSpecialAbilities(const std::string str); + + Shielders_Struct shielder[MAX_SHIELDERS]; + Trade* trade; + + inline float GetCWPX() const { return(cur_wp_x); } + inline float GetCWPY() const { return(cur_wp_y); } + inline float GetCWPZ() const { return(cur_wp_z); } + inline float GetCWPH() const { return(cur_wp_heading); } + inline float GetCWPP() const { return(static_cast(cur_wp_pause)); } + inline int GetCWP() const { return(cur_wp); } + void SetCurrentWP(uint16 waypoint) { cur_wp = waypoint; } + virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; } + + inline bool IsTrackable() const { return(trackable); } + Timer* GetAIThinkTimer() { return AIthink_timer; } + Timer* GetAIMovementTimer() { return AImovement_timer; } + Timer GetAttackTimer() { return attack_timer; } + Timer GetAttackDWTimer() { return attack_dw_timer; } + inline bool IsFindable() { return findable; } + inline uint8 GetManaPercent() { return (uint8)((float)cur_mana / (float)max_mana * 100.0f); } + virtual uint8 GetEndurancePercent() { return 0; } + + inline virtual bool IsBlockedBuff(int16 SpellID) { return false; } + inline virtual bool IsBlockedPetBuff(int16 SpellID) { return false; } + + void SetGlobal(const char *varname, const char *newvalue, int options, const char *duration, Mob *other = nullptr); + void TarGlobal(const char *varname, const char *value, const char *duration, int npcid, int charid, int zoneid); + void DelGlobal(const char *varname); + + inline void SetEmoteID(uint16 emote) { emoteid = emote; } + inline uint16 GetEmoteID() { return emoteid; } + + bool HasSpellEffect(int effectid); + int mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster); + float mod_hit_chance(float chancetohit, SkillUseTypes skillinuse, Mob* attacker); + float mod_riposte_chance(float ripostchance, Mob* attacker); + float mod_block_chance(float blockchance, Mob* attacker); + float mod_parry_chance(float parrychance, Mob* attacker); + float mod_dodge_chance(float dodgechance, Mob* attacker); + float mod_monk_weight(float monkweight, Mob* attacker); + float mod_mitigation_rating(float mitigation_rating, Mob* attacker); + float mod_attack_rating(float attack_rating, Mob* defender); + int32 mod_kick_damage(int32 dmg); + int32 mod_bash_damage(int32 dmg); + int32 mod_frenzy_damage(int32 dmg); + int32 mod_monk_special_damage(int32 ndamage, SkillUseTypes skill_type); + int32 mod_backstab_damage(int32 ndamage); + int mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon); + uint32 mod_archery_bonus_damage(uint32 MaxDmg, const ItemInst* RangeWeapon); + int32 mod_archery_damage(int32 TotalDmg, bool hasbonus, const ItemInst* RangeWeapon); + uint16 mod_throwing_damage(uint16 MaxDmg); + int32 mod_cast_time(int32 cast_time); + int mod_buff_duration(int res, Mob* caster, Mob* target, uint16 spell_id); + int mod_spell_stack(uint16 spellid1, int caster_level1, Mob* caster1, uint16 spellid2, int caster_level2, Mob* caster2); + int mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster); + void mod_spell_cast(uint16 spell_id, Mob* spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust, bool isproc); + bool mod_will_aggro(Mob *attacker, Mob *on); + +protected: + void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); + static uint16 GetProcID(uint16 spell_id, uint8 effect_index); + float _GetMovementSpeed(int mod) const; + virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, bool checkZ); + + virtual bool AI_EngagedCastCheck() { return(false); } + virtual bool AI_PursueCastCheck() { return(false); } + virtual bool AI_IdleCastCheck() { return(false); } + + + bool IsFullHP; + bool moved; + + std::vector RampageArray; + std::map m_EntityVariables; + + int16 SkillDmgTaken_Mod[HIGHEST_SKILL+2]; + int16 Vulnerability_Mod[HIGHEST_RESIST+2]; + bool m_AllowBeneficial; + bool m_DisableMelee; + + bool isgrouped; + bool israidgrouped; + bool pendinggroup; + bool islooting; + uint8 texture; + uint8 helmtexture; + + int AC; + int16 ATK; + int16 STR; + int16 STA; + int16 DEX; + int16 AGI; + int16 INT; + int16 WIS; + int16 CHA; + int16 MR; + int16 CR; + int16 FR; + int16 DR; + int16 PR; + int16 Corrup; + int16 PhR; + bool moving; + int targeted; + bool findable; + bool trackable; + int32 cur_hp; + int32 max_hp; + int32 base_hp; + int32 cur_mana; + int32 max_mana; + int32 hp_regen; + int32 mana_regen; + int32 oocregen; + uint8 maxlevel; + uint32 scalerate; + Buffs_Struct *buffs; + uint32 current_buff_count; + StatBonuses itembonuses; + StatBonuses spellbonuses; + StatBonuses aabonuses; + uint16 petid; + uint16 ownerid; + PetType typeofpet; + int16 petpower; + uint32 follow; + uint32 follow_dist; + bool no_target_hotkey; + + uint8 gender; + uint16 race; + uint8 base_gender; + uint16 base_race; + uint8 class_; + bodyType bodytype; + bodyType orig_bodytype; + uint16 deity; + uint8 level; + uint8 orig_level; + uint32 npctype_id; + float x_pos; + float y_pos; + float z_pos; + float heading; + uint16 animation; + float base_size; + float size; + float runspeed; + uint32 pLastChange; + bool held; + bool nocast; + bool focused; + void CalcSpellBonuses(StatBonuses* newbon); + virtual void CalcBonuses(); + void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); + bool PassLimitToSkill(uint16 spell_id, uint16 skill); + bool PassLimitClass(uint32 Classes_, uint16 Class_); + void TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand = 13, int damage=0); + void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = 13); + void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = 13); + void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = 13); + void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on); + virtual float GetProcChances(float ProcBonus, uint16 weapon_speed = 30, uint16 hand = 13); + virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed = 30, uint16 hand = 13); + virtual float GetSpecialProcChances(uint16 hand); + virtual float GetAssassinateProcChances(uint16 ReuseTime); + virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); + uint16 GetWeaponSpeedbyHand(uint16 hand); + int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item); + int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr); + int GetKickDamage(); + int GetBashDamage(); + virtual void ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg); + bool HasDied(); + void CalculateNewFearpoint(); + float FindGroundZ(float new_x, float new_y, float z_offset=0.0); + Map::Vertex UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached); + void PrintRoute(); + + virtual float GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate = 0); + + enum {MAX_PROCS = 4}; + tProc PermaProcs[MAX_PROCS]; + tProc SpellProcs[MAX_PROCS]; + tProc DefensiveProcs[MAX_PROCS]; + tProc RangedProcs[MAX_PROCS]; + tProc SkillProcs[MAX_PROCS]; + + char name[64]; + char orig_name[64]; + char clean_name[64]; + char lastname[64]; + + int32 delta_heading; + float delta_x; + float delta_y; + float delta_z; + + uint8 light; + + float fixedZ; + EmuAppearance _appearance; + uint8 pRunAnimSpeed; + bool m_is_running; + + + Timer attack_timer; + Timer attack_dw_timer; + Timer ranged_timer; + float attack_speed; //% increase/decrease in attack speed (not haste) + float slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%) + Timer tic_timer; + Timer mana_timer; + + //spell casting vars + Timer spellend_timer; + uint16 casting_spell_id; + float spell_x, spell_y, spell_z; + int attacked_count; + bool delaytimer; + uint16 casting_spell_targetid; + uint16 casting_spell_slot; + uint16 casting_spell_mana; + uint32 casting_spell_inventory_slot; + uint32 casting_spell_timer; + uint32 casting_spell_timer_duration; + uint32 casting_spell_type; + int16 casting_spell_resist_adjust; + bool casting_spell_checks; + uint16 bardsong; + uint8 bardsong_slot; + uint32 bardsong_target_id; + + Timer projectile_timer; + uint32 projectile_spell_id[MAX_SPELL_PROJECTILE]; + uint16 projectile_target_id[MAX_SPELL_PROJECTILE]; + uint8 projectile_increment[MAX_SPELL_PROJECTILE]; + float projectile_x[MAX_SPELL_PROJECTILE], projectile_y[MAX_SPELL_PROJECTILE], projectile_z[MAX_SPELL_PROJECTILE]; + + float rewind_x; + float rewind_y; + float rewind_z; + Timer rewind_timer; + + // Currently 3 max nimbus particle effects at a time + uint32 nimbus_effect1; + uint32 nimbus_effect2; + uint32 nimbus_effect3; + + uint8 haircolor; + uint8 beardcolor; + uint8 eyecolor1; // the eyecolors always seem to be the same, maybe left and right eye? + uint8 eyecolor2; + uint8 hairstyle; + uint8 luclinface; // + uint8 beard; + uint32 drakkin_heritage; + uint32 drakkin_tattoo; + uint32 drakkin_details; + uint32 armor_tint[_MaterialCount]; + + uint8 aa_title; + + Mob* shield_target; + + int ExtraHaste; // for the #haste command + bool mezzed; + bool stunned; + bool charmed; //this isnt fully implemented yet + bool rooted; + bool silenced; + bool amnesiad; + bool inWater; // Set to true or false by Water Detection code if enabled by rules + bool has_virus; // whether this mob has a viral spell on them + uint16 viral_spells[MAX_SPELL_TRIGGER*2]; // Stores the spell ids of the viruses on target and caster ids + bool offhand; + bool has_shieldequiped; + bool has_numhits; + bool has_MGB; + bool has_ProjectIllusion; + + // Bind wound + Timer bindwound_timer; + Mob* bindwound_target; + + Timer stunned_timer; + Timer spun_timer; + Timer bardsong_timer; + Timer gravity_timer; + Timer viral_timer; + uint8 viral_timer_counter; + + // MobAI stuff + eStandingPetOrder pStandingPetOrder; + uint32 minLastFightingDelayMoving; + uint32 maxLastFightingDelayMoving; + float pAggroRange; + float pAssistRange; + Timer* AIthink_timer; + Timer* AImovement_timer; + Timer* AItarget_check_timer; + bool movetimercompleted; + bool permarooted; + Timer* AIscanarea_timer; + Timer* AIwalking_timer; + Timer* AIfeignremember_timer; + uint32 pLastFightingDelayMoving; + HateList hate_list; + std::set feign_memory_list; + // This is to keep track of mobs we cast faction mod spells on + std::map faction_bonuses; // Primary FactionID, Bonus + void AddFactionBonus(uint32 pFactionID,int32 bonus); + int32 GetFactionBonus(uint32 pFactionID); + // This is to keep track of item faction modifiers + std::map item_faction_bonuses; // Primary FactionID, Bonus + void AddItemFactionBonus(uint32 pFactionID,int32 bonus); + int32 GetItemFactionBonus(uint32 pFactionID); + void ClearItemFactionBonuses(); + + void CalculateFearPosition(); + uint32 move_tic_count; + + bool flee_mode; + Timer flee_timer; + + bool pAIControlled; + bool roamer; + bool logging_enabled; + + int wandertype; + int pausetype; + + int cur_wp; + float cur_wp_x; + float cur_wp_y; + float cur_wp_z; + int cur_wp_pause; + float cur_wp_heading; + + int patrol; + float fear_walkto_x; + float fear_walkto_y; + float fear_walkto_z; + bool curfp; + + // Pathing + // + Map::Vertex PathingDestination; + Map::Vertex PathingLastPosition; + int PathingLoopCount; + int PathingLastNodeVisited; + std::list Route; + LOSType PathingLOSState; + Timer *PathingLOSCheckTimer; + Timer *PathingRouteUpdateTimerShort; + Timer *PathingRouteUpdateTimerLong; + bool DistractedFromGrid; + int PathingTraversedNodes; + + uint32 pDontHealMeBefore; + uint32 pDontBuffMeBefore; + uint32 pDontDotMeBefore; + uint32 pDontRootMeBefore; + uint32 pDontSnareMeBefore; + uint32 pDontCureMeBefore; + + // hp event + int nexthpevent; + int nextinchpevent; + + //temppet + bool hasTempPet; + + EGNode *_egnode; //the EG node we are in + float tarx; + float tary; + float tarz; + uint8 tar_ndx; + float tar_vector; + float tar_vx; + float tar_vy; + float tar_vz; + float test_vector; + + uint32 m_spellHitsLeft[38]; // Used to track which spells will have their numhits incremented when spell finishes casting, 38 Buffslots + int flymode; + bool m_targetable; + int QGVarDuration(const char *fmt); + void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate); + uint16 emoteid; + + SpecialAbility SpecialAbilities[MAX_SPECIAL_ATTACK]; + bool bEnraged; + bool destructibleobject; + +private: + void _StopSong(); //this is not what you think it is + Mob* target; +}; + +#endif + diff --git a/zone/net_Fix.cpp b/zone/net_Fix.cpp new file mode 100644 index 000000000..9b4080eb2 --- /dev/null +++ b/zone/net_Fix.cpp @@ -0,0 +1,644 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define DONT_SHARED_OPCODES + +#include "../common/debug.h" +#include "../common/features.h" +#include "../common/queue.h" +#include "../common/timer.h" +#include "../common/eq_stream.h" +#include "../common/eq_stream_factory.h" +#include "../common/eq_packet_structs.h" +#include "../common/mutex.h" +#include "../common/version.h" +#include "../common/eqemu_error.h" +#include "../common/packet_dump_file.h" +#include "../common/opcodemgr.h" +#include "../common/guilds.h" +#include "../common/eq_stream_ident.h" +#include "../common/patches/patches.h" +#include "../common/rulesys.h" +#include "../common/misc_functions.h" +#include "../common/string_util.h" +#include "../common/platform.h" +#include "../common/crash.h" +#include "../common/ipc_mutex.h" +#include "../common/memory_mapped_file.h" +#include "../common/eqemu_exception.h" +#include "../common/spdat.h" + +#include "zone_config.h" +#include "masterentity.h" +#include "worldserver.h" +#include "net.h" +#include "zone.h" +#include "queryserv.h" +#include "command.h" +#include "zone_config.h" +#include "titles.h" +#include "guild_mgr.h" +#include "tasks.h" + +#include "quest_parser_collection.h" +#include "embparser.h" +#include "lua_parser.h" +#include "client_logs.h" +#include "questmgr.h" + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef _CRTDBG_MAP_ALLOC + #undef new + #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) +#endif + +#ifdef _WINDOWS + #include + #include +#else + #include + #include "../common/unix.h" +#endif + +volatile bool RunLoops = true; +extern volatile bool ZoneLoaded; + +TimeoutManager timeout_manager; +NetConnection net; +EntityList entity_list; +WorldServer worldserver; +uint32 numclients = 0; +char errorname[32]; +uint16 adverrornum = 0; +extern Zone* zone; +EQStreamFactory eqsf(ZoneStream); +npcDecayTimes_Struct npcCorpseDecayTimes[100]; +TitleManager title_manager; +QueryServ *QServ = 0; +TaskManager *taskmanager = 0; +QuestParserCollection *parse = 0; + +const SPDat_Spell_Struct* spells; +void LoadSpells(EQEmu::MemoryMappedFile **mmf); +int32 SPDAT_RECORDS = -1; + +void Shutdown(); +extern void MapOpcodes(); + +int main(int argc, char** argv) { + RegisterExecutablePlatform(ExePlatformZone); + set_exception_handler(); + + const char *zone_name; + + QServ = new QueryServ; + + if(argc == 3) { + worldserver.SetLauncherName(argv[2]); + worldserver.SetLaunchedName(argv[1]); + if(strncmp(argv[1], "dynamic_", 8) == 0) { + //dynamic zone with a launcher name correlation + zone_name = "."; + } else { + zone_name = argv[1]; + worldserver.SetLaunchedName(zone_name); + } + } else if (argc == 2) { + worldserver.SetLauncherName("NONE"); + worldserver.SetLaunchedName(argv[1]); + if(strncmp(argv[1], "dynamic_", 8) == 0) { + //dynamic zone with a launcher name correlation + zone_name = "."; + } else { + zone_name = argv[1]; + worldserver.SetLaunchedName(zone_name); + } + } else { + zone_name = "."; + worldserver.SetLaunchedName("."); + worldserver.SetLauncherName("NONE"); + } + + _log(ZONE__INIT, "Loading server configuration.."); + if (!ZoneConfig::LoadConfig()) { + _log(ZONE__INIT_ERR, "Loading server configuration failed."); + return 1; + } + const ZoneConfig *Config=ZoneConfig::get(); + + if(!load_log_settings(Config->LogSettingsFile.c_str())) + _log(ZONE__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str()); + else + _log(ZONE__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str()); + + worldserver.SetPassword(Config->SharedKey.c_str()); + + _log(ZONE__INIT, "Connecting to MySQL..."); + if (!database.Connect( + Config->DatabaseHost.c_str(), + Config->DatabaseUsername.c_str(), + Config->DatabasePassword.c_str(), + Config->DatabaseDB.c_str(), + Config->DatabasePort)) { + _log(ZONE__INIT_ERR, "Cannot continue without a database connection."); + return 1; + } + guild_mgr.SetDatabase(&database); + + GuildBanks = nullptr; + +#ifdef _EQDEBUG + _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); +#endif + + _log(ZONE__INIT, "CURRENT_VERSION: %s", CURRENT_VERSION); + + /* + * Setup nice signal handlers + */ + if (signal(SIGINT, CatchSignal) == SIG_ERR) { + _log(ZONE__INIT_ERR, "Could not set signal handler"); + return 1; + } + if (signal(SIGTERM, CatchSignal) == SIG_ERR) { + _log(ZONE__INIT_ERR, "Could not set signal handler"); + return 1; + } + #ifndef WIN32 + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { + _log(ZONE__INIT_ERR, "Could not set signal handler"); + return 1; + } + #endif + + const char *log_ini_file = "./log.ini"; + if(!load_log_settings(log_ini_file)) + _log(ZONE__INIT, "Warning: Unable to read %s", log_ini_file); + else + _log(ZONE__INIT, "Log settings loaded from %s", log_ini_file); + + _log(ZONE__INIT, "Mapping Incoming Opcodes"); + MapOpcodes(); + _log(ZONE__INIT, "Loading Variables"); + database.LoadVariables(); + _log(ZONE__INIT, "Loading zone names"); + database.LoadZoneNames(); + _log(ZONE__INIT, "Loading items"); + if (!database.LoadItems()) { + _log(ZONE__INIT_ERR, "Loading items FAILED!"); + _log(ZONE__INIT, "Failed. But ignoring error and going on..."); + } + + _log(ZONE__INIT, "Loading npc faction lists"); + if (!database.LoadNPCFactionLists()) { + _log(ZONE__INIT_ERR, "Loading npcs faction lists FAILED!"); + CheckEQEMuErrorAndPause(); + return 1; + } + _log(ZONE__INIT, "Loading loot tables"); + if (!database.LoadLoot()) { + _log(ZONE__INIT_ERR, "Loading loot FAILED!"); + CheckEQEMuErrorAndPause(); + return 1; + } + _log(ZONE__INIT, "Loading skill caps"); + if (!database.LoadSkillCaps()) { + _log(ZONE__INIT_ERR, "Loading skill caps FAILED!"); + CheckEQEMuErrorAndPause(); + return 1; + } + + _log(ZONE__INIT, "Loading spells"); + EQEmu::MemoryMappedFile *mmf = nullptr; + LoadSpells(&mmf); + + _log(ZONE__INIT, "Loading base data"); + if (!database.LoadBaseData()) { + _log(ZONE__INIT_ERR, "Loading base data FAILED!"); + CheckEQEMuErrorAndPause(); + return 1; + } + + _log(ZONE__INIT, "Loading guilds"); + guild_mgr.LoadGuilds(); + _log(ZONE__INIT, "Loading factions"); + database.LoadFactionData(); + _log(ZONE__INIT, "Loading titles"); + title_manager.LoadTitles(); + _log(ZONE__INIT, "Loading AA effects"); + database.LoadAAEffects(); + _log(ZONE__INIT, "Loading tributes"); + database.LoadTributes(); + _log(ZONE__INIT, "Loading corpse timers"); + database.GetDecayTimes(npcCorpseDecayTimes); + _log(ZONE__INIT, "Loading commands"); + int retval=command_init(); + if(retval<0) + _log(ZONE__INIT_ERR, "Command loading FAILED"); + else + _log(ZONE__INIT, "%d commands loaded", retval); + + //rules: + { + char tmp[64]; + if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) { + _log(ZONE__INIT, "Loading rule set '%s'", tmp); + if(!RuleManager::Instance()->LoadRules(&database, tmp)) { + _log(ZONE__INIT_ERR, "Failed to load ruleset '%s', falling back to defaults.", tmp); + } + } else { + if(!RuleManager::Instance()->LoadRules(&database, "default")) { + _log(ZONE__INIT, "No rule set configured, using default rules"); + } else { + _log(ZONE__INIT, "Loaded default rule set 'default'", tmp); + } + } + } + + if(RuleB(TaskSystem, EnableTaskSystem)) { + _log(ZONE__INIT, "Loading Tasks"); + taskmanager = new TaskManager; + taskmanager->LoadTasks(); + } + + parse = new QuestParserCollection(); +#ifdef LUA_EQEMU + LuaParser *lua_parser = new LuaParser(); + parse->RegisterQuestInterface(lua_parser, "lua"); +#endif + +#ifdef EMBPERL + PerlembParser *perl_parser = new PerlembParser(); + parse->RegisterQuestInterface(perl_parser, "pl"); +#endif + + //now we have our parser, load the quests + _log(ZONE__INIT, "Loading quests"); + parse->ReloadQuests(); + + +#ifdef CLIENT_LOGS + LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_buf); + LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_fmt); + LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_pva); +#endif + if (!worldserver.Connect()) { + _log(ZONE__INIT_ERR, "worldserver.Connect() FAILED!"); + } + + Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect +#ifdef EQPROFILE +#ifdef PROFILE_DUMP_TIME + Timer profile_dump_timer(PROFILE_DUMP_TIME*1000); + profile_dump_timer.Start(); +#endif +#endif + if (!strlen(zone_name) || !strcmp(zone_name,".")) { + _log(ZONE__INIT, "Entering sleep mode"); + } else if (!Zone::Bootup(database.GetZoneID(zone_name), 0, true)) { //todo: go above and fix this to allow cmd line instance + _log(ZONE__INIT_ERR, "Zone bootup FAILED!"); + zone = 0; + } + + //register all the patches we have avaliable with the stream identifier. + EQStreamIdentifier stream_identifier; + RegisterAllPatches(stream_identifier); + +#ifndef WIN32 + _log(COMMON__THREADS, "Main thread running with thread id %d", pthread_self()); +#endif + + Timer quest_timers(100); + UpdateWindowTitle(); + bool worldwasconnected = worldserver.Connected(); + EQStream* eqss; + EQStreamInterface *eqsi; + uint8 IDLEZONEUPDATE = 200; + uint8 ZONEUPDATE = 10; + Timer zoneupdate_timer(ZONEUPDATE); + zoneupdate_timer.Start(); + while(RunLoops) { + { //profiler block to omit the sleep from times + + //Advance the timer to our current point in time + Timer::SetCurrentTime(); + + //process stuff from world + worldserver.Process(); + + if (!eqsf.IsOpen() && Config->ZonePort!=0) { + _log(ZONE__INIT, "Starting EQ Network server on port %d",Config->ZonePort); + if (!eqsf.Open(Config->ZonePort)) { + _log(ZONE__INIT_ERR, "Failed to open port %d",Config->ZonePort); + ZoneConfig::SetZonePort(0); + worldserver.Disconnect(); + worldwasconnected = false; + } + } + + //check the factory for any new incoming streams. + while ((eqss = eqsf.Pop())) { + //pull the stream out of the factory and give it to the stream identifier + //which will figure out what patch they are running, and set up the dynamic + //structures and opcodes for that patch. + struct in_addr in; + in.s_addr = eqss->GetRemoteIP(); + _log(WORLD__CLIENT, "New connection from %s:%d", inet_ntoa(in),ntohs(eqss->GetRemotePort())); + stream_identifier.AddStream(eqss); //takes the stream + } + + //give the stream identifier a chance to do its work.... + stream_identifier.Process(); + + //check the stream identifier for any now-identified streams + while((eqsi = stream_identifier.PopIdentified())) { + //now that we know what patch they are running, start up their client object + struct in_addr in; + in.s_addr = eqsi->GetRemoteIP(); + _log(WORLD__CLIENT, "New client from %s:%d", inet_ntoa(in), ntohs(eqsi->GetRemotePort())); + Client* client = new Client(eqsi); + entity_list.AddClient(client); + } + + if ( numclients < 1 && zoneupdate_timer.GetDuration() != IDLEZONEUPDATE ) + zoneupdate_timer.SetTimer(IDLEZONEUPDATE); + else if ( numclients > 0 && zoneupdate_timer.GetDuration() == IDLEZONEUPDATE ) + { + zoneupdate_timer.SetTimer(ZONEUPDATE); + zoneupdate_timer.Trigger(); + } + + //check for timeouts in other threads + timeout_manager.CheckTimeouts(); + + if (worldserver.Connected()) { + worldwasconnected = true; + } + else { + if (worldwasconnected && ZoneLoaded) + entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost"); + worldwasconnected = false; + } + + if (ZoneLoaded && zoneupdate_timer.Check()) { + { + if(net.group_timer.Enabled() && net.group_timer.Check()) + entity_list.GroupProcess(); + + if(net.door_timer.Enabled() && net.door_timer.Check()) + entity_list.DoorProcess(); + + if(net.object_timer.Enabled() && net.object_timer.Check()) + entity_list.ObjectProcess(); + + if(net.corpse_timer.Enabled() && net.corpse_timer.Check()) + entity_list.CorpseProcess(); + + if(net.trap_timer.Enabled() && net.trap_timer.Check()) + entity_list.TrapProcess(); + + if(net.raid_timer.Enabled() && net.raid_timer.Check()) + entity_list.RaidProcess(); + + entity_list.Process(); + + entity_list.MobProcess(); + + entity_list.BeaconProcess(); + + if (zone) { + if(!zone->Process()) { + Zone::Shutdown(); + } + } + + if(quest_timers.Check()) + quest_manager.Process(); + + } + } + if (InterserverTimer.Check()) { + InterserverTimer.Start(); + database.ping(); + // AsyncLoadVariables(dbasync, &database); + entity_list.UpdateWho(); + if (worldserver.TryReconnect() && (!worldserver.Connected())) + worldserver.AsyncConnect(); + } + +#if defined(_EQDEBUG) && defined(DEBUG_PC) + QueryPerformanceCounter(&tmp3); + mainloop_time += tmp3.QuadPart - tmp2.QuadPart; + if (!--tmp0) { + tmp0 = 200; + printf("Elapsed Tics : %9.0f (%1.4f sec)\n", (double)mainloop_time, ((double)mainloop_time/tmp.QuadPart)); + printf("NPCAI Tics : %9.0f (%1.2f%%)\n", (double)npcai_time, ((double)npcai_time/mainloop_time)*100); + printf("FindSpell Tics: %9.0f (%1.2f%%)\n", (double)findspell_time, ((double)findspell_time/mainloop_time)*100); + printf("AtkAllowd Tics: %9.0f (%1.2f%%)\n", (double)IsAttackAllowed_time, ((double)IsAttackAllowed_time/mainloop_time)*100); + printf("ClientPro Tics: %9.0f (%1.2f%%)\n", (double)clientprocess_time, ((double)clientprocess_time/mainloop_time)*100); + printf("ClientAtk Tics: %9.0f (%1.2f%%)\n", (double)clientattack_time, ((double)clientattack_time/mainloop_time)*100); + mainloop_time = 0; + npcai_time = 0; + findspell_time = 0; + IsAttackAllowed_time = 0; + clientprocess_time = 0; + clientattack_time = 0; + } +#endif +#ifdef EQPROFILE +#ifdef PROFILE_DUMP_TIME + if(profile_dump_timer.Check()) { + DumpZoneProfile(); + } +#endif +#endif + } //end extra profiler block + Sleep(ZoneTimerResolution); + } + + entity_list.Clear(); + + parse->ClearInterfaces(); + +#ifdef EMBPERL + safe_delete(perl_parser); +#endif + +#ifdef LUA_EQEMU + safe_delete(lua_parser); +#endif + + safe_delete(mmf); + safe_delete(Config); + + if (zone != 0) + Zone::Shutdown(true); + //Fix for Linux world server problem. + eqsf.Close(); + worldserver.Disconnect(); + safe_delete(taskmanager); + command_deinit(); + safe_delete(parse); + CheckEQEMuErrorAndPause(); + _log(ZONE__INIT, "Proper zone shutdown complete."); + return 0; +} + +void CatchSignal(int sig_num) { +#ifdef _WINDOWS + _log(ZONE__INIT, "Recieved signal: %i", sig_num); +#endif + RunLoops = false; +} + +void Shutdown() +{ + Zone::Shutdown(true); + RunLoops = false; + worldserver.Disconnect(); + // safe_delete(worldserver); + _log(ZONE__INIT, "Shutting down..."); +} + +uint32 NetConnection::GetIP() +{ + char name[255+1]; + size_t len = 0; + hostent* host = 0; + + if (gethostname(name, len) < 0 || len <= 0) + { + return 0; + } + + host = (hostent*)gethostbyname(name); + if (host == 0) + { + return 0; + } + + return inet_addr(host->h_addr); +} + +uint32 NetConnection::GetIP(char* name) +{ + hostent* host = 0; + + host = (hostent*)gethostbyname(name); + if (host == 0) + { + return 0; + } + + return inet_addr(host->h_addr); + +} + +void NetConnection::SaveInfo(char* address, uint32 port, char* waddress, char* filename) { + + ZoneAddress = new char[strlen(address)+1]; + strcpy(ZoneAddress, address); + ZonePort = port; + WorldAddress = new char[strlen(waddress)+1]; + strcpy(WorldAddress, waddress); + strn0cpy(ZoneFileName, filename, sizeof(ZoneFileName)); +} + +NetConnection::NetConnection() +: + object_timer(5000), + door_timer(5000), + corpse_timer(2000), + group_timer(1000), + raid_timer(1000), + trap_timer(1000) +{ + ZonePort = 0; + ZoneAddress = 0; + WorldAddress = 0; + group_timer.Disable(); + raid_timer.Disable(); + corpse_timer.Disable(); + door_timer.Disable(); + object_timer.Disable(); + trap_timer.Disable(); +} + +NetConnection::~NetConnection() { + if (ZoneAddress != 0) + safe_delete_array(ZoneAddress); + if (WorldAddress != 0) + safe_delete_array(WorldAddress); +} + +void LoadSpells(EQEmu::MemoryMappedFile **mmf) { + int records = database.GetMaxSpellID() + 1; + + try { + EQEmu::IPCMutex mutex("spells"); + mutex.Lock(); + *mmf = new EQEmu::MemoryMappedFile("shared/spells"); + uint32 size = (*mmf)->Size(); + if(size != (records * sizeof(SPDat_Spell_Struct))) { + EQ_EXCEPT("Zone", "Unable to load spells: (*mmf)->Size() != records * sizeof(SPDat_Spell_Struct)"); + } + + spells = reinterpret_cast((*mmf)->Get()); + mutex.Unlock(); + } catch(std::exception &ex) { + LogFile->write(EQEMuLog::Error, "Error loading spells: %s", ex.what()); + return; + } + + SPDAT_RECORDS = records; +} + +/* Update Window Title with relevant information */ +void UpdateWindowTitle(char* iNewTitle) { +#ifdef _WINDOWS + char tmp[500]; + if (iNewTitle) { + snprintf(tmp, sizeof(tmp), "%i: %s", ZoneConfig::get()->ZonePort, iNewTitle); + } + else { + if (zone) { + #if defined(GOTFRAGS) || defined(_EQDEBUG) + snprintf(tmp, sizeof(tmp), "%i: %s, %i clients, %i", ZoneConfig::get()->ZonePort, zone->GetShortName(), numclients, getpid()); + #else + snprintf(tmp, sizeof(tmp), "%s :: clients: %i inst_id: %i inst_ver: %i :: port: %i", zone->GetShortName(), numclients, zone->GetInstanceID(), zone->GetInstanceVersion(), ZoneConfig::get()->ZonePort); + #endif + } + else { + #if defined(GOTFRAGS) || defined(_EQDEBUG) + snprintf(tmp, sizeof(tmp), "%i: sleeping, %i", ZoneConfig::get()->ZonePort, getpid()); + #else + snprintf(tmp, sizeof(tmp), "%i: sleeping", ZoneConfig::get()->ZonePort); + #endif + } + } + SetConsoleTitle(tmp); +#endif +} diff --git a/zone/npcx.cpp b/zone/npcx.cpp new file mode 100644 index 000000000..7d2766854 --- /dev/null +++ b/zone/npcx.cpp @@ -0,0 +1,2492 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include "../common/debug.h" +#include +#include +#include +#include +#include "../common/moremath.h" +#include +#include "../common/packet_dump_file.h" +#include "zone.h" +#ifdef _WINDOWS +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#else +#include +#include +#endif + +#include "npc.h" +#include "map.h" +#include "entity.h" +#include "masterentity.h" +#include "../common/spdat.h" +#include "../common/bodytypes.h" +#include "spawngroup.h" +#include "../common/MiscFunctions.h" +#include "../common/StringUtil.h" +#include "../common/rulesys.h" +#include "StringIDs.h" + +//#define SPELLQUEUE //Use only if you want to be spammed by spell testing + + +extern Zone* zone; +extern volatile bool ZoneLoaded; +extern EntityList entity_list; + +#include "QuestParserCollection.h" + +NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float heading, int iflymode, bool IsCorpse) +: Mob(d->name, + d->lastname, + d->max_hp, + d->max_hp, + d->gender, + d->race, + d->class_, + (bodyType)d->bodytype, + d->deity, + d->level, + d->npc_id, + d->size, + d->runspeed, + heading, + x, + y, + z, + d->light, + d->texture, + d->helmtexture, + d->AC, + d->ATK, + d->STR, + d->STA, + d->DEX, + d->AGI, + d->INT, + d->WIS, + d->CHA, + d->haircolor, + d->beardcolor, + d->eyecolor1, + d->eyecolor2, + d->hairstyle, + d->luclinface, + d->beard, + d->drakkin_heritage, + d->drakkin_tattoo, + d->drakkin_details, + (uint32*)d->armor_tint, + 0, + d->see_invis, // pass see_invis/see_ivu flags to mob constructor + d->see_invis_undead, + d->see_hide, + d->see_improved_hide, + d->hp_regen, + d->mana_regen, + d->qglobal, + d->maxlevel, + d->scalerate ), + attacked_timer(CombatEventTimer_expire), + swarm_timer(100), + classattack_timer(1000), + knightattack_timer(1000), + assist_timer(AIassistcheck_delay), + qglobal_purge_timer(30000), + sendhpupdate_timer(1000), + enraged_timer(1000), + taunt_timer(TauntReuseTime * 1000) +{ + //What is the point of this, since the names get mangled.. + Mob* mob = entity_list.GetMob(name); + if(mob != 0) + entity_list.RemoveEntity(mob->GetID()); + + int moblevel=GetLevel(); + + NPCTypedata = d; + NPCTypedata_ours = nullptr; + respawn2 = in_respawn; + swarm_timer.Disable(); + + taunting = false; + proximity = nullptr; + copper = 0; + silver = 0; + gold = 0; + platinum = 0; + max_dmg = d->max_dmg; + min_dmg = d->min_dmg; + attack_count = d->attack_count; + grid = 0; + wp_m = 0; + max_wp=0; + save_wp = 0; + spawn_group = 0; + swarmInfoPtr = nullptr; + spellscale = d->spellscale; + healscale = d->healscale; + + logging_enabled = NPC_DEFAULT_LOGGING_ENABLED; + + pAggroRange = d->aggroradius; + pAssistRange = d->assistradius; + findable = d->findable; + trackable = d->trackable; + + MR = d->MR; + CR = d->CR; + DR = d->DR; + FR = d->FR; + PR = d->PR; + Corrup = d->Corrup; + PhR = d->PhR; + + STR = d->STR; + STA = d->STA; + AGI = d->AGI; + DEX = d->DEX; + INT = d->INT; + WIS = d->WIS; + CHA = d->CHA; + npc_mana = d->Mana; + + //quick fix of ordering if they screwed it up in the DB + if(max_dmg < min_dmg) { + int tmp = min_dmg; + min_dmg = max_dmg; + max_dmg = tmp; + } + + // Max Level and Stat Scaling if maxlevel is set + if(maxlevel > level) + { + LevelScale(); + } + + // Set Resists if they are 0 in the DB + CalcNPCResists(); + + // Set Mana and HP Regen Rates if they are 0 in the DB + CalcNPCRegen(); + + // Set Min and Max Damage if they are 0 in the DB + if(max_dmg == 0){ + CalcNPCDamage(); + } + + accuracy_rating = d->accuracy_rating; + ATK = d->ATK; + + CalcMaxMana(); + SetMana(GetMaxMana()); + + MerchantType = d->merchanttype; + merchant_open = GetClass() == MERCHANT; + adventure_template_id = d->adventure_template; + org_x = x; + org_y = y; + org_z = z; + flymode = iflymode; + guard_x = -1; //just some value we might be able to recongize as "unset" + guard_y = -1; + guard_z = -1; + guard_heading = 0; + guard_anim = eaStanding; + roambox_distance = 0; + roambox_max_x = -2; + roambox_max_y = -2; + roambox_min_x = -2; + roambox_min_y = -2; + roambox_movingto_x = -2; + roambox_movingto_y = -2; + roambox_min_delay = 1000; + roambox_delay = 1000; + org_heading = heading; + p_depop = false; + loottable_id = d->loottable_id; + + no_target_hotkey = d->no_target_hotkey; + + primary_faction = 0; + SetNPCFactionID(d->npc_faction_id); + + npc_spells_id = 0; + HasAISpell = false; + HasAISpellEffects = false; + + if(GetClass() == MERCERNARY_MASTER && RuleB(Mercs, AllowMercs)) + { + LoadMercTypes(); + LoadMercs(); + } + + SpellFocusDMG = 0; + SpellFocusHeal = 0; + + pet_spell_id = 0; + + delaytimer = false; + combat_event = false; + attack_speed = d->attack_speed; + slow_mitigation = d->slow_mitigation; + + EntityList::RemoveNumbers(name); + entity_list.MakeNameUnique(name); + + npc_aggro = d->npc_aggro; + + if(!IsMerc()) + AI_Start(); + + d_meele_texture1 = d->d_meele_texture1; + d_meele_texture2 = d->d_meele_texture2; + memset(equipment, 0, sizeof(equipment)); + prim_melee_type = d->prim_melee_type; + sec_melee_type = d->sec_melee_type; + + // If Melee Textures are not set, set attack type to Hand to Hand as default + if(!d_meele_texture1) + prim_melee_type = 28; + if(!d_meele_texture2) + sec_melee_type = 28; + + //give NPCs skill values... + int r; + for(r = 0; r <= HIGHEST_SKILL; r++) { + skills[r] = database.GetSkillCap(GetClass(),(SkillUseTypes)r,moblevel); + } + + if(d->trap_template > 0) + { + std::map >::iterator trap_ent_iter; + std::list trap_list; + + trap_ent_iter = zone->ldon_trap_entry_list.find(d->trap_template); + if(trap_ent_iter != zone->ldon_trap_entry_list.end()) + { + trap_list = trap_ent_iter->second; + if(trap_list.size() > 0) + { + std::list::iterator trap_list_iter = trap_list.begin(); + std::advance(trap_list_iter, MakeRandomInt(0, trap_list.size() - 1)); + LDoNTrapTemplate* tt = (*trap_list_iter); + if(tt) + { + if((uint8)tt->spell_id > 0) + { + ldon_trapped = true; + ldon_spell_id = tt->spell_id; + } + else + { + ldon_trapped = false; + ldon_spell_id = 0; + } + + ldon_trap_type = (uint8)tt->type; + if(tt->locked > 0) + { + ldon_locked = true; + ldon_locked_skill = tt->skill; + } + else + { + ldon_locked = false; + ldon_locked_skill = 0; + } + ldon_trap_detected = 0; + } + } + else + { + ldon_trapped = false; + ldon_trap_type = 0; + ldon_spell_id = 0; + ldon_locked = false; + ldon_locked_skill = 0; + ldon_trap_detected = 0; + } + } + else + { + ldon_trapped = false; + ldon_trap_type = 0; + ldon_spell_id = 0; + ldon_locked = false; + ldon_locked_skill = 0; + ldon_trap_detected = 0; + } + } + else + { + ldon_trapped = false; + ldon_trap_type = 0; + ldon_spell_id = 0; + ldon_locked = false; + ldon_locked_skill = 0; + ldon_trap_detected = 0; + } + reface_timer = new Timer(15000); + reface_timer->Disable(); + qGlobals = nullptr; + guard_x_saved = 0; + guard_y_saved = 0; + guard_z_saved = 0; + guard_heading_saved = 0; + SetEmoteID(d->emoteid); + InitializeBuffSlots(); + CalcBonuses(); +} + +NPC::~NPC() +{ + AI_Stop(); + + if(proximity != nullptr) { + entity_list.RemoveProximity(GetID()); + safe_delete(proximity); + } + + safe_delete(NPCTypedata_ours); + + { + ItemList::iterator cur,end; + cur = itemlist.begin(); + end = itemlist.end(); + for(; cur != end; ++cur) { + ServerLootItem_Struct* item = *cur; + safe_delete(item); + } + itemlist.clear(); + } + + { + std::list::iterator cur,end; + cur = faction_list.begin(); + end = faction_list.end(); + for(; cur != end; ++cur) { + struct NPCFaction* fac = *cur; + safe_delete(fac); + } + faction_list.clear(); + } + + safe_delete(reface_timer); + safe_delete(swarmInfoPtr); + safe_delete(qGlobals); + //Moved this from ~Mob, because it could cause a crash in some cases where a hate list was still used and that mob was the only one on the hate list. + entity_list.RemoveFromTargets(this, true); + UninitializeBuffSlots(); +} + +void NPC::SetTarget(Mob* mob) { + if(mob == GetTarget()) //dont bother if they are allready our target + return; + + //our target is already set, do not turn from the course, unless our current target is dead. + if(GetSwarmInfo() && GetTarget() && (GetTarget()->GetHP() > 0)) { + Mob *targ = entity_list.GetMob(GetSwarmInfo()->target); + if(targ != mob){ + return; + } + } + + if (mob) { + SetAttackTimer(); + } else { + ranged_timer.Disable(); + //attack_timer.Disable(); + attack_dw_timer.Disable(); + } + Mob::SetTarget(mob); +} + +ServerLootItem_Struct* NPC::GetItem(int slot_id) { + ItemList::iterator cur,end; + cur = itemlist.begin(); + end = itemlist.end(); + for(; cur != end; ++cur) { + ServerLootItem_Struct* item = *cur; + if (item->equipSlot == slot_id) { + return item; + } + } + return(nullptr); +} + +void NPC::RemoveItem(uint32 item_id, uint16 quantity, uint16 slot) { + ItemList::iterator cur,end; + cur = itemlist.begin(); + end = itemlist.end(); + for(; cur != end; ++cur) { + ServerLootItem_Struct* item = *cur; + if (item->item_id == item_id && slot <= 0 && quantity <= 0) { + itemlist.erase(cur); + return; + } + else if (item->item_id == item_id && item->equipSlot == slot && quantity >= 1) { + //std::cout<<"NPC::RemoveItem"<<" equipSlot:"<equipSlot<<" quantity:"<< quantity<charges <= quantity) + itemlist.erase(cur); + else + item->charges -= quantity; + return; + } + } +} + +void NPC::CheckMinMaxLevel(Mob *them) +{ + if(them == nullptr || !them->IsClient()) + return; + + uint16 themlevel = them->GetLevel(); + uint8 material; + + std::list::iterator cur = itemlist.begin(); + while(cur != itemlist.end()) + { + if(!(*cur)) + return; + + if(themlevel < (*cur)->minlevel || themlevel > (*cur)->maxlevel) + { + material = Inventory::CalcMaterialFromSlot((*cur)->equipSlot); + if(material != 0xFF) + SendWearChange(material); + + cur = itemlist.erase(cur); + continue; + } + ++cur; + } + +} + +void NPC::ClearItemList() { + ItemList::iterator cur,end; + cur = itemlist.begin(); + end = itemlist.end(); + for(; cur != end; ++cur) { + ServerLootItem_Struct* item = *cur; + safe_delete(item); + } + itemlist.clear(); +} + +void NPC::QueryLoot(Client* to) { + int x = 0; + to->Message(0, "Coin: %ip %ig %is %ic", platinum, gold, silver, copper); + + ItemList::iterator cur,end; + cur = itemlist.begin(); + end = itemlist.end(); + for(; cur != end; ++cur) { + const Item_Struct* item = database.GetItem((*cur)->item_id); + if (item) + if (to->GetClientVersion() >= EQClientRoF) + { + to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(*cur)->minlevel, (*cur)->maxlevel, (int) item->ID,0x12, item->ID, item->Name, 0x12); + } + else if (to->GetClientVersion() >= EQClientSoF) + { + to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X00000000000000000000000000000000000000000000%s%c",(*cur)->minlevel, (*cur)->maxlevel, (int) item->ID,0x12, item->ID, item->Name, 0x12); + } + else + { + to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X000000000000000000000000000000000000000%s%c",(*cur)->minlevel, (*cur)->maxlevel, (int) item->ID,0x12, item->ID, item->Name, 0x12); + } + else + LogFile->write(EQEMuLog::Error, "Database error, invalid item"); + x++; + } + to->Message(0, "%i items on %s.", x, GetName()); +} + +void NPC::AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_platinum) { + if(in_copper >= 0) + copper = in_copper; + else + copper = 0; + + if(in_silver >= 0) + silver = in_silver; + else + silver = 0; + + if(in_gold >= 0) + gold = in_gold; + else + gold = 0; + + if(in_platinum >= 0) + platinum = in_platinum; + else + platinum = 0; +} + +void NPC::AddCash() { + copper = MakeRandomInt(1, 100); + silver = MakeRandomInt(1, 50); + gold = MakeRandomInt(1, 10); + platinum = MakeRandomInt(1, 5); +} + +void NPC::RemoveCash() { + copper = 0; + silver = 0; + gold = 0; + platinum = 0; +} + +bool NPC::Process() +{ + if (IsStunned() && stunned_timer.Check()) + { + this->stunned = false; + this->stunned_timer.Disable(); + this->spun_timer.Disable(); + } + + if (p_depop) + { + Mob* owner = entity_list.GetMob(this->ownerid); + if (owner != 0) + { + //if(GetBodyType() != BT_SwarmPet) + // owner->SetPetID(0); + this->ownerid = 0; + this->petid = 0; + } + return false; + } + + SpellProcess(); + + if(tic_timer.Check()) + { + BuffProcess(); + + if(curfp) + ProcessFlee(); + + uint32 bonus = 0; + + if(GetAppearance() == eaSitting) + bonus+=3; + + int32 OOCRegen = 0; + if(oocregen > 0){ //should pull from Mob class + OOCRegen += GetMaxHP() * oocregen / 100; + } + //Lieka Edit:Fixing NPC regen.NPCs should regen to full during a set duration, not based on their HPs.Increase NPC's HPs by % of total HPs / tick. + if((GetHP() < GetMaxHP()) && !IsPet()) { + if(!IsEngaged()) {//NPC out of combat + if(hp_regen > OOCRegen) + SetHP(GetHP() + hp_regen); + else + SetHP(GetHP() + OOCRegen); + } else + SetHP(GetHP()+hp_regen); + } else if(GetHP() < GetMaxHP() && GetOwnerID() !=0) { + if(!IsEngaged()) //pet + SetHP(GetHP()+hp_regen+bonus+(GetLevel()/5)); + else + SetHP(GetHP()+hp_regen+bonus); + } else + SetHP(GetHP()+hp_regen); + + if(GetMana() < GetMaxMana()) { + SetMana(GetMana()+mana_regen+bonus); + } + + + if(zone->adv_data && !p_depop) + { + ServerZoneAdventureDataReply_Struct* ds = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; + if(ds->type == Adventure_Rescue && ds->data_id == GetNPCTypeID()) + { + Mob *o = GetOwner(); + if(o && o->IsClient()) + { + float x_diff = ds->dest_x - GetX(); + float y_diff = ds->dest_y - GetY(); + float z_diff = ds->dest_z - GetZ(); + float dist = ((x_diff * x_diff) + (y_diff * y_diff) + (z_diff * z_diff)); + if(dist < RuleR(Adventure, DistanceForRescueComplete)) + { + zone->DoAdventureCountIncrease(); + Say("You don't know what this means to me. Thank you so much for finding and saving me from" + " this wretched place. I'll find my way from here."); + Depop(); + } + } + } + } + } + + if (sendhpupdate_timer.Check() && (IsTargeted() || (IsPet() && GetOwner() && GetOwner()->IsClient()))) { + if(!IsFullHP || cur_hp 999) + viral_timer_counter = 0; + } + + if(projectile_timer.Check()) + SpellProjectileEffect(); + + if(spellbonuses.GravityEffect == 1) { + if(gravity_timer.Check()) + DoGravityEffect(); + } + + if(reface_timer->Check() && !IsEngaged() && (guard_x == GetX() && guard_y == GetY() && guard_z == GetZ())) { + SetHeading(guard_heading); + SendPosition(); + reface_timer->Disable(); + } + + if (IsMezzed()) + return true; + + if(IsStunned()) { + if(spun_timer.Check()) + Spin(); + return true; + } + + if (enraged_timer.Check()){ + ProcessEnrage(); + } + + //Handle assists... + if(assist_timer.Check() && IsEngaged() && !Charmed()) { + entity_list.AIYellForHelp(this, GetTarget()); + } + + if(qGlobals) + { + if(qglobal_purge_timer.Check()) + { + qGlobals->PurgeExpiredGlobals(); + } + } + + AI_Process(); + + return true; +} + +uint32 NPC::CountLoot() { + return(itemlist.size()); +} + +void NPC::Depop(bool StartSpawnTimer) { + uint16 emoteid = this->GetEmoteID(); + if(emoteid != 0) + this->DoNPCEmote(ONDESPAWN,emoteid); + p_depop = true; + if (StartSpawnTimer) { + if (respawn2 != 0) { + respawn2->DeathReset(); + } + } +} + +bool NPC::DatabaseCastAccepted(int spell_id) { + for (int i=0; i < 12; i++) { + switch(spells[spell_id].effectid[i]) { + case SE_Stamina: { + if(IsEngaged() && GetHPRatio() < 100) + return true; + else + return false; + break; + } + case SE_CurrentHPOnce: + case SE_CurrentHP: { + if(this->GetHPRatio() < 100 && spells[spell_id].buffduration == 0) + return true; + else + return false; + break; + } + + case SE_HealOverTime: { + if(this->GetHPRatio() < 100) + return true; + else + return false; + break; + } + case SE_DamageShield: { + return true; + } + case SE_NecPet: + case SE_SummonPet: { + if(GetPet()){ +#ifdef SPELLQUEUE + printf("%s: Attempted to make a second pet, denied.\n",GetName()); +#endif + return false; + } + break; + } + case SE_LocateCorpse: + case SE_SummonCorpse: { + return false; //Pfft, npcs don't need to summon corpses/locate corpses! + break; + } + default: + if(spells[spell_id].goodEffect == 1 && !(spells[spell_id].buffduration == 0 && this->GetHPRatio() == 100) && !IsEngaged()) + return true; + return false; + } + } + return false; +} + +NPC* NPC::SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z, float in_heading, Client* client) { + if(spawncommand == 0 || spawncommand[0] == 0) { + return 0; + } + else { + Seperator sep(spawncommand); + //Lets see if someone didn't fill out the whole #spawn function properly + if (!sep.IsNumber(1)) + sprintf(sep.arg[1],"1"); + if (!sep.IsNumber(2)) + sprintf(sep.arg[2],"1"); + if (!sep.IsNumber(3)) + sprintf(sep.arg[3],"0"); + if (atoi(sep.arg[4]) > 2100000000 || atoi(sep.arg[4]) <= 0) + sprintf(sep.arg[4]," "); + if (!strcmp(sep.arg[5],"-")) + sprintf(sep.arg[5]," "); + if (!sep.IsNumber(5)) + sprintf(sep.arg[5]," "); + if (!sep.IsNumber(6)) + sprintf(sep.arg[6],"1"); + if (!sep.IsNumber(8)) + sprintf(sep.arg[8],"0"); + if (!sep.IsNumber(9)) + sprintf(sep.arg[9], "0"); + if (!sep.IsNumber(7)) + sprintf(sep.arg[7],"0"); + if (!strcmp(sep.arg[4],"-")) + sprintf(sep.arg[4]," "); + if (!sep.IsNumber(10)) // bodytype + sprintf(sep.arg[10], "0"); + //Calc MaxHP if client neglected to enter it... + if (!sep.IsNumber(4)) { + //Stolen from Client::GetMaxHP... + uint8 multiplier = 0; + int tmplevel = atoi(sep.arg[2]); + switch(atoi(sep.arg[5])) + { + case WARRIOR: + if (tmplevel < 20) + multiplier = 22; + else if (tmplevel < 30) + multiplier = 23; + else if (tmplevel < 40) + multiplier = 25; + else if (tmplevel < 53) + multiplier = 27; + else if (tmplevel < 57) + multiplier = 28; + else + multiplier = 30; + break; + + case DRUID: + case CLERIC: + case SHAMAN: + multiplier = 15; + break; + + case PALADIN: + case SHADOWKNIGHT: + if (tmplevel < 35) + multiplier = 21; + else if (tmplevel < 45) + multiplier = 22; + else if (tmplevel < 51) + multiplier = 23; + else if (tmplevel < 56) + multiplier = 24; + else if (tmplevel < 60) + multiplier = 25; + else + multiplier = 26; + break; + + case MONK: + case BARD: + case ROGUE: + //case BEASTLORD: + if (tmplevel < 51) + multiplier = 18; + else if (tmplevel < 58) + multiplier = 19; + else + multiplier = 20; + break; + + case RANGER: + if (tmplevel < 58) + multiplier = 20; + else + multiplier = 21; + break; + + case MAGICIAN: + case WIZARD: + case NECROMANCER: + case ENCHANTER: + multiplier = 12; + break; + + default: + if (tmplevel < 35) + multiplier = 21; + else if (tmplevel < 45) + multiplier = 22; + else if (tmplevel < 51) + multiplier = 23; + else if (tmplevel < 56) + multiplier = 24; + else if (tmplevel < 60) + multiplier = 25; + else + multiplier = 26; + break; + } + sprintf(sep.arg[4],"%i",5+multiplier*atoi(sep.arg[2])+multiplier*atoi(sep.arg[2])*75/300); + } + + // Autoselect NPC Gender + if (sep.arg[5][0] == 0) { + sprintf(sep.arg[5], "%i", (int) Mob::GetDefaultGender(atoi(sep.arg[1]))); + } + + //Time to create the NPC!! + NPCType* npc_type = new NPCType; + memset(npc_type, 0, sizeof(NPCType)); + + strncpy(npc_type->name, sep.arg[0], 60); + npc_type->cur_hp = atoi(sep.arg[4]); + npc_type->max_hp = atoi(sep.arg[4]); + npc_type->race = atoi(sep.arg[1]); + npc_type->gender = atoi(sep.arg[5]); + npc_type->class_ = atoi(sep.arg[6]); + npc_type->deity = 1; + npc_type->level = atoi(sep.arg[2]); + npc_type->npc_id = 0; + npc_type->loottable_id = 0; + npc_type->texture = atoi(sep.arg[3]); + npc_type->light = 0; + npc_type->runspeed = 1.25; + npc_type->d_meele_texture1 = atoi(sep.arg[7]); + npc_type->d_meele_texture2 = atoi(sep.arg[8]); + npc_type->merchanttype = atoi(sep.arg[9]); + npc_type->bodytype = atoi(sep.arg[10]); + + npc_type->STR = 150; + npc_type->STA = 150; + npc_type->DEX = 150; + npc_type->AGI = 150; + npc_type->INT = 150; + npc_type->WIS = 150; + npc_type->CHA = 150; + + npc_type->prim_melee_type = 28; + npc_type->sec_melee_type = 28; + + NPC* npc = new NPC(npc_type, 0, in_x, in_y, in_z, in_heading/8, FlyMode3); + npc->GiveNPCTypeData(npc_type); + + entity_list.AddNPC(npc); + + if (client) { + // Notify client of spawn data + client->Message(0, "New spawn:"); + client->Message(0, "Name: %s", npc->name); + client->Message(0, "Race: %u", npc->race); + client->Message(0, "Level: %u", npc->level); + client->Message(0, "Material: %u", npc->texture); + client->Message(0, "Current/Max HP: %i", npc->max_hp); + client->Message(0, "Gender: %u", npc->gender); + client->Message(0, "Class: %u", npc->class_); + client->Message(0, "Weapon Item Number: %u/%u", npc->d_meele_texture1, npc->d_meele_texture2); + client->Message(0, "MerchantID: %u", npc->MerchantType); + client->Message(0, "Bodytype: %u", npc->bodytype); + } + + return npc; + } +} + +uint32 ZoneDatabase::NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn, uint32 extra) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char *query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + uint32 tmp = 0; + uint32 tmp2 = 0; + uint32 last_insert_id = 0; + switch (command) { + case 0: { // Create a new NPC and add all spawn related data + uint32 npc_type_id = 0; + uint32 spawngroupid; + if (extra && c && c->GetZoneID()) + { + // Set an npc_type ID within the standard range for the current zone if possible (zone_id * 1000) + int starting_npc_id = c->GetZoneID() * 1000; + if (RunQuery(query, MakeAnyLenString(&query, "SELECT MAX(id) FROM npc_types WHERE id >= %i AND id < %i", starting_npc_id, (starting_npc_id + 1000)), errbuf, &result)) { + row = mysql_fetch_row(result); + if(row) + { + if (row[0]) + { + npc_type_id = atoi(row[0]) + 1; + // Prevent the npc_type id from exceeding the range for this zone + if (npc_type_id >= (starting_npc_id + 1000)) + { + npc_type_id = 0; + } + } + else + { + // row[0] is nullptr - No npc_type IDs set in this range yet + npc_type_id = starting_npc_id; + } + } + + safe_delete_array(query); + mysql_free_result(result); + } + } + char tmpstr[64]; + EntityList::RemoveNumbers(strn0cpy(tmpstr, spawn->GetName(), sizeof(tmpstr))); + if (npc_type_id) + { + if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO npc_types (id, name, level, race, class, hp, gender, texture, helmtexture, size, loottable_id, merchant_id, face, runspeed, prim_melee_type, sec_melee_type) values(%i,\"%s\",%i,%i,%i,%i,%i,%i,%i,%f,%i,%i,%i,%f,%i,%i)", npc_type_id, tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28), errbuf, 0, 0, &npc_type_id)) { + LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); + safe_delete(query); + return false; + } + } + else + { + if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO npc_types (name, level, race, class, hp, gender, texture, helmtexture, size, loottable_id, merchant_id, face, runspeed, prim_melee_type, sec_melee_type) values(\"%s\",%i,%i,%i,%i,%i,%i,%i,%f,%i,%i,%i,%f,%i,%i)", tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28), errbuf, 0, 0, &npc_type_id)) { + LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); + safe_delete(query); + return false; + } + } + if(c) c->LogSQL(query); + safe_delete_array(query); + snprintf(tmpstr, sizeof(tmpstr), "%s-%s", zone, spawn->GetName()); + if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawngroup (id, name) values(%i, '%s')", tmp, tmpstr), errbuf, 0, 0, &spawngroupid)) { + LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) values('%s', %u, %f, %f, %f, %i, %f, %i)", zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), 1200, spawn->GetHeading(), spawngroupid), errbuf, 0, 0, &tmp)) { + LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawnentry (spawngroupID, npcID, chance) values(%i, %i, %i)", spawngroupid, npc_type_id, 100), errbuf, 0)) { + LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + return true; + break; + } + case 1:{ // Add new spawn group and spawn point for an existing NPC Type ID + tmp2 = spawn->GetNPCTypeID(); + char tmpstr[64]; + snprintf(tmpstr, sizeof(tmpstr), "%s%s%i", zone, spawn->GetName(),Timer::GetCurrentTime()); + if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawngroup (name) values('%s')", tmpstr), errbuf, 0, 0, &last_insert_id)) { + LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + + uint32 respawntime = 0; + uint32 spawnid = 0; + if (extra) + respawntime = extra; + else if(spawn->respawn2 && spawn->respawn2->RespawnTimer() != 0) + respawntime = spawn->respawn2->RespawnTimer(); + else + respawntime = 1200; + if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) values('%s', %u, %f, %f, %f, %i, %f, %i)", zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), respawntime, spawn->GetHeading(), last_insert_id), errbuf, 0, 0, &spawnid)) { + LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + + if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawnentry (spawngroupID, npcID, chance) values(%i, %i, %i)", last_insert_id, tmp2, 100), errbuf, 0)) { + LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + return spawnid; + break; + } + case 2: { // Update npc_type appearance and other data on targeted spawn + if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE npc_types SET name=\"%s\", level=%i, race=%i, class=%i, hp=%i, gender=%i, texture=%i, helmtexture=%i, size=%i, loottable_id=%i, merchant_id=%i, face=%i, WHERE id=%i", spawn->GetName(), spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, spawn->GetNPCTypeID()), errbuf, 0)) { + if(c) c->LogSQL(query); + safe_delete_array(query); + return true; + } + else { + safe_delete_array(query); + return false; + } + break; + } + case 3: { // delete spawn from spawning, but leave in npc_types table + if (!RunQuery(query, MakeAnyLenString(&query, "SELECT id,spawngroupID from spawn2 where zone='%s' AND spawngroupID=%i", zone, spawn->GetSp2()), errbuf, &result)) { + safe_delete_array(query); + return 0; + } + safe_delete_array(query); + + row = mysql_fetch_row(result); + if (row == nullptr) return false; + if (row[0]) tmp = atoi(row[0]); + if (row[1]) tmp2 = atoi(row[1]); + + if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawn2 WHERE id='%i'", tmp), errbuf,0)) { + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawngroup WHERE id='%i'", tmp2), errbuf,0)) { + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawnentry WHERE spawngroupID='%i'", tmp2), errbuf,0)) { + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + return true; + + + break; + } + case 4: { //delete spawn from DB (including npc_type) + if (!RunQuery(query, MakeAnyLenString(&query, "SELECT id,spawngroupID from spawn2 where zone='%s' AND version=%u AND spawngroupID=%i", zone, zone_version, spawn->GetSp2()), errbuf, &result)) { + safe_delete_array(query); + return(0); + } + safe_delete_array(query); + + row = mysql_fetch_row(result); + if (row == nullptr) return false; + if (row[0]) tmp = atoi(row[0]); + if (row[1]) tmp2 = atoi(row[1]); + mysql_free_result(result); + + if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawn2 WHERE id='%i'", tmp), errbuf,0)) { + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawngroup WHERE id='%i'", tmp2), errbuf,0)) { + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawnentry WHERE spawngroupID='%i'", tmp2), errbuf,0)) { + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM npc_types WHERE id='%i'", spawn->GetNPCTypeID()), errbuf,0)) { + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + return true; + break; + } + case 5: { // add a spawn from spawngroup + if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) values('%s', %u, %f, %f, %f, %i, %f, %i)", zone, zone_version, c->GetX(), c->GetY(), c->GetZ(), 120, c->GetHeading(), extra), errbuf, 0, 0, &tmp)) { + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + + return true; + break; + } + case 6: { // add npc_type + uint32 npc_type_id; + char tmpstr[64]; + EntityList::RemoveNumbers(strn0cpy(tmpstr, spawn->GetName(), sizeof(tmpstr))); + if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO npc_types (name, level, race, class, hp, gender, texture, helmtexture, size, loottable_id, merchant_id, face, runspeed, prim_melee_type, sec_melee_type) values(\"%s\",%i,%i,%i,%i,%i,%i,%i,%f,%i,%i,%i,%f,%i,%i)", tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28), errbuf, 0, 0, &npc_type_id)) { + safe_delete(query); + return false; + } + if(c) c->LogSQL(query); + safe_delete_array(query); + if(c) c->Message(0, "%s npc_type ID %i created successfully!", tmpstr, npc_type_id); + return true; + break; + } + } + return false; +} + +int32 NPC::GetEquipmentMaterial(uint8 material_slot) const +{ + if (material_slot >= _MaterialCount) + return 0; + + int inv_slot = Inventory::CalcSlotFromMaterial(material_slot); + if (inv_slot == -1) + return 0; + if(equipment[inv_slot] == 0) { + switch(material_slot) { + case MaterialHead: + return helmtexture; + case MaterialChest: + return texture; + case MaterialPrimary: + return d_meele_texture1; + case MaterialSecondary: + return d_meele_texture2; + default: + //they have nothing in the slot, and its not a special slot... they get nothing. + return(0); + } + } + + //they have some loot item in this slot, pass it up to the default handler + return(Mob::GetEquipmentMaterial(material_slot)); +} + +uint32 NPC::GetMaxDamage(uint8 tlevel) +{ + uint32 dmg = 0; + if (tlevel < 40) + dmg = tlevel*2+2; + else if (tlevel < 50) + dmg = level*25/10+2; + else if (tlevel < 60) + dmg = (tlevel*3+2)+((tlevel-50)*30); + else + dmg = (tlevel*3+2)+((tlevel-50)*35); + return dmg; +} + +void NPC::PickPocket(Client* thief) { + + thief->CheckIncreaseSkill(SkillPickPockets, nullptr, 5); + + //make sure were allowed to targte them: + int olevel = GetLevel(); + if(olevel > (thief->GetLevel() + THIEF_PICKPOCKET_OVER)) { + thief->Message(13, "You are too inexperienced to pick pocket this target"); + thief->SendPickPocketResponse(this, 0, PickPocketFailed); + //should we check aggro + return; + } + + if(MakeRandomInt(0, 100) > 95){ + AddToHateList(thief, 50); + Say("Stop thief!"); + thief->Message(13, "You are noticed trying to steal!"); + thief->SendPickPocketResponse(this, 0, PickPocketFailed); + return; + } + + int steal_skill = thief->GetSkill(SkillPickPockets); + int stealchance = steal_skill*100/(5*olevel+5); + ItemInst* inst = 0; + int x = 0; + int slot[50]; + int steal_items[50]; + int charges[50]; + int money[4]; + money[0] = GetPlatinum(); + money[1] = GetGold(); + money[2] = GetSilver(); + money[3] = GetCopper(); + if (steal_skill < 125) + money[0] = 0; + if (steal_skill < 60) + money[1] = 0; + memset(slot,0,50); + memset(steal_items,0,50); + memset(charges,0,50); + //Determine wheter to steal money or an item. + bool no_coin = ((money[0] + money[1] + money[2] + money[3]) == 0); + bool steal_item = (MakeRandomInt(0, 99) < 50 || no_coin); + if (steal_item) + { + ItemList::iterator cur,end; + cur = itemlist.begin(); + end = itemlist.end(); + for(; cur != end && x < 49; ++cur) { + ServerLootItem_Struct* citem = *cur; + const Item_Struct* item = database.GetItem(citem->item_id); + if (item) + { + inst = database.CreateItem(item, citem->charges); + bool is_arrow = (item->ItemType == ItemTypeArrow) ? true : false; + int slot_id = thief->GetInv().FindFreeSlot(false, true, inst->GetItem()->Size, is_arrow); + if (/*!Equipped(item->ID) &&*/ + !item->Magic && item->NoDrop != 0 && !inst->IsType(ItemClassContainer) && slot_id != SLOT_INVALID + /*&& steal_skill > item->StealSkill*/ ) + { + slot[x] = slot_id; + steal_items[x] = item->ID; + if (inst->IsStackable()) + charges[x] = 1; + else + charges[x] = citem->charges; + x++; + } + } + } + if (x > 0) + { + int random = MakeRandomInt(0, x-1); + inst = database.CreateItem(steal_items[random], charges[random]); + if (inst) + { + const Item_Struct* item = inst->GetItem(); + if (item) + { + if (/*item->StealSkill || */steal_skill >= stealchance) + { + thief->PutItemInInventory(slot[random], *inst); + thief->SendItemPacket(slot[random], inst, ItemPacketTrade); + RemoveItem(item->ID); + thief->SendPickPocketResponse(this, 0, PickPocketItem, item); + } + else + steal_item = false; + } + else + steal_item = false; + } + else + steal_item = false; + } + else if (!no_coin) + { + steal_item = false; + } + else + { + thief->Message(0, "This target's pockets are empty"); + thief->SendPickPocketResponse(this, 0, PickPocketFailed); + } + } + if (!steal_item) //Steal money + { + uint32 amt = MakeRandomInt(1, (steal_skill/25)+1); + int steal_type = 0; + if (!money[0]) + { + steal_type = 1; + if (!money[1]) + { + steal_type = 2; + if (!money[2]) + { + steal_type = 3; + } + } + } + + if (MakeRandomInt(0, 100) <= stealchance) + { + switch (steal_type) + { + case 0:{ + if (amt > GetPlatinum()) + amt = GetPlatinum(); + SetPlatinum(GetPlatinum()-amt); + thief->AddMoneyToPP(0,0,0,amt,false); + thief->SendPickPocketResponse(this, amt, PickPocketPlatinum); + break; + } + case 1:{ + if (amt > GetGold()) + amt = GetGold(); + SetGold(GetGold()-amt); + thief->AddMoneyToPP(0,0,amt,0,false); + thief->SendPickPocketResponse(this, amt, PickPocketGold); + break; + } + case 2:{ + if (amt > GetSilver()) + amt = GetSilver(); + SetSilver(GetSilver()-amt); + thief->AddMoneyToPP(0,amt,0,0,false); + thief->SendPickPocketResponse(this, amt, PickPocketSilver); + break; + } + case 3:{ + if (amt > GetCopper()) + amt = GetCopper(); + SetCopper(GetCopper()-amt); + thief->AddMoneyToPP(amt,0,0,0,false); + thief->SendPickPocketResponse(this, amt, PickPocketCopper); + break; + } + } + } + else + { + thief->SendPickPocketResponse(this, 0, PickPocketFailed); + } + } + safe_delete(inst); +} + +void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool remove) { + if(reset) + { + ClearSpecialAbilities(); + } + + const char* orig_parse = parse; + while (*parse) + { + switch(*parse) + { + case 'E': + SetSpecialAbility(SPECATK_ENRAGE, remove ? 0 : 1); + break; + case 'F': + SetSpecialAbility(SPECATK_FLURRY, remove ? 0 : 1); + break; + case 'R': + SetSpecialAbility(SPECATK_RAMPAGE, remove ? 0 : 1); + break; + case 'r': + SetSpecialAbility(SPECATK_AREA_RAMPAGE, remove ? 0 : 1); + break; + case 'S': + if(remove) { + SetSpecialAbility(SPECATK_SUMMON, 0); + StopSpecialAbilityTimer(SPECATK_SUMMON); + } else { + SetSpecialAbility(SPECATK_SUMMON, 1); + } + break; + case 'T': + SetSpecialAbility(SPECATK_TRIPLE, remove ? 0 : 1); + break; + case 'Q': + //quad requires triple to work properly + if(remove) { + SetSpecialAbility(SPECATK_QUAD, 0); + } else { + SetSpecialAbility(SPECATK_TRIPLE, 1); + SetSpecialAbility(SPECATK_QUAD, 1); + } + break; + case 'b': + SetSpecialAbility(SPECATK_BANE, remove ? 0 : 1); + break; + case 'm': + SetSpecialAbility(SPECATK_MAGICAL, remove ? 0 : 1); + break; + case 'U': + SetSpecialAbility(UNSLOWABLE, remove ? 0 : 1); + break; + case 'M': + SetSpecialAbility(UNMEZABLE, remove ? 0 : 1); + break; + case 'C': + SetSpecialAbility(UNCHARMABLE, remove ? 0 : 1); + break; + case 'N': + SetSpecialAbility(UNSTUNABLE, remove ? 0 : 1); + break; + case 'I': + SetSpecialAbility(UNSNAREABLE, remove ? 0 : 1); + break; + case 'D': + SetSpecialAbility(UNFEARABLE, remove ? 0 : 1); + break; + case 'K': + SetSpecialAbility(UNDISPELLABLE, remove ? 0 : 1); + break; + case 'A': + SetSpecialAbility(IMMUNE_MELEE, remove ? 0 : 1); + break; + case 'B': + SetSpecialAbility(IMMUNE_MAGIC, remove ? 0 : 1); + break; + case 'f': + SetSpecialAbility(IMMUNE_FLEEING, remove ? 0 : 1); + break; + case 'O': + SetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE, remove ? 0 : 1); + break; + case 'W': + SetSpecialAbility(IMMUNE_MELEE_NONMAGICAL, remove ? 0 : 1); + break; + case 'H': + SetSpecialAbility(IMMUNE_AGGRO, remove ? 0 : 1); + break; + case 'G': + SetSpecialAbility(IMMUNE_AGGRO_ON, remove ? 0 : 1); + break; + case 'g': + SetSpecialAbility(IMMUNE_CASTING_FROM_RANGE, remove ? 0 : 1); + break; + case 'd': + SetSpecialAbility(IMMUNE_FEIGN_DEATH, remove ? 0 : 1); + break; + case 'Y': + SetSpecialAbility(SPECATK_RANGED_ATK, remove ? 0 : 1); + break; + case 'L': + SetSpecialAbility(SPECATK_INNATE_DW, remove ? 0 : 1); + break; + case 't': + SetSpecialAbility(NPC_TUNNELVISION, remove ? 0 : 1); + break; + case 'n': + SetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS, remove ? 0 : 1); + break; + case 'p': + SetSpecialAbility(IMMUNE_PACIFY, remove ? 0 : 1); + break; + case 'J': + SetSpecialAbility(LEASH, remove ? 0 : 1); + break; + case 'j': + SetSpecialAbility(TETHER, remove ? 0 : 1); + break; + case 'o': + SetSpecialAbility(DESTRUCTIBLE_OBJECT, remove ? 0 : 1); + SetDestructibleObject(remove ? true : false); + break; + case 'Z': + SetSpecialAbility(NO_HARM_FROM_CLIENT, remove ? 0 : 1); + break; + case 'i': + SetSpecialAbility(IMMUNE_TAUNT, remove ? 0 : 1); + break; + case 'e': + SetSpecialAbility(ALWAYS_FLEE, remove ? 0 : 1); + break; + case 'h': + SetSpecialAbility(FLEE_PERCENT, remove ? 0 : 1); + break; + + default: + break; + } + parse++; + } + + if(permtag == 1 && this->GetNPCTypeID() > 0) + { + if(database.SetSpecialAttkFlag(this->GetNPCTypeID(), orig_parse)) + { + LogFile->write(EQEMuLog::Normal, "NPCTypeID: %i flagged to '%s' for Special Attacks.\n",this->GetNPCTypeID(),orig_parse); + } + } +} + +bool Mob::HasNPCSpecialAtk(const char* parse) { + + bool HasAllAttacks = true; + + while (*parse && HasAllAttacks == true) + { + switch(*parse) + { + case 'E': + if (!GetSpecialAbility(SPECATK_ENRAGE)) + HasAllAttacks = false; + break; + case 'F': + if (!GetSpecialAbility(SPECATK_FLURRY)) + HasAllAttacks = false; + break; + case 'R': + if (!GetSpecialAbility(SPECATK_RAMPAGE)) + HasAllAttacks = false; + break; + case 'r': + if (!GetSpecialAbility(SPECATK_AREA_RAMPAGE)) + HasAllAttacks = false; + break; + case 'S': + if (!GetSpecialAbility(SPECATK_SUMMON)) + HasAllAttacks = false; + break; + case 'T': + if (!GetSpecialAbility(SPECATK_TRIPLE)) + HasAllAttacks = false; + break; + case 'Q': + if (!GetSpecialAbility(SPECATK_QUAD)) + HasAllAttacks = false; + break; + case 'b': + if (!GetSpecialAbility(SPECATK_BANE)) + HasAllAttacks = false; + break; + case 'm': + if (!GetSpecialAbility(SPECATK_MAGICAL)) + HasAllAttacks = false; + break; + case 'U': + if (!GetSpecialAbility(UNSLOWABLE)) + HasAllAttacks = false; + break; + case 'M': + if (!GetSpecialAbility(UNMEZABLE)) + HasAllAttacks = false; + break; + case 'C': + if (!GetSpecialAbility(UNCHARMABLE)) + HasAllAttacks = false; + break; + case 'N': + if (!GetSpecialAbility(UNSTUNABLE)) + HasAllAttacks = false; + break; + case 'I': + if (!GetSpecialAbility(UNSNAREABLE)) + HasAllAttacks = false; + break; + case 'D': + if (!GetSpecialAbility(UNFEARABLE)) + HasAllAttacks = false; + break; + case 'A': + if (!GetSpecialAbility(IMMUNE_MELEE)) + HasAllAttacks = false; + break; + case 'B': + if (!GetSpecialAbility(IMMUNE_MAGIC)) + HasAllAttacks = false; + break; + case 'f': + if (!GetSpecialAbility(IMMUNE_FLEEING)) + HasAllAttacks = false; + break; + case 'O': + if (!GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) + HasAllAttacks = false; + break; + case 'W': + if (!GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)) + HasAllAttacks = false; + break; + case 'H': + if (!GetSpecialAbility(IMMUNE_AGGRO)) + HasAllAttacks = false; + break; + case 'G': + if (!GetSpecialAbility(IMMUNE_AGGRO_ON)) + HasAllAttacks = false; + break; + case 'g': + if (!GetSpecialAbility(IMMUNE_CASTING_FROM_RANGE)) + HasAllAttacks = false; + break; + case 'd': + if (!GetSpecialAbility(IMMUNE_FEIGN_DEATH)) + HasAllAttacks = false; + break; + case 'Y': + if (!GetSpecialAbility(SPECATK_RANGED_ATK)) + HasAllAttacks = false; + break; + case 'L': + if (!GetSpecialAbility(SPECATK_INNATE_DW)) + HasAllAttacks = false; + break; + case 't': + if (!GetSpecialAbility(NPC_TUNNELVISION)) + HasAllAttacks = false; + break; + case 'n': + if (!GetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS)) + HasAllAttacks = false; + break; + case 'p': + if(!GetSpecialAbility(IMMUNE_PACIFY)) + HasAllAttacks = false; + break; + case 'J': + if(!GetSpecialAbility(LEASH)) + HasAllAttacks = false; + break; + case 'j': + if(!GetSpecialAbility(TETHER)) + HasAllAttacks = false; + break; + case 'o': + if(!GetSpecialAbility(DESTRUCTIBLE_OBJECT)) + { + HasAllAttacks = false; + SetDestructibleObject(false); + } + break; + case 'Z': + if(!GetSpecialAbility(NO_HARM_FROM_CLIENT)){ + HasAllAttacks = false; + } + break; + case 'e': + if(!GetSpecialAbility(ALWAYS_FLEE)) + HasAllAttacks = false; + break; + case 'h': + if(!GetSpecialAbility(FLEE_PERCENT)) + HasAllAttacks = false; + break; + default: + HasAllAttacks = false; + break; + } + parse++; + } + + return HasAllAttacks; +} + +void NPC::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) +{ + Mob::FillSpawnStruct(ns, ForWho); + + //Basic settings to make sure swarm pets work properly. + if (GetSwarmOwner()) { + Client *c = entity_list.GetClientByID(GetSwarmOwner()); + if(c) { + SetAllowBeneficial(1); //Allow client cast swarm pets to be heal/buffed. + //This is a hack to allow CLIENT swarm pets NOT to be targeted with F8. Warning: Will turn name 'Yellow'! + if (RuleB(Pets, SwarmPetNotTargetableWithHotKey)) + ns->spawn.IsMercenary = 1; + } + //NPC cast swarm pets should still be targetable with F8. + else + ns->spawn.IsMercenary = 0; + } + + //Not recommended if using above (However, this will work better on older clients). + if (RuleB(Pets, UnTargetableSwarmPet)) { + if(GetOwnerID() || GetSwarmOwner()) { + ns->spawn.is_pet = 1; + if (!IsCharmed() && GetOwnerID()) { + Client *c = entity_list.GetClientByID(GetOwnerID()); + if(c) + sprintf(ns->spawn.lastName, "%s's Pet", c->GetName()); + } + else if (GetSwarmOwner()) { + ns->spawn.bodytype = 11; + if(!IsCharmed()) + { + Client *c = entity_list.GetClientByID(GetSwarmOwner()); + if(c) + sprintf(ns->spawn.lastName, "%s's Pet", c->GetName()); + } + } + } + } else { + if(GetOwnerID()) { + ns->spawn.is_pet = 1; + if (!IsCharmed() && GetOwnerID()) { + Client *c = entity_list.GetClientByID(GetOwnerID()); + if(c) + sprintf(ns->spawn.lastName, "%s's Pet", c->GetName()); + } + } else + ns->spawn.is_pet = 0; + } + + ns->spawn.is_npc = 1; +} + +void NPC::SetLevel(uint8 in_level, bool command) +{ + if(in_level > level) + SendLevelAppearance(); + level = in_level; + SendAppearancePacket(AT_WhoLevel, in_level); +} + +void NPC::ModifyNPCStat(const char *identifier, const char *newValue) +{ + std::string id = identifier; + std::string val = newValue; + for(int i = 0; i < id.length(); ++i) + { + id[i] = std::tolower(id[i]); + } + + if(id == "ac") + { + AC = atoi(val.c_str()); + return; + } + + if(id == "str") + { + STR = atoi(val.c_str()); + return; + } + + if(id == "sta") + { + STA = atoi(val.c_str()); + return; + } + + if(id == "agi") + { + AGI = atoi(val.c_str()); + return; + } + + if(id == "dex") + { + DEX = atoi(val.c_str()); + return; + } + + if(id == "wis") + { + WIS = atoi(val.c_str()); + CalcMaxMana(); + return; + } + + if(id == "int" || id == "_int") + { + INT = atoi(val.c_str()); + CalcMaxMana(); + return; + } + + if(id == "cha") + { + CHA = atoi(val.c_str()); + return; + } + + if(id == "max_hp") + { + base_hp = atoi(val.c_str()); + CalcMaxHP(); + if(cur_hp > max_hp) + cur_hp = max_hp; + return; + } + + if(id == "max_mana") + { + npc_mana = atoi(val.c_str()); + CalcMaxMana(); + if(cur_mana > max_mana) + cur_mana = max_mana; + return; + } + + if(id == "mr") + { + MR = atoi(val.c_str()); + return; + } + + if(id == "fr") + { + FR = atoi(val.c_str()); + return; + } + + if(id == "cr") + { + CR = atoi(val.c_str()); + return; + } + + if(id == "pr") + { + PR = atoi(val.c_str()); + return; + } + + if(id == "dr") + { + DR = atoi(val.c_str()); + return; + } + + if(id == "PhR") + { + PhR = atoi(val.c_str()); + return; + } + + if(id == "runspeed") + { + runspeed = (float)atof(val.c_str()); + CalcBonuses(); + return; + } + + if(id == "special_attacks") + { + //Added reset flag. + NPCSpecialAttacks(val.c_str(), 0, 1); + return; + } + + if(id == "attack_speed") + { + attack_speed = (float)atof(val.c_str()); + CalcBonuses(); + return; + } + + if(id == "atk") + { + ATK = atoi(val.c_str()); + return; + } + + if(id == "accuracy") + { + accuracy_rating = atoi(val.c_str()); + return; + } + + if(id == "trackable") + { + trackable = atoi(val.c_str()); + return; + } + + if(id == "min_hit") + { + min_dmg = atoi(val.c_str()); + return; + } + + if(id == "max_hit") + { + max_dmg = atoi(val.c_str()); + return; + } + + if(id == "attack_count") + { + attack_count = atoi(val.c_str()); + return; + } + + if(id == "see_invis") + { + see_invis = atoi(val.c_str()); + return; + } + + if(id == "see_invis_undead") + { + see_invis_undead = atoi(val.c_str()); + return; + } + + if(id == "see_hide") + { + see_hide = atoi(val.c_str()); + return; + } + + if(id == "see_improved_hide") + { + see_improved_hide = atoi(val.c_str()); + return; + } + + if(id == "hp_regen") + { + hp_regen = atoi(val.c_str()); + return; + } + + if(id == "mana_regen") + { + mana_regen = atoi(val.c_str()); + return; + } + + if(id == "level") + { + SetLevel(atoi(val.c_str())); + return; + } + + if(id == "aggro") + { + pAggroRange = atof(val.c_str()); + return; + } + + if(id == "assist") + { + pAssistRange = atof(val.c_str()); + return; + } + + if(id == "slow_mitigation") + { + slow_mitigation = atoi(val.c_str()); + return; + } + if(id == "loottable_id") + { + loottable_id = atof(val.c_str()); + return; + } + if(id == "healscale") + { + healscale = atof(val.c_str()); + return; + } + if(id == "spellscale") + { + spellscale = atof(val.c_str()); + return; + } +} + +void NPC::LevelScale() { + + uint8 random_level = (MakeRandomInt(level, maxlevel)); + + float scaling = (((random_level / (float)level) - 1) * (scalerate / 100.0f)); + + // Compensate for scale rates at low levels so they don't add too much + uint8 scale_adjust = 1; + if(level > 0 && level <= 5) + scale_adjust = 10; + if(level > 5 && level <= 10) + scale_adjust = 5; + if(level > 10 && level <= 15) + scale_adjust = 3; + if(level > 15 && level <= 25) + scale_adjust = 2; + + base_hp += (int)(base_hp * scaling); + max_hp += (int)(max_hp * scaling); + cur_hp = max_hp; + STR += (int)(STR * scaling / scale_adjust); + STA += (int)(STA * scaling / scale_adjust); + AGI += (int)(AGI * scaling / scale_adjust); + DEX += (int)(DEX * scaling / scale_adjust); + INT += (int)(INT * scaling / scale_adjust); + WIS += (int)(WIS * scaling / scale_adjust); + CHA += (int)(CHA * scaling / scale_adjust); + if (MR) + MR += (int)(MR * scaling / scale_adjust); + if (CR) + CR += (int)(CR * scaling / scale_adjust); + if (DR) + DR += (int)(DR * scaling / scale_adjust); + if (FR) + FR += (int)(FR * scaling / scale_adjust); + if (PR) + PR += (int)(PR * scaling / scale_adjust); + + if (max_dmg) + { + max_dmg += (int)(max_dmg * scaling / scale_adjust); + min_dmg += (int)(min_dmg * scaling / scale_adjust); + } + + level = random_level; + + return; +} + +void NPC::CalcNPCResists() { + + if (!MR) + MR = (GetLevel() * 11)/10; + if (!CR) + CR = (GetLevel() * 11)/10; + if (!DR) + DR = (GetLevel() * 11)/10; + if (!FR) + FR = (GetLevel() * 11)/10; + if (!PR) + PR = (GetLevel() * 11)/10; + if (!Corrup) + Corrup = 15; + if (!PhR) + PhR = 10; + return; +} + +void NPC::CalcNPCRegen() { + + // Fix for lazy db-updaters (regen values left at 0) + if (GetCasterClass() != 'N' && mana_regen == 0) + mana_regen = (GetLevel() / 10) + 4; + else if(mana_regen < 0) + mana_regen = 0; + else + mana_regen = mana_regen; + + // Gives low end monsters no regen if set to 0 in database. Should make low end monsters killable + // Might want to lower this to /5 rather than 10. + if(hp_regen == 0) + { + if(GetLevel() <= 6) + hp_regen = 1; + else if(GetLevel() > 6 && GetLevel() <= 10) + hp_regen = 2; + else if(GetLevel() > 10 && GetLevel() <= 15) + hp_regen = 3; + else if(GetLevel() > 15 && GetLevel() <= 20) + hp_regen = 5; + else if(GetLevel() > 20 && GetLevel() <= 30) + hp_regen = 7; + else if(GetLevel() > 30 && GetLevel() <= 35) + hp_regen = 9; + else if(GetLevel() > 35 && GetLevel() <= 40) + hp_regen = 12; + else if(GetLevel() > 40 && GetLevel() <= 45) + hp_regen = 18; + else if(GetLevel() > 45 && GetLevel() <= 50) + hp_regen = 21; + else + hp_regen = 30; + } else if(hp_regen < 0) { + hp_regen = 0; + } else + hp_regen = hp_regen; + + return; +} + +void NPC::CalcNPCDamage() { + + int AC_adjust=12; + + if (GetLevel() >= 66) { + if (min_dmg==0) + min_dmg = 220; + if (max_dmg==0) + max_dmg = ((((99000)*(GetLevel()-64))/400)*AC_adjust/10); + } + else if (GetLevel() >= 60 && GetLevel() <= 65){ + if(min_dmg==0) + min_dmg = (GetLevel()+(GetLevel()/3)); + if(max_dmg==0) + max_dmg = (GetLevel()*3)*AC_adjust/10; + } + else if (GetLevel() >= 51 && GetLevel() <= 59){ + if(min_dmg==0) + min_dmg = (GetLevel()+(GetLevel()/3)); + if(max_dmg==0) + max_dmg = (GetLevel()*3)*AC_adjust/10; + } + else if (GetLevel() >= 40 && GetLevel() <= 50) { + if (min_dmg==0) + min_dmg = GetLevel(); + if(max_dmg==0) + max_dmg = (GetLevel()*3)*AC_adjust/10; + } + else if (GetLevel() >= 28 && GetLevel() <= 39) { + if (min_dmg==0) + min_dmg = GetLevel() / 2; + if (max_dmg==0) + max_dmg = ((GetLevel()*2)+2)*AC_adjust/10; + } + else if (GetLevel() <= 27) { + if (min_dmg==0) + min_dmg=1; + if (max_dmg==0) + max_dmg = (GetLevel()*2)*AC_adjust/10; + } + + int clfact = GetClassLevelFactor(); + min_dmg = (min_dmg * clfact) / 220; + max_dmg = (max_dmg * clfact) / 220; + + return; +} + + +uint32 NPC::GetSpawnPointID() const +{ + if(respawn2) + { + return respawn2->GetID(); + } + return 0; +} + +void NPC::NPCSlotTexture(uint8 slot, uint16 texture) +{ + if (slot == 7) { + d_meele_texture1 = texture; + } + else if (slot == 8) { + d_meele_texture2 = texture; + } + else if (slot < 6) { + // Reserved for texturing individual armor slots + } + return; +} + +uint32 NPC::GetSwarmOwner() +{ + if(GetSwarmInfo() != nullptr) + { + return GetSwarmInfo()->owner_id; + } + return 0; +} + +uint32 NPC::GetSwarmTarget() +{ + if(GetSwarmInfo() != nullptr) + { + return GetSwarmInfo()->target; + } + return 0; +} + +void NPC::SetSwarmTarget(int target_id) +{ + if(GetSwarmInfo() != nullptr) + { + GetSwarmInfo()->target = target_id; + } + return; +} + +int32 NPC::CalcMaxMana() { + if(npc_mana == 0) { + switch (GetCasterClass()) { + case 'I': + max_mana = (((GetINT()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana; + break; + case 'W': + max_mana = (((GetWIS()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana; + break; + case 'N': + default: + max_mana = 0; + break; + } + if (max_mana < 0) { + max_mana = 0; + } + + return max_mana; + } else { + switch (GetCasterClass()) { + case 'I': + max_mana = npc_mana + spellbonuses.Mana + itembonuses.Mana; + break; + case 'W': + max_mana = npc_mana + spellbonuses.Mana + itembonuses.Mana; + break; + case 'N': + default: + max_mana = 0; + break; + } + if (max_mana < 0) { + max_mana = 0; + } + + return max_mana; + } +} + +void NPC::SignalNPC(int _signal_id) +{ + signal_q.push_back(_signal_id); +} + +NPC_Emote_Struct* NPC::GetNPCEmote(uint16 emoteid, uint8 event_) { + LinkedListIterator iterator(zone->NPCEmoteList); + iterator.Reset(); + while(iterator.MoreElements()) + { + NPC_Emote_Struct* nes = iterator.GetData(); + if (emoteid == nes->emoteid && event_ == nes->event_) { + return (nes); + } + iterator.Advance(); + } + return (nullptr); +} + +void NPC::DoNPCEmote(uint8 event_, uint16 emoteid) +{ + if(this == nullptr || emoteid == 0) + { + return; + } + + NPC_Emote_Struct* nes = GetNPCEmote(emoteid,event_); + if(nes == nullptr) + { + return; + } + + if(emoteid == nes->emoteid) + { + if(nes->type == 1) + this->Emote("%s",nes->text); + else if(nes->type == 2) + this->Shout("%s",nes->text); + else if(nes->type == 3) + entity_list.MessageClose_StringID(this, true, 200, 10, GENERIC_STRING, nes->text); + else + this->Say("%s",nes->text); + } +} + +bool NPC::CanTalk() +{ + //Races that should be able to talk. (Races up to Titanium) + + uint16 TalkRace[473] = + {1,2,3,4,5,6,7,8,9,10,11,12,0,0,15,16,0,18,19,20,0,0,23,0,25,0,0,0,0,0,0, + 32,0,0,0,0,0,0,39,40,0,0,0,44,0,0,0,0,49,0,51,0,53,54,55,56,57,58,0,0,0, + 62,0,64,65,66,67,0,0,70,71,0,0,0,0,0,77,78,79,0,81,82,0,0,0,86,0,0,0,90, + 0,92,93,94,95,0,0,98,99,0,101,0,103,0,0,0,0,0,0,110,111,112,0,0,0,0,0,0, + 0,0,0,0,123,0,0,126,0,128,0,130,131,0,0,0,0,136,137,0,139,140,0,0,0,144, + 0,0,0,0,0,150,151,152,153,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,183,184,0,0,187,188,189,0,0,0,0,0,195,196,0,198,0,0,0,202,0, + 0,205,0,0,208,0,0,0,0,0,0,0,0,217,0,219,0,0,0,0,0,0,226,0,0,229,230,0,0, + 0,0,235,236,0,238,239,240,241,242,243,244,0,246,247,0,0,0,251,0,0,254,255, + 256,257,0,0,0,0,0,0,0,0,266,267,0,0,270,271,0,0,0,0,0,277,278,0,0,0,0,283, + 284,0,286,0,288,289,290,0,0,0,0,295,296,297,298,299,300,0,0,0,304,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,320,0,322,323,324,325,0,0,0,0,330,331,332,333,334,335, + 336,337,338,339,340,341,342,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,359,360,361,362, + 0,364,365,366,0,368,369,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,385,386,0,0,0,0,0,392, + 393,394,395,396,397,398,0,400,402,0,0,0,0,406,0,408,0,0,411,0,413,0,0,0,417, + 0,0,420,0,0,0,0,425,0,0,0,0,0,0,0,433,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,458,0,0,0,0,0,0,0,0,467,0,0,470,0,0,473}; + + int talk_check = TalkRace[GetRace() - 1]; + + if (TalkRace[GetRace() - 1] > 0) + return true; + + return false; +} + +//this is called with 'this' as the mob being looked at, and +//iOther the mob who is doing the looking. It should figure out +//what iOther thinks about 'this' +FACTION_VALUE NPC::GetReverseFactionCon(Mob* iOther) { + iOther = iOther->GetOwnerOrSelf(); + int primaryFaction= iOther->GetPrimaryFaction(); + + //I am pretty sure that this special faction call is backwards + //and should be iOther->GetSpecialFactionCon(this) + if (primaryFaction < 0) + return GetSpecialFactionCon(iOther); + + if (primaryFaction == 0) + return FACTION_INDIFFERENT; + + //if we are a pet, use our owner's faction stuff + Mob *own = GetOwner(); + if (own != nullptr) + return own->GetReverseFactionCon(iOther); + + //make sure iOther is an npc + //also, if we dont have a faction, then they arnt gunna think anything of us either + if(!iOther->IsNPC() || GetPrimaryFaction() == 0) + return(FACTION_INDIFFERENT); + + //if we get here, iOther is an NPC too + + //otherwise, employ the npc faction stuff + //so we need to look at iOther's faction table to see + //what iOther thinks about our primary faction + return(iOther->CastToNPC()->CheckNPCFactionAlly(GetPrimaryFaction())); +} + +//Look through our faction list and return a faction con based +//on the npc_value for the other person's primary faction in our list. +FACTION_VALUE NPC::CheckNPCFactionAlly(int32 other_faction) { + std::list::iterator cur,end; + cur = faction_list.begin(); + end = faction_list.end(); + for(; cur != end; ++cur) { + struct NPCFaction* fac = *cur; + if ((int32)fac->factionID == other_faction) { + if (fac->npc_value > 0) + return FACTION_ALLY; + else if (fac->npc_value < 0) + return FACTION_SCOWLS; + else + return FACTION_INDIFFERENT; + } + } + return FACTION_INDIFFERENT; +} + +bool NPC::IsFactionListAlly(uint32 other_faction) { + return(CheckNPCFactionAlly(other_faction) == FACTION_ALLY); +} + +int NPC::GetScore() +{ + int lv = std::min(70, (int)GetLevel()); + int basedmg = (lv*2)*(1+(lv / 100)) - (lv / 2); + int minx = 0; + int basehp = 0; + int hpcontrib = 0; + int dmgcontrib = 0; + int spccontrib = 0; + int hp = GetMaxHP(); + int mindmg = min_dmg; + int maxdmg = max_dmg; + int final; + + if(lv < 46) + { + minx = static_cast (ceil( ((lv - (lv / 10.0)) - 1.0) )); + basehp = (lv * 10) + (lv * lv); + } + else + { + minx = static_cast (ceil( ((lv - (lv / 10.0)) - 1.0) - (( lv - 45.0 ) / 2.0) )); + basehp = (lv * 10) + ((lv * lv) * 4); + } + + if(hp > basehp) + { + hpcontrib = static_cast (((hp / static_cast (basehp)) * 1.5)); + if(hpcontrib > 5) { hpcontrib = 5; } + + if(maxdmg > basedmg) + { + dmgcontrib = static_cast (ceil( ((maxdmg / basedmg) * 1.5) )); + } + + if(HasNPCSpecialAtk("E")) { spccontrib++; } //Enrage + if(HasNPCSpecialAtk("F")) { spccontrib++; } //Flurry + if(HasNPCSpecialAtk("R")) { spccontrib++; } //Rampage + if(HasNPCSpecialAtk("r")) { spccontrib++; } //Area Rampage + if(HasNPCSpecialAtk("S")) { spccontrib++; } //Summon + if(HasNPCSpecialAtk("T")) { spccontrib += 2; } //Triple + if(HasNPCSpecialAtk("Q")) { spccontrib += 3; } //Quad + if(HasNPCSpecialAtk("U")) { spccontrib += 5; } //Unslowable + if(HasNPCSpecialAtk("L")) { spccontrib++; } //Innate Dual Wield + } + + if(npc_spells_id > 12) + { + if(lv < 16) + spccontrib++; + else + spccontrib += static_cast (floor(lv/15.0)); + } + + final = minx + hpcontrib + dmgcontrib + spccontrib; + final = std::max(1, final); + final = std::min(100, final); + return(final); +} + +uint32 NPC::GetSpawnKillCount() +{ + uint32 sid = GetSpawnPointID(); + + if(sid > 0) + { + return(zone->GetSpawnKillCount(sid)); + } + + return(0); +} + +void NPC::DoQuestPause(Mob *other) { + if(IsMoving() && !IsOnHatelist(other)) { + PauseWandering(RuleI(NPC, SayPauseTimeInSec)); + FaceTarget(other); + } else if(!IsMoving()) { + FaceTarget(other); + } + +} diff --git a/zone/perl_npcX.cpp b/zone/perl_npcX.cpp new file mode 100644 index 000000000..957baf7ab --- /dev/null +++ b/zone/perl_npcX.cpp @@ -0,0 +1,2487 @@ +/* +* This file was generated automatically by xsubpp version 1.9508 from the +* contents of tmp. Do not edit this file, edit tmp instead. +* +* ANY CHANGES MADE HERE WILL BE LOST! +* +*/ + + +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "../common/features.h" +#ifdef EMBPERL_XS_CLASSES +#include "../common/debug.h" +#include "embperl.h" + +#ifdef seed +#undef seed +#endif + +typedef const char Const_char; + +#include "npc.h" + +#ifdef THIS /* this macro seems to leak out on some systems */ +#undef THIS +#endif + + +XS(XS_NPC_SignalNPC); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SignalNPC) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SignalNPC(THIS, _signal_id)"); + { + NPC * THIS; + int _signal_id = (int)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SignalNPC(_signal_id); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_CheckNPCFactionAlly); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_CheckNPCFactionAlly) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::CheckNPCFactionAlly(THIS, other_faction)"); + { + NPC * THIS; + FACTION_VALUE RETVAL; + dXSTARG; + int32 other_faction = (int32)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->CheckNPCFactionAlly(other_faction); + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_AddItem); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_AddItem) +{ + dXSARGS; + if (items < 2 || items > 4) + Perl_croak(aTHX_ "Usage: NPC::AddItem(THIS, itemid, charges = 0, equipitem = true)"); + { + NPC * THIS; + uint32 itemid = (uint32)SvUV(ST(1)); + uint16 charges = 0; + bool equipitem = true; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (items > 2) + charges = (uint16)SvUV(ST(2)); + if (items > 3) + equipitem = (bool)SvTRUE(ST(3)); + + THIS->AddItem(itemid, charges, equipitem); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_AddLootTable); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_AddLootTable) +{ + dXSARGS; + if (items < 1) + Perl_croak(aTHX_ "Usage: NPC::AddLootTable(THIS, [loottable_id])"); + { + NPC * THIS; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + uint32 loottable_id = 0; + + if(items > 1) + { + loottable_id = (uint32)SvUV(ST(1)); + THIS->AddLootTable(loottable_id); + } + else + { + THIS->AddLootTable(); + } + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_RemoveItem); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_RemoveItem) +{ + dXSARGS; + if (items < 2 || items > 4) + Perl_croak(aTHX_ "Usage: NPC::RemoveItem(THIS, item_id, quantity= 0, slot= 0)"); + { + NPC * THIS; + uint32 item_id = (uint32)SvUV(ST(1)); + uint16 quantity; + uint16 slot; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (items < 3) + quantity = 0; + else { + quantity = (uint16)SvUV(ST(2)); + } + + if (items < 4) + slot = 0; + else { + slot = (uint16)SvUV(ST(3)); + } + + THIS->RemoveItem(item_id, quantity, slot); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_ClearItemList); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_ClearItemList) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::ClearItemList(THIS)"); + { + NPC * THIS; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->ClearItemList(); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_AddCash); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_AddCash) +{ + dXSARGS; + if (items != 5) + Perl_croak(aTHX_ "Usage: NPC::AddCash(THIS, in_copper, in_silver, in_gold, in_platinum)"); + { + NPC * THIS; + uint16 in_copper = (uint16)SvUV(ST(1)); + uint16 in_silver = (uint16)SvUV(ST(2)); + uint16 in_gold = (uint16)SvUV(ST(3)); + uint16 in_platinum = (uint16)SvUV(ST(4)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->AddCash(in_copper, in_silver, in_gold, in_platinum); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_RemoveCash); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_RemoveCash) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::RemoveCash(THIS)"); + { + NPC * THIS; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->RemoveCash(); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_CountLoot); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_CountLoot) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::CountLoot(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->CountLoot(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetLoottableID); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetLoottableID) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetLoottableID(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetLoottableID(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetCopper); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetCopper) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetCopper(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetCopper(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSilver); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSilver) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSilver(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetSilver(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetGold); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetGold) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetGold(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetGold(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetPlatinum); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetPlatinum) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetPlatinum(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetPlatinum(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_SetCopper); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetCopper) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetCopper(THIS, amt)"); + { + NPC * THIS; + uint32 amt = (uint32)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetCopper(amt); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_SetSilver); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetSilver) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetSilver(THIS, amt)"); + { + NPC * THIS; + uint32 amt = (uint32)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetSilver(amt); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_SetGold); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetGold) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetGold(THIS, amt)"); + { + NPC * THIS; + uint32 amt = (uint32)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetGold(amt); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_SetPlatinum); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetPlatinum) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetPlatinum(THIS, amt)"); + { + NPC * THIS; + uint32 amt = (uint32)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetPlatinum(amt); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_SetGrid); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetGrid) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetGrid(THIS, grid_)"); + { + NPC * THIS; + int32 grid_ = (int32)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetGrid(grid_); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_SetSaveWaypoint); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetSaveWaypoint) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetSaveWaypoint(THIS, waypoint)"); + { + NPC * THIS; + uint16 waypoint = (uint16)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetSaveWaypoint(waypoint); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_SetSp2); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetSp2) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetSp2(THIS, sg2)"); + { + NPC * THIS; + uint32 sg2 = (uint32)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetSp2(sg2); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_GetWaypointMax); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetWaypointMax) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetWaypointMax(THIS)"); + { + NPC * THIS; + uint16 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetWaypointMax(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetGrid); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetGrid) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetGrid(THIS)"); + { + NPC * THIS; + int32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetGrid(); + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSp2); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSp2) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSp2(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetSp2(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetNPCFactionID); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetNPCFactionID) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetNPCFactionID(THIS)"); + { + NPC * THIS; + int32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetNPCFactionID(); + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetPrimaryFaction); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetPrimaryFaction) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetPrimaryFaction(THIS)"); + { + NPC * THIS; + int32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetPrimaryFaction(); + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetNPCHate); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetNPCHate) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::GetNPCHate(THIS, in_ent)"); + { + NPC * THIS; + int32 RETVAL; + dXSTARG; + Mob* in_ent; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (sv_derived_from(ST(1), "Mob")) { + IV tmp = SvIV((SV*)SvRV(ST(1))); + in_ent = INT2PTR(Mob *,tmp); + } + else + Perl_croak(aTHX_ "in_ent is not of type Mob"); + if(in_ent == nullptr) + Perl_croak(aTHX_ "in_ent is nullptr, avoiding crash."); + + RETVAL = THIS->GetNPCHate(in_ent); + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_IsOnHatelist); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_IsOnHatelist) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::IsOnHatelist(THIS, p)"); + { + NPC * THIS; + bool RETVAL; + Mob* p; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (sv_derived_from(ST(1), "Mob")) { + IV tmp = SvIV((SV*)SvRV(ST(1))); + p = INT2PTR(Mob *,tmp); + } + else + Perl_croak(aTHX_ "p is not of type Mob"); + if(p == nullptr) + Perl_croak(aTHX_ "p is nullptr, avoiding crash."); + + RETVAL = THIS->IsOnHatelist(p); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_NPC_SetNPCFactionID); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetNPCFactionID) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetNPCFactionID(THIS, in)"); + { + NPC * THIS; + int32 in = (int32)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetNPCFactionID(in); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_GetMaxDMG); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetMaxDMG) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetMaxDMG(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetMaxDMG(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetMinDMG); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetMinDMG) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetMinDMG(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetMinDMG(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + + +XS(XS_NPC_IsAnimal); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_IsAnimal) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::IsAnimal(THIS)"); + { + NPC * THIS; + bool RETVAL; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->IsAnimal(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_NPC_GetPetSpellID); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetPetSpellID) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetPetSpellID(THIS)"); + { + NPC * THIS; + uint16 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetPetSpellID(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_SetPetSpellID); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetPetSpellID) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetPetSpellID(THIS, amt)"); + { + NPC * THIS; + uint16 amt = (uint16)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetPetSpellID(amt); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_GetMaxDamage); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetMaxDamage) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::GetMaxDamage(THIS, tlevel)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + uint8 tlevel = (uint8)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetMaxDamage(tlevel); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_SetTaunting); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetTaunting) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetTaunting(THIS, tog)"); + { + NPC * THIS; + bool tog = (bool)SvTRUE(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetTaunting(tog); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_PickPocket); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_PickPocket) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::PickPocket(THIS, thief)"); + { + NPC * THIS; + Client* thief; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (sv_derived_from(ST(1), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(1))); + thief = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "thief is not of type Client"); + if(thief == nullptr) + Perl_croak(aTHX_ "thief is nullptr, avoiding crash."); + + THIS->PickPocket(thief); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_StartSwarmTimer); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_StartSwarmTimer) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::StartSwarmTimer(THIS, duration)"); + { + NPC * THIS; + uint32 duration = (uint32)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->StartSwarmTimer(duration); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_DoClassAttacks); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_DoClassAttacks) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::DoClassAttacks(THIS, target)"); + { + NPC * THIS; + Mob * target; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (sv_derived_from(ST(1), "Mob")) { + IV tmp = SvIV((SV*)SvRV(ST(1))); + target = INT2PTR(Mob *,tmp); + } + else + Perl_croak(aTHX_ "target is not of type Mob"); + if(target == nullptr) + Perl_croak(aTHX_ "target is nullptr, avoiding crash."); + + THIS->DoClassAttacks(target); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_GetMaxWp); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetMaxWp) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetMaxWp(THIS)"); + { + NPC * THIS; + int RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetMaxWp(); + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_DisplayWaypointInfo); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_DisplayWaypointInfo) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::DisplayWaypointInfo(THIS, to)"); + { + NPC * THIS; + Client * to; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (sv_derived_from(ST(1), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(1))); + to = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "to is not of type Client"); + if(to == nullptr) + Perl_croak(aTHX_ "to is nullptr, avoiding crash."); + + THIS->DisplayWaypointInfo(to); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_CalculateNewWaypoint); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_CalculateNewWaypoint) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::CalculateNewWaypoint(THIS)"); + { + NPC * THIS; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->CalculateNewWaypoint(); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_AssignWaypoints); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_AssignWaypoints) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::AssignWaypoints(THIS, grid)"); + { + NPC * THIS; + uint32 grid = (uint32)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->AssignWaypoints(grid); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_SetWaypointPause); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetWaypointPause) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::SetWaypointPause(THIS)"); + { + NPC * THIS; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetWaypointPause(); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_UpdateWaypoint); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_UpdateWaypoint) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::UpdateWaypoint(THIS, wp_index)"); + { + NPC * THIS; + int wp_index = (int)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->UpdateWaypoint(wp_index); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_StopWandering); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_StopWandering) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::StopWandering(THIS)"); + { + NPC * THIS; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->StopWandering(); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_ResumeWandering); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_ResumeWandering) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::ResumeWandering(THIS)"); + { + NPC * THIS; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->ResumeWandering(); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_PauseWandering); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_PauseWandering) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::PauseWandering(THIS, pausetime)"); + { + NPC * THIS; + int pausetime = (int)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->PauseWandering(pausetime); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_MoveTo); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_MoveTo) +{ + dXSARGS; + if (items != 4 && items != 5 && items != 6) + Perl_croak(aTHX_ "Usage: NPC::MoveTo(THIS, mtx, mty, mtz, [mth, saveguard?])"); + { + NPC * THIS; + float mtx = (float)SvNV(ST(1)); + float mty = (float)SvNV(ST(2)); + float mtz = (float)SvNV(ST(3)); + float mth; + bool saveguard; + + if(items > 4) + mth = (float)SvNV(ST(4)); + else + mth = 0; + + if(items > 5) + saveguard = (bool)SvTRUE(ST(5)); + else + saveguard = false; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->MoveTo(mtx, mty, mtz, mth, saveguard); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_NextGuardPosition); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_NextGuardPosition) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::NextGuardPosition(THIS)"); + { + NPC * THIS; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->NextGuardPosition(); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_SaveGuardSpot); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SaveGuardSpot) +{ + dXSARGS; + if (items < 1 || items > 2) + Perl_croak(aTHX_ "Usage: NPC::SaveGuardSpot(THIS, iClearGuardSpot= false)"); + { + NPC * THIS; + bool iClearGuardSpot; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (items < 2) + iClearGuardSpot = false; + else { + iClearGuardSpot = (bool)SvTRUE(ST(1)); + } + + THIS->SaveGuardSpot(iClearGuardSpot); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_IsGuarding); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_IsGuarding) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::IsGuarding(THIS)"); + { + NPC * THIS; + bool RETVAL; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->IsGuarding(); + ST(0) = boolSV(RETVAL); + sv_2mortal(ST(0)); + } + XSRETURN(1); +} + +XS(XS_NPC_AI_SetRoambox); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_AI_SetRoambox) +{ + dXSARGS; + if (items < 6 || items > 8) + Perl_croak(aTHX_ "Usage: NPC::AI_SetRoambox(THIS, iDist, iMaxX, iMinX, iMaxY, iMinY, iDelay= 2500, iMinDelay= 2500)"); + { + NPC * THIS; + float iDist = (float)SvNV(ST(1)); + float iMaxX = (float)SvNV(ST(2)); + float iMinX = (float)SvNV(ST(3)); + float iMaxY = (float)SvNV(ST(4)); + float iMinY = (float)SvNV(ST(5)); + uint32 iDelay; + uint32 iMinDelay; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (items < 7){ + iMinDelay = 2500; + iDelay = 2500; + } + else if (items < 8){ + iMinDelay = 2500; + iDelay = (uint32)SvUV(ST(6)); + } + else { + iDelay = (uint32)SvUV(ST(6)); + iMinDelay = (uint32)SvUV(ST(7)); + } + + THIS->AI_SetRoambox(iDist, iMaxX, iMinX, iMaxY, iMinY, iDelay, iMinDelay); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_GetNPCSpellsID); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetNPCSpellsID) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetNPCSpellsID(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetNPCSpellsID(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSpawnPointID); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSpawnPointID) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointID(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetSpawnPointID(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSpawnPointX); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSpawnPointX) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointX(THIS)"); + { + NPC * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + + RETVAL = THIS->GetSpawnPointX(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSpawnPointY); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSpawnPointY) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointY(THIS)"); + { + NPC * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + + RETVAL = THIS->GetSpawnPointY(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSpawnPointZ); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSpawnPointZ) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointZ(THIS)"); + { + NPC * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + + RETVAL = THIS->GetSpawnPointZ(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSpawnPointH); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSpawnPointH) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointH(THIS)"); + { + NPC * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + + RETVAL = THIS->GetSpawnPointH(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetGuardPointX); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetGuardPointX) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetGuardPointX(THIS)"); + { + NPC * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + + RETVAL = THIS->GetGuardPointX(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetGuardPointY); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetGuardPointY) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetGuardPointY(THIS)"); + { + NPC * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + + RETVAL = THIS->GetGuardPointY(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetGuardPointZ); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetGuardPointZ) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetGuardPointZ(THIS)"); + { + NPC * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + + RETVAL = THIS->GetGuardPointZ(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_SetPrimSkill); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetPrimSkill) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetPrimSkill(THIS, skill_id)"); + { + NPC * THIS; + int skill_id = (int)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetPrimSkill(skill_id); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_SetSecSkill); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetSecSkill) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetSecSkill(THIS, skill_id)"); + { + NPC * THIS; + int skill_id = (int)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetSecSkill(skill_id); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_GetPrimSkill); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetPrimSkill) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetPrimSkill(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetPrimSkill(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSecSkill); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSecSkill) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSecSkill(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetSecSkill(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSwarmOwner); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSwarmOwner) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSwarmOwner(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetSwarmOwner(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSwarmTarget); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSwarmTarget) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSwarmTarget(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetSwarmTarget(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_SetSwarmTarget); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetSwarmTarget) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetSwarmTarget(THIS, target_id)"); + { + NPC * THIS; + int target_id = (int)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetSwarmTarget(target_id); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_ModifyNPCStat); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_ModifyNPCStat) +{ + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: NPC::ModifyNPCStat(THIS, identifier, newValue)"); + { + NPC * THIS; + Const_char * identifier = (Const_char *)SvPV_nolen(ST(1)); + Const_char * newValue = (Const_char *)SvPV_nolen(ST(2)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->ModifyNPCStat(identifier, newValue); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_AddSpellToNPCList); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_AddSpellToNPCList) +{ + dXSARGS; + if (items != 7) + Perl_croak(aTHX_ "Usage: NPC::AddAISpell(THIS, priority, spell_id, type, mana_cost, recast_delay, resist_adjust)"); + { + NPC * THIS; + int priority = (int)SvIV(ST(1)); + int spell_id = (int)SvIV(ST(2)); + int type = (int)SvIV(ST(3)); + int mana_cost = (int)SvIV(ST(4)); + int recast_delay = (int)SvIV(ST(5)); + int resist_adjust = (int)SvIV(ST(6)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->AddSpellToNPCList(priority, spell_id, type, mana_cost, recast_delay, resist_adjust); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_RemoveSpellFromNPCList); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_RemoveSpellFromNPCList) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::RemoveAISpell(THIS, spell_id)"); + { + NPC * THIS; + int spell_id = (int)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->RemoveSpellFromNPCList(spell_id); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_SetSpellFocusDMG); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetSpellFocusDMG) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetSpellFocusDMG(THIS, NewSpellFocusDMG)"); + { + NPC * THIS; + int32 NewSpellFocusDMG = (int32)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetSpellFocusDMG(NewSpellFocusDMG); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_GetSpellFocusDMG); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSpellFocusDMG) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusDMG(THIS)"); + { + NPC * THIS; + int32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetSpellFocusDMG(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_SetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_SetSpellFocusHeal) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetSpellFocusHeal(THIS, NewSpellFocusHeal)"); + { + NPC * THIS; + int32 NewSpellFocusHeal = (int32)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetSpellFocusHeal(NewSpellFocusHeal); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_GetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSpellFocusHeal) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusHeal(THIS)"); + { + NPC * THIS; + int32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetSpellFocusHeal(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSlowMitigation); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSlowMitigation) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSlowMitigation(THIS)"); + { + NPC * THIS; + int16 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetSlowMitigation(); + XSprePUSH; PUSHn((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetAttackSpeed); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetAttackSpeed) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetAttackSpeed(THIS)"); + { + NPC * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetAttackSpeed(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetAttackDelay); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetAttackDelay) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetAttackDelay(THIS)"); + { + NPC * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetAttackDelay(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetAccuracyRating); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetAccuracyRating) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetAccuracyRating(THIS)"); + { + NPC * THIS; + int32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetAccuracyRating(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetAvoidanceRating); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetAvoidanceRating) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetAvoidanceyRating(THIS)"); + { + NPC * THIS; + int32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetAvoidanceRating(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetSpawnKillCount); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSpawnKillCount) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSpawnKillCount(THIS)"); + { + NPC * THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + RETVAL = THIS->GetSpawnKillCount(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_GetScore); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetScore) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetScore(THIS)"); + { + NPC * THIS; + int RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + RETVAL = THIS->GetScore(); + XSprePUSH; PUSHi((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_SetMerchantProbability); +XS(XS_NPC_SetMerchantProbability) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: NPC::SetMerchantProbability(THIS, Probability)"); + { + NPC *THIS; + uint8 Probability = (uint8)SvIV(ST(1)); + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetMerchantProbability(Probability); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_GetMerchantProbability); +XS(XS_NPC_GetMerchantProbability) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetMerchantProbability(THIS)"); + { + NPC *THIS; + uint8 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + RETVAL = THIS->GetMerchantProbability(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + +XS(XS_NPC_AddMeleeProc); +XS(XS_NPC_AddMeleeProc) { + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: NPC::AddMeleeProc(THIS,spellid,chance)"); + { + NPC * THIS; + int spell_id = (int)SvIV(ST(1)); + int chance = (int)SvIV(ST(2)); + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + THIS->AddProcToWeapon(spell_id, true, chance); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_AddRangedProc); +XS(XS_NPC_AddRangedProc) { + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: NPC::AddRangedProc(THIS,spellid,chance)"); + { + NPC * THIS; + int spell_id = (int)SvIV(ST(1)); + int chance = (int)SvIV(ST(2)); + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + THIS->AddDefensiveProc(spell_id,chance); + } + XSRETURN_EMPTY; +} + +XS(XS_NPC_AddDefensiveProc); +XS(XS_NPC_AddDefensiveProc) { + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: NPC::AddDefensiveProc(THIS,spellid,chance)"); + { + NPC * THIS; + int spell_id = (int)SvIV(ST(1)); + int chance = (int)SvIV(ST(2)); + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + THIS->AddProcToWeapon(spell_id, true, chance); + } + XSRETURN_EMPTY; +} + + +#ifdef __cplusplus +extern "C" +#endif +XS(boot_NPC); /* prototype to pass -Wmissing-prototypes */ +XS(boot_NPC) +{ + dXSARGS; + char file[256]; + strncpy(file, __FILE__, 256); + file[255] = 0; + + if(items != 1) + fprintf(stderr, "boot_quest does not take any arguments."); + char buf[128]; + + //add the strcpy stuff to get rid of const warnings.... + + XS_VERSION_BOOTCHECK ; + + newXSproto(strcpy(buf, "SignalNPC"), XS_NPC_SignalNPC, file, "$$"); + newXSproto(strcpy(buf, "CheckNPCFactionAlly"), XS_NPC_CheckNPCFactionAlly, file, "$$"); + newXSproto(strcpy(buf, "AddItem"), XS_NPC_AddItem, file, "$$;$$"); + newXSproto(strcpy(buf, "AddLootTable"), XS_NPC_AddLootTable, file, "$"); + newXSproto(strcpy(buf, "RemoveItem"), XS_NPC_RemoveItem, file, "$$;$$"); + newXSproto(strcpy(buf, "ClearItemList"), XS_NPC_ClearItemList, file, "$"); + newXSproto(strcpy(buf, "AddCash"), XS_NPC_AddCash, file, "$$$$$"); + newXSproto(strcpy(buf, "RemoveCash"), XS_NPC_RemoveCash, file, "$"); + newXSproto(strcpy(buf, "CountLoot"), XS_NPC_CountLoot, file, "$"); + newXSproto(strcpy(buf, "GetLoottableID"), XS_NPC_GetLoottableID, file, "$"); + newXSproto(strcpy(buf, "GetCopper"), XS_NPC_GetCopper, file, "$"); + newXSproto(strcpy(buf, "GetSilver"), XS_NPC_GetSilver, file, "$"); + newXSproto(strcpy(buf, "GetGold"), XS_NPC_GetGold, file, "$"); + newXSproto(strcpy(buf, "GetPlatinum"), XS_NPC_GetPlatinum, file, "$"); + newXSproto(strcpy(buf, "SetCopper"), XS_NPC_SetCopper, file, "$$"); + newXSproto(strcpy(buf, "SetSilver"), XS_NPC_SetSilver, file, "$$"); + newXSproto(strcpy(buf, "SetGold"), XS_NPC_SetGold, file, "$$"); + newXSproto(strcpy(buf, "SetPlatinum"), XS_NPC_SetPlatinum, file, "$$"); + newXSproto(strcpy(buf, "SetGrid"), XS_NPC_SetGrid, file, "$$"); + newXSproto(strcpy(buf, "SetSaveWaypoint"), XS_NPC_SetSaveWaypoint, file, "$$"); + newXSproto(strcpy(buf, "SetSp2"), XS_NPC_SetSp2, file, "$$"); + newXSproto(strcpy(buf, "GetWaypointMax"), XS_NPC_GetWaypointMax, file, "$"); + newXSproto(strcpy(buf, "GetGrid"), XS_NPC_GetGrid, file, "$"); + newXSproto(strcpy(buf, "GetSp2"), XS_NPC_GetSp2, file, "$"); + newXSproto(strcpy(buf, "GetNPCFactionID"), XS_NPC_GetNPCFactionID, file, "$"); + newXSproto(strcpy(buf, "GetPrimaryFaction"), XS_NPC_GetPrimaryFaction, file, "$"); + newXSproto(strcpy(buf, "GetNPCHate"), XS_NPC_GetNPCHate, file, "$$"); + newXSproto(strcpy(buf, "IsOnHatelist"), XS_NPC_IsOnHatelist, file, "$$"); + newXSproto(strcpy(buf, "SetNPCFactionID"), XS_NPC_SetNPCFactionID, file, "$$"); + newXSproto(strcpy(buf, "GetMaxDMG"), XS_NPC_GetMaxDMG, file, "$"); + newXSproto(strcpy(buf, "GetMinDMG"), XS_NPC_GetMinDMG, file, "$"); + newXSproto(strcpy(buf, "IsAnimal"), XS_NPC_IsAnimal, file, "$"); + newXSproto(strcpy(buf, "GetPetSpellID"), XS_NPC_GetPetSpellID, file, "$"); + newXSproto(strcpy(buf, "SetPetSpellID"), XS_NPC_SetPetSpellID, file, "$$"); + newXSproto(strcpy(buf, "GetMaxDamage"), XS_NPC_GetMaxDamage, file, "$$"); + newXSproto(strcpy(buf, "SetTaunting"), XS_NPC_SetTaunting, file, "$$"); + newXSproto(strcpy(buf, "PickPocket"), XS_NPC_PickPocket, file, "$$"); + newXSproto(strcpy(buf, "StartSwarmTimer"), XS_NPC_StartSwarmTimer, file, "$$"); + newXSproto(strcpy(buf, "DoClassAttacks"), XS_NPC_DoClassAttacks, file, "$$"); + newXSproto(strcpy(buf, "GetMaxWp"), XS_NPC_GetMaxWp, file, "$"); + newXSproto(strcpy(buf, "DisplayWaypointInfo"), XS_NPC_DisplayWaypointInfo, file, "$$"); + newXSproto(strcpy(buf, "CalculateNewWaypoint"), XS_NPC_CalculateNewWaypoint, file, "$"); + newXSproto(strcpy(buf, "AssignWaypoints"), XS_NPC_AssignWaypoints, file, "$$"); + newXSproto(strcpy(buf, "SetWaypointPause"), XS_NPC_SetWaypointPause, file, "$"); + newXSproto(strcpy(buf, "UpdateWaypoint"), XS_NPC_UpdateWaypoint, file, "$$"); + newXSproto(strcpy(buf, "StopWandering"), XS_NPC_StopWandering, file, "$"); + newXSproto(strcpy(buf, "ResumeWandering"), XS_NPC_ResumeWandering, file, "$"); + newXSproto(strcpy(buf, "PauseWandering"), XS_NPC_PauseWandering, file, "$$"); + newXSproto(strcpy(buf, "MoveTo"), XS_NPC_MoveTo, file, "$$$$"); + newXSproto(strcpy(buf, "NextGuardPosition"), XS_NPC_NextGuardPosition, file, "$"); + newXSproto(strcpy(buf, "SaveGuardSpot"), XS_NPC_SaveGuardSpot, file, "$;$"); + newXSproto(strcpy(buf, "IsGuarding"), XS_NPC_IsGuarding, file, "$"); + newXSproto(strcpy(buf, "AI_SetRoambox"), XS_NPC_AI_SetRoambox, file, "$$$$$$;$$"); + newXSproto(strcpy(buf, "GetNPCSpellsID"), XS_NPC_GetNPCSpellsID, file, "$"); + newXSproto(strcpy(buf, "GetSpawnPointID"), XS_NPC_GetSpawnPointID, file, "$"); + newXSproto(strcpy(buf, "GetSpawnPointX"), XS_NPC_GetSpawnPointX, file, "$"); + newXSproto(strcpy(buf, "GetSpawnPointY"), XS_NPC_GetSpawnPointY, file, "$"); + newXSproto(strcpy(buf, "GetSpawnPointZ"), XS_NPC_GetSpawnPointZ, file, "$"); + newXSproto(strcpy(buf, "GetSpawnPointH"), XS_NPC_GetSpawnPointH, file, "$"); + newXSproto(strcpy(buf, "GetGuardPointX"), XS_NPC_GetGuardPointX, file, "$"); + newXSproto(strcpy(buf, "GetGuardPointY"), XS_NPC_GetGuardPointY, file, "$"); + newXSproto(strcpy(buf, "GetGuardPointZ"), XS_NPC_GetGuardPointZ, file, "$"); + newXSproto(strcpy(buf, "SetPrimSkill"), XS_NPC_SetPrimSkill, file, "$$"); + newXSproto(strcpy(buf, "SetSecSkill"), XS_NPC_SetSecSkill, file, "$$"); + newXSproto(strcpy(buf, "GetPrimSkill"), XS_NPC_GetPrimSkill, file, "$"); + newXSproto(strcpy(buf, "GetSecSkill"), XS_NPC_GetSecSkill, file, "$"); + newXSproto(strcpy(buf, "GetSwarmOwner"), XS_NPC_GetSwarmOwner, file, "$"); + newXSproto(strcpy(buf, "GetSwarmTarget"), XS_NPC_GetSwarmTarget, file, "$"); + newXSproto(strcpy(buf, "SetSwarmTarget"), XS_NPC_SetSwarmTarget, file, "$$"); + newXSproto(strcpy(buf, "ModifyNPCStat"), XS_NPC_ModifyNPCStat, file, "$$$"); + newXSproto(strcpy(buf, "AddAISpell"), XS_NPC_AddSpellToNPCList, file, "$$$$$$$"); + newXSproto(strcpy(buf, "RemoveAISpell"), XS_NPC_RemoveSpellFromNPCList, file, "$$"); + newXSproto(strcpy(buf, "SetSpellFocusDMG"), XS_NPC_SetSpellFocusDMG, file, "$$"); + newXSproto(strcpy(buf, "SetSpellFocusHeal"), XS_NPC_SetSpellFocusHeal, file, "$$"); + newXSproto(strcpy(buf, "GetSpellFocusDMG"), XS_NPC_GetSpellFocusDMG, file, "$"); + newXSproto(strcpy(buf, "GetSpellFocusHeal"), XS_NPC_GetSpellFocusHeal, file, "$"); + newXSproto(strcpy(buf, "GetSlowMitigation"), XS_NPC_GetSlowMitigation, file, "$"); + newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetAttackSpeed, file, "$"); + newXSproto(strcpy(buf, "GetAttackDelay"), XS_NPC_GetAttackDelay, file, "$"); + newXSproto(strcpy(buf, "GetAccuracyRating"), XS_NPC_GetAccuracyRating, file, "$"); + newXSproto(strcpy(buf, "GetAvoidanceRating"), XS_NPC_GetAvoidanceRating, file, "$"); + newXSproto(strcpy(buf, "GetSpawnKillCount"), XS_NPC_GetSpawnKillCount, file, "$"); + newXSproto(strcpy(buf, "GetScore"), XS_NPC_GetScore, file, "$"); + newXSproto(strcpy(buf, "SetMerchantProbability"), XS_NPC_SetMerchantProbability, file, "$$"); + newXSproto(strcpy(buf, "GetMerchantProbability"), XS_NPC_GetMerchantProbability, file, "$"); + newXSproto(strcpy(buf, "AddMeleeProc"), XS_NPC_AddMeleeProc, file, "$$$"); + newXSproto(strcpy(buf, "AddRangedProc"), XS_NPC_AddRangedProc, file, "$$$"); + newXSproto(strcpy(buf, "AddDefensiveProc"), XS_NPC_AddDefensiveProc, file, "$$$"); + XSRETURN_YES; +} + +#endif //EMBPERL_XS_CLASSES + diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ecf2bb7ba..5490b9c6f 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1270,7 +1270,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Melee Absorb Rune: %+i", effect_value); #endif - effect_value = ApplySpellEffectiveness(caster, spell_id, effect_value); + if (caster) + effect_value = caster->ApplySpellEffectiveness(spell_id, effect_value); + buffs[buffslot].melee_rune = effect_value; break; } @@ -3020,7 +3022,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, uint32 instrument_mod, Mob *caster, - int ticsremaining) + int ticsremaining, uint16 caster_id) { int formula, base, max, effect_value; @@ -3048,7 +3050,7 @@ int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, spells[spell_id].effectid[effect_id] != SE_ManaRegen_v2) { int oval = effect_value; - int mod = ApplySpellEffectiveness(caster, spell_id, instrument_mod, true); + int mod = ApplySpellEffectiveness(spell_id, instrument_mod, true, caster_id); effect_value = effect_value * mod / 10; Log.Out(Logs::Detail, Logs::Spells, "Effect value %d altered with bard modifier of %d to yeild %d", oval, mod, effect_value); @@ -6043,16 +6045,21 @@ int32 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spel return value; } -int32 Mob::ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard) { +int32 Mob::ApplySpellEffectiveness(int16 spell_id, int32 value, bool IsBard, uint16 caster_id) { // 9-17-12: This is likely causing crashes, disabled till can resolve. if (IsBard) return value; + Mob* caster = this; + + if (caster_id && caster_id != GetID())//Make sure we are checking the casters focus + caster = entity_list.GetMob(caster_id); + if (!caster) return value; - int16 focus = GetFocusEffect(focusFcBaseEffects, spell_id); + int16 focus = caster->GetFocusEffect(focusFcBaseEffects, spell_id); if (IsBard) value += focus; From cc554be1df3dd10332f673d2ffa2180927b48429 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 27 Mar 2016 10:36:49 -0400 Subject: [PATCH 020/693] Revert "Removed unneccessary entitylist check from ApplySpellBonuses" --- Server | 1 - common/shareddbx.cpp | 2162 ------- common/spdat.h | 2 +- .../required/2014_02_12_spells_new_update.sql | 13 - ...014_04_10_No_Target_With_Hotkey - Copy.sql | 3 - .../git/required/2014_06_22_MetabolismAAs.sql | 6 - zone/AA_base.cpp | 1990 ------- zone/AA_v1.cpp | 2032 ------- zone/MobAI_M.cpp | 2760 --------- zone/attackx.cpp | 4663 --------------- zone/bonuses.cpp | 6 +- zone/bonusesxx.cpp | 4337 -------------- zone/groupsx.cpp | 2194 ------- zone/mob.h | 4 +- zone/mobx.cpp | 5148 ----------------- zone/mobx.h | 1236 ---- zone/net_Fix.cpp | 644 --- zone/npcx.cpp | 2492 -------- zone/perl_npcX.cpp | 2487 -------- zone/spell_effects.cpp | 17 +- 20 files changed, 13 insertions(+), 32184 deletions(-) delete mode 160000 Server delete mode 100644 common/shareddbx.cpp delete mode 100644 utils/sql/git/required/2014_02_12_spells_new_update.sql delete mode 100644 utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql delete mode 100644 utils/sql/git/required/2014_06_22_MetabolismAAs.sql delete mode 100644 zone/AA_base.cpp delete mode 100644 zone/AA_v1.cpp delete mode 100644 zone/MobAI_M.cpp delete mode 100644 zone/attackx.cpp delete mode 100644 zone/bonusesxx.cpp delete mode 100644 zone/groupsx.cpp delete mode 100644 zone/mobx.cpp delete mode 100644 zone/mobx.h delete mode 100644 zone/net_Fix.cpp delete mode 100644 zone/npcx.cpp delete mode 100644 zone/perl_npcX.cpp diff --git a/Server b/Server deleted file mode 160000 index 9d78eec48..000000000 --- a/Server +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9d78eec485fb73c8d61ce035590474556390783e diff --git a/common/shareddbx.cpp b/common/shareddbx.cpp deleted file mode 100644 index 60e29cccb..000000000 --- a/common/shareddbx.cpp +++ /dev/null @@ -1,2162 +0,0 @@ -#include -#include -#include - -#include "shareddb.h" -#include "mysql.h" -#include "Item.h" -#include "classes.h" -#include "rulesys.h" -#include "seperator.h" -#include "StringUtil.h" -#include "eq_packet_structs.h" -#include "guilds.h" -#include "extprofile.h" -#include "memory_mapped_file.h" -#include "ipc_mutex.h" -#include "eqemu_exception.h" -#include "loottable.h" -#include "faction.h" -#include "features.h" - -SharedDatabase::SharedDatabase() -: Database(), skill_caps_mmf(nullptr), items_mmf(nullptr), items_hash(nullptr), faction_mmf(nullptr), faction_hash(nullptr), - loot_table_mmf(nullptr), loot_table_hash(nullptr), loot_drop_mmf(nullptr), loot_drop_hash(nullptr), base_data_mmf(nullptr) -{ -} - -SharedDatabase::SharedDatabase(const char* host, const char* user, const char* passwd, const char* database, uint32 port) -: Database(host, user, passwd, database, port), skill_caps_mmf(nullptr), items_mmf(nullptr), items_hash(nullptr), - faction_mmf(nullptr), faction_hash(nullptr), loot_table_mmf(nullptr), loot_table_hash(nullptr), loot_drop_mmf(nullptr), - loot_drop_hash(nullptr), base_data_mmf(nullptr) -{ -} - -SharedDatabase::~SharedDatabase() { - safe_delete(skill_caps_mmf); - safe_delete(items_mmf); - safe_delete(items_hash); - safe_delete(faction_mmf); - safe_delete(faction_hash); - safe_delete(loot_table_mmf); - safe_delete(loot_drop_mmf); - safe_delete(loot_table_hash); - safe_delete(loot_drop_hash); - safe_delete(base_data_mmf); -} - -bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET hideme = %i where id = %i", hideme, account_id), errbuf)) { - std::cerr << "Error in SetGMSpeed query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - safe_delete_array(query); - return true; - -} - -uint8 SharedDatabase::GetGMSpeed(uint32 account_id) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT gmspeed FROM account where id='%i'", account_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint8 gmspeed = atoi(row[0]); - mysql_free_result(result); - return gmspeed; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else - { - - std::cerr << "Error in GetGMSpeed query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - return 0; - - -} - -bool SharedDatabase::SetGMSpeed(uint32 account_id, uint8 gmspeed) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET gmspeed = %i where id = %i", gmspeed, account_id), errbuf)) { - std::cerr << "Error in SetGMSpeed query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - safe_delete_array(query); - return true; - -} - -uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) { - - uint32 EntitledTime = 0; - - const char *EntitledQuery = "select sum(ascii(substring(profile, 237, 1)) + (ascii(substring(profile, 238, 1)) * 256) +" - "(ascii(substring(profile, 239, 1)) * 65536) + (ascii(substring(profile, 240, 1)) * 16777216))" - "from character_ where account_id = %i"; - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, EntitledQuery, AccountID), errbuf, &result)) { - - if (mysql_num_rows(result) == 1) { - - row = mysql_fetch_row(result); - - EntitledTime = atoi(row[0]); - } - - mysql_free_result(result); - } - - safe_delete_array(query); - - return EntitledTime; -} - -bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iterator &start, std::list::const_iterator &end) -{ -iter_queue it; -int i; -bool ret=true; - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - // Delete cursor items - if ((ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND ( (slotid >=8000 and slotid<=8999) or slotid=30 or (slotid>=331 and slotid<=340))", char_id), errbuf))) { - for(it=start,i=8000;it!=end;++it,i++) { - ItemInst *inst=*it; - if (!(ret=SaveInventory(char_id,inst,(i==8000) ? 30 : i))) - break; - } - } else { - std::cout << "Clearing cursor failed: " << errbuf << std::endl; - } - safe_delete_array(query); - - return ret; -} - -bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const ItemInst* inst) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - // Delete cursor items - if (!RunQuery(query, MakeAnyLenString(&query, - "SELECT itemid,charges FROM sharedbank " - "WHERE acctid=%d AND slotid=%d", - account_id, slot_id), errbuf, &result)) { - LogFile->write(EQEMuLog::Error, "Error runing inventory verification query '%s': %s", query, errbuf); - safe_delete_array(query); - //returning true is less harmful in the face of a query error - return(true); - } - safe_delete_array(query); - - row = mysql_fetch_row(result); - bool found = false; - if(row) { - uint32 id = atoi(row[0]); - uint16 charges = atoi(row[1]); - - uint16 expect_charges = 0; - if(inst->GetCharges() >= 0) - expect_charges = inst->GetCharges(); - else - expect_charges = 0x7FFF; - - if(id == inst->GetItem()->ID && charges == expect_charges) - found = true; - } - mysql_free_result(result); - return(found); -} - -bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 slot_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - bool ret = false; - uint32 augslot[5] = { 0, 0, 0, 0, 0 }; - - //never save tribute slots: - if(slot_id >= 400 && slot_id <= 404) - return(true); - - if (inst && inst->IsType(ItemClassCommon)) { - for(int i=0;i<5;i++) { - ItemInst *auginst=inst->GetItem(i); - augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; - } - } - - if (slot_id>=2500 && slot_id<=2600) { // Shared bank inventory - if (!inst) { - // Delete item - uint32 account_id = GetAccountIDByChar(char_id); - uint32 len_query = MakeAnyLenString(&query, "DELETE FROM sharedbank WHERE acctid=%i AND slotid=%i", - account_id, slot_id); - - ret = RunQuery(query, len_query, errbuf); - - // Delete bag slots, if need be - if (ret && Inventory::SupportsContainers(slot_id)) { - safe_delete_array(query); - int16 base_slot_id = Inventory::CalcSlotId(slot_id, 0); - ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM sharedbank WHERE acctid=%i AND slotid>=%i AND slotid<%i", - account_id, base_slot_id, (base_slot_id+10)), errbuf); - } - - // @merth: need to delete augments here - } - else { - // Update/Insert item - uint32 account_id = GetAccountIDByChar(char_id); - uint16 charges = 0; - if(inst->GetCharges() >= 0) - charges = inst->GetCharges(); - else - charges = 0x7FFF; - - uint32 len_query = MakeAnyLenString(&query, - "REPLACE INTO sharedbank " - " (acctid,slotid,itemid,charges,custom_data," - " augslot1,augslot2,augslot3,augslot4,augslot5)" - " VALUES(%lu,%lu,%lu,%lu,'%s'," - " %lu,%lu,%lu,%lu,%lu)", - (unsigned long)account_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, (unsigned long)charges, - inst->GetCustomDataString().c_str(), - (unsigned long)augslot[0],(unsigned long)augslot[1],(unsigned long)augslot[2],(unsigned long)augslot[3],(unsigned long)augslot[4]); - - - ret = RunQuery(query, len_query, errbuf); - } - } - else { // All other inventory - if (!inst) { - // Delete item - ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND slotid=%i", - char_id, slot_id), errbuf); - - // Delete bag slots, if need be - if (ret && Inventory::SupportsContainers(slot_id)) { - safe_delete_array(query); - int16 base_slot_id = Inventory::CalcSlotId(slot_id, 0); - ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND slotid>=%i AND slotid<%i", - char_id, base_slot_id, (base_slot_id+10)), errbuf); - } - - // @merth: need to delete augments here - } - else { - uint16 charges = 0; - if(inst->GetCharges() >= 0) - charges = inst->GetCharges(); - else - charges = 0x7FFF; - // Update/Insert item - uint32 len_query = MakeAnyLenString(&query, - "REPLACE INTO inventory " - " (charid,slotid,itemid,charges,instnodrop,custom_data,color," - " augslot1,augslot2,augslot3,augslot4,augslot5)" - " VALUES(%lu,%lu,%lu,%lu,%lu,'%s',%lu," - " %lu,%lu,%lu,%lu,%lu)", - (unsigned long)char_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, (unsigned long)charges, - (unsigned long)(inst->IsInstNoDrop() ? 1:0),inst->GetCustomDataString().c_str(),(unsigned long)inst->GetColor(), - (unsigned long)augslot[0],(unsigned long)augslot[1],(unsigned long)augslot[2],(unsigned long)augslot[3],(unsigned long)augslot[4] ); - - ret = RunQuery(query, len_query, errbuf); - } - } - - if (!ret) - LogFile->write(EQEMuLog::Error, "SaveInventory query '%s': %s", query, errbuf); - safe_delete_array(query); - - // Save bag contents, if slot supports bag contents - if (inst && inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) { - for (uint8 idx=0; idx<10; idx++) { - const ItemInst* baginst = inst->GetItem(idx); - SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); - } - } - - // @merth: need to save augments here - - return ret; -} - -int32 SharedDatabase::GetSharedPlatinum(uint32 account_id) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT sharedplat FROM account WHERE id='%i'", account_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint32 shared_platinum = atoi(row[0]); - mysql_free_result(result); - return shared_platinum; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else - { - std::cerr << "Error in GetSharedPlatinum query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - return 0; -} - -bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id), errbuf)) { - std::cerr << "Error in SetSharedPlatinum query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - safe_delete_array(query); - return true; -} - -bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - const Item_Struct* myitem; - - RunQuery - ( - query, - MakeAnyLenString - ( - &query, - "SELECT itemid, item_charges, slot FROM starting_items " - "WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND " - "(deityid = %i or deityid=0) AND (zoneid = %i or zoneid = 0) AND " - "gm <= %i ORDER BY id", - si_race, si_class, si_deity, si_current_zone, admin_level - ), - errbuf, - &result - ); - safe_delete_array(query); - - while((row = mysql_fetch_row(result))) { - int itemid = atoi(row[0]); - int charges = atoi(row[1]); - int slot = atoi(row[2]); - myitem = GetItem(itemid); - if(!myitem) - continue; - ItemInst* myinst = CreateBaseItem(myitem, charges); - if(slot < 0) - slot = inv->FindFreeSlot(0,0); - inv->PutItem(slot, *myinst); - safe_delete(myinst); - } - - if(result) mysql_free_result(result); - - return true; -} - - -// Retrieve shared bank inventory based on either account or character -bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 len_query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - bool ret = false; - - if (is_charid) { - len_query = MakeAnyLenString(&query, - "SELECT sb.slotid,sb.itemid,sb.charges,sb.augslot1,sb.augslot2,sb.augslot3,sb.augslot4,sb.augslot5,sb.custom_data from sharedbank sb " - "INNER JOIN character_ ch ON ch.account_id=sb.acctid " - "WHERE ch.id=%i", id); - } - else { - len_query = MakeAnyLenString(&query, - "SELECT slotid,itemid,charges,augslot1,augslot2,augslot3,augslot4,augslot5,custom_data from sharedbank WHERE acctid=%i", id); - } - - if (RunQuery(query, len_query, errbuf, &result)) { - while ((row = mysql_fetch_row(result))) { - int16 slot_id = (int16)atoi(row[0]); - uint32 item_id = (uint32)atoi(row[1]); - int8 charges = (int8)atoi(row[2]); - uint32 aug[5]; - aug[0] = (uint32)atoi(row[3]); - aug[1] = (uint32)atoi(row[4]); - aug[2] = (uint32)atoi(row[5]); - aug[3] = (uint32)atoi(row[6]); - aug[4] = (uint32)atoi(row[7]); - const Item_Struct* item = GetItem(item_id); - - if (item) { - int16 put_slot_id = INVALID_INDEX; - - ItemInst* inst = CreateBaseItem(item, charges); - if (item->ItemClass == ItemClassCommon) { - for(int i=0;i<5;i++) { - if (aug[i]) { - inst->PutAugment(this, i, aug[i]); - } - } - } - if(row[8]) { - std::string data_str(row[8]); - std::string id; - std::string value; - bool use_id = true; - - for(int i = 0; i < data_str.length(); ++i) { - if(data_str[i] == '^') { - if(!use_id) { - inst->SetCustomData(id, value); - id.clear(); - value.clear(); - } - use_id = !use_id; - } - else { - char v = data_str[i]; - if(use_id) { - id.push_back(v); - } else { - value.push_back(v); - } - } - } - } - - put_slot_id = inv->PutItem(slot_id, *inst); - safe_delete(inst); - - // Save ptr to item in inventory - if (put_slot_id == INVALID_INDEX) { - LogFile->write(EQEMuLog::Error, - "Warning: Invalid slot_id for item in shared bank inventory: %s=%i, item_id=%i, slot_id=%i", - ((is_charid==true) ? "charid" : "acctid"), id, item_id, slot_id); - - if(is_charid) - SaveInventory(id,nullptr,slot_id); - } - } - else { - LogFile->write(EQEMuLog::Error, - "Warning: %s %i has an invalid item_id %i in inventory slot %i", - ((is_charid==true) ? "charid" : "acctid"), id, item_id, slot_id); - } - } - - mysql_free_result(result); - ret = true; - } - else { - LogFile->write(EQEMuLog::Error, "Database::GetSharedBank(uint32 account_id): %s", errbuf); - } - - safe_delete_array(query); - return ret; -} - - -// Overloaded: Retrieve character inventory based on character id -bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES* result; - MYSQL_ROW row; - bool ret = false; - - // Retrieve character inventory - if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5," - "instnodrop,custom_data FROM inventory WHERE charid=%i ORDER BY slotid", char_id), errbuf, &result)) { - - while ((row = mysql_fetch_row(result))) { - int16 slot_id = atoi(row[0]); - uint32 item_id = atoi(row[1]); - uint16 charges = atoi(row[2]); - uint32 color = atoul(row[3]); - uint32 aug[5]; - aug[0] = (uint32)atoul(row[4]); - aug[1] = (uint32)atoul(row[5]); - aug[2] = (uint32)atoul(row[6]); - aug[3] = (uint32)atoul(row[7]); - aug[4] = (uint32)atoul(row[8]); - bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false; - - const Item_Struct* item = GetItem(item_id); - - if (item) { - int16 put_slot_id = INVALID_INDEX; - - ItemInst* inst = CreateBaseItem(item, charges); - - if(row[10]) { - std::string data_str(row[10]); - std::string id; - std::string value; - bool use_id = true; - - for(int i = 0; i < data_str.length(); ++i) { - if(data_str[i] == '^') { - if(!use_id) { - inst->SetCustomData(id, value); - id.clear(); - value.clear(); - } - use_id = !use_id; - } - else { - char v = data_str[i]; - if(use_id) { - id.push_back(v); - } else { - value.push_back(v); - } - } - } - } - - if (instnodrop || (slot_id >= 0 && slot_id <= 21 && inst->GetItem()->Attuneable)) - inst->SetInstNoDrop(true); - if (color > 0) - inst->SetColor(color); - if(charges==0x7FFF) - inst->SetCharges(-1); - else - inst->SetCharges(charges); - - if (item->ItemClass == ItemClassCommon) { - for(int i=0;i<5;i++) { - if (aug[i]) { - inst->PutAugment(this, i, aug[i]); - } - } - } - - if (slot_id>=8000 && slot_id <= 8999) - put_slot_id = inv->PushCursor(*inst); - else - put_slot_id = inv->PutItem(slot_id, *inst); - safe_delete(inst); - - // Save ptr to item in inventory - if (put_slot_id == INVALID_INDEX) { - LogFile->write(EQEMuLog::Error, - "Warning: Invalid slot_id for item in inventory: charid=%i, item_id=%i, slot_id=%i", - char_id, item_id, slot_id); - } - } - else { - LogFile->write(EQEMuLog::Error, - "Warning: charid %i has an invalid item_id %i in inventory slot %i", - char_id, item_id, slot_id); - } - } - mysql_free_result(result); - - // Retrieve shared inventory - ret = GetSharedBank(char_id, inv, true); - } - else { - LogFile->write(EQEMuLog::Error, "GetInventory query '%s' %s", query, errbuf); - LogFile->write(EQEMuLog::Error, "If you got an error related to the 'instnodrop' field, run the following SQL Queries:\nalter table inventory add instnodrop tinyint(1) unsigned default 0 not null;\n"); - } - - safe_delete_array(query); - return ret; -} - -// Overloaded: Retrieve character inventory based on account_id and character name -bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES* result; - MYSQL_ROW row; - bool ret = false; - - // Retrieve character inventory - if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5," - "instnodrop,custom_data FROM inventory INNER JOIN character_ ch ON ch.id=charid WHERE ch.name='%s' AND ch.account_id=%i ORDER BY slotid", - name, account_id), errbuf, &result)) - { - while ((row = mysql_fetch_row(result))) { - int16 slot_id = atoi(row[0]); - uint32 item_id = atoi(row[1]); - int8 charges = atoi(row[2]); - uint32 color = atoul(row[3]); - uint32 aug[5]; - aug[0] = (uint32)atoi(row[4]); - aug[1] = (uint32)atoi(row[5]); - aug[2] = (uint32)atoi(row[6]); - aug[3] = (uint32)atoi(row[7]); - aug[4] = (uint32)atoi(row[8]); - bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false; - const Item_Struct* item = GetItem(item_id); - int16 put_slot_id = INVALID_INDEX; - if(!item) - continue; - - ItemInst* inst = CreateBaseItem(item, charges); - inst->SetInstNoDrop(instnodrop); - - if(row[10]) { - std::string data_str(row[10]); - std::string id; - std::string value; - bool use_id = true; - - for(int i = 0; i < data_str.length(); ++i) { - if(data_str[i] == '^') { - if(!use_id) { - inst->SetCustomData(id, value); - id.clear(); - value.clear(); - } - use_id = !use_id; - } - else { - char v = data_str[i]; - if(use_id) { - id.push_back(v); - } else { - value.push_back(v); - } - } - } - } - - if (color > 0) - inst->SetColor(color); - inst->SetCharges(charges); - - if (item->ItemClass == ItemClassCommon) { - for(int i=0;i<5;i++) { - if (aug[i]) { - inst->PutAugment(this, i, aug[i]); - } - } - } - if (slot_id>=8000 && slot_id <= 8999) - put_slot_id = inv->PushCursor(*inst); - else - put_slot_id = inv->PutItem(slot_id, *inst); - safe_delete(inst); - - // Save ptr to item in inventory - if (put_slot_id == INVALID_INDEX) { - LogFile->write(EQEMuLog::Error, - "Warning: Invalid slot_id for item in inventory: name=%s, acctid=%i, item_id=%i, slot_id=%i", - name, account_id, item_id, slot_id); - } - } - mysql_free_result(result); - - // Retrieve shared inventory - ret = GetSharedBank(account_id, inv, false); - } - else { - LogFile->write(EQEMuLog::Error, "GetInventory query '%s' %s", query, errbuf); - LogFile->write(EQEMuLog::Error, "If you got an error related to the 'instnodrop' field, run the following SQL Queries:\nalter table inventory add instnodrop tinyint(1) unsigned default 0 not null;\n"); - } - - safe_delete_array(query); - return ret; -} - - -void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - item_count = -1; - max_id = 0; - - char query[] = "SELECT MAX(id), count(*) FROM items"; - if (RunQuery(query, static_cast(strlen(query)), errbuf, &result)) { - row = mysql_fetch_row(result); - if (row != nullptr && row[1] != 0) { - item_count = atoi(row[1]); - if(row[0]) - max_id = atoi(row[0]); - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in GetItemsCount '%s': '%s'", query, errbuf); - } -} - -bool SharedDatabase::LoadItems() { - if(items_mmf) { - return true; - } - - try { - EQEmu::IPCMutex mutex("items"); - mutex.Lock(); - items_mmf = new EQEmu::MemoryMappedFile("shared/items"); - - int32 items = -1; - uint32 max_item = 0; - GetItemsCount(items, max_item); - if(items == -1) { - EQ_EXCEPT("SharedDatabase", "Database returned no result"); - } - uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); - if(items_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Couldn't load items because items_mmf->Size() != size"); - } - - items_hash = new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), size); - mutex.Unlock(); - } catch(std::exception& ex) { - LogFile->write(EQEMuLog::Error, "Error Loading Items: %s", ex.what()); - return false; - } - - return true; -} - -void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id) { - EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - char ndbuffer[4]; - bool disableNoRent = false; - if(GetVariable("disablenorent", ndbuffer, 4)) { - if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableNoRent = true; - } - } - bool disableNoDrop = false; - if(GetVariable("disablenodrop", ndbuffer, 4)) { - if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableNoDrop = true; - } - } - bool disableLoreGroup = false; - if(GetVariable("disablelore", ndbuffer, 4)) { - if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableLoreGroup = true; - } - } - bool disableNoTransfer = false; - if(GetVariable("disablenotransfer", ndbuffer, 4)) { - if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableNoTransfer = true; - } - } - - char query[] = "select source," -#define F(x) "`"#x"`," -#include "item_fieldlist.h" -#undef F - "updated" - " from items order by id"; - Item_Struct item; - if(RunQuery(query, sizeof(query), errbuf, &result)) { - while((row = mysql_fetch_row(result))) { - memset(&item, 0, sizeof(Item_Struct)); - - item.ItemClass = (uint8)atoi(row[ItemField::itemclass]); - strcpy(item.Name,row[ItemField::name]); - strcpy(item.Lore,row[ItemField::lore]); - strcpy(item.IDFile,row[ItemField::idfile]); - item.ID = (uint32)atoul(row[ItemField::id]); - item.Weight = (uint8)atoi(row[ItemField::weight]); - item.NoRent = disableNoRent ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::norent]); - item.NoDrop = disableNoDrop ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::nodrop]); - item.Size = (uint8)atoi(row[ItemField::size]); - item.Slots = (uint32)atoul(row[ItemField::slots]); - item.Price = (uint32)atoul(row[ItemField::price]); - item.Icon = (uint32)atoul(row[ItemField::icon]); - item.BenefitFlag = (atoul(row[ItemField::benefitflag]) != 0); - item.Tradeskills = (atoi(row[ItemField::tradeskills])==0) ? false : true; - item.CR = (int8)atoi(row[ItemField::cr]); - item.DR = (int8)atoi(row[ItemField::dr]); - item.PR = (int8)atoi(row[ItemField::pr]); - item.MR = (int8)atoi(row[ItemField::mr]); - item.FR = (int8)atoi(row[ItemField::fr]); - item.AStr = (int8)atoi(row[ItemField::astr]); - item.ASta = (int8)atoi(row[ItemField::asta]); - item.AAgi = (int8)atoi(row[ItemField::aagi]); - item.ADex = (int8)atoi(row[ItemField::adex]); - item.ACha = (int8)atoi(row[ItemField::acha]); - item.AInt = (int8)atoi(row[ItemField::aint]); - item.AWis = (int8)atoi(row[ItemField::awis]); - item.HP = (int32)atoul(row[ItemField::hp]); - item.Mana = (int32)atoul(row[ItemField::mana]); - item.AC = (int32)atoul(row[ItemField::ac]); - item.Deity = (uint32)atoul(row[ItemField::deity]); - item.SkillModValue = (int32)atoul(row[ItemField::skillmodvalue]); - //item.Unk033 = (int32)atoul(row[ItemField::UNK033]); - item.SkillModType = (uint32)atoul(row[ItemField::skillmodtype]); - item.BaneDmgRace = (uint32)atoul(row[ItemField::banedmgrace]); - item.BaneDmgAmt = (int8)atoi(row[ItemField::banedmgamt]); - item.BaneDmgBody = (uint32)atoul(row[ItemField::banedmgbody]); - item.Magic = (atoi(row[ItemField::magic])==0) ? false : true; - item.CastTime_ = (int32)atoul(row[ItemField::casttime_]); - item.ReqLevel = (uint8)atoi(row[ItemField::reqlevel]); - item.BardType = (uint32)atoul(row[ItemField::bardtype]); - item.BardValue = (int32)atoul(row[ItemField::bardvalue]); - item.Light = (int8)atoi(row[ItemField::light]); - item.Delay = (uint8)atoi(row[ItemField::delay]); - item.RecLevel = (uint8)atoi(row[ItemField::reclevel]); - item.RecSkill = (uint8)atoi(row[ItemField::recskill]); - item.ElemDmgType = (uint8)atoi(row[ItemField::elemdmgtype]); - item.ElemDmgAmt = (uint8)atoi(row[ItemField::elemdmgamt]); - item.Range = (uint8)atoi(row[ItemField::range]); - item.Damage = (uint32)atoi(row[ItemField::damage]); - item.Color = (uint32)atoul(row[ItemField::color]); - item.Classes = (uint32)atoul(row[ItemField::classes]); - item.Races = (uint32)atoul(row[ItemField::races]); - //item.Unk054 = (uint32)atoul(row[ItemField::UNK054]); - item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]); - item.ItemType = (uint8)atoi(row[ItemField::itemtype]); - item.Material = (uint8)atoi(row[ItemField::material]); - item.SellRate = (float)atof(row[ItemField::sellrate]); - //item.Unk059 = (uint32)atoul(row[ItemField::UNK059]); - item.CastTime = (uint32)atoul(row[ItemField::casttime]); - item.EliteMaterial = (uint32)atoul(row[ItemField::elitematerial]); - item.ProcRate = (int32)atoi(row[ItemField::procrate]); - item.CombatEffects = (int8)atoi(row[ItemField::combateffects]); - item.Shielding = (int8)atoi(row[ItemField::shielding]); - item.StunResist = (int8)atoi(row[ItemField::stunresist]); - item.StrikeThrough = (int8)atoi(row[ItemField::strikethrough]); - item.ExtraDmgSkill = (uint32)atoul(row[ItemField::extradmgskill]); - item.ExtraDmgAmt = (uint32)atoul(row[ItemField::extradmgamt]); - item.SpellShield = (int8)atoi(row[ItemField::spellshield]); - item.Avoidance = (int8)atoi(row[ItemField::avoidance]); - item.Accuracy = (int8)atoi(row[ItemField::accuracy]); - item.CharmFileID = (uint32)atoul(row[ItemField::charmfileid]); - item.FactionMod1 = (int32)atoul(row[ItemField::factionmod1]); - item.FactionMod2 = (int32)atoul(row[ItemField::factionmod2]); - item.FactionMod3 = (int32)atoul(row[ItemField::factionmod3]); - item.FactionMod4 = (int32)atoul(row[ItemField::factionmod4]); - item.FactionAmt1 = (int32)atoul(row[ItemField::factionamt1]); - item.FactionAmt2 = (int32)atoul(row[ItemField::factionamt2]); - item.FactionAmt3 = (int32)atoul(row[ItemField::factionamt3]); - item.FactionAmt4 = (int32)atoul(row[ItemField::factionamt4]); - strcpy(item.CharmFile,row[ItemField::charmfile]); - item.AugType = (uint32)atoul(row[ItemField::augtype]); - item.AugSlotType[0] = (uint8)atoi(row[ItemField::augslot1type]); - item.AugSlotVisible[0] = (uint8)atoi(row[ItemField::augslot1visible]); - item.AugSlotUnk2[0] = 0; - item.AugSlotType[1] = (uint8)atoi(row[ItemField::augslot2type]); - item.AugSlotVisible[1] = (uint8)atoi(row[ItemField::augslot2visible]); - item.AugSlotUnk2[1] = 0; - item.AugSlotType[2] = (uint8)atoi(row[ItemField::augslot3type]); - item.AugSlotVisible[2] = (uint8)atoi(row[ItemField::augslot3visible]); - item.AugSlotUnk2[2] = 0; - item.AugSlotType[3] = (uint8)atoi(row[ItemField::augslot4type]); - item.AugSlotVisible[3] = (uint8)atoi(row[ItemField::augslot4visible]); - item.AugSlotUnk2[3] = 0; - item.AugSlotType[4] = (uint8)atoi(row[ItemField::augslot5type]); - item.AugSlotVisible[4] = (uint8)atoi(row[ItemField::augslot5visible]); - item.AugSlotUnk2[4] = 0; - item.LDoNTheme = (uint32)atoul(row[ItemField::ldontheme]); - item.LDoNPrice = (uint32)atoul(row[ItemField::ldonprice]); - item.LDoNSold = (uint32)atoul(row[ItemField::ldonsold]); - item.BagType = (uint8)atoi(row[ItemField::bagtype]); - item.BagSlots = (uint8)atoi(row[ItemField::bagslots]); - item.BagSize = (uint8)atoi(row[ItemField::bagsize]); - item.BagWR = (uint8)atoi(row[ItemField::bagwr]); - item.Book = (uint8)atoi(row[ItemField::book]); - item.BookType = (uint32)atoul(row[ItemField::booktype]); - strcpy(item.Filename,row[ItemField::filename]); - item.BaneDmgRaceAmt = (uint32)atoul(row[ItemField::banedmgraceamt]); - item.AugRestrict = (uint32)atoul(row[ItemField::augrestrict]); - item.LoreGroup = disableLoreGroup ? (uint8)atoi("0") : atoi(row[ItemField::loregroup]); - item.LoreFlag = item.LoreGroup!=0; - item.PendingLoreFlag = (atoi(row[ItemField::pendingloreflag])==0) ? false : true; - item.ArtifactFlag = (atoi(row[ItemField::artifactflag])==0) ? false : true; - item.SummonedFlag = (atoi(row[ItemField::summonedflag])==0) ? false : true; - item.Favor = (uint32)atoul(row[ItemField::favor]); - item.FVNoDrop = (atoi(row[ItemField::fvnodrop])==0) ? false : true; - item.Endur = (uint32)atoul(row[ItemField::endur]); - item.DotShielding = (uint32)atoul(row[ItemField::dotshielding]); - item.Attack = (uint32)atoul(row[ItemField::attack]); - item.Regen = (uint32)atoul(row[ItemField::regen]); - item.ManaRegen = (uint32)atoul(row[ItemField::manaregen]); - item.EnduranceRegen = (uint32)atoul(row[ItemField::enduranceregen]); - item.Haste = (uint32)atoul(row[ItemField::haste]); - item.DamageShield = (uint32)atoul(row[ItemField::damageshield]); - item.RecastDelay = (uint32)atoul(row[ItemField::recastdelay]); - item.RecastType = (uint32)atoul(row[ItemField::recasttype]); - item.GuildFavor = (uint32)atoul(row[ItemField::guildfavor]); - item.AugDistiller = (uint32)atoul(row[ItemField::augdistiller]); - item.Attuneable = (atoi(row[ItemField::attuneable])==0) ? false : true; - item.NoPet = (atoi(row[ItemField::nopet])==0) ? false : true; - item.PointType = (uint32)atoul(row[ItemField::pointtype]); - item.PotionBelt = (atoi(row[ItemField::potionbelt])==0) ? false : true; - item.PotionBeltSlots = (atoi(row[ItemField::potionbeltslots])==0) ? false : true; - item.StackSize = (uint16)atoi(row[ItemField::stacksize]); - item.NoTransfer = disableNoTransfer ? false : (atoi(row[ItemField::notransfer])==0) ? false : true; - item.Stackable = (atoi(row[ItemField::stackable])==0) ? false : true; - item.Click.Effect = (uint32)atoul(row[ItemField::clickeffect]); - item.Click.Type = (uint8)atoul(row[ItemField::clicktype]); - item.Click.Level = (uint8)atoul(row[ItemField::clicklevel]); - item.Click.Level2 = (uint8)atoul(row[ItemField::clicklevel2]); - strcpy(item.CharmFile,row[ItemField::charmfile]); - item.Proc.Effect = (uint16)atoul(row[ItemField::proceffect]); - item.Proc.Type = (uint8)atoul(row[ItemField::proctype]); - item.Proc.Level = (uint8)atoul(row[ItemField::proclevel]); - item.Proc.Level2 = (uint8)atoul(row[ItemField::proclevel2]); - item.Worn.Effect = (uint16)atoul(row[ItemField::worneffect]); - item.Worn.Type = (uint8)atoul(row[ItemField::worntype]); - item.Worn.Level = (uint8)atoul(row[ItemField::wornlevel]); - item.Worn.Level2 = (uint8)atoul(row[ItemField::wornlevel2]); - item.Focus.Effect = (uint16)atoul(row[ItemField::focuseffect]); - item.Focus.Type = (uint8)atoul(row[ItemField::focustype]); - item.Focus.Level = (uint8)atoul(row[ItemField::focuslevel]); - item.Focus.Level2 = (uint8)atoul(row[ItemField::focuslevel2]); - item.Scroll.Effect = (uint16)atoul(row[ItemField::scrolleffect]); - item.Scroll.Type = (uint8)atoul(row[ItemField::scrolltype]); - item.Scroll.Level = (uint8)atoul(row[ItemField::scrolllevel]); - item.Scroll.Level2 = (uint8)atoul(row[ItemField::scrolllevel2]); - item.Bard.Effect = (uint16)atoul(row[ItemField::bardeffect]); - item.Bard.Type = (uint8)atoul(row[ItemField::bardtype]); - item.Bard.Level = (uint8)atoul(row[ItemField::bardlevel]); - item.Bard.Level2 = (uint8)atoul(row[ItemField::bardlevel2]); - item.QuestItemFlag = (atoi(row[ItemField::questitemflag])==0) ? false : true; - item.SVCorruption = (int32)atoi(row[ItemField::svcorruption]); - item.Purity = (uint32)atoul(row[ItemField::purity]); - item.BackstabDmg = (uint32)atoul(row[ItemField::backstabdmg]); - item.DSMitigation = (uint32)atoul(row[ItemField::dsmitigation]); - item.HeroicStr = (int32)atoi(row[ItemField::heroic_str]); - item.HeroicInt = (int32)atoi(row[ItemField::heroic_int]); - item.HeroicWis = (int32)atoi(row[ItemField::heroic_wis]); - item.HeroicAgi = (int32)atoi(row[ItemField::heroic_agi]); - item.HeroicDex = (int32)atoi(row[ItemField::heroic_dex]); - item.HeroicSta = (int32)atoi(row[ItemField::heroic_sta]); - item.HeroicCha = (int32)atoi(row[ItemField::heroic_cha]); - item.HeroicMR = (int32)atoi(row[ItemField::heroic_mr]); - item.HeroicFR = (int32)atoi(row[ItemField::heroic_fr]); - item.HeroicCR = (int32)atoi(row[ItemField::heroic_cr]); - item.HeroicDR = (int32)atoi(row[ItemField::heroic_dr]); - item.HeroicPR = (int32)atoi(row[ItemField::heroic_pr]); - item.HeroicSVCorrup = (int32)atoi(row[ItemField::heroic_svcorrup]); - item.HealAmt = (int32)atoi(row[ItemField::healamt]); - item.SpellDmg = (int32)atoi(row[ItemField::spelldmg]); - item.LDoNSellBackRate = (uint32)atoul(row[ItemField::ldonsellbackrate]); - item.ScriptFileID = (uint32)atoul(row[ItemField::scriptfileid]); - item.ExpendableArrow = (uint16)atoul(row[ItemField::expendablearrow]); - item.Clairvoyance = (uint32)atoul(row[ItemField::clairvoyance]); - strcpy(item.ClickName,row[ItemField::clickname]); - strcpy(item.ProcName,row[ItemField::procname]); - strcpy(item.WornName,row[ItemField::wornname]); - strcpy(item.FocusName,row[ItemField::focusname]); - strcpy(item.ScrollName,row[ItemField::scrollname]); - - try { - hash.insert(item.ID, item); - } catch(std::exception &ex) { - LogFile->write(EQEMuLog::Error, "Database::LoadItems: %s", ex.what()); - break; - } - } - - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "LoadItems '%s', %s", query, errbuf); - } -} - -const Item_Struct* SharedDatabase::GetItem(uint32 id) { - if(!items_hash || id > items_hash->max_key()) { - return nullptr; - } - - if(items_hash->exists(id)) { - return &(items_hash->at(id)); - } - - return nullptr; -} - -const Item_Struct* SharedDatabase::IterateItems(uint32* id) { - if(!items_hash || !id) { - return nullptr; - } - - for(;;) { - if(*id > items_hash->max_key()) { - break; - } - - if(items_hash->exists(*id)) { - return &(items_hash->at((*id)++)); - } else { - ++(*id); - } - } - - return nullptr; -} - -std::string SharedDatabase::GetBook(const char *txtfile) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - char txtfile2[20]; - std::string txtout; - strcpy(txtfile2,txtfile); - if (!RunQuery(query, MakeAnyLenString(&query, "SELECT txtfile FROM books where name='%s'", txtfile2), errbuf, &result)) { - std::cerr << "Error in GetBook query '" << query << "' " << errbuf << std::endl; - if (query != 0) - safe_delete_array(query); - txtout.assign(" ",1); - return txtout; - } - else { - safe_delete_array(query); - if (mysql_num_rows(result) == 0) { - mysql_free_result(result); - LogFile->write(EQEMuLog::Error, "No book to send, (%s)", txtfile); - txtout.assign(" ",1); - return txtout; - } - else { - row = mysql_fetch_row(result); - txtout.assign(row[0],strlen(row[0])); - mysql_free_result(result); - return txtout; - } - } -} - -void SharedDatabase::GetFactionListInfo(uint32 &list_count, uint32 &max_lists) { - list_count = 0; - max_lists = 0; - const char *query = "SELECT COUNT(*), MAX(id) FROM npc_faction"; - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query, strlen(query), errbuf, &result)) { - if(row = mysql_fetch_row(result)) { - list_count = static_cast(atoul(row[0])); - max_lists = static_cast(atoul(row[1])); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting npc faction info from database: %s, %s", query, errbuf); - } -} - -const NPCFactionList* SharedDatabase::GetNPCFactionEntry(uint32 id) { - if(!faction_hash) { - return nullptr; - } - - if(faction_hash->exists(id)) { - return &(faction_hash->at(id)); - } - - return nullptr; -} - -void SharedDatabase::LoadNPCFactionLists(void *data, uint32 size, uint32 list_count, uint32 max_lists) { - EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, list_count, max_lists); - const char *query = "SELECT npc_faction.id, npc_faction.primaryfaction, npc_faction.ignore_primary_assist, " - "npc_faction_entries.faction_id, npc_faction_entries.value, npc_faction_entries.npc_value, npc_faction_entries.temp " - "FROM npc_faction LEFT JOIN npc_faction_entries ON npc_faction.id = npc_faction_entries.npc_faction_id ORDER BY " - "npc_faction.id;"; - - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - NPCFactionList faction; - - if(RunQuery(query, strlen(query), errbuf, &result)) { - uint32 current_id = 0; - uint32 current_entry = 0; - while(row = mysql_fetch_row(result)) { - uint32 id = static_cast(atoul(row[0])); - if(id != current_id) { - if(current_id != 0) { - hash.insert(current_id, faction); - } - - memset(&faction, 0, sizeof(faction)); - current_entry = 0; - current_id = id; - faction.id = id; - faction.primaryfaction = static_cast(atoul(row[1])); - faction.assistprimaryfaction = (atoi(row[2]) == 0); - } - - if(!row[3]) { - continue; - } - - if(current_entry >= MAX_NPC_FACTIONS) { - continue; - } - - faction.factionid[current_entry] = static_cast(atoul(row[3])); - faction.factionvalue[current_entry] = static_cast(atoi(row[4])); - faction.factionnpcvalue[current_entry] = static_cast(atoi(row[5])); - faction.factiontemp[current_entry] = static_cast(atoi(row[6])); - ++current_entry; - } - - if(current_id != 0) { - hash.insert(current_id, faction); - } - - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting npc faction info from database: %s, %s", query, errbuf); -} -} - -bool SharedDatabase::LoadNPCFactionLists() { - if(faction_hash) { - return true; - } - - try { - EQEmu::IPCMutex mutex("faction"); - mutex.Lock(); - faction_mmf = new EQEmu::MemoryMappedFile("shared/faction"); - - uint32 list_count = 0; - uint32 max_lists = 0; - GetFactionListInfo(list_count, max_lists); - if(list_count == 0) { - EQ_EXCEPT("SharedDatabase", "Database returned no result"); - } - uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size( - list_count, max_lists)); - - if(faction_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Couldn't load npc factions because faction_mmf->Size() != size"); - } - - faction_hash = new EQEmu::FixedMemoryHashSet(reinterpret_cast(faction_mmf->Get()), size); - mutex.Unlock(); - } catch(std::exception& ex) { - LogFile->write(EQEMuLog::Error, "Error Loading npc factions: %s", ex.what()); - return false; - } - - return true; -} - -// Get the player profile and inventory for the given account "account_id" and -// character name "name". Return true if the character was found, otherwise false. -// False will also be returned if there is a database error. -bool SharedDatabase::GetPlayerProfile(uint32 account_id, char* name, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, char* current_zone, uint32 *current_instance) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES* result; - MYSQL_ROW row; - bool ret = false; - - unsigned long* lengths; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile,zonename,x,y,z,extprofile,instanceid FROM character_ WHERE account_id=%i AND name='%s'", account_id, name), errbuf, &result)) { - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - lengths = mysql_fetch_lengths(result); - if (lengths[0] == sizeof(PlayerProfile_Struct)) { - memcpy(pp, row[0], sizeof(PlayerProfile_Struct)); - - if (current_zone) - strcpy(current_zone, row[1]); - pp->zone_id = GetZoneID(row[1]); - pp->x = atof(row[2]); - pp->y = atof(row[3]); - pp->z = atof(row[4]); - pp->zoneInstance = atoi(row[6]); - if (pp->x == -1 && pp->y == -1 && pp->z == -1) - GetSafePoints(pp->zone_id, GetInstanceVersion(pp->zoneInstance), &pp->x, &pp->y, &pp->z); - - if(current_instance) - *current_instance = pp->zoneInstance; - - if(ext) { - //SetExtendedProfile handles any conversion - SetExtendedProfile(ext, row[5], lengths[5]); - } - - // Retrieve character inventory - ret = GetInventory(account_id, name, inv); - } - else { - LogFile->write(EQEMuLog::Error, "Player profile length mismatch in GetPlayerProfile. Found: %i, Expected: %i", - lengths[0], sizeof(PlayerProfile_Struct)); - } - } - - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "GetPlayerProfile query '%s' %s", query, errbuf); - } - - safe_delete_array(query); - return ret; -} - -bool SharedDatabase::SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 affected_rows = 0; - bool ret = false; - - if (RunQuery(query, SetPlayerProfile_MQ(&query, account_id, charid, pp, inv, ext, current_zone, current_instance, MaxXTargets), errbuf, 0, &affected_rows)) { - ret = (affected_rows != 0); - } - - if (!ret) { - LogFile->write(EQEMuLog::Error, "SetPlayerProfile query '%s' %s", query, errbuf); - } - - safe_delete_array(query); - return ret; -} - -// Generate SQL for updating player profile -uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { - *query = new char[396 + sizeof(PlayerProfile_Struct)*2 + sizeof(ExtendedProfile_Struct)*2 + 4]; - char* end = *query; - if (!current_zone) - current_zone = pp->zone_id; - - if (!current_instance) - current_instance = pp->zoneInstance; - - if(strlen(pp->name) == 0) // Sanity check in case pp never loaded - return false; - - end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, profile=\'", pp->name, GetZoneName(current_zone), current_zone, current_instance, pp->x, pp->y, pp->z); - end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct)); - end += sprintf(end,"\', extprofile=\'"); - end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); - end += sprintf(end,"\',class=%d,level=%d,xtargets=%u WHERE id=%u", pp->class_, pp->level, MaxXTargets, charid); - - return (uint32) (end - (*query)); -} - - - -// Create appropriate ItemInst class -ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) -{ - const Item_Struct* item = nullptr; - ItemInst* inst = nullptr; - item = GetItem(item_id); - if (item) { - inst = CreateBaseItem(item, charges); - inst->PutAugment(this, 0, aug1); - inst->PutAugment(this, 1, aug2); - inst->PutAugment(this, 2, aug3); - inst->PutAugment(this, 3, aug4); - inst->PutAugment(this, 4, aug5); - } - - return inst; -} - - -// Create appropriate ItemInst class -ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) -{ - ItemInst* inst = nullptr; - if (item) { - inst = CreateBaseItem(item, charges); - inst->PutAugment(this, 0, aug1); - inst->PutAugment(this, 1, aug2); - inst->PutAugment(this, 2, aug3); - inst->PutAugment(this, 3, aug4); - inst->PutAugment(this, 4, aug5); - } - - return inst; -} - -ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges) { - ItemInst* inst = nullptr; - if (item) { - // if maxcharges is -1 that means it is an unlimited use item. - // set it to 1 charge so that it is usable on creation - if (charges == 0 && item->MaxCharges == -1) - charges = 1; - - inst = new ItemInst(item, charges); - - if(item->CharmFileID != 0 || (item->LoreGroup >= 1000 && item->LoreGroup != -1)) { - inst->Initialize(this); - } - } - return inst; -} - -int32 SharedDatabase::DeleteStalePlayerCorpses() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - - if(RuleB(Zone, EnableShadowrest)) - { - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE player_corpses SET IsBurried = 1 WHERE IsBurried=0 and " - "(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timeofdeath)) > %d and not timeofdeath=0", - (RuleI(Character, CorpseDecayTimeMS) / 1000)), errbuf, 0, &affected_rows)) - { - safe_delete_array(query); - return -1; - } - } - else - { - if (!RunQuery(query, MakeAnyLenString(&query, "Delete from player_corpses where (UNIX_TIMESTAMP() - " - "UNIX_TIMESTAMP(timeofdeath)) > %d and not timeofdeath=0", (RuleI(Character, CorpseDecayTimeMS) / 1000)), - errbuf, 0, &affected_rows)) - { - safe_delete_array(query); - return -1; - } - } - - safe_delete_array(query); - return affected_rows; -} - -int32 SharedDatabase::DeleteStalePlayerBackups() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - - // 1209600 seconds = 2 weeks - if (!RunQuery(query, MakeAnyLenString(&query, "Delete from player_corpses_backup where (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timeofdeath)) > 1209600"), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - return -1; - } - safe_delete_array(query); - - return affected_rows; -} - -bool SharedDatabase::GetCommandSettings(std::map &commands) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - query = new char[256]; - strcpy(query, "SELECT command,access from commands"); - commands.clear(); - if (RunQuery(query, strlen(query), errbuf, &result)) { - safe_delete_array(query); - while((row = mysql_fetch_row(result))) { - commands[row[0]]=atoi(row[1]); - } - mysql_free_result(result); - return true; - } else { - std::cerr << "Error in GetCommands query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - return false; -} - -bool SharedDatabase::LoadSkillCaps() { - if(skill_caps_mmf) - return true; - - uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; - uint32 level_count = HARD_LEVEL_CAP + 1; - uint32 size = (class_count * skill_count * level_count * sizeof(uint16)); - - try { - EQEmu::IPCMutex mutex("skill_caps"); - mutex.Lock(); - skill_caps_mmf = new EQEmu::MemoryMappedFile("shared/skill_caps"); - if(skill_caps_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Unable to load skill caps: skill_caps_mmf->Size() != size"); - } - - mutex.Unlock(); - } catch(std::exception &ex) { - LogFile->write(EQEMuLog::Error, "Error loading skill caps: %s", ex.what()); - return false; - } - - return true; -} - -void SharedDatabase::LoadSkillCaps(void *data) { - uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; - uint32 level_count = HARD_LEVEL_CAP + 1; - uint16 *skill_caps_table = reinterpret_cast(data); - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if(RunQuery(query, MakeAnyLenString(&query, - "SELECT skillID, class, level, cap FROM skill_caps ORDER BY skillID, class, level"), - errbuf, &result)) { - safe_delete_array(query); - - while((row = mysql_fetch_row(result))) { - uint8 skillID = atoi(row[0]); - uint8 class_ = atoi(row[1]) - 1; - uint8 level = atoi(row[2]); - uint16 cap = atoi(row[3]); - if(skillID >= skill_count || class_ >= class_count || level >= level_count) - continue; - - uint32 index = (((class_ * skill_count) + skillID) * level_count) + level; - skill_caps_table[index] = cap; - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error loading skill caps from database: %s", errbuf); - safe_delete_array(query); - } -} - -uint16 SharedDatabase::GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Level) { - if(!skill_caps_mmf) { - return 0; - } - - if(Class_ == 0) - return 0; - - int SkillMaxLevel = RuleI(Character, SkillCapMaxLevel); - if(SkillMaxLevel < 1) { - SkillMaxLevel = RuleI(Character, MaxLevel); - } - - uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; - uint32 level_count = HARD_LEVEL_CAP + 1; - if(Class_ > class_count || static_cast(Skill) > skill_count || Level > level_count) { - return 0; - } - - if(Level > static_cast(SkillMaxLevel)){ - Level = static_cast(SkillMaxLevel); - } - - uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count) + Level; - uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); - return skill_caps_table[index]; -} - -uint8 SharedDatabase::GetTrainLevel(uint8 Class_, SkillUseTypes Skill, uint8 Level) { - if(!skill_caps_mmf) { - return 0; - } - - if(Class_ == 0) - return 0; - - int SkillMaxLevel = RuleI(Character, SkillCapMaxLevel); - if (SkillMaxLevel < 1) { - SkillMaxLevel = RuleI(Character, MaxLevel); - } - - uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; - uint32 level_count = HARD_LEVEL_CAP + 1; - if(Class_ > class_count || static_cast(Skill) > skill_count || Level > level_count) { - return 0; - } - - uint8 ret = 0; - if(Level > static_cast(SkillMaxLevel)) { - uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count); - uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); - for(uint8 x = 0; x < Level; x++){ - if(skill_caps_table[index + x]){ - ret = x; - break; - } - } - } - else - { - uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count); - uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); - for(int x = 0; x < SkillMaxLevel; x++){ - if(skill_caps_table[index + x]){ - ret = x; - break; - } - } - } - - if(ret > GetSkillCap(Class_, Skill, Level)) - ret = static_cast(GetSkillCap(Class_, Skill, Level)); - - return ret; -} - -void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID) { - - const char *DSQuery = "SELECT `spellid`, `type` from `damageshieldtypes` WHERE `spellid` > 0 " - "AND `spellid` <= %i"; - - const char *ERR_MYSQLERROR = "Error in LoadDamageShieldTypes: %s %s"; - - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query,MakeAnyLenString(&query,DSQuery,iMaxSpellID),errbuf,&result)) { - - while((row = mysql_fetch_row(result))) { - - int SpellID = atoi(row[0]); - if((SpellID > 0) && (SpellID <= iMaxSpellID)) { - sp[SpellID].DamageShieldType = atoi(row[1]); - } - } - mysql_free_result(result); - safe_delete_array(query); - } - else { - LogFile->write(EQEMuLog::Error, ERR_MYSQLERROR, query, errbuf); - safe_delete_array(query); - } -} - -const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) { - return nullptr; // nothing here for now... database and/or sharemem pulls later -} - -int SharedDatabase::GetMaxSpellID() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = nullptr; - MYSQL_RES *result; - MYSQL_ROW row; - int32 ret = 0; - if(RunQuery(query, MakeAnyLenString(&query, "SELECT MAX(id) FROM spells_new"), - errbuf, &result)) { - safe_delete_array(query); - row = mysql_fetch_row(result); - ret = atoi(row[0]); - mysql_free_result(result); - } else { - _log(SPELLS__LOAD_ERR, "Error in GetMaxSpellID query '%s' %s", query, errbuf); - safe_delete_array(query); - ret = -1; - } - return ret; -} - -void SharedDatabase::LoadSpells(void *data, int max_spells) { - SPDat_Spell_Struct *sp = reinterpret_cast(data); - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query, MakeAnyLenString(&query, - "SELECT * FROM spells_new ORDER BY id ASC"), - errbuf, &result)) { - safe_delete_array(query); - - int tempid = 0; - int counter = 0; - while (row = mysql_fetch_row(result)) { - tempid = atoi(row[0]); - if(tempid >= max_spells) { - _log(SPELLS__LOAD_ERR, "Non fatal error: spell.id >= max_spells, ignoring."); - continue; - } - - ++counter; - sp[tempid].id = tempid; - strn0cpy(sp[tempid].name, row[1], sizeof(sp[tempid].name)); - strn0cpy(sp[tempid].player_1, row[2], sizeof(sp[tempid].player_1)); - strn0cpy(sp[tempid].teleport_zone, row[3], sizeof(sp[tempid].teleport_zone)); - strn0cpy(sp[tempid].you_cast, row[4], sizeof(sp[tempid].you_cast)); - strn0cpy(sp[tempid].other_casts, row[5], sizeof(sp[tempid].other_casts)); - strn0cpy(sp[tempid].cast_on_you, row[6], sizeof(sp[tempid].cast_on_you)); - strn0cpy(sp[tempid].cast_on_other, row[7], sizeof(sp[tempid].cast_on_other)); - strn0cpy(sp[tempid].spell_fades, row[8], sizeof(sp[tempid].spell_fades)); - - sp[tempid].range=static_cast(atof(row[9])); - sp[tempid].aoerange=static_cast(atof(row[10])); - sp[tempid].pushback=static_cast(atof(row[11])); - sp[tempid].pushup=static_cast(atof(row[12])); - sp[tempid].cast_time=atoi(row[13]); - sp[tempid].recovery_time=atoi(row[14]); - sp[tempid].recast_time=atoi(row[15]); - sp[tempid].buffdurationformula=atoi(row[16]); - sp[tempid].buffduration=atoi(row[17]); - sp[tempid].AEDuration=atoi(row[18]); - sp[tempid].mana=atoi(row[19]); - - int y=0; - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].base[y]=atoi(row[20+y]); // effect_base_value - for(y=0; y < EFFECT_COUNT; y++) - sp[tempid].base2[y]=atoi(row[32+y]); // effect_limit_value - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].max[y]=atoi(row[44+y]); - - for(y=0; y< 4;y++) - sp[tempid].components[y]=atoi(row[58+y]); - - for(y=0; y< 4;y++) - sp[tempid].component_counts[y]=atoi(row[62+y]); - - for(y=0; y< 4;y++) - sp[tempid].NoexpendReagent[y]=atoi(row[66+y]); - - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].formula[y]=atoi(row[70+y]); - - sp[tempid].goodEffect=atoi(row[83]); - sp[tempid].Activated=atoi(row[84]); - sp[tempid].resisttype=atoi(row[85]); - - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].effectid[y]=atoi(row[86+y]); - - sp[tempid].targettype = (SpellTargetType) atoi(row[98]); - sp[tempid].basediff=atoi(row[99]); - int tmp_skill = atoi(row[100]);; - if(tmp_skill < 0 || tmp_skill > HIGHEST_SKILL) - sp[tempid].skill = SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated - else - sp[tempid].skill = (SkillUseTypes) tmp_skill; - sp[tempid].zonetype=atoi(row[101]); - sp[tempid].EnvironmentType=atoi(row[102]); - sp[tempid].TimeOfDay=atoi(row[103]); - - for(y=0; y < PLAYER_CLASS_COUNT;y++) - sp[tempid].classes[y]=atoi(row[104+y]); - - sp[tempid].CastingAnim=atoi(row[120]); - sp[tempid].SpellAffectIndex=atoi(row[123]); - sp[tempid].disallow_sit=atoi(row[124]); - - for (y = 0; y < 16; y++) - sp[tempid].deities[y]=atoi(row[126+y]); - - sp[tempid].uninterruptable=atoi(row[146]); - sp[tempid].ResistDiff=atoi(row[147]); - sp[tempid].dot_stacking_exempt=atoi(row[148]); - sp[tempid].RecourseLink = atoi(row[150]); - sp[tempid].no_partial_resist = atoi(row[151]) != 0; - - sp[tempid].short_buff_box = atoi(row[154]); - sp[tempid].descnum = atoi(row[155]); - sp[tempid].effectdescnum = atoi(row[157]); - - sp[tempid].reflectable = atoi(row[161]) != 0; - sp[tempid].bonushate=atoi(row[162]); - - sp[tempid].EndurCost=atoi(row[166]); - sp[tempid].EndurTimerIndex=atoi(row[167]); - sp[tempid].HateAdded=atoi(row[173]); - sp[tempid].EndurUpkeep=atoi(row[174]); - sp[tempid].numhitstype = atoi(row[175]); - sp[tempid].numhits = atoi(row[176]); - sp[tempid].pvpresistbase=atoi(row[177]); - sp[tempid].pvpresistcalc=atoi(row[178]); - sp[tempid].pvpresistcap=atoi(row[179]); - sp[tempid].spell_category=atoi(row[180]); - sp[tempid].can_mgb=atoi(row[185]); - sp[tempid].dispel_flag = atoi(row[186]); - sp[tempid].MinResist = atoi(row[189]); - sp[tempid].MaxResist = atoi(row[190]); - sp[tempid].viral_targets = atoi(row[191]); - sp[tempid].viral_timer = atoi(row[192]); - sp[tempid].NimbusEffect = atoi(row[193]); - sp[tempid].directional_start = (float)atoi(row[194]); - sp[tempid].directional_end = (float)atoi(row[195]); - sp[tempid].not_extendable = atoi(row[197]) != 0; - sp[tempid].suspendable = atoi(row[200]) != 0; - sp[tempid].spellgroup=atoi(row[207]); - sp[tempid].powerful_flag=atoi(row[209]); - sp[tempid].CastRestriction = atoi(row[211]); - sp[tempid].AllowRest = atoi(row[212]) != 0; - sp[tempid].NotOutofCombat = atoi(row[213]) != 0; - sp[tempid].NotInCombat = atoi(row[214]) != 0; - sp[tempid].aemaxtargets = atoi(row[218]); - sp[tempid].maxtargets = atoi(row[219]); - sp[tempid].persistdeath = atoi(row[224]) != 0; - sp[tempid].DamageShieldType = 0; - } - mysql_free_result(result); - - LoadDamageShieldTypes(sp, max_spells); - } else { - _log(SPELLS__LOAD_ERR, "Error in LoadSpells query '%s' %s", query, errbuf); - safe_delete_array(query); - } -} - -int SharedDatabase::GetMaxBaseDataLevel() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = "SELECT MAX(level) FROM base_data"; - MYSQL_RES *result; - MYSQL_ROW row; - int32 ret = 0; - if(RunQuery(query, strlen(query), errbuf, &result)) { - row = mysql_fetch_row(result); - if(row) { - ret = atoi(row[0]); - mysql_free_result(result); - } else { - ret = -1; - mysql_free_result(result); - } - } else { - LogFile->write(EQEMuLog::Error, "Error in GetMaxBaseDataLevel query '%s' %s", query, errbuf); - ret = -1; - } - return ret; -} - -bool SharedDatabase::LoadBaseData() { - if(base_data_mmf) { - return true; - } - - try { - EQEmu::IPCMutex mutex("base_data"); - mutex.Lock(); - base_data_mmf = new EQEmu::MemoryMappedFile("shared/base_data"); - - int size = 16 * (GetMaxBaseDataLevel() + 1) * sizeof(BaseDataStruct); - if(size == 0) { - EQ_EXCEPT("SharedDatabase", "Base Data size is zero"); - } - - if(base_data_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Couldn't load base data because base_data_mmf->Size() != size"); - } - - mutex.Unlock(); - } catch(std::exception& ex) { - LogFile->write(EQEMuLog::Error, "Error Loading Base Data: %s", ex.what()); - return false; - } - - return true; -} - -void SharedDatabase::LoadBaseData(void *data, int max_level) { - char *base_ptr = reinterpret_cast(data); - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = "SELECT * FROM base_data ORDER BY level, class ASC"; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query, strlen(query), errbuf, &result)) { - - int lvl = 0; - int cl = 0; - while (row = mysql_fetch_row(result)) { - lvl = atoi(row[0]); - cl = atoi(row[1]); - if(lvl <= 0) { - LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.level <= 0, ignoring."); - continue; - } - - if(lvl >= max_level) { - LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.level >= max_level, ignoring."); - continue; - } - - if(cl <= 0) { - LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.cl <= 0, ignoring."); - continue; - } - - if(cl > 16) { - LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.class > 16, ignoring."); - continue; - } - - BaseDataStruct *bd = reinterpret_cast(base_ptr + (((16 * (lvl - 1)) + (cl - 1)) * sizeof(BaseDataStruct))); - bd->base_hp = atof(row[2]); - bd->base_mana = atof(row[3]); - bd->base_end = atof(row[4]); - bd->unk1 = atof(row[5]); - bd->unk2 = atof(row[6]); - bd->hp_factor = atof(row[7]); - bd->mana_factor = atof(row[8]); - bd->endurance_factor = atof(row[9]); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in LoadBaseData query '%s' %s", query, errbuf); - safe_delete_array(query); - } -} - -const BaseDataStruct* SharedDatabase::GetBaseData(int lvl, int cl) { - if(!base_data_mmf) { - return nullptr; - } - - if(lvl <= 0) { - return nullptr; - } - - if(cl <= 0) { - return nullptr; - } - - if(cl > 16) { - return nullptr; - } - - char *base_ptr = reinterpret_cast(base_data_mmf->Get()); - - uint32 offset = ((16 * (lvl - 1)) + (cl - 1)) * sizeof(BaseDataStruct); - - if(offset >= base_data_mmf->Size()) { - return nullptr; - } - - BaseDataStruct *bd = reinterpret_cast(base_ptr + offset); - return bd; -} - -void SharedDatabase::GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot_table, uint32 &loot_table_entries) { - loot_table_count = 0; - max_loot_table = 0; - loot_table_entries = 0; - const char *query = "SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM loottable_entries) FROM loottable"; - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query, strlen(query), errbuf, &result)) { - if(row = mysql_fetch_row(result)) { - loot_table_count = static_cast(atoul(row[0])); - max_loot_table = static_cast(atoul(row[1])); - loot_table_entries = static_cast(atoul(row[2])); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", query, errbuf); - } -} - -void SharedDatabase::GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_drop, uint32 &loot_drop_entries) { - loot_drop_count = 0; - max_loot_drop = 0; - loot_drop_entries = 0; - const char *query = "SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM lootdrop_entries) FROM lootdrop"; - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query, strlen(query), errbuf, &result)) { - if(row = mysql_fetch_row(result)) { - loot_drop_count = static_cast(atoul(row[0])); - max_loot_drop = static_cast(atoul(row[1])); - loot_drop_entries = static_cast(atoul(row[2])); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", query, errbuf); - } -} - -void SharedDatabase::LoadLootTables(void *data, uint32 size) { - EQEmu::FixedMemoryVariableHashSet hash(reinterpret_cast(data), size); - const char *query = "SELECT loottable.id, loottable.mincash, loottable.maxcash, loottable.avgcoin," - " loottable_entries.lootdrop_id, loottable_entries.multiplier, loottable_entries.droplimit, " - "loottable_entries.mindrop, loottable_entries.probability FROM loottable LEFT JOIN loottable_entries" - " ON loottable.id = loottable_entries.loottable_id ORDER BY id"; - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - uint8 loot_table[sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128)]; - LootTable_Struct *lt = reinterpret_cast(loot_table); - - if(RunQuery(query, strlen(query), errbuf, &result)) { - uint32 current_id = 0; - uint32 current_entry = 0; - while(row = mysql_fetch_row(result)) { - uint32 id = static_cast(atoul(row[0])); - if(id != current_id) { - if(current_id != 0) { - hash.insert(current_id, loot_table, (sizeof(LootTable_Struct) + - (sizeof(LootTableEntries_Struct) * lt->NumEntries))); - } - - memset(loot_table, 0, sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128)); - current_entry = 0; - current_id = id; - lt->mincash = static_cast(atoul(row[1])); - lt->maxcash = static_cast(atoul(row[2])); - lt->avgcoin = static_cast(atoul(row[3])); - } - - if(current_entry > 128) { - continue; - } - - if(!row[4]) { - continue; - } - - lt->Entries[current_entry].lootdrop_id = static_cast(atoul(row[4])); - lt->Entries[current_entry].multiplier = static_cast(atoi(row[5])); - lt->Entries[current_entry].droplimit = static_cast(atoi(row[6])); - lt->Entries[current_entry].mindrop = static_cast(atoi(row[7])); - lt->Entries[current_entry].probability = static_cast(atof(row[8])); - - ++(lt->NumEntries); - ++current_entry; - } - if(current_id != 0) { - hash.insert(current_id, loot_table, (sizeof(LootTable_Struct) + - (sizeof(LootTableEntries_Struct) * lt->NumEntries))); - } - - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", query, errbuf); - } -} - -void SharedDatabase::LoadLootDrops(void *data, uint32 size) { - EQEmu::FixedMemoryVariableHashSet hash(reinterpret_cast(data), size); - const char *query = "SELECT lootdrop.id, lootdrop_entries.item_id, lootdrop_entries.item_charges, " - "lootdrop_entries.equip_item, lootdrop_entries.chance, lootdrop_entries.minlevel, " - "lootdrop_entries.maxlevel, lootdrop_entries.multiplier FROM lootdrop JOIN lootdrop_entries " - "ON lootdrop.id = lootdrop_entries.lootdrop_id ORDER BY lootdrop_id"; - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - uint8 loot_drop[sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * 1260)]; - LootDrop_Struct *ld = reinterpret_cast(loot_drop); - if(RunQuery(query, strlen(query), errbuf, &result)) { - uint32 current_id = 0; - uint32 current_entry = 0; - while(row = mysql_fetch_row(result)) { - uint32 id = static_cast(atoul(row[0])); - if(id != current_id) { - if(current_id != 0) { - hash.insert(current_id, loot_drop, (sizeof(LootDrop_Struct) + - (sizeof(LootDropEntries_Struct) * ld->NumEntries))); - } - - memset(loot_drop, 0, sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * 1260)); - current_entry = 0; - current_id = id; - } - - if(current_entry >= 1260) { - continue; - } - - ld->Entries[current_entry].item_id = static_cast(atoul(row[1])); - ld->Entries[current_entry].item_charges = static_cast(atoi(row[2])); - ld->Entries[current_entry].equip_item = static_cast(atoi(row[3])); - ld->Entries[current_entry].chance = static_cast(atof(row[4])); - ld->Entries[current_entry].minlevel = static_cast(atoi(row[5])); - ld->Entries[current_entry].maxlevel = static_cast(atoi(row[6])); - ld->Entries[current_entry].multiplier = static_cast(atoi(row[7])); - - ++(ld->NumEntries); - ++current_entry; - } - if(current_id != 0) { - hash.insert(current_id, loot_drop, (sizeof(LootDrop_Struct) + - (sizeof(LootDropEntries_Struct) * ld->NumEntries))); - } - - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting loot drop info from database: %s, %s", query, errbuf); - } -} - -bool SharedDatabase::LoadLoot() { - if(loot_table_mmf || loot_drop_mmf) - return true; - - try { - EQEmu::IPCMutex mutex("loot"); - mutex.Lock(); - loot_table_mmf = new EQEmu::MemoryMappedFile("shared/loot_table"); - loot_table_hash = new EQEmu::FixedMemoryVariableHashSet( - reinterpret_cast(loot_table_mmf->Get()), - loot_table_mmf->Size()); - loot_drop_mmf = new EQEmu::MemoryMappedFile("shared/loot_drop"); - loot_drop_hash = new EQEmu::FixedMemoryVariableHashSet( - reinterpret_cast(loot_drop_mmf->Get()), - loot_drop_mmf->Size()); - mutex.Unlock(); - } catch(std::exception &ex) { - LogFile->write(EQEMuLog::Error, "Error loading loot: %s", ex.what()); - return false; - } - - return true; -} - -const LootTable_Struct* SharedDatabase::GetLootTable(uint32 loottable_id) { - if(!loot_table_hash) - return nullptr; - - try { - if(loot_table_hash->exists(loottable_id)) { - return &loot_table_hash->at(loottable_id); - } - } catch(std::exception &ex) { - LogFile->write(EQEMuLog::Error, "Could not get loot table: %s", ex.what()); - } - return nullptr; -} - -const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) { - if(!loot_drop_hash) - return nullptr; - - try { - if(loot_drop_hash->exists(lootdrop_id)) { - return &loot_drop_hash->at(lootdrop_id); - } - } catch(std::exception &ex) { - LogFile->write(EQEMuLog::Error, "Could not get loot drop: %s", ex.what()); - } - return nullptr; -} - -void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT inspectmessage FROM character_ WHERE name='%s'", playername), errbuf, &result)) { - safe_delete_array(query); - - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - memcpy(message, row[0], sizeof(InspectMessage_Struct)); - } - - mysql_free_result(result); - } - else { - std::cerr << "Error in GetPlayerInspectMessage query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } -} - -void SharedDatabase::SetPlayerInspectMessage(char* playername, const InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET inspectmessage='%s' WHERE name='%s'", message->text, playername), errbuf)) { - std::cerr << "Error in SetPlayerInspectMessage query '" << query << "' " << errbuf << std::endl; - } - - safe_delete_array(query); -} - -void SharedDatabase::GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT BotInspectMessage FROM bots WHERE BotID=%i", botid), errbuf, &result)) { - safe_delete_array(query); - - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - memcpy(message, row[0], sizeof(InspectMessage_Struct)); - } - - mysql_free_result(result); - } - else { - std::cerr << "Error in GetBotInspectMessage query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } -} - -void SharedDatabase::SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE bots SET BotInspectMessage='%s' WHERE BotID=%i", message->text, botid), errbuf)) { - std::cerr << "Error in SetBotInspectMessage query '" << query << "' " << errbuf << std::endl; - } - - safe_delete_array(query); -} diff --git a/common/spdat.h b/common/spdat.h index 5bb29b8c4..0e9096f1a 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -529,7 +529,7 @@ typedef enum { #define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades. #define SE_ApplyEffect 374 // implemented #define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount -#define SE_Fling 376 // *not implemented - used in 2 test spells (12945 | Movement Test Spell 1) +//#define SE_Fling 376 // *not implemented - used in 2 test spells (12945 | Movement Test Spell 1) #define SE_CastOnFadeEffectNPC 377 // implemented - Triggers only if fades after natural duration (On live these are usually players spells that effect an NPC). #define SE_SpellEffectResistChance 378 // implemented - Increase chance to resist specific spell effect (base1=value, base2=spell effect id) #define SE_ShadowStepDirectional 379 // implemented - handled by client diff --git a/utils/sql/git/required/2014_02_12_spells_new_update.sql b/utils/sql/git/required/2014_02_12_spells_new_update.sql deleted file mode 100644 index ba552e1ed..000000000 --- a/utils/sql/git/required/2014_02_12_spells_new_update.sql +++ /dev/null @@ -1,13 +0,0 @@ -ALTER TABLE `spells_new` CHANGE `field161` `not_reflectable` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field151` `no_partial_resist` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field189` `MinResist` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field190` `MaxResist` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field194` `ConeStartAngle` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field195` `ConeStopAngle` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field208` `rank` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field159` `npc_no_los` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field213` `NotOutofCombat` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field214` `NotInCombat` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field168` `IsDiscipline` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field211` `CastRestrict` INT(11) NOT NULL DEFAULT '0'; - diff --git a/utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql b/utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql deleted file mode 100644 index 12e9963a5..000000000 --- a/utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql +++ /dev/null @@ -1,3 +0,0 @@ -ALTER TABLE `npc_types` ADD `no_target_hotkey` tinyint( 1 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `healscale`; - - diff --git a/utils/sql/git/required/2014_06_22_MetabolismAAs.sql b/utils/sql/git/required/2014_06_22_MetabolismAAs.sql deleted file mode 100644 index 3a957edb2..000000000 --- a/utils/sql/git/required/2014_06_22_MetabolismAAs.sql +++ /dev/null @@ -1,6 +0,0 @@ --- Innate Metabolism -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('68', '1', '233', '110', '0'); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('69', '1', '233', '125', '0'); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('70', '1', '233', '150', '0'); - - diff --git a/zone/AA_base.cpp b/zone/AA_base.cpp deleted file mode 100644 index 8566c09b5..000000000 --- a/zone/AA_base.cpp +++ /dev/null @@ -1,1990 +0,0 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -// Test 1 - -#include "../common/debug.h" -#include "AA.h" -#include "mob.h" -#include "client.h" -#include "groups.h" -#include "raids.h" -#include "../common/spdat.h" -#include "object.h" -#include "doors.h" -#include "beacon.h" -#include "corpse.h" -#include "titles.h" -#include "../common/races.h" -#include "../common/classes.h" -#include "../common/eq_packet_structs.h" -#include "../common/packet_dump.h" -#include "../common/StringUtil.h" -#include "../common/logsys.h" -#include "zonedb.h" -#include "StringIDs.h" - -//static data arrays, really not big enough to warrant shared mem. -AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank] -std::mapaas_send; -std::map > aa_effects; //stores the effects from the aa_effects table in memory -std::map AARequiredLevelAndCost; - -/* - - -Schema: - -spell_id is spell to cast, SPELL_UNKNOWN == no spell -nonspell_action is action to preform on activation which is not a spell, 0=none -nonspell_mana is mana that the nonspell action consumes -nonspell_duration is a duration which may be used by the nonspell action -redux_aa is the aa which reduces the reuse timer of the skill -redux_rate is the multiplier of redux_aa, as a percentage of total rate (10 == 10% faster) - -CREATE TABLE aa_actions ( - aaid mediumint unsigned not null, - rank tinyint unsigned not null, - reuse_time mediumint unsigned not null, - spell_id mediumint unsigned not null, - target tinyint unsigned not null, - nonspell_action tinyint unsigned not null, - nonspell_mana mediumint unsigned not null, - nonspell_duration mediumint unsigned not null, - redux_aa mediumint unsigned not null, - redux_rate tinyint not null, - - PRIMARY KEY(aaid, rank) -); - -CREATE TABLE aa_swarmpets ( - spell_id mediumint unsigned not null, - count tinyint unsigned not null, - npc_id int not null, - duration mediumint unsigned not null, - PRIMARY KEY(spell_id) -); -*/ - -/* - -Credits for this function: - -FatherNitwit: Structure and mechanism - -Wiz: Initial set of AAs, original function contents - -Branks: Much updated info and a bunch of higher-numbered AAs - -*/ -int Client::GetAATimerID(aaID activate) -{ - SendAA_Struct* aa2 = zone->FindAA(activate); - - if(!aa2) - { - for(int i = 1;i < MAX_AA_ACTION_RANKS; ++i) - { - int a = activate - i; - - if(a <= 0) - break; - - aa2 = zone->FindAA(a); - - if(aa2 != nullptr) - break; - } - } - - if(aa2) - return aa2->spell_type; - - return 0; -} - -int Client::CalcAAReuseTimer(const AA_DBAction *caa) { - - if(!caa) - return 0; - - int ReuseTime = caa->reuse_time; - - if(ReuseTime > 0) - { - int ReductionPercentage; - - if(caa->redux_aa > 0 && caa->redux_aa < aaHighestID) - { - ReductionPercentage = GetAA(caa->redux_aa) * caa->redux_rate; - - if(caa->redux_aa2 > 0 && caa->redux_aa2 < aaHighestID) - ReductionPercentage += (GetAA(caa->redux_aa2) * caa->redux_rate2); - - ReuseTime = caa->reuse_time * (100 - ReductionPercentage) / 100; - } - - } - return ReuseTime; -} - -void Client::ActivateAA(aaID activate){ - if(activate < 0 || activate >= aaHighestID) - return; - if(IsStunned() || IsFeared() || IsMezzed() || IsSilenced() || IsPet() || IsSitting() || GetFeigned()) - return; - - int AATimerID = GetAATimerID(activate); - - SendAA_Struct* aa2 = nullptr; - aaID aaid = activate; - uint8 activate_val = GetAA(activate); - //this wasn't taking into acct multi tiered act talents before... - if(activate_val == 0){ - aa2 = zone->FindAA(activate); - if(!aa2){ - int i; - int a; - for(i=1;iFindAA(a); - if(aa2 != nullptr) - break; - } - } - if(aa2){ - aaid = (aaID) aa2->id; - activate_val = GetAA(aa2->id); - } - } - - if (activate_val == 0){ - return; - } - - if(aa2) - { - if(aa2->account_time_required) - { - if((Timer::GetTimeSeconds() + account_creation) < aa2->account_time_required) - { - return; - } - } - } - - if(!p_timers.Expired(&database, AATimerID + pTimerAAStart)) - { - uint32 aaremain = p_timers.GetRemainingTime(AATimerID + pTimerAAStart); - uint32 aaremain_hr = aaremain / (60 * 60); - uint32 aaremain_min = (aaremain / 60) % 60; - uint32 aaremain_sec = aaremain % 60; - - if(aa2) { - if (aaremain_hr >= 1) //1 hour or more - Message(13, "You can use the ability %s again in %u hour(s) %u minute(s) %u seconds", - aa2->name, aaremain_hr, aaremain_min, aaremain_sec); - else //less than an hour - Message(13, "You can use the ability %s again in %u minute(s) %u seconds", - aa2->name, aaremain_min, aaremain_sec); - } else { - if (aaremain_hr >= 1) //1 hour or more - Message(13, "You can use this ability again in %u hour(s) %u minute(s) %u seconds", - aaremain_hr, aaremain_min, aaremain_sec); - else //less than an hour - Message(13, "You can use this ability again in %u minute(s) %u seconds", - aaremain_min, aaremain_sec); - } - return; - } - - if(activate_val > MAX_AA_ACTION_RANKS) - activate_val = MAX_AA_ACTION_RANKS; - activate_val--; //to get array index. - - //get our current node, now that the indices are well bounded - const AA_DBAction *caa = &AA_Actions[aaid][activate_val]; - - if((aaid == aaImprovedHarmTouch || aaid == aaLeechTouch) && !p_timers.Expired(&database, pTimerHarmTouch)){ - Message(13,"Ability recovery time not yet met."); - return; - } - - //everything should be configured out now - - uint16 target_id = 0; - - //figure out our target - switch(caa->target) { - case aaTargetUser: - case aaTargetGroup: - target_id = GetID(); - break; - case aaTargetCurrent: - case aaTargetCurrentGroup: - if(GetTarget() == nullptr) { - Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - target_id = GetTarget()->GetID(); - break; - case aaTargetPet: - if(GetPet() == nullptr) { - Message(0, "A pet is required for this skill."); - return; - } - target_id = GetPetID(); - break; - } - - //handle non-spell action - if(caa->action != aaActionNone) { - if(caa->mana_cost > 0) { - if(GetMana() < caa->mana_cost) { - Message_StringID(13, INSUFFICIENT_MANA); - return; - } - SetMana(GetMana() - caa->mana_cost); - } - if(caa->reuse_time > 0) - { - uint32 timer_base = CalcAAReuseTimer(caa); - if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) - { - p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); - } - p_timers.Start(AATimerID + pTimerAAStart, timer_base); - SendAATimer(AATimerID, 0, 0); - } - HandleAAAction(aaid); - } - - //cast the spell, if we have one - if(caa->spell_id > 0 && caa->spell_id < SPDAT_RECORDS) { - - if(caa->reuse_time > 0) - { - uint32 timer_base = CalcAAReuseTimer(caa); - SendAATimer(AATimerID, 0, 0); - p_timers.Start(AATimerID + pTimerAAStart, timer_base); - if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) - { - p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); - } - // Bards can cast instant cast AAs while they are casting another song - if (spells[caa->spell_id].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { - if(!SpellFinished(caa->spell_id, entity_list.GetMob(target_id), 10, -1, -1, spells[caa->spell_id].ResistDiff, false)) { - //Reset on failed cast - SendAATimer(AATimerID, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - } else { - if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { - //Reset on failed cast - SendAATimer(AATimerID, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - } - } - else - { - if(!CastSpell(caa->spell_id, target_id)) - return; - } - } - // Check if AA is expendable - if (aas_send[activate - activate_val]->special_category == 7) - { - // Add the AA cost to the extended profile to track overall total - m_epp.expended_aa += aas_send[activate]->cost; - SetAA(activate, 0); - - Save(); - SendAA(activate); - SendAATable(); - } -} - -void Client::HandleAAAction(aaID activate) { - if(activate < 0 || activate >= aaHighestID) - return; - - uint8 activate_val = GetAA(activate); - - if (activate_val == 0) - return; - - if(activate_val > MAX_AA_ACTION_RANKS) - activate_val = MAX_AA_ACTION_RANKS; - activate_val--; //to get array index. - - //get our current node, now that the indices are well bounded - const AA_DBAction *caa = &AA_Actions[activate][activate_val]; - - uint16 timer_id = 0; - uint16 timer_duration = caa->duration; - aaTargetType target = aaTargetUser; - - uint16 spell_id = SPELL_UNKNOWN; //gets cast at the end if not still unknown - - switch(caa->action) { - case aaActionAETaunt: - entity_list.AETaunt(this); - break; - - case aaActionMassBuff: - EnableAAEffect(aaEffectMassGroupBuff, 3600); - Message_StringID(MT_Disciplines, MGB_STRING); //The next group buff you cast will hit all targets in range. - break; - - case aaActionFlamingArrows: - //toggle it - if(CheckAAEffect(aaEffectFlamingArrows)) - EnableAAEffect(aaEffectFlamingArrows); - else - DisableAAEffect(aaEffectFlamingArrows); - break; - - case aaActionFrostArrows: - if(CheckAAEffect(aaEffectFrostArrows)) - EnableAAEffect(aaEffectFrostArrows); - else - DisableAAEffect(aaEffectFrostArrows); - break; - - case aaActionRampage: - EnableAAEffect(aaEffectRampage, 10); - break; - - case aaActionSharedHealth: - if(CheckAAEffect(aaEffectSharedHealth)) - EnableAAEffect(aaEffectSharedHealth); - else - DisableAAEffect(aaEffectSharedHealth); - break; - - case aaActionCelestialRegen: { - //special because spell_id depends on a different AA - switch (GetAA(aaCelestialRenewal)) { - case 1: - spell_id = 3250; - break; - case 2: - spell_id = 3251; - break; - default: - spell_id = 2740; - break; - } - target = aaTargetCurrent; - break; - } - - case aaActionDireCharm: { - //special because spell_id depends on class - switch (GetClass()) - { - case DRUID: - spell_id = 2760; //2644? - break; - case NECROMANCER: - spell_id = 2759; //2643? - break; - case ENCHANTER: - spell_id = 2761; //2642? - break; - } - target = aaTargetCurrent; - break; - } - - case aaActionImprovedFamiliar: { - //Spell IDs might be wrong... - if (GetAA(aaAllegiantFamiliar)) - spell_id = 3264; //1994? - else - spell_id = 2758; //2155? - break; - } - - case aaActionActOfValor: - if(GetTarget() != nullptr) { - int curhp = GetTarget()->GetHP(); - target = aaTargetCurrent; - GetTarget()->HealDamage(curhp, this); - Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); - } - break; - - case aaActionSuspendedMinion: - if (GetPet()) { - target = aaTargetPet; - switch (GetAA(aaSuspendedMinion)) { - case 1: - spell_id = 3248; - break; - case 2: - spell_id = 3249; - break; - } - //do we really need to cast a spell? - - Message(0,"You call your pet to your side."); - GetPet()->WipeHateList(); - GetPet()->GMMove(GetX(),GetY(),GetZ()); - if (activate_val > 1) - entity_list.ClearFeignAggro(GetPet()); - } else { - Message(0,"You have no pet to call."); - } - break; - - case aaActionProjectIllusion: - EnableAAEffect(aaEffectProjectIllusion, 3600); - Message(10, "The power of your next illusion spell will flow to your grouped target in your place."); - break; - - - case aaActionEscape: - Escape(); - break; - - // Don't think this code is used any longer for Bestial Alignment as the AA has a spell_id and no nonspell_action. - case aaActionBeastialAlignment: - switch(GetBaseRace()) { - case BARBARIAN: - spell_id = AA_Choose3(activate_val, 4521, 4522, 4523); - break; - case TROLL: - spell_id = AA_Choose3(activate_val, 4524, 4525, 4526); - break; - case OGRE: - spell_id = AA_Choose3(activate_val, 4527, 4527, 4529); - break; - case IKSAR: - spell_id = AA_Choose3(activate_val, 4530, 4531, 4532); - break; - case VAHSHIR: - spell_id = AA_Choose3(activate_val, 4533, 4534, 4535); - break; - } - - case aaActionLeechTouch: - target = aaTargetCurrent; - spell_id = SPELL_HARM_TOUCH2; - EnableAAEffect(aaEffectLeechTouch, 1000); - break; - - case aaActionFadingMemories: - // Do nothing since spell effect works correctly, but mana isn't used. - break; - - default: - LogFile->write(EQEMuLog::Error, "Unknown AA nonspell action type %d", caa->action); - return; - } - - - uint16 target_id = 0; - //figure out our target - switch(target) { - case aaTargetUser: - case aaTargetGroup: - target_id = GetID(); - break; - case aaTargetCurrent: - case aaTargetCurrentGroup: - if(GetTarget() == nullptr) { - Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! - p_timers.Clear(&database, timer_id + pTimerAAEffectStart); - return; - } - target_id = GetTarget()->GetID(); - break; - case aaTargetPet: - if(GetPet() == nullptr) { - Message(0, "A pet is required for this skill."); - return; - } - target_id = GetPetID(); - break; - } - - //cast the spell, if we have one - if(IsValidSpell(spell_id)) { - int aatid = GetAATimerID(activate); - if(!CastSpell(spell_id, target_id , 10, -1, -1, 0, -1, pTimerAAStart + aatid , CalcAAReuseTimer(caa), 1)) { - SendAATimer(aatid, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, pTimerAAStart + aatid); - return; - } - } - - //handle the duration timer if we have one. - if(timer_id > 0 && timer_duration > 0) { - p_timers.Start(pTimerAAEffectStart + timer_id, timer_duration); - } -} - - -//Originally written by Branks -//functionality rewritten by Father Nitwit -void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override) { - - //It might not be a bad idea to put these into the database, eventually.. - - //Dook- swarms and wards - - PetRecord record; - if(!database.GetPetEntry(spells[spell_id].teleport_zone, &record)) - { - LogFile->write(EQEMuLog::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id); - Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone); - return; - } - - AA_SwarmPet pet; - pet.count = 1; - pet.duration = 1; - - for(int x = 0; x < 12; x++) - { - if(spells[spell_id].effectid[x] == SE_TemporaryPets) - { - pet.count = spells[spell_id].base[x]; - pet.duration = spells[spell_id].max[x]; - } - } - - if(IsClient()) - pet.duration += (CastToClient()->GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000); - - pet.npc_id = record.npc_type; - - NPCType *made_npc = nullptr; - - const NPCType *npc_type = database.GetNPCType(pet.npc_id); - if(npc_type == nullptr) { - //log write - LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet spell id: %d", spell_id); - Message(0,"Unable to find pet!"); - return; - } - - if(name_override != nullptr) { - //we have to make a custom NPC type for this name change - made_npc = new NPCType; - memcpy(made_npc, npc_type, sizeof(NPCType)); - strcpy(made_npc->name, name_override); - npc_type = made_npc; - } - - int summon_count = 0; - summon_count = pet.count; - - if(summon_count > MAX_SWARM_PETS) - summon_count = MAX_SWARM_PETS; - - static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, - 10, -10, 10, -10, - 8, -8, 8, -8 }; - static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, - 10, 10, -10, -10, - 8, 8, -8, -8 }; - TempPets(true); - - while(summon_count > 0) { - int pet_duration = pet.duration; - if(duration_override > 0) - pet_duration = duration_override; - - //this is a little messy, but the only way to do it right - //it would be possible to optimize out this copy for the last pet, but oh well - NPCType *npc_dup = nullptr; - if(made_npc != nullptr) { - npc_dup = new NPCType; - memcpy(npc_dup, made_npc, sizeof(NPCType)); - } - - NPC* npca = new NPC( - (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer - 0, - GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], - GetZ(), GetHeading(), FlyMode3); - - if((spell_id == 6882) || (spell_id == 6884)) - npca->SetFollowID(GetID()); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); - } - - //removing this prevents the pet from attacking - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pets somebody to "love" - if(targ != nullptr){ - npca->AddToHateList(targ, 1000, 1000); - npca->GetSwarmInfo()->target = targ->GetID(); - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); - - entity_list.AddNPC(npca, true, true); - summon_count--; - } - - //the target of these swarm pets will take offense to being cast on... - if(targ != nullptr) - targ->AddToHateList(this, 1, 0); -} - -void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_override, uint32 duration_override, bool followme) { - - AA_SwarmPet pet; - pet.count = 1; - pet.duration = 1; - - pet.npc_id = typesid; - - NPCType *made_npc = nullptr; - - const NPCType *npc_type = database.GetNPCType(typesid); - if(npc_type == nullptr) { - //log write - LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet type id: %d", typesid); - Message(0,"Unable to find pet!"); - return; - } - - if(name_override != nullptr) { - //we have to make a custom NPC type for this name change - made_npc = new NPCType; - memcpy(made_npc, npc_type, sizeof(NPCType)); - strcpy(made_npc->name, name_override); - npc_type = made_npc; - } - - int summon_count = 0; - summon_count = pet.count; - - if(summon_count > MAX_SWARM_PETS) - summon_count = MAX_SWARM_PETS; - - static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, - 10, -10, 10, -10, - 8, -8, 8, -8 }; - static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, - 10, 10, -10, -10, - 8, 8, -8, -8 }; - TempPets(true); - - while(summon_count > 0) { - int pet_duration = pet.duration; - if(duration_override > 0) - pet_duration = duration_override; - - //this is a little messy, but the only way to do it right - //it would be possible to optimize out this copy for the last pet, but oh well - NPCType *npc_dup = nullptr; - if(made_npc != nullptr) { - npc_dup = new NPCType; - memcpy(npc_dup, made_npc, sizeof(NPCType)); - } - - NPC* npca = new NPC( - (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer - 0, - GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], - GetZ(), GetHeading(), FlyMode3); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); - } - - //removing this prevents the pet from attacking - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pets somebody to "love" - if(targ != nullptr){ - npca->AddToHateList(targ, 1000, 1000); - npca->GetSwarmInfo()->target = targ->GetID(); - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); - - entity_list.AddNPC(npca, true, true); - summon_count--; - } -} - -void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) -{ - Corpse *CorpseToUse = nullptr; - CorpseToUse = entity_list.GetClosestCorpse(this, nullptr); - - if(!CorpseToUse) - return; - - //assuming we have pets in our table; we take the first pet as a base type. - const NPCType *base_type = database.GetNPCType(500); - NPCType *make_npc = new NPCType; - memcpy(make_npc, base_type, sizeof(NPCType)); - - //combat stats - make_npc->AC = ((GetLevel() * 7) + 550); - make_npc->ATK = GetLevel(); - make_npc->max_dmg = (GetLevel() * 4) + 2; - make_npc->min_dmg = 1; - - //base stats - make_npc->cur_hp = (GetLevel() * 55); - make_npc->max_hp = (GetLevel() * 55); - make_npc->STR = 85 + (GetLevel() * 3); - make_npc->STA = 85 + (GetLevel() * 3); - make_npc->DEX = 85 + (GetLevel() * 3); - make_npc->AGI = 85 + (GetLevel() * 3); - make_npc->INT = 85 + (GetLevel() * 3); - make_npc->WIS = 85 + (GetLevel() * 3); - make_npc->CHA = 85 + (GetLevel() * 3); - make_npc->MR = 25; - make_npc->FR = 25; - make_npc->CR = 25; - make_npc->DR = 25; - make_npc->PR = 25; - - //level class and gender - make_npc->level = GetLevel(); - make_npc->class_ = CorpseToUse->class_; - make_npc->race = CorpseToUse->race; - make_npc->gender = CorpseToUse->gender; - make_npc->loottable_id = 0; - //name - char NewName[64]; - sprintf(NewName, "%s`s Animated Corpse", GetCleanName()); - strcpy(make_npc->name, NewName); - - //appearance - make_npc->beard = CorpseToUse->beard; - make_npc->beardcolor = CorpseToUse->beardcolor; - make_npc->eyecolor1 = CorpseToUse->eyecolor1; - make_npc->eyecolor2 = CorpseToUse->eyecolor2; - make_npc->haircolor = CorpseToUse->haircolor; - make_npc->hairstyle = CorpseToUse->hairstyle; - make_npc->helmtexture = CorpseToUse->helmtexture; - make_npc->luclinface = CorpseToUse->luclinface; - make_npc->size = CorpseToUse->size; - make_npc->texture = CorpseToUse->texture; - - //cast stuff.. based off of PEQ's if you want to change - //it you'll have to mod this code, but most likely - //most people will be using PEQ style for the first - //part of their spell list; can't think of any smooth - //way to do this - //some basic combat mods here too since it's convienent - switch(CorpseToUse->class_) - { - case CLERIC: - make_npc->npc_spells_id = 1; - break; - case WIZARD: - make_npc->npc_spells_id = 2; - break; - case NECROMANCER: - make_npc->npc_spells_id = 3; - break; - case MAGICIAN: - make_npc->npc_spells_id = 4; - break; - case ENCHANTER: - make_npc->npc_spells_id = 5; - break; - case SHAMAN: - make_npc->npc_spells_id = 6; - break; - case DRUID: - make_npc->npc_spells_id = 7; - break; - case PALADIN: - //SPECATK_TRIPLE - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 150 / 100; - make_npc->max_hp = make_npc->max_hp * 150 / 100; - make_npc->npc_spells_id = 8; - break; - case SHADOWKNIGHT: - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 150 / 100; - make_npc->max_hp = make_npc->max_hp * 150 / 100; - make_npc->npc_spells_id = 9; - break; - case RANGER: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->cur_hp = make_npc->cur_hp * 135 / 100; - make_npc->max_hp = make_npc->max_hp * 135 / 100; - make_npc->npc_spells_id = 10; - break; - case BARD: - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - make_npc->npc_spells_id = 11; - break; - case BEASTLORD: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - make_npc->npc_spells_id = 12; - break; - case ROGUE: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - break; - case MONK: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 135 / 100; - make_npc->max_hp = make_npc->max_hp * 135 / 100; - break; - case WARRIOR: - case BERSERKER: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 175 / 100; - make_npc->max_hp = make_npc->max_hp * 175 / 100; - break; - default: - make_npc->npc_spells_id = 0; - break; - } - - make_npc->loottable_id = 0; - make_npc->merchanttype = 0; - make_npc->d_meele_texture1 = 0; - make_npc->d_meele_texture2 = 0; - - TempPets(true); - - NPC* npca = new NPC(make_npc, 0, GetX(), GetY(), GetZ(), GetHeading(), FlyMode3); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(duration*1000); - } - - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pet somebody to "love" - if(target != nullptr){ - npca->AddToHateList(target, 100000); - npca->GetSwarmInfo()->target = target->GetID(); - } - - //gear stuff, need to make sure there's - //no situation where this stuff can be duped - for(int x = 0; x < 21; x++) - { - uint32 sitem = 0; - sitem = CorpseToUse->GetWornItem(x); - if(sitem){ - const Item_Struct * itm = database.GetItem(sitem); - npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 127, true, true); - } - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(make_npc != nullptr) - npca->GiveNPCTypeData(make_npc); - - entity_list.AddNPC(npca, true, true); - - //the target of these swarm pets will take offense to being cast on... - if(target != nullptr) - target->AddToHateList(this, 1, 0); -} - -//turn on an AA effect -//duration == 0 means no time limit, used for one-shot deals, etc.. -void Client::EnableAAEffect(aaEffectType type, uint32 duration) { - if(type > 32) - return; //for now, special logic needed. - m_epp.aa_effects |= 1 << (type-1); - - if(duration > 0) { - p_timers.Start(pTimerAAEffectStart + type, duration); - } else { - p_timers.Clear(&database, pTimerAAEffectStart + type); - } -} - -void Client::DisableAAEffect(aaEffectType type) { - if(type > 32) - return; //for now, special logic needed. - uint32 bit = 1 << (type-1); - if(m_epp.aa_effects & bit) { - m_epp.aa_effects ^= bit; - } - p_timers.Clear(&database, pTimerAAEffectStart + type); -} - -/* -By default an AA effect is a one shot deal, unless -a duration timer is set. -*/ -bool Client::CheckAAEffect(aaEffectType type) { - if(type > 32) - return(false); //for now, special logic needed. - if(m_epp.aa_effects & (1 << (type-1))) { //is effect enabled? - //has our timer expired? - if(p_timers.Expired(&database, pTimerAAEffectStart + type)) { - DisableAAEffect(type); - return(false); - } - return(true); - } - return(false); -} - -void Client::SendAAStats() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); - AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer; - aps->experience = m_pp.expAA; - aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP); - aps->unspent = m_pp.aapoints; - aps->percentage = m_epp.perAA; - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::BuyAA(AA_Action* action) -{ - mlog(AA__MESSAGE, "Starting to buy AA %d", action->ability); - - //find the AA information from the database - SendAA_Struct* aa2 = zone->FindAA(action->ability); - if(!aa2) { - //hunt for a lower level... - int i; - int a; - for(i=1;iability - i; - if(a <= 0) - break; - mlog(AA__MESSAGE, "Could not find AA %d, trying potential parent %d", action->ability, a); - aa2 = zone->FindAA(a); - if(aa2 != nullptr) - break; - } - } - if(aa2 == nullptr) - return; //invalid ability... - - if(aa2->special_category == 1 || aa2->special_category == 2) - return; // Not purchasable progression style AAs - - if(aa2->special_category == 8 && aa2->cost == 0) - return; // Not purchasable racial AAs(set a cost to make them purchasable) - - uint32 cur_level = GetAA(aa2->id); - if((aa2->id + cur_level) != action->ability) { //got invalid AA - mlog(AA__ERROR, "Unable to find or match AA %d (found %d + lvl %d)", action->ability, aa2->id, cur_level); - return; - } - - if(aa2->account_time_required) - { - if((Timer::GetTimeSeconds() - account_creation) < aa2->account_time_required) - { - return; - } - } - - uint32 real_cost; - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); - - if(RequiredLevel != AARequiredLevelAndCost.end()) - { - real_cost = RequiredLevel->second.Cost; - } - else - real_cost = aa2->cost + (aa2->cost_inc * cur_level); - - if(m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { - SetAA(aa2->id, cur_level+1); - - mlog(AA__MESSAGE, "Set AA %d to level %d", aa2->id, cur_level+1); - - m_pp.aapoints -= real_cost; - - Save(); - if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u)) - && ((aa2->max_level == (cur_level+1)) && aa2->sof_next_id)){ - SendAA(aa2->id); - SendAA(aa2->sof_next_id); - } - else - SendAA(aa2->id); - - SendAATable(); - - //we are building these messages ourself instead of using the stringID to work around patch discrepencies - //these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2 - if(cur_level<1) - Message(15,"You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1)?"points":"point"); - else - Message(15,"You have improved %s %d at a cost of %d ability %s.", aa2->name, cur_level+1, real_cost, (real_cost>1)?"points":"point"); - - - SendAAStats(); - - CalcBonuses(); - if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) - NotifyNewTitlesAvailable(); - } -} - -void Client::SendAATimer(uint32 ability, uint32 begin, uint32 end) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); - UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; - uaaout->ability = ability; - uaaout->begin = begin; - uaaout->end = end; - QueuePacket(outapp); - safe_delete(outapp); -} - -//sends all AA timers. -void Client::SendAATimers() { - //we dont use SendAATimer because theres no reason to allocate the EQApplicationPacket every time - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); - UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; - - PTimerList::iterator c,e; - c = p_timers.begin(); - e = p_timers.end(); - for(; c != e; ++c) { - PersistentTimer *cur = c->second; - if(cur->GetType() < pTimerAAStart || cur->GetType() > pTimerAAEnd) - continue; //not an AA timer - //send timer - uaaout->begin = cur->GetStartTime(); - uaaout->end = static_cast(time(nullptr)); - uaaout->ability = cur->GetType() - pTimerAAStart; // uuaaout->ability is really a shared timer number - QueuePacket(outapp); - } - - safe_delete(outapp); -} - -void Client::SendAATable() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); - - AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; - aa2->aa_spent = GetAAPointsSpent(); - - uint32 i; - for(i=0;i < MAX_PP_AA_ARRAY;i++){ - aa2->aa_list[i].aa_skill = aa[i]->AA; - aa2->aa_list[i].aa_value = aa[i]->value; - aa2->aa_list[i].unknown08 = 0; - } - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendPreviousAA(uint32 id, int seq){ - uint32 value=0; - SendAA_Struct* saa2 = nullptr; - if(id==0) - saa2 = zone->GetAABySequence(seq); - else - saa2 = zone->FindAA(id); - if(!saa2) - return; - int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; - uchar* buffer = new uchar[size]; - SendAA_Struct* saa=(SendAA_Struct*)buffer; - value = GetAA(saa2->id); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); - outapp->size=size; - outapp->pBuffer=(uchar*)saa; - value--; - memcpy(saa,saa2,size); - - if(value>0){ - if(saa->spellid==0) - saa->spellid=0xFFFFFFFF; - saa->id+=value; - saa->next_id=saa->id+1; - if(value==1) - saa->last_id=saa2->id; - else - saa->last_id=saa->id-1; - saa->current_level=value+1; - saa->cost2 = 0; //cost 2 is what the client uses to calc how many points we've spent, so we have to add up the points in order - for(uint32 i = 0; i < (value+1); i++) { - saa->cost2 += saa->cost + (saa->cost_inc * i); - } - } - - database.FillAAEffects(saa); - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendAA(uint32 id, int seq) { - - uint32 value=0; - SendAA_Struct* saa2 = nullptr; - SendAA_Struct* qaa = nullptr; - SendAA_Struct* saa_pp = nullptr; - bool IsBaseLevel = true; - bool aa_stack = false; - - if(id==0) - saa2 = zone->GetAABySequence(seq); - else - saa2 = zone->FindAA(id); - if(!saa2) - return; - - uint16 classes = saa2->classes; - if(!(classes & (1 << GetClass())) && (GetClass()!=BERSERKER || saa2->berserker==0)){ - return; - } - - if(saa2->account_time_required) - { - if((Timer::GetTimeSeconds() - account_creation) < saa2->account_time_required) - { - return; - } - } - - // Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). - if (saa2->special_category == 1 || saa2->special_category == 2 ) { - if(GetAA(saa2->id) == 0) - return; - // For Quest line AA(demiplane AEs) where only 1 is visible at a time, check to make sure only the highest level obtained is shown - if(saa2->aa_expansion > 0) { - qaa = zone->FindAA(saa2->id+1); - if(qaa && (saa2->aa_expansion == qaa->aa_expansion) && GetAA(qaa->id) > 0) - return; - } - } - -/* Beginning of Shroud AAs, these categories are for Passive and Active Shroud AAs - Eventually with a toggle we could have it show player list or shroud list - if (saa2->special_category == 3 || saa2->special_category == 4) - return; -*/ - // Check for racial/Drakkin blood line AAs - if (saa2->special_category == 8) - { - uint32 client_race = this->GetBaseRace(); - - // Drakkin Bloodlines - if (saa2->aa_expansion > 522) - { - if (client_race != 522) - return; // Check for Drakkin Race - - int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline - - if (heritage != saa2->aa_expansion) - return; - } - // Racial AAs - else if (client_race != saa2->aa_expansion) - { - return; - } - } - - /* - AA stacking on SoF+ clients. - - Note: There were many ways to achieve this effect - The method used proved to be the most straight forward and consistent. - Stacking does not currently work ideally for AA's that use hotkeys, therefore they will be excluded at this time. - - TODO: Problem with AA hotkeys - When you reach max rank of an AA tier (ie 5/5), it automatically displays the next AA in - the series and you can not transfer the hotkey to the next AA series. To the best of the my ability and through many - different variations of coding I could not find an ideal solution to this issue. - - How stacking works: - Utilizes two new fields: sof_next_id (which is the next id in the series), sof_current_level (ranks the AA's as the current level) - 1) If no AA's purchased only display the base levels of each AA series. - 2) When you purchase an AA and its rank is maxed it sends the packet for the completed AA, and the packet - for the next aa in the series. The previous tier is removed from your window, and the new AA is displayed. - 3) When you zone/buy your player profile will be checked and determine what AA can be displayed base on what you have already. - */ - - if (RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (saa2->hotkey_sid == 4294967295u)) - aa_stack = true; - - if (aa_stack){ - uint32 aa_AA = 0; - uint32 aa_value = 0; - for (int i = 0; i < MAX_PP_AA_ARRAY; i++) { - if (aa[i]) { - aa_AA = aa[i]->AA; - aa_value = aa[i]->value; - - if (aa_AA){ - - if (aa_value > 0) - aa_AA -= aa_value-1; - - saa_pp = zone->FindAA(aa_AA); - - if (saa_pp){ - - if (saa_pp->sof_next_skill == saa2->sof_next_skill){ - - if (saa_pp->id == saa2->id) - break; //You already have this in the player profile. - else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value < saa_pp->max_level)) - return; //DISABLE DISPLAY HIGHER - You have not reached max level yet of your current AA. - else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value == saa_pp->max_level) && (saa_pp->sof_next_id == saa2->id)) - IsBaseLevel = false; //ALLOW DISPLAY HIGHER - } - } - } - } - } - } - - //Hide higher tiers of multi tiered AA's if the base level is not fully purchased. - if (aa_stack && IsBaseLevel && saa2->sof_current_level > 0) - return; - - int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; - - if(size == 0) - return; - - uchar* buffer = new uchar[size]; - SendAA_Struct* saa=(SendAA_Struct*)buffer; - memcpy(saa,saa2,size); - - if(saa->spellid==0) - saa->spellid=0xFFFFFFFF; - - value=GetAA(saa->id); - uint32 orig_val = value; - - if(value && saa->id){ - - if(value < saa->max_level){ - saa->id+=value; - saa->next_id=saa->id+1; - value++; - } - - else if (aa_stack && saa->sof_next_id){ - saa->id+=value-1; - saa->next_id=saa->sof_next_id; - - //Prevent removal of previous AA from window if next AA belongs to a higher client version. - SendAA_Struct* saa_next = nullptr; - saa_next = zone->FindAA(saa->sof_next_id); - if (saa_next && - (((GetClientVersionBit() == 4) && (saa_next->clientver > 4)) - || ((GetClientVersionBit() == 8) && (saa_next->clientver > 5)) - || ((GetClientVersionBit() == 16) && (saa_next->clientver > 6)))){ - saa->next_id=0xFFFFFFFF; - } - } - - else{ - saa->id+=value-1; - saa->next_id=0xFFFFFFFF; - } - - uint32 current_level_mod = 0; - if (aa_stack) - current_level_mod = saa->sof_current_level; - - saa->last_id=saa->id-1; - saa->current_level=value+(current_level_mod); - saa->cost = saa2->cost + (saa2->cost_inc*(value-1)); - saa->cost2 = 0; - for(uint32 i = 0; i < value; i++) { - saa->cost2 += saa2->cost + (saa2->cost_inc * i); - } - saa->class_type = saa2->class_type + (saa2->level_inc*(value-1)); - } - - if (aa_stack){ - - if (saa->sof_current_level >= 1 && value == 0) - saa->current_level = saa->sof_current_level+1; - - saa->max_level = saa->sof_max_level; - } - - database.FillAAEffects(saa); - - if(value > 0) - { - // AA_Action stores the base ID - const AA_DBAction *caa = &AA_Actions[saa->id - value + 1][value - 1]; - - if(caa && caa->reuse_time > 0) - saa->spell_refresh = CalcAAReuseTimer(caa); - } - - //You can now use the level_inc field in the altadv_vars table to accomplish this, though still needed - //for special cases like LOH/HT due to inability to implement correct stacking of AA's that use hotkeys. - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(saa->id); - - if(RequiredLevel != AARequiredLevelAndCost.end()) - { - saa->class_type = RequiredLevel->second.Level; - saa->cost = RequiredLevel->second.Cost; - } - - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); - outapp->size=size; - outapp->pBuffer=(uchar*)saa; - if(id==0 && value && (orig_val < saa->max_level)) //send previous AA only on zone in - SendPreviousAA(id, seq); - - QueuePacket(outapp); - safe_delete(outapp); - //will outapp delete the buffer for us even though it didnt make it? --- Yes, it should -} - -void Client::SendAAList(){ - int total = zone->GetTotalAAs(); - for(int i=0;i < total;i++){ - SendAA(0,i); - } -} - -uint32 Client::GetAA(uint32 aa_id) const { - std::map::const_iterator res; - res = aa_points.find(aa_id); - if(res != aa_points.end()) { - return(res->second); - } - return(0); -} - -bool Client::SetAA(uint32 aa_id, uint32 new_value) { - aa_points[aa_id] = new_value; - uint32 cur; - for(cur=0;cur < MAX_PP_AA_ARRAY;cur++){ - if((aa[cur]->value > 1) && ((aa[cur]->AA - aa[cur]->value + 1)== aa_id)){ - aa[cur]->value = new_value; - if(new_value > 0) - aa[cur]->AA++; - else - aa[cur]->AA = 0; - return true; - } - else if((aa[cur]->value == 1) && (aa[cur]->AA == aa_id)){ - aa[cur]->value = new_value; - if(new_value > 0) - aa[cur]->AA++; - else - aa[cur]->AA = 0; - return true; - } - else if(aa[cur]->AA==0){ //end of list - aa[cur]->AA = aa_id; - aa[cur]->value = new_value; - return true; - } - } - return false; -} - -SendAA_Struct* Zone::FindAA(uint32 id) { - return aas_send[id]; -} - -void Zone::LoadAAs() { - LogFile->write(EQEMuLog::Status, "Loading AA information..."); - totalAAs = database.CountAAs(); - if(totalAAs == 0) { - LogFile->write(EQEMuLog::Error, "Failed to load AAs!"); - aas = nullptr; - return; - } - aas = new SendAA_Struct *[totalAAs]; - - database.LoadAAs(aas); - - int i; - for(i=0; i < totalAAs; i++){ - SendAA_Struct* aa = aas[i]; - aas_send[aa->id] = aa; - } - - //load AA Effects into aa_effects - LogFile->write(EQEMuLog::Status, "Loading AA Effects..."); - if (database.LoadAAEffects2()) - LogFile->write(EQEMuLog::Status, "Loaded %d AA Effects.", aa_effects.size()); - else - LogFile->write(EQEMuLog::Error, "Failed to load AA Effects!"); -} - -bool ZoneDatabase::LoadAAEffects2() { - aa_effects.clear(); //start fresh - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT aaid, slot, effectid, base1, base2 FROM aa_effects ORDER BY aaid ASC, slot ASC"), errbuf, &result)) { - int count = 0; - while((row = mysql_fetch_row(result))!= nullptr) { - int aaid = atoi(row[0]); - int slot = atoi(row[1]); - int effectid = atoi(row[2]); - int base1 = atoi(row[3]); - int base2 = atoi(row[4]); - aa_effects[aaid][slot].skill_id = effectid; - aa_effects[aaid][slot].base1 = base1; - aa_effects[aaid][slot].base2 = base2; - aa_effects[aaid][slot].slot = slot; //not really needed, but we'll populate it just in case - count++; - } - mysql_free_result(result); - if (count < 1) //no results - LogFile->write(EQEMuLog::Error, "Error loading AA Effects, none found in the database."); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAEffects2 query: '%s': %s", query, errbuf); - return false; - } - safe_delete_array(query); - return true; -} -void Client::ResetAA(){ - uint32 i; - for(i=0;iAA = 0; - aa[i]->value = 0; - } - std::map::iterator itr; - for(itr=aa_points.begin();itr!=aa_points.end();++itr) - aa_points[itr->first] = 0; - - for(int i = 0; i < _maxLeaderAA; ++i) - m_pp.leader_abilities.ranks[i] = 0; - - m_pp.group_leadership_points = 0; - m_pp.raid_leadership_points = 0; - m_pp.group_leadership_exp = 0; - m_pp.raid_leadership_exp = 0; -} - -int Client::GroupLeadershipAAHealthEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAHealthEnhancement)) - { - case 0: - return 0; - case 1: - return 30; - case 2: - return 60; - case 3: - return 100; - } - - return 0; -} - -int Client::GroupLeadershipAAManaEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAManaEnhancement)) - { - case 0: - return 0; - case 1: - return 30; - case 2: - return 60; - case 3: - return 100; - } - - return 0; -} - -int Client::GroupLeadershipAAHealthRegeneration() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAHealthRegeneration)) - { - case 0: - return 0; - case 1: - return 4; - case 2: - return 6; - case 3: - return 8; - } - - return 0; -} - -int Client::GroupLeadershipAAOffenseEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAOffenseEnhancement)) - { - case 0: - return 0; - case 1: - return 10; - case 2: - return 19; - case 3: - return 28; - case 4: - return 34; - case 5: - return 40; - } - return 0; -} - -void Client::InspectBuffs(Client* Inspector, int Rank) -{ - if(!Inspector || (Rank == 0)) return; - - Inspector->Message_StringID(0, CURRENT_SPELL_EFFECTS, GetName()); - uint32 buff_count = GetMaxTotalSlots(); - for (uint32 i = 0; i < buff_count; ++i) - { - if (buffs[i].spellid != SPELL_UNKNOWN) - { - if(Rank == 1) - Inspector->Message(0, "%s", spells[buffs[i].spellid].name); - else - { - if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) - Inspector->Message(0, "%s (Permanent)", spells[buffs[i].spellid].name); - else { - char *TempString = nullptr; - MakeAnyLenString(&TempString, "%.1f", static_cast(buffs[i].ticsremaining) / 10.0f); - Inspector->Message_StringID(0, BUFF_MINUTES_REMAINING, spells[buffs[i].spellid].name, TempString); - safe_delete_array(TempString); - } - } - } - } -} - -//this really need to be renamed to LoadAAActions() -bool ZoneDatabase::LoadAAEffects() { - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - memset(AA_Actions, 0, sizeof(AA_Actions)); //I hope the compiler is smart about this size... - - const char *query = "SELECT aaid,rank,reuse_time,spell_id,target,nonspell_action,nonspell_mana,nonspell_duration," - "redux_aa,redux_rate,redux_aa2,redux_rate2 FROM aa_actions"; - - if(RunQuery(query, static_cast(strlen(query)), errbuf, &result)) { - //safe_delete_array(query); - int r; - while ((row = mysql_fetch_row(result))) { - r = 0; - int aaid = atoi(row[r++]); - int rank = atoi(row[r++]); - if(aaid < 0 || aaid >= aaHighestID || rank < 0 || rank >= MAX_AA_ACTION_RANKS) - continue; - AA_DBAction *caction = &AA_Actions[aaid][rank]; - - caction->reuse_time = atoi(row[r++]); - caction->spell_id = atoi(row[r++]); - caction->target = (aaTargetType) atoi(row[r++]); - caction->action = (aaNonspellAction) atoi(row[r++]); - caction->mana_cost = atoi(row[r++]); - caction->duration = atoi(row[r++]); - caction->redux_aa = (aaID) atoi(row[r++]); - caction->redux_rate = atoi(row[r++]); - caction->redux_aa2 = (aaID) atoi(row[r++]); - caction->redux_rate2 = atoi(row[r++]); - - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in LoadAAEffects query '%s': %s", query, errbuf);; - //safe_delete_array(query); - return false; - } - - return true; -} - -//Returns the number effects an AA has when we send them to the client -//For the purposes of sizing a packet because every skill does not -//have the same number effects, they can range from none to a few depending on AA. -//counts the # of effects by counting the different slots of an AAID in the DB. - -//AndMetal: this may now be obsolete since we have Zone::GetTotalAALevels() -uint8 ZoneDatabase::GetTotalAALevels(uint32 skill_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int total=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(slot) from aa_effects where aaid=%i", skill_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - total=atoi(row[0]); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in GetTotalAALevels '%s: %s", query, errbuf); - safe_delete_array(query); - } - return total; -} - -//this will allow us to count the number of effects for an AA by pulling the info from memory instead of the database. hopefully this will same some CPU cycles -uint8 Zone::GetTotalAALevels(uint32 skill_id) { - size_t sz = aa_effects[skill_id].size(); - return sz >= 255 ? 255 : static_cast(sz); -} - -/* -Every AA can send the client effects, which are purely for client side effects. -Essentially it's like being able to attach a very simple version of a spell to -Any given AA, it has 4 fields: -skill_id = spell effect id -slot = ID slot, doesn't appear to have any impact on stacking like real spells, just needs to be unique. -base1 = the base field of a spell -base2 = base field 2 of a spell, most AAs do not utilize this -example: - skill_id = SE_STA - slot = 1 - base1 = 15 - This would if you filled the abilities struct with this make the client show if it had - that AA an additional 15 stamina on the client's stats -*/ -void ZoneDatabase::FillAAEffects(SendAA_Struct* aa_struct){ - if(!aa_struct) - return; - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT effectid, base1, base2, slot from aa_effects where aaid=%i order by slot asc", aa_struct->id), errbuf, &result)) { - int ndx=0; - while((row = mysql_fetch_row(result))!=nullptr) { - aa_struct->abilities[ndx].skill_id=atoi(row[0]); - aa_struct->abilities[ndx].base1=atoi(row[1]); - aa_struct->abilities[ndx].base2=atoi(row[2]); - aa_struct->abilities[ndx].slot=atoi(row[3]); - ndx++; - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in Client::FillAAEffects query: '%s': %s", query, errbuf); - } - safe_delete_array(query); -} - -uint32 ZoneDatabase::CountAAs(){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int count=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(title_sid) from altadv_vars"), errbuf, &result)) { - if((row = mysql_fetch_row(result))!=nullptr) - count = atoi(row[0]); - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAAs query '%s': %s", query, errbuf); - } - safe_delete_array(query); - return count; -} - -uint32 ZoneDatabase::CountAAEffects(){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int count=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(id) from aa_effects"), errbuf, &result)) { - if((row = mysql_fetch_row(result))!=nullptr){ - count = atoi(row[0]); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAALevels query '%s': %s", query, errbuf); - } - safe_delete_array(query); - return count; -} - -uint32 ZoneDatabase::GetSizeAA(){ - int size=CountAAs()*sizeof(SendAA_Struct); - if(size>0) - size+=CountAAEffects()*sizeof(AA_Ability); - return size; -} - -void ZoneDatabase::LoadAAs(SendAA_Struct **load){ - if(!load) - return; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id from altadv_vars order by skill_id"), errbuf, &result)) { - int skill=0,ndx=0; - while((row = mysql_fetch_row(result))!=nullptr) { - skill=atoi(row[0]); - load[ndx] = GetAASkillVars(skill); - load[ndx]->seq = ndx+1; - ndx++; - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); - } - safe_delete_array(query); - - AARequiredLevelAndCost.clear(); - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id, level, cost from aa_required_level_cost order by skill_id"), errbuf, &result)) - { - AALevelCost_Struct aalcs; - while((row = mysql_fetch_row(result))!=nullptr) - { - aalcs.Level = atoi(row[1]); - aalcs.Cost = atoi(row[2]); - AARequiredLevelAndCost[atoi(row[0])] = aalcs; - } - mysql_free_result(result); - } - else - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); - - safe_delete_array(query); -} - -SendAA_Struct* ZoneDatabase::GetAASkillVars(uint32 skill_id) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - SendAA_Struct* sendaa = nullptr; - uchar* buffer; - if (RunQuery(query, MakeAnyLenString(&query, "SET @row = 0"), errbuf)) { //initialize "row" variable in database for next query - safe_delete_array(query); - MYSQL_RES *result; //we don't really need these unless we get to this point, so why bother? - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, - "SELECT " - "a.cost, " - "a.max_level, " - "a.hotkey_sid, " - "a.hotkey_sid2, " - "a.title_sid, " - "a.desc_sid, " - "a.type, " - "COALESCE(" //so we can return 0 if it's null - "(" //this is our derived table that has the row # that we can SELECT from, because the client is stupid - "SELECT " - "p.prereq_index_num " - "FROM " - "(" - "SELECT " - "a2.skill_id, " - "@row := @row + 1 AS prereq_index_num " - "FROM " - "altadv_vars a2" - ") AS p " - "WHERE " - "p.skill_id = a.prereq_skill" - "), " - "0) AS prereq_skill_index, " - "a.prereq_minpoints, " - "a.spell_type, " - "a.spell_refresh, " - "a.classes, " - "a.berserker, " - "a.spellid, " - "a.class_type, " - "a.name, " - "a.cost_inc, " - "a.aa_expansion, " - "a.special_category, " - "a.sof_type, " - "a.sof_cost_inc, " - "a.sof_max_level, " - "a.sof_next_skill, " - "a.clientver, " // Client Version 0 = None, 1 = All, 2 = Titanium/6.2, 4 = SoF 5 = SOD 6 = UF - "a.account_time_required, " - "a.sof_current_level," - "a.sof_next_id, " - "a.level_inc " - " FROM altadv_vars a WHERE skill_id=%i", skill_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - int total_abilities = GetTotalAALevels(skill_id); //eventually we'll want to use zone->GetTotalAALevels(skill_id) since it should save queries to the DB - int totalsize = total_abilities * sizeof(AA_Ability) + sizeof(SendAA_Struct); - - buffer = new uchar[totalsize]; - memset(buffer,0,totalsize); - sendaa = (SendAA_Struct*)buffer; - - row = mysql_fetch_row(result); - - //ATOI IS NOT UNISGNED LONG-SAFE!!! - - sendaa->cost = atoul(row[0]); - sendaa->cost2 = sendaa->cost; - sendaa->max_level = atoul(row[1]); - sendaa->hotkey_sid = atoul(row[2]); - sendaa->id = skill_id; - sendaa->hotkey_sid2 = atoul(row[3]); - sendaa->title_sid = atoul(row[4]); - sendaa->desc_sid = atoul(row[5]); - sendaa->type = atoul(row[6]); - sendaa->prereq_skill = atoul(row[7]); - sendaa->prereq_minpoints = atoul(row[8]); - sendaa->spell_type = atoul(row[9]); - sendaa->spell_refresh = atoul(row[10]); - sendaa->classes = static_cast(atoul(row[11])); - sendaa->berserker = static_cast(atoul(row[12])); - sendaa->last_id = 0xFFFFFFFF; - sendaa->current_level=1; - sendaa->spellid = atoul(row[13]); - sendaa->class_type = atoul(row[14]); - strcpy(sendaa->name,row[15]); - - sendaa->total_abilities=total_abilities; - if(sendaa->max_level > 1) - sendaa->next_id=skill_id+1; - else - sendaa->next_id=0xFFFFFFFF; - - sendaa->cost_inc = atoi(row[16]); - // Begin SoF Specific/Adjusted AA Fields - sendaa->aa_expansion = atoul(row[17]); - sendaa->special_category = atoul(row[18]); - sendaa->sof_type = atoul(row[19]); - sendaa->sof_cost_inc = atoi(row[20]); - sendaa->sof_max_level = atoul(row[21]); - sendaa->sof_next_skill = atoul(row[22]); - sendaa->clientver = atoul(row[23]); - sendaa->account_time_required = atoul(row[24]); - //Internal use only - not sent to client - sendaa->sof_current_level = atoul(row[25]); - sendaa->sof_next_id = atoul(row[26]); - sendaa->level_inc = static_cast(atoul(row[27])); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); - safe_delete_array(query); - } - } else { - LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); - safe_delete_array(query); - } - return sendaa; -} - -void Client::DurationRampage(uint32 duration) -{ - if(duration) { - m_epp.aa_effects |= 1 << (aaEffectRampage-1); - p_timers.Start(pTimerAAEffectStart + aaEffectRampage, duration); - } -} - -AA_SwarmPetInfo::AA_SwarmPetInfo() -{ - target = 0; - owner_id = 0; - duration = nullptr; -} - -AA_SwarmPetInfo::~AA_SwarmPetInfo() -{ - target = 0; - owner_id = 0; - safe_delete(duration); -} - -Mob *AA_SwarmPetInfo::GetOwner() -{ - return entity_list.GetMobID(owner_id); -} diff --git a/zone/AA_v1.cpp b/zone/AA_v1.cpp deleted file mode 100644 index fb1413927..000000000 --- a/zone/AA_v1.cpp +++ /dev/null @@ -1,2032 +0,0 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -// Test 1 - -#include "../common/debug.h" -#include "AA.h" -#include "mob.h" -#include "client.h" -#include "groups.h" -#include "raids.h" -#include "../common/spdat.h" -#include "object.h" -#include "doors.h" -#include "beacon.h" -#include "corpse.h" -#include "titles.h" -#include "../common/races.h" -#include "../common/classes.h" -#include "../common/eq_packet_structs.h" -#include "../common/packet_dump.h" -#include "../common/StringUtil.h" -#include "../common/logsys.h" -#include "zonedb.h" -#include "StringIDs.h" - -//static data arrays, really not big enough to warrant shared mem. -AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank] -std::mapaas_send; -std::map > aa_effects; //stores the effects from the aa_effects table in memory -std::map AARequiredLevelAndCost; - -/* - - -Schema: - -spell_id is spell to cast, SPELL_UNKNOWN == no spell -nonspell_action is action to preform on activation which is not a spell, 0=none -nonspell_mana is mana that the nonspell action consumes -nonspell_duration is a duration which may be used by the nonspell action -redux_aa is the aa which reduces the reuse timer of the skill -redux_rate is the multiplier of redux_aa, as a percentage of total rate (10 == 10% faster) - -CREATE TABLE aa_actions ( - aaid mediumint unsigned not null, - rank tinyint unsigned not null, - reuse_time mediumint unsigned not null, - spell_id mediumint unsigned not null, - target tinyint unsigned not null, - nonspell_action tinyint unsigned not null, - nonspell_mana mediumint unsigned not null, - nonspell_duration mediumint unsigned not null, - redux_aa mediumint unsigned not null, - redux_rate tinyint not null, - - PRIMARY KEY(aaid, rank) -); - -CREATE TABLE aa_swarmpets ( - spell_id mediumint unsigned not null, - count tinyint unsigned not null, - npc_id int not null, - duration mediumint unsigned not null, - PRIMARY KEY(spell_id) -); -*/ - -/* - -Credits for this function: - -FatherNitwit: Structure and mechanism - -Wiz: Initial set of AAs, original function contents - -Branks: Much updated info and a bunch of higher-numbered AAs - -*/ -int Client::GetAATimerID(aaID activate) -{ - SendAA_Struct* aa2 = zone->FindAA(activate); - - if(!aa2) - { - for(int i = 1;i < MAX_AA_ACTION_RANKS; ++i) - { - int a = activate - i; - - if(a <= 0) - break; - - aa2 = zone->FindAA(a); - - if(aa2 != nullptr) - break; - } - } - - if(aa2) - return aa2->spell_type; - - return 0; -} - -int Client::CalcAAReuseTimer(const AA_DBAction *caa) { - - if(!caa) - return 0; - - int ReuseTime = caa->reuse_time; - - if(ReuseTime > 0) - { - int ReductionPercentage; - - if(caa->redux_aa > 0 && caa->redux_aa < aaHighestID) - { - ReductionPercentage = GetAA(caa->redux_aa) * caa->redux_rate; - - if(caa->redux_aa2 > 0 && caa->redux_aa2 < aaHighestID) - ReductionPercentage += (GetAA(caa->redux_aa2) * caa->redux_rate2); - - ReuseTime = caa->reuse_time * (100 - ReductionPercentage) / 100; - } - - } - return ReuseTime; -} - -void Client::ActivateAA(aaID activate){ - if(activate < 0 || activate >= aaHighestID) - return; - if(IsStunned() || IsFeared() || IsMezzed() || IsSilenced() || IsPet() || IsSitting() || GetFeigned()) - return; - - int AATimerID = GetAATimerID(activate); - - SendAA_Struct* aa2 = nullptr; - aaID aaid = activate; - uint8 activate_val = GetAA(activate); - //this wasn't taking into acct multi tiered act talents before... - if(activate_val == 0){ - aa2 = zone->FindAA(activate); - if(!aa2){ - int i; - int a; - for(i=1;iFindAA(a); - if(aa2 != nullptr) - break; - } - } - if(aa2){ - aaid = (aaID) aa2->id; - activate_val = GetAA(aa2->id); - } - } - - if (activate_val == 0){ - return; - } - - if(aa2) - { - if(aa2->account_time_required) - { - if((Timer::GetTimeSeconds() + account_creation) < aa2->account_time_required) - { - return; - } - } - } - - if(!p_timers.Expired(&database, AATimerID + pTimerAAStart)) - { - uint32 aaremain = p_timers.GetRemainingTime(AATimerID + pTimerAAStart); - uint32 aaremain_hr = aaremain / (60 * 60); - uint32 aaremain_min = (aaremain / 60) % 60; - uint32 aaremain_sec = aaremain % 60; - - if(aa2) { - if (aaremain_hr >= 1) //1 hour or more - Message(13, "You can use the ability %s again in %u hour(s) %u minute(s) %u seconds", - aa2->name, aaremain_hr, aaremain_min, aaremain_sec); - else //less than an hour - Message(13, "You can use the ability %s again in %u minute(s) %u seconds", - aa2->name, aaremain_min, aaremain_sec); - } else { - if (aaremain_hr >= 1) //1 hour or more - Message(13, "You can use this ability again in %u hour(s) %u minute(s) %u seconds", - aaremain_hr, aaremain_min, aaremain_sec); - else //less than an hour - Message(13, "You can use this ability again in %u minute(s) %u seconds", - aaremain_min, aaremain_sec); - } - return; - } - - if(activate_val > MAX_AA_ACTION_RANKS) - activate_val = MAX_AA_ACTION_RANKS; - activate_val--; //to get array index. - - //get our current node, now that the indices are well bounded - const AA_DBAction *caa = &AA_Actions[aaid][activate_val]; - - if((aaid == aaImprovedHarmTouch || aaid == aaLeechTouch) && !p_timers.Expired(&database, pTimerHarmTouch)){ - Message(13,"Ability recovery time not yet met."); - return; - } - Shout("spell id %i", caa->spell_id); - //everything should be configured out now - - uint16 target_id = 0; - - //figure out our target - switch(caa->target) { - case aaTargetUser: - case aaTargetGroup: - target_id = GetID(); - break; - case aaTargetCurrent: - case aaTargetCurrentGroup: - if(GetTarget() == nullptr) { - Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - target_id = GetTarget()->GetID(); - break; - case aaTargetPet: - if(GetPet() == nullptr) { - Message(0, "A pet is required for this skill."); - return; - } - target_id = GetPetID(); - break; - } - - //handle non-spell action - if(caa->action != aaActionNone) { - if(caa->mana_cost > 0) { - if(GetMana() < caa->mana_cost) { - Message_StringID(13, INSUFFICIENT_MANA); - return; - } - SetMana(GetMana() - caa->mana_cost); - } - if(caa->reuse_time > 0) - { - uint32 timer_base = CalcAAReuseTimer(caa); - if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) - { - p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); - } - p_timers.Start(AATimerID + pTimerAAStart, timer_base); - SendAATimer(AATimerID, 0, 0); - } - HandleAAAction(aaid); - } - Shout("1 spell id %i", caa->spell_id); - //cast the spell, if we have one - if(caa->spell_id > 0 && caa->spell_id < SPDAT_RECORDS) { - Shout("2 spell id %i", caa->spell_id); - if(caa->reuse_time > 0) - { - uint32 timer_base = CalcAAReuseTimer(caa); - SendAATimer(AATimerID, 0, 0); - p_timers.Start(AATimerID + pTimerAAStart, timer_base); - if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) - { - p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); - } - // Bards can cast instant cast AAs while they are casting another song - if (spells[caa->spell_id].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { - if(!SpellFinished(caa->spell_id, entity_list.GetMob(target_id), 10, -1, -1, spells[caa->spell_id].ResistDiff, false)) { - //Reset on failed cast - SendAATimer(AATimerID, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - } else { - if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { - //Reset on failed cast - SendAATimer(AATimerID, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - } - } - else - { - if(!CastSpell(caa->spell_id, target_id)) - return; - } - } - // Check if AA is expendable - if (aas_send[activate - activate_val]->special_category == 7) - { - // Add the AA cost to the extended profile to track overall total - m_epp.expended_aa += aas_send[activate]->cost; - SetAA(activate, 0); - - Save(); - SendAA(activate); - SendAATable(); - } -} - -void Client::HandleAAAction(aaID activate) { - if(activate < 0 || activate >= aaHighestID) - return; - - uint8 activate_val = GetAA(activate); - - if (activate_val == 0) - return; - - if(activate_val > MAX_AA_ACTION_RANKS) - activate_val = MAX_AA_ACTION_RANKS; - activate_val--; //to get array index. - - //get our current node, now that the indices are well bounded - const AA_DBAction *caa = &AA_Actions[activate][activate_val]; - - uint16 timer_id = 0; - uint16 timer_duration = caa->duration; - aaTargetType target = aaTargetUser; - - uint16 spell_id = SPELL_UNKNOWN; //gets cast at the end if not still unknown - - switch(caa->action) { - case aaActionAETaunt: - entity_list.AETaunt(this); - break; - - case aaActionMassBuff: - EnableAAEffect(aaEffectMassGroupBuff, 3600); - Message_StringID(MT_Disciplines, MGB_STRING); //The next group buff you cast will hit all targets in range. - break; - - case aaActionFlamingArrows: - //toggle it - if(CheckAAEffect(aaEffectFlamingArrows)) - EnableAAEffect(aaEffectFlamingArrows); - else - DisableAAEffect(aaEffectFlamingArrows); - break; - - case aaActionFrostArrows: - if(CheckAAEffect(aaEffectFrostArrows)) - EnableAAEffect(aaEffectFrostArrows); - else - DisableAAEffect(aaEffectFrostArrows); - break; - - case aaActionRampage: - EnableAAEffect(aaEffectRampage, 10); - break; - - case aaActionSharedHealth: - if(CheckAAEffect(aaEffectSharedHealth)) - EnableAAEffect(aaEffectSharedHealth); - else - DisableAAEffect(aaEffectSharedHealth); - break; - - case aaActionCelestialRegen: { - //special because spell_id depends on a different AA - switch (GetAA(aaCelestialRenewal)) { - case 1: - spell_id = 3250; - break; - case 2: - spell_id = 3251; - break; - default: - spell_id = 2740; - break; - } - target = aaTargetCurrent; - break; - } - - case aaActionDireCharm: { - //special because spell_id depends on class - switch (GetClass()) - { - case DRUID: - spell_id = 2760; //2644? - break; - case NECROMANCER: - spell_id = 2759; //2643? - break; - case ENCHANTER: - spell_id = 2761; //2642? - break; - } - target = aaTargetCurrent; - break; - } - - case aaActionImprovedFamiliar: { - //Spell IDs might be wrong... - if (GetAA(aaAllegiantFamiliar)) - spell_id = 3264; //1994? - else - spell_id = 2758; //2155? - break; - } - - case aaActionActOfValor: - if(GetTarget() != nullptr) { - int curhp = GetTarget()->GetHP(); - target = aaTargetCurrent; - GetTarget()->HealDamage(curhp, this); - Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); - } - break; - - case aaActionSuspendedMinion: - if (GetPet()) { - target = aaTargetPet; - switch (GetAA(aaSuspendedMinion)) { - case 1: - spell_id = 3248; - break; - case 2: - spell_id = 3249; - break; - } - //do we really need to cast a spell? - - Message(0,"You call your pet to your side."); - GetPet()->WipeHateList(); - GetPet()->GMMove(GetX(),GetY(),GetZ()); - if (activate_val > 1) - entity_list.ClearFeignAggro(GetPet()); - } else { - Message(0,"You have no pet to call."); - } - break; - - case aaActionProjectIllusion: - EnableAAEffect(aaEffectProjectIllusion, 3600); - Message(10, "The power of your next illusion spell will flow to your grouped target in your place."); - break; - - - case aaActionEscape: - Escape(); - break; - - // Don't think this code is used any longer for Bestial Alignment as the AA has a spell_id and no nonspell_action. - case aaActionBeastialAlignment: - switch(GetBaseRace()) { - case BARBARIAN: - spell_id = AA_Choose3(activate_val, 4521, 4522, 4523); - break; - case TROLL: - spell_id = AA_Choose3(activate_val, 4524, 4525, 4526); - break; - case OGRE: - spell_id = AA_Choose3(activate_val, 4527, 4527, 4529); - break; - case IKSAR: - spell_id = AA_Choose3(activate_val, 4530, 4531, 4532); - break; - case VAHSHIR: - spell_id = AA_Choose3(activate_val, 4533, 4534, 4535); - break; - } - - case aaActionLeechTouch: - target = aaTargetCurrent; - spell_id = SPELL_HARM_TOUCH2; - EnableAAEffect(aaEffectLeechTouch, 1000); - break; - - case aaActionFadingMemories: - // Do nothing since spell effect works correctly, but mana isn't used. - break; - - default: - LogFile->write(EQEMuLog::Error, "Unknown AA nonspell action type %d", caa->action); - return; - } - - - uint16 target_id = 0; - //figure out our target - switch(target) { - case aaTargetUser: - case aaTargetGroup: - target_id = GetID(); - break; - case aaTargetCurrent: - case aaTargetCurrentGroup: - if(GetTarget() == nullptr) { - Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! - p_timers.Clear(&database, timer_id + pTimerAAEffectStart); - return; - } - target_id = GetTarget()->GetID(); - break; - case aaTargetPet: - if(GetPet() == nullptr) { - Message(0, "A pet is required for this skill."); - return; - } - target_id = GetPetID(); - break; - } - - //cast the spell, if we have one - if(IsValidSpell(spell_id)) { - int aatid = GetAATimerID(activate); - if(!CastSpell(spell_id, target_id , 10, -1, -1, 0, -1, pTimerAAStart + aatid , CalcAAReuseTimer(caa), 1)) { - SendAATimer(aatid, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, pTimerAAStart + aatid); - return; - } - } - - //handle the duration timer if we have one. - if(timer_id > 0 && timer_duration > 0) { - p_timers.Start(pTimerAAEffectStart + timer_id, timer_duration); - } -} - - -//Originally written by Branks -//functionality rewritten by Father Nitwit -void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override) { - - //It might not be a bad idea to put these into the database, eventually.. - - //Dook- swarms and wards - - PetRecord record; - if(!database.GetPetEntry(spells[spell_id].teleport_zone, &record)) - { - LogFile->write(EQEMuLog::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id); - Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone); - return; - } - - AA_SwarmPet pet; - pet.count = 1; - pet.duration = 1; - - for(int x = 0; x < 12; x++) - { - if(spells[spell_id].effectid[x] == SE_TemporaryPets) - { - pet.count = spells[spell_id].base[x]; - pet.duration = spells[spell_id].max[x]; - } - } - - if(IsClient()) - pet.duration += (CastToClient()->GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000); - - pet.npc_id = record.npc_type; - - NPCType *made_npc = nullptr; - - const NPCType *npc_type = database.GetNPCType(pet.npc_id); - if(npc_type == nullptr) { - //log write - LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet spell id: %d", spell_id); - Message(0,"Unable to find pet!"); - return; - } - - if(name_override != nullptr) { - //we have to make a custom NPC type for this name change - made_npc = new NPCType; - memcpy(made_npc, npc_type, sizeof(NPCType)); - strcpy(made_npc->name, name_override); - npc_type = made_npc; - } - - int summon_count = 0; - summon_count = pet.count; - - if(summon_count > MAX_SWARM_PETS) - summon_count = MAX_SWARM_PETS; - - static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, - 10, -10, 10, -10, - 8, -8, 8, -8 }; - static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, - 10, 10, -10, -10, - 8, 8, -8, -8 }; - TempPets(true); - - while(summon_count > 0) { - int pet_duration = pet.duration; - if(duration_override > 0) - pet_duration = duration_override; - - //this is a little messy, but the only way to do it right - //it would be possible to optimize out this copy for the last pet, but oh well - NPCType *npc_dup = nullptr; - if(made_npc != nullptr) { - npc_dup = new NPCType; - memcpy(npc_dup, made_npc, sizeof(NPCType)); - } - - NPC* npca = new NPC( - (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer - 0, - GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], - GetZ(), GetHeading(), FlyMode3); - - if((spell_id == 6882) || (spell_id == 6884)) - npca->SetFollowID(GetID()); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); - } - - //removing this prevents the pet from attacking - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pets somebody to "love" - if(targ != nullptr){ - npca->AddToHateList(targ, 1000, 1000); - npca->GetSwarmInfo()->target = targ->GetID(); - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); - - entity_list.AddNPC(npca, true, true); - summon_count--; - } - - //the target of these swarm pets will take offense to being cast on... - if(targ != nullptr) - targ->AddToHateList(this, 1, 0); -} - -void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_override, uint32 duration_override, bool followme) { - - AA_SwarmPet pet; - pet.count = 1; - pet.duration = 1; - - pet.npc_id = typesid; - - NPCType *made_npc = nullptr; - - const NPCType *npc_type = database.GetNPCType(typesid); - if(npc_type == nullptr) { - //log write - LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet type id: %d", typesid); - Message(0,"Unable to find pet!"); - return; - } - - if(name_override != nullptr) { - //we have to make a custom NPC type for this name change - made_npc = new NPCType; - memcpy(made_npc, npc_type, sizeof(NPCType)); - strcpy(made_npc->name, name_override); - npc_type = made_npc; - } - - int summon_count = 0; - summon_count = pet.count; - - if(summon_count > MAX_SWARM_PETS) - summon_count = MAX_SWARM_PETS; - - static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, - 10, -10, 10, -10, - 8, -8, 8, -8 }; - static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, - 10, 10, -10, -10, - 8, 8, -8, -8 }; - TempPets(true); - - while(summon_count > 0) { - int pet_duration = pet.duration; - if(duration_override > 0) - pet_duration = duration_override; - - //this is a little messy, but the only way to do it right - //it would be possible to optimize out this copy for the last pet, but oh well - NPCType *npc_dup = nullptr; - if(made_npc != nullptr) { - npc_dup = new NPCType; - memcpy(npc_dup, made_npc, sizeof(NPCType)); - } - - NPC* npca = new NPC( - (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer - 0, - GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], - GetZ(), GetHeading(), FlyMode3); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); - } - - //removing this prevents the pet from attacking - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pets somebody to "love" - if(targ != nullptr){ - npca->AddToHateList(targ, 1000, 1000); - npca->GetSwarmInfo()->target = targ->GetID(); - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); - - entity_list.AddNPC(npca, true, true); - summon_count--; - } -} - -void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) -{ - Corpse *CorpseToUse = nullptr; - CorpseToUse = entity_list.GetClosestCorpse(this, nullptr); - - if(!CorpseToUse) - return; - - //assuming we have pets in our table; we take the first pet as a base type. - const NPCType *base_type = database.GetNPCType(500); - NPCType *make_npc = new NPCType; - memcpy(make_npc, base_type, sizeof(NPCType)); - - //combat stats - make_npc->AC = ((GetLevel() * 7) + 550); - make_npc->ATK = GetLevel(); - make_npc->max_dmg = (GetLevel() * 4) + 2; - make_npc->min_dmg = 1; - - //base stats - make_npc->cur_hp = (GetLevel() * 55); - make_npc->max_hp = (GetLevel() * 55); - make_npc->STR = 85 + (GetLevel() * 3); - make_npc->STA = 85 + (GetLevel() * 3); - make_npc->DEX = 85 + (GetLevel() * 3); - make_npc->AGI = 85 + (GetLevel() * 3); - make_npc->INT = 85 + (GetLevel() * 3); - make_npc->WIS = 85 + (GetLevel() * 3); - make_npc->CHA = 85 + (GetLevel() * 3); - make_npc->MR = 25; - make_npc->FR = 25; - make_npc->CR = 25; - make_npc->DR = 25; - make_npc->PR = 25; - - //level class and gender - make_npc->level = GetLevel(); - make_npc->class_ = CorpseToUse->class_; - make_npc->race = CorpseToUse->race; - make_npc->gender = CorpseToUse->gender; - make_npc->loottable_id = 0; - //name - char NewName[64]; - sprintf(NewName, "%s`s Animated Corpse", GetCleanName()); - strcpy(make_npc->name, NewName); - - //appearance - make_npc->beard = CorpseToUse->beard; - make_npc->beardcolor = CorpseToUse->beardcolor; - make_npc->eyecolor1 = CorpseToUse->eyecolor1; - make_npc->eyecolor2 = CorpseToUse->eyecolor2; - make_npc->haircolor = CorpseToUse->haircolor; - make_npc->hairstyle = CorpseToUse->hairstyle; - make_npc->helmtexture = CorpseToUse->helmtexture; - make_npc->luclinface = CorpseToUse->luclinface; - make_npc->size = CorpseToUse->size; - make_npc->texture = CorpseToUse->texture; - - //cast stuff.. based off of PEQ's if you want to change - //it you'll have to mod this code, but most likely - //most people will be using PEQ style for the first - //part of their spell list; can't think of any smooth - //way to do this - //some basic combat mods here too since it's convienent - switch(CorpseToUse->class_) - { - case CLERIC: - make_npc->npc_spells_id = 1; - break; - case WIZARD: - make_npc->npc_spells_id = 2; - break; - case NECROMANCER: - make_npc->npc_spells_id = 3; - break; - case MAGICIAN: - make_npc->npc_spells_id = 4; - break; - case ENCHANTER: - make_npc->npc_spells_id = 5; - break; - case SHAMAN: - make_npc->npc_spells_id = 6; - break; - case DRUID: - make_npc->npc_spells_id = 7; - break; - case PALADIN: - //SPECATK_TRIPLE - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 150 / 100; - make_npc->max_hp = make_npc->max_hp * 150 / 100; - make_npc->npc_spells_id = 8; - break; - case SHADOWKNIGHT: - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 150 / 100; - make_npc->max_hp = make_npc->max_hp * 150 / 100; - make_npc->npc_spells_id = 9; - break; - case RANGER: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->cur_hp = make_npc->cur_hp * 135 / 100; - make_npc->max_hp = make_npc->max_hp * 135 / 100; - make_npc->npc_spells_id = 10; - break; - case BARD: - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - make_npc->npc_spells_id = 11; - break; - case BEASTLORD: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - make_npc->npc_spells_id = 12; - break; - case ROGUE: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - break; - case MONK: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 135 / 100; - make_npc->max_hp = make_npc->max_hp * 135 / 100; - break; - case WARRIOR: - case BERSERKER: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 175 / 100; - make_npc->max_hp = make_npc->max_hp * 175 / 100; - break; - default: - make_npc->npc_spells_id = 0; - break; - } - - make_npc->loottable_id = 0; - make_npc->merchanttype = 0; - make_npc->d_meele_texture1 = 0; - make_npc->d_meele_texture2 = 0; - - TempPets(true); - - NPC* npca = new NPC(make_npc, 0, GetX(), GetY(), GetZ(), GetHeading(), FlyMode3); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(duration*1000); - } - - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pet somebody to "love" - if(target != nullptr){ - npca->AddToHateList(target, 100000); - npca->GetSwarmInfo()->target = target->GetID(); - } - - //gear stuff, need to make sure there's - //no situation where this stuff can be duped - for(int x = 0; x < 21; x++) - { - uint32 sitem = 0; - sitem = CorpseToUse->GetWornItem(x); - if(sitem){ - const Item_Struct * itm = database.GetItem(sitem); - npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 127, true, true); - } - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(make_npc != nullptr) - npca->GiveNPCTypeData(make_npc); - - entity_list.AddNPC(npca, true, true); - - //the target of these swarm pets will take offense to being cast on... - if(target != nullptr) - target->AddToHateList(this, 1, 0); -} - -//turn on an AA effect -//duration == 0 means no time limit, used for one-shot deals, etc.. -void Client::EnableAAEffect(aaEffectType type, uint32 duration) { - if(type > 32) - return; //for now, special logic needed. - m_epp.aa_effects |= 1 << (type-1); - - if(duration > 0) { - p_timers.Start(pTimerAAEffectStart + type, duration); - } else { - p_timers.Clear(&database, pTimerAAEffectStart + type); - } -} - -void Client::DisableAAEffect(aaEffectType type) { - if(type > 32) - return; //for now, special logic needed. - uint32 bit = 1 << (type-1); - if(m_epp.aa_effects & bit) { - m_epp.aa_effects ^= bit; - } - p_timers.Clear(&database, pTimerAAEffectStart + type); -} - -/* -By default an AA effect is a one shot deal, unless -a duration timer is set. -*/ -bool Client::CheckAAEffect(aaEffectType type) { - if(type > 32) - return(false); //for now, special logic needed. - if(m_epp.aa_effects & (1 << (type-1))) { //is effect enabled? - //has our timer expired? - if(p_timers.Expired(&database, pTimerAAEffectStart + type)) { - DisableAAEffect(type); - return(false); - } - return(true); - } - return(false); -} - -void Client::SendAAStats() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); - AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer; - aps->experience = m_pp.expAA; - aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP); - aps->unspent = m_pp.aapoints; - aps->percentage = m_epp.perAA; - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::BuyAA(AA_Action* action) -{ - mlog(AA__MESSAGE, "Starting to buy AA %d", action->ability); - - //find the AA information from the database - SendAA_Struct* aa2 = zone->FindAA(action->ability); - if(!aa2) { - //hunt for a lower level... - int i; - int a; - for(i=1;iability - i; - if(a <= 0) - break; - mlog(AA__MESSAGE, "Could not find AA %d, trying potential parent %d", action->ability, a); - aa2 = zone->FindAA(a); - if(aa2 != nullptr) - break; - } - } - if(aa2 == nullptr) - return; //invalid ability... - - if(aa2->special_category == 1 || aa2->special_category == 2) - return; // Not purchasable progression style AAs - - if(aa2->special_category == 8 && aa2->cost == 0) - return; // Not purchasable racial AAs(set a cost to make them purchasable) - - uint32 cur_level = GetAA(aa2->id); - if((aa2->id + cur_level) != action->ability) { //got invalid AA - mlog(AA__ERROR, "Unable to find or match AA %d (found %d + lvl %d)", action->ability, aa2->id, cur_level); - return; - } - - if(aa2->account_time_required) - { - if((Timer::GetTimeSeconds() - account_creation) < aa2->account_time_required) - { - return; - } - } - - uint32 real_cost; - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); - - if(RequiredLevel != AARequiredLevelAndCost.end()) - { - real_cost = RequiredLevel->second.Cost; - } - else - real_cost = aa2->cost + (aa2->cost_inc * cur_level); - - if(m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { - SetAA(aa2->id, cur_level+1); - - mlog(AA__MESSAGE, "Set AA %d to level %d", aa2->id, cur_level+1); - - m_pp.aapoints -= real_cost; - - Save(); - //if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u)) - if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4)) - && ((aa2->max_level == (cur_level+1)) && aa2->sof_next_id)){ - SendAA(aa2->id); - SendAA(aa2->sof_next_id); - } - //else if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && cur_level == 0 && aa2->hotkey_sid != 4294967295u)) - //{ - //Shout("Current lv 0 for AA hot key %i %i", cur_level, aa2->hotkey_sid); - //} - - else - SendAA(aa2->id); - - SendAATable(); - - //we are building these messages ourself instead of using the stringID to work around patch discrepencies - //these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2 - if(cur_level<1) - Message(15,"You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1)?"points":"point"); - else - Message(15,"You have improved %s %d at a cost of %d ability %s.", aa2->name, cur_level+1, real_cost, (real_cost>1)?"points":"point"); - - - SendAAStats(); - - //SendAAList(true); - //SendAATable(); - CalcBonuses(); - if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) - NotifyNewTitlesAvailable(); - } -} - -void Client::SendAATimer(uint32 ability, uint32 begin, uint32 end) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); - UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; - uaaout->ability = ability; - uaaout->begin = begin; - uaaout->end = end; - QueuePacket(outapp); - safe_delete(outapp); -} - -//sends all AA timers. -void Client::SendAATimers() { - //we dont use SendAATimer because theres no reason to allocate the EQApplicationPacket every time - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); - UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; - - PTimerList::iterator c,e; - c = p_timers.begin(); - e = p_timers.end(); - for(; c != e; ++c) { - PersistentTimer *cur = c->second; - if(cur->GetType() < pTimerAAStart || cur->GetType() > pTimerAAEnd) - continue; //not an AA timer - //send timer - uaaout->begin = cur->GetStartTime(); - uaaout->end = static_cast(time(nullptr)); - uaaout->ability = cur->GetType() - pTimerAAStart; // uuaaout->ability is really a shared timer number - QueuePacket(outapp); - } - - safe_delete(outapp); -} - -void Client::SendAATable() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); - - AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; - aa2->aa_spent = GetAAPointsSpent(); - - uint32 i; - for(i=0;i < MAX_PP_AA_ARRAY;i++){ - aa2->aa_list[i].aa_skill = aa[i]->AA; - aa2->aa_list[i].aa_value = aa[i]->value; - aa2->aa_list[i].unknown08 = 0; - } - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendPreviousAA(uint32 id, int seq){ - uint32 value=0; - SendAA_Struct* saa2 = nullptr; - if(id==0) - saa2 = zone->GetAABySequence(seq); - else - saa2 = zone->FindAA(id); - if(!saa2) - return; - int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; - uchar* buffer = new uchar[size]; - SendAA_Struct* saa=(SendAA_Struct*)buffer; - value = GetAA(saa2->id); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); - outapp->size=size; - outapp->pBuffer=(uchar*)saa; - value--; - memcpy(saa,saa2,size); - - if(value>0){ - if(saa->spellid==0) - saa->spellid=0xFFFFFFFF; - saa->id+=value; - saa->next_id=saa->id+1; - if(value==1) - saa->last_id=saa2->id; - else - saa->last_id=saa->id-1; - saa->current_level=value+1; - saa->cost2 = 0; //cost 2 is what the client uses to calc how many points we've spent, so we have to add up the points in order - for(uint32 i = 0; i < (value+1); i++) { - saa->cost2 += saa->cost + (saa->cost_inc * i); - } - } - - database.FillAAEffects(saa); - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendAA(uint32 id, int seq, bool seqrest) { - - uint32 value=0; - SendAA_Struct* saa2 = nullptr; - SendAA_Struct* qaa = nullptr; - SendAA_Struct* saa_pp = nullptr; - bool IsBaseLevel = true; - bool aa_stack = false; - - Shout("Reset: %i", seqrest); - - if(id==0){ - saa2 = zone->GetAABySequence(seq); - //Shout("SAA2 %i x seq %i", GetAA(saa2->id), seq); - } - else - saa2 = zone->FindAA(id); - if(!saa2) - return; - - uint16 classes = saa2->classes; - if(!(classes & (1 << GetClass())) && (GetClass()!=BERSERKER || saa2->berserker==0)){ - return; - } - - if(saa2->account_time_required) - { - if((Timer::GetTimeSeconds() - account_creation) < saa2->account_time_required) - { - return; - } - } - - // Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). - if (saa2->special_category == 1 || saa2->special_category == 2 ) { - if(GetAA(saa2->id) == 0) - return; - // For Quest line AA(demiplane AEs) where only 1 is visible at a time, check to make sure only the highest level obtained is shown - if(saa2->aa_expansion > 0) { - qaa = zone->FindAA(saa2->id+1); - if(qaa && (saa2->aa_expansion == qaa->aa_expansion) && GetAA(qaa->id) > 0) - return; - } - } - -/* Beginning of Shroud AAs, these categories are for Passive and Active Shroud AAs - Eventually with a toggle we could have it show player list or shroud list - if (saa2->special_category == 3 || saa2->special_category == 4) - return; -*/ - // Check for racial/Drakkin blood line AAs - if (saa2->special_category == 8) - { - uint32 client_race = this->GetBaseRace(); - - // Drakkin Bloodlines - if (saa2->aa_expansion > 522) - { - if (client_race != 522) - return; // Check for Drakkin Race - - int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline - - if (heritage != saa2->aa_expansion) - return; - } - // Racial AAs - else if (client_race != saa2->aa_expansion) - { - return; - } - } - - /* - AA stacking on SoF+ clients. - - Note: There were many ways to achieve this effect - The method used proved to be the most straight forward and consistent. - Stacking does not currently work ideally for AA's that use hotkeys, therefore they will be excluded at this time. - - TODO: Problem with AA hotkeys - When you reach max rank of an AA tier (ie 5/5), it automatically displays the next AA in - the series and you can not transfer the hotkey to the next AA series. To the best of the my ability and through many - different variations of coding I could not find an ideal solution to this issue. - - How stacking works: - Utilizes two new fields: sof_next_id (which is the next id in the series), sof_current_level (ranks the AA's as the current level) - 1) If no AA's purchased only display the base levels of each AA series. - 2) When you purchase an AA and its rank is maxed it sends the packet for the completed AA, and the packet - for the next aa in the series. The previous tier is removed from your window, and the new AA is displayed. - 3) When you zone/buy your player profile will be checked and determine what AA can be displayed base on what you have already. - */ - - //if (RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (saa2->hotkey_sid == 4294967295u)) - if (RuleB(AA, Stacking) && (GetClientVersionBit() >= 4)) - aa_stack = true; - - if (aa_stack){ - uint32 aa_AA = 0; - uint32 aa_value = 0; - for (int i = 0; i < MAX_PP_AA_ARRAY; i++) { - if (aa[i]) { - aa_AA = aa[i]->AA; - aa_value = aa[i]->value; - - if (aa_AA){ - - if (aa_value > 0) - aa_AA -= aa_value-1; - - saa_pp = zone->FindAA(aa_AA); - - if (saa_pp){ - - if (saa_pp->sof_next_skill == saa2->sof_next_skill){ - - if (saa_pp->id == saa2->id) - break; //You already have this in the player profile. - else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value < saa_pp->max_level)) - return; //DISABLE DISPLAY HIGHER - You have not reached max level yet of your current AA. - else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value == saa_pp->max_level) && (saa_pp->sof_next_id == saa2->id)) - IsBaseLevel = false; //ALLOW DISPLAY HIGHER - } - } - } - } - } - } - - //Hide higher tiers of multi tiered AA's if the base level is not fully purchased. - if (aa_stack && IsBaseLevel && saa2->sof_current_level > 0) - return; - - int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; - - if(size == 0) - return; - - uchar* buffer = new uchar[size]; - SendAA_Struct* saa=(SendAA_Struct*)buffer; - memcpy(saa,saa2,size); - Shout("[AA ID %i] SEQ %i SEQLIVE %i",saa->id, saa->seq, saa->seqlive); - if(saa->spellid==0) - saa->spellid=0xFFFFFFFF; - - value=GetAA(saa->id); - uint32 orig_val = value; - - if(value && saa->id){ - - if(value < saa->max_level){ - saa->id+=value; - saa->next_id=saa->id+1; - value++; - } - - else if (aa_stack && saa->sof_next_id){ - //Max value of current tier reached. - saa->id+=value-1; - saa->next_id=saa->sof_next_id; - - //Prevent removal of previous AA from window if next AA belongs to a higher client version. - SendAA_Struct* saa_next = nullptr; - saa_next = zone->FindAA(saa->sof_next_id); - if (saa_next && - (((GetClientVersionBit() == 4) && (saa_next->clientver > 4)) - || ((GetClientVersionBit() == 8) && (saa_next->clientver > 5)) - || ((GetClientVersionBit() == 16) && (saa_next->clientver > 6)))){ - saa->next_id=0xFFFFFFFF; - } - - //if (saa->id == 131) { - // saa->seq = 1; - // Shout("SET SEQ 1"); - //} - Shout("AA Completed: Next"); - } - - else{ - saa->id+=value-1; - saa->next_id=0xFFFFFFFF; - Shout("AA Completed: Final"); - } - - uint32 current_level_mod = 0; - if (aa_stack) - current_level_mod = saa->sof_current_level; - - saa->last_id=saa->id-1; - Shout("1 Current level %i + Value %i",saa->sof_current_level, value); - saa->current_level=value+(current_level_mod); - saa->cost = saa2->cost + (saa2->cost_inc*(value-1)); - saa->cost2 = 0; - for(uint32 i = 0; i < value; i++) { - saa->cost2 += saa2->cost + (saa2->cost_inc * i); - } - saa->class_type = saa2->class_type + (saa2->level_inc*(value-1)); - - } - - if (aa_stack){ - Shout("2 Current level %i VALUE %i",saa->sof_current_level, value); - //After finishing an AA tier transfer over the current level to the next tier to display. - if (saa->sof_current_level >= 1 && value == 0){ - saa->current_level = saa->sof_current_level+1; - - Shout("value = 0 SET LAST AND SEQ"); - saa->last_id = 131; - //saa->seq = 38; - if (saa->seqlive) - saa->seq = saa->seqlive; - } - - saa->max_level = saa->sof_max_level; - } - - - if(seqrest) { - //saa->seq = 0; - saa->id+= saa->max_level-1; - saa->next_id=1; - saa->seq = 0; - Shout("reset"); - } - - database.FillAAEffects(saa); - - if(value > 0) - { - // AA_Action stores the base ID - const AA_DBAction *caa = &AA_Actions[saa->id - value + 1][value - 1]; - - if(caa && caa->reuse_time > 0) - saa->spell_refresh = CalcAAReuseTimer(caa); - } - - //You can now use the level_inc field in the altadv_vars table to accomplish this, though still needed - //for special cases like LOH/HT due to inability to implement correct stacking of AA's that use hotkeys. - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(saa->id); - - if(RequiredLevel != AARequiredLevelAndCost.end()) - { - saa->class_type = RequiredLevel->second.Level; - saa->cost = RequiredLevel->second.Cost; - } - - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); - outapp->size=size; - outapp->pBuffer=(uchar*)saa; - if(id==0 && value && (orig_val < saa->max_level)) //send previous AA only on zone in - SendPreviousAA(id, seq); - - QueuePacket(outapp); - safe_delete(outapp); - //will outapp delete the buffer for us even though it didnt make it? --- Yes, it should -} - -void Client::SendAAList(bool seqrest){ - int total = zone->GetTotalAAs(); - for(int i=0;i < total;i++){ - SendAA(0,i, seqrest); - } -} - -uint32 Client::GetAA(uint32 aa_id) const { - std::map::const_iterator res; - res = aa_points.find(aa_id); - if(res != aa_points.end()) { - return(res->second); - } - return(0); -} - -bool Client::SetAA(uint32 aa_id, uint32 new_value) { - aa_points[aa_id] = new_value; - uint32 cur; - for(cur=0;cur < MAX_PP_AA_ARRAY;cur++){ - if((aa[cur]->value > 1) && ((aa[cur]->AA - aa[cur]->value + 1)== aa_id)){ - aa[cur]->value = new_value; - if(new_value > 0) - aa[cur]->AA++; - else - aa[cur]->AA = 0; - return true; - } - else if((aa[cur]->value == 1) && (aa[cur]->AA == aa_id)){ - aa[cur]->value = new_value; - if(new_value > 0) - aa[cur]->AA++; - else - aa[cur]->AA = 0; - return true; - } - else if(aa[cur]->AA==0){ //end of list - aa[cur]->AA = aa_id; - aa[cur]->value = new_value; - return true; - } - } - return false; -} - -SendAA_Struct* Zone::FindAA(uint32 id) { - return aas_send[id]; -} - -void Zone::LoadAAs() { - LogFile->write(EQEMuLog::Status, "Loading AA information..."); - totalAAs = database.CountAAs(); - if(totalAAs == 0) { - LogFile->write(EQEMuLog::Error, "Failed to load AAs!"); - aas = nullptr; - return; - } - aas = new SendAA_Struct *[totalAAs]; - - database.LoadAAs(aas); - - int i; - for(i=0; i < totalAAs; i++){ - SendAA_Struct* aa = aas[i]; - aas_send[aa->id] = aa; - } - - //load AA Effects into aa_effects - LogFile->write(EQEMuLog::Status, "Loading AA Effects..."); - if (database.LoadAAEffects2()) - LogFile->write(EQEMuLog::Status, "Loaded %d AA Effects.", aa_effects.size()); - else - LogFile->write(EQEMuLog::Error, "Failed to load AA Effects!"); -} - -bool ZoneDatabase::LoadAAEffects2() { - aa_effects.clear(); //start fresh - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT aaid, slot, effectid, base1, base2 FROM aa_effects ORDER BY aaid ASC, slot ASC"), errbuf, &result)) { - int count = 0; - while((row = mysql_fetch_row(result))!= nullptr) { - int aaid = atoi(row[0]); - int slot = atoi(row[1]); - int effectid = atoi(row[2]); - int base1 = atoi(row[3]); - int base2 = atoi(row[4]); - aa_effects[aaid][slot].skill_id = effectid; - aa_effects[aaid][slot].base1 = base1; - aa_effects[aaid][slot].base2 = base2; - aa_effects[aaid][slot].slot = slot; //not really needed, but we'll populate it just in case - count++; - } - mysql_free_result(result); - if (count < 1) //no results - LogFile->write(EQEMuLog::Error, "Error loading AA Effects, none found in the database."); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAEffects2 query: '%s': %s", query, errbuf); - return false; - } - safe_delete_array(query); - return true; -} -void Client::ResetAA(){ - uint32 i; - for(i=0;iAA = 0; - aa[i]->value = 0; - } - std::map::iterator itr; - for(itr=aa_points.begin();itr!=aa_points.end();++itr) - aa_points[itr->first] = 0; - - for(int i = 0; i < _maxLeaderAA; ++i) - m_pp.leader_abilities.ranks[i] = 0; - - m_pp.group_leadership_points = 0; - m_pp.raid_leadership_points = 0; - m_pp.group_leadership_exp = 0; - m_pp.raid_leadership_exp = 0; -} - -int Client::GroupLeadershipAAHealthEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAHealthEnhancement)) - { - case 0: - return 0; - case 1: - return 30; - case 2: - return 60; - case 3: - return 100; - } - - return 0; -} - -int Client::GroupLeadershipAAManaEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAManaEnhancement)) - { - case 0: - return 0; - case 1: - return 30; - case 2: - return 60; - case 3: - return 100; - } - - return 0; -} - -int Client::GroupLeadershipAAHealthRegeneration() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAHealthRegeneration)) - { - case 0: - return 0; - case 1: - return 4; - case 2: - return 6; - case 3: - return 8; - } - - return 0; -} - -int Client::GroupLeadershipAAOffenseEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAOffenseEnhancement)) - { - case 0: - return 0; - case 1: - return 10; - case 2: - return 19; - case 3: - return 28; - case 4: - return 34; - case 5: - return 40; - } - return 0; -} - -void Client::InspectBuffs(Client* Inspector, int Rank) -{ - if(!Inspector || (Rank == 0)) return; - - Inspector->Message_StringID(0, CURRENT_SPELL_EFFECTS, GetName()); - uint32 buff_count = GetMaxTotalSlots(); - for (uint32 i = 0; i < buff_count; ++i) - { - if (buffs[i].spellid != SPELL_UNKNOWN) - { - if(Rank == 1) - Inspector->Message(0, "%s", spells[buffs[i].spellid].name); - else - { - if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) - Inspector->Message(0, "%s (Permanent)", spells[buffs[i].spellid].name); - else { - char *TempString = nullptr; - MakeAnyLenString(&TempString, "%.1f", static_cast(buffs[i].ticsremaining) / 10.0f); - Inspector->Message_StringID(0, BUFF_MINUTES_REMAINING, spells[buffs[i].spellid].name, TempString); - safe_delete_array(TempString); - } - } - } - } -} - -//this really need to be renamed to LoadAAActions() -bool ZoneDatabase::LoadAAEffects() { - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - memset(AA_Actions, 0, sizeof(AA_Actions)); //I hope the compiler is smart about this size... - - const char *query = "SELECT aaid,rank,reuse_time,spell_id,target,nonspell_action,nonspell_mana,nonspell_duration," - "redux_aa,redux_rate,redux_aa2,redux_rate2 FROM aa_actions"; - - if(RunQuery(query, static_cast(strlen(query)), errbuf, &result)) { - //safe_delete_array(query); - int r; - while ((row = mysql_fetch_row(result))) { - r = 0; - int aaid = atoi(row[r++]); - int rank = atoi(row[r++]); - if(aaid < 0 || aaid >= aaHighestID || rank < 0 || rank >= MAX_AA_ACTION_RANKS) - continue; - AA_DBAction *caction = &AA_Actions[aaid][rank]; - - caction->reuse_time = atoi(row[r++]); - caction->spell_id = atoi(row[r++]); - caction->target = (aaTargetType) atoi(row[r++]); - caction->action = (aaNonspellAction) atoi(row[r++]); - caction->mana_cost = atoi(row[r++]); - caction->duration = atoi(row[r++]); - caction->redux_aa = (aaID) atoi(row[r++]); - caction->redux_rate = atoi(row[r++]); - caction->redux_aa2 = (aaID) atoi(row[r++]); - caction->redux_rate2 = atoi(row[r++]); - - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in LoadAAEffects query '%s': %s", query, errbuf);; - //safe_delete_array(query); - return false; - } - - return true; -} - -//Returns the number effects an AA has when we send them to the client -//For the purposes of sizing a packet because every skill does not -//have the same number effects, they can range from none to a few depending on AA. -//counts the # of effects by counting the different slots of an AAID in the DB. - -//AndMetal: this may now be obsolete since we have Zone::GetTotalAALevels() -uint8 ZoneDatabase::GetTotalAALevels(uint32 skill_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int total=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(slot) from aa_effects where aaid=%i", skill_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - total=atoi(row[0]); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in GetTotalAALevels '%s: %s", query, errbuf); - safe_delete_array(query); - } - return total; -} - -//this will allow us to count the number of effects for an AA by pulling the info from memory instead of the database. hopefully this will same some CPU cycles -uint8 Zone::GetTotalAALevels(uint32 skill_id) { - size_t sz = aa_effects[skill_id].size(); - return sz >= 255 ? 255 : static_cast(sz); -} - -/* -Every AA can send the client effects, which are purely for client side effects. -Essentially it's like being able to attach a very simple version of a spell to -Any given AA, it has 4 fields: -skill_id = spell effect id -slot = ID slot, doesn't appear to have any impact on stacking like real spells, just needs to be unique. -base1 = the base field of a spell -base2 = base field 2 of a spell, most AAs do not utilize this -example: - skill_id = SE_STA - slot = 1 - base1 = 15 - This would if you filled the abilities struct with this make the client show if it had - that AA an additional 15 stamina on the client's stats -*/ -void ZoneDatabase::FillAAEffects(SendAA_Struct* aa_struct){ - if(!aa_struct) - return; - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT effectid, base1, base2, slot from aa_effects where aaid=%i order by slot asc", aa_struct->id), errbuf, &result)) { - int ndx=0; - while((row = mysql_fetch_row(result))!=nullptr) { - aa_struct->abilities[ndx].skill_id=atoi(row[0]); - aa_struct->abilities[ndx].base1=atoi(row[1]); - aa_struct->abilities[ndx].base2=atoi(row[2]); - aa_struct->abilities[ndx].slot=atoi(row[3]); - ndx++; - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in Client::FillAAEffects query: '%s': %s", query, errbuf); - } - safe_delete_array(query); -} - -uint32 ZoneDatabase::CountAAs(){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int count=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(title_sid) from altadv_vars"), errbuf, &result)) { - if((row = mysql_fetch_row(result))!=nullptr) - count = atoi(row[0]); - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAAs query '%s': %s", query, errbuf); - } - safe_delete_array(query); - return count; -} - -uint32 ZoneDatabase::CountAAEffects(){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int count=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(id) from aa_effects"), errbuf, &result)) { - if((row = mysql_fetch_row(result))!=nullptr){ - count = atoi(row[0]); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAALevels query '%s': %s", query, errbuf); - } - safe_delete_array(query); - return count; -} - -uint32 ZoneDatabase::GetSizeAA(){ - int size=CountAAs()*sizeof(SendAA_Struct); - if(size>0) - size+=CountAAEffects()*sizeof(AA_Ability); - return size; -} - -void ZoneDatabase::LoadAAs(SendAA_Struct **load){ - if(!load) - return; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id from altadv_vars order by skill_id"), errbuf, &result)) { - int skill=0,ndx=0; - while((row = mysql_fetch_row(result))!=nullptr) { - skill=atoi(row[0]); - load[ndx] = GetAASkillVars(skill); - load[ndx]->seq = ndx+1; - ndx++; - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); - } - safe_delete_array(query); - - AARequiredLevelAndCost.clear(); - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id, level, cost from aa_required_level_cost order by skill_id"), errbuf, &result)) - { - AALevelCost_Struct aalcs; - while((row = mysql_fetch_row(result))!=nullptr) - { - aalcs.Level = atoi(row[1]); - aalcs.Cost = atoi(row[2]); - AARequiredLevelAndCost[atoi(row[0])] = aalcs; - } - mysql_free_result(result); - } - else - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); - - safe_delete_array(query); -} - -SendAA_Struct* ZoneDatabase::GetAASkillVars(uint32 skill_id) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - SendAA_Struct* sendaa = nullptr; - uchar* buffer; - if (RunQuery(query, MakeAnyLenString(&query, "SET @row = 0"), errbuf)) { //initialize "row" variable in database for next query - safe_delete_array(query); - MYSQL_RES *result; //we don't really need these unless we get to this point, so why bother? - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, - "SELECT " - "a.cost, " - "a.max_level, " - "a.hotkey_sid, " - "a.hotkey_sid2, " - "a.title_sid, " - "a.desc_sid, " - "a.type, " - "COALESCE(" //so we can return 0 if it's null - "(" //this is our derived table that has the row # that we can SELECT from, because the client is stupid - "SELECT " - "p.prereq_index_num " - "FROM " - "(" - "SELECT " - "a2.skill_id, " - "@row := @row + 1 AS prereq_index_num " - "FROM " - "altadv_vars a2" - ") AS p " - "WHERE " - "p.skill_id = a.prereq_skill" - "), " - "0) AS prereq_skill_index, " - "a.prereq_minpoints, " - "a.spell_type, " - "a.spell_refresh, " - "a.classes, " - "a.berserker, " - "a.spellid, " - "a.class_type, " - "a.name, " - "a.cost_inc, " - "a.aa_expansion, " - "a.special_category, " - "a.sof_type, " - "a.sof_cost_inc, " - "a.sof_max_level, " - "a.sof_next_skill, " - "a.clientver, " // Client Version 0 = None, 1 = All, 2 = Titanium/6.2, 4 = SoF 5 = SOD 6 = UF - "a.account_time_required, " - "a.sof_current_level," - "a.sof_next_id, " - "a.level_inc, " - "a.seqlive " - " FROM altadv_vars a WHERE skill_id=%i", skill_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - int total_abilities = GetTotalAALevels(skill_id); //eventually we'll want to use zone->GetTotalAALevels(skill_id) since it should save queries to the DB - int totalsize = total_abilities * sizeof(AA_Ability) + sizeof(SendAA_Struct); - - buffer = new uchar[totalsize]; - memset(buffer,0,totalsize); - sendaa = (SendAA_Struct*)buffer; - - row = mysql_fetch_row(result); - - //ATOI IS NOT UNISGNED LONG-SAFE!!! - - sendaa->cost = atoul(row[0]); - sendaa->cost2 = sendaa->cost; - sendaa->max_level = atoul(row[1]); - sendaa->hotkey_sid = atoul(row[2]); - sendaa->id = skill_id; - sendaa->hotkey_sid2 = atoul(row[3]); - sendaa->title_sid = atoul(row[4]); - sendaa->desc_sid = atoul(row[5]); - sendaa->type = atoul(row[6]); - sendaa->prereq_skill = atoul(row[7]); - sendaa->prereq_minpoints = atoul(row[8]); - sendaa->spell_type = atoul(row[9]); - sendaa->spell_refresh = atoul(row[10]); - sendaa->classes = static_cast(atoul(row[11])); - sendaa->berserker = static_cast(atoul(row[12])); - sendaa->last_id = 0xFFFFFFFF; - sendaa->current_level=1; - sendaa->spellid = atoul(row[13]); - sendaa->class_type = atoul(row[14]); - strcpy(sendaa->name,row[15]); - - sendaa->total_abilities=total_abilities; - if(sendaa->max_level > 1) - sendaa->next_id=skill_id+1; - else - sendaa->next_id=0xFFFFFFFF; - - sendaa->cost_inc = atoi(row[16]); - // Begin SoF Specific/Adjusted AA Fields - sendaa->aa_expansion = atoul(row[17]); - sendaa->special_category = atoul(row[18]); - sendaa->sof_type = atoul(row[19]); - sendaa->sof_cost_inc = atoi(row[20]); - sendaa->sof_max_level = atoul(row[21]); - sendaa->sof_next_skill = atoul(row[22]); - sendaa->clientver = atoul(row[23]); - sendaa->account_time_required = atoul(row[24]); - //Internal use only - not sent to client - sendaa->sof_current_level = atoul(row[25]); - sendaa->sof_next_id = atoul(row[26]); - sendaa->level_inc = static_cast(atoul(row[27])); - sendaa->seqlive = (atoul(row[28])); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); - safe_delete_array(query); - } - } else { - LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); - safe_delete_array(query); - } - return sendaa; -} - -void Client::DurationRampage(uint32 duration) -{ - if(duration) { - m_epp.aa_effects |= 1 << (aaEffectRampage-1); - p_timers.Start(pTimerAAEffectStart + aaEffectRampage, duration); - } -} - -AA_SwarmPetInfo::AA_SwarmPetInfo() -{ - target = 0; - owner_id = 0; - duration = nullptr; -} - -AA_SwarmPetInfo::~AA_SwarmPetInfo() -{ - target = 0; - owner_id = 0; - safe_delete(duration); -} - -Mob *AA_SwarmPetInfo::GetOwner() -{ - return entity_list.GetMobID(owner_id); -} diff --git a/zone/MobAI_M.cpp b/zone/MobAI_M.cpp deleted file mode 100644 index 7574f19ad..000000000 --- a/zone/MobAI_M.cpp +++ /dev/null @@ -1,2760 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "../common/debug.h" -#include -#include -#include -#include -#include -#include "npc.h" -#include "masterentity.h" -#include "NpcAI.h" -#include "map.h" -#include "../common/moremath.h" -#include "StringIDs.h" -#include "../common/MiscFunctions.h" -#include "../common/StringUtil.h" -#include "../common/rulesys.h" -#include "../common/features.h" -#include "QuestParserCollection.h" -#include "watermap.h" - -extern EntityList entity_list; - -extern Zone *zone; - -#ifdef _EQDEBUG - #define MobAI_DEBUG_Spells -1 -#else - #define MobAI_DEBUG_Spells -1 -#endif -#define ABS(x) ((x)<0?-(x):(x)) - -//NOTE: do NOT pass in beneficial and detrimental spell types into the same call here! -bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { - if (!tar) - return false; - - if (IsNoCast()) - return false; - - if(AI_HasSpells() == false) - return false; - - if (iChance < 100) { - if (MakeRandomInt(0, 100) >= iChance) - return false; - } - - float dist2; - - if (iSpellTypes & SpellType_Escape) { - dist2 = 0; //DistNoRoot(*this); //WTF was up with this... - } - else - dist2 = DistNoRoot(*tar); - - bool checked_los = false; //we do not check LOS until we are absolutely sure we need to, and we only do it once. - - float manaR = GetManaRatio(); - for (int i = static_cast(AIspells.size()) - 1; i >= 0; i--) { - if (AIspells[i].spellid <= 0 || AIspells[i].spellid >= SPDAT_RECORDS) { - // this is both to quit early to save cpu and to avoid casting bad spells - // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here - //return false; - continue; - } - if (iSpellTypes & AIspells[i].type) { - // manacost has special values, -1 is no mana cost, -2 is instant cast (no mana) - int32 mana_cost = AIspells[i].manacost; - if (mana_cost == -1) - mana_cost = spells[AIspells[i].spellid].mana; - else if (mana_cost == -2) - mana_cost = 0; - if ( - (( - (spells[AIspells[i].spellid].targettype==ST_AECaster || spells[AIspells[i].spellid].targettype==ST_AEBard) - && dist2 <= spells[AIspells[i].spellid].aoerange*spells[AIspells[i].spellid].aoerange - ) || - dist2 <= spells[AIspells[i].spellid].range*spells[AIspells[i].spellid].range - ) - && (mana_cost <= GetMana() || GetMana() == GetMaxMana()) - && (AIspells[i].time_cancast + (MakeRandomInt(0, 4) * 1000)) <= Timer::GetCurrentTime() //break up the spelling casting over a period of time. - ) { - -#if MobAI_DEBUG_Spells >= 21 - std::cout << "Mob::AICastSpell: Casting: spellid=" << AIspells[i].spellid - << ", tar=" << tar->GetName() - << ", dist2[" << dist2 << "]<=" << spells[AIspells[i].spellid].range *spells[AIspells[i].spellid].range - << ", mana_cost[" << mana_cost << "]<=" << GetMana() - << ", cancast[" << AIspells[i].time_cancast << "]<=" << Timer::GetCurrentTime() - << ", type=" << AIspells[i].type << std::endl; -#endif - - switch (AIspells[i].type) { - case SpellType_Heal: { - if ( - (spells[AIspells[i].spellid].targettype == ST_Target || tar == this) - && tar->DontHealMeBefore() < Timer::GetCurrentTime() - && !(tar->IsPet() && tar->GetOwner()->IsClient()) //no buffing PC's pets - ) { - uint8 hpr = (uint8)tar->GetHPRatio(); - - if(hpr <= 35 || (!IsEngaged() && hpr <= 50) || (tar->IsClient() && hpr <= 99)) { - uint32 tempTime = 0; - AIDoSpellCast(i, tar, mana_cost, &tempTime); - tar->SetDontHealMeBefore(tempTime); - return true; - } - } - break; - } - case SpellType_Root: { - Mob *rootee = GetHateRandom(); - if (rootee && !rootee->IsRooted() && MakeRandomInt(0, 99) < 50 - && rootee->DontRootMeBefore() < Timer::GetCurrentTime() - && rootee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - ) { - if(!checked_los) { - if(!CheckLosFN(rootee)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - uint32 tempTime = 0; - AIDoSpellCast(i, rootee, mana_cost, &tempTime); - rootee->SetDontRootMeBefore(tempTime); - return true; - } - break; - } - case SpellType_Buff: { - if ( - (spells[AIspells[i].spellid].targettype == ST_Target || tar == this) - && tar->DontBuffMeBefore() < Timer::GetCurrentTime() - && !tar->IsImmuneToSpell(AIspells[i].spellid, this) - && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - && !(tar->IsPet() && tar->GetOwner()->IsClient() && this != tar) //no buffing PC's pets, but they can buff themself - ) - { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); - checked_los = true; - } - uint32 tempTime = 0; - AIDoSpellCast(i, tar, mana_cost, &tempTime); - tar->SetDontBuffMeBefore(tempTime); - return true; - } - break; - } - - case SpellType_InCombatBuff: { - if(MakeRandomInt(0, 99) < 50) - { - AIDoSpellCast(i, tar, mana_cost); - return true; - } - break; - } - - case SpellType_Escape: { - if (GetHPRatio() <= 5 ) - { - AIDoSpellCast(i, tar, mana_cost); - return true; - } - break; - } - case SpellType_Slow: - case SpellType_Debuff: { - Mob * debuffee = GetHateRandom(); - if (debuffee && manaR >= 10 && MakeRandomInt(0, 99 < 70) && - debuffee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) { - if (!checked_los) { - if (!CheckLosFN(debuffee)) - return false; - checked_los = true; - } - AIDoSpellCast(i, debuffee, mana_cost); - return true; - } - break; - } - case SpellType_Nuke: { - if ( - manaR >= 10 && MakeRandomInt(0, 99) < 70 - && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - ) { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - AIDoSpellCast(i, tar, mana_cost); - return true; - } - break; - } - case SpellType_Dispel: { - if(MakeRandomInt(0, 99) < 15) - { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - if(tar->CountDispellableBuffs() > 0) - { - AIDoSpellCast(i, tar, mana_cost); - return true; - } - } - break; - } - case SpellType_Mez: { - if(MakeRandomInt(0, 99) < 20) - { - Mob * mezTar = nullptr; - mezTar = entity_list.GetTargetForMez(this); - - if(mezTar && mezTar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) - { - AIDoSpellCast(i, mezTar, mana_cost); - return true; - } - } - break; - } - - case SpellType_Charm: - { - if(!IsPet() && MakeRandomInt(0, 99) < 20) - { - Mob * chrmTar = GetHateRandom(); - if(chrmTar && chrmTar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) - { - AIDoSpellCast(i, chrmTar, mana_cost); - return true; - } - } - break; - } - - case SpellType_Pet: { - //keep mobs from recasting pets when they have them. - if (!IsPet() && !GetPetID() && MakeRandomInt(0, 99) < 25) { - AIDoSpellCast(i, tar, mana_cost); - return true; - } - break; - } - case SpellType_Lifetap: { - if (GetHPRatio() <= 95 - && MakeRandomInt(0, 99) < 50 - && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - ) { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - AIDoSpellCast(i, tar, mana_cost); - return true; - } - break; - } - case SpellType_Snare: { - if ( - !tar->IsRooted() - && MakeRandomInt(0, 99) < 50 - && tar->DontSnareMeBefore() < Timer::GetCurrentTime() - && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - ) { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - uint32 tempTime = 0; - AIDoSpellCast(i, tar, mana_cost, &tempTime); - tar->SetDontSnareMeBefore(tempTime); - return true; - } - break; - } - case SpellType_DOT: { - if ( - MakeRandomInt(0, 99) < 60 - && tar->DontDotMeBefore() < Timer::GetCurrentTime() - && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - ) { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - uint32 tempTime = 0; - AIDoSpellCast(i, tar, mana_cost, &tempTime); - tar->SetDontDotMeBefore(tempTime); - return true; - } - break; - } - default: { - std::cout << "Error: Unknown spell type in AICastSpell. caster:" << this->GetName() << " type:" << AIspells[i].type << " slot:" << i << std::endl; - break; - } - } - } -#if MobAI_DEBUG_Spells >= 21 - else { - std::cout << "Mob::AICastSpell: NotCasting: spellid=" << AIspells[i].spellid << ", tar=" << tar->GetName() << ", dist2[" << dist2 << "]<=" << spells[AIspells[i].spellid].range*spells[AIspells[i].spellid].range << ", mana_cost[" << mana_cost << "]<=" << GetMana() << ", cancast[" << AIspells[i].time_cancast << "]<=" << Timer::GetCurrentTime() << std::endl; - } -#endif - } - } - return false; -} - -bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore) { -#if MobAI_DEBUG_Spells >= 1 - std::cout << "Mob::AIDoSpellCast: spellid=" << AIspells[i].spellid << ", tar=" << tar->GetName() << ", mana=" << mana_cost << ", Name: " << spells[AIspells[i].spellid].name << std::endl; -#endif - casting_spell_AIindex = i; - - //stop moving if were casting a spell and were not a bard... - if(!IsBardSong(AIspells[i].spellid)) { - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - } - - return CastSpell(AIspells[i].spellid, tar->GetID(), 1, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0, &(AIspells[i].resist_adjust)); -} - -bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint16 iSpellTypes) { - if((iSpellTypes&SpellTypes_Detrimental) != 0) { - //according to live, you can buff and heal through walls... - //now with PCs, this only applies if you can TARGET the target, but - // according to Rogean, Live NPCs will just cast through walls/floors, no problem.. - // - // This check was put in to address an idle-mob CPU issue - _log(AI__ERROR, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!"); - return(false); - } - - if(!caster) - return false; - - if(caster->AI_HasSpells() == false) - return false; - - if(caster->GetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS)) - return false; - - if (iChance < 100) { - uint8 tmp = MakeRandomInt(0, 99); - if (tmp >= iChance) - return false; - } - if (caster->GetPrimaryFaction() == 0 ) - return(false); // well, if we dont have a faction set, we're gonna be indiff to everybody - - float iRange2 = iRange*iRange; - - float t1, t2, t3; - - - //Only iterate through NPCs - for (auto it = npc_list.begin(); it != npc_list.end(); ++it) { - NPC* mob = it->second; - - //Since >90% of mobs will always be out of range, try to - //catch them with simple bounding box checks first. These - //checks are about 6X faster than DistNoRoot on my athlon 1Ghz - t1 = mob->GetX() - caster->GetX(); - t2 = mob->GetY() - caster->GetY(); - t3 = mob->GetZ() - caster->GetZ(); - //cheap ABS() - if(t1 < 0) - t1 = 0 - t1; - if(t2 < 0) - t2 = 0 - t2; - if(t3 < 0) - t3 = 0 - t3; - if (t1 > iRange - || t2 > iRange - || t3 > iRange - || mob->DistNoRoot(*caster) > iRange2 - //this call should seem backwards: - || !mob->CheckLosFN(caster) - || mob->GetReverseFactionCon(caster) >= FACTION_KINDLY - ) { - continue; - } - - //since we assume these are beneficial spells, which do not - //require LOS, we just go for it. - // we have a winner! - if((iSpellTypes & SpellType_Buff) && !RuleB(NPC, BuffFriends)){ - if (mob != caster) - iSpellTypes = SpellType_Heal; - } - - if (caster->AICastSpell(mob, 100, iSpellTypes)) - return true; - } - return false; -} - -void Mob::AI_Init() { - pAIControlled = false; - AIthink_timer = 0; - AIwalking_timer = 0; - AImovement_timer = 0; - AItarget_check_timer = 0; - AIfeignremember_timer = nullptr; - AIscanarea_timer = 0; - minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin); - maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax); - - pDontHealMeBefore = 0; - pDontBuffMeBefore = 0; - pDontDotMeBefore = 0; - pDontRootMeBefore = 0; - pDontSnareMeBefore = 0; - pDontCureMeBefore = 0; -} - -void NPC::AI_Init() { - Mob::AI_Init(); - - AIautocastspell_timer = 0; - casting_spell_AIindex = static_cast(AIspells.size()); - - roambox_max_x = 0; - roambox_max_y = 0; - roambox_min_x = 0; - roambox_min_y = 0; - roambox_distance = 0; - roambox_movingto_x = 0; - roambox_movingto_y = 0; - roambox_min_delay = 2500; - roambox_delay = 2500; -} - -void Client::AI_Init() { - Mob::AI_Init(); - minLastFightingDelayMoving = CLIENT_LD_TIMEOUT; - maxLastFightingDelayMoving = CLIENT_LD_TIMEOUT; -} - -void Mob::AI_Start(uint32 iMoveDelay) { - if (pAIControlled) - return; - - if (iMoveDelay) - pLastFightingDelayMoving = Timer::GetCurrentTime() + iMoveDelay; - else - pLastFightingDelayMoving = 0; - - pAIControlled = true; - AIthink_timer = new Timer(AIthink_duration); - AIthink_timer->Trigger(); - AIwalking_timer = new Timer(0); - AImovement_timer = new Timer(AImovement_duration); - AItarget_check_timer = new Timer(AItarget_check_duration); - AIfeignremember_timer = new Timer(AIfeignremember_delay); - AIscanarea_timer = new Timer(AIscanarea_delay); -#ifdef REVERSE_AGGRO - if(IsNPC() && !CastToNPC()->WillAggroNPCs()) - AIscanarea_timer->Disable(); -#endif - - if (GetAggroRange() == 0) - pAggroRange = 70; - if (GetAssistRange() == 0) - pAssistRange = 70; - hate_list.Wipe(); - - delta_heading = 0; - delta_x = 0; - delta_y = 0; - delta_z = 0; - pRunAnimSpeed = 0; - pLastChange = Timer::GetCurrentTime(); -} - -void Client::AI_Start(uint32 iMoveDelay) { - Mob::AI_Start(iMoveDelay); - - if (!pAIControlled) - return; - - pClientSideTarget = GetTarget() ? GetTarget()->GetID() : 0; - SendAppearancePacket(AT_Anim, ANIM_FREEZE); // this freezes the client - SendAppearancePacket(AT_Linkdead, 1); // Sending LD packet so *LD* appears by the player name when charmed/feared -Kasai - SetAttackTimer(); - SetFeigned(false); -} - -void NPC::AI_Start(uint32 iMoveDelay) { - Mob::AI_Start(iMoveDelay); - if (!pAIControlled) - return; - - if (AIspells.size() == 0) { - AIautocastspell_timer = new Timer(1000); - AIautocastspell_timer->Disable(); - } else { - AIautocastspell_timer = new Timer(750); - AIautocastspell_timer->Start(RandomTimer(0, 15000), false); - } - - if (NPCTypedata) { - AI_AddNPCSpells(NPCTypedata->npc_spells_id); - ProcessSpecialAbilities(NPCTypedata->special_abilities); - AI_AddNPCSpellsEffects(NPCTypedata->npc_spells_effects_id); - } - - SendTo(GetX(), GetY(), GetZ()); - SetChanged(); - SaveGuardSpot(); -} - -void Mob::AI_Stop() { - if (!IsAIControlled()) - return; - pAIControlled = false; - safe_delete(AIthink_timer); - safe_delete(AIwalking_timer); - safe_delete(AImovement_timer); - safe_delete(AItarget_check_timer) - safe_delete(AIscanarea_timer); - safe_delete(AIfeignremember_timer); - hate_list.Wipe(); -} - -void NPC::AI_Stop() { - Waypoints.clear(); - safe_delete(AIautocastspell_timer); -} - -void Client::AI_Stop() { - Mob::AI_Stop(); - this->Message_StringID(13,PLAYER_REGAIN); - - EQApplicationPacket *app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); - Charm_Struct *ps = (Charm_Struct*)app->pBuffer; - ps->owner_id = 0; - ps->pet_id = this->GetID(); - ps->command = 0; - entity_list.QueueClients(this, app); - safe_delete(app); - - SetTarget(entity_list.GetMob(pClientSideTarget)); - SendAppearancePacket(AT_Anim, GetAppearanceValue(GetAppearance())); - SendAppearancePacket(AT_Linkdead, 0); // Removing LD packet so *LD* no longer appears by the player name when charmed/feared -Kasai - if (!auto_attack) { - attack_timer.Disable(); - attack_dw_timer.Disable(); - } - if (IsLD()) - { - Save(); - Disconnect(); - } -} - -//todo: expand the logic here to cover: -//redundant debuffs -//buffing owner -//certain types of det spells that need special behavior. -void Client::AI_SpellCast() -{ - if(!charm_cast_timer.Check()) - return; - - Mob *targ = GetTarget(); - if(!targ) - return; - - float dist = DistNoRootNoZ(*targ); - - std::vector valid_spells; - std::vector slots; - - for(uint32 x = 0; x < 9; ++x) - { - uint32 current_spell = m_pp.mem_spells[x]; - if(!IsValidSpell(current_spell)) - continue; - - if(IsBeneficialSpell(current_spell)) - { - continue; - } - - if(dist > spells[current_spell].range*spells[current_spell].range) - { - continue; - } - - if(GetMana() < spells[current_spell].mana) - { - continue; - } - - if(IsEffectInSpell(current_spell, SE_Charm)) - { - continue; - } - - if(!GetPTimers().Expired(&database, pTimerSpellStart + current_spell, false)) - { - continue; - } - - if(targ->CanBuffStack(current_spell, GetLevel(), true) < 0) - { - continue; - } - - //bard songs cause trouble atm - if(IsBardSong(current_spell)) - continue; - - valid_spells.push_back(current_spell); - slots.push_back(x); - } - - uint32 spell_to_cast = 0xFFFFFFFF; - uint32 slot_to_use = 10; - if(valid_spells.size() == 1) - { - spell_to_cast = valid_spells[0]; - slot_to_use = slots[0]; - } - else if(valid_spells.size() == 0) - { - return; - } - else - { - uint32 idx = MakeRandomInt(0, (valid_spells.size()-1)); - spell_to_cast = valid_spells[idx]; - slot_to_use = slots[idx]; - } - - if(IsMezSpell(spell_to_cast) || IsFearSpell(spell_to_cast)) - { - Mob *tar = entity_list.GetTargetForMez(this); - if(!tar) - { - tar = GetTarget(); - if(tar && IsFearSpell(spell_to_cast)) - { - if(!IsBardSong(spell_to_cast)) - { - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - } - CastSpell(spell_to_cast, tar->GetID(), slot_to_use); - return; - } - } - } - else - { - Mob *tar = GetTarget(); - if(tar) - { - if(!IsBardSong(spell_to_cast)) - { - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - } - CastSpell(spell_to_cast, tar->GetID(), slot_to_use); - return; - } - } - - -} - -void Client::AI_Process() -{ - if (!IsAIControlled()) - return; - - if (!(AIthink_timer->Check() || attack_timer.Check(false))) - return; - - if (IsCasting()) - return; - - bool engaged = IsEngaged(); - - Mob *ow = GetOwner(); - if(!engaged) - { - if(ow) - { - if(ow->IsEngaged()) - { - Mob *tar = ow->GetTarget(); - if(tar) - { - AddToHateList(tar, 1, 0, false); - } - } - } - } - - if(!ow) - { - if(!IsFeared() && !IsLD()) - { - BuffFadeByEffect(SE_Charm); - return; - } - } - - if(RuleB(Combat, EnableFearPathing)){ - if(curfp) { - if(IsRooted()) { - //make sure everybody knows were not moving, for appearance sake - if(IsMoving()) - { - if(GetTarget()) - SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - moved=false; - } - //continue on to attack code, ensuring that we execute the engaged code - engaged = true; - } else { - if(AImovement_timer->Check()) { - animation = GetRunspeed() * 21; - // Check if we have reached the last fear point - if((ABS(GetX()-fear_walkto_x) < 0.1) && (ABS(GetY()-fear_walkto_y) <0.1)) { - // Calculate a new point to run to - CalculateNewFearpoint(); - } - if(!RuleB(Pathing, Fear) || !zone->pathing) - CalculateNewPosition2(fear_walkto_x, fear_walkto_y, fear_walkto_z, GetFearSpeed(), true); - else - { - bool WaypointChanged, NodeReached; - - VERTEX Goal = UpdatePath(fear_walkto_x, fear_walkto_y, fear_walkto_z, - GetFearSpeed(), WaypointChanged, NodeReached); - - if(WaypointChanged) - tar_ndx = 20; - - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetFearSpeed()); - } - } - return; - } - } - } - - if (engaged) - { - if (IsRooted()) - SetTarget(hate_list.GetClosest(this)); - else - { - if(AItarget_check_timer->Check()) - { - SetTarget(hate_list.GetTop(this)); - } - } - - if (!GetTarget()) - return; - - if (GetTarget()->IsCorpse()) { - RemoveFromHateList(this); - return; - } - - if(DivineAura()) - return; - - bool is_combat_range = CombatRange(GetTarget()); - - if(is_combat_range) { - if(charm_class_attacks_timer.Check()) { - DoClassAttacks(GetTarget()); - } - - if (AImovement_timer->Check()) { - SetRunAnimSpeed(0); - } - if(IsMoving()) { - SetMoving(false); - moved=false; - SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); - SendPosition(); - tar_ndx =0; - } - - if(GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) { - if(attack_timer.Check()) { - Attack(GetTarget(), 13); - if(GetTarget()) { - if(CheckDoubleAttack()) { - Attack(GetTarget(), 13); - if(GetTarget()) { - bool triple_attack_success = false; - if((((GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER) - && GetLevel() >= 60) || GetSpecialAbility(SPECATK_TRIPLE)) - && CheckDoubleAttack(true)) - { - Attack(GetTarget(), 13, true); - triple_attack_success = true; - } - - if(GetTarget()) - { - //Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). - int16 flurrychance = aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance; - - if (flurrychance) - { - if(MakeRandomInt(0, 100) < flurrychance) - { - Message_StringID(MT_NPCFlurry, YOU_FLURRY); - Attack(GetTarget(), 13, false); - Attack(GetTarget(), 13, false); - } - } - - int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance; - - if (ExtraAttackChanceBonus && GetTarget()) { - ItemInst *wpn = GetInv().GetItem(SLOT_PRIMARY); - if(wpn){ - if(wpn->GetItem()->ItemType == ItemType2HSlash || - wpn->GetItem()->ItemType == ItemType2HBlunt || - wpn->GetItem()->ItemType == ItemType2HPiercing ) - { - if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus) - { - Attack(GetTarget(), 13, false); - } - } - } - } - - if (GetClass() == WARRIOR || GetClass() == BERSERKER) - { - if(!dead && !berserk && this->GetHPRatio() < 30) - { - entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_START, GetName()); - berserk = true; - } - else if (berserk && this->GetHPRatio() > 30) - { - entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_END, GetName()); - berserk = false; - } - } - } - } - } - } - } - } - - if(CanThisClassDualWield() && attack_dw_timer.Check()) - { - if(GetTarget()) - { - float DualWieldProbability = 0.0f; - - int16 Ambidexterity = aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity; - DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f; // 78.0 max - int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance; - DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f; - - if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability) - { - Attack(GetTarget(), 14); - if(CheckDoubleAttack()) - { - Attack(GetTarget(), 14); - } - - } - } - } - } - else - { - if(!IsRooted()) - { - animation = 21 * GetRunspeed(); - if(!RuleB(Pathing, Aggro) || !zone->pathing) - CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed()); - else - { - bool WaypointChanged, NodeReached; - VERTEX Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), - GetRunspeed(), WaypointChanged, NodeReached); - - if(WaypointChanged) - tar_ndx = 20; - - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); - } - } - else if(IsMoving()) - { - SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - moved=false; - } - } - AI_SpellCast(); - } - else - { - if(AIfeignremember_timer->Check()) { - std::set::iterator RememberedCharID; - RememberedCharID = feign_memory_list.begin(); - while (RememberedCharID != feign_memory_list.end()) { - Client* remember_client = entity_list.GetClientByCharID(*RememberedCharID); - if (remember_client == nullptr) { - //they are gone now... - RememberedCharID = feign_memory_list.erase(RememberedCharID); - } else if (!remember_client->GetFeigned()) { - AddToHateList(remember_client->CastToMob(),1); - RememberedCharID = feign_memory_list.erase(RememberedCharID); - break; - } else { - //they are still feigned, carry on... - ++RememberedCharID; - } - } - } - - if(IsPet()) - { - Mob* owner = GetOwner(); - if(owner == nullptr) - return; - - float dist = DistNoRoot(*owner); - if (dist >= 100) - { - float speed = dist >= 225 ? GetRunspeed() : GetWalkspeed(); - animation = 21 * speed; - CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); - } - else - { - SetHeading(owner->GetHeading()); - if(moved) - { - moved=false; - SetMoving(false); - SendPosition(); - SetRunAnimSpeed(0); - } - } - } - } -} - -void Mob::AI_Process() { - if (!IsAIControlled()) - return; - - if (!(AIthink_timer->Check() || attack_timer.Check(false))) - return; - - if (IsCasting()) - return; - - bool engaged = IsEngaged(); - bool doranged = false; - - // Begin: Additions for Wiz Fear Code - // - if(RuleB(Combat, EnableFearPathing)){ - if(curfp) { - if(IsRooted()) { - //make sure everybody knows were not moving, for appearance sake - if(IsMoving()) - { - if(target) - SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - moved=false; - } - //continue on to attack code, ensuring that we execute the engaged code - engaged = true; - } else { - if(AImovement_timer->Check()) { - // Check if we have reached the last fear point - if((ABS(GetX()-fear_walkto_x) < 0.1) && (ABS(GetY()-fear_walkto_y) <0.1)) { - // Calculate a new point to run to - CalculateNewFearpoint(); - } - if(!RuleB(Pathing, Fear) || !zone->pathing) - CalculateNewPosition2(fear_walkto_x, fear_walkto_y, fear_walkto_z, GetFearSpeed(), true); - else - { - bool WaypointChanged, NodeReached; - - VERTEX Goal = UpdatePath(fear_walkto_x, fear_walkto_y, fear_walkto_z, - GetFearSpeed(), WaypointChanged, NodeReached); - - if(WaypointChanged) - tar_ndx = 20; - - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetFearSpeed()); - } - } - return; - } - } - } - - // trigger EVENT_SIGNAL if required - if(IsNPC()) { - CastToNPC()->CheckSignal(); - } - - if (engaged) - { - if (IsRooted()) - SetTarget(hate_list.GetClosest(this)); - else - { - if(AItarget_check_timer->Check()) - { - if (IsFocused()) { - if (!target) { - SetTarget(hate_list.GetTop(this)); - } - } else { - if (!ImprovedTaunt()) - SetTarget(hate_list.GetTop(this)); - } - - } - } - - if (!target) - return; - - if (target->IsCorpse()) - { - RemoveFromHateList(this); - return; - } - -#ifdef BOTS - if (IsPet() && GetOwner()->IsBot() && target == GetOwner()) - { - // this blocks all pet attacks against owner..bot pet test (copied above check) - RemoveFromHateList(this); - return; - } -#endif //BOTS - - if(DivineAura()) - return; - - if(GetSpecialAbility(TETHER)) { - float tether_range = static_cast(GetSpecialAbilityParam(TETHER, 0)); - tether_range = tether_range > 0.0f ? tether_range * tether_range : pAggroRange * pAggroRange; - - if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > tether_range) { - GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH()); - } - } else if(GetSpecialAbility(LEASH)) { - float leash_range = static_cast(GetSpecialAbilityParam(LEASH, 0)); - leash_range = leash_range > 0.0f ? leash_range * leash_range : pAggroRange * pAggroRange; - - if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > leash_range) { - GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH()); - SetHP(GetMaxHP()); - BuffFadeAll(); - WipeHateList(); - return; - } - } - - StartEnrage(); - - bool is_combat_range = CombatRange(target); - - if (is_combat_range) - { - if (AImovement_timer->Check()) - { - SetRunAnimSpeed(0); - } - if(IsMoving()) - { - SetMoving(false); - moved=false; - SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); - SendPosition(); - tar_ndx =0; - } - - //casting checked above... - if(target && !IsStunned() && !IsMezzed() && GetAppearance() != eaDead && !IsMeleeDisabled()) { - - //we should check to see if they die mid-attacks, previous - //crap of checking target for null was not gunna cut it - - //try main hand first - if(attack_timer.Check()) { - if(IsNPC()) { - int16 n_atk = CastToNPC()->GetNumberOfAttacks(); - if(n_atk <= 1) { - Attack(target, 13); - } else { - for(int i = 0; i < n_atk; ++i) { - Attack(target, 13); - } - } - } else { - Attack(target, 13); - } - - if (target) { - //we use this random value in three comparisons with different - //thresholds, and if its truely random, then this should work - //out reasonably and will save us compute resources. - int32 RandRoll = MakeRandomInt(0, 99); - if ((CanThisClassDoubleAttack() || GetSpecialAbility(SPECATK_TRIPLE) - || GetSpecialAbility(SPECATK_QUAD)) - //check double attack, this is NOT the same rules that clients use... - && RandRoll < (GetLevel() + NPCDualAttackModifier)) { - Attack(target, 13); - // lets see if we can do a triple attack with the main hand - //pets are excluded from triple and quads... - if ((GetSpecialAbility(SPECATK_TRIPLE) || GetSpecialAbility(SPECATK_QUAD)) - && !IsPet() && RandRoll < (GetLevel() + NPCTripleAttackModifier)) { - Attack(target, 13); - // now lets check the quad attack - if (GetSpecialAbility(SPECATK_QUAD) - && RandRoll < (GetLevel() + NPCQuadAttackModifier)) { - Attack(target, 13); - } - } - } - } - - if (GetSpecialAbility(SPECATK_FLURRY)) { - int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0); - flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance); - - if (MakeRandomInt(0, 99) < flurry_chance) { - ExtraAttackOptions opts; - int cur = GetSpecialAbilityParam(SPECATK_FLURRY, 2); - if (cur > 0) - opts.damage_percent = cur / 100.0f; - - cur = GetSpecialAbilityParam(SPECATK_FLURRY, 3); - if (cur > 0) - opts.damage_flat = cur; - - cur = GetSpecialAbilityParam(SPECATK_FLURRY, 4); - if (cur > 0) - opts.armor_pen_percent = cur / 100.0f; - - cur = GetSpecialAbilityParam(SPECATK_FLURRY, 5); - if (cur > 0) - opts.armor_pen_flat = cur; - - cur = GetSpecialAbilityParam(SPECATK_FLURRY, 6); - if (cur > 0) - opts.crit_percent = cur / 100.0f; - - cur = GetSpecialAbilityParam(SPECATK_FLURRY, 7); - if (cur > 0) - opts.crit_flat = cur; - - Flurry(&opts); - } - } - - if (IsPet()) { - Mob *owner = GetOwner(); - if (owner) { - int16 flurry_chance = owner->aabonuses.PetFlurry + - owner->spellbonuses.PetFlurry + owner->itembonuses.PetFlurry; - if (flurry_chance && (MakeRandomInt(0, 99) < flurry_chance)) - Flurry(nullptr); - } - } - - if (GetSpecialAbility(SPECATK_RAMPAGE)) - { - int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0); - rampage_chance = rampage_chance > 0 ? rampage_chance : 20; - if(MakeRandomInt(0, 99) < rampage_chance) { - ExtraAttackOptions opts; - int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2); - if(cur > 0) { - opts.damage_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 3); - if(cur > 0) { - opts.damage_flat = cur; - } - - cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 4); - if(cur > 0) { - opts.armor_pen_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 5); - if(cur > 0) { - opts.armor_pen_flat = cur; - } - - cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 6); - if(cur > 0) { - opts.crit_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 7); - if(cur > 0) { - opts.crit_flat = cur; - } - Rampage(&opts); - } - } - - if (GetSpecialAbility(SPECATK_AREA_RAMPAGE)) - { - int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0); - rampage_chance = rampage_chance > 0 ? rampage_chance : 20; - if(MakeRandomInt(0, 99) < rampage_chance) { - ExtraAttackOptions opts; - int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2); - if(cur > 0) { - opts.damage_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 3); - if(cur > 0) { - opts.damage_flat = cur; - } - - cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 4); - if(cur > 0) { - opts.armor_pen_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 5); - if(cur > 0) { - opts.armor_pen_flat = cur; - } - - cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 6); - if(cur > 0) { - opts.crit_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 7); - if(cur > 0) { - opts.crit_flat = cur; - } - - AreaRampage(&opts); - } - } - } - - //now off hand - if (attack_dw_timer.Check() && CanThisClassDualWield()) - { - int myclass = GetClass(); - //can only dual wield without a weapon if your a monk - if(GetSpecialAbility(SPECATK_INNATE_DW) || (GetEquipment(MaterialSecondary) != 0 && GetLevel() > 29) || myclass == MONK || myclass == MONKGM) { - float DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel()) / 400.0f; - if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability) - { - Attack(target, 14); - if (CanThisClassDoubleAttack()) - { - int32 RandRoll = MakeRandomInt(0, 99); - if (RandRoll < (GetLevel() + 20)) - { - Attack(target, 14); - } - } - } - } - } - - //now special attacks (kick, etc) - if(IsNPC()) - CastToNPC()->DoClassAttacks(target); - } - AI_EngagedCastCheck(); - } //end is within combat range - else { - //we cannot reach our target... - //underwater stuff only works with water maps in the zone! - if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { - if(!zone->watermap->InLiquid(target->GetX(), target->GetY(), target->GetZ())) { - Mob *tar = hate_list.GetTop(this); - if(tar == target) { - WipeHateList(); - Heal(); - BuffFadeAll(); - AIwalking_timer->Start(100); - pLastFightingDelayMoving = Timer::GetCurrentTime(); - return; - } else if(tar != nullptr) { - SetTarget(tar); - return; - } - } - } - - // See if we can summon the mob to us - if (!HateSummon()) - { - //could not summon them, check ranged... - if(GetSpecialAbility(SPECATK_RANGED_ATK)) - doranged = true; - - // Now pursue - // TODO: Check here for another person on hate list with close hate value - if(AI_PursueCastCheck()){ - //we did something, so do not process movement. - } - else if (AImovement_timer->Check()) - { - if(!IsRooted()) { - mlog(AI__WAYPOINTS, "Pursuing %s while engaged.", target->GetName()); - if(!RuleB(Pathing, Aggro) || !zone->pathing) - CalculateNewPosition2(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed()); - else - { - bool WaypointChanged, NodeReached; - - VERTEX Goal = UpdatePath(target->GetX(), target->GetY(), target->GetZ(), - GetRunspeed(), WaypointChanged, NodeReached); - - if(WaypointChanged) - tar_ndx = 20; - - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); - } - - } - else if(IsMoving()) { - SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - moved=false; - - } - } - } - } - } - else - { - if(AIfeignremember_timer->Check()) { - // EverHood - 6/14/06 - // Improved Feign Death Memory - // check to see if any of our previous feigned targets have gotten up. - std::set::iterator RememberedCharID; - RememberedCharID = feign_memory_list.begin(); - while (RememberedCharID != feign_memory_list.end()) { - Client* remember_client = entity_list.GetClientByCharID(*RememberedCharID); - if (remember_client == nullptr) { - //they are gone now... - RememberedCharID = feign_memory_list.erase(RememberedCharID); - } else if (!remember_client->GetFeigned()) { - AddToHateList(remember_client->CastToMob(),1); - RememberedCharID = feign_memory_list.erase(RememberedCharID); - break; - } else { - //they are still feigned, carry on... - ++RememberedCharID; - } - } - } - if (AI_IdleCastCheck()) - { - //we processed a spell action, so do nothing else. - } - else if (AIscanarea_timer->Check()) - { - /* - * This is where NPCs look around to see if they want to attack anybody. - * - * if REVERSE_AGGRO is enabled, then this timer is disabled unless they - * have the npc_aggro flag on them, and aggro against clients is checked - * by the clients. - * - */ - - Mob* tmptar = entity_list.AICheckCloseAggro(this, GetAggroRange(), GetAssistRange()); - if (tmptar) - AddToHateList(tmptar); - } - else if (AImovement_timer->Check() && !IsRooted()) - { - SetRunAnimSpeed(0); - if (IsPet()) - { - // we're a pet, do as we're told - switch (pStandingPetOrder) - { - case SPO_Follow: - { - - Mob* owner = GetOwner(); - if(owner == nullptr) - break; - - //if(owner->IsClient()) - // printf("Pet start pos: (%f, %f, %f)\n", GetX(), GetY(), GetZ()); - - float dist = DistNoRoot(*owner); - if (dist >= 400) - { - float speed = GetWalkspeed(); - if (dist >= 5625) - speed = GetRunspeed(); - CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); - } - else - { - if(moved) - { - moved=false; - SetMoving(false); - SendPosition(); - } - } - - /* - //fix up Z - float zdiff = GetZ() - owner->GetZ(); - if(zdiff < 0) - zdiff = 0 - zdiff; - if(zdiff > 2.0f) { - SendTo(GetX(), GetY(), owner->GetZ()); - SendPosition(); - } - - if(owner->IsClient()) - printf("Pet pos: (%f, %f, %f)\n", GetX(), GetY(), GetZ()); - */ - - break; - } - case SPO_Sit: - { - SetAppearance(eaSitting, false); - break; - } - case SPO_Guard: - { - //only NPCs can guard stuff. (forced by where the guard movement code is in the AI) - if(IsNPC()) { - CastToNPC()->NextGuardPosition(); - } - break; - } - } - } - else if (GetFollowID()) - { - Mob* follow = entity_list.GetMob(GetFollowID()); - if (!follow) SetFollowID(0); - else - { - float dist2 = DistNoRoot(*follow); - int followdist = GetFollowDistance(); - - if (dist2 >= followdist) // Default follow distance is 100 - { - float speed = GetWalkspeed(); - if (dist2 >= followdist + 150) - speed = GetRunspeed(); - CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); - } - else - { - if(moved) - { - SendPosition(); - moved=false; - SetMoving(false); - } - } - } - } - else //not a pet, and not following somebody... - { - // dont move till a bit after you last fought - if (pLastFightingDelayMoving < Timer::GetCurrentTime()) - { - if (this->IsClient()) - { - // LD timer expired, drop out of world - if (this->CastToClient()->IsLD()) - this->CastToClient()->Disconnect(); - return; - } - - if(IsNPC()) - { - if(RuleB(NPC, SmartLastFightingDelayMoving) && !feign_memory_list.empty()) - { - minLastFightingDelayMoving = 0; - maxLastFightingDelayMoving = 0; - } - CastToNPC()->AI_DoMovement(); - } - } - - } - } // else if (AImovement_timer->Check()) - } - - //Do Ranged attack here - if(doranged) - { - int attacks = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0); - attacks = attacks > 0 ? attacks : 1; - for(int i = 0; i < attacks; ++i) { - RangedAttack(target); - } - } -} - -void NPC::AI_DoMovement() { - float walksp = GetMovespeed(); - if(walksp <= 0.0f) - return; //this is idle movement at walk speed, and we are unable to walk right now. - - if (roambox_distance > 0) { - if ( - roambox_movingto_x > roambox_max_x - || roambox_movingto_x < roambox_min_x - || roambox_movingto_y > roambox_max_y - || roambox_movingto_y < roambox_min_y - ) - { - float movedist = roambox_distance*roambox_distance; - float movex = MakeRandomFloat(0, movedist); - float movey = movedist - movex; - movex = sqrtf(movex); - movey = sqrtf(movey); - movex *= MakeRandomInt(0, 1) ? 1 : -1; - movey *= MakeRandomInt(0, 1) ? 1 : -1; - roambox_movingto_x = GetX() + movex; - roambox_movingto_y = GetY() + movey; - //Try to calculate new coord using distance. - if (roambox_movingto_x > roambox_max_x || roambox_movingto_x < roambox_min_x) - roambox_movingto_x -= movex * 2; - if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y) - roambox_movingto_y -= movey * 2; - //New coord is still invalid, ignore distance and just pick a new random coord. - //If we're here we may have a roambox where one side is shorter than the specified distance. Commons, Wkarana, etc. - if (roambox_movingto_x > roambox_max_x || roambox_movingto_x < roambox_min_x) - roambox_movingto_x = MakeRandomFloat(roambox_min_x+1,roambox_max_x-1); - if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y) - roambox_movingto_y = MakeRandomFloat(roambox_min_y+1,roambox_max_y-1); - } - - mlog(AI__WAYPOINTS, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)", - roambox_distance, roambox_min_x, roambox_max_x, roambox_min_y, roambox_max_y, roambox_movingto_x, roambox_movingto_y); - if (!CalculateNewPosition2(roambox_movingto_x, roambox_movingto_y, GetZ(), walksp, true)) - { - roambox_movingto_x = roambox_max_x + 1; // force update - pLastFightingDelayMoving = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay); - SetMoving(false); - SendPosition(); // makes mobs stop clientside - } - } - else if (roamer) - { - if (AIwalking_timer->Check()) - { - movetimercompleted=true; - AIwalking_timer->Disable(); - } - - - int16 gridno = CastToNPC()->GetGrid(); - - if (gridno > 0 || cur_wp==-2) { - if (movetimercompleted==true) { // time to pause at wp is over - - int32 spawn_id = this->GetSpawnPointID(); - LinkedListIterator iterator(zone->spawn2_list); - iterator.Reset(); - Spawn2 *found_spawn = nullptr; - - while(iterator.MoreElements()) - { - Spawn2* cur = iterator.GetData(); - iterator.Advance(); - if(cur->GetID() == spawn_id) - { - found_spawn = cur; - break; - } - } - - if (wandertype == 4 && cur_wp == CastToNPC()->GetMaxWp()) { - CastToNPC()->Depop(true); //depop and resart spawn timer - if(found_spawn) - found_spawn->SetNPCPointerNull(); - } - else if (wandertype == 6 && cur_wp == CastToNPC()->GetMaxWp()) { - CastToNPC()->Depop(false);//depop without spawn timer - if(found_spawn) - found_spawn->SetNPCPointerNull(); - } - else { - movetimercompleted=false; - - mlog(QUESTS__PATHING, "We are departing waypoint %d.", cur_wp); - - //if we were under quest control (with no grid), we are done now.. - if(cur_wp == -2) { - mlog(QUESTS__PATHING, "Non-grid quest mob has reached its quest ordered waypoint. Leaving pathing mode."); - roamer = false; - cur_wp = 0; - } - - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); - - entity_list.OpenDoorsNear(CastToNPC()); - - if(!DistractedFromGrid) { - //kick off event_waypoint depart - char temp[16]; - sprintf(temp, "%d", cur_wp); - parse->EventNPC(EVENT_WAYPOINT_DEPART, CastToNPC(), nullptr, temp, 0); - - //setup our next waypoint, if we are still on our normal grid - //remember that the quest event above could have done anything it wanted with our grid - if(gridno > 0) { - CastToNPC()->CalculateNewWaypoint(); - } - } - else { - DistractedFromGrid = false; - } - } - } // endif (movetimercompleted==true) - else if (!(AIwalking_timer->Enabled())) - { // currently moving - if (cur_wp_x == GetX() && cur_wp_y == GetY()) - { // are we there yet? then stop - mlog(AI__WAYPOINTS, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid()); - SetWaypointPause(); - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); - SetMoving(false); - if (cur_wp_heading >= 0.0) { - SetHeading(cur_wp_heading); - } - SendPosition(); - - //kick off event_waypoint arrive - char temp[16]; - sprintf(temp, "%d", cur_wp); - parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0); - - // wipe feign memory since we reached our first waypoint - if(cur_wp == 1) - ClearFeignMemory(); - } - else - { // not at waypoint yet, so keep moving - if(!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0)) - CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, walksp, true); - else - { - bool WaypointChanged; - bool NodeReached; - VERTEX Goal = UpdatePath(cur_wp_x, cur_wp_y, cur_wp_z, walksp, WaypointChanged, NodeReached); - if(WaypointChanged) - tar_ndx = 20; - - if(NodeReached) - entity_list.OpenDoorsNear(CastToNPC()); - - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, walksp, true); - } - - } - } - } // endif (gridno > 0) -// handle new quest grid command processing - else if (gridno < 0) - { // this mob is under quest control - if (movetimercompleted==true) - { // time to pause has ended - SetGrid( 0 - GetGrid()); // revert to AI control - mlog(QUESTS__PATHING, "Quest pathing is finished. Resuming on grid %d", GetGrid()); - - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); - - CalculateNewWaypoint(); - } - } - - } - else if (IsGuarding()) - { - bool CP2Moved; - if(!RuleB(Pathing, Guard) || !zone->pathing) - CP2Moved = CalculateNewPosition2(guard_x, guard_y, guard_z, walksp); - else - { - if(!((x_pos == guard_x) && (y_pos == guard_y) && (z_pos == guard_z))) - { - bool WaypointChanged, NodeReached; - VERTEX Goal = UpdatePath(guard_x, guard_y, guard_z, walksp, WaypointChanged, NodeReached); - if(WaypointChanged) - tar_ndx = 20; - - if(NodeReached) - entity_list.OpenDoorsNear(CastToNPC()); - - CP2Moved = CalculateNewPosition2(Goal.x, Goal.y, Goal.z, walksp); - } - else - CP2Moved = false; - - } - if (!CP2Moved) - { - if(moved) { - mlog(AI__WAYPOINTS, "Reached guard point (%.3f,%.3f,%.3f)", guard_x, guard_y, guard_z); - ClearFeignMemory(); - moved=false; - SetMoving(false); - if (GetTarget() == nullptr || DistNoRoot(*GetTarget()) >= 5*5 ) - { - SetHeading(guard_heading); - } else { - FaceTarget(GetTarget()); - } - SendPosition(); - SetAppearance(GetGuardPointAnim()); - } - } - } -} - -// Note: Mob that caused this may not get added to the hate list until after this function call completes -void Mob::AI_Event_Engaged(Mob* attacker, bool iYellForHelp) { - if (!IsAIControlled()) - return; - - if(GetAppearance() != eaStanding) - { - SetAppearance(eaStanding); - } - - if (iYellForHelp) { - if(IsPet()) { - GetOwner()->AI_Event_Engaged(attacker, iYellForHelp); - } else { - entity_list.AIYellForHelp(this, attacker); - } - } - - if(IsNPC()) - { - if(CastToNPC()->GetGrid() > 0) - { - DistractedFromGrid = true; - } - if(attacker && !attacker->IsCorpse()) - { - //Because sometimes the AIYellForHelp triggers another engaged and then immediately a not engaged - //if the target dies before it goes off - if(attacker->GetHP() > 0) - { - if(!CastToNPC()->GetCombatEvent() && GetHP() > 0) - { - parse->EventNPC(EVENT_COMBAT, CastToNPC(), attacker, "1", 0); - uint16 emoteid = GetEmoteID(); - if(emoteid != 0) - CastToNPC()->DoNPCEmote(ENTERCOMBAT,emoteid); - CastToNPC()->SetCombatEvent(true); - } - } - } - } -} - -// Note: Hate list may not be actually clear until after this function call completes -void Mob::AI_Event_NoLongerEngaged() { - if (!IsAIControlled()) - return; - this->AIwalking_timer->Start(RandomTimer(3000,20000)); - pLastFightingDelayMoving = Timer::GetCurrentTime(); - if (minLastFightingDelayMoving == maxLastFightingDelayMoving) - pLastFightingDelayMoving += minLastFightingDelayMoving; - else - pLastFightingDelayMoving += MakeRandomInt(minLastFightingDelayMoving, maxLastFightingDelayMoving); - // EverHood - So mobs don't keep running as a ghost until AIwalking_timer fires - // if they were moving prior to losing all hate - if(IsMoving()){ - SetRunAnimSpeed(0); - SetMoving(false); - SendPosition(); - } - ClearRampage(); - - if(IsNPC()) - { - if(CastToNPC()->GetCombatEvent() && GetHP() > 0) - { - if(entity_list.GetNPCByID(this->GetID())) - { - uint16 emoteid = CastToNPC()->GetEmoteID(); - parse->EventNPC(EVENT_COMBAT, CastToNPC(), nullptr, "0", 0); - if(emoteid != 0) - CastToNPC()->DoNPCEmote(LEAVECOMBAT,emoteid); - CastToNPC()->SetCombatEvent(false); - } - } - } -} - -//this gets called from InterruptSpell() for failure or SpellFinished() for success -void NPC::AI_Event_SpellCastFinished(bool iCastSucceeded, uint8 slot) { - if (slot == 1) { - uint32 recovery_time = 0; - if (iCastSucceeded) { - if (casting_spell_AIindex < AIspells.size()) { - recovery_time += spells[AIspells[casting_spell_AIindex].spellid].recovery_time; - if (AIspells[casting_spell_AIindex].recast_delay >= 0) - { - if (AIspells[casting_spell_AIindex].recast_delay < 10000) - AIspells[casting_spell_AIindex].time_cancast = Timer::GetCurrentTime() + (AIspells[casting_spell_AIindex].recast_delay*1000); - } - else - AIspells[casting_spell_AIindex].time_cancast = Timer::GetCurrentTime() + spells[AIspells[casting_spell_AIindex].spellid].recast_time; - } - if (recovery_time < AIautocastspell_timer->GetSetAtTrigger()) - recovery_time = AIautocastspell_timer->GetSetAtTrigger(); - AIautocastspell_timer->Start(recovery_time, false); - } - else - AIautocastspell_timer->Start(800, false); - casting_spell_AIindex = AIspells.size(); - } -} - - -bool NPC::AI_EngagedCastCheck() { - if (AIautocastspell_timer->Check(false)) { - AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - - mlog(AI__SPELLS, "Engaged autocast check triggered. Trying to cast healing spells then maybe offensive spells."); - Shout("KAYEN"); - // try casting a heal or gate - if (!AICastSpell(this, 100, SpellType_Heal | SpellType_Escape | SpellType_InCombatBuff)) { - // try casting a heal on nearby - if (!entity_list.AICheckCloseBeneficialSpells(this, 25, MobAISpellRange, SpellType_Heal)) { - //nobody to heal, try some detrimental spells. - if(!AICastSpell(GetTarget(), 20, SpellType_Nuke | SpellType_Lifetap | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff | SpellType_Charm | SpellType_Root)) { - //no spell to cast, try again soon. - AIautocastspell_timer->Start(RandomTimer(500, 1000), false); - } - } - } - return(true); - } - - return(false); -} - -bool NPC::AI_PursueCastCheck() { - if (AIautocastspell_timer->Check(false)) { - AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - - mlog(AI__SPELLS, "Engaged (pursuing) autocast check triggered. Trying to cast offensive spells."); - if(!AICastSpell(GetTarget(), 90, SpellType_Root | SpellType_Nuke | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff)) { - //no spell cast, try again soon. - AIautocastspell_timer->Start(RandomTimer(500, 2000), false); - } //else, spell casting finishing will reset the timer. - return(true); - } - return(false); -} - -bool NPC::AI_IdleCastCheck() { - if (AIautocastspell_timer->Check(false)) { -#if MobAI_DEBUG_Spells >= 25 - std::cout << "Non-Engaged autocast check triggered: " << this->GetName() << std::endl; -#endif - AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - if (!AICastSpell(this, 100, SpellType_Heal | SpellType_Buff | SpellType_Pet)) { - if(!entity_list.AICheckCloseBeneficialSpells(this, 33, MobAISpellRange, SpellType_Heal | SpellType_Buff)) { - //if we didnt cast any spells, our autocast timer just resets to the - //last duration it was set to... try to put up a more reasonable timer... - AIautocastspell_timer->Start(RandomTimer(1000, 5000), false); - } //else, spell casting finishing will reset the timer. - } //else, spell casting finishing will reset the timer. - return(true); - } - return(false); -} - -void Mob::StartEnrage() -{ - // dont continue if already enraged - if (bEnraged) - return; - - if(!GetSpecialAbility(SPECATK_ENRAGE)) - return; - - int hp_ratio = GetSpecialAbilityParam(SPECATK_ENRAGE, 0); - hp_ratio = hp_ratio > 0 ? hp_ratio : RuleI(NPC, StartEnrageValue); - if(GetHPRatio() > static_cast(hp_ratio)) { - return; - } - - if(RuleB(NPC, LiveLikeEnrage) && !((IsPet() && !IsCharmed() && GetOwner() && GetOwner()->IsClient()) || - (CastToNPC()->GetSwarmOwner() && entity_list.GetMob(CastToNPC()->GetSwarmOwner())->IsClient()))) { - return; - } - - Timer *timer = GetSpecialAbilityTimer(SPECATK_ENRAGE); - if (timer && !timer->Check()) - return; - - int enraged_duration = GetSpecialAbilityParam(SPECATK_ENRAGE, 1); - enraged_duration = enraged_duration > 0 ? enraged_duration : EnragedDurationTimer; - StartSpecialAbilityTimer(SPECATK_ENRAGE, enraged_duration); - - // start the timer. need to call IsEnraged frequently since we dont have callback timers :-/ - bEnraged = true; - entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_START, GetCleanName()); -} - -void Mob::ProcessEnrage(){ - if(IsEnraged()){ - Timer *timer = GetSpecialAbilityTimer(SPECATK_ENRAGE); - if(timer && timer->Check()){ - entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_END, GetCleanName()); - - int enraged_cooldown = GetSpecialAbilityParam(SPECATK_ENRAGE, 2); - enraged_cooldown = enraged_cooldown > 0 ? enraged_cooldown : EnragedTimer; - StartSpecialAbilityTimer(SPECATK_ENRAGE, enraged_cooldown); - bEnraged = false; - } - } -} - -bool Mob::IsEnraged() -{ - return bEnraged; -} - -bool Mob::Flurry(ExtraAttackOptions *opts) -{ - // this is wrong, flurry is extra attacks on the current target - Mob *target = GetTarget(); - if (target) { - if (!IsPet()) { - entity_list.MessageClose_StringID(this, true, 200, MT_NPCFlurry, NPC_FLURRY, GetCleanName(), target->GetCleanName()); - } else { - entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, NPC_FLURRY, GetCleanName(), target->GetCleanName()); - } - - int num_attacks = GetSpecialAbilityParam(SPECATK_FLURRY, 1); - num_attacks = num_attacks > 0 ? num_attacks : RuleI(Combat, MaxFlurryHits); - for (int i = 0; i < num_attacks; i++) - Attack(target, 13, false, false, false, opts); - } - return true; -} - -bool Mob::AddRampage(Mob *mob) -{ - if (!mob) - return false; - - if (!GetSpecialAbility(SPECATK_RAMPAGE)) - return false; - - for (int i = 0; i < RampageArray.size(); i++) { - // if Entity ID is already on the list don't add it again - if (mob->GetID() == RampageArray[i]) - return false; - } - RampageArray.push_back(mob->GetID()); - return true; -} - -void Mob::ClearRampage() -{ - RampageArray.clear(); -} - -bool Mob::Rampage(ExtraAttackOptions *opts) -{ - int index_hit = 0; - if (!IsPet()) - entity_list.MessageClose_StringID(this, true, 200, MT_NPCRampage, NPC_RAMPAGE, GetCleanName()); - else - entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, NPC_RAMPAGE, GetCleanName()); - - int rampage_targets = GetSpecialAbilityParam(SPECATK_RAMPAGE, 1); - if (rampage_targets == 0) // if set to 0 or not set in the DB - rampage_targets = RuleI(Combat, DefaultRampageTargets); - if (rampage_targets > RuleI(Combat, MaxRampageTargets)) - rampage_targets = RuleI(Combat, MaxRampageTargets); - for (int i = 0; i < RampageArray.size(); i++) { - if (index_hit >= rampage_targets) - break; - // range is important - Mob *m_target = entity_list.GetMob(RampageArray[i]); - if (m_target) { - if (m_target == GetTarget()) - continue; - if (CombatRange(m_target)) { - Attack(m_target, 13, false, false, false, opts); - index_hit++; - } - } - } - - if (RuleB(Combat, RampageHitsTarget) && index_hit < rampage_targets) - Attack(GetTarget(), 13, false, false, false, opts); - - return true; -} - -void Mob::AreaRampage(ExtraAttackOptions *opts) -{ - int index_hit = 0; - if (!IsPet()) { // do not know every pet AA so thought it safer to add this - entity_list.MessageClose_StringID(this, true, 200, MT_NPCRampage, AE_RAMPAGE, GetCleanName()); - } else { - entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, AE_RAMPAGE, GetCleanName()); - } - - int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1); - rampage_targets = rampage_targets > 0 ? rampage_targets : 1; - index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts); - - if(index_hit == 0) { - Attack(GetTarget(), 13, false, false, false, opts); - } -} - -uint32 Mob::GetLevelCon(uint8 mylevel, uint8 iOtherLevel) { - int16 diff = iOtherLevel - mylevel; - uint32 conlevel=0; - - if (diff == 0) - return CON_WHITE; - else if (diff >= 1 && diff <= 2) - return CON_YELLOW; - else if (diff >= 3) - return CON_RED; - - if (mylevel <= 8) - { - if (diff <= -4) - conlevel = CON_GREEN; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 9) - { - if (diff <= -6) - conlevel = CON_GREEN; - else if (diff <= -4) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 13) - { - if (diff <= -7) - conlevel = CON_GREEN; - else if (diff <= -5) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 15) - { - if (diff <= -7) - conlevel = CON_GREEN; - else if (diff <= -5) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 17) - { - if (diff <= -8) - conlevel = CON_GREEN; - else if (diff <= -6) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 21) - { - if (diff <= -9) - conlevel = CON_GREEN; - else if (diff <= -7) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 25) - { - if (diff <= -10) - conlevel = CON_GREEN; - else if (diff <= -8) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 29) - { - if (diff <= -11) - conlevel = CON_GREEN; - else if (diff <= -9) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 31) - { - if (diff <= -12) - conlevel = CON_GREEN; - else if (diff <= -9) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 33) - { - if (diff <= -13) - conlevel = CON_GREEN; - else if (diff <= -10) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 37) - { - if (diff <= -14) - conlevel = CON_GREEN; - else if (diff <= -11) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 41) - { - if (diff <= -16) - conlevel = CON_GREEN; - else if (diff <= -12) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 45) - { - if (diff <= -17) - conlevel = CON_GREEN; - else if (diff <= -13) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 49) - { - if (diff <= -18) - conlevel = CON_GREEN; - else if (diff <= -14) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 53) - { - if (diff <= -19) - conlevel = CON_GREEN; - else if (diff <= -15) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 55) - { - if (diff <= -20) - conlevel = CON_GREEN; - else if (diff <= -15) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else - { - if (diff <= -21) - conlevel = CON_GREEN; - else if (diff <= -16) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - return conlevel; -} - -void NPC::CheckSignal() { - if (!signal_q.empty()) { - int signal_id = signal_q.front(); - signal_q.pop_front(); - char buf[32]; - snprintf(buf, 31, "%d", signal_id); - buf[31] = '\0'; - parse->EventNPC(EVENT_SIGNAL, this, nullptr, buf, 0); - } -} - - - -/* -alter table npc_types drop column usedspells; -alter table npc_types add column npc_spells_id int(11) unsigned not null default 0 after merchant_id; -Create Table npc_spells ( - id int(11) unsigned not null auto_increment primary key, - name tinytext, - parent_list int(11) unsigned not null default 0, - attack_proc smallint(5) not null default -1, - proc_chance tinyint(3) not null default 3 - ); -create table npc_spells_entries ( - id int(11) unsigned not null auto_increment primary key, - npc_spells_id int(11) not null, - spellid smallint(5) not null default 0, - type smallint(5) unsigned not null default 0, - minlevel tinyint(3) unsigned not null default 0, - maxlevel tinyint(3) unsigned not null default 255, - manacost smallint(5) not null default '-1', - recast_delay int(11) not null default '-1', - priority smallint(5) not null default 0, - index npc_spells_id (npc_spells_id) - ); -*/ - -bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID); -bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSpellEffectID, int32 base, int32 limit, int32 max); -bool Compare_AI_Spells(AISpells_Struct i, AISpells_Struct j); - -bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { - // ok, this function should load the list, and the parent list then shove them into the struct and sort - npc_spells_id = iDBSpellsID; - AIspells.clear(); - if (iDBSpellsID == 0) { - AIautocastspell_timer->Disable(); - return false; - } - DBnpcspells_Struct* spell_list = database.GetNPCSpells(iDBSpellsID); - if (!spell_list) { - AIautocastspell_timer->Disable(); - return false; - } - DBnpcspells_Struct* parentlist = database.GetNPCSpells(spell_list->parent_list); - uint32 i; -#if MobAI_DEBUG_Spells >= 10 - std::cout << "Loading NPCSpells onto " << this->GetName() << ": dbspellsid=" << iDBSpellsID; - if (spell_list) { - std::cout << " (found, " << spell_list->numentries << "), parentlist=" << spell_list->parent_list; - if (spell_list->parent_list) { - if (parentlist) { - std::cout << " (found, " << parentlist->numentries << ")"; - } - else - std::cout << " (not found)"; - } - } - else - std::cout << " (not found)"; - std::cout << std::endl; -#endif - int16 attack_proc_spell = -1; - int8 proc_chance = 3; - if (parentlist) { - attack_proc_spell = parentlist->attack_proc; - proc_chance = parentlist->proc_chance; - for (i=0; inumentries; i++) { - if (GetLevel() >= parentlist->entries[i].minlevel && GetLevel() <= parentlist->entries[i].maxlevel && parentlist->entries[i].spellid > 0) { - if (!IsSpellInList(spell_list, parentlist->entries[i].spellid)) - { - AddSpellToNPCList(parentlist->entries[i].priority, - parentlist->entries[i].spellid, parentlist->entries[i].type, - parentlist->entries[i].manacost, parentlist->entries[i].recast_delay, - parentlist->entries[i].resist_adjust); - } - } - } - } - if (spell_list->attack_proc >= 0) { - attack_proc_spell = spell_list->attack_proc; - proc_chance = spell_list->proc_chance; - } - for (i=0; inumentries; i++) { - if (GetLevel() >= spell_list->entries[i].minlevel && GetLevel() <= spell_list->entries[i].maxlevel && spell_list->entries[i].spellid > 0) { - AddSpellToNPCList(spell_list->entries[i].priority, - spell_list->entries[i].spellid, spell_list->entries[i].type, - spell_list->entries[i].manacost, spell_list->entries[i].recast_delay, - spell_list->entries[i].resist_adjust); - } - } - std::sort(AIspells.begin(), AIspells.end(), Compare_AI_Spells); - - if (attack_proc_spell > 0) - AddProcToWeapon(attack_proc_spell, true, proc_chance); - - if (AIspells.size() == 0) - AIautocastspell_timer->Disable(); - else - AIautocastspell_timer->Trigger(); - return true; -} - -bool NPC::AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID) { - - npc_spells_effects_id = iDBSpellsEffectsID; - AIspellsEffects.clear(); - - if (iDBSpellsEffectsID == 0) - return false; - - DBnpcspellseffects_Struct* spell_effects_list = database.GetNPCSpellsEffects(iDBSpellsEffectsID); - - if (!spell_effects_list) { - return false; - } - - DBnpcspellseffects_Struct* parentlist = database.GetNPCSpellsEffects(spell_effects_list->parent_list); - - uint32 i; -#if MobAI_DEBUG_Spells >= 10 - std::cout << "Loading NPCSpellsEffects onto " << this->GetName() << ": dbspellseffectsid=" << iDBSpellsEffectsID; - if (spell_effects_list) { - std::cout << " (found, " << spell_effects_list->numentries << "), parentlist=" << spell_effects)list->parent_list; - if (spell_effects_list->parent_list) { - if (parentlist) { - std::cout << " (found, " << parentlist->numentries << ")"; - } - else - std::cout << " (not found)"; - } - } - else - std::cout << " (not found)"; - std::cout << std::endl; -#endif - - if (parentlist) { - for (i=0; inumentries; i++) { - if (GetLevel() >= parentlist->entries[i].minlevel && GetLevel() <= parentlist->entries[i].maxlevel && parentlist->entries[i].spelleffectid > 0) { - if (!IsSpellEffectInList(spell_effects_list, parentlist->entries[i].spelleffectid, parentlist->entries[i].base, - parentlist->entries[i].limit, parentlist->entries[i].max)) - { - AddSpellEffectToNPCList(parentlist->entries[i].spelleffectid, - parentlist->entries[i].base, parentlist->entries[i].limit, - parentlist->entries[i].max); - } - } - } - } - - for (i=0; inumentries; i++) { - if (GetLevel() >= spell_effects_list->entries[i].minlevel && GetLevel() <= spell_effects_list->entries[i].maxlevel && spell_effects_list->entries[i].spelleffectid > 0) { - AddSpellEffectToNPCList(spell_effects_list->entries[i].spelleffectid, - spell_effects_list->entries[i].base, spell_effects_list->entries[i].limit, - spell_effects_list->entries[i].max); - } - } - - return true; -} - -void NPC::ApplyAISpellEffects(StatBonuses* newbon) -{ - if (!AI_HasSpellsEffects()) - return; - - - - for(int i=0; i < AIspellsEffects.size(); i++) - { - Shout("ApplyAISpellEffects %i %i %i %i", AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); - ApplySpellsBonuses(0, 0, newbon, 0, false, 0,-1, - true, AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); - } - - return; -} - -// adds a spell to the list, taking into account priority and resorting list as needed. -void NPC::AddSpellEffectToNPCList(uint16 iSpellEffectID, int32 base, int32 limit, int32 max) -{ - - if(!iSpellEffectID) - return; - - - HasAISpellEffects = true; - AISpellsEffects_Struct t; - - t.spelleffectid = iSpellEffectID; - t.base = base; - t.limit = limit; - t.max = max; - Shout("AddSpellEffectToNPCList %i %i %i %i", iSpellEffectID,base, limit, max ); - AIspellsEffects.push_back(t); -} - -bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSpellEffectID, int32 base, int32 limit, int32 max) { - for (uint32 i=0; i < spelleffect_list->numentries; i++) { - if (spelleffect_list->entries[i].spelleffectid == iSpellEffectID && spelleffect_list->entries[i].base == base - && spelleffect_list->entries[i].limit == limit && spelleffect_list->entries[i].max == max) - return true; - } - return false; -} - -bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID) { - for (uint32 i=0; i < spell_list->numentries; i++) { - if (spell_list->entries[i].spellid == iSpellID) - return true; - } - return false; -} - -bool Compare_AI_Spells(AISpells_Struct i, AISpells_Struct j) -{ - return(i.priority > j.priority); -} - -// adds a spell to the list, taking into account priority and resorting list as needed. -void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint16 iType, - int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust) -{ - - if(!IsValidSpell(iSpellID)) - return; - - HasAISpell = true; - AISpells_Struct t; - - t.priority = iPriority; - t.spellid = iSpellID; - t.type = iType; - t.manacost = iManaCost; - t.recast_delay = iRecastDelay; - t.time_cancast = 0; - t.resist_adjust = iResistAdjust; - - AIspells.push_back(t); -} - -void NPC::RemoveSpellFromNPCList(int16 spell_id) -{ - std::vector::iterator iter = AIspells.begin(); - while(iter != AIspells.end()) - { - if((*iter).spellid == spell_id) - { - iter = AIspells.erase(iter); - continue; - } - ++iter; - } -} - -void NPC::AISpellsList(Client *c) -{ - if (!c) - return; - - for (std::vector::iterator it = AIspells.begin(); it != AIspells.end(); ++it) - c->Message(0, "%s (%d): Type %d, Priority %d", - spells[it->spellid].name, it->spellid, it->type, it->priority); - - return; -} - -DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { - if (iDBSpellsID == 0) - return 0; - - if (!npc_spells_cache) { - npc_spells_maxid = GetMaxNPCSpellsID(); - npc_spells_cache = new DBnpcspells_Struct*[npc_spells_maxid+1]; - npc_spells_loadtried = new bool[npc_spells_maxid+1]; - for (uint32 i=0; i<=npc_spells_maxid; i++) { - npc_spells_cache[i] = 0; - npc_spells_loadtried[i] = false; - } - } - - if (iDBSpellsID > npc_spells_maxid) - return 0; - if (npc_spells_cache[iDBSpellsID]) { // it's in the cache, easy =) - return npc_spells_cache[iDBSpellsID]; - } - - else if (!npc_spells_loadtried[iDBSpellsID]) { // no reason to ask the DB again if we have failed once already - npc_spells_loadtried[iDBSpellsID] = true; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list, attack_proc, proc_chance from npc_spells where id=%d", iDBSpellsID), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 tmpparent_list = atoi(row[1]); - int16 tmpattack_proc = atoi(row[2]); - uint8 tmpproc_chance = atoi(row[3]); - mysql_free_result(result); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT spellid, type, minlevel, maxlevel, manacost, recast_delay, priority, resist_adjust from npc_spells_entries where npc_spells_id=%d ORDER BY minlevel", iDBSpellsID), errbuf, &result)) { - safe_delete_array(query); - uint32 tmpSize = sizeof(DBnpcspells_Struct) + (sizeof(DBnpcspells_entries_Struct) * mysql_num_rows(result)); - npc_spells_cache[iDBSpellsID] = (DBnpcspells_Struct*) new uchar[tmpSize]; - memset(npc_spells_cache[iDBSpellsID], 0, tmpSize); - npc_spells_cache[iDBSpellsID]->parent_list = tmpparent_list; - npc_spells_cache[iDBSpellsID]->attack_proc = tmpattack_proc; - npc_spells_cache[iDBSpellsID]->proc_chance = tmpproc_chance; - npc_spells_cache[iDBSpellsID]->numentries = mysql_num_rows(result); - int j = 0; - while ((row = mysql_fetch_row(result))) { - int spell_id = atoi(row[0]); - npc_spells_cache[iDBSpellsID]->entries[j].spellid = spell_id; - npc_spells_cache[iDBSpellsID]->entries[j].type = atoi(row[1]); - npc_spells_cache[iDBSpellsID]->entries[j].minlevel = atoi(row[2]); - npc_spells_cache[iDBSpellsID]->entries[j].maxlevel = atoi(row[3]); - npc_spells_cache[iDBSpellsID]->entries[j].manacost = atoi(row[4]); - npc_spells_cache[iDBSpellsID]->entries[j].recast_delay = atoi(row[5]); - npc_spells_cache[iDBSpellsID]->entries[j].priority = atoi(row[6]); - if(row[7]) - { - npc_spells_cache[iDBSpellsID]->entries[j].resist_adjust = atoi(row[7]); - } - else - { - if(IsValidSpell(spell_id)) - { - npc_spells_cache[iDBSpellsID]->entries[j].resist_adjust = spells[spell_id].ResistDiff; - } - } - j++; - } - mysql_free_result(result); - return npc_spells_cache[iDBSpellsID]; - } - else { - std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - } - else { - mysql_free_result(result); - } - } - else { - std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - - return 0; - } - return 0; -} - -uint32 ZoneDatabase::GetMaxNPCSpellsID() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id) from npc_spells"), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 ret = 0; - if (row[0]) - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetMaxNPCSpellsID query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - - return 0; -} - -DBnpcspellseffects_Struct* ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEffectsID) { - if (iDBSpellsEffectsID == 0) - return 0; - - if (!npc_spellseffects_cache) { - npc_spellseffects_maxid = GetMaxNPCSpellsEffectsID(); - npc_spellseffects_cache = new DBnpcspellseffects_Struct*[npc_spellseffects_maxid+1]; - npc_spellseffects_loadtried = new bool[npc_spellseffects_maxid+1]; - for (uint32 i=0; i<=npc_spellseffects_maxid; i++) { - npc_spellseffects_cache[i] = 0; - npc_spellseffects_loadtried[i] = false; - } - } - - if (iDBSpellsEffectsID > npc_spellseffects_maxid) - return 0; - if (npc_spellseffects_cache[iDBSpellsEffectsID]) { // it's in the cache, easy =) - return npc_spellseffects_cache[iDBSpellsEffectsID]; - } - - else if (!npc_spellseffects_loadtried[iDBSpellsEffectsID]) { // no reason to ask the DB again if we have failed once already - npc_spellseffects_loadtried[iDBSpellsEffectsID] = true; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list from npc_spells_effects where id=%d", iDBSpellsEffectsID), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 tmpparent_list = atoi(row[1]); - mysql_free_result(result); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT spell_effect_id, minlevel, maxlevel,se_base, se_limit, se_max from npc_spells_effects_entries where npc_spells_effects_id=%d ORDER BY minlevel", iDBSpellsEffectsID), errbuf, &result)) { - safe_delete_array(query); - uint32 tmpSize = sizeof(DBnpcspellseffects_Struct) + (sizeof(DBnpcspellseffects_Struct) * mysql_num_rows(result)); - npc_spellseffects_cache[iDBSpellsEffectsID] = (DBnpcspellseffects_Struct*) new uchar[tmpSize]; - memset(npc_spellseffects_cache[iDBSpellsEffectsID], 0, tmpSize); - npc_spellseffects_cache[iDBSpellsEffectsID]->parent_list = tmpparent_list; - npc_spellseffects_cache[iDBSpellsEffectsID]->numentries = mysql_num_rows(result); - int j = 0; - while ((row = mysql_fetch_row(result))) { - int spell_effect_id = atoi(row[0]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].spelleffectid = spell_effect_id; - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].minlevel = atoi(row[1]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].maxlevel = atoi(row[2]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].base = atoi(row[3]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].limit = atoi(row[4]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].max = atoi(row[5]); - j++; - } - mysql_free_result(result); - return npc_spellseffects_cache[iDBSpellsEffectsID]; - } - else { - std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - } - else { - mysql_free_result(result); - } - } - else { - std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - return 0; - } - return 0; -} - -uint32 ZoneDatabase::GetMaxNPCSpellsEffectsID() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id) from npc_spells_effects"), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 ret = 0; - if (row[0]) - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetMaxNPCSpellsEffectsID query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - - return 0; -} - diff --git a/zone/attackx.cpp b/zone/attackx.cpp deleted file mode 100644 index 3f96399be..000000000 --- a/zone/attackx.cpp +++ /dev/null @@ -1,4663 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#if EQDEBUG >= 5 -//#define ATTACK_DEBUG 20 -#endif - -#include "../common/debug.h" -#include -#include -#include -#include -#include -#include - -#include "masterentity.h" -#include "NpcAI.h" -#include "../common/packet_dump.h" -#include "../common/eq_packet_structs.h" -#include "../common/eq_constants.h" -#include "../common/skills.h" -#include "../common/spdat.h" -#include "zone.h" -#include "StringIDs.h" -#include "../common/StringUtil.h" -#include "../common/rulesys.h" -#include "QuestParserCollection.h" -#include "watermap.h" -#include "worldserver.h" -extern WorldServer worldserver; - -#ifdef _WINDOWS -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif - -extern EntityList entity_list; -extern Zone* zone; - -bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* weapon) -{ - // Determine animation - int type = 0; - if (weapon && weapon->IsType(ItemClassCommon)) { - const Item_Struct* item = weapon->GetItem(); -#if EQDEBUG >= 11 - LogFile->write(EQEMuLog::Debug, "Weapon skill:%i", item->ItemType); -#endif - switch (item->ItemType) - { - case ItemType1HSlash: // 1H Slashing - { - skillinuse = Skill1HSlashing; - type = anim1HWeapon; - break; - } - case ItemType2HSlash: // 2H Slashing - { - skillinuse = Skill2HSlashing; - type = anim2HSlashing; - break; - } - case ItemType1HPiercing: // Piercing - { - skillinuse = Skill1HPiercing; - type = animPiercing; - break; - } - case ItemType1HBlunt: // 1H Blunt - { - skillinuse = Skill1HBlunt; - type = anim1HWeapon; - break; - } - case ItemType2HBlunt: // 2H Blunt - { - skillinuse = Skill2HBlunt; - type = anim2HWeapon; - break; - } - case ItemType2HPiercing: // 2H Piercing - { - skillinuse = Skill1HPiercing; // change to Skill2HPiercing once activated - type = anim2HWeapon; - break; - } - case ItemTypeMartial: - { - skillinuse = SkillHandtoHand; - type = animHand2Hand; - break; - } - default: - { - skillinuse = SkillHandtoHand; - type = animHand2Hand; - break; - } - }// switch - } - else if(IsNPC()) { - - switch (skillinuse) - { - case Skill1HSlashing: // 1H Slashing - { - type = anim1HWeapon; - break; - } - case Skill2HSlashing: // 2H Slashing - { - type = anim2HSlashing; - break; - } - case Skill1HPiercing: // Piercing - { - type = animPiercing; - break; - } - case Skill1HBlunt: // 1H Blunt - { - type = anim1HWeapon; - break; - } - case Skill2HBlunt: // 2H Blunt - { - type = anim2HWeapon; - break; - } - case 99: // 2H Piercing // change to Skill2HPiercing once activated - { - type = anim2HWeapon; - break; - } - case SkillHandtoHand: - { - type = animHand2Hand; - break; - } - default: - { - type = animHand2Hand; - break; - } - }// switch - } - else { - skillinuse = SkillHandtoHand; - type = animHand2Hand; - } - - // If we're attacking with the secondary hand, play the dual wield anim - if (Hand == 14) // DW anim - type = animDualWield; - - DoAnim(type); - return true; -} - -// called when a mob is attacked, does the checks to see if it's a hit -// and does other mitigation checks. 'this' is the mob being attacked. -bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 chance_mod) -{ -/*/ - //Reworked a lot of this code to achieve better balance at higher levels. - //The old code basically meant that any in high level (50+) combat, - //both parties always had 95% chance to hit the other one. -/*/ - - Mob *attacker=other; - Mob *defender=this; - float chancetohit = RuleR(Combat, BaseHitChance); - - if(attacker->IsNPC() && !attacker->IsPet()) - chancetohit += RuleR(Combat, NPCBonusHitChance); - -#if ATTACK_DEBUG>=11 - LogFile->write(EQEMuLog::Debug, "CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName()); -#endif - mlog(COMBAT__TOHIT,"CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName()); - - bool pvpmode = false; - if(IsClient() && other->IsClient()) - pvpmode = true; - - if (chance_mod >= 10000) - return true; - - float bonus; - - //////////////////////////////////////////////////////// - // To hit calcs go here - //////////////////////////////////////////////////////// - - uint8 attacker_level = attacker->GetLevel() ? attacker->GetLevel() : 1; - uint8 defender_level = defender->GetLevel() ? defender->GetLevel() : 1; - - //Calculate the level difference - - mlog(COMBAT__TOHIT, "Chance to hit before level diff calc %.2f", chancetohit); - double level_difference = attacker_level - defender_level; - double range = defender->GetLevel(); - range = ((range / 4) + 3); - - if(level_difference < 0) - { - if(level_difference >= -range) - { - chancetohit += (level_difference / range) * RuleR(Combat,HitFalloffMinor); //5 - } - else if (level_difference >= -(range+3.0)) - { - chancetohit -= RuleR(Combat,HitFalloffMinor); - chancetohit += ((level_difference+range) / (3.0)) * RuleR(Combat,HitFalloffModerate); //7 - } - else - { - chancetohit -= (RuleR(Combat,HitFalloffMinor) + RuleR(Combat,HitFalloffModerate)); - chancetohit += ((level_difference+range+3.0)/12.0) * RuleR(Combat,HitFalloffMajor); //50 - } - } - else - { - chancetohit += (RuleR(Combat,HitBonusPerLevel) * level_difference); - } - - mlog(COMBAT__TOHIT, "Chance to hit after level diff calc %.2f", chancetohit); - - chancetohit -= ((float)defender->GetAGI() * RuleR(Combat, AgiHitFactor)); - - mlog(COMBAT__TOHIT, "Chance to hit after agil calc %.2f", chancetohit); - - if(attacker->IsClient()) - { - chancetohit -= (RuleR(Combat,WeaponSkillFalloff) * (attacker->CastToClient()->MaxSkill(skillinuse) - attacker->GetSkill(skillinuse))); - mlog(COMBAT__TOHIT, "Chance to hit after weapon falloff calc (attack) %.2f", chancetohit); - } - - if(defender->IsClient()) - { - chancetohit += (RuleR(Combat,WeaponSkillFalloff) * (defender->CastToClient()->MaxSkill(SkillDefense) - defender->GetSkill(SkillDefense))); - mlog(COMBAT__TOHIT, "Chance to hit after weapon falloff calc (defense) %.2f", chancetohit); - } - - //I dont think this is 100% correct, but at least it does something... - if(attacker->spellbonuses.MeleeSkillCheckSkill == skillinuse || attacker->spellbonuses.MeleeSkillCheckSkill == 255) { - chancetohit += attacker->spellbonuses.MeleeSkillCheck; - mlog(COMBAT__TOHIT, "Applied spell melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit); - } - if(attacker->itembonuses.MeleeSkillCheckSkill == skillinuse || attacker->itembonuses.MeleeSkillCheckSkill == 255) { - chancetohit += attacker->itembonuses.MeleeSkillCheck; - mlog(COMBAT__TOHIT, "Applied item melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit); - } - - //subtract off avoidance by the defender. (Live AA - Combat Agility) - bonus = defender->spellbonuses.AvoidMeleeChance + defender->itembonuses.AvoidMeleeChance + (defender->aabonuses.AvoidMeleeChance * 10); - - //AA Live - Elemental Agility - if (IsPet()) { - Mob *owner = defender->GetOwner(); - if (!owner)return false; - bonus += (owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance)*10; - } - - if(bonus > 0) { - chancetohit -= ((bonus * chancetohit) / 1000); - mlog(COMBAT__TOHIT, "Applied avoidance chance %.2f/10, yeilding %.2f", bonus, chancetohit); - } - - if(attacker->IsNPC()) - chancetohit += (chancetohit * attacker->CastToNPC()->GetAccuracyRating() / 1000); - - mlog(COMBAT__TOHIT, "Chance to hit after accuracy rating calc %.2f", chancetohit); - - float hitBonus = 0; - - /* - Kayen: Unknown if the HitChance and Accuracy effect's should modify 'chancetohit' - cumulatively or successively. For now all hitBonuses are cumulative. - */ - - hitBonus += attacker->itembonuses.HitChanceEffect[skillinuse] + - attacker->spellbonuses.HitChanceEffect[skillinuse]+ - attacker->itembonuses.HitChanceEffect[HIGHEST_SKILL+1] + - attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1]; - - //Accuracy = Spell Effect , HitChance = 'Accuracy' from Item Effect - //Only AA derived accuracy can be skill limited. ie (Precision of the Pathfinder, Dead Aim) - hitBonus += (attacker->itembonuses.Accuracy[HIGHEST_SKILL+1] + - attacker->spellbonuses.Accuracy[HIGHEST_SKILL+1] + - attacker->aabonuses.Accuracy[HIGHEST_SKILL+1] + - attacker->aabonuses.Accuracy[skillinuse] + - attacker->itembonuses.HitChance) / 15.0f; - - hitBonus += chance_mod; //Modifier applied from casted/disc skill attacks. - - chancetohit += ((chancetohit * hitBonus) / 100.0f); - - if(skillinuse == SkillArchery) - chancetohit -= (chancetohit * RuleR(Combat, ArcheryHitPenalty)) / 100.0f; - - chancetohit = mod_hit_chance(chancetohit, skillinuse, attacker); - - // Chance to hit; Max 95%, Min 30% - if(chancetohit > 1000) { - //if chance to hit is crazy high, that means a discipline is in use, and let it stay there - } - else if(chancetohit > 95) { - chancetohit = 95; - } - else if(chancetohit < 5) { - chancetohit = 5; - } - - //I dont know the best way to handle a garunteed hit discipline being used - //agains a garunteed riposte (for example) discipline... for now, garunteed hit wins - - - #if EQDEBUG>=11 - LogFile->write(EQEMuLog::Debug, "3 FINAL calculated chance to hit is: %5.2f", chancetohit); - #endif - - // - // Did we hit? - // - - float tohit_roll = MakeRandomFloat(0, 100); - - mlog(COMBAT__TOHIT, "Final hit chance: %.2f%%. Hit roll %.2f", chancetohit, tohit_roll); - - return(tohit_roll <= chancetohit); -} - - -bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) -{ - /* solar: called when a mob is attacked, does the checks to see if it's a hit - * and does other mitigation checks. 'this' is the mob being attacked. - * - * special return values: - * -1 - block - * -2 - parry - * -3 - riposte - * -4 - dodge - * - */ - float skill; - float bonus; - float RollTable[4] = {0,0,0,0}; - float roll; - Mob *attacker=other; - Mob *defender=this; - - //garunteed hit - bool ghit = false; - if((attacker->spellbonuses.MeleeSkillCheck + attacker->itembonuses.MeleeSkillCheck) > 500) - ghit = true; - - ////////////////////////////////////////////////////////// - // make enrage same as riposte - ///////////////////////////////////////////////////////// - if (IsEnraged() && other->InFrontMob(this, other->GetX(), other->GetY())) { - damage = -3; - mlog(COMBAT__DAMAGE, "I am enraged, riposting frontal attack."); - } - - ///////////////////////////////////////////////////////// - // riposte - ///////////////////////////////////////////////////////// - float riposte_chance = 0.0f; - if (CanRiposte && damage > 0 && CanThisClassRiposte() && other->InFrontMob(this, other->GetX(), other->GetY())) - { - riposte_chance = (100.0f + (float)defender->aabonuses.RiposteChance + (float)defender->spellbonuses.RiposteChance + (float)defender->itembonuses.RiposteChance) / 100.0f; - skill = GetSkill(SkillRiposte); - if (IsClient()) { - CastToClient()->CheckIncreaseSkill(SkillRiposte, other, -10); - } - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetDEX()/200); - bonus *= riposte_chance; - bonus = mod_riposte_chance(bonus, attacker); - RollTable[0] = bonus + (itembonuses.HeroicDEX / 25); // 25 heroic = 1%, applies to ripo, parry, block - } - } - - /////////////////////////////////////////////////////// - // block - /////////////////////////////////////////////////////// - - bool bBlockFromRear = false; - bool bShieldBlockFromRear = false; - - if (this->IsClient()) { - int aaChance = 0; - - // a successful roll on this does not mean a successful block is forthcoming. only that a chance to block - // from a direction other than the rear is granted. - - //Live AA - HightenedAwareness - int BlockBehindChance = aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind; - - if (BlockBehindChance && (BlockBehindChance > MakeRandomInt(1, 100))){ - bBlockFromRear = true; - - if (spellbonuses.BlockBehind || itembonuses.BlockBehind) - bShieldBlockFromRear = true; //This bonus should allow a chance to Shield Block from behind. - } - } - - float block_chance = 0.0f; - if (damage > 0 && CanThisClassBlock() && (other->InFrontMob(this, other->GetX(), other->GetY()) || bBlockFromRear)) { - block_chance = (100.0f + (float)spellbonuses.IncreaseBlockChance + (float)itembonuses.IncreaseBlockChance) / 100.0f; - skill = CastToClient()->GetSkill(SkillBlock); - if (IsClient()) { - CastToClient()->CheckIncreaseSkill(SkillBlock, other, -10); - } - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/35.0 + (GetDEX()/200); - bonus = mod_block_chance(bonus, attacker); - RollTable[1] = RollTable[0] + (bonus * block_chance); - } - } - else{ - RollTable[1] = RollTable[0]; - } - - if(damage > 0 && HasShieldEquiped() && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) - && (other->InFrontMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) { - - float bonusShieldBlock = 0.0f; - bonusShieldBlock = aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock; - RollTable[1] += bonusShieldBlock; - } - - if(damage > 0 && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) - && (other->InFrontMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) { - bool equiped2 = CastToClient()->m_inv.GetItem(13); - if(equiped2) { - uint8 TwoHandBlunt = CastToClient()->m_inv.GetItem(13)->GetItem()->ItemType; - float bonusStaffBlock = 0.0f; - if(TwoHandBlunt == ItemType2HBlunt) { - - bonusStaffBlock = aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock; - RollTable[1] += bonusStaffBlock; - } - } - } - - ////////////////////////////////////////////////////// - // parry - ////////////////////////////////////////////////////// - float parry_chance = 0.0f; - if (damage > 0 && CanThisClassParry() && other->InFrontMob(this, other->GetX(), other->GetY())) - { - parry_chance = (100.0f + (float)defender->spellbonuses.ParryChance + (float)defender->itembonuses.ParryChance) / 100.0f; - skill = CastToClient()->GetSkill(SkillParry); - if (IsClient()) { - CastToClient()->CheckIncreaseSkill(SkillParry, other, -10); - } - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetDEX()/200); - bonus *= parry_chance; - bonus = mod_parry_chance(bonus, attacker); - RollTable[2] = RollTable[1] + bonus; - } - } - else{ - RollTable[2] = RollTable[1]; - } - - //////////////////////////////////////////////////////// - // dodge - //////////////////////////////////////////////////////// - float dodge_chance = 0.0f; - if (damage > 0 && CanThisClassDodge() && other->InFrontMob(this, other->GetX(), other->GetY())) - { - dodge_chance = (100.0f + (float)defender->spellbonuses.DodgeChance + (float)defender->itembonuses.DodgeChance) / 100.0f; - skill = CastToClient()->GetSkill(SkillDodge); - if (IsClient()) { - CastToClient()->CheckIncreaseSkill(SkillDodge, other, -10); - } - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetAGI()/200); - bonus *= dodge_chance; - //DCBOOMKAR - bonus = mod_dodge_chance(bonus, attacker); - RollTable[3] = RollTable[2] + bonus - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25); - } - } - else{ - RollTable[3] = RollTable[2]; - } - - if(damage > 0){ - roll = MakeRandomFloat(0,100); - if(roll <= RollTable[0]){ - damage = -3; - } - else if(roll <= RollTable[1]){ - damage = -1; - } - else if(roll <= RollTable[2]){ - damage = -2; - } - else if(roll <= RollTable[3]){ - damage = -4; - } - } - - mlog(COMBAT__DAMAGE, "Final damage after all avoidances: %d", damage); - - if (damage < 0) - return true; - return false; -} - -void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts) -{ - if (damage <= 0) - return; - - Mob* defender = this; - float aa_mit = (aabonuses.CombatStability + itembonuses.CombatStability + - spellbonuses.CombatStability) / 100.0f; - - if (RuleB(Combat, UseIntervalAC)) { - float softcap = (GetSkill(SkillDefense) + GetLevel()) * - RuleR(Combat, SoftcapFactor) * (1.0 + aa_mit); - float mitigation_rating = 0.0; - float attack_rating = 0.0; - int shield_ac = 0; - int armor = 0; - float weight = 0.0; - - float monkweight = RuleI(Combat, MonkACBonusWeight); - monkweight = mod_monk_weight(monkweight, attacker); - - if (IsClient()) { - armor = CastToClient()->GetRawACNoShield(shield_ac); - weight = (CastToClient()->CalcCurrentWeight() / 10.0); - } else if (IsNPC()) { - armor = CastToNPC()->GetRawAC(); - - if (!IsPet()) - armor = (armor / RuleR(Combat, NPCACFactor)); - - armor += spellbonuses.AC + itembonuses.AC + 1; - } - - if (opts) { - armor *= (1.0f - opts->armor_pen_percent); - armor -= opts->armor_pen_flat; - } - - if (RuleB(Combat, OldACSoftcapRules)) { - if (GetClass() == WIZARD || GetClass() == MAGICIAN || - GetClass() == NECROMANCER || GetClass() == ENCHANTER) - softcap = RuleI(Combat, ClothACSoftcap); - else if (GetClass() == MONK && weight <= monkweight) - softcap = RuleI(Combat, MonkACSoftcap); - else if(GetClass() == DRUID || GetClass() == BEASTLORD || GetClass() == MONK) - softcap = RuleI(Combat, LeatherACSoftcap); - else if(GetClass() == SHAMAN || GetClass() == ROGUE || - GetClass() == BERSERKER || GetClass() == RANGER) - softcap = RuleI(Combat, ChainACSoftcap); - else - softcap = RuleI(Combat, PlateACSoftcap); - } - - softcap += shield_ac; - armor += shield_ac; - if (RuleB(Combat, OldACSoftcapRules)) - softcap += (softcap * (aa_mit * RuleR(Combat, AAMitigationACFactor))); - if (armor > softcap) { - int softcap_armor = armor - softcap; - if (RuleB(Combat, OldACSoftcapRules)) { - if (GetClass() == WARRIOR) - softcap_armor = softcap_armor * RuleR(Combat, WarriorACSoftcapReturn); - else if (GetClass() == SHADOWKNIGHT || GetClass() == PALADIN || - (GetClass() == MONK && weight <= monkweight)) - softcap_armor = softcap_armor * RuleR(Combat, KnightACSoftcapReturn); - else if (GetClass() == CLERIC || GetClass() == BARD || - GetClass() == BERSERKER || GetClass() == ROGUE || - GetClass() == SHAMAN || GetClass() == MONK) - softcap_armor = softcap_armor * RuleR(Combat, LowPlateChainACSoftcapReturn); - else if (GetClass() == RANGER || GetClass() == BEASTLORD) - softcap_armor = softcap_armor * RuleR(Combat, LowChainLeatherACSoftcapReturn); - else if (GetClass() == WIZARD || GetClass() == MAGICIAN || - GetClass() == NECROMANCER || GetClass() == ENCHANTER || - GetClass() == DRUID) - softcap_armor = softcap_armor * RuleR(Combat, CasterACSoftcapReturn); - else - softcap_armor = softcap_armor * RuleR(Combat, MiscACSoftcapReturn); - } else { - if (GetClass() == WARRIOR) - softcap_armor *= RuleR(Combat, WarACSoftcapReturn); - else if (GetClass() == PALADIN || GetClass() == SHADOWKNIGHT) - softcap_armor *= RuleR(Combat, PalShdACSoftcapReturn); - else if (GetClass() == CLERIC || GetClass() == RANGER || - GetClass() == MONK || GetClass() == BARD) - softcap_armor *= RuleR(Combat, ClrRngMnkBrdACSoftcapReturn); - else if (GetClass() == DRUID || GetClass() == NECROMANCER || - GetClass() == WIZARD || GetClass() == ENCHANTER || - GetClass() == MAGICIAN) - softcap_armor *= RuleR(Combat, DruNecWizEncMagACSoftcapReturn); - else if (GetClass() == ROGUE || GetClass() == SHAMAN || - GetClass() == BEASTLORD || GetClass() == BERSERKER) - softcap_armor *= RuleR(Combat, RogShmBstBerACSoftcapReturn); - else - softcap_armor *= RuleR(Combat, MiscACSoftcapReturn); - } - armor = softcap + softcap_armor; - } - - if (GetClass() == WIZARD || GetClass() == MAGICIAN || - GetClass() == NECROMANCER || GetClass() == ENCHANTER) - mitigation_rating = ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10) / 4.0) + armor + 1; - else - mitigation_rating = ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10) / 3.0) + (armor * 1.333333) + 1; - mitigation_rating *= 0.847; - - mitigation_rating = mod_mitigation_rating(mitigation_rating, attacker); - - if (attacker->IsClient()) - attack_rating = (attacker->CastToClient()->CalcATK() + ((attacker->GetSTR()-66) * 0.9) + (attacker->GetSkill(SkillOffense)*1.345)); - else - attack_rating = (attacker->GetATK() + (attacker->GetSkill(SkillOffense)*1.345) + ((attacker->GetSTR()-66) * 0.9)); - - attack_rating = attacker->mod_attack_rating(attack_rating, this); - - damage = GetMeleeMitDmg(attacker, damage, minhit, mitigation_rating, attack_rating); - } else { - //////////////////////////////////////////////////////// - // Scorpious2k: Include AC in the calculation - // use serverop variables to set values - int myac = GetAC(); - if(opts) { - myac *= (1.0f - opts->armor_pen_percent); - myac -= opts->armor_pen_flat; - } - - if (damage > 0 && myac > 0) { - int acfail=1000; - char tmp[10]; - - if (database.GetVariable("ACfail", tmp, 9)) { - acfail = (int) (atof(tmp) * 100); - if (acfail>100) acfail=100; - } - - if (acfail<=0 || MakeRandomInt(0, 100)>acfail) { - float acreduction=1; - int acrandom=300; - if (database.GetVariable("ACreduction", tmp, 9)) - { - acreduction=atof(tmp); - if (acreduction>100) acreduction=100; - } - - if (database.GetVariable("ACrandom", tmp, 9)) - { - acrandom = (int) ((atof(tmp)+1) * 100); - if (acrandom>10100) acrandom=10100; - } - - if (acreduction>0) { - damage -= (int) (GetAC() * acreduction/100.0f); - } - if (acrandom>0) { - damage -= (myac * MakeRandomInt(0, acrandom) / 10000); - } - if (damage<1) damage=1; - mlog(COMBAT__DAMAGE, "AC Damage Reduction: fail chance %d%%. Failed. Reduction %.3f%%, random %d. Resulting damage %d.", acfail, acreduction, acrandom, damage); - } else { - mlog(COMBAT__DAMAGE, "AC Damage Reduction: fail chance %d%%. Did not fail.", acfail); - } - } - - damage -= (aa_mit * damage); - - if(damage != 0 && damage < minhit) - damage = minhit; - //reduce the damage from shielding item and aa based on the min dmg - //spells offer pure mitigation - damage -= (minhit * defender->itembonuses.MeleeMitigation / 100); - damage -= (damage * defender->spellbonuses.MeleeMitigation / 100); - } - - if (damage < 0) - damage = 0; -} - -// This is called when the Mob is the one being hit -int32 Mob::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, - float mit_rating, float atk_rating) -{ - float d = 10.0; - float mit_roll = MakeRandomFloat(0, mit_rating); - float atk_roll = MakeRandomFloat(0, atk_rating); - - if (atk_roll > mit_roll) { - float a_diff = atk_roll - mit_roll; - float thac0 = atk_rating * RuleR(Combat, ACthac0Factor); - float thac0cap = attacker->GetLevel() * 9 + 20; - if (thac0 > thac0cap) - thac0 = thac0cap; - - d -= 10.0 * (a_diff / thac0); - } else if (mit_roll > atk_roll) { - float m_diff = mit_roll - atk_roll; - float thac20 = mit_rating * RuleR(Combat, ACthac20Factor); - float thac20cap = GetLevel() * 9 + 20; - if (thac20 > thac20cap) - thac20 = thac20cap; - - d += 10.0 * (m_diff / thac20); - } - - if (d < 0.0) - d = 0.0; - else if (d > 20.0) - d = 20.0; - - float interval = (damage - minhit) / 20.0; - damage -= ((int)d * interval); - - damage -= (minhit * itembonuses.MeleeMitigation / 100); - damage -= (damage * spellbonuses.MeleeMitigation / 100); - return damage; -} - -// This is called when the Client is the one being hit -int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, - float mit_rating, float atk_rating) -{ - if (!attacker->IsNPC() || RuleB(Combat, UseOldDamageIntervalRules)) - return Mob::GetMeleeMitDmg(attacker, damage, minhit, mit_rating, atk_rating); - int d = 10; - // floats for the rounding issues - float dmg_interval = (damage - minhit) / 19.0; - float dmg_bonus = minhit - dmg_interval; - float spellMeleeMit = spellbonuses.MeleeMitigation / 100.0; - if (GetClass() == WARRIOR) - spellMeleeMit += 0.05; - dmg_bonus -= dmg_bonus * (itembonuses.MeleeMitigation / 100.0); - dmg_interval -= dmg_interval * spellMeleeMit; - - float mit_roll = MakeRandomFloat(0, mit_rating); - float atk_roll = MakeRandomFloat(0, atk_rating); - - if (atk_roll > mit_roll) { - float a_diff = atk_roll - mit_roll; - float thac0 = atk_rating * RuleR(Combat, ACthac0Factor); - float thac0cap = attacker->GetLevel() * 9 + 20; - if (thac0 > thac0cap) - thac0 = thac0cap; - - d += 10 * (a_diff / thac0); - } else if (mit_roll > atk_roll) { - float m_diff = mit_roll - atk_roll; - float thac20 = mit_rating * RuleR(Combat, ACthac20Factor); - float thac20cap = GetLevel() * 9 + 20; - if (thac20 > thac20cap) - thac20 = thac20cap; - - d -= 10 * (m_diff / thac20); - } - - if (d < 1) - d = 1; - else if (d > 20) - d = 20; - - return static_cast((dmg_bonus + dmg_interval * d)); -} - -//Returns the weapon damage against the input mob -//if we cannot hit the mob with the current weapon we will get a value less than or equal to zero -//Else we know we can hit. -//GetWeaponDamage(mob*, const Item_Struct*) is intended to be used for mobs or any other situation where we do not have a client inventory item -//GetWeaponDamage(mob*, const ItemInst*) is intended to be used for situations where we have a client inventory item -int Mob::GetWeaponDamage(Mob *against, const Item_Struct *weapon_item) { - int dmg = 0; - int banedmg = 0; - - //can't hit invulnerable stuff with weapons. - if(against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)){ - return 0; - } - - //check to see if our weapons or fists are magical. - if(against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)){ - if(weapon_item){ - if(weapon_item->Magic){ - dmg = weapon_item->Damage; - - //this is more for non weapon items, ex: boots for kick - //they don't have a dmg but we should be able to hit magical - dmg = dmg <= 0 ? 1 : dmg; - } - else - return 0; - } - else{ - if((GetClass() == MONK || GetClass() == BEASTLORD) && GetLevel() >= 30){ - dmg = GetMonkHandToHandDamage(); - } - else if(GetOwner() && GetLevel() >= RuleI(Combat, PetAttackMagicLevel)){ - //pets wouldn't actually use this but... - //it gives us an idea if we can hit due to the dual nature of this function - dmg = 1; - } - else if(GetSpecialAbility(SPECATK_MAGICAL)) - { - dmg = 1; - } - else - return 0; - } - } - else{ - if(weapon_item){ - dmg = weapon_item->Damage; - - dmg = dmg <= 0 ? 1 : dmg; - } - else{ - if(GetClass() == MONK || GetClass() == BEASTLORD){ - dmg = GetMonkHandToHandDamage(); - } - else{ - dmg = 1; - } - } - } - - int eledmg = 0; - if(!against->GetSpecialAbility(IMMUNE_MAGIC)){ - if(weapon_item && weapon_item->ElemDmgAmt){ - //we don't check resist for npcs here - eledmg = weapon_item->ElemDmgAmt; - dmg += eledmg; - } - } - - if(against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)){ - if(weapon_item){ - if(weapon_item->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->BaneDmgAmt; - } - - if(weapon_item->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->BaneDmgRaceAmt; - } - } - - if(!eledmg && !banedmg){ - if(!GetSpecialAbility(SPECATK_BANE)) - return 0; - else - return 1; - } - else - dmg += banedmg; - } - else{ - if(weapon_item){ - if(weapon_item->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->BaneDmgAmt; - } - - if(weapon_item->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->BaneDmgRaceAmt; - } - } - - dmg += (banedmg + eledmg); - } - - if(dmg <= 0){ - return 0; - } - else - return dmg; -} - -int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate) -{ - int dmg = 0; - int banedmg = 0; - - if(!against || against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)){ - return 0; - } - - //check for items being illegally attained - if(weapon_item){ - const Item_Struct *mWeaponItem = weapon_item->GetItem(); - if(mWeaponItem){ - if(mWeaponItem->ReqLevel > GetLevel()){ - return 0; - } - - if(!weapon_item->IsEquipable(GetBaseRace(), GetClass())){ - return 0; - } - } - else{ - return 0; - } - } - - if(against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)){ - if(weapon_item){ - // check to see if the weapon is magic - bool MagicWeapon = false; - if(weapon_item->GetItem() && weapon_item->GetItem()->Magic) - MagicWeapon = true; - else { - if(spellbonuses.MagicWeapon || itembonuses.MagicWeapon) - MagicWeapon = true; - } - - if(MagicWeapon) { - - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - dmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->Damage); - } - else{ - dmg = weapon_item->GetItem()->Damage; - } - - for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - dmg += weapon_item->GetAugment(x)->GetItem()->Damage; - if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt; - } - } - dmg = dmg <= 0 ? 1 : dmg; - } - else - return 0; - } - else{ - if((GetClass() == MONK || GetClass() == BEASTLORD) && GetLevel() >= 30){ - dmg = GetMonkHandToHandDamage(); - if (hate) *hate += dmg; - } - else if(GetOwner() && GetLevel() >= RuleI(Combat, PetAttackMagicLevel)){ //pets wouldn't actually use this but... - dmg = 1; //it gives us an idea if we can hit - } - else if(GetSpecialAbility(SPECATK_MAGICAL)){ - dmg = 1; - } - else - return 0; - } - } - else{ - if(weapon_item){ - if(weapon_item->GetItem()){ - - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - dmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->Damage); - } - else{ - dmg = weapon_item->GetItem()->Damage; - } - - for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - dmg += weapon_item->GetAugment(x)->GetItem()->Damage; - if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt; - } - } - dmg = dmg <= 0 ? 1 : dmg; - } - } - else{ - if(GetClass() == MONK || GetClass() == BEASTLORD){ - dmg = GetMonkHandToHandDamage(); - if (hate) *hate += dmg; - } - else{ - dmg = 1; - } - } - } - - int eledmg = 0; - if(!against->GetSpecialAbility(IMMUNE_MAGIC)){ - if(weapon_item && weapon_item->GetItem() && weapon_item->GetItem()->ElemDmgAmt){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - eledmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->ElemDmgAmt); - } - else{ - eledmg = weapon_item->GetItem()->ElemDmgAmt; - } - - if(eledmg) - { - eledmg = (eledmg * against->ResistSpell(weapon_item->GetItem()->ElemDmgType, 0, this) / 100); - } - } - - if(weapon_item){ - for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt) - eledmg += (weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt * against->ResistSpell(weapon_item->GetAugment(x)->GetItem()->ElemDmgType, 0, this) / 100); - } - } - } - } - - if(against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)){ - if(weapon_item && weapon_item->GetItem()){ - if(weapon_item->GetItem()->BaneDmgBody == against->GetBodyType()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgAmt; - } - } - - if(weapon_item->GetItem()->BaneDmgRace == against->GetRace()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgRaceAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgRaceAmt; - } - } - - for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt; - } - - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgRaceAmt; - } - } - } - } - - if(!eledmg && !banedmg) - { - if(!GetSpecialAbility(SPECATK_BANE)) - return 0; - else - return 1; - } - else { - dmg += (banedmg + eledmg); - if (hate) *hate += banedmg; - } - } - else{ - if(weapon_item && weapon_item->GetItem()){ - if(weapon_item->GetItem()->BaneDmgBody == against->GetBodyType()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgAmt; - } - } - - if(weapon_item->GetItem()->BaneDmgRace == against->GetRace()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgRaceAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgRaceAmt; - } - } - - for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt; - } - - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgRaceAmt; - } - } - } - } - dmg += (banedmg + eledmg); - if (hate) *hate += banedmg; - } - - if(dmg <= 0){ - return 0; - } - else - return dmg; -} - -//note: throughout this method, setting `damage` to a negative is a way to -//stop the attack calculations -// IsFromSpell added to allow spell effects to use Attack. (Mainly for the Rampage AA right now.) -bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) -{ - if (!other) { - SetTarget(nullptr); - LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Client::Attack() for evaluation!"); - return false; - } - - if(!GetTarget()) - SetTarget(other); - - mlog(COMBAT__ATTACKS, "Attacking %s with hand %d %s", other?other->GetName():"(nullptr)", Hand, bRiposte?"(this is a riposte)":""); - - //SetAttackTimer(); - if ( - (IsCasting() && GetClass() != BARD && !IsFromSpell) - || other == nullptr - || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) - || (GetHP() < 0) - || (!IsAttackAllowed(other)) - ) { - mlog(COMBAT__ATTACKS, "Attack canceled, invalid circumstances."); - return false; // Only bards can attack while casting - } - - if(DivineAura() && !GetGM()) {//cant attack while invulnerable unless your a gm - mlog(COMBAT__ATTACKS, "Attack canceled, Divine Aura is in effect."); - Message_StringID(MT_DefaultText, DIVINE_AURA_NO_ATK); //You can't attack while invulnerable! - return false; - } - - if (GetFeigned()) - return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code. - - - ItemInst* weapon; - if (Hand == 14){ // Kaiyodo - Pick weapon from the attacking hand - weapon = GetInv().GetItem(SLOT_SECONDARY); - OffHandAtk(true); - } - else{ - weapon = GetInv().GetItem(SLOT_PRIMARY); - OffHandAtk(false); - } - - if(weapon != nullptr) { - if (!weapon->IsWeapon()) { - mlog(COMBAT__ATTACKS, "Attack canceled, Item %s (%d) is not a weapon.", weapon->GetItem()->Name, weapon->GetID()); - return(false); - } - mlog(COMBAT__ATTACKS, "Attacking with weapon: %s (%d)", weapon->GetItem()->Name, weapon->GetID()); - } else { - mlog(COMBAT__ATTACKS, "Attacking without a weapon."); - } - - // calculate attack_skill and skillinuse depending on hand and weapon - // also send Packet to near clients - SkillUseTypes skillinuse; - AttackAnimation(skillinuse, Hand, weapon); - mlog(COMBAT__ATTACKS, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse); - - /// Now figure out damage - int damage = 0; - uint8 mylevel = GetLevel() ? GetLevel() : 1; - uint32 hate = 0; - if (weapon) hate = weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt; - int weapon_damage = GetWeaponDamage(other, weapon, &hate); - if (hate == 0 && weapon_damage > 1) hate = weapon_damage; - - //if weapon damage > 0 then we know we can hit the target with this weapon - //otherwise we cannot and we set the damage to -5 later on - if(weapon_damage > 0){ - - //Berserker Berserk damage bonus - if(IsBerserk() && GetClass() == BERSERKER){ - int bonus = 3 + GetLevel()/10; //unverified - weapon_damage = weapon_damage * (100+bonus) / 100; - mlog(COMBAT__DAMAGE, "Berserker damage bonus increases DMG to %d", weapon_damage); - } - - //try a finishing blow.. if successful end the attack - if(TryFinishingBlow(other, skillinuse)) - return (true); - - int min_hit = 1; - int max_hit = (2*weapon_damage*GetDamageTable(skillinuse)) / 100; - - if(GetLevel() < 10 && max_hit > RuleI(Combat, HitCapPre10)) - max_hit = (RuleI(Combat, HitCapPre10)); - else if(GetLevel() < 20 && max_hit > RuleI(Combat, HitCapPre20)) - max_hit = (RuleI(Combat, HitCapPre20)); - - CheckIncreaseSkill(skillinuse, other, -15); - CheckIncreaseSkill(SkillOffense, other, -15); - - - // *************************************************************** - // *** Calculate the damage bonus, if applicable, for this hit *** - // *************************************************************** - -#ifndef EQEMU_NO_WEAPON_DAMAGE_BONUS - - // If you include the preprocessor directive "#define EQEMU_NO_WEAPON_DAMAGE_BONUS", that indicates that you do not - // want damage bonuses added to weapon damage at all. This feature was requested by ChaosSlayer on the EQEmu Forums. - // - // This is not recommended for normal usage, as the damage bonus represents a non-trivial component of the DPS output - // of weapons wielded by higher-level melee characters (especially for two-handed weapons). - - int ucDamageBonus = 0; - - if( Hand == 13 && GetLevel() >= 28 && IsWarriorClass() ) - { - // Damage bonuses apply only to hits from the main hand (Hand == 13) by characters level 28 and above - // who belong to a melee class. If we're here, then all of these conditions apply. - - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); - - min_hit += (int) ucDamageBonus; - max_hit += (int) ucDamageBonus; - hate += ucDamageBonus; - } -#endif - //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. - if (Hand==14) { - if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); - - min_hit += (int) ucDamageBonus; - max_hit += (int) ucDamageBonus; - hate += ucDamageBonus; - } - } - - min_hit += min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100; - - if(max_hit < min_hit) - max_hit = min_hit; - - if(RuleB(Combat, UseIntervalAC)) - damage = max_hit; - else - damage = MakeRandomInt(min_hit, max_hit); - - damage = mod_client_damage(damage, skillinuse, Hand, weapon, other); - - mlog(COMBAT__DAMAGE, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)", - damage, min_hit, max_hit, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel); - - if(opts) { - damage *= opts->damage_percent; - damage += opts->damage_flat; - hate *= opts->hate_percent; - hate += opts->hate_flat; - } - - //check to see if we hit.. - if(!other->CheckHitChance(this, skillinuse, Hand)) { - mlog(COMBAT__ATTACKS, "Attack missed. Damage set to 0."); - damage = 0; - } else { //we hit, try to avoid it - other->AvoidDamage(this, damage); - other->MeleeMitigation(this, damage, min_hit, opts); - if(damage > 0) { - ApplyMeleeDamageBonus(skillinuse, damage); - damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); - TryCriticalHit(other, skillinuse, damage, opts); - } - mlog(COMBAT__DAMAGE, "Final damage after all reductions: %d", damage); - } - - //riposte - bool slippery_attack = false; // Part of hack to allow riposte to become a miss, but still allow a Strikethrough chance (like on Live) - if (damage == -3) { - if (bRiposte) return false; - else { - if (Hand == 14) {// Do we even have it & was attack with mainhand? If not, don't bother with other calculations - //Live AA - SlipperyAttacks - //This spell effect most likely directly modifies the actual riposte chance when using offhand attack. - int16 OffhandRiposteFail = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail; - OffhandRiposteFail *= -1; //Live uses a negative value for this. - - if (OffhandRiposteFail && - (OffhandRiposteFail > 99 || (MakeRandomInt(0, 100) < OffhandRiposteFail))) { - damage = 0; // Counts as a miss - slippery_attack = true; - } else - DoRiposte(other); - if (IsDead()) return false; - } - else - DoRiposte(other); - if (IsDead()) return false; - } - } - - if (((damage < 0) || slippery_attack) && !bRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA - int16 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; - - if(bonusStrikeThrough && (MakeRandomInt(0, 100) < bonusStrikeThrough)) { - Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses! - Attack(other, Hand, false, true); // Strikethrough only gives another attempted hit - return false; - } - } - } - else{ - damage = -5; - } - - // Hate Generation is on a per swing basis, regardless of a hit, miss, or block, its always the same. - // If we are this far, this means we are atleast making a swing. - - if (!bRiposte) // Ripostes never generate any aggro. - other->AddToHateList(this, hate); - - /////////////////////////////////////////////////////////// - ////// Send Attack Damage - /////////////////////////////////////////////////////////// - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); - - if (IsDead()) return false; - - MeleeLifeTap(damage); - - if (damage > 0) - CheckNumHitsRemaining(5); - - //break invis when you attack - if(invisible) { - mlog(COMBAT__ATTACKS, "Removing invisibility due to melee attack."); - BuffFadeByEffect(SE_Invisibility); - BuffFadeByEffect(SE_Invisibility2); - invisible = false; - } - if(invisible_undead) { - mlog(COMBAT__ATTACKS, "Removing invisibility vs. undead due to melee attack."); - BuffFadeByEffect(SE_InvisVsUndead); - BuffFadeByEffect(SE_InvisVsUndead2); - invisible_undead = false; - } - if(invisible_animals){ - mlog(COMBAT__ATTACKS, "Removing invisibility vs. animals due to melee attack."); - BuffFadeByEffect(SE_InvisVsAnimals); - invisible_animals = false; - } - - if(hidden || improved_hidden){ - hidden = false; - improved_hidden = false; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; - sa_out->spawn_id = GetID(); - sa_out->type = 0x03; - sa_out->parameter = 0; - entity_list.QueueClients(this, outapp, true); - safe_delete(outapp); - } - - if(GetTarget()) - TriggerDefensiveProcs(weapon, other, Hand, damage); - - if (damage > 0) - return true; - - else - return false; -} - -//used by complete heal and #heal -void Mob::Heal() -{ - SetMaxHP(); - SendHPUpdate(); -} - -void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) -{ - if(dead || IsCorpse()) - return; - - if(spell_id==0) - spell_id = SPELL_UNKNOWN; - - if(spell_id!=0 && spell_id != SPELL_UNKNOWN && other && damage > 0) - { - if(other->IsNPC() && !other->IsPet()) - { - float npcspellscale = other->CastToNPC()->GetSpellScale(); - damage = ((float)damage * npcspellscale) / (float)100; - } - } - - // cut all PVP spell damage to 2/3 -solar - // EverHood - Blasting ourselfs is considered PvP - //Don't do PvP mitigation if the caster is damaging himself - if(other && other->IsClient() && (other != this) && damage > 0) { - int PvPMitigation = 100; - if(attack_skill == SkillArchery) - PvPMitigation = 80; - else - PvPMitigation = 67; - damage = (damage * PvPMitigation) / 100; - } - - if(!ClientFinishedLoading()) - damage = -5; - - //do a majority of the work... - CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); - - if (damage > 0) { - - if (spell_id == SPELL_UNKNOWN) - CheckIncreaseSkill(SkillDefense, other, -15); - } -} - -bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) -{ - if(!ClientFinishedLoading()) - return false; - - if(dead) - return false; //cant die more than once... - - if(!spell) - spell = SPELL_UNKNOWN; - - char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); - if(parse->EventPlayer(EVENT_DEATH, this, buffer, 0) != 0) { - if(GetHP() < 0) { - SetHP(0); - } - return false; - } - - if(killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { - char val1[20]={0}; - entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE, - killerMob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); - } - - int exploss = 0; - mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob ? killerMob->GetName() : "Unknown", damage, spell, attack_skill); - - // - // #1: Send death packet to everyone - // - uint8 killed_level = GetLevel(); - - SendLogoutPackets(); - - //make our become corpse packet, and queue to ourself before OP_Death. - EQApplicationPacket app2(OP_BecomeCorpse, sizeof(BecomeCorpse_Struct)); - BecomeCorpse_Struct* bc = (BecomeCorpse_Struct*)app2.pBuffer; - bc->spawn_id = GetID(); - bc->x = GetX(); - bc->y = GetY(); - bc->z = GetZ(); - QueuePacket(&app2); - - // make death packet - EQApplicationPacket app(OP_Death, sizeof(Death_Struct)); - Death_Struct* d = (Death_Struct*)app.pBuffer; - d->spawn_id = GetID(); - d->killer_id = killerMob ? killerMob->GetID() : 0; - d->corpseid=GetID(); - d->bindzoneid = m_pp.binds[0].zoneId; - d->spell_id = spell == SPELL_UNKNOWN ? 0xffffffff : spell; - d->attack_skill = spell != SPELL_UNKNOWN ? 0xe7 : attack_skill; - d->damage = damage; - app.priority = 6; - entity_list.QueueClients(this, &app); - - // - // #2: figure out things that affect the player dying and mark them dead - // - - InterruptSpell(); - SetPet(0); - SetHorseId(0); - dead = true; - - if(GetMerc()) { - GetMerc()->Suspend(); - } - - if (killerMob != nullptr) - { - if (killerMob->IsNPC()) { - parse->EventNPC(EVENT_SLAY, killerMob->CastToNPC(), this, "", 0); - - mod_client_death_npc(killerMob); - - uint16 emoteid = killerMob->GetEmoteID(); - if(emoteid != 0) - killerMob->CastToNPC()->DoNPCEmote(KILLEDPC,emoteid); - killerMob->TrySpellOnKill(killed_level,spell); - } - - if(killerMob->IsClient() && (IsDueling() || killerMob->CastToClient()->IsDueling())) { - SetDueling(false); - SetDuelTarget(0); - if (killerMob->IsClient() && killerMob->CastToClient()->IsDueling() && killerMob->CastToClient()->GetDuelTarget() == GetID()) - { - //if duel opponent killed us... - killerMob->CastToClient()->SetDueling(false); - killerMob->CastToClient()->SetDuelTarget(0); - entity_list.DuelMessage(killerMob,this,false); - - mod_client_death_duel(killerMob); - - } else { - //otherwise, we just died, end the duel. - Mob* who = entity_list.GetMob(GetDuelTarget()); - if(who && who->IsClient()) { - who->CastToClient()->SetDueling(false); - who->CastToClient()->SetDuelTarget(0); - } - } - } - } - - entity_list.RemoveFromTargets(this); - hate_list.RemoveEnt(this); - RemoveAutoXTargets(); - - - //remove ourself from all proximities - ClearAllProximities(); - - // - // #3: exp loss and corpse generation - // - - // figure out if they should lose exp - if(RuleB(Character, UseDeathExpLossMult)){ - float GetNum [] = {0.005f,0.015f,0.025f,0.035f,0.045f,0.055f,0.065f,0.075f,0.085f,0.095f,0.110f }; - int Num = RuleI(Character, DeathExpLossMultiplier); - if((Num < 0) || (Num > 10)) - Num = 3; - float loss = GetNum[Num]; - exploss=(int)((float)GetEXP() * (loss)); //loose % of total XP pending rule (choose 0-10) - } - - if(!RuleB(Character, UseDeathExpLossMult)){ - exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000); - } - - if( (GetLevel() < RuleI(Character, DeathExpLossLevel)) || (GetLevel() > RuleI(Character, DeathExpLossMaxLevel)) || IsBecomeNPC() ) - { - exploss = 0; - } - else if( killerMob ) - { - if( killerMob->IsClient() ) - { - exploss = 0; - } - else if( killerMob->GetOwner() && killerMob->GetOwner()->IsClient() ) - { - exploss = 0; - } - } - - if(spell != SPELL_UNKNOWN) - { - uint32 buff_count = GetMaxTotalSlots(); - for(uint16 buffIt = 0; buffIt < buff_count; buffIt++) - { - if(buffs[buffIt].spellid == spell && buffs[buffIt].client) - { - exploss = 0; // no exp loss for pvp dot - break; - } - } - } - - bool LeftCorpse = false; - - // now we apply the exp loss, unmem their spells, and make a corpse - // unless they're a GM (or less than lvl 10 - if(!GetGM()) - { - if(exploss > 0) { - int32 newexp = GetEXP(); - if(exploss > newexp) { - //lost more than we have... wtf.. - newexp = 1; - } else { - newexp -= exploss; - } - SetEXP(newexp, GetAAXP()); - //m_epp.perAA = 0; //reset to no AA exp on death. - } - - //this generates a lot of 'updates' to the client that the client does not need - BuffFadeNonPersistDeath(); - if((GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover)) - UnmemSpellAll(true); - else - UnmemSpellAll(false); - - if(RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel) || RuleB(Character, LeaveNakedCorpses)) - { - // creating the corpse takes the cash/items off the player too - Corpse *new_corpse = new Corpse(this, exploss); - - char tmp[20]; - database.GetVariable("ServerType", tmp, 9); - if(atoi(tmp)==1 && killerMob != nullptr && killerMob->IsClient()){ - char tmp2[10] = {0}; - database.GetVariable("PvPreward", tmp, 9); - int reward = atoi(tmp); - if(reward==3){ - database.GetVariable("PvPitem", tmp2, 9); - int pvpitem = atoi(tmp2); - if(pvpitem>0 && pvpitem<200000) - new_corpse->SetPKItem(pvpitem); - } - else if(reward==2) - new_corpse->SetPKItem(-1); - else if(reward==1) - new_corpse->SetPKItem(1); - else - new_corpse->SetPKItem(0); - if(killerMob->CastToClient()->isgrouped) { - Group* group = entity_list.GetGroupByClient(killerMob->CastToClient()); - if(group != 0) - { - for(int i=0;i<6;i++) - { - if(group->members[i] != nullptr) - { - new_corpse->AllowMobLoot(group->members[i],i); - } - } - } - } - } - - entity_list.AddCorpse(new_corpse, GetID()); - SetID(0); - - //send the become corpse packet to everybody else in the zone. - entity_list.QueueClients(this, &app2, true); - - LeftCorpse = true; - } - -// if(!IsLD())//Todo: make it so an LDed client leaves corpse if its enabled -// MakeCorpse(exploss); - } else { - BuffFadeDetrimental(); - } - - // - // Finally, send em home - // - - // we change the mob variables, not pp directly, because Save() will copy - // from these and overwrite what we set in pp anyway - // - - if(LeftCorpse && (GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover)) - { - ClearDraggedCorpses(); - - RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000); - - SendRespawnBinds(); - } - else - { - if(isgrouped) - { - Group *g = GetGroup(); - if(g) - g->MemberZoned(this); - } - - Raid* r = entity_list.GetRaidByClient(this); - - if(r) - r->MemberZoned(this); - - dead_timer.Start(5000, true); - - m_pp.zone_id = m_pp.binds[0].zoneId; - m_pp.zoneInstance = 0; - database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id)); - - Save(); - - GoToDeath(); - } - - parse->EventPlayer(EVENT_DEATH_COMPLETE, this, buffer, 0); - return true; -} - -bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) -{ - int damage = 0; - - if (!other) { - SetTarget(nullptr); - LogFile->write(EQEMuLog::Error, "A null Mob object was passed to NPC::Attack() for evaluation!"); - return false; - } - - if(DivineAura()) - return(false); - - if(!GetTarget()) - SetTarget(other); - - //Check that we can attack before we calc heading and face our target - if (!IsAttackAllowed(other)) { - if (this->GetOwnerID()) - this->Say_StringID(NOT_LEGAL_TARGET); - if(other) { - if (other->IsClient()) - other->CastToClient()->RemoveXTarget(this, false); - RemoveFromHateList(other); - mlog(COMBAT__ATTACKS, "I am not allowed to attack %s", other->GetName()); - } - return false; - } - - FaceTarget(GetTarget()); - - SkillUseTypes skillinuse = SkillHandtoHand; - if (Hand == 13) { - skillinuse = static_cast(GetPrimSkill()); - OffHandAtk(false); - } - if (Hand == 14) { - skillinuse = static_cast(GetSecSkill()); - OffHandAtk(true); - } - - //figure out what weapon they are using, if any - const Item_Struct* weapon = nullptr; - if (Hand == 13 && equipment[SLOT_PRIMARY] > 0) - weapon = database.GetItem(equipment[SLOT_PRIMARY]); - else if (equipment[SLOT_SECONDARY]) - weapon = database.GetItem(equipment[SLOT_SECONDARY]); - - //We dont factor much from the weapon into the attack. - //Just the skill type so it doesn't look silly using punching animations and stuff while wielding weapons - if(weapon) { - mlog(COMBAT__ATTACKS, "Attacking with weapon: %s (%d) (too bad im not using it for much)", weapon->Name, weapon->ID); - - if(Hand == 14 && weapon->ItemType == ItemTypeShield){ - mlog(COMBAT__ATTACKS, "Attack with shield canceled."); - return false; - } - - switch(weapon->ItemType){ - case ItemType1HSlash: - skillinuse = Skill1HSlashing; - break; - case ItemType2HSlash: - skillinuse = Skill2HSlashing; - break; - case ItemType1HPiercing: - //skillinuse = Skill1HPiercing; - //break; - case ItemType2HPiercing: - skillinuse = Skill1HPiercing; // change to Skill2HPiercing once activated - break; - case ItemType1HBlunt: - skillinuse = Skill1HBlunt; - break; - case ItemType2HBlunt: - skillinuse = Skill2HBlunt; - break; - case ItemTypeBow: - skillinuse = SkillArchery; - break; - case ItemTypeLargeThrowing: - case ItemTypeSmallThrowing: - skillinuse = SkillThrowing; - break; - default: - skillinuse = SkillHandtoHand; - break; - } - } - - int weapon_damage = GetWeaponDamage(other, weapon); - - //do attack animation regardless of whether or not we can hit below - int16 charges = 0; - ItemInst weapon_inst(weapon, charges); - AttackAnimation(skillinuse, Hand, &weapon_inst); - - // Remove this once Skill2HPiercing is activated - //Work-around for there being no 2HP skill - We use 99 for the 2HB animation and 36 for pierce messages - if(skillinuse == 99) - skillinuse = static_cast(36); - - //basically "if not immune" then do the attack - if((weapon_damage) > 0) { - - //ele and bane dmg too - //NPCs add this differently than PCs - //if NPCs can't inheriently hit the target we don't add bane/magic dmg which isn't exactly the same as PCs - uint16 eleBane = 0; - if(weapon){ - if(weapon->BaneDmgBody == other->GetBodyType()){ - eleBane += weapon->BaneDmgAmt; - } - - if(weapon->BaneDmgRace == other->GetRace()){ - eleBane += weapon->BaneDmgRaceAmt; - } - - if(weapon->ElemDmgAmt){ - eleBane += (weapon->ElemDmgAmt * other->ResistSpell(weapon->ElemDmgType, 0, this) / 100); - } - } - - if(!RuleB(NPC, UseItemBonusesForNonPets)){ - if(!GetOwner()){ - eleBane = 0; - } - } - - uint8 otherlevel = other->GetLevel(); - uint8 mylevel = this->GetLevel(); - - otherlevel = otherlevel ? otherlevel : 1; - mylevel = mylevel ? mylevel : 1; - - //instead of calcing damage in floats lets just go straight to ints - if(RuleB(Combat, UseIntervalAC)) - damage = (max_dmg+eleBane); - else - damage = MakeRandomInt((min_dmg+eleBane),(max_dmg+eleBane)); - - - //check if we're hitting above our max or below it. - if((min_dmg+eleBane) != 0 && damage < (min_dmg+eleBane)) { - mlog(COMBAT__DAMAGE, "Damage (%d) is below min (%d). Setting to min.", damage, (min_dmg+eleBane)); - damage = (min_dmg+eleBane); - } - if((max_dmg+eleBane) != 0 && damage > (max_dmg+eleBane)) { - mlog(COMBAT__DAMAGE, "Damage (%d) is above max (%d). Setting to max.", damage, (max_dmg+eleBane)); - damage = (max_dmg+eleBane); - } - - damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other); - - int32 hate = damage; - if(IsPet()) - { - hate = hate * 100 / GetDamageTable(skillinuse); - } - - if(other->IsClient() && other->CastToClient()->IsSitting()) { - mlog(COMBAT__DAMAGE, "Client %s is sitting. Hitting for max damage (%d).", other->GetName(), (max_dmg+eleBane)); - damage = (max_dmg+eleBane); - damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); - - if(opts) { - damage *= opts->damage_percent; - damage += opts->damage_flat; - hate *= opts->hate_percent; - hate += opts->hate_flat; - } - - mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, GetName()); - // now add done damage to the hate list - other->AddToHateList(this, hate); - - } else { - if(opts) { - damage *= opts->damage_percent; - damage += opts->damage_flat; - hate *= opts->hate_percent; - hate += opts->hate_flat; - } - - if(!other->CheckHitChance(this, skillinuse, Hand)) { - damage = 0; //miss - } else { //hit, check for damage avoidance - other->AvoidDamage(this, damage); - other->MeleeMitigation(this, damage, min_dmg+eleBane, opts); - if(damage > 0) { - ApplyMeleeDamageBonus(skillinuse, damage); - damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); - TryCriticalHit(other, skillinuse, damage, opts); - } - mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, GetName()); - // now add done damage to the hate list - if(damage > 0) - { - other->AddToHateList(this, hate); - } - else - other->AddToHateList(this, 0); - } - } - - mlog(COMBAT__DAMAGE, "Final damage against %s: %d", other->GetName(), damage); - - if(other->IsClient() && IsPet() && GetOwner()->IsClient()) { - //pets do half damage to clients in pvp - damage=damage/2; - } - } - else - damage = -5; - - //cant riposte a riposte - if (bRiposte && damage == -3) { - mlog(COMBAT__DAMAGE, "Riposte of riposte canceled."); - return false; - } - - int16 DeathHP = 0; - DeathHP = other->GetDelayDeath() * -1; - - if(GetHP() > 0 && other->GetHP() >= DeathHP) { - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, false); // Not avoidable client already had thier chance to Avoid - } else - return false; - - if (HasDied()) //killed by damage shield ect - return false; - - MeleeLifeTap(damage); - - if (damage > 0) - CheckNumHitsRemaining(5); - - //break invis when you attack - if(invisible) { - mlog(COMBAT__ATTACKS, "Removing invisibility due to melee attack."); - BuffFadeByEffect(SE_Invisibility); - BuffFadeByEffect(SE_Invisibility2); - invisible = false; - } - if(invisible_undead) { - mlog(COMBAT__ATTACKS, "Removing invisibility vs. undead due to melee attack."); - BuffFadeByEffect(SE_InvisVsUndead); - BuffFadeByEffect(SE_InvisVsUndead2); - invisible_undead = false; - } - if(invisible_animals){ - mlog(COMBAT__ATTACKS, "Removing invisibility vs. animals due to melee attack."); - BuffFadeByEffect(SE_InvisVsAnimals); - invisible_animals = false; - } - - if(hidden || improved_hidden) - { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; - sa_out->spawn_id = GetID(); - sa_out->type = 0x03; - sa_out->parameter = 0; - entity_list.QueueClients(this, outapp, true); - safe_delete(outapp); - } - - - hidden = false; - improved_hidden = false; - - //I doubt this works... - if (!GetTarget()) - return true; //We killed them - - if(!bRiposte && other->GetHP() > 0 ) { - TryWeaponProc(nullptr, weapon, other, Hand); //no weapon - TrySpellProc(nullptr, weapon, other, Hand); - } - - TriggerDefensiveProcs(nullptr, other, Hand, damage); - - // now check ripostes - if (damage == -3) { // riposting - DoRiposte(other); - } - - if (damage > 0) - return true; - - else - return false; -} - -void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) { - if(spell_id==0) - spell_id = SPELL_UNKNOWN; - - //handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds - if(attacked_timer.Check()) - { - mlog(COMBAT__HITS, "Triggering EVENT_ATTACK due to attack by %s", other->GetName()); - parse->EventNPC(EVENT_ATTACK, this, other, "", 0); - } - attacked_timer.Start(CombatEventTimer_expire); - - if (!IsEngaged()) - zone->AddAggroMob(); - - if(GetClass() == LDON_TREASURE) - { - if(IsLDoNLocked() && GetLDoNLockedSkill() != LDoNTypeMechanical) - { - damage = -5; - } - else - { - if(IsLDoNTrapped()) - { - Message_StringID(13, LDON_ACCIDENT_SETOFF2); - SpellFinished(GetLDoNTrapSpellID(), other, 10, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false); - SetLDoNTrapSpellID(0); - SetLDoNTrapped(false); - SetLDoNTrapDetected(false); - } - } - } - - //do a majority of the work... - CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); - - if(damage > 0) { - //see if we are gunna start fleeing - if(!IsPet()) CheckFlee(); - } -} - -bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) { - mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob->GetName(), damage, spell, attack_skill); - - Mob *oos = nullptr; - if(killerMob) { - oos = killerMob->GetOwnerOrSelf(); - - char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); - if(parse->EventNPC(EVENT_DEATH, this, oos, buffer, 0) != 0) - { - if(GetHP() < 0) { - SetHP(0); - } - return false; - } - - if(killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { - char val1[20]={0}; - entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE, - killerMob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); - } - } else { - - char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); - if(parse->EventNPC(EVENT_DEATH, this, nullptr, buffer, 0) != 0) - { - if(GetHP() < 0) { - SetHP(0); - } - return false; - } - } - - if (IsEngaged()) - { - zone->DelAggroMob(); -#if EQDEBUG >= 11 - LogFile->write(EQEMuLog::Debug,"NPC::Death() Mobs currently Aggro %i", zone->MobsAggroCount()); -#endif - } - SetHP(0); - SetPet(0); - Mob* killer = GetHateDamageTop(this); - - entity_list.RemoveFromTargets(this, p_depop); - - if(p_depop == true) - return false; - - BuffFadeAll(); - uint8 killed_level = GetLevel(); - - EQApplicationPacket* app= new EQApplicationPacket(OP_Death,sizeof(Death_Struct)); - Death_Struct* d = (Death_Struct*)app->pBuffer; - d->spawn_id = GetID(); - d->killer_id = killerMob ? killerMob->GetID() : 0; - d->bindzoneid = 0; - d->spell_id = spell == SPELL_UNKNOWN ? 0xffffffff : spell; - d->attack_skill = SkillDamageTypes[attack_skill]; - d->damage = damage; - app->priority = 6; - entity_list.QueueClients(killerMob, app, false); - - if(respawn2) { - respawn2->DeathReset(1); - } - - if (killerMob) { - if(GetClass() != LDON_TREASURE) - hate_list.Add(killerMob, damage); - } - - safe_delete(app); - - Mob *give_exp = hate_list.GetDamageTop(this); - - if(give_exp == nullptr) - give_exp = killer; - - if(give_exp && give_exp->HasOwner()) { - - bool ownerInGroup = false; - if((give_exp->HasGroup() && give_exp->GetGroup()->IsGroupMember(give_exp->GetUltimateOwner())) - || (give_exp->IsPet() && (give_exp->GetOwner()->IsClient() - || ( give_exp->GetOwner()->HasGroup() && give_exp->GetOwner()->GetGroup()->IsGroupMember(give_exp->GetOwner()->GetUltimateOwner()))))) - ownerInGroup = true; - - give_exp = give_exp->GetUltimateOwner(); - -#ifdef BOTS - if(!RuleB(Bots, BotGroupXP) && !ownerInGroup) { - give_exp = nullptr; - } -#endif //BOTS - } - - int PlayerCount = 0; // QueryServ Player Counting - - Client *give_exp_client = nullptr; - if(give_exp && give_exp->IsClient()) - give_exp_client = give_exp->CastToClient(); - - bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE); - if (give_exp_client && !IsCorpse() && MerchantType == 0) - { - Group *kg = entity_list.GetGroupByClient(give_exp_client); - Raid *kr = entity_list.GetRaidByClient(give_exp_client); - - int32 finalxp = EXP_FORMULA; - finalxp = give_exp_client->mod_client_xp(finalxp, this); - - if(kr) - { - if(!IsLdonTreasure) { - kr->SplitExp((finalxp), this); - if(killerMob && (kr->IsRaidMember(killerMob->GetName()) || kr->IsRaidMember(killerMob->GetUltimateOwner()->GetName()))) - killerMob->TrySpellOnKill(killed_level,spell); - } - /* Send the EVENT_KILLED_MERIT event for all raid members */ - for (int i = 0; i < MAX_RAID_MEMBERS; i++) { - if (kr->members[i].member != nullptr) { // If Group Member is Client - parse->EventNPC(EVENT_KILLED_MERIT, this, kr->members[i].member, "killed", 0); - - mod_npc_killed_merit(kr->members[i].member); - - if(RuleB(TaskSystem, EnableTaskSystem)) - kr->members[i].member->UpdateTasksOnKill(GetNPCTypeID()); - PlayerCount++; - } - } - - // QueryServ Logging - Raid Kills - if(RuleB(QueryServ, PlayerLogNPCKills)){ - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); - PlayerCount = 0; - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; - QS->s1.NPCID = this->GetNPCTypeID(); - QS->s1.ZoneID = this->GetZoneID(); - QS->s1.Type = 2; // Raid Fight - for (int i = 0; i < MAX_RAID_MEMBERS; i++) { - if (kr->members[i].member != nullptr) { // If Group Member is Client - Client *c = kr->members[i].member; - QS->Chars[PlayerCount].char_id = c->CharacterID(); - PlayerCount++; - } - } - worldserver.SendPacket(pack); // Send Packet to World - safe_delete(pack); - } - // End QueryServ Logging - - } - else if (give_exp_client->IsGrouped() && kg != nullptr) - { - if(!IsLdonTreasure) { - kg->SplitExp((finalxp), this); - if(killerMob && (kg->IsGroupMember(killerMob->GetName()) || kg->IsGroupMember(killerMob->GetUltimateOwner()->GetName()))) - killerMob->TrySpellOnKill(killed_level,spell); - } - /* Send the EVENT_KILLED_MERIT event and update kill tasks - * for all group members */ - for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (kg->members[i] != nullptr && kg->members[i]->IsClient()) { // If Group Member is Client - Client *c = kg->members[i]->CastToClient(); - parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); - - mod_npc_killed_merit(c); - - if(RuleB(TaskSystem, EnableTaskSystem)) - c->UpdateTasksOnKill(GetNPCTypeID()); - - PlayerCount++; - } - } - - // QueryServ Logging - Group Kills - if(RuleB(QueryServ, PlayerLogNPCKills)){ - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); - PlayerCount = 0; - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; - QS->s1.NPCID = this->GetNPCTypeID(); - QS->s1.ZoneID = this->GetZoneID(); - QS->s1.Type = 1; // Group Fight - for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (kg->members[i] != nullptr && kg->members[i]->IsClient()) { // If Group Member is Client - Client *c = kg->members[i]->CastToClient(); - QS->Chars[PlayerCount].char_id = c->CharacterID(); - PlayerCount++; - } - } - worldserver.SendPacket(pack); // Send Packet to World - safe_delete(pack); - } - // End QueryServ Logging - } - else - { - if(!IsLdonTreasure) { - int conlevel = give_exp->GetLevelCon(GetLevel()); - if (conlevel != CON_GREEN) - { - if(GetOwner() && GetOwner()->IsClient()){ - } - else { - give_exp_client->AddEXP((finalxp), conlevel); // Pyro: Comment this if NPC death crashes zone - if(killerMob && (killerMob->GetID() == give_exp_client->GetID() || killerMob->GetUltimateOwner()->GetID() == give_exp_client->GetID())) - killerMob->TrySpellOnKill(killed_level,spell); - } - } - } - /* Send the EVENT_KILLED_MERIT event */ - parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); - - mod_npc_killed_merit(give_exp_client); - - if(RuleB(TaskSystem, EnableTaskSystem)) - give_exp_client->UpdateTasksOnKill(GetNPCTypeID()); - - // QueryServ Logging - Solo - if(RuleB(QueryServ, PlayerLogNPCKills)){ - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1)); - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; - QS->s1.NPCID = this->GetNPCTypeID(); - QS->s1.ZoneID = this->GetZoneID(); - QS->s1.Type = 0; // Solo Fight - Client *c = give_exp_client; - QS->Chars[0].char_id = c->CharacterID(); - PlayerCount++; - worldserver.SendPacket(pack); // Send Packet to World - safe_delete(pack); - } - // End QueryServ Logging - } - } - - //do faction hits even if we are a merchant, so long as a player killed us - if(give_exp_client) - hate_list.DoFactionHits(GetNPCFactionID()); - - if (!HasOwner() && !IsMerc() && class_ != MERCHANT && class_ != ADVENTUREMERCHANT && !GetSwarmInfo() - && MerchantType == 0 && killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) || - (killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient()))) - { - if(killer != 0) - { - if(killer->GetOwner() != 0 && killer->GetOwner()->IsClient()) - killer = killer->GetOwner(); - - if(!killer->CastToClient()->GetGM() && killer->IsClient()) - this->CheckMinMaxLevel(killer); - } - entity_list.RemoveFromAutoXTargets(this); - uint16 emoteid = this->GetEmoteID(); - Corpse* corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata,level>54?RuleI(NPC,MajorNPCCorpseDecayTimeMS):RuleI(NPC,MinorNPCCorpseDecayTimeMS)); - entity_list.LimitRemoveNPC(this); - entity_list.AddCorpse(corpse, GetID()); - - entity_list.UnMarkNPC(GetID()); - entity_list.RemoveNPC(GetID()); - this->SetID(0); - if(killer != 0 && emoteid != 0) - corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid); - if(killer != 0 && killer->IsClient()) { - corpse->AllowMobLoot(killer, 0); - if(killer->IsGrouped()) { - Group* group = entity_list.GetGroupByClient(killer->CastToClient()); - if(group != 0) { - for(int i=0;i<6;i++) { // Doesnt work right, needs work - if(group->members[i] != nullptr) { - corpse->AllowMobLoot(group->members[i],i); - } - } - } - } - else if(killer->IsRaidGrouped()){ - Raid* r = entity_list.GetRaidByClient(killer->CastToClient()); - if(r){ - int i = 0; - for(int x = 0; x < MAX_RAID_MEMBERS; x++) - { - switch(r->GetLootType()) - { - case 0: - case 1: - if(r->members[x].member && r->members[x].IsRaidLeader){ - corpse->AllowMobLoot(r->members[x].member, i); - i++; - } - break; - case 2: - if(r->members[x].member && r->members[x].IsRaidLeader){ - corpse->AllowMobLoot(r->members[x].member, i); - i++; - } - else if(r->members[x].member && r->members[x].IsGroupLeader){ - corpse->AllowMobLoot(r->members[x].member, i); - i++; - } - break; - case 3: - if(r->members[x].member && r->members[x].IsLooter){ - corpse->AllowMobLoot(r->members[x].member, i); - i++; - } - break; - case 4: - if(r->members[x].member) - { - corpse->AllowMobLoot(r->members[x].member, i); - i++; - } - break; - } - } - } - } - } - - if(zone && zone->adv_data) - { - ServerZoneAdventureDataReply_Struct *sr = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; - if(sr->type == Adventure_Kill) - { - zone->DoAdventureCountIncrease(); - } - else if(sr->type == Adventure_Assassinate) - { - if(sr->data_id == GetNPCTypeID()) - { - zone->DoAdventureCountIncrease(); - } - else - { - zone->DoAdventureAssassinationCountIncrease(); - } - } - } - } - else - entity_list.RemoveFromXTargets(this); - - // Parse quests even if we're killed by an NPC - if(oos) { - mod_npc_killed(oos); - - uint16 emoteid = this->GetEmoteID(); - if(emoteid != 0) - this->DoNPCEmote(ONDEATH, emoteid); - if(oos->IsNPC()) - { - parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0); - uint16 emoteid = oos->GetEmoteID(); - if(emoteid != 0) - oos->CastToNPC()->DoNPCEmote(KILLEDNPC, emoteid); - killerMob->TrySpellOnKill(killed_level, spell); - } - } - - WipeHateList(); - p_depop = true; - if(killerMob && killerMob->GetTarget() == this) //we can kill things without having them targeted - killerMob->SetTarget(nullptr); //via AE effects and such.. - - entity_list.UpdateFindableNPCState(this, true); - - char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); - parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, buffer, 0); - return true; -} - -void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) { - - assert(other != nullptr); - - if (other == this) - return; - - if(damage < 0){ - hate = 1; - } - - bool wasengaged = IsEngaged(); - Mob* owner = other->GetOwner(); - Mob* mypet = this->GetPet(); - Mob* myowner = this->GetOwner(); - Mob* targetmob = this->GetTarget(); - - if(other){ - AddRampage(other); - int hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod; - - int16 shieldhatemod = other->spellbonuses.ShieldEquipHateMod + other->itembonuses.ShieldEquipHateMod + other->aabonuses.ShieldEquipHateMod; - - if (shieldhatemod && other->HasShieldEquiped()) - hatemod += shieldhatemod; - - if(hatemod < 1) - hatemod = 1; - hate = ((hate * (hatemod))/100); - } - - if(IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && !IsFocused()) { //ignore aggro if hold and !focus - return; - } - - if(IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && GetOwner()->GetAA(aaAdvancedPetDiscipline) >= 1 && IsFocused()) { - if (!targetmob) - return; - } - - if (other->IsNPC() && (other->IsPet() || other->CastToNPC()->GetSwarmOwner() > 0)) - TryTriggerOnValueAmount(false, false, false, true); - - if(IsClient() && !IsAIControlled()) - return; - - if(IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO)) - return; - - if (other == myowner) - return; - - if(other->GetSpecialAbility(IMMUNE_AGGRO_ON)) - return; - - if(GetSpecialAbility(NPC_TUNNELVISION)) { - int tv_mod = GetSpecialAbilityParam(NPC_TUNNELVISION, 0); - - Mob *top = GetTarget(); - if(top && top != other) { - if(tv_mod) { - float tv = tv_mod / 100.0f; - hate *= tv; - } else { - hate *= RuleR(Aggro, TunnelVisionAggroMod); - } - } - } - - if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { - if(!zone->watermap->InLiquid(other->GetX(), other->GetY(), other->GetZ())) { - return; - } - } - // first add self - - // The damage on the hate list is used to award XP to the killer. This check is to prevent Killstealing. - // e.g. Mob has 5000 hit points, Player A melees it down to 500 hp, Player B executes a headshot (10000 damage). - // If we add 10000 damage, Player B would get the kill credit, so we only award damage credit to player B of the - // amount of HP the mob had left. - // - if(damage > GetHP()) - damage = GetHP(); - - if (spellbonuses.ImprovedTaunt[1] && (GetLevel() < spellbonuses.ImprovedTaunt[0]) - && other && (buffs[spellbonuses.ImprovedTaunt[2]].casterid != other->GetID())) - hate = (hate*spellbonuses.ImprovedTaunt[1])/100; - - hate_list.Add(other, hate, damage, bFrenzy, !iBuffTic); - - if(other->IsClient()) - other->CastToClient()->AddAutoXTarget(this); - -#ifdef BOTS - // if other is a bot, add the bots client to the hate list - if(other->IsBot()) { - if(other->CastToBot()->GetBotOwner() && other->CastToBot()->GetBotOwner()->CastToClient()->GetFeigned()) { - AddFeignMemory(other->CastToBot()->GetBotOwner()->CastToClient()); - } - else { - if(!hate_list.IsOnHateList(other->CastToBot()->GetBotOwner())) - hate_list.Add(other->CastToBot()->GetBotOwner(), 0, 0, false, true); - } - } -#endif //BOTS - - - // if other is a merc, add the merc client to the hate list - if(other->IsMerc()) { - if(other->CastToMerc()->GetMercOwner() && other->CastToMerc()->GetMercOwner()->CastToClient()->GetFeigned()) { - AddFeignMemory(other->CastToMerc()->GetMercOwner()->CastToClient()); - } - else { - if(!hate_list.IsOnHateList(other->CastToMerc()->GetMercOwner())) - hate_list.Add(other->CastToMerc()->GetMercOwner(), 0, 0, false, true); - } - } //MERC - - // then add pet owner if there's one - if (owner) { // Other is a pet, add him and it - // EverHood 6/12/06 - // Can't add a feigned owner to hate list - if(owner->IsClient() && owner->CastToClient()->GetFeigned()) { - //they avoid hate due to feign death... - } else { - // cb:2007-08-17 - // owner must get on list, but he's not actually gained any hate yet - if(!owner->GetSpecialAbility(IMMUNE_AGGRO)) - { - hate_list.Add(owner, 0, 0, false, !iBuffTic); - if(owner->IsClient()) - owner->CastToClient()->AddAutoXTarget(this); - } - } - } - - if (mypet && (!(GetAA(aaPetDiscipline) && mypet->IsHeld()))) { // I have a pet, add other to it - if(!mypet->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO)) - mypet->hate_list.Add(other, 0, 0, bFrenzy); - } else if (myowner) { // I am a pet, add other to owner if it's NPC/LD - if (myowner->IsAIControlled() && !myowner->GetSpecialAbility(IMMUNE_AGGRO)) - myowner->hate_list.Add(other, 0, 0, bFrenzy); - } - if (!wasengaged) { - if(IsNPC() && other->IsClient() && other->CastToClient()) - parse->EventNPC(EVENT_AGGRO, this->CastToNPC(), other, "", 0); - AI_Event_Engaged(other, iYellForHelp); - } -} - -// solar: this is called from Damage() when 'this' is attacked by 'other. -// 'this' is the one being attacked -// 'other' is the attacker -// a damage shield causes damage (or healing) to whoever attacks the wearer -// a reverse ds causes damage to the wearer whenever it attack someone -// given this, a reverse ds must be checked each time the wearer is attacking -// and not when they're attacked -//a damage shield on a spell is a negative value but on an item it's a positive value so add the spell value and subtract the item value to get the end ds value -void Mob::DamageShield(Mob* attacker, bool spell_ds) { - - if(!attacker || this == attacker) - return; - - int DS = 0; - int rev_ds = 0; - uint16 spellid = 0; - - if(!spell_ds) - { - DS = spellbonuses.DamageShield; - rev_ds = attacker->spellbonuses.ReverseDamageShield; - - if(spellbonuses.DamageShieldSpellID != 0 && spellbonuses.DamageShieldSpellID != SPELL_UNKNOWN) - spellid = spellbonuses.DamageShieldSpellID; - } - else { - DS = spellbonuses.SpellDamageShield; - rev_ds = 0; - // This ID returns "you are burned", seemed most appropriate for spell DS - spellid = 2166; - } - - if(DS == 0 && rev_ds == 0) - return; - - mlog(COMBAT__HITS, "Applying Damage Shield of value %d to %s", DS, attacker->GetName()); - - //invert DS... spells yield negative values for a true damage shield - if(DS < 0) { - if(!spell_ds) { - - DS += aabonuses.DamageShield; //Live AA - coat of thistles. (negative value) - DS -= itembonuses.DamageShield; //+Damage Shield should only work when you already have a DS spell - - //Spell data for damage shield mitigation shows a negative value for spells for clients and positive - //value for spells that effect pets. Unclear as to why. For now will convert all positive to be consistent. - if (attacker->IsOffHandAtk()){ - int16 mitigation = attacker->itembonuses.DSMitigationOffHand + - attacker->spellbonuses.DSMitigationOffHand + - attacker->aabonuses.DSMitigationOffHand; - DS -= DS*mitigation/100; - } - DS -= DS * attacker->itembonuses.DSMitigation / 100; - } - attacker->Damage(this, -DS, spellid, SkillAbjuration/*hackish*/, false); - //we can assume there is a spell now - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); - CombatDamage_Struct* cds = (CombatDamage_Struct*)outapp->pBuffer; - cds->target = attacker->GetID(); - cds->source = GetID(); - cds->type = spellbonuses.DamageShieldType; - cds->spellid = 0x0; - cds->damage = DS; - entity_list.QueueCloseClients(this, outapp); - safe_delete(outapp); - } else if (DS > 0 && !spell_ds) { - //we are healing the attacker... - attacker->HealDamage(DS); - //TODO: send a packet??? - } - - //Reverse DS - //this is basically a DS, but the spell is on the attacker, not the attackee - //if we've gotten to this point, we know we know "attacker" hit "this" (us) for damage & we aren't invulnerable - uint16 rev_ds_spell_id = SPELL_UNKNOWN; - - if(spellbonuses.ReverseDamageShieldSpellID != 0 && spellbonuses.ReverseDamageShieldSpellID != SPELL_UNKNOWN) - rev_ds_spell_id = spellbonuses.ReverseDamageShieldSpellID; - - if(rev_ds < 0) { - mlog(COMBAT__HITS, "Applying Reverse Damage Shield of value %d to %s", rev_ds, attacker->GetName()); - attacker->Damage(this, -rev_ds, rev_ds_spell_id, SkillAbjuration/*hackish*/, false); //"this" (us) will get the hate, etc. not sure how this works on Live, but it'll works for now, and tanks will love us for this - //do we need to send a damage packet here also? - } -} - -uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) -{ - // This function calculates and returns the damage bonus for the weapon identified by the parameter "Weapon". - // Modified 9/21/2008 by Cantus - - - // Assert: This function should only be called for hits by the mainhand, as damage bonuses apply only to the - // weapon in the primary slot. Be sure to check that Hand == 13 before calling. - - // Assert: The caller should ensure that Weapon is actually a weapon before calling this function. - // The ItemInst::IsWeapon() method can be used to quickly determine this. - - // Assert: This function should not be called if the player's level is below 28, as damage bonuses do not begin - // to apply until level 28. - - // Assert: This function should not be called unless the player is a melee class, as casters do not receive a damage bonus. - - - if( Weapon == nullptr || Weapon->ItemType == ItemType1HSlash || Weapon->ItemType == ItemType1HBlunt || Weapon->ItemType == ItemTypeMartial || Weapon->ItemType == ItemType1HPiercing ) - { - // The weapon in the player's main (primary) hand is a one-handed weapon, or there is no item equipped at all. - // - // According to player posts on Allakhazam, 1H damage bonuses apply to bare fists (nothing equipped in the mainhand, - // as indicated by Weapon == nullptr). - // - // The following formula returns the correct damage bonus for all 1H weapons: - - return (uint8) ((GetLevel() - 25) / 3); - } - - // If we've gotten to this point, the weapon in the mainhand is a two-handed weapon. - // Calculating damage bonuses for 2H weapons is more complicated, as it's based on PC level AND the delay of the weapon. - // The formula to calculate 2H bonuses is HIDEOUS. It's a huge conglomeration of ternary operators and multiple operations. - // - // The following is a hybrid approach. In cases where the Level and Delay merit a formula that does not use many operators, - // the formula is used. In other cases, lookup tables are used for speed. - // Though the following code may look bloated and ridiculous, it's actually a very efficient way of calculating these bonuses. - - // Player Level is used several times in the code below, so save it into a variable. - // If GetLevel() were an ordinary function, this would DEFINITELY make sense, as it'd cut back on all of the function calling - // overhead involved with multiple calls to GetLevel(). But in this case, GetLevel() is a simple, inline accessor method. - // So it probably doesn't matter. If anyone knows for certain that there is no overhead involved with calling GetLevel(), - // as I suspect, then please feel free to delete the following line, and replace all occurences of "ucPlayerLevel" with "GetLevel()". - uint8 ucPlayerLevel = (uint8) GetLevel(); - - - // The following may look cleaner, and would certainly be easier to understand, if it was - // a simple 53x150 cell matrix. - // - // However, that would occupy 7,950 Bytes of memory (7.76 KB), and would likely result - // in "thrashing the cache" when performing lookups. - // - // Initially, I thought the best approach would be to reverse-engineer the formula used by - // Sony/Verant to calculate these 2H weapon damage bonuses. But the more than Reno and I - // worked on figuring out this formula, the more we're concluded that the formula itself ugly - // (that is, it contains so many operations and conditionals that it's fairly CPU intensive). - // Because of that, we're decided that, in most cases, a lookup table is the most efficient way - // to calculate these damage bonuses. - // - // The code below is a hybrid between a pure formulaic approach and a pure, brute-force - // lookup table. In cases where a formula is the best bet, I use a formula. In other places - // where a formula would be ugly, I use a lookup table in the interests of speed. - - - if( Weapon->Delay <= 27 ) - { - // Damage Bonuses for all 2H weapons with delays of 27 or less are identical. - // They are the same as the damage bonus would be for a corresponding 1H weapon, plus one. - // This formula applies to all levels 28-80, and will probably continue to apply if - - // the level cap on Live ever is increased beyond 80. - - return (ucPlayerLevel - 22) / 3; - } - - - if( ucPlayerLevel == 65 && Weapon->Delay <= 59 ) - { - // Consider these two facts: - // * Level 65 is the maximum level on many EQ Emu servers. - // * If you listed the levels of all characters logged on to a server, odds are that the number you'll - // see most frequently is level 65. That is, there are more level 65 toons than any other single level. - // - // Therefore, if we can optimize this function for level 65 toons, we're speeding up the server! - // - // With that goal in mind, I create an array of Damage Bonuses for level 65 characters wielding 2H weapons with - // delays between 28 and 59 (inclusive). I suspect that this one small lookup array will therefore handle - // many of the calls to this function. - - static const uint8 ucLevel65DamageBonusesForDelays28to59[] = {35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 42, 42, 42, 45, 45, 47, 48, 49, 49, 51, 51, 52, 53, 54, 54, 56, 56, 57, 58, 59}; - - return ucLevel65DamageBonusesForDelays28to59[Weapon->Delay-28]; - } - - - if( ucPlayerLevel > 65 ) - { - if( ucPlayerLevel > 80 ) - { - // As level 80 is currently the highest achievable level on Live, we only include - // damage bonus information up to this level. - // - // If there is a custom EQEmu server that allows players to level beyond 80, the - // damage bonus for their 2H weapons will simply not increase beyond their damage - // bonus at level 80. - - ucPlayerLevel = 80; - } - - // Lucy does not list a chart of damage bonuses for players levels 66+, - // so my original version of this function just applied the level 65 damage - // bonus for level 66+ toons. That sucked for higher level toons, as their - // 2H weapons stopped ramping up in DPS as they leveled past 65. - // - // Thanks to the efforts of two guys, this is no longer the case: - // - // Janusd (Zetrakyl) ran a nifty query against the PEQ item database to list - // the name of an example 2H weapon that represents each possible unique 2H delay. - // - // Romai then wrote an excellent script to automatically look up each of those - // weapons, open the Lucy item page associated with it, and iterate through all - // levels in the range 66 - 80. He saved the damage bonus for that weapon for - // each level, and that forms the basis of the lookup tables below. - - if( Weapon->Delay <= 59 ) - { - static const uint8 ucDelay28to59Levels66to80[32][15]= - { - /* Level: */ - /* 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 */ - - {36, 37, 38, 39, 41, 42, 43, 44, 45, 47, 49, 49, 49, 50, 53}, /* Delay = 28 */ - {36, 38, 38, 39, 42, 43, 43, 45, 46, 48, 49, 50, 51, 52, 54}, /* Delay = 29 */ - {37, 38, 39, 40, 43, 43, 44, 46, 47, 48, 50, 51, 52, 53, 55}, /* Delay = 30 */ - {37, 39, 40, 40, 43, 44, 45, 46, 47, 49, 51, 52, 52, 52, 54}, /* Delay = 31 */ - {38, 39, 40, 41, 44, 45, 45, 47, 48, 48, 50, 52, 53, 55, 57}, /* Delay = 32 */ - {38, 40, 41, 41, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 58}, /* Delay = 33 */ - {39, 40, 41, 42, 45, 46, 47, 48, 49, 51, 53, 54, 55, 57, 58}, /* Delay = 34 */ - {39, 41, 42, 43, 46, 46, 47, 49, 50, 52, 54, 55, 56, 57, 59}, /* Delay = 35 */ - {40, 41, 42, 43, 46, 47, 48, 50, 51, 53, 55, 55, 56, 58, 60}, /* Delay = 36 */ - {40, 42, 43, 44, 47, 48, 49, 50, 51, 53, 55, 56, 57, 59, 61}, /* Delay = 37 */ - {41, 42, 43, 44, 47, 48, 49, 51, 52, 54, 56, 57, 58, 60, 62}, /* Delay = 38 */ - {41, 43, 44, 45, 48, 49, 50, 52, 53, 55, 57, 58, 59, 61, 63}, /* Delay = 39 */ - {43, 45, 46, 47, 50, 51, 52, 54, 55, 57, 59, 60, 61, 63, 65}, /* Delay = 40 */ - {43, 45, 46, 47, 50, 51, 52, 54, 55, 57, 59, 60, 61, 63, 65}, /* Delay = 41 */ - {44, 46, 47, 48, 51, 52, 53, 55, 56, 58, 60, 61, 62, 64, 66}, /* Delay = 42 */ - {46, 48, 49, 50, 53, 54, 55, 58, 59, 61, 63, 64, 65, 67, 69}, /* Delay = 43 */ - {47, 49, 50, 51, 54, 55, 56, 58, 59, 61, 64, 65, 66, 68, 70}, /* Delay = 44 */ - {48, 50, 51, 52, 56, 57, 58, 60, 61, 63, 65, 66, 68, 70, 72}, /* Delay = 45 */ - {50, 52, 53, 54, 57, 58, 59, 62, 63, 65, 67, 68, 69, 71, 74}, /* Delay = 46 */ - {50, 52, 53, 55, 58, 59, 60, 62, 63, 66, 68, 69, 70, 72, 74}, /* Delay = 47 */ - {51, 53, 54, 55, 58, 60, 61, 63, 64, 66, 69, 69, 71, 73, 75}, /* Delay = 48 */ - {52, 54, 55, 57, 60, 61, 62, 65, 66, 68, 70, 71, 73, 75, 77}, /* Delay = 49 */ - {53, 55, 56, 57, 61, 62, 63, 65, 67, 69, 71, 72, 74, 76, 78}, /* Delay = 50 */ - {53, 55, 57, 58, 61, 62, 64, 66, 67, 69, 72, 73, 74, 77, 79}, /* Delay = 51 */ - {55, 57, 58, 59, 63, 64, 65, 68, 69, 71, 74, 75, 76, 78, 81}, /* Delay = 52 */ - {57, 55, 59, 60, 63, 65, 66, 68, 70, 72, 74, 76, 77, 79, 82}, /* Delay = 53 */ - {56, 58, 59, 61, 64, 65, 67, 69, 70, 73, 75, 76, 78, 80, 82}, /* Delay = 54 */ - {57, 59, 61, 62, 66, 67, 68, 71, 72, 74, 77, 78, 80, 82, 84}, /* Delay = 55 */ - {58, 60, 61, 63, 66, 68, 69, 71, 73, 75, 78, 79, 80, 83, 85}, /* Delay = 56 */ - - /* Important Note: Janusd's search for 2H weapons did not find */ - /* any 2H weapon with a delay of 57. Therefore the values below */ - /* are interpolated, not exact! */ - {59, 61, 62, 64, 67, 69, 70, 72, 74, 76, 77, 78, 81, 84, 86}, /* Delay = 57 INTERPOLATED */ - - {60, 62, 63, 65, 68, 70, 71, 74, 75, 78, 80, 81, 83, 85, 88}, /* Delay = 58 */ - - /* Important Note: Janusd's search for 2H weapons did not find */ - /* any 2H weapon with a delay of 59. Therefore the values below */ - /* are interpolated, not exact! */ - {60, 62, 64, 65, 69, 70, 72, 74, 76, 78, 81, 82, 84, 86, 89}, /* Delay = 59 INTERPOLATED */ - }; - - return ucDelay28to59Levels66to80[Weapon->Delay-28][ucPlayerLevel-66]; - } - else - { - // Delay is 60+ - - const static uint8 ucDelayOver59Levels66to80[6][15] = - { - /* Level: */ - /* 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 */ - - {61, 63, 65, 66, 70, 71, 73, 75, 77, 79, 82, 83, 85, 87, 90}, /* Delay = 60 */ - {65, 68, 69, 71, 75, 76, 78, 80, 82, 85, 87, 89, 91, 93, 96}, /* Delay = 65 */ - - /* Important Note: Currently, the only 2H weapon with a delay */ - /* of 66 is not player equippable (it's None/None). So I'm */ - /* leaving it commented out to keep this table smaller. */ - //{66, 68, 70, 71, 75, 77, 78, 81, 83, 85, 88, 90, 91, 94, 97}, /* Delay = 66 */ - - {70, 72, 74, 76, 80, 81, 83, 86, 88, 88, 90, 95, 97, 99, 102}, /* Delay = 70 */ - {82, 85, 87, 89, 89, 94, 98, 101, 103, 106, 109, 111, 114, 117, 120}, /* Delay = 85 */ - {90, 93, 96, 98, 103, 105, 107, 111, 113, 116, 120, 122, 125, 128, 131}, /* Delay = 95 */ - - /* Important Note: Currently, the only 2H weapons with delay */ - /* 100 are GM-only items purchased from vendors in Sunset Home */ - /* (cshome). Because they are highly unlikely to be used in */ - /* combat, I'm commenting it out to keep the table smaller. */ - //{95, 98, 101, 103, 108, 110, 113, 116, 119, 122, 126, 128, 131, 134, 138},/* Delay = 100 */ - - {136, 140, 144, 148, 154, 157, 161, 166, 170, 174, 179, 183, 187, 191, 196} /* Delay = 150 */ - }; - - if( Weapon->Delay < 65 ) - { - return ucDelayOver59Levels66to80[0][ucPlayerLevel-66]; - } - else if( Weapon->Delay < 70 ) - { - return ucDelayOver59Levels66to80[1][ucPlayerLevel-66]; - } - else if( Weapon->Delay < 85 ) - { - return ucDelayOver59Levels66to80[2][ucPlayerLevel-66]; - } - else if( Weapon->Delay < 95 ) - { - return ucDelayOver59Levels66to80[3][ucPlayerLevel-66]; - } - else if( Weapon->Delay < 150 ) - { - return ucDelayOver59Levels66to80[4][ucPlayerLevel-66]; - } - else - { - return ucDelayOver59Levels66to80[5][ucPlayerLevel-66]; - } - } - } - - - // If we've gotten to this point in the function without hitting a return statement, - // we know that the character's level is between 28 and 65, and that the 2H weapon's - // delay is 28 or higher. - - // The Damage Bonus values returned by this function (in the level 28-65 range) are - // based on a table of 2H Weapon Damage Bonuses provided by Lucy at the following address: - // http://lucy.allakhazam.com/dmgbonus.html - - if( Weapon->Delay <= 39 ) - { - if( ucPlayerLevel <= 53) - { - // The Damage Bonus for all 2H weapons with delays between 28 and 39 (inclusive) is the same for players level 53 and below... - static const uint8 ucDelay28to39LevelUnder54[] = {1, 1, 2, 3, 3, 3, 4, 5, 5, 6, 6, 6, 8, 8, 8, 9, 9, 10, 11, 11, 11, 12, 13, 14, 16, 17}; - - // As a note: The following formula accurately calculates damage bonuses for 2H weapons with delays in the range 28-39 (inclusive) - // for characters levels 28-50 (inclusive): - // return ( (ucPlayerLevel - 22) / 3 ) + ( (ucPlayerLevel - 25) / 5 ); - // - // However, the small lookup array used above is actually much faster. So we'll just use it instead of the formula - // - // (Thanks to Reno for helping figure out the above formula!) - - return ucDelay28to39LevelUnder54[ucPlayerLevel-28]; - } - else - { - // Use a matrix to look up the damage bonus for 2H weapons with delays between 28 and 39 wielded by characters level 54 and above. - static const uint8 ucDelay28to39Level54to64[12][11] = - { - /* Level: */ - /* 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 */ - - {17, 21, 21, 23, 25, 26, 28, 30, 31, 31, 33}, /* Delay = 28 */ - {17, 21, 22, 23, 25, 26, 29, 30, 31, 32, 34}, /* Delay = 29 */ - {18, 21, 22, 23, 25, 27, 29, 31, 32, 32, 34}, /* Delay = 30 */ - {18, 21, 22, 23, 25, 27, 29, 31, 32, 33, 34}, /* Delay = 31 */ - {18, 21, 22, 24, 26, 27, 30, 32, 32, 33, 35}, /* Delay = 32 */ - {18, 21, 22, 24, 26, 27, 30, 32, 33, 34, 35}, /* Delay = 33 */ - {18, 22, 22, 24, 26, 28, 30, 32, 33, 34, 36}, /* Delay = 34 */ - {18, 22, 23, 24, 26, 28, 31, 33, 34, 34, 36}, /* Delay = 35 */ - {18, 22, 23, 25, 27, 28, 31, 33, 34, 35, 37}, /* Delay = 36 */ - {18, 22, 23, 25, 27, 29, 31, 33, 34, 35, 37}, /* Delay = 37 */ - {18, 22, 23, 25, 27, 29, 32, 34, 35, 36, 38}, /* Delay = 38 */ - {18, 22, 23, 25, 27, 29, 32, 34, 35, 36, 38} /* Delay = 39 */ - }; - - return ucDelay28to39Level54to64[Weapon->Delay-28][ucPlayerLevel-54]; - } - } - else if( Weapon->Delay <= 59 ) - { - if( ucPlayerLevel <= 52 ) - { - if( Weapon->Delay <= 45 ) - { - static const uint8 ucDelay40to45Levels28to52[6][25] = - { - /* Level: */ - /* 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52 */ - - {2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 7, 7, 9, 9, 9, 10, 10, 11, 12, 12, 12, 13, 14, 16, 18}, /* Delay = 40 */ - {2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 7, 7, 9, 9, 9, 10, 10, 11, 12, 12, 12, 13, 14, 16, 18}, /* Delay = 41 */ - {2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 7, 7, 9, 9, 9, 10, 10, 11, 12, 12, 12, 13, 14, 16, 18}, /* Delay = 42 */ - {4, 4, 5, 6, 6, 6, 7, 8, 8, 9, 9, 9, 11, 11, 11, 12, 12, 13, 14, 14, 14, 15, 16, 18, 20}, /* Delay = 43 */ - {4, 4, 5, 6, 6, 6, 7, 8, 8, 9, 9, 9, 11, 11, 11, 12, 12, 13, 14, 14, 14, 15, 16, 18, 20}, /* Delay = 44 */ - {5, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 10, 12, 12, 12, 13, 13, 14, 15, 15, 15, 16, 17, 19, 21} /* Delay = 45 */ - }; - - return ucDelay40to45Levels28to52[Weapon->Delay-40][ucPlayerLevel-28]; - } - else - { - static const uint8 ucDelay46Levels28to52[] = {6, 6, 7, 8, 8, 8, 9, 10, 10, 11, 11, 11, 13, 13, 13, 14, 14, 15, 16, 16, 16, 17, 18, 20, 22}; - - return ucDelay46Levels28to52[ucPlayerLevel-28] + ((Weapon->Delay-46) / 3); - } - } - else - { - // Player is in the level range 53 - 64 - - // Calculating damage bonus for 2H weapons with a delay between 40 and 59 (inclusive) involves, unforunately, a brute-force matrix lookup. - static const uint8 ucDelay40to59Levels53to64[20][37] = - { - /* Level: */ - /* 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 */ - - {19, 20, 24, 25, 27, 29, 31, 34, 36, 37, 38, 40}, /* Delay = 40 */ - {19, 20, 24, 25, 27, 29, 31, 34, 36, 37, 38, 40}, /* Delay = 41 */ - {19, 20, 24, 25, 27, 29, 31, 34, 36, 37, 38, 40}, /* Delay = 42 */ - {21, 22, 26, 27, 29, 31, 33, 37, 39, 40, 41, 43}, /* Delay = 43 */ - {21, 22, 26, 27, 29, 32, 34, 37, 39, 40, 41, 43}, /* Delay = 44 */ - {22, 23, 27, 28, 31, 33, 35, 38, 40, 42, 43, 45}, /* Delay = 45 */ - {23, 24, 28, 30, 32, 34, 36, 40, 42, 43, 44, 46}, /* Delay = 46 */ - {23, 24, 29, 30, 32, 34, 37, 40, 42, 43, 44, 47}, /* Delay = 47 */ - {23, 24, 29, 30, 32, 35, 37, 40, 43, 44, 45, 47}, /* Delay = 48 */ - {24, 25, 30, 31, 34, 36, 38, 42, 44, 45, 46, 49}, /* Delay = 49 */ - {24, 26, 30, 31, 34, 36, 39, 42, 44, 46, 47, 49}, /* Delay = 50 */ - {24, 26, 30, 31, 34, 36, 39, 42, 45, 46, 47, 49}, /* Delay = 51 */ - {25, 27, 31, 33, 35, 38, 40, 44, 46, 47, 49, 51}, /* Delay = 52 */ - {25, 27, 31, 33, 35, 38, 40, 44, 46, 48, 49, 51}, /* Delay = 53 */ - {26, 27, 32, 33, 36, 38, 41, 44, 47, 48, 49, 52}, /* Delay = 54 */ - {27, 28, 33, 34, 37, 39, 42, 46, 48, 50, 51, 53}, /* Delay = 55 */ - {27, 28, 33, 34, 37, 40, 42, 46, 49, 50, 51, 54}, /* Delay = 56 */ - {27, 28, 33, 34, 37, 40, 43, 46, 49, 50, 52, 54}, /* Delay = 57 */ - {28, 29, 34, 36, 39, 41, 44, 48, 50, 52, 53, 56}, /* Delay = 58 */ - {28, 29, 34, 36, 39, 41, 44, 48, 51, 52, 54, 56} /* Delay = 59 */ - }; - - return ucDelay40to59Levels53to64[Weapon->Delay-40][ucPlayerLevel-53]; - } - } - else - { - // The following table allows us to look up Damage Bonuses for weapons with delays greater than or equal to 60. - // - // There aren't a lot of 2H weapons with a delay greater than 60. In fact, both a database and Lucy search run by janusd confirm - // that the only unique 2H delays greater than 60 are: 65, 70, 85, 95, and 150. - // - // To be fair, there are also weapons with delays of 66 and 100. But they are either not equippable (None/None), or are - // only available to GMs from merchants in Sunset Home (cshome). In order to keep this table "lean and mean", I will not - // include the values for delays 66 and 100. If they ever are wielded, the 66 delay weapon will use the 65 delay bonuses, - // and the 100 delay weapon will use the 95 delay bonuses. So it's not a big deal. - // - // Still, if someone in the future decides that they do want to include them, here are the tables for these two delays: - // - // {12, 12, 13, 14, 14, 14, 15, 16, 16, 17, 17, 17, 19, 19, 19, 20, 20, 21, 22, 22, 22, 23, 24, 26, 29, 30, 32, 37, 39, 42, 45, 48, 53, 55, 57, 59, 61, 64} /* Delay = 66 */ - // {24, 24, 25, 26, 26, 26, 27, 28, 28, 29, 29, 29, 31, 31, 31, 32, 32, 33, 34, 34, 34, 35, 36, 39, 43, 45, 48, 55, 57, 62, 66, 71, 77, 80, 83, 85, 89, 92} /* Delay = 100 */ - // - // In case there are 2H weapons added in the future with delays other than those listed above (and until the damage bonuses - // associated with that new delay are added to this function), this function is designed to do the following: - // - // For weapons with delays in the range 60-64, use the Damage Bonus that would apply to a 2H weapon with delay 60. - // For weapons with delays in the range 65-69, use the Damage Bonus that would apply to a 2H weapon with delay 65 - // For weapons with delays in the range 70-84, use the Damage Bonus that would apply to a 2H weapon with delay 70. - // For weapons with delays in the range 85-94, use the Damage Bonus that would apply to a 2H weapon with delay 85. - // For weapons with delays in the range 95-149, use the Damage Bonus that would apply to a 2H weapon with delay 95. - // For weapons with delays 150 or higher, use the Damage Bonus that would apply to a 2H weapon with delay 150. - - static const uint8 ucDelayOver59Levels28to65[6][38] = - { - /* Level: */ - /* 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64. 65 */ - - {10, 10, 11, 12, 12, 12, 13, 14, 14, 15, 15, 15, 17, 17, 17, 18, 18, 19, 20, 20, 20, 21, 22, 24, 27, 28, 30, 35, 36, 39, 42, 45, 49, 51, 53, 54, 57, 59}, /* Delay = 60 */ - {12, 12, 13, 14, 14, 14, 15, 16, 16, 17, 17, 17, 19, 19, 19, 20, 20, 21, 22, 22, 22, 23, 24, 26, 29, 30, 32, 37, 39, 42, 45, 48, 52, 55, 57, 58, 61, 63}, /* Delay = 65 */ - {14, 14, 15, 16, 16, 16, 17, 18, 18, 19, 19, 19, 21, 21, 21, 22, 22, 23, 24, 24, 24, 25, 26, 28, 31, 33, 35, 40, 42, 45, 48, 52, 56, 59, 61, 62, 65, 68}, /* Delay = 70 */ - {19, 19, 20, 21, 21, 21, 22, 23, 23, 24, 24, 24, 26, 26, 26, 27, 27, 28, 29, 29, 29, 30, 31, 34, 37, 39, 41, 47, 49, 54, 57, 61, 66, 69, 72, 74, 77, 80}, /* Delay = 85 */ - {22, 22, 23, 24, 24, 24, 25, 26, 26, 27, 27, 27, 29, 29, 29, 30, 30, 31, 32, 32, 32, 33, 34, 37, 40, 43, 45, 52, 54, 59, 62, 67, 73, 76, 79, 81, 84, 88}, /* Delay = 95 */ - {40, 40, 41, 42, 42, 42, 43, 44, 44, 45, 45, 45, 47, 47, 47, 48, 48, 49, 50, 50, 50, 51, 52, 56, 61, 65, 69, 78, 82, 89, 94, 102, 110, 115, 119, 122, 127, 132} /* Delay = 150 */ - }; - - if( Weapon->Delay < 65 ) - { - return ucDelayOver59Levels28to65[0][ucPlayerLevel-28]; - } - else if( Weapon->Delay < 70 ) - { - return ucDelayOver59Levels28to65[1][ucPlayerLevel-28]; - } - else if( Weapon->Delay < 85 ) - { - return ucDelayOver59Levels28to65[2][ucPlayerLevel-28]; - } - else if( Weapon->Delay < 95 ) - { - return ucDelayOver59Levels28to65[3][ucPlayerLevel-28]; - } - else if( Weapon->Delay < 150 ) - { - return ucDelayOver59Levels28to65[4][ucPlayerLevel-28]; - } - else - { - return ucDelayOver59Levels28to65[5][ucPlayerLevel-28]; - } - } -} - -int Mob::GetMonkHandToHandDamage(void) -{ - // Kaiyodo - Determine a monk's fist damage. Table data from www.monkly-business.com - // saved as static array - this should speed this function up considerably - static int damage[66] = { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 - 99, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 9, 9, 9, 9, 9,10,10,10,10,10,11,11,11,11,11, - 12,12,12,12,12,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14, - 14,14,15,15,15,15 }; - - // Have a look to see if we have epic fists on - - if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652) - return(9); - else - { - int Level = GetLevel(); - if (Level > 65) - return(19); - else - return damage[Level]; - } -} - -int Mob::GetMonkHandToHandDelay(void) -{ - // Kaiyodo - Determine a monk's fist delay. Table data from www.monkly-business.com - // saved as static array - this should speed this function up considerably - static int delayshuman[66] = { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 - 99,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, - 36,36,36,36,36,35,35,35,35,35,34,34,34,34,34,33,33,33,33,33, - 32,32,32,32,32,31,31,31,31,31,30,30,30,29,29,29,28,28,28,27, - 26,24,22,20,20,20 }; - static int delaysiksar[66] = { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 - 99,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, - 36,36,36,36,36,36,36,36,36,36,35,35,35,35,35,34,34,34,34,34, - 33,33,33,33,33,32,32,32,32,32,31,31,31,30,30,30,29,29,29,28, - 27,24,22,20,20,20 }; - - // Have a look to see if we have epic fists on - if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652) - return(16); - else - { - int Level = GetLevel(); - if (GetRace() == HUMAN) - { - if (Level > 65) - return(24); - else - return delayshuman[Level]; - } - else //heko: iksar table - { - if (Level > 65) - return(25); - else - return delaysiksar[Level]; - } - } -} - - -int32 Mob::ReduceDamage(int32 damage) -{ - if(damage <= 0) - return damage; - - int32 slot = -1; - bool DisableMeleeRune = false; - - if (spellbonuses.NegateAttacks[0]){ - slot = spellbonuses.NegateAttacks[1]; - if(slot >= 0) { - if(--buffs[slot].numhits == 0) { - - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot , true); - } - return -6; - } - } - - //Only mitigate if damage is above the minimium specified. - if (spellbonuses.MeleeThresholdGuard[0]){ - slot = spellbonuses.MeleeThresholdGuard[1]; - - if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) - { - DisableMeleeRune = true; - int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[0] / 100; - if(damage_to_reduce > buffs[slot].melee_rune) - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d" - " damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune); - damage -= damage_to_reduce; - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d" - " damage remaining.", damage_to_reduce, buffs[slot].melee_rune); - buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); - damage -= damage_to_reduce; - } - } - } - - - if (spellbonuses.MitigateMeleeRune[0] && !DisableMeleeRune){ - slot = spellbonuses.MitigateMeleeRune[1]; - if(slot >= 0) - { - int damage_to_reduce = damage * spellbonuses.MitigateMeleeRune[0] / 100; - if(damage_to_reduce > buffs[slot].melee_rune) - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" - " damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune); - damage -= damage_to_reduce; - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" - " damage remaining.", damage_to_reduce, buffs[slot].melee_rune); - buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); - damage -= damage_to_reduce; - } - } - } - - if (spellbonuses.TriggerMeleeThreshold[2]){ - slot = spellbonuses.TriggerMeleeThreshold[1]; - - if (slot >= 0) { - if(damage > buffs[slot].melee_rune) { - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else{ - buffs[slot].melee_rune = (buffs[slot].melee_rune - damage); - } - } - } - - if(damage < 1) - return -6; - - if (spellbonuses.MeleeRune[0] && spellbonuses.MeleeRune[1] >= 0) - damage = RuneAbsorb(damage, SE_Rune); - - if(damage < 1) - return -6; - - return(damage); -} - -int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker) -{ - if(damage <= 0) - return damage; - - bool DisableSpellRune = false; - int32 slot = -1; - - // See if we block the spell outright first - if (spellbonuses.NegateAttacks[0]){ - slot = spellbonuses.NegateAttacks[1]; - if(slot >= 0) { - if(--buffs[slot].numhits == 0) { - - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot , true); - } - return 0; - } - } - - // If this is a DoT, use DoT Shielding... - if(iBuffTic) { - damage -= (damage * itembonuses.DoTShielding / 100); - - if (spellbonuses.MitigateDotRune[0]){ - slot = spellbonuses.MitigateDotRune[1]; - if(slot >= 0) - { - int damage_to_reduce = damage * spellbonuses.MitigateDotRune[0] / 100; - if(damage_to_reduce > buffs[slot].dot_rune) - { - damage -= damage_to_reduce; - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else - { - buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce); - damage -= damage_to_reduce; - } - } - } - } - - // This must be a DD then so lets apply Spell Shielding and runes. - else - { - // Reduce damage by the Spell Shielding first so that the runes don't take the raw damage. - damage -= (damage * itembonuses.SpellShield / 100); - - - //Only mitigate if damage is above the minimium specified. - if (spellbonuses.SpellThresholdGuard[0]){ - slot = spellbonuses.SpellThresholdGuard[1]; - - if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) - { - DisableSpellRune = true; - int damage_to_reduce = damage * spellbonuses.SpellThresholdGuard[0] / 100; - if(damage_to_reduce > buffs[slot].magic_rune) - { - damage -= damage_to_reduce; - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else - { - buffs[slot].melee_rune = (buffs[slot].magic_rune - damage_to_reduce); - damage -= damage_to_reduce; - } - } - } - - - // Do runes now. - if (spellbonuses.MitigateSpellRune[0] && !DisableSpellRune){ - slot = spellbonuses.MitigateSpellRune[1]; - if(slot >= 0) - { - int damage_to_reduce = damage * spellbonuses.MitigateSpellRune[0] / 100; - if(damage_to_reduce > buffs[slot].magic_rune) - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d" - " damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune); - damage -= damage_to_reduce; - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" - " damage remaining.", damage_to_reduce, buffs[slot].magic_rune); - buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce); - damage -= damage_to_reduce; - } - } - } - - if (spellbonuses.TriggerSpellThreshold[2]){ - slot = spellbonuses.TriggerSpellThreshold[1]; - - if (slot >= 0) { - if(damage > buffs[slot].magic_rune) { - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else{ - buffs[slot].magic_rune = (buffs[slot].magic_rune - damage); - } - } - } - - if(damage < 1) - return 0; - - - if (spellbonuses.AbsorbMagicAtt[0] && spellbonuses.AbsorbMagicAtt[1] >= 0) - damage = RuneAbsorb(damage, SE_AbsorbMagicAtt); - - if(damage < 1) - return 0; - } - return damage; -} - -int32 Mob::ReduceAllDamage(int32 damage) -{ - if(damage <= 0) - return damage; - - if(spellbonuses.ManaAbsorbPercentDamage[0] && (GetMana() > damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100)) { - damage -= (damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100); - SetMana(GetMana() - damage); - TryTriggerOnValueAmount(false, true); - } - - CheckNumHitsRemaining(8); - - return(damage); -} - -bool Mob::HasProcs() const -{ - for (int i = 0; i < MAX_PROCS; i++) - if (PermaProcs[i].spellID != SPELL_UNKNOWN || SpellProcs[i].spellID != SPELL_UNKNOWN) - return true; - return false; -} - -bool Mob::HasDefensiveProcs() const -{ - for (int i = 0; i < MAX_PROCS; i++) - if (DefensiveProcs[i].spellID != SPELL_UNKNOWN) - return true; - return false; -} - -bool Mob::HasSkillProcs() const -{ - for (int i = 0; i < MAX_PROCS; i++) - if (SkillProcs[i].spellID != SPELL_UNKNOWN) - return true; - return false; -} - -bool Mob::HasRangedProcs() const -{ - for (int i = 0; i < MAX_PROCS; i++) - if (RangedProcs[i].spellID != SPELL_UNKNOWN) - return true; - return false; -} - -bool Client::CheckDoubleAttack(bool tripleAttack) { - - //Check for bonuses that give you a double attack chance regardless of skill (ie Bestial Frenzy/Harmonious Attack AA) - uint16 bonusGiveDA = aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack; - - if(!HasSkill(SkillDoubleAttack) && !bonusGiveDA) - return false; - - float chance = 0.0f; - - uint16 skill = GetSkill(SkillDoubleAttack); - - int16 bonusDA = aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance; - - //Use skill calculations otherwise, if you only have AA applied GiveDoubleAttack chance then use that value as the base. - if (skill) - chance = (float(skill+GetLevel()) * (float(100.0f+bonusDA+bonusGiveDA) /100.0f)) /500.0f; - else - chance = (float(bonusGiveDA) * (float(100.0f+bonusDA)/100.0f) ) /100.0f; - - //Live now uses a static Triple Attack skill (lv 46 = 2% lv 60 = 20%) - We do not have this skill on EMU ATM. - //A reasonable forumla would then be TA = 20% * chance - //AA's can also give triple attack skill over cap. (ie Burst of Power) NOTE: Skill ID in spell data is 76 (Triple Attack) - //Kayen: Need to decide if we can implement triple attack skill before working in over the cap effect. - if(tripleAttack) { - // Only some Double Attack classes get Triple Attack [This is already checked in client_processes.cpp] - int16 triple_bonus = spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance; - chance *= 0.2f; //Baseline chance is 20% of your double attack chance. - chance *= float(100.0f+triple_bonus)/100.0f; //Apply modifiers. - } - - if((MakeRandomFloat(0, 1) < chance)) - return true; - - return false; -} - -bool Client::CheckDoubleRangedAttack() { - - int16 chance = spellbonuses.DoubleRangedAttack + itembonuses.DoubleRangedAttack + aabonuses.DoubleRangedAttack; - - if(chance && (MakeRandomInt(0, 100) < chance)) - return true; - - return false; -} - -void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, const SkillUseTypes skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic) { - // This method is called with skill_used=ABJURE for Damage Shield damage. - bool FromDamageShield = (skill_used == SkillAbjuration); - - mlog(COMBAT__HITS, "Applying damage %d done by %s with skill %d and spell %d, avoidable? %s, is %sa buff tic in slot %d", - damage, attacker?attacker->GetName():"NOBODY", skill_used, spell_id, avoidable?"yes":"no", iBuffTic?"":"not ", buffslot); - - if (GetInvul() || DivineAura()) { - mlog(COMBAT__DAMAGE, "Avoiding %d damage due to invulnerability.", damage); - damage = -5; - } - - if( spell_id != SPELL_UNKNOWN || attacker == nullptr ) - avoidable = false; - - // only apply DS if physical damage (no spell damage) - // damage shield calls this function with spell_id set, so its unavoidable - if (attacker && damage > 0 && spell_id == SPELL_UNKNOWN && skill_used != SkillArchery && skill_used != SkillThrowing) { - DamageShield(attacker); - } - - if (spell_id == SPELL_UNKNOWN && skill_used) { - CheckNumHitsRemaining(1); //Incoming Hit Attempts - - if (attacker) - attacker->CheckNumHitsRemaining(2); //Outgoing Hit Attempts - } - - if(attacker){ - if(attacker->IsClient()){ - if(!RuleB(Combat, EXPFromDmgShield)) { - // Damage shield damage shouldn't count towards who gets EXP - if(!attacker->CastToClient()->GetFeigned() && !FromDamageShield) - AddToHateList(attacker, 0, damage, true, false, iBuffTic); - } - else { - if(!attacker->CastToClient()->GetFeigned()) - AddToHateList(attacker, 0, damage, true, false, iBuffTic); - } - } - else - AddToHateList(attacker, 0, damage, true, false, iBuffTic); - } - - if(damage > 0) { - //if there is some damage being done and theres an attacker involved - if(attacker) { - if(spell_id == SPELL_HARM_TOUCH2 && attacker->IsClient() && attacker->CastToClient()->CheckAAEffect(aaEffectLeechTouch)){ - int healed = damage; - healed = attacker->GetActSpellHealing(spell_id, healed); - attacker->HealDamage(healed); - entity_list.MessageClose(this, true, 300, MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName() ); - attacker->CastToClient()->DisableAAEffect(aaEffectLeechTouch); - } - - // if spell is lifetap add hp to the caster - if (spell_id != SPELL_UNKNOWN && IsLifetapSpell( spell_id )) { - int healed = damage; - - healed = attacker->GetActSpellHealing(spell_id, healed); - mlog(COMBAT__DAMAGE, "Applying lifetap heal of %d to %s", healed, attacker->GetName()); - attacker->HealDamage(healed); - - //we used to do a message to the client, but its gone now. - // emote goes with every one ... even npcs - entity_list.MessageClose(this, true, 300, MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName() ); - } - } //end `if there is some damage being done and theres anattacker person involved` - - Mob *pet = GetPet(); - if (pet && !pet->IsFamiliar() && !pet->GetSpecialAbility(IMMUNE_AGGRO) && !pet->IsEngaged() && attacker && attacker != this && !attacker->IsCorpse()) - { - if (!pet->IsHeld()) { - mlog(PETS__AGGRO, "Sending pet %s into battle due to attack.", pet->GetName()); - pet->AddToHateList(attacker, 1); - pet->SetTarget(attacker); - Message_StringID(10, PET_ATTACKING, pet->GetCleanName(), attacker->GetCleanName()); - } - } - - //see if any runes want to reduce this damage - if(spell_id == SPELL_UNKNOWN) { - damage = ReduceDamage(damage); - mlog(COMBAT__HITS, "Melee Damage reduced to %d", damage); - } else { - int32 origdmg = damage; - damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker); - if (origdmg != damage && attacker && attacker->IsClient()) { - if(attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide) - attacker->Message(15, "The Spellshield absorbed %d of %d points of damage", origdmg - damage, origdmg); - } - if (damage == 0 && attacker && origdmg != damage && IsClient()) { - //Kayen: Probably need to add a filter for this - Not sure if this msg is correct but there should be a message for spell negate/runes. - Message(263, "%s tries to cast on YOU, but YOUR magical skin absorbs the spell.",attacker->GetCleanName()); - } - - } - - if (skill_used) - CheckNumHitsRemaining(6); //Incomming Hit Success on Defender - - ReduceAllDamage(damage); - - if(IsClient() && CastToClient()->sneaking){ - CastToClient()->sneaking = false; - SendAppearancePacket(AT_Sneak, 0); - } - if(attacker && attacker->IsClient() && attacker->CastToClient()->sneaking){ - attacker->CastToClient()->sneaking = false; - attacker->SendAppearancePacket(AT_Sneak, 0); - } - - //final damage has been determined. - - SetHP(GetHP() - damage); - - if(HasDied()) { - bool IsSaved = false; - - if(TryDivineSave()) - IsSaved = true; - - if(!IsSaved && !TrySpellOnDeath()) { - SetHP(-500); - - if(Death(attacker, damage, spell_id, skill_used)) { - return; - } - } - } - else{ - if(GetHPRatio() < 16) - TryDeathSave(); - } - - TryTriggerOnValueAmount(true); - - //fade mez if we are mezzed - if (IsMezzed()) { - mlog(COMBAT__HITS, "Breaking mez due to attack."); - BuffFadeByEffect(SE_Mez); - } - - //check stun chances if bashing - if (damage > 0 && ((skill_used == SkillBash || skill_used == SkillKick) && attacker)) { - // NPCs can stun with their bash/kick as soon as they receive it. - // Clients can stun mobs under level 56 with their kick when they get level 55 or greater. - // Clients have a chance to stun if the mob is 56+ - - // Calculate the chance to stun - int stun_chance = 0; - if (!GetSpecialAbility(UNSTUNABLE)) { - if (attacker->IsNPC()) { - stun_chance = RuleI(Combat, NPCBashKickStunChance); - } else if (attacker->IsClient()) { - // Less than base immunity - // Client vs. Client always uses the chance - if (!IsClient() && GetLevel() <= RuleI(Spells, BaseImmunityLevel)) { - if (skill_used == SkillBash) // Bash always will - stun_chance = 100; - else if (attacker->GetLevel() >= RuleI(Combat, ClientStunLevel)) - stun_chance = 100; // only if you're over level 55 and using kick - } else { // higher than base immunity or Client vs. Client - // not sure on this number, use same as NPC for now - if (skill_used == SkillKick && attacker->GetLevel() < RuleI(Combat, ClientStunLevel)) - stun_chance = RuleI(Combat, NPCBashKickStunChance); - else if (skill_used == SkillBash) - stun_chance = RuleI(Combat, NPCBashKickStunChance) + - attacker->spellbonuses.StunBashChance + - attacker->itembonuses.StunBashChance + - attacker->aabonuses.StunBashChance; - } - } - } - - if (stun_chance && MakeRandomInt(0, 99) < stun_chance) { - // Passed stun, try to resist now - int stun_resist = itembonuses.StunResist + spellbonuses.StunResist; - int frontal_stun_resist = itembonuses.FrontalStunResist + spellbonuses.FrontalStunResist; - - mlog(COMBAT__HITS, "Stun passed, checking resists. Was %d chance.", stun_chance); - if (IsClient()) { - stun_resist += aabonuses.StunResist; - frontal_stun_resist += aabonuses.FrontalStunResist; - } - - // frontal stun check for ogres/bonuses - if (((GetBaseRace() == OGRE && IsClient()) || - (frontal_stun_resist && MakeRandomInt(0, 99) < frontal_stun_resist)) && - !attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) { - mlog(COMBAT__HITS, "Frontal stun resisted. %d chance.", frontal_stun_resist); - } else { - // Normal stun resist check. - if (stun_resist && MakeRandomInt(0, 99) < stun_resist) { - if (IsClient()) - Message_StringID(MT_Stun, SHAKE_OFF_STUN); - mlog(COMBAT__HITS, "Stun Resisted. %d chance.", stun_resist); - } else { - mlog(COMBAT__HITS, "Stunned. %d resist chance.", stun_resist); - Stun(MakeRandomInt(0, 2) * 1000); // 0-2 seconds - } - } - } else { - mlog(COMBAT__HITS, "Stun failed. %d chance.", stun_chance); - } - } - - if(spell_id != SPELL_UNKNOWN && !iBuffTic) { - //see if root will break - if (IsRooted() && !FromDamageShield) // neotoyko: only spells cancel root - TryRootFadeByDamage(buffslot, attacker); - } - else if(spell_id == SPELL_UNKNOWN) - { - //increment chances of interrupting - if(IsCasting()) { //shouldnt interrupt on regular spell damage - attacked_count++; - mlog(COMBAT__HITS, "Melee attack while casting. Attack count %d", attacked_count); - } - } - - //send an HP update if we are hurt - if(GetHP() < GetMaxHP()) - SendHPUpdate(); - } //end `if damage was done` - - //send damage packet... - if(!iBuffTic) { //buff ticks do not send damage, instead they just call SendHPUpdate(), which is done below - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); - CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer; - a->target = GetID(); - if (attacker == nullptr) - a->source = 0; - else if (attacker->IsClient() && attacker->CastToClient()->GMHideMe()) - a->source = 0; - else - a->source = attacker->GetID(); - a->type = SkillDamageTypes[skill_used]; // was 0x1c - a->damage = damage; - a->spellid = spell_id; - - //Note: if players can become pets, they will not receive damage messages of their own - //this was done to simplify the code here (since we can only effectively skip one mob on queue) - eqFilterType filter; - Mob *skip = attacker; - if(attacker && attacker->GetOwnerID()) { - //attacker is a pet, let pet owners see their pet's damage - Mob* owner = attacker->GetOwner(); - if (owner && owner->IsClient()) { - if (((spell_id != SPELL_UNKNOWN) || (FromDamageShield)) && damage>0) { - //special crap for spell damage, looks hackish to me - char val1[20]={0}; - owner->Message_StringID(MT_NonMelee,OTHER_HIT_NONMELEE,GetCleanName(),ConvertArray(damage,val1)); - } else { - if(damage > 0) { - if(spell_id != SPELL_UNKNOWN) - filter = iBuffTic ? FilterDOT : FilterSpellDamage; - else - filter = FilterPetHits; - } else if(damage == -5) - filter = FilterNone; //cant filter invulnerable - else - filter = FilterPetMisses; - - if(!FromDamageShield) - owner->CastToClient()->QueuePacket(outapp,true,CLIENT_CONNECTED,filter); - } - } - skip = owner; - } else { - //attacker is not a pet, send to the attacker - - //if the attacker is a client, try them with the correct filter - if(attacker && attacker->IsClient()) { - if (((spell_id != SPELL_UNKNOWN)||(FromDamageShield)) && damage>0) { - //special crap for spell damage, looks hackish to me - char val1[20]={0}; - if (FromDamageShield) - { - if(!attacker->CastToClient()->GetFilter(FilterDamageShields) == FilterHide) - { - attacker->Message_StringID(MT_DS,OTHER_HIT_NONMELEE,GetCleanName(),ConvertArray(damage,val1)); - } - } - else - entity_list.MessageClose_StringID(this, true, 100, MT_NonMelee,HIT_NON_MELEE,attacker->GetCleanName(),GetCleanName(),ConvertArray(damage,val1)); - } else { - if(damage > 0) { - if(spell_id != SPELL_UNKNOWN) - filter = iBuffTic ? FilterDOT : FilterSpellDamage; - else - filter = FilterNone; //cant filter our own hits - } else if(damage == -5) - filter = FilterNone; //cant filter invulnerable - else - filter = FilterMyMisses; - - attacker->CastToClient()->QueuePacket(outapp, true, CLIENT_CONNECTED, filter); - } - } - skip = attacker; - } - - //send damage to all clients around except the specified skip mob (attacker or the attacker's owner) and ourself - if(damage > 0) { - if(spell_id != SPELL_UNKNOWN) - filter = iBuffTic ? FilterDOT : FilterSpellDamage; - else - filter = FilterOthersHit; - } else if(damage == -5) - filter = FilterNone; //cant filter invulnerable - else - filter = FilterOthersMiss; - //make attacker (the attacker) send the packet so we can skip them and the owner - //this call will send the packet to `this` as well (using the wrong filter) (will not happen until PC charm works) - // If this is Damage Shield damage, the correct OP_Damage packets will be sent from Mob::DamageShield, so - // we don't send them here. - if(!FromDamageShield) { - entity_list.QueueCloseClients(this, outapp, true, 200, skip, true, filter); - //send the damage to ourself if we are a client - if(IsClient()) { - //I dont think any filters apply to damage affecting us - CastToClient()->QueuePacket(outapp); - } - } - - safe_delete(outapp); - } else { - //else, it is a buff tic... - // Everhood - So we can see our dot dmg like live shows it. - if(spell_id != SPELL_UNKNOWN && damage > 0 && attacker && attacker != this && attacker->IsClient()) { - //might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it - attacker->FilteredMessage_StringID(attacker, MT_DoTDamage, FilterDOT, - YOUR_HIT_DOT, GetCleanName(), itoa(damage), spells[spell_id].name); - // older clients don't have the below String ID, but it will be filtered - entity_list.FilteredMessageClose_StringID(attacker, true, 200, - MT_DoTDamage, FilterDOT, OTHER_HIT_DOT, GetCleanName(), - itoa(damage), attacker->GetCleanName(), spells[spell_id].name); - } - } //end packet sending - -} - - -void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id) -{ - int32 maxhp = GetMaxHP(); - int32 curhp = GetHP(); - uint32 acthealed = 0; - - if (caster && amount > 0) { - if (caster->IsNPC() && !caster->IsPet()) { - float npchealscale = caster->CastToNPC()->GetHealScale(); - amount = (static_cast(amount) * npchealscale) / 100.0f; - } - } - - if (amount > (maxhp - curhp)) - acthealed = (maxhp - curhp); - else - acthealed = amount; - - if (acthealed > 100) { - if (caster) { - if (IsBuffSpell(spell_id)) { // hots - // message to caster - if (caster->IsClient() && caster == this) { - if (caster->CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) - FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, - HOT_HEAL_SELF, itoa(acthealed), spells[spell_id].name); - else - FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, - YOU_HEALED, GetCleanName(), itoa(acthealed)); - } else if (caster->IsClient() && caster != this) { - if (caster->CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) - caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, - HOT_HEAL_OTHER, GetCleanName(), itoa(acthealed), - spells[spell_id].name); - else - caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, - YOU_HEAL, GetCleanName(), itoa(acthealed)); - } - // message to target - if (IsClient() && caster != this) { - if (CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) - FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime, - HOT_HEALED_OTHER, caster->GetCleanName(), - itoa(acthealed), spells[spell_id].name); - else - FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime, - YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); - } - } else { // normal heals - FilteredMessage_StringID(caster, MT_NonMelee, FilterSpellDamage, - YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); - if (caster != this) - caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterSpellDamage, - YOU_HEAL, GetCleanName(), itoa(acthealed)); - } - } else { - Message(MT_NonMelee, "You have been healed for %d points of damage.", acthealed); - } - } - - if (curhp < maxhp) { - if ((curhp + amount) > maxhp) - curhp = maxhp; - else - curhp += amount; - SetHP(curhp); - - SendHPUpdate(); - } -} - -//proc chance includes proc bonus -float Mob::GetProcChances(float ProcBonus, uint16 weapon_speed, uint16 hand) -{ - int mydex = GetDEX(); - float ProcChance = 0.0f; - - switch (hand) { - case 13: - weapon_speed = attack_timer.GetDuration(); - break; - case 14: - weapon_speed = attack_dw_timer.GetDuration(); - break; - case 11: - weapon_speed = ranged_timer.GetDuration(); - break; - } - - //calculate the weapon speed in ms, so we can use the rule to compare against. - // fast as a client can swing, so should be the floor of the proc chance - if (weapon_speed < RuleI(Combat, MinHastedDelay)) - weapon_speed = RuleI(Combat, MinHastedDelay); - - if (RuleB(Combat, AdjustProcPerMinute)) { - ProcChance = (static_cast(weapon_speed) * - RuleR(Combat, AvgProcsPerMinute) / 60000.0f); // compensate for weapon_speed being in ms - ProcBonus += static_cast(mydex) * RuleR(Combat, ProcPerMinDexContrib); - ProcChance += ProcChance * ProcBonus / 100.0f; - } else { - ProcChance = RuleR(Combat, BaseProcChance) + - static_cast(mydex) / RuleR(Combat, ProcDexDivideBy); - ProcChance += ProcChance * ProcBonus / 100.0f; - } - - mlog(COMBAT__PROCS, "Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus); - return ProcChance; -} - -float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed, uint16 hand) { - int myagi = GetAGI(); - ProcBonus = 0; - ProcChance = 0; - - switch(hand){ - case 13: - weapon_speed = attack_timer.GetDuration(); - break; - case 14: - weapon_speed = attack_dw_timer.GetDuration(); - break; - case 11: - return 0; - break; - } - - //calculate the weapon speed in ms, so we can use the rule to compare against. - //weapon_speed = ((int)(weapon_speed*(100.0f+attack_speed)*PermaHaste)); - if(weapon_speed < RuleI(Combat, MinHastedDelay)) // fast as a client can swing, so should be the floor of the proc chance - weapon_speed = RuleI(Combat, MinHastedDelay); - - ProcChance = ((float)weapon_speed * RuleR(Combat, AvgDefProcsPerMinute) / 60000.0f); // compensate for weapon_speed being in ms - ProcBonus += float(myagi) * RuleR(Combat, DefProcPerMinAgiContrib) / 100.0f; - ProcChance = ProcChance + (ProcChance * ProcBonus); - - mlog(COMBAT__PROCS, "Defensive Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus); - return ProcChance; -} - -void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand, int damage) { - - if (!on) { - SetTarget(nullptr); - LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryDefensiveProc for evaluation!"); - return; - } - - bool bSkillProc = HasSkillProcs(); - bool bDefensiveProc = HasDefensiveProcs(); - - if (!bDefensiveProc && !bSkillProc) - return; - - if (!bDefensiveProc && (bSkillProc && damage >= 0)) - return; - - float ProcChance, ProcBonus; - if(weapon!=nullptr) - on->GetDefensiveProcChances(ProcBonus, ProcChance, weapon->GetItem()->Delay, hand); - else - on->GetDefensiveProcChances(ProcBonus, ProcChance); - if(hand != 13) - ProcChance /= 2; - - if (bDefensiveProc){ - for (int i = 0; i < MAX_PROCS; i++) { - if (DefensiveProcs[i].spellID != SPELL_UNKNOWN) { - int chance = ProcChance * (DefensiveProcs[i].chance); - if ((MakeRandomInt(0, 100) < chance)) { - ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on); - CheckNumHitsRemaining(10,0,DefensiveProcs[i].base_spellID); - } - } - } - } - - if (bSkillProc && damage < 0){ - - if (damage == -1) - TrySkillProc(on, SkillBlock, ProcChance); - - if (damage == -2) - TrySkillProc(on, SkillParry, ProcChance); - - if (damage == -3) - TrySkillProc(on, SkillRiposte, ProcChance); - - if (damage == -4) - TrySkillProc(on, SkillDodge, ProcChance); - } -} - -void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { - if(!on) { - SetTarget(nullptr); - LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryWeaponProc for evaluation!"); - return; - } - - if (!IsAttackAllowed(on)) { - mlog(COMBAT__PROCS, "Preventing procing off of unattackable things."); - return; - } - - if(!weapon_g) { - TrySpellProc(nullptr, (const Item_Struct*)nullptr, on); - return; - } - - if(!weapon_g->IsType(ItemClassCommon)) { - TrySpellProc(nullptr, (const Item_Struct*)nullptr, on); - return; - } - - // Innate + aug procs from weapons - // TODO: powersource procs - TryWeaponProc(weapon_g, weapon_g->GetItem(), on, hand); - // Procs from Buffs and AA both melee and range - TrySpellProc(weapon_g, weapon_g->GetItem(), on, hand); - - return; -} - -void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand) -{ - if (!weapon) - return; - uint16 skillinuse = 28; - int ourlevel = GetLevel(); - float ProcBonus = static_cast(aabonuses.ProcChanceSPA + - spellbonuses.ProcChanceSPA + itembonuses.ProcChanceSPA); - ProcBonus += static_cast(itembonuses.ProcChance) / 10.0f; // Combat Effects - float ProcChance = GetProcChances(ProcBonus, weapon->Delay, hand); - - if (hand != 13) //Is Archery intened to proc at 50% rate? - ProcChance /= 2; - - // Try innate proc on weapon - // We can proc once here, either weapon or one aug - bool proced = false; // silly bool to prevent augs from going if weapon does - skillinuse = GetSkillByItemType(weapon->ItemType); - if (weapon->Proc.Type == ET_CombatProc) { - float WPC = ProcChance * (100.0f + // Proc chance for this weapon - static_cast(weapon->ProcRate)) / 100.0f; - if (MakeRandomFloat(0, 1) <= WPC) { // 255 dex = 0.084 chance of proc. No idea what this number should be really. - if (weapon->Proc.Level > ourlevel) { - mlog(COMBAT__PROCS, - "Tried to proc (%s), but our level (%d) is lower than required (%d)", - weapon->Name, ourlevel, weapon->Proc.Level); - if (IsPet()) { - Mob *own = GetOwner(); - if (own) - own->Message_StringID(13, PROC_PETTOOLOW); - } else { - Message_StringID(13, PROC_TOOLOW); - } - } else { - mlog(COMBAT__PROCS, - "Attacking weapon (%s) successfully procing spell %d (%.2f percent chance)", - weapon->Name, weapon->Proc.Effect, WPC * 100); - ExecWeaponProc(inst, weapon->Proc.Effect, on); - proced = true; - } - } - } - - if (!proced && inst) { - for (int r = 0; r < MAX_AUGMENT_SLOTS; r++) { - const ItemInst *aug_i = inst->GetAugment(r); - if (!aug_i) // no aug, try next slot! - continue; - const Item_Struct *aug = aug_i->GetItem(); - if (!aug) - continue; - - if (aug->Proc.Type == ET_CombatProc) { - float APC = ProcChance * (100.0f + // Proc chance for this aug - static_cast(aug->ProcRate)) / 100.0f; - if (MakeRandomFloat(0, 1) <= APC) { - if (aug->Proc.Level > ourlevel) { - if (IsPet()) { - Mob *own = GetOwner(); - if (own) - own->Message_StringID(13, PROC_PETTOOLOW); - } else { - Message_StringID(13, PROC_TOOLOW); - } - } else { - ExecWeaponProc(aug_i, aug->Proc.Effect, on); - break; - } - } - } - } - } - // TODO: Powersource procs - if (HasSkillProcs()) - TrySkillProc(on, skillinuse, ProcChance); - - return; -} - -void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand) -{ - float ProcBonus = static_cast(spellbonuses.SpellProcChance + - itembonuses.SpellProcChance + aabonuses.SpellProcChance); - float ProcChance = 0.0f; - if (weapon) - ProcChance = GetProcChances(ProcBonus, weapon->Delay, hand); - else - ProcChance = GetProcChances(ProcBonus); - - if (hand != 13) //Is Archery intened to proc at 50% rate? - ProcChance /= 2; - - bool rangedattk = false; - if (weapon && hand == 11) { - if (weapon->ItemType == ItemTypeArrow || - weapon->ItemType == ItemTypeLargeThrowing || - weapon->ItemType == ItemTypeSmallThrowing || - weapon->ItemType == ItemTypeBow) - rangedattk = true; - } - - for (uint32 i = 0; i < MAX_PROCS; i++) { - if (IsPet() && hand != 13) //Pets can only proc spell procs from their primay hand (ie; beastlord pets) - continue; // If pets ever can proc from off hand, this will need to change - - // Not ranged - if (!rangedattk) { - // Perma procs (AAs) - if (PermaProcs[i].spellID != SPELL_UNKNOWN) { - if (MakeRandomInt(0, 99) < PermaProcs[i].chance) { // TODO: Do these get spell bonus? - mlog(COMBAT__PROCS, - "Permanent proc %d procing spell %d (%d percent chance)", - i, PermaProcs[i].spellID, PermaProcs[i].chance); - ExecWeaponProc(nullptr, PermaProcs[i].spellID, on); - } else { - mlog(COMBAT__PROCS, - "Permanent proc %d failed to proc %d (%d percent chance)", - i, PermaProcs[i].spellID, PermaProcs[i].chance); - } - } - - // Spell procs (buffs) - if (SpellProcs[i].spellID != SPELL_UNKNOWN) { - float chance = ProcChance * (SpellProcs[i].chance / 100.0f); - if (MakeRandomFloat(0, 1) <= chance) { - mlog(COMBAT__PROCS, - "Spell proc %d procing spell %d (%.2f percent chance)", - i, SpellProcs[i].spellID, chance); - ExecWeaponProc(nullptr, SpellProcs[i].spellID, on); - CheckNumHitsRemaining(11, 0, SpellProcs[i].base_spellID); - } else { - mlog(COMBAT__PROCS, - "Spell proc %d failed to proc %d (%.2f percent chance)", - i, SpellProcs[i].spellID, chance); - } - } - } else if (rangedattk) { // ranged only - // ranged spell procs (buffs) - if (RangedProcs[i].spellID != SPELL_UNKNOWN) { - float chance = ProcChance * (RangedProcs[i].chance / 100.0f); - if (MakeRandomFloat(0, 1) <= chance) { - mlog(COMBAT__PROCS, - "Ranged proc %d procing spell %d (%.2f percent chance)", - i, RangedProcs[i].spellID, chance); - ExecWeaponProc(nullptr, RangedProcs[i].spellID, on); - CheckNumHitsRemaining(11, 0, RangedProcs[i].base_spellID); - } else { - mlog(COMBAT__PROCS, - "Ranged proc %d failed to proc %d (%.2f percent chance)", - i, RangedProcs[i].spellID, chance); - } - } - } - } - - return; -} - -void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage) -{ - if(damage < 1) - return; - - //Allows pets to perform critical hits. - //Each rank adds an additional 1% chance for any melee hit (primary, secondary, kick, bash, etc) to critical, - //dealing up to 63% more damage. http://www.magecompendium.com/aa-short-library.html - - Mob *owner = nullptr; - float critChance = 0.0f; - critChance += RuleI(Combat, MeleeBaseCritChance); - uint16 critMod = 163; - - if (damage < 1) //We can't critical hit if we don't hit. - return; - - if (!IsPet()) - return; - - owner = GetOwner(); - - if (!owner) - return; - - int16 CritPetChance = owner->aabonuses.PetCriticalHit + owner->itembonuses.PetCriticalHit + owner->spellbonuses.PetCriticalHit; - int16 CritChanceBonus = GetCriticalChanceBonus(skill); - - if (CritPetChance || critChance) { - - //For pets use PetCriticalHit for base chance, pets do not innately critical with without it - //even if buffed with a CritChanceBonus effects. - critChance += CritPetChance; - critChance += critChance*CritChanceBonus/100.0f; - } - - if(critChance > 0){ - - critChance /= 100; - - if(MakeRandomFloat(0, 1) < critChance) - { - critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100 - damage = (damage * critMod) / 100; - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, CRITICAL_HIT, - GetCleanName(), itoa(damage)); - } - } -} - -void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts) -{ - if(damage < 1) - return; - - // decided to branch this into it's own function since it's going to be duplicating a lot of the - // code in here, but could lead to some confusion otherwise - if (IsPet() && GetOwner()->IsClient()) { - TryPetCriticalHit(defender,skill,damage); - return; - } - -#ifdef BOTS - if (this->IsPet() && this->GetOwner()->IsBot()) { - this->TryPetCriticalHit(defender,skill,damage); - return; - } -#endif //BOTS - - - float critChance = 0.0f; - - //1: Try Slay Undead - if(defender && defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire){ - - int16 SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0]; - - if (SlayRateBonus) { - - critChance += (float(SlayRateBonus)/100.0f); - critChance /= 100.0f; - - if(MakeRandomFloat(0, 1) < critChance){ - int16 SlayDmgBonus = aabonuses.SlayUndead[1] + itembonuses.SlayUndead[1] + spellbonuses.SlayUndead[1]; - damage = (damage*SlayDmgBonus*2.25)/100; - entity_list.MessageClose(this, false, 200, MT_CritMelee, "%s cleanses %s target!(%d)", GetCleanName(), this->GetGender() == 0 ? "his" : this->GetGender() == 1 ? "her" : "its", damage); - return; - } - } - } - - //2: Try Melee Critical - - //Base critical rate for all classes is dervived from DEX stat, this rate is then augmented - //by item,spell and AA bonuses allowing you a chance to critical hit. If the following rules - //are defined you will have an innate chance to hit at Level 1 regardless of bonuses. - //Warning: Do not define these rules if you want live like critical hits. - critChance += RuleI(Combat, MeleeBaseCritChance); - - if (IsClient()) { - critChance += RuleI(Combat, ClientBaseCritChance); - - if ((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) { - if (IsBerserk()) - critChance += RuleI(Combat, BerserkBaseCritChance); - else - critChance += RuleI(Combat, WarBerBaseCritChance); - } - } - - int deadlyChance = 0; - int deadlyMod = 0; - if(skill == SkillArchery && GetClass() == RANGER && GetSkill(SkillArchery) >= 65) - critChance += 6; - - if (skill == SkillThrowing && GetClass() == ROGUE && GetSkill(SkillThrowing) >= 65) { - critChance += RuleI(Combat, RogueCritThrowingChance); - deadlyChance = RuleI(Combat, RogueDeadlyStrikeChance); - deadlyMod = RuleI(Combat, RogueDeadlyStrikeMod); - } - - int CritChanceBonus = GetCriticalChanceBonus(skill); - - if (CritChanceBonus || critChance) { - - //Get Base CritChance from Dex. (200 = ~1.6%, 255 = ~2.0%, 355 = ~2.20%) Fall off rate > 255 - //http://giline.versus.jp/shiden/su.htm , http://giline.versus.jp/shiden/damage_e.htm - if (GetDEX() <= 255) - critChance += (float(GetDEX()) / 125.0f); - else if (GetDEX() > 255) - critChance += (float(GetDEX()-255)/ 500.0f) + 2.0f; - critChance += critChance*(float)CritChanceBonus /100.0f; - } - - if(opts) { - critChance *= opts->crit_percent; - critChance += opts->crit_flat; - } - - if(critChance > 0) { - - critChance /= 100; - - if(MakeRandomFloat(0, 1) < critChance) - { - uint16 critMod = 200; - bool crip_success = false; - int16 CripplingBlowChance = GetCrippBlowChance(); - - //Crippling Blow Chance: The percent value of the effect is applied - //to the your Chance to Critical. (ie You have 10% chance to critical and you - //have a 200% Chance to Critical Blow effect, therefore you have a 20% Chance to Critical Blow. - if (CripplingBlowChance || IsBerserk()) { - if (!IsBerserk()) - critChance *= float(CripplingBlowChance)/100.0f; - - if (IsBerserk() || MakeRandomFloat(0, 1) < critChance) { - critMod = 400; - crip_success = true; - } - } - - critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100 - damage = damage * critMod / 100; - - bool deadlySuccess = false; - if (deadlyChance && MakeRandomFloat(0, 1) < static_cast(deadlyChance) / 100.0f) { - if (BehindMob(defender, GetX(), GetY())) { - damage *= deadlyMod; - deadlySuccess = true; - } - } - - if (crip_success) { - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, CRIPPLING_BLOW, - GetCleanName(), itoa(damage)); - // Crippling blows also have a chance to stun - //Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a staggers message. - if (defender->GetLevel() <= 55 && !defender->GetSpecialAbility(IMMUNE_STUN)){ - defender->Emote("staggers."); - defender->Stun(0); - } - } else if (deadlySuccess) { - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, DEADLY_STRIKE, - GetCleanName(), itoa(damage)); - } else { - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, CRITICAL_HIT, - GetCleanName(), itoa(damage)); - } - } - } -} - - -bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) -{ - - if (!defender) - return false; - - if (aabonuses.FinishingBlow[1] && !defender->IsClient() && defender->GetHPRatio() < 10){ - - uint32 chance = aabonuses.FinishingBlow[0]/10; //500 = 5% chance. - uint32 damage = aabonuses.FinishingBlow[1]; - uint16 levelreq = aabonuses.FinishingBlowLvl[0]; - - if(defender->GetLevel() <= levelreq && (chance >= MakeRandomInt(0, 1000))){ - mlog(COMBAT__ATTACKS, "Landed a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); - defender->Damage(this, damage, SPELL_UNKNOWN, skillinuse); - return true; - } - else - { - mlog(COMBAT__ATTACKS, "FAILED a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); - return false; - } - } - return false; -} - -void Mob::DoRiposte(Mob* defender) { - mlog(COMBAT__ATTACKS, "Preforming a riposte"); - - if (!defender) - return; - - defender->Attack(this, SLOT_PRIMARY, true); - if (HasDied()) return; - - int16 DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[0] + - defender->spellbonuses.GiveDoubleRiposte[0] + - defender->itembonuses.GiveDoubleRiposte[0]; - - //Live AA - Double Riposte - if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) { - mlog(COMBAT__ATTACKS, "Preforming a double riposed (%d percent chance)", DoubleRipChance); - defender->Attack(this, SLOT_PRIMARY, true); - if (HasDied()) return; - } - - //Double Riposte effect, allows for a chance to do RIPOSTE with a skill specfic special attack (ie Return Kick). - //Coded narrowly: Limit to one per client. Limit AA only. [1 = Skill Attack Chance, 2 = Skill] - DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[1]; - - if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) { - mlog(COMBAT__ATTACKS, "Preforming a return SPECIAL ATTACK (%d percent chance)", DoubleRipChance); - - if (defender->GetClass() == MONK) - defender->MonkSpecialAttack(this, defender->aabonuses.GiveDoubleRiposte[2]); - else if (defender->IsClient()) - defender->CastToClient()->DoClassAttacks(this,defender->aabonuses.GiveDoubleRiposte[2], true); - } -} - -void Mob::ApplyMeleeDamageBonus(uint16 skill, int32 &damage){ - - if(!RuleB(Combat, UseIntervalAC)){ - if(IsNPC()){ //across the board NPC damage bonuses. - //only account for STR here, assume their base STR was factored into their DB damages - int dmgbonusmod = 0; - dmgbonusmod += (100*(itembonuses.STR + spellbonuses.STR))/3; - dmgbonusmod += (100*(spellbonuses.ATK + itembonuses.ATK))/5; - mlog(COMBAT__DAMAGE, "Damage bonus: %d percent from ATK and STR bonuses.", (dmgbonusmod/100)); - damage += (damage*dmgbonusmod/10000); - } - } - - damage += damage * GetMeleeDamageMod_SE(skill) / 100; -} - -bool Mob::HasDied() { - bool Result = false; - int16 hp_below = 0; - - hp_below = (GetDelayDeath() * -1); - - if((GetHP()) <= (hp_below)) - Result = true; - - return Result; -} - -uint16 Mob::GetDamageTable(SkillUseTypes skillinuse) -{ - if(GetLevel() <= 51) - { - uint16 ret_table = 0; - int str_over_75 = 0; - if(GetSTR() > 75) - str_over_75 = GetSTR() - 75; - if(str_over_75 > 255) - ret_table = (GetSkill(skillinuse)+255)/2; - else - ret_table = (GetSkill(skillinuse)+str_over_75)/2; - - if(ret_table < 100) - return 100; - - return ret_table; - } - else if(GetLevel() >= 90) - { - if(GetClass() == MONK) - return 379; - else - return 345; - } - else - { - uint16 dmg_table[] = { - 275, 275, 275, 275, 275, - 280, 280, 280, 280, 285, - 285, 285, 290, 290, 295, - 295, 300, 300, 300, 305, - 305, 305, 310, 310, 315, - 315, 320, 320, 320, 325, - 325, 325, 330, 330, 335, - 335, 340, 340, 340, - }; - if(GetClass() == MONK) - return (dmg_table[GetLevel()-51]*(100+RuleI(Combat,MonkDamageTableBonus))/100); - else - return dmg_table[GetLevel()-51]; - } -} - -void Mob::TrySkillProc(Mob *on, uint16 skill, float chance) -{ - - if (!on) { - SetTarget(nullptr); - LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TrySkillProc for evaluation!"); - return; - } - - for (int i = 0; i < MAX_PROCS; i++) { - if (SkillProcs[i].spellID != SPELL_UNKNOWN){ - if (PassLimitToSkill(SkillProcs[i].base_spellID,skill)){ - int ProcChance = chance * (float)SkillProcs[i].chance; - if ((MakeRandomInt(0, 100) < ProcChance)) { - ExecWeaponProc(nullptr, SkillProcs[i].spellID, on); - CheckNumHitsRemaining(11,0, SkillProcs[i].base_spellID); - } - } - } - } -} - -bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) -{ - /*Dev Quote 2010: http://forums.station.sony.com/eq/posts/list.m?topic_id=161443 - The Viscid Roots AA does the following: Reduces the chance for root to break by X percent. - There is no distinction of any kind between the caster inflicted damage, or anyone - else's damage. There is also no distinction between Direct and DOT damage in the root code. - There is however, a provision that if the damage inflicted is greater than 500 per hit, the - chance to break root is increased. My guess is when this code was put in place, the devs at - the time couldn't imagine DOT damage getting that high. - */ - - /* General Mechanics - - Check buffslot to make sure damage from a root does not cancel the root - - If multiple roots on target, always and only checks first root slot and if broken only removes that slots root. - - Only roots on determental spells can be broken by damage. - - Root break chance values obtained from live parses. - */ - - if (!attacker || !spellbonuses.Root[0] || spellbonuses.Root[1] < 0) - return false; - - if (IsDetrimentalSpell(spellbonuses.Root[1]) && spellbonuses.Root[1] != buffslot){ - - int BreakChance = RuleI(Spells, RootBreakFromSpells); - BreakChance -= BreakChance*buffs[spellbonuses.Root[1]].RootBreakChance/100; - int level_diff = attacker->GetLevel() - GetLevel(); - - attacker->Shout("%i ATTACKER LV %i",attacker->GetLevel(), level_diff); - Shout("%i DEF LEVEL %i", GetLevel(), level_diff); - //Use baseline if level difference <= 1 (ie. If target is (1) level less than you, or equal or greater level) - - if (level_diff == 2) - BreakChance = (BreakChance * 80) /100; //Decrease by 20%; - - else if (level_diff >= 3 && level_diff <= 20) - BreakChance = (BreakChance * 60) /100; //Decrease by 40%; - - else if (level_diff > 21) - BreakChance = (BreakChance * 20) /100; //Decrease by 80%; - - Shout("Root Break Chance %i Lv diff %i base %i ", BreakChance, level_diff, RuleI(Spells, RootBreakFromSpells)); - - if (BreakChance < 1) - BreakChance = 1; - - if (MakeRandomInt(0, 99) < BreakChance) { - - if (!TryFadeEffect(spellbonuses.Root[1])) { - BuffFadeBySlot(spellbonuses.Root[1]); - mlog(COMBAT__HITS, "Spell broke root! BreakChance percent chance"); - return true; - } - } - } - - mlog(COMBAT__HITS, "Spell did not break root. BreakChance percent chance"); - return false; -} - -int32 Mob::RuneAbsorb(int32 damage, uint16 type) -{ - uint32 buff_max = GetMaxTotalSlots(); - if (type == SE_Rune){ - for(uint32 slot = 0; slot < buff_max; slot++) { - if(slot == spellbonuses.MeleeRune[1] && spellbonuses.MeleeRune[0] && buffs[slot].melee_rune && IsValidSpell(buffs[slot].spellid)){ - uint32 melee_rune_left = buffs[slot].melee_rune; - - if(melee_rune_left > damage) - { - melee_rune_left -= damage; - buffs[slot].melee_rune = melee_rune_left; - return -6; - } - - else - { - if(melee_rune_left > 0) - damage -= melee_rune_left; - - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - } - } - } - - - else{ - for(uint32 slot = 0; slot < buff_max; slot++) { - if(slot == spellbonuses.AbsorbMagicAtt[1] && spellbonuses.AbsorbMagicAtt[0] && buffs[slot].magic_rune && IsValidSpell(buffs[slot].spellid)){ - uint32 magic_rune_left = buffs[slot].magic_rune; - if(magic_rune_left > damage) - { - magic_rune_left -= damage; - buffs[slot].magic_rune = magic_rune_left; - return 0; - } - - else - { - if(magic_rune_left > 0) - damage -= magic_rune_left; - - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - } - } - } - - return damage; -} - diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index f57e92247..413b8d6c6 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1543,10 +1543,14 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne { int i, effect_value, base2, max, effectid; bool AdditiveWornBonus = false; + Mob *caster = nullptr; if(!IsAISpellEffect && !IsValidSpell(spell_id)) return; + if(casterId > 0) + caster = entity_list.GetMob(casterId); + for (i = 0; i < EFFECT_COUNT; i++) { //Buffs/Item effects @@ -1573,7 +1577,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne AdditiveWornBonus = true; effectid = spells[spell_id].effectid[i]; - effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, instrument_mod, nullptr, ticsremaining, casterId); + effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, instrument_mod, caster, ticsremaining); base2 = spells[spell_id].base2[i]; max = spells[spell_id].max[i]; } diff --git a/zone/bonusesxx.cpp b/zone/bonusesxx.cpp deleted file mode 100644 index 8e23eb5fb..000000000 --- a/zone/bonusesxx.cpp +++ /dev/null @@ -1,4337 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "../common/debug.h" -#include "../common/spdat.h" -#include "masterentity.h" -#include "../common/packet_dump.h" -#include "../common/moremath.h" -#include "../common/Item.h" -#include "worldserver.h" -#include "../common/skills.h" -#include "../common/bodytypes.h" -#include "../common/classes.h" -#include "../common/rulesys.h" -#include "QuestParserCollection.h" -#include -#include -#include -#ifndef WIN32 -#include -#include "../common/unix.h" -#endif - -#include "StringIDs.h" - -void Mob::CalcBonuses() -{ - CalcSpellBonuses(&spellbonuses); - CalcMaxHP(); - CalcMaxMana(); - SetAttackTimer(); - - rooted = FindType(SE_Root); -} - -void NPC::CalcBonuses() -{ - Mob::CalcBonuses(); - memset(&aabonuses, 0, sizeof(StatBonuses)); - - if(RuleB(NPC, UseItemBonusesForNonPets)){ - memset(&itembonuses, 0, sizeof(StatBonuses)); - CalcItemBonuses(&itembonuses); - } - else{ - if(GetOwner()){ - memset(&itembonuses, 0, sizeof(StatBonuses)); - CalcItemBonuses(&itembonuses); - } - } - - // This has to happen last, so we actually take the item bonuses into account. - Mob::CalcBonuses(); -} - -void Client::CalcBonuses() -{ - memset(&itembonuses, 0, sizeof(StatBonuses)); - CalcItemBonuses(&itembonuses); - CalcEdibleBonuses(&itembonuses); - - CalcSpellBonuses(&spellbonuses); - - _log(AA__BONUSES, "Calculating AA Bonuses for %s.", this->GetCleanName()); - CalcAABonuses(&aabonuses); //we're not quite ready for this - _log(AA__BONUSES, "Finished calculating AA Bonuses for %s.", this->GetCleanName()); - - RecalcWeight(); - - CalcAC(); - CalcATK(); - CalcHaste(); - - CalcSTR(); - CalcSTA(); - CalcDEX(); - CalcAGI(); - CalcINT(); - CalcWIS(); - CalcCHA(); - - CalcMR(); - CalcFR(); - CalcDR(); - CalcPR(); - CalcCR(); - CalcCorrup(); - - CalcMaxHP(); - CalcMaxMana(); - CalcMaxEndurance(); - - rooted = FindType(SE_Root); - - XPRate = 100 + spellbonuses.XPRateMod; -} - -int Client::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat) -{ - if( (reclevel > 0) && (level < reclevel) ) - { - int32 statmod = (level * 10000 / reclevel) * basestat; - - if( statmod < 0 ) - { - statmod -= 5000; - return (statmod/10000); - } - else - { - statmod += 5000; - return (statmod/10000); - } - } - - return 0; -} - -void Client::CalcItemBonuses(StatBonuses* newbon) { - //memset assumed to be done by caller. - - // Clear item faction mods - ClearItemFactionBonuses(); - ShieldEquiped(false); - - unsigned int i; - //should not include 21 (SLOT_AMMO) - for (i=0; i<21; i++) { - const ItemInst* inst = m_inv[i]; - if(inst == 0) - continue; - AddItemBonuses(inst, newbon); - - //Check if item is secondary slot is a 'shield'. Required for multiple spelll effects. - if (i == 14 && (m_inv.GetItem(14)->GetItem()->ItemType == ItemTypeShield)) - ShieldEquiped(true); - } - - //Power Source Slot - if (GetClientVersion() >= EQClientSoF) - { - const ItemInst* inst = m_inv[9999]; - if(inst) - AddItemBonuses(inst, newbon); - } - - //tribute items - for (i = 0; i < MAX_PLAYER_TRIBUTES; i++) { - const ItemInst* inst = m_inv[TRIBUTE_SLOT_START + i]; - if(inst == 0) - continue; - AddItemBonuses(inst, newbon, false, true); - } - // Caps - if(newbon->HPRegen > CalcHPRegenCap()) - newbon->HPRegen = CalcHPRegenCap(); - - if(newbon->ManaRegen > CalcManaRegenCap()) - newbon->ManaRegen = CalcManaRegenCap(); - - if(newbon->EnduranceRegen > CalcEnduranceRegenCap()) - newbon->EnduranceRegen = CalcEnduranceRegenCap(); - - SetAttackTimer(); -} - -void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute) { - if(!inst || !inst->IsType(ItemClassCommon)) - { - return; - } - - if(inst->GetAugmentType()==0 && isAug == true) - { - return; - } - - const Item_Struct *item = inst->GetItem(); - - if(!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass())) - { - if(item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink) - return; - } - - if(GetLevel() < item->ReqLevel) - { - return; - } - - if(GetLevel() >= item->RecLevel) - { - newbon->AC += item->AC; - newbon->HP += item->HP; - newbon->Mana += item->Mana; - newbon->Endurance += item->Endur; - newbon->STR += (item->AStr + item->HeroicStr); - newbon->STA += (item->ASta + item->HeroicSta); - newbon->DEX += (item->ADex + item->HeroicDex); - newbon->AGI += (item->AAgi + item->HeroicAgi); - newbon->INT += (item->AInt + item->HeroicInt); - newbon->WIS += (item->AWis + item->HeroicWis); - newbon->CHA += (item->ACha + item->HeroicCha); - - newbon->MR += (item->MR + item->HeroicMR); - newbon->FR += (item->FR + item->HeroicFR); - newbon->CR += (item->CR + item->HeroicCR); - newbon->PR += (item->PR + item->HeroicPR); - newbon->DR += (item->DR + item->HeroicDR); - newbon->Corrup += (item->SVCorruption + item->HeroicSVCorrup); - - newbon->STRCapMod += item->HeroicStr; - newbon->STACapMod += item->HeroicSta; - newbon->DEXCapMod += item->HeroicDex; - newbon->AGICapMod += item->HeroicAgi; - newbon->INTCapMod += item->HeroicInt; - newbon->WISCapMod += item->HeroicWis; - newbon->CHACapMod += item->HeroicCha; - newbon->MRCapMod += item->HeroicMR; - newbon->CRCapMod += item->HeroicFR; - newbon->FRCapMod += item->HeroicCR; - newbon->PRCapMod += item->HeroicPR; - newbon->DRCapMod += item->HeroicDR; - newbon->CorrupCapMod += item->HeroicSVCorrup; - - newbon->HeroicSTR += item->HeroicStr; - newbon->HeroicSTA += item->HeroicSta; - newbon->HeroicDEX += item->HeroicDex; - newbon->HeroicAGI += item->HeroicAgi; - newbon->HeroicINT += item->HeroicInt; - newbon->HeroicWIS += item->HeroicWis; - newbon->HeroicCHA += item->HeroicCha; - newbon->HeroicMR += item->HeroicMR; - newbon->HeroicFR += item->HeroicFR; - newbon->HeroicCR += item->HeroicCR; - newbon->HeroicPR += item->HeroicPR; - newbon->HeroicDR += item->HeroicDR; - newbon->HeroicCorrup += item->HeroicSVCorrup; - - } - else - { - int lvl = GetLevel(); - int reclvl = item->RecLevel; - - newbon->AC += CalcRecommendedLevelBonus( lvl, reclvl, item->AC ); - newbon->HP += CalcRecommendedLevelBonus( lvl, reclvl, item->HP ); - newbon->Mana += CalcRecommendedLevelBonus( lvl, reclvl, item->Mana ); - newbon->Endurance += CalcRecommendedLevelBonus( lvl, reclvl, item->Endur ); - newbon->STR += CalcRecommendedLevelBonus( lvl, reclvl, (item->AStr + item->HeroicStr) ); - newbon->STA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ASta + item->HeroicSta) ); - newbon->DEX += CalcRecommendedLevelBonus( lvl, reclvl, (item->ADex + item->HeroicDex) ); - newbon->AGI += CalcRecommendedLevelBonus( lvl, reclvl, (item->AAgi + item->HeroicAgi) ); - newbon->INT += CalcRecommendedLevelBonus( lvl, reclvl, (item->AInt + item->HeroicInt) ); - newbon->WIS += CalcRecommendedLevelBonus( lvl, reclvl, (item->AWis + item->HeroicWis) ); - newbon->CHA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ACha + item->HeroicCha) ); - - newbon->MR += CalcRecommendedLevelBonus( lvl, reclvl, (item->MR + item->HeroicMR) ); - newbon->FR += CalcRecommendedLevelBonus( lvl, reclvl, (item->FR + item->HeroicFR) ); - newbon->CR += CalcRecommendedLevelBonus( lvl, reclvl, (item->CR + item->HeroicCR) ); - newbon->PR += CalcRecommendedLevelBonus( lvl, reclvl, (item->PR + item->HeroicPR) ); - newbon->DR += CalcRecommendedLevelBonus( lvl, reclvl, (item->DR + item->HeroicDR) ); - newbon->Corrup += CalcRecommendedLevelBonus( lvl, reclvl, (item->SVCorruption + item->HeroicSVCorrup) ); - - newbon->STRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr ); - newbon->STACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta ); - newbon->DEXCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex ); - newbon->AGICapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi ); - newbon->INTCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt ); - newbon->WISCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis ); - newbon->CHACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha ); - newbon->MRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR ); - newbon->CRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR ); - newbon->FRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR ); - newbon->PRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR ); - newbon->DRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR ); - newbon->CorrupCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup ); - - newbon->HeroicSTR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr ); - newbon->HeroicSTA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta ); - newbon->HeroicDEX += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex ); - newbon->HeroicAGI += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi ); - newbon->HeroicINT += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt ); - newbon->HeroicWIS += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis ); - newbon->HeroicCHA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha ); - newbon->HeroicMR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR ); - newbon->HeroicFR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR ); - newbon->HeroicCR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR ); - newbon->HeroicPR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR ); - newbon->HeroicDR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR ); - newbon->HeroicCorrup += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup ); - } - - //FatherNitwit: New style haste, shields, and regens - if(newbon->haste < (int16)item->Haste) { - newbon->haste = item->Haste; - } - if(item->Regen > 0) - newbon->HPRegen += item->Regen; - - if(item->ManaRegen > 0) - newbon->ManaRegen += item->ManaRegen; - - if(item->EnduranceRegen > 0) - newbon->EnduranceRegen += item->EnduranceRegen; - - if(item->Attack > 0) { - - int cap = RuleI(Character, ItemATKCap); - cap += itembonuses.ItemATKCap + spellbonuses.ItemATKCap + aabonuses.ItemATKCap; - - if((newbon->ATK + item->Attack) > cap) - newbon->ATK = RuleI(Character, ItemATKCap); - else - newbon->ATK += item->Attack; - } - if(item->DamageShield > 0) { - if((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap)) - newbon->DamageShield = RuleI(Character, ItemDamageShieldCap); - else - newbon->DamageShield += item->DamageShield; - } - if(item->SpellShield > 0) { - if((newbon->SpellShield + item->SpellShield) > RuleI(Character, ItemSpellShieldingCap)) - newbon->SpellShield = RuleI(Character, ItemSpellShieldingCap); - else - newbon->SpellShield += item->SpellShield; - } - if(item->Shielding > 0) { - if((newbon->MeleeMitigation + item->Shielding) > RuleI(Character, ItemShieldingCap)) - newbon->MeleeMitigation = RuleI(Character, ItemShieldingCap); - else - newbon->MeleeMitigation += item->Shielding; - } - if(item->StunResist > 0) { - if((newbon->StunResist + item->StunResist) > RuleI(Character, ItemStunResistCap)) - newbon->StunResist = RuleI(Character, ItemStunResistCap); - else - newbon->StunResist += item->StunResist; - } - if(item->StrikeThrough > 0) { - if((newbon->StrikeThrough + item->StrikeThrough) > RuleI(Character, ItemStrikethroughCap)) - newbon->StrikeThrough = RuleI(Character, ItemStrikethroughCap); - else - newbon->StrikeThrough += item->StrikeThrough; - } - if(item->Avoidance > 0) { - if((newbon->AvoidMeleeChance + item->Avoidance) > RuleI(Character, ItemAvoidanceCap)) - newbon->AvoidMeleeChance = RuleI(Character, ItemAvoidanceCap); - else - newbon->AvoidMeleeChance += item->Avoidance; - } - if(item->Accuracy > 0) { - if((newbon->HitChance + item->Accuracy) > RuleI(Character, ItemAccuracyCap)) - newbon->HitChance = RuleI(Character, ItemAccuracyCap); - else - newbon->HitChance += item->Accuracy; - } - if(item->CombatEffects > 0) { - if((newbon->ProcChance + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap)) - newbon->ProcChance = RuleI(Character, ItemCombatEffectsCap); - else - newbon->ProcChance += item->CombatEffects; - } - if(item->DotShielding > 0) { - if((newbon->DoTShielding + item->DotShielding) > RuleI(Character, ItemDoTShieldingCap)) - newbon->DoTShielding = RuleI(Character, ItemDoTShieldingCap); - else - newbon->DoTShielding += item->DotShielding; - } - - if(item->HealAmt > 0) { - if((newbon->HealAmt + item->HealAmt) > RuleI(Character, ItemHealAmtCap)) - newbon->HealAmt = RuleI(Character, ItemHealAmtCap); - else - newbon->HealAmt += item->HealAmt; - } - if(item->SpellDmg > 0) { - if((newbon->SpellDmg + item->SpellDmg) > RuleI(Character, ItemSpellDmgCap)) - newbon->SpellDmg = RuleI(Character, ItemSpellDmgCap); - else - newbon->SpellDmg += item->SpellDmg; - } - if(item->Clairvoyance > 0) { - if((newbon->Clairvoyance + item->Clairvoyance) > RuleI(Character, ItemClairvoyanceCap)) - newbon->Clairvoyance = RuleI(Character, ItemClairvoyanceCap); - else - newbon->Clairvoyance += item->Clairvoyance; - } - - if(item->DSMitigation > 0) { - if((newbon->DSMitigation + item->DSMitigation) > RuleI(Character, ItemDSMitigationCap)) - newbon->DSMitigation = RuleI(Character, ItemDSMitigationCap); - else - newbon->DSMitigation += item->DSMitigation; - } - if (item->Worn.Effect>0 && (item->Worn.Type == ET_WornEffect)) { // latent effects - ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, true); - } - - if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects - ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0, true); - } - - switch(item->BardType) - { - case 51: /* All (e.g. Singing Short Sword) */ - { - if(item->BardValue > newbon->singingMod) - newbon->singingMod = item->BardValue; - if(item->BardValue > newbon->brassMod) - newbon->brassMod = item->BardValue; - if(item->BardValue > newbon->stringedMod) - newbon->stringedMod = item->BardValue; - if(item->BardValue > newbon->percussionMod) - newbon->percussionMod = item->BardValue; - if(item->BardValue > newbon->windMod) - newbon->windMod = item->BardValue; - break; - } - case 50: /* Singing */ - { - if(item->BardValue > newbon->singingMod) - newbon->singingMod = item->BardValue; - break; - } - case 23: /* Wind */ - { - if(item->BardValue > newbon->windMod) - newbon->windMod = item->BardValue; - break; - } - case 24: /* stringed */ - { - if(item->BardValue > newbon->stringedMod) - newbon->stringedMod = item->BardValue; - break; - } - case 25: /* brass */ - { - if(item->BardValue > newbon->brassMod) - newbon->brassMod = item->BardValue; - break; - } - case 26: /* Percussion */ - { - if(item->BardValue > newbon->percussionMod) - newbon->percussionMod = item->BardValue; - break; - } - } - - if (item->SkillModValue != 0 && item->SkillModType <= HIGHEST_SKILL){ - if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) || - (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) - { - newbon->skillmod[item->SkillModType] = item->SkillModValue; - } - } - - // Add Item Faction Mods - if (item->FactionMod1) - { - if (item->FactionAmt1 > 0 && item->FactionAmt1 > GetItemFactionBonus(item->FactionMod1)) - { - AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); - } - else if (item->FactionAmt1 < 0 && item->FactionAmt1 < GetItemFactionBonus(item->FactionMod1)) - { - AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); - } - } - if (item->FactionMod2) - { - if (item->FactionAmt2 > 0 && item->FactionAmt2 > GetItemFactionBonus(item->FactionMod2)) - { - AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); - } - else if (item->FactionAmt2 < 0 && item->FactionAmt2 < GetItemFactionBonus(item->FactionMod2)) - { - AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); - } - } - if (item->FactionMod3) - { - if (item->FactionAmt3 > 0 && item->FactionAmt3 > GetItemFactionBonus(item->FactionMod3)) - { - AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); - } - else if (item->FactionAmt3 < 0 && item->FactionAmt3 < GetItemFactionBonus(item->FactionMod3)) - { - AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); - } - } - if (item->FactionMod4) - { - if (item->FactionAmt4 > 0 && item->FactionAmt4 > GetItemFactionBonus(item->FactionMod4)) - { - AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); - } - else if (item->FactionAmt4 < 0 && item->FactionAmt4 < GetItemFactionBonus(item->FactionMod4)) - { - AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); - } - } - - if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= HIGHEST_SKILL) { - if((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) - newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); - else - newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt; - } - - if (!isAug) - { - int i; - for(i = 0; i < MAX_AUGMENT_SLOTS; i++) { - AddItemBonuses(inst->GetAugment(i),newbon,true); - } - } - -} - -void Client::CalcEdibleBonuses(StatBonuses* newbon) { -#if EQDEBUG >= 11 - std::cout<<"Client::CalcEdibleBonuses(StatBonuses* newbon)"<GetItem() && inst->IsType(ItemClassCommon)) { - const Item_Struct *item=inst->GetItem(); - if (item->ItemType == ItemTypeFood && !food) - food = true; - else if (item->ItemType == ItemTypeDrink && !drink) - drink = true; - else - continue; - AddItemBonuses(inst, newbon); - } - } - for (i = 251; i <= 330; i++) - { - if (food && drink) - break; - const ItemInst* inst = GetInv().GetItem(i); - if (inst && inst->GetItem() && inst->IsType(ItemClassCommon)) { - const Item_Struct *item=inst->GetItem(); - if (item->ItemType == ItemTypeFood && !food) - food = true; - else if (item->ItemType == ItemTypeDrink && !drink) - drink = true; - else - continue; - AddItemBonuses(inst, newbon); - } - } -} - -void Client::CalcAABonuses(StatBonuses* newbon) { - memset(newbon, 0, sizeof(StatBonuses)); //start fresh - - int i; - uint32 slots = 0; - uint32 aa_AA = 0; - uint32 aa_value = 0; - if(this->aa) { - for (i = 0; i < MAX_PP_AA_ARRAY; i++) { //iterate through all of the client's AAs - if (this->aa[i]) { // make sure aa exists or we'll crash zone - aa_AA = this->aa[i]->AA; //same as aaid from the aa_effects table - aa_value = this->aa[i]->value; //how many points in it - if (aa_AA > 0 || aa_value > 0) { //do we have the AA? if 1 of the 2 is set, we can assume we do - //slots = database.GetTotalAALevels(aa_AA); //find out how many effects from aa_effects table - slots = zone->GetTotalAALevels(aa_AA); //find out how many effects from aa_effects, which is loaded into memory - if (slots > 0) //and does it have any effects? may be able to put this above, not sure if it runs on each iteration - ApplyAABonuses(aa_AA, slots, newbon); //add the bonuses - } - } - } - } -} - - -//A lot of the normal spell functions (IsBlankSpellEffect, etc) are set for just spells (in common/spdat.h). -//For now, we'll just put them directly into the code and comment with the corresponding normal function -//Maybe we'll fix it later? :-D -void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) -{ - if(slots == 0) //sanity check. why bother if no slots to fill? - return; - - //from AA_Ability struct - uint32 effect = 0; - int32 base1 = 0; - int32 base2 = 0; //only really used for SE_RaiseStatCap & SE_ReduceSkillTimer in aa_effects table - uint32 slot = 0; - - std::map >::const_iterator find_iter = aa_effects.find(aaid); - if(find_iter == aa_effects.end()) - { - return; - } - - for (std::map::const_iterator iter = aa_effects[aaid].begin(); iter != aa_effects[aaid].end(); ++iter) { - effect = iter->second.skill_id; - base1 = iter->second.base1; - base2 = iter->second.base2; - slot = iter->second.slot; - - //we default to 0 (SE_CurrentHP) for the effect, so if there aren't any base1/2 values, we'll just skip it - if (effect == 0 && base1 == 0 && base2 == 0) - continue; - - //IsBlankSpellEffect() - if (effect == SE_Blank || (effect == SE_CHA && base1 == 0) || effect == SE_StackingCommand_Block || effect == SE_StackingCommand_Overwrite) - continue; - - _log(AA__BONUSES, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName()); - - uint8 focus = IsFocusEffect(0, 0, true,effect); - if (focus) - { - newbon->FocusEffects[focus] = effect; - continue; - } - - switch (effect) - { - //Note: AA effects that use accuracy are skill limited, while spell effect is not. - case SE_Accuracy: - if ((base2 == -1) && (newbon->Accuracy[HIGHEST_SKILL+1] < base1)) - newbon->Accuracy[HIGHEST_SKILL+1] = base1; - else if (newbon->Accuracy[base2] < base1) - newbon->Accuracy[base2] += base1; - break; - case SE_CurrentHP: //regens - newbon->HPRegen += base1; - break; - case SE_CurrentEndurance: - newbon->EnduranceRegen += base1; - break; - case SE_MovementSpeed: - newbon->movementspeed += base1; //should we let these stack? - /*if (base1 > newbon->movementspeed) //or should we use a total value? - newbon->movementspeed = base1;*/ - break; - case SE_STR: - newbon->STR += base1; - break; - case SE_DEX: - newbon->DEX += base1; - break; - case SE_AGI: - newbon->AGI += base1; - break; - case SE_STA: - newbon->STA += base1; - break; - case SE_INT: - newbon->INT += base1; - break; - case SE_WIS: - newbon->WIS += base1; - break; - case SE_CHA: - newbon->CHA += base1; - break; - case SE_WaterBreathing: - //handled by client - break; - case SE_CurrentMana: - newbon->ManaRegen += base1; - break; - case SE_ItemManaRegenCapIncrease: - newbon->ItemManaRegenCap += base1; - break; - case SE_ResistFire: - newbon->FR += base1; - break; - case SE_ResistCold: - newbon->CR += base1; - break; - case SE_ResistPoison: - newbon->PR += base1; - break; - case SE_ResistDisease: - newbon->DR += base1; - break; - case SE_ResistMagic: - newbon->MR += base1; - break; - case SE_ResistCorruption: - newbon->Corrup += base1; - break; - case SE_IncreaseSpellHaste: - break; - case SE_IncreaseRange: - break; - case SE_MaxHPChange: - newbon->MaxHP += base1; - break; - case SE_Packrat: - newbon->Packrat += base1; - break; - case SE_TwoHandBash: - break; - case SE_SetBreathLevel: - break; - case SE_RaiseStatCap: - switch(base2) - { - //are these #define'd somewhere? - case 0: //str - newbon->STRCapMod += base1; - break; - case 1: //sta - newbon->STACapMod += base1; - break; - case 2: //agi - newbon->AGICapMod += base1; - break; - case 3: //dex - newbon->DEXCapMod += base1; - break; - case 4: //wis - newbon->WISCapMod += base1; - break; - case 5: //int - newbon->INTCapMod += base1; - break; - case 6: //cha - newbon->CHACapMod += base1; - break; - case 7: //mr - newbon->MRCapMod += base1; - break; - case 8: //cr - newbon->CRCapMod += base1; - break; - case 9: //fr - newbon->FRCapMod += base1; - break; - case 10: //pr - newbon->PRCapMod += base1; - break; - case 11: //dr - newbon->DRCapMod += base1; - break; - case 12: //corruption - newbon->CorrupCapMod += base1; - break; - } - break; - case SE_PetDiscipline2: - break; - case SE_SpellSlotIncrease: - break; - case SE_MysticalAttune: - newbon->BuffSlotIncrease += base1; - break; - case SE_TotalHP: - newbon->HP += base1; - break; - case SE_StunResist: - newbon->StunResist += base1; - break; - case SE_SpellCritChance: - newbon->CriticalSpellChance += base1; - break; - case SE_SpellCritDmgIncrease: - newbon->SpellCritDmgIncrease += base1; - break; - case SE_DotCritDmgIncrease: - newbon->DotCritDmgIncrease += base1; - break; - case SE_ResistSpellChance: - newbon->ResistSpellChance += base1; - break; - case SE_CriticalHealChance: - newbon->CriticalHealChance += base1; - break; - case SE_CriticalHealOverTime: - newbon->CriticalHealOverTime += base1; - break; - case SE_CriticalDoTChance: - newbon->CriticalDoTChance += base1; - break; - case SE_ReduceSkillTimer: - newbon->SkillReuseTime[base2] += base1; - break; - case SE_Fearless: - newbon->Fearless = true; - break; - case SE_PersistantCasting: - newbon->PersistantCasting += base1; - break; - case SE_DelayDeath: - newbon->DelayDeath += base1; - break; - case SE_FrontalStunResist: - newbon->FrontalStunResist += base1; - break; - case SE_ImprovedBindWound: - newbon->BindWound += base1; - break; - case SE_MaxBindWound: - newbon->MaxBindWound += base1; - break; - case SE_ExtraAttackChance: - newbon->ExtraAttackChance += base1; - break; - case SE_SeeInvis: - newbon->SeeInvis = base1; - break; - case SE_BaseMovementSpeed: - newbon->BaseMovementSpeed += base1; - break; - case SE_IncreaseRunSpeedCap: - newbon->IncreaseRunSpeedCap += base1; - break; - case SE_ConsumeProjectile: - newbon->ConsumeProjectile += base1; - break; - case SE_ForageAdditionalItems: - newbon->ForageAdditionalItems += base1; - break; - case SE_Salvage: - newbon->SalvageChance += base1; - break; - case SE_ArcheryDamageModifier: - newbon->ArcheryDamageModifier += base1; - break; - case SE_DoubleRangedAttack: - newbon->DoubleRangedAttack += base1; - break; - case SE_DamageShield: - newbon->DamageShield += base1; - break; - case SE_CharmBreakChance: - newbon->CharmBreakChance += base1; - break; - case SE_OffhandRiposteFail: - newbon->OffhandRiposteFail += base1; - break; - case SE_ItemAttackCapIncrease: - newbon->ItemATKCap += base1; - break; - case SE_GivePetGroupTarget: - newbon->GivePetGroupTarget = true; - break; - case SE_ItemHPRegenCapIncrease: - newbon->ItemHPRegenCap = +base1; - break; - case SE_Ambidexterity: - newbon->Ambidexterity += base1; - break; - case SE_PetMaxHP: - newbon->PetMaxHP += base1; - break; - case SE_AvoidMeleeChance: - newbon->AvoidMeleeChance += base1; - break; - case SE_CombatStability: - newbon->CombatStability += base1; - break; - case SE_AddSingingMod: - switch (base2) - { - case ItemTypeWindInstrument: - newbon->windMod += base1; - break; - case ItemTypeStringedInstrument: - newbon->stringedMod += base1; - break; - case ItemTypeBrassInstrument: - newbon->brassMod += base1; - break; - case ItemTypePercussionInstrument: - newbon->percussionMod += base1; - break; - case ItemTypeSinging: - newbon->singingMod += base1; - break; - } - break; - case SE_SongModCap: - newbon->songModCap += base1; - break; - case SE_PetCriticalHit: - newbon->PetCriticalHit += base1; - break; - case SE_PetAvoidance: - newbon->PetAvoidance += base1; - break; - case SE_ShieldBlock: - newbon->ShieldBlock += base1; - break; - case SE_ShieldEquipHateMod: - newbon->ShieldEquipHateMod += base1; - break; - case SE_ShieldEquipDmgMod: - newbon->ShieldEquipDmgMod[0] += base1; - newbon->ShieldEquipDmgMod[1] += base2; - break; - case SE_SecondaryDmgInc: - newbon->SecondaryDmgInc = true; - break; - case SE_ChangeAggro: - newbon->hatemod += base1; - break; - case SE_EndurancePool: - newbon->Endurance += base1; - break; - case SE_ChannelChanceItems: - newbon->ChannelChanceItems += base1; - break; - case SE_ChannelChanceSpells: - newbon->ChannelChanceSpells += base1; - break; - case SE_DoubleSpecialAttack: - newbon->DoubleSpecialAttack += base1; - break; - case SE_TripleBackstab: - newbon->TripleBackstab += base1; - break; - case SE_FrontalBackstabMinDmg: - newbon->FrontalBackstabMinDmg = true; - break; - case SE_FrontalBackstabChance: - newbon->FrontalBackstabChance += base1; - break; - case SE_BlockBehind: - newbon->BlockBehind += base1; - break; - - case SE_StrikeThrough: - case SE_StrikeThrough2: - newbon->StrikeThrough += base1; - break; - case SE_DoubleAttackChance: - newbon->DoubleAttackChance += base1; - break; - case SE_GiveDoubleAttack: - newbon->GiveDoubleAttack += base1; - break; - case SE_ProcChance: - newbon->ProcChanceSPA += base1; - break; - case SE_RiposteChance: - newbon->RiposteChance += base1; - break; - case SE_Flurry: - newbon->FlurryChance += base1; - break; - case SE_PetFlurry: - newbon->PetFlurry = base1; - break; - case SE_BardSongRange: - newbon->SongRange += base1; - break; - case SE_RootBreakChance: - newbon->RootBreakChance += base1; - break; - case SE_UnfailingDivinity: - newbon->UnfailingDivinity += base1; - break; - case SE_CrippBlowChance: - newbon->CrippBlowChance += base1; - break; - - case SE_ProcOnKillShot: - for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) - { - if(!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == base2) && (newbon->SpellOnKill[i+1] < base1))) - { - //base1 = chance, base2 = SpellID to be triggered, base3 = min npc level - newbon->SpellOnKill[i] = base2; - newbon->SpellOnKill[i+1] = base1; - - if (GetLevel() > 15) - newbon->SpellOnKill[i+2] = GetLevel() - 15; //AA specifiy "non-trivial" - else - newbon->SpellOnKill[i+2] = 0; - - break; - } - } - break; - - case SE_SpellOnDeath: - for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) - { - if(!newbon->SpellOnDeath[i]) - { - // base1 = SpellID to be triggered, base2 = chance to fire - newbon->SpellOnDeath[i] = base1; - newbon->SpellOnDeath[i+1] = base2; - break; - } - } - break; - - case SE_TriggerOnCast: - - for(int i = 0; i < MAX_SPELL_TRIGGER; i++) - { - if (newbon->SpellTriggers[i] == aaid) - break; - - if(!newbon->SpellTriggers[i]) - { - //Save the 'aaid' of each triggerable effect to an array - newbon->SpellTriggers[i] = aaid; - break; - } - } - break; - - case SE_CriticalHitChance: - { - if(base2 == -1) - newbon->CriticalHitChance[HIGHEST_SKILL+1] += base1; - else - newbon->CriticalHitChance[base2] += base1; - } - break; - - case SE_CriticalDamageMob: - { - // base1 = effect value, base2 = skill restrictions(-1 for all) - if(base2 == -1) - newbon->CritDmgMob[HIGHEST_SKILL+1] += base1; - else - newbon->CritDmgMob[base2] += base1; - break; - } - - case SE_CriticalSpellChance: - { - newbon->CriticalSpellChance += base1; - - if (base2 > newbon->SpellCritDmgIncNoStack) - newbon->SpellCritDmgIncNoStack = base2; - - break; - } - - case SE_ResistFearChance: - { - if(base1 == 100) // If we reach 100% in a single spell/item then we should be immune to negative fear resist effects until our immunity is over - newbon->Fearless = true; - - newbon->ResistFearChance += base1; // these should stack - break; - } - - case SE_SkillDamageAmount: - { - if(base2 == -1) - newbon->SkillDamageAmount[HIGHEST_SKILL+1] += base1; - else - newbon->SkillDamageAmount[base2] += base1; - break; - } - - case SE_SpecialAttackKBProc: - { - //You can only have one of these per client. [AA Dragon Punch] - newbon->SpecialAttackKBProc[0] = base1; //Chance base 100 = 25% proc rate - newbon->SpecialAttackKBProc[1] = base2; //Skill to KB Proc Off - break; - } - - case SE_DamageModifier: - { - if(base2 == -1) - newbon->DamageModifier[HIGHEST_SKILL+1] += base1; - else - newbon->DamageModifier[base2] += base1; - break; - } - - case SE_DamageModifier2: - { - if(base2 == -1) - newbon->DamageModifier2[HIGHEST_SKILL+1] += base1; - else - newbon->DamageModifier2[base2] += base1; - break; - } - - case SE_SlayUndead: - { - if(newbon->SlayUndead[1] < base1) - newbon->SlayUndead[0] = base1; // Rate - newbon->SlayUndead[1] = base2; // Damage Modifier - break; - } - - case SE_DoubleRiposte: - { - newbon->DoubleRiposte += base1; - } - - case SE_GiveDoubleRiposte: - { - //0=Regular Riposte 1=Skill Attack Riposte 2=Skill - if(base2 == 0){ - if(newbon->GiveDoubleRiposte[0] < base1) - newbon->GiveDoubleRiposte[0] = base1; - } - //Only for special attacks. - else if(base2 > 0 && (newbon->GiveDoubleRiposte[1] < base1)){ - newbon->GiveDoubleRiposte[1] = base1; - newbon->GiveDoubleRiposte[2] = base2; - } - - break; - } - - //Kayen: Not sure best way to implement this yet. - //Physically raises skill cap ie if 55/55 it will raise to 55/60 - case SE_RaiseSkillCap: - { - if(newbon->RaiseSkillCap[0] < base1){ - newbon->RaiseSkillCap[0] = base1; //value - newbon->RaiseSkillCap[1] = base2; //skill - } - break; - } - - case SE_MasteryofPast: - { - if(newbon->MasteryofPast < base1) - newbon->MasteryofPast = base1; - break; - } - - case SE_CastingLevel2: - case SE_CastingLevel: - { - newbon->effective_casting_level += base1; - break; - } - - case SE_DivineSave: - { - if(newbon->DivineSaveChance[0] < base1) - { - newbon->DivineSaveChance[0] = base1; - newbon->DivineSaveChance[1] = base2; - } - break; - } - - - case SE_SpellEffectResistChance: - { - for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) - { - if(newbon->SEResist[e+1] && (newbon->SEResist[e] == base2) && (newbon->SEResist[e+1] < base1)){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = base1; //Resist Chance - break; - } - else if (!newbon->SEResist[e+1]){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = base1; //Resist Chance - break; - } - } - break; - } - - case SE_MitigateDamageShield: - { - if (base1 < 0) - base1 = base1*(-1); - - newbon->DSMitigationOffHand += base1; - break; - } - - case SE_FinishingBlow: - { - //base1 = chance, base2 = damage - if (newbon->FinishingBlow[1] < base2){ - newbon->FinishingBlow[0] = base1; - newbon->FinishingBlow[1] = base2; - } - break; - } - - case SE_FinishingBlowLvl: - { - //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) - if (newbon->FinishingBlowLvl[0] < base1){ - newbon->FinishingBlowLvl[0] = base1; - newbon->FinishingBlowLvl[1] = base2; - } - break; - } - - case SE_StunBashChance: - newbon->StunBashChance += base1; - break; - - case SE_IncreaseChanceMemwipe: - newbon->IncreaseChanceMemwipe += base1; - break; - - case SE_CriticalMend: - newbon->CriticalMend += base1; - break; - - case SE_HealRate: - newbon->HealRate += base1; - break; - - case SE_MeleeLifetap: - { - - if((base1 < 0) && (newbon->MeleeLifetap > base1)) - newbon->MeleeLifetap = base1; - - else if(newbon->MeleeLifetap < base1) - newbon->MeleeLifetap = base1; - break; - } - - case SE_Vampirism: - newbon->Vampirism += base1; - break; - - case SE_FrenziedDevastation: - newbon->FrenziedDevastation += base2; - break; - - case SE_SpellProcChance: - newbon->SpellProcChance += base1; - break; - - case SE_Berserk: - newbon->BerserkSPA = true; - break; - - case SE_Metabolism: - newbon->Metabolism += base1; - break; - - case SE_ImprovedReclaimEnergy: - { - if((base1 < 0) && (newbon->ImprovedReclaimEnergy > base1)) - newbon->ImprovedReclaimEnergy = base1; - - else if(newbon->ImprovedReclaimEnergy < base1) - newbon->ImprovedReclaimEnergy = base1; - break; - } - - case SE_HeadShot: - { - if(newbon->HeadShot[1] < base2){ - newbon->HeadShot[0] = base1; - newbon->HeadShot[1] = base2; - } - break; - } - - case SE_HeadShotLevel: - { - if(newbon->HSLevel < base1) - newbon->HSLevel = base1; - break; - } - - case SE_Assassinate: - { - if(newbon->Assassinate[1] < base2){ - newbon->Assassinate[0] = base1; - newbon->Assassinate[1] = base2; - } - break; - } - - case SE_AssassinateLevel: - { - if(newbon->AssassinateLevel < base1) - newbon->AssassinateLevel = base1; - break; - } - - case SE_PetMeleeMitigation: - newbon->PetMeleeMitigation += base1; - break; - - } - } -} - -void Mob::CalcSpellBonuses(StatBonuses* newbon) -{ - int i; - - memset(newbon, 0, sizeof(StatBonuses)); - newbon->AggroRange = -1; - newbon->AssistRange = -1; - - uint32 buff_count = GetMaxTotalSlots(); - for(i = 0; i < buff_count; i++) { - if(buffs[i].spellid != SPELL_UNKNOWN){ - ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, false, buffs[i].ticsremaining,i); - - if (buffs[i].numhits > 0) - Numhits(true); - } - } - - //Applies any perma NPC spell bonuses from npc_spells_effects table. - if (IsNPC()) - CastToNPC()->ApplyAISpellEffects(newbon); - - //Removes the spell bonuses that are effected by a 'negate' debuff. - if (spellbonuses.NegateEffects){ - for(i = 0; i < buff_count; i++) { - if( (buffs[i].spellid != SPELL_UNKNOWN) && (IsEffectInSpell(buffs[i].spellid, SE_NegateSpellEffect)) ) - NegateSpellsBonuses(buffs[i].spellid); - } - } - //this prolly suffer from roundoff error slightly... - newbon->AC = newbon->AC * 10 / 34; //ratio determined impirically from client. - if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. -} - -void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterId, bool item_bonus, uint32 ticsremaining, int buffslot, - bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) -{ - int i, effect_value, base2, max, effectid; - Mob *caster = nullptr; - - if(!IsAISpellEffect && !IsValidSpell(spell_id)) - return; - - if(casterId > 0) - caster = entity_list.GetMob(casterId); - - for (i = 0; i < EFFECT_COUNT; i++) - { - //Buffs/Item effects - if (!IsAISpellEffect) { - - if(IsBlankSpellEffect(spell_id, i)) - continue; - - uint8 focus = IsFocusEffect(spell_id, i); - if (focus) - { - newbon->FocusEffects[focus] = spells[spell_id].effectid[i]; - continue; - } - - - effectid = spells[spell_id].effectid[i]; - effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, caster, ticsremaining); - base2 = spells[spell_id].base2[i]; - max = spells[spell_id].max[i]; - } - //Use AISpellEffects - else { - effectid = effect_id; - effect_value = se_base; - base2 = se_limit; - max = se_max; - i = EFFECT_COUNT; //End the loop - } - - switch (effectid) - { - case SE_CurrentHP: //regens - if(effect_value > 0) { - newbon->HPRegen += effect_value; - } - break; - - case SE_CurrentEndurance: - newbon->EnduranceRegen += effect_value; - break; - - case SE_ChangeFrenzyRad: - { - // redundant to have level check here - if(newbon->AggroRange == -1 || effect_value < newbon->AggroRange) - { - newbon->AggroRange = effect_value; - } - break; - } - - case SE_Harmony: - { - // neotokyo: Harmony effect as buff - kinda tricky - // harmony could stack with a lull spell, which has better aggro range - // take the one with less range in any case - if(newbon->AssistRange == -1 || effect_value < newbon->AssistRange) - { - newbon->AssistRange = effect_value; - } - break; - } - - case SE_AttackSpeed: - { - if ((effect_value - 100) > 0) { // Haste - if (newbon->haste < 0) break; // Slowed - Don't apply haste - if ((effect_value - 100) > newbon->haste) { - newbon->haste = effect_value - 100; - } - } - else if ((effect_value - 100) < 0) { // Slow - int real_slow_value = (100 - effect_value) * -1; - real_slow_value -= ((real_slow_value * GetSlowMitigation()/100)); - if (real_slow_value < newbon->haste) - newbon->haste = real_slow_value; - } - break; - } - - case SE_AttackSpeed2: - { - if ((effect_value - 100) > 0) { // Haste V2 - Stacks with V1 but does not Overcap - if (newbon->hastetype2 < 0) break; //Slowed - Don't apply haste2 - if ((effect_value - 100) > newbon->hastetype2) { - newbon->hastetype2 = effect_value - 100; - } - } - else if ((effect_value - 100) < 0) { // Slow - int real_slow_value = (100 - effect_value) * -1; - real_slow_value -= ((real_slow_value * GetSlowMitigation()/100)); - if (real_slow_value < newbon->hastetype2) - newbon->hastetype2 = real_slow_value; - } - break; - } - - case SE_AttackSpeed3: - { - if (effect_value < 0){ //Slow - effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value < newbon->hastetype3) - newbon->hastetype3 = effect_value; - } - - else if (effect_value > 0) { // Haste V3 - Stacks and Overcaps - if (effect_value > newbon->hastetype3) { - newbon->hastetype3 = effect_value; - } - } - break; - } - - case SE_AttackSpeed4: - { - if (effect_value < 0) //A few spells use negative values(Descriptions all indicate it should be a slow) - effect_value = effect_value * -1; - - if (effect_value > 0 && effect_value > newbon->inhibitmelee) { - effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value > newbon->inhibitmelee) - newbon->inhibitmelee = effect_value; - } - - break; - } - - case SE_TotalHP: - { - newbon->HP += effect_value; - break; - } - - case SE_ManaRegen_v2: - case SE_CurrentMana: - { - newbon->ManaRegen += effect_value; - break; - } - - case SE_ManaPool: - { - newbon->Mana += effect_value; - break; - } - - case SE_Stamina: - { - newbon->EnduranceReduction += effect_value; - break; - } - - case SE_ACv2: - case SE_ArmorClass: - { - newbon->AC += effect_value; - break; - } - - case SE_ATK: - { - newbon->ATK += effect_value; - break; - } - - case SE_STR: - { - newbon->STR += effect_value; - break; - } - - case SE_DEX: - { - newbon->DEX += effect_value; - break; - } - - case SE_AGI: - { - newbon->AGI += effect_value; - break; - } - - case SE_STA: - { - newbon->STA += effect_value; - break; - } - - case SE_INT: - { - newbon->INT += effect_value; - break; - } - - case SE_WIS: - { - newbon->WIS += effect_value; - break; - } - - case SE_CHA: - { - if (spells[spell_id].base[i] != 0) { - newbon->CHA += effect_value; - } - break; - } - - case SE_AllStats: - { - newbon->STR += effect_value; - newbon->DEX += effect_value; - newbon->AGI += effect_value; - newbon->STA += effect_value; - newbon->INT += effect_value; - newbon->WIS += effect_value; - newbon->CHA += effect_value; - break; - } - - case SE_ResistFire: - { - newbon->FR += effect_value; - break; - } - - case SE_ResistCold: - { - newbon->CR += effect_value; - break; - } - - case SE_ResistPoison: - { - newbon->PR += effect_value; - break; - } - - case SE_ResistDisease: - { - newbon->DR += effect_value; - break; - } - - case SE_ResistMagic: - { - newbon->MR += effect_value; - break; - } - - case SE_ResistAll: - { - newbon->MR += effect_value; - newbon->DR += effect_value; - newbon->PR += effect_value; - newbon->CR += effect_value; - newbon->FR += effect_value; - break; - } - - case SE_ResistCorruption: - { - newbon->Corrup += effect_value; - break; - } - - case SE_RaiseStatCap: - { - switch(spells[spell_id].base2[i]) - { - //are these #define'd somewhere? - case 0: //str - newbon->STRCapMod += effect_value; - break; - case 1: //sta - newbon->STACapMod += effect_value; - break; - case 2: //agi - newbon->AGICapMod += effect_value; - break; - case 3: //dex - newbon->DEXCapMod += effect_value; - break; - case 4: //wis - newbon->WISCapMod += effect_value; - break; - case 5: //int - newbon->INTCapMod += effect_value; - break; - case 6: //cha - newbon->CHACapMod += effect_value; - break; - case 7: //mr - newbon->MRCapMod += effect_value; - break; - case 8: //cr - newbon->CRCapMod += effect_value; - break; - case 9: //fr - newbon->FRCapMod += effect_value; - break; - case 10: //pr - newbon->PRCapMod += effect_value; - break; - case 11: //dr - newbon->DRCapMod += effect_value; - break; - case 12: // corruption - newbon->CorrupCapMod += effect_value; - break; - } - break; - } - - case SE_CastingLevel2: - case SE_CastingLevel: // Brilliance of Ro - { - newbon->effective_casting_level += effect_value; - break; - } - - case SE_MovementSpeed: - newbon->movementspeed += effect_value; - break; - - case SE_SpellDamageShield: - newbon->SpellDamageShield += effect_value; - break; - - case SE_DamageShield: - { - newbon->DamageShield += effect_value; - newbon->DamageShieldSpellID = spell_id; - //When using npc_spells_effects MAX value can be set to determine DS Type - if (IsAISpellEffect && max) - newbon->DamageShieldType = GetDamageShieldType(spell_id, max); - else - newbon->DamageShieldType = GetDamageShieldType(spell_id); - - break; - } - - case SE_ReverseDS: - { - newbon->ReverseDamageShield += effect_value; - newbon->ReverseDamageShieldSpellID = spell_id; - - if (IsAISpellEffect && max) - newbon->ReverseDamageShieldType = GetDamageShieldType(spell_id, max); - else - newbon->ReverseDamageShieldType = GetDamageShieldType(spell_id); - break; - } - - case SE_Reflect: - newbon->reflect_chance += effect_value; - break; - - case SE_Amplification: - newbon->Amplification += effect_value; - break; - - case SE_ChangeAggro: - newbon->hatemod += effect_value; - break; - - case SE_MeleeMitigation: - //for some reason... this value is negative for increased mitigation - newbon->MeleeMitigation -= effect_value; - break; - - case SE_CriticalHitChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) { - if(base2 == -1) - newbon->CriticalHitChance[HIGHEST_SKILL+1] += effect_value; - else - newbon->CriticalHitChance[base2] += effect_value; - } - - else if(effect_value < 0) { - - if(base2 == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] > effect_value) - newbon->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; - else if(base2 != -1 && newbon->CriticalHitChance[base2] > effect_value) - newbon->CriticalHitChance[base2] = effect_value; - } - - - else if(base2 == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] < effect_value) - newbon->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; - else if(base2 != -1 && newbon->CriticalHitChance[base2] < effect_value) - newbon->CriticalHitChance[base2] = effect_value; - - break; - } - - case SE_CrippBlowChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->CrippBlowChance += effect_value; - - else if((effect_value < 0) && (newbon->CrippBlowChance > effect_value)) - newbon->CrippBlowChance = effect_value; - - else if(newbon->CrippBlowChance < effect_value) - newbon->CrippBlowChance = effect_value; - - break; - } - - case SE_AvoidMeleeChance: - { - //multiplier is to be compatible with item effects, watching for overflow too - effect_value = effect_value<3000? effect_value * 10 : 30000; - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->AvoidMeleeChance += effect_value; - - else if((effect_value < 0) && (newbon->AvoidMeleeChance > effect_value)) - newbon->AvoidMeleeChance = effect_value; - - else if(newbon->AvoidMeleeChance < effect_value) - newbon->AvoidMeleeChance = effect_value; - break; - } - - case SE_RiposteChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->RiposteChance += effect_value; - - else if((effect_value < 0) && (newbon->RiposteChance > effect_value)) - newbon->RiposteChance = effect_value; - - else if(newbon->RiposteChance < effect_value) - newbon->RiposteChance = effect_value; - break; - } - - case SE_DodgeChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->DodgeChance += effect_value; - - else if((effect_value < 0) && (newbon->DodgeChance > effect_value)) - newbon->DodgeChance = effect_value; - - if(newbon->DodgeChance < effect_value) - newbon->DodgeChance = effect_value; - break; - } - - case SE_ParryChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->ParryChance += effect_value; - - else if((effect_value < 0) && (newbon->ParryChance > effect_value)) - newbon->ParryChance = effect_value; - - if(newbon->ParryChance < effect_value) - newbon->ParryChance = effect_value; - break; - } - - case SE_DualWieldChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->DualWieldChance += effect_value; - - else if((effect_value < 0) && (newbon->DualWieldChance > effect_value)) - newbon->DualWieldChance = effect_value; - - if(newbon->DualWieldChance < effect_value) - newbon->DualWieldChance = effect_value; - break; - } - - case SE_DoubleAttackChance: - { - - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->DoubleAttackChance += effect_value; - - else if((effect_value < 0) && (newbon->DoubleAttackChance > effect_value)) - newbon->DoubleAttackChance = effect_value; - - if(newbon->DoubleAttackChance < effect_value) - newbon->DoubleAttackChance = effect_value; - break; - } - - case SE_TripleAttackChance: - { - - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->TripleAttackChance += effect_value; - - else if((effect_value < 0) && (newbon->TripleAttackChance > effect_value)) - newbon->TripleAttackChance = effect_value; - - if(newbon->TripleAttackChance < effect_value) - newbon->TripleAttackChance = effect_value; - break; - } - - case SE_MeleeLifetap: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->MeleeLifetap += spells[spell_id].base[i]; - - else if((effect_value < 0) && (newbon->MeleeLifetap > effect_value)) - newbon->MeleeLifetap = effect_value; - - else if(newbon->MeleeLifetap < effect_value) - newbon->MeleeLifetap = effect_value; - break; - } - - case SE_Vampirism: - newbon->Vampirism += effect_value; - break; - - case SE_AllInstrumentMod: - { - if(effect_value > newbon->singingMod) - newbon->singingMod = effect_value; - if(effect_value > newbon->brassMod) - newbon->brassMod = effect_value; - if(effect_value > newbon->percussionMod) - newbon->percussionMod = effect_value; - if(effect_value > newbon->windMod) - newbon->windMod = effect_value; - if(effect_value > newbon->stringedMod) - newbon->stringedMod = effect_value; - break; - } - - case SE_ResistSpellChance: - newbon->ResistSpellChance += effect_value; - break; - - case SE_ResistFearChance: - { - if(effect_value == 100) // If we reach 100% in a single spell/item then we should be immune to negative fear resist effects until our immunity is over - newbon->Fearless = true; - - newbon->ResistFearChance += effect_value; // these should stack - break; - } - - case SE_Fearless: - newbon->Fearless = true; - break; - - case SE_HundredHands: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->HundredHands += effect_value; - - if (effect_value > 0 && effect_value > newbon->HundredHands) - newbon->HundredHands = effect_value; //Increase Weapon Delay - else if (effect_value < 0 && effect_value < newbon->HundredHands) - newbon->HundredHands = effect_value; //Decrease Weapon Delay - break; - } - - case SE_MeleeSkillCheck: - { - if(newbon->MeleeSkillCheck < effect_value) { - newbon->MeleeSkillCheck = effect_value; - newbon->MeleeSkillCheckSkill = base2==-1?255:base2; - } - break; - } - - case SE_HitChance: - { - - if (RuleB(Spells, AdditiveBonusValues) && item_bonus){ - if(base2 == -1) - newbon->HitChanceEffect[HIGHEST_SKILL+1] += effect_value; - else - newbon->HitChanceEffect[base2] += effect_value; - } - - else if(base2 == -1){ - - if ((effect_value < 0) && (newbon->HitChanceEffect[HIGHEST_SKILL+1] > effect_value)) - newbon->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; - - else if (!newbon->HitChanceEffect[HIGHEST_SKILL+1] || - ((newbon->HitChanceEffect[HIGHEST_SKILL+1] > 0) && (newbon->HitChanceEffect[HIGHEST_SKILL+1] < effect_value))) - newbon->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; - } - - else { - - if ((effect_value < 0) && (newbon->HitChanceEffect[base2] > effect_value)) - newbon->HitChanceEffect[base2] = effect_value; - - else if (!newbon->HitChanceEffect[base2] || - ((newbon->HitChanceEffect[base2] > 0) && (newbon->HitChanceEffect[base2] < effect_value))) - newbon->HitChanceEffect[base2] = effect_value; - } - - break; - - } - - case SE_DamageModifier: - { - if(base2 == -1) - newbon->DamageModifier[HIGHEST_SKILL+1] += effect_value; - else - newbon->DamageModifier[base2] += effect_value; - break; - } - - case SE_DamageModifier2: - { - if(base2 == -1) - newbon->DamageModifier2[HIGHEST_SKILL+1] += effect_value; - else - newbon->DamageModifier2[base2] += effect_value; - break; - } - - case SE_MinDamageModifier: - { - if(base2 == -1) - newbon->MinDamageModifier[HIGHEST_SKILL+1] += effect_value; - else - newbon->MinDamageModifier[base2] += effect_value; - break; - } - - case SE_StunResist: - { - if(newbon->StunResist < effect_value) - newbon->StunResist = effect_value; - break; - } - - case SE_ProcChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->ProcChanceSPA += effect_value; - - else if((effect_value < 0) && (newbon->ProcChanceSPA > effect_value)) - newbon->ProcChanceSPA = effect_value; - - if(newbon->ProcChanceSPA < effect_value) - newbon->ProcChanceSPA = effect_value; - - break; - } - - case SE_ExtraAttackChance: - newbon->ExtraAttackChance += effect_value; - break; - - case SE_PercentXPIncrease: - { - if(newbon->XPRateMod < effect_value) - newbon->XPRateMod = effect_value; - break; - } - - case SE_DeathSave: - { - if(newbon->DeathSave[0] < effect_value) - { - newbon->DeathSave[0] = effect_value; //1='Partial' 2='Full' - newbon->DeathSave[1] = buffslot; - //These are used in later expansion spell effects. - newbon->DeathSave[2] = base2;//Min level for HealAmt - newbon->DeathSave[3] = max;//HealAmt - } - break; - } - - case SE_DivineSave: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) { - newbon->DivineSaveChance[0] += effect_value; - newbon->DivineSaveChance[1] = 0; - } - - else if(newbon->DivineSaveChance[0] < effect_value) - { - newbon->DivineSaveChance[0] = effect_value; - newbon->DivineSaveChance[1] = base2; - //SetDeathSaveChance(true); - } - break; - } - - case SE_Flurry: - newbon->FlurryChance += effect_value; - break; - - case SE_Accuracy: - { - if ((effect_value < 0) && (newbon->Accuracy[HIGHEST_SKILL+1] > effect_value)) - newbon->Accuracy[HIGHEST_SKILL+1] = effect_value; - - else if (!newbon->Accuracy[HIGHEST_SKILL+1] || - ((newbon->Accuracy[HIGHEST_SKILL+1] > 0) && (newbon->Accuracy[HIGHEST_SKILL+1] < effect_value))) - newbon->Accuracy[HIGHEST_SKILL+1] = effect_value; - break; - } - - case SE_MaxHPChange: - newbon->MaxHPChange += effect_value; - break; - - case SE_EndurancePool: - newbon->Endurance += effect_value; - break; - - case SE_HealRate: - newbon->HealRate += effect_value; - break; - - case SE_SkillDamageTaken: - { - //When using npc_spells_effects if MAX value set, use stackable quest based modifier. - if (IsAISpellEffect && max){ - if(base2 == -1) - SkillDmgTaken_Mod[HIGHEST_SKILL+1] = effect_value; - else - SkillDmgTaken_Mod[base2] = effect_value; - } - else { - - if(base2 == -1) - newbon->SkillDmgTaken[HIGHEST_SKILL+1] += effect_value; - else - newbon->SkillDmgTaken[base2] += effect_value; - - } - break; - } - - case SE_TriggerOnCast: - { - for(int e = 0; e < MAX_SPELL_TRIGGER; e++) - { - if(!newbon->SpellTriggers[e]) - { - newbon->SpellTriggers[e] = spell_id; - break; - } - } - break; - } - - case SE_SpellCritChance: - newbon->CriticalSpellChance += effect_value; - break; - - case SE_CriticalSpellChance: - { - newbon->CriticalSpellChance += effect_value; - - if (base2 > newbon->SpellCritDmgIncNoStack) - newbon->SpellCritDmgIncNoStack = base2; - break; - } - - case SE_SpellCritDmgIncrease: - newbon->SpellCritDmgIncrease += effect_value; - break; - - case SE_DotCritDmgIncrease: - newbon->DotCritDmgIncrease += effect_value; - break; - - case SE_CriticalHealChance: - newbon->CriticalHealChance += effect_value; - break; - - case SE_CriticalHealOverTime: - newbon->CriticalHealOverTime += effect_value; - break; - - case SE_CriticalHealDecay: - newbon->CriticalHealDecay = true; - break; - - case SE_CriticalRegenDecay: - newbon->CriticalRegenDecay = true; - break; - - case SE_CriticalDotDecay: - newbon->CriticalDotDecay = true; - break; - - case SE_MitigateDamageShield: - { - if (effect_value < 0) - effect_value = effect_value*-1; - - newbon->DSMitigationOffHand += effect_value; - break; - } - - case SE_CriticalDoTChance: - newbon->CriticalDoTChance += effect_value; - break; - - case SE_ProcOnKillShot: - { - for(int e = 0; e < MAX_SPELL_TRIGGER*3; e+=3) - { - if(!newbon->SpellOnKill[e]) - { - // Base2 = Spell to fire | Base1 = % chance | Base3 = min level - newbon->SpellOnKill[e] = base2; - newbon->SpellOnKill[e+1] = effect_value; - newbon->SpellOnKill[e+2] = max; - break; - } - } - break; - } - - case SE_SpellOnDeath: - { - for(int e = 0; e < MAX_SPELL_TRIGGER; e+=2) - { - if(!newbon->SpellOnDeath[e]) - { - // Base2 = Spell to fire | Base1 = % chance - newbon->SpellOnDeath[e] = base2; - newbon->SpellOnDeath[e+1] = effect_value; - break; - } - } - break; - } - - case SE_CriticalDamageMob: - { - if(base2 == -1) - newbon->CritDmgMob[HIGHEST_SKILL+1] += effect_value; - else - newbon->CritDmgMob[base2] += effect_value; - break; - } - - case SE_ReduceSkillTimer: - { - if(newbon->SkillReuseTime[base2] < effect_value) - newbon->SkillReuseTime[base2] = effect_value; - break; - } - - case SE_SkillDamageAmount: - { - if(base2 == -1) - newbon->SkillDamageAmount[HIGHEST_SKILL+1] += effect_value; - else - newbon->SkillDamageAmount[base2] += effect_value; - break; - } - - case SE_GravityEffect: - newbon->GravityEffect = 1; - break; - - case SE_AntiGate: - newbon->AntiGate = true; - break; - - case SE_MagicWeapon: - newbon->MagicWeapon = true; - break; - - case SE_IncreaseBlockChance: - newbon->IncreaseBlockChance += effect_value; - break; - - case SE_PersistantCasting: - newbon->PersistantCasting += effect_value; - break; - - case SE_LimitHPPercent: - { - if(newbon->HPPercCap[0] != 0 && newbon->HPPercCap[0] > effect_value){ - newbon->HPPercCap[0] = effect_value; - newbon->HPPercCap[1] = base2; - } - else if(newbon->HPPercCap[0] == 0){ - newbon->HPPercCap[0] = effect_value; - newbon->HPPercCap[1] = base2; - } - break; - } - case SE_LimitManaPercent: - { - if(newbon->ManaPercCap[0] != 0 && newbon->ManaPercCap[0] > effect_value){ - newbon->ManaPercCap[0] = effect_value; - newbon->ManaPercCap[1] = base2; - } - else if(newbon->ManaPercCap[0] == 0) { - newbon->ManaPercCap[0] = effect_value; - newbon->ManaPercCap[1] = base2; - } - - break; - } - case SE_LimitEndPercent: - { - if(newbon->EndPercCap[0] != 0 && newbon->EndPercCap[0] > effect_value) { - newbon->EndPercCap[0] = effect_value; - newbon->EndPercCap[1] = base2; - } - - else if(newbon->EndPercCap[0] == 0){ - newbon->EndPercCap[0] = effect_value; - newbon->EndPercCap[1] = base2; - } - - break; - } - - case SE_BlockNextSpellFocus: - newbon->BlockNextSpell = true; - break; - - case SE_NegateSpellEffect: - newbon->NegateEffects = true; - break; - - case SE_ImmuneFleeing: - newbon->ImmuneToFlee = true; - break; - - case SE_DelayDeath: - newbon->DelayDeath += effect_value; - break; - - case SE_SpellProcChance: - newbon->SpellProcChance += effect_value; - break; - - case SE_CharmBreakChance: - newbon->CharmBreakChance += effect_value; - break; - - case SE_BardSongRange: - newbon->SongRange += effect_value; - break; - - case SE_HPToMana: - { - //Lower the ratio the more favorable - if((!newbon->HPToManaConvert) || (newbon->HPToManaConvert >= effect_value)) - newbon->HPToManaConvert = spells[spell_id].base[i]; - break; - } - - case SE_SkillDamageAmount2: - { - if(base2 == -1) - newbon->SkillDamageAmount2[HIGHEST_SKILL+1] += effect_value; - else - newbon->SkillDamageAmount2[base2] += effect_value; - break; - } - - case SE_NegateAttacks: - { - if (!newbon->NegateAttacks[0] || - ((newbon->NegateAttacks[0] && newbon->NegateAttacks[2]) && (newbon->NegateAttacks[2] < max))){ - newbon->NegateAttacks[0] = 1; - newbon->NegateAttacks[1] = buffslot; - newbon->NegateAttacks[2] = max; - } - break; - } - - case SE_MitigateMeleeDamage: - { - if (newbon->MitigateMeleeRune[0] < effect_value){ - newbon->MitigateMeleeRune[0] = effect_value; - newbon->MitigateMeleeRune[1] = buffslot; - newbon->MitigateMeleeRune[2] = base2; - newbon->MitigateMeleeRune[3] = max; - } - break; - } - - - case SE_MeleeThresholdGuard: - { - if (newbon->MeleeThresholdGuard[0] < effect_value){ - newbon->MeleeThresholdGuard[0] = effect_value; - newbon->MeleeThresholdGuard[1] = buffslot; - newbon->MeleeThresholdGuard[2] = base2; - } - break; - } - - case SE_SpellThresholdGuard: - { - if (newbon->SpellThresholdGuard[0] < effect_value){ - newbon->SpellThresholdGuard[0] = effect_value; - newbon->SpellThresholdGuard[1] = buffslot; - newbon->SpellThresholdGuard[2] = base2; - } - break; - } - - case SE_MitigateSpellDamage: - { - if (newbon->MitigateSpellRune[0] < effect_value){ - newbon->MitigateSpellRune[0] = effect_value; - newbon->MitigateSpellRune[1] = buffslot; - newbon->MitigateSpellRune[2] = base2; - newbon->MitigateSpellRune[3] = max; - } - break; - } - - case SE_MitigateDotDamage: - { - if (newbon->MitigateDotRune[0] < effect_value){ - newbon->MitigateDotRune[0] = effect_value; - newbon->MitigateDotRune[1] = buffslot; - newbon->MitigateDotRune[2] = base2; - newbon->MitigateDotRune[3] = max; - } - break; - } - - case SE_ManaAbsorbPercentDamage: - { - if (newbon->ManaAbsorbPercentDamage[0] < effect_value){ - newbon->ManaAbsorbPercentDamage[0] = effect_value; - newbon->ManaAbsorbPercentDamage[1] = buffslot; - } - break; - } - - case SE_TriggerMeleeThreshold: - { - if (newbon->TriggerMeleeThreshold[2] < base2){ - newbon->TriggerMeleeThreshold[0] = effect_value; - newbon->TriggerMeleeThreshold[1] = buffslot; - newbon->TriggerMeleeThreshold[2] = base2; - } - break; - } - - case SE_TriggerSpellThreshold: - { - if (newbon->TriggerSpellThreshold[2] < base2){ - newbon->TriggerSpellThreshold[0] = effect_value; - newbon->TriggerSpellThreshold[1] = buffslot; - newbon->TriggerSpellThreshold[2] = base2; - } - break; - } - - case SE_ShieldBlock: - newbon->ShieldBlock += effect_value; - break; - - case SE_ShieldEquipHateMod: - newbon->ShieldEquipHateMod += effect_value; - break; - - case SE_ShieldEquipDmgMod: - newbon->ShieldEquipDmgMod[0] += effect_value; - newbon->ShieldEquipDmgMod[1] += base2; - break; - - case SE_BlockBehind: - newbon->BlockBehind += effect_value; - break; - - case SE_Fear: - newbon->IsFeared = true; - break; - - //AA bonuses - implemented broadly into spell/item effects - case SE_FrontalStunResist: - newbon->FrontalStunResist += effect_value; - break; - - case SE_ImprovedBindWound: - newbon->BindWound += effect_value; - break; - - case SE_MaxBindWound: - newbon->MaxBindWound += effect_value; - break; - - case SE_BaseMovementSpeed: - newbon->BaseMovementSpeed += effect_value; - break; - - case SE_IncreaseRunSpeedCap: - newbon->IncreaseRunSpeedCap += effect_value; - break; - - case SE_DoubleSpecialAttack: - newbon->DoubleSpecialAttack += effect_value; - break; - - case SE_TripleBackstab: - newbon->TripleBackstab += effect_value; - break; - - case SE_FrontalBackstabMinDmg: - newbon->FrontalBackstabMinDmg = true; - break; - - case SE_FrontalBackstabChance: - newbon->FrontalBackstabChance += effect_value; - break; - - case SE_ConsumeProjectile: - newbon->ConsumeProjectile += effect_value; - break; - - case SE_ForageAdditionalItems: - newbon->ForageAdditionalItems += effect_value; - break; - - case SE_Salvage: - newbon->SalvageChance += effect_value; - break; - - case SE_ArcheryDamageModifier: - newbon->ArcheryDamageModifier += effect_value; - break; - - case SE_DoubleRangedAttack: - newbon->DoubleRangedAttack += effect_value; - break; - - case SE_SecondaryDmgInc: - newbon->SecondaryDmgInc = true; - break; - - case SE_StrikeThrough: - case SE_StrikeThrough2: - newbon->StrikeThrough += effect_value; - break; - - case SE_GiveDoubleAttack: - newbon->GiveDoubleAttack += effect_value; - break; - - case SE_PetCriticalHit: - newbon->PetCriticalHit += effect_value; - break; - - case SE_CombatStability: - newbon->CombatStability += effect_value; - break; - - case SE_AddSingingMod: - switch (base2) - { - case ItemTypeWindInstrument: - newbon->windMod += effect_value; - break; - case ItemTypeStringedInstrument: - newbon->stringedMod += effect_value; - break; - case ItemTypeBrassInstrument: - newbon->brassMod += effect_value; - break; - case ItemTypePercussionInstrument: - newbon->percussionMod += effect_value; - break; - case ItemTypeSinging: - newbon->singingMod += effect_value; - break; - } - break; - - case SE_SongModCap: - newbon->songModCap += effect_value; - break; - - case SE_PetAvoidance: - newbon->PetAvoidance += effect_value; - break; - - case SE_Ambidexterity: - newbon->Ambidexterity += effect_value; - break; - - case SE_PetMaxHP: - newbon->PetMaxHP += effect_value; - break; - - case SE_PetFlurry: - newbon->PetFlurry += effect_value; - break; - - case SE_GivePetGroupTarget: - newbon->GivePetGroupTarget = true; - break; - - case SE_RootBreakChance: - newbon->RootBreakChance += effect_value; - break; - - case SE_ChannelChanceItems: - newbon->ChannelChanceItems += effect_value; - break; - - case SE_ChannelChanceSpells: - newbon->ChannelChanceSpells += effect_value; - break; - - case SE_UnfailingDivinity: - newbon->UnfailingDivinity += effect_value; - break; - - - case SE_ItemHPRegenCapIncrease: - newbon->ItemHPRegenCap += effect_value; - break; - - case SE_OffhandRiposteFail: - newbon->OffhandRiposteFail += effect_value; - break; - - case SE_ItemAttackCapIncrease: - newbon->ItemATKCap += effect_value; - break; - - case SE_TwoHandBluntBlock: - newbon->TwoHandBluntBlock += effect_value; - break; - - case SE_StunBashChance: - newbon->StunBashChance += effect_value; - break; - - case SE_IncreaseChanceMemwipe: - newbon->IncreaseChanceMemwipe += effect_value; - break; - - case SE_CriticalMend: - newbon->CriticalMend += effect_value; - break; - - case SE_SpellEffectResistChance: - { - for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) - { - if(newbon->SEResist[e+1] && (newbon->SEResist[e] == base2) && (newbon->SEResist[e+1] < effect_value)){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = effect_value; //Resist Chance - break; - } - else if (!newbon->SEResist[e+1]){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = effect_value; //Resist Chance - break; - } - } - break; - } - - case SE_MasteryofPast: - { - if(newbon->MasteryofPast < effect_value) - newbon->MasteryofPast = effect_value; - break; - } - - case SE_DoubleRiposte: - { - newbon->DoubleRiposte += effect_value; - } - - case SE_GiveDoubleRiposte: - { - //Only allow for regular double riposte chance. - if(newbon->GiveDoubleRiposte[base2] == 0){ - if(newbon->GiveDoubleRiposte[0] < effect_value) - newbon->GiveDoubleRiposte[0] = effect_value; - } - break; - } - - case SE_SlayUndead: - { - if(newbon->SlayUndead[1] < effect_value) - newbon->SlayUndead[0] = effect_value; // Rate - newbon->SlayUndead[1] = base2; // Damage Modifier - break; - } - - case SE_TriggerOnReqTarget: - case SE_TriggerOnReqCaster: - newbon->TriggerOnValueAmount = true; - break; - - case SE_DivineAura: - newbon->DivineAura = true; - break; - - case SE_ImprovedTaunt: - if (newbon->ImprovedTaunt[0] < effect_value) { - newbon->ImprovedTaunt[0] = effect_value; - newbon->ImprovedTaunt[1] = base2; - newbon->ImprovedTaunt[2] = buffslot; - } - break; - - - case SE_DistanceRemoval: - newbon->DistanceRemoval = true; - break; - - case SE_FrenziedDevastation: - newbon->FrenziedDevastation += base2; - break; - - case SE_Root: - if (newbon->Root[0] && (newbon->Root[1] > buffslot)){ - newbon->Root[0] = 1; - newbon->Root[1] = buffslot; - } - else if (!newbon->Root[0]){ - newbon->Root[0] = 1; - newbon->Root[1] = buffslot; - } - break; - - case SE_Rune: - - if (newbon->MeleeRune[0] && (newbon->MeleeRune[1] > buffslot)){ - - newbon->MeleeRune[0] = effect_value; - newbon->MeleeRune[1] = buffslot; - } - else if (!newbon->MeleeRune[0]){ - newbon->MeleeRune[0] = effect_value; - newbon->MeleeRune[1] = buffslot; - } - - break; - - case SE_AbsorbMagicAtt: - if (newbon->AbsorbMagicAtt[0] && (newbon->AbsorbMagicAtt[1] > buffslot)){ - newbon->AbsorbMagicAtt[0] = effect_value; - newbon->AbsorbMagicAtt[1] = buffslot; - } - else if (!newbon->AbsorbMagicAtt[0]){ - newbon->AbsorbMagicAtt[0] = effect_value; - newbon->AbsorbMagicAtt[1] = buffslot; - } - break; - - case SE_NegateIfCombat: - newbon->NegateIfCombat = true; - break; - - case SE_Screech: - newbon->Screech = effect_value; - break; - - case SE_AlterNPCLevel: - - if (IsNPC()){ - if (!newbon->AlterNPCLevel - || ((effect_value < 0) && (newbon->AlterNPCLevel > effect_value)) - || ((effect_value > 0) && (newbon->AlterNPCLevel < effect_value))) { - - int16 tmp_lv = GetOrigLevel() + effect_value; - if (tmp_lv < 1) - tmp_lv = 1; - else if (tmp_lv > 255) - tmp_lv = 255; - if ((GetLevel() != tmp_lv)){ - newbon->AlterNPCLevel = effect_value; - SetLevel(tmp_lv); - } - } - } - break; - - case SE_AStacker: - newbon->AStacker[0] = 1; - newbon->AStacker[1] = effect_value; - break; - - case SE_BStacker: - newbon->BStacker[0] = 1; - newbon->BStacker[1] = effect_value; - break; - - case SE_CStacker: - newbon->CStacker[0] = 1; - newbon->CStacker[1] = effect_value; - break; - - case SE_DStacker: - newbon->DStacker[0] = 1; - newbon->DStacker[1] = effect_value; - break; - - case SE_Berserk: - newbon->BerserkSPA = true; - break; - - - case SE_Metabolism: - newbon->Metabolism += effect_value; - break; - - case SE_ImprovedReclaimEnergy: - { - if((effect_value < 0) && (newbon->ImprovedReclaimEnergy > effect_value)) - newbon->ImprovedReclaimEnergy = effect_value; - - else if(newbon->ImprovedReclaimEnergy < effect_value) - newbon->ImprovedReclaimEnergy = effect_value; - break; - } - - case SE_HeadShot: - { - if(newbon->HeadShot[1] < base2){ - newbon->HeadShot[0] = effect_value; - newbon->HeadShot[1] = base2; - } - break; - } - - case SE_HeadShotLevel: - { - if(newbon->HSLevel < effect_value) - newbon->HSLevel = effect_value; - break; - } - - case SE_Assassinate: - { - if(newbon->Assassinate[1] < base2){ - newbon->Assassinate[0] = effect_value; - newbon->Assassinate[1] = base2; - } - break; - } - - case SE_AssassinateLevel: - { - if(newbon->AssassinateLevel < effect_value) - newbon->AssassinateLevel = effect_value; - break; - } - - case SE_FinishingBlow: - { - //base1 = chance, base2 = damage - if (newbon->FinishingBlow[1] < base2){ - newbon->FinishingBlow[0] = effect_value; - newbon->FinishingBlow[1] = base2; - } - break; - } - - case SE_FinishingBlowLvl: - { - //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) - if (newbon->FinishingBlowLvl[0] < effect_value){ - newbon->FinishingBlowLvl[0] = effect_value; - newbon->FinishingBlowLvl[1] = base2; - } - break; - } - - case SE_PetMeleeMitigation: - newbon->PetMeleeMitigation += effect_value; - break; - - //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table - if (IsAISpellEffect) { - - //Non-Focused Effect to modify incomming spell damage by resist type. - case SE_FcSpellVulnerability: - ModVulnerability(base2, effect_value); - break; - } - } - } -} - -void NPC::CalcItemBonuses(StatBonuses *newbon) -{ - if(newbon){ - - for(int i = 0; i < MAX_WORN_INVENTORY; i++){ - const Item_Struct *cur = database.GetItem(equipment[i]); - if(cur){ - //basic stats - newbon->AC += cur->AC; - newbon->HP += cur->HP; - newbon->Mana += cur->Mana; - newbon->Endurance += cur->Endur; - newbon->STR += (cur->AStr + cur->HeroicStr); - newbon->STA += (cur->ASta + cur->HeroicSta); - newbon->DEX += (cur->ADex + cur->HeroicDex); - newbon->AGI += (cur->AAgi + cur->HeroicAgi); - newbon->INT += (cur->AInt + cur->HeroicInt); - newbon->WIS += (cur->AWis + cur->HeroicWis); - newbon->CHA += (cur->ACha + cur->HeroicCha); - newbon->MR += (cur->MR + cur->HeroicMR); - newbon->FR += (cur->FR + cur->HeroicFR); - newbon->CR += (cur->CR + cur->HeroicCR); - newbon->PR += (cur->PR + cur->HeroicPR); - newbon->DR += (cur->DR + cur->HeroicDR); - newbon->Corrup += (cur->SVCorruption + cur->HeroicSVCorrup); - - //more complex stats - if(cur->Regen > 0) { - newbon->HPRegen += cur->Regen; - } - if(cur->ManaRegen > 0) { - newbon->ManaRegen += cur->ManaRegen; - } - if(cur->Attack > 0) { - newbon->ATK += cur->Attack; - } - if(cur->DamageShield > 0) { - newbon->DamageShield += cur->DamageShield; - } - if(cur->SpellShield > 0) { - newbon->SpellDamageShield += cur->SpellShield; - } - if(cur->Shielding > 0) { - newbon->MeleeMitigation += cur->Shielding; - } - if(cur->StunResist > 0) { - newbon->StunResist += cur->StunResist; - } - if(cur->StrikeThrough > 0) { - newbon->StrikeThrough += cur->StrikeThrough; - } - if(cur->Avoidance > 0) { - newbon->AvoidMeleeChance += cur->Avoidance; - } - if(cur->Accuracy > 0) { - newbon->HitChance += cur->Accuracy; - } - if(cur->CombatEffects > 0) { - newbon->ProcChance += cur->CombatEffects; - } - if (cur->Worn.Effect>0 && (cur->Worn.Type == ET_WornEffect)) { // latent effects - ApplySpellsBonuses(cur->Worn.Effect, cur->Worn.Level, newbon); - } - if (cur->Haste > newbon->haste) - newbon->haste = cur->Haste; - } - } - - } -} - -void Client::CalcItemScale() -{ - bool changed = false; - - if(CalcItemScale(0, 21)) - changed = true; - - if(CalcItemScale(22, 30)) - changed = true; - - if(CalcItemScale(251, 341)) - changed = true; - - if(CalcItemScale(400, 405)) - changed = true; - - //Power Source Slot - if (GetClientVersion() >= EQClientSoF) - { - if(CalcItemScale(9999, 10000)) - changed = true; - } - - if(changed) - { - CalcBonuses(); - } -} - -bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) -{ - bool changed = false; - int i; - for (i = slot_x; i < slot_y; i++) { - ItemInst* inst = m_inv.GetItem(i); - if(inst == 0) - continue; - - bool update_slot = false; - if(inst->IsScaling()) - { - uint16 oldexp = inst->GetExp(); - parse->EventItem(EVENT_SCALE_CALC, this, inst, nullptr, "", 0); - - if (inst->GetExp() != oldexp) { // if the scaling factor changed, rescale the item and update the client - inst->ScaleItem(); - changed = true; - update_slot = true; - } - } - - //iterate all augments - for(int x = 0; x < MAX_AUGMENT_SLOTS; ++x) - { - ItemInst * a_inst = inst->GetAugment(x); - if(!a_inst) - continue; - - if(a_inst->IsScaling()) - { - uint16 oldexp = a_inst->GetExp(); - parse->EventItem(EVENT_SCALE_CALC, this, a_inst, nullptr, "", 0); - - if (a_inst->GetExp() != oldexp) - { - a_inst->ScaleItem(); - changed = true; - update_slot = true; - } - } - } - - if(update_slot) - { - SendItemPacket(i, inst, ItemPacketCharmUpdate); - } - } - return changed; -} - -void Client::DoItemEnterZone() { - bool changed = false; - - if(DoItemEnterZone(0, 21)) - changed = true; - - if(DoItemEnterZone(22, 30)) - changed = true; - - if(DoItemEnterZone(251, 341)) - changed = true; - - if(DoItemEnterZone(400, 405)) - changed = true; - - //Power Source Slot - if (GetClientVersion() >= EQClientSoF) - { - if(DoItemEnterZone(9999, 10000)) - changed = true; - } - - if(changed) - { - CalcBonuses(); - } -} - -bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { - bool changed = false; - for(int i = slot_x; i < slot_y; i++) { - ItemInst* inst = m_inv.GetItem(i); - if(!inst) - continue; - - bool update_slot = false; - if(inst->IsScaling()) - { - uint16 oldexp = inst->GetExp(); - - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); - if(i < 22 || i == 9999) { - parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); - } - - if (inst->GetExp() != oldexp) { // if the scaling factor changed, rescale the item and update the client - inst->ScaleItem(); - changed = true; - update_slot = true; - } - } else { - if(i < 22 || i == 9999) { - parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); - } - - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); - } - - //iterate all augments - for(int x = 0; x < MAX_AUGMENT_SLOTS; ++x) - { - ItemInst *a_inst = inst->GetAugment(x); - if(!a_inst) - continue; - - if(a_inst->IsScaling()) - { - uint16 oldexp = a_inst->GetExp(); - - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, a_inst, nullptr, "", 0); - - if (a_inst->GetExp() != oldexp) - { - a_inst->ScaleItem(); - changed = true; - update_slot = true; - } - } else { - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, a_inst, nullptr, "", 0); - } - } - - if(update_slot) - { - SendItemPacket(i, inst, ItemPacketCharmUpdate); - } - } - return changed; -} - -uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_effect) -{ - uint16 effect = 0; - - if (!AA) - effect = spells[spell_id].effectid[effect_index]; - else - effect = aa_effect; - - switch (effect) - { - case SE_ImprovedDamage: - return focusImprovedDamage; - case SE_ImprovedHeal: - return focusImprovedHeal; - case SE_ReduceManaCost: - return focusManaCost; - case SE_IncreaseSpellHaste: - return focusSpellHaste; - case SE_IncreaseSpellDuration: - return focusSpellDuration; - case SE_SpellDurationIncByTic: - return focusSpellDurByTic; - case SE_SwarmPetDuration: - return focusSwarmPetDuration; - case SE_IncreaseRange: - return focusRange; - case SE_ReduceReagentCost: - return focusReagentCost; - case SE_PetPowerIncrease: - return focusPetPower; - case SE_SpellResistReduction: - return focusResistRate; - case SE_SpellHateMod: - return focusSpellHateMod; - case SE_ReduceReuseTimer: - return focusReduceRecastTime; - case SE_TriggerOnCast: - //return focusTriggerOnCast; - return 0; //This is calculated as an actual bonus - case SE_FcSpellVulnerability: - return focusSpellVulnerability; - case SE_BlockNextSpellFocus: - //return focusBlockNextSpell; - return 0; //This is calculated as an actual bonus - case SE_FcTwincast: - return focusTwincast; - case SE_SympatheticProc: - return focusSympatheticProc; - case SE_FcDamageAmt: - return focusFcDamageAmt; - case SE_FcDamageAmtCrit: - return focusFcDamageAmtCrit; - case SE_FcDamagePctCrit: - return focusFcDamagePctCrit; - case SE_FcDamageAmtIncoming: - return focusFcDamageAmtIncoming; - case SE_FcHealAmtIncoming: - return focusFcHealAmtIncoming; - case SE_FcHealPctIncoming: - return focusFcHealPctIncoming; - case SE_FcBaseEffects: - return focusFcBaseEffects; - case SE_FcIncreaseNumHits: - return focusIncreaseNumHits; - case SE_FcLimitUse: - return focusFcLimitUse; - case SE_FcMute: - return focusFcMute; - case SE_FcTimerRefresh: - return focusFcTimerRefresh; - case SE_FcStunTimeMod: - return focusFcStunTimeMod; - case SE_FcHealPctCritIncoming: - return focusFcHealPctCritIncoming; - case SE_FcHealAmt: - return focusFcHealAmt; - case SE_FcHealAmtCrit: - return focusFcHealAmtCrit; - } - return 0; -} - -void Mob::NegateSpellsBonuses(uint16 spell_id) -{ - if(!IsValidSpell(spell_id)) - return; - - int effect_value = 0; - - for (int i = 0; i < EFFECT_COUNT; i++) - { - if (spells[spell_id].effectid[i] == SE_NegateSpellEffect){ - - //Negate focus effects - for(int e = 0; e < HIGHEST_FOCUS+1; e++) - { - if (spellbonuses.FocusEffects[e] == spells[spell_id].base2[i]) - { - spellbonuses.FocusEffects[e] = effect_value; - continue; - } - } - - //Negate bonuses - switch (spells[spell_id].base2[i]) - { - case SE_CurrentHP: - if(spells[spell_id].base[i] == 1) { - spellbonuses.HPRegen = effect_value; - aabonuses.HPRegen = effect_value; - itembonuses.HPRegen = effect_value; - } - break; - - case SE_CurrentEndurance: - spellbonuses.EnduranceRegen = effect_value; - aabonuses.EnduranceRegen = effect_value; - itembonuses.EnduranceRegen = effect_value; - break; - - case SE_ChangeFrenzyRad: - spellbonuses.AggroRange = effect_value; - aabonuses.AggroRange = effect_value; - itembonuses.AggroRange = effect_value; - break; - - case SE_Harmony: - spellbonuses.AssistRange = effect_value; - aabonuses.AssistRange = effect_value; - itembonuses.AssistRange = effect_value; - break; - - case SE_AttackSpeed: - spellbonuses.haste = effect_value; - aabonuses.haste = effect_value; - itembonuses.haste = effect_value; - break; - - case SE_AttackSpeed2: - spellbonuses.hastetype2 = effect_value; - aabonuses.hastetype2 = effect_value; - itembonuses.hastetype2 = effect_value; - break; - - case SE_AttackSpeed3: - { - if (effect_value > 0) { - spellbonuses.hastetype3 = effect_value; - aabonuses.hastetype3 = effect_value; - itembonuses.hastetype3 = effect_value; - - } - break; - } - - case SE_AttackSpeed4: - spellbonuses.inhibitmelee = effect_value; - aabonuses.inhibitmelee = effect_value; - itembonuses.inhibitmelee = effect_value; - break; - - case SE_TotalHP: - spellbonuses.HP = effect_value; - aabonuses.HP = effect_value; - itembonuses.HP = effect_value; - break; - - case SE_ManaRegen_v2: - case SE_CurrentMana: - spellbonuses.ManaRegen = effect_value; - aabonuses.ManaRegen = effect_value; - itembonuses.ManaRegen = effect_value; - break; - - case SE_ManaPool: - spellbonuses.Mana = effect_value; - itembonuses.Mana = effect_value; - aabonuses.Mana = effect_value; - break; - - case SE_Stamina: - spellbonuses.EnduranceReduction = effect_value; - itembonuses.EnduranceReduction = effect_value; - aabonuses.EnduranceReduction = effect_value; - break; - - case SE_ACv2: - case SE_ArmorClass: - spellbonuses.AC = effect_value; - aabonuses.AC = effect_value; - itembonuses.AC = effect_value; - break; - - case SE_ATK: - spellbonuses.ATK = effect_value; - aabonuses.ATK = effect_value; - itembonuses.ATK = effect_value; - break; - - case SE_STR: - spellbonuses.STR = effect_value; - itembonuses.STR = effect_value; - aabonuses.STR = effect_value; - break; - - case SE_DEX: - spellbonuses.DEX = effect_value; - aabonuses.DEX = effect_value; - itembonuses.DEX = effect_value; - break; - - case SE_AGI: - itembonuses.AGI = effect_value; - aabonuses.AGI = effect_value; - spellbonuses.AGI = effect_value; - break; - - case SE_STA: - spellbonuses.STA = effect_value; - itembonuses.STA = effect_value; - aabonuses.STA = effect_value; - break; - - case SE_INT: - spellbonuses.INT = effect_value; - aabonuses.INT = effect_value; - itembonuses.INT = effect_value; - break; - - case SE_WIS: - spellbonuses.WIS = effect_value; - aabonuses.WIS = effect_value; - itembonuses.WIS = effect_value; - break; - - case SE_CHA: - itembonuses.CHA = effect_value; - spellbonuses.CHA = effect_value; - aabonuses.CHA = effect_value; - break; - - case SE_AllStats: - { - spellbonuses.STR = effect_value; - spellbonuses.DEX = effect_value; - spellbonuses.AGI = effect_value; - spellbonuses.STA = effect_value; - spellbonuses.INT = effect_value; - spellbonuses.WIS = effect_value; - spellbonuses.CHA = effect_value; - - itembonuses.STR = effect_value; - itembonuses.DEX = effect_value; - itembonuses.AGI = effect_value; - itembonuses.STA = effect_value; - itembonuses.INT = effect_value; - itembonuses.WIS = effect_value; - itembonuses.CHA = effect_value; - - aabonuses.STR = effect_value; - aabonuses.DEX = effect_value; - aabonuses.AGI = effect_value; - aabonuses.STA = effect_value; - aabonuses.INT = effect_value; - aabonuses.WIS = effect_value; - aabonuses.CHA = effect_value; - break; - } - - case SE_ResistFire: - spellbonuses.FR = effect_value; - itembonuses.FR = effect_value; - aabonuses.FR = effect_value; - break; - - case SE_ResistCold: - spellbonuses.CR = effect_value; - aabonuses.CR = effect_value; - itembonuses.CR = effect_value; - break; - - case SE_ResistPoison: - spellbonuses.PR = effect_value; - aabonuses.PR = effect_value; - itembonuses.PR = effect_value; - break; - - case SE_ResistDisease: - spellbonuses.DR = effect_value; - itembonuses.DR = effect_value; - aabonuses.DR = effect_value; - break; - - case SE_ResistMagic: - spellbonuses.MR = effect_value; - aabonuses.MR = effect_value; - itembonuses.MR = effect_value; - break; - - case SE_ResistAll: - { - spellbonuses.MR = effect_value; - spellbonuses.DR = effect_value; - spellbonuses.PR = effect_value; - spellbonuses.CR = effect_value; - spellbonuses.FR = effect_value; - - aabonuses.MR = effect_value; - aabonuses.DR = effect_value; - aabonuses.PR = effect_value; - aabonuses.CR = effect_value; - aabonuses.FR = effect_value; - - itembonuses.MR = effect_value; - itembonuses.DR = effect_value; - itembonuses.PR = effect_value; - itembonuses.CR = effect_value; - itembonuses.FR = effect_value; - break; - } - - case SE_ResistCorruption: - spellbonuses.Corrup = effect_value; - itembonuses.Corrup = effect_value; - aabonuses.Corrup = effect_value; - break; - - case SE_CastingLevel2: - case SE_CastingLevel: // Brilliance of Ro - spellbonuses.effective_casting_level = effect_value; - aabonuses.effective_casting_level = effect_value; - itembonuses.effective_casting_level = effect_value; - break; - - - case SE_MovementSpeed: - spellbonuses.movementspeed = effect_value; - aabonuses.movementspeed = effect_value; - itembonuses.movementspeed = effect_value; - break; - - case SE_SpellDamageShield: - spellbonuses.SpellDamageShield = effect_value; - aabonuses.SpellDamageShield = effect_value; - itembonuses.SpellDamageShield = effect_value; - break; - - case SE_DamageShield: - spellbonuses.DamageShield = effect_value; - aabonuses.DamageShield = effect_value; - itembonuses.DamageShield = effect_value; - break; - - case SE_ReverseDS: - spellbonuses.ReverseDamageShield = effect_value; - aabonuses.ReverseDamageShield = effect_value; - itembonuses.ReverseDamageShield = effect_value; - break; - - case SE_Reflect: - spellbonuses.reflect_chance = effect_value; - aabonuses.reflect_chance = effect_value; - itembonuses.reflect_chance = effect_value; - break; - - case SE_Amplification: - spellbonuses.Amplification = effect_value; - itembonuses.Amplification = effect_value; - aabonuses.Amplification = effect_value; - break; - - case SE_ChangeAggro: - spellbonuses.hatemod = effect_value; - itembonuses.hatemod = effect_value; - aabonuses.hatemod = effect_value; - break; - - case SE_MeleeMitigation: - spellbonuses.MeleeMitigation = effect_value; - itembonuses.MeleeMitigation = effect_value; - aabonuses.MeleeMitigation = effect_value; - break; - - case SE_CriticalHitChance: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.CriticalHitChance[e] = effect_value; - aabonuses.CriticalHitChance[e] = effect_value; - itembonuses.CriticalHitChance[e] = effect_value; - } - } - - case SE_CrippBlowChance: - spellbonuses.CrippBlowChance = effect_value; - aabonuses.CrippBlowChance = effect_value; - itembonuses.CrippBlowChance = effect_value; - break; - - case SE_AvoidMeleeChance: - spellbonuses.AvoidMeleeChance = effect_value; - aabonuses.AvoidMeleeChance = effect_value; - itembonuses.AvoidMeleeChance = effect_value; - break; - - case SE_RiposteChance: - spellbonuses.RiposteChance = effect_value; - aabonuses.RiposteChance = effect_value; - itembonuses.RiposteChance = effect_value; - break; - - case SE_DodgeChance: - spellbonuses.DodgeChance = effect_value; - aabonuses.DodgeChance = effect_value; - itembonuses.DodgeChance = effect_value; - break; - - case SE_ParryChance: - spellbonuses.ParryChance = effect_value; - aabonuses.ParryChance = effect_value; - itembonuses.ParryChance = effect_value; - break; - - case SE_DualWieldChance: - spellbonuses.DualWieldChance = effect_value; - aabonuses.DualWieldChance = effect_value; - itembonuses.DualWieldChance = effect_value; - break; - - case SE_DoubleAttackChance: - spellbonuses.DoubleAttackChance = effect_value; - aabonuses.DoubleAttackChance = effect_value; - itembonuses.DoubleAttackChance = effect_value; - break; - - case SE_TripleAttackChance: - spellbonuses.TripleAttackChance = effect_value; - aabonuses.TripleAttackChance = effect_value; - itembonuses.TripleAttackChance = effect_value; - break; - - case SE_MeleeLifetap: - spellbonuses.MeleeLifetap = effect_value; - aabonuses.MeleeLifetap = effect_value; - itembonuses.MeleeLifetap = effect_value; - break; - - case SE_AllInstrumentMod: - { - spellbonuses.singingMod = effect_value; - spellbonuses.brassMod = effect_value; - spellbonuses.percussionMod = effect_value; - spellbonuses.windMod = effect_value; - spellbonuses.stringedMod = effect_value; - - itembonuses.singingMod = effect_value; - itembonuses.brassMod = effect_value; - itembonuses.percussionMod = effect_value; - itembonuses.windMod = effect_value; - itembonuses.stringedMod = effect_value; - - aabonuses.singingMod = effect_value; - aabonuses.brassMod = effect_value; - aabonuses.percussionMod = effect_value; - aabonuses.windMod = effect_value; - aabonuses.stringedMod = effect_value; - break; - } - - case SE_ResistSpellChance: - spellbonuses.ResistSpellChance = effect_value; - aabonuses.ResistSpellChance = effect_value; - itembonuses.ResistSpellChance = effect_value; - break; - - case SE_ResistFearChance: - spellbonuses.Fearless = false; - spellbonuses.ResistFearChance = effect_value; - aabonuses.ResistFearChance = effect_value; - itembonuses.ResistFearChance = effect_value; - break; - - case SE_Fearless: - spellbonuses.Fearless = false; - aabonuses.Fearless = false; - itembonuses.Fearless = false; - break; - - case SE_HundredHands: - spellbonuses.HundredHands = effect_value; - aabonuses.HundredHands = effect_value; - itembonuses.HundredHands = effect_value; - break; - - case SE_MeleeSkillCheck: - { - spellbonuses.MeleeSkillCheck = effect_value; - spellbonuses.MeleeSkillCheckSkill = effect_value; - break; - } - - case SE_HitChance: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.HitChanceEffect[e] = effect_value; - aabonuses.HitChanceEffect[e] = effect_value; - itembonuses.HitChanceEffect[e] = effect_value; - } - break; - } - - case SE_DamageModifier: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.DamageModifier[e] = effect_value; - aabonuses.DamageModifier[e] = effect_value; - itembonuses.DamageModifier[e] = effect_value; - } - break; - } - - case SE_DamageModifier2: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.DamageModifier2[e] = effect_value; - aabonuses.DamageModifier2[e] = effect_value; - itembonuses.DamageModifier2[e] = effect_value; - } - break; - } - - case SE_MinDamageModifier: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.MinDamageModifier[e] = effect_value; - aabonuses.MinDamageModifier[e] = effect_value; - itembonuses.MinDamageModifier[e] = effect_value; - } - break; - } - - case SE_StunResist: - spellbonuses.StunResist = effect_value; - aabonuses.StunResist = effect_value; - itembonuses.StunResist = effect_value; - break; - - case SE_ProcChance: - spellbonuses.ProcChanceSPA = effect_value; - aabonuses.ProcChanceSPA = effect_value; - itembonuses.ProcChanceSPA = effect_value; - break; - - case SE_ExtraAttackChance: - spellbonuses.ExtraAttackChance = effect_value; - aabonuses.ExtraAttackChance = effect_value; - itembonuses.ExtraAttackChance = effect_value; - break; - - case SE_PercentXPIncrease: - spellbonuses.XPRateMod = effect_value; - aabonuses.XPRateMod = effect_value; - itembonuses.XPRateMod = effect_value; - break; - - case SE_Flurry: - spellbonuses.FlurryChance = effect_value; - aabonuses.FlurryChance = effect_value; - itembonuses.FlurryChance = effect_value; - break; - - case SE_Accuracy: - { - spellbonuses.Accuracy[HIGHEST_SKILL+1] = effect_value; - itembonuses.Accuracy[HIGHEST_SKILL+1] = effect_value; - - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - aabonuses.Accuracy[e] = effect_value; - } - break; - } - - case SE_MaxHPChange: - spellbonuses.MaxHPChange = effect_value; - aabonuses.MaxHPChange = effect_value; - itembonuses.MaxHPChange = effect_value; - break; - - case SE_EndurancePool: - spellbonuses.Endurance = effect_value; - aabonuses.Endurance = effect_value; - itembonuses.Endurance = effect_value; - break; - - case SE_HealRate: - spellbonuses.HealRate = effect_value; - aabonuses.HealRate = effect_value; - itembonuses.HealRate = effect_value; - break; - - case SE_SkillDamageTaken: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.SkillDmgTaken[e] = effect_value; - aabonuses.SkillDmgTaken[e] = effect_value; - itembonuses.SkillDmgTaken[e] = effect_value; - - } - break; - } - - case SE_TriggerOnCast: - { - for(int e = 0; e < MAX_SPELL_TRIGGER; e++) - { - spellbonuses.SpellTriggers[e] = effect_value; - aabonuses.SpellTriggers[e] = effect_value; - itembonuses.SpellTriggers[e] = effect_value; - } - break; - } - - case SE_SpellCritChance: - spellbonuses.CriticalSpellChance = effect_value; - aabonuses.CriticalSpellChance = effect_value; - itembonuses.CriticalSpellChance = effect_value; - break; - - case SE_CriticalSpellChance: - spellbonuses.CriticalSpellChance = effect_value; - spellbonuses.SpellCritDmgIncrease = effect_value; - aabonuses.CriticalSpellChance = effect_value; - aabonuses.SpellCritDmgIncrease = effect_value; - itembonuses.CriticalSpellChance = effect_value; - itembonuses.SpellCritDmgIncrease = effect_value; - break; - - case SE_SpellCritDmgIncrease: - spellbonuses.SpellCritDmgIncrease = effect_value; - aabonuses.SpellCritDmgIncrease = effect_value; - itembonuses.SpellCritDmgIncrease = effect_value; - break; - - case SE_DotCritDmgIncrease: - spellbonuses.DotCritDmgIncrease = effect_value; - aabonuses.DotCritDmgIncrease = effect_value; - itembonuses.DotCritDmgIncrease = effect_value; - break; - - case SE_CriticalHealChance: - spellbonuses.CriticalHealChance = effect_value; - aabonuses.CriticalHealChance = effect_value; - itembonuses.CriticalHealChance = effect_value; - break; - - case SE_CriticalHealOverTime: - spellbonuses.CriticalHealOverTime = effect_value; - aabonuses.CriticalHealOverTime = effect_value; - itembonuses.CriticalHealOverTime = effect_value; - break; - - case SE_MitigateDamageShield: - spellbonuses.DSMitigationOffHand = effect_value; - itembonuses.DSMitigationOffHand = effect_value; - aabonuses.DSMitigationOffHand = effect_value; - break; - - case SE_CriticalDoTChance: - spellbonuses.CriticalDoTChance = effect_value; - aabonuses.CriticalDoTChance = effect_value; - itembonuses.CriticalDoTChance = effect_value; - break; - - case SE_ProcOnKillShot: - { - for(int e = 0; e < MAX_SPELL_TRIGGER*3; e=3) - { - spellbonuses.SpellOnKill[e] = effect_value; - spellbonuses.SpellOnKill[e+1] = effect_value; - spellbonuses.SpellOnKill[e+2] = effect_value; - - aabonuses.SpellOnKill[e] = effect_value; - aabonuses.SpellOnKill[e+1] = effect_value; - aabonuses.SpellOnKill[e+2] = effect_value; - - itembonuses.SpellOnKill[e] = effect_value; - itembonuses.SpellOnKill[e+1] = effect_value; - itembonuses.SpellOnKill[e+2] = effect_value; - } - break; - } - - /* - case SE_SpellOnDeath: - { - for(int e = 0; e < MAX_SPELL_TRIGGER; e=2) - { - spellbonuses.SpellOnDeath[e] = SPELL_UNKNOWN; - spellbonuses.SpellOnDeath[e+1] = effect_value; - } - break; - } - */ - - case SE_CriticalDamageMob: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.CritDmgMob[e] = effect_value; - aabonuses.CritDmgMob[e] = effect_value; - itembonuses.CritDmgMob[e] = effect_value; - } - break; - } - - case SE_SkillDamageAmount: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.SkillDamageAmount[e] = effect_value; - aabonuses.SkillDamageAmount[e] = effect_value; - itembonuses.SkillDamageAmount[e] = effect_value; - } - break; - } - - case SE_IncreaseBlockChance: - spellbonuses.IncreaseBlockChance = effect_value; - aabonuses.IncreaseBlockChance = effect_value; - itembonuses.IncreaseBlockChance = effect_value; - break; - - case SE_PersistantCasting: - spellbonuses.PersistantCasting = effect_value; - itembonuses.PersistantCasting = effect_value; - aabonuses.PersistantCasting = effect_value; - break; - - case SE_ImmuneFleeing: - spellbonuses.ImmuneToFlee = false; - break; - - case SE_DelayDeath: - spellbonuses.DelayDeath = effect_value; - aabonuses.DelayDeath = effect_value; - itembonuses.DelayDeath = effect_value; - break; - - case SE_SpellProcChance: - spellbonuses.SpellProcChance = effect_value; - itembonuses.SpellProcChance = effect_value; - aabonuses.SpellProcChance = effect_value; - break; - - case SE_CharmBreakChance: - spellbonuses.CharmBreakChance = effect_value; - aabonuses.CharmBreakChance = effect_value; - itembonuses.CharmBreakChance = effect_value; - break; - - case SE_BardSongRange: - spellbonuses.SongRange = effect_value; - aabonuses.SongRange = effect_value; - itembonuses.SongRange = effect_value; - break; - - case SE_SkillDamageAmount2: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.SkillDamageAmount2[e] = effect_value; - aabonuses.SkillDamageAmount2[e] = effect_value; - itembonuses.SkillDamageAmount2[e] = effect_value; - } - break; - } - - case SE_NegateAttacks: - spellbonuses.NegateAttacks[0] = effect_value; - spellbonuses.NegateAttacks[1] = effect_value; - break; - - case SE_MitigateMeleeDamage: - spellbonuses.MitigateMeleeRune[0] = effect_value; - spellbonuses.MitigateMeleeRune[1] = -1; - break; - - case SE_MeleeThresholdGuard: - spellbonuses.MeleeThresholdGuard[0] = effect_value; - spellbonuses.MeleeThresholdGuard[1] = -1; - spellbonuses.MeleeThresholdGuard[1] = effect_value; - break; - - case SE_SpellThresholdGuard: - spellbonuses.SpellThresholdGuard[0] = effect_value; - spellbonuses.SpellThresholdGuard[1] = -1; - spellbonuses.SpellThresholdGuard[1] = effect_value; - break; - - case SE_MitigateSpellDamage: - spellbonuses.MitigateSpellRune[0] = effect_value; - spellbonuses.MitigateSpellRune[1] = -1; - break; - - case SE_MitigateDotDamage: - spellbonuses.MitigateDotRune[0] = effect_value; - spellbonuses.MitigateDotRune[1] = -1; - break; - - case SE_ManaAbsorbPercentDamage: - spellbonuses.ManaAbsorbPercentDamage[0] = effect_value; - spellbonuses.ManaAbsorbPercentDamage[1] = -1; - break; - - case SE_ShieldBlock: - spellbonuses.ShieldBlock = effect_value; - aabonuses.ShieldBlock = effect_value; - itembonuses.ShieldBlock = effect_value; - - case SE_BlockBehind: - spellbonuses.BlockBehind = effect_value; - aabonuses.BlockBehind = effect_value; - itembonuses.BlockBehind = effect_value; - break; - - case SE_Fear: - spellbonuses.IsFeared = false; - break; - - case SE_FrontalStunResist: - spellbonuses.FrontalStunResist = effect_value; - aabonuses.FrontalStunResist = effect_value; - itembonuses.FrontalStunResist = effect_value; - break; - - case SE_ImprovedBindWound: - aabonuses.BindWound = effect_value; - itembonuses.BindWound = effect_value; - spellbonuses.BindWound = effect_value; - break; - - case SE_MaxBindWound: - spellbonuses.MaxBindWound = effect_value; - aabonuses.MaxBindWound = effect_value; - itembonuses.MaxBindWound = effect_value; - break; - - case SE_BaseMovementSpeed: - spellbonuses.BaseMovementSpeed = effect_value; - aabonuses.BaseMovementSpeed = effect_value; - itembonuses.BaseMovementSpeed = effect_value; - break; - - case SE_IncreaseRunSpeedCap: - itembonuses.IncreaseRunSpeedCap = effect_value; - aabonuses.IncreaseRunSpeedCap = effect_value; - spellbonuses.IncreaseRunSpeedCap = effect_value; - break; - - case SE_DoubleSpecialAttack: - spellbonuses.DoubleSpecialAttack = effect_value; - aabonuses.DoubleSpecialAttack = effect_value; - itembonuses.DoubleSpecialAttack = effect_value; - break; - - case SE_TripleBackstab: - spellbonuses.TripleBackstab = effect_value; - aabonuses.TripleBackstab = effect_value; - itembonuses.TripleBackstab = effect_value; - break; - - case SE_FrontalBackstabMinDmg: - spellbonuses.FrontalBackstabMinDmg = false; - break; - - case SE_FrontalBackstabChance: - spellbonuses.FrontalBackstabChance = effect_value; - aabonuses.FrontalBackstabChance = effect_value; - itembonuses.FrontalBackstabChance = effect_value; - break; - - case SE_ConsumeProjectile: - spellbonuses.ConsumeProjectile = effect_value; - aabonuses.ConsumeProjectile = effect_value; - itembonuses.ConsumeProjectile = effect_value; - break; - - case SE_ForageAdditionalItems: - spellbonuses.ForageAdditionalItems = effect_value; - aabonuses.ForageAdditionalItems = effect_value; - itembonuses.ForageAdditionalItems = effect_value; - break; - - case SE_Salvage: - spellbonuses.SalvageChance = effect_value; - aabonuses.SalvageChance = effect_value; - itembonuses.SalvageChance = effect_value; - break; - - case SE_ArcheryDamageModifier: - spellbonuses.ArcheryDamageModifier = effect_value; - aabonuses.ArcheryDamageModifier = effect_value; - itembonuses.ArcheryDamageModifier = effect_value; - break; - - case SE_SecondaryDmgInc: - spellbonuses.SecondaryDmgInc = false; - aabonuses.SecondaryDmgInc = false; - itembonuses.SecondaryDmgInc = false; - break; - - case SE_StrikeThrough: - spellbonuses.StrikeThrough = effect_value; - aabonuses.StrikeThrough = effect_value; - itembonuses.StrikeThrough = effect_value; - break; - - case SE_StrikeThrough2: - spellbonuses.StrikeThrough = effect_value; - aabonuses.StrikeThrough = effect_value; - itembonuses.StrikeThrough = effect_value; - break; - - case SE_GiveDoubleAttack: - spellbonuses.GiveDoubleAttack = effect_value; - aabonuses.GiveDoubleAttack = effect_value; - itembonuses.GiveDoubleAttack = effect_value; - break; - - case SE_PetCriticalHit: - spellbonuses.PetCriticalHit = effect_value; - aabonuses.PetCriticalHit = effect_value; - itembonuses.PetCriticalHit = effect_value; - break; - - case SE_CombatStability: - spellbonuses.CombatStability = effect_value; - aabonuses.CombatStability = effect_value; - itembonuses.CombatStability = effect_value; - break; - - case SE_PetAvoidance: - spellbonuses.PetAvoidance = effect_value; - aabonuses.PetAvoidance = effect_value; - itembonuses.PetAvoidance = effect_value; - break; - - case SE_Ambidexterity: - spellbonuses.Ambidexterity = effect_value; - aabonuses.Ambidexterity = effect_value; - itembonuses.Ambidexterity = effect_value; - break; - - case SE_PetMaxHP: - spellbonuses.PetMaxHP = effect_value; - aabonuses.PetMaxHP = effect_value; - itembonuses.PetMaxHP = effect_value; - break; - - case SE_PetFlurry: - spellbonuses.PetFlurry = effect_value; - aabonuses.PetFlurry = effect_value; - itembonuses.PetFlurry = effect_value; - break; - - case SE_GivePetGroupTarget: - spellbonuses.GivePetGroupTarget = false; - aabonuses.GivePetGroupTarget = false; - itembonuses.GivePetGroupTarget = false; - break; - - case SE_PetMeleeMitigation: - spellbonuses.PetMeleeMitigation = effect_value; - itembonuses.PetMeleeMitigation = effect_value; - aabonuses.PetMeleeMitigation = effect_value; - break; - - case SE_RootBreakChance: - spellbonuses.RootBreakChance = effect_value; - aabonuses.RootBreakChance = effect_value; - itembonuses.RootBreakChance = effect_value; - break; - - case SE_ChannelChanceItems: - spellbonuses.ChannelChanceItems = effect_value; - aabonuses.ChannelChanceItems = effect_value; - itembonuses.ChannelChanceItems = effect_value; - break; - - case SE_ChannelChanceSpells: - spellbonuses.ChannelChanceSpells = effect_value; - aabonuses.ChannelChanceSpells = effect_value; - itembonuses.ChannelChanceSpells = effect_value; - break; - - case SE_UnfailingDivinity: - spellbonuses.UnfailingDivinity = effect_value; - aabonuses.UnfailingDivinity = effect_value; - itembonuses.UnfailingDivinity = effect_value; - break; - - case SE_ItemHPRegenCapIncrease: - spellbonuses.ItemHPRegenCap = effect_value; - aabonuses.ItemHPRegenCap = effect_value; - itembonuses.ItemHPRegenCap = effect_value; - break; - - case SE_OffhandRiposteFail: - spellbonuses.OffhandRiposteFail = effect_value; - aabonuses.OffhandRiposteFail = effect_value; - itembonuses.OffhandRiposteFail = effect_value; - break; - - case SE_ItemAttackCapIncrease: - aabonuses.ItemATKCap = effect_value; - itembonuses.ItemATKCap = effect_value; - spellbonuses.ItemATKCap = effect_value; - break; - - case SE_SpellEffectResistChance: - { - for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) - { - spellbonuses.SEResist[e] = effect_value; - spellbonuses.SEResist[e+1] = effect_value; - } - break; - } - - case SE_MasteryofPast: - spellbonuses.MasteryofPast = effect_value; - aabonuses.MasteryofPast = effect_value; - itembonuses.MasteryofPast = effect_value; - break; - - case SE_DoubleRiposte: - spellbonuses.DoubleRiposte = effect_value; - itembonuses.DoubleRiposte = effect_value; - aabonuses.DoubleRiposte = effect_value; - break; - - case SE_GiveDoubleRiposte: - spellbonuses.GiveDoubleRiposte[0] = effect_value; - itembonuses.GiveDoubleRiposte[0] = effect_value; - aabonuses.GiveDoubleRiposte[0] = effect_value; - break; - - case SE_SlayUndead: - spellbonuses.SlayUndead[0] = effect_value; - spellbonuses.SlayUndead[1] = effect_value; - itembonuses.SlayUndead[0] = effect_value; - itembonuses.SlayUndead[1] = effect_value; - aabonuses.SlayUndead[0] = effect_value; - aabonuses.SlayUndead[1] = effect_value; - break; - - case SE_DoubleRangedAttack: - spellbonuses.DoubleRangedAttack = effect_value; - aabonuses.DoubleRangedAttack = effect_value; - itembonuses.DoubleRangedAttack = effect_value; - break; - - case SE_ShieldEquipHateMod: - spellbonuses.ShieldEquipHateMod = effect_value; - aabonuses.ShieldEquipHateMod = effect_value; - itembonuses.ShieldEquipHateMod = effect_value; - break; - - case SE_ShieldEquipDmgMod: - spellbonuses.ShieldEquipDmgMod[0] = effect_value; - spellbonuses.ShieldEquipDmgMod[1] = effect_value; - aabonuses.ShieldEquipDmgMod[0] = effect_value; - aabonuses.ShieldEquipDmgMod[1] = effect_value; - itembonuses.ShieldEquipDmgMod[0] = effect_value; - itembonuses.ShieldEquipDmgMod[1] = effect_value; - break; - - case SE_TriggerMeleeThreshold: - spellbonuses.TriggerMeleeThreshold[0] = effect_value; - spellbonuses.TriggerMeleeThreshold[1] = effect_value; - spellbonuses.TriggerMeleeThreshold[2] = effect_value; - break; - - case SE_TriggerSpellThreshold: - spellbonuses.TriggerSpellThreshold[0] = effect_value; - spellbonuses.TriggerSpellThreshold[1] = effect_value; - spellbonuses.TriggerSpellThreshold[2] = effect_value; - break; - - case SE_DivineAura: - spellbonuses.DivineAura = false; - break; - - case SE_StunBashChance: - spellbonuses.StunBashChance = effect_value; - itembonuses.StunBashChance = effect_value; - aabonuses.StunBashChance = effect_value; - break; - - case SE_IncreaseChanceMemwipe: - spellbonuses.IncreaseChanceMemwipe = effect_value; - itembonuses.IncreaseChanceMemwipe = effect_value; - aabonuses.IncreaseChanceMemwipe = effect_value; - break; - - case SE_CriticalMend: - spellbonuses.CriticalMend = effect_value; - itembonuses.CriticalMend = effect_value; - aabonuses.CriticalMend = effect_value; - break; - - case SE_DistanceRemoval: - spellbonuses.DistanceRemoval = effect_value; - break; - - case SE_ImprovedTaunt: - spellbonuses.ImprovedTaunt[0] = effect_value; - spellbonuses.ImprovedTaunt[1] = effect_value; - spellbonuses.ImprovedTaunt[2] = -1; - break; - - case SE_FrenziedDevastation: - spellbonuses.FrenziedDevastation = effect_value; - aabonuses.FrenziedDevastation = effect_value; - itembonuses.FrenziedDevastation = effect_value; - break; - - case SE_Root: - spellbonuses.Root[0] = effect_value; - spellbonuses.Root[1] = -1; - break; - - case SE_Rune: - spellbonuses.MeleeRune[0] = effect_value; - spellbonuses.MeleeRune[1] = -1; - break; - - case SE_AbsorbMagicAtt: - spellbonuses.AbsorbMagicAtt[0] = effect_value; - spellbonuses.AbsorbMagicAtt[1] = -1; - break; - - case SE_Berserk: - spellbonuses.BerserkSPA = false; - aabonuses.BerserkSPA = false; - itembonuses.BerserkSPA = false; - break; - - case SE_Vampirism: - spellbonuses.Vampirism = effect_value; - aabonuses.Vampirism = effect_value; - itembonuses.Vampirism = effect_value; - break; - - case SE_Metabolism: - spellbonuses.Metabolism = effect_value; - aabonuses.Metabolism = effect_value; - itembonuses.Metabolism = effect_value; - break; - - case SE_ImprovedReclaimEnergy: - spellbonuses.ImprovedReclaimEnergy = effect_value; - aabonuses.ImprovedReclaimEnergy = effect_value; - itembonuses.ImprovedReclaimEnergy = effect_value; - break; - - case SE_HeadShot: - spellbonuses.HeadShot[0] = effect_value; - aabonuses.HeadShot[0] = effect_value; - itembonuses.HeadShot[0] = effect_value; - spellbonuses.HeadShot[1] = effect_value; - aabonuses.HeadShot[1] = effect_value; - itembonuses.HeadShot[1] = effect_value; - break; - - case SE_HeadShotLevel: - spellbonuses.HSLevel = effect_value; - aabonuses.HSLevel = effect_value; - itembonuses.HSLevel = effect_value; - break; - - case SE_Assassinate: - spellbonuses.Assassinate[0] = effect_value; - aabonuses.Assassinate[0] = effect_value; - itembonuses.Assassinate[0] = effect_value; - spellbonuses.Assassinate[1] = effect_value; - aabonuses.Assassinate[1] = effect_value; - itembonuses.Assassinate[1] = effect_value; - break; - - case SE_AssassinateLevel: - spellbonuses.AssassinateLevel = effect_value; - aabonuses.AssassinateLevel = effect_value; - itembonuses.AssassinateLevel = effect_value; - break; - - case SE_FinishingBlow: - spellbonuses.FinishingBlow[0] = effect_value; - aabonuses.FinishingBlow[0] = effect_value; - itembonuses.FinishingBlow[0] = effect_value; - spellbonuses.FinishingBlow[1] = effect_value; - aabonuses.FinishingBlow[1] = effect_value; - itembonuses.FinishingBlow[1] = effect_value; - break; - - case SE_FinishingBlowLvl: - spellbonuses.FinishingBlowLvl[0] = effect_value; - aabonuses.FinishingBlowLvl[0] = effect_value; - itembonuses.FinishingBlowLvl[0] = effect_value; - spellbonuses.FinishingBlowLvl[1] = effect_value; - aabonuses.FinishingBlowLvl[1] = effect_value; - itembonuses.FinishingBlowLvl[1] = effect_value; - break; - - } - } - } -} - diff --git a/zone/groupsx.cpp b/zone/groupsx.cpp deleted file mode 100644 index 6aee5f38b..000000000 --- a/zone/groupsx.cpp +++ /dev/null @@ -1,2194 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "../common/debug.h" -#include "masterentity.h" -#include "NpcAI.h" -#include "../common/packet_functions.h" -#include "../common/packet_dump.h" -#include "../common/StringUtil.h" -#include "worldserver.h" -extern EntityList entity_list; -extern WorldServer worldserver; - -// -// Xorlac: This will need proper synchronization to make it work correctly. -// Also, should investigate client ack for packet to ensure proper synch. -// - -/* - -note about how groups work: -A group contains 2 list, a list of pointers to members and a -list of member names. All members of a group should have their -name in the membername array, wether they are in the zone or not. -Only members in this zone will have non-null pointers in the -members array. - -*/ - -//create a group which should allready exist in the database -Group::Group(uint32 gid) -: GroupIDConsumer(gid) -{ - leader = nullptr; - memset(members,0,sizeof(Mob*) * MAX_GROUP_MEMBERS); - AssistTargetID = 0; - TankTargetID = 0; - PullerTargetID = 0; - - memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct)); - uint32 i; - for(i=0;iSetGrouped(true); - SetLeader(leader); - AssistTargetID = 0; - TankTargetID = 0; - PullerTargetID = 0; - memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct)); - uint32 i; - for(i=0;iGetName()); - - if(leader->IsClient()) - strcpy(leader->CastToClient()->GetPP().groupMembers[0],leader->GetName()); - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - MarkedNPCs[i] = 0; - - NPCMarkerID = 0; -} - -Group::~Group() -{ - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - if(MarkedNPCs[i]) - { - Mob* m = entity_list.GetMob(MarkedNPCs[i]); - if(m) - m->IsTargeted(-1); - } -} - -//Cofruben:Split money used in OP_Split. -//Rewritten by Father Nitwit -void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter) { - //avoid unneeded work - if(copper == 0 && silver == 0 && gold == 0 && platinum == 0) - return; - - uint32 i; - uint8 membercount = 0; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr) { - membercount++; - } - } - - if (membercount == 0) - return; - - uint32 mod; - //try to handle round off error a little better - if(membercount > 1) { - mod = platinum % membercount; - if((mod) > 0) { - platinum -= mod; - gold += 10 * mod; - } - mod = gold % membercount; - if((mod) > 0) { - gold -= mod; - silver += 10 * mod; - } - mod = silver % membercount; - if((mod) > 0) { - silver -= mod; - copper += 10 * mod; - } - } - - //calculate the splits - //We can still round off copper pieces, but I dont care - uint32 sc; - uint32 cpsplit = copper / membercount; - sc = copper % membercount; - uint32 spsplit = silver / membercount; - uint32 gpsplit = gold / membercount; - uint32 ppsplit = platinum / membercount; - - char buf[128]; - buf[63] = '\0'; - std::string msg = "You receive"; - bool one = false; - - if(ppsplit > 0) { - snprintf(buf, 63, " %u platinum", ppsplit); - msg += buf; - one = true; - } - if(gpsplit > 0) { - if(one) - msg += ","; - snprintf(buf, 63, " %u gold", gpsplit); - msg += buf; - one = true; - } - if(spsplit > 0) { - if(one) - msg += ","; - snprintf(buf, 63, " %u silver", spsplit); - msg += buf; - one = true; - } - if(cpsplit > 0) { - if(one) - msg += ","; - //this message is not 100% accurate for the splitter - //if they are receiving any roundoff - snprintf(buf, 63, " %u copper", cpsplit); - msg += buf; - one = true; - } - msg += " as your split"; - - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr && members[i]->IsClient()) { // If Group Member is Client - Client *c = members[i]->CastToClient(); - //I could not get MoneyOnCorpse to work, so we use this - c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true); - - c->Message(2, msg.c_str()); - } - } -} - -bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 CharacterID) -{ - bool InZone = true; - bool ismerc = false; - - // This method should either be passed a Mob*, if the new member is in this zone, or a nullptr Mob* - // and the name and CharacterID of the new member, if they are out of zone. - // - if(!newmember && !NewMemberName) - return false; - - if(GroupCount() >= MAX_GROUP_MEMBERS) //Sanity check for merging groups together. - return false; - - if(!newmember) - InZone = false; - else - { - NewMemberName = newmember->GetCleanName(); - - if(newmember->IsClient()) - CharacterID = newmember->CastToClient()->CharacterID(); - if(newmember->IsMerc()) - { - Client* owner = newmember->CastToMerc()->GetMercOwner(); - if(owner) - { - CharacterID = owner->CastToClient()->CharacterID(); - NewMemberName = newmember->GetName(); - ismerc = true; - } - } - } - - uint32 i = 0; - - // See if they are already in the group - // - for (i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(!strcasecmp(membername[i], NewMemberName)) - return false; - - // Put them in the group - for (i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if (membername[i][0] == '\0') - { - if(InZone) - members[i] = newmember; - - break; - } - } - - if (i == MAX_GROUP_MEMBERS) - return false; - - strcpy(membername[i], NewMemberName); - MemberRoles[i] = 0; - - int x=1; - - //build the template join packet - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); - GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer; - strcpy(gj->membername, NewMemberName); - gj->action = groupActJoin; - - gj->leader_aas = LeaderAbilities; - - for (i = 0;i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr && members[i] != newmember) { - //fill in group join & send it - if(members[i]->IsMerc()) - { - strcpy(gj->yourname, members[i]->GetName()); - } - else - { - strcpy(gj->yourname, members[i]->GetCleanName()); - } - if(members[i]->IsClient()) { - members[i]->CastToClient()->QueuePacket(outapp); - - //put new member into existing person's list - strcpy(members[i]->CastToClient()->GetPP().groupMembers[this->GroupCount()-1], NewMemberName); - } - - //put this existing person into the new member's list - if(InZone && newmember->IsClient()) { - if(IsLeader(members[i])) - strcpy(newmember->CastToClient()->GetPP().groupMembers[0], members[i]->GetCleanName()); - else { - strcpy(newmember->CastToClient()->GetPP().groupMembers[x], members[i]->GetCleanName()); - x++; - } - } - } - } - - if(InZone) - { - //put new member in his own list. - newmember->SetGrouped(true); - - if(newmember->IsClient()) - { - strcpy(newmember->CastToClient()->GetPP().groupMembers[x], NewMemberName); - newmember->CastToClient()->Save(); - database.SetGroupID(NewMemberName, GetID(), newmember->CastToClient()->CharacterID(), false); - SendMarkedNPCsToMember(newmember->CastToClient()); - - NotifyMainTank(newmember->CastToClient(), 1); - NotifyMainAssist(newmember->CastToClient(), 1); - NotifyPuller(newmember->CastToClient(), 1); - } - - if(newmember->IsMerc()) - { - Client* owner = newmember->CastToMerc()->GetMercOwner(); - if(owner) - { - database.SetGroupID(newmember->GetName(), GetID(), owner->CharacterID(), true); - } - } -#ifdef BOTS - for (i = 0;i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr && members[i]->IsBot()) { - members[i]->CastToBot()->CalcChanceToCast(); - } - } -#endif //BOTS - } - else - database.SetGroupID(NewMemberName, GetID(), CharacterID, ismerc); - - safe_delete(outapp); - - return true; -} - -void Group::AddMember(const char *NewMemberName) -{ - // This method should be called when both the new member and the group leader are in a different zone to this one. - // - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(!strcasecmp(membername[i], NewMemberName)) - { - return; - } - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if (membername[i][0] == '\0') - { - strcpy(membername[i], NewMemberName); - MemberRoles[i] = 0; - break; - } - } -} - - -void Group::QueuePacket(const EQApplicationPacket *app, bool ack_req) -{ - uint32 i; - for(i = 0; i < MAX_GROUP_MEMBERS; i++) - if(members[i] && members[i]->IsClient()) - members[i]->CastToClient()->QueuePacket(app, ack_req); -} - -// solar: sends the rest of the group's hps to member. this is useful when -// someone first joins a group, but otherwise there shouldn't be a need to -// call it -void Group::SendHPPacketsTo(Mob *member) -{ - if(member && member->IsClient()) - { - EQApplicationPacket hpapp; - EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) - { - if(members[i] && members[i] != member) - { - members[i]->CreateHPPacket(&hpapp); - member->CastToClient()->QueuePacket(&hpapp, false); - if(member->CastToClient()->GetClientVersion() >= EQClientSoD) - { - outapp.SetOpcode(OP_MobManaUpdate); - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; - mmus->spawn_id = members[i]->GetID(); - mmus->mana = members[i]->GetManaPercent(); - member->CastToClient()->QueuePacket(&outapp, false); - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; - outapp.SetOpcode(OP_MobEnduranceUpdate); - meus->endurance = members[i]->GetEndurancePercent(); - member->CastToClient()->QueuePacket(&outapp, false); - } - } - } - } -} - -void Group::SendHPPacketsFrom(Mob *member) -{ - EQApplicationPacket hp_app; - if(!member) - return; - - member->CreateHPPacket(&hp_app); - EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - - uint32 i; - for(i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(members[i] && members[i] != member && members[i]->IsClient()) - { - members[i]->CastToClient()->QueuePacket(&hp_app); - if(members[i]->CastToClient()->GetClientVersion() >= EQClientSoD) - { - outapp.SetOpcode(OP_MobManaUpdate); - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; - mmus->spawn_id = member->GetID(); - mmus->mana = member->GetManaPercent(); - members[i]->CastToClient()->QueuePacket(&outapp, false); - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; - outapp.SetOpcode(OP_MobEnduranceUpdate); - meus->endurance = member->GetEndurancePercent(); - members[i]->CastToClient()->QueuePacket(&outapp, false); - } - } - } -} - -//updates a group member's client pointer when they zone in -//if the group was in the zone allready -bool Group::UpdatePlayer(Mob* update){ - - VerifyGroup(); - - uint32 i=0; - if(update->IsClient()) { - //update their player profile - PlayerProfile_Struct &pp = update->CastToClient()->GetPP(); - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(membername[i][0] == '\0') - memset(pp.groupMembers[i], 0, 64); - else - strn0cpy(pp.groupMembers[i], membername[i], 64); - } - if(IsNPCMarker(update->CastToClient())) - { - NPCMarkerID = update->GetID(); - SendLeadershipAAUpdate(); - } - } - - for (i = 0; i < MAX_GROUP_MEMBERS; i++) - { - if (!strcasecmp(membername[i],update->GetName())) - { - members[i] = update; - members[i]->SetGrouped(true); - return true; - } - } - return false; -} - - -void Group::MemberZoned(Mob* removemob) { - uint32 i; - - if (removemob == nullptr) - return; - - if(removemob == GetLeader()) - SetLeader(nullptr); - - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == removemob) { - members[i] = nullptr; - //should NOT clear the name, it is used for world communication. - break; - } -#ifdef BOTS - if (members[i] != nullptr && members[i]->IsBot()) { - members[i]->CastToBot()->CalcChanceToCast(); - } -#endif //BOTS - } - if(removemob->IsClient() && HasRole(removemob, RoleAssist)) - SetGroupAssistTarget(0); - - if(removemob->IsClient() && HasRole(removemob, RoleTank)) - SetGroupTankTarget(0); - - if(removemob->IsClient() && HasRole(removemob, RolePuller)) - SetGroupPullerTarget(0); -} - -bool Group::DelMemberOOZ(const char *Name) { - - if(!Name) return false; - - // If a member out of zone has disbanded, clear out their name. - // - for(unsigned int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(!strcasecmp(Name, membername[i])) - // This shouldn't be called if the member is in this zone. - if(!members[i]) { - if(!strncmp(GetLeaderName(), Name, 64)) - { - //TODO: Transfer leadership if leader disbands OOZ. - UpdateGroupAAs(); - } - - memset(membername[i], 0, 64); - MemberRoles[i] = 0; - if(GroupCount() < 3) - { - UnDelegateMarkNPC(NPCMarkerName.c_str()); - if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < EQClientSoD) { - UnDelegateMainAssist(MainAssistName.c_str()); - } - ClearAllNPCMarks(); - } - return true; - } - } - - return false; -} - -bool Group::DelMember(Mob* oldmember,bool ignoresender) -{ - if (oldmember == nullptr){ - return false; - } - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == oldmember) { - members[i] = nullptr; - membername[i][0] = '\0'; - memset(membername[i],0,64); - MemberRoles[i] = 0; - break; - } - } - - //handle leader quitting group gracefully - if (oldmember == GetLeader() && GroupCount() >= 2) { - for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) { - if(members[nl]) { - ChangeLeader(members[nl]); - break; - } - } - } - - ServerPacket* pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct)); - ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer; - gl->gid = GetID(); - gl->zoneid = zone->GetZoneID(); - gl->instance_id = zone->GetInstanceID(); - strcpy(gl->member_name, oldmember->GetName()); - worldserver.SendPacket(pack); - safe_delete(pack); - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); - GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer; - gu->action = groupActLeave; - strcpy(gu->membername, oldmember->GetCleanName()); - strcpy(gu->yourname, oldmember->GetCleanName()); - - gu->leader_aas = LeaderAbilities; - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == nullptr) { - //if (DEBUG>=5) LogFile->write(EQEMuLog::Debug, "Group::DelMember() null member at slot %i", i); - continue; - } - if (members[i] != oldmember) { - strcpy(gu->yourname, members[i]->GetCleanName()); - if(members[i]->IsClient()) - members[i]->CastToClient()->QueuePacket(outapp); - } -#ifdef BOTS - if (members[i] != nullptr && members[i]->IsBot()) { - members[i]->CastToBot()->CalcChanceToCast(); - } -#endif //BOTS - } - - if (!ignoresender) { - strcpy(gu->yourname,oldmember->GetCleanName()); - strcpy(gu->membername,oldmember->GetCleanName()); - gu->action = groupActLeave; - - if(oldmember->IsClient()) - oldmember->CastToClient()->QueuePacket(outapp); - } - - if(oldmember->IsClient()) - database.SetGroupID(oldmember->GetCleanName(), 0, oldmember->CastToClient()->CharacterID()); - - oldmember->SetGrouped(false); - disbandcheck = true; - - safe_delete(outapp); - - if(HasRole(oldmember, RoleTank)) - { - SetGroupTankTarget(0); - UnDelegateMainTank(oldmember->GetName()); - } - - if(HasRole(oldmember, RoleAssist)) - { - SetGroupAssistTarget(0); - UnDelegateMainAssist(oldmember->GetName()); - } - - if(HasRole(oldmember, RolePuller)) - { - SetGroupPullerTarget(0); - UnDelegatePuller(oldmember->GetName()); - } - - if(oldmember->IsClient()) - SendMarkedNPCsToMember(oldmember->CastToClient(), true); - - if(GroupCount() < 3) - { - UnDelegateMarkNPC(NPCMarkerName.c_str()); - if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < EQClientSoD) { - UnDelegateMainAssist(MainAssistName.c_str()); - } - ClearAllNPCMarks(); - } - - return true; -} - -// does the caster + group -void Group::CastGroupSpell(Mob* caster, uint16 spell_id) { - uint32 z; - float range, distance; - - if(!caster) - return; - - castspell = true; - range = caster->GetAOERange(spell_id); - - float range2 = range*range; - -// caster->SpellOnTarget(spell_id, caster); - - for(z=0; z < MAX_GROUP_MEMBERS; z++) - { - if(members[z] == caster) { - caster->SpellOnTarget(spell_id, caster); -#ifdef GROUP_BUFF_PETS - if(caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed()) - caster->SpellOnTarget(spell_id, caster->GetPet()); -#endif - } - else if(members[z] != nullptr) - { - distance = caster->DistNoRoot(*members[z]); - if(distance <= range2) { - caster->SpellOnTarget(spell_id, members[z]); -#ifdef GROUP_BUFF_PETS - if(members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed()) - caster->SpellOnTarget(spell_id, members[z]->GetPet()); -#endif - } else - _log(SPELLS__CASTING, "Group spell: %s is out of range %f at distance %f from %s", members[z]->GetName(), range, distance, caster->GetName()); - } - } - - castspell = false; - disbandcheck = true; -} - -// does the caster + group -void Group::GroupBardPulse(Mob* caster, uint16 spell_id) { - uint32 z; - float range, distance; - - if(!caster) - return; - - castspell = true; - range = caster->GetAOERange(spell_id); - - float range2 = range*range; - - for(z=0; z < MAX_GROUP_MEMBERS; z++) { - if(members[z] == caster) { - caster->BardPulse(spell_id, caster); -#ifdef GROUP_BUFF_PETS - if(caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed()) - caster->BardPulse(spell_id, caster->GetPet()); -#endif - } - else if(members[z] != nullptr) - { - distance = caster->DistNoRoot(*members[z]); - if(distance <= range2) { - members[z]->BardPulse(spell_id, caster); -#ifdef GROUP_BUFF_PETS - if(members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed()) - members[z]->GetPet()->BardPulse(spell_id, caster); -#endif - } else - _log(SPELLS__BARDS, "Group bard pulse: %s is out of range %f at distance %f from %s", members[z]->GetName(), range, distance, caster->GetName()); - } - } -} - -bool Group::IsGroupMember(Mob* client) -{ - bool Result = false; - - if(client) { - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == client) - Result = true; - } - } - - return Result; -} - -bool Group::IsGroupMember(const char *Name) -{ - if(Name) - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) - if((strlen(Name) == strlen(membername[i])) && !strncmp(membername[i], Name, strlen(Name))) - return true; - - return false; -} - -void Group::GroupMessage(Mob* sender, uint8 language, uint8 lang_skill, const char* message) { - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(!members[i]) - continue; - - if (members[i]->IsClient() && members[i]->CastToClient()->GetFilter(FilterGroupChat)!=0) - members[i]->CastToClient()->ChannelMessageSend(sender->GetName(),members[i]->GetName(),2,language,lang_skill,message); - } - - ServerPacket* pack = new ServerPacket(ServerOP_OOZGroupMessage, sizeof(ServerGroupChannelMessage_Struct) + strlen(message) + 1); - ServerGroupChannelMessage_Struct* gcm = (ServerGroupChannelMessage_Struct*)pack->pBuffer; - gcm->zoneid = zone->GetZoneID(); - gcm->groupid = GetID(); - gcm->instanceid = zone->GetInstanceID(); - strcpy(gcm->from, sender->GetName()); - strcpy(gcm->message, message); - worldserver.SendPacket(pack); - safe_delete(pack); -} - -uint32 Group::GetTotalGroupDamage(Mob* other) { - uint32 total = 0; - - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(!members[i]) - continue; - if (other->CheckAggro(members[i])) - total += other->GetHateAmount(members[i],true); - } - return total; -} - -void Group::DisbandGroup() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupUpdate_Struct)); - - GroupUpdate_Struct* gu = (GroupUpdate_Struct*) outapp->pBuffer; - gu->action = groupActDisband; - - Client *Leader = nullptr; - - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == nullptr) { - continue; - } - - if (members[i]->IsClient()) { - if(IsLeader(members[i])) - Leader = members[i]->CastToClient(); - - strcpy(gu->yourname, members[i]->GetName()); - database.SetGroupID(members[i]->GetName(), 0, members[i]->CastToClient()->CharacterID()); - members[i]->CastToClient()->QueuePacket(outapp); - SendMarkedNPCsToMember(members[i]->CastToClient(), true); - - } - - members[i]->SetGrouped(false); - members[i] = nullptr; - membername[i][0] = '\0'; - } - - ClearAllNPCMarks(); - - ServerPacket* pack = new ServerPacket(ServerOP_DisbandGroup, sizeof(ServerDisbandGroup_Struct)); - ServerDisbandGroup_Struct* dg = (ServerDisbandGroup_Struct*)pack->pBuffer; - dg->zoneid = zone->GetZoneID(); - dg->groupid = GetID(); - dg->instance_id = zone->GetInstanceID(); - worldserver.SendPacket(pack); - safe_delete(pack); - - entity_list.RemoveGroup(GetID()); - if(GetID() != 0) - database.ClearGroup(GetID()); - - if(Leader && (Leader->IsLFP())) { - Leader->UpdateLFP(); - } - - safe_delete(outapp); -} - -bool Group::Process() { - if(disbandcheck && !GroupCount()) - return false; - else if(disbandcheck && GroupCount()) - disbandcheck = false; - return true; -} - -void Group::SendUpdate(uint32 type, Mob* member) -{ - if(!member->IsClient()) - return; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate2_Struct)); - GroupUpdate2_Struct* gu = (GroupUpdate2_Struct*)outapp->pBuffer; - gu->action = type; - strcpy(gu->yourname,member->GetName()); - - int x = 0; - - gu->leader_aas = LeaderAbilities; - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if((members[i] != nullptr) && IsLeader(members[i])) - { - strcpy(gu->leadersname, members[i]->GetName()); - break; - } - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if (members[i] != nullptr && members[i] != member) - strcpy(gu->membername[x++], members[i]->GetName()); - - member->CastToClient()->QueuePacket(outapp); - - safe_delete(outapp); -} - -void Group::SendLeadershipAAUpdate() -{ - // This method updates other members of the group in the current zone with the Leader's group leadership AAs. - // - // It is called when the leader purchases a leadership AA or enters a zone. - // - // If a group member is not in the same zone as the leader when the leader purchases a new AA, they will not become - // aware of it until they are next in the same zone as the leader. - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); - - GroupJoin_Struct* gu = (GroupJoin_Struct*)outapp->pBuffer; - - gu->action = groupActAAUpdate; - - uint32 i = 0; - - gu->leader_aas = LeaderAbilities; - - gu->NPCMarkerID = GetNPCMarkerID(); - - for (i = 0;i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - { - strcpy(gu->yourname, members[i]->GetName()); - strcpy(gu->membername, members[i]->GetName()); - members[i]->CastToClient()->QueuePacket(outapp); - } - - safe_delete(outapp); -} - -uint8 Group::GroupCount() { - - uint8 MemberCount = 0; - - for(uint8 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(membername[i][0]) - ++MemberCount; - - return MemberCount; -} - -uint32 Group::GetHighestLevel() -{ -uint32 level = 1; -uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) - { - if (members[i]) - { - if(members[i]->GetLevel() > level) - level = members[i]->GetLevel(); - } - } - return level; -} -uint32 Group::GetLowestLevel() -{ -uint32 level = 255; -uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) - { - if (members[i]) - { - if(members[i]->GetLevel() < level) - level = members[i]->GetLevel(); - } - } - return level; -} - -void Group::TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float x, float y, float z, float heading) -{ - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) - { - if (members[i] != nullptr && members[i]->IsClient() && members[i] != sender) - { - members[i]->CastToClient()->MovePC(zoneID, instance_id, x, y, z, heading, 0, ZoneSolicited); - } - } -} - -bool Group::LearnMembers() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (database.RunQuery(query,MakeAnyLenString(&query, "SELECT name FROM group_id WHERE groupid=%lu", (unsigned long)GetID()), - errbuf,&result)){ - safe_delete_array(query); - if(mysql_num_rows(result) < 1) { //could prolly be 2 - mysql_free_result(result); - LogFile->write(EQEMuLog::Error, "Error getting group members for group %lu: %s", (unsigned long)GetID(), errbuf); - return(false); - } - int i = 0; - while((row = mysql_fetch_row(result))) { - if(!row[0]) - continue; - members[i] = nullptr; - strn0cpy(membername[i], row[0], 64); - - i++; - } - mysql_free_result(result); - } - - return(true); -} - -void Group::VerifyGroup() { - /* - The purpose of this method is to make sure that a group - is in a valid state, to prevent dangling pointers. - Only called every once in a while (on member re-join for now). - */ - - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (membername[i][0] == '\0') { -#if EQDEBUG >= 7 -LogFile->write(EQEMuLog::Debug, "Group %lu: Verify %d: Empty.\n", (unsigned long)GetID(), i); -#endif - members[i] = nullptr; - continue; - } - - //it should be safe to use GetClientByName, but Group is trying - //to be generic, so we'll go for general Mob - Mob *them = entity_list.GetMob(membername[i]); - if(them == nullptr && members[i] != nullptr) { //they arnt here anymore.... -#if EQDEBUG >= 6 - LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' has disappeared!!", (unsigned long)GetID(), membername[i]); -#endif - membername[i][0] = '\0'; - members[i] = nullptr; - continue; - } - - if(them != nullptr && members[i] != them) { //our pointer is out of date... not so good. -#if EQDEBUG >= 5 - LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' had an out of date pointer!!", (unsigned long)GetID(), membername[i]); -#endif - members[i] = them; - continue; - } -#if EQDEBUG >= 8 - LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' is valid.", (unsigned long)GetID(), membername[i]); -#endif - } -} - - -void Group::GroupMessage_StringID(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2,const char* message3,const char* message4,const char* message5,const char* message6,const char* message7,const char* message8,const char* message9, uint32 distance) { - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(members[i] == nullptr) - continue; - - if(members[i] == sender) - continue; - - members[i]->Message_StringID(type, string_id, message, message2, message3, message4, message5, message6, message7, message8, message9, 0); - } -} - - - -void Client::LeaveGroup() { - Group *g = GetGroup(); - - if(g) { - if(g->GroupCount() < 3) - g->DisbandGroup(); - else - g->DelMember(this); - } else { - //force things a little - database.SetGroupID(GetName(), 0, CharacterID()); - } - - isgrouped = false; -} - -void Group::HealGroup(uint32 heal_amt, Mob* caster, int32 range) -{ - if (!caster) - return; - - if (!range) - range = 200; - - float distance; - float range2 = range*range; - - - int numMem = 0; - unsigned int gi = 0; - for(; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi]){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - numMem += 1; - } - } - } - - heal_amt /= numMem; - for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi]){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - members[gi]->HealDamage(heal_amt, caster); - members[gi]->SendHPUpdate(); - } - } - } -} - - -void Group::BalanceHP(int32 penalty, int32 range, Mob* caster, int32 limit) -{ - if (!caster) - return; - - if (!range) - range = 200; - - int dmgtaken = 0, numMem = 0, dmgtaken_tmp = 0; - - float distance; - float range2 = range*range; - - unsigned int gi = 0; - for(; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi]){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - - dmgtaken_tmp = members[gi]->GetMaxHP() - members[gi]->GetHP(); - if (limit && (dmgtaken_tmp > limit)) - dmgtaken_tmp = limit; - - dmgtaken += (dmgtaken_tmp); - numMem += 1; - } - } - } - - dmgtaken += dmgtaken * penalty / 100; - dmgtaken /= numMem; - for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi]){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - if((members[gi]->GetMaxHP() - dmgtaken) < 1){ //this way the ability will never kill someone - members[gi]->SetHP(1); //but it will come darn close - members[gi]->SendHPUpdate(); - } - else{ - members[gi]->SetHP(members[gi]->GetMaxHP() - dmgtaken); - members[gi]->SendHPUpdate(); - } - } - } - } -} - -void Group::BalanceMana(int32 penalty, int32 range, Mob* caster, int32 limit) -{ - if (!caster) - return; - - if (!range) - range = 200; - - float distance; - float range2 = range*range; - - int manataken = 0, numMem = 0, manataken_tmp = 0; - unsigned int gi = 0; - for(; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi] && (members[gi]->GetMaxMana() > 0)){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - - manataken_tmp = members[gi]->GetMaxMana() - members[gi]->GetMana(); - if (limit && (manataken_tmp > limit)) - manataken_tmp = limit; - - manataken += (manataken_tmp); - numMem += 1; - } - } - } - - manataken += manataken * penalty / 100; - manataken /= numMem; - - if (limit && (manataken > limit)) - manataken = limit; - - for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi]){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - if((members[gi]->GetMaxMana() - manataken) < 1){ - members[gi]->SetMana(1); - if (members[gi]->IsClient()) - members[gi]->CastToClient()->SendManaUpdate(); - } - else{ - members[gi]->SetMana(members[gi]->GetMaxMana() - manataken); - if (members[gi]->IsClient()) - members[gi]->CastToClient()->SendManaUpdate(); - } - } - } - } -} - -uint16 Group::GetAvgLevel() -{ - double levelHolder = 0; - uint8 i = 0; - uint8 numMem = 0; - while(i < MAX_GROUP_MEMBERS) - { - if (members[i]) - { - numMem++; - levelHolder = levelHolder + (members[i]->GetLevel()); - } - i++; - } - levelHolder = ((levelHolder/numMem)+.5); // total levels divided by num of characters - return (uint16(levelHolder)); -} - -void Group::MarkNPC(Mob* Target, int Number) -{ - // Send a packet to all group members in this zone causing the client to prefix the Target mob's name - // with the specified Number. - // - if(!Target || Target->IsClient()) - return; - - if((Number < 1) || (Number > MAX_MARKED_NPCS)) - return; - - bool AlreadyMarked = false; - - uint16 EntityID = Target->GetID(); - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - if(MarkedNPCs[i] == EntityID) - { - if(i == (Number - 1)) - return; - - UpdateXTargetMarkedNPC(i+1, nullptr); - MarkedNPCs[i] = 0; - - AlreadyMarked = true; - - break; - } - - if(!AlreadyMarked) - { - if(MarkedNPCs[Number - 1]) - { - Mob* m = entity_list.GetMob(MarkedNPCs[Number-1]); - if(m) - m->IsTargeted(-1); - - UpdateXTargetMarkedNPC(Number, nullptr); - } - - if(EntityID) - { - Mob* m = entity_list.GetMob(Target->GetID()); - if(m) - m->IsTargeted(1); - } - } - - MarkedNPCs[Number - 1] = EntityID; - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct)); - - MarkNPC_Struct* mnpcs = (MarkNPC_Struct *)outapp->pBuffer; - - mnpcs->TargetID = EntityID; - - mnpcs->Number = Number; - - Mob *m = entity_list.GetMob(EntityID); - - if(m) - sprintf(mnpcs->Name, "%s", m->GetCleanName()); - - QueuePacket(outapp); - - safe_delete(outapp); - - UpdateXTargetMarkedNPC(Number, m); -} - -void Group::DelegateMainTank(const char *NewMainTankName, uint8 toggle) -{ - // This method is called when the group leader Delegates the Main Tank role to a member of the group - // (or himself). All group members in the zone are notified of the new Main Tank and it is recorded - // in the group_leaders table so as to persist across zones. - // - - bool updateDB = false; - - if(!NewMainTankName) - return; - - Mob *m = entity_list.GetMob(NewMainTankName); - - if(!m) - return; - - if(MainTankName != NewMainTankName || !toggle) - updateDB = true; - - if(m->GetTarget()) - TankTargetID = m->GetTarget()->GetID(); - else - TankTargetID = 0; - - Mob *mtt = TankTargetID ? entity_list.GetMob(TankTargetID) : 0; - - SetMainTank(NewMainTankName); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - NotifyMainTank(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(GroupTank, m, NewMainTankName); - members[i]->CastToClient()->UpdateXTargetType(GroupTankTarget, mtt); - } - } - - if(updateDB) { - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = nullptr; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET maintank='%s' WHERE gid=%i LIMIT 1", - MainTankName.c_str(), GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group main tank: %s\n", errbuff); - - safe_delete_array(Query); - } -} - -void Group::DelegateMainAssist(const char *NewMainAssistName, uint8 toggle) -{ - // This method is called when the group leader Delegates the Main Assist role to a member of the group - // (or himself). All group members in the zone are notified of the new Main Assist and it is recorded - // in the group_leaders table so as to persist across zones. - // - - bool updateDB = false; - - if(!NewMainAssistName) - return; - - Mob *m = entity_list.GetMob(NewMainAssistName); - - if(!m) - return; - - if(MainAssistName != NewMainAssistName || !toggle) - updateDB = true; - - if(m->GetTarget()) - AssistTargetID = m->GetTarget()->GetID(); - else - AssistTargetID = 0; - - SetMainAssist(NewMainAssistName); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { - if(members[i] && members[i]->IsClient()) - { - NotifyMainAssist(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(GroupAssist, m, NewMainAssistName); - members[i]->CastToClient()->UpdateXTargetType(GroupAssistTarget, m->GetTarget()); - } - } - - if(updateDB) { - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = nullptr; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET assist='%s' WHERE gid=%i LIMIT 1", - MainAssistName.c_str(), GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group main assist: %s\n", errbuff); - - safe_delete_array(Query); - } -} - -void Group::DelegatePuller(const char *NewPullerName, uint8 toggle) -{ - // This method is called when the group leader Delegates the Puller role to a member of the group - // (or himself). All group members in the zone are notified of the new Puller and it is recorded - // in the group_leaders table so as to persist across zones. - // - - bool updateDB = false; - - if(!NewPullerName) - return; - - Mob *m = entity_list.GetMob(NewPullerName); - - if(!m) - return; - - if(PullerName != NewPullerName || !toggle) - updateDB = true; - - if(m->GetTarget()) - PullerTargetID = m->GetTarget()->GetID(); - else - PullerTargetID = 0; - - SetPuller(NewPullerName); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { - if(members[i] && members[i]->IsClient()) - { - NotifyPuller(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(Puller, m, NewPullerName); - members[i]->CastToClient()->UpdateXTargetType(PullerTarget, m->GetTarget()); - } - } - - if(updateDB) { - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = nullptr; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET puller='%s' WHERE gid=%i LIMIT 1", - PullerName.c_str(), GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group main puller: %s\n", errbuff); - - safe_delete_array(Query); - } - -} - -void Group::NotifyMainTank(Client *c, uint8 toggle) -{ - // Send a packet to the specified Client notifying them who the new Main Tank is. This causes the client to display - // a message with the name of the Main Tank. - // - - if(!c) - return; - - if(!MainTankName.size()) - return; - - if(c->GetClientVersion() < EQClientSoD) - { - if(toggle) - c->Message(0, "%s is now Main Tank.", MainTankName.c_str()); - else - c->Message(0, "%s is no longer Main Tank.", MainTankName.c_str()); - } - else - { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); - - GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; - - strn0cpy(grs->Name1, MainTankName.c_str(), sizeof(grs->Name1)); - - strn0cpy(grs->Name2, GetLeaderName(), sizeof(grs->Name2)); - - grs->RoleNumber = 1; - - grs->Toggle = toggle; - - c->QueuePacket(outapp); - - safe_delete(outapp); - } - -} - -void Group::NotifyMainAssist(Client *c, uint8 toggle) -{ - // Send a packet to the specified Client notifying them who the new Main Assist is. This causes the client to display - // a message with the name of the Main Assist. - // - - if(!c) - return; - - if(!MainAssistName.size()) - return; - - if(c->GetClientVersion() < EQClientSoD) - { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); - - DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; - - das->DelegateAbility = 0; - - das->MemberNumber = 0; - - das->Action = 0; - - das->EntityID = 0; - - strn0cpy(das->Name, MainAssistName.c_str(), sizeof(das->Name)); - - c->QueuePacket(outapp); - - safe_delete(outapp); - } - else - { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); - - GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; - - strn0cpy(grs->Name1, MainAssistName.c_str(), sizeof(grs->Name1)); - - strn0cpy(grs->Name2, GetLeaderName(), sizeof(grs->Name2)); - - grs->RoleNumber = 2; - - grs->Toggle = toggle; - - c->QueuePacket(outapp); - - safe_delete(outapp); - } - - NotifyAssistTarget(c); - -} - -void Group::NotifyPuller(Client *c, uint8 toggle) -{ - // Send a packet to the specified Client notifying them who the new Puller is. This causes the client to display - // a message with the name of the Puller. - // - - if(!c) - return; - - if(!PullerName.size()) - return; - - if(c->GetClientVersion() < EQClientSoD) - { - if(toggle) - c->Message(0, "%s is now Puller.", PullerName.c_str()); - else - c->Message(0, "%s is no longer Puller.", PullerName.c_str()); - } - else - { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); - - GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; - - strn0cpy(grs->Name1, PullerName.c_str(), sizeof(grs->Name1)); - - strn0cpy(grs->Name2, GetLeaderName(), sizeof(grs->Name2)); - - grs->RoleNumber = 3; - - grs->Toggle = toggle; - - c->QueuePacket(outapp); - - safe_delete(outapp); - } - -} - -void Group::UnDelegateMainTank(const char *OldMainTankName, uint8 toggle) -{ - // Called when the group Leader removes the Main Tank delegation. Sends a packet to each group member in the zone - // informing them of the change and update the group_leaders table. - // - if(OldMainTankName == MainTankName) { - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET maintank='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group main tank: %s\n", errbuff); - - safe_delete_array(Query); - - if(!toggle) { - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { - if(members[i] && members[i]->IsClient()) - { - NotifyMainTank(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(GroupTank, nullptr, ""); - members[i]->CastToClient()->UpdateXTargetType(GroupTankTarget, nullptr); - } - } - } - - SetMainTank(""); - } -} - -void Group::UnDelegateMainAssist(const char *OldMainAssistName, uint8 toggle) -{ - // Called when the group Leader removes the Main Assist delegation. Sends a packet to each group member in the zone - // informing them of the change and update the group_leaders table. - // - if(OldMainAssistName == MainAssistName) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); - - DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; - - das->DelegateAbility = 0; - - das->MemberNumber = 0; - - das->Action = 1; - - das->EntityID = 0; - - strn0cpy(das->Name, OldMainAssistName, sizeof(das->Name)); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - { - members[i]->CastToClient()->QueuePacket(outapp); - members[i]->CastToClient()->UpdateXTargetType(GroupAssist, nullptr, ""); - } - - safe_delete(outapp); - - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET assist='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group main assist: %s\n", errbuff); - - safe_delete_array(Query); - - if(!toggle) - { - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - NotifyMainAssist(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(GroupAssistTarget, nullptr); - } - } - } - - SetMainAssist(""); - } -} - -void Group::UnDelegatePuller(const char *OldPullerName, uint8 toggle) -{ - // Called when the group Leader removes the Puller delegation. Sends a packet to each group member in the zone - // informing them of the change and update the group_leaders table. - // - if(OldPullerName == PullerName) { - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET puller='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group main puller: %s\n", errbuff); - - safe_delete_array(Query); - - if(!toggle) { - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { - if(members[i] && members[i]->IsClient()) - { - NotifyPuller(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(Puller, nullptr, ""); - members[i]->CastToClient()->UpdateXTargetType(PullerTarget, nullptr); - } - } - } - - SetPuller(""); - } -} - -bool Group::IsNPCMarker(Client *c) -{ - // Returns true if the specified client has been delegated the NPC Marker Role - // - if(!c) - return false; - - if(NPCMarkerName.size()) - return(c->GetName() == NPCMarkerName); - - return false; - -} - -void Group::SetGroupAssistTarget(Mob *m) -{ - // Notify all group members in the zone of the new target the Main Assist has selected. - // - AssistTargetID = m ? m->GetID() : 0; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - NotifyAssistTarget(members[i]->CastToClient()); - } - } -} - -void Group::SetGroupTankTarget(Mob *m) -{ - TankTargetID = m ? m->GetID() : 0; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - members[i]->CastToClient()->UpdateXTargetType(GroupTankTarget, m); - } - } -} - -void Group::SetGroupPullerTarget(Mob *m) -{ - PullerTargetID = m ? m->GetID() : 0; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - members[i]->CastToClient()->UpdateXTargetType(PullerTarget, m); - } - } -} - -void Group::NotifyAssistTarget(Client *c) -{ - // Send a packet to the specified client notifying them of the group target selected by the Main Assist. - - if(!c) - return; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SetGroupTarget, sizeof(MarkNPC_Struct)); - - MarkNPC_Struct* mnpcs = (MarkNPC_Struct *)outapp->pBuffer; - - mnpcs->TargetID = AssistTargetID; - - mnpcs->Number = 0; - - c->QueuePacket(outapp); - - safe_delete(outapp); - - Mob *m = entity_list.GetMob(AssistTargetID); - - c->UpdateXTargetType(GroupAssistTarget, m); - -} - -void Group::NotifyTankTarget(Client *c) -{ - if(!c) - return; - - Mob *m = entity_list.GetMob(TankTargetID); - - c->UpdateXTargetType(GroupTankTarget, m); -} - -void Group::NotifyPullerTarget(Client *c) -{ - if(!c) - return; - - Mob *m = entity_list.GetMob(PullerTargetID); - - c->UpdateXTargetType(PullerTarget, m); -} - -void Group::DelegateMarkNPC(const char *NewNPCMarkerName) -{ - // Called when the group leader has delegated the Mark NPC ability to a group member. - // Notify all group members in the zone of the change and save the change in the group_leaders - // table to persist across zones. - // - if(NPCMarkerName.size() > 0) - UnDelegateMarkNPC(NPCMarkerName.c_str()); - - if(!NewNPCMarkerName) - return; - - SetNPCMarker(NewNPCMarkerName); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - NotifyMarkNPC(members[i]->CastToClient()); - - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET marknpc='%s' WHERE gid=%i LIMIT 1", - NewNPCMarkerName, GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group mark npc: %s\n", errbuff); - - safe_delete_array(Query); - -} - -void Group::NotifyMarkNPC(Client *c) -{ - // Notify the specified client who the group member is who has been delgated the Mark NPC ability. - - if(!c) - return; - - if(!NPCMarkerName.size()) - return; - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); - - DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; - - das->DelegateAbility = 1; - - das->MemberNumber = 0; - - das->Action = 0; - - das->EntityID = NPCMarkerID; - - strn0cpy(das->Name, NPCMarkerName.c_str(), sizeof(das->Name)); - - c->QueuePacket(outapp); - - safe_delete(outapp); - -} -void Group::SetNPCMarker(const char *NewNPCMarkerName) -{ - NPCMarkerName = NewNPCMarkerName; - - Client *m = entity_list.GetClientByName(NPCMarkerName.c_str()); - - if(!m) - NPCMarkerID = 0; - else - NPCMarkerID = m->GetID(); -} - -void Group::UnDelegateMarkNPC(const char *OldNPCMarkerName) -{ - // Notify all group members in the zone that the Mark NPC ability has been rescinded from the specified - // group member. - - if(!OldNPCMarkerName) - return; - - if(!NPCMarkerName.size()) - return; - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); - - DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; - - das->DelegateAbility = 1; - - das->MemberNumber = 0; - - das->Action = 1; - - das->EntityID = 0; - - strn0cpy(das->Name, OldNPCMarkerName, sizeof(das->Name)); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - members[i]->CastToClient()->QueuePacket(outapp); - - safe_delete(outapp); - - NPCMarkerName.clear(); - - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET marknpc='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group marknpc: %s\n", errbuff); - - safe_delete_array(Query); -} - -void Group::SaveGroupLeaderAA() -{ - // Stores the Group Leaders Leadership AA data from the Player Profile as a blob in the group_leaders table. - // This is done so that group members not in the same zone as the Leader still have access to this information. - - char *Query = new char[200 + sizeof(GroupLeadershipAA_Struct)*2]; - - char *End = Query; - - End += sprintf(End, "UPDATE group_leaders SET leadershipaa='"); - - End += database.DoEscapeString(End, (char*)&LeaderAbilities, sizeof(GroupLeadershipAA_Struct)); - - End += sprintf(End,"' WHERE gid=%i LIMIT 1", GetID()); - - char errbuff[MYSQL_ERRMSG_SIZE]; - if (!database.RunQuery(Query, End - Query, errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", errbuff); - - safe_delete_array(Query); -} - -void Group::UnMarkNPC(uint16 ID) -{ - // Called from entity_list when the mob with the specified ID is being destroyed. - // - // If the given mob has been marked by this group, it is removed from the list of marked NPCs. - // The primary reason for doing this is so that when a new group member joins or zones in, we - // send them correct details of which NPCs are currently marked. - - if(AssistTargetID == ID) - AssistTargetID = 0; - - - if(TankTargetID == ID) - TankTargetID = 0; - - if(PullerTargetID == ID) - PullerTargetID = 0; - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - { - if(MarkedNPCs[i] == ID) - { - MarkedNPCs[i] = 0; - UpdateXTargetMarkedNPC(i + 1, nullptr); - } - } -} - -void Group::SendMarkedNPCsToMember(Client *c, bool Clear) -{ - // Send the Entity IDs of the NPCs marked by the Group Leader or delegate to the specified client. - // If Clear == true, then tell the client to unmark the NPCs (when a member disbands). - // - // - if(!c) - return; - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct)); - - MarkNPC_Struct *mnpcs = (MarkNPC_Struct *)outapp->pBuffer; - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - { - if(MarkedNPCs[i]) - { - mnpcs->TargetID = MarkedNPCs[i]; - - Mob *m = entity_list.GetMob(MarkedNPCs[i]); - - if(m) - sprintf(mnpcs->Name, "%s", m->GetCleanName()); - - if(!Clear) - mnpcs->Number = i + 1; - else - mnpcs->Number = 0; - - c->QueuePacket(outapp); - c->UpdateXTargetType((mnpcs->Number == 1) ? GroupMarkTarget1 : ((mnpcs->Number == 2) ? GroupMarkTarget2 : GroupMarkTarget3), m); - } - } - - safe_delete(outapp); -} - -void Group::ClearAllNPCMarks() -{ - // This method is designed to be called when the number of members in the group drops below 3 and leadership AA - // may no longer be used. It removes all NPC marks. - // - for(uint8 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - SendMarkedNPCsToMember(members[i]->CastToClient(), true); - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - { - if(MarkedNPCs[i]) - { - Mob* m = entity_list.GetMob(MarkedNPCs[i]); - - if(m) - m->IsTargeted(-1); - } - - MarkedNPCs[i] = 0; - } - -} - -int8 Group::GetNumberNeedingHealedInGroup(int8 hpr, bool includePets) { - int8 needHealed = 0; - - for( int i = 0; iqglobal) { - - if(members[i]->GetHPRatio() <= hpr) - needHealed++; - - if(includePets) { - if(members[i]->GetPet() && members[i]->GetPet()->GetHPRatio() <= hpr) { - needHealed++; - } - } - } - } - - - return needHealed; -} - -void Group::UpdateGroupAAs() -{ - // This method updates the Groups Leadership abilities from the Player Profile of the Leader. - // - Mob *m = GetLeader(); - - if(m && m->IsClient()) - m->CastToClient()->GetGroupAAs(&LeaderAbilities); - else - memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct)); - - SaveGroupLeaderAA(); -} - -void Group::QueueHPPacketsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app) -{ - // Send a mobs HP packets to group members if the leader has the NPC Health AA and the mob is the - // target of the group's main assist, or is marked, and the member doesn't already have the mob targeted. - - if(!sender || !app || !GetLeadershipAA(groupAANPCHealth)) - return; - - uint16 SenderID = sender->GetID(); - - if(SenderID != AssistTargetID) - { - bool Marked = false; - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - { - if(MarkedNPCs[i] == SenderID) - { - Marked = true; - break; - } - } - - if(!Marked) - return; - - } - - for(unsigned int i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - { - if(!members[i]->GetTarget() || (members[i]->GetTarget()->GetID() != SenderID)) - { - members[i]->CastToClient()->QueuePacket(app); - } - } - -} - -void Group::ChangeLeader(Mob* newleader) -{ - // this changes the current group leader, notifies other members, and updates leadship AA - - // if the new leader is invalid, do nothing - if (!newleader) - return; - - Mob* oldleader = GetLeader(); - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); - GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer; - gu->action = groupActMakeLeader; - - strcpy(gu->membername, newleader->GetName()); - strcpy(gu->yourname, oldleader->GetName()); - SetLeader(newleader); - database.SetGroupLeaderName(GetID(), newleader->GetName()); - UpdateGroupAAs(); - gu->leader_aas = LeaderAbilities; - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] && members[i]->IsClient()) - { - if(members[i]->CastToClient()->GetClientVersion() >= EQClientSoD) - members[i]->CastToClient()->SendGroupLeaderChangePacket(newleader->GetName()); - - members[i]->CastToClient()->QueuePacket(outapp); - } - } - safe_delete(outapp); -} - -const char *Group::GetClientNameByIndex(uint8 index) -{ - return membername[index]; -} - -void Group::UpdateXTargetMarkedNPC(uint32 Number, Mob *m) -{ - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - members[i]->CastToClient()->UpdateXTargetType((Number == 1) ? GroupMarkTarget1 : ((Number == 2) ? GroupMarkTarget2 : GroupMarkTarget3), m); - } - } - -} - -void Group::SetMainTank(const char *NewMainTankName) -{ - MainTankName = NewMainTankName; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(!strncasecmp(membername[i], NewMainTankName, 64)) - MemberRoles[i] |= RoleTank; - else - MemberRoles[i] &= ~RoleTank; - } -} - -void Group::SetMainAssist(const char *NewMainAssistName) -{ - MainAssistName = NewMainAssistName; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(!strncasecmp(membername[i], NewMainAssistName, 64)) - MemberRoles[i] |= RoleAssist; - else - MemberRoles[i] &= ~RoleAssist; - } -} - -void Group::SetPuller(const char *NewPullerName) -{ - PullerName = NewPullerName; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(!strncasecmp(membername[i], NewPullerName, 64)) - MemberRoles[i] |= RolePuller; - else - MemberRoles[i] &= ~RolePuller; - } -} - -bool Group::HasRole(Mob *m, uint8 Role) -{ - if(!m) - return false; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if((m == members[i]) && (MemberRoles[i] & Role)) - return true; - } - return false; -} - diff --git a/zone/mob.h b/zone/mob.h index 97b75a4fb..7083e45ca 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -662,7 +662,7 @@ public: bool TryReflectSpell(uint32 spell_id); bool CanBlockSpell() const { return(spellbonuses.BlockNextSpell); } bool DoHPToManaCovert(uint16 mana_cost = 0); - int32 ApplySpellEffectiveness(int16 spell_id, int32 value, bool IsBard = false, uint16 caster_id=0); + int32 ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard = false); int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect); int32 GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg); void MeleeLifeTap(int32 damage); @@ -898,7 +898,7 @@ public: virtual int32 CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possible = 0); uint32 GetInstrumentMod(uint16 spell_id) const; - int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0,uint16 casterid=0); + int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0); int CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining = 0); virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1); uint32 GetCastedSpellInvSlot() const { return casting_spell_inventory_slot; } diff --git a/zone/mobx.cpp b/zone/mobx.cpp deleted file mode 100644 index 340dfdfea..000000000 --- a/zone/mobx.cpp +++ /dev/null @@ -1,5148 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "../common/debug.h" -#include "masterentity.h" -#include "../common/spdat.h" -#include "StringIDs.h" -#include "worldserver.h" -#include "QuestParserCollection.h" -#include "../common/StringUtil.h" - -#include -#include -#include - -extern EntityList entity_list; - -extern Zone* zone; -extern WorldServer worldserver; - -Mob::Mob(const char* in_name, - const char* in_lastname, - int32 in_cur_hp, - int32 in_max_hp, - uint8 in_gender, - uint16 in_race, - uint8 in_class, - bodyType in_bodytype, - uint8 in_deity, - uint8 in_level, - uint32 in_npctype_id, - float in_size, - float in_runspeed, - float in_heading, - float in_x_pos, - float in_y_pos, - float in_z_pos, - - uint8 in_light, - uint8 in_texture, - uint8 in_helmtexture, - uint16 in_ac, - uint16 in_atk, - uint16 in_str, - uint16 in_sta, - uint16 in_dex, - uint16 in_agi, - uint16 in_int, - uint16 in_wis, - uint16 in_cha, - uint8 in_haircolor, - uint8 in_beardcolor, - uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye? - uint8 in_eyecolor2, - uint8 in_hairstyle, - uint8 in_luclinface, - uint8 in_beard, - uint32 in_drakkin_heritage, - uint32 in_drakkin_tattoo, - uint32 in_drakkin_details, - uint32 in_armor_tint[_MaterialCount], - - uint8 in_aa_title, - uint8 in_see_invis, // see through invis/ivu - uint8 in_see_invis_undead, - uint8 in_see_hide, - uint8 in_see_improved_hide, - int32 in_hp_regen, - int32 in_mana_regen, - uint8 in_qglobal, - uint8 in_maxlevel, - uint32 in_scalerate - ) : - attack_timer(2000), - attack_dw_timer(2000), - ranged_timer(2000), - tic_timer(6000), - mana_timer(2000), - spellend_timer(0), - rewind_timer(30000), //Timer used for determining amount of time between actual player position updates for /rewind. - bindwound_timer(10000), - stunned_timer(0), - spun_timer(0), - bardsong_timer(6000), - gravity_timer(1000), - viral_timer(0), - flee_timer(FLEE_CHECK_TIMER) - -{ - targeted = 0; - tar_ndx=0; - tar_vector=0; - tar_vx=0; - tar_vy=0; - tar_vz=0; - tarx=0; - tary=0; - tarz=0; - fear_walkto_x = -999999; - fear_walkto_y = -999999; - fear_walkto_z = -999999; - curfp = false; - - AI_Init(); - SetMoving(false); - moved=false; - rewind_x = 0; //Stored x_pos for /rewind - rewind_y = 0; //Stored y_pos for /rewind - rewind_z = 0; //Stored z_pos for /rewind - move_tic_count = 0; - - _egnode = nullptr; - name[0]=0; - orig_name[0]=0; - clean_name[0]=0; - lastname[0]=0; - if(in_name) { - strn0cpy(name,in_name,64); - strn0cpy(orig_name,in_name,64); - } - if(in_lastname) - strn0cpy(lastname,in_lastname,64); - cur_hp = in_cur_hp; - max_hp = in_max_hp; - base_hp = in_max_hp; - gender = in_gender; - race = in_race; - base_gender = in_gender; - base_race = in_race; - class_ = in_class; - bodytype = in_bodytype; - orig_bodytype = in_bodytype; - deity = in_deity; - level = in_level; - orig_level = in_level; - npctype_id = in_npctype_id; - size = in_size; - base_size = size; - runspeed = in_runspeed; - - - // sanity check - if (runspeed < 0 || runspeed > 20) - runspeed = 1.25f; - - heading = in_heading; - x_pos = in_x_pos; - y_pos = in_y_pos; - z_pos = in_z_pos; - light = in_light; - texture = in_texture; - helmtexture = in_helmtexture; - haircolor = in_haircolor; - beardcolor = in_beardcolor; - eyecolor1 = in_eyecolor1; - eyecolor2 = in_eyecolor2; - hairstyle = in_hairstyle; - luclinface = in_luclinface; - beard = in_beard; - drakkin_heritage = in_drakkin_heritage; - drakkin_tattoo = in_drakkin_tattoo; - drakkin_details = in_drakkin_details; - attack_speed= 0; - slow_mitigation= 0; - findable = false; - trackable = true; - has_shieldequiped = false; - has_numhits = false; - has_MGB = false; - has_ProjectIllusion = false; - - if(in_aa_title>0) - aa_title = in_aa_title; - else - aa_title =0xFF; - AC = in_ac; - ATK = in_atk; - STR = in_str; - STA = in_sta; - DEX = in_dex; - AGI = in_agi; - INT = in_int; - WIS = in_wis; - CHA = in_cha; - MR = CR = FR = DR = PR = Corrup = 0; - - ExtraHaste = 0; - bEnraged = false; - - shield_target = nullptr; - cur_mana = 0; - max_mana = 0; - hp_regen = in_hp_regen; - mana_regen = in_mana_regen; - oocregen = RuleI(NPC, OOCRegen); //default Out of Combat Regen - maxlevel = in_maxlevel; - scalerate = in_scalerate; - invisible = false; - invisible_undead = false; - invisible_animals = false; - sneaking = false; - hidden = false; - improved_hidden = false; - invulnerable = false; - IsFullHP = (cur_hp == max_hp); - qglobal=0; - - InitializeBuffSlots(); - - // clear the proc arrays - int i; - int j; - for (j = 0; j < MAX_PROCS; j++) - { - PermaProcs[j].spellID = SPELL_UNKNOWN; - PermaProcs[j].chance = 0; - PermaProcs[j].base_spellID = SPELL_UNKNOWN; - SpellProcs[j].spellID = SPELL_UNKNOWN; - SpellProcs[j].chance = 0; - SpellProcs[j].base_spellID = SPELL_UNKNOWN; - DefensiveProcs[j].spellID = SPELL_UNKNOWN; - DefensiveProcs[j].chance = 0; - DefensiveProcs[j].base_spellID = SPELL_UNKNOWN; - RangedProcs[j].spellID = SPELL_UNKNOWN; - RangedProcs[j].chance = 0; - RangedProcs[j].base_spellID = SPELL_UNKNOWN; - SkillProcs[j].spellID = SPELL_UNKNOWN; - SkillProcs[j].chance = 0; - SkillProcs[j].base_spellID = SPELL_UNKNOWN; - } - - for (i = 0; i < _MaterialCount; i++) - { - if (in_armor_tint) - { - armor_tint[i] = in_armor_tint[i]; - } - else - { - armor_tint[i] = 0; - } - } - - delta_heading = 0; - delta_x = 0; - delta_y = 0; - delta_z = 0; - animation = 0; - - logging_enabled = false; - isgrouped = false; - israidgrouped = false; - islooting = false; - _appearance = eaStanding; - pRunAnimSpeed = 0; - - spellend_timer.Disable(); - bardsong_timer.Disable(); - bardsong = 0; - bardsong_target_id = 0; - casting_spell_id = 0; - casting_spell_timer = 0; - casting_spell_timer_duration = 0; - casting_spell_type = 0; - casting_spell_inventory_slot = 0; - target = 0; - - for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_spell_id[i] = 0; } - for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_target_id[i] = 0; } - for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_increment[i] = 0; } - for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_x[i] = 0; } - for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_y[i] = 0; } - for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { projectile_z[i] = 0; } - projectile_timer.Disable(); - - memset(&itembonuses, 0, sizeof(StatBonuses)); - memset(&spellbonuses, 0, sizeof(StatBonuses)); - memset(&aabonuses, 0, sizeof(StatBonuses)); - spellbonuses.AggroRange = -1; - spellbonuses.AssistRange = -1; - pLastChange = 0; - SetPetID(0); - SetOwnerID(0); - typeofpet = petCharmed; //default to charmed... - petpower = 0; - held = false; - nocast = false; - focused = false; - - attacked_count = 0; - mezzed = false; - stunned = false; - silenced = false; - amnesiad = false; - inWater = false; - int m; - for (m = 0; m < MAX_SHIELDERS; m++) - { - shielder[m].shielder_id = 0; - shielder[m].shielder_bonus = 0; - } - - destructibleobject = false; - wandertype=0; - pausetype=0; - cur_wp = 0; - cur_wp_x = 0; - cur_wp_y = 0; - cur_wp_z = 0; - cur_wp_pause = 0; - patrol=0; - follow=0; - follow_dist = 100; // Default Distance for Follow - flee_mode = false; - fear_walkto_x = -999999; - fear_walkto_y = -999999; - fear_walkto_z = -999999; - curfp = false; - flee_timer.Start(); - - permarooted = (runspeed > 0) ? false : true; - - movetimercompleted = false; - roamer = false; - rooted = false; - charmed = false; - has_virus = false; - for (i=0; iCharmed()) - GetPet()->BuffFadeByEffect(SE_Charm); - else - SetPet(0); - } - - EQApplicationPacket app; - CreateDespawnPacket(&app, !IsCorpse()); - Corpse* corpse = entity_list.GetCorpseByID(GetID()); - if(!corpse || (corpse && !corpse->IsPlayerCorpse())) - entity_list.QueueClients(this, &app, true); - - entity_list.RemoveFromTargets(this, true); - - if(trade) { - Mob *with = trade->With(); - if(with && with->IsClient()) { - with->CastToClient()->FinishTrade(with); - with->trade->Reset(); - } - delete trade; - } - - if(HadTempPets()){ - entity_list.DestroyTempPets(this); - } - entity_list.UnMarkNPC(GetID()); - safe_delete(PathingLOSCheckTimer); - safe_delete(PathingRouteUpdateTimerShort); - safe_delete(PathingRouteUpdateTimerLong); - UninitializeBuffSlots(); -} - -uint32 Mob::GetAppearanceValue(EmuAppearance iAppearance) { - switch (iAppearance) { - // 0 standing, 1 sitting, 2 ducking, 3 lieing down, 4 looting - case eaStanding: { - return ANIM_STAND; - } - case eaSitting: { - return ANIM_SIT; - } - case eaCrouching: { - return ANIM_CROUCH; - } - case eaDead: { - return ANIM_DEATH; - } - case eaLooting: { - return ANIM_LOOT; - } - //to shup up compiler: - case _eaMaxAppearance: - break; - } - return(ANIM_STAND); -} - -void Mob::SetInvisible(uint8 state) -{ - invisible = state; - SendAppearancePacket(AT_Invis, invisible); - // Invis and hide breaks charms - - if ((this->GetPetType() == petCharmed) && (invisible || hidden || improved_hidden)) - { - Mob* formerpet = this->GetPet(); - - if(formerpet) - formerpet->BuffFadeByEffect(SE_Charm); - } -} - -//check to see if `this` is invisible to `other` -bool Mob::IsInvisible(Mob* other) const -{ - if(!other) - return(false); - - uint8 SeeInvisBonus = 0; - if (IsClient()) - SeeInvisBonus = aabonuses.SeeInvis; - - //check regular invisibility - if (invisible && invisible > (other->SeeInvisible())) - return true; - - //check invis vs. undead - if (other->GetBodyType() == BT_Undead || other->GetBodyType() == BT_SummonedUndead) { - if(invisible_undead && !other->SeeInvisibleUndead()) - return true; - } - - //check invis vs. animals... - if (other->GetBodyType() == BT_Animal){ - if(invisible_animals && !other->SeeInvisible()) - return true; - } - - if(hidden){ - if(!other->see_hide && !other->see_improved_hide){ - return true; - } - } - - if(improved_hidden){ - if(!other->see_improved_hide){ - return true; - } - } - - //handle sneaking - if(sneaking) { - if(BehindMob(other, GetX(), GetY()) ) - return true; - } - - return(false); -} - -float Mob::_GetMovementSpeed(int mod) const -{ - // List of movement speed modifiers, including AAs & spells: - // http://everquest.allakhazam.com/db/item.html?item=1721;page=1;howmany=50#m10822246245352 - if (IsRooted()) - return 0.0f; - - float speed_mod = runspeed; - - // These two cases ignore the cap, be wise in the DB for horses. - if (IsClient()) { - if (CastToClient()->GetGMSpeed()) { - speed_mod = 3.125f; - if (mod != 0) - speed_mod += speed_mod * static_cast(mod) / 100.0f; - return speed_mod; - } else { - Mob *horse = entity_list.GetMob(CastToClient()->GetHorseId()); - if (horse) { - speed_mod = horse->GetBaseRunspeed(); - if (mod != 0) - speed_mod += speed_mod * static_cast(mod) / 100.0f; - return speed_mod; - } - } - } - - int aa_mod = 0; - int spell_mod = 0; - int runspeedcap = RuleI(Character,BaseRunSpeedCap); - int movemod = 0; - float frunspeedcap = 0.0f; - - runspeedcap += itembonuses.IncreaseRunSpeedCap + spellbonuses.IncreaseRunSpeedCap + aabonuses.IncreaseRunSpeedCap; - aa_mod += itembonuses.BaseMovementSpeed + spellbonuses.BaseMovementSpeed + aabonuses.BaseMovementSpeed; - spell_mod += spellbonuses.movementspeed + itembonuses.movementspeed; - - // hard cap - if (runspeedcap > 225) - runspeedcap = 225; - - if (spell_mod < 0) - movemod += spell_mod; - else if (spell_mod > aa_mod) - movemod = spell_mod; - else - movemod = aa_mod; - - // cap negative movemods from snares mostly - if (movemod < -85) - movemod = -85; - - if (movemod != 0) - speed_mod += speed_mod * static_cast(movemod) / 100.0f; - - // runspeed caps - frunspeedcap = static_cast(runspeedcap) / 100.0f; - if (IsClient() && speed_mod > frunspeedcap) - speed_mod = frunspeedcap; - - // apply final mod such as the -47 for walking - // use runspeed since it should stack with snares - // and if we get here, we know runspeed was the initial - // value before we applied movemod. - if (mod != 0) - speed_mod += runspeed * static_cast(mod) / 100.0f; - - if (speed_mod <= 0.0f) - speed_mod = IsClient() ? 0.0001f : 0.0f; - - return speed_mod; -} - -int32 Mob::CalcMaxMana() { - switch (GetCasterClass()) { - case 'I': - max_mana = (((GetINT()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana; - break; - case 'W': - max_mana = (((GetWIS()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana; - break; - case 'N': - default: - max_mana = 0; - break; - } - if (max_mana < 0) { - max_mana = 0; - } - - return max_mana; -} - -int32 Mob::CalcMaxHP() { - max_hp = (base_hp + itembonuses.HP + spellbonuses.HP); - max_hp += max_hp * ((aabonuses.MaxHPChange + spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f); - return max_hp; -} - -int32 Mob::GetItemHPBonuses() { - int32 item_hp = 0; - item_hp = itembonuses.HP; - item_hp += item_hp * itembonuses.MaxHPChange / 10000; - return item_hp; -} - -int32 Mob::GetSpellHPBonuses() { - int32 spell_hp = 0; - spell_hp = spellbonuses.HP; - spell_hp += spell_hp * spellbonuses.MaxHPChange / 10000; - return spell_hp; -} - -char Mob::GetCasterClass() const { - switch(class_) - { - case CLERIC: - case PALADIN: - case RANGER: - case DRUID: - case SHAMAN: - case BEASTLORD: - case CLERICGM: - case PALADINGM: - case RANGERGM: - case DRUIDGM: - case SHAMANGM: - case BEASTLORDGM: - return 'W'; - break; - - case SHADOWKNIGHT: - case BARD: - case NECROMANCER: - case WIZARD: - case MAGICIAN: - case ENCHANTER: - case SHADOWKNIGHTGM: - case BARDGM: - case NECROMANCERGM: - case WIZARDGM: - case MAGICIANGM: - case ENCHANTERGM: - return 'I'; - break; - - default: - return 'N'; - break; - } -} - -uint8 Mob::GetArchetype() const { - switch(class_) - { - case PALADIN: - case RANGER: - case SHADOWKNIGHT: - case BARD: - case BEASTLORD: - case PALADINGM: - case RANGERGM: - case SHADOWKNIGHTGM: - case BARDGM: - case BEASTLORDGM: - return ARCHETYPE_HYBRID; - break; - case CLERIC: - case DRUID: - case SHAMAN: - case NECROMANCER: - case WIZARD: - case MAGICIAN: - case ENCHANTER: - case CLERICGM: - case DRUIDGM: - case SHAMANGM: - case NECROMANCERGM: - case WIZARDGM: - case MAGICIANGM: - case ENCHANTERGM: - return ARCHETYPE_CASTER; - break; - case WARRIOR: - case MONK: - case ROGUE: - case BERSERKER: - case WARRIORGM: - case MONKGM: - case ROGUEGM: - case BERSERKERGM: - return ARCHETYPE_MELEE; - break; - default: - return ARCHETYPE_HYBRID; - break; - } -} - -void Mob::CreateSpawnPacket(EQApplicationPacket* app, Mob* ForWho) { - app->SetOpcode(OP_NewSpawn); - app->size = sizeof(NewSpawn_Struct); - app->pBuffer = new uchar[app->size]; - memset(app->pBuffer, 0, app->size); - NewSpawn_Struct* ns = (NewSpawn_Struct*)app->pBuffer; - FillSpawnStruct(ns, ForWho); - - if(strlen(ns->spawn.lastName) == 0) { - switch(ns->spawn.class_) - { - case TRIBUTE_MASTER: - strcpy(ns->spawn.lastName, "Tribute Master"); - break; - case ADVENTURERECRUITER: - strcpy(ns->spawn.lastName, "Adventure Recruiter"); - break; - case BANKER: - strcpy(ns->spawn.lastName, "Banker"); - break; - case ADVENTUREMERCHANT: - strcpy(ns->spawn.lastName,"Adventure Merchant"); - break; - case WARRIORGM: - strcpy(ns->spawn.lastName, "GM Warrior"); - break; - case PALADINGM: - strcpy(ns->spawn.lastName, "GM Paladin"); - break; - case RANGERGM: - strcpy(ns->spawn.lastName, "GM Ranger"); - break; - case SHADOWKNIGHTGM: - strcpy(ns->spawn.lastName, "GM Shadowknight"); - break; - case DRUIDGM: - strcpy(ns->spawn.lastName, "GM Druid"); - break; - case BARDGM: - strcpy(ns->spawn.lastName, "GM Bard"); - break; - case ROGUEGM: - strcpy(ns->spawn.lastName, "GM Rogue"); - break; - case SHAMANGM: - strcpy(ns->spawn.lastName, "GM Shaman"); - break; - case NECROMANCERGM: - strcpy(ns->spawn.lastName, "GM Necromancer"); - break; - case WIZARDGM: - strcpy(ns->spawn.lastName, "GM Wizard"); - break; - case MAGICIANGM: - strcpy(ns->spawn.lastName, "GM Magician"); - break; - case ENCHANTERGM: - strcpy(ns->spawn.lastName, "GM Enchanter"); - break; - case BEASTLORDGM: - strcpy(ns->spawn.lastName, "GM Beastlord"); - break; - case BERSERKERGM: - strcpy(ns->spawn.lastName, "GM Berserker"); - break; - case MERCERNARY_MASTER: - strcpy(ns->spawn.lastName, "Mercenary Recruiter"); - break; - default: - break; - } - } -} - -void Mob::CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns) { - app->SetOpcode(OP_NewSpawn); - app->size = sizeof(NewSpawn_Struct); - - app->pBuffer = new uchar[sizeof(NewSpawn_Struct)]; - - // Copy ns directly into packet - memcpy(app->pBuffer, ns, sizeof(NewSpawn_Struct)); - - // Custom packet data - NewSpawn_Struct* ns2 = (NewSpawn_Struct*)app->pBuffer; - strcpy(ns2->spawn.name, ns->spawn.name); - switch(ns->spawn.class_) - { - case TRIBUTE_MASTER: - strcpy(ns2->spawn.lastName, "Tribute Master"); - break; - case ADVENTURERECRUITER: - strcpy(ns2->spawn.lastName, "Adventure Recruiter"); - break; - case BANKER: - strcpy(ns2->spawn.lastName, "Banker"); - break; - case ADVENTUREMERCHANT: - strcpy(ns->spawn.lastName,"Adventure Merchant"); - break; - case WARRIORGM: - strcpy(ns2->spawn.lastName, "GM Warrior"); - break; - case PALADINGM: - strcpy(ns2->spawn.lastName, "GM Paladin"); - break; - case RANGERGM: - strcpy(ns2->spawn.lastName, "GM Ranger"); - break; - case SHADOWKNIGHTGM: - strcpy(ns2->spawn.lastName, "GM Shadowknight"); - break; - case DRUIDGM: - strcpy(ns2->spawn.lastName, "GM Druid"); - break; - case BARDGM: - strcpy(ns2->spawn.lastName, "GM Bard"); - break; - case ROGUEGM: - strcpy(ns2->spawn.lastName, "GM Rogue"); - break; - case SHAMANGM: - strcpy(ns2->spawn.lastName, "GM Shaman"); - break; - case NECROMANCERGM: - strcpy(ns2->spawn.lastName, "GM Necromancer"); - break; - case WIZARDGM: - strcpy(ns2->spawn.lastName, "GM Wizard"); - break; - case MAGICIANGM: - strcpy(ns2->spawn.lastName, "GM Magician"); - break; - case ENCHANTERGM: - strcpy(ns2->spawn.lastName, "GM Enchanter"); - break; - case BEASTLORDGM: - strcpy(ns2->spawn.lastName, "GM Beastlord"); - break; - case BERSERKERGM: - strcpy(ns2->spawn.lastName, "GM Berserker"); - break; - case MERCERNARY_MASTER: - strcpy(ns->spawn.lastName, "Mercenary Recruiter"); - break; - default: - strcpy(ns2->spawn.lastName, ns->spawn.lastName); - break; - } - - memset(&app->pBuffer[sizeof(Spawn_Struct)-7], 0xFF, 7); -} - -void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) -{ - int i; - - strcpy(ns->spawn.name, name); - if(IsClient()) { - strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName)); - } - - ns->spawn.heading = FloatToEQ19(heading); - ns->spawn.x = FloatToEQ19(x_pos);//((int32)x_pos)<<3; - ns->spawn.y = FloatToEQ19(y_pos);//((int32)y_pos)<<3; - ns->spawn.z = FloatToEQ19(z_pos);//((int32)z_pos)<<3; - ns->spawn.spawnId = GetID(); - ns->spawn.curHp = static_cast(GetHPRatio()); - ns->spawn.max_hp = 100; //this field needs a better name - ns->spawn.race = race; - ns->spawn.runspeed = runspeed; - ns->spawn.walkspeed = runspeed * 0.5f; - ns->spawn.class_ = class_; - ns->spawn.gender = gender; - ns->spawn.level = level; - ns->spawn.deity = deity; - ns->spawn.animation = 0; - ns->spawn.findable = findable?1:0; - ns->spawn.light = light; - ns->spawn.showhelm = 1; - - ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players - ns->spawn.NPC = IsClient() ? 0 : 1; - ns->spawn.IsMercenary = (IsMerc() || no_target_hotkey) ? 1 : 0; - - ns->spawn.petOwnerId = ownerid; - - ns->spawn.haircolor = haircolor; - ns->spawn.beardcolor = beardcolor; - ns->spawn.eyecolor1 = eyecolor1; - ns->spawn.eyecolor2 = eyecolor2; - ns->spawn.hairstyle = hairstyle; - ns->spawn.face = luclinface; - ns->spawn.beard = beard; - ns->spawn.StandState = GetAppearanceValue(_appearance); - ns->spawn.drakkin_heritage = drakkin_heritage; - ns->spawn.drakkin_tattoo = drakkin_tattoo; - ns->spawn.drakkin_details = drakkin_details; - ns->spawn.equip_chest2 = texture; - -// ns->spawn.invis2 = 0xff;//this used to be labeled beard.. if its not FF it will turn mob invis - - if(helmtexture && helmtexture != 0xFF) - { - ns->spawn.helm=helmtexture; - } else { - ns->spawn.helm = 0; - } - - ns->spawn.guildrank = 0xFF; - ns->spawn.size = size; - ns->spawn.bodytype = bodytype; - // The 'flymode' settings have the following effect: - // 0 - Mobs in water sink like a stone to the bottom - // 1 - Same as #flymode 1 - // 2 - Same as #flymode 2 - // 3 - Mobs in water do not sink. A value of 3 in this field appears to be the default setting for all mobs - // (in water or not) according to 6.2 era packet collects. - if(IsClient()) - { - ns->spawn.flymode = FindType(SE_Levitate) ? 2 : 0; - } - else - ns->spawn.flymode = flymode; - - ns->spawn.lastName[0] = '\0'; - - strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName)); - - for(i = 0; i < _MaterialCount; i++) - { - ns->spawn.equipment[i] = GetEquipmentMaterial(i); - if (armor_tint[i]) - { - ns->spawn.colors[i].color = armor_tint[i]; - } - else - { - ns->spawn.colors[i].color = GetEquipmentColor(i); - } - } - - memset(ns->spawn.set_to_0xFF, 0xFF, sizeof(ns->spawn.set_to_0xFF)); - if(IsNPC() && IsDestructibleObject()) - { - ns->spawn.DestructibleObject = true; - - // Changing the first string made it vanish, so it has some significance. - if(lastname) - sprintf(ns->spawn.DestructibleModel, "%s", lastname); - // Changing the second string made no visible difference - sprintf(ns->spawn.DestructibleName2, "%s", ns->spawn.name); - // Putting a string in the final one that was previously empty had no visible effect. - sprintf(ns->spawn.DestructibleString, ""); - - // Sets damage appearance level of the object. - ns->spawn.DestructibleAppearance = luclinface; // Was 0x00000000 - //ns->spawn.DestructibleAppearance = static_cast(_appearance); - // #appearance 44 1 makes it jump but no visible damage - // #appearance 44 2 makes it look completely broken but still visible - // #appearnace 44 3 makes it jump but not visible difference to 3 - // #appearance 44 4 makes it disappear altogether - // #appearance 44 5 makes the client crash. - - ns->spawn.DestructibleUnk1 = 0x00000224; // Was 0x000001f5; - // These next 4 are mostly always sequential - // Originally they were 633, 634, 635, 636 - // Changing them all to 633 - no visible effect. - // Changing them all to 636 - no visible effect. - // Reversing the order of these four numbers and then using #appearance gain had no visible change. - // Setting these four ids to zero had no visible effect when the catapult spawned, nor when #appearance was used. - ns->spawn.DestructibleID1 = 1968; - ns->spawn.DestructibleID2 = 1969; - ns->spawn.DestructibleID3 = 1970; - ns->spawn.DestructibleID4 = 1971; - // Next one was originally 0x1ce45008, changing it to 0x00000000 made no visible difference - ns->spawn.DestructibleUnk2 = 0x13f79d00; - // Next one was originally 0x1a68fe30, changing it to 0x00000000 made no visible difference - ns->spawn.DestructibleUnk3 = 0x00000000; - // Next one was already 0x00000000 - ns->spawn.DestructibleUnk4 = 0x13f79d58; - // Next one was originally 0x005a69ec, changing it to 0x00000000 made no visible difference. - ns->spawn.DestructibleUnk5 = 0x13c55b00; - // Next one was originally 0x1a68fe30, changing it to 0x00000000 made no visible difference. - ns->spawn.DestructibleUnk6 = 0x00128860; - // Next one was originally 0x0059de6d, changing it to 0x00000000 made no visible difference. - ns->spawn.DestructibleUnk7 = 0x005a8f66; - // Next one was originally 0x00000201, changing it to 0x00000000 made no visible difference. - // For the Minohten tents, 0x00000000 had them up in the air, while 0x201 put them on the ground. - // Changing it it 0x00000001 makes the tent sink into the ground. - ns->spawn.DestructibleUnk8 = 0x01; // Needs to be 1 for tents? - ns->spawn.DestructibleUnk9 = 0x00000002; // Needs to be 2 for tents? - - ns->spawn.flymode = 0; - } -} - -void Mob::CreateDespawnPacket(EQApplicationPacket* app, bool Decay) -{ - app->SetOpcode(OP_DeleteSpawn); - app->size = sizeof(DeleteSpawn_Struct); - app->pBuffer = new uchar[app->size]; - memset(app->pBuffer, 0, app->size); - DeleteSpawn_Struct* ds = (DeleteSpawn_Struct*)app->pBuffer; - ds->spawn_id = GetID(); - // The next field only applies to corpses. If 0, they vanish instantly, otherwise they 'decay' - ds->Decay = Decay ? 1 : 0; -} - -void Mob::CreateHPPacket(EQApplicationPacket* app) -{ - this->IsFullHP=(cur_hp>=max_hp); - app->SetOpcode(OP_MobHealth); - app->size = sizeof(SpawnHPUpdate_Struct2); - app->pBuffer = new uchar[app->size]; - memset(app->pBuffer, 0, sizeof(SpawnHPUpdate_Struct2)); - SpawnHPUpdate_Struct2* ds = (SpawnHPUpdate_Struct2*)app->pBuffer; - - ds->spawn_id = GetID(); - // they don't need to know the real hp - ds->hp = (int)GetHPRatio(); - - // hp event - if (IsNPC() && (GetNextHPEvent() > 0)) - { - if (ds->hp < GetNextHPEvent()) - { - char buf[10]; - snprintf(buf, 9, "%i", GetNextHPEvent()); - buf[9] = '\0'; - SetNextHPEvent(-1); - parse->EventNPC(EVENT_HP, CastToNPC(), nullptr, buf, 0); - } - } - - if (IsNPC() && (GetNextIncHPEvent() > 0)) - { - if (ds->hp > GetNextIncHPEvent()) - { - char buf[10]; - snprintf(buf, 9, "%i", GetNextIncHPEvent()); - buf[9] = '\0'; - SetNextIncHPEvent(-1); - parse->EventNPC(EVENT_HP, CastToNPC(), nullptr, buf, 1); - } - } -} - -// sends hp update of this mob to people who might care -void Mob::SendHPUpdate() -{ - EQApplicationPacket hp_app; - Group *group; - - // destructor will free the pBuffer - CreateHPPacket(&hp_app); - - // send to people who have us targeted - entity_list.QueueClientsByTarget(this, &hp_app, false, 0, false, true, BIT_AllClients); - entity_list.QueueClientsByXTarget(this, &hp_app, false); - entity_list.QueueToGroupsForNPCHealthAA(this, &hp_app); - - // send to group - if(IsGrouped()) - { - group = entity_list.GetGroupByMob(this); - if(group) //not sure why this might be null, but it happens - group->SendHPPacketsFrom(this); - } - - if(IsClient()){ - Raid *r = entity_list.GetRaidByClient(CastToClient()); - if(r){ - r->SendHPPacketsFrom(this); - } - } - - // send to master - if(GetOwner() && GetOwner()->IsClient()) - { - GetOwner()->CastToClient()->QueuePacket(&hp_app, false); - group = entity_list.GetGroupByClient(GetOwner()->CastToClient()); - if(group) - group->SendHPPacketsFrom(this); - Raid *r = entity_list.GetRaidByClient(GetOwner()->CastToClient()); - if(r) - r->SendHPPacketsFrom(this); - } - - // send to pet - if(GetPet() && GetPet()->IsClient()) - { - GetPet()->CastToClient()->QueuePacket(&hp_app, false); - } - - // Update the damage state of destructible objects - if(IsNPC() && IsDestructibleObject()) - { - if (GetHPRatio() > 74) - { - if (GetAppearance() != eaStanding) - { - SendAppearancePacket(AT_DamageState, eaStanding); - _appearance = eaStanding; - } - } - else if (GetHPRatio() > 49) - { - if (GetAppearance() != eaSitting) - { - SendAppearancePacket(AT_DamageState, eaSitting); - _appearance = eaSitting; - } - } - else if (GetHPRatio() > 24) - { - if (GetAppearance() != eaCrouching) - { - SendAppearancePacket(AT_DamageState, eaCrouching); - _appearance = eaCrouching; - } - } - else if (GetHPRatio() > 0) - { - if (GetAppearance() != eaDead) - { - SendAppearancePacket(AT_DamageState, eaDead); - _appearance = eaDead; - } - } - else if (GetAppearance() != eaLooting) - { - SendAppearancePacket(AT_DamageState, eaLooting); - _appearance = eaLooting; - } - } - - // send to self - we need the actual hps here - if(IsClient()) - { - EQApplicationPacket* hp_app2 = new EQApplicationPacket(OP_HPUpdate,sizeof(SpawnHPUpdate_Struct)); - SpawnHPUpdate_Struct* ds = (SpawnHPUpdate_Struct*)hp_app2->pBuffer; - ds->cur_hp = CastToClient()->GetHP() - itembonuses.HP; - ds->spawn_id = GetID(); - ds->max_hp = CastToClient()->GetMaxHP() - itembonuses.HP; - CastToClient()->QueuePacket(hp_app2); - safe_delete(hp_app2); - } -} - -// this one just warps the mob to the current location -void Mob::SendPosition() -{ - EQApplicationPacket* app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); - PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; - MakeSpawnUpdateNoDelta(spu); - move_tic_count = 0; - entity_list.QueueClients(this, app, true); - safe_delete(app); -} - -// this one is for mobs on the move, with deltas - this makes them walk -void Mob::SendPosUpdate(uint8 iSendToSelf) { - EQApplicationPacket* app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); - PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; - MakeSpawnUpdate(spu); - - if (iSendToSelf == 2) { - if (this->IsClient()) - this->CastToClient()->FastQueuePacket(&app,false); - } - else - { - if(move_tic_count == RuleI(Zone, NPCPositonUpdateTicCount)) - { - entity_list.QueueClients(this, app, (iSendToSelf==0), false); - move_tic_count = 0; - } - else - { - entity_list.QueueCloseClients(this, app, (iSendToSelf==0), 800, nullptr, false); - move_tic_count++; - } - } - safe_delete(app); -} - -// this is for SendPosition() -void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu){ - memset(spu,0xff,sizeof(PlayerPositionUpdateServer_Struct)); - spu->spawn_id = GetID(); - spu->x_pos = FloatToEQ19(x_pos); - spu->y_pos = FloatToEQ19(y_pos); - spu->z_pos = FloatToEQ19(z_pos); - spu->delta_x = NewFloatToEQ13(0); - spu->delta_y = NewFloatToEQ13(0); - spu->delta_z = NewFloatToEQ13(0); - spu->heading = FloatToEQ19(heading); - spu->animation = 0; - spu->delta_heading = NewFloatToEQ13(0); - spu->padding0002 =0; - spu->padding0006 =7; - spu->padding0014 =0x7f; - spu->padding0018 =0x5df27; - -} - -// this is for SendPosUpdate() -void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) { - spu->spawn_id = GetID(); - spu->x_pos = FloatToEQ19(x_pos); - spu->y_pos = FloatToEQ19(y_pos); - spu->z_pos = FloatToEQ19(z_pos); - spu->delta_x = NewFloatToEQ13(delta_x); - spu->delta_y = NewFloatToEQ13(delta_y); - spu->delta_z = NewFloatToEQ13(delta_z); - spu->heading = FloatToEQ19(heading); - spu->padding0002 =0; - spu->padding0006 =7; - spu->padding0014 =0x7f; - spu->padding0018 =0x5df27; - if(this->IsClient()) - spu->animation = animation; - else - spu->animation = pRunAnimSpeed;//animation; - spu->delta_heading = NewFloatToEQ13(static_cast(delta_heading)); -} - -void Mob::ShowStats(Client* client) -{ - if (IsClient()) { - CastToClient()->SendStatsWindow(client, RuleB(Character, UseNewStatsWindow)); - } - else if (IsCorpse()) { - if (IsPlayerCorpse()) { - client->Message(0, " CharID: %i PlayerCorpse: %i", CastToCorpse()->GetCharID(), CastToCorpse()->GetDBID()); - } - else { - client->Message(0, " NPCCorpse", GetID()); - } - } - else { - client->Message(0, " Level: %i AC: %i Class: %i Size: %1.1f Haste: %i", GetLevel(), GetAC(), GetClass(), GetSize(), GetHaste()); - client->Message(0, " HP: %i Max HP: %i",GetHP(), GetMaxHP()); - client->Message(0, " Mana: %i Max Mana: %i", GetMana(), GetMaxMana()); - client->Message(0, " Total ATK: %i Worn/Spell ATK (Cap %i): %i", GetATK(), RuleI(Character, ItemATKCap), GetATKBonus()); - client->Message(0, " STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA()); - client->Message(0, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup()); - client->Message(0, " Race: %i BaseRace: %i Texture: %i HelmTexture: %i Gender: %i BaseGender: %i", GetRace(), GetBaseRace(), GetTexture(), GetHelmTexture(), GetGender(), GetBaseGender()); - if (client->Admin() >= 100) - client->Message(0, " EntityID: %i PetID: %i OwnerID: %i AIControlled: %i Targetted: %i", GetID(), GetPetID(), GetOwnerID(), IsAIControlled(), targeted); - - if (IsNPC()) { - NPC *n = CastToNPC(); - uint32 spawngroupid = 0; - if(n->respawn2 != 0) - spawngroupid = n->respawn2->SpawnGroupID(); - client->Message(0, " NPCID: %u SpawnGroupID: %u Grid: %i LootTable: %u FactionID: %i SpellsID: %u ", GetNPCTypeID(),spawngroupid, n->GetGrid(), n->GetLoottableID(), n->GetNPCFactionID(), n->GetNPCSpellsID()); - client->Message(0, " Accuracy: %i MerchantID: %i EmoteID: %i Runspeed: %f Walkspeed: %f", n->GetAccuracyRating(), n->MerchantType, n->GetEmoteID(), n->GetRunspeed(), n->GetWalkspeed()); - n->QueryLoot(client); - } - if (IsAIControlled()) { - client->Message(0, " AggroRange: %1.0f AssistRange: %1.0f", GetAggroRange(), GetAssistRange()); - } - } -} - -void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); - Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer; - anim->spawnid = GetID(); - if(type == 0){ - anim->action = 10; - anim->value=animnum; - } - else{ - anim->action = animnum; - anim->value=type; - } - entity_list.QueueCloseClients(this, outapp, false, 200, 0, ackreq, filter); - safe_delete(outapp); -} - -void Mob::ShowBuffs(Client* client) { - if(SPDAT_RECORDS <= 0) - return; - client->Message(0, "Buffs on: %s", this->GetName()); - uint32 i; - uint32 buff_count = GetMaxTotalSlots(); - for (i=0; i < buff_count; i++) { - if (buffs[i].spellid != SPELL_UNKNOWN) { - if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) - client->Message(0, " %i: %s: Permanent", i, spells[buffs[i].spellid].name); - else - client->Message(0, " %i: %s: %i tics left", i, spells[buffs[i].spellid].name, buffs[i].ticsremaining); - - } - } - if (IsClient()){ - client->Message(0, "itembonuses:"); - client->Message(0, "Atk:%i Ac:%i HP(%i):%i Mana:%i", itembonuses.ATK, itembonuses.AC, itembonuses.HPRegen, itembonuses.HP, itembonuses.Mana); - client->Message(0, "Str:%i Sta:%i Dex:%i Agi:%i Int:%i Wis:%i Cha:%i", - itembonuses.STR,itembonuses.STA,itembonuses.DEX,itembonuses.AGI,itembonuses.INT,itembonuses.WIS,itembonuses.CHA); - client->Message(0, "SvMagic:%i SvFire:%i SvCold:%i SvPoison:%i SvDisease:%i", - itembonuses.MR,itembonuses.FR,itembonuses.CR,itembonuses.PR,itembonuses.DR); - client->Message(0, "DmgShield:%i Haste:%i", itembonuses.DamageShield, itembonuses.haste ); - client->Message(0, "spellbonuses:"); - client->Message(0, "Atk:%i Ac:%i HP(%i):%i Mana:%i", spellbonuses.ATK, spellbonuses.AC, spellbonuses.HPRegen, spellbonuses.HP, spellbonuses.Mana); - client->Message(0, "Str:%i Sta:%i Dex:%i Agi:%i Int:%i Wis:%i Cha:%i", - spellbonuses.STR,spellbonuses.STA,spellbonuses.DEX,spellbonuses.AGI,spellbonuses.INT,spellbonuses.WIS,spellbonuses.CHA); - client->Message(0, "SvMagic:%i SvFire:%i SvCold:%i SvPoison:%i SvDisease:%i", - spellbonuses.MR,spellbonuses.FR,spellbonuses.CR,spellbonuses.PR,spellbonuses.DR); - client->Message(0, "DmgShield:%i Haste:%i", spellbonuses.DamageShield, spellbonuses.haste ); - } -} - -void Mob::ShowBuffList(Client* client) { - if(SPDAT_RECORDS <= 0) - return; - - client->Message(0, "Buffs on: %s", this->GetCleanName()); - uint32 i; - uint32 buff_count = GetMaxTotalSlots(); - for (i=0; i < buff_count; i++) { - if (buffs[i].spellid != SPELL_UNKNOWN) { - if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) - client->Message(0, " %i: %s: Permanent", i, spells[buffs[i].spellid].name); - else - client->Message(0, " %i: %s: %i tics left", i, spells[buffs[i].spellid].name, buffs[i].ticsremaining); - } - } -} - -void Mob::GMMove(float x, float y, float z, float heading, bool SendUpdate) { - - Route.clear(); - - if(IsNPC()) { - entity_list.ProcessMove(CastToNPC(), x, y, z); - } - - x_pos = x; - y_pos = y; - z_pos = z; - if (heading != 0.01) - this->heading = heading; - if(IsNPC()) - CastToNPC()->SaveGuardSpot(true); - if(SendUpdate) - SendPosition(); -} - -void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture, uint8 in_helmtexture, uint8 in_haircolor, uint8 in_beardcolor, uint8 in_eyecolor1, uint8 in_eyecolor2, uint8 in_hairstyle, uint8 in_luclinface, uint8 in_beard, uint8 in_aa_title, uint32 in_drakkin_heritage, uint32 in_drakkin_tattoo, uint32 in_drakkin_details, float in_size) { - - uint16 BaseRace = GetBaseRace(); - - if (in_race == 0) { - this->race = BaseRace; - if (in_gender == 0xFF) - this->gender = GetBaseGender(); - else - this->gender = in_gender; - } - else { - this->race = in_race; - if (in_gender == 0xFF) { - uint8 tmp = Mob::GetDefaultGender(this->race, gender); - if (tmp == 2) - gender = 2; - else if (gender == 2 && GetBaseGender() == 2) - gender = tmp; - else if (gender == 2) - gender = GetBaseGender(); - } - else - gender = in_gender; - } - if (in_texture == 0xFF) { - if (in_race <= 12 || in_race == 128 || in_race == 130 || in_race == 330 || in_race == 522) - this->texture = 0xFF; - else - this->texture = GetTexture(); - } - else - this->texture = in_texture; - - if (in_helmtexture == 0xFF) { - if (in_race <= 12 || in_race == 128 || in_race == 130 || in_race == 330 || in_race == 522) - this->helmtexture = 0xFF; - else if (in_texture != 0xFF) - this->helmtexture = in_texture; - else - this->helmtexture = GetHelmTexture(); - } - else - this->helmtexture = in_helmtexture; - - if (in_haircolor == 0xFF) - this->haircolor = GetHairColor(); - else - this->haircolor = in_haircolor; - - if (in_beardcolor == 0xFF) - this->beardcolor = GetBeardColor(); - else - this->beardcolor = in_beardcolor; - - if (in_eyecolor1 == 0xFF) - this->eyecolor1 = GetEyeColor1(); - else - this->eyecolor1 = in_eyecolor1; - - if (in_eyecolor2 == 0xFF) - this->eyecolor2 = GetEyeColor2(); - else - this->eyecolor2 = in_eyecolor2; - - if (in_hairstyle == 0xFF) - this->hairstyle = GetHairStyle(); - else - this->hairstyle = in_hairstyle; - - if (in_luclinface == 0xFF) - this->luclinface = GetLuclinFace(); - else - this->luclinface = in_luclinface; - - if (in_beard == 0xFF) - this->beard = GetBeard(); - else - this->beard = in_beard; - - this->aa_title = 0xFF; - - if (in_drakkin_heritage == 0xFFFFFFFF) - this->drakkin_heritage = GetDrakkinHeritage(); - else - this->drakkin_heritage = in_drakkin_heritage; - - if (in_drakkin_tattoo == 0xFFFFFFFF) - this->drakkin_tattoo = GetDrakkinTattoo(); - else - this->drakkin_tattoo = in_drakkin_tattoo; - - if (in_drakkin_details == 0xFFFFFFFF) - this->drakkin_details = GetDrakkinDetails(); - else - this->drakkin_details = in_drakkin_details; - - if (in_size == 0xFFFFFFFF) - this->size = GetSize(); - else - this->size = in_size; - - // Forces the feature information to be pulled from the Player Profile - if (this->IsClient() && in_race == 0) { - this->race = CastToClient()->GetBaseRace(); - this->gender = CastToClient()->GetBaseGender(); - this->texture = 0xFF; - this->helmtexture = 0xFF; - this->haircolor = CastToClient()->GetBaseHairColor(); - this->beardcolor = CastToClient()->GetBaseBeardColor(); - this->eyecolor1 = CastToClient()->GetBaseEyeColor(); - this->eyecolor2 = CastToClient()->GetBaseEyeColor(); - this->hairstyle = CastToClient()->GetBaseHairStyle(); - this->luclinface = CastToClient()->GetBaseFace(); - this->beard = CastToClient()->GetBaseBeard(); - this->aa_title = 0xFF; - this->drakkin_heritage = CastToClient()->GetBaseHeritage(); - this->drakkin_tattoo = CastToClient()->GetBaseTattoo(); - this->drakkin_details = CastToClient()->GetBaseDetails(); - switch(race){ - case OGRE: - this->size = 9; - break; - case TROLL: - this->size = 8; - break; - case VAHSHIR: - case BARBARIAN: - this->size = 7; - break; - case HALF_ELF: - case WOOD_ELF: - case DARK_ELF: - case FROGLOK: - this->size = 5; - break; - case DWARF: - this->size = 4; - break; - case HALFLING: - case GNOME: - this->size = 3; - break; - default: - this->size = 6; - break; - } - } - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Illusion, sizeof(Illusion_Struct)); - memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); - Illusion_Struct* is = (Illusion_Struct*) outapp->pBuffer; - is->spawnid = this->GetID(); - strcpy(is->charname, GetCleanName()); - is->race = this->race; - is->gender = this->gender; - is->texture = this->texture; - is->helmtexture = this->helmtexture; - is->haircolor = this->haircolor; - is->beardcolor = this->beardcolor; - is->beard = this->beard; - is->eyecolor1 = this->eyecolor1; - is->eyecolor2 = this->eyecolor2; - is->hairstyle = this->hairstyle; - is->face = this->luclinface; - //is->aa_title = this->aa_title; - is->drakkin_heritage = this->drakkin_heritage; - is->drakkin_tattoo = this->drakkin_tattoo; - is->drakkin_details = this->drakkin_details; - is->size = this->size; - - entity_list.QueueClients(this, outapp); - safe_delete(outapp); - mlog(CLIENT__SPELLS, "Illusion: Race = %i, Gender = %i, Texture = %i, HelmTexture = %i, HairColor = %i, BeardColor = %i, EyeColor1 = %i, EyeColor2 = %i, HairStyle = %i, Face = %i, DrakkinHeritage = %i, DrakkinTattoo = %i, DrakkinDetails = %i, Size = %f", - this->race, this->gender, this->texture, this->helmtexture, this->haircolor, this->beardcolor, this->eyecolor1, this->eyecolor2, this->hairstyle, this->luclinface, this->drakkin_heritage, this->drakkin_tattoo, this->drakkin_details, this->size); -} - -uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) { -//std::cout << "Gender in: " << (int)in_gender << std::endl; // undefined cout [CODEBUG] - if ((in_race > 0 && in_race <= GNOME ) - || in_race == IKSAR || in_race == VAHSHIR || in_race == FROGLOK || in_race == DRAKKIN - || in_race == 15 || in_race == 50 || in_race == 57 || in_race == 70 || in_race == 98 || in_race == 118) { - if (in_gender >= 2) { - // Female default for PC Races - return 1; - } - else - return in_gender; - } - else if (in_race == 44 || in_race == 52 || in_race == 55 || in_race == 65 || in_race == 67 || in_race == 88 || in_race == 117 || in_race == 127 || - in_race == 77 || in_race == 78 || in_race == 81 || in_race == 90 || in_race == 92 || in_race == 93 || in_race == 94 || in_race == 106 || in_race == 112 || in_race == 471) { - // Male only races - return 0; - - } - else if (in_race == 25 || in_race == 56) { - // Female only races - return 1; - } - else { - // Neutral default for NPC Races - return 2; - } -} - -void Mob::SendAppearancePacket(uint32 type, uint32 value, bool WholeZone, bool iIgnoreSelf, Client *specific_target) { - if (!GetID()) - return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* appearance = (SpawnAppearance_Struct*)outapp->pBuffer; - appearance->spawn_id = this->GetID(); - appearance->type = type; - appearance->parameter = value; - if (WholeZone) - entity_list.QueueClients(this, outapp, iIgnoreSelf); - else if(specific_target != nullptr) - specific_target->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); - else if (this->IsClient()) - this->CastToClient()->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); - safe_delete(outapp); -} - -void Mob::SendLevelAppearance(){ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); - LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer; - la->parm1 = 0x4D; - la->parm2 = la->parm1 + 1; - la->parm3 = la->parm2 + 1; - la->parm4 = la->parm3 + 1; - la->parm5 = la->parm4 + 1; - la->spawn_id = GetID(); - la->value1a = 1; - la->value2a = 2; - la->value3a = 1; - la->value3b = 1; - la->value4a = 1; - la->value4b = 1; - la->value5a = 2; - entity_list.QueueCloseClients(this,outapp); - safe_delete(outapp); -} - -void Mob::SendStunAppearance() -{ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); - LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer; - la->parm1 = 58; - la->parm2 = 60; - la->spawn_id = GetID(); - la->value1a = 2; - la->value1b = 0; - la->value2a = 2; - la->value2b = 0; - entity_list.QueueCloseClients(this,outapp); - safe_delete(outapp); -} - -void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target){ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); - LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer; - la->spawn_id = GetID(); - la->parm1 = parm1; - la->parm2 = parm2; - la->parm3 = parm3; - la->parm4 = parm4; - la->parm5 = parm5; - // Note that setting the b values to 0 will disable the related effect from the corresponding parameter. - // Setting the a value appears to have no affect at all.s - la->value1a = 1; - la->value1b = 1; - la->value2a = 1; - la->value2b = 1; - la->value3a = 1; - la->value3b = 1; - la->value4a = 1; - la->value4b = 1; - la->value5a = 1; - la->value5b = 1; - if(specific_target == nullptr) { - entity_list.QueueClients(this,outapp); - } - else if (specific_target->IsClient()) { - specific_target->CastToClient()->QueuePacket(outapp, false); - } - safe_delete(outapp); -} - -void Mob::SendTargetable(bool on, Client *specific_target) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Untargetable, sizeof(Untargetable_Struct)); - Untargetable_Struct *ut = (Untargetable_Struct*)outapp->pBuffer; - ut->id = GetID(); - ut->targetable_flag = on == true ? 1 : 0; - - if(specific_target == nullptr) { - entity_list.QueueClients(this, outapp); - } - else if (specific_target->IsClient()) { - specific_target->CastToClient()->QueuePacket(outapp, false); - } - safe_delete(outapp); -} - -void Mob::QuestReward(Client *c, uint32 silver, uint32 gold, uint32 platinum) { - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct)); - memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); - QuestReward_Struct* qr = (QuestReward_Struct*) outapp->pBuffer; - - qr->from_mob = GetID(); // Entity ID for the from mob name - qr->silver = silver; - qr->gold = gold; - qr->platinum = platinum; - - if(c) - c->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); - - safe_delete(outapp); -} - -void Mob::CameraEffect(uint32 duration, uint32 intensity, Client *c, bool global) { - - - if(global == true) - { - ServerPacket* pack = new ServerPacket(ServerOP_CameraShake, sizeof(ServerCameraShake_Struct)); - memset(pack->pBuffer, 0, sizeof(pack->pBuffer)); - ServerCameraShake_Struct* scss = (ServerCameraShake_Struct*) pack->pBuffer; - scss->duration = duration; - scss->intensity = intensity; - worldserver.SendPacket(pack); - safe_delete(pack); - return; - } - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CameraEffect, sizeof(Camera_Struct)); - memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); - Camera_Struct* cs = (Camera_Struct*) outapp->pBuffer; - cs->duration = duration; // Duration in milliseconds - cs->intensity = ((intensity * 6710886) + 1023410176); // Intensity ranges from 1023410176 to 1090519040, so simplify it from 0 to 10. - - if(c) - c->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); - else - entity_list.QueueClients(this, outapp); - - safe_delete(outapp); -} - -void Mob::SendSpellEffect(uint32 effectid, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk020, bool perm_effect, Client *c) { - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpellEffect, sizeof(SpellEffect_Struct)); - memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); - SpellEffect_Struct* se = (SpellEffect_Struct*) outapp->pBuffer; - se->EffectID = effectid; // ID of the Particle Effect - se->EntityID = GetID(); - se->EntityID2 = GetID(); // EntityID again - se->Duration = duration; // In Milliseconds - se->FinishDelay = finish_delay; // Seen 0 - se->Unknown020 = unk020; // Seen 3000 - se->Unknown024 = 1; // Seen 1 for SoD - se->Unknown025 = 1; // Seen 1 for Live - se->Unknown026 = 0; // Seen 1157 - - if(c) - c->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); - else if(zone_wide) - entity_list.QueueClients(this, outapp); - else - entity_list.QueueCloseClients(this, outapp); - - safe_delete(outapp); - - if (perm_effect) { - if(!IsNimbusEffectActive(effectid)) { - SetNimbusEffect(effectid); - } - } - -} - -void Mob::TempName(const char *newname) -{ - char temp_name[64]; - char old_name[64]; - strn0cpy(old_name, GetName(), 64); - - if(newname) - strn0cpy(temp_name, newname, 64); - - // Reset the name to the original if left null. - if(!newname) { - strn0cpy(temp_name, GetOrigName(), 64); - SetName(temp_name); - //CleanMobName(GetName(), temp_name); - strn0cpy(temp_name, GetCleanName(), 64); - } - - // Make the new name unique and set it - strn0cpy(temp_name, entity_list.MakeNameUnique(temp_name), 64); - - - // Send the new name to all clients - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MobRename, sizeof(MobRename_Struct)); - memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); - MobRename_Struct* mr = (MobRename_Struct*) outapp->pBuffer; - strn0cpy(mr->old_name, old_name, 64); - strn0cpy(mr->old_name_again, old_name, 64); - strn0cpy(mr->new_name, temp_name, 64); - mr->unknown192 = 0; - mr->unknown196 = 1; - entity_list.QueueClients(this, outapp); - safe_delete(outapp); - - SetName(temp_name); -} - -void Mob::SetTargetable(bool on) { - if(m_targetable != on) { - m_targetable = on; - SendTargetable(on); - } -} - -const int32& Mob::SetMana(int32 amount) -{ - CalcMaxMana(); - int32 mmana = GetMaxMana(); - cur_mana = amount < 0 ? 0 : (amount > mmana ? mmana : amount); -/* - if(IsClient()) - LogFile->write(EQEMuLog::Debug, "Setting mana for %s to %d (%4.1f%%)", GetName(), amount, GetManaRatio()); -*/ - - return cur_mana; -} - - -void Mob::SetAppearance(EmuAppearance app, bool iIgnoreSelf) { - if (_appearance != app) { - _appearance = app; - SendAppearancePacket(AT_Anim, GetAppearanceValue(app), true, iIgnoreSelf); - if (this->IsClient() && this->IsAIControlled()) - SendAppearancePacket(AT_Anim, ANIM_FREEZE, false, false); - } -} - -void Mob::ChangeSize(float in_size = 0, bool bNoRestriction) { - // Size Code - if (!bNoRestriction) - { - if (this->IsClient() || this->petid != 0) - if (in_size < 3.0) - in_size = 3.0; - - - if (this->IsClient() || this->petid != 0) - if (in_size > 15.0) - in_size = 15.0; - } - - - if (in_size < 1.0) - in_size = 1.0; - - if (in_size > 255.0) - in_size = 255.0; - //End of Size Code - this->size = in_size; - SendAppearancePacket(AT_Size, (uint32) in_size); -} - -Mob* Mob::GetOwnerOrSelf() { - if (!GetOwnerID()) - return this; - Mob* owner = entity_list.GetMob(this->GetOwnerID()); - if (!owner) { - SetOwnerID(0); - return(this); - } - if (owner->GetPetID() == this->GetID()) { - return owner; - } - if(IsNPC() && CastToNPC()->GetSwarmInfo()){ - return (CastToNPC()->GetSwarmInfo()->GetOwner()); - } - SetOwnerID(0); - return this; -} - -Mob* Mob::GetOwner() { - Mob* owner = entity_list.GetMob(this->GetOwnerID()); - if (owner && owner->GetPetID() == this->GetID()) { - - return owner; - } - if(IsNPC() && CastToNPC()->GetSwarmInfo()){ - return (CastToNPC()->GetSwarmInfo()->GetOwner()); - } - SetOwnerID(0); - return 0; -} - -Mob* Mob::GetUltimateOwner() -{ - Mob* Owner = GetOwner(); - - if(!Owner) - return this; - - while(Owner && Owner->HasOwner()) - Owner = Owner->GetOwner(); - - return Owner ? Owner : this; -} - -void Mob::SetOwnerID(uint16 NewOwnerID) { - if (NewOwnerID == GetID() && NewOwnerID != 0) // ok, no charming yourself now =p - return; - ownerid = NewOwnerID; - if (ownerid == 0 && this->IsNPC() && this->GetPetType() != petCharmed) - this->Depop(); -} - -// used in checking for behind (backstab) and checking in front (melee LoS) -float Mob::MobAngle(Mob *other, float ourx, float oury) const { - if (!other || other == this) - return 0.0f; - - float angle, lengthb, vectorx, vectory, dotp; - float mobx = -(other->GetX()); // mob xloc (inverse because eq) - float moby = other->GetY(); // mob yloc - float heading = other->GetHeading(); // mob heading - heading = (heading * 360.0f) / 256.0f; // convert to degrees - if (heading < 270) - heading += 90; - else - heading -= 270; - - heading = heading * 3.1415f / 180.0f; // convert to radians - vectorx = mobx + (10.0f * cosf(heading)); // create a vector based on heading - vectory = moby + (10.0f * sinf(heading)); // of mob length 10 - - // length of mob to player vector - lengthb = (float) sqrtf(((-ourx - mobx) * (-ourx - mobx)) + ((oury - moby) * (oury - moby))); - - // calculate dot product to get angle - // Handle acos domain errors due to floating point rounding errors - dotp = ((vectorx - mobx) * (-ourx - mobx) + - (vectory - moby) * (oury - moby)) / (10 * lengthb); - // I haven't seen any errors that cause problems that weren't slightly - // larger/smaller than 1/-1, so only handle these cases for now - if (dotp > 1) - return 0.0f; - else if (dotp < -1) - return 180.0f; - - angle = acosf(dotp); - angle = angle * 180.0f / 3.1415f; - - return angle; -} - -void Mob::SetZone(uint32 zone_id, uint32 instance_id) -{ - if(IsClient()) - { - CastToClient()->GetPP().zone_id = zone_id; - CastToClient()->GetPP().zoneInstance = instance_id; - } - Save(); -} - -void Mob::Kill() { - Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); -} - -void Mob::SetAttackTimer() { - float PermaHaste; - if(GetHaste() > 0) - PermaHaste = 1 / (1 + (float)GetHaste()/100); - else if(GetHaste() < 0) - PermaHaste = 1 * (1 - (float)GetHaste()/100); - else - PermaHaste = 1.0f; - - //default value for attack timer in case they have - //an invalid weapon equipped: - attack_timer.SetAtTrigger(4000, true); - - Timer* TimerToUse = nullptr; - const Item_Struct* PrimaryWeapon = nullptr; - - for (int i=SLOT_RANGE; i<=SLOT_SECONDARY; i++) { - - //pick a timer - if (i == SLOT_PRIMARY) - TimerToUse = &attack_timer; - else if (i == SLOT_RANGE) - TimerToUse = &ranged_timer; - else if(i == SLOT_SECONDARY) - TimerToUse = &attack_dw_timer; - else //invalid slot (hands will always hit this) - continue; - - const Item_Struct* ItemToUse = nullptr; - - //find our item - if (IsClient()) { - ItemInst* ci = CastToClient()->GetInv().GetItem(i); - if (ci) - ItemToUse = ci->GetItem(); - } else if(IsNPC()) - { - //The code before here was fundementally flawed because equipment[] - //isn't the same as PC inventory and also: - //NPCs don't use weapon speed to dictate how fast they hit anyway. - ItemToUse = nullptr; - } - - //special offhand stuff - if(i == SLOT_SECONDARY) { - //if we have a 2H weapon in our main hand, no dual - if(PrimaryWeapon != nullptr) { - if( PrimaryWeapon->ItemClass == ItemClassCommon - && (PrimaryWeapon->ItemType == ItemType2HSlash - || PrimaryWeapon->ItemType == ItemType2HBlunt - || PrimaryWeapon->ItemType == ItemType2HPiercing)) { - attack_dw_timer.Disable(); - continue; - } - } - - //clients must have the skill to use it... - if(IsClient()) { - //if we cant dual wield, skip it - if (!CanThisClassDualWield()) { - attack_dw_timer.Disable(); - continue; - } - } else { - //NPCs get it for free at 13 - if(GetLevel() < 13) { - attack_dw_timer.Disable(); - continue; - } - } - } - - //see if we have a valid weapon - if(ItemToUse != nullptr) { - //check type and damage/delay - if(ItemToUse->ItemClass != ItemClassCommon - || ItemToUse->Damage == 0 - || ItemToUse->Delay == 0) { - //no weapon - ItemToUse = nullptr; - } - // Check to see if skill is valid - else if((ItemToUse->ItemType > ItemTypeLargeThrowing) && (ItemToUse->ItemType != ItemTypeMartial) && (ItemToUse->ItemType != ItemType2HPiercing)) { - //no weapon - ItemToUse = nullptr; - } - } - - int16 DelayMod = itembonuses.HundredHands + spellbonuses.HundredHands; - if (DelayMod < -99) - DelayMod = -99; - - //if we have no weapon.. - if (ItemToUse == nullptr) { - //above checks ensure ranged weapons do not fall into here - // Work out if we're a monk - if ((GetClass() == MONK) || (GetClass() == BEASTLORD)) { - //we are a monk, use special delay - int speed = (int)( (GetMonkHandToHandDelay()*(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste); - // 1200 seemed too much, with delay 10 weapons available - if(speed < RuleI(Combat, MinHastedDelay)) //lower bound - speed = RuleI(Combat, MinHastedDelay); - TimerToUse->SetAtTrigger(speed, true); // Hand to hand, delay based on level or epic - } else { - //not a monk... using fist, regular delay - int speed = (int)((36 *(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste); - if(speed < RuleI(Combat, MinHastedDelay) && IsClient()) //lower bound - speed = RuleI(Combat, MinHastedDelay); - TimerToUse->SetAtTrigger(speed, true); // Hand to hand, non-monk 2/36 - } - } else { - //we have a weapon, use its delay - // Convert weapon delay to timer resolution (milliseconds) - //delay * 100 - int speed = (int)((ItemToUse->Delay*(100+DelayMod)/100)*(100.0f+attack_speed)*PermaHaste); - if(speed < RuleI(Combat, MinHastedDelay)) - speed = RuleI(Combat, MinHastedDelay); - - if(ItemToUse && (ItemToUse->ItemType == ItemTypeBow || ItemToUse->ItemType == ItemTypeLargeThrowing)) - { - if(IsClient()) - { - float max_quiver = 0; - for(int r = SLOT_PERSONAL_BEGIN; r <= SLOT_PERSONAL_END; r++) - { - const ItemInst *pi = CastToClient()->GetInv().GetItem(r); - if(!pi) - continue; - if(pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == BagTypeQuiver) - { - float temp_wr = ( pi->GetItem()->BagWR / RuleI(Combat, QuiverWRHasteDiv) ); - if(temp_wr > max_quiver) - { - max_quiver = temp_wr; - } - } - } - if(max_quiver > 0) - { - float quiver_haste = 1 / (1 + max_quiver / 100); - speed *= quiver_haste; - } - } - } - TimerToUse->SetAtTrigger(speed, true); - } - - if(i == SLOT_PRIMARY) - PrimaryWeapon = ItemToUse; - } - -} - -bool Mob::CanThisClassDualWield(void) const { - if(!IsClient()) { - return(GetSkill(SkillDualWield) > 0); - } - else if(CastToClient()->HasSkill(SkillDualWield)) { - const ItemInst* pinst = CastToClient()->GetInv().GetItem(SLOT_PRIMARY); - const ItemInst* sinst = CastToClient()->GetInv().GetItem(SLOT_SECONDARY); - - // 2HS, 2HB, or 2HP - if(pinst && pinst->IsWeapon()) { - const Item_Struct* item = pinst->GetItem(); - - if((item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HPiercing)) - return false; - } - - // OffHand Weapon - if(sinst && !sinst->IsWeapon()) - return false; - - // Dual-Wielding Empty Fists - if(!pinst && !sinst) - if(class_ != MONK && class_ != MONKGM && class_ != BEASTLORD && class_ != BEASTLORDGM) - return false; - - return true; - } - - return false; -} - -bool Mob::CanThisClassDoubleAttack(void) const -{ - if(!IsClient()) { - return(GetSkill(SkillDoubleAttack) > 0); - } else { - if(aabonuses.GiveDoubleAttack || itembonuses.GiveDoubleAttack || spellbonuses.GiveDoubleAttack) { - return true; - } - return(CastToClient()->HasSkill(SkillDoubleAttack)); - } -} - -bool Mob::IsWarriorClass(void) const -{ - switch(GetClass()) - { - case WARRIOR: - case WARRIORGM: - case ROGUE: - case ROGUEGM: - case MONK: - case MONKGM: - case PALADIN: - case PALADINGM: - case SHADOWKNIGHT: - case SHADOWKNIGHTGM: - case RANGER: - case RANGERGM: - case BEASTLORD: - case BEASTLORDGM: - case BERSERKER: - case BERSERKERGM: - case BARD: - case BARDGM: - { - return true; - } - default: - { - return false; - } - } - -} - -bool Mob::CanThisClassParry(void) const -{ - if(!IsClient()) { - return(GetSkill(SkillParry) > 0); - } else { - return(CastToClient()->HasSkill(SkillParry)); - } -} - -bool Mob::CanThisClassDodge(void) const -{ - if(!IsClient()) { - return(GetSkill(SkillDodge) > 0); - } else { - return(CastToClient()->HasSkill(SkillDodge)); - } -} - -bool Mob::CanThisClassRiposte(void) const -{ - if(!IsClient()) { - return(GetSkill(SkillRiposte) > 0); - } else { - return(CastToClient()->HasSkill(SkillRiposte)); - } -} - -bool Mob::CanThisClassBlock(void) const -{ - if(!IsClient()) { - return(GetSkill(SkillBlock) > 0); - } else { - return(CastToClient()->HasSkill(SkillBlock)); - } -} - -float Mob::Dist(const Mob &other) const { - float xDiff = other.x_pos - x_pos; - float yDiff = other.y_pos - y_pos; - float zDiff = other.z_pos - z_pos; - - return sqrtf( (xDiff * xDiff) - + (yDiff * yDiff) - + (zDiff * zDiff) ); -} - -float Mob::DistNoZ(const Mob &other) const { - float xDiff = other.x_pos - x_pos; - float yDiff = other.y_pos - y_pos; - - return sqrtf( (xDiff * xDiff) - + (yDiff * yDiff) ); -} - -float Mob::DistNoRoot(const Mob &other) const { - float xDiff = other.x_pos - x_pos; - float yDiff = other.y_pos - y_pos; - float zDiff = other.z_pos - z_pos; - - return ( (xDiff * xDiff) - + (yDiff * yDiff) - + (zDiff * zDiff) ); -} - -float Mob::DistNoRoot(float x, float y, float z) const { - float xDiff = x - x_pos; - float yDiff = y - y_pos; - float zDiff = z - z_pos; - - return ( (xDiff * xDiff) - + (yDiff * yDiff) - + (zDiff * zDiff) ); -} - -float Mob::DistNoRootNoZ(float x, float y) const { - float xDiff = x - x_pos; - float yDiff = y - y_pos; - - return ( (xDiff * xDiff) + (yDiff * yDiff) ); -} - -float Mob::DistNoRootNoZ(const Mob &other) const { - float xDiff = other.x_pos - x_pos; - float yDiff = other.y_pos - y_pos; - - return ( (xDiff * xDiff) + (yDiff * yDiff) ); -} - -float Mob::GetReciprocalHeading(Mob* target) { - float Result = 0; - - if(target) { - // Convert to radians - float h = (target->GetHeading() / 256.0f) * 6.283184f; - - // Calculate the reciprocal heading in radians - Result = h + 3.141592f; - - // Convert back to eq heading from radians - Result = (Result / 6.283184f) * 256.0f; - } - - return Result; -} - -bool Mob::PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest, bool lookForAftArc) { - bool Result = false; - - if(target) { - float look_heading = 0; - - if(lookForAftArc) - look_heading = GetReciprocalHeading(target); - else - look_heading = target->GetHeading(); - - // Convert to sony heading to radians - look_heading = (look_heading / 256.0f) * 6.283184f; - - float tempX = 0; - float tempY = 0; - float tempZ = 0; - float tempSize = 0; - const float rangeCreepMod = 0.25; - const uint8 maxIterationsAllowed = 4; - uint8 counter = 0; - float rangeReduction= 0; - - tempSize = target->GetSize(); - rangeReduction = (tempSize * rangeCreepMod); - - while(tempSize > 0 && counter != maxIterationsAllowed) { - tempX = GetX() + (tempSize * static_cast(sin(double(look_heading)))); - tempY = GetY() + (tempSize * static_cast(cos(double(look_heading)))); - tempZ = target->GetZ(); - - if(!CheckLosFN(tempX, tempY, tempZ, tempSize)) { - tempSize -= rangeReduction; - } - else { - Result = true; - break; - } - - counter++; - } - - if(!Result) { - // Try to find an attack arc to position at from the opposite direction. - look_heading += (3.141592 / 2); - - tempSize = target->GetSize(); - counter = 0; - - while(tempSize > 0 && counter != maxIterationsAllowed) { - tempX = GetX() + (tempSize * static_cast(sin(double(look_heading)))); - tempY = GetY() + (tempSize * static_cast(cos(double(look_heading)))); - tempZ = target->GetZ(); - - if(!CheckLosFN(tempX, tempY, tempZ, tempSize)) { - tempSize -= rangeReduction; - } - else { - Result = true; - break; - } - - counter++; - } - } - - if(Result) { - x_dest = tempX; - y_dest = tempY; - z_dest = tempZ; - } - } - - return Result; -} - -bool Mob::HateSummon() { - // check if mob has ability to summon - // 97% is the offical % that summoning starts on live, not 94 - // if the mob can summon and is charmed, it can only summon mobs it has LoS to - Mob* mob_owner = nullptr; - if(GetOwnerID()) - mob_owner = entity_list.GetMob(GetOwnerID()); - - int summon_level = GetSpecialAbility(SPECATK_SUMMON); - if(summon_level == 1 || summon_level == 2) { - if(!GetTarget() || (mob_owner && mob_owner->IsClient() && !CheckLosFN(GetTarget()))) { - return false; - } - } else { - //unsupported summon level or OFF - return false; - } - - // validate hp - int hp_ratio = GetSpecialAbilityParam(SPECATK_SUMMON, 1); - hp_ratio = hp_ratio > 0 ? hp_ratio : 97; - if(GetHPRatio() > static_cast(hp_ratio)) { - return false; - } - - // now validate the timer - int summon_timer_duration = GetSpecialAbilityParam(SPECATK_SUMMON, 0); - summon_timer_duration = summon_timer_duration > 0 ? summon_timer_duration : 6000; - Timer *timer = GetSpecialAbilityTimer(SPECATK_SUMMON); - if (!timer) - { - StartSpecialAbilityTimer(SPECATK_SUMMON, summon_timer_duration); - } else { - if(!timer->Check()) - return false; - - timer->Start(summon_timer_duration); - } - - // get summon target - SetTarget(GetHateTop()); - if(target) - { - if(summon_level == 1) { - entity_list.MessageClose(this, true, 500, MT_Say, "%s says,'You will not evade me, %s!' ", GetCleanName(), target->GetCleanName() ); - - if (target->IsClient()) { - target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), x_pos, y_pos, z_pos, target->GetHeading(), 0, SummonPC); - } - else { -#ifdef BOTS - if(target && target->IsBot()) { - // set pre summoning info to return to (to get out of melee range for caster) - target->CastToBot()->SetHasBeenSummoned(true); - target->CastToBot()->SetPreSummonX(target->GetX()); - target->CastToBot()->SetPreSummonY(target->GetY()); - target->CastToBot()->SetPreSummonZ(target->GetZ()); - - } -#endif //BOTS - target->GMMove(x_pos, y_pos, z_pos, target->GetHeading()); - } - - return true; - } else if(summon_level == 2) { - entity_list.MessageClose(this, true, 500, MT_Say, "%s says,'You will not evade me, %s!'", GetCleanName(), target->GetCleanName()); - GMMove(target->GetX(), target->GetY(), target->GetZ()); - } - } - return false; -} - -void Mob::FaceTarget(Mob* MobToFace) { - Mob* facemob = MobToFace; - if(!facemob) { - if(!GetTarget()) { - return; - } - else { - facemob = GetTarget(); - } - } - - float oldheading = GetHeading(); - float newheading = CalculateHeadingToTarget(facemob->GetX(), facemob->GetY()); - if(oldheading != newheading) { - SetHeading(newheading); - if(moving) - SendPosUpdate(); - else - { - SendPosition(); - } - } - - if(IsNPC() && !IsEngaged()) { - CastToNPC()->GetRefaceTimer()->Start(15000); - CastToNPC()->GetRefaceTimer()->Enable(); - } -} - -bool Mob::RemoveFromHateList(Mob* mob) -{ - SetRunAnimSpeed(0); - bool bFound = false; - if(IsEngaged()) - { - bFound = hate_list.RemoveEnt(mob); - if(hate_list.IsEmpty()) - { - AI_Event_NoLongerEngaged(); - zone->DelAggroMob(); - } - } - if(GetTarget() == mob) - { - SetTarget(hate_list.GetTop(this)); - } - - return bFound; -} - -void Mob::WipeHateList() -{ - if(IsEngaged()) - { - hate_list.Wipe(); - AI_Event_NoLongerEngaged(); - } - else - { - hate_list.Wipe(); - } -} - -uint32 Mob::RandomTimer(int min,int max) { - int r = 14000; - if(min != 0 && max != 0 && min < max) - { - r = MakeRandomInt(min, max); - } - return r; -} - -uint32 NPC::GetEquipment(uint8 material_slot) const -{ - if(material_slot > 8) - return 0; - int invslot = Inventory::CalcSlotFromMaterial(material_slot); - if (invslot == -1) - return 0; - return equipment[invslot]; -} - -void Mob::SendWearChange(uint8 material_slot) -{ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); - WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; - - wc->spawn_id = GetID(); - wc->material = GetEquipmentMaterial(material_slot); - wc->elite_material = IsEliteMaterialItem(material_slot); - wc->color.color = GetEquipmentColor(material_slot); - wc->wear_slot_id = material_slot; - - entity_list.QueueClients(this, outapp); - safe_delete(outapp); -} - -void Mob::SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model, uint32 elite_material, uint32 unknown06, uint32 unknown18) -{ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); - WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; - - wc->spawn_id = this->GetID(); - wc->material = texture; - if (this->IsClient()) - wc->color.color = GetEquipmentColor(slot); - else - wc->color.color = this->GetArmorTint(slot); - wc->wear_slot_id = slot; - - wc->unknown06 = unknown06; - wc->elite_material = elite_material; - wc->hero_forge_model = hero_forge_model; - wc->unknown18 = unknown18; - - - entity_list.QueueClients(this, outapp); - safe_delete(outapp); -} - -void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint) -{ - uint32 color; - color = (red_tint & 0xFF) << 16; - color |= (green_tint & 0xFF) << 8; - color |= (blue_tint & 0xFF); - color |= (color) ? (0xFF << 24) : 0; - armor_tint[material_slot] = color; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); - WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; - - wc->spawn_id = this->GetID(); - wc->material = GetEquipmentMaterial(material_slot); - wc->color.color = color; - wc->wear_slot_id = material_slot; - - entity_list.QueueClients(this, outapp); - safe_delete(outapp); -} - -void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color) -{ - armor_tint[material_slot] = color; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); - WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; - - wc->spawn_id = this->GetID(); - wc->material = texture; - wc->color.color = color; - wc->wear_slot_id = material_slot; - - entity_list.QueueClients(this, outapp); - safe_delete(outapp); -} - -int32 Mob::GetEquipmentMaterial(uint8 material_slot) const -{ - const Item_Struct *item; - - item = database.GetItem(GetEquipment(material_slot)); - if(item != 0) - { - if // for primary and secondary we need the model, not the material - ( - material_slot == MaterialPrimary || - material_slot == MaterialSecondary - ) - { - if(strlen(item->IDFile) > 2) - return atoi(&item->IDFile[2]); - else //may as well try this, since were going to 0 anyways - return item->Material; - } - else - { - return item->Material; - } - } - - return 0; -} - -uint32 Mob::GetEquipmentColor(uint8 material_slot) const -{ - const Item_Struct *item; - - item = database.GetItem(GetEquipment(material_slot)); - if(item != 0) - { - return item->Color; - } - - return 0; -} - -uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const -{ - const Item_Struct *item; - - item = database.GetItem(GetEquipment(material_slot)); - if(item != 0) - { - return item->EliteMaterial; - } - - return 0; -} - -// works just like a printf -void Mob::Say(const char *format, ...) -{ - char buf[1000]; - va_list ap; - - va_start(ap, format); - vsnprintf(buf, 1000, format, ap); - va_end(ap); - - Mob* talker = this; - if(spellbonuses.VoiceGraft != 0) { - if(spellbonuses.VoiceGraft == GetPetID()) - talker = entity_list.GetMob(spellbonuses.VoiceGraft); - else - spellbonuses.VoiceGraft = 0; - } - - if(!talker) - talker = this; - - entity_list.MessageClose_StringID(talker, false, 200, 10, - GENERIC_SAY, GetCleanName(), buf); -} - -// -// solar: this is like the above, but the first parameter is a string id -// -void Mob::Say_StringID(uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9) -{ - char string_id_str[10]; - - snprintf(string_id_str, 10, "%d", string_id); - - entity_list.MessageClose_StringID(this, false, 200, 10, - GENERIC_STRINGID_SAY, GetCleanName(), string_id_str, message3, message4, message5, - message6, message7, message8, message9 - ); -} - -void Mob::Say_StringID(uint32 type, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9) -{ - char string_id_str[10]; - - snprintf(string_id_str, 10, "%d", string_id); - - entity_list.MessageClose_StringID(this, false, 200, type, - GENERIC_STRINGID_SAY, GetCleanName(), string_id_str, message3, message4, message5, - message6, message7, message8, message9 - ); -} - -void Mob::Shout(const char *format, ...) -{ - char buf[1000]; - va_list ap; - - va_start(ap, format); - vsnprintf(buf, 1000, format, ap); - va_end(ap); - - entity_list.Message_StringID(this, false, MT_Shout, - GENERIC_SHOUT, GetCleanName(), buf); -} - -void Mob::Emote(const char *format, ...) -{ - char buf[1000]; - va_list ap; - - va_start(ap, format); - vsnprintf(buf, 1000, format, ap); - va_end(ap); - - entity_list.MessageClose_StringID(this, false, 200, 10, - GENERIC_EMOTE, GetCleanName(), buf); -} - -void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str) -{ - entity_list.QuestJournalledSayClose(this, QuestInitiator, 200, GetCleanName(), str); -} - -const char *Mob::GetCleanName() -{ - if(!strlen(clean_name)) - { - CleanMobName(GetName(), clean_name); - } - - return clean_name; -} - -// hp event -void Mob::SetNextHPEvent( int hpevent ) -{ - nexthpevent = hpevent; -} - -void Mob::SetNextIncHPEvent( int inchpevent ) -{ - nextinchpevent = inchpevent; -} -//warp for quest function,from sandy -void Mob::Warp( float x, float y, float z ) -{ - if(IsNPC()) { - entity_list.ProcessMove(CastToNPC(), x, y, z); - } - - x_pos = x; - y_pos = y; - z_pos = z; - - Mob* target = GetTarget(); - if (target) { - FaceTarget( target ); - } - - SendPosition(); -} - -int16 Mob::GetResist(uint8 type) const -{ - if (IsNPC()) - { - if (type == 1) - return MR + spellbonuses.MR + itembonuses.MR; - else if (type == 2) - return FR + spellbonuses.FR + itembonuses.FR; - else if (type == 3) - return CR + spellbonuses.CR + itembonuses.CR; - else if (type == 4) - return PR + spellbonuses.PR + itembonuses.PR; - else if (type == 5) - return DR + spellbonuses.DR + itembonuses.DR; - } - else if (IsClient()) - { - if (type == 1) - return CastToClient()->GetMR(); - else if (type == 2) - return CastToClient()->GetFR(); - else if (type == 3) - return CastToClient()->GetCR(); - else if (type == 4) - return CastToClient()->GetPR(); - else if (type == 5) - return CastToClient()->GetDR(); - } - return 25; -} - -uint32 Mob::GetLevelHP(uint8 tlevel) -{ - //std::cout<<"Tlevel: "<<(int)tlevel<= 60 && casttime > 1000) - { - casttime = casttime / 2; - if (casttime < 1000) - casttime = 1000; - } else if (level >= 50 && casttime > 1000) { - int32 cast_deduction = (casttime*(level - 49))/5; - if (cast_deduction > casttime/2) - casttime /= 2; - else - casttime -= cast_deduction; - } - return(casttime); -} - -void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) { - // Changed proc targets to look up based on the spells goodEffect flag. - // This should work for the majority of weapons. - if(spell_id == SPELL_UNKNOWN || on->GetSpecialAbility(NO_HARM_FROM_CLIENT)) { - //This is so 65535 doesn't get passed to the client message and to logs because it is not relavant information for debugging. - return; - } - - if (IsNoCast()) - return; - - if(!IsValidSpell(spell_id)) { // Check for a valid spell otherwise it will crash through the function - if(IsClient()){ - Message(0, "Invalid spell proc %u", spell_id); - mlog(CLIENT__SPELLS, "Player %s, Weapon Procced invalid spell %u", this->GetName(), spell_id); - } - return; - } - - if(inst && IsClient()) { - //const cast is dirty but it would require redoing a ton of interfaces at this point - //It should be safe as we don't have any truly const ItemInst floating around anywhere. - //So we'll live with it for now - int i = parse->EventItem(EVENT_WEAPON_PROC, CastToClient(), const_cast(inst), on, "", spell_id); - if(i != 0) { - return; - } - } - - bool twinproc = false; - int32 twinproc_chance = 0; - - if(IsClient()) - twinproc_chance = CastToClient()->GetFocusEffect(focusTwincast, spell_id); - - if(twinproc_chance && (MakeRandomInt(0,99) < twinproc_chance)) - twinproc = true; - - if (IsBeneficialSpell(spell_id)) { - SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff, true); - if(twinproc) - SpellOnTarget(spell_id, this, false, false, 0, true); - } - else if(!(on->IsClient() && on->CastToClient()->dead)) { //dont proc on dead clients - SpellFinished(spell_id, on, 10, 0, -1, spells[spell_id].ResistDiff, true); - if(twinproc) - SpellOnTarget(spell_id, on, false, false, 0, true); - } - return; -} - -uint32 Mob::GetZoneID() const { - return(zone->GetZoneID()); -} - -int Mob::GetHaste() { - int h = spellbonuses.haste + spellbonuses.hastetype2; - int cap = 0; - int overhaste = 0; - int level = GetLevel(); - - // 26+ no cap, 1-25 10 - if (level > 25) // 26+ - h += itembonuses.haste; - else // 1-25 - h += itembonuses.haste > 10 ? 10 : itembonuses.haste; - - // 60+ 100, 51-59 85, 1-50 level+25 - if (level > 59) // 60+ - cap = RuleI(Character, HasteCap); - else if (level > 50) // 51-59 - cap = 85; - else // 1-50 - cap = level + 25; - - if(h > cap) - h = cap; - - // 51+ 25 (despite there being higher spells...), 1-50 10 - if (level > 50) // 51+ - overhaste = spellbonuses.hastetype3 > 25 ? 25 : spellbonuses.hastetype3; - else // 1-50 - overhaste = spellbonuses.hastetype3 > 10 ? 10 : spellbonuses.hastetype3; - - h += overhaste; - h += ExtraHaste; //GM granted haste. - - if (spellbonuses.inhibitmelee) { - if (h >= 0) - h -= spellbonuses.inhibitmelee; - else - h -= ((100 + h) * spellbonuses.inhibitmelee / 100); - } - - return(h); -} - -void Mob::SetTarget(Mob* mob) { - if (target == mob) return; - target = mob; - entity_list.UpdateHoTT(this); - if(IsNPC()) - parse->EventNPC(EVENT_TARGET_CHANGE, CastToNPC(), mob, "", 0); - else if (IsClient()) - parse->EventPlayer(EVENT_TARGET_CHANGE, CastToClient(), "", 0); - - if(IsPet() && GetOwner() && GetOwner()->IsClient()) - GetOwner()->CastToClient()->UpdateXTargetType(MyPetTarget, mob); -} - -float Mob::FindGroundZ(float new_x, float new_y, float z_offset) -{ - float ret = -999999; - if (zone->zonemap != nullptr) - { - Map::Vertex me; - me.x = new_x; - me.y = new_y; - me.z = z_pos+z_offset; - Map::Vertex hit; - float best_z = zone->zonemap->FindBestZ(me, &hit); - if (best_z != -999999) - { - ret = best_z; - } - } - return ret; -} - -// Copy of above function that isn't protected to be exported to Perl::Mob -float Mob::GetGroundZ(float new_x, float new_y, float z_offset) -{ - float ret = -999999; - if (zone->zonemap != 0) - { - Map::Vertex me; - me.x = new_x; - me.y = new_y; - me.z = z_pos+z_offset; - Map::Vertex hit; - float best_z = zone->zonemap->FindBestZ(me, &hit); - if (best_z != -999999) - { - ret = best_z; - } - } - return ret; -} - -//helper function for npc AI; needs to be mob:: cause we need to be able to count buffs on other clients and npcs -int Mob::CountDispellableBuffs() -{ - int val = 0; - int buff_count = GetMaxTotalSlots(); - for(int x = 0; x < buff_count; x++) - { - if(!IsValidSpell(buffs[x].spellid)) - continue; - - if(buffs[x].counters) - continue; - - if(spells[buffs[x].spellid].goodEffect == 0) - continue; - - if(buffs[x].spellid != SPELL_UNKNOWN && spells[buffs[x].spellid].buffdurationformula != DF_Permanent) - val++; - } - return val; -} - -// Returns the % that a mob is snared (as a positive value). -1 means not snared -int Mob::GetSnaredAmount() -{ - int worst_snare = -1; - - int buff_count = GetMaxTotalSlots(); - for (int i = 0; i < buff_count; i++) - { - if (!IsValidSpell(buffs[i].spellid)) - continue; - - for(int j = 0; j < EFFECT_COUNT; j++) - { - if (spells[buffs[i].spellid].effectid[j] == SE_MovementSpeed) - { - int val = CalcSpellEffectValue_formula(spells[buffs[i].spellid].formula[j], spells[buffs[i].spellid].base[j], spells[buffs[i].spellid].max[j], buffs[i].casterlevel, buffs[i].spellid); - //int effect = CalcSpellEffectValue(buffs[i].spellid, spells[buffs[i].spellid].effectid[j], buffs[i].casterlevel); - if (val < 0 && abs(val) > worst_snare) - worst_snare = abs(val); - } - } - } - - return worst_snare; -} - -void Mob::TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand, int damage) -{ - if (!on) - return; - - on->TryDefensiveProc(weapon, this, hand, damage); - - //Defensive Skill Procs - if (damage < 0 && damage >= -4) { - uint16 skillinuse = 0; - switch (damage) { - case (-1): - skillinuse = SkillBlock; - break; - - case (-2): - skillinuse = SkillParry; - break; - - case (-3): - skillinuse = SkillRiposte; - break; - - case (-4): - skillinuse = SkillDodge; - break; - } - - if (on->HasSkillProcs()) - on->TrySkillProc(this, skillinuse, 0, false, hand, true); - - if (on->HasSkillProcSuccess()) - on->TrySkillProc(this, skillinuse, 0, true, hand, true); - } -} - -void Mob::SetDeltas(float dx, float dy, float dz, float dh) { - delta_x = dx; - delta_y = dy; - delta_z = dz; - delta_heading = static_cast(dh); -} - -void Mob::SetEntityVariable(const char *id, const char *m_var) -{ - std::string n_m_var = m_var; - m_EntityVariables[id] = n_m_var; -} - -const char* Mob::GetEntityVariable(const char *id) -{ - std::map::iterator iter = m_EntityVariables.find(id); - if(iter != m_EntityVariables.end()) - { - return iter->second.c_str(); - } - return nullptr; -} - -bool Mob::EntityVariableExists(const char *id) -{ - std::map::iterator iter = m_EntityVariables.find(id); - if(iter != m_EntityVariables.end()) - { - return true; - } - return false; -} - -void Mob::SetFlyMode(uint8 flymode) -{ - if(IsClient() && flymode >= 0 && flymode < 3) - { - this->SendAppearancePacket(AT_Levitate, flymode); - } - else if(IsNPC() && flymode >= 0 && flymode <= 3) - { - this->SendAppearancePacket(AT_Levitate, flymode); - this->CastToNPC()->SetFlyMode(flymode); - } -} - -bool Mob::IsNimbusEffectActive(uint32 nimbus_effect) -{ - if(nimbus_effect1 == nimbus_effect || nimbus_effect2 == nimbus_effect || nimbus_effect3 == nimbus_effect) - { - return true; - } - return false; -} - -void Mob::SetNimbusEffect(uint32 nimbus_effect) -{ - if(nimbus_effect1 == 0) - { - nimbus_effect1 = nimbus_effect; - } - else if(nimbus_effect2 == 0) - { - nimbus_effect2 = nimbus_effect; - } - else - { - nimbus_effect3 = nimbus_effect; - } -} - -void Mob::TryTriggerOnCast(uint32 spell_id, bool aa_trigger) -{ - if(!IsValidSpell(spell_id)) - return; - - if (aabonuses.SpellTriggers[0] || spellbonuses.SpellTriggers[0] || itembonuses.SpellTriggers[0]){ - - for(int i = 0; i < MAX_SPELL_TRIGGER; i++){ - - if(aabonuses.SpellTriggers[i] && IsClient()) - TriggerOnCast(aabonuses.SpellTriggers[i], spell_id,1); - - if(spellbonuses.SpellTriggers[i]) - TriggerOnCast(spellbonuses.SpellTriggers[i], spell_id,0); - - if(itembonuses.SpellTriggers[i]) - TriggerOnCast(spellbonuses.SpellTriggers[i], spell_id,0); - } - } -} - - -void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger) -{ - if(!IsValidSpell(focus_spell) || !IsValidSpell(spell_id)) - return; - - uint32 trigger_spell_id = 0; - - if (aa_trigger && IsClient()){ - //focus_spell = aaid - trigger_spell_id = CastToClient()->CalcAAFocus(focusTriggerOnCast, focus_spell, spell_id); - - if(IsValidSpell(trigger_spell_id) && GetTarget()) - SpellFinished(trigger_spell_id, GetTarget(), 10, 0, -1, spells[trigger_spell_id].ResistDiff); - } - - else{ - trigger_spell_id = CalcFocusEffect(focusTriggerOnCast, focus_spell, spell_id); - - if(IsValidSpell(trigger_spell_id) && GetTarget()){ - SpellFinished(trigger_spell_id, GetTarget(),10, 0, -1, spells[trigger_spell_id].ResistDiff); - CheckNumHitsRemaining(NUMHIT_MatchingSpells,0, focus_spell); - } - } -} - -void Mob::TrySpellTrigger(Mob *target, uint32 spell_id) -{ - if(target == nullptr || !IsValidSpell(spell_id)) - { - return; - } - int spell_trig = 0; - // Count all the percentage chances to trigger for all effects - for(int i = 0; i < EFFECT_COUNT; i++) - { - if (spells[spell_id].effectid[i] == SE_SpellTrigger) - spell_trig += spells[spell_id].base[i]; - } - // If all the % add to 100, then only one of the effects can fire but one has to fire. - if (spell_trig == 100) - { - int trig_chance = 100; - for(int i = 0; i < EFFECT_COUNT; i++) - { - if (spells[spell_id].effectid[i] == SE_SpellTrigger) - { - if(MakeRandomInt(0, trig_chance) <= spells[spell_id].base[i]) - { - // If we trigger an effect then its over. - SpellFinished(spells[spell_id].base2[i], target, 10, 0, -1, spells[spell_id].ResistDiff); - break; - } - else - { - // Increase the chance to fire for the next effect, if all effects fail, the final effect will fire. - trig_chance -= spells[spell_id].base[i]; - } - } - - } - } - // if the chances don't add to 100, then each effect gets a chance to fire, chance for no trigger as well. - else - { - for(int i = 0; i < EFFECT_COUNT; i++) - { - if (spells[spell_id].effectid[i] == SE_SpellTrigger) - { - if(MakeRandomInt(0, 100) <= spells[spell_id].base[i]) - { - SpellFinished(spells[spell_id].base2[i], target, 10, 0, -1, spells[spell_id].ResistDiff); - } - } - } - } -} - -void Mob::TryApplyEffect(Mob *target, uint32 spell_id) -{ - if(target == nullptr || !IsValidSpell(spell_id)) - { - return; - } - - for(int i = 0; i < EFFECT_COUNT; i++) - { - if (spells[spell_id].effectid[i] == SE_ApplyEffect) - { - if(MakeRandomInt(0, 100) <= spells[spell_id].base[i]) - { - if(target) - SpellFinished(spells[spell_id].base2[i], target, 10, 0, -1, spells[spell_id].ResistDiff); - } - } - } -} - -void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsPet) -{ - /* - At present time there is no obvious difference between ReqTarget and ReqCaster - ReqTarget is typically used in spells cast on a target where the trigger occurs on that target. - ReqCaster is typically self only spells where the triggers on self. - Regardless both trigger on the owner of the buff. - */ - - /* - Base2 Range: 1004 = Below < 80% HP - Base2 Range: 500-520 = Below (base2 - 500)*5 HP - Base2 Range: 521 = Below (?) Mana UKNOWN - Will assume its 20% unless proven otherwise - Base2 Range: 522 = Below (40%) Endurance - Base2 Range: 523 = Below (40%) Mana - Base2 Range: 220-? = Number of pets on hatelist to trigger (base2 - 220) (Set at 30 pets max for now) - 38311 = < 10% mana; - */ - - if (!spellbonuses.TriggerOnValueAmount) - return; - - if (spellbonuses.TriggerOnValueAmount){ - - int buff_count = GetMaxTotalSlots(); - - for(int e = 0; e < buff_count; e++){ - - uint32 spell_id = buffs[e].spellid; - - if (IsValidSpell(spell_id)){ - - for(int i = 0; i < EFFECT_COUNT; i++){ - - if ((spells[spell_id].effectid[i] == SE_TriggerOnReqTarget) || (spells[spell_id].effectid[i] == SE_TriggerOnReqCaster)) { - - int base2 = spells[spell_id].base2[i]; - bool use_spell = false; - - if (IsHP){ - if ((base2 >= 500 && base2 <= 520) && GetHPRatio() < (base2 - 500)*5) - use_spell = true; - - else if (base2 = 1004 && GetHPRatio() < 80) - use_spell = true; - } - - else if (IsMana){ - if ( (base2 = 521 && GetManaRatio() < 20) || (base2 = 523 && GetManaRatio() < 40)) - use_spell = true; - - else if (base2 = 38311 && GetManaRatio() < 10) - use_spell = true; - } - - else if (IsEndur){ - if (base2 = 522 && GetEndurancePercent() < 40){ - use_spell = true; - } - } - - else if (IsPet){ - int count = hate_list.SummonedPetCount(this); - if ((base2 >= 220 && base2 <= 250) && count >= (base2 - 220)){ - use_spell = true; - } - } - - if (use_spell){ - SpellFinished(spells[spell_id].base[i], this, 10, 0, -1, spells[spell_id].ResistDiff); - - if(!TryFadeEffect(e)) - BuffFadeBySlot(e); - } - } - } - } - } - } -} - - -//Twincast Focus effects should stack across different types (Spell, AA - when implemented ect) -void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id) -{ - if(!IsValidSpell(spell_id)) - return; - - if(IsClient()) - { - int32 focus = CastToClient()->GetFocusEffect(focusTwincast, spell_id); - - if (focus > 0) - { - if(MakeRandomInt(0, 100) <= focus) - { - Message(MT_Spells,"You twincast %s!",spells[spell_id].name); - SpellFinished(spell_id, target, 10, 0, -1, spells[spell_id].ResistDiff); - } - } - } - - //Retains function for non clients - else if (spellbonuses.FocusEffects[focusTwincast] || itembonuses.FocusEffects[focusTwincast]) - { - int buff_count = GetMaxTotalSlots(); - for(int i = 0; i < buff_count; i++) - { - if(IsEffectInSpell(buffs[i].spellid, SE_FcTwincast)) - { - int32 focus = CalcFocusEffect(focusTwincast, buffs[i].spellid, spell_id); - if(focus > 0) - { - if(MakeRandomInt(0, 100) <= focus) - { - SpellFinished(spell_id, target, 10, 0, -1, spells[spell_id].ResistDiff); - } - } - } - } - } -} - -int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining) -{ - if (!IsValidSpell(spell_id)) - return 0; - - if (!caster) - return 0; - - int32 value = 0; - - //Apply innate vulnerabilities - if (Vulnerability_Mod[GetSpellResistType(spell_id)] != 0) - value = Vulnerability_Mod[GetSpellResistType(spell_id)]; - - - else if (Vulnerability_Mod[HIGHEST_RESIST+1] != 0) - value = Vulnerability_Mod[HIGHEST_RESIST+1]; - - //Apply spell derived vulnerabilities - if (spellbonuses.FocusEffects[focusSpellVulnerability]){ - - int32 tmp_focus = 0; - int tmp_buffslot = -1; - - int buff_count = GetMaxTotalSlots(); - for(int i = 0; i < buff_count; i++) { - - if((IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, SE_FcSpellVulnerability))){ - - int32 focus = caster->CalcFocusEffect(focusSpellVulnerability, buffs[i].spellid, spell_id); - - if (!focus) - continue; - - if (tmp_focus && focus > tmp_focus){ - tmp_focus = focus; - tmp_buffslot = i; - } - - else if (!tmp_focus){ - tmp_focus = focus; - tmp_buffslot = i; - } - - } - } - - if (tmp_focus < -99) - tmp_focus = -99; - - value += tmp_focus; - - if (tmp_buffslot >= 0) - CheckNumHitsRemaining(NUMHIT_MatchingSpells, tmp_buffslot); - } - return value; -} - -int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used) -{ - int skilldmg_mod = 0; - - int16 MeleeVuln = spellbonuses.MeleeVulnerability + itembonuses.MeleeVulnerability + aabonuses.MeleeVulnerability; - - // All skill dmg mod + Skill specific - skilldmg_mod += itembonuses.SkillDmgTaken[HIGHEST_SKILL+1] + spellbonuses.SkillDmgTaken[HIGHEST_SKILL+1] + - itembonuses.SkillDmgTaken[skill_used] + spellbonuses.SkillDmgTaken[skill_used]; - - //Innate SetSkillDamgeTaken(skill,value) - if ((SkillDmgTaken_Mod[skill_used]) || (SkillDmgTaken_Mod[HIGHEST_SKILL+1])) - skilldmg_mod += SkillDmgTaken_Mod[skill_used] + SkillDmgTaken_Mod[HIGHEST_SKILL+1]; - - skilldmg_mod += MeleeVuln; - - if(skilldmg_mod < -100) - skilldmg_mod = -100; - - return skilldmg_mod; -} - -int16 Mob::GetHealRate(uint16 spell_id, Mob* caster) { - - int16 heal_rate = 0; - - heal_rate += itembonuses.HealRate + spellbonuses.HealRate + aabonuses.HealRate; - heal_rate += GetFocusIncoming(focusFcHealPctIncoming, SE_FcHealPctIncoming, caster, spell_id); - - if(heal_rate < -99) - heal_rate = -99; - - return heal_rate; -} - -bool Mob::TryFadeEffect(int slot) -{ - if(IsValidSpell(buffs[slot].spellid)) - { - for(int i = 0; i < EFFECT_COUNT; i++) - { - if (spells[buffs[slot].spellid].effectid[i] == SE_CastOnFadeEffectAlways || - spells[buffs[slot].spellid].effectid[i] == SE_CastOnRuneFadeEffect) - { - uint16 spell_id = spells[buffs[slot].spellid].base[i]; - BuffFadeBySlot(slot); - - if(spell_id) - { - - if(spell_id == SPELL_UNKNOWN) - return false; - - if(IsValidSpell(spell_id)) - { - if (IsBeneficialSpell(spell_id)) { - SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff); - } - else if(!(IsClient() && CastToClient()->dead)) { - SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff); - } - return true; - } - } - } - } - } - return false; -} - -void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) -{ - if(target == nullptr || !IsValidSpell(spell_id)) - return; - - int focus_spell = CastToClient()->GetSympatheticFocusEffect(focusSympatheticProc,spell_id); - - if(IsValidSpell(focus_spell)){ - int focus_trigger = spells[focus_spell].base2[0]; - // For beneficial spells, if the triggered spell is also beneficial then proc it on the target - // if the triggered spell is detrimental, then it will trigger on the caster(ie cursed items) - if(IsBeneficialSpell(spell_id)) - { - if(IsBeneficialSpell(focus_trigger)) - SpellFinished(focus_trigger, target); - - else - SpellFinished(focus_trigger, this, 10, 0, -1, spells[focus_trigger].ResistDiff); - } - // For detrimental spells, if the triggered spell is beneficial, then it will land on the caster - // if the triggered spell is also detrimental, then it will land on the target - else - { - if(IsBeneficialSpell(focus_trigger)) - SpellFinished(focus_trigger, this); - - else - SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff); - } - - CheckNumHitsRemaining(NUMHIT_MatchingSpells, 0, focus_spell); - } -} - -uint32 Mob::GetItemStat(uint32 itemid, const char *identifier) -{ - const ItemInst* inst = database.CreateItem(itemid); - if (!inst) - return 0; - - const Item_Struct* item = inst->GetItem(); - if (!item) - return 0; - - if (!identifier) - return 0; - - uint32 stat = 0; - - std::string id = identifier; - for(int i = 0; i < id.length(); ++i) - { - id[i] = tolower(id[i]); - } - - if (id == "itemclass") - stat = uint32(item->ItemClass); - if (id == "id") - stat = uint32(item->ID); - if (id == "weight") - stat = uint32(item->Weight); - if (id == "norent") - stat = uint32(item->NoRent); - if (id == "nodrop") - stat = uint32(item->NoDrop); - if (id == "size") - stat = uint32(item->Size); - if (id == "slots") - stat = uint32(item->Slots); - if (id == "price") - stat = uint32(item->Price); - if (id == "icon") - stat = uint32(item->Icon); - if (id == "loregroup") - stat = uint32(item->LoreGroup); - if (id == "loreflag") - stat = uint32(item->LoreFlag); - if (id == "pendingloreflag") - stat = uint32(item->PendingLoreFlag); - if (id == "artifactflag") - stat = uint32(item->ArtifactFlag); - if (id == "summonedflag") - stat = uint32(item->SummonedFlag); - if (id == "fvnodrop") - stat = uint32(item->FVNoDrop); - if (id == "favor") - stat = uint32(item->Favor); - if (id == "guildfavor") - stat = uint32(item->GuildFavor); - if (id == "pointtype") - stat = uint32(item->PointType); - if (id == "bagtype") - stat = uint32(item->BagType); - if (id == "bagslots") - stat = uint32(item->BagSlots); - if (id == "bagsize") - stat = uint32(item->BagSize); - if (id == "bagwr") - stat = uint32(item->BagWR); - if (id == "benefitflag") - stat = uint32(item->BenefitFlag); - if (id == "tradeskills") - stat = uint32(item->Tradeskills); - if (id == "cr") - stat = uint32(item->CR); - if (id == "dr") - stat = uint32(item->DR); - if (id == "pr") - stat = uint32(item->PR); - if (id == "mr") - stat = uint32(item->MR); - if (id == "fr") - stat = uint32(item->FR); - if (id == "astr") - stat = uint32(item->AStr); - if (id == "asta") - stat = uint32(item->ASta); - if (id == "aagi") - stat = uint32(item->AAgi); - if (id == "adex") - stat = uint32(item->ADex); - if (id == "acha") - stat = uint32(item->ACha); - if (id == "aint") - stat = uint32(item->AInt); - if (id == "awis") - stat = uint32(item->AWis); - if (id == "hp") - stat = uint32(item->HP); - if (id == "mana") - stat = uint32(item->Mana); - if (id == "ac") - stat = uint32(item->AC); - if (id == "deity") - stat = uint32(item->Deity); - if (id == "skillmodvalue") - stat = uint32(item->SkillModValue); - if (id == "skillmodtype") - stat = uint32(item->SkillModType); - if (id == "banedmgrace") - stat = uint32(item->BaneDmgRace); - if (id == "banedmgamt") - stat = uint32(item->BaneDmgAmt); - if (id == "banedmgbody") - stat = uint32(item->BaneDmgBody); - if (id == "magic") - stat = uint32(item->Magic); - if (id == "casttime_") - stat = uint32(item->CastTime_); - if (id == "reqlevel") - stat = uint32(item->ReqLevel); - if (id == "bardtype") - stat = uint32(item->BardType); - if (id == "bardvalue") - stat = uint32(item->BardValue); - if (id == "light") - stat = uint32(item->Light); - if (id == "delay") - stat = uint32(item->Delay); - if (id == "reclevel") - stat = uint32(item->RecLevel); - if (id == "recskill") - stat = uint32(item->RecSkill); - if (id == "elemdmgtype") - stat = uint32(item->ElemDmgType); - if (id == "elemdmgamt") - stat = uint32(item->ElemDmgAmt); - if (id == "range") - stat = uint32(item->Range); - if (id == "damage") - stat = uint32(item->Damage); - if (id == "color") - stat = uint32(item->Color); - if (id == "classes") - stat = uint32(item->Classes); - if (id == "races") - stat = uint32(item->Races); - if (id == "maxcharges") - stat = uint32(item->MaxCharges); - if (id == "itemtype") - stat = uint32(item->ItemType); - if (id == "material") - stat = uint32(item->Material); - if (id == "casttime") - stat = uint32(item->CastTime); - if (id == "elitematerial") - stat = uint32(item->EliteMaterial); - if (id == "procrate") - stat = uint32(item->ProcRate); - if (id == "combateffects") - stat = uint32(item->CombatEffects); - if (id == "shielding") - stat = uint32(item->Shielding); - if (id == "stunresist") - stat = uint32(item->StunResist); - if (id == "strikethrough") - stat = uint32(item->StrikeThrough); - if (id == "extradmgskill") - stat = uint32(item->ExtraDmgSkill); - if (id == "extradmgamt") - stat = uint32(item->ExtraDmgAmt); - if (id == "spellshield") - stat = uint32(item->SpellShield); - if (id == "avoidance") - stat = uint32(item->Avoidance); - if (id == "accuracy") - stat = uint32(item->Accuracy); - if (id == "charmfileid") - stat = uint32(item->CharmFileID); - if (id == "factionmod1") - stat = uint32(item->FactionMod1); - if (id == "factionmod2") - stat = uint32(item->FactionMod2); - if (id == "factionmod3") - stat = uint32(item->FactionMod3); - if (id == "factionmod4") - stat = uint32(item->FactionMod4); - if (id == "factionamt1") - stat = uint32(item->FactionAmt1); - if (id == "factionamt2") - stat = uint32(item->FactionAmt2); - if (id == "factionamt3") - stat = uint32(item->FactionAmt3); - if (id == "factionamt4") - stat = uint32(item->FactionAmt4); - if (id == "augtype") - stat = uint32(item->AugType); - if (id == "ldontheme") - stat = uint32(item->LDoNTheme); - if (id == "ldonprice") - stat = uint32(item->LDoNPrice); - if (id == "ldonsold") - stat = uint32(item->LDoNSold); - if (id == "banedmgraceamt") - stat = uint32(item->BaneDmgRaceAmt); - if (id == "augrestrict") - stat = uint32(item->AugRestrict); - if (id == "endur") - stat = uint32(item->Endur); - if (id == "dotshielding") - stat = uint32(item->DotShielding); - if (id == "attack") - stat = uint32(item->Attack); - if (id == "regen") - stat = uint32(item->Regen); - if (id == "manaregen") - stat = uint32(item->ManaRegen); - if (id == "enduranceregen") - stat = uint32(item->EnduranceRegen); - if (id == "haste") - stat = uint32(item->Haste); - if (id == "damageshield") - stat = uint32(item->DamageShield); - if (id == "recastdelay") - stat = uint32(item->RecastDelay); - if (id == "recasttype") - stat = uint32(item->RecastType); - if (id == "augdistiller") - stat = uint32(item->AugDistiller); - if (id == "attuneable") - stat = uint32(item->Attuneable); - if (id == "nopet") - stat = uint32(item->NoPet); - if (id == "potionbelt") - stat = uint32(item->PotionBelt); - if (id == "stackable") - stat = uint32(item->Stackable); - if (id == "notransfer") - stat = uint32(item->NoTransfer); - if (id == "questitemflag") - stat = uint32(item->QuestItemFlag); - if (id == "stacksize") - stat = uint32(item->StackSize); - if (id == "potionbeltslots") - stat = uint32(item->PotionBeltSlots); - if (id == "book") - stat = uint32(item->Book); - if (id == "booktype") - stat = uint32(item->BookType); - if (id == "svcorruption") - stat = uint32(item->SVCorruption); - if (id == "purity") - stat = uint32(item->Purity); - if (id == "backstabdmg") - stat = uint32(item->BackstabDmg); - if (id == "dsmitigation") - stat = uint32(item->DSMitigation); - if (id == "heroicstr") - stat = uint32(item->HeroicStr); - if (id == "heroicint") - stat = uint32(item->HeroicInt); - if (id == "heroicwis") - stat = uint32(item->HeroicWis); - if (id == "heroicagi") - stat = uint32(item->HeroicAgi); - if (id == "heroicdex") - stat = uint32(item->HeroicDex); - if (id == "heroicsta") - stat = uint32(item->HeroicSta); - if (id == "heroiccha") - stat = uint32(item->HeroicCha); - if (id == "heroicmr") - stat = uint32(item->HeroicMR); - if (id == "heroicfr") - stat = uint32(item->HeroicFR); - if (id == "heroiccr") - stat = uint32(item->HeroicCR); - if (id == "heroicdr") - stat = uint32(item->HeroicDR); - if (id == "heroicpr") - stat = uint32(item->HeroicPR); - if (id == "heroicsvcorrup") - stat = uint32(item->HeroicSVCorrup); - if (id == "healamt") - stat = uint32(item->HealAmt); - if (id == "spelldmg") - stat = uint32(item->SpellDmg); - if (id == "ldonsellbackrate") - stat = uint32(item->LDoNSellBackRate); - if (id == "scriptfileid") - stat = uint32(item->ScriptFileID); - if (id == "expendablearrow") - stat = uint32(item->ExpendableArrow); - if (id == "clairvoyance") - stat = uint32(item->Clairvoyance); - // Begin Effects - if (id == "clickeffect") - stat = uint32(item->Click.Effect); - if (id == "clicktype") - stat = uint32(item->Click.Type); - if (id == "clicklevel") - stat = uint32(item->Click.Level); - if (id == "clicklevel2") - stat = uint32(item->Click.Level2); - if (id == "proceffect") - stat = uint32(item->Proc.Effect); - if (id == "proctype") - stat = uint32(item->Proc.Type); - if (id == "proclevel") - stat = uint32(item->Proc.Level); - if (id == "proclevel2") - stat = uint32(item->Proc.Level2); - if (id == "worneffect") - stat = uint32(item->Worn.Effect); - if (id == "worntype") - stat = uint32(item->Worn.Type); - if (id == "wornlevel") - stat = uint32(item->Worn.Level); - if (id == "wornlevel2") - stat = uint32(item->Worn.Level2); - if (id == "focuseffect") - stat = uint32(item->Focus.Effect); - if (id == "focustype") - stat = uint32(item->Focus.Type); - if (id == "focuslevel") - stat = uint32(item->Focus.Level); - if (id == "focuslevel2") - stat = uint32(item->Focus.Level2); - if (id == "scrolleffect") - stat = uint32(item->Scroll.Effect); - if (id == "scrolltype") - stat = uint32(item->Scroll.Type); - if (id == "scrolllevel") - stat = uint32(item->Scroll.Level); - if (id == "scrolllevel2") - stat = uint32(item->Scroll.Level2); - - safe_delete(inst); - return stat; -} - -void Mob::SetGlobal(const char *varname, const char *newvalue, int options, const char *duration, Mob *other) { - - int qgZoneid = zone->GetZoneID(); - int qgCharid = 0; - int qgNpcid = 0; - - if (this->IsNPC()) - { - qgNpcid = this->GetNPCTypeID(); - } - else if (other && other->IsNPC()) - { - qgNpcid = other->GetNPCTypeID(); - } - - if (this->IsClient()) - { - qgCharid = this->CastToClient()->CharacterID(); - } - else if (other && other->IsClient()) - { - qgCharid = other->CastToClient()->CharacterID(); - } - else - { - qgCharid = -qgNpcid; // make char id negative npc id as a fudge - } - - if (options < 0 || options > 7) - { - //cerr << "Invalid options for global var " << varname << " using defaults" << endl; - options = 0; // default = 0 (only this npcid,player and zone) - } - else - { - if (options & 1) - qgNpcid=0; - if (options & 2) - qgCharid=0; - if (options & 4) - qgZoneid=0; - } - - InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, newvalue, QGVarDuration(duration)); -} - -void Mob::TarGlobal(const char *varname, const char *value, const char *duration, int qgNpcid, int qgCharid, int qgZoneid) -{ - InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, value, QGVarDuration(duration)); -} - -void Mob::DelGlobal(const char *varname) { - // delglobal(varname) - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - int qgZoneid=zone->GetZoneID(); - int qgCharid=0; - int qgNpcid=0; - - if (this->IsNPC()) - { - qgNpcid = this->GetNPCTypeID(); - } - - if (this->IsClient()) - { - qgCharid = this->CastToClient()->CharacterID(); - } - else - { - qgCharid = -qgNpcid; // make char id negative npc id as a fudge - } - - if (!database.RunQuery(query, - MakeAnyLenString(&query, - "DELETE FROM quest_globals WHERE name='%s'" - " && (npcid=0 || npcid=%i) && (charid=0 || charid=%i) && (zoneid=%i || zoneid=0)", - varname,qgNpcid,qgCharid,qgZoneid),errbuf)) - { - //_log(QUESTS, "DelGlobal error deleting %s : %s", varname, errbuf); - } - safe_delete_array(query); - - if(zone) - { - ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); - ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct*)pack->pBuffer; - - qgu->npc_id = qgNpcid; - qgu->char_id = qgCharid; - qgu->zone_id = qgZoneid; - strcpy(qgu->name, varname); - - entity_list.DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); - zone->DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); - - worldserver.SendPacket(pack); - safe_delete(pack); - } -} - -// Inserts global variable into quest_globals table -void Mob::InsertQuestGlobal(int charid, int npcid, int zoneid, const char *varname, const char *varvalue, int duration) { - - char *query = 0; - char errbuf[MYSQL_ERRMSG_SIZE]; - - // Make duration string either "unix_timestamp(now()) + xxx" or "NULL" - std::stringstream duration_ss; - - if (duration == INT_MAX) - { - duration_ss << "NULL"; - } - else - { - duration_ss << "unix_timestamp(now()) + " << duration; - } - - //NOTE: this should be escaping the contents of arglist - //npcwise a malicious script can arbitrarily alter the DB - uint32 last_id = 0; - if (!database.RunQuery(query, MakeAnyLenString(&query, - "REPLACE INTO quest_globals (charid, npcid, zoneid, name, value, expdate)" - "VALUES (%i, %i, %i, '%s', '%s', %s)", - charid, npcid, zoneid, varname, varvalue, duration_ss.str().c_str() - ), errbuf)) - { - //_log(QUESTS, "SelGlobal error inserting %s : %s", varname, errbuf); - } - safe_delete_array(query); - - if(zone) - { - //first delete our global - ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); - ServerQGlobalDelete_Struct *qgd = (ServerQGlobalDelete_Struct*)pack->pBuffer; - qgd->npc_id = npcid; - qgd->char_id = charid; - qgd->zone_id = zoneid; - qgd->from_zone_id = zone->GetZoneID(); - qgd->from_instance_id = zone->GetInstanceID(); - strcpy(qgd->name, varname); - - entity_list.DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); - zone->DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); - - worldserver.SendPacket(pack); - safe_delete(pack); - - //then create a new one with the new id - pack = new ServerPacket(ServerOP_QGlobalUpdate, sizeof(ServerQGlobalUpdate_Struct)); - ServerQGlobalUpdate_Struct *qgu = (ServerQGlobalUpdate_Struct*)pack->pBuffer; - qgu->npc_id = npcid; - qgu->char_id = charid; - qgu->zone_id = zoneid; - if(duration == INT_MAX) - { - qgu->expdate = 0xFFFFFFFF; - } - else - { - qgu->expdate = Timer::GetTimeSeconds() + duration; - } - strcpy((char*)qgu->name, varname); - strcpy((char*)qgu->value, varvalue); - qgu->id = last_id; - qgu->from_zone_id = zone->GetZoneID(); - qgu->from_instance_id = zone->GetInstanceID(); - - QGlobal temp; - temp.npc_id = npcid; - temp.char_id = charid; - temp.zone_id = zoneid; - temp.expdate = qgu->expdate; - temp.name.assign(qgu->name); - temp.value.assign(qgu->value); - entity_list.UpdateQGlobal(qgu->id, temp); - zone->UpdateQGlobal(qgu->id, temp); - - worldserver.SendPacket(pack); - safe_delete(pack); - } - -} - -// Converts duration string to duration value (in seconds) -// Return of INT_MAX indicates infinite duration -int Mob::QGVarDuration(const char *fmt) -{ - int duration = 0; - - // format: Y#### or D## or H## or M## or S## or T###### or C####### - - int len = static_cast(strlen(fmt)); - - // Default to no duration - if (len < 1) - return 0; - - // Set val to value after type character - // e.g., for "M3924", set to 3924 - int val = atoi(&fmt[0] + 1); - - switch (fmt[0]) - { - // Forever - case 'F': - case 'f': - duration = INT_MAX; - break; - // Years - case 'Y': - case 'y': - duration = val * 31556926; - break; - case 'D': - case 'd': - duration = val * 86400; - break; - // Hours - case 'H': - case 'h': - duration = val * 3600; - break; - // Minutes - case 'M': - case 'm': - duration = val * 60; - break; - // Seconds - case 'S': - case 's': - duration = val; - break; - // Invalid - default: - duration = 0; - break; - } - - return duration; -} - -void Mob::DoKnockback(Mob *caster, uint32 pushback, uint32 pushup) -{ - if(IsClient()) - { - CastToClient()->SetKnockBackExemption(true); - - EQApplicationPacket* outapp_push = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); - PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp_push->pBuffer; - - double look_heading = caster->CalculateHeadingToTarget(GetX(), GetY()); - look_heading /= 256; - look_heading *= 360; - if(look_heading > 360) - look_heading -= 360; - - //x and y are crossed mkay - double new_x = pushback * sin(double(look_heading * 3.141592 / 180.0)); - double new_y = pushback * cos(double(look_heading * 3.141592 / 180.0)); - - spu->spawn_id = GetID(); - spu->x_pos = FloatToEQ19(GetX()); - spu->y_pos = FloatToEQ19(GetY()); - spu->z_pos = FloatToEQ19(GetZ()); - spu->delta_x = NewFloatToEQ13(static_cast(new_x)); - spu->delta_y = NewFloatToEQ13(static_cast(new_y)); - spu->delta_z = NewFloatToEQ13(static_cast(pushup)); - spu->heading = FloatToEQ19(GetHeading()); - spu->padding0002 =0; - spu->padding0006 =7; - spu->padding0014 =0x7f; - spu->padding0018 =0x5df27; - spu->animation = 0; - spu->delta_heading = NewFloatToEQ13(0); - outapp_push->priority = 6; - entity_list.QueueClients(this, outapp_push, true); - CastToClient()->FastQueuePacket(&outapp_push); - } -} - -void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) -{ - if (spell_id != SPELL_UNKNOWN) - { - if(IsEffectInSpell(spell_id, SE_ProcOnSpellKillShot)) { - for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[spell_id].effectid[i] == SE_ProcOnSpellKillShot) - { - if (IsValidSpell(spells[spell_id].base2[i]) && spells[spell_id].max[i] <= level) - { - if(MakeRandomInt(0,99) < spells[spell_id].base[i]) - SpellFinished(spells[spell_id].base2[i], this, 10, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); - } - } - } - } - } - - if (!aabonuses.SpellOnKill[0] && !itembonuses.SpellOnKill[0] && !spellbonuses.SpellOnKill[0]) - return; - - // Allow to check AA, items and buffs in all cases. Base2 = Spell to fire | Base1 = % chance | Base3 = min level - for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) { - - if(aabonuses.SpellOnKill[i] && IsValidSpell(aabonuses.SpellOnKill[i]) && (level >= aabonuses.SpellOnKill[i + 2])) { - if(MakeRandomInt(0, 99) < static_cast(aabonuses.SpellOnKill[i + 1])) - SpellFinished(aabonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); - } - - if(itembonuses.SpellOnKill[i] && IsValidSpell(itembonuses.SpellOnKill[i]) && (level >= itembonuses.SpellOnKill[i + 2])){ - if(MakeRandomInt(0, 99) < static_cast(itembonuses.SpellOnKill[i + 1])) - SpellFinished(itembonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); - } - - if(spellbonuses.SpellOnKill[i] && IsValidSpell(spellbonuses.SpellOnKill[i]) && (level >= spellbonuses.SpellOnKill[i + 2])) { - if(MakeRandomInt(0, 99) < static_cast(spellbonuses.SpellOnKill[i + 1])) - SpellFinished(spellbonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); - } - - } -} - -bool Mob::TrySpellOnDeath() -{ - if (IsNPC() && !spellbonuses.SpellOnDeath[0] && !itembonuses.SpellOnDeath[0]) - return false; - - if (IsClient() && !aabonuses.SpellOnDeath[0] && !spellbonuses.SpellOnDeath[0] && !itembonuses.SpellOnDeath[0]) - return false; - - for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) { - if(IsClient() && aabonuses.SpellOnDeath[i] && IsValidSpell(aabonuses.SpellOnDeath[i])) { - if(MakeRandomInt(0, 99) < static_cast(aabonuses.SpellOnDeath[i + 1])) { - SpellFinished(aabonuses.SpellOnDeath[i], this, 10, 0, -1, spells[aabonuses.SpellOnDeath[i]].ResistDiff); - } - } - - if(itembonuses.SpellOnDeath[i] && IsValidSpell(itembonuses.SpellOnDeath[i])) { - if(MakeRandomInt(0, 99) < static_cast(itembonuses.SpellOnDeath[i + 1])) { - SpellFinished(itembonuses.SpellOnDeath[i], this, 10, 0, -1, spells[itembonuses.SpellOnDeath[i]].ResistDiff); - } - } - - if(spellbonuses.SpellOnDeath[i] && IsValidSpell(spellbonuses.SpellOnDeath[i])) { - if(MakeRandomInt(0, 99) < static_cast(spellbonuses.SpellOnDeath[i + 1])) { - SpellFinished(spellbonuses.SpellOnDeath[i], this, 10, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff); - } - } - } - - BuffFadeAll(); - return false; - //You should not be able to use this effect and survive (ALWAYS return false), - //attempting to place a heal in these effects will still result - //in death because the heal will not register before the script kills you. -} - -int16 Mob::GetCritDmgMob(uint16 skill) -{ - int critDmg_mod = 0; - - // All skill dmg mod + Skill specific - critDmg_mod += itembonuses.CritDmgMob[HIGHEST_SKILL+1] + spellbonuses.CritDmgMob[HIGHEST_SKILL+1] + aabonuses.CritDmgMob[HIGHEST_SKILL+1] + - itembonuses.CritDmgMob[skill] + spellbonuses.CritDmgMob[skill] + aabonuses.CritDmgMob[skill]; - - if(critDmg_mod < -100) - critDmg_mod = -100; - - return critDmg_mod; -} - -void Mob::SetGrouped(bool v) -{ - if(v) - { - israidgrouped = false; - } - isgrouped = v; - - if(IsClient()) - { - parse->EventPlayer(EVENT_GROUP_CHANGE, CastToClient(), "", 0); - - if(!v) - CastToClient()->RemoveGroupXTargets(); - } -} - -void Mob::SetRaidGrouped(bool v) -{ - if(v) - { - isgrouped = false; - } - israidgrouped = v; - - if(IsClient()) - { - parse->EventPlayer(EVENT_GROUP_CHANGE, CastToClient(), "", 0); - } -} - -int16 Mob::GetCriticalChanceBonus(uint16 skill) -{ - int critical_chance = 0; - - // All skills + Skill specific - critical_chance += itembonuses.CriticalHitChance[HIGHEST_SKILL+1] + spellbonuses.CriticalHitChance[HIGHEST_SKILL+1] + aabonuses.CriticalHitChance[HIGHEST_SKILL+1] + - itembonuses.CriticalHitChance[skill] + spellbonuses.CriticalHitChance[skill] + aabonuses.CriticalHitChance[skill]; - - if(critical_chance < -100) - critical_chance = -100; - - return critical_chance; -} - -int16 Mob::GetMeleeDamageMod_SE(uint16 skill) -{ - int dmg_mod = 0; - - // All skill dmg mod + Skill specific - dmg_mod += itembonuses.DamageModifier[HIGHEST_SKILL+1] + spellbonuses.DamageModifier[HIGHEST_SKILL+1] + aabonuses.DamageModifier[HIGHEST_SKILL+1] + - itembonuses.DamageModifier[skill] + spellbonuses.DamageModifier[skill] + aabonuses.DamageModifier[skill]; - - dmg_mod += itembonuses.DamageModifier2[HIGHEST_SKILL+1] + spellbonuses.DamageModifier2[HIGHEST_SKILL+1] + aabonuses.DamageModifier2[HIGHEST_SKILL+1] + - itembonuses.DamageModifier2[skill] + spellbonuses.DamageModifier2[skill] + aabonuses.DamageModifier2[skill]; - - if (HasShieldEquiped() && !IsOffHandAtk()) - dmg_mod += itembonuses.ShieldEquipDmgMod[0] + spellbonuses.ShieldEquipDmgMod[0] + aabonuses.ShieldEquipDmgMod[0]; - - if(dmg_mod < -100) - dmg_mod = -100; - - return dmg_mod; -} - -int16 Mob::GetMeleeMinDamageMod_SE(uint16 skill) -{ - int dmg_mod = 0; - - dmg_mod = itembonuses.MinDamageModifier[skill] + spellbonuses.MinDamageModifier[skill] + - itembonuses.MinDamageModifier[HIGHEST_SKILL+1] + spellbonuses.MinDamageModifier[HIGHEST_SKILL+1]; - - if(dmg_mod < -100) - dmg_mod = -100; - - return dmg_mod; -} - -int16 Mob::GetCrippBlowChance() -{ - int16 crip_chance = 0; - - crip_chance += itembonuses.CrippBlowChance + spellbonuses.CrippBlowChance + aabonuses.CrippBlowChance; - - if(crip_chance < 0) - crip_chance = 0; - - return crip_chance; -} - -int16 Mob::GetSkillReuseTime(uint16 skill) -{ - int skill_reduction = this->itembonuses.SkillReuseTime[skill] + this->spellbonuses.SkillReuseTime[skill] + this->aabonuses.SkillReuseTime[skill]; - - return skill_reduction; -} - -int16 Mob::GetSkillDmgAmt(uint16 skill) -{ - int skill_dmg = 0; - - // All skill dmg(only spells do this) + Skill specific - skill_dmg += spellbonuses.SkillDamageAmount[HIGHEST_SKILL+1] + itembonuses.SkillDamageAmount[HIGHEST_SKILL+1] + aabonuses.SkillDamageAmount[HIGHEST_SKILL+1] - + itembonuses.SkillDamageAmount[skill] + spellbonuses.SkillDamageAmount[skill] + aabonuses.SkillDamageAmount[skill]; - - skill_dmg += spellbonuses.SkillDamageAmount2[HIGHEST_SKILL+1] + itembonuses.SkillDamageAmount2[HIGHEST_SKILL+1] - + itembonuses.SkillDamageAmount2[skill] + spellbonuses.SkillDamageAmount2[skill]; - - return skill_dmg; -} - -void Mob::MeleeLifeTap(int32 damage) { - - int16 lifetap_amt = 0; - lifetap_amt = spellbonuses.MeleeLifetap + itembonuses.MeleeLifetap + aabonuses.MeleeLifetap - + spellbonuses.Vampirism + itembonuses.Vampirism + aabonuses.Vampirism; - - if(lifetap_amt && damage > 0){ - - lifetap_amt = damage * lifetap_amt / 100; - mlog(COMBAT__DAMAGE, "Melee lifetap healing for %d damage.", damage); - - if (lifetap_amt > 0) - HealDamage(lifetap_amt); //Heal self for modified damage amount. - else - Damage(this, -lifetap_amt,0, SkillEvocation,false); //Dmg self for modified damage amount. - } -} - -bool Mob::TryReflectSpell(uint32 spell_id) -{ - if (!spells[spell_id].reflectable) - return false; - - int chance = itembonuses.reflect_chance + spellbonuses.reflect_chance + aabonuses.reflect_chance; - - if(chance && MakeRandomInt(0, 99) < chance) - return true; - - return false; -} - -void Mob::SpellProjectileEffect() -{ - bool time_disable = false; - - for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { - - if (projectile_increment[i] == 0){ - continue; - } - - Mob* target = entity_list.GetMobID(projectile_target_id[i]); - - float dist = 0; - - if (target) - dist = target->CalculateDistance(projectile_x[i], projectile_y[i], projectile_z[i]); - - int increment_end = 0; - increment_end = (dist / 10) - 1; //This pretty accurately determines end time for speed for 1.5 and timer of 250 ms - - if (increment_end <= projectile_increment[i]){ - - if (target && IsValidSpell(projectile_spell_id[i])) - SpellOnTarget(projectile_spell_id[i], target, false, true, spells[projectile_spell_id[i]].ResistDiff, true); - - projectile_spell_id[i] = 0; - projectile_target_id[i] = 0; - projectile_x[i] = 0, projectile_y[i] = 0, projectile_z[i] = 0; - projectile_increment[i] = 0; - time_disable = true; - } - - else { - projectile_increment[i]++; - time_disable = false; - } - } - - if (time_disable) - projectile_timer.Disable(); -} - - -void Mob::DoGravityEffect() -{ - Mob *caster = nullptr; - int away = -1; - float caster_x, caster_y, amount, value, cur_x, my_x, cur_y, my_y, x_vector, y_vector, hypot; - - // Set values so we can run through all gravity effects and then apply the culmative move at the end - // instead of many small moves if the mob/client had more than 1 gravity effect on them - cur_x = my_x = GetX(); - cur_y = my_y = GetY(); - - int buff_count = GetMaxTotalSlots(); - for (int slot = 0; slot < buff_count; slot++) - { - if (buffs[slot].spellid != SPELL_UNKNOWN && IsEffectInSpell(buffs[slot].spellid, SE_GravityEffect)) - { - for (int i = 0; i < EFFECT_COUNT; i++) - { - if(spells[buffs[slot].spellid].effectid[i] == SE_GravityEffect) { - - int casterId = buffs[slot].casterid; - if(casterId) - caster = entity_list.GetMob(casterId); - - if(!caster || casterId == this->GetID()) - continue; - - caster_x = caster->GetX(); - caster_y = caster->GetY(); - - value = static_cast(spells[buffs[slot].spellid].base[i]); - if(value == 0) - continue; - - if(value > 0) - away = 1; - - amount = fabs(value) / (100.0f); // to bring the values in line, arbitarily picked - - x_vector = cur_x - caster_x; - y_vector = cur_y - caster_y; - hypot = sqrt(x_vector*x_vector + y_vector*y_vector); - - if(hypot <= 5) // dont want to be inside the mob, even though we can, it looks bad - continue; - - x_vector /= hypot; - y_vector /= hypot; - - cur_x = cur_x + (x_vector * amount * away); - cur_y = cur_y + (y_vector * amount * away); - } - } - } - } - - if((fabs(my_x - cur_x) > 0.01) || (fabs(my_y - cur_y) > 0.01)) { - float new_ground = GetGroundZ(cur_x, cur_y); - // If we cant get LoS on our new spot then keep checking up to 5 units up. - if(!CheckLosFN(cur_x, cur_y, new_ground, GetSize())) { - for(float z_adjust = 0.1f; z_adjust < 5; z_adjust += 0.1f) { - if(CheckLosFN(cur_x, cur_y, new_ground+z_adjust, GetSize())) { - new_ground += z_adjust; - break; - } - } - // If we still fail, then lets only use the x portion(ie sliding around a wall) - if(!CheckLosFN(cur_x, my_y, new_ground, GetSize())) { - // If that doesnt work, try the y - if(!CheckLosFN(my_x, cur_y, new_ground, GetSize())) { - // If everything fails, then lets do nothing - return; - } - else { - cur_x = my_x; - } - } - else { - cur_y = my_y; - } - } - - if(IsClient()) - this->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), cur_x, cur_y, new_ground, GetHeading()*2); // I know the heading thing is weird(chance of movepc to halve the heading value, too lazy to figure out why atm) - else - this->GMMove(cur_x, cur_y, new_ground, GetHeading()); - } -} - -void Mob::SpreadVirus(uint16 spell_id, uint16 casterID) -{ - int num_targs = spells[spell_id].viral_targets; - - Mob* caster = entity_list.GetMob(casterID); - Mob* target = nullptr; - // Only spread in zones without perm buffs - if(!zone->BuffTimersSuspended()) { - for(int i = 0; i < num_targs; i++) { - target = entity_list.GetTargetForVirus(this); - if(target) { - // Only spreads to the uninfected - if(!target->FindBuff(spell_id)) { - if(caster) - caster->SpellOnTarget(spell_id, target); - - } - } - } - } -} - -void Mob::RemoveNimbusEffect(int effectid) -{ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RemoveNimbusEffect, sizeof(RemoveNimbusEffect_Struct)); - RemoveNimbusEffect_Struct* rne = (RemoveNimbusEffect_Struct*)outapp->pBuffer; - rne->spawnid = GetID(); - rne->nimbus_effect = effectid; - entity_list.QueueClients(this, outapp); - safe_delete(outapp); -} - -bool Mob::IsBoat() const { - return (race == 72 || race == 73 || race == 114 || race == 404 || race == 550 || race == 551 || race == 552); -} - -void Mob::SetBodyType(bodyType new_body, bool overwrite_orig) { - bool needs_spawn_packet = false; - if(bodytype == 11 || bodytype >= 65 || new_body == 11 || new_body >= 65) { - needs_spawn_packet = true; - } - - if(overwrite_orig) { - orig_bodytype = new_body; - } - bodytype = new_body; - - if(needs_spawn_packet) { - EQApplicationPacket* app = new EQApplicationPacket; - CreateDespawnPacket(app, true); - entity_list.QueueClients(this, app); - CreateSpawnPacket(app, this); - entity_list.QueueClients(this, app); - safe_delete(app); - } -} - - -void Mob::ModSkillDmgTaken(SkillUseTypes skill_num, int value) -{ - if (skill_num <= HIGHEST_SKILL) - SkillDmgTaken_Mod[skill_num] = value; - - - else if (skill_num == 255 || skill_num == -1) - SkillDmgTaken_Mod[HIGHEST_SKILL+1] = value; -} - -int16 Mob::GetModSkillDmgTaken(const SkillUseTypes skill_num) -{ - if (skill_num <= HIGHEST_SKILL) - return SkillDmgTaken_Mod[skill_num]; - - else if (skill_num == 255 || skill_num == -1) - return SkillDmgTaken_Mod[HIGHEST_SKILL+1]; - - return 0; -} - -void Mob::ModVulnerability(uint8 resist, int16 value) -{ - if (resist < HIGHEST_RESIST+1) - Vulnerability_Mod[resist] = value; - - else if (resist == 255) - Vulnerability_Mod[HIGHEST_RESIST+1] = value; -} - -int16 Mob::GetModVulnerability(const uint8 resist) -{ - if (resist < HIGHEST_RESIST+1) - return Vulnerability_Mod[resist]; - - else if (resist == 255) - return Vulnerability_Mod[HIGHEST_RESIST+1]; - - return 0; -} - -void Mob::CastOnCurer(uint32 spell_id) -{ - for(int i = 0; i < EFFECT_COUNT; i++) - { - if (spells[spell_id].effectid[i] == SE_CastOnCurer) - { - if(IsValidSpell(spells[spell_id].base[i])) - { - SpellFinished(spells[spell_id].base[i], this); - } - } - } -} - -void Mob::CastOnCure(uint32 spell_id) -{ - for(int i = 0; i < EFFECT_COUNT; i++) - { - if (spells[spell_id].effectid[i] == SE_CastOnCure) - { - if(IsValidSpell(spells[spell_id].base[i])) - { - SpellFinished(spells[spell_id].base[i], this); - } - } - } -} - -void Mob::CastOnNumHitFade(uint32 spell_id) -{ - if(!IsValidSpell(spell_id)) - return; - - for(int i = 0; i < EFFECT_COUNT; i++) - { - if (spells[spell_id].effectid[i] == SE_CastonNumHitFade) - { - if(IsValidSpell(spells[spell_id].base[i])) - { - SpellFinished(spells[spell_id].base[i], this); - } - } - } -} - -void Mob::SlowMitigation(Mob* caster) -{ - if (GetSlowMitigation() && caster && caster->IsClient()) - { - if ((GetSlowMitigation() > 0) && (GetSlowMitigation() < 26)) - caster->Message_StringID(MT_SpellFailure, SLOW_MOSTLY_SUCCESSFUL); - - else if ((GetSlowMitigation() >= 26) && (GetSlowMitigation() < 74)) - caster->Message_StringID(MT_SpellFailure, SLOW_PARTIALLY_SUCCESSFUL); - - else if ((GetSlowMitigation() >= 74) && (GetSlowMitigation() < 101)) - caster->Message_StringID(MT_SpellFailure, SLOW_SLIGHTLY_SUCCESSFUL); - - else if (GetSlowMitigation() > 100) - caster->Message_StringID(MT_SpellFailure, SPELL_OPPOSITE_EFFECT); - } -} - -uint16 Mob::GetSkillByItemType(int ItemType) -{ - switch (ItemType) - { - case ItemType1HSlash: - return Skill1HSlashing; - case ItemType2HSlash: - return Skill2HSlashing; - case ItemType1HPiercing: - return Skill1HPiercing; - case ItemType1HBlunt: - return Skill1HBlunt; - case ItemType2HBlunt: - return Skill2HBlunt; - case ItemType2HPiercing: - return Skill1HPiercing; // change to 2HPiercing once activated - case ItemTypeMartial: - return SkillHandtoHand; - default: - return SkillHandtoHand; - } - return SkillHandtoHand; - } - - -bool Mob::PassLimitToSkill(uint16 spell_id, uint16 skill) { - - if (!IsValidSpell(spell_id)) - return false; - - for (int i = 0; i < EFFECT_COUNT; i++) { - if (spells[spell_id].effectid[i] == SE_LimitToSkill){ - if (spells[spell_id].base[i] == skill){ - return true; - } - } - } - return false; -} - -uint16 Mob::GetWeaponSpeedbyHand(uint16 hand) { - - uint16 weapon_speed = 0; - switch (hand) { - - case 13: - weapon_speed = attack_timer.GetDuration(); - break; - case 14: - weapon_speed = attack_dw_timer.GetDuration(); - break; - case 11: - weapon_speed = ranged_timer.GetDuration(); - break; - } - - if (weapon_speed < RuleI(Combat, MinHastedDelay)) - weapon_speed = RuleI(Combat, MinHastedDelay); - - return weapon_speed; -} - -int8 Mob::GetDecayEffectValue(uint16 spell_id, uint16 spelleffect) { - - if (!IsValidSpell(spell_id)) - return false; - - int spell_level = spells[spell_id].classes[(GetClass()%16) - 1]; - int effect_value = 0; - int lvlModifier = 100; - - int buff_count = GetMaxTotalSlots(); - for (int slot = 0; slot < buff_count; slot++){ - if (IsValidSpell(buffs[slot].spellid)){ - for (int i = 0; i < EFFECT_COUNT; i++){ - if(spells[buffs[slot].spellid].effectid[i] == spelleffect) { - - int critchance = spells[buffs[slot].spellid].base[i]; - int decay = spells[buffs[slot].spellid].base2[i]; - int lvldiff = spell_level - spells[buffs[slot].spellid].max[i]; - - if(lvldiff > 0 && decay > 0) - { - lvlModifier -= decay*lvldiff; - if (lvlModifier > 0){ - critchance = (critchance*lvlModifier)/100; - effect_value += critchance; - } - } - - else - effect_value += critchance; - } - } - } - } - - return effect_value; -} - -// Faction Mods for Alliance type spells -void Mob::AddFactionBonus(uint32 pFactionID,int32 bonus) { - std::map :: const_iterator faction_bonus; - typedef std::pair NewFactionBonus; - - faction_bonus = faction_bonuses.find(pFactionID); - if(faction_bonus == faction_bonuses.end()) - { - faction_bonuses.insert(NewFactionBonus(pFactionID,bonus)); - } - else - { - if(faction_bonus->second :: const_iterator faction_bonus; - typedef std::pair NewFactionBonus; - - faction_bonus = item_faction_bonuses.find(pFactionID); - if(faction_bonus == item_faction_bonuses.end()) - { - item_faction_bonuses.insert(NewFactionBonus(pFactionID,bonus)); - } - else - { - if((bonus > 0 && faction_bonus->second < bonus) || (bonus < 0 && faction_bonus->second > bonus)) - { - item_faction_bonuses.erase(pFactionID); - item_faction_bonuses.insert(NewFactionBonus(pFactionID,bonus)); - } - } -} - -int32 Mob::GetFactionBonus(uint32 pFactionID) { - std::map :: const_iterator faction_bonus; - faction_bonus = faction_bonuses.find(pFactionID); - if(faction_bonus != faction_bonuses.end()) - { - return (*faction_bonus).second; - } - return 0; -} - -int32 Mob::GetItemFactionBonus(uint32 pFactionID) { - std::map :: const_iterator faction_bonus; - faction_bonus = item_faction_bonuses.find(pFactionID); - if(faction_bonus != item_faction_bonuses.end()) - { - return (*faction_bonus).second; - } - return 0; -} - -void Mob::ClearItemFactionBonuses() { - item_faction_bonuses.clear(); -} - -FACTION_VALUE Mob::GetSpecialFactionCon(Mob* iOther) { - if (!iOther) - return FACTION_INDIFFERENT; - - iOther = iOther->GetOwnerOrSelf(); - Mob* self = this->GetOwnerOrSelf(); - - bool selfAIcontrolled = self->IsAIControlled(); - bool iOtherAIControlled = iOther->IsAIControlled(); - int selfPrimaryFaction = self->GetPrimaryFaction(); - int iOtherPrimaryFaction = iOther->GetPrimaryFaction(); - - if (selfPrimaryFaction >= 0 && selfAIcontrolled) - return FACTION_INDIFFERENT; - if (iOther->GetPrimaryFaction() >= 0) - return FACTION_INDIFFERENT; -/* special values: - -2 = indiff to player, ally to AI on special values, indiff to AI - -3 = dub to player, ally to AI on special values, indiff to AI - -4 = atk to player, ally to AI on special values, indiff to AI - -5 = indiff to player, indiff to AI - -6 = dub to player, indiff to AI - -7 = atk to player, indiff to AI - -8 = indiff to players, ally to AI on same value, indiff to AI - -9 = dub to players, ally to AI on same value, indiff to AI - -10 = atk to players, ally to AI on same value, indiff to AI - -11 = indiff to players, ally to AI on same value, atk to AI - -12 = dub to players, ally to AI on same value, atk to AI - -13 = atk to players, ally to AI on same value, atk to AI -*/ - switch (iOtherPrimaryFaction) { - case -2: // -2 = indiff to player, ally to AI on special values, indiff to AI - if (selfAIcontrolled && iOtherAIControlled) - return FACTION_ALLY; - else - return FACTION_INDIFFERENT; - case -3: // -3 = dub to player, ally to AI on special values, indiff to AI - if (selfAIcontrolled && iOtherAIControlled) - return FACTION_ALLY; - else - return FACTION_DUBIOUS; - case -4: // -4 = atk to player, ally to AI on special values, indiff to AI - if (selfAIcontrolled && iOtherAIControlled) - return FACTION_ALLY; - else - return FACTION_SCOWLS; - case -5: // -5 = indiff to player, indiff to AI - return FACTION_INDIFFERENT; - case -6: // -6 = dub to player, indiff to AI - if (selfAIcontrolled && iOtherAIControlled) - return FACTION_INDIFFERENT; - else - return FACTION_DUBIOUS; - case -7: // -7 = atk to player, indiff to AI - if (selfAIcontrolled && iOtherAIControlled) - return FACTION_INDIFFERENT; - else - return FACTION_SCOWLS; - case -8: // -8 = indiff to players, ally to AI on same value, indiff to AI - if (selfAIcontrolled && iOtherAIControlled) { - if (selfPrimaryFaction == iOtherPrimaryFaction) - return FACTION_ALLY; - else - return FACTION_INDIFFERENT; - } - else - return FACTION_INDIFFERENT; - case -9: // -9 = dub to players, ally to AI on same value, indiff to AI - if (selfAIcontrolled && iOtherAIControlled) { - if (selfPrimaryFaction == iOtherPrimaryFaction) - return FACTION_ALLY; - else - return FACTION_INDIFFERENT; - } - else - return FACTION_DUBIOUS; - case -10: // -10 = atk to players, ally to AI on same value, indiff to AI - if (selfAIcontrolled && iOtherAIControlled) { - if (selfPrimaryFaction == iOtherPrimaryFaction) - return FACTION_ALLY; - else - return FACTION_INDIFFERENT; - } - else - return FACTION_SCOWLS; - case -11: // -11 = indiff to players, ally to AI on same value, atk to AI - if (selfAIcontrolled && iOtherAIControlled) { - if (selfPrimaryFaction == iOtherPrimaryFaction) - return FACTION_ALLY; - else - return FACTION_SCOWLS; - } - else - return FACTION_INDIFFERENT; - case -12: // -12 = dub to players, ally to AI on same value, atk to AI - if (selfAIcontrolled && iOtherAIControlled) { - if (selfPrimaryFaction == iOtherPrimaryFaction) - return FACTION_ALLY; - else - return FACTION_SCOWLS; - - - } - else - return FACTION_DUBIOUS; - case -13: // -13 = atk to players, ally to AI on same value, atk to AI - if (selfAIcontrolled && iOtherAIControlled) { - if (selfPrimaryFaction == iOtherPrimaryFaction) - return FACTION_ALLY; - else - return FACTION_SCOWLS; - } - else - return FACTION_SCOWLS; - default: - return FACTION_INDIFFERENT; - } -} - -bool Mob::HasSpellEffect(int effectid) -{ - int i; - - uint32 buff_count = GetMaxTotalSlots(); - for(i = 0; i < buff_count; i++) - { - if(buffs[i].spellid == SPELL_UNKNOWN) { continue; } - - if(IsEffectInSpell(buffs[i].spellid, effectid)) - { - return(1); - } - } - return(0); -} - -int Mob::GetSpecialAbility(int ability) { - if(ability >= MAX_SPECIAL_ATTACK || ability < 0) { - return 0; - } - - return SpecialAbilities[ability].level; -} - -int Mob::GetSpecialAbilityParam(int ability, int param) { - if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0 || ability >= MAX_SPECIAL_ATTACK || ability < 0) { - return 0; - } - - return SpecialAbilities[ability].params[param]; -} - -void Mob::SetSpecialAbility(int ability, int level) { - if(ability >= MAX_SPECIAL_ATTACK || ability < 0) { - return; - } - - SpecialAbilities[ability].level = level; -} - -void Mob::SetSpecialAbilityParam(int ability, int param, int value) { - if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0 || ability >= MAX_SPECIAL_ATTACK || ability < 0) { - return; - } - - SpecialAbilities[ability].params[param] = value; -} - -void Mob::StartSpecialAbilityTimer(int ability, uint32 time) { - if (ability >= MAX_SPECIAL_ATTACK || ability < 0) { - return; - } - - if(SpecialAbilities[ability].timer) { - SpecialAbilities[ability].timer->Start(time); - } else { - SpecialAbilities[ability].timer = new Timer(time); - SpecialAbilities[ability].timer->Start(); - } -} - -void Mob::StopSpecialAbilityTimer(int ability) { - if (ability >= MAX_SPECIAL_ATTACK || ability < 0) { - return; - } - - safe_delete(SpecialAbilities[ability].timer); -} - -Timer *Mob::GetSpecialAbilityTimer(int ability) { - if (ability >= MAX_SPECIAL_ATTACK || ability < 0) { - return nullptr; - } - - return SpecialAbilities[ability].timer; -} - -void Mob::ClearSpecialAbilities() { - for(int a = 0; a < MAX_SPECIAL_ATTACK; ++a) { - SpecialAbilities[a].level = 0; - safe_delete(SpecialAbilities[a].timer); - for(int p = 0; p < MAX_SPECIAL_ATTACK_PARAMS; ++p) { - SpecialAbilities[a].params[p] = 0; - } - } -} - -void Mob::ProcessSpecialAbilities(const std::string str) { - ClearSpecialAbilities(); - - std::vector sp = SplitString(str, '^'); - for(auto iter = sp.begin(); iter != sp.end(); ++iter) { - std::vector sub_sp = SplitString((*iter), ','); - if(sub_sp.size() >= 2) { - int ability = std::stoi(sub_sp[0]); - int value = std::stoi(sub_sp[1]); - - SetSpecialAbility(ability, value); - switch(ability) { - case SPECATK_QUAD: - if(value > 0) { - SetSpecialAbility(SPECATK_TRIPLE, 1); - } - break; - case DESTRUCTIBLE_OBJECT: - if(value == 0) { - SetDestructibleObject(false); - } else { - SetDestructibleObject(true); - } - break; - default: - break; - } - - for(size_t i = 2, p = 0; i < sub_sp.size(); ++i, ++p) { - if(p >= MAX_SPECIAL_ATTACK_PARAMS) { - break; - } - - SetSpecialAbilityParam(ability, p, std::stoi(sub_sp[i])); - } - } - } -} - -// derived from client to keep these functions more consistent -// if anything seems weird, blame SoE -bool Mob::IsFacingMob(Mob *other) -{ - if (!other) - return false; - float angle = HeadingAngleToMob(other); - // what the client uses appears to be 2x our internal heading - float heading = GetHeading() * 2.0; - - if (angle > 472.0 && heading < 40.0) - angle = heading; - if (angle < 40.0 && heading > 472.0) - angle = heading; - - if (fabs(angle - heading) <= 80.0) - return true; - - return false; -} - -// All numbers derived from the client -float Mob::HeadingAngleToMob(Mob *other) -{ - float mob_x = other->GetX(); - float mob_y = other->GetY(); - float this_x = GetX(); - float this_y = GetY(); - - float y_diff = fabs(this_y - mob_y); - float x_diff = fabs(this_x - mob_x); - if (y_diff < 0.0000009999999974752427) - y_diff = 0.0000009999999974752427; - - float angle = atan2(x_diff, y_diff) * 180.0 * 0.3183099014828645; // angle, nice "pi" - - // return the right thing based on relative quadrant - // I'm sure this could be improved for readability, but whatever - if (this_y >= mob_y) { - if (mob_x >= this_x) - return (90.0 - angle + 90.0) * 511.5 * 0.0027777778; - if (mob_x <= this_x) - return (angle + 180.0) * 511.5 * 0.0027777778; - } - if (this_y > mob_y || mob_x > this_x) - return angle * 511.5 * 0.0027777778; - else - return (90.0 - angle + 270.0) * 511.5 * 0.0027777778; -} - diff --git a/zone/mobx.h b/zone/mobx.h deleted file mode 100644 index 4cd6d5f49..000000000 --- a/zone/mobx.h +++ /dev/null @@ -1,1236 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#ifndef MOB_H -#define MOB_H - -#include "../common/features.h" -#include "common.h" -#include "entity.h" -#include "hate_list.h" -#include "pathing.h" -#include -#include -#include - -char* strn0cpy(char* dest, const char* source, uint32 size); - -#define MAX_SPECIAL_ATTACK_PARAMS 8 - -class EGNode; -class MobFearState; -class Mob : public Entity { -public: - enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD, - CLIENT_KICKED, DISCONNECTED, CLIENT_ERROR, CLIENT_CONNECTINGALL }; - enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard }; - - struct SpecialAbility { - SpecialAbility() { - level = 0; - timer = nullptr; - for(int i = 0; i < MAX_SPECIAL_ATTACK_PARAMS; ++i) { - params[i] = 0; - } - } - - ~SpecialAbility() { - safe_delete(timer); - } - - int level; - Timer *timer; - int params[MAX_SPECIAL_ATTACK_PARAMS]; - }; - - Mob(const char* in_name, - const char* in_lastname, - int32 in_cur_hp, - int32 in_max_hp, - uint8 in_gender, - uint16 in_race, - uint8 in_class, - bodyType in_bodytype, - uint8 in_deity, - uint8 in_level, - uint32 in_npctype_id, - float in_size, - float in_runspeed, - float in_heading, - float in_x_pos, - float in_y_pos, - float in_z_pos, - uint8 in_light, - uint8 in_texture, - uint8 in_helmtexture, - uint16 in_ac, - uint16 in_atk, - uint16 in_str, - uint16 in_sta, - uint16 in_dex, - uint16 in_agi, - uint16 in_int, - uint16 in_wis, - uint16 in_cha, - uint8 in_haircolor, - uint8 in_beardcolor, - uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye? - uint8 in_eyecolor2, - uint8 in_hairstyle, - uint8 in_luclinface, - uint8 in_beard, - uint32 in_drakkin_heritage, - uint32 in_drakkin_tattoo, - uint32 in_drakkin_details, - uint32 in_armor_tint[_MaterialCount], - uint8 in_aa_title, - uint8 in_see_invis, // see through invis - uint8 in_see_invis_undead, // see through invis vs. undead - uint8 in_see_hide, - uint8 in_see_improved_hide, - int32 in_hp_regen, - int32 in_mana_regen, - uint8 in_qglobal, - uint8 in_maxlevel, - uint32 in_scalerate - ); - virtual ~Mob(); - - inline virtual bool IsMob() const { return true; } - inline virtual bool InZone() const { return true; } - - //Somewhat sorted: needs documenting! - - //Attack - virtual void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10); - virtual void RogueAssassinate(Mob* other); // solar - float MobAngle(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const; - // greater than 90 is behind - inline bool BehindMob(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const - { return (!other || other == this) ? true : MobAngle(other, ourx, oury) > 90.0f; } - // less than 56 is in front, greater than 56 is usually where the client generates the messages - inline bool InFrontMob(Mob *other = 0, float ourx = 0.0f, float oury = 0.0f) const - { return (!other || other == this) ? true : MobAngle(other, ourx, oury) < 56.0f; } - bool IsFacingMob(Mob *other); // kind of does the same as InFrontMob, but derived from client - float HeadingAngleToMob(Mob *other); // to keep consistent with client generated messages - virtual void RangedAttack(Mob* other) { } - virtual void ThrowingAttack(Mob* other) { } - uint16 GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg); - // 13 = Primary (default), 14 = secondary - virtual bool Attack(Mob* other, int Hand = 13, bool FromRiposte = false, bool IsStrikethrough = false, - bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) = 0; - int MonkSpecialAttack(Mob* other, uint8 skill_used); - virtual void TryBackstab(Mob *other,int ReuseTime = 10); - void TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand = 13, int damage = 0); - virtual bool AvoidDamage(Mob* attacker, int32 &damage, bool CanRiposte = true); - virtual bool CheckHitChance(Mob* attacker, SkillUseTypes skillinuse, int Hand, int16 chance_mod = 0); - virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts = nullptr); - void TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage); - virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse); - uint32 TryHeadShot(Mob* defender, SkillUseTypes skillInUse); - uint32 TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 ReuseTime); - virtual void DoRiposte(Mob* defender); - void ApplyMeleeDamageBonus(uint16 skill, int32 &damage); - virtual void MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts = nullptr); - virtual int32 GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating); - bool CombatRange(Mob* other); - virtual inline bool IsBerserk() { return false; } // only clients - void RogueEvade(Mob *other); - - //Appearance - void SendLevelAppearance(); - void SendStunAppearance(); - void SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, - Client *specific_target=nullptr); - void SendTargetable(bool on, Client *specific_target = nullptr); - virtual void SendWearChange(uint8 material_slot); - virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, - uint32 unknown06 = 0, uint32 unknown18 = 0); - virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint); - virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color); - void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone); - void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0, - float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr); - void ChangeSize(float in_size, bool bNoRestriction = false); - inline uint8 SeeInvisible() const { return see_invis; } - inline bool SeeInvisibleUndead() const { return see_invis_undead; } - inline bool SeeHide() const { return see_hide; } - inline bool SeeImprovedHide() const { return see_improved_hide; } - bool IsInvisible(Mob* other = 0) const; - void SetInvisible(uint8 state); - bool AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* weapon); - - //Song - bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1); - bool ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, uint16 slot); - void BardPulse(uint16 spell_id, Mob *caster); - - //Spell - void SendSpellEffect(uint32 effectid, uint32 duration, uint32 finish_delay, bool zone_wide, - uint32 unk020, bool perm_effect = false, Client *c = nullptr); - bool IsBeneficialAllowed(Mob *target); - virtual int GetCasterLevel(uint16 spell_id); - void ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterID = 0, - bool item_bonus = false, uint32 ticsremaining = 0, int buffslot = -1, - bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0); - void NegateSpellsBonuses(uint16 spell_id); - virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false) { return range;} - virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr) { return value; } - virtual int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr) { return value; } - virtual int32 GetActSpellCost(uint16 spell_id, int32 cost){ return cost;} - virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration){ return duration;} - virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime); - float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false, - int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false); - int ResistPhysical(int level_diff, uint8 caster_level); - uint16 GetSpecializeSkillValue(uint16 spell_id) const; - void SendSpellBarDisable(); - void SendSpellBarEnable(uint16 spellid); - void ZeroCastingVars(); - virtual void SpellProcess(); - virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, - int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, - uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 *resist_adjust = nullptr); - virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, - int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, - uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 resist_adjust = 0); - void CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, uint16 mana_used, - uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0); - bool SpellFinished(uint16 spell_id, Mob *target, uint16 slot = 10, uint16 mana_used = 0, - uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false); - virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect = false, - bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false); - virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100); - virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, - CastAction_type &CastAction); - virtual bool CheckFizzle(uint16 spell_id); - virtual bool CheckSpellLevelRestriction(uint16 spell_id); - virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); - virtual float GetAOERange(uint16 spell_id); - void InterruptSpell(uint16 spellid = SPELL_UNKNOWN); - void InterruptSpell(uint16, uint16, uint16 spellid = SPELL_UNKNOWN); - inline bool IsCasting() const { return((casting_spell_id != 0)); } - uint16 CastingSpellID() const { return casting_spell_id; } - bool DoCastingChecks(); - bool TryDispel(uint8 caster_level, uint8 buff_level, int level_modifier); - void SpellProjectileEffect(); - bool TrySpellProjectile(Mob* spell_target, uint16 spell_id); - void ResourceTap(int32 damage, uint16 spell_id); - void TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker); - bool CheckSpellCategory(uint16 spell_id, int category_id, int effect_id); - - - //Buff - void BuffProcess(); - virtual void DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0); - void BuffFadeBySpellID(uint16 spell_id); - void BuffFadeByEffect(int effectid, int skipslot = -1); - void BuffFadeAll(); - void BuffFadeNonPersistDeath(); - void BuffFadeDetrimental(); - void BuffFadeBySlot(int slot, bool iRecalcBonuses = true); - void BuffFadeDetrimentalByCaster(Mob *caster); - void BuffFadeBySitModifier(); - void BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration); - int AddBuff(Mob *caster, const uint16 spell_id, int duration = 0, int32 level_override = -1); - int CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite = false); - int CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caster_level_override = -1); - void SendPetBuffsToClient(); - virtual int GetCurrentBuffSlots() const { return 0; } - virtual int GetCurrentSongSlots() const { return 0; } - virtual int GetCurrentDiscSlots() const { return 0; } - virtual int GetMaxBuffSlots() const { return 0; } - virtual int GetMaxSongSlots() const { return 0; } - virtual int GetMaxDiscSlots() const { return 0; } - virtual int GetMaxTotalSlots() const { return 0; } - virtual void InitializeBuffSlots() { buffs = nullptr; current_buff_count = 0; } - virtual void UninitializeBuffSlots() { } - EQApplicationPacket *MakeBuffsPacket(bool for_target = true); - void SendBuffsToClient(Client *c); - inline Buffs_Struct* GetBuffs() { return buffs; } - void DoGravityEffect(); - void DamageShield(Mob* other, bool spell_ds = false); - int32 RuneAbsorb(int32 damage, uint16 type); - bool FindBuff(uint16 spellid); - bool FindType(uint16 type, bool bOffensive = false, uint16 threshold = 100); - int16 GetBuffSlotFromType(uint16 type); - uint16 GetSpellIDFromSlot(uint8 slot); - int CountDispellableBuffs(); - void CheckNumHitsRemaining(uint8 type, uint32 buff_slot=0, uint16 spell_id=SPELL_UNKNOWN); - bool HasNumhits() const { return has_numhits; } - inline void Numhits(bool val) { has_numhits = val; } - bool HasMGB() const { return has_MGB; } - inline void SetMGB(bool val) { has_MGB = val; } - bool HasProjectIllusion() const { return has_ProjectIllusion ; } - inline void SetProjectIllusion(bool val) { has_ProjectIllusion = val; } - void SpreadVirus(uint16 spell_id, uint16 casterID); - bool IsNimbusEffectActive(uint32 nimbus_effect); - void SetNimbusEffect(uint32 nimbus_effect); - inline virtual uint32 GetNimbusEffect1() const { return nimbus_effect1; } - inline virtual uint32 GetNimbusEffect2() const { return nimbus_effect2; } - inline virtual uint32 GetNimbusEffect3() const { return nimbus_effect3; } - void RemoveNimbusEffect(int effectid); - - //Basic Stats/Inventory - virtual void SetLevel(uint8 in_level, bool command = false) { level = in_level; } - void TempName(const char *newname = nullptr); - void SetTargetable(bool on); - bool IsTargetable() const { return m_targetable; } - bool HasShieldEquiped() const { return has_shieldequiped; } - inline void ShieldEquiped(bool val) { has_shieldequiped = val; } - virtual uint16 GetSkill(SkillUseTypes skill_num) const { return 0; } - virtual uint32 GetEquipment(uint8 material_slot) const { return(0); } - virtual int32 GetEquipmentMaterial(uint8 material_slot) const; - virtual uint32 GetEquipmentColor(uint8 material_slot) const; - virtual uint32 IsEliteMaterialItem(uint8 material_slot) const; - bool AffectedBySpellExcludingSlot(int slot, int effect); - virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) = 0; - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, - bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) = 0; - inline virtual void SetHP(int32 hp) { if (hp >= max_hp) cur_hp = max_hp; else cur_hp = hp;} - bool ChangeHP(Mob* other, int32 amount, uint16 spell_id = 0, int8 buffslot = -1, bool iBuffTic = false); - inline void SetOOCRegen(int32 newoocregen) {oocregen = newoocregen;} - virtual void Heal(); - virtual void HealDamage(uint32 ammount, Mob* caster = nullptr, uint16 spell_id = SPELL_UNKNOWN); - virtual void SetMaxHP() { cur_hp = max_hp; } - virtual inline uint16 GetBaseRace() const { return base_race; } - virtual inline uint8 GetBaseGender() const { return base_gender; } - virtual inline uint16 GetDeity() const { return deity; } - inline uint16 GetRace() const { return race; } - inline uint8 GetGender() const { return gender; } - inline uint8 GetTexture() const { return texture; } - inline uint8 GetHelmTexture() const { return helmtexture; } - inline uint8 GetHairColor() const { return haircolor; } - inline uint8 GetBeardColor() const { return beardcolor; } - inline uint8 GetEyeColor1() const { return eyecolor1; } - inline uint8 GetEyeColor2() const { return eyecolor2; } - inline uint8 GetHairStyle() const { return hairstyle; } - inline uint8 GetLuclinFace() const { return luclinface; } - inline uint8 GetBeard() const { return beard; } - inline uint8 GetDrakkinHeritage() const { return drakkin_heritage; } - inline uint8 GetDrakkinTattoo() const { return drakkin_tattoo; } - inline uint8 GetDrakkinDetails() const { return drakkin_details; } - inline uint32 GetArmorTint(uint8 i) const { return armor_tint[(i < _MaterialCount) ? i : 0]; } - inline uint8 GetClass() const { return class_; } - inline uint8 GetLevel() const { return level; } - inline uint8 GetOrigLevel() const { return orig_level; } - inline const char* GetName() const { return name; } - inline const char* GetOrigName() const { return orig_name; } - inline const char* GetLastName() const { return lastname; } - const char *GetCleanName(); - virtual void SetName(const char *new_name = nullptr) { new_name ? strn0cpy(name, new_name, 64) : - strn0cpy(name, GetName(), 64); return; }; - inline Mob* GetTarget() const { return target; } - virtual void SetTarget(Mob* mob); - virtual inline float GetHPRatio() const { return max_hp == 0 ? 0 : ((float)cur_hp/max_hp*100); } - inline virtual int16 GetAC() const { return AC + itembonuses.AC + spellbonuses.AC; } - inline virtual int16 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK; } - inline virtual int16 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } - inline virtual int16 GetSTR() const { return STR + itembonuses.STR + spellbonuses.STR; } - inline virtual int16 GetSTA() const { return STA + itembonuses.STA + spellbonuses.STA; } - inline virtual int16 GetDEX() const { return DEX + itembonuses.DEX + spellbonuses.DEX; } - inline virtual int16 GetAGI() const { return AGI + itembonuses.AGI + spellbonuses.AGI; } - inline virtual int16 GetINT() const { return INT + itembonuses.INT + spellbonuses.INT; } - inline virtual int16 GetWIS() const { return WIS + itembonuses.WIS + spellbonuses.WIS; } - inline virtual int16 GetCHA() const { return CHA + itembonuses.CHA + spellbonuses.CHA; } - inline virtual int16 GetMR() const { return MR + itembonuses.MR + spellbonuses.MR; } - inline virtual int16 GetFR() const { return FR + itembonuses.FR + spellbonuses.FR; } - inline virtual int16 GetDR() const { return DR + itembonuses.DR + spellbonuses.DR; } - inline virtual int16 GetPR() const { return PR + itembonuses.PR + spellbonuses.PR; } - inline virtual int16 GetCR() const { return CR + itembonuses.CR + spellbonuses.CR; } - inline virtual int16 GetCorrup() const { return Corrup + itembonuses.Corrup + spellbonuses.Corrup; } - inline virtual int16 GetPhR() const { return PhR; } - inline StatBonuses GetItemBonuses() const { return itembonuses; } - inline StatBonuses GetSpellBonuses() const { return spellbonuses; } - inline StatBonuses GetAABonuses() const { return aabonuses; } - inline virtual int16 GetMaxSTR() const { return GetSTR(); } - inline virtual int16 GetMaxSTA() const { return GetSTA(); } - inline virtual int16 GetMaxDEX() const { return GetDEX(); } - inline virtual int16 GetMaxAGI() const { return GetAGI(); } - inline virtual int16 GetMaxINT() const { return GetINT(); } - inline virtual int16 GetMaxWIS() const { return GetWIS(); } - inline virtual int16 GetMaxCHA() const { return GetCHA(); } - inline virtual int16 GetMaxMR() const { return 255; } - inline virtual int16 GetMaxPR() const { return 255; } - inline virtual int16 GetMaxDR() const { return 255; } - inline virtual int16 GetMaxCR() const { return 255; } - inline virtual int16 GetMaxFR() const { return 255; } - inline virtual int16 GetDelayDeath() const { return 0; } - inline int32 GetHP() const { return cur_hp; } - inline int32 GetMaxHP() const { return max_hp; } - virtual int32 CalcMaxHP(); - inline int32 GetMaxMana() const { return max_mana; } - inline int32 GetMana() const { return cur_mana; } - int32 GetItemHPBonuses(); - int32 GetSpellHPBonuses(); - virtual const int32& SetMana(int32 amount); - inline float GetManaRatio() const { return max_mana == 0 ? 100 : - ((static_cast(cur_mana) / max_mana) * 100); } - virtual int32 CalcMaxMana(); - uint32 GetNPCTypeID() const { return npctype_id; } - inline const float GetX() const { return x_pos; } - inline const float GetY() const { return y_pos; } - inline const float GetZ() const { return z_pos; } - inline const float GetHeading() const { return heading; } - inline const float GetSize() const { return size; } - inline const float GetBaseSize() const { return base_size; } - inline const float GetTarX() const { return tarx; } - inline const float GetTarY() const { return tary; } - inline const float GetTarZ() const { return tarz; } - inline const float GetTarVX() const { return tar_vx; } - inline const float GetTarVY() const { return tar_vy; } - inline const float GetTarVZ() const { return tar_vz; } - inline const float GetTarVector() const { return tar_vector; } - inline const uint8 GetTarNDX() const { return tar_ndx; } - bool IsBoat() const; - - //Group - virtual bool HasRaid() = 0; - virtual bool HasGroup() = 0; - virtual Raid* GetRaid() = 0; - virtual Group* GetGroup() = 0; - - //Faction - virtual inline int32 GetPrimaryFaction() const { return 0; } - - //Movement - void Warp( float x, float y, float z ); - inline bool IsMoving() const { return moving; } - virtual void SetMoving(bool move) { moving = move; delta_x = 0; delta_y = 0; delta_z = 0; delta_heading = 0; } - virtual void GoToBind(uint8 bindnum = 0) { } - virtual void Gate(); - float GetWalkspeed() const { return(_GetMovementSpeed(-47)); } - float GetRunspeed() const { return(_GetMovementSpeed(0)); } - float GetBaseRunspeed() const { return runspeed; } - float GetMovespeed() const { return IsRunning() ? GetRunspeed() : GetWalkspeed(); } - bool IsRunning() const { return m_is_running; } - void SetRunning(bool val) { m_is_running = val; } - virtual void GMMove(float x, float y, float z, float heading = 0.01, bool SendUpdate = true); - void SetDeltas(float delta_x, float delta_y, float delta_z, float delta_h); - void SetTargetDestSteps(uint8 target_steps) { tar_ndx = target_steps; } - void SendPosUpdate(uint8 iSendToSelf = 0); - void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu); - void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu); - void SendPosition(); - void SetFlyMode(uint8 flymode); - inline void Teleport(Map::Vertex NewPosition) { x_pos = NewPosition.x; y_pos = NewPosition.y; - z_pos = NewPosition.z; }; - - //AI - static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel); - inline uint32 GetLevelCon(uint8 iOtherLevel) const { - return this ? GetLevelCon(GetLevel(), iOtherLevel) : CON_GREEN; } - virtual void AddToHateList(Mob* other, int32 hate = 0, int32 damage = 0, bool iYellForHelp = true, - bool bFrenzy = false, bool iBuffTic = false); - bool RemoveFromHateList(Mob* mob); - void SetHate(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.Set(other,hate,damage);} - void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHate(other, (in_hate > 1 ? in_hate / 2 : 1)); } - void DoubleAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHate(other, (in_hate ? in_hate * 2 : 1)); } - uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHate(tmob,is_dam);} - uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHate(tmob, true);} - Mob* GetHateTop() { return hate_list.GetTop(this);} - Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTop(other);} - Mob* GetHateRandom() { return hate_list.GetRandom();} - Mob* GetHateMost() { return hate_list.GetMostHate();} - bool IsEngaged() { return(!hate_list.IsEmpty()); } - bool HateSummon(); - void FaceTarget(Mob* MobToFace = 0); - void SetHeading(float iHeading) { if(heading != iHeading) { pLastChange = Timer::GetCurrentTime(); - heading = iHeading; } } - void WipeHateList(); - void AddFeignMemory(Client* attacker); - void RemoveFromFeignMemory(Client* attacker); - void ClearFeignMemory(); - void PrintHateListToClient(Client *who) { hate_list.PrintToClient(who); } - std::list& GetHateList() { return hate_list.GetHateList(); } - bool CheckLosFN(Mob* other); - bool CheckLosFN(float posX, float posY, float posZ, float mobSize); - inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); } - inline const uint32 LastChange() const { return pLastChange; } - - //Quest - void QuestReward(Client *c = nullptr, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0); - void CameraEffect(uint32 duration, uint32 intensity, Client *c = nullptr, bool global = false); - inline bool GetQglobal() const { return qglobal; } - - //Other Packet - void CreateDespawnPacket(EQApplicationPacket* app, bool Decay); - void CreateHorseSpawnPacket(EQApplicationPacket* app, const char* ownername, uint16 ownerid, Mob* ForWho = 0); - void CreateSpawnPacket(EQApplicationPacket* app, Mob* ForWho = 0); - static void CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns); - virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); - void CreateHPPacket(EQApplicationPacket* app); - void SendHPUpdate(); - - //Util - static uint32 RandomTimer(int min, int max); - static uint8 GetDefaultGender(uint16 in_race, uint8 in_gender = 0xFF); - uint16 GetSkillByItemType(int ItemType); - virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr); - virtual void MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, const char *petname = nullptr, float in_size = 0.0f); - bool IsWarriorClass() const; - char GetCasterClass() const; - uint8 GetArchetype() const; - void SetZone(uint32 zone_id, uint32 instance_id); - void ShowStats(Client* client); - void ShowBuffs(Client* client); - void ShowBuffList(Client* client); - float Dist(const Mob &) const; - float DistNoZ(const Mob &) const; - float DistNoRoot(const Mob &) const; - float DistNoRoot(float x, float y, float z) const; - float DistNoRootNoZ(float x, float y) const; - float DistNoRootNoZ(const Mob &) const; - static float GetReciprocalHeading(Mob* target); - bool PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest, - bool lookForAftArc = true); - - //Procs - bool AddRangedProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); - bool RemoveRangedProc(uint16 spell_id, bool bAll = false); - bool HasRangedProcs() const; - bool AddDefensiveProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); - bool RemoveDefensiveProc(uint16 spell_id, bool bAll = false); - bool HasDefensiveProcs() const; - bool HasSkillProcs() const; - bool HasSkillProcSuccess() const; - bool AddProcToWeapon(uint16 spell_id, bool bPerma = false, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); - bool RemoveProcFromWeapon(uint16 spell_id, bool bAll = false); - bool HasProcs() const; - bool IsCombatProc(uint16 spell_id); - - //Logging - bool IsLoggingEnabled() const { return(logging_enabled); } - void EnableLogging() { logging_enabled = true; } - void DisableLogging() { logging_enabled = false; } - - - //More stuff to sort: - virtual bool IsAttackAllowed(Mob *target, bool isSpellAttack = false); - bool IsTargeted() const { return (targeted > 0); } - inline void IsTargeted(int in_tar) { targeted += in_tar; if(targeted < 0) targeted = 0;} - void SetFollowID(uint32 id) { follow = id; } - void SetFollowDistance(uint32 dist) { follow_dist = dist; } - uint32 GetFollowID() const { return follow; } - uint32 GetFollowDistance() const { return follow_dist; } - - virtual void Message(uint32 type, const char* message, ...) { } - virtual void Message_StringID(uint32 type, uint32 string_id, uint32 distance = 0) { } - virtual void Message_StringID(uint32 type, uint32 string_id, const char* message, const char* message2 = 0, - const char* message3 = 0, const char* message4 = 0, const char* message5 = 0, const char* message6 = 0, - const char* message7 = 0, const char* message8 = 0, const char* message9 = 0, uint32 distance = 0) { } - virtual void FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType filter, uint32 string_id) { } - virtual void FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType filter, - uint32 string_id, const char *message1, const char *message2 = nullptr, - const char *message3 = nullptr, const char *message4 = nullptr, - const char *message5 = nullptr, const char *message6 = nullptr, - const char *message7 = nullptr, const char *message8 = nullptr, - const char *message9 = nullptr) { } - void Say(const char *format, ...); - void Say_StringID(uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0, - const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); - void Say_StringID(uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0, - const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); - void Shout(const char *format, ...); - void Emote(const char *format, ...); - void QuestJournalledSay(Client *QuestInitiator, const char *str); - uint32 GetItemStat(uint32 itemid, const char *identifier); - - int16 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false); - uint8 IsFocusEffect(uint16 spellid, int effect_index, bool AA=false,uint32 aa_effect=0); - void SendIllusionPacket(uint16 in_race, uint8 in_gender = 0xFF, uint8 in_texture = 0xFF, uint8 in_helmtexture = 0xFF, - uint8 in_haircolor = 0xFF, uint8 in_beardcolor = 0xFF, uint8 in_eyecolor1 = 0xFF, uint8 in_eyecolor2 = 0xFF, - uint8 in_hairstyle = 0xFF, uint8 in_luclinface = 0xFF, uint8 in_beard = 0xFF, uint8 in_aa_title = 0xFF, - uint32 in_drakkin_heritage = 0xFFFFFFFF, uint32 in_drakkin_tattoo = 0xFFFFFFFF, - uint32 in_drakkin_details = 0xFFFFFFFF, float in_size = 0xFFFFFFFF); - virtual void Stun(int duration); - virtual void UnStun(); - inline void Silence(bool newval) { silenced = newval; } - inline void Amnesia(bool newval) { amnesiad = newval; } - void TemporaryPets(uint16 spell_id, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0); - void TypesTemporaryPets(uint32 typesid, Mob *target, const char *name_override = nullptr, uint32 duration_override = 0, bool followme = false); - void WakeTheDead(uint16 spell_id, Mob *target, uint32 duration); - void Spin(); - void Kill(); - bool PassCharismaCheck(Mob* caster, Mob* spellTarget, uint16 spell_id); - bool TryDeathSave(); - bool TryDivineSave(); - void DoBuffWearOffEffect(uint32 index); - void TryTriggerOnCast(uint32 spell_id, bool aa_trigger); - void TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger); - void TrySpellTrigger(Mob *target, uint32 spell_id); - void TryApplyEffect(Mob *target, uint32 spell_id); - void TryTriggerOnValueAmount(bool IsHP = false, bool IsMana = false, bool IsEndur = false, bool IsPet = false); - void TryTwincast(Mob *caster, Mob *target, uint32 spell_id); - void TrySympatheticProc(Mob *target, uint32 spell_id); - bool TryFadeEffect(int slot); - uint16 GetSpellEffectResistChance(uint16 spell_id); - int16 GetHealRate(uint16 spell_id, Mob* caster = nullptr); - int32 GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining); - int32 GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill = false, uint16 skill=0); - int32 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id); - int16 GetSkillDmgTaken(const SkillUseTypes skill_used); - void DoKnockback(Mob *caster, uint32 pushback, uint32 pushup); - int16 CalcResistChanceBonus(); - int16 CalcFearResistChance(); - void TrySpellOnKill(uint8 level, uint16 spell_id); - bool TrySpellOnDeath(); - void CastOnCurer(uint32 spell_id); - void CastOnCure(uint32 spell_id); - void CastOnNumHitFade(uint32 spell_id); - void SlowMitigation(Mob* caster); - int16 GetCritDmgMob(uint16 skill); - int16 GetMeleeDamageMod_SE(uint16 skill); - int16 GetMeleeMinDamageMod_SE(uint16 skill); - int16 GetCrippBlowChance(); - int16 GetSkillReuseTime(uint16 skill); - int16 GetCriticalChanceBonus(uint16 skill); - int16 GetSkillDmgAmt(uint16 skill); - bool TryReflectSpell(uint32 spell_id); - bool CanBlockSpell() const { return(spellbonuses.BlockNextSpell); } - bool DoHPToManaCovert(uint16 mana_cost = 0); - int32 ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard = false); - int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect); - int32 GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg); - void MeleeLifeTap(int32 damage); - bool PassCastRestriction(bool UseCastRestriction = true, int16 value = 0, bool IsDamage = true); - bool ImprovedTaunt(); - bool TryRootFadeByDamage(int buffslot, Mob* attacker); - int16 GetSlowMitigation() const {return slow_mitigation;} - - void ModSkillDmgTaken(SkillUseTypes skill_num, int value); - int16 GetModSkillDmgTaken(const SkillUseTypes skill_num); - void ModVulnerability(uint8 resist, int16 value); - int16 GetModVulnerability(const uint8 resist); - - void SetAllowBeneficial(bool value) { m_AllowBeneficial = value; } - bool GetAllowBeneficial() { if (m_AllowBeneficial || GetSpecialAbility(ALLOW_BENEFICIAL)){return true;} return false; } - void SetDisableMelee(bool value) { m_DisableMelee = value; } - bool IsMeleeDisabled() { if (m_DisableMelee || GetSpecialAbility(DISABLE_MELEE)){return true;} return false; } - - bool IsOffHandAtk() const { return offhand; } - inline void OffHandAtk(bool val) { offhand = val; } - - void SetFlurryChance(uint8 value) { SetSpecialAbilityParam(SPECATK_FLURRY, 0, value); } - uint8 GetFlurryChance() { return GetSpecialAbilityParam(SPECATK_FLURRY, 0); } - - static uint32 GetAppearanceValue(EmuAppearance iAppearance); - void SendAppearancePacket(uint32 type, uint32 value, bool WholeZone = true, bool iIgnoreSelf = false, Client *specific_target=nullptr); - void SetAppearance(EmuAppearance app, bool iIgnoreSelf = true); - inline EmuAppearance GetAppearance() const { return _appearance; } - inline const uint8 GetRunAnimSpeed() const { return pRunAnimSpeed; } - inline void SetRunAnimSpeed(int8 in) { if (pRunAnimSpeed != in) { pRunAnimSpeed = in; pLastChange = Timer::GetCurrentTime(); } } - bool IsDestructibleObject() { return destructibleobject; } - void SetDestructibleObject(bool in) { destructibleobject = in; } - - Mob* GetPet(); - void SetPet(Mob* newpet); - virtual Mob* GetOwner(); - virtual Mob* GetOwnerOrSelf(); - Mob* GetUltimateOwner(); - void SetPetID(uint16 NewPetID); - inline uint16 GetPetID() const { return petid; } - inline PetType GetPetType() const { return typeofpet; } - void SetPetType(PetType p) { typeofpet = p; } - inline int16 GetPetPower() const { return (petpower < 0) ? 0 : petpower; } - void SetPetPower(int16 p) { if (p < 0) petpower = 0; else petpower = p; } - bool IsFamiliar() const { return(typeofpet == petFamiliar); } - bool IsAnimation() const { return(typeofpet == petAnimation); } - bool IsCharmed() const { return(typeofpet == petCharmed); } - void SetOwnerID(uint16 NewOwnerID); - inline uint16 GetOwnerID() const { return ownerid; } - inline virtual bool HasOwner() { if(GetOwnerID()==0){return false;} return( entity_list.GetMob(GetOwnerID()) != 0); } - inline virtual bool IsPet() { return(HasOwner() && !IsMerc()); } - inline bool HasPet() const { if(GetPetID()==0){return false;} return (entity_list.GetMob(GetPetID()) != 0);} - bool HadTempPets() const { return(hasTempPet); } - void TempPets(bool i) { hasTempPet = i; } - bool HasPetAffinity() { if (aabonuses.GivePetGroupTarget || itembonuses.GivePetGroupTarget || spellbonuses.GivePetGroupTarget) return true; return false; } - - inline const bodyType GetBodyType() const { return bodytype; } - inline const bodyType GetOrigBodyType() const { return orig_bodytype; } - void SetBodyType(bodyType new_body, bool overwrite_orig); - - uint8 invisible, see_invis; - bool invulnerable, invisible_undead, invisible_animals, sneaking, hidden, improved_hidden; - bool see_invis_undead, see_hide, see_improved_hide; - bool qglobal; - - virtual void SetAttackTimer(); - inline void SetInvul(bool invul) { invulnerable=invul; } - inline bool GetInvul(void) { return invulnerable; } - inline void SetExtraHaste(int Haste) { ExtraHaste = Haste; } - virtual int GetHaste(); - - uint8 GetWeaponDamageBonus(const Item_Struct* Weapon); - uint16 GetDamageTable(SkillUseTypes skillinuse); - virtual int GetMonkHandToHandDamage(void); - - bool CanThisClassDoubleAttack(void) const; - bool CanThisClassDualWield(void) const; - bool CanThisClassRiposte(void) const; - bool CanThisClassDodge(void) const; - bool CanThisClassParry(void) const; - bool CanThisClassBlock(void) const; - - int GetMonkHandToHandDelay(void); - uint16 GetClassLevelFactor(); - void Mesmerize(); - inline bool IsMezzed() const { return mezzed; } - inline bool IsStunned() const { return stunned; } - inline bool IsSilenced() const { return silenced; } - inline bool IsAmnesiad() const { return amnesiad; } - - int32 ReduceDamage(int32 damage); - int32 AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker); - int32 ReduceAllDamage(int32 damage); - - virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true); - virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* item=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0); - virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime=0); - virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0); - bool CanDoSpecialAttack(Mob *other); - bool Flurry(ExtraAttackOptions *opts); - bool Rampage(ExtraAttackOptions *opts); - bool AddRampage(Mob*); - void ClearRampage(); - void AreaRampage(ExtraAttackOptions *opts); - - void StartEnrage(); - void ProcessEnrage(); - bool IsEnraged(); - void Taunt(NPC* who, bool always_succeed, float chance_bonus = 0); - - virtual void AI_Init(); - virtual void AI_Start(uint32 iMoveDelay = 0); - virtual void AI_Stop(); - virtual void AI_Process(); - - const char* GetEntityVariable(const char *id); - void SetEntityVariable(const char *id, const char *m_var); - bool EntityVariableExists(const char *id); - - void AI_Event_Engaged(Mob* attacker, bool iYellForHelp = true); - void AI_Event_NoLongerEngaged(); - - FACTION_VALUE GetSpecialFactionCon(Mob* iOther); - inline const bool IsAIControlled() const { return pAIControlled; } - inline const float GetAggroRange() const { return (spellbonuses.AggroRange == -1) ? pAggroRange : spellbonuses.AggroRange; } - inline const float GetAssistRange() const { return (spellbonuses.AssistRange == -1) ? pAssistRange : spellbonuses.AssistRange; } - - - inline void SetPetOrder(eStandingPetOrder i) { pStandingPetOrder = i; } - inline const eStandingPetOrder GetPetOrder() const { return pStandingPetOrder; } - inline void SetHeld(bool nState) { held = nState; } - inline const bool IsHeld() const { return held; } - inline void SetNoCast(bool nState) { nocast = nState; } - inline const bool IsNoCast() const { return nocast; } - inline void SetFocused(bool nState) { focused = nState; } - inline const bool IsFocused() const { return focused; } - inline const bool IsRoamer() const { return roamer; } - inline const bool IsRooted() const { return rooted || permarooted; } - inline const bool HasVirus() const { return has_virus; } - int GetSnaredAmount(); - - - int GetCurWp() { return cur_wp; } - - //old fear function - //void SetFeared(Mob *caster, uint32 duration, bool flee = false); - float GetFearSpeed(); - bool IsFeared() { return curfp; } // This returns true if the mob is feared or fleeing due to low HP - //old fear: inline void StartFleeing() { SetFeared(GetHateTop(), FLEE_RUN_DURATION, true); } - inline void StartFleeing() { flee_mode = true; CalculateNewFearpoint(); } - void ProcessFlee(); - void CheckFlee(); - - inline bool CheckAggro(Mob* other) {return hate_list.IsOnHateList(other);} - float CalculateHeadingToTarget(float in_x, float in_y); - bool CalculateNewPosition(float x, float y, float z, float speed, bool checkZ = false); - virtual bool CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ = true); - float CalculateDistance(float x, float y, float z); - float GetGroundZ(float new_x, float new_y, float z_offset=0.0); - void SendTo(float new_x, float new_y, float new_z); - void SendToFixZ(float new_x, float new_y, float new_z); - void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false); - inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; } - inline uint32 DontBuffMeBefore() const { return pDontBuffMeBefore; } - inline uint32 DontDotMeBefore() const { return pDontDotMeBefore; } - inline uint32 DontRootMeBefore() const { return pDontRootMeBefore; } - inline uint32 DontSnareMeBefore() const { return pDontSnareMeBefore; } - inline uint32 DontCureMeBefore() const { return pDontCureMeBefore; } - void SetDontRootMeBefore(uint32 time) { pDontRootMeBefore = time; } - void SetDontHealMeBefore(uint32 time) { pDontHealMeBefore = time; } - void SetDontBuffMeBefore(uint32 time) { pDontBuffMeBefore = time; } - void SetDontDotMeBefore(uint32 time) { pDontDotMeBefore = time; } - void SetDontSnareMeBefore(uint32 time) { pDontSnareMeBefore = time; } - void SetDontCureMeBefore(uint32 time) { pDontCureMeBefore = time; } - - // calculate interruption of spell via movement of mob - void SaveSpellLoc() {spell_x = x_pos; spell_y = y_pos; spell_z = z_pos; } - inline float GetSpellX() const {return spell_x;} - inline float GetSpellY() const {return spell_y;} - inline float GetSpellZ() const {return spell_z;} - inline bool IsGrouped() const { return isgrouped; } - void SetGrouped(bool v); - inline bool IsRaidGrouped() const { return israidgrouped; } - void SetRaidGrouped(bool v); - inline bool IsLooting() const { return islooting; } - void SetLooting(bool val) { islooting = val; } - - bool CheckWillAggro(Mob *mob); - - void InstillDoubt(Mob *who); - int16 GetResist(uint8 type) const; - Mob* GetShieldTarget() const { return shield_target; } - void SetShieldTarget(Mob* mob) { shield_target = mob; } - bool HasActiveSong() const { return(bardsong != 0); } - bool Charmed() const { return charmed; } - static uint32 GetLevelHP(uint8 tlevel); - uint32 GetZoneID() const; //for perl - virtual int32 CheckAggroAmount(uint16 spell_id, bool isproc = false); - virtual int32 CheckHealAggroAmount(uint16 spell_id, uint32 heal_possible = 0); - virtual uint32 GetAA(uint32 aa_id) const { return(0); } - - uint16 GetInstrumentMod(uint16 spell_id) const; - int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, Mob *caster = nullptr, int ticsremaining = 0); - int CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining = 0); - virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1); - uint32 GetCastedSpellInvSlot() const { return casting_spell_inventory_slot; } - - // HP Event - inline int GetNextHPEvent() const { return nexthpevent; } - void SetNextHPEvent( int hpevent ); - void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse); - inline int& GetNextIncHPEvent() { return nextinchpevent; } - void SetNextIncHPEvent( int inchpevent ); - - inline bool DivineAura() const { return spellbonuses.DivineAura; } - inline bool Sanctuary() const { return spellbonuses.Sanctuary; } - - bool HasNPCSpecialAtk(const char* parse); - int GetSpecialAbility(int ability); - int GetSpecialAbilityParam(int ability, int param); - void SetSpecialAbility(int ability, int level); - void SetSpecialAbilityParam(int ability, int param, int value); - void StartSpecialAbilityTimer(int ability, uint32 time); - void StopSpecialAbilityTimer(int ability); - Timer *GetSpecialAbilityTimer(int ability); - void ClearSpecialAbilities(); - void ProcessSpecialAbilities(const std::string str); - - Shielders_Struct shielder[MAX_SHIELDERS]; - Trade* trade; - - inline float GetCWPX() const { return(cur_wp_x); } - inline float GetCWPY() const { return(cur_wp_y); } - inline float GetCWPZ() const { return(cur_wp_z); } - inline float GetCWPH() const { return(cur_wp_heading); } - inline float GetCWPP() const { return(static_cast(cur_wp_pause)); } - inline int GetCWP() const { return(cur_wp); } - void SetCurrentWP(uint16 waypoint) { cur_wp = waypoint; } - virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; } - - inline bool IsTrackable() const { return(trackable); } - Timer* GetAIThinkTimer() { return AIthink_timer; } - Timer* GetAIMovementTimer() { return AImovement_timer; } - Timer GetAttackTimer() { return attack_timer; } - Timer GetAttackDWTimer() { return attack_dw_timer; } - inline bool IsFindable() { return findable; } - inline uint8 GetManaPercent() { return (uint8)((float)cur_mana / (float)max_mana * 100.0f); } - virtual uint8 GetEndurancePercent() { return 0; } - - inline virtual bool IsBlockedBuff(int16 SpellID) { return false; } - inline virtual bool IsBlockedPetBuff(int16 SpellID) { return false; } - - void SetGlobal(const char *varname, const char *newvalue, int options, const char *duration, Mob *other = nullptr); - void TarGlobal(const char *varname, const char *value, const char *duration, int npcid, int charid, int zoneid); - void DelGlobal(const char *varname); - - inline void SetEmoteID(uint16 emote) { emoteid = emote; } - inline uint16 GetEmoteID() { return emoteid; } - - bool HasSpellEffect(int effectid); - int mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster); - float mod_hit_chance(float chancetohit, SkillUseTypes skillinuse, Mob* attacker); - float mod_riposte_chance(float ripostchance, Mob* attacker); - float mod_block_chance(float blockchance, Mob* attacker); - float mod_parry_chance(float parrychance, Mob* attacker); - float mod_dodge_chance(float dodgechance, Mob* attacker); - float mod_monk_weight(float monkweight, Mob* attacker); - float mod_mitigation_rating(float mitigation_rating, Mob* attacker); - float mod_attack_rating(float attack_rating, Mob* defender); - int32 mod_kick_damage(int32 dmg); - int32 mod_bash_damage(int32 dmg); - int32 mod_frenzy_damage(int32 dmg); - int32 mod_monk_special_damage(int32 ndamage, SkillUseTypes skill_type); - int32 mod_backstab_damage(int32 ndamage); - int mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon); - uint32 mod_archery_bonus_damage(uint32 MaxDmg, const ItemInst* RangeWeapon); - int32 mod_archery_damage(int32 TotalDmg, bool hasbonus, const ItemInst* RangeWeapon); - uint16 mod_throwing_damage(uint16 MaxDmg); - int32 mod_cast_time(int32 cast_time); - int mod_buff_duration(int res, Mob* caster, Mob* target, uint16 spell_id); - int mod_spell_stack(uint16 spellid1, int caster_level1, Mob* caster1, uint16 spellid2, int caster_level2, Mob* caster2); - int mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster); - void mod_spell_cast(uint16 spell_id, Mob* spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust, bool isproc); - bool mod_will_aggro(Mob *attacker, Mob *on); - -protected: - void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); - static uint16 GetProcID(uint16 spell_id, uint8 effect_index); - float _GetMovementSpeed(int mod) const; - virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, bool checkZ); - - virtual bool AI_EngagedCastCheck() { return(false); } - virtual bool AI_PursueCastCheck() { return(false); } - virtual bool AI_IdleCastCheck() { return(false); } - - - bool IsFullHP; - bool moved; - - std::vector RampageArray; - std::map m_EntityVariables; - - int16 SkillDmgTaken_Mod[HIGHEST_SKILL+2]; - int16 Vulnerability_Mod[HIGHEST_RESIST+2]; - bool m_AllowBeneficial; - bool m_DisableMelee; - - bool isgrouped; - bool israidgrouped; - bool pendinggroup; - bool islooting; - uint8 texture; - uint8 helmtexture; - - int AC; - int16 ATK; - int16 STR; - int16 STA; - int16 DEX; - int16 AGI; - int16 INT; - int16 WIS; - int16 CHA; - int16 MR; - int16 CR; - int16 FR; - int16 DR; - int16 PR; - int16 Corrup; - int16 PhR; - bool moving; - int targeted; - bool findable; - bool trackable; - int32 cur_hp; - int32 max_hp; - int32 base_hp; - int32 cur_mana; - int32 max_mana; - int32 hp_regen; - int32 mana_regen; - int32 oocregen; - uint8 maxlevel; - uint32 scalerate; - Buffs_Struct *buffs; - uint32 current_buff_count; - StatBonuses itembonuses; - StatBonuses spellbonuses; - StatBonuses aabonuses; - uint16 petid; - uint16 ownerid; - PetType typeofpet; - int16 petpower; - uint32 follow; - uint32 follow_dist; - bool no_target_hotkey; - - uint8 gender; - uint16 race; - uint8 base_gender; - uint16 base_race; - uint8 class_; - bodyType bodytype; - bodyType orig_bodytype; - uint16 deity; - uint8 level; - uint8 orig_level; - uint32 npctype_id; - float x_pos; - float y_pos; - float z_pos; - float heading; - uint16 animation; - float base_size; - float size; - float runspeed; - uint32 pLastChange; - bool held; - bool nocast; - bool focused; - void CalcSpellBonuses(StatBonuses* newbon); - virtual void CalcBonuses(); - void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); - bool PassLimitToSkill(uint16 spell_id, uint16 skill); - bool PassLimitClass(uint32 Classes_, uint16 Class_); - void TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand = 13, int damage=0); - void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = 13); - void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = 13); - void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = 13); - void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on); - virtual float GetProcChances(float ProcBonus, uint16 weapon_speed = 30, uint16 hand = 13); - virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed = 30, uint16 hand = 13); - virtual float GetSpecialProcChances(uint16 hand); - virtual float GetAssassinateProcChances(uint16 ReuseTime); - virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); - uint16 GetWeaponSpeedbyHand(uint16 hand); - int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item); - int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr); - int GetKickDamage(); - int GetBashDamage(); - virtual void ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg); - bool HasDied(); - void CalculateNewFearpoint(); - float FindGroundZ(float new_x, float new_y, float z_offset=0.0); - Map::Vertex UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached); - void PrintRoute(); - - virtual float GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate = 0); - - enum {MAX_PROCS = 4}; - tProc PermaProcs[MAX_PROCS]; - tProc SpellProcs[MAX_PROCS]; - tProc DefensiveProcs[MAX_PROCS]; - tProc RangedProcs[MAX_PROCS]; - tProc SkillProcs[MAX_PROCS]; - - char name[64]; - char orig_name[64]; - char clean_name[64]; - char lastname[64]; - - int32 delta_heading; - float delta_x; - float delta_y; - float delta_z; - - uint8 light; - - float fixedZ; - EmuAppearance _appearance; - uint8 pRunAnimSpeed; - bool m_is_running; - - - Timer attack_timer; - Timer attack_dw_timer; - Timer ranged_timer; - float attack_speed; //% increase/decrease in attack speed (not haste) - float slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%) - Timer tic_timer; - Timer mana_timer; - - //spell casting vars - Timer spellend_timer; - uint16 casting_spell_id; - float spell_x, spell_y, spell_z; - int attacked_count; - bool delaytimer; - uint16 casting_spell_targetid; - uint16 casting_spell_slot; - uint16 casting_spell_mana; - uint32 casting_spell_inventory_slot; - uint32 casting_spell_timer; - uint32 casting_spell_timer_duration; - uint32 casting_spell_type; - int16 casting_spell_resist_adjust; - bool casting_spell_checks; - uint16 bardsong; - uint8 bardsong_slot; - uint32 bardsong_target_id; - - Timer projectile_timer; - uint32 projectile_spell_id[MAX_SPELL_PROJECTILE]; - uint16 projectile_target_id[MAX_SPELL_PROJECTILE]; - uint8 projectile_increment[MAX_SPELL_PROJECTILE]; - float projectile_x[MAX_SPELL_PROJECTILE], projectile_y[MAX_SPELL_PROJECTILE], projectile_z[MAX_SPELL_PROJECTILE]; - - float rewind_x; - float rewind_y; - float rewind_z; - Timer rewind_timer; - - // Currently 3 max nimbus particle effects at a time - uint32 nimbus_effect1; - uint32 nimbus_effect2; - uint32 nimbus_effect3; - - uint8 haircolor; - uint8 beardcolor; - uint8 eyecolor1; // the eyecolors always seem to be the same, maybe left and right eye? - uint8 eyecolor2; - uint8 hairstyle; - uint8 luclinface; // - uint8 beard; - uint32 drakkin_heritage; - uint32 drakkin_tattoo; - uint32 drakkin_details; - uint32 armor_tint[_MaterialCount]; - - uint8 aa_title; - - Mob* shield_target; - - int ExtraHaste; // for the #haste command - bool mezzed; - bool stunned; - bool charmed; //this isnt fully implemented yet - bool rooted; - bool silenced; - bool amnesiad; - bool inWater; // Set to true or false by Water Detection code if enabled by rules - bool has_virus; // whether this mob has a viral spell on them - uint16 viral_spells[MAX_SPELL_TRIGGER*2]; // Stores the spell ids of the viruses on target and caster ids - bool offhand; - bool has_shieldequiped; - bool has_numhits; - bool has_MGB; - bool has_ProjectIllusion; - - // Bind wound - Timer bindwound_timer; - Mob* bindwound_target; - - Timer stunned_timer; - Timer spun_timer; - Timer bardsong_timer; - Timer gravity_timer; - Timer viral_timer; - uint8 viral_timer_counter; - - // MobAI stuff - eStandingPetOrder pStandingPetOrder; - uint32 minLastFightingDelayMoving; - uint32 maxLastFightingDelayMoving; - float pAggroRange; - float pAssistRange; - Timer* AIthink_timer; - Timer* AImovement_timer; - Timer* AItarget_check_timer; - bool movetimercompleted; - bool permarooted; - Timer* AIscanarea_timer; - Timer* AIwalking_timer; - Timer* AIfeignremember_timer; - uint32 pLastFightingDelayMoving; - HateList hate_list; - std::set feign_memory_list; - // This is to keep track of mobs we cast faction mod spells on - std::map faction_bonuses; // Primary FactionID, Bonus - void AddFactionBonus(uint32 pFactionID,int32 bonus); - int32 GetFactionBonus(uint32 pFactionID); - // This is to keep track of item faction modifiers - std::map item_faction_bonuses; // Primary FactionID, Bonus - void AddItemFactionBonus(uint32 pFactionID,int32 bonus); - int32 GetItemFactionBonus(uint32 pFactionID); - void ClearItemFactionBonuses(); - - void CalculateFearPosition(); - uint32 move_tic_count; - - bool flee_mode; - Timer flee_timer; - - bool pAIControlled; - bool roamer; - bool logging_enabled; - - int wandertype; - int pausetype; - - int cur_wp; - float cur_wp_x; - float cur_wp_y; - float cur_wp_z; - int cur_wp_pause; - float cur_wp_heading; - - int patrol; - float fear_walkto_x; - float fear_walkto_y; - float fear_walkto_z; - bool curfp; - - // Pathing - // - Map::Vertex PathingDestination; - Map::Vertex PathingLastPosition; - int PathingLoopCount; - int PathingLastNodeVisited; - std::list Route; - LOSType PathingLOSState; - Timer *PathingLOSCheckTimer; - Timer *PathingRouteUpdateTimerShort; - Timer *PathingRouteUpdateTimerLong; - bool DistractedFromGrid; - int PathingTraversedNodes; - - uint32 pDontHealMeBefore; - uint32 pDontBuffMeBefore; - uint32 pDontDotMeBefore; - uint32 pDontRootMeBefore; - uint32 pDontSnareMeBefore; - uint32 pDontCureMeBefore; - - // hp event - int nexthpevent; - int nextinchpevent; - - //temppet - bool hasTempPet; - - EGNode *_egnode; //the EG node we are in - float tarx; - float tary; - float tarz; - uint8 tar_ndx; - float tar_vector; - float tar_vx; - float tar_vy; - float tar_vz; - float test_vector; - - uint32 m_spellHitsLeft[38]; // Used to track which spells will have their numhits incremented when spell finishes casting, 38 Buffslots - int flymode; - bool m_targetable; - int QGVarDuration(const char *fmt); - void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate); - uint16 emoteid; - - SpecialAbility SpecialAbilities[MAX_SPECIAL_ATTACK]; - bool bEnraged; - bool destructibleobject; - -private: - void _StopSong(); //this is not what you think it is - Mob* target; -}; - -#endif - diff --git a/zone/net_Fix.cpp b/zone/net_Fix.cpp deleted file mode 100644 index 9b4080eb2..000000000 --- a/zone/net_Fix.cpp +++ /dev/null @@ -1,644 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#define DONT_SHARED_OPCODES - -#include "../common/debug.h" -#include "../common/features.h" -#include "../common/queue.h" -#include "../common/timer.h" -#include "../common/eq_stream.h" -#include "../common/eq_stream_factory.h" -#include "../common/eq_packet_structs.h" -#include "../common/mutex.h" -#include "../common/version.h" -#include "../common/eqemu_error.h" -#include "../common/packet_dump_file.h" -#include "../common/opcodemgr.h" -#include "../common/guilds.h" -#include "../common/eq_stream_ident.h" -#include "../common/patches/patches.h" -#include "../common/rulesys.h" -#include "../common/misc_functions.h" -#include "../common/string_util.h" -#include "../common/platform.h" -#include "../common/crash.h" -#include "../common/ipc_mutex.h" -#include "../common/memory_mapped_file.h" -#include "../common/eqemu_exception.h" -#include "../common/spdat.h" - -#include "zone_config.h" -#include "masterentity.h" -#include "worldserver.h" -#include "net.h" -#include "zone.h" -#include "queryserv.h" -#include "command.h" -#include "zone_config.h" -#include "titles.h" -#include "guild_mgr.h" -#include "tasks.h" - -#include "quest_parser_collection.h" -#include "embparser.h" -#include "lua_parser.h" -#include "client_logs.h" -#include "questmgr.h" - -#include -#include -#include - -#include -#include -#include -#include - -#ifdef _CRTDBG_MAP_ALLOC - #undef new - #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) -#endif - -#ifdef _WINDOWS - #include - #include -#else - #include - #include "../common/unix.h" -#endif - -volatile bool RunLoops = true; -extern volatile bool ZoneLoaded; - -TimeoutManager timeout_manager; -NetConnection net; -EntityList entity_list; -WorldServer worldserver; -uint32 numclients = 0; -char errorname[32]; -uint16 adverrornum = 0; -extern Zone* zone; -EQStreamFactory eqsf(ZoneStream); -npcDecayTimes_Struct npcCorpseDecayTimes[100]; -TitleManager title_manager; -QueryServ *QServ = 0; -TaskManager *taskmanager = 0; -QuestParserCollection *parse = 0; - -const SPDat_Spell_Struct* spells; -void LoadSpells(EQEmu::MemoryMappedFile **mmf); -int32 SPDAT_RECORDS = -1; - -void Shutdown(); -extern void MapOpcodes(); - -int main(int argc, char** argv) { - RegisterExecutablePlatform(ExePlatformZone); - set_exception_handler(); - - const char *zone_name; - - QServ = new QueryServ; - - if(argc == 3) { - worldserver.SetLauncherName(argv[2]); - worldserver.SetLaunchedName(argv[1]); - if(strncmp(argv[1], "dynamic_", 8) == 0) { - //dynamic zone with a launcher name correlation - zone_name = "."; - } else { - zone_name = argv[1]; - worldserver.SetLaunchedName(zone_name); - } - } else if (argc == 2) { - worldserver.SetLauncherName("NONE"); - worldserver.SetLaunchedName(argv[1]); - if(strncmp(argv[1], "dynamic_", 8) == 0) { - //dynamic zone with a launcher name correlation - zone_name = "."; - } else { - zone_name = argv[1]; - worldserver.SetLaunchedName(zone_name); - } - } else { - zone_name = "."; - worldserver.SetLaunchedName("."); - worldserver.SetLauncherName("NONE"); - } - - _log(ZONE__INIT, "Loading server configuration.."); - if (!ZoneConfig::LoadConfig()) { - _log(ZONE__INIT_ERR, "Loading server configuration failed."); - return 1; - } - const ZoneConfig *Config=ZoneConfig::get(); - - if(!load_log_settings(Config->LogSettingsFile.c_str())) - _log(ZONE__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str()); - else - _log(ZONE__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str()); - - worldserver.SetPassword(Config->SharedKey.c_str()); - - _log(ZONE__INIT, "Connecting to MySQL..."); - if (!database.Connect( - Config->DatabaseHost.c_str(), - Config->DatabaseUsername.c_str(), - Config->DatabasePassword.c_str(), - Config->DatabaseDB.c_str(), - Config->DatabasePort)) { - _log(ZONE__INIT_ERR, "Cannot continue without a database connection."); - return 1; - } - guild_mgr.SetDatabase(&database); - - GuildBanks = nullptr; - -#ifdef _EQDEBUG - _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); -#endif - - _log(ZONE__INIT, "CURRENT_VERSION: %s", CURRENT_VERSION); - - /* - * Setup nice signal handlers - */ - if (signal(SIGINT, CatchSignal) == SIG_ERR) { - _log(ZONE__INIT_ERR, "Could not set signal handler"); - return 1; - } - if (signal(SIGTERM, CatchSignal) == SIG_ERR) { - _log(ZONE__INIT_ERR, "Could not set signal handler"); - return 1; - } - #ifndef WIN32 - if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { - _log(ZONE__INIT_ERR, "Could not set signal handler"); - return 1; - } - #endif - - const char *log_ini_file = "./log.ini"; - if(!load_log_settings(log_ini_file)) - _log(ZONE__INIT, "Warning: Unable to read %s", log_ini_file); - else - _log(ZONE__INIT, "Log settings loaded from %s", log_ini_file); - - _log(ZONE__INIT, "Mapping Incoming Opcodes"); - MapOpcodes(); - _log(ZONE__INIT, "Loading Variables"); - database.LoadVariables(); - _log(ZONE__INIT, "Loading zone names"); - database.LoadZoneNames(); - _log(ZONE__INIT, "Loading items"); - if (!database.LoadItems()) { - _log(ZONE__INIT_ERR, "Loading items FAILED!"); - _log(ZONE__INIT, "Failed. But ignoring error and going on..."); - } - - _log(ZONE__INIT, "Loading npc faction lists"); - if (!database.LoadNPCFactionLists()) { - _log(ZONE__INIT_ERR, "Loading npcs faction lists FAILED!"); - CheckEQEMuErrorAndPause(); - return 1; - } - _log(ZONE__INIT, "Loading loot tables"); - if (!database.LoadLoot()) { - _log(ZONE__INIT_ERR, "Loading loot FAILED!"); - CheckEQEMuErrorAndPause(); - return 1; - } - _log(ZONE__INIT, "Loading skill caps"); - if (!database.LoadSkillCaps()) { - _log(ZONE__INIT_ERR, "Loading skill caps FAILED!"); - CheckEQEMuErrorAndPause(); - return 1; - } - - _log(ZONE__INIT, "Loading spells"); - EQEmu::MemoryMappedFile *mmf = nullptr; - LoadSpells(&mmf); - - _log(ZONE__INIT, "Loading base data"); - if (!database.LoadBaseData()) { - _log(ZONE__INIT_ERR, "Loading base data FAILED!"); - CheckEQEMuErrorAndPause(); - return 1; - } - - _log(ZONE__INIT, "Loading guilds"); - guild_mgr.LoadGuilds(); - _log(ZONE__INIT, "Loading factions"); - database.LoadFactionData(); - _log(ZONE__INIT, "Loading titles"); - title_manager.LoadTitles(); - _log(ZONE__INIT, "Loading AA effects"); - database.LoadAAEffects(); - _log(ZONE__INIT, "Loading tributes"); - database.LoadTributes(); - _log(ZONE__INIT, "Loading corpse timers"); - database.GetDecayTimes(npcCorpseDecayTimes); - _log(ZONE__INIT, "Loading commands"); - int retval=command_init(); - if(retval<0) - _log(ZONE__INIT_ERR, "Command loading FAILED"); - else - _log(ZONE__INIT, "%d commands loaded", retval); - - //rules: - { - char tmp[64]; - if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) { - _log(ZONE__INIT, "Loading rule set '%s'", tmp); - if(!RuleManager::Instance()->LoadRules(&database, tmp)) { - _log(ZONE__INIT_ERR, "Failed to load ruleset '%s', falling back to defaults.", tmp); - } - } else { - if(!RuleManager::Instance()->LoadRules(&database, "default")) { - _log(ZONE__INIT, "No rule set configured, using default rules"); - } else { - _log(ZONE__INIT, "Loaded default rule set 'default'", tmp); - } - } - } - - if(RuleB(TaskSystem, EnableTaskSystem)) { - _log(ZONE__INIT, "Loading Tasks"); - taskmanager = new TaskManager; - taskmanager->LoadTasks(); - } - - parse = new QuestParserCollection(); -#ifdef LUA_EQEMU - LuaParser *lua_parser = new LuaParser(); - parse->RegisterQuestInterface(lua_parser, "lua"); -#endif - -#ifdef EMBPERL - PerlembParser *perl_parser = new PerlembParser(); - parse->RegisterQuestInterface(perl_parser, "pl"); -#endif - - //now we have our parser, load the quests - _log(ZONE__INIT, "Loading quests"); - parse->ReloadQuests(); - - -#ifdef CLIENT_LOGS - LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_buf); - LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_fmt); - LogFile->SetAllCallbacks(ClientLogs::EQEmuIO_pva); -#endif - if (!worldserver.Connect()) { - _log(ZONE__INIT_ERR, "worldserver.Connect() FAILED!"); - } - - Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect -#ifdef EQPROFILE -#ifdef PROFILE_DUMP_TIME - Timer profile_dump_timer(PROFILE_DUMP_TIME*1000); - profile_dump_timer.Start(); -#endif -#endif - if (!strlen(zone_name) || !strcmp(zone_name,".")) { - _log(ZONE__INIT, "Entering sleep mode"); - } else if (!Zone::Bootup(database.GetZoneID(zone_name), 0, true)) { //todo: go above and fix this to allow cmd line instance - _log(ZONE__INIT_ERR, "Zone bootup FAILED!"); - zone = 0; - } - - //register all the patches we have avaliable with the stream identifier. - EQStreamIdentifier stream_identifier; - RegisterAllPatches(stream_identifier); - -#ifndef WIN32 - _log(COMMON__THREADS, "Main thread running with thread id %d", pthread_self()); -#endif - - Timer quest_timers(100); - UpdateWindowTitle(); - bool worldwasconnected = worldserver.Connected(); - EQStream* eqss; - EQStreamInterface *eqsi; - uint8 IDLEZONEUPDATE = 200; - uint8 ZONEUPDATE = 10; - Timer zoneupdate_timer(ZONEUPDATE); - zoneupdate_timer.Start(); - while(RunLoops) { - { //profiler block to omit the sleep from times - - //Advance the timer to our current point in time - Timer::SetCurrentTime(); - - //process stuff from world - worldserver.Process(); - - if (!eqsf.IsOpen() && Config->ZonePort!=0) { - _log(ZONE__INIT, "Starting EQ Network server on port %d",Config->ZonePort); - if (!eqsf.Open(Config->ZonePort)) { - _log(ZONE__INIT_ERR, "Failed to open port %d",Config->ZonePort); - ZoneConfig::SetZonePort(0); - worldserver.Disconnect(); - worldwasconnected = false; - } - } - - //check the factory for any new incoming streams. - while ((eqss = eqsf.Pop())) { - //pull the stream out of the factory and give it to the stream identifier - //which will figure out what patch they are running, and set up the dynamic - //structures and opcodes for that patch. - struct in_addr in; - in.s_addr = eqss->GetRemoteIP(); - _log(WORLD__CLIENT, "New connection from %s:%d", inet_ntoa(in),ntohs(eqss->GetRemotePort())); - stream_identifier.AddStream(eqss); //takes the stream - } - - //give the stream identifier a chance to do its work.... - stream_identifier.Process(); - - //check the stream identifier for any now-identified streams - while((eqsi = stream_identifier.PopIdentified())) { - //now that we know what patch they are running, start up their client object - struct in_addr in; - in.s_addr = eqsi->GetRemoteIP(); - _log(WORLD__CLIENT, "New client from %s:%d", inet_ntoa(in), ntohs(eqsi->GetRemotePort())); - Client* client = new Client(eqsi); - entity_list.AddClient(client); - } - - if ( numclients < 1 && zoneupdate_timer.GetDuration() != IDLEZONEUPDATE ) - zoneupdate_timer.SetTimer(IDLEZONEUPDATE); - else if ( numclients > 0 && zoneupdate_timer.GetDuration() == IDLEZONEUPDATE ) - { - zoneupdate_timer.SetTimer(ZONEUPDATE); - zoneupdate_timer.Trigger(); - } - - //check for timeouts in other threads - timeout_manager.CheckTimeouts(); - - if (worldserver.Connected()) { - worldwasconnected = true; - } - else { - if (worldwasconnected && ZoneLoaded) - entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost"); - worldwasconnected = false; - } - - if (ZoneLoaded && zoneupdate_timer.Check()) { - { - if(net.group_timer.Enabled() && net.group_timer.Check()) - entity_list.GroupProcess(); - - if(net.door_timer.Enabled() && net.door_timer.Check()) - entity_list.DoorProcess(); - - if(net.object_timer.Enabled() && net.object_timer.Check()) - entity_list.ObjectProcess(); - - if(net.corpse_timer.Enabled() && net.corpse_timer.Check()) - entity_list.CorpseProcess(); - - if(net.trap_timer.Enabled() && net.trap_timer.Check()) - entity_list.TrapProcess(); - - if(net.raid_timer.Enabled() && net.raid_timer.Check()) - entity_list.RaidProcess(); - - entity_list.Process(); - - entity_list.MobProcess(); - - entity_list.BeaconProcess(); - - if (zone) { - if(!zone->Process()) { - Zone::Shutdown(); - } - } - - if(quest_timers.Check()) - quest_manager.Process(); - - } - } - if (InterserverTimer.Check()) { - InterserverTimer.Start(); - database.ping(); - // AsyncLoadVariables(dbasync, &database); - entity_list.UpdateWho(); - if (worldserver.TryReconnect() && (!worldserver.Connected())) - worldserver.AsyncConnect(); - } - -#if defined(_EQDEBUG) && defined(DEBUG_PC) - QueryPerformanceCounter(&tmp3); - mainloop_time += tmp3.QuadPart - tmp2.QuadPart; - if (!--tmp0) { - tmp0 = 200; - printf("Elapsed Tics : %9.0f (%1.4f sec)\n", (double)mainloop_time, ((double)mainloop_time/tmp.QuadPart)); - printf("NPCAI Tics : %9.0f (%1.2f%%)\n", (double)npcai_time, ((double)npcai_time/mainloop_time)*100); - printf("FindSpell Tics: %9.0f (%1.2f%%)\n", (double)findspell_time, ((double)findspell_time/mainloop_time)*100); - printf("AtkAllowd Tics: %9.0f (%1.2f%%)\n", (double)IsAttackAllowed_time, ((double)IsAttackAllowed_time/mainloop_time)*100); - printf("ClientPro Tics: %9.0f (%1.2f%%)\n", (double)clientprocess_time, ((double)clientprocess_time/mainloop_time)*100); - printf("ClientAtk Tics: %9.0f (%1.2f%%)\n", (double)clientattack_time, ((double)clientattack_time/mainloop_time)*100); - mainloop_time = 0; - npcai_time = 0; - findspell_time = 0; - IsAttackAllowed_time = 0; - clientprocess_time = 0; - clientattack_time = 0; - } -#endif -#ifdef EQPROFILE -#ifdef PROFILE_DUMP_TIME - if(profile_dump_timer.Check()) { - DumpZoneProfile(); - } -#endif -#endif - } //end extra profiler block - Sleep(ZoneTimerResolution); - } - - entity_list.Clear(); - - parse->ClearInterfaces(); - -#ifdef EMBPERL - safe_delete(perl_parser); -#endif - -#ifdef LUA_EQEMU - safe_delete(lua_parser); -#endif - - safe_delete(mmf); - safe_delete(Config); - - if (zone != 0) - Zone::Shutdown(true); - //Fix for Linux world server problem. - eqsf.Close(); - worldserver.Disconnect(); - safe_delete(taskmanager); - command_deinit(); - safe_delete(parse); - CheckEQEMuErrorAndPause(); - _log(ZONE__INIT, "Proper zone shutdown complete."); - return 0; -} - -void CatchSignal(int sig_num) { -#ifdef _WINDOWS - _log(ZONE__INIT, "Recieved signal: %i", sig_num); -#endif - RunLoops = false; -} - -void Shutdown() -{ - Zone::Shutdown(true); - RunLoops = false; - worldserver.Disconnect(); - // safe_delete(worldserver); - _log(ZONE__INIT, "Shutting down..."); -} - -uint32 NetConnection::GetIP() -{ - char name[255+1]; - size_t len = 0; - hostent* host = 0; - - if (gethostname(name, len) < 0 || len <= 0) - { - return 0; - } - - host = (hostent*)gethostbyname(name); - if (host == 0) - { - return 0; - } - - return inet_addr(host->h_addr); -} - -uint32 NetConnection::GetIP(char* name) -{ - hostent* host = 0; - - host = (hostent*)gethostbyname(name); - if (host == 0) - { - return 0; - } - - return inet_addr(host->h_addr); - -} - -void NetConnection::SaveInfo(char* address, uint32 port, char* waddress, char* filename) { - - ZoneAddress = new char[strlen(address)+1]; - strcpy(ZoneAddress, address); - ZonePort = port; - WorldAddress = new char[strlen(waddress)+1]; - strcpy(WorldAddress, waddress); - strn0cpy(ZoneFileName, filename, sizeof(ZoneFileName)); -} - -NetConnection::NetConnection() -: - object_timer(5000), - door_timer(5000), - corpse_timer(2000), - group_timer(1000), - raid_timer(1000), - trap_timer(1000) -{ - ZonePort = 0; - ZoneAddress = 0; - WorldAddress = 0; - group_timer.Disable(); - raid_timer.Disable(); - corpse_timer.Disable(); - door_timer.Disable(); - object_timer.Disable(); - trap_timer.Disable(); -} - -NetConnection::~NetConnection() { - if (ZoneAddress != 0) - safe_delete_array(ZoneAddress); - if (WorldAddress != 0) - safe_delete_array(WorldAddress); -} - -void LoadSpells(EQEmu::MemoryMappedFile **mmf) { - int records = database.GetMaxSpellID() + 1; - - try { - EQEmu::IPCMutex mutex("spells"); - mutex.Lock(); - *mmf = new EQEmu::MemoryMappedFile("shared/spells"); - uint32 size = (*mmf)->Size(); - if(size != (records * sizeof(SPDat_Spell_Struct))) { - EQ_EXCEPT("Zone", "Unable to load spells: (*mmf)->Size() != records * sizeof(SPDat_Spell_Struct)"); - } - - spells = reinterpret_cast((*mmf)->Get()); - mutex.Unlock(); - } catch(std::exception &ex) { - LogFile->write(EQEMuLog::Error, "Error loading spells: %s", ex.what()); - return; - } - - SPDAT_RECORDS = records; -} - -/* Update Window Title with relevant information */ -void UpdateWindowTitle(char* iNewTitle) { -#ifdef _WINDOWS - char tmp[500]; - if (iNewTitle) { - snprintf(tmp, sizeof(tmp), "%i: %s", ZoneConfig::get()->ZonePort, iNewTitle); - } - else { - if (zone) { - #if defined(GOTFRAGS) || defined(_EQDEBUG) - snprintf(tmp, sizeof(tmp), "%i: %s, %i clients, %i", ZoneConfig::get()->ZonePort, zone->GetShortName(), numclients, getpid()); - #else - snprintf(tmp, sizeof(tmp), "%s :: clients: %i inst_id: %i inst_ver: %i :: port: %i", zone->GetShortName(), numclients, zone->GetInstanceID(), zone->GetInstanceVersion(), ZoneConfig::get()->ZonePort); - #endif - } - else { - #if defined(GOTFRAGS) || defined(_EQDEBUG) - snprintf(tmp, sizeof(tmp), "%i: sleeping, %i", ZoneConfig::get()->ZonePort, getpid()); - #else - snprintf(tmp, sizeof(tmp), "%i: sleeping", ZoneConfig::get()->ZonePort); - #endif - } - } - SetConsoleTitle(tmp); -#endif -} diff --git a/zone/npcx.cpp b/zone/npcx.cpp deleted file mode 100644 index 7d2766854..000000000 --- a/zone/npcx.cpp +++ /dev/null @@ -1,2492 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "../common/debug.h" -#include -#include -#include -#include -#include "../common/moremath.h" -#include -#include "../common/packet_dump_file.h" -#include "zone.h" -#ifdef _WINDOWS -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else -#include -#include -#endif - -#include "npc.h" -#include "map.h" -#include "entity.h" -#include "masterentity.h" -#include "../common/spdat.h" -#include "../common/bodytypes.h" -#include "spawngroup.h" -#include "../common/MiscFunctions.h" -#include "../common/StringUtil.h" -#include "../common/rulesys.h" -#include "StringIDs.h" - -//#define SPELLQUEUE //Use only if you want to be spammed by spell testing - - -extern Zone* zone; -extern volatile bool ZoneLoaded; -extern EntityList entity_list; - -#include "QuestParserCollection.h" - -NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float heading, int iflymode, bool IsCorpse) -: Mob(d->name, - d->lastname, - d->max_hp, - d->max_hp, - d->gender, - d->race, - d->class_, - (bodyType)d->bodytype, - d->deity, - d->level, - d->npc_id, - d->size, - d->runspeed, - heading, - x, - y, - z, - d->light, - d->texture, - d->helmtexture, - d->AC, - d->ATK, - d->STR, - d->STA, - d->DEX, - d->AGI, - d->INT, - d->WIS, - d->CHA, - d->haircolor, - d->beardcolor, - d->eyecolor1, - d->eyecolor2, - d->hairstyle, - d->luclinface, - d->beard, - d->drakkin_heritage, - d->drakkin_tattoo, - d->drakkin_details, - (uint32*)d->armor_tint, - 0, - d->see_invis, // pass see_invis/see_ivu flags to mob constructor - d->see_invis_undead, - d->see_hide, - d->see_improved_hide, - d->hp_regen, - d->mana_regen, - d->qglobal, - d->maxlevel, - d->scalerate ), - attacked_timer(CombatEventTimer_expire), - swarm_timer(100), - classattack_timer(1000), - knightattack_timer(1000), - assist_timer(AIassistcheck_delay), - qglobal_purge_timer(30000), - sendhpupdate_timer(1000), - enraged_timer(1000), - taunt_timer(TauntReuseTime * 1000) -{ - //What is the point of this, since the names get mangled.. - Mob* mob = entity_list.GetMob(name); - if(mob != 0) - entity_list.RemoveEntity(mob->GetID()); - - int moblevel=GetLevel(); - - NPCTypedata = d; - NPCTypedata_ours = nullptr; - respawn2 = in_respawn; - swarm_timer.Disable(); - - taunting = false; - proximity = nullptr; - copper = 0; - silver = 0; - gold = 0; - platinum = 0; - max_dmg = d->max_dmg; - min_dmg = d->min_dmg; - attack_count = d->attack_count; - grid = 0; - wp_m = 0; - max_wp=0; - save_wp = 0; - spawn_group = 0; - swarmInfoPtr = nullptr; - spellscale = d->spellscale; - healscale = d->healscale; - - logging_enabled = NPC_DEFAULT_LOGGING_ENABLED; - - pAggroRange = d->aggroradius; - pAssistRange = d->assistradius; - findable = d->findable; - trackable = d->trackable; - - MR = d->MR; - CR = d->CR; - DR = d->DR; - FR = d->FR; - PR = d->PR; - Corrup = d->Corrup; - PhR = d->PhR; - - STR = d->STR; - STA = d->STA; - AGI = d->AGI; - DEX = d->DEX; - INT = d->INT; - WIS = d->WIS; - CHA = d->CHA; - npc_mana = d->Mana; - - //quick fix of ordering if they screwed it up in the DB - if(max_dmg < min_dmg) { - int tmp = min_dmg; - min_dmg = max_dmg; - max_dmg = tmp; - } - - // Max Level and Stat Scaling if maxlevel is set - if(maxlevel > level) - { - LevelScale(); - } - - // Set Resists if they are 0 in the DB - CalcNPCResists(); - - // Set Mana and HP Regen Rates if they are 0 in the DB - CalcNPCRegen(); - - // Set Min and Max Damage if they are 0 in the DB - if(max_dmg == 0){ - CalcNPCDamage(); - } - - accuracy_rating = d->accuracy_rating; - ATK = d->ATK; - - CalcMaxMana(); - SetMana(GetMaxMana()); - - MerchantType = d->merchanttype; - merchant_open = GetClass() == MERCHANT; - adventure_template_id = d->adventure_template; - org_x = x; - org_y = y; - org_z = z; - flymode = iflymode; - guard_x = -1; //just some value we might be able to recongize as "unset" - guard_y = -1; - guard_z = -1; - guard_heading = 0; - guard_anim = eaStanding; - roambox_distance = 0; - roambox_max_x = -2; - roambox_max_y = -2; - roambox_min_x = -2; - roambox_min_y = -2; - roambox_movingto_x = -2; - roambox_movingto_y = -2; - roambox_min_delay = 1000; - roambox_delay = 1000; - org_heading = heading; - p_depop = false; - loottable_id = d->loottable_id; - - no_target_hotkey = d->no_target_hotkey; - - primary_faction = 0; - SetNPCFactionID(d->npc_faction_id); - - npc_spells_id = 0; - HasAISpell = false; - HasAISpellEffects = false; - - if(GetClass() == MERCERNARY_MASTER && RuleB(Mercs, AllowMercs)) - { - LoadMercTypes(); - LoadMercs(); - } - - SpellFocusDMG = 0; - SpellFocusHeal = 0; - - pet_spell_id = 0; - - delaytimer = false; - combat_event = false; - attack_speed = d->attack_speed; - slow_mitigation = d->slow_mitigation; - - EntityList::RemoveNumbers(name); - entity_list.MakeNameUnique(name); - - npc_aggro = d->npc_aggro; - - if(!IsMerc()) - AI_Start(); - - d_meele_texture1 = d->d_meele_texture1; - d_meele_texture2 = d->d_meele_texture2; - memset(equipment, 0, sizeof(equipment)); - prim_melee_type = d->prim_melee_type; - sec_melee_type = d->sec_melee_type; - - // If Melee Textures are not set, set attack type to Hand to Hand as default - if(!d_meele_texture1) - prim_melee_type = 28; - if(!d_meele_texture2) - sec_melee_type = 28; - - //give NPCs skill values... - int r; - for(r = 0; r <= HIGHEST_SKILL; r++) { - skills[r] = database.GetSkillCap(GetClass(),(SkillUseTypes)r,moblevel); - } - - if(d->trap_template > 0) - { - std::map >::iterator trap_ent_iter; - std::list trap_list; - - trap_ent_iter = zone->ldon_trap_entry_list.find(d->trap_template); - if(trap_ent_iter != zone->ldon_trap_entry_list.end()) - { - trap_list = trap_ent_iter->second; - if(trap_list.size() > 0) - { - std::list::iterator trap_list_iter = trap_list.begin(); - std::advance(trap_list_iter, MakeRandomInt(0, trap_list.size() - 1)); - LDoNTrapTemplate* tt = (*trap_list_iter); - if(tt) - { - if((uint8)tt->spell_id > 0) - { - ldon_trapped = true; - ldon_spell_id = tt->spell_id; - } - else - { - ldon_trapped = false; - ldon_spell_id = 0; - } - - ldon_trap_type = (uint8)tt->type; - if(tt->locked > 0) - { - ldon_locked = true; - ldon_locked_skill = tt->skill; - } - else - { - ldon_locked = false; - ldon_locked_skill = 0; - } - ldon_trap_detected = 0; - } - } - else - { - ldon_trapped = false; - ldon_trap_type = 0; - ldon_spell_id = 0; - ldon_locked = false; - ldon_locked_skill = 0; - ldon_trap_detected = 0; - } - } - else - { - ldon_trapped = false; - ldon_trap_type = 0; - ldon_spell_id = 0; - ldon_locked = false; - ldon_locked_skill = 0; - ldon_trap_detected = 0; - } - } - else - { - ldon_trapped = false; - ldon_trap_type = 0; - ldon_spell_id = 0; - ldon_locked = false; - ldon_locked_skill = 0; - ldon_trap_detected = 0; - } - reface_timer = new Timer(15000); - reface_timer->Disable(); - qGlobals = nullptr; - guard_x_saved = 0; - guard_y_saved = 0; - guard_z_saved = 0; - guard_heading_saved = 0; - SetEmoteID(d->emoteid); - InitializeBuffSlots(); - CalcBonuses(); -} - -NPC::~NPC() -{ - AI_Stop(); - - if(proximity != nullptr) { - entity_list.RemoveProximity(GetID()); - safe_delete(proximity); - } - - safe_delete(NPCTypedata_ours); - - { - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end; ++cur) { - ServerLootItem_Struct* item = *cur; - safe_delete(item); - } - itemlist.clear(); - } - - { - std::list::iterator cur,end; - cur = faction_list.begin(); - end = faction_list.end(); - for(; cur != end; ++cur) { - struct NPCFaction* fac = *cur; - safe_delete(fac); - } - faction_list.clear(); - } - - safe_delete(reface_timer); - safe_delete(swarmInfoPtr); - safe_delete(qGlobals); - //Moved this from ~Mob, because it could cause a crash in some cases where a hate list was still used and that mob was the only one on the hate list. - entity_list.RemoveFromTargets(this, true); - UninitializeBuffSlots(); -} - -void NPC::SetTarget(Mob* mob) { - if(mob == GetTarget()) //dont bother if they are allready our target - return; - - //our target is already set, do not turn from the course, unless our current target is dead. - if(GetSwarmInfo() && GetTarget() && (GetTarget()->GetHP() > 0)) { - Mob *targ = entity_list.GetMob(GetSwarmInfo()->target); - if(targ != mob){ - return; - } - } - - if (mob) { - SetAttackTimer(); - } else { - ranged_timer.Disable(); - //attack_timer.Disable(); - attack_dw_timer.Disable(); - } - Mob::SetTarget(mob); -} - -ServerLootItem_Struct* NPC::GetItem(int slot_id) { - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end; ++cur) { - ServerLootItem_Struct* item = *cur; - if (item->equipSlot == slot_id) { - return item; - } - } - return(nullptr); -} - -void NPC::RemoveItem(uint32 item_id, uint16 quantity, uint16 slot) { - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end; ++cur) { - ServerLootItem_Struct* item = *cur; - if (item->item_id == item_id && slot <= 0 && quantity <= 0) { - itemlist.erase(cur); - return; - } - else if (item->item_id == item_id && item->equipSlot == slot && quantity >= 1) { - //std::cout<<"NPC::RemoveItem"<<" equipSlot:"<equipSlot<<" quantity:"<< quantity<charges <= quantity) - itemlist.erase(cur); - else - item->charges -= quantity; - return; - } - } -} - -void NPC::CheckMinMaxLevel(Mob *them) -{ - if(them == nullptr || !them->IsClient()) - return; - - uint16 themlevel = them->GetLevel(); - uint8 material; - - std::list::iterator cur = itemlist.begin(); - while(cur != itemlist.end()) - { - if(!(*cur)) - return; - - if(themlevel < (*cur)->minlevel || themlevel > (*cur)->maxlevel) - { - material = Inventory::CalcMaterialFromSlot((*cur)->equipSlot); - if(material != 0xFF) - SendWearChange(material); - - cur = itemlist.erase(cur); - continue; - } - ++cur; - } - -} - -void NPC::ClearItemList() { - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end; ++cur) { - ServerLootItem_Struct* item = *cur; - safe_delete(item); - } - itemlist.clear(); -} - -void NPC::QueryLoot(Client* to) { - int x = 0; - to->Message(0, "Coin: %ip %ig %is %ic", platinum, gold, silver, copper); - - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end; ++cur) { - const Item_Struct* item = database.GetItem((*cur)->item_id); - if (item) - if (to->GetClientVersion() >= EQClientRoF) - { - to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(*cur)->minlevel, (*cur)->maxlevel, (int) item->ID,0x12, item->ID, item->Name, 0x12); - } - else if (to->GetClientVersion() >= EQClientSoF) - { - to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X00000000000000000000000000000000000000000000%s%c",(*cur)->minlevel, (*cur)->maxlevel, (int) item->ID,0x12, item->ID, item->Name, 0x12); - } - else - { - to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X000000000000000000000000000000000000000%s%c",(*cur)->minlevel, (*cur)->maxlevel, (int) item->ID,0x12, item->ID, item->Name, 0x12); - } - else - LogFile->write(EQEMuLog::Error, "Database error, invalid item"); - x++; - } - to->Message(0, "%i items on %s.", x, GetName()); -} - -void NPC::AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_platinum) { - if(in_copper >= 0) - copper = in_copper; - else - copper = 0; - - if(in_silver >= 0) - silver = in_silver; - else - silver = 0; - - if(in_gold >= 0) - gold = in_gold; - else - gold = 0; - - if(in_platinum >= 0) - platinum = in_platinum; - else - platinum = 0; -} - -void NPC::AddCash() { - copper = MakeRandomInt(1, 100); - silver = MakeRandomInt(1, 50); - gold = MakeRandomInt(1, 10); - platinum = MakeRandomInt(1, 5); -} - -void NPC::RemoveCash() { - copper = 0; - silver = 0; - gold = 0; - platinum = 0; -} - -bool NPC::Process() -{ - if (IsStunned() && stunned_timer.Check()) - { - this->stunned = false; - this->stunned_timer.Disable(); - this->spun_timer.Disable(); - } - - if (p_depop) - { - Mob* owner = entity_list.GetMob(this->ownerid); - if (owner != 0) - { - //if(GetBodyType() != BT_SwarmPet) - // owner->SetPetID(0); - this->ownerid = 0; - this->petid = 0; - } - return false; - } - - SpellProcess(); - - if(tic_timer.Check()) - { - BuffProcess(); - - if(curfp) - ProcessFlee(); - - uint32 bonus = 0; - - if(GetAppearance() == eaSitting) - bonus+=3; - - int32 OOCRegen = 0; - if(oocregen > 0){ //should pull from Mob class - OOCRegen += GetMaxHP() * oocregen / 100; - } - //Lieka Edit:Fixing NPC regen.NPCs should regen to full during a set duration, not based on their HPs.Increase NPC's HPs by % of total HPs / tick. - if((GetHP() < GetMaxHP()) && !IsPet()) { - if(!IsEngaged()) {//NPC out of combat - if(hp_regen > OOCRegen) - SetHP(GetHP() + hp_regen); - else - SetHP(GetHP() + OOCRegen); - } else - SetHP(GetHP()+hp_regen); - } else if(GetHP() < GetMaxHP() && GetOwnerID() !=0) { - if(!IsEngaged()) //pet - SetHP(GetHP()+hp_regen+bonus+(GetLevel()/5)); - else - SetHP(GetHP()+hp_regen+bonus); - } else - SetHP(GetHP()+hp_regen); - - if(GetMana() < GetMaxMana()) { - SetMana(GetMana()+mana_regen+bonus); - } - - - if(zone->adv_data && !p_depop) - { - ServerZoneAdventureDataReply_Struct* ds = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; - if(ds->type == Adventure_Rescue && ds->data_id == GetNPCTypeID()) - { - Mob *o = GetOwner(); - if(o && o->IsClient()) - { - float x_diff = ds->dest_x - GetX(); - float y_diff = ds->dest_y - GetY(); - float z_diff = ds->dest_z - GetZ(); - float dist = ((x_diff * x_diff) + (y_diff * y_diff) + (z_diff * z_diff)); - if(dist < RuleR(Adventure, DistanceForRescueComplete)) - { - zone->DoAdventureCountIncrease(); - Say("You don't know what this means to me. Thank you so much for finding and saving me from" - " this wretched place. I'll find my way from here."); - Depop(); - } - } - } - } - } - - if (sendhpupdate_timer.Check() && (IsTargeted() || (IsPet() && GetOwner() && GetOwner()->IsClient()))) { - if(!IsFullHP || cur_hp 999) - viral_timer_counter = 0; - } - - if(projectile_timer.Check()) - SpellProjectileEffect(); - - if(spellbonuses.GravityEffect == 1) { - if(gravity_timer.Check()) - DoGravityEffect(); - } - - if(reface_timer->Check() && !IsEngaged() && (guard_x == GetX() && guard_y == GetY() && guard_z == GetZ())) { - SetHeading(guard_heading); - SendPosition(); - reface_timer->Disable(); - } - - if (IsMezzed()) - return true; - - if(IsStunned()) { - if(spun_timer.Check()) - Spin(); - return true; - } - - if (enraged_timer.Check()){ - ProcessEnrage(); - } - - //Handle assists... - if(assist_timer.Check() && IsEngaged() && !Charmed()) { - entity_list.AIYellForHelp(this, GetTarget()); - } - - if(qGlobals) - { - if(qglobal_purge_timer.Check()) - { - qGlobals->PurgeExpiredGlobals(); - } - } - - AI_Process(); - - return true; -} - -uint32 NPC::CountLoot() { - return(itemlist.size()); -} - -void NPC::Depop(bool StartSpawnTimer) { - uint16 emoteid = this->GetEmoteID(); - if(emoteid != 0) - this->DoNPCEmote(ONDESPAWN,emoteid); - p_depop = true; - if (StartSpawnTimer) { - if (respawn2 != 0) { - respawn2->DeathReset(); - } - } -} - -bool NPC::DatabaseCastAccepted(int spell_id) { - for (int i=0; i < 12; i++) { - switch(spells[spell_id].effectid[i]) { - case SE_Stamina: { - if(IsEngaged() && GetHPRatio() < 100) - return true; - else - return false; - break; - } - case SE_CurrentHPOnce: - case SE_CurrentHP: { - if(this->GetHPRatio() < 100 && spells[spell_id].buffduration == 0) - return true; - else - return false; - break; - } - - case SE_HealOverTime: { - if(this->GetHPRatio() < 100) - return true; - else - return false; - break; - } - case SE_DamageShield: { - return true; - } - case SE_NecPet: - case SE_SummonPet: { - if(GetPet()){ -#ifdef SPELLQUEUE - printf("%s: Attempted to make a second pet, denied.\n",GetName()); -#endif - return false; - } - break; - } - case SE_LocateCorpse: - case SE_SummonCorpse: { - return false; //Pfft, npcs don't need to summon corpses/locate corpses! - break; - } - default: - if(spells[spell_id].goodEffect == 1 && !(spells[spell_id].buffduration == 0 && this->GetHPRatio() == 100) && !IsEngaged()) - return true; - return false; - } - } - return false; -} - -NPC* NPC::SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z, float in_heading, Client* client) { - if(spawncommand == 0 || spawncommand[0] == 0) { - return 0; - } - else { - Seperator sep(spawncommand); - //Lets see if someone didn't fill out the whole #spawn function properly - if (!sep.IsNumber(1)) - sprintf(sep.arg[1],"1"); - if (!sep.IsNumber(2)) - sprintf(sep.arg[2],"1"); - if (!sep.IsNumber(3)) - sprintf(sep.arg[3],"0"); - if (atoi(sep.arg[4]) > 2100000000 || atoi(sep.arg[4]) <= 0) - sprintf(sep.arg[4]," "); - if (!strcmp(sep.arg[5],"-")) - sprintf(sep.arg[5]," "); - if (!sep.IsNumber(5)) - sprintf(sep.arg[5]," "); - if (!sep.IsNumber(6)) - sprintf(sep.arg[6],"1"); - if (!sep.IsNumber(8)) - sprintf(sep.arg[8],"0"); - if (!sep.IsNumber(9)) - sprintf(sep.arg[9], "0"); - if (!sep.IsNumber(7)) - sprintf(sep.arg[7],"0"); - if (!strcmp(sep.arg[4],"-")) - sprintf(sep.arg[4]," "); - if (!sep.IsNumber(10)) // bodytype - sprintf(sep.arg[10], "0"); - //Calc MaxHP if client neglected to enter it... - if (!sep.IsNumber(4)) { - //Stolen from Client::GetMaxHP... - uint8 multiplier = 0; - int tmplevel = atoi(sep.arg[2]); - switch(atoi(sep.arg[5])) - { - case WARRIOR: - if (tmplevel < 20) - multiplier = 22; - else if (tmplevel < 30) - multiplier = 23; - else if (tmplevel < 40) - multiplier = 25; - else if (tmplevel < 53) - multiplier = 27; - else if (tmplevel < 57) - multiplier = 28; - else - multiplier = 30; - break; - - case DRUID: - case CLERIC: - case SHAMAN: - multiplier = 15; - break; - - case PALADIN: - case SHADOWKNIGHT: - if (tmplevel < 35) - multiplier = 21; - else if (tmplevel < 45) - multiplier = 22; - else if (tmplevel < 51) - multiplier = 23; - else if (tmplevel < 56) - multiplier = 24; - else if (tmplevel < 60) - multiplier = 25; - else - multiplier = 26; - break; - - case MONK: - case BARD: - case ROGUE: - //case BEASTLORD: - if (tmplevel < 51) - multiplier = 18; - else if (tmplevel < 58) - multiplier = 19; - else - multiplier = 20; - break; - - case RANGER: - if (tmplevel < 58) - multiplier = 20; - else - multiplier = 21; - break; - - case MAGICIAN: - case WIZARD: - case NECROMANCER: - case ENCHANTER: - multiplier = 12; - break; - - default: - if (tmplevel < 35) - multiplier = 21; - else if (tmplevel < 45) - multiplier = 22; - else if (tmplevel < 51) - multiplier = 23; - else if (tmplevel < 56) - multiplier = 24; - else if (tmplevel < 60) - multiplier = 25; - else - multiplier = 26; - break; - } - sprintf(sep.arg[4],"%i",5+multiplier*atoi(sep.arg[2])+multiplier*atoi(sep.arg[2])*75/300); - } - - // Autoselect NPC Gender - if (sep.arg[5][0] == 0) { - sprintf(sep.arg[5], "%i", (int) Mob::GetDefaultGender(atoi(sep.arg[1]))); - } - - //Time to create the NPC!! - NPCType* npc_type = new NPCType; - memset(npc_type, 0, sizeof(NPCType)); - - strncpy(npc_type->name, sep.arg[0], 60); - npc_type->cur_hp = atoi(sep.arg[4]); - npc_type->max_hp = atoi(sep.arg[4]); - npc_type->race = atoi(sep.arg[1]); - npc_type->gender = atoi(sep.arg[5]); - npc_type->class_ = atoi(sep.arg[6]); - npc_type->deity = 1; - npc_type->level = atoi(sep.arg[2]); - npc_type->npc_id = 0; - npc_type->loottable_id = 0; - npc_type->texture = atoi(sep.arg[3]); - npc_type->light = 0; - npc_type->runspeed = 1.25; - npc_type->d_meele_texture1 = atoi(sep.arg[7]); - npc_type->d_meele_texture2 = atoi(sep.arg[8]); - npc_type->merchanttype = atoi(sep.arg[9]); - npc_type->bodytype = atoi(sep.arg[10]); - - npc_type->STR = 150; - npc_type->STA = 150; - npc_type->DEX = 150; - npc_type->AGI = 150; - npc_type->INT = 150; - npc_type->WIS = 150; - npc_type->CHA = 150; - - npc_type->prim_melee_type = 28; - npc_type->sec_melee_type = 28; - - NPC* npc = new NPC(npc_type, 0, in_x, in_y, in_z, in_heading/8, FlyMode3); - npc->GiveNPCTypeData(npc_type); - - entity_list.AddNPC(npc); - - if (client) { - // Notify client of spawn data - client->Message(0, "New spawn:"); - client->Message(0, "Name: %s", npc->name); - client->Message(0, "Race: %u", npc->race); - client->Message(0, "Level: %u", npc->level); - client->Message(0, "Material: %u", npc->texture); - client->Message(0, "Current/Max HP: %i", npc->max_hp); - client->Message(0, "Gender: %u", npc->gender); - client->Message(0, "Class: %u", npc->class_); - client->Message(0, "Weapon Item Number: %u/%u", npc->d_meele_texture1, npc->d_meele_texture2); - client->Message(0, "MerchantID: %u", npc->MerchantType); - client->Message(0, "Bodytype: %u", npc->bodytype); - } - - return npc; - } -} - -uint32 ZoneDatabase::NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn, uint32 extra) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 tmp = 0; - uint32 tmp2 = 0; - uint32 last_insert_id = 0; - switch (command) { - case 0: { // Create a new NPC and add all spawn related data - uint32 npc_type_id = 0; - uint32 spawngroupid; - if (extra && c && c->GetZoneID()) - { - // Set an npc_type ID within the standard range for the current zone if possible (zone_id * 1000) - int starting_npc_id = c->GetZoneID() * 1000; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT MAX(id) FROM npc_types WHERE id >= %i AND id < %i", starting_npc_id, (starting_npc_id + 1000)), errbuf, &result)) { - row = mysql_fetch_row(result); - if(row) - { - if (row[0]) - { - npc_type_id = atoi(row[0]) + 1; - // Prevent the npc_type id from exceeding the range for this zone - if (npc_type_id >= (starting_npc_id + 1000)) - { - npc_type_id = 0; - } - } - else - { - // row[0] is nullptr - No npc_type IDs set in this range yet - npc_type_id = starting_npc_id; - } - } - - safe_delete_array(query); - mysql_free_result(result); - } - } - char tmpstr[64]; - EntityList::RemoveNumbers(strn0cpy(tmpstr, spawn->GetName(), sizeof(tmpstr))); - if (npc_type_id) - { - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO npc_types (id, name, level, race, class, hp, gender, texture, helmtexture, size, loottable_id, merchant_id, face, runspeed, prim_melee_type, sec_melee_type) values(%i,\"%s\",%i,%i,%i,%i,%i,%i,%i,%f,%i,%i,%i,%f,%i,%i)", npc_type_id, tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28), errbuf, 0, 0, &npc_type_id)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - } - else - { - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO npc_types (name, level, race, class, hp, gender, texture, helmtexture, size, loottable_id, merchant_id, face, runspeed, prim_melee_type, sec_melee_type) values(\"%s\",%i,%i,%i,%i,%i,%i,%i,%f,%i,%i,%i,%f,%i,%i)", tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28), errbuf, 0, 0, &npc_type_id)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - } - if(c) c->LogSQL(query); - safe_delete_array(query); - snprintf(tmpstr, sizeof(tmpstr), "%s-%s", zone, spawn->GetName()); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawngroup (id, name) values(%i, '%s')", tmp, tmpstr), errbuf, 0, 0, &spawngroupid)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) values('%s', %u, %f, %f, %f, %i, %f, %i)", zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), 1200, spawn->GetHeading(), spawngroupid), errbuf, 0, 0, &tmp)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawnentry (spawngroupID, npcID, chance) values(%i, %i, %i)", spawngroupid, npc_type_id, 100), errbuf, 0)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - return true; - break; - } - case 1:{ // Add new spawn group and spawn point for an existing NPC Type ID - tmp2 = spawn->GetNPCTypeID(); - char tmpstr[64]; - snprintf(tmpstr, sizeof(tmpstr), "%s%s%i", zone, spawn->GetName(),Timer::GetCurrentTime()); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawngroup (name) values('%s')", tmpstr), errbuf, 0, 0, &last_insert_id)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - - uint32 respawntime = 0; - uint32 spawnid = 0; - if (extra) - respawntime = extra; - else if(spawn->respawn2 && spawn->respawn2->RespawnTimer() != 0) - respawntime = spawn->respawn2->RespawnTimer(); - else - respawntime = 1200; - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) values('%s', %u, %f, %f, %f, %i, %f, %i)", zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), respawntime, spawn->GetHeading(), last_insert_id), errbuf, 0, 0, &spawnid)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawnentry (spawngroupID, npcID, chance) values(%i, %i, %i)", last_insert_id, tmp2, 100), errbuf, 0)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - return spawnid; - break; - } - case 2: { // Update npc_type appearance and other data on targeted spawn - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE npc_types SET name=\"%s\", level=%i, race=%i, class=%i, hp=%i, gender=%i, texture=%i, helmtexture=%i, size=%i, loottable_id=%i, merchant_id=%i, face=%i, WHERE id=%i", spawn->GetName(), spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, spawn->GetNPCTypeID()), errbuf, 0)) { - if(c) c->LogSQL(query); - safe_delete_array(query); - return true; - } - else { - safe_delete_array(query); - return false; - } - break; - } - case 3: { // delete spawn from spawning, but leave in npc_types table - if (!RunQuery(query, MakeAnyLenString(&query, "SELECT id,spawngroupID from spawn2 where zone='%s' AND spawngroupID=%i", zone, spawn->GetSp2()), errbuf, &result)) { - safe_delete_array(query); - return 0; - } - safe_delete_array(query); - - row = mysql_fetch_row(result); - if (row == nullptr) return false; - if (row[0]) tmp = atoi(row[0]); - if (row[1]) tmp2 = atoi(row[1]); - - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawn2 WHERE id='%i'", tmp), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawngroup WHERE id='%i'", tmp2), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawnentry WHERE spawngroupID='%i'", tmp2), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - return true; - - - break; - } - case 4: { //delete spawn from DB (including npc_type) - if (!RunQuery(query, MakeAnyLenString(&query, "SELECT id,spawngroupID from spawn2 where zone='%s' AND version=%u AND spawngroupID=%i", zone, zone_version, spawn->GetSp2()), errbuf, &result)) { - safe_delete_array(query); - return(0); - } - safe_delete_array(query); - - row = mysql_fetch_row(result); - if (row == nullptr) return false; - if (row[0]) tmp = atoi(row[0]); - if (row[1]) tmp2 = atoi(row[1]); - mysql_free_result(result); - - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawn2 WHERE id='%i'", tmp), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawngroup WHERE id='%i'", tmp2), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawnentry WHERE spawngroupID='%i'", tmp2), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM npc_types WHERE id='%i'", spawn->GetNPCTypeID()), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - return true; - break; - } - case 5: { // add a spawn from spawngroup - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) values('%s', %u, %f, %f, %f, %i, %f, %i)", zone, zone_version, c->GetX(), c->GetY(), c->GetZ(), 120, c->GetHeading(), extra), errbuf, 0, 0, &tmp)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - - return true; - break; - } - case 6: { // add npc_type - uint32 npc_type_id; - char tmpstr[64]; - EntityList::RemoveNumbers(strn0cpy(tmpstr, spawn->GetName(), sizeof(tmpstr))); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO npc_types (name, level, race, class, hp, gender, texture, helmtexture, size, loottable_id, merchant_id, face, runspeed, prim_melee_type, sec_melee_type) values(\"%s\",%i,%i,%i,%i,%i,%i,%i,%f,%i,%i,%i,%f,%i,%i)", tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28), errbuf, 0, 0, &npc_type_id)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if(c) c->Message(0, "%s npc_type ID %i created successfully!", tmpstr, npc_type_id); - return true; - break; - } - } - return false; -} - -int32 NPC::GetEquipmentMaterial(uint8 material_slot) const -{ - if (material_slot >= _MaterialCount) - return 0; - - int inv_slot = Inventory::CalcSlotFromMaterial(material_slot); - if (inv_slot == -1) - return 0; - if(equipment[inv_slot] == 0) { - switch(material_slot) { - case MaterialHead: - return helmtexture; - case MaterialChest: - return texture; - case MaterialPrimary: - return d_meele_texture1; - case MaterialSecondary: - return d_meele_texture2; - default: - //they have nothing in the slot, and its not a special slot... they get nothing. - return(0); - } - } - - //they have some loot item in this slot, pass it up to the default handler - return(Mob::GetEquipmentMaterial(material_slot)); -} - -uint32 NPC::GetMaxDamage(uint8 tlevel) -{ - uint32 dmg = 0; - if (tlevel < 40) - dmg = tlevel*2+2; - else if (tlevel < 50) - dmg = level*25/10+2; - else if (tlevel < 60) - dmg = (tlevel*3+2)+((tlevel-50)*30); - else - dmg = (tlevel*3+2)+((tlevel-50)*35); - return dmg; -} - -void NPC::PickPocket(Client* thief) { - - thief->CheckIncreaseSkill(SkillPickPockets, nullptr, 5); - - //make sure were allowed to targte them: - int olevel = GetLevel(); - if(olevel > (thief->GetLevel() + THIEF_PICKPOCKET_OVER)) { - thief->Message(13, "You are too inexperienced to pick pocket this target"); - thief->SendPickPocketResponse(this, 0, PickPocketFailed); - //should we check aggro - return; - } - - if(MakeRandomInt(0, 100) > 95){ - AddToHateList(thief, 50); - Say("Stop thief!"); - thief->Message(13, "You are noticed trying to steal!"); - thief->SendPickPocketResponse(this, 0, PickPocketFailed); - return; - } - - int steal_skill = thief->GetSkill(SkillPickPockets); - int stealchance = steal_skill*100/(5*olevel+5); - ItemInst* inst = 0; - int x = 0; - int slot[50]; - int steal_items[50]; - int charges[50]; - int money[4]; - money[0] = GetPlatinum(); - money[1] = GetGold(); - money[2] = GetSilver(); - money[3] = GetCopper(); - if (steal_skill < 125) - money[0] = 0; - if (steal_skill < 60) - money[1] = 0; - memset(slot,0,50); - memset(steal_items,0,50); - memset(charges,0,50); - //Determine wheter to steal money or an item. - bool no_coin = ((money[0] + money[1] + money[2] + money[3]) == 0); - bool steal_item = (MakeRandomInt(0, 99) < 50 || no_coin); - if (steal_item) - { - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end && x < 49; ++cur) { - ServerLootItem_Struct* citem = *cur; - const Item_Struct* item = database.GetItem(citem->item_id); - if (item) - { - inst = database.CreateItem(item, citem->charges); - bool is_arrow = (item->ItemType == ItemTypeArrow) ? true : false; - int slot_id = thief->GetInv().FindFreeSlot(false, true, inst->GetItem()->Size, is_arrow); - if (/*!Equipped(item->ID) &&*/ - !item->Magic && item->NoDrop != 0 && !inst->IsType(ItemClassContainer) && slot_id != SLOT_INVALID - /*&& steal_skill > item->StealSkill*/ ) - { - slot[x] = slot_id; - steal_items[x] = item->ID; - if (inst->IsStackable()) - charges[x] = 1; - else - charges[x] = citem->charges; - x++; - } - } - } - if (x > 0) - { - int random = MakeRandomInt(0, x-1); - inst = database.CreateItem(steal_items[random], charges[random]); - if (inst) - { - const Item_Struct* item = inst->GetItem(); - if (item) - { - if (/*item->StealSkill || */steal_skill >= stealchance) - { - thief->PutItemInInventory(slot[random], *inst); - thief->SendItemPacket(slot[random], inst, ItemPacketTrade); - RemoveItem(item->ID); - thief->SendPickPocketResponse(this, 0, PickPocketItem, item); - } - else - steal_item = false; - } - else - steal_item = false; - } - else - steal_item = false; - } - else if (!no_coin) - { - steal_item = false; - } - else - { - thief->Message(0, "This target's pockets are empty"); - thief->SendPickPocketResponse(this, 0, PickPocketFailed); - } - } - if (!steal_item) //Steal money - { - uint32 amt = MakeRandomInt(1, (steal_skill/25)+1); - int steal_type = 0; - if (!money[0]) - { - steal_type = 1; - if (!money[1]) - { - steal_type = 2; - if (!money[2]) - { - steal_type = 3; - } - } - } - - if (MakeRandomInt(0, 100) <= stealchance) - { - switch (steal_type) - { - case 0:{ - if (amt > GetPlatinum()) - amt = GetPlatinum(); - SetPlatinum(GetPlatinum()-amt); - thief->AddMoneyToPP(0,0,0,amt,false); - thief->SendPickPocketResponse(this, amt, PickPocketPlatinum); - break; - } - case 1:{ - if (amt > GetGold()) - amt = GetGold(); - SetGold(GetGold()-amt); - thief->AddMoneyToPP(0,0,amt,0,false); - thief->SendPickPocketResponse(this, amt, PickPocketGold); - break; - } - case 2:{ - if (amt > GetSilver()) - amt = GetSilver(); - SetSilver(GetSilver()-amt); - thief->AddMoneyToPP(0,amt,0,0,false); - thief->SendPickPocketResponse(this, amt, PickPocketSilver); - break; - } - case 3:{ - if (amt > GetCopper()) - amt = GetCopper(); - SetCopper(GetCopper()-amt); - thief->AddMoneyToPP(amt,0,0,0,false); - thief->SendPickPocketResponse(this, amt, PickPocketCopper); - break; - } - } - } - else - { - thief->SendPickPocketResponse(this, 0, PickPocketFailed); - } - } - safe_delete(inst); -} - -void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool remove) { - if(reset) - { - ClearSpecialAbilities(); - } - - const char* orig_parse = parse; - while (*parse) - { - switch(*parse) - { - case 'E': - SetSpecialAbility(SPECATK_ENRAGE, remove ? 0 : 1); - break; - case 'F': - SetSpecialAbility(SPECATK_FLURRY, remove ? 0 : 1); - break; - case 'R': - SetSpecialAbility(SPECATK_RAMPAGE, remove ? 0 : 1); - break; - case 'r': - SetSpecialAbility(SPECATK_AREA_RAMPAGE, remove ? 0 : 1); - break; - case 'S': - if(remove) { - SetSpecialAbility(SPECATK_SUMMON, 0); - StopSpecialAbilityTimer(SPECATK_SUMMON); - } else { - SetSpecialAbility(SPECATK_SUMMON, 1); - } - break; - case 'T': - SetSpecialAbility(SPECATK_TRIPLE, remove ? 0 : 1); - break; - case 'Q': - //quad requires triple to work properly - if(remove) { - SetSpecialAbility(SPECATK_QUAD, 0); - } else { - SetSpecialAbility(SPECATK_TRIPLE, 1); - SetSpecialAbility(SPECATK_QUAD, 1); - } - break; - case 'b': - SetSpecialAbility(SPECATK_BANE, remove ? 0 : 1); - break; - case 'm': - SetSpecialAbility(SPECATK_MAGICAL, remove ? 0 : 1); - break; - case 'U': - SetSpecialAbility(UNSLOWABLE, remove ? 0 : 1); - break; - case 'M': - SetSpecialAbility(UNMEZABLE, remove ? 0 : 1); - break; - case 'C': - SetSpecialAbility(UNCHARMABLE, remove ? 0 : 1); - break; - case 'N': - SetSpecialAbility(UNSTUNABLE, remove ? 0 : 1); - break; - case 'I': - SetSpecialAbility(UNSNAREABLE, remove ? 0 : 1); - break; - case 'D': - SetSpecialAbility(UNFEARABLE, remove ? 0 : 1); - break; - case 'K': - SetSpecialAbility(UNDISPELLABLE, remove ? 0 : 1); - break; - case 'A': - SetSpecialAbility(IMMUNE_MELEE, remove ? 0 : 1); - break; - case 'B': - SetSpecialAbility(IMMUNE_MAGIC, remove ? 0 : 1); - break; - case 'f': - SetSpecialAbility(IMMUNE_FLEEING, remove ? 0 : 1); - break; - case 'O': - SetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE, remove ? 0 : 1); - break; - case 'W': - SetSpecialAbility(IMMUNE_MELEE_NONMAGICAL, remove ? 0 : 1); - break; - case 'H': - SetSpecialAbility(IMMUNE_AGGRO, remove ? 0 : 1); - break; - case 'G': - SetSpecialAbility(IMMUNE_AGGRO_ON, remove ? 0 : 1); - break; - case 'g': - SetSpecialAbility(IMMUNE_CASTING_FROM_RANGE, remove ? 0 : 1); - break; - case 'd': - SetSpecialAbility(IMMUNE_FEIGN_DEATH, remove ? 0 : 1); - break; - case 'Y': - SetSpecialAbility(SPECATK_RANGED_ATK, remove ? 0 : 1); - break; - case 'L': - SetSpecialAbility(SPECATK_INNATE_DW, remove ? 0 : 1); - break; - case 't': - SetSpecialAbility(NPC_TUNNELVISION, remove ? 0 : 1); - break; - case 'n': - SetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS, remove ? 0 : 1); - break; - case 'p': - SetSpecialAbility(IMMUNE_PACIFY, remove ? 0 : 1); - break; - case 'J': - SetSpecialAbility(LEASH, remove ? 0 : 1); - break; - case 'j': - SetSpecialAbility(TETHER, remove ? 0 : 1); - break; - case 'o': - SetSpecialAbility(DESTRUCTIBLE_OBJECT, remove ? 0 : 1); - SetDestructibleObject(remove ? true : false); - break; - case 'Z': - SetSpecialAbility(NO_HARM_FROM_CLIENT, remove ? 0 : 1); - break; - case 'i': - SetSpecialAbility(IMMUNE_TAUNT, remove ? 0 : 1); - break; - case 'e': - SetSpecialAbility(ALWAYS_FLEE, remove ? 0 : 1); - break; - case 'h': - SetSpecialAbility(FLEE_PERCENT, remove ? 0 : 1); - break; - - default: - break; - } - parse++; - } - - if(permtag == 1 && this->GetNPCTypeID() > 0) - { - if(database.SetSpecialAttkFlag(this->GetNPCTypeID(), orig_parse)) - { - LogFile->write(EQEMuLog::Normal, "NPCTypeID: %i flagged to '%s' for Special Attacks.\n",this->GetNPCTypeID(),orig_parse); - } - } -} - -bool Mob::HasNPCSpecialAtk(const char* parse) { - - bool HasAllAttacks = true; - - while (*parse && HasAllAttacks == true) - { - switch(*parse) - { - case 'E': - if (!GetSpecialAbility(SPECATK_ENRAGE)) - HasAllAttacks = false; - break; - case 'F': - if (!GetSpecialAbility(SPECATK_FLURRY)) - HasAllAttacks = false; - break; - case 'R': - if (!GetSpecialAbility(SPECATK_RAMPAGE)) - HasAllAttacks = false; - break; - case 'r': - if (!GetSpecialAbility(SPECATK_AREA_RAMPAGE)) - HasAllAttacks = false; - break; - case 'S': - if (!GetSpecialAbility(SPECATK_SUMMON)) - HasAllAttacks = false; - break; - case 'T': - if (!GetSpecialAbility(SPECATK_TRIPLE)) - HasAllAttacks = false; - break; - case 'Q': - if (!GetSpecialAbility(SPECATK_QUAD)) - HasAllAttacks = false; - break; - case 'b': - if (!GetSpecialAbility(SPECATK_BANE)) - HasAllAttacks = false; - break; - case 'm': - if (!GetSpecialAbility(SPECATK_MAGICAL)) - HasAllAttacks = false; - break; - case 'U': - if (!GetSpecialAbility(UNSLOWABLE)) - HasAllAttacks = false; - break; - case 'M': - if (!GetSpecialAbility(UNMEZABLE)) - HasAllAttacks = false; - break; - case 'C': - if (!GetSpecialAbility(UNCHARMABLE)) - HasAllAttacks = false; - break; - case 'N': - if (!GetSpecialAbility(UNSTUNABLE)) - HasAllAttacks = false; - break; - case 'I': - if (!GetSpecialAbility(UNSNAREABLE)) - HasAllAttacks = false; - break; - case 'D': - if (!GetSpecialAbility(UNFEARABLE)) - HasAllAttacks = false; - break; - case 'A': - if (!GetSpecialAbility(IMMUNE_MELEE)) - HasAllAttacks = false; - break; - case 'B': - if (!GetSpecialAbility(IMMUNE_MAGIC)) - HasAllAttacks = false; - break; - case 'f': - if (!GetSpecialAbility(IMMUNE_FLEEING)) - HasAllAttacks = false; - break; - case 'O': - if (!GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) - HasAllAttacks = false; - break; - case 'W': - if (!GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)) - HasAllAttacks = false; - break; - case 'H': - if (!GetSpecialAbility(IMMUNE_AGGRO)) - HasAllAttacks = false; - break; - case 'G': - if (!GetSpecialAbility(IMMUNE_AGGRO_ON)) - HasAllAttacks = false; - break; - case 'g': - if (!GetSpecialAbility(IMMUNE_CASTING_FROM_RANGE)) - HasAllAttacks = false; - break; - case 'd': - if (!GetSpecialAbility(IMMUNE_FEIGN_DEATH)) - HasAllAttacks = false; - break; - case 'Y': - if (!GetSpecialAbility(SPECATK_RANGED_ATK)) - HasAllAttacks = false; - break; - case 'L': - if (!GetSpecialAbility(SPECATK_INNATE_DW)) - HasAllAttacks = false; - break; - case 't': - if (!GetSpecialAbility(NPC_TUNNELVISION)) - HasAllAttacks = false; - break; - case 'n': - if (!GetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS)) - HasAllAttacks = false; - break; - case 'p': - if(!GetSpecialAbility(IMMUNE_PACIFY)) - HasAllAttacks = false; - break; - case 'J': - if(!GetSpecialAbility(LEASH)) - HasAllAttacks = false; - break; - case 'j': - if(!GetSpecialAbility(TETHER)) - HasAllAttacks = false; - break; - case 'o': - if(!GetSpecialAbility(DESTRUCTIBLE_OBJECT)) - { - HasAllAttacks = false; - SetDestructibleObject(false); - } - break; - case 'Z': - if(!GetSpecialAbility(NO_HARM_FROM_CLIENT)){ - HasAllAttacks = false; - } - break; - case 'e': - if(!GetSpecialAbility(ALWAYS_FLEE)) - HasAllAttacks = false; - break; - case 'h': - if(!GetSpecialAbility(FLEE_PERCENT)) - HasAllAttacks = false; - break; - default: - HasAllAttacks = false; - break; - } - parse++; - } - - return HasAllAttacks; -} - -void NPC::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) -{ - Mob::FillSpawnStruct(ns, ForWho); - - //Basic settings to make sure swarm pets work properly. - if (GetSwarmOwner()) { - Client *c = entity_list.GetClientByID(GetSwarmOwner()); - if(c) { - SetAllowBeneficial(1); //Allow client cast swarm pets to be heal/buffed. - //This is a hack to allow CLIENT swarm pets NOT to be targeted with F8. Warning: Will turn name 'Yellow'! - if (RuleB(Pets, SwarmPetNotTargetableWithHotKey)) - ns->spawn.IsMercenary = 1; - } - //NPC cast swarm pets should still be targetable with F8. - else - ns->spawn.IsMercenary = 0; - } - - //Not recommended if using above (However, this will work better on older clients). - if (RuleB(Pets, UnTargetableSwarmPet)) { - if(GetOwnerID() || GetSwarmOwner()) { - ns->spawn.is_pet = 1; - if (!IsCharmed() && GetOwnerID()) { - Client *c = entity_list.GetClientByID(GetOwnerID()); - if(c) - sprintf(ns->spawn.lastName, "%s's Pet", c->GetName()); - } - else if (GetSwarmOwner()) { - ns->spawn.bodytype = 11; - if(!IsCharmed()) - { - Client *c = entity_list.GetClientByID(GetSwarmOwner()); - if(c) - sprintf(ns->spawn.lastName, "%s's Pet", c->GetName()); - } - } - } - } else { - if(GetOwnerID()) { - ns->spawn.is_pet = 1; - if (!IsCharmed() && GetOwnerID()) { - Client *c = entity_list.GetClientByID(GetOwnerID()); - if(c) - sprintf(ns->spawn.lastName, "%s's Pet", c->GetName()); - } - } else - ns->spawn.is_pet = 0; - } - - ns->spawn.is_npc = 1; -} - -void NPC::SetLevel(uint8 in_level, bool command) -{ - if(in_level > level) - SendLevelAppearance(); - level = in_level; - SendAppearancePacket(AT_WhoLevel, in_level); -} - -void NPC::ModifyNPCStat(const char *identifier, const char *newValue) -{ - std::string id = identifier; - std::string val = newValue; - for(int i = 0; i < id.length(); ++i) - { - id[i] = std::tolower(id[i]); - } - - if(id == "ac") - { - AC = atoi(val.c_str()); - return; - } - - if(id == "str") - { - STR = atoi(val.c_str()); - return; - } - - if(id == "sta") - { - STA = atoi(val.c_str()); - return; - } - - if(id == "agi") - { - AGI = atoi(val.c_str()); - return; - } - - if(id == "dex") - { - DEX = atoi(val.c_str()); - return; - } - - if(id == "wis") - { - WIS = atoi(val.c_str()); - CalcMaxMana(); - return; - } - - if(id == "int" || id == "_int") - { - INT = atoi(val.c_str()); - CalcMaxMana(); - return; - } - - if(id == "cha") - { - CHA = atoi(val.c_str()); - return; - } - - if(id == "max_hp") - { - base_hp = atoi(val.c_str()); - CalcMaxHP(); - if(cur_hp > max_hp) - cur_hp = max_hp; - return; - } - - if(id == "max_mana") - { - npc_mana = atoi(val.c_str()); - CalcMaxMana(); - if(cur_mana > max_mana) - cur_mana = max_mana; - return; - } - - if(id == "mr") - { - MR = atoi(val.c_str()); - return; - } - - if(id == "fr") - { - FR = atoi(val.c_str()); - return; - } - - if(id == "cr") - { - CR = atoi(val.c_str()); - return; - } - - if(id == "pr") - { - PR = atoi(val.c_str()); - return; - } - - if(id == "dr") - { - DR = atoi(val.c_str()); - return; - } - - if(id == "PhR") - { - PhR = atoi(val.c_str()); - return; - } - - if(id == "runspeed") - { - runspeed = (float)atof(val.c_str()); - CalcBonuses(); - return; - } - - if(id == "special_attacks") - { - //Added reset flag. - NPCSpecialAttacks(val.c_str(), 0, 1); - return; - } - - if(id == "attack_speed") - { - attack_speed = (float)atof(val.c_str()); - CalcBonuses(); - return; - } - - if(id == "atk") - { - ATK = atoi(val.c_str()); - return; - } - - if(id == "accuracy") - { - accuracy_rating = atoi(val.c_str()); - return; - } - - if(id == "trackable") - { - trackable = atoi(val.c_str()); - return; - } - - if(id == "min_hit") - { - min_dmg = atoi(val.c_str()); - return; - } - - if(id == "max_hit") - { - max_dmg = atoi(val.c_str()); - return; - } - - if(id == "attack_count") - { - attack_count = atoi(val.c_str()); - return; - } - - if(id == "see_invis") - { - see_invis = atoi(val.c_str()); - return; - } - - if(id == "see_invis_undead") - { - see_invis_undead = atoi(val.c_str()); - return; - } - - if(id == "see_hide") - { - see_hide = atoi(val.c_str()); - return; - } - - if(id == "see_improved_hide") - { - see_improved_hide = atoi(val.c_str()); - return; - } - - if(id == "hp_regen") - { - hp_regen = atoi(val.c_str()); - return; - } - - if(id == "mana_regen") - { - mana_regen = atoi(val.c_str()); - return; - } - - if(id == "level") - { - SetLevel(atoi(val.c_str())); - return; - } - - if(id == "aggro") - { - pAggroRange = atof(val.c_str()); - return; - } - - if(id == "assist") - { - pAssistRange = atof(val.c_str()); - return; - } - - if(id == "slow_mitigation") - { - slow_mitigation = atoi(val.c_str()); - return; - } - if(id == "loottable_id") - { - loottable_id = atof(val.c_str()); - return; - } - if(id == "healscale") - { - healscale = atof(val.c_str()); - return; - } - if(id == "spellscale") - { - spellscale = atof(val.c_str()); - return; - } -} - -void NPC::LevelScale() { - - uint8 random_level = (MakeRandomInt(level, maxlevel)); - - float scaling = (((random_level / (float)level) - 1) * (scalerate / 100.0f)); - - // Compensate for scale rates at low levels so they don't add too much - uint8 scale_adjust = 1; - if(level > 0 && level <= 5) - scale_adjust = 10; - if(level > 5 && level <= 10) - scale_adjust = 5; - if(level > 10 && level <= 15) - scale_adjust = 3; - if(level > 15 && level <= 25) - scale_adjust = 2; - - base_hp += (int)(base_hp * scaling); - max_hp += (int)(max_hp * scaling); - cur_hp = max_hp; - STR += (int)(STR * scaling / scale_adjust); - STA += (int)(STA * scaling / scale_adjust); - AGI += (int)(AGI * scaling / scale_adjust); - DEX += (int)(DEX * scaling / scale_adjust); - INT += (int)(INT * scaling / scale_adjust); - WIS += (int)(WIS * scaling / scale_adjust); - CHA += (int)(CHA * scaling / scale_adjust); - if (MR) - MR += (int)(MR * scaling / scale_adjust); - if (CR) - CR += (int)(CR * scaling / scale_adjust); - if (DR) - DR += (int)(DR * scaling / scale_adjust); - if (FR) - FR += (int)(FR * scaling / scale_adjust); - if (PR) - PR += (int)(PR * scaling / scale_adjust); - - if (max_dmg) - { - max_dmg += (int)(max_dmg * scaling / scale_adjust); - min_dmg += (int)(min_dmg * scaling / scale_adjust); - } - - level = random_level; - - return; -} - -void NPC::CalcNPCResists() { - - if (!MR) - MR = (GetLevel() * 11)/10; - if (!CR) - CR = (GetLevel() * 11)/10; - if (!DR) - DR = (GetLevel() * 11)/10; - if (!FR) - FR = (GetLevel() * 11)/10; - if (!PR) - PR = (GetLevel() * 11)/10; - if (!Corrup) - Corrup = 15; - if (!PhR) - PhR = 10; - return; -} - -void NPC::CalcNPCRegen() { - - // Fix for lazy db-updaters (regen values left at 0) - if (GetCasterClass() != 'N' && mana_regen == 0) - mana_regen = (GetLevel() / 10) + 4; - else if(mana_regen < 0) - mana_regen = 0; - else - mana_regen = mana_regen; - - // Gives low end monsters no regen if set to 0 in database. Should make low end monsters killable - // Might want to lower this to /5 rather than 10. - if(hp_regen == 0) - { - if(GetLevel() <= 6) - hp_regen = 1; - else if(GetLevel() > 6 && GetLevel() <= 10) - hp_regen = 2; - else if(GetLevel() > 10 && GetLevel() <= 15) - hp_regen = 3; - else if(GetLevel() > 15 && GetLevel() <= 20) - hp_regen = 5; - else if(GetLevel() > 20 && GetLevel() <= 30) - hp_regen = 7; - else if(GetLevel() > 30 && GetLevel() <= 35) - hp_regen = 9; - else if(GetLevel() > 35 && GetLevel() <= 40) - hp_regen = 12; - else if(GetLevel() > 40 && GetLevel() <= 45) - hp_regen = 18; - else if(GetLevel() > 45 && GetLevel() <= 50) - hp_regen = 21; - else - hp_regen = 30; - } else if(hp_regen < 0) { - hp_regen = 0; - } else - hp_regen = hp_regen; - - return; -} - -void NPC::CalcNPCDamage() { - - int AC_adjust=12; - - if (GetLevel() >= 66) { - if (min_dmg==0) - min_dmg = 220; - if (max_dmg==0) - max_dmg = ((((99000)*(GetLevel()-64))/400)*AC_adjust/10); - } - else if (GetLevel() >= 60 && GetLevel() <= 65){ - if(min_dmg==0) - min_dmg = (GetLevel()+(GetLevel()/3)); - if(max_dmg==0) - max_dmg = (GetLevel()*3)*AC_adjust/10; - } - else if (GetLevel() >= 51 && GetLevel() <= 59){ - if(min_dmg==0) - min_dmg = (GetLevel()+(GetLevel()/3)); - if(max_dmg==0) - max_dmg = (GetLevel()*3)*AC_adjust/10; - } - else if (GetLevel() >= 40 && GetLevel() <= 50) { - if (min_dmg==0) - min_dmg = GetLevel(); - if(max_dmg==0) - max_dmg = (GetLevel()*3)*AC_adjust/10; - } - else if (GetLevel() >= 28 && GetLevel() <= 39) { - if (min_dmg==0) - min_dmg = GetLevel() / 2; - if (max_dmg==0) - max_dmg = ((GetLevel()*2)+2)*AC_adjust/10; - } - else if (GetLevel() <= 27) { - if (min_dmg==0) - min_dmg=1; - if (max_dmg==0) - max_dmg = (GetLevel()*2)*AC_adjust/10; - } - - int clfact = GetClassLevelFactor(); - min_dmg = (min_dmg * clfact) / 220; - max_dmg = (max_dmg * clfact) / 220; - - return; -} - - -uint32 NPC::GetSpawnPointID() const -{ - if(respawn2) - { - return respawn2->GetID(); - } - return 0; -} - -void NPC::NPCSlotTexture(uint8 slot, uint16 texture) -{ - if (slot == 7) { - d_meele_texture1 = texture; - } - else if (slot == 8) { - d_meele_texture2 = texture; - } - else if (slot < 6) { - // Reserved for texturing individual armor slots - } - return; -} - -uint32 NPC::GetSwarmOwner() -{ - if(GetSwarmInfo() != nullptr) - { - return GetSwarmInfo()->owner_id; - } - return 0; -} - -uint32 NPC::GetSwarmTarget() -{ - if(GetSwarmInfo() != nullptr) - { - return GetSwarmInfo()->target; - } - return 0; -} - -void NPC::SetSwarmTarget(int target_id) -{ - if(GetSwarmInfo() != nullptr) - { - GetSwarmInfo()->target = target_id; - } - return; -} - -int32 NPC::CalcMaxMana() { - if(npc_mana == 0) { - switch (GetCasterClass()) { - case 'I': - max_mana = (((GetINT()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana; - break; - case 'W': - max_mana = (((GetWIS()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana; - break; - case 'N': - default: - max_mana = 0; - break; - } - if (max_mana < 0) { - max_mana = 0; - } - - return max_mana; - } else { - switch (GetCasterClass()) { - case 'I': - max_mana = npc_mana + spellbonuses.Mana + itembonuses.Mana; - break; - case 'W': - max_mana = npc_mana + spellbonuses.Mana + itembonuses.Mana; - break; - case 'N': - default: - max_mana = 0; - break; - } - if (max_mana < 0) { - max_mana = 0; - } - - return max_mana; - } -} - -void NPC::SignalNPC(int _signal_id) -{ - signal_q.push_back(_signal_id); -} - -NPC_Emote_Struct* NPC::GetNPCEmote(uint16 emoteid, uint8 event_) { - LinkedListIterator iterator(zone->NPCEmoteList); - iterator.Reset(); - while(iterator.MoreElements()) - { - NPC_Emote_Struct* nes = iterator.GetData(); - if (emoteid == nes->emoteid && event_ == nes->event_) { - return (nes); - } - iterator.Advance(); - } - return (nullptr); -} - -void NPC::DoNPCEmote(uint8 event_, uint16 emoteid) -{ - if(this == nullptr || emoteid == 0) - { - return; - } - - NPC_Emote_Struct* nes = GetNPCEmote(emoteid,event_); - if(nes == nullptr) - { - return; - } - - if(emoteid == nes->emoteid) - { - if(nes->type == 1) - this->Emote("%s",nes->text); - else if(nes->type == 2) - this->Shout("%s",nes->text); - else if(nes->type == 3) - entity_list.MessageClose_StringID(this, true, 200, 10, GENERIC_STRING, nes->text); - else - this->Say("%s",nes->text); - } -} - -bool NPC::CanTalk() -{ - //Races that should be able to talk. (Races up to Titanium) - - uint16 TalkRace[473] = - {1,2,3,4,5,6,7,8,9,10,11,12,0,0,15,16,0,18,19,20,0,0,23,0,25,0,0,0,0,0,0, - 32,0,0,0,0,0,0,39,40,0,0,0,44,0,0,0,0,49,0,51,0,53,54,55,56,57,58,0,0,0, - 62,0,64,65,66,67,0,0,70,71,0,0,0,0,0,77,78,79,0,81,82,0,0,0,86,0,0,0,90, - 0,92,93,94,95,0,0,98,99,0,101,0,103,0,0,0,0,0,0,110,111,112,0,0,0,0,0,0, - 0,0,0,0,123,0,0,126,0,128,0,130,131,0,0,0,0,136,137,0,139,140,0,0,0,144, - 0,0,0,0,0,150,151,152,153,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,183,184,0,0,187,188,189,0,0,0,0,0,195,196,0,198,0,0,0,202,0, - 0,205,0,0,208,0,0,0,0,0,0,0,0,217,0,219,0,0,0,0,0,0,226,0,0,229,230,0,0, - 0,0,235,236,0,238,239,240,241,242,243,244,0,246,247,0,0,0,251,0,0,254,255, - 256,257,0,0,0,0,0,0,0,0,266,267,0,0,270,271,0,0,0,0,0,277,278,0,0,0,0,283, - 284,0,286,0,288,289,290,0,0,0,0,295,296,297,298,299,300,0,0,0,304,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,320,0,322,323,324,325,0,0,0,0,330,331,332,333,334,335, - 336,337,338,339,340,341,342,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,359,360,361,362, - 0,364,365,366,0,368,369,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,385,386,0,0,0,0,0,392, - 393,394,395,396,397,398,0,400,402,0,0,0,0,406,0,408,0,0,411,0,413,0,0,0,417, - 0,0,420,0,0,0,0,425,0,0,0,0,0,0,0,433,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,458,0,0,0,0,0,0,0,0,467,0,0,470,0,0,473}; - - int talk_check = TalkRace[GetRace() - 1]; - - if (TalkRace[GetRace() - 1] > 0) - return true; - - return false; -} - -//this is called with 'this' as the mob being looked at, and -//iOther the mob who is doing the looking. It should figure out -//what iOther thinks about 'this' -FACTION_VALUE NPC::GetReverseFactionCon(Mob* iOther) { - iOther = iOther->GetOwnerOrSelf(); - int primaryFaction= iOther->GetPrimaryFaction(); - - //I am pretty sure that this special faction call is backwards - //and should be iOther->GetSpecialFactionCon(this) - if (primaryFaction < 0) - return GetSpecialFactionCon(iOther); - - if (primaryFaction == 0) - return FACTION_INDIFFERENT; - - //if we are a pet, use our owner's faction stuff - Mob *own = GetOwner(); - if (own != nullptr) - return own->GetReverseFactionCon(iOther); - - //make sure iOther is an npc - //also, if we dont have a faction, then they arnt gunna think anything of us either - if(!iOther->IsNPC() || GetPrimaryFaction() == 0) - return(FACTION_INDIFFERENT); - - //if we get here, iOther is an NPC too - - //otherwise, employ the npc faction stuff - //so we need to look at iOther's faction table to see - //what iOther thinks about our primary faction - return(iOther->CastToNPC()->CheckNPCFactionAlly(GetPrimaryFaction())); -} - -//Look through our faction list and return a faction con based -//on the npc_value for the other person's primary faction in our list. -FACTION_VALUE NPC::CheckNPCFactionAlly(int32 other_faction) { - std::list::iterator cur,end; - cur = faction_list.begin(); - end = faction_list.end(); - for(; cur != end; ++cur) { - struct NPCFaction* fac = *cur; - if ((int32)fac->factionID == other_faction) { - if (fac->npc_value > 0) - return FACTION_ALLY; - else if (fac->npc_value < 0) - return FACTION_SCOWLS; - else - return FACTION_INDIFFERENT; - } - } - return FACTION_INDIFFERENT; -} - -bool NPC::IsFactionListAlly(uint32 other_faction) { - return(CheckNPCFactionAlly(other_faction) == FACTION_ALLY); -} - -int NPC::GetScore() -{ - int lv = std::min(70, (int)GetLevel()); - int basedmg = (lv*2)*(1+(lv / 100)) - (lv / 2); - int minx = 0; - int basehp = 0; - int hpcontrib = 0; - int dmgcontrib = 0; - int spccontrib = 0; - int hp = GetMaxHP(); - int mindmg = min_dmg; - int maxdmg = max_dmg; - int final; - - if(lv < 46) - { - minx = static_cast (ceil( ((lv - (lv / 10.0)) - 1.0) )); - basehp = (lv * 10) + (lv * lv); - } - else - { - minx = static_cast (ceil( ((lv - (lv / 10.0)) - 1.0) - (( lv - 45.0 ) / 2.0) )); - basehp = (lv * 10) + ((lv * lv) * 4); - } - - if(hp > basehp) - { - hpcontrib = static_cast (((hp / static_cast (basehp)) * 1.5)); - if(hpcontrib > 5) { hpcontrib = 5; } - - if(maxdmg > basedmg) - { - dmgcontrib = static_cast (ceil( ((maxdmg / basedmg) * 1.5) )); - } - - if(HasNPCSpecialAtk("E")) { spccontrib++; } //Enrage - if(HasNPCSpecialAtk("F")) { spccontrib++; } //Flurry - if(HasNPCSpecialAtk("R")) { spccontrib++; } //Rampage - if(HasNPCSpecialAtk("r")) { spccontrib++; } //Area Rampage - if(HasNPCSpecialAtk("S")) { spccontrib++; } //Summon - if(HasNPCSpecialAtk("T")) { spccontrib += 2; } //Triple - if(HasNPCSpecialAtk("Q")) { spccontrib += 3; } //Quad - if(HasNPCSpecialAtk("U")) { spccontrib += 5; } //Unslowable - if(HasNPCSpecialAtk("L")) { spccontrib++; } //Innate Dual Wield - } - - if(npc_spells_id > 12) - { - if(lv < 16) - spccontrib++; - else - spccontrib += static_cast (floor(lv/15.0)); - } - - final = minx + hpcontrib + dmgcontrib + spccontrib; - final = std::max(1, final); - final = std::min(100, final); - return(final); -} - -uint32 NPC::GetSpawnKillCount() -{ - uint32 sid = GetSpawnPointID(); - - if(sid > 0) - { - return(zone->GetSpawnKillCount(sid)); - } - - return(0); -} - -void NPC::DoQuestPause(Mob *other) { - if(IsMoving() && !IsOnHatelist(other)) { - PauseWandering(RuleI(NPC, SayPauseTimeInSec)); - FaceTarget(other); - } else if(!IsMoving()) { - FaceTarget(other); - } - -} diff --git a/zone/perl_npcX.cpp b/zone/perl_npcX.cpp deleted file mode 100644 index 957baf7ab..000000000 --- a/zone/perl_npcX.cpp +++ /dev/null @@ -1,2487 +0,0 @@ -/* -* This file was generated automatically by xsubpp version 1.9508 from the -* contents of tmp. Do not edit this file, edit tmp instead. -* -* ANY CHANGES MADE HERE WILL BE LOST! -* -*/ - - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "../common/features.h" -#ifdef EMBPERL_XS_CLASSES -#include "../common/debug.h" -#include "embperl.h" - -#ifdef seed -#undef seed -#endif - -typedef const char Const_char; - -#include "npc.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -XS(XS_NPC_SignalNPC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SignalNPC) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SignalNPC(THIS, _signal_id)"); - { - NPC * THIS; - int _signal_id = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SignalNPC(_signal_id); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_CheckNPCFactionAlly); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_CheckNPCFactionAlly) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::CheckNPCFactionAlly(THIS, other_faction)"); - { - NPC * THIS; - FACTION_VALUE RETVAL; - dXSTARG; - int32 other_faction = (int32)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->CheckNPCFactionAlly(other_faction); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_AddItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddItem) -{ - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: NPC::AddItem(THIS, itemid, charges = 0, equipitem = true)"); - { - NPC * THIS; - uint32 itemid = (uint32)SvUV(ST(1)); - uint16 charges = 0; - bool equipitem = true; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items > 2) - charges = (uint16)SvUV(ST(2)); - if (items > 3) - equipitem = (bool)SvTRUE(ST(3)); - - THIS->AddItem(itemid, charges, equipitem); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AddLootTable); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddLootTable) -{ - dXSARGS; - if (items < 1) - Perl_croak(aTHX_ "Usage: NPC::AddLootTable(THIS, [loottable_id])"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - uint32 loottable_id = 0; - - if(items > 1) - { - loottable_id = (uint32)SvUV(ST(1)); - THIS->AddLootTable(loottable_id); - } - else - { - THIS->AddLootTable(); - } - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_RemoveItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RemoveItem) -{ - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: NPC::RemoveItem(THIS, item_id, quantity= 0, slot= 0)"); - { - NPC * THIS; - uint32 item_id = (uint32)SvUV(ST(1)); - uint16 quantity; - uint16 slot; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items < 3) - quantity = 0; - else { - quantity = (uint16)SvUV(ST(2)); - } - - if (items < 4) - slot = 0; - else { - slot = (uint16)SvUV(ST(3)); - } - - THIS->RemoveItem(item_id, quantity, slot); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_ClearItemList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ClearItemList) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::ClearItemList(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->ClearItemList(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AddCash); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddCash) -{ - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: NPC::AddCash(THIS, in_copper, in_silver, in_gold, in_platinum)"); - { - NPC * THIS; - uint16 in_copper = (uint16)SvUV(ST(1)); - uint16 in_silver = (uint16)SvUV(ST(2)); - uint16 in_gold = (uint16)SvUV(ST(3)); - uint16 in_platinum = (uint16)SvUV(ST(4)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->AddCash(in_copper, in_silver, in_gold, in_platinum); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_RemoveCash); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RemoveCash) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::RemoveCash(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->RemoveCash(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_CountLoot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_CountLoot) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::CountLoot(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->CountLoot(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetLoottableID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetLoottableID) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetLoottableID(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetLoottableID(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetCopper); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetCopper) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetCopper(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetCopper(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSilver); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSilver) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSilver(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSilver(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetGold); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGold) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGold(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetGold(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetPlatinum); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPlatinum) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPlatinum(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetPlatinum(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetCopper); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetCopper) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetCopper(THIS, amt)"); - { - NPC * THIS; - uint32 amt = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetCopper(amt); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetSilver); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSilver) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSilver(THIS, amt)"); - { - NPC * THIS; - uint32 amt = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSilver(amt); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetGold); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetGold) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetGold(THIS, amt)"); - { - NPC * THIS; - uint32 amt = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetGold(amt); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetPlatinum); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetPlatinum) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetPlatinum(THIS, amt)"); - { - NPC * THIS; - uint32 amt = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetPlatinum(amt); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetGrid); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetGrid) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetGrid(THIS, grid_)"); - { - NPC * THIS; - int32 grid_ = (int32)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetGrid(grid_); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetSaveWaypoint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSaveWaypoint) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSaveWaypoint(THIS, waypoint)"); - { - NPC * THIS; - uint16 waypoint = (uint16)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSaveWaypoint(waypoint); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetSp2); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSp2) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSp2(THIS, sg2)"); - { - NPC * THIS; - uint32 sg2 = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSp2(sg2); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetWaypointMax); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetWaypointMax) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetWaypointMax(THIS)"); - { - NPC * THIS; - uint16 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetWaypointMax(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetGrid); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGrid) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGrid(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetGrid(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSp2); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSp2) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSp2(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSp2(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetNPCFactionID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetNPCFactionID) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetNPCFactionID(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetNPCFactionID(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetPrimaryFaction); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPrimaryFaction) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPrimaryFaction(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetPrimaryFaction(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetNPCHate); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetNPCHate) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::GetNPCHate(THIS, in_ent)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - Mob* in_ent; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - in_ent = INT2PTR(Mob *,tmp); - } - else - Perl_croak(aTHX_ "in_ent is not of type Mob"); - if(in_ent == nullptr) - Perl_croak(aTHX_ "in_ent is nullptr, avoiding crash."); - - RETVAL = THIS->GetNPCHate(in_ent); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_IsOnHatelist); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_IsOnHatelist) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::IsOnHatelist(THIS, p)"); - { - NPC * THIS; - bool RETVAL; - Mob* p; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - p = INT2PTR(Mob *,tmp); - } - else - Perl_croak(aTHX_ "p is not of type Mob"); - if(p == nullptr) - Perl_croak(aTHX_ "p is nullptr, avoiding crash."); - - RETVAL = THIS->IsOnHatelist(p); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_NPC_SetNPCFactionID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetNPCFactionID) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetNPCFactionID(THIS, in)"); - { - NPC * THIS; - int32 in = (int32)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetNPCFactionID(in); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetMaxDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMaxDMG) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetMaxDMG(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetMaxDMG(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetMinDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMinDMG) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetMinDMG(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetMinDMG(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - - -XS(XS_NPC_IsAnimal); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_IsAnimal) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::IsAnimal(THIS)"); - { - NPC * THIS; - bool RETVAL; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->IsAnimal(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_NPC_GetPetSpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPetSpellID) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPetSpellID(THIS)"); - { - NPC * THIS; - uint16 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetPetSpellID(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetPetSpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetPetSpellID) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetPetSpellID(THIS, amt)"); - { - NPC * THIS; - uint16 amt = (uint16)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetPetSpellID(amt); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetMaxDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMaxDamage) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::GetMaxDamage(THIS, tlevel)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - uint8 tlevel = (uint8)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetMaxDamage(tlevel); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetTaunting); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetTaunting) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetTaunting(THIS, tog)"); - { - NPC * THIS; - bool tog = (bool)SvTRUE(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetTaunting(tog); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_PickPocket); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_PickPocket) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::PickPocket(THIS, thief)"); - { - NPC * THIS; - Client* thief; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - thief = INT2PTR(Client *,tmp); - } - else - Perl_croak(aTHX_ "thief is not of type Client"); - if(thief == nullptr) - Perl_croak(aTHX_ "thief is nullptr, avoiding crash."); - - THIS->PickPocket(thief); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_StartSwarmTimer); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_StartSwarmTimer) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::StartSwarmTimer(THIS, duration)"); - { - NPC * THIS; - uint32 duration = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->StartSwarmTimer(duration); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_DoClassAttacks); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_DoClassAttacks) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::DoClassAttacks(THIS, target)"); - { - NPC * THIS; - Mob * target; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - target = INT2PTR(Mob *,tmp); - } - else - Perl_croak(aTHX_ "target is not of type Mob"); - if(target == nullptr) - Perl_croak(aTHX_ "target is nullptr, avoiding crash."); - - THIS->DoClassAttacks(target); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetMaxWp); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMaxWp) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetMaxWp(THIS)"); - { - NPC * THIS; - int RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetMaxWp(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_DisplayWaypointInfo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_DisplayWaypointInfo) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::DisplayWaypointInfo(THIS, to)"); - { - NPC * THIS; - Client * to; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - to = INT2PTR(Client *,tmp); - } - else - Perl_croak(aTHX_ "to is not of type Client"); - if(to == nullptr) - Perl_croak(aTHX_ "to is nullptr, avoiding crash."); - - THIS->DisplayWaypointInfo(to); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_CalculateNewWaypoint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_CalculateNewWaypoint) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::CalculateNewWaypoint(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->CalculateNewWaypoint(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AssignWaypoints); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AssignWaypoints) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::AssignWaypoints(THIS, grid)"); - { - NPC * THIS; - uint32 grid = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->AssignWaypoints(grid); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetWaypointPause); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetWaypointPause) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::SetWaypointPause(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetWaypointPause(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_UpdateWaypoint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_UpdateWaypoint) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::UpdateWaypoint(THIS, wp_index)"); - { - NPC * THIS; - int wp_index = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->UpdateWaypoint(wp_index); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_StopWandering); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_StopWandering) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::StopWandering(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->StopWandering(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_ResumeWandering); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ResumeWandering) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::ResumeWandering(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->ResumeWandering(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_PauseWandering); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_PauseWandering) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::PauseWandering(THIS, pausetime)"); - { - NPC * THIS; - int pausetime = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->PauseWandering(pausetime); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_MoveTo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_MoveTo) -{ - dXSARGS; - if (items != 4 && items != 5 && items != 6) - Perl_croak(aTHX_ "Usage: NPC::MoveTo(THIS, mtx, mty, mtz, [mth, saveguard?])"); - { - NPC * THIS; - float mtx = (float)SvNV(ST(1)); - float mty = (float)SvNV(ST(2)); - float mtz = (float)SvNV(ST(3)); - float mth; - bool saveguard; - - if(items > 4) - mth = (float)SvNV(ST(4)); - else - mth = 0; - - if(items > 5) - saveguard = (bool)SvTRUE(ST(5)); - else - saveguard = false; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->MoveTo(mtx, mty, mtz, mth, saveguard); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_NextGuardPosition); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_NextGuardPosition) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::NextGuardPosition(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->NextGuardPosition(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SaveGuardSpot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SaveGuardSpot) -{ - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: NPC::SaveGuardSpot(THIS, iClearGuardSpot= false)"); - { - NPC * THIS; - bool iClearGuardSpot; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items < 2) - iClearGuardSpot = false; - else { - iClearGuardSpot = (bool)SvTRUE(ST(1)); - } - - THIS->SaveGuardSpot(iClearGuardSpot); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_IsGuarding); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_IsGuarding) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::IsGuarding(THIS)"); - { - NPC * THIS; - bool RETVAL; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->IsGuarding(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_NPC_AI_SetRoambox); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AI_SetRoambox) -{ - dXSARGS; - if (items < 6 || items > 8) - Perl_croak(aTHX_ "Usage: NPC::AI_SetRoambox(THIS, iDist, iMaxX, iMinX, iMaxY, iMinY, iDelay= 2500, iMinDelay= 2500)"); - { - NPC * THIS; - float iDist = (float)SvNV(ST(1)); - float iMaxX = (float)SvNV(ST(2)); - float iMinX = (float)SvNV(ST(3)); - float iMaxY = (float)SvNV(ST(4)); - float iMinY = (float)SvNV(ST(5)); - uint32 iDelay; - uint32 iMinDelay; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items < 7){ - iMinDelay = 2500; - iDelay = 2500; - } - else if (items < 8){ - iMinDelay = 2500; - iDelay = (uint32)SvUV(ST(6)); - } - else { - iDelay = (uint32)SvUV(ST(6)); - iMinDelay = (uint32)SvUV(ST(7)); - } - - THIS->AI_SetRoambox(iDist, iMaxX, iMinX, iMaxY, iMinY, iDelay, iMinDelay); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetNPCSpellsID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetNPCSpellsID) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetNPCSpellsID(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetNPCSpellsID(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnPointID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointID) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointID(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSpawnPointID(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnPointX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointX) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointX(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetSpawnPointX(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnPointY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointY) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointY(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetSpawnPointY(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnPointZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointZ) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointZ(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetSpawnPointZ(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnPointH); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointH) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointH(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetSpawnPointH(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetGuardPointX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGuardPointX) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGuardPointX(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetGuardPointX(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetGuardPointY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGuardPointY) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGuardPointY(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetGuardPointY(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetGuardPointZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGuardPointZ) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGuardPointZ(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetGuardPointZ(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetPrimSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetPrimSkill) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetPrimSkill(THIS, skill_id)"); - { - NPC * THIS; - int skill_id = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetPrimSkill(skill_id); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetSecSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSecSkill) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSecSkill(THIS, skill_id)"); - { - NPC * THIS; - int skill_id = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSecSkill(skill_id); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetPrimSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPrimSkill) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPrimSkill(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetPrimSkill(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSecSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSecSkill) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSecSkill(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSecSkill(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSwarmOwner); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSwarmOwner) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSwarmOwner(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSwarmOwner(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSwarmTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSwarmTarget) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSwarmTarget(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSwarmTarget(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetSwarmTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSwarmTarget) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSwarmTarget(THIS, target_id)"); - { - NPC * THIS; - int target_id = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSwarmTarget(target_id); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_ModifyNPCStat); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ModifyNPCStat) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::ModifyNPCStat(THIS, identifier, newValue)"); - { - NPC * THIS; - Const_char * identifier = (Const_char *)SvPV_nolen(ST(1)); - Const_char * newValue = (Const_char *)SvPV_nolen(ST(2)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->ModifyNPCStat(identifier, newValue); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AddSpellToNPCList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddSpellToNPCList) -{ - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: NPC::AddAISpell(THIS, priority, spell_id, type, mana_cost, recast_delay, resist_adjust)"); - { - NPC * THIS; - int priority = (int)SvIV(ST(1)); - int spell_id = (int)SvIV(ST(2)); - int type = (int)SvIV(ST(3)); - int mana_cost = (int)SvIV(ST(4)); - int recast_delay = (int)SvIV(ST(5)); - int resist_adjust = (int)SvIV(ST(6)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->AddSpellToNPCList(priority, spell_id, type, mana_cost, recast_delay, resist_adjust); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_RemoveSpellFromNPCList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RemoveSpellFromNPCList) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::RemoveAISpell(THIS, spell_id)"); - { - NPC * THIS; - int spell_id = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->RemoveSpellFromNPCList(spell_id); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetSpellFocusDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSpellFocusDMG) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSpellFocusDMG(THIS, NewSpellFocusDMG)"); - { - NPC * THIS; - int32 NewSpellFocusDMG = (int32)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSpellFocusDMG(NewSpellFocusDMG); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetSpellFocusDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpellFocusDMG) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusDMG(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSpellFocusDMG(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSpellFocusHeal) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSpellFocusHeal(THIS, NewSpellFocusHeal)"); - { - NPC * THIS; - int32 NewSpellFocusHeal = (int32)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSpellFocusHeal(NewSpellFocusHeal); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpellFocusHeal) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusHeal(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSpellFocusHeal(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSlowMitigation); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSlowMitigation) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSlowMitigation(THIS)"); - { - NPC * THIS; - int16 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSlowMitigation(); - XSprePUSH; PUSHn((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetAttackSpeed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAttackSpeed) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAttackSpeed(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetAttackSpeed(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetAttackDelay); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAttackDelay) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAttackDelay(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetAttackDelay(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetAccuracyRating); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAccuracyRating) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAccuracyRating(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetAccuracyRating(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetAvoidanceRating); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAvoidanceRating) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAvoidanceyRating(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetAvoidanceRating(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnKillCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnKillCount) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnKillCount(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - RETVAL = THIS->GetSpawnKillCount(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetScore); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetScore) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetScore(THIS)"); - { - NPC * THIS; - int RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - RETVAL = THIS->GetScore(); - XSprePUSH; PUSHi((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetMerchantProbability); -XS(XS_NPC_SetMerchantProbability) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetMerchantProbability(THIS, Probability)"); - { - NPC *THIS; - uint8 Probability = (uint8)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetMerchantProbability(Probability); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetMerchantProbability); -XS(XS_NPC_GetMerchantProbability) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetMerchantProbability(THIS)"); - { - NPC *THIS; - uint8 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - RETVAL = THIS->GetMerchantProbability(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_AddMeleeProc); -XS(XS_NPC_AddMeleeProc) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::AddMeleeProc(THIS,spellid,chance)"); - { - NPC * THIS; - int spell_id = (int)SvIV(ST(1)); - int chance = (int)SvIV(ST(2)); - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - THIS->AddProcToWeapon(spell_id, true, chance); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AddRangedProc); -XS(XS_NPC_AddRangedProc) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::AddRangedProc(THIS,spellid,chance)"); - { - NPC * THIS; - int spell_id = (int)SvIV(ST(1)); - int chance = (int)SvIV(ST(2)); - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - THIS->AddDefensiveProc(spell_id,chance); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AddDefensiveProc); -XS(XS_NPC_AddDefensiveProc) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::AddDefensiveProc(THIS,spellid,chance)"); - { - NPC * THIS; - int spell_id = (int)SvIV(ST(1)); - int chance = (int)SvIV(ST(2)); - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - THIS->AddProcToWeapon(spell_id, true, chance); - } - XSRETURN_EMPTY; -} - - -#ifdef __cplusplus -extern "C" -#endif -XS(boot_NPC); /* prototype to pass -Wmissing-prototypes */ -XS(boot_NPC) -{ - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - - if(items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK ; - - newXSproto(strcpy(buf, "SignalNPC"), XS_NPC_SignalNPC, file, "$$"); - newXSproto(strcpy(buf, "CheckNPCFactionAlly"), XS_NPC_CheckNPCFactionAlly, file, "$$"); - newXSproto(strcpy(buf, "AddItem"), XS_NPC_AddItem, file, "$$;$$"); - newXSproto(strcpy(buf, "AddLootTable"), XS_NPC_AddLootTable, file, "$"); - newXSproto(strcpy(buf, "RemoveItem"), XS_NPC_RemoveItem, file, "$$;$$"); - newXSproto(strcpy(buf, "ClearItemList"), XS_NPC_ClearItemList, file, "$"); - newXSproto(strcpy(buf, "AddCash"), XS_NPC_AddCash, file, "$$$$$"); - newXSproto(strcpy(buf, "RemoveCash"), XS_NPC_RemoveCash, file, "$"); - newXSproto(strcpy(buf, "CountLoot"), XS_NPC_CountLoot, file, "$"); - newXSproto(strcpy(buf, "GetLoottableID"), XS_NPC_GetLoottableID, file, "$"); - newXSproto(strcpy(buf, "GetCopper"), XS_NPC_GetCopper, file, "$"); - newXSproto(strcpy(buf, "GetSilver"), XS_NPC_GetSilver, file, "$"); - newXSproto(strcpy(buf, "GetGold"), XS_NPC_GetGold, file, "$"); - newXSproto(strcpy(buf, "GetPlatinum"), XS_NPC_GetPlatinum, file, "$"); - newXSproto(strcpy(buf, "SetCopper"), XS_NPC_SetCopper, file, "$$"); - newXSproto(strcpy(buf, "SetSilver"), XS_NPC_SetSilver, file, "$$"); - newXSproto(strcpy(buf, "SetGold"), XS_NPC_SetGold, file, "$$"); - newXSproto(strcpy(buf, "SetPlatinum"), XS_NPC_SetPlatinum, file, "$$"); - newXSproto(strcpy(buf, "SetGrid"), XS_NPC_SetGrid, file, "$$"); - newXSproto(strcpy(buf, "SetSaveWaypoint"), XS_NPC_SetSaveWaypoint, file, "$$"); - newXSproto(strcpy(buf, "SetSp2"), XS_NPC_SetSp2, file, "$$"); - newXSproto(strcpy(buf, "GetWaypointMax"), XS_NPC_GetWaypointMax, file, "$"); - newXSproto(strcpy(buf, "GetGrid"), XS_NPC_GetGrid, file, "$"); - newXSproto(strcpy(buf, "GetSp2"), XS_NPC_GetSp2, file, "$"); - newXSproto(strcpy(buf, "GetNPCFactionID"), XS_NPC_GetNPCFactionID, file, "$"); - newXSproto(strcpy(buf, "GetPrimaryFaction"), XS_NPC_GetPrimaryFaction, file, "$"); - newXSproto(strcpy(buf, "GetNPCHate"), XS_NPC_GetNPCHate, file, "$$"); - newXSproto(strcpy(buf, "IsOnHatelist"), XS_NPC_IsOnHatelist, file, "$$"); - newXSproto(strcpy(buf, "SetNPCFactionID"), XS_NPC_SetNPCFactionID, file, "$$"); - newXSproto(strcpy(buf, "GetMaxDMG"), XS_NPC_GetMaxDMG, file, "$"); - newXSproto(strcpy(buf, "GetMinDMG"), XS_NPC_GetMinDMG, file, "$"); - newXSproto(strcpy(buf, "IsAnimal"), XS_NPC_IsAnimal, file, "$"); - newXSproto(strcpy(buf, "GetPetSpellID"), XS_NPC_GetPetSpellID, file, "$"); - newXSproto(strcpy(buf, "SetPetSpellID"), XS_NPC_SetPetSpellID, file, "$$"); - newXSproto(strcpy(buf, "GetMaxDamage"), XS_NPC_GetMaxDamage, file, "$$"); - newXSproto(strcpy(buf, "SetTaunting"), XS_NPC_SetTaunting, file, "$$"); - newXSproto(strcpy(buf, "PickPocket"), XS_NPC_PickPocket, file, "$$"); - newXSproto(strcpy(buf, "StartSwarmTimer"), XS_NPC_StartSwarmTimer, file, "$$"); - newXSproto(strcpy(buf, "DoClassAttacks"), XS_NPC_DoClassAttacks, file, "$$"); - newXSproto(strcpy(buf, "GetMaxWp"), XS_NPC_GetMaxWp, file, "$"); - newXSproto(strcpy(buf, "DisplayWaypointInfo"), XS_NPC_DisplayWaypointInfo, file, "$$"); - newXSproto(strcpy(buf, "CalculateNewWaypoint"), XS_NPC_CalculateNewWaypoint, file, "$"); - newXSproto(strcpy(buf, "AssignWaypoints"), XS_NPC_AssignWaypoints, file, "$$"); - newXSproto(strcpy(buf, "SetWaypointPause"), XS_NPC_SetWaypointPause, file, "$"); - newXSproto(strcpy(buf, "UpdateWaypoint"), XS_NPC_UpdateWaypoint, file, "$$"); - newXSproto(strcpy(buf, "StopWandering"), XS_NPC_StopWandering, file, "$"); - newXSproto(strcpy(buf, "ResumeWandering"), XS_NPC_ResumeWandering, file, "$"); - newXSproto(strcpy(buf, "PauseWandering"), XS_NPC_PauseWandering, file, "$$"); - newXSproto(strcpy(buf, "MoveTo"), XS_NPC_MoveTo, file, "$$$$"); - newXSproto(strcpy(buf, "NextGuardPosition"), XS_NPC_NextGuardPosition, file, "$"); - newXSproto(strcpy(buf, "SaveGuardSpot"), XS_NPC_SaveGuardSpot, file, "$;$"); - newXSproto(strcpy(buf, "IsGuarding"), XS_NPC_IsGuarding, file, "$"); - newXSproto(strcpy(buf, "AI_SetRoambox"), XS_NPC_AI_SetRoambox, file, "$$$$$$;$$"); - newXSproto(strcpy(buf, "GetNPCSpellsID"), XS_NPC_GetNPCSpellsID, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointID"), XS_NPC_GetSpawnPointID, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointX"), XS_NPC_GetSpawnPointX, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointY"), XS_NPC_GetSpawnPointY, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointZ"), XS_NPC_GetSpawnPointZ, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointH"), XS_NPC_GetSpawnPointH, file, "$"); - newXSproto(strcpy(buf, "GetGuardPointX"), XS_NPC_GetGuardPointX, file, "$"); - newXSproto(strcpy(buf, "GetGuardPointY"), XS_NPC_GetGuardPointY, file, "$"); - newXSproto(strcpy(buf, "GetGuardPointZ"), XS_NPC_GetGuardPointZ, file, "$"); - newXSproto(strcpy(buf, "SetPrimSkill"), XS_NPC_SetPrimSkill, file, "$$"); - newXSproto(strcpy(buf, "SetSecSkill"), XS_NPC_SetSecSkill, file, "$$"); - newXSproto(strcpy(buf, "GetPrimSkill"), XS_NPC_GetPrimSkill, file, "$"); - newXSproto(strcpy(buf, "GetSecSkill"), XS_NPC_GetSecSkill, file, "$"); - newXSproto(strcpy(buf, "GetSwarmOwner"), XS_NPC_GetSwarmOwner, file, "$"); - newXSproto(strcpy(buf, "GetSwarmTarget"), XS_NPC_GetSwarmTarget, file, "$"); - newXSproto(strcpy(buf, "SetSwarmTarget"), XS_NPC_SetSwarmTarget, file, "$$"); - newXSproto(strcpy(buf, "ModifyNPCStat"), XS_NPC_ModifyNPCStat, file, "$$$"); - newXSproto(strcpy(buf, "AddAISpell"), XS_NPC_AddSpellToNPCList, file, "$$$$$$$"); - newXSproto(strcpy(buf, "RemoveAISpell"), XS_NPC_RemoveSpellFromNPCList, file, "$$"); - newXSproto(strcpy(buf, "SetSpellFocusDMG"), XS_NPC_SetSpellFocusDMG, file, "$$"); - newXSproto(strcpy(buf, "SetSpellFocusHeal"), XS_NPC_SetSpellFocusHeal, file, "$$"); - newXSproto(strcpy(buf, "GetSpellFocusDMG"), XS_NPC_GetSpellFocusDMG, file, "$"); - newXSproto(strcpy(buf, "GetSpellFocusHeal"), XS_NPC_GetSpellFocusHeal, file, "$"); - newXSproto(strcpy(buf, "GetSlowMitigation"), XS_NPC_GetSlowMitigation, file, "$"); - newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetAttackSpeed, file, "$"); - newXSproto(strcpy(buf, "GetAttackDelay"), XS_NPC_GetAttackDelay, file, "$"); - newXSproto(strcpy(buf, "GetAccuracyRating"), XS_NPC_GetAccuracyRating, file, "$"); - newXSproto(strcpy(buf, "GetAvoidanceRating"), XS_NPC_GetAvoidanceRating, file, "$"); - newXSproto(strcpy(buf, "GetSpawnKillCount"), XS_NPC_GetSpawnKillCount, file, "$"); - newXSproto(strcpy(buf, "GetScore"), XS_NPC_GetScore, file, "$"); - newXSproto(strcpy(buf, "SetMerchantProbability"), XS_NPC_SetMerchantProbability, file, "$$"); - newXSproto(strcpy(buf, "GetMerchantProbability"), XS_NPC_GetMerchantProbability, file, "$"); - newXSproto(strcpy(buf, "AddMeleeProc"), XS_NPC_AddMeleeProc, file, "$$$"); - newXSproto(strcpy(buf, "AddRangedProc"), XS_NPC_AddRangedProc, file, "$$$"); - newXSproto(strcpy(buf, "AddDefensiveProc"), XS_NPC_AddDefensiveProc, file, "$$$"); - XSRETURN_YES; -} - -#endif //EMBPERL_XS_CLASSES - diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 5490b9c6f..ecf2bb7ba 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1270,9 +1270,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Melee Absorb Rune: %+i", effect_value); #endif - if (caster) - effect_value = caster->ApplySpellEffectiveness(spell_id, effect_value); - + effect_value = ApplySpellEffectiveness(caster, spell_id, effect_value); buffs[buffslot].melee_rune = effect_value; break; } @@ -3022,7 +3020,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, uint32 instrument_mod, Mob *caster, - int ticsremaining, uint16 caster_id) + int ticsremaining) { int formula, base, max, effect_value; @@ -3050,7 +3048,7 @@ int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, spells[spell_id].effectid[effect_id] != SE_ManaRegen_v2) { int oval = effect_value; - int mod = ApplySpellEffectiveness(spell_id, instrument_mod, true, caster_id); + int mod = ApplySpellEffectiveness(caster, spell_id, instrument_mod, true); effect_value = effect_value * mod / 10; Log.Out(Logs::Detail, Logs::Spells, "Effect value %d altered with bard modifier of %d to yeild %d", oval, mod, effect_value); @@ -6045,21 +6043,16 @@ int32 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spel return value; } -int32 Mob::ApplySpellEffectiveness(int16 spell_id, int32 value, bool IsBard, uint16 caster_id) { +int32 Mob::ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard) { // 9-17-12: This is likely causing crashes, disabled till can resolve. if (IsBard) return value; - Mob* caster = this; - - if (caster_id && caster_id != GetID())//Make sure we are checking the casters focus - caster = entity_list.GetMob(caster_id); - if (!caster) return value; - int16 focus = caster->GetFocusEffect(focusFcBaseEffects, spell_id); + int16 focus = GetFocusEffect(focusFcBaseEffects, spell_id); if (IsBard) value += focus; From d1facd9368ebeb24051376dabfefdbbbd8449c55 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 27 Mar 2016 10:57:29 -0400 Subject: [PATCH 021/693] Kayen: delete bad test files accidently merged --- common/shareddbx.cpp | 2162 -------- .../required/2014_02_12_spells_new_update.sql | 13 - ...014_04_10_No_Target_With_Hotkey - Copy.sql | 3 - .../git/required/2014_06_22_MetabolismAAs.sql | 6 - zone/AA_base.cpp | 1990 ------- zone/AA_v1.cpp | 2032 ------- zone/MobAI_M.cpp | 2760 ---------- zone/attackx.cpp | 4663 ----------------- zone/bonusesxx.cpp | 4337 --------------- zone/groupsx.cpp | 2194 -------- zone/npcx.cpp | 2492 --------- zone/perl_npcX.cpp | 2487 --------- 12 files changed, 25139 deletions(-) delete mode 100644 common/shareddbx.cpp delete mode 100644 utils/sql/git/required/2014_02_12_spells_new_update.sql delete mode 100644 utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql delete mode 100644 utils/sql/git/required/2014_06_22_MetabolismAAs.sql delete mode 100644 zone/AA_base.cpp delete mode 100644 zone/AA_v1.cpp delete mode 100644 zone/MobAI_M.cpp delete mode 100644 zone/attackx.cpp delete mode 100644 zone/bonusesxx.cpp delete mode 100644 zone/groupsx.cpp delete mode 100644 zone/npcx.cpp delete mode 100644 zone/perl_npcX.cpp diff --git a/common/shareddbx.cpp b/common/shareddbx.cpp deleted file mode 100644 index 60e29cccb..000000000 --- a/common/shareddbx.cpp +++ /dev/null @@ -1,2162 +0,0 @@ -#include -#include -#include - -#include "shareddb.h" -#include "mysql.h" -#include "Item.h" -#include "classes.h" -#include "rulesys.h" -#include "seperator.h" -#include "StringUtil.h" -#include "eq_packet_structs.h" -#include "guilds.h" -#include "extprofile.h" -#include "memory_mapped_file.h" -#include "ipc_mutex.h" -#include "eqemu_exception.h" -#include "loottable.h" -#include "faction.h" -#include "features.h" - -SharedDatabase::SharedDatabase() -: Database(), skill_caps_mmf(nullptr), items_mmf(nullptr), items_hash(nullptr), faction_mmf(nullptr), faction_hash(nullptr), - loot_table_mmf(nullptr), loot_table_hash(nullptr), loot_drop_mmf(nullptr), loot_drop_hash(nullptr), base_data_mmf(nullptr) -{ -} - -SharedDatabase::SharedDatabase(const char* host, const char* user, const char* passwd, const char* database, uint32 port) -: Database(host, user, passwd, database, port), skill_caps_mmf(nullptr), items_mmf(nullptr), items_hash(nullptr), - faction_mmf(nullptr), faction_hash(nullptr), loot_table_mmf(nullptr), loot_table_hash(nullptr), loot_drop_mmf(nullptr), - loot_drop_hash(nullptr), base_data_mmf(nullptr) -{ -} - -SharedDatabase::~SharedDatabase() { - safe_delete(skill_caps_mmf); - safe_delete(items_mmf); - safe_delete(items_hash); - safe_delete(faction_mmf); - safe_delete(faction_hash); - safe_delete(loot_table_mmf); - safe_delete(loot_drop_mmf); - safe_delete(loot_table_hash); - safe_delete(loot_drop_hash); - safe_delete(base_data_mmf); -} - -bool SharedDatabase::SetHideMe(uint32 account_id, uint8 hideme) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET hideme = %i where id = %i", hideme, account_id), errbuf)) { - std::cerr << "Error in SetGMSpeed query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - safe_delete_array(query); - return true; - -} - -uint8 SharedDatabase::GetGMSpeed(uint32 account_id) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT gmspeed FROM account where id='%i'", account_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint8 gmspeed = atoi(row[0]); - mysql_free_result(result); - return gmspeed; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else - { - - std::cerr << "Error in GetGMSpeed query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - return 0; - - -} - -bool SharedDatabase::SetGMSpeed(uint32 account_id, uint8 gmspeed) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET gmspeed = %i where id = %i", gmspeed, account_id), errbuf)) { - std::cerr << "Error in SetGMSpeed query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - safe_delete_array(query); - return true; - -} - -uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) { - - uint32 EntitledTime = 0; - - const char *EntitledQuery = "select sum(ascii(substring(profile, 237, 1)) + (ascii(substring(profile, 238, 1)) * 256) +" - "(ascii(substring(profile, 239, 1)) * 65536) + (ascii(substring(profile, 240, 1)) * 16777216))" - "from character_ where account_id = %i"; - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, EntitledQuery, AccountID), errbuf, &result)) { - - if (mysql_num_rows(result) == 1) { - - row = mysql_fetch_row(result); - - EntitledTime = atoi(row[0]); - } - - mysql_free_result(result); - } - - safe_delete_array(query); - - return EntitledTime; -} - -bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iterator &start, std::list::const_iterator &end) -{ -iter_queue it; -int i; -bool ret=true; - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - // Delete cursor items - if ((ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND ( (slotid >=8000 and slotid<=8999) or slotid=30 or (slotid>=331 and slotid<=340))", char_id), errbuf))) { - for(it=start,i=8000;it!=end;++it,i++) { - ItemInst *inst=*it; - if (!(ret=SaveInventory(char_id,inst,(i==8000) ? 30 : i))) - break; - } - } else { - std::cout << "Clearing cursor failed: " << errbuf << std::endl; - } - safe_delete_array(query); - - return ret; -} - -bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const ItemInst* inst) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - // Delete cursor items - if (!RunQuery(query, MakeAnyLenString(&query, - "SELECT itemid,charges FROM sharedbank " - "WHERE acctid=%d AND slotid=%d", - account_id, slot_id), errbuf, &result)) { - LogFile->write(EQEMuLog::Error, "Error runing inventory verification query '%s': %s", query, errbuf); - safe_delete_array(query); - //returning true is less harmful in the face of a query error - return(true); - } - safe_delete_array(query); - - row = mysql_fetch_row(result); - bool found = false; - if(row) { - uint32 id = atoi(row[0]); - uint16 charges = atoi(row[1]); - - uint16 expect_charges = 0; - if(inst->GetCharges() >= 0) - expect_charges = inst->GetCharges(); - else - expect_charges = 0x7FFF; - - if(id == inst->GetItem()->ID && charges == expect_charges) - found = true; - } - mysql_free_result(result); - return(found); -} - -bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 slot_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - bool ret = false; - uint32 augslot[5] = { 0, 0, 0, 0, 0 }; - - //never save tribute slots: - if(slot_id >= 400 && slot_id <= 404) - return(true); - - if (inst && inst->IsType(ItemClassCommon)) { - for(int i=0;i<5;i++) { - ItemInst *auginst=inst->GetItem(i); - augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; - } - } - - if (slot_id>=2500 && slot_id<=2600) { // Shared bank inventory - if (!inst) { - // Delete item - uint32 account_id = GetAccountIDByChar(char_id); - uint32 len_query = MakeAnyLenString(&query, "DELETE FROM sharedbank WHERE acctid=%i AND slotid=%i", - account_id, slot_id); - - ret = RunQuery(query, len_query, errbuf); - - // Delete bag slots, if need be - if (ret && Inventory::SupportsContainers(slot_id)) { - safe_delete_array(query); - int16 base_slot_id = Inventory::CalcSlotId(slot_id, 0); - ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM sharedbank WHERE acctid=%i AND slotid>=%i AND slotid<%i", - account_id, base_slot_id, (base_slot_id+10)), errbuf); - } - - // @merth: need to delete augments here - } - else { - // Update/Insert item - uint32 account_id = GetAccountIDByChar(char_id); - uint16 charges = 0; - if(inst->GetCharges() >= 0) - charges = inst->GetCharges(); - else - charges = 0x7FFF; - - uint32 len_query = MakeAnyLenString(&query, - "REPLACE INTO sharedbank " - " (acctid,slotid,itemid,charges,custom_data," - " augslot1,augslot2,augslot3,augslot4,augslot5)" - " VALUES(%lu,%lu,%lu,%lu,'%s'," - " %lu,%lu,%lu,%lu,%lu)", - (unsigned long)account_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, (unsigned long)charges, - inst->GetCustomDataString().c_str(), - (unsigned long)augslot[0],(unsigned long)augslot[1],(unsigned long)augslot[2],(unsigned long)augslot[3],(unsigned long)augslot[4]); - - - ret = RunQuery(query, len_query, errbuf); - } - } - else { // All other inventory - if (!inst) { - // Delete item - ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND slotid=%i", - char_id, slot_id), errbuf); - - // Delete bag slots, if need be - if (ret && Inventory::SupportsContainers(slot_id)) { - safe_delete_array(query); - int16 base_slot_id = Inventory::CalcSlotId(slot_id, 0); - ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND slotid>=%i AND slotid<%i", - char_id, base_slot_id, (base_slot_id+10)), errbuf); - } - - // @merth: need to delete augments here - } - else { - uint16 charges = 0; - if(inst->GetCharges() >= 0) - charges = inst->GetCharges(); - else - charges = 0x7FFF; - // Update/Insert item - uint32 len_query = MakeAnyLenString(&query, - "REPLACE INTO inventory " - " (charid,slotid,itemid,charges,instnodrop,custom_data,color," - " augslot1,augslot2,augslot3,augslot4,augslot5)" - " VALUES(%lu,%lu,%lu,%lu,%lu,'%s',%lu," - " %lu,%lu,%lu,%lu,%lu)", - (unsigned long)char_id, (unsigned long)slot_id, (unsigned long)inst->GetItem()->ID, (unsigned long)charges, - (unsigned long)(inst->IsInstNoDrop() ? 1:0),inst->GetCustomDataString().c_str(),(unsigned long)inst->GetColor(), - (unsigned long)augslot[0],(unsigned long)augslot[1],(unsigned long)augslot[2],(unsigned long)augslot[3],(unsigned long)augslot[4] ); - - ret = RunQuery(query, len_query, errbuf); - } - } - - if (!ret) - LogFile->write(EQEMuLog::Error, "SaveInventory query '%s': %s", query, errbuf); - safe_delete_array(query); - - // Save bag contents, if slot supports bag contents - if (inst && inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) { - for (uint8 idx=0; idx<10; idx++) { - const ItemInst* baginst = inst->GetItem(idx); - SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); - } - } - - // @merth: need to save augments here - - return ret; -} - -int32 SharedDatabase::GetSharedPlatinum(uint32 account_id) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT sharedplat FROM account WHERE id='%i'", account_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) - { - row = mysql_fetch_row(result); - uint32 shared_platinum = atoi(row[0]); - mysql_free_result(result); - return shared_platinum; - } - else - { - mysql_free_result(result); - return 0; - } - mysql_free_result(result); - } - else - { - std::cerr << "Error in GetSharedPlatinum query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - return 0; -} - -bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE account SET sharedplat = sharedplat + %i WHERE id = %i", amount_to_add, account_id), errbuf)) { - std::cerr << "Error in SetSharedPlatinum query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - safe_delete_array(query); - return true; -} - -bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - const Item_Struct* myitem; - - RunQuery - ( - query, - MakeAnyLenString - ( - &query, - "SELECT itemid, item_charges, slot FROM starting_items " - "WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND " - "(deityid = %i or deityid=0) AND (zoneid = %i or zoneid = 0) AND " - "gm <= %i ORDER BY id", - si_race, si_class, si_deity, si_current_zone, admin_level - ), - errbuf, - &result - ); - safe_delete_array(query); - - while((row = mysql_fetch_row(result))) { - int itemid = atoi(row[0]); - int charges = atoi(row[1]); - int slot = atoi(row[2]); - myitem = GetItem(itemid); - if(!myitem) - continue; - ItemInst* myinst = CreateBaseItem(myitem, charges); - if(slot < 0) - slot = inv->FindFreeSlot(0,0); - inv->PutItem(slot, *myinst); - safe_delete(myinst); - } - - if(result) mysql_free_result(result); - - return true; -} - - -// Retrieve shared bank inventory based on either account or character -bool SharedDatabase::GetSharedBank(uint32 id, Inventory* inv, bool is_charid) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 len_query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - bool ret = false; - - if (is_charid) { - len_query = MakeAnyLenString(&query, - "SELECT sb.slotid,sb.itemid,sb.charges,sb.augslot1,sb.augslot2,sb.augslot3,sb.augslot4,sb.augslot5,sb.custom_data from sharedbank sb " - "INNER JOIN character_ ch ON ch.account_id=sb.acctid " - "WHERE ch.id=%i", id); - } - else { - len_query = MakeAnyLenString(&query, - "SELECT slotid,itemid,charges,augslot1,augslot2,augslot3,augslot4,augslot5,custom_data from sharedbank WHERE acctid=%i", id); - } - - if (RunQuery(query, len_query, errbuf, &result)) { - while ((row = mysql_fetch_row(result))) { - int16 slot_id = (int16)atoi(row[0]); - uint32 item_id = (uint32)atoi(row[1]); - int8 charges = (int8)atoi(row[2]); - uint32 aug[5]; - aug[0] = (uint32)atoi(row[3]); - aug[1] = (uint32)atoi(row[4]); - aug[2] = (uint32)atoi(row[5]); - aug[3] = (uint32)atoi(row[6]); - aug[4] = (uint32)atoi(row[7]); - const Item_Struct* item = GetItem(item_id); - - if (item) { - int16 put_slot_id = INVALID_INDEX; - - ItemInst* inst = CreateBaseItem(item, charges); - if (item->ItemClass == ItemClassCommon) { - for(int i=0;i<5;i++) { - if (aug[i]) { - inst->PutAugment(this, i, aug[i]); - } - } - } - if(row[8]) { - std::string data_str(row[8]); - std::string id; - std::string value; - bool use_id = true; - - for(int i = 0; i < data_str.length(); ++i) { - if(data_str[i] == '^') { - if(!use_id) { - inst->SetCustomData(id, value); - id.clear(); - value.clear(); - } - use_id = !use_id; - } - else { - char v = data_str[i]; - if(use_id) { - id.push_back(v); - } else { - value.push_back(v); - } - } - } - } - - put_slot_id = inv->PutItem(slot_id, *inst); - safe_delete(inst); - - // Save ptr to item in inventory - if (put_slot_id == INVALID_INDEX) { - LogFile->write(EQEMuLog::Error, - "Warning: Invalid slot_id for item in shared bank inventory: %s=%i, item_id=%i, slot_id=%i", - ((is_charid==true) ? "charid" : "acctid"), id, item_id, slot_id); - - if(is_charid) - SaveInventory(id,nullptr,slot_id); - } - } - else { - LogFile->write(EQEMuLog::Error, - "Warning: %s %i has an invalid item_id %i in inventory slot %i", - ((is_charid==true) ? "charid" : "acctid"), id, item_id, slot_id); - } - } - - mysql_free_result(result); - ret = true; - } - else { - LogFile->write(EQEMuLog::Error, "Database::GetSharedBank(uint32 account_id): %s", errbuf); - } - - safe_delete_array(query); - return ret; -} - - -// Overloaded: Retrieve character inventory based on character id -bool SharedDatabase::GetInventory(uint32 char_id, Inventory* inv) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES* result; - MYSQL_ROW row; - bool ret = false; - - // Retrieve character inventory - if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5," - "instnodrop,custom_data FROM inventory WHERE charid=%i ORDER BY slotid", char_id), errbuf, &result)) { - - while ((row = mysql_fetch_row(result))) { - int16 slot_id = atoi(row[0]); - uint32 item_id = atoi(row[1]); - uint16 charges = atoi(row[2]); - uint32 color = atoul(row[3]); - uint32 aug[5]; - aug[0] = (uint32)atoul(row[4]); - aug[1] = (uint32)atoul(row[5]); - aug[2] = (uint32)atoul(row[6]); - aug[3] = (uint32)atoul(row[7]); - aug[4] = (uint32)atoul(row[8]); - bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false; - - const Item_Struct* item = GetItem(item_id); - - if (item) { - int16 put_slot_id = INVALID_INDEX; - - ItemInst* inst = CreateBaseItem(item, charges); - - if(row[10]) { - std::string data_str(row[10]); - std::string id; - std::string value; - bool use_id = true; - - for(int i = 0; i < data_str.length(); ++i) { - if(data_str[i] == '^') { - if(!use_id) { - inst->SetCustomData(id, value); - id.clear(); - value.clear(); - } - use_id = !use_id; - } - else { - char v = data_str[i]; - if(use_id) { - id.push_back(v); - } else { - value.push_back(v); - } - } - } - } - - if (instnodrop || (slot_id >= 0 && slot_id <= 21 && inst->GetItem()->Attuneable)) - inst->SetInstNoDrop(true); - if (color > 0) - inst->SetColor(color); - if(charges==0x7FFF) - inst->SetCharges(-1); - else - inst->SetCharges(charges); - - if (item->ItemClass == ItemClassCommon) { - for(int i=0;i<5;i++) { - if (aug[i]) { - inst->PutAugment(this, i, aug[i]); - } - } - } - - if (slot_id>=8000 && slot_id <= 8999) - put_slot_id = inv->PushCursor(*inst); - else - put_slot_id = inv->PutItem(slot_id, *inst); - safe_delete(inst); - - // Save ptr to item in inventory - if (put_slot_id == INVALID_INDEX) { - LogFile->write(EQEMuLog::Error, - "Warning: Invalid slot_id for item in inventory: charid=%i, item_id=%i, slot_id=%i", - char_id, item_id, slot_id); - } - } - else { - LogFile->write(EQEMuLog::Error, - "Warning: charid %i has an invalid item_id %i in inventory slot %i", - char_id, item_id, slot_id); - } - } - mysql_free_result(result); - - // Retrieve shared inventory - ret = GetSharedBank(char_id, inv, true); - } - else { - LogFile->write(EQEMuLog::Error, "GetInventory query '%s' %s", query, errbuf); - LogFile->write(EQEMuLog::Error, "If you got an error related to the 'instnodrop' field, run the following SQL Queries:\nalter table inventory add instnodrop tinyint(1) unsigned default 0 not null;\n"); - } - - safe_delete_array(query); - return ret; -} - -// Overloaded: Retrieve character inventory based on account_id and character name -bool SharedDatabase::GetInventory(uint32 account_id, char* name, Inventory* inv) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES* result; - MYSQL_ROW row; - bool ret = false; - - // Retrieve character inventory - if (RunQuery(query, MakeAnyLenString(&query, "SELECT slotid,itemid,charges,color,augslot1,augslot2,augslot3,augslot4,augslot5," - "instnodrop,custom_data FROM inventory INNER JOIN character_ ch ON ch.id=charid WHERE ch.name='%s' AND ch.account_id=%i ORDER BY slotid", - name, account_id), errbuf, &result)) - { - while ((row = mysql_fetch_row(result))) { - int16 slot_id = atoi(row[0]); - uint32 item_id = atoi(row[1]); - int8 charges = atoi(row[2]); - uint32 color = atoul(row[3]); - uint32 aug[5]; - aug[0] = (uint32)atoi(row[4]); - aug[1] = (uint32)atoi(row[5]); - aug[2] = (uint32)atoi(row[6]); - aug[3] = (uint32)atoi(row[7]); - aug[4] = (uint32)atoi(row[8]); - bool instnodrop = (row[9] && (uint16)atoi(row[9])) ? true : false; - const Item_Struct* item = GetItem(item_id); - int16 put_slot_id = INVALID_INDEX; - if(!item) - continue; - - ItemInst* inst = CreateBaseItem(item, charges); - inst->SetInstNoDrop(instnodrop); - - if(row[10]) { - std::string data_str(row[10]); - std::string id; - std::string value; - bool use_id = true; - - for(int i = 0; i < data_str.length(); ++i) { - if(data_str[i] == '^') { - if(!use_id) { - inst->SetCustomData(id, value); - id.clear(); - value.clear(); - } - use_id = !use_id; - } - else { - char v = data_str[i]; - if(use_id) { - id.push_back(v); - } else { - value.push_back(v); - } - } - } - } - - if (color > 0) - inst->SetColor(color); - inst->SetCharges(charges); - - if (item->ItemClass == ItemClassCommon) { - for(int i=0;i<5;i++) { - if (aug[i]) { - inst->PutAugment(this, i, aug[i]); - } - } - } - if (slot_id>=8000 && slot_id <= 8999) - put_slot_id = inv->PushCursor(*inst); - else - put_slot_id = inv->PutItem(slot_id, *inst); - safe_delete(inst); - - // Save ptr to item in inventory - if (put_slot_id == INVALID_INDEX) { - LogFile->write(EQEMuLog::Error, - "Warning: Invalid slot_id for item in inventory: name=%s, acctid=%i, item_id=%i, slot_id=%i", - name, account_id, item_id, slot_id); - } - } - mysql_free_result(result); - - // Retrieve shared inventory - ret = GetSharedBank(account_id, inv, false); - } - else { - LogFile->write(EQEMuLog::Error, "GetInventory query '%s' %s", query, errbuf); - LogFile->write(EQEMuLog::Error, "If you got an error related to the 'instnodrop' field, run the following SQL Queries:\nalter table inventory add instnodrop tinyint(1) unsigned default 0 not null;\n"); - } - - safe_delete_array(query); - return ret; -} - - -void SharedDatabase::GetItemsCount(int32 &item_count, uint32 &max_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - item_count = -1; - max_id = 0; - - char query[] = "SELECT MAX(id), count(*) FROM items"; - if (RunQuery(query, static_cast(strlen(query)), errbuf, &result)) { - row = mysql_fetch_row(result); - if (row != nullptr && row[1] != 0) { - item_count = atoi(row[1]); - if(row[0]) - max_id = atoi(row[0]); - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in GetItemsCount '%s': '%s'", query, errbuf); - } -} - -bool SharedDatabase::LoadItems() { - if(items_mmf) { - return true; - } - - try { - EQEmu::IPCMutex mutex("items"); - mutex.Lock(); - items_mmf = new EQEmu::MemoryMappedFile("shared/items"); - - int32 items = -1; - uint32 max_item = 0; - GetItemsCount(items, max_item); - if(items == -1) { - EQ_EXCEPT("SharedDatabase", "Database returned no result"); - } - uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); - if(items_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Couldn't load items because items_mmf->Size() != size"); - } - - items_hash = new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), size); - mutex.Unlock(); - } catch(std::exception& ex) { - LogFile->write(EQEMuLog::Error, "Error Loading Items: %s", ex.what()); - return false; - } - - return true; -} - -void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id) { - EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - char ndbuffer[4]; - bool disableNoRent = false; - if(GetVariable("disablenorent", ndbuffer, 4)) { - if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableNoRent = true; - } - } - bool disableNoDrop = false; - if(GetVariable("disablenodrop", ndbuffer, 4)) { - if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableNoDrop = true; - } - } - bool disableLoreGroup = false; - if(GetVariable("disablelore", ndbuffer, 4)) { - if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableLoreGroup = true; - } - } - bool disableNoTransfer = false; - if(GetVariable("disablenotransfer", ndbuffer, 4)) { - if(ndbuffer[0] == '1' && ndbuffer[1] == '\0') { - disableNoTransfer = true; - } - } - - char query[] = "select source," -#define F(x) "`"#x"`," -#include "item_fieldlist.h" -#undef F - "updated" - " from items order by id"; - Item_Struct item; - if(RunQuery(query, sizeof(query), errbuf, &result)) { - while((row = mysql_fetch_row(result))) { - memset(&item, 0, sizeof(Item_Struct)); - - item.ItemClass = (uint8)atoi(row[ItemField::itemclass]); - strcpy(item.Name,row[ItemField::name]); - strcpy(item.Lore,row[ItemField::lore]); - strcpy(item.IDFile,row[ItemField::idfile]); - item.ID = (uint32)atoul(row[ItemField::id]); - item.Weight = (uint8)atoi(row[ItemField::weight]); - item.NoRent = disableNoRent ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::norent]); - item.NoDrop = disableNoDrop ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::nodrop]); - item.Size = (uint8)atoi(row[ItemField::size]); - item.Slots = (uint32)atoul(row[ItemField::slots]); - item.Price = (uint32)atoul(row[ItemField::price]); - item.Icon = (uint32)atoul(row[ItemField::icon]); - item.BenefitFlag = (atoul(row[ItemField::benefitflag]) != 0); - item.Tradeskills = (atoi(row[ItemField::tradeskills])==0) ? false : true; - item.CR = (int8)atoi(row[ItemField::cr]); - item.DR = (int8)atoi(row[ItemField::dr]); - item.PR = (int8)atoi(row[ItemField::pr]); - item.MR = (int8)atoi(row[ItemField::mr]); - item.FR = (int8)atoi(row[ItemField::fr]); - item.AStr = (int8)atoi(row[ItemField::astr]); - item.ASta = (int8)atoi(row[ItemField::asta]); - item.AAgi = (int8)atoi(row[ItemField::aagi]); - item.ADex = (int8)atoi(row[ItemField::adex]); - item.ACha = (int8)atoi(row[ItemField::acha]); - item.AInt = (int8)atoi(row[ItemField::aint]); - item.AWis = (int8)atoi(row[ItemField::awis]); - item.HP = (int32)atoul(row[ItemField::hp]); - item.Mana = (int32)atoul(row[ItemField::mana]); - item.AC = (int32)atoul(row[ItemField::ac]); - item.Deity = (uint32)atoul(row[ItemField::deity]); - item.SkillModValue = (int32)atoul(row[ItemField::skillmodvalue]); - //item.Unk033 = (int32)atoul(row[ItemField::UNK033]); - item.SkillModType = (uint32)atoul(row[ItemField::skillmodtype]); - item.BaneDmgRace = (uint32)atoul(row[ItemField::banedmgrace]); - item.BaneDmgAmt = (int8)atoi(row[ItemField::banedmgamt]); - item.BaneDmgBody = (uint32)atoul(row[ItemField::banedmgbody]); - item.Magic = (atoi(row[ItemField::magic])==0) ? false : true; - item.CastTime_ = (int32)atoul(row[ItemField::casttime_]); - item.ReqLevel = (uint8)atoi(row[ItemField::reqlevel]); - item.BardType = (uint32)atoul(row[ItemField::bardtype]); - item.BardValue = (int32)atoul(row[ItemField::bardvalue]); - item.Light = (int8)atoi(row[ItemField::light]); - item.Delay = (uint8)atoi(row[ItemField::delay]); - item.RecLevel = (uint8)atoi(row[ItemField::reclevel]); - item.RecSkill = (uint8)atoi(row[ItemField::recskill]); - item.ElemDmgType = (uint8)atoi(row[ItemField::elemdmgtype]); - item.ElemDmgAmt = (uint8)atoi(row[ItemField::elemdmgamt]); - item.Range = (uint8)atoi(row[ItemField::range]); - item.Damage = (uint32)atoi(row[ItemField::damage]); - item.Color = (uint32)atoul(row[ItemField::color]); - item.Classes = (uint32)atoul(row[ItemField::classes]); - item.Races = (uint32)atoul(row[ItemField::races]); - //item.Unk054 = (uint32)atoul(row[ItemField::UNK054]); - item.MaxCharges = (int16)atoi(row[ItemField::maxcharges]); - item.ItemType = (uint8)atoi(row[ItemField::itemtype]); - item.Material = (uint8)atoi(row[ItemField::material]); - item.SellRate = (float)atof(row[ItemField::sellrate]); - //item.Unk059 = (uint32)atoul(row[ItemField::UNK059]); - item.CastTime = (uint32)atoul(row[ItemField::casttime]); - item.EliteMaterial = (uint32)atoul(row[ItemField::elitematerial]); - item.ProcRate = (int32)atoi(row[ItemField::procrate]); - item.CombatEffects = (int8)atoi(row[ItemField::combateffects]); - item.Shielding = (int8)atoi(row[ItemField::shielding]); - item.StunResist = (int8)atoi(row[ItemField::stunresist]); - item.StrikeThrough = (int8)atoi(row[ItemField::strikethrough]); - item.ExtraDmgSkill = (uint32)atoul(row[ItemField::extradmgskill]); - item.ExtraDmgAmt = (uint32)atoul(row[ItemField::extradmgamt]); - item.SpellShield = (int8)atoi(row[ItemField::spellshield]); - item.Avoidance = (int8)atoi(row[ItemField::avoidance]); - item.Accuracy = (int8)atoi(row[ItemField::accuracy]); - item.CharmFileID = (uint32)atoul(row[ItemField::charmfileid]); - item.FactionMod1 = (int32)atoul(row[ItemField::factionmod1]); - item.FactionMod2 = (int32)atoul(row[ItemField::factionmod2]); - item.FactionMod3 = (int32)atoul(row[ItemField::factionmod3]); - item.FactionMod4 = (int32)atoul(row[ItemField::factionmod4]); - item.FactionAmt1 = (int32)atoul(row[ItemField::factionamt1]); - item.FactionAmt2 = (int32)atoul(row[ItemField::factionamt2]); - item.FactionAmt3 = (int32)atoul(row[ItemField::factionamt3]); - item.FactionAmt4 = (int32)atoul(row[ItemField::factionamt4]); - strcpy(item.CharmFile,row[ItemField::charmfile]); - item.AugType = (uint32)atoul(row[ItemField::augtype]); - item.AugSlotType[0] = (uint8)atoi(row[ItemField::augslot1type]); - item.AugSlotVisible[0] = (uint8)atoi(row[ItemField::augslot1visible]); - item.AugSlotUnk2[0] = 0; - item.AugSlotType[1] = (uint8)atoi(row[ItemField::augslot2type]); - item.AugSlotVisible[1] = (uint8)atoi(row[ItemField::augslot2visible]); - item.AugSlotUnk2[1] = 0; - item.AugSlotType[2] = (uint8)atoi(row[ItemField::augslot3type]); - item.AugSlotVisible[2] = (uint8)atoi(row[ItemField::augslot3visible]); - item.AugSlotUnk2[2] = 0; - item.AugSlotType[3] = (uint8)atoi(row[ItemField::augslot4type]); - item.AugSlotVisible[3] = (uint8)atoi(row[ItemField::augslot4visible]); - item.AugSlotUnk2[3] = 0; - item.AugSlotType[4] = (uint8)atoi(row[ItemField::augslot5type]); - item.AugSlotVisible[4] = (uint8)atoi(row[ItemField::augslot5visible]); - item.AugSlotUnk2[4] = 0; - item.LDoNTheme = (uint32)atoul(row[ItemField::ldontheme]); - item.LDoNPrice = (uint32)atoul(row[ItemField::ldonprice]); - item.LDoNSold = (uint32)atoul(row[ItemField::ldonsold]); - item.BagType = (uint8)atoi(row[ItemField::bagtype]); - item.BagSlots = (uint8)atoi(row[ItemField::bagslots]); - item.BagSize = (uint8)atoi(row[ItemField::bagsize]); - item.BagWR = (uint8)atoi(row[ItemField::bagwr]); - item.Book = (uint8)atoi(row[ItemField::book]); - item.BookType = (uint32)atoul(row[ItemField::booktype]); - strcpy(item.Filename,row[ItemField::filename]); - item.BaneDmgRaceAmt = (uint32)atoul(row[ItemField::banedmgraceamt]); - item.AugRestrict = (uint32)atoul(row[ItemField::augrestrict]); - item.LoreGroup = disableLoreGroup ? (uint8)atoi("0") : atoi(row[ItemField::loregroup]); - item.LoreFlag = item.LoreGroup!=0; - item.PendingLoreFlag = (atoi(row[ItemField::pendingloreflag])==0) ? false : true; - item.ArtifactFlag = (atoi(row[ItemField::artifactflag])==0) ? false : true; - item.SummonedFlag = (atoi(row[ItemField::summonedflag])==0) ? false : true; - item.Favor = (uint32)atoul(row[ItemField::favor]); - item.FVNoDrop = (atoi(row[ItemField::fvnodrop])==0) ? false : true; - item.Endur = (uint32)atoul(row[ItemField::endur]); - item.DotShielding = (uint32)atoul(row[ItemField::dotshielding]); - item.Attack = (uint32)atoul(row[ItemField::attack]); - item.Regen = (uint32)atoul(row[ItemField::regen]); - item.ManaRegen = (uint32)atoul(row[ItemField::manaregen]); - item.EnduranceRegen = (uint32)atoul(row[ItemField::enduranceregen]); - item.Haste = (uint32)atoul(row[ItemField::haste]); - item.DamageShield = (uint32)atoul(row[ItemField::damageshield]); - item.RecastDelay = (uint32)atoul(row[ItemField::recastdelay]); - item.RecastType = (uint32)atoul(row[ItemField::recasttype]); - item.GuildFavor = (uint32)atoul(row[ItemField::guildfavor]); - item.AugDistiller = (uint32)atoul(row[ItemField::augdistiller]); - item.Attuneable = (atoi(row[ItemField::attuneable])==0) ? false : true; - item.NoPet = (atoi(row[ItemField::nopet])==0) ? false : true; - item.PointType = (uint32)atoul(row[ItemField::pointtype]); - item.PotionBelt = (atoi(row[ItemField::potionbelt])==0) ? false : true; - item.PotionBeltSlots = (atoi(row[ItemField::potionbeltslots])==0) ? false : true; - item.StackSize = (uint16)atoi(row[ItemField::stacksize]); - item.NoTransfer = disableNoTransfer ? false : (atoi(row[ItemField::notransfer])==0) ? false : true; - item.Stackable = (atoi(row[ItemField::stackable])==0) ? false : true; - item.Click.Effect = (uint32)atoul(row[ItemField::clickeffect]); - item.Click.Type = (uint8)atoul(row[ItemField::clicktype]); - item.Click.Level = (uint8)atoul(row[ItemField::clicklevel]); - item.Click.Level2 = (uint8)atoul(row[ItemField::clicklevel2]); - strcpy(item.CharmFile,row[ItemField::charmfile]); - item.Proc.Effect = (uint16)atoul(row[ItemField::proceffect]); - item.Proc.Type = (uint8)atoul(row[ItemField::proctype]); - item.Proc.Level = (uint8)atoul(row[ItemField::proclevel]); - item.Proc.Level2 = (uint8)atoul(row[ItemField::proclevel2]); - item.Worn.Effect = (uint16)atoul(row[ItemField::worneffect]); - item.Worn.Type = (uint8)atoul(row[ItemField::worntype]); - item.Worn.Level = (uint8)atoul(row[ItemField::wornlevel]); - item.Worn.Level2 = (uint8)atoul(row[ItemField::wornlevel2]); - item.Focus.Effect = (uint16)atoul(row[ItemField::focuseffect]); - item.Focus.Type = (uint8)atoul(row[ItemField::focustype]); - item.Focus.Level = (uint8)atoul(row[ItemField::focuslevel]); - item.Focus.Level2 = (uint8)atoul(row[ItemField::focuslevel2]); - item.Scroll.Effect = (uint16)atoul(row[ItemField::scrolleffect]); - item.Scroll.Type = (uint8)atoul(row[ItemField::scrolltype]); - item.Scroll.Level = (uint8)atoul(row[ItemField::scrolllevel]); - item.Scroll.Level2 = (uint8)atoul(row[ItemField::scrolllevel2]); - item.Bard.Effect = (uint16)atoul(row[ItemField::bardeffect]); - item.Bard.Type = (uint8)atoul(row[ItemField::bardtype]); - item.Bard.Level = (uint8)atoul(row[ItemField::bardlevel]); - item.Bard.Level2 = (uint8)atoul(row[ItemField::bardlevel2]); - item.QuestItemFlag = (atoi(row[ItemField::questitemflag])==0) ? false : true; - item.SVCorruption = (int32)atoi(row[ItemField::svcorruption]); - item.Purity = (uint32)atoul(row[ItemField::purity]); - item.BackstabDmg = (uint32)atoul(row[ItemField::backstabdmg]); - item.DSMitigation = (uint32)atoul(row[ItemField::dsmitigation]); - item.HeroicStr = (int32)atoi(row[ItemField::heroic_str]); - item.HeroicInt = (int32)atoi(row[ItemField::heroic_int]); - item.HeroicWis = (int32)atoi(row[ItemField::heroic_wis]); - item.HeroicAgi = (int32)atoi(row[ItemField::heroic_agi]); - item.HeroicDex = (int32)atoi(row[ItemField::heroic_dex]); - item.HeroicSta = (int32)atoi(row[ItemField::heroic_sta]); - item.HeroicCha = (int32)atoi(row[ItemField::heroic_cha]); - item.HeroicMR = (int32)atoi(row[ItemField::heroic_mr]); - item.HeroicFR = (int32)atoi(row[ItemField::heroic_fr]); - item.HeroicCR = (int32)atoi(row[ItemField::heroic_cr]); - item.HeroicDR = (int32)atoi(row[ItemField::heroic_dr]); - item.HeroicPR = (int32)atoi(row[ItemField::heroic_pr]); - item.HeroicSVCorrup = (int32)atoi(row[ItemField::heroic_svcorrup]); - item.HealAmt = (int32)atoi(row[ItemField::healamt]); - item.SpellDmg = (int32)atoi(row[ItemField::spelldmg]); - item.LDoNSellBackRate = (uint32)atoul(row[ItemField::ldonsellbackrate]); - item.ScriptFileID = (uint32)atoul(row[ItemField::scriptfileid]); - item.ExpendableArrow = (uint16)atoul(row[ItemField::expendablearrow]); - item.Clairvoyance = (uint32)atoul(row[ItemField::clairvoyance]); - strcpy(item.ClickName,row[ItemField::clickname]); - strcpy(item.ProcName,row[ItemField::procname]); - strcpy(item.WornName,row[ItemField::wornname]); - strcpy(item.FocusName,row[ItemField::focusname]); - strcpy(item.ScrollName,row[ItemField::scrollname]); - - try { - hash.insert(item.ID, item); - } catch(std::exception &ex) { - LogFile->write(EQEMuLog::Error, "Database::LoadItems: %s", ex.what()); - break; - } - } - - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "LoadItems '%s', %s", query, errbuf); - } -} - -const Item_Struct* SharedDatabase::GetItem(uint32 id) { - if(!items_hash || id > items_hash->max_key()) { - return nullptr; - } - - if(items_hash->exists(id)) { - return &(items_hash->at(id)); - } - - return nullptr; -} - -const Item_Struct* SharedDatabase::IterateItems(uint32* id) { - if(!items_hash || !id) { - return nullptr; - } - - for(;;) { - if(*id > items_hash->max_key()) { - break; - } - - if(items_hash->exists(*id)) { - return &(items_hash->at((*id)++)); - } else { - ++(*id); - } - } - - return nullptr; -} - -std::string SharedDatabase::GetBook(const char *txtfile) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - char txtfile2[20]; - std::string txtout; - strcpy(txtfile2,txtfile); - if (!RunQuery(query, MakeAnyLenString(&query, "SELECT txtfile FROM books where name='%s'", txtfile2), errbuf, &result)) { - std::cerr << "Error in GetBook query '" << query << "' " << errbuf << std::endl; - if (query != 0) - safe_delete_array(query); - txtout.assign(" ",1); - return txtout; - } - else { - safe_delete_array(query); - if (mysql_num_rows(result) == 0) { - mysql_free_result(result); - LogFile->write(EQEMuLog::Error, "No book to send, (%s)", txtfile); - txtout.assign(" ",1); - return txtout; - } - else { - row = mysql_fetch_row(result); - txtout.assign(row[0],strlen(row[0])); - mysql_free_result(result); - return txtout; - } - } -} - -void SharedDatabase::GetFactionListInfo(uint32 &list_count, uint32 &max_lists) { - list_count = 0; - max_lists = 0; - const char *query = "SELECT COUNT(*), MAX(id) FROM npc_faction"; - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query, strlen(query), errbuf, &result)) { - if(row = mysql_fetch_row(result)) { - list_count = static_cast(atoul(row[0])); - max_lists = static_cast(atoul(row[1])); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting npc faction info from database: %s, %s", query, errbuf); - } -} - -const NPCFactionList* SharedDatabase::GetNPCFactionEntry(uint32 id) { - if(!faction_hash) { - return nullptr; - } - - if(faction_hash->exists(id)) { - return &(faction_hash->at(id)); - } - - return nullptr; -} - -void SharedDatabase::LoadNPCFactionLists(void *data, uint32 size, uint32 list_count, uint32 max_lists) { - EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, list_count, max_lists); - const char *query = "SELECT npc_faction.id, npc_faction.primaryfaction, npc_faction.ignore_primary_assist, " - "npc_faction_entries.faction_id, npc_faction_entries.value, npc_faction_entries.npc_value, npc_faction_entries.temp " - "FROM npc_faction LEFT JOIN npc_faction_entries ON npc_faction.id = npc_faction_entries.npc_faction_id ORDER BY " - "npc_faction.id;"; - - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - NPCFactionList faction; - - if(RunQuery(query, strlen(query), errbuf, &result)) { - uint32 current_id = 0; - uint32 current_entry = 0; - while(row = mysql_fetch_row(result)) { - uint32 id = static_cast(atoul(row[0])); - if(id != current_id) { - if(current_id != 0) { - hash.insert(current_id, faction); - } - - memset(&faction, 0, sizeof(faction)); - current_entry = 0; - current_id = id; - faction.id = id; - faction.primaryfaction = static_cast(atoul(row[1])); - faction.assistprimaryfaction = (atoi(row[2]) == 0); - } - - if(!row[3]) { - continue; - } - - if(current_entry >= MAX_NPC_FACTIONS) { - continue; - } - - faction.factionid[current_entry] = static_cast(atoul(row[3])); - faction.factionvalue[current_entry] = static_cast(atoi(row[4])); - faction.factionnpcvalue[current_entry] = static_cast(atoi(row[5])); - faction.factiontemp[current_entry] = static_cast(atoi(row[6])); - ++current_entry; - } - - if(current_id != 0) { - hash.insert(current_id, faction); - } - - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting npc faction info from database: %s, %s", query, errbuf); -} -} - -bool SharedDatabase::LoadNPCFactionLists() { - if(faction_hash) { - return true; - } - - try { - EQEmu::IPCMutex mutex("faction"); - mutex.Lock(); - faction_mmf = new EQEmu::MemoryMappedFile("shared/faction"); - - uint32 list_count = 0; - uint32 max_lists = 0; - GetFactionListInfo(list_count, max_lists); - if(list_count == 0) { - EQ_EXCEPT("SharedDatabase", "Database returned no result"); - } - uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size( - list_count, max_lists)); - - if(faction_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Couldn't load npc factions because faction_mmf->Size() != size"); - } - - faction_hash = new EQEmu::FixedMemoryHashSet(reinterpret_cast(faction_mmf->Get()), size); - mutex.Unlock(); - } catch(std::exception& ex) { - LogFile->write(EQEMuLog::Error, "Error Loading npc factions: %s", ex.what()); - return false; - } - - return true; -} - -// Get the player profile and inventory for the given account "account_id" and -// character name "name". Return true if the character was found, otherwise false. -// False will also be returned if there is a database error. -bool SharedDatabase::GetPlayerProfile(uint32 account_id, char* name, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, char* current_zone, uint32 *current_instance) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES* result; - MYSQL_ROW row; - bool ret = false; - - unsigned long* lengths; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT profile,zonename,x,y,z,extprofile,instanceid FROM character_ WHERE account_id=%i AND name='%s'", account_id, name), errbuf, &result)) { - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - lengths = mysql_fetch_lengths(result); - if (lengths[0] == sizeof(PlayerProfile_Struct)) { - memcpy(pp, row[0], sizeof(PlayerProfile_Struct)); - - if (current_zone) - strcpy(current_zone, row[1]); - pp->zone_id = GetZoneID(row[1]); - pp->x = atof(row[2]); - pp->y = atof(row[3]); - pp->z = atof(row[4]); - pp->zoneInstance = atoi(row[6]); - if (pp->x == -1 && pp->y == -1 && pp->z == -1) - GetSafePoints(pp->zone_id, GetInstanceVersion(pp->zoneInstance), &pp->x, &pp->y, &pp->z); - - if(current_instance) - *current_instance = pp->zoneInstance; - - if(ext) { - //SetExtendedProfile handles any conversion - SetExtendedProfile(ext, row[5], lengths[5]); - } - - // Retrieve character inventory - ret = GetInventory(account_id, name, inv); - } - else { - LogFile->write(EQEMuLog::Error, "Player profile length mismatch in GetPlayerProfile. Found: %i, Expected: %i", - lengths[0], sizeof(PlayerProfile_Struct)); - } - } - - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "GetPlayerProfile query '%s' %s", query, errbuf); - } - - safe_delete_array(query); - return ret; -} - -bool SharedDatabase::SetPlayerProfile(uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - uint32 affected_rows = 0; - bool ret = false; - - if (RunQuery(query, SetPlayerProfile_MQ(&query, account_id, charid, pp, inv, ext, current_zone, current_instance, MaxXTargets), errbuf, 0, &affected_rows)) { - ret = (affected_rows != 0); - } - - if (!ret) { - LogFile->write(EQEMuLog::Error, "SetPlayerProfile query '%s' %s", query, errbuf); - } - - safe_delete_array(query); - return ret; -} - -// Generate SQL for updating player profile -uint32 SharedDatabase::SetPlayerProfile_MQ(char** query, uint32 account_id, uint32 charid, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext, uint32 current_zone, uint32 current_instance, uint8 MaxXTargets) { - *query = new char[396 + sizeof(PlayerProfile_Struct)*2 + sizeof(ExtendedProfile_Struct)*2 + 4]; - char* end = *query; - if (!current_zone) - current_zone = pp->zone_id; - - if (!current_instance) - current_instance = pp->zoneInstance; - - if(strlen(pp->name) == 0) // Sanity check in case pp never loaded - return false; - - end += sprintf(end, "UPDATE character_ SET timelaston=unix_timestamp(now()),name=\'%s\', zonename=\'%s\', zoneid=%u, instanceid=%u, x = %f, y = %f, z = %f, profile=\'", pp->name, GetZoneName(current_zone), current_zone, current_instance, pp->x, pp->y, pp->z); - end += DoEscapeString(end, (char*)pp, sizeof(PlayerProfile_Struct)); - end += sprintf(end,"\', extprofile=\'"); - end += DoEscapeString(end, (char*)ext, sizeof(ExtendedProfile_Struct)); - end += sprintf(end,"\',class=%d,level=%d,xtargets=%u WHERE id=%u", pp->class_, pp->level, MaxXTargets, charid); - - return (uint32) (end - (*query)); -} - - - -// Create appropriate ItemInst class -ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) -{ - const Item_Struct* item = nullptr; - ItemInst* inst = nullptr; - item = GetItem(item_id); - if (item) { - inst = CreateBaseItem(item, charges); - inst->PutAugment(this, 0, aug1); - inst->PutAugment(this, 1, aug2); - inst->PutAugment(this, 2, aug3); - inst->PutAugment(this, 3, aug4); - inst->PutAugment(this, 4, aug5); - } - - return inst; -} - - -// Create appropriate ItemInst class -ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5) -{ - ItemInst* inst = nullptr; - if (item) { - inst = CreateBaseItem(item, charges); - inst->PutAugment(this, 0, aug1); - inst->PutAugment(this, 1, aug2); - inst->PutAugment(this, 2, aug3); - inst->PutAugment(this, 3, aug4); - inst->PutAugment(this, 4, aug5); - } - - return inst; -} - -ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges) { - ItemInst* inst = nullptr; - if (item) { - // if maxcharges is -1 that means it is an unlimited use item. - // set it to 1 charge so that it is usable on creation - if (charges == 0 && item->MaxCharges == -1) - charges = 1; - - inst = new ItemInst(item, charges); - - if(item->CharmFileID != 0 || (item->LoreGroup >= 1000 && item->LoreGroup != -1)) { - inst->Initialize(this); - } - } - return inst; -} - -int32 SharedDatabase::DeleteStalePlayerCorpses() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - - if(RuleB(Zone, EnableShadowrest)) - { - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE player_corpses SET IsBurried = 1 WHERE IsBurried=0 and " - "(UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timeofdeath)) > %d and not timeofdeath=0", - (RuleI(Character, CorpseDecayTimeMS) / 1000)), errbuf, 0, &affected_rows)) - { - safe_delete_array(query); - return -1; - } - } - else - { - if (!RunQuery(query, MakeAnyLenString(&query, "Delete from player_corpses where (UNIX_TIMESTAMP() - " - "UNIX_TIMESTAMP(timeofdeath)) > %d and not timeofdeath=0", (RuleI(Character, CorpseDecayTimeMS) / 1000)), - errbuf, 0, &affected_rows)) - { - safe_delete_array(query); - return -1; - } - } - - safe_delete_array(query); - return affected_rows; -} - -int32 SharedDatabase::DeleteStalePlayerBackups() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - uint32 affected_rows = 0; - - // 1209600 seconds = 2 weeks - if (!RunQuery(query, MakeAnyLenString(&query, "Delete from player_corpses_backup where (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(timeofdeath)) > 1209600"), errbuf, 0, &affected_rows)) { - safe_delete_array(query); - return -1; - } - safe_delete_array(query); - - return affected_rows; -} - -bool SharedDatabase::GetCommandSettings(std::map &commands) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - query = new char[256]; - strcpy(query, "SELECT command,access from commands"); - commands.clear(); - if (RunQuery(query, strlen(query), errbuf, &result)) { - safe_delete_array(query); - while((row = mysql_fetch_row(result))) { - commands[row[0]]=atoi(row[1]); - } - mysql_free_result(result); - return true; - } else { - std::cerr << "Error in GetCommands query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return false; - } - - return false; -} - -bool SharedDatabase::LoadSkillCaps() { - if(skill_caps_mmf) - return true; - - uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; - uint32 level_count = HARD_LEVEL_CAP + 1; - uint32 size = (class_count * skill_count * level_count * sizeof(uint16)); - - try { - EQEmu::IPCMutex mutex("skill_caps"); - mutex.Lock(); - skill_caps_mmf = new EQEmu::MemoryMappedFile("shared/skill_caps"); - if(skill_caps_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Unable to load skill caps: skill_caps_mmf->Size() != size"); - } - - mutex.Unlock(); - } catch(std::exception &ex) { - LogFile->write(EQEMuLog::Error, "Error loading skill caps: %s", ex.what()); - return false; - } - - return true; -} - -void SharedDatabase::LoadSkillCaps(void *data) { - uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; - uint32 level_count = HARD_LEVEL_CAP + 1; - uint16 *skill_caps_table = reinterpret_cast(data); - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if(RunQuery(query, MakeAnyLenString(&query, - "SELECT skillID, class, level, cap FROM skill_caps ORDER BY skillID, class, level"), - errbuf, &result)) { - safe_delete_array(query); - - while((row = mysql_fetch_row(result))) { - uint8 skillID = atoi(row[0]); - uint8 class_ = atoi(row[1]) - 1; - uint8 level = atoi(row[2]); - uint16 cap = atoi(row[3]); - if(skillID >= skill_count || class_ >= class_count || level >= level_count) - continue; - - uint32 index = (((class_ * skill_count) + skillID) * level_count) + level; - skill_caps_table[index] = cap; - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error loading skill caps from database: %s", errbuf); - safe_delete_array(query); - } -} - -uint16 SharedDatabase::GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Level) { - if(!skill_caps_mmf) { - return 0; - } - - if(Class_ == 0) - return 0; - - int SkillMaxLevel = RuleI(Character, SkillCapMaxLevel); - if(SkillMaxLevel < 1) { - SkillMaxLevel = RuleI(Character, MaxLevel); - } - - uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; - uint32 level_count = HARD_LEVEL_CAP + 1; - if(Class_ > class_count || static_cast(Skill) > skill_count || Level > level_count) { - return 0; - } - - if(Level > static_cast(SkillMaxLevel)){ - Level = static_cast(SkillMaxLevel); - } - - uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count) + Level; - uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); - return skill_caps_table[index]; -} - -uint8 SharedDatabase::GetTrainLevel(uint8 Class_, SkillUseTypes Skill, uint8 Level) { - if(!skill_caps_mmf) { - return 0; - } - - if(Class_ == 0) - return 0; - - int SkillMaxLevel = RuleI(Character, SkillCapMaxLevel); - if (SkillMaxLevel < 1) { - SkillMaxLevel = RuleI(Character, MaxLevel); - } - - uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; - uint32 level_count = HARD_LEVEL_CAP + 1; - if(Class_ > class_count || static_cast(Skill) > skill_count || Level > level_count) { - return 0; - } - - uint8 ret = 0; - if(Level > static_cast(SkillMaxLevel)) { - uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count); - uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); - for(uint8 x = 0; x < Level; x++){ - if(skill_caps_table[index + x]){ - ret = x; - break; - } - } - } - else - { - uint32 index = ((((Class_ - 1) * skill_count) + Skill) * level_count); - uint16 *skill_caps_table = reinterpret_cast(skill_caps_mmf->Get()); - for(int x = 0; x < SkillMaxLevel; x++){ - if(skill_caps_table[index + x]){ - ret = x; - break; - } - } - } - - if(ret > GetSkillCap(Class_, Skill, Level)) - ret = static_cast(GetSkillCap(Class_, Skill, Level)); - - return ret; -} - -void SharedDatabase::LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID) { - - const char *DSQuery = "SELECT `spellid`, `type` from `damageshieldtypes` WHERE `spellid` > 0 " - "AND `spellid` <= %i"; - - const char *ERR_MYSQLERROR = "Error in LoadDamageShieldTypes: %s %s"; - - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query,MakeAnyLenString(&query,DSQuery,iMaxSpellID),errbuf,&result)) { - - while((row = mysql_fetch_row(result))) { - - int SpellID = atoi(row[0]); - if((SpellID > 0) && (SpellID <= iMaxSpellID)) { - sp[SpellID].DamageShieldType = atoi(row[1]); - } - } - mysql_free_result(result); - safe_delete_array(query); - } - else { - LogFile->write(EQEMuLog::Error, ERR_MYSQLERROR, query, errbuf); - safe_delete_array(query); - } -} - -const EvolveInfo* SharedDatabase::GetEvolveInfo(uint32 loregroup) { - return nullptr; // nothing here for now... database and/or sharemem pulls later -} - -int SharedDatabase::GetMaxSpellID() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = nullptr; - MYSQL_RES *result; - MYSQL_ROW row; - int32 ret = 0; - if(RunQuery(query, MakeAnyLenString(&query, "SELECT MAX(id) FROM spells_new"), - errbuf, &result)) { - safe_delete_array(query); - row = mysql_fetch_row(result); - ret = atoi(row[0]); - mysql_free_result(result); - } else { - _log(SPELLS__LOAD_ERR, "Error in GetMaxSpellID query '%s' %s", query, errbuf); - safe_delete_array(query); - ret = -1; - } - return ret; -} - -void SharedDatabase::LoadSpells(void *data, int max_spells) { - SPDat_Spell_Struct *sp = reinterpret_cast(data); - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query, MakeAnyLenString(&query, - "SELECT * FROM spells_new ORDER BY id ASC"), - errbuf, &result)) { - safe_delete_array(query); - - int tempid = 0; - int counter = 0; - while (row = mysql_fetch_row(result)) { - tempid = atoi(row[0]); - if(tempid >= max_spells) { - _log(SPELLS__LOAD_ERR, "Non fatal error: spell.id >= max_spells, ignoring."); - continue; - } - - ++counter; - sp[tempid].id = tempid; - strn0cpy(sp[tempid].name, row[1], sizeof(sp[tempid].name)); - strn0cpy(sp[tempid].player_1, row[2], sizeof(sp[tempid].player_1)); - strn0cpy(sp[tempid].teleport_zone, row[3], sizeof(sp[tempid].teleport_zone)); - strn0cpy(sp[tempid].you_cast, row[4], sizeof(sp[tempid].you_cast)); - strn0cpy(sp[tempid].other_casts, row[5], sizeof(sp[tempid].other_casts)); - strn0cpy(sp[tempid].cast_on_you, row[6], sizeof(sp[tempid].cast_on_you)); - strn0cpy(sp[tempid].cast_on_other, row[7], sizeof(sp[tempid].cast_on_other)); - strn0cpy(sp[tempid].spell_fades, row[8], sizeof(sp[tempid].spell_fades)); - - sp[tempid].range=static_cast(atof(row[9])); - sp[tempid].aoerange=static_cast(atof(row[10])); - sp[tempid].pushback=static_cast(atof(row[11])); - sp[tempid].pushup=static_cast(atof(row[12])); - sp[tempid].cast_time=atoi(row[13]); - sp[tempid].recovery_time=atoi(row[14]); - sp[tempid].recast_time=atoi(row[15]); - sp[tempid].buffdurationformula=atoi(row[16]); - sp[tempid].buffduration=atoi(row[17]); - sp[tempid].AEDuration=atoi(row[18]); - sp[tempid].mana=atoi(row[19]); - - int y=0; - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].base[y]=atoi(row[20+y]); // effect_base_value - for(y=0; y < EFFECT_COUNT; y++) - sp[tempid].base2[y]=atoi(row[32+y]); // effect_limit_value - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].max[y]=atoi(row[44+y]); - - for(y=0; y< 4;y++) - sp[tempid].components[y]=atoi(row[58+y]); - - for(y=0; y< 4;y++) - sp[tempid].component_counts[y]=atoi(row[62+y]); - - for(y=0; y< 4;y++) - sp[tempid].NoexpendReagent[y]=atoi(row[66+y]); - - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].formula[y]=atoi(row[70+y]); - - sp[tempid].goodEffect=atoi(row[83]); - sp[tempid].Activated=atoi(row[84]); - sp[tempid].resisttype=atoi(row[85]); - - for(y=0; y< EFFECT_COUNT;y++) - sp[tempid].effectid[y]=atoi(row[86+y]); - - sp[tempid].targettype = (SpellTargetType) atoi(row[98]); - sp[tempid].basediff=atoi(row[99]); - int tmp_skill = atoi(row[100]);; - if(tmp_skill < 0 || tmp_skill > HIGHEST_SKILL) - sp[tempid].skill = SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated - else - sp[tempid].skill = (SkillUseTypes) tmp_skill; - sp[tempid].zonetype=atoi(row[101]); - sp[tempid].EnvironmentType=atoi(row[102]); - sp[tempid].TimeOfDay=atoi(row[103]); - - for(y=0; y < PLAYER_CLASS_COUNT;y++) - sp[tempid].classes[y]=atoi(row[104+y]); - - sp[tempid].CastingAnim=atoi(row[120]); - sp[tempid].SpellAffectIndex=atoi(row[123]); - sp[tempid].disallow_sit=atoi(row[124]); - - for (y = 0; y < 16; y++) - sp[tempid].deities[y]=atoi(row[126+y]); - - sp[tempid].uninterruptable=atoi(row[146]); - sp[tempid].ResistDiff=atoi(row[147]); - sp[tempid].dot_stacking_exempt=atoi(row[148]); - sp[tempid].RecourseLink = atoi(row[150]); - sp[tempid].no_partial_resist = atoi(row[151]) != 0; - - sp[tempid].short_buff_box = atoi(row[154]); - sp[tempid].descnum = atoi(row[155]); - sp[tempid].effectdescnum = atoi(row[157]); - - sp[tempid].reflectable = atoi(row[161]) != 0; - sp[tempid].bonushate=atoi(row[162]); - - sp[tempid].EndurCost=atoi(row[166]); - sp[tempid].EndurTimerIndex=atoi(row[167]); - sp[tempid].HateAdded=atoi(row[173]); - sp[tempid].EndurUpkeep=atoi(row[174]); - sp[tempid].numhitstype = atoi(row[175]); - sp[tempid].numhits = atoi(row[176]); - sp[tempid].pvpresistbase=atoi(row[177]); - sp[tempid].pvpresistcalc=atoi(row[178]); - sp[tempid].pvpresistcap=atoi(row[179]); - sp[tempid].spell_category=atoi(row[180]); - sp[tempid].can_mgb=atoi(row[185]); - sp[tempid].dispel_flag = atoi(row[186]); - sp[tempid].MinResist = atoi(row[189]); - sp[tempid].MaxResist = atoi(row[190]); - sp[tempid].viral_targets = atoi(row[191]); - sp[tempid].viral_timer = atoi(row[192]); - sp[tempid].NimbusEffect = atoi(row[193]); - sp[tempid].directional_start = (float)atoi(row[194]); - sp[tempid].directional_end = (float)atoi(row[195]); - sp[tempid].not_extendable = atoi(row[197]) != 0; - sp[tempid].suspendable = atoi(row[200]) != 0; - sp[tempid].spellgroup=atoi(row[207]); - sp[tempid].powerful_flag=atoi(row[209]); - sp[tempid].CastRestriction = atoi(row[211]); - sp[tempid].AllowRest = atoi(row[212]) != 0; - sp[tempid].NotOutofCombat = atoi(row[213]) != 0; - sp[tempid].NotInCombat = atoi(row[214]) != 0; - sp[tempid].aemaxtargets = atoi(row[218]); - sp[tempid].maxtargets = atoi(row[219]); - sp[tempid].persistdeath = atoi(row[224]) != 0; - sp[tempid].DamageShieldType = 0; - } - mysql_free_result(result); - - LoadDamageShieldTypes(sp, max_spells); - } else { - _log(SPELLS__LOAD_ERR, "Error in LoadSpells query '%s' %s", query, errbuf); - safe_delete_array(query); - } -} - -int SharedDatabase::GetMaxBaseDataLevel() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = "SELECT MAX(level) FROM base_data"; - MYSQL_RES *result; - MYSQL_ROW row; - int32 ret = 0; - if(RunQuery(query, strlen(query), errbuf, &result)) { - row = mysql_fetch_row(result); - if(row) { - ret = atoi(row[0]); - mysql_free_result(result); - } else { - ret = -1; - mysql_free_result(result); - } - } else { - LogFile->write(EQEMuLog::Error, "Error in GetMaxBaseDataLevel query '%s' %s", query, errbuf); - ret = -1; - } - return ret; -} - -bool SharedDatabase::LoadBaseData() { - if(base_data_mmf) { - return true; - } - - try { - EQEmu::IPCMutex mutex("base_data"); - mutex.Lock(); - base_data_mmf = new EQEmu::MemoryMappedFile("shared/base_data"); - - int size = 16 * (GetMaxBaseDataLevel() + 1) * sizeof(BaseDataStruct); - if(size == 0) { - EQ_EXCEPT("SharedDatabase", "Base Data size is zero"); - } - - if(base_data_mmf->Size() != size) { - EQ_EXCEPT("SharedDatabase", "Couldn't load base data because base_data_mmf->Size() != size"); - } - - mutex.Unlock(); - } catch(std::exception& ex) { - LogFile->write(EQEMuLog::Error, "Error Loading Base Data: %s", ex.what()); - return false; - } - - return true; -} - -void SharedDatabase::LoadBaseData(void *data, int max_level) { - char *base_ptr = reinterpret_cast(data); - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = "SELECT * FROM base_data ORDER BY level, class ASC"; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query, strlen(query), errbuf, &result)) { - - int lvl = 0; - int cl = 0; - while (row = mysql_fetch_row(result)) { - lvl = atoi(row[0]); - cl = atoi(row[1]); - if(lvl <= 0) { - LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.level <= 0, ignoring."); - continue; - } - - if(lvl >= max_level) { - LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.level >= max_level, ignoring."); - continue; - } - - if(cl <= 0) { - LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.cl <= 0, ignoring."); - continue; - } - - if(cl > 16) { - LogFile->write(EQEMuLog::Error, "Non fatal error: base_data.class > 16, ignoring."); - continue; - } - - BaseDataStruct *bd = reinterpret_cast(base_ptr + (((16 * (lvl - 1)) + (cl - 1)) * sizeof(BaseDataStruct))); - bd->base_hp = atof(row[2]); - bd->base_mana = atof(row[3]); - bd->base_end = atof(row[4]); - bd->unk1 = atof(row[5]); - bd->unk2 = atof(row[6]); - bd->hp_factor = atof(row[7]); - bd->mana_factor = atof(row[8]); - bd->endurance_factor = atof(row[9]); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in LoadBaseData query '%s' %s", query, errbuf); - safe_delete_array(query); - } -} - -const BaseDataStruct* SharedDatabase::GetBaseData(int lvl, int cl) { - if(!base_data_mmf) { - return nullptr; - } - - if(lvl <= 0) { - return nullptr; - } - - if(cl <= 0) { - return nullptr; - } - - if(cl > 16) { - return nullptr; - } - - char *base_ptr = reinterpret_cast(base_data_mmf->Get()); - - uint32 offset = ((16 * (lvl - 1)) + (cl - 1)) * sizeof(BaseDataStruct); - - if(offset >= base_data_mmf->Size()) { - return nullptr; - } - - BaseDataStruct *bd = reinterpret_cast(base_ptr + offset); - return bd; -} - -void SharedDatabase::GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot_table, uint32 &loot_table_entries) { - loot_table_count = 0; - max_loot_table = 0; - loot_table_entries = 0; - const char *query = "SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM loottable_entries) FROM loottable"; - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query, strlen(query), errbuf, &result)) { - if(row = mysql_fetch_row(result)) { - loot_table_count = static_cast(atoul(row[0])); - max_loot_table = static_cast(atoul(row[1])); - loot_table_entries = static_cast(atoul(row[2])); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", query, errbuf); - } -} - -void SharedDatabase::GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_drop, uint32 &loot_drop_entries) { - loot_drop_count = 0; - max_loot_drop = 0; - loot_drop_entries = 0; - const char *query = "SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM lootdrop_entries) FROM lootdrop"; - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - if(RunQuery(query, strlen(query), errbuf, &result)) { - if(row = mysql_fetch_row(result)) { - loot_drop_count = static_cast(atoul(row[0])); - max_loot_drop = static_cast(atoul(row[1])); - loot_drop_entries = static_cast(atoul(row[2])); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", query, errbuf); - } -} - -void SharedDatabase::LoadLootTables(void *data, uint32 size) { - EQEmu::FixedMemoryVariableHashSet hash(reinterpret_cast(data), size); - const char *query = "SELECT loottable.id, loottable.mincash, loottable.maxcash, loottable.avgcoin," - " loottable_entries.lootdrop_id, loottable_entries.multiplier, loottable_entries.droplimit, " - "loottable_entries.mindrop, loottable_entries.probability FROM loottable LEFT JOIN loottable_entries" - " ON loottable.id = loottable_entries.loottable_id ORDER BY id"; - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - uint8 loot_table[sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128)]; - LootTable_Struct *lt = reinterpret_cast(loot_table); - - if(RunQuery(query, strlen(query), errbuf, &result)) { - uint32 current_id = 0; - uint32 current_entry = 0; - while(row = mysql_fetch_row(result)) { - uint32 id = static_cast(atoul(row[0])); - if(id != current_id) { - if(current_id != 0) { - hash.insert(current_id, loot_table, (sizeof(LootTable_Struct) + - (sizeof(LootTableEntries_Struct) * lt->NumEntries))); - } - - memset(loot_table, 0, sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128)); - current_entry = 0; - current_id = id; - lt->mincash = static_cast(atoul(row[1])); - lt->maxcash = static_cast(atoul(row[2])); - lt->avgcoin = static_cast(atoul(row[3])); - } - - if(current_entry > 128) { - continue; - } - - if(!row[4]) { - continue; - } - - lt->Entries[current_entry].lootdrop_id = static_cast(atoul(row[4])); - lt->Entries[current_entry].multiplier = static_cast(atoi(row[5])); - lt->Entries[current_entry].droplimit = static_cast(atoi(row[6])); - lt->Entries[current_entry].mindrop = static_cast(atoi(row[7])); - lt->Entries[current_entry].probability = static_cast(atof(row[8])); - - ++(lt->NumEntries); - ++current_entry; - } - if(current_id != 0) { - hash.insert(current_id, loot_table, (sizeof(LootTable_Struct) + - (sizeof(LootTableEntries_Struct) * lt->NumEntries))); - } - - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting loot table info from database: %s, %s", query, errbuf); - } -} - -void SharedDatabase::LoadLootDrops(void *data, uint32 size) { - EQEmu::FixedMemoryVariableHashSet hash(reinterpret_cast(data), size); - const char *query = "SELECT lootdrop.id, lootdrop_entries.item_id, lootdrop_entries.item_charges, " - "lootdrop_entries.equip_item, lootdrop_entries.chance, lootdrop_entries.minlevel, " - "lootdrop_entries.maxlevel, lootdrop_entries.multiplier FROM lootdrop JOIN lootdrop_entries " - "ON lootdrop.id = lootdrop_entries.lootdrop_id ORDER BY lootdrop_id"; - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - uint8 loot_drop[sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * 1260)]; - LootDrop_Struct *ld = reinterpret_cast(loot_drop); - if(RunQuery(query, strlen(query), errbuf, &result)) { - uint32 current_id = 0; - uint32 current_entry = 0; - while(row = mysql_fetch_row(result)) { - uint32 id = static_cast(atoul(row[0])); - if(id != current_id) { - if(current_id != 0) { - hash.insert(current_id, loot_drop, (sizeof(LootDrop_Struct) + - (sizeof(LootDropEntries_Struct) * ld->NumEntries))); - } - - memset(loot_drop, 0, sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * 1260)); - current_entry = 0; - current_id = id; - } - - if(current_entry >= 1260) { - continue; - } - - ld->Entries[current_entry].item_id = static_cast(atoul(row[1])); - ld->Entries[current_entry].item_charges = static_cast(atoi(row[2])); - ld->Entries[current_entry].equip_item = static_cast(atoi(row[3])); - ld->Entries[current_entry].chance = static_cast(atof(row[4])); - ld->Entries[current_entry].minlevel = static_cast(atoi(row[5])); - ld->Entries[current_entry].maxlevel = static_cast(atoi(row[6])); - ld->Entries[current_entry].multiplier = static_cast(atoi(row[7])); - - ++(ld->NumEntries); - ++current_entry; - } - if(current_id != 0) { - hash.insert(current_id, loot_drop, (sizeof(LootDrop_Struct) + - (sizeof(LootDropEntries_Struct) * ld->NumEntries))); - } - - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error getting loot drop info from database: %s, %s", query, errbuf); - } -} - -bool SharedDatabase::LoadLoot() { - if(loot_table_mmf || loot_drop_mmf) - return true; - - try { - EQEmu::IPCMutex mutex("loot"); - mutex.Lock(); - loot_table_mmf = new EQEmu::MemoryMappedFile("shared/loot_table"); - loot_table_hash = new EQEmu::FixedMemoryVariableHashSet( - reinterpret_cast(loot_table_mmf->Get()), - loot_table_mmf->Size()); - loot_drop_mmf = new EQEmu::MemoryMappedFile("shared/loot_drop"); - loot_drop_hash = new EQEmu::FixedMemoryVariableHashSet( - reinterpret_cast(loot_drop_mmf->Get()), - loot_drop_mmf->Size()); - mutex.Unlock(); - } catch(std::exception &ex) { - LogFile->write(EQEMuLog::Error, "Error loading loot: %s", ex.what()); - return false; - } - - return true; -} - -const LootTable_Struct* SharedDatabase::GetLootTable(uint32 loottable_id) { - if(!loot_table_hash) - return nullptr; - - try { - if(loot_table_hash->exists(loottable_id)) { - return &loot_table_hash->at(loottable_id); - } - } catch(std::exception &ex) { - LogFile->write(EQEMuLog::Error, "Could not get loot table: %s", ex.what()); - } - return nullptr; -} - -const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) { - if(!loot_drop_hash) - return nullptr; - - try { - if(loot_drop_hash->exists(lootdrop_id)) { - return &loot_drop_hash->at(lootdrop_id); - } - } catch(std::exception &ex) { - LogFile->write(EQEMuLog::Error, "Could not get loot drop: %s", ex.what()); - } - return nullptr; -} - -void SharedDatabase::GetPlayerInspectMessage(char* playername, InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT inspectmessage FROM character_ WHERE name='%s'", playername), errbuf, &result)) { - safe_delete_array(query); - - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - memcpy(message, row[0], sizeof(InspectMessage_Struct)); - } - - mysql_free_result(result); - } - else { - std::cerr << "Error in GetPlayerInspectMessage query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } -} - -void SharedDatabase::SetPlayerInspectMessage(char* playername, const InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET inspectmessage='%s' WHERE name='%s'", message->text, playername), errbuf)) { - std::cerr << "Error in SetPlayerInspectMessage query '" << query << "' " << errbuf << std::endl; - } - - safe_delete_array(query); -} - -void SharedDatabase::GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT BotInspectMessage FROM bots WHERE BotID=%i", botid), errbuf, &result)) { - safe_delete_array(query); - - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - memcpy(message, row[0], sizeof(InspectMessage_Struct)); - } - - mysql_free_result(result); - } - else { - std::cerr << "Error in GetBotInspectMessage query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - } -} - -void SharedDatabase::SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message) { - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE bots SET BotInspectMessage='%s' WHERE BotID=%i", message->text, botid), errbuf)) { - std::cerr << "Error in SetBotInspectMessage query '" << query << "' " << errbuf << std::endl; - } - - safe_delete_array(query); -} diff --git a/utils/sql/git/required/2014_02_12_spells_new_update.sql b/utils/sql/git/required/2014_02_12_spells_new_update.sql deleted file mode 100644 index ba552e1ed..000000000 --- a/utils/sql/git/required/2014_02_12_spells_new_update.sql +++ /dev/null @@ -1,13 +0,0 @@ -ALTER TABLE `spells_new` CHANGE `field161` `not_reflectable` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field151` `no_partial_resist` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field189` `MinResist` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field190` `MaxResist` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field194` `ConeStartAngle` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field195` `ConeStopAngle` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field208` `rank` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field159` `npc_no_los` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field213` `NotOutofCombat` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field214` `NotInCombat` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field168` `IsDiscipline` INT(11) NOT NULL DEFAULT '0'; -ALTER TABLE `spells_new` CHANGE `field211` `CastRestrict` INT(11) NOT NULL DEFAULT '0'; - diff --git a/utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql b/utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql deleted file mode 100644 index 12e9963a5..000000000 --- a/utils/sql/git/required/2014_04_10_No_Target_With_Hotkey - Copy.sql +++ /dev/null @@ -1,3 +0,0 @@ -ALTER TABLE `npc_types` ADD `no_target_hotkey` tinyint( 1 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `healscale`; - - diff --git a/utils/sql/git/required/2014_06_22_MetabolismAAs.sql b/utils/sql/git/required/2014_06_22_MetabolismAAs.sql deleted file mode 100644 index 3a957edb2..000000000 --- a/utils/sql/git/required/2014_06_22_MetabolismAAs.sql +++ /dev/null @@ -1,6 +0,0 @@ --- Innate Metabolism -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('68', '1', '233', '110', '0'); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('69', '1', '233', '125', '0'); -INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('70', '1', '233', '150', '0'); - - diff --git a/zone/AA_base.cpp b/zone/AA_base.cpp deleted file mode 100644 index 8566c09b5..000000000 --- a/zone/AA_base.cpp +++ /dev/null @@ -1,1990 +0,0 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -// Test 1 - -#include "../common/debug.h" -#include "AA.h" -#include "mob.h" -#include "client.h" -#include "groups.h" -#include "raids.h" -#include "../common/spdat.h" -#include "object.h" -#include "doors.h" -#include "beacon.h" -#include "corpse.h" -#include "titles.h" -#include "../common/races.h" -#include "../common/classes.h" -#include "../common/eq_packet_structs.h" -#include "../common/packet_dump.h" -#include "../common/StringUtil.h" -#include "../common/logsys.h" -#include "zonedb.h" -#include "StringIDs.h" - -//static data arrays, really not big enough to warrant shared mem. -AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank] -std::mapaas_send; -std::map > aa_effects; //stores the effects from the aa_effects table in memory -std::map AARequiredLevelAndCost; - -/* - - -Schema: - -spell_id is spell to cast, SPELL_UNKNOWN == no spell -nonspell_action is action to preform on activation which is not a spell, 0=none -nonspell_mana is mana that the nonspell action consumes -nonspell_duration is a duration which may be used by the nonspell action -redux_aa is the aa which reduces the reuse timer of the skill -redux_rate is the multiplier of redux_aa, as a percentage of total rate (10 == 10% faster) - -CREATE TABLE aa_actions ( - aaid mediumint unsigned not null, - rank tinyint unsigned not null, - reuse_time mediumint unsigned not null, - spell_id mediumint unsigned not null, - target tinyint unsigned not null, - nonspell_action tinyint unsigned not null, - nonspell_mana mediumint unsigned not null, - nonspell_duration mediumint unsigned not null, - redux_aa mediumint unsigned not null, - redux_rate tinyint not null, - - PRIMARY KEY(aaid, rank) -); - -CREATE TABLE aa_swarmpets ( - spell_id mediumint unsigned not null, - count tinyint unsigned not null, - npc_id int not null, - duration mediumint unsigned not null, - PRIMARY KEY(spell_id) -); -*/ - -/* - -Credits for this function: - -FatherNitwit: Structure and mechanism - -Wiz: Initial set of AAs, original function contents - -Branks: Much updated info and a bunch of higher-numbered AAs - -*/ -int Client::GetAATimerID(aaID activate) -{ - SendAA_Struct* aa2 = zone->FindAA(activate); - - if(!aa2) - { - for(int i = 1;i < MAX_AA_ACTION_RANKS; ++i) - { - int a = activate - i; - - if(a <= 0) - break; - - aa2 = zone->FindAA(a); - - if(aa2 != nullptr) - break; - } - } - - if(aa2) - return aa2->spell_type; - - return 0; -} - -int Client::CalcAAReuseTimer(const AA_DBAction *caa) { - - if(!caa) - return 0; - - int ReuseTime = caa->reuse_time; - - if(ReuseTime > 0) - { - int ReductionPercentage; - - if(caa->redux_aa > 0 && caa->redux_aa < aaHighestID) - { - ReductionPercentage = GetAA(caa->redux_aa) * caa->redux_rate; - - if(caa->redux_aa2 > 0 && caa->redux_aa2 < aaHighestID) - ReductionPercentage += (GetAA(caa->redux_aa2) * caa->redux_rate2); - - ReuseTime = caa->reuse_time * (100 - ReductionPercentage) / 100; - } - - } - return ReuseTime; -} - -void Client::ActivateAA(aaID activate){ - if(activate < 0 || activate >= aaHighestID) - return; - if(IsStunned() || IsFeared() || IsMezzed() || IsSilenced() || IsPet() || IsSitting() || GetFeigned()) - return; - - int AATimerID = GetAATimerID(activate); - - SendAA_Struct* aa2 = nullptr; - aaID aaid = activate; - uint8 activate_val = GetAA(activate); - //this wasn't taking into acct multi tiered act talents before... - if(activate_val == 0){ - aa2 = zone->FindAA(activate); - if(!aa2){ - int i; - int a; - for(i=1;iFindAA(a); - if(aa2 != nullptr) - break; - } - } - if(aa2){ - aaid = (aaID) aa2->id; - activate_val = GetAA(aa2->id); - } - } - - if (activate_val == 0){ - return; - } - - if(aa2) - { - if(aa2->account_time_required) - { - if((Timer::GetTimeSeconds() + account_creation) < aa2->account_time_required) - { - return; - } - } - } - - if(!p_timers.Expired(&database, AATimerID + pTimerAAStart)) - { - uint32 aaremain = p_timers.GetRemainingTime(AATimerID + pTimerAAStart); - uint32 aaremain_hr = aaremain / (60 * 60); - uint32 aaremain_min = (aaremain / 60) % 60; - uint32 aaremain_sec = aaremain % 60; - - if(aa2) { - if (aaremain_hr >= 1) //1 hour or more - Message(13, "You can use the ability %s again in %u hour(s) %u minute(s) %u seconds", - aa2->name, aaremain_hr, aaremain_min, aaremain_sec); - else //less than an hour - Message(13, "You can use the ability %s again in %u minute(s) %u seconds", - aa2->name, aaremain_min, aaremain_sec); - } else { - if (aaremain_hr >= 1) //1 hour or more - Message(13, "You can use this ability again in %u hour(s) %u minute(s) %u seconds", - aaremain_hr, aaremain_min, aaremain_sec); - else //less than an hour - Message(13, "You can use this ability again in %u minute(s) %u seconds", - aaremain_min, aaremain_sec); - } - return; - } - - if(activate_val > MAX_AA_ACTION_RANKS) - activate_val = MAX_AA_ACTION_RANKS; - activate_val--; //to get array index. - - //get our current node, now that the indices are well bounded - const AA_DBAction *caa = &AA_Actions[aaid][activate_val]; - - if((aaid == aaImprovedHarmTouch || aaid == aaLeechTouch) && !p_timers.Expired(&database, pTimerHarmTouch)){ - Message(13,"Ability recovery time not yet met."); - return; - } - - //everything should be configured out now - - uint16 target_id = 0; - - //figure out our target - switch(caa->target) { - case aaTargetUser: - case aaTargetGroup: - target_id = GetID(); - break; - case aaTargetCurrent: - case aaTargetCurrentGroup: - if(GetTarget() == nullptr) { - Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - target_id = GetTarget()->GetID(); - break; - case aaTargetPet: - if(GetPet() == nullptr) { - Message(0, "A pet is required for this skill."); - return; - } - target_id = GetPetID(); - break; - } - - //handle non-spell action - if(caa->action != aaActionNone) { - if(caa->mana_cost > 0) { - if(GetMana() < caa->mana_cost) { - Message_StringID(13, INSUFFICIENT_MANA); - return; - } - SetMana(GetMana() - caa->mana_cost); - } - if(caa->reuse_time > 0) - { - uint32 timer_base = CalcAAReuseTimer(caa); - if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) - { - p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); - } - p_timers.Start(AATimerID + pTimerAAStart, timer_base); - SendAATimer(AATimerID, 0, 0); - } - HandleAAAction(aaid); - } - - //cast the spell, if we have one - if(caa->spell_id > 0 && caa->spell_id < SPDAT_RECORDS) { - - if(caa->reuse_time > 0) - { - uint32 timer_base = CalcAAReuseTimer(caa); - SendAATimer(AATimerID, 0, 0); - p_timers.Start(AATimerID + pTimerAAStart, timer_base); - if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) - { - p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); - } - // Bards can cast instant cast AAs while they are casting another song - if (spells[caa->spell_id].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { - if(!SpellFinished(caa->spell_id, entity_list.GetMob(target_id), 10, -1, -1, spells[caa->spell_id].ResistDiff, false)) { - //Reset on failed cast - SendAATimer(AATimerID, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - } else { - if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { - //Reset on failed cast - SendAATimer(AATimerID, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - } - } - else - { - if(!CastSpell(caa->spell_id, target_id)) - return; - } - } - // Check if AA is expendable - if (aas_send[activate - activate_val]->special_category == 7) - { - // Add the AA cost to the extended profile to track overall total - m_epp.expended_aa += aas_send[activate]->cost; - SetAA(activate, 0); - - Save(); - SendAA(activate); - SendAATable(); - } -} - -void Client::HandleAAAction(aaID activate) { - if(activate < 0 || activate >= aaHighestID) - return; - - uint8 activate_val = GetAA(activate); - - if (activate_val == 0) - return; - - if(activate_val > MAX_AA_ACTION_RANKS) - activate_val = MAX_AA_ACTION_RANKS; - activate_val--; //to get array index. - - //get our current node, now that the indices are well bounded - const AA_DBAction *caa = &AA_Actions[activate][activate_val]; - - uint16 timer_id = 0; - uint16 timer_duration = caa->duration; - aaTargetType target = aaTargetUser; - - uint16 spell_id = SPELL_UNKNOWN; //gets cast at the end if not still unknown - - switch(caa->action) { - case aaActionAETaunt: - entity_list.AETaunt(this); - break; - - case aaActionMassBuff: - EnableAAEffect(aaEffectMassGroupBuff, 3600); - Message_StringID(MT_Disciplines, MGB_STRING); //The next group buff you cast will hit all targets in range. - break; - - case aaActionFlamingArrows: - //toggle it - if(CheckAAEffect(aaEffectFlamingArrows)) - EnableAAEffect(aaEffectFlamingArrows); - else - DisableAAEffect(aaEffectFlamingArrows); - break; - - case aaActionFrostArrows: - if(CheckAAEffect(aaEffectFrostArrows)) - EnableAAEffect(aaEffectFrostArrows); - else - DisableAAEffect(aaEffectFrostArrows); - break; - - case aaActionRampage: - EnableAAEffect(aaEffectRampage, 10); - break; - - case aaActionSharedHealth: - if(CheckAAEffect(aaEffectSharedHealth)) - EnableAAEffect(aaEffectSharedHealth); - else - DisableAAEffect(aaEffectSharedHealth); - break; - - case aaActionCelestialRegen: { - //special because spell_id depends on a different AA - switch (GetAA(aaCelestialRenewal)) { - case 1: - spell_id = 3250; - break; - case 2: - spell_id = 3251; - break; - default: - spell_id = 2740; - break; - } - target = aaTargetCurrent; - break; - } - - case aaActionDireCharm: { - //special because spell_id depends on class - switch (GetClass()) - { - case DRUID: - spell_id = 2760; //2644? - break; - case NECROMANCER: - spell_id = 2759; //2643? - break; - case ENCHANTER: - spell_id = 2761; //2642? - break; - } - target = aaTargetCurrent; - break; - } - - case aaActionImprovedFamiliar: { - //Spell IDs might be wrong... - if (GetAA(aaAllegiantFamiliar)) - spell_id = 3264; //1994? - else - spell_id = 2758; //2155? - break; - } - - case aaActionActOfValor: - if(GetTarget() != nullptr) { - int curhp = GetTarget()->GetHP(); - target = aaTargetCurrent; - GetTarget()->HealDamage(curhp, this); - Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); - } - break; - - case aaActionSuspendedMinion: - if (GetPet()) { - target = aaTargetPet; - switch (GetAA(aaSuspendedMinion)) { - case 1: - spell_id = 3248; - break; - case 2: - spell_id = 3249; - break; - } - //do we really need to cast a spell? - - Message(0,"You call your pet to your side."); - GetPet()->WipeHateList(); - GetPet()->GMMove(GetX(),GetY(),GetZ()); - if (activate_val > 1) - entity_list.ClearFeignAggro(GetPet()); - } else { - Message(0,"You have no pet to call."); - } - break; - - case aaActionProjectIllusion: - EnableAAEffect(aaEffectProjectIllusion, 3600); - Message(10, "The power of your next illusion spell will flow to your grouped target in your place."); - break; - - - case aaActionEscape: - Escape(); - break; - - // Don't think this code is used any longer for Bestial Alignment as the AA has a spell_id and no nonspell_action. - case aaActionBeastialAlignment: - switch(GetBaseRace()) { - case BARBARIAN: - spell_id = AA_Choose3(activate_val, 4521, 4522, 4523); - break; - case TROLL: - spell_id = AA_Choose3(activate_val, 4524, 4525, 4526); - break; - case OGRE: - spell_id = AA_Choose3(activate_val, 4527, 4527, 4529); - break; - case IKSAR: - spell_id = AA_Choose3(activate_val, 4530, 4531, 4532); - break; - case VAHSHIR: - spell_id = AA_Choose3(activate_val, 4533, 4534, 4535); - break; - } - - case aaActionLeechTouch: - target = aaTargetCurrent; - spell_id = SPELL_HARM_TOUCH2; - EnableAAEffect(aaEffectLeechTouch, 1000); - break; - - case aaActionFadingMemories: - // Do nothing since spell effect works correctly, but mana isn't used. - break; - - default: - LogFile->write(EQEMuLog::Error, "Unknown AA nonspell action type %d", caa->action); - return; - } - - - uint16 target_id = 0; - //figure out our target - switch(target) { - case aaTargetUser: - case aaTargetGroup: - target_id = GetID(); - break; - case aaTargetCurrent: - case aaTargetCurrentGroup: - if(GetTarget() == nullptr) { - Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! - p_timers.Clear(&database, timer_id + pTimerAAEffectStart); - return; - } - target_id = GetTarget()->GetID(); - break; - case aaTargetPet: - if(GetPet() == nullptr) { - Message(0, "A pet is required for this skill."); - return; - } - target_id = GetPetID(); - break; - } - - //cast the spell, if we have one - if(IsValidSpell(spell_id)) { - int aatid = GetAATimerID(activate); - if(!CastSpell(spell_id, target_id , 10, -1, -1, 0, -1, pTimerAAStart + aatid , CalcAAReuseTimer(caa), 1)) { - SendAATimer(aatid, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, pTimerAAStart + aatid); - return; - } - } - - //handle the duration timer if we have one. - if(timer_id > 0 && timer_duration > 0) { - p_timers.Start(pTimerAAEffectStart + timer_id, timer_duration); - } -} - - -//Originally written by Branks -//functionality rewritten by Father Nitwit -void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override) { - - //It might not be a bad idea to put these into the database, eventually.. - - //Dook- swarms and wards - - PetRecord record; - if(!database.GetPetEntry(spells[spell_id].teleport_zone, &record)) - { - LogFile->write(EQEMuLog::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id); - Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone); - return; - } - - AA_SwarmPet pet; - pet.count = 1; - pet.duration = 1; - - for(int x = 0; x < 12; x++) - { - if(spells[spell_id].effectid[x] == SE_TemporaryPets) - { - pet.count = spells[spell_id].base[x]; - pet.duration = spells[spell_id].max[x]; - } - } - - if(IsClient()) - pet.duration += (CastToClient()->GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000); - - pet.npc_id = record.npc_type; - - NPCType *made_npc = nullptr; - - const NPCType *npc_type = database.GetNPCType(pet.npc_id); - if(npc_type == nullptr) { - //log write - LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet spell id: %d", spell_id); - Message(0,"Unable to find pet!"); - return; - } - - if(name_override != nullptr) { - //we have to make a custom NPC type for this name change - made_npc = new NPCType; - memcpy(made_npc, npc_type, sizeof(NPCType)); - strcpy(made_npc->name, name_override); - npc_type = made_npc; - } - - int summon_count = 0; - summon_count = pet.count; - - if(summon_count > MAX_SWARM_PETS) - summon_count = MAX_SWARM_PETS; - - static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, - 10, -10, 10, -10, - 8, -8, 8, -8 }; - static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, - 10, 10, -10, -10, - 8, 8, -8, -8 }; - TempPets(true); - - while(summon_count > 0) { - int pet_duration = pet.duration; - if(duration_override > 0) - pet_duration = duration_override; - - //this is a little messy, but the only way to do it right - //it would be possible to optimize out this copy for the last pet, but oh well - NPCType *npc_dup = nullptr; - if(made_npc != nullptr) { - npc_dup = new NPCType; - memcpy(npc_dup, made_npc, sizeof(NPCType)); - } - - NPC* npca = new NPC( - (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer - 0, - GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], - GetZ(), GetHeading(), FlyMode3); - - if((spell_id == 6882) || (spell_id == 6884)) - npca->SetFollowID(GetID()); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); - } - - //removing this prevents the pet from attacking - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pets somebody to "love" - if(targ != nullptr){ - npca->AddToHateList(targ, 1000, 1000); - npca->GetSwarmInfo()->target = targ->GetID(); - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); - - entity_list.AddNPC(npca, true, true); - summon_count--; - } - - //the target of these swarm pets will take offense to being cast on... - if(targ != nullptr) - targ->AddToHateList(this, 1, 0); -} - -void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_override, uint32 duration_override, bool followme) { - - AA_SwarmPet pet; - pet.count = 1; - pet.duration = 1; - - pet.npc_id = typesid; - - NPCType *made_npc = nullptr; - - const NPCType *npc_type = database.GetNPCType(typesid); - if(npc_type == nullptr) { - //log write - LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet type id: %d", typesid); - Message(0,"Unable to find pet!"); - return; - } - - if(name_override != nullptr) { - //we have to make a custom NPC type for this name change - made_npc = new NPCType; - memcpy(made_npc, npc_type, sizeof(NPCType)); - strcpy(made_npc->name, name_override); - npc_type = made_npc; - } - - int summon_count = 0; - summon_count = pet.count; - - if(summon_count > MAX_SWARM_PETS) - summon_count = MAX_SWARM_PETS; - - static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, - 10, -10, 10, -10, - 8, -8, 8, -8 }; - static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, - 10, 10, -10, -10, - 8, 8, -8, -8 }; - TempPets(true); - - while(summon_count > 0) { - int pet_duration = pet.duration; - if(duration_override > 0) - pet_duration = duration_override; - - //this is a little messy, but the only way to do it right - //it would be possible to optimize out this copy for the last pet, but oh well - NPCType *npc_dup = nullptr; - if(made_npc != nullptr) { - npc_dup = new NPCType; - memcpy(npc_dup, made_npc, sizeof(NPCType)); - } - - NPC* npca = new NPC( - (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer - 0, - GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], - GetZ(), GetHeading(), FlyMode3); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); - } - - //removing this prevents the pet from attacking - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pets somebody to "love" - if(targ != nullptr){ - npca->AddToHateList(targ, 1000, 1000); - npca->GetSwarmInfo()->target = targ->GetID(); - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); - - entity_list.AddNPC(npca, true, true); - summon_count--; - } -} - -void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) -{ - Corpse *CorpseToUse = nullptr; - CorpseToUse = entity_list.GetClosestCorpse(this, nullptr); - - if(!CorpseToUse) - return; - - //assuming we have pets in our table; we take the first pet as a base type. - const NPCType *base_type = database.GetNPCType(500); - NPCType *make_npc = new NPCType; - memcpy(make_npc, base_type, sizeof(NPCType)); - - //combat stats - make_npc->AC = ((GetLevel() * 7) + 550); - make_npc->ATK = GetLevel(); - make_npc->max_dmg = (GetLevel() * 4) + 2; - make_npc->min_dmg = 1; - - //base stats - make_npc->cur_hp = (GetLevel() * 55); - make_npc->max_hp = (GetLevel() * 55); - make_npc->STR = 85 + (GetLevel() * 3); - make_npc->STA = 85 + (GetLevel() * 3); - make_npc->DEX = 85 + (GetLevel() * 3); - make_npc->AGI = 85 + (GetLevel() * 3); - make_npc->INT = 85 + (GetLevel() * 3); - make_npc->WIS = 85 + (GetLevel() * 3); - make_npc->CHA = 85 + (GetLevel() * 3); - make_npc->MR = 25; - make_npc->FR = 25; - make_npc->CR = 25; - make_npc->DR = 25; - make_npc->PR = 25; - - //level class and gender - make_npc->level = GetLevel(); - make_npc->class_ = CorpseToUse->class_; - make_npc->race = CorpseToUse->race; - make_npc->gender = CorpseToUse->gender; - make_npc->loottable_id = 0; - //name - char NewName[64]; - sprintf(NewName, "%s`s Animated Corpse", GetCleanName()); - strcpy(make_npc->name, NewName); - - //appearance - make_npc->beard = CorpseToUse->beard; - make_npc->beardcolor = CorpseToUse->beardcolor; - make_npc->eyecolor1 = CorpseToUse->eyecolor1; - make_npc->eyecolor2 = CorpseToUse->eyecolor2; - make_npc->haircolor = CorpseToUse->haircolor; - make_npc->hairstyle = CorpseToUse->hairstyle; - make_npc->helmtexture = CorpseToUse->helmtexture; - make_npc->luclinface = CorpseToUse->luclinface; - make_npc->size = CorpseToUse->size; - make_npc->texture = CorpseToUse->texture; - - //cast stuff.. based off of PEQ's if you want to change - //it you'll have to mod this code, but most likely - //most people will be using PEQ style for the first - //part of their spell list; can't think of any smooth - //way to do this - //some basic combat mods here too since it's convienent - switch(CorpseToUse->class_) - { - case CLERIC: - make_npc->npc_spells_id = 1; - break; - case WIZARD: - make_npc->npc_spells_id = 2; - break; - case NECROMANCER: - make_npc->npc_spells_id = 3; - break; - case MAGICIAN: - make_npc->npc_spells_id = 4; - break; - case ENCHANTER: - make_npc->npc_spells_id = 5; - break; - case SHAMAN: - make_npc->npc_spells_id = 6; - break; - case DRUID: - make_npc->npc_spells_id = 7; - break; - case PALADIN: - //SPECATK_TRIPLE - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 150 / 100; - make_npc->max_hp = make_npc->max_hp * 150 / 100; - make_npc->npc_spells_id = 8; - break; - case SHADOWKNIGHT: - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 150 / 100; - make_npc->max_hp = make_npc->max_hp * 150 / 100; - make_npc->npc_spells_id = 9; - break; - case RANGER: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->cur_hp = make_npc->cur_hp * 135 / 100; - make_npc->max_hp = make_npc->max_hp * 135 / 100; - make_npc->npc_spells_id = 10; - break; - case BARD: - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - make_npc->npc_spells_id = 11; - break; - case BEASTLORD: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - make_npc->npc_spells_id = 12; - break; - case ROGUE: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - break; - case MONK: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 135 / 100; - make_npc->max_hp = make_npc->max_hp * 135 / 100; - break; - case WARRIOR: - case BERSERKER: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 175 / 100; - make_npc->max_hp = make_npc->max_hp * 175 / 100; - break; - default: - make_npc->npc_spells_id = 0; - break; - } - - make_npc->loottable_id = 0; - make_npc->merchanttype = 0; - make_npc->d_meele_texture1 = 0; - make_npc->d_meele_texture2 = 0; - - TempPets(true); - - NPC* npca = new NPC(make_npc, 0, GetX(), GetY(), GetZ(), GetHeading(), FlyMode3); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(duration*1000); - } - - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pet somebody to "love" - if(target != nullptr){ - npca->AddToHateList(target, 100000); - npca->GetSwarmInfo()->target = target->GetID(); - } - - //gear stuff, need to make sure there's - //no situation where this stuff can be duped - for(int x = 0; x < 21; x++) - { - uint32 sitem = 0; - sitem = CorpseToUse->GetWornItem(x); - if(sitem){ - const Item_Struct * itm = database.GetItem(sitem); - npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 127, true, true); - } - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(make_npc != nullptr) - npca->GiveNPCTypeData(make_npc); - - entity_list.AddNPC(npca, true, true); - - //the target of these swarm pets will take offense to being cast on... - if(target != nullptr) - target->AddToHateList(this, 1, 0); -} - -//turn on an AA effect -//duration == 0 means no time limit, used for one-shot deals, etc.. -void Client::EnableAAEffect(aaEffectType type, uint32 duration) { - if(type > 32) - return; //for now, special logic needed. - m_epp.aa_effects |= 1 << (type-1); - - if(duration > 0) { - p_timers.Start(pTimerAAEffectStart + type, duration); - } else { - p_timers.Clear(&database, pTimerAAEffectStart + type); - } -} - -void Client::DisableAAEffect(aaEffectType type) { - if(type > 32) - return; //for now, special logic needed. - uint32 bit = 1 << (type-1); - if(m_epp.aa_effects & bit) { - m_epp.aa_effects ^= bit; - } - p_timers.Clear(&database, pTimerAAEffectStart + type); -} - -/* -By default an AA effect is a one shot deal, unless -a duration timer is set. -*/ -bool Client::CheckAAEffect(aaEffectType type) { - if(type > 32) - return(false); //for now, special logic needed. - if(m_epp.aa_effects & (1 << (type-1))) { //is effect enabled? - //has our timer expired? - if(p_timers.Expired(&database, pTimerAAEffectStart + type)) { - DisableAAEffect(type); - return(false); - } - return(true); - } - return(false); -} - -void Client::SendAAStats() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); - AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer; - aps->experience = m_pp.expAA; - aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP); - aps->unspent = m_pp.aapoints; - aps->percentage = m_epp.perAA; - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::BuyAA(AA_Action* action) -{ - mlog(AA__MESSAGE, "Starting to buy AA %d", action->ability); - - //find the AA information from the database - SendAA_Struct* aa2 = zone->FindAA(action->ability); - if(!aa2) { - //hunt for a lower level... - int i; - int a; - for(i=1;iability - i; - if(a <= 0) - break; - mlog(AA__MESSAGE, "Could not find AA %d, trying potential parent %d", action->ability, a); - aa2 = zone->FindAA(a); - if(aa2 != nullptr) - break; - } - } - if(aa2 == nullptr) - return; //invalid ability... - - if(aa2->special_category == 1 || aa2->special_category == 2) - return; // Not purchasable progression style AAs - - if(aa2->special_category == 8 && aa2->cost == 0) - return; // Not purchasable racial AAs(set a cost to make them purchasable) - - uint32 cur_level = GetAA(aa2->id); - if((aa2->id + cur_level) != action->ability) { //got invalid AA - mlog(AA__ERROR, "Unable to find or match AA %d (found %d + lvl %d)", action->ability, aa2->id, cur_level); - return; - } - - if(aa2->account_time_required) - { - if((Timer::GetTimeSeconds() - account_creation) < aa2->account_time_required) - { - return; - } - } - - uint32 real_cost; - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); - - if(RequiredLevel != AARequiredLevelAndCost.end()) - { - real_cost = RequiredLevel->second.Cost; - } - else - real_cost = aa2->cost + (aa2->cost_inc * cur_level); - - if(m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { - SetAA(aa2->id, cur_level+1); - - mlog(AA__MESSAGE, "Set AA %d to level %d", aa2->id, cur_level+1); - - m_pp.aapoints -= real_cost; - - Save(); - if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u)) - && ((aa2->max_level == (cur_level+1)) && aa2->sof_next_id)){ - SendAA(aa2->id); - SendAA(aa2->sof_next_id); - } - else - SendAA(aa2->id); - - SendAATable(); - - //we are building these messages ourself instead of using the stringID to work around patch discrepencies - //these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2 - if(cur_level<1) - Message(15,"You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1)?"points":"point"); - else - Message(15,"You have improved %s %d at a cost of %d ability %s.", aa2->name, cur_level+1, real_cost, (real_cost>1)?"points":"point"); - - - SendAAStats(); - - CalcBonuses(); - if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) - NotifyNewTitlesAvailable(); - } -} - -void Client::SendAATimer(uint32 ability, uint32 begin, uint32 end) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); - UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; - uaaout->ability = ability; - uaaout->begin = begin; - uaaout->end = end; - QueuePacket(outapp); - safe_delete(outapp); -} - -//sends all AA timers. -void Client::SendAATimers() { - //we dont use SendAATimer because theres no reason to allocate the EQApplicationPacket every time - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); - UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; - - PTimerList::iterator c,e; - c = p_timers.begin(); - e = p_timers.end(); - for(; c != e; ++c) { - PersistentTimer *cur = c->second; - if(cur->GetType() < pTimerAAStart || cur->GetType() > pTimerAAEnd) - continue; //not an AA timer - //send timer - uaaout->begin = cur->GetStartTime(); - uaaout->end = static_cast(time(nullptr)); - uaaout->ability = cur->GetType() - pTimerAAStart; // uuaaout->ability is really a shared timer number - QueuePacket(outapp); - } - - safe_delete(outapp); -} - -void Client::SendAATable() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); - - AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; - aa2->aa_spent = GetAAPointsSpent(); - - uint32 i; - for(i=0;i < MAX_PP_AA_ARRAY;i++){ - aa2->aa_list[i].aa_skill = aa[i]->AA; - aa2->aa_list[i].aa_value = aa[i]->value; - aa2->aa_list[i].unknown08 = 0; - } - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendPreviousAA(uint32 id, int seq){ - uint32 value=0; - SendAA_Struct* saa2 = nullptr; - if(id==0) - saa2 = zone->GetAABySequence(seq); - else - saa2 = zone->FindAA(id); - if(!saa2) - return; - int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; - uchar* buffer = new uchar[size]; - SendAA_Struct* saa=(SendAA_Struct*)buffer; - value = GetAA(saa2->id); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); - outapp->size=size; - outapp->pBuffer=(uchar*)saa; - value--; - memcpy(saa,saa2,size); - - if(value>0){ - if(saa->spellid==0) - saa->spellid=0xFFFFFFFF; - saa->id+=value; - saa->next_id=saa->id+1; - if(value==1) - saa->last_id=saa2->id; - else - saa->last_id=saa->id-1; - saa->current_level=value+1; - saa->cost2 = 0; //cost 2 is what the client uses to calc how many points we've spent, so we have to add up the points in order - for(uint32 i = 0; i < (value+1); i++) { - saa->cost2 += saa->cost + (saa->cost_inc * i); - } - } - - database.FillAAEffects(saa); - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendAA(uint32 id, int seq) { - - uint32 value=0; - SendAA_Struct* saa2 = nullptr; - SendAA_Struct* qaa = nullptr; - SendAA_Struct* saa_pp = nullptr; - bool IsBaseLevel = true; - bool aa_stack = false; - - if(id==0) - saa2 = zone->GetAABySequence(seq); - else - saa2 = zone->FindAA(id); - if(!saa2) - return; - - uint16 classes = saa2->classes; - if(!(classes & (1 << GetClass())) && (GetClass()!=BERSERKER || saa2->berserker==0)){ - return; - } - - if(saa2->account_time_required) - { - if((Timer::GetTimeSeconds() - account_creation) < saa2->account_time_required) - { - return; - } - } - - // Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). - if (saa2->special_category == 1 || saa2->special_category == 2 ) { - if(GetAA(saa2->id) == 0) - return; - // For Quest line AA(demiplane AEs) where only 1 is visible at a time, check to make sure only the highest level obtained is shown - if(saa2->aa_expansion > 0) { - qaa = zone->FindAA(saa2->id+1); - if(qaa && (saa2->aa_expansion == qaa->aa_expansion) && GetAA(qaa->id) > 0) - return; - } - } - -/* Beginning of Shroud AAs, these categories are for Passive and Active Shroud AAs - Eventually with a toggle we could have it show player list or shroud list - if (saa2->special_category == 3 || saa2->special_category == 4) - return; -*/ - // Check for racial/Drakkin blood line AAs - if (saa2->special_category == 8) - { - uint32 client_race = this->GetBaseRace(); - - // Drakkin Bloodlines - if (saa2->aa_expansion > 522) - { - if (client_race != 522) - return; // Check for Drakkin Race - - int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline - - if (heritage != saa2->aa_expansion) - return; - } - // Racial AAs - else if (client_race != saa2->aa_expansion) - { - return; - } - } - - /* - AA stacking on SoF+ clients. - - Note: There were many ways to achieve this effect - The method used proved to be the most straight forward and consistent. - Stacking does not currently work ideally for AA's that use hotkeys, therefore they will be excluded at this time. - - TODO: Problem with AA hotkeys - When you reach max rank of an AA tier (ie 5/5), it automatically displays the next AA in - the series and you can not transfer the hotkey to the next AA series. To the best of the my ability and through many - different variations of coding I could not find an ideal solution to this issue. - - How stacking works: - Utilizes two new fields: sof_next_id (which is the next id in the series), sof_current_level (ranks the AA's as the current level) - 1) If no AA's purchased only display the base levels of each AA series. - 2) When you purchase an AA and its rank is maxed it sends the packet for the completed AA, and the packet - for the next aa in the series. The previous tier is removed from your window, and the new AA is displayed. - 3) When you zone/buy your player profile will be checked and determine what AA can be displayed base on what you have already. - */ - - if (RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (saa2->hotkey_sid == 4294967295u)) - aa_stack = true; - - if (aa_stack){ - uint32 aa_AA = 0; - uint32 aa_value = 0; - for (int i = 0; i < MAX_PP_AA_ARRAY; i++) { - if (aa[i]) { - aa_AA = aa[i]->AA; - aa_value = aa[i]->value; - - if (aa_AA){ - - if (aa_value > 0) - aa_AA -= aa_value-1; - - saa_pp = zone->FindAA(aa_AA); - - if (saa_pp){ - - if (saa_pp->sof_next_skill == saa2->sof_next_skill){ - - if (saa_pp->id == saa2->id) - break; //You already have this in the player profile. - else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value < saa_pp->max_level)) - return; //DISABLE DISPLAY HIGHER - You have not reached max level yet of your current AA. - else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value == saa_pp->max_level) && (saa_pp->sof_next_id == saa2->id)) - IsBaseLevel = false; //ALLOW DISPLAY HIGHER - } - } - } - } - } - } - - //Hide higher tiers of multi tiered AA's if the base level is not fully purchased. - if (aa_stack && IsBaseLevel && saa2->sof_current_level > 0) - return; - - int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; - - if(size == 0) - return; - - uchar* buffer = new uchar[size]; - SendAA_Struct* saa=(SendAA_Struct*)buffer; - memcpy(saa,saa2,size); - - if(saa->spellid==0) - saa->spellid=0xFFFFFFFF; - - value=GetAA(saa->id); - uint32 orig_val = value; - - if(value && saa->id){ - - if(value < saa->max_level){ - saa->id+=value; - saa->next_id=saa->id+1; - value++; - } - - else if (aa_stack && saa->sof_next_id){ - saa->id+=value-1; - saa->next_id=saa->sof_next_id; - - //Prevent removal of previous AA from window if next AA belongs to a higher client version. - SendAA_Struct* saa_next = nullptr; - saa_next = zone->FindAA(saa->sof_next_id); - if (saa_next && - (((GetClientVersionBit() == 4) && (saa_next->clientver > 4)) - || ((GetClientVersionBit() == 8) && (saa_next->clientver > 5)) - || ((GetClientVersionBit() == 16) && (saa_next->clientver > 6)))){ - saa->next_id=0xFFFFFFFF; - } - } - - else{ - saa->id+=value-1; - saa->next_id=0xFFFFFFFF; - } - - uint32 current_level_mod = 0; - if (aa_stack) - current_level_mod = saa->sof_current_level; - - saa->last_id=saa->id-1; - saa->current_level=value+(current_level_mod); - saa->cost = saa2->cost + (saa2->cost_inc*(value-1)); - saa->cost2 = 0; - for(uint32 i = 0; i < value; i++) { - saa->cost2 += saa2->cost + (saa2->cost_inc * i); - } - saa->class_type = saa2->class_type + (saa2->level_inc*(value-1)); - } - - if (aa_stack){ - - if (saa->sof_current_level >= 1 && value == 0) - saa->current_level = saa->sof_current_level+1; - - saa->max_level = saa->sof_max_level; - } - - database.FillAAEffects(saa); - - if(value > 0) - { - // AA_Action stores the base ID - const AA_DBAction *caa = &AA_Actions[saa->id - value + 1][value - 1]; - - if(caa && caa->reuse_time > 0) - saa->spell_refresh = CalcAAReuseTimer(caa); - } - - //You can now use the level_inc field in the altadv_vars table to accomplish this, though still needed - //for special cases like LOH/HT due to inability to implement correct stacking of AA's that use hotkeys. - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(saa->id); - - if(RequiredLevel != AARequiredLevelAndCost.end()) - { - saa->class_type = RequiredLevel->second.Level; - saa->cost = RequiredLevel->second.Cost; - } - - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); - outapp->size=size; - outapp->pBuffer=(uchar*)saa; - if(id==0 && value && (orig_val < saa->max_level)) //send previous AA only on zone in - SendPreviousAA(id, seq); - - QueuePacket(outapp); - safe_delete(outapp); - //will outapp delete the buffer for us even though it didnt make it? --- Yes, it should -} - -void Client::SendAAList(){ - int total = zone->GetTotalAAs(); - for(int i=0;i < total;i++){ - SendAA(0,i); - } -} - -uint32 Client::GetAA(uint32 aa_id) const { - std::map::const_iterator res; - res = aa_points.find(aa_id); - if(res != aa_points.end()) { - return(res->second); - } - return(0); -} - -bool Client::SetAA(uint32 aa_id, uint32 new_value) { - aa_points[aa_id] = new_value; - uint32 cur; - for(cur=0;cur < MAX_PP_AA_ARRAY;cur++){ - if((aa[cur]->value > 1) && ((aa[cur]->AA - aa[cur]->value + 1)== aa_id)){ - aa[cur]->value = new_value; - if(new_value > 0) - aa[cur]->AA++; - else - aa[cur]->AA = 0; - return true; - } - else if((aa[cur]->value == 1) && (aa[cur]->AA == aa_id)){ - aa[cur]->value = new_value; - if(new_value > 0) - aa[cur]->AA++; - else - aa[cur]->AA = 0; - return true; - } - else if(aa[cur]->AA==0){ //end of list - aa[cur]->AA = aa_id; - aa[cur]->value = new_value; - return true; - } - } - return false; -} - -SendAA_Struct* Zone::FindAA(uint32 id) { - return aas_send[id]; -} - -void Zone::LoadAAs() { - LogFile->write(EQEMuLog::Status, "Loading AA information..."); - totalAAs = database.CountAAs(); - if(totalAAs == 0) { - LogFile->write(EQEMuLog::Error, "Failed to load AAs!"); - aas = nullptr; - return; - } - aas = new SendAA_Struct *[totalAAs]; - - database.LoadAAs(aas); - - int i; - for(i=0; i < totalAAs; i++){ - SendAA_Struct* aa = aas[i]; - aas_send[aa->id] = aa; - } - - //load AA Effects into aa_effects - LogFile->write(EQEMuLog::Status, "Loading AA Effects..."); - if (database.LoadAAEffects2()) - LogFile->write(EQEMuLog::Status, "Loaded %d AA Effects.", aa_effects.size()); - else - LogFile->write(EQEMuLog::Error, "Failed to load AA Effects!"); -} - -bool ZoneDatabase::LoadAAEffects2() { - aa_effects.clear(); //start fresh - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT aaid, slot, effectid, base1, base2 FROM aa_effects ORDER BY aaid ASC, slot ASC"), errbuf, &result)) { - int count = 0; - while((row = mysql_fetch_row(result))!= nullptr) { - int aaid = atoi(row[0]); - int slot = atoi(row[1]); - int effectid = atoi(row[2]); - int base1 = atoi(row[3]); - int base2 = atoi(row[4]); - aa_effects[aaid][slot].skill_id = effectid; - aa_effects[aaid][slot].base1 = base1; - aa_effects[aaid][slot].base2 = base2; - aa_effects[aaid][slot].slot = slot; //not really needed, but we'll populate it just in case - count++; - } - mysql_free_result(result); - if (count < 1) //no results - LogFile->write(EQEMuLog::Error, "Error loading AA Effects, none found in the database."); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAEffects2 query: '%s': %s", query, errbuf); - return false; - } - safe_delete_array(query); - return true; -} -void Client::ResetAA(){ - uint32 i; - for(i=0;iAA = 0; - aa[i]->value = 0; - } - std::map::iterator itr; - for(itr=aa_points.begin();itr!=aa_points.end();++itr) - aa_points[itr->first] = 0; - - for(int i = 0; i < _maxLeaderAA; ++i) - m_pp.leader_abilities.ranks[i] = 0; - - m_pp.group_leadership_points = 0; - m_pp.raid_leadership_points = 0; - m_pp.group_leadership_exp = 0; - m_pp.raid_leadership_exp = 0; -} - -int Client::GroupLeadershipAAHealthEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAHealthEnhancement)) - { - case 0: - return 0; - case 1: - return 30; - case 2: - return 60; - case 3: - return 100; - } - - return 0; -} - -int Client::GroupLeadershipAAManaEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAManaEnhancement)) - { - case 0: - return 0; - case 1: - return 30; - case 2: - return 60; - case 3: - return 100; - } - - return 0; -} - -int Client::GroupLeadershipAAHealthRegeneration() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAHealthRegeneration)) - { - case 0: - return 0; - case 1: - return 4; - case 2: - return 6; - case 3: - return 8; - } - - return 0; -} - -int Client::GroupLeadershipAAOffenseEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAOffenseEnhancement)) - { - case 0: - return 0; - case 1: - return 10; - case 2: - return 19; - case 3: - return 28; - case 4: - return 34; - case 5: - return 40; - } - return 0; -} - -void Client::InspectBuffs(Client* Inspector, int Rank) -{ - if(!Inspector || (Rank == 0)) return; - - Inspector->Message_StringID(0, CURRENT_SPELL_EFFECTS, GetName()); - uint32 buff_count = GetMaxTotalSlots(); - for (uint32 i = 0; i < buff_count; ++i) - { - if (buffs[i].spellid != SPELL_UNKNOWN) - { - if(Rank == 1) - Inspector->Message(0, "%s", spells[buffs[i].spellid].name); - else - { - if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) - Inspector->Message(0, "%s (Permanent)", spells[buffs[i].spellid].name); - else { - char *TempString = nullptr; - MakeAnyLenString(&TempString, "%.1f", static_cast(buffs[i].ticsremaining) / 10.0f); - Inspector->Message_StringID(0, BUFF_MINUTES_REMAINING, spells[buffs[i].spellid].name, TempString); - safe_delete_array(TempString); - } - } - } - } -} - -//this really need to be renamed to LoadAAActions() -bool ZoneDatabase::LoadAAEffects() { - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - memset(AA_Actions, 0, sizeof(AA_Actions)); //I hope the compiler is smart about this size... - - const char *query = "SELECT aaid,rank,reuse_time,spell_id,target,nonspell_action,nonspell_mana,nonspell_duration," - "redux_aa,redux_rate,redux_aa2,redux_rate2 FROM aa_actions"; - - if(RunQuery(query, static_cast(strlen(query)), errbuf, &result)) { - //safe_delete_array(query); - int r; - while ((row = mysql_fetch_row(result))) { - r = 0; - int aaid = atoi(row[r++]); - int rank = atoi(row[r++]); - if(aaid < 0 || aaid >= aaHighestID || rank < 0 || rank >= MAX_AA_ACTION_RANKS) - continue; - AA_DBAction *caction = &AA_Actions[aaid][rank]; - - caction->reuse_time = atoi(row[r++]); - caction->spell_id = atoi(row[r++]); - caction->target = (aaTargetType) atoi(row[r++]); - caction->action = (aaNonspellAction) atoi(row[r++]); - caction->mana_cost = atoi(row[r++]); - caction->duration = atoi(row[r++]); - caction->redux_aa = (aaID) atoi(row[r++]); - caction->redux_rate = atoi(row[r++]); - caction->redux_aa2 = (aaID) atoi(row[r++]); - caction->redux_rate2 = atoi(row[r++]); - - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in LoadAAEffects query '%s': %s", query, errbuf);; - //safe_delete_array(query); - return false; - } - - return true; -} - -//Returns the number effects an AA has when we send them to the client -//For the purposes of sizing a packet because every skill does not -//have the same number effects, they can range from none to a few depending on AA. -//counts the # of effects by counting the different slots of an AAID in the DB. - -//AndMetal: this may now be obsolete since we have Zone::GetTotalAALevels() -uint8 ZoneDatabase::GetTotalAALevels(uint32 skill_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int total=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(slot) from aa_effects where aaid=%i", skill_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - total=atoi(row[0]); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in GetTotalAALevels '%s: %s", query, errbuf); - safe_delete_array(query); - } - return total; -} - -//this will allow us to count the number of effects for an AA by pulling the info from memory instead of the database. hopefully this will same some CPU cycles -uint8 Zone::GetTotalAALevels(uint32 skill_id) { - size_t sz = aa_effects[skill_id].size(); - return sz >= 255 ? 255 : static_cast(sz); -} - -/* -Every AA can send the client effects, which are purely for client side effects. -Essentially it's like being able to attach a very simple version of a spell to -Any given AA, it has 4 fields: -skill_id = spell effect id -slot = ID slot, doesn't appear to have any impact on stacking like real spells, just needs to be unique. -base1 = the base field of a spell -base2 = base field 2 of a spell, most AAs do not utilize this -example: - skill_id = SE_STA - slot = 1 - base1 = 15 - This would if you filled the abilities struct with this make the client show if it had - that AA an additional 15 stamina on the client's stats -*/ -void ZoneDatabase::FillAAEffects(SendAA_Struct* aa_struct){ - if(!aa_struct) - return; - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT effectid, base1, base2, slot from aa_effects where aaid=%i order by slot asc", aa_struct->id), errbuf, &result)) { - int ndx=0; - while((row = mysql_fetch_row(result))!=nullptr) { - aa_struct->abilities[ndx].skill_id=atoi(row[0]); - aa_struct->abilities[ndx].base1=atoi(row[1]); - aa_struct->abilities[ndx].base2=atoi(row[2]); - aa_struct->abilities[ndx].slot=atoi(row[3]); - ndx++; - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in Client::FillAAEffects query: '%s': %s", query, errbuf); - } - safe_delete_array(query); -} - -uint32 ZoneDatabase::CountAAs(){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int count=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(title_sid) from altadv_vars"), errbuf, &result)) { - if((row = mysql_fetch_row(result))!=nullptr) - count = atoi(row[0]); - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAAs query '%s': %s", query, errbuf); - } - safe_delete_array(query); - return count; -} - -uint32 ZoneDatabase::CountAAEffects(){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int count=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(id) from aa_effects"), errbuf, &result)) { - if((row = mysql_fetch_row(result))!=nullptr){ - count = atoi(row[0]); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAALevels query '%s': %s", query, errbuf); - } - safe_delete_array(query); - return count; -} - -uint32 ZoneDatabase::GetSizeAA(){ - int size=CountAAs()*sizeof(SendAA_Struct); - if(size>0) - size+=CountAAEffects()*sizeof(AA_Ability); - return size; -} - -void ZoneDatabase::LoadAAs(SendAA_Struct **load){ - if(!load) - return; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id from altadv_vars order by skill_id"), errbuf, &result)) { - int skill=0,ndx=0; - while((row = mysql_fetch_row(result))!=nullptr) { - skill=atoi(row[0]); - load[ndx] = GetAASkillVars(skill); - load[ndx]->seq = ndx+1; - ndx++; - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); - } - safe_delete_array(query); - - AARequiredLevelAndCost.clear(); - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id, level, cost from aa_required_level_cost order by skill_id"), errbuf, &result)) - { - AALevelCost_Struct aalcs; - while((row = mysql_fetch_row(result))!=nullptr) - { - aalcs.Level = atoi(row[1]); - aalcs.Cost = atoi(row[2]); - AARequiredLevelAndCost[atoi(row[0])] = aalcs; - } - mysql_free_result(result); - } - else - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); - - safe_delete_array(query); -} - -SendAA_Struct* ZoneDatabase::GetAASkillVars(uint32 skill_id) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - SendAA_Struct* sendaa = nullptr; - uchar* buffer; - if (RunQuery(query, MakeAnyLenString(&query, "SET @row = 0"), errbuf)) { //initialize "row" variable in database for next query - safe_delete_array(query); - MYSQL_RES *result; //we don't really need these unless we get to this point, so why bother? - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, - "SELECT " - "a.cost, " - "a.max_level, " - "a.hotkey_sid, " - "a.hotkey_sid2, " - "a.title_sid, " - "a.desc_sid, " - "a.type, " - "COALESCE(" //so we can return 0 if it's null - "(" //this is our derived table that has the row # that we can SELECT from, because the client is stupid - "SELECT " - "p.prereq_index_num " - "FROM " - "(" - "SELECT " - "a2.skill_id, " - "@row := @row + 1 AS prereq_index_num " - "FROM " - "altadv_vars a2" - ") AS p " - "WHERE " - "p.skill_id = a.prereq_skill" - "), " - "0) AS prereq_skill_index, " - "a.prereq_minpoints, " - "a.spell_type, " - "a.spell_refresh, " - "a.classes, " - "a.berserker, " - "a.spellid, " - "a.class_type, " - "a.name, " - "a.cost_inc, " - "a.aa_expansion, " - "a.special_category, " - "a.sof_type, " - "a.sof_cost_inc, " - "a.sof_max_level, " - "a.sof_next_skill, " - "a.clientver, " // Client Version 0 = None, 1 = All, 2 = Titanium/6.2, 4 = SoF 5 = SOD 6 = UF - "a.account_time_required, " - "a.sof_current_level," - "a.sof_next_id, " - "a.level_inc " - " FROM altadv_vars a WHERE skill_id=%i", skill_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - int total_abilities = GetTotalAALevels(skill_id); //eventually we'll want to use zone->GetTotalAALevels(skill_id) since it should save queries to the DB - int totalsize = total_abilities * sizeof(AA_Ability) + sizeof(SendAA_Struct); - - buffer = new uchar[totalsize]; - memset(buffer,0,totalsize); - sendaa = (SendAA_Struct*)buffer; - - row = mysql_fetch_row(result); - - //ATOI IS NOT UNISGNED LONG-SAFE!!! - - sendaa->cost = atoul(row[0]); - sendaa->cost2 = sendaa->cost; - sendaa->max_level = atoul(row[1]); - sendaa->hotkey_sid = atoul(row[2]); - sendaa->id = skill_id; - sendaa->hotkey_sid2 = atoul(row[3]); - sendaa->title_sid = atoul(row[4]); - sendaa->desc_sid = atoul(row[5]); - sendaa->type = atoul(row[6]); - sendaa->prereq_skill = atoul(row[7]); - sendaa->prereq_minpoints = atoul(row[8]); - sendaa->spell_type = atoul(row[9]); - sendaa->spell_refresh = atoul(row[10]); - sendaa->classes = static_cast(atoul(row[11])); - sendaa->berserker = static_cast(atoul(row[12])); - sendaa->last_id = 0xFFFFFFFF; - sendaa->current_level=1; - sendaa->spellid = atoul(row[13]); - sendaa->class_type = atoul(row[14]); - strcpy(sendaa->name,row[15]); - - sendaa->total_abilities=total_abilities; - if(sendaa->max_level > 1) - sendaa->next_id=skill_id+1; - else - sendaa->next_id=0xFFFFFFFF; - - sendaa->cost_inc = atoi(row[16]); - // Begin SoF Specific/Adjusted AA Fields - sendaa->aa_expansion = atoul(row[17]); - sendaa->special_category = atoul(row[18]); - sendaa->sof_type = atoul(row[19]); - sendaa->sof_cost_inc = atoi(row[20]); - sendaa->sof_max_level = atoul(row[21]); - sendaa->sof_next_skill = atoul(row[22]); - sendaa->clientver = atoul(row[23]); - sendaa->account_time_required = atoul(row[24]); - //Internal use only - not sent to client - sendaa->sof_current_level = atoul(row[25]); - sendaa->sof_next_id = atoul(row[26]); - sendaa->level_inc = static_cast(atoul(row[27])); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); - safe_delete_array(query); - } - } else { - LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); - safe_delete_array(query); - } - return sendaa; -} - -void Client::DurationRampage(uint32 duration) -{ - if(duration) { - m_epp.aa_effects |= 1 << (aaEffectRampage-1); - p_timers.Start(pTimerAAEffectStart + aaEffectRampage, duration); - } -} - -AA_SwarmPetInfo::AA_SwarmPetInfo() -{ - target = 0; - owner_id = 0; - duration = nullptr; -} - -AA_SwarmPetInfo::~AA_SwarmPetInfo() -{ - target = 0; - owner_id = 0; - safe_delete(duration); -} - -Mob *AA_SwarmPetInfo::GetOwner() -{ - return entity_list.GetMobID(owner_id); -} diff --git a/zone/AA_v1.cpp b/zone/AA_v1.cpp deleted file mode 100644 index fb1413927..000000000 --- a/zone/AA_v1.cpp +++ /dev/null @@ -1,2032 +0,0 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -// Test 1 - -#include "../common/debug.h" -#include "AA.h" -#include "mob.h" -#include "client.h" -#include "groups.h" -#include "raids.h" -#include "../common/spdat.h" -#include "object.h" -#include "doors.h" -#include "beacon.h" -#include "corpse.h" -#include "titles.h" -#include "../common/races.h" -#include "../common/classes.h" -#include "../common/eq_packet_structs.h" -#include "../common/packet_dump.h" -#include "../common/StringUtil.h" -#include "../common/logsys.h" -#include "zonedb.h" -#include "StringIDs.h" - -//static data arrays, really not big enough to warrant shared mem. -AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank] -std::mapaas_send; -std::map > aa_effects; //stores the effects from the aa_effects table in memory -std::map AARequiredLevelAndCost; - -/* - - -Schema: - -spell_id is spell to cast, SPELL_UNKNOWN == no spell -nonspell_action is action to preform on activation which is not a spell, 0=none -nonspell_mana is mana that the nonspell action consumes -nonspell_duration is a duration which may be used by the nonspell action -redux_aa is the aa which reduces the reuse timer of the skill -redux_rate is the multiplier of redux_aa, as a percentage of total rate (10 == 10% faster) - -CREATE TABLE aa_actions ( - aaid mediumint unsigned not null, - rank tinyint unsigned not null, - reuse_time mediumint unsigned not null, - spell_id mediumint unsigned not null, - target tinyint unsigned not null, - nonspell_action tinyint unsigned not null, - nonspell_mana mediumint unsigned not null, - nonspell_duration mediumint unsigned not null, - redux_aa mediumint unsigned not null, - redux_rate tinyint not null, - - PRIMARY KEY(aaid, rank) -); - -CREATE TABLE aa_swarmpets ( - spell_id mediumint unsigned not null, - count tinyint unsigned not null, - npc_id int not null, - duration mediumint unsigned not null, - PRIMARY KEY(spell_id) -); -*/ - -/* - -Credits for this function: - -FatherNitwit: Structure and mechanism - -Wiz: Initial set of AAs, original function contents - -Branks: Much updated info and a bunch of higher-numbered AAs - -*/ -int Client::GetAATimerID(aaID activate) -{ - SendAA_Struct* aa2 = zone->FindAA(activate); - - if(!aa2) - { - for(int i = 1;i < MAX_AA_ACTION_RANKS; ++i) - { - int a = activate - i; - - if(a <= 0) - break; - - aa2 = zone->FindAA(a); - - if(aa2 != nullptr) - break; - } - } - - if(aa2) - return aa2->spell_type; - - return 0; -} - -int Client::CalcAAReuseTimer(const AA_DBAction *caa) { - - if(!caa) - return 0; - - int ReuseTime = caa->reuse_time; - - if(ReuseTime > 0) - { - int ReductionPercentage; - - if(caa->redux_aa > 0 && caa->redux_aa < aaHighestID) - { - ReductionPercentage = GetAA(caa->redux_aa) * caa->redux_rate; - - if(caa->redux_aa2 > 0 && caa->redux_aa2 < aaHighestID) - ReductionPercentage += (GetAA(caa->redux_aa2) * caa->redux_rate2); - - ReuseTime = caa->reuse_time * (100 - ReductionPercentage) / 100; - } - - } - return ReuseTime; -} - -void Client::ActivateAA(aaID activate){ - if(activate < 0 || activate >= aaHighestID) - return; - if(IsStunned() || IsFeared() || IsMezzed() || IsSilenced() || IsPet() || IsSitting() || GetFeigned()) - return; - - int AATimerID = GetAATimerID(activate); - - SendAA_Struct* aa2 = nullptr; - aaID aaid = activate; - uint8 activate_val = GetAA(activate); - //this wasn't taking into acct multi tiered act talents before... - if(activate_val == 0){ - aa2 = zone->FindAA(activate); - if(!aa2){ - int i; - int a; - for(i=1;iFindAA(a); - if(aa2 != nullptr) - break; - } - } - if(aa2){ - aaid = (aaID) aa2->id; - activate_val = GetAA(aa2->id); - } - } - - if (activate_val == 0){ - return; - } - - if(aa2) - { - if(aa2->account_time_required) - { - if((Timer::GetTimeSeconds() + account_creation) < aa2->account_time_required) - { - return; - } - } - } - - if(!p_timers.Expired(&database, AATimerID + pTimerAAStart)) - { - uint32 aaremain = p_timers.GetRemainingTime(AATimerID + pTimerAAStart); - uint32 aaremain_hr = aaremain / (60 * 60); - uint32 aaremain_min = (aaremain / 60) % 60; - uint32 aaremain_sec = aaremain % 60; - - if(aa2) { - if (aaremain_hr >= 1) //1 hour or more - Message(13, "You can use the ability %s again in %u hour(s) %u minute(s) %u seconds", - aa2->name, aaremain_hr, aaremain_min, aaremain_sec); - else //less than an hour - Message(13, "You can use the ability %s again in %u minute(s) %u seconds", - aa2->name, aaremain_min, aaremain_sec); - } else { - if (aaremain_hr >= 1) //1 hour or more - Message(13, "You can use this ability again in %u hour(s) %u minute(s) %u seconds", - aaremain_hr, aaremain_min, aaremain_sec); - else //less than an hour - Message(13, "You can use this ability again in %u minute(s) %u seconds", - aaremain_min, aaremain_sec); - } - return; - } - - if(activate_val > MAX_AA_ACTION_RANKS) - activate_val = MAX_AA_ACTION_RANKS; - activate_val--; //to get array index. - - //get our current node, now that the indices are well bounded - const AA_DBAction *caa = &AA_Actions[aaid][activate_val]; - - if((aaid == aaImprovedHarmTouch || aaid == aaLeechTouch) && !p_timers.Expired(&database, pTimerHarmTouch)){ - Message(13,"Ability recovery time not yet met."); - return; - } - Shout("spell id %i", caa->spell_id); - //everything should be configured out now - - uint16 target_id = 0; - - //figure out our target - switch(caa->target) { - case aaTargetUser: - case aaTargetGroup: - target_id = GetID(); - break; - case aaTargetCurrent: - case aaTargetCurrentGroup: - if(GetTarget() == nullptr) { - Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - target_id = GetTarget()->GetID(); - break; - case aaTargetPet: - if(GetPet() == nullptr) { - Message(0, "A pet is required for this skill."); - return; - } - target_id = GetPetID(); - break; - } - - //handle non-spell action - if(caa->action != aaActionNone) { - if(caa->mana_cost > 0) { - if(GetMana() < caa->mana_cost) { - Message_StringID(13, INSUFFICIENT_MANA); - return; - } - SetMana(GetMana() - caa->mana_cost); - } - if(caa->reuse_time > 0) - { - uint32 timer_base = CalcAAReuseTimer(caa); - if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) - { - p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); - } - p_timers.Start(AATimerID + pTimerAAStart, timer_base); - SendAATimer(AATimerID, 0, 0); - } - HandleAAAction(aaid); - } - Shout("1 spell id %i", caa->spell_id); - //cast the spell, if we have one - if(caa->spell_id > 0 && caa->spell_id < SPDAT_RECORDS) { - Shout("2 spell id %i", caa->spell_id); - if(caa->reuse_time > 0) - { - uint32 timer_base = CalcAAReuseTimer(caa); - SendAATimer(AATimerID, 0, 0); - p_timers.Start(AATimerID + pTimerAAStart, timer_base); - if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) - { - p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); - } - // Bards can cast instant cast AAs while they are casting another song - if (spells[caa->spell_id].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { - if(!SpellFinished(caa->spell_id, entity_list.GetMob(target_id), 10, -1, -1, spells[caa->spell_id].ResistDiff, false)) { - //Reset on failed cast - SendAATimer(AATimerID, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - } else { - if(!CastSpell(caa->spell_id, target_id, 10, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { - //Reset on failed cast - SendAATimer(AATimerID, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - } - } - else - { - if(!CastSpell(caa->spell_id, target_id)) - return; - } - } - // Check if AA is expendable - if (aas_send[activate - activate_val]->special_category == 7) - { - // Add the AA cost to the extended profile to track overall total - m_epp.expended_aa += aas_send[activate]->cost; - SetAA(activate, 0); - - Save(); - SendAA(activate); - SendAATable(); - } -} - -void Client::HandleAAAction(aaID activate) { - if(activate < 0 || activate >= aaHighestID) - return; - - uint8 activate_val = GetAA(activate); - - if (activate_val == 0) - return; - - if(activate_val > MAX_AA_ACTION_RANKS) - activate_val = MAX_AA_ACTION_RANKS; - activate_val--; //to get array index. - - //get our current node, now that the indices are well bounded - const AA_DBAction *caa = &AA_Actions[activate][activate_val]; - - uint16 timer_id = 0; - uint16 timer_duration = caa->duration; - aaTargetType target = aaTargetUser; - - uint16 spell_id = SPELL_UNKNOWN; //gets cast at the end if not still unknown - - switch(caa->action) { - case aaActionAETaunt: - entity_list.AETaunt(this); - break; - - case aaActionMassBuff: - EnableAAEffect(aaEffectMassGroupBuff, 3600); - Message_StringID(MT_Disciplines, MGB_STRING); //The next group buff you cast will hit all targets in range. - break; - - case aaActionFlamingArrows: - //toggle it - if(CheckAAEffect(aaEffectFlamingArrows)) - EnableAAEffect(aaEffectFlamingArrows); - else - DisableAAEffect(aaEffectFlamingArrows); - break; - - case aaActionFrostArrows: - if(CheckAAEffect(aaEffectFrostArrows)) - EnableAAEffect(aaEffectFrostArrows); - else - DisableAAEffect(aaEffectFrostArrows); - break; - - case aaActionRampage: - EnableAAEffect(aaEffectRampage, 10); - break; - - case aaActionSharedHealth: - if(CheckAAEffect(aaEffectSharedHealth)) - EnableAAEffect(aaEffectSharedHealth); - else - DisableAAEffect(aaEffectSharedHealth); - break; - - case aaActionCelestialRegen: { - //special because spell_id depends on a different AA - switch (GetAA(aaCelestialRenewal)) { - case 1: - spell_id = 3250; - break; - case 2: - spell_id = 3251; - break; - default: - spell_id = 2740; - break; - } - target = aaTargetCurrent; - break; - } - - case aaActionDireCharm: { - //special because spell_id depends on class - switch (GetClass()) - { - case DRUID: - spell_id = 2760; //2644? - break; - case NECROMANCER: - spell_id = 2759; //2643? - break; - case ENCHANTER: - spell_id = 2761; //2642? - break; - } - target = aaTargetCurrent; - break; - } - - case aaActionImprovedFamiliar: { - //Spell IDs might be wrong... - if (GetAA(aaAllegiantFamiliar)) - spell_id = 3264; //1994? - else - spell_id = 2758; //2155? - break; - } - - case aaActionActOfValor: - if(GetTarget() != nullptr) { - int curhp = GetTarget()->GetHP(); - target = aaTargetCurrent; - GetTarget()->HealDamage(curhp, this); - Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); - } - break; - - case aaActionSuspendedMinion: - if (GetPet()) { - target = aaTargetPet; - switch (GetAA(aaSuspendedMinion)) { - case 1: - spell_id = 3248; - break; - case 2: - spell_id = 3249; - break; - } - //do we really need to cast a spell? - - Message(0,"You call your pet to your side."); - GetPet()->WipeHateList(); - GetPet()->GMMove(GetX(),GetY(),GetZ()); - if (activate_val > 1) - entity_list.ClearFeignAggro(GetPet()); - } else { - Message(0,"You have no pet to call."); - } - break; - - case aaActionProjectIllusion: - EnableAAEffect(aaEffectProjectIllusion, 3600); - Message(10, "The power of your next illusion spell will flow to your grouped target in your place."); - break; - - - case aaActionEscape: - Escape(); - break; - - // Don't think this code is used any longer for Bestial Alignment as the AA has a spell_id and no nonspell_action. - case aaActionBeastialAlignment: - switch(GetBaseRace()) { - case BARBARIAN: - spell_id = AA_Choose3(activate_val, 4521, 4522, 4523); - break; - case TROLL: - spell_id = AA_Choose3(activate_val, 4524, 4525, 4526); - break; - case OGRE: - spell_id = AA_Choose3(activate_val, 4527, 4527, 4529); - break; - case IKSAR: - spell_id = AA_Choose3(activate_val, 4530, 4531, 4532); - break; - case VAHSHIR: - spell_id = AA_Choose3(activate_val, 4533, 4534, 4535); - break; - } - - case aaActionLeechTouch: - target = aaTargetCurrent; - spell_id = SPELL_HARM_TOUCH2; - EnableAAEffect(aaEffectLeechTouch, 1000); - break; - - case aaActionFadingMemories: - // Do nothing since spell effect works correctly, but mana isn't used. - break; - - default: - LogFile->write(EQEMuLog::Error, "Unknown AA nonspell action type %d", caa->action); - return; - } - - - uint16 target_id = 0; - //figure out our target - switch(target) { - case aaTargetUser: - case aaTargetGroup: - target_id = GetID(); - break; - case aaTargetCurrent: - case aaTargetCurrentGroup: - if(GetTarget() == nullptr) { - Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! - p_timers.Clear(&database, timer_id + pTimerAAEffectStart); - return; - } - target_id = GetTarget()->GetID(); - break; - case aaTargetPet: - if(GetPet() == nullptr) { - Message(0, "A pet is required for this skill."); - return; - } - target_id = GetPetID(); - break; - } - - //cast the spell, if we have one - if(IsValidSpell(spell_id)) { - int aatid = GetAATimerID(activate); - if(!CastSpell(spell_id, target_id , 10, -1, -1, 0, -1, pTimerAAStart + aatid , CalcAAReuseTimer(caa), 1)) { - SendAATimer(aatid, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, pTimerAAStart + aatid); - return; - } - } - - //handle the duration timer if we have one. - if(timer_id > 0 && timer_duration > 0) { - p_timers.Start(pTimerAAEffectStart + timer_id, timer_duration); - } -} - - -//Originally written by Branks -//functionality rewritten by Father Nitwit -void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override) { - - //It might not be a bad idea to put these into the database, eventually.. - - //Dook- swarms and wards - - PetRecord record; - if(!database.GetPetEntry(spells[spell_id].teleport_zone, &record)) - { - LogFile->write(EQEMuLog::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id); - Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone); - return; - } - - AA_SwarmPet pet; - pet.count = 1; - pet.duration = 1; - - for(int x = 0; x < 12; x++) - { - if(spells[spell_id].effectid[x] == SE_TemporaryPets) - { - pet.count = spells[spell_id].base[x]; - pet.duration = spells[spell_id].max[x]; - } - } - - if(IsClient()) - pet.duration += (CastToClient()->GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000); - - pet.npc_id = record.npc_type; - - NPCType *made_npc = nullptr; - - const NPCType *npc_type = database.GetNPCType(pet.npc_id); - if(npc_type == nullptr) { - //log write - LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet spell id: %d", spell_id); - Message(0,"Unable to find pet!"); - return; - } - - if(name_override != nullptr) { - //we have to make a custom NPC type for this name change - made_npc = new NPCType; - memcpy(made_npc, npc_type, sizeof(NPCType)); - strcpy(made_npc->name, name_override); - npc_type = made_npc; - } - - int summon_count = 0; - summon_count = pet.count; - - if(summon_count > MAX_SWARM_PETS) - summon_count = MAX_SWARM_PETS; - - static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, - 10, -10, 10, -10, - 8, -8, 8, -8 }; - static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, - 10, 10, -10, -10, - 8, 8, -8, -8 }; - TempPets(true); - - while(summon_count > 0) { - int pet_duration = pet.duration; - if(duration_override > 0) - pet_duration = duration_override; - - //this is a little messy, but the only way to do it right - //it would be possible to optimize out this copy for the last pet, but oh well - NPCType *npc_dup = nullptr; - if(made_npc != nullptr) { - npc_dup = new NPCType; - memcpy(npc_dup, made_npc, sizeof(NPCType)); - } - - NPC* npca = new NPC( - (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer - 0, - GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], - GetZ(), GetHeading(), FlyMode3); - - if((spell_id == 6882) || (spell_id == 6884)) - npca->SetFollowID(GetID()); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); - } - - //removing this prevents the pet from attacking - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pets somebody to "love" - if(targ != nullptr){ - npca->AddToHateList(targ, 1000, 1000); - npca->GetSwarmInfo()->target = targ->GetID(); - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); - - entity_list.AddNPC(npca, true, true); - summon_count--; - } - - //the target of these swarm pets will take offense to being cast on... - if(targ != nullptr) - targ->AddToHateList(this, 1, 0); -} - -void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_override, uint32 duration_override, bool followme) { - - AA_SwarmPet pet; - pet.count = 1; - pet.duration = 1; - - pet.npc_id = typesid; - - NPCType *made_npc = nullptr; - - const NPCType *npc_type = database.GetNPCType(typesid); - if(npc_type == nullptr) { - //log write - LogFile->write(EQEMuLog::Error, "Unknown npc type for swarm pet type id: %d", typesid); - Message(0,"Unable to find pet!"); - return; - } - - if(name_override != nullptr) { - //we have to make a custom NPC type for this name change - made_npc = new NPCType; - memcpy(made_npc, npc_type, sizeof(NPCType)); - strcpy(made_npc->name, name_override); - npc_type = made_npc; - } - - int summon_count = 0; - summon_count = pet.count; - - if(summon_count > MAX_SWARM_PETS) - summon_count = MAX_SWARM_PETS; - - static const float swarm_pet_x[MAX_SWARM_PETS] = { 5, -5, 5, -5, - 10, -10, 10, -10, - 8, -8, 8, -8 }; - static const float swarm_pet_y[MAX_SWARM_PETS] = { 5, 5, -5, -5, - 10, 10, -10, -10, - 8, 8, -8, -8 }; - TempPets(true); - - while(summon_count > 0) { - int pet_duration = pet.duration; - if(duration_override > 0) - pet_duration = duration_override; - - //this is a little messy, but the only way to do it right - //it would be possible to optimize out this copy for the last pet, but oh well - NPCType *npc_dup = nullptr; - if(made_npc != nullptr) { - npc_dup = new NPCType; - memcpy(npc_dup, made_npc, sizeof(NPCType)); - } - - NPC* npca = new NPC( - (npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer - 0, - GetX()+swarm_pet_x[summon_count], GetY()+swarm_pet_y[summon_count], - GetZ(), GetHeading(), FlyMode3); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(pet_duration*1000); - } - - //removing this prevents the pet from attacking - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pets somebody to "love" - if(targ != nullptr){ - npca->AddToHateList(targ, 1000, 1000); - npca->GetSwarmInfo()->target = targ->GetID(); - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(npc_dup != nullptr) - npca->GiveNPCTypeData(npc_dup); - - entity_list.AddNPC(npca, true, true); - summon_count--; - } -} - -void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) -{ - Corpse *CorpseToUse = nullptr; - CorpseToUse = entity_list.GetClosestCorpse(this, nullptr); - - if(!CorpseToUse) - return; - - //assuming we have pets in our table; we take the first pet as a base type. - const NPCType *base_type = database.GetNPCType(500); - NPCType *make_npc = new NPCType; - memcpy(make_npc, base_type, sizeof(NPCType)); - - //combat stats - make_npc->AC = ((GetLevel() * 7) + 550); - make_npc->ATK = GetLevel(); - make_npc->max_dmg = (GetLevel() * 4) + 2; - make_npc->min_dmg = 1; - - //base stats - make_npc->cur_hp = (GetLevel() * 55); - make_npc->max_hp = (GetLevel() * 55); - make_npc->STR = 85 + (GetLevel() * 3); - make_npc->STA = 85 + (GetLevel() * 3); - make_npc->DEX = 85 + (GetLevel() * 3); - make_npc->AGI = 85 + (GetLevel() * 3); - make_npc->INT = 85 + (GetLevel() * 3); - make_npc->WIS = 85 + (GetLevel() * 3); - make_npc->CHA = 85 + (GetLevel() * 3); - make_npc->MR = 25; - make_npc->FR = 25; - make_npc->CR = 25; - make_npc->DR = 25; - make_npc->PR = 25; - - //level class and gender - make_npc->level = GetLevel(); - make_npc->class_ = CorpseToUse->class_; - make_npc->race = CorpseToUse->race; - make_npc->gender = CorpseToUse->gender; - make_npc->loottable_id = 0; - //name - char NewName[64]; - sprintf(NewName, "%s`s Animated Corpse", GetCleanName()); - strcpy(make_npc->name, NewName); - - //appearance - make_npc->beard = CorpseToUse->beard; - make_npc->beardcolor = CorpseToUse->beardcolor; - make_npc->eyecolor1 = CorpseToUse->eyecolor1; - make_npc->eyecolor2 = CorpseToUse->eyecolor2; - make_npc->haircolor = CorpseToUse->haircolor; - make_npc->hairstyle = CorpseToUse->hairstyle; - make_npc->helmtexture = CorpseToUse->helmtexture; - make_npc->luclinface = CorpseToUse->luclinface; - make_npc->size = CorpseToUse->size; - make_npc->texture = CorpseToUse->texture; - - //cast stuff.. based off of PEQ's if you want to change - //it you'll have to mod this code, but most likely - //most people will be using PEQ style for the first - //part of their spell list; can't think of any smooth - //way to do this - //some basic combat mods here too since it's convienent - switch(CorpseToUse->class_) - { - case CLERIC: - make_npc->npc_spells_id = 1; - break; - case WIZARD: - make_npc->npc_spells_id = 2; - break; - case NECROMANCER: - make_npc->npc_spells_id = 3; - break; - case MAGICIAN: - make_npc->npc_spells_id = 4; - break; - case ENCHANTER: - make_npc->npc_spells_id = 5; - break; - case SHAMAN: - make_npc->npc_spells_id = 6; - break; - case DRUID: - make_npc->npc_spells_id = 7; - break; - case PALADIN: - //SPECATK_TRIPLE - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 150 / 100; - make_npc->max_hp = make_npc->max_hp * 150 / 100; - make_npc->npc_spells_id = 8; - break; - case SHADOWKNIGHT: - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 150 / 100; - make_npc->max_hp = make_npc->max_hp * 150 / 100; - make_npc->npc_spells_id = 9; - break; - case RANGER: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->cur_hp = make_npc->cur_hp * 135 / 100; - make_npc->max_hp = make_npc->max_hp * 135 / 100; - make_npc->npc_spells_id = 10; - break; - case BARD: - strcpy(make_npc->special_abilities, "6,1"); - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - make_npc->npc_spells_id = 11; - break; - case BEASTLORD: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - make_npc->npc_spells_id = 12; - break; - case ROGUE: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 110 / 100; - make_npc->max_hp = make_npc->max_hp * 110 / 100; - break; - case MONK: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 135 / 100; - make_npc->max_hp = make_npc->max_hp * 135 / 100; - break; - case WARRIOR: - case BERSERKER: - strcpy(make_npc->special_abilities, "7,1"); - make_npc->max_dmg = make_npc->max_dmg * 150 /100; - make_npc->cur_hp = make_npc->cur_hp * 175 / 100; - make_npc->max_hp = make_npc->max_hp * 175 / 100; - break; - default: - make_npc->npc_spells_id = 0; - break; - } - - make_npc->loottable_id = 0; - make_npc->merchanttype = 0; - make_npc->d_meele_texture1 = 0; - make_npc->d_meele_texture2 = 0; - - TempPets(true); - - NPC* npca = new NPC(make_npc, 0, GetX(), GetY(), GetZ(), GetHeading(), FlyMode3); - - if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; - npca->SetSwarmInfo(nSI); - npca->GetSwarmInfo()->duration = new Timer(duration*1000); - } - else{ - npca->GetSwarmInfo()->duration->Start(duration*1000); - } - - npca->GetSwarmInfo()->owner_id = GetID(); - - //give the pet somebody to "love" - if(target != nullptr){ - npca->AddToHateList(target, 100000); - npca->GetSwarmInfo()->target = target->GetID(); - } - - //gear stuff, need to make sure there's - //no situation where this stuff can be duped - for(int x = 0; x < 21; x++) - { - uint32 sitem = 0; - sitem = CorpseToUse->GetWornItem(x); - if(sitem){ - const Item_Struct * itm = database.GetItem(sitem); - npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 127, true, true); - } - } - - //we allocated a new NPC type object, give the NPC ownership of that memory - if(make_npc != nullptr) - npca->GiveNPCTypeData(make_npc); - - entity_list.AddNPC(npca, true, true); - - //the target of these swarm pets will take offense to being cast on... - if(target != nullptr) - target->AddToHateList(this, 1, 0); -} - -//turn on an AA effect -//duration == 0 means no time limit, used for one-shot deals, etc.. -void Client::EnableAAEffect(aaEffectType type, uint32 duration) { - if(type > 32) - return; //for now, special logic needed. - m_epp.aa_effects |= 1 << (type-1); - - if(duration > 0) { - p_timers.Start(pTimerAAEffectStart + type, duration); - } else { - p_timers.Clear(&database, pTimerAAEffectStart + type); - } -} - -void Client::DisableAAEffect(aaEffectType type) { - if(type > 32) - return; //for now, special logic needed. - uint32 bit = 1 << (type-1); - if(m_epp.aa_effects & bit) { - m_epp.aa_effects ^= bit; - } - p_timers.Clear(&database, pTimerAAEffectStart + type); -} - -/* -By default an AA effect is a one shot deal, unless -a duration timer is set. -*/ -bool Client::CheckAAEffect(aaEffectType type) { - if(type > 32) - return(false); //for now, special logic needed. - if(m_epp.aa_effects & (1 << (type-1))) { //is effect enabled? - //has our timer expired? - if(p_timers.Expired(&database, pTimerAAEffectStart + type)) { - DisableAAEffect(type); - return(false); - } - return(true); - } - return(false); -} - -void Client::SendAAStats() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); - AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer; - aps->experience = m_pp.expAA; - aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP); - aps->unspent = m_pp.aapoints; - aps->percentage = m_epp.perAA; - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::BuyAA(AA_Action* action) -{ - mlog(AA__MESSAGE, "Starting to buy AA %d", action->ability); - - //find the AA information from the database - SendAA_Struct* aa2 = zone->FindAA(action->ability); - if(!aa2) { - //hunt for a lower level... - int i; - int a; - for(i=1;iability - i; - if(a <= 0) - break; - mlog(AA__MESSAGE, "Could not find AA %d, trying potential parent %d", action->ability, a); - aa2 = zone->FindAA(a); - if(aa2 != nullptr) - break; - } - } - if(aa2 == nullptr) - return; //invalid ability... - - if(aa2->special_category == 1 || aa2->special_category == 2) - return; // Not purchasable progression style AAs - - if(aa2->special_category == 8 && aa2->cost == 0) - return; // Not purchasable racial AAs(set a cost to make them purchasable) - - uint32 cur_level = GetAA(aa2->id); - if((aa2->id + cur_level) != action->ability) { //got invalid AA - mlog(AA__ERROR, "Unable to find or match AA %d (found %d + lvl %d)", action->ability, aa2->id, cur_level); - return; - } - - if(aa2->account_time_required) - { - if((Timer::GetTimeSeconds() - account_creation) < aa2->account_time_required) - { - return; - } - } - - uint32 real_cost; - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); - - if(RequiredLevel != AARequiredLevelAndCost.end()) - { - real_cost = RequiredLevel->second.Cost; - } - else - real_cost = aa2->cost + (aa2->cost_inc * cur_level); - - if(m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { - SetAA(aa2->id, cur_level+1); - - mlog(AA__MESSAGE, "Set AA %d to level %d", aa2->id, cur_level+1); - - m_pp.aapoints -= real_cost; - - Save(); - //if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u)) - if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4)) - && ((aa2->max_level == (cur_level+1)) && aa2->sof_next_id)){ - SendAA(aa2->id); - SendAA(aa2->sof_next_id); - } - //else if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && cur_level == 0 && aa2->hotkey_sid != 4294967295u)) - //{ - //Shout("Current lv 0 for AA hot key %i %i", cur_level, aa2->hotkey_sid); - //} - - else - SendAA(aa2->id); - - SendAATable(); - - //we are building these messages ourself instead of using the stringID to work around patch discrepencies - //these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2 - if(cur_level<1) - Message(15,"You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1)?"points":"point"); - else - Message(15,"You have improved %s %d at a cost of %d ability %s.", aa2->name, cur_level+1, real_cost, (real_cost>1)?"points":"point"); - - - SendAAStats(); - - //SendAAList(true); - //SendAATable(); - CalcBonuses(); - if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) - NotifyNewTitlesAvailable(); - } -} - -void Client::SendAATimer(uint32 ability, uint32 begin, uint32 end) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); - UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; - uaaout->ability = ability; - uaaout->begin = begin; - uaaout->end = end; - QueuePacket(outapp); - safe_delete(outapp); -} - -//sends all AA timers. -void Client::SendAATimers() { - //we dont use SendAATimer because theres no reason to allocate the EQApplicationPacket every time - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); - UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; - - PTimerList::iterator c,e; - c = p_timers.begin(); - e = p_timers.end(); - for(; c != e; ++c) { - PersistentTimer *cur = c->second; - if(cur->GetType() < pTimerAAStart || cur->GetType() > pTimerAAEnd) - continue; //not an AA timer - //send timer - uaaout->begin = cur->GetStartTime(); - uaaout->end = static_cast(time(nullptr)); - uaaout->ability = cur->GetType() - pTimerAAStart; // uuaaout->ability is really a shared timer number - QueuePacket(outapp); - } - - safe_delete(outapp); -} - -void Client::SendAATable() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); - - AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; - aa2->aa_spent = GetAAPointsSpent(); - - uint32 i; - for(i=0;i < MAX_PP_AA_ARRAY;i++){ - aa2->aa_list[i].aa_skill = aa[i]->AA; - aa2->aa_list[i].aa_value = aa[i]->value; - aa2->aa_list[i].unknown08 = 0; - } - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendPreviousAA(uint32 id, int seq){ - uint32 value=0; - SendAA_Struct* saa2 = nullptr; - if(id==0) - saa2 = zone->GetAABySequence(seq); - else - saa2 = zone->FindAA(id); - if(!saa2) - return; - int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; - uchar* buffer = new uchar[size]; - SendAA_Struct* saa=(SendAA_Struct*)buffer; - value = GetAA(saa2->id); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); - outapp->size=size; - outapp->pBuffer=(uchar*)saa; - value--; - memcpy(saa,saa2,size); - - if(value>0){ - if(saa->spellid==0) - saa->spellid=0xFFFFFFFF; - saa->id+=value; - saa->next_id=saa->id+1; - if(value==1) - saa->last_id=saa2->id; - else - saa->last_id=saa->id-1; - saa->current_level=value+1; - saa->cost2 = 0; //cost 2 is what the client uses to calc how many points we've spent, so we have to add up the points in order - for(uint32 i = 0; i < (value+1); i++) { - saa->cost2 += saa->cost + (saa->cost_inc * i); - } - } - - database.FillAAEffects(saa); - QueuePacket(outapp); - safe_delete(outapp); -} - -void Client::SendAA(uint32 id, int seq, bool seqrest) { - - uint32 value=0; - SendAA_Struct* saa2 = nullptr; - SendAA_Struct* qaa = nullptr; - SendAA_Struct* saa_pp = nullptr; - bool IsBaseLevel = true; - bool aa_stack = false; - - Shout("Reset: %i", seqrest); - - if(id==0){ - saa2 = zone->GetAABySequence(seq); - //Shout("SAA2 %i x seq %i", GetAA(saa2->id), seq); - } - else - saa2 = zone->FindAA(id); - if(!saa2) - return; - - uint16 classes = saa2->classes; - if(!(classes & (1 << GetClass())) && (GetClass()!=BERSERKER || saa2->berserker==0)){ - return; - } - - if(saa2->account_time_required) - { - if((Timer::GetTimeSeconds() - account_creation) < saa2->account_time_required) - { - return; - } - } - - // Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). - if (saa2->special_category == 1 || saa2->special_category == 2 ) { - if(GetAA(saa2->id) == 0) - return; - // For Quest line AA(demiplane AEs) where only 1 is visible at a time, check to make sure only the highest level obtained is shown - if(saa2->aa_expansion > 0) { - qaa = zone->FindAA(saa2->id+1); - if(qaa && (saa2->aa_expansion == qaa->aa_expansion) && GetAA(qaa->id) > 0) - return; - } - } - -/* Beginning of Shroud AAs, these categories are for Passive and Active Shroud AAs - Eventually with a toggle we could have it show player list or shroud list - if (saa2->special_category == 3 || saa2->special_category == 4) - return; -*/ - // Check for racial/Drakkin blood line AAs - if (saa2->special_category == 8) - { - uint32 client_race = this->GetBaseRace(); - - // Drakkin Bloodlines - if (saa2->aa_expansion > 522) - { - if (client_race != 522) - return; // Check for Drakkin Race - - int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline - - if (heritage != saa2->aa_expansion) - return; - } - // Racial AAs - else if (client_race != saa2->aa_expansion) - { - return; - } - } - - /* - AA stacking on SoF+ clients. - - Note: There were many ways to achieve this effect - The method used proved to be the most straight forward and consistent. - Stacking does not currently work ideally for AA's that use hotkeys, therefore they will be excluded at this time. - - TODO: Problem with AA hotkeys - When you reach max rank of an AA tier (ie 5/5), it automatically displays the next AA in - the series and you can not transfer the hotkey to the next AA series. To the best of the my ability and through many - different variations of coding I could not find an ideal solution to this issue. - - How stacking works: - Utilizes two new fields: sof_next_id (which is the next id in the series), sof_current_level (ranks the AA's as the current level) - 1) If no AA's purchased only display the base levels of each AA series. - 2) When you purchase an AA and its rank is maxed it sends the packet for the completed AA, and the packet - for the next aa in the series. The previous tier is removed from your window, and the new AA is displayed. - 3) When you zone/buy your player profile will be checked and determine what AA can be displayed base on what you have already. - */ - - //if (RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (saa2->hotkey_sid == 4294967295u)) - if (RuleB(AA, Stacking) && (GetClientVersionBit() >= 4)) - aa_stack = true; - - if (aa_stack){ - uint32 aa_AA = 0; - uint32 aa_value = 0; - for (int i = 0; i < MAX_PP_AA_ARRAY; i++) { - if (aa[i]) { - aa_AA = aa[i]->AA; - aa_value = aa[i]->value; - - if (aa_AA){ - - if (aa_value > 0) - aa_AA -= aa_value-1; - - saa_pp = zone->FindAA(aa_AA); - - if (saa_pp){ - - if (saa_pp->sof_next_skill == saa2->sof_next_skill){ - - if (saa_pp->id == saa2->id) - break; //You already have this in the player profile. - else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value < saa_pp->max_level)) - return; //DISABLE DISPLAY HIGHER - You have not reached max level yet of your current AA. - else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value == saa_pp->max_level) && (saa_pp->sof_next_id == saa2->id)) - IsBaseLevel = false; //ALLOW DISPLAY HIGHER - } - } - } - } - } - } - - //Hide higher tiers of multi tiered AA's if the base level is not fully purchased. - if (aa_stack && IsBaseLevel && saa2->sof_current_level > 0) - return; - - int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; - - if(size == 0) - return; - - uchar* buffer = new uchar[size]; - SendAA_Struct* saa=(SendAA_Struct*)buffer; - memcpy(saa,saa2,size); - Shout("[AA ID %i] SEQ %i SEQLIVE %i",saa->id, saa->seq, saa->seqlive); - if(saa->spellid==0) - saa->spellid=0xFFFFFFFF; - - value=GetAA(saa->id); - uint32 orig_val = value; - - if(value && saa->id){ - - if(value < saa->max_level){ - saa->id+=value; - saa->next_id=saa->id+1; - value++; - } - - else if (aa_stack && saa->sof_next_id){ - //Max value of current tier reached. - saa->id+=value-1; - saa->next_id=saa->sof_next_id; - - //Prevent removal of previous AA from window if next AA belongs to a higher client version. - SendAA_Struct* saa_next = nullptr; - saa_next = zone->FindAA(saa->sof_next_id); - if (saa_next && - (((GetClientVersionBit() == 4) && (saa_next->clientver > 4)) - || ((GetClientVersionBit() == 8) && (saa_next->clientver > 5)) - || ((GetClientVersionBit() == 16) && (saa_next->clientver > 6)))){ - saa->next_id=0xFFFFFFFF; - } - - //if (saa->id == 131) { - // saa->seq = 1; - // Shout("SET SEQ 1"); - //} - Shout("AA Completed: Next"); - } - - else{ - saa->id+=value-1; - saa->next_id=0xFFFFFFFF; - Shout("AA Completed: Final"); - } - - uint32 current_level_mod = 0; - if (aa_stack) - current_level_mod = saa->sof_current_level; - - saa->last_id=saa->id-1; - Shout("1 Current level %i + Value %i",saa->sof_current_level, value); - saa->current_level=value+(current_level_mod); - saa->cost = saa2->cost + (saa2->cost_inc*(value-1)); - saa->cost2 = 0; - for(uint32 i = 0; i < value; i++) { - saa->cost2 += saa2->cost + (saa2->cost_inc * i); - } - saa->class_type = saa2->class_type + (saa2->level_inc*(value-1)); - - } - - if (aa_stack){ - Shout("2 Current level %i VALUE %i",saa->sof_current_level, value); - //After finishing an AA tier transfer over the current level to the next tier to display. - if (saa->sof_current_level >= 1 && value == 0){ - saa->current_level = saa->sof_current_level+1; - - Shout("value = 0 SET LAST AND SEQ"); - saa->last_id = 131; - //saa->seq = 38; - if (saa->seqlive) - saa->seq = saa->seqlive; - } - - saa->max_level = saa->sof_max_level; - } - - - if(seqrest) { - //saa->seq = 0; - saa->id+= saa->max_level-1; - saa->next_id=1; - saa->seq = 0; - Shout("reset"); - } - - database.FillAAEffects(saa); - - if(value > 0) - { - // AA_Action stores the base ID - const AA_DBAction *caa = &AA_Actions[saa->id - value + 1][value - 1]; - - if(caa && caa->reuse_time > 0) - saa->spell_refresh = CalcAAReuseTimer(caa); - } - - //You can now use the level_inc field in the altadv_vars table to accomplish this, though still needed - //for special cases like LOH/HT due to inability to implement correct stacking of AA's that use hotkeys. - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(saa->id); - - if(RequiredLevel != AARequiredLevelAndCost.end()) - { - saa->class_type = RequiredLevel->second.Level; - saa->cost = RequiredLevel->second.Cost; - } - - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); - outapp->size=size; - outapp->pBuffer=(uchar*)saa; - if(id==0 && value && (orig_val < saa->max_level)) //send previous AA only on zone in - SendPreviousAA(id, seq); - - QueuePacket(outapp); - safe_delete(outapp); - //will outapp delete the buffer for us even though it didnt make it? --- Yes, it should -} - -void Client::SendAAList(bool seqrest){ - int total = zone->GetTotalAAs(); - for(int i=0;i < total;i++){ - SendAA(0,i, seqrest); - } -} - -uint32 Client::GetAA(uint32 aa_id) const { - std::map::const_iterator res; - res = aa_points.find(aa_id); - if(res != aa_points.end()) { - return(res->second); - } - return(0); -} - -bool Client::SetAA(uint32 aa_id, uint32 new_value) { - aa_points[aa_id] = new_value; - uint32 cur; - for(cur=0;cur < MAX_PP_AA_ARRAY;cur++){ - if((aa[cur]->value > 1) && ((aa[cur]->AA - aa[cur]->value + 1)== aa_id)){ - aa[cur]->value = new_value; - if(new_value > 0) - aa[cur]->AA++; - else - aa[cur]->AA = 0; - return true; - } - else if((aa[cur]->value == 1) && (aa[cur]->AA == aa_id)){ - aa[cur]->value = new_value; - if(new_value > 0) - aa[cur]->AA++; - else - aa[cur]->AA = 0; - return true; - } - else if(aa[cur]->AA==0){ //end of list - aa[cur]->AA = aa_id; - aa[cur]->value = new_value; - return true; - } - } - return false; -} - -SendAA_Struct* Zone::FindAA(uint32 id) { - return aas_send[id]; -} - -void Zone::LoadAAs() { - LogFile->write(EQEMuLog::Status, "Loading AA information..."); - totalAAs = database.CountAAs(); - if(totalAAs == 0) { - LogFile->write(EQEMuLog::Error, "Failed to load AAs!"); - aas = nullptr; - return; - } - aas = new SendAA_Struct *[totalAAs]; - - database.LoadAAs(aas); - - int i; - for(i=0; i < totalAAs; i++){ - SendAA_Struct* aa = aas[i]; - aas_send[aa->id] = aa; - } - - //load AA Effects into aa_effects - LogFile->write(EQEMuLog::Status, "Loading AA Effects..."); - if (database.LoadAAEffects2()) - LogFile->write(EQEMuLog::Status, "Loaded %d AA Effects.", aa_effects.size()); - else - LogFile->write(EQEMuLog::Error, "Failed to load AA Effects!"); -} - -bool ZoneDatabase::LoadAAEffects2() { - aa_effects.clear(); //start fresh - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT aaid, slot, effectid, base1, base2 FROM aa_effects ORDER BY aaid ASC, slot ASC"), errbuf, &result)) { - int count = 0; - while((row = mysql_fetch_row(result))!= nullptr) { - int aaid = atoi(row[0]); - int slot = atoi(row[1]); - int effectid = atoi(row[2]); - int base1 = atoi(row[3]); - int base2 = atoi(row[4]); - aa_effects[aaid][slot].skill_id = effectid; - aa_effects[aaid][slot].base1 = base1; - aa_effects[aaid][slot].base2 = base2; - aa_effects[aaid][slot].slot = slot; //not really needed, but we'll populate it just in case - count++; - } - mysql_free_result(result); - if (count < 1) //no results - LogFile->write(EQEMuLog::Error, "Error loading AA Effects, none found in the database."); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAEffects2 query: '%s': %s", query, errbuf); - return false; - } - safe_delete_array(query); - return true; -} -void Client::ResetAA(){ - uint32 i; - for(i=0;iAA = 0; - aa[i]->value = 0; - } - std::map::iterator itr; - for(itr=aa_points.begin();itr!=aa_points.end();++itr) - aa_points[itr->first] = 0; - - for(int i = 0; i < _maxLeaderAA; ++i) - m_pp.leader_abilities.ranks[i] = 0; - - m_pp.group_leadership_points = 0; - m_pp.raid_leadership_points = 0; - m_pp.group_leadership_exp = 0; - m_pp.raid_leadership_exp = 0; -} - -int Client::GroupLeadershipAAHealthEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAHealthEnhancement)) - { - case 0: - return 0; - case 1: - return 30; - case 2: - return 60; - case 3: - return 100; - } - - return 0; -} - -int Client::GroupLeadershipAAManaEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAManaEnhancement)) - { - case 0: - return 0; - case 1: - return 30; - case 2: - return 60; - case 3: - return 100; - } - - return 0; -} - -int Client::GroupLeadershipAAHealthRegeneration() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAHealthRegeneration)) - { - case 0: - return 0; - case 1: - return 4; - case 2: - return 6; - case 3: - return 8; - } - - return 0; -} - -int Client::GroupLeadershipAAOffenseEnhancement() -{ - Group *g = GetGroup(); - - if(!g || (g->GroupCount() < 3)) - return 0; - - switch(g->GetLeadershipAA(groupAAOffenseEnhancement)) - { - case 0: - return 0; - case 1: - return 10; - case 2: - return 19; - case 3: - return 28; - case 4: - return 34; - case 5: - return 40; - } - return 0; -} - -void Client::InspectBuffs(Client* Inspector, int Rank) -{ - if(!Inspector || (Rank == 0)) return; - - Inspector->Message_StringID(0, CURRENT_SPELL_EFFECTS, GetName()); - uint32 buff_count = GetMaxTotalSlots(); - for (uint32 i = 0; i < buff_count; ++i) - { - if (buffs[i].spellid != SPELL_UNKNOWN) - { - if(Rank == 1) - Inspector->Message(0, "%s", spells[buffs[i].spellid].name); - else - { - if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) - Inspector->Message(0, "%s (Permanent)", spells[buffs[i].spellid].name); - else { - char *TempString = nullptr; - MakeAnyLenString(&TempString, "%.1f", static_cast(buffs[i].ticsremaining) / 10.0f); - Inspector->Message_StringID(0, BUFF_MINUTES_REMAINING, spells[buffs[i].spellid].name, TempString); - safe_delete_array(TempString); - } - } - } - } -} - -//this really need to be renamed to LoadAAActions() -bool ZoneDatabase::LoadAAEffects() { - char errbuf[MYSQL_ERRMSG_SIZE]; - MYSQL_RES *result; - MYSQL_ROW row; - - memset(AA_Actions, 0, sizeof(AA_Actions)); //I hope the compiler is smart about this size... - - const char *query = "SELECT aaid,rank,reuse_time,spell_id,target,nonspell_action,nonspell_mana,nonspell_duration," - "redux_aa,redux_rate,redux_aa2,redux_rate2 FROM aa_actions"; - - if(RunQuery(query, static_cast(strlen(query)), errbuf, &result)) { - //safe_delete_array(query); - int r; - while ((row = mysql_fetch_row(result))) { - r = 0; - int aaid = atoi(row[r++]); - int rank = atoi(row[r++]); - if(aaid < 0 || aaid >= aaHighestID || rank < 0 || rank >= MAX_AA_ACTION_RANKS) - continue; - AA_DBAction *caction = &AA_Actions[aaid][rank]; - - caction->reuse_time = atoi(row[r++]); - caction->spell_id = atoi(row[r++]); - caction->target = (aaTargetType) atoi(row[r++]); - caction->action = (aaNonspellAction) atoi(row[r++]); - caction->mana_cost = atoi(row[r++]); - caction->duration = atoi(row[r++]); - caction->redux_aa = (aaID) atoi(row[r++]); - caction->redux_rate = atoi(row[r++]); - caction->redux_aa2 = (aaID) atoi(row[r++]); - caction->redux_rate2 = atoi(row[r++]); - - } - mysql_free_result(result); - } - else { - LogFile->write(EQEMuLog::Error, "Error in LoadAAEffects query '%s': %s", query, errbuf);; - //safe_delete_array(query); - return false; - } - - return true; -} - -//Returns the number effects an AA has when we send them to the client -//For the purposes of sizing a packet because every skill does not -//have the same number effects, they can range from none to a few depending on AA. -//counts the # of effects by counting the different slots of an AAID in the DB. - -//AndMetal: this may now be obsolete since we have Zone::GetTotalAALevels() -uint8 ZoneDatabase::GetTotalAALevels(uint32 skill_id) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int total=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(slot) from aa_effects where aaid=%i", skill_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - total=atoi(row[0]); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in GetTotalAALevels '%s: %s", query, errbuf); - safe_delete_array(query); - } - return total; -} - -//this will allow us to count the number of effects for an AA by pulling the info from memory instead of the database. hopefully this will same some CPU cycles -uint8 Zone::GetTotalAALevels(uint32 skill_id) { - size_t sz = aa_effects[skill_id].size(); - return sz >= 255 ? 255 : static_cast(sz); -} - -/* -Every AA can send the client effects, which are purely for client side effects. -Essentially it's like being able to attach a very simple version of a spell to -Any given AA, it has 4 fields: -skill_id = spell effect id -slot = ID slot, doesn't appear to have any impact on stacking like real spells, just needs to be unique. -base1 = the base field of a spell -base2 = base field 2 of a spell, most AAs do not utilize this -example: - skill_id = SE_STA - slot = 1 - base1 = 15 - This would if you filled the abilities struct with this make the client show if it had - that AA an additional 15 stamina on the client's stats -*/ -void ZoneDatabase::FillAAEffects(SendAA_Struct* aa_struct){ - if(!aa_struct) - return; - - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT effectid, base1, base2, slot from aa_effects where aaid=%i order by slot asc", aa_struct->id), errbuf, &result)) { - int ndx=0; - while((row = mysql_fetch_row(result))!=nullptr) { - aa_struct->abilities[ndx].skill_id=atoi(row[0]); - aa_struct->abilities[ndx].base1=atoi(row[1]); - aa_struct->abilities[ndx].base2=atoi(row[2]); - aa_struct->abilities[ndx].slot=atoi(row[3]); - ndx++; - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in Client::FillAAEffects query: '%s': %s", query, errbuf); - } - safe_delete_array(query); -} - -uint32 ZoneDatabase::CountAAs(){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int count=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(title_sid) from altadv_vars"), errbuf, &result)) { - if((row = mysql_fetch_row(result))!=nullptr) - count = atoi(row[0]); - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAAs query '%s': %s", query, errbuf); - } - safe_delete_array(query); - return count; -} - -uint32 ZoneDatabase::CountAAEffects(){ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - int count=0; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT count(id) from aa_effects"), errbuf, &result)) { - if((row = mysql_fetch_row(result))!=nullptr){ - count = atoi(row[0]); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::CountAALevels query '%s': %s", query, errbuf); - } - safe_delete_array(query); - return count; -} - -uint32 ZoneDatabase::GetSizeAA(){ - int size=CountAAs()*sizeof(SendAA_Struct); - if(size>0) - size+=CountAAEffects()*sizeof(AA_Ability); - return size; -} - -void ZoneDatabase::LoadAAs(SendAA_Struct **load){ - if(!load) - return; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id from altadv_vars order by skill_id"), errbuf, &result)) { - int skill=0,ndx=0; - while((row = mysql_fetch_row(result))!=nullptr) { - skill=atoi(row[0]); - load[ndx] = GetAASkillVars(skill); - load[ndx]->seq = ndx+1; - ndx++; - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); - } - safe_delete_array(query); - - AARequiredLevelAndCost.clear(); - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT skill_id, level, cost from aa_required_level_cost order by skill_id"), errbuf, &result)) - { - AALevelCost_Struct aalcs; - while((row = mysql_fetch_row(result))!=nullptr) - { - aalcs.Level = atoi(row[1]); - aalcs.Cost = atoi(row[2]); - AARequiredLevelAndCost[atoi(row[0])] = aalcs; - } - mysql_free_result(result); - } - else - LogFile->write(EQEMuLog::Error, "Error in ZoneDatabase::LoadAAs query '%s': %s", query, errbuf); - - safe_delete_array(query); -} - -SendAA_Struct* ZoneDatabase::GetAASkillVars(uint32 skill_id) -{ - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - SendAA_Struct* sendaa = nullptr; - uchar* buffer; - if (RunQuery(query, MakeAnyLenString(&query, "SET @row = 0"), errbuf)) { //initialize "row" variable in database for next query - safe_delete_array(query); - MYSQL_RES *result; //we don't really need these unless we get to this point, so why bother? - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, - "SELECT " - "a.cost, " - "a.max_level, " - "a.hotkey_sid, " - "a.hotkey_sid2, " - "a.title_sid, " - "a.desc_sid, " - "a.type, " - "COALESCE(" //so we can return 0 if it's null - "(" //this is our derived table that has the row # that we can SELECT from, because the client is stupid - "SELECT " - "p.prereq_index_num " - "FROM " - "(" - "SELECT " - "a2.skill_id, " - "@row := @row + 1 AS prereq_index_num " - "FROM " - "altadv_vars a2" - ") AS p " - "WHERE " - "p.skill_id = a.prereq_skill" - "), " - "0) AS prereq_skill_index, " - "a.prereq_minpoints, " - "a.spell_type, " - "a.spell_refresh, " - "a.classes, " - "a.berserker, " - "a.spellid, " - "a.class_type, " - "a.name, " - "a.cost_inc, " - "a.aa_expansion, " - "a.special_category, " - "a.sof_type, " - "a.sof_cost_inc, " - "a.sof_max_level, " - "a.sof_next_skill, " - "a.clientver, " // Client Version 0 = None, 1 = All, 2 = Titanium/6.2, 4 = SoF 5 = SOD 6 = UF - "a.account_time_required, " - "a.sof_current_level," - "a.sof_next_id, " - "a.level_inc, " - "a.seqlive " - " FROM altadv_vars a WHERE skill_id=%i", skill_id), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - int total_abilities = GetTotalAALevels(skill_id); //eventually we'll want to use zone->GetTotalAALevels(skill_id) since it should save queries to the DB - int totalsize = total_abilities * sizeof(AA_Ability) + sizeof(SendAA_Struct); - - buffer = new uchar[totalsize]; - memset(buffer,0,totalsize); - sendaa = (SendAA_Struct*)buffer; - - row = mysql_fetch_row(result); - - //ATOI IS NOT UNISGNED LONG-SAFE!!! - - sendaa->cost = atoul(row[0]); - sendaa->cost2 = sendaa->cost; - sendaa->max_level = atoul(row[1]); - sendaa->hotkey_sid = atoul(row[2]); - sendaa->id = skill_id; - sendaa->hotkey_sid2 = atoul(row[3]); - sendaa->title_sid = atoul(row[4]); - sendaa->desc_sid = atoul(row[5]); - sendaa->type = atoul(row[6]); - sendaa->prereq_skill = atoul(row[7]); - sendaa->prereq_minpoints = atoul(row[8]); - sendaa->spell_type = atoul(row[9]); - sendaa->spell_refresh = atoul(row[10]); - sendaa->classes = static_cast(atoul(row[11])); - sendaa->berserker = static_cast(atoul(row[12])); - sendaa->last_id = 0xFFFFFFFF; - sendaa->current_level=1; - sendaa->spellid = atoul(row[13]); - sendaa->class_type = atoul(row[14]); - strcpy(sendaa->name,row[15]); - - sendaa->total_abilities=total_abilities; - if(sendaa->max_level > 1) - sendaa->next_id=skill_id+1; - else - sendaa->next_id=0xFFFFFFFF; - - sendaa->cost_inc = atoi(row[16]); - // Begin SoF Specific/Adjusted AA Fields - sendaa->aa_expansion = atoul(row[17]); - sendaa->special_category = atoul(row[18]); - sendaa->sof_type = atoul(row[19]); - sendaa->sof_cost_inc = atoi(row[20]); - sendaa->sof_max_level = atoul(row[21]); - sendaa->sof_next_skill = atoul(row[22]); - sendaa->clientver = atoul(row[23]); - sendaa->account_time_required = atoul(row[24]); - //Internal use only - not sent to client - sendaa->sof_current_level = atoul(row[25]); - sendaa->sof_next_id = atoul(row[26]); - sendaa->level_inc = static_cast(atoul(row[27])); - sendaa->seqlive = (atoul(row[28])); - } - mysql_free_result(result); - } else { - LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); - safe_delete_array(query); - } - } else { - LogFile->write(EQEMuLog::Error, "Error in GetAASkillVars '%s': %s", query, errbuf); - safe_delete_array(query); - } - return sendaa; -} - -void Client::DurationRampage(uint32 duration) -{ - if(duration) { - m_epp.aa_effects |= 1 << (aaEffectRampage-1); - p_timers.Start(pTimerAAEffectStart + aaEffectRampage, duration); - } -} - -AA_SwarmPetInfo::AA_SwarmPetInfo() -{ - target = 0; - owner_id = 0; - duration = nullptr; -} - -AA_SwarmPetInfo::~AA_SwarmPetInfo() -{ - target = 0; - owner_id = 0; - safe_delete(duration); -} - -Mob *AA_SwarmPetInfo::GetOwner() -{ - return entity_list.GetMobID(owner_id); -} diff --git a/zone/MobAI_M.cpp b/zone/MobAI_M.cpp deleted file mode 100644 index 7574f19ad..000000000 --- a/zone/MobAI_M.cpp +++ /dev/null @@ -1,2760 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "../common/debug.h" -#include -#include -#include -#include -#include -#include "npc.h" -#include "masterentity.h" -#include "NpcAI.h" -#include "map.h" -#include "../common/moremath.h" -#include "StringIDs.h" -#include "../common/MiscFunctions.h" -#include "../common/StringUtil.h" -#include "../common/rulesys.h" -#include "../common/features.h" -#include "QuestParserCollection.h" -#include "watermap.h" - -extern EntityList entity_list; - -extern Zone *zone; - -#ifdef _EQDEBUG - #define MobAI_DEBUG_Spells -1 -#else - #define MobAI_DEBUG_Spells -1 -#endif -#define ABS(x) ((x)<0?-(x):(x)) - -//NOTE: do NOT pass in beneficial and detrimental spell types into the same call here! -bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { - if (!tar) - return false; - - if (IsNoCast()) - return false; - - if(AI_HasSpells() == false) - return false; - - if (iChance < 100) { - if (MakeRandomInt(0, 100) >= iChance) - return false; - } - - float dist2; - - if (iSpellTypes & SpellType_Escape) { - dist2 = 0; //DistNoRoot(*this); //WTF was up with this... - } - else - dist2 = DistNoRoot(*tar); - - bool checked_los = false; //we do not check LOS until we are absolutely sure we need to, and we only do it once. - - float manaR = GetManaRatio(); - for (int i = static_cast(AIspells.size()) - 1; i >= 0; i--) { - if (AIspells[i].spellid <= 0 || AIspells[i].spellid >= SPDAT_RECORDS) { - // this is both to quit early to save cpu and to avoid casting bad spells - // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here - //return false; - continue; - } - if (iSpellTypes & AIspells[i].type) { - // manacost has special values, -1 is no mana cost, -2 is instant cast (no mana) - int32 mana_cost = AIspells[i].manacost; - if (mana_cost == -1) - mana_cost = spells[AIspells[i].spellid].mana; - else if (mana_cost == -2) - mana_cost = 0; - if ( - (( - (spells[AIspells[i].spellid].targettype==ST_AECaster || spells[AIspells[i].spellid].targettype==ST_AEBard) - && dist2 <= spells[AIspells[i].spellid].aoerange*spells[AIspells[i].spellid].aoerange - ) || - dist2 <= spells[AIspells[i].spellid].range*spells[AIspells[i].spellid].range - ) - && (mana_cost <= GetMana() || GetMana() == GetMaxMana()) - && (AIspells[i].time_cancast + (MakeRandomInt(0, 4) * 1000)) <= Timer::GetCurrentTime() //break up the spelling casting over a period of time. - ) { - -#if MobAI_DEBUG_Spells >= 21 - std::cout << "Mob::AICastSpell: Casting: spellid=" << AIspells[i].spellid - << ", tar=" << tar->GetName() - << ", dist2[" << dist2 << "]<=" << spells[AIspells[i].spellid].range *spells[AIspells[i].spellid].range - << ", mana_cost[" << mana_cost << "]<=" << GetMana() - << ", cancast[" << AIspells[i].time_cancast << "]<=" << Timer::GetCurrentTime() - << ", type=" << AIspells[i].type << std::endl; -#endif - - switch (AIspells[i].type) { - case SpellType_Heal: { - if ( - (spells[AIspells[i].spellid].targettype == ST_Target || tar == this) - && tar->DontHealMeBefore() < Timer::GetCurrentTime() - && !(tar->IsPet() && tar->GetOwner()->IsClient()) //no buffing PC's pets - ) { - uint8 hpr = (uint8)tar->GetHPRatio(); - - if(hpr <= 35 || (!IsEngaged() && hpr <= 50) || (tar->IsClient() && hpr <= 99)) { - uint32 tempTime = 0; - AIDoSpellCast(i, tar, mana_cost, &tempTime); - tar->SetDontHealMeBefore(tempTime); - return true; - } - } - break; - } - case SpellType_Root: { - Mob *rootee = GetHateRandom(); - if (rootee && !rootee->IsRooted() && MakeRandomInt(0, 99) < 50 - && rootee->DontRootMeBefore() < Timer::GetCurrentTime() - && rootee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - ) { - if(!checked_los) { - if(!CheckLosFN(rootee)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - uint32 tempTime = 0; - AIDoSpellCast(i, rootee, mana_cost, &tempTime); - rootee->SetDontRootMeBefore(tempTime); - return true; - } - break; - } - case SpellType_Buff: { - if ( - (spells[AIspells[i].spellid].targettype == ST_Target || tar == this) - && tar->DontBuffMeBefore() < Timer::GetCurrentTime() - && !tar->IsImmuneToSpell(AIspells[i].spellid, this) - && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - && !(tar->IsPet() && tar->GetOwner()->IsClient() && this != tar) //no buffing PC's pets, but they can buff themself - ) - { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); - checked_los = true; - } - uint32 tempTime = 0; - AIDoSpellCast(i, tar, mana_cost, &tempTime); - tar->SetDontBuffMeBefore(tempTime); - return true; - } - break; - } - - case SpellType_InCombatBuff: { - if(MakeRandomInt(0, 99) < 50) - { - AIDoSpellCast(i, tar, mana_cost); - return true; - } - break; - } - - case SpellType_Escape: { - if (GetHPRatio() <= 5 ) - { - AIDoSpellCast(i, tar, mana_cost); - return true; - } - break; - } - case SpellType_Slow: - case SpellType_Debuff: { - Mob * debuffee = GetHateRandom(); - if (debuffee && manaR >= 10 && MakeRandomInt(0, 99 < 70) && - debuffee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) { - if (!checked_los) { - if (!CheckLosFN(debuffee)) - return false; - checked_los = true; - } - AIDoSpellCast(i, debuffee, mana_cost); - return true; - } - break; - } - case SpellType_Nuke: { - if ( - manaR >= 10 && MakeRandomInt(0, 99) < 70 - && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - ) { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - AIDoSpellCast(i, tar, mana_cost); - return true; - } - break; - } - case SpellType_Dispel: { - if(MakeRandomInt(0, 99) < 15) - { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - if(tar->CountDispellableBuffs() > 0) - { - AIDoSpellCast(i, tar, mana_cost); - return true; - } - } - break; - } - case SpellType_Mez: { - if(MakeRandomInt(0, 99) < 20) - { - Mob * mezTar = nullptr; - mezTar = entity_list.GetTargetForMez(this); - - if(mezTar && mezTar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) - { - AIDoSpellCast(i, mezTar, mana_cost); - return true; - } - } - break; - } - - case SpellType_Charm: - { - if(!IsPet() && MakeRandomInt(0, 99) < 20) - { - Mob * chrmTar = GetHateRandom(); - if(chrmTar && chrmTar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0) - { - AIDoSpellCast(i, chrmTar, mana_cost); - return true; - } - } - break; - } - - case SpellType_Pet: { - //keep mobs from recasting pets when they have them. - if (!IsPet() && !GetPetID() && MakeRandomInt(0, 99) < 25) { - AIDoSpellCast(i, tar, mana_cost); - return true; - } - break; - } - case SpellType_Lifetap: { - if (GetHPRatio() <= 95 - && MakeRandomInt(0, 99) < 50 - && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - ) { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - AIDoSpellCast(i, tar, mana_cost); - return true; - } - break; - } - case SpellType_Snare: { - if ( - !tar->IsRooted() - && MakeRandomInt(0, 99) < 50 - && tar->DontSnareMeBefore() < Timer::GetCurrentTime() - && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - ) { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - uint32 tempTime = 0; - AIDoSpellCast(i, tar, mana_cost, &tempTime); - tar->SetDontSnareMeBefore(tempTime); - return true; - } - break; - } - case SpellType_DOT: { - if ( - MakeRandomInt(0, 99) < 60 - && tar->DontDotMeBefore() < Timer::GetCurrentTime() - && tar->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 - ) { - if(!checked_los) { - if(!CheckLosFN(tar)) - return(false); //cannot see target... we assume that no spell is going to work since we will only be casting detrimental spells in this call - checked_los = true; - } - uint32 tempTime = 0; - AIDoSpellCast(i, tar, mana_cost, &tempTime); - tar->SetDontDotMeBefore(tempTime); - return true; - } - break; - } - default: { - std::cout << "Error: Unknown spell type in AICastSpell. caster:" << this->GetName() << " type:" << AIspells[i].type << " slot:" << i << std::endl; - break; - } - } - } -#if MobAI_DEBUG_Spells >= 21 - else { - std::cout << "Mob::AICastSpell: NotCasting: spellid=" << AIspells[i].spellid << ", tar=" << tar->GetName() << ", dist2[" << dist2 << "]<=" << spells[AIspells[i].spellid].range*spells[AIspells[i].spellid].range << ", mana_cost[" << mana_cost << "]<=" << GetMana() << ", cancast[" << AIspells[i].time_cancast << "]<=" << Timer::GetCurrentTime() << std::endl; - } -#endif - } - } - return false; -} - -bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore) { -#if MobAI_DEBUG_Spells >= 1 - std::cout << "Mob::AIDoSpellCast: spellid=" << AIspells[i].spellid << ", tar=" << tar->GetName() << ", mana=" << mana_cost << ", Name: " << spells[AIspells[i].spellid].name << std::endl; -#endif - casting_spell_AIindex = i; - - //stop moving if were casting a spell and were not a bard... - if(!IsBardSong(AIspells[i].spellid)) { - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - } - - return CastSpell(AIspells[i].spellid, tar->GetID(), 1, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0, &(AIspells[i].resist_adjust)); -} - -bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint16 iSpellTypes) { - if((iSpellTypes&SpellTypes_Detrimental) != 0) { - //according to live, you can buff and heal through walls... - //now with PCs, this only applies if you can TARGET the target, but - // according to Rogean, Live NPCs will just cast through walls/floors, no problem.. - // - // This check was put in to address an idle-mob CPU issue - _log(AI__ERROR, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!"); - return(false); - } - - if(!caster) - return false; - - if(caster->AI_HasSpells() == false) - return false; - - if(caster->GetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS)) - return false; - - if (iChance < 100) { - uint8 tmp = MakeRandomInt(0, 99); - if (tmp >= iChance) - return false; - } - if (caster->GetPrimaryFaction() == 0 ) - return(false); // well, if we dont have a faction set, we're gonna be indiff to everybody - - float iRange2 = iRange*iRange; - - float t1, t2, t3; - - - //Only iterate through NPCs - for (auto it = npc_list.begin(); it != npc_list.end(); ++it) { - NPC* mob = it->second; - - //Since >90% of mobs will always be out of range, try to - //catch them with simple bounding box checks first. These - //checks are about 6X faster than DistNoRoot on my athlon 1Ghz - t1 = mob->GetX() - caster->GetX(); - t2 = mob->GetY() - caster->GetY(); - t3 = mob->GetZ() - caster->GetZ(); - //cheap ABS() - if(t1 < 0) - t1 = 0 - t1; - if(t2 < 0) - t2 = 0 - t2; - if(t3 < 0) - t3 = 0 - t3; - if (t1 > iRange - || t2 > iRange - || t3 > iRange - || mob->DistNoRoot(*caster) > iRange2 - //this call should seem backwards: - || !mob->CheckLosFN(caster) - || mob->GetReverseFactionCon(caster) >= FACTION_KINDLY - ) { - continue; - } - - //since we assume these are beneficial spells, which do not - //require LOS, we just go for it. - // we have a winner! - if((iSpellTypes & SpellType_Buff) && !RuleB(NPC, BuffFriends)){ - if (mob != caster) - iSpellTypes = SpellType_Heal; - } - - if (caster->AICastSpell(mob, 100, iSpellTypes)) - return true; - } - return false; -} - -void Mob::AI_Init() { - pAIControlled = false; - AIthink_timer = 0; - AIwalking_timer = 0; - AImovement_timer = 0; - AItarget_check_timer = 0; - AIfeignremember_timer = nullptr; - AIscanarea_timer = 0; - minLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMin); - maxLastFightingDelayMoving = RuleI(NPC, LastFightingDelayMovingMax); - - pDontHealMeBefore = 0; - pDontBuffMeBefore = 0; - pDontDotMeBefore = 0; - pDontRootMeBefore = 0; - pDontSnareMeBefore = 0; - pDontCureMeBefore = 0; -} - -void NPC::AI_Init() { - Mob::AI_Init(); - - AIautocastspell_timer = 0; - casting_spell_AIindex = static_cast(AIspells.size()); - - roambox_max_x = 0; - roambox_max_y = 0; - roambox_min_x = 0; - roambox_min_y = 0; - roambox_distance = 0; - roambox_movingto_x = 0; - roambox_movingto_y = 0; - roambox_min_delay = 2500; - roambox_delay = 2500; -} - -void Client::AI_Init() { - Mob::AI_Init(); - minLastFightingDelayMoving = CLIENT_LD_TIMEOUT; - maxLastFightingDelayMoving = CLIENT_LD_TIMEOUT; -} - -void Mob::AI_Start(uint32 iMoveDelay) { - if (pAIControlled) - return; - - if (iMoveDelay) - pLastFightingDelayMoving = Timer::GetCurrentTime() + iMoveDelay; - else - pLastFightingDelayMoving = 0; - - pAIControlled = true; - AIthink_timer = new Timer(AIthink_duration); - AIthink_timer->Trigger(); - AIwalking_timer = new Timer(0); - AImovement_timer = new Timer(AImovement_duration); - AItarget_check_timer = new Timer(AItarget_check_duration); - AIfeignremember_timer = new Timer(AIfeignremember_delay); - AIscanarea_timer = new Timer(AIscanarea_delay); -#ifdef REVERSE_AGGRO - if(IsNPC() && !CastToNPC()->WillAggroNPCs()) - AIscanarea_timer->Disable(); -#endif - - if (GetAggroRange() == 0) - pAggroRange = 70; - if (GetAssistRange() == 0) - pAssistRange = 70; - hate_list.Wipe(); - - delta_heading = 0; - delta_x = 0; - delta_y = 0; - delta_z = 0; - pRunAnimSpeed = 0; - pLastChange = Timer::GetCurrentTime(); -} - -void Client::AI_Start(uint32 iMoveDelay) { - Mob::AI_Start(iMoveDelay); - - if (!pAIControlled) - return; - - pClientSideTarget = GetTarget() ? GetTarget()->GetID() : 0; - SendAppearancePacket(AT_Anim, ANIM_FREEZE); // this freezes the client - SendAppearancePacket(AT_Linkdead, 1); // Sending LD packet so *LD* appears by the player name when charmed/feared -Kasai - SetAttackTimer(); - SetFeigned(false); -} - -void NPC::AI_Start(uint32 iMoveDelay) { - Mob::AI_Start(iMoveDelay); - if (!pAIControlled) - return; - - if (AIspells.size() == 0) { - AIautocastspell_timer = new Timer(1000); - AIautocastspell_timer->Disable(); - } else { - AIautocastspell_timer = new Timer(750); - AIautocastspell_timer->Start(RandomTimer(0, 15000), false); - } - - if (NPCTypedata) { - AI_AddNPCSpells(NPCTypedata->npc_spells_id); - ProcessSpecialAbilities(NPCTypedata->special_abilities); - AI_AddNPCSpellsEffects(NPCTypedata->npc_spells_effects_id); - } - - SendTo(GetX(), GetY(), GetZ()); - SetChanged(); - SaveGuardSpot(); -} - -void Mob::AI_Stop() { - if (!IsAIControlled()) - return; - pAIControlled = false; - safe_delete(AIthink_timer); - safe_delete(AIwalking_timer); - safe_delete(AImovement_timer); - safe_delete(AItarget_check_timer) - safe_delete(AIscanarea_timer); - safe_delete(AIfeignremember_timer); - hate_list.Wipe(); -} - -void NPC::AI_Stop() { - Waypoints.clear(); - safe_delete(AIautocastspell_timer); -} - -void Client::AI_Stop() { - Mob::AI_Stop(); - this->Message_StringID(13,PLAYER_REGAIN); - - EQApplicationPacket *app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); - Charm_Struct *ps = (Charm_Struct*)app->pBuffer; - ps->owner_id = 0; - ps->pet_id = this->GetID(); - ps->command = 0; - entity_list.QueueClients(this, app); - safe_delete(app); - - SetTarget(entity_list.GetMob(pClientSideTarget)); - SendAppearancePacket(AT_Anim, GetAppearanceValue(GetAppearance())); - SendAppearancePacket(AT_Linkdead, 0); // Removing LD packet so *LD* no longer appears by the player name when charmed/feared -Kasai - if (!auto_attack) { - attack_timer.Disable(); - attack_dw_timer.Disable(); - } - if (IsLD()) - { - Save(); - Disconnect(); - } -} - -//todo: expand the logic here to cover: -//redundant debuffs -//buffing owner -//certain types of det spells that need special behavior. -void Client::AI_SpellCast() -{ - if(!charm_cast_timer.Check()) - return; - - Mob *targ = GetTarget(); - if(!targ) - return; - - float dist = DistNoRootNoZ(*targ); - - std::vector valid_spells; - std::vector slots; - - for(uint32 x = 0; x < 9; ++x) - { - uint32 current_spell = m_pp.mem_spells[x]; - if(!IsValidSpell(current_spell)) - continue; - - if(IsBeneficialSpell(current_spell)) - { - continue; - } - - if(dist > spells[current_spell].range*spells[current_spell].range) - { - continue; - } - - if(GetMana() < spells[current_spell].mana) - { - continue; - } - - if(IsEffectInSpell(current_spell, SE_Charm)) - { - continue; - } - - if(!GetPTimers().Expired(&database, pTimerSpellStart + current_spell, false)) - { - continue; - } - - if(targ->CanBuffStack(current_spell, GetLevel(), true) < 0) - { - continue; - } - - //bard songs cause trouble atm - if(IsBardSong(current_spell)) - continue; - - valid_spells.push_back(current_spell); - slots.push_back(x); - } - - uint32 spell_to_cast = 0xFFFFFFFF; - uint32 slot_to_use = 10; - if(valid_spells.size() == 1) - { - spell_to_cast = valid_spells[0]; - slot_to_use = slots[0]; - } - else if(valid_spells.size() == 0) - { - return; - } - else - { - uint32 idx = MakeRandomInt(0, (valid_spells.size()-1)); - spell_to_cast = valid_spells[idx]; - slot_to_use = slots[idx]; - } - - if(IsMezSpell(spell_to_cast) || IsFearSpell(spell_to_cast)) - { - Mob *tar = entity_list.GetTargetForMez(this); - if(!tar) - { - tar = GetTarget(); - if(tar && IsFearSpell(spell_to_cast)) - { - if(!IsBardSong(spell_to_cast)) - { - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - } - CastSpell(spell_to_cast, tar->GetID(), slot_to_use); - return; - } - } - } - else - { - Mob *tar = GetTarget(); - if(tar) - { - if(!IsBardSong(spell_to_cast)) - { - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - } - CastSpell(spell_to_cast, tar->GetID(), slot_to_use); - return; - } - } - - -} - -void Client::AI_Process() -{ - if (!IsAIControlled()) - return; - - if (!(AIthink_timer->Check() || attack_timer.Check(false))) - return; - - if (IsCasting()) - return; - - bool engaged = IsEngaged(); - - Mob *ow = GetOwner(); - if(!engaged) - { - if(ow) - { - if(ow->IsEngaged()) - { - Mob *tar = ow->GetTarget(); - if(tar) - { - AddToHateList(tar, 1, 0, false); - } - } - } - } - - if(!ow) - { - if(!IsFeared() && !IsLD()) - { - BuffFadeByEffect(SE_Charm); - return; - } - } - - if(RuleB(Combat, EnableFearPathing)){ - if(curfp) { - if(IsRooted()) { - //make sure everybody knows were not moving, for appearance sake - if(IsMoving()) - { - if(GetTarget()) - SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - moved=false; - } - //continue on to attack code, ensuring that we execute the engaged code - engaged = true; - } else { - if(AImovement_timer->Check()) { - animation = GetRunspeed() * 21; - // Check if we have reached the last fear point - if((ABS(GetX()-fear_walkto_x) < 0.1) && (ABS(GetY()-fear_walkto_y) <0.1)) { - // Calculate a new point to run to - CalculateNewFearpoint(); - } - if(!RuleB(Pathing, Fear) || !zone->pathing) - CalculateNewPosition2(fear_walkto_x, fear_walkto_y, fear_walkto_z, GetFearSpeed(), true); - else - { - bool WaypointChanged, NodeReached; - - VERTEX Goal = UpdatePath(fear_walkto_x, fear_walkto_y, fear_walkto_z, - GetFearSpeed(), WaypointChanged, NodeReached); - - if(WaypointChanged) - tar_ndx = 20; - - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetFearSpeed()); - } - } - return; - } - } - } - - if (engaged) - { - if (IsRooted()) - SetTarget(hate_list.GetClosest(this)); - else - { - if(AItarget_check_timer->Check()) - { - SetTarget(hate_list.GetTop(this)); - } - } - - if (!GetTarget()) - return; - - if (GetTarget()->IsCorpse()) { - RemoveFromHateList(this); - return; - } - - if(DivineAura()) - return; - - bool is_combat_range = CombatRange(GetTarget()); - - if(is_combat_range) { - if(charm_class_attacks_timer.Check()) { - DoClassAttacks(GetTarget()); - } - - if (AImovement_timer->Check()) { - SetRunAnimSpeed(0); - } - if(IsMoving()) { - SetMoving(false); - moved=false; - SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); - SendPosition(); - tar_ndx =0; - } - - if(GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) { - if(attack_timer.Check()) { - Attack(GetTarget(), 13); - if(GetTarget()) { - if(CheckDoubleAttack()) { - Attack(GetTarget(), 13); - if(GetTarget()) { - bool triple_attack_success = false; - if((((GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER) - && GetLevel() >= 60) || GetSpecialAbility(SPECATK_TRIPLE)) - && CheckDoubleAttack(true)) - { - Attack(GetTarget(), 13, true); - triple_attack_success = true; - } - - if(GetTarget()) - { - //Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). - int16 flurrychance = aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance; - - if (flurrychance) - { - if(MakeRandomInt(0, 100) < flurrychance) - { - Message_StringID(MT_NPCFlurry, YOU_FLURRY); - Attack(GetTarget(), 13, false); - Attack(GetTarget(), 13, false); - } - } - - int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance; - - if (ExtraAttackChanceBonus && GetTarget()) { - ItemInst *wpn = GetInv().GetItem(SLOT_PRIMARY); - if(wpn){ - if(wpn->GetItem()->ItemType == ItemType2HSlash || - wpn->GetItem()->ItemType == ItemType2HBlunt || - wpn->GetItem()->ItemType == ItemType2HPiercing ) - { - if(MakeRandomInt(0, 100) < ExtraAttackChanceBonus) - { - Attack(GetTarget(), 13, false); - } - } - } - } - - if (GetClass() == WARRIOR || GetClass() == BERSERKER) - { - if(!dead && !berserk && this->GetHPRatio() < 30) - { - entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_START, GetName()); - berserk = true; - } - else if (berserk && this->GetHPRatio() > 30) - { - entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_END, GetName()); - berserk = false; - } - } - } - } - } - } - } - } - - if(CanThisClassDualWield() && attack_dw_timer.Check()) - { - if(GetTarget()) - { - float DualWieldProbability = 0.0f; - - int16 Ambidexterity = aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity; - DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f; // 78.0 max - int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance; - DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f; - - if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability) - { - Attack(GetTarget(), 14); - if(CheckDoubleAttack()) - { - Attack(GetTarget(), 14); - } - - } - } - } - } - else - { - if(!IsRooted()) - { - animation = 21 * GetRunspeed(); - if(!RuleB(Pathing, Aggro) || !zone->pathing) - CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed()); - else - { - bool WaypointChanged, NodeReached; - VERTEX Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), - GetRunspeed(), WaypointChanged, NodeReached); - - if(WaypointChanged) - tar_ndx = 20; - - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); - } - } - else if(IsMoving()) - { - SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - moved=false; - } - } - AI_SpellCast(); - } - else - { - if(AIfeignremember_timer->Check()) { - std::set::iterator RememberedCharID; - RememberedCharID = feign_memory_list.begin(); - while (RememberedCharID != feign_memory_list.end()) { - Client* remember_client = entity_list.GetClientByCharID(*RememberedCharID); - if (remember_client == nullptr) { - //they are gone now... - RememberedCharID = feign_memory_list.erase(RememberedCharID); - } else if (!remember_client->GetFeigned()) { - AddToHateList(remember_client->CastToMob(),1); - RememberedCharID = feign_memory_list.erase(RememberedCharID); - break; - } else { - //they are still feigned, carry on... - ++RememberedCharID; - } - } - } - - if(IsPet()) - { - Mob* owner = GetOwner(); - if(owner == nullptr) - return; - - float dist = DistNoRoot(*owner); - if (dist >= 100) - { - float speed = dist >= 225 ? GetRunspeed() : GetWalkspeed(); - animation = 21 * speed; - CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); - } - else - { - SetHeading(owner->GetHeading()); - if(moved) - { - moved=false; - SetMoving(false); - SendPosition(); - SetRunAnimSpeed(0); - } - } - } - } -} - -void Mob::AI_Process() { - if (!IsAIControlled()) - return; - - if (!(AIthink_timer->Check() || attack_timer.Check(false))) - return; - - if (IsCasting()) - return; - - bool engaged = IsEngaged(); - bool doranged = false; - - // Begin: Additions for Wiz Fear Code - // - if(RuleB(Combat, EnableFearPathing)){ - if(curfp) { - if(IsRooted()) { - //make sure everybody knows were not moving, for appearance sake - if(IsMoving()) - { - if(target) - SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - moved=false; - } - //continue on to attack code, ensuring that we execute the engaged code - engaged = true; - } else { - if(AImovement_timer->Check()) { - // Check if we have reached the last fear point - if((ABS(GetX()-fear_walkto_x) < 0.1) && (ABS(GetY()-fear_walkto_y) <0.1)) { - // Calculate a new point to run to - CalculateNewFearpoint(); - } - if(!RuleB(Pathing, Fear) || !zone->pathing) - CalculateNewPosition2(fear_walkto_x, fear_walkto_y, fear_walkto_z, GetFearSpeed(), true); - else - { - bool WaypointChanged, NodeReached; - - VERTEX Goal = UpdatePath(fear_walkto_x, fear_walkto_y, fear_walkto_z, - GetFearSpeed(), WaypointChanged, NodeReached); - - if(WaypointChanged) - tar_ndx = 20; - - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetFearSpeed()); - } - } - return; - } - } - } - - // trigger EVENT_SIGNAL if required - if(IsNPC()) { - CastToNPC()->CheckSignal(); - } - - if (engaged) - { - if (IsRooted()) - SetTarget(hate_list.GetClosest(this)); - else - { - if(AItarget_check_timer->Check()) - { - if (IsFocused()) { - if (!target) { - SetTarget(hate_list.GetTop(this)); - } - } else { - if (!ImprovedTaunt()) - SetTarget(hate_list.GetTop(this)); - } - - } - } - - if (!target) - return; - - if (target->IsCorpse()) - { - RemoveFromHateList(this); - return; - } - -#ifdef BOTS - if (IsPet() && GetOwner()->IsBot() && target == GetOwner()) - { - // this blocks all pet attacks against owner..bot pet test (copied above check) - RemoveFromHateList(this); - return; - } -#endif //BOTS - - if(DivineAura()) - return; - - if(GetSpecialAbility(TETHER)) { - float tether_range = static_cast(GetSpecialAbilityParam(TETHER, 0)); - tether_range = tether_range > 0.0f ? tether_range * tether_range : pAggroRange * pAggroRange; - - if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > tether_range) { - GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH()); - } - } else if(GetSpecialAbility(LEASH)) { - float leash_range = static_cast(GetSpecialAbilityParam(LEASH, 0)); - leash_range = leash_range > 0.0f ? leash_range * leash_range : pAggroRange * pAggroRange; - - if(DistNoRootNoZ(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY()) > leash_range) { - GMMove(CastToNPC()->GetSpawnPointX(), CastToNPC()->GetSpawnPointY(), CastToNPC()->GetSpawnPointZ(), CastToNPC()->GetSpawnPointH()); - SetHP(GetMaxHP()); - BuffFadeAll(); - WipeHateList(); - return; - } - } - - StartEnrage(); - - bool is_combat_range = CombatRange(target); - - if (is_combat_range) - { - if (AImovement_timer->Check()) - { - SetRunAnimSpeed(0); - } - if(IsMoving()) - { - SetMoving(false); - moved=false; - SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); - SendPosition(); - tar_ndx =0; - } - - //casting checked above... - if(target && !IsStunned() && !IsMezzed() && GetAppearance() != eaDead && !IsMeleeDisabled()) { - - //we should check to see if they die mid-attacks, previous - //crap of checking target for null was not gunna cut it - - //try main hand first - if(attack_timer.Check()) { - if(IsNPC()) { - int16 n_atk = CastToNPC()->GetNumberOfAttacks(); - if(n_atk <= 1) { - Attack(target, 13); - } else { - for(int i = 0; i < n_atk; ++i) { - Attack(target, 13); - } - } - } else { - Attack(target, 13); - } - - if (target) { - //we use this random value in three comparisons with different - //thresholds, and if its truely random, then this should work - //out reasonably and will save us compute resources. - int32 RandRoll = MakeRandomInt(0, 99); - if ((CanThisClassDoubleAttack() || GetSpecialAbility(SPECATK_TRIPLE) - || GetSpecialAbility(SPECATK_QUAD)) - //check double attack, this is NOT the same rules that clients use... - && RandRoll < (GetLevel() + NPCDualAttackModifier)) { - Attack(target, 13); - // lets see if we can do a triple attack with the main hand - //pets are excluded from triple and quads... - if ((GetSpecialAbility(SPECATK_TRIPLE) || GetSpecialAbility(SPECATK_QUAD)) - && !IsPet() && RandRoll < (GetLevel() + NPCTripleAttackModifier)) { - Attack(target, 13); - // now lets check the quad attack - if (GetSpecialAbility(SPECATK_QUAD) - && RandRoll < (GetLevel() + NPCQuadAttackModifier)) { - Attack(target, 13); - } - } - } - } - - if (GetSpecialAbility(SPECATK_FLURRY)) { - int flurry_chance = GetSpecialAbilityParam(SPECATK_FLURRY, 0); - flurry_chance = flurry_chance > 0 ? flurry_chance : RuleI(Combat, NPCFlurryChance); - - if (MakeRandomInt(0, 99) < flurry_chance) { - ExtraAttackOptions opts; - int cur = GetSpecialAbilityParam(SPECATK_FLURRY, 2); - if (cur > 0) - opts.damage_percent = cur / 100.0f; - - cur = GetSpecialAbilityParam(SPECATK_FLURRY, 3); - if (cur > 0) - opts.damage_flat = cur; - - cur = GetSpecialAbilityParam(SPECATK_FLURRY, 4); - if (cur > 0) - opts.armor_pen_percent = cur / 100.0f; - - cur = GetSpecialAbilityParam(SPECATK_FLURRY, 5); - if (cur > 0) - opts.armor_pen_flat = cur; - - cur = GetSpecialAbilityParam(SPECATK_FLURRY, 6); - if (cur > 0) - opts.crit_percent = cur / 100.0f; - - cur = GetSpecialAbilityParam(SPECATK_FLURRY, 7); - if (cur > 0) - opts.crit_flat = cur; - - Flurry(&opts); - } - } - - if (IsPet()) { - Mob *owner = GetOwner(); - if (owner) { - int16 flurry_chance = owner->aabonuses.PetFlurry + - owner->spellbonuses.PetFlurry + owner->itembonuses.PetFlurry; - if (flurry_chance && (MakeRandomInt(0, 99) < flurry_chance)) - Flurry(nullptr); - } - } - - if (GetSpecialAbility(SPECATK_RAMPAGE)) - { - int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0); - rampage_chance = rampage_chance > 0 ? rampage_chance : 20; - if(MakeRandomInt(0, 99) < rampage_chance) { - ExtraAttackOptions opts; - int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2); - if(cur > 0) { - opts.damage_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 3); - if(cur > 0) { - opts.damage_flat = cur; - } - - cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 4); - if(cur > 0) { - opts.armor_pen_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 5); - if(cur > 0) { - opts.armor_pen_flat = cur; - } - - cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 6); - if(cur > 0) { - opts.crit_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 7); - if(cur > 0) { - opts.crit_flat = cur; - } - Rampage(&opts); - } - } - - if (GetSpecialAbility(SPECATK_AREA_RAMPAGE)) - { - int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0); - rampage_chance = rampage_chance > 0 ? rampage_chance : 20; - if(MakeRandomInt(0, 99) < rampage_chance) { - ExtraAttackOptions opts; - int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2); - if(cur > 0) { - opts.damage_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 3); - if(cur > 0) { - opts.damage_flat = cur; - } - - cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 4); - if(cur > 0) { - opts.armor_pen_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 5); - if(cur > 0) { - opts.armor_pen_flat = cur; - } - - cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 6); - if(cur > 0) { - opts.crit_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 7); - if(cur > 0) { - opts.crit_flat = cur; - } - - AreaRampage(&opts); - } - } - } - - //now off hand - if (attack_dw_timer.Check() && CanThisClassDualWield()) - { - int myclass = GetClass(); - //can only dual wield without a weapon if your a monk - if(GetSpecialAbility(SPECATK_INNATE_DW) || (GetEquipment(MaterialSecondary) != 0 && GetLevel() > 29) || myclass == MONK || myclass == MONKGM) { - float DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel()) / 400.0f; - if(MakeRandomFloat(0.0, 1.0) < DualWieldProbability) - { - Attack(target, 14); - if (CanThisClassDoubleAttack()) - { - int32 RandRoll = MakeRandomInt(0, 99); - if (RandRoll < (GetLevel() + 20)) - { - Attack(target, 14); - } - } - } - } - } - - //now special attacks (kick, etc) - if(IsNPC()) - CastToNPC()->DoClassAttacks(target); - } - AI_EngagedCastCheck(); - } //end is within combat range - else { - //we cannot reach our target... - //underwater stuff only works with water maps in the zone! - if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { - if(!zone->watermap->InLiquid(target->GetX(), target->GetY(), target->GetZ())) { - Mob *tar = hate_list.GetTop(this); - if(tar == target) { - WipeHateList(); - Heal(); - BuffFadeAll(); - AIwalking_timer->Start(100); - pLastFightingDelayMoving = Timer::GetCurrentTime(); - return; - } else if(tar != nullptr) { - SetTarget(tar); - return; - } - } - } - - // See if we can summon the mob to us - if (!HateSummon()) - { - //could not summon them, check ranged... - if(GetSpecialAbility(SPECATK_RANGED_ATK)) - doranged = true; - - // Now pursue - // TODO: Check here for another person on hate list with close hate value - if(AI_PursueCastCheck()){ - //we did something, so do not process movement. - } - else if (AImovement_timer->Check()) - { - if(!IsRooted()) { - mlog(AI__WAYPOINTS, "Pursuing %s while engaged.", target->GetName()); - if(!RuleB(Pathing, Aggro) || !zone->pathing) - CalculateNewPosition2(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed()); - else - { - bool WaypointChanged, NodeReached; - - VERTEX Goal = UpdatePath(target->GetX(), target->GetY(), target->GetZ(), - GetRunspeed(), WaypointChanged, NodeReached); - - if(WaypointChanged) - tar_ndx = 20; - - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); - } - - } - else if(IsMoving()) { - SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); - SetRunAnimSpeed(0); - SendPosition(); - SetMoving(false); - moved=false; - - } - } - } - } - } - else - { - if(AIfeignremember_timer->Check()) { - // EverHood - 6/14/06 - // Improved Feign Death Memory - // check to see if any of our previous feigned targets have gotten up. - std::set::iterator RememberedCharID; - RememberedCharID = feign_memory_list.begin(); - while (RememberedCharID != feign_memory_list.end()) { - Client* remember_client = entity_list.GetClientByCharID(*RememberedCharID); - if (remember_client == nullptr) { - //they are gone now... - RememberedCharID = feign_memory_list.erase(RememberedCharID); - } else if (!remember_client->GetFeigned()) { - AddToHateList(remember_client->CastToMob(),1); - RememberedCharID = feign_memory_list.erase(RememberedCharID); - break; - } else { - //they are still feigned, carry on... - ++RememberedCharID; - } - } - } - if (AI_IdleCastCheck()) - { - //we processed a spell action, so do nothing else. - } - else if (AIscanarea_timer->Check()) - { - /* - * This is where NPCs look around to see if they want to attack anybody. - * - * if REVERSE_AGGRO is enabled, then this timer is disabled unless they - * have the npc_aggro flag on them, and aggro against clients is checked - * by the clients. - * - */ - - Mob* tmptar = entity_list.AICheckCloseAggro(this, GetAggroRange(), GetAssistRange()); - if (tmptar) - AddToHateList(tmptar); - } - else if (AImovement_timer->Check() && !IsRooted()) - { - SetRunAnimSpeed(0); - if (IsPet()) - { - // we're a pet, do as we're told - switch (pStandingPetOrder) - { - case SPO_Follow: - { - - Mob* owner = GetOwner(); - if(owner == nullptr) - break; - - //if(owner->IsClient()) - // printf("Pet start pos: (%f, %f, %f)\n", GetX(), GetY(), GetZ()); - - float dist = DistNoRoot(*owner); - if (dist >= 400) - { - float speed = GetWalkspeed(); - if (dist >= 5625) - speed = GetRunspeed(); - CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); - } - else - { - if(moved) - { - moved=false; - SetMoving(false); - SendPosition(); - } - } - - /* - //fix up Z - float zdiff = GetZ() - owner->GetZ(); - if(zdiff < 0) - zdiff = 0 - zdiff; - if(zdiff > 2.0f) { - SendTo(GetX(), GetY(), owner->GetZ()); - SendPosition(); - } - - if(owner->IsClient()) - printf("Pet pos: (%f, %f, %f)\n", GetX(), GetY(), GetZ()); - */ - - break; - } - case SPO_Sit: - { - SetAppearance(eaSitting, false); - break; - } - case SPO_Guard: - { - //only NPCs can guard stuff. (forced by where the guard movement code is in the AI) - if(IsNPC()) { - CastToNPC()->NextGuardPosition(); - } - break; - } - } - } - else if (GetFollowID()) - { - Mob* follow = entity_list.GetMob(GetFollowID()); - if (!follow) SetFollowID(0); - else - { - float dist2 = DistNoRoot(*follow); - int followdist = GetFollowDistance(); - - if (dist2 >= followdist) // Default follow distance is 100 - { - float speed = GetWalkspeed(); - if (dist2 >= followdist + 150) - speed = GetRunspeed(); - CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); - } - else - { - if(moved) - { - SendPosition(); - moved=false; - SetMoving(false); - } - } - } - } - else //not a pet, and not following somebody... - { - // dont move till a bit after you last fought - if (pLastFightingDelayMoving < Timer::GetCurrentTime()) - { - if (this->IsClient()) - { - // LD timer expired, drop out of world - if (this->CastToClient()->IsLD()) - this->CastToClient()->Disconnect(); - return; - } - - if(IsNPC()) - { - if(RuleB(NPC, SmartLastFightingDelayMoving) && !feign_memory_list.empty()) - { - minLastFightingDelayMoving = 0; - maxLastFightingDelayMoving = 0; - } - CastToNPC()->AI_DoMovement(); - } - } - - } - } // else if (AImovement_timer->Check()) - } - - //Do Ranged attack here - if(doranged) - { - int attacks = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0); - attacks = attacks > 0 ? attacks : 1; - for(int i = 0; i < attacks; ++i) { - RangedAttack(target); - } - } -} - -void NPC::AI_DoMovement() { - float walksp = GetMovespeed(); - if(walksp <= 0.0f) - return; //this is idle movement at walk speed, and we are unable to walk right now. - - if (roambox_distance > 0) { - if ( - roambox_movingto_x > roambox_max_x - || roambox_movingto_x < roambox_min_x - || roambox_movingto_y > roambox_max_y - || roambox_movingto_y < roambox_min_y - ) - { - float movedist = roambox_distance*roambox_distance; - float movex = MakeRandomFloat(0, movedist); - float movey = movedist - movex; - movex = sqrtf(movex); - movey = sqrtf(movey); - movex *= MakeRandomInt(0, 1) ? 1 : -1; - movey *= MakeRandomInt(0, 1) ? 1 : -1; - roambox_movingto_x = GetX() + movex; - roambox_movingto_y = GetY() + movey; - //Try to calculate new coord using distance. - if (roambox_movingto_x > roambox_max_x || roambox_movingto_x < roambox_min_x) - roambox_movingto_x -= movex * 2; - if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y) - roambox_movingto_y -= movey * 2; - //New coord is still invalid, ignore distance and just pick a new random coord. - //If we're here we may have a roambox where one side is shorter than the specified distance. Commons, Wkarana, etc. - if (roambox_movingto_x > roambox_max_x || roambox_movingto_x < roambox_min_x) - roambox_movingto_x = MakeRandomFloat(roambox_min_x+1,roambox_max_x-1); - if (roambox_movingto_y > roambox_max_y || roambox_movingto_y < roambox_min_y) - roambox_movingto_y = MakeRandomFloat(roambox_min_y+1,roambox_max_y-1); - } - - mlog(AI__WAYPOINTS, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)", - roambox_distance, roambox_min_x, roambox_max_x, roambox_min_y, roambox_max_y, roambox_movingto_x, roambox_movingto_y); - if (!CalculateNewPosition2(roambox_movingto_x, roambox_movingto_y, GetZ(), walksp, true)) - { - roambox_movingto_x = roambox_max_x + 1; // force update - pLastFightingDelayMoving = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay); - SetMoving(false); - SendPosition(); // makes mobs stop clientside - } - } - else if (roamer) - { - if (AIwalking_timer->Check()) - { - movetimercompleted=true; - AIwalking_timer->Disable(); - } - - - int16 gridno = CastToNPC()->GetGrid(); - - if (gridno > 0 || cur_wp==-2) { - if (movetimercompleted==true) { // time to pause at wp is over - - int32 spawn_id = this->GetSpawnPointID(); - LinkedListIterator iterator(zone->spawn2_list); - iterator.Reset(); - Spawn2 *found_spawn = nullptr; - - while(iterator.MoreElements()) - { - Spawn2* cur = iterator.GetData(); - iterator.Advance(); - if(cur->GetID() == spawn_id) - { - found_spawn = cur; - break; - } - } - - if (wandertype == 4 && cur_wp == CastToNPC()->GetMaxWp()) { - CastToNPC()->Depop(true); //depop and resart spawn timer - if(found_spawn) - found_spawn->SetNPCPointerNull(); - } - else if (wandertype == 6 && cur_wp == CastToNPC()->GetMaxWp()) { - CastToNPC()->Depop(false);//depop without spawn timer - if(found_spawn) - found_spawn->SetNPCPointerNull(); - } - else { - movetimercompleted=false; - - mlog(QUESTS__PATHING, "We are departing waypoint %d.", cur_wp); - - //if we were under quest control (with no grid), we are done now.. - if(cur_wp == -2) { - mlog(QUESTS__PATHING, "Non-grid quest mob has reached its quest ordered waypoint. Leaving pathing mode."); - roamer = false; - cur_wp = 0; - } - - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); - - entity_list.OpenDoorsNear(CastToNPC()); - - if(!DistractedFromGrid) { - //kick off event_waypoint depart - char temp[16]; - sprintf(temp, "%d", cur_wp); - parse->EventNPC(EVENT_WAYPOINT_DEPART, CastToNPC(), nullptr, temp, 0); - - //setup our next waypoint, if we are still on our normal grid - //remember that the quest event above could have done anything it wanted with our grid - if(gridno > 0) { - CastToNPC()->CalculateNewWaypoint(); - } - } - else { - DistractedFromGrid = false; - } - } - } // endif (movetimercompleted==true) - else if (!(AIwalking_timer->Enabled())) - { // currently moving - if (cur_wp_x == GetX() && cur_wp_y == GetY()) - { // are we there yet? then stop - mlog(AI__WAYPOINTS, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid()); - SetWaypointPause(); - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); - SetMoving(false); - if (cur_wp_heading >= 0.0) { - SetHeading(cur_wp_heading); - } - SendPosition(); - - //kick off event_waypoint arrive - char temp[16]; - sprintf(temp, "%d", cur_wp); - parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0); - - // wipe feign memory since we reached our first waypoint - if(cur_wp == 1) - ClearFeignMemory(); - } - else - { // not at waypoint yet, so keep moving - if(!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0)) - CalculateNewPosition2(cur_wp_x, cur_wp_y, cur_wp_z, walksp, true); - else - { - bool WaypointChanged; - bool NodeReached; - VERTEX Goal = UpdatePath(cur_wp_x, cur_wp_y, cur_wp_z, walksp, WaypointChanged, NodeReached); - if(WaypointChanged) - tar_ndx = 20; - - if(NodeReached) - entity_list.OpenDoorsNear(CastToNPC()); - - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, walksp, true); - } - - } - } - } // endif (gridno > 0) -// handle new quest grid command processing - else if (gridno < 0) - { // this mob is under quest control - if (movetimercompleted==true) - { // time to pause has ended - SetGrid( 0 - GetGrid()); // revert to AI control - mlog(QUESTS__PATHING, "Quest pathing is finished. Resuming on grid %d", GetGrid()); - - if(GetAppearance() != eaStanding) - SetAppearance(eaStanding, false); - - CalculateNewWaypoint(); - } - } - - } - else if (IsGuarding()) - { - bool CP2Moved; - if(!RuleB(Pathing, Guard) || !zone->pathing) - CP2Moved = CalculateNewPosition2(guard_x, guard_y, guard_z, walksp); - else - { - if(!((x_pos == guard_x) && (y_pos == guard_y) && (z_pos == guard_z))) - { - bool WaypointChanged, NodeReached; - VERTEX Goal = UpdatePath(guard_x, guard_y, guard_z, walksp, WaypointChanged, NodeReached); - if(WaypointChanged) - tar_ndx = 20; - - if(NodeReached) - entity_list.OpenDoorsNear(CastToNPC()); - - CP2Moved = CalculateNewPosition2(Goal.x, Goal.y, Goal.z, walksp); - } - else - CP2Moved = false; - - } - if (!CP2Moved) - { - if(moved) { - mlog(AI__WAYPOINTS, "Reached guard point (%.3f,%.3f,%.3f)", guard_x, guard_y, guard_z); - ClearFeignMemory(); - moved=false; - SetMoving(false); - if (GetTarget() == nullptr || DistNoRoot(*GetTarget()) >= 5*5 ) - { - SetHeading(guard_heading); - } else { - FaceTarget(GetTarget()); - } - SendPosition(); - SetAppearance(GetGuardPointAnim()); - } - } - } -} - -// Note: Mob that caused this may not get added to the hate list until after this function call completes -void Mob::AI_Event_Engaged(Mob* attacker, bool iYellForHelp) { - if (!IsAIControlled()) - return; - - if(GetAppearance() != eaStanding) - { - SetAppearance(eaStanding); - } - - if (iYellForHelp) { - if(IsPet()) { - GetOwner()->AI_Event_Engaged(attacker, iYellForHelp); - } else { - entity_list.AIYellForHelp(this, attacker); - } - } - - if(IsNPC()) - { - if(CastToNPC()->GetGrid() > 0) - { - DistractedFromGrid = true; - } - if(attacker && !attacker->IsCorpse()) - { - //Because sometimes the AIYellForHelp triggers another engaged and then immediately a not engaged - //if the target dies before it goes off - if(attacker->GetHP() > 0) - { - if(!CastToNPC()->GetCombatEvent() && GetHP() > 0) - { - parse->EventNPC(EVENT_COMBAT, CastToNPC(), attacker, "1", 0); - uint16 emoteid = GetEmoteID(); - if(emoteid != 0) - CastToNPC()->DoNPCEmote(ENTERCOMBAT,emoteid); - CastToNPC()->SetCombatEvent(true); - } - } - } - } -} - -// Note: Hate list may not be actually clear until after this function call completes -void Mob::AI_Event_NoLongerEngaged() { - if (!IsAIControlled()) - return; - this->AIwalking_timer->Start(RandomTimer(3000,20000)); - pLastFightingDelayMoving = Timer::GetCurrentTime(); - if (minLastFightingDelayMoving == maxLastFightingDelayMoving) - pLastFightingDelayMoving += minLastFightingDelayMoving; - else - pLastFightingDelayMoving += MakeRandomInt(minLastFightingDelayMoving, maxLastFightingDelayMoving); - // EverHood - So mobs don't keep running as a ghost until AIwalking_timer fires - // if they were moving prior to losing all hate - if(IsMoving()){ - SetRunAnimSpeed(0); - SetMoving(false); - SendPosition(); - } - ClearRampage(); - - if(IsNPC()) - { - if(CastToNPC()->GetCombatEvent() && GetHP() > 0) - { - if(entity_list.GetNPCByID(this->GetID())) - { - uint16 emoteid = CastToNPC()->GetEmoteID(); - parse->EventNPC(EVENT_COMBAT, CastToNPC(), nullptr, "0", 0); - if(emoteid != 0) - CastToNPC()->DoNPCEmote(LEAVECOMBAT,emoteid); - CastToNPC()->SetCombatEvent(false); - } - } - } -} - -//this gets called from InterruptSpell() for failure or SpellFinished() for success -void NPC::AI_Event_SpellCastFinished(bool iCastSucceeded, uint8 slot) { - if (slot == 1) { - uint32 recovery_time = 0; - if (iCastSucceeded) { - if (casting_spell_AIindex < AIspells.size()) { - recovery_time += spells[AIspells[casting_spell_AIindex].spellid].recovery_time; - if (AIspells[casting_spell_AIindex].recast_delay >= 0) - { - if (AIspells[casting_spell_AIindex].recast_delay < 10000) - AIspells[casting_spell_AIindex].time_cancast = Timer::GetCurrentTime() + (AIspells[casting_spell_AIindex].recast_delay*1000); - } - else - AIspells[casting_spell_AIindex].time_cancast = Timer::GetCurrentTime() + spells[AIspells[casting_spell_AIindex].spellid].recast_time; - } - if (recovery_time < AIautocastspell_timer->GetSetAtTrigger()) - recovery_time = AIautocastspell_timer->GetSetAtTrigger(); - AIautocastspell_timer->Start(recovery_time, false); - } - else - AIautocastspell_timer->Start(800, false); - casting_spell_AIindex = AIspells.size(); - } -} - - -bool NPC::AI_EngagedCastCheck() { - if (AIautocastspell_timer->Check(false)) { - AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - - mlog(AI__SPELLS, "Engaged autocast check triggered. Trying to cast healing spells then maybe offensive spells."); - Shout("KAYEN"); - // try casting a heal or gate - if (!AICastSpell(this, 100, SpellType_Heal | SpellType_Escape | SpellType_InCombatBuff)) { - // try casting a heal on nearby - if (!entity_list.AICheckCloseBeneficialSpells(this, 25, MobAISpellRange, SpellType_Heal)) { - //nobody to heal, try some detrimental spells. - if(!AICastSpell(GetTarget(), 20, SpellType_Nuke | SpellType_Lifetap | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff | SpellType_Charm | SpellType_Root)) { - //no spell to cast, try again soon. - AIautocastspell_timer->Start(RandomTimer(500, 1000), false); - } - } - } - return(true); - } - - return(false); -} - -bool NPC::AI_PursueCastCheck() { - if (AIautocastspell_timer->Check(false)) { - AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - - mlog(AI__SPELLS, "Engaged (pursuing) autocast check triggered. Trying to cast offensive spells."); - if(!AICastSpell(GetTarget(), 90, SpellType_Root | SpellType_Nuke | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Slow | SpellType_Debuff)) { - //no spell cast, try again soon. - AIautocastspell_timer->Start(RandomTimer(500, 2000), false); - } //else, spell casting finishing will reset the timer. - return(true); - } - return(false); -} - -bool NPC::AI_IdleCastCheck() { - if (AIautocastspell_timer->Check(false)) { -#if MobAI_DEBUG_Spells >= 25 - std::cout << "Non-Engaged autocast check triggered: " << this->GetName() << std::endl; -#endif - AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - if (!AICastSpell(this, 100, SpellType_Heal | SpellType_Buff | SpellType_Pet)) { - if(!entity_list.AICheckCloseBeneficialSpells(this, 33, MobAISpellRange, SpellType_Heal | SpellType_Buff)) { - //if we didnt cast any spells, our autocast timer just resets to the - //last duration it was set to... try to put up a more reasonable timer... - AIautocastspell_timer->Start(RandomTimer(1000, 5000), false); - } //else, spell casting finishing will reset the timer. - } //else, spell casting finishing will reset the timer. - return(true); - } - return(false); -} - -void Mob::StartEnrage() -{ - // dont continue if already enraged - if (bEnraged) - return; - - if(!GetSpecialAbility(SPECATK_ENRAGE)) - return; - - int hp_ratio = GetSpecialAbilityParam(SPECATK_ENRAGE, 0); - hp_ratio = hp_ratio > 0 ? hp_ratio : RuleI(NPC, StartEnrageValue); - if(GetHPRatio() > static_cast(hp_ratio)) { - return; - } - - if(RuleB(NPC, LiveLikeEnrage) && !((IsPet() && !IsCharmed() && GetOwner() && GetOwner()->IsClient()) || - (CastToNPC()->GetSwarmOwner() && entity_list.GetMob(CastToNPC()->GetSwarmOwner())->IsClient()))) { - return; - } - - Timer *timer = GetSpecialAbilityTimer(SPECATK_ENRAGE); - if (timer && !timer->Check()) - return; - - int enraged_duration = GetSpecialAbilityParam(SPECATK_ENRAGE, 1); - enraged_duration = enraged_duration > 0 ? enraged_duration : EnragedDurationTimer; - StartSpecialAbilityTimer(SPECATK_ENRAGE, enraged_duration); - - // start the timer. need to call IsEnraged frequently since we dont have callback timers :-/ - bEnraged = true; - entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_START, GetCleanName()); -} - -void Mob::ProcessEnrage(){ - if(IsEnraged()){ - Timer *timer = GetSpecialAbilityTimer(SPECATK_ENRAGE); - if(timer && timer->Check()){ - entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_END, GetCleanName()); - - int enraged_cooldown = GetSpecialAbilityParam(SPECATK_ENRAGE, 2); - enraged_cooldown = enraged_cooldown > 0 ? enraged_cooldown : EnragedTimer; - StartSpecialAbilityTimer(SPECATK_ENRAGE, enraged_cooldown); - bEnraged = false; - } - } -} - -bool Mob::IsEnraged() -{ - return bEnraged; -} - -bool Mob::Flurry(ExtraAttackOptions *opts) -{ - // this is wrong, flurry is extra attacks on the current target - Mob *target = GetTarget(); - if (target) { - if (!IsPet()) { - entity_list.MessageClose_StringID(this, true, 200, MT_NPCFlurry, NPC_FLURRY, GetCleanName(), target->GetCleanName()); - } else { - entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, NPC_FLURRY, GetCleanName(), target->GetCleanName()); - } - - int num_attacks = GetSpecialAbilityParam(SPECATK_FLURRY, 1); - num_attacks = num_attacks > 0 ? num_attacks : RuleI(Combat, MaxFlurryHits); - for (int i = 0; i < num_attacks; i++) - Attack(target, 13, false, false, false, opts); - } - return true; -} - -bool Mob::AddRampage(Mob *mob) -{ - if (!mob) - return false; - - if (!GetSpecialAbility(SPECATK_RAMPAGE)) - return false; - - for (int i = 0; i < RampageArray.size(); i++) { - // if Entity ID is already on the list don't add it again - if (mob->GetID() == RampageArray[i]) - return false; - } - RampageArray.push_back(mob->GetID()); - return true; -} - -void Mob::ClearRampage() -{ - RampageArray.clear(); -} - -bool Mob::Rampage(ExtraAttackOptions *opts) -{ - int index_hit = 0; - if (!IsPet()) - entity_list.MessageClose_StringID(this, true, 200, MT_NPCRampage, NPC_RAMPAGE, GetCleanName()); - else - entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, NPC_RAMPAGE, GetCleanName()); - - int rampage_targets = GetSpecialAbilityParam(SPECATK_RAMPAGE, 1); - if (rampage_targets == 0) // if set to 0 or not set in the DB - rampage_targets = RuleI(Combat, DefaultRampageTargets); - if (rampage_targets > RuleI(Combat, MaxRampageTargets)) - rampage_targets = RuleI(Combat, MaxRampageTargets); - for (int i = 0; i < RampageArray.size(); i++) { - if (index_hit >= rampage_targets) - break; - // range is important - Mob *m_target = entity_list.GetMob(RampageArray[i]); - if (m_target) { - if (m_target == GetTarget()) - continue; - if (CombatRange(m_target)) { - Attack(m_target, 13, false, false, false, opts); - index_hit++; - } - } - } - - if (RuleB(Combat, RampageHitsTarget) && index_hit < rampage_targets) - Attack(GetTarget(), 13, false, false, false, opts); - - return true; -} - -void Mob::AreaRampage(ExtraAttackOptions *opts) -{ - int index_hit = 0; - if (!IsPet()) { // do not know every pet AA so thought it safer to add this - entity_list.MessageClose_StringID(this, true, 200, MT_NPCRampage, AE_RAMPAGE, GetCleanName()); - } else { - entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, AE_RAMPAGE, GetCleanName()); - } - - int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1); - rampage_targets = rampage_targets > 0 ? rampage_targets : 1; - index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts); - - if(index_hit == 0) { - Attack(GetTarget(), 13, false, false, false, opts); - } -} - -uint32 Mob::GetLevelCon(uint8 mylevel, uint8 iOtherLevel) { - int16 diff = iOtherLevel - mylevel; - uint32 conlevel=0; - - if (diff == 0) - return CON_WHITE; - else if (diff >= 1 && diff <= 2) - return CON_YELLOW; - else if (diff >= 3) - return CON_RED; - - if (mylevel <= 8) - { - if (diff <= -4) - conlevel = CON_GREEN; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 9) - { - if (diff <= -6) - conlevel = CON_GREEN; - else if (diff <= -4) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 13) - { - if (diff <= -7) - conlevel = CON_GREEN; - else if (diff <= -5) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 15) - { - if (diff <= -7) - conlevel = CON_GREEN; - else if (diff <= -5) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 17) - { - if (diff <= -8) - conlevel = CON_GREEN; - else if (diff <= -6) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 21) - { - if (diff <= -9) - conlevel = CON_GREEN; - else if (diff <= -7) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 25) - { - if (diff <= -10) - conlevel = CON_GREEN; - else if (diff <= -8) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 29) - { - if (diff <= -11) - conlevel = CON_GREEN; - else if (diff <= -9) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 31) - { - if (diff <= -12) - conlevel = CON_GREEN; - else if (diff <= -9) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 33) - { - if (diff <= -13) - conlevel = CON_GREEN; - else if (diff <= -10) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 37) - { - if (diff <= -14) - conlevel = CON_GREEN; - else if (diff <= -11) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 41) - { - if (diff <= -16) - conlevel = CON_GREEN; - else if (diff <= -12) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 45) - { - if (diff <= -17) - conlevel = CON_GREEN; - else if (diff <= -13) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 49) - { - if (diff <= -18) - conlevel = CON_GREEN; - else if (diff <= -14) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 53) - { - if (diff <= -19) - conlevel = CON_GREEN; - else if (diff <= -15) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else if (mylevel <= 55) - { - if (diff <= -20) - conlevel = CON_GREEN; - else if (diff <= -15) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - else - { - if (diff <= -21) - conlevel = CON_GREEN; - else if (diff <= -16) - conlevel = CON_LIGHTBLUE; - else - conlevel = CON_BLUE; - } - return conlevel; -} - -void NPC::CheckSignal() { - if (!signal_q.empty()) { - int signal_id = signal_q.front(); - signal_q.pop_front(); - char buf[32]; - snprintf(buf, 31, "%d", signal_id); - buf[31] = '\0'; - parse->EventNPC(EVENT_SIGNAL, this, nullptr, buf, 0); - } -} - - - -/* -alter table npc_types drop column usedspells; -alter table npc_types add column npc_spells_id int(11) unsigned not null default 0 after merchant_id; -Create Table npc_spells ( - id int(11) unsigned not null auto_increment primary key, - name tinytext, - parent_list int(11) unsigned not null default 0, - attack_proc smallint(5) not null default -1, - proc_chance tinyint(3) not null default 3 - ); -create table npc_spells_entries ( - id int(11) unsigned not null auto_increment primary key, - npc_spells_id int(11) not null, - spellid smallint(5) not null default 0, - type smallint(5) unsigned not null default 0, - minlevel tinyint(3) unsigned not null default 0, - maxlevel tinyint(3) unsigned not null default 255, - manacost smallint(5) not null default '-1', - recast_delay int(11) not null default '-1', - priority smallint(5) not null default 0, - index npc_spells_id (npc_spells_id) - ); -*/ - -bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID); -bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSpellEffectID, int32 base, int32 limit, int32 max); -bool Compare_AI_Spells(AISpells_Struct i, AISpells_Struct j); - -bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { - // ok, this function should load the list, and the parent list then shove them into the struct and sort - npc_spells_id = iDBSpellsID; - AIspells.clear(); - if (iDBSpellsID == 0) { - AIautocastspell_timer->Disable(); - return false; - } - DBnpcspells_Struct* spell_list = database.GetNPCSpells(iDBSpellsID); - if (!spell_list) { - AIautocastspell_timer->Disable(); - return false; - } - DBnpcspells_Struct* parentlist = database.GetNPCSpells(spell_list->parent_list); - uint32 i; -#if MobAI_DEBUG_Spells >= 10 - std::cout << "Loading NPCSpells onto " << this->GetName() << ": dbspellsid=" << iDBSpellsID; - if (spell_list) { - std::cout << " (found, " << spell_list->numentries << "), parentlist=" << spell_list->parent_list; - if (spell_list->parent_list) { - if (parentlist) { - std::cout << " (found, " << parentlist->numentries << ")"; - } - else - std::cout << " (not found)"; - } - } - else - std::cout << " (not found)"; - std::cout << std::endl; -#endif - int16 attack_proc_spell = -1; - int8 proc_chance = 3; - if (parentlist) { - attack_proc_spell = parentlist->attack_proc; - proc_chance = parentlist->proc_chance; - for (i=0; inumentries; i++) { - if (GetLevel() >= parentlist->entries[i].minlevel && GetLevel() <= parentlist->entries[i].maxlevel && parentlist->entries[i].spellid > 0) { - if (!IsSpellInList(spell_list, parentlist->entries[i].spellid)) - { - AddSpellToNPCList(parentlist->entries[i].priority, - parentlist->entries[i].spellid, parentlist->entries[i].type, - parentlist->entries[i].manacost, parentlist->entries[i].recast_delay, - parentlist->entries[i].resist_adjust); - } - } - } - } - if (spell_list->attack_proc >= 0) { - attack_proc_spell = spell_list->attack_proc; - proc_chance = spell_list->proc_chance; - } - for (i=0; inumentries; i++) { - if (GetLevel() >= spell_list->entries[i].minlevel && GetLevel() <= spell_list->entries[i].maxlevel && spell_list->entries[i].spellid > 0) { - AddSpellToNPCList(spell_list->entries[i].priority, - spell_list->entries[i].spellid, spell_list->entries[i].type, - spell_list->entries[i].manacost, spell_list->entries[i].recast_delay, - spell_list->entries[i].resist_adjust); - } - } - std::sort(AIspells.begin(), AIspells.end(), Compare_AI_Spells); - - if (attack_proc_spell > 0) - AddProcToWeapon(attack_proc_spell, true, proc_chance); - - if (AIspells.size() == 0) - AIautocastspell_timer->Disable(); - else - AIautocastspell_timer->Trigger(); - return true; -} - -bool NPC::AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID) { - - npc_spells_effects_id = iDBSpellsEffectsID; - AIspellsEffects.clear(); - - if (iDBSpellsEffectsID == 0) - return false; - - DBnpcspellseffects_Struct* spell_effects_list = database.GetNPCSpellsEffects(iDBSpellsEffectsID); - - if (!spell_effects_list) { - return false; - } - - DBnpcspellseffects_Struct* parentlist = database.GetNPCSpellsEffects(spell_effects_list->parent_list); - - uint32 i; -#if MobAI_DEBUG_Spells >= 10 - std::cout << "Loading NPCSpellsEffects onto " << this->GetName() << ": dbspellseffectsid=" << iDBSpellsEffectsID; - if (spell_effects_list) { - std::cout << " (found, " << spell_effects_list->numentries << "), parentlist=" << spell_effects)list->parent_list; - if (spell_effects_list->parent_list) { - if (parentlist) { - std::cout << " (found, " << parentlist->numentries << ")"; - } - else - std::cout << " (not found)"; - } - } - else - std::cout << " (not found)"; - std::cout << std::endl; -#endif - - if (parentlist) { - for (i=0; inumentries; i++) { - if (GetLevel() >= parentlist->entries[i].minlevel && GetLevel() <= parentlist->entries[i].maxlevel && parentlist->entries[i].spelleffectid > 0) { - if (!IsSpellEffectInList(spell_effects_list, parentlist->entries[i].spelleffectid, parentlist->entries[i].base, - parentlist->entries[i].limit, parentlist->entries[i].max)) - { - AddSpellEffectToNPCList(parentlist->entries[i].spelleffectid, - parentlist->entries[i].base, parentlist->entries[i].limit, - parentlist->entries[i].max); - } - } - } - } - - for (i=0; inumentries; i++) { - if (GetLevel() >= spell_effects_list->entries[i].minlevel && GetLevel() <= spell_effects_list->entries[i].maxlevel && spell_effects_list->entries[i].spelleffectid > 0) { - AddSpellEffectToNPCList(spell_effects_list->entries[i].spelleffectid, - spell_effects_list->entries[i].base, spell_effects_list->entries[i].limit, - spell_effects_list->entries[i].max); - } - } - - return true; -} - -void NPC::ApplyAISpellEffects(StatBonuses* newbon) -{ - if (!AI_HasSpellsEffects()) - return; - - - - for(int i=0; i < AIspellsEffects.size(); i++) - { - Shout("ApplyAISpellEffects %i %i %i %i", AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); - ApplySpellsBonuses(0, 0, newbon, 0, false, 0,-1, - true, AIspellsEffects[i].spelleffectid, AIspellsEffects[i].base, AIspellsEffects[i].limit,AIspellsEffects[i].max); - } - - return; -} - -// adds a spell to the list, taking into account priority and resorting list as needed. -void NPC::AddSpellEffectToNPCList(uint16 iSpellEffectID, int32 base, int32 limit, int32 max) -{ - - if(!iSpellEffectID) - return; - - - HasAISpellEffects = true; - AISpellsEffects_Struct t; - - t.spelleffectid = iSpellEffectID; - t.base = base; - t.limit = limit; - t.max = max; - Shout("AddSpellEffectToNPCList %i %i %i %i", iSpellEffectID,base, limit, max ); - AIspellsEffects.push_back(t); -} - -bool IsSpellEffectInList(DBnpcspellseffects_Struct* spelleffect_list, uint16 iSpellEffectID, int32 base, int32 limit, int32 max) { - for (uint32 i=0; i < spelleffect_list->numentries; i++) { - if (spelleffect_list->entries[i].spelleffectid == iSpellEffectID && spelleffect_list->entries[i].base == base - && spelleffect_list->entries[i].limit == limit && spelleffect_list->entries[i].max == max) - return true; - } - return false; -} - -bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID) { - for (uint32 i=0; i < spell_list->numentries; i++) { - if (spell_list->entries[i].spellid == iSpellID) - return true; - } - return false; -} - -bool Compare_AI_Spells(AISpells_Struct i, AISpells_Struct j) -{ - return(i.priority > j.priority); -} - -// adds a spell to the list, taking into account priority and resorting list as needed. -void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint16 iType, - int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust) -{ - - if(!IsValidSpell(iSpellID)) - return; - - HasAISpell = true; - AISpells_Struct t; - - t.priority = iPriority; - t.spellid = iSpellID; - t.type = iType; - t.manacost = iManaCost; - t.recast_delay = iRecastDelay; - t.time_cancast = 0; - t.resist_adjust = iResistAdjust; - - AIspells.push_back(t); -} - -void NPC::RemoveSpellFromNPCList(int16 spell_id) -{ - std::vector::iterator iter = AIspells.begin(); - while(iter != AIspells.end()) - { - if((*iter).spellid == spell_id) - { - iter = AIspells.erase(iter); - continue; - } - ++iter; - } -} - -void NPC::AISpellsList(Client *c) -{ - if (!c) - return; - - for (std::vector::iterator it = AIspells.begin(); it != AIspells.end(); ++it) - c->Message(0, "%s (%d): Type %d, Priority %d", - spells[it->spellid].name, it->spellid, it->type, it->priority); - - return; -} - -DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { - if (iDBSpellsID == 0) - return 0; - - if (!npc_spells_cache) { - npc_spells_maxid = GetMaxNPCSpellsID(); - npc_spells_cache = new DBnpcspells_Struct*[npc_spells_maxid+1]; - npc_spells_loadtried = new bool[npc_spells_maxid+1]; - for (uint32 i=0; i<=npc_spells_maxid; i++) { - npc_spells_cache[i] = 0; - npc_spells_loadtried[i] = false; - } - } - - if (iDBSpellsID > npc_spells_maxid) - return 0; - if (npc_spells_cache[iDBSpellsID]) { // it's in the cache, easy =) - return npc_spells_cache[iDBSpellsID]; - } - - else if (!npc_spells_loadtried[iDBSpellsID]) { // no reason to ask the DB again if we have failed once already - npc_spells_loadtried[iDBSpellsID] = true; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list, attack_proc, proc_chance from npc_spells where id=%d", iDBSpellsID), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 tmpparent_list = atoi(row[1]); - int16 tmpattack_proc = atoi(row[2]); - uint8 tmpproc_chance = atoi(row[3]); - mysql_free_result(result); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT spellid, type, minlevel, maxlevel, manacost, recast_delay, priority, resist_adjust from npc_spells_entries where npc_spells_id=%d ORDER BY minlevel", iDBSpellsID), errbuf, &result)) { - safe_delete_array(query); - uint32 tmpSize = sizeof(DBnpcspells_Struct) + (sizeof(DBnpcspells_entries_Struct) * mysql_num_rows(result)); - npc_spells_cache[iDBSpellsID] = (DBnpcspells_Struct*) new uchar[tmpSize]; - memset(npc_spells_cache[iDBSpellsID], 0, tmpSize); - npc_spells_cache[iDBSpellsID]->parent_list = tmpparent_list; - npc_spells_cache[iDBSpellsID]->attack_proc = tmpattack_proc; - npc_spells_cache[iDBSpellsID]->proc_chance = tmpproc_chance; - npc_spells_cache[iDBSpellsID]->numentries = mysql_num_rows(result); - int j = 0; - while ((row = mysql_fetch_row(result))) { - int spell_id = atoi(row[0]); - npc_spells_cache[iDBSpellsID]->entries[j].spellid = spell_id; - npc_spells_cache[iDBSpellsID]->entries[j].type = atoi(row[1]); - npc_spells_cache[iDBSpellsID]->entries[j].minlevel = atoi(row[2]); - npc_spells_cache[iDBSpellsID]->entries[j].maxlevel = atoi(row[3]); - npc_spells_cache[iDBSpellsID]->entries[j].manacost = atoi(row[4]); - npc_spells_cache[iDBSpellsID]->entries[j].recast_delay = atoi(row[5]); - npc_spells_cache[iDBSpellsID]->entries[j].priority = atoi(row[6]); - if(row[7]) - { - npc_spells_cache[iDBSpellsID]->entries[j].resist_adjust = atoi(row[7]); - } - else - { - if(IsValidSpell(spell_id)) - { - npc_spells_cache[iDBSpellsID]->entries[j].resist_adjust = spells[spell_id].ResistDiff; - } - } - j++; - } - mysql_free_result(result); - return npc_spells_cache[iDBSpellsID]; - } - else { - std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - } - else { - mysql_free_result(result); - } - } - else { - std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - - return 0; - } - return 0; -} - -uint32 ZoneDatabase::GetMaxNPCSpellsID() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id) from npc_spells"), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 ret = 0; - if (row[0]) - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetMaxNPCSpellsID query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - - return 0; -} - -DBnpcspellseffects_Struct* ZoneDatabase::GetNPCSpellsEffects(uint32 iDBSpellsEffectsID) { - if (iDBSpellsEffectsID == 0) - return 0; - - if (!npc_spellseffects_cache) { - npc_spellseffects_maxid = GetMaxNPCSpellsEffectsID(); - npc_spellseffects_cache = new DBnpcspellseffects_Struct*[npc_spellseffects_maxid+1]; - npc_spellseffects_loadtried = new bool[npc_spellseffects_maxid+1]; - for (uint32 i=0; i<=npc_spellseffects_maxid; i++) { - npc_spellseffects_cache[i] = 0; - npc_spellseffects_loadtried[i] = false; - } - } - - if (iDBSpellsEffectsID > npc_spellseffects_maxid) - return 0; - if (npc_spellseffects_cache[iDBSpellsEffectsID]) { // it's in the cache, easy =) - return npc_spellseffects_cache[iDBSpellsEffectsID]; - } - - else if (!npc_spellseffects_loadtried[iDBSpellsEffectsID]) { // no reason to ask the DB again if we have failed once already - npc_spellseffects_loadtried[iDBSpellsEffectsID] = true; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT id, parent_list from npc_spells_effects where id=%d", iDBSpellsEffectsID), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 tmpparent_list = atoi(row[1]); - mysql_free_result(result); - if (RunQuery(query, MakeAnyLenString(&query, "SELECT spell_effect_id, minlevel, maxlevel,se_base, se_limit, se_max from npc_spells_effects_entries where npc_spells_effects_id=%d ORDER BY minlevel", iDBSpellsEffectsID), errbuf, &result)) { - safe_delete_array(query); - uint32 tmpSize = sizeof(DBnpcspellseffects_Struct) + (sizeof(DBnpcspellseffects_Struct) * mysql_num_rows(result)); - npc_spellseffects_cache[iDBSpellsEffectsID] = (DBnpcspellseffects_Struct*) new uchar[tmpSize]; - memset(npc_spellseffects_cache[iDBSpellsEffectsID], 0, tmpSize); - npc_spellseffects_cache[iDBSpellsEffectsID]->parent_list = tmpparent_list; - npc_spellseffects_cache[iDBSpellsEffectsID]->numentries = mysql_num_rows(result); - int j = 0; - while ((row = mysql_fetch_row(result))) { - int spell_effect_id = atoi(row[0]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].spelleffectid = spell_effect_id; - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].minlevel = atoi(row[1]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].maxlevel = atoi(row[2]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].base = atoi(row[3]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].limit = atoi(row[4]); - npc_spellseffects_cache[iDBSpellsEffectsID]->entries[j].max = atoi(row[5]); - j++; - } - mysql_free_result(result); - return npc_spellseffects_cache[iDBSpellsEffectsID]; - } - else { - std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - } - else { - mysql_free_result(result); - } - } - else { - std::cerr << "Error in AddNPCSpells query1 '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - return 0; - } - return 0; -} - -uint32 ZoneDatabase::GetMaxNPCSpellsEffectsID() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - - if (RunQuery(query, MakeAnyLenString(&query, "SELECT max(id) from npc_spells_effects"), errbuf, &result)) { - safe_delete_array(query); - if (mysql_num_rows(result) == 1) { - row = mysql_fetch_row(result); - uint32 ret = 0; - if (row[0]) - ret = atoi(row[0]); - mysql_free_result(result); - return ret; - } - mysql_free_result(result); - } - else { - std::cerr << "Error in GetMaxNPCSpellsEffectsID query '" << query << "' " << errbuf << std::endl; - safe_delete_array(query); - return 0; - } - - return 0; -} - diff --git a/zone/attackx.cpp b/zone/attackx.cpp deleted file mode 100644 index 3f96399be..000000000 --- a/zone/attackx.cpp +++ /dev/null @@ -1,4663 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#if EQDEBUG >= 5 -//#define ATTACK_DEBUG 20 -#endif - -#include "../common/debug.h" -#include -#include -#include -#include -#include -#include - -#include "masterentity.h" -#include "NpcAI.h" -#include "../common/packet_dump.h" -#include "../common/eq_packet_structs.h" -#include "../common/eq_constants.h" -#include "../common/skills.h" -#include "../common/spdat.h" -#include "zone.h" -#include "StringIDs.h" -#include "../common/StringUtil.h" -#include "../common/rulesys.h" -#include "QuestParserCollection.h" -#include "watermap.h" -#include "worldserver.h" -extern WorldServer worldserver; - -#ifdef _WINDOWS -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif - -extern EntityList entity_list; -extern Zone* zone; - -bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* weapon) -{ - // Determine animation - int type = 0; - if (weapon && weapon->IsType(ItemClassCommon)) { - const Item_Struct* item = weapon->GetItem(); -#if EQDEBUG >= 11 - LogFile->write(EQEMuLog::Debug, "Weapon skill:%i", item->ItemType); -#endif - switch (item->ItemType) - { - case ItemType1HSlash: // 1H Slashing - { - skillinuse = Skill1HSlashing; - type = anim1HWeapon; - break; - } - case ItemType2HSlash: // 2H Slashing - { - skillinuse = Skill2HSlashing; - type = anim2HSlashing; - break; - } - case ItemType1HPiercing: // Piercing - { - skillinuse = Skill1HPiercing; - type = animPiercing; - break; - } - case ItemType1HBlunt: // 1H Blunt - { - skillinuse = Skill1HBlunt; - type = anim1HWeapon; - break; - } - case ItemType2HBlunt: // 2H Blunt - { - skillinuse = Skill2HBlunt; - type = anim2HWeapon; - break; - } - case ItemType2HPiercing: // 2H Piercing - { - skillinuse = Skill1HPiercing; // change to Skill2HPiercing once activated - type = anim2HWeapon; - break; - } - case ItemTypeMartial: - { - skillinuse = SkillHandtoHand; - type = animHand2Hand; - break; - } - default: - { - skillinuse = SkillHandtoHand; - type = animHand2Hand; - break; - } - }// switch - } - else if(IsNPC()) { - - switch (skillinuse) - { - case Skill1HSlashing: // 1H Slashing - { - type = anim1HWeapon; - break; - } - case Skill2HSlashing: // 2H Slashing - { - type = anim2HSlashing; - break; - } - case Skill1HPiercing: // Piercing - { - type = animPiercing; - break; - } - case Skill1HBlunt: // 1H Blunt - { - type = anim1HWeapon; - break; - } - case Skill2HBlunt: // 2H Blunt - { - type = anim2HWeapon; - break; - } - case 99: // 2H Piercing // change to Skill2HPiercing once activated - { - type = anim2HWeapon; - break; - } - case SkillHandtoHand: - { - type = animHand2Hand; - break; - } - default: - { - type = animHand2Hand; - break; - } - }// switch - } - else { - skillinuse = SkillHandtoHand; - type = animHand2Hand; - } - - // If we're attacking with the secondary hand, play the dual wield anim - if (Hand == 14) // DW anim - type = animDualWield; - - DoAnim(type); - return true; -} - -// called when a mob is attacked, does the checks to see if it's a hit -// and does other mitigation checks. 'this' is the mob being attacked. -bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 chance_mod) -{ -/*/ - //Reworked a lot of this code to achieve better balance at higher levels. - //The old code basically meant that any in high level (50+) combat, - //both parties always had 95% chance to hit the other one. -/*/ - - Mob *attacker=other; - Mob *defender=this; - float chancetohit = RuleR(Combat, BaseHitChance); - - if(attacker->IsNPC() && !attacker->IsPet()) - chancetohit += RuleR(Combat, NPCBonusHitChance); - -#if ATTACK_DEBUG>=11 - LogFile->write(EQEMuLog::Debug, "CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName()); -#endif - mlog(COMBAT__TOHIT,"CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName()); - - bool pvpmode = false; - if(IsClient() && other->IsClient()) - pvpmode = true; - - if (chance_mod >= 10000) - return true; - - float bonus; - - //////////////////////////////////////////////////////// - // To hit calcs go here - //////////////////////////////////////////////////////// - - uint8 attacker_level = attacker->GetLevel() ? attacker->GetLevel() : 1; - uint8 defender_level = defender->GetLevel() ? defender->GetLevel() : 1; - - //Calculate the level difference - - mlog(COMBAT__TOHIT, "Chance to hit before level diff calc %.2f", chancetohit); - double level_difference = attacker_level - defender_level; - double range = defender->GetLevel(); - range = ((range / 4) + 3); - - if(level_difference < 0) - { - if(level_difference >= -range) - { - chancetohit += (level_difference / range) * RuleR(Combat,HitFalloffMinor); //5 - } - else if (level_difference >= -(range+3.0)) - { - chancetohit -= RuleR(Combat,HitFalloffMinor); - chancetohit += ((level_difference+range) / (3.0)) * RuleR(Combat,HitFalloffModerate); //7 - } - else - { - chancetohit -= (RuleR(Combat,HitFalloffMinor) + RuleR(Combat,HitFalloffModerate)); - chancetohit += ((level_difference+range+3.0)/12.0) * RuleR(Combat,HitFalloffMajor); //50 - } - } - else - { - chancetohit += (RuleR(Combat,HitBonusPerLevel) * level_difference); - } - - mlog(COMBAT__TOHIT, "Chance to hit after level diff calc %.2f", chancetohit); - - chancetohit -= ((float)defender->GetAGI() * RuleR(Combat, AgiHitFactor)); - - mlog(COMBAT__TOHIT, "Chance to hit after agil calc %.2f", chancetohit); - - if(attacker->IsClient()) - { - chancetohit -= (RuleR(Combat,WeaponSkillFalloff) * (attacker->CastToClient()->MaxSkill(skillinuse) - attacker->GetSkill(skillinuse))); - mlog(COMBAT__TOHIT, "Chance to hit after weapon falloff calc (attack) %.2f", chancetohit); - } - - if(defender->IsClient()) - { - chancetohit += (RuleR(Combat,WeaponSkillFalloff) * (defender->CastToClient()->MaxSkill(SkillDefense) - defender->GetSkill(SkillDefense))); - mlog(COMBAT__TOHIT, "Chance to hit after weapon falloff calc (defense) %.2f", chancetohit); - } - - //I dont think this is 100% correct, but at least it does something... - if(attacker->spellbonuses.MeleeSkillCheckSkill == skillinuse || attacker->spellbonuses.MeleeSkillCheckSkill == 255) { - chancetohit += attacker->spellbonuses.MeleeSkillCheck; - mlog(COMBAT__TOHIT, "Applied spell melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit); - } - if(attacker->itembonuses.MeleeSkillCheckSkill == skillinuse || attacker->itembonuses.MeleeSkillCheckSkill == 255) { - chancetohit += attacker->itembonuses.MeleeSkillCheck; - mlog(COMBAT__TOHIT, "Applied item melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit); - } - - //subtract off avoidance by the defender. (Live AA - Combat Agility) - bonus = defender->spellbonuses.AvoidMeleeChance + defender->itembonuses.AvoidMeleeChance + (defender->aabonuses.AvoidMeleeChance * 10); - - //AA Live - Elemental Agility - if (IsPet()) { - Mob *owner = defender->GetOwner(); - if (!owner)return false; - bonus += (owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance)*10; - } - - if(bonus > 0) { - chancetohit -= ((bonus * chancetohit) / 1000); - mlog(COMBAT__TOHIT, "Applied avoidance chance %.2f/10, yeilding %.2f", bonus, chancetohit); - } - - if(attacker->IsNPC()) - chancetohit += (chancetohit * attacker->CastToNPC()->GetAccuracyRating() / 1000); - - mlog(COMBAT__TOHIT, "Chance to hit after accuracy rating calc %.2f", chancetohit); - - float hitBonus = 0; - - /* - Kayen: Unknown if the HitChance and Accuracy effect's should modify 'chancetohit' - cumulatively or successively. For now all hitBonuses are cumulative. - */ - - hitBonus += attacker->itembonuses.HitChanceEffect[skillinuse] + - attacker->spellbonuses.HitChanceEffect[skillinuse]+ - attacker->itembonuses.HitChanceEffect[HIGHEST_SKILL+1] + - attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1]; - - //Accuracy = Spell Effect , HitChance = 'Accuracy' from Item Effect - //Only AA derived accuracy can be skill limited. ie (Precision of the Pathfinder, Dead Aim) - hitBonus += (attacker->itembonuses.Accuracy[HIGHEST_SKILL+1] + - attacker->spellbonuses.Accuracy[HIGHEST_SKILL+1] + - attacker->aabonuses.Accuracy[HIGHEST_SKILL+1] + - attacker->aabonuses.Accuracy[skillinuse] + - attacker->itembonuses.HitChance) / 15.0f; - - hitBonus += chance_mod; //Modifier applied from casted/disc skill attacks. - - chancetohit += ((chancetohit * hitBonus) / 100.0f); - - if(skillinuse == SkillArchery) - chancetohit -= (chancetohit * RuleR(Combat, ArcheryHitPenalty)) / 100.0f; - - chancetohit = mod_hit_chance(chancetohit, skillinuse, attacker); - - // Chance to hit; Max 95%, Min 30% - if(chancetohit > 1000) { - //if chance to hit is crazy high, that means a discipline is in use, and let it stay there - } - else if(chancetohit > 95) { - chancetohit = 95; - } - else if(chancetohit < 5) { - chancetohit = 5; - } - - //I dont know the best way to handle a garunteed hit discipline being used - //agains a garunteed riposte (for example) discipline... for now, garunteed hit wins - - - #if EQDEBUG>=11 - LogFile->write(EQEMuLog::Debug, "3 FINAL calculated chance to hit is: %5.2f", chancetohit); - #endif - - // - // Did we hit? - // - - float tohit_roll = MakeRandomFloat(0, 100); - - mlog(COMBAT__TOHIT, "Final hit chance: %.2f%%. Hit roll %.2f", chancetohit, tohit_roll); - - return(tohit_roll <= chancetohit); -} - - -bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) -{ - /* solar: called when a mob is attacked, does the checks to see if it's a hit - * and does other mitigation checks. 'this' is the mob being attacked. - * - * special return values: - * -1 - block - * -2 - parry - * -3 - riposte - * -4 - dodge - * - */ - float skill; - float bonus; - float RollTable[4] = {0,0,0,0}; - float roll; - Mob *attacker=other; - Mob *defender=this; - - //garunteed hit - bool ghit = false; - if((attacker->spellbonuses.MeleeSkillCheck + attacker->itembonuses.MeleeSkillCheck) > 500) - ghit = true; - - ////////////////////////////////////////////////////////// - // make enrage same as riposte - ///////////////////////////////////////////////////////// - if (IsEnraged() && other->InFrontMob(this, other->GetX(), other->GetY())) { - damage = -3; - mlog(COMBAT__DAMAGE, "I am enraged, riposting frontal attack."); - } - - ///////////////////////////////////////////////////////// - // riposte - ///////////////////////////////////////////////////////// - float riposte_chance = 0.0f; - if (CanRiposte && damage > 0 && CanThisClassRiposte() && other->InFrontMob(this, other->GetX(), other->GetY())) - { - riposte_chance = (100.0f + (float)defender->aabonuses.RiposteChance + (float)defender->spellbonuses.RiposteChance + (float)defender->itembonuses.RiposteChance) / 100.0f; - skill = GetSkill(SkillRiposte); - if (IsClient()) { - CastToClient()->CheckIncreaseSkill(SkillRiposte, other, -10); - } - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetDEX()/200); - bonus *= riposte_chance; - bonus = mod_riposte_chance(bonus, attacker); - RollTable[0] = bonus + (itembonuses.HeroicDEX / 25); // 25 heroic = 1%, applies to ripo, parry, block - } - } - - /////////////////////////////////////////////////////// - // block - /////////////////////////////////////////////////////// - - bool bBlockFromRear = false; - bool bShieldBlockFromRear = false; - - if (this->IsClient()) { - int aaChance = 0; - - // a successful roll on this does not mean a successful block is forthcoming. only that a chance to block - // from a direction other than the rear is granted. - - //Live AA - HightenedAwareness - int BlockBehindChance = aabonuses.BlockBehind + spellbonuses.BlockBehind + itembonuses.BlockBehind; - - if (BlockBehindChance && (BlockBehindChance > MakeRandomInt(1, 100))){ - bBlockFromRear = true; - - if (spellbonuses.BlockBehind || itembonuses.BlockBehind) - bShieldBlockFromRear = true; //This bonus should allow a chance to Shield Block from behind. - } - } - - float block_chance = 0.0f; - if (damage > 0 && CanThisClassBlock() && (other->InFrontMob(this, other->GetX(), other->GetY()) || bBlockFromRear)) { - block_chance = (100.0f + (float)spellbonuses.IncreaseBlockChance + (float)itembonuses.IncreaseBlockChance) / 100.0f; - skill = CastToClient()->GetSkill(SkillBlock); - if (IsClient()) { - CastToClient()->CheckIncreaseSkill(SkillBlock, other, -10); - } - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/35.0 + (GetDEX()/200); - bonus = mod_block_chance(bonus, attacker); - RollTable[1] = RollTable[0] + (bonus * block_chance); - } - } - else{ - RollTable[1] = RollTable[0]; - } - - if(damage > 0 && HasShieldEquiped() && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) - && (other->InFrontMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) { - - float bonusShieldBlock = 0.0f; - bonusShieldBlock = aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock; - RollTable[1] += bonusShieldBlock; - } - - if(damage > 0 && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) - && (other->InFrontMob(this, other->GetX(), other->GetY()) || bShieldBlockFromRear)) { - bool equiped2 = CastToClient()->m_inv.GetItem(13); - if(equiped2) { - uint8 TwoHandBlunt = CastToClient()->m_inv.GetItem(13)->GetItem()->ItemType; - float bonusStaffBlock = 0.0f; - if(TwoHandBlunt == ItemType2HBlunt) { - - bonusStaffBlock = aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock; - RollTable[1] += bonusStaffBlock; - } - } - } - - ////////////////////////////////////////////////////// - // parry - ////////////////////////////////////////////////////// - float parry_chance = 0.0f; - if (damage > 0 && CanThisClassParry() && other->InFrontMob(this, other->GetX(), other->GetY())) - { - parry_chance = (100.0f + (float)defender->spellbonuses.ParryChance + (float)defender->itembonuses.ParryChance) / 100.0f; - skill = CastToClient()->GetSkill(SkillParry); - if (IsClient()) { - CastToClient()->CheckIncreaseSkill(SkillParry, other, -10); - } - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetDEX()/200); - bonus *= parry_chance; - bonus = mod_parry_chance(bonus, attacker); - RollTable[2] = RollTable[1] + bonus; - } - } - else{ - RollTable[2] = RollTable[1]; - } - - //////////////////////////////////////////////////////// - // dodge - //////////////////////////////////////////////////////// - float dodge_chance = 0.0f; - if (damage > 0 && CanThisClassDodge() && other->InFrontMob(this, other->GetX(), other->GetY())) - { - dodge_chance = (100.0f + (float)defender->spellbonuses.DodgeChance + (float)defender->itembonuses.DodgeChance) / 100.0f; - skill = CastToClient()->GetSkill(SkillDodge); - if (IsClient()) { - CastToClient()->CheckIncreaseSkill(SkillDodge, other, -10); - } - - if (!ghit) { //if they are not using a garunteed hit discipline - bonus = 2.0 + skill/60.0 + (GetAGI()/200); - bonus *= dodge_chance; - //DCBOOMKAR - bonus = mod_dodge_chance(bonus, attacker); - RollTable[3] = RollTable[2] + bonus - (itembonuses.HeroicDEX / 25) + (itembonuses.HeroicAGI / 25); - } - } - else{ - RollTable[3] = RollTable[2]; - } - - if(damage > 0){ - roll = MakeRandomFloat(0,100); - if(roll <= RollTable[0]){ - damage = -3; - } - else if(roll <= RollTable[1]){ - damage = -1; - } - else if(roll <= RollTable[2]){ - damage = -2; - } - else if(roll <= RollTable[3]){ - damage = -4; - } - } - - mlog(COMBAT__DAMAGE, "Final damage after all avoidances: %d", damage); - - if (damage < 0) - return true; - return false; -} - -void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts) -{ - if (damage <= 0) - return; - - Mob* defender = this; - float aa_mit = (aabonuses.CombatStability + itembonuses.CombatStability + - spellbonuses.CombatStability) / 100.0f; - - if (RuleB(Combat, UseIntervalAC)) { - float softcap = (GetSkill(SkillDefense) + GetLevel()) * - RuleR(Combat, SoftcapFactor) * (1.0 + aa_mit); - float mitigation_rating = 0.0; - float attack_rating = 0.0; - int shield_ac = 0; - int armor = 0; - float weight = 0.0; - - float monkweight = RuleI(Combat, MonkACBonusWeight); - monkweight = mod_monk_weight(monkweight, attacker); - - if (IsClient()) { - armor = CastToClient()->GetRawACNoShield(shield_ac); - weight = (CastToClient()->CalcCurrentWeight() / 10.0); - } else if (IsNPC()) { - armor = CastToNPC()->GetRawAC(); - - if (!IsPet()) - armor = (armor / RuleR(Combat, NPCACFactor)); - - armor += spellbonuses.AC + itembonuses.AC + 1; - } - - if (opts) { - armor *= (1.0f - opts->armor_pen_percent); - armor -= opts->armor_pen_flat; - } - - if (RuleB(Combat, OldACSoftcapRules)) { - if (GetClass() == WIZARD || GetClass() == MAGICIAN || - GetClass() == NECROMANCER || GetClass() == ENCHANTER) - softcap = RuleI(Combat, ClothACSoftcap); - else if (GetClass() == MONK && weight <= monkweight) - softcap = RuleI(Combat, MonkACSoftcap); - else if(GetClass() == DRUID || GetClass() == BEASTLORD || GetClass() == MONK) - softcap = RuleI(Combat, LeatherACSoftcap); - else if(GetClass() == SHAMAN || GetClass() == ROGUE || - GetClass() == BERSERKER || GetClass() == RANGER) - softcap = RuleI(Combat, ChainACSoftcap); - else - softcap = RuleI(Combat, PlateACSoftcap); - } - - softcap += shield_ac; - armor += shield_ac; - if (RuleB(Combat, OldACSoftcapRules)) - softcap += (softcap * (aa_mit * RuleR(Combat, AAMitigationACFactor))); - if (armor > softcap) { - int softcap_armor = armor - softcap; - if (RuleB(Combat, OldACSoftcapRules)) { - if (GetClass() == WARRIOR) - softcap_armor = softcap_armor * RuleR(Combat, WarriorACSoftcapReturn); - else if (GetClass() == SHADOWKNIGHT || GetClass() == PALADIN || - (GetClass() == MONK && weight <= monkweight)) - softcap_armor = softcap_armor * RuleR(Combat, KnightACSoftcapReturn); - else if (GetClass() == CLERIC || GetClass() == BARD || - GetClass() == BERSERKER || GetClass() == ROGUE || - GetClass() == SHAMAN || GetClass() == MONK) - softcap_armor = softcap_armor * RuleR(Combat, LowPlateChainACSoftcapReturn); - else if (GetClass() == RANGER || GetClass() == BEASTLORD) - softcap_armor = softcap_armor * RuleR(Combat, LowChainLeatherACSoftcapReturn); - else if (GetClass() == WIZARD || GetClass() == MAGICIAN || - GetClass() == NECROMANCER || GetClass() == ENCHANTER || - GetClass() == DRUID) - softcap_armor = softcap_armor * RuleR(Combat, CasterACSoftcapReturn); - else - softcap_armor = softcap_armor * RuleR(Combat, MiscACSoftcapReturn); - } else { - if (GetClass() == WARRIOR) - softcap_armor *= RuleR(Combat, WarACSoftcapReturn); - else if (GetClass() == PALADIN || GetClass() == SHADOWKNIGHT) - softcap_armor *= RuleR(Combat, PalShdACSoftcapReturn); - else if (GetClass() == CLERIC || GetClass() == RANGER || - GetClass() == MONK || GetClass() == BARD) - softcap_armor *= RuleR(Combat, ClrRngMnkBrdACSoftcapReturn); - else if (GetClass() == DRUID || GetClass() == NECROMANCER || - GetClass() == WIZARD || GetClass() == ENCHANTER || - GetClass() == MAGICIAN) - softcap_armor *= RuleR(Combat, DruNecWizEncMagACSoftcapReturn); - else if (GetClass() == ROGUE || GetClass() == SHAMAN || - GetClass() == BEASTLORD || GetClass() == BERSERKER) - softcap_armor *= RuleR(Combat, RogShmBstBerACSoftcapReturn); - else - softcap_armor *= RuleR(Combat, MiscACSoftcapReturn); - } - armor = softcap + softcap_armor; - } - - if (GetClass() == WIZARD || GetClass() == MAGICIAN || - GetClass() == NECROMANCER || GetClass() == ENCHANTER) - mitigation_rating = ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10) / 4.0) + armor + 1; - else - mitigation_rating = ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10) / 3.0) + (armor * 1.333333) + 1; - mitigation_rating *= 0.847; - - mitigation_rating = mod_mitigation_rating(mitigation_rating, attacker); - - if (attacker->IsClient()) - attack_rating = (attacker->CastToClient()->CalcATK() + ((attacker->GetSTR()-66) * 0.9) + (attacker->GetSkill(SkillOffense)*1.345)); - else - attack_rating = (attacker->GetATK() + (attacker->GetSkill(SkillOffense)*1.345) + ((attacker->GetSTR()-66) * 0.9)); - - attack_rating = attacker->mod_attack_rating(attack_rating, this); - - damage = GetMeleeMitDmg(attacker, damage, minhit, mitigation_rating, attack_rating); - } else { - //////////////////////////////////////////////////////// - // Scorpious2k: Include AC in the calculation - // use serverop variables to set values - int myac = GetAC(); - if(opts) { - myac *= (1.0f - opts->armor_pen_percent); - myac -= opts->armor_pen_flat; - } - - if (damage > 0 && myac > 0) { - int acfail=1000; - char tmp[10]; - - if (database.GetVariable("ACfail", tmp, 9)) { - acfail = (int) (atof(tmp) * 100); - if (acfail>100) acfail=100; - } - - if (acfail<=0 || MakeRandomInt(0, 100)>acfail) { - float acreduction=1; - int acrandom=300; - if (database.GetVariable("ACreduction", tmp, 9)) - { - acreduction=atof(tmp); - if (acreduction>100) acreduction=100; - } - - if (database.GetVariable("ACrandom", tmp, 9)) - { - acrandom = (int) ((atof(tmp)+1) * 100); - if (acrandom>10100) acrandom=10100; - } - - if (acreduction>0) { - damage -= (int) (GetAC() * acreduction/100.0f); - } - if (acrandom>0) { - damage -= (myac * MakeRandomInt(0, acrandom) / 10000); - } - if (damage<1) damage=1; - mlog(COMBAT__DAMAGE, "AC Damage Reduction: fail chance %d%%. Failed. Reduction %.3f%%, random %d. Resulting damage %d.", acfail, acreduction, acrandom, damage); - } else { - mlog(COMBAT__DAMAGE, "AC Damage Reduction: fail chance %d%%. Did not fail.", acfail); - } - } - - damage -= (aa_mit * damage); - - if(damage != 0 && damage < minhit) - damage = minhit; - //reduce the damage from shielding item and aa based on the min dmg - //spells offer pure mitigation - damage -= (minhit * defender->itembonuses.MeleeMitigation / 100); - damage -= (damage * defender->spellbonuses.MeleeMitigation / 100); - } - - if (damage < 0) - damage = 0; -} - -// This is called when the Mob is the one being hit -int32 Mob::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, - float mit_rating, float atk_rating) -{ - float d = 10.0; - float mit_roll = MakeRandomFloat(0, mit_rating); - float atk_roll = MakeRandomFloat(0, atk_rating); - - if (atk_roll > mit_roll) { - float a_diff = atk_roll - mit_roll; - float thac0 = atk_rating * RuleR(Combat, ACthac0Factor); - float thac0cap = attacker->GetLevel() * 9 + 20; - if (thac0 > thac0cap) - thac0 = thac0cap; - - d -= 10.0 * (a_diff / thac0); - } else if (mit_roll > atk_roll) { - float m_diff = mit_roll - atk_roll; - float thac20 = mit_rating * RuleR(Combat, ACthac20Factor); - float thac20cap = GetLevel() * 9 + 20; - if (thac20 > thac20cap) - thac20 = thac20cap; - - d += 10.0 * (m_diff / thac20); - } - - if (d < 0.0) - d = 0.0; - else if (d > 20.0) - d = 20.0; - - float interval = (damage - minhit) / 20.0; - damage -= ((int)d * interval); - - damage -= (minhit * itembonuses.MeleeMitigation / 100); - damage -= (damage * spellbonuses.MeleeMitigation / 100); - return damage; -} - -// This is called when the Client is the one being hit -int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, - float mit_rating, float atk_rating) -{ - if (!attacker->IsNPC() || RuleB(Combat, UseOldDamageIntervalRules)) - return Mob::GetMeleeMitDmg(attacker, damage, minhit, mit_rating, atk_rating); - int d = 10; - // floats for the rounding issues - float dmg_interval = (damage - minhit) / 19.0; - float dmg_bonus = minhit - dmg_interval; - float spellMeleeMit = spellbonuses.MeleeMitigation / 100.0; - if (GetClass() == WARRIOR) - spellMeleeMit += 0.05; - dmg_bonus -= dmg_bonus * (itembonuses.MeleeMitigation / 100.0); - dmg_interval -= dmg_interval * spellMeleeMit; - - float mit_roll = MakeRandomFloat(0, mit_rating); - float atk_roll = MakeRandomFloat(0, atk_rating); - - if (atk_roll > mit_roll) { - float a_diff = atk_roll - mit_roll; - float thac0 = atk_rating * RuleR(Combat, ACthac0Factor); - float thac0cap = attacker->GetLevel() * 9 + 20; - if (thac0 > thac0cap) - thac0 = thac0cap; - - d += 10 * (a_diff / thac0); - } else if (mit_roll > atk_roll) { - float m_diff = mit_roll - atk_roll; - float thac20 = mit_rating * RuleR(Combat, ACthac20Factor); - float thac20cap = GetLevel() * 9 + 20; - if (thac20 > thac20cap) - thac20 = thac20cap; - - d -= 10 * (m_diff / thac20); - } - - if (d < 1) - d = 1; - else if (d > 20) - d = 20; - - return static_cast((dmg_bonus + dmg_interval * d)); -} - -//Returns the weapon damage against the input mob -//if we cannot hit the mob with the current weapon we will get a value less than or equal to zero -//Else we know we can hit. -//GetWeaponDamage(mob*, const Item_Struct*) is intended to be used for mobs or any other situation where we do not have a client inventory item -//GetWeaponDamage(mob*, const ItemInst*) is intended to be used for situations where we have a client inventory item -int Mob::GetWeaponDamage(Mob *against, const Item_Struct *weapon_item) { - int dmg = 0; - int banedmg = 0; - - //can't hit invulnerable stuff with weapons. - if(against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)){ - return 0; - } - - //check to see if our weapons or fists are magical. - if(against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)){ - if(weapon_item){ - if(weapon_item->Magic){ - dmg = weapon_item->Damage; - - //this is more for non weapon items, ex: boots for kick - //they don't have a dmg but we should be able to hit magical - dmg = dmg <= 0 ? 1 : dmg; - } - else - return 0; - } - else{ - if((GetClass() == MONK || GetClass() == BEASTLORD) && GetLevel() >= 30){ - dmg = GetMonkHandToHandDamage(); - } - else if(GetOwner() && GetLevel() >= RuleI(Combat, PetAttackMagicLevel)){ - //pets wouldn't actually use this but... - //it gives us an idea if we can hit due to the dual nature of this function - dmg = 1; - } - else if(GetSpecialAbility(SPECATK_MAGICAL)) - { - dmg = 1; - } - else - return 0; - } - } - else{ - if(weapon_item){ - dmg = weapon_item->Damage; - - dmg = dmg <= 0 ? 1 : dmg; - } - else{ - if(GetClass() == MONK || GetClass() == BEASTLORD){ - dmg = GetMonkHandToHandDamage(); - } - else{ - dmg = 1; - } - } - } - - int eledmg = 0; - if(!against->GetSpecialAbility(IMMUNE_MAGIC)){ - if(weapon_item && weapon_item->ElemDmgAmt){ - //we don't check resist for npcs here - eledmg = weapon_item->ElemDmgAmt; - dmg += eledmg; - } - } - - if(against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)){ - if(weapon_item){ - if(weapon_item->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->BaneDmgAmt; - } - - if(weapon_item->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->BaneDmgRaceAmt; - } - } - - if(!eledmg && !banedmg){ - if(!GetSpecialAbility(SPECATK_BANE)) - return 0; - else - return 1; - } - else - dmg += banedmg; - } - else{ - if(weapon_item){ - if(weapon_item->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->BaneDmgAmt; - } - - if(weapon_item->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->BaneDmgRaceAmt; - } - } - - dmg += (banedmg + eledmg); - } - - if(dmg <= 0){ - return 0; - } - else - return dmg; -} - -int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate) -{ - int dmg = 0; - int banedmg = 0; - - if(!against || against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)){ - return 0; - } - - //check for items being illegally attained - if(weapon_item){ - const Item_Struct *mWeaponItem = weapon_item->GetItem(); - if(mWeaponItem){ - if(mWeaponItem->ReqLevel > GetLevel()){ - return 0; - } - - if(!weapon_item->IsEquipable(GetBaseRace(), GetClass())){ - return 0; - } - } - else{ - return 0; - } - } - - if(against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)){ - if(weapon_item){ - // check to see if the weapon is magic - bool MagicWeapon = false; - if(weapon_item->GetItem() && weapon_item->GetItem()->Magic) - MagicWeapon = true; - else { - if(spellbonuses.MagicWeapon || itembonuses.MagicWeapon) - MagicWeapon = true; - } - - if(MagicWeapon) { - - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - dmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->Damage); - } - else{ - dmg = weapon_item->GetItem()->Damage; - } - - for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - dmg += weapon_item->GetAugment(x)->GetItem()->Damage; - if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt; - } - } - dmg = dmg <= 0 ? 1 : dmg; - } - else - return 0; - } - else{ - if((GetClass() == MONK || GetClass() == BEASTLORD) && GetLevel() >= 30){ - dmg = GetMonkHandToHandDamage(); - if (hate) *hate += dmg; - } - else if(GetOwner() && GetLevel() >= RuleI(Combat, PetAttackMagicLevel)){ //pets wouldn't actually use this but... - dmg = 1; //it gives us an idea if we can hit - } - else if(GetSpecialAbility(SPECATK_MAGICAL)){ - dmg = 1; - } - else - return 0; - } - } - else{ - if(weapon_item){ - if(weapon_item->GetItem()){ - - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - dmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->Damage); - } - else{ - dmg = weapon_item->GetItem()->Damage; - } - - for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - dmg += weapon_item->GetAugment(x)->GetItem()->Damage; - if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt; - } - } - dmg = dmg <= 0 ? 1 : dmg; - } - } - else{ - if(GetClass() == MONK || GetClass() == BEASTLORD){ - dmg = GetMonkHandToHandDamage(); - if (hate) *hate += dmg; - } - else{ - dmg = 1; - } - } - } - - int eledmg = 0; - if(!against->GetSpecialAbility(IMMUNE_MAGIC)){ - if(weapon_item && weapon_item->GetItem() && weapon_item->GetItem()->ElemDmgAmt){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - eledmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->ElemDmgAmt); - } - else{ - eledmg = weapon_item->GetItem()->ElemDmgAmt; - } - - if(eledmg) - { - eledmg = (eledmg * against->ResistSpell(weapon_item->GetItem()->ElemDmgType, 0, this) / 100); - } - } - - if(weapon_item){ - for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt) - eledmg += (weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt * against->ResistSpell(weapon_item->GetAugment(x)->GetItem()->ElemDmgType, 0, this) / 100); - } - } - } - } - - if(against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)){ - if(weapon_item && weapon_item->GetItem()){ - if(weapon_item->GetItem()->BaneDmgBody == against->GetBodyType()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgAmt; - } - } - - if(weapon_item->GetItem()->BaneDmgRace == against->GetRace()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgRaceAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgRaceAmt; - } - } - - for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt; - } - - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgRaceAmt; - } - } - } - } - - if(!eledmg && !banedmg) - { - if(!GetSpecialAbility(SPECATK_BANE)) - return 0; - else - return 1; - } - else { - dmg += (banedmg + eledmg); - if (hate) *hate += banedmg; - } - } - else{ - if(weapon_item && weapon_item->GetItem()){ - if(weapon_item->GetItem()->BaneDmgBody == against->GetBodyType()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgAmt; - } - } - - if(weapon_item->GetItem()->BaneDmgRace == against->GetRace()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgRaceAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgRaceAmt; - } - } - - for(int x = 0; x < MAX_AUGMENT_SLOTS; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt; - } - - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgRaceAmt; - } - } - } - } - dmg += (banedmg + eledmg); - if (hate) *hate += banedmg; - } - - if(dmg <= 0){ - return 0; - } - else - return dmg; -} - -//note: throughout this method, setting `damage` to a negative is a way to -//stop the attack calculations -// IsFromSpell added to allow spell effects to use Attack. (Mainly for the Rampage AA right now.) -bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) -{ - if (!other) { - SetTarget(nullptr); - LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Client::Attack() for evaluation!"); - return false; - } - - if(!GetTarget()) - SetTarget(other); - - mlog(COMBAT__ATTACKS, "Attacking %s with hand %d %s", other?other->GetName():"(nullptr)", Hand, bRiposte?"(this is a riposte)":""); - - //SetAttackTimer(); - if ( - (IsCasting() && GetClass() != BARD && !IsFromSpell) - || other == nullptr - || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) - || (GetHP() < 0) - || (!IsAttackAllowed(other)) - ) { - mlog(COMBAT__ATTACKS, "Attack canceled, invalid circumstances."); - return false; // Only bards can attack while casting - } - - if(DivineAura() && !GetGM()) {//cant attack while invulnerable unless your a gm - mlog(COMBAT__ATTACKS, "Attack canceled, Divine Aura is in effect."); - Message_StringID(MT_DefaultText, DIVINE_AURA_NO_ATK); //You can't attack while invulnerable! - return false; - } - - if (GetFeigned()) - return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code. - - - ItemInst* weapon; - if (Hand == 14){ // Kaiyodo - Pick weapon from the attacking hand - weapon = GetInv().GetItem(SLOT_SECONDARY); - OffHandAtk(true); - } - else{ - weapon = GetInv().GetItem(SLOT_PRIMARY); - OffHandAtk(false); - } - - if(weapon != nullptr) { - if (!weapon->IsWeapon()) { - mlog(COMBAT__ATTACKS, "Attack canceled, Item %s (%d) is not a weapon.", weapon->GetItem()->Name, weapon->GetID()); - return(false); - } - mlog(COMBAT__ATTACKS, "Attacking with weapon: %s (%d)", weapon->GetItem()->Name, weapon->GetID()); - } else { - mlog(COMBAT__ATTACKS, "Attacking without a weapon."); - } - - // calculate attack_skill and skillinuse depending on hand and weapon - // also send Packet to near clients - SkillUseTypes skillinuse; - AttackAnimation(skillinuse, Hand, weapon); - mlog(COMBAT__ATTACKS, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse); - - /// Now figure out damage - int damage = 0; - uint8 mylevel = GetLevel() ? GetLevel() : 1; - uint32 hate = 0; - if (weapon) hate = weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt; - int weapon_damage = GetWeaponDamage(other, weapon, &hate); - if (hate == 0 && weapon_damage > 1) hate = weapon_damage; - - //if weapon damage > 0 then we know we can hit the target with this weapon - //otherwise we cannot and we set the damage to -5 later on - if(weapon_damage > 0){ - - //Berserker Berserk damage bonus - if(IsBerserk() && GetClass() == BERSERKER){ - int bonus = 3 + GetLevel()/10; //unverified - weapon_damage = weapon_damage * (100+bonus) / 100; - mlog(COMBAT__DAMAGE, "Berserker damage bonus increases DMG to %d", weapon_damage); - } - - //try a finishing blow.. if successful end the attack - if(TryFinishingBlow(other, skillinuse)) - return (true); - - int min_hit = 1; - int max_hit = (2*weapon_damage*GetDamageTable(skillinuse)) / 100; - - if(GetLevel() < 10 && max_hit > RuleI(Combat, HitCapPre10)) - max_hit = (RuleI(Combat, HitCapPre10)); - else if(GetLevel() < 20 && max_hit > RuleI(Combat, HitCapPre20)) - max_hit = (RuleI(Combat, HitCapPre20)); - - CheckIncreaseSkill(skillinuse, other, -15); - CheckIncreaseSkill(SkillOffense, other, -15); - - - // *************************************************************** - // *** Calculate the damage bonus, if applicable, for this hit *** - // *************************************************************** - -#ifndef EQEMU_NO_WEAPON_DAMAGE_BONUS - - // If you include the preprocessor directive "#define EQEMU_NO_WEAPON_DAMAGE_BONUS", that indicates that you do not - // want damage bonuses added to weapon damage at all. This feature was requested by ChaosSlayer on the EQEmu Forums. - // - // This is not recommended for normal usage, as the damage bonus represents a non-trivial component of the DPS output - // of weapons wielded by higher-level melee characters (especially for two-handed weapons). - - int ucDamageBonus = 0; - - if( Hand == 13 && GetLevel() >= 28 && IsWarriorClass() ) - { - // Damage bonuses apply only to hits from the main hand (Hand == 13) by characters level 28 and above - // who belong to a melee class. If we're here, then all of these conditions apply. - - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); - - min_hit += (int) ucDamageBonus; - max_hit += (int) ucDamageBonus; - hate += ucDamageBonus; - } -#endif - //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. - if (Hand==14) { - if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); - - min_hit += (int) ucDamageBonus; - max_hit += (int) ucDamageBonus; - hate += ucDamageBonus; - } - } - - min_hit += min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100; - - if(max_hit < min_hit) - max_hit = min_hit; - - if(RuleB(Combat, UseIntervalAC)) - damage = max_hit; - else - damage = MakeRandomInt(min_hit, max_hit); - - damage = mod_client_damage(damage, skillinuse, Hand, weapon, other); - - mlog(COMBAT__DAMAGE, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)", - damage, min_hit, max_hit, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel); - - if(opts) { - damage *= opts->damage_percent; - damage += opts->damage_flat; - hate *= opts->hate_percent; - hate += opts->hate_flat; - } - - //check to see if we hit.. - if(!other->CheckHitChance(this, skillinuse, Hand)) { - mlog(COMBAT__ATTACKS, "Attack missed. Damage set to 0."); - damage = 0; - } else { //we hit, try to avoid it - other->AvoidDamage(this, damage); - other->MeleeMitigation(this, damage, min_hit, opts); - if(damage > 0) { - ApplyMeleeDamageBonus(skillinuse, damage); - damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); - TryCriticalHit(other, skillinuse, damage, opts); - } - mlog(COMBAT__DAMAGE, "Final damage after all reductions: %d", damage); - } - - //riposte - bool slippery_attack = false; // Part of hack to allow riposte to become a miss, but still allow a Strikethrough chance (like on Live) - if (damage == -3) { - if (bRiposte) return false; - else { - if (Hand == 14) {// Do we even have it & was attack with mainhand? If not, don't bother with other calculations - //Live AA - SlipperyAttacks - //This spell effect most likely directly modifies the actual riposte chance when using offhand attack. - int16 OffhandRiposteFail = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail; - OffhandRiposteFail *= -1; //Live uses a negative value for this. - - if (OffhandRiposteFail && - (OffhandRiposteFail > 99 || (MakeRandomInt(0, 100) < OffhandRiposteFail))) { - damage = 0; // Counts as a miss - slippery_attack = true; - } else - DoRiposte(other); - if (IsDead()) return false; - } - else - DoRiposte(other); - if (IsDead()) return false; - } - } - - if (((damage < 0) || slippery_attack) && !bRiposte && !IsStrikethrough) { // Hack to still allow Strikethrough chance w/ Slippery Attacks AA - int16 bonusStrikeThrough = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; - - if(bonusStrikeThrough && (MakeRandomInt(0, 100) < bonusStrikeThrough)) { - Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses! - Attack(other, Hand, false, true); // Strikethrough only gives another attempted hit - return false; - } - } - } - else{ - damage = -5; - } - - // Hate Generation is on a per swing basis, regardless of a hit, miss, or block, its always the same. - // If we are this far, this means we are atleast making a swing. - - if (!bRiposte) // Ripostes never generate any aggro. - other->AddToHateList(this, hate); - - /////////////////////////////////////////////////////////// - ////// Send Attack Damage - /////////////////////////////////////////////////////////// - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); - - if (IsDead()) return false; - - MeleeLifeTap(damage); - - if (damage > 0) - CheckNumHitsRemaining(5); - - //break invis when you attack - if(invisible) { - mlog(COMBAT__ATTACKS, "Removing invisibility due to melee attack."); - BuffFadeByEffect(SE_Invisibility); - BuffFadeByEffect(SE_Invisibility2); - invisible = false; - } - if(invisible_undead) { - mlog(COMBAT__ATTACKS, "Removing invisibility vs. undead due to melee attack."); - BuffFadeByEffect(SE_InvisVsUndead); - BuffFadeByEffect(SE_InvisVsUndead2); - invisible_undead = false; - } - if(invisible_animals){ - mlog(COMBAT__ATTACKS, "Removing invisibility vs. animals due to melee attack."); - BuffFadeByEffect(SE_InvisVsAnimals); - invisible_animals = false; - } - - if(hidden || improved_hidden){ - hidden = false; - improved_hidden = false; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; - sa_out->spawn_id = GetID(); - sa_out->type = 0x03; - sa_out->parameter = 0; - entity_list.QueueClients(this, outapp, true); - safe_delete(outapp); - } - - if(GetTarget()) - TriggerDefensiveProcs(weapon, other, Hand, damage); - - if (damage > 0) - return true; - - else - return false; -} - -//used by complete heal and #heal -void Mob::Heal() -{ - SetMaxHP(); - SendHPUpdate(); -} - -void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) -{ - if(dead || IsCorpse()) - return; - - if(spell_id==0) - spell_id = SPELL_UNKNOWN; - - if(spell_id!=0 && spell_id != SPELL_UNKNOWN && other && damage > 0) - { - if(other->IsNPC() && !other->IsPet()) - { - float npcspellscale = other->CastToNPC()->GetSpellScale(); - damage = ((float)damage * npcspellscale) / (float)100; - } - } - - // cut all PVP spell damage to 2/3 -solar - // EverHood - Blasting ourselfs is considered PvP - //Don't do PvP mitigation if the caster is damaging himself - if(other && other->IsClient() && (other != this) && damage > 0) { - int PvPMitigation = 100; - if(attack_skill == SkillArchery) - PvPMitigation = 80; - else - PvPMitigation = 67; - damage = (damage * PvPMitigation) / 100; - } - - if(!ClientFinishedLoading()) - damage = -5; - - //do a majority of the work... - CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); - - if (damage > 0) { - - if (spell_id == SPELL_UNKNOWN) - CheckIncreaseSkill(SkillDefense, other, -15); - } -} - -bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) -{ - if(!ClientFinishedLoading()) - return false; - - if(dead) - return false; //cant die more than once... - - if(!spell) - spell = SPELL_UNKNOWN; - - char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); - if(parse->EventPlayer(EVENT_DEATH, this, buffer, 0) != 0) { - if(GetHP() < 0) { - SetHP(0); - } - return false; - } - - if(killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { - char val1[20]={0}; - entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE, - killerMob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); - } - - int exploss = 0; - mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob ? killerMob->GetName() : "Unknown", damage, spell, attack_skill); - - // - // #1: Send death packet to everyone - // - uint8 killed_level = GetLevel(); - - SendLogoutPackets(); - - //make our become corpse packet, and queue to ourself before OP_Death. - EQApplicationPacket app2(OP_BecomeCorpse, sizeof(BecomeCorpse_Struct)); - BecomeCorpse_Struct* bc = (BecomeCorpse_Struct*)app2.pBuffer; - bc->spawn_id = GetID(); - bc->x = GetX(); - bc->y = GetY(); - bc->z = GetZ(); - QueuePacket(&app2); - - // make death packet - EQApplicationPacket app(OP_Death, sizeof(Death_Struct)); - Death_Struct* d = (Death_Struct*)app.pBuffer; - d->spawn_id = GetID(); - d->killer_id = killerMob ? killerMob->GetID() : 0; - d->corpseid=GetID(); - d->bindzoneid = m_pp.binds[0].zoneId; - d->spell_id = spell == SPELL_UNKNOWN ? 0xffffffff : spell; - d->attack_skill = spell != SPELL_UNKNOWN ? 0xe7 : attack_skill; - d->damage = damage; - app.priority = 6; - entity_list.QueueClients(this, &app); - - // - // #2: figure out things that affect the player dying and mark them dead - // - - InterruptSpell(); - SetPet(0); - SetHorseId(0); - dead = true; - - if(GetMerc()) { - GetMerc()->Suspend(); - } - - if (killerMob != nullptr) - { - if (killerMob->IsNPC()) { - parse->EventNPC(EVENT_SLAY, killerMob->CastToNPC(), this, "", 0); - - mod_client_death_npc(killerMob); - - uint16 emoteid = killerMob->GetEmoteID(); - if(emoteid != 0) - killerMob->CastToNPC()->DoNPCEmote(KILLEDPC,emoteid); - killerMob->TrySpellOnKill(killed_level,spell); - } - - if(killerMob->IsClient() && (IsDueling() || killerMob->CastToClient()->IsDueling())) { - SetDueling(false); - SetDuelTarget(0); - if (killerMob->IsClient() && killerMob->CastToClient()->IsDueling() && killerMob->CastToClient()->GetDuelTarget() == GetID()) - { - //if duel opponent killed us... - killerMob->CastToClient()->SetDueling(false); - killerMob->CastToClient()->SetDuelTarget(0); - entity_list.DuelMessage(killerMob,this,false); - - mod_client_death_duel(killerMob); - - } else { - //otherwise, we just died, end the duel. - Mob* who = entity_list.GetMob(GetDuelTarget()); - if(who && who->IsClient()) { - who->CastToClient()->SetDueling(false); - who->CastToClient()->SetDuelTarget(0); - } - } - } - } - - entity_list.RemoveFromTargets(this); - hate_list.RemoveEnt(this); - RemoveAutoXTargets(); - - - //remove ourself from all proximities - ClearAllProximities(); - - // - // #3: exp loss and corpse generation - // - - // figure out if they should lose exp - if(RuleB(Character, UseDeathExpLossMult)){ - float GetNum [] = {0.005f,0.015f,0.025f,0.035f,0.045f,0.055f,0.065f,0.075f,0.085f,0.095f,0.110f }; - int Num = RuleI(Character, DeathExpLossMultiplier); - if((Num < 0) || (Num > 10)) - Num = 3; - float loss = GetNum[Num]; - exploss=(int)((float)GetEXP() * (loss)); //loose % of total XP pending rule (choose 0-10) - } - - if(!RuleB(Character, UseDeathExpLossMult)){ - exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000); - } - - if( (GetLevel() < RuleI(Character, DeathExpLossLevel)) || (GetLevel() > RuleI(Character, DeathExpLossMaxLevel)) || IsBecomeNPC() ) - { - exploss = 0; - } - else if( killerMob ) - { - if( killerMob->IsClient() ) - { - exploss = 0; - } - else if( killerMob->GetOwner() && killerMob->GetOwner()->IsClient() ) - { - exploss = 0; - } - } - - if(spell != SPELL_UNKNOWN) - { - uint32 buff_count = GetMaxTotalSlots(); - for(uint16 buffIt = 0; buffIt < buff_count; buffIt++) - { - if(buffs[buffIt].spellid == spell && buffs[buffIt].client) - { - exploss = 0; // no exp loss for pvp dot - break; - } - } - } - - bool LeftCorpse = false; - - // now we apply the exp loss, unmem their spells, and make a corpse - // unless they're a GM (or less than lvl 10 - if(!GetGM()) - { - if(exploss > 0) { - int32 newexp = GetEXP(); - if(exploss > newexp) { - //lost more than we have... wtf.. - newexp = 1; - } else { - newexp -= exploss; - } - SetEXP(newexp, GetAAXP()); - //m_epp.perAA = 0; //reset to no AA exp on death. - } - - //this generates a lot of 'updates' to the client that the client does not need - BuffFadeNonPersistDeath(); - if((GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover)) - UnmemSpellAll(true); - else - UnmemSpellAll(false); - - if(RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel) || RuleB(Character, LeaveNakedCorpses)) - { - // creating the corpse takes the cash/items off the player too - Corpse *new_corpse = new Corpse(this, exploss); - - char tmp[20]; - database.GetVariable("ServerType", tmp, 9); - if(atoi(tmp)==1 && killerMob != nullptr && killerMob->IsClient()){ - char tmp2[10] = {0}; - database.GetVariable("PvPreward", tmp, 9); - int reward = atoi(tmp); - if(reward==3){ - database.GetVariable("PvPitem", tmp2, 9); - int pvpitem = atoi(tmp2); - if(pvpitem>0 && pvpitem<200000) - new_corpse->SetPKItem(pvpitem); - } - else if(reward==2) - new_corpse->SetPKItem(-1); - else if(reward==1) - new_corpse->SetPKItem(1); - else - new_corpse->SetPKItem(0); - if(killerMob->CastToClient()->isgrouped) { - Group* group = entity_list.GetGroupByClient(killerMob->CastToClient()); - if(group != 0) - { - for(int i=0;i<6;i++) - { - if(group->members[i] != nullptr) - { - new_corpse->AllowMobLoot(group->members[i],i); - } - } - } - } - } - - entity_list.AddCorpse(new_corpse, GetID()); - SetID(0); - - //send the become corpse packet to everybody else in the zone. - entity_list.QueueClients(this, &app2, true); - - LeftCorpse = true; - } - -// if(!IsLD())//Todo: make it so an LDed client leaves corpse if its enabled -// MakeCorpse(exploss); - } else { - BuffFadeDetrimental(); - } - - // - // Finally, send em home - // - - // we change the mob variables, not pp directly, because Save() will copy - // from these and overwrite what we set in pp anyway - // - - if(LeftCorpse && (GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover)) - { - ClearDraggedCorpses(); - - RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000); - - SendRespawnBinds(); - } - else - { - if(isgrouped) - { - Group *g = GetGroup(); - if(g) - g->MemberZoned(this); - } - - Raid* r = entity_list.GetRaidByClient(this); - - if(r) - r->MemberZoned(this); - - dead_timer.Start(5000, true); - - m_pp.zone_id = m_pp.binds[0].zoneId; - m_pp.zoneInstance = 0; - database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id)); - - Save(); - - GoToDeath(); - } - - parse->EventPlayer(EVENT_DEATH_COMPLETE, this, buffer, 0); - return true; -} - -bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) -{ - int damage = 0; - - if (!other) { - SetTarget(nullptr); - LogFile->write(EQEMuLog::Error, "A null Mob object was passed to NPC::Attack() for evaluation!"); - return false; - } - - if(DivineAura()) - return(false); - - if(!GetTarget()) - SetTarget(other); - - //Check that we can attack before we calc heading and face our target - if (!IsAttackAllowed(other)) { - if (this->GetOwnerID()) - this->Say_StringID(NOT_LEGAL_TARGET); - if(other) { - if (other->IsClient()) - other->CastToClient()->RemoveXTarget(this, false); - RemoveFromHateList(other); - mlog(COMBAT__ATTACKS, "I am not allowed to attack %s", other->GetName()); - } - return false; - } - - FaceTarget(GetTarget()); - - SkillUseTypes skillinuse = SkillHandtoHand; - if (Hand == 13) { - skillinuse = static_cast(GetPrimSkill()); - OffHandAtk(false); - } - if (Hand == 14) { - skillinuse = static_cast(GetSecSkill()); - OffHandAtk(true); - } - - //figure out what weapon they are using, if any - const Item_Struct* weapon = nullptr; - if (Hand == 13 && equipment[SLOT_PRIMARY] > 0) - weapon = database.GetItem(equipment[SLOT_PRIMARY]); - else if (equipment[SLOT_SECONDARY]) - weapon = database.GetItem(equipment[SLOT_SECONDARY]); - - //We dont factor much from the weapon into the attack. - //Just the skill type so it doesn't look silly using punching animations and stuff while wielding weapons - if(weapon) { - mlog(COMBAT__ATTACKS, "Attacking with weapon: %s (%d) (too bad im not using it for much)", weapon->Name, weapon->ID); - - if(Hand == 14 && weapon->ItemType == ItemTypeShield){ - mlog(COMBAT__ATTACKS, "Attack with shield canceled."); - return false; - } - - switch(weapon->ItemType){ - case ItemType1HSlash: - skillinuse = Skill1HSlashing; - break; - case ItemType2HSlash: - skillinuse = Skill2HSlashing; - break; - case ItemType1HPiercing: - //skillinuse = Skill1HPiercing; - //break; - case ItemType2HPiercing: - skillinuse = Skill1HPiercing; // change to Skill2HPiercing once activated - break; - case ItemType1HBlunt: - skillinuse = Skill1HBlunt; - break; - case ItemType2HBlunt: - skillinuse = Skill2HBlunt; - break; - case ItemTypeBow: - skillinuse = SkillArchery; - break; - case ItemTypeLargeThrowing: - case ItemTypeSmallThrowing: - skillinuse = SkillThrowing; - break; - default: - skillinuse = SkillHandtoHand; - break; - } - } - - int weapon_damage = GetWeaponDamage(other, weapon); - - //do attack animation regardless of whether or not we can hit below - int16 charges = 0; - ItemInst weapon_inst(weapon, charges); - AttackAnimation(skillinuse, Hand, &weapon_inst); - - // Remove this once Skill2HPiercing is activated - //Work-around for there being no 2HP skill - We use 99 for the 2HB animation and 36 for pierce messages - if(skillinuse == 99) - skillinuse = static_cast(36); - - //basically "if not immune" then do the attack - if((weapon_damage) > 0) { - - //ele and bane dmg too - //NPCs add this differently than PCs - //if NPCs can't inheriently hit the target we don't add bane/magic dmg which isn't exactly the same as PCs - uint16 eleBane = 0; - if(weapon){ - if(weapon->BaneDmgBody == other->GetBodyType()){ - eleBane += weapon->BaneDmgAmt; - } - - if(weapon->BaneDmgRace == other->GetRace()){ - eleBane += weapon->BaneDmgRaceAmt; - } - - if(weapon->ElemDmgAmt){ - eleBane += (weapon->ElemDmgAmt * other->ResistSpell(weapon->ElemDmgType, 0, this) / 100); - } - } - - if(!RuleB(NPC, UseItemBonusesForNonPets)){ - if(!GetOwner()){ - eleBane = 0; - } - } - - uint8 otherlevel = other->GetLevel(); - uint8 mylevel = this->GetLevel(); - - otherlevel = otherlevel ? otherlevel : 1; - mylevel = mylevel ? mylevel : 1; - - //instead of calcing damage in floats lets just go straight to ints - if(RuleB(Combat, UseIntervalAC)) - damage = (max_dmg+eleBane); - else - damage = MakeRandomInt((min_dmg+eleBane),(max_dmg+eleBane)); - - - //check if we're hitting above our max or below it. - if((min_dmg+eleBane) != 0 && damage < (min_dmg+eleBane)) { - mlog(COMBAT__DAMAGE, "Damage (%d) is below min (%d). Setting to min.", damage, (min_dmg+eleBane)); - damage = (min_dmg+eleBane); - } - if((max_dmg+eleBane) != 0 && damage > (max_dmg+eleBane)) { - mlog(COMBAT__DAMAGE, "Damage (%d) is above max (%d). Setting to max.", damage, (max_dmg+eleBane)); - damage = (max_dmg+eleBane); - } - - damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other); - - int32 hate = damage; - if(IsPet()) - { - hate = hate * 100 / GetDamageTable(skillinuse); - } - - if(other->IsClient() && other->CastToClient()->IsSitting()) { - mlog(COMBAT__DAMAGE, "Client %s is sitting. Hitting for max damage (%d).", other->GetName(), (max_dmg+eleBane)); - damage = (max_dmg+eleBane); - damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); - - if(opts) { - damage *= opts->damage_percent; - damage += opts->damage_flat; - hate *= opts->hate_percent; - hate += opts->hate_flat; - } - - mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, GetName()); - // now add done damage to the hate list - other->AddToHateList(this, hate); - - } else { - if(opts) { - damage *= opts->damage_percent; - damage += opts->damage_flat; - hate *= opts->hate_percent; - hate += opts->hate_flat; - } - - if(!other->CheckHitChance(this, skillinuse, Hand)) { - damage = 0; //miss - } else { //hit, check for damage avoidance - other->AvoidDamage(this, damage); - other->MeleeMitigation(this, damage, min_dmg+eleBane, opts); - if(damage > 0) { - ApplyMeleeDamageBonus(skillinuse, damage); - damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); - TryCriticalHit(other, skillinuse, damage, opts); - } - mlog(COMBAT__HITS, "Generating hate %d towards %s", hate, GetName()); - // now add done damage to the hate list - if(damage > 0) - { - other->AddToHateList(this, hate); - } - else - other->AddToHateList(this, 0); - } - } - - mlog(COMBAT__DAMAGE, "Final damage against %s: %d", other->GetName(), damage); - - if(other->IsClient() && IsPet() && GetOwner()->IsClient()) { - //pets do half damage to clients in pvp - damage=damage/2; - } - } - else - damage = -5; - - //cant riposte a riposte - if (bRiposte && damage == -3) { - mlog(COMBAT__DAMAGE, "Riposte of riposte canceled."); - return false; - } - - int16 DeathHP = 0; - DeathHP = other->GetDelayDeath() * -1; - - if(GetHP() > 0 && other->GetHP() >= DeathHP) { - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, false); // Not avoidable client already had thier chance to Avoid - } else - return false; - - if (HasDied()) //killed by damage shield ect - return false; - - MeleeLifeTap(damage); - - if (damage > 0) - CheckNumHitsRemaining(5); - - //break invis when you attack - if(invisible) { - mlog(COMBAT__ATTACKS, "Removing invisibility due to melee attack."); - BuffFadeByEffect(SE_Invisibility); - BuffFadeByEffect(SE_Invisibility2); - invisible = false; - } - if(invisible_undead) { - mlog(COMBAT__ATTACKS, "Removing invisibility vs. undead due to melee attack."); - BuffFadeByEffect(SE_InvisVsUndead); - BuffFadeByEffect(SE_InvisVsUndead2); - invisible_undead = false; - } - if(invisible_animals){ - mlog(COMBAT__ATTACKS, "Removing invisibility vs. animals due to melee attack."); - BuffFadeByEffect(SE_InvisVsAnimals); - invisible_animals = false; - } - - if(hidden || improved_hidden) - { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; - sa_out->spawn_id = GetID(); - sa_out->type = 0x03; - sa_out->parameter = 0; - entity_list.QueueClients(this, outapp, true); - safe_delete(outapp); - } - - - hidden = false; - improved_hidden = false; - - //I doubt this works... - if (!GetTarget()) - return true; //We killed them - - if(!bRiposte && other->GetHP() > 0 ) { - TryWeaponProc(nullptr, weapon, other, Hand); //no weapon - TrySpellProc(nullptr, weapon, other, Hand); - } - - TriggerDefensiveProcs(nullptr, other, Hand, damage); - - // now check ripostes - if (damage == -3) { // riposting - DoRiposte(other); - } - - if (damage > 0) - return true; - - else - return false; -} - -void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic) { - if(spell_id==0) - spell_id = SPELL_UNKNOWN; - - //handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds - if(attacked_timer.Check()) - { - mlog(COMBAT__HITS, "Triggering EVENT_ATTACK due to attack by %s", other->GetName()); - parse->EventNPC(EVENT_ATTACK, this, other, "", 0); - } - attacked_timer.Start(CombatEventTimer_expire); - - if (!IsEngaged()) - zone->AddAggroMob(); - - if(GetClass() == LDON_TREASURE) - { - if(IsLDoNLocked() && GetLDoNLockedSkill() != LDoNTypeMechanical) - { - damage = -5; - } - else - { - if(IsLDoNTrapped()) - { - Message_StringID(13, LDON_ACCIDENT_SETOFF2); - SpellFinished(GetLDoNTrapSpellID(), other, 10, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false); - SetLDoNTrapSpellID(0); - SetLDoNTrapped(false); - SetLDoNTrapDetected(false); - } - } - } - - //do a majority of the work... - CommonDamage(other, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic); - - if(damage > 0) { - //see if we are gunna start fleeing - if(!IsPet()) CheckFlee(); - } -} - -bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) { - mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob->GetName(), damage, spell, attack_skill); - - Mob *oos = nullptr; - if(killerMob) { - oos = killerMob->GetOwnerOrSelf(); - - char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); - if(parse->EventNPC(EVENT_DEATH, this, oos, buffer, 0) != 0) - { - if(GetHP() < 0) { - SetHP(0); - } - return false; - } - - if(killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { - char val1[20]={0}; - entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE, - killerMob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); - } - } else { - - char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); - if(parse->EventNPC(EVENT_DEATH, this, nullptr, buffer, 0) != 0) - { - if(GetHP() < 0) { - SetHP(0); - } - return false; - } - } - - if (IsEngaged()) - { - zone->DelAggroMob(); -#if EQDEBUG >= 11 - LogFile->write(EQEMuLog::Debug,"NPC::Death() Mobs currently Aggro %i", zone->MobsAggroCount()); -#endif - } - SetHP(0); - SetPet(0); - Mob* killer = GetHateDamageTop(this); - - entity_list.RemoveFromTargets(this, p_depop); - - if(p_depop == true) - return false; - - BuffFadeAll(); - uint8 killed_level = GetLevel(); - - EQApplicationPacket* app= new EQApplicationPacket(OP_Death,sizeof(Death_Struct)); - Death_Struct* d = (Death_Struct*)app->pBuffer; - d->spawn_id = GetID(); - d->killer_id = killerMob ? killerMob->GetID() : 0; - d->bindzoneid = 0; - d->spell_id = spell == SPELL_UNKNOWN ? 0xffffffff : spell; - d->attack_skill = SkillDamageTypes[attack_skill]; - d->damage = damage; - app->priority = 6; - entity_list.QueueClients(killerMob, app, false); - - if(respawn2) { - respawn2->DeathReset(1); - } - - if (killerMob) { - if(GetClass() != LDON_TREASURE) - hate_list.Add(killerMob, damage); - } - - safe_delete(app); - - Mob *give_exp = hate_list.GetDamageTop(this); - - if(give_exp == nullptr) - give_exp = killer; - - if(give_exp && give_exp->HasOwner()) { - - bool ownerInGroup = false; - if((give_exp->HasGroup() && give_exp->GetGroup()->IsGroupMember(give_exp->GetUltimateOwner())) - || (give_exp->IsPet() && (give_exp->GetOwner()->IsClient() - || ( give_exp->GetOwner()->HasGroup() && give_exp->GetOwner()->GetGroup()->IsGroupMember(give_exp->GetOwner()->GetUltimateOwner()))))) - ownerInGroup = true; - - give_exp = give_exp->GetUltimateOwner(); - -#ifdef BOTS - if(!RuleB(Bots, BotGroupXP) && !ownerInGroup) { - give_exp = nullptr; - } -#endif //BOTS - } - - int PlayerCount = 0; // QueryServ Player Counting - - Client *give_exp_client = nullptr; - if(give_exp && give_exp->IsClient()) - give_exp_client = give_exp->CastToClient(); - - bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE); - if (give_exp_client && !IsCorpse() && MerchantType == 0) - { - Group *kg = entity_list.GetGroupByClient(give_exp_client); - Raid *kr = entity_list.GetRaidByClient(give_exp_client); - - int32 finalxp = EXP_FORMULA; - finalxp = give_exp_client->mod_client_xp(finalxp, this); - - if(kr) - { - if(!IsLdonTreasure) { - kr->SplitExp((finalxp), this); - if(killerMob && (kr->IsRaidMember(killerMob->GetName()) || kr->IsRaidMember(killerMob->GetUltimateOwner()->GetName()))) - killerMob->TrySpellOnKill(killed_level,spell); - } - /* Send the EVENT_KILLED_MERIT event for all raid members */ - for (int i = 0; i < MAX_RAID_MEMBERS; i++) { - if (kr->members[i].member != nullptr) { // If Group Member is Client - parse->EventNPC(EVENT_KILLED_MERIT, this, kr->members[i].member, "killed", 0); - - mod_npc_killed_merit(kr->members[i].member); - - if(RuleB(TaskSystem, EnableTaskSystem)) - kr->members[i].member->UpdateTasksOnKill(GetNPCTypeID()); - PlayerCount++; - } - } - - // QueryServ Logging - Raid Kills - if(RuleB(QueryServ, PlayerLogNPCKills)){ - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); - PlayerCount = 0; - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; - QS->s1.NPCID = this->GetNPCTypeID(); - QS->s1.ZoneID = this->GetZoneID(); - QS->s1.Type = 2; // Raid Fight - for (int i = 0; i < MAX_RAID_MEMBERS; i++) { - if (kr->members[i].member != nullptr) { // If Group Member is Client - Client *c = kr->members[i].member; - QS->Chars[PlayerCount].char_id = c->CharacterID(); - PlayerCount++; - } - } - worldserver.SendPacket(pack); // Send Packet to World - safe_delete(pack); - } - // End QueryServ Logging - - } - else if (give_exp_client->IsGrouped() && kg != nullptr) - { - if(!IsLdonTreasure) { - kg->SplitExp((finalxp), this); - if(killerMob && (kg->IsGroupMember(killerMob->GetName()) || kg->IsGroupMember(killerMob->GetUltimateOwner()->GetName()))) - killerMob->TrySpellOnKill(killed_level,spell); - } - /* Send the EVENT_KILLED_MERIT event and update kill tasks - * for all group members */ - for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (kg->members[i] != nullptr && kg->members[i]->IsClient()) { // If Group Member is Client - Client *c = kg->members[i]->CastToClient(); - parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); - - mod_npc_killed_merit(c); - - if(RuleB(TaskSystem, EnableTaskSystem)) - c->UpdateTasksOnKill(GetNPCTypeID()); - - PlayerCount++; - } - } - - // QueryServ Logging - Group Kills - if(RuleB(QueryServ, PlayerLogNPCKills)){ - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); - PlayerCount = 0; - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; - QS->s1.NPCID = this->GetNPCTypeID(); - QS->s1.ZoneID = this->GetZoneID(); - QS->s1.Type = 1; // Group Fight - for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (kg->members[i] != nullptr && kg->members[i]->IsClient()) { // If Group Member is Client - Client *c = kg->members[i]->CastToClient(); - QS->Chars[PlayerCount].char_id = c->CharacterID(); - PlayerCount++; - } - } - worldserver.SendPacket(pack); // Send Packet to World - safe_delete(pack); - } - // End QueryServ Logging - } - else - { - if(!IsLdonTreasure) { - int conlevel = give_exp->GetLevelCon(GetLevel()); - if (conlevel != CON_GREEN) - { - if(GetOwner() && GetOwner()->IsClient()){ - } - else { - give_exp_client->AddEXP((finalxp), conlevel); // Pyro: Comment this if NPC death crashes zone - if(killerMob && (killerMob->GetID() == give_exp_client->GetID() || killerMob->GetUltimateOwner()->GetID() == give_exp_client->GetID())) - killerMob->TrySpellOnKill(killed_level,spell); - } - } - } - /* Send the EVENT_KILLED_MERIT event */ - parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); - - mod_npc_killed_merit(give_exp_client); - - if(RuleB(TaskSystem, EnableTaskSystem)) - give_exp_client->UpdateTasksOnKill(GetNPCTypeID()); - - // QueryServ Logging - Solo - if(RuleB(QueryServ, PlayerLogNPCKills)){ - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1)); - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; - QS->s1.NPCID = this->GetNPCTypeID(); - QS->s1.ZoneID = this->GetZoneID(); - QS->s1.Type = 0; // Solo Fight - Client *c = give_exp_client; - QS->Chars[0].char_id = c->CharacterID(); - PlayerCount++; - worldserver.SendPacket(pack); // Send Packet to World - safe_delete(pack); - } - // End QueryServ Logging - } - } - - //do faction hits even if we are a merchant, so long as a player killed us - if(give_exp_client) - hate_list.DoFactionHits(GetNPCFactionID()); - - if (!HasOwner() && !IsMerc() && class_ != MERCHANT && class_ != ADVENTUREMERCHANT && !GetSwarmInfo() - && MerchantType == 0 && killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) || - (killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient()))) - { - if(killer != 0) - { - if(killer->GetOwner() != 0 && killer->GetOwner()->IsClient()) - killer = killer->GetOwner(); - - if(!killer->CastToClient()->GetGM() && killer->IsClient()) - this->CheckMinMaxLevel(killer); - } - entity_list.RemoveFromAutoXTargets(this); - uint16 emoteid = this->GetEmoteID(); - Corpse* corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata,level>54?RuleI(NPC,MajorNPCCorpseDecayTimeMS):RuleI(NPC,MinorNPCCorpseDecayTimeMS)); - entity_list.LimitRemoveNPC(this); - entity_list.AddCorpse(corpse, GetID()); - - entity_list.UnMarkNPC(GetID()); - entity_list.RemoveNPC(GetID()); - this->SetID(0); - if(killer != 0 && emoteid != 0) - corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid); - if(killer != 0 && killer->IsClient()) { - corpse->AllowMobLoot(killer, 0); - if(killer->IsGrouped()) { - Group* group = entity_list.GetGroupByClient(killer->CastToClient()); - if(group != 0) { - for(int i=0;i<6;i++) { // Doesnt work right, needs work - if(group->members[i] != nullptr) { - corpse->AllowMobLoot(group->members[i],i); - } - } - } - } - else if(killer->IsRaidGrouped()){ - Raid* r = entity_list.GetRaidByClient(killer->CastToClient()); - if(r){ - int i = 0; - for(int x = 0; x < MAX_RAID_MEMBERS; x++) - { - switch(r->GetLootType()) - { - case 0: - case 1: - if(r->members[x].member && r->members[x].IsRaidLeader){ - corpse->AllowMobLoot(r->members[x].member, i); - i++; - } - break; - case 2: - if(r->members[x].member && r->members[x].IsRaidLeader){ - corpse->AllowMobLoot(r->members[x].member, i); - i++; - } - else if(r->members[x].member && r->members[x].IsGroupLeader){ - corpse->AllowMobLoot(r->members[x].member, i); - i++; - } - break; - case 3: - if(r->members[x].member && r->members[x].IsLooter){ - corpse->AllowMobLoot(r->members[x].member, i); - i++; - } - break; - case 4: - if(r->members[x].member) - { - corpse->AllowMobLoot(r->members[x].member, i); - i++; - } - break; - } - } - } - } - } - - if(zone && zone->adv_data) - { - ServerZoneAdventureDataReply_Struct *sr = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; - if(sr->type == Adventure_Kill) - { - zone->DoAdventureCountIncrease(); - } - else if(sr->type == Adventure_Assassinate) - { - if(sr->data_id == GetNPCTypeID()) - { - zone->DoAdventureCountIncrease(); - } - else - { - zone->DoAdventureAssassinationCountIncrease(); - } - } - } - } - else - entity_list.RemoveFromXTargets(this); - - // Parse quests even if we're killed by an NPC - if(oos) { - mod_npc_killed(oos); - - uint16 emoteid = this->GetEmoteID(); - if(emoteid != 0) - this->DoNPCEmote(ONDEATH, emoteid); - if(oos->IsNPC()) - { - parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0); - uint16 emoteid = oos->GetEmoteID(); - if(emoteid != 0) - oos->CastToNPC()->DoNPCEmote(KILLEDNPC, emoteid); - killerMob->TrySpellOnKill(killed_level, spell); - } - } - - WipeHateList(); - p_depop = true; - if(killerMob && killerMob->GetTarget() == this) //we can kill things without having them targeted - killerMob->SetTarget(nullptr); //via AE effects and such.. - - entity_list.UpdateFindableNPCState(this, true); - - char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killerMob ? killerMob->GetID() : 0, damage, spell, static_cast(attack_skill)); - parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, buffer, 0); - return true; -} - -void Mob::AddToHateList(Mob* other, int32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) { - - assert(other != nullptr); - - if (other == this) - return; - - if(damage < 0){ - hate = 1; - } - - bool wasengaged = IsEngaged(); - Mob* owner = other->GetOwner(); - Mob* mypet = this->GetPet(); - Mob* myowner = this->GetOwner(); - Mob* targetmob = this->GetTarget(); - - if(other){ - AddRampage(other); - int hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod; - - int16 shieldhatemod = other->spellbonuses.ShieldEquipHateMod + other->itembonuses.ShieldEquipHateMod + other->aabonuses.ShieldEquipHateMod; - - if (shieldhatemod && other->HasShieldEquiped()) - hatemod += shieldhatemod; - - if(hatemod < 1) - hatemod = 1; - hate = ((hate * (hatemod))/100); - } - - if(IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && !IsFocused()) { //ignore aggro if hold and !focus - return; - } - - if(IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && GetOwner()->GetAA(aaAdvancedPetDiscipline) >= 1 && IsFocused()) { - if (!targetmob) - return; - } - - if (other->IsNPC() && (other->IsPet() || other->CastToNPC()->GetSwarmOwner() > 0)) - TryTriggerOnValueAmount(false, false, false, true); - - if(IsClient() && !IsAIControlled()) - return; - - if(IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO)) - return; - - if (other == myowner) - return; - - if(other->GetSpecialAbility(IMMUNE_AGGRO_ON)) - return; - - if(GetSpecialAbility(NPC_TUNNELVISION)) { - int tv_mod = GetSpecialAbilityParam(NPC_TUNNELVISION, 0); - - Mob *top = GetTarget(); - if(top && top != other) { - if(tv_mod) { - float tv = tv_mod / 100.0f; - hate *= tv; - } else { - hate *= RuleR(Aggro, TunnelVisionAggroMod); - } - } - } - - if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { - if(!zone->watermap->InLiquid(other->GetX(), other->GetY(), other->GetZ())) { - return; - } - } - // first add self - - // The damage on the hate list is used to award XP to the killer. This check is to prevent Killstealing. - // e.g. Mob has 5000 hit points, Player A melees it down to 500 hp, Player B executes a headshot (10000 damage). - // If we add 10000 damage, Player B would get the kill credit, so we only award damage credit to player B of the - // amount of HP the mob had left. - // - if(damage > GetHP()) - damage = GetHP(); - - if (spellbonuses.ImprovedTaunt[1] && (GetLevel() < spellbonuses.ImprovedTaunt[0]) - && other && (buffs[spellbonuses.ImprovedTaunt[2]].casterid != other->GetID())) - hate = (hate*spellbonuses.ImprovedTaunt[1])/100; - - hate_list.Add(other, hate, damage, bFrenzy, !iBuffTic); - - if(other->IsClient()) - other->CastToClient()->AddAutoXTarget(this); - -#ifdef BOTS - // if other is a bot, add the bots client to the hate list - if(other->IsBot()) { - if(other->CastToBot()->GetBotOwner() && other->CastToBot()->GetBotOwner()->CastToClient()->GetFeigned()) { - AddFeignMemory(other->CastToBot()->GetBotOwner()->CastToClient()); - } - else { - if(!hate_list.IsOnHateList(other->CastToBot()->GetBotOwner())) - hate_list.Add(other->CastToBot()->GetBotOwner(), 0, 0, false, true); - } - } -#endif //BOTS - - - // if other is a merc, add the merc client to the hate list - if(other->IsMerc()) { - if(other->CastToMerc()->GetMercOwner() && other->CastToMerc()->GetMercOwner()->CastToClient()->GetFeigned()) { - AddFeignMemory(other->CastToMerc()->GetMercOwner()->CastToClient()); - } - else { - if(!hate_list.IsOnHateList(other->CastToMerc()->GetMercOwner())) - hate_list.Add(other->CastToMerc()->GetMercOwner(), 0, 0, false, true); - } - } //MERC - - // then add pet owner if there's one - if (owner) { // Other is a pet, add him and it - // EverHood 6/12/06 - // Can't add a feigned owner to hate list - if(owner->IsClient() && owner->CastToClient()->GetFeigned()) { - //they avoid hate due to feign death... - } else { - // cb:2007-08-17 - // owner must get on list, but he's not actually gained any hate yet - if(!owner->GetSpecialAbility(IMMUNE_AGGRO)) - { - hate_list.Add(owner, 0, 0, false, !iBuffTic); - if(owner->IsClient()) - owner->CastToClient()->AddAutoXTarget(this); - } - } - } - - if (mypet && (!(GetAA(aaPetDiscipline) && mypet->IsHeld()))) { // I have a pet, add other to it - if(!mypet->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO)) - mypet->hate_list.Add(other, 0, 0, bFrenzy); - } else if (myowner) { // I am a pet, add other to owner if it's NPC/LD - if (myowner->IsAIControlled() && !myowner->GetSpecialAbility(IMMUNE_AGGRO)) - myowner->hate_list.Add(other, 0, 0, bFrenzy); - } - if (!wasengaged) { - if(IsNPC() && other->IsClient() && other->CastToClient()) - parse->EventNPC(EVENT_AGGRO, this->CastToNPC(), other, "", 0); - AI_Event_Engaged(other, iYellForHelp); - } -} - -// solar: this is called from Damage() when 'this' is attacked by 'other. -// 'this' is the one being attacked -// 'other' is the attacker -// a damage shield causes damage (or healing) to whoever attacks the wearer -// a reverse ds causes damage to the wearer whenever it attack someone -// given this, a reverse ds must be checked each time the wearer is attacking -// and not when they're attacked -//a damage shield on a spell is a negative value but on an item it's a positive value so add the spell value and subtract the item value to get the end ds value -void Mob::DamageShield(Mob* attacker, bool spell_ds) { - - if(!attacker || this == attacker) - return; - - int DS = 0; - int rev_ds = 0; - uint16 spellid = 0; - - if(!spell_ds) - { - DS = spellbonuses.DamageShield; - rev_ds = attacker->spellbonuses.ReverseDamageShield; - - if(spellbonuses.DamageShieldSpellID != 0 && spellbonuses.DamageShieldSpellID != SPELL_UNKNOWN) - spellid = spellbonuses.DamageShieldSpellID; - } - else { - DS = spellbonuses.SpellDamageShield; - rev_ds = 0; - // This ID returns "you are burned", seemed most appropriate for spell DS - spellid = 2166; - } - - if(DS == 0 && rev_ds == 0) - return; - - mlog(COMBAT__HITS, "Applying Damage Shield of value %d to %s", DS, attacker->GetName()); - - //invert DS... spells yield negative values for a true damage shield - if(DS < 0) { - if(!spell_ds) { - - DS += aabonuses.DamageShield; //Live AA - coat of thistles. (negative value) - DS -= itembonuses.DamageShield; //+Damage Shield should only work when you already have a DS spell - - //Spell data for damage shield mitigation shows a negative value for spells for clients and positive - //value for spells that effect pets. Unclear as to why. For now will convert all positive to be consistent. - if (attacker->IsOffHandAtk()){ - int16 mitigation = attacker->itembonuses.DSMitigationOffHand + - attacker->spellbonuses.DSMitigationOffHand + - attacker->aabonuses.DSMitigationOffHand; - DS -= DS*mitigation/100; - } - DS -= DS * attacker->itembonuses.DSMitigation / 100; - } - attacker->Damage(this, -DS, spellid, SkillAbjuration/*hackish*/, false); - //we can assume there is a spell now - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); - CombatDamage_Struct* cds = (CombatDamage_Struct*)outapp->pBuffer; - cds->target = attacker->GetID(); - cds->source = GetID(); - cds->type = spellbonuses.DamageShieldType; - cds->spellid = 0x0; - cds->damage = DS; - entity_list.QueueCloseClients(this, outapp); - safe_delete(outapp); - } else if (DS > 0 && !spell_ds) { - //we are healing the attacker... - attacker->HealDamage(DS); - //TODO: send a packet??? - } - - //Reverse DS - //this is basically a DS, but the spell is on the attacker, not the attackee - //if we've gotten to this point, we know we know "attacker" hit "this" (us) for damage & we aren't invulnerable - uint16 rev_ds_spell_id = SPELL_UNKNOWN; - - if(spellbonuses.ReverseDamageShieldSpellID != 0 && spellbonuses.ReverseDamageShieldSpellID != SPELL_UNKNOWN) - rev_ds_spell_id = spellbonuses.ReverseDamageShieldSpellID; - - if(rev_ds < 0) { - mlog(COMBAT__HITS, "Applying Reverse Damage Shield of value %d to %s", rev_ds, attacker->GetName()); - attacker->Damage(this, -rev_ds, rev_ds_spell_id, SkillAbjuration/*hackish*/, false); //"this" (us) will get the hate, etc. not sure how this works on Live, but it'll works for now, and tanks will love us for this - //do we need to send a damage packet here also? - } -} - -uint8 Mob::GetWeaponDamageBonus( const Item_Struct *Weapon ) -{ - // This function calculates and returns the damage bonus for the weapon identified by the parameter "Weapon". - // Modified 9/21/2008 by Cantus - - - // Assert: This function should only be called for hits by the mainhand, as damage bonuses apply only to the - // weapon in the primary slot. Be sure to check that Hand == 13 before calling. - - // Assert: The caller should ensure that Weapon is actually a weapon before calling this function. - // The ItemInst::IsWeapon() method can be used to quickly determine this. - - // Assert: This function should not be called if the player's level is below 28, as damage bonuses do not begin - // to apply until level 28. - - // Assert: This function should not be called unless the player is a melee class, as casters do not receive a damage bonus. - - - if( Weapon == nullptr || Weapon->ItemType == ItemType1HSlash || Weapon->ItemType == ItemType1HBlunt || Weapon->ItemType == ItemTypeMartial || Weapon->ItemType == ItemType1HPiercing ) - { - // The weapon in the player's main (primary) hand is a one-handed weapon, or there is no item equipped at all. - // - // According to player posts on Allakhazam, 1H damage bonuses apply to bare fists (nothing equipped in the mainhand, - // as indicated by Weapon == nullptr). - // - // The following formula returns the correct damage bonus for all 1H weapons: - - return (uint8) ((GetLevel() - 25) / 3); - } - - // If we've gotten to this point, the weapon in the mainhand is a two-handed weapon. - // Calculating damage bonuses for 2H weapons is more complicated, as it's based on PC level AND the delay of the weapon. - // The formula to calculate 2H bonuses is HIDEOUS. It's a huge conglomeration of ternary operators and multiple operations. - // - // The following is a hybrid approach. In cases where the Level and Delay merit a formula that does not use many operators, - // the formula is used. In other cases, lookup tables are used for speed. - // Though the following code may look bloated and ridiculous, it's actually a very efficient way of calculating these bonuses. - - // Player Level is used several times in the code below, so save it into a variable. - // If GetLevel() were an ordinary function, this would DEFINITELY make sense, as it'd cut back on all of the function calling - // overhead involved with multiple calls to GetLevel(). But in this case, GetLevel() is a simple, inline accessor method. - // So it probably doesn't matter. If anyone knows for certain that there is no overhead involved with calling GetLevel(), - // as I suspect, then please feel free to delete the following line, and replace all occurences of "ucPlayerLevel" with "GetLevel()". - uint8 ucPlayerLevel = (uint8) GetLevel(); - - - // The following may look cleaner, and would certainly be easier to understand, if it was - // a simple 53x150 cell matrix. - // - // However, that would occupy 7,950 Bytes of memory (7.76 KB), and would likely result - // in "thrashing the cache" when performing lookups. - // - // Initially, I thought the best approach would be to reverse-engineer the formula used by - // Sony/Verant to calculate these 2H weapon damage bonuses. But the more than Reno and I - // worked on figuring out this formula, the more we're concluded that the formula itself ugly - // (that is, it contains so many operations and conditionals that it's fairly CPU intensive). - // Because of that, we're decided that, in most cases, a lookup table is the most efficient way - // to calculate these damage bonuses. - // - // The code below is a hybrid between a pure formulaic approach and a pure, brute-force - // lookup table. In cases where a formula is the best bet, I use a formula. In other places - // where a formula would be ugly, I use a lookup table in the interests of speed. - - - if( Weapon->Delay <= 27 ) - { - // Damage Bonuses for all 2H weapons with delays of 27 or less are identical. - // They are the same as the damage bonus would be for a corresponding 1H weapon, plus one. - // This formula applies to all levels 28-80, and will probably continue to apply if - - // the level cap on Live ever is increased beyond 80. - - return (ucPlayerLevel - 22) / 3; - } - - - if( ucPlayerLevel == 65 && Weapon->Delay <= 59 ) - { - // Consider these two facts: - // * Level 65 is the maximum level on many EQ Emu servers. - // * If you listed the levels of all characters logged on to a server, odds are that the number you'll - // see most frequently is level 65. That is, there are more level 65 toons than any other single level. - // - // Therefore, if we can optimize this function for level 65 toons, we're speeding up the server! - // - // With that goal in mind, I create an array of Damage Bonuses for level 65 characters wielding 2H weapons with - // delays between 28 and 59 (inclusive). I suspect that this one small lookup array will therefore handle - // many of the calls to this function. - - static const uint8 ucLevel65DamageBonusesForDelays28to59[] = {35, 35, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 42, 42, 42, 45, 45, 47, 48, 49, 49, 51, 51, 52, 53, 54, 54, 56, 56, 57, 58, 59}; - - return ucLevel65DamageBonusesForDelays28to59[Weapon->Delay-28]; - } - - - if( ucPlayerLevel > 65 ) - { - if( ucPlayerLevel > 80 ) - { - // As level 80 is currently the highest achievable level on Live, we only include - // damage bonus information up to this level. - // - // If there is a custom EQEmu server that allows players to level beyond 80, the - // damage bonus for their 2H weapons will simply not increase beyond their damage - // bonus at level 80. - - ucPlayerLevel = 80; - } - - // Lucy does not list a chart of damage bonuses for players levels 66+, - // so my original version of this function just applied the level 65 damage - // bonus for level 66+ toons. That sucked for higher level toons, as their - // 2H weapons stopped ramping up in DPS as they leveled past 65. - // - // Thanks to the efforts of two guys, this is no longer the case: - // - // Janusd (Zetrakyl) ran a nifty query against the PEQ item database to list - // the name of an example 2H weapon that represents each possible unique 2H delay. - // - // Romai then wrote an excellent script to automatically look up each of those - // weapons, open the Lucy item page associated with it, and iterate through all - // levels in the range 66 - 80. He saved the damage bonus for that weapon for - // each level, and that forms the basis of the lookup tables below. - - if( Weapon->Delay <= 59 ) - { - static const uint8 ucDelay28to59Levels66to80[32][15]= - { - /* Level: */ - /* 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 */ - - {36, 37, 38, 39, 41, 42, 43, 44, 45, 47, 49, 49, 49, 50, 53}, /* Delay = 28 */ - {36, 38, 38, 39, 42, 43, 43, 45, 46, 48, 49, 50, 51, 52, 54}, /* Delay = 29 */ - {37, 38, 39, 40, 43, 43, 44, 46, 47, 48, 50, 51, 52, 53, 55}, /* Delay = 30 */ - {37, 39, 40, 40, 43, 44, 45, 46, 47, 49, 51, 52, 52, 52, 54}, /* Delay = 31 */ - {38, 39, 40, 41, 44, 45, 45, 47, 48, 48, 50, 52, 53, 55, 57}, /* Delay = 32 */ - {38, 40, 41, 41, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 58}, /* Delay = 33 */ - {39, 40, 41, 42, 45, 46, 47, 48, 49, 51, 53, 54, 55, 57, 58}, /* Delay = 34 */ - {39, 41, 42, 43, 46, 46, 47, 49, 50, 52, 54, 55, 56, 57, 59}, /* Delay = 35 */ - {40, 41, 42, 43, 46, 47, 48, 50, 51, 53, 55, 55, 56, 58, 60}, /* Delay = 36 */ - {40, 42, 43, 44, 47, 48, 49, 50, 51, 53, 55, 56, 57, 59, 61}, /* Delay = 37 */ - {41, 42, 43, 44, 47, 48, 49, 51, 52, 54, 56, 57, 58, 60, 62}, /* Delay = 38 */ - {41, 43, 44, 45, 48, 49, 50, 52, 53, 55, 57, 58, 59, 61, 63}, /* Delay = 39 */ - {43, 45, 46, 47, 50, 51, 52, 54, 55, 57, 59, 60, 61, 63, 65}, /* Delay = 40 */ - {43, 45, 46, 47, 50, 51, 52, 54, 55, 57, 59, 60, 61, 63, 65}, /* Delay = 41 */ - {44, 46, 47, 48, 51, 52, 53, 55, 56, 58, 60, 61, 62, 64, 66}, /* Delay = 42 */ - {46, 48, 49, 50, 53, 54, 55, 58, 59, 61, 63, 64, 65, 67, 69}, /* Delay = 43 */ - {47, 49, 50, 51, 54, 55, 56, 58, 59, 61, 64, 65, 66, 68, 70}, /* Delay = 44 */ - {48, 50, 51, 52, 56, 57, 58, 60, 61, 63, 65, 66, 68, 70, 72}, /* Delay = 45 */ - {50, 52, 53, 54, 57, 58, 59, 62, 63, 65, 67, 68, 69, 71, 74}, /* Delay = 46 */ - {50, 52, 53, 55, 58, 59, 60, 62, 63, 66, 68, 69, 70, 72, 74}, /* Delay = 47 */ - {51, 53, 54, 55, 58, 60, 61, 63, 64, 66, 69, 69, 71, 73, 75}, /* Delay = 48 */ - {52, 54, 55, 57, 60, 61, 62, 65, 66, 68, 70, 71, 73, 75, 77}, /* Delay = 49 */ - {53, 55, 56, 57, 61, 62, 63, 65, 67, 69, 71, 72, 74, 76, 78}, /* Delay = 50 */ - {53, 55, 57, 58, 61, 62, 64, 66, 67, 69, 72, 73, 74, 77, 79}, /* Delay = 51 */ - {55, 57, 58, 59, 63, 64, 65, 68, 69, 71, 74, 75, 76, 78, 81}, /* Delay = 52 */ - {57, 55, 59, 60, 63, 65, 66, 68, 70, 72, 74, 76, 77, 79, 82}, /* Delay = 53 */ - {56, 58, 59, 61, 64, 65, 67, 69, 70, 73, 75, 76, 78, 80, 82}, /* Delay = 54 */ - {57, 59, 61, 62, 66, 67, 68, 71, 72, 74, 77, 78, 80, 82, 84}, /* Delay = 55 */ - {58, 60, 61, 63, 66, 68, 69, 71, 73, 75, 78, 79, 80, 83, 85}, /* Delay = 56 */ - - /* Important Note: Janusd's search for 2H weapons did not find */ - /* any 2H weapon with a delay of 57. Therefore the values below */ - /* are interpolated, not exact! */ - {59, 61, 62, 64, 67, 69, 70, 72, 74, 76, 77, 78, 81, 84, 86}, /* Delay = 57 INTERPOLATED */ - - {60, 62, 63, 65, 68, 70, 71, 74, 75, 78, 80, 81, 83, 85, 88}, /* Delay = 58 */ - - /* Important Note: Janusd's search for 2H weapons did not find */ - /* any 2H weapon with a delay of 59. Therefore the values below */ - /* are interpolated, not exact! */ - {60, 62, 64, 65, 69, 70, 72, 74, 76, 78, 81, 82, 84, 86, 89}, /* Delay = 59 INTERPOLATED */ - }; - - return ucDelay28to59Levels66to80[Weapon->Delay-28][ucPlayerLevel-66]; - } - else - { - // Delay is 60+ - - const static uint8 ucDelayOver59Levels66to80[6][15] = - { - /* Level: */ - /* 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 */ - - {61, 63, 65, 66, 70, 71, 73, 75, 77, 79, 82, 83, 85, 87, 90}, /* Delay = 60 */ - {65, 68, 69, 71, 75, 76, 78, 80, 82, 85, 87, 89, 91, 93, 96}, /* Delay = 65 */ - - /* Important Note: Currently, the only 2H weapon with a delay */ - /* of 66 is not player equippable (it's None/None). So I'm */ - /* leaving it commented out to keep this table smaller. */ - //{66, 68, 70, 71, 75, 77, 78, 81, 83, 85, 88, 90, 91, 94, 97}, /* Delay = 66 */ - - {70, 72, 74, 76, 80, 81, 83, 86, 88, 88, 90, 95, 97, 99, 102}, /* Delay = 70 */ - {82, 85, 87, 89, 89, 94, 98, 101, 103, 106, 109, 111, 114, 117, 120}, /* Delay = 85 */ - {90, 93, 96, 98, 103, 105, 107, 111, 113, 116, 120, 122, 125, 128, 131}, /* Delay = 95 */ - - /* Important Note: Currently, the only 2H weapons with delay */ - /* 100 are GM-only items purchased from vendors in Sunset Home */ - /* (cshome). Because they are highly unlikely to be used in */ - /* combat, I'm commenting it out to keep the table smaller. */ - //{95, 98, 101, 103, 108, 110, 113, 116, 119, 122, 126, 128, 131, 134, 138},/* Delay = 100 */ - - {136, 140, 144, 148, 154, 157, 161, 166, 170, 174, 179, 183, 187, 191, 196} /* Delay = 150 */ - }; - - if( Weapon->Delay < 65 ) - { - return ucDelayOver59Levels66to80[0][ucPlayerLevel-66]; - } - else if( Weapon->Delay < 70 ) - { - return ucDelayOver59Levels66to80[1][ucPlayerLevel-66]; - } - else if( Weapon->Delay < 85 ) - { - return ucDelayOver59Levels66to80[2][ucPlayerLevel-66]; - } - else if( Weapon->Delay < 95 ) - { - return ucDelayOver59Levels66to80[3][ucPlayerLevel-66]; - } - else if( Weapon->Delay < 150 ) - { - return ucDelayOver59Levels66to80[4][ucPlayerLevel-66]; - } - else - { - return ucDelayOver59Levels66to80[5][ucPlayerLevel-66]; - } - } - } - - - // If we've gotten to this point in the function without hitting a return statement, - // we know that the character's level is between 28 and 65, and that the 2H weapon's - // delay is 28 or higher. - - // The Damage Bonus values returned by this function (in the level 28-65 range) are - // based on a table of 2H Weapon Damage Bonuses provided by Lucy at the following address: - // http://lucy.allakhazam.com/dmgbonus.html - - if( Weapon->Delay <= 39 ) - { - if( ucPlayerLevel <= 53) - { - // The Damage Bonus for all 2H weapons with delays between 28 and 39 (inclusive) is the same for players level 53 and below... - static const uint8 ucDelay28to39LevelUnder54[] = {1, 1, 2, 3, 3, 3, 4, 5, 5, 6, 6, 6, 8, 8, 8, 9, 9, 10, 11, 11, 11, 12, 13, 14, 16, 17}; - - // As a note: The following formula accurately calculates damage bonuses for 2H weapons with delays in the range 28-39 (inclusive) - // for characters levels 28-50 (inclusive): - // return ( (ucPlayerLevel - 22) / 3 ) + ( (ucPlayerLevel - 25) / 5 ); - // - // However, the small lookup array used above is actually much faster. So we'll just use it instead of the formula - // - // (Thanks to Reno for helping figure out the above formula!) - - return ucDelay28to39LevelUnder54[ucPlayerLevel-28]; - } - else - { - // Use a matrix to look up the damage bonus for 2H weapons with delays between 28 and 39 wielded by characters level 54 and above. - static const uint8 ucDelay28to39Level54to64[12][11] = - { - /* Level: */ - /* 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 */ - - {17, 21, 21, 23, 25, 26, 28, 30, 31, 31, 33}, /* Delay = 28 */ - {17, 21, 22, 23, 25, 26, 29, 30, 31, 32, 34}, /* Delay = 29 */ - {18, 21, 22, 23, 25, 27, 29, 31, 32, 32, 34}, /* Delay = 30 */ - {18, 21, 22, 23, 25, 27, 29, 31, 32, 33, 34}, /* Delay = 31 */ - {18, 21, 22, 24, 26, 27, 30, 32, 32, 33, 35}, /* Delay = 32 */ - {18, 21, 22, 24, 26, 27, 30, 32, 33, 34, 35}, /* Delay = 33 */ - {18, 22, 22, 24, 26, 28, 30, 32, 33, 34, 36}, /* Delay = 34 */ - {18, 22, 23, 24, 26, 28, 31, 33, 34, 34, 36}, /* Delay = 35 */ - {18, 22, 23, 25, 27, 28, 31, 33, 34, 35, 37}, /* Delay = 36 */ - {18, 22, 23, 25, 27, 29, 31, 33, 34, 35, 37}, /* Delay = 37 */ - {18, 22, 23, 25, 27, 29, 32, 34, 35, 36, 38}, /* Delay = 38 */ - {18, 22, 23, 25, 27, 29, 32, 34, 35, 36, 38} /* Delay = 39 */ - }; - - return ucDelay28to39Level54to64[Weapon->Delay-28][ucPlayerLevel-54]; - } - } - else if( Weapon->Delay <= 59 ) - { - if( ucPlayerLevel <= 52 ) - { - if( Weapon->Delay <= 45 ) - { - static const uint8 ucDelay40to45Levels28to52[6][25] = - { - /* Level: */ - /* 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52 */ - - {2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 7, 7, 9, 9, 9, 10, 10, 11, 12, 12, 12, 13, 14, 16, 18}, /* Delay = 40 */ - {2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 7, 7, 9, 9, 9, 10, 10, 11, 12, 12, 12, 13, 14, 16, 18}, /* Delay = 41 */ - {2, 2, 3, 4, 4, 4, 5, 6, 6, 7, 7, 7, 9, 9, 9, 10, 10, 11, 12, 12, 12, 13, 14, 16, 18}, /* Delay = 42 */ - {4, 4, 5, 6, 6, 6, 7, 8, 8, 9, 9, 9, 11, 11, 11, 12, 12, 13, 14, 14, 14, 15, 16, 18, 20}, /* Delay = 43 */ - {4, 4, 5, 6, 6, 6, 7, 8, 8, 9, 9, 9, 11, 11, 11, 12, 12, 13, 14, 14, 14, 15, 16, 18, 20}, /* Delay = 44 */ - {5, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 10, 12, 12, 12, 13, 13, 14, 15, 15, 15, 16, 17, 19, 21} /* Delay = 45 */ - }; - - return ucDelay40to45Levels28to52[Weapon->Delay-40][ucPlayerLevel-28]; - } - else - { - static const uint8 ucDelay46Levels28to52[] = {6, 6, 7, 8, 8, 8, 9, 10, 10, 11, 11, 11, 13, 13, 13, 14, 14, 15, 16, 16, 16, 17, 18, 20, 22}; - - return ucDelay46Levels28to52[ucPlayerLevel-28] + ((Weapon->Delay-46) / 3); - } - } - else - { - // Player is in the level range 53 - 64 - - // Calculating damage bonus for 2H weapons with a delay between 40 and 59 (inclusive) involves, unforunately, a brute-force matrix lookup. - static const uint8 ucDelay40to59Levels53to64[20][37] = - { - /* Level: */ - /* 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 */ - - {19, 20, 24, 25, 27, 29, 31, 34, 36, 37, 38, 40}, /* Delay = 40 */ - {19, 20, 24, 25, 27, 29, 31, 34, 36, 37, 38, 40}, /* Delay = 41 */ - {19, 20, 24, 25, 27, 29, 31, 34, 36, 37, 38, 40}, /* Delay = 42 */ - {21, 22, 26, 27, 29, 31, 33, 37, 39, 40, 41, 43}, /* Delay = 43 */ - {21, 22, 26, 27, 29, 32, 34, 37, 39, 40, 41, 43}, /* Delay = 44 */ - {22, 23, 27, 28, 31, 33, 35, 38, 40, 42, 43, 45}, /* Delay = 45 */ - {23, 24, 28, 30, 32, 34, 36, 40, 42, 43, 44, 46}, /* Delay = 46 */ - {23, 24, 29, 30, 32, 34, 37, 40, 42, 43, 44, 47}, /* Delay = 47 */ - {23, 24, 29, 30, 32, 35, 37, 40, 43, 44, 45, 47}, /* Delay = 48 */ - {24, 25, 30, 31, 34, 36, 38, 42, 44, 45, 46, 49}, /* Delay = 49 */ - {24, 26, 30, 31, 34, 36, 39, 42, 44, 46, 47, 49}, /* Delay = 50 */ - {24, 26, 30, 31, 34, 36, 39, 42, 45, 46, 47, 49}, /* Delay = 51 */ - {25, 27, 31, 33, 35, 38, 40, 44, 46, 47, 49, 51}, /* Delay = 52 */ - {25, 27, 31, 33, 35, 38, 40, 44, 46, 48, 49, 51}, /* Delay = 53 */ - {26, 27, 32, 33, 36, 38, 41, 44, 47, 48, 49, 52}, /* Delay = 54 */ - {27, 28, 33, 34, 37, 39, 42, 46, 48, 50, 51, 53}, /* Delay = 55 */ - {27, 28, 33, 34, 37, 40, 42, 46, 49, 50, 51, 54}, /* Delay = 56 */ - {27, 28, 33, 34, 37, 40, 43, 46, 49, 50, 52, 54}, /* Delay = 57 */ - {28, 29, 34, 36, 39, 41, 44, 48, 50, 52, 53, 56}, /* Delay = 58 */ - {28, 29, 34, 36, 39, 41, 44, 48, 51, 52, 54, 56} /* Delay = 59 */ - }; - - return ucDelay40to59Levels53to64[Weapon->Delay-40][ucPlayerLevel-53]; - } - } - else - { - // The following table allows us to look up Damage Bonuses for weapons with delays greater than or equal to 60. - // - // There aren't a lot of 2H weapons with a delay greater than 60. In fact, both a database and Lucy search run by janusd confirm - // that the only unique 2H delays greater than 60 are: 65, 70, 85, 95, and 150. - // - // To be fair, there are also weapons with delays of 66 and 100. But they are either not equippable (None/None), or are - // only available to GMs from merchants in Sunset Home (cshome). In order to keep this table "lean and mean", I will not - // include the values for delays 66 and 100. If they ever are wielded, the 66 delay weapon will use the 65 delay bonuses, - // and the 100 delay weapon will use the 95 delay bonuses. So it's not a big deal. - // - // Still, if someone in the future decides that they do want to include them, here are the tables for these two delays: - // - // {12, 12, 13, 14, 14, 14, 15, 16, 16, 17, 17, 17, 19, 19, 19, 20, 20, 21, 22, 22, 22, 23, 24, 26, 29, 30, 32, 37, 39, 42, 45, 48, 53, 55, 57, 59, 61, 64} /* Delay = 66 */ - // {24, 24, 25, 26, 26, 26, 27, 28, 28, 29, 29, 29, 31, 31, 31, 32, 32, 33, 34, 34, 34, 35, 36, 39, 43, 45, 48, 55, 57, 62, 66, 71, 77, 80, 83, 85, 89, 92} /* Delay = 100 */ - // - // In case there are 2H weapons added in the future with delays other than those listed above (and until the damage bonuses - // associated with that new delay are added to this function), this function is designed to do the following: - // - // For weapons with delays in the range 60-64, use the Damage Bonus that would apply to a 2H weapon with delay 60. - // For weapons with delays in the range 65-69, use the Damage Bonus that would apply to a 2H weapon with delay 65 - // For weapons with delays in the range 70-84, use the Damage Bonus that would apply to a 2H weapon with delay 70. - // For weapons with delays in the range 85-94, use the Damage Bonus that would apply to a 2H weapon with delay 85. - // For weapons with delays in the range 95-149, use the Damage Bonus that would apply to a 2H weapon with delay 95. - // For weapons with delays 150 or higher, use the Damage Bonus that would apply to a 2H weapon with delay 150. - - static const uint8 ucDelayOver59Levels28to65[6][38] = - { - /* Level: */ - /* 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64. 65 */ - - {10, 10, 11, 12, 12, 12, 13, 14, 14, 15, 15, 15, 17, 17, 17, 18, 18, 19, 20, 20, 20, 21, 22, 24, 27, 28, 30, 35, 36, 39, 42, 45, 49, 51, 53, 54, 57, 59}, /* Delay = 60 */ - {12, 12, 13, 14, 14, 14, 15, 16, 16, 17, 17, 17, 19, 19, 19, 20, 20, 21, 22, 22, 22, 23, 24, 26, 29, 30, 32, 37, 39, 42, 45, 48, 52, 55, 57, 58, 61, 63}, /* Delay = 65 */ - {14, 14, 15, 16, 16, 16, 17, 18, 18, 19, 19, 19, 21, 21, 21, 22, 22, 23, 24, 24, 24, 25, 26, 28, 31, 33, 35, 40, 42, 45, 48, 52, 56, 59, 61, 62, 65, 68}, /* Delay = 70 */ - {19, 19, 20, 21, 21, 21, 22, 23, 23, 24, 24, 24, 26, 26, 26, 27, 27, 28, 29, 29, 29, 30, 31, 34, 37, 39, 41, 47, 49, 54, 57, 61, 66, 69, 72, 74, 77, 80}, /* Delay = 85 */ - {22, 22, 23, 24, 24, 24, 25, 26, 26, 27, 27, 27, 29, 29, 29, 30, 30, 31, 32, 32, 32, 33, 34, 37, 40, 43, 45, 52, 54, 59, 62, 67, 73, 76, 79, 81, 84, 88}, /* Delay = 95 */ - {40, 40, 41, 42, 42, 42, 43, 44, 44, 45, 45, 45, 47, 47, 47, 48, 48, 49, 50, 50, 50, 51, 52, 56, 61, 65, 69, 78, 82, 89, 94, 102, 110, 115, 119, 122, 127, 132} /* Delay = 150 */ - }; - - if( Weapon->Delay < 65 ) - { - return ucDelayOver59Levels28to65[0][ucPlayerLevel-28]; - } - else if( Weapon->Delay < 70 ) - { - return ucDelayOver59Levels28to65[1][ucPlayerLevel-28]; - } - else if( Weapon->Delay < 85 ) - { - return ucDelayOver59Levels28to65[2][ucPlayerLevel-28]; - } - else if( Weapon->Delay < 95 ) - { - return ucDelayOver59Levels28to65[3][ucPlayerLevel-28]; - } - else if( Weapon->Delay < 150 ) - { - return ucDelayOver59Levels28to65[4][ucPlayerLevel-28]; - } - else - { - return ucDelayOver59Levels28to65[5][ucPlayerLevel-28]; - } - } -} - -int Mob::GetMonkHandToHandDamage(void) -{ - // Kaiyodo - Determine a monk's fist damage. Table data from www.monkly-business.com - // saved as static array - this should speed this function up considerably - static int damage[66] = { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 - 99, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 9, 9, 9, 9, 9,10,10,10,10,10,11,11,11,11,11, - 12,12,12,12,12,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14, - 14,14,15,15,15,15 }; - - // Have a look to see if we have epic fists on - - if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652) - return(9); - else - { - int Level = GetLevel(); - if (Level > 65) - return(19); - else - return damage[Level]; - } -} - -int Mob::GetMonkHandToHandDelay(void) -{ - // Kaiyodo - Determine a monk's fist delay. Table data from www.monkly-business.com - // saved as static array - this should speed this function up considerably - static int delayshuman[66] = { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 - 99,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, - 36,36,36,36,36,35,35,35,35,35,34,34,34,34,34,33,33,33,33,33, - 32,32,32,32,32,31,31,31,31,31,30,30,30,29,29,29,28,28,28,27, - 26,24,22,20,20,20 }; - static int delaysiksar[66] = { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 - 99,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36, - 36,36,36,36,36,36,36,36,36,36,35,35,35,35,35,34,34,34,34,34, - 33,33,33,33,33,32,32,32,32,32,31,31,31,30,30,30,29,29,29,28, - 27,24,22,20,20,20 }; - - // Have a look to see if we have epic fists on - if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652) - return(16); - else - { - int Level = GetLevel(); - if (GetRace() == HUMAN) - { - if (Level > 65) - return(24); - else - return delayshuman[Level]; - } - else //heko: iksar table - { - if (Level > 65) - return(25); - else - return delaysiksar[Level]; - } - } -} - - -int32 Mob::ReduceDamage(int32 damage) -{ - if(damage <= 0) - return damage; - - int32 slot = -1; - bool DisableMeleeRune = false; - - if (spellbonuses.NegateAttacks[0]){ - slot = spellbonuses.NegateAttacks[1]; - if(slot >= 0) { - if(--buffs[slot].numhits == 0) { - - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot , true); - } - return -6; - } - } - - //Only mitigate if damage is above the minimium specified. - if (spellbonuses.MeleeThresholdGuard[0]){ - slot = spellbonuses.MeleeThresholdGuard[1]; - - if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) - { - DisableMeleeRune = true; - int damage_to_reduce = damage * spellbonuses.MeleeThresholdGuard[0] / 100; - if(damage_to_reduce > buffs[slot].melee_rune) - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d" - " damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune); - damage -= damage_to_reduce; - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MeleeThresholdGuard %d damage negated, %d" - " damage remaining.", damage_to_reduce, buffs[slot].melee_rune); - buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); - damage -= damage_to_reduce; - } - } - } - - - if (spellbonuses.MitigateMeleeRune[0] && !DisableMeleeRune){ - slot = spellbonuses.MitigateMeleeRune[1]; - if(slot >= 0) - { - int damage_to_reduce = damage * spellbonuses.MitigateMeleeRune[0] / 100; - if(damage_to_reduce > buffs[slot].melee_rune) - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" - " damage remaining, fading buff.", damage_to_reduce, buffs[slot].melee_rune); - damage -= damage_to_reduce; - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" - " damage remaining.", damage_to_reduce, buffs[slot].melee_rune); - buffs[slot].melee_rune = (buffs[slot].melee_rune - damage_to_reduce); - damage -= damage_to_reduce; - } - } - } - - if (spellbonuses.TriggerMeleeThreshold[2]){ - slot = spellbonuses.TriggerMeleeThreshold[1]; - - if (slot >= 0) { - if(damage > buffs[slot].melee_rune) { - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else{ - buffs[slot].melee_rune = (buffs[slot].melee_rune - damage); - } - } - } - - if(damage < 1) - return -6; - - if (spellbonuses.MeleeRune[0] && spellbonuses.MeleeRune[1] >= 0) - damage = RuneAbsorb(damage, SE_Rune); - - if(damage < 1) - return -6; - - return(damage); -} - -int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker) -{ - if(damage <= 0) - return damage; - - bool DisableSpellRune = false; - int32 slot = -1; - - // See if we block the spell outright first - if (spellbonuses.NegateAttacks[0]){ - slot = spellbonuses.NegateAttacks[1]; - if(slot >= 0) { - if(--buffs[slot].numhits == 0) { - - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot , true); - } - return 0; - } - } - - // If this is a DoT, use DoT Shielding... - if(iBuffTic) { - damage -= (damage * itembonuses.DoTShielding / 100); - - if (spellbonuses.MitigateDotRune[0]){ - slot = spellbonuses.MitigateDotRune[1]; - if(slot >= 0) - { - int damage_to_reduce = damage * spellbonuses.MitigateDotRune[0] / 100; - if(damage_to_reduce > buffs[slot].dot_rune) - { - damage -= damage_to_reduce; - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else - { - buffs[slot].dot_rune = (buffs[slot].dot_rune - damage_to_reduce); - damage -= damage_to_reduce; - } - } - } - } - - // This must be a DD then so lets apply Spell Shielding and runes. - else - { - // Reduce damage by the Spell Shielding first so that the runes don't take the raw damage. - damage -= (damage * itembonuses.SpellShield / 100); - - - //Only mitigate if damage is above the minimium specified. - if (spellbonuses.SpellThresholdGuard[0]){ - slot = spellbonuses.SpellThresholdGuard[1]; - - if (slot >= 0 && (damage > spellbonuses.MeleeThresholdGuard[2])) - { - DisableSpellRune = true; - int damage_to_reduce = damage * spellbonuses.SpellThresholdGuard[0] / 100; - if(damage_to_reduce > buffs[slot].magic_rune) - { - damage -= damage_to_reduce; - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else - { - buffs[slot].melee_rune = (buffs[slot].magic_rune - damage_to_reduce); - damage -= damage_to_reduce; - } - } - } - - - // Do runes now. - if (spellbonuses.MitigateSpellRune[0] && !DisableSpellRune){ - slot = spellbonuses.MitigateSpellRune[1]; - if(slot >= 0) - { - int damage_to_reduce = damage * spellbonuses.MitigateSpellRune[0] / 100; - if(damage_to_reduce > buffs[slot].magic_rune) - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateSpellDamage %d damage negated, %d" - " damage remaining, fading buff.", damage_to_reduce, buffs[slot].magic_rune); - damage -= damage_to_reduce; - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else - { - mlog(SPELLS__EFFECT_VALUES, "Mob::ReduceDamage SE_MitigateMeleeDamage %d damage negated, %d" - " damage remaining.", damage_to_reduce, buffs[slot].magic_rune); - buffs[slot].magic_rune = (buffs[slot].magic_rune - damage_to_reduce); - damage -= damage_to_reduce; - } - } - } - - if (spellbonuses.TriggerSpellThreshold[2]){ - slot = spellbonuses.TriggerSpellThreshold[1]; - - if (slot >= 0) { - if(damage > buffs[slot].magic_rune) { - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - else{ - buffs[slot].magic_rune = (buffs[slot].magic_rune - damage); - } - } - } - - if(damage < 1) - return 0; - - - if (spellbonuses.AbsorbMagicAtt[0] && spellbonuses.AbsorbMagicAtt[1] >= 0) - damage = RuneAbsorb(damage, SE_AbsorbMagicAtt); - - if(damage < 1) - return 0; - } - return damage; -} - -int32 Mob::ReduceAllDamage(int32 damage) -{ - if(damage <= 0) - return damage; - - if(spellbonuses.ManaAbsorbPercentDamage[0] && (GetMana() > damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100)) { - damage -= (damage * spellbonuses.ManaAbsorbPercentDamage[0] / 100); - SetMana(GetMana() - damage); - TryTriggerOnValueAmount(false, true); - } - - CheckNumHitsRemaining(8); - - return(damage); -} - -bool Mob::HasProcs() const -{ - for (int i = 0; i < MAX_PROCS; i++) - if (PermaProcs[i].spellID != SPELL_UNKNOWN || SpellProcs[i].spellID != SPELL_UNKNOWN) - return true; - return false; -} - -bool Mob::HasDefensiveProcs() const -{ - for (int i = 0; i < MAX_PROCS; i++) - if (DefensiveProcs[i].spellID != SPELL_UNKNOWN) - return true; - return false; -} - -bool Mob::HasSkillProcs() const -{ - for (int i = 0; i < MAX_PROCS; i++) - if (SkillProcs[i].spellID != SPELL_UNKNOWN) - return true; - return false; -} - -bool Mob::HasRangedProcs() const -{ - for (int i = 0; i < MAX_PROCS; i++) - if (RangedProcs[i].spellID != SPELL_UNKNOWN) - return true; - return false; -} - -bool Client::CheckDoubleAttack(bool tripleAttack) { - - //Check for bonuses that give you a double attack chance regardless of skill (ie Bestial Frenzy/Harmonious Attack AA) - uint16 bonusGiveDA = aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack; - - if(!HasSkill(SkillDoubleAttack) && !bonusGiveDA) - return false; - - float chance = 0.0f; - - uint16 skill = GetSkill(SkillDoubleAttack); - - int16 bonusDA = aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance; - - //Use skill calculations otherwise, if you only have AA applied GiveDoubleAttack chance then use that value as the base. - if (skill) - chance = (float(skill+GetLevel()) * (float(100.0f+bonusDA+bonusGiveDA) /100.0f)) /500.0f; - else - chance = (float(bonusGiveDA) * (float(100.0f+bonusDA)/100.0f) ) /100.0f; - - //Live now uses a static Triple Attack skill (lv 46 = 2% lv 60 = 20%) - We do not have this skill on EMU ATM. - //A reasonable forumla would then be TA = 20% * chance - //AA's can also give triple attack skill over cap. (ie Burst of Power) NOTE: Skill ID in spell data is 76 (Triple Attack) - //Kayen: Need to decide if we can implement triple attack skill before working in over the cap effect. - if(tripleAttack) { - // Only some Double Attack classes get Triple Attack [This is already checked in client_processes.cpp] - int16 triple_bonus = spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance; - chance *= 0.2f; //Baseline chance is 20% of your double attack chance. - chance *= float(100.0f+triple_bonus)/100.0f; //Apply modifiers. - } - - if((MakeRandomFloat(0, 1) < chance)) - return true; - - return false; -} - -bool Client::CheckDoubleRangedAttack() { - - int16 chance = spellbonuses.DoubleRangedAttack + itembonuses.DoubleRangedAttack + aabonuses.DoubleRangedAttack; - - if(chance && (MakeRandomInt(0, 100) < chance)) - return true; - - return false; -} - -void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, const SkillUseTypes skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic) { - // This method is called with skill_used=ABJURE for Damage Shield damage. - bool FromDamageShield = (skill_used == SkillAbjuration); - - mlog(COMBAT__HITS, "Applying damage %d done by %s with skill %d and spell %d, avoidable? %s, is %sa buff tic in slot %d", - damage, attacker?attacker->GetName():"NOBODY", skill_used, spell_id, avoidable?"yes":"no", iBuffTic?"":"not ", buffslot); - - if (GetInvul() || DivineAura()) { - mlog(COMBAT__DAMAGE, "Avoiding %d damage due to invulnerability.", damage); - damage = -5; - } - - if( spell_id != SPELL_UNKNOWN || attacker == nullptr ) - avoidable = false; - - // only apply DS if physical damage (no spell damage) - // damage shield calls this function with spell_id set, so its unavoidable - if (attacker && damage > 0 && spell_id == SPELL_UNKNOWN && skill_used != SkillArchery && skill_used != SkillThrowing) { - DamageShield(attacker); - } - - if (spell_id == SPELL_UNKNOWN && skill_used) { - CheckNumHitsRemaining(1); //Incoming Hit Attempts - - if (attacker) - attacker->CheckNumHitsRemaining(2); //Outgoing Hit Attempts - } - - if(attacker){ - if(attacker->IsClient()){ - if(!RuleB(Combat, EXPFromDmgShield)) { - // Damage shield damage shouldn't count towards who gets EXP - if(!attacker->CastToClient()->GetFeigned() && !FromDamageShield) - AddToHateList(attacker, 0, damage, true, false, iBuffTic); - } - else { - if(!attacker->CastToClient()->GetFeigned()) - AddToHateList(attacker, 0, damage, true, false, iBuffTic); - } - } - else - AddToHateList(attacker, 0, damage, true, false, iBuffTic); - } - - if(damage > 0) { - //if there is some damage being done and theres an attacker involved - if(attacker) { - if(spell_id == SPELL_HARM_TOUCH2 && attacker->IsClient() && attacker->CastToClient()->CheckAAEffect(aaEffectLeechTouch)){ - int healed = damage; - healed = attacker->GetActSpellHealing(spell_id, healed); - attacker->HealDamage(healed); - entity_list.MessageClose(this, true, 300, MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName() ); - attacker->CastToClient()->DisableAAEffect(aaEffectLeechTouch); - } - - // if spell is lifetap add hp to the caster - if (spell_id != SPELL_UNKNOWN && IsLifetapSpell( spell_id )) { - int healed = damage; - - healed = attacker->GetActSpellHealing(spell_id, healed); - mlog(COMBAT__DAMAGE, "Applying lifetap heal of %d to %s", healed, attacker->GetName()); - attacker->HealDamage(healed); - - //we used to do a message to the client, but its gone now. - // emote goes with every one ... even npcs - entity_list.MessageClose(this, true, 300, MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName() ); - } - } //end `if there is some damage being done and theres anattacker person involved` - - Mob *pet = GetPet(); - if (pet && !pet->IsFamiliar() && !pet->GetSpecialAbility(IMMUNE_AGGRO) && !pet->IsEngaged() && attacker && attacker != this && !attacker->IsCorpse()) - { - if (!pet->IsHeld()) { - mlog(PETS__AGGRO, "Sending pet %s into battle due to attack.", pet->GetName()); - pet->AddToHateList(attacker, 1); - pet->SetTarget(attacker); - Message_StringID(10, PET_ATTACKING, pet->GetCleanName(), attacker->GetCleanName()); - } - } - - //see if any runes want to reduce this damage - if(spell_id == SPELL_UNKNOWN) { - damage = ReduceDamage(damage); - mlog(COMBAT__HITS, "Melee Damage reduced to %d", damage); - } else { - int32 origdmg = damage; - damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker); - if (origdmg != damage && attacker && attacker->IsClient()) { - if(attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide) - attacker->Message(15, "The Spellshield absorbed %d of %d points of damage", origdmg - damage, origdmg); - } - if (damage == 0 && attacker && origdmg != damage && IsClient()) { - //Kayen: Probably need to add a filter for this - Not sure if this msg is correct but there should be a message for spell negate/runes. - Message(263, "%s tries to cast on YOU, but YOUR magical skin absorbs the spell.",attacker->GetCleanName()); - } - - } - - if (skill_used) - CheckNumHitsRemaining(6); //Incomming Hit Success on Defender - - ReduceAllDamage(damage); - - if(IsClient() && CastToClient()->sneaking){ - CastToClient()->sneaking = false; - SendAppearancePacket(AT_Sneak, 0); - } - if(attacker && attacker->IsClient() && attacker->CastToClient()->sneaking){ - attacker->CastToClient()->sneaking = false; - attacker->SendAppearancePacket(AT_Sneak, 0); - } - - //final damage has been determined. - - SetHP(GetHP() - damage); - - if(HasDied()) { - bool IsSaved = false; - - if(TryDivineSave()) - IsSaved = true; - - if(!IsSaved && !TrySpellOnDeath()) { - SetHP(-500); - - if(Death(attacker, damage, spell_id, skill_used)) { - return; - } - } - } - else{ - if(GetHPRatio() < 16) - TryDeathSave(); - } - - TryTriggerOnValueAmount(true); - - //fade mez if we are mezzed - if (IsMezzed()) { - mlog(COMBAT__HITS, "Breaking mez due to attack."); - BuffFadeByEffect(SE_Mez); - } - - //check stun chances if bashing - if (damage > 0 && ((skill_used == SkillBash || skill_used == SkillKick) && attacker)) { - // NPCs can stun with their bash/kick as soon as they receive it. - // Clients can stun mobs under level 56 with their kick when they get level 55 or greater. - // Clients have a chance to stun if the mob is 56+ - - // Calculate the chance to stun - int stun_chance = 0; - if (!GetSpecialAbility(UNSTUNABLE)) { - if (attacker->IsNPC()) { - stun_chance = RuleI(Combat, NPCBashKickStunChance); - } else if (attacker->IsClient()) { - // Less than base immunity - // Client vs. Client always uses the chance - if (!IsClient() && GetLevel() <= RuleI(Spells, BaseImmunityLevel)) { - if (skill_used == SkillBash) // Bash always will - stun_chance = 100; - else if (attacker->GetLevel() >= RuleI(Combat, ClientStunLevel)) - stun_chance = 100; // only if you're over level 55 and using kick - } else { // higher than base immunity or Client vs. Client - // not sure on this number, use same as NPC for now - if (skill_used == SkillKick && attacker->GetLevel() < RuleI(Combat, ClientStunLevel)) - stun_chance = RuleI(Combat, NPCBashKickStunChance); - else if (skill_used == SkillBash) - stun_chance = RuleI(Combat, NPCBashKickStunChance) + - attacker->spellbonuses.StunBashChance + - attacker->itembonuses.StunBashChance + - attacker->aabonuses.StunBashChance; - } - } - } - - if (stun_chance && MakeRandomInt(0, 99) < stun_chance) { - // Passed stun, try to resist now - int stun_resist = itembonuses.StunResist + spellbonuses.StunResist; - int frontal_stun_resist = itembonuses.FrontalStunResist + spellbonuses.FrontalStunResist; - - mlog(COMBAT__HITS, "Stun passed, checking resists. Was %d chance.", stun_chance); - if (IsClient()) { - stun_resist += aabonuses.StunResist; - frontal_stun_resist += aabonuses.FrontalStunResist; - } - - // frontal stun check for ogres/bonuses - if (((GetBaseRace() == OGRE && IsClient()) || - (frontal_stun_resist && MakeRandomInt(0, 99) < frontal_stun_resist)) && - !attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) { - mlog(COMBAT__HITS, "Frontal stun resisted. %d chance.", frontal_stun_resist); - } else { - // Normal stun resist check. - if (stun_resist && MakeRandomInt(0, 99) < stun_resist) { - if (IsClient()) - Message_StringID(MT_Stun, SHAKE_OFF_STUN); - mlog(COMBAT__HITS, "Stun Resisted. %d chance.", stun_resist); - } else { - mlog(COMBAT__HITS, "Stunned. %d resist chance.", stun_resist); - Stun(MakeRandomInt(0, 2) * 1000); // 0-2 seconds - } - } - } else { - mlog(COMBAT__HITS, "Stun failed. %d chance.", stun_chance); - } - } - - if(spell_id != SPELL_UNKNOWN && !iBuffTic) { - //see if root will break - if (IsRooted() && !FromDamageShield) // neotoyko: only spells cancel root - TryRootFadeByDamage(buffslot, attacker); - } - else if(spell_id == SPELL_UNKNOWN) - { - //increment chances of interrupting - if(IsCasting()) { //shouldnt interrupt on regular spell damage - attacked_count++; - mlog(COMBAT__HITS, "Melee attack while casting. Attack count %d", attacked_count); - } - } - - //send an HP update if we are hurt - if(GetHP() < GetMaxHP()) - SendHPUpdate(); - } //end `if damage was done` - - //send damage packet... - if(!iBuffTic) { //buff ticks do not send damage, instead they just call SendHPUpdate(), which is done below - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); - CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer; - a->target = GetID(); - if (attacker == nullptr) - a->source = 0; - else if (attacker->IsClient() && attacker->CastToClient()->GMHideMe()) - a->source = 0; - else - a->source = attacker->GetID(); - a->type = SkillDamageTypes[skill_used]; // was 0x1c - a->damage = damage; - a->spellid = spell_id; - - //Note: if players can become pets, they will not receive damage messages of their own - //this was done to simplify the code here (since we can only effectively skip one mob on queue) - eqFilterType filter; - Mob *skip = attacker; - if(attacker && attacker->GetOwnerID()) { - //attacker is a pet, let pet owners see their pet's damage - Mob* owner = attacker->GetOwner(); - if (owner && owner->IsClient()) { - if (((spell_id != SPELL_UNKNOWN) || (FromDamageShield)) && damage>0) { - //special crap for spell damage, looks hackish to me - char val1[20]={0}; - owner->Message_StringID(MT_NonMelee,OTHER_HIT_NONMELEE,GetCleanName(),ConvertArray(damage,val1)); - } else { - if(damage > 0) { - if(spell_id != SPELL_UNKNOWN) - filter = iBuffTic ? FilterDOT : FilterSpellDamage; - else - filter = FilterPetHits; - } else if(damage == -5) - filter = FilterNone; //cant filter invulnerable - else - filter = FilterPetMisses; - - if(!FromDamageShield) - owner->CastToClient()->QueuePacket(outapp,true,CLIENT_CONNECTED,filter); - } - } - skip = owner; - } else { - //attacker is not a pet, send to the attacker - - //if the attacker is a client, try them with the correct filter - if(attacker && attacker->IsClient()) { - if (((spell_id != SPELL_UNKNOWN)||(FromDamageShield)) && damage>0) { - //special crap for spell damage, looks hackish to me - char val1[20]={0}; - if (FromDamageShield) - { - if(!attacker->CastToClient()->GetFilter(FilterDamageShields) == FilterHide) - { - attacker->Message_StringID(MT_DS,OTHER_HIT_NONMELEE,GetCleanName(),ConvertArray(damage,val1)); - } - } - else - entity_list.MessageClose_StringID(this, true, 100, MT_NonMelee,HIT_NON_MELEE,attacker->GetCleanName(),GetCleanName(),ConvertArray(damage,val1)); - } else { - if(damage > 0) { - if(spell_id != SPELL_UNKNOWN) - filter = iBuffTic ? FilterDOT : FilterSpellDamage; - else - filter = FilterNone; //cant filter our own hits - } else if(damage == -5) - filter = FilterNone; //cant filter invulnerable - else - filter = FilterMyMisses; - - attacker->CastToClient()->QueuePacket(outapp, true, CLIENT_CONNECTED, filter); - } - } - skip = attacker; - } - - //send damage to all clients around except the specified skip mob (attacker or the attacker's owner) and ourself - if(damage > 0) { - if(spell_id != SPELL_UNKNOWN) - filter = iBuffTic ? FilterDOT : FilterSpellDamage; - else - filter = FilterOthersHit; - } else if(damage == -5) - filter = FilterNone; //cant filter invulnerable - else - filter = FilterOthersMiss; - //make attacker (the attacker) send the packet so we can skip them and the owner - //this call will send the packet to `this` as well (using the wrong filter) (will not happen until PC charm works) - // If this is Damage Shield damage, the correct OP_Damage packets will be sent from Mob::DamageShield, so - // we don't send them here. - if(!FromDamageShield) { - entity_list.QueueCloseClients(this, outapp, true, 200, skip, true, filter); - //send the damage to ourself if we are a client - if(IsClient()) { - //I dont think any filters apply to damage affecting us - CastToClient()->QueuePacket(outapp); - } - } - - safe_delete(outapp); - } else { - //else, it is a buff tic... - // Everhood - So we can see our dot dmg like live shows it. - if(spell_id != SPELL_UNKNOWN && damage > 0 && attacker && attacker != this && attacker->IsClient()) { - //might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it - attacker->FilteredMessage_StringID(attacker, MT_DoTDamage, FilterDOT, - YOUR_HIT_DOT, GetCleanName(), itoa(damage), spells[spell_id].name); - // older clients don't have the below String ID, but it will be filtered - entity_list.FilteredMessageClose_StringID(attacker, true, 200, - MT_DoTDamage, FilterDOT, OTHER_HIT_DOT, GetCleanName(), - itoa(damage), attacker->GetCleanName(), spells[spell_id].name); - } - } //end packet sending - -} - - -void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id) -{ - int32 maxhp = GetMaxHP(); - int32 curhp = GetHP(); - uint32 acthealed = 0; - - if (caster && amount > 0) { - if (caster->IsNPC() && !caster->IsPet()) { - float npchealscale = caster->CastToNPC()->GetHealScale(); - amount = (static_cast(amount) * npchealscale) / 100.0f; - } - } - - if (amount > (maxhp - curhp)) - acthealed = (maxhp - curhp); - else - acthealed = amount; - - if (acthealed > 100) { - if (caster) { - if (IsBuffSpell(spell_id)) { // hots - // message to caster - if (caster->IsClient() && caster == this) { - if (caster->CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) - FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, - HOT_HEAL_SELF, itoa(acthealed), spells[spell_id].name); - else - FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, - YOU_HEALED, GetCleanName(), itoa(acthealed)); - } else if (caster->IsClient() && caster != this) { - if (caster->CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) - caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, - HOT_HEAL_OTHER, GetCleanName(), itoa(acthealed), - spells[spell_id].name); - else - caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, - YOU_HEAL, GetCleanName(), itoa(acthealed)); - } - // message to target - if (IsClient() && caster != this) { - if (CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) - FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime, - HOT_HEALED_OTHER, caster->GetCleanName(), - itoa(acthealed), spells[spell_id].name); - else - FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime, - YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); - } - } else { // normal heals - FilteredMessage_StringID(caster, MT_NonMelee, FilterSpellDamage, - YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); - if (caster != this) - caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterSpellDamage, - YOU_HEAL, GetCleanName(), itoa(acthealed)); - } - } else { - Message(MT_NonMelee, "You have been healed for %d points of damage.", acthealed); - } - } - - if (curhp < maxhp) { - if ((curhp + amount) > maxhp) - curhp = maxhp; - else - curhp += amount; - SetHP(curhp); - - SendHPUpdate(); - } -} - -//proc chance includes proc bonus -float Mob::GetProcChances(float ProcBonus, uint16 weapon_speed, uint16 hand) -{ - int mydex = GetDEX(); - float ProcChance = 0.0f; - - switch (hand) { - case 13: - weapon_speed = attack_timer.GetDuration(); - break; - case 14: - weapon_speed = attack_dw_timer.GetDuration(); - break; - case 11: - weapon_speed = ranged_timer.GetDuration(); - break; - } - - //calculate the weapon speed in ms, so we can use the rule to compare against. - // fast as a client can swing, so should be the floor of the proc chance - if (weapon_speed < RuleI(Combat, MinHastedDelay)) - weapon_speed = RuleI(Combat, MinHastedDelay); - - if (RuleB(Combat, AdjustProcPerMinute)) { - ProcChance = (static_cast(weapon_speed) * - RuleR(Combat, AvgProcsPerMinute) / 60000.0f); // compensate for weapon_speed being in ms - ProcBonus += static_cast(mydex) * RuleR(Combat, ProcPerMinDexContrib); - ProcChance += ProcChance * ProcBonus / 100.0f; - } else { - ProcChance = RuleR(Combat, BaseProcChance) + - static_cast(mydex) / RuleR(Combat, ProcDexDivideBy); - ProcChance += ProcChance * ProcBonus / 100.0f; - } - - mlog(COMBAT__PROCS, "Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus); - return ProcChance; -} - -float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed, uint16 hand) { - int myagi = GetAGI(); - ProcBonus = 0; - ProcChance = 0; - - switch(hand){ - case 13: - weapon_speed = attack_timer.GetDuration(); - break; - case 14: - weapon_speed = attack_dw_timer.GetDuration(); - break; - case 11: - return 0; - break; - } - - //calculate the weapon speed in ms, so we can use the rule to compare against. - //weapon_speed = ((int)(weapon_speed*(100.0f+attack_speed)*PermaHaste)); - if(weapon_speed < RuleI(Combat, MinHastedDelay)) // fast as a client can swing, so should be the floor of the proc chance - weapon_speed = RuleI(Combat, MinHastedDelay); - - ProcChance = ((float)weapon_speed * RuleR(Combat, AvgDefProcsPerMinute) / 60000.0f); // compensate for weapon_speed being in ms - ProcBonus += float(myagi) * RuleR(Combat, DefProcPerMinAgiContrib) / 100.0f; - ProcChance = ProcChance + (ProcChance * ProcBonus); - - mlog(COMBAT__PROCS, "Defensive Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus); - return ProcChance; -} - -void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand, int damage) { - - if (!on) { - SetTarget(nullptr); - LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryDefensiveProc for evaluation!"); - return; - } - - bool bSkillProc = HasSkillProcs(); - bool bDefensiveProc = HasDefensiveProcs(); - - if (!bDefensiveProc && !bSkillProc) - return; - - if (!bDefensiveProc && (bSkillProc && damage >= 0)) - return; - - float ProcChance, ProcBonus; - if(weapon!=nullptr) - on->GetDefensiveProcChances(ProcBonus, ProcChance, weapon->GetItem()->Delay, hand); - else - on->GetDefensiveProcChances(ProcBonus, ProcChance); - if(hand != 13) - ProcChance /= 2; - - if (bDefensiveProc){ - for (int i = 0; i < MAX_PROCS; i++) { - if (DefensiveProcs[i].spellID != SPELL_UNKNOWN) { - int chance = ProcChance * (DefensiveProcs[i].chance); - if ((MakeRandomInt(0, 100) < chance)) { - ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on); - CheckNumHitsRemaining(10,0,DefensiveProcs[i].base_spellID); - } - } - } - } - - if (bSkillProc && damage < 0){ - - if (damage == -1) - TrySkillProc(on, SkillBlock, ProcChance); - - if (damage == -2) - TrySkillProc(on, SkillParry, ProcChance); - - if (damage == -3) - TrySkillProc(on, SkillRiposte, ProcChance); - - if (damage == -4) - TrySkillProc(on, SkillDodge, ProcChance); - } -} - -void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { - if(!on) { - SetTarget(nullptr); - LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryWeaponProc for evaluation!"); - return; - } - - if (!IsAttackAllowed(on)) { - mlog(COMBAT__PROCS, "Preventing procing off of unattackable things."); - return; - } - - if(!weapon_g) { - TrySpellProc(nullptr, (const Item_Struct*)nullptr, on); - return; - } - - if(!weapon_g->IsType(ItemClassCommon)) { - TrySpellProc(nullptr, (const Item_Struct*)nullptr, on); - return; - } - - // Innate + aug procs from weapons - // TODO: powersource procs - TryWeaponProc(weapon_g, weapon_g->GetItem(), on, hand); - // Procs from Buffs and AA both melee and range - TrySpellProc(weapon_g, weapon_g->GetItem(), on, hand); - - return; -} - -void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand) -{ - if (!weapon) - return; - uint16 skillinuse = 28; - int ourlevel = GetLevel(); - float ProcBonus = static_cast(aabonuses.ProcChanceSPA + - spellbonuses.ProcChanceSPA + itembonuses.ProcChanceSPA); - ProcBonus += static_cast(itembonuses.ProcChance) / 10.0f; // Combat Effects - float ProcChance = GetProcChances(ProcBonus, weapon->Delay, hand); - - if (hand != 13) //Is Archery intened to proc at 50% rate? - ProcChance /= 2; - - // Try innate proc on weapon - // We can proc once here, either weapon or one aug - bool proced = false; // silly bool to prevent augs from going if weapon does - skillinuse = GetSkillByItemType(weapon->ItemType); - if (weapon->Proc.Type == ET_CombatProc) { - float WPC = ProcChance * (100.0f + // Proc chance for this weapon - static_cast(weapon->ProcRate)) / 100.0f; - if (MakeRandomFloat(0, 1) <= WPC) { // 255 dex = 0.084 chance of proc. No idea what this number should be really. - if (weapon->Proc.Level > ourlevel) { - mlog(COMBAT__PROCS, - "Tried to proc (%s), but our level (%d) is lower than required (%d)", - weapon->Name, ourlevel, weapon->Proc.Level); - if (IsPet()) { - Mob *own = GetOwner(); - if (own) - own->Message_StringID(13, PROC_PETTOOLOW); - } else { - Message_StringID(13, PROC_TOOLOW); - } - } else { - mlog(COMBAT__PROCS, - "Attacking weapon (%s) successfully procing spell %d (%.2f percent chance)", - weapon->Name, weapon->Proc.Effect, WPC * 100); - ExecWeaponProc(inst, weapon->Proc.Effect, on); - proced = true; - } - } - } - - if (!proced && inst) { - for (int r = 0; r < MAX_AUGMENT_SLOTS; r++) { - const ItemInst *aug_i = inst->GetAugment(r); - if (!aug_i) // no aug, try next slot! - continue; - const Item_Struct *aug = aug_i->GetItem(); - if (!aug) - continue; - - if (aug->Proc.Type == ET_CombatProc) { - float APC = ProcChance * (100.0f + // Proc chance for this aug - static_cast(aug->ProcRate)) / 100.0f; - if (MakeRandomFloat(0, 1) <= APC) { - if (aug->Proc.Level > ourlevel) { - if (IsPet()) { - Mob *own = GetOwner(); - if (own) - own->Message_StringID(13, PROC_PETTOOLOW); - } else { - Message_StringID(13, PROC_TOOLOW); - } - } else { - ExecWeaponProc(aug_i, aug->Proc.Effect, on); - break; - } - } - } - } - } - // TODO: Powersource procs - if (HasSkillProcs()) - TrySkillProc(on, skillinuse, ProcChance); - - return; -} - -void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand) -{ - float ProcBonus = static_cast(spellbonuses.SpellProcChance + - itembonuses.SpellProcChance + aabonuses.SpellProcChance); - float ProcChance = 0.0f; - if (weapon) - ProcChance = GetProcChances(ProcBonus, weapon->Delay, hand); - else - ProcChance = GetProcChances(ProcBonus); - - if (hand != 13) //Is Archery intened to proc at 50% rate? - ProcChance /= 2; - - bool rangedattk = false; - if (weapon && hand == 11) { - if (weapon->ItemType == ItemTypeArrow || - weapon->ItemType == ItemTypeLargeThrowing || - weapon->ItemType == ItemTypeSmallThrowing || - weapon->ItemType == ItemTypeBow) - rangedattk = true; - } - - for (uint32 i = 0; i < MAX_PROCS; i++) { - if (IsPet() && hand != 13) //Pets can only proc spell procs from their primay hand (ie; beastlord pets) - continue; // If pets ever can proc from off hand, this will need to change - - // Not ranged - if (!rangedattk) { - // Perma procs (AAs) - if (PermaProcs[i].spellID != SPELL_UNKNOWN) { - if (MakeRandomInt(0, 99) < PermaProcs[i].chance) { // TODO: Do these get spell bonus? - mlog(COMBAT__PROCS, - "Permanent proc %d procing spell %d (%d percent chance)", - i, PermaProcs[i].spellID, PermaProcs[i].chance); - ExecWeaponProc(nullptr, PermaProcs[i].spellID, on); - } else { - mlog(COMBAT__PROCS, - "Permanent proc %d failed to proc %d (%d percent chance)", - i, PermaProcs[i].spellID, PermaProcs[i].chance); - } - } - - // Spell procs (buffs) - if (SpellProcs[i].spellID != SPELL_UNKNOWN) { - float chance = ProcChance * (SpellProcs[i].chance / 100.0f); - if (MakeRandomFloat(0, 1) <= chance) { - mlog(COMBAT__PROCS, - "Spell proc %d procing spell %d (%.2f percent chance)", - i, SpellProcs[i].spellID, chance); - ExecWeaponProc(nullptr, SpellProcs[i].spellID, on); - CheckNumHitsRemaining(11, 0, SpellProcs[i].base_spellID); - } else { - mlog(COMBAT__PROCS, - "Spell proc %d failed to proc %d (%.2f percent chance)", - i, SpellProcs[i].spellID, chance); - } - } - } else if (rangedattk) { // ranged only - // ranged spell procs (buffs) - if (RangedProcs[i].spellID != SPELL_UNKNOWN) { - float chance = ProcChance * (RangedProcs[i].chance / 100.0f); - if (MakeRandomFloat(0, 1) <= chance) { - mlog(COMBAT__PROCS, - "Ranged proc %d procing spell %d (%.2f percent chance)", - i, RangedProcs[i].spellID, chance); - ExecWeaponProc(nullptr, RangedProcs[i].spellID, on); - CheckNumHitsRemaining(11, 0, RangedProcs[i].base_spellID); - } else { - mlog(COMBAT__PROCS, - "Ranged proc %d failed to proc %d (%.2f percent chance)", - i, RangedProcs[i].spellID, chance); - } - } - } - } - - return; -} - -void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage) -{ - if(damage < 1) - return; - - //Allows pets to perform critical hits. - //Each rank adds an additional 1% chance for any melee hit (primary, secondary, kick, bash, etc) to critical, - //dealing up to 63% more damage. http://www.magecompendium.com/aa-short-library.html - - Mob *owner = nullptr; - float critChance = 0.0f; - critChance += RuleI(Combat, MeleeBaseCritChance); - uint16 critMod = 163; - - if (damage < 1) //We can't critical hit if we don't hit. - return; - - if (!IsPet()) - return; - - owner = GetOwner(); - - if (!owner) - return; - - int16 CritPetChance = owner->aabonuses.PetCriticalHit + owner->itembonuses.PetCriticalHit + owner->spellbonuses.PetCriticalHit; - int16 CritChanceBonus = GetCriticalChanceBonus(skill); - - if (CritPetChance || critChance) { - - //For pets use PetCriticalHit for base chance, pets do not innately critical with without it - //even if buffed with a CritChanceBonus effects. - critChance += CritPetChance; - critChance += critChance*CritChanceBonus/100.0f; - } - - if(critChance > 0){ - - critChance /= 100; - - if(MakeRandomFloat(0, 1) < critChance) - { - critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100 - damage = (damage * critMod) / 100; - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, CRITICAL_HIT, - GetCleanName(), itoa(damage)); - } - } -} - -void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts) -{ - if(damage < 1) - return; - - // decided to branch this into it's own function since it's going to be duplicating a lot of the - // code in here, but could lead to some confusion otherwise - if (IsPet() && GetOwner()->IsClient()) { - TryPetCriticalHit(defender,skill,damage); - return; - } - -#ifdef BOTS - if (this->IsPet() && this->GetOwner()->IsBot()) { - this->TryPetCriticalHit(defender,skill,damage); - return; - } -#endif //BOTS - - - float critChance = 0.0f; - - //1: Try Slay Undead - if(defender && defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire){ - - int16 SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0]; - - if (SlayRateBonus) { - - critChance += (float(SlayRateBonus)/100.0f); - critChance /= 100.0f; - - if(MakeRandomFloat(0, 1) < critChance){ - int16 SlayDmgBonus = aabonuses.SlayUndead[1] + itembonuses.SlayUndead[1] + spellbonuses.SlayUndead[1]; - damage = (damage*SlayDmgBonus*2.25)/100; - entity_list.MessageClose(this, false, 200, MT_CritMelee, "%s cleanses %s target!(%d)", GetCleanName(), this->GetGender() == 0 ? "his" : this->GetGender() == 1 ? "her" : "its", damage); - return; - } - } - } - - //2: Try Melee Critical - - //Base critical rate for all classes is dervived from DEX stat, this rate is then augmented - //by item,spell and AA bonuses allowing you a chance to critical hit. If the following rules - //are defined you will have an innate chance to hit at Level 1 regardless of bonuses. - //Warning: Do not define these rules if you want live like critical hits. - critChance += RuleI(Combat, MeleeBaseCritChance); - - if (IsClient()) { - critChance += RuleI(Combat, ClientBaseCritChance); - - if ((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) { - if (IsBerserk()) - critChance += RuleI(Combat, BerserkBaseCritChance); - else - critChance += RuleI(Combat, WarBerBaseCritChance); - } - } - - int deadlyChance = 0; - int deadlyMod = 0; - if(skill == SkillArchery && GetClass() == RANGER && GetSkill(SkillArchery) >= 65) - critChance += 6; - - if (skill == SkillThrowing && GetClass() == ROGUE && GetSkill(SkillThrowing) >= 65) { - critChance += RuleI(Combat, RogueCritThrowingChance); - deadlyChance = RuleI(Combat, RogueDeadlyStrikeChance); - deadlyMod = RuleI(Combat, RogueDeadlyStrikeMod); - } - - int CritChanceBonus = GetCriticalChanceBonus(skill); - - if (CritChanceBonus || critChance) { - - //Get Base CritChance from Dex. (200 = ~1.6%, 255 = ~2.0%, 355 = ~2.20%) Fall off rate > 255 - //http://giline.versus.jp/shiden/su.htm , http://giline.versus.jp/shiden/damage_e.htm - if (GetDEX() <= 255) - critChance += (float(GetDEX()) / 125.0f); - else if (GetDEX() > 255) - critChance += (float(GetDEX()-255)/ 500.0f) + 2.0f; - critChance += critChance*(float)CritChanceBonus /100.0f; - } - - if(opts) { - critChance *= opts->crit_percent; - critChance += opts->crit_flat; - } - - if(critChance > 0) { - - critChance /= 100; - - if(MakeRandomFloat(0, 1) < critChance) - { - uint16 critMod = 200; - bool crip_success = false; - int16 CripplingBlowChance = GetCrippBlowChance(); - - //Crippling Blow Chance: The percent value of the effect is applied - //to the your Chance to Critical. (ie You have 10% chance to critical and you - //have a 200% Chance to Critical Blow effect, therefore you have a 20% Chance to Critical Blow. - if (CripplingBlowChance || IsBerserk()) { - if (!IsBerserk()) - critChance *= float(CripplingBlowChance)/100.0f; - - if (IsBerserk() || MakeRandomFloat(0, 1) < critChance) { - critMod = 400; - crip_success = true; - } - } - - critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100 - damage = damage * critMod / 100; - - bool deadlySuccess = false; - if (deadlyChance && MakeRandomFloat(0, 1) < static_cast(deadlyChance) / 100.0f) { - if (BehindMob(defender, GetX(), GetY())) { - damage *= deadlyMod; - deadlySuccess = true; - } - } - - if (crip_success) { - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, CRIPPLING_BLOW, - GetCleanName(), itoa(damage)); - // Crippling blows also have a chance to stun - //Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a staggers message. - if (defender->GetLevel() <= 55 && !defender->GetSpecialAbility(IMMUNE_STUN)){ - defender->Emote("staggers."); - defender->Stun(0); - } - } else if (deadlySuccess) { - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, DEADLY_STRIKE, - GetCleanName(), itoa(damage)); - } else { - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, CRITICAL_HIT, - GetCleanName(), itoa(damage)); - } - } - } -} - - -bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) -{ - - if (!defender) - return false; - - if (aabonuses.FinishingBlow[1] && !defender->IsClient() && defender->GetHPRatio() < 10){ - - uint32 chance = aabonuses.FinishingBlow[0]/10; //500 = 5% chance. - uint32 damage = aabonuses.FinishingBlow[1]; - uint16 levelreq = aabonuses.FinishingBlowLvl[0]; - - if(defender->GetLevel() <= levelreq && (chance >= MakeRandomInt(0, 1000))){ - mlog(COMBAT__ATTACKS, "Landed a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); - defender->Damage(this, damage, SPELL_UNKNOWN, skillinuse); - return true; - } - else - { - mlog(COMBAT__ATTACKS, "FAILED a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); - return false; - } - } - return false; -} - -void Mob::DoRiposte(Mob* defender) { - mlog(COMBAT__ATTACKS, "Preforming a riposte"); - - if (!defender) - return; - - defender->Attack(this, SLOT_PRIMARY, true); - if (HasDied()) return; - - int16 DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[0] + - defender->spellbonuses.GiveDoubleRiposte[0] + - defender->itembonuses.GiveDoubleRiposte[0]; - - //Live AA - Double Riposte - if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) { - mlog(COMBAT__ATTACKS, "Preforming a double riposed (%d percent chance)", DoubleRipChance); - defender->Attack(this, SLOT_PRIMARY, true); - if (HasDied()) return; - } - - //Double Riposte effect, allows for a chance to do RIPOSTE with a skill specfic special attack (ie Return Kick). - //Coded narrowly: Limit to one per client. Limit AA only. [1 = Skill Attack Chance, 2 = Skill] - DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[1]; - - if(DoubleRipChance && (DoubleRipChance >= MakeRandomInt(0, 100))) { - mlog(COMBAT__ATTACKS, "Preforming a return SPECIAL ATTACK (%d percent chance)", DoubleRipChance); - - if (defender->GetClass() == MONK) - defender->MonkSpecialAttack(this, defender->aabonuses.GiveDoubleRiposte[2]); - else if (defender->IsClient()) - defender->CastToClient()->DoClassAttacks(this,defender->aabonuses.GiveDoubleRiposte[2], true); - } -} - -void Mob::ApplyMeleeDamageBonus(uint16 skill, int32 &damage){ - - if(!RuleB(Combat, UseIntervalAC)){ - if(IsNPC()){ //across the board NPC damage bonuses. - //only account for STR here, assume their base STR was factored into their DB damages - int dmgbonusmod = 0; - dmgbonusmod += (100*(itembonuses.STR + spellbonuses.STR))/3; - dmgbonusmod += (100*(spellbonuses.ATK + itembonuses.ATK))/5; - mlog(COMBAT__DAMAGE, "Damage bonus: %d percent from ATK and STR bonuses.", (dmgbonusmod/100)); - damage += (damage*dmgbonusmod/10000); - } - } - - damage += damage * GetMeleeDamageMod_SE(skill) / 100; -} - -bool Mob::HasDied() { - bool Result = false; - int16 hp_below = 0; - - hp_below = (GetDelayDeath() * -1); - - if((GetHP()) <= (hp_below)) - Result = true; - - return Result; -} - -uint16 Mob::GetDamageTable(SkillUseTypes skillinuse) -{ - if(GetLevel() <= 51) - { - uint16 ret_table = 0; - int str_over_75 = 0; - if(GetSTR() > 75) - str_over_75 = GetSTR() - 75; - if(str_over_75 > 255) - ret_table = (GetSkill(skillinuse)+255)/2; - else - ret_table = (GetSkill(skillinuse)+str_over_75)/2; - - if(ret_table < 100) - return 100; - - return ret_table; - } - else if(GetLevel() >= 90) - { - if(GetClass() == MONK) - return 379; - else - return 345; - } - else - { - uint16 dmg_table[] = { - 275, 275, 275, 275, 275, - 280, 280, 280, 280, 285, - 285, 285, 290, 290, 295, - 295, 300, 300, 300, 305, - 305, 305, 310, 310, 315, - 315, 320, 320, 320, 325, - 325, 325, 330, 330, 335, - 335, 340, 340, 340, - }; - if(GetClass() == MONK) - return (dmg_table[GetLevel()-51]*(100+RuleI(Combat,MonkDamageTableBonus))/100); - else - return dmg_table[GetLevel()-51]; - } -} - -void Mob::TrySkillProc(Mob *on, uint16 skill, float chance) -{ - - if (!on) { - SetTarget(nullptr); - LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TrySkillProc for evaluation!"); - return; - } - - for (int i = 0; i < MAX_PROCS; i++) { - if (SkillProcs[i].spellID != SPELL_UNKNOWN){ - if (PassLimitToSkill(SkillProcs[i].base_spellID,skill)){ - int ProcChance = chance * (float)SkillProcs[i].chance; - if ((MakeRandomInt(0, 100) < ProcChance)) { - ExecWeaponProc(nullptr, SkillProcs[i].spellID, on); - CheckNumHitsRemaining(11,0, SkillProcs[i].base_spellID); - } - } - } - } -} - -bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) -{ - /*Dev Quote 2010: http://forums.station.sony.com/eq/posts/list.m?topic_id=161443 - The Viscid Roots AA does the following: Reduces the chance for root to break by X percent. - There is no distinction of any kind between the caster inflicted damage, or anyone - else's damage. There is also no distinction between Direct and DOT damage in the root code. - There is however, a provision that if the damage inflicted is greater than 500 per hit, the - chance to break root is increased. My guess is when this code was put in place, the devs at - the time couldn't imagine DOT damage getting that high. - */ - - /* General Mechanics - - Check buffslot to make sure damage from a root does not cancel the root - - If multiple roots on target, always and only checks first root slot and if broken only removes that slots root. - - Only roots on determental spells can be broken by damage. - - Root break chance values obtained from live parses. - */ - - if (!attacker || !spellbonuses.Root[0] || spellbonuses.Root[1] < 0) - return false; - - if (IsDetrimentalSpell(spellbonuses.Root[1]) && spellbonuses.Root[1] != buffslot){ - - int BreakChance = RuleI(Spells, RootBreakFromSpells); - BreakChance -= BreakChance*buffs[spellbonuses.Root[1]].RootBreakChance/100; - int level_diff = attacker->GetLevel() - GetLevel(); - - attacker->Shout("%i ATTACKER LV %i",attacker->GetLevel(), level_diff); - Shout("%i DEF LEVEL %i", GetLevel(), level_diff); - //Use baseline if level difference <= 1 (ie. If target is (1) level less than you, or equal or greater level) - - if (level_diff == 2) - BreakChance = (BreakChance * 80) /100; //Decrease by 20%; - - else if (level_diff >= 3 && level_diff <= 20) - BreakChance = (BreakChance * 60) /100; //Decrease by 40%; - - else if (level_diff > 21) - BreakChance = (BreakChance * 20) /100; //Decrease by 80%; - - Shout("Root Break Chance %i Lv diff %i base %i ", BreakChance, level_diff, RuleI(Spells, RootBreakFromSpells)); - - if (BreakChance < 1) - BreakChance = 1; - - if (MakeRandomInt(0, 99) < BreakChance) { - - if (!TryFadeEffect(spellbonuses.Root[1])) { - BuffFadeBySlot(spellbonuses.Root[1]); - mlog(COMBAT__HITS, "Spell broke root! BreakChance percent chance"); - return true; - } - } - } - - mlog(COMBAT__HITS, "Spell did not break root. BreakChance percent chance"); - return false; -} - -int32 Mob::RuneAbsorb(int32 damage, uint16 type) -{ - uint32 buff_max = GetMaxTotalSlots(); - if (type == SE_Rune){ - for(uint32 slot = 0; slot < buff_max; slot++) { - if(slot == spellbonuses.MeleeRune[1] && spellbonuses.MeleeRune[0] && buffs[slot].melee_rune && IsValidSpell(buffs[slot].spellid)){ - uint32 melee_rune_left = buffs[slot].melee_rune; - - if(melee_rune_left > damage) - { - melee_rune_left -= damage; - buffs[slot].melee_rune = melee_rune_left; - return -6; - } - - else - { - if(melee_rune_left > 0) - damage -= melee_rune_left; - - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - } - } - } - - - else{ - for(uint32 slot = 0; slot < buff_max; slot++) { - if(slot == spellbonuses.AbsorbMagicAtt[1] && spellbonuses.AbsorbMagicAtt[0] && buffs[slot].magic_rune && IsValidSpell(buffs[slot].spellid)){ - uint32 magic_rune_left = buffs[slot].magic_rune; - if(magic_rune_left > damage) - { - magic_rune_left -= damage; - buffs[slot].magic_rune = magic_rune_left; - return 0; - } - - else - { - if(magic_rune_left > 0) - damage -= magic_rune_left; - - if(!TryFadeEffect(slot)) - BuffFadeBySlot(slot); - } - } - } - } - - return damage; -} - diff --git a/zone/bonusesxx.cpp b/zone/bonusesxx.cpp deleted file mode 100644 index 8e23eb5fb..000000000 --- a/zone/bonusesxx.cpp +++ /dev/null @@ -1,4337 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "../common/debug.h" -#include "../common/spdat.h" -#include "masterentity.h" -#include "../common/packet_dump.h" -#include "../common/moremath.h" -#include "../common/Item.h" -#include "worldserver.h" -#include "../common/skills.h" -#include "../common/bodytypes.h" -#include "../common/classes.h" -#include "../common/rulesys.h" -#include "QuestParserCollection.h" -#include -#include -#include -#ifndef WIN32 -#include -#include "../common/unix.h" -#endif - -#include "StringIDs.h" - -void Mob::CalcBonuses() -{ - CalcSpellBonuses(&spellbonuses); - CalcMaxHP(); - CalcMaxMana(); - SetAttackTimer(); - - rooted = FindType(SE_Root); -} - -void NPC::CalcBonuses() -{ - Mob::CalcBonuses(); - memset(&aabonuses, 0, sizeof(StatBonuses)); - - if(RuleB(NPC, UseItemBonusesForNonPets)){ - memset(&itembonuses, 0, sizeof(StatBonuses)); - CalcItemBonuses(&itembonuses); - } - else{ - if(GetOwner()){ - memset(&itembonuses, 0, sizeof(StatBonuses)); - CalcItemBonuses(&itembonuses); - } - } - - // This has to happen last, so we actually take the item bonuses into account. - Mob::CalcBonuses(); -} - -void Client::CalcBonuses() -{ - memset(&itembonuses, 0, sizeof(StatBonuses)); - CalcItemBonuses(&itembonuses); - CalcEdibleBonuses(&itembonuses); - - CalcSpellBonuses(&spellbonuses); - - _log(AA__BONUSES, "Calculating AA Bonuses for %s.", this->GetCleanName()); - CalcAABonuses(&aabonuses); //we're not quite ready for this - _log(AA__BONUSES, "Finished calculating AA Bonuses for %s.", this->GetCleanName()); - - RecalcWeight(); - - CalcAC(); - CalcATK(); - CalcHaste(); - - CalcSTR(); - CalcSTA(); - CalcDEX(); - CalcAGI(); - CalcINT(); - CalcWIS(); - CalcCHA(); - - CalcMR(); - CalcFR(); - CalcDR(); - CalcPR(); - CalcCR(); - CalcCorrup(); - - CalcMaxHP(); - CalcMaxMana(); - CalcMaxEndurance(); - - rooted = FindType(SE_Root); - - XPRate = 100 + spellbonuses.XPRateMod; -} - -int Client::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat) -{ - if( (reclevel > 0) && (level < reclevel) ) - { - int32 statmod = (level * 10000 / reclevel) * basestat; - - if( statmod < 0 ) - { - statmod -= 5000; - return (statmod/10000); - } - else - { - statmod += 5000; - return (statmod/10000); - } - } - - return 0; -} - -void Client::CalcItemBonuses(StatBonuses* newbon) { - //memset assumed to be done by caller. - - // Clear item faction mods - ClearItemFactionBonuses(); - ShieldEquiped(false); - - unsigned int i; - //should not include 21 (SLOT_AMMO) - for (i=0; i<21; i++) { - const ItemInst* inst = m_inv[i]; - if(inst == 0) - continue; - AddItemBonuses(inst, newbon); - - //Check if item is secondary slot is a 'shield'. Required for multiple spelll effects. - if (i == 14 && (m_inv.GetItem(14)->GetItem()->ItemType == ItemTypeShield)) - ShieldEquiped(true); - } - - //Power Source Slot - if (GetClientVersion() >= EQClientSoF) - { - const ItemInst* inst = m_inv[9999]; - if(inst) - AddItemBonuses(inst, newbon); - } - - //tribute items - for (i = 0; i < MAX_PLAYER_TRIBUTES; i++) { - const ItemInst* inst = m_inv[TRIBUTE_SLOT_START + i]; - if(inst == 0) - continue; - AddItemBonuses(inst, newbon, false, true); - } - // Caps - if(newbon->HPRegen > CalcHPRegenCap()) - newbon->HPRegen = CalcHPRegenCap(); - - if(newbon->ManaRegen > CalcManaRegenCap()) - newbon->ManaRegen = CalcManaRegenCap(); - - if(newbon->EnduranceRegen > CalcEnduranceRegenCap()) - newbon->EnduranceRegen = CalcEnduranceRegenCap(); - - SetAttackTimer(); -} - -void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute) { - if(!inst || !inst->IsType(ItemClassCommon)) - { - return; - } - - if(inst->GetAugmentType()==0 && isAug == true) - { - return; - } - - const Item_Struct *item = inst->GetItem(); - - if(!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass())) - { - if(item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink) - return; - } - - if(GetLevel() < item->ReqLevel) - { - return; - } - - if(GetLevel() >= item->RecLevel) - { - newbon->AC += item->AC; - newbon->HP += item->HP; - newbon->Mana += item->Mana; - newbon->Endurance += item->Endur; - newbon->STR += (item->AStr + item->HeroicStr); - newbon->STA += (item->ASta + item->HeroicSta); - newbon->DEX += (item->ADex + item->HeroicDex); - newbon->AGI += (item->AAgi + item->HeroicAgi); - newbon->INT += (item->AInt + item->HeroicInt); - newbon->WIS += (item->AWis + item->HeroicWis); - newbon->CHA += (item->ACha + item->HeroicCha); - - newbon->MR += (item->MR + item->HeroicMR); - newbon->FR += (item->FR + item->HeroicFR); - newbon->CR += (item->CR + item->HeroicCR); - newbon->PR += (item->PR + item->HeroicPR); - newbon->DR += (item->DR + item->HeroicDR); - newbon->Corrup += (item->SVCorruption + item->HeroicSVCorrup); - - newbon->STRCapMod += item->HeroicStr; - newbon->STACapMod += item->HeroicSta; - newbon->DEXCapMod += item->HeroicDex; - newbon->AGICapMod += item->HeroicAgi; - newbon->INTCapMod += item->HeroicInt; - newbon->WISCapMod += item->HeroicWis; - newbon->CHACapMod += item->HeroicCha; - newbon->MRCapMod += item->HeroicMR; - newbon->CRCapMod += item->HeroicFR; - newbon->FRCapMod += item->HeroicCR; - newbon->PRCapMod += item->HeroicPR; - newbon->DRCapMod += item->HeroicDR; - newbon->CorrupCapMod += item->HeroicSVCorrup; - - newbon->HeroicSTR += item->HeroicStr; - newbon->HeroicSTA += item->HeroicSta; - newbon->HeroicDEX += item->HeroicDex; - newbon->HeroicAGI += item->HeroicAgi; - newbon->HeroicINT += item->HeroicInt; - newbon->HeroicWIS += item->HeroicWis; - newbon->HeroicCHA += item->HeroicCha; - newbon->HeroicMR += item->HeroicMR; - newbon->HeroicFR += item->HeroicFR; - newbon->HeroicCR += item->HeroicCR; - newbon->HeroicPR += item->HeroicPR; - newbon->HeroicDR += item->HeroicDR; - newbon->HeroicCorrup += item->HeroicSVCorrup; - - } - else - { - int lvl = GetLevel(); - int reclvl = item->RecLevel; - - newbon->AC += CalcRecommendedLevelBonus( lvl, reclvl, item->AC ); - newbon->HP += CalcRecommendedLevelBonus( lvl, reclvl, item->HP ); - newbon->Mana += CalcRecommendedLevelBonus( lvl, reclvl, item->Mana ); - newbon->Endurance += CalcRecommendedLevelBonus( lvl, reclvl, item->Endur ); - newbon->STR += CalcRecommendedLevelBonus( lvl, reclvl, (item->AStr + item->HeroicStr) ); - newbon->STA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ASta + item->HeroicSta) ); - newbon->DEX += CalcRecommendedLevelBonus( lvl, reclvl, (item->ADex + item->HeroicDex) ); - newbon->AGI += CalcRecommendedLevelBonus( lvl, reclvl, (item->AAgi + item->HeroicAgi) ); - newbon->INT += CalcRecommendedLevelBonus( lvl, reclvl, (item->AInt + item->HeroicInt) ); - newbon->WIS += CalcRecommendedLevelBonus( lvl, reclvl, (item->AWis + item->HeroicWis) ); - newbon->CHA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ACha + item->HeroicCha) ); - - newbon->MR += CalcRecommendedLevelBonus( lvl, reclvl, (item->MR + item->HeroicMR) ); - newbon->FR += CalcRecommendedLevelBonus( lvl, reclvl, (item->FR + item->HeroicFR) ); - newbon->CR += CalcRecommendedLevelBonus( lvl, reclvl, (item->CR + item->HeroicCR) ); - newbon->PR += CalcRecommendedLevelBonus( lvl, reclvl, (item->PR + item->HeroicPR) ); - newbon->DR += CalcRecommendedLevelBonus( lvl, reclvl, (item->DR + item->HeroicDR) ); - newbon->Corrup += CalcRecommendedLevelBonus( lvl, reclvl, (item->SVCorruption + item->HeroicSVCorrup) ); - - newbon->STRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr ); - newbon->STACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta ); - newbon->DEXCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex ); - newbon->AGICapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi ); - newbon->INTCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt ); - newbon->WISCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis ); - newbon->CHACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha ); - newbon->MRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR ); - newbon->CRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR ); - newbon->FRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR ); - newbon->PRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR ); - newbon->DRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR ); - newbon->CorrupCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup ); - - newbon->HeroicSTR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr ); - newbon->HeroicSTA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta ); - newbon->HeroicDEX += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex ); - newbon->HeroicAGI += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi ); - newbon->HeroicINT += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt ); - newbon->HeroicWIS += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis ); - newbon->HeroicCHA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha ); - newbon->HeroicMR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR ); - newbon->HeroicFR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR ); - newbon->HeroicCR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR ); - newbon->HeroicPR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR ); - newbon->HeroicDR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR ); - newbon->HeroicCorrup += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup ); - } - - //FatherNitwit: New style haste, shields, and regens - if(newbon->haste < (int16)item->Haste) { - newbon->haste = item->Haste; - } - if(item->Regen > 0) - newbon->HPRegen += item->Regen; - - if(item->ManaRegen > 0) - newbon->ManaRegen += item->ManaRegen; - - if(item->EnduranceRegen > 0) - newbon->EnduranceRegen += item->EnduranceRegen; - - if(item->Attack > 0) { - - int cap = RuleI(Character, ItemATKCap); - cap += itembonuses.ItemATKCap + spellbonuses.ItemATKCap + aabonuses.ItemATKCap; - - if((newbon->ATK + item->Attack) > cap) - newbon->ATK = RuleI(Character, ItemATKCap); - else - newbon->ATK += item->Attack; - } - if(item->DamageShield > 0) { - if((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap)) - newbon->DamageShield = RuleI(Character, ItemDamageShieldCap); - else - newbon->DamageShield += item->DamageShield; - } - if(item->SpellShield > 0) { - if((newbon->SpellShield + item->SpellShield) > RuleI(Character, ItemSpellShieldingCap)) - newbon->SpellShield = RuleI(Character, ItemSpellShieldingCap); - else - newbon->SpellShield += item->SpellShield; - } - if(item->Shielding > 0) { - if((newbon->MeleeMitigation + item->Shielding) > RuleI(Character, ItemShieldingCap)) - newbon->MeleeMitigation = RuleI(Character, ItemShieldingCap); - else - newbon->MeleeMitigation += item->Shielding; - } - if(item->StunResist > 0) { - if((newbon->StunResist + item->StunResist) > RuleI(Character, ItemStunResistCap)) - newbon->StunResist = RuleI(Character, ItemStunResistCap); - else - newbon->StunResist += item->StunResist; - } - if(item->StrikeThrough > 0) { - if((newbon->StrikeThrough + item->StrikeThrough) > RuleI(Character, ItemStrikethroughCap)) - newbon->StrikeThrough = RuleI(Character, ItemStrikethroughCap); - else - newbon->StrikeThrough += item->StrikeThrough; - } - if(item->Avoidance > 0) { - if((newbon->AvoidMeleeChance + item->Avoidance) > RuleI(Character, ItemAvoidanceCap)) - newbon->AvoidMeleeChance = RuleI(Character, ItemAvoidanceCap); - else - newbon->AvoidMeleeChance += item->Avoidance; - } - if(item->Accuracy > 0) { - if((newbon->HitChance + item->Accuracy) > RuleI(Character, ItemAccuracyCap)) - newbon->HitChance = RuleI(Character, ItemAccuracyCap); - else - newbon->HitChance += item->Accuracy; - } - if(item->CombatEffects > 0) { - if((newbon->ProcChance + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap)) - newbon->ProcChance = RuleI(Character, ItemCombatEffectsCap); - else - newbon->ProcChance += item->CombatEffects; - } - if(item->DotShielding > 0) { - if((newbon->DoTShielding + item->DotShielding) > RuleI(Character, ItemDoTShieldingCap)) - newbon->DoTShielding = RuleI(Character, ItemDoTShieldingCap); - else - newbon->DoTShielding += item->DotShielding; - } - - if(item->HealAmt > 0) { - if((newbon->HealAmt + item->HealAmt) > RuleI(Character, ItemHealAmtCap)) - newbon->HealAmt = RuleI(Character, ItemHealAmtCap); - else - newbon->HealAmt += item->HealAmt; - } - if(item->SpellDmg > 0) { - if((newbon->SpellDmg + item->SpellDmg) > RuleI(Character, ItemSpellDmgCap)) - newbon->SpellDmg = RuleI(Character, ItemSpellDmgCap); - else - newbon->SpellDmg += item->SpellDmg; - } - if(item->Clairvoyance > 0) { - if((newbon->Clairvoyance + item->Clairvoyance) > RuleI(Character, ItemClairvoyanceCap)) - newbon->Clairvoyance = RuleI(Character, ItemClairvoyanceCap); - else - newbon->Clairvoyance += item->Clairvoyance; - } - - if(item->DSMitigation > 0) { - if((newbon->DSMitigation + item->DSMitigation) > RuleI(Character, ItemDSMitigationCap)) - newbon->DSMitigation = RuleI(Character, ItemDSMitigationCap); - else - newbon->DSMitigation += item->DSMitigation; - } - if (item->Worn.Effect>0 && (item->Worn.Type == ET_WornEffect)) { // latent effects - ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, true); - } - - if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects - ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0, true); - } - - switch(item->BardType) - { - case 51: /* All (e.g. Singing Short Sword) */ - { - if(item->BardValue > newbon->singingMod) - newbon->singingMod = item->BardValue; - if(item->BardValue > newbon->brassMod) - newbon->brassMod = item->BardValue; - if(item->BardValue > newbon->stringedMod) - newbon->stringedMod = item->BardValue; - if(item->BardValue > newbon->percussionMod) - newbon->percussionMod = item->BardValue; - if(item->BardValue > newbon->windMod) - newbon->windMod = item->BardValue; - break; - } - case 50: /* Singing */ - { - if(item->BardValue > newbon->singingMod) - newbon->singingMod = item->BardValue; - break; - } - case 23: /* Wind */ - { - if(item->BardValue > newbon->windMod) - newbon->windMod = item->BardValue; - break; - } - case 24: /* stringed */ - { - if(item->BardValue > newbon->stringedMod) - newbon->stringedMod = item->BardValue; - break; - } - case 25: /* brass */ - { - if(item->BardValue > newbon->brassMod) - newbon->brassMod = item->BardValue; - break; - } - case 26: /* Percussion */ - { - if(item->BardValue > newbon->percussionMod) - newbon->percussionMod = item->BardValue; - break; - } - } - - if (item->SkillModValue != 0 && item->SkillModType <= HIGHEST_SKILL){ - if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) || - (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) - { - newbon->skillmod[item->SkillModType] = item->SkillModValue; - } - } - - // Add Item Faction Mods - if (item->FactionMod1) - { - if (item->FactionAmt1 > 0 && item->FactionAmt1 > GetItemFactionBonus(item->FactionMod1)) - { - AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); - } - else if (item->FactionAmt1 < 0 && item->FactionAmt1 < GetItemFactionBonus(item->FactionMod1)) - { - AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); - } - } - if (item->FactionMod2) - { - if (item->FactionAmt2 > 0 && item->FactionAmt2 > GetItemFactionBonus(item->FactionMod2)) - { - AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); - } - else if (item->FactionAmt2 < 0 && item->FactionAmt2 < GetItemFactionBonus(item->FactionMod2)) - { - AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); - } - } - if (item->FactionMod3) - { - if (item->FactionAmt3 > 0 && item->FactionAmt3 > GetItemFactionBonus(item->FactionMod3)) - { - AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); - } - else if (item->FactionAmt3 < 0 && item->FactionAmt3 < GetItemFactionBonus(item->FactionMod3)) - { - AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); - } - } - if (item->FactionMod4) - { - if (item->FactionAmt4 > 0 && item->FactionAmt4 > GetItemFactionBonus(item->FactionMod4)) - { - AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); - } - else if (item->FactionAmt4 < 0 && item->FactionAmt4 < GetItemFactionBonus(item->FactionMod4)) - { - AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); - } - } - - if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= HIGHEST_SKILL) { - if((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) - newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); - else - newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt; - } - - if (!isAug) - { - int i; - for(i = 0; i < MAX_AUGMENT_SLOTS; i++) { - AddItemBonuses(inst->GetAugment(i),newbon,true); - } - } - -} - -void Client::CalcEdibleBonuses(StatBonuses* newbon) { -#if EQDEBUG >= 11 - std::cout<<"Client::CalcEdibleBonuses(StatBonuses* newbon)"<GetItem() && inst->IsType(ItemClassCommon)) { - const Item_Struct *item=inst->GetItem(); - if (item->ItemType == ItemTypeFood && !food) - food = true; - else if (item->ItemType == ItemTypeDrink && !drink) - drink = true; - else - continue; - AddItemBonuses(inst, newbon); - } - } - for (i = 251; i <= 330; i++) - { - if (food && drink) - break; - const ItemInst* inst = GetInv().GetItem(i); - if (inst && inst->GetItem() && inst->IsType(ItemClassCommon)) { - const Item_Struct *item=inst->GetItem(); - if (item->ItemType == ItemTypeFood && !food) - food = true; - else if (item->ItemType == ItemTypeDrink && !drink) - drink = true; - else - continue; - AddItemBonuses(inst, newbon); - } - } -} - -void Client::CalcAABonuses(StatBonuses* newbon) { - memset(newbon, 0, sizeof(StatBonuses)); //start fresh - - int i; - uint32 slots = 0; - uint32 aa_AA = 0; - uint32 aa_value = 0; - if(this->aa) { - for (i = 0; i < MAX_PP_AA_ARRAY; i++) { //iterate through all of the client's AAs - if (this->aa[i]) { // make sure aa exists or we'll crash zone - aa_AA = this->aa[i]->AA; //same as aaid from the aa_effects table - aa_value = this->aa[i]->value; //how many points in it - if (aa_AA > 0 || aa_value > 0) { //do we have the AA? if 1 of the 2 is set, we can assume we do - //slots = database.GetTotalAALevels(aa_AA); //find out how many effects from aa_effects table - slots = zone->GetTotalAALevels(aa_AA); //find out how many effects from aa_effects, which is loaded into memory - if (slots > 0) //and does it have any effects? may be able to put this above, not sure if it runs on each iteration - ApplyAABonuses(aa_AA, slots, newbon); //add the bonuses - } - } - } - } -} - - -//A lot of the normal spell functions (IsBlankSpellEffect, etc) are set for just spells (in common/spdat.h). -//For now, we'll just put them directly into the code and comment with the corresponding normal function -//Maybe we'll fix it later? :-D -void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) -{ - if(slots == 0) //sanity check. why bother if no slots to fill? - return; - - //from AA_Ability struct - uint32 effect = 0; - int32 base1 = 0; - int32 base2 = 0; //only really used for SE_RaiseStatCap & SE_ReduceSkillTimer in aa_effects table - uint32 slot = 0; - - std::map >::const_iterator find_iter = aa_effects.find(aaid); - if(find_iter == aa_effects.end()) - { - return; - } - - for (std::map::const_iterator iter = aa_effects[aaid].begin(); iter != aa_effects[aaid].end(); ++iter) { - effect = iter->second.skill_id; - base1 = iter->second.base1; - base2 = iter->second.base2; - slot = iter->second.slot; - - //we default to 0 (SE_CurrentHP) for the effect, so if there aren't any base1/2 values, we'll just skip it - if (effect == 0 && base1 == 0 && base2 == 0) - continue; - - //IsBlankSpellEffect() - if (effect == SE_Blank || (effect == SE_CHA && base1 == 0) || effect == SE_StackingCommand_Block || effect == SE_StackingCommand_Overwrite) - continue; - - _log(AA__BONUSES, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName()); - - uint8 focus = IsFocusEffect(0, 0, true,effect); - if (focus) - { - newbon->FocusEffects[focus] = effect; - continue; - } - - switch (effect) - { - //Note: AA effects that use accuracy are skill limited, while spell effect is not. - case SE_Accuracy: - if ((base2 == -1) && (newbon->Accuracy[HIGHEST_SKILL+1] < base1)) - newbon->Accuracy[HIGHEST_SKILL+1] = base1; - else if (newbon->Accuracy[base2] < base1) - newbon->Accuracy[base2] += base1; - break; - case SE_CurrentHP: //regens - newbon->HPRegen += base1; - break; - case SE_CurrentEndurance: - newbon->EnduranceRegen += base1; - break; - case SE_MovementSpeed: - newbon->movementspeed += base1; //should we let these stack? - /*if (base1 > newbon->movementspeed) //or should we use a total value? - newbon->movementspeed = base1;*/ - break; - case SE_STR: - newbon->STR += base1; - break; - case SE_DEX: - newbon->DEX += base1; - break; - case SE_AGI: - newbon->AGI += base1; - break; - case SE_STA: - newbon->STA += base1; - break; - case SE_INT: - newbon->INT += base1; - break; - case SE_WIS: - newbon->WIS += base1; - break; - case SE_CHA: - newbon->CHA += base1; - break; - case SE_WaterBreathing: - //handled by client - break; - case SE_CurrentMana: - newbon->ManaRegen += base1; - break; - case SE_ItemManaRegenCapIncrease: - newbon->ItemManaRegenCap += base1; - break; - case SE_ResistFire: - newbon->FR += base1; - break; - case SE_ResistCold: - newbon->CR += base1; - break; - case SE_ResistPoison: - newbon->PR += base1; - break; - case SE_ResistDisease: - newbon->DR += base1; - break; - case SE_ResistMagic: - newbon->MR += base1; - break; - case SE_ResistCorruption: - newbon->Corrup += base1; - break; - case SE_IncreaseSpellHaste: - break; - case SE_IncreaseRange: - break; - case SE_MaxHPChange: - newbon->MaxHP += base1; - break; - case SE_Packrat: - newbon->Packrat += base1; - break; - case SE_TwoHandBash: - break; - case SE_SetBreathLevel: - break; - case SE_RaiseStatCap: - switch(base2) - { - //are these #define'd somewhere? - case 0: //str - newbon->STRCapMod += base1; - break; - case 1: //sta - newbon->STACapMod += base1; - break; - case 2: //agi - newbon->AGICapMod += base1; - break; - case 3: //dex - newbon->DEXCapMod += base1; - break; - case 4: //wis - newbon->WISCapMod += base1; - break; - case 5: //int - newbon->INTCapMod += base1; - break; - case 6: //cha - newbon->CHACapMod += base1; - break; - case 7: //mr - newbon->MRCapMod += base1; - break; - case 8: //cr - newbon->CRCapMod += base1; - break; - case 9: //fr - newbon->FRCapMod += base1; - break; - case 10: //pr - newbon->PRCapMod += base1; - break; - case 11: //dr - newbon->DRCapMod += base1; - break; - case 12: //corruption - newbon->CorrupCapMod += base1; - break; - } - break; - case SE_PetDiscipline2: - break; - case SE_SpellSlotIncrease: - break; - case SE_MysticalAttune: - newbon->BuffSlotIncrease += base1; - break; - case SE_TotalHP: - newbon->HP += base1; - break; - case SE_StunResist: - newbon->StunResist += base1; - break; - case SE_SpellCritChance: - newbon->CriticalSpellChance += base1; - break; - case SE_SpellCritDmgIncrease: - newbon->SpellCritDmgIncrease += base1; - break; - case SE_DotCritDmgIncrease: - newbon->DotCritDmgIncrease += base1; - break; - case SE_ResistSpellChance: - newbon->ResistSpellChance += base1; - break; - case SE_CriticalHealChance: - newbon->CriticalHealChance += base1; - break; - case SE_CriticalHealOverTime: - newbon->CriticalHealOverTime += base1; - break; - case SE_CriticalDoTChance: - newbon->CriticalDoTChance += base1; - break; - case SE_ReduceSkillTimer: - newbon->SkillReuseTime[base2] += base1; - break; - case SE_Fearless: - newbon->Fearless = true; - break; - case SE_PersistantCasting: - newbon->PersistantCasting += base1; - break; - case SE_DelayDeath: - newbon->DelayDeath += base1; - break; - case SE_FrontalStunResist: - newbon->FrontalStunResist += base1; - break; - case SE_ImprovedBindWound: - newbon->BindWound += base1; - break; - case SE_MaxBindWound: - newbon->MaxBindWound += base1; - break; - case SE_ExtraAttackChance: - newbon->ExtraAttackChance += base1; - break; - case SE_SeeInvis: - newbon->SeeInvis = base1; - break; - case SE_BaseMovementSpeed: - newbon->BaseMovementSpeed += base1; - break; - case SE_IncreaseRunSpeedCap: - newbon->IncreaseRunSpeedCap += base1; - break; - case SE_ConsumeProjectile: - newbon->ConsumeProjectile += base1; - break; - case SE_ForageAdditionalItems: - newbon->ForageAdditionalItems += base1; - break; - case SE_Salvage: - newbon->SalvageChance += base1; - break; - case SE_ArcheryDamageModifier: - newbon->ArcheryDamageModifier += base1; - break; - case SE_DoubleRangedAttack: - newbon->DoubleRangedAttack += base1; - break; - case SE_DamageShield: - newbon->DamageShield += base1; - break; - case SE_CharmBreakChance: - newbon->CharmBreakChance += base1; - break; - case SE_OffhandRiposteFail: - newbon->OffhandRiposteFail += base1; - break; - case SE_ItemAttackCapIncrease: - newbon->ItemATKCap += base1; - break; - case SE_GivePetGroupTarget: - newbon->GivePetGroupTarget = true; - break; - case SE_ItemHPRegenCapIncrease: - newbon->ItemHPRegenCap = +base1; - break; - case SE_Ambidexterity: - newbon->Ambidexterity += base1; - break; - case SE_PetMaxHP: - newbon->PetMaxHP += base1; - break; - case SE_AvoidMeleeChance: - newbon->AvoidMeleeChance += base1; - break; - case SE_CombatStability: - newbon->CombatStability += base1; - break; - case SE_AddSingingMod: - switch (base2) - { - case ItemTypeWindInstrument: - newbon->windMod += base1; - break; - case ItemTypeStringedInstrument: - newbon->stringedMod += base1; - break; - case ItemTypeBrassInstrument: - newbon->brassMod += base1; - break; - case ItemTypePercussionInstrument: - newbon->percussionMod += base1; - break; - case ItemTypeSinging: - newbon->singingMod += base1; - break; - } - break; - case SE_SongModCap: - newbon->songModCap += base1; - break; - case SE_PetCriticalHit: - newbon->PetCriticalHit += base1; - break; - case SE_PetAvoidance: - newbon->PetAvoidance += base1; - break; - case SE_ShieldBlock: - newbon->ShieldBlock += base1; - break; - case SE_ShieldEquipHateMod: - newbon->ShieldEquipHateMod += base1; - break; - case SE_ShieldEquipDmgMod: - newbon->ShieldEquipDmgMod[0] += base1; - newbon->ShieldEquipDmgMod[1] += base2; - break; - case SE_SecondaryDmgInc: - newbon->SecondaryDmgInc = true; - break; - case SE_ChangeAggro: - newbon->hatemod += base1; - break; - case SE_EndurancePool: - newbon->Endurance += base1; - break; - case SE_ChannelChanceItems: - newbon->ChannelChanceItems += base1; - break; - case SE_ChannelChanceSpells: - newbon->ChannelChanceSpells += base1; - break; - case SE_DoubleSpecialAttack: - newbon->DoubleSpecialAttack += base1; - break; - case SE_TripleBackstab: - newbon->TripleBackstab += base1; - break; - case SE_FrontalBackstabMinDmg: - newbon->FrontalBackstabMinDmg = true; - break; - case SE_FrontalBackstabChance: - newbon->FrontalBackstabChance += base1; - break; - case SE_BlockBehind: - newbon->BlockBehind += base1; - break; - - case SE_StrikeThrough: - case SE_StrikeThrough2: - newbon->StrikeThrough += base1; - break; - case SE_DoubleAttackChance: - newbon->DoubleAttackChance += base1; - break; - case SE_GiveDoubleAttack: - newbon->GiveDoubleAttack += base1; - break; - case SE_ProcChance: - newbon->ProcChanceSPA += base1; - break; - case SE_RiposteChance: - newbon->RiposteChance += base1; - break; - case SE_Flurry: - newbon->FlurryChance += base1; - break; - case SE_PetFlurry: - newbon->PetFlurry = base1; - break; - case SE_BardSongRange: - newbon->SongRange += base1; - break; - case SE_RootBreakChance: - newbon->RootBreakChance += base1; - break; - case SE_UnfailingDivinity: - newbon->UnfailingDivinity += base1; - break; - case SE_CrippBlowChance: - newbon->CrippBlowChance += base1; - break; - - case SE_ProcOnKillShot: - for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) - { - if(!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == base2) && (newbon->SpellOnKill[i+1] < base1))) - { - //base1 = chance, base2 = SpellID to be triggered, base3 = min npc level - newbon->SpellOnKill[i] = base2; - newbon->SpellOnKill[i+1] = base1; - - if (GetLevel() > 15) - newbon->SpellOnKill[i+2] = GetLevel() - 15; //AA specifiy "non-trivial" - else - newbon->SpellOnKill[i+2] = 0; - - break; - } - } - break; - - case SE_SpellOnDeath: - for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) - { - if(!newbon->SpellOnDeath[i]) - { - // base1 = SpellID to be triggered, base2 = chance to fire - newbon->SpellOnDeath[i] = base1; - newbon->SpellOnDeath[i+1] = base2; - break; - } - } - break; - - case SE_TriggerOnCast: - - for(int i = 0; i < MAX_SPELL_TRIGGER; i++) - { - if (newbon->SpellTriggers[i] == aaid) - break; - - if(!newbon->SpellTriggers[i]) - { - //Save the 'aaid' of each triggerable effect to an array - newbon->SpellTriggers[i] = aaid; - break; - } - } - break; - - case SE_CriticalHitChance: - { - if(base2 == -1) - newbon->CriticalHitChance[HIGHEST_SKILL+1] += base1; - else - newbon->CriticalHitChance[base2] += base1; - } - break; - - case SE_CriticalDamageMob: - { - // base1 = effect value, base2 = skill restrictions(-1 for all) - if(base2 == -1) - newbon->CritDmgMob[HIGHEST_SKILL+1] += base1; - else - newbon->CritDmgMob[base2] += base1; - break; - } - - case SE_CriticalSpellChance: - { - newbon->CriticalSpellChance += base1; - - if (base2 > newbon->SpellCritDmgIncNoStack) - newbon->SpellCritDmgIncNoStack = base2; - - break; - } - - case SE_ResistFearChance: - { - if(base1 == 100) // If we reach 100% in a single spell/item then we should be immune to negative fear resist effects until our immunity is over - newbon->Fearless = true; - - newbon->ResistFearChance += base1; // these should stack - break; - } - - case SE_SkillDamageAmount: - { - if(base2 == -1) - newbon->SkillDamageAmount[HIGHEST_SKILL+1] += base1; - else - newbon->SkillDamageAmount[base2] += base1; - break; - } - - case SE_SpecialAttackKBProc: - { - //You can only have one of these per client. [AA Dragon Punch] - newbon->SpecialAttackKBProc[0] = base1; //Chance base 100 = 25% proc rate - newbon->SpecialAttackKBProc[1] = base2; //Skill to KB Proc Off - break; - } - - case SE_DamageModifier: - { - if(base2 == -1) - newbon->DamageModifier[HIGHEST_SKILL+1] += base1; - else - newbon->DamageModifier[base2] += base1; - break; - } - - case SE_DamageModifier2: - { - if(base2 == -1) - newbon->DamageModifier2[HIGHEST_SKILL+1] += base1; - else - newbon->DamageModifier2[base2] += base1; - break; - } - - case SE_SlayUndead: - { - if(newbon->SlayUndead[1] < base1) - newbon->SlayUndead[0] = base1; // Rate - newbon->SlayUndead[1] = base2; // Damage Modifier - break; - } - - case SE_DoubleRiposte: - { - newbon->DoubleRiposte += base1; - } - - case SE_GiveDoubleRiposte: - { - //0=Regular Riposte 1=Skill Attack Riposte 2=Skill - if(base2 == 0){ - if(newbon->GiveDoubleRiposte[0] < base1) - newbon->GiveDoubleRiposte[0] = base1; - } - //Only for special attacks. - else if(base2 > 0 && (newbon->GiveDoubleRiposte[1] < base1)){ - newbon->GiveDoubleRiposte[1] = base1; - newbon->GiveDoubleRiposte[2] = base2; - } - - break; - } - - //Kayen: Not sure best way to implement this yet. - //Physically raises skill cap ie if 55/55 it will raise to 55/60 - case SE_RaiseSkillCap: - { - if(newbon->RaiseSkillCap[0] < base1){ - newbon->RaiseSkillCap[0] = base1; //value - newbon->RaiseSkillCap[1] = base2; //skill - } - break; - } - - case SE_MasteryofPast: - { - if(newbon->MasteryofPast < base1) - newbon->MasteryofPast = base1; - break; - } - - case SE_CastingLevel2: - case SE_CastingLevel: - { - newbon->effective_casting_level += base1; - break; - } - - case SE_DivineSave: - { - if(newbon->DivineSaveChance[0] < base1) - { - newbon->DivineSaveChance[0] = base1; - newbon->DivineSaveChance[1] = base2; - } - break; - } - - - case SE_SpellEffectResistChance: - { - for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) - { - if(newbon->SEResist[e+1] && (newbon->SEResist[e] == base2) && (newbon->SEResist[e+1] < base1)){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = base1; //Resist Chance - break; - } - else if (!newbon->SEResist[e+1]){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = base1; //Resist Chance - break; - } - } - break; - } - - case SE_MitigateDamageShield: - { - if (base1 < 0) - base1 = base1*(-1); - - newbon->DSMitigationOffHand += base1; - break; - } - - case SE_FinishingBlow: - { - //base1 = chance, base2 = damage - if (newbon->FinishingBlow[1] < base2){ - newbon->FinishingBlow[0] = base1; - newbon->FinishingBlow[1] = base2; - } - break; - } - - case SE_FinishingBlowLvl: - { - //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) - if (newbon->FinishingBlowLvl[0] < base1){ - newbon->FinishingBlowLvl[0] = base1; - newbon->FinishingBlowLvl[1] = base2; - } - break; - } - - case SE_StunBashChance: - newbon->StunBashChance += base1; - break; - - case SE_IncreaseChanceMemwipe: - newbon->IncreaseChanceMemwipe += base1; - break; - - case SE_CriticalMend: - newbon->CriticalMend += base1; - break; - - case SE_HealRate: - newbon->HealRate += base1; - break; - - case SE_MeleeLifetap: - { - - if((base1 < 0) && (newbon->MeleeLifetap > base1)) - newbon->MeleeLifetap = base1; - - else if(newbon->MeleeLifetap < base1) - newbon->MeleeLifetap = base1; - break; - } - - case SE_Vampirism: - newbon->Vampirism += base1; - break; - - case SE_FrenziedDevastation: - newbon->FrenziedDevastation += base2; - break; - - case SE_SpellProcChance: - newbon->SpellProcChance += base1; - break; - - case SE_Berserk: - newbon->BerserkSPA = true; - break; - - case SE_Metabolism: - newbon->Metabolism += base1; - break; - - case SE_ImprovedReclaimEnergy: - { - if((base1 < 0) && (newbon->ImprovedReclaimEnergy > base1)) - newbon->ImprovedReclaimEnergy = base1; - - else if(newbon->ImprovedReclaimEnergy < base1) - newbon->ImprovedReclaimEnergy = base1; - break; - } - - case SE_HeadShot: - { - if(newbon->HeadShot[1] < base2){ - newbon->HeadShot[0] = base1; - newbon->HeadShot[1] = base2; - } - break; - } - - case SE_HeadShotLevel: - { - if(newbon->HSLevel < base1) - newbon->HSLevel = base1; - break; - } - - case SE_Assassinate: - { - if(newbon->Assassinate[1] < base2){ - newbon->Assassinate[0] = base1; - newbon->Assassinate[1] = base2; - } - break; - } - - case SE_AssassinateLevel: - { - if(newbon->AssassinateLevel < base1) - newbon->AssassinateLevel = base1; - break; - } - - case SE_PetMeleeMitigation: - newbon->PetMeleeMitigation += base1; - break; - - } - } -} - -void Mob::CalcSpellBonuses(StatBonuses* newbon) -{ - int i; - - memset(newbon, 0, sizeof(StatBonuses)); - newbon->AggroRange = -1; - newbon->AssistRange = -1; - - uint32 buff_count = GetMaxTotalSlots(); - for(i = 0; i < buff_count; i++) { - if(buffs[i].spellid != SPELL_UNKNOWN){ - ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, false, buffs[i].ticsremaining,i); - - if (buffs[i].numhits > 0) - Numhits(true); - } - } - - //Applies any perma NPC spell bonuses from npc_spells_effects table. - if (IsNPC()) - CastToNPC()->ApplyAISpellEffects(newbon); - - //Removes the spell bonuses that are effected by a 'negate' debuff. - if (spellbonuses.NegateEffects){ - for(i = 0; i < buff_count; i++) { - if( (buffs[i].spellid != SPELL_UNKNOWN) && (IsEffectInSpell(buffs[i].spellid, SE_NegateSpellEffect)) ) - NegateSpellsBonuses(buffs[i].spellid); - } - } - //this prolly suffer from roundoff error slightly... - newbon->AC = newbon->AC * 10 / 34; //ratio determined impirically from client. - if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. -} - -void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterId, bool item_bonus, uint32 ticsremaining, int buffslot, - bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max) -{ - int i, effect_value, base2, max, effectid; - Mob *caster = nullptr; - - if(!IsAISpellEffect && !IsValidSpell(spell_id)) - return; - - if(casterId > 0) - caster = entity_list.GetMob(casterId); - - for (i = 0; i < EFFECT_COUNT; i++) - { - //Buffs/Item effects - if (!IsAISpellEffect) { - - if(IsBlankSpellEffect(spell_id, i)) - continue; - - uint8 focus = IsFocusEffect(spell_id, i); - if (focus) - { - newbon->FocusEffects[focus] = spells[spell_id].effectid[i]; - continue; - } - - - effectid = spells[spell_id].effectid[i]; - effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, caster, ticsremaining); - base2 = spells[spell_id].base2[i]; - max = spells[spell_id].max[i]; - } - //Use AISpellEffects - else { - effectid = effect_id; - effect_value = se_base; - base2 = se_limit; - max = se_max; - i = EFFECT_COUNT; //End the loop - } - - switch (effectid) - { - case SE_CurrentHP: //regens - if(effect_value > 0) { - newbon->HPRegen += effect_value; - } - break; - - case SE_CurrentEndurance: - newbon->EnduranceRegen += effect_value; - break; - - case SE_ChangeFrenzyRad: - { - // redundant to have level check here - if(newbon->AggroRange == -1 || effect_value < newbon->AggroRange) - { - newbon->AggroRange = effect_value; - } - break; - } - - case SE_Harmony: - { - // neotokyo: Harmony effect as buff - kinda tricky - // harmony could stack with a lull spell, which has better aggro range - // take the one with less range in any case - if(newbon->AssistRange == -1 || effect_value < newbon->AssistRange) - { - newbon->AssistRange = effect_value; - } - break; - } - - case SE_AttackSpeed: - { - if ((effect_value - 100) > 0) { // Haste - if (newbon->haste < 0) break; // Slowed - Don't apply haste - if ((effect_value - 100) > newbon->haste) { - newbon->haste = effect_value - 100; - } - } - else if ((effect_value - 100) < 0) { // Slow - int real_slow_value = (100 - effect_value) * -1; - real_slow_value -= ((real_slow_value * GetSlowMitigation()/100)); - if (real_slow_value < newbon->haste) - newbon->haste = real_slow_value; - } - break; - } - - case SE_AttackSpeed2: - { - if ((effect_value - 100) > 0) { // Haste V2 - Stacks with V1 but does not Overcap - if (newbon->hastetype2 < 0) break; //Slowed - Don't apply haste2 - if ((effect_value - 100) > newbon->hastetype2) { - newbon->hastetype2 = effect_value - 100; - } - } - else if ((effect_value - 100) < 0) { // Slow - int real_slow_value = (100 - effect_value) * -1; - real_slow_value -= ((real_slow_value * GetSlowMitigation()/100)); - if (real_slow_value < newbon->hastetype2) - newbon->hastetype2 = real_slow_value; - } - break; - } - - case SE_AttackSpeed3: - { - if (effect_value < 0){ //Slow - effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value < newbon->hastetype3) - newbon->hastetype3 = effect_value; - } - - else if (effect_value > 0) { // Haste V3 - Stacks and Overcaps - if (effect_value > newbon->hastetype3) { - newbon->hastetype3 = effect_value; - } - } - break; - } - - case SE_AttackSpeed4: - { - if (effect_value < 0) //A few spells use negative values(Descriptions all indicate it should be a slow) - effect_value = effect_value * -1; - - if (effect_value > 0 && effect_value > newbon->inhibitmelee) { - effect_value -= ((effect_value * GetSlowMitigation()/100)); - if (effect_value > newbon->inhibitmelee) - newbon->inhibitmelee = effect_value; - } - - break; - } - - case SE_TotalHP: - { - newbon->HP += effect_value; - break; - } - - case SE_ManaRegen_v2: - case SE_CurrentMana: - { - newbon->ManaRegen += effect_value; - break; - } - - case SE_ManaPool: - { - newbon->Mana += effect_value; - break; - } - - case SE_Stamina: - { - newbon->EnduranceReduction += effect_value; - break; - } - - case SE_ACv2: - case SE_ArmorClass: - { - newbon->AC += effect_value; - break; - } - - case SE_ATK: - { - newbon->ATK += effect_value; - break; - } - - case SE_STR: - { - newbon->STR += effect_value; - break; - } - - case SE_DEX: - { - newbon->DEX += effect_value; - break; - } - - case SE_AGI: - { - newbon->AGI += effect_value; - break; - } - - case SE_STA: - { - newbon->STA += effect_value; - break; - } - - case SE_INT: - { - newbon->INT += effect_value; - break; - } - - case SE_WIS: - { - newbon->WIS += effect_value; - break; - } - - case SE_CHA: - { - if (spells[spell_id].base[i] != 0) { - newbon->CHA += effect_value; - } - break; - } - - case SE_AllStats: - { - newbon->STR += effect_value; - newbon->DEX += effect_value; - newbon->AGI += effect_value; - newbon->STA += effect_value; - newbon->INT += effect_value; - newbon->WIS += effect_value; - newbon->CHA += effect_value; - break; - } - - case SE_ResistFire: - { - newbon->FR += effect_value; - break; - } - - case SE_ResistCold: - { - newbon->CR += effect_value; - break; - } - - case SE_ResistPoison: - { - newbon->PR += effect_value; - break; - } - - case SE_ResistDisease: - { - newbon->DR += effect_value; - break; - } - - case SE_ResistMagic: - { - newbon->MR += effect_value; - break; - } - - case SE_ResistAll: - { - newbon->MR += effect_value; - newbon->DR += effect_value; - newbon->PR += effect_value; - newbon->CR += effect_value; - newbon->FR += effect_value; - break; - } - - case SE_ResistCorruption: - { - newbon->Corrup += effect_value; - break; - } - - case SE_RaiseStatCap: - { - switch(spells[spell_id].base2[i]) - { - //are these #define'd somewhere? - case 0: //str - newbon->STRCapMod += effect_value; - break; - case 1: //sta - newbon->STACapMod += effect_value; - break; - case 2: //agi - newbon->AGICapMod += effect_value; - break; - case 3: //dex - newbon->DEXCapMod += effect_value; - break; - case 4: //wis - newbon->WISCapMod += effect_value; - break; - case 5: //int - newbon->INTCapMod += effect_value; - break; - case 6: //cha - newbon->CHACapMod += effect_value; - break; - case 7: //mr - newbon->MRCapMod += effect_value; - break; - case 8: //cr - newbon->CRCapMod += effect_value; - break; - case 9: //fr - newbon->FRCapMod += effect_value; - break; - case 10: //pr - newbon->PRCapMod += effect_value; - break; - case 11: //dr - newbon->DRCapMod += effect_value; - break; - case 12: // corruption - newbon->CorrupCapMod += effect_value; - break; - } - break; - } - - case SE_CastingLevel2: - case SE_CastingLevel: // Brilliance of Ro - { - newbon->effective_casting_level += effect_value; - break; - } - - case SE_MovementSpeed: - newbon->movementspeed += effect_value; - break; - - case SE_SpellDamageShield: - newbon->SpellDamageShield += effect_value; - break; - - case SE_DamageShield: - { - newbon->DamageShield += effect_value; - newbon->DamageShieldSpellID = spell_id; - //When using npc_spells_effects MAX value can be set to determine DS Type - if (IsAISpellEffect && max) - newbon->DamageShieldType = GetDamageShieldType(spell_id, max); - else - newbon->DamageShieldType = GetDamageShieldType(spell_id); - - break; - } - - case SE_ReverseDS: - { - newbon->ReverseDamageShield += effect_value; - newbon->ReverseDamageShieldSpellID = spell_id; - - if (IsAISpellEffect && max) - newbon->ReverseDamageShieldType = GetDamageShieldType(spell_id, max); - else - newbon->ReverseDamageShieldType = GetDamageShieldType(spell_id); - break; - } - - case SE_Reflect: - newbon->reflect_chance += effect_value; - break; - - case SE_Amplification: - newbon->Amplification += effect_value; - break; - - case SE_ChangeAggro: - newbon->hatemod += effect_value; - break; - - case SE_MeleeMitigation: - //for some reason... this value is negative for increased mitigation - newbon->MeleeMitigation -= effect_value; - break; - - case SE_CriticalHitChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) { - if(base2 == -1) - newbon->CriticalHitChance[HIGHEST_SKILL+1] += effect_value; - else - newbon->CriticalHitChance[base2] += effect_value; - } - - else if(effect_value < 0) { - - if(base2 == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] > effect_value) - newbon->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; - else if(base2 != -1 && newbon->CriticalHitChance[base2] > effect_value) - newbon->CriticalHitChance[base2] = effect_value; - } - - - else if(base2 == -1 && newbon->CriticalHitChance[HIGHEST_SKILL+1] < effect_value) - newbon->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; - else if(base2 != -1 && newbon->CriticalHitChance[base2] < effect_value) - newbon->CriticalHitChance[base2] = effect_value; - - break; - } - - case SE_CrippBlowChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->CrippBlowChance += effect_value; - - else if((effect_value < 0) && (newbon->CrippBlowChance > effect_value)) - newbon->CrippBlowChance = effect_value; - - else if(newbon->CrippBlowChance < effect_value) - newbon->CrippBlowChance = effect_value; - - break; - } - - case SE_AvoidMeleeChance: - { - //multiplier is to be compatible with item effects, watching for overflow too - effect_value = effect_value<3000? effect_value * 10 : 30000; - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->AvoidMeleeChance += effect_value; - - else if((effect_value < 0) && (newbon->AvoidMeleeChance > effect_value)) - newbon->AvoidMeleeChance = effect_value; - - else if(newbon->AvoidMeleeChance < effect_value) - newbon->AvoidMeleeChance = effect_value; - break; - } - - case SE_RiposteChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->RiposteChance += effect_value; - - else if((effect_value < 0) && (newbon->RiposteChance > effect_value)) - newbon->RiposteChance = effect_value; - - else if(newbon->RiposteChance < effect_value) - newbon->RiposteChance = effect_value; - break; - } - - case SE_DodgeChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->DodgeChance += effect_value; - - else if((effect_value < 0) && (newbon->DodgeChance > effect_value)) - newbon->DodgeChance = effect_value; - - if(newbon->DodgeChance < effect_value) - newbon->DodgeChance = effect_value; - break; - } - - case SE_ParryChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->ParryChance += effect_value; - - else if((effect_value < 0) && (newbon->ParryChance > effect_value)) - newbon->ParryChance = effect_value; - - if(newbon->ParryChance < effect_value) - newbon->ParryChance = effect_value; - break; - } - - case SE_DualWieldChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->DualWieldChance += effect_value; - - else if((effect_value < 0) && (newbon->DualWieldChance > effect_value)) - newbon->DualWieldChance = effect_value; - - if(newbon->DualWieldChance < effect_value) - newbon->DualWieldChance = effect_value; - break; - } - - case SE_DoubleAttackChance: - { - - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->DoubleAttackChance += effect_value; - - else if((effect_value < 0) && (newbon->DoubleAttackChance > effect_value)) - newbon->DoubleAttackChance = effect_value; - - if(newbon->DoubleAttackChance < effect_value) - newbon->DoubleAttackChance = effect_value; - break; - } - - case SE_TripleAttackChance: - { - - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->TripleAttackChance += effect_value; - - else if((effect_value < 0) && (newbon->TripleAttackChance > effect_value)) - newbon->TripleAttackChance = effect_value; - - if(newbon->TripleAttackChance < effect_value) - newbon->TripleAttackChance = effect_value; - break; - } - - case SE_MeleeLifetap: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->MeleeLifetap += spells[spell_id].base[i]; - - else if((effect_value < 0) && (newbon->MeleeLifetap > effect_value)) - newbon->MeleeLifetap = effect_value; - - else if(newbon->MeleeLifetap < effect_value) - newbon->MeleeLifetap = effect_value; - break; - } - - case SE_Vampirism: - newbon->Vampirism += effect_value; - break; - - case SE_AllInstrumentMod: - { - if(effect_value > newbon->singingMod) - newbon->singingMod = effect_value; - if(effect_value > newbon->brassMod) - newbon->brassMod = effect_value; - if(effect_value > newbon->percussionMod) - newbon->percussionMod = effect_value; - if(effect_value > newbon->windMod) - newbon->windMod = effect_value; - if(effect_value > newbon->stringedMod) - newbon->stringedMod = effect_value; - break; - } - - case SE_ResistSpellChance: - newbon->ResistSpellChance += effect_value; - break; - - case SE_ResistFearChance: - { - if(effect_value == 100) // If we reach 100% in a single spell/item then we should be immune to negative fear resist effects until our immunity is over - newbon->Fearless = true; - - newbon->ResistFearChance += effect_value; // these should stack - break; - } - - case SE_Fearless: - newbon->Fearless = true; - break; - - case SE_HundredHands: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->HundredHands += effect_value; - - if (effect_value > 0 && effect_value > newbon->HundredHands) - newbon->HundredHands = effect_value; //Increase Weapon Delay - else if (effect_value < 0 && effect_value < newbon->HundredHands) - newbon->HundredHands = effect_value; //Decrease Weapon Delay - break; - } - - case SE_MeleeSkillCheck: - { - if(newbon->MeleeSkillCheck < effect_value) { - newbon->MeleeSkillCheck = effect_value; - newbon->MeleeSkillCheckSkill = base2==-1?255:base2; - } - break; - } - - case SE_HitChance: - { - - if (RuleB(Spells, AdditiveBonusValues) && item_bonus){ - if(base2 == -1) - newbon->HitChanceEffect[HIGHEST_SKILL+1] += effect_value; - else - newbon->HitChanceEffect[base2] += effect_value; - } - - else if(base2 == -1){ - - if ((effect_value < 0) && (newbon->HitChanceEffect[HIGHEST_SKILL+1] > effect_value)) - newbon->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; - - else if (!newbon->HitChanceEffect[HIGHEST_SKILL+1] || - ((newbon->HitChanceEffect[HIGHEST_SKILL+1] > 0) && (newbon->HitChanceEffect[HIGHEST_SKILL+1] < effect_value))) - newbon->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; - } - - else { - - if ((effect_value < 0) && (newbon->HitChanceEffect[base2] > effect_value)) - newbon->HitChanceEffect[base2] = effect_value; - - else if (!newbon->HitChanceEffect[base2] || - ((newbon->HitChanceEffect[base2] > 0) && (newbon->HitChanceEffect[base2] < effect_value))) - newbon->HitChanceEffect[base2] = effect_value; - } - - break; - - } - - case SE_DamageModifier: - { - if(base2 == -1) - newbon->DamageModifier[HIGHEST_SKILL+1] += effect_value; - else - newbon->DamageModifier[base2] += effect_value; - break; - } - - case SE_DamageModifier2: - { - if(base2 == -1) - newbon->DamageModifier2[HIGHEST_SKILL+1] += effect_value; - else - newbon->DamageModifier2[base2] += effect_value; - break; - } - - case SE_MinDamageModifier: - { - if(base2 == -1) - newbon->MinDamageModifier[HIGHEST_SKILL+1] += effect_value; - else - newbon->MinDamageModifier[base2] += effect_value; - break; - } - - case SE_StunResist: - { - if(newbon->StunResist < effect_value) - newbon->StunResist = effect_value; - break; - } - - case SE_ProcChance: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) - newbon->ProcChanceSPA += effect_value; - - else if((effect_value < 0) && (newbon->ProcChanceSPA > effect_value)) - newbon->ProcChanceSPA = effect_value; - - if(newbon->ProcChanceSPA < effect_value) - newbon->ProcChanceSPA = effect_value; - - break; - } - - case SE_ExtraAttackChance: - newbon->ExtraAttackChance += effect_value; - break; - - case SE_PercentXPIncrease: - { - if(newbon->XPRateMod < effect_value) - newbon->XPRateMod = effect_value; - break; - } - - case SE_DeathSave: - { - if(newbon->DeathSave[0] < effect_value) - { - newbon->DeathSave[0] = effect_value; //1='Partial' 2='Full' - newbon->DeathSave[1] = buffslot; - //These are used in later expansion spell effects. - newbon->DeathSave[2] = base2;//Min level for HealAmt - newbon->DeathSave[3] = max;//HealAmt - } - break; - } - - case SE_DivineSave: - { - if (RuleB(Spells, AdditiveBonusValues) && item_bonus) { - newbon->DivineSaveChance[0] += effect_value; - newbon->DivineSaveChance[1] = 0; - } - - else if(newbon->DivineSaveChance[0] < effect_value) - { - newbon->DivineSaveChance[0] = effect_value; - newbon->DivineSaveChance[1] = base2; - //SetDeathSaveChance(true); - } - break; - } - - case SE_Flurry: - newbon->FlurryChance += effect_value; - break; - - case SE_Accuracy: - { - if ((effect_value < 0) && (newbon->Accuracy[HIGHEST_SKILL+1] > effect_value)) - newbon->Accuracy[HIGHEST_SKILL+1] = effect_value; - - else if (!newbon->Accuracy[HIGHEST_SKILL+1] || - ((newbon->Accuracy[HIGHEST_SKILL+1] > 0) && (newbon->Accuracy[HIGHEST_SKILL+1] < effect_value))) - newbon->Accuracy[HIGHEST_SKILL+1] = effect_value; - break; - } - - case SE_MaxHPChange: - newbon->MaxHPChange += effect_value; - break; - - case SE_EndurancePool: - newbon->Endurance += effect_value; - break; - - case SE_HealRate: - newbon->HealRate += effect_value; - break; - - case SE_SkillDamageTaken: - { - //When using npc_spells_effects if MAX value set, use stackable quest based modifier. - if (IsAISpellEffect && max){ - if(base2 == -1) - SkillDmgTaken_Mod[HIGHEST_SKILL+1] = effect_value; - else - SkillDmgTaken_Mod[base2] = effect_value; - } - else { - - if(base2 == -1) - newbon->SkillDmgTaken[HIGHEST_SKILL+1] += effect_value; - else - newbon->SkillDmgTaken[base2] += effect_value; - - } - break; - } - - case SE_TriggerOnCast: - { - for(int e = 0; e < MAX_SPELL_TRIGGER; e++) - { - if(!newbon->SpellTriggers[e]) - { - newbon->SpellTriggers[e] = spell_id; - break; - } - } - break; - } - - case SE_SpellCritChance: - newbon->CriticalSpellChance += effect_value; - break; - - case SE_CriticalSpellChance: - { - newbon->CriticalSpellChance += effect_value; - - if (base2 > newbon->SpellCritDmgIncNoStack) - newbon->SpellCritDmgIncNoStack = base2; - break; - } - - case SE_SpellCritDmgIncrease: - newbon->SpellCritDmgIncrease += effect_value; - break; - - case SE_DotCritDmgIncrease: - newbon->DotCritDmgIncrease += effect_value; - break; - - case SE_CriticalHealChance: - newbon->CriticalHealChance += effect_value; - break; - - case SE_CriticalHealOverTime: - newbon->CriticalHealOverTime += effect_value; - break; - - case SE_CriticalHealDecay: - newbon->CriticalHealDecay = true; - break; - - case SE_CriticalRegenDecay: - newbon->CriticalRegenDecay = true; - break; - - case SE_CriticalDotDecay: - newbon->CriticalDotDecay = true; - break; - - case SE_MitigateDamageShield: - { - if (effect_value < 0) - effect_value = effect_value*-1; - - newbon->DSMitigationOffHand += effect_value; - break; - } - - case SE_CriticalDoTChance: - newbon->CriticalDoTChance += effect_value; - break; - - case SE_ProcOnKillShot: - { - for(int e = 0; e < MAX_SPELL_TRIGGER*3; e+=3) - { - if(!newbon->SpellOnKill[e]) - { - // Base2 = Spell to fire | Base1 = % chance | Base3 = min level - newbon->SpellOnKill[e] = base2; - newbon->SpellOnKill[e+1] = effect_value; - newbon->SpellOnKill[e+2] = max; - break; - } - } - break; - } - - case SE_SpellOnDeath: - { - for(int e = 0; e < MAX_SPELL_TRIGGER; e+=2) - { - if(!newbon->SpellOnDeath[e]) - { - // Base2 = Spell to fire | Base1 = % chance - newbon->SpellOnDeath[e] = base2; - newbon->SpellOnDeath[e+1] = effect_value; - break; - } - } - break; - } - - case SE_CriticalDamageMob: - { - if(base2 == -1) - newbon->CritDmgMob[HIGHEST_SKILL+1] += effect_value; - else - newbon->CritDmgMob[base2] += effect_value; - break; - } - - case SE_ReduceSkillTimer: - { - if(newbon->SkillReuseTime[base2] < effect_value) - newbon->SkillReuseTime[base2] = effect_value; - break; - } - - case SE_SkillDamageAmount: - { - if(base2 == -1) - newbon->SkillDamageAmount[HIGHEST_SKILL+1] += effect_value; - else - newbon->SkillDamageAmount[base2] += effect_value; - break; - } - - case SE_GravityEffect: - newbon->GravityEffect = 1; - break; - - case SE_AntiGate: - newbon->AntiGate = true; - break; - - case SE_MagicWeapon: - newbon->MagicWeapon = true; - break; - - case SE_IncreaseBlockChance: - newbon->IncreaseBlockChance += effect_value; - break; - - case SE_PersistantCasting: - newbon->PersistantCasting += effect_value; - break; - - case SE_LimitHPPercent: - { - if(newbon->HPPercCap[0] != 0 && newbon->HPPercCap[0] > effect_value){ - newbon->HPPercCap[0] = effect_value; - newbon->HPPercCap[1] = base2; - } - else if(newbon->HPPercCap[0] == 0){ - newbon->HPPercCap[0] = effect_value; - newbon->HPPercCap[1] = base2; - } - break; - } - case SE_LimitManaPercent: - { - if(newbon->ManaPercCap[0] != 0 && newbon->ManaPercCap[0] > effect_value){ - newbon->ManaPercCap[0] = effect_value; - newbon->ManaPercCap[1] = base2; - } - else if(newbon->ManaPercCap[0] == 0) { - newbon->ManaPercCap[0] = effect_value; - newbon->ManaPercCap[1] = base2; - } - - break; - } - case SE_LimitEndPercent: - { - if(newbon->EndPercCap[0] != 0 && newbon->EndPercCap[0] > effect_value) { - newbon->EndPercCap[0] = effect_value; - newbon->EndPercCap[1] = base2; - } - - else if(newbon->EndPercCap[0] == 0){ - newbon->EndPercCap[0] = effect_value; - newbon->EndPercCap[1] = base2; - } - - break; - } - - case SE_BlockNextSpellFocus: - newbon->BlockNextSpell = true; - break; - - case SE_NegateSpellEffect: - newbon->NegateEffects = true; - break; - - case SE_ImmuneFleeing: - newbon->ImmuneToFlee = true; - break; - - case SE_DelayDeath: - newbon->DelayDeath += effect_value; - break; - - case SE_SpellProcChance: - newbon->SpellProcChance += effect_value; - break; - - case SE_CharmBreakChance: - newbon->CharmBreakChance += effect_value; - break; - - case SE_BardSongRange: - newbon->SongRange += effect_value; - break; - - case SE_HPToMana: - { - //Lower the ratio the more favorable - if((!newbon->HPToManaConvert) || (newbon->HPToManaConvert >= effect_value)) - newbon->HPToManaConvert = spells[spell_id].base[i]; - break; - } - - case SE_SkillDamageAmount2: - { - if(base2 == -1) - newbon->SkillDamageAmount2[HIGHEST_SKILL+1] += effect_value; - else - newbon->SkillDamageAmount2[base2] += effect_value; - break; - } - - case SE_NegateAttacks: - { - if (!newbon->NegateAttacks[0] || - ((newbon->NegateAttacks[0] && newbon->NegateAttacks[2]) && (newbon->NegateAttacks[2] < max))){ - newbon->NegateAttacks[0] = 1; - newbon->NegateAttacks[1] = buffslot; - newbon->NegateAttacks[2] = max; - } - break; - } - - case SE_MitigateMeleeDamage: - { - if (newbon->MitigateMeleeRune[0] < effect_value){ - newbon->MitigateMeleeRune[0] = effect_value; - newbon->MitigateMeleeRune[1] = buffslot; - newbon->MitigateMeleeRune[2] = base2; - newbon->MitigateMeleeRune[3] = max; - } - break; - } - - - case SE_MeleeThresholdGuard: - { - if (newbon->MeleeThresholdGuard[0] < effect_value){ - newbon->MeleeThresholdGuard[0] = effect_value; - newbon->MeleeThresholdGuard[1] = buffslot; - newbon->MeleeThresholdGuard[2] = base2; - } - break; - } - - case SE_SpellThresholdGuard: - { - if (newbon->SpellThresholdGuard[0] < effect_value){ - newbon->SpellThresholdGuard[0] = effect_value; - newbon->SpellThresholdGuard[1] = buffslot; - newbon->SpellThresholdGuard[2] = base2; - } - break; - } - - case SE_MitigateSpellDamage: - { - if (newbon->MitigateSpellRune[0] < effect_value){ - newbon->MitigateSpellRune[0] = effect_value; - newbon->MitigateSpellRune[1] = buffslot; - newbon->MitigateSpellRune[2] = base2; - newbon->MitigateSpellRune[3] = max; - } - break; - } - - case SE_MitigateDotDamage: - { - if (newbon->MitigateDotRune[0] < effect_value){ - newbon->MitigateDotRune[0] = effect_value; - newbon->MitigateDotRune[1] = buffslot; - newbon->MitigateDotRune[2] = base2; - newbon->MitigateDotRune[3] = max; - } - break; - } - - case SE_ManaAbsorbPercentDamage: - { - if (newbon->ManaAbsorbPercentDamage[0] < effect_value){ - newbon->ManaAbsorbPercentDamage[0] = effect_value; - newbon->ManaAbsorbPercentDamage[1] = buffslot; - } - break; - } - - case SE_TriggerMeleeThreshold: - { - if (newbon->TriggerMeleeThreshold[2] < base2){ - newbon->TriggerMeleeThreshold[0] = effect_value; - newbon->TriggerMeleeThreshold[1] = buffslot; - newbon->TriggerMeleeThreshold[2] = base2; - } - break; - } - - case SE_TriggerSpellThreshold: - { - if (newbon->TriggerSpellThreshold[2] < base2){ - newbon->TriggerSpellThreshold[0] = effect_value; - newbon->TriggerSpellThreshold[1] = buffslot; - newbon->TriggerSpellThreshold[2] = base2; - } - break; - } - - case SE_ShieldBlock: - newbon->ShieldBlock += effect_value; - break; - - case SE_ShieldEquipHateMod: - newbon->ShieldEquipHateMod += effect_value; - break; - - case SE_ShieldEquipDmgMod: - newbon->ShieldEquipDmgMod[0] += effect_value; - newbon->ShieldEquipDmgMod[1] += base2; - break; - - case SE_BlockBehind: - newbon->BlockBehind += effect_value; - break; - - case SE_Fear: - newbon->IsFeared = true; - break; - - //AA bonuses - implemented broadly into spell/item effects - case SE_FrontalStunResist: - newbon->FrontalStunResist += effect_value; - break; - - case SE_ImprovedBindWound: - newbon->BindWound += effect_value; - break; - - case SE_MaxBindWound: - newbon->MaxBindWound += effect_value; - break; - - case SE_BaseMovementSpeed: - newbon->BaseMovementSpeed += effect_value; - break; - - case SE_IncreaseRunSpeedCap: - newbon->IncreaseRunSpeedCap += effect_value; - break; - - case SE_DoubleSpecialAttack: - newbon->DoubleSpecialAttack += effect_value; - break; - - case SE_TripleBackstab: - newbon->TripleBackstab += effect_value; - break; - - case SE_FrontalBackstabMinDmg: - newbon->FrontalBackstabMinDmg = true; - break; - - case SE_FrontalBackstabChance: - newbon->FrontalBackstabChance += effect_value; - break; - - case SE_ConsumeProjectile: - newbon->ConsumeProjectile += effect_value; - break; - - case SE_ForageAdditionalItems: - newbon->ForageAdditionalItems += effect_value; - break; - - case SE_Salvage: - newbon->SalvageChance += effect_value; - break; - - case SE_ArcheryDamageModifier: - newbon->ArcheryDamageModifier += effect_value; - break; - - case SE_DoubleRangedAttack: - newbon->DoubleRangedAttack += effect_value; - break; - - case SE_SecondaryDmgInc: - newbon->SecondaryDmgInc = true; - break; - - case SE_StrikeThrough: - case SE_StrikeThrough2: - newbon->StrikeThrough += effect_value; - break; - - case SE_GiveDoubleAttack: - newbon->GiveDoubleAttack += effect_value; - break; - - case SE_PetCriticalHit: - newbon->PetCriticalHit += effect_value; - break; - - case SE_CombatStability: - newbon->CombatStability += effect_value; - break; - - case SE_AddSingingMod: - switch (base2) - { - case ItemTypeWindInstrument: - newbon->windMod += effect_value; - break; - case ItemTypeStringedInstrument: - newbon->stringedMod += effect_value; - break; - case ItemTypeBrassInstrument: - newbon->brassMod += effect_value; - break; - case ItemTypePercussionInstrument: - newbon->percussionMod += effect_value; - break; - case ItemTypeSinging: - newbon->singingMod += effect_value; - break; - } - break; - - case SE_SongModCap: - newbon->songModCap += effect_value; - break; - - case SE_PetAvoidance: - newbon->PetAvoidance += effect_value; - break; - - case SE_Ambidexterity: - newbon->Ambidexterity += effect_value; - break; - - case SE_PetMaxHP: - newbon->PetMaxHP += effect_value; - break; - - case SE_PetFlurry: - newbon->PetFlurry += effect_value; - break; - - case SE_GivePetGroupTarget: - newbon->GivePetGroupTarget = true; - break; - - case SE_RootBreakChance: - newbon->RootBreakChance += effect_value; - break; - - case SE_ChannelChanceItems: - newbon->ChannelChanceItems += effect_value; - break; - - case SE_ChannelChanceSpells: - newbon->ChannelChanceSpells += effect_value; - break; - - case SE_UnfailingDivinity: - newbon->UnfailingDivinity += effect_value; - break; - - - case SE_ItemHPRegenCapIncrease: - newbon->ItemHPRegenCap += effect_value; - break; - - case SE_OffhandRiposteFail: - newbon->OffhandRiposteFail += effect_value; - break; - - case SE_ItemAttackCapIncrease: - newbon->ItemATKCap += effect_value; - break; - - case SE_TwoHandBluntBlock: - newbon->TwoHandBluntBlock += effect_value; - break; - - case SE_StunBashChance: - newbon->StunBashChance += effect_value; - break; - - case SE_IncreaseChanceMemwipe: - newbon->IncreaseChanceMemwipe += effect_value; - break; - - case SE_CriticalMend: - newbon->CriticalMend += effect_value; - break; - - case SE_SpellEffectResistChance: - { - for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) - { - if(newbon->SEResist[e+1] && (newbon->SEResist[e] == base2) && (newbon->SEResist[e+1] < effect_value)){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = effect_value; //Resist Chance - break; - } - else if (!newbon->SEResist[e+1]){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = effect_value; //Resist Chance - break; - } - } - break; - } - - case SE_MasteryofPast: - { - if(newbon->MasteryofPast < effect_value) - newbon->MasteryofPast = effect_value; - break; - } - - case SE_DoubleRiposte: - { - newbon->DoubleRiposte += effect_value; - } - - case SE_GiveDoubleRiposte: - { - //Only allow for regular double riposte chance. - if(newbon->GiveDoubleRiposte[base2] == 0){ - if(newbon->GiveDoubleRiposte[0] < effect_value) - newbon->GiveDoubleRiposte[0] = effect_value; - } - break; - } - - case SE_SlayUndead: - { - if(newbon->SlayUndead[1] < effect_value) - newbon->SlayUndead[0] = effect_value; // Rate - newbon->SlayUndead[1] = base2; // Damage Modifier - break; - } - - case SE_TriggerOnReqTarget: - case SE_TriggerOnReqCaster: - newbon->TriggerOnValueAmount = true; - break; - - case SE_DivineAura: - newbon->DivineAura = true; - break; - - case SE_ImprovedTaunt: - if (newbon->ImprovedTaunt[0] < effect_value) { - newbon->ImprovedTaunt[0] = effect_value; - newbon->ImprovedTaunt[1] = base2; - newbon->ImprovedTaunt[2] = buffslot; - } - break; - - - case SE_DistanceRemoval: - newbon->DistanceRemoval = true; - break; - - case SE_FrenziedDevastation: - newbon->FrenziedDevastation += base2; - break; - - case SE_Root: - if (newbon->Root[0] && (newbon->Root[1] > buffslot)){ - newbon->Root[0] = 1; - newbon->Root[1] = buffslot; - } - else if (!newbon->Root[0]){ - newbon->Root[0] = 1; - newbon->Root[1] = buffslot; - } - break; - - case SE_Rune: - - if (newbon->MeleeRune[0] && (newbon->MeleeRune[1] > buffslot)){ - - newbon->MeleeRune[0] = effect_value; - newbon->MeleeRune[1] = buffslot; - } - else if (!newbon->MeleeRune[0]){ - newbon->MeleeRune[0] = effect_value; - newbon->MeleeRune[1] = buffslot; - } - - break; - - case SE_AbsorbMagicAtt: - if (newbon->AbsorbMagicAtt[0] && (newbon->AbsorbMagicAtt[1] > buffslot)){ - newbon->AbsorbMagicAtt[0] = effect_value; - newbon->AbsorbMagicAtt[1] = buffslot; - } - else if (!newbon->AbsorbMagicAtt[0]){ - newbon->AbsorbMagicAtt[0] = effect_value; - newbon->AbsorbMagicAtt[1] = buffslot; - } - break; - - case SE_NegateIfCombat: - newbon->NegateIfCombat = true; - break; - - case SE_Screech: - newbon->Screech = effect_value; - break; - - case SE_AlterNPCLevel: - - if (IsNPC()){ - if (!newbon->AlterNPCLevel - || ((effect_value < 0) && (newbon->AlterNPCLevel > effect_value)) - || ((effect_value > 0) && (newbon->AlterNPCLevel < effect_value))) { - - int16 tmp_lv = GetOrigLevel() + effect_value; - if (tmp_lv < 1) - tmp_lv = 1; - else if (tmp_lv > 255) - tmp_lv = 255; - if ((GetLevel() != tmp_lv)){ - newbon->AlterNPCLevel = effect_value; - SetLevel(tmp_lv); - } - } - } - break; - - case SE_AStacker: - newbon->AStacker[0] = 1; - newbon->AStacker[1] = effect_value; - break; - - case SE_BStacker: - newbon->BStacker[0] = 1; - newbon->BStacker[1] = effect_value; - break; - - case SE_CStacker: - newbon->CStacker[0] = 1; - newbon->CStacker[1] = effect_value; - break; - - case SE_DStacker: - newbon->DStacker[0] = 1; - newbon->DStacker[1] = effect_value; - break; - - case SE_Berserk: - newbon->BerserkSPA = true; - break; - - - case SE_Metabolism: - newbon->Metabolism += effect_value; - break; - - case SE_ImprovedReclaimEnergy: - { - if((effect_value < 0) && (newbon->ImprovedReclaimEnergy > effect_value)) - newbon->ImprovedReclaimEnergy = effect_value; - - else if(newbon->ImprovedReclaimEnergy < effect_value) - newbon->ImprovedReclaimEnergy = effect_value; - break; - } - - case SE_HeadShot: - { - if(newbon->HeadShot[1] < base2){ - newbon->HeadShot[0] = effect_value; - newbon->HeadShot[1] = base2; - } - break; - } - - case SE_HeadShotLevel: - { - if(newbon->HSLevel < effect_value) - newbon->HSLevel = effect_value; - break; - } - - case SE_Assassinate: - { - if(newbon->Assassinate[1] < base2){ - newbon->Assassinate[0] = effect_value; - newbon->Assassinate[1] = base2; - } - break; - } - - case SE_AssassinateLevel: - { - if(newbon->AssassinateLevel < effect_value) - newbon->AssassinateLevel = effect_value; - break; - } - - case SE_FinishingBlow: - { - //base1 = chance, base2 = damage - if (newbon->FinishingBlow[1] < base2){ - newbon->FinishingBlow[0] = effect_value; - newbon->FinishingBlow[1] = base2; - } - break; - } - - case SE_FinishingBlowLvl: - { - //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) - if (newbon->FinishingBlowLvl[0] < effect_value){ - newbon->FinishingBlowLvl[0] = effect_value; - newbon->FinishingBlowLvl[1] = base2; - } - break; - } - - case SE_PetMeleeMitigation: - newbon->PetMeleeMitigation += effect_value; - break; - - //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table - if (IsAISpellEffect) { - - //Non-Focused Effect to modify incomming spell damage by resist type. - case SE_FcSpellVulnerability: - ModVulnerability(base2, effect_value); - break; - } - } - } -} - -void NPC::CalcItemBonuses(StatBonuses *newbon) -{ - if(newbon){ - - for(int i = 0; i < MAX_WORN_INVENTORY; i++){ - const Item_Struct *cur = database.GetItem(equipment[i]); - if(cur){ - //basic stats - newbon->AC += cur->AC; - newbon->HP += cur->HP; - newbon->Mana += cur->Mana; - newbon->Endurance += cur->Endur; - newbon->STR += (cur->AStr + cur->HeroicStr); - newbon->STA += (cur->ASta + cur->HeroicSta); - newbon->DEX += (cur->ADex + cur->HeroicDex); - newbon->AGI += (cur->AAgi + cur->HeroicAgi); - newbon->INT += (cur->AInt + cur->HeroicInt); - newbon->WIS += (cur->AWis + cur->HeroicWis); - newbon->CHA += (cur->ACha + cur->HeroicCha); - newbon->MR += (cur->MR + cur->HeroicMR); - newbon->FR += (cur->FR + cur->HeroicFR); - newbon->CR += (cur->CR + cur->HeroicCR); - newbon->PR += (cur->PR + cur->HeroicPR); - newbon->DR += (cur->DR + cur->HeroicDR); - newbon->Corrup += (cur->SVCorruption + cur->HeroicSVCorrup); - - //more complex stats - if(cur->Regen > 0) { - newbon->HPRegen += cur->Regen; - } - if(cur->ManaRegen > 0) { - newbon->ManaRegen += cur->ManaRegen; - } - if(cur->Attack > 0) { - newbon->ATK += cur->Attack; - } - if(cur->DamageShield > 0) { - newbon->DamageShield += cur->DamageShield; - } - if(cur->SpellShield > 0) { - newbon->SpellDamageShield += cur->SpellShield; - } - if(cur->Shielding > 0) { - newbon->MeleeMitigation += cur->Shielding; - } - if(cur->StunResist > 0) { - newbon->StunResist += cur->StunResist; - } - if(cur->StrikeThrough > 0) { - newbon->StrikeThrough += cur->StrikeThrough; - } - if(cur->Avoidance > 0) { - newbon->AvoidMeleeChance += cur->Avoidance; - } - if(cur->Accuracy > 0) { - newbon->HitChance += cur->Accuracy; - } - if(cur->CombatEffects > 0) { - newbon->ProcChance += cur->CombatEffects; - } - if (cur->Worn.Effect>0 && (cur->Worn.Type == ET_WornEffect)) { // latent effects - ApplySpellsBonuses(cur->Worn.Effect, cur->Worn.Level, newbon); - } - if (cur->Haste > newbon->haste) - newbon->haste = cur->Haste; - } - } - - } -} - -void Client::CalcItemScale() -{ - bool changed = false; - - if(CalcItemScale(0, 21)) - changed = true; - - if(CalcItemScale(22, 30)) - changed = true; - - if(CalcItemScale(251, 341)) - changed = true; - - if(CalcItemScale(400, 405)) - changed = true; - - //Power Source Slot - if (GetClientVersion() >= EQClientSoF) - { - if(CalcItemScale(9999, 10000)) - changed = true; - } - - if(changed) - { - CalcBonuses(); - } -} - -bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) -{ - bool changed = false; - int i; - for (i = slot_x; i < slot_y; i++) { - ItemInst* inst = m_inv.GetItem(i); - if(inst == 0) - continue; - - bool update_slot = false; - if(inst->IsScaling()) - { - uint16 oldexp = inst->GetExp(); - parse->EventItem(EVENT_SCALE_CALC, this, inst, nullptr, "", 0); - - if (inst->GetExp() != oldexp) { // if the scaling factor changed, rescale the item and update the client - inst->ScaleItem(); - changed = true; - update_slot = true; - } - } - - //iterate all augments - for(int x = 0; x < MAX_AUGMENT_SLOTS; ++x) - { - ItemInst * a_inst = inst->GetAugment(x); - if(!a_inst) - continue; - - if(a_inst->IsScaling()) - { - uint16 oldexp = a_inst->GetExp(); - parse->EventItem(EVENT_SCALE_CALC, this, a_inst, nullptr, "", 0); - - if (a_inst->GetExp() != oldexp) - { - a_inst->ScaleItem(); - changed = true; - update_slot = true; - } - } - } - - if(update_slot) - { - SendItemPacket(i, inst, ItemPacketCharmUpdate); - } - } - return changed; -} - -void Client::DoItemEnterZone() { - bool changed = false; - - if(DoItemEnterZone(0, 21)) - changed = true; - - if(DoItemEnterZone(22, 30)) - changed = true; - - if(DoItemEnterZone(251, 341)) - changed = true; - - if(DoItemEnterZone(400, 405)) - changed = true; - - //Power Source Slot - if (GetClientVersion() >= EQClientSoF) - { - if(DoItemEnterZone(9999, 10000)) - changed = true; - } - - if(changed) - { - CalcBonuses(); - } -} - -bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { - bool changed = false; - for(int i = slot_x; i < slot_y; i++) { - ItemInst* inst = m_inv.GetItem(i); - if(!inst) - continue; - - bool update_slot = false; - if(inst->IsScaling()) - { - uint16 oldexp = inst->GetExp(); - - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); - if(i < 22 || i == 9999) { - parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); - } - - if (inst->GetExp() != oldexp) { // if the scaling factor changed, rescale the item and update the client - inst->ScaleItem(); - changed = true; - update_slot = true; - } - } else { - if(i < 22 || i == 9999) { - parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); - } - - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); - } - - //iterate all augments - for(int x = 0; x < MAX_AUGMENT_SLOTS; ++x) - { - ItemInst *a_inst = inst->GetAugment(x); - if(!a_inst) - continue; - - if(a_inst->IsScaling()) - { - uint16 oldexp = a_inst->GetExp(); - - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, a_inst, nullptr, "", 0); - - if (a_inst->GetExp() != oldexp) - { - a_inst->ScaleItem(); - changed = true; - update_slot = true; - } - } else { - parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, a_inst, nullptr, "", 0); - } - } - - if(update_slot) - { - SendItemPacket(i, inst, ItemPacketCharmUpdate); - } - } - return changed; -} - -uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_effect) -{ - uint16 effect = 0; - - if (!AA) - effect = spells[spell_id].effectid[effect_index]; - else - effect = aa_effect; - - switch (effect) - { - case SE_ImprovedDamage: - return focusImprovedDamage; - case SE_ImprovedHeal: - return focusImprovedHeal; - case SE_ReduceManaCost: - return focusManaCost; - case SE_IncreaseSpellHaste: - return focusSpellHaste; - case SE_IncreaseSpellDuration: - return focusSpellDuration; - case SE_SpellDurationIncByTic: - return focusSpellDurByTic; - case SE_SwarmPetDuration: - return focusSwarmPetDuration; - case SE_IncreaseRange: - return focusRange; - case SE_ReduceReagentCost: - return focusReagentCost; - case SE_PetPowerIncrease: - return focusPetPower; - case SE_SpellResistReduction: - return focusResistRate; - case SE_SpellHateMod: - return focusSpellHateMod; - case SE_ReduceReuseTimer: - return focusReduceRecastTime; - case SE_TriggerOnCast: - //return focusTriggerOnCast; - return 0; //This is calculated as an actual bonus - case SE_FcSpellVulnerability: - return focusSpellVulnerability; - case SE_BlockNextSpellFocus: - //return focusBlockNextSpell; - return 0; //This is calculated as an actual bonus - case SE_FcTwincast: - return focusTwincast; - case SE_SympatheticProc: - return focusSympatheticProc; - case SE_FcDamageAmt: - return focusFcDamageAmt; - case SE_FcDamageAmtCrit: - return focusFcDamageAmtCrit; - case SE_FcDamagePctCrit: - return focusFcDamagePctCrit; - case SE_FcDamageAmtIncoming: - return focusFcDamageAmtIncoming; - case SE_FcHealAmtIncoming: - return focusFcHealAmtIncoming; - case SE_FcHealPctIncoming: - return focusFcHealPctIncoming; - case SE_FcBaseEffects: - return focusFcBaseEffects; - case SE_FcIncreaseNumHits: - return focusIncreaseNumHits; - case SE_FcLimitUse: - return focusFcLimitUse; - case SE_FcMute: - return focusFcMute; - case SE_FcTimerRefresh: - return focusFcTimerRefresh; - case SE_FcStunTimeMod: - return focusFcStunTimeMod; - case SE_FcHealPctCritIncoming: - return focusFcHealPctCritIncoming; - case SE_FcHealAmt: - return focusFcHealAmt; - case SE_FcHealAmtCrit: - return focusFcHealAmtCrit; - } - return 0; -} - -void Mob::NegateSpellsBonuses(uint16 spell_id) -{ - if(!IsValidSpell(spell_id)) - return; - - int effect_value = 0; - - for (int i = 0; i < EFFECT_COUNT; i++) - { - if (spells[spell_id].effectid[i] == SE_NegateSpellEffect){ - - //Negate focus effects - for(int e = 0; e < HIGHEST_FOCUS+1; e++) - { - if (spellbonuses.FocusEffects[e] == spells[spell_id].base2[i]) - { - spellbonuses.FocusEffects[e] = effect_value; - continue; - } - } - - //Negate bonuses - switch (spells[spell_id].base2[i]) - { - case SE_CurrentHP: - if(spells[spell_id].base[i] == 1) { - spellbonuses.HPRegen = effect_value; - aabonuses.HPRegen = effect_value; - itembonuses.HPRegen = effect_value; - } - break; - - case SE_CurrentEndurance: - spellbonuses.EnduranceRegen = effect_value; - aabonuses.EnduranceRegen = effect_value; - itembonuses.EnduranceRegen = effect_value; - break; - - case SE_ChangeFrenzyRad: - spellbonuses.AggroRange = effect_value; - aabonuses.AggroRange = effect_value; - itembonuses.AggroRange = effect_value; - break; - - case SE_Harmony: - spellbonuses.AssistRange = effect_value; - aabonuses.AssistRange = effect_value; - itembonuses.AssistRange = effect_value; - break; - - case SE_AttackSpeed: - spellbonuses.haste = effect_value; - aabonuses.haste = effect_value; - itembonuses.haste = effect_value; - break; - - case SE_AttackSpeed2: - spellbonuses.hastetype2 = effect_value; - aabonuses.hastetype2 = effect_value; - itembonuses.hastetype2 = effect_value; - break; - - case SE_AttackSpeed3: - { - if (effect_value > 0) { - spellbonuses.hastetype3 = effect_value; - aabonuses.hastetype3 = effect_value; - itembonuses.hastetype3 = effect_value; - - } - break; - } - - case SE_AttackSpeed4: - spellbonuses.inhibitmelee = effect_value; - aabonuses.inhibitmelee = effect_value; - itembonuses.inhibitmelee = effect_value; - break; - - case SE_TotalHP: - spellbonuses.HP = effect_value; - aabonuses.HP = effect_value; - itembonuses.HP = effect_value; - break; - - case SE_ManaRegen_v2: - case SE_CurrentMana: - spellbonuses.ManaRegen = effect_value; - aabonuses.ManaRegen = effect_value; - itembonuses.ManaRegen = effect_value; - break; - - case SE_ManaPool: - spellbonuses.Mana = effect_value; - itembonuses.Mana = effect_value; - aabonuses.Mana = effect_value; - break; - - case SE_Stamina: - spellbonuses.EnduranceReduction = effect_value; - itembonuses.EnduranceReduction = effect_value; - aabonuses.EnduranceReduction = effect_value; - break; - - case SE_ACv2: - case SE_ArmorClass: - spellbonuses.AC = effect_value; - aabonuses.AC = effect_value; - itembonuses.AC = effect_value; - break; - - case SE_ATK: - spellbonuses.ATK = effect_value; - aabonuses.ATK = effect_value; - itembonuses.ATK = effect_value; - break; - - case SE_STR: - spellbonuses.STR = effect_value; - itembonuses.STR = effect_value; - aabonuses.STR = effect_value; - break; - - case SE_DEX: - spellbonuses.DEX = effect_value; - aabonuses.DEX = effect_value; - itembonuses.DEX = effect_value; - break; - - case SE_AGI: - itembonuses.AGI = effect_value; - aabonuses.AGI = effect_value; - spellbonuses.AGI = effect_value; - break; - - case SE_STA: - spellbonuses.STA = effect_value; - itembonuses.STA = effect_value; - aabonuses.STA = effect_value; - break; - - case SE_INT: - spellbonuses.INT = effect_value; - aabonuses.INT = effect_value; - itembonuses.INT = effect_value; - break; - - case SE_WIS: - spellbonuses.WIS = effect_value; - aabonuses.WIS = effect_value; - itembonuses.WIS = effect_value; - break; - - case SE_CHA: - itembonuses.CHA = effect_value; - spellbonuses.CHA = effect_value; - aabonuses.CHA = effect_value; - break; - - case SE_AllStats: - { - spellbonuses.STR = effect_value; - spellbonuses.DEX = effect_value; - spellbonuses.AGI = effect_value; - spellbonuses.STA = effect_value; - spellbonuses.INT = effect_value; - spellbonuses.WIS = effect_value; - spellbonuses.CHA = effect_value; - - itembonuses.STR = effect_value; - itembonuses.DEX = effect_value; - itembonuses.AGI = effect_value; - itembonuses.STA = effect_value; - itembonuses.INT = effect_value; - itembonuses.WIS = effect_value; - itembonuses.CHA = effect_value; - - aabonuses.STR = effect_value; - aabonuses.DEX = effect_value; - aabonuses.AGI = effect_value; - aabonuses.STA = effect_value; - aabonuses.INT = effect_value; - aabonuses.WIS = effect_value; - aabonuses.CHA = effect_value; - break; - } - - case SE_ResistFire: - spellbonuses.FR = effect_value; - itembonuses.FR = effect_value; - aabonuses.FR = effect_value; - break; - - case SE_ResistCold: - spellbonuses.CR = effect_value; - aabonuses.CR = effect_value; - itembonuses.CR = effect_value; - break; - - case SE_ResistPoison: - spellbonuses.PR = effect_value; - aabonuses.PR = effect_value; - itembonuses.PR = effect_value; - break; - - case SE_ResistDisease: - spellbonuses.DR = effect_value; - itembonuses.DR = effect_value; - aabonuses.DR = effect_value; - break; - - case SE_ResistMagic: - spellbonuses.MR = effect_value; - aabonuses.MR = effect_value; - itembonuses.MR = effect_value; - break; - - case SE_ResistAll: - { - spellbonuses.MR = effect_value; - spellbonuses.DR = effect_value; - spellbonuses.PR = effect_value; - spellbonuses.CR = effect_value; - spellbonuses.FR = effect_value; - - aabonuses.MR = effect_value; - aabonuses.DR = effect_value; - aabonuses.PR = effect_value; - aabonuses.CR = effect_value; - aabonuses.FR = effect_value; - - itembonuses.MR = effect_value; - itembonuses.DR = effect_value; - itembonuses.PR = effect_value; - itembonuses.CR = effect_value; - itembonuses.FR = effect_value; - break; - } - - case SE_ResistCorruption: - spellbonuses.Corrup = effect_value; - itembonuses.Corrup = effect_value; - aabonuses.Corrup = effect_value; - break; - - case SE_CastingLevel2: - case SE_CastingLevel: // Brilliance of Ro - spellbonuses.effective_casting_level = effect_value; - aabonuses.effective_casting_level = effect_value; - itembonuses.effective_casting_level = effect_value; - break; - - - case SE_MovementSpeed: - spellbonuses.movementspeed = effect_value; - aabonuses.movementspeed = effect_value; - itembonuses.movementspeed = effect_value; - break; - - case SE_SpellDamageShield: - spellbonuses.SpellDamageShield = effect_value; - aabonuses.SpellDamageShield = effect_value; - itembonuses.SpellDamageShield = effect_value; - break; - - case SE_DamageShield: - spellbonuses.DamageShield = effect_value; - aabonuses.DamageShield = effect_value; - itembonuses.DamageShield = effect_value; - break; - - case SE_ReverseDS: - spellbonuses.ReverseDamageShield = effect_value; - aabonuses.ReverseDamageShield = effect_value; - itembonuses.ReverseDamageShield = effect_value; - break; - - case SE_Reflect: - spellbonuses.reflect_chance = effect_value; - aabonuses.reflect_chance = effect_value; - itembonuses.reflect_chance = effect_value; - break; - - case SE_Amplification: - spellbonuses.Amplification = effect_value; - itembonuses.Amplification = effect_value; - aabonuses.Amplification = effect_value; - break; - - case SE_ChangeAggro: - spellbonuses.hatemod = effect_value; - itembonuses.hatemod = effect_value; - aabonuses.hatemod = effect_value; - break; - - case SE_MeleeMitigation: - spellbonuses.MeleeMitigation = effect_value; - itembonuses.MeleeMitigation = effect_value; - aabonuses.MeleeMitigation = effect_value; - break; - - case SE_CriticalHitChance: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.CriticalHitChance[e] = effect_value; - aabonuses.CriticalHitChance[e] = effect_value; - itembonuses.CriticalHitChance[e] = effect_value; - } - } - - case SE_CrippBlowChance: - spellbonuses.CrippBlowChance = effect_value; - aabonuses.CrippBlowChance = effect_value; - itembonuses.CrippBlowChance = effect_value; - break; - - case SE_AvoidMeleeChance: - spellbonuses.AvoidMeleeChance = effect_value; - aabonuses.AvoidMeleeChance = effect_value; - itembonuses.AvoidMeleeChance = effect_value; - break; - - case SE_RiposteChance: - spellbonuses.RiposteChance = effect_value; - aabonuses.RiposteChance = effect_value; - itembonuses.RiposteChance = effect_value; - break; - - case SE_DodgeChance: - spellbonuses.DodgeChance = effect_value; - aabonuses.DodgeChance = effect_value; - itembonuses.DodgeChance = effect_value; - break; - - case SE_ParryChance: - spellbonuses.ParryChance = effect_value; - aabonuses.ParryChance = effect_value; - itembonuses.ParryChance = effect_value; - break; - - case SE_DualWieldChance: - spellbonuses.DualWieldChance = effect_value; - aabonuses.DualWieldChance = effect_value; - itembonuses.DualWieldChance = effect_value; - break; - - case SE_DoubleAttackChance: - spellbonuses.DoubleAttackChance = effect_value; - aabonuses.DoubleAttackChance = effect_value; - itembonuses.DoubleAttackChance = effect_value; - break; - - case SE_TripleAttackChance: - spellbonuses.TripleAttackChance = effect_value; - aabonuses.TripleAttackChance = effect_value; - itembonuses.TripleAttackChance = effect_value; - break; - - case SE_MeleeLifetap: - spellbonuses.MeleeLifetap = effect_value; - aabonuses.MeleeLifetap = effect_value; - itembonuses.MeleeLifetap = effect_value; - break; - - case SE_AllInstrumentMod: - { - spellbonuses.singingMod = effect_value; - spellbonuses.brassMod = effect_value; - spellbonuses.percussionMod = effect_value; - spellbonuses.windMod = effect_value; - spellbonuses.stringedMod = effect_value; - - itembonuses.singingMod = effect_value; - itembonuses.brassMod = effect_value; - itembonuses.percussionMod = effect_value; - itembonuses.windMod = effect_value; - itembonuses.stringedMod = effect_value; - - aabonuses.singingMod = effect_value; - aabonuses.brassMod = effect_value; - aabonuses.percussionMod = effect_value; - aabonuses.windMod = effect_value; - aabonuses.stringedMod = effect_value; - break; - } - - case SE_ResistSpellChance: - spellbonuses.ResistSpellChance = effect_value; - aabonuses.ResistSpellChance = effect_value; - itembonuses.ResistSpellChance = effect_value; - break; - - case SE_ResistFearChance: - spellbonuses.Fearless = false; - spellbonuses.ResistFearChance = effect_value; - aabonuses.ResistFearChance = effect_value; - itembonuses.ResistFearChance = effect_value; - break; - - case SE_Fearless: - spellbonuses.Fearless = false; - aabonuses.Fearless = false; - itembonuses.Fearless = false; - break; - - case SE_HundredHands: - spellbonuses.HundredHands = effect_value; - aabonuses.HundredHands = effect_value; - itembonuses.HundredHands = effect_value; - break; - - case SE_MeleeSkillCheck: - { - spellbonuses.MeleeSkillCheck = effect_value; - spellbonuses.MeleeSkillCheckSkill = effect_value; - break; - } - - case SE_HitChance: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.HitChanceEffect[e] = effect_value; - aabonuses.HitChanceEffect[e] = effect_value; - itembonuses.HitChanceEffect[e] = effect_value; - } - break; - } - - case SE_DamageModifier: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.DamageModifier[e] = effect_value; - aabonuses.DamageModifier[e] = effect_value; - itembonuses.DamageModifier[e] = effect_value; - } - break; - } - - case SE_DamageModifier2: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.DamageModifier2[e] = effect_value; - aabonuses.DamageModifier2[e] = effect_value; - itembonuses.DamageModifier2[e] = effect_value; - } - break; - } - - case SE_MinDamageModifier: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.MinDamageModifier[e] = effect_value; - aabonuses.MinDamageModifier[e] = effect_value; - itembonuses.MinDamageModifier[e] = effect_value; - } - break; - } - - case SE_StunResist: - spellbonuses.StunResist = effect_value; - aabonuses.StunResist = effect_value; - itembonuses.StunResist = effect_value; - break; - - case SE_ProcChance: - spellbonuses.ProcChanceSPA = effect_value; - aabonuses.ProcChanceSPA = effect_value; - itembonuses.ProcChanceSPA = effect_value; - break; - - case SE_ExtraAttackChance: - spellbonuses.ExtraAttackChance = effect_value; - aabonuses.ExtraAttackChance = effect_value; - itembonuses.ExtraAttackChance = effect_value; - break; - - case SE_PercentXPIncrease: - spellbonuses.XPRateMod = effect_value; - aabonuses.XPRateMod = effect_value; - itembonuses.XPRateMod = effect_value; - break; - - case SE_Flurry: - spellbonuses.FlurryChance = effect_value; - aabonuses.FlurryChance = effect_value; - itembonuses.FlurryChance = effect_value; - break; - - case SE_Accuracy: - { - spellbonuses.Accuracy[HIGHEST_SKILL+1] = effect_value; - itembonuses.Accuracy[HIGHEST_SKILL+1] = effect_value; - - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - aabonuses.Accuracy[e] = effect_value; - } - break; - } - - case SE_MaxHPChange: - spellbonuses.MaxHPChange = effect_value; - aabonuses.MaxHPChange = effect_value; - itembonuses.MaxHPChange = effect_value; - break; - - case SE_EndurancePool: - spellbonuses.Endurance = effect_value; - aabonuses.Endurance = effect_value; - itembonuses.Endurance = effect_value; - break; - - case SE_HealRate: - spellbonuses.HealRate = effect_value; - aabonuses.HealRate = effect_value; - itembonuses.HealRate = effect_value; - break; - - case SE_SkillDamageTaken: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.SkillDmgTaken[e] = effect_value; - aabonuses.SkillDmgTaken[e] = effect_value; - itembonuses.SkillDmgTaken[e] = effect_value; - - } - break; - } - - case SE_TriggerOnCast: - { - for(int e = 0; e < MAX_SPELL_TRIGGER; e++) - { - spellbonuses.SpellTriggers[e] = effect_value; - aabonuses.SpellTriggers[e] = effect_value; - itembonuses.SpellTriggers[e] = effect_value; - } - break; - } - - case SE_SpellCritChance: - spellbonuses.CriticalSpellChance = effect_value; - aabonuses.CriticalSpellChance = effect_value; - itembonuses.CriticalSpellChance = effect_value; - break; - - case SE_CriticalSpellChance: - spellbonuses.CriticalSpellChance = effect_value; - spellbonuses.SpellCritDmgIncrease = effect_value; - aabonuses.CriticalSpellChance = effect_value; - aabonuses.SpellCritDmgIncrease = effect_value; - itembonuses.CriticalSpellChance = effect_value; - itembonuses.SpellCritDmgIncrease = effect_value; - break; - - case SE_SpellCritDmgIncrease: - spellbonuses.SpellCritDmgIncrease = effect_value; - aabonuses.SpellCritDmgIncrease = effect_value; - itembonuses.SpellCritDmgIncrease = effect_value; - break; - - case SE_DotCritDmgIncrease: - spellbonuses.DotCritDmgIncrease = effect_value; - aabonuses.DotCritDmgIncrease = effect_value; - itembonuses.DotCritDmgIncrease = effect_value; - break; - - case SE_CriticalHealChance: - spellbonuses.CriticalHealChance = effect_value; - aabonuses.CriticalHealChance = effect_value; - itembonuses.CriticalHealChance = effect_value; - break; - - case SE_CriticalHealOverTime: - spellbonuses.CriticalHealOverTime = effect_value; - aabonuses.CriticalHealOverTime = effect_value; - itembonuses.CriticalHealOverTime = effect_value; - break; - - case SE_MitigateDamageShield: - spellbonuses.DSMitigationOffHand = effect_value; - itembonuses.DSMitigationOffHand = effect_value; - aabonuses.DSMitigationOffHand = effect_value; - break; - - case SE_CriticalDoTChance: - spellbonuses.CriticalDoTChance = effect_value; - aabonuses.CriticalDoTChance = effect_value; - itembonuses.CriticalDoTChance = effect_value; - break; - - case SE_ProcOnKillShot: - { - for(int e = 0; e < MAX_SPELL_TRIGGER*3; e=3) - { - spellbonuses.SpellOnKill[e] = effect_value; - spellbonuses.SpellOnKill[e+1] = effect_value; - spellbonuses.SpellOnKill[e+2] = effect_value; - - aabonuses.SpellOnKill[e] = effect_value; - aabonuses.SpellOnKill[e+1] = effect_value; - aabonuses.SpellOnKill[e+2] = effect_value; - - itembonuses.SpellOnKill[e] = effect_value; - itembonuses.SpellOnKill[e+1] = effect_value; - itembonuses.SpellOnKill[e+2] = effect_value; - } - break; - } - - /* - case SE_SpellOnDeath: - { - for(int e = 0; e < MAX_SPELL_TRIGGER; e=2) - { - spellbonuses.SpellOnDeath[e] = SPELL_UNKNOWN; - spellbonuses.SpellOnDeath[e+1] = effect_value; - } - break; - } - */ - - case SE_CriticalDamageMob: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.CritDmgMob[e] = effect_value; - aabonuses.CritDmgMob[e] = effect_value; - itembonuses.CritDmgMob[e] = effect_value; - } - break; - } - - case SE_SkillDamageAmount: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.SkillDamageAmount[e] = effect_value; - aabonuses.SkillDamageAmount[e] = effect_value; - itembonuses.SkillDamageAmount[e] = effect_value; - } - break; - } - - case SE_IncreaseBlockChance: - spellbonuses.IncreaseBlockChance = effect_value; - aabonuses.IncreaseBlockChance = effect_value; - itembonuses.IncreaseBlockChance = effect_value; - break; - - case SE_PersistantCasting: - spellbonuses.PersistantCasting = effect_value; - itembonuses.PersistantCasting = effect_value; - aabonuses.PersistantCasting = effect_value; - break; - - case SE_ImmuneFleeing: - spellbonuses.ImmuneToFlee = false; - break; - - case SE_DelayDeath: - spellbonuses.DelayDeath = effect_value; - aabonuses.DelayDeath = effect_value; - itembonuses.DelayDeath = effect_value; - break; - - case SE_SpellProcChance: - spellbonuses.SpellProcChance = effect_value; - itembonuses.SpellProcChance = effect_value; - aabonuses.SpellProcChance = effect_value; - break; - - case SE_CharmBreakChance: - spellbonuses.CharmBreakChance = effect_value; - aabonuses.CharmBreakChance = effect_value; - itembonuses.CharmBreakChance = effect_value; - break; - - case SE_BardSongRange: - spellbonuses.SongRange = effect_value; - aabonuses.SongRange = effect_value; - itembonuses.SongRange = effect_value; - break; - - case SE_SkillDamageAmount2: - { - for(int e = 0; e < HIGHEST_SKILL+1; e++) - { - spellbonuses.SkillDamageAmount2[e] = effect_value; - aabonuses.SkillDamageAmount2[e] = effect_value; - itembonuses.SkillDamageAmount2[e] = effect_value; - } - break; - } - - case SE_NegateAttacks: - spellbonuses.NegateAttacks[0] = effect_value; - spellbonuses.NegateAttacks[1] = effect_value; - break; - - case SE_MitigateMeleeDamage: - spellbonuses.MitigateMeleeRune[0] = effect_value; - spellbonuses.MitigateMeleeRune[1] = -1; - break; - - case SE_MeleeThresholdGuard: - spellbonuses.MeleeThresholdGuard[0] = effect_value; - spellbonuses.MeleeThresholdGuard[1] = -1; - spellbonuses.MeleeThresholdGuard[1] = effect_value; - break; - - case SE_SpellThresholdGuard: - spellbonuses.SpellThresholdGuard[0] = effect_value; - spellbonuses.SpellThresholdGuard[1] = -1; - spellbonuses.SpellThresholdGuard[1] = effect_value; - break; - - case SE_MitigateSpellDamage: - spellbonuses.MitigateSpellRune[0] = effect_value; - spellbonuses.MitigateSpellRune[1] = -1; - break; - - case SE_MitigateDotDamage: - spellbonuses.MitigateDotRune[0] = effect_value; - spellbonuses.MitigateDotRune[1] = -1; - break; - - case SE_ManaAbsorbPercentDamage: - spellbonuses.ManaAbsorbPercentDamage[0] = effect_value; - spellbonuses.ManaAbsorbPercentDamage[1] = -1; - break; - - case SE_ShieldBlock: - spellbonuses.ShieldBlock = effect_value; - aabonuses.ShieldBlock = effect_value; - itembonuses.ShieldBlock = effect_value; - - case SE_BlockBehind: - spellbonuses.BlockBehind = effect_value; - aabonuses.BlockBehind = effect_value; - itembonuses.BlockBehind = effect_value; - break; - - case SE_Fear: - spellbonuses.IsFeared = false; - break; - - case SE_FrontalStunResist: - spellbonuses.FrontalStunResist = effect_value; - aabonuses.FrontalStunResist = effect_value; - itembonuses.FrontalStunResist = effect_value; - break; - - case SE_ImprovedBindWound: - aabonuses.BindWound = effect_value; - itembonuses.BindWound = effect_value; - spellbonuses.BindWound = effect_value; - break; - - case SE_MaxBindWound: - spellbonuses.MaxBindWound = effect_value; - aabonuses.MaxBindWound = effect_value; - itembonuses.MaxBindWound = effect_value; - break; - - case SE_BaseMovementSpeed: - spellbonuses.BaseMovementSpeed = effect_value; - aabonuses.BaseMovementSpeed = effect_value; - itembonuses.BaseMovementSpeed = effect_value; - break; - - case SE_IncreaseRunSpeedCap: - itembonuses.IncreaseRunSpeedCap = effect_value; - aabonuses.IncreaseRunSpeedCap = effect_value; - spellbonuses.IncreaseRunSpeedCap = effect_value; - break; - - case SE_DoubleSpecialAttack: - spellbonuses.DoubleSpecialAttack = effect_value; - aabonuses.DoubleSpecialAttack = effect_value; - itembonuses.DoubleSpecialAttack = effect_value; - break; - - case SE_TripleBackstab: - spellbonuses.TripleBackstab = effect_value; - aabonuses.TripleBackstab = effect_value; - itembonuses.TripleBackstab = effect_value; - break; - - case SE_FrontalBackstabMinDmg: - spellbonuses.FrontalBackstabMinDmg = false; - break; - - case SE_FrontalBackstabChance: - spellbonuses.FrontalBackstabChance = effect_value; - aabonuses.FrontalBackstabChance = effect_value; - itembonuses.FrontalBackstabChance = effect_value; - break; - - case SE_ConsumeProjectile: - spellbonuses.ConsumeProjectile = effect_value; - aabonuses.ConsumeProjectile = effect_value; - itembonuses.ConsumeProjectile = effect_value; - break; - - case SE_ForageAdditionalItems: - spellbonuses.ForageAdditionalItems = effect_value; - aabonuses.ForageAdditionalItems = effect_value; - itembonuses.ForageAdditionalItems = effect_value; - break; - - case SE_Salvage: - spellbonuses.SalvageChance = effect_value; - aabonuses.SalvageChance = effect_value; - itembonuses.SalvageChance = effect_value; - break; - - case SE_ArcheryDamageModifier: - spellbonuses.ArcheryDamageModifier = effect_value; - aabonuses.ArcheryDamageModifier = effect_value; - itembonuses.ArcheryDamageModifier = effect_value; - break; - - case SE_SecondaryDmgInc: - spellbonuses.SecondaryDmgInc = false; - aabonuses.SecondaryDmgInc = false; - itembonuses.SecondaryDmgInc = false; - break; - - case SE_StrikeThrough: - spellbonuses.StrikeThrough = effect_value; - aabonuses.StrikeThrough = effect_value; - itembonuses.StrikeThrough = effect_value; - break; - - case SE_StrikeThrough2: - spellbonuses.StrikeThrough = effect_value; - aabonuses.StrikeThrough = effect_value; - itembonuses.StrikeThrough = effect_value; - break; - - case SE_GiveDoubleAttack: - spellbonuses.GiveDoubleAttack = effect_value; - aabonuses.GiveDoubleAttack = effect_value; - itembonuses.GiveDoubleAttack = effect_value; - break; - - case SE_PetCriticalHit: - spellbonuses.PetCriticalHit = effect_value; - aabonuses.PetCriticalHit = effect_value; - itembonuses.PetCriticalHit = effect_value; - break; - - case SE_CombatStability: - spellbonuses.CombatStability = effect_value; - aabonuses.CombatStability = effect_value; - itembonuses.CombatStability = effect_value; - break; - - case SE_PetAvoidance: - spellbonuses.PetAvoidance = effect_value; - aabonuses.PetAvoidance = effect_value; - itembonuses.PetAvoidance = effect_value; - break; - - case SE_Ambidexterity: - spellbonuses.Ambidexterity = effect_value; - aabonuses.Ambidexterity = effect_value; - itembonuses.Ambidexterity = effect_value; - break; - - case SE_PetMaxHP: - spellbonuses.PetMaxHP = effect_value; - aabonuses.PetMaxHP = effect_value; - itembonuses.PetMaxHP = effect_value; - break; - - case SE_PetFlurry: - spellbonuses.PetFlurry = effect_value; - aabonuses.PetFlurry = effect_value; - itembonuses.PetFlurry = effect_value; - break; - - case SE_GivePetGroupTarget: - spellbonuses.GivePetGroupTarget = false; - aabonuses.GivePetGroupTarget = false; - itembonuses.GivePetGroupTarget = false; - break; - - case SE_PetMeleeMitigation: - spellbonuses.PetMeleeMitigation = effect_value; - itembonuses.PetMeleeMitigation = effect_value; - aabonuses.PetMeleeMitigation = effect_value; - break; - - case SE_RootBreakChance: - spellbonuses.RootBreakChance = effect_value; - aabonuses.RootBreakChance = effect_value; - itembonuses.RootBreakChance = effect_value; - break; - - case SE_ChannelChanceItems: - spellbonuses.ChannelChanceItems = effect_value; - aabonuses.ChannelChanceItems = effect_value; - itembonuses.ChannelChanceItems = effect_value; - break; - - case SE_ChannelChanceSpells: - spellbonuses.ChannelChanceSpells = effect_value; - aabonuses.ChannelChanceSpells = effect_value; - itembonuses.ChannelChanceSpells = effect_value; - break; - - case SE_UnfailingDivinity: - spellbonuses.UnfailingDivinity = effect_value; - aabonuses.UnfailingDivinity = effect_value; - itembonuses.UnfailingDivinity = effect_value; - break; - - case SE_ItemHPRegenCapIncrease: - spellbonuses.ItemHPRegenCap = effect_value; - aabonuses.ItemHPRegenCap = effect_value; - itembonuses.ItemHPRegenCap = effect_value; - break; - - case SE_OffhandRiposteFail: - spellbonuses.OffhandRiposteFail = effect_value; - aabonuses.OffhandRiposteFail = effect_value; - itembonuses.OffhandRiposteFail = effect_value; - break; - - case SE_ItemAttackCapIncrease: - aabonuses.ItemATKCap = effect_value; - itembonuses.ItemATKCap = effect_value; - spellbonuses.ItemATKCap = effect_value; - break; - - case SE_SpellEffectResistChance: - { - for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) - { - spellbonuses.SEResist[e] = effect_value; - spellbonuses.SEResist[e+1] = effect_value; - } - break; - } - - case SE_MasteryofPast: - spellbonuses.MasteryofPast = effect_value; - aabonuses.MasteryofPast = effect_value; - itembonuses.MasteryofPast = effect_value; - break; - - case SE_DoubleRiposte: - spellbonuses.DoubleRiposte = effect_value; - itembonuses.DoubleRiposte = effect_value; - aabonuses.DoubleRiposte = effect_value; - break; - - case SE_GiveDoubleRiposte: - spellbonuses.GiveDoubleRiposte[0] = effect_value; - itembonuses.GiveDoubleRiposte[0] = effect_value; - aabonuses.GiveDoubleRiposte[0] = effect_value; - break; - - case SE_SlayUndead: - spellbonuses.SlayUndead[0] = effect_value; - spellbonuses.SlayUndead[1] = effect_value; - itembonuses.SlayUndead[0] = effect_value; - itembonuses.SlayUndead[1] = effect_value; - aabonuses.SlayUndead[0] = effect_value; - aabonuses.SlayUndead[1] = effect_value; - break; - - case SE_DoubleRangedAttack: - spellbonuses.DoubleRangedAttack = effect_value; - aabonuses.DoubleRangedAttack = effect_value; - itembonuses.DoubleRangedAttack = effect_value; - break; - - case SE_ShieldEquipHateMod: - spellbonuses.ShieldEquipHateMod = effect_value; - aabonuses.ShieldEquipHateMod = effect_value; - itembonuses.ShieldEquipHateMod = effect_value; - break; - - case SE_ShieldEquipDmgMod: - spellbonuses.ShieldEquipDmgMod[0] = effect_value; - spellbonuses.ShieldEquipDmgMod[1] = effect_value; - aabonuses.ShieldEquipDmgMod[0] = effect_value; - aabonuses.ShieldEquipDmgMod[1] = effect_value; - itembonuses.ShieldEquipDmgMod[0] = effect_value; - itembonuses.ShieldEquipDmgMod[1] = effect_value; - break; - - case SE_TriggerMeleeThreshold: - spellbonuses.TriggerMeleeThreshold[0] = effect_value; - spellbonuses.TriggerMeleeThreshold[1] = effect_value; - spellbonuses.TriggerMeleeThreshold[2] = effect_value; - break; - - case SE_TriggerSpellThreshold: - spellbonuses.TriggerSpellThreshold[0] = effect_value; - spellbonuses.TriggerSpellThreshold[1] = effect_value; - spellbonuses.TriggerSpellThreshold[2] = effect_value; - break; - - case SE_DivineAura: - spellbonuses.DivineAura = false; - break; - - case SE_StunBashChance: - spellbonuses.StunBashChance = effect_value; - itembonuses.StunBashChance = effect_value; - aabonuses.StunBashChance = effect_value; - break; - - case SE_IncreaseChanceMemwipe: - spellbonuses.IncreaseChanceMemwipe = effect_value; - itembonuses.IncreaseChanceMemwipe = effect_value; - aabonuses.IncreaseChanceMemwipe = effect_value; - break; - - case SE_CriticalMend: - spellbonuses.CriticalMend = effect_value; - itembonuses.CriticalMend = effect_value; - aabonuses.CriticalMend = effect_value; - break; - - case SE_DistanceRemoval: - spellbonuses.DistanceRemoval = effect_value; - break; - - case SE_ImprovedTaunt: - spellbonuses.ImprovedTaunt[0] = effect_value; - spellbonuses.ImprovedTaunt[1] = effect_value; - spellbonuses.ImprovedTaunt[2] = -1; - break; - - case SE_FrenziedDevastation: - spellbonuses.FrenziedDevastation = effect_value; - aabonuses.FrenziedDevastation = effect_value; - itembonuses.FrenziedDevastation = effect_value; - break; - - case SE_Root: - spellbonuses.Root[0] = effect_value; - spellbonuses.Root[1] = -1; - break; - - case SE_Rune: - spellbonuses.MeleeRune[0] = effect_value; - spellbonuses.MeleeRune[1] = -1; - break; - - case SE_AbsorbMagicAtt: - spellbonuses.AbsorbMagicAtt[0] = effect_value; - spellbonuses.AbsorbMagicAtt[1] = -1; - break; - - case SE_Berserk: - spellbonuses.BerserkSPA = false; - aabonuses.BerserkSPA = false; - itembonuses.BerserkSPA = false; - break; - - case SE_Vampirism: - spellbonuses.Vampirism = effect_value; - aabonuses.Vampirism = effect_value; - itembonuses.Vampirism = effect_value; - break; - - case SE_Metabolism: - spellbonuses.Metabolism = effect_value; - aabonuses.Metabolism = effect_value; - itembonuses.Metabolism = effect_value; - break; - - case SE_ImprovedReclaimEnergy: - spellbonuses.ImprovedReclaimEnergy = effect_value; - aabonuses.ImprovedReclaimEnergy = effect_value; - itembonuses.ImprovedReclaimEnergy = effect_value; - break; - - case SE_HeadShot: - spellbonuses.HeadShot[0] = effect_value; - aabonuses.HeadShot[0] = effect_value; - itembonuses.HeadShot[0] = effect_value; - spellbonuses.HeadShot[1] = effect_value; - aabonuses.HeadShot[1] = effect_value; - itembonuses.HeadShot[1] = effect_value; - break; - - case SE_HeadShotLevel: - spellbonuses.HSLevel = effect_value; - aabonuses.HSLevel = effect_value; - itembonuses.HSLevel = effect_value; - break; - - case SE_Assassinate: - spellbonuses.Assassinate[0] = effect_value; - aabonuses.Assassinate[0] = effect_value; - itembonuses.Assassinate[0] = effect_value; - spellbonuses.Assassinate[1] = effect_value; - aabonuses.Assassinate[1] = effect_value; - itembonuses.Assassinate[1] = effect_value; - break; - - case SE_AssassinateLevel: - spellbonuses.AssassinateLevel = effect_value; - aabonuses.AssassinateLevel = effect_value; - itembonuses.AssassinateLevel = effect_value; - break; - - case SE_FinishingBlow: - spellbonuses.FinishingBlow[0] = effect_value; - aabonuses.FinishingBlow[0] = effect_value; - itembonuses.FinishingBlow[0] = effect_value; - spellbonuses.FinishingBlow[1] = effect_value; - aabonuses.FinishingBlow[1] = effect_value; - itembonuses.FinishingBlow[1] = effect_value; - break; - - case SE_FinishingBlowLvl: - spellbonuses.FinishingBlowLvl[0] = effect_value; - aabonuses.FinishingBlowLvl[0] = effect_value; - itembonuses.FinishingBlowLvl[0] = effect_value; - spellbonuses.FinishingBlowLvl[1] = effect_value; - aabonuses.FinishingBlowLvl[1] = effect_value; - itembonuses.FinishingBlowLvl[1] = effect_value; - break; - - } - } - } -} - diff --git a/zone/groupsx.cpp b/zone/groupsx.cpp deleted file mode 100644 index 6aee5f38b..000000000 --- a/zone/groupsx.cpp +++ /dev/null @@ -1,2194 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "../common/debug.h" -#include "masterentity.h" -#include "NpcAI.h" -#include "../common/packet_functions.h" -#include "../common/packet_dump.h" -#include "../common/StringUtil.h" -#include "worldserver.h" -extern EntityList entity_list; -extern WorldServer worldserver; - -// -// Xorlac: This will need proper synchronization to make it work correctly. -// Also, should investigate client ack for packet to ensure proper synch. -// - -/* - -note about how groups work: -A group contains 2 list, a list of pointers to members and a -list of member names. All members of a group should have their -name in the membername array, wether they are in the zone or not. -Only members in this zone will have non-null pointers in the -members array. - -*/ - -//create a group which should allready exist in the database -Group::Group(uint32 gid) -: GroupIDConsumer(gid) -{ - leader = nullptr; - memset(members,0,sizeof(Mob*) * MAX_GROUP_MEMBERS); - AssistTargetID = 0; - TankTargetID = 0; - PullerTargetID = 0; - - memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct)); - uint32 i; - for(i=0;iSetGrouped(true); - SetLeader(leader); - AssistTargetID = 0; - TankTargetID = 0; - PullerTargetID = 0; - memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct)); - uint32 i; - for(i=0;iGetName()); - - if(leader->IsClient()) - strcpy(leader->CastToClient()->GetPP().groupMembers[0],leader->GetName()); - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - MarkedNPCs[i] = 0; - - NPCMarkerID = 0; -} - -Group::~Group() -{ - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - if(MarkedNPCs[i]) - { - Mob* m = entity_list.GetMob(MarkedNPCs[i]); - if(m) - m->IsTargeted(-1); - } -} - -//Cofruben:Split money used in OP_Split. -//Rewritten by Father Nitwit -void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter) { - //avoid unneeded work - if(copper == 0 && silver == 0 && gold == 0 && platinum == 0) - return; - - uint32 i; - uint8 membercount = 0; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr) { - membercount++; - } - } - - if (membercount == 0) - return; - - uint32 mod; - //try to handle round off error a little better - if(membercount > 1) { - mod = platinum % membercount; - if((mod) > 0) { - platinum -= mod; - gold += 10 * mod; - } - mod = gold % membercount; - if((mod) > 0) { - gold -= mod; - silver += 10 * mod; - } - mod = silver % membercount; - if((mod) > 0) { - silver -= mod; - copper += 10 * mod; - } - } - - //calculate the splits - //We can still round off copper pieces, but I dont care - uint32 sc; - uint32 cpsplit = copper / membercount; - sc = copper % membercount; - uint32 spsplit = silver / membercount; - uint32 gpsplit = gold / membercount; - uint32 ppsplit = platinum / membercount; - - char buf[128]; - buf[63] = '\0'; - std::string msg = "You receive"; - bool one = false; - - if(ppsplit > 0) { - snprintf(buf, 63, " %u platinum", ppsplit); - msg += buf; - one = true; - } - if(gpsplit > 0) { - if(one) - msg += ","; - snprintf(buf, 63, " %u gold", gpsplit); - msg += buf; - one = true; - } - if(spsplit > 0) { - if(one) - msg += ","; - snprintf(buf, 63, " %u silver", spsplit); - msg += buf; - one = true; - } - if(cpsplit > 0) { - if(one) - msg += ","; - //this message is not 100% accurate for the splitter - //if they are receiving any roundoff - snprintf(buf, 63, " %u copper", cpsplit); - msg += buf; - one = true; - } - msg += " as your split"; - - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr && members[i]->IsClient()) { // If Group Member is Client - Client *c = members[i]->CastToClient(); - //I could not get MoneyOnCorpse to work, so we use this - c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true); - - c->Message(2, msg.c_str()); - } - } -} - -bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 CharacterID) -{ - bool InZone = true; - bool ismerc = false; - - // This method should either be passed a Mob*, if the new member is in this zone, or a nullptr Mob* - // and the name and CharacterID of the new member, if they are out of zone. - // - if(!newmember && !NewMemberName) - return false; - - if(GroupCount() >= MAX_GROUP_MEMBERS) //Sanity check for merging groups together. - return false; - - if(!newmember) - InZone = false; - else - { - NewMemberName = newmember->GetCleanName(); - - if(newmember->IsClient()) - CharacterID = newmember->CastToClient()->CharacterID(); - if(newmember->IsMerc()) - { - Client* owner = newmember->CastToMerc()->GetMercOwner(); - if(owner) - { - CharacterID = owner->CastToClient()->CharacterID(); - NewMemberName = newmember->GetName(); - ismerc = true; - } - } - } - - uint32 i = 0; - - // See if they are already in the group - // - for (i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(!strcasecmp(membername[i], NewMemberName)) - return false; - - // Put them in the group - for (i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if (membername[i][0] == '\0') - { - if(InZone) - members[i] = newmember; - - break; - } - } - - if (i == MAX_GROUP_MEMBERS) - return false; - - strcpy(membername[i], NewMemberName); - MemberRoles[i] = 0; - - int x=1; - - //build the template join packet - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); - GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer; - strcpy(gj->membername, NewMemberName); - gj->action = groupActJoin; - - gj->leader_aas = LeaderAbilities; - - for (i = 0;i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr && members[i] != newmember) { - //fill in group join & send it - if(members[i]->IsMerc()) - { - strcpy(gj->yourname, members[i]->GetName()); - } - else - { - strcpy(gj->yourname, members[i]->GetCleanName()); - } - if(members[i]->IsClient()) { - members[i]->CastToClient()->QueuePacket(outapp); - - //put new member into existing person's list - strcpy(members[i]->CastToClient()->GetPP().groupMembers[this->GroupCount()-1], NewMemberName); - } - - //put this existing person into the new member's list - if(InZone && newmember->IsClient()) { - if(IsLeader(members[i])) - strcpy(newmember->CastToClient()->GetPP().groupMembers[0], members[i]->GetCleanName()); - else { - strcpy(newmember->CastToClient()->GetPP().groupMembers[x], members[i]->GetCleanName()); - x++; - } - } - } - } - - if(InZone) - { - //put new member in his own list. - newmember->SetGrouped(true); - - if(newmember->IsClient()) - { - strcpy(newmember->CastToClient()->GetPP().groupMembers[x], NewMemberName); - newmember->CastToClient()->Save(); - database.SetGroupID(NewMemberName, GetID(), newmember->CastToClient()->CharacterID(), false); - SendMarkedNPCsToMember(newmember->CastToClient()); - - NotifyMainTank(newmember->CastToClient(), 1); - NotifyMainAssist(newmember->CastToClient(), 1); - NotifyPuller(newmember->CastToClient(), 1); - } - - if(newmember->IsMerc()) - { - Client* owner = newmember->CastToMerc()->GetMercOwner(); - if(owner) - { - database.SetGroupID(newmember->GetName(), GetID(), owner->CharacterID(), true); - } - } -#ifdef BOTS - for (i = 0;i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr && members[i]->IsBot()) { - members[i]->CastToBot()->CalcChanceToCast(); - } - } -#endif //BOTS - } - else - database.SetGroupID(NewMemberName, GetID(), CharacterID, ismerc); - - safe_delete(outapp); - - return true; -} - -void Group::AddMember(const char *NewMemberName) -{ - // This method should be called when both the new member and the group leader are in a different zone to this one. - // - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(!strcasecmp(membername[i], NewMemberName)) - { - return; - } - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if (membername[i][0] == '\0') - { - strcpy(membername[i], NewMemberName); - MemberRoles[i] = 0; - break; - } - } -} - - -void Group::QueuePacket(const EQApplicationPacket *app, bool ack_req) -{ - uint32 i; - for(i = 0; i < MAX_GROUP_MEMBERS; i++) - if(members[i] && members[i]->IsClient()) - members[i]->CastToClient()->QueuePacket(app, ack_req); -} - -// solar: sends the rest of the group's hps to member. this is useful when -// someone first joins a group, but otherwise there shouldn't be a need to -// call it -void Group::SendHPPacketsTo(Mob *member) -{ - if(member && member->IsClient()) - { - EQApplicationPacket hpapp; - EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) - { - if(members[i] && members[i] != member) - { - members[i]->CreateHPPacket(&hpapp); - member->CastToClient()->QueuePacket(&hpapp, false); - if(member->CastToClient()->GetClientVersion() >= EQClientSoD) - { - outapp.SetOpcode(OP_MobManaUpdate); - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; - mmus->spawn_id = members[i]->GetID(); - mmus->mana = members[i]->GetManaPercent(); - member->CastToClient()->QueuePacket(&outapp, false); - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; - outapp.SetOpcode(OP_MobEnduranceUpdate); - meus->endurance = members[i]->GetEndurancePercent(); - member->CastToClient()->QueuePacket(&outapp, false); - } - } - } - } -} - -void Group::SendHPPacketsFrom(Mob *member) -{ - EQApplicationPacket hp_app; - if(!member) - return; - - member->CreateHPPacket(&hp_app); - EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - - uint32 i; - for(i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(members[i] && members[i] != member && members[i]->IsClient()) - { - members[i]->CastToClient()->QueuePacket(&hp_app); - if(members[i]->CastToClient()->GetClientVersion() >= EQClientSoD) - { - outapp.SetOpcode(OP_MobManaUpdate); - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; - mmus->spawn_id = member->GetID(); - mmus->mana = member->GetManaPercent(); - members[i]->CastToClient()->QueuePacket(&outapp, false); - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; - outapp.SetOpcode(OP_MobEnduranceUpdate); - meus->endurance = member->GetEndurancePercent(); - members[i]->CastToClient()->QueuePacket(&outapp, false); - } - } - } -} - -//updates a group member's client pointer when they zone in -//if the group was in the zone allready -bool Group::UpdatePlayer(Mob* update){ - - VerifyGroup(); - - uint32 i=0; - if(update->IsClient()) { - //update their player profile - PlayerProfile_Struct &pp = update->CastToClient()->GetPP(); - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(membername[i][0] == '\0') - memset(pp.groupMembers[i], 0, 64); - else - strn0cpy(pp.groupMembers[i], membername[i], 64); - } - if(IsNPCMarker(update->CastToClient())) - { - NPCMarkerID = update->GetID(); - SendLeadershipAAUpdate(); - } - } - - for (i = 0; i < MAX_GROUP_MEMBERS; i++) - { - if (!strcasecmp(membername[i],update->GetName())) - { - members[i] = update; - members[i]->SetGrouped(true); - return true; - } - } - return false; -} - - -void Group::MemberZoned(Mob* removemob) { - uint32 i; - - if (removemob == nullptr) - return; - - if(removemob == GetLeader()) - SetLeader(nullptr); - - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == removemob) { - members[i] = nullptr; - //should NOT clear the name, it is used for world communication. - break; - } -#ifdef BOTS - if (members[i] != nullptr && members[i]->IsBot()) { - members[i]->CastToBot()->CalcChanceToCast(); - } -#endif //BOTS - } - if(removemob->IsClient() && HasRole(removemob, RoleAssist)) - SetGroupAssistTarget(0); - - if(removemob->IsClient() && HasRole(removemob, RoleTank)) - SetGroupTankTarget(0); - - if(removemob->IsClient() && HasRole(removemob, RolePuller)) - SetGroupPullerTarget(0); -} - -bool Group::DelMemberOOZ(const char *Name) { - - if(!Name) return false; - - // If a member out of zone has disbanded, clear out their name. - // - for(unsigned int i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(!strcasecmp(Name, membername[i])) - // This shouldn't be called if the member is in this zone. - if(!members[i]) { - if(!strncmp(GetLeaderName(), Name, 64)) - { - //TODO: Transfer leadership if leader disbands OOZ. - UpdateGroupAAs(); - } - - memset(membername[i], 0, 64); - MemberRoles[i] = 0; - if(GroupCount() < 3) - { - UnDelegateMarkNPC(NPCMarkerName.c_str()); - if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < EQClientSoD) { - UnDelegateMainAssist(MainAssistName.c_str()); - } - ClearAllNPCMarks(); - } - return true; - } - } - - return false; -} - -bool Group::DelMember(Mob* oldmember,bool ignoresender) -{ - if (oldmember == nullptr){ - return false; - } - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == oldmember) { - members[i] = nullptr; - membername[i][0] = '\0'; - memset(membername[i],0,64); - MemberRoles[i] = 0; - break; - } - } - - //handle leader quitting group gracefully - if (oldmember == GetLeader() && GroupCount() >= 2) { - for(uint32 nl = 0; nl < MAX_GROUP_MEMBERS; nl++) { - if(members[nl]) { - ChangeLeader(members[nl]); - break; - } - } - } - - ServerPacket* pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct)); - ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer; - gl->gid = GetID(); - gl->zoneid = zone->GetZoneID(); - gl->instance_id = zone->GetInstanceID(); - strcpy(gl->member_name, oldmember->GetName()); - worldserver.SendPacket(pack); - safe_delete(pack); - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); - GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer; - gu->action = groupActLeave; - strcpy(gu->membername, oldmember->GetCleanName()); - strcpy(gu->yourname, oldmember->GetCleanName()); - - gu->leader_aas = LeaderAbilities; - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == nullptr) { - //if (DEBUG>=5) LogFile->write(EQEMuLog::Debug, "Group::DelMember() null member at slot %i", i); - continue; - } - if (members[i] != oldmember) { - strcpy(gu->yourname, members[i]->GetCleanName()); - if(members[i]->IsClient()) - members[i]->CastToClient()->QueuePacket(outapp); - } -#ifdef BOTS - if (members[i] != nullptr && members[i]->IsBot()) { - members[i]->CastToBot()->CalcChanceToCast(); - } -#endif //BOTS - } - - if (!ignoresender) { - strcpy(gu->yourname,oldmember->GetCleanName()); - strcpy(gu->membername,oldmember->GetCleanName()); - gu->action = groupActLeave; - - if(oldmember->IsClient()) - oldmember->CastToClient()->QueuePacket(outapp); - } - - if(oldmember->IsClient()) - database.SetGroupID(oldmember->GetCleanName(), 0, oldmember->CastToClient()->CharacterID()); - - oldmember->SetGrouped(false); - disbandcheck = true; - - safe_delete(outapp); - - if(HasRole(oldmember, RoleTank)) - { - SetGroupTankTarget(0); - UnDelegateMainTank(oldmember->GetName()); - } - - if(HasRole(oldmember, RoleAssist)) - { - SetGroupAssistTarget(0); - UnDelegateMainAssist(oldmember->GetName()); - } - - if(HasRole(oldmember, RolePuller)) - { - SetGroupPullerTarget(0); - UnDelegatePuller(oldmember->GetName()); - } - - if(oldmember->IsClient()) - SendMarkedNPCsToMember(oldmember->CastToClient(), true); - - if(GroupCount() < 3) - { - UnDelegateMarkNPC(NPCMarkerName.c_str()); - if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < EQClientSoD) { - UnDelegateMainAssist(MainAssistName.c_str()); - } - ClearAllNPCMarks(); - } - - return true; -} - -// does the caster + group -void Group::CastGroupSpell(Mob* caster, uint16 spell_id) { - uint32 z; - float range, distance; - - if(!caster) - return; - - castspell = true; - range = caster->GetAOERange(spell_id); - - float range2 = range*range; - -// caster->SpellOnTarget(spell_id, caster); - - for(z=0; z < MAX_GROUP_MEMBERS; z++) - { - if(members[z] == caster) { - caster->SpellOnTarget(spell_id, caster); -#ifdef GROUP_BUFF_PETS - if(caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed()) - caster->SpellOnTarget(spell_id, caster->GetPet()); -#endif - } - else if(members[z] != nullptr) - { - distance = caster->DistNoRoot(*members[z]); - if(distance <= range2) { - caster->SpellOnTarget(spell_id, members[z]); -#ifdef GROUP_BUFF_PETS - if(members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed()) - caster->SpellOnTarget(spell_id, members[z]->GetPet()); -#endif - } else - _log(SPELLS__CASTING, "Group spell: %s is out of range %f at distance %f from %s", members[z]->GetName(), range, distance, caster->GetName()); - } - } - - castspell = false; - disbandcheck = true; -} - -// does the caster + group -void Group::GroupBardPulse(Mob* caster, uint16 spell_id) { - uint32 z; - float range, distance; - - if(!caster) - return; - - castspell = true; - range = caster->GetAOERange(spell_id); - - float range2 = range*range; - - for(z=0; z < MAX_GROUP_MEMBERS; z++) { - if(members[z] == caster) { - caster->BardPulse(spell_id, caster); -#ifdef GROUP_BUFF_PETS - if(caster->GetPet() && caster->HasPetAffinity() && !caster->GetPet()->IsCharmed()) - caster->BardPulse(spell_id, caster->GetPet()); -#endif - } - else if(members[z] != nullptr) - { - distance = caster->DistNoRoot(*members[z]); - if(distance <= range2) { - members[z]->BardPulse(spell_id, caster); -#ifdef GROUP_BUFF_PETS - if(members[z]->GetPet() && members[z]->HasPetAffinity() && !members[z]->GetPet()->IsCharmed()) - members[z]->GetPet()->BardPulse(spell_id, caster); -#endif - } else - _log(SPELLS__BARDS, "Group bard pulse: %s is out of range %f at distance %f from %s", members[z]->GetName(), range, distance, caster->GetName()); - } - } -} - -bool Group::IsGroupMember(Mob* client) -{ - bool Result = false; - - if(client) { - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == client) - Result = true; - } - } - - return Result; -} - -bool Group::IsGroupMember(const char *Name) -{ - if(Name) - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) - if((strlen(Name) == strlen(membername[i])) && !strncmp(membername[i], Name, strlen(Name))) - return true; - - return false; -} - -void Group::GroupMessage(Mob* sender, uint8 language, uint8 lang_skill, const char* message) { - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(!members[i]) - continue; - - if (members[i]->IsClient() && members[i]->CastToClient()->GetFilter(FilterGroupChat)!=0) - members[i]->CastToClient()->ChannelMessageSend(sender->GetName(),members[i]->GetName(),2,language,lang_skill,message); - } - - ServerPacket* pack = new ServerPacket(ServerOP_OOZGroupMessage, sizeof(ServerGroupChannelMessage_Struct) + strlen(message) + 1); - ServerGroupChannelMessage_Struct* gcm = (ServerGroupChannelMessage_Struct*)pack->pBuffer; - gcm->zoneid = zone->GetZoneID(); - gcm->groupid = GetID(); - gcm->instanceid = zone->GetInstanceID(); - strcpy(gcm->from, sender->GetName()); - strcpy(gcm->message, message); - worldserver.SendPacket(pack); - safe_delete(pack); -} - -uint32 Group::GetTotalGroupDamage(Mob* other) { - uint32 total = 0; - - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(!members[i]) - continue; - if (other->CheckAggro(members[i])) - total += other->GetHateAmount(members[i],true); - } - return total; -} - -void Group::DisbandGroup() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupUpdate_Struct)); - - GroupUpdate_Struct* gu = (GroupUpdate_Struct*) outapp->pBuffer; - gu->action = groupActDisband; - - Client *Leader = nullptr; - - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == nullptr) { - continue; - } - - if (members[i]->IsClient()) { - if(IsLeader(members[i])) - Leader = members[i]->CastToClient(); - - strcpy(gu->yourname, members[i]->GetName()); - database.SetGroupID(members[i]->GetName(), 0, members[i]->CastToClient()->CharacterID()); - members[i]->CastToClient()->QueuePacket(outapp); - SendMarkedNPCsToMember(members[i]->CastToClient(), true); - - } - - members[i]->SetGrouped(false); - members[i] = nullptr; - membername[i][0] = '\0'; - } - - ClearAllNPCMarks(); - - ServerPacket* pack = new ServerPacket(ServerOP_DisbandGroup, sizeof(ServerDisbandGroup_Struct)); - ServerDisbandGroup_Struct* dg = (ServerDisbandGroup_Struct*)pack->pBuffer; - dg->zoneid = zone->GetZoneID(); - dg->groupid = GetID(); - dg->instance_id = zone->GetInstanceID(); - worldserver.SendPacket(pack); - safe_delete(pack); - - entity_list.RemoveGroup(GetID()); - if(GetID() != 0) - database.ClearGroup(GetID()); - - if(Leader && (Leader->IsLFP())) { - Leader->UpdateLFP(); - } - - safe_delete(outapp); -} - -bool Group::Process() { - if(disbandcheck && !GroupCount()) - return false; - else if(disbandcheck && GroupCount()) - disbandcheck = false; - return true; -} - -void Group::SendUpdate(uint32 type, Mob* member) -{ - if(!member->IsClient()) - return; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate2_Struct)); - GroupUpdate2_Struct* gu = (GroupUpdate2_Struct*)outapp->pBuffer; - gu->action = type; - strcpy(gu->yourname,member->GetName()); - - int x = 0; - - gu->leader_aas = LeaderAbilities; - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if((members[i] != nullptr) && IsLeader(members[i])) - { - strcpy(gu->leadersname, members[i]->GetName()); - break; - } - - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if (members[i] != nullptr && members[i] != member) - strcpy(gu->membername[x++], members[i]->GetName()); - - member->CastToClient()->QueuePacket(outapp); - - safe_delete(outapp); -} - -void Group::SendLeadershipAAUpdate() -{ - // This method updates other members of the group in the current zone with the Leader's group leadership AAs. - // - // It is called when the leader purchases a leadership AA or enters a zone. - // - // If a group member is not in the same zone as the leader when the leader purchases a new AA, they will not become - // aware of it until they are next in the same zone as the leader. - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); - - GroupJoin_Struct* gu = (GroupJoin_Struct*)outapp->pBuffer; - - gu->action = groupActAAUpdate; - - uint32 i = 0; - - gu->leader_aas = LeaderAbilities; - - gu->NPCMarkerID = GetNPCMarkerID(); - - for (i = 0;i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - { - strcpy(gu->yourname, members[i]->GetName()); - strcpy(gu->membername, members[i]->GetName()); - members[i]->CastToClient()->QueuePacket(outapp); - } - - safe_delete(outapp); -} - -uint8 Group::GroupCount() { - - uint8 MemberCount = 0; - - for(uint8 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(membername[i][0]) - ++MemberCount; - - return MemberCount; -} - -uint32 Group::GetHighestLevel() -{ -uint32 level = 1; -uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) - { - if (members[i]) - { - if(members[i]->GetLevel() > level) - level = members[i]->GetLevel(); - } - } - return level; -} -uint32 Group::GetLowestLevel() -{ -uint32 level = 255; -uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) - { - if (members[i]) - { - if(members[i]->GetLevel() < level) - level = members[i]->GetLevel(); - } - } - return level; -} - -void Group::TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float x, float y, float z, float heading) -{ - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) - { - if (members[i] != nullptr && members[i]->IsClient() && members[i] != sender) - { - members[i]->CastToClient()->MovePC(zoneID, instance_id, x, y, z, heading, 0, ZoneSolicited); - } - } -} - -bool Group::LearnMembers() { - char errbuf[MYSQL_ERRMSG_SIZE]; - char* query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - if (database.RunQuery(query,MakeAnyLenString(&query, "SELECT name FROM group_id WHERE groupid=%lu", (unsigned long)GetID()), - errbuf,&result)){ - safe_delete_array(query); - if(mysql_num_rows(result) < 1) { //could prolly be 2 - mysql_free_result(result); - LogFile->write(EQEMuLog::Error, "Error getting group members for group %lu: %s", (unsigned long)GetID(), errbuf); - return(false); - } - int i = 0; - while((row = mysql_fetch_row(result))) { - if(!row[0]) - continue; - members[i] = nullptr; - strn0cpy(membername[i], row[0], 64); - - i++; - } - mysql_free_result(result); - } - - return(true); -} - -void Group::VerifyGroup() { - /* - The purpose of this method is to make sure that a group - is in a valid state, to prevent dangling pointers. - Only called every once in a while (on member re-join for now). - */ - - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (membername[i][0] == '\0') { -#if EQDEBUG >= 7 -LogFile->write(EQEMuLog::Debug, "Group %lu: Verify %d: Empty.\n", (unsigned long)GetID(), i); -#endif - members[i] = nullptr; - continue; - } - - //it should be safe to use GetClientByName, but Group is trying - //to be generic, so we'll go for general Mob - Mob *them = entity_list.GetMob(membername[i]); - if(them == nullptr && members[i] != nullptr) { //they arnt here anymore.... -#if EQDEBUG >= 6 - LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' has disappeared!!", (unsigned long)GetID(), membername[i]); -#endif - membername[i][0] = '\0'; - members[i] = nullptr; - continue; - } - - if(them != nullptr && members[i] != them) { //our pointer is out of date... not so good. -#if EQDEBUG >= 5 - LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' had an out of date pointer!!", (unsigned long)GetID(), membername[i]); -#endif - members[i] = them; - continue; - } -#if EQDEBUG >= 8 - LogFile->write(EQEMuLog::Debug, "Member of group %lu named '%s' is valid.", (unsigned long)GetID(), membername[i]); -#endif - } -} - - -void Group::GroupMessage_StringID(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2,const char* message3,const char* message4,const char* message5,const char* message6,const char* message7,const char* message8,const char* message9, uint32 distance) { - uint32 i; - for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(members[i] == nullptr) - continue; - - if(members[i] == sender) - continue; - - members[i]->Message_StringID(type, string_id, message, message2, message3, message4, message5, message6, message7, message8, message9, 0); - } -} - - - -void Client::LeaveGroup() { - Group *g = GetGroup(); - - if(g) { - if(g->GroupCount() < 3) - g->DisbandGroup(); - else - g->DelMember(this); - } else { - //force things a little - database.SetGroupID(GetName(), 0, CharacterID()); - } - - isgrouped = false; -} - -void Group::HealGroup(uint32 heal_amt, Mob* caster, int32 range) -{ - if (!caster) - return; - - if (!range) - range = 200; - - float distance; - float range2 = range*range; - - - int numMem = 0; - unsigned int gi = 0; - for(; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi]){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - numMem += 1; - } - } - } - - heal_amt /= numMem; - for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi]){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - members[gi]->HealDamage(heal_amt, caster); - members[gi]->SendHPUpdate(); - } - } - } -} - - -void Group::BalanceHP(int32 penalty, int32 range, Mob* caster, int32 limit) -{ - if (!caster) - return; - - if (!range) - range = 200; - - int dmgtaken = 0, numMem = 0, dmgtaken_tmp = 0; - - float distance; - float range2 = range*range; - - unsigned int gi = 0; - for(; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi]){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - - dmgtaken_tmp = members[gi]->GetMaxHP() - members[gi]->GetHP(); - if (limit && (dmgtaken_tmp > limit)) - dmgtaken_tmp = limit; - - dmgtaken += (dmgtaken_tmp); - numMem += 1; - } - } - } - - dmgtaken += dmgtaken * penalty / 100; - dmgtaken /= numMem; - for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi]){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - if((members[gi]->GetMaxHP() - dmgtaken) < 1){ //this way the ability will never kill someone - members[gi]->SetHP(1); //but it will come darn close - members[gi]->SendHPUpdate(); - } - else{ - members[gi]->SetHP(members[gi]->GetMaxHP() - dmgtaken); - members[gi]->SendHPUpdate(); - } - } - } - } -} - -void Group::BalanceMana(int32 penalty, int32 range, Mob* caster, int32 limit) -{ - if (!caster) - return; - - if (!range) - range = 200; - - float distance; - float range2 = range*range; - - int manataken = 0, numMem = 0, manataken_tmp = 0; - unsigned int gi = 0; - for(; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi] && (members[gi]->GetMaxMana() > 0)){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - - manataken_tmp = members[gi]->GetMaxMana() - members[gi]->GetMana(); - if (limit && (manataken_tmp > limit)) - manataken_tmp = limit; - - manataken += (manataken_tmp); - numMem += 1; - } - } - } - - manataken += manataken * penalty / 100; - manataken /= numMem; - - if (limit && (manataken > limit)) - manataken = limit; - - for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++) - { - if(members[gi]){ - distance = caster->DistNoRoot(*members[gi]); - if(distance <= range2){ - if((members[gi]->GetMaxMana() - manataken) < 1){ - members[gi]->SetMana(1); - if (members[gi]->IsClient()) - members[gi]->CastToClient()->SendManaUpdate(); - } - else{ - members[gi]->SetMana(members[gi]->GetMaxMana() - manataken); - if (members[gi]->IsClient()) - members[gi]->CastToClient()->SendManaUpdate(); - } - } - } - } -} - -uint16 Group::GetAvgLevel() -{ - double levelHolder = 0; - uint8 i = 0; - uint8 numMem = 0; - while(i < MAX_GROUP_MEMBERS) - { - if (members[i]) - { - numMem++; - levelHolder = levelHolder + (members[i]->GetLevel()); - } - i++; - } - levelHolder = ((levelHolder/numMem)+.5); // total levels divided by num of characters - return (uint16(levelHolder)); -} - -void Group::MarkNPC(Mob* Target, int Number) -{ - // Send a packet to all group members in this zone causing the client to prefix the Target mob's name - // with the specified Number. - // - if(!Target || Target->IsClient()) - return; - - if((Number < 1) || (Number > MAX_MARKED_NPCS)) - return; - - bool AlreadyMarked = false; - - uint16 EntityID = Target->GetID(); - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - if(MarkedNPCs[i] == EntityID) - { - if(i == (Number - 1)) - return; - - UpdateXTargetMarkedNPC(i+1, nullptr); - MarkedNPCs[i] = 0; - - AlreadyMarked = true; - - break; - } - - if(!AlreadyMarked) - { - if(MarkedNPCs[Number - 1]) - { - Mob* m = entity_list.GetMob(MarkedNPCs[Number-1]); - if(m) - m->IsTargeted(-1); - - UpdateXTargetMarkedNPC(Number, nullptr); - } - - if(EntityID) - { - Mob* m = entity_list.GetMob(Target->GetID()); - if(m) - m->IsTargeted(1); - } - } - - MarkedNPCs[Number - 1] = EntityID; - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct)); - - MarkNPC_Struct* mnpcs = (MarkNPC_Struct *)outapp->pBuffer; - - mnpcs->TargetID = EntityID; - - mnpcs->Number = Number; - - Mob *m = entity_list.GetMob(EntityID); - - if(m) - sprintf(mnpcs->Name, "%s", m->GetCleanName()); - - QueuePacket(outapp); - - safe_delete(outapp); - - UpdateXTargetMarkedNPC(Number, m); -} - -void Group::DelegateMainTank(const char *NewMainTankName, uint8 toggle) -{ - // This method is called when the group leader Delegates the Main Tank role to a member of the group - // (or himself). All group members in the zone are notified of the new Main Tank and it is recorded - // in the group_leaders table so as to persist across zones. - // - - bool updateDB = false; - - if(!NewMainTankName) - return; - - Mob *m = entity_list.GetMob(NewMainTankName); - - if(!m) - return; - - if(MainTankName != NewMainTankName || !toggle) - updateDB = true; - - if(m->GetTarget()) - TankTargetID = m->GetTarget()->GetID(); - else - TankTargetID = 0; - - Mob *mtt = TankTargetID ? entity_list.GetMob(TankTargetID) : 0; - - SetMainTank(NewMainTankName); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - NotifyMainTank(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(GroupTank, m, NewMainTankName); - members[i]->CastToClient()->UpdateXTargetType(GroupTankTarget, mtt); - } - } - - if(updateDB) { - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = nullptr; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET maintank='%s' WHERE gid=%i LIMIT 1", - MainTankName.c_str(), GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group main tank: %s\n", errbuff); - - safe_delete_array(Query); - } -} - -void Group::DelegateMainAssist(const char *NewMainAssistName, uint8 toggle) -{ - // This method is called when the group leader Delegates the Main Assist role to a member of the group - // (or himself). All group members in the zone are notified of the new Main Assist and it is recorded - // in the group_leaders table so as to persist across zones. - // - - bool updateDB = false; - - if(!NewMainAssistName) - return; - - Mob *m = entity_list.GetMob(NewMainAssistName); - - if(!m) - return; - - if(MainAssistName != NewMainAssistName || !toggle) - updateDB = true; - - if(m->GetTarget()) - AssistTargetID = m->GetTarget()->GetID(); - else - AssistTargetID = 0; - - SetMainAssist(NewMainAssistName); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { - if(members[i] && members[i]->IsClient()) - { - NotifyMainAssist(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(GroupAssist, m, NewMainAssistName); - members[i]->CastToClient()->UpdateXTargetType(GroupAssistTarget, m->GetTarget()); - } - } - - if(updateDB) { - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = nullptr; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET assist='%s' WHERE gid=%i LIMIT 1", - MainAssistName.c_str(), GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group main assist: %s\n", errbuff); - - safe_delete_array(Query); - } -} - -void Group::DelegatePuller(const char *NewPullerName, uint8 toggle) -{ - // This method is called when the group leader Delegates the Puller role to a member of the group - // (or himself). All group members in the zone are notified of the new Puller and it is recorded - // in the group_leaders table so as to persist across zones. - // - - bool updateDB = false; - - if(!NewPullerName) - return; - - Mob *m = entity_list.GetMob(NewPullerName); - - if(!m) - return; - - if(PullerName != NewPullerName || !toggle) - updateDB = true; - - if(m->GetTarget()) - PullerTargetID = m->GetTarget()->GetID(); - else - PullerTargetID = 0; - - SetPuller(NewPullerName); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { - if(members[i] && members[i]->IsClient()) - { - NotifyPuller(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(Puller, m, NewPullerName); - members[i]->CastToClient()->UpdateXTargetType(PullerTarget, m->GetTarget()); - } - } - - if(updateDB) { - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = nullptr; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET puller='%s' WHERE gid=%i LIMIT 1", - PullerName.c_str(), GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group main puller: %s\n", errbuff); - - safe_delete_array(Query); - } - -} - -void Group::NotifyMainTank(Client *c, uint8 toggle) -{ - // Send a packet to the specified Client notifying them who the new Main Tank is. This causes the client to display - // a message with the name of the Main Tank. - // - - if(!c) - return; - - if(!MainTankName.size()) - return; - - if(c->GetClientVersion() < EQClientSoD) - { - if(toggle) - c->Message(0, "%s is now Main Tank.", MainTankName.c_str()); - else - c->Message(0, "%s is no longer Main Tank.", MainTankName.c_str()); - } - else - { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); - - GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; - - strn0cpy(grs->Name1, MainTankName.c_str(), sizeof(grs->Name1)); - - strn0cpy(grs->Name2, GetLeaderName(), sizeof(grs->Name2)); - - grs->RoleNumber = 1; - - grs->Toggle = toggle; - - c->QueuePacket(outapp); - - safe_delete(outapp); - } - -} - -void Group::NotifyMainAssist(Client *c, uint8 toggle) -{ - // Send a packet to the specified Client notifying them who the new Main Assist is. This causes the client to display - // a message with the name of the Main Assist. - // - - if(!c) - return; - - if(!MainAssistName.size()) - return; - - if(c->GetClientVersion() < EQClientSoD) - { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); - - DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; - - das->DelegateAbility = 0; - - das->MemberNumber = 0; - - das->Action = 0; - - das->EntityID = 0; - - strn0cpy(das->Name, MainAssistName.c_str(), sizeof(das->Name)); - - c->QueuePacket(outapp); - - safe_delete(outapp); - } - else - { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); - - GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; - - strn0cpy(grs->Name1, MainAssistName.c_str(), sizeof(grs->Name1)); - - strn0cpy(grs->Name2, GetLeaderName(), sizeof(grs->Name2)); - - grs->RoleNumber = 2; - - grs->Toggle = toggle; - - c->QueuePacket(outapp); - - safe_delete(outapp); - } - - NotifyAssistTarget(c); - -} - -void Group::NotifyPuller(Client *c, uint8 toggle) -{ - // Send a packet to the specified Client notifying them who the new Puller is. This causes the client to display - // a message with the name of the Puller. - // - - if(!c) - return; - - if(!PullerName.size()) - return; - - if(c->GetClientVersion() < EQClientSoD) - { - if(toggle) - c->Message(0, "%s is now Puller.", PullerName.c_str()); - else - c->Message(0, "%s is no longer Puller.", PullerName.c_str()); - } - else - { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); - - GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; - - strn0cpy(grs->Name1, PullerName.c_str(), sizeof(grs->Name1)); - - strn0cpy(grs->Name2, GetLeaderName(), sizeof(grs->Name2)); - - grs->RoleNumber = 3; - - grs->Toggle = toggle; - - c->QueuePacket(outapp); - - safe_delete(outapp); - } - -} - -void Group::UnDelegateMainTank(const char *OldMainTankName, uint8 toggle) -{ - // Called when the group Leader removes the Main Tank delegation. Sends a packet to each group member in the zone - // informing them of the change and update the group_leaders table. - // - if(OldMainTankName == MainTankName) { - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET maintank='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group main tank: %s\n", errbuff); - - safe_delete_array(Query); - - if(!toggle) { - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { - if(members[i] && members[i]->IsClient()) - { - NotifyMainTank(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(GroupTank, nullptr, ""); - members[i]->CastToClient()->UpdateXTargetType(GroupTankTarget, nullptr); - } - } - } - - SetMainTank(""); - } -} - -void Group::UnDelegateMainAssist(const char *OldMainAssistName, uint8 toggle) -{ - // Called when the group Leader removes the Main Assist delegation. Sends a packet to each group member in the zone - // informing them of the change and update the group_leaders table. - // - if(OldMainAssistName == MainAssistName) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); - - DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; - - das->DelegateAbility = 0; - - das->MemberNumber = 0; - - das->Action = 1; - - das->EntityID = 0; - - strn0cpy(das->Name, OldMainAssistName, sizeof(das->Name)); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - { - members[i]->CastToClient()->QueuePacket(outapp); - members[i]->CastToClient()->UpdateXTargetType(GroupAssist, nullptr, ""); - } - - safe_delete(outapp); - - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET assist='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group main assist: %s\n", errbuff); - - safe_delete_array(Query); - - if(!toggle) - { - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - NotifyMainAssist(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(GroupAssistTarget, nullptr); - } - } - } - - SetMainAssist(""); - } -} - -void Group::UnDelegatePuller(const char *OldPullerName, uint8 toggle) -{ - // Called when the group Leader removes the Puller delegation. Sends a packet to each group member in the zone - // informing them of the change and update the group_leaders table. - // - if(OldPullerName == PullerName) { - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET puller='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group main puller: %s\n", errbuff); - - safe_delete_array(Query); - - if(!toggle) { - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) { - if(members[i] && members[i]->IsClient()) - { - NotifyPuller(members[i]->CastToClient(), toggle); - members[i]->CastToClient()->UpdateXTargetType(Puller, nullptr, ""); - members[i]->CastToClient()->UpdateXTargetType(PullerTarget, nullptr); - } - } - } - - SetPuller(""); - } -} - -bool Group::IsNPCMarker(Client *c) -{ - // Returns true if the specified client has been delegated the NPC Marker Role - // - if(!c) - return false; - - if(NPCMarkerName.size()) - return(c->GetName() == NPCMarkerName); - - return false; - -} - -void Group::SetGroupAssistTarget(Mob *m) -{ - // Notify all group members in the zone of the new target the Main Assist has selected. - // - AssistTargetID = m ? m->GetID() : 0; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - NotifyAssistTarget(members[i]->CastToClient()); - } - } -} - -void Group::SetGroupTankTarget(Mob *m) -{ - TankTargetID = m ? m->GetID() : 0; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - members[i]->CastToClient()->UpdateXTargetType(GroupTankTarget, m); - } - } -} - -void Group::SetGroupPullerTarget(Mob *m) -{ - PullerTargetID = m ? m->GetID() : 0; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - members[i]->CastToClient()->UpdateXTargetType(PullerTarget, m); - } - } -} - -void Group::NotifyAssistTarget(Client *c) -{ - // Send a packet to the specified client notifying them of the group target selected by the Main Assist. - - if(!c) - return; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SetGroupTarget, sizeof(MarkNPC_Struct)); - - MarkNPC_Struct* mnpcs = (MarkNPC_Struct *)outapp->pBuffer; - - mnpcs->TargetID = AssistTargetID; - - mnpcs->Number = 0; - - c->QueuePacket(outapp); - - safe_delete(outapp); - - Mob *m = entity_list.GetMob(AssistTargetID); - - c->UpdateXTargetType(GroupAssistTarget, m); - -} - -void Group::NotifyTankTarget(Client *c) -{ - if(!c) - return; - - Mob *m = entity_list.GetMob(TankTargetID); - - c->UpdateXTargetType(GroupTankTarget, m); -} - -void Group::NotifyPullerTarget(Client *c) -{ - if(!c) - return; - - Mob *m = entity_list.GetMob(PullerTargetID); - - c->UpdateXTargetType(PullerTarget, m); -} - -void Group::DelegateMarkNPC(const char *NewNPCMarkerName) -{ - // Called when the group leader has delegated the Mark NPC ability to a group member. - // Notify all group members in the zone of the change and save the change in the group_leaders - // table to persist across zones. - // - if(NPCMarkerName.size() > 0) - UnDelegateMarkNPC(NPCMarkerName.c_str()); - - if(!NewNPCMarkerName) - return; - - SetNPCMarker(NewNPCMarkerName); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - NotifyMarkNPC(members[i]->CastToClient()); - - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET marknpc='%s' WHERE gid=%i LIMIT 1", - NewNPCMarkerName, GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to set group mark npc: %s\n", errbuff); - - safe_delete_array(Query); - -} - -void Group::NotifyMarkNPC(Client *c) -{ - // Notify the specified client who the group member is who has been delgated the Mark NPC ability. - - if(!c) - return; - - if(!NPCMarkerName.size()) - return; - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); - - DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; - - das->DelegateAbility = 1; - - das->MemberNumber = 0; - - das->Action = 0; - - das->EntityID = NPCMarkerID; - - strn0cpy(das->Name, NPCMarkerName.c_str(), sizeof(das->Name)); - - c->QueuePacket(outapp); - - safe_delete(outapp); - -} -void Group::SetNPCMarker(const char *NewNPCMarkerName) -{ - NPCMarkerName = NewNPCMarkerName; - - Client *m = entity_list.GetClientByName(NPCMarkerName.c_str()); - - if(!m) - NPCMarkerID = 0; - else - NPCMarkerID = m->GetID(); -} - -void Group::UnDelegateMarkNPC(const char *OldNPCMarkerName) -{ - // Notify all group members in the zone that the Mark NPC ability has been rescinded from the specified - // group member. - - if(!OldNPCMarkerName) - return; - - if(!NPCMarkerName.size()) - return; - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); - - DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; - - das->DelegateAbility = 1; - - das->MemberNumber = 0; - - das->Action = 1; - - das->EntityID = 0; - - strn0cpy(das->Name, OldNPCMarkerName, sizeof(das->Name)); - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - members[i]->CastToClient()->QueuePacket(outapp); - - safe_delete(outapp); - - NPCMarkerName.clear(); - - char errbuff[MYSQL_ERRMSG_SIZE]; - - char *Query = 0; - - if (!database.RunQuery(Query, MakeAnyLenString(&Query, "UPDATE group_leaders SET marknpc='' WHERE gid=%i LIMIT 1", - GetID()), errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to clear group marknpc: %s\n", errbuff); - - safe_delete_array(Query); -} - -void Group::SaveGroupLeaderAA() -{ - // Stores the Group Leaders Leadership AA data from the Player Profile as a blob in the group_leaders table. - // This is done so that group members not in the same zone as the Leader still have access to this information. - - char *Query = new char[200 + sizeof(GroupLeadershipAA_Struct)*2]; - - char *End = Query; - - End += sprintf(End, "UPDATE group_leaders SET leadershipaa='"); - - End += database.DoEscapeString(End, (char*)&LeaderAbilities, sizeof(GroupLeadershipAA_Struct)); - - End += sprintf(End,"' WHERE gid=%i LIMIT 1", GetID()); - - char errbuff[MYSQL_ERRMSG_SIZE]; - if (!database.RunQuery(Query, End - Query, errbuff)) - LogFile->write(EQEMuLog::Error, "Unable to store LeadershipAA: %s\n", errbuff); - - safe_delete_array(Query); -} - -void Group::UnMarkNPC(uint16 ID) -{ - // Called from entity_list when the mob with the specified ID is being destroyed. - // - // If the given mob has been marked by this group, it is removed from the list of marked NPCs. - // The primary reason for doing this is so that when a new group member joins or zones in, we - // send them correct details of which NPCs are currently marked. - - if(AssistTargetID == ID) - AssistTargetID = 0; - - - if(TankTargetID == ID) - TankTargetID = 0; - - if(PullerTargetID == ID) - PullerTargetID = 0; - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - { - if(MarkedNPCs[i] == ID) - { - MarkedNPCs[i] = 0; - UpdateXTargetMarkedNPC(i + 1, nullptr); - } - } -} - -void Group::SendMarkedNPCsToMember(Client *c, bool Clear) -{ - // Send the Entity IDs of the NPCs marked by the Group Leader or delegate to the specified client. - // If Clear == true, then tell the client to unmark the NPCs (when a member disbands). - // - // - if(!c) - return; - - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct)); - - MarkNPC_Struct *mnpcs = (MarkNPC_Struct *)outapp->pBuffer; - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - { - if(MarkedNPCs[i]) - { - mnpcs->TargetID = MarkedNPCs[i]; - - Mob *m = entity_list.GetMob(MarkedNPCs[i]); - - if(m) - sprintf(mnpcs->Name, "%s", m->GetCleanName()); - - if(!Clear) - mnpcs->Number = i + 1; - else - mnpcs->Number = 0; - - c->QueuePacket(outapp); - c->UpdateXTargetType((mnpcs->Number == 1) ? GroupMarkTarget1 : ((mnpcs->Number == 2) ? GroupMarkTarget2 : GroupMarkTarget3), m); - } - } - - safe_delete(outapp); -} - -void Group::ClearAllNPCMarks() -{ - // This method is designed to be called when the number of members in the group drops below 3 and leadership AA - // may no longer be used. It removes all NPC marks. - // - for(uint8 i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - SendMarkedNPCsToMember(members[i]->CastToClient(), true); - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - { - if(MarkedNPCs[i]) - { - Mob* m = entity_list.GetMob(MarkedNPCs[i]); - - if(m) - m->IsTargeted(-1); - } - - MarkedNPCs[i] = 0; - } - -} - -int8 Group::GetNumberNeedingHealedInGroup(int8 hpr, bool includePets) { - int8 needHealed = 0; - - for( int i = 0; iqglobal) { - - if(members[i]->GetHPRatio() <= hpr) - needHealed++; - - if(includePets) { - if(members[i]->GetPet() && members[i]->GetPet()->GetHPRatio() <= hpr) { - needHealed++; - } - } - } - } - - - return needHealed; -} - -void Group::UpdateGroupAAs() -{ - // This method updates the Groups Leadership abilities from the Player Profile of the Leader. - // - Mob *m = GetLeader(); - - if(m && m->IsClient()) - m->CastToClient()->GetGroupAAs(&LeaderAbilities); - else - memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct)); - - SaveGroupLeaderAA(); -} - -void Group::QueueHPPacketsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app) -{ - // Send a mobs HP packets to group members if the leader has the NPC Health AA and the mob is the - // target of the group's main assist, or is marked, and the member doesn't already have the mob targeted. - - if(!sender || !app || !GetLeadershipAA(groupAANPCHealth)) - return; - - uint16 SenderID = sender->GetID(); - - if(SenderID != AssistTargetID) - { - bool Marked = false; - - for(int i = 0; i < MAX_MARKED_NPCS; ++i) - { - if(MarkedNPCs[i] == SenderID) - { - Marked = true; - break; - } - } - - if(!Marked) - return; - - } - - for(unsigned int i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(members[i] && members[i]->IsClient()) - { - if(!members[i]->GetTarget() || (members[i]->GetTarget()->GetID() != SenderID)) - { - members[i]->CastToClient()->QueuePacket(app); - } - } - -} - -void Group::ChangeLeader(Mob* newleader) -{ - // this changes the current group leader, notifies other members, and updates leadship AA - - // if the new leader is invalid, do nothing - if (!newleader) - return; - - Mob* oldleader = GetLeader(); - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); - GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer; - gu->action = groupActMakeLeader; - - strcpy(gu->membername, newleader->GetName()); - strcpy(gu->yourname, oldleader->GetName()); - SetLeader(newleader); - database.SetGroupLeaderName(GetID(), newleader->GetName()); - UpdateGroupAAs(); - gu->leader_aas = LeaderAbilities; - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] && members[i]->IsClient()) - { - if(members[i]->CastToClient()->GetClientVersion() >= EQClientSoD) - members[i]->CastToClient()->SendGroupLeaderChangePacket(newleader->GetName()); - - members[i]->CastToClient()->QueuePacket(outapp); - } - } - safe_delete(outapp); -} - -const char *Group::GetClientNameByIndex(uint8 index) -{ - return membername[index]; -} - -void Group::UpdateXTargetMarkedNPC(uint32 Number, Mob *m) -{ - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(members[i] && members[i]->IsClient()) - { - members[i]->CastToClient()->UpdateXTargetType((Number == 1) ? GroupMarkTarget1 : ((Number == 2) ? GroupMarkTarget2 : GroupMarkTarget3), m); - } - } - -} - -void Group::SetMainTank(const char *NewMainTankName) -{ - MainTankName = NewMainTankName; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(!strncasecmp(membername[i], NewMainTankName, 64)) - MemberRoles[i] |= RoleTank; - else - MemberRoles[i] &= ~RoleTank; - } -} - -void Group::SetMainAssist(const char *NewMainAssistName) -{ - MainAssistName = NewMainAssistName; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(!strncasecmp(membername[i], NewMainAssistName, 64)) - MemberRoles[i] |= RoleAssist; - else - MemberRoles[i] &= ~RoleAssist; - } -} - -void Group::SetPuller(const char *NewPullerName) -{ - PullerName = NewPullerName; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if(!strncasecmp(membername[i], NewPullerName, 64)) - MemberRoles[i] |= RolePuller; - else - MemberRoles[i] &= ~RolePuller; - } -} - -bool Group::HasRole(Mob *m, uint8 Role) -{ - if(!m) - return false; - - for(uint32 i = 0; i < MAX_GROUP_MEMBERS; ++i) - { - if((m == members[i]) && (MemberRoles[i] & Role)) - return true; - } - return false; -} - diff --git a/zone/npcx.cpp b/zone/npcx.cpp deleted file mode 100644 index 7d2766854..000000000 --- a/zone/npcx.cpp +++ /dev/null @@ -1,2492 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#include "../common/debug.h" -#include -#include -#include -#include -#include "../common/moremath.h" -#include -#include "../common/packet_dump_file.h" -#include "zone.h" -#ifdef _WINDOWS -#define snprintf _snprintf -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#else -#include -#include -#endif - -#include "npc.h" -#include "map.h" -#include "entity.h" -#include "masterentity.h" -#include "../common/spdat.h" -#include "../common/bodytypes.h" -#include "spawngroup.h" -#include "../common/MiscFunctions.h" -#include "../common/StringUtil.h" -#include "../common/rulesys.h" -#include "StringIDs.h" - -//#define SPELLQUEUE //Use only if you want to be spammed by spell testing - - -extern Zone* zone; -extern volatile bool ZoneLoaded; -extern EntityList entity_list; - -#include "QuestParserCollection.h" - -NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float heading, int iflymode, bool IsCorpse) -: Mob(d->name, - d->lastname, - d->max_hp, - d->max_hp, - d->gender, - d->race, - d->class_, - (bodyType)d->bodytype, - d->deity, - d->level, - d->npc_id, - d->size, - d->runspeed, - heading, - x, - y, - z, - d->light, - d->texture, - d->helmtexture, - d->AC, - d->ATK, - d->STR, - d->STA, - d->DEX, - d->AGI, - d->INT, - d->WIS, - d->CHA, - d->haircolor, - d->beardcolor, - d->eyecolor1, - d->eyecolor2, - d->hairstyle, - d->luclinface, - d->beard, - d->drakkin_heritage, - d->drakkin_tattoo, - d->drakkin_details, - (uint32*)d->armor_tint, - 0, - d->see_invis, // pass see_invis/see_ivu flags to mob constructor - d->see_invis_undead, - d->see_hide, - d->see_improved_hide, - d->hp_regen, - d->mana_regen, - d->qglobal, - d->maxlevel, - d->scalerate ), - attacked_timer(CombatEventTimer_expire), - swarm_timer(100), - classattack_timer(1000), - knightattack_timer(1000), - assist_timer(AIassistcheck_delay), - qglobal_purge_timer(30000), - sendhpupdate_timer(1000), - enraged_timer(1000), - taunt_timer(TauntReuseTime * 1000) -{ - //What is the point of this, since the names get mangled.. - Mob* mob = entity_list.GetMob(name); - if(mob != 0) - entity_list.RemoveEntity(mob->GetID()); - - int moblevel=GetLevel(); - - NPCTypedata = d; - NPCTypedata_ours = nullptr; - respawn2 = in_respawn; - swarm_timer.Disable(); - - taunting = false; - proximity = nullptr; - copper = 0; - silver = 0; - gold = 0; - platinum = 0; - max_dmg = d->max_dmg; - min_dmg = d->min_dmg; - attack_count = d->attack_count; - grid = 0; - wp_m = 0; - max_wp=0; - save_wp = 0; - spawn_group = 0; - swarmInfoPtr = nullptr; - spellscale = d->spellscale; - healscale = d->healscale; - - logging_enabled = NPC_DEFAULT_LOGGING_ENABLED; - - pAggroRange = d->aggroradius; - pAssistRange = d->assistradius; - findable = d->findable; - trackable = d->trackable; - - MR = d->MR; - CR = d->CR; - DR = d->DR; - FR = d->FR; - PR = d->PR; - Corrup = d->Corrup; - PhR = d->PhR; - - STR = d->STR; - STA = d->STA; - AGI = d->AGI; - DEX = d->DEX; - INT = d->INT; - WIS = d->WIS; - CHA = d->CHA; - npc_mana = d->Mana; - - //quick fix of ordering if they screwed it up in the DB - if(max_dmg < min_dmg) { - int tmp = min_dmg; - min_dmg = max_dmg; - max_dmg = tmp; - } - - // Max Level and Stat Scaling if maxlevel is set - if(maxlevel > level) - { - LevelScale(); - } - - // Set Resists if they are 0 in the DB - CalcNPCResists(); - - // Set Mana and HP Regen Rates if they are 0 in the DB - CalcNPCRegen(); - - // Set Min and Max Damage if they are 0 in the DB - if(max_dmg == 0){ - CalcNPCDamage(); - } - - accuracy_rating = d->accuracy_rating; - ATK = d->ATK; - - CalcMaxMana(); - SetMana(GetMaxMana()); - - MerchantType = d->merchanttype; - merchant_open = GetClass() == MERCHANT; - adventure_template_id = d->adventure_template; - org_x = x; - org_y = y; - org_z = z; - flymode = iflymode; - guard_x = -1; //just some value we might be able to recongize as "unset" - guard_y = -1; - guard_z = -1; - guard_heading = 0; - guard_anim = eaStanding; - roambox_distance = 0; - roambox_max_x = -2; - roambox_max_y = -2; - roambox_min_x = -2; - roambox_min_y = -2; - roambox_movingto_x = -2; - roambox_movingto_y = -2; - roambox_min_delay = 1000; - roambox_delay = 1000; - org_heading = heading; - p_depop = false; - loottable_id = d->loottable_id; - - no_target_hotkey = d->no_target_hotkey; - - primary_faction = 0; - SetNPCFactionID(d->npc_faction_id); - - npc_spells_id = 0; - HasAISpell = false; - HasAISpellEffects = false; - - if(GetClass() == MERCERNARY_MASTER && RuleB(Mercs, AllowMercs)) - { - LoadMercTypes(); - LoadMercs(); - } - - SpellFocusDMG = 0; - SpellFocusHeal = 0; - - pet_spell_id = 0; - - delaytimer = false; - combat_event = false; - attack_speed = d->attack_speed; - slow_mitigation = d->slow_mitigation; - - EntityList::RemoveNumbers(name); - entity_list.MakeNameUnique(name); - - npc_aggro = d->npc_aggro; - - if(!IsMerc()) - AI_Start(); - - d_meele_texture1 = d->d_meele_texture1; - d_meele_texture2 = d->d_meele_texture2; - memset(equipment, 0, sizeof(equipment)); - prim_melee_type = d->prim_melee_type; - sec_melee_type = d->sec_melee_type; - - // If Melee Textures are not set, set attack type to Hand to Hand as default - if(!d_meele_texture1) - prim_melee_type = 28; - if(!d_meele_texture2) - sec_melee_type = 28; - - //give NPCs skill values... - int r; - for(r = 0; r <= HIGHEST_SKILL; r++) { - skills[r] = database.GetSkillCap(GetClass(),(SkillUseTypes)r,moblevel); - } - - if(d->trap_template > 0) - { - std::map >::iterator trap_ent_iter; - std::list trap_list; - - trap_ent_iter = zone->ldon_trap_entry_list.find(d->trap_template); - if(trap_ent_iter != zone->ldon_trap_entry_list.end()) - { - trap_list = trap_ent_iter->second; - if(trap_list.size() > 0) - { - std::list::iterator trap_list_iter = trap_list.begin(); - std::advance(trap_list_iter, MakeRandomInt(0, trap_list.size() - 1)); - LDoNTrapTemplate* tt = (*trap_list_iter); - if(tt) - { - if((uint8)tt->spell_id > 0) - { - ldon_trapped = true; - ldon_spell_id = tt->spell_id; - } - else - { - ldon_trapped = false; - ldon_spell_id = 0; - } - - ldon_trap_type = (uint8)tt->type; - if(tt->locked > 0) - { - ldon_locked = true; - ldon_locked_skill = tt->skill; - } - else - { - ldon_locked = false; - ldon_locked_skill = 0; - } - ldon_trap_detected = 0; - } - } - else - { - ldon_trapped = false; - ldon_trap_type = 0; - ldon_spell_id = 0; - ldon_locked = false; - ldon_locked_skill = 0; - ldon_trap_detected = 0; - } - } - else - { - ldon_trapped = false; - ldon_trap_type = 0; - ldon_spell_id = 0; - ldon_locked = false; - ldon_locked_skill = 0; - ldon_trap_detected = 0; - } - } - else - { - ldon_trapped = false; - ldon_trap_type = 0; - ldon_spell_id = 0; - ldon_locked = false; - ldon_locked_skill = 0; - ldon_trap_detected = 0; - } - reface_timer = new Timer(15000); - reface_timer->Disable(); - qGlobals = nullptr; - guard_x_saved = 0; - guard_y_saved = 0; - guard_z_saved = 0; - guard_heading_saved = 0; - SetEmoteID(d->emoteid); - InitializeBuffSlots(); - CalcBonuses(); -} - -NPC::~NPC() -{ - AI_Stop(); - - if(proximity != nullptr) { - entity_list.RemoveProximity(GetID()); - safe_delete(proximity); - } - - safe_delete(NPCTypedata_ours); - - { - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end; ++cur) { - ServerLootItem_Struct* item = *cur; - safe_delete(item); - } - itemlist.clear(); - } - - { - std::list::iterator cur,end; - cur = faction_list.begin(); - end = faction_list.end(); - for(; cur != end; ++cur) { - struct NPCFaction* fac = *cur; - safe_delete(fac); - } - faction_list.clear(); - } - - safe_delete(reface_timer); - safe_delete(swarmInfoPtr); - safe_delete(qGlobals); - //Moved this from ~Mob, because it could cause a crash in some cases where a hate list was still used and that mob was the only one on the hate list. - entity_list.RemoveFromTargets(this, true); - UninitializeBuffSlots(); -} - -void NPC::SetTarget(Mob* mob) { - if(mob == GetTarget()) //dont bother if they are allready our target - return; - - //our target is already set, do not turn from the course, unless our current target is dead. - if(GetSwarmInfo() && GetTarget() && (GetTarget()->GetHP() > 0)) { - Mob *targ = entity_list.GetMob(GetSwarmInfo()->target); - if(targ != mob){ - return; - } - } - - if (mob) { - SetAttackTimer(); - } else { - ranged_timer.Disable(); - //attack_timer.Disable(); - attack_dw_timer.Disable(); - } - Mob::SetTarget(mob); -} - -ServerLootItem_Struct* NPC::GetItem(int slot_id) { - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end; ++cur) { - ServerLootItem_Struct* item = *cur; - if (item->equipSlot == slot_id) { - return item; - } - } - return(nullptr); -} - -void NPC::RemoveItem(uint32 item_id, uint16 quantity, uint16 slot) { - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end; ++cur) { - ServerLootItem_Struct* item = *cur; - if (item->item_id == item_id && slot <= 0 && quantity <= 0) { - itemlist.erase(cur); - return; - } - else if (item->item_id == item_id && item->equipSlot == slot && quantity >= 1) { - //std::cout<<"NPC::RemoveItem"<<" equipSlot:"<equipSlot<<" quantity:"<< quantity<charges <= quantity) - itemlist.erase(cur); - else - item->charges -= quantity; - return; - } - } -} - -void NPC::CheckMinMaxLevel(Mob *them) -{ - if(them == nullptr || !them->IsClient()) - return; - - uint16 themlevel = them->GetLevel(); - uint8 material; - - std::list::iterator cur = itemlist.begin(); - while(cur != itemlist.end()) - { - if(!(*cur)) - return; - - if(themlevel < (*cur)->minlevel || themlevel > (*cur)->maxlevel) - { - material = Inventory::CalcMaterialFromSlot((*cur)->equipSlot); - if(material != 0xFF) - SendWearChange(material); - - cur = itemlist.erase(cur); - continue; - } - ++cur; - } - -} - -void NPC::ClearItemList() { - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end; ++cur) { - ServerLootItem_Struct* item = *cur; - safe_delete(item); - } - itemlist.clear(); -} - -void NPC::QueryLoot(Client* to) { - int x = 0; - to->Message(0, "Coin: %ip %ig %is %ic", platinum, gold, silver, copper); - - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end; ++cur) { - const Item_Struct* item = database.GetItem((*cur)->item_id); - if (item) - if (to->GetClientVersion() >= EQClientRoF) - { - to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X0000000000000000000000000000000000000000000000000%s%c",(*cur)->minlevel, (*cur)->maxlevel, (int) item->ID,0x12, item->ID, item->Name, 0x12); - } - else if (to->GetClientVersion() >= EQClientSoF) - { - to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X00000000000000000000000000000000000000000000%s%c",(*cur)->minlevel, (*cur)->maxlevel, (int) item->ID,0x12, item->ID, item->Name, 0x12); - } - else - { - to->Message(0, "minlvl: %i maxlvl: %i %i: %c%06X000000000000000000000000000000000000000%s%c",(*cur)->minlevel, (*cur)->maxlevel, (int) item->ID,0x12, item->ID, item->Name, 0x12); - } - else - LogFile->write(EQEMuLog::Error, "Database error, invalid item"); - x++; - } - to->Message(0, "%i items on %s.", x, GetName()); -} - -void NPC::AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_platinum) { - if(in_copper >= 0) - copper = in_copper; - else - copper = 0; - - if(in_silver >= 0) - silver = in_silver; - else - silver = 0; - - if(in_gold >= 0) - gold = in_gold; - else - gold = 0; - - if(in_platinum >= 0) - platinum = in_platinum; - else - platinum = 0; -} - -void NPC::AddCash() { - copper = MakeRandomInt(1, 100); - silver = MakeRandomInt(1, 50); - gold = MakeRandomInt(1, 10); - platinum = MakeRandomInt(1, 5); -} - -void NPC::RemoveCash() { - copper = 0; - silver = 0; - gold = 0; - platinum = 0; -} - -bool NPC::Process() -{ - if (IsStunned() && stunned_timer.Check()) - { - this->stunned = false; - this->stunned_timer.Disable(); - this->spun_timer.Disable(); - } - - if (p_depop) - { - Mob* owner = entity_list.GetMob(this->ownerid); - if (owner != 0) - { - //if(GetBodyType() != BT_SwarmPet) - // owner->SetPetID(0); - this->ownerid = 0; - this->petid = 0; - } - return false; - } - - SpellProcess(); - - if(tic_timer.Check()) - { - BuffProcess(); - - if(curfp) - ProcessFlee(); - - uint32 bonus = 0; - - if(GetAppearance() == eaSitting) - bonus+=3; - - int32 OOCRegen = 0; - if(oocregen > 0){ //should pull from Mob class - OOCRegen += GetMaxHP() * oocregen / 100; - } - //Lieka Edit:Fixing NPC regen.NPCs should regen to full during a set duration, not based on their HPs.Increase NPC's HPs by % of total HPs / tick. - if((GetHP() < GetMaxHP()) && !IsPet()) { - if(!IsEngaged()) {//NPC out of combat - if(hp_regen > OOCRegen) - SetHP(GetHP() + hp_regen); - else - SetHP(GetHP() + OOCRegen); - } else - SetHP(GetHP()+hp_regen); - } else if(GetHP() < GetMaxHP() && GetOwnerID() !=0) { - if(!IsEngaged()) //pet - SetHP(GetHP()+hp_regen+bonus+(GetLevel()/5)); - else - SetHP(GetHP()+hp_regen+bonus); - } else - SetHP(GetHP()+hp_regen); - - if(GetMana() < GetMaxMana()) { - SetMana(GetMana()+mana_regen+bonus); - } - - - if(zone->adv_data && !p_depop) - { - ServerZoneAdventureDataReply_Struct* ds = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; - if(ds->type == Adventure_Rescue && ds->data_id == GetNPCTypeID()) - { - Mob *o = GetOwner(); - if(o && o->IsClient()) - { - float x_diff = ds->dest_x - GetX(); - float y_diff = ds->dest_y - GetY(); - float z_diff = ds->dest_z - GetZ(); - float dist = ((x_diff * x_diff) + (y_diff * y_diff) + (z_diff * z_diff)); - if(dist < RuleR(Adventure, DistanceForRescueComplete)) - { - zone->DoAdventureCountIncrease(); - Say("You don't know what this means to me. Thank you so much for finding and saving me from" - " this wretched place. I'll find my way from here."); - Depop(); - } - } - } - } - } - - if (sendhpupdate_timer.Check() && (IsTargeted() || (IsPet() && GetOwner() && GetOwner()->IsClient()))) { - if(!IsFullHP || cur_hp 999) - viral_timer_counter = 0; - } - - if(projectile_timer.Check()) - SpellProjectileEffect(); - - if(spellbonuses.GravityEffect == 1) { - if(gravity_timer.Check()) - DoGravityEffect(); - } - - if(reface_timer->Check() && !IsEngaged() && (guard_x == GetX() && guard_y == GetY() && guard_z == GetZ())) { - SetHeading(guard_heading); - SendPosition(); - reface_timer->Disable(); - } - - if (IsMezzed()) - return true; - - if(IsStunned()) { - if(spun_timer.Check()) - Spin(); - return true; - } - - if (enraged_timer.Check()){ - ProcessEnrage(); - } - - //Handle assists... - if(assist_timer.Check() && IsEngaged() && !Charmed()) { - entity_list.AIYellForHelp(this, GetTarget()); - } - - if(qGlobals) - { - if(qglobal_purge_timer.Check()) - { - qGlobals->PurgeExpiredGlobals(); - } - } - - AI_Process(); - - return true; -} - -uint32 NPC::CountLoot() { - return(itemlist.size()); -} - -void NPC::Depop(bool StartSpawnTimer) { - uint16 emoteid = this->GetEmoteID(); - if(emoteid != 0) - this->DoNPCEmote(ONDESPAWN,emoteid); - p_depop = true; - if (StartSpawnTimer) { - if (respawn2 != 0) { - respawn2->DeathReset(); - } - } -} - -bool NPC::DatabaseCastAccepted(int spell_id) { - for (int i=0; i < 12; i++) { - switch(spells[spell_id].effectid[i]) { - case SE_Stamina: { - if(IsEngaged() && GetHPRatio() < 100) - return true; - else - return false; - break; - } - case SE_CurrentHPOnce: - case SE_CurrentHP: { - if(this->GetHPRatio() < 100 && spells[spell_id].buffduration == 0) - return true; - else - return false; - break; - } - - case SE_HealOverTime: { - if(this->GetHPRatio() < 100) - return true; - else - return false; - break; - } - case SE_DamageShield: { - return true; - } - case SE_NecPet: - case SE_SummonPet: { - if(GetPet()){ -#ifdef SPELLQUEUE - printf("%s: Attempted to make a second pet, denied.\n",GetName()); -#endif - return false; - } - break; - } - case SE_LocateCorpse: - case SE_SummonCorpse: { - return false; //Pfft, npcs don't need to summon corpses/locate corpses! - break; - } - default: - if(spells[spell_id].goodEffect == 1 && !(spells[spell_id].buffduration == 0 && this->GetHPRatio() == 100) && !IsEngaged()) - return true; - return false; - } - } - return false; -} - -NPC* NPC::SpawnNPC(const char* spawncommand, float in_x, float in_y, float in_z, float in_heading, Client* client) { - if(spawncommand == 0 || spawncommand[0] == 0) { - return 0; - } - else { - Seperator sep(spawncommand); - //Lets see if someone didn't fill out the whole #spawn function properly - if (!sep.IsNumber(1)) - sprintf(sep.arg[1],"1"); - if (!sep.IsNumber(2)) - sprintf(sep.arg[2],"1"); - if (!sep.IsNumber(3)) - sprintf(sep.arg[3],"0"); - if (atoi(sep.arg[4]) > 2100000000 || atoi(sep.arg[4]) <= 0) - sprintf(sep.arg[4]," "); - if (!strcmp(sep.arg[5],"-")) - sprintf(sep.arg[5]," "); - if (!sep.IsNumber(5)) - sprintf(sep.arg[5]," "); - if (!sep.IsNumber(6)) - sprintf(sep.arg[6],"1"); - if (!sep.IsNumber(8)) - sprintf(sep.arg[8],"0"); - if (!sep.IsNumber(9)) - sprintf(sep.arg[9], "0"); - if (!sep.IsNumber(7)) - sprintf(sep.arg[7],"0"); - if (!strcmp(sep.arg[4],"-")) - sprintf(sep.arg[4]," "); - if (!sep.IsNumber(10)) // bodytype - sprintf(sep.arg[10], "0"); - //Calc MaxHP if client neglected to enter it... - if (!sep.IsNumber(4)) { - //Stolen from Client::GetMaxHP... - uint8 multiplier = 0; - int tmplevel = atoi(sep.arg[2]); - switch(atoi(sep.arg[5])) - { - case WARRIOR: - if (tmplevel < 20) - multiplier = 22; - else if (tmplevel < 30) - multiplier = 23; - else if (tmplevel < 40) - multiplier = 25; - else if (tmplevel < 53) - multiplier = 27; - else if (tmplevel < 57) - multiplier = 28; - else - multiplier = 30; - break; - - case DRUID: - case CLERIC: - case SHAMAN: - multiplier = 15; - break; - - case PALADIN: - case SHADOWKNIGHT: - if (tmplevel < 35) - multiplier = 21; - else if (tmplevel < 45) - multiplier = 22; - else if (tmplevel < 51) - multiplier = 23; - else if (tmplevel < 56) - multiplier = 24; - else if (tmplevel < 60) - multiplier = 25; - else - multiplier = 26; - break; - - case MONK: - case BARD: - case ROGUE: - //case BEASTLORD: - if (tmplevel < 51) - multiplier = 18; - else if (tmplevel < 58) - multiplier = 19; - else - multiplier = 20; - break; - - case RANGER: - if (tmplevel < 58) - multiplier = 20; - else - multiplier = 21; - break; - - case MAGICIAN: - case WIZARD: - case NECROMANCER: - case ENCHANTER: - multiplier = 12; - break; - - default: - if (tmplevel < 35) - multiplier = 21; - else if (tmplevel < 45) - multiplier = 22; - else if (tmplevel < 51) - multiplier = 23; - else if (tmplevel < 56) - multiplier = 24; - else if (tmplevel < 60) - multiplier = 25; - else - multiplier = 26; - break; - } - sprintf(sep.arg[4],"%i",5+multiplier*atoi(sep.arg[2])+multiplier*atoi(sep.arg[2])*75/300); - } - - // Autoselect NPC Gender - if (sep.arg[5][0] == 0) { - sprintf(sep.arg[5], "%i", (int) Mob::GetDefaultGender(atoi(sep.arg[1]))); - } - - //Time to create the NPC!! - NPCType* npc_type = new NPCType; - memset(npc_type, 0, sizeof(NPCType)); - - strncpy(npc_type->name, sep.arg[0], 60); - npc_type->cur_hp = atoi(sep.arg[4]); - npc_type->max_hp = atoi(sep.arg[4]); - npc_type->race = atoi(sep.arg[1]); - npc_type->gender = atoi(sep.arg[5]); - npc_type->class_ = atoi(sep.arg[6]); - npc_type->deity = 1; - npc_type->level = atoi(sep.arg[2]); - npc_type->npc_id = 0; - npc_type->loottable_id = 0; - npc_type->texture = atoi(sep.arg[3]); - npc_type->light = 0; - npc_type->runspeed = 1.25; - npc_type->d_meele_texture1 = atoi(sep.arg[7]); - npc_type->d_meele_texture2 = atoi(sep.arg[8]); - npc_type->merchanttype = atoi(sep.arg[9]); - npc_type->bodytype = atoi(sep.arg[10]); - - npc_type->STR = 150; - npc_type->STA = 150; - npc_type->DEX = 150; - npc_type->AGI = 150; - npc_type->INT = 150; - npc_type->WIS = 150; - npc_type->CHA = 150; - - npc_type->prim_melee_type = 28; - npc_type->sec_melee_type = 28; - - NPC* npc = new NPC(npc_type, 0, in_x, in_y, in_z, in_heading/8, FlyMode3); - npc->GiveNPCTypeData(npc_type); - - entity_list.AddNPC(npc); - - if (client) { - // Notify client of spawn data - client->Message(0, "New spawn:"); - client->Message(0, "Name: %s", npc->name); - client->Message(0, "Race: %u", npc->race); - client->Message(0, "Level: %u", npc->level); - client->Message(0, "Material: %u", npc->texture); - client->Message(0, "Current/Max HP: %i", npc->max_hp); - client->Message(0, "Gender: %u", npc->gender); - client->Message(0, "Class: %u", npc->class_); - client->Message(0, "Weapon Item Number: %u/%u", npc->d_meele_texture1, npc->d_meele_texture2); - client->Message(0, "MerchantID: %u", npc->MerchantType); - client->Message(0, "Bodytype: %u", npc->bodytype); - } - - return npc; - } -} - -uint32 ZoneDatabase::NPCSpawnDB(uint8 command, const char* zone, uint32 zone_version, Client *c, NPC* spawn, uint32 extra) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - uint32 tmp = 0; - uint32 tmp2 = 0; - uint32 last_insert_id = 0; - switch (command) { - case 0: { // Create a new NPC and add all spawn related data - uint32 npc_type_id = 0; - uint32 spawngroupid; - if (extra && c && c->GetZoneID()) - { - // Set an npc_type ID within the standard range for the current zone if possible (zone_id * 1000) - int starting_npc_id = c->GetZoneID() * 1000; - if (RunQuery(query, MakeAnyLenString(&query, "SELECT MAX(id) FROM npc_types WHERE id >= %i AND id < %i", starting_npc_id, (starting_npc_id + 1000)), errbuf, &result)) { - row = mysql_fetch_row(result); - if(row) - { - if (row[0]) - { - npc_type_id = atoi(row[0]) + 1; - // Prevent the npc_type id from exceeding the range for this zone - if (npc_type_id >= (starting_npc_id + 1000)) - { - npc_type_id = 0; - } - } - else - { - // row[0] is nullptr - No npc_type IDs set in this range yet - npc_type_id = starting_npc_id; - } - } - - safe_delete_array(query); - mysql_free_result(result); - } - } - char tmpstr[64]; - EntityList::RemoveNumbers(strn0cpy(tmpstr, spawn->GetName(), sizeof(tmpstr))); - if (npc_type_id) - { - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO npc_types (id, name, level, race, class, hp, gender, texture, helmtexture, size, loottable_id, merchant_id, face, runspeed, prim_melee_type, sec_melee_type) values(%i,\"%s\",%i,%i,%i,%i,%i,%i,%i,%f,%i,%i,%i,%f,%i,%i)", npc_type_id, tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28), errbuf, 0, 0, &npc_type_id)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - } - else - { - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO npc_types (name, level, race, class, hp, gender, texture, helmtexture, size, loottable_id, merchant_id, face, runspeed, prim_melee_type, sec_melee_type) values(\"%s\",%i,%i,%i,%i,%i,%i,%i,%f,%i,%i,%i,%f,%i,%i)", tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28), errbuf, 0, 0, &npc_type_id)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - } - if(c) c->LogSQL(query); - safe_delete_array(query); - snprintf(tmpstr, sizeof(tmpstr), "%s-%s", zone, spawn->GetName()); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawngroup (id, name) values(%i, '%s')", tmp, tmpstr), errbuf, 0, 0, &spawngroupid)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) values('%s', %u, %f, %f, %f, %i, %f, %i)", zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), 1200, spawn->GetHeading(), spawngroupid), errbuf, 0, 0, &tmp)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawnentry (spawngroupID, npcID, chance) values(%i, %i, %i)", spawngroupid, npc_type_id, 100), errbuf, 0)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - return true; - break; - } - case 1:{ // Add new spawn group and spawn point for an existing NPC Type ID - tmp2 = spawn->GetNPCTypeID(); - char tmpstr[64]; - snprintf(tmpstr, sizeof(tmpstr), "%s%s%i", zone, spawn->GetName(),Timer::GetCurrentTime()); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawngroup (name) values('%s')", tmpstr), errbuf, 0, 0, &last_insert_id)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - - uint32 respawntime = 0; - uint32 spawnid = 0; - if (extra) - respawntime = extra; - else if(spawn->respawn2 && spawn->respawn2->RespawnTimer() != 0) - respawntime = spawn->respawn2->RespawnTimer(); - else - respawntime = 1200; - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) values('%s', %u, %f, %f, %f, %i, %f, %i)", zone, zone_version, spawn->GetX(), spawn->GetY(), spawn->GetZ(), respawntime, spawn->GetHeading(), last_insert_id), errbuf, 0, 0, &spawnid)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawnentry (spawngroupID, npcID, chance) values(%i, %i, %i)", last_insert_id, tmp2, 100), errbuf, 0)) { - LogFile->write(EQEMuLog::Error, "NPCSpawnDB Error: %s %s", query, errbuf); - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - return spawnid; - break; - } - case 2: { // Update npc_type appearance and other data on targeted spawn - if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE npc_types SET name=\"%s\", level=%i, race=%i, class=%i, hp=%i, gender=%i, texture=%i, helmtexture=%i, size=%i, loottable_id=%i, merchant_id=%i, face=%i, WHERE id=%i", spawn->GetName(), spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, spawn->GetNPCTypeID()), errbuf, 0)) { - if(c) c->LogSQL(query); - safe_delete_array(query); - return true; - } - else { - safe_delete_array(query); - return false; - } - break; - } - case 3: { // delete spawn from spawning, but leave in npc_types table - if (!RunQuery(query, MakeAnyLenString(&query, "SELECT id,spawngroupID from spawn2 where zone='%s' AND spawngroupID=%i", zone, spawn->GetSp2()), errbuf, &result)) { - safe_delete_array(query); - return 0; - } - safe_delete_array(query); - - row = mysql_fetch_row(result); - if (row == nullptr) return false; - if (row[0]) tmp = atoi(row[0]); - if (row[1]) tmp2 = atoi(row[1]); - - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawn2 WHERE id='%i'", tmp), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawngroup WHERE id='%i'", tmp2), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawnentry WHERE spawngroupID='%i'", tmp2), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - return true; - - - break; - } - case 4: { //delete spawn from DB (including npc_type) - if (!RunQuery(query, MakeAnyLenString(&query, "SELECT id,spawngroupID from spawn2 where zone='%s' AND version=%u AND spawngroupID=%i", zone, zone_version, spawn->GetSp2()), errbuf, &result)) { - safe_delete_array(query); - return(0); - } - safe_delete_array(query); - - row = mysql_fetch_row(result); - if (row == nullptr) return false; - if (row[0]) tmp = atoi(row[0]); - if (row[1]) tmp2 = atoi(row[1]); - mysql_free_result(result); - - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawn2 WHERE id='%i'", tmp), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawngroup WHERE id='%i'", tmp2), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM spawnentry WHERE spawngroupID='%i'", tmp2), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if (!RunQuery(query, MakeAnyLenString(&query, "DELETE FROM npc_types WHERE id='%i'", spawn->GetNPCTypeID()), errbuf,0)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - return true; - break; - } - case 5: { // add a spawn from spawngroup - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) values('%s', %u, %f, %f, %f, %i, %f, %i)", zone, zone_version, c->GetX(), c->GetY(), c->GetZ(), 120, c->GetHeading(), extra), errbuf, 0, 0, &tmp)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - - return true; - break; - } - case 6: { // add npc_type - uint32 npc_type_id; - char tmpstr[64]; - EntityList::RemoveNumbers(strn0cpy(tmpstr, spawn->GetName(), sizeof(tmpstr))); - if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO npc_types (name, level, race, class, hp, gender, texture, helmtexture, size, loottable_id, merchant_id, face, runspeed, prim_melee_type, sec_melee_type) values(\"%s\",%i,%i,%i,%i,%i,%i,%i,%f,%i,%i,%i,%f,%i,%i)", tmpstr, spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), spawn->GetLoottableID(), spawn->MerchantType, 0, spawn->GetRunspeed(), 28, 28), errbuf, 0, 0, &npc_type_id)) { - safe_delete(query); - return false; - } - if(c) c->LogSQL(query); - safe_delete_array(query); - if(c) c->Message(0, "%s npc_type ID %i created successfully!", tmpstr, npc_type_id); - return true; - break; - } - } - return false; -} - -int32 NPC::GetEquipmentMaterial(uint8 material_slot) const -{ - if (material_slot >= _MaterialCount) - return 0; - - int inv_slot = Inventory::CalcSlotFromMaterial(material_slot); - if (inv_slot == -1) - return 0; - if(equipment[inv_slot] == 0) { - switch(material_slot) { - case MaterialHead: - return helmtexture; - case MaterialChest: - return texture; - case MaterialPrimary: - return d_meele_texture1; - case MaterialSecondary: - return d_meele_texture2; - default: - //they have nothing in the slot, and its not a special slot... they get nothing. - return(0); - } - } - - //they have some loot item in this slot, pass it up to the default handler - return(Mob::GetEquipmentMaterial(material_slot)); -} - -uint32 NPC::GetMaxDamage(uint8 tlevel) -{ - uint32 dmg = 0; - if (tlevel < 40) - dmg = tlevel*2+2; - else if (tlevel < 50) - dmg = level*25/10+2; - else if (tlevel < 60) - dmg = (tlevel*3+2)+((tlevel-50)*30); - else - dmg = (tlevel*3+2)+((tlevel-50)*35); - return dmg; -} - -void NPC::PickPocket(Client* thief) { - - thief->CheckIncreaseSkill(SkillPickPockets, nullptr, 5); - - //make sure were allowed to targte them: - int olevel = GetLevel(); - if(olevel > (thief->GetLevel() + THIEF_PICKPOCKET_OVER)) { - thief->Message(13, "You are too inexperienced to pick pocket this target"); - thief->SendPickPocketResponse(this, 0, PickPocketFailed); - //should we check aggro - return; - } - - if(MakeRandomInt(0, 100) > 95){ - AddToHateList(thief, 50); - Say("Stop thief!"); - thief->Message(13, "You are noticed trying to steal!"); - thief->SendPickPocketResponse(this, 0, PickPocketFailed); - return; - } - - int steal_skill = thief->GetSkill(SkillPickPockets); - int stealchance = steal_skill*100/(5*olevel+5); - ItemInst* inst = 0; - int x = 0; - int slot[50]; - int steal_items[50]; - int charges[50]; - int money[4]; - money[0] = GetPlatinum(); - money[1] = GetGold(); - money[2] = GetSilver(); - money[3] = GetCopper(); - if (steal_skill < 125) - money[0] = 0; - if (steal_skill < 60) - money[1] = 0; - memset(slot,0,50); - memset(steal_items,0,50); - memset(charges,0,50); - //Determine wheter to steal money or an item. - bool no_coin = ((money[0] + money[1] + money[2] + money[3]) == 0); - bool steal_item = (MakeRandomInt(0, 99) < 50 || no_coin); - if (steal_item) - { - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end && x < 49; ++cur) { - ServerLootItem_Struct* citem = *cur; - const Item_Struct* item = database.GetItem(citem->item_id); - if (item) - { - inst = database.CreateItem(item, citem->charges); - bool is_arrow = (item->ItemType == ItemTypeArrow) ? true : false; - int slot_id = thief->GetInv().FindFreeSlot(false, true, inst->GetItem()->Size, is_arrow); - if (/*!Equipped(item->ID) &&*/ - !item->Magic && item->NoDrop != 0 && !inst->IsType(ItemClassContainer) && slot_id != SLOT_INVALID - /*&& steal_skill > item->StealSkill*/ ) - { - slot[x] = slot_id; - steal_items[x] = item->ID; - if (inst->IsStackable()) - charges[x] = 1; - else - charges[x] = citem->charges; - x++; - } - } - } - if (x > 0) - { - int random = MakeRandomInt(0, x-1); - inst = database.CreateItem(steal_items[random], charges[random]); - if (inst) - { - const Item_Struct* item = inst->GetItem(); - if (item) - { - if (/*item->StealSkill || */steal_skill >= stealchance) - { - thief->PutItemInInventory(slot[random], *inst); - thief->SendItemPacket(slot[random], inst, ItemPacketTrade); - RemoveItem(item->ID); - thief->SendPickPocketResponse(this, 0, PickPocketItem, item); - } - else - steal_item = false; - } - else - steal_item = false; - } - else - steal_item = false; - } - else if (!no_coin) - { - steal_item = false; - } - else - { - thief->Message(0, "This target's pockets are empty"); - thief->SendPickPocketResponse(this, 0, PickPocketFailed); - } - } - if (!steal_item) //Steal money - { - uint32 amt = MakeRandomInt(1, (steal_skill/25)+1); - int steal_type = 0; - if (!money[0]) - { - steal_type = 1; - if (!money[1]) - { - steal_type = 2; - if (!money[2]) - { - steal_type = 3; - } - } - } - - if (MakeRandomInt(0, 100) <= stealchance) - { - switch (steal_type) - { - case 0:{ - if (amt > GetPlatinum()) - amt = GetPlatinum(); - SetPlatinum(GetPlatinum()-amt); - thief->AddMoneyToPP(0,0,0,amt,false); - thief->SendPickPocketResponse(this, amt, PickPocketPlatinum); - break; - } - case 1:{ - if (amt > GetGold()) - amt = GetGold(); - SetGold(GetGold()-amt); - thief->AddMoneyToPP(0,0,amt,0,false); - thief->SendPickPocketResponse(this, amt, PickPocketGold); - break; - } - case 2:{ - if (amt > GetSilver()) - amt = GetSilver(); - SetSilver(GetSilver()-amt); - thief->AddMoneyToPP(0,amt,0,0,false); - thief->SendPickPocketResponse(this, amt, PickPocketSilver); - break; - } - case 3:{ - if (amt > GetCopper()) - amt = GetCopper(); - SetCopper(GetCopper()-amt); - thief->AddMoneyToPP(amt,0,0,0,false); - thief->SendPickPocketResponse(this, amt, PickPocketCopper); - break; - } - } - } - else - { - thief->SendPickPocketResponse(this, 0, PickPocketFailed); - } - } - safe_delete(inst); -} - -void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool remove) { - if(reset) - { - ClearSpecialAbilities(); - } - - const char* orig_parse = parse; - while (*parse) - { - switch(*parse) - { - case 'E': - SetSpecialAbility(SPECATK_ENRAGE, remove ? 0 : 1); - break; - case 'F': - SetSpecialAbility(SPECATK_FLURRY, remove ? 0 : 1); - break; - case 'R': - SetSpecialAbility(SPECATK_RAMPAGE, remove ? 0 : 1); - break; - case 'r': - SetSpecialAbility(SPECATK_AREA_RAMPAGE, remove ? 0 : 1); - break; - case 'S': - if(remove) { - SetSpecialAbility(SPECATK_SUMMON, 0); - StopSpecialAbilityTimer(SPECATK_SUMMON); - } else { - SetSpecialAbility(SPECATK_SUMMON, 1); - } - break; - case 'T': - SetSpecialAbility(SPECATK_TRIPLE, remove ? 0 : 1); - break; - case 'Q': - //quad requires triple to work properly - if(remove) { - SetSpecialAbility(SPECATK_QUAD, 0); - } else { - SetSpecialAbility(SPECATK_TRIPLE, 1); - SetSpecialAbility(SPECATK_QUAD, 1); - } - break; - case 'b': - SetSpecialAbility(SPECATK_BANE, remove ? 0 : 1); - break; - case 'm': - SetSpecialAbility(SPECATK_MAGICAL, remove ? 0 : 1); - break; - case 'U': - SetSpecialAbility(UNSLOWABLE, remove ? 0 : 1); - break; - case 'M': - SetSpecialAbility(UNMEZABLE, remove ? 0 : 1); - break; - case 'C': - SetSpecialAbility(UNCHARMABLE, remove ? 0 : 1); - break; - case 'N': - SetSpecialAbility(UNSTUNABLE, remove ? 0 : 1); - break; - case 'I': - SetSpecialAbility(UNSNAREABLE, remove ? 0 : 1); - break; - case 'D': - SetSpecialAbility(UNFEARABLE, remove ? 0 : 1); - break; - case 'K': - SetSpecialAbility(UNDISPELLABLE, remove ? 0 : 1); - break; - case 'A': - SetSpecialAbility(IMMUNE_MELEE, remove ? 0 : 1); - break; - case 'B': - SetSpecialAbility(IMMUNE_MAGIC, remove ? 0 : 1); - break; - case 'f': - SetSpecialAbility(IMMUNE_FLEEING, remove ? 0 : 1); - break; - case 'O': - SetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE, remove ? 0 : 1); - break; - case 'W': - SetSpecialAbility(IMMUNE_MELEE_NONMAGICAL, remove ? 0 : 1); - break; - case 'H': - SetSpecialAbility(IMMUNE_AGGRO, remove ? 0 : 1); - break; - case 'G': - SetSpecialAbility(IMMUNE_AGGRO_ON, remove ? 0 : 1); - break; - case 'g': - SetSpecialAbility(IMMUNE_CASTING_FROM_RANGE, remove ? 0 : 1); - break; - case 'd': - SetSpecialAbility(IMMUNE_FEIGN_DEATH, remove ? 0 : 1); - break; - case 'Y': - SetSpecialAbility(SPECATK_RANGED_ATK, remove ? 0 : 1); - break; - case 'L': - SetSpecialAbility(SPECATK_INNATE_DW, remove ? 0 : 1); - break; - case 't': - SetSpecialAbility(NPC_TUNNELVISION, remove ? 0 : 1); - break; - case 'n': - SetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS, remove ? 0 : 1); - break; - case 'p': - SetSpecialAbility(IMMUNE_PACIFY, remove ? 0 : 1); - break; - case 'J': - SetSpecialAbility(LEASH, remove ? 0 : 1); - break; - case 'j': - SetSpecialAbility(TETHER, remove ? 0 : 1); - break; - case 'o': - SetSpecialAbility(DESTRUCTIBLE_OBJECT, remove ? 0 : 1); - SetDestructibleObject(remove ? true : false); - break; - case 'Z': - SetSpecialAbility(NO_HARM_FROM_CLIENT, remove ? 0 : 1); - break; - case 'i': - SetSpecialAbility(IMMUNE_TAUNT, remove ? 0 : 1); - break; - case 'e': - SetSpecialAbility(ALWAYS_FLEE, remove ? 0 : 1); - break; - case 'h': - SetSpecialAbility(FLEE_PERCENT, remove ? 0 : 1); - break; - - default: - break; - } - parse++; - } - - if(permtag == 1 && this->GetNPCTypeID() > 0) - { - if(database.SetSpecialAttkFlag(this->GetNPCTypeID(), orig_parse)) - { - LogFile->write(EQEMuLog::Normal, "NPCTypeID: %i flagged to '%s' for Special Attacks.\n",this->GetNPCTypeID(),orig_parse); - } - } -} - -bool Mob::HasNPCSpecialAtk(const char* parse) { - - bool HasAllAttacks = true; - - while (*parse && HasAllAttacks == true) - { - switch(*parse) - { - case 'E': - if (!GetSpecialAbility(SPECATK_ENRAGE)) - HasAllAttacks = false; - break; - case 'F': - if (!GetSpecialAbility(SPECATK_FLURRY)) - HasAllAttacks = false; - break; - case 'R': - if (!GetSpecialAbility(SPECATK_RAMPAGE)) - HasAllAttacks = false; - break; - case 'r': - if (!GetSpecialAbility(SPECATK_AREA_RAMPAGE)) - HasAllAttacks = false; - break; - case 'S': - if (!GetSpecialAbility(SPECATK_SUMMON)) - HasAllAttacks = false; - break; - case 'T': - if (!GetSpecialAbility(SPECATK_TRIPLE)) - HasAllAttacks = false; - break; - case 'Q': - if (!GetSpecialAbility(SPECATK_QUAD)) - HasAllAttacks = false; - break; - case 'b': - if (!GetSpecialAbility(SPECATK_BANE)) - HasAllAttacks = false; - break; - case 'm': - if (!GetSpecialAbility(SPECATK_MAGICAL)) - HasAllAttacks = false; - break; - case 'U': - if (!GetSpecialAbility(UNSLOWABLE)) - HasAllAttacks = false; - break; - case 'M': - if (!GetSpecialAbility(UNMEZABLE)) - HasAllAttacks = false; - break; - case 'C': - if (!GetSpecialAbility(UNCHARMABLE)) - HasAllAttacks = false; - break; - case 'N': - if (!GetSpecialAbility(UNSTUNABLE)) - HasAllAttacks = false; - break; - case 'I': - if (!GetSpecialAbility(UNSNAREABLE)) - HasAllAttacks = false; - break; - case 'D': - if (!GetSpecialAbility(UNFEARABLE)) - HasAllAttacks = false; - break; - case 'A': - if (!GetSpecialAbility(IMMUNE_MELEE)) - HasAllAttacks = false; - break; - case 'B': - if (!GetSpecialAbility(IMMUNE_MAGIC)) - HasAllAttacks = false; - break; - case 'f': - if (!GetSpecialAbility(IMMUNE_FLEEING)) - HasAllAttacks = false; - break; - case 'O': - if (!GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) - HasAllAttacks = false; - break; - case 'W': - if (!GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)) - HasAllAttacks = false; - break; - case 'H': - if (!GetSpecialAbility(IMMUNE_AGGRO)) - HasAllAttacks = false; - break; - case 'G': - if (!GetSpecialAbility(IMMUNE_AGGRO_ON)) - HasAllAttacks = false; - break; - case 'g': - if (!GetSpecialAbility(IMMUNE_CASTING_FROM_RANGE)) - HasAllAttacks = false; - break; - case 'd': - if (!GetSpecialAbility(IMMUNE_FEIGN_DEATH)) - HasAllAttacks = false; - break; - case 'Y': - if (!GetSpecialAbility(SPECATK_RANGED_ATK)) - HasAllAttacks = false; - break; - case 'L': - if (!GetSpecialAbility(SPECATK_INNATE_DW)) - HasAllAttacks = false; - break; - case 't': - if (!GetSpecialAbility(NPC_TUNNELVISION)) - HasAllAttacks = false; - break; - case 'n': - if (!GetSpecialAbility(NPC_NO_BUFFHEAL_FRIENDS)) - HasAllAttacks = false; - break; - case 'p': - if(!GetSpecialAbility(IMMUNE_PACIFY)) - HasAllAttacks = false; - break; - case 'J': - if(!GetSpecialAbility(LEASH)) - HasAllAttacks = false; - break; - case 'j': - if(!GetSpecialAbility(TETHER)) - HasAllAttacks = false; - break; - case 'o': - if(!GetSpecialAbility(DESTRUCTIBLE_OBJECT)) - { - HasAllAttacks = false; - SetDestructibleObject(false); - } - break; - case 'Z': - if(!GetSpecialAbility(NO_HARM_FROM_CLIENT)){ - HasAllAttacks = false; - } - break; - case 'e': - if(!GetSpecialAbility(ALWAYS_FLEE)) - HasAllAttacks = false; - break; - case 'h': - if(!GetSpecialAbility(FLEE_PERCENT)) - HasAllAttacks = false; - break; - default: - HasAllAttacks = false; - break; - } - parse++; - } - - return HasAllAttacks; -} - -void NPC::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) -{ - Mob::FillSpawnStruct(ns, ForWho); - - //Basic settings to make sure swarm pets work properly. - if (GetSwarmOwner()) { - Client *c = entity_list.GetClientByID(GetSwarmOwner()); - if(c) { - SetAllowBeneficial(1); //Allow client cast swarm pets to be heal/buffed. - //This is a hack to allow CLIENT swarm pets NOT to be targeted with F8. Warning: Will turn name 'Yellow'! - if (RuleB(Pets, SwarmPetNotTargetableWithHotKey)) - ns->spawn.IsMercenary = 1; - } - //NPC cast swarm pets should still be targetable with F8. - else - ns->spawn.IsMercenary = 0; - } - - //Not recommended if using above (However, this will work better on older clients). - if (RuleB(Pets, UnTargetableSwarmPet)) { - if(GetOwnerID() || GetSwarmOwner()) { - ns->spawn.is_pet = 1; - if (!IsCharmed() && GetOwnerID()) { - Client *c = entity_list.GetClientByID(GetOwnerID()); - if(c) - sprintf(ns->spawn.lastName, "%s's Pet", c->GetName()); - } - else if (GetSwarmOwner()) { - ns->spawn.bodytype = 11; - if(!IsCharmed()) - { - Client *c = entity_list.GetClientByID(GetSwarmOwner()); - if(c) - sprintf(ns->spawn.lastName, "%s's Pet", c->GetName()); - } - } - } - } else { - if(GetOwnerID()) { - ns->spawn.is_pet = 1; - if (!IsCharmed() && GetOwnerID()) { - Client *c = entity_list.GetClientByID(GetOwnerID()); - if(c) - sprintf(ns->spawn.lastName, "%s's Pet", c->GetName()); - } - } else - ns->spawn.is_pet = 0; - } - - ns->spawn.is_npc = 1; -} - -void NPC::SetLevel(uint8 in_level, bool command) -{ - if(in_level > level) - SendLevelAppearance(); - level = in_level; - SendAppearancePacket(AT_WhoLevel, in_level); -} - -void NPC::ModifyNPCStat(const char *identifier, const char *newValue) -{ - std::string id = identifier; - std::string val = newValue; - for(int i = 0; i < id.length(); ++i) - { - id[i] = std::tolower(id[i]); - } - - if(id == "ac") - { - AC = atoi(val.c_str()); - return; - } - - if(id == "str") - { - STR = atoi(val.c_str()); - return; - } - - if(id == "sta") - { - STA = atoi(val.c_str()); - return; - } - - if(id == "agi") - { - AGI = atoi(val.c_str()); - return; - } - - if(id == "dex") - { - DEX = atoi(val.c_str()); - return; - } - - if(id == "wis") - { - WIS = atoi(val.c_str()); - CalcMaxMana(); - return; - } - - if(id == "int" || id == "_int") - { - INT = atoi(val.c_str()); - CalcMaxMana(); - return; - } - - if(id == "cha") - { - CHA = atoi(val.c_str()); - return; - } - - if(id == "max_hp") - { - base_hp = atoi(val.c_str()); - CalcMaxHP(); - if(cur_hp > max_hp) - cur_hp = max_hp; - return; - } - - if(id == "max_mana") - { - npc_mana = atoi(val.c_str()); - CalcMaxMana(); - if(cur_mana > max_mana) - cur_mana = max_mana; - return; - } - - if(id == "mr") - { - MR = atoi(val.c_str()); - return; - } - - if(id == "fr") - { - FR = atoi(val.c_str()); - return; - } - - if(id == "cr") - { - CR = atoi(val.c_str()); - return; - } - - if(id == "pr") - { - PR = atoi(val.c_str()); - return; - } - - if(id == "dr") - { - DR = atoi(val.c_str()); - return; - } - - if(id == "PhR") - { - PhR = atoi(val.c_str()); - return; - } - - if(id == "runspeed") - { - runspeed = (float)atof(val.c_str()); - CalcBonuses(); - return; - } - - if(id == "special_attacks") - { - //Added reset flag. - NPCSpecialAttacks(val.c_str(), 0, 1); - return; - } - - if(id == "attack_speed") - { - attack_speed = (float)atof(val.c_str()); - CalcBonuses(); - return; - } - - if(id == "atk") - { - ATK = atoi(val.c_str()); - return; - } - - if(id == "accuracy") - { - accuracy_rating = atoi(val.c_str()); - return; - } - - if(id == "trackable") - { - trackable = atoi(val.c_str()); - return; - } - - if(id == "min_hit") - { - min_dmg = atoi(val.c_str()); - return; - } - - if(id == "max_hit") - { - max_dmg = atoi(val.c_str()); - return; - } - - if(id == "attack_count") - { - attack_count = atoi(val.c_str()); - return; - } - - if(id == "see_invis") - { - see_invis = atoi(val.c_str()); - return; - } - - if(id == "see_invis_undead") - { - see_invis_undead = atoi(val.c_str()); - return; - } - - if(id == "see_hide") - { - see_hide = atoi(val.c_str()); - return; - } - - if(id == "see_improved_hide") - { - see_improved_hide = atoi(val.c_str()); - return; - } - - if(id == "hp_regen") - { - hp_regen = atoi(val.c_str()); - return; - } - - if(id == "mana_regen") - { - mana_regen = atoi(val.c_str()); - return; - } - - if(id == "level") - { - SetLevel(atoi(val.c_str())); - return; - } - - if(id == "aggro") - { - pAggroRange = atof(val.c_str()); - return; - } - - if(id == "assist") - { - pAssistRange = atof(val.c_str()); - return; - } - - if(id == "slow_mitigation") - { - slow_mitigation = atoi(val.c_str()); - return; - } - if(id == "loottable_id") - { - loottable_id = atof(val.c_str()); - return; - } - if(id == "healscale") - { - healscale = atof(val.c_str()); - return; - } - if(id == "spellscale") - { - spellscale = atof(val.c_str()); - return; - } -} - -void NPC::LevelScale() { - - uint8 random_level = (MakeRandomInt(level, maxlevel)); - - float scaling = (((random_level / (float)level) - 1) * (scalerate / 100.0f)); - - // Compensate for scale rates at low levels so they don't add too much - uint8 scale_adjust = 1; - if(level > 0 && level <= 5) - scale_adjust = 10; - if(level > 5 && level <= 10) - scale_adjust = 5; - if(level > 10 && level <= 15) - scale_adjust = 3; - if(level > 15 && level <= 25) - scale_adjust = 2; - - base_hp += (int)(base_hp * scaling); - max_hp += (int)(max_hp * scaling); - cur_hp = max_hp; - STR += (int)(STR * scaling / scale_adjust); - STA += (int)(STA * scaling / scale_adjust); - AGI += (int)(AGI * scaling / scale_adjust); - DEX += (int)(DEX * scaling / scale_adjust); - INT += (int)(INT * scaling / scale_adjust); - WIS += (int)(WIS * scaling / scale_adjust); - CHA += (int)(CHA * scaling / scale_adjust); - if (MR) - MR += (int)(MR * scaling / scale_adjust); - if (CR) - CR += (int)(CR * scaling / scale_adjust); - if (DR) - DR += (int)(DR * scaling / scale_adjust); - if (FR) - FR += (int)(FR * scaling / scale_adjust); - if (PR) - PR += (int)(PR * scaling / scale_adjust); - - if (max_dmg) - { - max_dmg += (int)(max_dmg * scaling / scale_adjust); - min_dmg += (int)(min_dmg * scaling / scale_adjust); - } - - level = random_level; - - return; -} - -void NPC::CalcNPCResists() { - - if (!MR) - MR = (GetLevel() * 11)/10; - if (!CR) - CR = (GetLevel() * 11)/10; - if (!DR) - DR = (GetLevel() * 11)/10; - if (!FR) - FR = (GetLevel() * 11)/10; - if (!PR) - PR = (GetLevel() * 11)/10; - if (!Corrup) - Corrup = 15; - if (!PhR) - PhR = 10; - return; -} - -void NPC::CalcNPCRegen() { - - // Fix for lazy db-updaters (regen values left at 0) - if (GetCasterClass() != 'N' && mana_regen == 0) - mana_regen = (GetLevel() / 10) + 4; - else if(mana_regen < 0) - mana_regen = 0; - else - mana_regen = mana_regen; - - // Gives low end monsters no regen if set to 0 in database. Should make low end monsters killable - // Might want to lower this to /5 rather than 10. - if(hp_regen == 0) - { - if(GetLevel() <= 6) - hp_regen = 1; - else if(GetLevel() > 6 && GetLevel() <= 10) - hp_regen = 2; - else if(GetLevel() > 10 && GetLevel() <= 15) - hp_regen = 3; - else if(GetLevel() > 15 && GetLevel() <= 20) - hp_regen = 5; - else if(GetLevel() > 20 && GetLevel() <= 30) - hp_regen = 7; - else if(GetLevel() > 30 && GetLevel() <= 35) - hp_regen = 9; - else if(GetLevel() > 35 && GetLevel() <= 40) - hp_regen = 12; - else if(GetLevel() > 40 && GetLevel() <= 45) - hp_regen = 18; - else if(GetLevel() > 45 && GetLevel() <= 50) - hp_regen = 21; - else - hp_regen = 30; - } else if(hp_regen < 0) { - hp_regen = 0; - } else - hp_regen = hp_regen; - - return; -} - -void NPC::CalcNPCDamage() { - - int AC_adjust=12; - - if (GetLevel() >= 66) { - if (min_dmg==0) - min_dmg = 220; - if (max_dmg==0) - max_dmg = ((((99000)*(GetLevel()-64))/400)*AC_adjust/10); - } - else if (GetLevel() >= 60 && GetLevel() <= 65){ - if(min_dmg==0) - min_dmg = (GetLevel()+(GetLevel()/3)); - if(max_dmg==0) - max_dmg = (GetLevel()*3)*AC_adjust/10; - } - else if (GetLevel() >= 51 && GetLevel() <= 59){ - if(min_dmg==0) - min_dmg = (GetLevel()+(GetLevel()/3)); - if(max_dmg==0) - max_dmg = (GetLevel()*3)*AC_adjust/10; - } - else if (GetLevel() >= 40 && GetLevel() <= 50) { - if (min_dmg==0) - min_dmg = GetLevel(); - if(max_dmg==0) - max_dmg = (GetLevel()*3)*AC_adjust/10; - } - else if (GetLevel() >= 28 && GetLevel() <= 39) { - if (min_dmg==0) - min_dmg = GetLevel() / 2; - if (max_dmg==0) - max_dmg = ((GetLevel()*2)+2)*AC_adjust/10; - } - else if (GetLevel() <= 27) { - if (min_dmg==0) - min_dmg=1; - if (max_dmg==0) - max_dmg = (GetLevel()*2)*AC_adjust/10; - } - - int clfact = GetClassLevelFactor(); - min_dmg = (min_dmg * clfact) / 220; - max_dmg = (max_dmg * clfact) / 220; - - return; -} - - -uint32 NPC::GetSpawnPointID() const -{ - if(respawn2) - { - return respawn2->GetID(); - } - return 0; -} - -void NPC::NPCSlotTexture(uint8 slot, uint16 texture) -{ - if (slot == 7) { - d_meele_texture1 = texture; - } - else if (slot == 8) { - d_meele_texture2 = texture; - } - else if (slot < 6) { - // Reserved for texturing individual armor slots - } - return; -} - -uint32 NPC::GetSwarmOwner() -{ - if(GetSwarmInfo() != nullptr) - { - return GetSwarmInfo()->owner_id; - } - return 0; -} - -uint32 NPC::GetSwarmTarget() -{ - if(GetSwarmInfo() != nullptr) - { - return GetSwarmInfo()->target; - } - return 0; -} - -void NPC::SetSwarmTarget(int target_id) -{ - if(GetSwarmInfo() != nullptr) - { - GetSwarmInfo()->target = target_id; - } - return; -} - -int32 NPC::CalcMaxMana() { - if(npc_mana == 0) { - switch (GetCasterClass()) { - case 'I': - max_mana = (((GetINT()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana; - break; - case 'W': - max_mana = (((GetWIS()/2)+1) * GetLevel()) + spellbonuses.Mana + itembonuses.Mana; - break; - case 'N': - default: - max_mana = 0; - break; - } - if (max_mana < 0) { - max_mana = 0; - } - - return max_mana; - } else { - switch (GetCasterClass()) { - case 'I': - max_mana = npc_mana + spellbonuses.Mana + itembonuses.Mana; - break; - case 'W': - max_mana = npc_mana + spellbonuses.Mana + itembonuses.Mana; - break; - case 'N': - default: - max_mana = 0; - break; - } - if (max_mana < 0) { - max_mana = 0; - } - - return max_mana; - } -} - -void NPC::SignalNPC(int _signal_id) -{ - signal_q.push_back(_signal_id); -} - -NPC_Emote_Struct* NPC::GetNPCEmote(uint16 emoteid, uint8 event_) { - LinkedListIterator iterator(zone->NPCEmoteList); - iterator.Reset(); - while(iterator.MoreElements()) - { - NPC_Emote_Struct* nes = iterator.GetData(); - if (emoteid == nes->emoteid && event_ == nes->event_) { - return (nes); - } - iterator.Advance(); - } - return (nullptr); -} - -void NPC::DoNPCEmote(uint8 event_, uint16 emoteid) -{ - if(this == nullptr || emoteid == 0) - { - return; - } - - NPC_Emote_Struct* nes = GetNPCEmote(emoteid,event_); - if(nes == nullptr) - { - return; - } - - if(emoteid == nes->emoteid) - { - if(nes->type == 1) - this->Emote("%s",nes->text); - else if(nes->type == 2) - this->Shout("%s",nes->text); - else if(nes->type == 3) - entity_list.MessageClose_StringID(this, true, 200, 10, GENERIC_STRING, nes->text); - else - this->Say("%s",nes->text); - } -} - -bool NPC::CanTalk() -{ - //Races that should be able to talk. (Races up to Titanium) - - uint16 TalkRace[473] = - {1,2,3,4,5,6,7,8,9,10,11,12,0,0,15,16,0,18,19,20,0,0,23,0,25,0,0,0,0,0,0, - 32,0,0,0,0,0,0,39,40,0,0,0,44,0,0,0,0,49,0,51,0,53,54,55,56,57,58,0,0,0, - 62,0,64,65,66,67,0,0,70,71,0,0,0,0,0,77,78,79,0,81,82,0,0,0,86,0,0,0,90, - 0,92,93,94,95,0,0,98,99,0,101,0,103,0,0,0,0,0,0,110,111,112,0,0,0,0,0,0, - 0,0,0,0,123,0,0,126,0,128,0,130,131,0,0,0,0,136,137,0,139,140,0,0,0,144, - 0,0,0,0,0,150,151,152,153,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,183,184,0,0,187,188,189,0,0,0,0,0,195,196,0,198,0,0,0,202,0, - 0,205,0,0,208,0,0,0,0,0,0,0,0,217,0,219,0,0,0,0,0,0,226,0,0,229,230,0,0, - 0,0,235,236,0,238,239,240,241,242,243,244,0,246,247,0,0,0,251,0,0,254,255, - 256,257,0,0,0,0,0,0,0,0,266,267,0,0,270,271,0,0,0,0,0,277,278,0,0,0,0,283, - 284,0,286,0,288,289,290,0,0,0,0,295,296,297,298,299,300,0,0,0,304,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,320,0,322,323,324,325,0,0,0,0,330,331,332,333,334,335, - 336,337,338,339,340,341,342,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,359,360,361,362, - 0,364,365,366,0,368,369,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,385,386,0,0,0,0,0,392, - 393,394,395,396,397,398,0,400,402,0,0,0,0,406,0,408,0,0,411,0,413,0,0,0,417, - 0,0,420,0,0,0,0,425,0,0,0,0,0,0,0,433,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,458,0,0,0,0,0,0,0,0,467,0,0,470,0,0,473}; - - int talk_check = TalkRace[GetRace() - 1]; - - if (TalkRace[GetRace() - 1] > 0) - return true; - - return false; -} - -//this is called with 'this' as the mob being looked at, and -//iOther the mob who is doing the looking. It should figure out -//what iOther thinks about 'this' -FACTION_VALUE NPC::GetReverseFactionCon(Mob* iOther) { - iOther = iOther->GetOwnerOrSelf(); - int primaryFaction= iOther->GetPrimaryFaction(); - - //I am pretty sure that this special faction call is backwards - //and should be iOther->GetSpecialFactionCon(this) - if (primaryFaction < 0) - return GetSpecialFactionCon(iOther); - - if (primaryFaction == 0) - return FACTION_INDIFFERENT; - - //if we are a pet, use our owner's faction stuff - Mob *own = GetOwner(); - if (own != nullptr) - return own->GetReverseFactionCon(iOther); - - //make sure iOther is an npc - //also, if we dont have a faction, then they arnt gunna think anything of us either - if(!iOther->IsNPC() || GetPrimaryFaction() == 0) - return(FACTION_INDIFFERENT); - - //if we get here, iOther is an NPC too - - //otherwise, employ the npc faction stuff - //so we need to look at iOther's faction table to see - //what iOther thinks about our primary faction - return(iOther->CastToNPC()->CheckNPCFactionAlly(GetPrimaryFaction())); -} - -//Look through our faction list and return a faction con based -//on the npc_value for the other person's primary faction in our list. -FACTION_VALUE NPC::CheckNPCFactionAlly(int32 other_faction) { - std::list::iterator cur,end; - cur = faction_list.begin(); - end = faction_list.end(); - for(; cur != end; ++cur) { - struct NPCFaction* fac = *cur; - if ((int32)fac->factionID == other_faction) { - if (fac->npc_value > 0) - return FACTION_ALLY; - else if (fac->npc_value < 0) - return FACTION_SCOWLS; - else - return FACTION_INDIFFERENT; - } - } - return FACTION_INDIFFERENT; -} - -bool NPC::IsFactionListAlly(uint32 other_faction) { - return(CheckNPCFactionAlly(other_faction) == FACTION_ALLY); -} - -int NPC::GetScore() -{ - int lv = std::min(70, (int)GetLevel()); - int basedmg = (lv*2)*(1+(lv / 100)) - (lv / 2); - int minx = 0; - int basehp = 0; - int hpcontrib = 0; - int dmgcontrib = 0; - int spccontrib = 0; - int hp = GetMaxHP(); - int mindmg = min_dmg; - int maxdmg = max_dmg; - int final; - - if(lv < 46) - { - minx = static_cast (ceil( ((lv - (lv / 10.0)) - 1.0) )); - basehp = (lv * 10) + (lv * lv); - } - else - { - minx = static_cast (ceil( ((lv - (lv / 10.0)) - 1.0) - (( lv - 45.0 ) / 2.0) )); - basehp = (lv * 10) + ((lv * lv) * 4); - } - - if(hp > basehp) - { - hpcontrib = static_cast (((hp / static_cast (basehp)) * 1.5)); - if(hpcontrib > 5) { hpcontrib = 5; } - - if(maxdmg > basedmg) - { - dmgcontrib = static_cast (ceil( ((maxdmg / basedmg) * 1.5) )); - } - - if(HasNPCSpecialAtk("E")) { spccontrib++; } //Enrage - if(HasNPCSpecialAtk("F")) { spccontrib++; } //Flurry - if(HasNPCSpecialAtk("R")) { spccontrib++; } //Rampage - if(HasNPCSpecialAtk("r")) { spccontrib++; } //Area Rampage - if(HasNPCSpecialAtk("S")) { spccontrib++; } //Summon - if(HasNPCSpecialAtk("T")) { spccontrib += 2; } //Triple - if(HasNPCSpecialAtk("Q")) { spccontrib += 3; } //Quad - if(HasNPCSpecialAtk("U")) { spccontrib += 5; } //Unslowable - if(HasNPCSpecialAtk("L")) { spccontrib++; } //Innate Dual Wield - } - - if(npc_spells_id > 12) - { - if(lv < 16) - spccontrib++; - else - spccontrib += static_cast (floor(lv/15.0)); - } - - final = minx + hpcontrib + dmgcontrib + spccontrib; - final = std::max(1, final); - final = std::min(100, final); - return(final); -} - -uint32 NPC::GetSpawnKillCount() -{ - uint32 sid = GetSpawnPointID(); - - if(sid > 0) - { - return(zone->GetSpawnKillCount(sid)); - } - - return(0); -} - -void NPC::DoQuestPause(Mob *other) { - if(IsMoving() && !IsOnHatelist(other)) { - PauseWandering(RuleI(NPC, SayPauseTimeInSec)); - FaceTarget(other); - } else if(!IsMoving()) { - FaceTarget(other); - } - -} diff --git a/zone/perl_npcX.cpp b/zone/perl_npcX.cpp deleted file mode 100644 index 957baf7ab..000000000 --- a/zone/perl_npcX.cpp +++ /dev/null @@ -1,2487 +0,0 @@ -/* -* This file was generated automatically by xsubpp version 1.9508 from the -* contents of tmp. Do not edit this file, edit tmp instead. -* -* ANY CHANGES MADE HERE WILL BE LOST! -* -*/ - - -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "../common/features.h" -#ifdef EMBPERL_XS_CLASSES -#include "../common/debug.h" -#include "embperl.h" - -#ifdef seed -#undef seed -#endif - -typedef const char Const_char; - -#include "npc.h" - -#ifdef THIS /* this macro seems to leak out on some systems */ -#undef THIS -#endif - - -XS(XS_NPC_SignalNPC); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SignalNPC) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SignalNPC(THIS, _signal_id)"); - { - NPC * THIS; - int _signal_id = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SignalNPC(_signal_id); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_CheckNPCFactionAlly); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_CheckNPCFactionAlly) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::CheckNPCFactionAlly(THIS, other_faction)"); - { - NPC * THIS; - FACTION_VALUE RETVAL; - dXSTARG; - int32 other_faction = (int32)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->CheckNPCFactionAlly(other_faction); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_AddItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddItem) -{ - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: NPC::AddItem(THIS, itemid, charges = 0, equipitem = true)"); - { - NPC * THIS; - uint32 itemid = (uint32)SvUV(ST(1)); - uint16 charges = 0; - bool equipitem = true; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items > 2) - charges = (uint16)SvUV(ST(2)); - if (items > 3) - equipitem = (bool)SvTRUE(ST(3)); - - THIS->AddItem(itemid, charges, equipitem); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AddLootTable); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddLootTable) -{ - dXSARGS; - if (items < 1) - Perl_croak(aTHX_ "Usage: NPC::AddLootTable(THIS, [loottable_id])"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - uint32 loottable_id = 0; - - if(items > 1) - { - loottable_id = (uint32)SvUV(ST(1)); - THIS->AddLootTable(loottable_id); - } - else - { - THIS->AddLootTable(); - } - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_RemoveItem); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RemoveItem) -{ - dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: NPC::RemoveItem(THIS, item_id, quantity= 0, slot= 0)"); - { - NPC * THIS; - uint32 item_id = (uint32)SvUV(ST(1)); - uint16 quantity; - uint16 slot; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items < 3) - quantity = 0; - else { - quantity = (uint16)SvUV(ST(2)); - } - - if (items < 4) - slot = 0; - else { - slot = (uint16)SvUV(ST(3)); - } - - THIS->RemoveItem(item_id, quantity, slot); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_ClearItemList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ClearItemList) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::ClearItemList(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->ClearItemList(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AddCash); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddCash) -{ - dXSARGS; - if (items != 5) - Perl_croak(aTHX_ "Usage: NPC::AddCash(THIS, in_copper, in_silver, in_gold, in_platinum)"); - { - NPC * THIS; - uint16 in_copper = (uint16)SvUV(ST(1)); - uint16 in_silver = (uint16)SvUV(ST(2)); - uint16 in_gold = (uint16)SvUV(ST(3)); - uint16 in_platinum = (uint16)SvUV(ST(4)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->AddCash(in_copper, in_silver, in_gold, in_platinum); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_RemoveCash); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RemoveCash) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::RemoveCash(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->RemoveCash(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_CountLoot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_CountLoot) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::CountLoot(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->CountLoot(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetLoottableID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetLoottableID) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetLoottableID(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetLoottableID(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetCopper); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetCopper) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetCopper(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetCopper(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSilver); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSilver) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSilver(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSilver(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetGold); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGold) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGold(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetGold(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetPlatinum); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPlatinum) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPlatinum(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetPlatinum(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetCopper); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetCopper) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetCopper(THIS, amt)"); - { - NPC * THIS; - uint32 amt = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetCopper(amt); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetSilver); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSilver) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSilver(THIS, amt)"); - { - NPC * THIS; - uint32 amt = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSilver(amt); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetGold); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetGold) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetGold(THIS, amt)"); - { - NPC * THIS; - uint32 amt = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetGold(amt); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetPlatinum); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetPlatinum) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetPlatinum(THIS, amt)"); - { - NPC * THIS; - uint32 amt = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetPlatinum(amt); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetGrid); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetGrid) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetGrid(THIS, grid_)"); - { - NPC * THIS; - int32 grid_ = (int32)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetGrid(grid_); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetSaveWaypoint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSaveWaypoint) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSaveWaypoint(THIS, waypoint)"); - { - NPC * THIS; - uint16 waypoint = (uint16)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSaveWaypoint(waypoint); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetSp2); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSp2) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSp2(THIS, sg2)"); - { - NPC * THIS; - uint32 sg2 = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSp2(sg2); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetWaypointMax); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetWaypointMax) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetWaypointMax(THIS)"); - { - NPC * THIS; - uint16 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetWaypointMax(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetGrid); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGrid) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGrid(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetGrid(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSp2); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSp2) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSp2(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSp2(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetNPCFactionID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetNPCFactionID) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetNPCFactionID(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetNPCFactionID(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetPrimaryFaction); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPrimaryFaction) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPrimaryFaction(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetPrimaryFaction(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetNPCHate); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetNPCHate) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::GetNPCHate(THIS, in_ent)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - Mob* in_ent; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - in_ent = INT2PTR(Mob *,tmp); - } - else - Perl_croak(aTHX_ "in_ent is not of type Mob"); - if(in_ent == nullptr) - Perl_croak(aTHX_ "in_ent is nullptr, avoiding crash."); - - RETVAL = THIS->GetNPCHate(in_ent); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_IsOnHatelist); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_IsOnHatelist) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::IsOnHatelist(THIS, p)"); - { - NPC * THIS; - bool RETVAL; - Mob* p; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - p = INT2PTR(Mob *,tmp); - } - else - Perl_croak(aTHX_ "p is not of type Mob"); - if(p == nullptr) - Perl_croak(aTHX_ "p is nullptr, avoiding crash."); - - RETVAL = THIS->IsOnHatelist(p); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_NPC_SetNPCFactionID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetNPCFactionID) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetNPCFactionID(THIS, in)"); - { - NPC * THIS; - int32 in = (int32)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetNPCFactionID(in); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetMaxDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMaxDMG) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetMaxDMG(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetMaxDMG(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetMinDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMinDMG) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetMinDMG(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetMinDMG(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - - -XS(XS_NPC_IsAnimal); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_IsAnimal) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::IsAnimal(THIS)"); - { - NPC * THIS; - bool RETVAL; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->IsAnimal(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_NPC_GetPetSpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPetSpellID) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPetSpellID(THIS)"); - { - NPC * THIS; - uint16 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetPetSpellID(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetPetSpellID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetPetSpellID) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetPetSpellID(THIS, amt)"); - { - NPC * THIS; - uint16 amt = (uint16)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetPetSpellID(amt); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetMaxDamage); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMaxDamage) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::GetMaxDamage(THIS, tlevel)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - uint8 tlevel = (uint8)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetMaxDamage(tlevel); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetTaunting); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetTaunting) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetTaunting(THIS, tog)"); - { - NPC * THIS; - bool tog = (bool)SvTRUE(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetTaunting(tog); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_PickPocket); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_PickPocket) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::PickPocket(THIS, thief)"); - { - NPC * THIS; - Client* thief; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - thief = INT2PTR(Client *,tmp); - } - else - Perl_croak(aTHX_ "thief is not of type Client"); - if(thief == nullptr) - Perl_croak(aTHX_ "thief is nullptr, avoiding crash."); - - THIS->PickPocket(thief); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_StartSwarmTimer); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_StartSwarmTimer) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::StartSwarmTimer(THIS, duration)"); - { - NPC * THIS; - uint32 duration = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->StartSwarmTimer(duration); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_DoClassAttacks); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_DoClassAttacks) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::DoClassAttacks(THIS, target)"); - { - NPC * THIS; - Mob * target; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (sv_derived_from(ST(1), "Mob")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - target = INT2PTR(Mob *,tmp); - } - else - Perl_croak(aTHX_ "target is not of type Mob"); - if(target == nullptr) - Perl_croak(aTHX_ "target is nullptr, avoiding crash."); - - THIS->DoClassAttacks(target); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetMaxWp); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetMaxWp) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetMaxWp(THIS)"); - { - NPC * THIS; - int RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetMaxWp(); - XSprePUSH; PUSHi((IV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_DisplayWaypointInfo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_DisplayWaypointInfo) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::DisplayWaypointInfo(THIS, to)"); - { - NPC * THIS; - Client * to; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (sv_derived_from(ST(1), "Client")) { - IV tmp = SvIV((SV*)SvRV(ST(1))); - to = INT2PTR(Client *,tmp); - } - else - Perl_croak(aTHX_ "to is not of type Client"); - if(to == nullptr) - Perl_croak(aTHX_ "to is nullptr, avoiding crash."); - - THIS->DisplayWaypointInfo(to); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_CalculateNewWaypoint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_CalculateNewWaypoint) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::CalculateNewWaypoint(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->CalculateNewWaypoint(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AssignWaypoints); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AssignWaypoints) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::AssignWaypoints(THIS, grid)"); - { - NPC * THIS; - uint32 grid = (uint32)SvUV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->AssignWaypoints(grid); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetWaypointPause); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetWaypointPause) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::SetWaypointPause(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetWaypointPause(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_UpdateWaypoint); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_UpdateWaypoint) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::UpdateWaypoint(THIS, wp_index)"); - { - NPC * THIS; - int wp_index = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->UpdateWaypoint(wp_index); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_StopWandering); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_StopWandering) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::StopWandering(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->StopWandering(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_ResumeWandering); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ResumeWandering) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::ResumeWandering(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->ResumeWandering(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_PauseWandering); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_PauseWandering) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::PauseWandering(THIS, pausetime)"); - { - NPC * THIS; - int pausetime = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->PauseWandering(pausetime); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_MoveTo); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_MoveTo) -{ - dXSARGS; - if (items != 4 && items != 5 && items != 6) - Perl_croak(aTHX_ "Usage: NPC::MoveTo(THIS, mtx, mty, mtz, [mth, saveguard?])"); - { - NPC * THIS; - float mtx = (float)SvNV(ST(1)); - float mty = (float)SvNV(ST(2)); - float mtz = (float)SvNV(ST(3)); - float mth; - bool saveguard; - - if(items > 4) - mth = (float)SvNV(ST(4)); - else - mth = 0; - - if(items > 5) - saveguard = (bool)SvTRUE(ST(5)); - else - saveguard = false; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->MoveTo(mtx, mty, mtz, mth, saveguard); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_NextGuardPosition); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_NextGuardPosition) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::NextGuardPosition(THIS)"); - { - NPC * THIS; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->NextGuardPosition(); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SaveGuardSpot); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SaveGuardSpot) -{ - dXSARGS; - if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: NPC::SaveGuardSpot(THIS, iClearGuardSpot= false)"); - { - NPC * THIS; - bool iClearGuardSpot; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items < 2) - iClearGuardSpot = false; - else { - iClearGuardSpot = (bool)SvTRUE(ST(1)); - } - - THIS->SaveGuardSpot(iClearGuardSpot); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_IsGuarding); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_IsGuarding) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::IsGuarding(THIS)"); - { - NPC * THIS; - bool RETVAL; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->IsGuarding(); - ST(0) = boolSV(RETVAL); - sv_2mortal(ST(0)); - } - XSRETURN(1); -} - -XS(XS_NPC_AI_SetRoambox); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AI_SetRoambox) -{ - dXSARGS; - if (items < 6 || items > 8) - Perl_croak(aTHX_ "Usage: NPC::AI_SetRoambox(THIS, iDist, iMaxX, iMinX, iMaxY, iMinY, iDelay= 2500, iMinDelay= 2500)"); - { - NPC * THIS; - float iDist = (float)SvNV(ST(1)); - float iMaxX = (float)SvNV(ST(2)); - float iMinX = (float)SvNV(ST(3)); - float iMaxY = (float)SvNV(ST(4)); - float iMinY = (float)SvNV(ST(5)); - uint32 iDelay; - uint32 iMinDelay; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - if (items < 7){ - iMinDelay = 2500; - iDelay = 2500; - } - else if (items < 8){ - iMinDelay = 2500; - iDelay = (uint32)SvUV(ST(6)); - } - else { - iDelay = (uint32)SvUV(ST(6)); - iMinDelay = (uint32)SvUV(ST(7)); - } - - THIS->AI_SetRoambox(iDist, iMaxX, iMinX, iMaxY, iMinY, iDelay, iMinDelay); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetNPCSpellsID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetNPCSpellsID) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetNPCSpellsID(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetNPCSpellsID(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnPointID); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointID) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointID(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSpawnPointID(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnPointX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointX) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointX(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetSpawnPointX(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnPointY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointY) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointY(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetSpawnPointY(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnPointZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointZ) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointZ(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetSpawnPointZ(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnPointH); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnPointH) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnPointH(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetSpawnPointH(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetGuardPointX); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGuardPointX) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGuardPointX(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetGuardPointX(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetGuardPointY); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGuardPointY) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGuardPointY(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetGuardPointY(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetGuardPointZ); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetGuardPointZ) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetGuardPointZ(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - - RETVAL = THIS->GetGuardPointZ(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetPrimSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetPrimSkill) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetPrimSkill(THIS, skill_id)"); - { - NPC * THIS; - int skill_id = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetPrimSkill(skill_id); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetSecSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSecSkill) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSecSkill(THIS, skill_id)"); - { - NPC * THIS; - int skill_id = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSecSkill(skill_id); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetPrimSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetPrimSkill) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetPrimSkill(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetPrimSkill(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSecSkill); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSecSkill) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSecSkill(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSecSkill(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSwarmOwner); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSwarmOwner) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSwarmOwner(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSwarmOwner(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSwarmTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSwarmTarget) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSwarmTarget(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSwarmTarget(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetSwarmTarget); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSwarmTarget) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSwarmTarget(THIS, target_id)"); - { - NPC * THIS; - int target_id = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSwarmTarget(target_id); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_ModifyNPCStat); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_ModifyNPCStat) -{ - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::ModifyNPCStat(THIS, identifier, newValue)"); - { - NPC * THIS; - Const_char * identifier = (Const_char *)SvPV_nolen(ST(1)); - Const_char * newValue = (Const_char *)SvPV_nolen(ST(2)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->ModifyNPCStat(identifier, newValue); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AddSpellToNPCList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_AddSpellToNPCList) -{ - dXSARGS; - if (items != 7) - Perl_croak(aTHX_ "Usage: NPC::AddAISpell(THIS, priority, spell_id, type, mana_cost, recast_delay, resist_adjust)"); - { - NPC * THIS; - int priority = (int)SvIV(ST(1)); - int spell_id = (int)SvIV(ST(2)); - int type = (int)SvIV(ST(3)); - int mana_cost = (int)SvIV(ST(4)); - int recast_delay = (int)SvIV(ST(5)); - int resist_adjust = (int)SvIV(ST(6)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->AddSpellToNPCList(priority, spell_id, type, mana_cost, recast_delay, resist_adjust); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_RemoveSpellFromNPCList); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_RemoveSpellFromNPCList) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::RemoveAISpell(THIS, spell_id)"); - { - NPC * THIS; - int spell_id = (int)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->RemoveSpellFromNPCList(spell_id); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_SetSpellFocusDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSpellFocusDMG) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSpellFocusDMG(THIS, NewSpellFocusDMG)"); - { - NPC * THIS; - int32 NewSpellFocusDMG = (int32)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSpellFocusDMG(NewSpellFocusDMG); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetSpellFocusDMG); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpellFocusDMG) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusDMG(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSpellFocusDMG(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_SetSpellFocusHeal) -{ - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetSpellFocusHeal(THIS, NewSpellFocusHeal)"); - { - NPC * THIS; - int32 NewSpellFocusHeal = (int32)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetSpellFocusHeal(NewSpellFocusHeal); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpellFocusHeal) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusHeal(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSpellFocusHeal(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSlowMitigation); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSlowMitigation) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSlowMitigation(THIS)"); - { - NPC * THIS; - int16 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetSlowMitigation(); - XSprePUSH; PUSHn((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetAttackSpeed); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAttackSpeed) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAttackSpeed(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetAttackSpeed(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetAttackDelay); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAttackDelay) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAttackDelay(THIS)"); - { - NPC * THIS; - float RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetAttackDelay(); - XSprePUSH; PUSHn((double)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetAccuracyRating); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAccuracyRating) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAccuracyRating(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetAccuracyRating(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetAvoidanceRating); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetAvoidanceRating) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetAvoidanceyRating(THIS)"); - { - NPC * THIS; - int32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - RETVAL = THIS->GetAvoidanceRating(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetSpawnKillCount); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetSpawnKillCount) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetSpawnKillCount(THIS)"); - { - NPC * THIS; - uint32 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - RETVAL = THIS->GetSpawnKillCount(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_GetScore); /* prototype to pass -Wmissing-prototypes */ -XS(XS_NPC_GetScore) -{ - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetScore(THIS)"); - { - NPC * THIS; - int RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - RETVAL = THIS->GetScore(); - XSprePUSH; PUSHi((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_SetMerchantProbability); -XS(XS_NPC_SetMerchantProbability) { - dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: NPC::SetMerchantProbability(THIS, Probability)"); - { - NPC *THIS; - uint8 Probability = (uint8)SvIV(ST(1)); - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == nullptr) - Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - - THIS->SetMerchantProbability(Probability); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_GetMerchantProbability); -XS(XS_NPC_GetMerchantProbability) { - dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::GetMerchantProbability(THIS)"); - { - NPC *THIS; - uint8 RETVAL; - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - RETVAL = THIS->GetMerchantProbability(); - XSprePUSH; PUSHu((UV)RETVAL); - } - XSRETURN(1); -} - -XS(XS_NPC_AddMeleeProc); -XS(XS_NPC_AddMeleeProc) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::AddMeleeProc(THIS,spellid,chance)"); - { - NPC * THIS; - int spell_id = (int)SvIV(ST(1)); - int chance = (int)SvIV(ST(2)); - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - THIS->AddProcToWeapon(spell_id, true, chance); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AddRangedProc); -XS(XS_NPC_AddRangedProc) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::AddRangedProc(THIS,spellid,chance)"); - { - NPC * THIS; - int spell_id = (int)SvIV(ST(1)); - int chance = (int)SvIV(ST(2)); - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - THIS->AddDefensiveProc(spell_id,chance); - } - XSRETURN_EMPTY; -} - -XS(XS_NPC_AddDefensiveProc); -XS(XS_NPC_AddDefensiveProc) { - dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: NPC::AddDefensiveProc(THIS,spellid,chance)"); - { - NPC * THIS; - int spell_id = (int)SvIV(ST(1)); - int chance = (int)SvIV(ST(2)); - dXSTARG; - - if (sv_derived_from(ST(0), "NPC")) { - IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(NPC *,tmp); - } - else - Perl_croak(aTHX_ "THIS is not of type NPC"); - if(THIS == NULL) - Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); - - THIS->AddProcToWeapon(spell_id, true, chance); - } - XSRETURN_EMPTY; -} - - -#ifdef __cplusplus -extern "C" -#endif -XS(boot_NPC); /* prototype to pass -Wmissing-prototypes */ -XS(boot_NPC) -{ - dXSARGS; - char file[256]; - strncpy(file, __FILE__, 256); - file[255] = 0; - - if(items != 1) - fprintf(stderr, "boot_quest does not take any arguments."); - char buf[128]; - - //add the strcpy stuff to get rid of const warnings.... - - XS_VERSION_BOOTCHECK ; - - newXSproto(strcpy(buf, "SignalNPC"), XS_NPC_SignalNPC, file, "$$"); - newXSproto(strcpy(buf, "CheckNPCFactionAlly"), XS_NPC_CheckNPCFactionAlly, file, "$$"); - newXSproto(strcpy(buf, "AddItem"), XS_NPC_AddItem, file, "$$;$$"); - newXSproto(strcpy(buf, "AddLootTable"), XS_NPC_AddLootTable, file, "$"); - newXSproto(strcpy(buf, "RemoveItem"), XS_NPC_RemoveItem, file, "$$;$$"); - newXSproto(strcpy(buf, "ClearItemList"), XS_NPC_ClearItemList, file, "$"); - newXSproto(strcpy(buf, "AddCash"), XS_NPC_AddCash, file, "$$$$$"); - newXSproto(strcpy(buf, "RemoveCash"), XS_NPC_RemoveCash, file, "$"); - newXSproto(strcpy(buf, "CountLoot"), XS_NPC_CountLoot, file, "$"); - newXSproto(strcpy(buf, "GetLoottableID"), XS_NPC_GetLoottableID, file, "$"); - newXSproto(strcpy(buf, "GetCopper"), XS_NPC_GetCopper, file, "$"); - newXSproto(strcpy(buf, "GetSilver"), XS_NPC_GetSilver, file, "$"); - newXSproto(strcpy(buf, "GetGold"), XS_NPC_GetGold, file, "$"); - newXSproto(strcpy(buf, "GetPlatinum"), XS_NPC_GetPlatinum, file, "$"); - newXSproto(strcpy(buf, "SetCopper"), XS_NPC_SetCopper, file, "$$"); - newXSproto(strcpy(buf, "SetSilver"), XS_NPC_SetSilver, file, "$$"); - newXSproto(strcpy(buf, "SetGold"), XS_NPC_SetGold, file, "$$"); - newXSproto(strcpy(buf, "SetPlatinum"), XS_NPC_SetPlatinum, file, "$$"); - newXSproto(strcpy(buf, "SetGrid"), XS_NPC_SetGrid, file, "$$"); - newXSproto(strcpy(buf, "SetSaveWaypoint"), XS_NPC_SetSaveWaypoint, file, "$$"); - newXSproto(strcpy(buf, "SetSp2"), XS_NPC_SetSp2, file, "$$"); - newXSproto(strcpy(buf, "GetWaypointMax"), XS_NPC_GetWaypointMax, file, "$"); - newXSproto(strcpy(buf, "GetGrid"), XS_NPC_GetGrid, file, "$"); - newXSproto(strcpy(buf, "GetSp2"), XS_NPC_GetSp2, file, "$"); - newXSproto(strcpy(buf, "GetNPCFactionID"), XS_NPC_GetNPCFactionID, file, "$"); - newXSproto(strcpy(buf, "GetPrimaryFaction"), XS_NPC_GetPrimaryFaction, file, "$"); - newXSproto(strcpy(buf, "GetNPCHate"), XS_NPC_GetNPCHate, file, "$$"); - newXSproto(strcpy(buf, "IsOnHatelist"), XS_NPC_IsOnHatelist, file, "$$"); - newXSproto(strcpy(buf, "SetNPCFactionID"), XS_NPC_SetNPCFactionID, file, "$$"); - newXSproto(strcpy(buf, "GetMaxDMG"), XS_NPC_GetMaxDMG, file, "$"); - newXSproto(strcpy(buf, "GetMinDMG"), XS_NPC_GetMinDMG, file, "$"); - newXSproto(strcpy(buf, "IsAnimal"), XS_NPC_IsAnimal, file, "$"); - newXSproto(strcpy(buf, "GetPetSpellID"), XS_NPC_GetPetSpellID, file, "$"); - newXSproto(strcpy(buf, "SetPetSpellID"), XS_NPC_SetPetSpellID, file, "$$"); - newXSproto(strcpy(buf, "GetMaxDamage"), XS_NPC_GetMaxDamage, file, "$$"); - newXSproto(strcpy(buf, "SetTaunting"), XS_NPC_SetTaunting, file, "$$"); - newXSproto(strcpy(buf, "PickPocket"), XS_NPC_PickPocket, file, "$$"); - newXSproto(strcpy(buf, "StartSwarmTimer"), XS_NPC_StartSwarmTimer, file, "$$"); - newXSproto(strcpy(buf, "DoClassAttacks"), XS_NPC_DoClassAttacks, file, "$$"); - newXSproto(strcpy(buf, "GetMaxWp"), XS_NPC_GetMaxWp, file, "$"); - newXSproto(strcpy(buf, "DisplayWaypointInfo"), XS_NPC_DisplayWaypointInfo, file, "$$"); - newXSproto(strcpy(buf, "CalculateNewWaypoint"), XS_NPC_CalculateNewWaypoint, file, "$"); - newXSproto(strcpy(buf, "AssignWaypoints"), XS_NPC_AssignWaypoints, file, "$$"); - newXSproto(strcpy(buf, "SetWaypointPause"), XS_NPC_SetWaypointPause, file, "$"); - newXSproto(strcpy(buf, "UpdateWaypoint"), XS_NPC_UpdateWaypoint, file, "$$"); - newXSproto(strcpy(buf, "StopWandering"), XS_NPC_StopWandering, file, "$"); - newXSproto(strcpy(buf, "ResumeWandering"), XS_NPC_ResumeWandering, file, "$"); - newXSproto(strcpy(buf, "PauseWandering"), XS_NPC_PauseWandering, file, "$$"); - newXSproto(strcpy(buf, "MoveTo"), XS_NPC_MoveTo, file, "$$$$"); - newXSproto(strcpy(buf, "NextGuardPosition"), XS_NPC_NextGuardPosition, file, "$"); - newXSproto(strcpy(buf, "SaveGuardSpot"), XS_NPC_SaveGuardSpot, file, "$;$"); - newXSproto(strcpy(buf, "IsGuarding"), XS_NPC_IsGuarding, file, "$"); - newXSproto(strcpy(buf, "AI_SetRoambox"), XS_NPC_AI_SetRoambox, file, "$$$$$$;$$"); - newXSproto(strcpy(buf, "GetNPCSpellsID"), XS_NPC_GetNPCSpellsID, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointID"), XS_NPC_GetSpawnPointID, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointX"), XS_NPC_GetSpawnPointX, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointY"), XS_NPC_GetSpawnPointY, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointZ"), XS_NPC_GetSpawnPointZ, file, "$"); - newXSproto(strcpy(buf, "GetSpawnPointH"), XS_NPC_GetSpawnPointH, file, "$"); - newXSproto(strcpy(buf, "GetGuardPointX"), XS_NPC_GetGuardPointX, file, "$"); - newXSproto(strcpy(buf, "GetGuardPointY"), XS_NPC_GetGuardPointY, file, "$"); - newXSproto(strcpy(buf, "GetGuardPointZ"), XS_NPC_GetGuardPointZ, file, "$"); - newXSproto(strcpy(buf, "SetPrimSkill"), XS_NPC_SetPrimSkill, file, "$$"); - newXSproto(strcpy(buf, "SetSecSkill"), XS_NPC_SetSecSkill, file, "$$"); - newXSproto(strcpy(buf, "GetPrimSkill"), XS_NPC_GetPrimSkill, file, "$"); - newXSproto(strcpy(buf, "GetSecSkill"), XS_NPC_GetSecSkill, file, "$"); - newXSproto(strcpy(buf, "GetSwarmOwner"), XS_NPC_GetSwarmOwner, file, "$"); - newXSproto(strcpy(buf, "GetSwarmTarget"), XS_NPC_GetSwarmTarget, file, "$"); - newXSproto(strcpy(buf, "SetSwarmTarget"), XS_NPC_SetSwarmTarget, file, "$$"); - newXSproto(strcpy(buf, "ModifyNPCStat"), XS_NPC_ModifyNPCStat, file, "$$$"); - newXSproto(strcpy(buf, "AddAISpell"), XS_NPC_AddSpellToNPCList, file, "$$$$$$$"); - newXSproto(strcpy(buf, "RemoveAISpell"), XS_NPC_RemoveSpellFromNPCList, file, "$$"); - newXSproto(strcpy(buf, "SetSpellFocusDMG"), XS_NPC_SetSpellFocusDMG, file, "$$"); - newXSproto(strcpy(buf, "SetSpellFocusHeal"), XS_NPC_SetSpellFocusHeal, file, "$$"); - newXSproto(strcpy(buf, "GetSpellFocusDMG"), XS_NPC_GetSpellFocusDMG, file, "$"); - newXSproto(strcpy(buf, "GetSpellFocusHeal"), XS_NPC_GetSpellFocusHeal, file, "$"); - newXSproto(strcpy(buf, "GetSlowMitigation"), XS_NPC_GetSlowMitigation, file, "$"); - newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetAttackSpeed, file, "$"); - newXSproto(strcpy(buf, "GetAttackDelay"), XS_NPC_GetAttackDelay, file, "$"); - newXSproto(strcpy(buf, "GetAccuracyRating"), XS_NPC_GetAccuracyRating, file, "$"); - newXSproto(strcpy(buf, "GetAvoidanceRating"), XS_NPC_GetAvoidanceRating, file, "$"); - newXSproto(strcpy(buf, "GetSpawnKillCount"), XS_NPC_GetSpawnKillCount, file, "$"); - newXSproto(strcpy(buf, "GetScore"), XS_NPC_GetScore, file, "$"); - newXSproto(strcpy(buf, "SetMerchantProbability"), XS_NPC_SetMerchantProbability, file, "$$"); - newXSproto(strcpy(buf, "GetMerchantProbability"), XS_NPC_GetMerchantProbability, file, "$"); - newXSproto(strcpy(buf, "AddMeleeProc"), XS_NPC_AddMeleeProc, file, "$$$"); - newXSproto(strcpy(buf, "AddRangedProc"), XS_NPC_AddRangedProc, file, "$$$"); - newXSproto(strcpy(buf, "AddDefensiveProc"), XS_NPC_AddDefensiveProc, file, "$$$"); - XSRETURN_YES; -} - -#endif //EMBPERL_XS_CLASSES - From 365a08ee869f6048f1a7c3a084701a677fe16ca1 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 27 Mar 2016 11:08:08 -0400 Subject: [PATCH 022/693] Removed unneccessary entitylist check from ApplySpellBonuses Fixed an issue with FCBaseEffects not applying bonus when cast on targets from runes. --- zone/bonuses.cpp | 6 +----- zone/mob.h | 6 +++--- zone/mod_functions.cpp | 2 +- zone/spell_effects.cpp | 19 +++++++++++++------ 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 413b8d6c6..f57e92247 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1543,14 +1543,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne { int i, effect_value, base2, max, effectid; bool AdditiveWornBonus = false; - Mob *caster = nullptr; if(!IsAISpellEffect && !IsValidSpell(spell_id)) return; - if(casterId > 0) - caster = entity_list.GetMob(casterId); - for (i = 0; i < EFFECT_COUNT; i++) { //Buffs/Item effects @@ -1577,7 +1573,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne AdditiveWornBonus = true; effectid = spells[spell_id].effectid[i]; - effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, instrument_mod, caster, ticsremaining); + effect_value = CalcSpellEffectValue(spell_id, i, casterlevel, instrument_mod, nullptr, ticsremaining, casterId); base2 = spells[spell_id].base2[i]; max = spells[spell_id].max[i]; } diff --git a/zone/mob.h b/zone/mob.h index 7083e45ca..8cb899d0f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -662,7 +662,7 @@ public: bool TryReflectSpell(uint32 spell_id); bool CanBlockSpell() const { return(spellbonuses.BlockNextSpell); } bool DoHPToManaCovert(uint16 mana_cost = 0); - int32 ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard = false); + int32 ApplySpellEffectiveness(int16 spell_id, int32 value, bool IsBard = false, uint16 caster_id=0); int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect); int32 GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg); void MeleeLifeTap(int32 damage); @@ -898,7 +898,7 @@ public: virtual int32 CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possible = 0); uint32 GetInstrumentMod(uint16 spell_id) const; - int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0); + int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0,uint16 casterid=0); int CalcSpellEffectValue_formula(int formula, int base, int max, int caster_level, uint16 spell_id, int ticsremaining = 0); virtual int CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int caster_level2, Mob* caster1 = nullptr, Mob* caster2 = nullptr, int buffslot = -1); uint32 GetCastedSpellInvSlot() const { return casting_spell_inventory_slot; } @@ -956,7 +956,7 @@ public: inline uint16 GetEmoteID() { return emoteid; } bool HasSpellEffect(int effectid); - int mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster); + int mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster, uint16 caster_id); float mod_hit_chance(float chancetohit, SkillUseTypes skillinuse, Mob* attacker); float mod_riposte_chance(float ripostchance, Mob* attacker); float mod_block_chance(float blockchance, Mob* attacker); diff --git a/zone/mod_functions.cpp b/zone/mod_functions.cpp index 6ae0eddad..5c98541c0 100644 --- a/zone/mod_functions.cpp +++ b/zone/mod_functions.cpp @@ -108,7 +108,7 @@ int Client::mod_food_value(const Item_Struct *item, int change) { return(change) int Client::mod_drink_value(const Item_Struct *item, int change) { return(change); } //effect_vallue - Spell effect value as calculated by default formulas. You will want to ignore effects that don't lend themselves to scaling - pet ID's, gate coords, etc. -int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster) { return(effect_value); } +int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster, uint16 caster_id) { return(effect_value); } //chancetohit - 0 to 100 percent - set over 1000 for a guaranteed hit float Mob::mod_hit_chance(float chancetohit, SkillUseTypes skillinuse, Mob* attacker) { return(chancetohit); } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ecf2bb7ba..f0b93ca9c 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1270,7 +1270,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Melee Absorb Rune: %+i", effect_value); #endif - effect_value = ApplySpellEffectiveness(caster, spell_id, effect_value); + if (caster) + effect_value = caster->ApplySpellEffectiveness(spell_id, effect_value); + buffs[buffslot].melee_rune = effect_value; break; } @@ -3020,7 +3022,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, uint32 instrument_mod, Mob *caster, - int ticsremaining) + int ticsremaining, uint16 caster_id) { int formula, base, max, effect_value; @@ -3048,13 +3050,13 @@ int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, spells[spell_id].effectid[effect_id] != SE_ManaRegen_v2) { int oval = effect_value; - int mod = ApplySpellEffectiveness(caster, spell_id, instrument_mod, true); + int mod = ApplySpellEffectiveness(spell_id, instrument_mod, true, caster_id); effect_value = effect_value * mod / 10; Log.Out(Logs::Detail, Logs::Spells, "Effect value %d altered with bard modifier of %d to yeild %d", oval, mod, effect_value); } - effect_value = mod_effect_value(effect_value, spell_id, spells[spell_id].effectid[effect_id], caster); + effect_value = mod_effect_value(effect_value, spell_id, spells[spell_id].effectid[effect_id], caster, caster_id); return effect_value; } @@ -6043,16 +6045,21 @@ int32 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spel return value; } -int32 Mob::ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard) { +int32 Mob::ApplySpellEffectiveness(int16 spell_id, int32 value, bool IsBard, uint16 caster_id) { // 9-17-12: This is likely causing crashes, disabled till can resolve. if (IsBard) return value; + Mob* caster = this; + + if (caster_id && caster_id != GetID())//Make sure we are checking the casters focus + caster = entity_list.GetMob(caster_id); + if (!caster) return value; - int16 focus = GetFocusEffect(focusFcBaseEffects, spell_id); + int16 focus = caster->GetFocusEffect(focusFcBaseEffects, spell_id); if (IsBard) value += focus; From 9f6e4dd8e7c39196b94bb231c3b90bba8fda7503 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 27 Mar 2016 15:32:45 -0400 Subject: [PATCH 023/693] More appropriate for bot owner targeting issue. Fix for self-following issue using bot_command_follow --- zone/bot_command.cpp | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 124bd7205..c9d7d31bb 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -1898,6 +1898,13 @@ namespace ActionableTarget return (bot_owner->GetGroup() == grouped_player->GetGroup()); } + static bool IsAttackable(Client *bot_owner, Mob* target_mob) { + if (!bot_owner || !target_mob || bot_owner == target_mob) + return false; + + return bot_owner->IsAttackAllowed(target_mob); + } + static Client* AsSingle_ByPlayer(Client *bot_owner, bool return_me_on_null_target = true) { if (!bot_owner) return nullptr; @@ -1940,7 +1947,7 @@ namespace ActionableTarget } static Mob* AsSingle_ByAttackable(Client *bot_owner) { - if (!bot_owner || !bot_owner->IsAttackAllowed(bot_owner->GetTarget())) + if (!IsAttackable(bot_owner, bot_owner->GetTarget())) return nullptr; return bot_owner->GetTarget(); @@ -1954,13 +1961,10 @@ namespace ActionableTarget } static Mob* VerifyFriendly(Client* bot_owner, BCEnum::TType target_type, bool return_me_on_null_target = true) { - if (!bot_owner || target_type == BCEnum::TT_None) + if (IsAttackable(bot_owner, bot_owner->GetTarget()) || target_type == BCEnum::TT_None) return nullptr; auto target_mob = bot_owner->GetTarget(); - if (!IsFriendlyAllowed(target_mob)) - return nullptr; - Mob* verified_friendly = nullptr; switch (target_type) { case BCEnum::TT_Single: @@ -2010,13 +2014,10 @@ namespace ActionableTarget } static Mob* VerifyEnemy(Client* bot_owner, BCEnum::TType target_type) { - if (!bot_owner || target_type == BCEnum::TT_None) + if (!IsAttackable(bot_owner, bot_owner->GetTarget()) || target_type == BCEnum::TT_None) return nullptr; auto target_mob = bot_owner->GetTarget(); - if (!target_mob || !bot_owner->IsAttackAllowed(target_mob)) - return nullptr; - Mob* verified_enemy = nullptr; switch (target_type) { case BCEnum::TT_Animal: @@ -2437,7 +2438,7 @@ void bot_command_actionable(Client *c, const Seperator *sep) c->Message(m_usage, "target - selects target as single bot .. use ^command [target] or imply by empty actionable argument"); c->Message(m_usage, "byname [name] - selects single bot by name"); c->Message(m_usage, "ownergroup - selects all bots in the owner's group"); - c->Message(m_usage, "botgroup [name] - selects members of a bot-group by it's name"); + c->Message(m_usage, "botgroup [name] - selects members of a bot-group by its name"); c->Message(m_usage, "targetgroup - selects all bots in target's group"); c->Message(m_usage, "namesgroup [name] - selects all bots in name's group"); c->Message(m_usage, "healrotation [name] - selects all member and target bots of a heal rotation where name is a member"); @@ -2972,15 +2973,10 @@ void bot_command_follow(Client *c, const Seperator *sep) name_arg = 3; } else { - if (c->GetTarget()) { - if (c != c->GetTarget() && c->IsAttackAllowed(c->GetTarget())) { - c->Message(m_fail, "You must a friendly mob to use this command"); - return; - } - target_mob = c->GetTarget(); - } - else { - target_mob = c; + target_mob = ActionableTarget::VerifyFriendly(c, BCEnum::TT_Single); + if (!target_mob) { + c->Message(m_fail, "You must a friendly mob to use this command"); + return; } } @@ -3000,7 +2996,10 @@ void bot_command_follow(Client *c, const Seperator *sep) bot_iter->SetFollowID(my_group->GetLeader()->GetID()); } else { - bot_iter->SetFollowID(target_mob->GetID()); + if (bot_iter == target_mob) + bot_iter->SetFollowID(c->GetID()); + else + bot_iter->SetFollowID(target_mob->GetID()); } } else { @@ -3917,7 +3916,7 @@ void bot_command_taunt(Client *c, const Seperator *sep) c->Message(m_action, "%i of your bots %s %s taunting", taunting_count, ((taunting_count != 1) ? ("have") : ("has")), ((taunt_state) ? ("started") : ("stopped"))); } else { - c->Message(m_fail, "None of your bots are able to taunt"); + c->Message(m_fail, "None of your bots are capable of taunting"); } } From a82f5f8bf661315778bc6080b3fa657386640f63 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 28 Mar 2016 21:13:37 -0500 Subject: [PATCH 024/693] Allow heroforge textures to be manipulated via perl --- zone/embparser_api.cpp | 15 ++++++++++++--- zone/questmgr.cpp | 4 ++-- zone/questmgr.h | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index bf43e43a1..804d7cbab 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3317,13 +3317,22 @@ XS(XS__wearchange); XS(XS__wearchange) { dXSARGS; - if (items != 2) - Perl_croak(aTHX_ "Usage: wearchange(slot, texture)"); + if (items < 4) + Perl_croak(aTHX_ "Usage: wearchange(slot, texture, [hero_forge_model], [elite_material])"); uint8 slot = (int)SvUV(ST(0)); uint16 texture = (int)SvUV(ST(1)); - quest_manager.wearchange(slot, texture); + uint32 hero_forge_model = 0; + uint32 elite_material = 0; + + if (items > 2) + hero_forge_model = (int)SvUV(ST(2)); + + if (items > 3) + elite_material = (int)SvUV(ST(3)); + + quest_manager.wearchange(slot, texture, hero_forge_model, elite_material); XSRETURN_EMPTY; } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index b16613e75..dc5e3136f 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2881,11 +2881,11 @@ void QuestManager::removetitle(int titleset) { initiator->RemoveTitle(titleset); } -void QuestManager::wearchange(uint8 slot, uint16 texture) +void QuestManager::wearchange(uint8 slot, uint16 texture, uint32 hero_forge_model /*= 0*/, uint32 elite_material /*= 0*/) { QuestManagerCurrentQuestVars(); if(owner){ - owner->SendTextureWC(slot, texture); + owner->SendTextureWC(slot, texture, hero_forge_model, elite_material); if(owner->IsNPC()) { owner->CastToNPC()->NPCSlotTexture(slot, texture); } diff --git a/zone/questmgr.h b/zone/questmgr.h index a4cc2a38b..612c7815f 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -240,7 +240,7 @@ public: bool IsRunning(); void FlyMode(uint8 flymode); uint8 FactionValue(); - void wearchange(uint8 slot, uint16 texture); + void wearchange(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0); void voicetell(const char *str, int macronum, int racenum, int gendernum); void LearnRecipe(uint32 recipe_id); void SendMail(const char *to, const char *from, const char *subject, const char *message); From 5cbf4aca4f6771d5a7ac9545b3d71d8a8fdbe51c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 28 Mar 2016 21:53:46 -0500 Subject: [PATCH 025/693] Slight adjustment to wearchange commit --- zone/embparser_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 804d7cbab..b9b28f0a6 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3317,7 +3317,7 @@ XS(XS__wearchange); XS(XS__wearchange) { dXSARGS; - if (items < 4) + if (items < 2) Perl_croak(aTHX_ "Usage: wearchange(slot, texture, [hero_forge_model], [elite_material])"); uint8 slot = (int)SvUV(ST(0)); From ba5b3c2796248a362da62e1e5258ed217be5a5a5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 29 Mar 2016 15:11:59 -0400 Subject: [PATCH 026/693] Update fling struct and add Fling to lua opcode enum --- common/eq_packet_structs.h | 6 +++--- zone/lua_packet.cpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 0022aa347..2a25450e8 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -5361,10 +5361,10 @@ struct TextLinkBody_Struct { struct fling_struct { -/* 00 */ uint32 unk1; +/* 00 */ uint32 collision; // 0 collision is off, anything else it's on /* 04 */ int32 travel_time; // ms -- UF we need to calc this, RoF+ -1 auto calcs -/* 08 */ char unk3; // bool, set to 1 has something to do with z-axis or something -/* 09 */ char disable_fall_damage; // 1 you take no fall damage, 0 you take fall damage +/* 08 */ uint8 unk3; // bool, set to 1 has something to do with z-axis or something weird things happen if the new Z is above or equal to yours +/* 09 */ uint8 disable_fall_damage; // 1 you take no fall damage, 0 you take fall damage /* 10 */ uint8 padding[2]; /* 12 */ float speed_z; /* 16 */ float new_y; diff --git a/zone/lua_packet.cpp b/zone/lua_packet.cpp index 1eef7220d..648d6fa87 100644 --- a/zone/lua_packet.cpp +++ b/zone/lua_packet.cpp @@ -847,7 +847,8 @@ luabind::scope lua_register_packet_opcodes() { luabind::value("OpenContainer", static_cast(OP_OpenContainer)), luabind::value("Marquee", static_cast(OP_Marquee)), luabind::value("ClientTimeStamp", static_cast(OP_ClientTimeStamp)), - luabind::value("GuildPromote", static_cast(OP_GuildPromote)) + luabind::value("GuildPromote", static_cast(OP_GuildPromote)), + luabind::value("Fling", static_cast(OP_Fling)) ]; } From 1f5eeda79e92c9b1786423de0890418d42f38a39 Mon Sep 17 00:00:00 2001 From: hateborne Date: Thu, 31 Mar 2016 13:09:36 -0400 Subject: [PATCH 027/693] Exported GetSpellIDFromSlot into Perl Exported the GetSpellIDFromSlot into Perl. Currently, there are numerous Perl objections that can accept buff slot info, but nothing that can return the buffs a mob/client currently has. This lets us iterate over them with a loop, returning -1 if the slot requested doesn't exist. --- zone/perl_mob.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 8f96849df..2819d2bf2 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -2362,6 +2362,37 @@ XS(XS_Mob_GetSpellHPBonuses) XSRETURN(1); } +XS(XS_Mob_GetSpellIDFromSlot); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_GetSpellIDFromSlot) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Mob::GetSpellIDFromSlot(THIS, slot)"); + { + Mob * THIS; + int RETVAL; + dXSTARG; + uint8 slot = (uint16)SvUV(ST(1)); + + if (sv_derived_from(ST(0), "Mob")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Mob *, tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Mob"); + if (THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (slot > THIS->GetMaxBuffSlots()) + RETVAL = -1; + else + RETVAL = THIS->GetSpellIDFromSlot(slot); + + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + XS(XS_Mob_GetWalkspeed); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_GetWalkspeed) { @@ -9105,6 +9136,7 @@ XS(boot_Mob) newXSproto(strcpy(buf, "GetMaxHP"), XS_Mob_GetMaxHP, file, "$"); newXSproto(strcpy(buf, "GetItemHPBonuses"), XS_Mob_GetItemHPBonuses, file, "$"); newXSproto(strcpy(buf, "GetSpellHPBonuses"), XS_Mob_GetSpellHPBonuses, file, "$"); + newXSproto(strcpy(buf, "GetSpellIDFromSlot"), XS_Mob_GetSpellIDFromSlot, file, "$$"); newXSproto(strcpy(buf, "GetWalkspeed"), XS_Mob_GetWalkspeed, file, "$"); newXSproto(strcpy(buf, "GetRunspeed"), XS_Mob_GetRunspeed, file, "$"); newXSproto(strcpy(buf, "GetCasterLevel"), XS_Mob_GetCasterLevel, file, "$$"); From 22b7e76537b781b8644bc757c65b1a5bba879dc1 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 5 Apr 2016 14:23:49 -0500 Subject: [PATCH 028/693] Added "nolock" argument option, allows database backups while server is online --- utils/scripts/db_dumper.pl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/utils/scripts/db_dumper.pl b/utils/scripts/db_dumper.pl index dd0808bca..5b4bb229d 100644 --- a/utils/scripts/db_dumper.pl +++ b/utils/scripts/db_dumper.pl @@ -32,6 +32,7 @@ if(!$ARGV[0]){ print " database=\"dbname\" - Manually specify databasename, default is database in eqemu_config.xml\n"; print " tables=\"table1,table2,table3\" - Manually specify tables, default is to dump all tables from database\n"; print " compress - Compress Database with 7-ZIP, will fallback to WinRAR depending on what is installed (Must be installed to default program dir)...\n"; + print " nolock - Does not lock tables, meant for backuping while the server is running..\n"; print ' Example: perl DB_Dumper.pl Loc="E:\Backups"' . "\n\n"; print "######################################################\n"; exit; @@ -59,6 +60,9 @@ print "Arguments\n" if $Debug; $n = 0; while($ARGV[$n]){ print $n . ': ' . $ARGV[$n] . "\n" if $Debug; + if($ARGV[$n]=~/nolock/i){ + $no_lock = 1; + } if($ARGV[$n]=~/compress/i){ print "Compression SET\n"; $Compress = 1; @@ -109,7 +113,10 @@ if($t_tables ne ""){ print "Performing table based backup...\n"; #::: Backup Database... print "Backing up Database " . $db . "... \n\n"; - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' ' . $t_tables . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; + if($no_lock == 1){ + $added_parameters .= " --skip-lock-tables "; + } + $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' ' . $t_tables . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; printcmd($cmd); system($cmd); } @@ -117,7 +124,10 @@ else{ #::: Entire DB Backup $target_file = '' . $db . '_' . $date . ''; #::: Backup Database... print "Backing up Database " . $db . "... \n\n"; - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; + if($no_lock == 1){ + $added_parameters .= " --skip-lock-tables "; + } + $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; printcmd($cmd); system($cmd); } From e759bb6da8c829c3347b56bdcf2d094de8fb4a88 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 5 Apr 2016 18:37:19 -0400 Subject: [PATCH 029/693] Moved class Bot database code into class BotDatbase --- changelog.txt | 3 + common/version.h | 2 +- .../sql/git/bots/bots_db_update_manifest.txt | 1 + .../2016_04_05_bots_pet_spell_id_field.sql | 1 + zone/bot.cpp | 1641 +++--------- zone/bot.h | 80 +- zone/bot_command.cpp | 540 ++-- zone/bot_database.cpp | 2247 +++++++++++++++-- zone/bot_database.h | 245 +- zone/bot_structs.h | 12 +- zone/questmgr.cpp | 18 +- zone/zonedb.cpp | 33 + zone/zonedb.h | 4 + 13 files changed, 2899 insertions(+), 1928 deletions(-) create mode 100644 utils/sql/git/bots/required/2016_04_05_bots_pet_spell_id_field.sql diff --git a/changelog.txt b/changelog.txt index 6ee721e64..913204cab 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/05/2016 == +Uleat: Moved database query code out of bot.cpp and into the new BotDatabase class + == 03/25/2016 == Uleat: Fix for heal rotation 'Stack Overflow' error Kayen: Defensive procs will now only proc once per attack round (instead of every attack chance). diff --git a/common/version.h b/common/version.h index 64c063917..248ce3beb 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9096 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9002 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9003 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 12e5996f2..f25bac0de 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -1,6 +1,7 @@ 9000|2015_09_30_bots.sql|SHOW TABLES LIKE 'bot_data'|empty| 9001|2016_03_24_bots_command_settings.sql|SHOW TABLES LIKE 'bot_command_settings'|empty| 9002|2016_03_24_bots_command_rules.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CommandSpellRank'|empty| +9003|2016_04_05_bots_pet_spell_id_field.sql|EXPLAIN `bot_pets`|contains|pet_id # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2016_04_05_bots_pet_spell_id_field.sql b/utils/sql/git/bots/required/2016_04_05_bots_pet_spell_id_field.sql new file mode 100644 index 000000000..d2d930160 --- /dev/null +++ b/utils/sql/git/bots/required/2016_04_05_bots_pet_spell_id_field.sql @@ -0,0 +1 @@ +ALTER TABLE `bot_pets` CHANGE COLUMN `pet_id` `spell_id` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `pets_index`; diff --git a/zone/bot.cpp b/zone/bot.cpp index 6cb27f8e7..21cdd6d46 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -94,14 +94,18 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm strcpy(this->name, this->GetCleanName()); memset(&m_Light, 0, sizeof(LightProfile_Struct)); + memset(&_botInspectMessage, 0, sizeof(InspectMessage_Struct)); } // This constructor is used when the bot is loaded out of the database -Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData) : NPC(&npcTypeData, nullptr, glm::vec4(), 0, false), rest_timer(1) { +Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData) : NPC(&npcTypeData, nullptr, glm::vec4(), 0, false), rest_timer(1) +{ this->_botOwnerCharacterID = botOwnerCharacterID; if(this->_botOwnerCharacterID > 0) this->SetBotOwner(entity_list.GetClientByCharID(this->_botOwnerCharacterID)); + auto bot_owner = GetBotOwner(); + _guildRank = 0; _guildId = 0; _lastTotalPlayTime = totalPlayTime; @@ -138,7 +142,13 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SetPetChooser(false); SetRangerAutoWeaponSelect(false); SetHasBeenSummoned(false); - LoadStance(); + + bool stance_flag = false; + if (!botdb.LoadStance(this, stance_flag) && bot_owner) + bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::LoadStance(), GetCleanName()); + if (!stance_flag && bot_owner) + bot_owner->Message(13, "Could not locate stance for '%s'", GetCleanName()); + SetTaunting((GetClass() == WARRIOR || GetClass() == PALADIN || GetClass() == SHADOWKNIGHT) && (GetBotStance() == BotStanceAggressive)); SetPauseAI(false); @@ -146,22 +156,36 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to rest_timer.Disable(); SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE); strcpy(this->name, this->GetCleanName()); - botdb.GetInspectMessage(this->GetBotID(), &_botInspectMessage); - LoadGuildMembership(&_guildId, &_guildRank, &_guildName); - std::string TempErrorMessage; - EquipBot(&TempErrorMessage); - if(!TempErrorMessage.empty()) { - if(GetBotOwner()) - GetBotOwner()->Message(13, TempErrorMessage.c_str()); + + memset(&_botInspectMessage, 0, sizeof(InspectMessage_Struct)); + if (!botdb.LoadInspectMessage(GetBotID(), _botInspectMessage) && bot_owner) + bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::LoadInspectMessage(), GetCleanName()); + + if (!botdb.LoadGuildMembership(GetBotID(), _guildId, _guildRank, _guildName) && bot_owner) + bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::LoadGuildMembership(), GetCleanName()); + + std::string error_message; + + EquipBot(&error_message); + if(!error_message.empty()) { + if(bot_owner) + bot_owner->Message(13, error_message.c_str()); + error_message.clear(); } for (int i = 0; i < MaxTimer; i++) timers[i] = 0; GenerateBaseStats(); - LoadTimers(); + + if (!botdb.LoadTimers(this) && bot_owner) + bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::LoadTimers(), GetCleanName()); + LoadAAs(); - LoadBuffs(); + + if (!botdb.LoadBuffs(this) && bot_owner) + bot_owner->Message(13, "&s for '%s'", BotDatabase::fail::LoadBuffs(), GetCleanName()); + CalcBotStats(false); hp_regen = CalcHPRegen(); mana_regen = CalcManaRegen(); @@ -1530,272 +1554,89 @@ bool Bot::IsValidName(std::string& name) return true; } -bool Bot::IsBotNameAvailable(const char *botName, std::string* errorMessage) { - if (botName == "" || strlen(botName) > 15 || !database.CheckNameFilter(botName) || !database.CheckUsedName(botName)) - return false; - - std::string query = StringFormat("SELECT `id` FROM `vw_bot_character_mobs` WHERE `name` LIKE '%s'", botName); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return false; - } - - if (results.RowCount()) - return false; - - return true; //We made it with a valid name! -} - bool Bot::Save() { - if(this->GetBotID() == 0) { - // New bot record - std::string query = StringFormat( - "INSERT INTO `bot_data` (" - " `owner_id`," - " `spells_id`," - " `name`," - " `last_name`," - " `zone_id`," - " `gender`," - " `race`," - " `class`," - " `level`," - " `creation_day`," - " `last_spawn`," - " `time_spawned`," - " `size`," - " `face`," - " `hair_color`," - " `hair_style`," - " `beard`," - " `beard_color`," - " `eye_color_1`," - " `eye_color_2`," - " `drakkin_heritage`," - " `drakkin_tattoo`," - " `drakkin_details`," - " `ac`," - " `atk`," - " `hp`," - " `mana`," - " `str`," - " `sta`," - " `cha`," - " `dex`," - " `int`," - " `agi`," - " `wis`," - " `fire`," - " `cold`," - " `magic`," - " `poison`," - " `disease`," - " `corruption`," - " `show_helm`," - " `follow_distance`" - ")" - " VALUES (" - "'%u'," /*owner_id*/ - " '%u'," /*spells_id*/ - " '%s'," /*name*/ - " '%s'," /*last_name*/ - " '%i'," /*zone_id*/ - " '%i'," /*gender*/ - " '%i'," /*race*/ - " '%i'," /*class*/ - " '%u'," /*level*/ - " UNIX_TIMESTAMP(),"/*creation_day*/ - " UNIX_TIMESTAMP(),"/*last_spawn*/ - " 0," /*time_spawned*/ - " '%f'," /*size*/ - " '%i'," /*face*/ - " '%i'," /*hair_color*/ - " '%i'," /*hair_style*/ - " '%i'," /*beard*/ - " '%i'," /*beard_color*/ - " '%i'," /*eye_color_1*/ - " '%i'," /*eye_color_2*/ - " '%i'," /*drakkin_heritage*/ - " '%i'," /*drakkin_tattoo*/ - " '%i'," /*drakkin_details*/ - " '%i'," /*ac*/ - " '%i'," /*atk*/ - " '%i'," /*hp*/ - " '%i'," /*mana*/ - " '%i'," /*str*/ - " '%i'," /*sta*/ - " '%i'," /*cha*/ - " '%i'," /*dex*/ - " '%i'," /*int*/ - " '%i'," /*agi*/ - " '%i'," /*wis*/ - " '%i'," /*fire*/ - " '%i'," /*cold*/ - " '%i'," /*magic*/ - " '%i'," /*poison*/ - " '%i'," /*disease*/ - " '%i'," /*corruption*/ - " '1'," /*show_helm*/ - " '%i'" /*follow_distance*/ - ")", - this->_botOwnerCharacterID, - this->GetBotSpellID(), - this->GetCleanName(), - this->lastname, - _lastZoneId, - GetGender(), - GetRace(), - GetClass(), - this->GetLevel(), - GetSize(), - this->GetLuclinFace(), - GetHairColor(), - this->GetHairStyle(), - this->GetBeard(), - this->GetBeardColor(), - this->GetEyeColor1(), - this->GetEyeColor2(), - this->GetDrakkinHeritage(), - this->GetDrakkinTattoo(), - this->GetDrakkinDetails(), - GetAC(), - GetATK(), - GetHP(), - GetMana(), - GetSTR(), - GetSTA(), - GetCHA(), - GetDEX(), - GetINT(), - GetAGI(), - GetWIS(), - GetFR(), - GetCR(), - GetMR(), - GetPR(), - GetDR(), - GetCorrup(), - BOT_DEFAULT_FOLLOW_DISTANCE - ); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - auto botOwner = GetBotOwner(); - if (botOwner) - botOwner->Message(13, results.ErrorMessage().c_str()); - + auto bot_owner = GetBotOwner(); + if (!bot_owner) + return false; + + std::string error_message; + + if(!GetBotID()) { // New bot record + uint32 bot_id = 0; + if (!botdb.SaveNewBot(this, bot_id) || !bot_id) { + bot_owner->Message(13, "%s '%s'", BotDatabase::fail::SaveNewBot(), GetCleanName()); + return false; + } + SetBotID(bot_id); + } + else { // Update existing bot record + if (!botdb.SaveBot(this)) { + bot_owner->Message(13, "%s '%s'", BotDatabase::fail::SaveBot(), GetCleanName()); return false; } - - SetBotID(results.LastInsertedID()); - SaveBuffs(); - SavePet(); - SaveStance(); - SaveTimers(); - return true; } - // Update existing bot record - std::string query = StringFormat( - "UPDATE `bot_data`" - " SET" - " `owner_id` = '%u'," - " `spells_id` = '%u'," - " `name` = '%s'," - " `last_name` = '%s'," - " `zone_id` = '%i'," - " `gender` = '%i'," - " `race` = '%i'," - " `class` = '%i'," - " `level` = '%u'," - " `last_spawn` = UNIX_TIMESTAMP()," - " `time_spawned` = '%u'," - " `size` = '%f'," - " `face` = '%i'," - " `hair_color` = '%i'," - " `hair_style` = '%i'," - " `beard` = '%i'," - " `beard_color` = '%i'," - " `eye_color_1` = '%i'," - " `eye_color_2` = '%i'," - " `drakkin_heritage` = '%i'," - " `drakkin_tattoo` = '%i'," - " `drakkin_details` = '%i'," - " `ac` = '%i'," - " `atk` = '%i'," - " `hp` = '%i'," - " `mana` = '%i'," - " `str` = '%i'," - " `sta` = '%i'," - " `cha` = '%i'," - " `dex` = '%i'," - " `int` = '%i'," - " `agi` = '%i'," - " `wis` = '%i'," - " `fire` = '%i'," - " `cold` = '%i'," - " `magic` = '%i'," - " `poison` = '%i'," - " `disease` = '%i'," - " `corruption` = '%i'," - " `show_helm` = '%i'," - " `follow_distance` = '%i'" - " WHERE `bot_id` = '%u'", - _botOwnerCharacterID, - this->GetBotSpellID(), - this->GetCleanName(), - this->lastname, - _lastZoneId, - _baseGender, - _baseRace, - this->GetClass(), - this->GetLevel(), - GetTotalPlayTime(), - GetSize(), - this->GetLuclinFace(), - GetHairColor(), - this->GetHairStyle(), - this->GetBeard(), - this->GetBeardColor(), - this->GetEyeColor1(), - this->GetEyeColor2(), - this->GetDrakkinHeritage(), - GetDrakkinTattoo(), - GetDrakkinDetails(), - _baseAC, - _baseATK, - GetHP(), - GetMana(), - _baseSTR, - _baseSTA, - _baseCHA, - _baseDEX, - _baseINT, - _baseAGI, - _baseWIS, - _baseFR, - _baseCR, - _baseMR, - _basePR, - _baseDR, - _baseCorrup, - (GetShowHelm() ? 1 : 0), - GetFollowDistance(), - GetBotID() - ); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - auto botOwner = GetBotOwner(); - if (botOwner) - botOwner->Message(13, results.ErrorMessage().c_str()); - + // All of these continue to process if any fail + if (!botdb.SaveBuffs(this)) + bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::SaveBuffs(), GetCleanName()); + if (!botdb.SaveTimers(this)) + bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::SaveTimers(), GetCleanName()); + if (!botdb.SaveStance(this)) + bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::SaveStance(), GetCleanName()); + + if (!SavePet()) + bot_owner->Message(13, "Failed to save pet for '%s'", GetCleanName()); + + return true; +} + +bool Bot::DeleteBot() +{ + auto bot_owner = GetBotOwner(); + if (!bot_owner) + return false; + + if (!DeletePet()) { + bot_owner->Message(13, "Failed to delete pet for '%s'", GetCleanName()); return false; } - SaveBuffs(); - SavePet(); - SaveStance(); - SaveTimers(); + + if (GetGroup()) + RemoveBotFromGroup(this, GetGroup()); + + std::string error_message; + + if (!botdb.RemoveMemberFromBotGroup(GetBotID())) { + bot_owner->Message(13, "%s - '%s'", BotDatabase::fail::RemoveMemberFromBotGroup(), GetCleanName()); + return false; + } + + if (!botdb.DeleteItems(GetBotID())) { + bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::DeleteItems(), GetCleanName()); + return false; + } + + if (!botdb.DeleteTimers(GetBotID())) { + bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::DeleteTimers(), GetCleanName()); + return false; + } + + if (!botdb.DeleteBuffs(GetBotID())) { + bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::DeleteBuffs(), GetCleanName()); + return false; + } + + if (!botdb.DeleteStance(GetBotID())) { + bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::DeleteStance(), GetCleanName()); + return false; + } + + if (!botdb.DeleteBot(GetBotID())) { + bot_owner->Message(13, "%s '%s'", BotDatabase::fail::DeleteBot(), GetCleanName()); + return false; + } + return true; } @@ -1810,461 +1651,139 @@ uint32 Bot::GetTotalPlayTime() { return Result; } -void Bot::SaveBuffs() +bool Bot::LoadPet() { - // Remove any existing buff saves - std::string query = StringFormat("DELETE FROM `bot_buffs` WHERE `bot_id` = %u", GetBotID()); - auto results = database.QueryDatabase(query); - if(!results.Success()) - return; + if (GetPet()) + return true; + + auto bot_owner = GetBotOwner(); + if (!bot_owner) + return false; - for (int buffIndex = 0; buffIndex < BUFF_COUNT; buffIndex++) { - if (buffs[buffIndex].spellid <= 0 || buffs[buffIndex].spellid == SPELL_UNKNOWN) - continue; - - int isPersistent = buffs[buffIndex].persistant_buff ? 1 : 0; - query = StringFormat( - "INSERT INTO `bot_buffs` (" - "`bot_id`," - " `spell_id`," - " `caster_level`," - " `duration_formula`," - " `tics_remaining`," - " `poison_counters`," - " `disease_counters`," - " `curse_counters`," - " `corruption_counters`," - " `numhits`," - " `melee_rune`," - " `magic_rune`," - " `dot_rune`," - " `persistent`," - " `caston_x`," - " `caston_y`," - " `caston_z`," - " `extra_di_chance`" - ")" - " VALUES (" - "%u," /*bot_id*/ - " %u," /*spell_id*/ - " %u," /*caster_level*/ - " %u," /*duration_formula*/ - " %u," /*tics_remaining*/ - " %u," /*poison_counters*/ - " %u," /*disease_counters*/ - " %u," /*curse_counters*/ - " %u," /*corruption_counters*/ - " %u," /*numhits*/ - " %u," /*melee_rune*/ - " %u," /*magic_rune*/ - " %u," /*dot_rune*/ - " %u," /*persistent*/ - " %i," /*caston_x*/ - " %i," /*caston_y*/ - " %i," /*caston_z*/ - " %i" /*extra_di_chance*/ - ")", - GetBotID(), - buffs[buffIndex].spellid, - buffs[buffIndex].casterlevel, - spells[buffs[buffIndex].spellid].buffdurationformula, - buffs[buffIndex].ticsremaining, - CalculatePoisonCounters(buffs[buffIndex].spellid) > 0 ? buffs[buffIndex].counters : 0, - CalculateDiseaseCounters(buffs[buffIndex].spellid) > 0 ? buffs[buffIndex].counters : 0, - CalculateCurseCounters(buffs[buffIndex].spellid) > 0 ? buffs[buffIndex].counters : 0, - CalculateCorruptionCounters(buffs[buffIndex].spellid) > 0 ? buffs[buffIndex].counters : 0, - buffs[buffIndex].numhits, - buffs[buffIndex].melee_rune, - buffs[buffIndex].magic_rune, - buffs[buffIndex].dot_rune, - isPersistent, - buffs[buffIndex].caston_x, - buffs[buffIndex].caston_y, - buffs[buffIndex].caston_z, - buffs[buffIndex].ExtraDIChance - ); - auto results = database.QueryDatabase(query); - if(!results.Success()) - return; + std::string error_message; + + uint32 pet_index = 0; + if (!botdb.LoadPetIndex(GetBotID(), pet_index)) { + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetIndex(), GetCleanName()); + return false; } + if (!pet_index) + return true; + + uint32 saved_pet_spell_id = 0; + if (!botdb.LoadPetSpellID(GetBotID(), saved_pet_spell_id)) { + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetSpellID(), GetCleanName()); + } + if (!saved_pet_spell_id || saved_pet_spell_id > SPDAT_RECORDS) { + bot_owner->Message(13, "Invalid spell id for %s's pet", GetCleanName()); + DeletePet(); + return false; + } + + std::string pet_name; + uint32 pet_mana = 0; + uint32 pet_hp = 0; + uint32 pet_spell_id = 0; + + if (!botdb.LoadPetStats(GetBotID(), pet_name, pet_mana, pet_hp, pet_spell_id)) { + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetStats(), GetCleanName()); + return false; + } + + MakePet(pet_spell_id, spells[pet_spell_id].teleport_zone, pet_name.c_str()); + if (!GetPet() || !GetPet()->IsNPC()) { + DeletePet(); + return false; + } + + NPC *pet_inst = GetPet()->CastToNPC(); + + SpellBuff_Struct pet_buffs[BUFF_COUNT]; + memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * BUFF_COUNT)); + if (!botdb.LoadPetBuffs(GetBotID(), pet_buffs)) + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetBuffs(), GetCleanName()); + + uint32 pet_items[EmuConstants::EQUIPMENT_SIZE]; + memset(pet_items, 0, (sizeof(uint32) * EmuConstants::EQUIPMENT_SIZE)); + if (!botdb.LoadPetItems(GetBotID(), pet_items)) + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetItems(), GetCleanName()); + + pet_inst->SetPetState(pet_buffs, pet_items); + pet_inst->CalcBonuses(); + pet_inst->SetHP(pet_hp); + pet_inst->SetMana(pet_mana); + + return true; } -void Bot::LoadBuffs() +bool Bot::SavePet() { - std::string query = StringFormat( - "SELECT" - " `spell_id`," - " `caster_level`," - " `duration_formula`," - " `tics_remaining`," - " `poison_counters`," - " `disease_counters`," - " `curse_counters`," - " `corruption_counters`," - " `numhits`," - " `melee_rune`," - " `magic_rune`," - " `dot_rune`," - " `persistent`," - " `caston_x`," - " `caston_y`," - " `caston_z`," - " `extra_di_chance`" - " FROM `bot_buffs`" - " WHERE `bot_id` = '%u'", - GetBotID() - ); - auto results = database.QueryDatabase(query); - if(!results.Success()) - return; + if (!GetPet() /*|| dead*/) + return true; - int buffCount = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - if(buffCount == BUFF_COUNT) - break; - - buffs[buffCount].spellid = atoi(row[0]); - buffs[buffCount].casterlevel = atoi(row[1]); - //row[2] (duration_formula) can probably be removed - buffs[buffCount].ticsremaining = atoi(row[3]); + NPC *pet_inst = GetPet()->CastToNPC(); + if (pet_inst->IsFamiliar() || !pet_inst->GetPetSpellID() || pet_inst->GetPetSpellID() > SPDAT_RECORDS) + return false; - if(CalculatePoisonCounters(buffs[buffCount].spellid) > 0) - buffs[buffCount].counters = atoi(row[4]); - else if(CalculateDiseaseCounters(buffs[buffCount].spellid) > 0) - buffs[buffCount].counters = atoi(row[5]); - else if(CalculateCurseCounters(buffs[buffCount].spellid) > 0) - buffs[buffCount].counters = atoi(row[6]); - else if(CalculateCorruptionCounters(buffs[buffCount].spellid) > 0) - buffs[buffCount].counters = atoi(row[7]); - - buffs[buffCount].numhits = atoi(row[8]); - buffs[buffCount].melee_rune = atoi(row[9]); - buffs[buffCount].magic_rune = atoi(row[10]); - buffs[buffCount].dot_rune = atoi(row[11]); - buffs[buffCount].persistant_buff = atoi(row[12]) ? true : false; - buffs[buffCount].caston_x = atoi(row[13]); - buffs[buffCount].caston_y = atoi(row[14]); - buffs[buffCount].caston_z = atoi(row[15]); - buffs[buffCount].ExtraDIChance = atoi(row[16]); - buffs[buffCount].casterid = 0; - ++buffCount; - } - query = StringFormat("DELETE FROM `bot_buffs` WHERE `bot_id` = %u", GetBotID()); - results = database.QueryDatabase(query); -} + auto bot_owner = GetBotOwner(); + if (!bot_owner) + return false; -uint32 Bot::GetPetSaveId() -{ - std::string query = StringFormat("SELECT `pets_index` FROM `bot_pets` WHERE `bot_id` = %u", GetBotID()); - auto results = database.QueryDatabase(query); - if(!results.Success() || results.RowCount() == 0) - return 0; + char* pet_name = new char[64]; + SpellBuff_Struct pet_buffs[BUFF_COUNT]; + uint32 pet_items[EmuConstants::EQUIPMENT_SIZE]; - auto row = results.begin(); - return atoi(row[0]); -} - -void Bot::LoadPet() { - uint32 PetSaveId = GetPetSaveId(); - if(PetSaveId > 0 && !GetPet() && PetSaveId <= SPDAT_RECORDS) { - std::string petName; - uint32 petMana = 0; - uint32 petHitPoints = 0; - uint32 botPetId = 0; - LoadPetStats(&petName, &petMana, &petHitPoints, &botPetId, PetSaveId); - MakePet(botPetId, spells[botPetId].teleport_zone, petName.c_str()); - if(GetPet() && GetPet()->IsNPC()) { - NPC *pet = GetPet()->CastToNPC(); - SpellBuff_Struct petBuffs[BUFF_COUNT]; - memset(petBuffs, 0, sizeof(petBuffs)); - uint32 petItems[EmuConstants::EQUIPMENT_SIZE]; - - LoadPetBuffs(petBuffs, PetSaveId); - LoadPetItems(petItems, PetSaveId); - - pet->SetPetState(petBuffs, petItems); - pet->CalcBonuses(); - pet->SetHP(petHitPoints); - pet->SetMana(petMana); - } - DeletePetStats(PetSaveId); - } -} - -void Bot::LoadPetStats(std::string* petName, uint32* petMana, uint32* petHitPoints, uint32* botPetId, uint32 botPetSaveId) -{ - if(botPetSaveId == 0) - return; - - std::string query = StringFormat("SELECT `pet_id`, `name`, `mana`, `hp` FROM `bot_pets` WHERE `pets_index` = %u", botPetSaveId); - auto results = database.QueryDatabase(query); - if(!results.Success() || results.RowCount() == 0) - return; - - auto row = results.begin(); - *botPetId = atoi(row[0]); - *petName = std::string(row[1]); - *petMana = atoi(row[2]); - *petHitPoints = atoi(row[3]); -} - -void Bot::LoadPetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) { - if(!petBuffs || botPetSaveId == 0) - return; - - std::string query = StringFormat("SELECT `spell_id`, `caster_level`, `duration` FROM `bot_pet_buffs` WHERE `pets_index` = %u;", botPetSaveId); - auto results = database.QueryDatabase(query); - if(!results.Success()) - return; - - int buffIndex = 0; - for (auto row = results.begin();row != results.end(); ++row) { - if(buffIndex == BUFF_COUNT) - break; - - petBuffs[buffIndex].spellid = atoi(row[0]); - petBuffs[buffIndex].level = atoi(row[1]); - petBuffs[buffIndex].duration = atoi(row[2]); - //Work around for loading the counters and setting them back to max. Need entry in DB for saved counters - if(CalculatePoisonCounters(petBuffs[buffIndex].spellid) > 0) - petBuffs[buffIndex].counters = CalculatePoisonCounters(petBuffs[buffIndex].spellid); - else if(CalculateDiseaseCounters(petBuffs[buffIndex].spellid) > 0) - petBuffs[buffIndex].counters = CalculateDiseaseCounters(petBuffs[buffIndex].spellid); - else if(CalculateCurseCounters(petBuffs[buffIndex].spellid) > 0) - petBuffs[buffIndex].counters = CalculateCurseCounters(petBuffs[buffIndex].spellid); - else if(CalculateCorruptionCounters(petBuffs[buffIndex].spellid) > 0) - petBuffs[buffIndex].counters = CalculateCorruptionCounters(petBuffs[buffIndex].spellid); - - buffIndex++; - } - query = StringFormat("DELETE FROM `bot_pet_buffs` WHERE `pets_index` = %u;", botPetSaveId); - results = database.QueryDatabase(query); -} - -void Bot::LoadPetItems(uint32* petItems, uint32 botPetSaveId) { - if(!petItems || botPetSaveId == 0) - return; - - std::string query = StringFormat("SELECT `item_id` FROM `bot_pet_inventories` WHERE `pets_index` = %u;", botPetSaveId); - auto results = database.QueryDatabase(query); - if(!results.Success()) - return; - - int itemIndex = 0; - for(auto row = results.begin(); row != results.end(); ++row) { - if(itemIndex == EmuConstants::EQUIPMENT_SIZE) - break; - - petItems[itemIndex] = atoi(row[0]); - itemIndex++; - } - query = StringFormat("DELETE FROM `bot_pet_inventories` WHERE `pets_index` = %u", botPetSaveId); - results = database.QueryDatabase(query); -} - -void Bot::SavePet() { - if(GetPet() && !GetPet()->IsFamiliar() && GetPet()->CastToNPC()->GetPetSpellID() /*&& !dead*/) { - NPC *pet = GetPet()->CastToNPC(); - uint16 petMana = pet->GetMana(); - uint16 petHitPoints = pet->GetHP(); - uint32 botPetId = pet->CastToNPC()->GetPetSpellID(); - char* tempPetName = new char[64]; - SpellBuff_Struct petBuffs[BUFF_COUNT]; - uint32 petItems[EmuConstants::EQUIPMENT_SIZE]; - pet->GetPetState(petBuffs, petItems, tempPetName); - uint32 existingBotPetSaveId = GetPetSaveId(); - if(existingBotPetSaveId > 0) { - // Remove any existing pet buffs - DeletePetBuffs(existingBotPetSaveId); - // Remove any existing pet items - DeletePetItems(existingBotPetSaveId); - } - // Save pet stats and get a new bot pet save id - uint32 botPetSaveId = SavePetStats(std::string(tempPetName), petMana, petHitPoints, botPetId); - // Save pet buffs - SavePetBuffs(petBuffs, botPetSaveId); - // Save pet items - SavePetItems(petItems, botPetSaveId); - if(tempPetName) - safe_delete_array(tempPetName); - } -} - -uint32 Bot::SavePetStats(std::string petName, uint32 petMana, uint32 petHitPoints, uint32 botPetId) -{ - std::string query = StringFormat( - "REPLACE INTO `bot_pets`" - " SET" - " `pet_id` = %u," - " `bot_id` = %u," - " `name` = '%s'," - " `mana` = %u," - " `hp` = %u", - botPetId, - GetBotID(), - petName.c_str(), - petMana, - petHitPoints - ); - auto results = database.QueryDatabase(query); - return results.LastInsertedID(); -} - -void Bot::SavePetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId) -{ - if(!petBuffs || botPetSaveId == 0) - return; + memset(pet_name, 0, 64); + memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * BUFF_COUNT)); + memset(pet_items, 0, (sizeof(uint32) * EmuConstants::EQUIPMENT_SIZE)); - int buffIndex = 0; - while(buffIndex < BUFF_COUNT) { - if(petBuffs[buffIndex].spellid > 0 && petBuffs[buffIndex].spellid != SPELL_UNKNOWN) { - std::string query = StringFormat( - "INSERT INTO `bot_pet_buffs` (" - "`pets_index`," - " `spell_id`," - " `caster_level`," - " `duration`" - ")" - " VALUES (" - "%u," - " %u," - " %u," - " %u" - ")", - botPetSaveId, - petBuffs[buffIndex].spellid, - petBuffs[buffIndex].level, - petBuffs[buffIndex].duration - ); - auto results = database.QueryDatabase(query); - if(!results.Success()) - break; - } - buffIndex++; - } -} - -void Bot::SavePetItems(uint32* petItems, uint32 botPetSaveId) { - if(!petItems || botPetSaveId == 0) - return; - - for (int itemIndex = 0; itemIndex < EmuConstants::EQUIPMENT_SIZE; itemIndex++) { - if(petItems[itemIndex] == 0) - continue; - - std::string query = StringFormat("INSERT INTO `bot_pet_inventories` (`pets_index`, `item_id`) VALUES (%u, %u)", botPetSaveId, petItems[itemIndex]); - auto results = database.QueryDatabase(query); - if(!results.Success()) - break; - } -} - -void Bot::DeletePetBuffs(uint32 botPetSaveId) { - if(botPetSaveId == 0) - return; - - std::string query = StringFormat("DELETE FROM `bot_pet_buffs` WHERE `pets_index` = %u", botPetSaveId); - auto results = database.QueryDatabase(query); -} - -void Bot::DeletePetItems(uint32 botPetSaveId) { - if(botPetSaveId == 0) - return; - - std::string query = StringFormat("DELETE FROM `bot_pet_inventories` WHERE `pets_index` = %u", botPetSaveId); - auto results = database.QueryDatabase(query); -} - -void Bot::DeletePetStats(uint32 botPetSaveId) { - if(botPetSaveId == 0) - return; - - std::string query = StringFormat("DELETE FROM `bot_pets` WHERE `pets_index` = %u", botPetSaveId); - auto results = database.QueryDatabase(query); -} - -void Bot::LoadStance() -{ - std::string query = StringFormat("SELECT `stance_id` FROM `bot_stances` WHERE `bot_id` = %u", GetBotID()); - auto results = database.QueryDatabase(query); - if(!results.Success() || results.RowCount() == 0) { - Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadStance()"); - SetDefaultBotStance(); - return; - } - auto row = results.begin(); - SetBotStance((BotStanceType)atoi(row[0])); -} - -void Bot::SaveStance() { - if(_baseBotStance == _botStance) - return; - - std::string query = StringFormat("REPLACE INTO `bot_stances` (`bot_id`, `stance_id`) VALUES (%u, %u)", GetBotID(), GetBotStance()); - auto results = database.QueryDatabase(query); - if(!results.Success()) - Log.Out(Logs::General, Logs::Error, "Error in Bot::SaveStance()"); -} - -void Bot::LoadTimers() -{ - std::string query = StringFormat( - "SELECT" - " IfNull(bt.`timer_id`, 0) As timer_id," - " IfNull(bt.`timer_value`, 0) As timer_value," - " IfNull(MAX(sn.`recast_time`), 0) AS MaxTimer" - " FROM `bot_timers` bt, `spells_new` sn" - " WHERE bt.`bot_id` = %u AND sn.`EndurTimerIndex` = (" - "SELECT case" - " WHEN timer_id > %i THEN timer_id - %i" - " ELSE timer_id END AS timer_id" - " FROM `bot_timers` WHERE `timer_id` = bt.`timer_id` AND `bot_id` = bt.`bot_id`" // double-check validity - ")" - " AND sn.`classes%i` <= %i", - GetBotID(), - (DisciplineReuseStart - 1), - (DisciplineReuseStart - 1), - GetClass(), - GetLevel() - ); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadTimers()"); - return; - } + pet_inst->GetPetState(pet_buffs, pet_items, pet_name); - int timerID = 0; - uint32 value = 0; - uint32 maxValue = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - timerID = atoi(row[0]) - 1; - value = atoi(row[1]); - maxValue = atoi(row[2]); - if(timerID >= 0 && timerID < MaxTimer && value < (Timer::GetCurrentTime() + maxValue)) - timers[timerID] = value; + std::string error_message; + + if (!botdb.SavePetStats(GetBotID(), pet_name, pet_inst->GetMana(), pet_inst->GetHP(), pet_inst->GetPetSpellID())) { + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::SavePetStats(), GetCleanName()); + safe_delete_array(pet_name); + return false; } + safe_delete_array(pet_name); + + if (!botdb.SavePetBuffs(GetBotID(), pet_buffs)) + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::SavePetBuffs(), GetCleanName()); + if (!botdb.SavePetItems(GetBotID(), pet_items)) + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::SavePetItems(), GetCleanName()); + + return true; } -void Bot::SaveTimers() { - bool hadError = false; - std::string query = StringFormat("DELETE FROM `bot_timers` WHERE `bot_id` = %u", GetBotID()); - auto results = database.QueryDatabase(query); - if(!results.Success()) - hadError = true; +bool Bot::DeletePet() +{ + auto bot_owner = GetBotOwner(); + if (!bot_owner) + return false; + + std::string error_message; - for(int timerIndex = 0; timerIndex < MaxTimer; timerIndex++) { - if(timers[timerIndex] <= Timer::GetCurrentTime()) - continue; - - query = StringFormat("REPLACE INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) VALUES (%u, %u, %u)", GetBotID(), timerIndex + 1, timers[timerIndex]); - results = database.QueryDatabase(query); - if(!results.Success()) - hadError = true; + if (!botdb.DeletePetItems(GetBotID())) { + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::DeletePetItems(), GetCleanName()); + return false; + } + if (!botdb.DeletePetBuffs(GetBotID())) { + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::DeletePetBuffs(), GetCleanName()); + return false; + } + if (!botdb.DeletePetStats(GetBotID())) { + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::DeletePetStats(), GetCleanName()); + return false; } - if(hadError) - Log.Out(Logs::General, Logs::Error, "Error in Bot::SaveTimers()"); + if (!GetPet() || !GetPet()->IsNPC()) + return true; + NPC* pet_inst = GetPet()->CastToNPC(); + pet_inst->SetOwnerID(0); + + return true; } bool Bot::Process() { @@ -3299,44 +2818,7 @@ void Bot::Depop() { NPC::Depop(false); } -bool Bot::DeleteBot(std::string* errorMessage) { - bool hadError = false; - if(this->GetBotID() == 0) - return false; - - // TODO: These queries need to be ran together as a transaction.. ie, if one or more fail then they all will fail to commit to the database. - std::string query = StringFormat("DELETE FROM `bot_inventories` WHERE `bot_id` = '%u'", this->GetBotID()); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - hadError = true; - } - - query = StringFormat("DELETE FROM `bot_buffs` WHERE `bot_id` = '%u'", this->GetBotID()); - results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - hadError = true; - } - - query = StringFormat("DELETE FROM `bot_stances` WHERE `bot_id` = '%u'", this->GetBotID()); - results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - hadError = true; - } - - query = StringFormat("DELETE FROM `bot_data` WHERE `bot_id` = '%u'", this->GetBotID()); - results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - hadError = true; - } - - return !hadError; -} - -void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) { +void Bot::Spawn(Client* botCharacterOwner) { if(GetBotID() > 0 && _botOwnerCharacterID > 0 && botCharacterOwner && botCharacterOwner->CharacterID() == _botOwnerCharacterID) { // Rename the bot name to make sure that Mob::GetName() matches Mob::GetCleanName() so we dont have a bot named "Jesuschrist001" strcpy(name, GetCleanName()); @@ -3381,236 +2863,46 @@ void Bot::Spawn(Client* botCharacterOwner, std::string* errorMessage) { } } -// Saves the specified item as an inventory record in the database for this bot. -void Bot::SetBotItemInSlot(uint32 slotID, uint32 itemID, const ItemInst* inst, std::string *errorMessage) -{ - uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; - if (this->GetBotID() == 0 || slotID < EmuConstants::EQUIPMENT_BEGIN || itemID <= NO_ITEM) - return; - - if (inst && inst->IsType(ItemClassCommon)) { - for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { - ItemInst* auginst = inst->GetItem(i); - augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; - } - } - - std::string query = StringFormat( - "REPLACE INTO `bot_inventories` (" - "`bot_id`," - " `slot_id`," - " `item_id`," - " `inst_charges`," - " `inst_color`," - " `inst_no_drop`," - " `inst_custom_data`," - " `ornament_icon`," - " `ornament_id_file`," - " `ornament_hero_model`," - " `augment_1`," - " `augment_2`," - " `augment_3`," - " `augment_4`," - " `augment_5`," - " `augment_6`" - ")" - " VALUES (" - "%lu," /*bot_id*/ - " %lu," /*slot_id*/ - " %lu," /*item_id*/ - " %lu," /*inst_charges*/ - " %lu," /*inst_color*/ - " %lu," /*inst_no_drop*/ - " '%s'," /*inst_custom_data*/ - " %lu," /*ornament_icon*/ - " %lu," /*ornament_id_file*/ - " %lu," /*ornament_hero_model*/ - " %lu," /*augment_1*/ - " %lu," /*augment_2*/ - " %lu," /*augment_3*/ - " %lu," /*augment_4*/ - " %lu," /*augment_5*/ - " %lu" /*augment_6*/ - ")", - (unsigned long)this->GetBotID(), - (unsigned long)slotID, - (unsigned long)itemID, - (unsigned long)inst->GetCharges(), - (unsigned long)inst->GetColor(), - (unsigned long)(inst->IsAttuned()? 1: 0), - inst->GetCustomDataString().c_str(), - (unsigned long)inst->GetOrnamentationIcon(), - (unsigned long)inst->GetOrnamentationIDFile(), - (unsigned long)inst->GetOrnamentHeroModel(), - (unsigned long)augslot[0], - (unsigned long)augslot[1], - (unsigned long)augslot[2], - (unsigned long)augslot[3], - (unsigned long)augslot[4], - (unsigned long)augslot[5] - ); - auto results = database.QueryDatabase(query); - if(!results.Success()) - *errorMessage = std::string(results.ErrorMessage()); -} - // Deletes the inventory record for the specified item from the database for this bot. -void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage) { - if(this->GetBotID() == 0) +void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage) +{ + if(!GetBotID()) return; - std::string query = StringFormat("DELETE FROM `bot_inventories` WHERE `bot_id` = %i AND `slot_id` = %i", this->GetBotID(), slotID); - auto results = database.QueryDatabase(query); - if(!results.Success()) - *errorMessage = std::string(results.ErrorMessage()); + if(!botdb.DeleteItemBySlot(GetBotID(), slotID)) + *errorMessage = BotDatabase::fail::DeleteItemBySlot(); m_inv.DeleteItem(slotID); UpdateEquipmentLight(); } // Retrieves all the inventory records from the database for this bot. -void Bot::GetBotItems(std::string* errorMessage, Inventory &inv) +void Bot::GetBotItems(Inventory &inv, std::string* errorMessage) { - if(this->GetBotID() == 0) - return; + if(!GetBotID()) + return; - std::string query = StringFormat( - "SELECT" - " `slot_id`," - " `item_id`," - " `inst_charges`," - " `inst_color`," - " `inst_no_drop`," - " `inst_custom_data`," - " `ornament_icon`," - " `ornament_id_file`," - " `ornament_hero_model`," - " `augment_1`," - " `augment_2`," - " `augment_3`," - " `augment_4`, " - " `augment_5`," - " `augment_6`" - " FROM `bot_inventories`" - " WHERE `bot_id` = %i" - " ORDER BY `slot_id`", - this->GetBotID() - ); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); + if (!botdb.LoadItems(GetBotID(), inv)) { + *errorMessage = BotDatabase::fail::LoadItems(); return; } - for (auto row = results.begin(); row != results.end(); ++row) { - int16 slot_id = atoi(row[0]); - uint32 item_id = atoi(row[1]); - uint16 charges = atoi(row[2]); - uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; - aug[0] = (uint32)atoul(row[9]); - aug[1] = (uint32)atoul(row[10]); - aug[2] = (uint32)atoul(row[11]); - aug[3] = (uint32)atoul(row[12]); - aug[4] = (uint32)atoul(row[13]); - aug[5] = (uint32)atoul(row[14]); - ItemInst* inst = database.CreateItem(item_id, charges, aug[0], aug[1], aug[2], aug[3], aug[4], aug[5]); - if (!inst) { - Log.Out(Logs::General, Logs::Error, "Warning: bot_id %i has an invalid item_id %i in inventory slot %i", this->GetBotID(), item_id, slot_id); - continue; - } - - if (charges == 255) - inst->SetCharges(-1); - else - inst->SetCharges(charges); - - uint32 color = atoul(row[3]); - if (color > 0) - inst->SetColor(color); - - bool instnodrop = (row[4] && (uint16)atoi(row[4])) ? true : false; - if (instnodrop || (((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || slot_id == 9999) && inst->GetItem()->Attuneable)) - inst->SetAttuned(true); - - if (row[5]) { - std::string data_str(row[5]); - std::string idAsString; - std::string value; - bool use_id = true; - - for (int i = 0; i < data_str.length(); ++i) { - if (data_str[i] == '^') { - if (!use_id) { - inst->SetCustomData(idAsString, value); - idAsString.clear(); - value.clear(); - } - - use_id = !use_id; - continue; - } - - char v = data_str[i]; - if (use_id) - idAsString.push_back(v); - else - value.push_back(v); - } - } - - uint32 ornament_icon = (uint32)atoul(row[6]); - inst->SetOrnamentIcon(ornament_icon); - - uint32 ornament_idfile = (uint32)atoul(row[7]); - inst->SetOrnamentationIDFile(ornament_idfile); - - uint32 ornament_hero_model = (uint32)atoul(row[8]); - inst->SetOrnamentHeroModel(ornament_hero_model); - - int16 put_slot_id = INVALID_INDEX; - if (slot_id < 8000 || slot_id > 8999) - put_slot_id = inv.PutItem(slot_id, *inst); - - safe_delete(inst); - - if (put_slot_id == INVALID_INDEX) - Log.Out(Logs::General, Logs::Error, "Warning: Invalid slot_id for item in inventory: bot_id=%i, item_id=%i, slot_id=%i",this->GetBotID(), item_id, slot_id); - } - UpdateEquipmentLight(); } // Returns the inventory record for this bot from the database for the specified equipment slot. -uint32 Bot::GetBotItemBySlot(uint32 slotID) { - if(this->GetBotID() == 0 || slotID < EmuConstants::EQUIPMENT_BEGIN) - return 0; +uint32 Bot::GetBotItemBySlot(uint32 slotID) +{ + uint32 item_id = 0; + if(!GetBotID()) + return item_id; - std::string query = StringFormat("SELECT `item_id` FROM `bot_inventories` WHERE `bot_id` = %i AND `slot_id` = %i", GetBotID(), slotID); - auto results = database.QueryDatabase(query); - if(!results.Success() || results.RowCount() != 1) - return 0; + if (!botdb.LoadItemBySlot(GetBotID(), slotID, item_id)) { + if (GetBotOwner() && GetBotOwner()->IsClient()) + GetBotOwner()->CastToClient()->Message(13, "%s", BotDatabase::fail::LoadItemBySlot()); + } - auto row = results.begin(); - return atoi(row[0]); -} - -// Returns the number of inventory records the bot has in the database. -uint32 Bot::GetBotItemsCount(std::string *errorMessage) { - if(this->GetBotID() == 0) - return 0; - - std::string query = StringFormat("SELECT COUNT(*) FROM `bot_inventories` WHERE `bot_id` = %i", this->GetBotID()); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return 0; - } - - if(results.RowCount() != 1) - return 0; - - auto row = results.begin(); - return atoi(row[0]); + return item_id; } void Bot::SetLevel(uint8 in_level, bool command) { @@ -3687,160 +2979,16 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { } } -uint32 Bot::GetBotIDByBotName(std::string botName) { - if(botName.empty()) - return 0; - - std::string query = StringFormat("SELECT `bot_id` FROM `bot_data` WHERE `name` = '%s'", botName.c_str()); - auto results = database.QueryDatabase(query); - if(!results.Success() || results.RowCount() == 0) - return 0; - - auto row = results.begin(); - return atoi(row[0]); -} - -Bot* Bot::LoadBot(uint32 botID, std::string* errorMessage) +Bot* Bot::LoadBot(uint32 botID) { - if(botID == 0) - return nullptr; + Bot* loaded_bot = nullptr; + if (!botID) + return loaded_bot; - std::string query = StringFormat( - "SELECT" - " `owner_id`," - " `spells_id`," - " `name`," - " `last_name`," - " `title`," /*planned use[4]*/ - " `suffix`," /*planned use[5]*/ - " `zone_id`," - " `gender`," - " `race`," - " `class`," - " `level`," - " `deity`," /*planned use[11]*/ - " `creation_day`," /*not in-use[12]*/ - " `last_spawn`," /*not in-use[13]*/ - " `time_spawned`," - " `size`," - " `face`," - " `hair_color`," - " `hair_style`," - " `beard`," - " `beard_color`," - " `eye_color_1`," - " `eye_color_2`," - " `drakkin_heritage`," - " `drakkin_tattoo`," - " `drakkin_details`," - " `ac`," /*not in-use[26]*/ - " `atk`," /*not in-use[27]*/ - " `hp`," - " `mana`," - " `str`," /*not in-use[30]*/ - " `sta`," /*not in-use[31]*/ - " `cha`," /*not in-use[32]*/ - " `dex`," /*not in-use[33]*/ - " `int`," /*not in-use[34]*/ - " `agi`," /*not in-use[35]*/ - " `wis`," /*not in-use[36]*/ - " `fire`," /*not in-use[37]*/ - " `cold`," /*not in-use[38]*/ - " `magic`," /*not in-use[39]*/ - " `poison`," /*not in-use[40]*/ - " `disease`," /*not in-use[41]*/ - " `corruption`," /*not in-use[42]*/ - " `show_helm`,"//43 - " `follow_distance`"//44 - " FROM `bot_data`" - " WHERE `bot_id` = '%u'", - botID - ); - - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return nullptr; - } - - if (results.RowCount() == 0) - return nullptr; + if (!botdb.LoadBot(botID, loaded_bot)) // TODO: Consider update to message handler + return loaded_bot; - // TODO: Consider removing resists and basic attributes from the load query above since we're using defaultNPCType values instead - auto row = results.begin(); - NPCType defaultNPCTypeStruct = CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[10]), atoi(row[8]), atoi(row[9]), atoi(row[7])); - NPCType tempNPCStruct = FillNPCTypeStruct( - atoi(row[1]), - std::string(row[2]), - std::string(row[3]), - atoi(row[10]), - atoi(row[8]), - atoi(row[9]), - atoi(row[7]), - atof(row[15]), - atoi(row[16]), - atoi(row[18]), - atoi(row[17]), - atoi(row[21]), - atoi(row[22]), - atoi(row[20]), - atoi(row[19]), - atoi(row[23]), - atoi(row[24]), - atoi(row[25]), - atoi(row[28]), - atoi(row[29]), - defaultNPCTypeStruct.MR, - defaultNPCTypeStruct.CR, - defaultNPCTypeStruct.DR, - defaultNPCTypeStruct.FR, - defaultNPCTypeStruct.PR, - defaultNPCTypeStruct.Corrup, - defaultNPCTypeStruct.AC, - defaultNPCTypeStruct.STR, - defaultNPCTypeStruct.STA, - defaultNPCTypeStruct.DEX, - defaultNPCTypeStruct.AGI, - defaultNPCTypeStruct.INT, - defaultNPCTypeStruct.WIS, - defaultNPCTypeStruct.CHA, - defaultNPCTypeStruct.ATK - ); - - Bot* loadedBot = new Bot(botID, atoi(row[0]), atoi(row[1]), atof(row[14]), atoi(row[6]), tempNPCStruct); - if (loadedBot) { - loadedBot->SetShowHelm((atoi(row[43]) > 0 ? true : false)); - loadedBot->SetFollowDistance(atoi(row[44])); - } - - return loadedBot; -} - -std::list Bot::GetGroupedBotsByGroupId(uint32 groupId, std::string* errorMessage) -{ - std::list groupedBots; - if(groupId == 0) - return groupedBots; - - std::string query = StringFormat( - "SELECT g.`mob_id` AS bot_id" - " FROM `vw_groups` AS g" - " JOIN `bot_data` AS b" - " ON g.`mob_id` = b.`bot_id`" - " AND g.`mob_type` = 'B'" - " WHERE g.`group_id` = %u", - groupId - ); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return groupedBots; - } - - for (auto row = results.begin(); row != results.end(); ++row) - groupedBots.push_back(atoi(row[0])); - - return groupedBots; + return loaded_bot; } // Load and spawn all zoned bots by bot owner character @@ -3850,18 +2998,18 @@ void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) { Group* g = botOwner->GetGroup(); if(g) { uint32 TempGroupId = g->GetID(); - std::string errorMessage; - std::list ActiveBots = Bot::GetGroupedBotsByGroupId(botOwner->GetGroup()->GetID(), &errorMessage); - if(errorMessage.empty() && !ActiveBots.empty()) { + std::list ActiveBots; + if (!botdb.LoadGroupedBotsByGroupID(TempGroupId, ActiveBots)) { + botOwner->Message(13, "%s", BotDatabase::fail::LoadGroupedBotsByGroupID()); + return; + } + + if(!ActiveBots.empty()) { for(std::list::iterator itr = ActiveBots.begin(); itr != ActiveBots.end(); ++itr) { - Bot* activeBot = Bot::LoadBot(*itr, &errorMessage); - if(!errorMessage.empty()) { - safe_delete(activeBot); - break; - } + Bot* activeBot = Bot::LoadBot(*itr); if(activeBot) { - activeBot->Spawn(botOwner, &errorMessage); + activeBot->Spawn(botOwner); g->UpdatePlayer(activeBot); if(g->GetLeader()) activeBot->SetFollowID(g->GetLeader()->GetID()); @@ -3893,74 +3041,7 @@ bool Bot::GroupHasBot(Group* group) { return Result; } -std::list Bot::GetBotList(uint32 botOwnerCharacterID, std::string* errorMessage) { - std::list ownersBots; - if(botOwnerCharacterID == 0) - return ownersBots; - - std::string query = StringFormat("SELECT `bot_id`, `name`, `class`, `level`, `race`, `gender` FROM `bot_data` WHERE `owner_id` = '%u'", botOwnerCharacterID); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return ownersBots; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - BotsAvailableList availableBot; - availableBot.BotID = atoi(row[0]); - strcpy(availableBot.BotName, row[1]); - availableBot.BotClass = atoi(row[2]); - availableBot.BotLevel = atoi(row[3]); - availableBot.BotRace = atoi(row[4]); - availableBot.BotGender = atoi(row[5]); - ownersBots.push_back(availableBot); - } - return ownersBots; -} - -std::list Bot::ListSpawnedBots(uint32 characterID, std::string* errorMessage) { - std::list spawnedBots; - //if(characterID == 0) - return spawnedBots; - - // Dead table..function needs to be updated or removed (no calls listed to Bot::ListSpawnedBots()) - std::string query = StringFormat("SELECT bot_name, zone_name FROM botleader WHERE leaderid = %i", characterID); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return spawnedBots; - } - - for(auto row = results.begin(); row != results.end(); ++row) { - SpawnedBotsList spawnedBotsList; - spawnedBotsList.BotLeaderCharID = characterID; - strcpy(spawnedBotsList.BotName, row[0]); - strcpy(spawnedBotsList.ZoneName, row[1]); - spawnedBots.push_back(spawnedBotsList); - } - - return spawnedBots; -} - -uint32 Bot::AllowedBotSpawns(uint32 botOwnerCharacterID, std::string* errorMessage) { - if(botOwnerCharacterID == 0) - return 0; - - std::string query = StringFormat("SELECT value FROM quest_globals WHERE name = 'bot_spawn_limit' AND charid = %i", botOwnerCharacterID); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - return atoi(row[0]); -} - -uint32 Bot::SpawnedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage) { +uint32 Bot::SpawnedBotCount(uint32 botOwnerCharacterID) { uint32 Result = 0; if(botOwnerCharacterID > 0) { std::list SpawnedBots = entity_list.GetBotsByBotOwnerCharacterID(botOwnerCharacterID); @@ -3969,43 +3050,6 @@ uint32 Bot::SpawnedBotCount(uint32 botOwnerCharacterID, std::string* errorMessag return Result; } -uint32 Bot::CreatedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage) { - if(botOwnerCharacterID == 0) - return 0; - - std::string query = StringFormat("SELECT COUNT(`bot_id`) FROM `bot_data` WHERE `owner_id` = %i", botOwnerCharacterID); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - return atoi(row[0]); -} - -uint32 Bot::GetBotOwnerCharacterID(uint32 botID, std::string* errorMessage) { - - if(botID == 0) - return 0; - - std::string query = StringFormat("SELECT `owner_id` FROM `bot_data` WHERE `bot_id` = %u", botID); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - *errorMessage = std::string(results.ErrorMessage()); - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - return atoi(row[0]); -} - void Bot::LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp) { // This essentially performs a '#bot update,' with appearance packets, based on the current methods. // This should not be called outside of Client::SetEXP() due to it's lack of rule checks. @@ -4225,11 +3269,14 @@ void Bot::BotTradeSwapItem(Client* client, int16 lootSlot, const ItemInst* inst, } } -void Bot::BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb) { +void Bot::BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb) +{ if(addToDb) { - this->SetBotItemInSlot(lootSlot, id, inst, errorMessage); - if(!errorMessage->empty()) + if (!botdb.SaveItemBySlot(this, lootSlot, inst)) { + *errorMessage = BotDatabase::fail::SaveItemBySlot(); return; + } + m_inv.PutItem(lootSlot, *inst); } @@ -6298,7 +5345,7 @@ bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) { } void Bot::EquipBot(std::string* errorMessage) { - GetBotItems(errorMessage, m_inv); + GetBotItems(m_inv, errorMessage); const ItemInst* inst = 0; const Item_Struct* item = 0; for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { @@ -6345,16 +5392,22 @@ void Bot::ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild) { guildOfficer->Message(13, "You dont have permission to invite."); return; } - SetBotGuildMembership(botToGuild->GetBotID(), guildOfficer->GuildID(), GUILD_MEMBER); + + if (!botdb.SaveGuildMembership(botToGuild->GetBotID(), guildOfficer->GuildID(), GUILD_MEMBER)) { + guildOfficer->Message(13, "%s for '%s'", BotDatabase::fail::SaveGuildMembership(), botToGuild->GetCleanName()); + return; + } + ServerPacket* pack = new ServerPacket(ServerOP_GuildCharRefresh, sizeof(ServerGuildCharRefresh_Struct)); ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer; s->guild_id = guildOfficer->GuildID(); s->old_guild_id = GUILD_NONE; s->char_id = botToGuild->GetBotID(); worldserver.SendPacket(pack); + safe_delete(pack); } else { - guildOfficer->Message(13, "Player is in a guild."); + guildOfficer->Message(13, "Bot is in a guild."); return; } } @@ -6365,14 +5418,17 @@ bool Bot::ProcessGuildRemoval(Client* guildOfficer, std::string botName) { if(guildOfficer && !botName.empty()) { Bot* botToUnGuild = entity_list.GetBotByBotName(botName); if(botToUnGuild) { - SetBotGuildMembership(botToUnGuild->GetBotID(), 0, 0); - Result = true; - } else { - uint32 botId = GetBotIDByBotName(botName); - if(botId > 0) { - SetBotGuildMembership(botId, 0, 0); + if (botdb.SaveGuildMembership(botToUnGuild->GetBotID(), 0, 0)) + Result = true; + } else { + uint32 ownerId = 0; + if (!botdb.LoadOwnerID(botName, ownerId)) + guildOfficer->Message(13, "%s for '%s'", BotDatabase::fail::LoadOwnerID(), botName.c_str()); + uint32 botId = 0; + if (!botdb.LoadBotID(ownerId, botName, botId)) + guildOfficer->Message(13, "%s for '%s'", BotDatabase::fail::LoadBotID(), botName.c_str()); + if (botId && botdb.SaveGuildMembership(botId, 0, 0)) Result = true; - } } if(Result) { @@ -6388,47 +5444,6 @@ bool Bot::ProcessGuildRemoval(Client* guildOfficer, std::string botName) { return Result; } -void Bot::SetBotGuildMembership(uint32 botId, uint32 guildid, uint8 rank) { - if(botId == 0) - return; - - if(guildid > 0) { - std::string query = StringFormat("REPLACE INTO `bot_guild_members` SET `bot_id` = %u, `guild_id` = %u, `rank` = %u", botId, guildid, rank); - auto results = database.QueryDatabase(query); - return; - } - - std::string query = StringFormat("DELETE FROM `bot_guild_members` WHERE `bot_id` = %u", botId); - auto results = database.QueryDatabase(query); -} - -void Bot::LoadGuildMembership(uint32* guildId, uint8* guildRank, std::string* guildName) -{ - if(guildId == nullptr || guildRank == nullptr || guildName == nullptr) - return; - - std::string query = StringFormat( - "SELECT" - " gm.`guild_id`," - " gm.`rank`," - " g.`name`" - " FROM `vw_guild_members` AS gm" - " JOIN `guilds` AS g" - " ON gm.`guild_id` = g.`id`" - " WHERE gm.`char_id` = %u" - " AND gm.`mob_type` = 'B'", - GetBotID() - ); - auto results = database.QueryDatabase(query); - if(!results.Success() || results.RowCount() == 0) - return; - - auto row = results.begin(); - *guildId = atoi(row[0]); - *guildRank = atoi(row[1]); - *guildName = std::string(row[2]); -} - int32 Bot::CalcMaxMana() { switch(GetCasterClass()) { case 'I': @@ -8996,23 +8011,6 @@ uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { return needHealed; } -uint32 Bot::GetEquipmentColor(uint8 material_slot) const -{ - int16 slotid = 0; - uint32 botid = this->GetBotID(); - slotid = Inventory::CalcSlotFromMaterial(material_slot); - if (slotid == INVALID_INDEX) - return 0; - - std::string query = StringFormat("SELECT `inst_color` FROM `bot_inventories` WHERE `bot_id` = %u AND `slot_id` = %u", botid, slotid); - auto results = database.QueryDatabase(query); - if (!results.Success() || results.RowCount() != 1) - return 0; - - auto row = results.begin(); - return atoul(row[0]); -} - int Bot::GetRawACNoShield(int &shield_ac) { int ac = itembonuses.AC + spellbonuses.AC; shield_ac = 0; @@ -9417,26 +8415,13 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) } if (save_flag) { - std::string where_clause; + int16 save_slot = slot_id; if (all_flag) - where_clause = StringFormat(" WHERE `slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u')", - MainHead, MainArms, MainWrist1, MainHands, MainChest, MainLegs, MainFeet); - else - where_clause = StringFormat(" WHERE `slot_id` = '%u'", slot_id); + save_slot = -2; - std::string query = StringFormat( - "UPDATE `bot_inventories`" - " SET `inst_color` = '%u'" - " %s" - " AND `bot_id` = '%u'", - rgb, - where_clause.c_str(), - GetBotID() - ); - - auto results = database.QueryDatabase(query); - if (!results.Success() && GetOwner() && GetOwner()->IsClient()) { - GetOwner()->CastToClient()->Message(15, "Failed to save dye armor changes for %s due to unknown cause", GetCleanName()); + if (!botdb.SaveEquipmentColor(GetBotID(), save_slot, rgb)) { + if (GetBotOwner() && GetBotOwner()->IsClient()) + GetBotOwner()->CastToClient()->Message(13, "%s", BotDatabase::fail::SaveEquipmentColor()); return false; } } @@ -9444,44 +8429,24 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) return true; } -std::string Bot::CreateSayLink(Client* c, const char* message, const char* name) { - int sayid = 0; - int sz = strlen(message); - char *escaped_string = new char[sz * 2]; - database.DoEscapeString(escaped_string, message, sz); - std::string query = StringFormat("SELECT `id` FROM `saylink` WHERE `phrase` = '%s'", escaped_string); - auto results = database.QueryDatabase(query); - if (results.Success()) { - if (results.RowCount() >= 1) { - for (auto row = results.begin();row != results.end(); ++row) - sayid = atoi(row[0]); - } else { - std::string insert_query = StringFormat("INSERT INTO `saylink` (`phrase`) VALUES ('%s')", escaped_string); - results = database.QueryDatabase(insert_query); - if (!results.Success()) { - Log.Out(Logs::General, Logs::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str()); - } else { - results = database.QueryDatabase(query); - if (results.Success()) { - if (results.RowCount() >= 1) - for(auto row = results.begin(); row != results.end(); ++row) - sayid = atoi(row[0]); - } - else - Log.Out(Logs::General, Logs::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str()); - } - } - } +std::string Bot::CreateSayLink(Client* c, const char* message, const char* name) +{ + int saylink_size = strlen(message); + char* escaped_string = new char[saylink_size * 2]; + + database.DoEscapeString(escaped_string, message, saylink_size); + + uint32 saylink_id = database.LoadSaylinkID(escaped_string); safe_delete_array(escaped_string); Client::TextLink linker; linker.SetLinkType(linker.linkItemData); linker.SetProxyItemID(SAYLINK_ITEM_ID); - linker.SetProxyAugment1ID(sayid); + linker.SetProxyAugment1ID(saylink_id); linker.SetProxyText(name); - auto say_link = linker.GenerateLink(); - return say_link; + auto saylink = linker.GenerateLink(); + return saylink; } #endif diff --git a/zone/bot.h b/zone/bot.h index 89759cd91..49d82f72a 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -226,9 +226,7 @@ public: static bool IsValidRaceClassCombo(uint16 r, uint8 c); bool IsValidName(); static bool IsValidName(std::string& name); - static bool IsBotNameAvailable(const char *botName, std::string* errorMessage); - bool DeleteBot(std::string* errorMessage); - void Spawn(Client* botCharacterOwner, std::string* errorMessage); + void Spawn(Client* botCharacterOwner); virtual void SetLevel(uint8 in_level, bool command = false); virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); virtual bool Process(); @@ -388,19 +386,12 @@ public: void BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true); void EquipBot(std::string* errorMessage); bool CheckLoreConflict(const Item_Struct* item); - uint32 GetEquipmentColor(uint8 material_slot) const; virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); } // Static Class Methods //static void DestroyBotRaidObjects(Client* client); // Can be removed after bot raids are dumped - static uint32 GetBotIDByBotName(std::string botName); - static Bot* LoadBot(uint32 botID, std::string* errorMessage); - static std::list GetBotList(uint32 botOwnerCharacterID, std::string* errorMessage); - static std::list ListSpawnedBots(uint32 characterID, std::string* errorMessage); - static uint32 SpawnedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage); - static uint32 CreatedBotCount(uint32 botOwnerCharacterID, std::string* errorMessage); - static uint32 AllowedBotSpawns(uint32 botOwnerCharacterID, std::string* errorMessage); - static uint32 GetBotOwnerCharacterID(uint32 botID, std::string* errorMessage); + static Bot* LoadBot(uint32 botID); + static uint32 SpawnedBotCount(uint32 botOwnerCharacterID); static void LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp); //static bool SetBotOwnerCharacterID(uint32 botID, uint32 botOwnerCharacterID, std::string* errorMessage); static std::string ClassIdToString(uint16 classId); @@ -411,7 +402,6 @@ public: static void ProcessBotGroupDisband(Client* c, std::string botName); static void BotOrderCampAll(Client* c); static void ProcessBotInspectionRequest(Bot* inspectedBot, Client* client); - static std::list GetGroupedBotsByGroupId(uint32 groupId, std::string* errorMessage); static void LoadAndSpawnAllZonedBots(Client* botOwner); static bool GroupHasBot(Group* group); static Bot* GetFirstBotInGroup(Group* group); @@ -604,15 +594,37 @@ public: // Class Destructors virtual ~Bot(); - // Publicized protected/private functions - virtual void BotRangedAttack(Mob* other); // protected - uint32 GetBotItemsCount(std::string* errorMessage); // private - void BotRemoveEquipItem(int slot); // private - void RemoveBotItemBySlot(uint32 slotID, std::string* errorMessage); // private + // Publicized protected functions + virtual void BotRangedAttack(Mob* other); + // Publicized private functions + static NPCType FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack); + void BotRemoveEquipItem(int slot); + void RemoveBotItemBySlot(uint32 slotID, std::string* errorMessage); + uint32 GetTotalPlayTime(); + + // New accessors for BotDatabase access + bool DeleteBot(); + uint32* GetTimers() { return timers; } + uint32 GetLastZoneID() { return _lastZoneId; } + int32 GetBaseAC() { return _baseAC; } + int32 GetBaseATK() { return _baseATK; } + int32 GetBaseSTR() { return _baseSTR; } + int32 GetBaseSTA() { return _baseSTA; } + int32 GetBaseCHA() { return _baseCHA; } + int32 GetBaseDEX() { return _baseDEX; } + int32 GetBaseINT() { return _baseINT; } + int32 GetBaseAGI() { return _baseAGI; } + int32 GetBaseWIS() { return _baseWIS; } + int32 GetBaseFR() { return _baseFR; } + int32 GetBaseCR() { return _baseCR; } + int32 GetBaseMR() { return _baseMR; } + int32 GetBasePR() { return _basePR; } + int32 GetBaseDR() { return _baseDR; } + int32 GetBaseCorrup() { return _baseCorrup; } + protected: virtual void PetAIProcess(); - static NPCType FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack); virtual void BotMeditate(bool isSitting); virtual bool CheckBotDoubleAttack(bool Triple = false); virtual int32 GetBotFocusEffect(BotfocusType bottype, uint16 spell_id); @@ -622,8 +634,6 @@ protected: virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); virtual float GetMaxMeleeRangeToTarget(Mob* target); - static void SetBotGuildMembership(uint32 botId, uint32 guildid, uint8 rank); - private: // Class Members uint32 _botID; @@ -701,30 +711,14 @@ private: void SetBotID(uint32 botID); // Private "Inventory" Methods - void GetBotItems(std::string* errorMessage, Inventory &inv); + void GetBotItems(Inventory &inv, std::string* errorMessage); void BotAddEquipItem(int slot, uint32 id); uint32 GetBotItemBySlot(uint32 slotID); - void SetBotItemInSlot(uint32 slotID, uint32 itemID, const ItemInst* inst, std::string* errorMessage); - uint32 GetTotalPlayTime(); - void SaveBuffs(); // Saves existing buffs to the database to persist zoning and camping - void LoadBuffs(); // Retrieves saved buffs from the database on spawning - void LoadPetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId); - void SavePetBuffs(SpellBuff_Struct* petBuffs, uint32 botPetSaveId); - void LoadPetItems(uint32* petItems, uint32 botPetSaveId); - void SavePetItems(uint32* petItems, uint32 botPetSaveId); - void LoadPetStats(std::string* petName, uint32* petMana, uint32* petHitPoints, uint32* botPetId, uint32 botPetSaveId); - uint32 SavePetStats(std::string petName, uint32 petMana, uint32 petHitPoints, uint32 botPetId); - void LoadPet(); // Load and spawn bot pet if there is one - void SavePet(); // Save and depop bot pet if there is one - uint32 GetPetSaveId(); - void DeletePetBuffs(uint32 botPetSaveId); - void DeletePetItems(uint32 botPetSaveId); - void DeletePetStats(uint32 botPetSaveId); - void LoadGuildMembership(uint32* guildId, uint8* guildRank, std::string* guildName); - void LoadStance(); - void SaveStance(); - void LoadTimers(); - void SaveTimers(); + + // Private "Pet" Methods + bool LoadPet(); // Load and spawn bot pet if there is one + bool SavePet(); // Save and depop bot pet if there is one + bool DeletePet(); }; #endif // BOTS diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index c9d7d31bb..0cd0b8072 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -1413,7 +1413,7 @@ int bot_command_init(void) } std::map>> bot_command_settings; - botdb.GetCommandSettings(bot_command_settings); + botdb.LoadBotCommandSettings(bot_command_settings); auto working_bcl = bot_command_list; for (auto working_bcl_iter : working_bcl) { @@ -1857,13 +1857,13 @@ namespace MyBots return; std::string group_name = name; - std::string error_message; - uint32 group_id = botdb.GetGroupIDForLoadGroup(bot_owner->CharacterID(), group_name, error_message); - if (!group_id || error_message.size()) + + uint32 botgroup_id = 0; + if (!botdb.LoadBotGroupIDForLoadBotGroup(bot_owner->CharacterID(), group_name, botgroup_id) || !botgroup_id) return; - std::map> group_list = botdb.LoadGroup(group_name, error_message); - if (group_list.find(group_id) == group_list.end() || !group_list[group_id].size() || error_message.size()) + std::map> botgroup_list; + if (!botdb.LoadBotGroup(group_name, botgroup_list) || botgroup_list.find(botgroup_id) == botgroup_list.end() || !botgroup_list[botgroup_id].size()) return; std::list selectable_bot_list; @@ -1872,7 +1872,7 @@ namespace MyBots return; selectable_bot_list.remove(nullptr); - for (auto group_iter : group_list[group_id]) { + for (auto group_iter : botgroup_list[botgroup_id]) { for (auto bot_iter : selectable_bot_list) { if (bot_iter->GetBotID() != group_iter) continue; @@ -4185,34 +4185,45 @@ void bot_subcommand_bot_clone(Client *c, const Seperator *sep) return; } - std::string TempErrorMessage; + std::string error_message; - if (!Bot::IsBotNameAvailable(bot_name.c_str(), &TempErrorMessage)) { - if (!TempErrorMessage.empty()) - c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + bool available_flag = false; + if (!botdb.QueryNameAvailablity(bot_name, available_flag)) { + c->Message(m_fail, "%s", BotDatabase::fail::QueryNameAvailablity()); + return; + } + if (!available_flag) { c->Message(m_fail, "The name %s is already being used. Please choose a different name", bot_name.c_str()); return; } - uint32 mbc = RuleI(Bots, CreationLimit); - if (Bot::CreatedBotCount(c->CharacterID(), &TempErrorMessage) >= mbc) { - if (!TempErrorMessage.empty()) - c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); - c->Message(m_fail, "You have reached the maximum limit of %i bots", mbc); + uint32 max_bot_count = RuleI(Bots, CreationLimit); + + uint32 bot_count = 0; + if (!botdb.QueryBotCount(c->CharacterID(), bot_count)) { + c->Message(m_fail, "%s", BotDatabase::fail::QueryBotCount()); + return; + } + if (bot_count >= max_bot_count) { + c->Message(m_fail, "You have reached the maximum limit of %i bots", max_bot_count); return; } - auto clone_id = botdb.Clone(c->CharacterID(), my_bot->GetBotID(), bot_name.c_str()); - if (!clone_id) { - c->Message(m_fail, "Clone creation of bot '%s' failed...", my_bot->GetCleanName()); + uint32 clone_id = 0; + if (!botdb.CreateCloneBot(c->CharacterID(), my_bot->GetBotID(), bot_name, clone_id) || !clone_id) { + c->Message(m_fail, "%s '%s'", BotDatabase::fail::CreateCloneBot(), bot_name.c_str()); return; } - if (!botdb.CloneInventory(c->CharacterID(), my_bot->GetBotID(), clone_id)) { - c->Message(m_fail, "Inventory import for bot clone '%s' failed...", bot_name.c_str()); - return; - } + BotStanceType clone_stance = BotStancePassive; + if (!botdb.LoadStance(my_bot->GetBotID(), clone_stance)) + c->Message(m_fail, "%s for bot '%s'", BotDatabase::fail::LoadStance(), my_bot->GetCleanName()); + if (!botdb.SaveStance(clone_id, clone_stance)) + c->Message(m_fail, "%s for clone '%s'", BotDatabase::fail::SaveStance(), bot_name.c_str()); + if (!botdb.CreateCloneBotInventory(c->CharacterID(), my_bot->GetBotID(), clone_id)) + c->Message(m_fail, "%s for clone '%s'", BotDatabase::fail::CreateCloneBotInventory(), bot_name.c_str()); + c->Message(m_action, "Bot '%s' was successfully cloned to bot '%s'", my_bot->GetCleanName(), bot_name.c_str()); } @@ -4276,11 +4287,10 @@ void bot_subcommand_bot_delete(Client *c, const Seperator *sep) return; } - std::string TempErrorMessage; + std::string error_message; - my_bot->DeleteBot(&TempErrorMessage); - if (!TempErrorMessage.empty()) { - c->Message(m_unknown, "Failed to delete '%s' due to database error: %s", my_bot->GetCleanName(), TempErrorMessage.c_str()); + if (!my_bot->DeleteBot()) { + c->Message(m_unknown, "Failed to delete '%s' due to database error", my_bot->GetCleanName()); return; } @@ -4401,14 +4411,14 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) } if (ab_type == ActionableBots::ABT_All) { - bool action_success = false; - if (dye_all) - action_success = botdb.SetAllArmorColors(c->CharacterID(), rgb_value); - else - action_success = botdb.SetAllArmorColorBySlot(c->CharacterID(), slot_id, rgb_value); - - if (!action_success) - c->Message(m_unknown, "Failed to save dye armor changes for your bots due to unknown cause"); + if (dye_all) { + if (!botdb.SaveAllArmorColors(c->CharacterID(), rgb_value)) + c->Message(m_fail, "%s", BotDatabase::fail::SaveAllArmorColors()); + } + else { + if (!botdb.SaveAllArmorColorBySlot(c->CharacterID(), slot_id, rgb_value)) + c->Message(m_fail, "%s", BotDatabase::fail::SaveAllArmorColorBySlot()); + } } } @@ -4551,8 +4561,8 @@ void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep) continue; bot_iter->SetFollowDistance(bfd); - if (ab_type != ActionableBots::ABT_All && !botdb.SetFollowDistance(c->CharacterID(), bot_iter->GetBotID(), bfd)) { - c->Message(m_unknown, "DATABASE ERROR: Could not change follow distance for bot %s", bot_iter->GetCleanName()); + if (ab_type != ActionableBots::ABT_All && !botdb.SaveFollowDistance(c->CharacterID(), bot_iter->GetBotID(), bfd)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::SaveFollowDistance(), bot_iter->GetCleanName()); return; } @@ -4560,8 +4570,8 @@ void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep) } if (ab_type == ActionableBots::ABT_All) { - if (!botdb.SetAllFollowDistances(c->CharacterID(), bfd)) { - c->Message(m_unknown, "Failed to save follow distance changes for your bots due to unknown cause"); + if (!botdb.SaveAllFollowDistances(c->CharacterID(), bfd)) { + c->Message(m_fail, "%s", BotDatabase::fail::SaveAllFollowDistances()); return; } @@ -4717,32 +4727,34 @@ void bot_subcommand_bot_inspect_message(Client *c, const Seperator *sep) if (ab_type == ActionableBots::ABT_None) return; - const auto cms = &c->GetInspectMessage(); + const auto client_message_struct = &c->GetInspectMessage(); int bot_count = 0; for (auto bot_iter : sbl) { if (!bot_iter) continue; - auto bms = &bot_iter->GetInspectMessage(); - memset(bms, 0, sizeof(InspectMessage_Struct)); + auto bot_message_struct = &bot_iter->GetInspectMessage(); + memset(bot_message_struct, 0, sizeof(InspectMessage_Struct)); if (set_flag) - memcpy(bms, cms, sizeof(InspectMessage_Struct)); + memcpy(bot_message_struct, client_message_struct, sizeof(InspectMessage_Struct)); - if (ab_type != ActionableBots::ABT_All) - botdb.SetInspectMessage(bot_iter->GetBotID(), bms); + if (ab_type != ActionableBots::ABT_All && !botdb.SaveInspectMessage(bot_iter->GetBotID(), *bot_message_struct)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::SaveInspectMessage(), bot_iter->GetCleanName()); + return; + } ++bot_count; } if (ab_type == ActionableBots::ABT_All) { - InspectMessage_Struct bms; - memset(&bms, 0, sizeof(InspectMessage_Struct)); + InspectMessage_Struct bot_message_struct; + memset(&bot_message_struct, 0, sizeof(InspectMessage_Struct)); if (set_flag) - memcpy(&bms, cms, sizeof(InspectMessage_Struct)); + memcpy(&bot_message_struct, client_message_struct, sizeof(InspectMessage_Struct)); - if (!botdb.SetAllInspectMessages(c->CharacterID(), &bms)) { - c->Message(m_fail, "Failed to save inspect message changes for your bots due to unknown cause"); + if (!botdb.SaveAllInspectMessages(c->CharacterID(), bot_message_struct)) { + c->Message(m_fail, "%s", BotDatabase::fail::SaveAllInspectMessages()); return; } @@ -4796,29 +4808,27 @@ void bot_subcommand_bot_list(Client *c, const Seperator *sep) return; } - std::string TempErrorMessage; - auto dbbl = Bot::GetBotList(c->CharacterID(), &TempErrorMessage); - - if (!TempErrorMessage.empty()) { - c->Message(m_fail, "Failed to load 'BotsAvailableList' due to unknown cause"); + std::list bots_list; + if (!botdb.LoadBotsList(c->CharacterID(), bots_list)) { + c->Message(m_fail, "%s", BotDatabase::fail::LoadBotsList()); return; } - if (dbbl.empty()) { + if (bots_list.empty()) { c->Message(m_fail, "You have no bots"); return; } int bot_count = 0; - for (auto dbbl_iter : dbbl) { + for (auto bots_iter : bots_list) { if (filter_mask) { - if ((filter_mask & MaskClass) && filter_value[FilterClass] != dbbl_iter.BotClass) + if ((filter_mask & MaskClass) && filter_value[FilterClass] != bots_iter.Class) continue; - if ((filter_mask & MaskRace) && filter_value[FilterRace] != dbbl_iter.BotRace) + if ((filter_mask & MaskRace) && filter_value[FilterRace] != bots_iter.Race) continue; if (filter_mask & MaskName) { std::string name_criteria = sep->arg[name_criteria_arg]; std::transform(name_criteria.begin(), name_criteria.end(), name_criteria.begin(), ::tolower); - std::string name_check = dbbl_iter.BotName; + std::string name_check = bots_iter.Name; std::transform(name_check.begin(), name_check.end(), name_check.begin(), ::tolower); if (name_check.find(name_criteria) == std::string::npos) continue; @@ -4826,11 +4836,11 @@ void bot_subcommand_bot_list(Client *c, const Seperator *sep) } c->Message(m_message, "%s is a level %u %s %s %s", - dbbl_iter.BotName, - dbbl_iter.BotLevel, - Bot::RaceIdToString(dbbl_iter.BotRace).c_str(), - ((dbbl_iter.BotGender == FEMALE) ? ("Female") : ((dbbl_iter.BotGender == MALE) ? ("Male") : ("Neuter"))), - Bot::ClassIdToString(dbbl_iter.BotClass).c_str() + bots_iter.Name, + bots_iter.Level, + Bot::RaceIdToString(bots_iter.Race).c_str(), + ((bots_iter.Gender == FEMALE) ? ("Female") : ((bots_iter.Gender == MALE) ? ("Male") : ("Neuter"))), + Bot::ClassIdToString(bots_iter.Class).c_str() ); ++bot_count; @@ -4839,7 +4849,7 @@ void bot_subcommand_bot_list(Client *c, const Seperator *sep) c->Message(m_fail, "You have no bots meeting this criteria"); } else { - c->Message(m_action, "%i of %i bot%s shown", bot_count, dbbl.size(), ((bot_count != 1) ? ("s") : (""))); + c->Message(m_action, "%i of %i bot%s shown", bot_count, bots_list.size(), ((bot_count != 1) ? ("s") : (""))); c->Message(m_message, "Your limit is %i bot%s", RuleI(Bots, CreationLimit), ((RuleI(Bots, CreationLimit) != 1) ? ("s") : (""))); } } @@ -4946,32 +4956,26 @@ void bot_subcommand_bot_spawn(Client *c, const Seperator *sep) return; } - std::string TempErrorMessage; - - int sbc = Bot::SpawnedBotCount(c->CharacterID(), &TempErrorMessage); - if (!TempErrorMessage.empty()) { - c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); - return; - } + int spawned_bot_count = Bot::SpawnedBotCount(c->CharacterID()); int rule_limit = RuleI(Bots, SpawnLimit); - if (sbc >= rule_limit && !c->GetGM()) { + if (spawned_bot_count >= rule_limit && !c->GetGM()) { c->Message(m_fail, "You can not have more than %i spawned bots", rule_limit); return; } if (RuleB(Bots, QuestableSpawnLimit) && !c->GetGM()) { - int abc = Bot::AllowedBotSpawns(c->CharacterID(), &TempErrorMessage); - if (!TempErrorMessage.empty()) { - c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + int allowed_bot_count = 0; + if (!botdb.LoadQuestableSpawnCount(c->CharacterID(), allowed_bot_count)) { + c->Message(m_fail, "%s", BotDatabase::fail::LoadQuestableSpawnCount()); return; } - if (!abc) { + if (!allowed_bot_count) { c->Message(m_fail, "You are not currently allowed any spawned bots"); return; } - if (sbc >= abc) { - c->Message(m_fail, "You have reached your current limit of %i spawned bots", abc); + if (spawned_bot_count >= allowed_bot_count) { + c->Message(m_fail, "You have reached your current limit of %i spawned bots", allowed_bot_count); return; } } @@ -4982,10 +4986,12 @@ void bot_subcommand_bot_spawn(Client *c, const Seperator *sep) } std::string bot_name = sep->arg[1]; - auto bot_id = Bot::GetBotIDByBotName(bot_name); - if (Bot::GetBotOwnerCharacterID(bot_id, &TempErrorMessage) != c->CharacterID()) { - if (!TempErrorMessage.empty()) - c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + uint32 bot_id = 0; + if (!botdb.LoadBotID(c->CharacterID(), bot_name, bot_id)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::LoadBotID(), bot_name.c_str()); + return; + } + if (!bot_id) { c->Message(m_fail, "You don't own a bot named '%s'", bot_name.c_str()); return; } @@ -5020,18 +5026,13 @@ void bot_subcommand_bot_spawn(Client *c, const Seperator *sep) // return; //} - auto my_bot = Bot::LoadBot(bot_id, &TempErrorMessage); - if (!TempErrorMessage.empty()) { - c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); - safe_delete(my_bot); - return; - } + auto my_bot = Bot::LoadBot(bot_id); if (!my_bot) { c->Message(m_fail, "No valid bot '%s' (id: %i) exists", bot_name.c_str(), bot_id); return; } - my_bot->Spawn(c, &TempErrorMessage); // 'TempErrorMessage' not used... + my_bot->Spawn(c); static const char* bot_spawn_message[16] = { "A solid weapon is my ally!", // WARRIOR / 'generic' @@ -5267,8 +5268,8 @@ void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep) bot_iter->SetShowHelm(helm_state); if (ab_type != ActionableBots::ABT_All) { - if (!botdb.SetHelmAppearance(c->CharacterID(), bot_iter->GetBotID(), bot_iter->GetShowHelm())) { - c->Message(m_unknown, "DATABASE ERROR: Could not change helm appearance for bot %s", bot_iter->GetCleanName()); + if (!botdb.SaveHelmAppearance(c->CharacterID(), bot_iter->GetBotID(), bot_iter->GetShowHelm())) { + c->Message(m_unknown, "%s for '%s'", bot_iter->GetCleanName()); return; } @@ -5287,15 +5288,14 @@ void bot_subcommand_bot_toggle_helm(Client *c, const Seperator *sep) } if (ab_type == ActionableBots::ABT_All) { - bool action_success = false; std::string query; - if (toggle_helm) - action_success = botdb.ToggleAllHelmAppearances(c->CharacterID()); - else - action_success = botdb.SetAllHelmAppearances(c->CharacterID(), helm_state); - if (!action_success) { - c->Message(m_unknown, "Failed to save helm changes for your bots due to unknown cause"); - return; + if (toggle_helm) { + if (!botdb.ToggleAllHelmAppearances(c->CharacterID())) + c->Message(m_fail, "%s", BotDatabase::fail::ToggleAllHelmAppearances()); + } + else { + if (!botdb.SaveAllHelmAppearances(c->CharacterID(), helm_state)) + c->Message(m_fail, "%s", BotDatabase::fail::SaveAllHelmAppearances()); } c->Message(m_action, "%s all of your bot show helm flags", toggle_helm ? "Toggled" : (helm_state ? "Set" : "Cleared")); @@ -5451,10 +5451,12 @@ void bot_subcommand_botgroup_add_member(Client *c, const Seperator *sep) return; } - std::string error_message; - if (botdb.GetGroupIDByMemberID(new_member->GetBotID(), error_message)) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + uint32 botgroup_id = 0; + if (!botdb.LoadBotGroupIDByMemberID(new_member->GetBotID(), botgroup_id)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDByMemberID(), new_member->GetCleanName()); + return; + } + if (botgroup_id) { c->Message(m_fail, "%s is already a current member of a bot-group", new_member->GetCleanName()); return; } @@ -5467,34 +5469,44 @@ void bot_subcommand_botgroup_add_member(Client *c, const Seperator *sep) return; } - auto group_leader = sbl.front(); - if (!group_leader) { + auto botgroup_leader = sbl.front(); + if (!botgroup_leader) { c->Message(m_unknown, "Error: Group leader bot dereferenced to nullptr"); return; } - Group* group_inst = group_leader->GetGroup(); - if (!group_inst || group_inst->GetLeader() != group_leader) { - c->Message(m_fail, "%s is not the current leader of a group", group_leader->GetCleanName()); + Group* group_inst = botgroup_leader->GetGroup(); + if (!group_inst || group_inst->GetLeader() != botgroup_leader) { + c->Message(m_fail, "%s is not the current leader of a group", botgroup_leader->GetCleanName()); return; } - if (!botdb.GetGroupIDByLeaderID(group_leader->GetBotID(), error_message)) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "%s is not the current leader of a bot-group", group_leader->GetCleanName()); + botgroup_id = 0; + if (!botdb.LoadBotGroupIDByLeaderID(botgroup_leader->GetBotID(), botgroup_id)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDByLeaderID(), botgroup_leader->GetCleanName()); + return; + } + if (!botgroup_id) { + c->Message(m_fail, "%s is not the current leader of a bot-group", botgroup_leader->GetCleanName()); return; } if (!Bot::AddBotToGroup(new_member, group_inst)) { - c->Message(m_fail, "Could not add %s as a new member to %s's group", new_member->GetCleanName(), group_leader->GetCleanName()); + c->Message(m_fail, "Could not add %s as a new member to %s's group", new_member->GetCleanName(), botgroup_leader->GetCleanName()); return; } database.SetGroupID(new_member->GetName(), group_inst->GetID(), new_member->GetBotID()); - botdb.AddMemberToBotGroup(group_leader->GetBotID(), new_member->GetBotID(), error_message); - std::string botgroup_name = botdb.GetGroupNameByLeaderID(group_leader->GetBotID(), error_message); + if (!botdb.AddMemberToBotGroup(botgroup_leader->GetBotID(), new_member->GetBotID())) { + c->Message(m_fail, "%s - %s->%s", BotDatabase::fail::AddMemberToBotGroup(), new_member->GetCleanName(), botgroup_leader->GetCleanName()); + Bot::RemoveBotFromGroup(new_member, botgroup_leader->GetGroup()); + return; + } + + std::string botgroup_name; + if (!botdb.LoadBotGroupNameByLeaderID(botgroup_leader->GetBotID(), botgroup_name)) + c->Message(m_fail, "%s", BotDatabase::fail::LoadBotGroupNameByLeaderID()); c->Message(m_action, "Successfully added %s to bot-group %s", new_member->GetCleanName(), botgroup_name.c_str()); } @@ -5508,13 +5520,19 @@ void bot_subcommand_botgroup_create(Client *c, const Seperator *sep) return; } - std::string group_name_arg = sep->arg[1]; - if (group_name_arg.empty()) { + std::string botgroup_name_arg = sep->arg[1]; + if (botgroup_name_arg.empty()) { c->Message(m_fail, "You must specify a [name] for this bot-group to use this command"); return; } - if (botdb.DoesBotGroupExist(group_name_arg)) { - c->Message(m_fail, "The [name] %s already exists for a bot-group. Please choose another", group_name_arg.c_str()); + + bool extant_flag = false; + if (!botdb.QueryBotGroupExistence(botgroup_name_arg, extant_flag)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::QueryBotGroupExistence(), botgroup_name_arg.c_str()); + return; + } + if (extant_flag) { + c->Message(m_fail, "The [name] %s already exists for a bot-group. Please choose another", botgroup_name_arg.c_str()); return; } @@ -5527,50 +5545,55 @@ void bot_subcommand_botgroup_create(Client *c, const Seperator *sep) return; } - auto group_leader = sbl.front(); - if (!group_leader) { + auto botgroup_leader = sbl.front(); + if (!botgroup_leader) { c->Message(m_unknown, "Error: Group leader bot dereferenced to nullptr"); return; } - if (group_leader->HasGroup()) { - c->Message(m_fail, "%s is already a current member of a group", group_leader->GetCleanName()); + if (botgroup_leader->HasGroup()) { + c->Message(m_fail, "%s is already a current member of a group", botgroup_leader->GetCleanName()); return; } - std::string error_message; - if (botdb.GetGroupIDByLeaderID(group_leader->GetBotID(), error_message)) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "%s is already the current leader of a bot-group", group_leader->GetCleanName()); + uint32 botgroup_id = 0; + if (!botdb.LoadBotGroupIDByLeaderID(botgroup_leader->GetBotID(), botgroup_id)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDByLeaderID(), botgroup_leader->GetCleanName()); return; } - if (botdb.GetGroupIDByMemberID(group_leader->GetBotID(), error_message)) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "%s is already a current member of a bot-group", group_leader->GetCleanName()); + if (botgroup_id) { + c->Message(m_fail, "%s is already the current leader of a bot-group", botgroup_leader->GetCleanName()); return; } - Group* group_inst = new Group(group_leader); + botgroup_id = 0; + if (!botdb.LoadBotGroupIDByMemberID(botgroup_leader->GetBotID(), botgroup_id)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDByMemberID(), botgroup_leader->GetCleanName()); + return; + } + if (botgroup_id) { + c->Message(m_fail, "%s is already a current member of a bot-group", botgroup_leader->GetCleanName()); + return; + } + + Group* group_inst = new Group(botgroup_leader); if (!group_inst) { c->Message(m_unknown, "Could not create a new group instance"); return; } - if (!botdb.CreateBotGroup(group_name_arg, group_leader->GetBotID(), error_message)) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "Could not create bot-group %s", group_name_arg.c_str()); + if (!botdb.CreateBotGroup(botgroup_name_arg, botgroup_leader->GetBotID())) { + c->Message(m_fail, "%s '%s'", BotDatabase::fail::CreateBotGroup(), botgroup_name_arg.c_str()); safe_delete(group_inst); return; } - entity_list.AddGroup(group_inst); - database.SetGroupID(group_leader->GetCleanName(), group_inst->GetID(), group_leader->GetBotID()); - database.SetGroupLeaderName(group_inst->GetID(), group_leader->GetCleanName()); - group_leader->SetFollowID(c->GetID()); - c->Message(m_action, "Successfully created bot-group %s with %s as its leader", group_name_arg.c_str(), group_leader->GetCleanName()); + entity_list.AddGroup(group_inst); + database.SetGroupID(botgroup_leader->GetCleanName(), group_inst->GetID(), botgroup_leader->GetBotID()); + database.SetGroupLeaderName(group_inst->GetID(), botgroup_leader->GetCleanName()); + botgroup_leader->SetFollowID(c->GetID()); + + c->Message(m_action, "Successfully created bot-group '%s' with '%s' as its leader", botgroup_name_arg.c_str(), botgroup_leader->GetCleanName()); } void bot_subcommand_botgroup_delete(Client *c, const Seperator *sep) @@ -5582,36 +5605,48 @@ void bot_subcommand_botgroup_delete(Client *c, const Seperator *sep) return; } - std::string group_name_arg = sep->arg[1]; - if (group_name_arg.empty()) { + std::string botgroup_name_arg = sep->arg[1]; + if (botgroup_name_arg.empty()) { c->Message(m_fail, "You must specify a [name] for this bot-group to use this command"); return; } - std::string error_message; - uint32 group_id = botdb.GetGroupIDForLoadGroup(c->CharacterID(), group_name_arg, error_message); - if (!group_id) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "Could not locate group id for %s", group_name_arg.c_str()); + uint32 botgroup_id = 0; + if (!botdb.LoadBotGroupIDForLoadBotGroup(c->CharacterID(), botgroup_name_arg, botgroup_id)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDForLoadBotGroup(), botgroup_name_arg.c_str()); + return; + } + if (!botgroup_id) { + c->Message(m_fail, "Could not locate group id for '%s'", botgroup_name_arg.c_str()); return; } - uint32 leader_id = botdb.GetLeaderIDByGroupID(group_id, error_message); + uint32 leader_id = 0; + if (!botdb.LoadLeaderIDByBotGroupID(botgroup_id, leader_id)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::LoadLeaderIDByBotGroupID(), botgroup_name_arg.c_str()); + return; + } if (!leader_id) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "Could not locate leader id for %s", group_name_arg.c_str()); + c->Message(m_fail, "Could not locate leader id for '%s'", botgroup_name_arg.c_str()); return; } std::list gbl; std::list sbl; MyBots::PopulateSBL_BySpawnedBots(c, sbl); - std::map> groups_list = botdb.LoadGroup(group_name_arg, error_message); + + std::map> member_list; + if (!botdb.LoadBotGroup(botgroup_name_arg, member_list)) { + c->Message(m_fail, "%s '%s'", BotDatabase::fail::LoadBotGroup(), botgroup_name_arg.c_str()); + return; + } + if (member_list.find(botgroup_id) == member_list.end() || member_list[botgroup_id].empty()) { + c->Message(m_fail, "Could not locate member list for bot-group '%s'", botgroup_name_arg.c_str()); + return; + } for (auto bot_iter : sbl) { - for (auto group_iter : groups_list[group_id]) { + for (auto group_iter : member_list[botgroup_id]) { if (bot_iter->GetBotID() == group_iter) { gbl.push_back(bot_iter); break; @@ -5625,14 +5660,12 @@ void bot_subcommand_botgroup_delete(Client *c, const Seperator *sep) Bot::RemoveBotFromGroup(group_member, group_member->GetGroup()); } - if (!botdb.DeleteBotGroup(leader_id, error_message)) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "Failed to delete bot-group %s", group_name_arg.c_str()); + if (!botdb.DeleteBotGroup(leader_id)) { + c->Message(m_fail, "%s '%s'", BotDatabase::fail::DeleteBotGroup(), botgroup_name_arg.c_str()); return; } - c->Message(m_action, "Successfully deleted bot-group %s", group_name_arg.c_str()); + c->Message(m_action, "Successfully deleted bot-group %s", botgroup_name_arg.c_str()); } void bot_subcommand_botgroup_list(Client *c, const Seperator *sep) @@ -5644,18 +5677,19 @@ void bot_subcommand_botgroup_list(Client *c, const Seperator *sep) return; } - std::string error_message; - auto groups_list = botdb.GetGroupsListByOwnerID(c->CharacterID(), error_message); - if (groups_list.empty()) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + std::list> botgroups_list; + if (!botdb.LoadBotGroupsListByOwnerID(c->CharacterID(), botgroups_list)) { + c->Message(m_fail, "%s", BotDatabase::fail::LoadBotGroupsListByOwnerID()); + return; + } + if (botgroups_list.empty()) { c->Message(m_fail, "You have no saved bot-groups"); return; } int botgroup_count = 0; - for (auto groups_iter : groups_list) - c->Message(m_message, "(%i) Bot-group name: %s | Leader: %s", (++botgroup_count), groups_iter.first.c_str(), groups_iter.second.c_str()); + for (auto botgroups_iter : botgroups_list) + c->Message(m_message, "(%i) Bot-group name: %s | Leader: %s", (++botgroup_count), botgroups_iter.first.c_str(), botgroups_iter.second.c_str()); c->Message(m_action, "%i bot-groups listed", botgroup_count); } @@ -5669,13 +5703,19 @@ void bot_subcommand_botgroup_load(Client *c, const Seperator *sep) return; } - std::string group_name_arg = sep->arg[1]; - if (group_name_arg.empty()) { + std::string botgroup_name_arg = sep->arg[1]; + if (botgroup_name_arg.empty()) { c->Message(m_fail, "You must specify the [name] of a bot-group to load to use this command"); return; } - if (!botdb.DoesBotGroupExist(group_name_arg)) { - c->Message(m_fail, "Bot-group %s does not exist", group_name_arg.c_str()); + + bool extant_flag = false; + if (!botdb.QueryBotGroupExistence(botgroup_name_arg, extant_flag)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::QueryBotGroupExistence(), botgroup_name_arg.c_str()); + return; + } + if (!extant_flag) { + c->Message(m_fail, "Bot-group %s does not exist", botgroup_name_arg.c_str()); return; } @@ -5699,33 +5739,28 @@ void bot_subcommand_botgroup_load(Client *c, const Seperator *sep) } } - std::string error_message; - uint32 group_id = botdb.GetGroupIDForLoadGroup(c->CharacterID(), group_name_arg, error_message); - if (!group_id) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "Can not resolve bot-group %s to a valid id", group_name_arg.c_str()); + uint32 botgroup_id = 0; + if (!botdb.LoadBotGroupIDForLoadBotGroup(c->CharacterID(), botgroup_name_arg, botgroup_id) || !botgroup_id) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::LoadBotGroupIDForLoadBotGroup(), botgroup_name_arg.c_str()); return; } - std::map> group_list = botdb.LoadGroup(group_name_arg, error_message); - if (group_list.empty()) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "Database returned an empty list for got-group %s", group_name_arg.c_str()); + std::map> member_list; + if (!botdb.LoadBotGroup(botgroup_name_arg, member_list)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::LoadBotGroup(), botgroup_name_arg.c_str()); + return; + } + if (member_list.find(botgroup_id) == member_list.end() || member_list[botgroup_id].empty()) { + c->Message(m_fail, "Database returned an empty list for bot-group '%s'", botgroup_name_arg.c_str()); return; } - int spawned_bot_count = Bot::SpawnedBotCount(c->CharacterID(), &error_message); - if (!error_message.empty()) { - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - return; - } + int spawned_bot_count = Bot::SpawnedBotCount(c->CharacterID()); if (RuleB(Bots, QuestableSpawnLimit)) { - const int allowed_bot_count = Bot::AllowedBotSpawns(c->CharacterID(), &error_message); - if (!error_message.empty()) { - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + int allowed_bot_count = 0; + if (!botdb.LoadQuestableSpawnCount(c->CharacterID(), allowed_bot_count)) { + c->Message(m_fail, "%s", BotDatabase::fail::LoadQuestableSpawnCount()); return; } @@ -5734,63 +5769,59 @@ void bot_subcommand_botgroup_load(Client *c, const Seperator *sep) return; } - if (spawned_bot_count >= allowed_bot_count || (spawned_bot_count + group_list.begin()->second.size()) > allowed_bot_count) { + if (spawned_bot_count >= allowed_bot_count || (spawned_bot_count + member_list.begin()->second.size()) > allowed_bot_count) { c->Message(m_fail, "You can not spawn more than %i bot%s (quest-limit)", allowed_bot_count, ((allowed_bot_count == 1) ? ("") : ("s"))); return; } } const int allowed_bot_limit = RuleI(Bots, SpawnLimit); - if (spawned_bot_count >= allowed_bot_limit || (spawned_bot_count + group_list.begin()->second.size()) > allowed_bot_limit) { + if (spawned_bot_count >= allowed_bot_limit || (spawned_bot_count + member_list.begin()->second.size()) > allowed_bot_limit) { c->Message(m_fail, "You can not spawn more than %i bot%s (hard-limit)", allowed_bot_limit, ((allowed_bot_limit == 1) ? ("") : ("s"))); return; } - uint32 leader_id = botdb.GetLeaderIDByGroupName(group_name_arg, error_message); + uint32 leader_id = 0; + if (!botdb.LoadLeaderIDByBotGroupName(botgroup_name_arg, leader_id)) { + c->Message(m_fail, "%s for '%s'", BotDatabase::fail::LoadLeaderIDByBotGroupName(), botgroup_name_arg.c_str()); + return; + } if (!leader_id) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "Can not locate bot-group leader id for %s", group_name_arg.c_str()); + c->Message(m_fail, "Can not locate bot-group leader id for '%s'", botgroup_name_arg.c_str()); return; } - auto group_leader = Bot::LoadBot(leader_id, &error_message); - if (!group_leader) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "Could not spawn bot-group leader for %s", group_name_arg.c_str()); - safe_delete(group_leader); + auto botgroup_leader = Bot::LoadBot(leader_id); + if (!botgroup_leader) { + c->Message(m_fail, "Could not spawn bot-group leader for '%s'", botgroup_name_arg.c_str()); + safe_delete(botgroup_leader); return; } - group_leader->Spawn(c, &error_message); - // No error_message code in Bot::Spawn() + botgroup_leader->Spawn(c); - Group* group_inst = new Group(group_leader); + Group* group_inst = new Group(botgroup_leader); entity_list.AddGroup(group_inst); - database.SetGroupID(group_leader->GetCleanName(), group_inst->GetID(), group_leader->GetBotID()); - database.SetGroupLeaderName(group_inst->GetID(), group_leader->GetCleanName()); - group_leader->SetFollowID(c->GetID()); + database.SetGroupID(botgroup_leader->GetCleanName(), group_inst->GetID(), botgroup_leader->GetBotID()); + database.SetGroupLeaderName(group_inst->GetID(), botgroup_leader->GetCleanName()); + botgroup_leader->SetFollowID(c->GetID()); - group_list[group_id].remove(0); - group_list[group_id].remove(group_leader->GetBotID()); - for (auto member_iter : group_list[group_id]) { - auto group_member = Bot::LoadBot(member_iter, &error_message); - if (!group_member) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); + member_list[botgroup_id].remove(0); + member_list[botgroup_id].remove(botgroup_leader->GetBotID()); + for (auto member_iter : member_list[botgroup_id]) { + auto botgroup_member = Bot::LoadBot(member_iter); + if (!botgroup_member) { c->Message(m_fail, "Could not load bot id %i", member_iter); - safe_delete(group_member); + safe_delete(botgroup_member); return; } - group_member->Spawn(c, &error_message); - // No error_message code in Bot::Spawn() - Bot::AddBotToGroup(group_member, group_inst); + botgroup_member->Spawn(c); + Bot::AddBotToGroup(botgroup_member, group_inst); } - c->Message(m_action, "Successfully loaded bot-group %s", group_name_arg.c_str()); + c->Message(m_action, "Successfully loaded bot-group %s", botgroup_name_arg.c_str()); } void bot_subcommand_botgroup_remove_member(Client *c, const Seperator *sep) @@ -5827,11 +5858,8 @@ void bot_subcommand_botgroup_remove_member(Client *c, const Seperator *sep) return; } - std::string error_message; - if (!botdb.RemoveMemberFromBotGroup(group_member->GetBotID(), error_message)) { - if (!error_message.empty()) - c->Message(m_unknown, "Database Error: %s", error_message.c_str()); - c->Message(m_fail, "Could not remove %s from their bot-group", group_member->GetCleanName()); + if (!botdb.RemoveMemberFromBotGroup(group_member->GetBotID())) { + c->Message(m_fail, "%s - '%s'", BotDatabase::fail::RemoveMemberFromBotGroup(), group_member->GetCleanName()); return; } @@ -6786,13 +6814,6 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) return; } - std::string TempErrorMessage; - my_bot->GetBotItemsCount(&TempErrorMessage); // database check to avoid false 'vacancy' reporting? - if (!TempErrorMessage.empty()) { - c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - const ItemInst* inst = nullptr; const Item_Struct* item = nullptr; bool is2Hweapon = false; @@ -6801,6 +6822,7 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) Client::TextLink linker; linker.SetLinkType(linker.linkItemInst); + uint32 inventory_count = 0; for (int i = EmuConstants::EQUIPMENT_BEGIN; i <= (EmuConstants::EQUIPMENT_END + 1); ++i) { if ((i == MainSecondary) && is2Hweapon) continue; @@ -6819,7 +6841,16 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) linker.SetItemInst(inst); item_link = linker.GenerateLink(); c->Message(m_message, "Using %s in my %s (slot %i)", item_link.c_str(), GetBotEquipSlotName(i), (i == 22 ? 9999 : i)); + + ++inventory_count; } + + uint32 database_count = 0; + if (!botdb.QueryInventoryCount(my_bot->GetBotID(), database_count)) + c->Message(m_unknown, "%s", BotDatabase::fail::QueryInventoryCount()); + + if (inventory_count != database_count) + c->Message(m_unknown, "Inventory-database item count mismatch: inv = '%u', db = '%u'", inventory_count, database_count); } void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) @@ -6847,13 +6878,6 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) return; } - std::string TempErrorMessage; - my_bot->GetBotItemsCount(&TempErrorMessage); // added same check as in bot_subcommand_inventory_list() - same note - if (!TempErrorMessage.empty()) { - c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); - return; - } - int slotId = atoi(sep->arg[1]); if (!sep->IsNumber(1) || ((slotId > EmuConstants::EQUIPMENT_END || slotId < EmuConstants::EQUIPMENT_BEGIN) && slotId != 9999)) { c->Message(m_fail, "Valid slots are 0-21 or 9999"); @@ -6884,14 +6908,15 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) return; } + std::string error_message; if (itm) { c->PushItemOnCursor(*itminst, true); if ((slotId == MainRange) || (slotId == MainAmmo) || (slotId == MainPrimary) || (slotId == MainSecondary)) my_bot->SetBotArcher(false); - my_bot->RemoveBotItemBySlot(slotId, &TempErrorMessage); - if (!TempErrorMessage.empty()) { - c->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + my_bot->RemoveBotItemBySlot(slotId, &error_message); + if (!error_message.empty()) { + c->Message(m_unknown, "Database Error: %s", error_message.c_str()); return; } @@ -7183,11 +7208,12 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas return bot_id; } - std::string TempErrorMessage; - - if (!Bot::IsBotNameAvailable(bot_name.c_str(), &TempErrorMessage)) { - if (!TempErrorMessage.empty()) - bot_owner->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); + bool available_flag = false; + if (!botdb.QueryNameAvailablity(bot_name, available_flag)) { + bot_owner->Message(m_fail, "%s for '%s'", BotDatabase::fail::QueryNameAvailablity(), bot_name.c_str()); + return bot_id; + } + if (!available_flag) { bot_owner->Message(m_fail, "The name %s is already being used. Please choose a different name", bot_name.c_str()); return bot_id; } @@ -7203,11 +7229,15 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas return bot_id; } - uint32 mbc = RuleI(Bots, CreationLimit); - if (Bot::CreatedBotCount(bot_owner->CharacterID(), &TempErrorMessage) >= mbc) { - if (!TempErrorMessage.empty()) - bot_owner->Message(m_unknown, "Database Error: %s", TempErrorMessage.c_str()); - bot_owner->Message(m_fail, "You have reached the maximum limit of %i bots", mbc); + uint32 max_bot_count = RuleI(Bots, CreationLimit); + + uint32 bot_count = 0; + if (!botdb.QueryBotCount(bot_owner->CharacterID(), bot_count)) { + bot_owner->Message(m_fail, "%s", BotDatabase::fail::QueryBotCount()); + return bot_id; + } + if (bot_count >= max_bot_count) { + bot_owner->Message(m_fail, "You have reached the maximum limit of %i bots", max_bot_count); return bot_id; } diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 3e7e18c1e..d031ee0cf 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -26,12 +26,13 @@ #include "bot_database.h" #include "bot.h" + BotDatabase botdb; BotDatabase::BotDatabase() { - + } BotDatabase::BotDatabase(const char* host, const char* user, const char* passwd, const char* database, uint32 port) @@ -57,11 +58,11 @@ bool BotDatabase::Connect(const char* host, const char* user, const char* passwd } } -bool BotDatabase::GetCommandSettings(std::map>> &bot_command_settings) +bool BotDatabase::LoadBotCommandSettings(std::map>> &bot_command_settings) { bot_command_settings.clear(); - std::string query = "SELECT `bot_command`, `access`, `aliases` FROM `bot_command_settings`"; + query = "SELECT `bot_command`, `access`, `aliases` FROM `bot_command_settings`"; auto results = QueryDatabase(query); if (!results.Success()) return false; @@ -82,57 +83,1664 @@ bool BotDatabase::GetCommandSettings(std::map 15 || !database.CheckNameFilter(bot_name.c_str()) || !database.CheckUsedName(bot_name.c_str())) + return false; + + query = StringFormat("SELECT `id` FROM `vw_bot_character_mobs` WHERE `name` LIKE '%s' LIMIT 1", bot_name.c_str()); auto results = QueryDatabase(query); if (!results.Success()) return false; + if (results.RowCount()) + return true; + + available_flag = true; + + return true; +} + +bool BotDatabase::QueryBotCount(const uint32 owner_id, uint32& bot_count) +{ + if (!owner_id) + return false; + + query = StringFormat("SELECT COUNT(`bot_id`) FROM `bot_data` WHERE `owner_id` = '%i'", owner_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + bot_count = atoi(row[0]); + + return true; +} + +bool BotDatabase::LoadQuestableSpawnCount(const uint32 owner_id, int& spawn_count) +{ + if (!owner_id) + return false; + + query = StringFormat("SELECT `value` FROM `quest_globals` WHERE `name` = 'bot_spawn_limit' AND `charid` = '%i' LIMIT 1", owner_id); + auto results = database.QueryDatabase(query); // use 'database' for non-bot table calls + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; auto row = results.begin(); - memset(message, '\0', sizeof(InspectMessage_Struct)); + spawn_count = atoi(row[0]); + + return true; +} + +bool BotDatabase::LoadBotsList(const uint32 owner_id, std::list& bots_list) +{ + if (!owner_id) + return false; + + query = StringFormat("SELECT `bot_id`, `name`, `class`, `level`, `race`, `gender` FROM `bot_data` WHERE `owner_id` = '%u'", owner_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + for (auto row = results.begin(); row != results.end(); ++row) { - memcpy(message, row[0], sizeof(InspectMessage_Struct)); + BotsAvailableList bot_entry; + + bot_entry.ID = atoi(row[0]); + + memset(&bot_entry.Name, 0, sizeof(bot_entry.Name)); + std::string bot_name = row[1]; + if (bot_name.size() > 63) + bot_name = bot_name.substr(0, 63); + if (!bot_name.empty()) + strcpy(bot_entry.Name, bot_name.c_str()); + + bot_entry.Class = atoi(row[2]); + bot_entry.Level = atoi(row[3]); + bot_entry.Race = atoi(row[4]); + bot_entry.Gender = atoi(row[5]); + + bots_list.push_back(bot_entry); } return true; } -bool BotDatabase::SetInspectMessage(uint32 bot_id, const InspectMessage_Struct* message) +bool BotDatabase::LoadOwnerID(const std::string& bot_name, uint32& owner_id) { - std::string query = StringFormat("REPLACE INTO `bot_inspect_messages` (bot_id, inspect_message) VALUES (%u, '%s')", bot_id, EscapeString(message->text).c_str()); - auto results = QueryDatabase(query); + if (bot_name.empty()) + return false; - return results.Success(); + query = StringFormat("SELECT `owner_id` FROM `bot_data` WHERE `name` = '%s' LIMIT 1", bot_name.c_str()); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + owner_id = atoi(row[0]); + + return true; } -bool BotDatabase::SetAllInspectMessages(uint32 owner_id, const InspectMessage_Struct* message) +bool BotDatabase::LoadOwnerID(const uint32 bot_id, uint32& owner_id) { - std::string query = StringFormat( - "UPDATE `bot_inspect_messages`" - " SET `inspect_message` = '%s'" - " WHERE `bot_id`" - " IN (SELECT `bot_id` FROM `bot_data` WHERE `owner_id` = '%u')", - EscapeString(message->text).c_str(), owner_id + if (!bot_id) + return false; + + query = StringFormat("SELECT `owner_id` FROM `bot_data` WHERE `bot_id` = '%u' LIMIT 1", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + owner_id = atoi(row[0]); + + return true; +} + +bool BotDatabase::LoadBotID(const uint32 owner_id, const std::string& bot_name, uint32& bot_id) +{ + if (!owner_id || bot_name.empty()) + return false; + + query = StringFormat("SELECT `bot_id` FROM `bot_data` WHERE `name` = '%s' LIMIT 1", bot_name.c_str()); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + bot_id = atoi(row[0]); + + return true; +} + +bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot) +{ + if (!bot_id || loaded_bot) + return false; + + query = StringFormat( + "SELECT" + " `owner_id`," + " `spells_id`," + " `name`," + " `last_name`," + " `title`," /* planned use[4] */ + " `suffix`," /* planned use[5] */ + " `zone_id`," + " `gender`," + " `race`," + " `class`," + " `level`," + " `deity`," /* planned use[11] */ + " `creation_day`," /* not in-use[12] */ + " `last_spawn`," /* not in-use[13] */ + " `time_spawned`," + " `size`," + " `face`," + " `hair_color`," + " `hair_style`," + " `beard`," + " `beard_color`," + " `eye_color_1`," + " `eye_color_2`," + " `drakkin_heritage`," + " `drakkin_tattoo`," + " `drakkin_details`," + " `ac`," /* not in-use[26] */ + " `atk`," /* not in-use[27] */ + " `hp`," + " `mana`," + " `str`," /* not in-use[30] */ + " `sta`," /* not in-use[31] */ + " `cha`," /* not in-use[32] */ + " `dex`," /* not in-use[33] */ + " `int`," /* not in-use[34] */ + " `agi`," /* not in-use[35] */ + " `wis`," /* not in-use[36] */ + " `fire`," /* not in-use[37] */ + " `cold`," /* not in-use[38] */ + " `magic`," /* not in-use[39] */ + " `poison`," /* not in-use[40] */ + " `disease`," /* not in-use[41] */ + " `corruption`," /* not in-use[42] */ + " `show_helm`," // 43 + " `follow_distance`" // 44 + " FROM `bot_data`" + " WHERE `bot_id` = '%u'" + " LIMIT 1", + bot_id + ); + + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + // TODO: Consider removing resists and basic attributes from the load query above since we're using defaultNPCType values instead + auto row = results.begin(); + NPCType defaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[10]), atoi(row[8]), atoi(row[9]), atoi(row[7])); + NPCType tempNPCStruct = Bot::FillNPCTypeStruct( + atoi(row[1]), + std::string(row[2]), + std::string(row[3]), + atoi(row[10]), + atoi(row[8]), + atoi(row[9]), + atoi(row[7]), + atof(row[15]), + atoi(row[16]), + atoi(row[18]), + atoi(row[17]), + atoi(row[21]), + atoi(row[22]), + atoi(row[20]), + atoi(row[19]), + atoi(row[23]), + atoi(row[24]), + atoi(row[25]), + atoi(row[28]), + atoi(row[29]), + defaultNPCTypeStruct.MR, + defaultNPCTypeStruct.CR, + defaultNPCTypeStruct.DR, + defaultNPCTypeStruct.FR, + defaultNPCTypeStruct.PR, + defaultNPCTypeStruct.Corrup, + defaultNPCTypeStruct.AC, + defaultNPCTypeStruct.STR, + defaultNPCTypeStruct.STA, + defaultNPCTypeStruct.DEX, + defaultNPCTypeStruct.AGI, + defaultNPCTypeStruct.INT, + defaultNPCTypeStruct.WIS, + defaultNPCTypeStruct.CHA, + defaultNPCTypeStruct.ATK + ); + + loaded_bot = new Bot(bot_id, atoi(row[0]), atoi(row[1]), atof(row[14]), atoi(row[6]), tempNPCStruct); + if (loaded_bot) { + loaded_bot->SetShowHelm((atoi(row[43]) > 0 ? true : false)); + loaded_bot->SetFollowDistance(atoi(row[44])); + } + + return true; +} + +bool BotDatabase::SaveNewBot(Bot* bot_inst, uint32& bot_id) +{ + if (!bot_inst) + return false; + + query = StringFormat( + "INSERT INTO `bot_data` (" + " `owner_id`," + " `spells_id`," + " `name`," + " `last_name`," + " `zone_id`," + " `gender`," + " `race`," + " `class`," + " `level`," + " `creation_day`," + " `last_spawn`," + " `time_spawned`," + " `size`," + " `face`," + " `hair_color`," + " `hair_style`," + " `beard`," + " `beard_color`," + " `eye_color_1`," + " `eye_color_2`," + " `drakkin_heritage`," + " `drakkin_tattoo`," + " `drakkin_details`," + " `ac`," + " `atk`," + " `hp`," + " `mana`," + " `str`," + " `sta`," + " `cha`," + " `dex`," + " `int`," + " `agi`," + " `wis`," + " `fire`," + " `cold`," + " `magic`," + " `poison`," + " `disease`," + " `corruption`," + " `show_helm`," + " `follow_distance`" + ")" + " VALUES (" + "'%u'," /* owner_id */ + " '%u'," /* spells_id */ + " '%s'," /* name */ + " '%s'," /* last_name */ + " '%i'," /* zone_id */ + " '%i'," /* gender */ + " '%i'," /* race */ + " '%i'," /* class */ + " '%u'," /* level */ + " UNIX_TIMESTAMP()," /* creation_day */ + " UNIX_TIMESTAMP()," /* last_spawn */ + " 0," /* time_spawned */ + " '%f'," /* size */ + " '%i'," /* face */ + " '%i'," /* hair_color */ + " '%i'," /* hair_style */ + " '%i'," /* beard */ + " '%i'," /* beard_color */ + " '%i'," /* eye_color_1 */ + " '%i'," /* eye_color_2 */ + " '%i'," /* drakkin_heritage */ + " '%i'," /* drakkin_tattoo */ + " '%i'," /* drakkin_details */ + " '%i'," /* ac */ + " '%i'," /* atk */ + " '%i'," /* hp */ + " '%i'," /* mana */ + " '%i'," /* str */ + " '%i'," /* sta */ + " '%i'," /* cha */ + " '%i'," /* dex */ + " '%i'," /* int */ + " '%i'," /* agi */ + " '%i'," /* wis */ + " '%i'," /* fire */ + " '%i'," /* cold */ + " '%i'," /* magic */ + " '%i'," /* poison */ + " '%i'," /* disease */ + " '%i'," /* corruption */ + " '1'," /* show_helm */ + " '%i'" /* follow_distance */ + ")", + bot_inst->GetBotOwnerCharacterID(), + bot_inst->GetBotSpellID(), + bot_inst->GetCleanName(), + bot_inst->GetLastName(), + bot_inst->GetLastZoneID(), + bot_inst->GetGender(), + bot_inst->GetRace(), + bot_inst->GetClass(), + bot_inst->GetLevel(), + bot_inst->GetSize(), + bot_inst->GetLuclinFace(), + bot_inst->GetHairColor(), + bot_inst->GetHairStyle(), + bot_inst->GetBeard(), + bot_inst->GetBeardColor(), + bot_inst->GetEyeColor1(), + bot_inst->GetEyeColor2(), + bot_inst->GetDrakkinHeritage(), + bot_inst->GetDrakkinTattoo(), + bot_inst->GetDrakkinDetails(), + bot_inst->GetAC(), + bot_inst->GetATK(), + bot_inst->GetHP(), + bot_inst->GetMana(), + bot_inst->GetSTR(), + bot_inst->GetSTA(), + bot_inst->GetCHA(), + bot_inst->GetDEX(), + bot_inst->GetINT(), + bot_inst->GetAGI(), + bot_inst->GetWIS(), + bot_inst->GetFR(), + bot_inst->GetCR(), + bot_inst->GetMR(), + bot_inst->GetPR(), + bot_inst->GetDR(), + bot_inst->GetCorrup(), + BOT_DEFAULT_FOLLOW_DISTANCE ); auto results = QueryDatabase(query); + if (!results.Success()) + return false; - return results.Success(); + bot_id = results.LastInsertedID(); + + return true; } -bool BotDatabase::SetAllArmorColorBySlot(uint32 owner_id, int16 slot_id, uint32 rgb_value) +bool BotDatabase::SaveBot(Bot* bot_inst) +{ + if (!bot_inst) + return false; + + query = StringFormat( + "UPDATE `bot_data`" + " SET" + " `owner_id` = '%u'," + " `spells_id` = '%u'," + " `name` = '%s'," + " `last_name` = '%s'," + " `zone_id` = '%i'," + " `gender` = '%i'," + " `race` = '%i'," + " `class` = '%i'," + " `level` = '%u'," + " `last_spawn` = UNIX_TIMESTAMP()," + " `time_spawned` = '%u'," + " `size` = '%f'," + " `face` = '%i'," + " `hair_color` = '%i'," + " `hair_style` = '%i'," + " `beard` = '%i'," + " `beard_color` = '%i'," + " `eye_color_1` = '%i'," + " `eye_color_2` = '%i'," + " `drakkin_heritage` = '%i'," + " `drakkin_tattoo` = '%i'," + " `drakkin_details` = '%i'," + " `ac` = '%i'," + " `atk` = '%i'," + " `hp` = '%i'," + " `mana` = '%i'," + " `str` = '%i'," + " `sta` = '%i'," + " `cha` = '%i'," + " `dex` = '%i'," + " `int` = '%i'," + " `agi` = '%i'," + " `wis` = '%i'," + " `fire` = '%i'," + " `cold` = '%i'," + " `magic` = '%i'," + " `poison` = '%i'," + " `disease` = '%i'," + " `corruption` = '%i'," + " `show_helm` = '%i'," + " `follow_distance` = '%i'" + " WHERE `bot_id` = '%u'", + bot_inst->GetBotOwnerCharacterID(), + bot_inst->GetBotSpellID(), + bot_inst->GetCleanName(), + bot_inst->GetLastName(), + bot_inst->GetLastZoneID(), + bot_inst->GetBaseGender(), + bot_inst->GetBaseRace(), + bot_inst->GetClass(), + bot_inst->GetLevel(), + bot_inst->GetTotalPlayTime(), + bot_inst->GetBaseSize(), + bot_inst->GetLuclinFace(), + bot_inst->GetHairColor(), + bot_inst->GetHairStyle(), + bot_inst->GetBeard(), + bot_inst->GetBeardColor(), + bot_inst->GetEyeColor1(), + bot_inst->GetEyeColor2(), + bot_inst->GetDrakkinHeritage(), + bot_inst->GetDrakkinTattoo(), + bot_inst->GetDrakkinDetails(), + bot_inst->GetBaseAC(), + bot_inst->GetBaseATK(), + bot_inst->GetHP(), + bot_inst->GetMana(), + bot_inst->GetBaseSTR(), + bot_inst->GetBaseSTA(), + bot_inst->GetBaseCHA(), + bot_inst->GetBaseDEX(), + bot_inst->GetBaseINT(), + bot_inst->GetBaseAGI(), + bot_inst->GetBaseWIS(), + bot_inst->GetBaseFR(), + bot_inst->GetBaseCR(), + bot_inst->GetBaseMR(), + bot_inst->GetBasePR(), + bot_inst->GetBaseDR(), + bot_inst->GetBaseCorrup(), + ((bot_inst->GetShowHelm()) ? (1) : (0)), + bot_inst->GetFollowDistance(), + bot_inst->GetBotID() + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::DeleteBot(const uint32 bot_id) +{ + if (!bot_id) + return false; + + query = StringFormat("DELETE FROM `bot_data` WHERE `bot_id` = '%u'", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::LoadBuffs(Bot* bot_inst) +{ + if (!bot_inst) + return false; + + query = StringFormat( + "SELECT" + " `spell_id`," + " `caster_level`," + " `duration_formula`," + " `tics_remaining`," + " `poison_counters`," + " `disease_counters`," + " `curse_counters`," + " `corruption_counters`," + " `numhits`," + " `melee_rune`," + " `magic_rune`," + " `dot_rune`," + " `persistent`," + " `caston_x`," + " `caston_y`," + " `caston_z`," + " `extra_di_chance`" + " FROM `bot_buffs`" + " WHERE `bot_id` = '%u'", + bot_inst->GetBotID() + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + Buffs_Struct* bot_buffs = bot_inst->GetBuffs(); + if (!bot_buffs) + return false; + + int buff_count = 0; + for (auto row = results.begin(); row != results.end() && buff_count < BUFF_COUNT; ++row) { + bot_buffs[buff_count].spellid = atoi(row[0]); + bot_buffs[buff_count].casterlevel = atoi(row[1]); + //row[2] (duration_formula) can probably be removed + bot_buffs[buff_count].ticsremaining = atoi(row[3]); + + if (CalculatePoisonCounters(bot_buffs[buff_count].spellid) > 0) + bot_buffs[buff_count].counters = atoi(row[4]); + else if (CalculateDiseaseCounters(bot_buffs[buff_count].spellid) > 0) + bot_buffs[buff_count].counters = atoi(row[5]); + else if (CalculateCurseCounters(bot_buffs[buff_count].spellid) > 0) + bot_buffs[buff_count].counters = atoi(row[6]); + else if (CalculateCorruptionCounters(bot_buffs[buff_count].spellid) > 0) + bot_buffs[buff_count].counters = atoi(row[7]); + + bot_buffs[buff_count].numhits = atoi(row[8]); + bot_buffs[buff_count].melee_rune = atoi(row[9]); + bot_buffs[buff_count].magic_rune = atoi(row[10]); + bot_buffs[buff_count].dot_rune = atoi(row[11]); + bot_buffs[buff_count].persistant_buff = ((atoi(row[12])) ? (true) : (false)); + bot_buffs[buff_count].caston_x = atoi(row[13]); + bot_buffs[buff_count].caston_y = atoi(row[14]); + bot_buffs[buff_count].caston_z = atoi(row[15]); + bot_buffs[buff_count].ExtraDIChance = atoi(row[16]); + bot_buffs[buff_count].casterid = 0; + ++buff_count; + } + + return true; +} + +bool BotDatabase::SaveBuffs(Bot* bot_inst) +{ + if (!bot_inst) + return false; + + if (!DeleteBuffs(bot_inst->GetBotID())) + return false; + + Buffs_Struct* bot_buffs = bot_inst->GetBuffs(); + if (!bot_buffs) + return false; + + for (int buff_index = 0; buff_index < BUFF_COUNT; ++buff_index) { + if (bot_buffs[buff_index].spellid <= 0 || bot_buffs[buff_index].spellid == SPELL_UNKNOWN) + continue; + + query = StringFormat( + "INSERT INTO `bot_buffs` (" + "`bot_id`," + " `spell_id`," + " `caster_level`," + " `duration_formula`," + " `tics_remaining`," + " `poison_counters`," + " `disease_counters`," + " `curse_counters`," + " `corruption_counters`," + " `numhits`," + " `melee_rune`," + " `magic_rune`," + " `dot_rune`," + " `persistent`," + " `caston_x`," + " `caston_y`," + " `caston_z`," + " `extra_di_chance`" + ")" + " VALUES (" + "'%u'," /* bot_id */ + " '%u'," /* spell_id */ + " '%u'," /* caster_level */ + " '%u'," /* duration_formula */ + " '%u'," /* tics_remaining */ + " '%u'," /* poison_counters */ + " '%u'," /* disease_counters */ + " '%u'," /* curse_counters */ + " '%u'," /* corruption_counters */ + " '%u'," /* numhits */ + " '%u'," /* melee_rune */ + " '%u'," /* magic_rune */ + " '%u'," /* dot_rune */ + " '%u'," /* persistent */ + " '%i'," /* caston_x */ + " '%i'," /* caston_y */ + " '%i'," /* caston_z */ + " '%i'" /* extra_di_chance */ + ")", + bot_inst->GetBotID(), + bot_buffs[buff_index].spellid, + bot_buffs[buff_index].casterlevel, + spells[bot_buffs[buff_index].spellid].buffdurationformula, + bot_buffs[buff_index].ticsremaining, + ((CalculatePoisonCounters(bot_buffs[buff_index].spellid) > 0) ? (bot_buffs[buff_index].counters) : (0)), + ((CalculateDiseaseCounters(bot_buffs[buff_index].spellid) > 0) ? (bot_buffs[buff_index].counters) : (0)), + ((CalculateCurseCounters(bot_buffs[buff_index].spellid) > 0) ? (bot_buffs[buff_index].counters) : (0)), + ((CalculateCorruptionCounters(bot_buffs[buff_index].spellid) > 0) ? (bot_buffs[buff_index].counters) : (0)), + bot_buffs[buff_index].numhits, + bot_buffs[buff_index].melee_rune, + bot_buffs[buff_index].magic_rune, + bot_buffs[buff_index].dot_rune, + ((bot_buffs[buff_index].persistant_buff) ? (1) : (0)), + bot_buffs[buff_index].caston_x, + bot_buffs[buff_index].caston_y, + bot_buffs[buff_index].caston_z, + bot_buffs[buff_index].ExtraDIChance + ); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeleteBuffs(bot_inst->GetBotID()); + return false; + } + } + + return true; +} + +bool BotDatabase::DeleteBuffs(const uint32 bot_id) +{ + if (!bot_id) + return false; + + query = StringFormat("DELETE FROM `bot_buffs` WHERE `bot_id` = '%u'", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::LoadStance(const uint32 bot_id, BotStanceType& bot_stance) +{ + if (!bot_id) + return false; + + query = StringFormat("SELECT `stance_id` FROM `bot_stances` WHERE `bot_id` = '%u' LIMIT 1", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + bot_stance = (BotStanceType)atoi(row[0]); + + return true; +} + +bool BotDatabase::LoadStance(Bot* bot_inst, bool& stance_flag) +{ + if (!bot_inst) + return false; + + bot_inst->SetDefaultBotStance(); + + query = StringFormat("SELECT `stance_id` FROM `bot_stances` WHERE `bot_id` = '%u' LIMIT 1", bot_inst->GetBotID()); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + bot_inst->SetBotStance((BotStanceType)atoi(row[0])); + stance_flag = true; + + return true; +} + +bool BotDatabase::SaveStance(const uint32 bot_id, const BotStanceType bot_stance) +{ + if (!bot_id) + return false; + + if (!DeleteStance(bot_id)) + return false; + + query = StringFormat("INSERT INTO `bot_stances` (`bot_id`, `stance_id`) VALUES ('%u', '%u')", bot_id, bot_stance); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeleteStance(bot_id); + return false; + } + + return true; +} + +bool BotDatabase::SaveStance(Bot* bot_inst) +{ + if (!bot_inst) + return false; + + if (!DeleteStance(bot_inst->GetBotID())) + return false; + + query = StringFormat("INSERT INTO `bot_stances` (`bot_id`, `stance_id`) VALUES ('%u', '%u')", bot_inst->GetBotID(), bot_inst->GetBotStance()); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeleteStance(bot_inst->GetBotID()); + return false; + } + + return true; +} + +bool BotDatabase::DeleteStance(const uint32 bot_id) +{ + if (!bot_id) + return false; + + query = StringFormat("DELETE FROM `bot_stances` WHERE `bot_id` = '%u'", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::LoadTimers(Bot* bot_inst) +{ + if (!bot_inst) + return false; + + query = StringFormat( + "SELECT" + " IfNull(bt.`timer_id`, '0') As timer_id," + " IfNull(bt.`timer_value`, '0') As timer_value," + " IfNull(MAX(sn.`recast_time`), '0') AS MaxTimer" + " FROM `bot_timers` bt, `spells_new` sn" + " WHERE bt.`bot_id` = '%u' AND sn.`EndurTimerIndex` = (" + "SELECT case" + " WHEN timer_id > '%i' THEN timer_id - '%i'" + " ELSE timer_id END AS timer_id" + " FROM `bot_timers` WHERE `timer_id` = bt.`timer_id` AND `bot_id` = bt.`bot_id`" // double-check validity + ")" + " AND sn.`classes%i` <= '%i'", + bot_inst->GetBotID(), + (DisciplineReuseStart - 1), + (DisciplineReuseStart - 1), + bot_inst->GetClass(), + bot_inst->GetLevel() + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + uint32* bot_timers = bot_inst->GetTimers(); + if (!bot_timers) + return false; + + int timer_id = 0; + uint32 timer_value = 0; + uint32 max_value = 0; + for (auto row = results.begin(); row != results.end(); ++row) { + timer_id = atoi(row[0]) - 1; + timer_value = atoi(row[1]); + max_value = atoi(row[2]); + + if (timer_id >= 0 && timer_id < MaxTimer && timer_value < (Timer::GetCurrentTime() + max_value)) + bot_timers[timer_id] = timer_value; + } + + return true; +} + +bool BotDatabase::SaveTimers(Bot* bot_inst) +{ + if (!bot_inst) + return false; + + if (!DeleteTimers(bot_inst->GetBotID())) + return false; + + uint32* bot_timers = bot_inst->GetTimers(); + if (!bot_timers) + return false; + + for (int timer_index = 0; timer_index < MaxTimer; ++timer_index) { + if (bot_timers[timer_index] <= Timer::GetCurrentTime()) + continue; + + query = StringFormat("INSERT INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) VALUES ('%u', '%u', '%u')", bot_inst->GetBotID(), (timer_index + 1), bot_timers[timer_index]); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeleteTimers(bot_inst->GetBotID()); + return false; + } + } + + return true; +} + +bool BotDatabase::DeleteTimers(const uint32 bot_id) +{ + if (!bot_id) + return false; + + query = StringFormat("DELETE FROM `bot_timers` WHERE `bot_id` = '%u'", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::LoadGuildMembership(const uint32 bot_id, uint32& guild_id, uint8& guild_rank, std::string& guild_name) +{ + if (!bot_id) + return false; + + query = StringFormat( + "SELECT" + " gm.`guild_id`," + " gm.`rank`," + " g.`name`" + " FROM `vw_guild_members` AS gm" + " JOIN `guilds` AS g" + " ON gm.`guild_id` = g.`id`" + " WHERE gm.`char_id` = '%u'" + " AND gm.`mob_type` = 'B'" + " LIMIT 1", + bot_id + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + guild_id = atoi(row[0]); + guild_rank = atoi(row[1]); + guild_name = row[2]; + + return true; +} + +bool BotDatabase::SaveGuildMembership(const uint32 bot_id, const uint32 guild_id, const uint8 guild_rank) +{ + if (!bot_id || !guild_id) + return false; + + if (!DeleteGuildMembership(bot_id)) + return false; + + query = StringFormat("INSERT INTO `bot_guild_members` SET `bot_id` = '%u', `guild_id` = '%u', `rank` = '%u'", bot_id, guild_id, guild_rank); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeleteGuildMembership(bot_id); + return false; + } + + return true; +} + +bool BotDatabase::DeleteGuildMembership(const uint32 bot_id) +{ + if (!bot_id) + return false; + + query = StringFormat("DELETE FROM `bot_guild_members` WHERE `bot_id` = '%u'", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + + +/* Bot inventory functions */ +bool BotDatabase::QueryInventoryCount(const uint32 bot_id, uint32& item_count) +{ + if (!bot_id) + return false; + + query = StringFormat("SELECT COUNT(`inventories_index`) FROM `bot_inventories` WHERE `bot_id` = '%u'", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + item_count = atoi(row[0]); + + return true; +} + +bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) +{ + if (!bot_id) + return false; + + query = StringFormat( + "SELECT" + " `slot_id`," + " `item_id`," + " `inst_charges`," + " `inst_color`," + " `inst_no_drop`," + " `inst_custom_data`," + " `ornament_icon`," + " `ornament_id_file`," + " `ornament_hero_model`," + " `augment_1`," + " `augment_2`," + " `augment_3`," + " `augment_4`, " + " `augment_5`," + " `augment_6`" + " FROM `bot_inventories`" + " WHERE `bot_id` = '%i'" + " ORDER BY `slot_id`", + bot_id + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + for (auto row = results.begin(); row != results.end(); ++row) { + int16 slot_id = atoi(row[0]); + if ((slot_id < EmuConstants::EQUIPMENT_BEGIN || slot_id > EmuConstants::EQUIPMENT_END) && slot_id != MainPowerSource) + continue; + + uint32 item_id = atoi(row[1]); + uint16 item_charges = (uint16)atoi(row[2]); + + ItemInst* item_inst = database.CreateItem( + item_id, + item_charges, + (uint32)atoul(row[9]), + (uint32)atoul(row[10]), + (uint32)atoul(row[11]), + (uint32)atoul(row[12]), + (uint32)atoul(row[13]), + (uint32)atoul(row[14]) + ); + if (!item_inst) { + Log.Out(Logs::General, Logs::Error, "Warning: bot_id '%i' has an invalid item_id '%i' in inventory slot '%i'", bot_id, item_id, slot_id); + continue; + } + + if (item_charges == 255) + item_inst->SetCharges(-1); + else + item_inst->SetCharges(item_charges); + + uint32 item_color = atoul(row[3]); + if (item_color > 0) + item_inst->SetColor(item_color); + + if (item_inst->GetItem()->Attuneable) { + if (atoi(row[4])) + item_inst->SetAttuned(true); + else if (((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || slot_id == 9999)) + item_inst->SetAttuned(true); + } + + if (row[5]) { + std::string data_str(row[5]); + std::string idAsString; + std::string value; + bool use_id = true; + + for (int i = 0; i < data_str.length(); ++i) { + if (data_str[i] == '^') { + if (!use_id) { + item_inst->SetCustomData(idAsString, value); + idAsString.clear(); + value.clear(); + } + + use_id = !use_id; + continue; + } + + char v = data_str[i]; + if (use_id) + idAsString.push_back(v); + else + value.push_back(v); + } + } + + item_inst->SetOrnamentIcon((uint32)atoul(row[6])); + item_inst->SetOrnamentationIDFile((uint32)atoul(row[7])); + item_inst->SetOrnamentHeroModel((uint32)atoul(row[8])); + + if (inventory_inst.PutItem(slot_id, *item_inst) == INVALID_INDEX) + Log.Out(Logs::General, Logs::Error, "Warning: Invalid slot_id for item in inventory: bot_id = '%i', item_id = '%i', slot_id = '%i'", bot_id, item_id, slot_id); + + safe_delete(item_inst); + } + + return true; +} + +bool BotDatabase::SaveItems(Bot* bot_inst) +{ + return false; +} + +bool BotDatabase::DeleteItems(const uint32 bot_id) +{ + if (!bot_id) + return false; + + query = StringFormat("DELETE FROM `bot_inventories` WHERE `bot_id` = '%u'", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::LoadItemBySlot(Bot* bot_inst) +{ + return false; +} + +bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint32& item_id) +{ + if (!bot_id || (slot_id > EmuConstants::EQUIPMENT_END && slot_id != MainPowerSource)) + return false; + + query = StringFormat("SELECT `item_id` FROM `bot_inventories` WHERE `bot_id` = '%i' AND `slot_id` = '%i' LIMIT 1", bot_id, slot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + item_id = atoi(row[0]); + + return true; +} + +bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const ItemInst* item_inst) +{ + if (!bot_inst || !bot_inst->GetBotID() || (slot_id > EmuConstants::EQUIPMENT_END && slot_id != MainPowerSource)) + return false; + + if (!DeleteItemBySlot(bot_inst->GetBotID(), slot_id)) + return false; + + if (!item_inst || !item_inst->GetID()) + return true; + + uint32 augment_id[] = { 0, 0, 0, 0, 0, 0 }; + for (int augment_iter = 0; augment_iter < EmuConstants::ITEM_COMMON_SIZE; ++augment_iter) + augment_id[augment_iter] = item_inst->GetAugmentItemID(augment_iter); + + query = StringFormat( + "INSERT INTO `bot_inventories` (" + "`bot_id`," + " `slot_id`," + " `item_id`," + " `inst_charges`," + " `inst_color`," + " `inst_no_drop`," + " `inst_custom_data`," + " `ornament_icon`," + " `ornament_id_file`," + " `ornament_hero_model`," + " `augment_1`," + " `augment_2`," + " `augment_3`," + " `augment_4`," + " `augment_5`," + " `augment_6`" + ")" + " VALUES (" + "'%lu'," /* bot_id */ + " '%lu'," /* slot_id */ + " '%lu'," /* item_id */ + " '%lu'," /* inst_charges */ + " '%lu'," /* inst_color */ + " '%lu'," /* inst_no_drop */ + " '%s'," /* inst_custom_data */ + " '%lu'," /* ornament_icon */ + " '%lu'," /* ornament_id_file */ + " '%lu'," /* ornament_hero_model */ + " '%lu'," /* augment_1 */ + " '%lu'," /* augment_2 */ + " '%lu'," /* augment_3 */ + " '%lu'," /* augment_4 */ + " '%lu'," /* augment_5 */ + " '%lu'" /* augment_6 */ + ")", + (unsigned long)bot_inst->GetBotID(), + (unsigned long)slot_id, + (unsigned long)item_inst->GetID(), + (unsigned long)item_inst->GetCharges(), + (unsigned long)item_inst->GetColor(), + (unsigned long)(item_inst->IsAttuned() ? 1 : 0), + item_inst->GetCustomDataString().c_str(), + (unsigned long)item_inst->GetOrnamentationIcon(), + (unsigned long)item_inst->GetOrnamentationIDFile(), + (unsigned long)item_inst->GetOrnamentHeroModel(), + (unsigned long)augment_id[0], + (unsigned long)augment_id[1], + (unsigned long)augment_id[2], + (unsigned long)augment_id[3], + (unsigned long)augment_id[4], + (unsigned long)augment_id[5] + ); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeleteItemBySlot(bot_inst->GetBotID(), slot_id); + return false; + } + + return true; +} + +bool BotDatabase::DeleteItemBySlot(const uint32 bot_id, const uint32 slot_id) +{ + if (!bot_id || (slot_id > EmuConstants::EQUIPMENT_END && slot_id != MainPowerSource)) + return false; + + query = StringFormat("DELETE FROM `bot_inventories` WHERE `bot_id` = '%u' AND `slot_id` = '%u'", bot_id, slot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::LoadEquipmentColor(const uint32 bot_id, const uint8 material_slot_id, uint32& rgb) +{ + if (!bot_id) + return false; + + int16 slot_id = Inventory::CalcSlotFromMaterial(material_slot_id); + if (slot_id == INVALID_INDEX) + return false; + + query = StringFormat("SELECT `inst_color` FROM `bot_inventories` WHERE `bot_id` = '%u' AND `slot_id` = '%u' LIMIT 1", bot_id, slot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + rgb = atoul(row[0]); + + return true; +} + +bool BotDatabase::SaveEquipmentColor(const uint32 bot_id, const int16 slot_id, const uint32 rgb) +{ + if (!bot_id) + return false; + + bool all_flag = (slot_id == -2); + if ((slot_id < EmuConstants::EQUIPMENT_BEGIN || slot_id > EmuConstants::EQUIPMENT_END) && slot_id != MainPowerSource && !all_flag) + return false; + + std::string where_clause; + if (all_flag) + where_clause = StringFormat(" AND `slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u')", MainHead, MainArms, MainWrist1, MainHands, MainChest, MainLegs, MainFeet); + else + where_clause = StringFormat(" AND `slot_id` = '%u'", slot_id); + + query = StringFormat( + "UPDATE `bot_inventories`" + " SET `inst_color` = '%u'" + " WHERE `bot_id` = '%u'" + " %s", + rgb, + where_clause.c_str(), + bot_id + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + + +/* Bot pet functions */ +bool BotDatabase::LoadPetIndex(const uint32 bot_id, uint32& pet_index) +{ + if (!bot_id) + return false; + + query = StringFormat("SELECT `pets_index` FROM `bot_pets` WHERE `bot_id` = '%u' LIMIT 1", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + pet_index = atoi(row[0]); + + return true; +} + +bool BotDatabase::LoadPetSpellID(const uint32 bot_id, uint32& pet_spell_id) +{ + if (!bot_id) + return false; + + query = StringFormat("SELECT `spell_id` FROM `bot_pets` WHERE `bot_id` = '%u' LIMIT 1", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + pet_spell_id = atoi(row[0]); + + return true; +} + +bool BotDatabase::LoadPetStats(const uint32 bot_id, std::string& pet_name, uint32& pet_mana, uint32& pet_hp, uint32& pet_spell_id) +{ + if (!bot_id) + return false; + + uint32 saved_pet_index = 0; + if (!LoadPetIndex(bot_id, saved_pet_index)) + return false; + if (!saved_pet_index) + return true; + + query = StringFormat("SELECT `spell_id`, `name`, `mana`, `hp` FROM `bot_pets` WHERE `pets_index` = '%u' LIMIT 1", saved_pet_index); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + pet_spell_id = atoi(row[0]); + pet_name = row[1]; + pet_mana = atoi(row[2]); + pet_hp = atoi(row[3]); + + return true; +} + +bool BotDatabase::SavePetStats(const uint32 bot_id, const std::string& pet_name, const uint32 pet_mana, const uint32 pet_hp, const uint32 pet_spell_id) +{ + if (!bot_id || pet_name.empty() || !pet_spell_id || pet_spell_id > SPDAT_RECORDS) + return false; + + if (!DeletePetItems(bot_id)) + return false; + if (!DeletePetBuffs(bot_id)) + return false; + if (!DeletePetStats(bot_id)) + return false; + + query = StringFormat( + "INSERT INTO `bot_pets` (" + "`spell_id`," + " `bot_id`," + " `name`," + " `mana`," + " `hp`" + ")" + " VALUES (" + "'%u'," + " '%u'," + " '%u'," + " '%u'," + " '%u'" + ")", + pet_spell_id, + bot_id, + pet_name.c_str(), + pet_mana, + pet_hp + ); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeletePetStats(bot_id); + return false; + } + + return true; +} + +bool BotDatabase::DeletePetStats(const uint32 bot_id) +{ + if (!bot_id) + return false; + + uint32 saved_pet_index = 0; + if (!LoadPetIndex(bot_id, saved_pet_index)) + return false; + if (!saved_pet_index) + return true; + + query = StringFormat("DELETE FROM `bot_pets` WHERE `pets_index` = '%u'", saved_pet_index); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::LoadPetBuffs(const uint32 bot_id, SpellBuff_Struct* pet_buffs) +{ + if (!bot_id) + return false; + + uint32 saved_pet_index = 0; + if (!LoadPetIndex(bot_id, saved_pet_index)) + return false; + if (!saved_pet_index) + return true; + + query = StringFormat("SELECT `spell_id`, `caster_level`, `duration` FROM `bot_pet_buffs` WHERE `pets_index` = '%u'", saved_pet_index); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + int buff_index = 0; + for (auto row = results.begin(); row != results.end() && buff_index < BUFF_COUNT; ++row) { + pet_buffs[buff_index].spellid = atoi(row[0]); + pet_buffs[buff_index].level = atoi(row[1]); + pet_buffs[buff_index].duration = atoi(row[2]); + + // Work around for loading the counters and setting them back to max. Need entry in DB for saved counters + if (CalculatePoisonCounters(pet_buffs[buff_index].spellid) > 0) + pet_buffs[buff_index].counters = CalculatePoisonCounters(pet_buffs[buff_index].spellid); + else if (CalculateDiseaseCounters(pet_buffs[buff_index].spellid) > 0) + pet_buffs[buff_index].counters = CalculateDiseaseCounters(pet_buffs[buff_index].spellid); + else if (CalculateCurseCounters(pet_buffs[buff_index].spellid) > 0) + pet_buffs[buff_index].counters = CalculateCurseCounters(pet_buffs[buff_index].spellid); + else if (CalculateCorruptionCounters(pet_buffs[buff_index].spellid) > 0) + pet_buffs[buff_index].counters = CalculateCorruptionCounters(pet_buffs[buff_index].spellid); + + ++buff_index; + } + + return true; +} + +bool BotDatabase::SavePetBuffs(const uint32 bot_id, const SpellBuff_Struct* pet_buffs, bool delete_flag) +{ + // Only use 'delete_flag' if not invoked after a botdb.SavePetStats() call + + if (!bot_id || !pet_buffs) + return false; + + if (delete_flag && !DeletePetBuffs(bot_id)) + return false; + + uint32 saved_pet_index = 0; + if (!LoadPetIndex(bot_id, saved_pet_index)) + return false; + if (!saved_pet_index) + return true; + + for (int buff_index = 0; buff_index < BUFF_COUNT; ++buff_index) { + if (!pet_buffs[buff_index].spellid || pet_buffs[buff_index].spellid == SPELL_UNKNOWN) + continue; + + query = StringFormat( + "INSERT INTO `bot_pet_buffs` (" + "`pets_index`," + " `spell_id`," + " `caster_level`," + " `duration`" + ")" + " VALUES (" + "'%u'," + " '%u'," + " '%u'," + " '%u'" + ")", + saved_pet_index, + pet_buffs[buff_index].spellid, + pet_buffs[buff_index].level, + pet_buffs[buff_index].duration + ); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeletePetBuffs(bot_id); + return false; + } + } + + return true; +} + +bool BotDatabase::DeletePetBuffs(const uint32 bot_id) +{ + if (!bot_id) + return false; + + uint32 saved_pet_index = 0; + if (!LoadPetIndex(bot_id, saved_pet_index)) + return false; + if (!saved_pet_index) + return true; + + query = StringFormat("DELETE FROM `bot_pet_buffs` WHERE `pets_index` = '%u'", saved_pet_index); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::LoadPetItems(const uint32 bot_id, uint32* pet_items) +{ + if (!bot_id || !pet_items) + return false; + + uint32 saved_pet_index = 0; + if (!LoadPetIndex(bot_id, saved_pet_index)) + return false; + if (!saved_pet_index) + return true; + + query = StringFormat("SELECT `item_id` FROM `bot_pet_inventories` WHERE `pets_index` = '%u'", saved_pet_index); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + int item_index = 0; + for (auto row = results.begin(); row != results.end() && item_index < EmuConstants::EQUIPMENT_SIZE; ++row) { + pet_items[item_index] = atoi(row[0]); + ++item_index; + } + + return true; +} + +bool BotDatabase::SavePetItems(const uint32 bot_id, const uint32* pet_items, bool delete_flag) +{ + // Only use 'delete_flag' if not invoked after a botdb.SavePetStats() call + + if (!bot_id || !pet_items) + return false; + + if (delete_flag && !DeletePetItems(bot_id)) + return false; + + uint32 saved_pet_index = 0; + if (!LoadPetIndex(bot_id, saved_pet_index)) + return false; + if (!saved_pet_index) + return true; + + for (int item_index = 0; item_index < EmuConstants::EQUIPMENT_SIZE; ++item_index) { + if (!pet_items[item_index]) + continue; + + query = StringFormat("INSERT INTO `bot_pet_inventories` (`pets_index`, `item_id`) VALUES ('%u', '%u')", saved_pet_index, pet_items[item_index]); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeletePetItems(bot_id); + return false; + } + } + + return true; +} + +bool BotDatabase::DeletePetItems(const uint32 bot_id) +{ + if (!bot_id) + return false; + + uint32 saved_pet_index = 0; + if (!LoadPetIndex(bot_id, saved_pet_index)) + return false; + if (!saved_pet_index) + return true; + + query = StringFormat("DELETE FROM `bot_pet_inventories` WHERE `pets_index` = '%u'", saved_pet_index); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + + +/* Bot command functions */ +bool BotDatabase::LoadInspectMessage(const uint32 bot_id, InspectMessage_Struct& inspect_message) +{ + if (!bot_id) + return false; + + query = StringFormat("SELECT `inspect_message` FROM `bot_inspect_messages` WHERE `bot_id` = '%u' LIMIT 1", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + std::string bot_message = row[0]; + if (bot_message.size() > 255) + bot_message = bot_message.substr(0, 255); + if (bot_message.empty()) + return true; + + memcpy(inspect_message.text, bot_message.c_str(), bot_message.size()); + + return true; +} + +bool BotDatabase::SaveInspectMessage(const uint32 bot_id, const InspectMessage_Struct& inspect_message) +{ + if (!bot_id) + return false; + + if (!DeleteInspectMessage(bot_id)) + return false; + + std::string bot_message = inspect_message.text; + if (bot_message.size() > 255) + bot_message = bot_message.substr(0, 255); + if (bot_message.empty()) + return true; + + query = StringFormat("INSERT INTO `bot_inspect_messages` (`bot_id`, `inspect_message`) VALUES ('%u', '%s')", bot_id, bot_message.c_str()); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeleteInspectMessage(bot_id); + return false; + } + + return true; +} + +bool BotDatabase::DeleteInspectMessage(const uint32 bot_id) +{ + if (!bot_id) + return false; + + query = StringFormat("DELETE FROM `bot_inspect_messages` WHERE `bot_id` = '%u'", bot_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::SaveAllInspectMessages(const uint32 owner_id, const InspectMessage_Struct& inspect_message) { if (!owner_id) return false; - std::string query = StringFormat( + if (!DeleteAllInspectMessages(owner_id)) + return false; + + std::string bot_message = inspect_message.text; + if (bot_message.size() > 255) + bot_message = bot_message.substr(0, 255); + if (bot_message.empty()) + return true; + + query = StringFormat("INSERT INTO `bot_inspect_messages` (`bot_id`, `inspect_message`) SELECT `bot_id`, '%s' inspect_message FROM `bot_data` WHERE `owner_id` = '%u'", bot_message.c_str(), owner_id); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeleteAllInspectMessages(owner_id); + return false; + } + + return true; +} + +bool BotDatabase::DeleteAllInspectMessages(const uint32 owner_id) +{ + if (!owner_id) + return false; + + query = StringFormat("DELETE FROM `bot_inspect_messages` WHERE `bot_id` IN (SELECT `bot_id` FROM `bot_data` WHERE `owner_id` = '%u')", owner_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::SaveAllArmorColorBySlot(const uint32 owner_id, const int16 slot_id, const uint32 rgb_value) +{ + if (!owner_id) + return false; + + query = StringFormat( "UPDATE `bot_inventories` bi" " INNER JOIN `bot_data` bd" " ON bd.`owner_id` = '%u'" " SET bi.`inst_color` = '%u'" " WHERE bi.`bot_id` = bd.`bot_id`" - " AND bi.`slot_id` IN (%u, %u, %u, %u, %u, %u, %u, %u)" + " AND bi.`slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')" " AND bi.`slot_id` = '%i'", owner_id, rgb_value, @@ -140,37 +1748,41 @@ bool BotDatabase::SetAllArmorColorBySlot(uint32 owner_id, int16 slot_id, uint32 slot_id ); auto results = QueryDatabase(query); + if (!results.Success()) + return false; - return results.Success(); + return true; } -bool BotDatabase::SetAllArmorColors(uint32 owner_id, uint32 rgb_value) +bool BotDatabase::SaveAllArmorColors(const uint32 owner_id, const uint32 rgb_value) { if (!owner_id) return false; - std::string query = StringFormat( + query = StringFormat( "UPDATE `bot_inventories` bi" " INNER JOIN `bot_data` bd" " ON bd.`owner_id` = '%u'" " SET bi.`inst_color` = '%u'" " WHERE bi.`bot_id` = bd.`bot_id`" - " AND bi.`slot_id` IN (%u, %u, %u, %u, %u, %u, %u, %u)", + " AND bi.`slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", owner_id, rgb_value, MainHead, MainChest, MainArms, MainWrist1, MainWrist2, MainHands, MainLegs, MainFeet ); auto results = QueryDatabase(query); + if (!results.Success()) + return false; - return results.Success(); + return true; } -bool BotDatabase::SetHelmAppearance(uint32 owner_id, uint32 bot_id, bool show_flag) +bool BotDatabase::SaveHelmAppearance(const uint32 owner_id, const uint32 bot_id, const bool show_flag) { if (!owner_id || !bot_id) return false; - std::string query = StringFormat( + query = StringFormat( "UPDATE `bot_data`" " SET `show_helm` = '%u'" " WHERE `owner_id` = '%u'" @@ -180,16 +1792,18 @@ bool BotDatabase::SetHelmAppearance(uint32 owner_id, uint32 bot_id, bool show_fl bot_id ); auto results = QueryDatabase(query); + if (!results.Success()) + return false; - return results.Success(); + return true; } -bool BotDatabase::SetAllHelmAppearances(uint32 owner_id, bool show_flag) +bool BotDatabase::SaveAllHelmAppearances(const uint32 owner_id, const bool show_flag) { if (!owner_id) return false; - std::string query = StringFormat( + query = StringFormat( "UPDATE `bot_data`" " SET `show_helm` = '%u'" " WHERE `owner_id` = '%u'", @@ -197,16 +1811,18 @@ bool BotDatabase::SetAllHelmAppearances(uint32 owner_id, bool show_flag) owner_id ); auto results = QueryDatabase(query); + if (!results.Success()) + return false; - return results.Success(); + return true; } -bool BotDatabase::ToggleHelmAppearance(uint32 owner_id, uint32 bot_id) +bool BotDatabase::ToggleHelmAppearance(const uint32 owner_id, const uint32 bot_id) { if (!owner_id || !bot_id) return false; - std::string query = StringFormat( + query = StringFormat( "UPDATE `bot_data`" " SET `show_helm` = (`show_helm` XOR '1')" " WHERE `owner_id` = '%u'" @@ -215,32 +1831,36 @@ bool BotDatabase::ToggleHelmAppearance(uint32 owner_id, uint32 bot_id) bot_id ); auto results = QueryDatabase(query); + if (!results.Success()) + return false; - return results.Success(); + return true; } -bool BotDatabase::ToggleAllHelmAppearances(uint32 owner_id) +bool BotDatabase::ToggleAllHelmAppearances(const uint32 owner_id) { if (!owner_id) return false; - std::string query = StringFormat( + query = StringFormat( "UPDATE `bot_data`" " SET `show_helm` = (`show_helm` XOR '1')" " WHERE `owner_id` = '%u'", owner_id ); auto results = QueryDatabase(query); + if (!results.Success()) + return false; - return results.Success(); + return true; } -bool BotDatabase::SetFollowDistance(uint32 owner_id, uint32 bot_id, uint32 follow_distance) +bool BotDatabase::SaveFollowDistance(const uint32 owner_id, const uint32 bot_id, const uint32 follow_distance) { if (!owner_id || !bot_id || !follow_distance) return false; - std::string query = StringFormat( + query = StringFormat( "UPDATE `bot_data`" " SET `follow_distance` = '%u'" " WHERE `owner_id` = '%u'" @@ -250,16 +1870,18 @@ bool BotDatabase::SetFollowDistance(uint32 owner_id, uint32 bot_id, uint32 follo bot_id ); auto results = QueryDatabase(query); + if (!results.Success()) + return false; - return results.Success(); + return true; } -bool BotDatabase::SetAllFollowDistances(uint32 owner_id, uint32 follow_distance) +bool BotDatabase::SaveAllFollowDistances(const uint32 owner_id, const uint32 follow_distance) { if (!owner_id || !follow_distance) return false; - std::string query = StringFormat( + query = StringFormat( "UPDATE `bot_data`" " SET `follow_distance` = '%u'" " WHERE `owner_id` = '%u'", @@ -267,16 +1889,18 @@ bool BotDatabase::SetAllFollowDistances(uint32 owner_id, uint32 follow_distance) owner_id ); auto results = QueryDatabase(query); + if (!results.Success()) + return false; - return results.Success(); + return true; } -uint32 BotDatabase::Clone(uint32 owner_id, uint32 bot_id, const char* clone_name) +bool BotDatabase::CreateCloneBot(const uint32 owner_id, const uint32 bot_id, const std::string& clone_name, uint32& clone_id) { - if (!owner_id || !bot_id || !clone_name) - return 0; + if (!owner_id || !bot_id || clone_name.empty()) + return false; - std::string data_query = StringFormat( + query = StringFormat( "INSERT INTO `bot_data`" " (" "`owner_id`," @@ -376,23 +2000,25 @@ uint32 BotDatabase::Clone(uint32 owner_id, uint32 bot_id, const char* clone_name " bd.`owner_id` = '%u'" " AND" " bd.`bot_id` = '%u'", - clone_name, + clone_name.c_str(), owner_id, bot_id ); - auto results = QueryDatabase(data_query); + auto results = QueryDatabase(query); if (!results.Success()) - return 0; + return false; - return results.LastInsertedID(); + clone_id = results.LastInsertedID(); + + return true; } -bool BotDatabase::CloneInventory(uint32 owner_id, uint32 bot_id, uint32 clone_id) +bool BotDatabase::CreateCloneBotInventory(const uint32 owner_id, const uint32 bot_id, const uint32 clone_id) { if (!owner_id || !bot_id || !clone_id) return false; - std::string inv_query = StringFormat( + query = StringFormat( "INSERT INTO `bot_inventories`" " (" "bot_id," @@ -439,297 +2065,436 @@ bool BotDatabase::CloneInventory(uint32 owner_id, uint32 bot_id, uint32 clone_id owner_id, bot_id ); - auto results = QueryDatabase(inv_query); + auto results = QueryDatabase(query); + if (!results.Success()) { + DeleteItems(clone_id); + return false; + } - return results.Success(); + return true; } -// Bot-group functions -bool BotDatabase::DoesBotGroupExist(std::string& group_name) +/* Bot bot-group functions */ +bool BotDatabase::QueryBotGroupExistence(const std::string& group_name, bool& extant_flag) { if (group_name.empty()) return false; - std::string query = StringFormat("SELECT `group_name` FROM `vw_bot_groups` WHERE `group_name` LIKE '%s' LIMIT 1", group_name.c_str()); + query = StringFormat("SELECT `group_name` FROM `vw_bot_groups` WHERE `group_name` LIKE '%s' LIMIT 1", group_name.c_str()); auto results = QueryDatabase(query); - if (!results.Success() || results.RowCount() == 0) + if (!results.Success()) return false; - - auto row = results.begin(); - if (!group_name.compare(row[0])) + if (!results.RowCount()) return true; + + extant_flag = true; + + return true; +} + +bool BotDatabase::LoadBotGroupIDByBotGroupName(const std::string& group_name, uint32& botgroup_id) +{ + if (group_name.empty()) + return false; + + query = StringFormat("SELECT `groups_index` FROM `bot_groups` WHERE `group_name` = '%s' LIMIT 1", group_name.c_str()); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + botgroup_id = atoi(row[0]); + + return true; +} + +bool BotDatabase::LoadBotGroupIDByLeaderID(const uint32 leader_id, uint32& botgroup_id) +{ + if (!leader_id) + return false; + + query = StringFormat("SELECT `groups_index` FROM `bot_groups` WHERE `group_leader_id` = '%u' LIMIT 1", leader_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + botgroup_id = atoi(row[0]); - return false; + return true; } -uint32 BotDatabase::GetGroupIDByGroupName(std::string& group_name, std::string& error_message) -{ - if (group_name.empty()) - return 0; - - std::string query = StringFormat("SELECT `groups_index` FROM `bot_groups` WHERE `group_name` = '%s'", group_name.c_str()); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - error_message = results.ErrorMessage(); - return 0; - } - auto row = results.begin(); - - return atoi(row[0]); -} - -uint32 BotDatabase::GetLeaderIDByGroupName(std::string& group_name, std::string& error_message) -{ - if (group_name.empty()) - return 0; - - std::string query = StringFormat("SELECT `group_leader_id` FROM `bot_groups` WHERE `group_name` = '%s'", group_name.c_str()); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - error_message = results.ErrorMessage(); - return 0; - } - auto row = results.begin(); - - return atoi(row[0]); -} - -std::string BotDatabase::GetGroupNameByGroupID(uint32 group_id, std::string& error_message) -{ - if (!group_id) - return std::string(); - - std::string query = StringFormat("SELECT `group_name` FROM `bot_groups` WHERE `groups_index` = '%u'", group_id); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - error_message = results.ErrorMessage(); - return std::string(); - } - auto row = results.begin(); - - return std::string(row[0]); -} - -std::string BotDatabase::GetGroupNameByLeaderID(uint32 leader_id, std::string& error_message) -{ - if (!leader_id) - return std::string(); - - std::string query = StringFormat("SELECT `group_name` FROM `bot_groups` WHERE `group_leader_id` = '%u'", leader_id); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - error_message = results.ErrorMessage(); - return std::string(); - } - auto row = results.begin(); - - return std::string(row[0]); -} - -uint32 BotDatabase::GetGroupIDByLeaderID(uint32 leader_id, std::string& error_message) -{ - if (!leader_id) - return 0; - - std::string query = StringFormat("SELECT `groups_index` FROM `bot_groups` WHERE `group_leader_id` = '%u'", leader_id); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - error_message = results.ErrorMessage(); - return 0; - } - auto row = results.begin(); - - return atoi(row[0]); -} - -uint32 BotDatabase::GetLeaderIDByGroupID(uint32 group_id, std::string& error_message) -{ - if (!group_id) - return 0; - - std::string query = StringFormat("SELECT `group_leader_id` FROM `bot_groups` WHERE `groups_index` = '%u'", group_id); - auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - error_message = results.ErrorMessage(); - return 0; - } - auto row = results.begin(); - - return atoi(row[0]); -} - -uint32 BotDatabase::GetGroupIDByMemberID(uint32 member_id, std::string& error_message) +bool BotDatabase::LoadBotGroupIDByMemberID(const uint32 member_id, uint32& botgroup_id) { if (!member_id) - return 0; + return false; - std::string query = StringFormat("SELECT `groups_index` FROM `bot_group_members` WHERE `bot_id` = '%u'", member_id); + query = StringFormat("SELECT `groups_index` FROM `bot_group_members` WHERE `bot_id` = '%u' LIMIT 1", member_id); auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - error_message = results.ErrorMessage(); - return 0; - } - auto row = results.begin(); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; - return atoi(row[0]); + auto row = results.begin(); + botgroup_id = atoi(row[0]); + + return true; } -bool BotDatabase::CreateBotGroup(std::string& group_name, uint32 leader_id, std::string& error_message) +bool BotDatabase::LoadLeaderIDByBotGroupName(const std::string& group_name, uint32& leader_id) +{ + if (group_name.empty()) + return false; + + query = StringFormat("SELECT `group_leader_id` FROM `bot_groups` WHERE `group_name` = '%s' LIMIT 1", group_name.c_str()); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + leader_id = atoi(row[0]); + + return true; +} + +bool BotDatabase::LoadLeaderIDByBotGroupID(const uint32 group_id, uint32& leader_id) +{ + if (!group_id) + return false; + + query = StringFormat("SELECT `group_leader_id` FROM `bot_groups` WHERE `groups_index` = '%u' LIMIT 1", group_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + leader_id = atoi(row[0]); + + return true; +} + +bool BotDatabase::LoadBotGroupNameByBotGroupID(const uint32 group_id, std::string& botgroup_name) +{ + if (!group_id) + false; + + query = StringFormat("SELECT `group_name` FROM `bot_groups` WHERE `groups_index` = '%u' LIMIT 1", group_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + botgroup_name = row[0]; + + return true; +} + +bool BotDatabase::LoadBotGroupNameByLeaderID(const uint32 leader_id, std::string& botgroup_name) +{ + if (!leader_id) + return false; + + query = StringFormat("SELECT `group_name` FROM `bot_groups` WHERE `group_leader_id` = '%u' LIMIT 1", leader_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + botgroup_name = row[0]; + + return true; +} + +bool BotDatabase::CreateBotGroup(const std::string& group_name, const uint32 leader_id) { if (group_name.empty() || !leader_id) return false; - if (DoesBotGroupExist(group_name)) + bool extant_flag = false; + if (!QueryBotGroupExistence(group_name, extant_flag)) return false; + if (extant_flag) + return true; - std::string query = StringFormat("INSERT INTO `bot_groups` (`group_leader_id`, `group_name`) VALUES ('%u', '%s')", leader_id, group_name.c_str()); + query = StringFormat("INSERT INTO `bot_groups` (`group_leader_id`, `group_name`) VALUES ('%u', '%s')", leader_id, group_name.c_str()); auto results = QueryDatabase(query); if (!results.Success()) { - error_message = results.ErrorMessage(); + DeleteBotGroup(leader_id); return false; } - auto group_id = results.LastInsertedID(); - if (!group_id) + auto botgroup_id = results.LastInsertedID(); + if (!botgroup_id) { + DeleteBotGroup(leader_id); return false; + } - query = StringFormat("INSERT INTO `bot_group_members` (`groups_index`, `bot_id`) VALUES ('%u', '%u')", group_id, leader_id); + query = StringFormat("INSERT INTO `bot_group_members` (`groups_index`, `bot_id`) VALUES ('%u', '%u')", botgroup_id, leader_id); results = QueryDatabase(query); if (!results.Success()) { - error_message = results.ErrorMessage(); + RemoveMemberFromBotGroup(leader_id); return false; } return true; } -bool BotDatabase::DeleteBotGroup(uint32 leader_id, std::string& error_message) +bool BotDatabase::DeleteBotGroup(const uint32 leader_id) { if (!leader_id) return false; - uint32 group_id = GetGroupIDByLeaderID(leader_id, error_message); - if (!group_id || !error_message.empty()) + uint32 botgroup_id = 0; + if (!LoadBotGroupIDByLeaderID(leader_id, botgroup_id)) return false; + if (!botgroup_id) + return true; - std::string query = StringFormat("DELETE FROM `bot_group_members` WHERE `groups_index` = '%u'", group_id); + query = StringFormat("DELETE FROM `bot_group_members` WHERE `groups_index` = '%u'", botgroup_id); auto results = QueryDatabase(query); - if (!results.Success()) { - error_message = results.ErrorMessage(); + if (!results.Success()) return false; - } - query = StringFormat("DELETE FROM `bot_groups` WHERE `groups_index` = '%u'", group_id); + query = StringFormat("DELETE FROM `bot_groups` WHERE `groups_index` = '%u'", botgroup_id); results = QueryDatabase(query); - if (!results.Success()) { - error_message = results.ErrorMessage(); + if (!results.Success()) return false; - } return true; } -bool BotDatabase::AddMemberToBotGroup(uint32 leader_id, uint32 member_id, std::string& error_message) +bool BotDatabase::AddMemberToBotGroup(const uint32 leader_id, const uint32 member_id) { if (!leader_id || !member_id) return false; - uint32 group_id = GetGroupIDByLeaderID(leader_id, error_message); - if (!group_id || !error_message.empty()) + uint32 botgroup_id = 0; + if (!LoadBotGroupIDByLeaderID(leader_id, botgroup_id)) return false; + if (!botgroup_id) + return true; - std::string query = StringFormat("INSERT INTO `bot_group_members` (`groups_index`, `bot_id`) VALUES ('%u', '%u')", group_id, member_id); + query = StringFormat("INSERT INTO `bot_group_members` (`groups_index`, `bot_id`) VALUES ('%u', '%u')", botgroup_id, member_id); auto results = QueryDatabase(query); if (!results.Success()) { - error_message = results.ErrorMessage(); + RemoveMemberFromBotGroup(member_id); return false; } return true; } -bool BotDatabase::RemoveMemberFromBotGroup(uint32 member_id, std::string& error_message) +bool BotDatabase::RemoveMemberFromBotGroup(const uint32 member_id) { if (!member_id) return false; - if (GetGroupIDByLeaderID(member_id, error_message)) - return DeleteBotGroup(member_id, error_message); - - if (!error_message.empty()) + uint32 botgroup_id = 0; + if (!LoadBotGroupIDByLeaderID(member_id, botgroup_id)) return false; + if (botgroup_id) + return DeleteBotGroup(member_id); - std::string query = StringFormat("DELETE FROM `bot_group_members` WHERE `bot_id` = '%u'", member_id); + query = StringFormat("DELETE FROM `bot_group_members` WHERE `bot_id` = '%u'", member_id); auto results = QueryDatabase(query); - if (!results.Success()) { - error_message = results.ErrorMessage(); + if (!results.Success()) return false; - } return true; } -uint32 BotDatabase::GetGroupIDForLoadGroup(uint32 owner_id, std::string& group_name, std::string& error_message) +bool BotDatabase::LoadBotGroupIDForLoadBotGroup(const uint32 owner_id, const std::string& group_name, uint32& botgroup_id) { if (!owner_id || group_name.empty()) - return 0; + return false; - std::string query = StringFormat("SELECT `groups_index`, `group_name` FROM `vw_bot_groups` WHERE `owner_id` = '%u'", owner_id); + query = StringFormat("SELECT `groups_index`, `group_name` FROM `vw_bot_groups` WHERE `owner_id` = '%u' LIMIT 1", owner_id); auto results = QueryDatabase(query); - if (!results.Success() || !results.RowCount()) { - error_message = results.ErrorMessage(); - return 0; - } + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; - for (auto row = results.begin(); row != results.end(); ++row) { - if (!group_name.compare(row[1])) - return atoi(row[0]); - } - - return 0; + auto row = results.begin(); + if (!group_name.compare(row[1])) + botgroup_id = atoi(row[0]); + + return true; } -std::map> BotDatabase::LoadGroup(std::string& group_name, std::string& error_message) +bool BotDatabase::LoadBotGroup(const std::string& group_name, std::map>& member_list) { - std::map> group_list; if (group_name.empty()) - return group_list; + return false; - uint32 group_id = GetGroupIDByGroupName(group_name, error_message); - if (!group_id || !error_message.empty()) - return group_list; + uint32 botgroup_id = 0; + if (!LoadBotGroupIDByBotGroupName(group_name, botgroup_id)) + return false; + if (!botgroup_id) + return true; - std::string query = StringFormat("SELECT `bot_id` FROM `bot_group_members` WHERE `groups_index` = '%u'", group_id); + query = StringFormat("SELECT `bot_id` FROM `bot_group_members` WHERE `groups_index` = '%u' LIMIT 6", botgroup_id); auto results = QueryDatabase(query); - if (!results.Success()) { - error_message = results.ErrorMessage(); - return group_list; - } + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; for (auto row = results.begin(); row != results.end(); ++row) - group_list[group_id].push_back(atoi(row[0])); + member_list[botgroup_id].push_back(atoi(row[0])); - return group_list; + return true; } -std::list> BotDatabase::GetGroupsListByOwnerID(uint32 owner_id, std::string& error_message) +bool BotDatabase::LoadBotGroupsListByOwnerID(const uint32 owner_id, std::list>& botgroups_list) { - std::list> groups_list; if (!owner_id) - return groups_list; + return false; - std::string query = StringFormat("SELECT `group_name`, `group_leader_name` FROM `vw_bot_groups` WHERE `owner_id` = '%u'", owner_id); + query = StringFormat("SELECT `group_name`, `group_leader_name` FROM `vw_bot_groups` WHERE `owner_id` = '%u'", owner_id); auto results = QueryDatabase(query); - if (!results.Success()) { - error_message = results.ErrorMessage(); - return groups_list; - } + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; for (auto row = results.begin(); row != results.end(); ++row) - groups_list.push_back(std::pair(row[0], row[1])); - - return groups_list; + botgroups_list.push_back(std::pair(row[0], row[1])); + + return true; } + +/* Bot group functions */ +bool BotDatabase::LoadGroupedBotsByGroupID(const uint32 group_id, std::list& group_list) +{ + if (!group_id) + return false; + + query = StringFormat( + "SELECT g.`mob_id` AS bot_id" + " FROM `vw_groups` AS g" + " JOIN `bot_data` AS b" + " ON g.`mob_id` = b.`bot_id`" + " AND g.`mob_type` = 'B'" + " WHERE g.`group_id` = '%u'", + group_id + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + for (auto row = results.begin(); row != results.end(); ++row) + group_list.push_back(atoi(row[0])); + + return true; +} + + +/* Bot miscellaneous functions */ + + +/* fail::Bot functions */ +const char* BotDatabase::fail::QueryNameAvailablity() { return "Failed to query name availability"; } +const char* BotDatabase::fail::QueryBotCount() { return "Failed to query bot count"; } +const char* BotDatabase::fail::LoadQuestableSpawnCount() { return "Failed to load questable spawn count"; } +const char* BotDatabase::fail::LoadBotsList() { return "Failed to bots list"; } +const char* BotDatabase::fail::LoadOwnerID() { return "Failed to load owner id"; } +const char* BotDatabase::fail::LoadBotID() { return "Failed to load bot id"; } +const char* BotDatabase::fail::LoadBot() { return "Failed to load bot"; } +const char* BotDatabase::fail::SaveNewBot() { return "Failed to save new bot"; } +const char* BotDatabase::fail::SaveBot() { return "Failed to save bot"; } +const char* BotDatabase::fail::DeleteBot() { return "Failed to delete bot"; } +const char* BotDatabase::fail::LoadBuffs() { return "Failed to load buffs"; } +const char* BotDatabase::fail::SaveBuffs() { return "Failed to save buffs"; } +const char* BotDatabase::fail::DeleteBuffs() { return "Failed to delete buffs"; } +const char* BotDatabase::fail::LoadStance() { return "Failed to load stance"; } +const char* BotDatabase::fail::SaveStance() { return "Failed to save stance"; } +const char* BotDatabase::fail::DeleteStance() { return "Failed to delete stance"; } +const char* BotDatabase::fail::LoadTimers() { return "Failed to load timers"; } +const char* BotDatabase::fail::SaveTimers() { return "Failed to save timers"; } +const char* BotDatabase::fail::DeleteTimers() { return "Failed to delete timers"; } +const char* BotDatabase::fail::LoadGuildMembership() { return "Failed to load guild membership"; } +const char* BotDatabase::fail::SaveGuildMembership() { return "Failed to save guild membership"; } +const char* BotDatabase::fail::DeleteGuildMembership() { return "Failed to delete guild membership"; } + +/* fail::Bot inventory functions */ +const char* BotDatabase::fail::QueryInventoryCount() { return "Failed to query inventory count"; } +const char* BotDatabase::fail::LoadItems() { return "Failed to load items"; } +const char* BotDatabase::fail::SaveItems() { return "Failed to save items"; } +const char* BotDatabase::fail::DeleteItems() { return "Failed to delete items"; } +const char* BotDatabase::fail::LoadItemBySlot() { return "Failed to load item by slot"; } +const char* BotDatabase::fail::SaveItemBySlot() { return "Failed to save item by slot"; } +const char* BotDatabase::fail::DeleteItemBySlot() { return "Failed to delete item by slot"; } +const char* BotDatabase::fail::LoadEquipmentColor() { return "Failed to load equipment color"; } +const char* BotDatabase::fail::SaveEquipmentColor() { return "Failed to save equipment color"; } + +/* fail::Bot pet functions */ +const char* BotDatabase::fail::LoadPetIndex() { return "Failed to load pet index"; } +const char* BotDatabase::fail::LoadPetSpellID() { return "Failed to load pet spell id"; } +const char* BotDatabase::fail::LoadPetStats() { return "Failed to load pet stats"; } +const char* BotDatabase::fail::SavePetStats() { return "Failed to save pet stats"; } +const char* BotDatabase::fail::DeletePetStats() { return "Failed to delete pet stats"; } +const char* BotDatabase::fail::LoadPetBuffs() { return "Failed to load pet buffs"; } +const char* BotDatabase::fail::SavePetBuffs() { return "Failed to save pet buffs"; } +const char* BotDatabase::fail::DeletePetBuffs() { return "Failed to delete pet buffs"; } +const char* BotDatabase::fail::LoadPetItems() { return "Failed to load pet items"; } +const char* BotDatabase::fail::SavePetItems() { return "Failed to save pet items"; } +const char* BotDatabase::fail::DeletePetItems() { return "Failed to delete pet items"; } + +/* fail::Bot command functions */ +const char* BotDatabase::fail::LoadInspectMessage() { return "Failed to load inspect message"; } +const char* BotDatabase::fail::SaveInspectMessage() { return "Failed to save inspect message"; } +const char* BotDatabase::fail::DeleteInspectMessage() { return "Failed to delete inspect message"; } +const char* BotDatabase::fail::SaveAllInspectMessages() { return "Failed to save all inspect messages"; } +const char* BotDatabase::fail::DeleteAllInspectMessages() { return "Failed to delete all inspect messages"; } +const char* BotDatabase::fail::SaveAllArmorColorBySlot() { return "Failed to save all armor color by slot"; } +const char* BotDatabase::fail::SaveAllArmorColors() { return "Failed to save all armor colors"; } +const char* BotDatabase::fail::SaveHelmAppearance() { return "Failed to save helm appearance"; } +const char* BotDatabase::fail::SaveAllHelmAppearances() { return "Failed to save all helm appearances"; } +const char* BotDatabase::fail::ToggleHelmAppearance() { return "Failed to save toggle helm appearance"; } +const char* BotDatabase::fail::ToggleAllHelmAppearances() { return "Failed to save toggle all helm appearance"; } +const char* BotDatabase::fail::SaveFollowDistance() { return "Failed to save follow distance"; } +const char* BotDatabase::fail::SaveAllFollowDistances() { return "Failed to save all follow distances"; } +const char* BotDatabase::fail::CreateCloneBot() { return "Failed to create clone bot"; } +const char* BotDatabase::fail::CreateCloneBotInventory() { return "Failed to create clone bot inventory"; } + +/* fail::Bot bot-group functions */ +const char* BotDatabase::fail::QueryBotGroupExistence() { return "Failed to query bot-group existence"; } +const char* BotDatabase::fail::LoadBotGroupIDByBotGroupName() { return "Failed to load bot-group id by bot-group name"; } +const char* BotDatabase::fail::LoadBotGroupIDByLeaderID() { return "Failed to load bot-group id by leader id"; } +const char* BotDatabase::fail::LoadBotGroupIDByMemberID() { return "Failed to load bot-group id by member id"; } +const char* BotDatabase::fail::LoadLeaderIDByBotGroupName() { return "Failed to load leader id by bot-group name"; } +const char* BotDatabase::fail::LoadLeaderIDByBotGroupID() { return "Failed to load leader id by bot-group id"; } +const char* BotDatabase::fail::LoadBotGroupNameByBotGroupID() { return "Failed to load bot-group name by bot-group id"; } +const char* BotDatabase::fail::LoadBotGroupNameByLeaderID() { return "Failed to load bot-group name by leader id"; } +const char* BotDatabase::fail::CreateBotGroup() { return "Failed to create bot-group"; } +const char* BotDatabase::fail::DeleteBotGroup() { return "Failed to delete bot-group"; } +const char* BotDatabase::fail::AddMemberToBotGroup() { return "Failed to add member to bot-group"; } +const char* BotDatabase::fail::RemoveMemberFromBotGroup() { return "Failed to remove member from bot-group"; } +const char* BotDatabase::fail::LoadBotGroupIDForLoadBotGroup() { return "Failed to load bot-group id for load bot-group"; } +const char* BotDatabase::fail::LoadBotGroup() { return "Failed to load bot-group"; } +const char* BotDatabase::fail::LoadBotGroupsListByOwnerID() { return "Failed to load bot-groups list by owner id"; } + +/* fail::Bot group functions */ +const char* BotDatabase::fail::LoadGroupedBotsByGroupID() { return "Failed to load grouped bots by group id"; } + +/* fail::Bot miscellaneous functions */ + #endif // BOTS diff --git a/zone/bot_database.h b/zone/bot_database.h index 5e9d02880..0acfcac33 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -29,9 +29,16 @@ #include #include + +class Bot; +class ItemInst; +class Inventory; +struct BotsAvailableList; +enum BotStanceType; + + class BotDatabase : public DBcore { - public: BotDatabase(); BotDatabase(const char* host, const char* user, const char* passwd, const char* database, uint32 port); @@ -39,49 +46,223 @@ public: bool Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port); - bool GetCommandSettings(std::map>> &bot_command_settings); + bool LoadBotCommandSettings(std::map>> &bot_command_settings); - // Bot command functions - bool GetInspectMessage(uint32 bot_id, InspectMessage_Struct* message); - bool SetInspectMessage(uint32 bot_id, const InspectMessage_Struct* message); - bool SetAllInspectMessages(uint32 owner_id, const InspectMessage_Struct* message); - bool SetAllArmorColorBySlot(uint32 owner_id, int16 slot_id, uint32 rgb_value); - bool SetAllArmorColors(uint32 owner_id, uint32 rgb_value); + /* Bot functions */ + bool QueryNameAvailablity(const std::string& bot_name, bool& available_flag); + bool QueryBotCount(const uint32 owner_id, uint32& bot_count); + bool LoadQuestableSpawnCount(const uint32 owner_id, int& spawn_count); + bool LoadBotsList(const uint32 owner_id, std::list& bots_list); - bool SetHelmAppearance(uint32 owner_id, uint32 bot_id, bool show_flag = true); - bool SetAllHelmAppearances(uint32 owner_id, bool show_flag = true); + bool LoadOwnerID(const std::string& bot_name, uint32& owner_id); + bool LoadOwnerID(const uint32 bot_id, uint32& owner_id); + bool LoadBotID(const uint32 owner_id, const std::string& bot_name, uint32& bot_id); - bool ToggleHelmAppearance(uint32 owner_id, uint32 bot_id); - bool ToggleAllHelmAppearances(uint32 owner_id); + bool LoadBot(const uint32 bot_id, Bot*& loaded_bot); + bool SaveNewBot(Bot* bot_inst, uint32& bot_id); + bool SaveBot(Bot* bot_inst); + bool DeleteBot(const uint32 bot_id); - bool SetFollowDistance(uint32 owner_id, uint32 bot_id, uint32 follow_distance); - bool SetAllFollowDistances(uint32 owner_id, uint32 follow_distance); + bool LoadBuffs(Bot* bot_inst); + bool SaveBuffs(Bot* bot_inst); + bool DeleteBuffs(const uint32 bot_id); - uint32 Clone(uint32 owner_id, uint32 bot_id, const char* clone_name); - bool CloneInventory(uint32 owner_id, uint32 bot_id, uint32 clone_id); + bool LoadStance(const uint32 bot_id, BotStanceType& bot_stance); + bool LoadStance(Bot* bot_inst, bool& stance_flag); + bool SaveStance(const uint32 bot_id, const BotStanceType bot_stance); + bool SaveStance(Bot* bot_inst); + bool DeleteStance(const uint32 bot_id); - // Bot-group functions - bool DoesBotGroupExist(std::string& group_name); + bool LoadTimers(Bot* bot_inst); + bool SaveTimers(Bot* bot_inst); + bool DeleteTimers(const uint32 bot_id); - uint32 GetGroupIDByGroupName(std::string& group_name, std::string& error_message); - uint32 GetLeaderIDByGroupName(std::string& group_name, std::string& error_message); - std::string GetGroupNameByGroupID(uint32 group_id, std::string& error_message); - std::string GetGroupNameByLeaderID(uint32 leader_id, std::string& error_message); - uint32 GetGroupIDByLeaderID(uint32 leader_id, std::string& error_message); - uint32 GetLeaderIDByGroupID(uint32 group_id, std::string& error_message); + bool LoadGuildMembership(const uint32 bot_id, uint32& guild_id, uint8& guild_rank, std::string& guild_name); + bool SaveGuildMembership(const uint32 bot_id, const uint32 guild_id, const uint8 guild_rank); + bool DeleteGuildMembership(const uint32 bot_id); - uint32 GetGroupIDByMemberID(uint32 member_id, std::string& error_message); - bool CreateBotGroup(std::string& group_name, uint32 leader_id, std::string& error_message); - bool DeleteBotGroup(uint32 leader_id, std::string& error_message); - bool AddMemberToBotGroup(uint32 leader_id, uint32 member_id, std::string& error_message); - bool RemoveMemberFromBotGroup(uint32 member_id, std::string& error_message); + /* Bot inventory functions */ + bool QueryInventoryCount(const uint32 bot_id, uint32& item_count); - uint32 GetGroupIDForLoadGroup(uint32 owner_id, std::string& group_name, std::string& error_message); - std::map> LoadGroup(std::string& group_name, std::string& error_message); + bool LoadItems(const uint32 bot_id, Inventory &inventory_inst); + bool SaveItems(Bot* bot_inst); + bool DeleteItems(const uint32 bot_id); + + bool LoadItemBySlot(Bot* bot_inst); + bool LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint32& item_id); + bool SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const ItemInst* item_inst); + bool DeleteItemBySlot(const uint32 bot_id, const uint32 slot_id); + + bool LoadEquipmentColor(const uint32 bot_id, const uint8 material_slot_id, uint32& rgb); + bool SaveEquipmentColor(const uint32 bot_id, const int16 slot_id, const uint32 rgb); + + + /* Bot pet functions */ + bool LoadPetIndex(const uint32 bot_id, uint32& pet_index); + bool LoadPetSpellID(const uint32 bot_id, uint32& pet_spell_id); - std::list> GetGroupsListByOwnerID(uint32 owner_id, std::string& error_message); + bool LoadPetStats(const uint32 bot_id, std::string& pet_name, uint32& pet_mana, uint32& pet_hp, uint32& pet_spell_id); + bool SavePetStats(const uint32 bot_id, const std::string& pet_name, const uint32 pet_mana, const uint32 pet_hp, const uint32 pet_spell_id); + bool DeletePetStats(const uint32 bot_id); + + bool LoadPetBuffs(const uint32 bot_id, SpellBuff_Struct* pet_buffs); + bool SavePetBuffs(const uint32 bot_id, const SpellBuff_Struct* pet_buffs, bool delete_flag = false); + bool DeletePetBuffs(const uint32 bot_id); + + bool LoadPetItems(const uint32 bot_id, uint32* pet_items); + bool SavePetItems(const uint32 bot_id, const uint32* pet_items, bool delete_flag = false); + bool DeletePetItems(const uint32 bot_id); + + + /* Bot command functions */ + bool LoadInspectMessage(const uint32 bot_id, InspectMessage_Struct& inspect_message); + bool SaveInspectMessage(const uint32 bot_id, const InspectMessage_Struct& inspect_message); + bool DeleteInspectMessage(const uint32 bot_id); + + bool SaveAllInspectMessages(const uint32 owner_id, const InspectMessage_Struct& inspect_message); + bool DeleteAllInspectMessages(const uint32 owner_id); + + bool SaveAllArmorColorBySlot(const uint32 owner_id, const int16 slot_id, const uint32 rgb_value); + bool SaveAllArmorColors(const uint32 owner_id, const uint32 rgb_value); + + bool SaveHelmAppearance(const uint32 owner_id, const uint32 bot_id, const bool show_flag = true); + bool SaveAllHelmAppearances(const uint32 owner_id, const bool show_flag = true); + + bool ToggleHelmAppearance(const uint32 owner_id, const uint32 bot_id); + bool ToggleAllHelmAppearances(const uint32 owner_id); + + bool SaveFollowDistance(const uint32 owner_id, const uint32 bot_id, const uint32 follow_distance); + bool SaveAllFollowDistances(const uint32 owner_id, const uint32 follow_distance); + + bool CreateCloneBot(const uint32 owner_id, const uint32 bot_id, const std::string& clone_name, uint32& clone_id); + bool CreateCloneBotInventory(const uint32 owner_id, const uint32 bot_id, const uint32 clone_id); + + + /* Bot bot-group functions */ + bool QueryBotGroupExistence(const std::string& botgroup_name, bool& extant_flag); + + bool LoadBotGroupIDByBotGroupName(const std::string& botgroup_name, uint32& botgroup_id); + bool LoadBotGroupIDByLeaderID(const uint32 leader_id, uint32& botgroup_id); + bool LoadBotGroupIDByMemberID(const uint32 member_id, uint32& botgroup_id); + + bool LoadLeaderIDByBotGroupName(const std::string& botgroup_name, uint32& leader_id); + bool LoadLeaderIDByBotGroupID(const uint32 botgroup_id, uint32& leader_id); + + bool LoadBotGroupNameByBotGroupID(const uint32 botgroup_id, std::string& botgroup_name); + bool LoadBotGroupNameByLeaderID(const uint32 leader_id, std::string& botgroup_name); + + bool CreateBotGroup(const std::string& botgroup_name, const uint32 leader_id); + bool DeleteBotGroup(const uint32 leader_id); + bool AddMemberToBotGroup(const uint32 leader_id, const uint32 member_id); + bool RemoveMemberFromBotGroup(const uint32 member_id); + + bool LoadBotGroupIDForLoadBotGroup(const uint32 owner_id, const std::string& botgroup_name, uint32& botgroup_id); + bool LoadBotGroup(const std::string& botgroup_name, std::map>& member_list); + + bool LoadBotGroupsListByOwnerID(const uint32 owner_id, std::list>& botgroups_list); + + + /* Bot group functions */ + bool LoadGroupedBotsByGroupID(const uint32 group_id, std::list& group_list); + + + /* Bot miscellaneous functions */ + + + class fail { + public: + /* fail::Bot functions */ + static const char* QueryNameAvailablity(); + static const char* QueryBotCount(); + static const char* LoadQuestableSpawnCount(); + static const char* LoadBotsList(); + static const char* LoadOwnerID(); + static const char* LoadBotID(); + static const char* LoadBot(); + static const char* SaveNewBot(); + static const char* SaveBot(); + static const char* DeleteBot(); + static const char* LoadBuffs(); + static const char* SaveBuffs(); + static const char* DeleteBuffs(); + static const char* LoadStance(); + static const char* SaveStance(); + static const char* DeleteStance(); + static const char* LoadTimers(); + static const char* SaveTimers(); + static const char* DeleteTimers(); + static const char* LoadGuildMembership(); + static const char* SaveGuildMembership(); + static const char* DeleteGuildMembership(); + + /* fail::Bot inventory functions */ + static const char* QueryInventoryCount(); + static const char* LoadItems(); + static const char* SaveItems(); + static const char* DeleteItems(); + static const char* LoadItemBySlot(); + static const char* SaveItemBySlot(); + static const char* DeleteItemBySlot(); + static const char* LoadEquipmentColor(); + static const char* SaveEquipmentColor(); + + /* fail::Bot pet functions */ + static const char* LoadPetIndex(); + static const char* LoadPetSpellID(); + static const char* LoadPetStats(); + static const char* SavePetStats(); + static const char* DeletePetStats(); + static const char* LoadPetBuffs(); + static const char* SavePetBuffs(); + static const char* DeletePetBuffs(); + static const char* LoadPetItems(); + static const char* SavePetItems(); + static const char* DeletePetItems(); + + /* fail::Bot command functions */ + static const char* LoadInspectMessage(); + static const char* SaveInspectMessage(); + static const char* DeleteInspectMessage(); + static const char* SaveAllInspectMessages(); + static const char* DeleteAllInspectMessages(); + static const char* SaveAllArmorColorBySlot(); + static const char* SaveAllArmorColors(); + static const char* SaveHelmAppearance(); + static const char* SaveAllHelmAppearances(); + static const char* ToggleHelmAppearance(); + static const char* ToggleAllHelmAppearances(); + static const char* SaveFollowDistance(); + static const char* SaveAllFollowDistances(); + static const char* CreateCloneBot(); + static const char* CreateCloneBotInventory(); + + /* fail::Bot bot-group functions */ + static const char* QueryBotGroupExistence(); + static const char* LoadBotGroupIDByBotGroupName(); + static const char* LoadBotGroupIDByLeaderID(); + static const char* LoadBotGroupIDByMemberID(); + static const char* LoadLeaderIDByBotGroupName(); + static const char* LoadLeaderIDByBotGroupID(); + static const char* LoadBotGroupNameByBotGroupID(); + static const char* LoadBotGroupNameByLeaderID(); + static const char* CreateBotGroup(); + static const char* DeleteBotGroup(); + static const char* AddMemberToBotGroup(); + static const char* RemoveMemberFromBotGroup(); + static const char* LoadBotGroupIDForLoadBotGroup(); + static const char* LoadBotGroup(); + static const char* LoadBotGroupsListByOwnerID(); + + /* fail::Bot group functions */ + static const char* LoadGroupedBotsByGroupID(); + + /* fail::Bot miscellaneous functions */ + }; + + private: + std::string query; }; extern BotDatabase botdb; diff --git a/zone/bot_structs.h b/zone/bot_structs.h index c8b9623eb..996fbff41 100644 --- a/zone/bot_structs.h +++ b/zone/bot_structs.h @@ -26,12 +26,12 @@ #include struct BotsAvailableList { - uint32 BotID; - char BotName[64]; - uint16 BotClass; - uint8 BotLevel; - uint16 BotRace; - uint8 BotGender; + uint32 ID; + char Name[64]; + uint16 Class; + uint8 Level; + uint16 Race; + uint8 Gender; }; struct BotGroup { diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index dc5e3136f..32d215b9b 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2056,24 +2056,23 @@ bool QuestManager::botquest() bool QuestManager::createBot(const char *name, const char *lastname, uint8 level, uint16 race, uint8 botclass, uint8 gender) { QuestManagerCurrentQuestVars(); - std::string TempErrorMessage; uint32 MaxBotCreate = RuleI(Bots, CreationLimit); if (initiator && initiator->IsClient()) { - if(Bot::SpawnedBotCount(initiator->CharacterID(), &TempErrorMessage) >= MaxBotCreate) + if(Bot::SpawnedBotCount(initiator->CharacterID()) >= MaxBotCreate) { initiator->Message(15,"You have the maximum number of bots allowed."); return false; } - if(!TempErrorMessage.empty()) - { - initiator->Message(13, "Database Error: %s", TempErrorMessage.c_str()); + std::string test_name = name; + bool available_flag = false; + if(!botdb.QueryNameAvailablity(test_name, available_flag)) { + initiator->Message(0, "%s for '%s'", BotDatabase::fail::QueryNameAvailablity(), (char*)name); return false; } - - if(Bot::IsBotNameAvailable((char*)name,&TempErrorMessage)) { + if (!available_flag) { initiator->Message(0, "The name %s is already being used or is invalid. Please choose a different name.", (char*)name); return false; } @@ -2093,11 +2092,6 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level return false; } - if(!TempErrorMessage.empty()) { - initiator->Message(13, "Database Error: %s", TempErrorMessage.c_str()); - return false; - } - // Now that all validation is complete, we can save our newly created bot if(!NewBot->Save()) { diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index e90e64af5..5347b2792 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -4134,3 +4134,36 @@ bool ZoneDatabase::DeleteCharacterCorpse(uint32 db_id) { return false; } + +uint32 ZoneDatabase::LoadSaylinkID(const char* saylink_text, bool auto_insert) +{ + if (!saylink_text || saylink_text[0] == '\0') + return 0; + + std::string query = StringFormat("SELECT `id` FROM `saylink` WHERE `phrase` = '%s' LIMIT 1", saylink_text); + auto results = QueryDatabase(query); + if (!results.Success()) + return 0; + if (!results.RowCount()) { + if (auto_insert) + return SaveSaylinkID(saylink_text); + else + return 0; + } + + auto row = results.begin(); + return atoi(row[0]); +} + +uint32 ZoneDatabase::SaveSaylinkID(const char* saylink_text) +{ + if (!saylink_text || saylink_text[0] == '\0') + return 0; + + std::string query = StringFormat("INSERT INTO `saylink` (`phrase`) VALUES ('%s')", saylink_text); + auto results = QueryDatabase(query); + if (!results.Success()) + return 0; + + return results.LastInsertedID(); +} diff --git a/zone/zonedb.h b/zone/zonedb.h index b5e1d3509..3c5ca7b00 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -480,6 +480,10 @@ public: void LoadAltCurrencyValues(uint32 char_id, std::map ¤cy); void UpdateAltCurrencyValue(uint32 char_id, uint32 currency_id, uint32 value); + /* Saylinks */ + uint32 LoadSaylinkID(const char* saylink_text, bool auto_insert = true); + uint32 SaveSaylinkID(const char* saylink_text); + /* * Misc stuff. * PLEASE DO NOT ADD TO THIS COLLECTION OF CRAP UNLESS YOUR METHOD From 51c97211a831291a7b6a43858db2450c06bb9cf9 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 5 Apr 2016 18:54:40 -0400 Subject: [PATCH 030/693] Fix for "ISO C++" taboo --- zone/bot_command.cpp | 2 +- zone/bot_database.cpp | 6 +++--- zone/bot_database.h | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 0cd0b8072..ff9b32236 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -4215,7 +4215,7 @@ void bot_subcommand_bot_clone(Client *c, const Seperator *sep) return; } - BotStanceType clone_stance = BotStancePassive; + int clone_stance = BotStancePassive; if (!botdb.LoadStance(my_bot->GetBotID(), clone_stance)) c->Message(m_fail, "%s for bot '%s'", BotDatabase::fail::LoadStance(), my_bot->GetCleanName()); if (!botdb.SaveStance(clone_id, clone_stance)) diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index d031ee0cf..e26ae7fea 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -763,7 +763,7 @@ bool BotDatabase::DeleteBuffs(const uint32 bot_id) return true; } -bool BotDatabase::LoadStance(const uint32 bot_id, BotStanceType& bot_stance) +bool BotDatabase::LoadStance(const uint32 bot_id, int& bot_stance) { if (!bot_id) return false; @@ -776,7 +776,7 @@ bool BotDatabase::LoadStance(const uint32 bot_id, BotStanceType& bot_stance) return true; auto row = results.begin(); - bot_stance = (BotStanceType)atoi(row[0]); + bot_stance = atoi(row[0]); return true; } @@ -802,7 +802,7 @@ bool BotDatabase::LoadStance(Bot* bot_inst, bool& stance_flag) return true; } -bool BotDatabase::SaveStance(const uint32 bot_id, const BotStanceType bot_stance) +bool BotDatabase::SaveStance(const uint32 bot_id, const int bot_stance) { if (!bot_id) return false; diff --git a/zone/bot_database.h b/zone/bot_database.h index 0acfcac33..27d4b4116 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -34,7 +34,6 @@ class Bot; class ItemInst; class Inventory; struct BotsAvailableList; -enum BotStanceType; class BotDatabase : public DBcore @@ -68,9 +67,9 @@ public: bool SaveBuffs(Bot* bot_inst); bool DeleteBuffs(const uint32 bot_id); - bool LoadStance(const uint32 bot_id, BotStanceType& bot_stance); + bool LoadStance(const uint32 bot_id, int& bot_stance); bool LoadStance(Bot* bot_inst, bool& stance_flag); - bool SaveStance(const uint32 bot_id, const BotStanceType bot_stance); + bool SaveStance(const uint32 bot_id, const int bot_stance); bool SaveStance(Bot* bot_inst); bool DeleteStance(const uint32 bot_id); From b07f3d04dfaf536b9542a82ffa6eb2453f0e3641 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 5 Apr 2016 19:04:06 -0400 Subject: [PATCH 031/693] Fix for version 9003 trigger criteria --- utils/sql/git/bots/bots_db_update_manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index f25bac0de..bbb0130ed 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -1,7 +1,7 @@ 9000|2015_09_30_bots.sql|SHOW TABLES LIKE 'bot_data'|empty| 9001|2016_03_24_bots_command_settings.sql|SHOW TABLES LIKE 'bot_command_settings'|empty| 9002|2016_03_24_bots_command_rules.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CommandSpellRank'|empty| -9003|2016_04_05_bots_pet_spell_id_field.sql|EXPLAIN `bot_pets`|contains|pet_id +9003|2016_04_05_bots_pet_spell_id_field.sql|SHOW COLUMNS FROM `bot_pets` LIKE 'pet_id'|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From 28b7e0e2088f11d0903719af018c5c52da30ad83 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 5 Apr 2016 20:04:31 -0400 Subject: [PATCH 032/693] Fix for bot pet names showing up as numbers --- zone/bot.cpp | 15 ++++++++------- zone/bot_database.cpp | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 21cdd6d46..2409b84b4 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1739,15 +1739,16 @@ bool Bot::SavePet() pet_inst->GetPetState(pet_buffs, pet_items, pet_name); - std::string error_message; - - if (!botdb.SavePetStats(GetBotID(), pet_name, pet_inst->GetMana(), pet_inst->GetHP(), pet_inst->GetPetSpellID())) { - bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::SavePetStats(), GetCleanName()); - safe_delete_array(pet_name); - return false; - } + std::string pet_name_str = pet_name; safe_delete_array(pet_name); + std::string error_message; + + if (!botdb.SavePetStats(GetBotID(), pet_name_str, pet_inst->GetMana(), pet_inst->GetHP(), pet_inst->GetPetSpellID())) { + bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::SavePetStats(), GetCleanName()); + return false; + } + if (!botdb.SavePetBuffs(GetBotID(), pet_buffs)) bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::SavePetBuffs(), GetCleanName()); if (!botdb.SavePetItems(GetBotID(), pet_items)) diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index e26ae7fea..54a701612 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1407,7 +1407,7 @@ bool BotDatabase::SavePetStats(const uint32 bot_id, const std::string& pet_name, " VALUES (" "'%u'," " '%u'," - " '%u'," + " '%s'," " '%u'," " '%u'" ")", From 6ea061dc5513eb68a881acf2df25f30abb047259 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 6 Apr 2016 15:38:26 -0400 Subject: [PATCH 033/693] Added missing argument descriptor to 'bot_subcommand_heal_rotation_adjust_safe' usage. --- zone/bot_command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index ff9b32236..204afeffc 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -6152,7 +6152,7 @@ void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep) if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_adjust_safe", sep->arg[0], "healrotationadjustsafe")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(m_usage, "usage: () %s [value: %3.1f-%3.1f | + | -] ([member_name])", sep->arg[0], CRITICAL_HP_RATIO_BASE, SAFE_HP_RATIO_BASE); + c->Message(m_usage, "usage: () %s [armor_type] [value: %3.1f-%3.1f | + | -] ([member_name])", sep->arg[0], CRITICAL_HP_RATIO_BASE, SAFE_HP_RATIO_BASE); c->Message(m_note, "armor_types: %u(Base), %u(Cloth), %u(Leather), %u(Chain), %u(Plate)", ARMOR_TYPE_UNKNOWN, ARMOR_TYPE_CLOTH, ARMOR_TYPE_LEATHER, ARMOR_TYPE_CHAIN, ARMOR_TYPE_PLATE); return; From e75a53b775429a481504e711d9b5b1b13d08ba24 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 7 Apr 2016 17:21:55 -0400 Subject: [PATCH 034/693] Rework of eq_dictionary --- changelog.txt | 3 + common/database.cpp | 14 +- common/database_conversions.cpp | 12 +- common/eq_constants.h | 138 ++++--- common/eq_dictionary.cpp | 621 ++++++++++++++-------------- common/eq_dictionary.h | 247 +++++------ common/eq_packet_structs.h | 26 +- common/extprofile.h | 2 +- common/item.cpp | 358 ++++++++-------- common/item_struct.h | 6 +- common/patches/rof.cpp | 318 +++++++------- common/patches/rof2.cpp | 328 +++++++-------- common/patches/rof2_constants.h | 212 +++++----- common/patches/rof2_structs.h | 90 ++-- common/patches/rof_constants.h | 210 +++++----- common/patches/rof_structs.h | 88 ++-- common/patches/sod.cpp | 48 +-- common/patches/sod_constants.h | 207 +++++----- common/patches/sof.cpp | 48 +-- common/patches/sof_constants.h | 207 +++++----- common/patches/titanium.cpp | 22 +- common/patches/titanium_constants.h | 205 +++++---- common/patches/uf.cpp | 48 +-- common/patches/uf_constants.h | 207 +++++----- common/shareddb.cpp | 38 +- world/client.cpp | 10 +- world/worlddb.cpp | 10 +- zone/aa.cpp | 2 +- zone/attack.cpp | 104 ++--- zone/beacon.h | 2 +- zone/bonuses.cpp | 64 +-- zone/bot.cpp | 252 +++++------ zone/bot.h | 6 +- zone/bot_command.cpp | 68 +-- zone/bot_database.cpp | 24 +- zone/client.cpp | 112 ++--- zone/client.h | 4 +- zone/client_mods.cpp | 24 +- zone/client_packet.cpp | 68 +-- zone/client_process.cpp | 38 +- zone/command.cpp | 56 +-- zone/corpse.cpp | 50 +-- zone/corpse.h | 2 +- zone/doors.cpp | 2 +- zone/encounter.h | 2 +- zone/entity.h | 2 +- zone/forage.cpp | 14 +- zone/inventory.cpp | 362 ++++++++-------- zone/loottables.cpp | 22 +- zone/lua_general.cpp | 88 ++-- zone/merc.cpp | 32 +- zone/merc.h | 4 +- zone/mob.cpp | 8 +- zone/mob.h | 24 +- zone/mob_ai.cpp | 8 +- zone/npc.cpp | 8 +- zone/npc.h | 4 +- zone/object.cpp | 12 +- zone/pets.cpp | 10 +- zone/questmgr.cpp | 4 +- zone/special_attacks.cpp | 124 +++--- zone/spell_effects.cpp | 28 +- zone/spells.cpp | 4 +- zone/tradeskills.cpp | 12 +- zone/trading.cpp | 78 ++-- zone/tribute.cpp | 30 +- zone/tune.cpp | 42 +- zone/zonedb.cpp | 38 +- zone/zonedb.h | 2 +- zone/zonedump.h | 2 +- 70 files changed, 2786 insertions(+), 2779 deletions(-) diff --git a/changelog.txt b/changelog.txt index 913204cab..25729bce1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/07/2016 == +Uleat: Rework of eq_dictionary to facilitate inventory work + == 04/05/2016 == Uleat: Moved database query code out of bot.cpp and into the new BotDatabase class diff --git a/common/database.cpp b/common/database.cpp index cdafaa165..36b8237e5 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -705,7 +705,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven /* Insert starting inventory... */ std::string invquery; - for (int16 i=EmuConstants::EQUIPMENT_BEGIN; i<=EmuConstants::BANK_BAGS_END;) { + for (int16 i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::BANK_BAGS_END;) { const ItemInst* newinv = inv->GetItem(i); if (newinv) { invquery = StringFormat("INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)", @@ -714,16 +714,16 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven auto results = QueryDatabase(invquery); } - if (i == MainCursor) { - i = EmuConstants::GENERAL_BAGS_BEGIN; + if (i == SlotCursor) { + i = EQEmu::Constants::GENERAL_BAGS_BEGIN; continue; } - else if (i == EmuConstants::CURSOR_BAG_END) { - i = EmuConstants::BANK_BEGIN; + else if (i == EQEmu::Constants::CURSOR_BAG_END) { + i = EQEmu::Constants::BANK_BEGIN; continue; } - else if (i == EmuConstants::BANK_END) { - i = EmuConstants::BANK_BAGS_BEGIN; + else if (i == EQEmu::Constants::BANK_END) { + i = EQEmu::Constants::BANK_BAGS_BEGIN; continue; } i++; diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index c7428c07e..4364ae27a 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -186,7 +186,7 @@ namespace Convert { /*002*/ uint32 HP; /*006*/ uint32 Mana; /*010*/ Convert::SpellBuff_Struct Buffs[BUFF_COUNT]; - /*510*/ uint32 Items[_MaterialCount]; + /*510*/ uint32 Items[MaterialCount]; /*546*/ char Name[64]; /*610*/ }; @@ -227,9 +227,9 @@ namespace Convert { /*0304*/ uint8 ability_time_minutes; /*0305*/ uint8 ability_time_hours; //place holder /*0306*/ uint8 unknown0306[6]; // @bp Spacer/Flag? - /*0312*/ uint32 item_material[_MaterialCount]; // Item texture/material of worn/held items + /*0312*/ uint32 item_material[MaterialCount]; // Item texture/material of worn/held items /*0348*/ uint8 unknown0348[44]; - /*0392*/ Convert::Color_Struct item_tint[_MaterialCount]; + /*0392*/ Convert::Color_Struct item_tint[MaterialCount]; /*0428*/ Convert::AA_Array aa_array[MAX_PP_AA_ARRAY]; /*2348*/ float unknown2384; //seen ~128, ~47 /*2352*/ char servername[32]; // length probably not right @@ -330,7 +330,7 @@ namespace Convert { /*7212*/ uint32 tribute_points; /*7216*/ uint32 unknown7252; /*7220*/ uint32 tribute_active; //1=active - /*7224*/ Convert::Tribute_Struct tributes[EmuConstants::TRIBUTE_SIZE]; + /*7224*/ Convert::Tribute_Struct tributes[EQEmu::Constants::TRIBUTE_SIZE]; /*7264*/ Convert::Disciplines_Struct disciplines; /*7664*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use) /*7744*/ char unknown7780[160]; @@ -1416,7 +1416,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){ if (rquery != ""){ results = QueryDatabase(rquery); } /* Run Material Color Convert */ first_entry = 0; rquery = ""; - for (i = 0; i < _MaterialCount; i++){ + for (i = 0; i < MaterialCount; i++){ if (pp->item_tint[i].color > 0){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); @@ -1428,7 +1428,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){ if (rquery != ""){ results = QueryDatabase(rquery); } /* Run Tribute Convert */ first_entry = 0; rquery = ""; - for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + for (i = 0; i < EQEmu::Constants::TRIBUTE_SIZE; i++){ if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 4294967295){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); diff --git a/common/eq_constants.h b/common/eq_constants.h index 222d5802f..d41af6e94 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -851,7 +851,7 @@ static const uint8 SkillDamageTypes[HIGHEST_SKILL + 1] = // change to _SkillServ ** Material use slots ** */ -enum MaterialUseSlots : uint8 +enum MaterialSlots : uint8 { MaterialHead = 0, MaterialChest, @@ -862,8 +862,8 @@ enum MaterialUseSlots : uint8 MaterialFeet, MaterialPrimary, MaterialSecondary, - _MaterialCount, - _MaterialInvalid = 255 + MaterialCount, + MaterialInvalid = 255 }; /* @@ -900,71 +900,73 @@ enum MaterialUseSlots : uint8 ** */ -enum InventoryMapTypes : int16 { - MapPossessions = 0, - MapBank, - MapSharedBank, - MapTrade, - MapWorld, - MapLimbo, // 5 - MapTribute, - MapTrophyTribute, - MapGuildTribute, - MapMerchant, - MapDeleted, // 10 - MapCorpse, - MapBazaar, - MapInspect, - MapRealEstate, - MapViewMODPC, // 15 - MapViewMODBank, - MapViewMODSharedBank, - MapViewMODLimbo, - MapAltStorage, - MapArchived, // 20 - MapMail, - MapGuildTrophyTribute, - MapKrono, - MapOther, - _MapCount +enum InventoryTypes : int16 +{ + TypePossessions = 0, + TypeBank, + TypeSharedBank, + TypeTrade, + TypeWorld, + TypeLimbo, // 5 + TypeTribute, + TypeTrophyTribute, + TypeGuildTribute, + TypeMerchant, + TypeDeleted, // 10 + TypeCorpse, + TypeBazaar, + TypeInspect, + TypeRealEstate, + TypeViewMODPC, // 15 + TypeViewMODBank, + TypeViewMODSharedBank, + TypeViewMODLimbo, + TypeAltStorage, + TypeArchived, // 20 + TypeMail, + TypeGuildTrophyTribute, + TypeKrono, + TypeOther, + TypeCount }; -enum InventoryMainTypes : int16 { - MainCharm = 0, - MainEar1, - MainHead, - MainFace, - MainEar2, - MainNeck, // 5 - MainShoulders, - MainArms, - MainBack, - MainWrist1, - MainWrist2, // 10 - MainRange, - MainHands, - MainPrimary, - MainSecondary, - MainFinger1, // 15 - MainFinger2, - MainChest, - MainLegs, - MainFeet, - MainWaist, // 20 - MainPowerSource = 9999, // temp - MainAmmo = 21, // temp - MainGeneral1, - MainGeneral2, - MainGeneral3, - MainGeneral4, // 25 - MainGeneral5, - MainGeneral6, - MainGeneral7, - MainGeneral8, - //MainGeneral9, - //MainGeneral10, - MainCursor, // 30 - _MainCount +enum PossessionsSlots : int16 +{ + SlotCharm = 0, + SlotEar1, + SlotHead, + SlotFace, + SlotEar2, + SlotNeck, // 5 + SlotShoulders, + SlotArms, + SlotBack, + SlotWrist1, + SlotWrist2, // 10 + SlotRange, + SlotHands, + SlotPrimary, + SlotSecondary, + SlotFinger1, // 15 + SlotFinger2, + SlotChest, + SlotLegs, + SlotFeet, + SlotWaist, // 20 + SlotPowerSource = 9999, // temp + SlotAmmo = 21, // temp + SlotGeneral1, + SlotGeneral2, + SlotGeneral3, + SlotGeneral4, // 25 + SlotGeneral5, + SlotGeneral6, + SlotGeneral7, + SlotGeneral8, + //SlotGeneral9, + //SlotGeneral10, + SlotCursor, // 30 + SlotCount }; #define INVALID_INDEX -1 @@ -973,8 +975,8 @@ enum InventoryMainTypes : int16 { // yes..these are redundant... but, they help to identify and define what is actually being performed // plus, since they're pre-op's, they don't affect the actual binary size -#define MAP_BEGIN 0 -#define MAIN_BEGIN 0 +#define TYPE_BEGIN 0 +#define SLOT_BEGIN 0 #define SUB_BEGIN 0 #define AUG_BEGIN 0 diff --git a/common/eq_dictionary.cpp b/common/eq_dictionary.cpp index 9bc602aa1..b4388b537 100644 --- a/common/eq_dictionary.cpp +++ b/common/eq_dictionary.cpp @@ -1,7 +1,7 @@ /* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) +Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,69 +23,68 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "string_util.h" // -// class EmuConstants +// class EQEmu::Constants // -uint16 EmuConstants::InventoryMapSize(int16 indexMap) +uint16 EQEmu::Constants::InventoryTypeSize(int16 type_index) { - switch (indexMap) - { - case MapPossessions: - return MAP_POSSESSIONS_SIZE; - case MapBank: - return MAP_BANK_SIZE; - case MapSharedBank: - return MAP_SHARED_BANK_SIZE; - case MapTrade: - return MAP_TRADE_SIZE; - case MapWorld: - return MAP_WORLD_SIZE; - case MapLimbo: - return MAP_LIMBO_SIZE; - case MapTribute: - return MAP_TRIBUTE_SIZE; - case MapTrophyTribute: - return MAP_TROPHY_TRIBUTE_SIZE; - case MapGuildTribute: - return MAP_GUILD_TRIBUTE_SIZE; - case MapMerchant: - return MAP_MERCHANT_SIZE; - case MapDeleted: - return MAP_DELETED_SIZE; - case MapCorpse: - return MAP_CORPSE_SIZE; - case MapBazaar: - return MAP_BAZAAR_SIZE; - case MapInspect: - return MAP_INSPECT_SIZE; - case MapRealEstate: - return MAP_REAL_ESTATE_SIZE; - case MapViewMODPC: - return MAP_VIEW_MOD_PC_SIZE; - case MapViewMODBank: - return MAP_VIEW_MOD_BANK_SIZE; - case MapViewMODSharedBank: - return MAP_VIEW_MOD_SHARED_BANK_SIZE; - case MapViewMODLimbo: - return MAP_VIEW_MOD_LIMBO_SIZE; - case MapAltStorage: - return MAP_ALT_STORAGE_SIZE; - case MapArchived: - return MAP_ARCHIVED_SIZE; - case MapMail: - return MAP_MAIL_SIZE; - case MapGuildTrophyTribute: - return MAP_GUILD_TROPHY_TRIBUTE_SIZE; - case MapKrono: - return MAP_KRONO_SIZE; - case MapOther: - return MAP_OTHER_SIZE; + switch (type_index) { + case TypePossessions: + return TYPE_POSSESSIONS_SIZE; + case TypeBank: + return TYPE_BANK_SIZE; + case TypeSharedBank: + return TYPE_SHARED_BANK_SIZE; + case TypeTrade: + return TYPE_TRADE_SIZE; + case TypeWorld: + return TYPE_WORLD_SIZE; + case TypeLimbo: + return TYPE_LIMBO_SIZE; + case TypeTribute: + return TYPE_TRIBUTE_SIZE; + case TypeTrophyTribute: + return TYPE_TROPHY_TRIBUTE_SIZE; + case TypeGuildTribute: + return TYPE_GUILD_TRIBUTE_SIZE; + case TypeMerchant: + return TYPE_MERCHANT_SIZE; + case TypeDeleted: + return TYPE_DELETED_SIZE; + case TypeCorpse: + return TYPE_CORPSE_SIZE; + case TypeBazaar: + return TYPE_BAZAAR_SIZE; + case TypeInspect: + return TYPE_INSPECT_SIZE; + case TypeRealEstate: + return TYPE_REAL_ESTATE_SIZE; + case TypeViewMODPC: + return TYPE_VIEW_MOD_PC_SIZE; + case TypeViewMODBank: + return TYPE_VIEW_MOD_BANK_SIZE; + case TypeViewMODSharedBank: + return TYPE_VIEW_MOD_SHARED_BANK_SIZE; + case TypeViewMODLimbo: + return TYPE_VIEW_MOD_LIMBO_SIZE; + case TypeAltStorage: + return TYPE_ALT_STORAGE_SIZE; + case TypeArchived: + return TYPE_ARCHIVED_SIZE; + case TypeMail: + return TYPE_MAIL_SIZE; + case TypeGuildTrophyTribute: + return TYPE_GUILD_TROPHY_TRIBUTE_SIZE; + case TypeKrono: + return TYPE_KRONO_SIZE; + case TypeOther: + return TYPE_OTHER_SIZE; default: return NOT_USED; } } /* -std::string EmuConstants::InventoryLocationName(Location_Struct location) +const char* EQEmu::Constants::InventoryLocationName(Location_Struct location) { // not ready for implementation... std::string ret_str; @@ -94,182 +93,180 @@ std::string EmuConstants::InventoryLocationName(Location_Struct location) } */ -std::string EmuConstants::InventoryMapName(int16 indexMap) +const char* EQEmu::Constants::InventoryTypeName(int16 type_index) { - switch (indexMap) - { + switch (type_index) { case INVALID_INDEX: - return "Invalid Map"; - case MapPossessions: + return "Invalid Type"; + case TypePossessions: return "Possessions"; - case MapBank: + case TypeBank: return "Bank"; - case MapSharedBank: + case TypeSharedBank: return "SharedBank"; - case MapTrade: + case TypeTrade: return "Trade"; - case MapWorld: + case TypeWorld: return "World"; - case MapLimbo: + case TypeLimbo: return "Limbo"; - case MapTribute: + case TypeTribute: return "Tribute"; - case MapTrophyTribute: + case TypeTrophyTribute: return "TrophyTribute"; - case MapGuildTribute: + case TypeGuildTribute: return "GuildTribute"; - case MapMerchant: + case TypeMerchant: return "Merchant"; - case MapDeleted: + case TypeDeleted: return "Deleted"; - case MapCorpse: + case TypeCorpse: return "Corpse"; - case MapBazaar: + case TypeBazaar: return "Bazaar"; - case MapInspect: + case TypeInspect: return "Inspect"; - case MapRealEstate: + case TypeRealEstate: return "RealEstate"; - case MapViewMODPC: + case TypeViewMODPC: return "ViewMODPC"; - case MapViewMODBank: + case TypeViewMODBank: return "ViewMODBank"; - case MapViewMODSharedBank: + case TypeViewMODSharedBank: return "ViewMODSharedBank"; - case MapViewMODLimbo: + case TypeViewMODLimbo: return "ViewMODLimbo"; - case MapAltStorage: + case TypeAltStorage: return "AltStorage"; - case MapArchived: + case TypeArchived: return "Archived"; - case MapMail: + case TypeMail: return "Mail"; - case MapGuildTrophyTribute: + case TypeGuildTrophyTribute: return "GuildTrophyTribute"; - case MapKrono: + case TypeKrono: return "Krono"; - case MapOther: + case TypeOther: return "Other"; default: - return "Unknown Map"; + return "Unknown Type"; } } -std::string EmuConstants::InventoryMainName(int16 indexMain) +const char* EQEmu::Constants::InventorySlotName(int16 slot_index) { - switch (indexMain) - { + switch (slot_index) { case INVALID_INDEX: - return "Invalid Main"; - case MainCharm: + return "Invalid Slot"; + case SlotCharm: return "Charm"; - case MainEar1: + case SlotEar1: return "Ear1"; - case MainHead: + case SlotHead: return "Head"; - case MainFace: + case SlotFace: return "Face"; - case MainEar2: + case SlotEar2: return "Ear2"; - case MainNeck: + case SlotNeck: return "Neck"; - case MainShoulders: + case SlotShoulders: return "Shoulders"; - case MainArms: + case SlotArms: return "Arms"; - case MainBack: + case SlotBack: return "Back"; - case MainWrist1: + case SlotWrist1: return "Wrist1"; - case MainWrist2: + case SlotWrist2: return "Wrist2"; - case MainRange: + case SlotRange: return "Range"; - case MainHands: + case SlotHands: return "Hands"; - case MainPrimary: + case SlotPrimary: return "Primary"; - case MainSecondary: + case SlotSecondary: return "Secondary"; - case MainFinger1: + case SlotFinger1: return "Finger1"; - case MainFinger2: + case SlotFinger2: return "Finger2"; - case MainChest: + case SlotChest: return "Chest"; - case MainLegs: + case SlotLegs: return "Legs"; - case MainFeet: + case SlotFeet: return "Feet"; - case MainWaist: + case SlotWaist: return "Waist"; - case MainPowerSource: + case SlotPowerSource: return "PowerSource"; - case MainAmmo: + case SlotAmmo: return "Ammo"; - case MainGeneral1: + case SlotGeneral1: return "General1"; - case MainGeneral2: + case SlotGeneral2: return "General2"; - case MainGeneral3: + case SlotGeneral3: return "General3"; - case MainGeneral4: + case SlotGeneral4: return "General4"; - case MainGeneral5: + case SlotGeneral5: return "General5"; - case MainGeneral6: + case SlotGeneral6: return "General6"; - case MainGeneral7: + case SlotGeneral7: return "General7"; - case MainGeneral8: + case SlotGeneral8: return "General8"; /* - case MainGeneral9: + case SlotGeneral9: return "General9"; - case MainGeneral10: + case SlotGeneral10: return "General10"; */ - case MainCursor: + case SlotCursor: return "Cursor"; default: - return "Unknown Main"; + return "Unknown Slot"; } } -std::string EmuConstants::InventorySubName(int16 indexSub) +const char* EQEmu::Constants::InventorySubName(int16 sub_index) { - if (indexSub == INVALID_INDEX) + if (sub_index == INVALID_INDEX) return "Invalid Sub"; - if ((uint16)indexSub >= ITEM_CONTAINER_SIZE) + if ((uint16)sub_index >= ITEM_CONTAINER_SIZE) return "Unknown Sub"; - std::string ret_str; - ret_str = StringFormat("Container%i", (indexSub + 1)); // zero-based index..but, count starts at one + static std::string ret_str; + ret_str = StringFormat("Container%i", (sub_index + 1)); // zero-based index..but, count starts at one - return ret_str; + return ret_str.c_str(); } -std::string EmuConstants::InventoryAugName(int16 indexAug) +const char* EQEmu::Constants::InventoryAugName(int16 aug_index) { - if (indexAug == INVALID_INDEX) + if (aug_index == INVALID_INDEX) return "Invalid Aug"; - if ((uint16)indexAug >= ITEM_COMMON_SIZE) + if ((uint16)aug_index >= ITEM_COMMON_SIZE) return "Unknown Aug"; - std::string ret_str; - ret_str = StringFormat("Augment%i", (indexAug + 1)); // zero-based index..but, count starts at one + static std::string ret_str; + ret_str = StringFormat("Augment%i", (aug_index + 1)); // zero-based index..but, count starts at one - return ret_str; + return ret_str.c_str(); } // -// class EQLimits +// class EQEmu::Limits // // client validation -bool EQLimits::IsValidPCClientVersion(ClientVersion clientVersion) +bool EQEmu::Limits::IsValidPCClientVersion(ClientVersion clientVersion) { if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) return true; @@ -277,7 +274,7 @@ bool EQLimits::IsValidPCClientVersion(ClientVersion clientVersion) return false; } -ClientVersion EQLimits::ValidatePCClientVersion(ClientVersion clientVersion) +ClientVersion EQEmu::Limits::ValidatePCClientVersion(ClientVersion clientVersion) { if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) return clientVersion; @@ -286,7 +283,7 @@ ClientVersion EQLimits::ValidatePCClientVersion(ClientVersion clientVersion) } // npc validation -bool EQLimits::IsValidNPCClientVersion(ClientVersion clientVersion) +bool EQEmu::Limits::IsValidNPCClientVersion(ClientVersion clientVersion) { if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) return true; @@ -294,7 +291,7 @@ bool EQLimits::IsValidNPCClientVersion(ClientVersion clientVersion) return false; } -ClientVersion EQLimits::ValidateNPCClientVersion(ClientVersion clientVersion) +ClientVersion EQEmu::Limits::ValidateNPCClientVersion(ClientVersion clientVersion) { if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) return clientVersion; @@ -303,7 +300,7 @@ ClientVersion EQLimits::ValidateNPCClientVersion(ClientVersion clientVersion) } // mob validation -bool EQLimits::IsValidMobClientVersion(ClientVersion clientVersion) +bool EQEmu::Limits::IsValidMobClientVersion(ClientVersion clientVersion) { if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) return true; @@ -311,7 +308,7 @@ bool EQLimits::IsValidMobClientVersion(ClientVersion clientVersion) return false; } -ClientVersion EQLimits::ValidateMobClientVersion(ClientVersion clientVersion) +ClientVersion EQEmu::Limits::ValidateMobClientVersion(ClientVersion clientVersion) { if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) return clientVersion; @@ -320,7 +317,7 @@ ClientVersion EQLimits::ValidateMobClientVersion(ClientVersion clientVersion) } // database -size_t EQLimits::CharacterCreationLimit(ClientVersion clientVersion) +size_t EQEmu::Limits::CharacterCreationLimit(ClientVersion clientVersion) { static const size_t local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, @@ -342,7 +339,7 @@ size_t EQLimits::CharacterCreationLimit(ClientVersion clientVersion) } // inventory -uint16 EQLimits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) +uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) { // not all maps will have an instantiated container..some are references for queue generators (i.e., bazaar, mail, etc...) // a zero '0' indicates a needed value..otherwise, change to '_NOTUSED' for a null value so indices requiring research can be identified @@ -351,383 +348,383 @@ uint16 EQLimits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) // make sure that you transcribe the actual value from 'defaults' to here before updating or client crashes will ensue..and/or... // insert older clients inside of the progression of client order // - // MAP_POSSESSIONS_SIZE does not reflect all actual _constants size due to bitmask-use compatibility + // TYPE_POSSESSIONS_SIZE does not reflect all actual _constants size due to bitmask-use compatibility // - // when setting NPC-based values, try to adhere to an EmuConstants:: or NOT_USED value to avoid unnecessary issues + // when setting NPC-based values, try to adhere to an Constants:: or NOT_USED value to avoid unnecessary issues - static const uint16 local[_MapCount][CLIENT_VERSION_COUNT] = { - // server and database are sync'd to current MapPossessions's client as set in 'using namespace RoF::slots;' and - // 'EmuConstants::MAP_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() - // for partial range validation checks and 'EmuConstants::MAP_POSSESSIONS_SIZE' for full range iterations - { // local[MainPossessions] + static const uint16 local[TypeCount][CLIENT_VERSION_COUNT] = { + // server and database are sync'd to current TypePossessions's client as set in 'using namespace RoF::slots;' and + // 'Constants::TYPE_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() + // for partial range validation checks and 'Constants::TYPE_POSSESSIONS_SIZE' for full range iterations + { // local[TypePossessions] /*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*Titanium*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*SoF*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*SoD*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*Underfoot*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*RoF*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*RoF2*/ EmuConstants::MAP_POSSESSIONS_SIZE, +/*62*/ Constants::TYPE_POSSESSIONS_SIZE, +/*Titanium*/ Constants::TYPE_POSSESSIONS_SIZE, +/*SoF*/ Constants::TYPE_POSSESSIONS_SIZE, +/*SoD*/ Constants::TYPE_POSSESSIONS_SIZE, +/*Underfoot*/ Constants::TYPE_POSSESSIONS_SIZE, +/*RoF*/ Constants::TYPE_POSSESSIONS_SIZE, +/*RoF2*/ Constants::TYPE_POSSESSIONS_SIZE, -/*NPC*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*Merc*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*Bot*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*Pet*/ EmuConstants::MAP_POSSESSIONS_SIZE +/*NPC*/ Constants::TYPE_POSSESSIONS_SIZE, +/*Merc*/ Constants::TYPE_POSSESSIONS_SIZE, +/*Bot*/ Constants::TYPE_POSSESSIONS_SIZE, +/*Pet*/ Constants::TYPE_POSSESSIONS_SIZE }, - { // local[MapBank] + { // local[TypeBank] /*Unknown*/ NOT_USED, /*62*/ NOT_USED, -/*Titanium*/ Titanium::consts::MAP_BANK_SIZE, -/*SoF*/ EmuConstants::MAP_BANK_SIZE, -/*SoD*/ EmuConstants::MAP_BANK_SIZE, -/*Underfoot*/ EmuConstants::MAP_BANK_SIZE, -/*RoF*/ EmuConstants::MAP_BANK_SIZE, -/*RoF2*/ EmuConstants::MAP_BANK_SIZE, +/*Titanium*/ Titanium::consts::TYPE_BANK_SIZE, +/*SoF*/ Constants::TYPE_BANK_SIZE, +/*SoD*/ Constants::TYPE_BANK_SIZE, +/*Underfoot*/ Constants::TYPE_BANK_SIZE, +/*RoF*/ Constants::TYPE_BANK_SIZE, +/*RoF2*/ Constants::TYPE_BANK_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, /*Bot*/ NOT_USED, /*Pet*/ NOT_USED }, - { // local[MapSharedBank] + { // local[TypeSharedBank] /*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*Titanium*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*SoF*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*SoD*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*Underfoot*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*RoF*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*RoF2*/ EmuConstants::MAP_SHARED_BANK_SIZE, +/*62*/ Constants::TYPE_SHARED_BANK_SIZE, +/*Titanium*/ Constants::TYPE_SHARED_BANK_SIZE, +/*SoF*/ Constants::TYPE_SHARED_BANK_SIZE, +/*SoD*/ Constants::TYPE_SHARED_BANK_SIZE, +/*Underfoot*/ Constants::TYPE_SHARED_BANK_SIZE, +/*RoF*/ Constants::TYPE_SHARED_BANK_SIZE, +/*RoF2*/ Constants::TYPE_SHARED_BANK_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, /*Bot*/ NOT_USED, /*Pet*/ NOT_USED }, - { // local[MapTrade] + { // local[TypeTrade] /*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_TRADE_SIZE, -/*Titanium*/ EmuConstants::MAP_TRADE_SIZE, -/*SoF*/ EmuConstants::MAP_TRADE_SIZE, -/*SoD*/ EmuConstants::MAP_TRADE_SIZE, -/*Underfoot*/ EmuConstants::MAP_TRADE_SIZE, -/*RoF*/ EmuConstants::MAP_TRADE_SIZE, -/*RoF2*/ EmuConstants::MAP_TRADE_SIZE, +/*62*/ Constants::TYPE_TRADE_SIZE, +/*Titanium*/ Constants::TYPE_TRADE_SIZE, +/*SoF*/ Constants::TYPE_TRADE_SIZE, +/*SoD*/ Constants::TYPE_TRADE_SIZE, +/*Underfoot*/ Constants::TYPE_TRADE_SIZE, +/*RoF*/ Constants::TYPE_TRADE_SIZE, +/*RoF2*/ Constants::TYPE_TRADE_SIZE, /*NPC*/ 4, /*Merc*/ 4, -/*Bot*/ EmuConstants::MAP_TRADE_SIZE, // client thinks this is another client +/*Bot*/ Constants::TYPE_TRADE_SIZE, // client thinks this is another client /*Pet*/ 4 }, - { // local[MapWorld] + { // local[TypeWorld] /*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_WORLD_SIZE, -/*Titanium*/ EmuConstants::MAP_WORLD_SIZE, -/*SoF*/ EmuConstants::MAP_WORLD_SIZE, -/*SoD*/ EmuConstants::MAP_WORLD_SIZE, -/*Underfoot*/ EmuConstants::MAP_WORLD_SIZE, -/*RoF*/ EmuConstants::MAP_WORLD_SIZE, -/*RoF2*/ EmuConstants::MAP_WORLD_SIZE, +/*62*/ Constants::TYPE_WORLD_SIZE, +/*Titanium*/ Constants::TYPE_WORLD_SIZE, +/*SoF*/ Constants::TYPE_WORLD_SIZE, +/*SoD*/ Constants::TYPE_WORLD_SIZE, +/*Underfoot*/ Constants::TYPE_WORLD_SIZE, +/*RoF*/ Constants::TYPE_WORLD_SIZE, +/*RoF2*/ Constants::TYPE_WORLD_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, /*Bot*/ NOT_USED, /*Pet*/ NOT_USED }, - { // local[MapLimbo] + { // local[TypeLimbo] /*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_LIMBO_SIZE, -/*Titanium*/ EmuConstants::MAP_LIMBO_SIZE, -/*SoF*/ EmuConstants::MAP_LIMBO_SIZE, -/*SoD*/ EmuConstants::MAP_LIMBO_SIZE, -/*Underfoot*/ EmuConstants::MAP_LIMBO_SIZE, -/*RoF*/ EmuConstants::MAP_LIMBO_SIZE, -/*RoF2*/ EmuConstants::MAP_LIMBO_SIZE, +/*62*/ Constants::TYPE_LIMBO_SIZE, +/*Titanium*/ Constants::TYPE_LIMBO_SIZE, +/*SoF*/ Constants::TYPE_LIMBO_SIZE, +/*SoD*/ Constants::TYPE_LIMBO_SIZE, +/*Underfoot*/ Constants::TYPE_LIMBO_SIZE, +/*RoF*/ Constants::TYPE_LIMBO_SIZE, +/*RoF2*/ Constants::TYPE_LIMBO_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, /*Bot*/ NOT_USED, /*Pet*/ NOT_USED }, - { // local[MapTribute] + { // local[TypeTribute] /*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*Titanium*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*SoF*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*SoD*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*Underfoot*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*RoF*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*RoF2*/ EmuConstants::MAP_TRIBUTE_SIZE, +/*62*/ Constants::TYPE_TRIBUTE_SIZE, +/*Titanium*/ Constants::TYPE_TRIBUTE_SIZE, +/*SoF*/ Constants::TYPE_TRIBUTE_SIZE, +/*SoD*/ Constants::TYPE_TRIBUTE_SIZE, +/*Underfoot*/ Constants::TYPE_TRIBUTE_SIZE, +/*RoF*/ Constants::TYPE_TRIBUTE_SIZE, +/*RoF2*/ Constants::TYPE_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapTrophyTribute] + { // local[TypeTrophyTribute] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE, +/*RoF*/ Constants::TYPE_TROPHY_TRIBUTE_SIZE, +/*RoF2*/ Constants::TYPE_TROPHY_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapGuildTribute] + { // local[TypeGuildTribute] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE, -/*RoF2*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE, +/*RoF*/ Constants::TYPE_GUILD_TRIBUTE_SIZE, +/*RoF2*/ Constants::TYPE_GUILD_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapMerchant] + { // local[TypeMerchant] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_MERCHANT_SIZE, -/*RoF2*/ EmuConstants::MAP_MERCHANT_SIZE, +/*RoF*/ Constants::TYPE_MERCHANT_SIZE, +/*RoF2*/ Constants::TYPE_MERCHANT_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapDeleted] + { // local[TypeDeleted] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_DELETED_SIZE, -/*RoF2*/ EmuConstants::MAP_DELETED_SIZE, +/*RoF*/ Constants::TYPE_DELETED_SIZE, +/*RoF2*/ Constants::TYPE_DELETED_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapCorpse] + { // local[TypeCorpse] /*Unknown*/ NOT_USED, /*62*/ NOT_USED, -/*Titanium*/ Titanium::consts::MAP_CORPSE_SIZE, -/*SoF*/ SoF::consts::MAP_CORPSE_SIZE, -/*SoD*/ SoD::consts::MAP_CORPSE_SIZE, -/*Underfoot*/ UF::consts::MAP_CORPSE_SIZE, -/*RoF*/ RoF::consts::MAP_CORPSE_SIZE, -/*RoF2*/ RoF2::consts::MAP_CORPSE_SIZE, +/*Titanium*/ Titanium::consts::TYPE_CORPSE_SIZE, +/*SoF*/ SoF::consts::TYPE_CORPSE_SIZE, +/*SoD*/ SoD::consts::TYPE_CORPSE_SIZE, +/*Underfoot*/ UF::consts::TYPE_CORPSE_SIZE, +/*RoF*/ RoF::consts::TYPE_CORPSE_SIZE, +/*RoF2*/ RoF2::consts::TYPE_CORPSE_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapBazaar] + { // local[TypeBazaar] /*Unknown*/ NOT_USED, -/*62*/ EmuConstants::MAP_BAZAAR_SIZE, -/*Titanium*/ EmuConstants::MAP_BAZAAR_SIZE, -/*SoF*/ EmuConstants::MAP_BAZAAR_SIZE, -/*SoD*/ EmuConstants::MAP_BAZAAR_SIZE, -/*Underfoot*/ EmuConstants::MAP_BAZAAR_SIZE, -/*RoF*/ EmuConstants::MAP_BAZAAR_SIZE, -/*RoF2*/ EmuConstants::MAP_BAZAAR_SIZE, +/*62*/ Constants::TYPE_BAZAAR_SIZE, +/*Titanium*/ Constants::TYPE_BAZAAR_SIZE, +/*SoF*/ Constants::TYPE_BAZAAR_SIZE, +/*SoD*/ Constants::TYPE_BAZAAR_SIZE, +/*Underfoot*/ Constants::TYPE_BAZAAR_SIZE, +/*RoF*/ Constants::TYPE_BAZAAR_SIZE, +/*RoF2*/ Constants::TYPE_BAZAAR_SIZE, -/*NPC*/ 0, // this may need to be 'EmuConstants::MAP_BAZAAR_SIZE' if offline client traders respawn as an npc +/*NPC*/ 0, // this may need to be 'Constants::TYPE_BAZAAR_SIZE' if offline client traders respawn as an npc /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapInspect] + { // local[TypeInspect] /*Unknown*/ NOT_USED, /*62*/ NOT_USED, -/*Titanium*/ Titanium::consts::MAP_INSPECT_SIZE, -/*SoF*/ SoF::consts::MAP_INSPECT_SIZE, -/*SoD*/ SoD::consts::MAP_INSPECT_SIZE, -/*Underfoot*/ UF::consts::MAP_INSPECT_SIZE, -/*RoF*/ RoF::consts::MAP_INSPECT_SIZE, -/*RoF2*/ RoF2::consts::MAP_INSPECT_SIZE, +/*Titanium*/ Titanium::consts::TYPE_INSPECT_SIZE, +/*SoF*/ SoF::consts::TYPE_INSPECT_SIZE, +/*SoD*/ SoD::consts::TYPE_INSPECT_SIZE, +/*Underfoot*/ UF::consts::TYPE_INSPECT_SIZE, +/*RoF*/ RoF::consts::TYPE_INSPECT_SIZE, +/*RoF2*/ RoF2::consts::TYPE_INSPECT_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, /*Bot*/ NOT_USED, /*Pet*/ NOT_USED }, - { // local[MapRealEstate] + { // local[TypeRealEstate] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_REAL_ESTATE_SIZE, -/*RoF2*/ EmuConstants::MAP_REAL_ESTATE_SIZE, +/*RoF*/ Constants::TYPE_REAL_ESTATE_SIZE, +/*RoF2*/ Constants::TYPE_REAL_ESTATE_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapViewMODPC] + { // local[TypeViewMODPC] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE, -/*RoF2*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE, +/*RoF*/ Constants::TYPE_VIEW_MOD_PC_SIZE, +/*RoF2*/ Constants::TYPE_VIEW_MOD_PC_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapViewMODBank] + { // local[TypeViewMODBank] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE, -/*RoF2*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE, +/*RoF*/ Constants::TYPE_VIEW_MOD_BANK_SIZE, +/*RoF2*/ Constants::TYPE_VIEW_MOD_BANK_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapViewMODSharedBank] + { // local[TypeViewMODSharedBank] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE, -/*RoF2*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE, +/*RoF*/ Constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, +/*RoF2*/ Constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapViewMODLimbo] + { // local[TypeViewMODLimbo] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE, -/*RoF2*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE, +/*RoF*/ Constants::TYPE_VIEW_MOD_LIMBO_SIZE, +/*RoF2*/ Constants::TYPE_VIEW_MOD_LIMBO_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapAltStorage] + { // local[TypeAltStorage] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_ALT_STORAGE_SIZE, -/*RoF2*/ EmuConstants::MAP_ALT_STORAGE_SIZE, +/*RoF*/ Constants::TYPE_ALT_STORAGE_SIZE, +/*RoF2*/ Constants::TYPE_ALT_STORAGE_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapArchived] + { // local[TypeArchived] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_ARCHIVED_SIZE, -/*RoF2*/ EmuConstants::MAP_ARCHIVED_SIZE, +/*RoF*/ Constants::TYPE_ARCHIVED_SIZE, +/*RoF2*/ Constants::TYPE_ARCHIVED_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapMail] + { // local[TypeMail] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_MAIL_SIZE, -/*RoF2*/ EmuConstants::MAP_MAIL_SIZE, +/*RoF*/ Constants::TYPE_MAIL_SIZE, +/*RoF2*/ Constants::TYPE_MAIL_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapGuildTrophyTribute] + { // local[TypeGuildTrophyTribute] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE, +/*RoF*/ Constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, +/*RoF2*/ Constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapKrono] + { // local[TypeKrono] /*Unknown*/ NOT_USED, /*62*/ NOT_USED, /*Titanium*/ NOT_USED, /*SoF*/ NOT_USED, /*SoD*/ NOT_USED, /*Underfoot*/ NOT_USED, -/*RoF*/ EmuConstants::MAP_KRONO_SIZE, -/*RoF2*/ EmuConstants::MAP_KRONO_SIZE, +/*RoF*/ Constants::TYPE_KRONO_SIZE, +/*RoF2*/ Constants::TYPE_KRONO_SIZE, /*NPC*/ 0, /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 }, - { // local[MapOther] + { // local[TypeOther] /*Unknown*/ NOT_USED, /*62*/ 0, /*Titanium*/ 0, /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ EmuConstants::MAP_OTHER_SIZE, -/*RoF2*/ EmuConstants::MAP_OTHER_SIZE, +/*RoF*/ Constants::TYPE_OTHER_SIZE, +/*RoF2*/ Constants::TYPE_OTHER_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -736,13 +733,13 @@ uint16 EQLimits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) } }; - if ((uint16)indexMap < _MapCount) + if ((uint16)indexMap < TypeCount) return local[indexMap][static_cast(ValidateMobClientVersion(clientVersion))]; return NOT_USED; } -uint64 EQLimits::PossessionsBitmask(ClientVersion clientVersion) +uint64 EQEmu::Limits::PossessionsBitmask(ClientVersion clientVersion) { // these are for the new inventory system (RoF)..not the current (Ti) one... // 0x0000000000200000 is SlotPowerSource (SoF+) @@ -769,7 +766,7 @@ uint64 EQLimits::PossessionsBitmask(ClientVersion clientVersion) //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint64 EQLimits::EquipmentBitmask(ClientVersion clientVersion) +uint64 EQEmu::Limits::EquipmentBitmask(ClientVersion clientVersion) { static const uint64 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, @@ -791,7 +788,7 @@ uint64 EQLimits::EquipmentBitmask(ClientVersion clientVersion) //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint64 EQLimits::GeneralBitmask(ClientVersion clientVersion) +uint64 EQEmu::Limits::GeneralBitmask(ClientVersion clientVersion) { static const uint64 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, @@ -813,7 +810,7 @@ uint64 EQLimits::GeneralBitmask(ClientVersion clientVersion) //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint64 EQLimits::CursorBitmask(ClientVersion clientVersion) +uint64 EQEmu::Limits::CursorBitmask(ClientVersion clientVersion) { static const uint64 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, @@ -835,7 +832,7 @@ uint64 EQLimits::CursorBitmask(ClientVersion clientVersion) //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -bool EQLimits::AllowsEmptyBagInBag(ClientVersion clientVersion) +bool EQEmu::Limits::AllowsEmptyBagInBag(ClientVersion clientVersion) { static const bool local[CLIENT_VERSION_COUNT] = { /*Unknown*/ false, @@ -857,7 +854,7 @@ bool EQLimits::AllowsEmptyBagInBag(ClientVersion clientVersion) //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -bool EQLimits::AllowsClickCastFromBag(ClientVersion clientVersion) +bool EQEmu::Limits::AllowsClickCastFromBag(ClientVersion clientVersion) { static const bool local[CLIENT_VERSION_COUNT] = { /*Unknown*/ false, @@ -879,49 +876,49 @@ bool EQLimits::AllowsClickCastFromBag(ClientVersion clientVersion) } // items -uint16 EQLimits::ItemCommonSize(ClientVersion clientVersion) +uint16 EQEmu::Limits::ItemCommonSize(ClientVersion clientVersion) { static const uint16 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, -/*62*/ EmuConstants::ITEM_COMMON_SIZE, -/*Titanium*/ EmuConstants::ITEM_COMMON_SIZE, -/*SoF*/ EmuConstants::ITEM_COMMON_SIZE, -/*SoD*/ EmuConstants::ITEM_COMMON_SIZE, -/*Underfoot*/ EmuConstants::ITEM_COMMON_SIZE, -/*RoF*/ EmuConstants::ITEM_COMMON_SIZE, -/*RoF2*/ EmuConstants::ITEM_COMMON_SIZE, +/*62*/ Constants::ITEM_COMMON_SIZE, +/*Titanium*/ Constants::ITEM_COMMON_SIZE, +/*SoF*/ Constants::ITEM_COMMON_SIZE, +/*SoD*/ Constants::ITEM_COMMON_SIZE, +/*Underfoot*/ Constants::ITEM_COMMON_SIZE, +/*RoF*/ Constants::ITEM_COMMON_SIZE, +/*RoF2*/ Constants::ITEM_COMMON_SIZE, -/*NPC*/ EmuConstants::ITEM_COMMON_SIZE, -/*Merc*/ EmuConstants::ITEM_COMMON_SIZE, -/*Bot*/ EmuConstants::ITEM_COMMON_SIZE, -/*Pet*/ EmuConstants::ITEM_COMMON_SIZE +/*NPC*/ Constants::ITEM_COMMON_SIZE, +/*Merc*/ Constants::ITEM_COMMON_SIZE, +/*Bot*/ Constants::ITEM_COMMON_SIZE, +/*Pet*/ Constants::ITEM_COMMON_SIZE }; return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint16 EQLimits::ItemContainerSize(ClientVersion clientVersion) +uint16 EQEmu::Limits::ItemContainerSize(ClientVersion clientVersion) { static const uint16 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, -/*62*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*Titanium*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*SoF*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*SoD*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*Underfoot*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*RoF*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*RoF2*/ EmuConstants::ITEM_CONTAINER_SIZE, +/*62*/ Constants::ITEM_CONTAINER_SIZE, +/*Titanium*/ Constants::ITEM_CONTAINER_SIZE, +/*SoF*/ Constants::ITEM_CONTAINER_SIZE, +/*SoD*/ Constants::ITEM_CONTAINER_SIZE, +/*Underfoot*/ Constants::ITEM_CONTAINER_SIZE, +/*RoF*/ Constants::ITEM_CONTAINER_SIZE, +/*RoF2*/ Constants::ITEM_CONTAINER_SIZE, -/*NPC*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*Merc*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*Bot*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*Pet*/ EmuConstants::ITEM_CONTAINER_SIZE +/*NPC*/ Constants::ITEM_CONTAINER_SIZE, +/*Merc*/ Constants::ITEM_CONTAINER_SIZE, +/*Bot*/ Constants::ITEM_CONTAINER_SIZE, +/*Pet*/ Constants::ITEM_CONTAINER_SIZE }; return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -bool EQLimits::CoinHasWeight(ClientVersion clientVersion) +bool EQEmu::Limits::CoinHasWeight(ClientVersion clientVersion) { static const bool local[CLIENT_VERSION_COUNT] = { /*Unknown*/ true, diff --git a/common/eq_dictionary.h b/common/eq_dictionary.h index 7828dd5cc..f67f2b65f 100644 --- a/common/eq_dictionary.h +++ b/common/eq_dictionary.h @@ -1,7 +1,7 @@ /* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) +Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -42,156 +42,157 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //using namespace RoF2::maps; // server inventory maps enumeration (code and database sync'd to reference) //using namespace RoF::slots; // server possessions slots enumeration (code and database sync'd to reference) -class EmuConstants -{ + +namespace EQEmu { // an immutable value is required to initialize arrays, etc... use this class as a repository for those -public: - // database - static const ClientVersion CHARACTER_CREATION_CLIENT = ClientVersion::RoF2; // adjust according to starting item placement and target client + class Constants { + public: + // database + static const ClientVersion CHARACTER_CREATION_CLIENT = ClientVersion::RoF2; // adjust according to starting item placement and target client - static const size_t CHARACTER_CREATION_LIMIT = RoF2::consts::CHARACTER_CREATION_LIMIT; + static const size_t CHARACTER_CREATION_LIMIT = RoF2::consts::CHARACTER_CREATION_LIMIT; - // inventory - static uint16 InventoryMapSize(int16 indexMap); - //static std::string InventoryLocationName(Location_Struct location); - static std::string InventoryMapName(int16 indexMap); - static std::string InventoryMainName(int16 indexMain); - static std::string InventorySubName(int16 indexSub); - static std::string InventoryAugName(int16 indexAug); + // inventory + static uint16 InventoryTypeSize(int16 type_index); + //static const char* InventoryLocationName(Location_Struct location); + static const char* InventoryTypeName(int16 type_index); + static const char* InventorySlotName(int16 slot_index); + static const char* InventorySubName(int16 sub_index); + static const char* InventoryAugName(int16 aug_index); - // these are currently hard-coded for existing inventory system..do not use in place of special client version handlers until ready - static const uint16 MAP_POSSESSIONS_SIZE = _MainCount; - static const uint16 MAP_BANK_SIZE = 24; - static const uint16 MAP_SHARED_BANK_SIZE = 2; - static const uint16 MAP_TRADE_SIZE = 8; - static const uint16 MAP_WORLD_SIZE = 10; - static const uint16 MAP_LIMBO_SIZE = 36; - static const uint16 MAP_TRIBUTE_SIZE = 5; // (need client values) - static const uint16 MAP_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_GUILD_TRIBUTE_SIZE = 0; - static const uint16 MAP_MERCHANT_SIZE = 0; - static const uint16 MAP_DELETED_SIZE = 0; - static const uint16 MAP_CORPSE_SIZE = _MainCount; // no bitmask use..limits to size of client corpse window (see EQLimits::InventoryMapSize(MapCorpse, = EmuConstants::TRADE_BEGIN && slot_id <= EmuConstants::TRADE_END) { + else if (slot_id >= EQEmu::Constants::TRADE_BEGIN && slot_id <= EQEmu::Constants::TRADE_END) { result = _GetItem(m_trade, slot_id); } - else if (slot_id >= EmuConstants::SHARED_BANK_BEGIN && slot_id <= EmuConstants::SHARED_BANK_END) { + else if (slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_END) { // Shared Bank slots result = _GetItem(m_shbank, slot_id); } - else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) { + else if (slot_id >= EQEmu::Constants::BANK_BEGIN && slot_id <= EQEmu::Constants::BANK_END) { // Bank slots result = _GetItem(m_bank, slot_id); } - else if ((slot_id >= EmuConstants::GENERAL_BEGIN && slot_id <= EmuConstants::GENERAL_END)) { + else if ((slot_id >= EQEmu::Constants::GENERAL_BEGIN && slot_id <= EQEmu::Constants::GENERAL_END)) { // Personal inventory slots result = _GetItem(m_inv, slot_id); } - else if ((slot_id >= EmuConstants::EQUIPMENT_BEGIN && slot_id <= EmuConstants::EQUIPMENT_END) || - (slot_id >= EmuConstants::TRIBUTE_BEGIN && slot_id <= EmuConstants::TRIBUTE_END) || (slot_id == MainPowerSource)) { + else if ((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::Constants::EQUIPMENT_END) || + (slot_id >= EQEmu::Constants::TRIBUTE_BEGIN && slot_id <= EQEmu::Constants::TRIBUTE_END) || (slot_id == SlotPowerSource)) { // Equippable slots (on body) result = _GetItem(m_worn, slot_id); } // Inner bag slots - else if (slot_id >= EmuConstants::TRADE_BAGS_BEGIN && slot_id <= EmuConstants::TRADE_BAGS_END) { + else if (slot_id >= EQEmu::Constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::Constants::TRADE_BAGS_END) { // Trade bag slots ItemInst* inst = _GetItem(m_trade, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EmuConstants::SHARED_BANK_BAGS_BEGIN && slot_id <= EmuConstants::SHARED_BANK_BAGS_END) { + else if (slot_id >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { // Shared Bank bag slots ItemInst* inst = _GetItem(m_shbank, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EmuConstants::BANK_BAGS_BEGIN && slot_id <= EmuConstants::BANK_BAGS_END) { + else if (slot_id >= EQEmu::Constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::BANK_BAGS_END) { // Bank bag slots ItemInst* inst = _GetItem(m_bank, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EmuConstants::CURSOR_BAG_BEGIN && slot_id <= EmuConstants::CURSOR_BAG_END) { + else if (slot_id >= EQEmu::Constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::Constants::CURSOR_BAG_END) { // Cursor bag slots ItemInst* inst = m_cursor.peek_front(); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END) { + else if (slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::Constants::GENERAL_BAGS_END) { // Personal inventory bag slots ItemInst* inst = _GetItem(m_inv, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { @@ -248,7 +248,7 @@ int16 Inventory::PutItem(int16 slot_id, const ItemInst& inst) int16 Inventory::PushCursor(const ItemInst& inst) { m_cursor.push(inst.Clone()); - return MainCursor; + return SlotCursor; } ItemInst* Inventory::GetCursorItem() @@ -314,7 +314,7 @@ bool Inventory::CheckNoDrop(int16 slot_id) { if (!inst) return false; if (!inst->GetItem()->NoDrop) return true; if (inst->GetItem()->ItemClass == 1) { - for (uint8 i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) { + for (uint8 i = SUB_BEGIN; i < EQEmu::Constants::ITEM_CONTAINER_SIZE; i++) { ItemInst* bagitem = GetItem(Inventory::CalcSlotId(slot_id, i)); if (bagitem && !bagitem->GetItem()->NoDrop) return true; @@ -329,30 +329,30 @@ ItemInst* Inventory::PopItem(int16 slot_id) { ItemInst* p = nullptr; - if (slot_id == MainCursor) { + if (slot_id == SlotCursor) { p = m_cursor.pop(); } - else if ((slot_id >= EmuConstants::EQUIPMENT_BEGIN && slot_id <= EmuConstants::EQUIPMENT_END) || (slot_id == MainPowerSource)) { + else if ((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::Constants::EQUIPMENT_END) || (slot_id == SlotPowerSource)) { p = m_worn[slot_id]; m_worn.erase(slot_id); } - else if ((slot_id >= EmuConstants::GENERAL_BEGIN && slot_id <= EmuConstants::GENERAL_END)) { + else if ((slot_id >= EQEmu::Constants::GENERAL_BEGIN && slot_id <= EQEmu::Constants::GENERAL_END)) { p = m_inv[slot_id]; m_inv.erase(slot_id); } - else if (slot_id >= EmuConstants::TRIBUTE_BEGIN && slot_id <= EmuConstants::TRIBUTE_END) { + else if (slot_id >= EQEmu::Constants::TRIBUTE_BEGIN && slot_id <= EQEmu::Constants::TRIBUTE_END) { p = m_worn[slot_id]; m_worn.erase(slot_id); } - else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) { + else if (slot_id >= EQEmu::Constants::BANK_BEGIN && slot_id <= EQEmu::Constants::BANK_END) { p = m_bank[slot_id]; m_bank.erase(slot_id); } - else if (slot_id >= EmuConstants::SHARED_BANK_BEGIN && slot_id <= EmuConstants::SHARED_BANK_END) { + else if (slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_END) { p = m_shbank[slot_id]; m_shbank.erase(slot_id); } - else if (slot_id >= EmuConstants::TRADE_BEGIN && slot_id <= EmuConstants::TRADE_END) { + else if (slot_id >= EQEmu::Constants::TRADE_BEGIN && slot_id <= EQEmu::Constants::TRADE_END) { p = m_trade[slot_id]; m_trade.erase(slot_id); } @@ -372,7 +372,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { if (ItemToTry->Stackable) { - for (int16 i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) { + for (int16 i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { ItemInst* InvItem = GetItem(i); @@ -409,7 +409,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { } } - for (int16 i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) { + for (int16 i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { ItemInst* InvItem = GetItem(i); @@ -615,14 +615,14 @@ int16 Inventory::HasItemByLoreGroup(uint32 loregroup, uint8 where) int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow) { // Check basic inventory - for (int16 i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) { + for (int16 i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { if (!GetItem(i)) // Found available slot in personal inventory return i; } if (!for_bag) { - for (int16 i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) { + for (int16 i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { const ItemInst* inst = GetItem(i); if (inst && inst->IsType(ItemClassContainer) && inst->GetItem()->BagSize >= min_size) { @@ -648,7 +648,7 @@ int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, boo if (try_cursor) { // Always room on cursor (it's a queue) // (we may wish to cap this in the future) - return MainCursor; + return SlotCursor; } // No available slots @@ -667,17 +667,17 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 1: find room for bags (caller should really ask for slots for bags first to avoid sending them to cursor..and bag item loss) if (inst->IsType(ItemClassContainer)) { - for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { if (!m_inv[free_slot]) return free_slot; } - return MainCursor; // return cursor since bags do not stack and will not fit inside other bags..yet...) + return SlotCursor; // return cursor since bags do not stack and will not fit inside other bags..yet...) } // step 2: find partial room for stackables if (inst->IsStackable()) { - for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst) @@ -687,14 +687,14 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { return free_slot; } - for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst) continue; if (main_inst->IsType(ItemClassContainer)) { // if item-specific containers already have bad items, we won't fix it here... - for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { const ItemInst* sub_inst = main_inst->GetItem(free_bag_slot); if (!sub_inst) @@ -709,13 +709,13 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 3a: find room for container-specific items (ItemClassArrow) if (inst->GetItem()->ItemType == ItemTypeArrow) { - for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst || (main_inst->GetItem()->BagType != BagTypeQuiver) || !main_inst->IsType(ItemClassContainer)) continue; - for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -724,13 +724,13 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 3b: find room for container-specific items (ItemClassSmallThrowing) if (inst->GetItem()->ItemType == ItemTypeSmallThrowing) { - for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst || (main_inst->GetItem()->BagType != BagTypeBandolier) || !main_inst->IsType(ItemClassContainer)) continue; - for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -738,21 +738,21 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { } // step 4: just find an empty slot - for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst) return free_slot; } - for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (main_inst && main_inst->IsType(ItemClassContainer)) { if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == BagTypeBandolier) || (main_inst->GetItem()->BagType == BagTypeQuiver)) continue; - for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -760,7 +760,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { } //return INVALID_INDEX; // everything else pushes to the cursor - return MainCursor; + return SlotCursor; } // Opposite of below: Get parent bag slot_id from a slot inside of bag @@ -772,20 +772,20 @@ int16 Inventory::CalcSlotId(int16 slot_id) { // parent_slot_id = EmuConstants::BANK_BEGIN + (slot_id - EmuConstants::BANK_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; //else if (slot_id >= 3100 && slot_id <= 3179) should be {3031..3110}..where did this range come from!!? (verified db save range) - if (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END) { - parent_slot_id = EmuConstants::GENERAL_BEGIN + (slot_id - EmuConstants::GENERAL_BAGS_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; + if (slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::Constants::GENERAL_BAGS_END) { + parent_slot_id = EQEmu::Constants::GENERAL_BEGIN + (slot_id - EQEmu::Constants::GENERAL_BAGS_BEGIN) / EQEmu::Constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EmuConstants::CURSOR_BAG_BEGIN && slot_id <= EmuConstants::CURSOR_BAG_END) { - parent_slot_id = MainCursor; + else if (slot_id >= EQEmu::Constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::Constants::CURSOR_BAG_END) { + parent_slot_id = SlotCursor; } - else if (slot_id >= EmuConstants::BANK_BAGS_BEGIN && slot_id <= EmuConstants::BANK_BAGS_END) { - parent_slot_id = EmuConstants::BANK_BEGIN + (slot_id - EmuConstants::BANK_BAGS_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::Constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::BANK_BAGS_END) { + parent_slot_id = EQEmu::Constants::BANK_BEGIN + (slot_id - EQEmu::Constants::BANK_BAGS_BEGIN) / EQEmu::Constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EmuConstants::SHARED_BANK_BAGS_BEGIN && slot_id <= EmuConstants::SHARED_BANK_BAGS_END) { - parent_slot_id = EmuConstants::SHARED_BANK_BEGIN + (slot_id - EmuConstants::SHARED_BANK_BAGS_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { + parent_slot_id = EQEmu::Constants::SHARED_BANK_BEGIN + (slot_id - EQEmu::Constants::SHARED_BANK_BAGS_BEGIN) / EQEmu::Constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EmuConstants::TRADE_BAGS_BEGIN && slot_id <= EmuConstants::TRADE_BAGS_END) { - parent_slot_id = EmuConstants::TRADE_BEGIN + (slot_id - EmuConstants::TRADE_BAGS_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::Constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::Constants::TRADE_BAGS_END) { + parent_slot_id = EQEmu::Constants::TRADE_BEGIN + (slot_id - EQEmu::Constants::TRADE_BAGS_BEGIN) / EQEmu::Constants::ITEM_CONTAINER_SIZE; } return parent_slot_id; @@ -798,20 +798,20 @@ int16 Inventory::CalcSlotId(int16 bagslot_id, uint8 bagidx) { int16 slot_id = INVALID_INDEX; - if (bagslot_id == MainCursor || bagslot_id == 8000) { - slot_id = EmuConstants::CURSOR_BAG_BEGIN + bagidx; + if (bagslot_id == SlotCursor || bagslot_id == 8000) { + slot_id = EQEmu::Constants::CURSOR_BAG_BEGIN + bagidx; } - else if (bagslot_id >= EmuConstants::GENERAL_BEGIN && bagslot_id <= EmuConstants::GENERAL_END) { - slot_id = EmuConstants::GENERAL_BAGS_BEGIN + (bagslot_id - EmuConstants::GENERAL_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::Constants::GENERAL_BEGIN && bagslot_id <= EQEmu::Constants::GENERAL_END) { + slot_id = EQEmu::Constants::GENERAL_BAGS_BEGIN + (bagslot_id - EQEmu::Constants::GENERAL_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE + bagidx; } - else if (bagslot_id >= EmuConstants::BANK_BEGIN && bagslot_id <= EmuConstants::BANK_END) { - slot_id = EmuConstants::BANK_BAGS_BEGIN + (bagslot_id - EmuConstants::BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::Constants::BANK_BEGIN && bagslot_id <= EQEmu::Constants::BANK_END) { + slot_id = EQEmu::Constants::BANK_BAGS_BEGIN + (bagslot_id - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE + bagidx; } - else if (bagslot_id >= EmuConstants::SHARED_BANK_BEGIN && bagslot_id <= EmuConstants::SHARED_BANK_END) { - slot_id = EmuConstants::SHARED_BANK_BAGS_BEGIN + (bagslot_id - EmuConstants::SHARED_BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && bagslot_id <= EQEmu::Constants::SHARED_BANK_END) { + slot_id = EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + (bagslot_id - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE + bagidx; } - else if (bagslot_id >= EmuConstants::TRADE_BEGIN && bagslot_id <= EmuConstants::TRADE_END) { - slot_id = EmuConstants::TRADE_BAGS_BEGIN + (bagslot_id - EmuConstants::TRADE_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::Constants::TRADE_BEGIN && bagslot_id <= EQEmu::Constants::TRADE_END) { + slot_id = EQEmu::Constants::TRADE_BAGS_BEGIN + (bagslot_id - EQEmu::Constants::TRADE_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE + bagidx; } return slot_id; @@ -824,23 +824,23 @@ uint8 Inventory::CalcBagIdx(int16 slot_id) { //else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) // index = (slot_id - EmuConstants::BANK_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; - if (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END) { - index = (slot_id - EmuConstants::GENERAL_BAGS_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; + if (slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::Constants::GENERAL_BAGS_END) { + index = (slot_id - EQEmu::Constants::GENERAL_BAGS_BEGIN) % EQEmu::Constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EmuConstants::CURSOR_BAG_BEGIN && slot_id <= EmuConstants::CURSOR_BAG_END) { - index = (slot_id - EmuConstants::CURSOR_BAG_BEGIN); // % EmuConstants::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots + else if (slot_id >= EQEmu::Constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::Constants::CURSOR_BAG_END) { + index = (slot_id - EQEmu::Constants::CURSOR_BAG_BEGIN); // % EQEmu::Constants::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots } - else if (slot_id >= EmuConstants::BANK_BAGS_BEGIN && slot_id <= EmuConstants::BANK_BAGS_END) { - index = (slot_id - EmuConstants::BANK_BAGS_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::Constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::BANK_BAGS_END) { + index = (slot_id - EQEmu::Constants::BANK_BAGS_BEGIN) % EQEmu::Constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EmuConstants::SHARED_BANK_BAGS_BEGIN && slot_id <= EmuConstants::SHARED_BANK_BAGS_END) { - index = (slot_id - EmuConstants::SHARED_BANK_BAGS_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { + index = (slot_id - EQEmu::Constants::SHARED_BANK_BAGS_BEGIN) % EQEmu::Constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EmuConstants::TRADE_BAGS_BEGIN && slot_id <= EmuConstants::TRADE_BAGS_END) { - index = (slot_id - EmuConstants::TRADE_BAGS_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::Constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::Constants::TRADE_BAGS_END) { + index = (slot_id - EQEmu::Constants::TRADE_BAGS_BEGIN) % EQEmu::Constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EmuConstants::WORLD_BEGIN && slot_id <= EmuConstants::WORLD_END) { - index = (slot_id - EmuConstants::WORLD_BEGIN); // % EmuConstants::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots + else if (slot_id >= EQEmu::Constants::WORLD_BEGIN && slot_id <= EQEmu::Constants::WORLD_END) { + index = (slot_id - EQEmu::Constants::WORLD_BEGIN); // % EQEmu::Constants::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots } return index; @@ -851,23 +851,23 @@ int16 Inventory::CalcSlotFromMaterial(uint8 material) switch (material) { case MaterialHead: - return MainHead; + return SlotHead; case MaterialChest: - return MainChest; + return SlotChest; case MaterialArms: - return MainArms; + return SlotArms; case MaterialWrist: - return MainWrist1; // there's 2 bracers, only one bracer material + return SlotWrist1; // there's 2 bracers, only one bracer material case MaterialHands: - return MainHands; + return SlotHands; case MaterialLegs: - return MainLegs; + return SlotLegs; case MaterialFeet: - return MainFeet; + return SlotFeet; case MaterialPrimary: - return MainPrimary; + return SlotPrimary; case MaterialSecondary: - return MainSecondary; + return SlotSecondary; default: return INVALID_INDEX; } @@ -877,27 +877,27 @@ uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) { switch (equipslot) { - case MainHead: + case SlotHead: return MaterialHead; - case MainChest: + case SlotChest: return MaterialChest; - case MainArms: + case SlotArms: return MaterialArms; - case MainWrist1: + case SlotWrist1: //case SLOT_BRACER02: // non-live behavior return MaterialWrist; - case MainHands: + case SlotHands: return MaterialHands; - case MainLegs: + case SlotLegs: return MaterialLegs; - case MainFeet: + case SlotFeet: return MaterialFeet; - case MainPrimary: + case SlotPrimary: return MaterialPrimary; - case MainSecondary: + case SlotSecondary: return MaterialSecondary; default: - return _MaterialInvalid; + return MaterialInvalid; } } @@ -921,13 +921,13 @@ bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_S bool Inventory::SupportsClickCasting(int16 slot_id) { // there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range - if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource) + if ((uint16)slot_id <= EQEmu::Constants::GENERAL_END || slot_id == SlotPowerSource) { return true; } - else if (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END) + else if (slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::Constants::GENERAL_BAGS_END) { - if (EQLimits::AllowsClickCastFromBag(m_version)) + if (EQEmu::Limits::AllowsClickCastFromBag(m_version)) return true; } @@ -936,7 +936,7 @@ bool Inventory::SupportsClickCasting(int16 slot_id) bool Inventory::SupportsPotionBeltCasting(int16 slot_id) { - if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource || (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END)) + if ((uint16)slot_id <= EQEmu::Constants::GENERAL_END || slot_id == SlotPowerSource || (slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::Constants::GENERAL_BAGS_END)) return true; return false; @@ -945,11 +945,11 @@ bool Inventory::SupportsPotionBeltCasting(int16 slot_id) // Test whether a given slot can support a container item bool Inventory::SupportsContainers(int16 slot_id) { - if ((slot_id == MainCursor) || - (slot_id >= EmuConstants::GENERAL_BEGIN && slot_id <= EmuConstants::GENERAL_END) || - (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) || - (slot_id >= EmuConstants::SHARED_BANK_BEGIN && slot_id <= EmuConstants::SHARED_BANK_END) || - (slot_id >= EmuConstants::TRADE_BEGIN && slot_id <= EmuConstants::TRADE_END) + if ((slot_id == SlotCursor) || + (slot_id >= EQEmu::Constants::GENERAL_BEGIN && slot_id <= EQEmu::Constants::GENERAL_END) || + (slot_id >= EQEmu::Constants::BANK_BEGIN && slot_id <= EQEmu::Constants::BANK_END) || + (slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_END) || + (slot_id >= EQEmu::Constants::TRADE_BEGIN && slot_id <= EQEmu::Constants::TRADE_END) ) { return true; } @@ -987,7 +987,7 @@ int Inventory::GetSlotByItemInst(ItemInst *inst) { } if (m_cursor.peek_front() == inst) { - return MainCursor; + return SlotCursor; } return INVALID_INDEX; @@ -998,8 +998,8 @@ uint8 Inventory::FindBrightestLightType() uint8 brightest_light_type = 0; for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { - if ((iter->first < EmuConstants::EQUIPMENT_BEGIN || iter->first > EmuConstants::EQUIPMENT_END) && iter->first != MainPowerSource) { continue; } - if (iter->first == MainAmmo) { continue; } + if ((iter->first < EQEmu::Constants::EQUIPMENT_BEGIN || iter->first > EQEmu::Constants::EQUIPMENT_END) && iter->first != SlotPowerSource) { continue; } + if (iter->first == SlotAmmo) { continue; } auto inst = iter->second; if (inst == nullptr) { continue; } @@ -1012,7 +1012,7 @@ uint8 Inventory::FindBrightestLightType() uint8 general_light_type = 0; for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) { - if (iter->first < EmuConstants::GENERAL_BEGIN || iter->first > EmuConstants::GENERAL_END) { continue; } + if (iter->first < EQEmu::Constants::GENERAL_BEGIN || iter->first > EQEmu::Constants::GENERAL_END) { continue; } auto inst = iter->second; if (inst == nullptr) { continue; } @@ -1143,33 +1143,33 @@ int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst) int16 result = INVALID_INDEX; int16 parentSlot = INVALID_INDEX; - if (slot_id == MainCursor) { + if (slot_id == SlotCursor) { // Replace current item on cursor, if exists m_cursor.pop(); // no memory delete, clients of this function know what they are doing m_cursor.push_front(inst); result = slot_id; } - else if ((slot_id >= EmuConstants::EQUIPMENT_BEGIN && slot_id <= EmuConstants::EQUIPMENT_END) || (slot_id == MainPowerSource)) { + else if ((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::Constants::EQUIPMENT_END) || (slot_id == SlotPowerSource)) { m_worn[slot_id] = inst; result = slot_id; } - else if ((slot_id >= EmuConstants::GENERAL_BEGIN && slot_id <= EmuConstants::GENERAL_END)) { + else if ((slot_id >= EQEmu::Constants::GENERAL_BEGIN && slot_id <= EQEmu::Constants::GENERAL_END)) { m_inv[slot_id] = inst; result = slot_id; } - else if (slot_id >= EmuConstants::TRIBUTE_BEGIN && slot_id <= EmuConstants::TRIBUTE_END) { + else if (slot_id >= EQEmu::Constants::TRIBUTE_BEGIN && slot_id <= EQEmu::Constants::TRIBUTE_END) { m_worn[slot_id] = inst; result = slot_id; } - else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) { + else if (slot_id >= EQEmu::Constants::BANK_BEGIN && slot_id <= EQEmu::Constants::BANK_END) { m_bank[slot_id] = inst; result = slot_id; } - else if (slot_id >= EmuConstants::SHARED_BANK_BEGIN && slot_id <= EmuConstants::SHARED_BANK_END) { + else if (slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_END) { m_shbank[slot_id] = inst; result = slot_id; } - else if (slot_id >= EmuConstants::TRADE_BEGIN && slot_id <= EmuConstants::TRADE_END) { + else if (slot_id >= EQEmu::Constants::TRADE_BEGIN && slot_id <= EQEmu::Constants::TRADE_END) { m_trade[slot_id] = inst; result = slot_id; } @@ -1207,7 +1207,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui return iter->first; } - for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) return legacy::SLOT_AUGMENT; } @@ -1224,7 +1224,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui return Inventory::CalcSlotId(iter->first, bag_iter->first); } - for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) return legacy::SLOT_AUGMENT; } @@ -1252,10 +1252,10 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) if (inst->GetID() == item_id) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); if (quantity_found >= quantity) - return MainCursor; + return SlotCursor; } - for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) return legacy::SLOT_AUGMENT; } @@ -1269,10 +1269,10 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) if (bag_inst->GetID() == item_id) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(MainCursor, bag_iter->first); + return Inventory::CalcSlotId(SlotCursor, bag_iter->first); } - for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) return legacy::SLOT_AUGMENT; } @@ -1329,7 +1329,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) if (inst->IsType(ItemClassCommon) && inst->GetItem()->ItemType == use) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); if (quantity_found >= quantity) - return MainCursor; + return SlotCursor; } if (!inst->IsType(ItemClassContainer)) { continue; } @@ -1341,7 +1341,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->ItemType == use) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(MainCursor, bag_iter->first); + return Inventory::CalcSlotId(SlotCursor, bag_iter->first); } } @@ -1361,7 +1361,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 if (inst->GetItem()->LoreGroup == loregroup) return iter->first; - for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { auto aug_inst = inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1378,7 +1378,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup) return Inventory::CalcSlotId(iter->first, bag_iter->first); - for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { auto aug_inst = bag_inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1399,9 +1399,9 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (inst == nullptr) { continue; } if (inst->GetItem()->LoreGroup == loregroup) - return MainCursor; + return SlotCursor; - for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { auto aug_inst = inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1416,9 +1416,9 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (bag_inst == nullptr) { continue; } if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup) - return Inventory::CalcSlotId(MainCursor, bag_iter->first); + return Inventory::CalcSlotId(SlotCursor, bag_iter->first); - for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { auto aug_inst = bag_inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1640,8 +1640,8 @@ bool ItemInst::IsEquipable(int16 slot_id) const // another "shouldn't do" fix..will be fixed in future updates (requires code and database work) int16 use_slot = INVALID_INDEX; - if (slot_id == MainPowerSource) { use_slot = MainGeneral1; } - if ((uint16)slot_id <= EmuConstants::EQUIPMENT_END) { use_slot = slot_id; } + if (slot_id == SlotPowerSource) { use_slot = SlotGeneral1; } + if ((uint16)slot_id <= EQEmu::Constants::EQUIPMENT_END) { use_slot = slot_id; } if (use_slot != INVALID_INDEX) { if (m_item->Slots & (1 << use_slot)) @@ -1656,7 +1656,7 @@ bool ItemInst::IsAugmentable() const if (!m_item) return false; - for (int index = 0; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { + for (int index = 0; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { if (m_item->AugSlotType[index] != NO_ITEM) return true; } @@ -1670,8 +1670,8 @@ bool ItemInst::AvailableWearSlot(uint32 aug_wear_slots) const { if (!m_item || m_item->ItemClass != ItemClassCommon) return false; - int index = EmuConstants::EQUIPMENT_BEGIN; - for (; index <= MainGeneral1; ++index) { // MainGeneral1 should be EmuConstants::EQUIPMENT_END + int index = EQEmu::Constants::EQUIPMENT_BEGIN; + for (; index <= SlotGeneral1; ++index) { // MainGeneral1 should be EQEmu::Constants::EQUIPMENT_END if (m_item->Slots & (1 << index)) { if (aug_wear_slots & (1 << index)) break; @@ -1687,13 +1687,13 @@ int8 ItemInst::AvailableAugmentSlot(int32 augtype) const return INVALID_INDEX; int index = AUG_BEGIN; - for (; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { + for (; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { if (GetItem(index)) { continue; } if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype))) break; } - return (index < EmuConstants::ITEM_COMMON_SIZE) ? index : INVALID_INDEX; + return (index < EQEmu::Constants::ITEM_COMMON_SIZE) ? index : INVALID_INDEX; } bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const @@ -1882,7 +1882,7 @@ ItemInst* ItemInst::GetOrnamentationAug(int32 ornamentationAugtype) const if (!m_item || m_item->ItemClass != ItemClassCommon) { return nullptr; } if (ornamentationAugtype == 0) { return nullptr; } - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype) { @@ -2049,7 +2049,7 @@ bool ItemInst::IsAugmented() if (!m_item || m_item->ItemClass != ItemClassCommon) return false; - for (int index = AUG_BEGIN; index < EmuConstants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { if (GetAugmentItemID(index)) return true; } @@ -2177,8 +2177,8 @@ bool ItemInst::IsSlotAllowed(int16 slot_id) const { if (!m_item) { return false; } else if (Inventory::SupportsContainers(slot_id)) { return true; } else if (m_item->Slots & (1 << slot_id)) { return true; } - else if (slot_id == MainPowerSource && (m_item->Slots & (1 << 22))) { return true; } // got lazy... - else if (slot_id != MainPowerSource && slot_id > EmuConstants::EQUIPMENT_END) { return true; } + else if (slot_id == SlotPowerSource && (m_item->Slots & (1 << 22))) { return true; } // got lazy... + else if (slot_id != SlotPowerSource && slot_id > EQEmu::Constants::EQUIPMENT_END) { return true; } else { return false; } } @@ -2330,7 +2330,7 @@ int ItemInst::GetItemArmorClass(bool augments) const if (item) { ac = item->AC; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) ac += GetAugment(i)->GetItemArmorClass(); } @@ -2372,7 +2372,7 @@ int ItemInst::GetItemElementalDamage(int &magic, int &fire, int &cold, int &pois } if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) GetAugment(i)->GetItemElementalDamage(magic, fire, cold, poison, disease, chromatic, prismatic, physical, corruption); } @@ -2389,7 +2389,7 @@ int ItemInst::GetItemElementalFlag(bool augments) const return flag; if (augments) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) { if (GetAugment(i)) flag = GetAugment(i)->GetItemElementalFlag(); if (flag) @@ -2410,7 +2410,7 @@ int ItemInst::GetItemElementalDamage(bool augments) const return damage; if (augments) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) { if (GetAugment(i)) damage = GetAugment(i)->GetItemElementalDamage(); if (damage) @@ -2429,7 +2429,7 @@ int ItemInst::GetItemRecommendedLevel(bool augments) const level = item->RecLevel; if (augments) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) { int temp = 0; if (GetAugment(i)) { temp = GetAugment(i)->GetItemRecommendedLevel(); @@ -2451,7 +2451,7 @@ int ItemInst::GetItemRequiredLevel(bool augments) const level = item->ReqLevel; if (augments) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) { int temp = 0; if (GetAugment(i)) { temp = GetAugment(i)->GetItemRequiredLevel(); @@ -2473,7 +2473,7 @@ int ItemInst::GetItemWeaponDamage(bool augments) const damage = item->Damage; if (augments) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemWeaponDamage(); } @@ -2489,7 +2489,7 @@ int ItemInst::GetItemBackstabDamage(bool augments) const damage = item->BackstabDmg; if (augments) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBackstabDamage(); } @@ -2507,7 +2507,7 @@ int ItemInst::GetItemBaneDamageBody(bool augments) const return body; if (augments) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) { body = GetAugment(i)->GetItemBaneDamageBody(); if (body) @@ -2528,7 +2528,7 @@ int ItemInst::GetItemBaneDamageRace(bool augments) const return race; if (augments) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) { race = GetAugment(i)->GetItemBaneDamageRace(); if (race) @@ -2548,7 +2548,7 @@ int ItemInst::GetItemBaneDamageBody(bodyType against, bool augments) const damage += item->BaneDmgAmt; if (augments) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBaneDamageBody(against); } @@ -2565,7 +2565,7 @@ int ItemInst::GetItemBaneDamageRace(uint16 against, bool augments) const damage += item->BaneDmgRaceAmt; if (augments) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBaneDamageRace(against); } @@ -2581,7 +2581,7 @@ int ItemInst::GetItemMagical(bool augments) const return 1; if (augments) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i) && GetAugment(i)->GetItemMagical()) return 1; } @@ -2596,7 +2596,7 @@ int ItemInst::GetItemHP(bool augments) const if (item) { hp = item->HP; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) hp += GetAugment(i)->GetItemHP(); } @@ -2610,7 +2610,7 @@ int ItemInst::GetItemMana(bool augments) const if (item) { mana = item->Mana; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) mana += GetAugment(i)->GetItemMana(); } @@ -2624,7 +2624,7 @@ int ItemInst::GetItemEndur(bool augments) const if (item) { endur = item->Endur; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) endur += GetAugment(i)->GetItemEndur(); } @@ -2638,7 +2638,7 @@ int ItemInst::GetItemAttack(bool augments) const if (item) { atk = item->Attack; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) atk += GetAugment(i)->GetItemAttack(); } @@ -2652,7 +2652,7 @@ int ItemInst::GetItemStr(bool augments) const if (item) { str = item->AStr; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) str += GetAugment(i)->GetItemStr(); } @@ -2666,7 +2666,7 @@ int ItemInst::GetItemSta(bool augments) const if (item) { sta = item->ASta; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) sta += GetAugment(i)->GetItemSta(); } @@ -2680,7 +2680,7 @@ int ItemInst::GetItemDex(bool augments) const if (item) { total = item->ADex; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemDex(); } @@ -2694,7 +2694,7 @@ int ItemInst::GetItemAgi(bool augments) const if (item) { total = item->AAgi; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemAgi(); } @@ -2708,7 +2708,7 @@ int ItemInst::GetItemInt(bool augments) const if (item) { total = item->AInt; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemInt(); } @@ -2722,7 +2722,7 @@ int ItemInst::GetItemWis(bool augments) const if (item) { total = item->AWis; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemWis(); } @@ -2736,7 +2736,7 @@ int ItemInst::GetItemCha(bool augments) const if (item) { total = item->ACha; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCha(); } @@ -2750,7 +2750,7 @@ int ItemInst::GetItemMR(bool augments) const if (item) { total = item->MR; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemMR(); } @@ -2764,7 +2764,7 @@ int ItemInst::GetItemFR(bool augments) const if (item) { total = item->FR; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemFR(); } @@ -2778,7 +2778,7 @@ int ItemInst::GetItemCR(bool augments) const if (item) { total = item->CR; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCR(); } @@ -2792,7 +2792,7 @@ int ItemInst::GetItemPR(bool augments) const if (item) { total = item->PR; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemPR(); } @@ -2806,7 +2806,7 @@ int ItemInst::GetItemDR(bool augments) const if (item) { total = item->DR; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemDR(); } @@ -2820,7 +2820,7 @@ int ItemInst::GetItemCorrup(bool augments) const if (item) { total = item->SVCorruption; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCorrup(); } @@ -2834,7 +2834,7 @@ int ItemInst::GetItemHeroicStr(bool augments) const if (item) { total = item->HeroicStr; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicStr(); } @@ -2848,7 +2848,7 @@ int ItemInst::GetItemHeroicSta(bool augments) const if (item) { total = item->HeroicSta; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicSta(); } @@ -2862,7 +2862,7 @@ int ItemInst::GetItemHeroicDex(bool augments) const if (item) { total = item->HeroicDex; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicDex(); } @@ -2876,7 +2876,7 @@ int ItemInst::GetItemHeroicAgi(bool augments) const if (item) { total = item->HeroicAgi; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicAgi(); } @@ -2890,7 +2890,7 @@ int ItemInst::GetItemHeroicInt(bool augments) const if (item) { total = item->HeroicInt; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicInt(); } @@ -2904,7 +2904,7 @@ int ItemInst::GetItemHeroicWis(bool augments) const if (item) { total = item->HeroicWis; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicWis(); } @@ -2918,7 +2918,7 @@ int ItemInst::GetItemHeroicCha(bool augments) const if (item) { total = item->HeroicCha; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCha(); } @@ -2932,7 +2932,7 @@ int ItemInst::GetItemHeroicMR(bool augments) const if (item) { total = item->HeroicMR; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicMR(); } @@ -2946,7 +2946,7 @@ int ItemInst::GetItemHeroicFR(bool augments) const if (item) { total = item->HeroicFR; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicFR(); } @@ -2960,7 +2960,7 @@ int ItemInst::GetItemHeroicCR(bool augments) const if (item) { total = item->HeroicCR; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCR(); } @@ -2974,7 +2974,7 @@ int ItemInst::GetItemHeroicPR(bool augments) const if (item) { total = item->HeroicPR; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicPR(); } @@ -2988,7 +2988,7 @@ int ItemInst::GetItemHeroicDR(bool augments) const if (item) { total = item->HeroicDR; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicDR(); } @@ -3002,7 +3002,7 @@ int ItemInst::GetItemHeroicCorrup(bool augments) const if (item) { total = item->HeroicSVCorrup; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCorrup(); } @@ -3016,7 +3016,7 @@ int ItemInst::GetItemHaste(bool augments) const if (item) { total = item->Haste; if (augments) - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) { int temp = GetAugment(i)->GetItemHaste(); if (temp > total) diff --git a/common/item_struct.h b/common/item_struct.h index 0d7505a2c..0cae9806d 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -184,9 +184,9 @@ struct Item_Struct { int32 FactionAmt4; // Faction Amt 4 char CharmFile[32]; // ? uint32 AugType; - uint8 AugSlotType[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Type - uint8 AugSlotVisible[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Visible - uint8 AugSlotUnk2[EmuConstants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related + uint8 AugSlotType[EQEmu::Constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Type + uint8 AugSlotVisible[EQEmu::Constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Visible + uint8 AugSlotUnk2[EQEmu::Constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related uint32 LDoNTheme; uint32 LDoNPrice; uint32 LDoNSold; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index b5349b617..d07281414 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -27,13 +27,13 @@ namespace RoF char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); // server to client inventory location converters - static inline structs::ItemSlotStruct ServerToRoFSlot(uint32 serverSlot); - static inline structs::MainInvItemSlotStruct ServerToRoFMainInvSlot(uint32 serverSlot); + static inline structs::InventorySlot_Struct ServerToRoFSlot(uint32 serverSlot); + static inline structs::TypelessInventorySlot_Struct ServerToRoFTypelessSlot(uint32 serverSlot); static inline uint32 ServerToRoFCorpseSlot(uint32 serverCorpseSlot); // client to server inventory location converters - static inline uint32 RoFToServerSlot(structs::ItemSlotStruct rofSlot); - static inline uint32 RoFToServerMainInvSlot(structs::MainInvItemSlotStruct rofSlot); + static inline uint32 RoFToServerSlot(structs::InventorySlot_Struct rofSlot); + static inline uint32 RoFToServerTypelessSlot(structs::TypelessInventorySlot_Struct rofSlot); static inline uint32 RoFToServerCorpseSlot(uint32 rofCorpseSlot); // server to client text link converter @@ -162,7 +162,7 @@ namespace RoF eq->unknown000 = 1; OUT(npcid); - eq->slot = ServerToRoFMainInvSlot(emu->slot); + eq->inventory_slot = ServerToRoFTypelessSlot(emu->slot); OUT(charges); OUT(sell_price); @@ -214,7 +214,7 @@ namespace RoF SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); OUT(merchant_entity_id); - eq->slot_id = ServerToRoFMainInvSlot(emu->slot_id); + eq->inventory_slot = ServerToRoFTypelessSlot(emu->slot_id); OUT(charges); OUT(cost); @@ -238,7 +238,7 @@ namespace RoF ENCODE_LENGTH_EXACT(ApplyPoison_Struct); SETUP_DIRECT_ENCODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - eq->inventorySlot = ServerToRoFMainInvSlot(emu->inventorySlot); + eq->inventory_slot = ServerToRoFTypelessSlot(emu->inventorySlot); OUT(success); FINISH_ENCODE(); @@ -481,7 +481,7 @@ namespace RoF OUT(slot); OUT(spell_id); - eq->inventoryslot = ServerToRoFSlot(emu->inventoryslot); + eq->inventory_slot = ServerToRoFSlot(emu->inventoryslot); //OUT(inventoryslot); OUT(target_id); @@ -1536,7 +1536,7 @@ namespace RoF ENCODE_LENGTH_EXACT(ItemVerifyReply_Struct); SETUP_DIRECT_ENCODE(ItemVerifyReply_Struct, structs::ItemVerifyReply_Struct); - eq->slot = ServerToRoFSlot(emu->slot); + eq->inventory_slot = ServerToRoFSlot(emu->slot); OUT(spell); OUT(target); @@ -2342,7 +2342,7 @@ namespace RoF outapp->WriteUInt32(consts::BANDOLIERS_SIZE); // Copy bandoliers where server and client indexes converge - for (uint32 r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(emu->bandoliers[r].Name); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(emu->bandoliers[r].Items[j].Name); @@ -2357,7 +2357,7 @@ namespace RoF } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (uint32 r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(""); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(""); @@ -2369,7 +2369,7 @@ namespace RoF outapp->WriteUInt32(consts::POTION_BELT_ITEM_COUNT); // Copy potion belt where server and client indexes converge - for (uint32 r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(emu->potionbelt.Items[r].Name); outapp->WriteUInt32(emu->potionbelt.Items[r].ID); if (emu->potionbelt.Items[r].Icon) { @@ -2381,7 +2381,7 @@ namespace RoF } } // Nullify potion belt where server and client indexes diverge, with a client bias - for (uint32 r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(""); outapp->WriteUInt32(0); outapp->WriteSInt32(-1); @@ -2502,9 +2502,9 @@ namespace RoF outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt32(EmuConstants::TRIBUTE_SIZE); + outapp->WriteUInt32(EQEmu::Constants::TRIBUTE_SIZE); - for (uint32 r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) + for (uint32 r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { outapp->WriteUInt32(emu->tributes[r].tribute); outapp->WriteUInt32(emu->tributes[r].tier); @@ -2820,12 +2820,12 @@ namespace RoF OUT(object_type); OUT(some_id); eq->container_slot = ServerToRoFSlot(emu->unknown1); - structs::ItemSlotStruct RoFSlot; - RoFSlot.SlotType = 8; // Observed + structs::InventorySlot_Struct RoFSlot; + RoFSlot.Type = 8; // Observed RoFSlot.Unknown02 = 0; - RoFSlot.MainSlot = 0xffff; - RoFSlot.SubSlot = 0xffff; - RoFSlot.AugSlot = 0xffff; + RoFSlot.Slot = 0xffff; + RoFSlot.Sub = 0xffff; + RoFSlot.Aug = 0xffff; RoFSlot.Unknown01 = 0; eq->unknown_slot = RoFSlot; OUT(recipe_id); @@ -3037,7 +3037,7 @@ namespace RoF eq_cse->Gender = emu_cse->Gender; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < MaterialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -3154,7 +3154,7 @@ namespace RoF SETUP_DIRECT_ENCODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); OUT(npcid); - eq->itemslot = ServerToRoFMainInvSlot(emu->itemslot); + eq->inventory_slot = ServerToRoFTypelessSlot(emu->itemslot); //OUT(itemslot); OUT(quantity); OUT(price); @@ -3679,7 +3679,7 @@ namespace RoF ENCODE_LENGTH_EXACT(TributeItem_Struct); SETUP_DIRECT_ENCODE(TributeItem_Struct, structs::TributeItem_Struct); - eq->slot = ServerToRoFSlot(emu->slot); + eq->inventory_slot = ServerToRoFSlot(emu->slot); OUT(quantity); OUT(tribute_master_id); OUT(tribute_points); @@ -4164,7 +4164,7 @@ namespace RoF SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); IN(npcid); - emu->slot = RoFToServerMainInvSlot(eq->slot); + emu->slot = RoFToServerTypelessSlot(eq->inventory_slot); IN(charges); IN(sell_price); @@ -4177,7 +4177,7 @@ namespace RoF SETUP_DIRECT_DECODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); IN(merchant_entity_id); - emu->slot_id = RoFToServerMainInvSlot(eq->slot_id); + emu->slot_id = RoFToServerTypelessSlot(eq->inventory_slot); IN(charges); IN(cost); @@ -4190,7 +4190,7 @@ namespace RoF SETUP_DIRECT_DECODE(AltCurrencySelectItem_Struct, structs::AltCurrencySelectItem_Struct); IN(merchant_entity_id); - emu->slot_id = RoFToServerMainInvSlot(eq->slot_id); + emu->slot_id = RoFToServerTypelessSlot(eq->inventory_slot); FINISH_DIRECT_DECODE(); } @@ -4212,7 +4212,7 @@ namespace RoF DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); SETUP_DIRECT_DECODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - emu->inventorySlot = RoFToServerMainInvSlot(eq->inventorySlot); + emu->inventorySlot = RoFToServerTypelessSlot(eq->inventory_slot); IN(success); FINISH_DIRECT_DECODE(); @@ -4321,7 +4321,7 @@ namespace RoF IN(slot); IN(spell_id); - emu->inventoryslot = RoFToServerSlot(eq->inventoryslot); + emu->inventoryslot = RoFToServerSlot(eq->inventory_slot); //IN(inventoryslot); IN(target_id); @@ -4449,7 +4449,7 @@ namespace RoF DECODE_LENGTH_EXACT(structs::Consume_Struct); SETUP_DIRECT_DECODE(Consume_Struct, structs::Consume_Struct); - emu->slot = RoFToServerSlot(eq->slot); + emu->slot = RoFToServerSlot(eq->inventory_slot); IN(auto_consumed); IN(type); @@ -4810,7 +4810,7 @@ namespace RoF IN(item_id); int r; - for (r = 0; r < EmuConstants::ITEM_COMMON_SIZE; r++) { + for (r = 0; r < EQEmu::Constants::ITEM_COMMON_SIZE; r++) { IN(augments[r]); } // Max Augs is now 6, but no code to support that many yet @@ -4825,7 +4825,7 @@ namespace RoF DECODE_LENGTH_EXACT(structs::ItemVerifyRequest_Struct); SETUP_DIRECT_DECODE(ItemVerifyRequest_Struct, structs::ItemVerifyRequest_Struct); - emu->slot = RoFToServerSlot(eq->slot); + emu->slot = RoFToServerSlot(eq->inventory_slot); IN(target); FINISH_DIRECT_DECODE(); @@ -4866,7 +4866,7 @@ namespace RoF SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot); - Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); + Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.Type, eq->to_slot.Type, eq->from_slot.Slot, eq->to_slot.Slot, eq->from_slot.Sub, eq->to_slot.Sub, eq->from_slot.Aug, eq->to_slot.Aug, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); emu->from_slot = RoFToServerSlot(eq->from_slot); emu->to_slot = RoFToServerSlot(eq->to_slot); IN(number_in_stack); @@ -5015,7 +5015,7 @@ namespace RoF SETUP_DIRECT_DECODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); IN(npcid); - emu->itemslot = RoFToServerMainInvSlot(eq->itemslot); + emu->itemslot = RoFToServerTypelessSlot(eq->inventory_slot); //IN(itemslot); IN(quantity); IN(price); @@ -5114,7 +5114,7 @@ namespace RoF DECODE_LENGTH_EXACT(structs::TributeItem_Struct); SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); - emu->slot = RoFToServerSlot(eq->slot); + emu->slot = RoFToServerSlot(eq->inventory_slot); IN(quantity); IN(tribute_master_id); IN(tribute_points); @@ -5214,12 +5214,12 @@ namespace RoF hdr.stacksize = stackable ? charges : 1; hdr.unknown004 = 0; - structs::ItemSlotStruct slot_id = ServerToRoFSlot(slot_id_in); + structs::InventorySlot_Struct slot_id = ServerToRoFSlot(slot_id_in); - hdr.slot_type = (merchant_slot == 0) ? slot_id.SlotType : 9; // 9 is merchant 20 is reclaim items? - hdr.main_slot = (merchant_slot == 0) ? slot_id.MainSlot : merchant_slot; - hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubSlot : 0xffff; - hdr.unknown013 = (merchant_slot == 0) ? slot_id.AugSlot : 0xffff; + hdr.slot_type = (merchant_slot == 0) ? slot_id.Type : 9; // 9 is merchant 20 is reclaim items? + hdr.main_slot = (merchant_slot == 0) ? slot_id.Slot : merchant_slot; + hdr.sub_slot = (merchant_slot == 0) ? slot_id.Sub : 0xffff; + hdr.unknown013 = (merchant_slot == 0) ? slot_id.Aug : 0xffff; hdr.price = inst->GetPrice(); hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); //hdr.merchant_slot = (merchant_slot == 0) ? 1 : 0xffffffff; @@ -5678,7 +5678,7 @@ namespace RoF uint32 SubLengths[10]; - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -5690,15 +5690,15 @@ namespace RoF iqbs.subitem_count++; - if (slot_id_in >= EmuConstants::GENERAL_BEGIN && slot_id_in <= EmuConstants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::Constants::GENERAL_BEGIN && slot_id_in <= EQEmu::Constants::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EmuConstants::BANK_BEGIN && slot_id_in <= EmuConstants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::Constants::BANK_BEGIN && slot_id_in <= EQEmu::Constants::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EmuConstants::SHARED_BANK_BEGIN && slot_id_in <= EmuConstants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::Constants::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::SHARED_BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -5713,7 +5713,7 @@ namespace RoF ss.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { if (SubSerializations[x]) { @@ -5733,30 +5733,30 @@ namespace RoF return item_serial; } - static inline structs::ItemSlotStruct ServerToRoFSlot(uint32 serverSlot) + static inline structs::InventorySlot_Struct ServerToRoFSlot(uint32 serverSlot) { - structs::ItemSlotStruct RoFSlot; - RoFSlot.SlotType = INVALID_INDEX; + structs::InventorySlot_Struct RoFSlot; + RoFSlot.Type = INVALID_INDEX; RoFSlot.Unknown02 = NOT_USED; - RoFSlot.MainSlot = INVALID_INDEX; - RoFSlot.SubSlot = INVALID_INDEX; - RoFSlot.AugSlot = INVALID_INDEX; + RoFSlot.Slot = INVALID_INDEX; + RoFSlot.Sub = INVALID_INDEX; + RoFSlot.Aug = INVALID_INDEX; RoFSlot.Unknown01 = NOT_USED; uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == MainPowerSource) { // Main Inventory and Cursor - RoFSlot.SlotType = maps::MapPossessions; - RoFSlot.MainSlot = serverSlot; + if (serverSlot < 56 || serverSlot == SlotPowerSource) { // Main Inventory and Cursor + RoFSlot.Type = inventory::TypePossessions; + RoFSlot.Slot = serverSlot; - if (serverSlot == MainPowerSource) - RoFSlot.MainSlot = slots::MainPowerSource; + if (serverSlot == SlotPowerSource) + RoFSlot.Slot = inventory::SlotPowerSource; - else if (serverSlot >= MainCursor) // Cursor and Extended Corpse Inventory - RoFSlot.MainSlot += 3; + else if (serverSlot >= SlotCursor) // Cursor and Extended Corpse Inventory + RoFSlot.Slot += 3; - else if (serverSlot >= MainAmmo) // (> 20) - RoFSlot.MainSlot += 1; + else if (serverSlot >= SlotAmmo) // (> 20) + RoFSlot.Slot += 1; } /*else if (ServerSlot < 51) { // Cursor Buffer @@ -5764,51 +5764,51 @@ namespace RoF RoFSlot.MainSlot = ServerSlot - 31; }*/ - else if (serverSlot >= EmuConstants::GENERAL_BAGS_BEGIN && serverSlot <= EmuConstants::CURSOR_BAG_END) { // (> 250 && < 341) - RoFSlot.SlotType = maps::MapPossessions; + else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) { // (> 250 && < 341) + RoFSlot.Type = inventory::TypePossessions; TempSlot = serverSlot - 1; - RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 2; - RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 2) * EmuConstants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 2; + RoFSlot.Sub = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::Constants::ITEM_CONTAINER_SIZE); - if (RoFSlot.MainSlot >= slots::MainGeneral9) // (> 30) - RoFSlot.MainSlot = slots::MainCursor; + if (RoFSlot.Slot >= inventory::SlotGeneral9) // (> 30) + RoFSlot.Slot = inventory::SlotCursor; } - else if (serverSlot >= EmuConstants::TRIBUTE_BEGIN && serverSlot <= EmuConstants::TRIBUTE_END) { // Tribute - RoFSlot.SlotType = maps::MapTribute; - RoFSlot.MainSlot = serverSlot - EmuConstants::TRIBUTE_BEGIN; + else if (serverSlot >= EQEmu::Constants::TRIBUTE_BEGIN && serverSlot <= EQEmu::Constants::TRIBUTE_END) { // Tribute + RoFSlot.Type = inventory::TypeTribute; + RoFSlot.Slot = serverSlot - EQEmu::Constants::TRIBUTE_BEGIN; } - else if (serverSlot >= EmuConstants::BANK_BEGIN && serverSlot <= EmuConstants::BANK_BAGS_END) { - RoFSlot.SlotType = maps::MapBank; - TempSlot = serverSlot - EmuConstants::BANK_BEGIN; - RoFSlot.MainSlot = TempSlot; + else if (serverSlot >= EQEmu::Constants::BANK_BEGIN && serverSlot <= EQEmu::Constants::BANK_BAGS_END) { + RoFSlot.Type = inventory::TypeBank; + TempSlot = serverSlot - EQEmu::Constants::BANK_BEGIN; + RoFSlot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.Sub = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EmuConstants::SHARED_BANK_BEGIN && serverSlot <= EmuConstants::SHARED_BANK_BAGS_END) { - RoFSlot.SlotType = maps::MapSharedBank; - TempSlot = serverSlot - EmuConstants::SHARED_BANK_BEGIN; - RoFSlot.MainSlot = TempSlot; + else if (serverSlot >= EQEmu::Constants::SHARED_BANK_BEGIN && serverSlot <= EQEmu::Constants::SHARED_BANK_BAGS_END) { + RoFSlot.Type = inventory::TypeSharedBank; + TempSlot = serverSlot - EQEmu::Constants::SHARED_BANK_BEGIN; + RoFSlot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.Sub = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EmuConstants::TRADE_BEGIN && serverSlot <= EmuConstants::TRADE_BAGS_END) { - RoFSlot.SlotType = maps::MapTrade; - TempSlot = serverSlot - EmuConstants::TRADE_BEGIN; - RoFSlot.MainSlot = TempSlot; + else if (serverSlot >= EQEmu::Constants::TRADE_BEGIN && serverSlot <= EQEmu::Constants::TRADE_BAGS_END) { + RoFSlot.Type = inventory::TypeTrade; + TempSlot = serverSlot - EQEmu::Constants::TRADE_BEGIN; + RoFSlot.Slot = TempSlot; if (TempSlot > 30) { - RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.Sub = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); } /* @@ -5825,38 +5825,38 @@ namespace RoF */ } - else if (serverSlot >= EmuConstants::WORLD_BEGIN && serverSlot <= EmuConstants::WORLD_END) { - RoFSlot.SlotType = maps::MapWorld; - TempSlot = serverSlot - EmuConstants::WORLD_BEGIN; - RoFSlot.MainSlot = TempSlot; + else if (serverSlot >= EQEmu::Constants::WORLD_BEGIN && serverSlot <= EQEmu::Constants::WORLD_END) { + RoFSlot.Type = inventory::TypeWorld; + TempSlot = serverSlot - EQEmu::Constants::WORLD_BEGIN; + RoFSlot.Slot = TempSlot; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoFSlot.SlotType, RoFSlot.Unknown02, RoFSlot.MainSlot, RoFSlot.SubSlot, RoFSlot.AugSlot, RoFSlot.Unknown01); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoFSlot.Type, RoFSlot.Unknown02, RoFSlot.Slot, RoFSlot.Sub, RoFSlot.Aug, RoFSlot.Unknown01); return RoFSlot; } - static inline structs::MainInvItemSlotStruct ServerToRoFMainInvSlot(uint32 serverSlot) + static inline structs::TypelessInventorySlot_Struct ServerToRoFTypelessSlot(uint32 serverSlot) { - structs::MainInvItemSlotStruct RoFSlot; - RoFSlot.MainSlot = INVALID_INDEX; - RoFSlot.SubSlot = INVALID_INDEX; - RoFSlot.AugSlot = INVALID_INDEX; + structs::TypelessInventorySlot_Struct RoFSlot; + RoFSlot.Slot = INVALID_INDEX; + RoFSlot.Sub = INVALID_INDEX; + RoFSlot.Aug = INVALID_INDEX; RoFSlot.Unknown01 = NOT_USED; uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == MainPowerSource) { // (< 52) - RoFSlot.MainSlot = serverSlot; + if (serverSlot < 56 || serverSlot == SlotPowerSource) { // (< 52) + RoFSlot.Slot = serverSlot; - if (serverSlot == MainPowerSource) - RoFSlot.MainSlot = slots::MainPowerSource; + if (serverSlot == SlotPowerSource) + RoFSlot.Slot = inventory::SlotPowerSource; - else if (serverSlot >= MainCursor) // Cursor and Extended Corpse Inventory - RoFSlot.MainSlot += 3; + else if (serverSlot >= SlotCursor) // Cursor and Extended Corpse Inventory + RoFSlot.Slot += 3; - else if (serverSlot >= MainAmmo) // Ammo and Personl Inventory - RoFSlot.MainSlot += 1; + else if (serverSlot >= SlotAmmo) // Ammo and Personl Inventory + RoFSlot.Slot += 1; /*else if (ServerSlot >= MainCursor) { // Cursor RoFSlot.MainSlot = slots::MainCursor; @@ -5866,13 +5866,13 @@ namespace RoF }*/ } - else if (serverSlot >= EmuConstants::GENERAL_BAGS_BEGIN && serverSlot <= EmuConstants::CURSOR_BAG_END) { + else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) { TempSlot = serverSlot - 1; - RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 2; - RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 2) * EmuConstants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 2; + RoFSlot.Sub = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::Constants::ITEM_CONTAINER_SIZE); } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoFSlot.MainSlot, RoFSlot.SubSlot, RoFSlot.AugSlot, RoFSlot.Unknown01); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoFSlot.Slot, RoFSlot.Sub, RoFSlot.Aug, RoFSlot.Unknown01); return RoFSlot; } @@ -5882,17 +5882,17 @@ namespace RoF return (serverCorpseSlot + 1); } - static inline uint32 RoFToServerSlot(structs::ItemSlotStruct rofSlot) + static inline uint32 RoFToServerSlot(structs::InventorySlot_Struct rofSlot) { uint32 ServerSlot = INVALID_INDEX; uint32 TempSlot = 0; - if (rofSlot.SlotType == maps::MapPossessions && rofSlot.MainSlot < 57) { // Worn/Personal Inventory and Cursor (< 51) - if (rofSlot.MainSlot == slots::MainPowerSource) - TempSlot = MainPowerSource; + if (rofSlot.Type == inventory::TypePossessions && rofSlot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 51) + if (rofSlot.Slot == inventory::SlotPowerSource) + TempSlot = SlotPowerSource; - else if (rofSlot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory - TempSlot = rofSlot.MainSlot - 3; + else if (rofSlot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory + TempSlot = rofSlot.Slot - 3; /*else if (RoFSlot.MainSlot == slots::MainGeneral9 || RoFSlot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF inventory/corpse slots // Need to figure out what to do when we get these @@ -5905,61 +5905,61 @@ namespace RoF // For now, it's probably best to leave as-is and let this work itself out in the inventory rework. }*/ - else if (rofSlot.MainSlot >= slots::MainAmmo) // Ammo and Main Inventory - TempSlot = rofSlot.MainSlot - 1; + else if (rofSlot.Slot >= inventory::SlotAmmo) // Ammo and Main Inventory + TempSlot = rofSlot.Slot - 1; else // Worn Slots - TempSlot = rofSlot.MainSlot; + TempSlot = rofSlot.Slot; - if (rofSlot.SubSlot >= SUB_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + rofSlot.SubSlot + 1; + if (rofSlot.Sub >= SUB_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rofSlot.Sub + 1; ServerSlot = TempSlot; } - else if (rofSlot.SlotType == maps::MapBank) { - TempSlot = EmuConstants::BANK_BEGIN; + else if (rofSlot.Type == inventory::TypeBank) { + TempSlot = EQEmu::Constants::BANK_BEGIN; - if (rofSlot.SubSlot >= SUB_BEGIN) - TempSlot += ((rofSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + rofSlot.SubSlot + 1; + if (rofSlot.Sub >= SUB_BEGIN) + TempSlot += ((rofSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rofSlot.Sub + 1; else - TempSlot += rofSlot.MainSlot; + TempSlot += rofSlot.Slot; ServerSlot = TempSlot; } - else if (rofSlot.SlotType == maps::MapSharedBank) { - TempSlot = EmuConstants::SHARED_BANK_BEGIN; + else if (rofSlot.Type == inventory::TypeSharedBank) { + TempSlot = EQEmu::Constants::SHARED_BANK_BEGIN; - if (rofSlot.SubSlot >= SUB_BEGIN) - TempSlot += ((rofSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + rofSlot.SubSlot + 1; + if (rofSlot.Sub >= SUB_BEGIN) + TempSlot += ((rofSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rofSlot.Sub + 1; else - TempSlot += rofSlot.MainSlot; + TempSlot += rofSlot.Slot; ServerSlot = TempSlot; } - else if (rofSlot.SlotType == maps::MapTrade) { - TempSlot = EmuConstants::TRADE_BEGIN; + else if (rofSlot.Type == inventory::TypeTrade) { + TempSlot = EQEmu::Constants::TRADE_BEGIN; - if (rofSlot.SubSlot >= SUB_BEGIN) - TempSlot += ((rofSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + rofSlot.SubSlot + 1; + if (rofSlot.Sub >= SUB_BEGIN) + TempSlot += ((rofSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rofSlot.Sub + 1; // OLD CODE: - //TempSlot += 100 + (RoFSlot.MainSlot * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot; + //TempSlot += 100 + (RoFSlot.MainSlot * EQEmu::Constants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot; else - TempSlot += rofSlot.MainSlot; + TempSlot += rofSlot.Slot; ServerSlot = TempSlot; } - else if (rofSlot.SlotType == maps::MapWorld) { - TempSlot = EmuConstants::WORLD_BEGIN; + else if (rofSlot.Type == inventory::TypeWorld) { + TempSlot = EQEmu::Constants::WORLD_BEGIN; - if (rofSlot.MainSlot >= SUB_BEGIN) - TempSlot += rofSlot.MainSlot; + if (rofSlot.Slot >= SUB_BEGIN) + TempSlot += rofSlot.Slot; ServerSlot = TempSlot; } @@ -5973,26 +5973,26 @@ namespace RoF ServerSlot = TempSlot; }*/ - else if (rofSlot.SlotType == maps::MapGuildTribute) { + else if (rofSlot.Type == inventory::TypeGuildTribute) { ServerSlot = INVALID_INDEX; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rofSlot.SlotType, rofSlot.Unknown02, rofSlot.MainSlot, rofSlot.SubSlot, rofSlot.AugSlot, rofSlot.Unknown01, ServerSlot); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rofSlot.Type, rofSlot.Unknown02, rofSlot.Slot, rofSlot.Sub, rofSlot.Aug, rofSlot.Unknown01, ServerSlot); return ServerSlot; } - static inline uint32 RoFToServerMainInvSlot(structs::MainInvItemSlotStruct rofSlot) + static inline uint32 RoFToServerTypelessSlot(structs::TypelessInventorySlot_Struct rofSlot) { uint32 ServerSlot = INVALID_INDEX; uint32 TempSlot = 0; - if (rofSlot.MainSlot < 57) { // Worn/Personal Inventory and Cursor (< 33) - if (rofSlot.MainSlot == slots::MainPowerSource) - TempSlot = MainPowerSource; + if (rofSlot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 33) + if (rofSlot.Slot == inventory::SlotPowerSource) + TempSlot = SlotPowerSource; - else if (rofSlot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory - TempSlot = rofSlot.MainSlot - 3; + else if (rofSlot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory + TempSlot = rofSlot.Slot - 3; /*else if (RoFSlot.MainSlot == slots::MainGeneral9 || RoFSlot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF inventory slots // Need to figure out what to do when we get these @@ -6000,19 +6000,19 @@ namespace RoF // Same as above }*/ - else if (rofSlot.MainSlot >= slots::MainAmmo) // Main Inventory and Ammo Slots - TempSlot = rofSlot.MainSlot - 1; + else if (rofSlot.Slot >= inventory::SlotAmmo) // Main Inventory and Ammo Slots + TempSlot = rofSlot.Slot - 1; else - TempSlot = rofSlot.MainSlot; + TempSlot = rofSlot.Slot; - if (rofSlot.SubSlot >= SUB_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + rofSlot.SubSlot + 1; + if (rofSlot.Sub >= SUB_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rofSlot.Sub + 1; ServerSlot = TempSlot; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rofSlot.MainSlot, rofSlot.SubSlot, rofSlot.AugSlot, rofSlot.Unknown01, ServerSlot); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rofSlot.Slot, rofSlot.Sub, rofSlot.Aug, rofSlot.Unknown01, ServerSlot); return ServerSlot; } @@ -6024,7 +6024,7 @@ namespace RoF static inline void ServerToRoFTextLink(std::string& rofTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { rofTextLink = serverTextLink; return; } @@ -6033,7 +6033,7 @@ namespace RoF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { rofTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -6063,7 +6063,7 @@ namespace RoF static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink) { - if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find('\x12') == std::string::npos)) { serverTextLink = rofTextLink; return; } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 1724b8167..776554cd3 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -27,13 +27,13 @@ namespace RoF2 char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth, ItemPacketType packet_type); // server to client inventory location converters - static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType = ItemPacketInvalid); - static inline structs::MainInvItemSlotStruct ServerToRoF2MainInvSlot(uint32 serverSlot); + static inline structs::InventorySlot_Struct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType = ItemPacketInvalid); + static inline structs::TypelessInventorySlot_Struct ServerToRoF2TypelessSlot(uint32 serverSlot); static inline uint32 ServerToRoF2CorpseSlot(uint32 serverCorpseSlot); // client to server inventory location converters - static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct rof2Slot, ItemPacketType PacketType = ItemPacketInvalid); - static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct rof2Slot); + static inline uint32 RoF2ToServerSlot(structs::InventorySlot_Struct rof2Slot, ItemPacketType PacketType = ItemPacketInvalid); + static inline uint32 RoF2ToServerTypelessSlot(structs::TypelessInventorySlot_Struct rof2Slot); static inline uint32 RoF2ToServerCorpseSlot(uint32 rof2CorpseSlot); // server to client text link converter @@ -228,7 +228,7 @@ namespace RoF2 eq->unknown000 = 1; OUT(npcid); - eq->slot = ServerToRoF2MainInvSlot(emu->slot); + eq->inventory_slot = ServerToRoF2TypelessSlot(emu->slot); OUT(charges); OUT(sell_price); @@ -280,7 +280,7 @@ namespace RoF2 SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); OUT(merchant_entity_id); - eq->slot_id = ServerToRoF2MainInvSlot(emu->slot_id); + eq->inventory_slot = ServerToRoF2TypelessSlot(emu->slot_id); OUT(charges); OUT(cost); @@ -304,7 +304,7 @@ namespace RoF2 ENCODE_LENGTH_EXACT(ApplyPoison_Struct); SETUP_DIRECT_ENCODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - eq->inventorySlot = ServerToRoF2MainInvSlot(emu->inventorySlot); + eq->inventorySlot = ServerToRoF2TypelessSlot(emu->inventorySlot); OUT(success); FINISH_ENCODE(); @@ -552,7 +552,7 @@ namespace RoF2 OUT(slot); OUT(spell_id); - eq->inventoryslot = ServerToRoF2Slot(emu->inventoryslot); + eq->inventory_slot = ServerToRoF2Slot(emu->inventoryslot); //OUT(inventoryslot); OUT(target_id); @@ -1607,7 +1607,7 @@ namespace RoF2 ENCODE_LENGTH_EXACT(ItemVerifyReply_Struct); SETUP_DIRECT_ENCODE(ItemVerifyReply_Struct, structs::ItemVerifyReply_Struct); - eq->slot = ServerToRoF2Slot(emu->slot); + eq->inventory_slot = ServerToRoF2Slot(emu->slot); OUT(spell); OUT(target); @@ -2421,7 +2421,7 @@ namespace RoF2 outapp->WriteUInt32(consts::BANDOLIERS_SIZE); // Copy bandoliers where server and client indexes converge - for (uint32 r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(emu->bandoliers[r].Name); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(emu->bandoliers[r].Items[j].Name); @@ -2436,7 +2436,7 @@ namespace RoF2 } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (uint32 r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(""); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(""); @@ -2448,7 +2448,7 @@ namespace RoF2 outapp->WriteUInt32(consts::POTION_BELT_ITEM_COUNT); // Copy potion belt where server and client indexes converge - for (uint32 r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(emu->potionbelt.Items[r].Name); outapp->WriteUInt32(emu->potionbelt.Items[r].ID); if (emu->potionbelt.Items[r].Icon) { @@ -2460,7 +2460,7 @@ namespace RoF2 } } // Nullify potion belt where server and client indexes diverge, with a client bias - for (uint32 r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(""); outapp->WriteUInt32(0); outapp->WriteSInt32(-1); @@ -2577,9 +2577,9 @@ namespace RoF2 outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt32(EmuConstants::TRIBUTE_SIZE); + outapp->WriteUInt32(EQEmu::Constants::TRIBUTE_SIZE); - for (uint32 r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) + for (uint32 r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { outapp->WriteUInt32(emu->tributes[r].tribute); outapp->WriteUInt32(emu->tributes[r].tier); @@ -2910,12 +2910,12 @@ namespace RoF2 OUT(object_type); OUT(some_id); eq->container_slot = ServerToRoF2Slot(emu->unknown1); - structs::ItemSlotStruct RoF2Slot; - RoF2Slot.SlotType = 8; // Observed + structs::InventorySlot_Struct RoF2Slot; + RoF2Slot.Type = 8; // Observed RoF2Slot.Unknown02 = 0; - RoF2Slot.MainSlot = 0xffff; - RoF2Slot.SubSlot = 0xffff; - RoF2Slot.AugSlot = 0xffff; + RoF2Slot.Slot = 0xffff; + RoF2Slot.Sub = 0xffff; + RoF2Slot.Aug = 0xffff; RoF2Slot.Unknown01 = 0; eq->unknown_slot = RoF2Slot; OUT(recipe_id); @@ -3126,7 +3126,7 @@ namespace RoF2 eq_cse->Gender = emu_cse->Gender; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < MaterialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -3225,7 +3225,7 @@ namespace RoF2 SETUP_DIRECT_ENCODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); OUT(npcid); - eq->itemslot = ServerToRoF2MainInvSlot(emu->itemslot); + eq->inventory_slot = ServerToRoF2TypelessSlot(emu->itemslot); //OUT(itemslot); OUT(quantity); OUT(price); @@ -3825,7 +3825,7 @@ namespace RoF2 ENCODE_LENGTH_EXACT(TributeItem_Struct); SETUP_DIRECT_ENCODE(TributeItem_Struct, structs::TributeItem_Struct); - eq->slot = ServerToRoF2Slot(emu->slot); + eq->inventory_slot = ServerToRoF2Slot(emu->slot); OUT(quantity); OUT(tribute_master_id); OUT(tribute_points); @@ -4384,7 +4384,7 @@ namespace RoF2 SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); IN(npcid); - emu->slot = RoF2ToServerMainInvSlot(eq->slot); + emu->slot = RoF2ToServerTypelessSlot(eq->inventory_slot); IN(charges); IN(sell_price); @@ -4397,7 +4397,7 @@ namespace RoF2 SETUP_DIRECT_DECODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); IN(merchant_entity_id); - emu->slot_id = RoF2ToServerMainInvSlot(eq->slot_id); + emu->slot_id = RoF2ToServerTypelessSlot(eq->inventory_slot); IN(charges); IN(cost); @@ -4410,7 +4410,7 @@ namespace RoF2 SETUP_DIRECT_DECODE(AltCurrencySelectItem_Struct, structs::AltCurrencySelectItem_Struct); IN(merchant_entity_id); - emu->slot_id = RoF2ToServerMainInvSlot(eq->slot_id); + emu->slot_id = RoF2ToServerTypelessSlot(eq->inventory_slot); FINISH_DIRECT_DECODE(); } @@ -4432,7 +4432,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); SETUP_DIRECT_DECODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - emu->inventorySlot = RoF2ToServerMainInvSlot(eq->inventorySlot); + emu->inventorySlot = RoF2ToServerTypelessSlot(eq->inventorySlot); IN(success); FINISH_DIRECT_DECODE(); @@ -4540,7 +4540,7 @@ namespace RoF2 IN(slot); IN(spell_id); - emu->inventoryslot = RoF2ToServerSlot(eq->inventoryslot); + emu->inventoryslot = RoF2ToServerSlot(eq->inventory_slot); //IN(inventoryslot); IN(target_id); IN(y_pos); @@ -4667,7 +4667,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::Consume_Struct); SETUP_DIRECT_DECODE(Consume_Struct, structs::Consume_Struct); - emu->slot = RoF2ToServerSlot(eq->slot); + emu->slot = RoF2ToServerSlot(eq->inventory_slot); IN(auto_consumed); IN(type); @@ -5028,7 +5028,7 @@ namespace RoF2 IN(item_id); int r; - for (r = 0; r < EmuConstants::ITEM_COMMON_SIZE; r++) { + for (r = 0; r < EQEmu::Constants::ITEM_COMMON_SIZE; r++) { IN(augments[r]); } IN(link_hash); @@ -5042,7 +5042,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::ItemVerifyRequest_Struct); SETUP_DIRECT_DECODE(ItemVerifyRequest_Struct, structs::ItemVerifyRequest_Struct); - emu->slot = RoF2ToServerSlot(eq->slot); + emu->slot = RoF2ToServerSlot(eq->inventory_slot); IN(target); FINISH_DIRECT_DECODE(); @@ -5082,7 +5082,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - Log.Out(Logs::General, Logs::Netcode, "[RoF2] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); + Log.Out(Logs::General, Logs::Netcode, "[RoF2] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.Type, eq->to_slot.Type, eq->from_slot.Slot, eq->to_slot.Slot, eq->from_slot.Sub, eq->to_slot.Sub, eq->from_slot.Aug, eq->to_slot.Aug, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); emu->from_slot = RoF2ToServerSlot(eq->from_slot); emu->to_slot = RoF2ToServerSlot(eq->to_slot); IN(number_in_stack); @@ -5231,7 +5231,7 @@ namespace RoF2 SETUP_DIRECT_DECODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); IN(npcid); - emu->itemslot = RoF2ToServerMainInvSlot(eq->itemslot); + emu->itemslot = RoF2ToServerTypelessSlot(eq->inventory_slot); //IN(itemslot); IN(quantity); IN(price); @@ -5385,7 +5385,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::TributeItem_Struct); SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); - emu->slot = RoF2ToServerSlot(eq->slot); + emu->slot = RoF2ToServerSlot(eq->inventory_slot); IN(quantity); IN(tribute_master_id); IN(tribute_points); @@ -5485,12 +5485,12 @@ namespace RoF2 hdr.stacksize = stackable ? charges : 1; hdr.unknown004 = 0; - structs::ItemSlotStruct slot_id = ServerToRoF2Slot(slot_id_in, packet_type); + structs::InventorySlot_Struct slot_id = ServerToRoF2Slot(slot_id_in, packet_type); - hdr.slot_type = (merchant_slot == 0) ? slot_id.SlotType : 9; // 9 is merchant 20 is reclaim items? - hdr.main_slot = (merchant_slot == 0) ? slot_id.MainSlot : merchant_slot; - hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubSlot : 0xffff; - hdr.aug_slot = (merchant_slot == 0) ? slot_id.AugSlot : 0xffff; + hdr.slot_type = (merchant_slot == 0) ? slot_id.Type : 9; // 9 is merchant 20 is reclaim items? + hdr.main_slot = (merchant_slot == 0) ? slot_id.Slot : merchant_slot; + hdr.sub_slot = (merchant_slot == 0) ? slot_id.Sub : 0xffff; + hdr.aug_slot = (merchant_slot == 0) ? slot_id.Aug : 0xffff; hdr.price = inst->GetPrice(); hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; @@ -5961,7 +5961,7 @@ namespace RoF2 uint32 SubLengths[10]; - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -5973,15 +5973,15 @@ namespace RoF2 iqbs.subitem_count++; - if (slot_id_in >= EmuConstants::GENERAL_BEGIN && slot_id_in <= EmuConstants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::Constants::GENERAL_BEGIN && slot_id_in <= EQEmu::Constants::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EmuConstants::BANK_BEGIN && slot_id_in <= EmuConstants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::Constants::BANK_BEGIN && slot_id_in <= EQEmu::Constants::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EmuConstants::SHARED_BANK_BEGIN && slot_id_in <= EmuConstants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::Constants::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::SHARED_BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -5996,7 +5996,7 @@ namespace RoF2 ss.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { if (SubSerializations[x]) { @@ -6016,38 +6016,38 @@ namespace RoF2 return item_serial; } - static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType) + static inline structs::InventorySlot_Struct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType) { - structs::ItemSlotStruct RoF2Slot; - RoF2Slot.SlotType = INVALID_INDEX; + structs::InventorySlot_Struct RoF2Slot; + RoF2Slot.Type = INVALID_INDEX; RoF2Slot.Unknown02 = NOT_USED; - RoF2Slot.MainSlot = INVALID_INDEX; - RoF2Slot.SubSlot = INVALID_INDEX; - RoF2Slot.AugSlot = INVALID_INDEX; + RoF2Slot.Slot = INVALID_INDEX; + RoF2Slot.Sub = INVALID_INDEX; + RoF2Slot.Aug = INVALID_INDEX; RoF2Slot.Unknown01 = NOT_USED; uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == MainPowerSource) { // Main Inventory and Cursor + if (serverSlot < 56 || serverSlot == SlotPowerSource) { // Main Inventory and Cursor if (PacketType == ItemPacketLoot) { - RoF2Slot.SlotType = maps::MapCorpse; - RoF2Slot.MainSlot = serverSlot - EmuConstants::CORPSE_BEGIN; + RoF2Slot.Type = inventory::TypeCorpse; + RoF2Slot.Slot = serverSlot - EQEmu::Constants::CORPSE_BEGIN; } else { - RoF2Slot.SlotType = maps::MapPossessions; - RoF2Slot.MainSlot = serverSlot; + RoF2Slot.Type = inventory::TypePossessions; + RoF2Slot.Slot = serverSlot; } - if (serverSlot == MainPowerSource) - RoF2Slot.MainSlot = slots::MainPowerSource; + if (serverSlot == SlotPowerSource) + RoF2Slot.Slot = inventory::SlotPowerSource; - else if (serverSlot >= MainCursor && PacketType != ItemPacketLoot) // Cursor and Extended Corpse Inventory - RoF2Slot.MainSlot += 3; + else if (serverSlot >= SlotCursor && PacketType != ItemPacketLoot) // Cursor and Extended Corpse Inventory + RoF2Slot.Slot += 3; - else if (serverSlot >= MainAmmo) // (> 20) - RoF2Slot.MainSlot += 1; + else if (serverSlot >= SlotAmmo) // (> 20) + RoF2Slot.Slot += 1; } /*else if (ServerSlot < 51) { // Cursor Buffer @@ -6055,51 +6055,51 @@ namespace RoF2 RoF2Slot.MainSlot = ServerSlot - 31; }*/ - else if (serverSlot >= EmuConstants::GENERAL_BAGS_BEGIN && serverSlot <= EmuConstants::CURSOR_BAG_END) { // (> 250 && < 341) - RoF2Slot.SlotType = maps::MapPossessions; + else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) { // (> 250 && < 341) + RoF2Slot.Type = inventory::TypePossessions; TempSlot = serverSlot - 1; - RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 2; - RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 2) * EmuConstants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 2; + RoF2Slot.Sub = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::Constants::ITEM_CONTAINER_SIZE); - if (RoF2Slot.MainSlot >= slots::MainGeneral9) // (> 30) - RoF2Slot.MainSlot = slots::MainCursor; + if (RoF2Slot.Slot >= inventory::SlotGeneral9) // (> 30) + RoF2Slot.Slot = inventory::SlotCursor; } - else if (serverSlot >= EmuConstants::TRIBUTE_BEGIN && serverSlot <= EmuConstants::TRIBUTE_END) { // Tribute - RoF2Slot.SlotType = maps::MapTribute; - RoF2Slot.MainSlot = serverSlot - EmuConstants::TRIBUTE_BEGIN; + else if (serverSlot >= EQEmu::Constants::TRIBUTE_BEGIN && serverSlot <= EQEmu::Constants::TRIBUTE_END) { // Tribute + RoF2Slot.Type = inventory::TypeTribute; + RoF2Slot.Slot = serverSlot - EQEmu::Constants::TRIBUTE_BEGIN; } - else if (serverSlot >= EmuConstants::BANK_BEGIN && serverSlot <= EmuConstants::BANK_BAGS_END) { - RoF2Slot.SlotType = maps::MapBank; - TempSlot = serverSlot - EmuConstants::BANK_BEGIN; - RoF2Slot.MainSlot = TempSlot; + else if (serverSlot >= EQEmu::Constants::BANK_BEGIN && serverSlot <= EQEmu::Constants::BANK_BAGS_END) { + RoF2Slot.Type = inventory::TypeBank; + TempSlot = serverSlot - EQEmu::Constants::BANK_BEGIN; + RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.Sub = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EmuConstants::SHARED_BANK_BEGIN && serverSlot <= EmuConstants::SHARED_BANK_BAGS_END) { - RoF2Slot.SlotType = maps::MapSharedBank; - TempSlot = serverSlot - EmuConstants::SHARED_BANK_BEGIN; - RoF2Slot.MainSlot = TempSlot; + else if (serverSlot >= EQEmu::Constants::SHARED_BANK_BEGIN && serverSlot <= EQEmu::Constants::SHARED_BANK_BAGS_END) { + RoF2Slot.Type = inventory::TypeSharedBank; + TempSlot = serverSlot - EQEmu::Constants::SHARED_BANK_BEGIN; + RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.Sub = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EmuConstants::TRADE_BEGIN && serverSlot <= EmuConstants::TRADE_BAGS_END) { - RoF2Slot.SlotType = maps::MapTrade; - TempSlot = serverSlot - EmuConstants::TRADE_BEGIN; - RoF2Slot.MainSlot = TempSlot; + else if (serverSlot >= EQEmu::Constants::TRADE_BEGIN && serverSlot <= EQEmu::Constants::TRADE_BAGS_END) { + RoF2Slot.Type = inventory::TypeTrade; + TempSlot = serverSlot - EQEmu::Constants::TRADE_BEGIN; + RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { - RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.Sub = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); } /* @@ -6116,38 +6116,38 @@ namespace RoF2 */ } - else if (serverSlot >= EmuConstants::WORLD_BEGIN && serverSlot <= EmuConstants::WORLD_END) { - RoF2Slot.SlotType = maps::MapWorld; - TempSlot = serverSlot - EmuConstants::WORLD_BEGIN; - RoF2Slot.MainSlot = TempSlot; + else if (serverSlot >= EQEmu::Constants::WORLD_BEGIN && serverSlot <= EQEmu::Constants::WORLD_END) { + RoF2Slot.Type = inventory::TypeWorld; + TempSlot = serverSlot - EQEmu::Constants::WORLD_BEGIN; + RoF2Slot.Slot = TempSlot; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoF2Slot.SlotType, RoF2Slot.Unknown02, RoF2Slot.MainSlot, RoF2Slot.SubSlot, RoF2Slot.AugSlot, RoF2Slot.Unknown01); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoF2Slot.Type, RoF2Slot.Unknown02, RoF2Slot.Slot, RoF2Slot.Sub, RoF2Slot.Aug, RoF2Slot.Unknown01); return RoF2Slot; } - static inline structs::MainInvItemSlotStruct ServerToRoF2MainInvSlot(uint32 serverSlot) + static inline structs::TypelessInventorySlot_Struct ServerToRoF2TypelessSlot(uint32 serverSlot) { - structs::MainInvItemSlotStruct RoF2Slot; - RoF2Slot.MainSlot = INVALID_INDEX; - RoF2Slot.SubSlot = INVALID_INDEX; - RoF2Slot.AugSlot = INVALID_INDEX; + structs::TypelessInventorySlot_Struct RoF2Slot; + RoF2Slot.Slot = INVALID_INDEX; + RoF2Slot.Sub = INVALID_INDEX; + RoF2Slot.Aug = INVALID_INDEX; RoF2Slot.Unknown01 = NOT_USED; uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == MainPowerSource) { // (< 52) - RoF2Slot.MainSlot = serverSlot; + if (serverSlot < 56 || serverSlot == SlotPowerSource) { // (< 52) + RoF2Slot.Slot = serverSlot; - if (serverSlot == MainPowerSource) - RoF2Slot.MainSlot = slots::MainPowerSource; + if (serverSlot == SlotPowerSource) + RoF2Slot.Slot = inventory::SlotPowerSource; - else if (serverSlot >= MainCursor) // Cursor and Extended Corpse Inventory - RoF2Slot.MainSlot += 3; + else if (serverSlot >= SlotCursor) // Cursor and Extended Corpse Inventory + RoF2Slot.Slot += 3; - else if (serverSlot >= MainAmmo) // Ammo and Personl Inventory - RoF2Slot.MainSlot += 1; + else if (serverSlot >= SlotAmmo) // Ammo and Personl Inventory + RoF2Slot.Slot += 1; /*else if (ServerSlot >= MainCursor) { // Cursor RoF2Slot.MainSlot = slots::MainCursor; @@ -6157,33 +6157,33 @@ namespace RoF2 }*/ } - else if (serverSlot >= EmuConstants::GENERAL_BAGS_BEGIN && serverSlot <= EmuConstants::CURSOR_BAG_END) { + else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) { TempSlot = serverSlot - 1; - RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 2; - RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 2) * EmuConstants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 2; + RoF2Slot.Sub = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::Constants::ITEM_CONTAINER_SIZE); } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoF2Slot.MainSlot, RoF2Slot.SubSlot, RoF2Slot.AugSlot, RoF2Slot.Unknown01); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoF2Slot.Slot, RoF2Slot.Sub, RoF2Slot.Aug, RoF2Slot.Unknown01); return RoF2Slot; } static inline uint32 ServerToRoF2CorpseSlot(uint32 serverCorpseSlot) { - return (serverCorpseSlot - EmuConstants::CORPSE_BEGIN + 1); + return (serverCorpseSlot - EQEmu::Constants::CORPSE_BEGIN + 1); } - static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct rof2Slot, ItemPacketType PacketType) + static inline uint32 RoF2ToServerSlot(structs::InventorySlot_Struct rof2Slot, ItemPacketType PacketType) { uint32 ServerSlot = INVALID_INDEX; uint32 TempSlot = 0; - if (rof2Slot.SlotType == maps::MapPossessions && rof2Slot.MainSlot < 57) { // Worn/Personal Inventory and Cursor (< 51) - if (rof2Slot.MainSlot == slots::MainPowerSource) - TempSlot = MainPowerSource; + if (rof2Slot.Type == inventory::TypePossessions && rof2Slot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 51) + if (rof2Slot.Slot == inventory::SlotPowerSource) + TempSlot = SlotPowerSource; - else if (rof2Slot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory - TempSlot = rof2Slot.MainSlot - 3; + else if (rof2Slot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory + TempSlot = rof2Slot.Slot - 3; /*else if (RoF2Slot.MainSlot == slots::MainGeneral9 || RoF2Slot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF2 inventory/corpse slots // Need to figure out what to do when we get these @@ -6196,61 +6196,61 @@ namespace RoF2 // For now, it's probably best to leave as-is and let this work itself out in the inventory rework. }*/ - else if (rof2Slot.MainSlot >= slots::MainAmmo) // Ammo and Main Inventory - TempSlot = rof2Slot.MainSlot - 1; + else if (rof2Slot.Slot >= inventory::SlotAmmo) // Ammo and Main Inventory + TempSlot = rof2Slot.Slot - 1; else // Worn Slots - TempSlot = rof2Slot.MainSlot; + TempSlot = rof2Slot.Slot; - if (rof2Slot.SubSlot >= SUB_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + rof2Slot.SubSlot + 1; + if (rof2Slot.Sub >= SUB_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rof2Slot.Sub + 1; ServerSlot = TempSlot; } - else if (rof2Slot.SlotType == maps::MapBank) { - TempSlot = EmuConstants::BANK_BEGIN; + else if (rof2Slot.Type == inventory::TypeBank) { + TempSlot = EQEmu::Constants::BANK_BEGIN; - if (rof2Slot.SubSlot >= SUB_BEGIN) - TempSlot += ((rof2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + rof2Slot.SubSlot + 1; + if (rof2Slot.Sub >= SUB_BEGIN) + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rof2Slot.Sub + 1; else - TempSlot += rof2Slot.MainSlot; + TempSlot += rof2Slot.Slot; ServerSlot = TempSlot; } - else if (rof2Slot.SlotType == maps::MapSharedBank) { - TempSlot = EmuConstants::SHARED_BANK_BEGIN; + else if (rof2Slot.Type == inventory::TypeSharedBank) { + TempSlot = EQEmu::Constants::SHARED_BANK_BEGIN; - if (rof2Slot.SubSlot >= SUB_BEGIN) - TempSlot += ((rof2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + rof2Slot.SubSlot + 1; + if (rof2Slot.Sub >= SUB_BEGIN) + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rof2Slot.Sub + 1; else - TempSlot += rof2Slot.MainSlot; + TempSlot += rof2Slot.Slot; ServerSlot = TempSlot; } - else if (rof2Slot.SlotType == maps::MapTrade) { - TempSlot = EmuConstants::TRADE_BEGIN; + else if (rof2Slot.Type == inventory::TypeTrade) { + TempSlot = EQEmu::Constants::TRADE_BEGIN; - if (rof2Slot.SubSlot >= SUB_BEGIN) - TempSlot += ((rof2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + rof2Slot.SubSlot + 1; + if (rof2Slot.Sub >= SUB_BEGIN) + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rof2Slot.Sub + 1; // OLD CODE: //TempSlot += 100 + (RoF2Slot.MainSlot * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot; else - TempSlot += rof2Slot.MainSlot; + TempSlot += rof2Slot.Slot; ServerSlot = TempSlot; } - else if (rof2Slot.SlotType == maps::MapWorld) { - TempSlot = EmuConstants::WORLD_BEGIN; + else if (rof2Slot.Type == inventory::TypeWorld) { + TempSlot = EQEmu::Constants::WORLD_BEGIN; - if (rof2Slot.MainSlot >= SUB_BEGIN) - TempSlot += rof2Slot.MainSlot; + if (rof2Slot.Slot >= SUB_BEGIN) + TempSlot += rof2Slot.Slot; ServerSlot = TempSlot; } @@ -6264,30 +6264,30 @@ namespace RoF2 ServerSlot = TempSlot; }*/ - else if (rof2Slot.SlotType == maps::MapGuildTribute) { + else if (rof2Slot.Type == inventory::TypeGuildTribute) { ServerSlot = INVALID_INDEX; } - else if (rof2Slot.SlotType == maps::MapCorpse) { - ServerSlot = rof2Slot.MainSlot + EmuConstants::CORPSE_BEGIN; + else if (rof2Slot.Type == inventory::TypeCorpse) { + ServerSlot = rof2Slot.Slot + EQEmu::Constants::CORPSE_BEGIN; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rof2Slot.SlotType, rof2Slot.Unknown02, rof2Slot.MainSlot, rof2Slot.SubSlot, rof2Slot.AugSlot, rof2Slot.Unknown01, ServerSlot); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rof2Slot.Type, rof2Slot.Unknown02, rof2Slot.Slot, rof2Slot.Sub, rof2Slot.Aug, rof2Slot.Unknown01, ServerSlot); return ServerSlot; } - static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct rof2Slot) + static inline uint32 RoF2ToServerTypelessSlot(structs::TypelessInventorySlot_Struct rof2Slot) { uint32 ServerSlot = INVALID_INDEX; uint32 TempSlot = 0; - if (rof2Slot.MainSlot < 57) { // Worn/Personal Inventory and Cursor (< 33) - if (rof2Slot.MainSlot == slots::MainPowerSource) - TempSlot = MainPowerSource; + if (rof2Slot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 33) + if (rof2Slot.Slot == inventory::SlotPowerSource) + TempSlot = SlotPowerSource; - else if (rof2Slot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory - TempSlot = rof2Slot.MainSlot - 3; + else if (rof2Slot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory + TempSlot = rof2Slot.Slot - 3; /*else if (RoF2Slot.MainSlot == slots::MainGeneral9 || RoF2Slot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF2 inventory slots // Need to figure out what to do when we get these @@ -6295,31 +6295,31 @@ namespace RoF2 // Same as above }*/ - else if (rof2Slot.MainSlot >= slots::MainAmmo) // Main Inventory and Ammo Slots - TempSlot = rof2Slot.MainSlot - 1; + else if (rof2Slot.Slot >= inventory::SlotAmmo) // Main Inventory and Ammo Slots + TempSlot = rof2Slot.Slot - 1; else - TempSlot = rof2Slot.MainSlot; + TempSlot = rof2Slot.Slot; - if (rof2Slot.SubSlot >= SUB_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + rof2Slot.SubSlot + 1; + if (rof2Slot.Sub >= SUB_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rof2Slot.Sub + 1; ServerSlot = TempSlot; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rof2Slot.MainSlot, rof2Slot.SubSlot, rof2Slot.AugSlot, rof2Slot.Unknown01, ServerSlot); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rof2Slot.Slot, rof2Slot.Sub, rof2Slot.Aug, rof2Slot.Unknown01, ServerSlot); return ServerSlot; } static inline uint32 RoF2ToServerCorpseSlot(uint32 rof2CorpseSlot) { - return (rof2CorpseSlot + EmuConstants::CORPSE_BEGIN - 1); + return (rof2CorpseSlot + EQEmu::Constants::CORPSE_BEGIN - 1); } static inline void ServerToRoF2TextLink(std::string& rof2TextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { rof2TextLink = serverTextLink; return; } @@ -6328,7 +6328,7 @@ namespace RoF2 for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { rof2TextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -6351,7 +6351,7 @@ namespace RoF2 static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink) { - if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find('\x12') == std::string::npos)) { serverTextLink = rof2TextLink; return; } diff --git a/common/patches/rof2_constants.h b/common/patches/rof2_constants.h index 0732044ca..e2886406b 100644 --- a/common/patches/rof2_constants.h +++ b/common/patches/rof2_constants.h @@ -1,7 +1,7 @@ /* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) +Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,126 +25,124 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../types.h" namespace RoF2 { - namespace maps { + namespace inventory { typedef enum : int16 { - MapPossessions = 0, - MapBank, - MapSharedBank, - MapTrade, - MapWorld, - MapLimbo, - MapTribute, - MapTrophyTribute, - MapGuildTribute, - MapMerchant, - MapDeleted, - MapCorpse, - MapBazaar, - MapInspect, - MapRealEstate, - MapViewMODPC, - MapViewMODBank, - MapViewMODSharedBank, - MapViewMODLimbo, - MapAltStorage, - MapArchived, - MapMail, - MapGuildTrophyTribute, - MapKrono, - MapOther, - _MapCount - } InventoryMaps; - } + TypePossessions = 0, + TypeBank, + TypeSharedBank, + TypeTrade, + TypeWorld, + TypeLimbo, + TypeTribute, + TypeTrophyTribute, + TypeGuildTribute, + TypeMerchant, + TypeDeleted, + TypeCorpse, + TypeBazaar, + TypeInspect, + TypeRealEstate, + TypeViewMODPC, + TypeViewMODBank, + TypeViewMODSharedBank, + TypeViewMODLimbo, + TypeAltStorage, + TypeArchived, + TypeMail, + TypeGuildTrophyTribute, + TypeKrono, + TypeOther, + TypeCount + } InventoryTypes; - namespace slots { typedef enum : int16 { - MainCharm = 0, - MainEar1, - MainHead, - MainFace, - MainEar2, - MainNeck, - MainShoulders, - MainArms, - MainBack, - MainWrist1, - MainWrist2, - MainRange, - MainHands, - MainPrimary, - MainSecondary, - MainFinger1, - MainFinger2, - MainChest, - MainLegs, - MainFeet, - MainWaist, - MainPowerSource, - MainAmmo, - MainGeneral1, - MainGeneral2, - MainGeneral3, - MainGeneral4, - MainGeneral5, - MainGeneral6, - MainGeneral7, - MainGeneral8, - MainGeneral9, - MainGeneral10, - MainCursor, - _MainCount, - _MainEquipmentBegin = MainCharm, - _MainEquipmentEnd = MainAmmo, - _MainEquipmentCount = (_MainEquipmentEnd - _MainEquipmentBegin + 1), - _MainGeneralBegin = MainGeneral1, - _MainGeneralEnd = MainGeneral10, - _MainGeneralCount = (_MainGeneralEnd - _MainGeneralBegin + 1) - } EquipmentSlots; + SlotCharm = 0, + SlotEar1, + SlotHead, + SlotFace, + SlotEar2, + SlotNeck, + SlotShoulders, + SlotArms, + SlotBack, + SlotWrist1, + SlotWrist2, + SlotRange, + SlotHands, + SlotPrimary, + SlotSecondary, + SlotFinger1, + SlotFinger2, + SlotChest, + SlotLegs, + SlotFeet, + SlotWaist, + SlotPowerSource, + SlotAmmo, + SlotGeneral1, + SlotGeneral2, + SlotGeneral3, + SlotGeneral4, + SlotGeneral5, + SlotGeneral6, + SlotGeneral7, + SlotGeneral8, + SlotGeneral9, + SlotGeneral10, + SlotCursor, + SlotCount, + SlotEquipmentBegin = SlotCharm, + SlotEquipmentEnd = SlotAmmo, + SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), + SlotGeneralBegin = SlotGeneral1, + SlotGeneralEnd = SlotGeneral10, + SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) + } PossessionsSlots; } namespace consts { static const size_t CHARACTER_CREATION_LIMIT = 12; - static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount; - static const uint16 MAP_BANK_SIZE = 24; - static const uint16 MAP_SHARED_BANK_SIZE = 2; - static const uint16 MAP_TRADE_SIZE = 8; - static const uint16 MAP_WORLD_SIZE = 10; - static const uint16 MAP_LIMBO_SIZE = 36; - static const uint16 MAP_TRIBUTE_SIZE = 0; //? - static const uint16 MAP_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_GUILD_TRIBUTE_SIZE = 0; - static const uint16 MAP_MERCHANT_SIZE = 0; - static const uint16 MAP_DELETED_SIZE = 0; - static const uint16 MAP_CORPSE_SIZE = slots::_MainCount; - static const uint16 MAP_BAZAAR_SIZE = 200; - static const uint16 MAP_INSPECT_SIZE = slots::_MainEquipmentCount; - static const uint16 MAP_REAL_ESTATE_SIZE = 0; - static const uint16 MAP_VIEW_MOD_PC_SIZE = MAP_POSSESSIONS_SIZE; - static const uint16 MAP_VIEW_MOD_BANK_SIZE = MAP_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_SHARED_BANK_SIZE = MAP_SHARED_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_LIMBO_SIZE = MAP_LIMBO_SIZE; - static const uint16 MAP_ALT_STORAGE_SIZE = 0; - static const uint16 MAP_ARCHIVED_SIZE = 0; - static const uint16 MAP_MAIL_SIZE = 0; - static const uint16 MAP_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_KRONO_SIZE = NOT_USED; - static const uint16 MAP_OTHER_SIZE = 0; + static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; + static const uint16 TYPE_BANK_SIZE = 24; + static const uint16 TYPE_SHARED_BANK_SIZE = 2; + static const uint16 TYPE_TRADE_SIZE = 8; + static const uint16 TYPE_WORLD_SIZE = 10; + static const uint16 TYPE_LIMBO_SIZE = 36; + static const uint16 TYPE_TRIBUTE_SIZE = 0; //? + static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; + static const uint16 TYPE_MERCHANT_SIZE = 0; + static const uint16 TYPE_DELETED_SIZE = 0; + static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; + static const uint16 TYPE_BAZAAR_SIZE = 200; + static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; + static const uint16 TYPE_REAL_ESTATE_SIZE = 0; + static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; + static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; + static const uint16 TYPE_ALT_STORAGE_SIZE = 0; + static const uint16 TYPE_ARCHIVED_SIZE = 0; + static const uint16 TYPE_MAIL_SIZE = 0; + static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_KRONO_SIZE = NOT_USED; + static const uint16 TYPE_OTHER_SIZE = 0; // most of these definitions will go away with the structure-based system..this maintains compatibility for now // (bag slots and main slots beyond Possessions are assigned for compatibility with current server coding) - static const int16 EQUIPMENT_BEGIN = slots::MainCharm; - static const int16 EQUIPMENT_END = slots::MainAmmo; - static const uint16 EQUIPMENT_SIZE = slots::_MainEquipmentCount; + static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; + static const int16 EQUIPMENT_END = inventory::SlotAmmo; + static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; - static const int16 GENERAL_BEGIN = slots::MainGeneral1; - static const int16 GENERAL_END = slots::MainGeneral10; - static const uint16 GENERAL_SIZE = slots::_MainGeneralCount; + static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; + static const int16 GENERAL_END = inventory::SlotGeneral10; + static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; static const int16 GENERAL_BAGS_BEGIN = 251; static const int16 GENERAL_BAGS_END_OFFSET = 99; static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; - static const int16 CURSOR = slots::MainCursor; + static const int16 CURSOR = inventory::SlotCursor; static const int16 CURSOR_BAG_BEGIN = 351; static const int16 CURSOR_BAG_END_OFFSET = 9; static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; @@ -174,8 +172,8 @@ namespace RoF2 { static const int16 TRIBUTE_BEGIN = 400; static const int16 TRIBUTE_END = 404; - static const int16 CORPSE_BEGIN = slots::MainGeneral1; - static const int16 CORPSE_END = slots::MainGeneral1 + slots::MainCursor; + static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; + static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; static const uint16 ITEM_COMMON_SIZE = 6; static const uint16 ITEM_CONTAINER_SIZE = 255; // 255; (server max will be 255..unsure what actual client is - test) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 20d3b47f2..f7963ae54 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -29,22 +29,24 @@ struct WorldObjectsSent_Struct { }; // New for RoF2 - Size: 12 -struct ItemSlotStruct { -/*000*/ int16 SlotType; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Delete Item = -1 +struct InventorySlot_Struct +{ +/*000*/ int16 Type; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Delete Item = -1 /*002*/ int16 Unknown02; -/*004*/ int16 MainSlot; -/*006*/ int16 SubSlot; -/*008*/ int16 AugSlot; // Guessing - Seen 0xffff +/*004*/ int16 Slot; +/*006*/ int16 Sub; +/*008*/ int16 Aug; // Guessing - Seen 0xffff /*010*/ int16 Unknown01; // Normally 0 - Seen 13262 when deleting an item, but didn't match item ID /*012*/ }; // New for RoF2 - Used for Merchant_Purchase_Struct // Can't sellfrom other than main inventory so Slot Type is not needed. -struct MainInvItemSlotStruct { -/*000*/ int16 MainSlot; -/*002*/ int16 SubSlot; -/*004*/ int16 AugSlot; +struct TypelessInventorySlot_Struct +{ +/*000*/ int16 Slot; +/*002*/ int16 Sub; +/*004*/ int16 Aug; /*006*/ int16 Unknown01; /*008*/ }; @@ -656,7 +658,7 @@ struct CastSpell_Struct { /*00*/ uint32 slot; /*04*/ uint32 spell_id; -/*08*/ ItemSlotStruct inventoryslot; // slot for clicky item, Seen unknown of 131 = normal cast +/*08*/ InventorySlot_Struct inventory_slot; // slot for clicky item, Seen unknown of 131 = normal cast /*20*/ uint32 target_id; /*24*/ uint32 cs_unknown[2]; /*32*/ float y_pos; @@ -1082,11 +1084,11 @@ union /*00184*/ EquipStruct equipment[22]; // Total Slots }; /*00624*/ uint32 equip2_count; // Seen 9 -/*00628*/ EquipStruct equipment2[_MaterialCount]; // Appears to be Visible slots, but all 0s +/*00628*/ EquipStruct equipment2[MaterialCount]; // Appears to be Visible slots, but all 0s /*00808*/ uint32 tint_count; // Seen 9 -/*00812*/ Color_Struct item_tint[_MaterialCount]; // RR GG BB 00 +/*00812*/ Color_Struct item_tint[MaterialCount]; // RR GG BB 00 /*00848*/ uint32 tint_count2; // Seen 9 -/*00852*/ Color_Struct item_tint2[_MaterialCount]; // RR GG BB 00 +/*00852*/ Color_Struct item_tint2[MaterialCount]; // RR GG BB 00 /*00888*/ uint8 haircolor; // Player hair color /*00889*/ uint8 beardcolor; // Player beard color /*00890*/ uint32 unknown_rof5; // @@ -1747,7 +1749,7 @@ struct BulkItemPacket_Struct struct Consume_Struct { -/*000*/ ItemSlotStruct slot; +/*000*/ InventorySlot_Struct inventory_slot; /*012*/ uint32 auto_consumed; // 0xffffffff when auto eating e7030000 when right click /*016*/ uint32 type; // 0x01=Food 0x02=Water /*020*/ uint32 c_unknown1; // Seen 2 @@ -1779,16 +1781,18 @@ struct ItemProperties_Struct { /*008*/ }; -struct DeleteItem_Struct { -/*0000*/ ItemSlotStruct from_slot; -/*0012*/ ItemSlotStruct to_slot; +struct DeleteItem_Struct +{ +/*0000*/ InventorySlot_Struct from_slot; +/*0012*/ InventorySlot_Struct to_slot; /*0024*/ uint32 number_in_stack; /*0028*/ }; -struct MoveItem_Struct { -/*0000*/ ItemSlotStruct from_slot; -/*0012*/ ItemSlotStruct to_slot; +struct MoveItem_Struct +{ +/*0000*/ InventorySlot_Struct from_slot; +/*0012*/ InventorySlot_Struct to_slot; /*0024*/ uint32 number_in_stack; /*0028*/ }; @@ -2222,7 +2226,7 @@ struct Merchant_Sell_Struct { struct Merchant_Purchase_Struct { /*000*/ uint32 npcid; // Merchant NPC's entity id -/*004*/ MainInvItemSlotStruct itemslot; +/*004*/ TypelessInventorySlot_Struct inventory_slot; /*012*/ uint32 quantity; /*016*/ uint32 price; /*020*/ @@ -2280,9 +2284,10 @@ struct AltCurrencyUpdate_Struct { //Client -> Server //When an item is selected while the alt currency merchant window is open -struct AltCurrencySelectItem_Struct { +struct AltCurrencySelectItem_Struct +{ /*000*/ uint32 merchant_entity_id; -/*004*/ MainInvItemSlotStruct slot_id; +/*004*/ TypelessInventorySlot_Struct inventory_slot; /*004*/ //uint32 slot_id; /*008*/ uint32 unknown008; /*012*/ uint32 unknown012; @@ -2338,9 +2343,10 @@ struct AltCurrencyReclaim_Struct { /*012*/ uint32 reclaim_flag; //1 = this is reclaim }; -struct AltCurrencySellItem_Struct { +struct AltCurrencySellItem_Struct +{ /*000*/ uint32 merchant_entity_id; -/*004*/ MainInvItemSlotStruct slot_id; +/*004*/ TypelessInventorySlot_Struct inventory_slot; /*004*/ //uint32 slot_id; /*016*/ uint32 charges; /*020*/ uint32 cost; @@ -2356,7 +2362,7 @@ struct Adventure_Purchase_Struct { struct Adventure_Sell_Struct { /*000*/ uint32 unknown000; //0x01 - Stack Size/Charges? /*004*/ uint32 npcid; -/*008*/ MainInvItemSlotStruct slot; +/*008*/ TypelessInventorySlot_Struct inventory_slot; /*016*/ uint32 charges; /*020*/ uint32 sell_price; /*024*/ @@ -2702,9 +2708,9 @@ struct Stun_Struct { // 8 bytes total struct AugmentItem_Struct { /*00*/ uint32 dest_inst_id; // The unique serial number for the item instance that is being augmented /*04*/ uint32 container_index; // Seen 0 -/*08*/ ItemSlotStruct container_slot; // Slot of the item being augmented +/*08*/ InventorySlot_Struct container_slot; // Slot of the item being augmented /*20*/ uint32 augment_index; // Seen 0 -/*24*/ ItemSlotStruct augment_slot; // Slot of the distiller to use (if one applies) +/*24*/ InventorySlot_Struct augment_slot; // Slot of the distiller to use (if one applies) /*36*/ int32 augment_action; // Guessed - 0 = augment, 1 = remove with distiller, 3 = delete aug /*36*/ //int32 augment_slot; /*40*/ @@ -3691,7 +3697,7 @@ struct TributeInfo_Struct { struct TributeItem_Struct { -/*00*/ ItemSlotStruct slot; +/*00*/ InventorySlot_Struct inventory_slot; /*12*/ uint32 quantity; /*16*/ uint32 tribute_master_id; /*20*/ int32 tribute_points; @@ -3728,9 +3734,10 @@ struct Split_Struct ** Used In: OP_TradeSkillCombine ** Last Updated: 01-05-2013 */ -struct NewCombine_Struct { -/*00*/ ItemSlotStruct container_slot; -/*12*/ ItemSlotStruct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8) +struct NewCombine_Struct +{ +/*00*/ InventorySlot_Struct container_slot; +/*12*/ InventorySlot_Struct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8) /*24*/ }; @@ -3769,8 +3776,8 @@ struct RecipeReply_Struct { struct RecipeAutoCombine_Struct { /*00*/ uint32 object_type; /*04*/ uint32 some_id; -/*08*/ ItemSlotStruct container_slot; //echoed in reply - Was uint32 unknown1 -/*20*/ ItemSlotStruct unknown_slot; //echoed in reply +/*08*/ InventorySlot_Struct container_slot; //echoed in reply - Was uint32 unknown1 +/*20*/ InventorySlot_Struct unknown_slot; //echoed in reply /*32*/ uint32 recipe_id; /*36*/ uint32 reply_code; /*40*/ @@ -4488,19 +4495,22 @@ struct ExpansionInfo_Struct { /*064*/ uint32 Expansions; }; -struct ApplyPoison_Struct { - MainInvItemSlotStruct inventorySlot; +struct ApplyPoison_Struct +{ + TypelessInventorySlot_Struct inventorySlot; uint32 success; }; -struct ItemVerifyRequest_Struct { -/*000*/ ItemSlotStruct slot; +struct ItemVerifyRequest_Struct +{ +/*000*/ InventorySlot_Struct inventory_slot; /*012*/ uint32 target; // Target Entity ID /*016*/ }; -struct ItemVerifyReply_Struct { -/*000*/ ItemSlotStruct slot; +struct ItemVerifyReply_Struct +{ +/*000*/ InventorySlot_Struct inventory_slot; /*012*/ uint32 spell; // Spell ID to cast if different than item effect /*016*/ uint32 target; // Target Entity ID /*020*/ diff --git a/common/patches/rof_constants.h b/common/patches/rof_constants.h index b348f5fd5..c75602da4 100644 --- a/common/patches/rof_constants.h +++ b/common/patches/rof_constants.h @@ -1,7 +1,7 @@ /* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) +Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,125 +25,123 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../types.h" namespace RoF { - namespace maps { + namespace inventory { typedef enum : int16 { - MapPossessions = 0, - MapBank, - MapSharedBank, - MapTrade, - MapWorld, - MapLimbo, - MapTribute, - MapTrophyTribute, - MapGuildTribute, - MapMerchant, - MapDeleted, - MapCorpse, - MapBazaar, - MapInspect, - MapRealEstate, - MapViewMODPC, - MapViewMODBank, - MapViewMODSharedBank, - MapViewMODLimbo, - MapAltStorage, - MapArchived, - MapMail, - MapGuildTrophyTribute, - MapOther, - _MapCount - } InventoryMaps; - } + TypePossessions = 0, + TypeBank, + TypeSharedBank, + TypeTrade, + TypeWorld, + TypeLimbo, + TypeTribute, + TypeTrophyTribute, + TypeGuildTribute, + TypeMerchant, + TypeDeleted, + TypeCorpse, + TypeBazaar, + TypeInspect, + TypeRealEstate, + TypeViewMODPC, + TypeViewMODBank, + TypeViewMODSharedBank, + TypeViewMODLimbo, + TypeAltStorage, + TypeArchived, + TypeMail, + TypeGuildTrophyTribute, + TypeOther, + TypeCount + } InventoryTypes; - namespace slots { typedef enum : int16 { - MainCharm = 0, - MainEar1, - MainHead, - MainFace, - MainEar2, - MainNeck, - MainShoulders, - MainArms, - MainBack, - MainWrist1, - MainWrist2, - MainRange, - MainHands, - MainPrimary, - MainSecondary, - MainFinger1, - MainFinger2, - MainChest, - MainLegs, - MainFeet, - MainWaist, - MainPowerSource, - MainAmmo, - MainGeneral1, - MainGeneral2, - MainGeneral3, - MainGeneral4, - MainGeneral5, - MainGeneral6, - MainGeneral7, - MainGeneral8, - MainGeneral9, - MainGeneral10, - MainCursor, - _MainCount, - _MainEquipmentBegin = MainCharm, - _MainEquipmentEnd = MainAmmo, - _MainEquipmentCount = (_MainEquipmentEnd - _MainEquipmentBegin + 1), - _MainGeneralBegin = MainGeneral1, - _MainGeneralEnd = MainGeneral10, - _MainGeneralCount = (_MainGeneralEnd - _MainGeneralBegin + 1) - } EquipmentSlots; + SlotCharm = 0, + SlotEar1, + SlotHead, + SlotFace, + SlotEar2, + SlotNeck, + SlotShoulders, + SlotArms, + SlotBack, + SlotWrist1, + SlotWrist2, + SlotRange, + SlotHands, + SlotPrimary, + SlotSecondary, + SlotFinger1, + SlotFinger2, + SlotChest, + SlotLegs, + SlotFeet, + SlotWaist, + SlotPowerSource, + SlotAmmo, + SlotGeneral1, + SlotGeneral2, + SlotGeneral3, + SlotGeneral4, + SlotGeneral5, + SlotGeneral6, + SlotGeneral7, + SlotGeneral8, + SlotGeneral9, + SlotGeneral10, + SlotCursor, + SlotCount, + SlotEquipmentBegin = SlotCharm, + SlotEquipmentEnd = SlotAmmo, + SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), + SlotGeneralBegin = SlotGeneral1, + SlotGeneralEnd = SlotGeneral10, + SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) + } PossessionsSlots; } namespace consts { static const size_t CHARACTER_CREATION_LIMIT = 12; - static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount; - static const uint16 MAP_BANK_SIZE = 24; - static const uint16 MAP_SHARED_BANK_SIZE = 2; - static const uint16 MAP_TRADE_SIZE = 8; - static const uint16 MAP_WORLD_SIZE = 10; - static const uint16 MAP_LIMBO_SIZE = 36; - static const uint16 MAP_TRIBUTE_SIZE = 0; //? - static const uint16 MAP_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_GUILD_TRIBUTE_SIZE = 0; - static const uint16 MAP_MERCHANT_SIZE = 0; - static const uint16 MAP_DELETED_SIZE = 0; - static const uint16 MAP_CORPSE_SIZE = slots::_MainCount; - static const uint16 MAP_BAZAAR_SIZE = 200; - static const uint16 MAP_INSPECT_SIZE = slots::_MainEquipmentCount; - static const uint16 MAP_REAL_ESTATE_SIZE = 0; - static const uint16 MAP_VIEW_MOD_PC_SIZE = MAP_POSSESSIONS_SIZE; - static const uint16 MAP_VIEW_MOD_BANK_SIZE = MAP_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_SHARED_BANK_SIZE = MAP_SHARED_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_LIMBO_SIZE = MAP_LIMBO_SIZE; - static const uint16 MAP_ALT_STORAGE_SIZE = 0; - static const uint16 MAP_ARCHIVED_SIZE = 0; - static const uint16 MAP_MAIL_SIZE = 0; - static const uint16 MAP_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_KRONO_SIZE = NOT_USED; - static const uint16 MAP_OTHER_SIZE = 0; + static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; + static const uint16 TYPE_BANK_SIZE = 24; + static const uint16 TYPE_SHARED_BANK_SIZE = 2; + static const uint16 TYPE_TRADE_SIZE = 8; + static const uint16 TYPE_WORLD_SIZE = 10; + static const uint16 TYPE_LIMBO_SIZE = 36; + static const uint16 TYPE_TRIBUTE_SIZE = 0; //? + static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; + static const uint16 TYPE_MERCHANT_SIZE = 0; + static const uint16 TYPE_DELETED_SIZE = 0; + static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; + static const uint16 TYPE_BAZAAR_SIZE = 200; + static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; + static const uint16 TYPE_REAL_ESTATE_SIZE = 0; + static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; + static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; + static const uint16 TYPE_ALT_STORAGE_SIZE = 0; + static const uint16 TYPE_ARCHIVED_SIZE = 0; + static const uint16 TYPE_MAIL_SIZE = 0; + static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_KRONO_SIZE = NOT_USED; + static const uint16 TYPE_OTHER_SIZE = 0; // most of these definitions will go away with the structure-based system..this maintains compatibility for now // (bag slots and main slots beyond Possessions are assigned for compatibility with current server coding) - static const int16 EQUIPMENT_BEGIN = slots::MainCharm; - static const int16 EQUIPMENT_END = slots::MainAmmo; - static const uint16 EQUIPMENT_SIZE = slots::_MainEquipmentCount; + static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; + static const int16 EQUIPMENT_END = inventory::SlotAmmo; + static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; - static const int16 GENERAL_BEGIN = slots::MainGeneral1; - static const int16 GENERAL_END = slots::MainGeneral10; - static const uint16 GENERAL_SIZE = slots::_MainGeneralCount; + static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; + static const int16 GENERAL_END = inventory::SlotGeneral10; + static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; static const int16 GENERAL_BAGS_BEGIN = 251; static const int16 GENERAL_BAGS_END_OFFSET = 99; static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; - static const int16 CURSOR = slots::MainCursor; + static const int16 CURSOR = inventory::SlotCursor; static const int16 CURSOR_BAG_BEGIN = 351; static const int16 CURSOR_BAG_END_OFFSET = 9; static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; @@ -173,8 +171,8 @@ namespace RoF { static const int16 TRIBUTE_BEGIN = 400; static const int16 TRIBUTE_END = 404; - static const int16 CORPSE_BEGIN = slots::MainGeneral1; - static const int16 CORPSE_END = slots::MainGeneral1 + slots::MainCursor; + static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; + static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; static const uint16 ITEM_COMMON_SIZE = 6; static const uint16 ITEM_CONTAINER_SIZE = 255; // 255; (server max will be 255..unsure what actual client is - test) diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 86f8b0872..d4f7ce368 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -29,22 +29,24 @@ struct WorldObjectsSent_Struct { }; // New for RoF - Size: 12 -struct ItemSlotStruct { -/*000*/ int16 SlotType; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Delete Item = -1 +struct InventorySlot_Struct +{ +/*000*/ int16 Type; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Delete Item = -1 /*002*/ int16 Unknown02; -/*004*/ int16 MainSlot; -/*006*/ int16 SubSlot; -/*008*/ int16 AugSlot; // Guessing - Seen 0xffff +/*004*/ int16 Slot; +/*006*/ int16 Sub; +/*008*/ int16 Aug; // Guessing - Seen 0xffff /*010*/ int16 Unknown01; // Normally 0 - Seen 13262 when deleting an item, but didn't match item ID /*012*/ }; // New for RoF - Used for Merchant_Purchase_Struct // Can't sellfrom other than main inventory so Slot Type is not needed. -struct MainInvItemSlotStruct { -/*000*/ int16 MainSlot; -/*002*/ int16 SubSlot; -/*004*/ int16 AugSlot; +struct TypelessInventorySlot_Struct +{ +/*000*/ int16 Slot; +/*002*/ int16 Sub; +/*004*/ int16 Aug; /*006*/ int16 Unknown01; /*008*/ }; @@ -645,7 +647,7 @@ struct CastSpell_Struct { /*00*/ uint32 slot; /*04*/ uint32 spell_id; -/*08*/ ItemSlotStruct inventoryslot; // slot for clicky item, Seen unknown of 131 = normal cast +/*08*/ InventorySlot_Struct inventory_slot; // slot for clicky item, Seen unknown of 131 = normal cast /*20*/ uint32 target_id; /*24*/ uint32 cs_unknown[2]; /*32*/ float y_pos; @@ -1777,7 +1779,7 @@ struct BulkItemPacket_Struct struct Consume_Struct { -/*000*/ ItemSlotStruct slot; +/*000*/ InventorySlot_Struct inventory_slot; /*012*/ uint32 auto_consumed; // 0xffffffff when auto eating e7030000 when right click /*016*/ uint32 type; // 0x01=Food 0x02=Water /*020*/ uint32 c_unknown1; // Seen 2 @@ -1809,17 +1811,19 @@ struct ItemProperties_Struct { /*008*/ }; -struct DeleteItem_Struct { -/*0000*/ ItemSlotStruct from_slot; -/*0012*/ ItemSlotStruct to_slot; -/*0024*/ uint32 number_in_stack; +struct DeleteItem_Struct +{ +/*0000*/ InventorySlot_Struct from_slot; +/*0012*/ InventorySlot_Struct to_slot; +/*0024*/ uint32 number_in_stack; /*0028*/ }; -struct MoveItem_Struct { -/*0000*/ ItemSlotStruct from_slot; -/*0012*/ ItemSlotStruct to_slot; -/*0024*/ uint32 number_in_stack; +struct MoveItem_Struct +{ +/*0000*/ InventorySlot_Struct from_slot; +/*0012*/ InventorySlot_Struct to_slot; +/*0024*/ uint32 number_in_stack; /*0028*/ }; @@ -2252,7 +2256,7 @@ struct Merchant_Sell_Struct { struct Merchant_Purchase_Struct { /*000*/ uint32 npcid; // Merchant NPC's entity id -/*004*/ MainInvItemSlotStruct itemslot; +/*004*/ TypelessInventorySlot_Struct inventory_slot; /*012*/ uint32 quantity; /*016*/ uint32 price; /*020*/ @@ -2310,9 +2314,10 @@ struct AltCurrencyUpdate_Struct { //Client -> Server //When an item is selected while the alt currency merchant window is open -struct AltCurrencySelectItem_Struct { +struct AltCurrencySelectItem_Struct +{ /*000*/ uint32 merchant_entity_id; -/*004*/ MainInvItemSlotStruct slot_id; +/*004*/ TypelessInventorySlot_Struct inventory_slot; /*008*/ uint32 unknown008; /*012*/ uint32 unknown012; /*016*/ uint32 unknown016; @@ -2369,7 +2374,7 @@ struct AltCurrencyReclaim_Struct { struct AltCurrencySellItem_Struct { /*000*/ uint32 merchant_entity_id; -/*004*/ MainInvItemSlotStruct slot_id; +/*004*/ TypelessInventorySlot_Struct inventory_slot; /*008*/ uint32 charges; /*012*/ uint32 cost; }; @@ -2384,7 +2389,7 @@ struct Adventure_Purchase_Struct { struct Adventure_Sell_Struct { /*000*/ uint32 unknown000; //0x01 - Stack Size/Charges? /*004*/ uint32 npcid; -/*008*/ MainInvItemSlotStruct slot; +/*008*/ TypelessInventorySlot_Struct inventory_slot; /*016*/ uint32 charges; /*020*/ uint32 sell_price; /*024*/ @@ -2730,9 +2735,9 @@ struct Stun_Struct { // 8 bytes total struct AugmentItem_Struct { /*00*/ uint32 dest_inst_id; // The unique serial number for the item instance that is being augmented /*04*/ uint32 container_index; // Seen 0 -/*08*/ ItemSlotStruct container_slot; // Slot of the item being augmented +/*08*/ InventorySlot_Struct container_slot; // Slot of the item being augmented /*20*/ uint32 augment_index; // Seen 0 -/*24*/ ItemSlotStruct augment_slot; // Slot of the distiller to use (if one applies) +/*24*/ InventorySlot_Struct augment_slot; // Slot of the distiller to use (if one applies) /*36*/ int32 augment_action; // Guessed - 0 = augment, 1 = remove with distiller, 3 = delete aug /*36*/ //int32 augment_slot; /*40*/ @@ -3692,7 +3697,7 @@ struct TributeInfo_Struct { struct TributeItem_Struct { -/*00*/ ItemSlotStruct slot; +/*00*/ InventorySlot_Struct inventory_slot; /*12*/ uint32 quantity; /*16*/ uint32 tribute_master_id; /*20*/ int32 tribute_points; @@ -3729,9 +3734,10 @@ struct Split_Struct ** Used In: OP_TradeSkillCombine ** Last Updated: 01-05-2013 */ -struct NewCombine_Struct { -/*00*/ ItemSlotStruct container_slot; -/*12*/ ItemSlotStruct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8) +struct NewCombine_Struct +{ +/*00*/ InventorySlot_Struct container_slot; +/*12*/ InventorySlot_Struct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8) /*24*/ }; @@ -3767,11 +3773,12 @@ struct RecipeReply_Struct { }; //received and sent back as an ACK with different reply_code -struct RecipeAutoCombine_Struct { +struct RecipeAutoCombine_Struct +{ /*00*/ uint32 object_type; /*04*/ uint32 some_id; -/*08*/ ItemSlotStruct container_slot; //echoed in reply - Was uint32 unknown1 -/*20*/ ItemSlotStruct unknown_slot; //echoed in reply +/*08*/ InventorySlot_Struct container_slot; //echoed in reply - Was uint32 unknown1 +/*20*/ InventorySlot_Struct unknown_slot; //echoed in reply /*32*/ uint32 recipe_id; /*36*/ uint32 reply_code; /*40*/ @@ -4486,19 +4493,22 @@ struct ExpansionInfo_Struct { /*064*/ uint32 Expansions; }; -struct ApplyPoison_Struct { - MainInvItemSlotStruct inventorySlot; +struct ApplyPoison_Struct +{ + TypelessInventorySlot_Struct inventory_slot; uint32 success; }; -struct ItemVerifyRequest_Struct { -/*000*/ ItemSlotStruct slot; +struct ItemVerifyRequest_Struct +{ +/*000*/ InventorySlot_Struct inventory_slot; /*012*/ uint32 target; // Target Entity ID /*016*/ }; -struct ItemVerifyReply_Struct { -/*000*/ ItemSlotStruct slot; +struct ItemVerifyReply_Struct +{ +/*000*/ InventorySlot_Struct inventory_slot; /*012*/ uint32 spell; // Spell ID to cast if different than item effect /*016*/ uint32 target; // Target Entity ID /*020*/ diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 424ad5a22..1d812927c 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1614,7 +1614,7 @@ namespace SoD // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -1623,7 +1623,7 @@ namespace SoD } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -1635,13 +1635,13 @@ namespace SoD // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -1981,7 +1981,7 @@ namespace SoD eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < MaterialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -3934,7 +3934,7 @@ namespace SoD uint32 SubLengths[10]; - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -3946,15 +3946,15 @@ namespace SoD iqbs.subitem_count++; - if (slot_id_in >= EmuConstants::GENERAL_BEGIN && slot_id_in <= EmuConstants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::Constants::GENERAL_BEGIN && slot_id_in <= EQEmu::Constants::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EmuConstants::BANK_BEGIN && slot_id_in <= EmuConstants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::Constants::BANK_BEGIN && slot_id_in <= EQEmu::Constants::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EmuConstants::SHARED_BANK_BEGIN && slot_id_in <= EmuConstants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::Constants::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::SHARED_BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -3993,16 +3993,16 @@ namespace SoD { uint32 SoDSlot = 0; - if (serverSlot >= MainAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (serverSlot >= SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots SoDSlot = serverSlot + 1; - else if (serverSlot >= EmuConstants::GENERAL_BAGS_BEGIN && serverSlot <= EmuConstants::CURSOR_BAG_END) + else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) SoDSlot = serverSlot + 11; - else if (serverSlot >= EmuConstants::BANK_BAGS_BEGIN && serverSlot <= EmuConstants::BANK_BAGS_END) + else if (serverSlot >= EQEmu::Constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::BANK_BAGS_END) SoDSlot = serverSlot + 1; - else if (serverSlot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EmuConstants::SHARED_BANK_BAGS_END) + else if (serverSlot >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::SHARED_BANK_BAGS_END) SoDSlot = serverSlot + 1; - else if (serverSlot == MainPowerSource) - SoDSlot = slots::MainPowerSource; + else if (serverSlot == SlotPowerSource) + SoDSlot = inventory::SlotPowerSource; else SoDSlot = serverSlot; return SoDSlot; @@ -4018,7 +4018,7 @@ namespace SoD { uint32 ServerSlot = 0; - if (sodSlot >= slots::MainAmmo && sodSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (sodSlot >= inventory::SlotAmmo && sodSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots ServerSlot = sodSlot - 1; else if (sodSlot >= consts::GENERAL_BAGS_BEGIN && sodSlot <= consts::CURSOR_BAG_END) ServerSlot = sodSlot - 11; @@ -4026,8 +4026,8 @@ namespace SoD ServerSlot = sodSlot - 1; else if (sodSlot >= consts::SHARED_BANK_BAGS_BEGIN && sodSlot <= consts::SHARED_BANK_BAGS_END) ServerSlot = sodSlot - 1; - else if (sodSlot == slots::MainPowerSource) - ServerSlot = MainPowerSource; + else if (sodSlot == inventory::SlotPowerSource) + ServerSlot = SlotPowerSource; else ServerSlot = sodSlot; return ServerSlot; @@ -4041,7 +4041,7 @@ namespace SoD static inline void ServerToSoDTextLink(std::string& sodTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { sodTextLink = serverTextLink; return; } @@ -4050,7 +4050,7 @@ namespace SoD for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { sodTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -4081,7 +4081,7 @@ namespace SoD static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink) { - if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find('\x12') == std::string::npos)) { serverTextLink = sodTextLink; return; } diff --git a/common/patches/sod_constants.h b/common/patches/sod_constants.h index ebd1d7d48..418525032 100644 --- a/common/patches/sod_constants.h +++ b/common/patches/sod_constants.h @@ -1,7 +1,7 @@ /* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) +Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,122 +25,119 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../types.h" namespace SoD { - namespace maps { + namespace inventory { typedef enum : int16 { - // this needs work to match actual client equivilents - MapPossessions = 0, - MapBank, - MapSharedBank, - MapTrade, - MapWorld, - MapLimbo, - MapTribute, - MapTrophyTribute, - MapGuildTribute, - MapMerchant, - MapDeleted, - MapCorpse, - MapBazaar, - MapInspect, - MapRealEstate, - MapViewMODPC, - MapViewMODBank, - MapViewMODSharedBank, - MapViewMODLimbo, - MapAltStorage, - MapArchived, - MapMail, - MapGuildTrophyTribute, - MapOther, - _MapCount - } InventoryMaps; - } + TypePossessions = 0, + TypeBank, + TypeSharedBank, + TypeTrade, + TypeWorld, + TypeLimbo, + TypeTribute, + TypeTrophyTribute, + TypeGuildTribute, + TypeMerchant, + TypeDeleted, + TypeCorpse, + TypeBazaar, + TypeInspect, + TypeRealEstate, + TypeViewMODPC, + TypeViewMODBank, + TypeViewMODSharedBank, + TypeViewMODLimbo, + TypeAltStorage, + TypeArchived, + TypeMail, + TypeGuildTrophyTribute, + TypeOther, + TypeCount + } InventoryTypes; - namespace slots { typedef enum : int16 { - MainCharm = 0, - MainEar1, - MainHead, - MainFace, - MainEar2, - MainNeck, - MainShoulders, - MainArms, - MainBack, - MainWrist1, - MainWrist2, - MainRange, - MainHands, - MainPrimary, - MainSecondary, - MainFinger1, - MainFinger2, - MainChest, - MainLegs, - MainFeet, - MainWaist, - MainPowerSource, - MainAmmo, - MainGeneral1, - MainGeneral2, - MainGeneral3, - MainGeneral4, - MainGeneral5, - MainGeneral6, - MainGeneral7, - MainGeneral8, - MainCursor, - _MainCount, - _MainEquipmentBegin = MainCharm, - _MainEquipmentEnd = MainAmmo, - _MainEquipmentCount = (_MainEquipmentEnd - _MainEquipmentBegin + 1), - _MainGeneralBegin = MainGeneral1, - _MainGeneralEnd = MainGeneral8, - _MainGeneralCount = (_MainGeneralEnd - _MainGeneralBegin + 1) - } EquipmentSlots; + SlotCharm = 0, + SlotEar1, + SlotHead, + SlotFace, + SlotEar2, + SlotNeck, + SlotShoulders, + SlotArms, + SlotBack, + SlotWrist1, + SlotWrist2, + SlotRange, + SlotHands, + SlotPrimary, + SlotSecondary, + SlotFinger1, + SlotFinger2, + SlotChest, + SlotLegs, + SlotFeet, + SlotWaist, + SlotPowerSource, + SlotAmmo, + SlotGeneral1, + SlotGeneral2, + SlotGeneral3, + SlotGeneral4, + SlotGeneral5, + SlotGeneral6, + SlotGeneral7, + SlotGeneral8, + SlotCursor, + SlotCount, + SlotEquipmentBegin = SlotCharm, + SlotEquipmentEnd = SlotAmmo, + SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), + SlotGeneralBegin = SlotGeneral1, + SlotGeneralEnd = SlotGeneral8, + SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) + } PossessionsSlots; } namespace consts { static const size_t CHARACTER_CREATION_LIMIT = 12; - static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount; - static const uint16 MAP_BANK_SIZE = 24; - static const uint16 MAP_SHARED_BANK_SIZE = 2; - static const uint16 MAP_TRADE_SIZE = 8; - static const uint16 MAP_WORLD_SIZE = 10; - static const uint16 MAP_LIMBO_SIZE = 36; - static const uint16 MAP_TRIBUTE_SIZE = 0; //? - static const uint16 MAP_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_GUILD_TRIBUTE_SIZE = 0; - static const uint16 MAP_MERCHANT_SIZE = 0; - static const uint16 MAP_DELETED_SIZE = 0; - static const uint16 MAP_CORPSE_SIZE = slots::_MainCount; - static const uint16 MAP_BAZAAR_SIZE = 80; - static const uint16 MAP_INSPECT_SIZE = slots::_MainEquipmentCount; - static const uint16 MAP_REAL_ESTATE_SIZE = 0; - static const uint16 MAP_VIEW_MOD_PC_SIZE = MAP_POSSESSIONS_SIZE; - static const uint16 MAP_VIEW_MOD_BANK_SIZE = MAP_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_SHARED_BANK_SIZE = MAP_SHARED_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_LIMBO_SIZE = MAP_LIMBO_SIZE; - static const uint16 MAP_ALT_STORAGE_SIZE = 0; - static const uint16 MAP_ARCHIVED_SIZE = 0; - static const uint16 MAP_MAIL_SIZE = 0; - static const uint16 MAP_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_KRONO_SIZE = NOT_USED; - static const uint16 MAP_OTHER_SIZE = 0; + static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; + static const uint16 TYPE_BANK_SIZE = 24; + static const uint16 TYPE_SHARED_BANK_SIZE = 2; + static const uint16 TYPE_TRADE_SIZE = 8; + static const uint16 TYPE_WORLD_SIZE = 10; + static const uint16 TYPE_LIMBO_SIZE = 36; + static const uint16 TYPE_TRIBUTE_SIZE = 0; //? + static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; + static const uint16 TYPE_MERCHANT_SIZE = 0; + static const uint16 TYPE_DELETED_SIZE = 0; + static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; + static const uint16 TYPE_BAZAAR_SIZE = 80; + static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; + static const uint16 TYPE_REAL_ESTATE_SIZE = 0; + static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; + static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; + static const uint16 TYPE_ALT_STORAGE_SIZE = 0; + static const uint16 TYPE_ARCHIVED_SIZE = 0; + static const uint16 TYPE_MAIL_SIZE = 0; + static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_KRONO_SIZE = NOT_USED; + static const uint16 TYPE_OTHER_SIZE = 0; - static const int16 EQUIPMENT_BEGIN = slots::MainCharm; - static const int16 EQUIPMENT_END = slots::MainAmmo; - static const uint16 EQUIPMENT_SIZE = slots::_MainEquipmentCount; + static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; + static const int16 EQUIPMENT_END = inventory::SlotAmmo; + static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; - static const int16 GENERAL_BEGIN = slots::MainGeneral1; - static const int16 GENERAL_END = slots::MainGeneral8; - static const uint16 GENERAL_SIZE = slots::_MainGeneralCount; + static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; + static const int16 GENERAL_END = inventory::SlotGeneral8; + static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; static const int16 GENERAL_BAGS_BEGIN = 262; static const int16 GENERAL_BAGS_END_OFFSET = 79; static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; - static const int16 CURSOR = slots::MainCursor; + static const int16 CURSOR = inventory::SlotCursor; static const int16 CURSOR_BAG_BEGIN = 342; static const int16 CURSOR_BAG_END_OFFSET = 9; static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; @@ -170,8 +167,8 @@ namespace SoD { static const int16 TRIBUTE_BEGIN = 400; static const int16 TRIBUTE_END = 404; - static const int16 CORPSE_BEGIN = slots::MainGeneral1; - static const int16 CORPSE_END = slots::MainGeneral1 + slots::MainCursor; + static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; + static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; static const uint16 ITEM_COMMON_SIZE = 5; static const uint16 ITEM_CONTAINER_SIZE = 10; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 11e365a71..2056b0798 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1271,7 +1271,7 @@ namespace SoF // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -1280,7 +1280,7 @@ namespace SoF } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -1292,13 +1292,13 @@ namespace SoF // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -1638,7 +1638,7 @@ namespace SoF eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < MaterialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -3256,7 +3256,7 @@ namespace SoF uint32 SubLengths[10]; - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); @@ -3267,15 +3267,15 @@ namespace SoF iqbs.subitem_count++; - if (slot_id_in >= EmuConstants::GENERAL_BEGIN && slot_id_in <= EmuConstants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::Constants::GENERAL_BEGIN && slot_id_in <= EQEmu::Constants::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EmuConstants::BANK_BEGIN && slot_id_in <= EmuConstants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::Constants::BANK_BEGIN && slot_id_in <= EQEmu::Constants::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EmuConstants::SHARED_BANK_BEGIN && slot_id_in <= EmuConstants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::Constants::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::SHARED_BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -3312,16 +3312,16 @@ namespace SoF { uint32 SoFSlot = 0; - if (serverSlot >= MainAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (serverSlot >= SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots SoFSlot = serverSlot + 1; - else if (serverSlot >= EmuConstants::GENERAL_BAGS_BEGIN && serverSlot <= EmuConstants::CURSOR_BAG_END) + else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) SoFSlot = serverSlot + 11; - else if (serverSlot >= EmuConstants::BANK_BAGS_BEGIN && serverSlot <= EmuConstants::BANK_BAGS_END) + else if (serverSlot >= EQEmu::Constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::BANK_BAGS_END) SoFSlot = serverSlot + 1; - else if (serverSlot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EmuConstants::SHARED_BANK_BAGS_END) + else if (serverSlot >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::SHARED_BANK_BAGS_END) SoFSlot = serverSlot + 1; - else if (serverSlot == MainPowerSource) - SoFSlot = slots::MainPowerSource; + else if (serverSlot == SlotPowerSource) + SoFSlot = inventory::SlotPowerSource; else SoFSlot = serverSlot; @@ -3338,7 +3338,7 @@ namespace SoF { uint32 ServerSlot = 0; - if (sofSlot >= slots::MainAmmo && sofSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (sofSlot >= inventory::SlotAmmo && sofSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots ServerSlot = sofSlot - 1; else if (sofSlot >= consts::GENERAL_BAGS_BEGIN && sofSlot <= consts::CURSOR_BAG_END) ServerSlot = sofSlot - 11; @@ -3346,8 +3346,8 @@ namespace SoF ServerSlot = sofSlot - 1; else if (sofSlot >= consts::SHARED_BANK_BAGS_BEGIN && sofSlot <= consts::SHARED_BANK_BAGS_END) ServerSlot = sofSlot - 1; - else if (sofSlot == slots::MainPowerSource) - ServerSlot = MainPowerSource; + else if (sofSlot == inventory::SlotPowerSource) + ServerSlot = SlotPowerSource; else ServerSlot = sofSlot; @@ -3362,7 +3362,7 @@ namespace SoF static inline void ServerToSoFTextLink(std::string& sofTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { sofTextLink = serverTextLink; return; } @@ -3371,7 +3371,7 @@ namespace SoF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { sofTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -3402,7 +3402,7 @@ namespace SoF static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink) { - if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find('\x12') == std::string::npos)) { serverTextLink = sofTextLink; return; } diff --git a/common/patches/sof_constants.h b/common/patches/sof_constants.h index 4ffcdd525..f556ac9d4 100644 --- a/common/patches/sof_constants.h +++ b/common/patches/sof_constants.h @@ -1,7 +1,7 @@ /* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) +Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,122 +25,119 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../types.h" namespace SoF { - namespace maps { + namespace inventory { typedef enum : int16 { - // this needs work to match actual client equivilents - MapPossessions = 0, - MapBank, - MapSharedBank, - MapTrade, - MapWorld, - MapLimbo, - MapTribute, - MapTrophyTribute, - MapGuildTribute, - MapMerchant, - MapDeleted, - MapCorpse, - MapBazaar, - MapInspect, - MapRealEstate, - MapViewMODPC, - MapViewMODBank, - MapViewMODSharedBank, - MapViewMODLimbo, - MapAltStorage, - MapArchived, - MapMail, - MapGuildTrophyTribute, - MapOther, - _MapCount - } InventoryMaps; - } + TypePossessions = 0, + TypeBank, + TypeSharedBank, + TypeTrade, + TypeWorld, + TypeLimbo, + TypeTribute, + TypeTrophyTribute, + TypeGuildTribute, + TypeMerchant, + TypeDeleted, + TypeCorpse, + TypeBazaar, + TypeInspect, + TypeRealEstate, + TypeViewMODPC, + TypeViewMODBank, + TypeViewMODSharedBank, + TypeViewMODLimbo, + TypeAltStorage, + TypeArchived, + TypeMail, + TypeGuildTrophyTribute, + TypeOther, + TypeCount + } InventoryTypes; - namespace slots { typedef enum : int16 { - MainCharm = 0, - MainEar1, - MainHead, - MainFace, - MainEar2, - MainNeck, - MainShoulders, - MainArms, - MainBack, - MainWrist1, - MainWrist2, - MainRange, - MainHands, - MainPrimary, - MainSecondary, - MainFinger1, - MainFinger2, - MainChest, - MainLegs, - MainFeet, - MainWaist, - MainPowerSource, - MainAmmo, - MainGeneral1, - MainGeneral2, - MainGeneral3, - MainGeneral4, - MainGeneral5, - MainGeneral6, - MainGeneral7, - MainGeneral8, - MainCursor, - _MainCount, - _MainEquipmentBegin = MainCharm, - _MainEquipmentEnd = MainAmmo, - _MainEquipmentCount = (_MainEquipmentEnd - _MainEquipmentBegin + 1), - _MainGeneralBegin = MainGeneral1, - _MainGeneralEnd = MainGeneral8, - _MainGeneralCount = (_MainGeneralEnd - _MainGeneralBegin + 1) - } EquipmentSlots; + SlotCharm = 0, + SlotEar1, + SlotHead, + SlotFace, + SlotEar2, + SlotNeck, + SlotShoulders, + SlotArms, + SlotBack, + SlotWrist1, + SlotWrist2, + SlotRange, + SlotHands, + SlotPrimary, + SlotSecondary, + SlotFinger1, + SlotFinger2, + SlotChest, + SlotLegs, + SlotFeet, + SlotWaist, + SlotPowerSource, + SlotAmmo, + SlotGeneral1, + SlotGeneral2, + SlotGeneral3, + SlotGeneral4, + SlotGeneral5, + SlotGeneral6, + SlotGeneral7, + SlotGeneral8, + SlotCursor, + SlotCount, + SlotEquipmentBegin = SlotCharm, + SlotEquipmentEnd = SlotAmmo, + SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), + SlotGeneralBegin = SlotGeneral1, + SlotGeneralEnd = SlotGeneral8, + SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) + } PossessionsSlots; } namespace consts { static const size_t CHARACTER_CREATION_LIMIT = 12; - static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount; - static const uint16 MAP_BANK_SIZE = 24; - static const uint16 MAP_SHARED_BANK_SIZE = 2; - static const uint16 MAP_TRADE_SIZE = 8; - static const uint16 MAP_WORLD_SIZE = 10; - static const uint16 MAP_LIMBO_SIZE = 36; - static const uint16 MAP_TRIBUTE_SIZE = 0; //? - static const uint16 MAP_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_GUILD_TRIBUTE_SIZE = 0; - static const uint16 MAP_MERCHANT_SIZE = 0; - static const uint16 MAP_DELETED_SIZE = 0; - static const uint16 MAP_CORPSE_SIZE = slots::_MainCount; - static const uint16 MAP_BAZAAR_SIZE = 80; - static const uint16 MAP_INSPECT_SIZE = slots::_MainEquipmentCount; - static const uint16 MAP_REAL_ESTATE_SIZE = 0; - static const uint16 MAP_VIEW_MOD_PC_SIZE = MAP_POSSESSIONS_SIZE; - static const uint16 MAP_VIEW_MOD_BANK_SIZE = MAP_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_SHARED_BANK_SIZE = MAP_SHARED_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_LIMBO_SIZE = MAP_LIMBO_SIZE; - static const uint16 MAP_ALT_STORAGE_SIZE = 0; - static const uint16 MAP_ARCHIVED_SIZE = 0; - static const uint16 MAP_MAIL_SIZE = 0; - static const uint16 MAP_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_KRONO_SIZE = NOT_USED; - static const uint16 MAP_OTHER_SIZE = 0; + static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; + static const uint16 TYPE_BANK_SIZE = 24; + static const uint16 TYPE_SHARED_BANK_SIZE = 2; + static const uint16 TYPE_TRADE_SIZE = 8; + static const uint16 TYPE_WORLD_SIZE = 10; + static const uint16 TYPE_LIMBO_SIZE = 36; + static const uint16 TYPE_TRIBUTE_SIZE = 0; //? + static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; + static const uint16 TYPE_MERCHANT_SIZE = 0; + static const uint16 TYPE_DELETED_SIZE = 0; + static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; + static const uint16 TYPE_BAZAAR_SIZE = 80; + static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; + static const uint16 TYPE_REAL_ESTATE_SIZE = 0; + static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; + static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; + static const uint16 TYPE_ALT_STORAGE_SIZE = 0; + static const uint16 TYPE_ARCHIVED_SIZE = 0; + static const uint16 TYPE_MAIL_SIZE = 0; + static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_KRONO_SIZE = NOT_USED; + static const uint16 TYPE_OTHER_SIZE = 0; - static const int16 EQUIPMENT_BEGIN = slots::MainCharm; - static const int16 EQUIPMENT_END = slots::MainAmmo; - static const uint16 EQUIPMENT_SIZE = slots::_MainEquipmentCount; + static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; + static const int16 EQUIPMENT_END = inventory::SlotAmmo; + static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; - static const int16 GENERAL_BEGIN = slots::MainGeneral1; - static const int16 GENERAL_END = slots::MainGeneral8; - static const uint16 GENERAL_SIZE = slots::_MainGeneralCount; + static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; + static const int16 GENERAL_END = inventory::SlotGeneral8; + static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; static const int16 GENERAL_BAGS_BEGIN = 262; static const int16 GENERAL_BAGS_END_OFFSET = 79; static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; - static const int16 CURSOR = slots::MainCursor; + static const int16 CURSOR = inventory::SlotCursor; static const int16 CURSOR_BAG_BEGIN = 342; static const int16 CURSOR_BAG_END_OFFSET = 9; static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; @@ -170,8 +167,8 @@ namespace SoF { static const int16 TRIBUTE_BEGIN = 400; static const int16 TRIBUTE_END = 404; - static const int16 CORPSE_BEGIN = slots::MainGeneral1; - static const int16 CORPSE_END = slots::MainGeneral1 + slots::MainCursor; + static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; + static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; static const uint16 ITEM_COMMON_SIZE = 5; static const uint16 ITEM_CONTAINER_SIZE = 10; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index d3873dd97..248ab1c85 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -943,7 +943,7 @@ namespace Titanium // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -952,7 +952,7 @@ namespace Titanium } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -964,13 +964,13 @@ namespace Titanium // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -1199,14 +1199,14 @@ namespace Titanium if (eq->Race[char_index] > 473) eq->Race[char_index] = 1; - for (int index = 0; index < _MaterialCount; ++index) { + for (int index = 0; index < MaterialCount; ++index) { eq->CS_Colors[char_index][index].Color = emu_cse->Equip[index].Color.Color; } eq->BeardColor[char_index] = emu_cse->BeardColor; eq->HairStyle[char_index] = emu_cse->HairStyle; - for (int index = 0; index < _MaterialCount; ++index) { + for (int index = 0; index < MaterialCount; ++index) { eq->Equip[char_index][index] = emu_cse->Equip[index].Material; } @@ -1236,14 +1236,14 @@ namespace Titanium for (; char_index < 10; ++char_index) { eq->Race[char_index] = 0; - for (int index = 0; index < _MaterialCount; ++index) { + for (int index = 0; index < MaterialCount; ++index) { eq->CS_Colors[char_index][index].Color = 0; } eq->BeardColor[char_index] = 0; eq->HairStyle[char_index] = 0; - for (int index = 0; index < _MaterialCount; ++index) { + for (int index = 0; index < MaterialCount; ++index) { eq->Equip[char_index][index] = 0; } @@ -2198,7 +2198,7 @@ namespace Titanium static inline void ServerToTitaniumTextLink(std::string& titaniumTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { titaniumTextLink = serverTextLink; return; } @@ -2207,7 +2207,7 @@ namespace Titanium for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { titaniumTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -2238,7 +2238,7 @@ namespace Titanium static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink) { - if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find('\x12') == std::string::npos)) { serverTextLink = titaniumTextLink; return; } diff --git a/common/patches/titanium_constants.h b/common/patches/titanium_constants.h index 4915c829c..b0a7353fa 100644 --- a/common/patches/titanium_constants.h +++ b/common/patches/titanium_constants.h @@ -1,7 +1,7 @@ /* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) +Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,121 +25,118 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../types.h" namespace Titanium { - namespace maps { + namespace inventory { typedef enum : int16 { - // this needs work to match actual client equivilents - MapPossessions = 0, - MapBank, - MapSharedBank, - MapTrade, - MapWorld, - MapLimbo, - MapTribute, - MapTrophyTribute, - MapGuildTribute, - MapMerchant, - MapDeleted, - MapCorpse, - MapBazaar, - MapInspect, - MapRealEstate, - MapViewMODPC, - MapViewMODBank, - MapViewMODSharedBank, - MapViewMODLimbo, - MapAltStorage, - MapArchived, - MapMail, - MapGuildTrophyTribute, - MapOther, - _MapCount - } InventoryMaps; - } + TypePossessions = 0, + TypeBank, + TypeSharedBank, + TypeTrade, + TypeWorld, + TypeLimbo, + TypeTribute, + TypeTrophyTribute, + TypeGuildTribute, + TypeMerchant, + TypeDeleted, + TypeCorpse, + TypeBazaar, + TypeInspect, + TypeRealEstate, + TypeViewMODPC, + TypeViewMODBank, + TypeViewMODSharedBank, + TypeViewMODLimbo, + TypeAltStorage, + TypeArchived, + TypeMail, + TypeGuildTrophyTribute, + TypeOther, + TypeCount + } InventoryTypes; - namespace slots { typedef enum : int16 { - MainCharm = 0, - MainEar1, - MainHead, - MainFace, - MainEar2, - MainNeck, - MainShoulders, - MainArms, - MainBack, - MainWrist1, - MainWrist2, - MainRange, - MainHands, - MainPrimary, - MainSecondary, - MainFinger1, - MainFinger2, - MainChest, - MainLegs, - MainFeet, - MainWaist, - MainAmmo, - MainGeneral1, - MainGeneral2, - MainGeneral3, - MainGeneral4, - MainGeneral5, - MainGeneral6, - MainGeneral7, - MainGeneral8, - MainCursor, - _MainCount, - _MainEquipmentBegin = MainCharm, - _MainEquipmentEnd = MainAmmo, - _MainEquipmentCount = (_MainEquipmentEnd - _MainEquipmentBegin + 1), - _MainGeneralBegin = MainGeneral1, - _MainGeneralEnd = MainGeneral8, - _MainGeneralCount = (_MainGeneralEnd - _MainGeneralBegin + 1) - } EquipmentSlots; + SlotCharm = 0, + SlotEar1, + SlotHead, + SlotFace, + SlotEar2, + SlotNeck, + SlotShoulders, + SlotArms, + SlotBack, + SlotWrist1, + SlotWrist2, + SlotRange, + SlotHands, + SlotPrimary, + SlotSecondary, + SlotFinger1, + SlotFinger2, + SlotChest, + SlotLegs, + SlotFeet, + SlotWaist, + SlotAmmo, + SlotGeneral1, + SlotGeneral2, + SlotGeneral3, + SlotGeneral4, + SlotGeneral5, + SlotGeneral6, + SlotGeneral7, + SlotGeneral8, + SlotCursor, + SlotCount, + SlotEquipmentBegin = SlotCharm, + SlotEquipmentEnd = SlotAmmo, + SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), + SlotGeneralBegin = SlotGeneral1, + SlotGeneralEnd = SlotGeneral8, + SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) + } PossessionsSlots; } namespace consts { static const size_t CHARACTER_CREATION_LIMIT = 8; // Hard-coded in client - DO NOT ALTER - static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount; - static const uint16 MAP_BANK_SIZE = 16; - static const uint16 MAP_SHARED_BANK_SIZE = 2; - static const uint16 MAP_TRADE_SIZE = 8; - static const uint16 MAP_WORLD_SIZE = 10; - static const uint16 MAP_LIMBO_SIZE = 36; - static const uint16 MAP_TRIBUTE_SIZE = 0; //? - static const uint16 MAP_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_GUILD_TRIBUTE_SIZE = 0; - static const uint16 MAP_MERCHANT_SIZE = 0; - static const uint16 MAP_DELETED_SIZE = 0; - static const uint16 MAP_CORPSE_SIZE = slots::_MainCount; - static const uint16 MAP_BAZAAR_SIZE = 80; - static const uint16 MAP_INSPECT_SIZE = slots::_MainEquipmentCount; - static const uint16 MAP_REAL_ESTATE_SIZE = 0; - static const uint16 MAP_VIEW_MOD_PC_SIZE = MAP_POSSESSIONS_SIZE; - static const uint16 MAP_VIEW_MOD_BANK_SIZE = MAP_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_SHARED_BANK_SIZE = MAP_SHARED_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_LIMBO_SIZE = MAP_LIMBO_SIZE; - static const uint16 MAP_ALT_STORAGE_SIZE = 0; - static const uint16 MAP_ARCHIVED_SIZE = 0; - static const uint16 MAP_MAIL_SIZE = 0; - static const uint16 MAP_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_KRONO_SIZE = NOT_USED; - static const uint16 MAP_OTHER_SIZE = 0; + static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; + static const uint16 TYPE_BANK_SIZE = 16; + static const uint16 TYPE_SHARED_BANK_SIZE = 2; + static const uint16 TYPE_TRADE_SIZE = 8; + static const uint16 TYPE_WORLD_SIZE = 10; + static const uint16 TYPE_LIMBO_SIZE = 36; + static const uint16 TYPE_TRIBUTE_SIZE = 0; //? + static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; + static const uint16 TYPE_MERCHANT_SIZE = 0; + static const uint16 TYPE_DELETED_SIZE = 0; + static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; + static const uint16 TYPE_BAZAAR_SIZE = 80; + static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; + static const uint16 TYPE_REAL_ESTATE_SIZE = 0; + static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; + static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; + static const uint16 TYPE_ALT_STORAGE_SIZE = 0; + static const uint16 TYPE_ARCHIVED_SIZE = 0; + static const uint16 TYPE_MAIL_SIZE = 0; + static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_KRONO_SIZE = NOT_USED; + static const uint16 TYPE_OTHER_SIZE = 0; - static const int16 EQUIPMENT_BEGIN = slots::MainCharm; - static const int16 EQUIPMENT_END = slots::MainAmmo; - static const uint16 EQUIPMENT_SIZE = slots::_MainEquipmentCount; + static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; + static const int16 EQUIPMENT_END = inventory::SlotAmmo; + static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; - static const int16 GENERAL_BEGIN = slots::MainGeneral1; - static const int16 GENERAL_END = slots::MainGeneral8; - static const uint16 GENERAL_SIZE = slots::_MainGeneralCount; + static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; + static const int16 GENERAL_END = inventory::SlotGeneral8; + static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; static const int16 GENERAL_BAGS_BEGIN = 251; static const int16 GENERAL_BAGS_END_OFFSET = 79; static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; - static const int16 CURSOR = slots::MainCursor; + static const int16 CURSOR = inventory::SlotCursor; static const int16 CURSOR_BAG_BEGIN = 331; static const int16 CURSOR_BAG_END_OFFSET = 9; static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; @@ -169,8 +166,8 @@ namespace Titanium { static const int16 TRIBUTE_BEGIN = 400; static const int16 TRIBUTE_END = 404; - static const int16 CORPSE_BEGIN = slots::MainGeneral1; - static const int16 CORPSE_END = slots::MainGeneral1 + slots::MainCursor; + static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; + static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; static const uint16 ITEM_COMMON_SIZE = 5; static const uint16 ITEM_CONTAINER_SIZE = 10; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index bc7d2906c..b7d88394c 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1878,7 +1878,7 @@ namespace UF // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EmuConstants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -1887,7 +1887,7 @@ namespace UF } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EmuConstants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -1899,13 +1899,13 @@ namespace UF // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EmuConstants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -2274,7 +2274,7 @@ namespace UF eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < _MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < MaterialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -4263,7 +4263,7 @@ namespace UF uint32 SubLengths[10]; - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -4275,15 +4275,15 @@ namespace UF iqbs.subitem_count++; - if (slot_id_in >= EmuConstants::GENERAL_BEGIN && slot_id_in <= EmuConstants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::Constants::GENERAL_BEGIN && slot_id_in <= EQEmu::Constants::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EmuConstants::BANK_BEGIN && slot_id_in <= EmuConstants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::Constants::BANK_BEGIN && slot_id_in <= EQEmu::Constants::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EmuConstants::SHARED_BANK_BEGIN && slot_id_in <= EmuConstants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::Constants::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::SHARED_BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -4322,16 +4322,16 @@ namespace UF { uint32 UnderfootSlot = 0; - if (serverSlot >= MainAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (serverSlot >= SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots UnderfootSlot = serverSlot + 1; - else if (serverSlot >= EmuConstants::GENERAL_BAGS_BEGIN && serverSlot <= EmuConstants::CURSOR_BAG_END) + else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) UnderfootSlot = serverSlot + 11; - else if (serverSlot >= EmuConstants::BANK_BAGS_BEGIN && serverSlot <= EmuConstants::BANK_BAGS_END) + else if (serverSlot >= EQEmu::Constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::BANK_BAGS_END) UnderfootSlot = serverSlot + 1; - else if (serverSlot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EmuConstants::SHARED_BANK_BAGS_END) + else if (serverSlot >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::SHARED_BANK_BAGS_END) UnderfootSlot = serverSlot + 1; - else if (serverSlot == MainPowerSource) - UnderfootSlot = slots::MainPowerSource; + else if (serverSlot == SlotPowerSource) + UnderfootSlot = inventory::SlotPowerSource; else UnderfootSlot = serverSlot; @@ -4348,7 +4348,7 @@ namespace UF { uint32 ServerSlot = 0; - if (ufSlot >= slots::MainAmmo && ufSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (ufSlot >= inventory::SlotAmmo && ufSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots ServerSlot = ufSlot - 1; else if (ufSlot >= consts::GENERAL_BAGS_BEGIN && ufSlot <= consts::CURSOR_BAG_END) ServerSlot = ufSlot - 11; @@ -4356,8 +4356,8 @@ namespace UF ServerSlot = ufSlot - 1; else if (ufSlot >= consts::SHARED_BANK_BAGS_BEGIN && ufSlot <= consts::SHARED_BANK_BAGS_END) ServerSlot = ufSlot - 1; - else if (ufSlot == slots::MainPowerSource) - ServerSlot = MainPowerSource; + else if (ufSlot == inventory::SlotPowerSource) + ServerSlot = SlotPowerSource; else ServerSlot = ufSlot; @@ -4372,7 +4372,7 @@ namespace UF static inline void ServerToUFTextLink(std::string& ufTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EmuConstants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { ufTextLink = serverTextLink; return; } @@ -4381,7 +4381,7 @@ namespace UF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EmuConstants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { ufTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -4412,7 +4412,7 @@ namespace UF static inline void UFToServerTextLink(std::string& serverTextLink, const std::string& ufTextLink) { - if ((EmuConstants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (ufTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (ufTextLink.find('\x12') == std::string::npos)) { serverTextLink = ufTextLink; return; } diff --git a/common/patches/uf_constants.h b/common/patches/uf_constants.h index b8096fd58..d254e66f6 100644 --- a/common/patches/uf_constants.h +++ b/common/patches/uf_constants.h @@ -1,7 +1,7 @@ /* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) +Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,122 +25,119 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../types.h" namespace UF { - namespace maps { + namespace inventory { typedef enum : int16 { - // this needs work to match actual client equivilents - MapPossessions = 0, - MapBank, - MapSharedBank, - MapTrade, - MapWorld, - MapLimbo, - MapTribute, - MapTrophyTribute, - MapGuildTribute, - MapMerchant, - MapDeleted, - MapCorpse, - MapBazaar, - MapInspect, - MapRealEstate, - MapViewMODPC, - MapViewMODBank, - MapViewMODSharedBank, - MapViewMODLimbo, - MapAltStorage, - MapArchived, - MapMail, - MapGuildTrophyTribute, - MapOther, - _MapCount - } InventoryMaps; - } + TypePossessions = 0, + TypeBank, + TypeSharedBank, + TypeTrade, + TypeWorld, + TypeLimbo, + TypeTribute, + TypeTrophyTribute, + TypeGuildTribute, + TypeMerchant, + TypeDeleted, + TypeCorpse, + TypeBazaar, + TypeInspect, + TypeRealEstate, + TypeViewMODPC, + TypeViewMODBank, + TypeViewMODSharedBank, + TypeViewMODLimbo, + TypeAltStorage, + TypeArchived, + TypeMail, + TypeGuildTrophyTribute, + TypeOther, + TypeCount + } InventoryTypes; - namespace slots { typedef enum : int16 { - MainCharm = 0, - MainEar1, - MainHead, - MainFace, - MainEar2, - MainNeck, - MainShoulders, - MainArms, - MainBack, - MainWrist1, - MainWrist2, - MainRange, - MainHands, - MainPrimary, - MainSecondary, - MainFinger1, - MainFinger2, - MainChest, - MainLegs, - MainFeet, - MainWaist, - MainPowerSource, - MainAmmo, - MainGeneral1, - MainGeneral2, - MainGeneral3, - MainGeneral4, - MainGeneral5, - MainGeneral6, - MainGeneral7, - MainGeneral8, - MainCursor, - _MainCount, - _MainEquipmentBegin = MainCharm, - _MainEquipmentEnd = MainAmmo, - _MainEquipmentCount = (_MainEquipmentEnd - _MainEquipmentBegin + 1), - _MainGeneralBegin = MainGeneral1, - _MainGeneralEnd = MainGeneral8, - _MainGeneralCount = (_MainGeneralEnd - _MainGeneralBegin + 1) - } EquipmentSlots; + SlotCharm = 0, + SlotEar1, + SlotHead, + SlotFace, + SlotEar2, + SlotNeck, + SlotShoulders, + SlotArms, + SlotBack, + SlotWrist1, + SlotWrist2, + SlotRange, + SlotHands, + SlotPrimary, + SlotSecondary, + SlotFinger1, + SlotFinger2, + SlotChest, + SlotLegs, + SlotFeet, + SlotWaist, + SlotPowerSource, + SlotAmmo, + SlotGeneral1, + SlotGeneral2, + SlotGeneral3, + SlotGeneral4, + SlotGeneral5, + SlotGeneral6, + SlotGeneral7, + SlotGeneral8, + SlotCursor, + SlotCount, + SlotEquipmentBegin = SlotCharm, + SlotEquipmentEnd = SlotAmmo, + SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), + SlotGeneralBegin = SlotGeneral1, + SlotGeneralEnd = SlotGeneral8, + SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) + } PossessionsSlots; } namespace consts { static const size_t CHARACTER_CREATION_LIMIT = 12; - static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount; - static const uint16 MAP_BANK_SIZE = 24; - static const uint16 MAP_SHARED_BANK_SIZE = 2; - static const uint16 MAP_TRADE_SIZE = 8; - static const uint16 MAP_WORLD_SIZE = 10; - static const uint16 MAP_LIMBO_SIZE = 36; - static const uint16 MAP_TRIBUTE_SIZE = 0; //? - static const uint16 MAP_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_GUILD_TRIBUTE_SIZE = 0; - static const uint16 MAP_MERCHANT_SIZE = 0; - static const uint16 MAP_DELETED_SIZE = 0; - static const uint16 MAP_CORPSE_SIZE = slots::_MainCount; - static const uint16 MAP_BAZAAR_SIZE = 80; - static const uint16 MAP_INSPECT_SIZE = slots::_MainEquipmentCount; - static const uint16 MAP_REAL_ESTATE_SIZE = 0; - static const uint16 MAP_VIEW_MOD_PC_SIZE = MAP_POSSESSIONS_SIZE; - static const uint16 MAP_VIEW_MOD_BANK_SIZE = MAP_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_SHARED_BANK_SIZE = MAP_SHARED_BANK_SIZE; - static const uint16 MAP_VIEW_MOD_LIMBO_SIZE = MAP_LIMBO_SIZE; - static const uint16 MAP_ALT_STORAGE_SIZE = 0; - static const uint16 MAP_ARCHIVED_SIZE = 0; - static const uint16 MAP_MAIL_SIZE = 0; - static const uint16 MAP_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 MAP_KRONO_SIZE = NOT_USED; - static const uint16 MAP_OTHER_SIZE = 0; + static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; + static const uint16 TYPE_BANK_SIZE = 24; + static const uint16 TYPE_SHARED_BANK_SIZE = 2; + static const uint16 TYPE_TRADE_SIZE = 8; + static const uint16 TYPE_WORLD_SIZE = 10; + static const uint16 TYPE_LIMBO_SIZE = 36; + static const uint16 TYPE_TRIBUTE_SIZE = 0; //? + static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; + static const uint16 TYPE_MERCHANT_SIZE = 0; + static const uint16 TYPE_DELETED_SIZE = 0; + static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; + static const uint16 TYPE_BAZAAR_SIZE = 80; + static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; + static const uint16 TYPE_REAL_ESTATE_SIZE = 0; + static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; + static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; + static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; + static const uint16 TYPE_ALT_STORAGE_SIZE = 0; + static const uint16 TYPE_ARCHIVED_SIZE = 0; + static const uint16 TYPE_MAIL_SIZE = 0; + static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_KRONO_SIZE = NOT_USED; + static const uint16 TYPE_OTHER_SIZE = 0; - static const int16 EQUIPMENT_BEGIN = slots::MainCharm; - static const int16 EQUIPMENT_END = slots::MainAmmo; - static const uint16 EQUIPMENT_SIZE = slots::_MainEquipmentCount; + static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; + static const int16 EQUIPMENT_END = inventory::SlotAmmo; + static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; - static const int16 GENERAL_BEGIN = slots::MainGeneral1; - static const int16 GENERAL_END = slots::MainGeneral8; - static const uint16 GENERAL_SIZE = slots::_MainGeneralCount; + static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; + static const int16 GENERAL_END = inventory::SlotGeneral8; + static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; static const int16 GENERAL_BAGS_BEGIN = 262; static const int16 GENERAL_BAGS_END_OFFSET = 79; static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; - static const int16 CURSOR = slots::MainCursor; + static const int16 CURSOR = inventory::SlotCursor; static const int16 CURSOR_BAG_BEGIN = 342; static const int16 CURSOR_BAG_END_OFFSET = 9; static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; @@ -170,8 +167,8 @@ namespace UF { static const int16 TRIBUTE_BEGIN = 400; static const int16 TRIBUTE_END = 404; - static const int16 CORPSE_BEGIN = slots::MainGeneral1; - static const int16 CORPSE_END = slots::MainGeneral1 + slots::MainCursor; + static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; + static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; static const uint16 ITEM_COMMON_SIZE = 5; static const uint16 ITEM_CONTAINER_SIZE = 10; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index efe7358db..e9536d9a3 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -104,8 +104,8 @@ bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iter std::string query = StringFormat("DELETE FROM inventory WHERE charid = %i " "AND ((slotid >= 8000 AND slotid <= 8999) " "OR slotid = %i OR (slotid >= %i AND slotid <= %i) )", - char_id, MainCursor, - EmuConstants::CURSOR_BAG_BEGIN, EmuConstants::CURSOR_BAG_END); + char_id, SlotCursor, + EQEmu::Constants::CURSOR_BAG_BEGIN, EQEmu::Constants::CURSOR_BAG_END); auto results = QueryDatabase(query); if (!results.Success()) { std::cout << "Clearing cursor failed: " << results.ErrorMessage() << std::endl; @@ -116,7 +116,7 @@ bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iter for(auto it = start; it != end; ++it, i++) { if (i > 8999) { break; } // shouldn't be anything in the queue that indexes this high ItemInst *inst = *it; - int16 use_slot = (i == 8000) ? MainCursor : i; + int16 use_slot = (i == 8000) ? SlotCursor : i; if (!SaveInventory(char_id, inst, use_slot)) { return false; } @@ -161,10 +161,10 @@ bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const Ite bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 slot_id) { //never save tribute slots: - if(slot_id >= EmuConstants::TRIBUTE_BEGIN && slot_id <= EmuConstants::TRIBUTE_END) + if (slot_id >= EQEmu::Constants::TRIBUTE_BEGIN && slot_id <= EQEmu::Constants::TRIBUTE_END) return true; - if (slot_id >= EmuConstants::SHARED_BANK_BEGIN && slot_id <= EmuConstants::SHARED_BANK_BAGS_END) { + if (slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { // Shared bank inventory if (!inst) { return DeleteSharedBankSlot(char_id, slot_id); @@ -191,9 +191,9 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 s bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer - uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; + uint32 augslot[EQEmu::Constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; if (inst->IsType(ItemClassCommon)) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { ItemInst *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM; } @@ -223,7 +223,7 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) - for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) { + for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::Constants::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = inst->GetItem(idx); SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); } @@ -238,9 +238,9 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer - uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; + uint32 augslot[EQEmu::Constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; if (inst->IsType(ItemClassCommon)) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { ItemInst *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM; } @@ -269,7 +269,7 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) { // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) - for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) { + for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::Constants::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = inst->GetItem(idx); SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); } @@ -427,7 +427,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) uint32 item_id = (uint32)atoi(row[1]); int8 charges = (int8)atoi(row[2]); - uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::Constants::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoi(row[3]); aug[1] = (uint32)atoi(row[4]); aug[2] = (uint32)atoi(row[5]); @@ -448,7 +448,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) ItemInst *inst = CreateBaseItem(item, charges); if (inst && item->ItemClass == ItemClassCommon) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } @@ -522,7 +522,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) uint16 charges = atoi(row[2]); uint32 color = atoul(row[3]); - uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::Constants::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoul(row[4]); aug[1] = (uint32)atoul(row[5]); @@ -584,8 +584,8 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) inst->SetOrnamentHeroModel(ornament_hero_model); if (instnodrop || - (((slot_id >= EmuConstants::EQUIPMENT_BEGIN && slot_id <= EmuConstants::EQUIPMENT_END) || - slot_id == MainPowerSource) && + (((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::Constants::EQUIPMENT_END) || + slot_id == SlotPowerSource) && inst->GetItem()->Attuneable)) inst->SetAttuned(true); @@ -608,7 +608,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) } if (item->ItemClass == ItemClassCommon) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } @@ -665,7 +665,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) int8 charges = atoi(row[2]); uint32 color = atoul(row[3]); - uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::Constants::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoi(row[4]); aug[1] = (uint32)atoi(row[5]); aug[2] = (uint32)atoi(row[6]); @@ -726,7 +726,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) inst->SetCharges(charges); if (item->ItemClass == ItemClassCommon) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } diff --git a/world/client.cpp b/world/client.cpp index d0ecac3c2..836b4c45b 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -211,9 +211,9 @@ void Client::SendMaxCharCreate() { auto outapp = new EQApplicationPacket(OP_SendMaxCharacters, sizeof(MaxCharacters_Struct)); MaxCharacters_Struct* mc = (MaxCharacters_Struct*)outapp->pBuffer; - mc->max_chars = EQLimits::CharacterCreationLimit(m_ClientVersion); - if (mc->max_chars > EmuConstants::CHARACTER_CREATION_LIMIT) - mc->max_chars = EmuConstants::CHARACTER_CREATION_LIMIT; + mc->max_chars = EQEmu::Limits::CharacterCreationLimit(m_ClientVersion); + if (mc->max_chars > EQEmu::Constants::CHARACTER_CREATION_LIMIT) + mc->max_chars = EQEmu::Constants::CHARACTER_CREATION_LIMIT; QueuePacket(outapp); safe_delete(outapp); @@ -746,8 +746,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { // This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above) // (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration) if (!pZoning) { - size_t character_limit = EQLimits::CharacterCreationLimit(eqs->GetClientVersion()); - if (character_limit > EmuConstants::CHARACTER_CREATION_LIMIT) { character_limit = EmuConstants::CHARACTER_CREATION_LIMIT; } + size_t character_limit = EQEmu::Limits::CharacterCreationLimit(eqs->GetClientVersion()); + if (character_limit > EQEmu::Constants::CHARACTER_CREATION_LIMIT) { character_limit = EQEmu::Constants::CHARACTER_CREATION_LIMIT; } if (eqs->GetClientVersion() == ClientVersion::Titanium) { character_limit = 8; } std::string tgh_query = StringFormat( diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 357ab3c33..cd73d9c7c 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -37,11 +37,11 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou { /* Set Character Creation Limit */ ClientVersion client_version = ClientVersionFromBit(clientVersionBit); - size_t character_limit = EQLimits::CharacterCreationLimit(client_version); + size_t character_limit = EQEmu::Limits::CharacterCreationLimit(client_version); // Validate against absolute server max - if (character_limit > EmuConstants::CHARACTER_CREATION_LIMIT) - character_limit = EmuConstants::CHARACTER_CREATION_LIMIT; + if (character_limit > EQEmu::Constants::CHARACTER_CREATION_LIMIT) + character_limit = EQEmu::Constants::CHARACTER_CREATION_LIMIT; // Force Titanium clients to use '8' if (client_version == ClientVersion::Titanium) @@ -117,7 +117,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou cse->Gender = (uint8)atoi(row[2]); cse->Face = (uint8)atoi(row[15]); - for (uint32 matslot = 0; matslot < _MaterialCount; matslot++) { // Processed below + for (uint32 matslot = 0; matslot < MaterialCount; matslot++) { // Processed below cse->Equip[matslot].Material = 0; cse->Equip[matslot].Unknown1 = 0; cse->Equip[matslot].EliteMaterial = 0; @@ -223,7 +223,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou const ItemInst* inst = nullptr; int16 invslot = 0; - for (uint32 matslot = 0; matslot < _MaterialCount; matslot++) { + for (uint32 matslot = 0; matslot < MaterialCount; matslot++) { invslot = Inventory::CalcSlotFromMaterial(matslot); if (invslot == INVALID_INDEX) { continue; } inst = inv.GetItem(invslot); diff --git a/zone/aa.cpp b/zone/aa.cpp index 403f9755d..229683550 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -419,7 +419,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) //gear stuff, need to make sure there's //no situation where this stuff can be duped - for(int x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::EQUIPMENT_END; x++) // (< 21) added MainAmmo + for (int x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::EQUIPMENT_END; x++) // (< 21) added MainAmmo { uint32 sitem = 0; sitem = CorpseToUse->GetWornItem(x); diff --git a/zone/attack.cpp b/zone/attack.cpp index 786eb128a..d831631c6 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -166,7 +166,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w } // If we're attacking with the secondary hand, play the dual wield anim - if (Hand == MainSecondary) // DW anim + if (Hand == SlotSecondary) // DW anim type = animDualWield; DoAnim(type); @@ -415,7 +415,7 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) // riposte -- it may seem crazy, but if the attacker has SPA 173 on them, they are immune to Ripo bool ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance; // Need to check if we have something in MainHand to actually attack with (or fists) - if (hand != MainRange && CanThisClassRiposte() && InFront && !ImmuneRipo) { + if (hand != SlotRange && CanThisClassRiposte() && InFront && !ImmuneRipo) { if (IsClient()) CastToClient()->CheckIncreaseSkill(SkillRiposte, other, -10); // check auto discs ... I guess aa/items too :P @@ -432,7 +432,7 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) chance -= chance * counter; } // AA Slippery Attacks - if (hand == MainSecondary) { + if (hand == SlotSecondary) { int slip = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail; chance += chance * slip / 100; } @@ -477,7 +477,7 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) } // parry - if (CanThisClassParry() && InFront && hand != MainRange) { + if (CanThisClassParry() && InFront && hand != SlotRange) { if (IsClient()) CastToClient()->CheckIncreaseSkill(SkillParry, other, -10); // check auto discs ... I guess aa/items too :P @@ -964,7 +964,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate } else { bool MagicGloves = false; if (IsClient()) { - const ItemInst *gloves = CastToClient()->GetInv().GetItem(MainHands); + const ItemInst *gloves = CastToClient()->GetInv().GetItem(SlotHands); if (gloves) MagicGloves = gloves->GetItemMagical(true); } @@ -1073,12 +1073,12 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code. ItemInst* weapon; - if (Hand == MainSecondary){ // Kaiyodo - Pick weapon from the attacking hand - weapon = GetInv().GetItem(MainSecondary); + if (Hand == SlotSecondary){ // Kaiyodo - Pick weapon from the attacking hand + weapon = GetInv().GetItem(SlotSecondary); OffHandAtk(true); } else{ - weapon = GetInv().GetItem(MainPrimary); + weapon = GetInv().GetItem(SlotPrimary); OffHandAtk(false); } @@ -1146,7 +1146,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b int ucDamageBonus = 0; - if( Hand == MainPrimary && GetLevel() >= 28 && IsWarriorClass() ) + if( Hand == SlotPrimary && GetLevel() >= 28 && IsWarriorClass() ) { // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. @@ -1159,7 +1159,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b } #endif //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. - if (Hand == MainSecondary) { + if (Hand == SlotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr, true ); @@ -1621,28 +1621,28 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool FaceTarget(GetTarget()); SkillUseTypes skillinuse = SkillHandtoHand; - if (Hand == MainPrimary) { + if (Hand == SlotPrimary) { skillinuse = static_cast(GetPrimSkill()); OffHandAtk(false); } - if (Hand == MainSecondary) { + if (Hand == SlotSecondary) { skillinuse = static_cast(GetSecSkill()); OffHandAtk(true); } //figure out what weapon they are using, if any const Item_Struct* weapon = nullptr; - if (Hand == MainPrimary && equipment[MainPrimary] > 0) - weapon = database.GetItem(equipment[MainPrimary]); - else if (equipment[MainSecondary]) - weapon = database.GetItem(equipment[MainSecondary]); + if (Hand == SlotPrimary && equipment[SlotPrimary] > 0) + weapon = database.GetItem(equipment[SlotPrimary]); + else if (equipment[SlotSecondary]) + weapon = database.GetItem(equipment[SlotSecondary]); //We dont factor much from the weapon into the attack. //Just the skill type so it doesn't look silly using punching animations and stuff while wielding weapons if(weapon) { Log.Out(Logs::Detail, Logs::Combat, "Attacking with weapon: %s (%d) (too bad im not using it for much)", weapon->Name, weapon->ID); - if(Hand == MainSecondary && weapon->ItemType == ItemTypeShield){ + if(Hand == SlotSecondary && weapon->ItemType == ItemTypeShield){ Log.Out(Logs::Detail, Logs::Combat, "Attack with shield canceled."); return false; } @@ -3532,7 +3532,7 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) { float ProcChance, ProcBonus; on->GetDefensiveProcChances(ProcBonus, ProcChance, hand , this); - if(hand != MainPrimary) + if(hand != SlotPrimary) ProcChance /= 2; int level_penalty = 0; @@ -3605,7 +3605,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on ProcBonus += static_cast(itembonuses.ProcChance) / 10.0f; // Combat Effects float ProcChance = GetProcChances(ProcBonus, hand); - if (hand != MainPrimary) //Is Archery intened to proc at 50% rate? + if (hand != SlotPrimary) //Is Archery intened to proc at 50% rate? ProcChance /= 2; // Try innate proc on weapon @@ -3642,7 +3642,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on proced = false; if (!proced && inst) { - for (int r = 0; r < EmuConstants::ITEM_COMMON_SIZE; r++) { + for (int r = 0; r < EQEmu::Constants::ITEM_COMMON_SIZE; r++) { const ItemInst *aug_i = inst->GetAugment(r); if (!aug_i) // no aug, try next slot! continue; @@ -3683,11 +3683,11 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, float ProcChance = 0.0f; ProcChance = GetProcChances(ProcBonus, hand); - if (hand != MainPrimary) //Is Archery intened to proc at 50% rate? + if (hand != SlotPrimary) //Is Archery intened to proc at 50% rate? ProcChance /= 2; bool rangedattk = false; - if (weapon && hand == MainRange) { + if (weapon && hand == SlotRange) { if (weapon->ItemType == ItemTypeArrow || weapon->ItemType == ItemTypeLargeThrowing || weapon->ItemType == ItemTypeSmallThrowing || @@ -3695,11 +3695,11 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, rangedattk = true; } - if (!weapon && hand == MainRange && GetSpecialAbility(SPECATK_RANGED_ATK)) + if (!weapon && hand == SlotRange && GetSpecialAbility(SPECATK_RANGED_ATK)) rangedattk = true; for (uint32 i = 0; i < MAX_PROCS; i++) { - if (IsPet() && hand != MainPrimary) //Pets can only proc spell procs from their primay hand (ie; beastlord pets) + if (IsPet() && hand != SlotPrimary) //Pets can only proc spell procs from their primay hand (ie; beastlord pets) continue; // If pets ever can proc from off hand, this will need to change // Not ranged @@ -3762,7 +3762,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, } } - if (HasSkillProcs() && hand != MainRange){ //We check ranged skill procs within the attack functions. + if (HasSkillProcs() && hand != SlotRange){ //We check ranged skill procs within the attack functions. uint16 skillinuse = 28; if (weapon) skillinuse = GetSkillByItemType(weapon->ItemType); @@ -4010,7 +4010,7 @@ void Mob::DoRiposte(Mob *defender) if (!defender) return; - defender->Attack(this, MainPrimary, true); + defender->Attack(this, SlotPrimary, true); if (HasDied()) return; @@ -4021,7 +4021,7 @@ void Mob::DoRiposte(Mob *defender) if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) { Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposted from SE_DoubleRiposte (%d percent chance)", DoubleRipChance); - defender->Attack(this, MainPrimary, true); + defender->Attack(this, SlotPrimary, true); if (HasDied()) return; } @@ -4034,7 +4034,7 @@ void Mob::DoRiposte(Mob *defender) Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposted from SE_GiveDoubleRiposte base1 == 0 (%d percent chance)", DoubleRipChance); - defender->Attack(this, MainPrimary, true); + defender->Attack(this, SlotPrimary, true); if (HasDied()) return; } @@ -4312,7 +4312,7 @@ float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) { if (!ReuseTime && hand) { weapon_speed = GetWeaponSpeedbyHand(hand); ProcChance = static_cast(weapon_speed) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f); - if (hand != MainPrimary) + if (hand != SlotPrimary) ProcChance /= 2; } @@ -4515,13 +4515,13 @@ void Client::SetAttackTimer() Timer *TimerToUse = nullptr; - for (int i = MainRange; i <= MainSecondary; i++) { + for (int i = SlotRange; i <= SlotSecondary; i++) { //pick a timer - if (i == MainPrimary) + if (i == SlotPrimary) TimerToUse = &attack_timer; - else if (i == MainRange) + else if (i == SlotRange) TimerToUse = &ranged_timer; - else if (i == MainSecondary) + else if (i == SlotSecondary) TimerToUse = &attack_dw_timer; else //invalid slot (hands will always hit this) continue; @@ -4534,7 +4534,7 @@ void Client::SetAttackTimer() ItemToUse = ci->GetItem(); //special offhand stuff - if (i == MainSecondary) { + if (i == SlotSecondary) { //if we cant dual wield, skip it if (!CanThisClassDualWield() || HasTwoHanderEquipped()) { attack_dw_timer.Disable(); @@ -4608,19 +4608,19 @@ void NPC::SetAttackTimer() else speed = static_cast(((attack_delay / haste_mod) + ((hhe / 100.0f) * attack_delay)) * 100); - for (int i = MainRange; i <= MainSecondary; i++) { + for (int i = SlotRange; i <= SlotSecondary; i++) { //pick a timer - if (i == MainPrimary) + if (i == SlotPrimary) TimerToUse = &attack_timer; - else if (i == MainRange) + else if (i == SlotRange) TimerToUse = &ranged_timer; - else if (i == MainSecondary) + else if (i == SlotSecondary) TimerToUse = &attack_dw_timer; else //invalid slot (hands will always hit this) continue; //special offhand stuff - if (i == MainSecondary) { + if (i == SlotSecondary) { // SPECATK_QUAD is uncheesable if(!CanThisClassDualWield() || (HasTwoHanderEquipped() && !GetSpecialAbility(SPECATK_QUAD))) { attack_dw_timer.Disable(); @@ -4642,7 +4642,7 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) bool candouble = CanThisClassDoubleAttack(); // extra off hand non-sense, can only double with skill of 150 or above // or you have any amount of GiveDoubleAttack - if (candouble && hand == MainSecondary) + if (candouble && hand == SlotSecondary) candouble = GetSkill(SkillDoubleAttack) > 149 || (aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack) > 0; if (candouble) { @@ -4650,7 +4650,7 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) if (CheckDoubleAttack()) { Attack(target, hand, false, false, IsFromSpell); // you can only triple from the main hand - if (hand == MainPrimary && CanThisClassTripleAttack()) { + if (hand == SlotPrimary && CanThisClassTripleAttack()) { CheckIncreaseSkill(SkillTripleAttack, target, -10); if (CheckTripleAttack()) Attack(target, hand, false, false, IsFromSpell); @@ -4658,7 +4658,7 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) } } - if (hand == MainPrimary) { + if (hand == SlotPrimary) { // According to http://www.monkly-business.net/forums/showpost.php?p=312095&postcount=168 a dev told them flurry isn't dependant on triple attack // the parses kind of back that up and all of my parses seemed to be 4 or 5 attacks in the round which would work out to be // doubles or triples with 2 from flurries or triple with 1 or 2 flurries ... Going with the "dev quote" I guess like we've always had it @@ -4711,9 +4711,9 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec if (RuleB(Combat, UseLiveCombatRounds)) { // A "quad" on live really is just a successful dual wield where both double attack // The mobs that could triple lost the ability to when the triple attack skill was added in - Attack(target, MainPrimary, false, false, false, opts, special); + Attack(target, SlotPrimary, false, false, false, opts, special); if (CanThisClassDoubleAttack() && CheckDoubleAttack()){ - Attack(target, MainPrimary, false, false, false, opts, special); + Attack(target, SlotPrimary, false, false, false, opts, special); if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ int chance = spellbonuses.PC_Pet_Flurry + itembonuses.PC_Pet_Flurry + aabonuses.PC_Pet_Flurry; @@ -4727,14 +4727,14 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec if (IsNPC()) { int16 n_atk = CastToNPC()->GetNumberOfAttacks(); if (n_atk <= 1) { - Attack(target, MainPrimary, false, false, false, opts, special); + Attack(target, SlotPrimary, false, false, false, opts, special); } else { for (int i = 0; i < n_atk; ++i) { - Attack(target, MainPrimary, false, false, false, opts, special); + Attack(target, SlotPrimary, false, false, false, opts, special); } } } else { - Attack(target, MainPrimary, false, false, false, opts, special); + Attack(target, SlotPrimary, false, false, false, opts, special); } // we use this random value in three comparisons with different @@ -4745,15 +4745,15 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec // check double attack, this is NOT the same rules that clients use... && RandRoll < (GetLevel() + NPCDualAttackModifier)) { - Attack(target, MainPrimary, false, false, false, opts, special); + Attack(target, SlotPrimary, false, false, false, opts, special); // lets see if we can do a triple attack with the main hand // pets are excluded from triple and quads... if ((GetSpecialAbility(SPECATK_TRIPLE) || GetSpecialAbility(SPECATK_QUAD)) && !IsPet() && RandRoll < (GetLevel() + NPCTripleAttackModifier)) { - Attack(target, MainPrimary, false, false, false, opts, special); + Attack(target, SlotPrimary, false, false, false, opts, special); // now lets check the quad attack if (GetSpecialAbility(SPECATK_QUAD) && RandRoll < (GetLevel() + NPCQuadAttackModifier)) { - Attack(target, MainPrimary, false, false, false, opts, special); + Attack(target, SlotPrimary, false, false, false, opts, special); } } } @@ -4769,9 +4769,9 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int speci (RuleB(Combat, UseLiveCombatRounds) && GetSpecialAbility(SPECATK_QUAD))) || GetEquipment(MaterialSecondary) != 0) { if (CheckDualWield()) { - Attack(target, MainSecondary, false, false, false, opts, special); + Attack(target, SlotSecondary, false, false, false, opts, special); if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()){ - Attack(target, MainSecondary, false, false, false, opts, special); + Attack(target, SlotSecondary, false, false, false, opts, special); if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ int chance = spellbonuses.PC_Pet_Flurry + itembonuses.PC_Pet_Flurry + aabonuses.PC_Pet_Flurry; diff --git a/zone/beacon.h b/zone/beacon.h index a35f6a1ed..ed59ee7c9 100644 --- a/zone/beacon.h +++ b/zone/beacon.h @@ -36,7 +36,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } - virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index f57e92247..57fc3da48 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -145,34 +145,34 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { unsigned int i; // Update: MainAmmo should only calc skill mods (TODO: Check for other cases) - for (i = MainCharm; i <= MainAmmo; i++) { + for (i = SlotCharm; i <= SlotAmmo; i++) { const ItemInst* inst = m_inv[i]; if(inst == 0) continue; - AddItemBonuses(inst, newbon, false, false, 0, (i == MainAmmo)); + AddItemBonuses(inst, newbon, false, false, 0, (i == SlotAmmo)); //These are given special flags due to how often they are checked for various spell effects. const Item_Struct *item = inst->GetItem(); - if (i == MainSecondary && (item && item->ItemType == ItemTypeShield)) + if (i == SlotSecondary && (item && item->ItemType == ItemTypeShield)) SetShieldEquiped(true); - else if (i == MainPrimary && (item && item->ItemType == ItemType2HBlunt)) { + else if (i == SlotPrimary && (item && item->ItemType == ItemType2HBlunt)) { SetTwoHandBluntEquiped(true); SetTwoHanderEquipped(true); - } else if (i == MainPrimary && (item && (item->ItemType == ItemType2HSlash || item->ItemType == ItemType2HPiercing))) + } else if (i == SlotPrimary && (item && (item->ItemType == ItemType2HSlash || item->ItemType == ItemType2HPiercing))) SetTwoHanderEquipped(true); } //Power Source Slot if (GetClientVersion() >= ClientVersion::SoF) { - const ItemInst* inst = m_inv[MainPowerSource]; + const ItemInst* inst = m_inv[SlotPowerSource]; if(inst) AddItemBonuses(inst, newbon); } //tribute items - for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++) { - const ItemInst* inst = m_inv[EmuConstants::TRIBUTE_BEGIN + i]; + for (i = 0; i < EQEmu::Constants::TRIBUTE_SIZE; i++) { + const ItemInst* inst = m_inv[EQEmu::Constants::TRIBUTE_BEGIN + i]; if(inst == 0) continue; AddItemBonuses(inst, newbon, false, true); @@ -180,7 +180,7 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { //Optional ability to have worn effects calculate as an addititive bonus instead of highest value if (RuleI(Spells, AdditiveBonusWornType) && RuleI(Spells, AdditiveBonusWornType) != ET_WornEffect){ - for (i = MainCharm; i < MainAmmo; i++) { + for (i = SlotCharm; i < SlotAmmo; i++) { const ItemInst* inst = m_inv[i]; if(inst == 0) continue; @@ -526,7 +526,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu } if (!isAug) { - for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) + for (int i = 0; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) AddItemBonuses(inst->GetAugment(i), newbon, true, false, rec_level, ammo_slot_item); } } @@ -564,7 +564,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool if (!isAug) { int i; - for (i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + for (i = 0; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { AdditiveWornBonuses(inst->GetAugment(i),newbon,true); } } @@ -575,7 +575,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { bool food = false; bool drink = false; - for (i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_BAGS_BEGIN; i++) + for (i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_BAGS_BEGIN; i++) { if (food && drink) break; @@ -591,7 +591,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { AddItemBonuses(inst, newbon); } } - for (i = EmuConstants::GENERAL_BAGS_BEGIN; i <= EmuConstants::GENERAL_BAGS_END; i++) + for (i = EQEmu::Constants::GENERAL_BAGS_BEGIN; i <= EQEmu::Constants::GENERAL_BAGS_END; i++) { if (food && drink) break; @@ -3200,7 +3200,7 @@ void NPC::CalcItemBonuses(StatBonuses *newbon) { if(newbon){ - for(int i = 0; i < EmuConstants::EQUIPMENT_SIZE; i++){ + for (int i = 0; i < EQEmu::Constants::EQUIPMENT_SIZE; i++){ const Item_Struct *cur = database.GetItem(equipment[i]); if(cur){ //basic stats @@ -3278,24 +3278,24 @@ void Client::CalcItemScale() { bool changed = false; // MainAmmo excluded in helper function below - if(CalcItemScale(EmuConstants::EQUIPMENT_BEGIN, EmuConstants::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) + if (CalcItemScale(EQEmu::Constants::EQUIPMENT_BEGIN, EQEmu::Constants::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) changed = true; - if(CalcItemScale(EmuConstants::GENERAL_BEGIN, EmuConstants::GENERAL_END)) // original coding excluded MainCursor (< 30) + if (CalcItemScale(EQEmu::Constants::GENERAL_BEGIN, EQEmu::Constants::GENERAL_END)) // original coding excluded MainCursor (< 30) changed = true; // I excluded cursor bag slots here because cursor was excluded above..if this is incorrect, change 'slot_y' here to CURSOR_BAG_END // and 'slot_y' above to CURSOR from GENERAL_END above - or however it is supposed to be... - if(CalcItemScale(EmuConstants::GENERAL_BAGS_BEGIN, EmuConstants::GENERAL_BAGS_END)) // (< 341) + if (CalcItemScale(EQEmu::Constants::GENERAL_BAGS_BEGIN, EQEmu::Constants::GENERAL_BAGS_END)) // (< 341) changed = true; - if(CalcItemScale(EmuConstants::TRIBUTE_BEGIN, EmuConstants::TRIBUTE_END)) // (< 405) + if (CalcItemScale(EQEmu::Constants::TRIBUTE_BEGIN, EQEmu::Constants::TRIBUTE_END)) // (< 405) changed = true; //Power Source Slot if (GetClientVersion() >= ClientVersion::SoF) { - if(CalcItemScale(MainPowerSource, MainPowerSource)) + if(CalcItemScale(SlotPowerSource, SlotPowerSource)) changed = true; } @@ -3310,7 +3310,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { bool changed = false; uint32 i; for (i = slot_x; i <= slot_y; i++) { - if (i == MainAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot + if (i == SlotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot continue; ItemInst* inst = m_inv.GetItem(i); @@ -3320,7 +3320,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) - if (i >= EmuConstants::GENERAL_BAGS_BEGIN && i <= EmuConstants::GENERAL_BAGS_END) { + if (i >= EQEmu::Constants::GENERAL_BAGS_BEGIN && i <= EQEmu::Constants::GENERAL_BAGS_END) { ItemInst* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; @@ -3340,7 +3340,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { } //iterate all augments - for (int x = AUG_BEGIN; x < EmuConstants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_BEGIN; x < EQEmu::Constants::ITEM_COMMON_SIZE; ++x) { ItemInst * a_inst = inst->GetAugment(x); if(!a_inst) @@ -3372,24 +3372,24 @@ void Client::DoItemEnterZone() { bool changed = false; // MainAmmo excluded in helper function below - if(DoItemEnterZone(EmuConstants::EQUIPMENT_BEGIN, EmuConstants::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) + if (DoItemEnterZone(EQEmu::Constants::EQUIPMENT_BEGIN, EQEmu::Constants::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) changed = true; - if(DoItemEnterZone(EmuConstants::GENERAL_BEGIN, EmuConstants::GENERAL_END)) // original coding excluded MainCursor (< 30) + if (DoItemEnterZone(EQEmu::Constants::GENERAL_BEGIN, EQEmu::Constants::GENERAL_END)) // original coding excluded MainCursor (< 30) changed = true; // I excluded cursor bag slots here because cursor was excluded above..if this is incorrect, change 'slot_y' here to CURSOR_BAG_END // and 'slot_y' above to CURSOR from GENERAL_END above - or however it is supposed to be... - if(DoItemEnterZone(EmuConstants::GENERAL_BAGS_BEGIN, EmuConstants::GENERAL_BAGS_END)) // (< 341) + if (DoItemEnterZone(EQEmu::Constants::GENERAL_BAGS_BEGIN, EQEmu::Constants::GENERAL_BAGS_END)) // (< 341) changed = true; - if(DoItemEnterZone(EmuConstants::TRIBUTE_BEGIN, EmuConstants::TRIBUTE_END)) // (< 405) + if (DoItemEnterZone(EQEmu::Constants::TRIBUTE_BEGIN, EQEmu::Constants::TRIBUTE_END)) // (< 405) changed = true; //Power Source Slot if (GetClientVersion() >= ClientVersion::SoF) { - if(DoItemEnterZone(MainPowerSource, MainPowerSource)) + if(DoItemEnterZone(SlotPowerSource, SlotPowerSource)) changed = true; } @@ -3403,7 +3403,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { // behavior change: 'slot_y' is now [RANGE]_END and not [RANGE]_END + 1 bool changed = false; for(uint32 i = slot_x; i <= slot_y; i++) { - if (i == MainAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot + if (i == SlotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot continue; ItemInst* inst = m_inv.GetItem(i); @@ -3413,7 +3413,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) - if (i >= EmuConstants::GENERAL_BAGS_BEGIN && i <= EmuConstants::GENERAL_BAGS_END) { + if (i >= EQEmu::Constants::GENERAL_BAGS_BEGIN && i <= EQEmu::Constants::GENERAL_BAGS_END) { ItemInst* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; @@ -3425,7 +3425,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { uint16 oldexp = inst->GetExp(); parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); - if(i <= MainAmmo || i == MainPowerSource) { + if(i <= SlotAmmo || i == SlotPowerSource) { parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); } @@ -3435,7 +3435,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { update_slot = true; } } else { - if(i <= MainAmmo || i == MainPowerSource) { + if(i <= SlotAmmo || i == SlotPowerSource) { parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); } @@ -3443,7 +3443,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { } //iterate all augments - for (int x = AUG_BEGIN; x < EmuConstants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_BEGIN; x < EQEmu::Constants::ITEM_COMMON_SIZE; ++x) { ItemInst *a_inst = inst->GetAugment(x); if(!a_inst) diff --git a/zone/bot.cpp b/zone/bot.cpp index 2409b84b4..2c22a12a6 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -229,8 +229,8 @@ void Bot::SetBotSpellID(uint32 newSpellID) { } uint32 Bot::GetBotArcheryRange() { - const ItemInst *range_inst = GetBotItem(MainRange); - const ItemInst *ammo_inst = GetBotItem(MainAmmo); + const ItemInst *range_inst = GetBotItem(SlotRange); + const ItemInst *ammo_inst = GetBotItem(SlotAmmo); if (!range_inst || !ammo_inst) return 0; @@ -246,15 +246,15 @@ uint32 Bot::GetBotArcheryRange() { void Bot::ChangeBotArcherWeapons(bool isArcher) { if((GetClass()==WARRIOR) || (GetClass()==PALADIN) || (GetClass()==RANGER) || (GetClass()==SHADOWKNIGHT) || (GetClass()==ROGUE)) { if(!isArcher) { - BotAddEquipItem(MainPrimary, GetBotItemBySlot(MainPrimary)); - BotAddEquipItem(MainSecondary, GetBotItemBySlot(MainSecondary)); + BotAddEquipItem(SlotPrimary, GetBotItemBySlot(SlotPrimary)); + BotAddEquipItem(SlotSecondary, GetBotItemBySlot(SlotSecondary)); SetAttackTimer(); BotGroupSay(this, "My blade is ready"); } else { - BotRemoveEquipItem(MainPrimary); - BotRemoveEquipItem(MainSecondary); - BotAddEquipItem(MainAmmo, GetBotItemBySlot(MainAmmo)); - BotAddEquipItem(MainSecondary, GetBotItemBySlot(MainRange)); + BotRemoveEquipItem(SlotPrimary); + BotRemoveEquipItem(SlotSecondary); + BotAddEquipItem(SlotAmmo, GetBotItemBySlot(SlotAmmo)); + BotAddEquipItem(SlotSecondary, GetBotItemBySlot(SlotRange)); SetAttackTimer(); BotGroupSay(this, "My bow is true and ready"); } @@ -1175,11 +1175,11 @@ void Bot::GenerateArmorClass() { uint16 Bot::GetPrimarySkillValue() { SkillUseTypes skill = HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill - bool equiped = m_inv.GetItem(MainPrimary); + bool equiped = m_inv.GetItem(SlotPrimary); if(!equiped) skill = SkillHandtoHand; else { - uint8 type = m_inv.GetItem(MainPrimary)->GetItem()->ItemType; //is this the best way to do this? + uint8 type = m_inv.GetItem(SlotPrimary)->GetItem()->ItemType; //is this the best way to do this? switch(type) { case ItemType1HSlash: { skill = Skill1HSlashing; @@ -1703,8 +1703,8 @@ bool Bot::LoadPet() if (!botdb.LoadPetBuffs(GetBotID(), pet_buffs)) bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetBuffs(), GetCleanName()); - uint32 pet_items[EmuConstants::EQUIPMENT_SIZE]; - memset(pet_items, 0, (sizeof(uint32) * EmuConstants::EQUIPMENT_SIZE)); + uint32 pet_items[EQEmu::Constants::EQUIPMENT_SIZE]; + memset(pet_items, 0, (sizeof(uint32) * EQEmu::Constants::EQUIPMENT_SIZE)); if (!botdb.LoadPetItems(GetBotID(), pet_items)) bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetItems(), GetCleanName()); @@ -1731,11 +1731,11 @@ bool Bot::SavePet() char* pet_name = new char[64]; SpellBuff_Struct pet_buffs[BUFF_COUNT]; - uint32 pet_items[EmuConstants::EQUIPMENT_SIZE]; + uint32 pet_items[EQEmu::Constants::EQUIPMENT_SIZE]; memset(pet_name, 0, 64); memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * BUFF_COUNT)); - memset(pet_items, 0, (sizeof(uint32) * EmuConstants::EQUIPMENT_SIZE)); + memset(pet_items, 0, (sizeof(uint32) * EQEmu::Constants::EQUIPMENT_SIZE)); pet_inst->GetPetState(pet_buffs, pet_items, pet_name); @@ -1887,12 +1887,12 @@ void Bot::BotRangedAttack(Mob* other) { return; } - ItemInst* rangedItem = GetBotItem(MainRange); + ItemInst* rangedItem = GetBotItem(SlotRange); const Item_Struct* RangeWeapon = 0; if(rangedItem) RangeWeapon = rangedItem->GetItem(); - ItemInst* ammoItem = GetBotItem(MainAmmo); + ItemInst* ammoItem = GetBotItem(SlotAmmo); const Item_Struct* Ammo = 0; if(ammoItem) Ammo = ammoItem->GetItem(); @@ -1989,7 +1989,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes int damage = 0; uint32 hate = 0; - int Hand = MainPrimary; + int Hand = SlotPrimary; if (hate == 0 && weapon_damage > 1) hate = weapon_damage; @@ -2018,7 +2018,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes else damage = zone->random.Int(min_hit, max_hit); - if (other->AvoidDamage(this, damage, CanRiposte ? MainRange : MainPrimary)) { // MainRange excludes ripo, primary doesn't have any extra behavior + if (other->AvoidDamage(this, damage, CanRiposte ? SlotRange : SlotPrimary)) { // MainRange excludes ripo, primary doesn't have any extra behavior if (damage == -3) { DoRiposte(other); if (HasDied()) @@ -2043,7 +2043,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes damage = -5; if(skillinuse == SkillBash){ - const ItemInst* inst = GetBotItem(MainSecondary); + const ItemInst* inst = GetBotItem(SlotSecondary); const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -2090,19 +2090,19 @@ void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) case SkillFlyingKick: case SkillRoundKick: case SkillKick: - item_slot = MainFeet; + item_slot = SlotFeet; break; case SkillBash: - item_slot = MainSecondary; + item_slot = SlotSecondary; break; case SkillDragonPunch: case SkillEagleStrike: case SkillTigerClaw: - item_slot = MainHands; + item_slot = SlotHands; break; } - if (item_slot >= EmuConstants::EQUIPMENT_BEGIN){ + if (item_slot >= EQEmu::Constants::EQUIPMENT_BEGIN){ const ItemInst* inst = GetBotItem(item_slot); const Item_Struct* botweapon = 0; if(inst) @@ -2430,23 +2430,23 @@ void Bot::AI_Process() { // First, special attack per class (kick, backstab etc..) DoClassAttacks(GetTarget()); if(attack_timer.Check()) { - Attack(GetTarget(), MainPrimary); - TriggerDefensiveProcs(GetTarget(), MainPrimary, false); - ItemInst *wpn = GetBotItem(MainPrimary); - TryWeaponProc(wpn, GetTarget(), MainPrimary); + Attack(GetTarget(), SlotPrimary); + TriggerDefensiveProcs(GetTarget(), SlotPrimary, false); + ItemInst *wpn = GetBotItem(SlotPrimary); + TryWeaponProc(wpn, GetTarget(), SlotPrimary); bool tripleSuccess = false; if(BotOwner && GetTarget() && CanThisClassDoubleAttack()) { if(BotOwner && CheckBotDoubleAttack()) - Attack(GetTarget(), MainPrimary, true); + Attack(GetTarget(), SlotPrimary, true); if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_TRIPLE) && CheckBotDoubleAttack(true)) { tripleSuccess = true; - Attack(GetTarget(), MainPrimary, true); + Attack(GetTarget(), SlotPrimary, true); } //quad attack, does this belong here?? if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) - Attack(GetTarget(), MainPrimary, true); + Attack(GetTarget(), SlotPrimary, true); } //Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). @@ -2454,18 +2454,18 @@ void Bot::AI_Process() { if (GetTarget() && flurrychance) { if(zone->random.Int(0, 100) < flurrychance) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); - Attack(GetTarget(), MainPrimary, false); - Attack(GetTarget(), MainPrimary, false); + Attack(GetTarget(), SlotPrimary, false); + Attack(GetTarget(), SlotPrimary, false); } } int32 ExtraAttackChanceBonus = (spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance); if (GetTarget() && ExtraAttackChanceBonus) { - ItemInst *wpn = GetBotItem(MainPrimary); + ItemInst *wpn = GetBotItem(SlotPrimary); if(wpn) { if(wpn->GetItem()->ItemType == ItemType2HSlash || wpn->GetItem()->ItemType == ItemType2HBlunt || wpn->GetItem()->ItemType == ItemType2HPiercing) { if(zone->random.Int(0, 100) < ExtraAttackChanceBonus) - Attack(GetTarget(), MainPrimary, false); + Attack(GetTarget(), SlotPrimary, false); } } } @@ -2485,7 +2485,7 @@ void Bot::AI_Process() { //now off hand if(GetTarget() && attack_dw_timer.Check() && CanThisClassDualWield()) { - const ItemInst* instweapon = GetBotItem(MainSecondary); + const ItemInst* instweapon = GetBotItem(SlotSecondary); const Item_Struct* weapon = 0; //can only dual wield without a weapon if you're a monk if(instweapon || (botClass == MONK)) { @@ -2507,12 +2507,12 @@ void Bot::AI_Process() { DualWieldProbability += (DualWieldProbability * float(DWBonus) / 100.0f); float random = zone->random.Real(0, 1); if (random < DualWieldProbability){ // Max 78% of DW - Attack(GetTarget(), MainSecondary); // Single attack with offhand - ItemInst *wpn = GetBotItem(MainSecondary); - TryWeaponProc(wpn, GetTarget(), MainSecondary); + Attack(GetTarget(), SlotSecondary); // Single attack with offhand + ItemInst *wpn = GetBotItem(SlotSecondary); + TryWeaponProc(wpn, GetTarget(), SlotSecondary); if( CanThisClassDoubleAttack() && CheckBotDoubleAttack()) { if(GetTarget() && GetTarget()->GetHP() > -10) - Attack(GetTarget(), MainSecondary); // Single attack with offhand + Attack(GetTarget(), SlotSecondary); // Single attack with offhand } } } @@ -2683,12 +2683,12 @@ void Bot::PetAIProcess() { if(!botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY()) && botPet->GetTarget()->IsEnraged()) return; - if(botPet->Attack(GetTarget(), MainPrimary)) // try the main hand + if(botPet->Attack(GetTarget(), SlotPrimary)) // try the main hand if (botPet->GetTarget()) { // We're a pet so we re able to dual attack int32 RandRoll = zone->random.Int(0, 99); if (botPet->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier))) { - if(botPet->Attack(botPet->GetTarget(), MainPrimary)) {} + if(botPet->Attack(botPet->GetTarget(), SlotPrimary)) {} } } @@ -2726,11 +2726,11 @@ void Bot::PetAIProcess() { float DualWieldProbability = ((botPet->GetSkill(SkillDualWield) + botPet->GetLevel()) / 400.0f); DualWieldProbability -= zone->random.Real(0, 1); if(DualWieldProbability < 0) { - botPet->Attack(botPet->GetTarget(), MainSecondary); + botPet->Attack(botPet->GetTarget(), SlotSecondary); if (botPet->CanThisClassDoubleAttack()) { int32 RandRoll = zone->random.Int(0, 99); if (RandRoll < (botPet->GetLevel() + 20)) - botPet->Attack(botPet->GetTarget(), MainSecondary); + botPet->Attack(botPet->GetTarget(), SlotSecondary); } } } @@ -2853,7 +2853,7 @@ void Bot::Spawn(Client* botCharacterOwner) { // I re-enabled this until I can sort it out uint32 itemID = 0; uint8 materialFromSlot = 0xFF; - for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { + for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; ++i) { itemID = GetBotItemBySlot(i); if(itemID != 0) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); @@ -2956,7 +2956,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { } } - inst = GetBotItem(MainPrimary); + inst = GetBotItem(SlotPrimary); if(inst) { item = inst->GetItem(); if(item) { @@ -2967,7 +2967,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { } } - inst = GetBotItem(MainSecondary); + inst = GetBotItem(SlotSecondary); if(inst) { item = inst->GetItem(); if(item) { @@ -3218,7 +3218,7 @@ void Bot::BotAddEquipItem(int slot, uint32 id) { if(slot > 0 && id > 0) { uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); - if(materialFromSlot != _MaterialInvalid) { + if(materialFromSlot != MaterialInvalid) { equipment[slot] = id; // npc has more than just material slots. Valid material should mean valid inventory index SendWearChange(materialFromSlot); } @@ -3234,7 +3234,7 @@ void Bot::BotRemoveEquipItem(int slot) { if(slot > 0) { uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); - if(materialFromSlot != _MaterialInvalid) { + if(materialFromSlot != MaterialInvalid) { equipment[slot] = 0; // npc has more than just material slots. Valid material should mean valid inventory index SendWearChange(materialFromSlot); if(materialFromSlot == MaterialChest) @@ -3336,12 +3336,12 @@ void Bot::FinishTrade(Client* client, BotTradeType tradeType) { if(tradeType == BotTradeClientNormal) { // Items being traded are found in the normal trade window used to trade between a Client and a Client or NPC // Items in this mode are found in slot ids 3000 thru 3003 - thought bots used the full 8-slot window..? - PerformTradeWithClient(EmuConstants::TRADE_BEGIN, EmuConstants::TRADE_END, client); // {3000..3007} + PerformTradeWithClient(EQEmu::Constants::TRADE_BEGIN, EQEmu::Constants::TRADE_END, client); // {3000..3007} } else if(tradeType == BotTradeClientNoDropNoTrade) { // Items being traded are found on the Client's cursor slot, slot id 30. This item can be either a single item or it can be a bag. // If it is a bag, then we have to search for items in slots 331 thru 340 - PerformTradeWithClient(MainCursor, MainCursor, client); + PerformTradeWithClient(SlotCursor, SlotCursor, client); // TODO: Add logic here to test if the item in SLOT_CURSOR is a container type, if it is then we need to call the following: // PerformTradeWithClient(331, 340, client); @@ -3353,7 +3353,7 @@ void Bot::FinishTrade(Client* client, BotTradeType tradeType) { void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client) { if(client) { // TODO: Figure out what the actual max slot id is - const int MAX_SLOT_ID = EmuConstants::TRADE_BAGS_END; // was the old incorrect 3179.. + const int MAX_SLOT_ID = EQEmu::Constants::TRADE_BAGS_END; // was the old incorrect 3179.. uint32 items[MAX_SLOT_ID] = {0}; uint8 charges[MAX_SLOT_ID] = {0}; bool botCanWear[MAX_SLOT_ID] = {0}; @@ -3370,7 +3370,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli charges[i] = inst->GetCharges(); } - if (i == MainCursor) + if (i == SlotCursor) UpdateClient = true; //EQoffline: will give the items to the bots and change the bot stats @@ -3378,7 +3378,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli std::string TempErrorMessage; const Item_Struct* mWeaponItem = inst->GetItem(); bool failedLoreCheck = false; - for (int m = AUG_BEGIN; m GetAugment(m); if(itm) { @@ -3398,29 +3398,29 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli botCanWear[i] = BotCanWear; ItemInst* swap_item = nullptr; - const char* equipped[EmuConstants::EQUIPMENT_SIZE + 1] = {"Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", + const char* equipped[EQEmu::Constants::EQUIPMENT_SIZE + 1] = { "Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; bool success = false; int how_many_slots = 0; - for(int j = EmuConstants::EQUIPMENT_BEGIN; j <= (EmuConstants::EQUIPMENT_END + 1); ++j) { + for (int j = EQEmu::Constants::EQUIPMENT_BEGIN; j <= (EQEmu::Constants::EQUIPMENT_END + 1); ++j) { if((mWeaponItem->Slots & (1 << j))) { if (j == 22) j = 9999; how_many_slots++; if(!GetBotItem(j)) { - if(j == MainPrimary) { + if(j == SlotPrimary) { if((mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) { - if(GetBotItem(MainSecondary)) { + if(GetBotItem(SlotSecondary)) { if(mWeaponItem && (mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) { - if(client->CheckLoreConflict(GetBotItem(MainSecondary)->GetItem())) { + if(client->CheckLoreConflict(GetBotItem(SlotSecondary)->GetItem())) { failedLoreCheck = true; } } else { - ItemInst* remove_item = GetBotItem(MainSecondary); - BotTradeSwapItem(client, MainSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + ItemInst* remove_item = GetBotItem(SlotSecondary); + BotTradeSwapItem(client, SlotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } } @@ -3430,7 +3430,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } break; } - else if(j == MainSecondary) { + else if(j == SlotSecondary) { if(inst->IsWeapon()) { if(CanThisClassDualWield()) { BotTradeAddItem(mWeaponItem->ID, inst, inst->GetCharges(), mWeaponItem->Slots, j, &TempErrorMessage); @@ -3446,10 +3446,10 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli success = true; } if(success) { - if(GetBotItem(MainPrimary)) { - ItemInst* remove_item = GetBotItem(MainPrimary); + if(GetBotItem(SlotPrimary)) { + ItemInst* remove_item = GetBotItem(SlotPrimary); if((remove_item->GetItem()->ItemType == ItemType2HSlash) || (remove_item->GetItem()->ItemType == ItemType2HBlunt) || (remove_item->GetItem()->ItemType == ItemType2HPiercing)) { - BotTradeSwapItem(client, MainPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + BotTradeSwapItem(client, SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } break; @@ -3464,14 +3464,14 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } if(!success) { - for(int j = EmuConstants::EQUIPMENT_BEGIN; j <= (EmuConstants::EQUIPMENT_END + 1); ++j) { + for (int j = EQEmu::Constants::EQUIPMENT_BEGIN; j <= (EQEmu::Constants::EQUIPMENT_END + 1); ++j) { if((mWeaponItem->Slots & (1 << j))) { if (j == 22) j = 9999; swap_item = GetBotItem(j); failedLoreCheck = false; - for (int k = AUG_BEGIN; k < EmuConstants::ITEM_COMMON_SIZE; ++k) { + for (int k = AUG_BEGIN; k < EQEmu::Constants::ITEM_COMMON_SIZE; ++k) { ItemInst *itm = swap_item->GetAugment(k); if(itm) { @@ -3484,28 +3484,28 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli failedLoreCheck = true; } if(!failedLoreCheck) { - if(j == MainPrimary) { + if(j == SlotPrimary) { if((mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) { - if(GetBotItem(MainSecondary)) { - if(client->CheckLoreConflict(GetBotItem(MainSecondary)->GetItem())) { + if(GetBotItem(SlotSecondary)) { + if(client->CheckLoreConflict(GetBotItem(SlotSecondary)->GetItem())) { failedLoreCheck = true; } else { - ItemInst* remove_item = GetBotItem(MainSecondary); - BotTradeSwapItem(client, MainSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + ItemInst* remove_item = GetBotItem(SlotSecondary); + BotTradeSwapItem(client, SlotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } } if(!failedLoreCheck) { - BotTradeSwapItem(client, MainPrimary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); + BotTradeSwapItem(client, SlotPrimary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); success = true; } break; } - else if(j == MainSecondary) { + else if(j == SlotSecondary) { if(inst->IsWeapon()) { if(CanThisClassDualWield()) { - BotTradeSwapItem(client, MainSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); + BotTradeSwapItem(client, SlotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); success = true; } else { @@ -3514,13 +3514,13 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } else { - BotTradeSwapItem(client, MainSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); + BotTradeSwapItem(client, SlotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); success = true; } - if(success && GetBotItem(MainPrimary)) { - ItemInst* remove_item = GetBotItem(MainPrimary); + if(success && GetBotItem(SlotPrimary)) { + ItemInst* remove_item = GetBotItem(SlotPrimary); if((remove_item->GetItem()->ItemType == ItemType2HSlash) || (remove_item->GetItem()->ItemType == ItemType2HBlunt) || (remove_item->GetItem()->ItemType == ItemType2HPiercing)) { - BotTradeSwapItem(client, MainPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + BotTradeSwapItem(client, SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } break; @@ -3720,13 +3720,13 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b FaceTarget(GetTarget()); ItemInst* weapon = nullptr; - if(Hand == MainPrimary) { - weapon = GetBotItem(MainPrimary); + if(Hand == SlotPrimary) { + weapon = GetBotItem(SlotPrimary); OffHandAtk(false); } - if(Hand == MainSecondary) { - weapon = GetBotItem(MainSecondary); + if(Hand == SlotSecondary) { + weapon = GetBotItem(SlotSecondary); OffHandAtk(true); } @@ -3791,7 +3791,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b // This is not recommended for normal usage, as the damage bonus represents a non-trivial component of the DPS output // of weapons wielded by higher-level melee characters (especially for two-handed weapons). int ucDamageBonus = 0; - if(Hand == MainPrimary && GetLevel() >= 28 && IsWarriorClass()) { + if(Hand == SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr); @@ -3801,7 +3801,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b } #endif //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. - if (Hand==MainSecondary) { + if (Hand == SlotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr); min_hit += (int) ucDamageBonus; @@ -4269,7 +4269,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { int32 focus_max = 0; int32 focus_max_real = 0; //item focus - for(int x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::EQUIPMENT_END; x++) { + for (int x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::EQUIPMENT_END; x++) { TempItem = nullptr; ItemInst* ins = GetBotItem(x); if (!ins) @@ -4294,7 +4294,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { } } - for (int y = AUG_BEGIN; y < EmuConstants::ITEM_COMMON_SIZE; ++y) { + for (int y = AUG_BEGIN; y < EQEmu::Constants::ITEM_COMMON_SIZE; ++y) { ItemInst *aug = nullptr; aug = ins->GetAugment(y); if(aug) { @@ -4730,13 +4730,13 @@ float Bot::GetProcChances(float ProcBonus, uint16 hand) { float ProcChance = 0.0f; uint32 weapon_speed = 0; switch (hand) { - case MainPrimary: + case SlotPrimary: weapon_speed = attack_timer.GetDuration(); break; - case MainSecondary: + case SlotSecondary: weapon_speed = attack_dw_timer.GetDuration(); break; - case MainRange: + case SlotRange: weapon_speed = ranged_timer.GetDuration(); break; } @@ -4823,11 +4823,11 @@ void Bot::DoRiposte(Mob* defender) { if (!defender) return; - defender->Attack(this, MainPrimary, true); + defender->Attack(this, SlotPrimary, true); int32 DoubleRipChance = (defender->GetAABonuses().GiveDoubleRiposte[0] + defender->GetSpellBonuses().GiveDoubleRiposte[0] + defender->GetItemBonuses().GiveDoubleRiposte[0]); if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposte (%d percent chance)", DoubleRipChance); - defender->Attack(this, MainPrimary, true); + defender->Attack(this, SlotPrimary, true); } DoubleRipChance = defender->GetAABonuses().GiveDoubleRiposte[1]; @@ -4845,7 +4845,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, hate = hate_override; if(skill == SkillBash) { - const ItemInst* inst = GetBotItem(MainSecondary); + const ItemInst* inst = GetBotItem(SlotSecondary); const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -4859,14 +4859,14 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, } min_damage += (min_damage * GetMeleeMinDamageMod_SE(skill) / 100); - int hand = MainPrimary; + int hand = SlotPrimary; if (skill == SkillThrowing || skill == SkillArchery) - hand = MainRange; + hand = SlotRange; if (who->AvoidDamage(this, max_damage, hand)) { if (max_damage == -3) DoRiposte(who); } else { - if (HitChance || who->CheckHitChance(this, skill, MainPrimary)) { + if (HitChance || who->CheckHitChance(this, skill, SlotPrimary)) { who->MeleeMitigation(this, max_damage, min_damage); ApplyMeleeDamageBonus(skill, max_damage); max_damage += who->GetFcDamageAmtIncoming(this, 0, true, skill); @@ -4910,7 +4910,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { bool bIsBehind = false; bool bCanFrontalBS = false; - const ItemInst* inst = GetBotItem(MainPrimary); + const ItemInst* inst = GetBotItem(SlotPrimary); const Item_Struct* botpiercer = nullptr; if(inst) botpiercer = inst->GetItem(); @@ -4960,7 +4960,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { } } else - Attack(other, MainPrimary); + Attack(other, SlotPrimary); } void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { @@ -4970,11 +4970,11 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { int32 hate = 0; int32 primaryweapondamage = 0; int32 backstab_dmg = 0; - ItemInst* botweaponInst = GetBotItem(MainPrimary); + ItemInst* botweaponInst = GetBotItem(SlotPrimary); if(botweaponInst) { primaryweapondamage = GetWeaponDamage(other, botweaponInst); backstab_dmg = botweaponInst->GetItem()->BackstabDmg; - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) { ItemInst *aug = botweaponInst->GetAugment(i); if(aug) backstab_dmg += aug->GetItem()->BackstabDmg; @@ -5018,7 +5018,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { } void Bot::RogueAssassinate(Mob* other) { - ItemInst* botweaponInst = GetBotItem(MainPrimary); + ItemInst* botweaponInst = GetBotItem(SlotPrimary); if(botweaponInst) { if(GetWeaponDamage(other, botweaponInst)) other->Damage(this, 32000, SPELL_UNKNOWN, SkillBackstab); @@ -5084,7 +5084,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { case WARRIOR: if(level >= RuleI(Combat, NPCBashKickLevel)){ bool canBash = false; - if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(MainSecondary) && m_inv.GetItem(MainSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(MainPrimary) && (m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) + if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(SlotSecondary) && m_inv.GetItem(SlotSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(SlotPrimary) && (m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) canBash = true; if(!canBash || zone->random.Int(0, 100) > 25) @@ -5103,7 +5103,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { case SHADOWKNIGHT: case PALADIN: if(level >= RuleI(Combat, NPCBashKickLevel)){ - if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(MainSecondary) && m_inv.GetItem(MainSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(MainPrimary) && (m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(MainPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) + if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(SlotSecondary) && m_inv.GetItem(SlotSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(SlotPrimary) && (m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) skill_to_use = SkillBash; } break; @@ -5132,7 +5132,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if(skill_to_use == SkillBash) { if (target != this) { DoAnim(animTailRake); - if(GetWeaponDamage(target, GetBotItem(MainSecondary)) <= 0 && GetWeaponDamage(target, GetBotItem(MainShoulders)) <= 0) + if(GetWeaponDamage(target, GetBotItem(SlotSecondary)) <= 0 && GetWeaponDamage(target, GetBotItem(SlotShoulders)) <= 0) dmg = -5; else { if(!target->CheckHitChance(this, SkillBash, 0)) @@ -5182,7 +5182,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if(skill_to_use == SkillKick) { if(target != this) { DoAnim(animKick); - if(GetWeaponDamage(target, GetBotItem(MainFeet)) <= 0) + if(GetWeaponDamage(target, GetBotItem(SlotFeet)) <= 0) dmg = -5; else { if(!target->CheckHitChance(this, SkillKick, 0)) @@ -5349,7 +5349,7 @@ void Bot::EquipBot(std::string* errorMessage) { GetBotItems(m_inv, errorMessage); const ItemInst* inst = 0; const Item_Struct* item = 0; - for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { + for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { item = inst->GetItem(); @@ -5476,12 +5476,12 @@ void Bot::SetAttackTimer() { attack_timer.SetAtTrigger(4000, true); Timer* TimerToUse = nullptr; const Item_Struct* PrimaryWeapon = nullptr; - for (int i = MainRange; i <= MainSecondary; i++) { - if (i == MainPrimary) + for (int i = SlotRange; i <= SlotSecondary; i++) { + if (i == SlotPrimary) TimerToUse = &attack_timer; - else if (i == MainRange) + else if (i == SlotRange) TimerToUse = &ranged_timer; - else if (i == MainSecondary) + else if (i == SlotSecondary) TimerToUse = &attack_dw_timer; else continue; @@ -5491,7 +5491,7 @@ void Bot::SetAttackTimer() { if (ci) ItemToUse = ci->GetItem(); - if (i == MainSecondary) { + if (i == SlotSecondary) { if (PrimaryWeapon != nullptr) { if (PrimaryWeapon->ItemClass == ItemClassCommon && (PrimaryWeapon->ItemType == ItemType2HSlash || PrimaryWeapon->ItemType == ItemType2HBlunt || PrimaryWeapon->ItemType == ItemType2HPiercing)) { attack_dw_timer.Disable(); @@ -5522,7 +5522,7 @@ void Bot::SetAttackTimer() { speed = (RuleB(Spells, Jun182014HundredHandsRevamp) ? static_cast(((delay / haste_mod) + ((hhe / 1000.0f) * (delay / haste_mod))) * 100) : static_cast(((delay / haste_mod) + ((hhe / 100.0f) * delay)) * 100)); TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true); - if(i == MainPrimary) + if(i == SlotPrimary) PrimaryWeapon = ItemToUse; } } @@ -7166,7 +7166,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { // Modded to display power source items (will only show up on SoF+ client inspect windows though.) // I don't think bots are currently coded to use them..but, you'll have to use '#bot inventory list' // to see them on a Titanium client when/if they are activated. - for(int16 L = EmuConstants::EQUIPMENT_BEGIN; L <= MainWaist; L++) { + for (int16 L = EQEmu::Constants::EQUIPMENT_BEGIN; L <= SlotWaist; L++) { inst = inspectedBot->GetBotItem(L); if(inst) { @@ -7180,28 +7180,28 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { } } - inst = inspectedBot->GetBotItem(MainPowerSource); + inst = inspectedBot->GetBotItem(SlotPowerSource); if(inst) { item = inst->GetItem(); if(item) { - strcpy(insr->itemnames[SoF::slots::MainPowerSource], item->Name); - insr->itemicons[SoF::slots::MainPowerSource] = item->Icon; + strcpy(insr->itemnames[SoF::inventory::SlotPowerSource], item->Name); + insr->itemicons[SoF::inventory::SlotPowerSource] = item->Icon; } else - insr->itemicons[SoF::slots::MainPowerSource] = 0xFFFFFFFF; + insr->itemicons[SoF::inventory::SlotPowerSource] = 0xFFFFFFFF; } - inst = inspectedBot->GetBotItem(MainAmmo); + inst = inspectedBot->GetBotItem(SlotAmmo); if(inst) { item = inst->GetItem(); if(item) { - strcpy(insr->itemnames[SoF::slots::MainAmmo], item->Name); - insr->itemicons[SoF::slots::MainAmmo] = item->Icon; + strcpy(insr->itemnames[SoF::inventory::SlotAmmo], item->Name); + insr->itemicons[SoF::inventory::SlotAmmo] = item->Icon; } else - insr->itemicons[SoF::slots::MainAmmo] = 0xFFFFFFFF; + insr->itemicons[SoF::inventory::SlotAmmo] = 0xFFFFFFFF; } strcpy(insr->text, inspectedBot->GetInspectMessage().text); @@ -7214,7 +7214,7 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) { const Item_Struct* itemtmp = 0; - for (int i = EmuConstants::EQUIPMENT_BEGIN; i <= (EmuConstants::EQUIPMENT_END + 1); ++i) { + for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= (EQEmu::Constants::EQUIPMENT_END + 1); ++i) { const ItemInst* item = GetBotItem((i == 22 ? 9999 : i)); if(item) { AddItemBonuses(item, newbon); @@ -7527,7 +7527,7 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, if (!isAug) { - for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) + for (int i = 0; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) AddItemBonuses(inst->GetAugment(i),newbon,true, false, rec_level); } @@ -8015,12 +8015,12 @@ uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { int Bot::GetRawACNoShield(int &shield_ac) { int ac = itembonuses.AC + spellbonuses.AC; shield_ac = 0; - ItemInst* inst = GetBotItem(MainSecondary); + ItemInst* inst = GetBotItem(SlotSecondary); if(inst) { if(inst->GetItem()->ItemType == ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; - for (uint8 i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + for (uint8 i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { if(inst->GetAugment(i)) { ac -= inst->GetAugment(i)->GetItem()->AC; shield_ac += inst->GetAugment(i)->GetItem()->AC; @@ -8035,7 +8035,7 @@ uint32 Bot::CalcCurrentWeight() { const Item_Struct* TempItem = 0; ItemInst* inst; uint32 Total = 0; - for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { + for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { TempItem = inst->GetItem(); @@ -8404,7 +8404,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) } else { uint8 mat_slot = Inventory::CalcMaterialFromSlot(slot_id); - if (mat_slot == _MaterialInvalid || mat_slot >= MaterialPrimary) + if (mat_slot == MaterialInvalid || mat_slot >= MaterialPrimary) return false; ItemInst* inst = m_inv.GetItem(slot_id); diff --git a/zone/bot.h b/zone/bot.h index 49d82f72a..0b39ee079 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -77,9 +77,9 @@ static const std::string bot_stance_name[BOT_STANCE_COUNT] = { static const char* GetBotStanceName(int stance_id) { return bot_stance_name[VALIDBOTSTANCE(stance_id)].c_str(); } -#define VALIDBOTEQUIPSLOT(x) ((x >= EmuConstants::EQUIPMENT_BEGIN && x <= EmuConstants::EQUIPMENT_END) ? (x) : ((x == MainPowerSource) ? (22) : (23))) +#define VALIDBOTEQUIPSLOT(x) ((x >= EQEmu::Constants::EQUIPMENT_BEGIN && x <= EQEmu::Constants::EQUIPMENT_END) ? (x) : ((x == SlotPowerSource) ? (22) : (23))) -static std::string bot_equip_slot_name[EmuConstants::EQUIPMENT_SIZE + 2] = +static std::string bot_equip_slot_name[EQEmu::Constants::EQUIPMENT_SIZE + 2] = { "Charm", // MainCharm "Left Ear", // MainEar1 @@ -207,7 +207,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 204afeffc..c69cfda44 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -2395,7 +2395,7 @@ namespace ActionableBots continue; mod_skill_value = base_skill_value; - for (int16 index = EmuConstants::EQUIPMENT_BEGIN; index <= EmuConstants::EQUIPMENT_END; ++index) { + for (int16 index = EQEmu::Constants::EQUIPMENT_BEGIN; index <= EQEmu::Constants::EQUIPMENT_END; ++index) { const ItemInst* indexed_item = bot_iter->GetBotItem(index); if (indexed_item && indexed_item->GetItem()->SkillModType == skill_type) mod_skill_value += (base_skill_value * (((float)indexed_item->GetItem()->SkillModValue) / 100.0f)); @@ -4357,7 +4357,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) } const int ab_mask = ActionableBots::ABM_NoFilter; - uint8 material_slot = _MaterialInvalid; + uint8 material_slot = MaterialInvalid; int16 slot_id = INVALID_INDEX; bool dye_all = (sep->arg[1][0] == '*'); @@ -6823,24 +6823,24 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) linker.SetLinkType(linker.linkItemInst); uint32 inventory_count = 0; - for (int i = EmuConstants::EQUIPMENT_BEGIN; i <= (EmuConstants::EQUIPMENT_END + 1); ++i) { - if ((i == MainSecondary) && is2Hweapon) + for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= (EQEmu::Constants::EQUIPMENT_END + 1); ++i) { + if ((i == SlotSecondary) && is2Hweapon) continue; - inst = my_bot->CastToBot()->GetBotItem(i == 22 ? 9999 : i); + inst = my_bot->CastToBot()->GetBotItem(i == 22 ? SlotPowerSource : i); if (!inst || !inst->GetItem()) { - c->Message(m_message, "I need something for my %s (slot %i)", GetBotEquipSlotName(i), (i == 22 ? 9999 : i)); + c->Message(m_message, "I need something for my %s (slot %i)", GetBotEquipSlotName(i), (i == 22 ? SlotPowerSource : i)); continue; } item = inst->GetItem(); - if ((i == MainPrimary) && ((item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HPiercing))) { + if ((i == SlotPrimary) && ((item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HPiercing))) { is2Hweapon = true; } linker.SetItemInst(inst); item_link = linker.GenerateLink(); - c->Message(m_message, "Using %s in my %s (slot %i)", item_link.c_str(), GetBotEquipSlotName(i), (i == 22 ? 9999 : i)); + c->Message(m_message, "Using %s in my %s (slot %i)", item_link.c_str(), GetBotEquipSlotName(i), (i == 22 ? SlotPowerSource : i)); ++inventory_count; } @@ -6879,7 +6879,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) } int slotId = atoi(sep->arg[1]); - if (!sep->IsNumber(1) || ((slotId > EmuConstants::EQUIPMENT_END || slotId < EmuConstants::EQUIPMENT_BEGIN) && slotId != 9999)) { + if (!sep->IsNumber(1) || ((slotId > EQEmu::Constants::EQUIPMENT_END || slotId < EQEmu::Constants::EQUIPMENT_BEGIN) && slotId != SlotPowerSource)) { c->Message(m_fail, "Valid slots are 0-21 or 9999"); return; } @@ -6894,7 +6894,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) return; } - for (int m = AUG_BEGIN; m < EmuConstants::ITEM_COMMON_SIZE; ++m) { + for (int m = AUG_BEGIN; m < EQEmu::Constants::ITEM_COMMON_SIZE; ++m) { if (!itminst) break; @@ -6911,7 +6911,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) std::string error_message; if (itm) { c->PushItemOnCursor(*itminst, true); - if ((slotId == MainRange) || (slotId == MainAmmo) || (slotId == MainPrimary) || (slotId == MainSecondary)) + if ((slotId == SlotRange) || (slotId == SlotAmmo) || (slotId == SlotPrimary) || (slotId == SlotSecondary)) my_bot->SetBotArcher(false); my_bot->RemoveBotItemBySlot(slotId, &error_message); @@ -6925,31 +6925,31 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) } switch (slotId) { - case MainCharm: - case MainEar1: - case MainHead: - case MainFace: - case MainEar2: - case MainNeck: - case MainBack: - case MainWrist1: - case MainWrist2: - case MainRange: - case MainPrimary: - case MainSecondary: - case MainFinger1: - case MainFinger2: - case MainChest: - case MainWaist: - case MainPowerSource: - case MainAmmo: + case SlotCharm: + case SlotEar1: + case SlotHead: + case SlotFace: + case SlotEar2: + case SlotNeck: + case SlotBack: + case SlotWrist1: + case SlotWrist2: + case SlotRange: + case SlotPrimary: + case SlotSecondary: + case SlotFinger1: + case SlotFinger2: + case SlotChest: + case SlotWaist: + case SlotPowerSource: + case SlotAmmo: c->Message(m_message, "My %s is %s unequipped", GetBotEquipSlotName(slotId), ((itm) ? ("now") : ("already"))); break; - case MainShoulders: - case MainArms: - case MainHands: - case MainLegs: - case MainFeet: + case SlotShoulders: + case SlotArms: + case SlotHands: + case SlotLegs: + case SlotFeet: c->Message(m_message, "My %s are %s unequipped", GetBotEquipSlotName(slotId), ((itm) ? ("now") : ("already"))); break; default: diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 54a701612..922259cab 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1058,7 +1058,7 @@ bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) for (auto row = results.begin(); row != results.end(); ++row) { int16 slot_id = atoi(row[0]); - if ((slot_id < EmuConstants::EQUIPMENT_BEGIN || slot_id > EmuConstants::EQUIPMENT_END) && slot_id != MainPowerSource) + if ((slot_id < EQEmu::Constants::EQUIPMENT_BEGIN || slot_id > EQEmu::Constants::EQUIPMENT_END) && slot_id != SlotPowerSource) continue; uint32 item_id = atoi(row[1]); @@ -1091,7 +1091,7 @@ bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) if (item_inst->GetItem()->Attuneable) { if (atoi(row[4])) item_inst->SetAttuned(true); - else if (((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || slot_id == 9999)) + else if (((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::Constants::EQUIPMENT_END) || slot_id == SlotPowerSource)) item_inst->SetAttuned(true); } @@ -1159,7 +1159,7 @@ bool BotDatabase::LoadItemBySlot(Bot* bot_inst) bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint32& item_id) { - if (!bot_id || (slot_id > EmuConstants::EQUIPMENT_END && slot_id != MainPowerSource)) + if (!bot_id || (slot_id > EQEmu::Constants::EQUIPMENT_END && slot_id != SlotPowerSource)) return false; query = StringFormat("SELECT `item_id` FROM `bot_inventories` WHERE `bot_id` = '%i' AND `slot_id` = '%i' LIMIT 1", bot_id, slot_id); @@ -1177,7 +1177,7 @@ bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const ItemInst* item_inst) { - if (!bot_inst || !bot_inst->GetBotID() || (slot_id > EmuConstants::EQUIPMENT_END && slot_id != MainPowerSource)) + if (!bot_inst || !bot_inst->GetBotID() || (slot_id > EQEmu::Constants::EQUIPMENT_END && slot_id != SlotPowerSource)) return false; if (!DeleteItemBySlot(bot_inst->GetBotID(), slot_id)) @@ -1187,7 +1187,7 @@ bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const Item return true; uint32 augment_id[] = { 0, 0, 0, 0, 0, 0 }; - for (int augment_iter = 0; augment_iter < EmuConstants::ITEM_COMMON_SIZE; ++augment_iter) + for (int augment_iter = 0; augment_iter < EQEmu::Constants::ITEM_COMMON_SIZE; ++augment_iter) augment_id[augment_iter] = item_inst->GetAugmentItemID(augment_iter); query = StringFormat( @@ -1255,7 +1255,7 @@ bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const Item bool BotDatabase::DeleteItemBySlot(const uint32 bot_id, const uint32 slot_id) { - if (!bot_id || (slot_id > EmuConstants::EQUIPMENT_END && slot_id != MainPowerSource)) + if (!bot_id || (slot_id > EQEmu::Constants::EQUIPMENT_END && slot_id != SlotPowerSource)) return false; query = StringFormat("DELETE FROM `bot_inventories` WHERE `bot_id` = '%u' AND `slot_id` = '%u'", bot_id, slot_id); @@ -1294,12 +1294,12 @@ bool BotDatabase::SaveEquipmentColor(const uint32 bot_id, const int16 slot_id, c return false; bool all_flag = (slot_id == -2); - if ((slot_id < EmuConstants::EQUIPMENT_BEGIN || slot_id > EmuConstants::EQUIPMENT_END) && slot_id != MainPowerSource && !all_flag) + if ((slot_id < EQEmu::Constants::EQUIPMENT_BEGIN || slot_id > EQEmu::Constants::EQUIPMENT_END) && slot_id != SlotPowerSource && !all_flag) return false; std::string where_clause; if (all_flag) - where_clause = StringFormat(" AND `slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u')", MainHead, MainArms, MainWrist1, MainHands, MainChest, MainLegs, MainFeet); + where_clause = StringFormat(" AND `slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u')", SlotHead, SlotArms, SlotWrist1, SlotHands, SlotChest, SlotLegs, SlotFeet); else where_clause = StringFormat(" AND `slot_id` = '%u'", slot_id); @@ -1571,7 +1571,7 @@ bool BotDatabase::LoadPetItems(const uint32 bot_id, uint32* pet_items) return true; int item_index = 0; - for (auto row = results.begin(); row != results.end() && item_index < EmuConstants::EQUIPMENT_SIZE; ++row) { + for (auto row = results.begin(); row != results.end() && item_index < EQEmu::Constants::EQUIPMENT_SIZE; ++row) { pet_items[item_index] = atoi(row[0]); ++item_index; } @@ -1595,7 +1595,7 @@ bool BotDatabase::SavePetItems(const uint32 bot_id, const uint32* pet_items, boo if (!saved_pet_index) return true; - for (int item_index = 0; item_index < EmuConstants::EQUIPMENT_SIZE; ++item_index) { + for (int item_index = 0; item_index < EQEmu::Constants::EQUIPMENT_SIZE; ++item_index) { if (!pet_items[item_index]) continue; @@ -1744,7 +1744,7 @@ bool BotDatabase::SaveAllArmorColorBySlot(const uint32 owner_id, const int16 slo " AND bi.`slot_id` = '%i'", owner_id, rgb_value, - MainHead, MainChest, MainArms, MainWrist1, MainWrist2, MainHands, MainLegs, MainFeet, + SlotHead, SlotChest, SlotArms, SlotWrist1, SlotWrist2, SlotHands, SlotLegs, SlotFeet, slot_id ); auto results = QueryDatabase(query); @@ -1768,7 +1768,7 @@ bool BotDatabase::SaveAllArmorColors(const uint32 owner_id, const uint32 rgb_val " AND bi.`slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", owner_id, rgb_value, - MainHead, MainChest, MainArms, MainWrist1, MainWrist2, MainHands, MainLegs, MainFeet + SlotHead, SlotChest, SlotArms, SlotWrist1, SlotWrist2, SlotHands, SlotLegs, SlotFeet ); auto results = QueryDatabase(query); if (!results.Success()) diff --git a/zone/client.cpp b/zone/client.cpp index 837306d99..d7e0f4a3b 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2731,7 +2731,7 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) { if (item && (item->ItemClass==ItemClassCommon)) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); - if (matslot != _MaterialInvalid) + if (matslot != MaterialInvalid) { m_pp.item_material[matslot] = GetEquipmentMaterial(matslot); } @@ -3073,7 +3073,7 @@ void Client::SetTint(int16 in_slot, uint32 color) { void Client::SetTint(int16 in_slot, Color_Struct& color) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); - if (matslot != _MaterialInvalid) + if (matslot != MaterialInvalid) { m_pp.item_tint[matslot].Color = color.Color; database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.Color); @@ -3148,58 +3148,58 @@ void Client::LinkDead() } uint8 Client::SlotConvert(uint8 slot,bool bracer){ - uint8 slot2=0; // why are we returning MainCharm instead of INVALID_INDEX? (must be a pre-charm segment...) + uint8 slot2 = 0; // why are we returning MainCharm instead of INVALID_INDEX? (must be a pre-charm segment...) if(bracer) - return MainWrist2; + return SlotWrist2; switch(slot){ case MaterialHead: - slot2=MainHead; + slot2 = SlotHead; break; case MaterialChest: - slot2=MainChest; + slot2 = SlotChest; break; case MaterialArms: - slot2=MainArms; + slot2 = SlotArms; break; case MaterialWrist: - slot2=MainWrist1; + slot2 = SlotWrist1; break; case MaterialHands: - slot2=MainHands; + slot2 = SlotHands; break; case MaterialLegs: - slot2=MainLegs; + slot2 = SlotLegs; break; case MaterialFeet: - slot2=MainFeet; + slot2 = SlotFeet; break; } return slot2; } uint8 Client::SlotConvert2(uint8 slot){ - uint8 slot2=0; // same as above... + uint8 slot2 = 0; // same as above... switch(slot){ - case MainHead: - slot2=MaterialHead; + case SlotHead: + slot2 = MaterialHead; break; - case MainChest: - slot2=MaterialChest; + case SlotChest: + slot2 = MaterialChest; break; - case MainArms: - slot2=MaterialArms; + case SlotArms: + slot2 = MaterialArms; break; - case MainWrist1: - slot2=MaterialWrist; + case SlotWrist1: + slot2 = MaterialWrist; break; - case MainHands: - slot2=MaterialHands; + case SlotHands: + slot2 = MaterialHands; break; - case MainLegs: - slot2=MaterialLegs; + case SlotLegs: + slot2 = MaterialLegs; break; - case MainFeet: - slot2=MaterialFeet; + case SlotFeet: + slot2 = MaterialFeet; break; } return slot2; @@ -4203,14 +4203,14 @@ bool Client::GroupFollow(Client* inviter) { uint16 Client::GetPrimarySkillValue() { SkillUseTypes skill = HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill - bool equiped = m_inv.GetItem(MainPrimary); + bool equiped = m_inv.GetItem(SlotPrimary); if (!equiped) skill = SkillHandtoHand; else { - uint8 type = m_inv.GetItem(MainPrimary)->GetItem()->ItemType; //is this the best way to do this? + uint8 type = m_inv.GetItem(SlotPrimary)->GetItem()->ItemType; //is this the best way to do this? switch (type) { @@ -5391,7 +5391,7 @@ bool Client::TryReward(uint32 claim_id) // save uint32 free_slot = 0xFFFFFFFF; - for (int i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; ++i) { + for (int i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; ++i) { ItemInst *item = GetInv().GetItem(i); if (!item) { free_slot = i; @@ -5737,30 +5737,30 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { } } - inst = requestee->GetInv().GetItem(MainPowerSource); + inst = requestee->GetInv().GetItem(SlotPowerSource); if(inst) { item = inst->GetItem(); if(item) { // we shouldn't do this..but, that's the way it's coded atm... // (this type of action should be handled exclusively in the client translator) - strcpy(insr->itemnames[SoF::slots::MainPowerSource], item->Name); - insr->itemicons[SoF::slots::MainPowerSource] = item->Icon; + strcpy(insr->itemnames[SoF::inventory::SlotPowerSource], item->Name); + insr->itemicons[SoF::inventory::SlotPowerSource] = item->Icon; } else - insr->itemicons[SoF::slots::MainPowerSource] = 0xFFFFFFFF; + insr->itemicons[SoF::inventory::SlotPowerSource] = 0xFFFFFFFF; } - inst = requestee->GetInv().GetItem(MainAmmo); + inst = requestee->GetInv().GetItem(SlotAmmo); if(inst) { item = inst->GetItem(); if(item) { - strcpy(insr->itemnames[SoF::slots::MainAmmo], item->Name); - insr->itemicons[SoF::slots::MainAmmo] = item->Icon; + strcpy(insr->itemnames[SoF::inventory::SlotAmmo], item->Name); + insr->itemicons[SoF::inventory::SlotAmmo] = item->Icon; } else - insr->itemicons[SoF::slots::MainAmmo] = 0xFFFFFFFF; + insr->itemicons[SoF::inventory::SlotAmmo] = 0xFFFFFFFF; } strcpy(insr->text, requestee->GetInspectMessage().text); @@ -6306,7 +6306,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid made_npc->drakkin_details = GetDrakkinDetails(); made_npc->d_melee_texture1 = GetEquipmentMaterial(MaterialPrimary); made_npc->d_melee_texture2 = GetEquipmentMaterial(MaterialSecondary); - for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) { + for (int i = EQEmu::Constants::MATERIAL_BEGIN; i <= EQEmu::Constants::MATERIAL_END; i++) { made_npc->armor_tint[i] = GetEquipmentColor(i); } made_npc->loottable_id = 0; @@ -7582,7 +7582,7 @@ void Client::GarbleMessage(char *message, uint8 variance) for (size_t i = 0; i < strlen(message); i++) { // Client expects hex values inside of a text link body if (message[i] == delimiter) { - if (!(delimiter_count & 1)) { i += EmuConstants::TEXT_LINK_BODY_LENGTH; } + if (!(delimiter_count & 1)) { i += EQEmu::Constants::TEXT_LINK_BODY_LENGTH; } ++delimiter_count; continue; } @@ -8007,17 +8007,17 @@ void Client::TickItemCheck() if(zone->tick_items.empty()) { return; } //Scan equip slots for items - for(i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; i++) + for (i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; i++) { TryItemTick(i); } //Scan main inventory + cursor - for(i = EmuConstants::GENERAL_BEGIN; i <= MainCursor; i++) + for (i = EQEmu::Constants::GENERAL_BEGIN; i <= SlotCursor; i++) { TryItemTick(i); } //Scan bags - for(i = EmuConstants::GENERAL_BAGS_BEGIN; i <= EmuConstants::CURSOR_BAG_END; i++) + for (i = EQEmu::Constants::GENERAL_BAGS_BEGIN; i <= EQEmu::Constants::CURSOR_BAG_END; i++) { TryItemTick(i); } @@ -8033,7 +8033,7 @@ void Client::TryItemTick(int slot) if(zone->tick_items.count(iid) > 0) { - if( GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EmuConstants::EQUIPMENT_END) ) + if (GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EQEmu::Constants::EQUIPMENT_END)) { ItemInst* e_inst = (ItemInst*)inst; parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); @@ -8041,9 +8041,9 @@ void Client::TryItemTick(int slot) } //Only look at augs in main inventory - if(slot > EmuConstants::EQUIPMENT_END) { return; } + if (slot > EQEmu::Constants::EQUIPMENT_END) { return; } - for (int x = AUG_BEGIN; x < EmuConstants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_BEGIN; x < EQEmu::Constants::ITEM_COMMON_SIZE; ++x) { ItemInst * a_inst = inst->GetAugment(x); if(!a_inst) { continue; } @@ -8064,17 +8064,17 @@ void Client::TryItemTick(int slot) void Client::ItemTimerCheck() { int i; - for(i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; i++) + for (i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; i++) { TryItemTimer(i); } - for(i = EmuConstants::GENERAL_BEGIN; i <= MainCursor; i++) + for (i = EQEmu::Constants::GENERAL_BEGIN; i <= SlotCursor; i++) { TryItemTimer(i); } - for(i = EmuConstants::GENERAL_BAGS_BEGIN; i <= EmuConstants::CURSOR_BAG_END; i++) + for (i = EQEmu::Constants::GENERAL_BAGS_BEGIN; i <= EQEmu::Constants::CURSOR_BAG_END; i++) { TryItemTimer(i); } @@ -8096,11 +8096,11 @@ void Client::TryItemTimer(int slot) ++it_iter; } - if(slot > EmuConstants::EQUIPMENT_END) { + if (slot > EQEmu::Constants::EQUIPMENT_END) { return; } - for (int x = AUG_BEGIN; x < EmuConstants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_BEGIN; x < EQEmu::Constants::ITEM_COMMON_SIZE; ++x) { ItemInst * a_inst = inst->GetAugment(x); if(!a_inst) { @@ -8388,12 +8388,12 @@ void Client::ShowNumHits() int Client::GetQuiverHaste(int delay) { const ItemInst *pi = nullptr; - for (int r = EmuConstants::GENERAL_BEGIN; r <= EmuConstants::GENERAL_END; r++) { + for (int r = EQEmu::Constants::GENERAL_BEGIN; r <= EQEmu::Constants::GENERAL_END; r++) { pi = GetInv().GetItem(r); if (pi && pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == BagTypeQuiver && pi->GetItem()->BagWR > 0) break; - if (r == EmuConstants::GENERAL_END) + if (r == EQEmu::Constants::GENERAL_END) // we will get here if we don't find a valid quiver return 0; } @@ -8427,7 +8427,7 @@ std::string Client::TextLink::GenerateLink() generate_body(); generate_text(); - if ((m_LinkBody.length() == EmuConstants::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) { + if ((m_LinkBody.length() == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) { m_Link.push_back(0x12); m_Link.append(m_LinkBody); m_Link.append(m_LinkText); @@ -8619,7 +8619,7 @@ void Client::TextLink::generate_text() bool Client::TextLink::DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruct, const std::string& textLinkBody) { memset(&textLinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); - if (textLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + if (textLinkBody.length() != EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { return false; } textLinkBodyStruct.unknown_1 = (uint8)strtol(textLinkBody.substr(0, 1).c_str(), nullptr, 16); textLinkBodyStruct.item_id = (uint32)strtol(textLinkBody.substr(1, 5).c_str(), nullptr, 16); @@ -8657,7 +8657,7 @@ bool Client::TextLink::GenerateLinkBody(std::string& textLinkBody, const TextLin (0xFFFFFFFF & textLinkBodyStruct.hash) ); - if (textLinkBody.length() != EmuConstants::TEXT_LINK_BODY_LENGTH) { return false; } + if (textLinkBody.length() != EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { return false; } return true; } @@ -8680,7 +8680,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, AddMoneyToPP(copper, silver, gold, platinum, false); if (itemid > 0) - SummonItem(itemid, 0, 0, 0, 0, 0, 0, false, MainPowerSource); + SummonItem(itemid, 0, 0, 0, 0, 0, 0, false, SlotPowerSource); if (faction) { diff --git a/zone/client.h b/zone/client.h index f36422d3a..544007e9b 100644 --- a/zone/client.h +++ b/zone/client.h @@ -217,7 +217,7 @@ public: //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } @@ -813,7 +813,7 @@ public: void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false); void PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data = 0); bool AutoPutLootInInventory(ItemInst& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0); - bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = MainCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); + bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = SlotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index adf477538..76caa9942 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -485,7 +485,7 @@ int32 Client::GetRawItemAC() { int32 Total = 0; // this skips MainAmmo..add an '=' conditional if that slot is required (original behavior) - for (int16 slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id < EmuConstants::EQUIPMENT_END; slot_id++) { + for (int16 slot_id = EQEmu::Constants::EQUIPMENT_BEGIN; slot_id < EQEmu::Constants::EQUIPMENT_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if (inst && inst->IsType(ItemClassCommon)) { Total += inst->GetItem()->AC; @@ -1067,9 +1067,9 @@ int32 Client::CalcAC() } // Shield AC bonus for HeroicSTR if (itembonuses.HeroicSTR) { - bool equiped = CastToClient()->m_inv.GetItem(MainSecondary); + bool equiped = CastToClient()->m_inv.GetItem(SlotSecondary); if (equiped) { - uint8 shield = CastToClient()->m_inv.GetItem(MainSecondary)->GetItem()->ItemType; + uint8 shield = CastToClient()->m_inv.GetItem(SlotSecondary)->GetItem()->ItemType; if (shield == ItemTypeShield) { displayed += itembonuses.HeroicSTR / 2; } @@ -1096,9 +1096,9 @@ int32 Client::GetACMit() } // Shield AC bonus for HeroicSTR if (itembonuses.HeroicSTR) { - bool equiped = CastToClient()->m_inv.GetItem(MainSecondary); + bool equiped = CastToClient()->m_inv.GetItem(SlotSecondary); if (equiped) { - uint8 shield = CastToClient()->m_inv.GetItem(MainSecondary)->GetItem()->ItemType; + uint8 shield = CastToClient()->m_inv.GetItem(SlotSecondary)->GetItem()->ItemType; if (shield == ItemTypeShield) { mitigation += itembonuses.HeroicSTR / 2; } @@ -1306,7 +1306,7 @@ uint32 Client::CalcCurrentWeight() ItemInst* ins; uint32 Total = 0; int x; - for (x = EmuConstants::EQUIPMENT_BEGIN; x <= MainCursor; x++) { // include cursor or not? + for (x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= SlotCursor; x++) { // include cursor or not? TempItem = 0; ins = GetInv().GetItem(x); if (ins) { @@ -1316,7 +1316,7 @@ uint32 Client::CalcCurrentWeight() Total += TempItem->Weight; } } - for (x = EmuConstants::GENERAL_BAGS_BEGIN; x <= EmuConstants::GENERAL_BAGS_END; x++) { // include cursor bags or not? + for (x = EQEmu::Constants::GENERAL_BAGS_BEGIN; x <= EQEmu::Constants::GENERAL_BAGS_END; x++) { // include cursor bags or not? int TmpWeight = 0; TempItem = 0; ins = GetInv().GetItem(x); @@ -1329,9 +1329,9 @@ uint32 Client::CalcCurrentWeight() if (TmpWeight > 0) { // this code indicates that weight redux bags can only be in the first general inventory slot to be effective... // is this correct? or can we scan for the highest weight redux and use that? (need client verifications) - int bagslot = MainGeneral1; + int bagslot = SlotGeneral1; int reduction = 0; - for (int m = EmuConstants::GENERAL_BAGS_BEGIN + 10; m <= EmuConstants::GENERAL_BAGS_END; m += 10) { // include cursor bags or not? + for (int m = EQEmu::Constants::GENERAL_BAGS_BEGIN + 10; m <= EQEmu::Constants::GENERAL_BAGS_END; m += 10) { // include cursor bags or not? if (x >= m) { bagslot += 1; } @@ -1355,7 +1355,7 @@ uint32 Client::CalcCurrentWeight() This is the ONLY instance I have seen where the client is hard coded to particular Item IDs to set a certain property for an item. It is very odd. */ // SoD+ client has no weight for coin - if (EQLimits::CoinHasWeight(GetClientVersion())) { + if (EQEmu::Limits::CoinHasWeight(GetClientVersion())) { Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4; } float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat; @@ -2205,12 +2205,12 @@ int Client::GetRawACNoShield(int &shield_ac) const { int ac = itembonuses.AC + spellbonuses.AC + aabonuses.AC; shield_ac = 0; - const ItemInst *inst = m_inv.GetItem(MainSecondary); + const ItemInst *inst = m_inv.GetItem(SlotSecondary); if (inst) { if (inst->GetItem()->ItemType == ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; - for (uint8 i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + for (uint8 i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { if (inst->GetAugment(i)) { ac -= inst->GetAugment(i)->GetItem()->AC; shield_ac += inst->GetAugment(i)->GetItem()->AC; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index fb7216b86..2c432b432 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1314,7 +1314,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) } /* Set item material tint */ - for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++) + for (int i = EQEmu::Constants::MATERIAL_BEGIN; i <= EQEmu::Constants::MATERIAL_END; i++) { if (m_pp.item_tint[i].RGB.UseTint == 1 || m_pp.item_tint[i].RGB.UseTint == 255) { @@ -1690,7 +1690,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (iter == m_inv.cursor_cbegin()) continue; const ItemInst *inst = *iter; - SendItemPacket(MainCursor, inst, ItemPacketSummonItem); + SendItemPacket(SlotCursor, inst, ItemPacketSummonItem); } } @@ -2028,7 +2028,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) ItemInst *inst = database.CreateItem(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) { - PutLootInInventory(MainCursor, *inst); + PutLootInInventory(SlotCursor, *inst); } Save(1); } @@ -2551,7 +2551,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) ItemInst *inst = database.CreateItem(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) { - PutLootInInventory(MainCursor, *inst); + PutLootInInventory(SlotCursor, *inst); } Save(1); @@ -2601,7 +2601,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) SetAlternateCurrencyValue(reclaim->currency_id, 0); } else { - SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, MainCursor); + SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, SlotCursor); AddAlternateCurrencyValue(reclaim->currency_id, -((int32)reclaim->count)); } /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ @@ -2812,8 +2812,8 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app) } uint32 ApplyPoisonSuccessResult = 0; ApplyPoison_Struct* ApplyPoisonData = (ApplyPoison_Struct*)app->pBuffer; - const ItemInst* PrimaryWeapon = GetInv().GetItem(MainPrimary); - const ItemInst* SecondaryWeapon = GetInv().GetItem(MainSecondary); + const ItemInst* PrimaryWeapon = GetInv().GetItem(SlotPrimary); + const ItemInst* SecondaryWeapon = GetInv().GetItem(SlotSecondary); const ItemInst* PoisonItemInstance = GetInv()[ApplyPoisonData->inventorySlot]; bool IsPoison = PoisonItemInstance && (PoisonItemInstance->GetItem()->ItemType == ItemTypePoison); @@ -2995,7 +2995,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) { case 0: // Adding an augment case 2: // Swapping augment - new_aug = user_inv.GetItem(MainCursor); + new_aug = user_inv.GetItem(SlotCursor); if (!new_aug) // Shouldn't get the OP code without the augment on the user's cursor, but maybe it's h4x. { @@ -3053,7 +3053,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (itemOneToPush) { DeleteItemInInventory(item_slot, 0, true); - DeleteItemInInventory(MainCursor, new_aug->IsStackable() ? 1 : 0, true); + DeleteItemInInventory(SlotCursor, new_aug->IsStackable() ? 1 : 0, true); if (solvent) { @@ -3064,7 +3064,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (itemTwoToPush) { // This is a swap. Return the old aug to the player's cursor. - if (!PutItemInInventory(MainCursor, *itemTwoToPush, true)) + if (!PutItemInInventory(SlotCursor, *itemTwoToPush, true)) { Log.Out(Logs::General, Logs::Error, "Problem returning old augment to player's cursor after augmentation swap."); Message(15, "Error: Failed to retrieve old augment after augmentation swap!"); @@ -3077,7 +3077,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != _MaterialInvalid) + if (mat != MaterialInvalid) { SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. } @@ -3142,13 +3142,13 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != _MaterialInvalid) + if (mat != MaterialInvalid) { SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. } // Drop the removed augment on the player's cursor - if (!PutItemInInventory(MainCursor, *itemTwoToPush, true)) + if (!PutItemInInventory(SlotCursor, *itemTwoToPush, true)) { Log.Out(Logs::General, Logs::Error, "Problem returning augment to player's cursor after safe removal."); Message(15, "Error: Failed to return augment after removal from item!"); @@ -3197,7 +3197,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != _MaterialInvalid) + if (mat != MaterialInvalid) { SendWearChange(mat); } @@ -4073,7 +4073,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) } else { - Message(0, "Error: castspell->inventoryslot >= %i (0x%04x)", MainCursor, castspell->inventoryslot); + Message(0, "Error: castspell->inventoryslot >= %i (0x%04x)", SlotCursor, castspell->inventoryslot); InterruptSpell(castspell->spell_id); } } @@ -4992,7 +4992,7 @@ void Client::Handle_OP_CrashDump(const EQApplicationPacket *app) void Client::Handle_OP_CreateObject(const EQApplicationPacket *app) { - DropItem(MainCursor); + DropItem(SlotCursor); return; } @@ -6906,7 +6906,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) return; } - ItemInst *CursorItemInst = GetInv().GetItem(MainCursor); + ItemInst *CursorItemInst = GetInv().GetItem(SlotCursor); bool Allowed = true; @@ -6954,7 +6954,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) { GuildBankDepositAck(false, sentAction); - DeleteItemInInventory(MainCursor, 0, false); + DeleteItemInInventory(SlotCursor, 0, false); } break; @@ -6975,7 +6975,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) case GuildBankWithdraw: { - if (GetInv()[MainCursor]) + if (GetInv()[SlotCursor]) { Message_StringID(13, GUILD_BANK_EMPTY_HANDS); @@ -7021,7 +7021,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) { PushItemOnCursor(*inst); - SendItemPacket(MainCursor, inst, ItemPacketSummonItem); + SendItemPacket(SlotCursor, inst, ItemPacketSummonItem); GuildBanks->DeleteItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity); } @@ -7995,7 +7995,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) const Item_Struct* item = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - for (int16 L = EmuConstants::EQUIPMENT_BEGIN; L <= MainWaist; L++) { + for (int16 L = EQEmu::Constants::EQUIPMENT_BEGIN; L <= SlotWaist; L++) { const ItemInst* inst = GetInv().GetItem(L); item = inst ? inst->GetItem() : nullptr; @@ -8015,15 +8015,15 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) else { insr->itemicons[L] = 0xFFFFFFFF; } } - const ItemInst* inst = GetInv().GetItem(MainAmmo); + const ItemInst* inst = GetInv().GetItem(SlotAmmo); item = inst ? inst->GetItem() : nullptr; if (item) { // another one..I did these, didn't I!!? - strcpy(insr->itemnames[SoF::slots::MainAmmo], item->Name); - insr->itemicons[SoF::slots::MainAmmo] = item->Icon; + strcpy(insr->itemnames[SoF::inventory::SlotAmmo], item->Name); + insr->itemicons[SoF::inventory::SlotAmmo] = item->Icon; } - else { insr->itemicons[SoF::slots::MainAmmo] = 0xFFFFFFFF; } + else { insr->itemicons[SoF::inventory::SlotAmmo] = 0xFFFFFFFF; } InspectMessage_Struct* newmessage = (InspectMessage_Struct*)insr->text; InspectMessage_Struct& playermessage = this->GetInspectMessage(); @@ -8475,7 +8475,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) ItemInst* clickaug = 0; Item_Struct* augitem = 0; - for (r = 0; r < EmuConstants::ITEM_COMMON_SIZE; r++) { + for (r = 0; r < EQEmu::Constants::ITEM_COMMON_SIZE; r++) { const ItemInst* aug_i = inst->GetAugment(r); if (!aug_i) continue; @@ -9676,7 +9676,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer; if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id)) { - if (mi->from_slot != mi->to_slot && (mi->from_slot <= EmuConstants::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) + if (mi->from_slot != mi->to_slot && (mi->from_slot <= EQEmu::Constants::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) { char *detect = nullptr; const ItemInst *itm_from = GetInv().GetItem(mi->from_slot); @@ -9697,8 +9697,8 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) // Illegal bagslot usage checks. Currently, user only receives a message if this check is triggered. bool mi_hack = false; - if (mi->from_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->from_slot <= EmuConstants::CURSOR_BAG_END) { - if (mi->from_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; } + if (mi->from_slot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && mi->from_slot <= EQEmu::Constants::CURSOR_BAG_END) { + if (mi->from_slot >= EQEmu::Constants::CURSOR_BAG_BEGIN) { mi_hack = true; } else { int16 from_parent = m_inv.CalcSlotId(mi->from_slot); if (!m_inv[from_parent]) { mi_hack = true; } @@ -9707,8 +9707,8 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) } } - if (mi->to_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->to_slot <= EmuConstants::CURSOR_BAG_END) { - if (mi->to_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; } + if (mi->to_slot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && mi->to_slot <= EQEmu::Constants::CURSOR_BAG_END) { + if (mi->to_slot >= EQEmu::Constants::CURSOR_BAG_BEGIN) { mi_hack = true; } else { int16 to_parent = m_inv.CalcSlotId(mi->to_slot); if (!m_inv[to_parent]) { mi_hack = true; } @@ -12024,7 +12024,7 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app) Shielding_Struct* shield = (Shielding_Struct*)app->pBuffer; shield_target = entity_list.GetMob(shield->target_id); bool ack = false; - ItemInst* inst = GetInv().GetItem(MainSecondary); + ItemInst* inst = GetInv().GetItem(SlotSecondary); if (!shield_target) return; if (inst) @@ -12241,8 +12241,8 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) // shouldn't we be reimbursing if these two fail? //make sure we are not completely full... - if (freeslotid == MainCursor) { - if (m_inv.GetItem(MainCursor) != nullptr) { + if (freeslotid == SlotCursor) { + if (m_inv.GetItem(SlotCursor) != nullptr) { Message(13, "You do not have room for any more items."); safe_delete(outapp); safe_delete(inst); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 3154a9ca9..69de6ef85 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -296,7 +296,7 @@ bool Client::Process() { } if(AutoFireEnabled()){ - ItemInst *ranged = GetInv().GetItem(MainRange); + ItemInst *ranged = GetInv().GetItem(SlotRange); if(ranged) { if(ranged->GetItem() && ranged->GetItem()->ItemType == ItemTypeBow){ @@ -391,10 +391,10 @@ bool Client::Process() { } else if (auto_attack_target->GetHP() > -10) // -10 so we can watch people bleed in PvP { - ItemInst *wpn = GetInv().GetItem(MainPrimary); - TryWeaponProc(wpn, auto_attack_target, MainPrimary); + ItemInst *wpn = GetInv().GetItem(SlotPrimary); + TryWeaponProc(wpn, auto_attack_target, SlotPrimary); - DoAttackRounds(auto_attack_target, MainPrimary); + DoAttackRounds(auto_attack_target, SlotPrimary); if (CheckAATimer(aaTimerRampage)) entity_list.AEAttack(this, 30); } @@ -430,10 +430,10 @@ bool Client::Process() { else if(auto_attack_target->GetHP() > -10) { CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10); if (CheckDualWield()) { - ItemInst *wpn = GetInv().GetItem(MainSecondary); - TryWeaponProc(wpn, auto_attack_target, MainSecondary); + ItemInst *wpn = GetInv().GetItem(SlotSecondary); + TryWeaponProc(wpn, auto_attack_target, SlotSecondary); - DoAttackRounds(auto_attack_target, MainSecondary); + DoAttackRounds(auto_attack_target, SlotSecondary); } } } @@ -742,7 +742,7 @@ void Client::BulkSendInventoryItems() { // LINKDEAD TRADE ITEMS // Move trade slot items back into normal inventory..need them there now for the proceeding validity checks - for(slot_id = EmuConstants::TRADE_BEGIN; slot_id <= EmuConstants::TRADE_END; slot_id++) { + for(slot_id = EQEmu::Constants::TRADE_BEGIN; slot_id <= EQEmu::Constants::TRADE_END; slot_id++) { ItemInst* inst = m_inv.PopItem(slot_id); if(inst) { bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; @@ -790,7 +790,7 @@ void Client::BulkSendInventoryItems() { std::map::iterator itr; //Inventory items - for(slot_id = MAIN_BEGIN; slot_id < EmuConstants::MAP_POSSESSIONS_SIZE; slot_id++) { + for(slot_id = SLOT_BEGIN; slot_id < EQEmu::Constants::TYPE_POSSESSIONS_SIZE; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if(inst) { std::string packet = inst->Serialize(slot_id); @@ -801,16 +801,16 @@ void Client::BulkSendInventoryItems() { // Power Source if(GetClientVersion() >= ClientVersion::SoF) { - const ItemInst* inst = m_inv[MainPowerSource]; + const ItemInst* inst = m_inv[SlotPowerSource]; if(inst) { - std::string packet = inst->Serialize(MainPowerSource); + std::string packet = inst->Serialize(SlotPowerSource); ser_items[i++] = packet; size += packet.length(); } } // Bank items - for(slot_id = EmuConstants::BANK_BEGIN; slot_id <= EmuConstants::BANK_END; slot_id++) { + for(slot_id = EQEmu::Constants::BANK_BEGIN; slot_id <= EQEmu::Constants::BANK_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if(inst) { std::string packet = inst->Serialize(slot_id); @@ -820,7 +820,7 @@ void Client::BulkSendInventoryItems() { } // Shared Bank items - for(slot_id = EmuConstants::SHARED_BANK_BEGIN; slot_id <= EmuConstants::SHARED_BANK_END; slot_id++) { + for(slot_id = EQEmu::Constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::Constants::SHARED_BANK_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if(inst) { std::string packet = inst->Serialize(slot_id); @@ -851,14 +851,14 @@ void Client::BulkSendInventoryItems() if(deletenorent){//client was offline for more than 30 minutes, delete no rent items RemoveNoRent(); } - for (slot_id=EmuConstants::POSSESSIONS_BEGIN; slot_id<=EmuConstants::POSSESSIONS_END; slot_id++) { + for (slot_id=EQEmu::Constants::POSSESSIONS_BEGIN; slot_id<=EQEmu::Constants::POSSESSIONS_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if (inst){ SendItemPacket(slot_id, inst, ItemPacketCharInventory); } } // Bank items - for (slot_id=EmuConstants::BANK_BEGIN; slot_id<=EmuConstants::BANK_END; slot_id++) { // 2015... + for (slot_id=EQEmu::Constants::BANK_BEGIN; slot_id<=EQEmu::Constants::BANK_END; slot_id++) { // 2015... const ItemInst* inst = m_inv[slot_id]; if (inst){ SendItemPacket(slot_id, inst, ItemPacketCharInventory); @@ -866,7 +866,7 @@ void Client::BulkSendInventoryItems() } // Shared Bank items - for (slot_id=EmuConstants::SHARED_BANK_BEGIN; slot_id<=EmuConstants::SHARED_BANK_END; slot_id++) { + for (slot_id=EQEmu::Constants::SHARED_BANK_BEGIN; slot_id<=EQEmu::Constants::SHARED_BANK_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if (inst){ SendItemPacket(slot_id, inst, ItemPacketCharInventory); @@ -876,7 +876,7 @@ void Client::BulkSendInventoryItems() // LINKDEAD TRADE ITEMS // If player went LD during a trade, they have items in the trade inventory // slots. These items are now being put into their inventory (then queue up on cursor) - for (int16 trade_slot_id=EmuConstants::TRADE_BEGIN; trade_slot_id<=EmuConstants::TRADE_END; trade_slot_id++) { + for (int16 trade_slot_id=EQEmu::Constants::TRADE_BEGIN; trade_slot_id<=EQEmu::Constants::TRADE_END; trade_slot_id++) { const ItemInst* inst = m_inv[slot_id]; if (inst) { int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size); @@ -1147,7 +1147,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) switch(memspell->scribing) { case memSpellScribing: { // scribing spell to book - const ItemInst* inst = m_inv[MainCursor]; + const ItemInst* inst = m_inv[SlotCursor]; if(inst && inst->IsType(ItemClassCommon)) { @@ -1161,7 +1161,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) if(item && item->Scroll.Effect == (int32)(memspell->spell_id)) { ScribeSpell(memspell->spell_id, memspell->slot); - DeleteItemInInventory(MainCursor, 1, true); + DeleteItemInInventory(SlotCursor, 1, true); } else Message(0,"Scribing spell: inst exists but item does not or spell ids do not match."); diff --git a/zone/command.cpp b/zone/command.cpp index dbbed07db..b3f00eed3 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2413,14 +2413,14 @@ void command_texture(Client *c, const Seperator *sep) // Player Races Wear Armor, so Wearchange is sent instead int i; if (!c->GetTarget()) - for (i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_TINT_END; i++) + for (i = EQEmu::Constants::MATERIAL_BEGIN; i <= EQEmu::Constants::MATERIAL_TINT_END; i++) { c->SendTextureWC(i, texture); } else if ((c->GetTarget()->GetRace() > 0 && c->GetTarget()->GetRace() <= 12) || c->GetTarget()->GetRace() == 128 || c->GetTarget()->GetRace() == 130 || c->GetTarget()->GetRace() == 330 || c->GetTarget()->GetRace() == 522) { - for (i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_TINT_END; i++) + for (i = EQEmu::Constants::MATERIAL_BEGIN; i <= EQEmu::Constants::MATERIAL_TINT_END; i++) { c->GetTarget()->SendTextureWC(i, texture); } @@ -2551,7 +2551,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message(0, "Displaying inventory for %s...", targetClient->GetName()); // worn - for (int16 indexMain = EmuConstants::EQUIPMENT_BEGIN; (scopeWhere & peekWorn) && (indexMain <= EmuConstants::EQUIPMENT_END); ++indexMain) { + for (int16 indexMain = EQEmu::Constants::EQUIPMENT_BEGIN; (scopeWhere & peekWorn) && (indexMain <= EQEmu::Constants::EQUIPMENT_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2563,18 +2563,18 @@ void command_peekinv(Client *c, const Seperator *sep) } if ((scopeWhere & peekWorn) && (targetClient->GetClientVersion() >= ClientVersion::SoF)) { - inst_main = targetClient->GetInv().GetItem(MainPowerSource); + inst_main = targetClient->GetInv().GetItem(SlotPowerSource); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); item_link = linker.GenerateLink(); c->Message((item_data == nullptr), "WornSlot: %i, Item: %i (%s), Charges: %i", - MainPowerSource, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); + SlotPowerSource, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); } // inv - for (int16 indexMain = EmuConstants::GENERAL_BEGIN; (scopeWhere & peekInv) && (indexMain <= EmuConstants::GENERAL_END); ++indexMain) { + for (int16 indexMain = EQEmu::Constants::GENERAL_BEGIN; (scopeWhere & peekInv) && (indexMain <= EQEmu::Constants::GENERAL_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2584,7 +2584,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "InvSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2604,7 +2604,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message(1, "CursorSlot: %i, Item: %i (%s), Charges: %i", - MainCursor, 0, item_link.c_str(), 0); + SlotCursor, 0, item_link.c_str(), 0); } else { int cursorDepth = 0; @@ -2616,9 +2616,9 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), "CursorSlot: %i, Depth: %i, Item: %i (%s), Charges: %i", - MainCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); + SlotCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2626,14 +2626,14 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(MainCursor, indexSub), MainCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + Inventory::CalcSlotId(SlotCursor, indexSub), SlotCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } } } // trib - for (int16 indexMain = EmuConstants::TRIBUTE_BEGIN; (scopeWhere & peekTrib) && (indexMain <= EmuConstants::TRIBUTE_END); ++indexMain) { + for (int16 indexMain = EQEmu::Constants::TRIBUTE_BEGIN; (scopeWhere & peekTrib) && (indexMain <= EQEmu::Constants::TRIBUTE_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2645,7 +2645,7 @@ void command_peekinv(Client *c, const Seperator *sep) } // bank - for (int16 indexMain = EmuConstants::BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EmuConstants::BANK_END); ++indexMain) { + for (int16 indexMain = EQEmu::Constants::BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EQEmu::Constants::BANK_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2655,7 +2655,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "BankSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2667,7 +2667,7 @@ void command_peekinv(Client *c, const Seperator *sep) } } - for (int16 indexMain = EmuConstants::SHARED_BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EmuConstants::SHARED_BANK_END); ++indexMain) { + for (int16 indexMain = EQEmu::Constants::SHARED_BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EQEmu::Constants::SHARED_BANK_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2677,7 +2677,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "SharedBankSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2690,7 +2690,7 @@ void command_peekinv(Client *c, const Seperator *sep) } // trade - for (int16 indexMain = EmuConstants::TRADE_BEGIN; (scopeWhere & peekTrade) && (indexMain <= EmuConstants::TRADE_END); ++indexMain) { + for (int16 indexMain = EQEmu::Constants::TRADE_BEGIN; (scopeWhere & peekTrade) && (indexMain <= EQEmu::Constants::TRADE_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2700,7 +2700,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "TradeSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2722,7 +2722,7 @@ void command_peekinv(Client *c, const Seperator *sep) else { c->Message(0, "[WorldObject DBID: %i (entityid: %i)]", objectTradeskill->GetDBID(), objectTradeskill->GetID()); - for (int16 indexMain = MAIN_BEGIN; indexMain < EmuConstants::MAP_WORLD_SIZE; ++indexMain) { + for (int16 indexMain = SLOT_BEGIN; indexMain < EQEmu::Constants::TYPE_WORLD_SIZE; ++indexMain) { inst_main = objectTradeskill->GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2730,9 +2730,9 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), "WorldSlot: %i, Item: %i (%s), Charges: %i", - (EmuConstants::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); + (EQEmu::Constants::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EmuConstants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -3140,8 +3140,8 @@ void command_listpetition(Client *c, const Seperator *sep) void command_equipitem(Client *c, const Seperator *sep) { uint32 slot_id = atoi(sep->arg[1]); - if (sep->IsNumber(1) && ((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || (slot_id == MainPowerSource))) { - const ItemInst* from_inst = c->GetInv().GetItem(MainCursor); + if (sep->IsNumber(1) && ((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::Constants::EQUIPMENT_END) || (slot_id == SlotPowerSource))) { + const ItemInst* from_inst = c->GetInv().GetItem(SlotCursor); const ItemInst* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack) bool partialmove = false; int16 movecount; @@ -3149,7 +3149,7 @@ void command_equipitem(Client *c, const Seperator *sep) if (from_inst && from_inst->IsType(ItemClassCommon)) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer; - mi->from_slot = MainCursor; + mi->from_slot = SlotCursor; mi->to_slot = slot_id; // mi->number_in_stack = from_inst->GetCharges(); // replaced with con check for stacking @@ -4333,7 +4333,7 @@ void command_goto(Client *c, const Seperator *sep) void command_iteminfo(Client *c, const Seperator *sep) { - auto inst = c->GetInv()[MainCursor]; + auto inst = c->GetInv()[SlotCursor]; if (!inst) { c->Message(13, "Error: You need an item on your cursor for this command"); } auto item = inst->GetItem(); if (!item) { @@ -5491,9 +5491,9 @@ void command_summonitem(Client *c, const Seperator *sep) std::string cmd_msg = sep->msg; size_t link_open = cmd_msg.find('\x12'); size_t link_close = cmd_msg.find_last_of('\x12'); - if (link_open != link_close && (cmd_msg.length() - link_open) > EmuConstants::TEXT_LINK_BODY_LENGTH) { + if (link_open != link_close && (cmd_msg.length() - link_open) > EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { TextLinkBody_Struct link_body; - Client::TextLink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EmuConstants::TEXT_LINK_BODY_LENGTH)); + Client::TextLink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQEmu::Constants::TEXT_LINK_BODY_LENGTH)); itemid = link_body.item_id; } else if (!sep->IsNumber(1)) { @@ -7114,7 +7114,7 @@ void command_path(Client *c, const Seperator *sep) } void Client::Undye() { - for (int cur_slot = EmuConstants::MATERIAL_BEGIN; cur_slot <= EmuConstants::MATERIAL_END; cur_slot++ ) { + for (int cur_slot = EQEmu::Constants::MATERIAL_BEGIN; cur_slot <= EQEmu::Constants::MATERIAL_END; cur_slot++ ) { uint8 slot2=SlotConvert(cur_slot); ItemInst* inst = m_inv.GetItem(slot2); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index b0e9bef0d..45d4eeb53 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -328,12 +328,12 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( // to go into the regular slots on the player, out of bags std::list removed_list; - for(i = MAIN_BEGIN; i < EmuConstants::MAP_POSSESSIONS_SIZE; ++i) { - if(i == MainAmmo && client->GetClientVersion() >= ClientVersion::SoF) { - item = client->GetInv().GetItem(MainPowerSource); + for(i = SLOT_BEGIN; i < EQEmu::Constants::TYPE_POSSESSIONS_SIZE; ++i) { + if(i == SlotAmmo && client->GetClientVersion() >= ClientVersion::SoF) { + item = client->GetInv().GetItem(SlotPowerSource); if (item != nullptr) { if (!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent)) - MoveItemToCorpse(client, item, MainPowerSource, removed_list); + MoveItemToCorpse(client, item, SlotPowerSource, removed_list); } } @@ -410,9 +410,9 @@ void Corpse::MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, s while (true) { if (!inst->IsType(ItemClassContainer)) { break; } - if (equipSlot < EmuConstants::GENERAL_BEGIN || equipSlot > MainCursor) { break; } + if (equipSlot < EQEmu::Constants::GENERAL_BEGIN || equipSlot > SlotCursor) { break; } - for (auto sub_index = SUB_BEGIN; sub_index < EmuConstants::ITEM_CONTAINER_SIZE; ++sub_index) { + for (auto sub_index = SUB_BEGIN; sub_index < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++sub_index) { int16 real_bag_slot = Inventory::CalcSlotId(equipSlot, sub_index); auto bag_inst = client->GetInv().GetItem(real_bag_slot); if (bag_inst == nullptr) { continue; } @@ -748,7 +748,7 @@ void Corpse::RemoveItem(ServerLootItem_Struct* item_data) itemlist.erase(iter); uint8 material = Inventory::CalcMaterialFromSlot(sitem->equip_slot); // autos to unsigned char - if (material != _MaterialInvalid) + if (material != MaterialInvalid) SendWearChange(material); UpdateEquipmentLight(); @@ -985,7 +985,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(inst) { if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); - client->SendItemPacket(EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot); + client->SendItemPacket(EQEmu::Constants::CORPSE_BEGIN, inst, ItemPacketLoot); safe_delete(inst); } else { client->Message(13, "Could not find item number %i to send!!", GetPlayerKillItem()); } @@ -1000,7 +1000,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQLimits::InventoryMapSize(MapCorpse, client->GetClientVersion()); + int corpselootlimit = EQEmu::Limits::InventoryMapSize(TypeCorpse, client->GetClientVersion()); for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; @@ -1009,7 +1009,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a // Dont display the item if it's in a bag // Added cursor queue slots to corpse item visibility list. Nothing else should be making it to corpse. - if(!IsPlayerCorpse() || item_data->equip_slot <= MainCursor || item_data->equip_slot == MainPowerSource || Loot_Request_Type>=3 || + if(!IsPlayerCorpse() || item_data->equip_slot <= SlotCursor || item_data->equip_slot == SlotPowerSource || Loot_Request_Type>=3 || (item_data->equip_slot >= 8000 && item_data->equip_slot <= 8999)) { if(i < corpselootlimit) { item = database.GetItem(item_data->item_id); @@ -1018,8 +1018,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(inst) { if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); - // MainGeneral1 is the corpse inventory start offset for Ti(EMu) - CORPSE_END = MainGeneral1 + MainCursor - client->SendItemPacket(i + EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot); + // SlotGeneral1 is the corpse inventory start offset for Ti(EMu) - CORPSE_END = SlotGeneral1 + SlotCursor + client->SendItemPacket(i + EQEmu::Constants::CORPSE_BEGIN, inst, ItemPacketLoot); safe_delete(inst); } @@ -1119,10 +1119,10 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { item = database.GetItem(GetPlayerKillItem()); } else if (GetPlayerKillItem() == -1 || GetPlayerKillItem() == 1){ - item_data = GetItem(lootitem->slot_id - EmuConstants::CORPSE_BEGIN); //dont allow them to loot entire bags of items as pvp reward + item_data = GetItem(lootitem->slot_id - EQEmu::Constants::CORPSE_BEGIN); //dont allow them to loot entire bags of items as pvp reward } else{ - item_data = GetItem(lootitem->slot_id - EmuConstants::CORPSE_BEGIN, bag_item_data); + item_data = GetItem(lootitem->slot_id - EQEmu::Constants::CORPSE_BEGIN, bag_item_data); } if (GetPlayerKillItem()<=1 && item_data != 0) { @@ -1148,7 +1148,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } if (inst->IsAugmented()) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { ItemInst *itm = inst->GetAugment(i); if (itm) { if (client->CheckLoreConflict(itm->GetItem())) { @@ -1190,10 +1190,10 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { /* First add it to the looter - this will do the bag contents too */ if (lootitem->auto_loot) { if (!client->AutoPutLootInInventory(*inst, true, true, bag_item_data)) - client->PutLootInInventory(MainCursor, *inst, bag_item_data); + client->PutLootInInventory(SlotCursor, *inst, bag_item_data); } else { - client->PutLootInInventory(MainCursor, *inst, bag_item_data); + client->PutLootInInventory(SlotCursor, *inst, bag_item_data); } /* Update any tasks that have an activity to loot this item */ @@ -1210,7 +1210,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { /* Remove Bag Contents */ if (item->ItemClass == ItemClassContainer && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) { - for (int i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) { + for (int i = SUB_BEGIN; i < EQEmu::Constants::ITEM_CONTAINER_SIZE; i++) { if (bag_item_data[i]) { /* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */ database.DeleteItemOffCharacterCorpse(this->corpse_db_id, bag_item_data[i]->equip_slot, bag_item_data[i]->item_id); @@ -1294,13 +1294,13 @@ void Corpse::QueryLoot(Client* to) { cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQLimits::InventoryMapSize(MapCorpse, to->GetClientVersion()); + int corpselootlimit = EQEmu::Limits::InventoryMapSize(TypeCorpse, to->GetClientVersion()); for(; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; if (IsPlayerCorpse()) { - if (sitem->equip_slot >= EmuConstants::GENERAL_BAGS_BEGIN && sitem->equip_slot <= EmuConstants::CURSOR_BAG_END) + if (sitem->equip_slot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && sitem->equip_slot <= EQEmu::Constants::CURSOR_BAG_END) sitem->lootslot = 0xFFFF; else x < corpselootlimit ? sitem->lootslot = x : sitem->lootslot = 0xFFFF; @@ -1402,7 +1402,7 @@ void Corpse::Spawn() { uint32 Corpse::GetEquipment(uint8 material_slot) const { int16 invslot; - if(material_slot > EmuConstants::MATERIAL_END) { + if(material_slot > EQEmu::Constants::MATERIAL_END) { return NO_ITEM; } @@ -1416,7 +1416,7 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { const Item_Struct *item; - if(material_slot > EmuConstants::MATERIAL_END) { + if(material_slot > EQEmu::Constants::MATERIAL_END) { return 0; } @@ -1436,8 +1436,8 @@ void Corpse::UpdateEquipmentLight() m_Light.Level.Equipment = 0; for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) { - if (((*iter)->equip_slot < EmuConstants::EQUIPMENT_BEGIN || (*iter)->equip_slot > EmuConstants::EQUIPMENT_END) && (*iter)->equip_slot != MainPowerSource) { continue; } - if ((*iter)->equip_slot == MainAmmo) { continue; } + if (((*iter)->equip_slot < EQEmu::Constants::EQUIPMENT_BEGIN || (*iter)->equip_slot > EQEmu::Constants::EQUIPMENT_END) && (*iter)->equip_slot != SlotPowerSource) { continue; } + if ((*iter)->equip_slot == SlotAmmo) { continue; } auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } @@ -1448,7 +1448,7 @@ void Corpse::UpdateEquipmentLight() uint8 general_light_type = 0; for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) { - if ((*iter)->equip_slot < EmuConstants::GENERAL_BEGIN || (*iter)->equip_slot > EmuConstants::GENERAL_END) { continue; } + if ((*iter)->equip_slot < EQEmu::Constants::GENERAL_BEGIN || (*iter)->equip_slot > EQEmu::Constants::GENERAL_END) { continue; } auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } diff --git a/zone/corpse.h b/zone/corpse.h index a9916f4fd..365084b43 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -49,7 +49,7 @@ class Corpse : public Mob { /* Corpse: General */ virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } - virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } + virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } diff --git a/zone/doors.cpp b/zone/doors.cpp index d5ad8064d..a12c74fd0 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -187,7 +187,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) uint8 keepoffkeyring = GetNoKeyring(); uint32 haskey = 0; uint32 playerkey = 0; - const ItemInst *lockpicks = sender->GetInv().GetItem(MainCursor); + const ItemInst *lockpicks = sender->GetInv().GetItem(SlotCursor); haskey = sender->GetInv().HasItem(keyneeded, 1); diff --git a/zone/encounter.h b/zone/encounter.h index e341fc7ae..aa22d3870 100644 --- a/zone/encounter.h +++ b/zone/encounter.h @@ -36,7 +36,7 @@ public: //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } - virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } diff --git a/zone/entity.h b/zone/entity.h index 986a60d99..f373e4251 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -322,7 +322,7 @@ public: void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app); void QueueManaged(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, bool ackreq = true); - void AEAttack(Mob *attacker, float dist, int Hand = MainPrimary, int count = 0, bool IsFromSpell = false); + void AEAttack(Mob *attacker, float dist, int Hand = SlotPrimary, int count = 0, bool IsFromSpell = false); void AETaunt(Client *caster, float range=0, int32 bonus_hate=0); void AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true, int16 resist_adjust = 0); void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true); diff --git a/zone/forage.cpp b/zone/forage.cpp index 89d4e254f..8d8762fb7 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -153,7 +153,7 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, //we need this function to immediately determine, after we receive OP_Fishing, if we can even try to fish, otherwise we have to wait a while to get the failure bool Client::CanFish() { //make sure we still have a fishing pole on: - const ItemInst* Pole = m_inv[MainPrimary]; + const ItemInst* Pole = m_inv[SlotPrimary]; int32 bslot = m_inv.HasItemByUse(ItemTypeFishingBait, 1, invWhereWorn|invWherePersonal); const ItemInst* Bait = nullptr; if (bslot != INVALID_INDEX) @@ -258,7 +258,7 @@ void Client::GoFish() Bait = m_inv.GetItem(bslot); //if the bait isnt equipped, need to add its skill bonus - if(bslot >= EmuConstants::GENERAL_BEGIN && Bait != nullptr && Bait->GetItem()->SkillModType == SkillFishing) { + if (bslot >= EQEmu::Constants::GENERAL_BEGIN && Bait != nullptr && Bait->GetItem()->SkillModType == SkillFishing) { fishing_skill += Bait->GetItem()->SkillModValue; } @@ -317,12 +317,12 @@ void Client::GoFish() else { PushItemOnCursor(*inst); - SendItemPacket(MainCursor, inst, ItemPacketSummonItem); + SendItemPacket(SlotCursor, inst, ItemPacketSummonItem); if(RuleB(TaskSystem, EnableTaskSystem)) UpdateTasksForItem(ActivityFish, food_id); safe_delete(inst); - inst = m_inv.GetItem(MainCursor); + inst = m_inv.GetItem(SlotCursor); } if(inst) { @@ -354,7 +354,7 @@ void Client::GoFish() //and then swap out items in primary slot... too lazy to fix right now if (zone->random.Int(0, 49) == 1) { Message_StringID(MT_Skills, FISHING_POLE_BROKE); //Your fishing pole broke! - DeleteItemInInventory(MainPrimary, 0, true); + DeleteItemInInventory(SlotPrimary, 0, true); } if(CheckIncreaseSkill(SkillFishing, nullptr, 5)) @@ -433,12 +433,12 @@ void Client::ForageItem(bool guarantee) { } else { PushItemOnCursor(*inst); - SendItemPacket(MainCursor, inst, ItemPacketSummonItem); + SendItemPacket(SlotCursor, inst, ItemPacketSummonItem); if(RuleB(TaskSystem, EnableTaskSystem)) UpdateTasksForItem(ActivityForage, foragedfood); safe_delete(inst); - inst = m_inv.GetItem(MainCursor); + inst = m_inv.GetItem(SlotCursor); } if(inst) { diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 9f7f061a0..ae1bbb63b 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -35,7 +35,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { int i; if(where_to_check & invWhereWorn) { - for (i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; i++) { + for (i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -48,8 +48,8 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - if (GetItemIDAt(MainPowerSource) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(MainPowerSource) != INVALID_ID)) { - cur = m_inv.GetItem(MainPowerSource); + if (GetItemIDAt(SlotPowerSource) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(SlotPowerSource) != INVALID_ID)) { + cur = m_inv.GetItem(SlotPowerSource); if(cur && cur->GetItem()->Stackable) { x += cur->GetCharges(); } else { @@ -57,25 +57,25 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if (GetClientVersion() >= ClientVersion::SoF) - DeleteItemInInventory(MainPowerSource, 0, true); + DeleteItemInInventory(SlotPowerSource, 0, true); else - DeleteItemInInventory(MainPowerSource, 0, false); // Prevents Titanium crash + DeleteItemInInventory(SlotPowerSource, 0, false); // Prevents Titanium crash } } if(where_to_check & invWhereCursor) { - if (GetItemIDAt(MainCursor) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(MainCursor) != INVALID_ID)) { - cur = m_inv.GetItem(MainCursor); + if (GetItemIDAt(SlotCursor) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(SlotCursor) != INVALID_ID)) { + cur = m_inv.GetItem(SlotCursor); if(cur && cur->GetItem()->Stackable) { x += cur->GetCharges(); } else { x++; } - DeleteItemInInventory(MainCursor, 0, true); + DeleteItemInInventory(SlotCursor, 0, true); } - for (i = EmuConstants::CURSOR_BAG_BEGIN; i <= EmuConstants::CURSOR_BAG_END; i++) { + for (i = EQEmu::Constants::CURSOR_BAG_BEGIN; i <= EQEmu::Constants::CURSOR_BAG_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -90,7 +90,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if(where_to_check & invWherePersonal) { - for (i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) { + for (i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -103,7 +103,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - for (i = EmuConstants::GENERAL_BAGS_BEGIN; i <= EmuConstants::GENERAL_BAGS_END; i++) { + for (i = EQEmu::Constants::GENERAL_BAGS_BEGIN; i <= EQEmu::Constants::GENERAL_BAGS_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -118,7 +118,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if(where_to_check & invWhereBank) { - for (i = EmuConstants::BANK_BEGIN; i <= EmuConstants::BANK_END; i++) { + for (i = EQEmu::Constants::BANK_BEGIN; i <= EQEmu::Constants::BANK_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -131,7 +131,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - for (i = EmuConstants::BANK_BAGS_BEGIN; i <= EmuConstants::BANK_BAGS_END; i++) { + for (i = EQEmu::Constants::BANK_BAGS_BEGIN; i <= EQEmu::Constants::BANK_BAGS_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -146,7 +146,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if(where_to_check & invWhereSharedBank) { - for (i = EmuConstants::SHARED_BANK_BEGIN; i <= EmuConstants::SHARED_BANK_END; i++) { + for (i = EQEmu::Constants::SHARED_BANK_BEGIN; i <= EQEmu::Constants::SHARED_BANK_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -159,7 +159,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - for (i = EmuConstants::SHARED_BANK_BAGS_BEGIN; i <= EmuConstants::SHARED_BANK_BAGS_END; i++) { + for (i = EQEmu::Constants::SHARED_BANK_BAGS_BEGIN; i <= EQEmu::Constants::SHARED_BANK_BAGS_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -236,7 +236,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, } */ - uint32 augments[EmuConstants::ITEM_COMMON_SIZE] = { aug1, aug2, aug3, aug4, aug5, aug6 }; + uint32 augments[EQEmu::Constants::ITEM_COMMON_SIZE] = { aug1, aug2, aug3, aug4, aug5, aug6 }; uint32 classes = item->Classes; uint32 races = item->Races; @@ -246,7 +246,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, bool enforcerestr = RuleB(Inventory, EnforceAugmentRestriction); bool enforceusable = RuleB(Inventory, EnforceAugmentUsability); - for (int iter = AUG_BEGIN; iter < EmuConstants::ITEM_COMMON_SIZE; ++iter) { + for (int iter = AUG_BEGIN; iter < EQEmu::Constants::ITEM_COMMON_SIZE; ++iter) { const Item_Struct* augtest = database.GetItem(augments[iter]); if(augtest == nullptr) { @@ -540,7 +540,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, } // add any validated augments - for (int iter = AUG_BEGIN; iter < EmuConstants::ITEM_COMMON_SIZE; ++iter) { + for (int iter = AUG_BEGIN; iter < EQEmu::Constants::ITEM_COMMON_SIZE; ++iter) { if(augments[iter]) inst->PutAugment(&database, iter, augments[iter]); } @@ -554,22 +554,22 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, inst->SetOrnamentHeroModel(ornament_hero_model); // check to see if item is usable in requested slot - if(enforceusable && (((to_slot >= MainCharm) && (to_slot <= MainAmmo)) || (to_slot == MainPowerSource))) { - uint32 slottest = (to_slot == MainPowerSource) ? 22 : to_slot; // can't change '22' just yet... + if(enforceusable && (((to_slot >= SlotCharm) && (to_slot <= SlotAmmo)) || (to_slot == SlotPowerSource))) { + uint32 slottest = (to_slot == SlotPowerSource) ? 22 : to_slot; // can't change '22' just yet... if(!(slots & ((uint32)1 << slottest))) { Message(0, "This item is not equipable at slot %u - moving to cursor.", to_slot); Log.Out(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to equip an item unusable in slot %u - moved to cursor.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", GetName(), account_name, to_slot, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); - to_slot = MainCursor; + to_slot = SlotCursor; } } // put item into inventory - if (to_slot == MainCursor) { + if (to_slot == SlotCursor) { PushItemOnCursor(*inst); - SendItemPacket(MainCursor, inst, ItemPacketSummonItem); + SendItemPacket(SlotCursor, inst, ItemPacketSummonItem); } else { PutItemInInventory(to_slot, *inst, true); @@ -583,7 +583,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, DiscoverItem(item_id); /* // Augments should have been discovered prior to being placed on an item. - for (int iter = AUG_BEGIN; iter < EmuConstants::ITEM_COMMON_SIZE; ++iter) { + for (int iter = AUG_BEGIN; iter < EQEmu::Constants::ITEM_COMMON_SIZE; ++iter) { if(augments[iter] && !IsDiscovered(augments[iter])) DiscoverItem(augments[iter]); } @@ -617,7 +617,7 @@ void Client::DropItem(int16 slot_id) } // Save client inventory change to database - if (slot_id == MainCursor) { + if (slot_id == SlotCursor) { SendCursorBuffer(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(CharacterID(), s, e); @@ -706,11 +706,11 @@ void Client::SendCursorBuffer() GetName(), test_item->Name, test_item->ID); Message_StringID(MT_LootMessages, 290); parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); - DeleteItemInInventory(MainCursor); + DeleteItemInInventory(SlotCursor); SendCursorBuffer(); } else { - SendItemPacket(MainCursor, test_inst, ItemPacketSummonItem); + SendItemPacket(SlotCursor, test_inst, ItemPacketSummonItem); } } @@ -788,7 +788,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd bool isDeleted = m_inv.DeleteItem(slot_id, quantity); const ItemInst* inst = nullptr; - if (slot_id == MainCursor) { + if (slot_id == SlotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); if(update_db) database.SaveCursor(character_id, s, e); @@ -840,7 +840,7 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update) m_inv.PushCursor(inst); if (client_update) { - SendItemPacket(MainCursor, &inst, ItemPacketSummonItem); + SendItemPacket(SlotCursor, &inst, ItemPacketSummonItem); } auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); @@ -854,7 +854,7 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update) bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client_update) { Log.Out(Logs::Detail, Logs::Inventory, "Putting item %s (%d) into slot %d", inst.GetItem()->Name, inst.GetItem()->ID, slot_id); - if (slot_id == MainCursor) { // don't trust macros before conditional statements... + if (slot_id == SlotCursor) { // don't trust macros before conditional statements... return PushItemOnCursor(inst, client_update); } else { @@ -863,11 +863,11 @@ bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client if (client_update) { - SendItemPacket(slot_id, &inst, ((slot_id == MainCursor) ? ItemPacketSummonItem : ItemPacketTrade)); + SendItemPacket(slot_id, &inst, ((slot_id == SlotCursor) ? ItemPacketSummonItem : ItemPacketTrade)); //SendWearChange(Inventory::CalcMaterialFromSlot(slot_id)); } - if (slot_id == MainCursor) { + if (slot_id == SlotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); return database.SaveCursor(this->CharacterID(), s, e); } @@ -885,7 +885,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI bool cursor_empty = m_inv.CursorEmpty(); - if (slot_id == MainCursor) { + if (slot_id == SlotCursor) { m_inv.PushCursor(inst); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(this->CharacterID(), s, e); @@ -896,7 +896,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI } // Subordinate items in cursor buffer must be sent via ItemPacketSummonItem or we just overwrite the visible cursor and desync the client - if (slot_id == MainCursor && !cursor_empty) { + if (slot_id == SlotCursor && !cursor_empty) { // RoF+ currently has a specialized cursor handler if (GetClientVersion() < ClientVersion::RoF) SendItemPacket(slot_id, &inst, ItemPacketSummonItem); @@ -906,7 +906,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI } if (bag_item_data) { - for (int index = 0; index < EmuConstants::ITEM_CONTAINER_SIZE; ++index) { + for (int index = 0; index < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++index) { if (bag_item_data[index] == nullptr) continue; @@ -924,12 +924,12 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI // Dump bag contents to cursor in the event that owning bag is not the first cursor item // (This assumes that the data passed is correctly associated..no safety checks are implemented) - if (slot_id == MainCursor && !cursor_empty) { + if (slot_id == SlotCursor && !cursor_empty) { Log.Out(Logs::Detail, Logs::Inventory, "Putting bag loot item %s (%d) into slot %d (non-empty cursor override)", - inst.GetItem()->Name, inst.GetItem()->ID, MainCursor); + inst.GetItem()->Name, inst.GetItem()->ID, SlotCursor); - PutLootInInventory(MainCursor, *bagitem); + PutLootInInventory(SlotCursor, *bagitem); } else { auto bag_slot = Inventory::CalcSlotId(slot_id, index); @@ -951,7 +951,7 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur return false; int16 i; uint32 item_id = item->GetItem()->ID; - for (i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) { + for (i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { ItemInst* tmp_inst = m_inv.GetItem(i); if(tmp_inst && tmp_inst->GetItem()->ID == item_id && tmp_inst->GetCharges() < tmp_inst->GetItem()->StackSize){ MoveItemCharges(*item, i, type); @@ -962,8 +962,8 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur return true; } } - for (i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) { - for (uint8 j = SUB_BEGIN; j < EmuConstants::ITEM_CONTAINER_SIZE; j++) { + for (i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { + for (uint8 j = SUB_BEGIN; j < EQEmu::Constants::ITEM_CONTAINER_SIZE; j++) { uint16 slotid = Inventory::CalcSlotId(i, j); ItemInst* tmp_inst = m_inv.GetItem(slotid); @@ -988,29 +988,29 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs // #1: Try to auto equip if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level && (!inst.GetItem()->Attuneable || inst.IsAttuned()) && inst.GetItem()->ItemType != ItemTypeAugmentation) { // too messy as-is... - for (int16 i = EmuConstants::EQUIPMENT_BEGIN; i < MainPowerSource; i++) { // originally (i < 22) - if (i == EmuConstants::GENERAL_BEGIN) { + for (int16 i = EQEmu::Constants::EQUIPMENT_BEGIN; i < SlotPowerSource; i++) { // originally (i < 22) + if (i == EQEmu::Constants::GENERAL_BEGIN) { // added power source check for SoF+ clients if (this->GetClientVersion() >= ClientVersion::SoF) - i = MainPowerSource; + i = SlotPowerSource; else break; } if (!m_inv[i]) { - if (i == MainPrimary && inst.IsWeapon()) { // If item is primary slot weapon + if (i == SlotPrimary && inst.IsWeapon()) { // If item is primary slot weapon if ((inst.GetItem()->ItemType == ItemType2HSlash) || (inst.GetItem()->ItemType == ItemType2HBlunt) || (inst.GetItem()->ItemType == ItemType2HPiercing)) { // and uses 2hs \ 2hb \ 2hp - if (m_inv[MainSecondary]) { // and if secondary slot is not empty + if (m_inv[SlotSecondary]) { // and if secondary slot is not empty continue; // Can't auto-equip } } } - if (i == MainSecondary && m_inv[MainPrimary]) { // check to see if primary slot is a two hander - uint8 use = m_inv[MainPrimary]->GetItem()->ItemType; + if (i == SlotSecondary && m_inv[SlotPrimary]) { // check to see if primary slot is a two hander + uint8 use = m_inv[SlotPrimary]->GetItem()->ItemType; if (use == ItemType2HSlash || use == ItemType2HBlunt || use == ItemType2HPiercing) continue; } - if (i == MainSecondary && inst.IsWeapon() && !CanThisClassDualWield()) { + if (i == SlotSecondary && inst.IsWeapon() && !CanThisClassDualWield()) { continue; } @@ -1018,7 +1018,7 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs //send worn to everyone... PutLootInInventory(i, inst); uint8 worn_slot_material = Inventory::CalcMaterialFromSlot(i); - if (worn_slot_material != _MaterialInvalid) { + if (worn_slot_material != MaterialInvalid) { SendWearChange(worn_slot_material); } @@ -1061,7 +1061,7 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type) tmp_inst->SetCharges(tmp_inst->GetCharges() + charges_to_move); from.SetCharges(from.GetCharges() - charges_to_move); SendLootItemInPacket(tmp_inst, to_slot); - if (to_slot == MainCursor) { + if (to_slot == SlotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(this->CharacterID(), s, e); } @@ -1318,16 +1318,16 @@ void Client::SendLootItemInPacket(const ItemInst* inst, int16 slot_id) bool Client::IsValidSlot(uint32 slot) { if ((slot == (uint32)INVALID_INDEX) || - (slot >= MAIN_BEGIN && slot < EmuConstants::MAP_POSSESSIONS_SIZE) || - (slot >= EmuConstants::GENERAL_BAGS_BEGIN && slot <= EmuConstants::CURSOR_BAG_END) || - (slot >= EmuConstants::TRIBUTE_BEGIN && slot <= EmuConstants::TRIBUTE_END) || - (slot >= EmuConstants::BANK_BEGIN && slot <= EmuConstants::BANK_END) || - (slot >= EmuConstants::BANK_BAGS_BEGIN && slot <= EmuConstants::BANK_BAGS_END) || - (slot >= EmuConstants::SHARED_BANK_BEGIN && slot <= EmuConstants::SHARED_BANK_END) || - (slot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && slot <= EmuConstants::SHARED_BANK_BAGS_END) || - (slot >= EmuConstants::TRADE_BEGIN && slot <= EmuConstants::TRADE_END) || - (slot >= EmuConstants::WORLD_BEGIN && slot <= EmuConstants::WORLD_END) || - (slot == MainPowerSource) + (slot >= SLOT_BEGIN && slot < EQEmu::Constants::TYPE_POSSESSIONS_SIZE) || + (slot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot <= EQEmu::Constants::CURSOR_BAG_END) || + (slot >= EQEmu::Constants::TRIBUTE_BEGIN && slot <= EQEmu::Constants::TRIBUTE_END) || + (slot >= EQEmu::Constants::BANK_BEGIN && slot <= EQEmu::Constants::BANK_END) || + (slot >= EQEmu::Constants::BANK_BAGS_BEGIN && slot <= EQEmu::Constants::BANK_BAGS_END) || + (slot >= EQEmu::Constants::SHARED_BANK_BEGIN && slot <= EQEmu::Constants::SHARED_BANK_END) || + (slot >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && slot <= EQEmu::Constants::SHARED_BANK_BAGS_END) || + (slot >= EQEmu::Constants::TRADE_BEGIN && slot <= EQEmu::Constants::TRADE_END) || + (slot >= EQEmu::Constants::WORLD_BEGIN && slot <= EQEmu::Constants::WORLD_END) || + (slot == SlotPowerSource) ) { return true; } @@ -1338,10 +1338,10 @@ bool Client::IsValidSlot(uint32 slot) { bool Client::IsBankSlot(uint32 slot) { - if ((slot >= EmuConstants::BANK_BEGIN && slot <= EmuConstants::BANK_END) || - (slot >= EmuConstants::BANK_BAGS_BEGIN && slot <= EmuConstants::BANK_BAGS_END) || - (slot >= EmuConstants::SHARED_BANK_BEGIN && slot <= EmuConstants::SHARED_BANK_END) || - (slot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && slot <= EmuConstants::SHARED_BANK_BAGS_END)) + if ((slot >= EQEmu::Constants::BANK_BEGIN && slot <= EQEmu::Constants::BANK_END) || + (slot >= EQEmu::Constants::BANK_BAGS_BEGIN && slot <= EQEmu::Constants::BANK_BAGS_END) || + (slot >= EQEmu::Constants::SHARED_BANK_BEGIN && slot <= EQEmu::Constants::SHARED_BANK_END) || + (slot >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && slot <= EQEmu::Constants::SHARED_BANK_BAGS_END)) { return true; } @@ -1377,8 +1377,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit if (GetClientVersion() >= ClientVersion::RoF) { return true; } // Can't do RoF+ - if (move_in->to_slot == MainCursor) { - auto test_inst = m_inv.GetItem(MainCursor); + if (move_in->to_slot == SlotCursor) { + auto test_inst = m_inv.GetItem(SlotCursor); if (test_inst == nullptr) { return true; } auto test_item = test_inst->GetItem(); if (test_item == nullptr) { return true; } @@ -1397,18 +1397,18 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { GetName(), test_item->Name, test_item->ID); Message_StringID(MT_LootMessages, 290); parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); - DeleteItemInInventory(MainCursor, 0, true); + DeleteItemInInventory(SlotCursor, 0, true); } } return true; } if (move_in->to_slot == (uint32)INVALID_INDEX) { - if (move_in->from_slot == (uint32)MainCursor) { + if (move_in->from_slot == (uint32)SlotCursor) { Log.Out(Logs::Detail, Logs::Inventory, "Client destroyed item from cursor slot %d", move_in->from_slot); if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit - ItemInst *inst = m_inv.GetItem(MainCursor); + ItemInst *inst = m_inv.GetItem(SlotCursor); if(inst) { parse->EventItem(EVENT_DESTROY_ITEM, this, inst, nullptr, "", 0); } @@ -1425,9 +1425,9 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return true; // Item deletion } } - if(auto_attack && (move_in->from_slot == MainPrimary || move_in->from_slot == MainSecondary || move_in->from_slot == MainRange)) + if(auto_attack && (move_in->from_slot == SlotPrimary || move_in->from_slot == SlotSecondary || move_in->from_slot == SlotRange)) SetAttackTimer(); - else if(auto_attack && (move_in->to_slot == MainPrimary || move_in->to_slot == MainSecondary || move_in->to_slot == MainRange)) + else if(auto_attack && (move_in->to_slot == SlotPrimary || move_in->to_slot == SlotSecondary || move_in->to_slot == SlotRange)) SetAttackTimer(); // Step 1: Variables int16 src_slot_id = (int16)move_in->from_slot; @@ -1475,13 +1475,13 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { uint32 dstbagid = 0; //if (src_slot_id >= 250 && src_slot_id < 330) { - if (src_slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && src_slot_id <= EmuConstants::GENERAL_BAGS_END) { + if (src_slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && src_slot_id <= EQEmu::Constants::GENERAL_BAGS_END) { srcbag = m_inv.GetItem(((int)(src_slot_id / 10)) - 3); if (srcbag) srcbagid = srcbag->GetItem()->ID; } //if (dst_slot_id >= 250 && dst_slot_id < 330) { - if (dst_slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && dst_slot_id <= EmuConstants::GENERAL_BAGS_END) { + if (dst_slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && dst_slot_id <= EQEmu::Constants::GENERAL_BAGS_END) { dstbag = m_inv.GetItem(((int)(dst_slot_id / 10)) - 3); if (dstbag) dstbagid = dstbag->GetItem()->ID; @@ -1494,7 +1494,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Step 2: Validate item in from_slot // After this, we can assume src_inst is a valid ptr - if (!src_inst && (src_slot_id < EmuConstants::WORLD_BEGIN || src_slot_id > EmuConstants::WORLD_END)) { + if (!src_inst && (src_slot_id < EQEmu::Constants::WORLD_BEGIN || src_slot_id > EQEmu::Constants::WORLD_END)) { if (dst_inst) { // If there is no source item, but there is a destination item, // move the slots around before deleting the invalid source slot item, @@ -1508,14 +1508,14 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return false; } //verify shared bank transactions in the database - if(src_inst && src_slot_id >= EmuConstants::SHARED_BANK_BEGIN && src_slot_id <= EmuConstants::SHARED_BANK_BAGS_END) { + if(src_inst && src_slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { if(!database.VerifyInventory(account_id, src_slot_id, src_inst)) { Log.Out(Logs::General, Logs::Error, "Player %s on account %s was found exploiting the shared bank.\n", GetName(), account_name); DeleteItemInInventory(dst_slot_id,0,true); return(false); } - if(src_slot_id >= EmuConstants::SHARED_BANK_BEGIN && src_slot_id <= EmuConstants::SHARED_BANK_END && src_inst->IsType(ItemClassContainer)){ - for (uint8 idx = SUB_BEGIN; idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) { + if(src_slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::Constants::SHARED_BANK_END && src_inst->IsType(ItemClassContainer)){ + for (uint8 idx = SUB_BEGIN; idx < EQEmu::Constants::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = src_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(src_slot_id, idx), baginst)){ DeleteItemInInventory(Inventory::CalcSlotId(src_slot_id, idx),0,false); @@ -1523,14 +1523,14 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } } } - if(dst_inst && dst_slot_id >= EmuConstants::SHARED_BANK_BEGIN && dst_slot_id <= EmuConstants::SHARED_BANK_BAGS_END) { + if(dst_inst && dst_slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { if(!database.VerifyInventory(account_id, dst_slot_id, dst_inst)) { Log.Out(Logs::General, Logs::Error, "Player %s on account %s was found exploting the shared bank.\n", GetName(), account_name); DeleteItemInInventory(src_slot_id,0,true); return(false); } - if(dst_slot_id >= EmuConstants::SHARED_BANK_BEGIN && dst_slot_id <= EmuConstants::SHARED_BANK_END && dst_inst->IsType(ItemClassContainer)){ - for (uint8 idx = SUB_BEGIN; idx < EmuConstants::ITEM_CONTAINER_SIZE; idx++) { + if(dst_slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::Constants::SHARED_BANK_END && dst_inst->IsType(ItemClassContainer)){ + for (uint8 idx = SUB_BEGIN; idx < EQEmu::Constants::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = dst_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(dst_slot_id, idx), baginst)){ DeleteItemInInventory(Inventory::CalcSlotId(dst_slot_id, idx),0,false); @@ -1542,8 +1542,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Check for No Drop Hacks Mob* with = trade->With(); - if (((with && with->IsClient() && dst_slot_id >= EmuConstants::TRADE_BEGIN && dst_slot_id <= EmuConstants::TRADE_END) || - (dst_slot_id >= EmuConstants::SHARED_BANK_BEGIN && dst_slot_id <= EmuConstants::SHARED_BANK_BAGS_END)) + if (((with && with->IsClient() && dst_slot_id >= EQEmu::Constants::TRADE_BEGIN && dst_slot_id <= EQEmu::Constants::TRADE_END) || + (dst_slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END)) && GetInv().CheckNoDrop(src_slot_id) && RuleI(World, FVNoDropFlag) == 0 || RuleI(Character, MinStatusForNoDropExemptions) < Admin() && RuleI(World, FVNoDropFlag) == 2) { auto ndh_inst = m_inv[src_slot_id]; @@ -1573,7 +1573,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Step 3: Check for interaction with World Container (tradeskills) if(m_tradeskill_object != nullptr) { - if (src_slot_id >= EmuConstants::WORLD_BEGIN && src_slot_id <= EmuConstants::WORLD_END) { + if (src_slot_id >= EQEmu::Constants::WORLD_BEGIN && src_slot_id <= EQEmu::Constants::WORLD_END) { // Picking up item from world container ItemInst* inst = m_tradeskill_object->PopItem(Inventory::CalcBagIdx(src_slot_id)); if (inst) { @@ -1585,7 +1585,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return true; } - else if (dst_slot_id >= EmuConstants::WORLD_BEGIN && dst_slot_id <= EmuConstants::WORLD_END) { + else if (dst_slot_id >= EQEmu::Constants::WORLD_BEGIN && dst_slot_id <= EQEmu::Constants::WORLD_END) { // Putting item into world container, which may swap (or pile onto) with existing item uint8 world_idx = Inventory::CalcBagIdx(dst_slot_id); ItemInst* world_inst = m_tradeskill_object->PopItem(world_idx); @@ -1637,7 +1637,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } safe_delete(world_inst); - if (src_slot_id == MainCursor) + if (src_slot_id == SlotCursor) { if (dstitemid == 0) { @@ -1658,15 +1658,15 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } // Step 4: Check for entity trade - if (dst_slot_id >= EmuConstants::TRADE_BEGIN && dst_slot_id <= EmuConstants::TRADE_END) { - if (src_slot_id != MainCursor) { + if (dst_slot_id >= EQEmu::Constants::TRADE_BEGIN && dst_slot_id <= EQEmu::Constants::TRADE_END) { + if (src_slot_id != SlotCursor) { Kick(); return false; } if (with) { Log.Out(Logs::Detail, Logs::Inventory, "Trade item move from slot %d to slot %d (trade with %s)", src_slot_id, dst_slot_id, with->GetName()); // Fill Trade list with items from cursor - if (!m_inv[MainCursor]) { + if (!m_inv[SlotCursor]) { Message(13, "Error: Cursor item not located on server!"); return false; } @@ -1686,7 +1686,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit SummonItem(src_inst->GetID(), src_inst->GetCharges()); - DeleteItemInInventory(MainCursor); + DeleteItemInInventory(SlotCursor); return true; } @@ -1751,12 +1751,12 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } else { // Not dealing with charges - just do direct swap - if(src_inst && (dst_slot_id <= EmuConstants::EQUIPMENT_END || dst_slot_id == MainPowerSource) && dst_slot_id >= EmuConstants::EQUIPMENT_BEGIN) { + if(src_inst && (dst_slot_id <= EQEmu::Constants::EQUIPMENT_END || dst_slot_id == SlotPowerSource) && dst_slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN) { if (src_inst->GetItem()->Attuneable) { src_inst->SetAttuned(true); } if (src_inst->IsAugmented()) { - for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { if (src_inst->GetAugment(i)) { if (src_inst->GetAugment(i)->GetItem()->Attuneable) { src_inst->GetAugment(i)->SetAttuned(true); @@ -1769,7 +1769,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(!m_inv.SwapItem(src_slot_id, dst_slot_id)) { return false; } Log.Out(Logs::Detail, Logs::Inventory, "Moving entire item from slot %d to slot %d", src_slot_id, dst_slot_id); - if(src_slot_id <= EmuConstants::EQUIPMENT_END || src_slot_id == MainPowerSource) { + if(src_slot_id <= EQEmu::Constants::EQUIPMENT_END || src_slot_id == SlotPowerSource) { if(src_inst) { parse->EventItem(EVENT_UNEQUIP_ITEM, this, src_inst, nullptr, "", src_slot_id); } @@ -1779,7 +1779,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } } - if(dst_slot_id <= EmuConstants::EQUIPMENT_END || dst_slot_id == MainPowerSource) { + if(dst_slot_id <= EQEmu::Constants::EQUIPMENT_END || dst_slot_id == SlotPowerSource) { if(dst_inst) { parse->EventItem(EVENT_UNEQUIP_ITEM, this, dst_inst, nullptr, "", dst_slot_id); } @@ -1791,12 +1791,12 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } int matslot = SlotConvert2(dst_slot_id); - if (dst_slot_id <= EmuConstants::EQUIPMENT_END && matslot != MaterialHead) { // think this is to allow the client to update with /showhelm + if (dst_slot_id <= EQEmu::Constants::EQUIPMENT_END && matslot != MaterialHead) { // think this is to allow the client to update with /showhelm SendWearChange(matslot); } // Step 7: Save change to the database - if (src_slot_id == MainCursor) { + if (src_slot_id == SlotCursor) { // If not swapping another item to cursor and stacking items were depleted if (dstitemid == 0 || all_to_stack == true) { @@ -1809,7 +1809,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { database.SaveInventory(character_id, m_inv.GetItem(src_slot_id), src_slot_id); } - if (dst_slot_id == MainCursor) { + if (dst_slot_id == SlotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(character_id, s, e); } @@ -1833,7 +1833,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { Log.Out(Logs::Detail, Logs::Inventory, "Inventory desyncronization. (charname: %s, source: %i, destination: %i)", GetName(), move_slots->from_slot, move_slots->to_slot); Message(15, "Inventory Desyncronization detected: Resending slot data..."); - if((move_slots->from_slot >= EmuConstants::EQUIPMENT_BEGIN && move_slots->from_slot <= EmuConstants::CURSOR_BAG_END) || move_slots->from_slot == MainPowerSource) { + if((move_slots->from_slot >= EQEmu::Constants::EQUIPMENT_BEGIN && move_slots->from_slot <= EQEmu::Constants::CURSOR_BAG_END) || move_slots->from_slot == SlotPowerSource) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { // This prevents the client from crashing when closing any 'phantom' bags @@ -1876,7 +1876,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); } } - if((move_slots->to_slot >= EmuConstants::EQUIPMENT_BEGIN && move_slots->to_slot <= EmuConstants::CURSOR_BAG_END) || move_slots->to_slot == MainPowerSource) { + if((move_slots->to_slot >= EQEmu::Constants::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::Constants::CURSOR_BAG_END) || move_slots->to_slot == SlotPowerSource) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' @@ -2019,7 +2019,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { void Client::DyeArmor(DyeStruct* dye){ int16 slot=0; - for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_TINT_END; i++) { + for (int i = EQEmu::Constants::MATERIAL_BEGIN; i <= EQEmu::Constants::MATERIAL_TINT_END; i++) { if ((m_pp.item_tint[i].Color & 0x00FFFFFF) != (dye->dye[i].Color & 0x00FFFFFF)) { slot = m_inv.HasItem(32557, 1, invWherePersonal); if (slot != INVALID_INDEX){ @@ -2058,7 +2058,7 @@ bool Client::DecreaseByItemType(uint32 type, uint8 amt) { const Item_Struct* TempItem = 0; ItemInst* ins; int x; - for(x=EmuConstants::POSSESSIONS_BEGIN; x <= EmuConstants::POSSESSIONS_END; x++) + for(x=EQEmu::Constants::POSSESSIONS_BEGIN; x <= EQEmu::Constants::POSSESSIONS_END; x++) { TempItem = 0; ins = GetInv().GetItem(x); @@ -2080,7 +2080,7 @@ bool Client::DecreaseByItemType(uint32 type, uint8 amt) { return true; } } - for(x=EmuConstants::GENERAL_BAGS_BEGIN; x <= EmuConstants::GENERAL_BAGS_END; x++) + for(x=EQEmu::Constants::GENERAL_BAGS_BEGIN; x <= EQEmu::Constants::GENERAL_BAGS_END; x++) { TempItem = 0; ins = GetInv().GetItem(x); @@ -2111,10 +2111,10 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) { ItemInst* ins = nullptr; int x; int num = 0; - for(x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::GENERAL_BAGS_END; x++) + for(x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::GENERAL_BAGS_END; x++) { - if (x == MainCursor + 1) - x = EmuConstants::GENERAL_BAGS_BEGIN; + if (x == SlotCursor + 1) + x = EQEmu::Constants::GENERAL_BAGS_BEGIN; TempItem = nullptr; ins = GetInv().GetItem(x); if (ins) @@ -2128,10 +2128,10 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) { } if (num < amt) return false; - for(x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::GENERAL_BAGS_END; x++) // should this be CURSOR_BAG_END? + for(x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::GENERAL_BAGS_END; x++) // should this be CURSOR_BAG_END? { - if (x == MainCursor + 1) - x = EmuConstants::GENERAL_BAGS_BEGIN; + if (x == SlotCursor + 1) + x = EQEmu::Constants::GENERAL_BAGS_BEGIN; TempItem = nullptr; ins = GetInv().GetItem(x); if (ins) @@ -2227,7 +2227,7 @@ static bool CopyBagContents(ItemInst* new_bag, const ItemInst* old_bag) void Client::DisenchantSummonedBags(bool client_update) { - for (auto slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::GENERAL_BEGIN; slot_id <= EQEmu::Constants::GENERAL_END; ++slot_id) { auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } @@ -2248,7 +2248,7 @@ void Client::DisenchantSummonedBags(bool client_update) safe_delete(new_inst); } - for (auto slot_id = EmuConstants::BANK_BEGIN; slot_id <= EmuConstants::BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::BANK_BEGIN; slot_id <= EQEmu::Constants::BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } @@ -2269,7 +2269,7 @@ void Client::DisenchantSummonedBags(bool client_update) safe_delete(new_inst); } - for (auto slot_id = EmuConstants::SHARED_BANK_BEGIN; slot_id <= EmuConstants::SHARED_BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::Constants::SHARED_BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } @@ -2291,7 +2291,7 @@ void Client::DisenchantSummonedBags(bool client_update) } while (!m_inv.CursorEmpty()) { - auto inst = m_inv[MainCursor]; + auto inst = m_inv[SlotCursor]; if (!inst) { break; } if (!IsSummonedBagID(inst->GetItem()->ID)) { break; } if (inst->GetItem()->ItemClass != ItemClassContainer) { break; } @@ -2305,14 +2305,14 @@ void Client::DisenchantSummonedBags(bool client_update) if (!new_inst) { break; } if (CopyBagContents(new_inst, inst)) { - Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, MainCursor); + Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, SlotCursor); std::list local; local.push_front(new_inst); - m_inv.PopItem(MainCursor); + m_inv.PopItem(SlotCursor); safe_delete(inst); while (!m_inv.CursorEmpty()) { - auto limbo_inst = m_inv.PopItem(MainCursor); + auto limbo_inst = m_inv.PopItem(SlotCursor); if (limbo_inst == nullptr) { continue; } local.push_back(limbo_inst); } @@ -2338,7 +2338,7 @@ void Client::DisenchantSummonedBags(bool client_update) void Client::RemoveNoRent(bool client_update) { - for (auto slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::Constants::EQUIPMENT_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2346,7 +2346,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::GENERAL_BEGIN; slot_id <= EQEmu::Constants::GENERAL_END; ++slot_id) { auto inst = m_inv[slot_id]; if (inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2354,15 +2354,15 @@ void Client::RemoveNoRent(bool client_update) } } - if (m_inv[MainPowerSource]) { - auto inst = m_inv[MainPowerSource]; + if (m_inv[SlotPowerSource]) { + auto inst = m_inv[SlotPowerSource]; if (inst && !inst->GetItem()->NoRent) { - Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, MainPowerSource); - DeleteItemInInventory(MainPowerSource, 0, (GetClientVersion() >= ClientVersion::SoF) ? client_update : false); // Ti slot non-existent + Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, SlotPowerSource); + DeleteItemInInventory(SlotPowerSource, 0, (GetClientVersion() >= ClientVersion::SoF) ? client_update : false); // Ti slot non-existent } } - for (auto slot_id = EmuConstants::GENERAL_BAGS_BEGIN; slot_id <= EmuConstants::CURSOR_BAG_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::Constants::CURSOR_BAG_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2370,7 +2370,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EmuConstants::BANK_BEGIN; slot_id <= EmuConstants::BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::BANK_BEGIN; slot_id <= EQEmu::Constants::BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2378,7 +2378,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EmuConstants::BANK_BAGS_BEGIN; slot_id <= EmuConstants::BANK_BAGS_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::BANK_BAGS_BEGIN; slot_id <= EQEmu::Constants::BANK_BAGS_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2386,7 +2386,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EmuConstants::SHARED_BANK_BEGIN; slot_id <= EmuConstants::SHARED_BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::Constants::SHARED_BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2394,7 +2394,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EmuConstants::SHARED_BANK_BAGS_BEGIN; slot_id <= EmuConstants::SHARED_BANK_BAGS_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::SHARED_BANK_BAGS_BEGIN; slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2406,7 +2406,7 @@ void Client::RemoveNoRent(bool client_update) std::list local; while (!m_inv.CursorEmpty()) { - auto inst = m_inv.PopItem(MainCursor); + auto inst = m_inv.PopItem(SlotCursor); if (inst == nullptr) { continue; } local.push_back(inst); } @@ -2432,7 +2432,7 @@ void Client::RemoveNoRent(bool client_update) // Two new methods to alleviate perpetual login desyncs void Client::RemoveDuplicateLore(bool client_update) { - for (auto slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::Constants::EQUIPMENT_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2445,7 +2445,7 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - for (auto slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::GENERAL_BEGIN; slot_id <= EQEmu::Constants::GENERAL_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if (CheckLoreConflict(inst->GetItem())) { @@ -2458,21 +2458,21 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - if (m_inv[MainPowerSource]) { - auto inst = m_inv.PopItem(MainPowerSource); + if (m_inv[SlotPowerSource]) { + auto inst = m_inv.PopItem(SlotPowerSource); if (inst) { if (CheckLoreConflict(inst->GetItem())) { - Log.Out(Logs::Detail, Logs::Inventory, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, MainPowerSource); - database.SaveInventory(character_id, nullptr, MainPowerSource); + Log.Out(Logs::Detail, Logs::Inventory, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, SlotPowerSource); + database.SaveInventory(character_id, nullptr, SlotPowerSource); } else { - m_inv.PutItem(MainPowerSource, *inst); + m_inv.PutItem(SlotPowerSource, *inst); } safe_delete(inst); } } - for (auto slot_id = EmuConstants::GENERAL_BAGS_BEGIN; slot_id <= EmuConstants::CURSOR_BAG_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::Constants::CURSOR_BAG_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2485,7 +2485,7 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - for (auto slot_id = EmuConstants::BANK_BEGIN; slot_id <= EmuConstants::BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::BANK_BEGIN; slot_id <= EQEmu::Constants::BANK_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2498,7 +2498,7 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - for (auto slot_id = EmuConstants::BANK_BAGS_BEGIN; slot_id <= EmuConstants::BANK_BAGS_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::BANK_BAGS_BEGIN; slot_id <= EQEmu::Constants::BANK_BAGS_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2518,7 +2518,7 @@ void Client::RemoveDuplicateLore(bool client_update) std::list local_2; while (!m_inv.CursorEmpty()) { - auto inst = m_inv.PopItem(MainCursor); + auto inst = m_inv.PopItem(SlotCursor); if (inst == nullptr) { continue; } local_1.push_back(inst); } @@ -2559,7 +2559,7 @@ void Client::RemoveDuplicateLore(bool client_update) void Client::MoveSlotNotAllowed(bool client_update) { - for (auto slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; ++slot_id) { + for (auto slot_id = EQEmu::Constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::Constants::EQUIPMENT_END; ++slot_id) { if(m_inv[slot_id] && !m_inv[slot_id]->IsSlotAllowed(slot_id)) { auto inst = m_inv.PopItem(slot_id); bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; @@ -2571,13 +2571,13 @@ void Client::MoveSlotNotAllowed(bool client_update) } } - if (m_inv[MainPowerSource] && !m_inv[MainPowerSource]->IsSlotAllowed(MainPowerSource)) { - auto inst = m_inv.PopItem(MainPowerSource); + if (m_inv[SlotPowerSource] && !m_inv[SlotPowerSource]->IsSlotAllowed(SlotPowerSource)) { + auto inst = m_inv.PopItem(SlotPowerSource); bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size, is_arrow); - Log.Out(Logs::Detail, Logs::Inventory, "Slot Assignment Error: Moving %s from slot %i to %i", inst->GetItem()->Name, MainPowerSource, free_slot_id); + Log.Out(Logs::Detail, Logs::Inventory, "Slot Assignment Error: Moving %s from slot %i to %i", inst->GetItem()->Name, SlotPowerSource, free_slot_id); PutItemInInventory(free_slot_id, *inst, (GetClientVersion() >= ClientVersion::SoF) ? client_update : false); - database.SaveInventory(character_id, nullptr, MainPowerSource); + database.SaveInventory(character_id, nullptr, SlotPowerSource); safe_delete(inst); } @@ -2591,7 +2591,7 @@ uint32 Client::GetEquipment(uint8 material_slot) const int16 invslot; const ItemInst *item; - if(material_slot > EmuConstants::MATERIAL_END) + if(material_slot > EQEmu::Constants::MATERIAL_END) { return 0; } @@ -2629,7 +2629,7 @@ int32 Client::GetEquipmentMaterial(uint8 material_slot) uint32 Client::GetEquipmentColor(uint8 material_slot) const { - if (material_slot > EmuConstants::MATERIAL_END) + if (material_slot > EQEmu::Constants::MATERIAL_END) return 0; const Item_Struct *item = database.GetItem(GetEquipment(material_slot)); @@ -2695,13 +2695,13 @@ static int16 BandolierSlotToWeaponSlot(int BandolierSlot) switch (BandolierSlot) { case bandolierPrimary: - return MainPrimary; + return SlotPrimary; case bandolierSecondary: - return MainSecondary; + return SlotSecondary; case bandolierRange: - return MainRange; + return SlotRange; default: - return MainAmmo; + return SlotAmmo; } } @@ -2774,13 +2774,13 @@ void Client::SetBandolier(const EQApplicationPacket *app) // removed 'invWhereCursor' argument from above and implemented slots 30, 331-340 checks here if (slot == INVALID_INDEX) { - if (m_inv.GetItem(MainCursor)) { - if (m_inv.GetItem(MainCursor)->GetItem()->ID == m_pp.bandoliers[bss->Number].Items[BandolierSlot].ID && - m_inv.GetItem(MainCursor)->GetCharges() >= 1) { // '> 0' the same, but this matches Inventory::_HasItem conditional check - slot = MainCursor; + if (m_inv.GetItem(SlotCursor)) { + if (m_inv.GetItem(SlotCursor)->GetItem()->ID == m_pp.bandoliers[bss->Number].Items[BandolierSlot].ID && + m_inv.GetItem(SlotCursor)->GetCharges() >= 1) { // '> 0' the same, but this matches Inventory::_HasItem conditional check + slot = SlotCursor; } - else if (m_inv.GetItem(MainCursor)->GetItem()->ItemClass == 1) { - for(int16 CursorBagSlot = EmuConstants::CURSOR_BAG_BEGIN; CursorBagSlot <= EmuConstants::CURSOR_BAG_END; CursorBagSlot++) { + else if (m_inv.GetItem(SlotCursor)->GetItem()->ItemClass == 1) { + for(int16 CursorBagSlot = EQEmu::Constants::CURSOR_BAG_BEGIN; CursorBagSlot <= EQEmu::Constants::CURSOR_BAG_END; CursorBagSlot++) { if (m_inv.GetItem(CursorBagSlot)) { if (m_inv.GetItem(CursorBagSlot)->GetItem()->ID == m_pp.bandoliers[bss->Number].Items[BandolierSlot].ID && m_inv.GetItem(CursorBagSlot)->GetCharges() >= 1) { // ditto @@ -2926,7 +2926,7 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { // if(ItemToReturn->IsStackable()) { - for (int16 i = EmuConstants::GENERAL_BEGIN; i <= MainCursor; i++) { // changed slot max to 30 from 29. client will stack into slot 30 (bags too) before moving. + for (int16 i = EQEmu::Constants::GENERAL_BEGIN; i <= SlotCursor; i++) { // changed slot max to 30 from 29. client will stack into slot 30 (bags too) before moving. ItemInst* InvItem = m_inv.GetItem(i); @@ -2985,7 +2985,7 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { // We have tried stacking items, now just try and find an empty slot. - for (int16 i = EmuConstants::GENERAL_BEGIN; i <= MainCursor; i++) { // changed slot max to 30 from 29. client will move into slot 30 (bags too) before pushing onto cursor. + for (int16 i = EQEmu::Constants::GENERAL_BEGIN; i <= SlotCursor; i++) { // changed slot max to 30 from 29. client will move into slot 30 (bags too) before pushing onto cursor. ItemInst* InvItem = m_inv.GetItem(i); @@ -3046,27 +3046,27 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool std::map instmap; // build reference map - for (int16 index = MAIN_BEGIN; index < EmuConstants::MAP_POSSESSIONS_SIZE; ++index) { + for (int16 index = SLOT_BEGIN; index < EQEmu::Constants::TYPE_POSSESSIONS_SIZE; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EmuConstants::TRIBUTE_BEGIN; index <= EmuConstants::TRIBUTE_END; ++index) { + for (int16 index = EQEmu::Constants::TRIBUTE_BEGIN; index <= EQEmu::Constants::TRIBUTE_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EmuConstants::BANK_BEGIN; index <= EmuConstants::BANK_END; ++index) { + for (int16 index = EQEmu::Constants::BANK_BEGIN; index <= EQEmu::Constants::BANK_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EmuConstants::SHARED_BANK_BEGIN; index <= EmuConstants::SHARED_BANK_END; ++index) { + for (int16 index = EQEmu::Constants::SHARED_BANK_BEGIN; index <= EQEmu::Constants::SHARED_BANK_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EmuConstants::TRADE_BEGIN; index <= EmuConstants::TRADE_END; ++index) { + for (int16 index = EQEmu::Constants::TRADE_BEGIN; index <= EQEmu::Constants::TRADE_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; @@ -3074,24 +3074,24 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool auto tsobject = GetTradeskillObject(); if (tsobject != nullptr) { - for (int16 index = MAIN_BEGIN; index < EmuConstants::MAP_WORLD_SIZE; ++index) { + for (int16 index = SLOT_BEGIN; index < EQEmu::Constants::TYPE_WORLD_SIZE; ++index) { auto inst = tsobject->GetItem(index); if (inst == nullptr) { continue; } - instmap[EmuConstants::WORLD_BEGIN + index] = inst; + instmap[EQEmu::Constants::WORLD_BEGIN + index] = inst; } } int limbo = 0; for (auto cursor_itr = m_inv.cursor_cbegin(); cursor_itr != m_inv.cursor_cend(); ++cursor_itr, ++limbo) { - // m_inv.cursor_begin() is referenced as MainCursor in MapPossessions above + // m_inv.cursor_begin() is referenced as SlotCursor in MapPossessions above if (cursor_itr == m_inv.cursor_cbegin()) continue; instmap[8000 + limbo] = *cursor_itr; } - if (m_inv[MainPowerSource]) - instmap[MainPowerSource] = m_inv[MainPowerSource]; + if (m_inv[SlotPowerSource]) + instmap[SlotPowerSource] = m_inv[SlotPowerSource]; // call InterrogateInventory_ for error check for (std::map::iterator instmap_itr = instmap.begin(); (instmap_itr != instmap.end()) && (!error); ++instmap_itr) { @@ -3149,7 +3149,7 @@ void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 hea } else { if (inst) { - for (int16 sub = SUB_BEGIN; (sub < EmuConstants::ITEM_CONTAINER_SIZE) && (!error); ++sub) { // treat any ItemInst as having the max internal slots available + for (int16 sub = SUB_BEGIN; (sub < EQEmu::Constants::ITEM_CONTAINER_SIZE) && (!error); ++sub) { // treat any ItemInst as having the max internal slots available if (inst->GetItem(sub)) InterrogateInventory_(true, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1); } @@ -3179,7 +3179,7 @@ void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 hea } if (inst) { - for (int16 sub = SUB_BEGIN; (sub < EmuConstants::ITEM_CONTAINER_SIZE); ++sub) { + for (int16 sub = SUB_BEGIN; (sub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++sub) { if (inst->GetItem(sub)) InterrogateInventory_(false, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1); } @@ -3194,11 +3194,11 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* // very basic error checking - can be elaborated upon if more in-depth testing is needed... if ( - (head >= EmuConstants::EQUIPMENT_BEGIN && head <= EmuConstants::EQUIPMENT_END) || - (head >= EmuConstants::TRIBUTE_BEGIN && head <= EmuConstants::TRIBUTE_END) || - (head >= EmuConstants::WORLD_BEGIN && head <= EmuConstants::WORLD_END) || + (head >= EQEmu::Constants::EQUIPMENT_BEGIN && head <= EQEmu::Constants::EQUIPMENT_END) || + (head >= EQEmu::Constants::TRIBUTE_BEGIN && head <= EQEmu::Constants::TRIBUTE_END) || + (head >= EQEmu::Constants::WORLD_BEGIN && head <= EQEmu::Constants::WORLD_END) || (head >= 8000 && head <= 8101) || - (head == MainPowerSource)) { + (head == SlotPowerSource)) { switch (depth) { case 0: // requirement: inst is extant @@ -3210,7 +3210,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* return true; if (!parent->IsType(ItemClassCommon)) return true; - if (index >= EmuConstants::ITEM_COMMON_SIZE) + if (index >= EQEmu::Constants::ITEM_COMMON_SIZE) return true; break; default: // requirement: none (something bad happened...) @@ -3218,11 +3218,11 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* } } else if ( - (head >= EmuConstants::GENERAL_BEGIN && head <= EmuConstants::GENERAL_END) || - (head == MainCursor) || - (head >= EmuConstants::BANK_BEGIN && head <= EmuConstants::BANK_END) || - (head >= EmuConstants::SHARED_BANK_BEGIN && head <= EmuConstants::SHARED_BANK_END) || - (head >= EmuConstants::TRADE_BEGIN && head <= EmuConstants::TRADE_END)) { + (head >= EQEmu::Constants::GENERAL_BEGIN && head <= EQEmu::Constants::GENERAL_END) || + (head == SlotCursor) || + (head >= EQEmu::Constants::BANK_BEGIN && head <= EQEmu::Constants::BANK_END) || + (head >= EQEmu::Constants::SHARED_BANK_BEGIN && head <= EQEmu::Constants::SHARED_BANK_END) || + (head >= EQEmu::Constants::TRADE_BEGIN && head <= EQEmu::Constants::TRADE_END)) { switch (depth) { case 0: // requirement: inst is extant @@ -3239,7 +3239,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* if (parent->IsType(ItemClassCommon)) { if (!(inst->GetItem()->AugType > 0)) return true; - if (index >= EmuConstants::ITEM_COMMON_SIZE) + if (index >= EQEmu::Constants::ITEM_COMMON_SIZE) return true; } break; @@ -3253,7 +3253,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* if (parent->IsType(ItemClassCommon)) { if (!(inst->GetItem()->AugType > 0)) return true; - if (index >= EmuConstants::ITEM_COMMON_SIZE) + if (index >= EQEmu::Constants::ITEM_COMMON_SIZE) return true; } break; diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 12766b57f..708d3cd82 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -272,7 +272,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge // it is an improvement. if (!item2->NoPet) { - for (int i = 0; !found && iSlots & slots) { if(equipment[i]) @@ -313,7 +313,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge // @merth: IDFile size has been increased, this needs to change uint16 emat; if(item2->Material <= 0 - || item2->Slots & (1 << MainPrimary | 1 << MainSecondary)) { + || item2->Slots & (1 << SlotPrimary | 1 << SlotSecondary)) { memset(newid, 0, sizeof(newid)); for(int i=0;i<7;i++){ if (!isalpha(item2->IDFile[i])){ @@ -327,7 +327,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge emat = item2->Material; } - if (foundslot == MainPrimary) { + if (foundslot == SlotPrimary) { if (item2->Proc.Effect != 0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); @@ -337,7 +337,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge if (item2->ItemType == ItemType2HBlunt || item2->ItemType == ItemType2HSlash || item2->ItemType == ItemType2HPiercing) SetTwoHanderEquipped(true); } - else if (foundslot == MainSecondary + else if (foundslot == SlotSecondary && (GetOwner() != nullptr || (CanThisClassDualWield() && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) && (item2->ItemType == ItemType1HSlash || item2->ItemType == ItemType1HBlunt || item2->ItemType == ItemTypeShield || item2->ItemType == ItemType1HPiercing)) @@ -349,25 +349,25 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge if (item2->Damage > 0) SendAddPlayerState(PlayerState::SecondaryWeaponEquipped); } - else if (foundslot == MainHead) { + else if (foundslot == SlotHead) { eslot = MaterialHead; } - else if (foundslot == MainChest) { + else if (foundslot == SlotChest) { eslot = MaterialChest; } - else if (foundslot == MainArms) { + else if (foundslot == SlotArms) { eslot = MaterialArms; } - else if (foundslot == MainWrist1 || foundslot == MainWrist2) { + else if (foundslot == SlotWrist1 || foundslot == SlotWrist2) { eslot = MaterialWrist; } - else if (foundslot == MainHands) { + else if (foundslot == SlotHands) { eslot = MaterialHands; } - else if (foundslot == MainLegs) { + else if (foundslot == SlotLegs) { eslot = MaterialLegs; } - else if (foundslot == MainFeet) { + else if (foundslot == SlotFeet) { eslot = MaterialFeet; } diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index a42efd592..4e8f1e8d0 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1757,47 +1757,47 @@ luabind::scope lua_register_slot() { return luabind::class_("Slot") .enum_("constants") [ - luabind::value("Charm", static_cast(MainCharm)), - luabind::value("Ear1", static_cast(MainEar1)), - luabind::value("Head", static_cast(MainHead)), - luabind::value("Face", static_cast(MainFace)), - luabind::value("Ear2", static_cast(MainEar2)), - luabind::value("Neck", static_cast(MainNeck)), - luabind::value("Shoulder", static_cast(MainShoulders)), // deprecated - luabind::value("Shoulders", static_cast(MainShoulders)), - luabind::value("Arms", static_cast(MainArms)), - luabind::value("Back", static_cast(MainBack)), - luabind::value("Bracer1", static_cast(MainWrist1)), // deprecated - luabind::value("Wrist1", static_cast(MainWrist1)), - luabind::value("Bracer2", static_cast(MainWrist2)), // deprecated - luabind::value("Wrist2", static_cast(MainWrist2)), - luabind::value("Range", static_cast(MainRange)), - luabind::value("Hands", static_cast(MainHands)), - luabind::value("Primary", static_cast(MainPrimary)), - luabind::value("Secondary", static_cast(MainSecondary)), - luabind::value("Ring1", static_cast(MainFinger1)), // deprecated - luabind::value("Finger1", static_cast(MainFinger1)), - luabind::value("Ring2", static_cast(MainFinger2)), // deprecated - luabind::value("Finger2", static_cast(MainFinger2)), - luabind::value("Chest", static_cast(MainChest)), - luabind::value("Legs", static_cast(MainLegs)), - luabind::value("Feet", static_cast(MainFeet)), - luabind::value("Waist", static_cast(MainWaist)), - luabind::value("PowerSource", static_cast(MainPowerSource)), - luabind::value("Ammo", static_cast(MainAmmo)), - luabind::value("General1", static_cast(MainGeneral1)), - luabind::value("General2", static_cast(MainGeneral2)), - luabind::value("General3", static_cast(MainGeneral3)), - luabind::value("General4", static_cast(MainGeneral4)), - luabind::value("General5", static_cast(MainGeneral5)), - luabind::value("General6", static_cast(MainGeneral6)), - luabind::value("General7", static_cast(MainGeneral7)), - luabind::value("General8", static_cast(MainGeneral8)), - luabind::value("Cursor", static_cast(MainCursor)), - luabind::value("PersonalBegin", static_cast(EmuConstants::GENERAL_BEGIN)), // deprecated - luabind::value("GeneralBegin", static_cast(EmuConstants::GENERAL_BEGIN)), - luabind::value("PersonalEnd", static_cast(EmuConstants::GENERAL_END)), // deprecated - luabind::value("GeneralEnd", static_cast(EmuConstants::GENERAL_END)), + luabind::value("Charm", static_cast(SlotCharm)), + luabind::value("Ear1", static_cast(SlotEar1)), + luabind::value("Head", static_cast(SlotHead)), + luabind::value("Face", static_cast(SlotFace)), + luabind::value("Ear2", static_cast(SlotEar2)), + luabind::value("Neck", static_cast(SlotNeck)), + luabind::value("Shoulder", static_cast(SlotShoulders)), // deprecated + luabind::value("Shoulders", static_cast(SlotShoulders)), + luabind::value("Arms", static_cast(SlotArms)), + luabind::value("Back", static_cast(SlotBack)), + luabind::value("Bracer1", static_cast(SlotWrist1)), // deprecated + luabind::value("Wrist1", static_cast(SlotWrist1)), + luabind::value("Bracer2", static_cast(SlotWrist2)), // deprecated + luabind::value("Wrist2", static_cast(SlotWrist2)), + luabind::value("Range", static_cast(SlotRange)), + luabind::value("Hands", static_cast(SlotHands)), + luabind::value("Primary", static_cast(SlotPrimary)), + luabind::value("Secondary", static_cast(SlotSecondary)), + luabind::value("Ring1", static_cast(SlotFinger1)), // deprecated + luabind::value("Finger1", static_cast(SlotFinger1)), + luabind::value("Ring2", static_cast(SlotFinger2)), // deprecated + luabind::value("Finger2", static_cast(SlotFinger2)), + luabind::value("Chest", static_cast(SlotChest)), + luabind::value("Legs", static_cast(SlotLegs)), + luabind::value("Feet", static_cast(SlotFeet)), + luabind::value("Waist", static_cast(SlotWaist)), + luabind::value("PowerSource", static_cast(SlotPowerSource)), + luabind::value("Ammo", static_cast(SlotAmmo)), + luabind::value("General1", static_cast(SlotGeneral1)), + luabind::value("General2", static_cast(SlotGeneral2)), + luabind::value("General3", static_cast(SlotGeneral3)), + luabind::value("General4", static_cast(SlotGeneral4)), + luabind::value("General5", static_cast(SlotGeneral5)), + luabind::value("General6", static_cast(SlotGeneral6)), + luabind::value("General7", static_cast(SlotGeneral7)), + luabind::value("General8", static_cast(SlotGeneral8)), + luabind::value("Cursor", static_cast(SlotCursor)), + luabind::value("PersonalBegin", static_cast(EQEmu::Constants::GENERAL_BEGIN)), // deprecated + luabind::value("GeneralBegin", static_cast(EQEmu::Constants::GENERAL_BEGIN)), + luabind::value("PersonalEnd", static_cast(EQEmu::Constants::GENERAL_END)), // deprecated + luabind::value("GeneralEnd", static_cast(EQEmu::Constants::GENERAL_END)), luabind::value("CursorEnd", 0xFFFE), // deprecated luabind::value("Tradeskill", static_cast(legacy::SLOT_TRADESKILL)), // deprecated luabind::value("Augment", static_cast(legacy::SLOT_AUGMENT)), // deprecated @@ -1819,9 +1819,9 @@ luabind::scope lua_register_material() { luabind::value("Feet", static_cast(MaterialFeet)), luabind::value("Primary", static_cast(MaterialPrimary)), luabind::value("Secondary", static_cast(MaterialSecondary)), - luabind::value("Max", static_cast(_MaterialCount)), // deprecated - luabind::value("Count", static_cast(_MaterialCount)), - luabind::value("Invalid", static_cast(_MaterialInvalid)) + luabind::value("Max", static_cast(MaterialCount)), // deprecated + luabind::value("Count", static_cast(MaterialCount)), + luabind::value("Invalid", static_cast(MaterialInvalid)) ]; } diff --git a/zone/merc.cpp b/zone/merc.cpp index 91a69f374..1379bc697 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -206,7 +206,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { unsigned int i; //should not include 21 (SLOT_AMMO) - for (i=0; irandom.Roll(flurrychance)) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); - Attack(GetTarget(), MainPrimary, false); - Attack(GetTarget(), MainPrimary, false); + Attack(GetTarget(), SlotPrimary, false); + Attack(GetTarget(), SlotPrimary, false); } } @@ -1590,7 +1590,7 @@ void Merc::AI_Process() { if (GetTarget() && ExtraAttackChanceBonus) { if(zone->random.Roll(ExtraAttackChanceBonus)) { - Attack(GetTarget(), MainPrimary, false); + Attack(GetTarget(), SlotPrimary, false); } } } @@ -1625,11 +1625,11 @@ void Merc::AI_Process() { // Max 78% of DW if (zone->random.Roll(DualWieldProbability)) { - Attack(GetTarget(), MainSecondary); // Single attack with offhand + Attack(GetTarget(), SlotSecondary); // Single attack with offhand if(CanThisClassDoubleAttack()) { if(GetTarget() && GetTarget()->GetHP() > -10) - Attack(GetTarget(), MainSecondary); // Single attack with offhand + Attack(GetTarget(), SlotSecondary); // Single attack with offhand } } } @@ -2544,7 +2544,7 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) { int16 focus_max_real = 0; //item focus - for (int x = 0; x < EmuConstants::EQUIPMENT_SIZE; ++x) + for (int x = 0; x < EQEmu::Constants::EQUIPMENT_SIZE; ++x) { TempItem = nullptr; if (equipment[x] == 0) @@ -5017,12 +5017,12 @@ void Merc::ScaleStats(int scalepercent, bool setmax) { void Merc::UpdateMercAppearance() { // Copied from Bot Code: uint32 itemID = NO_ITEM; - uint8 materialFromSlot = _MaterialInvalid; - for(int i = EmuConstants::EQUIPMENT_BEGIN; i <= EmuConstants::EQUIPMENT_END; ++i) { + uint8 materialFromSlot = MaterialInvalid; + for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; ++i) { itemID = equipment[i]; if(itemID != NO_ITEM) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); - if(materialFromSlot != _MaterialInvalid) + if(materialFromSlot != MaterialInvalid) this->SendWearChange(materialFromSlot); } } @@ -5036,8 +5036,8 @@ void Merc::UpdateEquipmentLight() m_Light.Type.Equipment = 0; m_Light.Level.Equipment = 0; - for (int index = MAIN_BEGIN; index < EmuConstants::EQUIPMENT_SIZE; ++index) { - if (index == MainAmmo) { continue; } + for (int index = SLOT_BEGIN; index < EQEmu::Constants::EQUIPMENT_SIZE; ++index) { + if (index == SlotAmmo) { continue; } auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } diff --git a/zone/merc.h b/zone/merc.h index 1e409e0ce..2a73bb8a3 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -62,7 +62,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return (GetGroup() ? true : false); } @@ -288,7 +288,7 @@ protected: std::map timers; uint16 skills[HIGHEST_SKILL+1]; - uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //this is an array of item IDs + uint32 equipment[EQEmu::Constants::EQUIPMENT_SIZE]; //this is an array of item IDs uint16 d_melee_texture1; //this is an item Material value uint16 d_melee_texture2; //this is an item Material value (offhand) uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation diff --git a/zone/mob.cpp b/zone/mob.cpp index c91ae404f..54781d095 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -73,7 +73,7 @@ Mob::Mob(const char* in_name, uint32 in_drakkin_heritage, uint32 in_drakkin_tattoo, uint32 in_drakkin_details, - uint32 in_armor_tint[_MaterialCount], + uint32 in_armor_tint[MaterialCount], uint8 in_aa_title, uint8 in_see_invis, // see through invis/ivu @@ -279,7 +279,7 @@ Mob::Mob(const char* in_name, RangedProcs[j].level_override = -1; } - for (i = 0; i < _MaterialCount; i++) + for (i = 0; i < MaterialCount; i++) { if (in_armor_tint) { @@ -2378,8 +2378,8 @@ bool Mob::CanThisClassDualWield(void) const { return(GetSkill(SkillDualWield) > 0); } else if(CastToClient()->HasSkill(SkillDualWield)) { - const ItemInst* pinst = CastToClient()->GetInv().GetItem(MainPrimary); - const ItemInst* sinst = CastToClient()->GetInv().GetItem(MainSecondary); + const ItemInst* pinst = CastToClient()->GetInv().GetItem(SlotPrimary); + const ItemInst* sinst = CastToClient()->GetInv().GetItem(SlotSecondary); // 2HS, 2HB, or 2HP if(pinst && pinst->IsWeapon()) { diff --git a/zone/mob.h b/zone/mob.h index 8cb899d0f..47d903fc2 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -108,7 +108,7 @@ public: uint32 in_drakkin_heritage, uint32 in_drakkin_tattoo, uint32 in_drakkin_details, - uint32 in_armor_tint[_MaterialCount], + uint32 in_armor_tint[MaterialCount], uint8 in_aa_title, uint8 in_see_invis, // see through invis uint8 in_see_invis_undead, // see through invis vs. undead @@ -148,7 +148,7 @@ public: virtual void ThrowingAttack(Mob* other) { } uint16 GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg); // 13 = Primary (default), 14 = secondary - virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) = 0; int MonkSpecialAttack(Mob* other, uint8 skill_used); virtual void TryBackstab(Mob *other,int ReuseTime = 10); @@ -378,7 +378,7 @@ public: inline uint8 GetDrakkinHeritage() const { return drakkin_heritage; } inline uint8 GetDrakkinTattoo() const { return drakkin_tattoo; } inline uint8 GetDrakkinDetails() const { return drakkin_details; } - inline uint32 GetArmorTint(uint8 i) const { return armor_tint[(i < _MaterialCount) ? i : 0]; } + inline uint32 GetArmorTint(uint8 i) const { return armor_tint[(i < MaterialCount) ? i : 0]; } inline uint8 GetClass() const { return class_; } inline uint8 GetLevel() const { return level; } inline uint8 GetOrigLevel() const { return orig_level; } @@ -563,7 +563,7 @@ public: bool lookForAftArc = true); //Procs - void TriggerDefensiveProcs(Mob *on, uint16 hand = MainPrimary, bool FromSkillProc=false, int damage = 0); + void TriggerDefensiveProcs(Mob *on, uint16 hand = SlotPrimary, bool FromSkillProc=false, int damage = 0); bool AddRangedProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); bool RemoveRangedProc(uint16 spell_id, bool bAll = false); bool HasRangedProcs() const; @@ -1139,16 +1139,16 @@ protected: bool focused; void CalcSpellBonuses(StatBonuses* newbon); virtual void CalcBonuses(); - void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand = MainCharm? + void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand = SlotCharm? bool PassLimitToSkill(uint16 spell_id, uint16 skill); bool PassLimitClass(uint32 Classes_, uint16 Class_); - void TryDefensiveProc(Mob *on, uint16 hand = MainPrimary); - void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = MainPrimary); - void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = MainPrimary); - void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = MainPrimary); + void TryDefensiveProc(Mob *on, uint16 hand = SlotPrimary); + void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = SlotPrimary); + void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = SlotPrimary); + void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = SlotPrimary); void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on, int level_override = -1); - virtual float GetProcChances(float ProcBonus, uint16 hand = MainPrimary); - virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = MainPrimary, Mob *on = nullptr); + virtual float GetProcChances(float ProcBonus, uint16 hand = SlotPrimary); + virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = SlotPrimary, Mob *on = nullptr); virtual float GetSpecialProcChances(uint16 hand); virtual float GetAssassinateProcChances(uint16 ReuseTime); virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm? @@ -1239,7 +1239,7 @@ protected: uint32 drakkin_heritage; uint32 drakkin_tattoo; uint32 drakkin_details; - uint32 armor_tint[_MaterialCount]; + uint32 armor_tint[MaterialCount]; uint8 aa_title; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 918c8afde..70f64b7a7 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -848,7 +848,7 @@ void Client::AI_Process() if (GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) { if (attack_timer.Check()) { // Should charmed clients not be procing? - DoAttackRounds(GetTarget(), MainPrimary); + DoAttackRounds(GetTarget(), SlotPrimary); } } @@ -856,7 +856,7 @@ void Client::AI_Process() if (attack_dw_timer.Check()) { if (CheckDualWield()) { // Should charmed clients not be procing? - DoAttackRounds(GetTarget(), MainSecondary); + DoAttackRounds(GetTarget(), SlotSecondary); } } } @@ -1107,7 +1107,7 @@ void Mob::AI_Process() { //try main hand first if(attack_timer.Check()) { DoMainHandAttackRounds(target); - TriggerDefensiveProcs(target, MainPrimary, false); + TriggerDefensiveProcs(target, SlotPrimary, false); bool specialed = false; // NPCs can only do one of these a round if (GetSpecialAbility(SPECATK_FLURRY)) { @@ -1953,7 +1953,7 @@ bool Mob::Flurry(ExtraAttackOptions *opts) int num_attacks = GetSpecialAbilityParam(SPECATK_FLURRY, 1); num_attacks = num_attacks > 0 ? num_attacks : RuleI(Combat, MaxFlurryHits); for (int i = 0; i < num_attacks; i++) - Attack(target, MainPrimary, false, false, false, opts); + Attack(target, SlotPrimary, false, false, false, opts); } return true; } diff --git a/zone/npc.cpp b/zone/npc.cpp index 103b5548e..25cdcfb86 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -488,7 +488,7 @@ void NPC::CheckMinMaxLevel(Mob *them) if(themlevel < (*cur)->min_level || themlevel > (*cur)->max_level) { material = Inventory::CalcMaterialFromSlot((*cur)->equip_slot); - if (material != _MaterialInvalid) + if (material != MaterialInvalid) SendWearChange(material); cur = itemlist.erase(cur); @@ -748,8 +748,8 @@ void NPC::UpdateEquipmentLight() m_Light.Type.Equipment = 0; m_Light.Level.Equipment = 0; - for (int index = MAIN_BEGIN; index < EmuConstants::EQUIPMENT_SIZE; ++index) { - if (index == MainAmmo) { continue; } + for (int index = SLOT_BEGIN; index < EQEmu::Constants::EQUIPMENT_SIZE; ++index) { + if (index == SlotAmmo) { continue; } auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } @@ -1372,7 +1372,7 @@ uint32 ZoneDatabase::NPCSpawnDB(uint8 command, const char* zone, uint32 zone_ver int32 NPC::GetEquipmentMaterial(uint8 material_slot) const { - if (material_slot >= _MaterialCount) + if (material_slot >= MaterialCount) return 0; int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); diff --git a/zone/npc.h b/zone/npc.h index fe658aab2..e788f414e 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -106,7 +106,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } @@ -495,7 +495,7 @@ protected: uint16 skills[HIGHEST_SKILL+1]; - uint32 equipment[EmuConstants::EQUIPMENT_SIZE]; //this is an array of item IDs + uint32 equipment[EQEmu::Constants::EQUIPMENT_SIZE]; //this is an array of item IDs uint32 herosforgemodel; //this is the Hero Forge Armor Model (i.e 63 or 84 or 203) uint16 d_melee_texture1; //this is an item Material value diff --git a/zone/object.cpp b/zone/object.cpp index d06a311c0..dd3c822c2 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -324,7 +324,7 @@ void Object::Delete(bool reset_state) } const ItemInst* Object::GetItem(uint8 index) { - if (index < EmuConstants::MAP_WORLD_SIZE) { + if (index < EQEmu::Constants::TYPE_WORLD_SIZE) { return m_inst->GetItem(index); } @@ -362,7 +362,7 @@ void Object::Close() { ItemInst* container = this->m_inst; if(container != nullptr) { - for (uint8 i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) + for (uint8 i = SUB_BEGIN; i < EQEmu::Constants::ITEM_CONTAINER_SIZE; i++) { ItemInst* inst = container->PopItem(i); if(inst != nullptr) @@ -503,11 +503,11 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) // Transfer item to client - sender->PutItemInInventory(MainCursor, *m_inst, false); - sender->SendItemPacket(MainCursor, m_inst, ItemPacketTrade); + sender->PutItemInInventory(SlotCursor, *m_inst, false); + sender->SendItemPacket(SlotCursor, m_inst, ItemPacketTrade); if(cursordelete) // delete the item if it's a duplicate lore. We have to do this because the client expects the item packet - sender->DeleteItemInInventory(MainCursor); + sender->DeleteItemInInventory(SlotCursor); if(!m_ground_spawn) safe_delete(m_inst); @@ -583,7 +583,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) EQApplicationPacket* outapp=new EQApplicationPacket(OP_ClientReady,0); sender->QueuePacket(outapp); safe_delete(outapp); - for (uint8 i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) { + for (uint8 i = SUB_BEGIN; i < EQEmu::Constants::ITEM_CONTAINER_SIZE; i++) { const ItemInst* inst = m_inst->GetItem(i); if (inst) { //sender->GetInv().PutItem(i+4000,inst); diff --git a/zone/pets.cpp b/zone/pets.cpp index fd777fab4..714f80b3c 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -417,12 +417,12 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, // the base items for the pet. These are always loaded // so that a rank 1 suspend minion does not kill things // like the special back items some focused pets may receive. - uint32 petinv[EmuConstants::EQUIPMENT_SIZE]; + uint32 petinv[EQEmu::Constants::EQUIPMENT_SIZE]; memset(petinv, 0, sizeof(petinv)); const Item_Struct *item = 0; if (database.GetBasePetItems(record.equipmentset, petinv)) { - for (int i = 0; iAddLootDrop(item, &npc->itemlist, 0, 1, 127, true, true); @@ -572,7 +572,7 @@ void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) { strn0cpy(name, GetName(), 64); //save their items, we only care about what they are actually wearing - memcpy(items, equipment, sizeof(uint32)*EmuConstants::EQUIPMENT_SIZE); + memcpy(items, equipment, sizeof(uint32) * EQEmu::Constants::EQUIPMENT_SIZE); //save their buffs. for (int i=0; i < GetPetMaxTotalSlots(); i++) { @@ -660,7 +660,7 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { } //restore their equipment... - for (i = 0; i < EmuConstants::EQUIPMENT_SIZE; i++) { + for (i = 0; i < EQEmu::Constants::EQUIPMENT_SIZE; i++) { if(items[i] == 0) continue; @@ -722,7 +722,7 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) { { slot = atoi(row[0]); - if (slot >= EmuConstants::EQUIPMENT_SIZE) + if (slot >= EQEmu::Constants::EQUIPMENT_SIZE) continue; if (items[slot] == 0) diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 32d215b9b..ce4c3e861 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2441,12 +2441,12 @@ int QuestManager::collectitems(uint32 item_id, bool remove) int quantity = 0; int slot_id; - for (slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; ++slot_id) + for (slot_id = EQEmu::Constants::GENERAL_BEGIN; slot_id <= EQEmu::Constants::GENERAL_END; ++slot_id) { quantity += collectitems_processSlot(slot_id, item_id, remove); } - for (slot_id = EmuConstants::GENERAL_BAGS_BEGIN; slot_id <= EmuConstants::GENERAL_BAGS_END; ++slot_id) + for (slot_id = EQEmu::Constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::Constants::GENERAL_BAGS_END; ++slot_id) { quantity += collectitems_processSlot(slot_id, item_id, remove); } diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 27a72f62c..7e424cf09 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -69,17 +69,17 @@ void Mob::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) case SkillFlyingKick: case SkillRoundKick: case SkillKick: - item_slot = MainFeet; + item_slot = SlotFeet; break; case SkillBash: - item_slot = MainSecondary; + item_slot = SlotSecondary; break; case SkillDragonPunch: case SkillEagleStrike: case SkillTigerClaw: - item_slot = MainHands; + item_slot = SlotHands; break; default: @@ -115,7 +115,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if(skill == SkillBash){ if(IsClient()){ - ItemInst *item = CastToClient()->GetInv().GetItem(MainSecondary); + ItemInst *item = CastToClient()->GetInv().GetItem(SlotSecondary); if(item) { if(item->GetItem()->ItemType == ItemTypeShield) @@ -133,14 +133,14 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, min_damage += min_damage * GetMeleeMinDamageMod_SE(skill) / 100; - int hand = MainPrimary; // Avoid checks hand for throwing/archery exclusion, primary should work for most + int hand = SlotPrimary; // Avoid checks hand for throwing/archery exclusion, primary should work for most if (skill == SkillThrowing || skill == SkillArchery) - hand = MainRange; + hand = SlotRange; if (who->AvoidDamage(this, max_damage, hand)) { if (max_damage == -3) DoRiposte(who); } else { - if (HitChance || who->CheckHitChance(this, skill, MainPrimary)) { + if (HitChance || who->CheckHitChance(this, skill, SlotPrimary)) { who->MeleeMitigation(this, max_damage, min_damage); CommonOutgoingHitSuccess(who, max_damage, skill); } else { @@ -198,7 +198,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { //These two are not subject to the combat ability timer, as they //allready do their checking in conjunction with the attack timer //throwing weapons - if(ca_atk->m_atk == MainRange) { + if(ca_atk->m_atk == SlotRange) { if (ca_atk->m_skill == SkillThrowing) { SetAttackTimer(); ThrowingAttack(GetTarget()); @@ -240,7 +240,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { int32 skill_reduction = this->GetSkillReuseTime(ca_atk->m_skill); - // not sure what the '100' indicates..if ->m_atk is not used as 'slot' reference, then change MainRange above back to '11' + // not sure what the '100' indicates..if ->m_atk is not used as 'slot' reference, then change SlotRange above back to '11' if ((ca_atk->m_atk == 100) && (ca_atk->m_skill == SkillBash)) { // SLAM - Bash without a shield equipped if (GetTarget() != this) { @@ -248,8 +248,8 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { DoAnim(animTailRake); int32 ht = 0; - if(GetWeaponDamage(GetTarget(), GetInv().GetItem(MainSecondary)) <= 0 && - GetWeaponDamage(GetTarget(), GetInv().GetItem(MainShoulders)) <= 0){ + if(GetWeaponDamage(GetTarget(), GetInv().GetItem(SlotSecondary)) <= 0 && + GetWeaponDamage(GetTarget(), GetInv().GetItem(SlotShoulders)) <= 0){ dmg = -5; } else{ @@ -325,7 +325,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { DoAnim(animKick); int32 ht = 0; - if(GetWeaponDamage(GetTarget(), GetInv().GetItem(MainFeet)) <= 0){ + if(GetWeaponDamage(GetTarget(), GetInv().GetItem(SlotFeet)) <= 0){ dmg = -5; } else{ @@ -408,7 +408,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) int32 min_dmg = 1; int reuse = 0; SkillUseTypes skill_type; //to avoid casting... even though it "would work" - uint8 itemslot = MainFeet; + uint8 itemslot = SlotFeet; switch(unchecked_type){ case SkillFlyingKick:{ @@ -423,7 +423,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) case SkillDragonPunch:{ skill_type = SkillDragonPunch; max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, DragonPunchBonus) / 100) + 26; - itemslot = MainHands; + itemslot = SlotHands; ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animTailRake); reuse = TailRakeReuseTime; @@ -433,7 +433,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) case SkillEagleStrike:{ skill_type = SkillEagleStrike; max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, EagleStrikeBonus) / 100) + 19; - itemslot = MainHands; + itemslot = SlotHands; ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animEagleStrike); reuse = EagleStrikeReuseTime; @@ -443,7 +443,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) case SkillTigerClaw:{ skill_type = SkillTigerClaw; max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, TigerClawBonus) / 100) + 12; - itemslot = MainHands; + itemslot = SlotHands; ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animTigerClaw); reuse = TigerClawReuseTime; @@ -512,7 +512,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { //make sure we have a proper weapon if we are a client. if(IsClient()) { - const ItemInst *wpn = CastToClient()->GetInv().GetItem(MainPrimary); + const ItemInst *wpn = CastToClient()->GetInv().GetItem(SlotPrimary); if(!wpn || (wpn->GetItem()->ItemType != ItemType1HPiercing)){ Message_StringID(13, BACKSTAB_WEAPON); return; @@ -573,7 +573,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10); } else { //We do a single regular attack if we attack from the front without chaotic stab - Attack(other, MainPrimary); + Attack(other, SlotPrimary); } } @@ -592,11 +592,11 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) if(IsClient()){ const ItemInst *wpn = nullptr; - wpn = CastToClient()->GetInv().GetItem(MainPrimary); + wpn = CastToClient()->GetInv().GetItem(SlotPrimary); if(wpn) { primaryweapondamage = GetWeaponDamage(other, wpn); backstab_dmg = wpn->GetItem()->BackstabDmg; - for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + for (int i = 0; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) { ItemInst *aug = wpn->GetAugment(i); if(aug) @@ -671,7 +671,7 @@ void Mob::RogueAssassinate(Mob* other) { //can you dodge, parry, etc.. an assassinate?? //if so, use DoSpecialAttackDamage(other, BACKSTAB, 32000); instead - if(GetWeaponDamage(other, IsClient()?CastToClient()->GetInv().GetItem(MainPrimary):(const ItemInst*)nullptr) > 0){ + if(GetWeaponDamage(other, IsClient()?CastToClient()->GetInv().GetItem(SlotPrimary):(const ItemInst*)nullptr) > 0){ other->Damage(this, 32000, SPELL_UNKNOWN, SkillBackstab); }else{ other->Damage(this, -5, SPELL_UNKNOWN, SkillBackstab); @@ -691,20 +691,20 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { //Message(0, "Error: Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime()); return; } - const ItemInst* RangeWeapon = m_inv[MainRange]; + const ItemInst* RangeWeapon = m_inv[SlotRange]; //locate ammo - int ammo_slot = MainAmmo; - const ItemInst* Ammo = m_inv[MainAmmo]; + int ammo_slot = SlotAmmo; + const ItemInst* Ammo = m_inv[SlotAmmo]; if (!RangeWeapon || !RangeWeapon->IsType(ItemClassCommon)) { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(MainRange), MainRange); - Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have no bow!", GetItemIDAt(MainRange)); + Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(SlotRange), SlotRange); + Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have no bow!", GetItemIDAt(SlotRange)); return; } if (!Ammo || !Ammo->IsType(ItemClassCommon)) { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ammo item (%d) in slot %d", GetItemIDAt(MainAmmo), MainAmmo); - Message(0, "Error: Ammo: GetItem(%i)==0, you have no ammo!", GetItemIDAt(MainAmmo)); + Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ammo item (%d) in slot %d", GetItemIDAt(SlotAmmo), SlotAmmo); + Message(0, "Error: Ammo: GetItem(%i)==0, you have no ammo!", GetItemIDAt(SlotAmmo)); return; } @@ -729,7 +729,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { //first look for quivers int r; bool found = false; - for(r = EmuConstants::GENERAL_BEGIN; r <= EmuConstants::GENERAL_END; r++) { + for(r = EQEmu::Constants::GENERAL_BEGIN; r <= EQEmu::Constants::GENERAL_END; r++) { const ItemInst *pi = m_inv[r]; if(pi == nullptr || !pi->IsType(ItemClassContainer)) continue; @@ -859,7 +859,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (IsClient()){ - _RangeWeapon = CastToClient()->m_inv[MainRange]; + _RangeWeapon = CastToClient()->m_inv[SlotRange]; if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id) RangeWeapon = _RangeWeapon; @@ -875,7 +875,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite else if (AmmoItem) SendItemAnimation(other, AmmoItem, SkillArchery); - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillArchery, MainPrimary, chance_mod))) { + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillArchery, SlotPrimary, chance_mod))) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ @@ -973,7 +973,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } if (!HeadShot) - other->AvoidDamage(this, TotalDmg, MainRange); + other->AvoidDamage(this, TotalDmg, SlotRange); other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0){ @@ -997,7 +997,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (ReuseTime) TrySkillProc(other, SkillArchery, ReuseTime); else - TrySkillProc(other, SkillArchery, 0, true, MainRange); + TrySkillProc(other, SkillArchery, 0, true, SlotRange); } } @@ -1006,20 +1006,20 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite //Weapon Proc if(RangeWeapon && other && !other->HasDied()) - TryWeaponProc(RangeWeapon, other, MainRange); + TryWeaponProc(RangeWeapon, other, SlotRange); //Ammo Proc if (ammo_lost) - TryWeaponProc(nullptr, ammo_lost, other, MainRange); + TryWeaponProc(nullptr, ammo_lost, other, SlotRange); else if(Ammo && other && !other->HasDied()) - TryWeaponProc(Ammo, other, MainRange); + TryWeaponProc(Ammo, other, SlotRange); //Skill Proc if (HasSkillProcs() && other && !other->HasDied()){ if (ReuseTime) TrySkillProc(other, SkillArchery, ReuseTime); else - TrySkillProc(other, SkillArchery, 0, false, MainRange); + TrySkillProc(other, SkillArchery, 0, false, SlotRange); } } @@ -1285,7 +1285,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha if (!chance_mod) chance_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2); - if (!other->CheckHitChance(this, skillInUse, MainRange, chance_mod)) + if (!other->CheckHitChance(this, skillInUse, SlotRange, chance_mod)) { other->Damage(this, 0, SPELL_UNKNOWN, skillInUse); } @@ -1306,7 +1306,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha TotalDmg += TotalDmg * damage_mod / 100; - other->AvoidDamage(this, TotalDmg, MainRange); + other->AvoidDamage(this, TotalDmg, SlotRange); other->MeleeMitigation(this, TotalDmg, MinDmg); if (TotalDmg > 0) @@ -1322,15 +1322,15 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillInUse); if (TotalDmg > 0 && HasSkillProcSuccess() && !other->HasDied()) - TrySkillProc(other, skillInUse, 0, true, MainRange); + TrySkillProc(other, skillInUse, 0, true, SlotRange); } //try proc on hits and misses if(other && !other->HasDied()) - TrySpellProc(nullptr, (const Item_Struct*)nullptr, other, MainRange); + TrySpellProc(nullptr, (const Item_Struct*)nullptr, other, SlotRange); if (HasSkillProcs() && other && !other->HasDied()) - TrySkillProc(other, skillInUse, 0, false, MainRange); + TrySkillProc(other, skillInUse, 0, false, SlotRange); } uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) { @@ -1372,19 +1372,19 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 return; } - int ammo_slot = MainRange; - const ItemInst* RangeWeapon = m_inv[MainRange]; + int ammo_slot = SlotRange; + const ItemInst* RangeWeapon = m_inv[SlotRange]; if (!RangeWeapon || !RangeWeapon->IsType(ItemClassCommon)) { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(MainRange), MainRange); - Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(MainRange)); + Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(SlotRange), SlotRange); + Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(SlotRange)); return; } const Item_Struct* item = RangeWeapon->GetItem(); if(item->ItemType != ItemTypeLargeThrowing && item->ItemType != ItemTypeSmallThrowing) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item %d is not a throwing weapon. type %d.", item->ItemType); - Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(MainRange)); + Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(SlotRange)); return; } @@ -1392,11 +1392,11 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 if(RangeWeapon->GetCharges() == 1) { //first check ammo - const ItemInst* AmmoItem = m_inv[MainAmmo]; + const ItemInst* AmmoItem = m_inv[SlotAmmo]; if(AmmoItem != nullptr && AmmoItem->GetID() == RangeWeapon->GetID()) { //more in the ammo slot, use it RangeWeapon = AmmoItem; - ammo_slot = MainAmmo; + ammo_slot = SlotAmmo; Log.Out(Logs::Detail, Logs::Combat, "Using ammo from ammo slot, stack at slot %d. %d in stack.", ammo_slot, RangeWeapon->GetCharges()); } else { //look through our inventory for more @@ -1493,7 +1493,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite else if (AmmoItem) SendItemAnimation(other, AmmoItem, SkillThrowing); - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillThrowing, MainPrimary, chance_mod))){ + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillThrowing, SlotPrimary, chance_mod))){ Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ TryProjectileAttack(other, AmmoItem, SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot, speed); @@ -1540,7 +1540,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite Log.Out(Logs::Detail, Logs::Combat, "Item DMG %d. Max Damage %d. Hit for damage %d", WDmg, MaxDmg, TotalDmg); if (!Assassinate_Dmg) - other->AvoidDamage(this, TotalDmg, MainRange); + other->AvoidDamage(this, TotalDmg, SlotRange); other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0) @@ -1559,7 +1559,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (ReuseTime) TrySkillProc(other, SkillThrowing, ReuseTime); else - TrySkillProc(other, SkillThrowing, 0, true, MainRange); + TrySkillProc(other, SkillThrowing, 0, true, SlotRange); } } @@ -1568,15 +1568,15 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite //Throwing item Proc if (ammo_lost) - TryWeaponProc(nullptr, ammo_lost, other, MainRange); + TryWeaponProc(nullptr, ammo_lost, other, SlotRange); else if(RangeWeapon && other && !other->HasDied()) - TryWeaponProc(RangeWeapon, other, MainRange); + TryWeaponProc(RangeWeapon, other, SlotRange); if (HasSkillProcs() && other && !other->HasDied()){ if (ReuseTime) TrySkillProc(other, SkillThrowing, ReuseTime); else - TrySkillProc(other, SkillThrowing, 0, false, MainRange); + TrySkillProc(other, SkillThrowing, 0, false, SlotRange); } } @@ -1976,7 +1976,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if (ca_target!=this) { DoAnim(animTailRake); - if(GetWeaponDamage(ca_target, GetInv().GetItem(MainSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(MainShoulders)) <= 0){ + if(GetWeaponDamage(ca_target, GetInv().GetItem(SlotSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(SlotShoulders)) <= 0){ dmg = -5; } else{ @@ -2040,7 +2040,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if(ca_target!=this){ DoAnim(animKick); - if(GetWeaponDamage(ca_target, GetInv().GetItem(MainFeet)) <= 0){ + if(GetWeaponDamage(ca_target, GetInv().GetItem(SlotFeet)) <= 0){ dmg = -5; } else{ @@ -2252,7 +2252,7 @@ uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { HeadShot_Level = itembonuses.HSLevel; if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){ - float ProcChance = GetSpecialProcChances(MainRange); + float ProcChance = GetSpecialProcChances(SlotRange); if(zone->random.Roll(ProcChance)) return HeadShot_Dmg; } @@ -2315,7 +2315,7 @@ uint32 Mob::TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 Reuse float ProcChance = 0.0f; if (skillInUse == SkillThrowing) - ProcChance = GetSpecialProcChances(MainRange); + ProcChance = GetSpecialProcChances(SlotRange); else ProcChance = GetAssassinateProcChances(ReuseTime); @@ -2366,7 +2366,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes int damage = 0; uint32 hate = 0; - int Hand = MainPrimary; + int Hand = SlotPrimary; if (hate == 0 && weapon_damage > 1) hate = weapon_damage; if(weapon_damage > 0){ @@ -2390,7 +2390,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if(skillinuse == SkillBash){ if(IsClient()){ - ItemInst *item = CastToClient()->GetInv().GetItem(MainSecondary); + ItemInst *item = CastToClient()->GetInv().GetItem(SlotSecondary); if(item){ if(item->GetItem()->ItemType == ItemTypeShield) { hate += item->GetItem()->AC; @@ -2412,7 +2412,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes else damage = zone->random.Int(min_hit, max_hit); - if (other->AvoidDamage(this, damage, CanRiposte ? MainRange : MainPrimary)) { // MainRange excludes ripo, primary doesn't have any extra behavior + if (other->AvoidDamage(this, damage, CanRiposte ? SlotRange : SlotPrimary)) { // SlotRange excludes ripo, primary doesn't have any extra behavior if (damage == -3) { DoRiposte(other); if (HasDied()) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index f0b93ca9c..445b97b39 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -616,7 +616,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Flesh To Bone"); #endif if(IsClient()){ - ItemInst* transI = CastToClient()->GetInv().GetItem(MainCursor); + ItemInst* transI = CastToClient()->GetInv().GetItem(SlotCursor); if(transI && transI->IsType(ItemClassCommon) && transI->IsStackable()){ uint32 fcharges = transI->GetCharges(); //Does it sound like meat... maybe should check if it looks like meat too... @@ -626,7 +626,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove strstr(transI->GetItem()->Name, "Flesh") || strstr(transI->GetItem()->Name, "parts") || strstr(transI->GetItem()->Name, "Parts")){ - CastToClient()->DeleteItemInInventory(MainCursor, fcharges, true); + CastToClient()->DeleteItemInInventory(SlotCursor, fcharges, true); CastToClient()->SummonItem(13073, fcharges); } else{ @@ -1157,7 +1157,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (SummonedItem) { c->PushItemOnCursor(*SummonedItem); - c->SendItemPacket(MainCursor, SummonedItem, ItemPacketSummonItem); + c->SendItemPacket(SlotCursor, SummonedItem, ItemPacketSummonItem); safe_delete(SummonedItem); } SummonedItem = database.CreateItem(spell.base[i], charges); @@ -1429,7 +1429,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } } - for(int x = EmuConstants::MATERIAL_BEGIN; x <= EmuConstants::MATERIAL_TINT_END; x++) + for (int x = EQEmu::Constants::MATERIAL_BEGIN; x <= EQEmu::Constants::MATERIAL_TINT_END; x++) SendWearChange(x); if (caster == this && @@ -1455,7 +1455,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove ); caster->SendAppearancePacket(AT_Size, static_cast(caster->GetTarget()->GetSize())); - for(int x = EmuConstants::MATERIAL_BEGIN; x <= EmuConstants::MATERIAL_TINT_END; x++) + for (int x = EQEmu::Constants::MATERIAL_BEGIN; x <= EQEmu::Constants::MATERIAL_TINT_END; x++) caster->SendWearChange(x); } } @@ -2216,7 +2216,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Rampage"); #endif if(caster) - entity_list.AEAttack(caster, 30, MainPrimary, 0, true); // on live wars dont get a duration ramp, its a one shot deal + entity_list.AEAttack(caster, 30, SlotPrimary, 0, true); // on live wars dont get a duration ramp, its a one shot deal break; } @@ -3014,7 +3014,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (SummonedItem) { Client *c=CastToClient(); c->PushItemOnCursor(*SummonedItem); - c->SendItemPacket(MainCursor, SummonedItem, ItemPacketSummonItem); + c->SendItemPacket(SlotCursor, SummonedItem, ItemPacketSummonItem); safe_delete(SummonedItem); } @@ -3809,7 +3809,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) else{ SendAppearancePacket(AT_Size, 6); } - for(int x = EmuConstants::MATERIAL_BEGIN; x <= EmuConstants::MATERIAL_TINT_END; x++){ + for (int x = EQEmu::Constants::MATERIAL_BEGIN; x <= EQEmu::Constants::MATERIAL_TINT_END; x++){ SendWearChange(x); } break; @@ -5126,7 +5126,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { const Item_Struct* TempItem = 0; - for(int x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::EQUIPMENT_END; x++) + for (int x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::EQUIPMENT_END; x++) { if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; @@ -5146,7 +5146,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { } } - for (int y = AUG_BEGIN; y < EmuConstants::ITEM_COMMON_SIZE; ++y) + for (int y = AUG_BEGIN; y < EQEmu::Constants::ITEM_COMMON_SIZE; ++y) { if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; @@ -5261,7 +5261,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) int16 focus_max_real = 0; //item focus - for(int x = EmuConstants::EQUIPMENT_BEGIN; x <= EmuConstants::EQUIPMENT_END; x++) + for (int x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::EQUIPMENT_END; x++) { TempItem = nullptr; ItemInst* ins = GetInv().GetItem(x); @@ -5295,7 +5295,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) } } - for (int y = AUG_BEGIN; y < EmuConstants::ITEM_COMMON_SIZE; ++y) + for (int y = AUG_BEGIN; y < EQEmu::Constants::ITEM_COMMON_SIZE; ++y) { ItemInst *aug = nullptr; aug = ins->GetAugment(y); @@ -5333,7 +5333,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) } //Tribute Focus - for(int x = EmuConstants::TRIBUTE_BEGIN; x <= EmuConstants::TRIBUTE_END; ++x) + for (int x = EQEmu::Constants::TRIBUTE_BEGIN; x <= EQEmu::Constants::TRIBUTE_END; ++x) { TempItem = nullptr; ItemInst* ins = GetInv().GetItem(x); @@ -5533,7 +5533,7 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { int16 focus_max_real = 0; //item focus - for(int i = 0; i < EmuConstants::EQUIPMENT_SIZE; i++){ + for (int i = 0; i < EQEmu::Constants::EQUIPMENT_SIZE; i++){ const Item_Struct *cur = database.GetItem(equipment[i]); if(!cur) diff --git a/zone/spells.cpp b/zone/spells.cpp index c386f81bb..7ed9e3012 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -291,7 +291,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, return(false); } } - if( itm && (itm->GetItem()->Click.Type == ET_EquipClick) && !(item_slot <= MainAmmo || item_slot == MainPowerSource) ){ + if( itm && (itm->GetItem()->Click.Type == ET_EquipClick) && !(item_slot <= SlotAmmo || item_slot == SlotPowerSource) ){ if (CastToClient()->GetClientVersion() < ClientVersion::SoF) { // They are attempting to cast a must equip clicky without having it equipped Log.Out(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click an equip-only effect on item %s (id: %d) without equiping it!", CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID); @@ -1206,7 +1206,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, if (inst == nullptr) break; - for (int r = AUG_BEGIN; r < EmuConstants::ITEM_COMMON_SIZE; r++) { + for (int r = AUG_BEGIN; r < EQEmu::Constants::ITEM_COMMON_SIZE; r++) { const ItemInst* aug_i = inst->GetAugment(r); if (!aug_i) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 2efed1e93..e6a4b25b5 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -69,7 +69,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme // Verify that no more than two items are in container to guarantee no inadvertant wipes. uint8 itemsFound = 0; - for (uint8 i = MAIN_BEGIN; i < EmuConstants::MAP_WORLD_SIZE; i++) + for (uint8 i = SLOT_BEGIN; i < EQEmu::Constants::TYPE_WORLD_SIZE; i++) { const ItemInst* inst = container->GetItem(i); if (inst) @@ -222,7 +222,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme else { // Delete items in our inventory container... - for (uint8 i = MAIN_BEGIN; i < EmuConstants::MAP_WORLD_SIZE; i++) + for (uint8 i = SLOT_BEGIN; i < EQEmu::Constants::TYPE_WORLD_SIZE; i++) { const ItemInst* inst = container->GetItem(i); if (inst) @@ -297,7 +297,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob const Item_Struct* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); - user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), MainCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2)); + user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), SlotCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2)); user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name); if (RuleB(Inventory, DeleteTransformationMold)) user->DeleteItemInInventory(in_combine->container_slot, 0, true); @@ -317,7 +317,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob const Item_Struct* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); - user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), MainCursor, 0, 0); + user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), SlotCursor, 0, 0); user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name); } else if (inst) { @@ -401,7 +401,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob safe_delete(outapp); database.DeleteWorldContainer(worldo->m_id, zone->GetZoneID()); } else{ - for (uint8 i = MAIN_BEGIN; i < EmuConstants::MAP_WORLD_SIZE; i++) { + for (uint8 i = SLOT_BEGIN; i < EQEmu::Constants::TYPE_WORLD_SIZE; i++) { const ItemInst* inst = container->GetItem(i); if (inst) { user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot,i),0,true); @@ -1227,7 +1227,7 @@ bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint3 for (auto row = results.begin(); row != results.end(); ++row) { int ccnt = 0; - for(int x = MAIN_BEGIN; x < EmuConstants::MAP_WORLD_SIZE; x++) { + for (int x = SLOT_BEGIN; x < EQEmu::Constants::TYPE_WORLD_SIZE; x++) { const ItemInst* inst = container->GetItem(x); if(!inst) continue; diff --git a/zone/trading.cpp b/zone/trading.cpp index a12b426e4..6cb081b2f 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -98,7 +98,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) { // Item always goes into trade bucket from cursor Client* client = owner->CastToClient(); - ItemInst* inst = client->GetInv().GetItem(MainCursor); + ItemInst* inst = client->GetInv().GetItem(SlotCursor); if (!inst) { client->Message(13, "Error: Could not find item on your cursor!"); @@ -131,7 +131,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) { if (_stack_size > 0) inst->SetCharges(_stack_size); else - client->DeleteItemInInventory(MainCursor); + client->DeleteItemInInventory(SlotCursor); SendItemData(inst2, trade_slot_id); } @@ -146,7 +146,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) { Log.Out(Logs::Detail, Logs::Trading, "%s added item '%s' to trade slot %i", owner->GetName(), inst->GetItem()->Name, trade_slot_id); client->PutItemInInventory(trade_slot_id, *inst); - client->DeleteItemInInventory(MainCursor); + client->DeleteItemInInventory(SlotCursor); } } @@ -171,13 +171,13 @@ void Trade::SendItemData(const ItemInst* inst, int16 dest_slot_id) Client* with = mob->CastToClient(); Client* trader = owner->CastToClient(); if (with && with->IsClient()) { - with->SendItemPacket(dest_slot_id - EmuConstants::TRADE_BEGIN, inst, ItemPacketTradeView); + with->SendItemPacket(dest_slot_id - EQEmu::Constants::TRADE_BEGIN, inst, ItemPacketTradeView); if (inst->GetItem()->ItemClass == 1) { - for (uint16 i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) { + for (uint16 i = SUB_BEGIN; i < EQEmu::Constants::ITEM_CONTAINER_SIZE; i++) { uint16 bagslot_id = Inventory::CalcSlotId(dest_slot_id, i); const ItemInst* bagitem = trader->GetInv().GetItem(bagslot_id); if (bagitem) { - with->SendItemPacket(bagslot_id - EmuConstants::TRADE_BEGIN, bagitem, ItemPacketTradeView); + with->SendItemPacket(bagslot_id - EQEmu::Constants::TRADE_BEGIN, bagitem, ItemPacketTradeView); } } } @@ -199,7 +199,7 @@ void Trade::LogTrade() uint8 item_count = 0; if (zone->tradevar != 0) { - for (uint16 i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_END; i++) { + for (uint16 i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_END; i++) { if (trader->GetInv().GetItem(i)) item_count++; } @@ -251,7 +251,7 @@ void Trade::LogTrade() if (item_count > 0) { strcat(logtext, "items {"); - for (uint16 i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_END; i++) { + for (uint16 i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_END; i++) { const ItemInst* inst = trader->GetInv().GetItem(i); if (!comma) @@ -267,7 +267,7 @@ void Trade::LogTrade() strcat(logtext, item_num); if (inst->IsType(ItemClassContainer)) { - for (uint8 j = SUB_BEGIN; j < EmuConstants::ITEM_CONTAINER_SIZE; j++) { + for (uint8 j = SUB_BEGIN; j < EQEmu::Constants::ITEM_CONTAINER_SIZE; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { strcat(logtext, ","); @@ -303,7 +303,7 @@ void Trade::DumpTrade() return; Client* trader = owner->CastToClient(); - for (uint16 i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_END; i++) { + for (uint16 i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_END; i++) { const ItemInst* inst = trader->GetInv().GetItem(i); if (inst) { @@ -312,7 +312,7 @@ void Trade::DumpTrade() i, ((inst->IsType(ItemClassContainer)) ? "True" : "False")); if (inst->IsType(ItemClassContainer)) { - for (uint8 j = SUB_BEGIN; j < EmuConstants::ITEM_CONTAINER_SIZE; j++) { + for (uint8 j = SUB_BEGIN; j < EQEmu::Constants::ITEM_CONTAINER_SIZE; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { Log.Out(Logs::Detail, Logs::Trading, "\tBagItem %i (Charges=%i, Slot=%i)", @@ -332,7 +332,7 @@ void Client::ResetTrade() { AddMoneyToPP(trade->cp, trade->sp, trade->gp, trade->pp, true); // step 1: process bags - for (int16 trade_slot = EmuConstants::TRADE_BEGIN; trade_slot <= EmuConstants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst && inst->IsType(ItemClassContainer)) { @@ -351,7 +351,7 @@ void Client::ResetTrade() { } // step 2a: process stackables - for (int16 trade_slot = EmuConstants::TRADE_BEGIN; trade_slot <= EmuConstants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { @@ -359,7 +359,7 @@ void Client::ResetTrade() { // there's no built-in safety check against an infinite loop..but, it should break on one of the conditional checks int16 free_slot = m_inv.FindFreeSlotForTradeItem(inst); - if ((free_slot == MainCursor) || (free_slot == INVALID_INDEX)) + if ((free_slot == SlotCursor) || (free_slot == INVALID_INDEX)) break; ItemInst* partial_inst = GetInv().GetItem(free_slot); @@ -398,11 +398,11 @@ void Client::ResetTrade() { // step 2b: adjust trade stack bias // (if any partial stacks exist before the final stack, FindFreeSlotForTradeItem() will return that slot in step 3 and an overwrite will occur) - for (int16 trade_slot = EmuConstants::TRADE_END; trade_slot >= EmuConstants::TRADE_BEGIN; --trade_slot) { + for (int16 trade_slot = EQEmu::Constants::TRADE_END; trade_slot >= EQEmu::Constants::TRADE_BEGIN; --trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { - for (int16 bias_slot = EmuConstants::TRADE_BEGIN; bias_slot <= EmuConstants::TRADE_END; ++bias_slot) { + for (int16 bias_slot = EQEmu::Constants::TRADE_BEGIN; bias_slot <= EQEmu::Constants::TRADE_END; ++bias_slot) { if (bias_slot >= trade_slot) break; @@ -432,7 +432,7 @@ void Client::ResetTrade() { } // step 3: process everything else - for (int16 trade_slot = EmuConstants::TRADE_BEGIN; trade_slot <= EmuConstants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst) { @@ -487,7 +487,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } // step 1: process bags - for (int16 trade_slot = EmuConstants::TRADE_BEGIN; trade_slot <= EmuConstants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst && inst->IsType(ItemClassContainer)) { @@ -523,7 +523,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st qs_audit->char1_count += detail->charges; //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { - for (uint8 sub_slot = SUB_BEGIN; (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items + for (uint8 sub_slot = SUB_BEGIN; (sub_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items const ItemInst* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { @@ -571,7 +571,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } // step 2a: process stackables - for (int16 trade_slot = EmuConstants::TRADE_BEGIN; trade_slot <= EmuConstants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { @@ -579,7 +579,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // there's no built-in safety check against an infinite loop..but, it should break on one of the conditional checks int16 partial_slot = other->GetInv().FindFreeSlotForTradeItem(inst); - if ((partial_slot == MainCursor) || (partial_slot == INVALID_INDEX)) + if ((partial_slot == SlotCursor) || (partial_slot == INVALID_INDEX)) break; ItemInst* partial_inst = other->GetInv().GetItem(partial_slot); @@ -653,11 +653,11 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // step 2b: adjust trade stack bias // (if any partial stacks exist before the final stack, FindFreeSlotForTradeItem() will return that slot in step 3 and an overwrite will occur) - for (int16 trade_slot = EmuConstants::TRADE_END; trade_slot >= EmuConstants::TRADE_BEGIN; --trade_slot) { + for (int16 trade_slot = EQEmu::Constants::TRADE_END; trade_slot >= EQEmu::Constants::TRADE_BEGIN; --trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { - for (int16 bias_slot = EmuConstants::TRADE_BEGIN; bias_slot <= EmuConstants::TRADE_END; ++bias_slot) { + for (int16 bias_slot = EQEmu::Constants::TRADE_BEGIN; bias_slot <= EQEmu::Constants::TRADE_END; ++bias_slot) { if (bias_slot >= trade_slot) break; @@ -706,7 +706,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } // step 3: process everything else - for (int16 trade_slot = EmuConstants::TRADE_BEGIN; trade_slot <= EmuConstants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst) { @@ -743,7 +743,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // 'step 3' should never really see containers..but, just in case... //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { - for (uint8 sub_slot = SUB_BEGIN; (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items + for (uint8 sub_slot = SUB_BEGIN; (sub_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items const ItemInst* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { @@ -820,7 +820,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } if(qs_log) { // This can be incorporated below when revisions are made - for (int16 trade_slot = EmuConstants::TRADE_BEGIN; trade_slot <= EmuConstants::TRADE_NPC_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_NPC_END; ++trade_slot) { const ItemInst* trade_inst = m_inv[trade_slot]; if(trade_inst) { @@ -875,7 +875,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st std::vector item_list; std::list items; - for(int i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_NPC_END; ++i) { + for (int i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_NPC_END; ++i) { ItemInst *inst = m_inv.GetItem(i); if(inst) { items.push_back(inst); @@ -948,8 +948,8 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } ItemInst *insts[4] = { 0 }; - for(int i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_NPC_END; ++i) { - insts[i - EmuConstants::TRADE_BEGIN] = m_inv.PopItem(i); + for (int i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_NPC_END; ++i) { + insts[i - EQEmu::Constants::TRADE_BEGIN] = m_inv.PopItem(i); database.SaveInventory(CharacterID(), nullptr, i); } @@ -968,7 +968,7 @@ bool Client::CheckTradeLoreConflict(Client* other) if (!other) return true; // Move each trade slot into free inventory slot - for (int16 i = EmuConstants::TRADE_BEGIN; i <= EmuConstants::TRADE_END; i++){ + for (int16 i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_END; i++){ const ItemInst* inst = m_inv[i]; if (inst && inst->GetItem()) { @@ -977,7 +977,7 @@ bool Client::CheckTradeLoreConflict(Client* other) } } - for (int16 i = EmuConstants::TRADE_BAGS_BEGIN; i <= EmuConstants::TRADE_BAGS_END; i++){ + for (int16 i = EQEmu::Constants::TRADE_BAGS_BEGIN; i <= EQEmu::Constants::TRADE_BAGS_END; i++){ const ItemInst* inst = m_inv[i]; if (inst && inst->GetItem()) { @@ -1232,10 +1232,10 @@ uint32 Client::FindTraderItemSerialNumber(int32 ItemID) { ItemInst* item = nullptr; uint16 SlotID = 0; - for (int i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++){ + for (int i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++){ item = this->GetInv().GetItem(i); if (item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; x++) { + for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1255,10 +1255,10 @@ ItemInst* Client::FindTraderItemBySerialNumber(int32 SerialNumber){ ItemInst* item = nullptr; uint16 SlotID = 0; - for(int i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++){ + for (int i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++){ item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for(int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; x++) { + for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1286,10 +1286,10 @@ GetItems_Struct* Client::GetTraderItems(){ uint8 ndx = 0; - for(int i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) { + for (int i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for(int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; x++) { + for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; x++) { SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1310,10 +1310,10 @@ uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){ const ItemInst* item= nullptr; uint16 SlotID = 0; - for(int i = EmuConstants::GENERAL_BEGIN; i <= EmuConstants::GENERAL_END; i++) { + for (int i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for(int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; x++){ + for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; x++){ SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); diff --git a/zone/tribute.cpp b/zone/tribute.cpp index df01f843e..084712f9a 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -66,7 +66,7 @@ void Client::ToggleTribute(bool enabled) { int r; uint32 cost = 0; uint32 level = GetLevel(); - for(r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { uint32 tid = m_pp.tributes[r].tribute; if(tid == TRIBUTE_NONE) continue; @@ -119,7 +119,7 @@ void Client::DoTributeUpdate() { tis->tribute_master_id = tribute_master_id; //Dont know what this is for int r; - for(r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { if(m_pp.tributes[r].tribute != TRIBUTE_NONE) { tis->tributes[r] = m_pp.tributes[r].tribute; tis->tiers[r] = m_pp.tributes[r].tier; @@ -134,24 +134,24 @@ void Client::DoTributeUpdate() { if(m_pp.tribute_active) { //send and equip tribute items... - for(r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { uint32 tid = m_pp.tributes[r].tribute; if(tid == TRIBUTE_NONE) { - if(m_inv[EmuConstants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EmuConstants::TRIBUTE_BEGIN + r, 0, false); + if (m_inv[EQEmu::Constants::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::Constants::TRIBUTE_BEGIN + r, 0, false); continue; } if(tribute_list.count(tid) != 1) { - if (m_inv[EmuConstants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EmuConstants::TRIBUTE_BEGIN + r, 0, false); + if (m_inv[EQEmu::Constants::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::Constants::TRIBUTE_BEGIN + r, 0, false); continue; } //sanity check if(m_pp.tributes[r].tier >= MAX_TRIBUTE_TIERS) { - if (m_inv[EmuConstants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EmuConstants::TRIBUTE_BEGIN + r, 0, false); + if (m_inv[EQEmu::Constants::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::Constants::TRIBUTE_BEGIN + r, 0, false); m_pp.tributes[r].tier = 0; continue; } @@ -165,15 +165,15 @@ void Client::DoTributeUpdate() { if(inst == nullptr) continue; - PutItemInInventory(EmuConstants::TRIBUTE_BEGIN + r, *inst, false); - SendItemPacket(EmuConstants::TRIBUTE_BEGIN + r, inst, ItemPacketTributeItem); + PutItemInInventory(EQEmu::Constants::TRIBUTE_BEGIN + r, *inst, false); + SendItemPacket(EQEmu::Constants::TRIBUTE_BEGIN + r, inst, ItemPacketTributeItem); safe_delete(inst); } } else { //unequip tribute items... - for(r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) { - if (m_inv[EmuConstants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EmuConstants::TRIBUTE_BEGIN + r, 0, false); + for (r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { + if (m_inv[EQEmu::Constants::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::Constants::TRIBUTE_BEGIN + r, 0, false); } } CalcBonuses(); @@ -192,7 +192,7 @@ void Client::SendTributeTimer() { void Client::ChangeTributeSettings(TributeInfo_Struct *t) { int r; - for(r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { m_pp.tributes[r].tribute = TRIBUTE_NONE; diff --git a/zone/tune.cpp b/zone/tune.cpp index 4153d5b84..30692b5bb 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -582,13 +582,13 @@ int32 Client::Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 mi int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) { - int Hand = MainPrimary; + int Hand = SlotPrimary; if (!other) return 0; ItemInst* weapon; - weapon = GetInv().GetItem(MainPrimary); + weapon = GetInv().GetItem(SlotPrimary); if(weapon != nullptr) { if (!weapon->IsWeapon()) { @@ -628,7 +628,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) int ucDamageBonus = 0; - if( Hand == MainPrimary && GetLevel() >= 28 && IsWarriorClass() ) + if( Hand == SlotPrimary && GetLevel() >= 28 && IsWarriorClass() ) { ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); @@ -662,24 +662,24 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch if (attacker->IsClient()) {//Will check first equiped weapon for skill. Ie. remove wepaons to assess bow. ItemInst* weapon; - weapon = attacker->CastToClient()->GetInv().GetItem(MainPrimary); + weapon = attacker->CastToClient()->GetInv().GetItem(SlotPrimary); if(weapon && weapon->IsWeapon()){ - attacker->CastToClient()->AttackAnimation(skillinuse, MainPrimary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, SlotPrimary, weapon); } else { - weapon = attacker->CastToClient()->GetInv().GetItem(MainSecondary); + weapon = attacker->CastToClient()->GetInv().GetItem(SlotSecondary); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, MainSecondary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, SlotSecondary, weapon); else { - weapon = attacker->CastToClient()->GetInv().GetItem(MainRange); + weapon = attacker->CastToClient()->GetInv().GetItem(SlotRange); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, MainRange, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, SlotRange, weapon); } } } - tmp_hit_chance = Tune_CheckHitChance(defender,attacker, skillinuse, MainPrimary,0,0,0, avoid_override); + tmp_hit_chance = Tune_CheckHitChance(defender,attacker, skillinuse, SlotPrimary,0,0,0, avoid_override); Message(0, "#Tune - Begin Parse [Interval %i Max Loop Iterations %i]", interval, max_loop); @@ -691,7 +691,7 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch for (int j=0; j < max_loop; j++) { - tmp_hit_chance =Tune_CheckHitChance(defender,attacker, skillinuse, MainPrimary,0,false,0, avoid_override, add_acc); + tmp_hit_chance =Tune_CheckHitChance(defender,attacker, skillinuse, SlotPrimary,0,false,0, avoid_override, add_acc); if (Msg >= 3) Message(15, "#Tune - Processing... [%i] [ACCURACY %i] Hit Chance %.2f ",j,add_acc,tmp_hit_chance); @@ -706,7 +706,7 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch if (end){ - Tune_CheckHitChance(defender,attacker, skillinuse, MainPrimary,0,Msg,0,avoid_override);//Display Stat Report + Tune_CheckHitChance(defender,attacker, skillinuse, SlotPrimary,0,Msg,0,avoid_override);//Display Stat Report Message(0, " "); @@ -742,24 +742,24 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ if (attacker->IsClient()) {//Will check first equiped weapon for skill. Ie. remove wepaons to assess bow. ItemInst* weapon; - weapon = attacker->CastToClient()->GetInv().GetItem(MainPrimary); + weapon = attacker->CastToClient()->GetInv().GetItem(SlotPrimary); if(weapon && weapon->IsWeapon()){ - attacker->CastToClient()->AttackAnimation(skillinuse, MainPrimary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, SlotPrimary, weapon); } else { - weapon = attacker->CastToClient()->GetInv().GetItem(MainSecondary); + weapon = attacker->CastToClient()->GetInv().GetItem(SlotSecondary); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, MainSecondary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, SlotSecondary, weapon); else { - weapon = attacker->CastToClient()->GetInv().GetItem(MainRange); + weapon = attacker->CastToClient()->GetInv().GetItem(SlotRange); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, MainRange, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, SlotRange, weapon); } } } - tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, MainPrimary,0,0,acc_override, 0); + tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, SlotPrimary,0,0,acc_override, 0); Message(0, "#Tune - Begin Parse [Interval %i Max Loop Iterations %i]", interval, max_loop); Message(0, "#Tune - Processing... Find Avoidance for hit chance on defender of (%.0f) pct from attacker. [Current Hit Chance %.2f]", hit_chance, tmp_hit_chance); @@ -769,7 +769,7 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ for (int j=0; j < max_loop; j++) { - tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, MainPrimary, 0,0, acc_override, 0,0,add_avoid); + tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, SlotPrimary, 0,0, acc_override, 0,0,add_avoid); if (Msg >= 3) Message(0, "#Tune - Processing... [%i] [AVOIDANCE %i] Hit Chance %.2f ",j,add_avoid,tmp_hit_chance); @@ -784,7 +784,7 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ if (end){ - Tune_CheckHitChance(defender,attacker, skillinuse, MainPrimary,0,Msg,acc_override, 0);//Display Stat Report + Tune_CheckHitChance(defender,attacker, skillinuse, SlotPrimary,0,Msg,acc_override, 0);//Display Stat Report Message(0, " "); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 5347b2792..0fc194c1e 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -487,7 +487,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, ItemInst* container) uint8 index = (uint8)atoi(row[0]); uint32 item_id = (uint32)atoi(row[1]); int8 charges = (int8)atoi(row[2]); - uint32 aug[EmuConstants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::Constants::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoi(row[3]); aug[1] = (uint32)atoi(row[4]); aug[2] = (uint32)atoi(row[5]); @@ -497,7 +497,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, ItemInst* container) ItemInst* inst = database.CreateItem(item_id, charges); if (inst && inst->GetItem()->ItemClass == ItemClassCommon) { - for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) if (aug[i]) inst->PutAugment(&database, i, aug[i]); // Put item inside world container @@ -520,17 +520,17 @@ void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const It DeleteWorldContainer(parent_id,zone_id); // Save all 10 items, if they exist - for (uint8 index = SUB_BEGIN; index < EmuConstants::ITEM_CONTAINER_SIZE; index++) { + for (uint8 index = SUB_BEGIN; index < EQEmu::Constants::ITEM_CONTAINER_SIZE; index++) { ItemInst* inst = container->GetItem(index); if (!inst) continue; uint32 item_id = inst->GetItem()->ID; - uint32 augslot[EmuConstants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; + uint32 augslot[EQEmu::Constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; if (inst->IsType(ItemClassCommon)) { - for(int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { ItemInst *auginst=inst->GetAugment(i); augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } @@ -1181,11 +1181,11 @@ bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp) { std::string query = StringFormat("SELECT `bandolier_id`, `bandolier_slot`, `item_id`, `icon`, `bandolier_name` FROM `character_bandolier` WHERE `id` = %u LIMIT %u", - character_id, EmuConstants::BANDOLIERS_SIZE); + character_id, EQEmu::Constants::BANDOLIERS_SIZE); auto results = database.QueryDatabase(query); int i = 0; int r = 0; int si = 0; - for (i = 0; i < EmuConstants::BANDOLIERS_SIZE; i++) { + for (i = 0; i < EQEmu::Constants::BANDOLIERS_SIZE; i++) { pp->bandoliers[i].Name[0] = '\0'; - for (int si = 0; si < EmuConstants::BANDOLIER_ITEM_COUNT; si++) { + for (int si = 0; si < EQEmu::Constants::BANDOLIER_ITEM_COUNT; si++) { pp->bandoliers[i].Items[si].ID = 0; pp->bandoliers[i].Items[si].Icon = 0; pp->bandoliers[i].Items[si].Name[0] = '\0'; @@ -1219,7 +1219,7 @@ bool ZoneDatabase::LoadCharacterTribute(uint32 character_id, PlayerProfile_Struc std::string query = StringFormat("SELECT `tier`, `tribute` FROM `character_tribute` WHERE `id` = %u", character_id); auto results = database.QueryDatabase(query); int i = 0; - for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + for (i = 0; i < EQEmu::Constants::TRIBUTE_SIZE; i++){ pp->tributes[i].tribute = 0xFFFFFFFF; pp->tributes[i].tier = 0; } @@ -1238,10 +1238,10 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc { std::string query = StringFormat("SELECT `potion_id`, `item_id`, `icon` FROM `character_potionbelt` WHERE `id` = %u LIMIT %u", - character_id, EmuConstants::POTION_BELT_ITEM_COUNT); + character_id, EQEmu::Constants::POTION_BELT_ITEM_COUNT); auto results = database.QueryDatabase(query); int i = 0; - for (i = 0; i < EmuConstants::POTION_BELT_ITEM_COUNT; i++) { + for (i = 0; i < EQEmu::Constants::POTION_BELT_ITEM_COUNT; i++) { pp->potionbelt.Items[i].Icon = 0; pp->potionbelt.Items[i].ID = 0; pp->potionbelt.Items[i].Name[0] = '\0'; @@ -1339,7 +1339,7 @@ bool ZoneDatabase::SaveCharacterTribute(uint32 character_id, PlayerProfile_Struc std::string query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query); /* Save Tributes only if we have values... */ - for (int i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + for (int i = 0; i < EQEmu::Constants::TRIBUTE_SIZE; i++){ if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != TRIBUTE_NONE){ std::string query = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); QueryDatabase(query); @@ -2092,7 +2092,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load else { auto armorTint_row = armortint_results.begin(); - for (int index = EmuConstants::MATERIAL_BEGIN; index <= EmuConstants::MATERIAL_END; index++) { + for (int index = EQEmu::Constants::MATERIAL_BEGIN; index <= EQEmu::Constants::MATERIAL_END; index++) { temp_npctype_data->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; temp_npctype_data->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; temp_npctype_data->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); @@ -2102,7 +2102,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load } // Try loading npc_types tint fields if armor tint is 0 or query failed to get results if (armor_tint_id == 0) { - for (int index = MaterialChest; index < _MaterialCount; index++) { + for (int index = MaterialChest; index < MaterialCount; index++) { temp_npctype_data->armor_tint[index] = temp_npctype_data->armor_tint[0]; } } @@ -2307,7 +2307,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; if (armor_tint_id == 0) - for (int index = MaterialChest; index <= EmuConstants::MATERIAL_END; index++) + for (int index = MaterialChest; index <= EQEmu::Constants::MATERIAL_END; index++) tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0]; else if (tmpNPCType->armor_tint[0] == 0) { std::string armorTint_query = StringFormat("SELECT red1h, grn1h, blu1h, " @@ -2327,7 +2327,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client else { auto armorTint_row = results.begin(); - for (int index = EmuConstants::MATERIAL_BEGIN; index <= EmuConstants::MATERIAL_END; index++) { + for (int index = EQEmu::Constants::MATERIAL_BEGIN; index <= EQEmu::Constants::MATERIAL_END; index++) { tmpNPCType->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); @@ -2684,7 +2684,7 @@ void ZoneDatabase::LoadMercEquipment(Merc *merc) { int itemCount = 0; for(auto row = results.begin(); row != results.end(); ++row) { - if (itemCount == EmuConstants::EQUIPMENT_SIZE) + if (itemCount == EQEmu::Constants::EQUIPMENT_SIZE) break; if(atoi(row[0]) == 0) @@ -3199,7 +3199,7 @@ void ZoneDatabase::SavePetInfo(Client *client) query.clear(); // pet inventory! - for (int index = EmuConstants::EQUIPMENT_BEGIN; index <= EmuConstants::EQUIPMENT_END; index++) { + for (int index = EQEmu::Constants::EQUIPMENT_BEGIN; index <= EQEmu::Constants::EQUIPMENT_END; index++) { if (!petinfo->Items[index]) continue; @@ -3331,7 +3331,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) continue; int slot = atoi(row[1]); - if (slot < EmuConstants::EQUIPMENT_BEGIN || slot > EmuConstants::EQUIPMENT_END) + if (slot < EQEmu::Constants::EQUIPMENT_BEGIN || slot > EQEmu::Constants::EQUIPMENT_END) continue; pi->Items[slot] = atoul(row[2]); diff --git a/zone/zonedb.h b/zone/zonedb.h index 3c5ca7b00..250c7106d 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -126,7 +126,7 @@ struct PetInfo { uint32 Mana; float size; SpellBuff_Struct Buffs[BUFF_COUNT]; - uint32 Items[EmuConstants::EQUIPMENT_SIZE]; + uint32 Items[EQEmu::Constants::EQUIPMENT_SIZE]; char Name[64]; }; diff --git a/zone/zonedump.h b/zone/zonedump.h index e69692339..cc8fe2010 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -86,7 +86,7 @@ struct NPCType uint32 drakkin_heritage; uint32 drakkin_tattoo; uint32 drakkin_details; - uint32 armor_tint[_MaterialCount]; + uint32 armor_tint[MaterialCount]; uint32 min_dmg; uint32 max_dmg; int16 attack_count; From fb23d961c17ed6760677848742f8191c89a15ed9 Mon Sep 17 00:00:00 2001 From: ngdeao Date: Mon, 28 Mar 2016 19:11:24 -0600 Subject: [PATCH 035/693] Changed where queued packets are sent while zoning. Moved where zoneinpacket_timer is started to assist in not dropping needed packets. Added better netcode support for handling out of order acks, to preclude excessive resending of same packets. Changed how timeout checks are performing on individual packets, for re-sends, so they do not happen more often than the client can respond. Improved how the data rate limit for throttling packets for compressed stream, so the size reduction in packets are accounted for better. --- common/eq_packet.h | 3 +- common/eq_stream.cpp | 183 +++++++++++++++++++--------------------- common/eq_stream.h | 3 +- zone/bot.cpp | 1 + zone/client.cpp | 3 +- zone/client_packet.cpp | 6 +- zone/client_process.cpp | 2 +- zone/entity.cpp | 6 +- zone/mob.cpp | 1 + zone/mob.h | 3 + 10 files changed, 105 insertions(+), 106 deletions(-) diff --git a/common/eq_packet.h b/common/eq_packet.h index ed90d132a..94c8a1e10 100644 --- a/common/eq_packet.h +++ b/common/eq_packet.h @@ -62,7 +62,7 @@ class EQProtocolPacket : public BasePacket { friend class EQStream; friend class EQStreamPair; public: - EQProtocolPacket(uint16 op, const unsigned char *buf, uint32 len) : BasePacket(buf,len), opcode(op) { acked = false; } + EQProtocolPacket(uint16 op, const unsigned char *buf, uint32 len) : BasePacket(buf, len), opcode(op) { acked = false; sent_time = 0; } // EQProtocolPacket(const unsigned char *buf, uint32 len); bool combine(const EQProtocolPacket *rhs); uint32 serialize (unsigned char *dest) const; @@ -70,6 +70,7 @@ public: EQRawApplicationPacket *MakeAppPacket() const; bool acked; + uint32 sent_time; virtual void build_raw_header_dump(char *buffer, uint16 seq=0xffff) const; virtual void build_header_dump(char *buffer) const; diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index 3438f533c..d132fb872 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -75,7 +75,7 @@ void EQStream::init(bool resetSession) { sent_packet_count = 0; received_packet_count = 0; SequencedBase = 0; - NextSequencedSend = 0; + AverageDelta = 500; if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { retransmittimer = Timer::GetCurrentTime(); @@ -86,10 +86,6 @@ void EQStream::init(bool resetSession) { if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { Log.Out(Logs::Detail, Logs::Netcode, _L "init Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } - - if(NextSequencedSend > SequencedQueue.size()) { - Log.Out(Logs::Detail, Logs::Netcode, _L "init Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); - } } EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p) @@ -420,36 +416,33 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } - if(NextSequencedSend > SequencedQueue.size()) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-OOA Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); - } //if the packet they got out of order is between our last acked packet and the last sent packet, then its valid. if (CompareSequence(SequencedBase,seq) != SeqPast && CompareSequence(NextOutSeq,seq) == SeqPast) { Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck for sequence %d, starting retransmit at the start of our unacked buffer (seq %d, was %d)." __L, - seq, SequencedBase, SequencedBase+NextSequencedSend); + seq, SequencedBase, SequencedBase+SequencedQueue.size()); - bool retransmit_acked_packets = false; - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - retransmit_acked_packets = RETRANSMIT_ACKED_PACKETS; - } - - if(!retransmit_acked_packets) { - uint16 sqsize = SequencedQueue.size(); - uint16 index = seq - SequencedBase; - Log.Out(Logs::Detail, Logs::Netcode, _L "OP_OutOfOrderAck marking packet acked in queue (queue index = %d, queue size = %d)." __L, index, sqsize); - if (index < sqsize) { - std::deque::iterator sitr; - sitr = SequencedQueue.begin(); - sitr += index; - (*sitr)->acked = true; + uint16 sqsize = SequencedQueue.size(); + uint16 index = seq - SequencedBase; + Log.Out(Logs::Detail, Logs::Netcode, _L "OP_OutOfOrderAck marking packet acked in queue (queue index = %d, queue size = %d)." __L, index, sqsize); + if (index < sqsize) { + std::deque::iterator sitr; + sitr = SequencedQueue.begin(); + sitr += index; + (*sitr)->acked = true; + // flag packets for a resend + uint16 count = 0; + uint32 timeout = AverageDelta * 2 + 100; + for (sitr = SequencedQueue.begin(); sitr != SequencedQueue.end() && count < index; ++sitr, ++count) { + if (!(*sitr)->acked && (*sitr)->sent_time > 0 && (((*sitr)->sent_time + timeout) < Timer::GetCurrentTime())) { + (*sitr)->sent_time = 0; + Log.Out(Logs::Detail, Logs::Netcode, _L "OP_OutOfOrderAck Flagging packet %d for retransmission" __L, SequencedBase + count); + } } } if(RETRANSMIT_TIMEOUT_MULT) { retransmittimer = Timer::GetCurrentTime(); } - - NextSequencedSend = 0; } else { Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck for out-of-window %d. Window (%d->%d)." __L, seq, SequencedBase, NextOutSeq); } @@ -458,9 +451,6 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) Log.Out(Logs::Detail, Logs::Netcode, _L "Post-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } - if(NextSequencedSend > SequencedQueue.size()) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Post-OOA Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); - } MOutboundQueue.unlock(); #endif } @@ -489,6 +479,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) } else { retransmittimeout = ntohl(ClientStats->average_delta) * 2 * RETRANSMIT_TIMEOUT_MULT; } + retransmittimeout += 300; if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX) retransmittimeout = RETRANSMIT_TIMEOUT_MAX; Log.Out(Logs::Detail, Logs::Netcode, _L "Retransmit timeout recalculated to %dms" __L, retransmittimeout); @@ -631,9 +622,7 @@ void EQStream::SequencedPush(EQProtocolPacket *p) if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } -if(NextSequencedSend > SequencedQueue.size()) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Push Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); -} + Log.Out(Logs::Detail, Logs::Netcode, _L "Pushing sequenced packet %d of length %d. Base Seq is %d." __L, NextOutSeq, p->size, SequencedBase); *(uint16 *)(p->pBuffer)=htons(NextOutSeq); @@ -643,9 +632,7 @@ if(NextSequencedSend > SequencedQueue.size()) { if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { Log.Out(Logs::Detail, Logs::Netcode, _L "Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } -if(NextSequencedSend > SequencedQueue.size()) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Push Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); -} + MOutboundQueue.unlock(); #endif } @@ -703,21 +690,15 @@ void EQStream::Write(int eq_fd) // Place to hold the base packet t combine into EQProtocolPacket *p=nullptr; - if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - // if we have a timeout defined and we have not received an ack recently enough, retransmit from beginning of queue - if (RETRANSMIT_TIMEOUT_MULT && !SequencedQueue.empty() && NextSequencedSend && - (GetState()==ESTABLISHED) && ((retransmittimer+retransmittimeout) < Timer::GetCurrentTime())) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Timeout since last ack received, starting retransmit at the start of our unacked " - "buffer (seq %d, was %d)." __L, SequencedBase, SequencedBase+NextSequencedSend); - NextSequencedSend = 0; - retransmittimer = Timer::GetCurrentTime(); // don't want to endlessly retransmit the first packet - } - } - // Find the next sequenced packet to send from the "queue" sitr = SequencedQueue.begin(); - if (sitr!=SequencedQueue.end()) - sitr += NextSequencedSend; + + uint16 count = 0; + // get to start of packets + while (sitr != SequencedQueue.end() && (*sitr)->sent_time > 0) { + sitr++; + count++; + } // Loop until both are empty or MaxSends is reached while(!SeqEmpty || !NonSeqEmpty) { @@ -731,7 +712,7 @@ void EQStream::Write(int eq_fd) Log.Out(Logs::Detail, Logs::Netcode, _L "Starting combined packet with non-seq packet of len %d" __L, p->size); NonSequencedQueue.pop(); } else if (!p->combine(NonSequencedQueue.front())) { - // Tryint to combine this packet with the base didn't work (too big maybe) + // Trying to combine this packet with the base didn't work (too big maybe) // So just send the base packet (we'll try this packet again later) Log.Out(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next non-seq packet is len %d" __L, p->size, (NonSequencedQueue.front())->size); ReadyToSend.push(p); @@ -754,15 +735,10 @@ void EQStream::Write(int eq_fd) NonSeqEmpty=true; } - if (sitr!=SequencedQueue.end()) { - if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Send Seq NSS=%d Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, NextSequencedSend, SequencedBase, SequencedQueue.size(), NextOutSeq); - } - if(NextSequencedSend > SequencedQueue.size()) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Send Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); - } - uint16 seq_send = SequencedBase + NextSequencedSend; //just for logging... + if (sitr!=SequencedQueue.end()) { + + uint16 seq_send = SequencedBase + count; //just for logging... if(SequencedQueue.empty()) { Log.Out(Logs::Detail, Logs::Netcode, _L "Tried to write a packet with an empty queue (%d is past next out %d)" __L, seq_send, NextOutSeq); @@ -771,26 +747,32 @@ void EQStream::Write(int eq_fd) } if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { - if (!RETRANSMIT_ACKED_PACKETS && (*sitr)->acked) { + if ((*sitr)->acked || (*sitr)->sent_time != 0) { + ++sitr; + ++count; + if (p) { + Log.Out(Logs::Detail, Logs::Netcode, _L "Final combined packet not full, len %d" __L, p->size); + ReadyToSend.push(p); + BytesWritten += p->size; + p = nullptr; + } Log.Out(Logs::Detail, Logs::Netcode, _L "Not retransmitting seq packet %d because already marked as acked" __L, seq_send); - sitr++; - NextSequencedSend++; } else if (!p) { // If we don't have a packet to try to combine into, use this one as the base // Copy it first as it will still live until it is acked p=(*sitr)->Copy(); Log.Out(Logs::Detail, Logs::Netcode, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size); + (*sitr)->sent_time = Timer::GetCurrentTime(); ++sitr; - NextSequencedSend++; + ++count; } else if (!p->combine(*sitr)) { // Trying to combine this packet with the base didn't work (too big maybe) // So just send the base packet (we'll try this packet again later) - Log.Out(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send, (*sitr)->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send + 1, (*sitr)->size); ReadyToSend.push(p); BytesWritten+=p->size; p=nullptr; - - if (BytesWritten > threshold) { + if ((*sitr)->opcode != OP_Fragment && BytesWritten > threshold) { // Sent enough this round, lets stop to be fair Log.Out(Logs::Detail, Logs::Netcode, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold); break; @@ -798,17 +780,28 @@ void EQStream::Write(int eq_fd) } else { // Combine worked Log.Out(Logs::Detail, Logs::Netcode, _L "Combined seq packet %d of len %d, yeilding %d combined." __L, seq_send, (*sitr)->size, p->size); + (*sitr)->sent_time = Timer::GetCurrentTime(); ++sitr; - NextSequencedSend++; + ++count; } } else { - if (!p) { + if ((*sitr)->sent_time != 0) { + ++sitr; + ++count; + if (p) { + Log.Out(Logs::Detail, Logs::Netcode, _L "Final combined packet not full, len %d" __L, p->size); + ReadyToSend.push(p); + BytesWritten += p->size; + p = nullptr; + } + } else if (!p) { // If we don't have a packet to try to combine into, use this one as the base // Copy it first as it will still live until it is acked p=(*sitr)->Copy(); + (*sitr)->sent_time = Timer::GetCurrentTime(); Log.Out(Logs::Detail, Logs::Netcode, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size); ++sitr; - NextSequencedSend++; + ++count; } else if (!p->combine(*sitr)) { // Trying to combine this packet with the base didn't work (too big maybe) // So just send the base packet (we'll try this packet again later) @@ -824,18 +817,16 @@ void EQStream::Write(int eq_fd) } } else { // Combine worked - Log.Out(Logs::Detail, Logs::Netcode, _L "Combined seq packet %d of len %d, yeilding %d combined." __L, seq_send, (*sitr)->size, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Combined seq packet %d of len %d, yielding %d combined." __L, seq_send, (*sitr)->size, p->size); + (*sitr)->sent_time = Timer::GetCurrentTime(); ++sitr; - NextSequencedSend++; + ++count; } } if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { Log.Out(Logs::Detail, Logs::Netcode, _L "Post send Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } - if(NextSequencedSend > SequencedQueue.size()) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Post send Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); - } } else { // No more sequenced packets SeqEmpty=true; @@ -894,9 +885,11 @@ sockaddr_in address; length=p->serialize(buffer); if (p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) { if (compressed) { + BytesWritten -= p->size; uint32 newlen=EQProtocolPacket::Compress(buffer,length, _tempBuffer, 2048); memcpy(buffer,_tempBuffer,newlen); length=newlen; + BytesWritten += newlen; } if (encoded) { EQProtocolPacket::ChatEncode(buffer,length,Key); @@ -1158,13 +1151,6 @@ void EQStream::AckPackets(uint16 seq) std::deque::iterator itr, tmp; MOutboundQueue.lock(); -//do a bit of sanity checking. -if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Ack Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); -} -if(NextSequencedSend > SequencedQueue.size()) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Ack Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); -} SeqOrder ord = CompareSequence(SequencedBase, seq); if(ord == SeqInOrder) { @@ -1180,28 +1166,21 @@ if(NextSequencedSend > SequencedQueue.size()) { //this is a good ack, we get to ack some blocks. seq++; //we stop at the block right after their ack, counting on the wrap of both numbers. while(SequencedBase != seq) { -if(SequencedQueue.empty()) { -Log.Out(Logs::Detail, Logs::Netcode, _L "OUT OF PACKETS acked packet with sequence %lu. Next send is %d before this." __L, (unsigned long)SequencedBase, NextSequencedSend); - SequencedBase = NextOutSeq; - NextSequencedSend = 0; - break; -} - Log.Out(Logs::Detail, Logs::Netcode, _L "Removing acked packet with sequence %lu. Next send is %d before this." __L, (unsigned long)SequencedBase, NextSequencedSend); + if(SequencedQueue.empty()) { + Log.Out(Logs::Detail, Logs::Netcode, _L "OUT OF PACKETS acked packet with sequence %lu. Next send is %d before this." __L, (unsigned long)SequencedBase, SequencedQueue.size()); + SequencedBase = NextOutSeq; + break; + } + Log.Out(Logs::Detail, Logs::Netcode, _L "Removing acked packet with sequence %lu." __L, (unsigned long)SequencedBase); //clean out the acked packet delete SequencedQueue.front(); SequencedQueue.pop_front(); - //adjust our "next" pointer - if(NextSequencedSend > 0) - NextSequencedSend--; //advance the base sequence number to the seq of the block after the one we just got rid of. SequencedBase++; } -if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Post-Ack on %d Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, seq, SequencedBase, SequencedQueue.size(), NextOutSeq); -} -if(NextSequencedSend > SequencedQueue.size()) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Post-Ack Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); -} + if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { + Log.Out(Logs::Detail, Logs::Netcode, _L "Post-Ack on %d Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, seq, SequencedBase, SequencedQueue.size(), NextOutSeq); + } } MOutboundQueue.unlock(); @@ -1379,6 +1358,16 @@ void EQStream::Decay() if (BytesWritten<0) BytesWritten=0; } + // check for any timed out acks + if ((GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) && RETRANSMIT_TIMEOUT_MULT && retransmittimeout) { + int count = 0; + for (std::deque::iterator sitr = SequencedQueue.begin(); sitr != SequencedQueue.end(); sitr++, count++) { + if (!(*sitr)->acked && (*sitr)->sent_time > 0 && ((*sitr)->sent_time + retransmittimeout) < Timer::GetCurrentTime()) { + (*sitr)->sent_time = 0; + Log.Out(Logs::Detail, Logs::Netcode, _L "Timeout exceeded for seq %d. Flagging packet for retransmission" __L, SequencedBase + count); + } + } + } } void EQStream::AdjustRates(uint32 average_delta) @@ -1386,18 +1375,24 @@ void EQStream::AdjustRates(uint32 average_delta) if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { if (average_delta && (average_delta <= AVERAGE_DELTA_MAX)) { MRate.lock(); + AverageDelta = average_delta; RateThreshold=RATEBASE/average_delta; DecayRate=DECAYBASE/average_delta; + if (BytesWritten > RateThreshold) + BytesWritten = RateThreshold + DecayRate; Log.Out(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, RateThreshold, DecayRate, average_delta); MRate.unlock(); } else { Log.Out(Logs::Detail, Logs::Netcode, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L, average_delta, AVERAGE_DELTA_MAX); + AverageDelta = AVERAGE_DELTA_MAX; } } else { if (average_delta) { MRate.lock(); + AverageDelta = average_delta; + BytesWritten = 0; RateThreshold=RATEBASE/average_delta; DecayRate=DECAYBASE/average_delta; Log.Out(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, diff --git a/common/eq_stream.h b/common/eq_stream.h index 0bdfeab53..d5e78c085 100644 --- a/common/eq_stream.h +++ b/common/eq_stream.h @@ -153,7 +153,6 @@ class EQStream : public EQStreamInterface { std::deque SequencedQueue; uint16 NextOutSeq; uint16 SequencedBase; //the sequence number of SequencedQueue[0] - long NextSequencedSend; //index into SequencedQueue Mutex MOutboundQueue; //a buffer we use for compression/decompression @@ -174,7 +173,7 @@ class EQStream : public EQStreamInterface { Mutex MRate; int32 RateThreshold; int32 DecayRate; - + uint32 AverageDelta; OpcodeManager **OpMgr; diff --git a/zone/bot.cpp b/zone/bot.cpp index 6cb27f8e7..c2213436b 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -8816,6 +8816,7 @@ Bot* EntityList::GetBotByBotName(std::string botName) { void EntityList::AddBot(Bot *newBot, bool SendSpawnPacket, bool dontqueue) { if(newBot) { newBot->SetID(GetFreeID()); + newBot->SetSpawned(); if(SendSpawnPacket) { if(dontqueue) { EQApplicationPacket* outapp = new EQApplicationPacket(); diff --git a/zone/client.cpp b/zone/client.cpp index 837306d99..896a794c2 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -123,7 +123,7 @@ Client::Client(EQStreamInterface* ieqs) camp_timer(29000), process_timer(100), stamina_timer(40000), - zoneinpacket_timer(3000), + zoneinpacket_timer(1000), linkdead_timer(RuleI(Zone,ClientLinkdeadMS)), dead_timer(2000), global_channel_timer(1000), @@ -439,6 +439,7 @@ void Client::SendZoneInPackets() outapp->priority = 6; if (!GetHideMe()) entity_list.QueueClients(this, outapp, true); safe_delete(outapp); + SetSpawned(); if (GetPVP()) //force a PVP update until we fix the spawn struct SendAppearancePacket(AT_PVP, GetPVP(), true, false); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index fb7216b86..0ec86ed0d 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -495,7 +495,7 @@ void Client::CompleteConnect() { UpdateWho(); client_state = CLIENT_CONNECTED; - + SendAllPackets(); hpupdate_timer.Start(); position_timer.Start(); autosave_timer.Start(); @@ -750,8 +750,6 @@ void Client::CompleteConnect() entity_list.SendTraders(this); - zoneinpacket_timer.Start(); - if (GetPet()){ GetPet()->SendPetBuffsToClient(); } @@ -1729,7 +1727,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) SetAttackTimer(); conn_state = ZoneInfoSent; - + zoneinpacket_timer.Start(); return; } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 3154a9ca9..6c51e6196 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -66,7 +66,7 @@ bool Client::Process() { if(Connected() || IsLD()) { // try to send all packets that weren't sent before - if(!IsLD() && zoneinpacket_timer.Check()) + if (!IsLD() && zoneinpacket_timer.Check()) { SendAllPackets(); } diff --git a/zone/entity.cpp b/zone/entity.cpp index a79d01609..00da8a7dc 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -647,7 +647,7 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) uint16 emoteid = npc->GetEmoteID(); if (emoteid != 0) npc->DoNPCEmote(ONSPAWN, emoteid); - + npc->SetSpawned(); if (SendSpawnPacket) { if (dontqueue) { // aka, SEND IT NOW BITCH! EQApplicationPacket *app = new EQApplicationPacket; @@ -686,7 +686,7 @@ void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue) if (merc) { merc->SetID(GetFreeID()); - + merc->SetSpawned(); if (SendSpawnPacket) { if (dontqueue) { @@ -1231,7 +1231,7 @@ void EntityList::SendZoneSpawnsBulk(Client *client) int32 race=-1; for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { spawn = it->second; - if (spawn && spawn->InZone()) { + if (spawn && spawn->GetID() > 0 && spawn->Spawned()) { if (spawn->IsClient() && (spawn->CastToClient()->GMHideMe(client) || spawn->CastToClient()->IsHoveringForRespawn())) continue; diff --git a/zone/mob.cpp b/zone/mob.cpp index c91ae404f..fdfe602ce 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -253,6 +253,7 @@ Mob::Mob(const char* in_name, invulnerable = false; IsFullHP = (cur_hp == max_hp); qglobal=0; + spawned = false; InitializeBuffSlots(); diff --git a/zone/mob.h b/zone/mob.h index 8cb899d0f..8bf1f1dda 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -488,6 +488,8 @@ public: void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu); void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu); void SendPosition(); + void SetSpawned() { spawned = true; }; + bool Spawned() { return spawned; }; void SetFlyMode(uint8 flymode); inline void Teleport(glm::vec3 NewPosition) { m_Position.x = NewPosition.x; m_Position.y = NewPosition.y; m_Position.z = NewPosition.z; }; @@ -1137,6 +1139,7 @@ protected: bool held; bool nocast; bool focused; + bool spawned; void CalcSpellBonuses(StatBonuses* newbon); virtual void CalcBonuses(); void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand = MainCharm? From 1551e5d908e2e3d07413fca78a51bc7771a4f37e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 8 Apr 2016 14:11:02 -0400 Subject: [PATCH 036/693] Add mutex to EQStream::Decay to prevent threading issues --- common/eq_stream.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index d132fb872..24d96562f 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -1361,12 +1361,14 @@ void EQStream::Decay() // check for any timed out acks if ((GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) && RETRANSMIT_TIMEOUT_MULT && retransmittimeout) { int count = 0; + MOutboundQueue.lock(); for (std::deque::iterator sitr = SequencedQueue.begin(); sitr != SequencedQueue.end(); sitr++, count++) { if (!(*sitr)->acked && (*sitr)->sent_time > 0 && ((*sitr)->sent_time + retransmittimeout) < Timer::GetCurrentTime()) { (*sitr)->sent_time = 0; Log.Out(Logs::Detail, Logs::Netcode, _L "Timeout exceeded for seq %d. Flagging packet for retransmission" __L, SequencedBase + count); } } + MOutboundQueue.unlock(); } } From 761c2be72278bb4840987c09c217240985693c8a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 8 Apr 2016 14:14:09 -0400 Subject: [PATCH 037/693] Style changes (auto, post-inc to pre-inc) --- common/eq_stream.cpp | 39 +++++++++++++++++------------------- common/eq_stream_factory.cpp | 27 +++++++++++++------------ 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index 24d96562f..4b231dc9a 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -425,14 +425,11 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) uint16 index = seq - SequencedBase; Log.Out(Logs::Detail, Logs::Netcode, _L "OP_OutOfOrderAck marking packet acked in queue (queue index = %d, queue size = %d)." __L, index, sqsize); if (index < sqsize) { - std::deque::iterator sitr; - sitr = SequencedQueue.begin(); - sitr += index; - (*sitr)->acked = true; + SequencedQueue[index]->acked = true; // flag packets for a resend uint16 count = 0; uint32 timeout = AverageDelta * 2 + 100; - for (sitr = SequencedQueue.begin(); sitr != SequencedQueue.end() && count < index; ++sitr, ++count) { + for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end() && count < index; ++sitr, ++count) { if (!(*sitr)->acked && (*sitr)->sent_time > 0 && (((*sitr)->sent_time + timeout) < Timer::GetCurrentTime())) { (*sitr)->sent_time = 0; Log.Out(Logs::Detail, Logs::Netcode, _L "OP_OutOfOrderAck Flagging packet %d for retransmission" __L, SequencedBase + count); @@ -619,19 +616,21 @@ void EQStream::SequencedPush(EQProtocolPacket *p) delete p; #else MOutboundQueue.lock(); -if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); -} + if (uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { + Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, + SequencedBase, SequencedQueue.size(), NextOutSeq); + } - - Log.Out(Logs::Detail, Logs::Netcode, _L "Pushing sequenced packet %d of length %d. Base Seq is %d." __L, NextOutSeq, p->size, SequencedBase); - *(uint16 *)(p->pBuffer)=htons(NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Pushing sequenced packet %d of length %d. Base Seq is %d." __L, + NextOutSeq, p->size, SequencedBase); + *(uint16 *)(p->pBuffer) = htons(NextOutSeq); SequencedQueue.push_back(p); NextOutSeq++; -if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - Log.Out(Logs::Detail, Logs::Netcode, _L "Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); -} + if (uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { + Log.Out(Logs::Detail, Logs::Netcode, _L "Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, + SequencedBase, SequencedQueue.size(), NextOutSeq); + } MOutboundQueue.unlock(); #endif @@ -696,8 +695,8 @@ void EQStream::Write(int eq_fd) uint16 count = 0; // get to start of packets while (sitr != SequencedQueue.end() && (*sitr)->sent_time > 0) { - sitr++; - count++; + ++sitr; + ++count; } // Loop until both are empty or MaxSends is reached @@ -735,11 +734,9 @@ void EQStream::Write(int eq_fd) NonSeqEmpty=true; } - - if (sitr!=SequencedQueue.end()) { - + if (sitr != SequencedQueue.end()) { uint16 seq_send = SequencedBase + count; //just for logging... - + if(SequencedQueue.empty()) { Log.Out(Logs::Detail, Logs::Netcode, _L "Tried to write a packet with an empty queue (%d is past next out %d)" __L, seq_send, NextOutSeq); SeqEmpty=true; @@ -1362,7 +1359,7 @@ void EQStream::Decay() if ((GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) && RETRANSMIT_TIMEOUT_MULT && retransmittimeout) { int count = 0; MOutboundQueue.lock(); - for (std::deque::iterator sitr = SequencedQueue.begin(); sitr != SequencedQueue.end(); sitr++, count++) { + for (auto sitr = SequencedQueue.begin(); sitr != SequencedQueue.end(); ++sitr, count++) { if (!(*sitr)->acked && (*sitr)->sent_time > 0 && ((*sitr)->sent_time + retransmittimeout) < Timer::GetCurrentTime()) { (*sitr)->sent_time = 0; Log.Out(Logs::Detail, Logs::Netcode, _L "Timeout exceeded for seq %d. Flagging packet for retransmission" __L, SequencedBase + count); diff --git a/common/eq_stream_factory.cpp b/common/eq_stream_factory.cpp index f48b0f723..ca5596410 100644 --- a/common/eq_stream_factory.cpp +++ b/common/eq_stream_factory.cpp @@ -250,8 +250,7 @@ void EQStreamFactory::CheckTimeout() void EQStreamFactory::WriterLoop() { - std::map, std::shared_ptr>::iterator stream_itr; - bool havework=true; + bool havework = true; std::vector> wants_write; std::vector>::iterator cur, end; bool decay = false; @@ -260,7 +259,7 @@ void EQStreamFactory::WriterLoop() WriterRunning = true; DecayTimer.Enable(); - while(sock!=-1) { + while (sock != -1) { MWriterRunning.lock(); if (!WriterRunning) break; @@ -269,34 +268,36 @@ void EQStreamFactory::WriterLoop() havework = false; wants_write.clear(); - decay=DecayTimer.Check(); + decay = DecayTimer.Check(); - //copy streams into a seperate list so we dont have to keep - //MStreams locked while we are writting + // copy streams into a seperate list so we dont have to keep + // MStreams locked while we are writting MStreams.lock(); - for(stream_itr=Streams.begin();stream_itr!=Streams.end();++stream_itr) { + for (auto stream_itr = Streams.begin(); stream_itr != Streams.end(); ++stream_itr) { // If it's time to decay the bytes sent, then let's do it before we try to write if (decay) stream_itr->second->Decay(); - //bullshit checking, to see if this is really happening, GDB seems to think so... - if(stream_itr->second == nullptr) { - fprintf(stderr, "ERROR: nullptr Stream encountered in EQStreamFactory::WriterLoop for: %i:%i", stream_itr->first.first, stream_itr->first.second); + // bullshit checking, to see if this is really happening, GDB seems to think so... + if (stream_itr->second == nullptr) { + fprintf(stderr, + "ERROR: nullptr Stream encountered in EQStreamFactory::WriterLoop for: %i:%i", + stream_itr->first.first, stream_itr->first.second); continue; } if (stream_itr->second->HasOutgoingData()) { - havework=true; + havework = true; stream_itr->second->PutInUse(); wants_write.push_back(stream_itr->second); } } MStreams.unlock(); - //do the actual writes + // do the actual writes cur = wants_write.begin(); end = wants_write.end(); - for(; cur != end; ++cur) { + for (; cur != end; ++cur) { (*cur)->Write(sock); (*cur)->ReleaseFromUse(); } From 6e11128cbcfef1bbddbfcf10bab93a96d728e95e Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 8 Apr 2016 20:58:17 -0400 Subject: [PATCH 038/693] Added HealRotation HOT methodology (Heal Override Target) and load/save/delete capabilities --- changelog.txt | 4 + common/version.h | 2 +- .../sql/git/bots/bots_db_update_manifest.txt | 2 + .../2016_04_07_bots_heal_override_target.sql | 3 + .../2016_04_08_bots_heal_rotations.sql | 41 +++ zone/bot.cpp | 21 +- zone/bot_command.cpp | 271 ++++++++++++++++- zone/bot_command.h | 4 + zone/bot_database.cpp | 287 ++++++++++++++++++ zone/bot_database.h | 20 ++ zone/heal_rotation.cpp | 76 ++++- zone/heal_rotation.h | 17 +- 12 files changed, 723 insertions(+), 25 deletions(-) create mode 100644 utils/sql/git/bots/required/2016_04_07_bots_heal_override_target.sql create mode 100644 utils/sql/git/bots/required/2016_04_08_bots_heal_rotations.sql diff --git a/changelog.txt b/changelog.txt index 25729bce1..8563a9a36 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/08/2016 == +Uleat: Added Heal Rotation HOTs (Heal Override Targets) that can be set for proactive healing (default HR behavior is reactive) +Uleat: Added the ability to save/load/delete Heal Rotations based on targeted member - load is automatic when ^hrcreate is used on a bot that has a saved HR entry + == 04/07/2016 == Uleat: Rework of eq_dictionary to facilitate inventory work diff --git a/common/version.h b/common/version.h index 248ce3beb..bebd65ade 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9096 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9003 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9005 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index bbb0130ed..08ef5f161 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -2,6 +2,8 @@ 9001|2016_03_24_bots_command_settings.sql|SHOW TABLES LIKE 'bot_command_settings'|empty| 9002|2016_03_24_bots_command_rules.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CommandSpellRank'|empty| 9003|2016_04_05_bots_pet_spell_id_field.sql|SHOW COLUMNS FROM `bot_pets` LIKE 'pet_id'|not_empty| +9004|2016_04_07_bots_heal_override_target.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'healrotationclearhot'|empty| +9005|2016_04_08_bots_heal_rotations.sql|SHOW TABLES LIKE 'bot_heal_rotations'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2016_04_07_bots_heal_override_target.sql b/utils/sql/git/bots/required/2016_04_07_bots_heal_override_target.sql new file mode 100644 index 000000000..02cc4083e --- /dev/null +++ b/utils/sql/git/bots/required/2016_04_07_bots_heal_override_target.sql @@ -0,0 +1,3 @@ +INSERT INTO `bot_command_settings` VALUES +('healrotationclearhot', 0, 'hrclearhot'), +('healrotationsethot', 0, 'hrsethot'); diff --git a/utils/sql/git/bots/required/2016_04_08_bots_heal_rotations.sql b/utils/sql/git/bots/required/2016_04_08_bots_heal_rotations.sql new file mode 100644 index 000000000..71e0f5af4 --- /dev/null +++ b/utils/sql/git/bots/required/2016_04_08_bots_heal_rotations.sql @@ -0,0 +1,41 @@ +CREATE TABLE `bot_heal_rotations` ( + `heal_rotation_index` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `bot_id` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `interval` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `fast_heals` INT(3) UNSIGNED NOT NULL DEFAULT '0', + `adaptive_targeting` INT(3) UNSIGNED NOT NULL DEFAULT '0', + `casting_override` INT(3) UNSIGNED NOT NULL DEFAULT '0', + `safe_hp_base` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0', + `safe_hp_cloth` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0', + `safe_hp_leather` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0', + `safe_hp_chain` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0', + `safe_hp_plate` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0', + `critical_hp_base` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0', + `critical_hp_cloth` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0', + `critical_hp_leather` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0', + `critical_hp_chain` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0', + `critical_hp_plate` FLOAT(11) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`heal_rotation_index`), + CONSTRAINT `FK_bot_heal_rotations` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +CREATE TABLE `bot_heal_rotation_members` ( + `member_index` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `heal_rotation_index` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `bot_id` INT(11) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`member_index`), + CONSTRAINT `FK_bot_heal_rotation_members_1` FOREIGN KEY (`heal_rotation_index`) REFERENCES `bot_heal_rotations` (`heal_rotation_index`), + CONSTRAINT `FK_bot_heal_rotation_members_2` FOREIGN KEY (`bot_id`) REFERENCES `bot_data` (`bot_id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +CREATE TABLE `bot_heal_rotation_targets` ( + `target_index` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `heal_rotation_index` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `target_name` varchar(64) NOT NULL DEFAULT '', + PRIMARY KEY (`target_index`), + CONSTRAINT `FK_bot_heal_rotation_targets` FOREIGN KEY (`heal_rotation_index`) REFERENCES `bot_heal_rotations` (`heal_rotation_index`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +INSERT INTO `bot_command_settings` VALUES +('healrotationdelete', 0, 'hrdelete'), +('healrotationsave', 0, 'hrsave'); diff --git a/zone/bot.cpp b/zone/bot.cpp index 2c22a12a6..925cf6a2c 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1597,6 +1597,25 @@ bool Bot::DeleteBot() if (!bot_owner) return false; + if (!botdb.DeleteHealRotation(GetBotID())) { + bot_owner->Message(13, "%s", BotDatabase::fail::DeleteHealRotation()); + return false; + } + + std::string query = StringFormat("DELETE FROM `bot_heal_rotation_members` WHERE `bot_id` = '%u'", GetBotID()); + auto results = botdb.QueryDatabase(query); + if (!results.Success()) { + bot_owner->Message(13, "Failed to delete heal rotation member '%s'", GetCleanName()); + return false; + } + + query = StringFormat("DELETE FROM `bot_heal_rotation_targets` WHERE `target_name` LIKE '%s'", GetCleanName()); + results = botdb.QueryDatabase(query); + if (!results.Success()) { + bot_owner->Message(13, "Failed to delete heal rotation target '%s'", GetCleanName()); + return false; + } + if (!DeletePet()) { bot_owner->Message(13, "Failed to delete pet for '%s'", GetCleanName()); return false; @@ -8358,7 +8377,7 @@ bool Bot::IsMyHealRotationSet() { if (!IsHealRotationMember()) return false; - if (!m_member_of_heal_rotation->IsActive()) + if (!m_member_of_heal_rotation->IsActive() && !m_member_of_heal_rotation->IsHOTActive()) return false; if (!m_member_of_heal_rotation->CastingReady()) return false; diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index c69cfda44..5422c41ab 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -1370,13 +1370,17 @@ int bot_command_init(void) bot_command_add("healrotationadjustsafe", "Adjusts the safe HP limit of the heal rotation instance's Class Armor Type criteria", 0, bot_subcommand_heal_rotation_adjust_safe) || bot_command_add("healrotationcastingoverride", "Enables or disables casting overrides within the heal rotation instance", 0, bot_subcommand_heal_rotation_casting_override) || bot_command_add("healrotationchangeinterval", "Changes casting interval between members within the heal rotation instance", 0, bot_subcommand_heal_rotation_change_interval) || + bot_command_add("healrotationclearhot", "Clears the HOT of a heal rotation instance", 0, bot_subcommand_heal_rotation_clear_hot) || bot_command_add("healrotationcleartargets", "Removes all targets from a heal rotation instance", 0, bot_subcommand_heal_rotation_clear_targets) || bot_command_add("healrotationcreate", "Creates a bot heal rotation instance and designates a leader", 0, bot_subcommand_heal_rotation_create) || + bot_command_add("healrotationdelete", "Deletes a bot heal rotation entry by leader", 0, bot_subcommand_heal_rotation_delete) || bot_command_add("healrotationfastheals", "Enables or disables fast heals within the heal rotation instance", 0, bot_subcommand_heal_rotation_fast_heals) || bot_command_add("healrotationlist", "Reports heal rotation instance(s) information", 0, bot_subcommand_heal_rotation_list) || bot_command_add("healrotationremovemember", "Removes a bot from a heal rotation instance", 0, bot_subcommand_heal_rotation_remove_member) || bot_command_add("healrotationremovetarget", "Removes target from a heal rotations instance", 0, bot_subcommand_heal_rotation_remove_target) || bot_command_add("healrotationresetlimits", "Resets all Class Armor Type HP limit criteria in a heal rotation to its default value", 0, bot_subcommand_heal_rotation_reset_limits) || + bot_command_add("healrotationsave", "Saves a bot heal rotation entry by leader", 0, bot_subcommand_heal_rotation_save) || + bot_command_add("healrotationsethot", "Sets the HOT in a heal rotation instance", 0, bot_subcommand_heal_rotation_set_hot) || bot_command_add("healrotationstart", "Starts a heal rotation", 0, bot_subcommand_heal_rotation_start) || bot_command_add("healrotationstop", "Stops a heal rotation", 0, bot_subcommand_heal_rotation_stop) || bot_command_add("help", "List available commands and their description - specify partial command as argument to search", 0, bot_command_help) || @@ -3064,13 +3068,17 @@ void bot_command_heal_rotation(Client *c, const Seperator *sep) subcommand_list.push_back("healrotationadjustsafe"); subcommand_list.push_back("healrotationcastoverride"); subcommand_list.push_back("healrotationchangeinterval"); + subcommand_list.push_back("healrotationclearhot"); subcommand_list.push_back("healrotationcleartargets"); subcommand_list.push_back("healrotationcreate"); + subcommand_list.push_back("healrotationdelete"); subcommand_list.push_back("healrotationfastheals"); subcommand_list.push_back("healrotationlist"); subcommand_list.push_back("healrotationremovemember"); subcommand_list.push_back("healrotationremovetarget"); subcommand_list.push_back("healrotationresetlimits"); + subcommand_list.push_back("healrotationsave"); + subcommand_list.push_back("healrotationsethot"); subcommand_list.push_back("healrotationstart"); subcommand_list.push_back("healrotationstop"); /* VS2012 code - end */ @@ -3078,8 +3086,9 @@ void bot_command_heal_rotation(Client *c, const Seperator *sep) /* VS2013 code const std::list subcommand_list = { "healrotationadaptivetargeting", "healrotationaddmember", "healrotationaddtarget", "healrotationadjustcritical", "healrotationadjustsafe", - "healrotationcastoverride", "healrotationchangeinterval", "healrotationcleartargets", "healrotationcreate", "healrotationfastheals", - "healrotationlist", "healrotationremovemember", "healrotationremovetarget", "healrotationresetlimits", "healrotationstart", "healrotationstop" + "healrotationcastoverride", "healrotationchangeinterval", "healrotationclearhot", "healrotationcleartargets", "healrotationcreate", + "healrotationdelete", "healrotationfastheals", "healrotationlist", "healrotationremovemember", "healrotationremovetarget", "healrotationsave", + "healrotationresetlimits", "healrotationsethot", "healrotationstart", "healrotationstop" }; */ @@ -6132,10 +6141,10 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se else if (!critical_arg.compare("-")) critical_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(armor_type_value) - HP_RATIO_DELTA; - if (critical_ratio > SAFE_HP_RATIO_BASE) - critical_ratio = SAFE_HP_RATIO_BASE; - if (critical_ratio < CRITICAL_HP_RATIO_BASE) - critical_ratio = CRITICAL_HP_RATIO_BASE; + if (critical_ratio > SAFE_HP_RATIO_ABS) + critical_ratio = SAFE_HP_RATIO_ABS; + if (critical_ratio < CRITICAL_HP_RATIO_ABS) + critical_ratio = CRITICAL_HP_RATIO_ABS; if (!(*current_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(armor_type_value, critical_ratio)) { c->Message(m_fail, "Critical value %3.1f%%(%u) exceeds safe value %3.1f%%(%u) for %s's Heal Rotation", @@ -6198,10 +6207,10 @@ void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep) else if (!safe_arg.compare("-")) safe_ratio = (*current_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(armor_type_value) - HP_RATIO_DELTA; - if (safe_ratio > SAFE_HP_RATIO_BASE) - safe_ratio = SAFE_HP_RATIO_BASE; - if (safe_ratio < CRITICAL_HP_RATIO_BASE) - safe_ratio = CRITICAL_HP_RATIO_BASE; + if (safe_ratio > SAFE_HP_RATIO_ABS) + safe_ratio = SAFE_HP_RATIO_ABS; + if (safe_ratio < CRITICAL_HP_RATIO_ABS) + safe_ratio = CRITICAL_HP_RATIO_ABS; if (!(*current_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(armor_type_value, safe_ratio)) { c->Message(m_fail, "Safe value %3.1f%%(%u) does not exceed critical value %3.1f%%(%u) for %s's Heal Rotation", @@ -6256,13 +6265,13 @@ void bot_subcommand_heal_rotation_casting_override(Client *c, const Seperator *s hr_casting_override = true; } else if (casting_override_arg.compare("off")) { - c->Message(m_action, "Fast heals are currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName()); + c->Message(m_action, "Casting override is currently '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName()); return; } (*current_member->MemberOfHealRotation())->SetCastingOverride(hr_casting_override); - c->Message(m_action, "Fast heals are now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName()); + c->Message(m_action, "Casting override is now '%s' for %s's Heal Rotation", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off")), current_member->GetCleanName()); } void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *sep) @@ -6323,6 +6332,42 @@ void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *se c->Message(m_action, "Casting interval is now '%i' second%s for %s's Heal Rotation", hr_change_interval_s, ((hr_change_interval_s == 1) ? ("") : ("s")), current_member->GetCleanName()); } +void bot_subcommand_heal_rotation_clear_hot(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_clear_hot", sep->arg[0], "healrotationclearhot")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + if (!(*current_member->MemberOfHealRotation())->ClearHOTTarget()) { + c->Message(m_fail, "Failed to clear %s's Heal Rotation HOT", current_member->GetCleanName()); + } + + c->Message(m_action, "Succeeded in clearing %s's Heal Rotation HOT", current_member->GetCleanName()); +} + void bot_subcommand_heal_rotation_clear_targets(Client *c, const Seperator *sep) { if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_clear_targets", sep->arg[0], "healrotationcleartargets")) @@ -6437,8 +6482,115 @@ void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep) c->Message(m_fail, "Failed to add %s as a current member to a new Heal Rotation", creator_member->GetCleanName()); return; } + + std::list member_list; + std::list target_list; + bool load_flag = false; + bool member_fail = false; + bool target_fail = false; + + if (!botdb.LoadHealRotation(creator_member, member_list, target_list, load_flag, member_fail, target_fail)) + c->Message(m_fail, "%s", BotDatabase::fail::LoadHealRotation()); - c->Message(m_action, "Successfully added %s as a current member to a new Heal Rotation", creator_member->GetCleanName()); + if (!load_flag) { + c->Message(m_action, "Successfully added %s as a current member to a new Heal Rotation", creator_member->GetCleanName()); + return; + } + + if (!member_fail) { + MyBots::PopulateSBL_BySpawnedBots(c, sbl); + for (auto member_iter : member_list) { + if (!member_iter || member_iter == creator_member->GetBotID()) + continue; + + bool member_found = false; + for (auto bot_iter : sbl) { + if (bot_iter->GetBotID() != member_iter) + continue; + + if (!bot_iter->JoinHealRotationMemberPool(creator_member->MemberOfHealRotation())) + c->Message(m_fail, "Failed to add member '%s'", bot_iter->GetCleanName()); + member_found = true; + + break; + } + + if (!member_found) + c->Message(m_fail, "Could not locate member with bot id '%u'", member_iter); + } + } + else { + c->Message(m_fail, "%s", BotDatabase::fail::LoadHealRotationMembers()); + } + + if (!target_fail) { + for (auto target_iter : target_list) { + if (target_iter.empty()) + continue; + + auto target_mob = entity_list.GetMob(target_iter.c_str()); + if (!target_mob) { + c->Message(m_fail, "Could not locate target '%s'", target_iter.c_str()); + continue; + } + + if (!target_mob->JoinHealRotationTargetPool(creator_member->MemberOfHealRotation())) + c->Message(m_fail, "Failed to add target '%s'", target_mob->GetCleanName()); + } + } + else { + c->Message(m_fail, "%s", BotDatabase::fail::LoadHealRotationTargets()); + } + + c->Message(m_action, "Successfully loaded %s's Heal Rotation", creator_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_delete(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_delete", sep->arg[0], "healrotationdelete")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([option: all]) ([member_name])", sep->arg[0]); + return; + } + + bool all_flag = false; + int name_arg = 1; + if (!strcasecmp(sep->arg[1], "all")) { + all_flag = true; + name_arg = 2; + } + + if (all_flag) { + if (botdb.DeleteAllHealRotations(c->CharacterID())) + c->Message(m_action, "Succeeded in deleting all heal rotations"); + else + c->Message(m_fail, "%s", BotDatabase::fail::DeleteAllHealRotations()); + + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[name_arg]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!botdb.DeleteHealRotation(current_member->GetBotID())) { + c->Message(m_fail, "%s", BotDatabase::fail::DeleteHealRotation()); + return; + } + + c->Message(m_action, "Succeeded in deleting %s's heal rotation", current_member->GetCleanName()); } void bot_subcommand_heal_rotation_fast_heals(Client *c, const Seperator *sep) @@ -6529,6 +6681,8 @@ void bot_subcommand_heal_rotation_list(Client *c, const Seperator *sep) c->Message(m_message, "Fast heals: '%s'", (((*current_member->MemberOfHealRotation())->FastHeals()) ? ("on") : ("off"))); c->Message(m_message, "Adaptive targeting: '%s'", (((*current_member->MemberOfHealRotation())->AdaptiveTargeting()) ? ("on") : ("off"))); c->Message(m_message, "Casting override: '%s'", (((*current_member->MemberOfHealRotation())->CastingOverride()) ? ("on") : ("off"))); + c->Message(m_message, "HOT state: %s", (((*current_member->MemberOfHealRotation())->IsHOTActive()) ? ("active") : ("inactive"))); + c->Message(m_message, "HOT target: %s", (((*current_member->MemberOfHealRotation())->HOTTarget()) ? ((*current_member->MemberOfHealRotation())->HOTTarget()->GetCleanName()) : ("null"))); c->Message(m_message, "Base hp limits - critical: %3.1f%%, safe: %3.1f%%", (*current_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_UNKNOWN), @@ -6687,6 +6841,97 @@ void bot_subcommand_heal_rotation_reset_limits(Client *c, const Seperator *sep) c->Message(m_action, "Class Armor Type HP limit criteria has been set to default values for %s's Heal Rotation", current_member->GetCleanName()); } +void bot_subcommand_heal_rotation_save(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_save", sep->arg[0], "healrotationsave")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[1]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a current member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + bool member_fail = false; + bool target_fail = false; + if (!botdb.SaveHealRotation(current_member, member_fail, target_fail)) { + c->Message(m_fail, "%s", BotDatabase::fail::SaveHealRotation()); + return; + } + if (member_fail) + c->Message(m_fail, "Failed to save heal rotation members"); + if (target_fail) + c->Message(m_fail, "Failed to save heal rotation targets"); + + c->Message(m_action, "Succeeded in saving %s's heal rotation", current_member->GetCleanName()); +} + +void bot_subcommand_heal_rotation_set_hot(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_set_hot", sep->arg[0], "healrotationsethot")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: () %s [heal_override_target_name] ([member_name])", sep->arg[0]); + return; + } + + std::list sbl; + MyBots::PopulateSBL_ByNamedBot(c, sbl, sep->arg[2]); + if (sbl.empty()) + MyBots::PopulateSBL_ByTargetedBot(c, sbl); + if (sbl.empty()) { + c->Message(m_fail, "You must or [name] a current member as a bot that you own to use this command"); + return; + } + + auto current_member = sbl.front(); + if (!current_member) { + c->Message(m_unknown, "Error: Current member bot dereferenced to nullptr"); + return; + } + + if (!current_member->IsHealRotationMember()) { + c->Message(m_fail, "%s is not a member of a Heal Rotation", current_member->GetCleanName()); + return; + } + + auto hot_target = entity_list.GetMob(sep->arg[1]); + if (!hot_target) { + c->Message(m_fail, "No target exists by the name '%s'", sep->arg[1]); + return; + } + + if (!(*current_member->MemberOfHealRotation())->IsTargetInPool(hot_target)) { + c->Message(m_fail, "%s is not a target in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName()); + return; + } + + if (!(*current_member->MemberOfHealRotation())->SetHOTTarget(hot_target)) { + c->Message(m_fail, "Failed to set %s as the HOT in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName()); + return; + } + + c->Message(m_action, "Succeeded in setting %s as the HOT in %s's Heal Rotation", hot_target->GetCleanName(), current_member->GetCleanName()); +} + void bot_subcommand_heal_rotation_start(Client *c, const Seperator *sep) { if (helper_command_alias_fail(c, "bot_subcommand_heal_rotation_start", sep->arg[0], "healrotationstart")) diff --git a/zone/bot_command.h b/zone/bot_command.h index bc8558ff1..6c7d66a9c 100644 --- a/zone/bot_command.h +++ b/zone/bot_command.h @@ -633,13 +633,17 @@ void bot_subcommand_heal_rotation_adjust_critical(Client *c, const Seperator *se void bot_subcommand_heal_rotation_adjust_safe(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_casting_override(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_change_interval(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_clear_hot(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_clear_targets(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_create(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_delete(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_fast_heals(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_list(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_remove_member(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_remove_target(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_reset_limits(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_save(Client *c, const Seperator *sep); +void bot_subcommand_heal_rotation_set_hot(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_start(Client *c, const Seperator *sep); void bot_subcommand_heal_rotation_stop(Client *c, const Seperator *sep); void bot_subcommand_inventory_give(Client *c, const Seperator *sep); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 922259cab..f8ab5c3d2 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -2407,6 +2407,284 @@ bool BotDatabase::LoadGroupedBotsByGroupID(const uint32 group_id, std::list& member_list, std::list& target_list, bool& load_flag, bool& member_fail, bool& target_fail) +{ + if (!hr_member) + return false; + + uint32 hr_index = 0; + if (!LoadHealRotationIDByBotID(hr_member->GetBotID(), hr_index)) + return false; + if (!hr_index) + return true; + + if (!hr_member->IsHealRotationMember()) + return false; + + query = StringFormat( + "SELECT " + " `interval`," + " `fast_heals`," + " `adaptive_targeting`," + " `casting_override`," + " `safe_hp_base`," + " `safe_hp_cloth`," + " `safe_hp_leather`," + " `safe_hp_chain`," + " `safe_hp_plate`," + " `critical_hp_base`," + " `critical_hp_cloth`," + " `critical_hp_leather`," + " `critical_hp_chain`," + " `critical_hp_plate`" + " FROM `bot_heal_rotations`" + " WHERE `heal_rotation_index` = '%u'" + " LIMIT 1", + hr_index + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + auto row = results.begin(); + (*hr_member->MemberOfHealRotation())->SetIntervalS((uint32)atoi(row[0])); + (*hr_member->MemberOfHealRotation())->SetFastHeals((bool)atoi(row[1])); + (*hr_member->MemberOfHealRotation())->SetAdaptiveTargeting((bool)atoi(row[2])); + (*hr_member->MemberOfHealRotation())->SetCastingOverride((bool)atoi(row[3])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_UNKNOWN, atof(row[4])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_CLOTH, atof(row[5])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_LEATHER, atof(row[6])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_CHAIN, atof(row[7])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeSafeHPRatio(ARMOR_TYPE_PLATE, atof(row[8])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_UNKNOWN, atof(row[9])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_CLOTH, atof(row[10])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_LEATHER, atof(row[11])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_CHAIN, atof(row[12])); + (*hr_member->MemberOfHealRotation())->SetArmorTypeCriticalHPRatio(ARMOR_TYPE_PLATE, atof(row[13])); + + load_flag = true; + + if (!LoadHealRotationMembers(hr_index, member_list)) + member_fail = true; + + if (!LoadHealRotationTargets(hr_index, target_list)) + target_fail = true; + + return true; +} + +bool BotDatabase::LoadHealRotationMembers(const uint32 hr_index, std::list& member_list) +{ + if (!hr_index) + return false; + + query = StringFormat("SELECT `bot_id` FROM `bot_heal_rotation_members` WHERE `heal_rotation_index` = '%u'", hr_index); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + for (auto row : results) { + if (row[0]) + member_list.push_back(atoi(row[0])); + } + + return true; +} + +bool BotDatabase::LoadHealRotationTargets(const uint32 hr_index, std::list& target_list) +{ + if (!hr_index) + return false; + + query = StringFormat("SELECT `target_name` FROM `bot_heal_rotation_targets` WHERE `heal_rotation_index` = '%u'", hr_index); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + if (!results.RowCount()) + return true; + + for (auto row : results) { + if (row[0]) + target_list.push_back(row[0]); + } + + return true; +} + +bool BotDatabase::SaveHealRotation(Bot* hr_member, bool& member_fail, bool& target_fail) +{ + if (!hr_member) + return false; + + if (!DeleteHealRotation(hr_member->GetBotID())) + return false; + + if (!hr_member->IsHealRotationMember()) + return false; + + query = StringFormat( + "INSERT INTO `bot_heal_rotations` (" + "`bot_id`," + " `interval`," + " `fast_heals`," + " `adaptive_targeting`," + " `casting_override`," + " `safe_hp_base`," + " `safe_hp_cloth`," + " `safe_hp_leather`," + " `safe_hp_chain`," + " `safe_hp_plate`," + " `critical_hp_base`," + " `critical_hp_cloth`," + " `critical_hp_leather`," + " `critical_hp_chain`," + " `critical_hp_plate`" + ")" + " VALUES (" + "'%u'," + " '%u'," + " '%u'," + " '%u'," + " '%u'," + " '%f'," + " '%f'," + " '%f'," + " '%f'," + " '%f'," + " '%f'," + " '%f'," + " '%f'," + " '%f'," + " '%f'" + ")", + hr_member->GetBotID(), + ((*hr_member->MemberOfHealRotation())->IntervalS()), + ((*hr_member->MemberOfHealRotation())->FastHeals()), + ((*hr_member->MemberOfHealRotation())->AdaptiveTargeting()), + ((*hr_member->MemberOfHealRotation())->CastingOverride()), + ((*hr_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_UNKNOWN)), + ((*hr_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_CLOTH)), + ((*hr_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_LEATHER)), + ((*hr_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_CHAIN)), + ((*hr_member->MemberOfHealRotation())->ArmorTypeSafeHPRatio(ARMOR_TYPE_PLATE)), + ((*hr_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_UNKNOWN)), + ((*hr_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_CLOTH)), + ((*hr_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_LEATHER)), + ((*hr_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_CHAIN)), + ((*hr_member->MemberOfHealRotation())->ArmorTypeCriticalHPRatio(ARMOR_TYPE_PLATE)) + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + uint32 hr_index = results.LastInsertedID(); + if (!hr_index) + return false; + + std::list* member_list = (*hr_member->MemberOfHealRotation())->MemberList(); + + for (auto member_iter : *member_list) { + if (!member_iter) + continue; + + query = StringFormat("INSERT INTO `bot_heal_rotation_members` (`heal_rotation_index`, `bot_id`) VALUES ('%u', '%u')", hr_index, member_iter->GetBotID()); + auto results = QueryDatabase(query); + if (!results.Success()) { + member_fail = true; + break; + } + } + + std::list* target_list = (*hr_member->MemberOfHealRotation())->TargetList(); + + for (auto target_iter : *target_list) { + if (!target_iter) + continue; + + query = StringFormat("INSERT INTO `bot_heal_rotation_targets` (`heal_rotation_index`, `target_name`) VALUES ('%u', '%s')", hr_index, target_iter->GetCleanName()); + auto results = QueryDatabase(query); + if (!results.Success()) { + target_fail = true; + break; + } + } + + return true; +} + +bool BotDatabase::DeleteHealRotation(const uint32 creator_id) +{ + if (!creator_id) + return false; + + uint32 hr_index = 0; + if (!LoadHealRotationIDByBotID(creator_id, hr_index)) + return false; + if (!hr_index) + return true; + + query = StringFormat("DELETE FROM `bot_heal_rotation_targets` WHERE `heal_rotation_index` = '%u'", hr_index); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + query = StringFormat("DELETE FROM `bot_heal_rotation_members` WHERE `heal_rotation_index` = '%u'", hr_index); + results = QueryDatabase(query); + if (!results.Success()) + return false; + + query = StringFormat("DELETE FROM `bot_heal_rotations` WHERE `heal_rotation_index` = '%u'", hr_index); + results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + +bool BotDatabase::DeleteAllHealRotations(const uint32 owner_id) +{ + if (!owner_id) + return false; + + query = StringFormat("SELECT `bot_id` FROM `bot_heal_rotations` WHERE `bot_id` IN (SELECT `bot_id` FROM `bot_data` WHERE `owner_id` = '%u')", owner_id); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + for (auto row : results) { + if (!row[0]) + continue; + + DeleteHealRotation(atoi(row[0])); + } + + return true; +} + + /* Bot miscellaneous functions */ @@ -2495,6 +2773,15 @@ const char* BotDatabase::fail::LoadBotGroupsListByOwnerID() { return "Failed to /* fail::Bot group functions */ const char* BotDatabase::fail::LoadGroupedBotsByGroupID() { return "Failed to load grouped bots by group id"; } +/* fail::Bot heal rotation functions */ +const char* BotDatabase::fail::LoadHealRotationIDByBotID() { return "Failed to load heal rotation id by bot id"; } +const char* BotDatabase::fail::LoadHealRotation() { return "Failed to load heal rotation"; } +const char* BotDatabase::fail::LoadHealRotationMembers() { return "Failed to load heal rotation members"; } +const char* BotDatabase::fail::LoadHealRotationTargets() { return "Failed to load heal rotation targets"; } +const char* BotDatabase::fail::SaveHealRotation() { return "Failed to save heal rotation"; } +const char* BotDatabase::fail::DeleteHealRotation() { return "Failed to delete heal rotation"; } +const char* BotDatabase::fail::DeleteAllHealRotations() { return "Failed to delete all heal rotations"; } + /* fail::Bot miscellaneous functions */ #endif // BOTS diff --git a/zone/bot_database.h b/zone/bot_database.h index 27d4b4116..5ade661c2 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -167,6 +167,17 @@ public: bool LoadGroupedBotsByGroupID(const uint32 group_id, std::list& group_list); + /* Bot heal rotation functions */ + bool LoadHealRotationIDByBotID(const uint32 bot_id, uint32& hr_index); + + bool LoadHealRotation(Bot* hr_member, std::list& member_list, std::list& target_list, bool& load_flag, bool& member_fail, bool& target_fail); + bool LoadHealRotationMembers(const uint32 hr_index, std::list& member_list); + bool LoadHealRotationTargets(const uint32 hr_index, std::list& target_list); + bool SaveHealRotation(Bot* hr_member, bool& member_fail, bool& target_fail); + bool DeleteHealRotation(const uint32 creator_id); + + bool DeleteAllHealRotations(const uint32 owner_id); + /* Bot miscellaneous functions */ @@ -257,6 +268,15 @@ public: /* fail::Bot group functions */ static const char* LoadGroupedBotsByGroupID(); + /* fail::Bot heal rotation functions */ + static const char* LoadHealRotationIDByBotID(); + static const char* LoadHealRotation(); + static const char* LoadHealRotationMembers(); + static const char* LoadHealRotationTargets(); + static const char* SaveHealRotation(); + static const char* DeleteHealRotation(); + static const char* DeleteAllHealRotations(); + /* fail::Bot miscellaneous functions */ }; diff --git a/zone/heal_rotation.cpp b/zone/heal_rotation.cpp index 4e22e5188..6981cc0c1 100644 --- a/zone/heal_rotation.cpp +++ b/zone/heal_rotation.cpp @@ -25,10 +25,10 @@ #define SAFE_HP_RATIO_CHAIN 80.0f #define SAFE_HP_RATIO_PLATE 75.0f -#define CRITICAL_HP_RATIO_CLOTH 30.0f -#define CRITICAL_HP_RATIO_LEATHER 25.0f -#define CRITICAL_HP_RATIO_CHAIN 15.0f -#define CRITICAL_HP_RATIO_PLATE 10.0f +#define CRITICAL_HP_RATIO_CLOTH 45.0f +#define CRITICAL_HP_RATIO_LEATHER 40.0f +#define CRITICAL_HP_RATIO_CHAIN 35.0f +#define CRITICAL_HP_RATIO_PLATE 30.0f HealRotation::HealRotation(Bot* hr_creator, uint32 interval_ms, bool fast_heals, bool adaptive_targeting, bool casting_override) { @@ -51,6 +51,9 @@ HealRotation::HealRotation(Bot* hr_creator, uint32 interval_ms, bool fast_heals, m_is_active = false; m_consumed = false; + + m_hot_target = nullptr; + m_hot_active = false; } void HealRotation::SetIntervalMS(uint32 interval_ms) @@ -143,6 +146,11 @@ bool HealRotation::RemoveTargetFromPool(Mob* hr_target) if (target_iter != hr_target) continue; + if (m_hot_target == hr_target) { + m_hot_target = nullptr; + m_hot_active = false; + } + m_target_healing_stats_2.erase(hr_target); m_target_healing_stats_1.erase(hr_target); m_target_pool.remove(hr_target); @@ -172,6 +180,8 @@ bool HealRotation::ClearMemberPool() bool HealRotation::ClearTargetPool() { + m_hot_target = nullptr; + m_hot_active = false; m_is_active = false; auto clear_list = m_target_pool; @@ -184,11 +194,32 @@ bool HealRotation::ClearTargetPool() return m_target_pool.empty(); } +bool HealRotation::SetHOTTarget(Mob* hot_target) +{ + if (!hot_target || !IsTargetInPool(hot_target)) + return false; + + m_hot_target = hot_target; + m_hot_active = true; + + return true; +} + +bool HealRotation::ClearHOTTarget() +{ + m_hot_target = nullptr; + m_hot_active = false; + + return true; +} + bool HealRotation::Start() { m_is_active = false; - if (m_member_pool.empty() || m_target_pool.empty()) + if (m_member_pool.empty() || m_target_pool.empty()) { + validate_hot(); return false; + } m_cycle_pool = m_member_pool; m_is_active = true; @@ -207,7 +238,7 @@ bool HealRotation::Stop() Bot* HealRotation::CastingMember() { - if (!m_is_active) + if (!m_is_active && !m_hot_active) return nullptr; if (m_cycle_pool.empty()) { @@ -222,6 +253,9 @@ Bot* HealRotation::CastingMember() bool HealRotation::PokeCastingTarget() { + if (m_hot_target && m_hot_active) + return true; + if (!m_is_active) return false; @@ -248,6 +282,9 @@ bool HealRotation::PokeCastingTarget() Mob* HealRotation::CastingTarget() { + if (m_hot_target && m_hot_active) + return m_hot_target; + if (!m_is_active) return nullptr; if (!m_active_heal_target) @@ -304,6 +341,16 @@ bool HealRotation::IsTargetInPool(Mob* hr_target) return false; } +bool HealRotation::IsHOTTarget(Mob* hot_target) +{ + if (!hot_target) + return false; + if (m_hot_target != hot_target) + return false; + + return true; +} + void HealRotation::SetMemberIsCasting(Bot* hr_member, bool flag) { if (!hr_member) @@ -444,7 +491,7 @@ bool HealRotation::SetArmorTypeSafeHPRatio(uint8 armor_type, float hp_ratio) { if (armor_type >= ARMOR_TYPE_COUNT) return false; - if (hp_ratio < CRITICAL_HP_RATIO_BASE || hp_ratio > SAFE_HP_RATIO_BASE) + if (hp_ratio < CRITICAL_HP_RATIO_ABS || hp_ratio > SAFE_HP_RATIO_ABS) return false; if (hp_ratio < m_critical_hp_ratio[armor_type]) return false; @@ -458,7 +505,7 @@ bool HealRotation::SetArmorTypeCriticalHPRatio(uint8 armor_type, float hp_ratio) { if (armor_type >= ARMOR_TYPE_COUNT) return false; - if (hp_ratio < CRITICAL_HP_RATIO_BASE || hp_ratio > SAFE_HP_RATIO_BASE) + if (hp_ratio < CRITICAL_HP_RATIO_ABS || hp_ratio > SAFE_HP_RATIO_ABS) return false; if (hp_ratio > m_safe_hp_ratio[armor_type]) return false; @@ -863,6 +910,19 @@ void HealRotation::bias_targets() #endif } +void HealRotation::validate_hot() +{ + if (!m_hot_target) { + m_hot_active = false; + return; + } + + if (!IsTargetInPool(m_hot_target)) { + m_hot_target = nullptr; + m_hot_active = false; + } +} + bool IsHealRotationMemberClass(uint8 class_id) { switch (class_id) { diff --git a/zone/heal_rotation.h b/zone/heal_rotation.h index 4b7426623..19a3f8311 100644 --- a/zone/heal_rotation.h +++ b/zone/heal_rotation.h @@ -35,8 +35,11 @@ #define HEALING_STATS_RESET_INTERVAL 60000 #define HEALING_STATS_RESET_INTERVAL_S 60 +#define SAFE_HP_RATIO_ABS 100.0f #define SAFE_HP_RATIO_BASE 95.0f -#define CRITICAL_HP_RATIO_BASE 10.0f + +#define CRITICAL_HP_RATIO_ABS 0.0f +#define CRITICAL_HP_RATIO_BASE 30.0f struct HealingStats { @@ -49,7 +52,7 @@ class HealRotation { public: HealRotation(Bot* hr_creator, uint32 interval_ms = CASTING_CYCLE_DEFAULT_INTERVAL, bool fast_heals = false, bool adaptive_targeting = false, bool casting_override = false); - HealRotation(HealRotation* allocator_shunt) {}; + HealRotation(HealRotation* allocator_shunt) {}; // use should be limited to the shared_ptr memory allocation call void SetIntervalMS(uint32 interval_ms); void SetIntervalS(uint32 interval_s); @@ -72,10 +75,15 @@ public: bool ClearMemberPool(); bool ClearTargetPool(); + Mob* HOTTarget() { return m_hot_target; } + bool SetHOTTarget(Mob* hot_target); + bool ClearHOTTarget(); + bool Start(); bool Stop(); bool IsActive() { return m_is_active; } + bool IsHOTActive() { return m_hot_active; } bool CastingReady() { return (Timer::GetCurrentTime() >= m_next_cast_time_ms); } Bot* CastingMember(); bool PokeCastingTarget(); @@ -88,6 +96,7 @@ public: bool IsMemberInPool(Bot* hr_member); bool IsTargetInPool(Mob* hr_target); + bool IsHOTTarget(Mob* hot_target); void SetMemberIsCasting(Bot* hr_member, bool flag = true); bool MemberIsCasting(Bot* hr_member); @@ -114,6 +123,7 @@ private: void cycle_refresh(); bool healable_target(bool use_class_at = true, bool critical_only = false); void bias_targets(); + void validate_hot(); uint32 m_creation_time_ms; uint32 m_last_heal_time_ms; @@ -131,6 +141,9 @@ private: bool m_consumed; + Mob* m_hot_target; + bool m_hot_active; + std::list m_member_pool; std::list m_cycle_pool; std::list m_target_pool; From a5119d1a9f991570cf8f584ad8a455aadf8298da Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 11 Apr 2016 14:29:45 -0500 Subject: [PATCH 039/693] Remove some instances of std::cerr --- common/database.cpp | 5 ++++- zone/client_packet.cpp | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 36b8237e5..525247131 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -313,7 +313,10 @@ bool Database::DeleteCharacter(char *name) { std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", name); auto results = QueryDatabase(query); for (auto row = results.begin(); row != results.end(); ++row) { charid = atoi(row[0]); } - if (charid <= 0){ std::cerr << "Database::DeleteCharacter :: Character not found, stopping delete...\n"; return false; } + if (charid <= 0){ + Log.Out(Logs::General, Logs::Error, "Database::DeleteCharacter :: Character (%s) not found, stopping delete...", name); + return false; + } query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", charid); QueryDatabase(query); query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", charid); QueryDatabase(query); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 3bc9622e1..a47903177 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -12722,7 +12722,7 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app) } else { - std::cerr << "Client " << name << " unknown apperance " << (int)sa->parameter << std::endl; + Log.Out(Logs::Detail, Logs::Error, "Client %s :: unknown appearance %i", name, (int)sa->parameter); return; } @@ -12744,7 +12744,7 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app) m_pp.anon = 0; } else { - std::cerr << "Client " << name << " unknown Anon/Roleplay Switch " << (int)sa->parameter << std::endl; + Log.Out(Logs::Detail, Logs::Error, "Client %s :: unknown Anon/Roleplay Switch %i", name, (int)sa->parameter); return; } entity_list.QueueClients(this, app, true); From daeec0f5ec533986e5f026f45d485361a48f2160 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 11 Apr 2016 16:51:30 -0400 Subject: [PATCH 040/693] Rework of some existing spell AI code --- zone/botspellsai.cpp | 17 ++++++++++++-- zone/merc.cpp | 14 ++++++++--- zone/mob_ai.cpp | 55 ++++++++++++++++++++++---------------------- 3 files changed, 53 insertions(+), 33 deletions(-) diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 46d10c36f..f19808d74 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -21,6 +21,14 @@ #include "bot.h" #include "../common/string_util.h" +#if EQDEBUG >= 12 + #define BotAI_DEBUG_Spells 25 +#elif EQDEBUG >= 9 + #define BotAI_DEBUG_Spells 10 +#else + #define BotAI_DEBUG_Spells -1 +#endif + bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { if (!tar) { @@ -995,8 +1003,8 @@ bool Bot::AI_IdleCastCheck() { bool result = false; if (AIautocastspell_timer->Check(false)) { -#if MobAI_DEBUG_Spells >= 25 - std::cout << "Non-Engaged autocast check triggered: " << this->GetCleanName() << std::endl; // cout undefine [CODEBUG] +#if BotAI_DEBUG_Spells >= 25 + Log.Out(Logs::Detail, Logs::AI, "Bot Non-Engaged autocast check triggered: %s", this->GetCleanName()); #endif AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. @@ -1320,6 +1328,11 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { } } +#if BotAI_DEBUG_Spells >= 10 + Log.Out(Logs::Detail, Logs::AI, "Bot::AIHealRotation: heal spellid = %u, fastheals = %c, casterlevel = %u", + botSpell.SpellId, ((useFastHeals) ? ('T') : ('F')), GetLevel()); +#endif + // If there is still no spell id, then there isn't going to be one so we are done if (botSpell.SpellId == 0) return false; diff --git a/zone/merc.cpp b/zone/merc.cpp index 1379bc697..19d846280 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -20,6 +20,14 @@ extern volatile bool is_zone_loaded; +#if EQDEBUG >= 12 + #define MercAI_DEBUG_Spells 25 +#elif EQDEBUG >= 9 + #define MercAI_DEBUG_Spells 10 +#else + #define MercAI_DEBUG_Spells -1 +#endif + Merc::Merc(const NPCType* d, float x, float y, float z, float heading) : NPC(d, nullptr, glm::vec4(x, y, z, heading), 0, false), endupkeep_timer(1000), rest_timer(1), confidence_timer(6000), check_target_timer(2000) { @@ -1768,7 +1776,7 @@ bool Merc::AI_EngagedCastCheck() { { AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - Log.Out(Logs::Detail, Logs::AI, "Engaged autocast check triggered (MERCS)."); + Log.Out(Logs::Detail, Logs::AI, "Merc Engaged autocast check triggered"); int8 mercClass = GetClass(); @@ -1822,8 +1830,8 @@ bool Merc::AI_IdleCastCheck() { bool failedToCast = false; if (AIautocastspell_timer->Check(false)) { -#if MobAI_DEBUG_Spells >= 25 - std::cout << "Non-Engaged autocast check triggered: " << this->GetCleanName() << std::endl; +#if MercAI_DEBUG_Spells >= 25 + Log.Out(Logs::Detail, Logs::AI, "Merc Non-Engaged autocast check triggered: %s", this->GetCleanName()); #endif AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 70f64b7a7..5d0493c62 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -38,8 +38,10 @@ extern EntityList entity_list; extern Zone *zone; -#ifdef _EQDEBUG - #define MobAI_DEBUG_Spells -1 +#if EQDEBUG >= 12 + #define MobAI_DEBUG_Spells 25 +#elif EQDEBUG >= 9 + #define MobAI_DEBUG_Spells 10 #else #define MobAI_DEBUG_Spells -1 #endif @@ -97,12 +99,8 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { ) { #if MobAI_DEBUG_Spells >= 21 - std::cout << "Mob::AICastSpell: Casting: spellid=" << AIspells[i].spellid - << ", tar=" << tar->GetName() - << ", dist2[" << dist2 << "]<=" << spells[AIspells[i].spellid].range *spells[AIspells[i].spellid].range - << ", mana_cost[" << mana_cost << "]<=" << GetMana() - << ", cancast[" << AIspells[i].time_cancast << "]<=" << Timer::GetCurrentTime() - << ", type=" << AIspells[i].type << std::endl; + Log.Out(Logs::Detail, Logs::AI, "Mob::AICastSpell: Casting: spellid=%u, tar=%s, dist2[%f]<=%f, mana_cost[%i]<=%i, cancast[%u]<=%u, type=%u", + AIspells[i].spellid, tar->GetName(), dist2, (spells[AIspells[i].spellid].range * spells[AIspells[i].spellid].range), mana_cost, GetMana(), AIspells[i].time_cancast, Timer::GetCurrentTime(), AIspells[i].type); #endif switch (AIspells[i].type) { @@ -323,7 +321,8 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { } #if MobAI_DEBUG_Spells >= 21 else { - std::cout << "Mob::AICastSpell: NotCasting: spellid=" << AIspells[i].spellid << ", tar=" << tar->GetName() << ", dist2[" << dist2 << "]<=" << spells[AIspells[i].spellid].range*spells[AIspells[i].spellid].range << ", mana_cost[" << mana_cost << "]<=" << GetMana() << ", cancast[" << AIspells[i].time_cancast << "]<=" << Timer::GetCurrentTime() << std::endl; + Log.Out(Logs::Detail, Logs::AI, "Mob::AICastSpell: NotCasting: spellid=%u, tar=%s, dist2[%f]<=%f, mana_cost[%i]<=%i, cancast[%u]<=%u, type=%u", + AIspells[i].spellid, tar->GetName(), dist2, (spells[AIspells[i].spellid].range * spells[AIspells[i].spellid].range), mana_cost, GetMana(), AIspells[i].time_cancast, Timer::GetCurrentTime(), AIspells[i].type); } #endif } @@ -333,7 +332,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore) { #if MobAI_DEBUG_Spells >= 1 - std::cout << "Mob::AIDoSpellCast: spellid=" << AIspells[i].spellid << ", tar=" << tar->GetName() << ", mana=" << mana_cost << ", Name: " << spells[AIspells[i].spellid].name << std::endl; + Log.Out(Logs::Detail, Logs::AI, "Mob::AIDoSpellCast: spellid = %u, tar = %s, mana = %i, Name: '%s'", AIspells[i].spellid, tar->GetName(), mana_cost, spells[AIspells[i].spellid].name); #endif casting_spell_AIindex = i; @@ -2252,20 +2251,20 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { DBnpcspells_Struct* parentlist = database.GetNPCSpells(spell_list->parent_list); uint32 i; #if MobAI_DEBUG_Spells >= 10 - std::cout << "Loading NPCSpells onto " << this->GetName() << ": dbspellsid=" << iDBSpellsID; + std::string debug_msg = StringFormat("Loading NPCSpells onto %s: dbspellsid=%u", this->GetName(), iDBSpellsID); if (spell_list) { - std::cout << " (found, " << spell_list->numentries << "), parentlist=" << spell_list->parent_list; + debug_msg.append(StringFormat(" (found, %u), parentlist=%u", spell_list->numentries, spell_list->parent_list)); if (spell_list->parent_list) { - if (parentlist) { - std::cout << " (found, " << parentlist->numentries << ")"; - } + if (parentlist) + debug_msg.append(StringFormat(" (found, %u)", parentlist->numentries)); else - std::cout << " (not found)"; + debug_msg.append(" (not found)"); } } - else - std::cout << " (not found)"; - std::cout << std::endl; + else { + debug_msg.append(" (not found)"); + } + Log.Out(Logs::Detail, Logs::AI, "%s", debug_msg.c_str()); #endif uint16 attack_proc_spell = -1; int8 proc_chance = 3; @@ -2412,20 +2411,20 @@ bool NPC::AI_AddNPCSpellsEffects(uint32 iDBSpellsEffectsID) { uint32 i; #if MobAI_DEBUG_Spells >= 10 - std::cout << "Loading NPCSpellsEffects onto " << this->GetName() << ": dbspellseffectsid=" << iDBSpellsEffectsID; + std::string debug_msg = StringFormat("Loading NPCSpellsEffects onto %s: dbspellseffectid=%u", this->GetName(), iDBSpellsEffectsID); if (spell_effects_list) { - std::cout << " (found, " << spell_effects_list->numentries << "), parentlist=" << spell_effects)list->parent_list; + debug_msg.append(StringFormat(" (found, %u), parentlist=%u", spell_effects_list->numentries, spell_effects_list->parent_list)); if (spell_effects_list->parent_list) { - if (parentlist) { - std::cout << " (found, " << parentlist->numentries << ")"; - } + if (parentlist) + debug_msg.append(StringFormat(" (found, %u)", parentlist->numentries)); else - std::cout << " (not found)"; + debug_msg.append(" (not found)"); } } - else - std::cout << " (not found)"; - std::cout << std::endl; + else { + debug_msg.append(" (not found)"); + } + Log.Out(Logs::Detail, Logs::AI, "%s", debug_msg.c_str()); #endif if (parentlist) { From 89f46144e657c987587379cb1d2892e2f1be94d3 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 11 Apr 2016 23:08:27 -0400 Subject: [PATCH 041/693] Fix for BotDatabase::LoadBotGroupIDForLoadBotGroup() failures when more than one bot-group exists and requested bg is not primary in retrieval order --- zone/bot.cpp | 1 + zone/bot_database.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 02a749f57..ed33fe8e8 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -6228,6 +6228,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 if((spelltypeequal || spelltypetargetequal) || spelltypeclassequal || slotequal) { if(((spells[thespell].effectid[0] == 0) && (spells[thespell].base[0] < 0)) && (spellTarget->GetHP() < ((spells[thespell].base[0] * (-1)) + 100))) { + Log.Out(Logs::General, Logs::Spells, "Bot::DoFinishedSpellSingleTarget - GroupBuffing failure"); return false; } diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index f8ab5c3d2..c9c5b594d 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -2322,7 +2322,7 @@ bool BotDatabase::LoadBotGroupIDForLoadBotGroup(const uint32 owner_id, const std if (!owner_id || group_name.empty()) return false; - query = StringFormat("SELECT `groups_index`, `group_name` FROM `vw_bot_groups` WHERE `owner_id` = '%u' LIMIT 1", owner_id); + query = StringFormat("SELECT `groups_index`, `group_name` FROM `vw_bot_groups` WHERE `owner_id` = '%u'", owner_id); auto results = QueryDatabase(query); if (!results.Success()) return false; From 700e80182140f4e2fbf5f4f20764e23b0c4a5c25 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 12 Apr 2016 13:42:28 -0400 Subject: [PATCH 042/693] Fix mismatched delete in QueryServ --- queryserv/database.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/queryserv/database.cpp b/queryserv/database.cpp index ea5bdff65..2e86c449f 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -361,7 +361,7 @@ void Database::GeneralQueryReceive(ServerPacket *pack) { } safe_delete(pack); - safe_delete(queryBuffer); + safe_delete_array(queryBuffer); } void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings){ @@ -404,4 +404,4 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings){ Log.file_logs_enabled = true; } } -} \ No newline at end of file +} From 3ef98c941155e1aa5b55ed95cf1940502e26d126 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 12 Apr 2016 16:46:45 -0400 Subject: [PATCH 043/693] Added bot command 'inventorywindow' --- common/version.h | 2 +- .../sql/git/bots/bots_db_update_manifest.txt | 1 + .../2016_04_12_bots_inventory_window.sql | 2 + zone/bot_command.cpp | 61 ++++++++++++++++++- zone/bot_command.h | 1 + zone/botspellsai.cpp | 3 + 6 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 utils/sql/git/bots/required/2016_04_12_bots_inventory_window.sql diff --git a/common/version.h b/common/version.h index bebd65ade..e5a4e6322 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9096 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9005 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9006 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 08ef5f161..0bfabf0ff 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -4,6 +4,7 @@ 9003|2016_04_05_bots_pet_spell_id_field.sql|SHOW COLUMNS FROM `bot_pets` LIKE 'pet_id'|not_empty| 9004|2016_04_07_bots_heal_override_target.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'healrotationclearhot'|empty| 9005|2016_04_08_bots_heal_rotations.sql|SHOW TABLES LIKE 'bot_heal_rotations'|empty| +9006|2016_04_12_bots_inventory_window.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'inventorywindow'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2016_04_12_bots_inventory_window.sql b/utils/sql/git/bots/required/2016_04_12_bots_inventory_window.sql new file mode 100644 index 000000000..b0269559d --- /dev/null +++ b/utils/sql/git/bots/required/2016_04_12_bots_inventory_window.sql @@ -0,0 +1,2 @@ +INSERT INTO `bot_command_settings` VALUES +('inventorywindow', 0, 'invwindow'); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 5422c41ab..3553f7e8d 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -1390,6 +1390,7 @@ int bot_command_init(void) bot_command_add("inventorygive", "Gives the item on your cursor to a bot", 0, bot_subcommand_inventory_give) || bot_command_add("inventorylist", "Lists all items in a bot's inventory", 0, bot_subcommand_inventory_list) || bot_command_add("inventoryremove", "Removes an item from a bot's inventory", 0, bot_subcommand_inventory_remove) || + bot_command_add("inventorywindow", "Displays all items in a bot's inventory in a pop-up window", 0, bot_subcommand_inventory_window) || bot_command_add("invisibility", "Orders a bot to cast a cloak of invisibility, or allow them to be seen", 0, bot_command_invisibility) || bot_command_add("levitation", "Orders a bot to cast a levitation spell", 0, bot_command_levitation) || bot_command_add("lull", "Orders a bot to cast a pacification spell", 0, bot_command_lull) || @@ -3199,10 +3200,11 @@ void bot_command_inventory(Client *c, const Seperator *sep) subcommand_list.push_back("inventorygive"); subcommand_list.push_back("inventorylist"); subcommand_list.push_back("inventoryremove"); + subcommand_list.push_back("inventorywindow"); /* VS2012 code - end */ /* VS2013 code - const std::list subcommand_list = { "inventorygive", "inventorylist", "inventoryremove" }; + const std::list subcommand_list = { "inventorygive", "inventorylist", "inventoryremove", "inventorywindow" }; */ if (helper_command_alias_fail(c, "bot_command_inventory", sep->arg[0], "inventory")) @@ -7203,6 +7205,63 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) } } +void bot_subcommand_inventory_window(Client *c, const Seperator *sep) +{ + if (helper_command_alias_fail(c, "bot_subcommand_inventory_window", sep->arg[0], "inventorywindow")) + return; + if (helper_is_help_or_usage(sep->arg[1])) { + c->Message(m_usage, "usage: %s [actionable: target]", sep->arg[0]); + return; + } + int ab_mask = ActionableBots::ABM_Target; + + std::list sbl; + if (ActionableBots::PopulateSBL(c, sep->arg[1], sbl, ab_mask, sep->arg[2]) == ActionableBots::ABT_None) + return; + + auto my_bot = sbl.front(); + if (!my_bot) { + c->Message(m_unknown, "ActionableBots returned 'nullptr'"); + return; + } + + std::string window_title = my_bot->GetCleanName(); + window_title.append("`s Inventory"); + + std::string window_text; + //std::string item_link; + //Client::TextLink linker; + //linker.SetLinkType(linker.linkItemInst); + + for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= (EQEmu::Constants::EQUIPMENT_END + 1); ++i) { + const Item_Struct* item = nullptr; + const ItemInst* inst = my_bot->CastToBot()->GetBotItem(i == 22 ? SlotPowerSource : i); + if (inst) + item = inst->GetItem(); + + window_text.append(""); + window_text.append(GetBotEquipSlotName(i == 22 ? SlotPowerSource : i)); + window_text.append(": "); + if (item) { + //window_text.append(""); + //linker.SetItemInst(inst); + //item_link = linker.GenerateLink(); + //window_text.append(item_link.c_str()); + + window_text.append(""); + window_text.append(StringFormat("%s", item->Name)); + } + else { + window_text.append(""); + window_text.append("[empty]"); + } + window_text.append("
"); + } + window_text.append("
"); + + c->SendPopupToClient(window_title.c_str(), window_text.c_str()); +} + void bot_subcommand_pet_remove(Client *c, const Seperator *sep) { if (helper_command_alias_fail(c, "bot_subcommand_pet_remove", sep->arg[0], "petremove")) diff --git a/zone/bot_command.h b/zone/bot_command.h index 6c7d66a9c..c25c7b0eb 100644 --- a/zone/bot_command.h +++ b/zone/bot_command.h @@ -649,6 +649,7 @@ void bot_subcommand_heal_rotation_stop(Client *c, const Seperator *sep); void bot_subcommand_inventory_give(Client *c, const Seperator *sep); void bot_subcommand_inventory_list(Client *c, const Seperator *sep); void bot_subcommand_inventory_remove(Client *c, const Seperator *sep); +void bot_subcommand_inventory_window(Client *c, const Seperator *sep); void bot_subcommand_pet_remove(Client *c, const Seperator *sep); void bot_subcommand_pet_set_type(Client *c, const Seperator *sep); void bot_subcommand_portal(Client *c, const Seperator *sep); diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index f19808d74..a35760535 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -1332,6 +1332,9 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { Log.Out(Logs::Detail, Logs::AI, "Bot::AIHealRotation: heal spellid = %u, fastheals = %c, casterlevel = %u", botSpell.SpellId, ((useFastHeals) ? ('T') : ('F')), GetLevel()); #endif +#if BotAI_DEBUG_Spells >= 25 + Log.Out(Logs::Detail, Logs::AI, "Bot::AIHealRotation: target = %s, current_time = %u, donthealmebefore = %u", tar->GetCleanName(), Timer::GetCurrentTime(), tar->DontHealMeBefore()); +#endif // If there is still no spell id, then there isn't going to be one so we are done if (botSpell.SpellId == 0) From 149a3c2e820b093b49fe898862f4043a6091372c Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 12 Apr 2016 18:29:09 -0400 Subject: [PATCH 044/693] Would real 'Fix for BotDatabase::LoadBotGroupIDForLoadBotGroup() failures when more than one bot-group exists and requested bg is not primary in retrieval order' please stand up.. --- zone/bot_database.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index c9c5b594d..416e0c304 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -2329,10 +2329,13 @@ bool BotDatabase::LoadBotGroupIDForLoadBotGroup(const uint32 owner_id, const std if (!results.RowCount()) return true; - auto row = results.begin(); - if (!group_name.compare(row[1])) - botgroup_id = atoi(row[0]); - + for (auto row = results.begin(); row != results.end(); ++row) { + if (!group_name.compare(row[1])) { + botgroup_id = atoi(row[0]); + break; + } + } + return true; } From 096dd21234aa3a7c6d54a03c6fdde15e640c37b6 Mon Sep 17 00:00:00 2001 From: ngdeao Date: Tue, 12 Apr 2016 21:27:59 -0600 Subject: [PATCH 045/693] Fix for RoF2 clients connecting and don't appear in the zone to others. --- zone/client_packet.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a47903177..561a0689c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1004,7 +1004,8 @@ void Client::Handle_Connect_OP_ClientError(const EQApplicationPacket *app) void Client::Handle_Connect_OP_ClientReady(const EQApplicationPacket *app) { conn_state = ClientReadyReceived; - + if (!Spawned()) + SendZoneInPackets(); CompleteConnect(); SendHPUpdate(); } From c33ccb138ff0c414c6253e4bd9907505389bf610 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 12 Apr 2016 23:49:44 -0500 Subject: [PATCH 046/693] Fix for marquee's crashing clients on zone --- zone/client.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zone/client.cpp b/zone/client.cpp index c280b825e..d07de3016 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8705,6 +8705,9 @@ void Client::SendHPUpdateMarquee(){ if (!RuleB(Character, MarqueeHPUpdates)) return; + if (!this || !this->IsClient() || !this->cur_hp || !this->max_hp) + return; + /* Health Update Marquee Display: Custom*/ uint32 health_percentage = (uint32)(this->cur_hp * 100 / this->max_hp); if (health_percentage == 100) From 1e05ee76f18e289e3eb3dd20129e796487a16e4b Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 13 Apr 2016 19:29:00 -0400 Subject: [PATCH 047/693] Fix for Bot::AI_Process() not advancing the heal rotation when member is currently casting for said heal rotation --- zone/bot.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index ed33fe8e8..d8693251a 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2211,10 +2211,16 @@ void Bot::AI_Process() { m_member_of_heal_rotation->CastingReady() && m_member_of_heal_rotation->CastingMember() == this && !m_member_of_heal_rotation->MemberIsCasting(this) - ) + ) { InterruptSpell(); - else if (botClass != BARD) + } + else if (AmICastingForHealRotation() && m_member_of_heal_rotation->CastingMember() == this) { + AdvanceHealRotation(false); return; + } + else if (botClass != BARD) { + return; + } } else if (IsHealRotationMember()) { m_member_of_heal_rotation->SetMemberIsCasting(this, false); @@ -8385,6 +8391,8 @@ bool Bot::IsMyHealRotationSet() return false; if (m_member_of_heal_rotation->CastingMember() != this) return false; + if (m_member_of_heal_rotation->MemberIsCasting(this)) + return false; if (!m_member_of_heal_rotation->PokeCastingTarget()) return false; From 3a339a66461718c622dcbedaa52aafc390ae34df Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 14 Apr 2016 08:40:11 -0400 Subject: [PATCH 048/693] EQ Dictionary rework --- common/eq_dictionary.cpp | 940 --------------------------------------- common/eq_dictionary.h | 206 --------- 2 files changed, 1146 deletions(-) delete mode 100644 common/eq_dictionary.cpp delete mode 100644 common/eq_dictionary.h diff --git a/common/eq_dictionary.cpp b/common/eq_dictionary.cpp deleted file mode 100644 index b4388b537..000000000 --- a/common/eq_dictionary.cpp +++ /dev/null @@ -1,940 +0,0 @@ -/* -EQEMu: Everquest Server Emulator - -Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "eq_dictionary.h" -#include "string_util.h" - -// -// class EQEmu::Constants -// -uint16 EQEmu::Constants::InventoryTypeSize(int16 type_index) -{ - switch (type_index) { - case TypePossessions: - return TYPE_POSSESSIONS_SIZE; - case TypeBank: - return TYPE_BANK_SIZE; - case TypeSharedBank: - return TYPE_SHARED_BANK_SIZE; - case TypeTrade: - return TYPE_TRADE_SIZE; - case TypeWorld: - return TYPE_WORLD_SIZE; - case TypeLimbo: - return TYPE_LIMBO_SIZE; - case TypeTribute: - return TYPE_TRIBUTE_SIZE; - case TypeTrophyTribute: - return TYPE_TROPHY_TRIBUTE_SIZE; - case TypeGuildTribute: - return TYPE_GUILD_TRIBUTE_SIZE; - case TypeMerchant: - return TYPE_MERCHANT_SIZE; - case TypeDeleted: - return TYPE_DELETED_SIZE; - case TypeCorpse: - return TYPE_CORPSE_SIZE; - case TypeBazaar: - return TYPE_BAZAAR_SIZE; - case TypeInspect: - return TYPE_INSPECT_SIZE; - case TypeRealEstate: - return TYPE_REAL_ESTATE_SIZE; - case TypeViewMODPC: - return TYPE_VIEW_MOD_PC_SIZE; - case TypeViewMODBank: - return TYPE_VIEW_MOD_BANK_SIZE; - case TypeViewMODSharedBank: - return TYPE_VIEW_MOD_SHARED_BANK_SIZE; - case TypeViewMODLimbo: - return TYPE_VIEW_MOD_LIMBO_SIZE; - case TypeAltStorage: - return TYPE_ALT_STORAGE_SIZE; - case TypeArchived: - return TYPE_ARCHIVED_SIZE; - case TypeMail: - return TYPE_MAIL_SIZE; - case TypeGuildTrophyTribute: - return TYPE_GUILD_TROPHY_TRIBUTE_SIZE; - case TypeKrono: - return TYPE_KRONO_SIZE; - case TypeOther: - return TYPE_OTHER_SIZE; - default: - return NOT_USED; - } -} - -/* -const char* EQEmu::Constants::InventoryLocationName(Location_Struct location) -{ - // not ready for implementation... - std::string ret_str; - StringFormat(ret_str, "%s, %s, %s, %s", InventoryMapName(location.map), InventoryMainName(location.main), InventorySubName(location.sub), InventoryAugName(location.aug)); - return ret_str; -} -*/ - -const char* EQEmu::Constants::InventoryTypeName(int16 type_index) -{ - switch (type_index) { - case INVALID_INDEX: - return "Invalid Type"; - case TypePossessions: - return "Possessions"; - case TypeBank: - return "Bank"; - case TypeSharedBank: - return "SharedBank"; - case TypeTrade: - return "Trade"; - case TypeWorld: - return "World"; - case TypeLimbo: - return "Limbo"; - case TypeTribute: - return "Tribute"; - case TypeTrophyTribute: - return "TrophyTribute"; - case TypeGuildTribute: - return "GuildTribute"; - case TypeMerchant: - return "Merchant"; - case TypeDeleted: - return "Deleted"; - case TypeCorpse: - return "Corpse"; - case TypeBazaar: - return "Bazaar"; - case TypeInspect: - return "Inspect"; - case TypeRealEstate: - return "RealEstate"; - case TypeViewMODPC: - return "ViewMODPC"; - case TypeViewMODBank: - return "ViewMODBank"; - case TypeViewMODSharedBank: - return "ViewMODSharedBank"; - case TypeViewMODLimbo: - return "ViewMODLimbo"; - case TypeAltStorage: - return "AltStorage"; - case TypeArchived: - return "Archived"; - case TypeMail: - return "Mail"; - case TypeGuildTrophyTribute: - return "GuildTrophyTribute"; - case TypeKrono: - return "Krono"; - case TypeOther: - return "Other"; - default: - return "Unknown Type"; - } -} - -const char* EQEmu::Constants::InventorySlotName(int16 slot_index) -{ - switch (slot_index) { - case INVALID_INDEX: - return "Invalid Slot"; - case SlotCharm: - return "Charm"; - case SlotEar1: - return "Ear1"; - case SlotHead: - return "Head"; - case SlotFace: - return "Face"; - case SlotEar2: - return "Ear2"; - case SlotNeck: - return "Neck"; - case SlotShoulders: - return "Shoulders"; - case SlotArms: - return "Arms"; - case SlotBack: - return "Back"; - case SlotWrist1: - return "Wrist1"; - case SlotWrist2: - return "Wrist2"; - case SlotRange: - return "Range"; - case SlotHands: - return "Hands"; - case SlotPrimary: - return "Primary"; - case SlotSecondary: - return "Secondary"; - case SlotFinger1: - return "Finger1"; - case SlotFinger2: - return "Finger2"; - case SlotChest: - return "Chest"; - case SlotLegs: - return "Legs"; - case SlotFeet: - return "Feet"; - case SlotWaist: - return "Waist"; - case SlotPowerSource: - return "PowerSource"; - case SlotAmmo: - return "Ammo"; - case SlotGeneral1: - return "General1"; - case SlotGeneral2: - return "General2"; - case SlotGeneral3: - return "General3"; - case SlotGeneral4: - return "General4"; - case SlotGeneral5: - return "General5"; - case SlotGeneral6: - return "General6"; - case SlotGeneral7: - return "General7"; - case SlotGeneral8: - return "General8"; - /* - case SlotGeneral9: - return "General9"; - case SlotGeneral10: - return "General10"; - */ - case SlotCursor: - return "Cursor"; - default: - return "Unknown Slot"; - } -} - -const char* EQEmu::Constants::InventorySubName(int16 sub_index) -{ - if (sub_index == INVALID_INDEX) - return "Invalid Sub"; - - if ((uint16)sub_index >= ITEM_CONTAINER_SIZE) - return "Unknown Sub"; - - static std::string ret_str; - ret_str = StringFormat("Container%i", (sub_index + 1)); // zero-based index..but, count starts at one - - return ret_str.c_str(); -} - -const char* EQEmu::Constants::InventoryAugName(int16 aug_index) -{ - if (aug_index == INVALID_INDEX) - return "Invalid Aug"; - - if ((uint16)aug_index >= ITEM_COMMON_SIZE) - return "Unknown Aug"; - - static std::string ret_str; - ret_str = StringFormat("Augment%i", (aug_index + 1)); // zero-based index..but, count starts at one - - return ret_str.c_str(); -} - - -// -// class EQEmu::Limits -// -// client validation -bool EQEmu::Limits::IsValidPCClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) - return true; - - return false; -} - -ClientVersion EQEmu::Limits::ValidatePCClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) - return clientVersion; - - return ClientVersion::Unknown; -} - -// npc validation -bool EQEmu::Limits::IsValidNPCClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) - return true; - - return false; -} - -ClientVersion EQEmu::Limits::ValidateNPCClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) - return clientVersion; - - return ClientVersion::Unknown; -} - -// mob validation -bool EQEmu::Limits::IsValidMobClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) - return true; - - return false; -} - -ClientVersion EQEmu::Limits::ValidateMobClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) - return clientVersion; - - return ClientVersion::Unknown; -} - -// database -size_t EQEmu::Limits::CharacterCreationLimit(ClientVersion clientVersion) -{ - static const size_t local[CLIENT_VERSION_COUNT] = { -/*Unknown*/ NOT_USED, -/*Client62*/ NOT_USED, -/*Titanium*/ Titanium::consts::CHARACTER_CREATION_LIMIT, -/*SoF*/ SoF::consts::CHARACTER_CREATION_LIMIT, -/*SoD*/ SoD::consts::CHARACTER_CREATION_LIMIT, -/*UF*/ UF::consts::CHARACTER_CREATION_LIMIT, -/*RoF*/ RoF::consts::CHARACTER_CREATION_LIMIT, -/*RoF2*/ RoF2::consts::CHARACTER_CREATION_LIMIT, - -/*MobNPC*/ NOT_USED, -/*MobMerc*/ NOT_USED, -/*MobBot*/ NOT_USED, -/*MobPet*/ NOT_USED - }; - - return local[static_cast(ValidateMobClientVersion(clientVersion))]; -} - -// inventory -uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) -{ - // not all maps will have an instantiated container..some are references for queue generators (i.e., bazaar, mail, etc...) - // a zero '0' indicates a needed value..otherwise, change to '_NOTUSED' for a null value so indices requiring research can be identified - // ALL of these values need to be verified before pushing to live - // - // make sure that you transcribe the actual value from 'defaults' to here before updating or client crashes will ensue..and/or... - // insert older clients inside of the progression of client order - // - // TYPE_POSSESSIONS_SIZE does not reflect all actual _constants size due to bitmask-use compatibility - // - // when setting NPC-based values, try to adhere to an Constants:: or NOT_USED value to avoid unnecessary issues - - static const uint16 local[TypeCount][CLIENT_VERSION_COUNT] = { - // server and database are sync'd to current TypePossessions's client as set in 'using namespace RoF::slots;' and - // 'Constants::TYPE_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() - // for partial range validation checks and 'Constants::TYPE_POSSESSIONS_SIZE' for full range iterations - { // local[TypePossessions] -/*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_POSSESSIONS_SIZE, -/*Titanium*/ Constants::TYPE_POSSESSIONS_SIZE, -/*SoF*/ Constants::TYPE_POSSESSIONS_SIZE, -/*SoD*/ Constants::TYPE_POSSESSIONS_SIZE, -/*Underfoot*/ Constants::TYPE_POSSESSIONS_SIZE, -/*RoF*/ Constants::TYPE_POSSESSIONS_SIZE, -/*RoF2*/ Constants::TYPE_POSSESSIONS_SIZE, - -/*NPC*/ Constants::TYPE_POSSESSIONS_SIZE, -/*Merc*/ Constants::TYPE_POSSESSIONS_SIZE, -/*Bot*/ Constants::TYPE_POSSESSIONS_SIZE, -/*Pet*/ Constants::TYPE_POSSESSIONS_SIZE - }, - { // local[TypeBank] -/*Unknown*/ NOT_USED, -/*62*/ NOT_USED, -/*Titanium*/ Titanium::consts::TYPE_BANK_SIZE, -/*SoF*/ Constants::TYPE_BANK_SIZE, -/*SoD*/ Constants::TYPE_BANK_SIZE, -/*Underfoot*/ Constants::TYPE_BANK_SIZE, -/*RoF*/ Constants::TYPE_BANK_SIZE, -/*RoF2*/ Constants::TYPE_BANK_SIZE, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }, - { // local[TypeSharedBank] -/*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_SHARED_BANK_SIZE, -/*Titanium*/ Constants::TYPE_SHARED_BANK_SIZE, -/*SoF*/ Constants::TYPE_SHARED_BANK_SIZE, -/*SoD*/ Constants::TYPE_SHARED_BANK_SIZE, -/*Underfoot*/ Constants::TYPE_SHARED_BANK_SIZE, -/*RoF*/ Constants::TYPE_SHARED_BANK_SIZE, -/*RoF2*/ Constants::TYPE_SHARED_BANK_SIZE, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }, - { // local[TypeTrade] -/*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_TRADE_SIZE, -/*Titanium*/ Constants::TYPE_TRADE_SIZE, -/*SoF*/ Constants::TYPE_TRADE_SIZE, -/*SoD*/ Constants::TYPE_TRADE_SIZE, -/*Underfoot*/ Constants::TYPE_TRADE_SIZE, -/*RoF*/ Constants::TYPE_TRADE_SIZE, -/*RoF2*/ Constants::TYPE_TRADE_SIZE, - -/*NPC*/ 4, -/*Merc*/ 4, -/*Bot*/ Constants::TYPE_TRADE_SIZE, // client thinks this is another client -/*Pet*/ 4 - }, - { // local[TypeWorld] -/*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_WORLD_SIZE, -/*Titanium*/ Constants::TYPE_WORLD_SIZE, -/*SoF*/ Constants::TYPE_WORLD_SIZE, -/*SoD*/ Constants::TYPE_WORLD_SIZE, -/*Underfoot*/ Constants::TYPE_WORLD_SIZE, -/*RoF*/ Constants::TYPE_WORLD_SIZE, -/*RoF2*/ Constants::TYPE_WORLD_SIZE, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }, - { // local[TypeLimbo] -/*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_LIMBO_SIZE, -/*Titanium*/ Constants::TYPE_LIMBO_SIZE, -/*SoF*/ Constants::TYPE_LIMBO_SIZE, -/*SoD*/ Constants::TYPE_LIMBO_SIZE, -/*Underfoot*/ Constants::TYPE_LIMBO_SIZE, -/*RoF*/ Constants::TYPE_LIMBO_SIZE, -/*RoF2*/ Constants::TYPE_LIMBO_SIZE, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }, - { // local[TypeTribute] -/*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_TRIBUTE_SIZE, -/*Titanium*/ Constants::TYPE_TRIBUTE_SIZE, -/*SoF*/ Constants::TYPE_TRIBUTE_SIZE, -/*SoD*/ Constants::TYPE_TRIBUTE_SIZE, -/*Underfoot*/ Constants::TYPE_TRIBUTE_SIZE, -/*RoF*/ Constants::TYPE_TRIBUTE_SIZE, -/*RoF2*/ Constants::TYPE_TRIBUTE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeTrophyTribute] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ Constants::TYPE_TROPHY_TRIBUTE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeGuildTribute] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_GUILD_TRIBUTE_SIZE, -/*RoF2*/ Constants::TYPE_GUILD_TRIBUTE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeMerchant] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_MERCHANT_SIZE, -/*RoF2*/ Constants::TYPE_MERCHANT_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeDeleted] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_DELETED_SIZE, -/*RoF2*/ Constants::TYPE_DELETED_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeCorpse] -/*Unknown*/ NOT_USED, -/*62*/ NOT_USED, -/*Titanium*/ Titanium::consts::TYPE_CORPSE_SIZE, -/*SoF*/ SoF::consts::TYPE_CORPSE_SIZE, -/*SoD*/ SoD::consts::TYPE_CORPSE_SIZE, -/*Underfoot*/ UF::consts::TYPE_CORPSE_SIZE, -/*RoF*/ RoF::consts::TYPE_CORPSE_SIZE, -/*RoF2*/ RoF2::consts::TYPE_CORPSE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeBazaar] -/*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_BAZAAR_SIZE, -/*Titanium*/ Constants::TYPE_BAZAAR_SIZE, -/*SoF*/ Constants::TYPE_BAZAAR_SIZE, -/*SoD*/ Constants::TYPE_BAZAAR_SIZE, -/*Underfoot*/ Constants::TYPE_BAZAAR_SIZE, -/*RoF*/ Constants::TYPE_BAZAAR_SIZE, -/*RoF2*/ Constants::TYPE_BAZAAR_SIZE, - -/*NPC*/ 0, // this may need to be 'Constants::TYPE_BAZAAR_SIZE' if offline client traders respawn as an npc -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeInspect] -/*Unknown*/ NOT_USED, -/*62*/ NOT_USED, -/*Titanium*/ Titanium::consts::TYPE_INSPECT_SIZE, -/*SoF*/ SoF::consts::TYPE_INSPECT_SIZE, -/*SoD*/ SoD::consts::TYPE_INSPECT_SIZE, -/*Underfoot*/ UF::consts::TYPE_INSPECT_SIZE, -/*RoF*/ RoF::consts::TYPE_INSPECT_SIZE, -/*RoF2*/ RoF2::consts::TYPE_INSPECT_SIZE, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED - }, - { // local[TypeRealEstate] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_REAL_ESTATE_SIZE, -/*RoF2*/ Constants::TYPE_REAL_ESTATE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeViewMODPC] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_VIEW_MOD_PC_SIZE, -/*RoF2*/ Constants::TYPE_VIEW_MOD_PC_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeViewMODBank] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_VIEW_MOD_BANK_SIZE, -/*RoF2*/ Constants::TYPE_VIEW_MOD_BANK_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeViewMODSharedBank] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, -/*RoF2*/ Constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeViewMODLimbo] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_VIEW_MOD_LIMBO_SIZE, -/*RoF2*/ Constants::TYPE_VIEW_MOD_LIMBO_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeAltStorage] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_ALT_STORAGE_SIZE, -/*RoF2*/ Constants::TYPE_ALT_STORAGE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeArchived] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_ARCHIVED_SIZE, -/*RoF2*/ Constants::TYPE_ARCHIVED_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeMail] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_MAIL_SIZE, -/*RoF2*/ Constants::TYPE_MAIL_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeGuildTrophyTribute] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ Constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeKrono] -/*Unknown*/ NOT_USED, -/*62*/ NOT_USED, -/*Titanium*/ NOT_USED, -/*SoF*/ NOT_USED, -/*SoD*/ NOT_USED, -/*Underfoot*/ NOT_USED, -/*RoF*/ Constants::TYPE_KRONO_SIZE, -/*RoF2*/ Constants::TYPE_KRONO_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }, - { // local[TypeOther] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_OTHER_SIZE, -/*RoF2*/ Constants::TYPE_OTHER_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - } - }; - - if ((uint16)indexMap < TypeCount) - return local[indexMap][static_cast(ValidateMobClientVersion(clientVersion))]; - - return NOT_USED; -} - -uint64 EQEmu::Limits::PossessionsBitmask(ClientVersion clientVersion) -{ - // these are for the new inventory system (RoF)..not the current (Ti) one... - // 0x0000000000200000 is SlotPowerSource (SoF+) - // 0x0000000080000000 is SlotGeneral9 (RoF+) - // 0x0000000100000000 is SlotGeneral10 (RoF+) - - static const uint64 local[CLIENT_VERSION_COUNT] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x000000027FDFFFFF, -/*Titanium*/ 0x000000027FDFFFFF, -/*SoF*/ 0x000000027FFFFFFF, -/*SoD*/ 0x000000027FFFFFFF, -/*Underfoot*/ 0x000000027FFFFFFF, -/*RoF*/ 0x00000003FFFFFFFF, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }; - - return NOT_USED; - //return local[static_cast(ValidateMobClientVersion(clientVersion))]; -} - -uint64 EQEmu::Limits::EquipmentBitmask(ClientVersion clientVersion) -{ - static const uint64 local[CLIENT_VERSION_COUNT] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x00000000005FFFFF, -/*Titanium*/ 0x00000000005FFFFF, -/*SoF*/ 0x00000000007FFFFF, -/*SoD*/ 0x00000000007FFFFF, -/*Underfoot*/ 0x00000000007FFFFF, -/*RoF*/ 0x00000000007FFFFF, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }; - - return NOT_USED; - //return local[static_cast(ValidateMobClientVersion(clientVersion))]; -} - -uint64 EQEmu::Limits::GeneralBitmask(ClientVersion clientVersion) -{ - static const uint64 local[CLIENT_VERSION_COUNT] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x000000007F800000, -/*Titanium*/ 0x000000007F800000, -/*SoF*/ 0x000000007F800000, -/*SoD*/ 0x000000007F800000, -/*Underfoot*/ 0x000000007F800000, -/*RoF*/ 0x00000001FF800000, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }; - - return NOT_USED; - //return local[static_cast(ValidateMobClientVersion(clientVersion))]; -} - -uint64 EQEmu::Limits::CursorBitmask(ClientVersion clientVersion) -{ - static const uint64 local[CLIENT_VERSION_COUNT] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x0000000200000000, -/*Titanium*/ 0x0000000200000000, -/*SoF*/ 0x0000000200000000, -/*SoD*/ 0x0000000200000000, -/*Underfoot*/ 0x0000000200000000, -/*RoF*/ 0x0000000200000000, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }; - - return NOT_USED; - //return local[static_cast(ValidateMobClientVersion(clientVersion))]; -} - -bool EQEmu::Limits::AllowsEmptyBagInBag(ClientVersion clientVersion) -{ - static const bool local[CLIENT_VERSION_COUNT] = { -/*Unknown*/ false, -/*62*/ false, -/*Titanium*/ Titanium::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*SoF*/ SoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*SoD*/ SoD::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*Underfoot*/ UF::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*RoF*/ RoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*RoF2*/ RoF2::limits::ALLOWS_EMPTY_BAG_IN_BAG, - -/*NPC*/ false, -/*Merc*/ false, -/*Bot*/ false, -/*Pet*/ false - }; - - return false; // not implemented - //return local[static_cast(ValidateMobClientVersion(clientVersion))]; -} - -bool EQEmu::Limits::AllowsClickCastFromBag(ClientVersion clientVersion) -{ - static const bool local[CLIENT_VERSION_COUNT] = { -/*Unknown*/ false, -/*62*/ false, -/*Titanium*/ Titanium::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*SoF*/ SoF::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*SoD*/ SoD::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*Underfoot*/ UF::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*RoF*/ RoF::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*RoF2*/ RoF2::limits::ALLOWS_CLICK_CAST_FROM_BAG, - -/*NPC*/ false, -/*Merc*/ false, -/*Bot*/ false, -/*Pet*/ false - }; - - return local[static_cast(ValidateMobClientVersion(clientVersion))]; -} - -// items -uint16 EQEmu::Limits::ItemCommonSize(ClientVersion clientVersion) -{ - static const uint16 local[CLIENT_VERSION_COUNT] = { -/*Unknown*/ NOT_USED, -/*62*/ Constants::ITEM_COMMON_SIZE, -/*Titanium*/ Constants::ITEM_COMMON_SIZE, -/*SoF*/ Constants::ITEM_COMMON_SIZE, -/*SoD*/ Constants::ITEM_COMMON_SIZE, -/*Underfoot*/ Constants::ITEM_COMMON_SIZE, -/*RoF*/ Constants::ITEM_COMMON_SIZE, -/*RoF2*/ Constants::ITEM_COMMON_SIZE, - -/*NPC*/ Constants::ITEM_COMMON_SIZE, -/*Merc*/ Constants::ITEM_COMMON_SIZE, -/*Bot*/ Constants::ITEM_COMMON_SIZE, -/*Pet*/ Constants::ITEM_COMMON_SIZE - }; - - return local[static_cast(ValidateMobClientVersion(clientVersion))]; -} - -uint16 EQEmu::Limits::ItemContainerSize(ClientVersion clientVersion) -{ - static const uint16 local[CLIENT_VERSION_COUNT] = { -/*Unknown*/ NOT_USED, -/*62*/ Constants::ITEM_CONTAINER_SIZE, -/*Titanium*/ Constants::ITEM_CONTAINER_SIZE, -/*SoF*/ Constants::ITEM_CONTAINER_SIZE, -/*SoD*/ Constants::ITEM_CONTAINER_SIZE, -/*Underfoot*/ Constants::ITEM_CONTAINER_SIZE, -/*RoF*/ Constants::ITEM_CONTAINER_SIZE, -/*RoF2*/ Constants::ITEM_CONTAINER_SIZE, - -/*NPC*/ Constants::ITEM_CONTAINER_SIZE, -/*Merc*/ Constants::ITEM_CONTAINER_SIZE, -/*Bot*/ Constants::ITEM_CONTAINER_SIZE, -/*Pet*/ Constants::ITEM_CONTAINER_SIZE - }; - - return local[static_cast(ValidateMobClientVersion(clientVersion))]; -} - -bool EQEmu::Limits::CoinHasWeight(ClientVersion clientVersion) -{ - static const bool local[CLIENT_VERSION_COUNT] = { -/*Unknown*/ true, -/*62*/ true, -/*Titanium*/ Titanium::limits::COIN_HAS_WEIGHT, -/*SoF*/ SoF::limits::COIN_HAS_WEIGHT, -/*SoD*/ SoD::limits::COIN_HAS_WEIGHT, -/*Underfoot*/ UF::limits::COIN_HAS_WEIGHT, -/*RoF*/ RoF::limits::COIN_HAS_WEIGHT, -/*RoF2*/ RoF::limits::COIN_HAS_WEIGHT, - -/*NPC*/ true, -/*Merc*/ true, -/*Bot*/ true, -/*Pet*/ true - }; - - return local[static_cast(ValidateMobClientVersion(clientVersion))]; -} diff --git a/common/eq_dictionary.h b/common/eq_dictionary.h deleted file mode 100644 index f67f2b65f..000000000 --- a/common/eq_dictionary.h +++ /dev/null @@ -1,206 +0,0 @@ -/* -EQEMu: Everquest Server Emulator - -Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef EQ_DICTIONARY_H -#define EQ_DICTIONARY_H - -#include "types.h" -#include "eq_constants.h" -#include "clientversions.h" -#include -#include "../common/patches/titanium_constants.h" -#include "../common/patches/sof_constants.h" -#include "../common/patches/sod_constants.h" -#include "../common/patches/uf_constants.h" -#include "../common/patches/rof_constants.h" -#include "../common/patches/rof2_constants.h" - -// *** DO NOT CHANGE without a full understanding of the consequences..the server is set up to use these settings explicitly!! *** -// *** You will cause compilation failures and corrupt your database if partial or incorrect attempts to change them are made!! *** - -// Hard-coded values usually indicate that further research is needed and the values given are from the old (known) system - -// (future use) -//using namespace RoF2::maps; // server inventory maps enumeration (code and database sync'd to reference) -//using namespace RoF::slots; // server possessions slots enumeration (code and database sync'd to reference) - - -namespace EQEmu { - // an immutable value is required to initialize arrays, etc... use this class as a repository for those - class Constants { - public: - // database - static const ClientVersion CHARACTER_CREATION_CLIENT = ClientVersion::RoF2; // adjust according to starting item placement and target client - - static const size_t CHARACTER_CREATION_LIMIT = RoF2::consts::CHARACTER_CREATION_LIMIT; - - // inventory - static uint16 InventoryTypeSize(int16 type_index); - //static const char* InventoryLocationName(Location_Struct location); - static const char* InventoryTypeName(int16 type_index); - static const char* InventorySlotName(int16 slot_index); - static const char* InventorySubName(int16 sub_index); - static const char* InventoryAugName(int16 aug_index); - - // these are currently hard-coded for existing inventory system..do not use in place of special client version handlers until ready - static const uint16 TYPE_POSSESSIONS_SIZE = SlotCount; - static const uint16 TYPE_BANK_SIZE = 24; - static const uint16 TYPE_SHARED_BANK_SIZE = 2; - static const uint16 TYPE_TRADE_SIZE = 8; - static const uint16 TYPE_WORLD_SIZE = 10; - static const uint16 TYPE_LIMBO_SIZE = 36; - static const uint16 TYPE_TRIBUTE_SIZE = 5; // (need client values) - static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; - static const uint16 TYPE_MERCHANT_SIZE = 0; - static const uint16 TYPE_DELETED_SIZE = 0; - static const uint16 TYPE_CORPSE_SIZE = SlotCount; // no bitmask use..limits to size of client corpse window (see EQLimits::InventoryMapSize(MapCorpse, Date: Fri, 15 Apr 2016 22:11:53 -0400 Subject: [PATCH 049/693] Reworked EQDictionary into namespace EQEmu --- changelog.txt | 3 + common/CMakeLists.txt | 13 +- common/deity.cpp | 149 ++++++++ common/deity.h | 187 +++------- common/emu_constants.cpp | 258 ++++++++++++++ common/emu_constants.h | 155 +++++++++ common/emu_legacy.cpp | 20 ++ common/emu_legacy.h | 109 ++++++ common/eq_constants.h | 126 ------- common/eq_limits.cpp | 695 +++++++++++++++++++++++++++++++++++++ common/eq_limits.h | 82 +++++ common/eq_packet_structs.h | 22 +- common/item.cpp | 85 +---- common/item.h | 39 --- common/item_struct.h | 5 +- common/light_source.cpp | 94 +++++ common/light_source.h | 109 ++++++ common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/say_link.cpp | 272 +++++++++++++++ common/say_link.h | 130 +++++++ zone/aa.cpp | 3 +- zone/bot.cpp | 6 +- zone/bot.h | 2 +- zone/bot_command.cpp | 4 +- zone/client.cpp | 246 ------------- zone/client.h | 77 +--- zone/command.cpp | 16 +- zone/corpse.cpp | 12 +- zone/lua_general.cpp | 4 +- zone/merc.cpp | 10 +- zone/mob.cpp | 6 +- zone/mob.h | 7 +- zone/npc.cpp | 14 +- zone/questmgr.cpp | 10 +- zone/tasks.cpp | 4 +- zone/tradeskills.cpp | 2 +- 37 files changed, 2204 insertions(+), 776 deletions(-) create mode 100644 common/deity.cpp create mode 100644 common/emu_constants.cpp create mode 100644 common/emu_constants.h create mode 100644 common/emu_legacy.cpp create mode 100644 common/emu_legacy.h create mode 100644 common/eq_limits.cpp create mode 100644 common/eq_limits.h create mode 100644 common/light_source.cpp create mode 100644 common/light_source.h create mode 100644 common/say_link.cpp create mode 100644 common/say_link.h diff --git a/changelog.txt b/changelog.txt index 8563a9a36..595526c70 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/15/2016 == +Uleat: Reworked EQDictionary into namespace EQEmu + == 04/08/2016 == Uleat: Added Heal Rotation HOTs (Heal Override Targets) that can be set for proactive healing (default HR behavior is reactive) Uleat: Added the ability to save/load/delete Heal Rotations based on targeted member - load is automatic when ^hrcreate is used on a bot that has a saved HR entry diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 09ed7e02c..57869b328 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -11,15 +11,18 @@ SET(common_sources database_conversions.cpp database_instances.cpp dbcore.cpp + deity.cpp + emu_constants.cpp + emu_legacy.cpp emu_opcodes.cpp emu_tcp_connection.cpp emu_tcp_server.cpp - eq_dictionary.cpp eqdb.cpp eqdb_res.cpp eqemu_exception.cpp eqemu_config.cpp eqemu_logsys.cpp + eq_limits.cpp eq_packet.cpp eq_stream.cpp eq_stream_factory.cpp @@ -32,6 +35,7 @@ SET(common_sources guilds.cpp ipc_mutex.cpp item.cpp + light_source.cpp md5.cpp memory_mapped_file.cpp misc.cpp @@ -51,6 +55,7 @@ SET(common_sources races.cpp rdtsc.cpp rulesys.cpp + say_link.cpp serverinfo.cpp shareddb.cpp skills.cpp @@ -104,12 +109,13 @@ SET(common_headers database.h dbcore.h deity.h + emu_constants.h + emu_legacy.h emu_opcodes.h emu_oplist.h emu_tcp_connection.h emu_tcp_server.h eq_constants.h - eq_dictionary.h eq_packet_structs.h eqdb.h eqdb_res.h @@ -117,6 +123,7 @@ SET(common_headers eqemu_config.h eqemu_config_elements.h eqemu_logsys.h + eq_limits.h eq_packet.h eq_stream.h eq_stream_factory.h @@ -140,6 +147,7 @@ SET(common_headers item_fieldlist.h item_struct.h languages.h + light_source.h linked_list.h loottable.h mail_oplist.h @@ -166,6 +174,7 @@ SET(common_headers rdtsc.h rulesys.h ruletypes.h + say_link.h seperator.h serverinfo.h servertalk.h diff --git a/common/deity.cpp b/common/deity.cpp new file mode 100644 index 000000000..af3d60e1a --- /dev/null +++ b/common/deity.cpp @@ -0,0 +1,149 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "deity.h" + + +EQEmu::Deity::TypeBits EQEmu::Deity::ConvertDeityToDeityBit(Types deity) +{ + switch (deity) { + case DeityBertoxxulous: + return BIT_DeityBertoxxulous; + case DeityBrellSirilis: + return BIT_DeityBrellSirilis; + case DeityCazicThule: + return BIT_DeityCazicThule; + case DeityErollisiMarr: + return BIT_DeityErollisiMarr; + case DeityBristlebane: + return BIT_DeityBristlebane; + case DeityInnoruuk: + return BIT_DeityInnoruuk; + case DeityKarana: + return BIT_DeityKarana; + case DeityMithanielMarr: + return BIT_DeityMithanielMarr; + case DeityPrexus: + return BIT_DeityPrexus; + case DeityQuellious: + return BIT_DeityQuellious; + case DeityRallosZek: + return BIT_DeityRallosZek; + case DeityRodcetNife: + return BIT_DeityRodcetNife; + case DeitySolusekRo: + return BIT_DeitySolusekRo; + case DeityTheTribunal: + return BIT_DeityTheTribunal; + case DeityTunare: + return BIT_DeityTunare; + case DeityVeeshan: + return BIT_DeityVeeshan; + case DeityAgnostic_LB: + case DeityAgnostic: + return BIT_DeityAgnostic; + default: + return BIT_DeityAll; + }; +} + +EQEmu::Deity::Types EQEmu::Deity::ConvertDeityBitToDeity(TypeBits deity_bit) +{ + switch (deity_bit) { + case BIT_DeityAgnostic: + return DeityAgnostic; + case BIT_DeityBertoxxulous: + return DeityBertoxxulous; + case BIT_DeityBrellSirilis: + return DeityBrellSirilis; + case BIT_DeityCazicThule: + return DeityCazicThule; + case BIT_DeityErollisiMarr: + return DeityErollisiMarr; + case BIT_DeityBristlebane: + return DeityBristlebane; + case BIT_DeityInnoruuk: + return DeityInnoruuk; + case BIT_DeityKarana: + return DeityKarana; + case BIT_DeityMithanielMarr: + return DeityMithanielMarr; + case BIT_DeityPrexus: + return DeityPrexus; + case BIT_DeityQuellious: + return DeityQuellious; + case BIT_DeityRallosZek: + return DeityRallosZek; + case BIT_DeityRodcetNife: + return DeityRodcetNife; + case BIT_DeitySolusekRo: + return DeitySolusekRo; + case BIT_DeityTheTribunal: + return DeityTheTribunal; + case BIT_DeityTunare: + return DeityTunare; + case BIT_DeityVeeshan: + return DeityVeeshan; + default: + return DeityUnknown; + }; +} + +const char* EQEmu::Deity::GetDeityName(Types deity) +{ + switch (deity) { + case DeityBertoxxulous: + return "Bertoxxulous"; + case DeityBrellSirilis: + return "Brell Serilis"; + case DeityCazicThule: + return "Cazic-Thule"; + case DeityErollisiMarr: + return "Erollisi Marr"; + case DeityBristlebane: + return "Bristlebane"; + case DeityInnoruuk: + return "Innoruuk"; + case DeityKarana: + return "Karana"; + case DeityMithanielMarr: + return "Mithaniel Marr"; + case DeityPrexus: + return "Prexus"; + case DeityQuellious: + return "Quellious"; + case DeityRallosZek: + return "Rallos Zek"; + case DeityRodcetNife: + return "Rodcet Nife"; + case DeitySolusekRo: + return "Solusek Ro"; + case DeityTheTribunal: + return "The Tribunal"; + case DeityTunare: + return "Tunare"; + case DeityVeeshan: + return "Veeshan"; + case DeityAgnostic_LB: + case DeityAgnostic: + return "Agnostic"; + default: + return "Unknown"; + }; +} diff --git a/common/deity.h b/common/deity.h index 486d17263..d832315d0 100644 --- a/common/deity.h +++ b/common/deity.h @@ -19,148 +19,59 @@ #define DEITY_H #include "types.h" -#include -// NOTE: This code is not fully implemented since there are no references in the existing code -/* -** Diety types -** -** (ref: eqstr_us.txt) -** -** (Another orphaned enumeration...) -*/ -enum DeityTypes +namespace EQEmu { -/*----*/ DeityUnknown = 0, -/*----*/ DeityAgnostic_LB = 140, -/*3251*/ DeityBertoxxulous = 201, -/*3262*/ DeityBrellSirilis, -/*3253*/ DeityCazicThule, -/*3256*/ DeityErollisiMarr, -/*3252*/ DeityBristlebane, -/*3254*/ DeityInnoruuk, -/*3255*/ DeityKarana, -/*3257*/ DeityMithanielMarr, -/*3259*/ DeityPrexus, -/*3260*/ DeityQuellious, -/*3266*/ DeityRallosZek, -/*3258*/ DeityRodcetNife, -/*3261*/ DeitySolusekRo, -/*3263*/ DeityTheTribunal, -/*3264*/ DeityTunare, -/*3265*/ DeityVeeshan, -/*3250*/ DeityAgnostic = 396 -}; + class Deity { + public: + enum Types { + DeityUnknown = 0, + DeityAgnostic_LB = 140, + DeityBertoxxulous = 201, + DeityBrellSirilis, + DeityCazicThule, + DeityErollisiMarr, + DeityBristlebane, + DeityInnoruuk, + DeityKarana, + DeityMithanielMarr, + DeityPrexus, + DeityQuellious, + DeityRallosZek, + DeityRodcetNife, + DeitySolusekRo, + DeityTheTribunal, + DeityTunare, + DeityVeeshan, + DeityAgnostic = 396 + }; -/* -** Deity type bits -** -** (New orphan, but make use of it!) -*/ -enum DeityTypeBits : uint32 -{ - BIT_DeityAll = 0x00000000, - BIT_DeityAgnostic = 0x00000001, - BIT_DeityBertoxxulous = 0x00000002, - BIT_DeityBrellSirilis = 0x00000004, - BIT_DeityCazicThule = 0x00000008, - BIT_DeityErollisiMarr = 0x00000010, - BIT_DeityBristlebane = 0x00000020, - BIT_DeityInnoruuk = 0x00000040, - BIT_DeityKarana = 0x00000080, - BIT_DeityMithanielMarr = 0x00000100, - BIT_DeityPrexus = 0x00000200, - BIT_DeityQuellious = 0x00000400, - BIT_DeityRallosZek = 0x00000800, - BIT_DeityRodcetNife = 0x00001000, - BIT_DeitySolusekRo = 0x00002000, - BIT_DeityTheTribunal = 0x00004000, - BIT_DeityTunare = 0x00008000, - BIT_DeityVeeshan = 0x00010000 -}; + enum TypeBits : uint32 { + BIT_DeityAll = 0x00000000, + BIT_DeityAgnostic = 0x00000001, + BIT_DeityBertoxxulous = 0x00000002, + BIT_DeityBrellSirilis = 0x00000004, + BIT_DeityCazicThule = 0x00000008, + BIT_DeityErollisiMarr = 0x00000010, + BIT_DeityBristlebane = 0x00000020, + BIT_DeityInnoruuk = 0x00000040, + BIT_DeityKarana = 0x00000080, + BIT_DeityMithanielMarr = 0x00000100, + BIT_DeityPrexus = 0x00000200, + BIT_DeityQuellious = 0x00000400, + BIT_DeityRallosZek = 0x00000800, + BIT_DeityRodcetNife = 0x00001000, + BIT_DeitySolusekRo = 0x00002000, + BIT_DeityTheTribunal = 0x00004000, + BIT_DeityTunare = 0x00008000, + BIT_DeityVeeshan = 0x00010000 + }; -static DeityTypeBits ConvertDeityToBitDeity(DeityTypes deity) -{ - switch(deity) - { - case DeityBertoxxulous: { return BIT_DeityBertoxxulous; } - case DeityBrellSirilis: { return BIT_DeityBrellSirilis; } - case DeityCazicThule: { return BIT_DeityCazicThule; } - case DeityErollisiMarr: { return BIT_DeityErollisiMarr; } - case DeityBristlebane: { return BIT_DeityBristlebane; } - case DeityInnoruuk: { return BIT_DeityInnoruuk; } - case DeityKarana: { return BIT_DeityKarana; } - case DeityMithanielMarr: { return BIT_DeityMithanielMarr; } - case DeityPrexus: { return BIT_DeityPrexus; } - case DeityQuellious: { return BIT_DeityQuellious; } - case DeityRallosZek: { return BIT_DeityRallosZek; } - case DeityRodcetNife: { return BIT_DeityRodcetNife; } - case DeitySolusekRo: { return BIT_DeitySolusekRo; } - case DeityTheTribunal: { return BIT_DeityTheTribunal; } - case DeityTunare: { return BIT_DeityTunare; } - case DeityVeeshan: { return BIT_DeityVeeshan; } - case DeityAgnostic_LB: - case DeityAgnostic: { return BIT_DeityAgnostic; } - default: { break; } + static TypeBits ConvertDeityToDeityBit(Types deity); + static Types ConvertDeityBitToDeity(TypeBits deity_bit); + static const char* GetDeityName(Types deity); }; +} - return BIT_DeityAll; -}; - -static DeityTypes ConvertBitDeityToDeity(DeityTypeBits deity_bit) -{ - switch(deity_bit) - { - case BIT_DeityAgnostic: { return DeityAgnostic; } - case BIT_DeityBertoxxulous: { return DeityBertoxxulous; } - case BIT_DeityBrellSirilis: { return DeityBrellSirilis; } - case BIT_DeityCazicThule: { return DeityCazicThule; } - case BIT_DeityErollisiMarr: { return DeityErollisiMarr; } - case BIT_DeityBristlebane: { return DeityBristlebane; } - case BIT_DeityInnoruuk: { return DeityInnoruuk; } - case BIT_DeityKarana: { return DeityKarana; } - case BIT_DeityMithanielMarr: { return DeityMithanielMarr; } - case BIT_DeityPrexus: { return DeityPrexus; } - case BIT_DeityQuellious: { return DeityQuellious; } - case BIT_DeityRallosZek: { return DeityRallosZek; } - case BIT_DeityRodcetNife: { return DeityRodcetNife; } - case BIT_DeitySolusekRo: { return DeitySolusekRo; } - case BIT_DeityTheTribunal: { return DeityTheTribunal; } - case BIT_DeityTunare: { return DeityTunare; } - case BIT_DeityVeeshan: { return DeityVeeshan; } - default: { break; } - }; - - return DeityUnknown; -}; - -static std::string GetDeityName(DeityTypes deity) -{ - switch(deity) - { - case DeityBertoxxulous: { return "Bertoxxulous"; } - case DeityBrellSirilis: { return "Brell Serilis"; } - case DeityCazicThule: { return "Cazic-Thule"; } - case DeityErollisiMarr: { return "Erollisi Marr"; } - case DeityBristlebane: { return "Bristlebane"; } - case DeityInnoruuk: { return "Innoruuk"; } - case DeityKarana: { return "Karana"; } - case DeityMithanielMarr: { return "Mithaniel Marr"; } - case DeityPrexus: { return "Prexus"; } - case DeityQuellious: { return "Quellious"; } - case DeityRallosZek: { return "Rallos Zek"; } - case DeityRodcetNife: { return "Rodcet Nife"; } - case DeitySolusekRo: { return "Solusek Ro"; } - case DeityTheTribunal: { return "The Tribunal"; } - case DeityTunare: { return "Tunare"; } - case DeityVeeshan: { return "Veeshan"; } - case DeityAgnostic_LB: - case DeityAgnostic: { return "Agnostic"; } - default: { break; } - }; - - return "Unknown"; -}; - -#endif +#endif /* DEITY_H */ diff --git a/common/emu_constants.cpp b/common/emu_constants.cpp new file mode 100644 index 000000000..5e62505fd --- /dev/null +++ b/common/emu_constants.cpp @@ -0,0 +1,258 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "emu_constants.h" +#include "string_util.h" + + +uint16 EQEmu::Constants::InventoryTypeSize(int16 type_index) +{ + switch (type_index) { + case TypePossessions: + return TYPE_POSSESSIONS_SIZE; + case TypeBank: + return TYPE_BANK_SIZE; + case TypeSharedBank: + return TYPE_SHARED_BANK_SIZE; + case TypeTrade: + return TYPE_TRADE_SIZE; + case TypeWorld: + return TYPE_WORLD_SIZE; + case TypeLimbo: + return TYPE_LIMBO_SIZE; + case TypeTribute: + return TYPE_TRIBUTE_SIZE; + case TypeTrophyTribute: + return TYPE_TROPHY_TRIBUTE_SIZE; + case TypeGuildTribute: + return TYPE_GUILD_TRIBUTE_SIZE; + case TypeMerchant: + return TYPE_MERCHANT_SIZE; + case TypeDeleted: + return TYPE_DELETED_SIZE; + case TypeCorpse: + return TYPE_CORPSE_SIZE; + case TypeBazaar: + return TYPE_BAZAAR_SIZE; + case TypeInspect: + return TYPE_INSPECT_SIZE; + case TypeRealEstate: + return TYPE_REAL_ESTATE_SIZE; + case TypeViewMODPC: + return TYPE_VIEW_MOD_PC_SIZE; + case TypeViewMODBank: + return TYPE_VIEW_MOD_BANK_SIZE; + case TypeViewMODSharedBank: + return TYPE_VIEW_MOD_SHARED_BANK_SIZE; + case TypeViewMODLimbo: + return TYPE_VIEW_MOD_LIMBO_SIZE; + case TypeAltStorage: + return TYPE_ALT_STORAGE_SIZE; + case TypeArchived: + return TYPE_ARCHIVED_SIZE; + case TypeMail: + return TYPE_MAIL_SIZE; + case TypeGuildTrophyTribute: + return TYPE_GUILD_TROPHY_TRIBUTE_SIZE; + case TypeKrono: + return TYPE_KRONO_SIZE; + case TypeOther: + return TYPE_OTHER_SIZE; + default: + return NOT_USED; + } +} + +/* +const char* EQEmu::Constants::InventoryLocationName(Location_Struct location) +{ + // not ready for implementation... + std::string ret_str; + StringFormat(ret_str, "%s, %s, %s, %s", InventoryMapName(location.map), InventoryMainName(location.main), InventorySubName(location.sub), InventoryAugName(location.aug)); + return ret_str; +} +*/ + +const char* EQEmu::Constants::InventoryTypeName(int16 type_index) +{ + switch (type_index) { + case INVALID_INDEX: + return "Invalid Type"; + case TypePossessions: + return "Possessions"; + case TypeBank: + return "Bank"; + case TypeSharedBank: + return "SharedBank"; + case TypeTrade: + return "Trade"; + case TypeWorld: + return "World"; + case TypeLimbo: + return "Limbo"; + case TypeTribute: + return "Tribute"; + case TypeTrophyTribute: + return "TrophyTribute"; + case TypeGuildTribute: + return "GuildTribute"; + case TypeMerchant: + return "Merchant"; + case TypeDeleted: + return "Deleted"; + case TypeCorpse: + return "Corpse"; + case TypeBazaar: + return "Bazaar"; + case TypeInspect: + return "Inspect"; + case TypeRealEstate: + return "RealEstate"; + case TypeViewMODPC: + return "ViewMODPC"; + case TypeViewMODBank: + return "ViewMODBank"; + case TypeViewMODSharedBank: + return "ViewMODSharedBank"; + case TypeViewMODLimbo: + return "ViewMODLimbo"; + case TypeAltStorage: + return "AltStorage"; + case TypeArchived: + return "Archived"; + case TypeMail: + return "Mail"; + case TypeGuildTrophyTribute: + return "GuildTrophyTribute"; + case TypeKrono: + return "Krono"; + case TypeOther: + return "Other"; + default: + return "Unknown Type"; + } +} + +const char* EQEmu::Constants::InventorySlotName(int16 slot_index) +{ + switch (slot_index) { + case INVALID_INDEX: + return "Invalid Slot"; + case SlotCharm: + return "Charm"; + case SlotEar1: + return "Ear1"; + case SlotHead: + return "Head"; + case SlotFace: + return "Face"; + case SlotEar2: + return "Ear2"; + case SlotNeck: + return "Neck"; + case SlotShoulders: + return "Shoulders"; + case SlotArms: + return "Arms"; + case SlotBack: + return "Back"; + case SlotWrist1: + return "Wrist1"; + case SlotWrist2: + return "Wrist2"; + case SlotRange: + return "Range"; + case SlotHands: + return "Hands"; + case SlotPrimary: + return "Primary"; + case SlotSecondary: + return "Secondary"; + case SlotFinger1: + return "Finger1"; + case SlotFinger2: + return "Finger2"; + case SlotChest: + return "Chest"; + case SlotLegs: + return "Legs"; + case SlotFeet: + return "Feet"; + case SlotWaist: + return "Waist"; + case SlotPowerSource: + return "PowerSource"; + case SlotAmmo: + return "Ammo"; + case SlotGeneral1: + return "General1"; + case SlotGeneral2: + return "General2"; + case SlotGeneral3: + return "General3"; + case SlotGeneral4: + return "General4"; + case SlotGeneral5: + return "General5"; + case SlotGeneral6: + return "General6"; + case SlotGeneral7: + return "General7"; + case SlotGeneral8: + return "General8"; + /* + case SlotGeneral9: + return "General9"; + case SlotGeneral10: + return "General10"; + */ + case SlotCursor: + return "Cursor"; + default: + return "Unknown Slot"; + } +} + +const char* EQEmu::Constants::InventorySubName(int16 sub_index) +{ + if (sub_index == INVALID_INDEX) + return "Invalid Sub"; + + if ((uint16)sub_index >= ITEM_CONTAINER_SIZE) + return "Unknown Sub"; + + static std::string ret_str; + ret_str = StringFormat("Container%i", (sub_index + 1)); // zero-based index..but, count starts at one + + return ret_str.c_str(); +} + +const char* EQEmu::Constants::InventoryAugName(int16 aug_index) +{ + if (aug_index == INVALID_INDEX) + return "Invalid Aug"; + + if ((uint16)aug_index >= ITEM_COMMON_SIZE) + return "Unknown Aug"; + + static std::string ret_str; + ret_str = StringFormat("Augment%i", (aug_index + 1)); // zero-based index..but, count starts at one + + return ret_str.c_str(); +} diff --git a/common/emu_constants.h b/common/emu_constants.h new file mode 100644 index 000000000..e5418be45 --- /dev/null +++ b/common/emu_constants.h @@ -0,0 +1,155 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef EMU_CONSTANTS_H +#define EMU_CONSTANTS_H + +#include "eq_limits.h" +// (future use) +//using namespace RoF2::maps; // server inventory maps enumeration (code and database sync'd to reference) +//using namespace RoF::slots; // server possessions slots enumeration (code and database sync'd to reference) + +#include "emu_legacy.h" +#include "light_source.h" +#include "deity.h" +#include "say_link.h" + +#include + + +// *** DO NOT CHANGE without a full understanding of the consequences..the server is set up to use these settings explicitly!! *** +// *** You will cause compilation failures and corrupt your database if partial or incorrect attempts to change them are made!! *** + +// Hard-coded values usually indicate that further research is needed and the values given are from the old (known) system + + +namespace EQEmu +{ + // an immutable value is required to initialize arrays, etc... use this class as a repository for those + class Constants { + public: + // database + static const ClientVersion CHARACTER_CREATION_CLIENT = ClientVersion::RoF2; // adjust according to starting item placement and target client + + static const size_t CHARACTER_CREATION_LIMIT = RoF2::consts::CHARACTER_CREATION_LIMIT; + + // inventory + static uint16 InventoryTypeSize(int16 type_index); + //static const char* InventoryLocationName(Location_Struct location); + static const char* InventoryTypeName(int16 type_index); + static const char* InventorySlotName(int16 slot_index); + static const char* InventorySubName(int16 sub_index); + static const char* InventoryAugName(int16 aug_index); + + // these are currently hard-coded for existing inventory system..do not use in place of special client version handlers until ready + static const uint16 TYPE_POSSESSIONS_SIZE = SlotCount; + static const uint16 TYPE_BANK_SIZE = 24; + static const uint16 TYPE_SHARED_BANK_SIZE = 2; + static const uint16 TYPE_TRADE_SIZE = 8; + static const uint16 TYPE_WORLD_SIZE = 10; + static const uint16 TYPE_LIMBO_SIZE = 36; + static const uint16 TYPE_TRIBUTE_SIZE = 5; // (need client values) + static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; + static const uint16 TYPE_MERCHANT_SIZE = 0; + static const uint16 TYPE_DELETED_SIZE = 0; + static const uint16 TYPE_CORPSE_SIZE = SlotCount; // no bitmask use..limits to size of client corpse window (see EQLimits::InventoryMapSize(MapCorpse, ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) + return true; + + return false; +} + +ClientVersion EQEmu::Limits::ValidatePCClientVersion(ClientVersion clientVersion) +{ + if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) + return clientVersion; + + return ClientVersion::Unknown; +} + +// npc validation +bool EQEmu::Limits::IsValidNPCClientVersion(ClientVersion clientVersion) +{ + if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) + return true; + + return false; +} + +ClientVersion EQEmu::Limits::ValidateNPCClientVersion(ClientVersion clientVersion) +{ + if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) + return clientVersion; + + return ClientVersion::Unknown; +} + +// mob validation +bool EQEmu::Limits::IsValidMobClientVersion(ClientVersion clientVersion) +{ + if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) + return true; + + return false; +} + +ClientVersion EQEmu::Limits::ValidateMobClientVersion(ClientVersion clientVersion) +{ + if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) + return clientVersion; + + return ClientVersion::Unknown; +} + +// database +size_t EQEmu::Limits::CharacterCreationLimit(ClientVersion clientVersion) +{ + static const size_t local[CLIENT_VERSION_COUNT] = { +/*Unknown*/ NOT_USED, +/*Client62*/ NOT_USED, +/*Titanium*/ Titanium::consts::CHARACTER_CREATION_LIMIT, +/*SoF*/ SoF::consts::CHARACTER_CREATION_LIMIT, +/*SoD*/ SoD::consts::CHARACTER_CREATION_LIMIT, +/*UF*/ UF::consts::CHARACTER_CREATION_LIMIT, +/*RoF*/ RoF::consts::CHARACTER_CREATION_LIMIT, +/*RoF2*/ RoF2::consts::CHARACTER_CREATION_LIMIT, + +/*MobNPC*/ NOT_USED, +/*MobMerc*/ NOT_USED, +/*MobBot*/ NOT_USED, +/*MobPet*/ NOT_USED + }; + + return local[static_cast(ValidateMobClientVersion(clientVersion))]; +} + +// inventory +uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) +{ + // not all maps will have an instantiated container..some are references for queue generators (i.e., bazaar, mail, etc...) + // a zero '0' indicates a needed value..otherwise, change to '_NOTUSED' for a null value so indices requiring research can be identified + // ALL of these values need to be verified before pushing to live + // + // make sure that you transcribe the actual value from 'defaults' to here before updating or client crashes will ensue..and/or... + // insert older clients inside of the progression of client order + // + // TYPE_POSSESSIONS_SIZE does not reflect all actual _constants size due to bitmask-use compatibility + // + // when setting NPC-based values, try to adhere to an Constants:: or NOT_USED value to avoid unnecessary issues + + static const uint16 local[TypeCount][CLIENT_VERSION_COUNT] = { + // server and database are sync'd to current TypePossessions's client as set in 'using namespace RoF::slots;' and + // 'Constants::TYPE_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() + // for partial range validation checks and 'Constants::TYPE_POSSESSIONS_SIZE' for full range iterations + { // local[TypePossessions] +/*Unknown*/ NOT_USED, +/*62*/ Constants::TYPE_POSSESSIONS_SIZE, +/*Titanium*/ Constants::TYPE_POSSESSIONS_SIZE, +/*SoF*/ Constants::TYPE_POSSESSIONS_SIZE, +/*SoD*/ Constants::TYPE_POSSESSIONS_SIZE, +/*Underfoot*/ Constants::TYPE_POSSESSIONS_SIZE, +/*RoF*/ Constants::TYPE_POSSESSIONS_SIZE, +/*RoF2*/ Constants::TYPE_POSSESSIONS_SIZE, + +/*NPC*/ Constants::TYPE_POSSESSIONS_SIZE, +/*Merc*/ Constants::TYPE_POSSESSIONS_SIZE, +/*Bot*/ Constants::TYPE_POSSESSIONS_SIZE, +/*Pet*/ Constants::TYPE_POSSESSIONS_SIZE + }, + { // local[TypeBank] +/*Unknown*/ NOT_USED, +/*62*/ NOT_USED, +/*Titanium*/ Titanium::consts::TYPE_BANK_SIZE, +/*SoF*/ Constants::TYPE_BANK_SIZE, +/*SoD*/ Constants::TYPE_BANK_SIZE, +/*Underfoot*/ Constants::TYPE_BANK_SIZE, +/*RoF*/ Constants::TYPE_BANK_SIZE, +/*RoF2*/ Constants::TYPE_BANK_SIZE, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }, + { // local[TypeSharedBank] +/*Unknown*/ NOT_USED, +/*62*/ Constants::TYPE_SHARED_BANK_SIZE, +/*Titanium*/ Constants::TYPE_SHARED_BANK_SIZE, +/*SoF*/ Constants::TYPE_SHARED_BANK_SIZE, +/*SoD*/ Constants::TYPE_SHARED_BANK_SIZE, +/*Underfoot*/ Constants::TYPE_SHARED_BANK_SIZE, +/*RoF*/ Constants::TYPE_SHARED_BANK_SIZE, +/*RoF2*/ Constants::TYPE_SHARED_BANK_SIZE, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }, + { // local[TypeTrade] +/*Unknown*/ NOT_USED, +/*62*/ Constants::TYPE_TRADE_SIZE, +/*Titanium*/ Constants::TYPE_TRADE_SIZE, +/*SoF*/ Constants::TYPE_TRADE_SIZE, +/*SoD*/ Constants::TYPE_TRADE_SIZE, +/*Underfoot*/ Constants::TYPE_TRADE_SIZE, +/*RoF*/ Constants::TYPE_TRADE_SIZE, +/*RoF2*/ Constants::TYPE_TRADE_SIZE, + +/*NPC*/ 4, +/*Merc*/ 4, +/*Bot*/ Constants::TYPE_TRADE_SIZE, // client thinks this is another client +/*Pet*/ 4 + }, + { // local[TypeWorld] +/*Unknown*/ NOT_USED, +/*62*/ Constants::TYPE_WORLD_SIZE, +/*Titanium*/ Constants::TYPE_WORLD_SIZE, +/*SoF*/ Constants::TYPE_WORLD_SIZE, +/*SoD*/ Constants::TYPE_WORLD_SIZE, +/*Underfoot*/ Constants::TYPE_WORLD_SIZE, +/*RoF*/ Constants::TYPE_WORLD_SIZE, +/*RoF2*/ Constants::TYPE_WORLD_SIZE, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }, + { // local[TypeLimbo] +/*Unknown*/ NOT_USED, +/*62*/ Constants::TYPE_LIMBO_SIZE, +/*Titanium*/ Constants::TYPE_LIMBO_SIZE, +/*SoF*/ Constants::TYPE_LIMBO_SIZE, +/*SoD*/ Constants::TYPE_LIMBO_SIZE, +/*Underfoot*/ Constants::TYPE_LIMBO_SIZE, +/*RoF*/ Constants::TYPE_LIMBO_SIZE, +/*RoF2*/ Constants::TYPE_LIMBO_SIZE, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }, + { // local[TypeTribute] +/*Unknown*/ NOT_USED, +/*62*/ Constants::TYPE_TRIBUTE_SIZE, +/*Titanium*/ Constants::TYPE_TRIBUTE_SIZE, +/*SoF*/ Constants::TYPE_TRIBUTE_SIZE, +/*SoD*/ Constants::TYPE_TRIBUTE_SIZE, +/*Underfoot*/ Constants::TYPE_TRIBUTE_SIZE, +/*RoF*/ Constants::TYPE_TRIBUTE_SIZE, +/*RoF2*/ Constants::TYPE_TRIBUTE_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeTrophyTribute] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_TROPHY_TRIBUTE_SIZE, +/*RoF2*/ Constants::TYPE_TROPHY_TRIBUTE_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeGuildTribute] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_GUILD_TRIBUTE_SIZE, +/*RoF2*/ Constants::TYPE_GUILD_TRIBUTE_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeMerchant] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_MERCHANT_SIZE, +/*RoF2*/ Constants::TYPE_MERCHANT_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeDeleted] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_DELETED_SIZE, +/*RoF2*/ Constants::TYPE_DELETED_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeCorpse] +/*Unknown*/ NOT_USED, +/*62*/ NOT_USED, +/*Titanium*/ Titanium::consts::TYPE_CORPSE_SIZE, +/*SoF*/ SoF::consts::TYPE_CORPSE_SIZE, +/*SoD*/ SoD::consts::TYPE_CORPSE_SIZE, +/*Underfoot*/ UF::consts::TYPE_CORPSE_SIZE, +/*RoF*/ RoF::consts::TYPE_CORPSE_SIZE, +/*RoF2*/ RoF2::consts::TYPE_CORPSE_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeBazaar] +/*Unknown*/ NOT_USED, +/*62*/ Constants::TYPE_BAZAAR_SIZE, +/*Titanium*/ Constants::TYPE_BAZAAR_SIZE, +/*SoF*/ Constants::TYPE_BAZAAR_SIZE, +/*SoD*/ Constants::TYPE_BAZAAR_SIZE, +/*Underfoot*/ Constants::TYPE_BAZAAR_SIZE, +/*RoF*/ Constants::TYPE_BAZAAR_SIZE, +/*RoF2*/ Constants::TYPE_BAZAAR_SIZE, + +/*NPC*/ 0, // this may need to be 'Constants::TYPE_BAZAAR_SIZE' if offline client traders respawn as an npc +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeInspect] +/*Unknown*/ NOT_USED, +/*62*/ NOT_USED, +/*Titanium*/ Titanium::consts::TYPE_INSPECT_SIZE, +/*SoF*/ SoF::consts::TYPE_INSPECT_SIZE, +/*SoD*/ SoD::consts::TYPE_INSPECT_SIZE, +/*Underfoot*/ UF::consts::TYPE_INSPECT_SIZE, +/*RoF*/ RoF::consts::TYPE_INSPECT_SIZE, +/*RoF2*/ RoF2::consts::TYPE_INSPECT_SIZE, + +/*NPC*/ NOT_USED, +/*Merc*/ NOT_USED, +/*Bot*/ NOT_USED, +/*Pet*/ NOT_USED + }, + { // local[TypeRealEstate] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_REAL_ESTATE_SIZE, +/*RoF2*/ Constants::TYPE_REAL_ESTATE_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeViewMODPC] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_VIEW_MOD_PC_SIZE, +/*RoF2*/ Constants::TYPE_VIEW_MOD_PC_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeViewMODBank] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_VIEW_MOD_BANK_SIZE, +/*RoF2*/ Constants::TYPE_VIEW_MOD_BANK_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeViewMODSharedBank] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, +/*RoF2*/ Constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeViewMODLimbo] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_VIEW_MOD_LIMBO_SIZE, +/*RoF2*/ Constants::TYPE_VIEW_MOD_LIMBO_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeAltStorage] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_ALT_STORAGE_SIZE, +/*RoF2*/ Constants::TYPE_ALT_STORAGE_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeArchived] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_ARCHIVED_SIZE, +/*RoF2*/ Constants::TYPE_ARCHIVED_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeMail] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_MAIL_SIZE, +/*RoF2*/ Constants::TYPE_MAIL_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeGuildTrophyTribute] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, +/*RoF2*/ Constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeKrono] +/*Unknown*/ NOT_USED, +/*62*/ NOT_USED, +/*Titanium*/ NOT_USED, +/*SoF*/ NOT_USED, +/*SoD*/ NOT_USED, +/*Underfoot*/ NOT_USED, +/*RoF*/ Constants::TYPE_KRONO_SIZE, +/*RoF2*/ Constants::TYPE_KRONO_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }, + { // local[TypeOther] +/*Unknown*/ NOT_USED, +/*62*/ 0, +/*Titanium*/ 0, +/*SoF*/ 0, +/*SoD*/ 0, +/*Underfoot*/ 0, +/*RoF*/ Constants::TYPE_OTHER_SIZE, +/*RoF2*/ Constants::TYPE_OTHER_SIZE, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + } + }; + + if ((uint16)indexMap < TypeCount) + return local[indexMap][static_cast(ValidateMobClientVersion(clientVersion))]; + + return NOT_USED; +} + +uint64 EQEmu::Limits::PossessionsBitmask(ClientVersion clientVersion) +{ + // these are for the new inventory system (RoF)..not the current (Ti) one... + // 0x0000000000200000 is SlotPowerSource (SoF+) + // 0x0000000080000000 is SlotGeneral9 (RoF+) + // 0x0000000100000000 is SlotGeneral10 (RoF+) + + static const uint64 local[CLIENT_VERSION_COUNT] = { +/*Unknown*/ NOT_USED, +/*62*/ 0x000000027FDFFFFF, +/*Titanium*/ 0x000000027FDFFFFF, +/*SoF*/ 0x000000027FFFFFFF, +/*SoD*/ 0x000000027FFFFFFF, +/*Underfoot*/ 0x000000027FFFFFFF, +/*RoF*/ 0x00000003FFFFFFFF, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }; + + return NOT_USED; + //return local[static_cast(ValidateMobClientVersion(clientVersion))]; +} + +uint64 EQEmu::Limits::EquipmentBitmask(ClientVersion clientVersion) +{ + static const uint64 local[CLIENT_VERSION_COUNT] = { +/*Unknown*/ NOT_USED, +/*62*/ 0x00000000005FFFFF, +/*Titanium*/ 0x00000000005FFFFF, +/*SoF*/ 0x00000000007FFFFF, +/*SoD*/ 0x00000000007FFFFF, +/*Underfoot*/ 0x00000000007FFFFF, +/*RoF*/ 0x00000000007FFFFF, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }; + + return NOT_USED; + //return local[static_cast(ValidateMobClientVersion(clientVersion))]; +} + +uint64 EQEmu::Limits::GeneralBitmask(ClientVersion clientVersion) +{ + static const uint64 local[CLIENT_VERSION_COUNT] = { +/*Unknown*/ NOT_USED, +/*62*/ 0x000000007F800000, +/*Titanium*/ 0x000000007F800000, +/*SoF*/ 0x000000007F800000, +/*SoD*/ 0x000000007F800000, +/*Underfoot*/ 0x000000007F800000, +/*RoF*/ 0x00000001FF800000, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }; + + return NOT_USED; + //return local[static_cast(ValidateMobClientVersion(clientVersion))]; +} + +uint64 EQEmu::Limits::CursorBitmask(ClientVersion clientVersion) +{ + static const uint64 local[CLIENT_VERSION_COUNT] = { +/*Unknown*/ NOT_USED, +/*62*/ 0x0000000200000000, +/*Titanium*/ 0x0000000200000000, +/*SoF*/ 0x0000000200000000, +/*SoD*/ 0x0000000200000000, +/*Underfoot*/ 0x0000000200000000, +/*RoF*/ 0x0000000200000000, +/*RoF2*/ 0, + +/*NPC*/ 0, +/*Merc*/ 0, +/*Bot*/ 0, +/*Pet*/ 0 + }; + + return NOT_USED; + //return local[static_cast(ValidateMobClientVersion(clientVersion))]; +} + +bool EQEmu::Limits::AllowsEmptyBagInBag(ClientVersion clientVersion) +{ + static const bool local[CLIENT_VERSION_COUNT] = { +/*Unknown*/ false, +/*62*/ false, +/*Titanium*/ Titanium::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*SoF*/ SoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*SoD*/ SoD::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*Underfoot*/ UF::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*RoF*/ RoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*RoF2*/ RoF2::limits::ALLOWS_EMPTY_BAG_IN_BAG, + +/*NPC*/ false, +/*Merc*/ false, +/*Bot*/ false, +/*Pet*/ false + }; + + return false; // not implemented + //return local[static_cast(ValidateMobClientVersion(clientVersion))]; +} + +bool EQEmu::Limits::AllowsClickCastFromBag(ClientVersion clientVersion) +{ + static const bool local[CLIENT_VERSION_COUNT] = { +/*Unknown*/ false, +/*62*/ false, +/*Titanium*/ Titanium::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*SoF*/ SoF::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*SoD*/ SoD::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*Underfoot*/ UF::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*RoF*/ RoF::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*RoF2*/ RoF2::limits::ALLOWS_CLICK_CAST_FROM_BAG, + +/*NPC*/ false, +/*Merc*/ false, +/*Bot*/ false, +/*Pet*/ false + }; + + return local[static_cast(ValidateMobClientVersion(clientVersion))]; +} + +// items +uint16 EQEmu::Limits::ItemCommonSize(ClientVersion clientVersion) +{ + static const uint16 local[CLIENT_VERSION_COUNT] = { +/*Unknown*/ NOT_USED, +/*62*/ Constants::ITEM_COMMON_SIZE, +/*Titanium*/ Constants::ITEM_COMMON_SIZE, +/*SoF*/ Constants::ITEM_COMMON_SIZE, +/*SoD*/ Constants::ITEM_COMMON_SIZE, +/*Underfoot*/ Constants::ITEM_COMMON_SIZE, +/*RoF*/ Constants::ITEM_COMMON_SIZE, +/*RoF2*/ Constants::ITEM_COMMON_SIZE, + +/*NPC*/ Constants::ITEM_COMMON_SIZE, +/*Merc*/ Constants::ITEM_COMMON_SIZE, +/*Bot*/ Constants::ITEM_COMMON_SIZE, +/*Pet*/ Constants::ITEM_COMMON_SIZE + }; + + return local[static_cast(ValidateMobClientVersion(clientVersion))]; +} + +uint16 EQEmu::Limits::ItemContainerSize(ClientVersion clientVersion) +{ + static const uint16 local[CLIENT_VERSION_COUNT] = { +/*Unknown*/ NOT_USED, +/*62*/ Constants::ITEM_CONTAINER_SIZE, +/*Titanium*/ Constants::ITEM_CONTAINER_SIZE, +/*SoF*/ Constants::ITEM_CONTAINER_SIZE, +/*SoD*/ Constants::ITEM_CONTAINER_SIZE, +/*Underfoot*/ Constants::ITEM_CONTAINER_SIZE, +/*RoF*/ Constants::ITEM_CONTAINER_SIZE, +/*RoF2*/ Constants::ITEM_CONTAINER_SIZE, + +/*NPC*/ Constants::ITEM_CONTAINER_SIZE, +/*Merc*/ Constants::ITEM_CONTAINER_SIZE, +/*Bot*/ Constants::ITEM_CONTAINER_SIZE, +/*Pet*/ Constants::ITEM_CONTAINER_SIZE + }; + + return local[static_cast(ValidateMobClientVersion(clientVersion))]; +} + +bool EQEmu::Limits::CoinHasWeight(ClientVersion clientVersion) +{ + static const bool local[CLIENT_VERSION_COUNT] = { +/*Unknown*/ true, +/*62*/ true, +/*Titanium*/ Titanium::limits::COIN_HAS_WEIGHT, +/*SoF*/ SoF::limits::COIN_HAS_WEIGHT, +/*SoD*/ SoD::limits::COIN_HAS_WEIGHT, +/*Underfoot*/ UF::limits::COIN_HAS_WEIGHT, +/*RoF*/ RoF::limits::COIN_HAS_WEIGHT, +/*RoF2*/ RoF::limits::COIN_HAS_WEIGHT, + +/*NPC*/ true, +/*Merc*/ true, +/*Bot*/ true, +/*Pet*/ true + }; + + return local[static_cast(ValidateMobClientVersion(clientVersion))]; +} diff --git a/common/eq_limits.h b/common/eq_limits.h new file mode 100644 index 000000000..bd65053f8 --- /dev/null +++ b/common/eq_limits.h @@ -0,0 +1,82 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef EQ_LIMITS_H +#define EQ_LIMITS_H + +#include "types.h" +#include "eq_constants.h" +#include "clientversions.h" +#include "../common/patches/titanium_constants.h" +#include "../common/patches/sof_constants.h" +#include "../common/patches/sod_constants.h" +#include "../common/patches/uf_constants.h" +#include "../common/patches/rof_constants.h" +#include "../common/patches/rof2_constants.h" + + +// *** DO NOT CHANGE without a full understanding of the consequences..the server is set up to use these settings explicitly!! *** +// *** You will cause compilation failures and corrupt your database if partial or incorrect attempts to change them are made!! *** + +// Hard-coded values usually indicate that further research is needed and the values given are from the old (known) system + + +namespace EQEmu +{ + // values should default to a non-beneficial value..unless value conflicts with intended operation + // + // EQEmu::Constants may be used as references..but, not every reference needs to be in EQEmu::Constants (i.e., AllowsEmptyBagInBag(), CoinHasWeight(), etc...) + class Limits { + public: + // client version validation (checks to avoid crashing zone server when accessing reference arrays) + // use this inside of class Client (limits to actual clients) + static bool IsValidPCClientVersion(ClientVersion clientVersion); + static ClientVersion ValidatePCClientVersion(ClientVersion clientVersion); + + // basically..any non-client classes - do not invoke when setting a valid client + static bool IsValidNPCClientVersion(ClientVersion clientVersion); + static ClientVersion ValidateNPCClientVersion(ClientVersion clientVersion); + + // these are 'universal' - do not invoke when setting a valid client + static bool IsValidMobClientVersion(ClientVersion clientVersion); + static ClientVersion ValidateMobClientVersion(ClientVersion clientVersion); + + // database + static size_t CharacterCreationLimit(ClientVersion clientVersion); + + // inventory + static uint16 InventoryMapSize(int16 indexMap, ClientVersion clientVersion); + static uint64 PossessionsBitmask(ClientVersion clientVersion); + static uint64 EquipmentBitmask(ClientVersion clientVersion); + static uint64 GeneralBitmask(ClientVersion clientVersion); + static uint64 CursorBitmask(ClientVersion clientVersion); + + static bool AllowsEmptyBagInBag(ClientVersion clientVersion); + static bool AllowsClickCastFromBag(ClientVersion clientVersion); + + // items + static uint16 ItemCommonSize(ClientVersion clientVersion); + static uint16 ItemContainerSize(ClientVersion clientVersion); + + // player profile + static bool CoinHasWeight(ClientVersion clientVersion); + }; +} + +#endif /* EQ_LIMITS_H */ diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index fb0190864..d0a60df8f 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,8 +33,7 @@ static const uint32 MAX_MERC_GRADES = 10; static const uint32 MAX_MERC_STANCES = 10; static const uint32 BLOCKED_BUFF_COUNT = 20; -//#include "eq_constants.h" -#include "eq_dictionary.h" +#include "emu_constants.h" /* ** Compiler override to ensure @@ -5342,23 +5341,6 @@ struct ClientMarqueeMessage_Struct { typedef std::list ItemList; -struct TextLinkBody_Struct { - // Current server mask: EQClientRoF2 - uint8 unknown_1; /* %1X */ - uint32 item_id; /* %05X */ - uint32 augment_1; /* %05X */ - uint32 augment_2; /* %05X */ - uint32 augment_3; /* %05X */ - uint32 augment_4; /* %05X */ - uint32 augment_5; /* %05X */ - uint32 augment_6; /* %05X */ - uint8 is_evolving; /* %1X */ - uint32 evolve_group; /* %05X */ - uint8 evolve_level; /* %02X */ - uint32 ornament_icon; /* %05X */ - int hash; /* %08X */ -}; - struct fling_struct { /* 00 */ uint32 collision; // 0 collision is off, anything else it's on diff --git a/common/item.cpp b/common/item.cpp index 5eb3a9072..f1635aeb1 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1006,7 +1006,7 @@ uint8 Inventory::FindBrightestLightType() auto item = inst->GetItem(); if (item == nullptr) { continue; } - if (LightProfile_Struct::IsLevelGreater(item->Light, brightest_light_type)) + if (EQEmu::LightSource::IsLevelGreater(item->Light, brightest_light_type)) brightest_light_type = item->Light; } @@ -1022,11 +1022,11 @@ uint8 Inventory::FindBrightestLightType() if (item->ItemClass != ItemClassCommon) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } - if (LightProfile_Struct::TypeToLevel(item->Light)) + if (EQEmu::LightSource::TypeToLevel(item->Light)) general_light_type = item->Light; } - if (LightProfile_Struct::IsLevelGreater(general_light_type, brightest_light_type)) + if (EQEmu::LightSource::IsLevelGreater(general_light_type, brightest_light_type)) brightest_light_type = general_light_type; return brightest_light_type; @@ -1209,7 +1209,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return legacy::SLOT_AUGMENT; + return EQEmu::Legacy::SLOT_AUGMENT; } if (!inst->IsType(ItemClassContainer)) { continue; } @@ -1226,7 +1226,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return legacy::SLOT_AUGMENT; + return EQEmu::Legacy::SLOT_AUGMENT; } } } @@ -1257,7 +1257,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return legacy::SLOT_AUGMENT; + return EQEmu::Legacy::SLOT_AUGMENT; } if (!inst->IsType(ItemClassContainer)) { continue; } @@ -1274,7 +1274,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return legacy::SLOT_AUGMENT; + return EQEmu::Legacy::SLOT_AUGMENT; } } @@ -1366,7 +1366,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return legacy::SLOT_AUGMENT; + return EQEmu::Legacy::SLOT_AUGMENT; } if (!inst->IsType(ItemClassContainer)) { continue; } @@ -1383,7 +1383,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return legacy::SLOT_AUGMENT; + return EQEmu::Legacy::SLOT_AUGMENT; } } } @@ -1406,7 +1406,7 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return legacy::SLOT_AUGMENT; + return EQEmu::Legacy::SLOT_AUGMENT; } if (!inst->IsType(ItemClassContainer)) { continue; } @@ -1423,7 +1423,7 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return legacy::SLOT_AUGMENT; + return EQEmu::Legacy::SLOT_AUGMENT; } } @@ -3089,66 +3089,3 @@ bool Item_Struct::IsEquipable(uint16 Race, uint16 Class_) const return (IsRace && IsClass); } - -// -// struct LightProfile_Struct -// -uint8 LightProfile_Struct::TypeToLevel(uint8 lightType) -{ - switch (lightType) { - case lightTypeGlobeOfStars: - return lightLevelBrilliant; // 10 - case lightTypeFlamelessLantern: - case lightTypeGreaterLightstone: - return lightLevelLargeMagic; // 9 - case lightTypeLargeLantern: - return lightLevelLargeLantern; // 8 - case lightTypeSteinOfMoggok: - case lightTypeLightstone: - return lightLevelMagicLantern; // 7 - case lightTypeSmallLantern: - return lightLevelSmallLantern; // 6 - case lightTypeColdlight: - case lightTypeUnknown2: - return lightLevelBlueLight; // 5 - case lightTypeFireBeetleEye: - case lightTypeUnknown1: - return lightLevelRedLight; // 4 - case lightTypeTinyGlowingSkull: - case lightTypeLightGlobe: - return lightLevelSmallMagic; // 3 - case lightTypeTorch: - return lightLevelTorch; // 2 - case lightTypeCandle: - return lightLevelCandle; // 1 - default: - return lightLevelUnlit; // 0 - } -} - -bool LightProfile_Struct::IsLevelGreater(uint8 leftType, uint8 rightType) -{ - static const uint8 light_levels[LIGHT_TYPES_COUNT] = { - lightLevelUnlit, /* lightTypeNone */ - lightLevelCandle, /* lightTypeCandle */ - lightLevelTorch, /* lightTypeTorch */ - lightLevelSmallMagic, /* lightTypeTinyGlowingSkull */ - lightLevelSmallLantern, /* lightTypeSmallLantern */ - lightLevelMagicLantern, /* lightTypeSteinOfMoggok */ - lightLevelLargeLantern, /* lightTypeLargeLantern */ - lightLevelLargeMagic, /* lightTypeFlamelessLantern */ - lightLevelBrilliant, /* lightTypeGlobeOfStars */ - lightLevelSmallMagic, /* lightTypeLightGlobe */ - lightLevelMagicLantern, /* lightTypeLightstone */ - lightLevelLargeMagic, /* lightTypeGreaterLightstone */ - lightLevelRedLight, /* lightTypeFireBeetleEye */ - lightLevelBlueLight, /* lightTypeColdlight */ - lightLevelRedLight, /* lightTypeUnknown1 */ - lightLevelBlueLight /* lightTypeUnknown2 */ - }; - - if (leftType >= LIGHT_TYPES_COUNT) { leftType = lightTypeNone; } - if (rightType >= LIGHT_TYPES_COUNT) { rightType = lightTypeNone; } - - return (light_levels[leftType] > light_levels[rightType]); -} diff --git a/common/item.h b/common/item.h index b6babde9f..28e714e31 100644 --- a/common/item.h +++ b/common/item.h @@ -525,43 +525,4 @@ public: ~EvolveInfo(); }; -struct LightProfile_Struct -{ - /* - Current criteria (light types): - Equipment: { 0 .. 15 } - General: { 9 .. 13 } - - Notes: - - Initial character load and item movement updates use different light source update behaviors - -- Server procedure matches the item movement behavior since most updates occur post-character load - - MainAmmo is not considered when determining light sources - - No 'Sub' or 'Aug' items are recognized as light sources - - Light types '< 9' and '> 13' are not considered for general (carried) light sources - - If values > 0x0F are valid, then assignment limiters will need to be removed - - MainCursor 'appears' to be a valid light source update slot..but, have not experienced updates during debug sessions - - All clients have a bug regarding stackable items (light and sound updates are not processed when picking up an item) - -- The timer-based update cancels out the invalid light source - */ - - static uint8 TypeToLevel(uint8 lightType); - static bool IsLevelGreater(uint8 leftType, uint8 rightType); - - // Light types (classifications) - struct { - uint8 Innate; // Defined by db field `npc_types`.`light` - where appropriate - uint8 Equipment; // Item_Struct::light value of worn/carried equipment - uint8 Spell; // Set value of any light-producing spell (can be modded to mimic equip_light behavior) - uint8 Active; // Highest value of all light sources - } Type; - - // Light levels (intensities) - used to determine which light source should be active - struct { - uint8 Innate; - uint8 Equipment; - uint8 Spell; - uint8 Active; - } Level; -}; - #endif // #define __ITEM_H diff --git a/common/item_struct.h b/common/item_struct.h index 0cae9806d..c22684207 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -42,8 +42,7 @@ * Made ya look! Ha! */ -//#include "eq_constants.h" -#include "eq_dictionary.h" +#include "emu_constants.h" /* ** Child struct of Item_Struct: diff --git a/common/light_source.cpp b/common/light_source.cpp new file mode 100644 index 000000000..9b20b4501 --- /dev/null +++ b/common/light_source.cpp @@ -0,0 +1,94 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "light_source.h" + + +void EQEmu::LightSource::impl::Clear() +{ + Type.Innate = 0; + Type.Equipment = 0; + Type.Spell = 0; + Type.Active = 0; + + Level.Innate = 0; + Level.Equipment = 0; + Level.Spell = 0; + Level.Active = 0; +} + +uint8 EQEmu::LightSource::TypeToLevel(uint8 light_type) +{ + switch (light_type) { + case TypeGlobeOfStars: + return LevelBrilliant; // 10 + case TypeFlamelessLantern: + case TypeGreaterLightstone: + return LevelLargeMagic; // 9 + case TypeLargeLantern: + return LevelLargeLantern; // 8 + case TypeSteinOfMoggok: + case TypeLightstone: + return LevelMagicLantern; // 7 + case TypeSmallLantern: + return LevelSmallLantern; // 6 + case TypeColdlight: + case TypeUnknown2: + return LevelBlueLight; // 5 + case TypeFireBeetleEye: + case TypeUnknown1: + return LevelRedLight; // 4 + case TypeTinyGlowingSkull: + case TypeLightGlobe: + return LevelSmallMagic; // 3 + case TypeTorch: + return LevelTorch; // 2 + case TypeCandle: + return LevelCandle; // 1 + default: + return LevelUnlit; // 0 + } +} + +bool EQEmu::LightSource::IsLevelGreater(uint8 left_type, uint8 right_type) +{ + static const uint8 light_levels[TypeCount] = { + LevelUnlit, /* TypeNone */ + LevelCandle, /* TypeCandle */ + LevelTorch, /* TypeTorch */ + LevelSmallMagic, /* TypeTinyGlowingSkull */ + LevelSmallLantern, /* TypeSmallLantern */ + LevelMagicLantern, /* TypeSteinOfMoggok */ + LevelLargeLantern, /* TypeLargeLantern */ + LevelLargeMagic, /* TypeFlamelessLantern */ + LevelBrilliant, /* TypeGlobeOfStars */ + LevelSmallMagic, /* TypeLightGlobe */ + LevelMagicLantern, /* TypeLightstone */ + LevelLargeMagic, /* TypeGreaterLightstone */ + LevelRedLight, /* TypeFireBeetleEye */ + LevelBlueLight, /* TypeColdlight */ + LevelRedLight, /* TypeUnknown1 */ + LevelBlueLight /* TypeUnknown2 */ + }; + + if (left_type >= TypeCount) { left_type = TypeNone; } + if (right_type >= TypeCount) { right_type = TypeNone; } + + return (light_levels[left_type] > light_levels[right_type]); +} diff --git a/common/light_source.h b/common/light_source.h new file mode 100644 index 000000000..3fabe7ebe --- /dev/null +++ b/common/light_source.h @@ -0,0 +1,109 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef LIGHT_SOURCE_H +#define LIGHT_SOURCE_H + +#include "types.h" + + +namespace EQEmu +{ + class LightSource { + public: + enum Types { + TypeNone = 0, + TypeCandle, + TypeTorch, + TypeTinyGlowingSkull, + TypeSmallLantern, + TypeSteinOfMoggok, // 5 + TypeLargeLantern, + TypeFlamelessLantern, + TypeGlobeOfStars, + TypeLightGlobe, + TypeLightstone, // 10 + TypeGreaterLightstone, + TypeFireBeetleEye, + TypeColdlight, + TypeUnknown1, + TypeUnknown2, // 15 + TypeCount + }; + + enum Levels { + LevelUnlit = 0, + LevelCandle, + LevelTorch, + LevelSmallMagic, + LevelRedLight, + LevelBlueLight, // 5 + LevelSmallLantern, + LevelMagicLantern, + LevelLargeLantern, + LevelLargeMagic, + LevelBrilliant, // 10 + LevelCount + }; + + class impl { + /* + Current criteria (light types): + Equipment: { 0 .. 15 } + General: { 9 .. 13 } + + Notes: + - Initial character load and item movement updates use different light source update behaviors + -- Server procedure matches the item movement behavior since most updates occur post-character load + - MainAmmo is not considered when determining light sources + - No 'Sub' or 'Aug' items are recognized as light sources + - Light types '< 9' and '> 13' are not considered for general (carried) light sources + - If values > 0x0F are valid, then assignment limiters will need to be removed + - MainCursor 'appears' to be a valid light source update slot..but, have not experienced updates during debug sessions + - All clients have a bug regarding stackable items (light and sound updates are not processed when picking up an item) + -- The timer-based update cancels out the invalid light source + */ + public: + impl() { Clear(); } + + void Clear(); + + // Light types (classifications) + struct { + uint8 Innate; // Defined by db field `npc_types`.`light` - where appropriate + uint8 Equipment; // Item_Struct::light value of worn/carried equipment + uint8 Spell; // Set value of any light-producing spell (can be modded to mimic equip_light behavior) + uint8 Active; // Highest value of all light sources + } Type; + + // Light levels (intensities) - used to determine which light source should be active + struct { + uint8 Innate; + uint8 Equipment; + uint8 Spell; + uint8 Active; + } Level; + }; + + static uint8 TypeToLevel(uint8 light_type); + static bool IsLevelGreater(uint8 left_type, uint8 right_type); + }; +} + +#endif /* LIGHT_SOURCE_H */ diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index d07281414..ad252d39d 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -5101,7 +5101,7 @@ namespace RoF int16 slot_id = RoFToServerSlot(eq->container_slot); if (slot_id == 4000) { - slot_id = legacy::SLOT_TRADESKILL; // 1000 + slot_id = EQEmu::Legacy::SLOT_TRADESKILL; // 1000 } emu->container_slot = slot_id; emu->guildtribute_slot = RoFToServerSlot(eq->guildtribute_slot); // this should only return INVALID_INDEX until implemented diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 776554cd3..684a89081 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -5372,7 +5372,7 @@ namespace RoF2 int16 slot_id = RoF2ToServerSlot(eq->container_slot); if (slot_id == 4000) { - slot_id = legacy::SLOT_TRADESKILL; // 1000 + slot_id = EQEmu::Legacy::SLOT_TRADESKILL; // 1000 } emu->container_slot = slot_id; emu->guildtribute_slot = RoF2ToServerSlot(eq->guildtribute_slot); // this should only return INVALID_INDEX until implemented diff --git a/common/say_link.cpp b/common/say_link.cpp new file mode 100644 index 000000000..4be401e91 --- /dev/null +++ b/common/say_link.cpp @@ -0,0 +1,272 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "emu_constants.h" + +#include "string_util.h" +#include "item.h" +#include "item_struct.h" +#include "../zone/zonedb.h" + + +std::string EQEmu::SayLink::impl::GenerateLink() +{ + m_Link.clear(); + m_LinkBody.clear(); + m_LinkText.clear(); + + generate_body(); + generate_text(); + + if ((m_LinkBody.length() == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) { + m_Link.push_back(0x12); + m_Link.append(m_LinkBody); + m_Link.append(m_LinkText); + m_Link.push_back(0x12); + } + + if ((m_Link.length() == 0) || (m_Link.length() > 250)) { + m_Error = true; + m_Link = ""; + Log.Out(Logs::General, Logs::Error, "TextLink::GenerateLink() failed to generate a useable text link (LinkType: %i, Lengths: {link: %u, body: %u, text: %u})", + m_LinkType, m_Link.length(), m_LinkBody.length(), m_LinkText.length()); + Log.Out(Logs::General, Logs::Error, ">> LinkBody: %s", m_LinkBody.c_str()); + Log.Out(Logs::General, Logs::Error, ">> LinkText: %s", m_LinkText.c_str()); + } + + return m_Link; +} + +void EQEmu::SayLink::impl::Reset() +{ + m_LinkType = LinkBlank; + m_ItemData = nullptr; + m_LootData = nullptr; + m_ItemInst = nullptr; + m_Proxy_unknown_1 = NOT_USED; + m_ProxyItemID = NOT_USED; + m_ProxyAugment1ID = NOT_USED; + m_ProxyAugment2ID = NOT_USED; + m_ProxyAugment3ID = NOT_USED; + m_ProxyAugment4ID = NOT_USED; + m_ProxyAugment5ID = NOT_USED; + m_ProxyAugment6ID = NOT_USED; + m_ProxyIsEvolving = NOT_USED; + m_ProxyEvolveGroup = NOT_USED; + m_ProxyEvolveLevel = NOT_USED; + m_ProxyOrnamentIcon = NOT_USED; + m_ProxyHash = NOT_USED; + m_ProxyText = nullptr; + m_TaskUse = false; + m_Link.clear(); + m_LinkBody.clear(); + m_LinkText.clear(); + m_Error = false; +} + +void EQEmu::SayLink::impl::generate_body() +{ + /* + Current server mask: EQClientRoF2 + + RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X" (56) + RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (55) + SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (50) + 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" (45) + */ + + memset(&m_LinkBodyStruct, 0, sizeof(SayLinkBody_Struct)); + + const Item_Struct* item_data = nullptr; + + switch (m_LinkType) { + case LinkBlank: + break; + case LinkItemData: + if (m_ItemData == nullptr) { break; } + m_LinkBodyStruct.item_id = m_ItemData->ID; + m_LinkBodyStruct.evolve_group = m_ItemData->LoreGroup; // this probably won't work for all items + //m_LinkBodyStruct.evolve_level = m_ItemData->EvolvingLevel; + // TODO: add hash call + break; + case LinkLootItem: + if (m_LootData == nullptr) { break; } + item_data = database.GetItem(m_LootData->item_id); + if (item_data == nullptr) { break; } + m_LinkBodyStruct.item_id = item_data->ID; + m_LinkBodyStruct.augment_1 = m_LootData->aug_1; + m_LinkBodyStruct.augment_2 = m_LootData->aug_2; + m_LinkBodyStruct.augment_3 = m_LootData->aug_3; + m_LinkBodyStruct.augment_4 = m_LootData->aug_4; + m_LinkBodyStruct.augment_5 = m_LootData->aug_5; + m_LinkBodyStruct.augment_6 = m_LootData->aug_6; + m_LinkBodyStruct.evolve_group = item_data->LoreGroup; // see note above + //m_LinkBodyStruct.evolve_level = item_data->EvolvingLevel; + // TODO: add hash call + break; + case LinkItemInst: + if (m_ItemInst == nullptr) { break; } + if (m_ItemInst->GetItem() == nullptr) { break; } + m_LinkBodyStruct.item_id = m_ItemInst->GetItem()->ID; + m_LinkBodyStruct.augment_1 = m_ItemInst->GetAugmentItemID(0); + m_LinkBodyStruct.augment_2 = m_ItemInst->GetAugmentItemID(1); + m_LinkBodyStruct.augment_3 = m_ItemInst->GetAugmentItemID(2); + m_LinkBodyStruct.augment_4 = m_ItemInst->GetAugmentItemID(3); + m_LinkBodyStruct.augment_5 = m_ItemInst->GetAugmentItemID(4); + m_LinkBodyStruct.augment_6 = m_ItemInst->GetAugmentItemID(5); + m_LinkBodyStruct.is_evolving = (m_ItemInst->IsEvolving() ? 1 : 0); + m_LinkBodyStruct.evolve_group = m_ItemInst->GetItem()->LoreGroup; // see note above + m_LinkBodyStruct.evolve_level = m_ItemInst->GetEvolveLvl(); + m_LinkBodyStruct.ornament_icon = m_ItemInst->GetOrnamentationIcon(); + // TODO: add hash call + break; + default: + break; + } + + if (m_Proxy_unknown_1) + m_LinkBodyStruct.unknown_1 = m_Proxy_unknown_1; + if (m_ProxyItemID) + m_LinkBodyStruct.item_id = m_ProxyItemID; + if (m_ProxyAugment1ID) + m_LinkBodyStruct.augment_1 = m_ProxyAugment1ID; + if (m_ProxyAugment2ID) + m_LinkBodyStruct.augment_2 = m_ProxyAugment2ID; + if (m_ProxyAugment3ID) + m_LinkBodyStruct.augment_3 = m_ProxyAugment3ID; + if (m_ProxyAugment4ID) + m_LinkBodyStruct.augment_4 = m_ProxyAugment4ID; + if (m_ProxyAugment5ID) + m_LinkBodyStruct.augment_5 = m_ProxyAugment5ID; + if (m_ProxyAugment6ID) + m_LinkBodyStruct.augment_6 = m_ProxyAugment6ID; + if (m_ProxyIsEvolving) + m_LinkBodyStruct.is_evolving = m_ProxyIsEvolving; + if (m_ProxyEvolveGroup) + m_LinkBodyStruct.evolve_group = m_ProxyEvolveGroup; + if (m_ProxyEvolveLevel) + m_LinkBodyStruct.evolve_level = m_ProxyEvolveLevel; + if (m_ProxyOrnamentIcon) + m_LinkBodyStruct.ornament_icon = m_ProxyOrnamentIcon; + if (m_ProxyHash) + m_LinkBodyStruct.hash = m_ProxyHash; + + + if (m_TaskUse) + m_LinkBodyStruct.hash = 0x14505DC2; + + m_LinkBody = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X", + (0x0F & m_LinkBodyStruct.unknown_1), + (0x000FFFFF & m_LinkBodyStruct.item_id), + (0x000FFFFF & m_LinkBodyStruct.augment_1), + (0x000FFFFF & m_LinkBodyStruct.augment_2), + (0x000FFFFF & m_LinkBodyStruct.augment_3), + (0x000FFFFF & m_LinkBodyStruct.augment_4), + (0x000FFFFF & m_LinkBodyStruct.augment_5), + (0x000FFFFF & m_LinkBodyStruct.augment_6), + (0x0F & m_LinkBodyStruct.is_evolving), + (0x0000FFFF & m_LinkBodyStruct.evolve_group), + (0xFF & m_LinkBodyStruct.evolve_level), + (0x000FFFFF & m_LinkBodyStruct.ornament_icon), + (0xFFFFFFFF & m_LinkBodyStruct.hash) + ); +} + +void EQEmu::SayLink::impl::generate_text() +{ + if (m_ProxyText != nullptr) { + m_LinkText = m_ProxyText; + return; + } + + const Item_Struct* item_data = nullptr; + + switch (m_LinkType) { + case LinkBlank: + break; + case LinkItemData: + if (m_ItemData == nullptr) { break; } + m_LinkText = m_ItemData->Name; + return; + case LinkLootItem: + if (m_LootData == nullptr) { break; } + item_data = database.GetItem(m_LootData->item_id); + if (item_data == nullptr) { break; } + m_LinkText = item_data->Name; + return; + case LinkItemInst: + if (m_ItemInst == nullptr) { break; } + if (m_ItemInst->GetItem() == nullptr) { break; } + m_LinkText = m_ItemInst->GetItem()->Name; + return; + default: + break; + } + + m_LinkText = "null"; +} + +bool EQEmu::SayLink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct, const std::string& say_link_body) +{ + memset(&say_link_body_struct, 0, sizeof(say_link_body_struct)); + if (say_link_body.length() != EQEmu::Constants::TEXT_LINK_BODY_LENGTH) + return false; + + say_link_body_struct.unknown_1 = (uint8)strtol(say_link_body.substr(0, 1).c_str(), nullptr, 16); + say_link_body_struct.item_id = (uint32)strtol(say_link_body.substr(1, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_1 = (uint32)strtol(say_link_body.substr(6, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_2 = (uint32)strtol(say_link_body.substr(11, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_3 = (uint32)strtol(say_link_body.substr(16, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_4 = (uint32)strtol(say_link_body.substr(21, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_5 = (uint32)strtol(say_link_body.substr(26, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_6 = (uint32)strtol(say_link_body.substr(31, 5).c_str(), nullptr, 16); + say_link_body_struct.is_evolving = (uint8)strtol(say_link_body.substr(36, 1).c_str(), nullptr, 16); + say_link_body_struct.evolve_group = (uint32)strtol(say_link_body.substr(37, 4).c_str(), nullptr, 16); + say_link_body_struct.evolve_level = (uint8)strtol(say_link_body.substr(41, 2).c_str(), nullptr, 16); + say_link_body_struct.ornament_icon = (uint32)strtol(say_link_body.substr(43, 5).c_str(), nullptr, 16); + say_link_body_struct.hash = (int)strtol(say_link_body.substr(48, 8).c_str(), nullptr, 16); + + return true; +} + +bool EQEmu::SayLink::GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct) +{ + say_link_body = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X", + (0x0F & say_link_body_struct.unknown_1), + (0x000FFFFF & say_link_body_struct.item_id), + (0x000FFFFF & say_link_body_struct.augment_1), + (0x000FFFFF & say_link_body_struct.augment_2), + (0x000FFFFF & say_link_body_struct.augment_3), + (0x000FFFFF & say_link_body_struct.augment_4), + (0x000FFFFF & say_link_body_struct.augment_5), + (0x000FFFFF & say_link_body_struct.augment_6), + (0x0F & say_link_body_struct.is_evolving), + (0x0000FFFF & say_link_body_struct.evolve_group), + (0xFF & say_link_body_struct.evolve_level), + (0x000FFFFF & say_link_body_struct.ornament_icon), + (0xFFFFFFFF & say_link_body_struct.hash) + ); + + if (say_link_body.length() != EQEmu::Constants::TEXT_LINK_BODY_LENGTH) + return false; + + return true; +} \ No newline at end of file diff --git a/common/say_link.h b/common/say_link.h new file mode 100644 index 000000000..34ba19bf7 --- /dev/null +++ b/common/say_link.h @@ -0,0 +1,130 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef SAY_LINK_H +#define SAY_LINK_H + +#include "types.h" + +#include + + +class ItemInst; +class Item_Struct; +class ServerLootItem_Struct; + + +namespace EQEmu +{ + class SayLink { + public: + enum Type { LinkBlank = 0, LinkItemData, LinkLootItem, LinkItemInst }; + + // Current server mask: EQClientRoF2 + struct SayLinkBody_Struct { + uint8 unknown_1; /* %1X */ + uint32 item_id; /* %05X */ + uint32 augment_1; /* %05X */ + uint32 augment_2; /* %05X */ + uint32 augment_3; /* %05X */ + uint32 augment_4; /* %05X */ + uint32 augment_5; /* %05X */ + uint32 augment_6; /* %05X */ + uint8 is_evolving; /* %1X */ + uint32 evolve_group; /* %05X */ + uint8 evolve_level; /* %02X */ + uint32 ornament_icon; /* %05X */ + int hash; /* %08X */ + }; + + class impl { + public: + impl() { Reset(); } + + void SetLinkType(Type link_type) { m_LinkType = link_type; } + void SetItemData(const Item_Struct* item_data) { m_ItemData = item_data; } + void SetLootData(const ServerLootItem_Struct* loot_data) { m_LootData = loot_data; } + void SetItemInst(const ItemInst* item_inst) { m_ItemInst = item_inst; } + + // mainly for saylinks..but, not limited to + void SetProxyUnknown1(uint8 proxy_unknown_1) { m_Proxy_unknown_1 = proxy_unknown_1; } + void SetProxyItemID(uint32 proxy_item_id) { m_ProxyItemID = proxy_item_id; } + void SetProxyAugment1ID(uint32 proxy_augment_id) { m_ProxyAugment1ID = proxy_augment_id; } + void SetProxyAugment2ID(uint32 proxy_augment_id) { m_ProxyAugment2ID = proxy_augment_id; } + void SetProxyAugment3ID(uint32 proxy_augment_id) { m_ProxyAugment3ID = proxy_augment_id; } + void SetProxyAugment4ID(uint32 proxy_augment_id) { m_ProxyAugment4ID = proxy_augment_id; } + void SetProxyAugment5ID(uint32 proxy_augment_id) { m_ProxyAugment5ID = proxy_augment_id; } + void SetProxyAugment6ID(uint32 proxy_augment_id) { m_ProxyAugment6ID = proxy_augment_id; } + void SetProxyIsEvolving(uint8 proxy_is_evolving) { m_ProxyIsEvolving = proxy_is_evolving; } + void SetProxyEvolveGroup(uint32 proxy_evolve_group) { m_ProxyEvolveGroup = proxy_evolve_group; } + void SetProxyEvolveLevel(uint8 proxy_evolve_level) { m_ProxyEvolveLevel = proxy_evolve_level; } + void SetProxyOrnamentIcon(uint32 proxy_ornament_icon) { m_ProxyOrnamentIcon = proxy_ornament_icon; } + void SetProxyHash(int proxy_hash) { m_ProxyHash = proxy_hash; } + + void SetProxyText(const char* proxy_text) { m_ProxyText = proxy_text; } // overrides standard text use + void SetTaskUse() { m_TaskUse = true; } + + std::string GenerateLink(); + bool LinkError() { return m_Error; } + + std::string GetLink() { return m_Link; } // contains full string format: '/12x' '' '' '/12x' + std::string GetLinkBody() { return m_LinkBody; } // contains string format: '' + std::string GetLinkText() { return m_LinkText; } // contains string format: '' + + void Reset(); + + private: + void generate_body(); + void generate_text(); + + int m_LinkType; + const Item_Struct* m_ItemData; + const ServerLootItem_Struct* m_LootData; + const ItemInst* m_ItemInst; + + uint8 m_Proxy_unknown_1; + uint32 m_ProxyItemID; + uint32 m_ProxyAugment1ID; + uint32 m_ProxyAugment2ID; + uint32 m_ProxyAugment3ID; + uint32 m_ProxyAugment4ID; + uint32 m_ProxyAugment5ID; + uint32 m_ProxyAugment6ID; + uint8 m_ProxyIsEvolving; + uint32 m_ProxyEvolveGroup; + uint8 m_ProxyEvolveLevel; + uint32 m_ProxyOrnamentIcon; + int m_ProxyHash; + const char* m_ProxyText; + bool m_TaskUse; + SayLinkBody_Struct m_LinkBodyStruct; + std::string m_Link; + std::string m_LinkBody; + std::string m_LinkText; + bool m_Error; + }; + + + + static bool DegenerateLinkBody(SayLinkBody_Struct& say_Link_body_struct, const std::string& say_link_body); + static bool GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct); + }; +} + +#endif /* SAY_LINK_H */ diff --git a/zone/aa.cpp b/zone/aa.cpp index 229683550..9301f240a 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -23,7 +23,6 @@ Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) #include "../common/races.h" #include "../common/spdat.h" #include "../common/string_util.h" -#include "../common/deity.h" #include "aa.h" #include "client.h" #include "corpse.h" @@ -1434,7 +1433,7 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { return false; } - auto deity = ConvertDeityToBitDeity((DeityTypes)GetDeity()); + auto deity = GetDeityBit(); if(!(ability->deities & deity)) { return false; } diff --git a/zone/bot.cpp b/zone/bot.cpp index d8693251a..f3344bdac 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -93,7 +93,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm timers[i] = 0; strcpy(this->name, this->GetCleanName()); - memset(&m_Light, 0, sizeof(LightProfile_Struct)); + memset(&m_Light, 0, sizeof(EQEmu::LightSource::impl)); memset(&_botInspectMessage, 0, sizeof(InspectMessage_Struct)); } @@ -8469,8 +8469,8 @@ std::string Bot::CreateSayLink(Client* c, const char* message, const char* name) uint32 saylink_id = database.LoadSaylinkID(escaped_string); safe_delete_array(escaped_string); - Client::TextLink linker; - linker.SetLinkType(linker.linkItemData); + EQEmu::SayLink::impl linker; + linker.SetLinkType(EQEmu::SayLink::LinkItemData); linker.SetProxyItemID(SAYLINK_ITEM_ID); linker.SetProxyAugment1ID(saylink_id); linker.SetProxyText(name); diff --git a/zone/bot.h b/zone/bot.h index 0b39ee079..34791b5a4 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -386,7 +386,7 @@ public: void BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true); void EquipBot(std::string* errorMessage); bool CheckLoreConflict(const Item_Struct* item); - virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); } + virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); } // Static Class Methods //static void DestroyBotRaidObjects(Client* client); // Can be removed after bot raids are dumped diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 3553f7e8d..0c1d6037b 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -7066,8 +7066,8 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) bool is2Hweapon = false; std::string item_link; - Client::TextLink linker; - linker.SetLinkType(linker.linkItemInst); + EQEmu::SayLink::impl linker; + linker.SetLinkType(EQEmu::SayLink::LinkItemInst); uint32 inventory_count = 0; for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= (EQEmu::Constants::EQUIPMENT_END + 1); ++i) { diff --git a/zone/client.cpp b/zone/client.cpp index d07de3016..2097e8374 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8416,252 +8416,6 @@ void Client::SendColoredText(uint32 color, std::string message) } -// -// class Client::TextLink -// -std::string Client::TextLink::GenerateLink() -{ - m_Link.clear(); - m_LinkBody.clear(); - m_LinkText.clear(); - - generate_body(); - generate_text(); - - if ((m_LinkBody.length() == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) { - m_Link.push_back(0x12); - m_Link.append(m_LinkBody); - m_Link.append(m_LinkText); - m_Link.push_back(0x12); - } - - if ((m_Link.length() == 0) || (m_Link.length() > 250)) { - m_Error = true; - m_Link = ""; - Log.Out(Logs::General, Logs::Error, "TextLink::GenerateLink() failed to generate a useable text link (LinkType: %i, Lengths: {link: %u, body: %u, text: %u})", - m_LinkType, m_Link.length(), m_LinkBody.length(), m_LinkText.length()); - Log.Out(Logs::General, Logs::Error, ">> LinkBody: %s", m_LinkBody.c_str()); - Log.Out(Logs::General, Logs::Error, ">> LinkText: %s", m_LinkText.c_str()); - } - - return m_Link; -} - -void Client::TextLink::Reset() -{ - m_LinkType = linkBlank; - m_ItemData = nullptr; - m_LootData = nullptr; - m_ItemInst = nullptr; - m_Proxy_unknown_1 = NOT_USED; - m_ProxyItemID = NOT_USED; - m_ProxyAugment1ID = NOT_USED; - m_ProxyAugment2ID = NOT_USED; - m_ProxyAugment3ID = NOT_USED; - m_ProxyAugment4ID = NOT_USED; - m_ProxyAugment5ID = NOT_USED; - m_ProxyAugment6ID = NOT_USED; - m_ProxyIsEvolving = NOT_USED; - m_ProxyEvolveGroup = NOT_USED; - m_ProxyEvolveLevel = NOT_USED; - m_ProxyOrnamentIcon = NOT_USED; - m_ProxyHash = NOT_USED; - m_ProxyText = nullptr; - m_TaskUse = false; - m_Link.clear(); - m_LinkBody.clear(); - m_LinkText.clear(); - m_Error = false; -} - -void Client::TextLink::generate_body() -{ - /* - Current server mask: EQClientRoF2 - - RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X" (56) - RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (55) - SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (50) - 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" (45) - */ - - memset(&m_LinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); - - const Item_Struct* item_data = nullptr; - - switch (m_LinkType) { - case linkBlank: - break; - case linkItemData: - if (m_ItemData == nullptr) { break; } - m_LinkBodyStruct.item_id = m_ItemData->ID; - m_LinkBodyStruct.evolve_group = m_ItemData->LoreGroup; // this probably won't work for all items - //m_LinkBodyStruct.evolve_level = m_ItemData->EvolvingLevel; - // TODO: add hash call - break; - case linkLootItem: - if (m_LootData == nullptr) { break; } - item_data = database.GetItem(m_LootData->item_id); - if (item_data == nullptr) { break; } - m_LinkBodyStruct.item_id = item_data->ID; - m_LinkBodyStruct.augment_1 = m_LootData->aug_1; - m_LinkBodyStruct.augment_2 = m_LootData->aug_2; - m_LinkBodyStruct.augment_3 = m_LootData->aug_3; - m_LinkBodyStruct.augment_4 = m_LootData->aug_4; - m_LinkBodyStruct.augment_5 = m_LootData->aug_5; - m_LinkBodyStruct.augment_6 = m_LootData->aug_6; - m_LinkBodyStruct.evolve_group = item_data->LoreGroup; // see note above - //m_LinkBodyStruct.evolve_level = item_data->EvolvingLevel; - // TODO: add hash call - break; - case linkItemInst: - if (m_ItemInst == nullptr) { break; } - if (m_ItemInst->GetItem() == nullptr) { break; } - m_LinkBodyStruct.item_id = m_ItemInst->GetItem()->ID; - m_LinkBodyStruct.augment_1 = m_ItemInst->GetAugmentItemID(0); - m_LinkBodyStruct.augment_2 = m_ItemInst->GetAugmentItemID(1); - m_LinkBodyStruct.augment_3 = m_ItemInst->GetAugmentItemID(2); - m_LinkBodyStruct.augment_4 = m_ItemInst->GetAugmentItemID(3); - m_LinkBodyStruct.augment_5 = m_ItemInst->GetAugmentItemID(4); - m_LinkBodyStruct.augment_6 = m_ItemInst->GetAugmentItemID(5); - m_LinkBodyStruct.is_evolving = (m_ItemInst->IsEvolving() ? 1 : 0); - m_LinkBodyStruct.evolve_group = m_ItemInst->GetItem()->LoreGroup; // see note above - m_LinkBodyStruct.evolve_level = m_ItemInst->GetEvolveLvl(); - m_LinkBodyStruct.ornament_icon = m_ItemInst->GetOrnamentationIcon(); - // TODO: add hash call - break; - default: - break; - } - - if (m_Proxy_unknown_1) - m_LinkBodyStruct.unknown_1 = m_Proxy_unknown_1; - if (m_ProxyItemID) - m_LinkBodyStruct.item_id = m_ProxyItemID; - if (m_ProxyAugment1ID) - m_LinkBodyStruct.augment_1 = m_ProxyAugment1ID; - if (m_ProxyAugment2ID) - m_LinkBodyStruct.augment_2 = m_ProxyAugment2ID; - if (m_ProxyAugment3ID) - m_LinkBodyStruct.augment_3 = m_ProxyAugment3ID; - if (m_ProxyAugment4ID) - m_LinkBodyStruct.augment_4 = m_ProxyAugment4ID; - if (m_ProxyAugment5ID) - m_LinkBodyStruct.augment_5 = m_ProxyAugment5ID; - if (m_ProxyAugment6ID) - m_LinkBodyStruct.augment_6 = m_ProxyAugment6ID; - if (m_ProxyIsEvolving) - m_LinkBodyStruct.is_evolving = m_ProxyIsEvolving; - if (m_ProxyEvolveGroup) - m_LinkBodyStruct.evolve_group = m_ProxyEvolveGroup; - if (m_ProxyEvolveLevel) - m_LinkBodyStruct.evolve_level = m_ProxyEvolveLevel; - if (m_ProxyOrnamentIcon) - m_LinkBodyStruct.ornament_icon = m_ProxyOrnamentIcon; - if (m_ProxyHash) - m_LinkBodyStruct.hash = m_ProxyHash; - - - if (m_TaskUse) - m_LinkBodyStruct.hash = 0x14505DC2; - - m_LinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X", - (0x0F & m_LinkBodyStruct.unknown_1), - (0x000FFFFF & m_LinkBodyStruct.item_id), - (0x000FFFFF & m_LinkBodyStruct.augment_1), - (0x000FFFFF & m_LinkBodyStruct.augment_2), - (0x000FFFFF & m_LinkBodyStruct.augment_3), - (0x000FFFFF & m_LinkBodyStruct.augment_4), - (0x000FFFFF & m_LinkBodyStruct.augment_5), - (0x000FFFFF & m_LinkBodyStruct.augment_6), - (0x0F & m_LinkBodyStruct.is_evolving), - (0x0000FFFF & m_LinkBodyStruct.evolve_group), - (0xFF & m_LinkBodyStruct.evolve_level), - (0x000FFFFF & m_LinkBodyStruct.ornament_icon), - (0xFFFFFFFF & m_LinkBodyStruct.hash) - ); -} - -void Client::TextLink::generate_text() -{ - if (m_ProxyText != nullptr) { - m_LinkText = m_ProxyText; - return; - } - - const Item_Struct* item_data = nullptr; - - switch (m_LinkType) { - case linkBlank: - break; - case linkItemData: - if (m_ItemData == nullptr) { break; } - m_LinkText = m_ItemData->Name; - return; - case linkLootItem: - if (m_LootData == nullptr) { break; } - item_data = database.GetItem(m_LootData->item_id); - if (item_data == nullptr) { break; } - m_LinkText = item_data->Name; - return; - case linkItemInst: - if (m_ItemInst == nullptr) { break; } - if (m_ItemInst->GetItem() == nullptr) { break; } - m_LinkText = m_ItemInst->GetItem()->Name; - return; - default: - break; - } - - m_LinkText = "null"; -} - -bool Client::TextLink::DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruct, const std::string& textLinkBody) -{ - memset(&textLinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); - if (textLinkBody.length() != EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { return false; } - - textLinkBodyStruct.unknown_1 = (uint8)strtol(textLinkBody.substr(0, 1).c_str(), nullptr, 16); - textLinkBodyStruct.item_id = (uint32)strtol(textLinkBody.substr(1, 5).c_str(), nullptr, 16); - textLinkBodyStruct.augment_1 = (uint32)strtol(textLinkBody.substr(6, 5).c_str(), nullptr, 16); - textLinkBodyStruct.augment_2 = (uint32)strtol(textLinkBody.substr(11, 5).c_str(), nullptr, 16); - textLinkBodyStruct.augment_3 = (uint32)strtol(textLinkBody.substr(16, 5).c_str(), nullptr, 16); - textLinkBodyStruct.augment_4 = (uint32)strtol(textLinkBody.substr(21, 5).c_str(), nullptr, 16); - textLinkBodyStruct.augment_5 = (uint32)strtol(textLinkBody.substr(26, 5).c_str(), nullptr, 16); - textLinkBodyStruct.augment_6 = (uint32)strtol(textLinkBody.substr(31, 5).c_str(), nullptr, 16); - textLinkBodyStruct.is_evolving = (uint8)strtol(textLinkBody.substr(36, 1).c_str(), nullptr, 16); - textLinkBodyStruct.evolve_group = (uint32)strtol(textLinkBody.substr(37, 4).c_str(), nullptr, 16); - textLinkBodyStruct.evolve_level = (uint8)strtol(textLinkBody.substr(41, 2).c_str(), nullptr, 16); - textLinkBodyStruct.ornament_icon = (uint32)strtol(textLinkBody.substr(43, 5).c_str(), nullptr, 16); - textLinkBodyStruct.hash = (int)strtol(textLinkBody.substr(48, 8).c_str(), nullptr, 16); - - return true; -} - -bool Client::TextLink::GenerateLinkBody(std::string& textLinkBody, const TextLinkBody_Struct& textLinkBodyStruct) -{ - textLinkBody = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X", - (0x0F & textLinkBodyStruct.unknown_1), - (0x000FFFFF & textLinkBodyStruct.item_id), - (0x000FFFFF & textLinkBodyStruct.augment_1), - (0x000FFFFF & textLinkBodyStruct.augment_2), - (0x000FFFFF & textLinkBodyStruct.augment_3), - (0x000FFFFF & textLinkBodyStruct.augment_4), - (0x000FFFFF & textLinkBodyStruct.augment_5), - (0x000FFFFF & textLinkBodyStruct.augment_6), - (0x0F & textLinkBodyStruct.is_evolving), - (0x0000FFFF & textLinkBodyStruct.evolve_group), - (0xFF & textLinkBodyStruct.evolve_level), - (0x000FFFFF & textLinkBodyStruct.ornament_icon), - (0xFFFFFFFF & textLinkBodyStruct.hash) - ); - - if (textLinkBody.length() != EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { return false; } - return true; -} - void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct)); diff --git a/zone/client.h b/zone/client.h index 544007e9b..47c3a10ee 100644 --- a/zone/client.h +++ b/zone/client.h @@ -736,7 +736,7 @@ public: #endif uint32 GetEquipment(uint8 material_slot) const; // returns item id uint32 GetEquipmentColor(uint8 material_slot) const; - virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); } + virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); } inline bool AutoSplitEnabled() { return m_pp.autosplit != 0; } @@ -818,81 +818,6 @@ public: void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); - // - // class Client::TextLink - // - class TextLink { - public: - enum LinkType { linkBlank = 0, linkItemData, linkLootItem, linkItemInst }; - - TextLink() { Reset(); } - - void SetLinkType(LinkType linkType) { m_LinkType = linkType; } - void SetItemData(const Item_Struct* itemData) { m_ItemData = itemData; } - void SetLootData(const ServerLootItem_Struct* lootData) { m_LootData = lootData; } - void SetItemInst(const ItemInst* itemInst) { m_ItemInst = itemInst; } - - // mainly for saylinks..but, not limited to - void SetProxyUnknown1(uint8 proxyUnknown1) { m_Proxy_unknown_1 = proxyUnknown1; } - void SetProxyItemID(uint32 proxyItemID) { m_ProxyItemID = proxyItemID; } - void SetProxyAugment1ID(uint32 proxyAugmentID) { m_ProxyAugment1ID = proxyAugmentID; } - void SetProxyAugment2ID(uint32 proxyAugmentID) { m_ProxyAugment2ID = proxyAugmentID; } - void SetProxyAugment3ID(uint32 proxyAugmentID) { m_ProxyAugment3ID = proxyAugmentID; } - void SetProxyAugment4ID(uint32 proxyAugmentID) { m_ProxyAugment4ID = proxyAugmentID; } - void SetProxyAugment5ID(uint32 proxyAugmentID) { m_ProxyAugment5ID = proxyAugmentID; } - void SetProxyAugment6ID(uint32 proxyAugmentID) { m_ProxyAugment6ID = proxyAugmentID; } - void SetProxyIsEvolving(uint8 proxyIsEvolving) { m_ProxyIsEvolving = proxyIsEvolving; } - void SetProxyEvolveGroup(uint32 proxyEvolveGroup) { m_ProxyEvolveGroup = proxyEvolveGroup; } - void SetProxyEvolveLevel(uint8 proxyEvolveLevel) { m_ProxyEvolveLevel = proxyEvolveLevel; } - void SetProxyOrnamentIcon(uint32 proxyOrnamentIcon) { m_ProxyOrnamentIcon = proxyOrnamentIcon; } - void SetProxyHash(int proxyHash) { m_ProxyHash = proxyHash; } - - void SetProxyText(const char* proxyText) { m_ProxyText = proxyText; } // overrides standard text use - void SetTaskUse() { m_TaskUse = true; } - - std::string GenerateLink(); - bool LinkError() { return m_Error; } - - std::string GetLink() { return m_Link; } // contains full string format: '/12x' '' '' '/12x' - std::string GetLinkBody() { return m_LinkBody; } // contains string format: '' - std::string GetLinkText() { return m_LinkText; } // contains string format: '' - - void Reset(); - - static bool DegenerateLinkBody(TextLinkBody_Struct& textLinkBodyStruct, const std::string& textLinkBody); - static bool GenerateLinkBody(std::string& textLinkBody, const TextLinkBody_Struct& textLinkBodyStruct); - - private: - void generate_body(); - void generate_text(); - - int m_LinkType; - const Item_Struct* m_ItemData; - const ServerLootItem_Struct* m_LootData; - const ItemInst* m_ItemInst; - - uint8 m_Proxy_unknown_1; - uint32 m_ProxyItemID; - uint32 m_ProxyAugment1ID; - uint32 m_ProxyAugment2ID; - uint32 m_ProxyAugment3ID; - uint32 m_ProxyAugment4ID; - uint32 m_ProxyAugment5ID; - uint32 m_ProxyAugment6ID; - uint8 m_ProxyIsEvolving; - uint32 m_ProxyEvolveGroup; - uint8 m_ProxyEvolveLevel; - uint32 m_ProxyOrnamentIcon; - int m_ProxyHash; - const char* m_ProxyText; - bool m_TaskUse; - TextLinkBody_Struct m_LinkBodyStruct; - std::string m_Link; - std::string m_LinkBody; - std::string m_LinkText; - bool m_Error; - }; - int GetItemLinkHash(const ItemInst* inst); // move to Item_Struct..or make use of the pre-calculated database field void SendItemLink(const ItemInst* inst, bool sendtoall=false); diff --git a/zone/command.cpp b/zone/command.cpp index b3f00eed3..97b3ac980 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2545,8 +2545,8 @@ void command_peekinv(Client *c, const Seperator *sep) const ItemInst* inst_sub = nullptr; const Item_Struct* item_data = nullptr; std::string item_link; - Client::TextLink linker; - linker.SetLinkType(linker.linkItemInst); + EQEmu::SayLink::impl linker; + linker.SetLinkType(EQEmu::SayLink::LinkItemInst); c->Message(0, "Displaying inventory for %s...", targetClient->GetName()); @@ -4341,8 +4341,8 @@ void command_iteminfo(Client *c, const Seperator *sep) c->Message(13, "Error: This item has no data reference"); } - Client::TextLink linker; - linker.SetLinkType(linker.linkItemInst); + EQEmu::SayLink::impl linker; + linker.SetLinkType(EQEmu::SayLink::LinkItemInst); linker.SetItemInst(inst); auto item_link = linker.GenerateLink(); @@ -5492,8 +5492,8 @@ void command_summonitem(Client *c, const Seperator *sep) size_t link_open = cmd_msg.find('\x12'); size_t link_close = cmd_msg.find_last_of('\x12'); if (link_open != link_close && (cmd_msg.length() - link_open) > EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { - TextLinkBody_Struct link_body; - Client::TextLink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQEmu::Constants::TEXT_LINK_BODY_LENGTH)); + EQEmu::SayLink::SayLinkBody_Struct link_body; + EQEmu::SayLink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQEmu::Constants::TEXT_LINK_BODY_LENGTH)); itemid = link_body.item_id; } else if (!sep->IsNumber(1)) { @@ -5603,8 +5603,8 @@ void command_itemsearch(Client *c, const Seperator *sep) const Item_Struct* item = nullptr; std::string item_link; - Client::TextLink linker; - linker.SetLinkType(linker.linkItemData); + EQEmu::SayLink::impl linker; + linker.SetLinkType(EQEmu::SayLink::LinkItemData); if (Seperator::IsNumber(search_criteria)) { item = database.GetItem(atoi(search_criteria)); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 45d4eeb53..b45aae96b 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1225,8 +1225,8 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } /* Send message with item link to groups and such */ - Client::TextLink linker; - linker.SetLinkType(linker.linkItemInst); + EQEmu::SayLink::impl linker; + linker.SetLinkType(EQEmu::SayLink::LinkItemInst); linker.SetItemInst(inst); auto item_link = linker.GenerateLink(); @@ -1442,7 +1442,7 @@ void Corpse::UpdateEquipmentLight() auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } - if (m_Light.IsLevelGreater(item->Light, m_Light.Type.Equipment)) + if (EQEmu::LightSource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) m_Light.Type.Equipment = item->Light; } @@ -1456,14 +1456,14 @@ void Corpse::UpdateEquipmentLight() if (item->ItemClass != ItemClassCommon) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } - if (m_Light.TypeToLevel(item->Light)) + if (EQEmu::LightSource::TypeToLevel(item->Light)) general_light_type = item->Light; } - if (m_Light.IsLevelGreater(general_light_type, m_Light.Type.Equipment)) + if (EQEmu::LightSource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) m_Light.Type.Equipment = general_light_type; - m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); + m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); } void Corpse::AddLooter(Mob* who) { diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 4e8f1e8d0..2b345d847 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1799,8 +1799,8 @@ luabind::scope lua_register_slot() { luabind::value("PersonalEnd", static_cast(EQEmu::Constants::GENERAL_END)), // deprecated luabind::value("GeneralEnd", static_cast(EQEmu::Constants::GENERAL_END)), luabind::value("CursorEnd", 0xFFFE), // deprecated - luabind::value("Tradeskill", static_cast(legacy::SLOT_TRADESKILL)), // deprecated - luabind::value("Augment", static_cast(legacy::SLOT_AUGMENT)), // deprecated + luabind::value("Tradeskill", static_cast(EQEmu::Legacy::SLOT_TRADESKILL)), // deprecated + luabind::value("Augment", static_cast(EQEmu::Legacy::SLOT_AUGMENT)), // deprecated luabind::value("Invalid", INVALID_INDEX) ]; } diff --git a/zone/merc.cpp b/zone/merc.cpp index 19d846280..91d66523c 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -5050,9 +5050,9 @@ void Merc::UpdateEquipmentLight() auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } - if (m_Light.IsLevelGreater(item->Light, m_Light.Type.Equipment)) { + if (EQEmu::LightSource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) { m_Light.Type.Equipment = item->Light; - m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); + m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); } } @@ -5064,14 +5064,14 @@ void Merc::UpdateEquipmentLight() if (item->ItemClass != ItemClassCommon) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } - if (m_Light.TypeToLevel(item->Light)) + if (EQEmu::LightSource::TypeToLevel(item->Light)) general_light_type = item->Light; } - if (m_Light.IsLevelGreater(general_light_type, m_Light.Type.Equipment)) + if (EQEmu::LightSource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) m_Light.Type.Equipment = general_light_type; - m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); + m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); } void Merc::AddItem(uint8 slot, uint32 item_id) { diff --git a/zone/mob.cpp b/zone/mob.cpp index 86e90247f..f7751a871 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -179,7 +179,7 @@ Mob::Mob(const char* in_name, runspeed = 1.25f; m_Light.Type.Innate = in_light; - m_Light.Level.Innate = m_Light.TypeToLevel(m_Light.Type.Innate); + m_Light.Level.Innate = EQEmu::LightSource::TypeToLevel(m_Light.Type.Innate); m_Light.Level.Equipment = m_Light.Type.Equipment = 0; m_Light.Level.Spell = m_Light.Type.Spell = 0; m_Light.Type.Active = m_Light.Type.Innate; @@ -2232,11 +2232,11 @@ bool Mob::UpdateActiveLight() m_Light.Type.Active = 0; m_Light.Level.Active = 0; - if (m_Light.IsLevelGreater((m_Light.Type.Innate & 0x0F), m_Light.Type.Active)) { m_Light.Type.Active = m_Light.Type.Innate; } + if (EQEmu::LightSource::IsLevelGreater((m_Light.Type.Innate & 0x0F), m_Light.Type.Active)) { m_Light.Type.Active = m_Light.Type.Innate; } if (m_Light.Level.Equipment > m_Light.Level.Active) { m_Light.Type.Active = m_Light.Type.Equipment; } // limiter in property handler if (m_Light.Level.Spell > m_Light.Level.Active) { m_Light.Type.Active = m_Light.Type.Spell; } // limiter in property handler - m_Light.Level.Active = m_Light.TypeToLevel(m_Light.Type.Active); + m_Light.Level.Active = EQEmu::LightSource::TypeToLevel(m_Light.Type.Active); return (m_Light.Level.Active != old_light_level); } diff --git a/zone/mob.h b/zone/mob.h index a55ff49ce..32ddcc643 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -364,6 +364,7 @@ public: virtual inline uint16 GetBaseRace() const { return base_race; } virtual inline uint8 GetBaseGender() const { return base_gender; } virtual inline uint16 GetDeity() const { return deity; } + virtual inline EQEmu::Deity::TypeBits GetDeityBit() { return EQEmu::Deity::ConvertDeityToDeityBit((EQEmu::Deity::Types)deity); } inline uint16 GetRace() const { return race; } inline uint8 GetGender() const { return gender; } inline uint8 GetTexture() const { return texture; } @@ -707,12 +708,12 @@ public: inline uint8 GetSpellLightType() { return m_Light.Type.Spell; } virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = 0; m_Light.Level.Equipment = 0; } - inline void SetSpellLightType(uint8 lightType) { m_Light.Type.Spell = (lightType & 0x0F); m_Light.Level.Spell = m_Light.TypeToLevel(m_Light.Type.Spell); } + inline void SetSpellLightType(uint8 light_type) { m_Light.Type.Spell = (light_type & 0x0F); m_Light.Level.Spell = EQEmu::LightSource::TypeToLevel(m_Light.Type.Spell); } inline uint8 GetActiveLightType() { return m_Light.Type.Active; } bool UpdateActiveLight(); // returns true if change, false if no change - LightProfile_Struct* GetLightProfile() { return &m_Light; } + EQEmu::LightSource::impl* GetLightProfile() { return &m_Light; } Mob* GetPet(); void SetPet(Mob* newpet); @@ -1184,7 +1185,7 @@ protected: glm::vec4 m_Delta; - LightProfile_Struct m_Light; + EQEmu::LightSource::impl m_Light; float fixedZ; EmuAppearance _appearance; diff --git a/zone/npc.cpp b/zone/npc.cpp index 25cdcfb86..648bbb563 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -529,8 +529,8 @@ void NPC::QueryLoot(Client* to) continue; } - Client::TextLink linker; - linker.SetLinkType(linker.linkItemData); + EQEmu::SayLink::impl linker; + linker.SetLinkType(EQEmu::SayLink::LinkItemData); linker.SetItemData(item); auto item_link = linker.GenerateLink(); @@ -754,9 +754,9 @@ void NPC::UpdateEquipmentLight() auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } - if (m_Light.IsLevelGreater(item->Light, m_Light.Type.Equipment)) { + if (EQEmu::LightSource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) { m_Light.Type.Equipment = item->Light; - m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); + m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); } } @@ -768,14 +768,14 @@ void NPC::UpdateEquipmentLight() if (item->ItemClass != ItemClassCommon) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } - if (m_Light.TypeToLevel(item->Light)) + if (EQEmu::LightSource::TypeToLevel(item->Light)) general_light_type = item->Light; } - if (m_Light.IsLevelGreater(general_light_type, m_Light.Type.Equipment)) + if (EQEmu::LightSource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) m_Light.Type.Equipment = general_light_type; - m_Light.Level.Equipment = m_Light.TypeToLevel(m_Light.Type.Equipment); + m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); } void NPC::Depop(bool StartSpawnTimer) { diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index ce4c3e861..abfa27a01 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1307,8 +1307,8 @@ void QuestManager::itemlink(int item_id) { if (item == nullptr) return; - Client::TextLink linker; - linker.SetLinkType(linker.linkItemData); + EQEmu::SayLink::impl linker; + linker.SetLinkType(EQEmu::SayLink::LinkItemData); linker.SetItemData(item); auto item_link = linker.GenerateLink(); @@ -2535,8 +2535,8 @@ const char* QuestManager::varlink(char* perltext, int item_id) { if (!item) return "INVALID ITEM ID IN VARLINK"; - Client::TextLink linker; - linker.SetLinkType(linker.linkItemData); + EQEmu::SayLink::impl linker; + linker.SetLinkType(EQEmu::SayLink::LinkItemData); linker.SetItemData(item); auto item_link = linker.GenerateLink(); @@ -2761,7 +2761,7 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam safe_delete_array(escaped_string); //Create the say link as an item link hash - Client::TextLink linker; + EQEmu::SayLink::impl linker; linker.SetProxyItemID(SAYLINK_ITEM_ID); if (silent) linker.SetProxyAugment2ID(sayid); diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 0e7de67cb..a10dc4204 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -2779,8 +2779,8 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN if(ItemID) { const Item_Struct* reward_item = database.GetItem(ItemID); - Client::TextLink linker; - linker.SetLinkType(linker.linkItemData); + EQEmu::SayLink::impl linker; + linker.SetLinkType(EQEmu::SayLink::LinkItemData); linker.SetItemData(reward_item); linker.SetTaskUse(); if (strlen(Tasks[TaskID]->Reward) != 0) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index e6a4b25b5..61e0f2bc8 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -264,7 +264,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob uint32 some_id = 0; bool worldcontainer=false; - if (in_combine->container_slot == legacy::SLOT_TRADESKILL) { + if (in_combine->container_slot == EQEmu::Legacy::SLOT_TRADESKILL) { if(!worldo) { user->Message(13, "Error: Server is not aware of the tradeskill container you are attempting to use"); return; From 53c7abf16e51ed88a0af4c5b4749cc75aed19700 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sun, 17 Apr 2016 16:25:46 -0700 Subject: [PATCH 050/693] Fix for ModifyNPCStat when checking PhR as it would never be true as the check is set to lowercase --- zone/npc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index 648bbb563..b7c017f96 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1961,7 +1961,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) else if(id == "cr") { CR = atoi(val.c_str()); return; } else if(id == "pr") { PR = atoi(val.c_str()); return; } else if(id == "dr") { DR = atoi(val.c_str()); return; } - else if(id == "PhR") { PhR = atoi(val.c_str()); return; } + else if(id == "phr") { PhR = atoi(val.c_str()); return; } else if(id == "runspeed") { runspeed = (float)atof(val.c_str()); base_runspeed = (int)((float)runspeed * 40.0f); From 8edb6e95954d853c3e9611c7940164110897420a Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 19 Apr 2016 04:02:53 -0400 Subject: [PATCH 051/693] Eliminated the nested class design of recent EQEmu work; Some more inv2 convergence work --- changelog.txt | 4 + common/database.cpp | 12 +- common/database_conversions.cpp | 4 +- common/deity.cpp | 76 ++++---- common/deity.h | 59 +++--- common/emu_constants.cpp | 12 +- common/emu_constants.h | 11 +- common/emu_legacy.h | 15 +- common/eq_constants.h | 4 +- common/eq_limits.cpp | 264 +++++++++++++------------- common/eq_limits.h | 45 +++-- common/eq_packet_structs.h | 12 +- common/item.cpp | 322 ++++++++++++++++---------------- common/item_struct.h | 6 +- common/light_source.cpp | 101 +++++----- common/light_source.h | 80 ++++---- common/patches/rof.cpp | 142 +++++++------- common/patches/rof2.cpp | 148 +++++++-------- common/patches/rof2_structs.h | 10 +- common/patches/rof_structs.h | 10 +- common/patches/sod.cpp | 34 ++-- common/patches/sof.cpp | 34 ++-- common/patches/titanium.cpp | 14 +- common/patches/uf.cpp | 34 ++-- common/say_link.cpp | 41 ++-- common/say_link.h | 42 +++-- common/shareddb.cpp | 36 ++-- world/client.cpp | 10 +- world/worlddb.cpp | 6 +- zone/aa.cpp | 2 +- zone/attack.cpp | 2 +- zone/bonuses.cpp | 38 ++-- zone/bot.cpp | 50 ++--- zone/bot.h | 6 +- zone/bot_command.cpp | 14 +- zone/bot_database.cpp | 18 +- zone/client.cpp | 32 ++-- zone/client.h | 2 +- zone/client_mods.cpp | 12 +- zone/client_packet.cpp | 16 +- zone/client_process.cpp | 16 +- zone/command.cpp | 54 +++--- zone/corpse.cpp | 46 ++--- zone/forage.cpp | 2 +- zone/inventory.cpp | 212 ++++++++++----------- zone/loottables.cpp | 2 +- zone/lua_general.cpp | 12 +- zone/merc.cpp | 16 +- zone/merc.h | 2 +- zone/mob.cpp | 6 +- zone/mob.h | 8 +- zone/npc.cpp | 16 +- zone/npc.h | 2 +- zone/object.cpp | 6 +- zone/pets.cpp | 10 +- zone/questmgr.cpp | 14 +- zone/special_attacks.cpp | 4 +- zone/spell_effects.cpp | 18 +- zone/spells.cpp | 2 +- zone/tasks.cpp | 4 +- zone/tradeskills.cpp | 10 +- zone/trading.cpp | 72 +++---- zone/tribute.cpp | 30 +-- zone/zonedb.cpp | 36 ++-- zone/zonedb.h | 2 +- 65 files changed, 1196 insertions(+), 1186 deletions(-) diff --git a/changelog.txt b/changelog.txt index 595526c70..964d325af 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/19/2016 == +Uleat: Changed the recent EQEmu rework to eliminate the nested class design (possible cause of VS2015 update crashes - unverified) +Uleat: Some more inv2 convergence work + == 04/15/2016 == Uleat: Reworked EQDictionary into namespace EQEmu diff --git a/common/database.cpp b/common/database.cpp index 525247131..d2b28f4ee 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -708,7 +708,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven /* Insert starting inventory... */ std::string invquery; - for (int16 i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::BANK_BAGS_END;) { + for (int16 i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::BANK_BAGS_END;) { const ItemInst* newinv = inv->GetItem(i); if (newinv) { invquery = StringFormat("INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)", @@ -718,15 +718,15 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven } if (i == SlotCursor) { - i = EQEmu::Constants::GENERAL_BAGS_BEGIN; + i = EQEmu::constants::GENERAL_BAGS_BEGIN; continue; } - else if (i == EQEmu::Constants::CURSOR_BAG_END) { - i = EQEmu::Constants::BANK_BEGIN; + else if (i == EQEmu::constants::CURSOR_BAG_END) { + i = EQEmu::constants::BANK_BEGIN; continue; } - else if (i == EQEmu::Constants::BANK_END) { - i = EQEmu::Constants::BANK_BAGS_BEGIN; + else if (i == EQEmu::constants::BANK_END) { + i = EQEmu::constants::BANK_BAGS_BEGIN; continue; } i++; diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index 4364ae27a..35c0ec939 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -330,7 +330,7 @@ namespace Convert { /*7212*/ uint32 tribute_points; /*7216*/ uint32 unknown7252; /*7220*/ uint32 tribute_active; //1=active - /*7224*/ Convert::Tribute_Struct tributes[EQEmu::Constants::TRIBUTE_SIZE]; + /*7224*/ Convert::Tribute_Struct tributes[EQEmu::constants::TRIBUTE_SIZE]; /*7264*/ Convert::Disciplines_Struct disciplines; /*7664*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use) /*7744*/ char unknown7780[160]; @@ -1428,7 +1428,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){ if (rquery != ""){ results = QueryDatabase(rquery); } /* Run Tribute Convert */ first_entry = 0; rquery = ""; - for (i = 0; i < EQEmu::Constants::TRIBUTE_SIZE; i++){ + for (i = 0; i < EQEmu::constants::TRIBUTE_SIZE; i++){ if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 4294967295){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); diff --git a/common/deity.cpp b/common/deity.cpp index af3d60e1a..e1f65a564 100644 --- a/common/deity.cpp +++ b/common/deity.cpp @@ -20,92 +20,92 @@ #include "deity.h" -EQEmu::Deity::TypeBits EQEmu::Deity::ConvertDeityToDeityBit(Types deity) +EQEmu::deity::DeityTypeBit EQEmu::deity::ConvertDeityToDeityBit(DeityType deity) { switch (deity) { case DeityBertoxxulous: - return BIT_DeityBertoxxulous; + return bit_DeityBertoxxulous; case DeityBrellSirilis: - return BIT_DeityBrellSirilis; + return bit_DeityBrellSirilis; case DeityCazicThule: - return BIT_DeityCazicThule; + return bit_DeityCazicThule; case DeityErollisiMarr: - return BIT_DeityErollisiMarr; + return bit_DeityErollisiMarr; case DeityBristlebane: - return BIT_DeityBristlebane; + return bit_DeityBristlebane; case DeityInnoruuk: - return BIT_DeityInnoruuk; + return bit_DeityInnoruuk; case DeityKarana: - return BIT_DeityKarana; + return bit_DeityKarana; case DeityMithanielMarr: - return BIT_DeityMithanielMarr; + return bit_DeityMithanielMarr; case DeityPrexus: - return BIT_DeityPrexus; + return bit_DeityPrexus; case DeityQuellious: - return BIT_DeityQuellious; + return bit_DeityQuellious; case DeityRallosZek: - return BIT_DeityRallosZek; + return bit_DeityRallosZek; case DeityRodcetNife: - return BIT_DeityRodcetNife; + return bit_DeityRodcetNife; case DeitySolusekRo: - return BIT_DeitySolusekRo; + return bit_DeitySolusekRo; case DeityTheTribunal: - return BIT_DeityTheTribunal; + return bit_DeityTheTribunal; case DeityTunare: - return BIT_DeityTunare; + return bit_DeityTunare; case DeityVeeshan: - return BIT_DeityVeeshan; + return bit_DeityVeeshan; case DeityAgnostic_LB: case DeityAgnostic: - return BIT_DeityAgnostic; + return bit_DeityAgnostic; default: - return BIT_DeityAll; + return bit_DeityAll; }; } -EQEmu::Deity::Types EQEmu::Deity::ConvertDeityBitToDeity(TypeBits deity_bit) +EQEmu::deity::DeityType EQEmu::deity::ConvertDeityBitToDeity(DeityTypeBit deity_bit) { switch (deity_bit) { - case BIT_DeityAgnostic: + case bit_DeityAgnostic: return DeityAgnostic; - case BIT_DeityBertoxxulous: + case bit_DeityBertoxxulous: return DeityBertoxxulous; - case BIT_DeityBrellSirilis: + case bit_DeityBrellSirilis: return DeityBrellSirilis; - case BIT_DeityCazicThule: + case bit_DeityCazicThule: return DeityCazicThule; - case BIT_DeityErollisiMarr: + case bit_DeityErollisiMarr: return DeityErollisiMarr; - case BIT_DeityBristlebane: + case bit_DeityBristlebane: return DeityBristlebane; - case BIT_DeityInnoruuk: + case bit_DeityInnoruuk: return DeityInnoruuk; - case BIT_DeityKarana: + case bit_DeityKarana: return DeityKarana; - case BIT_DeityMithanielMarr: + case bit_DeityMithanielMarr: return DeityMithanielMarr; - case BIT_DeityPrexus: + case bit_DeityPrexus: return DeityPrexus; - case BIT_DeityQuellious: + case bit_DeityQuellious: return DeityQuellious; - case BIT_DeityRallosZek: + case bit_DeityRallosZek: return DeityRallosZek; - case BIT_DeityRodcetNife: + case bit_DeityRodcetNife: return DeityRodcetNife; - case BIT_DeitySolusekRo: + case bit_DeitySolusekRo: return DeitySolusekRo; - case BIT_DeityTheTribunal: + case bit_DeityTheTribunal: return DeityTheTribunal; - case BIT_DeityTunare: + case bit_DeityTunare: return DeityTunare; - case BIT_DeityVeeshan: + case bit_DeityVeeshan: return DeityVeeshan; default: return DeityUnknown; }; } -const char* EQEmu::Deity::GetDeityName(Types deity) +const char* EQEmu::deity::GetDeityName(DeityType deity) { switch (deity) { case DeityBertoxxulous: diff --git a/common/deity.h b/common/deity.h index d832315d0..d9602afa8 100644 --- a/common/deity.h +++ b/common/deity.h @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,17 +15,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef DEITY_H -#define DEITY_H +#ifndef COMMON_DEITY_H +#define COMMON_DEITY_H #include "types.h" namespace EQEmu { - class Deity { - public: - enum Types { + namespace deity { + enum DeityType { DeityUnknown = 0, DeityAgnostic_LB = 140, DeityBertoxxulous = 201, @@ -47,31 +46,31 @@ namespace EQEmu DeityAgnostic = 396 }; - enum TypeBits : uint32 { - BIT_DeityAll = 0x00000000, - BIT_DeityAgnostic = 0x00000001, - BIT_DeityBertoxxulous = 0x00000002, - BIT_DeityBrellSirilis = 0x00000004, - BIT_DeityCazicThule = 0x00000008, - BIT_DeityErollisiMarr = 0x00000010, - BIT_DeityBristlebane = 0x00000020, - BIT_DeityInnoruuk = 0x00000040, - BIT_DeityKarana = 0x00000080, - BIT_DeityMithanielMarr = 0x00000100, - BIT_DeityPrexus = 0x00000200, - BIT_DeityQuellious = 0x00000400, - BIT_DeityRallosZek = 0x00000800, - BIT_DeityRodcetNife = 0x00001000, - BIT_DeitySolusekRo = 0x00002000, - BIT_DeityTheTribunal = 0x00004000, - BIT_DeityTunare = 0x00008000, - BIT_DeityVeeshan = 0x00010000 + enum DeityTypeBit : uint32 { + bit_DeityAll = 0x00000000, + bit_DeityAgnostic = 0x00000001, + bit_DeityBertoxxulous = 0x00000002, + bit_DeityBrellSirilis = 0x00000004, + bit_DeityCazicThule = 0x00000008, + bit_DeityErollisiMarr = 0x00000010, + bit_DeityBristlebane = 0x00000020, + bit_DeityInnoruuk = 0x00000040, + bit_DeityKarana = 0x00000080, + bit_DeityMithanielMarr = 0x00000100, + bit_DeityPrexus = 0x00000200, + bit_DeityQuellious = 0x00000400, + bit_DeityRallosZek = 0x00000800, + bit_DeityRodcetNife = 0x00001000, + bit_DeitySolusekRo = 0x00002000, + bit_DeityTheTribunal = 0x00004000, + bit_DeityTunare = 0x00008000, + bit_DeityVeeshan = 0x00010000 }; - static TypeBits ConvertDeityToDeityBit(Types deity); - static Types ConvertDeityBitToDeity(TypeBits deity_bit); - static const char* GetDeityName(Types deity); - }; + DeityTypeBit ConvertDeityToDeityBit(DeityType deity); + DeityType ConvertDeityBitToDeity(DeityTypeBit deity_bit); + const char* GetDeityName(DeityType deity); + } } -#endif /* DEITY_H */ +#endif /* COMMON_DEITY_H */ diff --git a/common/emu_constants.cpp b/common/emu_constants.cpp index 5e62505fd..b8024ee9e 100644 --- a/common/emu_constants.cpp +++ b/common/emu_constants.cpp @@ -21,7 +21,7 @@ #include "string_util.h" -uint16 EQEmu::Constants::InventoryTypeSize(int16 type_index) +uint16 EQEmu::constants::InventoryTypeSize(int16 type_index) { switch (type_index) { case TypePossessions: @@ -80,7 +80,7 @@ uint16 EQEmu::Constants::InventoryTypeSize(int16 type_index) } /* -const char* EQEmu::Constants::InventoryLocationName(Location_Struct location) +const char* EQEmu::constants::InventoryLocationName(Location_Struct location) { // not ready for implementation... std::string ret_str; @@ -89,7 +89,7 @@ const char* EQEmu::Constants::InventoryLocationName(Location_Struct location) } */ -const char* EQEmu::Constants::InventoryTypeName(int16 type_index) +const char* EQEmu::constants::InventoryTypeName(int16 type_index) { switch (type_index) { case INVALID_INDEX: @@ -149,7 +149,7 @@ const char* EQEmu::Constants::InventoryTypeName(int16 type_index) } } -const char* EQEmu::Constants::InventorySlotName(int16 slot_index) +const char* EQEmu::constants::InventorySlotName(int16 slot_index) { switch (slot_index) { case INVALID_INDEX: @@ -229,7 +229,7 @@ const char* EQEmu::Constants::InventorySlotName(int16 slot_index) } } -const char* EQEmu::Constants::InventorySubName(int16 sub_index) +const char* EQEmu::constants::InventorySubName(int16 sub_index) { if (sub_index == INVALID_INDEX) return "Invalid Sub"; @@ -243,7 +243,7 @@ const char* EQEmu::Constants::InventorySubName(int16 sub_index) return ret_str.c_str(); } -const char* EQEmu::Constants::InventoryAugName(int16 aug_index) +const char* EQEmu::constants::InventoryAugName(int16 aug_index) { if (aug_index == INVALID_INDEX) return "Invalid Aug"; diff --git a/common/emu_constants.h b/common/emu_constants.h index e5418be45..6f365d4e4 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -17,8 +17,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EMU_CONSTANTS_H -#define EMU_CONSTANTS_H +#ifndef COMMON_EMU_CONSTANTS_H +#define COMMON_EMU_CONSTANTS_H #include "eq_limits.h" // (future use) @@ -42,8 +42,7 @@ namespace EQEmu { // an immutable value is required to initialize arrays, etc... use this class as a repository for those - class Constants { - public: + namespace constants { // database static const ClientVersion CHARACTER_CREATION_CLIENT = ClientVersion::RoF2; // adjust according to starting item placement and target client @@ -149,7 +148,7 @@ namespace EQEmu static const size_t POTION_BELT_ITEM_COUNT = RoF2::consts::POTION_BELT_ITEM_COUNT; static const size_t TEXT_LINK_BODY_LENGTH = RoF2::consts::TEXT_LINK_BODY_LENGTH; - }; + } } -#endif /* EMU_CONSTANTS_H */ +#endif /* COMMON_EMU_CONSTANTS_H */ diff --git a/common/emu_legacy.h b/common/emu_legacy.h index 2ec1d2e18..640e55b1b 100644 --- a/common/emu_legacy.h +++ b/common/emu_legacy.h @@ -17,8 +17,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EMU_LEGACY_H -#define EMU_LEGACY_H +#ifndef COMMON_EMU_LEGACY_H +#define COMMON_EMU_LEGACY_H #include "types.h" @@ -26,9 +26,8 @@ namespace EQEmu { // this is for perl and other legacy systems - class Legacy { - public: - typedef enum { + namespace legacy { + enum InventorySlot : int16 { SLOT_CHARM = 0, SLOT_EAR01 = 1, SLOT_HEAD = 2, @@ -102,8 +101,8 @@ namespace EQEmu SLOT_WORLD_BEGIN = 4000, SLOT_WORLD_END = 4009 - } InventorySlot; - }; + }; + } } -#endif /* EMU_LEGACY_H */ +#endif /* COMMON_EMU_LEGACY_H */ diff --git a/common/eq_constants.h b/common/eq_constants.h index 8d256ddc1..3faa70e4e 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -931,8 +931,8 @@ enum PossessionsSlots : int16 // plus, since they're pre-op's, they don't affect the actual binary size #define TYPE_BEGIN 0 #define SLOT_BEGIN 0 -#define SUB_BEGIN 0 -#define AUG_BEGIN 0 +#define SUB_INDEX_BEGIN 0 +#define AUG_INDEX_BEGIN 0 static const uint32 MAX_SPELL_DB_ID_VAL = 65535; diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index c8902f4d2..d34f9990d 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -21,7 +21,7 @@ // client validation -bool EQEmu::Limits::IsValidPCClientVersion(ClientVersion clientVersion) +bool EQEmu::limits::IsValidPCClientVersion(ClientVersion clientVersion) { if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) return true; @@ -29,7 +29,7 @@ bool EQEmu::Limits::IsValidPCClientVersion(ClientVersion clientVersion) return false; } -ClientVersion EQEmu::Limits::ValidatePCClientVersion(ClientVersion clientVersion) +ClientVersion EQEmu::limits::ValidatePCClientVersion(ClientVersion clientVersion) { if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) return clientVersion; @@ -38,7 +38,7 @@ ClientVersion EQEmu::Limits::ValidatePCClientVersion(ClientVersion clientVersion } // npc validation -bool EQEmu::Limits::IsValidNPCClientVersion(ClientVersion clientVersion) +bool EQEmu::limits::IsValidNPCClientVersion(ClientVersion clientVersion) { if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) return true; @@ -46,7 +46,7 @@ bool EQEmu::Limits::IsValidNPCClientVersion(ClientVersion clientVersion) return false; } -ClientVersion EQEmu::Limits::ValidateNPCClientVersion(ClientVersion clientVersion) +ClientVersion EQEmu::limits::ValidateNPCClientVersion(ClientVersion clientVersion) { if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) return clientVersion; @@ -55,7 +55,7 @@ ClientVersion EQEmu::Limits::ValidateNPCClientVersion(ClientVersion clientVersio } // mob validation -bool EQEmu::Limits::IsValidMobClientVersion(ClientVersion clientVersion) +bool EQEmu::limits::IsValidMobClientVersion(ClientVersion clientVersion) { if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) return true; @@ -63,7 +63,7 @@ bool EQEmu::Limits::IsValidMobClientVersion(ClientVersion clientVersion) return false; } -ClientVersion EQEmu::Limits::ValidateMobClientVersion(ClientVersion clientVersion) +ClientVersion EQEmu::limits::ValidateMobClientVersion(ClientVersion clientVersion) { if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) return clientVersion; @@ -72,7 +72,7 @@ ClientVersion EQEmu::Limits::ValidateMobClientVersion(ClientVersion clientVersio } // database -size_t EQEmu::Limits::CharacterCreationLimit(ClientVersion clientVersion) +size_t EQEmu::limits::CharacterCreationLimit(ClientVersion clientVersion) { static const size_t local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, @@ -94,7 +94,7 @@ size_t EQEmu::Limits::CharacterCreationLimit(ClientVersion clientVersion) } // inventory -uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) +uint16 EQEmu::limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) { // not all maps will have an instantiated container..some are references for queue generators (i.e., bazaar, mail, etc...) // a zero '0' indicates a needed value..otherwise, change to '_NOTUSED' for a null value so indices requiring research can be identified @@ -105,36 +105,36 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi // // TYPE_POSSESSIONS_SIZE does not reflect all actual _constants size due to bitmask-use compatibility // - // when setting NPC-based values, try to adhere to an Constants:: or NOT_USED value to avoid unnecessary issues + // when setting NPC-based values, try to adhere to an constants:: or NOT_USED value to avoid unnecessary issues static const uint16 local[TypeCount][CLIENT_VERSION_COUNT] = { // server and database are sync'd to current TypePossessions's client as set in 'using namespace RoF::slots;' and - // 'Constants::TYPE_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() - // for partial range validation checks and 'Constants::TYPE_POSSESSIONS_SIZE' for full range iterations + // 'constants::TYPE_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() + // for partial range validation checks and 'constants::TYPE_POSSESSIONS_SIZE' for full range iterations { // local[TypePossessions] /*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_POSSESSIONS_SIZE, -/*Titanium*/ Constants::TYPE_POSSESSIONS_SIZE, -/*SoF*/ Constants::TYPE_POSSESSIONS_SIZE, -/*SoD*/ Constants::TYPE_POSSESSIONS_SIZE, -/*Underfoot*/ Constants::TYPE_POSSESSIONS_SIZE, -/*RoF*/ Constants::TYPE_POSSESSIONS_SIZE, -/*RoF2*/ Constants::TYPE_POSSESSIONS_SIZE, +/*62*/ constants::TYPE_POSSESSIONS_SIZE, +/*Titanium*/ constants::TYPE_POSSESSIONS_SIZE, +/*SoF*/ constants::TYPE_POSSESSIONS_SIZE, +/*SoD*/ constants::TYPE_POSSESSIONS_SIZE, +/*Underfoot*/ constants::TYPE_POSSESSIONS_SIZE, +/*RoF*/ constants::TYPE_POSSESSIONS_SIZE, +/*RoF2*/ constants::TYPE_POSSESSIONS_SIZE, -/*NPC*/ Constants::TYPE_POSSESSIONS_SIZE, -/*Merc*/ Constants::TYPE_POSSESSIONS_SIZE, -/*Bot*/ Constants::TYPE_POSSESSIONS_SIZE, -/*Pet*/ Constants::TYPE_POSSESSIONS_SIZE +/*NPC*/ constants::TYPE_POSSESSIONS_SIZE, +/*Merc*/ constants::TYPE_POSSESSIONS_SIZE, +/*Bot*/ constants::TYPE_POSSESSIONS_SIZE, +/*Pet*/ constants::TYPE_POSSESSIONS_SIZE }, { // local[TypeBank] /*Unknown*/ NOT_USED, /*62*/ NOT_USED, /*Titanium*/ Titanium::consts::TYPE_BANK_SIZE, -/*SoF*/ Constants::TYPE_BANK_SIZE, -/*SoD*/ Constants::TYPE_BANK_SIZE, -/*Underfoot*/ Constants::TYPE_BANK_SIZE, -/*RoF*/ Constants::TYPE_BANK_SIZE, -/*RoF2*/ Constants::TYPE_BANK_SIZE, +/*SoF*/ constants::TYPE_BANK_SIZE, +/*SoD*/ constants::TYPE_BANK_SIZE, +/*Underfoot*/ constants::TYPE_BANK_SIZE, +/*RoF*/ constants::TYPE_BANK_SIZE, +/*RoF2*/ constants::TYPE_BANK_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -143,13 +143,13 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi }, { // local[TypeSharedBank] /*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_SHARED_BANK_SIZE, -/*Titanium*/ Constants::TYPE_SHARED_BANK_SIZE, -/*SoF*/ Constants::TYPE_SHARED_BANK_SIZE, -/*SoD*/ Constants::TYPE_SHARED_BANK_SIZE, -/*Underfoot*/ Constants::TYPE_SHARED_BANK_SIZE, -/*RoF*/ Constants::TYPE_SHARED_BANK_SIZE, -/*RoF2*/ Constants::TYPE_SHARED_BANK_SIZE, +/*62*/ constants::TYPE_SHARED_BANK_SIZE, +/*Titanium*/ constants::TYPE_SHARED_BANK_SIZE, +/*SoF*/ constants::TYPE_SHARED_BANK_SIZE, +/*SoD*/ constants::TYPE_SHARED_BANK_SIZE, +/*Underfoot*/ constants::TYPE_SHARED_BANK_SIZE, +/*RoF*/ constants::TYPE_SHARED_BANK_SIZE, +/*RoF2*/ constants::TYPE_SHARED_BANK_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -158,28 +158,28 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi }, { // local[TypeTrade] /*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_TRADE_SIZE, -/*Titanium*/ Constants::TYPE_TRADE_SIZE, -/*SoF*/ Constants::TYPE_TRADE_SIZE, -/*SoD*/ Constants::TYPE_TRADE_SIZE, -/*Underfoot*/ Constants::TYPE_TRADE_SIZE, -/*RoF*/ Constants::TYPE_TRADE_SIZE, -/*RoF2*/ Constants::TYPE_TRADE_SIZE, +/*62*/ constants::TYPE_TRADE_SIZE, +/*Titanium*/ constants::TYPE_TRADE_SIZE, +/*SoF*/ constants::TYPE_TRADE_SIZE, +/*SoD*/ constants::TYPE_TRADE_SIZE, +/*Underfoot*/ constants::TYPE_TRADE_SIZE, +/*RoF*/ constants::TYPE_TRADE_SIZE, +/*RoF2*/ constants::TYPE_TRADE_SIZE, /*NPC*/ 4, /*Merc*/ 4, -/*Bot*/ Constants::TYPE_TRADE_SIZE, // client thinks this is another client +/*Bot*/ constants::TYPE_TRADE_SIZE, // client thinks this is another client /*Pet*/ 4 }, { // local[TypeWorld] /*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_WORLD_SIZE, -/*Titanium*/ Constants::TYPE_WORLD_SIZE, -/*SoF*/ Constants::TYPE_WORLD_SIZE, -/*SoD*/ Constants::TYPE_WORLD_SIZE, -/*Underfoot*/ Constants::TYPE_WORLD_SIZE, -/*RoF*/ Constants::TYPE_WORLD_SIZE, -/*RoF2*/ Constants::TYPE_WORLD_SIZE, +/*62*/ constants::TYPE_WORLD_SIZE, +/*Titanium*/ constants::TYPE_WORLD_SIZE, +/*SoF*/ constants::TYPE_WORLD_SIZE, +/*SoD*/ constants::TYPE_WORLD_SIZE, +/*Underfoot*/ constants::TYPE_WORLD_SIZE, +/*RoF*/ constants::TYPE_WORLD_SIZE, +/*RoF2*/ constants::TYPE_WORLD_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -188,13 +188,13 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi }, { // local[TypeLimbo] /*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_LIMBO_SIZE, -/*Titanium*/ Constants::TYPE_LIMBO_SIZE, -/*SoF*/ Constants::TYPE_LIMBO_SIZE, -/*SoD*/ Constants::TYPE_LIMBO_SIZE, -/*Underfoot*/ Constants::TYPE_LIMBO_SIZE, -/*RoF*/ Constants::TYPE_LIMBO_SIZE, -/*RoF2*/ Constants::TYPE_LIMBO_SIZE, +/*62*/ constants::TYPE_LIMBO_SIZE, +/*Titanium*/ constants::TYPE_LIMBO_SIZE, +/*SoF*/ constants::TYPE_LIMBO_SIZE, +/*SoD*/ constants::TYPE_LIMBO_SIZE, +/*Underfoot*/ constants::TYPE_LIMBO_SIZE, +/*RoF*/ constants::TYPE_LIMBO_SIZE, +/*RoF2*/ constants::TYPE_LIMBO_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -203,13 +203,13 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi }, { // local[TypeTribute] /*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_TRIBUTE_SIZE, -/*Titanium*/ Constants::TYPE_TRIBUTE_SIZE, -/*SoF*/ Constants::TYPE_TRIBUTE_SIZE, -/*SoD*/ Constants::TYPE_TRIBUTE_SIZE, -/*Underfoot*/ Constants::TYPE_TRIBUTE_SIZE, -/*RoF*/ Constants::TYPE_TRIBUTE_SIZE, -/*RoF2*/ Constants::TYPE_TRIBUTE_SIZE, +/*62*/ constants::TYPE_TRIBUTE_SIZE, +/*Titanium*/ constants::TYPE_TRIBUTE_SIZE, +/*SoF*/ constants::TYPE_TRIBUTE_SIZE, +/*SoD*/ constants::TYPE_TRIBUTE_SIZE, +/*Underfoot*/ constants::TYPE_TRIBUTE_SIZE, +/*RoF*/ constants::TYPE_TRIBUTE_SIZE, +/*RoF2*/ constants::TYPE_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -223,8 +223,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ Constants::TYPE_TROPHY_TRIBUTE_SIZE, +/*RoF*/ constants::TYPE_TROPHY_TRIBUTE_SIZE, +/*RoF2*/ constants::TYPE_TROPHY_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -238,8 +238,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_GUILD_TRIBUTE_SIZE, -/*RoF2*/ Constants::TYPE_GUILD_TRIBUTE_SIZE, +/*RoF*/ constants::TYPE_GUILD_TRIBUTE_SIZE, +/*RoF2*/ constants::TYPE_GUILD_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -253,8 +253,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_MERCHANT_SIZE, -/*RoF2*/ Constants::TYPE_MERCHANT_SIZE, +/*RoF*/ constants::TYPE_MERCHANT_SIZE, +/*RoF2*/ constants::TYPE_MERCHANT_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -268,8 +268,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_DELETED_SIZE, -/*RoF2*/ Constants::TYPE_DELETED_SIZE, +/*RoF*/ constants::TYPE_DELETED_SIZE, +/*RoF2*/ constants::TYPE_DELETED_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -293,15 +293,15 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi }, { // local[TypeBazaar] /*Unknown*/ NOT_USED, -/*62*/ Constants::TYPE_BAZAAR_SIZE, -/*Titanium*/ Constants::TYPE_BAZAAR_SIZE, -/*SoF*/ Constants::TYPE_BAZAAR_SIZE, -/*SoD*/ Constants::TYPE_BAZAAR_SIZE, -/*Underfoot*/ Constants::TYPE_BAZAAR_SIZE, -/*RoF*/ Constants::TYPE_BAZAAR_SIZE, -/*RoF2*/ Constants::TYPE_BAZAAR_SIZE, +/*62*/ constants::TYPE_BAZAAR_SIZE, +/*Titanium*/ constants::TYPE_BAZAAR_SIZE, +/*SoF*/ constants::TYPE_BAZAAR_SIZE, +/*SoD*/ constants::TYPE_BAZAAR_SIZE, +/*Underfoot*/ constants::TYPE_BAZAAR_SIZE, +/*RoF*/ constants::TYPE_BAZAAR_SIZE, +/*RoF2*/ constants::TYPE_BAZAAR_SIZE, -/*NPC*/ 0, // this may need to be 'Constants::TYPE_BAZAAR_SIZE' if offline client traders respawn as an npc +/*NPC*/ 0, // this may need to be 'constants::TYPE_BAZAAR_SIZE' if offline client traders respawn as an npc /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 @@ -328,8 +328,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_REAL_ESTATE_SIZE, -/*RoF2*/ Constants::TYPE_REAL_ESTATE_SIZE, +/*RoF*/ constants::TYPE_REAL_ESTATE_SIZE, +/*RoF2*/ constants::TYPE_REAL_ESTATE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -343,8 +343,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_VIEW_MOD_PC_SIZE, -/*RoF2*/ Constants::TYPE_VIEW_MOD_PC_SIZE, +/*RoF*/ constants::TYPE_VIEW_MOD_PC_SIZE, +/*RoF2*/ constants::TYPE_VIEW_MOD_PC_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -358,8 +358,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_VIEW_MOD_BANK_SIZE, -/*RoF2*/ Constants::TYPE_VIEW_MOD_BANK_SIZE, +/*RoF*/ constants::TYPE_VIEW_MOD_BANK_SIZE, +/*RoF2*/ constants::TYPE_VIEW_MOD_BANK_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -373,8 +373,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, -/*RoF2*/ Constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, +/*RoF*/ constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, +/*RoF2*/ constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -388,8 +388,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_VIEW_MOD_LIMBO_SIZE, -/*RoF2*/ Constants::TYPE_VIEW_MOD_LIMBO_SIZE, +/*RoF*/ constants::TYPE_VIEW_MOD_LIMBO_SIZE, +/*RoF2*/ constants::TYPE_VIEW_MOD_LIMBO_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -403,8 +403,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_ALT_STORAGE_SIZE, -/*RoF2*/ Constants::TYPE_ALT_STORAGE_SIZE, +/*RoF*/ constants::TYPE_ALT_STORAGE_SIZE, +/*RoF2*/ constants::TYPE_ALT_STORAGE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -418,8 +418,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_ARCHIVED_SIZE, -/*RoF2*/ Constants::TYPE_ARCHIVED_SIZE, +/*RoF*/ constants::TYPE_ARCHIVED_SIZE, +/*RoF2*/ constants::TYPE_ARCHIVED_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -433,8 +433,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_MAIL_SIZE, -/*RoF2*/ Constants::TYPE_MAIL_SIZE, +/*RoF*/ constants::TYPE_MAIL_SIZE, +/*RoF2*/ constants::TYPE_MAIL_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -448,8 +448,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ Constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, +/*RoF*/ constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, +/*RoF2*/ constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -463,8 +463,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ NOT_USED, /*SoD*/ NOT_USED, /*Underfoot*/ NOT_USED, -/*RoF*/ Constants::TYPE_KRONO_SIZE, -/*RoF2*/ Constants::TYPE_KRONO_SIZE, +/*RoF*/ constants::TYPE_KRONO_SIZE, +/*RoF2*/ constants::TYPE_KRONO_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -478,8 +478,8 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ Constants::TYPE_OTHER_SIZE, -/*RoF2*/ Constants::TYPE_OTHER_SIZE, +/*RoF*/ constants::TYPE_OTHER_SIZE, +/*RoF2*/ constants::TYPE_OTHER_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -494,7 +494,7 @@ uint16 EQEmu::Limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi return NOT_USED; } -uint64 EQEmu::Limits::PossessionsBitmask(ClientVersion clientVersion) +uint64 EQEmu::limits::PossessionsBitmask(ClientVersion clientVersion) { // these are for the new inventory system (RoF)..not the current (Ti) one... // 0x0000000000200000 is SlotPowerSource (SoF+) @@ -521,7 +521,7 @@ uint64 EQEmu::Limits::PossessionsBitmask(ClientVersion clientVersion) //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint64 EQEmu::Limits::EquipmentBitmask(ClientVersion clientVersion) +uint64 EQEmu::limits::EquipmentBitmask(ClientVersion clientVersion) { static const uint64 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, @@ -543,7 +543,7 @@ uint64 EQEmu::Limits::EquipmentBitmask(ClientVersion clientVersion) //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint64 EQEmu::Limits::GeneralBitmask(ClientVersion clientVersion) +uint64 EQEmu::limits::GeneralBitmask(ClientVersion clientVersion) { static const uint64 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, @@ -565,7 +565,7 @@ uint64 EQEmu::Limits::GeneralBitmask(ClientVersion clientVersion) //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint64 EQEmu::Limits::CursorBitmask(ClientVersion clientVersion) +uint64 EQEmu::limits::CursorBitmask(ClientVersion clientVersion) { static const uint64 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, @@ -587,7 +587,7 @@ uint64 EQEmu::Limits::CursorBitmask(ClientVersion clientVersion) //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -bool EQEmu::Limits::AllowsEmptyBagInBag(ClientVersion clientVersion) +bool EQEmu::limits::AllowsEmptyBagInBag(ClientVersion clientVersion) { static const bool local[CLIENT_VERSION_COUNT] = { /*Unknown*/ false, @@ -609,7 +609,7 @@ bool EQEmu::Limits::AllowsEmptyBagInBag(ClientVersion clientVersion) //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -bool EQEmu::Limits::AllowsClickCastFromBag(ClientVersion clientVersion) +bool EQEmu::limits::AllowsClickCastFromBag(ClientVersion clientVersion) { static const bool local[CLIENT_VERSION_COUNT] = { /*Unknown*/ false, @@ -631,49 +631,49 @@ bool EQEmu::Limits::AllowsClickCastFromBag(ClientVersion clientVersion) } // items -uint16 EQEmu::Limits::ItemCommonSize(ClientVersion clientVersion) +uint16 EQEmu::limits::ItemCommonSize(ClientVersion clientVersion) { static const uint16 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, -/*62*/ Constants::ITEM_COMMON_SIZE, -/*Titanium*/ Constants::ITEM_COMMON_SIZE, -/*SoF*/ Constants::ITEM_COMMON_SIZE, -/*SoD*/ Constants::ITEM_COMMON_SIZE, -/*Underfoot*/ Constants::ITEM_COMMON_SIZE, -/*RoF*/ Constants::ITEM_COMMON_SIZE, -/*RoF2*/ Constants::ITEM_COMMON_SIZE, +/*62*/ constants::ITEM_COMMON_SIZE, +/*Titanium*/ constants::ITEM_COMMON_SIZE, +/*SoF*/ constants::ITEM_COMMON_SIZE, +/*SoD*/ constants::ITEM_COMMON_SIZE, +/*Underfoot*/ constants::ITEM_COMMON_SIZE, +/*RoF*/ constants::ITEM_COMMON_SIZE, +/*RoF2*/ constants::ITEM_COMMON_SIZE, -/*NPC*/ Constants::ITEM_COMMON_SIZE, -/*Merc*/ Constants::ITEM_COMMON_SIZE, -/*Bot*/ Constants::ITEM_COMMON_SIZE, -/*Pet*/ Constants::ITEM_COMMON_SIZE +/*NPC*/ constants::ITEM_COMMON_SIZE, +/*Merc*/ constants::ITEM_COMMON_SIZE, +/*Bot*/ constants::ITEM_COMMON_SIZE, +/*Pet*/ constants::ITEM_COMMON_SIZE }; return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint16 EQEmu::Limits::ItemContainerSize(ClientVersion clientVersion) +uint16 EQEmu::limits::ItemContainerSize(ClientVersion clientVersion) { static const uint16 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, -/*62*/ Constants::ITEM_CONTAINER_SIZE, -/*Titanium*/ Constants::ITEM_CONTAINER_SIZE, -/*SoF*/ Constants::ITEM_CONTAINER_SIZE, -/*SoD*/ Constants::ITEM_CONTAINER_SIZE, -/*Underfoot*/ Constants::ITEM_CONTAINER_SIZE, -/*RoF*/ Constants::ITEM_CONTAINER_SIZE, -/*RoF2*/ Constants::ITEM_CONTAINER_SIZE, +/*62*/ constants::ITEM_CONTAINER_SIZE, +/*Titanium*/ constants::ITEM_CONTAINER_SIZE, +/*SoF*/ constants::ITEM_CONTAINER_SIZE, +/*SoD*/ constants::ITEM_CONTAINER_SIZE, +/*Underfoot*/ constants::ITEM_CONTAINER_SIZE, +/*RoF*/ constants::ITEM_CONTAINER_SIZE, +/*RoF2*/ constants::ITEM_CONTAINER_SIZE, -/*NPC*/ Constants::ITEM_CONTAINER_SIZE, -/*Merc*/ Constants::ITEM_CONTAINER_SIZE, -/*Bot*/ Constants::ITEM_CONTAINER_SIZE, -/*Pet*/ Constants::ITEM_CONTAINER_SIZE +/*NPC*/ constants::ITEM_CONTAINER_SIZE, +/*Merc*/ constants::ITEM_CONTAINER_SIZE, +/*Bot*/ constants::ITEM_CONTAINER_SIZE, +/*Pet*/ constants::ITEM_CONTAINER_SIZE }; return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -bool EQEmu::Limits::CoinHasWeight(ClientVersion clientVersion) +bool EQEmu::limits::CoinHasWeight(ClientVersion clientVersion) { static const bool local[CLIENT_VERSION_COUNT] = { /*Unknown*/ true, diff --git a/common/eq_limits.h b/common/eq_limits.h index bd65053f8..4d9d5e020 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -17,8 +17,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EQ_LIMITS_H -#define EQ_LIMITS_H +#ifndef COMMON_EQ_LIMITS_H +#define COMMON_EQ_LIMITS_H #include "types.h" #include "eq_constants.h" @@ -42,41 +42,40 @@ namespace EQEmu // values should default to a non-beneficial value..unless value conflicts with intended operation // // EQEmu::Constants may be used as references..but, not every reference needs to be in EQEmu::Constants (i.e., AllowsEmptyBagInBag(), CoinHasWeight(), etc...) - class Limits { - public: + namespace limits { // client version validation (checks to avoid crashing zone server when accessing reference arrays) // use this inside of class Client (limits to actual clients) - static bool IsValidPCClientVersion(ClientVersion clientVersion); - static ClientVersion ValidatePCClientVersion(ClientVersion clientVersion); + bool IsValidPCClientVersion(ClientVersion clientVersion); + ClientVersion ValidatePCClientVersion(ClientVersion clientVersion); // basically..any non-client classes - do not invoke when setting a valid client - static bool IsValidNPCClientVersion(ClientVersion clientVersion); - static ClientVersion ValidateNPCClientVersion(ClientVersion clientVersion); + bool IsValidNPCClientVersion(ClientVersion clientVersion); + ClientVersion ValidateNPCClientVersion(ClientVersion clientVersion); // these are 'universal' - do not invoke when setting a valid client - static bool IsValidMobClientVersion(ClientVersion clientVersion); - static ClientVersion ValidateMobClientVersion(ClientVersion clientVersion); + bool IsValidMobClientVersion(ClientVersion clientVersion); + ClientVersion ValidateMobClientVersion(ClientVersion clientVersion); // database - static size_t CharacterCreationLimit(ClientVersion clientVersion); + size_t CharacterCreationLimit(ClientVersion clientVersion); // inventory - static uint16 InventoryMapSize(int16 indexMap, ClientVersion clientVersion); - static uint64 PossessionsBitmask(ClientVersion clientVersion); - static uint64 EquipmentBitmask(ClientVersion clientVersion); - static uint64 GeneralBitmask(ClientVersion clientVersion); - static uint64 CursorBitmask(ClientVersion clientVersion); + uint16 InventoryMapSize(int16 indexMap, ClientVersion clientVersion); + uint64 PossessionsBitmask(ClientVersion clientVersion); + uint64 EquipmentBitmask(ClientVersion clientVersion); + uint64 GeneralBitmask(ClientVersion clientVersion); + uint64 CursorBitmask(ClientVersion clientVersion); - static bool AllowsEmptyBagInBag(ClientVersion clientVersion); - static bool AllowsClickCastFromBag(ClientVersion clientVersion); + bool AllowsEmptyBagInBag(ClientVersion clientVersion); + bool AllowsClickCastFromBag(ClientVersion clientVersion); // items - static uint16 ItemCommonSize(ClientVersion clientVersion); - static uint16 ItemContainerSize(ClientVersion clientVersion); + uint16 ItemCommonSize(ClientVersion clientVersion); + uint16 ItemContainerSize(ClientVersion clientVersion); // player profile - static bool CoinHasWeight(ClientVersion clientVersion); - }; + bool CoinHasWeight(ClientVersion clientVersion); + } } -#endif /* EQ_LIMITS_H */ +#endif /* COMMON_EQ_LIMITS_H */ diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index d0a60df8f..0f7283c5a 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -776,7 +776,7 @@ struct BandolierItem_Struct struct Bandolier_Struct { char Name[32]; - BandolierItem_Struct Items[EQEmu::Constants::BANDOLIER_ITEM_COUNT]; + BandolierItem_Struct Items[EQEmu::constants::BANDOLIER_ITEM_COUNT]; }; //len = 72 @@ -790,7 +790,7 @@ struct PotionBeltItem_Struct //len = 288 struct PotionBelt_Struct { - PotionBeltItem_Struct Items[EQEmu::Constants::POTION_BELT_ITEM_COUNT]; + PotionBeltItem_Struct Items[EQEmu::constants::POTION_BELT_ITEM_COUNT]; }; struct MovePotionToBelt_Struct @@ -1092,7 +1092,7 @@ struct PlayerProfile_Struct /*7212*/ uint32 tribute_points; /*7216*/ uint32 unknown7252; /*7220*/ uint32 tribute_active; //1=active -/*7224*/ Tribute_Struct tributes[EQEmu::Constants::TRIBUTE_SIZE]; +/*7224*/ Tribute_Struct tributes[EQEmu::constants::TRIBUTE_SIZE]; /*7264*/ Disciplines_Struct disciplines; /*7664*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use) /*7744*/ char unknown7780[160]; @@ -1119,7 +1119,7 @@ struct PlayerProfile_Struct /*12800*/ uint32 expAA; /*12804*/ uint32 aapoints; //avaliable, unspent /*12808*/ uint8 unknown12844[36]; -/*12844*/ Bandolier_Struct bandoliers[EQEmu::Constants::BANDOLIERS_SIZE]; +/*12844*/ Bandolier_Struct bandoliers[EQEmu::constants::BANDOLIERS_SIZE]; /*14124*/ uint8 unknown14160[4506]; /*18630*/ SuspendedMinion_Struct SuspendedMinion; // No longer in use /*19240*/ uint32 timeentitledonaccount; @@ -3472,8 +3472,8 @@ struct SelectTributeReply_Struct { struct TributeInfo_Struct { uint32 active; //0 == inactive, 1 == active - uint32 tributes[EQEmu::Constants::TRIBUTE_SIZE]; //-1 == NONE - uint32 tiers[EQEmu::Constants::TRIBUTE_SIZE]; //all 00's + uint32 tributes[EQEmu::constants::TRIBUTE_SIZE]; //-1 == NONE + uint32 tiers[EQEmu::constants::TRIBUTE_SIZE]; //all 00's uint32 tribute_master_id; }; diff --git a/common/item.cpp b/common/item.cpp index f1635aeb1..b65f33123 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -162,57 +162,57 @@ ItemInst* Inventory::GetItem(int16 slot_id) const } // Non bag slots - else if (slot_id >= EQEmu::Constants::TRADE_BEGIN && slot_id <= EQEmu::Constants::TRADE_END) { + else if (slot_id >= EQEmu::constants::TRADE_BEGIN && slot_id <= EQEmu::constants::TRADE_END) { result = _GetItem(m_trade, slot_id); } - else if (slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_END) { + else if (slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_END) { // Shared Bank slots result = _GetItem(m_shbank, slot_id); } - else if (slot_id >= EQEmu::Constants::BANK_BEGIN && slot_id <= EQEmu::Constants::BANK_END) { + else if (slot_id >= EQEmu::constants::BANK_BEGIN && slot_id <= EQEmu::constants::BANK_END) { // Bank slots result = _GetItem(m_bank, slot_id); } - else if ((slot_id >= EQEmu::Constants::GENERAL_BEGIN && slot_id <= EQEmu::Constants::GENERAL_END)) { + else if ((slot_id >= EQEmu::constants::GENERAL_BEGIN && slot_id <= EQEmu::constants::GENERAL_END)) { // Personal inventory slots result = _GetItem(m_inv, slot_id); } - else if ((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::Constants::EQUIPMENT_END) || - (slot_id >= EQEmu::Constants::TRIBUTE_BEGIN && slot_id <= EQEmu::Constants::TRIBUTE_END) || (slot_id == SlotPowerSource)) { + else if ((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::constants::EQUIPMENT_END) || + (slot_id >= EQEmu::constants::TRIBUTE_BEGIN && slot_id <= EQEmu::constants::TRIBUTE_END) || (slot_id == SlotPowerSource)) { // Equippable slots (on body) result = _GetItem(m_worn, slot_id); } // Inner bag slots - else if (slot_id >= EQEmu::Constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::Constants::TRADE_BAGS_END) { + else if (slot_id >= EQEmu::constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::constants::TRADE_BAGS_END) { // Trade bag slots ItemInst* inst = _GetItem(m_trade, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { + else if (slot_id >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { // Shared Bank bag slots ItemInst* inst = _GetItem(m_shbank, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::Constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::BANK_BAGS_END) { + else if (slot_id >= EQEmu::constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::BANK_BAGS_END) { // Bank bag slots ItemInst* inst = _GetItem(m_bank, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::Constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::Constants::CURSOR_BAG_END) { + else if (slot_id >= EQEmu::constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::constants::CURSOR_BAG_END) { // Cursor bag slots ItemInst* inst = m_cursor.peek_front(); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::Constants::GENERAL_BAGS_END) { + else if (slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::constants::GENERAL_BAGS_END) { // Personal inventory bag slots ItemInst* inst = _GetItem(m_inv, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { @@ -314,7 +314,7 @@ bool Inventory::CheckNoDrop(int16 slot_id) { if (!inst) return false; if (!inst->GetItem()->NoDrop) return true; if (inst->GetItem()->ItemClass == 1) { - for (uint8 i = SUB_BEGIN; i < EQEmu::Constants::ITEM_CONTAINER_SIZE; i++) { + for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::constants::ITEM_CONTAINER_SIZE; i++) { ItemInst* bagitem = GetItem(Inventory::CalcSlotId(slot_id, i)); if (bagitem && !bagitem->GetItem()->NoDrop) return true; @@ -332,27 +332,27 @@ ItemInst* Inventory::PopItem(int16 slot_id) if (slot_id == SlotCursor) { p = m_cursor.pop(); } - else if ((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::Constants::EQUIPMENT_END) || (slot_id == SlotPowerSource)) { + else if ((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::constants::EQUIPMENT_END) || (slot_id == SlotPowerSource)) { p = m_worn[slot_id]; m_worn.erase(slot_id); } - else if ((slot_id >= EQEmu::Constants::GENERAL_BEGIN && slot_id <= EQEmu::Constants::GENERAL_END)) { + else if ((slot_id >= EQEmu::constants::GENERAL_BEGIN && slot_id <= EQEmu::constants::GENERAL_END)) { p = m_inv[slot_id]; m_inv.erase(slot_id); } - else if (slot_id >= EQEmu::Constants::TRIBUTE_BEGIN && slot_id <= EQEmu::Constants::TRIBUTE_END) { + else if (slot_id >= EQEmu::constants::TRIBUTE_BEGIN && slot_id <= EQEmu::constants::TRIBUTE_END) { p = m_worn[slot_id]; m_worn.erase(slot_id); } - else if (slot_id >= EQEmu::Constants::BANK_BEGIN && slot_id <= EQEmu::Constants::BANK_END) { + else if (slot_id >= EQEmu::constants::BANK_BEGIN && slot_id <= EQEmu::constants::BANK_END) { p = m_bank[slot_id]; m_bank.erase(slot_id); } - else if (slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_END) { + else if (slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_END) { p = m_shbank[slot_id]; m_shbank.erase(slot_id); } - else if (slot_id >= EQEmu::Constants::TRADE_BEGIN && slot_id <= EQEmu::Constants::TRADE_END) { + else if (slot_id >= EQEmu::constants::TRADE_BEGIN && slot_id <= EQEmu::constants::TRADE_END) { p = m_trade[slot_id]; m_trade.erase(slot_id); } @@ -372,7 +372,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { if (ItemToTry->Stackable) { - for (int16 i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { + for (int16 i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { ItemInst* InvItem = GetItem(i); @@ -388,9 +388,9 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { } if (InvItem && InvItem->IsType(ItemClassContainer)) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_BEGIN); + int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); uint8 BagSize = InvItem->GetItem()->BagSlots; - for (uint8 BagSlot = SUB_BEGIN; BagSlot < BagSize; BagSlot++) { + for (uint8 BagSlot = SUB_INDEX_BEGIN; BagSlot < BagSize; BagSlot++) { InvItem = GetItem(BaseSlotID + BagSlot); @@ -409,7 +409,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { } } - for (int16 i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { + for (int16 i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { ItemInst* InvItem = GetItem(i); @@ -432,11 +432,11 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { } else if (InvItem->IsType(ItemClassContainer) && CanItemFitInContainer(ItemToTry, InvItem->GetItem())) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_BEGIN); + int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); uint8 BagSize = InvItem->GetItem()->BagSlots; - for (uint8 BagSlot = SUB_BEGIN; BagSlotIsType(ItemClassContainer) && inst->GetItem()->BagSize >= min_size) { @@ -631,11 +631,11 @@ int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, boo continue; } - int16 base_slot_id = Inventory::CalcSlotId(i, SUB_BEGIN); + int16 base_slot_id = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); uint8 slots = inst->GetItem()->BagSlots; uint8 j; - for (j = SUB_BEGIN; jIsType(ItemClassContainer)) { - for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { if (!m_inv[free_slot]) return free_slot; } @@ -677,7 +677,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 2: find partial room for stackables if (inst->IsStackable()) { - for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst) @@ -687,14 +687,14 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { return free_slot; } - for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst) continue; if (main_inst->IsType(ItemClassContainer)) { // if item-specific containers already have bad items, we won't fix it here... - for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { const ItemInst* sub_inst = main_inst->GetItem(free_bag_slot); if (!sub_inst) @@ -709,13 +709,13 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 3a: find room for container-specific items (ItemClassArrow) if (inst->GetItem()->ItemType == ItemTypeArrow) { - for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst || (main_inst->GetItem()->BagType != BagTypeQuiver) || !main_inst->IsType(ItemClassContainer)) continue; - for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -724,13 +724,13 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 3b: find room for container-specific items (ItemClassSmallThrowing) if (inst->GetItem()->ItemType == ItemTypeSmallThrowing) { - for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst || (main_inst->GetItem()->BagType != BagTypeBandolier) || !main_inst->IsType(ItemClassContainer)) continue; - for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -738,21 +738,21 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { } // step 4: just find an empty slot - for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst) return free_slot; } - for (int16 free_slot = EQEmu::Constants::GENERAL_BEGIN; free_slot <= EQEmu::Constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (main_inst && main_inst->IsType(ItemClassContainer)) { if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == BagTypeBandolier) || (main_inst->GetItem()->BagType == BagTypeQuiver)) continue; - for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -772,20 +772,20 @@ int16 Inventory::CalcSlotId(int16 slot_id) { // parent_slot_id = EmuConstants::BANK_BEGIN + (slot_id - EmuConstants::BANK_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; //else if (slot_id >= 3100 && slot_id <= 3179) should be {3031..3110}..where did this range come from!!? (verified db save range) - if (slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::Constants::GENERAL_BAGS_END) { - parent_slot_id = EQEmu::Constants::GENERAL_BEGIN + (slot_id - EQEmu::Constants::GENERAL_BAGS_BEGIN) / EQEmu::Constants::ITEM_CONTAINER_SIZE; + if (slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::constants::GENERAL_BAGS_END) { + parent_slot_id = EQEmu::constants::GENERAL_BEGIN + (slot_id - EQEmu::constants::GENERAL_BAGS_BEGIN) / EQEmu::constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::Constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::Constants::CURSOR_BAG_END) { + else if (slot_id >= EQEmu::constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::constants::CURSOR_BAG_END) { parent_slot_id = SlotCursor; } - else if (slot_id >= EQEmu::Constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::BANK_BAGS_END) { - parent_slot_id = EQEmu::Constants::BANK_BEGIN + (slot_id - EQEmu::Constants::BANK_BAGS_BEGIN) / EQEmu::Constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::BANK_BAGS_END) { + parent_slot_id = EQEmu::constants::BANK_BEGIN + (slot_id - EQEmu::constants::BANK_BAGS_BEGIN) / EQEmu::constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { - parent_slot_id = EQEmu::Constants::SHARED_BANK_BEGIN + (slot_id - EQEmu::Constants::SHARED_BANK_BAGS_BEGIN) / EQEmu::Constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { + parent_slot_id = EQEmu::constants::SHARED_BANK_BEGIN + (slot_id - EQEmu::constants::SHARED_BANK_BAGS_BEGIN) / EQEmu::constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::Constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::Constants::TRADE_BAGS_END) { - parent_slot_id = EQEmu::Constants::TRADE_BEGIN + (slot_id - EQEmu::Constants::TRADE_BAGS_BEGIN) / EQEmu::Constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::constants::TRADE_BAGS_END) { + parent_slot_id = EQEmu::constants::TRADE_BEGIN + (slot_id - EQEmu::constants::TRADE_BAGS_BEGIN) / EQEmu::constants::ITEM_CONTAINER_SIZE; } return parent_slot_id; @@ -799,19 +799,19 @@ int16 Inventory::CalcSlotId(int16 bagslot_id, uint8 bagidx) { int16 slot_id = INVALID_INDEX; if (bagslot_id == SlotCursor || bagslot_id == 8000) { - slot_id = EQEmu::Constants::CURSOR_BAG_BEGIN + bagidx; + slot_id = EQEmu::constants::CURSOR_BAG_BEGIN + bagidx; } - else if (bagslot_id >= EQEmu::Constants::GENERAL_BEGIN && bagslot_id <= EQEmu::Constants::GENERAL_END) { - slot_id = EQEmu::Constants::GENERAL_BAGS_BEGIN + (bagslot_id - EQEmu::Constants::GENERAL_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::constants::GENERAL_BEGIN && bagslot_id <= EQEmu::constants::GENERAL_END) { + slot_id = EQEmu::constants::GENERAL_BAGS_BEGIN + (bagslot_id - EQEmu::constants::GENERAL_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE + bagidx; } - else if (bagslot_id >= EQEmu::Constants::BANK_BEGIN && bagslot_id <= EQEmu::Constants::BANK_END) { - slot_id = EQEmu::Constants::BANK_BAGS_BEGIN + (bagslot_id - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::constants::BANK_BEGIN && bagslot_id <= EQEmu::constants::BANK_END) { + slot_id = EQEmu::constants::BANK_BAGS_BEGIN + (bagslot_id - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE + bagidx; } - else if (bagslot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && bagslot_id <= EQEmu::Constants::SHARED_BANK_END) { - slot_id = EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + (bagslot_id - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::constants::SHARED_BANK_BEGIN && bagslot_id <= EQEmu::constants::SHARED_BANK_END) { + slot_id = EQEmu::constants::SHARED_BANK_BAGS_BEGIN + (bagslot_id - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE + bagidx; } - else if (bagslot_id >= EQEmu::Constants::TRADE_BEGIN && bagslot_id <= EQEmu::Constants::TRADE_END) { - slot_id = EQEmu::Constants::TRADE_BAGS_BEGIN + (bagslot_id - EQEmu::Constants::TRADE_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::constants::TRADE_BEGIN && bagslot_id <= EQEmu::constants::TRADE_END) { + slot_id = EQEmu::constants::TRADE_BAGS_BEGIN + (bagslot_id - EQEmu::constants::TRADE_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE + bagidx; } return slot_id; @@ -824,23 +824,23 @@ uint8 Inventory::CalcBagIdx(int16 slot_id) { //else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) // index = (slot_id - EmuConstants::BANK_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; - if (slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::Constants::GENERAL_BAGS_END) { - index = (slot_id - EQEmu::Constants::GENERAL_BAGS_BEGIN) % EQEmu::Constants::ITEM_CONTAINER_SIZE; + if (slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::constants::GENERAL_BAGS_END) { + index = (slot_id - EQEmu::constants::GENERAL_BAGS_BEGIN) % EQEmu::constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::Constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::Constants::CURSOR_BAG_END) { - index = (slot_id - EQEmu::Constants::CURSOR_BAG_BEGIN); // % EQEmu::Constants::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots + else if (slot_id >= EQEmu::constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::constants::CURSOR_BAG_END) { + index = (slot_id - EQEmu::constants::CURSOR_BAG_BEGIN); // % EQEmu::Constants::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots } - else if (slot_id >= EQEmu::Constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::BANK_BAGS_END) { - index = (slot_id - EQEmu::Constants::BANK_BAGS_BEGIN) % EQEmu::Constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::BANK_BAGS_END) { + index = (slot_id - EQEmu::constants::BANK_BAGS_BEGIN) % EQEmu::constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { - index = (slot_id - EQEmu::Constants::SHARED_BANK_BAGS_BEGIN) % EQEmu::Constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { + index = (slot_id - EQEmu::constants::SHARED_BANK_BAGS_BEGIN) % EQEmu::constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::Constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::Constants::TRADE_BAGS_END) { - index = (slot_id - EQEmu::Constants::TRADE_BAGS_BEGIN) % EQEmu::Constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::constants::TRADE_BAGS_END) { + index = (slot_id - EQEmu::constants::TRADE_BAGS_BEGIN) % EQEmu::constants::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::Constants::WORLD_BEGIN && slot_id <= EQEmu::Constants::WORLD_END) { - index = (slot_id - EQEmu::Constants::WORLD_BEGIN); // % EQEmu::Constants::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots + else if (slot_id >= EQEmu::constants::WORLD_BEGIN && slot_id <= EQEmu::constants::WORLD_END) { + index = (slot_id - EQEmu::constants::WORLD_BEGIN); // % EQEmu::Constants::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots } return index; @@ -921,13 +921,13 @@ bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_S bool Inventory::SupportsClickCasting(int16 slot_id) { // there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range - if ((uint16)slot_id <= EQEmu::Constants::GENERAL_END || slot_id == SlotPowerSource) + if ((uint16)slot_id <= EQEmu::constants::GENERAL_END || slot_id == SlotPowerSource) { return true; } - else if (slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::Constants::GENERAL_BAGS_END) + else if (slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::constants::GENERAL_BAGS_END) { - if (EQEmu::Limits::AllowsClickCastFromBag(m_version)) + if (EQEmu::limits::AllowsClickCastFromBag(m_version)) return true; } @@ -936,7 +936,7 @@ bool Inventory::SupportsClickCasting(int16 slot_id) bool Inventory::SupportsPotionBeltCasting(int16 slot_id) { - if ((uint16)slot_id <= EQEmu::Constants::GENERAL_END || slot_id == SlotPowerSource || (slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::Constants::GENERAL_BAGS_END)) + if ((uint16)slot_id <= EQEmu::constants::GENERAL_END || slot_id == SlotPowerSource || (slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::constants::GENERAL_BAGS_END)) return true; return false; @@ -946,10 +946,10 @@ bool Inventory::SupportsPotionBeltCasting(int16 slot_id) bool Inventory::SupportsContainers(int16 slot_id) { if ((slot_id == SlotCursor) || - (slot_id >= EQEmu::Constants::GENERAL_BEGIN && slot_id <= EQEmu::Constants::GENERAL_END) || - (slot_id >= EQEmu::Constants::BANK_BEGIN && slot_id <= EQEmu::Constants::BANK_END) || - (slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_END) || - (slot_id >= EQEmu::Constants::TRADE_BEGIN && slot_id <= EQEmu::Constants::TRADE_END) + (slot_id >= EQEmu::constants::GENERAL_BEGIN && slot_id <= EQEmu::constants::GENERAL_END) || + (slot_id >= EQEmu::constants::BANK_BEGIN && slot_id <= EQEmu::constants::BANK_END) || + (slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_END) || + (slot_id >= EQEmu::constants::TRADE_BEGIN && slot_id <= EQEmu::constants::TRADE_END) ) { return true; } @@ -998,7 +998,7 @@ uint8 Inventory::FindBrightestLightType() uint8 brightest_light_type = 0; for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { - if ((iter->first < EQEmu::Constants::EQUIPMENT_BEGIN || iter->first > EQEmu::Constants::EQUIPMENT_END) && iter->first != SlotPowerSource) { continue; } + if ((iter->first < EQEmu::constants::EQUIPMENT_BEGIN || iter->first > EQEmu::constants::EQUIPMENT_END) && iter->first != SlotPowerSource) { continue; } if (iter->first == SlotAmmo) { continue; } auto inst = iter->second; @@ -1006,13 +1006,13 @@ uint8 Inventory::FindBrightestLightType() auto item = inst->GetItem(); if (item == nullptr) { continue; } - if (EQEmu::LightSource::IsLevelGreater(item->Light, brightest_light_type)) + if (EQEmu::lightsource::IsLevelGreater(item->Light, brightest_light_type)) brightest_light_type = item->Light; } uint8 general_light_type = 0; for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) { - if (iter->first < EQEmu::Constants::GENERAL_BEGIN || iter->first > EQEmu::Constants::GENERAL_END) { continue; } + if (iter->first < EQEmu::constants::GENERAL_BEGIN || iter->first > EQEmu::constants::GENERAL_END) { continue; } auto inst = iter->second; if (inst == nullptr) { continue; } @@ -1022,11 +1022,11 @@ uint8 Inventory::FindBrightestLightType() if (item->ItemClass != ItemClassCommon) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } - if (EQEmu::LightSource::TypeToLevel(item->Light)) + if (EQEmu::lightsource::TypeToLevel(item->Light)) general_light_type = item->Light; } - if (EQEmu::LightSource::IsLevelGreater(general_light_type, brightest_light_type)) + if (EQEmu::lightsource::IsLevelGreater(general_light_type, brightest_light_type)) brightest_light_type = general_light_type; return brightest_light_type; @@ -1149,27 +1149,27 @@ int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst) m_cursor.push_front(inst); result = slot_id; } - else if ((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::Constants::EQUIPMENT_END) || (slot_id == SlotPowerSource)) { + else if ((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::constants::EQUIPMENT_END) || (slot_id == SlotPowerSource)) { m_worn[slot_id] = inst; result = slot_id; } - else if ((slot_id >= EQEmu::Constants::GENERAL_BEGIN && slot_id <= EQEmu::Constants::GENERAL_END)) { + else if ((slot_id >= EQEmu::constants::GENERAL_BEGIN && slot_id <= EQEmu::constants::GENERAL_END)) { m_inv[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::Constants::TRIBUTE_BEGIN && slot_id <= EQEmu::Constants::TRIBUTE_END) { + else if (slot_id >= EQEmu::constants::TRIBUTE_BEGIN && slot_id <= EQEmu::constants::TRIBUTE_END) { m_worn[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::Constants::BANK_BEGIN && slot_id <= EQEmu::Constants::BANK_END) { + else if (slot_id >= EQEmu::constants::BANK_BEGIN && slot_id <= EQEmu::constants::BANK_END) { m_bank[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_END) { + else if (slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_END) { m_shbank[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::Constants::TRADE_BEGIN && slot_id <= EQEmu::Constants::TRADE_END) { + else if (slot_id >= EQEmu::constants::TRADE_BEGIN && slot_id <= EQEmu::constants::TRADE_END) { m_trade[slot_id] = inst; result = slot_id; } @@ -1207,9 +1207,9 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui return iter->first; } - for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::Legacy::SLOT_AUGMENT; + return EQEmu::legacy::SLOT_AUGMENT; } if (!inst->IsType(ItemClassContainer)) { continue; } @@ -1224,9 +1224,9 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui return Inventory::CalcSlotId(iter->first, bag_iter->first); } - for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::Legacy::SLOT_AUGMENT; + return EQEmu::legacy::SLOT_AUGMENT; } } } @@ -1255,9 +1255,9 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) return SlotCursor; } - for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::Legacy::SLOT_AUGMENT; + return EQEmu::legacy::SLOT_AUGMENT; } if (!inst->IsType(ItemClassContainer)) { continue; } @@ -1272,9 +1272,9 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) return Inventory::CalcSlotId(SlotCursor, bag_iter->first); } - for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::Legacy::SLOT_AUGMENT; + return EQEmu::legacy::SLOT_AUGMENT; } } @@ -1361,12 +1361,12 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 if (inst->GetItem()->LoreGroup == loregroup) return iter->first; - for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { auto aug_inst = inst->GetAugment(index); if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::Legacy::SLOT_AUGMENT; + return EQEmu::legacy::SLOT_AUGMENT; } if (!inst->IsType(ItemClassContainer)) { continue; } @@ -1378,12 +1378,12 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup) return Inventory::CalcSlotId(iter->first, bag_iter->first); - for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { auto aug_inst = bag_inst->GetAugment(index); if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::Legacy::SLOT_AUGMENT; + return EQEmu::legacy::SLOT_AUGMENT; } } } @@ -1401,12 +1401,12 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (inst->GetItem()->LoreGroup == loregroup) return SlotCursor; - for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { auto aug_inst = inst->GetAugment(index); if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::Legacy::SLOT_AUGMENT; + return EQEmu::legacy::SLOT_AUGMENT; } if (!inst->IsType(ItemClassContainer)) { continue; } @@ -1418,12 +1418,12 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup) return Inventory::CalcSlotId(SlotCursor, bag_iter->first); - for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { auto aug_inst = bag_inst->GetAugment(index); if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::Legacy::SLOT_AUGMENT; + return EQEmu::legacy::SLOT_AUGMENT; } } @@ -1641,7 +1641,7 @@ bool ItemInst::IsEquipable(int16 slot_id) const // another "shouldn't do" fix..will be fixed in future updates (requires code and database work) int16 use_slot = INVALID_INDEX; if (slot_id == SlotPowerSource) { use_slot = SlotGeneral1; } - if ((uint16)slot_id <= EQEmu::Constants::EQUIPMENT_END) { use_slot = slot_id; } + if ((uint16)slot_id <= EQEmu::constants::EQUIPMENT_END) { use_slot = slot_id; } if (use_slot != INVALID_INDEX) { if (m_item->Slots & (1 << use_slot)) @@ -1656,7 +1656,7 @@ bool ItemInst::IsAugmentable() const if (!m_item) return false; - for (int index = 0; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { + for (int index = 0; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { if (m_item->AugSlotType[index] != NO_ITEM) return true; } @@ -1670,8 +1670,8 @@ bool ItemInst::AvailableWearSlot(uint32 aug_wear_slots) const { if (!m_item || m_item->ItemClass != ItemClassCommon) return false; - int index = EQEmu::Constants::EQUIPMENT_BEGIN; - for (; index <= SlotGeneral1; ++index) { // MainGeneral1 should be EQEmu::Constants::EQUIPMENT_END + int index = EQEmu::constants::EQUIPMENT_BEGIN; + for (; index <= SlotGeneral1; ++index) { // MainGeneral1 should be EQEmu::constants::EQUIPMENT_END if (m_item->Slots & (1 << index)) { if (aug_wear_slots & (1 << index)) break; @@ -1686,14 +1686,14 @@ int8 ItemInst::AvailableAugmentSlot(int32 augtype) const if (!m_item || m_item->ItemClass != ItemClassCommon) return INVALID_INDEX; - int index = AUG_BEGIN; - for (; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { + int index = AUG_INDEX_BEGIN; + for (; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { if (GetItem(index)) { continue; } if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype))) break; } - return (index < EQEmu::Constants::ITEM_COMMON_SIZE) ? index : INVALID_INDEX; + return (index < EQEmu::constants::ITEM_COMMON_SIZE) ? index : INVALID_INDEX; } bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const @@ -1836,7 +1836,7 @@ uint8 ItemInst::FirstOpenSlot() const return INVALID_INDEX; uint8 slots = m_item->BagSlots, i; - for (i = SUB_BEGIN; i < slots; i++) { + for (i = SUB_INDEX_BEGIN; i < slots; i++) { if (!GetItem(i)) break; } @@ -1850,7 +1850,7 @@ uint8 ItemInst::GetTotalItemCount() const if (m_item && m_item->ItemClass != ItemClassContainer) { return item_count; } - for (int index = SUB_BEGIN; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } } + for (int index = SUB_INDEX_BEGIN; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } } return item_count; } @@ -1860,7 +1860,7 @@ bool ItemInst::IsNoneEmptyContainer() if (!m_item || m_item->ItemClass != ItemClassContainer) return false; - for (int index = SUB_BEGIN; index < m_item->BagSlots; ++index) { + for (int index = SUB_INDEX_BEGIN; index < m_item->BagSlots; ++index) { if (GetItem(index)) return true; } @@ -1882,7 +1882,7 @@ ItemInst* ItemInst::GetOrnamentationAug(int32 ornamentationAugtype) const if (!m_item || m_item->ItemClass != ItemClassCommon) { return nullptr; } if (ornamentationAugtype == 0) { return nullptr; } - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype) { @@ -2049,7 +2049,7 @@ bool ItemInst::IsAugmented() if (!m_item || m_item->ItemClass != ItemClassCommon) return false; - for (int index = AUG_BEGIN; index < EQEmu::Constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { if (GetAugmentItemID(index)) return true; } @@ -2178,7 +2178,7 @@ bool ItemInst::IsSlotAllowed(int16 slot_id) const { else if (Inventory::SupportsContainers(slot_id)) { return true; } else if (m_item->Slots & (1 << slot_id)) { return true; } else if (slot_id == SlotPowerSource && (m_item->Slots & (1 << 22))) { return true; } // got lazy... - else if (slot_id != SlotPowerSource && slot_id > EQEmu::Constants::EQUIPMENT_END) { return true; } + else if (slot_id != SlotPowerSource && slot_id > EQEmu::constants::EQUIPMENT_END) { return true; } else { return false; } } @@ -2330,7 +2330,7 @@ int ItemInst::GetItemArmorClass(bool augments) const if (item) { ac = item->AC; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) ac += GetAugment(i)->GetItemArmorClass(); } @@ -2372,7 +2372,7 @@ int ItemInst::GetItemElementalDamage(int &magic, int &fire, int &cold, int &pois } if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) GetAugment(i)->GetItemElementalDamage(magic, fire, cold, poison, disease, chromatic, prismatic, physical, corruption); } @@ -2389,7 +2389,7 @@ int ItemInst::GetItemElementalFlag(bool augments) const return flag; if (augments) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) { if (GetAugment(i)) flag = GetAugment(i)->GetItemElementalFlag(); if (flag) @@ -2410,7 +2410,7 @@ int ItemInst::GetItemElementalDamage(bool augments) const return damage; if (augments) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) { if (GetAugment(i)) damage = GetAugment(i)->GetItemElementalDamage(); if (damage) @@ -2429,7 +2429,7 @@ int ItemInst::GetItemRecommendedLevel(bool augments) const level = item->RecLevel; if (augments) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) { int temp = 0; if (GetAugment(i)) { temp = GetAugment(i)->GetItemRecommendedLevel(); @@ -2451,7 +2451,7 @@ int ItemInst::GetItemRequiredLevel(bool augments) const level = item->ReqLevel; if (augments) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) { int temp = 0; if (GetAugment(i)) { temp = GetAugment(i)->GetItemRequiredLevel(); @@ -2473,7 +2473,7 @@ int ItemInst::GetItemWeaponDamage(bool augments) const damage = item->Damage; if (augments) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemWeaponDamage(); } @@ -2489,7 +2489,7 @@ int ItemInst::GetItemBackstabDamage(bool augments) const damage = item->BackstabDmg; if (augments) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBackstabDamage(); } @@ -2507,7 +2507,7 @@ int ItemInst::GetItemBaneDamageBody(bool augments) const return body; if (augments) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) { body = GetAugment(i)->GetItemBaneDamageBody(); if (body) @@ -2528,7 +2528,7 @@ int ItemInst::GetItemBaneDamageRace(bool augments) const return race; if (augments) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) { race = GetAugment(i)->GetItemBaneDamageRace(); if (race) @@ -2548,7 +2548,7 @@ int ItemInst::GetItemBaneDamageBody(bodyType against, bool augments) const damage += item->BaneDmgAmt; if (augments) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBaneDamageBody(against); } @@ -2565,7 +2565,7 @@ int ItemInst::GetItemBaneDamageRace(uint16 against, bool augments) const damage += item->BaneDmgRaceAmt; if (augments) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBaneDamageRace(against); } @@ -2581,7 +2581,7 @@ int ItemInst::GetItemMagical(bool augments) const return 1; if (augments) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i) && GetAugment(i)->GetItemMagical()) return 1; } @@ -2596,7 +2596,7 @@ int ItemInst::GetItemHP(bool augments) const if (item) { hp = item->HP; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) hp += GetAugment(i)->GetItemHP(); } @@ -2610,7 +2610,7 @@ int ItemInst::GetItemMana(bool augments) const if (item) { mana = item->Mana; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) mana += GetAugment(i)->GetItemMana(); } @@ -2624,7 +2624,7 @@ int ItemInst::GetItemEndur(bool augments) const if (item) { endur = item->Endur; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) endur += GetAugment(i)->GetItemEndur(); } @@ -2638,7 +2638,7 @@ int ItemInst::GetItemAttack(bool augments) const if (item) { atk = item->Attack; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) atk += GetAugment(i)->GetItemAttack(); } @@ -2652,7 +2652,7 @@ int ItemInst::GetItemStr(bool augments) const if (item) { str = item->AStr; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) str += GetAugment(i)->GetItemStr(); } @@ -2666,7 +2666,7 @@ int ItemInst::GetItemSta(bool augments) const if (item) { sta = item->ASta; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) sta += GetAugment(i)->GetItemSta(); } @@ -2680,7 +2680,7 @@ int ItemInst::GetItemDex(bool augments) const if (item) { total = item->ADex; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemDex(); } @@ -2694,7 +2694,7 @@ int ItemInst::GetItemAgi(bool augments) const if (item) { total = item->AAgi; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemAgi(); } @@ -2708,7 +2708,7 @@ int ItemInst::GetItemInt(bool augments) const if (item) { total = item->AInt; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemInt(); } @@ -2722,7 +2722,7 @@ int ItemInst::GetItemWis(bool augments) const if (item) { total = item->AWis; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemWis(); } @@ -2736,7 +2736,7 @@ int ItemInst::GetItemCha(bool augments) const if (item) { total = item->ACha; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCha(); } @@ -2750,7 +2750,7 @@ int ItemInst::GetItemMR(bool augments) const if (item) { total = item->MR; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemMR(); } @@ -2764,7 +2764,7 @@ int ItemInst::GetItemFR(bool augments) const if (item) { total = item->FR; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemFR(); } @@ -2778,7 +2778,7 @@ int ItemInst::GetItemCR(bool augments) const if (item) { total = item->CR; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCR(); } @@ -2792,7 +2792,7 @@ int ItemInst::GetItemPR(bool augments) const if (item) { total = item->PR; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemPR(); } @@ -2806,7 +2806,7 @@ int ItemInst::GetItemDR(bool augments) const if (item) { total = item->DR; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemDR(); } @@ -2820,7 +2820,7 @@ int ItemInst::GetItemCorrup(bool augments) const if (item) { total = item->SVCorruption; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCorrup(); } @@ -2834,7 +2834,7 @@ int ItemInst::GetItemHeroicStr(bool augments) const if (item) { total = item->HeroicStr; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicStr(); } @@ -2848,7 +2848,7 @@ int ItemInst::GetItemHeroicSta(bool augments) const if (item) { total = item->HeroicSta; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicSta(); } @@ -2862,7 +2862,7 @@ int ItemInst::GetItemHeroicDex(bool augments) const if (item) { total = item->HeroicDex; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicDex(); } @@ -2876,7 +2876,7 @@ int ItemInst::GetItemHeroicAgi(bool augments) const if (item) { total = item->HeroicAgi; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicAgi(); } @@ -2890,7 +2890,7 @@ int ItemInst::GetItemHeroicInt(bool augments) const if (item) { total = item->HeroicInt; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicInt(); } @@ -2904,7 +2904,7 @@ int ItemInst::GetItemHeroicWis(bool augments) const if (item) { total = item->HeroicWis; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicWis(); } @@ -2918,7 +2918,7 @@ int ItemInst::GetItemHeroicCha(bool augments) const if (item) { total = item->HeroicCha; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCha(); } @@ -2932,7 +2932,7 @@ int ItemInst::GetItemHeroicMR(bool augments) const if (item) { total = item->HeroicMR; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicMR(); } @@ -2946,7 +2946,7 @@ int ItemInst::GetItemHeroicFR(bool augments) const if (item) { total = item->HeroicFR; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicFR(); } @@ -2960,7 +2960,7 @@ int ItemInst::GetItemHeroicCR(bool augments) const if (item) { total = item->HeroicCR; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCR(); } @@ -2974,7 +2974,7 @@ int ItemInst::GetItemHeroicPR(bool augments) const if (item) { total = item->HeroicPR; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicPR(); } @@ -2988,7 +2988,7 @@ int ItemInst::GetItemHeroicDR(bool augments) const if (item) { total = item->HeroicDR; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicDR(); } @@ -3002,7 +3002,7 @@ int ItemInst::GetItemHeroicCorrup(bool augments) const if (item) { total = item->HeroicSVCorrup; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCorrup(); } @@ -3016,7 +3016,7 @@ int ItemInst::GetItemHaste(bool augments) const if (item) { total = item->Haste; if (augments) - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) { int temp = GetAugment(i)->GetItemHaste(); if (temp > total) diff --git a/common/item_struct.h b/common/item_struct.h index c22684207..42625b5bc 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -183,9 +183,9 @@ struct Item_Struct { int32 FactionAmt4; // Faction Amt 4 char CharmFile[32]; // ? uint32 AugType; - uint8 AugSlotType[EQEmu::Constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Type - uint8 AugSlotVisible[EQEmu::Constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Visible - uint8 AugSlotUnk2[EQEmu::Constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related + uint8 AugSlotType[EQEmu::constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Type + uint8 AugSlotVisible[EQEmu::constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Visible + uint8 AugSlotUnk2[EQEmu::constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related uint32 LDoNTheme; uint32 LDoNPrice; uint32 LDoNSold; diff --git a/common/light_source.cpp b/common/light_source.cpp index 9b20b4501..c43395753 100644 --- a/common/light_source.cpp +++ b/common/light_source.cpp @@ -20,7 +20,12 @@ #include "light_source.h" -void EQEmu::LightSource::impl::Clear() +EQEmu::lightsource::LightSourceProfile::LightSourceProfile() +{ + Clear(); +} + +void EQEmu::lightsource::LightSourceProfile::Clear() { Type.Innate = 0; Type.Equipment = 0; @@ -33,62 +38,62 @@ void EQEmu::LightSource::impl::Clear() Level.Active = 0; } -uint8 EQEmu::LightSource::TypeToLevel(uint8 light_type) +uint8 EQEmu::lightsource::TypeToLevel(uint8 light_type) { switch (light_type) { - case TypeGlobeOfStars: - return LevelBrilliant; // 10 - case TypeFlamelessLantern: - case TypeGreaterLightstone: - return LevelLargeMagic; // 9 - case TypeLargeLantern: - return LevelLargeLantern; // 8 - case TypeSteinOfMoggok: - case TypeLightstone: - return LevelMagicLantern; // 7 - case TypeSmallLantern: - return LevelSmallLantern; // 6 - case TypeColdlight: - case TypeUnknown2: - return LevelBlueLight; // 5 - case TypeFireBeetleEye: - case TypeUnknown1: - return LevelRedLight; // 4 - case TypeTinyGlowingSkull: - case TypeLightGlobe: - return LevelSmallMagic; // 3 - case TypeTorch: - return LevelTorch; // 2 - case TypeCandle: - return LevelCandle; // 1 + case LightTypeGlobeOfStars: + return LightLevelBrilliant; // 10 + case LightTypeFlamelessLantern: + case LightTypeGreaterLightstone: + return LightLevelLargeMagic; // 9 + case LightTypeLargeLantern: + return LightLevelLargeLantern; // 8 + case LightTypeSteinOfMoggok: + case LightTypeLightstone: + return LightLevelMagicLantern; // 7 + case LightTypeSmallLantern: + return LightLevelSmallLantern; // 6 + case LightTypeColdlight: + case LightTypeUnknown2: + return LightLevelBlueLight; // 5 + case LightTypeFireBeetleEye: + case LightTypeUnknown1: + return LightLevelRedLight; // 4 + case LightTypeTinyGlowingSkull: + case LightTypeLightGlobe: + return LightLevelSmallMagic; // 3 + case LightTypeTorch: + return LightLevelTorch; // 2 + case LightTypeCandle: + return LightLevelCandle; // 1 default: - return LevelUnlit; // 0 + return LightLevelUnlit; // 0 } } -bool EQEmu::LightSource::IsLevelGreater(uint8 left_type, uint8 right_type) +bool EQEmu::lightsource::IsLevelGreater(uint8 left_type, uint8 right_type) { - static const uint8 light_levels[TypeCount] = { - LevelUnlit, /* TypeNone */ - LevelCandle, /* TypeCandle */ - LevelTorch, /* TypeTorch */ - LevelSmallMagic, /* TypeTinyGlowingSkull */ - LevelSmallLantern, /* TypeSmallLantern */ - LevelMagicLantern, /* TypeSteinOfMoggok */ - LevelLargeLantern, /* TypeLargeLantern */ - LevelLargeMagic, /* TypeFlamelessLantern */ - LevelBrilliant, /* TypeGlobeOfStars */ - LevelSmallMagic, /* TypeLightGlobe */ - LevelMagicLantern, /* TypeLightstone */ - LevelLargeMagic, /* TypeGreaterLightstone */ - LevelRedLight, /* TypeFireBeetleEye */ - LevelBlueLight, /* TypeColdlight */ - LevelRedLight, /* TypeUnknown1 */ - LevelBlueLight /* TypeUnknown2 */ + static const uint8 light_levels[LightTypeCount] = { + LightLevelUnlit, /* LightTypeNone */ + LightLevelCandle, /* LightTypeCandle */ + LightLevelTorch, /* LightTypeTorch */ + LightLevelSmallMagic, /* LightTypeTinyGlowingSkull */ + LightLevelSmallLantern, /* LightTypeSmallLantern */ + LightLevelMagicLantern, /* LightTypeSteinOfMoggok */ + LightLevelLargeLantern, /* LightTypeLargeLantern */ + LightLevelLargeMagic, /* LightTypeFlamelessLantern */ + LightLevelBrilliant, /* LightTypeGlobeOfStars */ + LightLevelSmallMagic, /* LightTypeLightGlobe */ + LightLevelMagicLantern, /* LightTypeLightstone */ + LightLevelLargeMagic, /* LightTypeGreaterLightstone */ + LightLevelRedLight, /* LightTypeFireBeetleEye */ + LightLevelBlueLight, /* LightTypeColdlight */ + LightLevelRedLight, /* LightTypeUnknown1 */ + LightLevelBlueLight /* LightTypeUnknown2 */ }; - if (left_type >= TypeCount) { left_type = TypeNone; } - if (right_type >= TypeCount) { right_type = TypeNone; } + if (left_type >= LightTypeCount) { left_type = LightTypeNone; } + if (right_type >= LightTypeCount) { right_type = LightTypeNone; } return (light_levels[left_type] > light_levels[right_type]); } diff --git a/common/light_source.h b/common/light_source.h index 3fabe7ebe..fa4f09003 100644 --- a/common/light_source.h +++ b/common/light_source.h @@ -17,52 +17,51 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef LIGHT_SOURCE_H -#define LIGHT_SOURCE_H +#ifndef COMMON_LIGHT_SOURCE_H +#define COMMON_LIGHT_SOURCE_H #include "types.h" namespace EQEmu { - class LightSource { - public: - enum Types { - TypeNone = 0, - TypeCandle, - TypeTorch, - TypeTinyGlowingSkull, - TypeSmallLantern, - TypeSteinOfMoggok, // 5 - TypeLargeLantern, - TypeFlamelessLantern, - TypeGlobeOfStars, - TypeLightGlobe, - TypeLightstone, // 10 - TypeGreaterLightstone, - TypeFireBeetleEye, - TypeColdlight, - TypeUnknown1, - TypeUnknown2, // 15 - TypeCount + namespace lightsource { + enum LightType { + LightTypeNone = 0, + LightTypeCandle, + LightTypeTorch, + LightTypeTinyGlowingSkull, + LightTypeSmallLantern, + LightTypeSteinOfMoggok, // 5 + LightTypeLargeLantern, + LightTypeFlamelessLantern, + LightTypeGlobeOfStars, + LightTypeLightGlobe, + LightTypeLightstone, // 10 + LightTypeGreaterLightstone, + LightTypeFireBeetleEye, + LightTypeColdlight, + LightTypeUnknown1, + LightTypeUnknown2, // 15 + LightTypeCount }; - enum Levels { - LevelUnlit = 0, - LevelCandle, - LevelTorch, - LevelSmallMagic, - LevelRedLight, - LevelBlueLight, // 5 - LevelSmallLantern, - LevelMagicLantern, - LevelLargeLantern, - LevelLargeMagic, - LevelBrilliant, // 10 - LevelCount + enum LightLevel { + LightLevelUnlit = 0, + LightLevelCandle, + LightLevelTorch, + LightLevelSmallMagic, + LightLevelRedLight, + LightLevelBlueLight, // 5 + LightLevelSmallLantern, + LightLevelMagicLantern, + LightLevelLargeLantern, + LightLevelLargeMagic, + LightLevelBrilliant, // 10 + LightLevelCount }; - class impl { + struct LightSourceProfile { /* Current criteria (light types): Equipment: { 0 .. 15 } @@ -79,8 +78,7 @@ namespace EQEmu - All clients have a bug regarding stackable items (light and sound updates are not processed when picking up an item) -- The timer-based update cancels out the invalid light source */ - public: - impl() { Clear(); } + LightSourceProfile(); void Clear(); @@ -101,9 +99,9 @@ namespace EQEmu } Level; }; - static uint8 TypeToLevel(uint8 light_type); - static bool IsLevelGreater(uint8 left_type, uint8 right_type); + uint8 TypeToLevel(uint8 light_type); + bool IsLevelGreater(uint8 left_type, uint8 right_type); }; } -#endif /* LIGHT_SOURCE_H */ +#endif /* COMMON_LIGHT_SOURCE_H */ diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index ad252d39d..58b420bf9 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2342,7 +2342,7 @@ namespace RoF outapp->WriteUInt32(consts::BANDOLIERS_SIZE); // Copy bandoliers where server and client indexes converge - for (uint32 r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(emu->bandoliers[r].Name); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(emu->bandoliers[r].Items[j].Name); @@ -2357,7 +2357,7 @@ namespace RoF } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(""); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(""); @@ -2369,7 +2369,7 @@ namespace RoF outapp->WriteUInt32(consts::POTION_BELT_ITEM_COUNT); // Copy potion belt where server and client indexes converge - for (uint32 r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(emu->potionbelt.Items[r].Name); outapp->WriteUInt32(emu->potionbelt.Items[r].ID); if (emu->potionbelt.Items[r].Icon) { @@ -2381,7 +2381,7 @@ namespace RoF } } // Nullify potion belt where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(""); outapp->WriteUInt32(0); outapp->WriteSInt32(-1); @@ -2502,9 +2502,9 @@ namespace RoF outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt32(EQEmu::Constants::TRIBUTE_SIZE); + outapp->WriteUInt32(EQEmu::constants::TRIBUTE_SIZE); - for (uint32 r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) + for (uint32 r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { outapp->WriteUInt32(emu->tributes[r].tribute); outapp->WriteUInt32(emu->tributes[r].tier); @@ -2824,8 +2824,8 @@ namespace RoF RoFSlot.Type = 8; // Observed RoFSlot.Unknown02 = 0; RoFSlot.Slot = 0xffff; - RoFSlot.Sub = 0xffff; - RoFSlot.Aug = 0xffff; + RoFSlot.SubIndex = 0xffff; + RoFSlot.AugIndex = 0xffff; RoFSlot.Unknown01 = 0; eq->unknown_slot = RoFSlot; OUT(recipe_id); @@ -4810,7 +4810,7 @@ namespace RoF IN(item_id); int r; - for (r = 0; r < EQEmu::Constants::ITEM_COMMON_SIZE; r++) { + for (r = 0; r < EQEmu::constants::ITEM_COMMON_SIZE; r++) { IN(augments[r]); } // Max Augs is now 6, but no code to support that many yet @@ -4866,7 +4866,7 @@ namespace RoF SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot); - Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.Type, eq->to_slot.Type, eq->from_slot.Slot, eq->to_slot.Slot, eq->from_slot.Sub, eq->to_slot.Sub, eq->from_slot.Aug, eq->to_slot.Aug, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); + Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.Type, eq->to_slot.Type, eq->from_slot.Slot, eq->to_slot.Slot, eq->from_slot.SubIndex, eq->to_slot.SubIndex, eq->from_slot.AugIndex, eq->to_slot.AugIndex, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); emu->from_slot = RoFToServerSlot(eq->from_slot); emu->to_slot = RoFToServerSlot(eq->to_slot); IN(number_in_stack); @@ -5101,7 +5101,7 @@ namespace RoF int16 slot_id = RoFToServerSlot(eq->container_slot); if (slot_id == 4000) { - slot_id = EQEmu::Legacy::SLOT_TRADESKILL; // 1000 + slot_id = EQEmu::legacy::SLOT_TRADESKILL; // 1000 } emu->container_slot = slot_id; emu->guildtribute_slot = RoFToServerSlot(eq->guildtribute_slot); // this should only return INVALID_INDEX until implemented @@ -5218,8 +5218,8 @@ namespace RoF hdr.slot_type = (merchant_slot == 0) ? slot_id.Type : 9; // 9 is merchant 20 is reclaim items? hdr.main_slot = (merchant_slot == 0) ? slot_id.Slot : merchant_slot; - hdr.sub_slot = (merchant_slot == 0) ? slot_id.Sub : 0xffff; - hdr.unknown013 = (merchant_slot == 0) ? slot_id.Aug : 0xffff; + hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubIndex : 0xffff; + hdr.unknown013 = (merchant_slot == 0) ? slot_id.AugIndex : 0xffff; hdr.price = inst->GetPrice(); hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); //hdr.merchant_slot = (merchant_slot == 0) ? 1 : 0xffffffff; @@ -5427,7 +5427,7 @@ namespace RoF isbs.augdistiller = 65535; isbs.augrestrict = item->AugRestrict; - for (int x = AUG_BEGIN; x < consts::ITEM_COMMON_SIZE; x++) + for (int x = AUG_INDEX_BEGIN; x < consts::ITEM_COMMON_SIZE; x++) { isbs.augslots[x].type = item->AugSlotType[x]; isbs.augslots[x].visible = item->AugSlotVisible[x]; @@ -5678,7 +5678,7 @@ namespace RoF uint32 SubLengths[10]; - for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -5690,15 +5690,15 @@ namespace RoF iqbs.subitem_count++; - if (slot_id_in >= EQEmu::Constants::GENERAL_BEGIN && slot_id_in <= EQEmu::Constants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::constants::GENERAL_BEGIN && slot_id_in <= EQEmu::constants::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::Constants::BANK_BEGIN && slot_id_in <= EQEmu::Constants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::constants::BANK_BEGIN && slot_id_in <= EQEmu::constants::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::Constants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::constants::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -5713,7 +5713,7 @@ namespace RoF ss.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); - for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { if (SubSerializations[x]) { @@ -5739,8 +5739,8 @@ namespace RoF RoFSlot.Type = INVALID_INDEX; RoFSlot.Unknown02 = NOT_USED; RoFSlot.Slot = INVALID_INDEX; - RoFSlot.Sub = INVALID_INDEX; - RoFSlot.Aug = INVALID_INDEX; + RoFSlot.SubIndex = INVALID_INDEX; + RoFSlot.AugIndex = INVALID_INDEX; RoFSlot.Unknown01 = NOT_USED; uint32 TempSlot = 0; @@ -5764,51 +5764,51 @@ namespace RoF RoFSlot.MainSlot = ServerSlot - 31; }*/ - else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) { // (> 250 && < 341) + else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) { // (> 250 && < 341) RoFSlot.Type = inventory::TypePossessions; TempSlot = serverSlot - 1; - RoFSlot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 2; - RoFSlot.Sub = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::Constants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 2; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::constants::ITEM_CONTAINER_SIZE); if (RoFSlot.Slot >= inventory::SlotGeneral9) // (> 30) RoFSlot.Slot = inventory::SlotCursor; } - else if (serverSlot >= EQEmu::Constants::TRIBUTE_BEGIN && serverSlot <= EQEmu::Constants::TRIBUTE_END) { // Tribute + else if (serverSlot >= EQEmu::constants::TRIBUTE_BEGIN && serverSlot <= EQEmu::constants::TRIBUTE_END) { // Tribute RoFSlot.Type = inventory::TypeTribute; - RoFSlot.Slot = serverSlot - EQEmu::Constants::TRIBUTE_BEGIN; + RoFSlot.Slot = serverSlot - EQEmu::constants::TRIBUTE_BEGIN; } - else if (serverSlot >= EQEmu::Constants::BANK_BEGIN && serverSlot <= EQEmu::Constants::BANK_BAGS_END) { + else if (serverSlot >= EQEmu::constants::BANK_BEGIN && serverSlot <= EQEmu::constants::BANK_BAGS_END) { RoFSlot.Type = inventory::TypeBank; - TempSlot = serverSlot - EQEmu::Constants::BANK_BEGIN; + TempSlot = serverSlot - EQEmu::constants::BANK_BEGIN; RoFSlot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoFSlot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.Sub = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EQEmu::Constants::SHARED_BANK_BEGIN && serverSlot <= EQEmu::Constants::SHARED_BANK_BAGS_END) { + else if (serverSlot >= EQEmu::constants::SHARED_BANK_BEGIN && serverSlot <= EQEmu::constants::SHARED_BANK_BAGS_END) { RoFSlot.Type = inventory::TypeSharedBank; - TempSlot = serverSlot - EQEmu::Constants::SHARED_BANK_BEGIN; + TempSlot = serverSlot - EQEmu::constants::SHARED_BANK_BEGIN; RoFSlot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoFSlot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.Sub = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EQEmu::Constants::TRADE_BEGIN && serverSlot <= EQEmu::Constants::TRADE_BAGS_END) { + else if (serverSlot >= EQEmu::constants::TRADE_BEGIN && serverSlot <= EQEmu::constants::TRADE_BAGS_END) { RoFSlot.Type = inventory::TypeTrade; - TempSlot = serverSlot - EQEmu::Constants::TRADE_BEGIN; + TempSlot = serverSlot - EQEmu::constants::TRADE_BEGIN; RoFSlot.Slot = TempSlot; if (TempSlot > 30) { - RoFSlot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.Sub = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); } /* @@ -5825,13 +5825,13 @@ namespace RoF */ } - else if (serverSlot >= EQEmu::Constants::WORLD_BEGIN && serverSlot <= EQEmu::Constants::WORLD_END) { + else if (serverSlot >= EQEmu::constants::WORLD_BEGIN && serverSlot <= EQEmu::constants::WORLD_END) { RoFSlot.Type = inventory::TypeWorld; - TempSlot = serverSlot - EQEmu::Constants::WORLD_BEGIN; + TempSlot = serverSlot - EQEmu::constants::WORLD_BEGIN; RoFSlot.Slot = TempSlot; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoFSlot.Type, RoFSlot.Unknown02, RoFSlot.Slot, RoFSlot.Sub, RoFSlot.Aug, RoFSlot.Unknown01); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoFSlot.Type, RoFSlot.Unknown02, RoFSlot.Slot, RoFSlot.SubIndex, RoFSlot.AugIndex, RoFSlot.Unknown01); return RoFSlot; } @@ -5840,8 +5840,8 @@ namespace RoF { structs::TypelessInventorySlot_Struct RoFSlot; RoFSlot.Slot = INVALID_INDEX; - RoFSlot.Sub = INVALID_INDEX; - RoFSlot.Aug = INVALID_INDEX; + RoFSlot.SubIndex = INVALID_INDEX; + RoFSlot.AugIndex = INVALID_INDEX; RoFSlot.Unknown01 = NOT_USED; uint32 TempSlot = 0; @@ -5866,13 +5866,13 @@ namespace RoF }*/ } - else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) { + else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) { TempSlot = serverSlot - 1; - RoFSlot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 2; - RoFSlot.Sub = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::Constants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 2; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::constants::ITEM_CONTAINER_SIZE); } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoFSlot.Slot, RoFSlot.Sub, RoFSlot.Aug, RoFSlot.Unknown01); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoFSlot.Slot, RoFSlot.SubIndex, RoFSlot.AugIndex, RoFSlot.Unknown01); return RoFSlot; } @@ -5911,17 +5911,17 @@ namespace RoF else // Worn Slots TempSlot = rofSlot.Slot; - if (rofSlot.Sub >= SUB_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rofSlot.Sub + 1; + if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; ServerSlot = TempSlot; } else if (rofSlot.Type == inventory::TypeBank) { - TempSlot = EQEmu::Constants::BANK_BEGIN; + TempSlot = EQEmu::constants::BANK_BEGIN; - if (rofSlot.Sub >= SUB_BEGIN) - TempSlot += ((rofSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rofSlot.Sub + 1; + if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) + TempSlot += ((rofSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; else TempSlot += rofSlot.Slot; @@ -5930,10 +5930,10 @@ namespace RoF } else if (rofSlot.Type == inventory::TypeSharedBank) { - TempSlot = EQEmu::Constants::SHARED_BANK_BEGIN; + TempSlot = EQEmu::constants::SHARED_BANK_BEGIN; - if (rofSlot.Sub >= SUB_BEGIN) - TempSlot += ((rofSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rofSlot.Sub + 1; + if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) + TempSlot += ((rofSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; else TempSlot += rofSlot.Slot; @@ -5942,12 +5942,12 @@ namespace RoF } else if (rofSlot.Type == inventory::TypeTrade) { - TempSlot = EQEmu::Constants::TRADE_BEGIN; + TempSlot = EQEmu::constants::TRADE_BEGIN; - if (rofSlot.Sub >= SUB_BEGIN) - TempSlot += ((rofSlot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rofSlot.Sub + 1; + if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) + TempSlot += ((rofSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; // OLD CODE: - //TempSlot += 100 + (RoFSlot.MainSlot * EQEmu::Constants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot; + //TempSlot += 100 + (RoFSlot.MainSlot * EQEmu::constants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot; else TempSlot += rofSlot.Slot; @@ -5956,9 +5956,9 @@ namespace RoF } else if (rofSlot.Type == inventory::TypeWorld) { - TempSlot = EQEmu::Constants::WORLD_BEGIN; + TempSlot = EQEmu::constants::WORLD_BEGIN; - if (rofSlot.Slot >= SUB_BEGIN) + if (rofSlot.Slot >= SUB_INDEX_BEGIN) TempSlot += rofSlot.Slot; ServerSlot = TempSlot; @@ -5977,7 +5977,7 @@ namespace RoF ServerSlot = INVALID_INDEX; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rofSlot.Type, rofSlot.Unknown02, rofSlot.Slot, rofSlot.Sub, rofSlot.Aug, rofSlot.Unknown01, ServerSlot); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rofSlot.Type, rofSlot.Unknown02, rofSlot.Slot, rofSlot.SubIndex, rofSlot.AugIndex, rofSlot.Unknown01, ServerSlot); return ServerSlot; } @@ -6006,13 +6006,13 @@ namespace RoF else TempSlot = rofSlot.Slot; - if (rofSlot.Sub >= SUB_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rofSlot.Sub + 1; + if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; ServerSlot = TempSlot; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rofSlot.Slot, rofSlot.Sub, rofSlot.Aug, rofSlot.Unknown01, ServerSlot); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rofSlot.Slot, rofSlot.SubIndex, rofSlot.AugIndex, rofSlot.Unknown01, ServerSlot); return ServerSlot; } @@ -6024,7 +6024,7 @@ namespace RoF static inline void ServerToRoFTextLink(std::string& rofTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { rofTextLink = serverTextLink; return; } @@ -6033,7 +6033,7 @@ namespace RoF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { rofTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -6063,7 +6063,7 @@ namespace RoF static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink) { - if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find('\x12') == std::string::npos)) { serverTextLink = rofTextLink; return; } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 684a89081..d25155776 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2421,7 +2421,7 @@ namespace RoF2 outapp->WriteUInt32(consts::BANDOLIERS_SIZE); // Copy bandoliers where server and client indexes converge - for (uint32 r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(emu->bandoliers[r].Name); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(emu->bandoliers[r].Items[j].Name); @@ -2436,7 +2436,7 @@ namespace RoF2 } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(""); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(""); @@ -2448,7 +2448,7 @@ namespace RoF2 outapp->WriteUInt32(consts::POTION_BELT_ITEM_COUNT); // Copy potion belt where server and client indexes converge - for (uint32 r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(emu->potionbelt.Items[r].Name); outapp->WriteUInt32(emu->potionbelt.Items[r].ID); if (emu->potionbelt.Items[r].Icon) { @@ -2460,7 +2460,7 @@ namespace RoF2 } } // Nullify potion belt where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(""); outapp->WriteUInt32(0); outapp->WriteSInt32(-1); @@ -2577,9 +2577,9 @@ namespace RoF2 outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt32(EQEmu::Constants::TRIBUTE_SIZE); + outapp->WriteUInt32(EQEmu::constants::TRIBUTE_SIZE); - for (uint32 r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) + for (uint32 r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { outapp->WriteUInt32(emu->tributes[r].tribute); outapp->WriteUInt32(emu->tributes[r].tier); @@ -2914,8 +2914,8 @@ namespace RoF2 RoF2Slot.Type = 8; // Observed RoF2Slot.Unknown02 = 0; RoF2Slot.Slot = 0xffff; - RoF2Slot.Sub = 0xffff; - RoF2Slot.Aug = 0xffff; + RoF2Slot.SubIndex = 0xffff; + RoF2Slot.AugIndex = 0xffff; RoF2Slot.Unknown01 = 0; eq->unknown_slot = RoF2Slot; OUT(recipe_id); @@ -5028,7 +5028,7 @@ namespace RoF2 IN(item_id); int r; - for (r = 0; r < EQEmu::Constants::ITEM_COMMON_SIZE; r++) { + for (r = 0; r < EQEmu::constants::ITEM_COMMON_SIZE; r++) { IN(augments[r]); } IN(link_hash); @@ -5082,7 +5082,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - Log.Out(Logs::General, Logs::Netcode, "[RoF2] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.Type, eq->to_slot.Type, eq->from_slot.Slot, eq->to_slot.Slot, eq->from_slot.Sub, eq->to_slot.Sub, eq->from_slot.Aug, eq->to_slot.Aug, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); + Log.Out(Logs::General, Logs::Netcode, "[RoF2] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.Type, eq->to_slot.Type, eq->from_slot.Slot, eq->to_slot.Slot, eq->from_slot.SubIndex, eq->to_slot.SubIndex, eq->from_slot.AugIndex, eq->to_slot.AugIndex, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); emu->from_slot = RoF2ToServerSlot(eq->from_slot); emu->to_slot = RoF2ToServerSlot(eq->to_slot); IN(number_in_stack); @@ -5372,7 +5372,7 @@ namespace RoF2 int16 slot_id = RoF2ToServerSlot(eq->container_slot); if (slot_id == 4000) { - slot_id = EQEmu::Legacy::SLOT_TRADESKILL; // 1000 + slot_id = EQEmu::legacy::SLOT_TRADESKILL; // 1000 } emu->container_slot = slot_id; emu->guildtribute_slot = RoF2ToServerSlot(eq->guildtribute_slot); // this should only return INVALID_INDEX until implemented @@ -5489,8 +5489,8 @@ namespace RoF2 hdr.slot_type = (merchant_slot == 0) ? slot_id.Type : 9; // 9 is merchant 20 is reclaim items? hdr.main_slot = (merchant_slot == 0) ? slot_id.Slot : merchant_slot; - hdr.sub_slot = (merchant_slot == 0) ? slot_id.Sub : 0xffff; - hdr.aug_slot = (merchant_slot == 0) ? slot_id.Aug : 0xffff; + hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubIndex : 0xffff; + hdr.aug_slot = (merchant_slot == 0) ? slot_id.AugIndex : 0xffff; hdr.price = inst->GetPrice(); hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; @@ -5697,7 +5697,7 @@ namespace RoF2 isbs.augrestrict2 = -1; isbs.augrestrict = item->AugRestrict; - for (int x = AUG_BEGIN; x < consts::ITEM_COMMON_SIZE; x++) + for (int x = AUG_INDEX_BEGIN; x < consts::ITEM_COMMON_SIZE; x++) { isbs.augslots[x].type = item->AugSlotType[x]; isbs.augslots[x].visible = item->AugSlotVisible[x]; @@ -5961,7 +5961,7 @@ namespace RoF2 uint32 SubLengths[10]; - for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -5973,15 +5973,15 @@ namespace RoF2 iqbs.subitem_count++; - if (slot_id_in >= EQEmu::Constants::GENERAL_BEGIN && slot_id_in <= EQEmu::Constants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::constants::GENERAL_BEGIN && slot_id_in <= EQEmu::constants::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::Constants::BANK_BEGIN && slot_id_in <= EQEmu::Constants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::constants::BANK_BEGIN && slot_id_in <= EQEmu::constants::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::Constants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::constants::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -5996,7 +5996,7 @@ namespace RoF2 ss.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); - for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { if (SubSerializations[x]) { @@ -6022,8 +6022,8 @@ namespace RoF2 RoF2Slot.Type = INVALID_INDEX; RoF2Slot.Unknown02 = NOT_USED; RoF2Slot.Slot = INVALID_INDEX; - RoF2Slot.Sub = INVALID_INDEX; - RoF2Slot.Aug = INVALID_INDEX; + RoF2Slot.SubIndex = INVALID_INDEX; + RoF2Slot.AugIndex = INVALID_INDEX; RoF2Slot.Unknown01 = NOT_USED; uint32 TempSlot = 0; @@ -6032,7 +6032,7 @@ namespace RoF2 if (PacketType == ItemPacketLoot) { RoF2Slot.Type = inventory::TypeCorpse; - RoF2Slot.Slot = serverSlot - EQEmu::Constants::CORPSE_BEGIN; + RoF2Slot.Slot = serverSlot - EQEmu::constants::CORPSE_BEGIN; } else { @@ -6055,51 +6055,51 @@ namespace RoF2 RoF2Slot.MainSlot = ServerSlot - 31; }*/ - else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) { // (> 250 && < 341) + else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) { // (> 250 && < 341) RoF2Slot.Type = inventory::TypePossessions; TempSlot = serverSlot - 1; - RoF2Slot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 2; - RoF2Slot.Sub = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::Constants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 2; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::constants::ITEM_CONTAINER_SIZE); if (RoF2Slot.Slot >= inventory::SlotGeneral9) // (> 30) RoF2Slot.Slot = inventory::SlotCursor; } - else if (serverSlot >= EQEmu::Constants::TRIBUTE_BEGIN && serverSlot <= EQEmu::Constants::TRIBUTE_END) { // Tribute + else if (serverSlot >= EQEmu::constants::TRIBUTE_BEGIN && serverSlot <= EQEmu::constants::TRIBUTE_END) { // Tribute RoF2Slot.Type = inventory::TypeTribute; - RoF2Slot.Slot = serverSlot - EQEmu::Constants::TRIBUTE_BEGIN; + RoF2Slot.Slot = serverSlot - EQEmu::constants::TRIBUTE_BEGIN; } - else if (serverSlot >= EQEmu::Constants::BANK_BEGIN && serverSlot <= EQEmu::Constants::BANK_BAGS_END) { + else if (serverSlot >= EQEmu::constants::BANK_BEGIN && serverSlot <= EQEmu::constants::BANK_BAGS_END) { RoF2Slot.Type = inventory::TypeBank; - TempSlot = serverSlot - EQEmu::Constants::BANK_BEGIN; + TempSlot = serverSlot - EQEmu::constants::BANK_BEGIN; RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoF2Slot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.Sub = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EQEmu::Constants::SHARED_BANK_BEGIN && serverSlot <= EQEmu::Constants::SHARED_BANK_BAGS_END) { + else if (serverSlot >= EQEmu::constants::SHARED_BANK_BEGIN && serverSlot <= EQEmu::constants::SHARED_BANK_BAGS_END) { RoF2Slot.Type = inventory::TypeSharedBank; - TempSlot = serverSlot - EQEmu::Constants::SHARED_BANK_BEGIN; + TempSlot = serverSlot - EQEmu::constants::SHARED_BANK_BEGIN; RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoF2Slot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.Sub = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EQEmu::Constants::TRADE_BEGIN && serverSlot <= EQEmu::Constants::TRADE_BAGS_END) { + else if (serverSlot >= EQEmu::constants::TRADE_BEGIN && serverSlot <= EQEmu::constants::TRADE_BAGS_END) { RoF2Slot.Type = inventory::TypeTrade; - TempSlot = serverSlot - EQEmu::Constants::TRADE_BEGIN; + TempSlot = serverSlot - EQEmu::constants::TRADE_BEGIN; RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { - RoF2Slot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.Sub = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); } /* @@ -6116,13 +6116,13 @@ namespace RoF2 */ } - else if (serverSlot >= EQEmu::Constants::WORLD_BEGIN && serverSlot <= EQEmu::Constants::WORLD_END) { + else if (serverSlot >= EQEmu::constants::WORLD_BEGIN && serverSlot <= EQEmu::constants::WORLD_END) { RoF2Slot.Type = inventory::TypeWorld; - TempSlot = serverSlot - EQEmu::Constants::WORLD_BEGIN; + TempSlot = serverSlot - EQEmu::constants::WORLD_BEGIN; RoF2Slot.Slot = TempSlot; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoF2Slot.Type, RoF2Slot.Unknown02, RoF2Slot.Slot, RoF2Slot.Sub, RoF2Slot.Aug, RoF2Slot.Unknown01); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoF2Slot.Type, RoF2Slot.Unknown02, RoF2Slot.Slot, RoF2Slot.SubIndex, RoF2Slot.AugIndex, RoF2Slot.Unknown01); return RoF2Slot; } @@ -6131,8 +6131,8 @@ namespace RoF2 { structs::TypelessInventorySlot_Struct RoF2Slot; RoF2Slot.Slot = INVALID_INDEX; - RoF2Slot.Sub = INVALID_INDEX; - RoF2Slot.Aug = INVALID_INDEX; + RoF2Slot.SubIndex = INVALID_INDEX; + RoF2Slot.AugIndex = INVALID_INDEX; RoF2Slot.Unknown01 = NOT_USED; uint32 TempSlot = 0; @@ -6157,20 +6157,20 @@ namespace RoF2 }*/ } - else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) { + else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) { TempSlot = serverSlot - 1; - RoF2Slot.Slot = int(TempSlot / EQEmu::Constants::ITEM_CONTAINER_SIZE) - 2; - RoF2Slot.Sub = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::Constants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 2; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::constants::ITEM_CONTAINER_SIZE); } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoF2Slot.Slot, RoF2Slot.Sub, RoF2Slot.Aug, RoF2Slot.Unknown01); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoF2Slot.Slot, RoF2Slot.SubIndex, RoF2Slot.AugIndex, RoF2Slot.Unknown01); return RoF2Slot; } static inline uint32 ServerToRoF2CorpseSlot(uint32 serverCorpseSlot) { - return (serverCorpseSlot - EQEmu::Constants::CORPSE_BEGIN + 1); + return (serverCorpseSlot - EQEmu::constants::CORPSE_BEGIN + 1); } static inline uint32 RoF2ToServerSlot(structs::InventorySlot_Struct rof2Slot, ItemPacketType PacketType) @@ -6202,17 +6202,17 @@ namespace RoF2 else // Worn Slots TempSlot = rof2Slot.Slot; - if (rof2Slot.Sub >= SUB_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rof2Slot.Sub + 1; + if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; ServerSlot = TempSlot; } else if (rof2Slot.Type == inventory::TypeBank) { - TempSlot = EQEmu::Constants::BANK_BEGIN; + TempSlot = EQEmu::constants::BANK_BEGIN; - if (rof2Slot.Sub >= SUB_BEGIN) - TempSlot += ((rof2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rof2Slot.Sub + 1; + if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; else TempSlot += rof2Slot.Slot; @@ -6221,10 +6221,10 @@ namespace RoF2 } else if (rof2Slot.Type == inventory::TypeSharedBank) { - TempSlot = EQEmu::Constants::SHARED_BANK_BEGIN; + TempSlot = EQEmu::constants::SHARED_BANK_BEGIN; - if (rof2Slot.Sub >= SUB_BEGIN) - TempSlot += ((rof2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rof2Slot.Sub + 1; + if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; else TempSlot += rof2Slot.Slot; @@ -6233,10 +6233,10 @@ namespace RoF2 } else if (rof2Slot.Type == inventory::TypeTrade) { - TempSlot = EQEmu::Constants::TRADE_BEGIN; + TempSlot = EQEmu::constants::TRADE_BEGIN; - if (rof2Slot.Sub >= SUB_BEGIN) - TempSlot += ((rof2Slot.Slot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rof2Slot.Sub + 1; + if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; // OLD CODE: //TempSlot += 100 + (RoF2Slot.MainSlot * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot; @@ -6247,9 +6247,9 @@ namespace RoF2 } else if (rof2Slot.Type == inventory::TypeWorld) { - TempSlot = EQEmu::Constants::WORLD_BEGIN; + TempSlot = EQEmu::constants::WORLD_BEGIN; - if (rof2Slot.Slot >= SUB_BEGIN) + if (rof2Slot.Slot >= SUB_INDEX_BEGIN) TempSlot += rof2Slot.Slot; ServerSlot = TempSlot; @@ -6269,10 +6269,10 @@ namespace RoF2 } else if (rof2Slot.Type == inventory::TypeCorpse) { - ServerSlot = rof2Slot.Slot + EQEmu::Constants::CORPSE_BEGIN; + ServerSlot = rof2Slot.Slot + EQEmu::constants::CORPSE_BEGIN; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rof2Slot.Type, rof2Slot.Unknown02, rof2Slot.Slot, rof2Slot.Sub, rof2Slot.Aug, rof2Slot.Unknown01, ServerSlot); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rof2Slot.Type, rof2Slot.Unknown02, rof2Slot.Slot, rof2Slot.SubIndex, rof2Slot.AugIndex, rof2Slot.Unknown01, ServerSlot); return ServerSlot; } @@ -6301,25 +6301,25 @@ namespace RoF2 else TempSlot = rof2Slot.Slot; - if (rof2Slot.Sub >= SUB_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + rof2Slot.Sub + 1; + if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; ServerSlot = TempSlot; } - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rof2Slot.Slot, rof2Slot.Sub, rof2Slot.Aug, rof2Slot.Unknown01, ServerSlot); + Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rof2Slot.Slot, rof2Slot.SubIndex, rof2Slot.AugIndex, rof2Slot.Unknown01, ServerSlot); return ServerSlot; } static inline uint32 RoF2ToServerCorpseSlot(uint32 rof2CorpseSlot) { - return (rof2CorpseSlot + EQEmu::Constants::CORPSE_BEGIN - 1); + return (rof2CorpseSlot + EQEmu::constants::CORPSE_BEGIN - 1); } static inline void ServerToRoF2TextLink(std::string& rof2TextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { rof2TextLink = serverTextLink; return; } @@ -6328,7 +6328,7 @@ namespace RoF2 for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { rof2TextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -6351,7 +6351,7 @@ namespace RoF2 static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink) { - if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find('\x12') == std::string::npos)) { serverTextLink = rof2TextLink; return; } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index f7963ae54..18ab3c478 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -31,11 +31,11 @@ struct WorldObjectsSent_Struct { // New for RoF2 - Size: 12 struct InventorySlot_Struct { -/*000*/ int16 Type; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Delete Item = -1 +/*000*/ int16 Type; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Delete Item = -1 /*002*/ int16 Unknown02; /*004*/ int16 Slot; -/*006*/ int16 Sub; -/*008*/ int16 Aug; // Guessing - Seen 0xffff +/*006*/ int16 SubIndex; +/*008*/ int16 AugIndex; // Guessing - Seen 0xffff /*010*/ int16 Unknown01; // Normally 0 - Seen 13262 when deleting an item, but didn't match item ID /*012*/ }; @@ -45,8 +45,8 @@ struct InventorySlot_Struct struct TypelessInventorySlot_Struct { /*000*/ int16 Slot; -/*002*/ int16 Sub; -/*004*/ int16 Aug; +/*002*/ int16 SubIndex; +/*004*/ int16 AugIndex; /*006*/ int16 Unknown01; /*008*/ }; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index d4f7ce368..4c7ecc1c1 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -31,11 +31,11 @@ struct WorldObjectsSent_Struct { // New for RoF - Size: 12 struct InventorySlot_Struct { -/*000*/ int16 Type; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Delete Item = -1 +/*000*/ int16 Type; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Delete Item = -1 /*002*/ int16 Unknown02; /*004*/ int16 Slot; -/*006*/ int16 Sub; -/*008*/ int16 Aug; // Guessing - Seen 0xffff +/*006*/ int16 SubIndex; +/*008*/ int16 AugIndex; // Guessing - Seen 0xffff /*010*/ int16 Unknown01; // Normally 0 - Seen 13262 when deleting an item, but didn't match item ID /*012*/ }; @@ -45,8 +45,8 @@ struct InventorySlot_Struct struct TypelessInventorySlot_Struct { /*000*/ int16 Slot; -/*002*/ int16 Sub; -/*004*/ int16 Aug; +/*002*/ int16 SubIndex; +/*004*/ int16 AugIndex; /*006*/ int16 Unknown01; /*008*/ }; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 1d812927c..4f8eb936d 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1614,7 +1614,7 @@ namespace SoD // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -1623,7 +1623,7 @@ namespace SoD } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -1635,13 +1635,13 @@ namespace SoD // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -3934,7 +3934,7 @@ namespace SoD uint32 SubLengths[10]; - for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -3946,15 +3946,15 @@ namespace SoD iqbs.subitem_count++; - if (slot_id_in >= EQEmu::Constants::GENERAL_BEGIN && slot_id_in <= EQEmu::Constants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::constants::GENERAL_BEGIN && slot_id_in <= EQEmu::constants::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::Constants::BANK_BEGIN && slot_id_in <= EQEmu::Constants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::constants::BANK_BEGIN && slot_id_in <= EQEmu::constants::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::Constants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::constants::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -3995,11 +3995,11 @@ namespace SoD if (serverSlot >= SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots SoDSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) + else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) SoDSlot = serverSlot + 11; - else if (serverSlot >= EQEmu::Constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::BANK_BAGS_END) + else if (serverSlot >= EQEmu::constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::BANK_BAGS_END) SoDSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::SHARED_BANK_BAGS_END) + else if (serverSlot >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::SHARED_BANK_BAGS_END) SoDSlot = serverSlot + 1; else if (serverSlot == SlotPowerSource) SoDSlot = inventory::SlotPowerSource; @@ -4041,7 +4041,7 @@ namespace SoD static inline void ServerToSoDTextLink(std::string& sodTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { sodTextLink = serverTextLink; return; } @@ -4050,7 +4050,7 @@ namespace SoD for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { sodTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -4081,7 +4081,7 @@ namespace SoD static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink) { - if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find('\x12') == std::string::npos)) { serverTextLink = sodTextLink; return; } diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 2056b0798..2c4f08038 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1271,7 +1271,7 @@ namespace SoF // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -1280,7 +1280,7 @@ namespace SoF } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -1292,13 +1292,13 @@ namespace SoF // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -3256,7 +3256,7 @@ namespace SoF uint32 SubLengths[10]; - for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); @@ -3267,15 +3267,15 @@ namespace SoF iqbs.subitem_count++; - if (slot_id_in >= EQEmu::Constants::GENERAL_BEGIN && slot_id_in <= EQEmu::Constants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::constants::GENERAL_BEGIN && slot_id_in <= EQEmu::constants::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::Constants::BANK_BEGIN && slot_id_in <= EQEmu::Constants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::constants::BANK_BEGIN && slot_id_in <= EQEmu::constants::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::Constants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::constants::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -3314,11 +3314,11 @@ namespace SoF if (serverSlot >= SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots SoFSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) + else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) SoFSlot = serverSlot + 11; - else if (serverSlot >= EQEmu::Constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::BANK_BAGS_END) + else if (serverSlot >= EQEmu::constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::BANK_BAGS_END) SoFSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::SHARED_BANK_BAGS_END) + else if (serverSlot >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::SHARED_BANK_BAGS_END) SoFSlot = serverSlot + 1; else if (serverSlot == SlotPowerSource) SoFSlot = inventory::SlotPowerSource; @@ -3362,7 +3362,7 @@ namespace SoF static inline void ServerToSoFTextLink(std::string& sofTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { sofTextLink = serverTextLink; return; } @@ -3371,7 +3371,7 @@ namespace SoF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { sofTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -3402,7 +3402,7 @@ namespace SoF static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink) { - if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find('\x12') == std::string::npos)) { serverTextLink = sofTextLink; return; } diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 248ab1c85..59381bf3b 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -943,7 +943,7 @@ namespace Titanium // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -952,7 +952,7 @@ namespace Titanium } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -964,13 +964,13 @@ namespace Titanium // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -2198,7 +2198,7 @@ namespace Titanium static inline void ServerToTitaniumTextLink(std::string& titaniumTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { titaniumTextLink = serverTextLink; return; } @@ -2207,7 +2207,7 @@ namespace Titanium for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { titaniumTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -2238,7 +2238,7 @@ namespace Titanium static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink) { - if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find('\x12') == std::string::npos)) { serverTextLink = titaniumTextLink; return; } diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index b7d88394c..b667fcea7 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1878,7 +1878,7 @@ namespace UF // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::Constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -1887,7 +1887,7 @@ namespace UF } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::Constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -1899,13 +1899,13 @@ namespace UF // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::Constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::Constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -4263,7 +4263,7 @@ namespace UF uint32 SubLengths[10]; - for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -4275,15 +4275,15 @@ namespace UF iqbs.subitem_count++; - if (slot_id_in >= EQEmu::Constants::GENERAL_BEGIN && slot_id_in <= EQEmu::Constants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::constants::GENERAL_BEGIN && slot_id_in <= EQEmu::constants::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::Constants::BANK_BEGIN && slot_id_in <= EQEmu::Constants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::constants::BANK_BEGIN && slot_id_in <= EQEmu::constants::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::Constants::BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::Constants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::constants::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::Constants::SHARED_BANK_BEGIN) * EQEmu::Constants::ITEM_CONTAINER_SIZE) + EQEmu::Constants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -4324,11 +4324,11 @@ namespace UF if (serverSlot >= SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots UnderfootSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::Constants::CURSOR_BAG_END) + else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) UnderfootSlot = serverSlot + 11; - else if (serverSlot >= EQEmu::Constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::BANK_BAGS_END) + else if (serverSlot >= EQEmu::constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::BANK_BAGS_END) UnderfootSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::Constants::SHARED_BANK_BAGS_END) + else if (serverSlot >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::SHARED_BANK_BAGS_END) UnderfootSlot = serverSlot + 1; else if (serverSlot == SlotPowerSource) UnderfootSlot = inventory::SlotPowerSource; @@ -4372,7 +4372,7 @@ namespace UF static inline void ServerToUFTextLink(std::string& ufTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { ufTextLink = serverTextLink; return; } @@ -4381,7 +4381,7 @@ namespace UF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { ufTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -4412,7 +4412,7 @@ namespace UF static inline void UFToServerTextLink(std::string& serverTextLink, const std::string& ufTextLink) { - if ((EQEmu::Constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (ufTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (ufTextLink.find('\x12') == std::string::npos)) { serverTextLink = ufTextLink; return; } diff --git a/common/say_link.cpp b/common/say_link.cpp index 4be401e91..0f9fefaa5 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -25,7 +25,12 @@ #include "../zone/zonedb.h" -std::string EQEmu::SayLink::impl::GenerateLink() +EQEmu::saylink::SayLinkEngine::SayLinkEngine() +{ + Reset(); +} + +std::string EQEmu::saylink::SayLinkEngine::GenerateLink() { m_Link.clear(); m_LinkBody.clear(); @@ -34,7 +39,7 @@ std::string EQEmu::SayLink::impl::GenerateLink() generate_body(); generate_text(); - if ((m_LinkBody.length() == EQEmu::Constants::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) { + if ((m_LinkBody.length() == EQEmu::constants::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) { m_Link.push_back(0x12); m_Link.append(m_LinkBody); m_Link.append(m_LinkText); @@ -53,9 +58,9 @@ std::string EQEmu::SayLink::impl::GenerateLink() return m_Link; } -void EQEmu::SayLink::impl::Reset() +void EQEmu::saylink::SayLinkEngine::Reset() { - m_LinkType = LinkBlank; + m_LinkType = SayLinkBlank; m_ItemData = nullptr; m_LootData = nullptr; m_ItemInst = nullptr; @@ -80,7 +85,7 @@ void EQEmu::SayLink::impl::Reset() m_Error = false; } -void EQEmu::SayLink::impl::generate_body() +void EQEmu::saylink::SayLinkEngine::generate_body() { /* Current server mask: EQClientRoF2 @@ -96,16 +101,16 @@ void EQEmu::SayLink::impl::generate_body() const Item_Struct* item_data = nullptr; switch (m_LinkType) { - case LinkBlank: + case SayLinkBlank: break; - case LinkItemData: + case SayLinkItemData: if (m_ItemData == nullptr) { break; } m_LinkBodyStruct.item_id = m_ItemData->ID; m_LinkBodyStruct.evolve_group = m_ItemData->LoreGroup; // this probably won't work for all items //m_LinkBodyStruct.evolve_level = m_ItemData->EvolvingLevel; // TODO: add hash call break; - case LinkLootItem: + case SayLinkLootItem: if (m_LootData == nullptr) { break; } item_data = database.GetItem(m_LootData->item_id); if (item_data == nullptr) { break; } @@ -120,7 +125,7 @@ void EQEmu::SayLink::impl::generate_body() //m_LinkBodyStruct.evolve_level = item_data->EvolvingLevel; // TODO: add hash call break; - case LinkItemInst: + case SayLinkItemInst: if (m_ItemInst == nullptr) { break; } if (m_ItemInst->GetItem() == nullptr) { break; } m_LinkBodyStruct.item_id = m_ItemInst->GetItem()->ID; @@ -189,7 +194,7 @@ void EQEmu::SayLink::impl::generate_body() ); } -void EQEmu::SayLink::impl::generate_text() +void EQEmu::saylink::SayLinkEngine::generate_text() { if (m_ProxyText != nullptr) { m_LinkText = m_ProxyText; @@ -199,19 +204,19 @@ void EQEmu::SayLink::impl::generate_text() const Item_Struct* item_data = nullptr; switch (m_LinkType) { - case LinkBlank: + case SayLinkBlank: break; - case LinkItemData: + case SayLinkItemData: if (m_ItemData == nullptr) { break; } m_LinkText = m_ItemData->Name; return; - case LinkLootItem: + case SayLinkLootItem: if (m_LootData == nullptr) { break; } item_data = database.GetItem(m_LootData->item_id); if (item_data == nullptr) { break; } m_LinkText = item_data->Name; return; - case LinkItemInst: + case SayLinkItemInst: if (m_ItemInst == nullptr) { break; } if (m_ItemInst->GetItem() == nullptr) { break; } m_LinkText = m_ItemInst->GetItem()->Name; @@ -223,10 +228,10 @@ void EQEmu::SayLink::impl::generate_text() m_LinkText = "null"; } -bool EQEmu::SayLink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct, const std::string& say_link_body) +bool EQEmu::saylink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct, const std::string& say_link_body) { memset(&say_link_body_struct, 0, sizeof(say_link_body_struct)); - if (say_link_body.length() != EQEmu::Constants::TEXT_LINK_BODY_LENGTH) + if (say_link_body.length() != EQEmu::constants::TEXT_LINK_BODY_LENGTH) return false; say_link_body_struct.unknown_1 = (uint8)strtol(say_link_body.substr(0, 1).c_str(), nullptr, 16); @@ -246,7 +251,7 @@ bool EQEmu::SayLink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct return true; } -bool EQEmu::SayLink::GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct) +bool EQEmu::saylink::GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct) { say_link_body = StringFormat( "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X", @@ -265,7 +270,7 @@ bool EQEmu::SayLink::GenerateLinkBody(std::string& say_link_body, const SayLinkB (0xFFFFFFFF & say_link_body_struct.hash) ); - if (say_link_body.length() != EQEmu::Constants::TEXT_LINK_BODY_LENGTH) + if (say_link_body.length() != EQEmu::constants::TEXT_LINK_BODY_LENGTH) return false; return true; diff --git a/common/say_link.h b/common/say_link.h index 34ba19bf7..60c7d7db0 100644 --- a/common/say_link.h +++ b/common/say_link.h @@ -17,8 +17,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef SAY_LINK_H -#define SAY_LINK_H +#ifndef COMMON_SAY_LINK_H +#define COMMON_SAY_LINK_H #include "types.h" @@ -26,16 +26,13 @@ class ItemInst; -class Item_Struct; -class ServerLootItem_Struct; +struct Item_Struct; +struct ServerLootItem_Struct; namespace EQEmu { - class SayLink { - public: - enum Type { LinkBlank = 0, LinkItemData, LinkLootItem, LinkItemInst }; - + namespace saylink { // Current server mask: EQClientRoF2 struct SayLinkBody_Struct { uint8 unknown_1; /* %1X */ @@ -53,11 +50,18 @@ namespace EQEmu int hash; /* %08X */ }; - class impl { + class SayLinkEngine { public: - impl() { Reset(); } + enum SayLinkType { + SayLinkBlank = 0, + SayLinkItemData, + SayLinkLootItem, + SayLinkItemInst + }; - void SetLinkType(Type link_type) { m_LinkType = link_type; } + SayLinkEngine(); + + void SetLinkType(SayLinkType link_type) { m_LinkType = link_type; } void SetItemData(const Item_Struct* item_data) { m_ItemData = item_data; } void SetLootData(const ServerLootItem_Struct* loot_data) { m_LootData = loot_data; } void SetItemInst(const ItemInst* item_inst) { m_ItemInst = item_inst; } @@ -83,9 +87,9 @@ namespace EQEmu std::string GenerateLink(); bool LinkError() { return m_Error; } - std::string GetLink() { return m_Link; } // contains full string format: '/12x' '' '' '/12x' - std::string GetLinkBody() { return m_LinkBody; } // contains string format: '' - std::string GetLinkText() { return m_LinkText; } // contains string format: '' + std::string Link() { return m_Link; } // contains full string format: '/12x' '' '' '/12x' + std::string LinkBody() { return m_LinkBody; } // contains string format: '' + std::string LinkText() { return m_LinkText; } // contains string format: '' void Reset(); @@ -120,11 +124,9 @@ namespace EQEmu bool m_Error; }; - - - static bool DegenerateLinkBody(SayLinkBody_Struct& say_Link_body_struct, const std::string& say_link_body); - static bool GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct); - }; + bool DegenerateLinkBody(SayLinkBody_Struct& say_Link_body_struct, const std::string& say_link_body); + bool GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct); + } } -#endif /* SAY_LINK_H */ +#endif /* COMMON_SAY_LINK_H */ diff --git a/common/shareddb.cpp b/common/shareddb.cpp index e9536d9a3..16f8096b8 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -105,7 +105,7 @@ bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iter "AND ((slotid >= 8000 AND slotid <= 8999) " "OR slotid = %i OR (slotid >= %i AND slotid <= %i) )", char_id, SlotCursor, - EQEmu::Constants::CURSOR_BAG_BEGIN, EQEmu::Constants::CURSOR_BAG_END); + EQEmu::constants::CURSOR_BAG_BEGIN, EQEmu::constants::CURSOR_BAG_END); auto results = QueryDatabase(query); if (!results.Success()) { std::cout << "Clearing cursor failed: " << results.ErrorMessage() << std::endl; @@ -161,10 +161,10 @@ bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const Ite bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 slot_id) { //never save tribute slots: - if (slot_id >= EQEmu::Constants::TRIBUTE_BEGIN && slot_id <= EQEmu::Constants::TRIBUTE_END) + if (slot_id >= EQEmu::constants::TRIBUTE_BEGIN && slot_id <= EQEmu::constants::TRIBUTE_END) return true; - if (slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { + if (slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { // Shared bank inventory if (!inst) { return DeleteSharedBankSlot(char_id, slot_id); @@ -191,9 +191,9 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 s bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer - uint32 augslot[EQEmu::Constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; + uint32 augslot[EQEmu::constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; if (inst->IsType(ItemClassCommon)) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { ItemInst *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM; } @@ -223,7 +223,7 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) - for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::Constants::ITEM_CONTAINER_SIZE; idx++) { + for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::constants::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = inst->GetItem(idx); SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); } @@ -238,9 +238,9 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer - uint32 augslot[EQEmu::Constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; + uint32 augslot[EQEmu::constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; if (inst->IsType(ItemClassCommon)) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { ItemInst *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM; } @@ -269,7 +269,7 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) { // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) - for (uint8 idx = SUB_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::Constants::ITEM_CONTAINER_SIZE; idx++) { + for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::constants::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = inst->GetItem(idx); SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); } @@ -295,7 +295,7 @@ bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id) { if (!Inventory::SupportsContainers(slot_id)) return true; - int16 base_slot_id = Inventory::CalcSlotId(slot_id, SUB_BEGIN); + int16 base_slot_id = Inventory::CalcSlotId(slot_id, SUB_INDEX_BEGIN); query = StringFormat("DELETE FROM inventory WHERE charid = %i AND slotid >= %i AND slotid < %i", char_id, base_slot_id, (base_slot_id+10)); results = QueryDatabase(query); @@ -321,7 +321,7 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) { if (!Inventory::SupportsContainers(slot_id)) return true; - int16 base_slot_id = Inventory::CalcSlotId(slot_id, SUB_BEGIN); + int16 base_slot_id = Inventory::CalcSlotId(slot_id, SUB_INDEX_BEGIN); query = StringFormat("DELETE FROM sharedbank WHERE acctid = %i " "AND slotid >= %i AND slotid < %i", account_id, base_slot_id, (base_slot_id+10)); @@ -427,7 +427,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) uint32 item_id = (uint32)atoi(row[1]); int8 charges = (int8)atoi(row[2]); - uint32 aug[EQEmu::Constants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::constants::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoi(row[3]); aug[1] = (uint32)atoi(row[4]); aug[2] = (uint32)atoi(row[5]); @@ -448,7 +448,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) ItemInst *inst = CreateBaseItem(item, charges); if (inst && item->ItemClass == ItemClassCommon) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } @@ -522,7 +522,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) uint16 charges = atoi(row[2]); uint32 color = atoul(row[3]); - uint32 aug[EQEmu::Constants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::constants::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoul(row[4]); aug[1] = (uint32)atoul(row[5]); @@ -584,7 +584,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) inst->SetOrnamentHeroModel(ornament_hero_model); if (instnodrop || - (((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::Constants::EQUIPMENT_END) || + (((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::constants::EQUIPMENT_END) || slot_id == SlotPowerSource) && inst->GetItem()->Attuneable)) inst->SetAttuned(true); @@ -608,7 +608,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) } if (item->ItemClass == ItemClassCommon) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } @@ -665,7 +665,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) int8 charges = atoi(row[2]); uint32 color = atoul(row[3]); - uint32 aug[EQEmu::Constants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::constants::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoi(row[4]); aug[1] = (uint32)atoi(row[5]); aug[2] = (uint32)atoi(row[6]); @@ -726,7 +726,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) inst->SetCharges(charges); if (item->ItemClass == ItemClassCommon) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } diff --git a/world/client.cpp b/world/client.cpp index 836b4c45b..66b66169f 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -211,9 +211,9 @@ void Client::SendMaxCharCreate() { auto outapp = new EQApplicationPacket(OP_SendMaxCharacters, sizeof(MaxCharacters_Struct)); MaxCharacters_Struct* mc = (MaxCharacters_Struct*)outapp->pBuffer; - mc->max_chars = EQEmu::Limits::CharacterCreationLimit(m_ClientVersion); - if (mc->max_chars > EQEmu::Constants::CHARACTER_CREATION_LIMIT) - mc->max_chars = EQEmu::Constants::CHARACTER_CREATION_LIMIT; + mc->max_chars = EQEmu::limits::CharacterCreationLimit(m_ClientVersion); + if (mc->max_chars > EQEmu::constants::CHARACTER_CREATION_LIMIT) + mc->max_chars = EQEmu::constants::CHARACTER_CREATION_LIMIT; QueuePacket(outapp); safe_delete(outapp); @@ -746,8 +746,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { // This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above) // (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration) if (!pZoning) { - size_t character_limit = EQEmu::Limits::CharacterCreationLimit(eqs->GetClientVersion()); - if (character_limit > EQEmu::Constants::CHARACTER_CREATION_LIMIT) { character_limit = EQEmu::Constants::CHARACTER_CREATION_LIMIT; } + size_t character_limit = EQEmu::limits::CharacterCreationLimit(eqs->GetClientVersion()); + if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT) { character_limit = EQEmu::constants::CHARACTER_CREATION_LIMIT; } if (eqs->GetClientVersion() == ClientVersion::Titanium) { character_limit = 8; } std::string tgh_query = StringFormat( diff --git a/world/worlddb.cpp b/world/worlddb.cpp index cd73d9c7c..af8d20eed 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -37,11 +37,11 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou { /* Set Character Creation Limit */ ClientVersion client_version = ClientVersionFromBit(clientVersionBit); - size_t character_limit = EQEmu::Limits::CharacterCreationLimit(client_version); + size_t character_limit = EQEmu::limits::CharacterCreationLimit(client_version); // Validate against absolute server max - if (character_limit > EQEmu::Constants::CHARACTER_CREATION_LIMIT) - character_limit = EQEmu::Constants::CHARACTER_CREATION_LIMIT; + if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT) + character_limit = EQEmu::constants::CHARACTER_CREATION_LIMIT; // Force Titanium clients to use '8' if (client_version == ClientVersion::Titanium) diff --git a/zone/aa.cpp b/zone/aa.cpp index 9301f240a..ec72cd707 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -418,7 +418,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) //gear stuff, need to make sure there's //no situation where this stuff can be duped - for (int x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::EQUIPMENT_END; x++) // (< 21) added MainAmmo + for (int x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::EQUIPMENT_END; x++) // (< 21) added MainAmmo { uint32 sitem = 0; sitem = CorpseToUse->GetWornItem(x); diff --git a/zone/attack.cpp b/zone/attack.cpp index d831631c6..ca87d955a 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3642,7 +3642,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on proced = false; if (!proced && inst) { - for (int r = 0; r < EQEmu::Constants::ITEM_COMMON_SIZE; r++) { + for (int r = 0; r < EQEmu::constants::ITEM_COMMON_SIZE; r++) { const ItemInst *aug_i = inst->GetAugment(r); if (!aug_i) // no aug, try next slot! continue; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 57fc3da48..642cc612b 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -171,8 +171,8 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { } //tribute items - for (i = 0; i < EQEmu::Constants::TRIBUTE_SIZE; i++) { - const ItemInst* inst = m_inv[EQEmu::Constants::TRIBUTE_BEGIN + i]; + for (i = 0; i < EQEmu::constants::TRIBUTE_SIZE; i++) { + const ItemInst* inst = m_inv[EQEmu::constants::TRIBUTE_BEGIN + i]; if(inst == 0) continue; AddItemBonuses(inst, newbon, false, true); @@ -526,7 +526,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu } if (!isAug) { - for (int i = 0; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) + for (int i = 0; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) AddItemBonuses(inst->GetAugment(i), newbon, true, false, rec_level, ammo_slot_item); } } @@ -564,7 +564,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool if (!isAug) { int i; - for (i = 0; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { + for (i = 0; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { AdditiveWornBonuses(inst->GetAugment(i),newbon,true); } } @@ -575,7 +575,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { bool food = false; bool drink = false; - for (i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_BAGS_BEGIN; i++) + for (i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_BAGS_BEGIN; i++) { if (food && drink) break; @@ -591,7 +591,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { AddItemBonuses(inst, newbon); } } - for (i = EQEmu::Constants::GENERAL_BAGS_BEGIN; i <= EQEmu::Constants::GENERAL_BAGS_END; i++) + for (i = EQEmu::constants::GENERAL_BAGS_BEGIN; i <= EQEmu::constants::GENERAL_BAGS_END; i++) { if (food && drink) break; @@ -3200,7 +3200,7 @@ void NPC::CalcItemBonuses(StatBonuses *newbon) { if(newbon){ - for (int i = 0; i < EQEmu::Constants::EQUIPMENT_SIZE; i++){ + for (int i = 0; i < EQEmu::constants::EQUIPMENT_SIZE; i++){ const Item_Struct *cur = database.GetItem(equipment[i]); if(cur){ //basic stats @@ -3278,18 +3278,18 @@ void Client::CalcItemScale() { bool changed = false; // MainAmmo excluded in helper function below - if (CalcItemScale(EQEmu::Constants::EQUIPMENT_BEGIN, EQEmu::Constants::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) + if (CalcItemScale(EQEmu::constants::EQUIPMENT_BEGIN, EQEmu::constants::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) changed = true; - if (CalcItemScale(EQEmu::Constants::GENERAL_BEGIN, EQEmu::Constants::GENERAL_END)) // original coding excluded MainCursor (< 30) + if (CalcItemScale(EQEmu::constants::GENERAL_BEGIN, EQEmu::constants::GENERAL_END)) // original coding excluded MainCursor (< 30) changed = true; // I excluded cursor bag slots here because cursor was excluded above..if this is incorrect, change 'slot_y' here to CURSOR_BAG_END // and 'slot_y' above to CURSOR from GENERAL_END above - or however it is supposed to be... - if (CalcItemScale(EQEmu::Constants::GENERAL_BAGS_BEGIN, EQEmu::Constants::GENERAL_BAGS_END)) // (< 341) + if (CalcItemScale(EQEmu::constants::GENERAL_BAGS_BEGIN, EQEmu::constants::GENERAL_BAGS_END)) // (< 341) changed = true; - if (CalcItemScale(EQEmu::Constants::TRIBUTE_BEGIN, EQEmu::Constants::TRIBUTE_END)) // (< 405) + if (CalcItemScale(EQEmu::constants::TRIBUTE_BEGIN, EQEmu::constants::TRIBUTE_END)) // (< 405) changed = true; //Power Source Slot @@ -3320,7 +3320,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) - if (i >= EQEmu::Constants::GENERAL_BAGS_BEGIN && i <= EQEmu::Constants::GENERAL_BAGS_END) { + if (i >= EQEmu::constants::GENERAL_BAGS_BEGIN && i <= EQEmu::constants::GENERAL_BAGS_END) { ItemInst* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; @@ -3340,7 +3340,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { } //iterate all augments - for (int x = AUG_BEGIN; x < EQEmu::Constants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_INDEX_BEGIN; x < EQEmu::constants::ITEM_COMMON_SIZE; ++x) { ItemInst * a_inst = inst->GetAugment(x); if(!a_inst) @@ -3372,18 +3372,18 @@ void Client::DoItemEnterZone() { bool changed = false; // MainAmmo excluded in helper function below - if (DoItemEnterZone(EQEmu::Constants::EQUIPMENT_BEGIN, EQEmu::Constants::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) + if (DoItemEnterZone(EQEmu::constants::EQUIPMENT_BEGIN, EQEmu::constants::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) changed = true; - if (DoItemEnterZone(EQEmu::Constants::GENERAL_BEGIN, EQEmu::Constants::GENERAL_END)) // original coding excluded MainCursor (< 30) + if (DoItemEnterZone(EQEmu::constants::GENERAL_BEGIN, EQEmu::constants::GENERAL_END)) // original coding excluded MainCursor (< 30) changed = true; // I excluded cursor bag slots here because cursor was excluded above..if this is incorrect, change 'slot_y' here to CURSOR_BAG_END // and 'slot_y' above to CURSOR from GENERAL_END above - or however it is supposed to be... - if (DoItemEnterZone(EQEmu::Constants::GENERAL_BAGS_BEGIN, EQEmu::Constants::GENERAL_BAGS_END)) // (< 341) + if (DoItemEnterZone(EQEmu::constants::GENERAL_BAGS_BEGIN, EQEmu::constants::GENERAL_BAGS_END)) // (< 341) changed = true; - if (DoItemEnterZone(EQEmu::Constants::TRIBUTE_BEGIN, EQEmu::Constants::TRIBUTE_END)) // (< 405) + if (DoItemEnterZone(EQEmu::constants::TRIBUTE_BEGIN, EQEmu::constants::TRIBUTE_END)) // (< 405) changed = true; //Power Source Slot @@ -3413,7 +3413,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) - if (i >= EQEmu::Constants::GENERAL_BAGS_BEGIN && i <= EQEmu::Constants::GENERAL_BAGS_END) { + if (i >= EQEmu::constants::GENERAL_BAGS_BEGIN && i <= EQEmu::constants::GENERAL_BAGS_END) { ItemInst* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; @@ -3443,7 +3443,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { } //iterate all augments - for (int x = AUG_BEGIN; x < EQEmu::Constants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_INDEX_BEGIN; x < EQEmu::constants::ITEM_COMMON_SIZE; ++x) { ItemInst *a_inst = inst->GetAugment(x); if(!a_inst) diff --git a/zone/bot.cpp b/zone/bot.cpp index f3344bdac..e358d04c8 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -93,7 +93,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm timers[i] = 0; strcpy(this->name, this->GetCleanName()); - memset(&m_Light, 0, sizeof(EQEmu::LightSource::impl)); + memset(&m_Light, 0, sizeof(EQEmu::lightsource::LightSourceProfile)); memset(&_botInspectMessage, 0, sizeof(InspectMessage_Struct)); } @@ -1722,8 +1722,8 @@ bool Bot::LoadPet() if (!botdb.LoadPetBuffs(GetBotID(), pet_buffs)) bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetBuffs(), GetCleanName()); - uint32 pet_items[EQEmu::Constants::EQUIPMENT_SIZE]; - memset(pet_items, 0, (sizeof(uint32) * EQEmu::Constants::EQUIPMENT_SIZE)); + uint32 pet_items[EQEmu::constants::EQUIPMENT_SIZE]; + memset(pet_items, 0, (sizeof(uint32) * EQEmu::constants::EQUIPMENT_SIZE)); if (!botdb.LoadPetItems(GetBotID(), pet_items)) bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetItems(), GetCleanName()); @@ -1750,11 +1750,11 @@ bool Bot::SavePet() char* pet_name = new char[64]; SpellBuff_Struct pet_buffs[BUFF_COUNT]; - uint32 pet_items[EQEmu::Constants::EQUIPMENT_SIZE]; + uint32 pet_items[EQEmu::constants::EQUIPMENT_SIZE]; memset(pet_name, 0, 64); memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * BUFF_COUNT)); - memset(pet_items, 0, (sizeof(uint32) * EQEmu::Constants::EQUIPMENT_SIZE)); + memset(pet_items, 0, (sizeof(uint32) * EQEmu::constants::EQUIPMENT_SIZE)); pet_inst->GetPetState(pet_buffs, pet_items, pet_name); @@ -2121,7 +2121,7 @@ void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) break; } - if (item_slot >= EQEmu::Constants::EQUIPMENT_BEGIN){ + if (item_slot >= EQEmu::constants::EQUIPMENT_BEGIN){ const ItemInst* inst = GetBotItem(item_slot); const Item_Struct* botweapon = 0; if(inst) @@ -2878,7 +2878,7 @@ void Bot::Spawn(Client* botCharacterOwner) { // I re-enabled this until I can sort it out uint32 itemID = 0; uint8 materialFromSlot = 0xFF; - for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; ++i) { + for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; ++i) { itemID = GetBotItemBySlot(i); if(itemID != 0) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); @@ -3361,7 +3361,7 @@ void Bot::FinishTrade(Client* client, BotTradeType tradeType) { if(tradeType == BotTradeClientNormal) { // Items being traded are found in the normal trade window used to trade between a Client and a Client or NPC // Items in this mode are found in slot ids 3000 thru 3003 - thought bots used the full 8-slot window..? - PerformTradeWithClient(EQEmu::Constants::TRADE_BEGIN, EQEmu::Constants::TRADE_END, client); // {3000..3007} + PerformTradeWithClient(EQEmu::constants::TRADE_BEGIN, EQEmu::constants::TRADE_END, client); // {3000..3007} } else if(tradeType == BotTradeClientNoDropNoTrade) { // Items being traded are found on the Client's cursor slot, slot id 30. This item can be either a single item or it can be a bag. @@ -3378,7 +3378,7 @@ void Bot::FinishTrade(Client* client, BotTradeType tradeType) { void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client) { if(client) { // TODO: Figure out what the actual max slot id is - const int MAX_SLOT_ID = EQEmu::Constants::TRADE_BAGS_END; // was the old incorrect 3179.. + const int MAX_SLOT_ID = EQEmu::constants::TRADE_BAGS_END; // was the old incorrect 3179.. uint32 items[MAX_SLOT_ID] = {0}; uint8 charges[MAX_SLOT_ID] = {0}; bool botCanWear[MAX_SLOT_ID] = {0}; @@ -3403,7 +3403,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli std::string TempErrorMessage; const Item_Struct* mWeaponItem = inst->GetItem(); bool failedLoreCheck = false; - for (int m = AUG_BEGIN; m < EQEmu::Constants::ITEM_COMMON_SIZE; ++m) { + for (int m = AUG_INDEX_BEGIN; m < EQEmu::constants::ITEM_COMMON_SIZE; ++m) { ItemInst *itm = inst->GetAugment(m); if(itm) { @@ -3423,12 +3423,12 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli botCanWear[i] = BotCanWear; ItemInst* swap_item = nullptr; - const char* equipped[EQEmu::Constants::EQUIPMENT_SIZE + 1] = { "Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", + const char* equipped[EQEmu::constants::EQUIPMENT_SIZE + 1] = { "Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; bool success = false; int how_many_slots = 0; - for (int j = EQEmu::Constants::EQUIPMENT_BEGIN; j <= (EQEmu::Constants::EQUIPMENT_END + 1); ++j) { + for (int j = EQEmu::constants::EQUIPMENT_BEGIN; j <= (EQEmu::constants::EQUIPMENT_END + 1); ++j) { if((mWeaponItem->Slots & (1 << j))) { if (j == 22) j = 9999; @@ -3489,14 +3489,14 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } if(!success) { - for (int j = EQEmu::Constants::EQUIPMENT_BEGIN; j <= (EQEmu::Constants::EQUIPMENT_END + 1); ++j) { + for (int j = EQEmu::constants::EQUIPMENT_BEGIN; j <= (EQEmu::constants::EQUIPMENT_END + 1); ++j) { if((mWeaponItem->Slots & (1 << j))) { if (j == 22) j = 9999; swap_item = GetBotItem(j); failedLoreCheck = false; - for (int k = AUG_BEGIN; k < EQEmu::Constants::ITEM_COMMON_SIZE; ++k) { + for (int k = AUG_INDEX_BEGIN; k < EQEmu::constants::ITEM_COMMON_SIZE; ++k) { ItemInst *itm = swap_item->GetAugment(k); if(itm) { @@ -4294,7 +4294,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { int32 focus_max = 0; int32 focus_max_real = 0; //item focus - for (int x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::EQUIPMENT_END; x++) { + for (int x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::EQUIPMENT_END; x++) { TempItem = nullptr; ItemInst* ins = GetBotItem(x); if (!ins) @@ -4319,7 +4319,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { } } - for (int y = AUG_BEGIN; y < EQEmu::Constants::ITEM_COMMON_SIZE; ++y) { + for (int y = AUG_INDEX_BEGIN; y < EQEmu::constants::ITEM_COMMON_SIZE; ++y) { ItemInst *aug = nullptr; aug = ins->GetAugment(y); if(aug) { @@ -4999,7 +4999,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { if(botweaponInst) { primaryweapondamage = GetWeaponDamage(other, botweaponInst); backstab_dmg = botweaponInst->GetItem()->BackstabDmg; - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) { ItemInst *aug = botweaponInst->GetAugment(i); if(aug) backstab_dmg += aug->GetItem()->BackstabDmg; @@ -5374,7 +5374,7 @@ void Bot::EquipBot(std::string* errorMessage) { GetBotItems(m_inv, errorMessage); const ItemInst* inst = 0; const Item_Struct* item = 0; - for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; ++i) { + for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { item = inst->GetItem(); @@ -7192,7 +7192,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { // Modded to display power source items (will only show up on SoF+ client inspect windows though.) // I don't think bots are currently coded to use them..but, you'll have to use '#bot inventory list' // to see them on a Titanium client when/if they are activated. - for (int16 L = EQEmu::Constants::EQUIPMENT_BEGIN; L <= SlotWaist; L++) { + for (int16 L = EQEmu::constants::EQUIPMENT_BEGIN; L <= SlotWaist; L++) { inst = inspectedBot->GetBotItem(L); if(inst) { @@ -7240,7 +7240,7 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) { const Item_Struct* itemtmp = 0; - for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= (EQEmu::Constants::EQUIPMENT_END + 1); ++i) { + for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= (EQEmu::constants::EQUIPMENT_END + 1); ++i) { const ItemInst* item = GetBotItem((i == 22 ? 9999 : i)); if(item) { AddItemBonuses(item, newbon); @@ -7553,7 +7553,7 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, if (!isAug) { - for (int i = 0; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) + for (int i = 0; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) AddItemBonuses(inst->GetAugment(i),newbon,true, false, rec_level); } @@ -8047,7 +8047,7 @@ int Bot::GetRawACNoShield(int &shield_ac) { if(inst->GetItem()->ItemType == ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; - for (uint8 i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { + for (uint8 i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { if(inst->GetAugment(i)) { ac -= inst->GetAugment(i)->GetItem()->AC; shield_ac += inst->GetAugment(i)->GetItem()->AC; @@ -8062,7 +8062,7 @@ uint32 Bot::CalcCurrentWeight() { const Item_Struct* TempItem = 0; ItemInst* inst; uint32 Total = 0; - for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; ++i) { + for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { TempItem = inst->GetItem(); @@ -8469,8 +8469,8 @@ std::string Bot::CreateSayLink(Client* c, const char* message, const char* name) uint32 saylink_id = database.LoadSaylinkID(escaped_string); safe_delete_array(escaped_string); - EQEmu::SayLink::impl linker; - linker.SetLinkType(EQEmu::SayLink::LinkItemData); + EQEmu::saylink::SayLinkEngine linker; + linker.SetLinkType(linker.SayLinkItemData); linker.SetProxyItemID(SAYLINK_ITEM_ID); linker.SetProxyAugment1ID(saylink_id); linker.SetProxyText(name); diff --git a/zone/bot.h b/zone/bot.h index 34791b5a4..a64b44a5e 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -77,9 +77,9 @@ static const std::string bot_stance_name[BOT_STANCE_COUNT] = { static const char* GetBotStanceName(int stance_id) { return bot_stance_name[VALIDBOTSTANCE(stance_id)].c_str(); } -#define VALIDBOTEQUIPSLOT(x) ((x >= EQEmu::Constants::EQUIPMENT_BEGIN && x <= EQEmu::Constants::EQUIPMENT_END) ? (x) : ((x == SlotPowerSource) ? (22) : (23))) +#define VALIDBOTEQUIPSLOT(x) ((x >= EQEmu::constants::EQUIPMENT_BEGIN && x <= EQEmu::constants::EQUIPMENT_END) ? (x) : ((x == SlotPowerSource) ? (22) : (23))) -static std::string bot_equip_slot_name[EQEmu::Constants::EQUIPMENT_SIZE + 2] = +static std::string bot_equip_slot_name[EQEmu::constants::EQUIPMENT_SIZE + 2] = { "Charm", // MainCharm "Left Ear", // MainEar1 @@ -386,7 +386,7 @@ public: void BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true); void EquipBot(std::string* errorMessage); bool CheckLoreConflict(const Item_Struct* item); - virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); } + virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); } // Static Class Methods //static void DestroyBotRaidObjects(Client* client); // Can be removed after bot raids are dumped diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 0c1d6037b..8b9031ff4 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -2400,7 +2400,7 @@ namespace ActionableBots continue; mod_skill_value = base_skill_value; - for (int16 index = EQEmu::Constants::EQUIPMENT_BEGIN; index <= EQEmu::Constants::EQUIPMENT_END; ++index) { + for (int16 index = EQEmu::constants::EQUIPMENT_BEGIN; index <= EQEmu::constants::EQUIPMENT_END; ++index) { const ItemInst* indexed_item = bot_iter->GetBotItem(index); if (indexed_item && indexed_item->GetItem()->SkillModType == skill_type) mod_skill_value += (base_skill_value * (((float)indexed_item->GetItem()->SkillModValue) / 100.0f)); @@ -7066,11 +7066,11 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) bool is2Hweapon = false; std::string item_link; - EQEmu::SayLink::impl linker; - linker.SetLinkType(EQEmu::SayLink::LinkItemInst); + EQEmu::saylink::SayLinkEngine linker; + linker.SetLinkType(linker.SayLinkItemInst); uint32 inventory_count = 0; - for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= (EQEmu::Constants::EQUIPMENT_END + 1); ++i) { + for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= (EQEmu::constants::EQUIPMENT_END + 1); ++i) { if ((i == SlotSecondary) && is2Hweapon) continue; @@ -7126,7 +7126,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) } int slotId = atoi(sep->arg[1]); - if (!sep->IsNumber(1) || ((slotId > EQEmu::Constants::EQUIPMENT_END || slotId < EQEmu::Constants::EQUIPMENT_BEGIN) && slotId != SlotPowerSource)) { + if (!sep->IsNumber(1) || ((slotId > EQEmu::constants::EQUIPMENT_END || slotId < EQEmu::constants::EQUIPMENT_BEGIN) && slotId != SlotPowerSource)) { c->Message(m_fail, "Valid slots are 0-21 or 9999"); return; } @@ -7141,7 +7141,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) return; } - for (int m = AUG_BEGIN; m < EQEmu::Constants::ITEM_COMMON_SIZE; ++m) { + for (int m = AUG_INDEX_BEGIN; m < EQEmu::constants::ITEM_COMMON_SIZE; ++m) { if (!itminst) break; @@ -7233,7 +7233,7 @@ void bot_subcommand_inventory_window(Client *c, const Seperator *sep) //Client::TextLink linker; //linker.SetLinkType(linker.linkItemInst); - for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= (EQEmu::Constants::EQUIPMENT_END + 1); ++i) { + for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= (EQEmu::constants::EQUIPMENT_END + 1); ++i) { const Item_Struct* item = nullptr; const ItemInst* inst = my_bot->CastToBot()->GetBotItem(i == 22 ? SlotPowerSource : i); if (inst) diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 416e0c304..fc98fd768 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1058,7 +1058,7 @@ bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) for (auto row = results.begin(); row != results.end(); ++row) { int16 slot_id = atoi(row[0]); - if ((slot_id < EQEmu::Constants::EQUIPMENT_BEGIN || slot_id > EQEmu::Constants::EQUIPMENT_END) && slot_id != SlotPowerSource) + if ((slot_id < EQEmu::constants::EQUIPMENT_BEGIN || slot_id > EQEmu::constants::EQUIPMENT_END) && slot_id != SlotPowerSource) continue; uint32 item_id = atoi(row[1]); @@ -1091,7 +1091,7 @@ bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) if (item_inst->GetItem()->Attuneable) { if (atoi(row[4])) item_inst->SetAttuned(true); - else if (((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::Constants::EQUIPMENT_END) || slot_id == SlotPowerSource)) + else if (((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::constants::EQUIPMENT_END) || slot_id == SlotPowerSource)) item_inst->SetAttuned(true); } @@ -1159,7 +1159,7 @@ bool BotDatabase::LoadItemBySlot(Bot* bot_inst) bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint32& item_id) { - if (!bot_id || (slot_id > EQEmu::Constants::EQUIPMENT_END && slot_id != SlotPowerSource)) + if (!bot_id || (slot_id > EQEmu::constants::EQUIPMENT_END && slot_id != SlotPowerSource)) return false; query = StringFormat("SELECT `item_id` FROM `bot_inventories` WHERE `bot_id` = '%i' AND `slot_id` = '%i' LIMIT 1", bot_id, slot_id); @@ -1177,7 +1177,7 @@ bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const ItemInst* item_inst) { - if (!bot_inst || !bot_inst->GetBotID() || (slot_id > EQEmu::Constants::EQUIPMENT_END && slot_id != SlotPowerSource)) + if (!bot_inst || !bot_inst->GetBotID() || (slot_id > EQEmu::constants::EQUIPMENT_END && slot_id != SlotPowerSource)) return false; if (!DeleteItemBySlot(bot_inst->GetBotID(), slot_id)) @@ -1187,7 +1187,7 @@ bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const Item return true; uint32 augment_id[] = { 0, 0, 0, 0, 0, 0 }; - for (int augment_iter = 0; augment_iter < EQEmu::Constants::ITEM_COMMON_SIZE; ++augment_iter) + for (int augment_iter = 0; augment_iter < EQEmu::constants::ITEM_COMMON_SIZE; ++augment_iter) augment_id[augment_iter] = item_inst->GetAugmentItemID(augment_iter); query = StringFormat( @@ -1255,7 +1255,7 @@ bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const Item bool BotDatabase::DeleteItemBySlot(const uint32 bot_id, const uint32 slot_id) { - if (!bot_id || (slot_id > EQEmu::Constants::EQUIPMENT_END && slot_id != SlotPowerSource)) + if (!bot_id || (slot_id > EQEmu::constants::EQUIPMENT_END && slot_id != SlotPowerSource)) return false; query = StringFormat("DELETE FROM `bot_inventories` WHERE `bot_id` = '%u' AND `slot_id` = '%u'", bot_id, slot_id); @@ -1294,7 +1294,7 @@ bool BotDatabase::SaveEquipmentColor(const uint32 bot_id, const int16 slot_id, c return false; bool all_flag = (slot_id == -2); - if ((slot_id < EQEmu::Constants::EQUIPMENT_BEGIN || slot_id > EQEmu::Constants::EQUIPMENT_END) && slot_id != SlotPowerSource && !all_flag) + if ((slot_id < EQEmu::constants::EQUIPMENT_BEGIN || slot_id > EQEmu::constants::EQUIPMENT_END) && slot_id != SlotPowerSource && !all_flag) return false; std::string where_clause; @@ -1571,7 +1571,7 @@ bool BotDatabase::LoadPetItems(const uint32 bot_id, uint32* pet_items) return true; int item_index = 0; - for (auto row = results.begin(); row != results.end() && item_index < EQEmu::Constants::EQUIPMENT_SIZE; ++row) { + for (auto row = results.begin(); row != results.end() && item_index < EQEmu::constants::EQUIPMENT_SIZE; ++row) { pet_items[item_index] = atoi(row[0]); ++item_index; } @@ -1595,7 +1595,7 @@ bool BotDatabase::SavePetItems(const uint32 bot_id, const uint32* pet_items, boo if (!saved_pet_index) return true; - for (int item_index = 0; item_index < EQEmu::Constants::EQUIPMENT_SIZE; ++item_index) { + for (int item_index = 0; item_index < EQEmu::constants::EQUIPMENT_SIZE; ++item_index) { if (!pet_items[item_index]) continue; diff --git a/zone/client.cpp b/zone/client.cpp index 2097e8374..0be517343 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -5392,7 +5392,7 @@ bool Client::TryReward(uint32 claim_id) // save uint32 free_slot = 0xFFFFFFFF; - for (int i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; ++i) { + for (int i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; ++i) { ItemInst *item = GetInv().GetItem(i); if (!item) { free_slot = i; @@ -6307,7 +6307,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid made_npc->drakkin_details = GetDrakkinDetails(); made_npc->d_melee_texture1 = GetEquipmentMaterial(MaterialPrimary); made_npc->d_melee_texture2 = GetEquipmentMaterial(MaterialSecondary); - for (int i = EQEmu::Constants::MATERIAL_BEGIN; i <= EQEmu::Constants::MATERIAL_END; i++) { + for (int i = EQEmu::constants::MATERIAL_BEGIN; i <= EQEmu::constants::MATERIAL_END; i++) { made_npc->armor_tint[i] = GetEquipmentColor(i); } made_npc->loottable_id = 0; @@ -7583,7 +7583,7 @@ void Client::GarbleMessage(char *message, uint8 variance) for (size_t i = 0; i < strlen(message); i++) { // Client expects hex values inside of a text link body if (message[i] == delimiter) { - if (!(delimiter_count & 1)) { i += EQEmu::Constants::TEXT_LINK_BODY_LENGTH; } + if (!(delimiter_count & 1)) { i += EQEmu::constants::TEXT_LINK_BODY_LENGTH; } ++delimiter_count; continue; } @@ -8008,17 +8008,17 @@ void Client::TickItemCheck() if(zone->tick_items.empty()) { return; } //Scan equip slots for items - for (i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; i++) + for (i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; i++) { TryItemTick(i); } //Scan main inventory + cursor - for (i = EQEmu::Constants::GENERAL_BEGIN; i <= SlotCursor; i++) + for (i = EQEmu::constants::GENERAL_BEGIN; i <= SlotCursor; i++) { TryItemTick(i); } //Scan bags - for (i = EQEmu::Constants::GENERAL_BAGS_BEGIN; i <= EQEmu::Constants::CURSOR_BAG_END; i++) + for (i = EQEmu::constants::GENERAL_BAGS_BEGIN; i <= EQEmu::constants::CURSOR_BAG_END; i++) { TryItemTick(i); } @@ -8034,7 +8034,7 @@ void Client::TryItemTick(int slot) if(zone->tick_items.count(iid) > 0) { - if (GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EQEmu::Constants::EQUIPMENT_END)) + if (GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EQEmu::constants::EQUIPMENT_END)) { ItemInst* e_inst = (ItemInst*)inst; parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); @@ -8042,9 +8042,9 @@ void Client::TryItemTick(int slot) } //Only look at augs in main inventory - if (slot > EQEmu::Constants::EQUIPMENT_END) { return; } + if (slot > EQEmu::constants::EQUIPMENT_END) { return; } - for (int x = AUG_BEGIN; x < EQEmu::Constants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_INDEX_BEGIN; x < EQEmu::constants::ITEM_COMMON_SIZE; ++x) { ItemInst * a_inst = inst->GetAugment(x); if(!a_inst) { continue; } @@ -8065,17 +8065,17 @@ void Client::TryItemTick(int slot) void Client::ItemTimerCheck() { int i; - for (i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; i++) + for (i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; i++) { TryItemTimer(i); } - for (i = EQEmu::Constants::GENERAL_BEGIN; i <= SlotCursor; i++) + for (i = EQEmu::constants::GENERAL_BEGIN; i <= SlotCursor; i++) { TryItemTimer(i); } - for (i = EQEmu::Constants::GENERAL_BAGS_BEGIN; i <= EQEmu::Constants::CURSOR_BAG_END; i++) + for (i = EQEmu::constants::GENERAL_BAGS_BEGIN; i <= EQEmu::constants::CURSOR_BAG_END; i++) { TryItemTimer(i); } @@ -8097,11 +8097,11 @@ void Client::TryItemTimer(int slot) ++it_iter; } - if (slot > EQEmu::Constants::EQUIPMENT_END) { + if (slot > EQEmu::constants::EQUIPMENT_END) { return; } - for (int x = AUG_BEGIN; x < EQEmu::Constants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_INDEX_BEGIN; x < EQEmu::constants::ITEM_COMMON_SIZE; ++x) { ItemInst * a_inst = inst->GetAugment(x); if(!a_inst) { @@ -8389,12 +8389,12 @@ void Client::ShowNumHits() int Client::GetQuiverHaste(int delay) { const ItemInst *pi = nullptr; - for (int r = EQEmu::Constants::GENERAL_BEGIN; r <= EQEmu::Constants::GENERAL_END; r++) { + for (int r = EQEmu::constants::GENERAL_BEGIN; r <= EQEmu::constants::GENERAL_END; r++) { pi = GetInv().GetItem(r); if (pi && pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == BagTypeQuiver && pi->GetItem()->BagWR > 0) break; - if (r == EQEmu::Constants::GENERAL_END) + if (r == EQEmu::constants::GENERAL_END) // we will get here if we don't find a valid quiver return 0; } diff --git a/zone/client.h b/zone/client.h index 47c3a10ee..f556197a4 100644 --- a/zone/client.h +++ b/zone/client.h @@ -736,7 +736,7 @@ public: #endif uint32 GetEquipment(uint8 material_slot) const; // returns item id uint32 GetEquipmentColor(uint8 material_slot) const; - virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); } + virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); } inline bool AutoSplitEnabled() { return m_pp.autosplit != 0; } diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 76caa9942..2e2c1bf46 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -485,7 +485,7 @@ int32 Client::GetRawItemAC() { int32 Total = 0; // this skips MainAmmo..add an '=' conditional if that slot is required (original behavior) - for (int16 slot_id = EQEmu::Constants::EQUIPMENT_BEGIN; slot_id < EQEmu::Constants::EQUIPMENT_END; slot_id++) { + for (int16 slot_id = EQEmu::constants::EQUIPMENT_BEGIN; slot_id < EQEmu::constants::EQUIPMENT_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if (inst && inst->IsType(ItemClassCommon)) { Total += inst->GetItem()->AC; @@ -1306,7 +1306,7 @@ uint32 Client::CalcCurrentWeight() ItemInst* ins; uint32 Total = 0; int x; - for (x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= SlotCursor; x++) { // include cursor or not? + for (x = EQEmu::constants::EQUIPMENT_BEGIN; x <= SlotCursor; x++) { // include cursor or not? TempItem = 0; ins = GetInv().GetItem(x); if (ins) { @@ -1316,7 +1316,7 @@ uint32 Client::CalcCurrentWeight() Total += TempItem->Weight; } } - for (x = EQEmu::Constants::GENERAL_BAGS_BEGIN; x <= EQEmu::Constants::GENERAL_BAGS_END; x++) { // include cursor bags or not? + for (x = EQEmu::constants::GENERAL_BAGS_BEGIN; x <= EQEmu::constants::GENERAL_BAGS_END; x++) { // include cursor bags or not? int TmpWeight = 0; TempItem = 0; ins = GetInv().GetItem(x); @@ -1331,7 +1331,7 @@ uint32 Client::CalcCurrentWeight() // is this correct? or can we scan for the highest weight redux and use that? (need client verifications) int bagslot = SlotGeneral1; int reduction = 0; - for (int m = EQEmu::Constants::GENERAL_BAGS_BEGIN + 10; m <= EQEmu::Constants::GENERAL_BAGS_END; m += 10) { // include cursor bags or not? + for (int m = EQEmu::constants::GENERAL_BAGS_BEGIN + 10; m <= EQEmu::constants::GENERAL_BAGS_END; m += 10) { // include cursor bags or not? if (x >= m) { bagslot += 1; } @@ -1355,7 +1355,7 @@ uint32 Client::CalcCurrentWeight() This is the ONLY instance I have seen where the client is hard coded to particular Item IDs to set a certain property for an item. It is very odd. */ // SoD+ client has no weight for coin - if (EQEmu::Limits::CoinHasWeight(GetClientVersion())) { + if (EQEmu::limits::CoinHasWeight(GetClientVersion())) { Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4; } float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat; @@ -2210,7 +2210,7 @@ int Client::GetRawACNoShield(int &shield_ac) const if (inst->GetItem()->ItemType == ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; - for (uint8 i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { + for (uint8 i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { if (inst->GetAugment(i)) { ac -= inst->GetAugment(i)->GetItem()->AC; shield_ac += inst->GetAugment(i)->GetItem()->AC; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 561a0689c..1a44650ae 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1313,7 +1313,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) } /* Set item material tint */ - for (int i = EQEmu::Constants::MATERIAL_BEGIN; i <= EQEmu::Constants::MATERIAL_END; i++) + for (int i = EQEmu::constants::MATERIAL_BEGIN; i <= EQEmu::constants::MATERIAL_END; i++) { if (m_pp.item_tint[i].RGB.UseTint == 1 || m_pp.item_tint[i].RGB.UseTint == 255) { @@ -7994,7 +7994,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) const Item_Struct* item = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - for (int16 L = EQEmu::Constants::EQUIPMENT_BEGIN; L <= SlotWaist; L++) { + for (int16 L = EQEmu::constants::EQUIPMENT_BEGIN; L <= SlotWaist; L++) { const ItemInst* inst = GetInv().GetItem(L); item = inst ? inst->GetItem() : nullptr; @@ -8474,7 +8474,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) ItemInst* clickaug = 0; Item_Struct* augitem = 0; - for (r = 0; r < EQEmu::Constants::ITEM_COMMON_SIZE; r++) { + for (r = 0; r < EQEmu::constants::ITEM_COMMON_SIZE; r++) { const ItemInst* aug_i = inst->GetAugment(r); if (!aug_i) continue; @@ -9675,7 +9675,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer; if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id)) { - if (mi->from_slot != mi->to_slot && (mi->from_slot <= EQEmu::Constants::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) + if (mi->from_slot != mi->to_slot && (mi->from_slot <= EQEmu::constants::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) { char *detect = nullptr; const ItemInst *itm_from = GetInv().GetItem(mi->from_slot); @@ -9696,8 +9696,8 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) // Illegal bagslot usage checks. Currently, user only receives a message if this check is triggered. bool mi_hack = false; - if (mi->from_slot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && mi->from_slot <= EQEmu::Constants::CURSOR_BAG_END) { - if (mi->from_slot >= EQEmu::Constants::CURSOR_BAG_BEGIN) { mi_hack = true; } + if (mi->from_slot >= EQEmu::constants::GENERAL_BAGS_BEGIN && mi->from_slot <= EQEmu::constants::CURSOR_BAG_END) { + if (mi->from_slot >= EQEmu::constants::CURSOR_BAG_BEGIN) { mi_hack = true; } else { int16 from_parent = m_inv.CalcSlotId(mi->from_slot); if (!m_inv[from_parent]) { mi_hack = true; } @@ -9706,8 +9706,8 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) } } - if (mi->to_slot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && mi->to_slot <= EQEmu::Constants::CURSOR_BAG_END) { - if (mi->to_slot >= EQEmu::Constants::CURSOR_BAG_BEGIN) { mi_hack = true; } + if (mi->to_slot >= EQEmu::constants::GENERAL_BAGS_BEGIN && mi->to_slot <= EQEmu::constants::CURSOR_BAG_END) { + if (mi->to_slot >= EQEmu::constants::CURSOR_BAG_BEGIN) { mi_hack = true; } else { int16 to_parent = m_inv.CalcSlotId(mi->to_slot); if (!m_inv[to_parent]) { mi_hack = true; } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index f1509164c..2184b35ed 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -742,7 +742,7 @@ void Client::BulkSendInventoryItems() { // LINKDEAD TRADE ITEMS // Move trade slot items back into normal inventory..need them there now for the proceeding validity checks - for(slot_id = EQEmu::Constants::TRADE_BEGIN; slot_id <= EQEmu::Constants::TRADE_END; slot_id++) { + for(slot_id = EQEmu::constants::TRADE_BEGIN; slot_id <= EQEmu::constants::TRADE_END; slot_id++) { ItemInst* inst = m_inv.PopItem(slot_id); if(inst) { bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; @@ -790,7 +790,7 @@ void Client::BulkSendInventoryItems() { std::map::iterator itr; //Inventory items - for(slot_id = SLOT_BEGIN; slot_id < EQEmu::Constants::TYPE_POSSESSIONS_SIZE; slot_id++) { + for(slot_id = SLOT_BEGIN; slot_id < EQEmu::constants::TYPE_POSSESSIONS_SIZE; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if(inst) { std::string packet = inst->Serialize(slot_id); @@ -810,7 +810,7 @@ void Client::BulkSendInventoryItems() { } // Bank items - for(slot_id = EQEmu::Constants::BANK_BEGIN; slot_id <= EQEmu::Constants::BANK_END; slot_id++) { + for(slot_id = EQEmu::constants::BANK_BEGIN; slot_id <= EQEmu::constants::BANK_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if(inst) { std::string packet = inst->Serialize(slot_id); @@ -820,7 +820,7 @@ void Client::BulkSendInventoryItems() { } // Shared Bank items - for(slot_id = EQEmu::Constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::Constants::SHARED_BANK_END; slot_id++) { + for(slot_id = EQEmu::constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::constants::SHARED_BANK_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if(inst) { std::string packet = inst->Serialize(slot_id); @@ -851,14 +851,14 @@ void Client::BulkSendInventoryItems() if(deletenorent){//client was offline for more than 30 minutes, delete no rent items RemoveNoRent(); } - for (slot_id=EQEmu::Constants::POSSESSIONS_BEGIN; slot_id<=EQEmu::Constants::POSSESSIONS_END; slot_id++) { + for (slot_id=EQEmu::constants::POSSESSIONS_BEGIN; slot_id<=EQEmu::constants::POSSESSIONS_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if (inst){ SendItemPacket(slot_id, inst, ItemPacketCharInventory); } } // Bank items - for (slot_id=EQEmu::Constants::BANK_BEGIN; slot_id<=EQEmu::Constants::BANK_END; slot_id++) { // 2015... + for (slot_id=EQEmu::constants::BANK_BEGIN; slot_id<=EQEmu::constants::BANK_END; slot_id++) { // 2015... const ItemInst* inst = m_inv[slot_id]; if (inst){ SendItemPacket(slot_id, inst, ItemPacketCharInventory); @@ -866,7 +866,7 @@ void Client::BulkSendInventoryItems() } // Shared Bank items - for (slot_id=EQEmu::Constants::SHARED_BANK_BEGIN; slot_id<=EQEmu::Constants::SHARED_BANK_END; slot_id++) { + for (slot_id=EQEmu::constants::SHARED_BANK_BEGIN; slot_id<=EQEmu::constants::SHARED_BANK_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if (inst){ SendItemPacket(slot_id, inst, ItemPacketCharInventory); @@ -876,7 +876,7 @@ void Client::BulkSendInventoryItems() // LINKDEAD TRADE ITEMS // If player went LD during a trade, they have items in the trade inventory // slots. These items are now being put into their inventory (then queue up on cursor) - for (int16 trade_slot_id=EQEmu::Constants::TRADE_BEGIN; trade_slot_id<=EQEmu::Constants::TRADE_END; trade_slot_id++) { + for (int16 trade_slot_id=EQEmu::constants::TRADE_BEGIN; trade_slot_id<=EQEmu::constants::TRADE_END; trade_slot_id++) { const ItemInst* inst = m_inv[slot_id]; if (inst) { int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size); diff --git a/zone/command.cpp b/zone/command.cpp index 97b3ac980..530f3052a 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2413,14 +2413,14 @@ void command_texture(Client *c, const Seperator *sep) // Player Races Wear Armor, so Wearchange is sent instead int i; if (!c->GetTarget()) - for (i = EQEmu::Constants::MATERIAL_BEGIN; i <= EQEmu::Constants::MATERIAL_TINT_END; i++) + for (i = EQEmu::constants::MATERIAL_BEGIN; i <= EQEmu::constants::MATERIAL_TINT_END; i++) { c->SendTextureWC(i, texture); } else if ((c->GetTarget()->GetRace() > 0 && c->GetTarget()->GetRace() <= 12) || c->GetTarget()->GetRace() == 128 || c->GetTarget()->GetRace() == 130 || c->GetTarget()->GetRace() == 330 || c->GetTarget()->GetRace() == 522) { - for (i = EQEmu::Constants::MATERIAL_BEGIN; i <= EQEmu::Constants::MATERIAL_TINT_END; i++) + for (i = EQEmu::constants::MATERIAL_BEGIN; i <= EQEmu::constants::MATERIAL_TINT_END; i++) { c->GetTarget()->SendTextureWC(i, texture); } @@ -2545,13 +2545,13 @@ void command_peekinv(Client *c, const Seperator *sep) const ItemInst* inst_sub = nullptr; const Item_Struct* item_data = nullptr; std::string item_link; - EQEmu::SayLink::impl linker; - linker.SetLinkType(EQEmu::SayLink::LinkItemInst); + EQEmu::saylink::SayLinkEngine linker; + linker.SetLinkType(linker.SayLinkItemInst); c->Message(0, "Displaying inventory for %s...", targetClient->GetName()); // worn - for (int16 indexMain = EQEmu::Constants::EQUIPMENT_BEGIN; (scopeWhere & peekWorn) && (indexMain <= EQEmu::Constants::EQUIPMENT_END); ++indexMain) { + for (int16 indexMain = EQEmu::constants::EQUIPMENT_BEGIN; (scopeWhere & peekWorn) && (indexMain <= EQEmu::constants::EQUIPMENT_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2574,7 +2574,7 @@ void command_peekinv(Client *c, const Seperator *sep) } // inv - for (int16 indexMain = EQEmu::Constants::GENERAL_BEGIN; (scopeWhere & peekInv) && (indexMain <= EQEmu::Constants::GENERAL_END); ++indexMain) { + for (int16 indexMain = EQEmu::constants::GENERAL_BEGIN; (scopeWhere & peekInv) && (indexMain <= EQEmu::constants::GENERAL_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2584,7 +2584,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "InvSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2618,7 +2618,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "CursorSlot: %i, Depth: %i, Item: %i (%s), Charges: %i", SlotCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2633,7 +2633,7 @@ void command_peekinv(Client *c, const Seperator *sep) } // trib - for (int16 indexMain = EQEmu::Constants::TRIBUTE_BEGIN; (scopeWhere & peekTrib) && (indexMain <= EQEmu::Constants::TRIBUTE_END); ++indexMain) { + for (int16 indexMain = EQEmu::constants::TRIBUTE_BEGIN; (scopeWhere & peekTrib) && (indexMain <= EQEmu::constants::TRIBUTE_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2645,7 +2645,7 @@ void command_peekinv(Client *c, const Seperator *sep) } // bank - for (int16 indexMain = EQEmu::Constants::BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EQEmu::Constants::BANK_END); ++indexMain) { + for (int16 indexMain = EQEmu::constants::BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EQEmu::constants::BANK_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2655,7 +2655,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "BankSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2667,7 +2667,7 @@ void command_peekinv(Client *c, const Seperator *sep) } } - for (int16 indexMain = EQEmu::Constants::SHARED_BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EQEmu::Constants::SHARED_BANK_END); ++indexMain) { + for (int16 indexMain = EQEmu::constants::SHARED_BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EQEmu::constants::SHARED_BANK_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2677,7 +2677,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "SharedBankSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2690,7 +2690,7 @@ void command_peekinv(Client *c, const Seperator *sep) } // trade - for (int16 indexMain = EQEmu::Constants::TRADE_BEGIN; (scopeWhere & peekTrade) && (indexMain <= EQEmu::Constants::TRADE_END); ++indexMain) { + for (int16 indexMain = EQEmu::constants::TRADE_BEGIN; (scopeWhere & peekTrade) && (indexMain <= EQEmu::constants::TRADE_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2700,7 +2700,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "TradeSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2722,7 +2722,7 @@ void command_peekinv(Client *c, const Seperator *sep) else { c->Message(0, "[WorldObject DBID: %i (entityid: %i)]", objectTradeskill->GetDBID(), objectTradeskill->GetID()); - for (int16 indexMain = SLOT_BEGIN; indexMain < EQEmu::Constants::TYPE_WORLD_SIZE; ++indexMain) { + for (int16 indexMain = SLOT_BEGIN; indexMain < EQEmu::constants::TYPE_WORLD_SIZE; ++indexMain) { inst_main = objectTradeskill->GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2730,9 +2730,9 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), "WorldSlot: %i, Item: %i (%s), Charges: %i", - (EQEmu::Constants::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); + (EQEmu::constants::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -3140,7 +3140,7 @@ void command_listpetition(Client *c, const Seperator *sep) void command_equipitem(Client *c, const Seperator *sep) { uint32 slot_id = atoi(sep->arg[1]); - if (sep->IsNumber(1) && ((slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::Constants::EQUIPMENT_END) || (slot_id == SlotPowerSource))) { + if (sep->IsNumber(1) && ((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::constants::EQUIPMENT_END) || (slot_id == SlotPowerSource))) { const ItemInst* from_inst = c->GetInv().GetItem(SlotCursor); const ItemInst* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack) bool partialmove = false; @@ -4341,8 +4341,8 @@ void command_iteminfo(Client *c, const Seperator *sep) c->Message(13, "Error: This item has no data reference"); } - EQEmu::SayLink::impl linker; - linker.SetLinkType(EQEmu::SayLink::LinkItemInst); + EQEmu::saylink::SayLinkEngine linker; + linker.SetLinkType(linker.SayLinkItemInst); linker.SetItemInst(inst); auto item_link = linker.GenerateLink(); @@ -5491,9 +5491,9 @@ void command_summonitem(Client *c, const Seperator *sep) std::string cmd_msg = sep->msg; size_t link_open = cmd_msg.find('\x12'); size_t link_close = cmd_msg.find_last_of('\x12'); - if (link_open != link_close && (cmd_msg.length() - link_open) > EQEmu::Constants::TEXT_LINK_BODY_LENGTH) { - EQEmu::SayLink::SayLinkBody_Struct link_body; - EQEmu::SayLink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQEmu::Constants::TEXT_LINK_BODY_LENGTH)); + if (link_open != link_close && (cmd_msg.length() - link_open) > EQEmu::constants::TEXT_LINK_BODY_LENGTH) { + EQEmu::saylink::SayLinkBody_Struct link_body; + EQEmu::saylink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQEmu::constants::TEXT_LINK_BODY_LENGTH)); itemid = link_body.item_id; } else if (!sep->IsNumber(1)) { @@ -5603,8 +5603,8 @@ void command_itemsearch(Client *c, const Seperator *sep) const Item_Struct* item = nullptr; std::string item_link; - EQEmu::SayLink::impl linker; - linker.SetLinkType(EQEmu::SayLink::LinkItemData); + EQEmu::saylink::SayLinkEngine linker; + linker.SetLinkType(linker.SayLinkItemData); if (Seperator::IsNumber(search_criteria)) { item = database.GetItem(atoi(search_criteria)); @@ -7114,7 +7114,7 @@ void command_path(Client *c, const Seperator *sep) } void Client::Undye() { - for (int cur_slot = EQEmu::Constants::MATERIAL_BEGIN; cur_slot <= EQEmu::Constants::MATERIAL_END; cur_slot++ ) { + for (int cur_slot = EQEmu::constants::MATERIAL_BEGIN; cur_slot <= EQEmu::constants::MATERIAL_END; cur_slot++ ) { uint8 slot2=SlotConvert(cur_slot); ItemInst* inst = m_inv.GetItem(slot2); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index b45aae96b..e942a6446 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -328,7 +328,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( // to go into the regular slots on the player, out of bags std::list removed_list; - for(i = SLOT_BEGIN; i < EQEmu::Constants::TYPE_POSSESSIONS_SIZE; ++i) { + for(i = SLOT_BEGIN; i < EQEmu::constants::TYPE_POSSESSIONS_SIZE; ++i) { if(i == SlotAmmo && client->GetClientVersion() >= ClientVersion::SoF) { item = client->GetInv().GetItem(SlotPowerSource); if (item != nullptr) { @@ -410,9 +410,9 @@ void Corpse::MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, s while (true) { if (!inst->IsType(ItemClassContainer)) { break; } - if (equipSlot < EQEmu::Constants::GENERAL_BEGIN || equipSlot > SlotCursor) { break; } + if (equipSlot < EQEmu::constants::GENERAL_BEGIN || equipSlot > SlotCursor) { break; } - for (auto sub_index = SUB_BEGIN; sub_index < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++sub_index) { + for (auto sub_index = SUB_INDEX_BEGIN; sub_index < EQEmu::constants::ITEM_CONTAINER_SIZE; ++sub_index) { int16 real_bag_slot = Inventory::CalcSlotId(equipSlot, sub_index); auto bag_inst = client->GetInv().GetItem(real_bag_slot); if (bag_inst == nullptr) { continue; } @@ -693,7 +693,7 @@ ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** } if (sitem && bag_item_data && Inventory::SupportsContainers(sitem->equip_slot)) { - int16 bagstart = Inventory::CalcSlotId(sitem->equip_slot, SUB_BEGIN); + int16 bagstart = Inventory::CalcSlotId(sitem->equip_slot, SUB_INDEX_BEGIN); cur = itemlist.begin(); end = itemlist.end(); @@ -985,7 +985,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(inst) { if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); - client->SendItemPacket(EQEmu::Constants::CORPSE_BEGIN, inst, ItemPacketLoot); + client->SendItemPacket(EQEmu::constants::CORPSE_BEGIN, inst, ItemPacketLoot); safe_delete(inst); } else { client->Message(13, "Could not find item number %i to send!!", GetPlayerKillItem()); } @@ -1000,7 +1000,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::Limits::InventoryMapSize(TypeCorpse, client->GetClientVersion()); + int corpselootlimit = EQEmu::limits::InventoryMapSize(TypeCorpse, client->GetClientVersion()); for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; @@ -1019,7 +1019,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); // SlotGeneral1 is the corpse inventory start offset for Ti(EMu) - CORPSE_END = SlotGeneral1 + SlotCursor - client->SendItemPacket(i + EQEmu::Constants::CORPSE_BEGIN, inst, ItemPacketLoot); + client->SendItemPacket(i + EQEmu::constants::CORPSE_BEGIN, inst, ItemPacketLoot); safe_delete(inst); } @@ -1119,10 +1119,10 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { item = database.GetItem(GetPlayerKillItem()); } else if (GetPlayerKillItem() == -1 || GetPlayerKillItem() == 1){ - item_data = GetItem(lootitem->slot_id - EQEmu::Constants::CORPSE_BEGIN); //dont allow them to loot entire bags of items as pvp reward + item_data = GetItem(lootitem->slot_id - EQEmu::constants::CORPSE_BEGIN); //dont allow them to loot entire bags of items as pvp reward } else{ - item_data = GetItem(lootitem->slot_id - EQEmu::Constants::CORPSE_BEGIN, bag_item_data); + item_data = GetItem(lootitem->slot_id - EQEmu::constants::CORPSE_BEGIN, bag_item_data); } if (GetPlayerKillItem()<=1 && item_data != 0) { @@ -1148,7 +1148,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } if (inst->IsAugmented()) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { ItemInst *itm = inst->GetAugment(i); if (itm) { if (client->CheckLoreConflict(itm->GetItem())) { @@ -1210,7 +1210,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { /* Remove Bag Contents */ if (item->ItemClass == ItemClassContainer && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) { - for (int i = SUB_BEGIN; i < EQEmu::Constants::ITEM_CONTAINER_SIZE; i++) { + for (int i = SUB_INDEX_BEGIN; i < EQEmu::constants::ITEM_CONTAINER_SIZE; i++) { if (bag_item_data[i]) { /* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */ database.DeleteItemOffCharacterCorpse(this->corpse_db_id, bag_item_data[i]->equip_slot, bag_item_data[i]->item_id); @@ -1225,8 +1225,8 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } /* Send message with item link to groups and such */ - EQEmu::SayLink::impl linker; - linker.SetLinkType(EQEmu::SayLink::LinkItemInst); + EQEmu::saylink::SayLinkEngine linker; + linker.SetLinkType(linker.SayLinkItemInst); linker.SetItemInst(inst); auto item_link = linker.GenerateLink(); @@ -1294,13 +1294,13 @@ void Corpse::QueryLoot(Client* to) { cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::Limits::InventoryMapSize(TypeCorpse, to->GetClientVersion()); + int corpselootlimit = EQEmu::limits::InventoryMapSize(TypeCorpse, to->GetClientVersion()); for(; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; if (IsPlayerCorpse()) { - if (sitem->equip_slot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && sitem->equip_slot <= EQEmu::Constants::CURSOR_BAG_END) + if (sitem->equip_slot >= EQEmu::constants::GENERAL_BAGS_BEGIN && sitem->equip_slot <= EQEmu::constants::CURSOR_BAG_END) sitem->lootslot = 0xFFFF; else x < corpselootlimit ? sitem->lootslot = x : sitem->lootslot = 0xFFFF; @@ -1402,7 +1402,7 @@ void Corpse::Spawn() { uint32 Corpse::GetEquipment(uint8 material_slot) const { int16 invslot; - if(material_slot > EQEmu::Constants::MATERIAL_END) { + if(material_slot > EQEmu::constants::MATERIAL_END) { return NO_ITEM; } @@ -1416,7 +1416,7 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { const Item_Struct *item; - if(material_slot > EQEmu::Constants::MATERIAL_END) { + if(material_slot > EQEmu::constants::MATERIAL_END) { return 0; } @@ -1436,19 +1436,19 @@ void Corpse::UpdateEquipmentLight() m_Light.Level.Equipment = 0; for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) { - if (((*iter)->equip_slot < EQEmu::Constants::EQUIPMENT_BEGIN || (*iter)->equip_slot > EQEmu::Constants::EQUIPMENT_END) && (*iter)->equip_slot != SlotPowerSource) { continue; } + if (((*iter)->equip_slot < EQEmu::constants::EQUIPMENT_BEGIN || (*iter)->equip_slot > EQEmu::constants::EQUIPMENT_END) && (*iter)->equip_slot != SlotPowerSource) { continue; } if ((*iter)->equip_slot == SlotAmmo) { continue; } auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } - if (EQEmu::LightSource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) + if (EQEmu::lightsource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) m_Light.Type.Equipment = item->Light; } uint8 general_light_type = 0; for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) { - if ((*iter)->equip_slot < EQEmu::Constants::GENERAL_BEGIN || (*iter)->equip_slot > EQEmu::Constants::GENERAL_END) { continue; } + if ((*iter)->equip_slot < EQEmu::constants::GENERAL_BEGIN || (*iter)->equip_slot > EQEmu::constants::GENERAL_END) { continue; } auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } @@ -1456,14 +1456,14 @@ void Corpse::UpdateEquipmentLight() if (item->ItemClass != ItemClassCommon) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } - if (EQEmu::LightSource::TypeToLevel(item->Light)) + if (EQEmu::lightsource::TypeToLevel(item->Light)) general_light_type = item->Light; } - if (EQEmu::LightSource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) + if (EQEmu::lightsource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) m_Light.Type.Equipment = general_light_type; - m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); + m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); } void Corpse::AddLooter(Mob* who) { diff --git a/zone/forage.cpp b/zone/forage.cpp index 8d8762fb7..7241b312a 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -258,7 +258,7 @@ void Client::GoFish() Bait = m_inv.GetItem(bslot); //if the bait isnt equipped, need to add its skill bonus - if (bslot >= EQEmu::Constants::GENERAL_BEGIN && Bait != nullptr && Bait->GetItem()->SkillModType == SkillFishing) { + if (bslot >= EQEmu::constants::GENERAL_BEGIN && Bait != nullptr && Bait->GetItem()->SkillModType == SkillFishing) { fishing_skill += Bait->GetItem()->SkillModValue; } diff --git a/zone/inventory.cpp b/zone/inventory.cpp index ae1bbb63b..7a27b325e 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -35,7 +35,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { int i; if(where_to_check & invWhereWorn) { - for (i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; i++) { + for (i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -75,7 +75,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { DeleteItemInInventory(SlotCursor, 0, true); } - for (i = EQEmu::Constants::CURSOR_BAG_BEGIN; i <= EQEmu::Constants::CURSOR_BAG_END; i++) { + for (i = EQEmu::constants::CURSOR_BAG_BEGIN; i <= EQEmu::constants::CURSOR_BAG_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -90,7 +90,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if(where_to_check & invWherePersonal) { - for (i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { + for (i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -103,7 +103,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - for (i = EQEmu::Constants::GENERAL_BAGS_BEGIN; i <= EQEmu::Constants::GENERAL_BAGS_END; i++) { + for (i = EQEmu::constants::GENERAL_BAGS_BEGIN; i <= EQEmu::constants::GENERAL_BAGS_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -118,7 +118,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if(where_to_check & invWhereBank) { - for (i = EQEmu::Constants::BANK_BEGIN; i <= EQEmu::Constants::BANK_END; i++) { + for (i = EQEmu::constants::BANK_BEGIN; i <= EQEmu::constants::BANK_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -131,7 +131,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - for (i = EQEmu::Constants::BANK_BAGS_BEGIN; i <= EQEmu::Constants::BANK_BAGS_END; i++) { + for (i = EQEmu::constants::BANK_BAGS_BEGIN; i <= EQEmu::constants::BANK_BAGS_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -146,7 +146,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if(where_to_check & invWhereSharedBank) { - for (i = EQEmu::Constants::SHARED_BANK_BEGIN; i <= EQEmu::Constants::SHARED_BANK_END; i++) { + for (i = EQEmu::constants::SHARED_BANK_BEGIN; i <= EQEmu::constants::SHARED_BANK_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -159,7 +159,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - for (i = EQEmu::Constants::SHARED_BANK_BAGS_BEGIN; i <= EQEmu::Constants::SHARED_BANK_BAGS_END; i++) { + for (i = EQEmu::constants::SHARED_BANK_BAGS_BEGIN; i <= EQEmu::constants::SHARED_BANK_BAGS_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -236,7 +236,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, } */ - uint32 augments[EQEmu::Constants::ITEM_COMMON_SIZE] = { aug1, aug2, aug3, aug4, aug5, aug6 }; + uint32 augments[EQEmu::constants::ITEM_COMMON_SIZE] = { aug1, aug2, aug3, aug4, aug5, aug6 }; uint32 classes = item->Classes; uint32 races = item->Races; @@ -246,7 +246,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, bool enforcerestr = RuleB(Inventory, EnforceAugmentRestriction); bool enforceusable = RuleB(Inventory, EnforceAugmentUsability); - for (int iter = AUG_BEGIN; iter < EQEmu::Constants::ITEM_COMMON_SIZE; ++iter) { + for (int iter = AUG_INDEX_BEGIN; iter < EQEmu::constants::ITEM_COMMON_SIZE; ++iter) { const Item_Struct* augtest = database.GetItem(augments[iter]); if(augtest == nullptr) { @@ -540,7 +540,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, } // add any validated augments - for (int iter = AUG_BEGIN; iter < EQEmu::Constants::ITEM_COMMON_SIZE; ++iter) { + for (int iter = AUG_INDEX_BEGIN; iter < EQEmu::constants::ITEM_COMMON_SIZE; ++iter) { if(augments[iter]) inst->PutAugment(&database, iter, augments[iter]); } @@ -583,7 +583,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, DiscoverItem(item_id); /* // Augments should have been discovered prior to being placed on an item. - for (int iter = AUG_BEGIN; iter < EQEmu::Constants::ITEM_COMMON_SIZE; ++iter) { + for (int iter = AUG_BEGIN; iter < EQEmu::constants::ITEM_COMMON_SIZE; ++iter) { if(augments[iter] && !IsDiscovered(augments[iter])) DiscoverItem(augments[iter]); } @@ -761,7 +761,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd qsaudit->items[parent_offset].aug_5 = m_inv[slot_id]->GetAugmentItemID(5); if(m_inv[slot_id]->IsType(ItemClassContainer)) { - for(uint8 bag_idx = SUB_BEGIN; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) { + for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) { ItemInst* bagitem = m_inv[slot_id]->GetItem(bag_idx); if(bagitem) { @@ -906,7 +906,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI } if (bag_item_data) { - for (int index = 0; index < EQEmu::Constants::ITEM_CONTAINER_SIZE; ++index) { + for (int index = 0; index < EQEmu::constants::ITEM_CONTAINER_SIZE; ++index) { if (bag_item_data[index] == nullptr) continue; @@ -951,7 +951,7 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur return false; int16 i; uint32 item_id = item->GetItem()->ID; - for (i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { + for (i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { ItemInst* tmp_inst = m_inv.GetItem(i); if(tmp_inst && tmp_inst->GetItem()->ID == item_id && tmp_inst->GetCharges() < tmp_inst->GetItem()->StackSize){ MoveItemCharges(*item, i, type); @@ -962,8 +962,8 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur return true; } } - for (i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { - for (uint8 j = SUB_BEGIN; j < EQEmu::Constants::ITEM_CONTAINER_SIZE; j++) { + for (i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { + for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::constants::ITEM_CONTAINER_SIZE; j++) { uint16 slotid = Inventory::CalcSlotId(i, j); ItemInst* tmp_inst = m_inv.GetItem(slotid); @@ -988,8 +988,8 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs // #1: Try to auto equip if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level && (!inst.GetItem()->Attuneable || inst.IsAttuned()) && inst.GetItem()->ItemType != ItemTypeAugmentation) { // too messy as-is... - for (int16 i = EQEmu::Constants::EQUIPMENT_BEGIN; i < SlotPowerSource; i++) { // originally (i < 22) - if (i == EQEmu::Constants::GENERAL_BEGIN) { + for (int16 i = EQEmu::constants::EQUIPMENT_BEGIN; i < SlotPowerSource; i++) { // originally (i < 22) + if (i == EQEmu::constants::GENERAL_BEGIN) { // added power source check for SoF+ clients if (this->GetClientVersion() >= ClientVersion::SoF) i = SlotPowerSource; @@ -1318,15 +1318,15 @@ void Client::SendLootItemInPacket(const ItemInst* inst, int16 slot_id) bool Client::IsValidSlot(uint32 slot) { if ((slot == (uint32)INVALID_INDEX) || - (slot >= SLOT_BEGIN && slot < EQEmu::Constants::TYPE_POSSESSIONS_SIZE) || - (slot >= EQEmu::Constants::GENERAL_BAGS_BEGIN && slot <= EQEmu::Constants::CURSOR_BAG_END) || - (slot >= EQEmu::Constants::TRIBUTE_BEGIN && slot <= EQEmu::Constants::TRIBUTE_END) || - (slot >= EQEmu::Constants::BANK_BEGIN && slot <= EQEmu::Constants::BANK_END) || - (slot >= EQEmu::Constants::BANK_BAGS_BEGIN && slot <= EQEmu::Constants::BANK_BAGS_END) || - (slot >= EQEmu::Constants::SHARED_BANK_BEGIN && slot <= EQEmu::Constants::SHARED_BANK_END) || - (slot >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && slot <= EQEmu::Constants::SHARED_BANK_BAGS_END) || - (slot >= EQEmu::Constants::TRADE_BEGIN && slot <= EQEmu::Constants::TRADE_END) || - (slot >= EQEmu::Constants::WORLD_BEGIN && slot <= EQEmu::Constants::WORLD_END) || + (slot >= SLOT_BEGIN && slot < EQEmu::constants::TYPE_POSSESSIONS_SIZE) || + (slot >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot <= EQEmu::constants::CURSOR_BAG_END) || + (slot >= EQEmu::constants::TRIBUTE_BEGIN && slot <= EQEmu::constants::TRIBUTE_END) || + (slot >= EQEmu::constants::BANK_BEGIN && slot <= EQEmu::constants::BANK_END) || + (slot >= EQEmu::constants::BANK_BAGS_BEGIN && slot <= EQEmu::constants::BANK_BAGS_END) || + (slot >= EQEmu::constants::SHARED_BANK_BEGIN && slot <= EQEmu::constants::SHARED_BANK_END) || + (slot >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && slot <= EQEmu::constants::SHARED_BANK_BAGS_END) || + (slot >= EQEmu::constants::TRADE_BEGIN && slot <= EQEmu::constants::TRADE_END) || + (slot >= EQEmu::constants::WORLD_BEGIN && slot <= EQEmu::constants::WORLD_END) || (slot == SlotPowerSource) ) { return true; @@ -1338,10 +1338,10 @@ bool Client::IsValidSlot(uint32 slot) { bool Client::IsBankSlot(uint32 slot) { - if ((slot >= EQEmu::Constants::BANK_BEGIN && slot <= EQEmu::Constants::BANK_END) || - (slot >= EQEmu::Constants::BANK_BAGS_BEGIN && slot <= EQEmu::Constants::BANK_BAGS_END) || - (slot >= EQEmu::Constants::SHARED_BANK_BEGIN && slot <= EQEmu::Constants::SHARED_BANK_END) || - (slot >= EQEmu::Constants::SHARED_BANK_BAGS_BEGIN && slot <= EQEmu::Constants::SHARED_BANK_BAGS_END)) + if ((slot >= EQEmu::constants::BANK_BEGIN && slot <= EQEmu::constants::BANK_END) || + (slot >= EQEmu::constants::BANK_BAGS_BEGIN && slot <= EQEmu::constants::BANK_BAGS_END) || + (slot >= EQEmu::constants::SHARED_BANK_BEGIN && slot <= EQEmu::constants::SHARED_BANK_END) || + (slot >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && slot <= EQEmu::constants::SHARED_BANK_BAGS_END)) { return true; } @@ -1475,13 +1475,13 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { uint32 dstbagid = 0; //if (src_slot_id >= 250 && src_slot_id < 330) { - if (src_slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && src_slot_id <= EQEmu::Constants::GENERAL_BAGS_END) { + if (src_slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && src_slot_id <= EQEmu::constants::GENERAL_BAGS_END) { srcbag = m_inv.GetItem(((int)(src_slot_id / 10)) - 3); if (srcbag) srcbagid = srcbag->GetItem()->ID; } //if (dst_slot_id >= 250 && dst_slot_id < 330) { - if (dst_slot_id >= EQEmu::Constants::GENERAL_BAGS_BEGIN && dst_slot_id <= EQEmu::Constants::GENERAL_BAGS_END) { + if (dst_slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && dst_slot_id <= EQEmu::constants::GENERAL_BAGS_END) { dstbag = m_inv.GetItem(((int)(dst_slot_id / 10)) - 3); if (dstbag) dstbagid = dstbag->GetItem()->ID; @@ -1494,7 +1494,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Step 2: Validate item in from_slot // After this, we can assume src_inst is a valid ptr - if (!src_inst && (src_slot_id < EQEmu::Constants::WORLD_BEGIN || src_slot_id > EQEmu::Constants::WORLD_END)) { + if (!src_inst && (src_slot_id < EQEmu::constants::WORLD_BEGIN || src_slot_id > EQEmu::constants::WORLD_END)) { if (dst_inst) { // If there is no source item, but there is a destination item, // move the slots around before deleting the invalid source slot item, @@ -1508,14 +1508,14 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return false; } //verify shared bank transactions in the database - if(src_inst && src_slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { + if(src_inst && src_slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { if(!database.VerifyInventory(account_id, src_slot_id, src_inst)) { Log.Out(Logs::General, Logs::Error, "Player %s on account %s was found exploiting the shared bank.\n", GetName(), account_name); DeleteItemInInventory(dst_slot_id,0,true); return(false); } - if(src_slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::Constants::SHARED_BANK_END && src_inst->IsType(ItemClassContainer)){ - for (uint8 idx = SUB_BEGIN; idx < EQEmu::Constants::ITEM_CONTAINER_SIZE; idx++) { + if(src_slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::constants::SHARED_BANK_END && src_inst->IsType(ItemClassContainer)){ + for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::constants::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = src_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(src_slot_id, idx), baginst)){ DeleteItemInInventory(Inventory::CalcSlotId(src_slot_id, idx),0,false); @@ -1523,14 +1523,14 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } } } - if(dst_inst && dst_slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END) { + if(dst_inst && dst_slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { if(!database.VerifyInventory(account_id, dst_slot_id, dst_inst)) { Log.Out(Logs::General, Logs::Error, "Player %s on account %s was found exploting the shared bank.\n", GetName(), account_name); DeleteItemInInventory(src_slot_id,0,true); return(false); } - if(dst_slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::Constants::SHARED_BANK_END && dst_inst->IsType(ItemClassContainer)){ - for (uint8 idx = SUB_BEGIN; idx < EQEmu::Constants::ITEM_CONTAINER_SIZE; idx++) { + if(dst_slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::constants::SHARED_BANK_END && dst_inst->IsType(ItemClassContainer)){ + for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::constants::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = dst_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(dst_slot_id, idx), baginst)){ DeleteItemInInventory(Inventory::CalcSlotId(dst_slot_id, idx),0,false); @@ -1542,8 +1542,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Check for No Drop Hacks Mob* with = trade->With(); - if (((with && with->IsClient() && dst_slot_id >= EQEmu::Constants::TRADE_BEGIN && dst_slot_id <= EQEmu::Constants::TRADE_END) || - (dst_slot_id >= EQEmu::Constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END)) + if (((with && with->IsClient() && dst_slot_id >= EQEmu::constants::TRADE_BEGIN && dst_slot_id <= EQEmu::constants::TRADE_END) || + (dst_slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END)) && GetInv().CheckNoDrop(src_slot_id) && RuleI(World, FVNoDropFlag) == 0 || RuleI(Character, MinStatusForNoDropExemptions) < Admin() && RuleI(World, FVNoDropFlag) == 2) { auto ndh_inst = m_inv[src_slot_id]; @@ -1573,7 +1573,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Step 3: Check for interaction with World Container (tradeskills) if(m_tradeskill_object != nullptr) { - if (src_slot_id >= EQEmu::Constants::WORLD_BEGIN && src_slot_id <= EQEmu::Constants::WORLD_END) { + if (src_slot_id >= EQEmu::constants::WORLD_BEGIN && src_slot_id <= EQEmu::constants::WORLD_END) { // Picking up item from world container ItemInst* inst = m_tradeskill_object->PopItem(Inventory::CalcBagIdx(src_slot_id)); if (inst) { @@ -1585,7 +1585,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return true; } - else if (dst_slot_id >= EQEmu::Constants::WORLD_BEGIN && dst_slot_id <= EQEmu::Constants::WORLD_END) { + else if (dst_slot_id >= EQEmu::constants::WORLD_BEGIN && dst_slot_id <= EQEmu::constants::WORLD_END) { // Putting item into world container, which may swap (or pile onto) with existing item uint8 world_idx = Inventory::CalcBagIdx(dst_slot_id); ItemInst* world_inst = m_tradeskill_object->PopItem(world_idx); @@ -1658,7 +1658,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } // Step 4: Check for entity trade - if (dst_slot_id >= EQEmu::Constants::TRADE_BEGIN && dst_slot_id <= EQEmu::Constants::TRADE_END) { + if (dst_slot_id >= EQEmu::constants::TRADE_BEGIN && dst_slot_id <= EQEmu::constants::TRADE_END) { if (src_slot_id != SlotCursor) { Kick(); return false; @@ -1751,12 +1751,12 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } else { // Not dealing with charges - just do direct swap - if(src_inst && (dst_slot_id <= EQEmu::Constants::EQUIPMENT_END || dst_slot_id == SlotPowerSource) && dst_slot_id >= EQEmu::Constants::EQUIPMENT_BEGIN) { + if(src_inst && (dst_slot_id <= EQEmu::constants::EQUIPMENT_END || dst_slot_id == SlotPowerSource) && dst_slot_id >= EQEmu::constants::EQUIPMENT_BEGIN) { if (src_inst->GetItem()->Attuneable) { src_inst->SetAttuned(true); } if (src_inst->IsAugmented()) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { if (src_inst->GetAugment(i)) { if (src_inst->GetAugment(i)->GetItem()->Attuneable) { src_inst->GetAugment(i)->SetAttuned(true); @@ -1769,7 +1769,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(!m_inv.SwapItem(src_slot_id, dst_slot_id)) { return false; } Log.Out(Logs::Detail, Logs::Inventory, "Moving entire item from slot %d to slot %d", src_slot_id, dst_slot_id); - if(src_slot_id <= EQEmu::Constants::EQUIPMENT_END || src_slot_id == SlotPowerSource) { + if(src_slot_id <= EQEmu::constants::EQUIPMENT_END || src_slot_id == SlotPowerSource) { if(src_inst) { parse->EventItem(EVENT_UNEQUIP_ITEM, this, src_inst, nullptr, "", src_slot_id); } @@ -1779,7 +1779,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } } - if(dst_slot_id <= EQEmu::Constants::EQUIPMENT_END || dst_slot_id == SlotPowerSource) { + if(dst_slot_id <= EQEmu::constants::EQUIPMENT_END || dst_slot_id == SlotPowerSource) { if(dst_inst) { parse->EventItem(EVENT_UNEQUIP_ITEM, this, dst_inst, nullptr, "", dst_slot_id); } @@ -1791,7 +1791,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } int matslot = SlotConvert2(dst_slot_id); - if (dst_slot_id <= EQEmu::Constants::EQUIPMENT_END && matslot != MaterialHead) { // think this is to allow the client to update with /showhelm + if (dst_slot_id <= EQEmu::constants::EQUIPMENT_END && matslot != MaterialHead) { // think this is to allow the client to update with /showhelm SendWearChange(matslot); } @@ -1833,7 +1833,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { Log.Out(Logs::Detail, Logs::Inventory, "Inventory desyncronization. (charname: %s, source: %i, destination: %i)", GetName(), move_slots->from_slot, move_slots->to_slot); Message(15, "Inventory Desyncronization detected: Resending slot data..."); - if((move_slots->from_slot >= EQEmu::Constants::EQUIPMENT_BEGIN && move_slots->from_slot <= EQEmu::Constants::CURSOR_BAG_END) || move_slots->from_slot == SlotPowerSource) { + if((move_slots->from_slot >= EQEmu::constants::EQUIPMENT_BEGIN && move_slots->from_slot <= EQEmu::constants::CURSOR_BAG_END) || move_slots->from_slot == SlotPowerSource) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { // This prevents the client from crashing when closing any 'phantom' bags @@ -1876,7 +1876,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); } } - if((move_slots->to_slot >= EQEmu::Constants::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::Constants::CURSOR_BAG_END) || move_slots->to_slot == SlotPowerSource) { + if((move_slots->to_slot >= EQEmu::constants::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::constants::CURSOR_BAG_END) || move_slots->to_slot == SlotPowerSource) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' @@ -1957,7 +1957,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { qsaudit->items[move_count++].aug_5 = from_inst->GetAugmentItemID(5); if(from_inst->IsType(ItemClassContainer)) { - for(uint8 bag_idx = SUB_BEGIN; bag_idx < from_inst->GetItem()->BagSlots; bag_idx++) { + for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < from_inst->GetItem()->BagSlots; bag_idx++) { const ItemInst* from_baginst = from_inst->GetItem(bag_idx); if(from_baginst) { @@ -1990,7 +1990,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { qsaudit->items[move_count++].aug_5 = to_inst->GetAugmentItemID(5); if(to_inst->IsType(ItemClassContainer)) { - for(uint8 bag_idx = SUB_BEGIN; bag_idx < to_inst->GetItem()->BagSlots; bag_idx++) { + for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < to_inst->GetItem()->BagSlots; bag_idx++) { const ItemInst* to_baginst = to_inst->GetItem(bag_idx); if(to_baginst) { @@ -2019,7 +2019,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { void Client::DyeArmor(DyeStruct* dye){ int16 slot=0; - for (int i = EQEmu::Constants::MATERIAL_BEGIN; i <= EQEmu::Constants::MATERIAL_TINT_END; i++) { + for (int i = EQEmu::constants::MATERIAL_BEGIN; i <= EQEmu::constants::MATERIAL_TINT_END; i++) { if ((m_pp.item_tint[i].Color & 0x00FFFFFF) != (dye->dye[i].Color & 0x00FFFFFF)) { slot = m_inv.HasItem(32557, 1, invWherePersonal); if (slot != INVALID_INDEX){ @@ -2058,7 +2058,7 @@ bool Client::DecreaseByItemType(uint32 type, uint8 amt) { const Item_Struct* TempItem = 0; ItemInst* ins; int x; - for(x=EQEmu::Constants::POSSESSIONS_BEGIN; x <= EQEmu::Constants::POSSESSIONS_END; x++) + for(x=EQEmu::constants::POSSESSIONS_BEGIN; x <= EQEmu::constants::POSSESSIONS_END; x++) { TempItem = 0; ins = GetInv().GetItem(x); @@ -2080,7 +2080,7 @@ bool Client::DecreaseByItemType(uint32 type, uint8 amt) { return true; } } - for(x=EQEmu::Constants::GENERAL_BAGS_BEGIN; x <= EQEmu::Constants::GENERAL_BAGS_END; x++) + for(x=EQEmu::constants::GENERAL_BAGS_BEGIN; x <= EQEmu::constants::GENERAL_BAGS_END; x++) { TempItem = 0; ins = GetInv().GetItem(x); @@ -2111,10 +2111,10 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) { ItemInst* ins = nullptr; int x; int num = 0; - for(x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::GENERAL_BAGS_END; x++) + for(x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::GENERAL_BAGS_END; x++) { if (x == SlotCursor + 1) - x = EQEmu::Constants::GENERAL_BAGS_BEGIN; + x = EQEmu::constants::GENERAL_BAGS_BEGIN; TempItem = nullptr; ins = GetInv().GetItem(x); if (ins) @@ -2128,10 +2128,10 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) { } if (num < amt) return false; - for(x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::GENERAL_BAGS_END; x++) // should this be CURSOR_BAG_END? + for(x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::GENERAL_BAGS_END; x++) // should this be CURSOR_BAG_END? { if (x == SlotCursor + 1) - x = EQEmu::Constants::GENERAL_BAGS_BEGIN; + x = EQEmu::constants::GENERAL_BAGS_BEGIN; TempItem = nullptr; ins = GetInv().GetItem(x); if (ins) @@ -2227,7 +2227,7 @@ static bool CopyBagContents(ItemInst* new_bag, const ItemInst* old_bag) void Client::DisenchantSummonedBags(bool client_update) { - for (auto slot_id = EQEmu::Constants::GENERAL_BEGIN; slot_id <= EQEmu::Constants::GENERAL_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::GENERAL_BEGIN; slot_id <= EQEmu::constants::GENERAL_END; ++slot_id) { auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } @@ -2248,7 +2248,7 @@ void Client::DisenchantSummonedBags(bool client_update) safe_delete(new_inst); } - for (auto slot_id = EQEmu::Constants::BANK_BEGIN; slot_id <= EQEmu::Constants::BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::BANK_BEGIN; slot_id <= EQEmu::constants::BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } @@ -2269,7 +2269,7 @@ void Client::DisenchantSummonedBags(bool client_update) safe_delete(new_inst); } - for (auto slot_id = EQEmu::Constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::Constants::SHARED_BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::constants::SHARED_BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } @@ -2338,7 +2338,7 @@ void Client::DisenchantSummonedBags(bool client_update) void Client::RemoveNoRent(bool client_update) { - for (auto slot_id = EQEmu::Constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::Constants::EQUIPMENT_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::constants::EQUIPMENT_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2346,7 +2346,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EQEmu::Constants::GENERAL_BEGIN; slot_id <= EQEmu::Constants::GENERAL_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::GENERAL_BEGIN; slot_id <= EQEmu::constants::GENERAL_END; ++slot_id) { auto inst = m_inv[slot_id]; if (inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2362,7 +2362,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EQEmu::Constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::Constants::CURSOR_BAG_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::constants::CURSOR_BAG_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2370,7 +2370,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EQEmu::Constants::BANK_BEGIN; slot_id <= EQEmu::Constants::BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::BANK_BEGIN; slot_id <= EQEmu::constants::BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2378,7 +2378,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EQEmu::Constants::BANK_BAGS_BEGIN; slot_id <= EQEmu::Constants::BANK_BAGS_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::BANK_BAGS_BEGIN; slot_id <= EQEmu::constants::BANK_BAGS_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2386,7 +2386,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EQEmu::Constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::Constants::SHARED_BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::constants::SHARED_BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2394,7 +2394,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EQEmu::Constants::SHARED_BANK_BAGS_BEGIN; slot_id <= EQEmu::Constants::SHARED_BANK_BAGS_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::SHARED_BANK_BAGS_BEGIN; slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2432,7 +2432,7 @@ void Client::RemoveNoRent(bool client_update) // Two new methods to alleviate perpetual login desyncs void Client::RemoveDuplicateLore(bool client_update) { - for (auto slot_id = EQEmu::Constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::Constants::EQUIPMENT_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::constants::EQUIPMENT_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2445,7 +2445,7 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - for (auto slot_id = EQEmu::Constants::GENERAL_BEGIN; slot_id <= EQEmu::Constants::GENERAL_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::GENERAL_BEGIN; slot_id <= EQEmu::constants::GENERAL_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if (CheckLoreConflict(inst->GetItem())) { @@ -2472,7 +2472,7 @@ void Client::RemoveDuplicateLore(bool client_update) } } - for (auto slot_id = EQEmu::Constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::Constants::CURSOR_BAG_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::constants::CURSOR_BAG_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2485,7 +2485,7 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - for (auto slot_id = EQEmu::Constants::BANK_BEGIN; slot_id <= EQEmu::Constants::BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::BANK_BEGIN; slot_id <= EQEmu::constants::BANK_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2498,7 +2498,7 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - for (auto slot_id = EQEmu::Constants::BANK_BAGS_BEGIN; slot_id <= EQEmu::Constants::BANK_BAGS_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::BANK_BAGS_BEGIN; slot_id <= EQEmu::constants::BANK_BAGS_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2559,7 +2559,7 @@ void Client::RemoveDuplicateLore(bool client_update) void Client::MoveSlotNotAllowed(bool client_update) { - for (auto slot_id = EQEmu::Constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::Constants::EQUIPMENT_END; ++slot_id) { + for (auto slot_id = EQEmu::constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::constants::EQUIPMENT_END; ++slot_id) { if(m_inv[slot_id] && !m_inv[slot_id]->IsSlotAllowed(slot_id)) { auto inst = m_inv.PopItem(slot_id); bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; @@ -2591,7 +2591,7 @@ uint32 Client::GetEquipment(uint8 material_slot) const int16 invslot; const ItemInst *item; - if(material_slot > EQEmu::Constants::MATERIAL_END) + if(material_slot > EQEmu::constants::MATERIAL_END) { return 0; } @@ -2629,7 +2629,7 @@ int32 Client::GetEquipmentMaterial(uint8 material_slot) uint32 Client::GetEquipmentColor(uint8 material_slot) const { - if (material_slot > EQEmu::Constants::MATERIAL_END) + if (material_slot > EQEmu::constants::MATERIAL_END) return 0; const Item_Struct *item = database.GetItem(GetEquipment(material_slot)); @@ -2780,7 +2780,7 @@ void Client::SetBandolier(const EQApplicationPacket *app) slot = SlotCursor; } else if (m_inv.GetItem(SlotCursor)->GetItem()->ItemClass == 1) { - for(int16 CursorBagSlot = EQEmu::Constants::CURSOR_BAG_BEGIN; CursorBagSlot <= EQEmu::Constants::CURSOR_BAG_END; CursorBagSlot++) { + for(int16 CursorBagSlot = EQEmu::constants::CURSOR_BAG_BEGIN; CursorBagSlot <= EQEmu::constants::CURSOR_BAG_END; CursorBagSlot++) { if (m_inv.GetItem(CursorBagSlot)) { if (m_inv.GetItem(CursorBagSlot)->GetItem()->ID == m_pp.bandoliers[bss->Number].Items[BandolierSlot].ID && m_inv.GetItem(CursorBagSlot)->GetCharges() >= 1) { // ditto @@ -2926,7 +2926,7 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { // if(ItemToReturn->IsStackable()) { - for (int16 i = EQEmu::Constants::GENERAL_BEGIN; i <= SlotCursor; i++) { // changed slot max to 30 from 29. client will stack into slot 30 (bags too) before moving. + for (int16 i = EQEmu::constants::GENERAL_BEGIN; i <= SlotCursor; i++) { // changed slot max to 30 from 29. client will stack into slot 30 (bags too) before moving. ItemInst* InvItem = m_inv.GetItem(i); @@ -2952,12 +2952,12 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { // if (InvItem && InvItem->IsType(ItemClassContainer)) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_BEGIN); + int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); uint8 BagSize=InvItem->GetItem()->BagSlots; uint8 BagSlot; - for (BagSlot = SUB_BEGIN; BagSlot < BagSize; BagSlot++) { + for (BagSlot = SUB_INDEX_BEGIN; BagSlot < BagSize; BagSlot++) { InvItem = m_inv.GetItem(BaseSlotID + BagSlot); if (InvItem && (InvItem->GetItem()->ID == ItemID) && (InvItem->GetCharges() < InvItem->GetItem()->StackSize)) { @@ -2985,7 +2985,7 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { // We have tried stacking items, now just try and find an empty slot. - for (int16 i = EQEmu::Constants::GENERAL_BEGIN; i <= SlotCursor; i++) { // changed slot max to 30 from 29. client will move into slot 30 (bags too) before pushing onto cursor. + for (int16 i = EQEmu::constants::GENERAL_BEGIN; i <= SlotCursor; i++) { // changed slot max to 30 from 29. client will move into slot 30 (bags too) before pushing onto cursor. ItemInst* InvItem = m_inv.GetItem(i); @@ -3004,11 +3004,11 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { } if(InvItem->IsType(ItemClassContainer) && Inventory::CanItemFitInContainer(ItemToReturn->GetItem(), InvItem->GetItem())) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_BEGIN); + int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); uint8 BagSize=InvItem->GetItem()->BagSlots; - for (uint8 BagSlot = SUB_BEGIN; BagSlot < BagSize; BagSlot++) { + for (uint8 BagSlot = SUB_INDEX_BEGIN; BagSlot < BagSize; BagSlot++) { InvItem = m_inv.GetItem(BaseSlotID + BagSlot); @@ -3046,27 +3046,27 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool std::map instmap; // build reference map - for (int16 index = SLOT_BEGIN; index < EQEmu::Constants::TYPE_POSSESSIONS_SIZE; ++index) { + for (int16 index = SLOT_BEGIN; index < EQEmu::constants::TYPE_POSSESSIONS_SIZE; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EQEmu::Constants::TRIBUTE_BEGIN; index <= EQEmu::Constants::TRIBUTE_END; ++index) { + for (int16 index = EQEmu::constants::TRIBUTE_BEGIN; index <= EQEmu::constants::TRIBUTE_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EQEmu::Constants::BANK_BEGIN; index <= EQEmu::Constants::BANK_END; ++index) { + for (int16 index = EQEmu::constants::BANK_BEGIN; index <= EQEmu::constants::BANK_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EQEmu::Constants::SHARED_BANK_BEGIN; index <= EQEmu::Constants::SHARED_BANK_END; ++index) { + for (int16 index = EQEmu::constants::SHARED_BANK_BEGIN; index <= EQEmu::constants::SHARED_BANK_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EQEmu::Constants::TRADE_BEGIN; index <= EQEmu::Constants::TRADE_END; ++index) { + for (int16 index = EQEmu::constants::TRADE_BEGIN; index <= EQEmu::constants::TRADE_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; @@ -3074,10 +3074,10 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool auto tsobject = GetTradeskillObject(); if (tsobject != nullptr) { - for (int16 index = SLOT_BEGIN; index < EQEmu::Constants::TYPE_WORLD_SIZE; ++index) { + for (int16 index = SLOT_BEGIN; index < EQEmu::constants::TYPE_WORLD_SIZE; ++index) { auto inst = tsobject->GetItem(index); if (inst == nullptr) { continue; } - instmap[EQEmu::Constants::WORLD_BEGIN + index] = inst; + instmap[EQEmu::constants::WORLD_BEGIN + index] = inst; } } @@ -3149,7 +3149,7 @@ void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 hea } else { if (inst) { - for (int16 sub = SUB_BEGIN; (sub < EQEmu::Constants::ITEM_CONTAINER_SIZE) && (!error); ++sub) { // treat any ItemInst as having the max internal slots available + for (int16 sub = SUB_INDEX_BEGIN; (sub < EQEmu::constants::ITEM_CONTAINER_SIZE) && (!error); ++sub) { // treat any ItemInst as having the max internal slots available if (inst->GetItem(sub)) InterrogateInventory_(true, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1); } @@ -3179,7 +3179,7 @@ void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 hea } if (inst) { - for (int16 sub = SUB_BEGIN; (sub < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++sub) { + for (int16 sub = SUB_INDEX_BEGIN; (sub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++sub) { if (inst->GetItem(sub)) InterrogateInventory_(false, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1); } @@ -3194,9 +3194,9 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* // very basic error checking - can be elaborated upon if more in-depth testing is needed... if ( - (head >= EQEmu::Constants::EQUIPMENT_BEGIN && head <= EQEmu::Constants::EQUIPMENT_END) || - (head >= EQEmu::Constants::TRIBUTE_BEGIN && head <= EQEmu::Constants::TRIBUTE_END) || - (head >= EQEmu::Constants::WORLD_BEGIN && head <= EQEmu::Constants::WORLD_END) || + (head >= EQEmu::constants::EQUIPMENT_BEGIN && head <= EQEmu::constants::EQUIPMENT_END) || + (head >= EQEmu::constants::TRIBUTE_BEGIN && head <= EQEmu::constants::TRIBUTE_END) || + (head >= EQEmu::constants::WORLD_BEGIN && head <= EQEmu::constants::WORLD_END) || (head >= 8000 && head <= 8101) || (head == SlotPowerSource)) { switch (depth) @@ -3210,7 +3210,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* return true; if (!parent->IsType(ItemClassCommon)) return true; - if (index >= EQEmu::Constants::ITEM_COMMON_SIZE) + if (index >= EQEmu::constants::ITEM_COMMON_SIZE) return true; break; default: // requirement: none (something bad happened...) @@ -3218,11 +3218,11 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* } } else if ( - (head >= EQEmu::Constants::GENERAL_BEGIN && head <= EQEmu::Constants::GENERAL_END) || + (head >= EQEmu::constants::GENERAL_BEGIN && head <= EQEmu::constants::GENERAL_END) || (head == SlotCursor) || - (head >= EQEmu::Constants::BANK_BEGIN && head <= EQEmu::Constants::BANK_END) || - (head >= EQEmu::Constants::SHARED_BANK_BEGIN && head <= EQEmu::Constants::SHARED_BANK_END) || - (head >= EQEmu::Constants::TRADE_BEGIN && head <= EQEmu::Constants::TRADE_END)) { + (head >= EQEmu::constants::BANK_BEGIN && head <= EQEmu::constants::BANK_END) || + (head >= EQEmu::constants::SHARED_BANK_BEGIN && head <= EQEmu::constants::SHARED_BANK_END) || + (head >= EQEmu::constants::TRADE_BEGIN && head <= EQEmu::constants::TRADE_END)) { switch (depth) { case 0: // requirement: inst is extant @@ -3239,7 +3239,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* if (parent->IsType(ItemClassCommon)) { if (!(inst->GetItem()->AugType > 0)) return true; - if (index >= EQEmu::Constants::ITEM_COMMON_SIZE) + if (index >= EQEmu::constants::ITEM_COMMON_SIZE) return true; } break; @@ -3253,7 +3253,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* if (parent->IsType(ItemClassCommon)) { if (!(inst->GetItem()->AugType > 0)) return true; - if (index >= EQEmu::Constants::ITEM_COMMON_SIZE) + if (index >= EQEmu::constants::ITEM_COMMON_SIZE) return true; } break; diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 708d3cd82..4985f9d9f 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -272,7 +272,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge // it is an improvement. if (!item2->NoPet) { - for (int i = 0; !found && i < EQEmu::Constants::EQUIPMENT_SIZE; i++) { + for (int i = 0; !found && i < EQEmu::constants::EQUIPMENT_SIZE; i++) { uint32 slots = (1 << i); if (item2->Slots & slots) { if(equipment[i]) diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 2b345d847..798fc7685 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1794,13 +1794,13 @@ luabind::scope lua_register_slot() { luabind::value("General7", static_cast(SlotGeneral7)), luabind::value("General8", static_cast(SlotGeneral8)), luabind::value("Cursor", static_cast(SlotCursor)), - luabind::value("PersonalBegin", static_cast(EQEmu::Constants::GENERAL_BEGIN)), // deprecated - luabind::value("GeneralBegin", static_cast(EQEmu::Constants::GENERAL_BEGIN)), - luabind::value("PersonalEnd", static_cast(EQEmu::Constants::GENERAL_END)), // deprecated - luabind::value("GeneralEnd", static_cast(EQEmu::Constants::GENERAL_END)), + luabind::value("PersonalBegin", static_cast(EQEmu::constants::GENERAL_BEGIN)), // deprecated + luabind::value("GeneralBegin", static_cast(EQEmu::constants::GENERAL_BEGIN)), + luabind::value("PersonalEnd", static_cast(EQEmu::constants::GENERAL_END)), // deprecated + luabind::value("GeneralEnd", static_cast(EQEmu::constants::GENERAL_END)), luabind::value("CursorEnd", 0xFFFE), // deprecated - luabind::value("Tradeskill", static_cast(EQEmu::Legacy::SLOT_TRADESKILL)), // deprecated - luabind::value("Augment", static_cast(EQEmu::Legacy::SLOT_AUGMENT)), // deprecated + luabind::value("Tradeskill", static_cast(EQEmu::legacy::SLOT_TRADESKILL)), // deprecated + luabind::value("Augment", static_cast(EQEmu::legacy::SLOT_AUGMENT)), // deprecated luabind::value("Invalid", INVALID_INDEX) ]; } diff --git a/zone/merc.cpp b/zone/merc.cpp index 91d66523c..bb5a96b9a 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -2552,7 +2552,7 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) { int16 focus_max_real = 0; //item focus - for (int x = 0; x < EQEmu::Constants::EQUIPMENT_SIZE; ++x) + for (int x = 0; x < EQEmu::constants::EQUIPMENT_SIZE; ++x) { TempItem = nullptr; if (equipment[x] == 0) @@ -5026,7 +5026,7 @@ void Merc::UpdateMercAppearance() { // Copied from Bot Code: uint32 itemID = NO_ITEM; uint8 materialFromSlot = MaterialInvalid; - for (int i = EQEmu::Constants::EQUIPMENT_BEGIN; i <= EQEmu::Constants::EQUIPMENT_END; ++i) { + for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; ++i) { itemID = equipment[i]; if(itemID != NO_ITEM) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); @@ -5044,15 +5044,15 @@ void Merc::UpdateEquipmentLight() m_Light.Type.Equipment = 0; m_Light.Level.Equipment = 0; - for (int index = SLOT_BEGIN; index < EQEmu::Constants::EQUIPMENT_SIZE; ++index) { + for (int index = SLOT_BEGIN; index < EQEmu::constants::EQUIPMENT_SIZE; ++index) { if (index == SlotAmmo) { continue; } auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } - if (EQEmu::LightSource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) { + if (EQEmu::lightsource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) { m_Light.Type.Equipment = item->Light; - m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); + m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); } } @@ -5064,14 +5064,14 @@ void Merc::UpdateEquipmentLight() if (item->ItemClass != ItemClassCommon) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } - if (EQEmu::LightSource::TypeToLevel(item->Light)) + if (EQEmu::lightsource::TypeToLevel(item->Light)) general_light_type = item->Light; } - if (EQEmu::LightSource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) + if (EQEmu::lightsource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) m_Light.Type.Equipment = general_light_type; - m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); + m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); } void Merc::AddItem(uint8 slot, uint32 item_id) { diff --git a/zone/merc.h b/zone/merc.h index 2a73bb8a3..0efb3d568 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -288,7 +288,7 @@ protected: std::map timers; uint16 skills[HIGHEST_SKILL+1]; - uint32 equipment[EQEmu::Constants::EQUIPMENT_SIZE]; //this is an array of item IDs + uint32 equipment[EQEmu::constants::EQUIPMENT_SIZE]; //this is an array of item IDs uint16 d_melee_texture1; //this is an item Material value uint16 d_melee_texture2; //this is an item Material value (offhand) uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation diff --git a/zone/mob.cpp b/zone/mob.cpp index f7751a871..6c9b6d0ca 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -179,7 +179,7 @@ Mob::Mob(const char* in_name, runspeed = 1.25f; m_Light.Type.Innate = in_light; - m_Light.Level.Innate = EQEmu::LightSource::TypeToLevel(m_Light.Type.Innate); + m_Light.Level.Innate = EQEmu::lightsource::TypeToLevel(m_Light.Type.Innate); m_Light.Level.Equipment = m_Light.Type.Equipment = 0; m_Light.Level.Spell = m_Light.Type.Spell = 0; m_Light.Type.Active = m_Light.Type.Innate; @@ -2232,11 +2232,11 @@ bool Mob::UpdateActiveLight() m_Light.Type.Active = 0; m_Light.Level.Active = 0; - if (EQEmu::LightSource::IsLevelGreater((m_Light.Type.Innate & 0x0F), m_Light.Type.Active)) { m_Light.Type.Active = m_Light.Type.Innate; } + if (EQEmu::lightsource::IsLevelGreater((m_Light.Type.Innate & 0x0F), m_Light.Type.Active)) { m_Light.Type.Active = m_Light.Type.Innate; } if (m_Light.Level.Equipment > m_Light.Level.Active) { m_Light.Type.Active = m_Light.Type.Equipment; } // limiter in property handler if (m_Light.Level.Spell > m_Light.Level.Active) { m_Light.Type.Active = m_Light.Type.Spell; } // limiter in property handler - m_Light.Level.Active = EQEmu::LightSource::TypeToLevel(m_Light.Type.Active); + m_Light.Level.Active = EQEmu::lightsource::TypeToLevel(m_Light.Type.Active); return (m_Light.Level.Active != old_light_level); } diff --git a/zone/mob.h b/zone/mob.h index 32ddcc643..d5040e93e 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -364,7 +364,7 @@ public: virtual inline uint16 GetBaseRace() const { return base_race; } virtual inline uint8 GetBaseGender() const { return base_gender; } virtual inline uint16 GetDeity() const { return deity; } - virtual inline EQEmu::Deity::TypeBits GetDeityBit() { return EQEmu::Deity::ConvertDeityToDeityBit((EQEmu::Deity::Types)deity); } + virtual EQEmu::deity::DeityTypeBit GetDeityBit() { return EQEmu::deity::ConvertDeityToDeityBit((EQEmu::deity::DeityType)deity); } inline uint16 GetRace() const { return race; } inline uint8 GetGender() const { return gender; } inline uint8 GetTexture() const { return texture; } @@ -708,12 +708,12 @@ public: inline uint8 GetSpellLightType() { return m_Light.Type.Spell; } virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = 0; m_Light.Level.Equipment = 0; } - inline void SetSpellLightType(uint8 light_type) { m_Light.Type.Spell = (light_type & 0x0F); m_Light.Level.Spell = EQEmu::LightSource::TypeToLevel(m_Light.Type.Spell); } + inline void SetSpellLightType(uint8 light_type) { m_Light.Type.Spell = (light_type & 0x0F); m_Light.Level.Spell = EQEmu::lightsource::TypeToLevel(m_Light.Type.Spell); } inline uint8 GetActiveLightType() { return m_Light.Type.Active; } bool UpdateActiveLight(); // returns true if change, false if no change - EQEmu::LightSource::impl* GetLightProfile() { return &m_Light; } + EQEmu::lightsource::LightSourceProfile* GetLightProfile() { return &m_Light; } Mob* GetPet(); void SetPet(Mob* newpet); @@ -1185,7 +1185,7 @@ protected: glm::vec4 m_Delta; - EQEmu::LightSource::impl m_Light; + EQEmu::lightsource::LightSourceProfile m_Light; float fixedZ; EmuAppearance _appearance; diff --git a/zone/npc.cpp b/zone/npc.cpp index b7c017f96..7b8a21cef 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -529,8 +529,8 @@ void NPC::QueryLoot(Client* to) continue; } - EQEmu::SayLink::impl linker; - linker.SetLinkType(EQEmu::SayLink::LinkItemData); + EQEmu::saylink::SayLinkEngine linker; + linker.SetLinkType(linker.SayLinkItemData); linker.SetItemData(item); auto item_link = linker.GenerateLink(); @@ -748,15 +748,15 @@ void NPC::UpdateEquipmentLight() m_Light.Type.Equipment = 0; m_Light.Level.Equipment = 0; - for (int index = SLOT_BEGIN; index < EQEmu::Constants::EQUIPMENT_SIZE; ++index) { + for (int index = SLOT_BEGIN; index < EQEmu::constants::EQUIPMENT_SIZE; ++index) { if (index == SlotAmmo) { continue; } auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } - if (EQEmu::LightSource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) { + if (EQEmu::lightsource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) { m_Light.Type.Equipment = item->Light; - m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); + m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); } } @@ -768,14 +768,14 @@ void NPC::UpdateEquipmentLight() if (item->ItemClass != ItemClassCommon) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } - if (EQEmu::LightSource::TypeToLevel(item->Light)) + if (EQEmu::lightsource::TypeToLevel(item->Light)) general_light_type = item->Light; } - if (EQEmu::LightSource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) + if (EQEmu::lightsource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) m_Light.Type.Equipment = general_light_type; - m_Light.Level.Equipment = EQEmu::LightSource::TypeToLevel(m_Light.Type.Equipment); + m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); } void NPC::Depop(bool StartSpawnTimer) { diff --git a/zone/npc.h b/zone/npc.h index e788f414e..c07ccc947 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -495,7 +495,7 @@ protected: uint16 skills[HIGHEST_SKILL+1]; - uint32 equipment[EQEmu::Constants::EQUIPMENT_SIZE]; //this is an array of item IDs + uint32 equipment[EQEmu::constants::EQUIPMENT_SIZE]; //this is an array of item IDs uint32 herosforgemodel; //this is the Hero Forge Armor Model (i.e 63 or 84 or 203) uint16 d_melee_texture1; //this is an item Material value diff --git a/zone/object.cpp b/zone/object.cpp index dd3c822c2..f27fa2f02 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -324,7 +324,7 @@ void Object::Delete(bool reset_state) } const ItemInst* Object::GetItem(uint8 index) { - if (index < EQEmu::Constants::TYPE_WORLD_SIZE) { + if (index < EQEmu::constants::TYPE_WORLD_SIZE) { return m_inst->GetItem(index); } @@ -362,7 +362,7 @@ void Object::Close() { ItemInst* container = this->m_inst; if(container != nullptr) { - for (uint8 i = SUB_BEGIN; i < EQEmu::Constants::ITEM_CONTAINER_SIZE; i++) + for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::constants::ITEM_CONTAINER_SIZE; i++) { ItemInst* inst = container->PopItem(i); if(inst != nullptr) @@ -583,7 +583,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) EQApplicationPacket* outapp=new EQApplicationPacket(OP_ClientReady,0); sender->QueuePacket(outapp); safe_delete(outapp); - for (uint8 i = SUB_BEGIN; i < EQEmu::Constants::ITEM_CONTAINER_SIZE; i++) { + for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::constants::ITEM_CONTAINER_SIZE; i++) { const ItemInst* inst = m_inst->GetItem(i); if (inst) { //sender->GetInv().PutItem(i+4000,inst); diff --git a/zone/pets.cpp b/zone/pets.cpp index 714f80b3c..4679d1477 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -417,12 +417,12 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, // the base items for the pet. These are always loaded // so that a rank 1 suspend minion does not kill things // like the special back items some focused pets may receive. - uint32 petinv[EQEmu::Constants::EQUIPMENT_SIZE]; + uint32 petinv[EQEmu::constants::EQUIPMENT_SIZE]; memset(petinv, 0, sizeof(petinv)); const Item_Struct *item = 0; if (database.GetBasePetItems(record.equipmentset, petinv)) { - for (int i = 0; i < EQEmu::Constants::EQUIPMENT_SIZE; i++) + for (int i = 0; i < EQEmu::constants::EQUIPMENT_SIZE; i++) if (petinv[i]) { item = database.GetItem(petinv[i]); npc->AddLootDrop(item, &npc->itemlist, 0, 1, 127, true, true); @@ -572,7 +572,7 @@ void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) { strn0cpy(name, GetName(), 64); //save their items, we only care about what they are actually wearing - memcpy(items, equipment, sizeof(uint32) * EQEmu::Constants::EQUIPMENT_SIZE); + memcpy(items, equipment, sizeof(uint32) * EQEmu::constants::EQUIPMENT_SIZE); //save their buffs. for (int i=0; i < GetPetMaxTotalSlots(); i++) { @@ -660,7 +660,7 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { } //restore their equipment... - for (i = 0; i < EQEmu::Constants::EQUIPMENT_SIZE; i++) { + for (i = 0; i < EQEmu::constants::EQUIPMENT_SIZE; i++) { if(items[i] == 0) continue; @@ -722,7 +722,7 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) { { slot = atoi(row[0]); - if (slot >= EQEmu::Constants::EQUIPMENT_SIZE) + if (slot >= EQEmu::constants::EQUIPMENT_SIZE) continue; if (items[slot] == 0) diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index abfa27a01..4ab6f4eb1 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1307,8 +1307,8 @@ void QuestManager::itemlink(int item_id) { if (item == nullptr) return; - EQEmu::SayLink::impl linker; - linker.SetLinkType(EQEmu::SayLink::LinkItemData); + EQEmu::saylink::SayLinkEngine linker; + linker.SetLinkType(linker.SayLinkItemData); linker.SetItemData(item); auto item_link = linker.GenerateLink(); @@ -2441,12 +2441,12 @@ int QuestManager::collectitems(uint32 item_id, bool remove) int quantity = 0; int slot_id; - for (slot_id = EQEmu::Constants::GENERAL_BEGIN; slot_id <= EQEmu::Constants::GENERAL_END; ++slot_id) + for (slot_id = EQEmu::constants::GENERAL_BEGIN; slot_id <= EQEmu::constants::GENERAL_END; ++slot_id) { quantity += collectitems_processSlot(slot_id, item_id, remove); } - for (slot_id = EQEmu::Constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::Constants::GENERAL_BAGS_END; ++slot_id) + for (slot_id = EQEmu::constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::constants::GENERAL_BAGS_END; ++slot_id) { quantity += collectitems_processSlot(slot_id, item_id, remove); } @@ -2535,8 +2535,8 @@ const char* QuestManager::varlink(char* perltext, int item_id) { if (!item) return "INVALID ITEM ID IN VARLINK"; - EQEmu::SayLink::impl linker; - linker.SetLinkType(EQEmu::SayLink::LinkItemData); + EQEmu::saylink::SayLinkEngine linker; + linker.SetLinkType(linker.SayLinkItemData); linker.SetItemData(item); auto item_link = linker.GenerateLink(); @@ -2761,7 +2761,7 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam safe_delete_array(escaped_string); //Create the say link as an item link hash - EQEmu::SayLink::impl linker; + EQEmu::saylink::SayLinkEngine linker; linker.SetProxyItemID(SAYLINK_ITEM_ID); if (silent) linker.SetProxyAugment2ID(sayid); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 7e424cf09..3ef86c806 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -596,7 +596,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) if(wpn) { primaryweapondamage = GetWeaponDamage(other, wpn); backstab_dmg = wpn->GetItem()->BackstabDmg; - for (int i = 0; i < EQEmu::Constants::ITEM_COMMON_SIZE; ++i) + for (int i = 0; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) { ItemInst *aug = wpn->GetAugment(i); if(aug) @@ -729,7 +729,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { //first look for quivers int r; bool found = false; - for(r = EQEmu::Constants::GENERAL_BEGIN; r <= EQEmu::Constants::GENERAL_END; r++) { + for(r = EQEmu::constants::GENERAL_BEGIN; r <= EQEmu::constants::GENERAL_END; r++) { const ItemInst *pi = m_inv[r]; if(pi == nullptr || !pi->IsType(ItemClassContainer)) continue; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 445b97b39..151f20249 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1429,7 +1429,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } } - for (int x = EQEmu::Constants::MATERIAL_BEGIN; x <= EQEmu::Constants::MATERIAL_TINT_END; x++) + for (int x = EQEmu::constants::MATERIAL_BEGIN; x <= EQEmu::constants::MATERIAL_TINT_END; x++) SendWearChange(x); if (caster == this && @@ -1455,7 +1455,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove ); caster->SendAppearancePacket(AT_Size, static_cast(caster->GetTarget()->GetSize())); - for (int x = EQEmu::Constants::MATERIAL_BEGIN; x <= EQEmu::Constants::MATERIAL_TINT_END; x++) + for (int x = EQEmu::constants::MATERIAL_BEGIN; x <= EQEmu::constants::MATERIAL_TINT_END; x++) caster->SendWearChange(x); } } @@ -3809,7 +3809,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) else{ SendAppearancePacket(AT_Size, 6); } - for (int x = EQEmu::Constants::MATERIAL_BEGIN; x <= EQEmu::Constants::MATERIAL_TINT_END; x++){ + for (int x = EQEmu::constants::MATERIAL_BEGIN; x <= EQEmu::constants::MATERIAL_TINT_END; x++){ SendWearChange(x); } break; @@ -5126,7 +5126,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { const Item_Struct* TempItem = 0; - for (int x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::EQUIPMENT_END; x++) + for (int x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::EQUIPMENT_END; x++) { if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; @@ -5146,7 +5146,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { } } - for (int y = AUG_BEGIN; y < EQEmu::Constants::ITEM_COMMON_SIZE; ++y) + for (int y = AUG_INDEX_BEGIN; y < EQEmu::constants::ITEM_COMMON_SIZE; ++y) { if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; @@ -5261,7 +5261,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) int16 focus_max_real = 0; //item focus - for (int x = EQEmu::Constants::EQUIPMENT_BEGIN; x <= EQEmu::Constants::EQUIPMENT_END; x++) + for (int x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::EQUIPMENT_END; x++) { TempItem = nullptr; ItemInst* ins = GetInv().GetItem(x); @@ -5295,7 +5295,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) } } - for (int y = AUG_BEGIN; y < EQEmu::Constants::ITEM_COMMON_SIZE; ++y) + for (int y = AUG_INDEX_BEGIN; y < EQEmu::constants::ITEM_COMMON_SIZE; ++y) { ItemInst *aug = nullptr; aug = ins->GetAugment(y); @@ -5333,7 +5333,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) } //Tribute Focus - for (int x = EQEmu::Constants::TRIBUTE_BEGIN; x <= EQEmu::Constants::TRIBUTE_END; ++x) + for (int x = EQEmu::constants::TRIBUTE_BEGIN; x <= EQEmu::constants::TRIBUTE_END; ++x) { TempItem = nullptr; ItemInst* ins = GetInv().GetItem(x); @@ -5533,7 +5533,7 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { int16 focus_max_real = 0; //item focus - for (int i = 0; i < EQEmu::Constants::EQUIPMENT_SIZE; i++){ + for (int i = 0; i < EQEmu::constants::EQUIPMENT_SIZE; i++){ const Item_Struct *cur = database.GetItem(equipment[i]); if(!cur) diff --git a/zone/spells.cpp b/zone/spells.cpp index 7ed9e3012..fe738b444 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1206,7 +1206,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, if (inst == nullptr) break; - for (int r = AUG_BEGIN; r < EQEmu::Constants::ITEM_COMMON_SIZE; r++) { + for (int r = AUG_INDEX_BEGIN; r < EQEmu::constants::ITEM_COMMON_SIZE; r++) { const ItemInst* aug_i = inst->GetAugment(r); if (!aug_i) diff --git a/zone/tasks.cpp b/zone/tasks.cpp index a10dc4204..66137dd9b 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -2779,8 +2779,8 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN if(ItemID) { const Item_Struct* reward_item = database.GetItem(ItemID); - EQEmu::SayLink::impl linker; - linker.SetLinkType(EQEmu::SayLink::LinkItemData); + EQEmu::saylink::SayLinkEngine linker; + linker.SetLinkType(linker.SayLinkItemData); linker.SetItemData(reward_item); linker.SetTaskUse(); if (strlen(Tasks[TaskID]->Reward) != 0) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 61e0f2bc8..1048e7c34 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -69,7 +69,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme // Verify that no more than two items are in container to guarantee no inadvertant wipes. uint8 itemsFound = 0; - for (uint8 i = SLOT_BEGIN; i < EQEmu::Constants::TYPE_WORLD_SIZE; i++) + for (uint8 i = SLOT_BEGIN; i < EQEmu::constants::TYPE_WORLD_SIZE; i++) { const ItemInst* inst = container->GetItem(i); if (inst) @@ -222,7 +222,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme else { // Delete items in our inventory container... - for (uint8 i = SLOT_BEGIN; i < EQEmu::Constants::TYPE_WORLD_SIZE; i++) + for (uint8 i = SLOT_BEGIN; i < EQEmu::constants::TYPE_WORLD_SIZE; i++) { const ItemInst* inst = container->GetItem(i); if (inst) @@ -264,7 +264,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob uint32 some_id = 0; bool worldcontainer=false; - if (in_combine->container_slot == EQEmu::Legacy::SLOT_TRADESKILL) { + if (in_combine->container_slot == EQEmu::legacy::SLOT_TRADESKILL) { if(!worldo) { user->Message(13, "Error: Server is not aware of the tradeskill container you are attempting to use"); return; @@ -401,7 +401,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob safe_delete(outapp); database.DeleteWorldContainer(worldo->m_id, zone->GetZoneID()); } else{ - for (uint8 i = SLOT_BEGIN; i < EQEmu::Constants::TYPE_WORLD_SIZE; i++) { + for (uint8 i = SLOT_BEGIN; i < EQEmu::constants::TYPE_WORLD_SIZE; i++) { const ItemInst* inst = container->GetItem(i); if (inst) { user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot,i),0,true); @@ -1227,7 +1227,7 @@ bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint3 for (auto row = results.begin(); row != results.end(); ++row) { int ccnt = 0; - for (int x = SLOT_BEGIN; x < EQEmu::Constants::TYPE_WORLD_SIZE; x++) { + for (int x = SLOT_BEGIN; x < EQEmu::constants::TYPE_WORLD_SIZE; x++) { const ItemInst* inst = container->GetItem(x); if(!inst) continue; diff --git a/zone/trading.cpp b/zone/trading.cpp index 6cb081b2f..00850faf5 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -171,13 +171,13 @@ void Trade::SendItemData(const ItemInst* inst, int16 dest_slot_id) Client* with = mob->CastToClient(); Client* trader = owner->CastToClient(); if (with && with->IsClient()) { - with->SendItemPacket(dest_slot_id - EQEmu::Constants::TRADE_BEGIN, inst, ItemPacketTradeView); + with->SendItemPacket(dest_slot_id - EQEmu::constants::TRADE_BEGIN, inst, ItemPacketTradeView); if (inst->GetItem()->ItemClass == 1) { - for (uint16 i = SUB_BEGIN; i < EQEmu::Constants::ITEM_CONTAINER_SIZE; i++) { + for (uint16 i = SUB_INDEX_BEGIN; i < EQEmu::constants::ITEM_CONTAINER_SIZE; i++) { uint16 bagslot_id = Inventory::CalcSlotId(dest_slot_id, i); const ItemInst* bagitem = trader->GetInv().GetItem(bagslot_id); if (bagitem) { - with->SendItemPacket(bagslot_id - EQEmu::Constants::TRADE_BEGIN, bagitem, ItemPacketTradeView); + with->SendItemPacket(bagslot_id - EQEmu::constants::TRADE_BEGIN, bagitem, ItemPacketTradeView); } } } @@ -199,7 +199,7 @@ void Trade::LogTrade() uint8 item_count = 0; if (zone->tradevar != 0) { - for (uint16 i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_END; i++) { + for (uint16 i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_END; i++) { if (trader->GetInv().GetItem(i)) item_count++; } @@ -251,7 +251,7 @@ void Trade::LogTrade() if (item_count > 0) { strcat(logtext, "items {"); - for (uint16 i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_END; i++) { + for (uint16 i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_END; i++) { const ItemInst* inst = trader->GetInv().GetItem(i); if (!comma) @@ -267,7 +267,7 @@ void Trade::LogTrade() strcat(logtext, item_num); if (inst->IsType(ItemClassContainer)) { - for (uint8 j = SUB_BEGIN; j < EQEmu::Constants::ITEM_CONTAINER_SIZE; j++) { + for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::constants::ITEM_CONTAINER_SIZE; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { strcat(logtext, ","); @@ -303,7 +303,7 @@ void Trade::DumpTrade() return; Client* trader = owner->CastToClient(); - for (uint16 i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_END; i++) { + for (uint16 i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_END; i++) { const ItemInst* inst = trader->GetInv().GetItem(i); if (inst) { @@ -312,7 +312,7 @@ void Trade::DumpTrade() i, ((inst->IsType(ItemClassContainer)) ? "True" : "False")); if (inst->IsType(ItemClassContainer)) { - for (uint8 j = SUB_BEGIN; j < EQEmu::Constants::ITEM_CONTAINER_SIZE; j++) { + for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::constants::ITEM_CONTAINER_SIZE; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { Log.Out(Logs::Detail, Logs::Trading, "\tBagItem %i (Charges=%i, Slot=%i)", @@ -332,7 +332,7 @@ void Client::ResetTrade() { AddMoneyToPP(trade->cp, trade->sp, trade->gp, trade->pp, true); // step 1: process bags - for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst && inst->IsType(ItemClassContainer)) { @@ -351,7 +351,7 @@ void Client::ResetTrade() { } // step 2a: process stackables - for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { @@ -398,11 +398,11 @@ void Client::ResetTrade() { // step 2b: adjust trade stack bias // (if any partial stacks exist before the final stack, FindFreeSlotForTradeItem() will return that slot in step 3 and an overwrite will occur) - for (int16 trade_slot = EQEmu::Constants::TRADE_END; trade_slot >= EQEmu::Constants::TRADE_BEGIN; --trade_slot) { + for (int16 trade_slot = EQEmu::constants::TRADE_END; trade_slot >= EQEmu::constants::TRADE_BEGIN; --trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { - for (int16 bias_slot = EQEmu::Constants::TRADE_BEGIN; bias_slot <= EQEmu::Constants::TRADE_END; ++bias_slot) { + for (int16 bias_slot = EQEmu::constants::TRADE_BEGIN; bias_slot <= EQEmu::constants::TRADE_END; ++bias_slot) { if (bias_slot >= trade_slot) break; @@ -432,7 +432,7 @@ void Client::ResetTrade() { } // step 3: process everything else - for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst) { @@ -487,7 +487,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } // step 1: process bags - for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst && inst->IsType(ItemClassContainer)) { @@ -523,7 +523,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st qs_audit->char1_count += detail->charges; //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { - for (uint8 sub_slot = SUB_BEGIN; (sub_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items + for (uint8 sub_slot = SUB_INDEX_BEGIN; (sub_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items const ItemInst* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { @@ -571,7 +571,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } // step 2a: process stackables - for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { @@ -653,11 +653,11 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // step 2b: adjust trade stack bias // (if any partial stacks exist before the final stack, FindFreeSlotForTradeItem() will return that slot in step 3 and an overwrite will occur) - for (int16 trade_slot = EQEmu::Constants::TRADE_END; trade_slot >= EQEmu::Constants::TRADE_BEGIN; --trade_slot) { + for (int16 trade_slot = EQEmu::constants::TRADE_END; trade_slot >= EQEmu::constants::TRADE_BEGIN; --trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { - for (int16 bias_slot = EQEmu::Constants::TRADE_BEGIN; bias_slot <= EQEmu::Constants::TRADE_END; ++bias_slot) { + for (int16 bias_slot = EQEmu::constants::TRADE_BEGIN; bias_slot <= EQEmu::constants::TRADE_END; ++bias_slot) { if (bias_slot >= trade_slot) break; @@ -706,7 +706,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } // step 3: process everything else - for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst) { @@ -743,7 +743,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // 'step 3' should never really see containers..but, just in case... //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { - for (uint8 sub_slot = SUB_BEGIN; (sub_slot < EQEmu::Constants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items + for (uint8 sub_slot = SUB_INDEX_BEGIN; (sub_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items const ItemInst* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { @@ -820,7 +820,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } if(qs_log) { // This can be incorporated below when revisions are made - for (int16 trade_slot = EQEmu::Constants::TRADE_BEGIN; trade_slot <= EQEmu::Constants::TRADE_NPC_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_NPC_END; ++trade_slot) { const ItemInst* trade_inst = m_inv[trade_slot]; if(trade_inst) { @@ -841,7 +841,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st qs_audit->char_count += detail->charges; if(trade_inst->IsType(ItemClassContainer)) { - for (uint8 sub_slot = SUB_BEGIN; sub_slot < trade_inst->GetItem()->BagSlots; ++sub_slot) { + for (uint8 sub_slot = SUB_INDEX_BEGIN; sub_slot < trade_inst->GetItem()->BagSlots; ++sub_slot) { const ItemInst* trade_baginst = trade_inst->GetItem(sub_slot); if(trade_baginst) { @@ -875,7 +875,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st std::vector item_list; std::list items; - for (int i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_NPC_END; ++i) { + for (int i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_NPC_END; ++i) { ItemInst *inst = m_inv.GetItem(i); if(inst) { items.push_back(inst); @@ -891,7 +891,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if(GetGM() || (item->NoDrop != 0 && inst->IsAttuned() == false)) { // pets need to look inside bags and try to equip items found there if(item->ItemClass == ItemClassContainer && item->BagSlots > 0) { - for(int16 bslot = SUB_BEGIN; bslot < item->BagSlots; bslot++) { + for (int16 bslot = SUB_INDEX_BEGIN; bslot < item->BagSlots; bslot++) { const ItemInst* baginst = inst->GetItem(bslot); if (baginst) { const Item_Struct* bagitem = baginst->GetItem(); @@ -948,8 +948,8 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } ItemInst *insts[4] = { 0 }; - for (int i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_NPC_END; ++i) { - insts[i - EQEmu::Constants::TRADE_BEGIN] = m_inv.PopItem(i); + for (int i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_NPC_END; ++i) { + insts[i - EQEmu::constants::TRADE_BEGIN] = m_inv.PopItem(i); database.SaveInventory(CharacterID(), nullptr, i); } @@ -968,7 +968,7 @@ bool Client::CheckTradeLoreConflict(Client* other) if (!other) return true; // Move each trade slot into free inventory slot - for (int16 i = EQEmu::Constants::TRADE_BEGIN; i <= EQEmu::Constants::TRADE_END; i++){ + for (int16 i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_END; i++){ const ItemInst* inst = m_inv[i]; if (inst && inst->GetItem()) { @@ -977,7 +977,7 @@ bool Client::CheckTradeLoreConflict(Client* other) } } - for (int16 i = EQEmu::Constants::TRADE_BAGS_BEGIN; i <= EQEmu::Constants::TRADE_BAGS_END; i++){ + for (int16 i = EQEmu::constants::TRADE_BAGS_BEGIN; i <= EQEmu::constants::TRADE_BAGS_END; i++){ const ItemInst* inst = m_inv[i]; if (inst && inst->GetItem()) { @@ -1232,10 +1232,10 @@ uint32 Client::FindTraderItemSerialNumber(int32 ItemID) { ItemInst* item = nullptr; uint16 SlotID = 0; - for (int i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++){ + for (int i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++){ item = this->GetInv().GetItem(i); if (item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; x++) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1255,10 +1255,10 @@ ItemInst* Client::FindTraderItemBySerialNumber(int32 SerialNumber){ ItemInst* item = nullptr; uint16 SlotID = 0; - for (int i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++){ + for (int i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++){ item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; x++) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1286,10 +1286,10 @@ GetItems_Struct* Client::GetTraderItems(){ uint8 ndx = 0; - for (int i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { + for (int i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; x++) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; x++) { SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1310,10 +1310,10 @@ uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){ const ItemInst* item= nullptr; uint16 SlotID = 0; - for (int i = EQEmu::Constants::GENERAL_BEGIN; i <= EQEmu::Constants::GENERAL_END; i++) { + for (int i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_BEGIN; x < EQEmu::Constants::ITEM_CONTAINER_SIZE; x++){ + for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; x++){ SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); diff --git a/zone/tribute.cpp b/zone/tribute.cpp index 084712f9a..077e97bee 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -66,7 +66,7 @@ void Client::ToggleTribute(bool enabled) { int r; uint32 cost = 0; uint32 level = GetLevel(); - for (r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { uint32 tid = m_pp.tributes[r].tribute; if(tid == TRIBUTE_NONE) continue; @@ -119,7 +119,7 @@ void Client::DoTributeUpdate() { tis->tribute_master_id = tribute_master_id; //Dont know what this is for int r; - for (r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { if(m_pp.tributes[r].tribute != TRIBUTE_NONE) { tis->tributes[r] = m_pp.tributes[r].tribute; tis->tiers[r] = m_pp.tributes[r].tier; @@ -134,24 +134,24 @@ void Client::DoTributeUpdate() { if(m_pp.tribute_active) { //send and equip tribute items... - for (r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { uint32 tid = m_pp.tributes[r].tribute; if(tid == TRIBUTE_NONE) { - if (m_inv[EQEmu::Constants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EQEmu::Constants::TRIBUTE_BEGIN + r, 0, false); + if (m_inv[EQEmu::constants::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::constants::TRIBUTE_BEGIN + r, 0, false); continue; } if(tribute_list.count(tid) != 1) { - if (m_inv[EQEmu::Constants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EQEmu::Constants::TRIBUTE_BEGIN + r, 0, false); + if (m_inv[EQEmu::constants::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::constants::TRIBUTE_BEGIN + r, 0, false); continue; } //sanity check if(m_pp.tributes[r].tier >= MAX_TRIBUTE_TIERS) { - if (m_inv[EQEmu::Constants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EQEmu::Constants::TRIBUTE_BEGIN + r, 0, false); + if (m_inv[EQEmu::constants::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::constants::TRIBUTE_BEGIN + r, 0, false); m_pp.tributes[r].tier = 0; continue; } @@ -165,15 +165,15 @@ void Client::DoTributeUpdate() { if(inst == nullptr) continue; - PutItemInInventory(EQEmu::Constants::TRIBUTE_BEGIN + r, *inst, false); - SendItemPacket(EQEmu::Constants::TRIBUTE_BEGIN + r, inst, ItemPacketTributeItem); + PutItemInInventory(EQEmu::constants::TRIBUTE_BEGIN + r, *inst, false); + SendItemPacket(EQEmu::constants::TRIBUTE_BEGIN + r, inst, ItemPacketTributeItem); safe_delete(inst); } } else { //unequip tribute items... - for (r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { - if (m_inv[EQEmu::Constants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EQEmu::Constants::TRIBUTE_BEGIN + r, 0, false); + for (r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { + if (m_inv[EQEmu::constants::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::constants::TRIBUTE_BEGIN + r, 0, false); } } CalcBonuses(); @@ -192,7 +192,7 @@ void Client::SendTributeTimer() { void Client::ChangeTributeSettings(TributeInfo_Struct *t) { int r; - for (r = 0; r < EQEmu::Constants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { m_pp.tributes[r].tribute = TRIBUTE_NONE; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 0fc194c1e..49ac1ff49 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -487,7 +487,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, ItemInst* container) uint8 index = (uint8)atoi(row[0]); uint32 item_id = (uint32)atoi(row[1]); int8 charges = (int8)atoi(row[2]); - uint32 aug[EQEmu::Constants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::constants::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoi(row[3]); aug[1] = (uint32)atoi(row[4]); aug[2] = (uint32)atoi(row[5]); @@ -497,7 +497,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, ItemInst* container) ItemInst* inst = database.CreateItem(item_id, charges); if (inst && inst->GetItem()->ItemClass == ItemClassCommon) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) if (aug[i]) inst->PutAugment(&database, i, aug[i]); // Put item inside world container @@ -520,17 +520,17 @@ void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const It DeleteWorldContainer(parent_id,zone_id); // Save all 10 items, if they exist - for (uint8 index = SUB_BEGIN; index < EQEmu::Constants::ITEM_CONTAINER_SIZE; index++) { + for (uint8 index = SUB_INDEX_BEGIN; index < EQEmu::constants::ITEM_CONTAINER_SIZE; index++) { ItemInst* inst = container->GetItem(index); if (!inst) continue; uint32 item_id = inst->GetItem()->ID; - uint32 augslot[EQEmu::Constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; + uint32 augslot[EQEmu::constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; if (inst->IsType(ItemClassCommon)) { - for (int i = AUG_BEGIN; i < EQEmu::Constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { ItemInst *auginst=inst->GetAugment(i); augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } @@ -1181,11 +1181,11 @@ bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp) { std::string query = StringFormat("SELECT `bandolier_id`, `bandolier_slot`, `item_id`, `icon`, `bandolier_name` FROM `character_bandolier` WHERE `id` = %u LIMIT %u", - character_id, EQEmu::Constants::BANDOLIERS_SIZE); + character_id, EQEmu::constants::BANDOLIERS_SIZE); auto results = database.QueryDatabase(query); int i = 0; int r = 0; int si = 0; - for (i = 0; i < EQEmu::Constants::BANDOLIERS_SIZE; i++) { + for (i = 0; i < EQEmu::constants::BANDOLIERS_SIZE; i++) { pp->bandoliers[i].Name[0] = '\0'; - for (int si = 0; si < EQEmu::Constants::BANDOLIER_ITEM_COUNT; si++) { + for (int si = 0; si < EQEmu::constants::BANDOLIER_ITEM_COUNT; si++) { pp->bandoliers[i].Items[si].ID = 0; pp->bandoliers[i].Items[si].Icon = 0; pp->bandoliers[i].Items[si].Name[0] = '\0'; @@ -1219,7 +1219,7 @@ bool ZoneDatabase::LoadCharacterTribute(uint32 character_id, PlayerProfile_Struc std::string query = StringFormat("SELECT `tier`, `tribute` FROM `character_tribute` WHERE `id` = %u", character_id); auto results = database.QueryDatabase(query); int i = 0; - for (i = 0; i < EQEmu::Constants::TRIBUTE_SIZE; i++){ + for (i = 0; i < EQEmu::constants::TRIBUTE_SIZE; i++){ pp->tributes[i].tribute = 0xFFFFFFFF; pp->tributes[i].tier = 0; } @@ -1238,10 +1238,10 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc { std::string query = StringFormat("SELECT `potion_id`, `item_id`, `icon` FROM `character_potionbelt` WHERE `id` = %u LIMIT %u", - character_id, EQEmu::Constants::POTION_BELT_ITEM_COUNT); + character_id, EQEmu::constants::POTION_BELT_ITEM_COUNT); auto results = database.QueryDatabase(query); int i = 0; - for (i = 0; i < EQEmu::Constants::POTION_BELT_ITEM_COUNT; i++) { + for (i = 0; i < EQEmu::constants::POTION_BELT_ITEM_COUNT; i++) { pp->potionbelt.Items[i].Icon = 0; pp->potionbelt.Items[i].ID = 0; pp->potionbelt.Items[i].Name[0] = '\0'; @@ -1339,7 +1339,7 @@ bool ZoneDatabase::SaveCharacterTribute(uint32 character_id, PlayerProfile_Struc std::string query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query); /* Save Tributes only if we have values... */ - for (int i = 0; i < EQEmu::Constants::TRIBUTE_SIZE; i++){ + for (int i = 0; i < EQEmu::constants::TRIBUTE_SIZE; i++){ if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != TRIBUTE_NONE){ std::string query = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); QueryDatabase(query); @@ -2092,7 +2092,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load else { auto armorTint_row = armortint_results.begin(); - for (int index = EQEmu::Constants::MATERIAL_BEGIN; index <= EQEmu::Constants::MATERIAL_END; index++) { + for (int index = EQEmu::constants::MATERIAL_BEGIN; index <= EQEmu::constants::MATERIAL_END; index++) { temp_npctype_data->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; temp_npctype_data->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; temp_npctype_data->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); @@ -2307,7 +2307,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; if (armor_tint_id == 0) - for (int index = MaterialChest; index <= EQEmu::Constants::MATERIAL_END; index++) + for (int index = MaterialChest; index <= EQEmu::constants::MATERIAL_END; index++) tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0]; else if (tmpNPCType->armor_tint[0] == 0) { std::string armorTint_query = StringFormat("SELECT red1h, grn1h, blu1h, " @@ -2327,7 +2327,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client else { auto armorTint_row = results.begin(); - for (int index = EQEmu::Constants::MATERIAL_BEGIN; index <= EQEmu::Constants::MATERIAL_END; index++) { + for (int index = EQEmu::constants::MATERIAL_BEGIN; index <= EQEmu::constants::MATERIAL_END; index++) { tmpNPCType->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); @@ -2684,7 +2684,7 @@ void ZoneDatabase::LoadMercEquipment(Merc *merc) { int itemCount = 0; for(auto row = results.begin(); row != results.end(); ++row) { - if (itemCount == EQEmu::Constants::EQUIPMENT_SIZE) + if (itemCount == EQEmu::constants::EQUIPMENT_SIZE) break; if(atoi(row[0]) == 0) @@ -3199,7 +3199,7 @@ void ZoneDatabase::SavePetInfo(Client *client) query.clear(); // pet inventory! - for (int index = EQEmu::Constants::EQUIPMENT_BEGIN; index <= EQEmu::Constants::EQUIPMENT_END; index++) { + for (int index = EQEmu::constants::EQUIPMENT_BEGIN; index <= EQEmu::constants::EQUIPMENT_END; index++) { if (!petinfo->Items[index]) continue; @@ -3331,7 +3331,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) continue; int slot = atoi(row[1]); - if (slot < EQEmu::Constants::EQUIPMENT_BEGIN || slot > EQEmu::Constants::EQUIPMENT_END) + if (slot < EQEmu::constants::EQUIPMENT_BEGIN || slot > EQEmu::constants::EQUIPMENT_END) continue; pi->Items[slot] = atoul(row[2]); diff --git a/zone/zonedb.h b/zone/zonedb.h index 250c7106d..3706131a9 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -126,7 +126,7 @@ struct PetInfo { uint32 Mana; float size; SpellBuff_Struct Buffs[BUFF_COUNT]; - uint32 Items[EQEmu::Constants::EQUIPMENT_SIZE]; + uint32 Items[EQEmu::constants::EQUIPMENT_SIZE]; char Name[64]; }; From 1ee32b4a306f5c737065e7f7dccf757755f69e64 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 20 Apr 2016 17:40:41 -0400 Subject: [PATCH 052/693] Removed type dec from EQEmu::legacy::InventorySlots --- common/emu_legacy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/emu_legacy.h b/common/emu_legacy.h index 640e55b1b..93f6e83d4 100644 --- a/common/emu_legacy.h +++ b/common/emu_legacy.h @@ -27,7 +27,7 @@ namespace EQEmu { // this is for perl and other legacy systems namespace legacy { - enum InventorySlot : int16 { + enum InventorySlot { SLOT_CHARM = 0, SLOT_EAR01 = 1, SLOT_HEAD = 2, From 1693797adb0d24c3fea6e184e9a2308bba86183c Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 21 Apr 2016 18:36:22 -0400 Subject: [PATCH 053/693] Update to EQEmu::deity function linkage --- common/deity.cpp | 2 +- common/deity.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/deity.cpp b/common/deity.cpp index e1f65a564..228a7a81e 100644 --- a/common/deity.cpp +++ b/common/deity.cpp @@ -105,7 +105,7 @@ EQEmu::deity::DeityType EQEmu::deity::ConvertDeityBitToDeity(DeityTypeBit deity_ }; } -const char* EQEmu::deity::GetDeityName(DeityType deity) +const char* EQEmu::deity::DeityName(DeityType deity) { switch (deity) { case DeityBertoxxulous: diff --git a/common/deity.h b/common/deity.h index d9602afa8..fe8dce938 100644 --- a/common/deity.h +++ b/common/deity.h @@ -67,9 +67,9 @@ namespace EQEmu bit_DeityVeeshan = 0x00010000 }; - DeityTypeBit ConvertDeityToDeityBit(DeityType deity); - DeityType ConvertDeityBitToDeity(DeityTypeBit deity_bit); - const char* GetDeityName(DeityType deity); + extern DeityTypeBit ConvertDeityToDeityBit(DeityType deity); + extern DeityType ConvertDeityBitToDeity(DeityTypeBit deity_bit); + extern const char* DeityName(DeityType deity); } } From 59e601733e8a9b872d2d5b1e29edfd39dbcc9346 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 21 Apr 2016 19:16:30 -0400 Subject: [PATCH 054/693] Update to EQEmu::constants function linkage --- common/emu_constants.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/emu_constants.h b/common/emu_constants.h index 6f365d4e4..b5b0ef561 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -49,12 +49,12 @@ namespace EQEmu static const size_t CHARACTER_CREATION_LIMIT = RoF2::consts::CHARACTER_CREATION_LIMIT; // inventory - static uint16 InventoryTypeSize(int16 type_index); - //static const char* InventoryLocationName(Location_Struct location); - static const char* InventoryTypeName(int16 type_index); - static const char* InventorySlotName(int16 slot_index); - static const char* InventorySubName(int16 sub_index); - static const char* InventoryAugName(int16 aug_index); + extern uint16 InventoryTypeSize(int16 type_index); + //extern const char* InventoryLocationName(Location_Struct location); + extern const char* InventoryTypeName(int16 type_index); + extern const char* InventorySlotName(int16 slot_index); + extern const char* InventorySubName(int16 sub_index); + extern const char* InventoryAugName(int16 aug_index); // these are currently hard-coded for existing inventory system..do not use in place of special client version handlers until ready static const uint16 TYPE_POSSESSIONS_SIZE = SlotCount; From 57b3652819818d2bc670e19f14ba72a5ecb9b3b2 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 21 Apr 2016 19:45:52 -0400 Subject: [PATCH 055/693] Update to EQEmu::limits function linkage --- common/eq_limits.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/common/eq_limits.h b/common/eq_limits.h index 4d9d5e020..4e68fa5d3 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -45,36 +45,36 @@ namespace EQEmu namespace limits { // client version validation (checks to avoid crashing zone server when accessing reference arrays) // use this inside of class Client (limits to actual clients) - bool IsValidPCClientVersion(ClientVersion clientVersion); - ClientVersion ValidatePCClientVersion(ClientVersion clientVersion); + extern bool IsValidPCClientVersion(ClientVersion clientVersion); + extern ClientVersion ValidatePCClientVersion(ClientVersion clientVersion); // basically..any non-client classes - do not invoke when setting a valid client - bool IsValidNPCClientVersion(ClientVersion clientVersion); - ClientVersion ValidateNPCClientVersion(ClientVersion clientVersion); + extern bool IsValidNPCClientVersion(ClientVersion clientVersion); + extern ClientVersion ValidateNPCClientVersion(ClientVersion clientVersion); // these are 'universal' - do not invoke when setting a valid client - bool IsValidMobClientVersion(ClientVersion clientVersion); - ClientVersion ValidateMobClientVersion(ClientVersion clientVersion); + extern bool IsValidMobClientVersion(ClientVersion clientVersion); + extern ClientVersion ValidateMobClientVersion(ClientVersion clientVersion); // database - size_t CharacterCreationLimit(ClientVersion clientVersion); + extern size_t CharacterCreationLimit(ClientVersion clientVersion); // inventory - uint16 InventoryMapSize(int16 indexMap, ClientVersion clientVersion); - uint64 PossessionsBitmask(ClientVersion clientVersion); - uint64 EquipmentBitmask(ClientVersion clientVersion); - uint64 GeneralBitmask(ClientVersion clientVersion); - uint64 CursorBitmask(ClientVersion clientVersion); + extern uint16 InventoryMapSize(int16 indexMap, ClientVersion clientVersion); + extern uint64 PossessionsBitmask(ClientVersion clientVersion); + extern uint64 EquipmentBitmask(ClientVersion clientVersion); + extern uint64 GeneralBitmask(ClientVersion clientVersion); + extern uint64 CursorBitmask(ClientVersion clientVersion); - bool AllowsEmptyBagInBag(ClientVersion clientVersion); - bool AllowsClickCastFromBag(ClientVersion clientVersion); + extern bool AllowsEmptyBagInBag(ClientVersion clientVersion); + extern bool AllowsClickCastFromBag(ClientVersion clientVersion); // items - uint16 ItemCommonSize(ClientVersion clientVersion); - uint16 ItemContainerSize(ClientVersion clientVersion); + extern uint16 ItemCommonSize(ClientVersion clientVersion); + extern uint16 ItemContainerSize(ClientVersion clientVersion); // player profile - bool CoinHasWeight(ClientVersion clientVersion); + extern bool CoinHasWeight(ClientVersion clientVersion); } } From e87e4d07f0e6ba5ddc65b302b8b000503410f18f Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 21 Apr 2016 19:55:46 -0400 Subject: [PATCH 056/693] Update to EQEmu::lightsource function linkage --- common/light_source.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/light_source.h b/common/light_source.h index fa4f09003..db93eaeb3 100644 --- a/common/light_source.h +++ b/common/light_source.h @@ -99,8 +99,8 @@ namespace EQEmu } Level; }; - uint8 TypeToLevel(uint8 light_type); - bool IsLevelGreater(uint8 left_type, uint8 right_type); + extern uint8 TypeToLevel(uint8 light_type); + extern bool IsLevelGreater(uint8 left_type, uint8 right_type); }; } From 6bc60391fb12b09c1b82c08b77ff8fd0c7466523 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 21 Apr 2016 21:43:58 -0400 Subject: [PATCH 057/693] Update to EQEmu::saylink function linkage --- common/say_link.h | 190 ++++++++++++++++++++++++---------------------- 1 file changed, 98 insertions(+), 92 deletions(-) diff --git a/common/say_link.h b/common/say_link.h index 60c7d7db0..c422bf7b2 100644 --- a/common/say_link.h +++ b/common/say_link.h @@ -25,108 +25,114 @@ #include -class ItemInst; struct Item_Struct; struct ServerLootItem_Struct; +class ItemInst; namespace EQEmu { namespace saylink { - // Current server mask: EQClientRoF2 - struct SayLinkBody_Struct { - uint8 unknown_1; /* %1X */ - uint32 item_id; /* %05X */ - uint32 augment_1; /* %05X */ - uint32 augment_2; /* %05X */ - uint32 augment_3; /* %05X */ - uint32 augment_4; /* %05X */ - uint32 augment_5; /* %05X */ - uint32 augment_6; /* %05X */ - uint8 is_evolving; /* %1X */ - uint32 evolve_group; /* %05X */ - uint8 evolve_level; /* %02X */ - uint32 ornament_icon; /* %05X */ - int hash; /* %08X */ - }; + struct SayLinkBody_Struct; // Current server mask: EQClientRoF2 - class SayLinkEngine { - public: - enum SayLinkType { - SayLinkBlank = 0, - SayLinkItemData, - SayLinkLootItem, - SayLinkItemInst - }; + class SayLinkEngine; - SayLinkEngine(); - - void SetLinkType(SayLinkType link_type) { m_LinkType = link_type; } - void SetItemData(const Item_Struct* item_data) { m_ItemData = item_data; } - void SetLootData(const ServerLootItem_Struct* loot_data) { m_LootData = loot_data; } - void SetItemInst(const ItemInst* item_inst) { m_ItemInst = item_inst; } - - // mainly for saylinks..but, not limited to - void SetProxyUnknown1(uint8 proxy_unknown_1) { m_Proxy_unknown_1 = proxy_unknown_1; } - void SetProxyItemID(uint32 proxy_item_id) { m_ProxyItemID = proxy_item_id; } - void SetProxyAugment1ID(uint32 proxy_augment_id) { m_ProxyAugment1ID = proxy_augment_id; } - void SetProxyAugment2ID(uint32 proxy_augment_id) { m_ProxyAugment2ID = proxy_augment_id; } - void SetProxyAugment3ID(uint32 proxy_augment_id) { m_ProxyAugment3ID = proxy_augment_id; } - void SetProxyAugment4ID(uint32 proxy_augment_id) { m_ProxyAugment4ID = proxy_augment_id; } - void SetProxyAugment5ID(uint32 proxy_augment_id) { m_ProxyAugment5ID = proxy_augment_id; } - void SetProxyAugment6ID(uint32 proxy_augment_id) { m_ProxyAugment6ID = proxy_augment_id; } - void SetProxyIsEvolving(uint8 proxy_is_evolving) { m_ProxyIsEvolving = proxy_is_evolving; } - void SetProxyEvolveGroup(uint32 proxy_evolve_group) { m_ProxyEvolveGroup = proxy_evolve_group; } - void SetProxyEvolveLevel(uint8 proxy_evolve_level) { m_ProxyEvolveLevel = proxy_evolve_level; } - void SetProxyOrnamentIcon(uint32 proxy_ornament_icon) { m_ProxyOrnamentIcon = proxy_ornament_icon; } - void SetProxyHash(int proxy_hash) { m_ProxyHash = proxy_hash; } - - void SetProxyText(const char* proxy_text) { m_ProxyText = proxy_text; } // overrides standard text use - void SetTaskUse() { m_TaskUse = true; } - - std::string GenerateLink(); - bool LinkError() { return m_Error; } - - std::string Link() { return m_Link; } // contains full string format: '/12x' '' '' '/12x' - std::string LinkBody() { return m_LinkBody; } // contains string format: '' - std::string LinkText() { return m_LinkText; } // contains string format: '' - - void Reset(); - - private: - void generate_body(); - void generate_text(); - - int m_LinkType; - const Item_Struct* m_ItemData; - const ServerLootItem_Struct* m_LootData; - const ItemInst* m_ItemInst; - - uint8 m_Proxy_unknown_1; - uint32 m_ProxyItemID; - uint32 m_ProxyAugment1ID; - uint32 m_ProxyAugment2ID; - uint32 m_ProxyAugment3ID; - uint32 m_ProxyAugment4ID; - uint32 m_ProxyAugment5ID; - uint32 m_ProxyAugment6ID; - uint8 m_ProxyIsEvolving; - uint32 m_ProxyEvolveGroup; - uint8 m_ProxyEvolveLevel; - uint32 m_ProxyOrnamentIcon; - int m_ProxyHash; - const char* m_ProxyText; - bool m_TaskUse; - SayLinkBody_Struct m_LinkBodyStruct; - std::string m_Link; - std::string m_LinkBody; - std::string m_LinkText; - bool m_Error; - }; - - bool DegenerateLinkBody(SayLinkBody_Struct& say_Link_body_struct, const std::string& say_link_body); - bool GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct); + extern bool DegenerateLinkBody(SayLinkBody_Struct& say_Link_body_struct, const std::string& say_link_body); + extern bool GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct); } } + +struct EQEmu::saylink::SayLinkBody_Struct +{ + uint8 unknown_1; /* %1X */ + uint32 item_id; /* %05X */ + uint32 augment_1; /* %05X */ + uint32 augment_2; /* %05X */ + uint32 augment_3; /* %05X */ + uint32 augment_4; /* %05X */ + uint32 augment_5; /* %05X */ + uint32 augment_6; /* %05X */ + uint8 is_evolving; /* %1X */ + uint32 evolve_group; /* %05X */ + uint8 evolve_level; /* %02X */ + uint32 ornament_icon; /* %05X */ + int hash; /* %08X */ +}; + +class EQEmu::saylink::SayLinkEngine +{ +public: + enum SayLinkType { + SayLinkBlank = 0, + SayLinkItemData, + SayLinkLootItem, + SayLinkItemInst + }; + + SayLinkEngine(); + + void SetLinkType(SayLinkType link_type) { m_LinkType = link_type; } + void SetItemData(const Item_Struct* item_data) { m_ItemData = item_data; } + void SetLootData(const ServerLootItem_Struct* loot_data) { m_LootData = loot_data; } + void SetItemInst(const ItemInst* item_inst) { m_ItemInst = item_inst; } + + // mainly for saylinks..but, not limited to + void SetProxyUnknown1(uint8 proxy_unknown_1) { m_Proxy_unknown_1 = proxy_unknown_1; } + void SetProxyItemID(uint32 proxy_item_id) { m_ProxyItemID = proxy_item_id; } + void SetProxyAugment1ID(uint32 proxy_augment_id) { m_ProxyAugment1ID = proxy_augment_id; } + void SetProxyAugment2ID(uint32 proxy_augment_id) { m_ProxyAugment2ID = proxy_augment_id; } + void SetProxyAugment3ID(uint32 proxy_augment_id) { m_ProxyAugment3ID = proxy_augment_id; } + void SetProxyAugment4ID(uint32 proxy_augment_id) { m_ProxyAugment4ID = proxy_augment_id; } + void SetProxyAugment5ID(uint32 proxy_augment_id) { m_ProxyAugment5ID = proxy_augment_id; } + void SetProxyAugment6ID(uint32 proxy_augment_id) { m_ProxyAugment6ID = proxy_augment_id; } + void SetProxyIsEvolving(uint8 proxy_is_evolving) { m_ProxyIsEvolving = proxy_is_evolving; } + void SetProxyEvolveGroup(uint32 proxy_evolve_group) { m_ProxyEvolveGroup = proxy_evolve_group; } + void SetProxyEvolveLevel(uint8 proxy_evolve_level) { m_ProxyEvolveLevel = proxy_evolve_level; } + void SetProxyOrnamentIcon(uint32 proxy_ornament_icon) { m_ProxyOrnamentIcon = proxy_ornament_icon; } + void SetProxyHash(int proxy_hash) { m_ProxyHash = proxy_hash; } + + void SetProxyText(const char* proxy_text) { m_ProxyText = proxy_text; } // overrides standard text use + void SetTaskUse() { m_TaskUse = true; } + + std::string GenerateLink(); + bool LinkError() { return m_Error; } + + std::string Link() { return m_Link; } // contains full string format: '/12x' '' '' '/12x' + std::string LinkBody() { return m_LinkBody; } // contains string format: '' + std::string LinkText() { return m_LinkText; } // contains string format: '' + + void Reset(); + +private: + void generate_body(); + void generate_text(); + + int m_LinkType; + const Item_Struct* m_ItemData; + const ServerLootItem_Struct* m_LootData; + const ItemInst* m_ItemInst; + + uint8 m_Proxy_unknown_1; + uint32 m_ProxyItemID; + uint32 m_ProxyAugment1ID; + uint32 m_ProxyAugment2ID; + uint32 m_ProxyAugment3ID; + uint32 m_ProxyAugment4ID; + uint32 m_ProxyAugment5ID; + uint32 m_ProxyAugment6ID; + uint8 m_ProxyIsEvolving; + uint32 m_ProxyEvolveGroup; + uint8 m_ProxyEvolveLevel; + uint32 m_ProxyOrnamentIcon; + int m_ProxyHash; + const char* m_ProxyText; + bool m_TaskUse; + SayLinkBody_Struct m_LinkBodyStruct; + std::string m_Link; + std::string m_LinkBody; + std::string m_LinkText; + bool m_Error; +}; + #endif /* COMMON_SAY_LINK_H */ From b3475d7b501e0677d5e9eb8fae264ad75f7e9213 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 22 Apr 2016 03:49:17 -0400 Subject: [PATCH 058/693] Reworked ClientVersion into EQEmu::versions; Added EQEmu::versions::InventoryVersion --- changelog.txt | 3 + common/CMakeLists.txt | 4 + common/client_version.cpp | 128 ++++++++++++++++++++++++ common/client_version.h | 74 ++++++++++++++ common/clientversions.h | 182 ----------------------------------- common/emu_constants.h | 6 +- common/eq_limits.cpp | 119 +++++++---------------- common/eq_limits.h | 40 +++----- common/eq_stream_intf.h | 4 +- common/eq_stream_proxy.cpp | 4 +- common/eq_stream_proxy.h | 2 +- common/inventory_version.cpp | 147 ++++++++++++++++++++++++++++ common/inventory_version.h | 62 ++++++++++++ common/item.cpp | 2 +- common/item.h | 21 ++-- common/patches/rof.cpp | 4 +- common/patches/rof.h | 2 +- common/patches/rof2.cpp | 4 +- common/patches/rof2.h | 2 +- common/patches/sod.cpp | 4 +- common/patches/sod.h | 2 +- common/patches/sof.cpp | 4 +- common/patches/sof.h | 2 +- common/patches/titanium.cpp | 4 +- common/patches/titanium.h | 2 +- common/patches/uf.cpp | 4 +- common/patches/uf.h | 2 +- common/struct_strategy.h | 4 +- world/client.cpp | 38 ++++---- world/client.h | 2 +- world/worlddb.cpp | 8 +- zone/aa.cpp | 4 +- zone/attack.cpp | 12 +-- zone/bonuses.cpp | 6 +- zone/bot.cpp | 10 +- zone/bot_command.cpp | 2 +- zone/client.cpp | 48 ++++----- zone/client.h | 15 +-- zone/client_mods.cpp | 12 +-- zone/client_packet.cpp | 60 ++++++------ zone/client_process.cpp | 12 +-- zone/command.cpp | 2 +- zone/corpse.cpp | 10 +- zone/entity.cpp | 6 +- zone/groups.cpp | 16 +-- zone/guild.cpp | 10 +- zone/guild_mgr.cpp | 4 +- zone/inventory.cpp | 14 +-- zone/lua_client.cpp | 4 +- zone/lua_general.cpp | 16 +-- zone/merc.cpp | 44 ++++----- zone/mob.cpp | 4 +- zone/npc.cpp | 2 +- zone/object.cpp | 4 +- zone/perl_client.cpp | 4 +- zone/pets.cpp | 2 +- zone/raids.cpp | 4 +- zone/special_attacks.cpp | 2 +- zone/spell_effects.cpp | 20 ++-- zone/spells.cpp | 16 +-- zone/tasks.cpp | 6 +- zone/trading.cpp | 24 ++--- zone/worldserver.cpp | 2 +- zone/zone.cpp | 4 +- zone/zonedb.cpp | 2 +- zone/zoning.cpp | 4 +- 66 files changed, 732 insertions(+), 561 deletions(-) create mode 100644 common/client_version.cpp create mode 100644 common/client_version.h delete mode 100644 common/clientversions.h create mode 100644 common/inventory_version.cpp create mode 100644 common/inventory_version.h diff --git a/changelog.txt b/changelog.txt index 964d325af..b019e8024 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/22/2016 == +Uleat: Reworked ClientVersion into namespace EQEmu; Added InventoryVersion + == 04/19/2016 == Uleat: Changed the recent EQEmu rework to eliminate the nested class design (possible cause of VS2015 update crashes - unverified) Uleat: Some more inv2 convergence work diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 57869b328..12b656716 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -3,6 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) SET(common_sources base_packet.cpp classes.cpp + client_version.cpp condition.cpp crash.cpp crc16.cpp @@ -33,6 +34,7 @@ SET(common_sources faction.cpp guild_base.cpp guilds.cpp + inventory_version.cpp ipc_mutex.cpp item.cpp light_source.cpp @@ -101,6 +103,7 @@ SET(common_headers base_data.h bodytypes.h classes.h + client_version.h condition.h crash.h crc16.h @@ -142,6 +145,7 @@ SET(common_headers global_define.h guild_base.h guilds.h + inventory_version.h ipc_mutex.h item.h item_fieldlist.h diff --git a/common/client_version.cpp b/common/client_version.cpp new file mode 100644 index 000000000..a9cb02a0b --- /dev/null +++ b/common/client_version.cpp @@ -0,0 +1,128 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "client_version.h" + + +bool EQEmu::versions::IsValidClientVersion(ClientVersion client_version) +{ + if (client_version <= ClientVersion::Unknown || client_version > LastClientVersion) + return false; + + return true; +} + +EQEmu::versions::ClientVersion EQEmu::versions::ValidateClientVersion(ClientVersion client_version) +{ + if (client_version <= ClientVersion::Unknown || client_version > LastClientVersion) + return ClientVersion::Unknown; + + return client_version; +} + +const char* EQEmu::versions::ClientVersionName(ClientVersion client_version) +{ + switch (client_version) { + case ClientVersion::Unknown: + return "Unknown Version"; + case ClientVersion::Client62: + return "Client 6.2"; + case ClientVersion::Titanium: + return "Titanium"; + case ClientVersion::SoF: + return "SoF"; + case ClientVersion::SoD: + return "SoD"; + case ClientVersion::UF: + return "UF"; + case ClientVersion::RoF: + return "RoF"; + case ClientVersion::RoF2: + return "RoF2"; + default: + return "Invalid Version"; + }; +} + +uint32 EQEmu::versions::ConvertClientVersionToClientVersionBit(ClientVersion client_version) +{ + switch (client_version) { + case ClientVersion::Unknown: + case ClientVersion::Client62: + return bit_Unknown; + case ClientVersion::Titanium: + return bit_Titanium; + case ClientVersion::SoF: + return bit_SoF; + case ClientVersion::SoD: + return bit_SoD; + case ClientVersion::UF: + return bit_UF; + case ClientVersion::RoF: + return bit_RoF; + case ClientVersion::RoF2: + return bit_RoF2; + default: + return bit_Unknown; + } +} + +EQEmu::versions::ClientVersion EQEmu::versions::ConvertClientVersionBitToClientVersion(uint32 client_version_bit) +{ + switch (client_version_bit) { + case (uint32)static_cast(ClientVersion::Unknown) : + case ((uint32)1 << (static_cast(ClientVersion::Client62) - 1)) : + return ClientVersion::Unknown; + case ((uint32)1 << (static_cast(ClientVersion::Titanium) - 1)) : + return ClientVersion::Titanium; + case ((uint32)1 << (static_cast(ClientVersion::SoF) - 1)) : + return ClientVersion::SoF; + case ((uint32)1 << (static_cast(ClientVersion::SoD) - 1)) : + return ClientVersion::SoD; + case ((uint32)1 << (static_cast(ClientVersion::UF) - 1)) : + return ClientVersion::UF; + case ((uint32)1 << (static_cast(ClientVersion::RoF) - 1)) : + return ClientVersion::RoF; + case ((uint32)1 << (static_cast(ClientVersion::RoF2) - 1)) : + return ClientVersion::RoF2; + default: + return ClientVersion::Unknown; + } +} + +uint32 EQEmu::versions::ConvertClientVersionToExpansion(ClientVersion client_version) +{ + switch (client_version) { + case ClientVersion::Unknown: + case ClientVersion::Client62: + case ClientVersion::Titanium: + return 0x000007FFU; + case ClientVersion::SoF: + return 0x00007FFFU; + case ClientVersion::SoD: + return 0x0000FFFFU; + case ClientVersion::UF: + return 0x0001FFFFU; + case ClientVersion::RoF: + case ClientVersion::RoF2: + return 0x000FFFFFU; + default: + return 0; + } +} diff --git a/common/client_version.h b/common/client_version.h new file mode 100644 index 000000000..fe0ceef53 --- /dev/null +++ b/common/client_version.h @@ -0,0 +1,74 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_CLIENT_VERSION_H +#define COMMON_CLIENT_VERSION_H + +#include "types.h" + + +namespace EQEmu +{ + namespace versions { + enum class ClientVersion { + Unknown = 0, + Client62, // Build: 'Aug 4 2005 15:40:59' + Titanium, // Build: 'Oct 31 2005 10:33:37' + SoF, // Build: 'Sep 7 2007 09:11:49' + SoD, // Build: 'Dec 19 2008 15:22:49' + UF, // Build: 'Jun 8 2010 16:44:32' + RoF, // Build: 'Dec 10 2012 17:35:44' + RoF2 // Build: 'May 10 2013 23:30:08' + }; + + enum ClientVersionBit : uint32 { + bit_Unknown = 0, + bit_Client62 = 0x00000001, // unsupported (placeholder for scripts) + bit_Titanium = 0x00000002, + bit_SoF = 0x00000004, + bit_SoD = 0x00000008, + bit_UF = 0x00000010, + bit_RoF = 0x00000020, + bit_RoF2 = 0x00000040, + bit_TitaniumAndEarlier = 0x00000003, + bit_SoFAndEarlier = 0x00000007, + bit_SoDAndEarlier = 0x0000000F, + bit_UFAndEarlier = 0x0000001F, + bit_RoFAndEarlier = 0x0000003F, + bit_SoFAndLater = 0xFFFFFFFC, + bit_SoDAndLater = 0xFFFFFFF8, + bit_UFAndLater = 0xFFFFFFF0, + bit_RoFAndLater = 0xFFFFFFE0, + bit_RoF2AndLater = 0xFFFFFFC0, + bit_AllClients = 0xFFFFFFFF + }; + + static const ClientVersion LastClientVersion = ClientVersion::RoF2; + static const size_t ClientVersionCount = (static_cast(LastClientVersion) + 1); + + extern bool IsValidClientVersion(ClientVersion client_version); + extern ClientVersion ValidateClientVersion(ClientVersion client_version); + extern const char* ClientVersionName(ClientVersion client_version); + extern uint32 ConvertClientVersionToClientVersionBit(ClientVersion client_version); + extern ClientVersion ConvertClientVersionBitToClientVersion(uint32 client_version_bit); + extern uint32 ConvertClientVersionToExpansion(ClientVersion client_version); + } +} + +#endif /* COMMON_CLIENT_VERSION_H */ diff --git a/common/clientversions.h b/common/clientversions.h deleted file mode 100644 index 308a5f091..000000000 --- a/common/clientversions.h +++ /dev/null @@ -1,182 +0,0 @@ -/* -EQEMu: Everquest Server Emulator - -Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net) - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#ifndef CLIENTVERSIONS_H -#define CLIENTVERSIONS_H - -#include "types.h" - -static const uint32 BIT_Client62 = 0x00000001; // 1 (unsupported - placeholder for scripts) - -static const uint32 BIT_Titanium = 0x00000002; // 2 -static const uint32 BIT_SoF = 0x00000004; // 4 -static const uint32 BIT_SoD = 0x00000008; // 8 -static const uint32 BIT_UF = 0x00000010; // 16 -static const uint32 BIT_RoF = 0x00000020; // 32 -static const uint32 BIT_RoF2 = 0x00000040; // 64 - -static const uint32 BIT_TitaniumAndEarlier = 0x00000003; // 3 -static const uint32 BIT_SoFAndEarlier = 0x00000007; // 7 -static const uint32 BIT_SoDAndEarlier = 0x0000000F; // 15 -static const uint32 BIT_UFAndEarlier = 0x0000001F; // 31 -static const uint32 BIT_RoFAndEarlier = 0x0000003F; // 63 - -static const uint32 BIT_SoFAndLater = 0xFFFFFFFC; // 4294967292 -static const uint32 BIT_SoDAndLater = 0xFFFFFFF8; // 4294967288 -static const uint32 BIT_UFAndLater = 0xFFFFFFF0; // 4294967280 -static const uint32 BIT_RoFAndLater = 0xFFFFFFE0; // 4294967264 -static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0; // 4294967232 - -static const uint32 BIT_AllClients = 0xFFFFFFFF; - -enum class ClientVersion -{ - Unknown = 0, - Client62, // Build: 'Aug 4 2005 15:40:59' - Titanium, // Build: 'Oct 31 2005 10:33:37' - SoF, // Build: 'Sep 7 2007 09:11:49' - SoD, // Build: 'Dec 19 2008 15:22:49' - UF, // Build: 'Jun 8 2010 16:44:32' - RoF, // Build: 'Dec 10 2012 17:35:44' - RoF2, // Build: 'May 10 2013 23:30:08' - - MobNPC, - MobMerc, - MobBot, - MobPet, -}; - -#define CLIENT_VERSION_COUNT 12 -#define LAST_PC_CLIENT ClientVersion::RoF2 -#define LAST_NPC_CLIENT ClientVersion::MobPet - - -static const char* ClientVersionName(ClientVersion version) -{ - switch (version) - { - case ClientVersion::Unknown: - return "Unknown"; - case ClientVersion::Client62: - return "Client62"; - case ClientVersion::Titanium: - return "Titanium"; - case ClientVersion::SoF: - return "SoF"; - case ClientVersion::SoD: - return "SoD"; - case ClientVersion::UF: - return "UF"; - case ClientVersion::RoF: - return "RoF"; - case ClientVersion::RoF2: - return "RoF2"; - case ClientVersion::MobNPC: - return "MobNPC"; - case ClientVersion::MobMerc: - return "MobMerc"; - case ClientVersion::MobBot: - return "MobBot"; - case ClientVersion::MobPet: - return "MobPet"; - default: - return " Invalid ClientVersion"; - }; -} - -static uint32 ClientBitFromVersion(ClientVersion clientVersion) -{ - switch (clientVersion) - { - case ClientVersion::Unknown: - case ClientVersion::Client62: - return 0; - case ClientVersion::Titanium: - case ClientVersion::SoF: - case ClientVersion::SoD: - case ClientVersion::UF: - case ClientVersion::RoF: - case ClientVersion::RoF2: - case ClientVersion::MobNPC: - case ClientVersion::MobMerc: - case ClientVersion::MobBot: - case ClientVersion::MobPet: - return ((uint32)1 << (static_cast(clientVersion) - 1)); - default: - return 0; - } -} - -static ClientVersion ClientVersionFromBit(uint32 clientVersionBit) -{ - switch (clientVersionBit) - { - case (uint32)static_cast(ClientVersion::Unknown): - case ((uint32)1 << (static_cast(ClientVersion::Client62) - 1)): - return ClientVersion::Unknown; - case ((uint32)1 << (static_cast(ClientVersion::Titanium) - 1)): - return ClientVersion::Titanium; - case ((uint32)1 << (static_cast(ClientVersion::SoF) - 1)): - return ClientVersion::SoF; - case ((uint32)1 << (static_cast(ClientVersion::SoD) - 1)): - return ClientVersion::SoD; - case ((uint32)1 << (static_cast(ClientVersion::UF) - 1)): - return ClientVersion::UF; - case ((uint32)1 << (static_cast(ClientVersion::RoF) - 1)): - return ClientVersion::RoF; - case ((uint32)1 << (static_cast(ClientVersion::RoF2) - 1)): - return ClientVersion::RoF2; - case ((uint32)1 << (static_cast(ClientVersion::MobNPC) - 1)): - return ClientVersion::MobNPC; - case ((uint32)1 << (static_cast(ClientVersion::MobMerc) - 1)): - return ClientVersion::MobMerc; - case ((uint32)1 << (static_cast(ClientVersion::MobBot) - 1)): - return ClientVersion::MobBot; - case ((uint32)1 << (static_cast(ClientVersion::MobPet) - 1)): - return ClientVersion::MobPet; - default: - return ClientVersion::Unknown; - } -} - -static uint32 ExpansionFromClientVersion(ClientVersion clientVersion) -{ - switch(clientVersion) - { - case ClientVersion::Unknown: - case ClientVersion::Client62: - case ClientVersion::Titanium: - return 0x000007FFU; - case ClientVersion::SoF: - return 0x00007FFFU; - case ClientVersion::SoD: - return 0x0000FFFFU; - case ClientVersion::UF: - return 0x0001FFFFU; - case ClientVersion::RoF: - case ClientVersion::RoF2: - return 0x000FFFFFU; - default: - return 0; - } -} - -#endif /* CLIENTVERSIONS_H */ diff --git a/common/emu_constants.h b/common/emu_constants.h index b5b0ef561..1cc6c9e5a 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -26,6 +26,7 @@ //using namespace RoF::slots; // server possessions slots enumeration (code and database sync'd to reference) #include "emu_legacy.h" +#include "inventory_version.h" #include "light_source.h" #include "deity.h" #include "say_link.h" @@ -44,9 +45,8 @@ namespace EQEmu // an immutable value is required to initialize arrays, etc... use this class as a repository for those namespace constants { // database - static const ClientVersion CHARACTER_CREATION_CLIENT = ClientVersion::RoF2; // adjust according to starting item placement and target client - - static const size_t CHARACTER_CREATION_LIMIT = RoF2::consts::CHARACTER_CREATION_LIMIT; + static const EQEmu::versions::ClientVersion CharacterCreationClient = EQEmu::versions::ClientVersion::RoF2; + static const size_t CharacterCreationLimit = RoF2::consts::CHARACTER_CREATION_LIMIT; // inventory extern uint16 InventoryTypeSize(int16 type_index); diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index d34f9990d..e7e729cd7 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -20,61 +20,10 @@ #include "emu_constants.h" -// client validation -bool EQEmu::limits::IsValidPCClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) - return true; - - return false; -} - -ClientVersion EQEmu::limits::ValidatePCClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) - return clientVersion; - - return ClientVersion::Unknown; -} - -// npc validation -bool EQEmu::limits::IsValidNPCClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) - return true; - - return false; -} - -ClientVersion EQEmu::limits::ValidateNPCClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) - return clientVersion; - - return ClientVersion::Unknown; -} - -// mob validation -bool EQEmu::limits::IsValidMobClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) - return true; - - return false; -} - -ClientVersion EQEmu::limits::ValidateMobClientVersion(ClientVersion clientVersion) -{ - if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) - return clientVersion; - - return ClientVersion::Unknown; -} - // database -size_t EQEmu::limits::CharacterCreationLimit(ClientVersion clientVersion) +size_t EQEmu::limits::CharacterCreationLimit(versions::ClientVersion client_version) { - static const size_t local[CLIENT_VERSION_COUNT] = { + static const size_t local[versions::InventoryVersionCount] = { /*Unknown*/ NOT_USED, /*Client62*/ NOT_USED, /*Titanium*/ Titanium::consts::CHARACTER_CREATION_LIMIT, @@ -90,11 +39,11 @@ size_t EQEmu::limits::CharacterCreationLimit(ClientVersion clientVersion) /*MobPet*/ NOT_USED }; - return local[static_cast(ValidateMobClientVersion(clientVersion))]; + return local[static_cast(versions::ValidateClientVersion(client_version))]; } // inventory -uint16 EQEmu::limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) +uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_version, int16 inv_type) { // not all maps will have an instantiated container..some are references for queue generators (i.e., bazaar, mail, etc...) // a zero '0' indicates a needed value..otherwise, change to '_NOTUSED' for a null value so indices requiring research can be identified @@ -107,7 +56,7 @@ uint16 EQEmu::limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi // // when setting NPC-based values, try to adhere to an constants:: or NOT_USED value to avoid unnecessary issues - static const uint16 local[TypeCount][CLIENT_VERSION_COUNT] = { + static const uint16 local[TypeCount][versions::InventoryVersionCount] = { // server and database are sync'd to current TypePossessions's client as set in 'using namespace RoF::slots;' and // 'constants::TYPE_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() // for partial range validation checks and 'constants::TYPE_POSSESSIONS_SIZE' for full range iterations @@ -488,20 +437,20 @@ uint16 EQEmu::limits::InventoryMapSize(int16 indexMap, ClientVersion clientVersi } }; - if ((uint16)indexMap < TypeCount) - return local[indexMap][static_cast(ValidateMobClientVersion(clientVersion))]; + if ((uint16)inv_type < TypeCount) + return local[inv_type][static_cast(versions::ValidateInventoryVersion(inventory_version))]; return NOT_USED; } -uint64 EQEmu::limits::PossessionsBitmask(ClientVersion clientVersion) +uint64 EQEmu::limits::PossessionsBitmask(versions::InventoryVersion inventory_version) { // these are for the new inventory system (RoF)..not the current (Ti) one... // 0x0000000000200000 is SlotPowerSource (SoF+) // 0x0000000080000000 is SlotGeneral9 (RoF+) // 0x0000000100000000 is SlotGeneral10 (RoF+) - static const uint64 local[CLIENT_VERSION_COUNT] = { + static const uint64 local[versions::InventoryVersionCount] = { /*Unknown*/ NOT_USED, /*62*/ 0x000000027FDFFFFF, /*Titanium*/ 0x000000027FDFFFFF, @@ -518,12 +467,12 @@ uint64 EQEmu::limits::PossessionsBitmask(ClientVersion clientVersion) }; return NOT_USED; - //return local[static_cast(ValidateMobClientVersion(clientVersion))]; + //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -uint64 EQEmu::limits::EquipmentBitmask(ClientVersion clientVersion) +uint64 EQEmu::limits::EquipmentBitmask(versions::InventoryVersion inventory_version) { - static const uint64 local[CLIENT_VERSION_COUNT] = { + static const uint64 local[versions::InventoryVersionCount] = { /*Unknown*/ NOT_USED, /*62*/ 0x00000000005FFFFF, /*Titanium*/ 0x00000000005FFFFF, @@ -540,12 +489,12 @@ uint64 EQEmu::limits::EquipmentBitmask(ClientVersion clientVersion) }; return NOT_USED; - //return local[static_cast(ValidateMobClientVersion(clientVersion))]; + //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -uint64 EQEmu::limits::GeneralBitmask(ClientVersion clientVersion) +uint64 EQEmu::limits::GeneralBitmask(versions::InventoryVersion inventory_version) { - static const uint64 local[CLIENT_VERSION_COUNT] = { + static const uint64 local[versions::InventoryVersionCount] = { /*Unknown*/ NOT_USED, /*62*/ 0x000000007F800000, /*Titanium*/ 0x000000007F800000, @@ -562,12 +511,12 @@ uint64 EQEmu::limits::GeneralBitmask(ClientVersion clientVersion) }; return NOT_USED; - //return local[static_cast(ValidateMobClientVersion(clientVersion))]; + //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -uint64 EQEmu::limits::CursorBitmask(ClientVersion clientVersion) +uint64 EQEmu::limits::CursorBitmask(versions::InventoryVersion inventory_version) { - static const uint64 local[CLIENT_VERSION_COUNT] = { + static const uint64 local[versions::InventoryVersionCount] = { /*Unknown*/ NOT_USED, /*62*/ 0x0000000200000000, /*Titanium*/ 0x0000000200000000, @@ -584,12 +533,12 @@ uint64 EQEmu::limits::CursorBitmask(ClientVersion clientVersion) }; return NOT_USED; - //return local[static_cast(ValidateMobClientVersion(clientVersion))]; + //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -bool EQEmu::limits::AllowsEmptyBagInBag(ClientVersion clientVersion) +bool EQEmu::limits::AllowEmptyBagInBag(versions::InventoryVersion inventory_version) { - static const bool local[CLIENT_VERSION_COUNT] = { + static const bool local[versions::InventoryVersionCount] = { /*Unknown*/ false, /*62*/ false, /*Titanium*/ Titanium::limits::ALLOWS_EMPTY_BAG_IN_BAG, @@ -606,12 +555,12 @@ bool EQEmu::limits::AllowsEmptyBagInBag(ClientVersion clientVersion) }; return false; // not implemented - //return local[static_cast(ValidateMobClientVersion(clientVersion))]; + //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -bool EQEmu::limits::AllowsClickCastFromBag(ClientVersion clientVersion) +bool EQEmu::limits::AllowClickCastFromBag(versions::InventoryVersion inventory_version) { - static const bool local[CLIENT_VERSION_COUNT] = { + static const bool local[versions::InventoryVersionCount] = { /*Unknown*/ false, /*62*/ false, /*Titanium*/ Titanium::limits::ALLOWS_CLICK_CAST_FROM_BAG, @@ -627,13 +576,13 @@ bool EQEmu::limits::AllowsClickCastFromBag(ClientVersion clientVersion) /*Pet*/ false }; - return local[static_cast(ValidateMobClientVersion(clientVersion))]; + return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } // items -uint16 EQEmu::limits::ItemCommonSize(ClientVersion clientVersion) +uint16 EQEmu::limits::ItemCommonSize(versions::InventoryVersion inventory_version) { - static const uint16 local[CLIENT_VERSION_COUNT] = { + static const uint16 local[versions::InventoryVersionCount] = { /*Unknown*/ NOT_USED, /*62*/ constants::ITEM_COMMON_SIZE, /*Titanium*/ constants::ITEM_COMMON_SIZE, @@ -649,12 +598,12 @@ uint16 EQEmu::limits::ItemCommonSize(ClientVersion clientVersion) /*Pet*/ constants::ITEM_COMMON_SIZE }; - return local[static_cast(ValidateMobClientVersion(clientVersion))]; + return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -uint16 EQEmu::limits::ItemContainerSize(ClientVersion clientVersion) +uint16 EQEmu::limits::ItemContainerSize(versions::InventoryVersion inventory_version) { - static const uint16 local[CLIENT_VERSION_COUNT] = { + static const uint16 local[versions::InventoryVersionCount] = { /*Unknown*/ NOT_USED, /*62*/ constants::ITEM_CONTAINER_SIZE, /*Titanium*/ constants::ITEM_CONTAINER_SIZE, @@ -670,12 +619,12 @@ uint16 EQEmu::limits::ItemContainerSize(ClientVersion clientVersion) /*Pet*/ constants::ITEM_CONTAINER_SIZE }; - return local[static_cast(ValidateMobClientVersion(clientVersion))]; + return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -bool EQEmu::limits::CoinHasWeight(ClientVersion clientVersion) +bool EQEmu::limits::CoinHasWeight(versions::InventoryVersion inventory_version) { - static const bool local[CLIENT_VERSION_COUNT] = { + static const bool local[versions::InventoryVersionCount] = { /*Unknown*/ true, /*62*/ true, /*Titanium*/ Titanium::limits::COIN_HAS_WEIGHT, @@ -691,5 +640,5 @@ bool EQEmu::limits::CoinHasWeight(ClientVersion clientVersion) /*Pet*/ true }; - return local[static_cast(ValidateMobClientVersion(clientVersion))]; + return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } diff --git a/common/eq_limits.h b/common/eq_limits.h index 4e68fa5d3..4c1db6252 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -22,7 +22,7 @@ #include "types.h" #include "eq_constants.h" -#include "clientversions.h" +#include "inventory_version.h" // inv2 watch #include "../common/patches/titanium_constants.h" #include "../common/patches/sof_constants.h" #include "../common/patches/sod_constants.h" @@ -39,42 +39,26 @@ namespace EQEmu { - // values should default to a non-beneficial value..unless value conflicts with intended operation - // - // EQEmu::Constants may be used as references..but, not every reference needs to be in EQEmu::Constants (i.e., AllowsEmptyBagInBag(), CoinHasWeight(), etc...) namespace limits { - // client version validation (checks to avoid crashing zone server when accessing reference arrays) - // use this inside of class Client (limits to actual clients) - extern bool IsValidPCClientVersion(ClientVersion clientVersion); - extern ClientVersion ValidatePCClientVersion(ClientVersion clientVersion); - - // basically..any non-client classes - do not invoke when setting a valid client - extern bool IsValidNPCClientVersion(ClientVersion clientVersion); - extern ClientVersion ValidateNPCClientVersion(ClientVersion clientVersion); - - // these are 'universal' - do not invoke when setting a valid client - extern bool IsValidMobClientVersion(ClientVersion clientVersion); - extern ClientVersion ValidateMobClientVersion(ClientVersion clientVersion); - // database - extern size_t CharacterCreationLimit(ClientVersion clientVersion); + extern size_t CharacterCreationLimit(versions::ClientVersion client_version); // inventory - extern uint16 InventoryMapSize(int16 indexMap, ClientVersion clientVersion); - extern uint64 PossessionsBitmask(ClientVersion clientVersion); - extern uint64 EquipmentBitmask(ClientVersion clientVersion); - extern uint64 GeneralBitmask(ClientVersion clientVersion); - extern uint64 CursorBitmask(ClientVersion clientVersion); + extern uint16 InventoryTypeSize(versions::InventoryVersion inventory_version, int16 inv_type); + extern uint64 PossessionsBitmask(versions::InventoryVersion inventory_version); + extern uint64 EquipmentBitmask(versions::InventoryVersion inventory_version); + extern uint64 GeneralBitmask(versions::InventoryVersion inventory_version); + extern uint64 CursorBitmask(versions::InventoryVersion inventory_version); - extern bool AllowsEmptyBagInBag(ClientVersion clientVersion); - extern bool AllowsClickCastFromBag(ClientVersion clientVersion); + extern bool AllowEmptyBagInBag(versions::InventoryVersion inventory_version); + extern bool AllowClickCastFromBag(versions::InventoryVersion inventory_version); // items - extern uint16 ItemCommonSize(ClientVersion clientVersion); - extern uint16 ItemContainerSize(ClientVersion clientVersion); + extern uint16 ItemCommonSize(versions::InventoryVersion inventory_version); + extern uint16 ItemContainerSize(versions::InventoryVersion inventory_version); // player profile - extern bool CoinHasWeight(ClientVersion clientVersion); + extern bool CoinHasWeight(versions::InventoryVersion inventory_version); } } diff --git a/common/eq_stream_intf.h b/common/eq_stream_intf.h index 68b8ffc96..f357eb27b 100644 --- a/common/eq_stream_intf.h +++ b/common/eq_stream_intf.h @@ -4,7 +4,7 @@ //this is the only part of an EQStream that is seen by the application. #include -#include "clientversions.h" +#include "client_version.h" // inv2 watch typedef enum { ESTABLISHED, @@ -35,7 +35,7 @@ public: virtual const uint32 GetBytesRecieved() const { return 0; } virtual const uint32 GetBytesSentPerSecond() const { return 0; } virtual const uint32 GetBytesRecvPerSecond() const { return 0; } - virtual const ClientVersion GetClientVersion() const { return ClientVersion::Unknown; } + virtual const EQEmu::versions::ClientVersion ClientVersion() const { return EQEmu::versions::ClientVersion::Unknown; } }; #endif /*EQSTREAMINTF_H_*/ diff --git a/common/eq_stream_proxy.cpp b/common/eq_stream_proxy.cpp index 117ae8c94..0c41988e4 100644 --- a/common/eq_stream_proxy.cpp +++ b/common/eq_stream_proxy.cpp @@ -21,9 +21,9 @@ std::string EQStreamProxy::Describe() const { return(m_structs->Describe()); } -const ClientVersion EQStreamProxy::GetClientVersion() const +const EQEmu::versions::ClientVersion EQStreamProxy::ClientVersion() const { - return m_structs->GetClientVersion(); + return m_structs->ClientVersion(); } void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) { diff --git a/common/eq_stream_proxy.h b/common/eq_stream_proxy.h index 93ad1d884..def543b34 100644 --- a/common/eq_stream_proxy.h +++ b/common/eq_stream_proxy.h @@ -28,7 +28,7 @@ public: virtual void RemoveData(); virtual bool CheckState(EQStreamState state); virtual std::string Describe() const; - virtual const ClientVersion GetClientVersion() const; + virtual const EQEmu::versions::ClientVersion ClientVersion() const; virtual const uint32 GetBytesSent() const; virtual const uint32 GetBytesRecieved() const; diff --git a/common/inventory_version.cpp b/common/inventory_version.cpp new file mode 100644 index 000000000..bc93e1408 --- /dev/null +++ b/common/inventory_version.cpp @@ -0,0 +1,147 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "inventory_version.h" + + +bool EQEmu::versions::IsValidInventoryVersion(InventoryVersion inventory_version) +{ + if (inventory_version <= InventoryVersion::Unknown || inventory_version > LastInventoryVersion) + return false; + + return true; +} + +bool EQEmu::versions::IsValidPCInventoryVersion(InventoryVersion inventory_version) +{ + if (inventory_version <= InventoryVersion::Unknown || inventory_version > LastPCInventoryVersion) + return false; + + return true; +} + +bool EQEmu::versions::IsValidNonPCInventoryVersion(InventoryVersion inventory_version) +{ + if (inventory_version <= LastPCInventoryVersion || inventory_version > LastNonPCInventoryVersion) + return false; + + return true; +} + +EQEmu::versions::InventoryVersion EQEmu::versions::ValidateInventoryVersion(InventoryVersion inventory_version) +{ + if (inventory_version <= InventoryVersion::Unknown || inventory_version > LastInventoryVersion) + return InventoryVersion::Unknown; + + return inventory_version; +} + +EQEmu::versions::InventoryVersion EQEmu::versions::ValidatePCInventoryVersion(InventoryVersion inventory_version) +{ + if (inventory_version <= InventoryVersion::Unknown || inventory_version > LastPCInventoryVersion) + return InventoryVersion::Unknown; + + return inventory_version; +} + +EQEmu::versions::InventoryVersion EQEmu::versions::ValidateNonPCInventoryVersion(InventoryVersion inventory_version) +{ + if (inventory_version <= LastPCInventoryVersion || inventory_version > LastNonPCInventoryVersion) + return InventoryVersion::Unknown; + + return inventory_version; +} + +const char* EQEmu::versions::InventoryVersionName(InventoryVersion inventory_version) +{ + switch (inventory_version) { + case InventoryVersion::Unknown: + return "Unknown Version"; + case InventoryVersion::Client62: + return "Client 6.2"; + case InventoryVersion::Titanium: + return "Titanium"; + case InventoryVersion::SoF: + return "SoF"; + case InventoryVersion::SoD: + return "SoD"; + case InventoryVersion::UF: + return "UF"; + case InventoryVersion::RoF: + return "RoF"; + case InventoryVersion::RoF2: + return "RoF2"; + case InventoryVersion::NPC: + return "NPC"; + case InventoryVersion::Merc: + return "Merc"; + case InventoryVersion::Bot: + return "Bot"; + case InventoryVersion::Pet: + return "Pet"; + default: + return "Invalid Version"; + }; +} + +EQEmu::versions::ClientVersion EQEmu::versions::ConvertInventoryVersionToClientVersion(InventoryVersion inventory_version) +{ + switch (inventory_version) { + case InventoryVersion::Unknown: + case InventoryVersion::Client62: + return ClientVersion::Unknown; + case InventoryVersion::Titanium: + return ClientVersion::Titanium; + case InventoryVersion::SoF: + return ClientVersion::SoF; + case InventoryVersion::SoD: + return ClientVersion::SoD; + case InventoryVersion::UF: + return ClientVersion::UF; + case InventoryVersion::RoF: + return ClientVersion::RoF; + case InventoryVersion::RoF2: + return ClientVersion::RoF2; + default: + return ClientVersion::Unknown; + } +} + +EQEmu::versions::InventoryVersion EQEmu::versions::ConvertClientVersionToInventoryVersion(ClientVersion client_version) +{ + switch (client_version) { + case ClientVersion::Unknown: + case ClientVersion::Client62: + return InventoryVersion::Unknown; + case ClientVersion::Titanium: + return InventoryVersion::Titanium; + case ClientVersion::SoF: + return InventoryVersion::SoF; + case ClientVersion::SoD: + return InventoryVersion::SoD; + case ClientVersion::UF: + return InventoryVersion::UF; + case ClientVersion::RoF: + return InventoryVersion::RoF; + case ClientVersion::RoF2: + return InventoryVersion::RoF2; + default: + return InventoryVersion::Unknown; + } +} diff --git a/common/inventory_version.h b/common/inventory_version.h new file mode 100644 index 000000000..70e295067 --- /dev/null +++ b/common/inventory_version.h @@ -0,0 +1,62 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_INVENTORY_VERSION_H +#define COMMON_INVENTORY_VERSION_H + +#include "types.h" +#include "client_version.h" + + +namespace EQEmu +{ + namespace versions { + enum class InventoryVersion { + Unknown = 0, + Client62, + Titanium, + SoF, + SoD, + UF, + RoF, + RoF2, + NPC, + Merc, + Bot, + Pet + }; + + static const InventoryVersion LastInventoryVersion = InventoryVersion::Pet; + static const InventoryVersion LastPCInventoryVersion = InventoryVersion::RoF2; + static const InventoryVersion LastNonPCInventoryVersion = InventoryVersion::Pet; + static const size_t InventoryVersionCount = (static_cast(LastInventoryVersion) + 1); + + extern bool IsValidInventoryVersion(InventoryVersion inventory_version); + extern bool IsValidPCInventoryVersion(InventoryVersion inventory_version); + extern bool IsValidNonPCInventoryVersion(InventoryVersion inventory_version); + extern InventoryVersion ValidateInventoryVersion(InventoryVersion inventory_version); + extern InventoryVersion ValidatePCInventoryVersion(InventoryVersion inventory_version); + extern InventoryVersion ValidateNonPCInventoryVersion(InventoryVersion inventory_version); + extern const char* InventoryVersionName(InventoryVersion inventory_version); + extern ClientVersion ConvertInventoryVersionToClientVersion(InventoryVersion inventory_version); + extern InventoryVersion ConvertClientVersionToInventoryVersion(ClientVersion client_version); + } +} + +#endif /* COMMON_INVENTORY_VERSION_H */ diff --git a/common/item.cpp b/common/item.cpp index b65f33123..a9c0df3c2 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -927,7 +927,7 @@ bool Inventory::SupportsClickCasting(int16 slot_id) } else if (slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::constants::GENERAL_BAGS_END) { - if (EQEmu::limits::AllowsClickCastFromBag(m_version)) + if (EQEmu::limits::AllowClickCastFromBag(m_inventory_version)) return true; } diff --git a/common/item.h b/common/item.h index 28e714e31..54bd519fc 100644 --- a/common/item.h +++ b/common/item.h @@ -114,22 +114,23 @@ public: /////////////////////////////// // Public Methods /////////////////////////////// - - Inventory() { m_version = ClientVersion::Unknown; m_versionset = false; } + + Inventory() { m_inventory_version = EQEmu::versions::InventoryVersion::Unknown; m_inventory_version_set = false; } ~Inventory(); - // Inventory v2 creep - bool SetInventoryVersion(ClientVersion version) { - if (!m_versionset) { - m_version = version; - return (m_versionset = true); + // inv2 creep + bool SetInventoryVersion(EQEmu::versions::InventoryVersion inventory_version) { + if (!m_inventory_version_set) { + m_inventory_version = EQEmu::versions::ValidateInventoryVersion(inventory_version); + return (m_inventory_version_set = true); } else { return false; } } + bool SetInventoryVersion(EQEmu::versions::ClientVersion client_version) { return SetInventoryVersion(EQEmu::versions::ConvertClientVersionToInventoryVersion(client_version)); } - ClientVersion GetInventoryVersion() { return m_version; } + EQEmu::versions::InventoryVersion InventoryVersion() { return m_inventory_version; } static void CleanDirty(); static void MarkDirty(ItemInst *inst); @@ -252,8 +253,8 @@ protected: private: // Active inventory version - ClientVersion m_version; - bool m_versionset; + EQEmu::versions::InventoryVersion m_inventory_version; + bool m_inventory_version_set; }; class SharedDatabase; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 58b420bf9..7d615d48c 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -117,9 +117,9 @@ namespace RoF return(r); } - const ClientVersion Strategy::GetClientVersion() const + const EQEmu::versions::ClientVersion Strategy::ClientVersion() const { - return ClientVersion::RoF; + return EQEmu::versions::ClientVersion::RoF; } #include "ss_define.h" diff --git a/common/patches/rof.h b/common/patches/rof.h index 4ac7d3532..a28293731 100644 --- a/common/patches/rof.h +++ b/common/patches/rof.h @@ -23,7 +23,7 @@ namespace RoF { protected: virtual std::string Describe() const; - virtual const ClientVersion GetClientVersion() const; + virtual const EQEmu::versions::ClientVersion ClientVersion() const; //magic macro to declare our opcode processors #include "ss_declare.h" diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index d25155776..4977ad984 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -117,9 +117,9 @@ namespace RoF2 return(r); } - const ClientVersion Strategy::GetClientVersion() const + const EQEmu::versions::ClientVersion Strategy::ClientVersion() const { - return ClientVersion::RoF2; + return EQEmu::versions::ClientVersion::RoF2; } #include "ss_define.h" diff --git a/common/patches/rof2.h b/common/patches/rof2.h index 8644473db..7b183c54e 100644 --- a/common/patches/rof2.h +++ b/common/patches/rof2.h @@ -23,7 +23,7 @@ namespace RoF2 { protected: virtual std::string Describe() const; - virtual const ClientVersion GetClientVersion() const; + virtual const EQEmu::versions::ClientVersion ClientVersion() const; //magic macro to declare our opcode processors #include "ss_declare.h" diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 4f8eb936d..7b75e5d5d 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -113,9 +113,9 @@ namespace SoD return(r); } - const ClientVersion Strategy::GetClientVersion() const + const EQEmu::versions::ClientVersion Strategy::ClientVersion() const { - return ClientVersion::SoD; + return EQEmu::versions::ClientVersion::SoD; } #include "ss_define.h" diff --git a/common/patches/sod.h b/common/patches/sod.h index 65d7f951a..23eddccba 100644 --- a/common/patches/sod.h +++ b/common/patches/sod.h @@ -23,7 +23,7 @@ namespace SoD { protected: virtual std::string Describe() const; - virtual const ClientVersion GetClientVersion() const; + virtual const EQEmu::versions::ClientVersion ClientVersion() const; //magic macro to declare our opcode processors #include "ss_declare.h" diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 2c4f08038..5a49f96a9 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -113,9 +113,9 @@ namespace SoF return(r); } - const ClientVersion Strategy::GetClientVersion() const + const EQEmu::versions::ClientVersion Strategy::ClientVersion() const { - return ClientVersion::SoF; + return EQEmu::versions::ClientVersion::SoF; } #include "ss_define.h" diff --git a/common/patches/sof.h b/common/patches/sof.h index 6a67009d1..4b3a22a35 100644 --- a/common/patches/sof.h +++ b/common/patches/sof.h @@ -23,7 +23,7 @@ namespace SoF { protected: virtual std::string Describe() const; - virtual const ClientVersion GetClientVersion() const; + virtual const EQEmu::versions::ClientVersion ClientVersion() const; //magic macro to declare our opcode processors #include "ss_declare.h" diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 59381bf3b..5afbcb0d6 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -111,9 +111,9 @@ namespace Titanium return(r); } - const ClientVersion Strategy::GetClientVersion() const + const EQEmu::versions::ClientVersion Strategy::ClientVersion() const { - return ClientVersion::Titanium; + return EQEmu::versions::ClientVersion::Titanium; } #include "ss_define.h" diff --git a/common/patches/titanium.h b/common/patches/titanium.h index 4b5164330..2275c265d 100644 --- a/common/patches/titanium.h +++ b/common/patches/titanium.h @@ -23,7 +23,7 @@ namespace Titanium { protected: virtual std::string Describe() const; - virtual const ClientVersion GetClientVersion() const; + virtual const EQEmu::versions::ClientVersion ClientVersion() const; //magic macro to declare our opcode processors #include "ss_declare.h" diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index b667fcea7..ff51b2e7d 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -113,9 +113,9 @@ namespace UF return(r); } - const ClientVersion Strategy::GetClientVersion() const + const EQEmu::versions::ClientVersion Strategy::ClientVersion() const { - return ClientVersion::UF; + return EQEmu::versions::ClientVersion::UF; } #include "ss_define.h" diff --git a/common/patches/uf.h b/common/patches/uf.h index 26e2346a7..3e0598cba 100644 --- a/common/patches/uf.h +++ b/common/patches/uf.h @@ -23,7 +23,7 @@ namespace UF { protected: virtual std::string Describe() const; - virtual const ClientVersion GetClientVersion() const; + virtual const EQEmu::versions::ClientVersion ClientVersion() const; //magic macro to declare our opcode processors #include "ss_declare.h" diff --git a/common/struct_strategy.h b/common/struct_strategy.h index f81881c26..b7417de8c 100644 --- a/common/struct_strategy.h +++ b/common/struct_strategy.h @@ -4,7 +4,7 @@ class EQApplicationPacket; class EQStream; #include "emu_opcodes.h" -#include "clientversions.h" +#include "client_version.h" // inv2 watch #include #include @@ -25,7 +25,7 @@ public: void Decode(EQApplicationPacket *p) const; virtual std::string Describe() const = 0; - virtual const ClientVersion GetClientVersion() const = 0; + virtual const EQEmu::versions::ClientVersion ClientVersion() const = 0; protected: //some common coders: diff --git a/world/client.cpp b/world/client.cpp index 66b66169f..7137d785e 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -32,7 +32,7 @@ #include "../common/skills.h" #include "../common/extprofile.h" #include "../common/string_util.h" -#include "../common/clientversions.h" +#include "../common/client_version.h" // inv2 watch #include "../common/random.h" #include "../common/shareddb.h" @@ -106,8 +106,8 @@ Client::Client(EQStreamInterface* ieqs) pwaitingforbootup = 0; StartInTutorial = false; - m_ClientVersion = eqs->GetClientVersion(); - m_ClientVersionBit = ClientBitFromVersion(m_ClientVersion); + m_ClientVersion = eqs->ClientVersion(); + m_ClientVersionBit = EQEmu::versions::ConvertClientVersionToClientVersionBit(m_ClientVersion); numclients++; } @@ -171,7 +171,7 @@ void Client::SendExpansionInfo() { auto outapp = new EQApplicationPacket(OP_ExpansionInfo, sizeof(ExpansionInfo_Struct)); ExpansionInfo_Struct *eis = (ExpansionInfo_Struct*)outapp->pBuffer; if(RuleB(World, UseClientBasedExpansionSettings)) { - eis->Expansions = ExpansionFromClientVersion(eqs->GetClientVersion()); + eis->Expansions = EQEmu::versions::ConvertClientVersionToExpansion(eqs->ClientVersion()); //eis->Expansions = ExpansionFromClientVersion(this->GetCLE. } else { eis->Expansions = (RuleI(World, ExpansionSettings)); @@ -186,7 +186,7 @@ void Client::SendCharInfo() { cle->SetOnline(CLE_Status_CharSelect); } - if (m_ClientVersionBit & BIT_RoFAndLater) { + if (m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater) { SendMaxCharCreate(); SendMembership(); SendMembershipSettings(); @@ -212,8 +212,8 @@ void Client::SendMaxCharCreate() { MaxCharacters_Struct* mc = (MaxCharacters_Struct*)outapp->pBuffer; mc->max_chars = EQEmu::limits::CharacterCreationLimit(m_ClientVersion); - if (mc->max_chars > EQEmu::constants::CHARACTER_CREATION_LIMIT) - mc->max_chars = EQEmu::constants::CHARACTER_CREATION_LIMIT; + if (mc->max_chars > EQEmu::constants::CharacterCreationLimit) + mc->max_chars = EQEmu::constants::CharacterCreationLimit; QueuePacket(outapp); safe_delete(outapp); @@ -698,7 +698,7 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) { } else { - if (m_ClientVersionBit & BIT_TitaniumAndEarlier) + if (m_ClientVersionBit & EQEmu::versions::bit_TitaniumAndEarlier) StartInTutorial = true; SendCharInfo(); } @@ -746,9 +746,9 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { // This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above) // (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration) if (!pZoning) { - size_t character_limit = EQEmu::limits::CharacterCreationLimit(eqs->GetClientVersion()); - if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT) { character_limit = EQEmu::constants::CHARACTER_CREATION_LIMIT; } - if (eqs->GetClientVersion() == ClientVersion::Titanium) { character_limit = 8; } + size_t character_limit = EQEmu::limits::CharacterCreationLimit(eqs->ClientVersion()); + if (character_limit > EQEmu::constants::CharacterCreationLimit) { character_limit = EQEmu::constants::CharacterCreationLimit; } + if (eqs->ClientVersion() == EQEmu::versions::ClientVersion::Titanium) { character_limit = 8; } std::string tgh_query = StringFormat( "SELECT " @@ -879,9 +879,9 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { char ConnectionType; - if (m_ClientVersionBit & BIT_UFAndLater) + if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) ConnectionType = 'U'; - else if (m_ClientVersionBit & BIT_SoFAndLater) + else if (m_ClientVersionBit & EQEmu::versions::bit_SoFAndLater) ConnectionType = 'S'; else ConnectionType = 'C'; @@ -905,7 +905,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { outapp2 = new EQApplicationPacket(OP_SetChatServer2); - if (m_ClientVersionBit & BIT_TitaniumAndEarlier) + if (m_ClientVersionBit & EQEmu::versions::bit_TitaniumAndEarlier) ConnectionType = 'M'; sprintf(buffer,"%s,%i,%s.%s,%c%08X", @@ -939,7 +939,7 @@ bool Client::HandleDeleteCharacterPacket(const EQApplicationPacket *app) { bool Client::HandleZoneChangePacket(const EQApplicationPacket *app) { // HoT sends this to world while zoning and wants it echoed back. - if (m_ClientVersionBit & BIT_RoFAndLater) + if (m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater) { QueuePacket(app); } @@ -1412,7 +1412,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) Log.Out(Logs::Detail, Logs::World_Server, "Beard: %d Beardcolor: %d", cc->beard, cc->beardcolor); /* Validate the char creation struct */ - if (m_ClientVersionBit & BIT_SoFAndLater) { + if (m_ClientVersionBit & EQEmu::versions::bit_SoFAndLater) { if (!CheckCharCreateInfoSoF(cc)) { Log.Out(Logs::Detail, Logs::World_Server,"CheckCharCreateInfo did not validate the request (bad race/class/stats)"); return false; @@ -1483,7 +1483,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) pp.pvp = database.GetServerType() == 1 ? 1 : 0; /* If it is an SoF Client and the SoF Start Zone rule is set, send new chars there */ - if (m_ClientVersionBit & BIT_SoFAndLater) { + if (m_ClientVersionBit & EQEmu::versions::bit_SoFAndLater) { Log.Out(Logs::Detail, Logs::World_Server,"Found 'SoFStartZoneID' rule setting: %i", RuleI(World, SoFStartZoneID)); if (RuleI(World, SoFStartZoneID) > 0) { pp.zone_id = RuleI(World, SoFStartZoneID); @@ -1499,7 +1499,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) } } /* use normal starting zone logic to either get defaults, or if startzone was set, load that from the db table.*/ - bool ValidStartZone = database.GetStartZone(&pp, cc, m_ClientVersionBit & BIT_TitaniumAndEarlier); + bool ValidStartZone = database.GetStartZone(&pp, cc, m_ClientVersionBit & EQEmu::versions::bit_TitaniumAndEarlier); if (!ValidStartZone){ return false; @@ -1833,7 +1833,7 @@ void Client::SetClassStartingSkills(PlayerProfile_Struct *pp) } } - if (cle->GetClientVersion() < static_cast(ClientVersion::RoF2) && pp->class_ == BERSERKER) { + if (cle->GetClientVersion() < static_cast(EQEmu::versions::ClientVersion::RoF2) && pp->class_ == BERSERKER) { pp->skills[Skill1HPiercing] = pp->skills[Skill2HPiercing]; pp->skills[Skill2HPiercing] = 0; } diff --git a/world/client.h b/world/client.h index d7a42ab28..b3e10db8a 100644 --- a/world/client.h +++ b/world/client.h @@ -84,7 +84,7 @@ private: uint32 pwaitingforbootup; bool StartInTutorial; - ClientVersion m_ClientVersion; + EQEmu::versions::ClientVersion m_ClientVersion; uint32 m_ClientVersionBit; bool OPCharCreate(char *name, CharCreate_Struct *cc); diff --git a/world/worlddb.cpp b/world/worlddb.cpp index af8d20eed..aed60e245 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -36,15 +36,15 @@ extern std::vector character_create_race_class_combos; void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **outApp, uint32 clientVersionBit) { /* Set Character Creation Limit */ - ClientVersion client_version = ClientVersionFromBit(clientVersionBit); + EQEmu::versions::ClientVersion client_version = EQEmu::versions::ConvertClientVersionBitToClientVersion(clientVersionBit); size_t character_limit = EQEmu::limits::CharacterCreationLimit(client_version); // Validate against absolute server max - if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT) - character_limit = EQEmu::constants::CHARACTER_CREATION_LIMIT; + if (character_limit > EQEmu::constants::CharacterCreationLimit) + character_limit = EQEmu::constants::CharacterCreationLimit; // Force Titanium clients to use '8' - if (client_version == ClientVersion::Titanium) + if (client_version == EQEmu::versions::ClientVersion::Titanium) character_limit = 8; /* Get Character Info */ diff --git a/zone/aa.cpp b/zone/aa.cpp index ec72cd707..26c168276 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -471,7 +471,7 @@ void Client::ResetAA() { database.DeleteCharacterLeadershipAAs(CharacterID()); // undefined for these clients - if (GetClientVersionBit() & BIT_TitaniumAndEarlier) + if (ClientVersionBit() & EQEmu::versions::bit_TitaniumAndEarlier) Kick(); } @@ -1411,7 +1411,7 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { //the one titanium hack i will allow //just to make sure we dont crash the client with newer aas //we'll exclude any expendable ones - if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_TitaniumAndEarlier) { + if(IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::bit_TitaniumAndEarlier) { if(ability->charges > 0) { return false; } diff --git a/zone/attack.cpp b/zone/attack.cpp index ca87d955a..7df1c1ed5 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -93,7 +93,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w } case ItemType2HPiercing: // 2H Piercing { - if (IsClient() && CastToClient()->GetClientVersion() < ClientVersion::RoF2) + if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) skillinuse = Skill1HPiercing; else skillinuse = Skill2HPiercing; @@ -1486,7 +1486,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att //this generates a lot of 'updates' to the client that the client does not need BuffFadeNonPersistDeath(); if (RuleB(Character, UnmemSpellsOnDeath)) { - if((GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover)) + if((ClientVersionBit() & EQEmu::versions::bit_SoFAndLater) && RuleB(Character, RespawnFromHover)) UnmemSpellAll(true); else UnmemSpellAll(false); @@ -1549,7 +1549,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att from these and overwrite what we set in pp anyway */ - if(LeftCorpse && (GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover)) + if(LeftCorpse && (ClientVersionBit() & EQEmu::versions::bit_SoFAndLater) && RuleB(Character, RespawnFromHover)) { ClearDraggedCorpses(); RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000); @@ -3425,14 +3425,14 @@ void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id) if (IsBuffSpell(spell_id)) { // hots // message to caster if (caster->IsClient() && caster == this) { - if (caster->CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) + if (caster->CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoFAndLater) FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, HOT_HEAL_SELF, itoa(acthealed), spells[spell_id].name); else FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, YOU_HEALED, GetCleanName(), itoa(acthealed)); } else if (caster->IsClient() && caster != this) { - if (caster->CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) + if (caster->CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoFAndLater) caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, HOT_HEAL_OTHER, GetCleanName(), itoa(acthealed), spells[spell_id].name); @@ -3442,7 +3442,7 @@ void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id) } // message to target if (IsClient() && caster != this) { - if (CastToClient()->GetClientVersionBit() & BIT_SoFAndLater) + if (CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoFAndLater) FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime, HOT_HEALED_OTHER, caster->GetCleanName(), itoa(acthealed), spells[spell_id].name); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 642cc612b..3239b514e 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -163,7 +163,7 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { } //Power Source Slot - if (GetClientVersion() >= ClientVersion::SoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { const ItemInst* inst = m_inv[SlotPowerSource]; if(inst) @@ -3293,7 +3293,7 @@ void Client::CalcItemScale() { changed = true; //Power Source Slot - if (GetClientVersion() >= ClientVersion::SoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { if(CalcItemScale(SlotPowerSource, SlotPowerSource)) changed = true; @@ -3387,7 +3387,7 @@ void Client::DoItemEnterZone() { changed = true; //Power Source Slot - if (GetClientVersion() >= ClientVersion::SoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { if(DoItemEnterZone(SlotPowerSource, SlotPowerSource)) changed = true; diff --git a/zone/bot.cpp b/zone/bot.cpp index e358d04c8..7494dd185 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1255,7 +1255,7 @@ int32 Bot::GenerateBaseHitPoints() { uint32 lm = GetClassLevelFactor(); int32 Post255; int32 NormalSTA = GetSTA(); - if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { + if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { float SoDPost255; if(((NormalSTA - 255) / 2) > 0) SoDPost255 = ((NormalSTA - 255) / 2); @@ -6127,7 +6127,7 @@ int32 Bot::GenerateBaseManaPoints() { switch(GetCasterClass()) { case 'I': WisInt = INT; - if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { + if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { if(WisInt > 100) { ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100); if(WisInt > 201) @@ -6162,7 +6162,7 @@ int32 Bot::GenerateBaseManaPoints() { break; case 'W': WisInt = WIS; - if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { + if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { if(WisInt > 100) { ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100); if(WisInt > 201) @@ -6346,7 +6346,7 @@ int32 Bot::GetMaxStat() { int32 base = 0; if (level < 61) base = 255; - else if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoF) + else if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoF) base = (255 + 5 * (level - 60)); else if (level < 71) base = (255 + 5 * (level - 60)); @@ -6841,7 +6841,7 @@ int32 Bot::CalcBaseEndurance() { int32 ConvertedStats = 0; int32 sta_end = 0; int Stats = 0; - if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { + if (GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd)) { int HeroicStats = 0; Stats = ((GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4); HeroicStats = ((GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 8b9031ff4..138a7aa02 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -4709,7 +4709,7 @@ void bot_subcommand_bot_inspect_message(Client *c, const Seperator *sep) if (helper_is_help_or_usage(sep->arg[1])) { c->Message(m_usage, "usage: %s [set | clear] ([actionable: target | byname | ownergroup | botgroup | targetgroup | namesgroup | healrotation | spawned] ([actionable_name]))", sep->arg[0]); c->Message(m_note, "Notes:"); - if (c->GetClientVersion() >= ClientVersion::SoF) { + if (c->ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { c->Message(m_message, "- Self-inspect and type your bot's inspect message"); c->Message(m_message, "- Close the self-inspect window to update the server"); c->Message(m_message, "- Type '%s set' to set the bot's inspect message", sep->arg[0]); diff --git a/zone/client.cpp b/zone/client.cpp index 0be517343..aa82bf291 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -257,7 +257,7 @@ Client::Client(EQStreamInterface* ieqs) GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS)); AttemptedMessages = 0; TotalKarma = 0; - m_ClientVersion = ClientVersion::Unknown; + m_ClientVersion = EQEmu::versions::ClientVersion::Unknown; m_ClientVersionBit = 0; AggroCount = 0; RestRegenHP = 0; @@ -1533,7 +1533,7 @@ void Client::UpdateWho(uint8 remove) { else if (m_pp.anon >= 2) scl->anon = 2; - scl->ClientVersion = static_cast(GetClientVersion()); + scl->ClientVersion = static_cast(ClientVersion()); scl->tellsoff = tellsoff; scl->guild_id = guild_id; scl->LFG = LFG; @@ -1789,7 +1789,7 @@ void Client::SendManaUpdatePacket() { if (!Connected() || IsCasting()) return; - if (GetClientVersion() >= ClientVersion::SoD) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { SendManaUpdate(); SendEnduranceUpdate(); } @@ -1824,7 +1824,7 @@ void Client::SendManaUpdatePacket() { for(int i = 0; i < MAX_GROUP_MEMBERS; ++i) - if(g->members[i] && g->members[i]->IsClient() && (g->members[i] != this) && (g->members[i]->CastToClient()->GetClientVersion() >= ClientVersion::SoD)) + if (g->members[i] && g->members[i]->IsClient() && (g->members[i] != this) && (g->members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD)) { g->members[i]->CastToClient()->QueuePacket(outapp); g->members[i]->CastToClient()->QueuePacket(outapp2); @@ -2007,7 +2007,7 @@ void Client::ReadBook(BookRequest_Struct *book) { BookText_Struct *out = (BookText_Struct *) outapp->pBuffer; out->window = book->window; - if(GetClientVersion() >= ClientVersion::SoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { const ItemInst *inst = m_inv[book->invslot]; if(inst) @@ -2364,7 +2364,7 @@ bool Client::HasSkill(SkillUseTypes skill_id) const { } bool Client::CanHaveSkill(SkillUseTypes skill_id) const { - if (GetClientVersion() < ClientVersion::RoF2 && class_ == BERSERKER && skill_id == Skill1HPiercing) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2 && class_ == BERSERKER && skill_id == Skill1HPiercing) skill_id = Skill2HPiercing; return(database.GetSkillCap(GetClass(), skill_id, RuleI(Character, MaxLevel)) > 0); @@ -2372,7 +2372,7 @@ bool Client::CanHaveSkill(SkillUseTypes skill_id) const { } uint16 Client::MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const { - if (GetClientVersion() < ClientVersion::RoF2 && class_ == BERSERKER && skillid == Skill1HPiercing) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2 && class_ == BERSERKER && skillid == Skill1HPiercing) skillid = Skill2HPiercing; return(database.GetSkillCap(class_, skillid, level)); @@ -2380,7 +2380,7 @@ uint16 Client::MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) cons uint8 Client::SkillTrainLevel(SkillUseTypes skillid, uint16 class_) { - if (GetClientVersion() < ClientVersion::RoF2 && class_ == BERSERKER && skillid == Skill1HPiercing) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2 && class_ == BERSERKER && skillid == Skill1HPiercing) skillid = Skill2HPiercing; return(database.GetTrainLevel(class_, skillid, RuleI(Character, MaxLevel))); @@ -2817,7 +2817,7 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){ Filter0(FilterMissedMe); Filter1(FilterDamageShields); - if (GetClientVersionBit() & BIT_SoDAndLater) { + if (ClientVersionBit() & EQEmu::versions::bit_SoDAndLater) { if (filter->filters[FilterDOT] == 0) ClientFilters[FilterDOT] = FilterShow; else if (filter->filters[FilterDOT] == 1) @@ -2838,7 +2838,7 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){ Filter1(FilterFocusEffects); Filter1(FilterPetSpells); - if (GetClientVersionBit() & BIT_SoDAndLater) { + if (ClientVersionBit() & EQEmu::versions::bit_SoDAndLater) { if (filter->filters[FilterHealOverTime] == 0) ClientFilters[FilterHealOverTime] = FilterShow; // This is called 'Show Mine Only' in the clients, but functions the same as show @@ -4123,7 +4123,7 @@ bool Client::GroupFollow(Client* inviter) { group->UpdateGroupAAs(); //Invite the inviter into the group first.....dont ask - if (inviter->GetClientVersion() < ClientVersion::SoD) + if (inviter->ClientVersion() < EQEmu::versions::ClientVersion::SoD) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* outgj = (GroupJoin_Struct*)outapp->pBuffer; @@ -4169,13 +4169,13 @@ bool Client::GroupFollow(Client* inviter) { return false; } - if (GetClientVersion() >= ClientVersion::SoD) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { SendGroupJoinAcknowledge(); } // Temporary hack for SoD, as things seem to work quite differently - if (inviter->IsClient() && inviter->GetClientVersion() >= ClientVersion::SoD) + if (inviter->IsClient() && inviter->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { database.RefreshGroupFromDB(inviter); } @@ -4242,7 +4242,7 @@ uint16 Client::GetPrimarySkillValue() } case ItemType2HPiercing: // 2H Piercing { - if (IsClient() && CastToClient()->GetClientVersion() < ClientVersion::RoF2) + if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) skill = Skill1HPiercing; else skill = Skill2HPiercing; @@ -4412,7 +4412,7 @@ void Client::IncrementAggroCount() { if (AggroCount == 1) SavedRaidRestTimer = rest_timer.GetRemainingTime(); - if(GetClientVersion() >= ClientVersion::SoF) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_RestState, 1); char *Buffer = (char *)outapp->pBuffer; @@ -4457,7 +4457,7 @@ void Client::DecrementAggroCount() { rest_timer.Start(time_until_rest); - if(GetClientVersion() >= ClientVersion::SoF) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_RestState, 5); char *Buffer = (char *)outapp->pBuffer; @@ -4978,12 +4978,12 @@ void Client::ShowSkillsWindow() std::string WindowText; std::map Skills = EQEmu::GetSkillUseTypesMap(); - if (GetClientVersion() < ClientVersion::RoF2) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2) Skills[Skill1HPiercing] = "Piercing"; // print out all available skills for (auto skills_iter : Skills) { - if (skills_iter.first == Skill2HPiercing && GetClientVersion() < ClientVersion::RoF2) + if (skills_iter.first == Skill2HPiercing && ClientVersion() < EQEmu::versions::ClientVersion::RoF2) continue; if (!GetSkill(skills_iter.first) && !MaxSkill(skills_iter.first)) continue; @@ -6115,7 +6115,7 @@ void Client::SendZonePoints() while(iterator.MoreElements()) { ZonePoint* data = iterator.GetData(); - if(GetClientVersionBit() & data->client_version_mask) + if(ClientVersionBit() & data->client_version_mask) { count++; } @@ -6132,7 +6132,7 @@ void Client::SendZonePoints() while(iterator.MoreElements()) { ZonePoint* data = iterator.GetData(); - if(GetClientVersionBit() & data->client_version_mask) + if(ClientVersionBit() & data->client_version_mask) { zp->zpe[i].iterator = data->number; zp->zpe[i].x = data->target_x; @@ -6852,7 +6852,7 @@ void Client::SendStatsWindow(Client* client, bool use_window) if(use_window) { if(final_stats.size() < 4096) { - uint32 Buttons = (client->GetClientVersion() < ClientVersion::SoD) ? 0 : 1; + uint32 Buttons = (client->ClientVersion() < EQEmu::versions::ClientVersion::SoD) ? 0 : 1; client->SendWindow(0, POPUPID_UPDATE_SHOWSTATSWINDOW, Buttons, "Cancel", "Update", 0, 1, this, "", "%s", final_stats.c_str()); goto Extra_Info; } @@ -6888,7 +6888,7 @@ void Client::SendStatsWindow(Client* client, bool use_window) } void Client::SendAltCurrencies() { - if(GetClientVersion() >= ClientVersion::SoF) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { uint32 count = zone->AlternateCurrencies.size(); if(count == 0) { return; @@ -7439,7 +7439,7 @@ void Client::SendMercPersonalInfo() if(mercData) { - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { if (mercCount > 0) { @@ -7550,7 +7550,7 @@ void Client::SendClearMercInfo() void Client::DuplicateLoreMessage(uint32 ItemID) { - if (!(m_ClientVersionBit & BIT_RoFAndLater)) + if (!(m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater)) { Message_StringID(0, PICK_LORE); return; diff --git a/zone/client.h b/zone/client.h index f556197a4..60582d9c4 100644 --- a/zone/client.h +++ b/zone/client.h @@ -33,7 +33,8 @@ struct Item_Struct; #include "../common/ptimer.h" #include "../common/emu_opcodes.h" #include "../common/eq_packet_structs.h" -#include "../common/eq_constants.h" +//#include "../common/eq_constants.h" +#include "../common/emu_constants.h" // inv2 watch #include "../common/eq_stream_intf.h" #include "../common/eq_packet.h" #include "../common/linked_list.h" @@ -43,7 +44,7 @@ struct Item_Struct; #include "../common/item.h" #include "../common/guilds.h" #include "../common/item_struct.h" -#include "../common/clientversions.h" +//#include "../common/clientversions.h" #include "common.h" #include "merc.h" @@ -976,9 +977,9 @@ public: inline int ActiveTasksInSet(int TaskSet) { return (taskstate ? taskstate->ActiveTasksInSet(TaskSet) :0); } inline int CompletedTasksInSet(int TaskSet) { return (taskstate ? taskstate->CompletedTasksInSet(TaskSet) :0); } - inline const ClientVersion GetClientVersion() const { return m_ClientVersion; } - inline const uint32 GetClientVersionBit() const { return m_ClientVersionBit; } - inline void SetClientVersion(ClientVersion in) { m_ClientVersion = in; } + inline const EQEmu::versions::ClientVersion ClientVersion() const { return m_ClientVersion; } + inline const uint32 ClientVersionBit() const { return m_ClientVersionBit; } + inline void SetClientVersion(EQEmu::versions::ClientVersion client_version) { m_ClientVersion = client_version; } /** Adventure Stuff **/ void SendAdventureError(const char *error); @@ -1096,7 +1097,7 @@ public: void HandleLFGuildResponse(ServerPacket *pack); void SendLFGuildStatus(); void SendGuildLFGuildStatus(); - inline bool XTargettingAvailable() const { return ((m_ClientVersionBit & BIT_UFAndLater) && RuleB(Character, EnableXTargetting)); } + inline bool XTargettingAvailable() const { return ((m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) && RuleB(Character, EnableXTargetting)); } inline uint8 GetMaxXTargets() const { return MaxXTargets; } void SetMaxXTargets(uint8 NewMax); bool IsXTarget(const Mob *m) const; @@ -1489,7 +1490,7 @@ private: Timer *GlobalChatLimiterTimer; //60 seconds uint32 AttemptedMessages; - ClientVersion m_ClientVersion; + EQEmu::versions::ClientVersion m_ClientVersion; uint32 m_ClientVersionBit; int XPRate; diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 2e2c1bf46..9dda04389 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -42,7 +42,7 @@ int32 Client::GetMaxStat() const if (level < 61) { base = 255; } - else if (GetClientVersion() >= ClientVersion::SoF) { + else if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { base = 255 + 5 * (level - 60); } else if (level < 71) { @@ -409,7 +409,7 @@ uint32 Mob::GetClassLevelFactor() int32 Client::CalcBaseHP() { - if (GetClientVersion() >= ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) { int stats = GetSTA(); if (stats > 255) { stats = (stats - 255) / 2; @@ -1162,7 +1162,7 @@ int32 Client::CalcBaseMana() switch (GetCasterClass()) { case 'I': WisInt = GetINT(); - if (GetClientVersion() >= ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) { if (WisInt > 100) { ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100); if (WisInt > 201) { @@ -1195,7 +1195,7 @@ int32 Client::CalcBaseMana() break; case 'W': WisInt = GetWIS(); - if (GetClientVersion() >= ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) { if (WisInt > 100) { ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100); if (WisInt > 201) { @@ -1355,7 +1355,7 @@ uint32 Client::CalcCurrentWeight() This is the ONLY instance I have seen where the client is hard coded to particular Item IDs to set a certain property for an item. It is very odd. */ // SoD+ client has no weight for coin - if (EQEmu::limits::CoinHasWeight(GetClientVersion())) { + if (EQEmu::limits::CoinHasWeight(EQEmu::versions::ConvertClientVersionToInventoryVersion(ClientVersion()))) { Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4; } float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat; @@ -2140,7 +2140,7 @@ void Client::CalcMaxEndurance() int32 Client::CalcBaseEndurance() { int32 base_end = 0; - if (GetClientVersion() >= ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) { double heroic_stats = (GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4.0f; double stats = (GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4.0f; if (stats > 201.0f) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 1a44650ae..e8dbbc7e8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -510,7 +510,7 @@ void Client::CompleteConnect() if (IsInAGuild()){ uint8 rank = GuildRank(); - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { switch (rank) { case 0: { rank = 5; break; } // GUILD_MEMBER 0 @@ -831,7 +831,7 @@ void Client::CompleteConnect() if (zone->GetZoneID() == RuleI(World, GuildBankZoneID) && GuildBanks) GuildBanks->SendGuildBank(this); - if (GetClientVersion() >= ClientVersion::SoD) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) entity_list.SendFindableNPCList(this); if (IsInAGuild()) { @@ -846,7 +846,7 @@ void Client::CompleteConnect() worldserver.SendPacket(pack); delete pack; - if (IsClient() && CastToClient()->GetClientVersionBit() & BIT_UFAndLater) { + if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::bit_UFAndLater) { EQApplicationPacket *outapp = MakeBuffsPacket(false); CastToClient()->FastQueuePacket(&outapp); } @@ -1044,7 +1044,7 @@ void Client::Handle_Connect_OP_ReqClientSpawn(const EQApplicationPacket *app) outapp = new EQApplicationPacket(OP_SendExpZonein, 0); FastQueuePacket(&outapp); - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { outapp = new EQApplicationPacket(OP_ClientReady, 0); FastQueuePacket(&outapp); @@ -1103,7 +1103,7 @@ void Client::Handle_Connect_OP_SendExpZonein(const EQApplicationPacket *app) safe_delete(outapp); // SoF+ Gets Zone-In packets after sending OP_WorldObjectsSent - if (GetClientVersion() < ClientVersion::SoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::SoF) { SendZoneInPackets(); } @@ -1199,8 +1199,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) conn_state = ReceivedZoneEntry; - SetClientVersion(Connection()->GetClientVersion()); - m_ClientVersionBit = ClientBitFromVersion(Connection()->GetClientVersion()); + SetClientVersion(Connection()->ClientVersion()); + m_ClientVersionBit = EQEmu::versions::ConvertClientVersionToClientVersionBit(Connection()->ClientVersion()); bool siv = m_inv.SetInventoryVersion(m_ClientVersion); Log.Out(Logs::General, Logs::None, "%s inventory version to %s(%i)", (siv ? "Succeeded in setting" : "Failed to set"), ClientVersionName(m_ClientVersion), m_ClientVersion); @@ -1387,7 +1387,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) m_pp.guild_id = GuildID(); uint8 rank = guild_mgr.GetDisplayedRank(GuildID(), GuildRank(), CharacterID()); // FIXME: RoF guild rank - if (GetClientVersion() >= ClientVersion::RoF) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { switch (rank) { case 0: rank = 5; @@ -1441,7 +1441,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000){ m_pp.ldon_points_available = 0; } if(RuleB(World, UseClientBasedExpansionSettings)) { - m_pp.expansions = ExpansionFromClientVersion(GetClientVersion()); + m_pp.expansions = EQEmu::versions::ConvertClientVersionToExpansion(ClientVersion()); } else { m_pp.expansions = RuleI(World, ExpansionSettings); @@ -1696,13 +1696,13 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /* Task Packets */ LoadClientTaskState(); - if (GetClientVersion() >= ClientVersion::RoF) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { outapp = new EQApplicationPacket(OP_ReqNewZone, 0); Handle_Connect_OP_ReqNewZone(outapp); safe_delete(outapp); } - if (m_ClientVersionBit & BIT_UFAndLater) { + if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) { outapp = new EQApplicationPacket(OP_XTargetResponse, 8); outapp->WriteUInt32(GetMaxXTargets()); outapp->WriteUInt32(0); @@ -2926,7 +2926,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) AugmentItem_Struct* in_augment = (AugmentItem_Struct*)app->pBuffer; bool deleteItems = false; - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { ItemInst *itemOneToPush = nullptr, *itemTwoToPush = nullptr; @@ -4252,7 +4252,7 @@ void Client::Handle_OP_ClickObjectAction(const EQApplicationPacket *app) QueuePacket(&end_trade2); // RoF sends a 0 sized packet for closing objects - if (GetTradeskillObject() && GetClientVersion() >= ClientVersion::RoF) + if (GetTradeskillObject() && ClientVersion() >= EQEmu::versions::ClientVersion::RoF) GetTradeskillObject()->CastToObject()->Close(); return; @@ -5141,7 +5141,7 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app) int16 AlcoholTolerance = GetSkill(SkillAlcoholTolerance); int16 IntoxicationIncrease; - if (GetClientVersion() < ClientVersion::SoD) + if (ClientVersion() < EQEmu::versions::ClientVersion::SoD) IntoxicationIncrease = (200 - AlcoholTolerance) * 30 / 200 + 10; else IntoxicationIncrease = (270 - AlcoholTolerance) * 0.111111108 + 10; @@ -5453,7 +5453,7 @@ void Client::Handle_OP_EndLootRequest(const EQApplicationPacket *app) Entity* entity = entity_list.GetID(*((uint16*)app->pBuffer)); if (entity == 0) { Message(13, "Error: OP_EndLootRequest: Corpse not found (ent = 0)"); - if (GetClientVersion() >= ClientVersion::SoD) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) Corpse::SendEndLootErrorPacket(this); else Corpse::SendLootReqErrorPacket(this); @@ -7333,11 +7333,11 @@ void Client::Handle_OP_GuildInvite(const EQApplicationPacket *app) gc->guildeqid = GuildID(); // Convert Membership Level between RoF and previous clients. - if (client->GetClientVersion() < ClientVersion::RoF && GetClientVersion() >= ClientVersion::RoF) + if (client->ClientVersion() < EQEmu::versions::ClientVersion::RoF && ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { gc->officer = 0; } - if (client->GetClientVersion() >= ClientVersion::RoF && GetClientVersion() < ClientVersion::RoF) + if (client->ClientVersion() >= EQEmu::versions::ClientVersion::RoF && ClientVersion() < EQEmu::versions::ClientVersion::RoF) { gc->officer = 8; } @@ -7378,7 +7378,7 @@ void Client::Handle_OP_GuildInviteAccept(const EQApplicationPacket *app) uint32 guildrank = gj->response; - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { if (gj->response > 9) { @@ -7413,11 +7413,11 @@ void Client::Handle_OP_GuildInviteAccept(const EQApplicationPacket *app) { Client* client = inviter->CastToClient(); // Convert Membership Level between RoF and previous clients. - if (client->GetClientVersion() < ClientVersion::RoF && GetClientVersion() >= ClientVersion::RoF) + if (client->ClientVersion() < EQEmu::versions::ClientVersion::RoF && ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { guildrank = 0; } - if (client->GetClientVersion() >= ClientVersion::RoF && GetClientVersion() < ClientVersion::RoF) + if (client->ClientVersion() >= EQEmu::versions::ClientVersion::RoF && ClientVersion() < EQEmu::versions::ClientVersion::RoF) { guildrank = 8; } @@ -7454,7 +7454,7 @@ void Client::Handle_OP_GuildInviteAccept(const EQApplicationPacket *app) guildrank = gj->response; - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { if (gj->response == 8) { @@ -8060,7 +8060,7 @@ void Client::Handle_OP_InspectRequest(const EQApplicationPacket *app) Mob* tmp = entity_list.GetMob(ins->TargetID); if (tmp != 0 && tmp->IsClient()) { - if (tmp->CastToClient()->GetClientVersion() < ClientVersion::SoF) { tmp->CastToClient()->QueuePacket(app); } // Send request to target + if (tmp->CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoF) { tmp->CastToClient()->QueuePacket(app); } // Send request to target // Inspecting an SoF or later client will make the server handle the request else { ProcessInspectRequest(tmp->CastToClient(), this); } } @@ -8563,7 +8563,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } else { - if (GetClientVersion() >= ClientVersion::SoD && !inst->IsEquipable(GetBaseRace(), GetClass())) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD && !inst->IsEquipable(GetBaseRace(), GetClass())) { if (item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink && item->ItemType != ItemTypeAlcohol) { @@ -9391,14 +9391,14 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app) return; } - mercTypeCount = tar->GetNumMercTypes(static_cast(GetClientVersion())); - mercCount = tar->GetNumMercs(static_cast(GetClientVersion())); + mercTypeCount = tar->GetNumMercTypes(static_cast(ClientVersion())); + mercCount = tar->GetNumMercs(static_cast(ClientVersion())); if (mercCount > MAX_MERC) return; - std::list mercTypeList = tar->GetMercTypesList(static_cast(GetClientVersion())); - std::list mercDataList = tar->GetMercsList(static_cast(GetClientVersion())); + std::list mercTypeList = tar->GetMercTypesList(static_cast(ClientVersion())); + std::list mercDataList = tar->GetMercsList(static_cast(ClientVersion())); int i = 0; int StanceCount = 0; @@ -11320,7 +11320,7 @@ void Client::Handle_OP_ReadBook(const EQApplicationPacket *app) } BookRequest_Struct* book = (BookRequest_Struct*)app->pBuffer; ReadBook(book); - if (GetClientVersion() >= ClientVersion::SoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { EQApplicationPacket EndOfBook(OP_FinishWindow, 0); QueuePacket(&EndOfBook); @@ -12669,7 +12669,7 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app) { if (!HasSkill(SkillHide) && GetSkill(SkillHide) == 0) { - if (GetClientVersion() < ClientVersion::SoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::SoF) { char *hack_str = nullptr; MakeAnyLenString(&hack_str, "Player sent OP_SpawnAppearance with AT_Invis: %i", sa->parameter); @@ -13519,7 +13519,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) this->Trader_StartTrader(); // This refreshes the Trader window to display the End Trader button - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_Trader, sizeof(TraderStatus_Struct)); TraderStatus_Struct* tss = (TraderStatus_Struct*)outapp->pBuffer; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 2184b35ed..301474456 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -126,7 +126,7 @@ bool Client::Process() { HandleRespawnFromHover(0); } - if(IsTracking() && (GetClientVersion() >= ClientVersion::SoD) && TrackingTimer.Check()) + if (IsTracking() && (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) && TrackingTimer.Check()) DoTracking(); // SendHPUpdate calls hpupdate_timer.Start so it can delay this timer, so lets not reset with the check @@ -800,7 +800,7 @@ void Client::BulkSendInventoryItems() { } // Power Source - if(GetClientVersion() >= ClientVersion::SoF) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { const ItemInst* inst = m_inv[SlotPowerSource]; if(inst) { std::string packet = inst->Serialize(SlotPowerSource); @@ -890,7 +890,7 @@ void Client::BulkSendInventoryItems() void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { const Item_Struct* handyitem = nullptr; uint32 numItemSlots = 80; //The max number of items passed in the transaction. - if (m_ClientVersionBit & BIT_RoFAndLater) { // RoF+ can send 200 items + if (m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater) { // RoF+ can send 200 items numItemSlots = 200; } const Item_Struct *item; @@ -1554,7 +1554,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app) } } - if (GetClientVersion() < ClientVersion::RoF2 && GetClass() == BERSERKER) { + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2 && GetClass() == BERSERKER) { gmtrain->skills[Skill1HPiercing] = gmtrain->skills[Skill2HPiercing]; gmtrain->skills[Skill2HPiercing] = 0; } @@ -1734,7 +1734,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app) } } - if(GetClientVersion() >= ClientVersion::SoF) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { // The following packet decreases the skill points left in the Training Window and // produces the 'You have increased your skill / learned the basics of' message. // @@ -2174,7 +2174,7 @@ void Client::ClearHover() entity_list.QueueClients(this, outapp, false); safe_delete(outapp); - if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UFAndLater) + if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::bit_UFAndLater) { EQApplicationPacket *outapp = MakeBuffsPacket(false); CastToClient()->FastQueuePacket(&outapp); diff --git a/zone/command.cpp b/zone/command.cpp index 530f3052a..6270c0182 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2562,7 +2562,7 @@ void command_peekinv(Client *c, const Seperator *sep) indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); } - if ((scopeWhere & peekWorn) && (targetClient->GetClientVersion() >= ClientVersion::SoF)) { + if ((scopeWhere & peekWorn) && (targetClient->ClientVersion() >= EQEmu::versions::ClientVersion::SoF)) { inst_main = targetClient->GetInv().GetItem(SlotPowerSource); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index e942a6446..2bb9883fa 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -313,7 +313,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( // cash // Let's not move the cash when 'RespawnFromHover = true' && 'client->GetClientVersion() < EQClientSoF' since the client doesn't. // (change to first client that supports 'death hover' mode, if not SoF.) - if (!RuleB(Character, RespawnFromHover) || client->GetClientVersion() < ClientVersion::SoF) { + if (!RuleB(Character, RespawnFromHover) || client->ClientVersion() < EQEmu::versions::ClientVersion::SoF) { SetCash(pp->copper, pp->silver, pp->gold, pp->platinum); pp->copper = 0; pp->silver = 0; @@ -329,7 +329,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( std::list removed_list; for(i = SLOT_BEGIN; i < EQEmu::constants::TYPE_POSSESSIONS_SIZE; ++i) { - if(i == SlotAmmo && client->GetClientVersion() >= ClientVersion::SoF) { + if (i == SlotAmmo && client->ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { item = client->GetInv().GetItem(SlotPowerSource); if (item != nullptr) { if (!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent)) @@ -1000,7 +1000,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::limits::InventoryMapSize(TypeCorpse, client->GetClientVersion()); + int corpselootlimit = EQEmu::limits::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()), TypeCorpse); for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; @@ -1060,7 +1060,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a // This is required for the 'Loot All' feature to work for SoD clients. I expect it is to tell the client that the // server has now sent all the items on the corpse. - if(client->GetClientVersion() >= ClientVersion::SoD) { SendLootReqErrorPacket(client, 6); } + if (client->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { SendLootReqErrorPacket(client, 6); } } void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { @@ -1294,7 +1294,7 @@ void Corpse::QueryLoot(Client* to) { cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::limits::InventoryMapSize(TypeCorpse, to->GetClientVersion()); + int corpselootlimit = EQEmu::limits::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()), TypeCorpse); for(; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; diff --git a/zone/entity.cpp b/zone/entity.cpp index 00da8a7dc..ee9d65b72 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -867,7 +867,7 @@ bool EntityList::MakeDoorSpawnPacket(EQApplicationPacket *app, Client *client) if (door_list.empty()) return false; - uint32 mask_test = client->GetClientVersionBit(); + uint32 mask_test = client->ClientVersionBit(); int count = 0; auto it = door_list.begin(); @@ -1474,7 +1474,7 @@ void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *ap } } - if (Send && (c->GetClientVersionBit() & ClientVersionBits)) + if (Send && (c->ClientVersionBit() & ClientVersionBits)) c->QueuePacket(app, ackreq); } } @@ -4406,7 +4406,7 @@ void EntityList::UpdateFindableNPCState(NPC *n, bool Remove) auto it = client_list.begin(); while (it != client_list.end()) { Client *c = it->second; - if (c && (c->GetClientVersion() >= ClientVersion::SoD)) + if (c && (c->ClientVersion() >= EQEmu::versions::ClientVersion::SoD)) c->QueuePacket(outapp); ++it; diff --git a/zone/groups.cpp b/zone/groups.cpp index 353751b5b..6ce658922 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -395,7 +395,7 @@ void Group::SendHPPacketsTo(Mob *member) { members[i]->CreateHPPacket(&hpapp); member->CastToClient()->QueuePacket(&hpapp, false); - if(member->CastToClient()->GetClientVersion() >= ClientVersion::SoD) + if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; @@ -426,7 +426,7 @@ void Group::SendHPPacketsFrom(Mob *member) if(members[i] && members[i] != member && members[i]->IsClient()) { members[i]->CastToClient()->QueuePacket(&hp_app); - if(members[i]->CastToClient()->GetClientVersion() >= ClientVersion::SoD) + if (members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; @@ -566,7 +566,7 @@ bool Group::DelMemberOOZ(const char *Name) { if(GroupCount() < 3) { UnDelegateMarkNPC(NPCMarkerName.c_str()); - if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < ClientVersion::SoD) { + if (GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoD) { UnDelegateMainAssist(MainAssistName.c_str()); } ClearAllNPCMarks(); @@ -724,7 +724,7 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) if(GroupCount() < 3) { UnDelegateMarkNPC(NPCMarkerName.c_str()); - if(GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->GetClientVersion() < ClientVersion::SoD) { + if (GetLeader() && GetLeader()->IsClient() && GetLeader()->CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoD) { UnDelegateMainAssist(MainAssistName.c_str()); } ClearAllNPCMarks(); @@ -1604,7 +1604,7 @@ void Group::NotifyMainTank(Client *c, uint8 toggle) if(!MainTankName.size()) return; - if(c->GetClientVersion() < ClientVersion::SoD) + if (c->ClientVersion() < EQEmu::versions::ClientVersion::SoD) { if(toggle) c->Message(0, "%s is now Main Tank.", MainTankName.c_str()); @@ -1644,7 +1644,7 @@ void Group::NotifyMainAssist(Client *c, uint8 toggle) if(!MainAssistName.size()) return; - if(c->GetClientVersion() < ClientVersion::SoD) + if (c->ClientVersion() < EQEmu::versions::ClientVersion::SoD) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); @@ -1699,7 +1699,7 @@ void Group::NotifyPuller(Client *c, uint8 toggle) if(!PullerName.size()) return; - if(c->GetClientVersion() < ClientVersion::SoD) + if (c->ClientVersion() < EQEmu::versions::ClientVersion::SoD) { if(toggle) c->Message(0, "%s is now Puller.", PullerName.c_str()); @@ -2265,7 +2265,7 @@ void Group::ChangeLeader(Mob* newleader) for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] && members[i]->IsClient()) { - if(members[i]->CastToClient()->GetClientVersion() >= ClientVersion::SoD) + if (members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) members[i]->CastToClient()->SendGroupLeaderChangePacket(newleader->GetName()); members[i]->CastToClient()->QueuePacket(outapp); diff --git a/zone/guild.cpp b/zone/guild.cpp index 7b3c104f8..ceaa40fd4 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -63,7 +63,7 @@ void Client::SendGuildMOTD(bool GetGuildMOTDReply) { void Client::SendGuildURL() { - if(GetClientVersion() < ClientVersion::SoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::SoF) return; if(IsInAGuild()) @@ -84,7 +84,7 @@ void Client::SendGuildURL() void Client::SendGuildChannel() { - if(GetClientVersion() < ClientVersion::SoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::SoF) return; if(IsInAGuild()) @@ -106,7 +106,7 @@ void Client::SendGuildChannel() void Client::SendGuildRanks() { - if(GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) return; int permissions = 30 + 1; //Static number of permissions in all EQ clients as of May 2014 @@ -149,7 +149,7 @@ void Client::SendGuildSpawnAppearance() { uint8 rank = guild_mgr.GetDisplayedRank(GuildID(), GuildRank(), CharacterID()); Log.Out(Logs::Detail, Logs::Guilds, "Sending spawn appearance for guild %d at rank %d", GuildID(), rank); SendAppearancePacket(AT_GuildID, GuildID()); - if(GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { switch (rank) { case 0: { rank = 5; break; } // GUILD_MEMBER 0 @@ -249,7 +249,7 @@ void Client::RefreshGuildInfo() if((guild_id != OldGuildID) && GuildBanks) { // Unsure about this for RoF+ ... But they don't have that action anymore so fuck it - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) ClearGuildBank(); if(guild_id != GUILD_NONE) diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index ed9957908..2ccb2bb1c 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -322,7 +322,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) { else if(c != nullptr && s->guild_id != GUILD_NONE) { //char is in zone, and has changed into a new guild, send MOTD. c->SendGuildMOTD(); - if(c->GetClientVersion() >= ClientVersion::RoF) + if (c->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { c->SendGuildRanks(); } @@ -691,7 +691,7 @@ void GuildBankManager::SendGuildBank(Client *c) auto &guild_bank = *Iterator; // RoF+ uses a bulk list packet -- This is also how the Action 0 of older clients basically works - if (c->GetClientVersionBit() & BIT_RoFAndLater) { + if (c->ClientVersionBit() & EQEmu::versions::bit_RoFAndLater) { auto outapp = new EQApplicationPacket(OP_GuildBankItemList, sizeof(GuildBankItemListEntry_Struct) * 240); for (int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i) { const Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 7a27b325e..ddba7d13f 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -56,7 +56,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { x++; } - if (GetClientVersion() >= ClientVersion::SoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) DeleteItemInInventory(SlotPowerSource, 0, true); else DeleteItemInInventory(SlotPowerSource, 0, false); // Prevents Titanium crash @@ -685,7 +685,7 @@ void Client::SendCursorBuffer() // Temporary work-around for the RoF+ Client Buffer // Instead of dealing with client moving items in cursor buffer, // we can just send the next item in the cursor buffer to the cursor. - if (GetClientVersion() < ClientVersion::RoF) { return; } + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) { return; } if (GetInv().CursorEmpty()) { return; } auto test_inst = GetInv().GetCursorItem(); @@ -898,7 +898,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI // Subordinate items in cursor buffer must be sent via ItemPacketSummonItem or we just overwrite the visible cursor and desync the client if (slot_id == SlotCursor && !cursor_empty) { // RoF+ currently has a specialized cursor handler - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendItemPacket(slot_id, &inst, ItemPacketSummonItem); } else { @@ -991,7 +991,7 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs for (int16 i = EQEmu::constants::EQUIPMENT_BEGIN; i < SlotPowerSource; i++) { // originally (i < 22) if (i == EQEmu::constants::GENERAL_BEGIN) { // added power source check for SoF+ clients - if (this->GetClientVersion() >= ClientVersion::SoF) + if (this->ClientVersion() >= EQEmu::versions::ClientVersion::SoF) i = SlotPowerSource; else break; @@ -1375,7 +1375,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (move_in->from_slot == move_in->to_slot) { // Item summon, no further processing needed if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit - if (GetClientVersion() >= ClientVersion::RoF) { return true; } // Can't do RoF+ + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { return true; } // Can't do RoF+ if (move_in->to_slot == SlotCursor) { auto test_inst = m_inv.GetItem(SlotCursor); @@ -2358,7 +2358,7 @@ void Client::RemoveNoRent(bool client_update) auto inst = m_inv[SlotPowerSource]; if (inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, SlotPowerSource); - DeleteItemInInventory(SlotPowerSource, 0, (GetClientVersion() >= ClientVersion::SoF) ? client_update : false); // Ti slot non-existent + DeleteItemInInventory(SlotPowerSource, 0, (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) ? client_update : false); // Ti slot non-existent } } @@ -2576,7 +2576,7 @@ void Client::MoveSlotNotAllowed(bool client_update) bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size, is_arrow); Log.Out(Logs::Detail, Logs::Inventory, "Slot Assignment Error: Moving %s from slot %i to %i", inst->GetItem()->Name, SlotPowerSource, free_slot_id); - PutItemInInventory(free_slot_id, *inst, (GetClientVersion() >= ClientVersion::SoF) ? client_update : false); + PutItemInInventory(free_slot_id, *inst, (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) ? client_update : false); database.SaveInventory(character_id, nullptr, SlotPowerSource); safe_delete(inst); } diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 3db1eabea..331067d36 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -854,12 +854,12 @@ void Lua_Client::SetAATitle(const char *title) { int Lua_Client::GetClientVersion() { Lua_Safe_Call_Int(); - return static_cast(self->GetClientVersion()); + return static_cast(self->ClientVersion()); } uint32 Lua_Client::GetClientVersionBit() { Lua_Safe_Call_Int(); - return self->GetClientVersionBit(); + return self->ClientVersionBit(); } void Lua_Client::SetTitleSuffix(const char *text) { diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 798fc7685..5aec9c029 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1829,14 +1829,14 @@ luabind::scope lua_register_client_version() { return luabind::class_("ClientVersion") .enum_("constants") [ - luabind::value("Unknown", static_cast(ClientVersion::Unknown)), - luabind::value("Titanium", static_cast(ClientVersion::Titanium)), - luabind::value("SoF", static_cast(ClientVersion::SoF)), - luabind::value("SoD", static_cast(ClientVersion::SoD)), - luabind::value("Underfoot", static_cast(ClientVersion::UF)), // deprecated - luabind::value("UF", static_cast(ClientVersion::UF)), - luabind::value("RoF", static_cast(ClientVersion::RoF)), - luabind::value("RoF2", static_cast(ClientVersion::RoF2)) + luabind::value("Unknown", static_cast(EQEmu::versions::ClientVersion::Unknown)), + luabind::value("Titanium", static_cast(EQEmu::versions::ClientVersion::Titanium)), + luabind::value("SoF", static_cast(EQEmu::versions::ClientVersion::SoF)), + luabind::value("SoD", static_cast(EQEmu::versions::ClientVersion::SoD)), + luabind::value("Underfoot", static_cast(EQEmu::versions::ClientVersion::UF)), // deprecated + luabind::value("UF", static_cast(EQEmu::versions::ClientVersion::UF)), + luabind::value("RoF", static_cast(EQEmu::versions::ClientVersion::RoF)), + luabind::value("RoF2", static_cast(EQEmu::versions::ClientVersion::RoF2)) ]; } diff --git a/zone/merc.cpp b/zone/merc.cpp index bb5a96b9a..ef2a4e7e6 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -50,7 +50,7 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading) _baseFR = d->FR; _basePR = d->PR; _baseCorrup = d->Corrup; - _OwnerClientVersion = static_cast(ClientVersion::Titanium); + _OwnerClientVersion = static_cast(EQEmu::versions::ClientVersion::Titanium); RestRegenHP = 0; RestRegenMana = 0; RestRegenEndurance = 0; @@ -1018,7 +1018,7 @@ int32 Merc::CalcBaseEndurance() int32 sta_end = 0; int Stats = 0; - if(GetClientVersion() >= static_cast(ClientVersion::SoD) && RuleB(Character, SoDClientUseSoDHPManaEnd)) { + if (GetClientVersion() >= static_cast(EQEmu::versions::ClientVersion::SoD) && RuleB(Character, SoDClientUseSoDHPManaEnd)) { int HeroicStats = 0; Stats = ((GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4); @@ -5127,109 +5127,109 @@ void Client::SendMercResponsePackets(uint32 ResponseType) SendMercMerchantResponsePacket(6); break; case 7: //You must dismiss your suspended mercenary before purchasing a new one! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendMercMerchantResponsePacket(7); else //You have the maximum number of mercenaries. You must dismiss one before purchasing a new one! SendMercMerchantResponsePacket(6); break; case 8: //You can not purchase a mercenary because your group is full! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendMercMerchantResponsePacket(8); else SendMercMerchantResponsePacket(7); break; case 9: //You can not purchase a mercenary because you are in combat! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) //Mercenary failed to spawn! SendMercMerchantResponsePacket(3); else SendMercMerchantResponsePacket(8); break; case 10: //You have recently dismissed a mercenary and must wait a few more seconds before you can purchase a new one! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) //Mercenary failed to spawn! SendMercMerchantResponsePacket(3); else SendMercMerchantResponsePacket(9); break; case 11: //An error occurred created your mercenary! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendMercMerchantResponsePacket(9); else SendMercMerchantResponsePacket(10); break; case 12: //Upkeep Charge Message - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendMercMerchantResponsePacket(10); else SendMercMerchantResponsePacket(11); break; case 13: // ??? - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendMercMerchantResponsePacket(11); else SendMercMerchantResponsePacket(12); break; case 14: //You ran out of funds to pay for your mercenary! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendMercMerchantResponsePacket(12); else SendMercMerchantResponsePacket(13); break; case 15: // ??? - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendMercMerchantResponsePacket(13); else SendMercMerchantResponsePacket(14); break; case 16: //Your mercenary is about to be suspended due to insufficient funds! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendMercMerchantResponsePacket(14); else SendMercMerchantResponsePacket(15); break; case 17: //There is no mercenary liaison nearby! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendMercMerchantResponsePacket(15); else SendMercMerchantResponsePacket(16); break; case 18: //You are too far from the liaison! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendMercMerchantResponsePacket(16); else SendMercMerchantResponsePacket(17); break; case 19: //You do not meet the requirements for that mercenary! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendMercMerchantResponsePacket(17); else SendMercMerchantResponsePacket(18); break; case 20: //You are unable to interact with the liaison! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) //You are too far from the liaison! SendMercMerchantResponsePacket(16); else SendMercMerchantResponsePacket(19); break; case 21: //You do not have a high enough membership level to purchase this mercenary! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) //You do not meet the requirements for that mercenary! SendMercMerchantResponsePacket(17); else SendMercMerchantResponsePacket(20); break; case 22: //Your purchase has failed because this mercenary requires a Gold membership! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) //You do not meet the requirements for that mercenary! SendMercMerchantResponsePacket(17); else SendMercMerchantResponsePacket(21); break; case 23: //Your purchase has failed because this mercenary requires at least a Silver membership! - if (GetClientVersion() < ClientVersion::RoF) + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) //You do not meet the requirements for that mercenary! SendMercMerchantResponsePacket(17); else @@ -5380,7 +5380,7 @@ bool Client::CheckCanSpawnMerc(uint32 template_id) { } // Check client version - if(static_cast(GetClientVersion()) < mercTemplate->ClientVersion) + if(static_cast(ClientVersion()) < mercTemplate->ClientVersion) { SendMercResponsePackets(3); return false; @@ -6036,7 +6036,7 @@ void Client::SetMerc(Merc* newmerc) { //Client* oldowner = entity_list.GetClientByID(newmerc->GetOwnerID()); newmerc->SetOwnerID(this->GetID()); newmerc->SetMercCharacterID(this->CharacterID()); - newmerc->SetClientVersion((uint8)this->GetClientVersion()); + newmerc->SetClientVersion((uint8)this->ClientVersion()); GetMercInfo().mercid = newmerc->GetMercID(); GetMercInfo().MercTemplateID = newmerc->GetMercTemplateID(); GetMercInfo().myTemplate = zone->GetMercTemplate(GetMercInfo().MercTemplateID); @@ -6060,7 +6060,7 @@ void Client::UpdateMercLevel() { void Client::SendMercMerchantResponsePacket(int32 response_type) { // This response packet brings up the Mercenary Manager window - if(GetClientVersion() >= ClientVersion::SoD) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryHire, sizeof(MercenaryMerchantResponse_Struct)); MercenaryMerchantResponse_Struct* mmr = (MercenaryMerchantResponse_Struct*)outapp->pBuffer; diff --git a/zone/mob.cpp b/zone/mob.cpp index 6c9b6d0ca..e488a09cb 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1284,7 +1284,7 @@ void Mob::SendHPUpdate(bool skip_self) CreateHPPacket(&hp_app); // send to people who have us targeted - entity_list.QueueClientsByTarget(this, &hp_app, false, 0, false, true, BIT_AllClients); + entity_list.QueueClientsByTarget(this, &hp_app, false, 0, false, true, EQEmu::versions::bit_AllClients); entity_list.QueueClientsByXTarget(this, &hp_app, false); entity_list.QueueToGroupsForNPCHealthAA(this, &hp_app); @@ -5031,7 +5031,7 @@ uint16 Mob::GetSkillByItemType(int ItemType) case ItemType2HBlunt: return Skill2HBlunt; case ItemType2HPiercing: - if (IsClient() && CastToClient()->GetClientVersion() < ClientVersion::RoF2) + if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) return Skill1HPiercing; else return Skill2HPiercing; diff --git a/zone/npc.cpp b/zone/npc.cpp index 7b8a21cef..ea123f32a 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -24,7 +24,7 @@ #include "../common/seperator.h" #include "../common/spdat.h" #include "../common/string_util.h" -#include "../common/clientversions.h" +#include "../common/client_version.h" // inv2 watch #include "../common/features.h" #include "../common/item.h" #include "../common/item_struct.h" diff --git a/zone/object.cpp b/zone/object.cpp index f27fa2f02..5c154b782 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -117,7 +117,7 @@ Object::Object(Client* client, const ItemInst* inst) m_data.heading = client->GetHeading(); m_data.x = client->GetX(); m_data.y = client->GetY(); - if (client->GetClientVersion() >= ClientVersion::RoF2) + if (client->ClientVersion() >= EQEmu::versions::ClientVersion::RoF2) { // RoF2 places items at player's Z, which is 0.625 of their height. m_data.z = client->GetZ() - (client->GetSize() * 0.625f); @@ -548,7 +548,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) else { coa->open = 0x00; - if (sender->GetClientVersion() >= ClientVersion::RoF) { + if (sender->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { coa->drop_id = 0xFFFFFFFF; sender->Message(0, "Someone else is using that. Try again later."); } diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 9c51b8a92..129dafd73 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -3974,7 +3974,7 @@ XS(XS_Client_GetClientVersion) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = static_cast(THIS->GetClientVersion()); + RETVAL = static_cast(THIS->ClientVersion()); XSprePUSH; PUSHu((UV)RETVAL); } XSRETURN(1); @@ -4000,7 +4000,7 @@ XS(XS_Client_GetClientVersionBit) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->GetClientVersionBit(); + RETVAL = THIS->ClientVersionBit(); XSprePUSH; PUSHu((UV)RETVAL); } XSRETURN(1); diff --git a/zone/pets.cpp b/zone/pets.cpp index 4679d1477..14d02097a 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -475,7 +475,7 @@ void Pet::SetTarget(Mob *mob) return; auto owner = GetOwner(); - if (owner && owner->IsClient() && owner->CastToClient()->GetClientVersionBit() & BIT_UFAndLater) { + if (owner && owner->IsClient() && owner->CastToClient()->ClientVersionBit() & EQEmu::versions::bit_UFAndLater) { auto app = new EQApplicationPacket(OP_PetHoTT, sizeof(ClientTarget_Struct)); auto ct = (ClientTarget_Struct *)app->pBuffer; ct->new_target = mob ? mob->GetID() : 0; diff --git a/zone/raids.cpp b/zone/raids.cpp index 7406b575f..45866884f 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -1529,7 +1529,7 @@ void Raid::SendHPPacketsTo(Client *c) { members[x].member->CreateHPPacket(&hpapp); c->QueuePacket(&hpapp, false); - if(c->GetClientVersion() >= ClientVersion::SoD) + if (c->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; @@ -1565,7 +1565,7 @@ void Raid::SendHPPacketsFrom(Mob *m) if(!m->IsClient() || ((members[x].member != m->CastToClient()) && (members[x].GroupNumber == gid))) { members[x].member->QueuePacket(&hpapp, false); - if(members[x].member->GetClientVersion() >= ClientVersion::SoD) + if (members[x].member->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 3ef86c806..929cee001 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -182,7 +182,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { pTimerType timer = pTimerCombatAbility; // RoF2+ Tiger Claw is unlinked from other monk skills, if they ever do that for other classes there will need // to be more checks here - if (GetClientVersion() >= ClientVersion::RoF2 && ca_atk->m_skill == SkillTigerClaw) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF2 && ca_atk->m_skill == SkillTigerClaw) timer = pTimerCombatAbility2; /* Check to see if actually have skill */ diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 151f20249..ee97a287f 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -135,7 +135,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (spells[spell_id].EndurUpkeep > 0) SetEndurUpkeep(true); - if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UFAndLater) + if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::bit_UFAndLater) { EQApplicationPacket *outapp = MakeBuffsPacket(false); CastToClient()->FastQueuePacket(&outapp); @@ -818,7 +818,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove { CastToClient()->SetSenseExemption(true); - if(CastToClient()->GetClientVersionBit() & BIT_SoDAndLater) + if (CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoDAndLater) { bodyType bt = BT_Undead; @@ -1627,7 +1627,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #endif // This is handled by the client prior to SoD. // - if(IsClient() && (CastToClient()->GetClientVersionBit() & BIT_SoDAndLater)) + if (IsClient() && (CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoDAndLater)) CastToClient()->LocateCorpse(); break; @@ -3374,7 +3374,7 @@ void Mob::BuffProcess() Log.Out(Logs::Detail, Logs::Spells, "Buff %d in slot %d has %d tics remaining.", buffs[buffs_i].spellid, buffs_i, buffs[buffs_i].ticsremaining); } } - else if(IsClient() && !(CastToClient()->GetClientVersionBit() & BIT_SoFAndLater)) + else if (IsClient() && !(CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoFAndLater)) { buffs[buffs_i].UpdateClient = true; } @@ -3386,7 +3386,7 @@ void Mob::BuffProcess() { CastToClient()->SendBuffDurationPacket(buffs[buffs_i]); // Hack to get UF to play nicer, RoF seems fine without it - if (CastToClient()->GetClientVersion() == ClientVersion::UF && buffs[buffs_i].numhits > 0) + if (CastToClient()->ClientVersion() == EQEmu::versions::ClientVersion::UF && buffs[buffs_i].numhits > 0) CastToClient()->SendBuffNumHitPacket(buffs[buffs_i], buffs_i); buffs[buffs_i].UpdateClient = false; } @@ -3649,7 +3649,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) case SE_LocateCorpse: { // This is handled by the client prior to SoD. - if (IsClient() && (CastToClient()->GetClientVersionBit() & BIT_SoDAndLater)) + if (IsClient() && (CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoDAndLater)) CastToClient()->LocateCorpse(); } case SE_TotalHP: { @@ -4113,7 +4113,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) { EQApplicationPacket *outapp = MakeBuffsPacket(); - entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, BIT_SoDAndLater); + entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::bit_SoDAndLater); if(IsClient() && GetTarget() == this) { CastToClient()->QueuePacket(outapp); } @@ -4123,11 +4123,11 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) if (IsNPC()) { EQApplicationPacket *outapp = MakeBuffsPacket(); - entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, BIT_SoDAndLater, true); + entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::bit_SoDAndLater, true); safe_delete(outapp); } - if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UFAndLater) + if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::bit_UFAndLater) { EQApplicationPacket *outapp = MakeBuffsPacket(false); CastToClient()->FastQueuePacket(&outapp); @@ -6574,7 +6574,7 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed){ if (spells[spell_id].resisttype == RESIST_FIRE) { if (IsClient()){ - if (CastToClient()->GetClientVersionBit() <= 4) //Titanium needs alternate graphic. + if (CastToClient()->ClientVersionBit() <= 4) //Titanium needs alternate graphic. ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_Titanium)), false, speed); else ProjectileAnimation(spell_target,(RuleI(Spells, FRProjectileItem_SOF)), false, speed); diff --git a/zone/spells.cpp b/zone/spells.cpp index fe738b444..ffc644ff0 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -259,7 +259,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, bitmask = bitmask << (CastToClient()->GetClass() - 1); if( itm && itm->GetItem()->Classes != 65535 ) { if ((itm->GetItem()->Click.Type == ET_EquipClick) && !(itm->GetItem()->Classes & bitmask)) { - if (CastToClient()->GetClientVersion() < ClientVersion::SoF) { + if (CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoF) { // They are casting a spell from an item that requires equipping but shouldn't let them equip it Log.Out(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click an equip-only effect on item %s (id: %d) which they shouldn't be able to equip!", CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID); @@ -271,14 +271,14 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, return(false); } if ((itm->GetItem()->Click.Type == ET_ClickEffect2) && !(itm->GetItem()->Classes & bitmask)) { - if (CastToClient()->GetClientVersion() < ClientVersion::SoF) { + if (CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoF) { // They are casting a spell from an item that they don't meet the race/class requirements to cast Log.Out(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click a race/class restricted effect on item %s (id: %d) which they shouldn't be able to click!", CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID); database.SetHackerFlag(CastToClient()->AccountName(), CastToClient()->GetCleanName(), "Clicking race/class restricted item with an invalid class"); } else { - if (CastToClient()->GetClientVersion() >= ClientVersion::RoF) + if (CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { // Line 181 in eqstr_us.txt was changed in RoF+ Message(15, "Your race, class, or deity cannot use this item."); @@ -292,7 +292,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, } } if( itm && (itm->GetItem()->Click.Type == ET_EquipClick) && !(item_slot <= SlotAmmo || item_slot == SlotPowerSource) ){ - if (CastToClient()->GetClientVersion() < ClientVersion::SoF) { + if (CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoF) { // They are attempting to cast a must equip clicky without having it equipped Log.Out(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click an equip-only effect on item %s (id: %d) without equiping it!", CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID); database.SetHackerFlag(CastToClient()->AccountName(), CastToClient()->GetCleanName(), "Clicking equip-only item without equiping it"); @@ -3246,7 +3246,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid { EQApplicationPacket *outapp = MakeBuffsPacket(); - entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, BIT_SoDAndLater); + entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::bit_SoDAndLater); if(IsClient() && GetTarget() == this) CastToClient()->QueuePacket(outapp); @@ -3256,7 +3256,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid if (IsNPC()) { EQApplicationPacket *outapp = MakeBuffsPacket(); - entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, BIT_SoDAndLater, true); + entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::bit_SoDAndLater, true); safe_delete(outapp); } @@ -5403,7 +5403,7 @@ void Client::SendBuffDurationPacket(Buffs_Struct &buff) void Client::SendBuffNumHitPacket(Buffs_Struct &buff, int slot) { // UF+ use this packet - if (GetClientVersion() < ClientVersion::UF) + if (ClientVersion() < EQEmu::versions::ClientVersion::UF) return; EQApplicationPacket *outapp; outapp = new EQApplicationPacket(OP_BuffCreate, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct)); @@ -5457,7 +5457,7 @@ void Mob::SendBuffsToClient(Client *c) if(!c) return; - if(c->GetClientVersionBit() & BIT_SoDAndLater) + if (c->ClientVersionBit() & EQEmu::versions::bit_SoDAndLater) { EQApplicationPacket *outapp = MakeBuffsPacket(); c->FastQueuePacket(&outapp); diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 66137dd9b..fc51c5810 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -990,7 +990,7 @@ void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, i void TaskManager::SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *TaskList) { - if (c->GetClientVersion() >= ClientVersion::RoF) + if (c->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { SendTaskSelectorNew(c, mob, TaskCount, TaskList); return; @@ -2485,7 +2485,7 @@ void TaskManager::SendTaskActivityShort(Client *c, int TaskID, int ActivityID, i TaskActivityShort_Struct* tass; - if(c->GetClientVersionBit() & BIT_RoFAndLater) + if (c->ClientVersionBit() & EQEmu::versions::bit_RoFAndLater) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_TaskActivity, 25); outapp->WriteUInt32(ClientTaskIndex); @@ -2521,7 +2521,7 @@ void TaskManager::SendTaskActivityShort(Client *c, int TaskID, int ActivityID, i void TaskManager::SendTaskActivityLong(Client *c, int TaskID, int ActivityID, int ClientTaskIndex, bool Optional, bool TaskComplete) { - if (c->GetClientVersion() >= ClientVersion::RoF) + if (c->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { SendTaskActivityNew(c, TaskID, ActivityID, ClientTaskIndex, Optional, TaskComplete); return; diff --git a/zone/trading.cpp b/zone/trading.cpp index 00850faf5..d52a25543 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1098,7 +1098,7 @@ void Client::Trader_EndTrader() { for(int i = 0; i < 80; i++) { if(gis->Items[i] != 0) { - if (Customer->GetClientVersion() >= ClientVersion::RoF) + if (Customer->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { // RoF+ use Item IDs for now tdis->ItemID = gis->Items[i]; @@ -1351,7 +1351,7 @@ void Client::NukeTraderItem(uint16 Slot,int16 Charges,uint16 Quantity,Client* Cu tdis->Unknown000 = 0; tdis->TraderID = Customer->GetID(); - if (Customer->GetClientVersion() >= ClientVersion::RoF) + if (Customer->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { // RoF+ use Item IDs for now tdis->ItemID = itemid; @@ -1487,7 +1487,7 @@ void Client::ReturnTraderReq(const EQApplicationPacket* app, int16 TraderItemCha EQApplicationPacket* outapp = nullptr; - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { outapp = new EQApplicationPacket(OP_TraderShop, sizeof(TraderBuy_Struct)); } @@ -1499,7 +1499,7 @@ void Client::ReturnTraderReq(const EQApplicationPacket* app, int16 TraderItemCha TraderBuy_Struct* outtbs = (TraderBuy_Struct*)outapp->pBuffer; memcpy(outtbs, tbs, app->size); - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { // Convert Serial Number back to Item ID for RoF+ outtbs->ItemID = itemid; @@ -1567,7 +1567,7 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic const ItemInst* BuyItem = nullptr; uint32 ItemID = 0; - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { // Convert Item ID to Serial Number for RoF+ ItemID = tbs->ItemID; @@ -1629,7 +1629,7 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic // This cannot overflow assuming MAX_TRANSACTION_VALUE, checked above, is the default of 2000000000 uint32 TotalCost = tbs->Price * outtbs->Quantity; - if(Trader->GetClientVersion() >= ClientVersion::RoF) + if (Trader->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { // RoF+ uses individual item price where older clients use total price outtbs->Price = tbs->Price; @@ -1680,7 +1680,7 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic Trader->FindAndNukeTraderItem(tbs->ItemID, outtbs->Quantity, this, 0); - if (ItemID > 0 && Trader->GetClientVersion() >= ClientVersion::RoF) + if (ItemID > 0 && Trader->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { // Convert Serial Number back to ItemID for RoF+ outtbs->ItemID = ItemID; @@ -1698,7 +1698,7 @@ void Client::SendBazaarWelcome() auto row = results.begin(); EQApplicationPacket* outapp = nullptr; - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { outapp = new EQApplicationPacket(OP_TraderShop, sizeof(BazaarWelcome_Struct)); } @@ -1716,7 +1716,7 @@ void Client::SendBazaarWelcome() bws->Traders = atoi(row[0]); bws->Items = atoi(row[1]); - if (GetClientVersion() >= ClientVersion::RoF) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { bws->Unknown012 = GetID(); } @@ -2091,7 +2091,7 @@ static void UpdateTraderCustomerPriceChanged(uint32 CustomerID, TraderCharges_St for(int i = 0; i < 80; i++) { if(gis->ItemID[i] == ItemID) { - if (Customer->GetClientVersion() >= ClientVersion::RoF) + if (Customer->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { // RoF+ use Item IDs for now tdis->ItemID = gis->ItemID[i]; @@ -2745,7 +2745,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity); VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price); - if(GetClientVersion() >= ClientVersion::SoD) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price } @@ -2769,7 +2769,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity); VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price); - if(Buyer->GetClientVersion() >= ClientVersion::SoD) + if (Buyer->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price } diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 9914fd15d..c9d3f4d5c 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -864,7 +864,7 @@ void WorldServer::Process() { database.SetGroupLeaderName(group->GetID(), Inviter->GetName()); group->UpdateGroupAAs(); - if(Inviter->CastToClient()->GetClientVersion() < ClientVersion::SoD) + if (Inviter->CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoD) { EQApplicationPacket* outapp=new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); GroupJoin_Struct* outgj=(GroupJoin_Struct*)outapp->pBuffer; diff --git a/zone/zone.cpp b/zone/zone.cpp index 08a98fb10..80d11fe8c 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1566,7 +1566,7 @@ ZonePoint* Zone::GetClosestZonePoint(const glm::vec3& location, uint32 to, Clien while(iterator.MoreElements()) { ZonePoint* zp = iterator.GetData(); - uint32 mask_test = client->GetClientVersionBit(); + uint32 mask_test = client->ClientVersionBit(); if(!(zp->client_version_mask & mask_test)) { iterator.Advance(); @@ -1620,7 +1620,7 @@ ZonePoint* Zone::GetClosestZonePointWithoutZone(float x, float y, float z, Clien while(iterator.MoreElements()) { ZonePoint* zp = iterator.GetData(); - uint32 mask_test = client->GetClientVersionBit(); + uint32 mask_test = client->ClientVersionBit(); if(!(zp->client_version_mask & mask_test)) { diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 49ac1ff49..08d31578c 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2823,7 +2823,7 @@ void ZoneDatabase::RefreshGroupFromDB(Client *client){ client->QueuePacket(outapp); safe_delete(outapp); - if(client->GetClientVersion() >= ClientVersion::SoD) { + if (client->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { group->NotifyMainTank(client, 1); group->NotifyPuller(client, 1); } diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 9c7ae87a4..8a387216e 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -562,7 +562,7 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z if (entity == 0) { Message(13, "Error: OP_EndLootRequest: Corpse not found (ent = 0)"); - if (GetClientVersion() >= ClientVersion::SoD) + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) Corpse::SendEndLootErrorPacket(this); else Corpse::SendLootReqErrorPacket(this); @@ -588,7 +588,7 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z // If we are SoF and later and are respawning from hover, we want the real zone ID, else zero to use the old hack. // if(zone->GetZoneID() == zoneID) { - if((GetClientVersionBit() & BIT_SoFAndLater) && (!RuleB(Character, RespawnFromHover) || !IsHoveringForRespawn())) + if ((ClientVersionBit() & EQEmu::versions::bit_SoFAndLater) && (!RuleB(Character, RespawnFromHover) || !IsHoveringForRespawn())) gmg->bind_zone_id = 0; else gmg->bind_zone_id = zoneID; From 1890d006a254969466463f13c9b16f6669b96de1 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 22 Apr 2016 07:34:55 -0400 Subject: [PATCH 059/693] Delinked current inventory slot enumeration and constants from EQEmu::constants and global definition --- changelog.txt | 1 + common/database.cpp | 14 +- common/database_conversions.cpp | 12 +- common/emu_constants.cpp | 222 +++++++++--------- common/emu_constants.h | 93 -------- common/emu_legacy.h | 183 ++++++++++++++- common/eq_constants.h | 88 ------- common/eq_limits.cpp | 228 +++++++++---------- common/eq_packet_structs.h | 26 +-- common/extprofile.h | 2 +- common/item.cpp | 392 ++++++++++++++++---------------- common/item_struct.h | 6 +- common/patches/rof.cpp | 126 +++++----- common/patches/rof2.cpp | 132 +++++------ common/patches/rof2_structs.h | 6 +- common/patches/sod.cpp | 46 ++-- common/patches/sof.cpp | 42 ++-- common/patches/titanium.cpp | 22 +- common/patches/uf.cpp | 50 ++-- common/say_link.cpp | 6 +- common/shareddb.cpp | 38 ++-- world/worlddb.cpp | 6 +- zone/aa.cpp | 2 +- zone/attack.cpp | 106 ++++----- zone/beacon.h | 2 +- zone/bonuses.cpp | 65 +++--- zone/bot.cpp | 272 +++++++++++----------- zone/bot.h | 6 +- zone/bot_command.cpp | 78 +++---- zone/bot_database.cpp | 24 +- zone/client.cpp | 146 ++++++------ zone/client.h | 4 +- zone/client_mods.cpp | 22 +- zone/client_packet.cpp | 62 ++--- zone/client_process.cpp | 30 +-- zone/command.cpp | 56 ++--- zone/corpse.cpp | 48 ++-- zone/corpse.h | 2 +- zone/doors.cpp | 2 +- zone/encounter.h | 2 +- zone/entity.h | 2 +- zone/forage.cpp | 14 +- zone/inventory.cpp | 358 ++++++++++++++--------------- zone/loottables.cpp | 40 ++-- zone/lua_general.cpp | 108 ++++----- zone/merc.cpp | 32 +-- zone/merc.h | 4 +- zone/mob.cpp | 12 +- zone/mob.h | 22 +- zone/mob_ai.cpp | 8 +- zone/npc.cpp | 26 +-- zone/npc.h | 4 +- zone/object.cpp | 12 +- zone/pets.cpp | 10 +- zone/questmgr.cpp | 4 +- zone/special_attacks.cpp | 122 +++++----- zone/spell_effects.cpp | 28 +-- zone/spells.cpp | 4 +- zone/tradeskills.cpp | 12 +- zone/trading.cpp | 78 +++---- zone/tribute.cpp | 30 +-- zone/tune.cpp | 42 ++-- zone/zonedb.cpp | 38 ++-- zone/zonedb.h | 2 +- zone/zonedump.h | 2 +- 65 files changed, 1835 insertions(+), 1849 deletions(-) diff --git a/changelog.txt b/changelog.txt index b019e8024..c4eff06b3 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 04/22/2016 == Uleat: Reworked ClientVersion into namespace EQEmu; Added InventoryVersion +Uleat: Delinked current inventory slot enumeration and constants from EQEmu::constants and global definition (inv2 pre-work) == 04/19/2016 == Uleat: Changed the recent EQEmu rework to eliminate the nested class design (possible cause of VS2015 update crashes - unverified) diff --git a/common/database.cpp b/common/database.cpp index d2b28f4ee..a54de2bd5 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -708,7 +708,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven /* Insert starting inventory... */ std::string invquery; - for (int16 i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::BANK_BAGS_END;) { + for (int16 i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::BANK_BAGS_END;) { const ItemInst* newinv = inv->GetItem(i); if (newinv) { invquery = StringFormat("INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)", @@ -717,16 +717,16 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven auto results = QueryDatabase(invquery); } - if (i == SlotCursor) { - i = EQEmu::constants::GENERAL_BAGS_BEGIN; + if (i == EQEmu::legacy::SlotCursor) { + i = EQEmu::legacy::GENERAL_BAGS_BEGIN; continue; } - else if (i == EQEmu::constants::CURSOR_BAG_END) { - i = EQEmu::constants::BANK_BEGIN; + else if (i == EQEmu::legacy::CURSOR_BAG_END) { + i = EQEmu::legacy::BANK_BEGIN; continue; } - else if (i == EQEmu::constants::BANK_END) { - i = EQEmu::constants::BANK_BAGS_BEGIN; + else if (i == EQEmu::legacy::BANK_END) { + i = EQEmu::legacy::BANK_BAGS_BEGIN; continue; } i++; diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index 35c0ec939..058c3ad2c 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -186,7 +186,7 @@ namespace Convert { /*002*/ uint32 HP; /*006*/ uint32 Mana; /*010*/ Convert::SpellBuff_Struct Buffs[BUFF_COUNT]; - /*510*/ uint32 Items[MaterialCount]; + /*510*/ uint32 Items[EQEmu::legacy::MaterialCount]; /*546*/ char Name[64]; /*610*/ }; @@ -227,9 +227,9 @@ namespace Convert { /*0304*/ uint8 ability_time_minutes; /*0305*/ uint8 ability_time_hours; //place holder /*0306*/ uint8 unknown0306[6]; // @bp Spacer/Flag? - /*0312*/ uint32 item_material[MaterialCount]; // Item texture/material of worn/held items + /*0312*/ uint32 item_material[EQEmu::legacy::MaterialCount]; // Item texture/material of worn/held items /*0348*/ uint8 unknown0348[44]; - /*0392*/ Convert::Color_Struct item_tint[MaterialCount]; + /*0392*/ Convert::Color_Struct item_tint[EQEmu::legacy::MaterialCount]; /*0428*/ Convert::AA_Array aa_array[MAX_PP_AA_ARRAY]; /*2348*/ float unknown2384; //seen ~128, ~47 /*2352*/ char servername[32]; // length probably not right @@ -330,7 +330,7 @@ namespace Convert { /*7212*/ uint32 tribute_points; /*7216*/ uint32 unknown7252; /*7220*/ uint32 tribute_active; //1=active - /*7224*/ Convert::Tribute_Struct tributes[EQEmu::constants::TRIBUTE_SIZE]; + /*7224*/ Convert::Tribute_Struct tributes[EQEmu::legacy::TRIBUTE_SIZE]; /*7264*/ Convert::Disciplines_Struct disciplines; /*7664*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use) /*7744*/ char unknown7780[160]; @@ -1416,7 +1416,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){ if (rquery != ""){ results = QueryDatabase(rquery); } /* Run Material Color Convert */ first_entry = 0; rquery = ""; - for (i = 0; i < MaterialCount; i++){ + for (i = 0; i < EQEmu::legacy::MaterialCount; i++){ if (pp->item_tint[i].color > 0){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); @@ -1428,7 +1428,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){ if (rquery != ""){ results = QueryDatabase(rquery); } /* Run Tribute Convert */ first_entry = 0; rquery = ""; - for (i = 0; i < EQEmu::constants::TRIBUTE_SIZE; i++){ + for (i = 0; i < EQEmu::legacy::TRIBUTE_SIZE; i++){ if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 4294967295){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); diff --git a/common/emu_constants.cpp b/common/emu_constants.cpp index b8024ee9e..8085f3004 100644 --- a/common/emu_constants.cpp +++ b/common/emu_constants.cpp @@ -24,56 +24,56 @@ uint16 EQEmu::constants::InventoryTypeSize(int16 type_index) { switch (type_index) { - case TypePossessions: - return TYPE_POSSESSIONS_SIZE; - case TypeBank: - return TYPE_BANK_SIZE; - case TypeSharedBank: - return TYPE_SHARED_BANK_SIZE; - case TypeTrade: - return TYPE_TRADE_SIZE; - case TypeWorld: - return TYPE_WORLD_SIZE; - case TypeLimbo: - return TYPE_LIMBO_SIZE; - case TypeTribute: - return TYPE_TRIBUTE_SIZE; - case TypeTrophyTribute: - return TYPE_TROPHY_TRIBUTE_SIZE; - case TypeGuildTribute: - return TYPE_GUILD_TRIBUTE_SIZE; - case TypeMerchant: - return TYPE_MERCHANT_SIZE; - case TypeDeleted: - return TYPE_DELETED_SIZE; - case TypeCorpse: - return TYPE_CORPSE_SIZE; - case TypeBazaar: - return TYPE_BAZAAR_SIZE; - case TypeInspect: - return TYPE_INSPECT_SIZE; - case TypeRealEstate: - return TYPE_REAL_ESTATE_SIZE; - case TypeViewMODPC: - return TYPE_VIEW_MOD_PC_SIZE; - case TypeViewMODBank: - return TYPE_VIEW_MOD_BANK_SIZE; - case TypeViewMODSharedBank: - return TYPE_VIEW_MOD_SHARED_BANK_SIZE; - case TypeViewMODLimbo: - return TYPE_VIEW_MOD_LIMBO_SIZE; - case TypeAltStorage: - return TYPE_ALT_STORAGE_SIZE; - case TypeArchived: - return TYPE_ARCHIVED_SIZE; - case TypeMail: - return TYPE_MAIL_SIZE; - case TypeGuildTrophyTribute: - return TYPE_GUILD_TROPHY_TRIBUTE_SIZE; - case TypeKrono: - return TYPE_KRONO_SIZE; - case TypeOther: - return TYPE_OTHER_SIZE; + case legacy::TypePossessions: + return legacy::TYPE_POSSESSIONS_SIZE; + case legacy::TypeBank: + return legacy::TYPE_BANK_SIZE; + case legacy::TypeSharedBank: + return legacy::TYPE_SHARED_BANK_SIZE; + case legacy::TypeTrade: + return legacy::TYPE_TRADE_SIZE; + case legacy::TypeWorld: + return legacy::TYPE_WORLD_SIZE; + case legacy::TypeLimbo: + return legacy::TYPE_LIMBO_SIZE; + case legacy::TypeTribute: + return legacy::TYPE_TRIBUTE_SIZE; + case legacy::TypeTrophyTribute: + return legacy::TYPE_TROPHY_TRIBUTE_SIZE; + case legacy::TypeGuildTribute: + return legacy::TYPE_GUILD_TRIBUTE_SIZE; + case legacy::TypeMerchant: + return legacy::TYPE_MERCHANT_SIZE; + case legacy::TypeDeleted: + return legacy::TYPE_DELETED_SIZE; + case legacy::TypeCorpse: + return legacy::TYPE_CORPSE_SIZE; + case legacy::TypeBazaar: + return legacy::TYPE_BAZAAR_SIZE; + case legacy::TypeInspect: + return legacy::TYPE_INSPECT_SIZE; + case legacy::TypeRealEstate: + return legacy::TYPE_REAL_ESTATE_SIZE; + case legacy::TypeViewMODPC: + return legacy::TYPE_VIEW_MOD_PC_SIZE; + case legacy::TypeViewMODBank: + return legacy::TYPE_VIEW_MOD_BANK_SIZE; + case legacy::TypeViewMODSharedBank: + return legacy::TYPE_VIEW_MOD_SHARED_BANK_SIZE; + case legacy::TypeViewMODLimbo: + return legacy::TYPE_VIEW_MOD_LIMBO_SIZE; + case legacy::TypeAltStorage: + return legacy::TYPE_ALT_STORAGE_SIZE; + case legacy::TypeArchived: + return legacy::TYPE_ARCHIVED_SIZE; + case legacy::TypeMail: + return legacy::TYPE_MAIL_SIZE; + case legacy::TypeGuildTrophyTribute: + return legacy::TYPE_GUILD_TROPHY_TRIBUTE_SIZE; + case legacy::TypeKrono: + return legacy::TYPE_KRONO_SIZE; + case legacy::TypeOther: + return legacy::TYPE_OTHER_SIZE; default: return NOT_USED; } @@ -94,55 +94,55 @@ const char* EQEmu::constants::InventoryTypeName(int16 type_index) switch (type_index) { case INVALID_INDEX: return "Invalid Type"; - case TypePossessions: + case legacy::TypePossessions: return "Possessions"; - case TypeBank: + case legacy::TypeBank: return "Bank"; - case TypeSharedBank: + case legacy::TypeSharedBank: return "SharedBank"; - case TypeTrade: + case legacy::TypeTrade: return "Trade"; - case TypeWorld: + case legacy::TypeWorld: return "World"; - case TypeLimbo: + case legacy::TypeLimbo: return "Limbo"; - case TypeTribute: + case legacy::TypeTribute: return "Tribute"; - case TypeTrophyTribute: + case legacy::TypeTrophyTribute: return "TrophyTribute"; - case TypeGuildTribute: + case legacy::TypeGuildTribute: return "GuildTribute"; - case TypeMerchant: + case legacy::TypeMerchant: return "Merchant"; - case TypeDeleted: + case legacy::TypeDeleted: return "Deleted"; - case TypeCorpse: + case legacy::TypeCorpse: return "Corpse"; - case TypeBazaar: + case legacy::TypeBazaar: return "Bazaar"; - case TypeInspect: + case legacy::TypeInspect: return "Inspect"; - case TypeRealEstate: + case legacy::TypeRealEstate: return "RealEstate"; - case TypeViewMODPC: + case legacy::TypeViewMODPC: return "ViewMODPC"; - case TypeViewMODBank: + case legacy::TypeViewMODBank: return "ViewMODBank"; - case TypeViewMODSharedBank: + case legacy::TypeViewMODSharedBank: return "ViewMODSharedBank"; - case TypeViewMODLimbo: + case legacy::TypeViewMODLimbo: return "ViewMODLimbo"; - case TypeAltStorage: + case legacy::TypeAltStorage: return "AltStorage"; - case TypeArchived: + case legacy::TypeArchived: return "Archived"; - case TypeMail: + case legacy::TypeMail: return "Mail"; - case TypeGuildTrophyTribute: + case legacy::TypeGuildTrophyTribute: return "GuildTrophyTribute"; - case TypeKrono: + case legacy::TypeKrono: return "Krono"; - case TypeOther: + case legacy::TypeOther: return "Other"; default: return "Unknown Type"; @@ -154,75 +154,75 @@ const char* EQEmu::constants::InventorySlotName(int16 slot_index) switch (slot_index) { case INVALID_INDEX: return "Invalid Slot"; - case SlotCharm: + case legacy::SlotCharm: return "Charm"; - case SlotEar1: + case legacy::SlotEar1: return "Ear1"; - case SlotHead: + case legacy::SlotHead: return "Head"; - case SlotFace: + case legacy::SlotFace: return "Face"; - case SlotEar2: + case legacy::SlotEar2: return "Ear2"; - case SlotNeck: + case legacy::SlotNeck: return "Neck"; - case SlotShoulders: + case legacy::SlotShoulders: return "Shoulders"; - case SlotArms: + case legacy::SlotArms: return "Arms"; - case SlotBack: + case legacy::SlotBack: return "Back"; - case SlotWrist1: + case legacy::SlotWrist1: return "Wrist1"; - case SlotWrist2: + case legacy::SlotWrist2: return "Wrist2"; - case SlotRange: + case legacy::SlotRange: return "Range"; - case SlotHands: + case legacy::SlotHands: return "Hands"; - case SlotPrimary: + case legacy::SlotPrimary: return "Primary"; - case SlotSecondary: + case legacy::SlotSecondary: return "Secondary"; - case SlotFinger1: + case legacy::SlotFinger1: return "Finger1"; - case SlotFinger2: + case legacy::SlotFinger2: return "Finger2"; - case SlotChest: + case legacy::SlotChest: return "Chest"; - case SlotLegs: + case legacy::SlotLegs: return "Legs"; - case SlotFeet: + case legacy::SlotFeet: return "Feet"; - case SlotWaist: + case legacy::SlotWaist: return "Waist"; - case SlotPowerSource: + case legacy::SlotPowerSource: return "PowerSource"; - case SlotAmmo: + case legacy::SlotAmmo: return "Ammo"; - case SlotGeneral1: + case legacy::SlotGeneral1: return "General1"; - case SlotGeneral2: + case legacy::SlotGeneral2: return "General2"; - case SlotGeneral3: + case legacy::SlotGeneral3: return "General3"; - case SlotGeneral4: + case legacy::SlotGeneral4: return "General4"; - case SlotGeneral5: + case legacy::SlotGeneral5: return "General5"; - case SlotGeneral6: + case legacy::SlotGeneral6: return "General6"; - case SlotGeneral7: + case legacy::SlotGeneral7: return "General7"; - case SlotGeneral8: + case legacy::SlotGeneral8: return "General8"; /* - case SlotGeneral9: + case legacy::SlotGeneral9: return "General9"; - case SlotGeneral10: + case legacy::SlotGeneral10: return "General10"; */ - case SlotCursor: + case legacy::SlotCursor: return "Cursor"; default: return "Unknown Slot"; @@ -234,7 +234,7 @@ const char* EQEmu::constants::InventorySubName(int16 sub_index) if (sub_index == INVALID_INDEX) return "Invalid Sub"; - if ((uint16)sub_index >= ITEM_CONTAINER_SIZE) + if ((uint16)sub_index >= legacy::ITEM_CONTAINER_SIZE) return "Unknown Sub"; static std::string ret_str; @@ -248,7 +248,7 @@ const char* EQEmu::constants::InventoryAugName(int16 aug_index) if (aug_index == INVALID_INDEX) return "Invalid Aug"; - if ((uint16)aug_index >= ITEM_COMMON_SIZE) + if ((uint16)aug_index >= legacy::ITEM_COMMON_SIZE) return "Unknown Aug"; static std::string ret_str; diff --git a/common/emu_constants.h b/common/emu_constants.h index 1cc6c9e5a..a012e8534 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -55,99 +55,6 @@ namespace EQEmu extern const char* InventorySlotName(int16 slot_index); extern const char* InventorySubName(int16 sub_index); extern const char* InventoryAugName(int16 aug_index); - - // these are currently hard-coded for existing inventory system..do not use in place of special client version handlers until ready - static const uint16 TYPE_POSSESSIONS_SIZE = SlotCount; - static const uint16 TYPE_BANK_SIZE = 24; - static const uint16 TYPE_SHARED_BANK_SIZE = 2; - static const uint16 TYPE_TRADE_SIZE = 8; - static const uint16 TYPE_WORLD_SIZE = 10; - static const uint16 TYPE_LIMBO_SIZE = 36; - static const uint16 TYPE_TRIBUTE_SIZE = 5; // (need client values) - static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; - static const uint16 TYPE_MERCHANT_SIZE = 0; - static const uint16 TYPE_DELETED_SIZE = 0; - static const uint16 TYPE_CORPSE_SIZE = SlotCount; // no bitmask use..limits to size of client corpse window (see EQLimits::InventoryMapSize(MapCorpse, or NOT_USED value to avoid unnecessary issues - static const uint16 local[TypeCount][versions::InventoryVersionCount] = { + static const uint16 local[legacy::TypeCount][versions::InventoryVersionCount] = { // server and database are sync'd to current TypePossessions's client as set in 'using namespace RoF::slots;' and // 'constants::TYPE_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() // for partial range validation checks and 'constants::TYPE_POSSESSIONS_SIZE' for full range iterations { // local[TypePossessions] /*Unknown*/ NOT_USED, -/*62*/ constants::TYPE_POSSESSIONS_SIZE, -/*Titanium*/ constants::TYPE_POSSESSIONS_SIZE, -/*SoF*/ constants::TYPE_POSSESSIONS_SIZE, -/*SoD*/ constants::TYPE_POSSESSIONS_SIZE, -/*Underfoot*/ constants::TYPE_POSSESSIONS_SIZE, -/*RoF*/ constants::TYPE_POSSESSIONS_SIZE, -/*RoF2*/ constants::TYPE_POSSESSIONS_SIZE, +/*62*/ legacy::TYPE_POSSESSIONS_SIZE, +/*Titanium*/ legacy::TYPE_POSSESSIONS_SIZE, +/*SoF*/ legacy::TYPE_POSSESSIONS_SIZE, +/*SoD*/ legacy::TYPE_POSSESSIONS_SIZE, +/*Underfoot*/ legacy::TYPE_POSSESSIONS_SIZE, +/*RoF*/ legacy::TYPE_POSSESSIONS_SIZE, +/*RoF2*/ legacy::TYPE_POSSESSIONS_SIZE, -/*NPC*/ constants::TYPE_POSSESSIONS_SIZE, -/*Merc*/ constants::TYPE_POSSESSIONS_SIZE, -/*Bot*/ constants::TYPE_POSSESSIONS_SIZE, -/*Pet*/ constants::TYPE_POSSESSIONS_SIZE +/*NPC*/ legacy::TYPE_POSSESSIONS_SIZE, +/*Merc*/ legacy::TYPE_POSSESSIONS_SIZE, +/*Bot*/ legacy::TYPE_POSSESSIONS_SIZE, +/*Pet*/ legacy::TYPE_POSSESSIONS_SIZE }, { // local[TypeBank] /*Unknown*/ NOT_USED, /*62*/ NOT_USED, /*Titanium*/ Titanium::consts::TYPE_BANK_SIZE, -/*SoF*/ constants::TYPE_BANK_SIZE, -/*SoD*/ constants::TYPE_BANK_SIZE, -/*Underfoot*/ constants::TYPE_BANK_SIZE, -/*RoF*/ constants::TYPE_BANK_SIZE, -/*RoF2*/ constants::TYPE_BANK_SIZE, +/*SoF*/ legacy::TYPE_BANK_SIZE, +/*SoD*/ legacy::TYPE_BANK_SIZE, +/*Underfoot*/ legacy::TYPE_BANK_SIZE, +/*RoF*/ legacy::TYPE_BANK_SIZE, +/*RoF2*/ legacy::TYPE_BANK_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -92,13 +92,13 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver }, { // local[TypeSharedBank] /*Unknown*/ NOT_USED, -/*62*/ constants::TYPE_SHARED_BANK_SIZE, -/*Titanium*/ constants::TYPE_SHARED_BANK_SIZE, -/*SoF*/ constants::TYPE_SHARED_BANK_SIZE, -/*SoD*/ constants::TYPE_SHARED_BANK_SIZE, -/*Underfoot*/ constants::TYPE_SHARED_BANK_SIZE, -/*RoF*/ constants::TYPE_SHARED_BANK_SIZE, -/*RoF2*/ constants::TYPE_SHARED_BANK_SIZE, +/*62*/ legacy::TYPE_SHARED_BANK_SIZE, +/*Titanium*/ legacy::TYPE_SHARED_BANK_SIZE, +/*SoF*/ legacy::TYPE_SHARED_BANK_SIZE, +/*SoD*/ legacy::TYPE_SHARED_BANK_SIZE, +/*Underfoot*/ legacy::TYPE_SHARED_BANK_SIZE, +/*RoF*/ legacy::TYPE_SHARED_BANK_SIZE, +/*RoF2*/ legacy::TYPE_SHARED_BANK_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -107,28 +107,28 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver }, { // local[TypeTrade] /*Unknown*/ NOT_USED, -/*62*/ constants::TYPE_TRADE_SIZE, -/*Titanium*/ constants::TYPE_TRADE_SIZE, -/*SoF*/ constants::TYPE_TRADE_SIZE, -/*SoD*/ constants::TYPE_TRADE_SIZE, -/*Underfoot*/ constants::TYPE_TRADE_SIZE, -/*RoF*/ constants::TYPE_TRADE_SIZE, -/*RoF2*/ constants::TYPE_TRADE_SIZE, +/*62*/ legacy::TYPE_TRADE_SIZE, +/*Titanium*/ legacy::TYPE_TRADE_SIZE, +/*SoF*/ legacy::TYPE_TRADE_SIZE, +/*SoD*/ legacy::TYPE_TRADE_SIZE, +/*Underfoot*/ legacy::TYPE_TRADE_SIZE, +/*RoF*/ legacy::TYPE_TRADE_SIZE, +/*RoF2*/ legacy::TYPE_TRADE_SIZE, /*NPC*/ 4, /*Merc*/ 4, -/*Bot*/ constants::TYPE_TRADE_SIZE, // client thinks this is another client +/*Bot*/ legacy::TYPE_TRADE_SIZE, // client thinks this is another client /*Pet*/ 4 }, { // local[TypeWorld] /*Unknown*/ NOT_USED, -/*62*/ constants::TYPE_WORLD_SIZE, -/*Titanium*/ constants::TYPE_WORLD_SIZE, -/*SoF*/ constants::TYPE_WORLD_SIZE, -/*SoD*/ constants::TYPE_WORLD_SIZE, -/*Underfoot*/ constants::TYPE_WORLD_SIZE, -/*RoF*/ constants::TYPE_WORLD_SIZE, -/*RoF2*/ constants::TYPE_WORLD_SIZE, +/*62*/ legacy::TYPE_WORLD_SIZE, +/*Titanium*/ legacy::TYPE_WORLD_SIZE, +/*SoF*/ legacy::TYPE_WORLD_SIZE, +/*SoD*/ legacy::TYPE_WORLD_SIZE, +/*Underfoot*/ legacy::TYPE_WORLD_SIZE, +/*RoF*/ legacy::TYPE_WORLD_SIZE, +/*RoF2*/ legacy::TYPE_WORLD_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -137,13 +137,13 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver }, { // local[TypeLimbo] /*Unknown*/ NOT_USED, -/*62*/ constants::TYPE_LIMBO_SIZE, -/*Titanium*/ constants::TYPE_LIMBO_SIZE, -/*SoF*/ constants::TYPE_LIMBO_SIZE, -/*SoD*/ constants::TYPE_LIMBO_SIZE, -/*Underfoot*/ constants::TYPE_LIMBO_SIZE, -/*RoF*/ constants::TYPE_LIMBO_SIZE, -/*RoF2*/ constants::TYPE_LIMBO_SIZE, +/*62*/ legacy::TYPE_LIMBO_SIZE, +/*Titanium*/ legacy::TYPE_LIMBO_SIZE, +/*SoF*/ legacy::TYPE_LIMBO_SIZE, +/*SoD*/ legacy::TYPE_LIMBO_SIZE, +/*Underfoot*/ legacy::TYPE_LIMBO_SIZE, +/*RoF*/ legacy::TYPE_LIMBO_SIZE, +/*RoF2*/ legacy::TYPE_LIMBO_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -152,13 +152,13 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver }, { // local[TypeTribute] /*Unknown*/ NOT_USED, -/*62*/ constants::TYPE_TRIBUTE_SIZE, -/*Titanium*/ constants::TYPE_TRIBUTE_SIZE, -/*SoF*/ constants::TYPE_TRIBUTE_SIZE, -/*SoD*/ constants::TYPE_TRIBUTE_SIZE, -/*Underfoot*/ constants::TYPE_TRIBUTE_SIZE, -/*RoF*/ constants::TYPE_TRIBUTE_SIZE, -/*RoF2*/ constants::TYPE_TRIBUTE_SIZE, +/*62*/ legacy::TYPE_TRIBUTE_SIZE, +/*Titanium*/ legacy::TYPE_TRIBUTE_SIZE, +/*SoF*/ legacy::TYPE_TRIBUTE_SIZE, +/*SoD*/ legacy::TYPE_TRIBUTE_SIZE, +/*Underfoot*/ legacy::TYPE_TRIBUTE_SIZE, +/*RoF*/ legacy::TYPE_TRIBUTE_SIZE, +/*RoF2*/ legacy::TYPE_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -172,8 +172,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ constants::TYPE_TROPHY_TRIBUTE_SIZE, +/*RoF*/ legacy::TYPE_TROPHY_TRIBUTE_SIZE, +/*RoF2*/ legacy::TYPE_TROPHY_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -187,8 +187,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_GUILD_TRIBUTE_SIZE, -/*RoF2*/ constants::TYPE_GUILD_TRIBUTE_SIZE, +/*RoF*/ legacy::TYPE_GUILD_TRIBUTE_SIZE, +/*RoF2*/ legacy::TYPE_GUILD_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -202,8 +202,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_MERCHANT_SIZE, -/*RoF2*/ constants::TYPE_MERCHANT_SIZE, +/*RoF*/ legacy::TYPE_MERCHANT_SIZE, +/*RoF2*/ legacy::TYPE_MERCHANT_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -217,8 +217,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_DELETED_SIZE, -/*RoF2*/ constants::TYPE_DELETED_SIZE, +/*RoF*/ legacy::TYPE_DELETED_SIZE, +/*RoF2*/ legacy::TYPE_DELETED_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -242,15 +242,15 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver }, { // local[TypeBazaar] /*Unknown*/ NOT_USED, -/*62*/ constants::TYPE_BAZAAR_SIZE, -/*Titanium*/ constants::TYPE_BAZAAR_SIZE, -/*SoF*/ constants::TYPE_BAZAAR_SIZE, -/*SoD*/ constants::TYPE_BAZAAR_SIZE, -/*Underfoot*/ constants::TYPE_BAZAAR_SIZE, -/*RoF*/ constants::TYPE_BAZAAR_SIZE, -/*RoF2*/ constants::TYPE_BAZAAR_SIZE, +/*62*/ legacy::TYPE_BAZAAR_SIZE, +/*Titanium*/ legacy::TYPE_BAZAAR_SIZE, +/*SoF*/ legacy::TYPE_BAZAAR_SIZE, +/*SoD*/ legacy::TYPE_BAZAAR_SIZE, +/*Underfoot*/ legacy::TYPE_BAZAAR_SIZE, +/*RoF*/ legacy::TYPE_BAZAAR_SIZE, +/*RoF2*/ legacy::TYPE_BAZAAR_SIZE, -/*NPC*/ 0, // this may need to be 'constants::TYPE_BAZAAR_SIZE' if offline client traders respawn as an npc +/*NPC*/ 0, // this may need to be 'legacy::TYPE_BAZAAR_SIZE' if offline client traders respawn as an npc /*Merc*/ 0, /*Bot*/ 0, /*Pet*/ 0 @@ -277,8 +277,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_REAL_ESTATE_SIZE, -/*RoF2*/ constants::TYPE_REAL_ESTATE_SIZE, +/*RoF*/ legacy::TYPE_REAL_ESTATE_SIZE, +/*RoF2*/ legacy::TYPE_REAL_ESTATE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -292,8 +292,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_VIEW_MOD_PC_SIZE, -/*RoF2*/ constants::TYPE_VIEW_MOD_PC_SIZE, +/*RoF*/ legacy::TYPE_VIEW_MOD_PC_SIZE, +/*RoF2*/ legacy::TYPE_VIEW_MOD_PC_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -307,8 +307,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_VIEW_MOD_BANK_SIZE, -/*RoF2*/ constants::TYPE_VIEW_MOD_BANK_SIZE, +/*RoF*/ legacy::TYPE_VIEW_MOD_BANK_SIZE, +/*RoF2*/ legacy::TYPE_VIEW_MOD_BANK_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -322,8 +322,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, -/*RoF2*/ constants::TYPE_VIEW_MOD_SHARED_BANK_SIZE, +/*RoF*/ legacy::TYPE_VIEW_MOD_SHARED_BANK_SIZE, +/*RoF2*/ legacy::TYPE_VIEW_MOD_SHARED_BANK_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -337,8 +337,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_VIEW_MOD_LIMBO_SIZE, -/*RoF2*/ constants::TYPE_VIEW_MOD_LIMBO_SIZE, +/*RoF*/ legacy::TYPE_VIEW_MOD_LIMBO_SIZE, +/*RoF2*/ legacy::TYPE_VIEW_MOD_LIMBO_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -352,8 +352,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_ALT_STORAGE_SIZE, -/*RoF2*/ constants::TYPE_ALT_STORAGE_SIZE, +/*RoF*/ legacy::TYPE_ALT_STORAGE_SIZE, +/*RoF2*/ legacy::TYPE_ALT_STORAGE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -367,8 +367,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_ARCHIVED_SIZE, -/*RoF2*/ constants::TYPE_ARCHIVED_SIZE, +/*RoF*/ legacy::TYPE_ARCHIVED_SIZE, +/*RoF2*/ legacy::TYPE_ARCHIVED_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -382,8 +382,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_MAIL_SIZE, -/*RoF2*/ constants::TYPE_MAIL_SIZE, +/*RoF*/ legacy::TYPE_MAIL_SIZE, +/*RoF2*/ legacy::TYPE_MAIL_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -397,8 +397,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ constants::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, +/*RoF*/ legacy::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, +/*RoF2*/ legacy::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -412,8 +412,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ NOT_USED, /*SoD*/ NOT_USED, /*Underfoot*/ NOT_USED, -/*RoF*/ constants::TYPE_KRONO_SIZE, -/*RoF2*/ constants::TYPE_KRONO_SIZE, +/*RoF*/ legacy::TYPE_KRONO_SIZE, +/*RoF2*/ legacy::TYPE_KRONO_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -427,8 +427,8 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver /*SoF*/ 0, /*SoD*/ 0, /*Underfoot*/ 0, -/*RoF*/ constants::TYPE_OTHER_SIZE, -/*RoF2*/ constants::TYPE_OTHER_SIZE, +/*RoF*/ legacy::TYPE_OTHER_SIZE, +/*RoF2*/ legacy::TYPE_OTHER_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -437,7 +437,7 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver } }; - if ((uint16)inv_type < TypeCount) + if ((uint16)inv_type < legacy::TypeCount) return local[inv_type][static_cast(versions::ValidateInventoryVersion(inventory_version))]; return NOT_USED; @@ -584,18 +584,18 @@ uint16 EQEmu::limits::ItemCommonSize(versions::InventoryVersion inventory_versio { static const uint16 local[versions::InventoryVersionCount] = { /*Unknown*/ NOT_USED, -/*62*/ constants::ITEM_COMMON_SIZE, -/*Titanium*/ constants::ITEM_COMMON_SIZE, -/*SoF*/ constants::ITEM_COMMON_SIZE, -/*SoD*/ constants::ITEM_COMMON_SIZE, -/*Underfoot*/ constants::ITEM_COMMON_SIZE, -/*RoF*/ constants::ITEM_COMMON_SIZE, -/*RoF2*/ constants::ITEM_COMMON_SIZE, +/*62*/ legacy::ITEM_COMMON_SIZE, +/*Titanium*/ legacy::ITEM_COMMON_SIZE, +/*SoF*/ legacy::ITEM_COMMON_SIZE, +/*SoD*/ legacy::ITEM_COMMON_SIZE, +/*Underfoot*/ legacy::ITEM_COMMON_SIZE, +/*RoF*/ legacy::ITEM_COMMON_SIZE, +/*RoF2*/ legacy::ITEM_COMMON_SIZE, -/*NPC*/ constants::ITEM_COMMON_SIZE, -/*Merc*/ constants::ITEM_COMMON_SIZE, -/*Bot*/ constants::ITEM_COMMON_SIZE, -/*Pet*/ constants::ITEM_COMMON_SIZE +/*NPC*/ legacy::ITEM_COMMON_SIZE, +/*Merc*/ legacy::ITEM_COMMON_SIZE, +/*Bot*/ legacy::ITEM_COMMON_SIZE, +/*Pet*/ legacy::ITEM_COMMON_SIZE }; return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; @@ -605,18 +605,18 @@ uint16 EQEmu::limits::ItemContainerSize(versions::InventoryVersion inventory_ver { static const uint16 local[versions::InventoryVersionCount] = { /*Unknown*/ NOT_USED, -/*62*/ constants::ITEM_CONTAINER_SIZE, -/*Titanium*/ constants::ITEM_CONTAINER_SIZE, -/*SoF*/ constants::ITEM_CONTAINER_SIZE, -/*SoD*/ constants::ITEM_CONTAINER_SIZE, -/*Underfoot*/ constants::ITEM_CONTAINER_SIZE, -/*RoF*/ constants::ITEM_CONTAINER_SIZE, -/*RoF2*/ constants::ITEM_CONTAINER_SIZE, +/*62*/ legacy::ITEM_CONTAINER_SIZE, +/*Titanium*/ legacy::ITEM_CONTAINER_SIZE, +/*SoF*/ legacy::ITEM_CONTAINER_SIZE, +/*SoD*/ legacy::ITEM_CONTAINER_SIZE, +/*Underfoot*/ legacy::ITEM_CONTAINER_SIZE, +/*RoF*/ legacy::ITEM_CONTAINER_SIZE, +/*RoF2*/ legacy::ITEM_CONTAINER_SIZE, -/*NPC*/ constants::ITEM_CONTAINER_SIZE, -/*Merc*/ constants::ITEM_CONTAINER_SIZE, -/*Bot*/ constants::ITEM_CONTAINER_SIZE, -/*Pet*/ constants::ITEM_CONTAINER_SIZE +/*NPC*/ legacy::ITEM_CONTAINER_SIZE, +/*Merc*/ legacy::ITEM_CONTAINER_SIZE, +/*Bot*/ legacy::ITEM_CONTAINER_SIZE, +/*Pet*/ legacy::ITEM_CONTAINER_SIZE }; return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 0f7283c5a..2e470714b 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -293,7 +293,7 @@ struct Spawn_Struct { /*0000*/ EquipStruct equip_primary; // Equipment: Main visual /*0000*/ EquipStruct equip_secondary; // Equipment: Off visual } equip; - /*0000*/ EquipStruct equipment[MaterialCount]; + /*0000*/ EquipStruct equipment[EQEmu::legacy::MaterialCount]; }; /*0233*/ float runspeed; // Speed when running /*0036*/ uint8 afk; // 0=no, 1=afk @@ -339,7 +339,7 @@ union /*0376*/ Color_Struct color_primary; // Color of primary item /*0380*/ Color_Struct color_secondary; // Color of secondary item } equipment_colors; - /*0348*/ Color_Struct colors[MaterialCount]; // Array elements correspond to struct equipment_colors above + /*0348*/ Color_Struct colors[EQEmu::legacy::MaterialCount]; // Array elements correspond to struct equipment_colors above }; /*0384*/ uint8 lfg; // 0=off, 1=lfg on /*0385*/ @@ -776,7 +776,7 @@ struct BandolierItem_Struct struct Bandolier_Struct { char Name[32]; - BandolierItem_Struct Items[EQEmu::constants::BANDOLIER_ITEM_COUNT]; + BandolierItem_Struct Items[EQEmu::legacy::BANDOLIER_ITEM_COUNT]; }; //len = 72 @@ -790,7 +790,7 @@ struct PotionBeltItem_Struct //len = 288 struct PotionBelt_Struct { - PotionBeltItem_Struct Items[EQEmu::constants::POTION_BELT_ITEM_COUNT]; + PotionBeltItem_Struct Items[EQEmu::legacy::POTION_BELT_ITEM_COUNT]; }; struct MovePotionToBelt_Struct @@ -881,7 +881,7 @@ struct SuspendedMinion_Struct /*002*/ uint32 HP; /*006*/ uint32 Mana; /*010*/ SpellBuff_Struct Buffs[BUFF_COUNT]; - /*510*/ uint32 Items[MaterialCount]; + /*510*/ uint32 Items[EQEmu::legacy::MaterialCount]; /*546*/ char Name[64]; /*610*/ }; @@ -989,9 +989,9 @@ struct PlayerProfile_Struct /*0304*/ uint8 ability_time_minutes; /*0305*/ uint8 ability_time_hours; //place holder /*0306*/ uint8 unknown0306[6]; // @bp Spacer/Flag? -/*0312*/ uint32 item_material[MaterialCount]; // Item texture/material of worn/held items +/*0312*/ uint32 item_material[EQEmu::legacy::MaterialCount]; // Item texture/material of worn/held items /*0348*/ uint8 unknown0348[44]; -/*0392*/ Color_Struct item_tint[MaterialCount]; +/*0392*/ Color_Struct item_tint[EQEmu::legacy::MaterialCount]; /*0428*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; /*2348*/ float unknown2384; //seen ~128, ~47 /*2352*/ char servername[32]; // length probably not right @@ -1092,7 +1092,7 @@ struct PlayerProfile_Struct /*7212*/ uint32 tribute_points; /*7216*/ uint32 unknown7252; /*7220*/ uint32 tribute_active; //1=active -/*7224*/ Tribute_Struct tributes[EQEmu::constants::TRIBUTE_SIZE]; +/*7224*/ Tribute_Struct tributes[EQEmu::legacy::TRIBUTE_SIZE]; /*7264*/ Disciplines_Struct disciplines; /*7664*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use) /*7744*/ char unknown7780[160]; @@ -1119,7 +1119,7 @@ struct PlayerProfile_Struct /*12800*/ uint32 expAA; /*12804*/ uint32 aapoints; //avaliable, unspent /*12808*/ uint8 unknown12844[36]; -/*12844*/ Bandolier_Struct bandoliers[EQEmu::constants::BANDOLIERS_SIZE]; +/*12844*/ Bandolier_Struct bandoliers[EQEmu::legacy::BANDOLIERS_SIZE]; /*14124*/ uint8 unknown14160[4506]; /*18630*/ SuspendedMinion_Struct SuspendedMinion; // No longer in use /*19240*/ uint32 timeentitledonaccount; @@ -2124,7 +2124,7 @@ struct Illusion_Struct { //size: 256 - SoF /*092*/ uint32 drakkin_heritage; // /*096*/ uint32 drakkin_tattoo; // /*100*/ uint32 drakkin_details; // -/*104*/ uint32 armor_tint[MaterialCount]; // +/*104*/ uint32 armor_tint[EQEmu::legacy::MaterialCount]; // /*140*/ uint8 eyecolor1; // Field Not Identified in any Illusion Struct /*141*/ uint8 eyecolor2; // Field Not Identified in any Illusion Struct /*142*/ uint8 unknown138[114]; // @@ -3411,7 +3411,7 @@ struct DyeStruct struct Color_Struct secondary; // or this } dyes; - struct Color_Struct dye[MaterialCount]; + struct Color_Struct dye[EQEmu::legacy::MaterialCount]; }; }; @@ -3472,8 +3472,8 @@ struct SelectTributeReply_Struct { struct TributeInfo_Struct { uint32 active; //0 == inactive, 1 == active - uint32 tributes[EQEmu::constants::TRIBUTE_SIZE]; //-1 == NONE - uint32 tiers[EQEmu::constants::TRIBUTE_SIZE]; //all 00's + uint32 tributes[EQEmu::legacy::TRIBUTE_SIZE]; //-1 == NONE + uint32 tiers[EQEmu::legacy::TRIBUTE_SIZE]; //all 00's uint32 tribute_master_id; }; diff --git a/common/extprofile.h b/common/extprofile.h index dc1124096..9713c2e60 100644 --- a/common/extprofile.h +++ b/common/extprofile.h @@ -40,7 +40,7 @@ struct ExtendedProfile_Struct { uint16 old_pet_hp; /* Not Used */ uint16 old_pet_mana; /* Not Used */ SpellBuff_Struct pet_buffs[BUFF_COUNT]; /* Not Used */ - uint32 pet_items[MaterialCount]; /* Not Used */ + uint32 pet_items[EQEmu::legacy::MaterialCount]; /* Not Used */ char merc_name[64]; /* Used */ uint32 aa_effects; /* Used */ diff --git a/common/item.cpp b/common/item.cpp index a9c0df3c2..25bf7d886 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -156,63 +156,63 @@ ItemInst* Inventory::GetItem(int16 slot_id) const ItemInst* result = nullptr; // Cursor - if (slot_id == SlotCursor) { + if (slot_id == EQEmu::legacy::SlotCursor) { // Cursor slot result = m_cursor.peek_front(); } // Non bag slots - else if (slot_id >= EQEmu::constants::TRADE_BEGIN && slot_id <= EQEmu::constants::TRADE_END) { + else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { result = _GetItem(m_trade, slot_id); } - else if (slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_END) { + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { // Shared Bank slots result = _GetItem(m_shbank, slot_id); } - else if (slot_id >= EQEmu::constants::BANK_BEGIN && slot_id <= EQEmu::constants::BANK_END) { + else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { // Bank slots result = _GetItem(m_bank, slot_id); } - else if ((slot_id >= EQEmu::constants::GENERAL_BEGIN && slot_id <= EQEmu::constants::GENERAL_END)) { + else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { // Personal inventory slots result = _GetItem(m_inv, slot_id); } - else if ((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::constants::EQUIPMENT_END) || - (slot_id >= EQEmu::constants::TRIBUTE_BEGIN && slot_id <= EQEmu::constants::TRIBUTE_END) || (slot_id == SlotPowerSource)) { + else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || + (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) || (slot_id == EQEmu::legacy::SlotPowerSource)) { // Equippable slots (on body) result = _GetItem(m_worn, slot_id); } // Inner bag slots - else if (slot_id >= EQEmu::constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::constants::TRADE_BAGS_END) { + else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { // Trade bag slots ItemInst* inst = _GetItem(m_trade, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { // Shared Bank bag slots ItemInst* inst = _GetItem(m_shbank, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::BANK_BAGS_END) { + else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { // Bank bag slots ItemInst* inst = _GetItem(m_bank, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::constants::CURSOR_BAG_END) { + else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { // Cursor bag slots ItemInst* inst = m_cursor.peek_front(); if (inst && inst->IsType(ItemClassContainer)) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::constants::GENERAL_BAGS_END) { + else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { // Personal inventory bag slots ItemInst* inst = _GetItem(m_inv, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsType(ItemClassContainer)) { @@ -248,7 +248,7 @@ int16 Inventory::PutItem(int16 slot_id, const ItemInst& inst) int16 Inventory::PushCursor(const ItemInst& inst) { m_cursor.push(inst.Clone()); - return SlotCursor; + return EQEmu::legacy::SlotCursor; } ItemInst* Inventory::GetCursorItem() @@ -314,7 +314,7 @@ bool Inventory::CheckNoDrop(int16 slot_id) { if (!inst) return false; if (!inst->GetItem()->NoDrop) return true; if (inst->GetItem()->ItemClass == 1) { - for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::constants::ITEM_CONTAINER_SIZE; i++) { + for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { ItemInst* bagitem = GetItem(Inventory::CalcSlotId(slot_id, i)); if (bagitem && !bagitem->GetItem()->NoDrop) return true; @@ -329,30 +329,30 @@ ItemInst* Inventory::PopItem(int16 slot_id) { ItemInst* p = nullptr; - if (slot_id == SlotCursor) { + if (slot_id == EQEmu::legacy::SlotCursor) { p = m_cursor.pop(); } - else if ((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::constants::EQUIPMENT_END) || (slot_id == SlotPowerSource)) { + else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::legacy::SlotPowerSource)) { p = m_worn[slot_id]; m_worn.erase(slot_id); } - else if ((slot_id >= EQEmu::constants::GENERAL_BEGIN && slot_id <= EQEmu::constants::GENERAL_END)) { + else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { p = m_inv[slot_id]; m_inv.erase(slot_id); } - else if (slot_id >= EQEmu::constants::TRIBUTE_BEGIN && slot_id <= EQEmu::constants::TRIBUTE_END) { + else if (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) { p = m_worn[slot_id]; m_worn.erase(slot_id); } - else if (slot_id >= EQEmu::constants::BANK_BEGIN && slot_id <= EQEmu::constants::BANK_END) { + else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { p = m_bank[slot_id]; m_bank.erase(slot_id); } - else if (slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_END) { + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { p = m_shbank[slot_id]; m_shbank.erase(slot_id); } - else if (slot_id >= EQEmu::constants::TRADE_BEGIN && slot_id <= EQEmu::constants::TRADE_END) { + else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { p = m_trade[slot_id]; m_trade.erase(slot_id); } @@ -372,7 +372,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { if (ItemToTry->Stackable) { - for (int16 i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { ItemInst* InvItem = GetItem(i); @@ -409,7 +409,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { } } - for (int16 i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { ItemInst* InvItem = GetItem(i); @@ -615,14 +615,14 @@ int16 Inventory::HasItemByLoreGroup(uint32 loregroup, uint8 where) int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow) { // Check basic inventory - for (int16 i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { if (!GetItem(i)) // Found available slot in personal inventory return i; } if (!for_bag) { - for (int16 i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { const ItemInst* inst = GetItem(i); if (inst && inst->IsType(ItemClassContainer) && inst->GetItem()->BagSize >= min_size) { @@ -648,7 +648,7 @@ int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, boo if (try_cursor) { // Always room on cursor (it's a queue) // (we may wish to cap this in the future) - return SlotCursor; + return EQEmu::legacy::SlotCursor; } // No available slots @@ -667,17 +667,17 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 1: find room for bags (caller should really ask for slots for bags first to avoid sending them to cursor..and bag item loss) if (inst->IsType(ItemClassContainer)) { - for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { if (!m_inv[free_slot]) return free_slot; } - return SlotCursor; // return cursor since bags do not stack and will not fit inside other bags..yet...) + return EQEmu::legacy::SlotCursor; // return cursor since bags do not stack and will not fit inside other bags..yet...) } // step 2: find partial room for stackables if (inst->IsStackable()) { - for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst) @@ -687,14 +687,14 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { return free_slot; } - for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst) continue; if (main_inst->IsType(ItemClassContainer)) { // if item-specific containers already have bad items, we won't fix it here... - for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { const ItemInst* sub_inst = main_inst->GetItem(free_bag_slot); if (!sub_inst) @@ -709,13 +709,13 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 3a: find room for container-specific items (ItemClassArrow) if (inst->GetItem()->ItemType == ItemTypeArrow) { - for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst || (main_inst->GetItem()->BagType != BagTypeQuiver) || !main_inst->IsType(ItemClassContainer)) continue; - for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -724,13 +724,13 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 3b: find room for container-specific items (ItemClassSmallThrowing) if (inst->GetItem()->ItemType == ItemTypeSmallThrowing) { - for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst || (main_inst->GetItem()->BagType != BagTypeBandolier) || !main_inst->IsType(ItemClassContainer)) continue; - for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -738,21 +738,21 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { } // step 4: just find an empty slot - for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (!main_inst) return free_slot; } - for (int16 free_slot = EQEmu::constants::GENERAL_BEGIN; free_slot <= EQEmu::constants::GENERAL_END; ++free_slot) { + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; if (main_inst && main_inst->IsType(ItemClassContainer)) { if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == BagTypeBandolier) || (main_inst->GetItem()->BagType == BagTypeQuiver)) continue; - for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -760,7 +760,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { } //return INVALID_INDEX; // everything else pushes to the cursor - return SlotCursor; + return EQEmu::legacy::SlotCursor; } // Opposite of below: Get parent bag slot_id from a slot inside of bag @@ -772,20 +772,20 @@ int16 Inventory::CalcSlotId(int16 slot_id) { // parent_slot_id = EmuConstants::BANK_BEGIN + (slot_id - EmuConstants::BANK_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; //else if (slot_id >= 3100 && slot_id <= 3179) should be {3031..3110}..where did this range come from!!? (verified db save range) - if (slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::constants::GENERAL_BAGS_END) { - parent_slot_id = EQEmu::constants::GENERAL_BEGIN + (slot_id - EQEmu::constants::GENERAL_BAGS_BEGIN) / EQEmu::constants::ITEM_CONTAINER_SIZE; + if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { + parent_slot_id = EQEmu::legacy::GENERAL_BEGIN + (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) / EQEmu::legacy::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::constants::CURSOR_BAG_END) { - parent_slot_id = SlotCursor; + else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { + parent_slot_id = EQEmu::legacy::SlotCursor; } - else if (slot_id >= EQEmu::constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::BANK_BAGS_END) { - parent_slot_id = EQEmu::constants::BANK_BEGIN + (slot_id - EQEmu::constants::BANK_BAGS_BEGIN) / EQEmu::constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { + parent_slot_id = EQEmu::legacy::BANK_BEGIN + (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) / EQEmu::legacy::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { - parent_slot_id = EQEmu::constants::SHARED_BANK_BEGIN + (slot_id - EQEmu::constants::SHARED_BANK_BAGS_BEGIN) / EQEmu::constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { + parent_slot_id = EQEmu::legacy::SHARED_BANK_BEGIN + (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) / EQEmu::legacy::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::constants::TRADE_BAGS_END) { - parent_slot_id = EQEmu::constants::TRADE_BEGIN + (slot_id - EQEmu::constants::TRADE_BAGS_BEGIN) / EQEmu::constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { + parent_slot_id = EQEmu::legacy::TRADE_BEGIN + (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) / EQEmu::legacy::ITEM_CONTAINER_SIZE; } return parent_slot_id; @@ -798,20 +798,20 @@ int16 Inventory::CalcSlotId(int16 bagslot_id, uint8 bagidx) { int16 slot_id = INVALID_INDEX; - if (bagslot_id == SlotCursor || bagslot_id == 8000) { - slot_id = EQEmu::constants::CURSOR_BAG_BEGIN + bagidx; + if (bagslot_id == EQEmu::legacy::SlotCursor || bagslot_id == 8000) { + slot_id = EQEmu::legacy::CURSOR_BAG_BEGIN + bagidx; } - else if (bagslot_id >= EQEmu::constants::GENERAL_BEGIN && bagslot_id <= EQEmu::constants::GENERAL_END) { - slot_id = EQEmu::constants::GENERAL_BAGS_BEGIN + (bagslot_id - EQEmu::constants::GENERAL_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::legacy::GENERAL_BEGIN && bagslot_id <= EQEmu::legacy::GENERAL_END) { + slot_id = EQEmu::legacy::GENERAL_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::GENERAL_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE + bagidx; } - else if (bagslot_id >= EQEmu::constants::BANK_BEGIN && bagslot_id <= EQEmu::constants::BANK_END) { - slot_id = EQEmu::constants::BANK_BAGS_BEGIN + (bagslot_id - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::legacy::BANK_BEGIN && bagslot_id <= EQEmu::legacy::BANK_END) { + slot_id = EQEmu::legacy::BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE + bagidx; } - else if (bagslot_id >= EQEmu::constants::SHARED_BANK_BEGIN && bagslot_id <= EQEmu::constants::SHARED_BANK_END) { - slot_id = EQEmu::constants::SHARED_BANK_BAGS_BEGIN + (bagslot_id - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && bagslot_id <= EQEmu::legacy::SHARED_BANK_END) { + slot_id = EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE + bagidx; } - else if (bagslot_id >= EQEmu::constants::TRADE_BEGIN && bagslot_id <= EQEmu::constants::TRADE_END) { - slot_id = EQEmu::constants::TRADE_BAGS_BEGIN + (bagslot_id - EQEmu::constants::TRADE_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE + bagidx; + else if (bagslot_id >= EQEmu::legacy::TRADE_BEGIN && bagslot_id <= EQEmu::legacy::TRADE_END) { + slot_id = EQEmu::legacy::TRADE_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::TRADE_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE + bagidx; } return slot_id; @@ -824,23 +824,23 @@ uint8 Inventory::CalcBagIdx(int16 slot_id) { //else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) // index = (slot_id - EmuConstants::BANK_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; - if (slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::constants::GENERAL_BAGS_END) { - index = (slot_id - EQEmu::constants::GENERAL_BAGS_BEGIN) % EQEmu::constants::ITEM_CONTAINER_SIZE; + if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { + index = (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) % EQEmu::legacy::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::constants::CURSOR_BAG_BEGIN && slot_id <= EQEmu::constants::CURSOR_BAG_END) { - index = (slot_id - EQEmu::constants::CURSOR_BAG_BEGIN); // % EQEmu::Constants::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots + else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { + index = (slot_id - EQEmu::legacy::CURSOR_BAG_BEGIN); // % EQEmu::legacy::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots } - else if (slot_id >= EQEmu::constants::BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::BANK_BAGS_END) { - index = (slot_id - EQEmu::constants::BANK_BAGS_BEGIN) % EQEmu::constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { + index = (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) % EQEmu::legacy::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { - index = (slot_id - EQEmu::constants::SHARED_BANK_BAGS_BEGIN) % EQEmu::constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { + index = (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) % EQEmu::legacy::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::constants::TRADE_BAGS_BEGIN && slot_id <= EQEmu::constants::TRADE_BAGS_END) { - index = (slot_id - EQEmu::constants::TRADE_BAGS_BEGIN) % EQEmu::constants::ITEM_CONTAINER_SIZE; + else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { + index = (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) % EQEmu::legacy::ITEM_CONTAINER_SIZE; } - else if (slot_id >= EQEmu::constants::WORLD_BEGIN && slot_id <= EQEmu::constants::WORLD_END) { - index = (slot_id - EQEmu::constants::WORLD_BEGIN); // % EQEmu::Constants::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots + else if (slot_id >= EQEmu::legacy::WORLD_BEGIN && slot_id <= EQEmu::legacy::WORLD_END) { + index = (slot_id - EQEmu::legacy::WORLD_BEGIN); // % EQEmu::legacy::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots } return index; @@ -850,24 +850,24 @@ int16 Inventory::CalcSlotFromMaterial(uint8 material) { switch (material) { - case MaterialHead: - return SlotHead; - case MaterialChest: - return SlotChest; - case MaterialArms: - return SlotArms; - case MaterialWrist: - return SlotWrist1; // there's 2 bracers, only one bracer material - case MaterialHands: - return SlotHands; - case MaterialLegs: - return SlotLegs; - case MaterialFeet: - return SlotFeet; - case MaterialPrimary: - return SlotPrimary; - case MaterialSecondary: - return SlotSecondary; + case EQEmu::legacy::MaterialHead: + return EQEmu::legacy::SlotHead; + case EQEmu::legacy::MaterialChest: + return EQEmu::legacy::SlotChest; + case EQEmu::legacy::MaterialArms: + return EQEmu::legacy::SlotArms; + case EQEmu::legacy::MaterialWrist: + return EQEmu::legacy::SlotWrist1; // there's 2 bracers, only one bracer material + case EQEmu::legacy::MaterialHands: + return EQEmu::legacy::SlotHands; + case EQEmu::legacy::MaterialLegs: + return EQEmu::legacy::SlotLegs; + case EQEmu::legacy::MaterialFeet: + return EQEmu::legacy::SlotFeet; + case EQEmu::legacy::MaterialPrimary: + return EQEmu::legacy::SlotPrimary; + case EQEmu::legacy::MaterialSecondary: + return EQEmu::legacy::SlotSecondary; default: return INVALID_INDEX; } @@ -877,27 +877,27 @@ uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) { switch (equipslot) { - case SlotHead: - return MaterialHead; - case SlotChest: - return MaterialChest; - case SlotArms: - return MaterialArms; - case SlotWrist1: + case EQEmu::legacy::SlotHead: + return EQEmu::legacy::MaterialHead; + case EQEmu::legacy::SlotChest: + return EQEmu::legacy::MaterialChest; + case EQEmu::legacy::SlotArms: + return EQEmu::legacy::MaterialArms; + case EQEmu::legacy::SlotWrist1: //case SLOT_BRACER02: // non-live behavior - return MaterialWrist; - case SlotHands: - return MaterialHands; - case SlotLegs: - return MaterialLegs; - case SlotFeet: - return MaterialFeet; - case SlotPrimary: - return MaterialPrimary; - case SlotSecondary: - return MaterialSecondary; + return EQEmu::legacy::MaterialWrist; + case EQEmu::legacy::SlotHands: + return EQEmu::legacy::MaterialHands; + case EQEmu::legacy::SlotLegs: + return EQEmu::legacy::MaterialLegs; + case EQEmu::legacy::SlotFeet: + return EQEmu::legacy::MaterialFeet; + case EQEmu::legacy::SlotPrimary: + return EQEmu::legacy::MaterialPrimary; + case EQEmu::legacy::SlotSecondary: + return EQEmu::legacy::MaterialSecondary; default: - return MaterialInvalid; + return EQEmu::legacy::MaterialInvalid; } } @@ -921,11 +921,11 @@ bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_S bool Inventory::SupportsClickCasting(int16 slot_id) { // there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range - if ((uint16)slot_id <= EQEmu::constants::GENERAL_END || slot_id == SlotPowerSource) + if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::legacy::SlotPowerSource) { return true; } - else if (slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::constants::GENERAL_BAGS_END) + else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { if (EQEmu::limits::AllowClickCastFromBag(m_inventory_version)) return true; @@ -936,7 +936,7 @@ bool Inventory::SupportsClickCasting(int16 slot_id) bool Inventory::SupportsPotionBeltCasting(int16 slot_id) { - if ((uint16)slot_id <= EQEmu::constants::GENERAL_END || slot_id == SlotPowerSource || (slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::constants::GENERAL_BAGS_END)) + if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::legacy::SlotPowerSource || (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END)) return true; return false; @@ -945,11 +945,11 @@ bool Inventory::SupportsPotionBeltCasting(int16 slot_id) // Test whether a given slot can support a container item bool Inventory::SupportsContainers(int16 slot_id) { - if ((slot_id == SlotCursor) || - (slot_id >= EQEmu::constants::GENERAL_BEGIN && slot_id <= EQEmu::constants::GENERAL_END) || - (slot_id >= EQEmu::constants::BANK_BEGIN && slot_id <= EQEmu::constants::BANK_END) || - (slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_END) || - (slot_id >= EQEmu::constants::TRADE_BEGIN && slot_id <= EQEmu::constants::TRADE_END) + if ((slot_id == EQEmu::legacy::SlotCursor) || + (slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END) || + (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) || + (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) || + (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) ) { return true; } @@ -987,7 +987,7 @@ int Inventory::GetSlotByItemInst(ItemInst *inst) { } if (m_cursor.peek_front() == inst) { - return SlotCursor; + return EQEmu::legacy::SlotCursor; } return INVALID_INDEX; @@ -998,8 +998,8 @@ uint8 Inventory::FindBrightestLightType() uint8 brightest_light_type = 0; for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { - if ((iter->first < EQEmu::constants::EQUIPMENT_BEGIN || iter->first > EQEmu::constants::EQUIPMENT_END) && iter->first != SlotPowerSource) { continue; } - if (iter->first == SlotAmmo) { continue; } + if ((iter->first < EQEmu::legacy::EQUIPMENT_BEGIN || iter->first > EQEmu::legacy::EQUIPMENT_END) && iter->first != EQEmu::legacy::SlotPowerSource) { continue; } + if (iter->first == EQEmu::legacy::SlotAmmo) { continue; } auto inst = iter->second; if (inst == nullptr) { continue; } @@ -1012,7 +1012,7 @@ uint8 Inventory::FindBrightestLightType() uint8 general_light_type = 0; for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) { - if (iter->first < EQEmu::constants::GENERAL_BEGIN || iter->first > EQEmu::constants::GENERAL_END) { continue; } + if (iter->first < EQEmu::legacy::GENERAL_BEGIN || iter->first > EQEmu::legacy::GENERAL_END) { continue; } auto inst = iter->second; if (inst == nullptr) { continue; } @@ -1143,33 +1143,33 @@ int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst) int16 result = INVALID_INDEX; int16 parentSlot = INVALID_INDEX; - if (slot_id == SlotCursor) { + if (slot_id == EQEmu::legacy::SlotCursor) { // Replace current item on cursor, if exists m_cursor.pop(); // no memory delete, clients of this function know what they are doing m_cursor.push_front(inst); result = slot_id; } - else if ((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::constants::EQUIPMENT_END) || (slot_id == SlotPowerSource)) { + else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::legacy::SlotPowerSource)) { m_worn[slot_id] = inst; result = slot_id; } - else if ((slot_id >= EQEmu::constants::GENERAL_BEGIN && slot_id <= EQEmu::constants::GENERAL_END)) { + else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { m_inv[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::constants::TRIBUTE_BEGIN && slot_id <= EQEmu::constants::TRIBUTE_END) { + else if (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) { m_worn[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::constants::BANK_BEGIN && slot_id <= EQEmu::constants::BANK_END) { + else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { m_bank[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_END) { + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { m_shbank[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::constants::TRADE_BEGIN && slot_id <= EQEmu::constants::TRADE_END) { + else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { m_trade[slot_id] = inst; result = slot_id; } @@ -1207,7 +1207,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui return iter->first; } - for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) return EQEmu::legacy::SLOT_AUGMENT; } @@ -1224,7 +1224,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui return Inventory::CalcSlotId(iter->first, bag_iter->first); } - for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) return EQEmu::legacy::SLOT_AUGMENT; } @@ -1252,10 +1252,10 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) if (inst->GetID() == item_id) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); if (quantity_found >= quantity) - return SlotCursor; + return EQEmu::legacy::SlotCursor; } - for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) return EQEmu::legacy::SLOT_AUGMENT; } @@ -1269,10 +1269,10 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) if (bag_inst->GetID() == item_id) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(SlotCursor, bag_iter->first); + return Inventory::CalcSlotId(EQEmu::legacy::SlotCursor, bag_iter->first); } - for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) return EQEmu::legacy::SLOT_AUGMENT; } @@ -1329,7 +1329,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) if (inst->IsType(ItemClassCommon) && inst->GetItem()->ItemType == use) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); if (quantity_found >= quantity) - return SlotCursor; + return EQEmu::legacy::SlotCursor; } if (!inst->IsType(ItemClassContainer)) { continue; } @@ -1341,7 +1341,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->ItemType == use) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(SlotCursor, bag_iter->first); + return Inventory::CalcSlotId(EQEmu::legacy::SlotCursor, bag_iter->first); } } @@ -1361,7 +1361,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 if (inst->GetItem()->LoreGroup == loregroup) return iter->first; - for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { auto aug_inst = inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1378,7 +1378,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup) return Inventory::CalcSlotId(iter->first, bag_iter->first); - for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { auto aug_inst = bag_inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1399,9 +1399,9 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (inst == nullptr) { continue; } if (inst->GetItem()->LoreGroup == loregroup) - return SlotCursor; + return EQEmu::legacy::SlotCursor; - for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { auto aug_inst = inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1416,9 +1416,9 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (bag_inst == nullptr) { continue; } if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup) - return Inventory::CalcSlotId(SlotCursor, bag_iter->first); + return Inventory::CalcSlotId(EQEmu::legacy::SlotCursor, bag_iter->first); - for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { auto aug_inst = bag_inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1640,8 +1640,8 @@ bool ItemInst::IsEquipable(int16 slot_id) const // another "shouldn't do" fix..will be fixed in future updates (requires code and database work) int16 use_slot = INVALID_INDEX; - if (slot_id == SlotPowerSource) { use_slot = SlotGeneral1; } - if ((uint16)slot_id <= EQEmu::constants::EQUIPMENT_END) { use_slot = slot_id; } + if (slot_id == EQEmu::legacy::SlotPowerSource) { use_slot = EQEmu::legacy::SlotGeneral1; } + if ((uint16)slot_id <= EQEmu::legacy::EQUIPMENT_END) { use_slot = slot_id; } if (use_slot != INVALID_INDEX) { if (m_item->Slots & (1 << use_slot)) @@ -1656,7 +1656,7 @@ bool ItemInst::IsAugmentable() const if (!m_item) return false; - for (int index = 0; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { + for (int index = 0; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { if (m_item->AugSlotType[index] != NO_ITEM) return true; } @@ -1670,8 +1670,8 @@ bool ItemInst::AvailableWearSlot(uint32 aug_wear_slots) const { if (!m_item || m_item->ItemClass != ItemClassCommon) return false; - int index = EQEmu::constants::EQUIPMENT_BEGIN; - for (; index <= SlotGeneral1; ++index) { // MainGeneral1 should be EQEmu::constants::EQUIPMENT_END + int index = EQEmu::legacy::EQUIPMENT_BEGIN; + for (; index <= EQEmu::legacy::SlotGeneral1; ++index) { // MainGeneral1 should be EQEmu::legacy::EQUIPMENT_END if (m_item->Slots & (1 << index)) { if (aug_wear_slots & (1 << index)) break; @@ -1687,13 +1687,13 @@ int8 ItemInst::AvailableAugmentSlot(int32 augtype) const return INVALID_INDEX; int index = AUG_INDEX_BEGIN; - for (; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { + for (; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { if (GetItem(index)) { continue; } if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype))) break; } - return (index < EQEmu::constants::ITEM_COMMON_SIZE) ? index : INVALID_INDEX; + return (index < EQEmu::legacy::ITEM_COMMON_SIZE) ? index : INVALID_INDEX; } bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const @@ -1882,7 +1882,7 @@ ItemInst* ItemInst::GetOrnamentationAug(int32 ornamentationAugtype) const if (!m_item || m_item->ItemClass != ItemClassCommon) { return nullptr; } if (ornamentationAugtype == 0) { return nullptr; } - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype) { @@ -2049,7 +2049,7 @@ bool ItemInst::IsAugmented() if (!m_item || m_item->ItemClass != ItemClassCommon) return false; - for (int index = AUG_INDEX_BEGIN; index < EQEmu::constants::ITEM_COMMON_SIZE; ++index) { + for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { if (GetAugmentItemID(index)) return true; } @@ -2177,8 +2177,8 @@ bool ItemInst::IsSlotAllowed(int16 slot_id) const { if (!m_item) { return false; } else if (Inventory::SupportsContainers(slot_id)) { return true; } else if (m_item->Slots & (1 << slot_id)) { return true; } - else if (slot_id == SlotPowerSource && (m_item->Slots & (1 << 22))) { return true; } // got lazy... - else if (slot_id != SlotPowerSource && slot_id > EQEmu::constants::EQUIPMENT_END) { return true; } + else if (slot_id == EQEmu::legacy::SlotPowerSource && (m_item->Slots & (1 << 22))) { return true; } // got lazy... + else if (slot_id != EQEmu::legacy::SlotPowerSource && slot_id > EQEmu::legacy::EQUIPMENT_END) { return true; } else { return false; } } @@ -2330,7 +2330,7 @@ int ItemInst::GetItemArmorClass(bool augments) const if (item) { ac = item->AC; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) ac += GetAugment(i)->GetItemArmorClass(); } @@ -2372,7 +2372,7 @@ int ItemInst::GetItemElementalDamage(int &magic, int &fire, int &cold, int &pois } if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) GetAugment(i)->GetItemElementalDamage(magic, fire, cold, poison, disease, chromatic, prismatic, physical, corruption); } @@ -2389,7 +2389,7 @@ int ItemInst::GetItemElementalFlag(bool augments) const return flag; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { if (GetAugment(i)) flag = GetAugment(i)->GetItemElementalFlag(); if (flag) @@ -2410,7 +2410,7 @@ int ItemInst::GetItemElementalDamage(bool augments) const return damage; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { if (GetAugment(i)) damage = GetAugment(i)->GetItemElementalDamage(); if (damage) @@ -2429,7 +2429,7 @@ int ItemInst::GetItemRecommendedLevel(bool augments) const level = item->RecLevel; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { int temp = 0; if (GetAugment(i)) { temp = GetAugment(i)->GetItemRecommendedLevel(); @@ -2451,7 +2451,7 @@ int ItemInst::GetItemRequiredLevel(bool augments) const level = item->ReqLevel; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { int temp = 0; if (GetAugment(i)) { temp = GetAugment(i)->GetItemRequiredLevel(); @@ -2473,7 +2473,7 @@ int ItemInst::GetItemWeaponDamage(bool augments) const damage = item->Damage; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemWeaponDamage(); } @@ -2489,7 +2489,7 @@ int ItemInst::GetItemBackstabDamage(bool augments) const damage = item->BackstabDmg; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBackstabDamage(); } @@ -2507,7 +2507,7 @@ int ItemInst::GetItemBaneDamageBody(bool augments) const return body; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) { body = GetAugment(i)->GetItemBaneDamageBody(); if (body) @@ -2528,7 +2528,7 @@ int ItemInst::GetItemBaneDamageRace(bool augments) const return race; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) { race = GetAugment(i)->GetItemBaneDamageRace(); if (race) @@ -2548,7 +2548,7 @@ int ItemInst::GetItemBaneDamageBody(bodyType against, bool augments) const damage += item->BaneDmgAmt; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBaneDamageBody(against); } @@ -2565,7 +2565,7 @@ int ItemInst::GetItemBaneDamageRace(uint16 against, bool augments) const damage += item->BaneDmgRaceAmt; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBaneDamageRace(against); } @@ -2581,7 +2581,7 @@ int ItemInst::GetItemMagical(bool augments) const return 1; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i) && GetAugment(i)->GetItemMagical()) return 1; } @@ -2596,7 +2596,7 @@ int ItemInst::GetItemHP(bool augments) const if (item) { hp = item->HP; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) hp += GetAugment(i)->GetItemHP(); } @@ -2610,7 +2610,7 @@ int ItemInst::GetItemMana(bool augments) const if (item) { mana = item->Mana; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) mana += GetAugment(i)->GetItemMana(); } @@ -2624,7 +2624,7 @@ int ItemInst::GetItemEndur(bool augments) const if (item) { endur = item->Endur; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) endur += GetAugment(i)->GetItemEndur(); } @@ -2638,7 +2638,7 @@ int ItemInst::GetItemAttack(bool augments) const if (item) { atk = item->Attack; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) atk += GetAugment(i)->GetItemAttack(); } @@ -2652,7 +2652,7 @@ int ItemInst::GetItemStr(bool augments) const if (item) { str = item->AStr; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) str += GetAugment(i)->GetItemStr(); } @@ -2666,7 +2666,7 @@ int ItemInst::GetItemSta(bool augments) const if (item) { sta = item->ASta; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) sta += GetAugment(i)->GetItemSta(); } @@ -2680,7 +2680,7 @@ int ItemInst::GetItemDex(bool augments) const if (item) { total = item->ADex; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemDex(); } @@ -2694,7 +2694,7 @@ int ItemInst::GetItemAgi(bool augments) const if (item) { total = item->AAgi; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemAgi(); } @@ -2708,7 +2708,7 @@ int ItemInst::GetItemInt(bool augments) const if (item) { total = item->AInt; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemInt(); } @@ -2722,7 +2722,7 @@ int ItemInst::GetItemWis(bool augments) const if (item) { total = item->AWis; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemWis(); } @@ -2736,7 +2736,7 @@ int ItemInst::GetItemCha(bool augments) const if (item) { total = item->ACha; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCha(); } @@ -2750,7 +2750,7 @@ int ItemInst::GetItemMR(bool augments) const if (item) { total = item->MR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemMR(); } @@ -2764,7 +2764,7 @@ int ItemInst::GetItemFR(bool augments) const if (item) { total = item->FR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemFR(); } @@ -2778,7 +2778,7 @@ int ItemInst::GetItemCR(bool augments) const if (item) { total = item->CR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCR(); } @@ -2792,7 +2792,7 @@ int ItemInst::GetItemPR(bool augments) const if (item) { total = item->PR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemPR(); } @@ -2806,7 +2806,7 @@ int ItemInst::GetItemDR(bool augments) const if (item) { total = item->DR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemDR(); } @@ -2820,7 +2820,7 @@ int ItemInst::GetItemCorrup(bool augments) const if (item) { total = item->SVCorruption; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCorrup(); } @@ -2834,7 +2834,7 @@ int ItemInst::GetItemHeroicStr(bool augments) const if (item) { total = item->HeroicStr; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicStr(); } @@ -2848,7 +2848,7 @@ int ItemInst::GetItemHeroicSta(bool augments) const if (item) { total = item->HeroicSta; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicSta(); } @@ -2862,7 +2862,7 @@ int ItemInst::GetItemHeroicDex(bool augments) const if (item) { total = item->HeroicDex; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicDex(); } @@ -2876,7 +2876,7 @@ int ItemInst::GetItemHeroicAgi(bool augments) const if (item) { total = item->HeroicAgi; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicAgi(); } @@ -2890,7 +2890,7 @@ int ItemInst::GetItemHeroicInt(bool augments) const if (item) { total = item->HeroicInt; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicInt(); } @@ -2904,7 +2904,7 @@ int ItemInst::GetItemHeroicWis(bool augments) const if (item) { total = item->HeroicWis; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicWis(); } @@ -2918,7 +2918,7 @@ int ItemInst::GetItemHeroicCha(bool augments) const if (item) { total = item->HeroicCha; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCha(); } @@ -2932,7 +2932,7 @@ int ItemInst::GetItemHeroicMR(bool augments) const if (item) { total = item->HeroicMR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicMR(); } @@ -2946,7 +2946,7 @@ int ItemInst::GetItemHeroicFR(bool augments) const if (item) { total = item->HeroicFR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicFR(); } @@ -2960,7 +2960,7 @@ int ItemInst::GetItemHeroicCR(bool augments) const if (item) { total = item->HeroicCR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCR(); } @@ -2974,7 +2974,7 @@ int ItemInst::GetItemHeroicPR(bool augments) const if (item) { total = item->HeroicPR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicPR(); } @@ -2988,7 +2988,7 @@ int ItemInst::GetItemHeroicDR(bool augments) const if (item) { total = item->HeroicDR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicDR(); } @@ -3002,7 +3002,7 @@ int ItemInst::GetItemHeroicCorrup(bool augments) const if (item) { total = item->HeroicSVCorrup; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCorrup(); } @@ -3016,7 +3016,7 @@ int ItemInst::GetItemHaste(bool augments) const if (item) { total = item->Haste; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) if (GetAugment(i)) { int temp = GetAugment(i)->GetItemHaste(); if (temp > total) diff --git a/common/item_struct.h b/common/item_struct.h index 42625b5bc..226458d70 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -183,9 +183,9 @@ struct Item_Struct { int32 FactionAmt4; // Faction Amt 4 char CharmFile[32]; // ? uint32 AugType; - uint8 AugSlotType[EQEmu::constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Type - uint8 AugSlotVisible[EQEmu::constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Visible - uint8 AugSlotUnk2[EQEmu::constants::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related + uint8 AugSlotType[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Type + uint8 AugSlotVisible[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Visible + uint8 AugSlotUnk2[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related uint32 LDoNTheme; uint32 LDoNPrice; uint32 LDoNSold; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 7d615d48c..2fb93343a 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2342,7 +2342,7 @@ namespace RoF outapp->WriteUInt32(consts::BANDOLIERS_SIZE); // Copy bandoliers where server and client indexes converge - for (uint32 r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(emu->bandoliers[r].Name); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(emu->bandoliers[r].Items[j].Name); @@ -2357,7 +2357,7 @@ namespace RoF } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(""); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(""); @@ -2369,7 +2369,7 @@ namespace RoF outapp->WriteUInt32(consts::POTION_BELT_ITEM_COUNT); // Copy potion belt where server and client indexes converge - for (uint32 r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(emu->potionbelt.Items[r].Name); outapp->WriteUInt32(emu->potionbelt.Items[r].ID); if (emu->potionbelt.Items[r].Icon) { @@ -2381,7 +2381,7 @@ namespace RoF } } // Nullify potion belt where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(""); outapp->WriteUInt32(0); outapp->WriteSInt32(-1); @@ -2502,9 +2502,9 @@ namespace RoF outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt32(EQEmu::constants::TRIBUTE_SIZE); + outapp->WriteUInt32(EQEmu::legacy::TRIBUTE_SIZE); - for (uint32 r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) + for (uint32 r = 0; r < EQEmu::legacy::TRIBUTE_SIZE; r++) { outapp->WriteUInt32(emu->tributes[r].tribute); outapp->WriteUInt32(emu->tributes[r].tier); @@ -3037,7 +3037,7 @@ namespace RoF eq_cse->Gender = emu_cse->Gender; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::legacy::MaterialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -4101,13 +4101,13 @@ namespace RoF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialPrimary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialSecondary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); @@ -4810,7 +4810,7 @@ namespace RoF IN(item_id); int r; - for (r = 0; r < EQEmu::constants::ITEM_COMMON_SIZE; r++) { + for (r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { IN(augments[r]); } // Max Augs is now 6, but no code to support that many yet @@ -5678,7 +5678,7 @@ namespace RoF uint32 SubLengths[10]; - for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -5690,15 +5690,15 @@ namespace RoF iqbs.subitem_count++; - if (slot_id_in >= EQEmu::constants::GENERAL_BEGIN && slot_id_in <= EQEmu::constants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::constants::BANK_BEGIN && slot_id_in <= EQEmu::constants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::constants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -5713,7 +5713,7 @@ namespace RoF ss.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); - for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { if (SubSerializations[x]) { @@ -5745,17 +5745,17 @@ namespace RoF uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == SlotPowerSource) { // Main Inventory and Cursor + if (serverSlot < 56 || serverSlot == EQEmu::legacy::SlotPowerSource) { // Main Inventory and Cursor RoFSlot.Type = inventory::TypePossessions; RoFSlot.Slot = serverSlot; - if (serverSlot == SlotPowerSource) + if (serverSlot == EQEmu::legacy::SlotPowerSource) RoFSlot.Slot = inventory::SlotPowerSource; - else if (serverSlot >= SlotCursor) // Cursor and Extended Corpse Inventory + else if (serverSlot >= EQEmu::legacy::SlotCursor) // Cursor and Extended Corpse Inventory RoFSlot.Slot += 3; - else if (serverSlot >= SlotAmmo) // (> 20) + else if (serverSlot >= EQEmu::legacy::SlotAmmo) // (> 20) RoFSlot.Slot += 1; } @@ -5764,51 +5764,51 @@ namespace RoF RoFSlot.MainSlot = ServerSlot - 31; }*/ - else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) { // (> 250 && < 341) + else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) { // (> 250 && < 341) RoFSlot.Type = inventory::TypePossessions; TempSlot = serverSlot - 1; - RoFSlot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 2; - RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::constants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 2; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::legacy::ITEM_CONTAINER_SIZE); if (RoFSlot.Slot >= inventory::SlotGeneral9) // (> 30) RoFSlot.Slot = inventory::SlotCursor; } - else if (serverSlot >= EQEmu::constants::TRIBUTE_BEGIN && serverSlot <= EQEmu::constants::TRIBUTE_END) { // Tribute + else if (serverSlot >= EQEmu::legacy::TRIBUTE_BEGIN && serverSlot <= EQEmu::legacy::TRIBUTE_END) { // Tribute RoFSlot.Type = inventory::TypeTribute; - RoFSlot.Slot = serverSlot - EQEmu::constants::TRIBUTE_BEGIN; + RoFSlot.Slot = serverSlot - EQEmu::legacy::TRIBUTE_BEGIN; } - else if (serverSlot >= EQEmu::constants::BANK_BEGIN && serverSlot <= EQEmu::constants::BANK_BAGS_END) { + else if (serverSlot >= EQEmu::legacy::BANK_BEGIN && serverSlot <= EQEmu::legacy::BANK_BAGS_END) { RoFSlot.Type = inventory::TypeBank; - TempSlot = serverSlot - EQEmu::constants::BANK_BEGIN; + TempSlot = serverSlot - EQEmu::legacy::BANK_BEGIN; RoFSlot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoFSlot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EQEmu::constants::SHARED_BANK_BEGIN && serverSlot <= EQEmu::constants::SHARED_BANK_BAGS_END) { + else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) { RoFSlot.Type = inventory::TypeSharedBank; - TempSlot = serverSlot - EQEmu::constants::SHARED_BANK_BEGIN; + TempSlot = serverSlot - EQEmu::legacy::SHARED_BANK_BEGIN; RoFSlot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoFSlot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EQEmu::constants::TRADE_BEGIN && serverSlot <= EQEmu::constants::TRADE_BAGS_END) { + else if (serverSlot >= EQEmu::legacy::TRADE_BEGIN && serverSlot <= EQEmu::legacy::TRADE_BAGS_END) { RoFSlot.Type = inventory::TypeTrade; - TempSlot = serverSlot - EQEmu::constants::TRADE_BEGIN; + TempSlot = serverSlot - EQEmu::legacy::TRADE_BEGIN; RoFSlot.Slot = TempSlot; if (TempSlot > 30) { - RoFSlot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); } /* @@ -5825,9 +5825,9 @@ namespace RoF */ } - else if (serverSlot >= EQEmu::constants::WORLD_BEGIN && serverSlot <= EQEmu::constants::WORLD_END) { + else if (serverSlot >= EQEmu::legacy::WORLD_BEGIN && serverSlot <= EQEmu::legacy::WORLD_END) { RoFSlot.Type = inventory::TypeWorld; - TempSlot = serverSlot - EQEmu::constants::WORLD_BEGIN; + TempSlot = serverSlot - EQEmu::legacy::WORLD_BEGIN; RoFSlot.Slot = TempSlot; } @@ -5846,16 +5846,16 @@ namespace RoF uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == SlotPowerSource) { // (< 52) + if (serverSlot < 56 || serverSlot == EQEmu::legacy::SlotPowerSource) { // (< 52) RoFSlot.Slot = serverSlot; - if (serverSlot == SlotPowerSource) + if (serverSlot == EQEmu::legacy::SlotPowerSource) RoFSlot.Slot = inventory::SlotPowerSource; - else if (serverSlot >= SlotCursor) // Cursor and Extended Corpse Inventory + else if (serverSlot >= EQEmu::legacy::SlotCursor) // Cursor and Extended Corpse Inventory RoFSlot.Slot += 3; - else if (serverSlot >= SlotAmmo) // Ammo and Personl Inventory + else if (serverSlot >= EQEmu::legacy::SlotAmmo) // Ammo and Personl Inventory RoFSlot.Slot += 1; /*else if (ServerSlot >= MainCursor) { // Cursor @@ -5866,10 +5866,10 @@ namespace RoF }*/ } - else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) { + else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) { TempSlot = serverSlot - 1; - RoFSlot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 2; - RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::constants::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 2; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::legacy::ITEM_CONTAINER_SIZE); } Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoFSlot.Slot, RoFSlot.SubIndex, RoFSlot.AugIndex, RoFSlot.Unknown01); @@ -5889,7 +5889,7 @@ namespace RoF if (rofSlot.Type == inventory::TypePossessions && rofSlot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 51) if (rofSlot.Slot == inventory::SlotPowerSource) - TempSlot = SlotPowerSource; + TempSlot = EQEmu::legacy::SlotPowerSource; else if (rofSlot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory TempSlot = rofSlot.Slot - 3; @@ -5912,16 +5912,16 @@ namespace RoF TempSlot = rofSlot.Slot; if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; + TempSlot = ((TempSlot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; ServerSlot = TempSlot; } else if (rofSlot.Type == inventory::TypeBank) { - TempSlot = EQEmu::constants::BANK_BEGIN; + TempSlot = EQEmu::legacy::BANK_BEGIN; if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rofSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; + TempSlot += ((rofSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; else TempSlot += rofSlot.Slot; @@ -5930,10 +5930,10 @@ namespace RoF } else if (rofSlot.Type == inventory::TypeSharedBank) { - TempSlot = EQEmu::constants::SHARED_BANK_BEGIN; + TempSlot = EQEmu::legacy::SHARED_BANK_BEGIN; if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rofSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; + TempSlot += ((rofSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; else TempSlot += rofSlot.Slot; @@ -5942,12 +5942,12 @@ namespace RoF } else if (rofSlot.Type == inventory::TypeTrade) { - TempSlot = EQEmu::constants::TRADE_BEGIN; + TempSlot = EQEmu::legacy::TRADE_BEGIN; if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rofSlot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; + TempSlot += ((rofSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; // OLD CODE: - //TempSlot += 100 + (RoFSlot.MainSlot * EQEmu::constants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot; + //TempSlot += 100 + (RoFSlot.MainSlot * EQEmu::legacy::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot; else TempSlot += rofSlot.Slot; @@ -5956,7 +5956,7 @@ namespace RoF } else if (rofSlot.Type == inventory::TypeWorld) { - TempSlot = EQEmu::constants::WORLD_BEGIN; + TempSlot = EQEmu::legacy::WORLD_BEGIN; if (rofSlot.Slot >= SUB_INDEX_BEGIN) TempSlot += rofSlot.Slot; @@ -5989,7 +5989,7 @@ namespace RoF if (rofSlot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 33) if (rofSlot.Slot == inventory::SlotPowerSource) - TempSlot = SlotPowerSource; + TempSlot = EQEmu::legacy::SlotPowerSource; else if (rofSlot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory TempSlot = rofSlot.Slot - 3; @@ -6007,7 +6007,7 @@ namespace RoF TempSlot = rofSlot.Slot; if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; + TempSlot = ((TempSlot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; ServerSlot = TempSlot; } @@ -6024,7 +6024,7 @@ namespace RoF static inline void ServerToRoFTextLink(std::string& rofTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { rofTextLink = serverTextLink; return; } @@ -6033,7 +6033,7 @@ namespace RoF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) { rofTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -6063,7 +6063,7 @@ namespace RoF static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink) { - if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find('\x12') == std::string::npos)) { serverTextLink = rofTextLink; return; } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 4977ad984..005b1d298 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2421,7 +2421,7 @@ namespace RoF2 outapp->WriteUInt32(consts::BANDOLIERS_SIZE); // Copy bandoliers where server and client indexes converge - for (uint32 r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(emu->bandoliers[r].Name); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(emu->bandoliers[r].Items[j].Name); @@ -2436,7 +2436,7 @@ namespace RoF2 } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { outapp->WriteString(""); for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(""); @@ -2448,7 +2448,7 @@ namespace RoF2 outapp->WriteUInt32(consts::POTION_BELT_ITEM_COUNT); // Copy potion belt where server and client indexes converge - for (uint32 r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(emu->potionbelt.Items[r].Name); outapp->WriteUInt32(emu->potionbelt.Items[r].ID); if (emu->potionbelt.Items[r].Icon) { @@ -2460,7 +2460,7 @@ namespace RoF2 } } // Nullify potion belt where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(""); outapp->WriteUInt32(0); outapp->WriteSInt32(-1); @@ -2577,9 +2577,9 @@ namespace RoF2 outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt32(EQEmu::constants::TRIBUTE_SIZE); + outapp->WriteUInt32(EQEmu::legacy::TRIBUTE_SIZE); - for (uint32 r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) + for (uint32 r = 0; r < EQEmu::legacy::TRIBUTE_SIZE; r++) { outapp->WriteUInt32(emu->tributes[r].tribute); outapp->WriteUInt32(emu->tributes[r].tier); @@ -3126,7 +3126,7 @@ namespace RoF2 eq_cse->Gender = emu_cse->Gender; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::legacy::MaterialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -4320,13 +4320,13 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialPrimary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialSecondary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); @@ -5028,7 +5028,7 @@ namespace RoF2 IN(item_id); int r; - for (r = 0; r < EQEmu::constants::ITEM_COMMON_SIZE; r++) { + for (r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { IN(augments[r]); } IN(link_hash); @@ -5961,7 +5961,7 @@ namespace RoF2 uint32 SubLengths[10]; - for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -5973,15 +5973,15 @@ namespace RoF2 iqbs.subitem_count++; - if (slot_id_in >= EQEmu::constants::GENERAL_BEGIN && slot_id_in <= EQEmu::constants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::constants::BANK_BEGIN && slot_id_in <= EQEmu::constants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::constants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -5996,7 +5996,7 @@ namespace RoF2 ss.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); - for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { if (SubSerializations[x]) { @@ -6028,11 +6028,11 @@ namespace RoF2 uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == SlotPowerSource) { // Main Inventory and Cursor + if (serverSlot < 56 || serverSlot == EQEmu::legacy::SlotPowerSource) { // Main Inventory and Cursor if (PacketType == ItemPacketLoot) { RoF2Slot.Type = inventory::TypeCorpse; - RoF2Slot.Slot = serverSlot - EQEmu::constants::CORPSE_BEGIN; + RoF2Slot.Slot = serverSlot - EQEmu::legacy::CORPSE_BEGIN; } else { @@ -6040,13 +6040,13 @@ namespace RoF2 RoF2Slot.Slot = serverSlot; } - if (serverSlot == SlotPowerSource) + if (serverSlot == EQEmu::legacy::SlotPowerSource) RoF2Slot.Slot = inventory::SlotPowerSource; - else if (serverSlot >= SlotCursor && PacketType != ItemPacketLoot) // Cursor and Extended Corpse Inventory + else if (serverSlot >= EQEmu::legacy::SlotCursor && PacketType != ItemPacketLoot) // Cursor and Extended Corpse Inventory RoF2Slot.Slot += 3; - else if (serverSlot >= SlotAmmo) // (> 20) + else if (serverSlot >= EQEmu::legacy::SlotAmmo) // (> 20) RoF2Slot.Slot += 1; } @@ -6055,51 +6055,51 @@ namespace RoF2 RoF2Slot.MainSlot = ServerSlot - 31; }*/ - else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) { // (> 250 && < 341) + else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) { // (> 250 && < 341) RoF2Slot.Type = inventory::TypePossessions; TempSlot = serverSlot - 1; - RoF2Slot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 2; - RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::constants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 2; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::legacy::ITEM_CONTAINER_SIZE); if (RoF2Slot.Slot >= inventory::SlotGeneral9) // (> 30) RoF2Slot.Slot = inventory::SlotCursor; } - else if (serverSlot >= EQEmu::constants::TRIBUTE_BEGIN && serverSlot <= EQEmu::constants::TRIBUTE_END) { // Tribute + else if (serverSlot >= EQEmu::legacy::TRIBUTE_BEGIN && serverSlot <= EQEmu::legacy::TRIBUTE_END) { // Tribute RoF2Slot.Type = inventory::TypeTribute; - RoF2Slot.Slot = serverSlot - EQEmu::constants::TRIBUTE_BEGIN; + RoF2Slot.Slot = serverSlot - EQEmu::legacy::TRIBUTE_BEGIN; } - else if (serverSlot >= EQEmu::constants::BANK_BEGIN && serverSlot <= EQEmu::constants::BANK_BAGS_END) { + else if (serverSlot >= EQEmu::legacy::BANK_BEGIN && serverSlot <= EQEmu::legacy::BANK_BAGS_END) { RoF2Slot.Type = inventory::TypeBank; - TempSlot = serverSlot - EQEmu::constants::BANK_BEGIN; + TempSlot = serverSlot - EQEmu::legacy::BANK_BEGIN; RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoF2Slot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EQEmu::constants::SHARED_BANK_BEGIN && serverSlot <= EQEmu::constants::SHARED_BANK_BAGS_END) { + else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) { RoF2Slot.Type = inventory::TypeSharedBank; - TempSlot = serverSlot - EQEmu::constants::SHARED_BANK_BEGIN; + TempSlot = serverSlot - EQEmu::legacy::SHARED_BANK_BEGIN; RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoF2Slot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); } } - else if (serverSlot >= EQEmu::constants::TRADE_BEGIN && serverSlot <= EQEmu::constants::TRADE_BAGS_END) { + else if (serverSlot >= EQEmu::legacy::TRADE_BEGIN && serverSlot <= EQEmu::legacy::TRADE_BAGS_END) { RoF2Slot.Type = inventory::TypeTrade; - TempSlot = serverSlot - EQEmu::constants::TRADE_BEGIN; + TempSlot = serverSlot - EQEmu::legacy::TRADE_BEGIN; RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { - RoF2Slot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); } /* @@ -6116,9 +6116,9 @@ namespace RoF2 */ } - else if (serverSlot >= EQEmu::constants::WORLD_BEGIN && serverSlot <= EQEmu::constants::WORLD_END) { + else if (serverSlot >= EQEmu::legacy::WORLD_BEGIN && serverSlot <= EQEmu::legacy::WORLD_END) { RoF2Slot.Type = inventory::TypeWorld; - TempSlot = serverSlot - EQEmu::constants::WORLD_BEGIN; + TempSlot = serverSlot - EQEmu::legacy::WORLD_BEGIN; RoF2Slot.Slot = TempSlot; } @@ -6137,16 +6137,16 @@ namespace RoF2 uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == SlotPowerSource) { // (< 52) + if (serverSlot < 56 || serverSlot == EQEmu::legacy::SlotPowerSource) { // (< 52) RoF2Slot.Slot = serverSlot; - if (serverSlot == SlotPowerSource) + if (serverSlot == EQEmu::legacy::SlotPowerSource) RoF2Slot.Slot = inventory::SlotPowerSource; - else if (serverSlot >= SlotCursor) // Cursor and Extended Corpse Inventory + else if (serverSlot >= EQEmu::legacy::SlotCursor) // Cursor and Extended Corpse Inventory RoF2Slot.Slot += 3; - else if (serverSlot >= SlotAmmo) // Ammo and Personl Inventory + else if (serverSlot >= EQEmu::legacy::SlotAmmo) // Ammo and Personl Inventory RoF2Slot.Slot += 1; /*else if (ServerSlot >= MainCursor) { // Cursor @@ -6157,10 +6157,10 @@ namespace RoF2 }*/ } - else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) { + else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) { TempSlot = serverSlot - 1; - RoF2Slot.Slot = int(TempSlot / EQEmu::constants::ITEM_CONTAINER_SIZE) - 2; - RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::constants::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 2; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::legacy::ITEM_CONTAINER_SIZE); } Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoF2Slot.Slot, RoF2Slot.SubIndex, RoF2Slot.AugIndex, RoF2Slot.Unknown01); @@ -6170,7 +6170,7 @@ namespace RoF2 static inline uint32 ServerToRoF2CorpseSlot(uint32 serverCorpseSlot) { - return (serverCorpseSlot - EQEmu::constants::CORPSE_BEGIN + 1); + return (serverCorpseSlot - EQEmu::legacy::CORPSE_BEGIN + 1); } static inline uint32 RoF2ToServerSlot(structs::InventorySlot_Struct rof2Slot, ItemPacketType PacketType) @@ -6180,7 +6180,7 @@ namespace RoF2 if (rof2Slot.Type == inventory::TypePossessions && rof2Slot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 51) if (rof2Slot.Slot == inventory::SlotPowerSource) - TempSlot = SlotPowerSource; + TempSlot = EQEmu::legacy::SlotPowerSource; else if (rof2Slot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory TempSlot = rof2Slot.Slot - 3; @@ -6203,16 +6203,16 @@ namespace RoF2 TempSlot = rof2Slot.Slot; if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; + TempSlot = ((TempSlot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; ServerSlot = TempSlot; } else if (rof2Slot.Type == inventory::TypeBank) { - TempSlot = EQEmu::constants::BANK_BEGIN; + TempSlot = EQEmu::legacy::BANK_BEGIN; if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rof2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; else TempSlot += rof2Slot.Slot; @@ -6221,10 +6221,10 @@ namespace RoF2 } else if (rof2Slot.Type == inventory::TypeSharedBank) { - TempSlot = EQEmu::constants::SHARED_BANK_BEGIN; + TempSlot = EQEmu::legacy::SHARED_BANK_BEGIN; if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rof2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; else TempSlot += rof2Slot.Slot; @@ -6233,10 +6233,10 @@ namespace RoF2 } else if (rof2Slot.Type == inventory::TypeTrade) { - TempSlot = EQEmu::constants::TRADE_BEGIN; + TempSlot = EQEmu::legacy::TRADE_BEGIN; if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rof2Slot.Slot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; // OLD CODE: //TempSlot += 100 + (RoF2Slot.MainSlot * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot; @@ -6247,7 +6247,7 @@ namespace RoF2 } else if (rof2Slot.Type == inventory::TypeWorld) { - TempSlot = EQEmu::constants::WORLD_BEGIN; + TempSlot = EQEmu::legacy::WORLD_BEGIN; if (rof2Slot.Slot >= SUB_INDEX_BEGIN) TempSlot += rof2Slot.Slot; @@ -6269,7 +6269,7 @@ namespace RoF2 } else if (rof2Slot.Type == inventory::TypeCorpse) { - ServerSlot = rof2Slot.Slot + EQEmu::constants::CORPSE_BEGIN; + ServerSlot = rof2Slot.Slot + EQEmu::legacy::CORPSE_BEGIN; } Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", rof2Slot.Type, rof2Slot.Unknown02, rof2Slot.Slot, rof2Slot.SubIndex, rof2Slot.AugIndex, rof2Slot.Unknown01, ServerSlot); @@ -6284,7 +6284,7 @@ namespace RoF2 if (rof2Slot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 33) if (rof2Slot.Slot == inventory::SlotPowerSource) - TempSlot = SlotPowerSource; + TempSlot = EQEmu::legacy::SlotPowerSource; else if (rof2Slot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory TempSlot = rof2Slot.Slot - 3; @@ -6302,7 +6302,7 @@ namespace RoF2 TempSlot = rof2Slot.Slot; if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; + TempSlot = ((TempSlot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; ServerSlot = TempSlot; } @@ -6314,12 +6314,12 @@ namespace RoF2 static inline uint32 RoF2ToServerCorpseSlot(uint32 rof2CorpseSlot) { - return (rof2CorpseSlot + EQEmu::constants::CORPSE_BEGIN - 1); + return (rof2CorpseSlot + EQEmu::legacy::CORPSE_BEGIN - 1); } static inline void ServerToRoF2TextLink(std::string& rof2TextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { rof2TextLink = serverTextLink; return; } @@ -6328,7 +6328,7 @@ namespace RoF2 for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) { rof2TextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -6351,7 +6351,7 @@ namespace RoF2 static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink) { - if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find('\x12') == std::string::npos)) { serverTextLink = rof2TextLink; return; } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 18ab3c478..0e457a0d1 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1084,11 +1084,11 @@ union /*00184*/ EquipStruct equipment[22]; // Total Slots }; /*00624*/ uint32 equip2_count; // Seen 9 -/*00628*/ EquipStruct equipment2[MaterialCount]; // Appears to be Visible slots, but all 0s +/*00628*/ EquipStruct equipment2[EQEmu::legacy::MaterialCount]; // Appears to be Visible slots, but all 0s /*00808*/ uint32 tint_count; // Seen 9 -/*00812*/ Color_Struct item_tint[MaterialCount]; // RR GG BB 00 +/*00812*/ Color_Struct item_tint[EQEmu::legacy::MaterialCount]; // RR GG BB 00 /*00848*/ uint32 tint_count2; // Seen 9 -/*00852*/ Color_Struct item_tint2[MaterialCount]; // RR GG BB 00 +/*00852*/ Color_Struct item_tint2[EQEmu::legacy::MaterialCount]; // RR GG BB 00 /*00888*/ uint8 haircolor; // Player hair color /*00889*/ uint8 beardcolor; // Player beard color /*00890*/ uint32 unknown_rof5; // diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 7b75e5d5d..48b7248ed 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1614,7 +1614,7 @@ namespace SoD // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -1623,7 +1623,7 @@ namespace SoD } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -1635,13 +1635,13 @@ namespace SoD // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -1981,7 +1981,7 @@ namespace SoD eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::legacy::MaterialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -2779,11 +2779,11 @@ namespace SoD VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialPrimary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialSecondary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); } @@ -3934,7 +3934,7 @@ namespace SoD uint32 SubLengths[10]; - for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -3946,15 +3946,15 @@ namespace SoD iqbs.subitem_count++; - if (slot_id_in >= EQEmu::constants::GENERAL_BEGIN && slot_id_in <= EQEmu::constants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::constants::BANK_BEGIN && slot_id_in <= EQEmu::constants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::constants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -3993,15 +3993,15 @@ namespace SoD { uint32 SoDSlot = 0; - if (serverSlot >= SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (serverSlot >= EQEmu::legacy::SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots SoDSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) + else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) SoDSlot = serverSlot + 11; - else if (serverSlot >= EQEmu::constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::BANK_BAGS_END) + else if (serverSlot >= EQEmu::legacy::BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::BANK_BAGS_END) SoDSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::SHARED_BANK_BAGS_END) + else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) SoDSlot = serverSlot + 1; - else if (serverSlot == SlotPowerSource) + else if (serverSlot == EQEmu::legacy::SlotPowerSource) SoDSlot = inventory::SlotPowerSource; else SoDSlot = serverSlot; @@ -4027,7 +4027,7 @@ namespace SoD else if (sodSlot >= consts::SHARED_BANK_BAGS_BEGIN && sodSlot <= consts::SHARED_BANK_BAGS_END) ServerSlot = sodSlot - 1; else if (sodSlot == inventory::SlotPowerSource) - ServerSlot = SlotPowerSource; + ServerSlot = EQEmu::legacy::SlotPowerSource; else ServerSlot = sodSlot; return ServerSlot; @@ -4041,7 +4041,7 @@ namespace SoD static inline void ServerToSoDTextLink(std::string& sodTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { sodTextLink = serverTextLink; return; } @@ -4050,7 +4050,7 @@ namespace SoD for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) { sodTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -4081,7 +4081,7 @@ namespace SoD static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink) { - if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find('\x12') == std::string::npos)) { serverTextLink = sodTextLink; return; } diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 5a49f96a9..ef0220f57 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1271,7 +1271,7 @@ namespace SoF // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -1280,7 +1280,7 @@ namespace SoF } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -1292,13 +1292,13 @@ namespace SoF // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -1638,7 +1638,7 @@ namespace SoF eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::legacy::MaterialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -3256,7 +3256,7 @@ namespace SoF uint32 SubLengths[10]; - for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); @@ -3267,15 +3267,15 @@ namespace SoF iqbs.subitem_count++; - if (slot_id_in >= EQEmu::constants::GENERAL_BEGIN && slot_id_in <= EQEmu::constants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::constants::BANK_BEGIN && slot_id_in <= EQEmu::constants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::constants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -3312,15 +3312,15 @@ namespace SoF { uint32 SoFSlot = 0; - if (serverSlot >= SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (serverSlot >= EQEmu::legacy::SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots SoFSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) + else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) SoFSlot = serverSlot + 11; - else if (serverSlot >= EQEmu::constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::BANK_BAGS_END) + else if (serverSlot >= EQEmu::legacy::BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::BANK_BAGS_END) SoFSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::SHARED_BANK_BAGS_END) + else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) SoFSlot = serverSlot + 1; - else if (serverSlot == SlotPowerSource) + else if (serverSlot == EQEmu::legacy::SlotPowerSource) SoFSlot = inventory::SlotPowerSource; else SoFSlot = serverSlot; @@ -3347,7 +3347,7 @@ namespace SoF else if (sofSlot >= consts::SHARED_BANK_BAGS_BEGIN && sofSlot <= consts::SHARED_BANK_BAGS_END) ServerSlot = sofSlot - 1; else if (sofSlot == inventory::SlotPowerSource) - ServerSlot = SlotPowerSource; + ServerSlot = EQEmu::legacy::SlotPowerSource; else ServerSlot = sofSlot; @@ -3362,7 +3362,7 @@ namespace SoF static inline void ServerToSoFTextLink(std::string& sofTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { sofTextLink = serverTextLink; return; } @@ -3371,7 +3371,7 @@ namespace SoF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) { sofTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -3402,7 +3402,7 @@ namespace SoF static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink) { - if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find('\x12') == std::string::npos)) { serverTextLink = sofTextLink; return; } diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 5afbcb0d6..cb291150c 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -943,7 +943,7 @@ namespace Titanium // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -952,7 +952,7 @@ namespace Titanium } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -964,13 +964,13 @@ namespace Titanium // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -1199,14 +1199,14 @@ namespace Titanium if (eq->Race[char_index] > 473) eq->Race[char_index] = 1; - for (int index = 0; index < MaterialCount; ++index) { + for (int index = 0; index < EQEmu::legacy::MaterialCount; ++index) { eq->CS_Colors[char_index][index].Color = emu_cse->Equip[index].Color.Color; } eq->BeardColor[char_index] = emu_cse->BeardColor; eq->HairStyle[char_index] = emu_cse->HairStyle; - for (int index = 0; index < MaterialCount; ++index) { + for (int index = 0; index < EQEmu::legacy::MaterialCount; ++index) { eq->Equip[char_index][index] = emu_cse->Equip[index].Material; } @@ -1236,14 +1236,14 @@ namespace Titanium for (; char_index < 10; ++char_index) { eq->Race[char_index] = 0; - for (int index = 0; index < MaterialCount; ++index) { + for (int index = 0; index < EQEmu::legacy::MaterialCount; ++index) { eq->CS_Colors[char_index][index].Color = 0; } eq->BeardColor[char_index] = 0; eq->HairStyle[char_index] = 0; - for (int index = 0; index < MaterialCount; ++index) { + for (int index = 0; index < EQEmu::legacy::MaterialCount; ++index) { eq->Equip[char_index][index] = 0; } @@ -2198,7 +2198,7 @@ namespace Titanium static inline void ServerToTitaniumTextLink(std::string& titaniumTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { titaniumTextLink = serverTextLink; return; } @@ -2207,7 +2207,7 @@ namespace Titanium for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) { titaniumTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -2238,7 +2238,7 @@ namespace Titanium static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink) { - if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find('\x12') == std::string::npos)) { serverTextLink = titaniumTextLink; return; } diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index ff51b2e7d..28ff1d541 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1878,7 +1878,7 @@ namespace UF // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::constants::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { OUT_str(bandoliers[r].Name); for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); @@ -1887,7 +1887,7 @@ namespace UF } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::constants::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { eq->bandoliers[r].Name[0] = '\0'; for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; @@ -1899,13 +1899,13 @@ namespace UF // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::constants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::constants::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -2274,7 +2274,7 @@ namespace UF eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::legacy::MaterialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -3053,19 +3053,19 @@ namespace UF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - if (emu->equipment[MaterialPrimary].Material > 99999) { + if (emu->equipment[EQEmu::legacy::MaterialPrimary].Material > 99999) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63); } else { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialPrimary].Material); } VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - if (emu->equipment[MaterialSecondary].Material > 99999) { + if (emu->equipment[EQEmu::legacy::MaterialSecondary].Material > 99999) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63); } else { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialSecondary].Material); } VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); @@ -4263,7 +4263,7 @@ namespace UF uint32 SubLengths[10]; - for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { SubSerializations[x] = nullptr; @@ -4275,15 +4275,15 @@ namespace UF iqbs.subitem_count++; - if (slot_id_in >= EQEmu::constants::GENERAL_BEGIN && slot_id_in <= EQEmu::constants::GENERAL_END) // (< 30) - no cursor? + if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor? //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::constants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::constants::BANK_BEGIN && slot_id_in <= EQEmu::constants::BANK_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::constants::BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::constants::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::constants::SHARED_BANK_BEGIN) * EQEmu::constants::ITEM_CONTAINER_SIZE) + EQEmu::constants::SHARED_BANK_BAGS_BEGIN + x); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x); else SubSlotNumber = slot_id_in; // ??????? @@ -4322,15 +4322,15 @@ namespace UF { uint32 UnderfootSlot = 0; - if (serverSlot >= SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (serverSlot >= EQEmu::legacy::SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots UnderfootSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::constants::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::constants::CURSOR_BAG_END) + else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) UnderfootSlot = serverSlot + 11; - else if (serverSlot >= EQEmu::constants::BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::BANK_BAGS_END) + else if (serverSlot >= EQEmu::legacy::BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::BANK_BAGS_END) UnderfootSlot = serverSlot + 1; - else if (serverSlot >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::constants::SHARED_BANK_BAGS_END) + else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) UnderfootSlot = serverSlot + 1; - else if (serverSlot == SlotPowerSource) + else if (serverSlot == EQEmu::legacy::SlotPowerSource) UnderfootSlot = inventory::SlotPowerSource; else UnderfootSlot = serverSlot; @@ -4357,7 +4357,7 @@ namespace UF else if (ufSlot >= consts::SHARED_BANK_BAGS_BEGIN && ufSlot <= consts::SHARED_BANK_BAGS_END) ServerSlot = ufSlot - 1; else if (ufSlot == inventory::SlotPowerSource) - ServerSlot = SlotPowerSource; + ServerSlot = EQEmu::legacy::SlotPowerSource; else ServerSlot = ufSlot; @@ -4372,7 +4372,7 @@ namespace UF static inline void ServerToUFTextLink(std::string& ufTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::constants::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { ufTextLink = serverTextLink; return; } @@ -4381,7 +4381,7 @@ namespace UF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= EQEmu::constants::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= EQEmu::legacy::TEXT_LINK_BODY_LENGTH) { ufTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; @@ -4412,7 +4412,7 @@ namespace UF static inline void UFToServerTextLink(std::string& serverTextLink, const std::string& ufTextLink) { - if ((EQEmu::constants::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (ufTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (ufTextLink.find('\x12') == std::string::npos)) { serverTextLink = ufTextLink; return; } diff --git a/common/say_link.cpp b/common/say_link.cpp index 0f9fefaa5..1cfe2635a 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -39,7 +39,7 @@ std::string EQEmu::saylink::SayLinkEngine::GenerateLink() generate_body(); generate_text(); - if ((m_LinkBody.length() == EQEmu::constants::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) { + if ((m_LinkBody.length() == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) && (m_LinkText.length() > 0)) { m_Link.push_back(0x12); m_Link.append(m_LinkBody); m_Link.append(m_LinkText); @@ -231,7 +231,7 @@ void EQEmu::saylink::SayLinkEngine::generate_text() bool EQEmu::saylink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct, const std::string& say_link_body) { memset(&say_link_body_struct, 0, sizeof(say_link_body_struct)); - if (say_link_body.length() != EQEmu::constants::TEXT_LINK_BODY_LENGTH) + if (say_link_body.length() != EQEmu::legacy::TEXT_LINK_BODY_LENGTH) return false; say_link_body_struct.unknown_1 = (uint8)strtol(say_link_body.substr(0, 1).c_str(), nullptr, 16); @@ -270,7 +270,7 @@ bool EQEmu::saylink::GenerateLinkBody(std::string& say_link_body, const SayLinkB (0xFFFFFFFF & say_link_body_struct.hash) ); - if (say_link_body.length() != EQEmu::constants::TEXT_LINK_BODY_LENGTH) + if (say_link_body.length() != EQEmu::legacy::TEXT_LINK_BODY_LENGTH) return false; return true; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 16f8096b8..ddf7b383f 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -104,8 +104,8 @@ bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iter std::string query = StringFormat("DELETE FROM inventory WHERE charid = %i " "AND ((slotid >= 8000 AND slotid <= 8999) " "OR slotid = %i OR (slotid >= %i AND slotid <= %i) )", - char_id, SlotCursor, - EQEmu::constants::CURSOR_BAG_BEGIN, EQEmu::constants::CURSOR_BAG_END); + char_id, EQEmu::legacy::SlotCursor, + EQEmu::legacy::CURSOR_BAG_BEGIN, EQEmu::legacy::CURSOR_BAG_END); auto results = QueryDatabase(query); if (!results.Success()) { std::cout << "Clearing cursor failed: " << results.ErrorMessage() << std::endl; @@ -116,7 +116,7 @@ bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iter for(auto it = start; it != end; ++it, i++) { if (i > 8999) { break; } // shouldn't be anything in the queue that indexes this high ItemInst *inst = *it; - int16 use_slot = (i == 8000) ? SlotCursor : i; + int16 use_slot = (i == 8000) ? EQEmu::legacy::SlotCursor : i; if (!SaveInventory(char_id, inst, use_slot)) { return false; } @@ -161,10 +161,10 @@ bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const Ite bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 slot_id) { //never save tribute slots: - if (slot_id >= EQEmu::constants::TRIBUTE_BEGIN && slot_id <= EQEmu::constants::TRIBUTE_END) + if (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) return true; - if (slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { + if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { // Shared bank inventory if (!inst) { return DeleteSharedBankSlot(char_id, slot_id); @@ -191,9 +191,9 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 s bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer - uint32 augslot[EQEmu::constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; + uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; if (inst->IsType(ItemClassCommon)) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { ItemInst *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM; } @@ -223,7 +223,7 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) - for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::constants::ITEM_CONTAINER_SIZE; idx++) { + for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = inst->GetItem(idx); SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); } @@ -238,9 +238,9 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer - uint32 augslot[EQEmu::constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; + uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; if (inst->IsType(ItemClassCommon)) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { ItemInst *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM; } @@ -269,7 +269,7 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) { // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) - for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::constants::ITEM_CONTAINER_SIZE; idx++) { + for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = inst->GetItem(idx); SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); } @@ -427,7 +427,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) uint32 item_id = (uint32)atoi(row[1]); int8 charges = (int8)atoi(row[2]); - uint32 aug[EQEmu::constants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::legacy::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoi(row[3]); aug[1] = (uint32)atoi(row[4]); aug[2] = (uint32)atoi(row[5]); @@ -448,7 +448,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) ItemInst *inst = CreateBaseItem(item, charges); if (inst && item->ItemClass == ItemClassCommon) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } @@ -522,7 +522,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) uint16 charges = atoi(row[2]); uint32 color = atoul(row[3]); - uint32 aug[EQEmu::constants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::legacy::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoul(row[4]); aug[1] = (uint32)atoul(row[5]); @@ -584,8 +584,8 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) inst->SetOrnamentHeroModel(ornament_hero_model); if (instnodrop || - (((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN && slot_id <= EQEmu::constants::EQUIPMENT_END) || - slot_id == SlotPowerSource) && + (((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || + slot_id == EQEmu::legacy::SlotPowerSource) && inst->GetItem()->Attuneable)) inst->SetAttuned(true); @@ -608,7 +608,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) } if (item->ItemClass == ItemClassCommon) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } @@ -665,7 +665,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) int8 charges = atoi(row[2]); uint32 color = atoul(row[3]); - uint32 aug[EQEmu::constants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::legacy::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoi(row[4]); aug[1] = (uint32)atoi(row[5]); aug[2] = (uint32)atoi(row[6]); @@ -726,7 +726,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) inst->SetCharges(charges); if (item->ItemClass == ItemClassCommon) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } diff --git a/world/worlddb.cpp b/world/worlddb.cpp index aed60e245..346f3a2e6 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -117,7 +117,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou cse->Gender = (uint8)atoi(row[2]); cse->Face = (uint8)atoi(row[15]); - for (uint32 matslot = 0; matslot < MaterialCount; matslot++) { // Processed below + for (uint32 matslot = 0; matslot < EQEmu::legacy::MaterialCount; matslot++) { // Processed below cse->Equip[matslot].Material = 0; cse->Equip[matslot].Unknown1 = 0; cse->Equip[matslot].EliteMaterial = 0; @@ -223,7 +223,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou const ItemInst* inst = nullptr; int16 invslot = 0; - for (uint32 matslot = 0; matslot < MaterialCount; matslot++) { + for (uint32 matslot = 0; matslot < EQEmu::legacy::MaterialCount; matslot++) { invslot = Inventory::CalcSlotFromMaterial(matslot); if (invslot == INVALID_INDEX) { continue; } inst = inv.GetItem(invslot); @@ -244,7 +244,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou cse->Equip[matslot].Material = idfile; } } - if (matslot == MaterialPrimary) { + if (matslot == EQEmu::legacy::MaterialPrimary) { cse->PrimaryIDFile = idfile; } else { diff --git a/zone/aa.cpp b/zone/aa.cpp index 26c168276..210e88cd2 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -418,7 +418,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) //gear stuff, need to make sure there's //no situation where this stuff can be duped - for (int x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::EQUIPMENT_END; x++) // (< 21) added MainAmmo + for (int x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::EQUIPMENT_END; x++) // (< 21) added MainAmmo { uint32 sitem = 0; sitem = CorpseToUse->GetWornItem(x); diff --git a/zone/attack.cpp b/zone/attack.cpp index 7df1c1ed5..d605a0da6 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -166,7 +166,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w } // If we're attacking with the secondary hand, play the dual wield anim - if (Hand == SlotSecondary) // DW anim + if (Hand == EQEmu::legacy::SlotSecondary) // DW anim type = animDualWield; DoAnim(type); @@ -415,7 +415,7 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) // riposte -- it may seem crazy, but if the attacker has SPA 173 on them, they are immune to Ripo bool ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance; // Need to check if we have something in MainHand to actually attack with (or fists) - if (hand != SlotRange && CanThisClassRiposte() && InFront && !ImmuneRipo) { + if (hand != EQEmu::legacy::SlotRange && CanThisClassRiposte() && InFront && !ImmuneRipo) { if (IsClient()) CastToClient()->CheckIncreaseSkill(SkillRiposte, other, -10); // check auto discs ... I guess aa/items too :P @@ -432,7 +432,7 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) chance -= chance * counter; } // AA Slippery Attacks - if (hand == SlotSecondary) { + if (hand == EQEmu::legacy::SlotSecondary) { int slip = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail; chance += chance * slip / 100; } @@ -477,7 +477,7 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) } // parry - if (CanThisClassParry() && InFront && hand != SlotRange) { + if (CanThisClassParry() && InFront && hand != EQEmu::legacy::SlotRange) { if (IsClient()) CastToClient()->CheckIncreaseSkill(SkillParry, other, -10); // check auto discs ... I guess aa/items too :P @@ -964,7 +964,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate } else { bool MagicGloves = false; if (IsClient()) { - const ItemInst *gloves = CastToClient()->GetInv().GetItem(SlotHands); + const ItemInst *gloves = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotHands); if (gloves) MagicGloves = gloves->GetItemMagical(true); } @@ -1073,12 +1073,12 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code. ItemInst* weapon; - if (Hand == SlotSecondary){ // Kaiyodo - Pick weapon from the attacking hand - weapon = GetInv().GetItem(SlotSecondary); + if (Hand == EQEmu::legacy::SlotSecondary){ // Kaiyodo - Pick weapon from the attacking hand + weapon = GetInv().GetItem(EQEmu::legacy::SlotSecondary); OffHandAtk(true); } else{ - weapon = GetInv().GetItem(SlotPrimary); + weapon = GetInv().GetItem(EQEmu::legacy::SlotPrimary); OffHandAtk(false); } @@ -1146,7 +1146,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b int ucDamageBonus = 0; - if( Hand == SlotPrimary && GetLevel() >= 28 && IsWarriorClass() ) + if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. @@ -1159,7 +1159,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b } #endif //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. - if (Hand == SlotSecondary) { + if (Hand == EQEmu::legacy::SlotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr, true ); @@ -1621,28 +1621,28 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool FaceTarget(GetTarget()); SkillUseTypes skillinuse = SkillHandtoHand; - if (Hand == SlotPrimary) { + if (Hand == EQEmu::legacy::SlotPrimary) { skillinuse = static_cast(GetPrimSkill()); OffHandAtk(false); } - if (Hand == SlotSecondary) { + if (Hand == EQEmu::legacy::SlotSecondary) { skillinuse = static_cast(GetSecSkill()); OffHandAtk(true); } //figure out what weapon they are using, if any const Item_Struct* weapon = nullptr; - if (Hand == SlotPrimary && equipment[SlotPrimary] > 0) - weapon = database.GetItem(equipment[SlotPrimary]); - else if (equipment[SlotSecondary]) - weapon = database.GetItem(equipment[SlotSecondary]); + if (Hand == EQEmu::legacy::SlotPrimary && equipment[EQEmu::legacy::SlotPrimary] > 0) + weapon = database.GetItem(equipment[EQEmu::legacy::SlotPrimary]); + else if (equipment[EQEmu::legacy::SlotSecondary]) + weapon = database.GetItem(equipment[EQEmu::legacy::SlotSecondary]); //We dont factor much from the weapon into the attack. //Just the skill type so it doesn't look silly using punching animations and stuff while wielding weapons if(weapon) { Log.Out(Logs::Detail, Logs::Combat, "Attacking with weapon: %s (%d) (too bad im not using it for much)", weapon->Name, weapon->ID); - if(Hand == SlotSecondary && weapon->ItemType == ItemTypeShield){ + if (Hand == EQEmu::legacy::SlotSecondary && weapon->ItemType == ItemTypeShield){ Log.Out(Logs::Detail, Logs::Combat, "Attack with shield canceled."); return false; } @@ -3532,7 +3532,7 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) { float ProcChance, ProcBonus; on->GetDefensiveProcChances(ProcBonus, ProcChance, hand , this); - if(hand != SlotPrimary) + if (hand != EQEmu::legacy::SlotPrimary) ProcChance /= 2; int level_penalty = 0; @@ -3605,7 +3605,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on ProcBonus += static_cast(itembonuses.ProcChance) / 10.0f; // Combat Effects float ProcChance = GetProcChances(ProcBonus, hand); - if (hand != SlotPrimary) //Is Archery intened to proc at 50% rate? + if (hand != EQEmu::legacy::SlotPrimary) //Is Archery intened to proc at 50% rate? ProcChance /= 2; // Try innate proc on weapon @@ -3642,7 +3642,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on proced = false; if (!proced && inst) { - for (int r = 0; r < EQEmu::constants::ITEM_COMMON_SIZE; r++) { + for (int r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { const ItemInst *aug_i = inst->GetAugment(r); if (!aug_i) // no aug, try next slot! continue; @@ -3683,11 +3683,11 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, float ProcChance = 0.0f; ProcChance = GetProcChances(ProcBonus, hand); - if (hand != SlotPrimary) //Is Archery intened to proc at 50% rate? + if (hand != EQEmu::legacy::SlotPrimary) //Is Archery intened to proc at 50% rate? ProcChance /= 2; bool rangedattk = false; - if (weapon && hand == SlotRange) { + if (weapon && hand == EQEmu::legacy::SlotRange) { if (weapon->ItemType == ItemTypeArrow || weapon->ItemType == ItemTypeLargeThrowing || weapon->ItemType == ItemTypeSmallThrowing || @@ -3695,11 +3695,11 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, rangedattk = true; } - if (!weapon && hand == SlotRange && GetSpecialAbility(SPECATK_RANGED_ATK)) + if (!weapon && hand == EQEmu::legacy::SlotRange && GetSpecialAbility(SPECATK_RANGED_ATK)) rangedattk = true; for (uint32 i = 0; i < MAX_PROCS; i++) { - if (IsPet() && hand != SlotPrimary) //Pets can only proc spell procs from their primay hand (ie; beastlord pets) + if (IsPet() && hand != EQEmu::legacy::SlotPrimary) //Pets can only proc spell procs from their primay hand (ie; beastlord pets) continue; // If pets ever can proc from off hand, this will need to change // Not ranged @@ -3762,7 +3762,7 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, } } - if (HasSkillProcs() && hand != SlotRange){ //We check ranged skill procs within the attack functions. + if (HasSkillProcs() && hand != EQEmu::legacy::SlotRange){ //We check ranged skill procs within the attack functions. uint16 skillinuse = 28; if (weapon) skillinuse = GetSkillByItemType(weapon->ItemType); @@ -4010,7 +4010,7 @@ void Mob::DoRiposte(Mob *defender) if (!defender) return; - defender->Attack(this, SlotPrimary, true); + defender->Attack(this, EQEmu::legacy::SlotPrimary, true); if (HasDied()) return; @@ -4021,7 +4021,7 @@ void Mob::DoRiposte(Mob *defender) if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) { Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposted from SE_DoubleRiposte (%d percent chance)", DoubleRipChance); - defender->Attack(this, SlotPrimary, true); + defender->Attack(this, EQEmu::legacy::SlotPrimary, true); if (HasDied()) return; } @@ -4034,7 +4034,7 @@ void Mob::DoRiposte(Mob *defender) Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposted from SE_GiveDoubleRiposte base1 == 0 (%d percent chance)", DoubleRipChance); - defender->Attack(this, SlotPrimary, true); + defender->Attack(this, EQEmu::legacy::SlotPrimary, true); if (HasDied()) return; } @@ -4312,7 +4312,7 @@ float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) { if (!ReuseTime && hand) { weapon_speed = GetWeaponSpeedbyHand(hand); ProcChance = static_cast(weapon_speed) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f); - if (hand != SlotPrimary) + if (hand != EQEmu::legacy::SlotPrimary) ProcChance /= 2; } @@ -4515,13 +4515,13 @@ void Client::SetAttackTimer() Timer *TimerToUse = nullptr; - for (int i = SlotRange; i <= SlotSecondary; i++) { + for (int i = EQEmu::legacy::SlotRange; i <= EQEmu::legacy::SlotSecondary; i++) { //pick a timer - if (i == SlotPrimary) + if (i == EQEmu::legacy::SlotPrimary) TimerToUse = &attack_timer; - else if (i == SlotRange) + else if (i == EQEmu::legacy::SlotRange) TimerToUse = &ranged_timer; - else if (i == SlotSecondary) + else if (i == EQEmu::legacy::SlotSecondary) TimerToUse = &attack_dw_timer; else //invalid slot (hands will always hit this) continue; @@ -4534,7 +4534,7 @@ void Client::SetAttackTimer() ItemToUse = ci->GetItem(); //special offhand stuff - if (i == SlotSecondary) { + if (i == EQEmu::legacy::SlotSecondary) { //if we cant dual wield, skip it if (!CanThisClassDualWield() || HasTwoHanderEquipped()) { attack_dw_timer.Disable(); @@ -4608,19 +4608,19 @@ void NPC::SetAttackTimer() else speed = static_cast(((attack_delay / haste_mod) + ((hhe / 100.0f) * attack_delay)) * 100); - for (int i = SlotRange; i <= SlotSecondary; i++) { + for (int i = EQEmu::legacy::SlotRange; i <= EQEmu::legacy::SlotSecondary; i++) { //pick a timer - if (i == SlotPrimary) + if (i == EQEmu::legacy::SlotPrimary) TimerToUse = &attack_timer; - else if (i == SlotRange) + else if (i == EQEmu::legacy::SlotRange) TimerToUse = &ranged_timer; - else if (i == SlotSecondary) + else if (i == EQEmu::legacy::SlotSecondary) TimerToUse = &attack_dw_timer; else //invalid slot (hands will always hit this) continue; //special offhand stuff - if (i == SlotSecondary) { + if (i == EQEmu::legacy::SlotSecondary) { // SPECATK_QUAD is uncheesable if(!CanThisClassDualWield() || (HasTwoHanderEquipped() && !GetSpecialAbility(SPECATK_QUAD))) { attack_dw_timer.Disable(); @@ -4642,7 +4642,7 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) bool candouble = CanThisClassDoubleAttack(); // extra off hand non-sense, can only double with skill of 150 or above // or you have any amount of GiveDoubleAttack - if (candouble && hand == SlotSecondary) + if (candouble && hand == EQEmu::legacy::SlotSecondary) candouble = GetSkill(SkillDoubleAttack) > 149 || (aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack) > 0; if (candouble) { @@ -4650,7 +4650,7 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) if (CheckDoubleAttack()) { Attack(target, hand, false, false, IsFromSpell); // you can only triple from the main hand - if (hand == SlotPrimary && CanThisClassTripleAttack()) { + if (hand == EQEmu::legacy::SlotPrimary && CanThisClassTripleAttack()) { CheckIncreaseSkill(SkillTripleAttack, target, -10); if (CheckTripleAttack()) Attack(target, hand, false, false, IsFromSpell); @@ -4658,7 +4658,7 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) } } - if (hand == SlotPrimary) { + if (hand == EQEmu::legacy::SlotPrimary) { // According to http://www.monkly-business.net/forums/showpost.php?p=312095&postcount=168 a dev told them flurry isn't dependant on triple attack // the parses kind of back that up and all of my parses seemed to be 4 or 5 attacks in the round which would work out to be // doubles or triples with 2 from flurries or triple with 1 or 2 flurries ... Going with the "dev quote" I guess like we've always had it @@ -4711,9 +4711,9 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec if (RuleB(Combat, UseLiveCombatRounds)) { // A "quad" on live really is just a successful dual wield where both double attack // The mobs that could triple lost the ability to when the triple attack skill was added in - Attack(target, SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); if (CanThisClassDoubleAttack() && CheckDoubleAttack()){ - Attack(target, SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ int chance = spellbonuses.PC_Pet_Flurry + itembonuses.PC_Pet_Flurry + aabonuses.PC_Pet_Flurry; @@ -4727,14 +4727,14 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec if (IsNPC()) { int16 n_atk = CastToNPC()->GetNumberOfAttacks(); if (n_atk <= 1) { - Attack(target, SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); } else { for (int i = 0; i < n_atk; ++i) { - Attack(target, SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); } } } else { - Attack(target, SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); } // we use this random value in three comparisons with different @@ -4745,15 +4745,15 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec // check double attack, this is NOT the same rules that clients use... && RandRoll < (GetLevel() + NPCDualAttackModifier)) { - Attack(target, SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); // lets see if we can do a triple attack with the main hand // pets are excluded from triple and quads... if ((GetSpecialAbility(SPECATK_TRIPLE) || GetSpecialAbility(SPECATK_QUAD)) && !IsPet() && RandRoll < (GetLevel() + NPCTripleAttackModifier)) { - Attack(target, SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); // now lets check the quad attack if (GetSpecialAbility(SPECATK_QUAD) && RandRoll < (GetLevel() + NPCQuadAttackModifier)) { - Attack(target, SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); } } } @@ -4767,11 +4767,11 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int speci // For now, SPECATK_QUAD means innate DW when Combat:UseLiveCombatRounds is true if ((GetSpecialAbility(SPECATK_INNATE_DW) || (RuleB(Combat, UseLiveCombatRounds) && GetSpecialAbility(SPECATK_QUAD))) || - GetEquipment(MaterialSecondary) != 0) { + GetEquipment(EQEmu::legacy::MaterialSecondary) != 0) { if (CheckDualWield()) { - Attack(target, SlotSecondary, false, false, false, opts, special); + Attack(target, EQEmu::legacy::SlotSecondary, false, false, false, opts, special); if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()){ - Attack(target, SlotSecondary, false, false, false, opts, special); + Attack(target, EQEmu::legacy::SlotSecondary, false, false, false, opts, special); if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ int chance = spellbonuses.PC_Pet_Flurry + itembonuses.PC_Pet_Flurry + aabonuses.PC_Pet_Flurry; diff --git a/zone/beacon.h b/zone/beacon.h index ed59ee7c9..bc09dae4b 100644 --- a/zone/beacon.h +++ b/zone/beacon.h @@ -36,7 +36,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } - virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 3239b514e..899cee359 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -145,34 +145,35 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { unsigned int i; // Update: MainAmmo should only calc skill mods (TODO: Check for other cases) - for (i = SlotCharm; i <= SlotAmmo; i++) { + for (i = EQEmu::legacy::SlotCharm; i <= EQEmu::legacy::SlotAmmo; i++) { const ItemInst* inst = m_inv[i]; if(inst == 0) continue; - AddItemBonuses(inst, newbon, false, false, 0, (i == SlotAmmo)); + AddItemBonuses(inst, newbon, false, false, 0, (i == EQEmu::legacy::SlotAmmo)); //These are given special flags due to how often they are checked for various spell effects. const Item_Struct *item = inst->GetItem(); - if (i == SlotSecondary && (item && item->ItemType == ItemTypeShield)) + if (i == EQEmu::legacy::SlotSecondary && (item && item->ItemType == ItemTypeShield)) SetShieldEquiped(true); - else if (i == SlotPrimary && (item && item->ItemType == ItemType2HBlunt)) { + else if (i == EQEmu::legacy::SlotPrimary && (item && item->ItemType == ItemType2HBlunt)) { SetTwoHandBluntEquiped(true); SetTwoHanderEquipped(true); - } else if (i == SlotPrimary && (item && (item->ItemType == ItemType2HSlash || item->ItemType == ItemType2HPiercing))) + } + else if (i == EQEmu::legacy::SlotPrimary && (item && (item->ItemType == ItemType2HSlash || item->ItemType == ItemType2HPiercing))) SetTwoHanderEquipped(true); } //Power Source Slot if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - const ItemInst* inst = m_inv[SlotPowerSource]; + const ItemInst* inst = m_inv[EQEmu::legacy::SlotPowerSource]; if(inst) AddItemBonuses(inst, newbon); } //tribute items - for (i = 0; i < EQEmu::constants::TRIBUTE_SIZE; i++) { - const ItemInst* inst = m_inv[EQEmu::constants::TRIBUTE_BEGIN + i]; + for (i = 0; i < EQEmu::legacy::TRIBUTE_SIZE; i++) { + const ItemInst* inst = m_inv[EQEmu::legacy::TRIBUTE_BEGIN + i]; if(inst == 0) continue; AddItemBonuses(inst, newbon, false, true); @@ -180,7 +181,7 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { //Optional ability to have worn effects calculate as an addititive bonus instead of highest value if (RuleI(Spells, AdditiveBonusWornType) && RuleI(Spells, AdditiveBonusWornType) != ET_WornEffect){ - for (i = SlotCharm; i < SlotAmmo; i++) { + for (i = EQEmu::legacy::SlotCharm; i < EQEmu::legacy::SlotAmmo; i++) { const ItemInst* inst = m_inv[i]; if(inst == 0) continue; @@ -526,7 +527,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu } if (!isAug) { - for (int i = 0; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) + for (int i = 0; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) AddItemBonuses(inst->GetAugment(i), newbon, true, false, rec_level, ammo_slot_item); } } @@ -564,7 +565,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool if (!isAug) { int i; - for (i = 0; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { + for (i = 0; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { AdditiveWornBonuses(inst->GetAugment(i),newbon,true); } } @@ -575,7 +576,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { bool food = false; bool drink = false; - for (i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_BAGS_BEGIN; i++) + for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_BAGS_BEGIN; i++) { if (food && drink) break; @@ -591,7 +592,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { AddItemBonuses(inst, newbon); } } - for (i = EQEmu::constants::GENERAL_BAGS_BEGIN; i <= EQEmu::constants::GENERAL_BAGS_END; i++) + for (i = EQEmu::legacy::GENERAL_BAGS_BEGIN; i <= EQEmu::legacy::GENERAL_BAGS_END; i++) { if (food && drink) break; @@ -3200,7 +3201,7 @@ void NPC::CalcItemBonuses(StatBonuses *newbon) { if(newbon){ - for (int i = 0; i < EQEmu::constants::EQUIPMENT_SIZE; i++){ + for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++){ const Item_Struct *cur = database.GetItem(equipment[i]); if(cur){ //basic stats @@ -3278,24 +3279,24 @@ void Client::CalcItemScale() { bool changed = false; // MainAmmo excluded in helper function below - if (CalcItemScale(EQEmu::constants::EQUIPMENT_BEGIN, EQEmu::constants::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) + if (CalcItemScale(EQEmu::legacy::EQUIPMENT_BEGIN, EQEmu::legacy::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) changed = true; - if (CalcItemScale(EQEmu::constants::GENERAL_BEGIN, EQEmu::constants::GENERAL_END)) // original coding excluded MainCursor (< 30) + if (CalcItemScale(EQEmu::legacy::GENERAL_BEGIN, EQEmu::legacy::GENERAL_END)) // original coding excluded MainCursor (< 30) changed = true; // I excluded cursor bag slots here because cursor was excluded above..if this is incorrect, change 'slot_y' here to CURSOR_BAG_END // and 'slot_y' above to CURSOR from GENERAL_END above - or however it is supposed to be... - if (CalcItemScale(EQEmu::constants::GENERAL_BAGS_BEGIN, EQEmu::constants::GENERAL_BAGS_END)) // (< 341) + if (CalcItemScale(EQEmu::legacy::GENERAL_BAGS_BEGIN, EQEmu::legacy::GENERAL_BAGS_END)) // (< 341) changed = true; - if (CalcItemScale(EQEmu::constants::TRIBUTE_BEGIN, EQEmu::constants::TRIBUTE_END)) // (< 405) + if (CalcItemScale(EQEmu::legacy::TRIBUTE_BEGIN, EQEmu::legacy::TRIBUTE_END)) // (< 405) changed = true; //Power Source Slot if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - if(CalcItemScale(SlotPowerSource, SlotPowerSource)) + if (CalcItemScale(EQEmu::legacy::SlotPowerSource, EQEmu::legacy::SlotPowerSource)) changed = true; } @@ -3310,7 +3311,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { bool changed = false; uint32 i; for (i = slot_x; i <= slot_y; i++) { - if (i == SlotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot + if (i == EQEmu::legacy::SlotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot continue; ItemInst* inst = m_inv.GetItem(i); @@ -3320,7 +3321,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) - if (i >= EQEmu::constants::GENERAL_BAGS_BEGIN && i <= EQEmu::constants::GENERAL_BAGS_END) { + if (i >= EQEmu::legacy::GENERAL_BAGS_BEGIN && i <= EQEmu::legacy::GENERAL_BAGS_END) { ItemInst* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; @@ -3340,7 +3341,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { } //iterate all augments - for (int x = AUG_INDEX_BEGIN; x < EQEmu::constants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) { ItemInst * a_inst = inst->GetAugment(x); if(!a_inst) @@ -3372,24 +3373,24 @@ void Client::DoItemEnterZone() { bool changed = false; // MainAmmo excluded in helper function below - if (DoItemEnterZone(EQEmu::constants::EQUIPMENT_BEGIN, EQEmu::constants::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) + if (DoItemEnterZone(EQEmu::legacy::EQUIPMENT_BEGIN, EQEmu::legacy::EQUIPMENT_END)) // original coding excluded MainAmmo (< 21) changed = true; - if (DoItemEnterZone(EQEmu::constants::GENERAL_BEGIN, EQEmu::constants::GENERAL_END)) // original coding excluded MainCursor (< 30) + if (DoItemEnterZone(EQEmu::legacy::GENERAL_BEGIN, EQEmu::legacy::GENERAL_END)) // original coding excluded MainCursor (< 30) changed = true; // I excluded cursor bag slots here because cursor was excluded above..if this is incorrect, change 'slot_y' here to CURSOR_BAG_END // and 'slot_y' above to CURSOR from GENERAL_END above - or however it is supposed to be... - if (DoItemEnterZone(EQEmu::constants::GENERAL_BAGS_BEGIN, EQEmu::constants::GENERAL_BAGS_END)) // (< 341) + if (DoItemEnterZone(EQEmu::legacy::GENERAL_BAGS_BEGIN, EQEmu::legacy::GENERAL_BAGS_END)) // (< 341) changed = true; - if (DoItemEnterZone(EQEmu::constants::TRIBUTE_BEGIN, EQEmu::constants::TRIBUTE_END)) // (< 405) + if (DoItemEnterZone(EQEmu::legacy::TRIBUTE_BEGIN, EQEmu::legacy::TRIBUTE_END)) // (< 405) changed = true; //Power Source Slot if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - if(DoItemEnterZone(SlotPowerSource, SlotPowerSource)) + if (DoItemEnterZone(EQEmu::legacy::SlotPowerSource, EQEmu::legacy::SlotPowerSource)) changed = true; } @@ -3403,7 +3404,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { // behavior change: 'slot_y' is now [RANGE]_END and not [RANGE]_END + 1 bool changed = false; for(uint32 i = slot_x; i <= slot_y; i++) { - if (i == SlotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot + if (i == EQEmu::legacy::SlotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot continue; ItemInst* inst = m_inv.GetItem(i); @@ -3413,7 +3414,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) - if (i >= EQEmu::constants::GENERAL_BAGS_BEGIN && i <= EQEmu::constants::GENERAL_BAGS_END) { + if (i >= EQEmu::legacy::GENERAL_BAGS_BEGIN && i <= EQEmu::legacy::GENERAL_BAGS_END) { ItemInst* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; @@ -3425,7 +3426,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { uint16 oldexp = inst->GetExp(); parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); - if(i <= SlotAmmo || i == SlotPowerSource) { + if (i <= EQEmu::legacy::SlotAmmo || i == EQEmu::legacy::SlotPowerSource) { parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); } @@ -3435,7 +3436,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { update_slot = true; } } else { - if(i <= SlotAmmo || i == SlotPowerSource) { + if (i <= EQEmu::legacy::SlotAmmo || i == EQEmu::legacy::SlotPowerSource) { parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); } @@ -3443,7 +3444,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { } //iterate all augments - for (int x = AUG_INDEX_BEGIN; x < EQEmu::constants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) { ItemInst *a_inst = inst->GetAugment(x); if(!a_inst) diff --git a/zone/bot.cpp b/zone/bot.cpp index 7494dd185..862054037 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -229,8 +229,8 @@ void Bot::SetBotSpellID(uint32 newSpellID) { } uint32 Bot::GetBotArcheryRange() { - const ItemInst *range_inst = GetBotItem(SlotRange); - const ItemInst *ammo_inst = GetBotItem(SlotAmmo); + const ItemInst *range_inst = GetBotItem(EQEmu::legacy::SlotRange); + const ItemInst *ammo_inst = GetBotItem(EQEmu::legacy::SlotAmmo); if (!range_inst || !ammo_inst) return 0; @@ -246,15 +246,15 @@ uint32 Bot::GetBotArcheryRange() { void Bot::ChangeBotArcherWeapons(bool isArcher) { if((GetClass()==WARRIOR) || (GetClass()==PALADIN) || (GetClass()==RANGER) || (GetClass()==SHADOWKNIGHT) || (GetClass()==ROGUE)) { if(!isArcher) { - BotAddEquipItem(SlotPrimary, GetBotItemBySlot(SlotPrimary)); - BotAddEquipItem(SlotSecondary, GetBotItemBySlot(SlotSecondary)); + BotAddEquipItem(EQEmu::legacy::SlotPrimary, GetBotItemBySlot(EQEmu::legacy::SlotPrimary)); + BotAddEquipItem(EQEmu::legacy::SlotSecondary, GetBotItemBySlot(EQEmu::legacy::SlotSecondary)); SetAttackTimer(); BotGroupSay(this, "My blade is ready"); } else { - BotRemoveEquipItem(SlotPrimary); - BotRemoveEquipItem(SlotSecondary); - BotAddEquipItem(SlotAmmo, GetBotItemBySlot(SlotAmmo)); - BotAddEquipItem(SlotSecondary, GetBotItemBySlot(SlotRange)); + BotRemoveEquipItem(EQEmu::legacy::SlotPrimary); + BotRemoveEquipItem(EQEmu::legacy::SlotSecondary); + BotAddEquipItem(EQEmu::legacy::SlotAmmo, GetBotItemBySlot(EQEmu::legacy::SlotAmmo)); + BotAddEquipItem(EQEmu::legacy::SlotSecondary, GetBotItemBySlot(EQEmu::legacy::SlotRange)); SetAttackTimer(); BotGroupSay(this, "My bow is true and ready"); } @@ -1175,11 +1175,11 @@ void Bot::GenerateArmorClass() { uint16 Bot::GetPrimarySkillValue() { SkillUseTypes skill = HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill - bool equiped = m_inv.GetItem(SlotPrimary); + bool equiped = m_inv.GetItem(EQEmu::legacy::SlotPrimary); if(!equiped) skill = SkillHandtoHand; else { - uint8 type = m_inv.GetItem(SlotPrimary)->GetItem()->ItemType; //is this the best way to do this? + uint8 type = m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType; //is this the best way to do this? switch(type) { case ItemType1HSlash: { skill = Skill1HSlashing; @@ -1722,8 +1722,8 @@ bool Bot::LoadPet() if (!botdb.LoadPetBuffs(GetBotID(), pet_buffs)) bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetBuffs(), GetCleanName()); - uint32 pet_items[EQEmu::constants::EQUIPMENT_SIZE]; - memset(pet_items, 0, (sizeof(uint32) * EQEmu::constants::EQUIPMENT_SIZE)); + uint32 pet_items[EQEmu::legacy::EQUIPMENT_SIZE]; + memset(pet_items, 0, (sizeof(uint32) * EQEmu::legacy::EQUIPMENT_SIZE)); if (!botdb.LoadPetItems(GetBotID(), pet_items)) bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetItems(), GetCleanName()); @@ -1750,11 +1750,11 @@ bool Bot::SavePet() char* pet_name = new char[64]; SpellBuff_Struct pet_buffs[BUFF_COUNT]; - uint32 pet_items[EQEmu::constants::EQUIPMENT_SIZE]; + uint32 pet_items[EQEmu::legacy::EQUIPMENT_SIZE]; memset(pet_name, 0, 64); memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * BUFF_COUNT)); - memset(pet_items, 0, (sizeof(uint32) * EQEmu::constants::EQUIPMENT_SIZE)); + memset(pet_items, 0, (sizeof(uint32) * EQEmu::legacy::EQUIPMENT_SIZE)); pet_inst->GetPetState(pet_buffs, pet_items, pet_name); @@ -1906,12 +1906,12 @@ void Bot::BotRangedAttack(Mob* other) { return; } - ItemInst* rangedItem = GetBotItem(SlotRange); + ItemInst* rangedItem = GetBotItem(EQEmu::legacy::SlotRange); const Item_Struct* RangeWeapon = 0; if(rangedItem) RangeWeapon = rangedItem->GetItem(); - ItemInst* ammoItem = GetBotItem(SlotAmmo); + ItemInst* ammoItem = GetBotItem(EQEmu::legacy::SlotAmmo); const Item_Struct* Ammo = 0; if(ammoItem) Ammo = ammoItem->GetItem(); @@ -2008,7 +2008,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes int damage = 0; uint32 hate = 0; - int Hand = SlotPrimary; + int Hand = EQEmu::legacy::SlotPrimary; if (hate == 0 && weapon_damage > 1) hate = weapon_damage; @@ -2037,7 +2037,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes else damage = zone->random.Int(min_hit, max_hit); - if (other->AvoidDamage(this, damage, CanRiposte ? SlotRange : SlotPrimary)) { // MainRange excludes ripo, primary doesn't have any extra behavior + if (other->AvoidDamage(this, damage, CanRiposte ? EQEmu::legacy::SlotRange : EQEmu::legacy::SlotPrimary)) { // MainRange excludes ripo, primary doesn't have any extra behavior if (damage == -3) { DoRiposte(other); if (HasDied()) @@ -2062,7 +2062,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes damage = -5; if(skillinuse == SkillBash){ - const ItemInst* inst = GetBotItem(SlotSecondary); + const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -2109,19 +2109,19 @@ void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) case SkillFlyingKick: case SkillRoundKick: case SkillKick: - item_slot = SlotFeet; + item_slot = EQEmu::legacy::SlotFeet; break; case SkillBash: - item_slot = SlotSecondary; + item_slot = EQEmu::legacy::SlotSecondary; break; case SkillDragonPunch: case SkillEagleStrike: case SkillTigerClaw: - item_slot = SlotHands; + item_slot = EQEmu::legacy::SlotHands; break; } - if (item_slot >= EQEmu::constants::EQUIPMENT_BEGIN){ + if (item_slot >= EQEmu::legacy::EQUIPMENT_BEGIN){ const ItemInst* inst = GetBotItem(item_slot); const Item_Struct* botweapon = 0; if(inst) @@ -2455,23 +2455,23 @@ void Bot::AI_Process() { // First, special attack per class (kick, backstab etc..) DoClassAttacks(GetTarget()); if(attack_timer.Check()) { - Attack(GetTarget(), SlotPrimary); - TriggerDefensiveProcs(GetTarget(), SlotPrimary, false); - ItemInst *wpn = GetBotItem(SlotPrimary); - TryWeaponProc(wpn, GetTarget(), SlotPrimary); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary); + TriggerDefensiveProcs(GetTarget(), EQEmu::legacy::SlotPrimary, false); + ItemInst *wpn = GetBotItem(EQEmu::legacy::SlotPrimary); + TryWeaponProc(wpn, GetTarget(), EQEmu::legacy::SlotPrimary); bool tripleSuccess = false; if(BotOwner && GetTarget() && CanThisClassDoubleAttack()) { if(BotOwner && CheckBotDoubleAttack()) - Attack(GetTarget(), SlotPrimary, true); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_TRIPLE) && CheckBotDoubleAttack(true)) { tripleSuccess = true; - Attack(GetTarget(), SlotPrimary, true); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); } //quad attack, does this belong here?? if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) - Attack(GetTarget(), SlotPrimary, true); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); } //Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). @@ -2479,18 +2479,18 @@ void Bot::AI_Process() { if (GetTarget() && flurrychance) { if(zone->random.Int(0, 100) < flurrychance) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); - Attack(GetTarget(), SlotPrimary, false); - Attack(GetTarget(), SlotPrimary, false); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); } } int32 ExtraAttackChanceBonus = (spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance); if (GetTarget() && ExtraAttackChanceBonus) { - ItemInst *wpn = GetBotItem(SlotPrimary); + ItemInst *wpn = GetBotItem(EQEmu::legacy::SlotPrimary); if(wpn) { if(wpn->GetItem()->ItemType == ItemType2HSlash || wpn->GetItem()->ItemType == ItemType2HBlunt || wpn->GetItem()->ItemType == ItemType2HPiercing) { if(zone->random.Int(0, 100) < ExtraAttackChanceBonus) - Attack(GetTarget(), SlotPrimary, false); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); } } } @@ -2510,7 +2510,7 @@ void Bot::AI_Process() { //now off hand if(GetTarget() && attack_dw_timer.Check() && CanThisClassDualWield()) { - const ItemInst* instweapon = GetBotItem(SlotSecondary); + const ItemInst* instweapon = GetBotItem(EQEmu::legacy::SlotSecondary); const Item_Struct* weapon = 0; //can only dual wield without a weapon if you're a monk if(instweapon || (botClass == MONK)) { @@ -2532,12 +2532,12 @@ void Bot::AI_Process() { DualWieldProbability += (DualWieldProbability * float(DWBonus) / 100.0f); float random = zone->random.Real(0, 1); if (random < DualWieldProbability){ // Max 78% of DW - Attack(GetTarget(), SlotSecondary); // Single attack with offhand - ItemInst *wpn = GetBotItem(SlotSecondary); - TryWeaponProc(wpn, GetTarget(), SlotSecondary); + Attack(GetTarget(), EQEmu::legacy::SlotSecondary); // Single attack with offhand + ItemInst *wpn = GetBotItem(EQEmu::legacy::SlotSecondary); + TryWeaponProc(wpn, GetTarget(), EQEmu::legacy::SlotSecondary); if( CanThisClassDoubleAttack() && CheckBotDoubleAttack()) { if(GetTarget() && GetTarget()->GetHP() > -10) - Attack(GetTarget(), SlotSecondary); // Single attack with offhand + Attack(GetTarget(), EQEmu::legacy::SlotSecondary); // Single attack with offhand } } } @@ -2708,12 +2708,12 @@ void Bot::PetAIProcess() { if(!botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY()) && botPet->GetTarget()->IsEnraged()) return; - if(botPet->Attack(GetTarget(), SlotPrimary)) // try the main hand + if (botPet->Attack(GetTarget(), EQEmu::legacy::SlotPrimary)) // try the main hand if (botPet->GetTarget()) { // We're a pet so we re able to dual attack int32 RandRoll = zone->random.Int(0, 99); if (botPet->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier))) { - if(botPet->Attack(botPet->GetTarget(), SlotPrimary)) {} + if (botPet->Attack(botPet->GetTarget(), EQEmu::legacy::SlotPrimary)) {} } } @@ -2751,11 +2751,11 @@ void Bot::PetAIProcess() { float DualWieldProbability = ((botPet->GetSkill(SkillDualWield) + botPet->GetLevel()) / 400.0f); DualWieldProbability -= zone->random.Real(0, 1); if(DualWieldProbability < 0) { - botPet->Attack(botPet->GetTarget(), SlotSecondary); + botPet->Attack(botPet->GetTarget(), EQEmu::legacy::SlotSecondary); if (botPet->CanThisClassDoubleAttack()) { int32 RandRoll = zone->random.Int(0, 99); if (RandRoll < (botPet->GetLevel() + 20)) - botPet->Attack(botPet->GetTarget(), SlotSecondary); + botPet->Attack(botPet->GetTarget(), EQEmu::legacy::SlotSecondary); } } } @@ -2878,7 +2878,7 @@ void Bot::Spawn(Client* botCharacterOwner) { // I re-enabled this until I can sort it out uint32 itemID = 0; uint8 materialFromSlot = 0xFF; - for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; ++i) { + for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { itemID = GetBotItemBySlot(i); if(itemID != 0) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); @@ -2962,7 +2962,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { const ItemInst* inst = 0; uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); - for (int i = 0; i < MaterialPrimary; i++) { + for (int i = 0; i < EQEmu::legacy::MaterialPrimary; i++) { inst = GetBotItem(i); if (inst) { item = inst->GetItem(); @@ -2981,25 +2981,25 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { } } - inst = GetBotItem(SlotPrimary); + inst = GetBotItem(EQEmu::legacy::SlotPrimary); if(inst) { item = inst->GetItem(); if(item) { if(strlen(item->IDFile) > 2) - ns->spawn.equipment[MaterialPrimary].Material = atoi(&item->IDFile[2]); + ns->spawn.equipment[EQEmu::legacy::MaterialPrimary].Material = atoi(&item->IDFile[2]); - ns->spawn.colors[MaterialPrimary].Color = GetEquipmentColor(MaterialPrimary); + ns->spawn.colors[EQEmu::legacy::MaterialPrimary].Color = GetEquipmentColor(EQEmu::legacy::MaterialPrimary); } } - inst = GetBotItem(SlotSecondary); + inst = GetBotItem(EQEmu::legacy::SlotSecondary); if(inst) { item = inst->GetItem(); if(item) { if(strlen(item->IDFile) > 2) - ns->spawn.equipment[MaterialSecondary].Material = atoi(&item->IDFile[2]); + ns->spawn.equipment[EQEmu::legacy::MaterialSecondary].Material = atoi(&item->IDFile[2]); - ns->spawn.colors[MaterialSecondary].Color = GetEquipmentColor(MaterialSecondary); + ns->spawn.colors[EQEmu::legacy::MaterialSecondary].Color = GetEquipmentColor(EQEmu::legacy::MaterialSecondary); } } } @@ -3243,7 +3243,7 @@ void Bot::BotAddEquipItem(int slot, uint32 id) { if(slot > 0 && id > 0) { uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); - if(materialFromSlot != MaterialInvalid) { + if (materialFromSlot != EQEmu::legacy::MaterialInvalid) { equipment[slot] = id; // npc has more than just material slots. Valid material should mean valid inventory index SendWearChange(materialFromSlot); } @@ -3259,11 +3259,11 @@ void Bot::BotRemoveEquipItem(int slot) { if(slot > 0) { uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); - if(materialFromSlot != MaterialInvalid) { + if (materialFromSlot != EQEmu::legacy::MaterialInvalid) { equipment[slot] = 0; // npc has more than just material slots. Valid material should mean valid inventory index SendWearChange(materialFromSlot); - if(materialFromSlot == MaterialChest) - SendWearChange(MaterialArms); + if (materialFromSlot == EQEmu::legacy::MaterialChest) + SendWearChange(EQEmu::legacy::MaterialArms); } UpdateEquipmentLight(); @@ -3361,12 +3361,12 @@ void Bot::FinishTrade(Client* client, BotTradeType tradeType) { if(tradeType == BotTradeClientNormal) { // Items being traded are found in the normal trade window used to trade between a Client and a Client or NPC // Items in this mode are found in slot ids 3000 thru 3003 - thought bots used the full 8-slot window..? - PerformTradeWithClient(EQEmu::constants::TRADE_BEGIN, EQEmu::constants::TRADE_END, client); // {3000..3007} + PerformTradeWithClient(EQEmu::legacy::TRADE_BEGIN, EQEmu::legacy::TRADE_END, client); // {3000..3007} } else if(tradeType == BotTradeClientNoDropNoTrade) { // Items being traded are found on the Client's cursor slot, slot id 30. This item can be either a single item or it can be a bag. // If it is a bag, then we have to search for items in slots 331 thru 340 - PerformTradeWithClient(SlotCursor, SlotCursor, client); + PerformTradeWithClient(EQEmu::legacy::SlotCursor, EQEmu::legacy::SlotCursor, client); // TODO: Add logic here to test if the item in SLOT_CURSOR is a container type, if it is then we need to call the following: // PerformTradeWithClient(331, 340, client); @@ -3378,7 +3378,7 @@ void Bot::FinishTrade(Client* client, BotTradeType tradeType) { void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client) { if(client) { // TODO: Figure out what the actual max slot id is - const int MAX_SLOT_ID = EQEmu::constants::TRADE_BAGS_END; // was the old incorrect 3179.. + const int MAX_SLOT_ID = EQEmu::legacy::TRADE_BAGS_END; // was the old incorrect 3179.. uint32 items[MAX_SLOT_ID] = {0}; uint8 charges[MAX_SLOT_ID] = {0}; bool botCanWear[MAX_SLOT_ID] = {0}; @@ -3395,7 +3395,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli charges[i] = inst->GetCharges(); } - if (i == SlotCursor) + if (i == EQEmu::legacy::SlotCursor) UpdateClient = true; //EQoffline: will give the items to the bots and change the bot stats @@ -3403,7 +3403,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli std::string TempErrorMessage; const Item_Struct* mWeaponItem = inst->GetItem(); bool failedLoreCheck = false; - for (int m = AUG_INDEX_BEGIN; m < EQEmu::constants::ITEM_COMMON_SIZE; ++m) { + for (int m = AUG_INDEX_BEGIN; m < EQEmu::legacy::ITEM_COMMON_SIZE; ++m) { ItemInst *itm = inst->GetAugment(m); if(itm) { @@ -3423,29 +3423,29 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli botCanWear[i] = BotCanWear; ItemInst* swap_item = nullptr; - const char* equipped[EQEmu::constants::EQUIPMENT_SIZE + 1] = { "Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", + const char* equipped[EQEmu::legacy::EQUIPMENT_SIZE + 1] = { "Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; bool success = false; int how_many_slots = 0; - for (int j = EQEmu::constants::EQUIPMENT_BEGIN; j <= (EQEmu::constants::EQUIPMENT_END + 1); ++j) { + for (int j = EQEmu::legacy::EQUIPMENT_BEGIN; j <= (EQEmu::legacy::EQUIPMENT_END + 1); ++j) { if((mWeaponItem->Slots & (1 << j))) { if (j == 22) j = 9999; how_many_slots++; if(!GetBotItem(j)) { - if(j == SlotPrimary) { + if (j == EQEmu::legacy::SlotPrimary) { if((mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) { - if(GetBotItem(SlotSecondary)) { + if (GetBotItem(EQEmu::legacy::SlotSecondary)) { if(mWeaponItem && (mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) { - if(client->CheckLoreConflict(GetBotItem(SlotSecondary)->GetItem())) { + if (client->CheckLoreConflict(GetBotItem(EQEmu::legacy::SlotSecondary)->GetItem())) { failedLoreCheck = true; } } else { - ItemInst* remove_item = GetBotItem(SlotSecondary); - BotTradeSwapItem(client, SlotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + ItemInst* remove_item = GetBotItem(EQEmu::legacy::SlotSecondary); + BotTradeSwapItem(client, EQEmu::legacy::SlotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } } @@ -3455,7 +3455,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } break; } - else if(j == SlotSecondary) { + else if (j == EQEmu::legacy::SlotSecondary) { if(inst->IsWeapon()) { if(CanThisClassDualWield()) { BotTradeAddItem(mWeaponItem->ID, inst, inst->GetCharges(), mWeaponItem->Slots, j, &TempErrorMessage); @@ -3471,10 +3471,10 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli success = true; } if(success) { - if(GetBotItem(SlotPrimary)) { - ItemInst* remove_item = GetBotItem(SlotPrimary); + if (GetBotItem(EQEmu::legacy::SlotPrimary)) { + ItemInst* remove_item = GetBotItem(EQEmu::legacy::SlotPrimary); if((remove_item->GetItem()->ItemType == ItemType2HSlash) || (remove_item->GetItem()->ItemType == ItemType2HBlunt) || (remove_item->GetItem()->ItemType == ItemType2HPiercing)) { - BotTradeSwapItem(client, SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + BotTradeSwapItem(client, EQEmu::legacy::SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } break; @@ -3489,14 +3489,14 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } if(!success) { - for (int j = EQEmu::constants::EQUIPMENT_BEGIN; j <= (EQEmu::constants::EQUIPMENT_END + 1); ++j) { + for (int j = EQEmu::legacy::EQUIPMENT_BEGIN; j <= (EQEmu::legacy::EQUIPMENT_END + 1); ++j) { if((mWeaponItem->Slots & (1 << j))) { if (j == 22) j = 9999; swap_item = GetBotItem(j); failedLoreCheck = false; - for (int k = AUG_INDEX_BEGIN; k < EQEmu::constants::ITEM_COMMON_SIZE; ++k) { + for (int k = AUG_INDEX_BEGIN; k < EQEmu::legacy::ITEM_COMMON_SIZE; ++k) { ItemInst *itm = swap_item->GetAugment(k); if(itm) { @@ -3509,28 +3509,28 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli failedLoreCheck = true; } if(!failedLoreCheck) { - if(j == SlotPrimary) { + if (j == EQEmu::legacy::SlotPrimary) { if((mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) { - if(GetBotItem(SlotSecondary)) { - if(client->CheckLoreConflict(GetBotItem(SlotSecondary)->GetItem())) { + if (GetBotItem(EQEmu::legacy::SlotSecondary)) { + if (client->CheckLoreConflict(GetBotItem(EQEmu::legacy::SlotSecondary)->GetItem())) { failedLoreCheck = true; } else { - ItemInst* remove_item = GetBotItem(SlotSecondary); - BotTradeSwapItem(client, SlotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + ItemInst* remove_item = GetBotItem(EQEmu::legacy::SlotSecondary); + BotTradeSwapItem(client, EQEmu::legacy::SlotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } } if(!failedLoreCheck) { - BotTradeSwapItem(client, SlotPrimary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); + BotTradeSwapItem(client, EQEmu::legacy::SlotPrimary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); success = true; } break; } - else if(j == SlotSecondary) { + else if (j == EQEmu::legacy::SlotSecondary) { if(inst->IsWeapon()) { if(CanThisClassDualWield()) { - BotTradeSwapItem(client, SlotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); + BotTradeSwapItem(client, EQEmu::legacy::SlotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); success = true; } else { @@ -3539,13 +3539,13 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } else { - BotTradeSwapItem(client, SlotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); + BotTradeSwapItem(client, EQEmu::legacy::SlotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); success = true; } - if(success && GetBotItem(SlotPrimary)) { - ItemInst* remove_item = GetBotItem(SlotPrimary); + if (success && GetBotItem(EQEmu::legacy::SlotPrimary)) { + ItemInst* remove_item = GetBotItem(EQEmu::legacy::SlotPrimary); if((remove_item->GetItem()->ItemType == ItemType2HSlash) || (remove_item->GetItem()->ItemType == ItemType2HBlunt) || (remove_item->GetItem()->ItemType == ItemType2HPiercing)) { - BotTradeSwapItem(client, SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + BotTradeSwapItem(client, EQEmu::legacy::SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } break; @@ -3745,13 +3745,13 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b FaceTarget(GetTarget()); ItemInst* weapon = nullptr; - if(Hand == SlotPrimary) { - weapon = GetBotItem(SlotPrimary); + if (Hand == EQEmu::legacy::SlotPrimary) { + weapon = GetBotItem(EQEmu::legacy::SlotPrimary); OffHandAtk(false); } - if(Hand == SlotSecondary) { - weapon = GetBotItem(SlotSecondary); + if (Hand == EQEmu::legacy::SlotSecondary) { + weapon = GetBotItem(EQEmu::legacy::SlotSecondary); OffHandAtk(true); } @@ -3816,7 +3816,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b // This is not recommended for normal usage, as the damage bonus represents a non-trivial component of the DPS output // of weapons wielded by higher-level melee characters (especially for two-handed weapons). int ucDamageBonus = 0; - if(Hand == SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { + if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr); @@ -3826,7 +3826,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b } #endif //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. - if (Hand == SlotSecondary) { + if (Hand == EQEmu::legacy::SlotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr); min_hit += (int) ucDamageBonus; @@ -4294,7 +4294,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { int32 focus_max = 0; int32 focus_max_real = 0; //item focus - for (int x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::EQUIPMENT_END; x++) { + for (int x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::EQUIPMENT_END; x++) { TempItem = nullptr; ItemInst* ins = GetBotItem(x); if (!ins) @@ -4319,7 +4319,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { } } - for (int y = AUG_INDEX_BEGIN; y < EQEmu::constants::ITEM_COMMON_SIZE; ++y) { + for (int y = AUG_INDEX_BEGIN; y < EQEmu::legacy::ITEM_COMMON_SIZE; ++y) { ItemInst *aug = nullptr; aug = ins->GetAugment(y); if(aug) { @@ -4755,15 +4755,15 @@ float Bot::GetProcChances(float ProcBonus, uint16 hand) { float ProcChance = 0.0f; uint32 weapon_speed = 0; switch (hand) { - case SlotPrimary: - weapon_speed = attack_timer.GetDuration(); - break; - case SlotSecondary: - weapon_speed = attack_dw_timer.GetDuration(); - break; - case SlotRange: - weapon_speed = ranged_timer.GetDuration(); - break; + case EQEmu::legacy::SlotPrimary: + weapon_speed = attack_timer.GetDuration(); + break; + case EQEmu::legacy::SlotSecondary: + weapon_speed = attack_dw_timer.GetDuration(); + break; + case EQEmu::legacy::SlotRange: + weapon_speed = ranged_timer.GetDuration(); + break; } if (weapon_speed < RuleI(Combat, MinHastedDelay)) @@ -4787,7 +4787,7 @@ int Bot::GetHandToHandDamage(void) { // everyone uses this in the revamp! int skill = GetSkill(SkillHandtoHand); int epic = 0; - if (CastToNPC()->GetEquipment(MaterialHands) == 10652 && GetLevel() > 46) + if (CastToNPC()->GetEquipment(EQEmu::legacy::MaterialHands) == 10652 && GetLevel() > 46) epic = 280; if (epic > skill) skill = epic; @@ -4809,7 +4809,7 @@ int Bot::GetHandToHandDamage(void) { 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, // 31-40 10, 11, 11, 11, 11, 11, 11, 12, 12}; // 41-49 if (GetClass() == MONK) { - if (CastToNPC()->GetEquipment(MaterialHands) == 10652 && GetLevel() > 50) + if (CastToNPC()->GetEquipment(EQEmu::legacy::MaterialHands) == 10652 && GetLevel() > 50) return 9; if (level > 62) return 15; @@ -4848,11 +4848,11 @@ void Bot::DoRiposte(Mob* defender) { if (!defender) return; - defender->Attack(this, SlotPrimary, true); + defender->Attack(this, EQEmu::legacy::SlotPrimary, true); int32 DoubleRipChance = (defender->GetAABonuses().GiveDoubleRiposte[0] + defender->GetSpellBonuses().GiveDoubleRiposte[0] + defender->GetItemBonuses().GiveDoubleRiposte[0]); if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposte (%d percent chance)", DoubleRipChance); - defender->Attack(this, SlotPrimary, true); + defender->Attack(this, EQEmu::legacy::SlotPrimary, true); } DoubleRipChance = defender->GetAABonuses().GiveDoubleRiposte[1]; @@ -4870,7 +4870,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, hate = hate_override; if(skill == SkillBash) { - const ItemInst* inst = GetBotItem(SlotSecondary); + const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); const Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -4884,14 +4884,14 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, } min_damage += (min_damage * GetMeleeMinDamageMod_SE(skill) / 100); - int hand = SlotPrimary; + int hand = EQEmu::legacy::SlotPrimary; if (skill == SkillThrowing || skill == SkillArchery) - hand = SlotRange; + hand = EQEmu::legacy::SlotRange; if (who->AvoidDamage(this, max_damage, hand)) { if (max_damage == -3) DoRiposte(who); } else { - if (HitChance || who->CheckHitChance(this, skill, SlotPrimary)) { + if (HitChance || who->CheckHitChance(this, skill, EQEmu::legacy::SlotPrimary)) { who->MeleeMitigation(this, max_damage, min_damage); ApplyMeleeDamageBonus(skill, max_damage); max_damage += who->GetFcDamageAmtIncoming(this, 0, true, skill); @@ -4935,7 +4935,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { bool bIsBehind = false; bool bCanFrontalBS = false; - const ItemInst* inst = GetBotItem(SlotPrimary); + const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotPrimary); const Item_Struct* botpiercer = nullptr; if(inst) botpiercer = inst->GetItem(); @@ -4985,7 +4985,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { } } else - Attack(other, SlotPrimary); + Attack(other, EQEmu::legacy::SlotPrimary); } void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { @@ -4995,11 +4995,11 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { int32 hate = 0; int32 primaryweapondamage = 0; int32 backstab_dmg = 0; - ItemInst* botweaponInst = GetBotItem(SlotPrimary); + ItemInst* botweaponInst = GetBotItem(EQEmu::legacy::SlotPrimary); if(botweaponInst) { primaryweapondamage = GetWeaponDamage(other, botweaponInst); backstab_dmg = botweaponInst->GetItem()->BackstabDmg; - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { ItemInst *aug = botweaponInst->GetAugment(i); if(aug) backstab_dmg += aug->GetItem()->BackstabDmg; @@ -5043,7 +5043,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { } void Bot::RogueAssassinate(Mob* other) { - ItemInst* botweaponInst = GetBotItem(SlotPrimary); + ItemInst* botweaponInst = GetBotItem(EQEmu::legacy::SlotPrimary); if(botweaponInst) { if(GetWeaponDamage(other, botweaponInst)) other->Damage(this, 32000, SPELL_UNKNOWN, SkillBackstab); @@ -5109,7 +5109,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { case WARRIOR: if(level >= RuleI(Combat, NPCBashKickLevel)){ bool canBash = false; - if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(SlotSecondary) && m_inv.GetItem(SlotSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(SlotPrimary) && (m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) + if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQEmu::legacy::SlotSecondary) && m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(EQEmu::legacy::SlotPrimary) && (m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) canBash = true; if(!canBash || zone->random.Int(0, 100) > 25) @@ -5128,7 +5128,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { case SHADOWKNIGHT: case PALADIN: if(level >= RuleI(Combat, NPCBashKickLevel)){ - if((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(SlotSecondary) && m_inv.GetItem(SlotSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(SlotPrimary) && (m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(SlotPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) + if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQEmu::legacy::SlotSecondary) && m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(EQEmu::legacy::SlotPrimary) && (m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) skill_to_use = SkillBash; } break; @@ -5157,7 +5157,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if(skill_to_use == SkillBash) { if (target != this) { DoAnim(animTailRake); - if(GetWeaponDamage(target, GetBotItem(SlotSecondary)) <= 0 && GetWeaponDamage(target, GetBotItem(SlotShoulders)) <= 0) + if (GetWeaponDamage(target, GetBotItem(EQEmu::legacy::SlotSecondary)) <= 0 && GetWeaponDamage(target, GetBotItem(EQEmu::legacy::SlotShoulders)) <= 0) dmg = -5; else { if(!target->CheckHitChance(this, SkillBash, 0)) @@ -5207,7 +5207,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if(skill_to_use == SkillKick) { if(target != this) { DoAnim(animKick); - if(GetWeaponDamage(target, GetBotItem(SlotFeet)) <= 0) + if (GetWeaponDamage(target, GetBotItem(EQEmu::legacy::SlotFeet)) <= 0) dmg = -5; else { if(!target->CheckHitChance(this, SkillKick, 0)) @@ -5374,7 +5374,7 @@ void Bot::EquipBot(std::string* errorMessage) { GetBotItems(m_inv, errorMessage); const ItemInst* inst = 0; const Item_Struct* item = 0; - for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; ++i) { + for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { item = inst->GetItem(); @@ -5501,12 +5501,12 @@ void Bot::SetAttackTimer() { attack_timer.SetAtTrigger(4000, true); Timer* TimerToUse = nullptr; const Item_Struct* PrimaryWeapon = nullptr; - for (int i = SlotRange; i <= SlotSecondary; i++) { - if (i == SlotPrimary) + for (int i = EQEmu::legacy::SlotRange; i <= EQEmu::legacy::SlotSecondary; i++) { + if (i == EQEmu::legacy::SlotPrimary) TimerToUse = &attack_timer; - else if (i == SlotRange) + else if (i == EQEmu::legacy::SlotRange) TimerToUse = &ranged_timer; - else if (i == SlotSecondary) + else if (i == EQEmu::legacy::SlotSecondary) TimerToUse = &attack_dw_timer; else continue; @@ -5516,7 +5516,7 @@ void Bot::SetAttackTimer() { if (ci) ItemToUse = ci->GetItem(); - if (i == SlotSecondary) { + if (i == EQEmu::legacy::SlotSecondary) { if (PrimaryWeapon != nullptr) { if (PrimaryWeapon->ItemClass == ItemClassCommon && (PrimaryWeapon->ItemType == ItemType2HSlash || PrimaryWeapon->ItemType == ItemType2HBlunt || PrimaryWeapon->ItemType == ItemType2HPiercing)) { attack_dw_timer.Disable(); @@ -5547,7 +5547,7 @@ void Bot::SetAttackTimer() { speed = (RuleB(Spells, Jun182014HundredHandsRevamp) ? static_cast(((delay / haste_mod) + ((hhe / 1000.0f) * (delay / haste_mod))) * 100) : static_cast(((delay / haste_mod) + ((hhe / 100.0f) * delay)) * 100)); TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true); - if(i == SlotPrimary) + if (i == EQEmu::legacy::SlotPrimary) PrimaryWeapon = ItemToUse; } } @@ -7192,7 +7192,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { // Modded to display power source items (will only show up on SoF+ client inspect windows though.) // I don't think bots are currently coded to use them..but, you'll have to use '#bot inventory list' // to see them on a Titanium client when/if they are activated. - for (int16 L = EQEmu::constants::EQUIPMENT_BEGIN; L <= SlotWaist; L++) { + for (int16 L = EQEmu::legacy::EQUIPMENT_BEGIN; L <= EQEmu::legacy::SlotWaist; L++) { inst = inspectedBot->GetBotItem(L); if(inst) { @@ -7206,7 +7206,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { } } - inst = inspectedBot->GetBotItem(SlotPowerSource); + inst = inspectedBot->GetBotItem(EQEmu::legacy::SlotPowerSource); if(inst) { item = inst->GetItem(); @@ -7218,7 +7218,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { insr->itemicons[SoF::inventory::SlotPowerSource] = 0xFFFFFFFF; } - inst = inspectedBot->GetBotItem(SlotAmmo); + inst = inspectedBot->GetBotItem(EQEmu::legacy::SlotAmmo); if(inst) { item = inst->GetItem(); @@ -7240,7 +7240,7 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) { const Item_Struct* itemtmp = 0; - for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= (EQEmu::constants::EQUIPMENT_END + 1); ++i) { + for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { const ItemInst* item = GetBotItem((i == 22 ? 9999 : i)); if(item) { AddItemBonuses(item, newbon); @@ -7553,7 +7553,7 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, if (!isAug) { - for (int i = 0; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) + for (int i = 0; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) AddItemBonuses(inst->GetAugment(i),newbon,true, false, rec_level); } @@ -8042,12 +8042,12 @@ uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { int Bot::GetRawACNoShield(int &shield_ac) { int ac = itembonuses.AC + spellbonuses.AC; shield_ac = 0; - ItemInst* inst = GetBotItem(SlotSecondary); + ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); if(inst) { if(inst->GetItem()->ItemType == ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; - for (uint8 i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { + for (uint8 i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { if(inst->GetAugment(i)) { ac -= inst->GetAugment(i)->GetItem()->AC; shield_ac += inst->GetAugment(i)->GetItem()->AC; @@ -8062,7 +8062,7 @@ uint32 Bot::CalcCurrentWeight() { const Item_Struct* TempItem = 0; ItemInst* inst; uint32 Total = 0; - for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; ++i) { + for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { TempItem = inst->GetItem(); @@ -8421,7 +8421,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) if (slot_id != INVALID_INDEX) return false; - for (uint8 i = 0; i < MaterialPrimary; ++i) { + for (uint8 i = 0; i < EQEmu::legacy::MaterialPrimary; ++i) { uint8 inv_slot = Inventory::CalcSlotFromMaterial(i); ItemInst* inst = m_inv.GetItem(inv_slot); if (!inst) @@ -8433,7 +8433,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) } else { uint8 mat_slot = Inventory::CalcMaterialFromSlot(slot_id); - if (mat_slot == MaterialInvalid || mat_slot >= MaterialPrimary) + if (mat_slot == EQEmu::legacy::MaterialInvalid || mat_slot >= EQEmu::legacy::MaterialPrimary) return false; ItemInst* inst = m_inv.GetItem(slot_id); diff --git a/zone/bot.h b/zone/bot.h index a64b44a5e..9cb0b4766 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -77,9 +77,9 @@ static const std::string bot_stance_name[BOT_STANCE_COUNT] = { static const char* GetBotStanceName(int stance_id) { return bot_stance_name[VALIDBOTSTANCE(stance_id)].c_str(); } -#define VALIDBOTEQUIPSLOT(x) ((x >= EQEmu::constants::EQUIPMENT_BEGIN && x <= EQEmu::constants::EQUIPMENT_END) ? (x) : ((x == SlotPowerSource) ? (22) : (23))) +#define VALIDBOTEQUIPSLOT(x) ((x >= EQEmu::legacy::EQUIPMENT_BEGIN && x <= EQEmu::legacy::EQUIPMENT_END) ? (x) : ((x == EQEmu::legacy::SlotPowerSource) ? (22) : (23))) -static std::string bot_equip_slot_name[EQEmu::constants::EQUIPMENT_SIZE + 2] = +static std::string bot_equip_slot_name[EQEmu::legacy::EQUIPMENT_SIZE + 2] = { "Charm", // MainCharm "Left Ear", // MainEar1 @@ -207,7 +207,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 138a7aa02..2fa020635 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -2400,7 +2400,7 @@ namespace ActionableBots continue; mod_skill_value = base_skill_value; - for (int16 index = EQEmu::constants::EQUIPMENT_BEGIN; index <= EQEmu::constants::EQUIPMENT_END; ++index) { + for (int16 index = EQEmu::legacy::EQUIPMENT_BEGIN; index <= EQEmu::legacy::EQUIPMENT_END; ++index) { const ItemInst* indexed_item = bot_iter->GetBotItem(index); if (indexed_item && indexed_item->GetItem()->SkillModType == skill_type) mod_skill_value += (base_skill_value * (((float)indexed_item->GetItem()->SkillModValue) / 100.0f)); @@ -4357,7 +4357,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) // TODO: Trouble-shoot model update issue const std::string msg_matslot = StringFormat("mat_slot: %c(All), %i(Head), %i(Chest), %i(Arms), %i(Wrists), %i(Hands), %i(Legs), %i(Feet)", - '*', MaterialHead, MaterialChest, MaterialArms, MaterialWrist, MaterialHands, MaterialLegs, MaterialFeet); + '*', EQEmu::legacy::MaterialHead, EQEmu::legacy::MaterialChest, EQEmu::legacy::MaterialArms, EQEmu::legacy::MaterialWrist, EQEmu::legacy::MaterialHands, EQEmu::legacy::MaterialLegs, EQEmu::legacy::MaterialFeet); if (helper_command_alias_fail(c, "bot_subcommand_bot_dye_armor", sep->arg[0], "botdyearmor")) return; @@ -4368,7 +4368,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) } const int ab_mask = ActionableBots::ABM_NoFilter; - uint8 material_slot = MaterialInvalid; + uint8 material_slot = EQEmu::legacy::MaterialInvalid; int16 slot_id = INVALID_INDEX; bool dye_all = (sep->arg[1][0] == '*'); @@ -4376,7 +4376,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) material_slot = atoi(sep->arg[1]); slot_id = Inventory::CalcSlotFromMaterial(material_slot); - if (!sep->IsNumber(1) || slot_id == INVALID_INDEX || material_slot > MaterialFeet) { + if (!sep->IsNumber(1) || slot_id == INVALID_INDEX || material_slot > EQEmu::legacy::MaterialFeet) { c->Message(m_fail, "Valid [mat_slot]s for this command are:"); c->Message(m_fail, msg_matslot.c_str()); return; @@ -7070,24 +7070,24 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) linker.SetLinkType(linker.SayLinkItemInst); uint32 inventory_count = 0; - for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= (EQEmu::constants::EQUIPMENT_END + 1); ++i) { - if ((i == SlotSecondary) && is2Hweapon) + for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { + if ((i == EQEmu::legacy::SlotSecondary) && is2Hweapon) continue; - inst = my_bot->CastToBot()->GetBotItem(i == 22 ? SlotPowerSource : i); + inst = my_bot->CastToBot()->GetBotItem(i == 22 ? EQEmu::legacy::SlotPowerSource : i); if (!inst || !inst->GetItem()) { - c->Message(m_message, "I need something for my %s (slot %i)", GetBotEquipSlotName(i), (i == 22 ? SlotPowerSource : i)); + c->Message(m_message, "I need something for my %s (slot %i)", GetBotEquipSlotName(i), (i == 22 ? EQEmu::legacy::SlotPowerSource : i)); continue; } item = inst->GetItem(); - if ((i == SlotPrimary) && ((item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HPiercing))) { + if ((i == EQEmu::legacy::SlotPrimary) && ((item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HPiercing))) { is2Hweapon = true; } linker.SetItemInst(inst); item_link = linker.GenerateLink(); - c->Message(m_message, "Using %s in my %s (slot %i)", item_link.c_str(), GetBotEquipSlotName(i), (i == 22 ? SlotPowerSource : i)); + c->Message(m_message, "Using %s in my %s (slot %i)", item_link.c_str(), GetBotEquipSlotName(i), (i == 22 ? EQEmu::legacy::SlotPowerSource : i)); ++inventory_count; } @@ -7126,7 +7126,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) } int slotId = atoi(sep->arg[1]); - if (!sep->IsNumber(1) || ((slotId > EQEmu::constants::EQUIPMENT_END || slotId < EQEmu::constants::EQUIPMENT_BEGIN) && slotId != SlotPowerSource)) { + if (!sep->IsNumber(1) || ((slotId > EQEmu::legacy::EQUIPMENT_END || slotId < EQEmu::legacy::EQUIPMENT_BEGIN) && slotId != EQEmu::legacy::SlotPowerSource)) { c->Message(m_fail, "Valid slots are 0-21 or 9999"); return; } @@ -7141,7 +7141,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) return; } - for (int m = AUG_INDEX_BEGIN; m < EQEmu::constants::ITEM_COMMON_SIZE; ++m) { + for (int m = AUG_INDEX_BEGIN; m < EQEmu::legacy::ITEM_COMMON_SIZE; ++m) { if (!itminst) break; @@ -7158,7 +7158,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) std::string error_message; if (itm) { c->PushItemOnCursor(*itminst, true); - if ((slotId == SlotRange) || (slotId == SlotAmmo) || (slotId == SlotPrimary) || (slotId == SlotSecondary)) + if ((slotId == EQEmu::legacy::SlotRange) || (slotId == EQEmu::legacy::SlotAmmo) || (slotId == EQEmu::legacy::SlotPrimary) || (slotId == EQEmu::legacy::SlotSecondary)) my_bot->SetBotArcher(false); my_bot->RemoveBotItemBySlot(slotId, &error_message); @@ -7172,31 +7172,31 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) } switch (slotId) { - case SlotCharm: - case SlotEar1: - case SlotHead: - case SlotFace: - case SlotEar2: - case SlotNeck: - case SlotBack: - case SlotWrist1: - case SlotWrist2: - case SlotRange: - case SlotPrimary: - case SlotSecondary: - case SlotFinger1: - case SlotFinger2: - case SlotChest: - case SlotWaist: - case SlotPowerSource: - case SlotAmmo: + case EQEmu::legacy::SlotCharm: + case EQEmu::legacy::SlotEar1: + case EQEmu::legacy::SlotHead: + case EQEmu::legacy::SlotFace: + case EQEmu::legacy::SlotEar2: + case EQEmu::legacy::SlotNeck: + case EQEmu::legacy::SlotBack: + case EQEmu::legacy::SlotWrist1: + case EQEmu::legacy::SlotWrist2: + case EQEmu::legacy::SlotRange: + case EQEmu::legacy::SlotPrimary: + case EQEmu::legacy::SlotSecondary: + case EQEmu::legacy::SlotFinger1: + case EQEmu::legacy::SlotFinger2: + case EQEmu::legacy::SlotChest: + case EQEmu::legacy::SlotWaist: + case EQEmu::legacy::SlotPowerSource: + case EQEmu::legacy::SlotAmmo: c->Message(m_message, "My %s is %s unequipped", GetBotEquipSlotName(slotId), ((itm) ? ("now") : ("already"))); break; - case SlotShoulders: - case SlotArms: - case SlotHands: - case SlotLegs: - case SlotFeet: + case EQEmu::legacy::SlotShoulders: + case EQEmu::legacy::SlotArms: + case EQEmu::legacy::SlotHands: + case EQEmu::legacy::SlotLegs: + case EQEmu::legacy::SlotFeet: c->Message(m_message, "My %s are %s unequipped", GetBotEquipSlotName(slotId), ((itm) ? ("now") : ("already"))); break; default: @@ -7233,14 +7233,14 @@ void bot_subcommand_inventory_window(Client *c, const Seperator *sep) //Client::TextLink linker; //linker.SetLinkType(linker.linkItemInst); - for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= (EQEmu::constants::EQUIPMENT_END + 1); ++i) { + for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { const Item_Struct* item = nullptr; - const ItemInst* inst = my_bot->CastToBot()->GetBotItem(i == 22 ? SlotPowerSource : i); + const ItemInst* inst = my_bot->CastToBot()->GetBotItem(i == 22 ? EQEmu::legacy::SlotPowerSource : i); if (inst) item = inst->GetItem(); window_text.append(""); - window_text.append(GetBotEquipSlotName(i == 22 ? SlotPowerSource : i)); + window_text.append(GetBotEquipSlotName(i == 22 ? EQEmu::legacy::SlotPowerSource : i)); window_text.append(": "); if (item) { //window_text.append(""); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index fc98fd768..3f8a60c0d 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1058,7 +1058,7 @@ bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) for (auto row = results.begin(); row != results.end(); ++row) { int16 slot_id = atoi(row[0]); - if ((slot_id < EQEmu::constants::EQUIPMENT_BEGIN || slot_id > EQEmu::constants::EQUIPMENT_END) && slot_id != SlotPowerSource) + if ((slot_id < EQEmu::legacy::EQUIPMENT_BEGIN || slot_id > EQEmu::legacy::EQUIPMENT_END) && slot_id != EQEmu::legacy::SlotPowerSource) continue; uint32 item_id = atoi(row[1]); @@ -1091,7 +1091,7 @@ bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) if (item_inst->GetItem()->Attuneable) { if (atoi(row[4])) item_inst->SetAttuned(true); - else if (((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::constants::EQUIPMENT_END) || slot_id == SlotPowerSource)) + else if (((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::legacy::EQUIPMENT_END) || slot_id == EQEmu::legacy::SlotPowerSource)) item_inst->SetAttuned(true); } @@ -1159,7 +1159,7 @@ bool BotDatabase::LoadItemBySlot(Bot* bot_inst) bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint32& item_id) { - if (!bot_id || (slot_id > EQEmu::constants::EQUIPMENT_END && slot_id != SlotPowerSource)) + if (!bot_id || (slot_id > EQEmu::legacy::EQUIPMENT_END && slot_id != EQEmu::legacy::SlotPowerSource)) return false; query = StringFormat("SELECT `item_id` FROM `bot_inventories` WHERE `bot_id` = '%i' AND `slot_id` = '%i' LIMIT 1", bot_id, slot_id); @@ -1177,7 +1177,7 @@ bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const ItemInst* item_inst) { - if (!bot_inst || !bot_inst->GetBotID() || (slot_id > EQEmu::constants::EQUIPMENT_END && slot_id != SlotPowerSource)) + if (!bot_inst || !bot_inst->GetBotID() || (slot_id > EQEmu::legacy::EQUIPMENT_END && slot_id != EQEmu::legacy::SlotPowerSource)) return false; if (!DeleteItemBySlot(bot_inst->GetBotID(), slot_id)) @@ -1187,7 +1187,7 @@ bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const Item return true; uint32 augment_id[] = { 0, 0, 0, 0, 0, 0 }; - for (int augment_iter = 0; augment_iter < EQEmu::constants::ITEM_COMMON_SIZE; ++augment_iter) + for (int augment_iter = 0; augment_iter < EQEmu::legacy::ITEM_COMMON_SIZE; ++augment_iter) augment_id[augment_iter] = item_inst->GetAugmentItemID(augment_iter); query = StringFormat( @@ -1255,7 +1255,7 @@ bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const Item bool BotDatabase::DeleteItemBySlot(const uint32 bot_id, const uint32 slot_id) { - if (!bot_id || (slot_id > EQEmu::constants::EQUIPMENT_END && slot_id != SlotPowerSource)) + if (!bot_id || (slot_id > EQEmu::legacy::EQUIPMENT_END && slot_id != EQEmu::legacy::SlotPowerSource)) return false; query = StringFormat("DELETE FROM `bot_inventories` WHERE `bot_id` = '%u' AND `slot_id` = '%u'", bot_id, slot_id); @@ -1294,12 +1294,12 @@ bool BotDatabase::SaveEquipmentColor(const uint32 bot_id, const int16 slot_id, c return false; bool all_flag = (slot_id == -2); - if ((slot_id < EQEmu::constants::EQUIPMENT_BEGIN || slot_id > EQEmu::constants::EQUIPMENT_END) && slot_id != SlotPowerSource && !all_flag) + if ((slot_id < EQEmu::legacy::EQUIPMENT_BEGIN || slot_id > EQEmu::legacy::EQUIPMENT_END) && slot_id != EQEmu::legacy::SlotPowerSource && !all_flag) return false; std::string where_clause; if (all_flag) - where_clause = StringFormat(" AND `slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u')", SlotHead, SlotArms, SlotWrist1, SlotHands, SlotChest, SlotLegs, SlotFeet); + where_clause = StringFormat(" AND `slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u')", EQEmu::legacy::SlotHead, EQEmu::legacy::SlotArms, EQEmu::legacy::SlotWrist1, EQEmu::legacy::SlotHands, EQEmu::legacy::SlotChest, EQEmu::legacy::SlotLegs, EQEmu::legacy::SlotFeet); else where_clause = StringFormat(" AND `slot_id` = '%u'", slot_id); @@ -1571,7 +1571,7 @@ bool BotDatabase::LoadPetItems(const uint32 bot_id, uint32* pet_items) return true; int item_index = 0; - for (auto row = results.begin(); row != results.end() && item_index < EQEmu::constants::EQUIPMENT_SIZE; ++row) { + for (auto row = results.begin(); row != results.end() && item_index < EQEmu::legacy::EQUIPMENT_SIZE; ++row) { pet_items[item_index] = atoi(row[0]); ++item_index; } @@ -1595,7 +1595,7 @@ bool BotDatabase::SavePetItems(const uint32 bot_id, const uint32* pet_items, boo if (!saved_pet_index) return true; - for (int item_index = 0; item_index < EQEmu::constants::EQUIPMENT_SIZE; ++item_index) { + for (int item_index = 0; item_index < EQEmu::legacy::EQUIPMENT_SIZE; ++item_index) { if (!pet_items[item_index]) continue; @@ -1744,7 +1744,7 @@ bool BotDatabase::SaveAllArmorColorBySlot(const uint32 owner_id, const int16 slo " AND bi.`slot_id` = '%i'", owner_id, rgb_value, - SlotHead, SlotChest, SlotArms, SlotWrist1, SlotWrist2, SlotHands, SlotLegs, SlotFeet, + EQEmu::legacy::SlotHead, EQEmu::legacy::SlotChest, EQEmu::legacy::SlotArms, EQEmu::legacy::SlotWrist1, EQEmu::legacy::SlotWrist2, EQEmu::legacy::SlotHands, EQEmu::legacy::SlotLegs, EQEmu::legacy::SlotFeet, slot_id ); auto results = QueryDatabase(query); @@ -1768,7 +1768,7 @@ bool BotDatabase::SaveAllArmorColors(const uint32 owner_id, const uint32 rgb_val " AND bi.`slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", owner_id, rgb_value, - SlotHead, SlotChest, SlotArms, SlotWrist1, SlotWrist2, SlotHands, SlotLegs, SlotFeet + EQEmu::legacy::SlotHead, EQEmu::legacy::SlotChest, EQEmu::legacy::SlotArms, EQEmu::legacy::SlotWrist1, EQEmu::legacy::SlotWrist2, EQEmu::legacy::SlotHands, EQEmu::legacy::SlotLegs, EQEmu::legacy::SlotFeet ); auto results = QueryDatabase(query); if (!results.Success()) diff --git a/zone/client.cpp b/zone/client.cpp index aa82bf291..f2ca38474 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2732,7 +2732,7 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) { if (item && (item->ItemClass==ItemClassCommon)) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); - if (matslot != MaterialInvalid) + if (matslot != EQEmu::legacy::MaterialInvalid) { m_pp.item_material[matslot] = GetEquipmentMaterial(matslot); } @@ -3074,7 +3074,7 @@ void Client::SetTint(int16 in_slot, uint32 color) { void Client::SetTint(int16 in_slot, Color_Struct& color) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); - if (matslot != MaterialInvalid) + if (matslot != EQEmu::legacy::MaterialInvalid) { m_pp.item_tint[matslot].Color = color.Color; database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.Color); @@ -3151,58 +3151,58 @@ void Client::LinkDead() uint8 Client::SlotConvert(uint8 slot,bool bracer){ uint8 slot2 = 0; // why are we returning MainCharm instead of INVALID_INDEX? (must be a pre-charm segment...) if(bracer) - return SlotWrist2; - switch(slot){ - case MaterialHead: - slot2 = SlotHead; - break; - case MaterialChest: - slot2 = SlotChest; - break; - case MaterialArms: - slot2 = SlotArms; - break; - case MaterialWrist: - slot2 = SlotWrist1; - break; - case MaterialHands: - slot2 = SlotHands; - break; - case MaterialLegs: - slot2 = SlotLegs; - break; - case MaterialFeet: - slot2 = SlotFeet; - break; - } + return EQEmu::legacy::SlotWrist2; + switch(slot) { + case EQEmu::legacy::MaterialHead: + slot2 = EQEmu::legacy::SlotHead; + break; + case EQEmu::legacy::MaterialChest: + slot2 = EQEmu::legacy::SlotChest; + break; + case EQEmu::legacy::MaterialArms: + slot2 = EQEmu::legacy::SlotArms; + break; + case EQEmu::legacy::MaterialWrist: + slot2 = EQEmu::legacy::SlotWrist1; + break; + case EQEmu::legacy::MaterialHands: + slot2 = EQEmu::legacy::SlotHands; + break; + case EQEmu::legacy::MaterialLegs: + slot2 = EQEmu::legacy::SlotLegs; + break; + case EQEmu::legacy::MaterialFeet: + slot2 = EQEmu::legacy::SlotFeet; + break; + } return slot2; } uint8 Client::SlotConvert2(uint8 slot){ uint8 slot2 = 0; // same as above... switch(slot){ - case SlotHead: - slot2 = MaterialHead; - break; - case SlotChest: - slot2 = MaterialChest; - break; - case SlotArms: - slot2 = MaterialArms; - break; - case SlotWrist1: - slot2 = MaterialWrist; - break; - case SlotHands: - slot2 = MaterialHands; - break; - case SlotLegs: - slot2 = MaterialLegs; - break; - case SlotFeet: - slot2 = MaterialFeet; - break; - } + case EQEmu::legacy::SlotHead: + slot2 = EQEmu::legacy::MaterialHead; + break; + case EQEmu::legacy::SlotChest: + slot2 = EQEmu::legacy::MaterialChest; + break; + case EQEmu::legacy::SlotArms: + slot2 = EQEmu::legacy::MaterialArms; + break; + case EQEmu::legacy::SlotWrist1: + slot2 = EQEmu::legacy::MaterialWrist; + break; + case EQEmu::legacy::SlotHands: + slot2 = EQEmu::legacy::MaterialHands; + break; + case EQEmu::legacy::SlotLegs: + slot2 = EQEmu::legacy::MaterialLegs; + break; + case EQEmu::legacy::SlotFeet: + slot2 = EQEmu::legacy::MaterialFeet; + break; + } return slot2; } @@ -4204,14 +4204,14 @@ bool Client::GroupFollow(Client* inviter) { uint16 Client::GetPrimarySkillValue() { SkillUseTypes skill = HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill - bool equiped = m_inv.GetItem(SlotPrimary); + bool equiped = m_inv.GetItem(EQEmu::legacy::SlotPrimary); if (!equiped) skill = SkillHandtoHand; else { - uint8 type = m_inv.GetItem(SlotPrimary)->GetItem()->ItemType; //is this the best way to do this? + uint8 type = m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType; //is this the best way to do this? switch (type) { @@ -5392,7 +5392,7 @@ bool Client::TryReward(uint32 claim_id) // save uint32 free_slot = 0xFFFFFFFF; - for (int i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; ++i) { + for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; ++i) { ItemInst *item = GetInv().GetItem(i); if (!item) { free_slot = i; @@ -5738,7 +5738,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { } } - inst = requestee->GetInv().GetItem(SlotPowerSource); + inst = requestee->GetInv().GetItem(EQEmu::legacy::SlotPowerSource); if(inst) { item = inst->GetItem(); @@ -5752,7 +5752,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { insr->itemicons[SoF::inventory::SlotPowerSource] = 0xFFFFFFFF; } - inst = requestee->GetInv().GetItem(SlotAmmo); + inst = requestee->GetInv().GetItem(EQEmu::legacy::SlotAmmo); if(inst) { item = inst->GetItem(); @@ -6293,8 +6293,8 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid made_npc->Corrup = GetCorrup(); made_npc->PhR = GetPhR(); // looks - made_npc->texture = GetEquipmentMaterial(MaterialChest); - made_npc->helmtexture = GetEquipmentMaterial(MaterialHead); + made_npc->texture = GetEquipmentMaterial(EQEmu::legacy::MaterialChest); + made_npc->helmtexture = GetEquipmentMaterial(EQEmu::legacy::MaterialHead); made_npc->haircolor = GetHairColor(); made_npc->beardcolor = GetBeardColor(); made_npc->eyecolor1 = GetEyeColor1(); @@ -6305,9 +6305,9 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid made_npc->drakkin_heritage = GetDrakkinHeritage(); made_npc->drakkin_tattoo = GetDrakkinTattoo(); made_npc->drakkin_details = GetDrakkinDetails(); - made_npc->d_melee_texture1 = GetEquipmentMaterial(MaterialPrimary); - made_npc->d_melee_texture2 = GetEquipmentMaterial(MaterialSecondary); - for (int i = EQEmu::constants::MATERIAL_BEGIN; i <= EQEmu::constants::MATERIAL_END; i++) { + made_npc->d_melee_texture1 = GetEquipmentMaterial(EQEmu::legacy::MaterialPrimary); + made_npc->d_melee_texture2 = GetEquipmentMaterial(EQEmu::legacy::MaterialSecondary); + for (int i = EQEmu::legacy::MATERIAL_BEGIN; i <= EQEmu::legacy::MATERIAL_END; i++) { made_npc->armor_tint[i] = GetEquipmentColor(i); } made_npc->loottable_id = 0; @@ -7583,7 +7583,7 @@ void Client::GarbleMessage(char *message, uint8 variance) for (size_t i = 0; i < strlen(message); i++) { // Client expects hex values inside of a text link body if (message[i] == delimiter) { - if (!(delimiter_count & 1)) { i += EQEmu::constants::TEXT_LINK_BODY_LENGTH; } + if (!(delimiter_count & 1)) { i += EQEmu::legacy::TEXT_LINK_BODY_LENGTH; } ++delimiter_count; continue; } @@ -8008,17 +8008,17 @@ void Client::TickItemCheck() if(zone->tick_items.empty()) { return; } //Scan equip slots for items - for (i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; i++) + for (i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; i++) { TryItemTick(i); } //Scan main inventory + cursor - for (i = EQEmu::constants::GENERAL_BEGIN; i <= SlotCursor; i++) + for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::SlotCursor; i++) { TryItemTick(i); } //Scan bags - for (i = EQEmu::constants::GENERAL_BAGS_BEGIN; i <= EQEmu::constants::CURSOR_BAG_END; i++) + for (i = EQEmu::legacy::GENERAL_BAGS_BEGIN; i <= EQEmu::legacy::CURSOR_BAG_END; i++) { TryItemTick(i); } @@ -8034,7 +8034,7 @@ void Client::TryItemTick(int slot) if(zone->tick_items.count(iid) > 0) { - if (GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EQEmu::constants::EQUIPMENT_END)) + if (GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EQEmu::legacy::EQUIPMENT_END)) { ItemInst* e_inst = (ItemInst*)inst; parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); @@ -8042,9 +8042,9 @@ void Client::TryItemTick(int slot) } //Only look at augs in main inventory - if (slot > EQEmu::constants::EQUIPMENT_END) { return; } + if (slot > EQEmu::legacy::EQUIPMENT_END) { return; } - for (int x = AUG_INDEX_BEGIN; x < EQEmu::constants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) { ItemInst * a_inst = inst->GetAugment(x); if(!a_inst) { continue; } @@ -8065,17 +8065,17 @@ void Client::TryItemTick(int slot) void Client::ItemTimerCheck() { int i; - for (i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; i++) + for (i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; i++) { TryItemTimer(i); } - for (i = EQEmu::constants::GENERAL_BEGIN; i <= SlotCursor; i++) + for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::SlotCursor; i++) { TryItemTimer(i); } - for (i = EQEmu::constants::GENERAL_BAGS_BEGIN; i <= EQEmu::constants::CURSOR_BAG_END; i++) + for (i = EQEmu::legacy::GENERAL_BAGS_BEGIN; i <= EQEmu::legacy::CURSOR_BAG_END; i++) { TryItemTimer(i); } @@ -8097,11 +8097,11 @@ void Client::TryItemTimer(int slot) ++it_iter; } - if (slot > EQEmu::constants::EQUIPMENT_END) { + if (slot > EQEmu::legacy::EQUIPMENT_END) { return; } - for (int x = AUG_INDEX_BEGIN; x < EQEmu::constants::ITEM_COMMON_SIZE; ++x) + for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) { ItemInst * a_inst = inst->GetAugment(x); if(!a_inst) { @@ -8389,12 +8389,12 @@ void Client::ShowNumHits() int Client::GetQuiverHaste(int delay) { const ItemInst *pi = nullptr; - for (int r = EQEmu::constants::GENERAL_BEGIN; r <= EQEmu::constants::GENERAL_END; r++) { + for (int r = EQEmu::legacy::GENERAL_BEGIN; r <= EQEmu::legacy::GENERAL_END; r++) { pi = GetInv().GetItem(r); if (pi && pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == BagTypeQuiver && pi->GetItem()->BagWR > 0) break; - if (r == EQEmu::constants::GENERAL_END) + if (r == EQEmu::legacy::GENERAL_END) // we will get here if we don't find a valid quiver return 0; } @@ -8435,7 +8435,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, AddMoneyToPP(copper, silver, gold, platinum, false); if (itemid > 0) - SummonItem(itemid, 0, 0, 0, 0, 0, 0, false, SlotPowerSource); + SummonItem(itemid, 0, 0, 0, 0, 0, 0, false, EQEmu::legacy::SlotPowerSource); if (faction) { diff --git a/zone/client.h b/zone/client.h index 60582d9c4..a17e59f40 100644 --- a/zone/client.h +++ b/zone/client.h @@ -218,7 +218,7 @@ public: //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } @@ -814,7 +814,7 @@ public: void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false); void PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data = 0); bool AutoPutLootInInventory(ItemInst& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0); - bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = SlotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); + bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = EQEmu::legacy::SlotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 9dda04389..6e22cc514 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -485,7 +485,7 @@ int32 Client::GetRawItemAC() { int32 Total = 0; // this skips MainAmmo..add an '=' conditional if that slot is required (original behavior) - for (int16 slot_id = EQEmu::constants::EQUIPMENT_BEGIN; slot_id < EQEmu::constants::EQUIPMENT_END; slot_id++) { + for (int16 slot_id = EQEmu::legacy::EQUIPMENT_BEGIN; slot_id < EQEmu::legacy::EQUIPMENT_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if (inst && inst->IsType(ItemClassCommon)) { Total += inst->GetItem()->AC; @@ -1067,9 +1067,9 @@ int32 Client::CalcAC() } // Shield AC bonus for HeroicSTR if (itembonuses.HeroicSTR) { - bool equiped = CastToClient()->m_inv.GetItem(SlotSecondary); + bool equiped = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary); if (equiped) { - uint8 shield = CastToClient()->m_inv.GetItem(SlotSecondary)->GetItem()->ItemType; + uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType; if (shield == ItemTypeShield) { displayed += itembonuses.HeroicSTR / 2; } @@ -1096,9 +1096,9 @@ int32 Client::GetACMit() } // Shield AC bonus for HeroicSTR if (itembonuses.HeroicSTR) { - bool equiped = CastToClient()->m_inv.GetItem(SlotSecondary); + bool equiped = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary); if (equiped) { - uint8 shield = CastToClient()->m_inv.GetItem(SlotSecondary)->GetItem()->ItemType; + uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType; if (shield == ItemTypeShield) { mitigation += itembonuses.HeroicSTR / 2; } @@ -1306,7 +1306,7 @@ uint32 Client::CalcCurrentWeight() ItemInst* ins; uint32 Total = 0; int x; - for (x = EQEmu::constants::EQUIPMENT_BEGIN; x <= SlotCursor; x++) { // include cursor or not? + for (x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::SlotCursor; x++) { // include cursor or not? TempItem = 0; ins = GetInv().GetItem(x); if (ins) { @@ -1316,7 +1316,7 @@ uint32 Client::CalcCurrentWeight() Total += TempItem->Weight; } } - for (x = EQEmu::constants::GENERAL_BAGS_BEGIN; x <= EQEmu::constants::GENERAL_BAGS_END; x++) { // include cursor bags or not? + for (x = EQEmu::legacy::GENERAL_BAGS_BEGIN; x <= EQEmu::legacy::GENERAL_BAGS_END; x++) { // include cursor bags or not? int TmpWeight = 0; TempItem = 0; ins = GetInv().GetItem(x); @@ -1329,9 +1329,9 @@ uint32 Client::CalcCurrentWeight() if (TmpWeight > 0) { // this code indicates that weight redux bags can only be in the first general inventory slot to be effective... // is this correct? or can we scan for the highest weight redux and use that? (need client verifications) - int bagslot = SlotGeneral1; + int bagslot = EQEmu::legacy::SlotGeneral1; int reduction = 0; - for (int m = EQEmu::constants::GENERAL_BAGS_BEGIN + 10; m <= EQEmu::constants::GENERAL_BAGS_END; m += 10) { // include cursor bags or not? + for (int m = EQEmu::legacy::GENERAL_BAGS_BEGIN + 10; m <= EQEmu::legacy::GENERAL_BAGS_END; m += 10) { // include cursor bags or not? if (x >= m) { bagslot += 1; } @@ -2205,12 +2205,12 @@ int Client::GetRawACNoShield(int &shield_ac) const { int ac = itembonuses.AC + spellbonuses.AC + aabonuses.AC; shield_ac = 0; - const ItemInst *inst = m_inv.GetItem(SlotSecondary); + const ItemInst *inst = m_inv.GetItem(EQEmu::legacy::SlotSecondary); if (inst) { if (inst->GetItem()->ItemType == ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; - for (uint8 i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { + for (uint8 i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { if (inst->GetAugment(i)) { ac -= inst->GetAugment(i)->GetItem()->AC; shield_ac += inst->GetAugment(i)->GetItem()->AC; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e8dbbc7e8..75ed6771e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1313,7 +1313,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) } /* Set item material tint */ - for (int i = EQEmu::constants::MATERIAL_BEGIN; i <= EQEmu::constants::MATERIAL_END; i++) + for (int i = EQEmu::legacy::MATERIAL_BEGIN; i <= EQEmu::legacy::MATERIAL_END; i++) { if (m_pp.item_tint[i].RGB.UseTint == 1 || m_pp.item_tint[i].RGB.UseTint == 255) { @@ -1689,7 +1689,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (iter == m_inv.cursor_cbegin()) continue; const ItemInst *inst = *iter; - SendItemPacket(SlotCursor, inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketSummonItem); } } @@ -2027,7 +2027,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) ItemInst *inst = database.CreateItem(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) { - PutLootInInventory(SlotCursor, *inst); + PutLootInInventory(EQEmu::legacy::SlotCursor, *inst); } Save(1); } @@ -2550,7 +2550,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) ItemInst *inst = database.CreateItem(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) { - PutLootInInventory(SlotCursor, *inst); + PutLootInInventory(EQEmu::legacy::SlotCursor, *inst); } Save(1); @@ -2600,7 +2600,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) SetAlternateCurrencyValue(reclaim->currency_id, 0); } else { - SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, SlotCursor); + SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, EQEmu::legacy::SlotCursor); AddAlternateCurrencyValue(reclaim->currency_id, -((int32)reclaim->count)); } /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ @@ -2811,8 +2811,8 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app) } uint32 ApplyPoisonSuccessResult = 0; ApplyPoison_Struct* ApplyPoisonData = (ApplyPoison_Struct*)app->pBuffer; - const ItemInst* PrimaryWeapon = GetInv().GetItem(SlotPrimary); - const ItemInst* SecondaryWeapon = GetInv().GetItem(SlotSecondary); + const ItemInst* PrimaryWeapon = GetInv().GetItem(EQEmu::legacy::SlotPrimary); + const ItemInst* SecondaryWeapon = GetInv().GetItem(EQEmu::legacy::SlotSecondary); const ItemInst* PoisonItemInstance = GetInv()[ApplyPoisonData->inventorySlot]; bool IsPoison = PoisonItemInstance && (PoisonItemInstance->GetItem()->ItemType == ItemTypePoison); @@ -2994,7 +2994,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) { case 0: // Adding an augment case 2: // Swapping augment - new_aug = user_inv.GetItem(SlotCursor); + new_aug = user_inv.GetItem(EQEmu::legacy::SlotCursor); if (!new_aug) // Shouldn't get the OP code without the augment on the user's cursor, but maybe it's h4x. { @@ -3052,7 +3052,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (itemOneToPush) { DeleteItemInInventory(item_slot, 0, true); - DeleteItemInInventory(SlotCursor, new_aug->IsStackable() ? 1 : 0, true); + DeleteItemInInventory(EQEmu::legacy::SlotCursor, new_aug->IsStackable() ? 1 : 0, true); if (solvent) { @@ -3063,7 +3063,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (itemTwoToPush) { // This is a swap. Return the old aug to the player's cursor. - if (!PutItemInInventory(SlotCursor, *itemTwoToPush, true)) + if (!PutItemInInventory(EQEmu::legacy::SlotCursor, *itemTwoToPush, true)) { Log.Out(Logs::General, Logs::Error, "Problem returning old augment to player's cursor after augmentation swap."); Message(15, "Error: Failed to retrieve old augment after augmentation swap!"); @@ -3076,7 +3076,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != MaterialInvalid) + if (mat != EQEmu::legacy::MaterialInvalid) { SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. } @@ -3141,13 +3141,13 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != MaterialInvalid) + if (mat != EQEmu::legacy::MaterialInvalid) { SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. } // Drop the removed augment on the player's cursor - if (!PutItemInInventory(SlotCursor, *itemTwoToPush, true)) + if (!PutItemInInventory(EQEmu::legacy::SlotCursor, *itemTwoToPush, true)) { Log.Out(Logs::General, Logs::Error, "Problem returning augment to player's cursor after safe removal."); Message(15, "Error: Failed to return augment after removal from item!"); @@ -3196,7 +3196,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != MaterialInvalid) + if (mat != EQEmu::legacy::MaterialInvalid) { SendWearChange(mat); } @@ -4072,7 +4072,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) } else { - Message(0, "Error: castspell->inventoryslot >= %i (0x%04x)", SlotCursor, castspell->inventoryslot); + Message(0, "Error: castspell->inventoryslot >= %i (0x%04x)", EQEmu::legacy::SlotCursor, castspell->inventoryslot); InterruptSpell(castspell->spell_id); } } @@ -4991,7 +4991,7 @@ void Client::Handle_OP_CrashDump(const EQApplicationPacket *app) void Client::Handle_OP_CreateObject(const EQApplicationPacket *app) { - DropItem(SlotCursor); + DropItem(EQEmu::legacy::SlotCursor); return; } @@ -6905,7 +6905,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) return; } - ItemInst *CursorItemInst = GetInv().GetItem(SlotCursor); + ItemInst *CursorItemInst = GetInv().GetItem(EQEmu::legacy::SlotCursor); bool Allowed = true; @@ -6953,7 +6953,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) { GuildBankDepositAck(false, sentAction); - DeleteItemInInventory(SlotCursor, 0, false); + DeleteItemInInventory(EQEmu::legacy::SlotCursor, 0, false); } break; @@ -6974,7 +6974,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) case GuildBankWithdraw: { - if (GetInv()[SlotCursor]) + if (GetInv()[EQEmu::legacy::SlotCursor]) { Message_StringID(13, GUILD_BANK_EMPTY_HANDS); @@ -7020,7 +7020,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) { PushItemOnCursor(*inst); - SendItemPacket(SlotCursor, inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketSummonItem); GuildBanks->DeleteItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity); } @@ -7994,7 +7994,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) const Item_Struct* item = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - for (int16 L = EQEmu::constants::EQUIPMENT_BEGIN; L <= SlotWaist; L++) { + for (int16 L = EQEmu::legacy::EQUIPMENT_BEGIN; L <= EQEmu::legacy::SlotWaist; L++) { const ItemInst* inst = GetInv().GetItem(L); item = inst ? inst->GetItem() : nullptr; @@ -8014,7 +8014,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) else { insr->itemicons[L] = 0xFFFFFFFF; } } - const ItemInst* inst = GetInv().GetItem(SlotAmmo); + const ItemInst* inst = GetInv().GetItem(EQEmu::legacy::SlotAmmo); item = inst ? inst->GetItem() : nullptr; if (item) { @@ -8474,7 +8474,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) ItemInst* clickaug = 0; Item_Struct* augitem = 0; - for (r = 0; r < EQEmu::constants::ITEM_COMMON_SIZE; r++) { + for (r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { const ItemInst* aug_i = inst->GetAugment(r); if (!aug_i) continue; @@ -9675,7 +9675,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer; if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id)) { - if (mi->from_slot != mi->to_slot && (mi->from_slot <= EQEmu::constants::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) + if (mi->from_slot != mi->to_slot && (mi->from_slot <= EQEmu::legacy::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) { char *detect = nullptr; const ItemInst *itm_from = GetInv().GetItem(mi->from_slot); @@ -9696,8 +9696,8 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) // Illegal bagslot usage checks. Currently, user only receives a message if this check is triggered. bool mi_hack = false; - if (mi->from_slot >= EQEmu::constants::GENERAL_BAGS_BEGIN && mi->from_slot <= EQEmu::constants::CURSOR_BAG_END) { - if (mi->from_slot >= EQEmu::constants::CURSOR_BAG_BEGIN) { mi_hack = true; } + if (mi->from_slot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && mi->from_slot <= EQEmu::legacy::CURSOR_BAG_END) { + if (mi->from_slot >= EQEmu::legacy::CURSOR_BAG_BEGIN) { mi_hack = true; } else { int16 from_parent = m_inv.CalcSlotId(mi->from_slot); if (!m_inv[from_parent]) { mi_hack = true; } @@ -9706,8 +9706,8 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) } } - if (mi->to_slot >= EQEmu::constants::GENERAL_BAGS_BEGIN && mi->to_slot <= EQEmu::constants::CURSOR_BAG_END) { - if (mi->to_slot >= EQEmu::constants::CURSOR_BAG_BEGIN) { mi_hack = true; } + if (mi->to_slot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && mi->to_slot <= EQEmu::legacy::CURSOR_BAG_END) { + if (mi->to_slot >= EQEmu::legacy::CURSOR_BAG_BEGIN) { mi_hack = true; } else { int16 to_parent = m_inv.CalcSlotId(mi->to_slot); if (!m_inv[to_parent]) { mi_hack = true; } @@ -12023,7 +12023,7 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app) Shielding_Struct* shield = (Shielding_Struct*)app->pBuffer; shield_target = entity_list.GetMob(shield->target_id); bool ack = false; - ItemInst* inst = GetInv().GetItem(SlotSecondary); + ItemInst* inst = GetInv().GetItem(EQEmu::legacy::SlotSecondary); if (!shield_target) return; if (inst) @@ -12240,8 +12240,8 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) // shouldn't we be reimbursing if these two fail? //make sure we are not completely full... - if (freeslotid == SlotCursor) { - if (m_inv.GetItem(SlotCursor) != nullptr) { + if (freeslotid == EQEmu::legacy::SlotCursor) { + if (m_inv.GetItem(EQEmu::legacy::SlotCursor) != nullptr) { Message(13, "You do not have room for any more items."); safe_delete(outapp); safe_delete(inst); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 301474456..942139b26 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -296,7 +296,7 @@ bool Client::Process() { } if(AutoFireEnabled()){ - ItemInst *ranged = GetInv().GetItem(SlotRange); + ItemInst *ranged = GetInv().GetItem(EQEmu::legacy::SlotRange); if(ranged) { if(ranged->GetItem() && ranged->GetItem()->ItemType == ItemTypeBow){ @@ -391,10 +391,10 @@ bool Client::Process() { } else if (auto_attack_target->GetHP() > -10) // -10 so we can watch people bleed in PvP { - ItemInst *wpn = GetInv().GetItem(SlotPrimary); - TryWeaponProc(wpn, auto_attack_target, SlotPrimary); + ItemInst *wpn = GetInv().GetItem(EQEmu::legacy::SlotPrimary); + TryWeaponProc(wpn, auto_attack_target, EQEmu::legacy::SlotPrimary); - DoAttackRounds(auto_attack_target, SlotPrimary); + DoAttackRounds(auto_attack_target, EQEmu::legacy::SlotPrimary); if (CheckAATimer(aaTimerRampage)) entity_list.AEAttack(this, 30); } @@ -430,10 +430,10 @@ bool Client::Process() { else if(auto_attack_target->GetHP() > -10) { CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10); if (CheckDualWield()) { - ItemInst *wpn = GetInv().GetItem(SlotSecondary); - TryWeaponProc(wpn, auto_attack_target, SlotSecondary); + ItemInst *wpn = GetInv().GetItem(EQEmu::legacy::SlotSecondary); + TryWeaponProc(wpn, auto_attack_target, EQEmu::legacy::SlotSecondary); - DoAttackRounds(auto_attack_target, SlotSecondary); + DoAttackRounds(auto_attack_target, EQEmu::legacy::SlotSecondary); } } } @@ -742,7 +742,7 @@ void Client::BulkSendInventoryItems() { // LINKDEAD TRADE ITEMS // Move trade slot items back into normal inventory..need them there now for the proceeding validity checks - for(slot_id = EQEmu::constants::TRADE_BEGIN; slot_id <= EQEmu::constants::TRADE_END; slot_id++) { + for (slot_id = EQEmu::legacy::TRADE_BEGIN; slot_id <= EQEmu::legacy::TRADE_END; slot_id++) { ItemInst* inst = m_inv.PopItem(slot_id); if(inst) { bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; @@ -790,7 +790,7 @@ void Client::BulkSendInventoryItems() { std::map::iterator itr; //Inventory items - for(slot_id = SLOT_BEGIN; slot_id < EQEmu::constants::TYPE_POSSESSIONS_SIZE; slot_id++) { + for (slot_id = SLOT_BEGIN; slot_id < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if(inst) { std::string packet = inst->Serialize(slot_id); @@ -801,16 +801,16 @@ void Client::BulkSendInventoryItems() { // Power Source if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - const ItemInst* inst = m_inv[SlotPowerSource]; + const ItemInst* inst = m_inv[EQEmu::legacy::SlotPowerSource]; if(inst) { - std::string packet = inst->Serialize(SlotPowerSource); + std::string packet = inst->Serialize(EQEmu::legacy::SlotPowerSource); ser_items[i++] = packet; size += packet.length(); } } // Bank items - for(slot_id = EQEmu::constants::BANK_BEGIN; slot_id <= EQEmu::constants::BANK_END; slot_id++) { + for (slot_id = EQEmu::legacy::BANK_BEGIN; slot_id <= EQEmu::legacy::BANK_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if(inst) { std::string packet = inst->Serialize(slot_id); @@ -820,7 +820,7 @@ void Client::BulkSendInventoryItems() { } // Shared Bank items - for(slot_id = EQEmu::constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::constants::SHARED_BANK_END; slot_id++) { + for (slot_id = EQEmu::legacy::SHARED_BANK_BEGIN; slot_id <= EQEmu::legacy::SHARED_BANK_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; if(inst) { std::string packet = inst->Serialize(slot_id); @@ -1147,7 +1147,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) switch(memspell->scribing) { case memSpellScribing: { // scribing spell to book - const ItemInst* inst = m_inv[SlotCursor]; + const ItemInst* inst = m_inv[EQEmu::legacy::SlotCursor]; if(inst && inst->IsType(ItemClassCommon)) { @@ -1161,7 +1161,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) if(item && item->Scroll.Effect == (int32)(memspell->spell_id)) { ScribeSpell(memspell->spell_id, memspell->slot); - DeleteItemInInventory(SlotCursor, 1, true); + DeleteItemInInventory(EQEmu::legacy::SlotCursor, 1, true); } else Message(0,"Scribing spell: inst exists but item does not or spell ids do not match."); diff --git a/zone/command.cpp b/zone/command.cpp index 6270c0182..671a793cb 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2413,14 +2413,14 @@ void command_texture(Client *c, const Seperator *sep) // Player Races Wear Armor, so Wearchange is sent instead int i; if (!c->GetTarget()) - for (i = EQEmu::constants::MATERIAL_BEGIN; i <= EQEmu::constants::MATERIAL_TINT_END; i++) + for (i = EQEmu::legacy::MATERIAL_BEGIN; i <= EQEmu::legacy::MATERIAL_TINT_END; i++) { c->SendTextureWC(i, texture); } else if ((c->GetTarget()->GetRace() > 0 && c->GetTarget()->GetRace() <= 12) || c->GetTarget()->GetRace() == 128 || c->GetTarget()->GetRace() == 130 || c->GetTarget()->GetRace() == 330 || c->GetTarget()->GetRace() == 522) { - for (i = EQEmu::constants::MATERIAL_BEGIN; i <= EQEmu::constants::MATERIAL_TINT_END; i++) + for (i = EQEmu::legacy::MATERIAL_BEGIN; i <= EQEmu::legacy::MATERIAL_TINT_END; i++) { c->GetTarget()->SendTextureWC(i, texture); } @@ -2551,7 +2551,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message(0, "Displaying inventory for %s...", targetClient->GetName()); // worn - for (int16 indexMain = EQEmu::constants::EQUIPMENT_BEGIN; (scopeWhere & peekWorn) && (indexMain <= EQEmu::constants::EQUIPMENT_END); ++indexMain) { + for (int16 indexMain = EQEmu::legacy::EQUIPMENT_BEGIN; (scopeWhere & peekWorn) && (indexMain <= EQEmu::legacy::EQUIPMENT_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2563,18 +2563,18 @@ void command_peekinv(Client *c, const Seperator *sep) } if ((scopeWhere & peekWorn) && (targetClient->ClientVersion() >= EQEmu::versions::ClientVersion::SoF)) { - inst_main = targetClient->GetInv().GetItem(SlotPowerSource); + inst_main = targetClient->GetInv().GetItem(EQEmu::legacy::SlotPowerSource); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); item_link = linker.GenerateLink(); c->Message((item_data == nullptr), "WornSlot: %i, Item: %i (%s), Charges: %i", - SlotPowerSource, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); + EQEmu::legacy::SlotPowerSource, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); } // inv - for (int16 indexMain = EQEmu::constants::GENERAL_BEGIN; (scopeWhere & peekInv) && (indexMain <= EQEmu::constants::GENERAL_END); ++indexMain) { + for (int16 indexMain = EQEmu::legacy::GENERAL_BEGIN; (scopeWhere & peekInv) && (indexMain <= EQEmu::legacy::GENERAL_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2584,7 +2584,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "InvSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2604,7 +2604,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message(1, "CursorSlot: %i, Item: %i (%s), Charges: %i", - SlotCursor, 0, item_link.c_str(), 0); + EQEmu::legacy::SlotCursor, 0, item_link.c_str(), 0); } else { int cursorDepth = 0; @@ -2616,9 +2616,9 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), "CursorSlot: %i, Depth: %i, Item: %i (%s), Charges: %i", - SlotCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); + EQEmu::legacy::SlotCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2626,14 +2626,14 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(SlotCursor, indexSub), SlotCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + Inventory::CalcSlotId(EQEmu::legacy::SlotCursor, indexSub), EQEmu::legacy::SlotCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } } } // trib - for (int16 indexMain = EQEmu::constants::TRIBUTE_BEGIN; (scopeWhere & peekTrib) && (indexMain <= EQEmu::constants::TRIBUTE_END); ++indexMain) { + for (int16 indexMain = EQEmu::legacy::TRIBUTE_BEGIN; (scopeWhere & peekTrib) && (indexMain <= EQEmu::legacy::TRIBUTE_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2645,7 +2645,7 @@ void command_peekinv(Client *c, const Seperator *sep) } // bank - for (int16 indexMain = EQEmu::constants::BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EQEmu::constants::BANK_END); ++indexMain) { + for (int16 indexMain = EQEmu::legacy::BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EQEmu::legacy::BANK_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2655,7 +2655,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "BankSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2667,7 +2667,7 @@ void command_peekinv(Client *c, const Seperator *sep) } } - for (int16 indexMain = EQEmu::constants::SHARED_BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EQEmu::constants::SHARED_BANK_END); ++indexMain) { + for (int16 indexMain = EQEmu::legacy::SHARED_BANK_BEGIN; (scopeWhere & peekBank) && (indexMain <= EQEmu::legacy::SHARED_BANK_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2677,7 +2677,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "SharedBankSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2690,7 +2690,7 @@ void command_peekinv(Client *c, const Seperator *sep) } // trade - for (int16 indexMain = EQEmu::constants::TRADE_BEGIN; (scopeWhere & peekTrade) && (indexMain <= EQEmu::constants::TRADE_END); ++indexMain) { + for (int16 indexMain = EQEmu::legacy::TRADE_BEGIN; (scopeWhere & peekTrade) && (indexMain <= EQEmu::legacy::TRADE_END); ++indexMain) { inst_main = targetClient->GetInv().GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2700,7 +2700,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "TradeSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2722,7 +2722,7 @@ void command_peekinv(Client *c, const Seperator *sep) else { c->Message(0, "[WorldObject DBID: %i (entityid: %i)]", objectTradeskill->GetDBID(), objectTradeskill->GetID()); - for (int16 indexMain = SLOT_BEGIN; indexMain < EQEmu::constants::TYPE_WORLD_SIZE; ++indexMain) { + for (int16 indexMain = SLOT_BEGIN; indexMain < EQEmu::legacy::TYPE_WORLD_SIZE; ++indexMain) { inst_main = objectTradeskill->GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2730,9 +2730,9 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), "WorldSlot: %i, Item: %i (%s), Charges: %i", - (EQEmu::constants::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); + (EQEmu::legacy::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -3140,8 +3140,8 @@ void command_listpetition(Client *c, const Seperator *sep) void command_equipitem(Client *c, const Seperator *sep) { uint32 slot_id = atoi(sep->arg[1]); - if (sep->IsNumber(1) && ((slot_id >= EQEmu::constants::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::constants::EQUIPMENT_END) || (slot_id == SlotPowerSource))) { - const ItemInst* from_inst = c->GetInv().GetItem(SlotCursor); + if (sep->IsNumber(1) && ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::legacy::SlotPowerSource))) { + const ItemInst* from_inst = c->GetInv().GetItem(EQEmu::legacy::SlotCursor); const ItemInst* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack) bool partialmove = false; int16 movecount; @@ -3149,7 +3149,7 @@ void command_equipitem(Client *c, const Seperator *sep) if (from_inst && from_inst->IsType(ItemClassCommon)) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer; - mi->from_slot = SlotCursor; + mi->from_slot = EQEmu::legacy::SlotCursor; mi->to_slot = slot_id; // mi->number_in_stack = from_inst->GetCharges(); // replaced with con check for stacking @@ -4333,7 +4333,7 @@ void command_goto(Client *c, const Seperator *sep) void command_iteminfo(Client *c, const Seperator *sep) { - auto inst = c->GetInv()[SlotCursor]; + auto inst = c->GetInv()[EQEmu::legacy::SlotCursor]; if (!inst) { c->Message(13, "Error: You need an item on your cursor for this command"); } auto item = inst->GetItem(); if (!item) { @@ -5491,9 +5491,9 @@ void command_summonitem(Client *c, const Seperator *sep) std::string cmd_msg = sep->msg; size_t link_open = cmd_msg.find('\x12'); size_t link_close = cmd_msg.find_last_of('\x12'); - if (link_open != link_close && (cmd_msg.length() - link_open) > EQEmu::constants::TEXT_LINK_BODY_LENGTH) { + if (link_open != link_close && (cmd_msg.length() - link_open) > EQEmu::legacy::TEXT_LINK_BODY_LENGTH) { EQEmu::saylink::SayLinkBody_Struct link_body; - EQEmu::saylink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQEmu::constants::TEXT_LINK_BODY_LENGTH)); + EQEmu::saylink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQEmu::legacy::TEXT_LINK_BODY_LENGTH)); itemid = link_body.item_id; } else if (!sep->IsNumber(1)) { @@ -7114,7 +7114,7 @@ void command_path(Client *c, const Seperator *sep) } void Client::Undye() { - for (int cur_slot = EQEmu::constants::MATERIAL_BEGIN; cur_slot <= EQEmu::constants::MATERIAL_END; cur_slot++ ) { + for (int cur_slot = EQEmu::legacy::MATERIAL_BEGIN; cur_slot <= EQEmu::legacy::MATERIAL_END; cur_slot++) { uint8 slot2=SlotConvert(cur_slot); ItemInst* inst = m_inv.GetItem(slot2); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 2bb9883fa..90dad987d 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -328,12 +328,12 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( // to go into the regular slots on the player, out of bags std::list removed_list; - for(i = SLOT_BEGIN; i < EQEmu::constants::TYPE_POSSESSIONS_SIZE; ++i) { - if (i == SlotAmmo && client->ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - item = client->GetInv().GetItem(SlotPowerSource); + for (i = SLOT_BEGIN; i < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; ++i) { + if (i == EQEmu::legacy::SlotAmmo && client->ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { + item = client->GetInv().GetItem(EQEmu::legacy::SlotPowerSource); if (item != nullptr) { if (!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent)) - MoveItemToCorpse(client, item, SlotPowerSource, removed_list); + MoveItemToCorpse(client, item, EQEmu::legacy::SlotPowerSource, removed_list); } } @@ -410,9 +410,9 @@ void Corpse::MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, s while (true) { if (!inst->IsType(ItemClassContainer)) { break; } - if (equipSlot < EQEmu::constants::GENERAL_BEGIN || equipSlot > SlotCursor) { break; } + if (equipSlot < EQEmu::legacy::GENERAL_BEGIN || equipSlot > EQEmu::legacy::SlotCursor) { break; } - for (auto sub_index = SUB_INDEX_BEGIN; sub_index < EQEmu::constants::ITEM_CONTAINER_SIZE; ++sub_index) { + for (auto sub_index = SUB_INDEX_BEGIN; sub_index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++sub_index) { int16 real_bag_slot = Inventory::CalcSlotId(equipSlot, sub_index); auto bag_inst = client->GetInv().GetItem(real_bag_slot); if (bag_inst == nullptr) { continue; } @@ -748,7 +748,7 @@ void Corpse::RemoveItem(ServerLootItem_Struct* item_data) itemlist.erase(iter); uint8 material = Inventory::CalcMaterialFromSlot(sitem->equip_slot); // autos to unsigned char - if (material != MaterialInvalid) + if (material != EQEmu::legacy::MaterialInvalid) SendWearChange(material); UpdateEquipmentLight(); @@ -985,7 +985,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(inst) { if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); - client->SendItemPacket(EQEmu::constants::CORPSE_BEGIN, inst, ItemPacketLoot); + client->SendItemPacket(EQEmu::legacy::CORPSE_BEGIN, inst, ItemPacketLoot); safe_delete(inst); } else { client->Message(13, "Could not find item number %i to send!!", GetPlayerKillItem()); } @@ -1000,7 +1000,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::limits::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()), TypeCorpse); + int corpselootlimit = EQEmu::limits::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()), EQEmu::legacy::TypeCorpse); for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; @@ -1009,7 +1009,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a // Dont display the item if it's in a bag // Added cursor queue slots to corpse item visibility list. Nothing else should be making it to corpse. - if(!IsPlayerCorpse() || item_data->equip_slot <= SlotCursor || item_data->equip_slot == SlotPowerSource || Loot_Request_Type>=3 || + if (!IsPlayerCorpse() || item_data->equip_slot <= EQEmu::legacy::SlotCursor || item_data->equip_slot == EQEmu::legacy::SlotPowerSource || Loot_Request_Type >= 3 || (item_data->equip_slot >= 8000 && item_data->equip_slot <= 8999)) { if(i < corpselootlimit) { item = database.GetItem(item_data->item_id); @@ -1019,7 +1019,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); // SlotGeneral1 is the corpse inventory start offset for Ti(EMu) - CORPSE_END = SlotGeneral1 + SlotCursor - client->SendItemPacket(i + EQEmu::constants::CORPSE_BEGIN, inst, ItemPacketLoot); + client->SendItemPacket(i + EQEmu::legacy::CORPSE_BEGIN, inst, ItemPacketLoot); safe_delete(inst); } @@ -1119,10 +1119,10 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { item = database.GetItem(GetPlayerKillItem()); } else if (GetPlayerKillItem() == -1 || GetPlayerKillItem() == 1){ - item_data = GetItem(lootitem->slot_id - EQEmu::constants::CORPSE_BEGIN); //dont allow them to loot entire bags of items as pvp reward + item_data = GetItem(lootitem->slot_id - EQEmu::legacy::CORPSE_BEGIN); //dont allow them to loot entire bags of items as pvp reward } else{ - item_data = GetItem(lootitem->slot_id - EQEmu::constants::CORPSE_BEGIN, bag_item_data); + item_data = GetItem(lootitem->slot_id - EQEmu::legacy::CORPSE_BEGIN, bag_item_data); } if (GetPlayerKillItem()<=1 && item_data != 0) { @@ -1148,7 +1148,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } if (inst->IsAugmented()) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { ItemInst *itm = inst->GetAugment(i); if (itm) { if (client->CheckLoreConflict(itm->GetItem())) { @@ -1190,10 +1190,10 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { /* First add it to the looter - this will do the bag contents too */ if (lootitem->auto_loot) { if (!client->AutoPutLootInInventory(*inst, true, true, bag_item_data)) - client->PutLootInInventory(SlotCursor, *inst, bag_item_data); + client->PutLootInInventory(EQEmu::legacy::SlotCursor, *inst, bag_item_data); } else { - client->PutLootInInventory(SlotCursor, *inst, bag_item_data); + client->PutLootInInventory(EQEmu::legacy::SlotCursor, *inst, bag_item_data); } /* Update any tasks that have an activity to loot this item */ @@ -1210,7 +1210,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { /* Remove Bag Contents */ if (item->ItemClass == ItemClassContainer && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) { - for (int i = SUB_INDEX_BEGIN; i < EQEmu::constants::ITEM_CONTAINER_SIZE; i++) { + for (int i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { if (bag_item_data[i]) { /* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */ database.DeleteItemOffCharacterCorpse(this->corpse_db_id, bag_item_data[i]->equip_slot, bag_item_data[i]->item_id); @@ -1294,13 +1294,13 @@ void Corpse::QueryLoot(Client* to) { cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::limits::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()), TypeCorpse); + int corpselootlimit = EQEmu::limits::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()), EQEmu::legacy::TypeCorpse); for(; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; if (IsPlayerCorpse()) { - if (sitem->equip_slot >= EQEmu::constants::GENERAL_BAGS_BEGIN && sitem->equip_slot <= EQEmu::constants::CURSOR_BAG_END) + if (sitem->equip_slot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && sitem->equip_slot <= EQEmu::legacy::CURSOR_BAG_END) sitem->lootslot = 0xFFFF; else x < corpselootlimit ? sitem->lootslot = x : sitem->lootslot = 0xFFFF; @@ -1402,7 +1402,7 @@ void Corpse::Spawn() { uint32 Corpse::GetEquipment(uint8 material_slot) const { int16 invslot; - if(material_slot > EQEmu::constants::MATERIAL_END) { + if (material_slot > EQEmu::legacy::MATERIAL_END) { return NO_ITEM; } @@ -1416,7 +1416,7 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { const Item_Struct *item; - if(material_slot > EQEmu::constants::MATERIAL_END) { + if (material_slot > EQEmu::legacy::MATERIAL_END) { return 0; } @@ -1436,8 +1436,8 @@ void Corpse::UpdateEquipmentLight() m_Light.Level.Equipment = 0; for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) { - if (((*iter)->equip_slot < EQEmu::constants::EQUIPMENT_BEGIN || (*iter)->equip_slot > EQEmu::constants::EQUIPMENT_END) && (*iter)->equip_slot != SlotPowerSource) { continue; } - if ((*iter)->equip_slot == SlotAmmo) { continue; } + if (((*iter)->equip_slot < EQEmu::legacy::EQUIPMENT_BEGIN || (*iter)->equip_slot > EQEmu::legacy::EQUIPMENT_END) && (*iter)->equip_slot != EQEmu::legacy::SlotPowerSource) { continue; } + if ((*iter)->equip_slot == EQEmu::legacy::SlotAmmo) { continue; } auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } @@ -1448,7 +1448,7 @@ void Corpse::UpdateEquipmentLight() uint8 general_light_type = 0; for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) { - if ((*iter)->equip_slot < EQEmu::constants::GENERAL_BEGIN || (*iter)->equip_slot > EQEmu::constants::GENERAL_END) { continue; } + if ((*iter)->equip_slot < EQEmu::legacy::GENERAL_BEGIN || (*iter)->equip_slot > EQEmu::legacy::GENERAL_END) { continue; } auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } diff --git a/zone/corpse.h b/zone/corpse.h index 365084b43..d96a38bdd 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -49,7 +49,7 @@ class Corpse : public Mob { /* Corpse: General */ virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } - virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } + virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } diff --git a/zone/doors.cpp b/zone/doors.cpp index a12c74fd0..0a5227988 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -187,7 +187,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) uint8 keepoffkeyring = GetNoKeyring(); uint32 haskey = 0; uint32 playerkey = 0; - const ItemInst *lockpicks = sender->GetInv().GetItem(SlotCursor); + const ItemInst *lockpicks = sender->GetInv().GetItem(EQEmu::legacy::SlotCursor); haskey = sender->GetInv().HasItem(keyneeded, 1); diff --git a/zone/encounter.h b/zone/encounter.h index aa22d3870..05c1b075b 100644 --- a/zone/encounter.h +++ b/zone/encounter.h @@ -36,7 +36,7 @@ public: //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } - virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } diff --git a/zone/entity.h b/zone/entity.h index f373e4251..90a372af8 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -322,7 +322,7 @@ public: void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app); void QueueManaged(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, bool ackreq = true); - void AEAttack(Mob *attacker, float dist, int Hand = SlotPrimary, int count = 0, bool IsFromSpell = false); + void AEAttack(Mob *attacker, float dist, int Hand = EQEmu::legacy::SlotPrimary, int count = 0, bool IsFromSpell = false); void AETaunt(Client *caster, float range=0, int32 bonus_hate=0); void AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true, int16 resist_adjust = 0); void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true); diff --git a/zone/forage.cpp b/zone/forage.cpp index 7241b312a..0a9f81e77 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -153,7 +153,7 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, //we need this function to immediately determine, after we receive OP_Fishing, if we can even try to fish, otherwise we have to wait a while to get the failure bool Client::CanFish() { //make sure we still have a fishing pole on: - const ItemInst* Pole = m_inv[SlotPrimary]; + const ItemInst* Pole = m_inv[EQEmu::legacy::SlotPrimary]; int32 bslot = m_inv.HasItemByUse(ItemTypeFishingBait, 1, invWhereWorn|invWherePersonal); const ItemInst* Bait = nullptr; if (bslot != INVALID_INDEX) @@ -258,7 +258,7 @@ void Client::GoFish() Bait = m_inv.GetItem(bslot); //if the bait isnt equipped, need to add its skill bonus - if (bslot >= EQEmu::constants::GENERAL_BEGIN && Bait != nullptr && Bait->GetItem()->SkillModType == SkillFishing) { + if (bslot >= EQEmu::legacy::GENERAL_BEGIN && Bait != nullptr && Bait->GetItem()->SkillModType == SkillFishing) { fishing_skill += Bait->GetItem()->SkillModValue; } @@ -317,12 +317,12 @@ void Client::GoFish() else { PushItemOnCursor(*inst); - SendItemPacket(SlotCursor, inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketSummonItem); if(RuleB(TaskSystem, EnableTaskSystem)) UpdateTasksForItem(ActivityFish, food_id); safe_delete(inst); - inst = m_inv.GetItem(SlotCursor); + inst = m_inv.GetItem(EQEmu::legacy::SlotCursor); } if(inst) { @@ -354,7 +354,7 @@ void Client::GoFish() //and then swap out items in primary slot... too lazy to fix right now if (zone->random.Int(0, 49) == 1) { Message_StringID(MT_Skills, FISHING_POLE_BROKE); //Your fishing pole broke! - DeleteItemInInventory(SlotPrimary, 0, true); + DeleteItemInInventory(EQEmu::legacy::SlotPrimary, 0, true); } if(CheckIncreaseSkill(SkillFishing, nullptr, 5)) @@ -433,12 +433,12 @@ void Client::ForageItem(bool guarantee) { } else { PushItemOnCursor(*inst); - SendItemPacket(SlotCursor, inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketSummonItem); if(RuleB(TaskSystem, EnableTaskSystem)) UpdateTasksForItem(ActivityForage, foragedfood); safe_delete(inst); - inst = m_inv.GetItem(SlotCursor); + inst = m_inv.GetItem(EQEmu::legacy::SlotCursor); } if(inst) { diff --git a/zone/inventory.cpp b/zone/inventory.cpp index ddba7d13f..9d7c72f14 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -35,7 +35,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { int i; if(where_to_check & invWhereWorn) { - for (i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; i++) { + for (i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -48,8 +48,8 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - if (GetItemIDAt(SlotPowerSource) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(SlotPowerSource) != INVALID_ID)) { - cur = m_inv.GetItem(SlotPowerSource); + if (GetItemIDAt(EQEmu::legacy::SlotPowerSource) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(EQEmu::legacy::SlotPowerSource) != INVALID_ID)) { + cur = m_inv.GetItem(EQEmu::legacy::SlotPowerSource); if(cur && cur->GetItem()->Stackable) { x += cur->GetCharges(); } else { @@ -57,25 +57,25 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) - DeleteItemInInventory(SlotPowerSource, 0, true); + DeleteItemInInventory(EQEmu::legacy::SlotPowerSource, 0, true); else - DeleteItemInInventory(SlotPowerSource, 0, false); // Prevents Titanium crash + DeleteItemInInventory(EQEmu::legacy::SlotPowerSource, 0, false); // Prevents Titanium crash } } if(where_to_check & invWhereCursor) { - if (GetItemIDAt(SlotCursor) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(SlotCursor) != INVALID_ID)) { - cur = m_inv.GetItem(SlotCursor); + if (GetItemIDAt(EQEmu::legacy::SlotCursor) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(EQEmu::legacy::SlotCursor) != INVALID_ID)) { + cur = m_inv.GetItem(EQEmu::legacy::SlotCursor); if(cur && cur->GetItem()->Stackable) { x += cur->GetCharges(); } else { x++; } - DeleteItemInInventory(SlotCursor, 0, true); + DeleteItemInInventory(EQEmu::legacy::SlotCursor, 0, true); } - for (i = EQEmu::constants::CURSOR_BAG_BEGIN; i <= EQEmu::constants::CURSOR_BAG_END; i++) { + for (i = EQEmu::legacy::CURSOR_BAG_BEGIN; i <= EQEmu::legacy::CURSOR_BAG_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -90,7 +90,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if(where_to_check & invWherePersonal) { - for (i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { + for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -103,7 +103,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - for (i = EQEmu::constants::GENERAL_BAGS_BEGIN; i <= EQEmu::constants::GENERAL_BAGS_END; i++) { + for (i = EQEmu::legacy::GENERAL_BAGS_BEGIN; i <= EQEmu::legacy::GENERAL_BAGS_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -118,7 +118,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if(where_to_check & invWhereBank) { - for (i = EQEmu::constants::BANK_BEGIN; i <= EQEmu::constants::BANK_END; i++) { + for (i = EQEmu::legacy::BANK_BEGIN; i <= EQEmu::legacy::BANK_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -131,7 +131,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - for (i = EQEmu::constants::BANK_BAGS_BEGIN; i <= EQEmu::constants::BANK_BAGS_END; i++) { + for (i = EQEmu::legacy::BANK_BAGS_BEGIN; i <= EQEmu::legacy::BANK_BAGS_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -146,7 +146,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if(where_to_check & invWhereSharedBank) { - for (i = EQEmu::constants::SHARED_BANK_BEGIN; i <= EQEmu::constants::SHARED_BANK_END; i++) { + for (i = EQEmu::legacy::SHARED_BANK_BEGIN; i <= EQEmu::legacy::SHARED_BANK_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -159,7 +159,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - for (i = EQEmu::constants::SHARED_BANK_BAGS_BEGIN; i <= EQEmu::constants::SHARED_BANK_BAGS_END; i++) { + for (i = EQEmu::legacy::SHARED_BANK_BAGS_BEGIN; i <= EQEmu::legacy::SHARED_BANK_BAGS_END; i++) { if (GetItemIDAt(i) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(i) != INVALID_ID)) { cur = m_inv.GetItem(i); if(cur && cur->GetItem()->Stackable) { @@ -236,7 +236,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, } */ - uint32 augments[EQEmu::constants::ITEM_COMMON_SIZE] = { aug1, aug2, aug3, aug4, aug5, aug6 }; + uint32 augments[EQEmu::legacy::ITEM_COMMON_SIZE] = { aug1, aug2, aug3, aug4, aug5, aug6 }; uint32 classes = item->Classes; uint32 races = item->Races; @@ -246,7 +246,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, bool enforcerestr = RuleB(Inventory, EnforceAugmentRestriction); bool enforceusable = RuleB(Inventory, EnforceAugmentUsability); - for (int iter = AUG_INDEX_BEGIN; iter < EQEmu::constants::ITEM_COMMON_SIZE; ++iter) { + for (int iter = AUG_INDEX_BEGIN; iter < EQEmu::legacy::ITEM_COMMON_SIZE; ++iter) { const Item_Struct* augtest = database.GetItem(augments[iter]); if(augtest == nullptr) { @@ -540,7 +540,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, } // add any validated augments - for (int iter = AUG_INDEX_BEGIN; iter < EQEmu::constants::ITEM_COMMON_SIZE; ++iter) { + for (int iter = AUG_INDEX_BEGIN; iter < EQEmu::legacy::ITEM_COMMON_SIZE; ++iter) { if(augments[iter]) inst->PutAugment(&database, iter, augments[iter]); } @@ -554,22 +554,22 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, inst->SetOrnamentHeroModel(ornament_hero_model); // check to see if item is usable in requested slot - if(enforceusable && (((to_slot >= SlotCharm) && (to_slot <= SlotAmmo)) || (to_slot == SlotPowerSource))) { - uint32 slottest = (to_slot == SlotPowerSource) ? 22 : to_slot; // can't change '22' just yet... + if (enforceusable && (((to_slot >= EQEmu::legacy::SlotCharm) && (to_slot <= EQEmu::legacy::SlotAmmo)) || (to_slot == EQEmu::legacy::SlotPowerSource))) { + uint32 slottest = (to_slot == EQEmu::legacy::SlotPowerSource) ? 22 : to_slot; // can't change '22' just yet... if(!(slots & ((uint32)1 << slottest))) { Message(0, "This item is not equipable at slot %u - moving to cursor.", to_slot); Log.Out(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to equip an item unusable in slot %u - moved to cursor.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", GetName(), account_name, to_slot, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); - to_slot = SlotCursor; + to_slot = EQEmu::legacy::SlotCursor; } } // put item into inventory - if (to_slot == SlotCursor) { + if (to_slot == EQEmu::legacy::SlotCursor) { PushItemOnCursor(*inst); - SendItemPacket(SlotCursor, inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketSummonItem); } else { PutItemInInventory(to_slot, *inst, true); @@ -617,7 +617,7 @@ void Client::DropItem(int16 slot_id) } // Save client inventory change to database - if (slot_id == SlotCursor) { + if (slot_id == EQEmu::legacy::SlotCursor) { SendCursorBuffer(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(CharacterID(), s, e); @@ -706,11 +706,11 @@ void Client::SendCursorBuffer() GetName(), test_item->Name, test_item->ID); Message_StringID(MT_LootMessages, 290); parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); - DeleteItemInInventory(SlotCursor); + DeleteItemInInventory(EQEmu::legacy::SlotCursor); SendCursorBuffer(); } else { - SendItemPacket(SlotCursor, test_inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, test_inst, ItemPacketSummonItem); } } @@ -788,7 +788,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd bool isDeleted = m_inv.DeleteItem(slot_id, quantity); const ItemInst* inst = nullptr; - if (slot_id == SlotCursor) { + if (slot_id == EQEmu::legacy::SlotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); if(update_db) database.SaveCursor(character_id, s, e); @@ -840,7 +840,7 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update) m_inv.PushCursor(inst); if (client_update) { - SendItemPacket(SlotCursor, &inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, &inst, ItemPacketSummonItem); } auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); @@ -854,7 +854,7 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update) bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client_update) { Log.Out(Logs::Detail, Logs::Inventory, "Putting item %s (%d) into slot %d", inst.GetItem()->Name, inst.GetItem()->ID, slot_id); - if (slot_id == SlotCursor) { // don't trust macros before conditional statements... + if (slot_id == EQEmu::legacy::SlotCursor) { // don't trust macros before conditional statements... return PushItemOnCursor(inst, client_update); } else { @@ -863,11 +863,11 @@ bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client if (client_update) { - SendItemPacket(slot_id, &inst, ((slot_id == SlotCursor) ? ItemPacketSummonItem : ItemPacketTrade)); + SendItemPacket(slot_id, &inst, ((slot_id == EQEmu::legacy::SlotCursor) ? ItemPacketSummonItem : ItemPacketTrade)); //SendWearChange(Inventory::CalcMaterialFromSlot(slot_id)); } - if (slot_id == SlotCursor) { + if (slot_id == EQEmu::legacy::SlotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); return database.SaveCursor(this->CharacterID(), s, e); } @@ -885,7 +885,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI bool cursor_empty = m_inv.CursorEmpty(); - if (slot_id == SlotCursor) { + if (slot_id == EQEmu::legacy::SlotCursor) { m_inv.PushCursor(inst); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(this->CharacterID(), s, e); @@ -896,7 +896,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI } // Subordinate items in cursor buffer must be sent via ItemPacketSummonItem or we just overwrite the visible cursor and desync the client - if (slot_id == SlotCursor && !cursor_empty) { + if (slot_id == EQEmu::legacy::SlotCursor && !cursor_empty) { // RoF+ currently has a specialized cursor handler if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendItemPacket(slot_id, &inst, ItemPacketSummonItem); @@ -906,7 +906,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI } if (bag_item_data) { - for (int index = 0; index < EQEmu::constants::ITEM_CONTAINER_SIZE; ++index) { + for (int index = 0; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { if (bag_item_data[index] == nullptr) continue; @@ -924,12 +924,12 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI // Dump bag contents to cursor in the event that owning bag is not the first cursor item // (This assumes that the data passed is correctly associated..no safety checks are implemented) - if (slot_id == SlotCursor && !cursor_empty) { + if (slot_id == EQEmu::legacy::SlotCursor && !cursor_empty) { Log.Out(Logs::Detail, Logs::Inventory, "Putting bag loot item %s (%d) into slot %d (non-empty cursor override)", - inst.GetItem()->Name, inst.GetItem()->ID, SlotCursor); + inst.GetItem()->Name, inst.GetItem()->ID, EQEmu::legacy::SlotCursor); - PutLootInInventory(SlotCursor, *bagitem); + PutLootInInventory(EQEmu::legacy::SlotCursor, *bagitem); } else { auto bag_slot = Inventory::CalcSlotId(slot_id, index); @@ -951,7 +951,7 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur return false; int16 i; uint32 item_id = item->GetItem()->ID; - for (i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { + for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { ItemInst* tmp_inst = m_inv.GetItem(i); if(tmp_inst && tmp_inst->GetItem()->ID == item_id && tmp_inst->GetCharges() < tmp_inst->GetItem()->StackSize){ MoveItemCharges(*item, i, type); @@ -962,8 +962,8 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur return true; } } - for (i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { - for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::constants::ITEM_CONTAINER_SIZE; j++) { + for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { + for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::legacy::ITEM_CONTAINER_SIZE; j++) { uint16 slotid = Inventory::CalcSlotId(i, j); ItemInst* tmp_inst = m_inv.GetItem(slotid); @@ -988,29 +988,29 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs // #1: Try to auto equip if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level && (!inst.GetItem()->Attuneable || inst.IsAttuned()) && inst.GetItem()->ItemType != ItemTypeAugmentation) { // too messy as-is... - for (int16 i = EQEmu::constants::EQUIPMENT_BEGIN; i < SlotPowerSource; i++) { // originally (i < 22) - if (i == EQEmu::constants::GENERAL_BEGIN) { + for (int16 i = EQEmu::legacy::EQUIPMENT_BEGIN; i < EQEmu::legacy::SlotPowerSource; i++) { // originally (i < 22) + if (i == EQEmu::legacy::GENERAL_BEGIN) { // added power source check for SoF+ clients if (this->ClientVersion() >= EQEmu::versions::ClientVersion::SoF) - i = SlotPowerSource; + i = EQEmu::legacy::SlotPowerSource; else break; } if (!m_inv[i]) { - if (i == SlotPrimary && inst.IsWeapon()) { // If item is primary slot weapon + if (i == EQEmu::legacy::SlotPrimary && inst.IsWeapon()) { // If item is primary slot weapon if ((inst.GetItem()->ItemType == ItemType2HSlash) || (inst.GetItem()->ItemType == ItemType2HBlunt) || (inst.GetItem()->ItemType == ItemType2HPiercing)) { // and uses 2hs \ 2hb \ 2hp - if (m_inv[SlotSecondary]) { // and if secondary slot is not empty + if (m_inv[EQEmu::legacy::SlotSecondary]) { // and if secondary slot is not empty continue; // Can't auto-equip } } } - if (i == SlotSecondary && m_inv[SlotPrimary]) { // check to see if primary slot is a two hander - uint8 use = m_inv[SlotPrimary]->GetItem()->ItemType; + if (i == EQEmu::legacy::SlotSecondary && m_inv[EQEmu::legacy::SlotPrimary]) { // check to see if primary slot is a two hander + uint8 use = m_inv[EQEmu::legacy::SlotPrimary]->GetItem()->ItemType; if (use == ItemType2HSlash || use == ItemType2HBlunt || use == ItemType2HPiercing) continue; } - if (i == SlotSecondary && inst.IsWeapon() && !CanThisClassDualWield()) { + if (i == EQEmu::legacy::SlotSecondary && inst.IsWeapon() && !CanThisClassDualWield()) { continue; } @@ -1018,7 +1018,7 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs //send worn to everyone... PutLootInInventory(i, inst); uint8 worn_slot_material = Inventory::CalcMaterialFromSlot(i); - if (worn_slot_material != MaterialInvalid) { + if (worn_slot_material != EQEmu::legacy::MaterialInvalid) { SendWearChange(worn_slot_material); } @@ -1061,7 +1061,7 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type) tmp_inst->SetCharges(tmp_inst->GetCharges() + charges_to_move); from.SetCharges(from.GetCharges() - charges_to_move); SendLootItemInPacket(tmp_inst, to_slot); - if (to_slot == SlotCursor) { + if (to_slot == EQEmu::legacy::SlotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(this->CharacterID(), s, e); } @@ -1318,16 +1318,16 @@ void Client::SendLootItemInPacket(const ItemInst* inst, int16 slot_id) bool Client::IsValidSlot(uint32 slot) { if ((slot == (uint32)INVALID_INDEX) || - (slot >= SLOT_BEGIN && slot < EQEmu::constants::TYPE_POSSESSIONS_SIZE) || - (slot >= EQEmu::constants::GENERAL_BAGS_BEGIN && slot <= EQEmu::constants::CURSOR_BAG_END) || - (slot >= EQEmu::constants::TRIBUTE_BEGIN && slot <= EQEmu::constants::TRIBUTE_END) || - (slot >= EQEmu::constants::BANK_BEGIN && slot <= EQEmu::constants::BANK_END) || - (slot >= EQEmu::constants::BANK_BAGS_BEGIN && slot <= EQEmu::constants::BANK_BAGS_END) || - (slot >= EQEmu::constants::SHARED_BANK_BEGIN && slot <= EQEmu::constants::SHARED_BANK_END) || - (slot >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && slot <= EQEmu::constants::SHARED_BANK_BAGS_END) || - (slot >= EQEmu::constants::TRADE_BEGIN && slot <= EQEmu::constants::TRADE_END) || - (slot >= EQEmu::constants::WORLD_BEGIN && slot <= EQEmu::constants::WORLD_END) || - (slot == SlotPowerSource) + (slot >= SLOT_BEGIN && slot < EQEmu::legacy::TYPE_POSSESSIONS_SIZE) || + (slot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot <= EQEmu::legacy::CURSOR_BAG_END) || + (slot >= EQEmu::legacy::TRIBUTE_BEGIN && slot <= EQEmu::legacy::TRIBUTE_END) || + (slot >= EQEmu::legacy::BANK_BEGIN && slot <= EQEmu::legacy::BANK_END) || + (slot >= EQEmu::legacy::BANK_BAGS_BEGIN && slot <= EQEmu::legacy::BANK_BAGS_END) || + (slot >= EQEmu::legacy::SHARED_BANK_BEGIN && slot <= EQEmu::legacy::SHARED_BANK_END) || + (slot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot <= EQEmu::legacy::SHARED_BANK_BAGS_END) || + (slot >= EQEmu::legacy::TRADE_BEGIN && slot <= EQEmu::legacy::TRADE_END) || + (slot >= EQEmu::legacy::WORLD_BEGIN && slot <= EQEmu::legacy::WORLD_END) || + (slot == EQEmu::legacy::SlotPowerSource) ) { return true; } @@ -1338,10 +1338,10 @@ bool Client::IsValidSlot(uint32 slot) { bool Client::IsBankSlot(uint32 slot) { - if ((slot >= EQEmu::constants::BANK_BEGIN && slot <= EQEmu::constants::BANK_END) || - (slot >= EQEmu::constants::BANK_BAGS_BEGIN && slot <= EQEmu::constants::BANK_BAGS_END) || - (slot >= EQEmu::constants::SHARED_BANK_BEGIN && slot <= EQEmu::constants::SHARED_BANK_END) || - (slot >= EQEmu::constants::SHARED_BANK_BAGS_BEGIN && slot <= EQEmu::constants::SHARED_BANK_BAGS_END)) + if ((slot >= EQEmu::legacy::BANK_BEGIN && slot <= EQEmu::legacy::BANK_END) || + (slot >= EQEmu::legacy::BANK_BAGS_BEGIN && slot <= EQEmu::legacy::BANK_BAGS_END) || + (slot >= EQEmu::legacy::SHARED_BANK_BEGIN && slot <= EQEmu::legacy::SHARED_BANK_END) || + (slot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot <= EQEmu::legacy::SHARED_BANK_BAGS_END)) { return true; } @@ -1377,8 +1377,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { return true; } // Can't do RoF+ - if (move_in->to_slot == SlotCursor) { - auto test_inst = m_inv.GetItem(SlotCursor); + if (move_in->to_slot == EQEmu::legacy::SlotCursor) { + auto test_inst = m_inv.GetItem(EQEmu::legacy::SlotCursor); if (test_inst == nullptr) { return true; } auto test_item = test_inst->GetItem(); if (test_item == nullptr) { return true; } @@ -1397,18 +1397,18 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { GetName(), test_item->Name, test_item->ID); Message_StringID(MT_LootMessages, 290); parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); - DeleteItemInInventory(SlotCursor, 0, true); + DeleteItemInInventory(EQEmu::legacy::SlotCursor, 0, true); } } return true; } if (move_in->to_slot == (uint32)INVALID_INDEX) { - if (move_in->from_slot == (uint32)SlotCursor) { + if (move_in->from_slot == (uint32)EQEmu::legacy::SlotCursor) { Log.Out(Logs::Detail, Logs::Inventory, "Client destroyed item from cursor slot %d", move_in->from_slot); if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit - ItemInst *inst = m_inv.GetItem(SlotCursor); + ItemInst *inst = m_inv.GetItem(EQEmu::legacy::SlotCursor); if(inst) { parse->EventItem(EVENT_DESTROY_ITEM, this, inst, nullptr, "", 0); } @@ -1425,9 +1425,9 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return true; // Item deletion } } - if(auto_attack && (move_in->from_slot == SlotPrimary || move_in->from_slot == SlotSecondary || move_in->from_slot == SlotRange)) + if (auto_attack && (move_in->from_slot == EQEmu::legacy::SlotPrimary || move_in->from_slot == EQEmu::legacy::SlotSecondary || move_in->from_slot == EQEmu::legacy::SlotRange)) SetAttackTimer(); - else if(auto_attack && (move_in->to_slot == SlotPrimary || move_in->to_slot == SlotSecondary || move_in->to_slot == SlotRange)) + else if (auto_attack && (move_in->to_slot == EQEmu::legacy::SlotPrimary || move_in->to_slot == EQEmu::legacy::SlotSecondary || move_in->to_slot == EQEmu::legacy::SlotRange)) SetAttackTimer(); // Step 1: Variables int16 src_slot_id = (int16)move_in->from_slot; @@ -1475,13 +1475,13 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { uint32 dstbagid = 0; //if (src_slot_id >= 250 && src_slot_id < 330) { - if (src_slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && src_slot_id <= EQEmu::constants::GENERAL_BAGS_END) { + if (src_slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && src_slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { srcbag = m_inv.GetItem(((int)(src_slot_id / 10)) - 3); if (srcbag) srcbagid = srcbag->GetItem()->ID; } //if (dst_slot_id >= 250 && dst_slot_id < 330) { - if (dst_slot_id >= EQEmu::constants::GENERAL_BAGS_BEGIN && dst_slot_id <= EQEmu::constants::GENERAL_BAGS_END) { + if (dst_slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && dst_slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { dstbag = m_inv.GetItem(((int)(dst_slot_id / 10)) - 3); if (dstbag) dstbagid = dstbag->GetItem()->ID; @@ -1494,7 +1494,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Step 2: Validate item in from_slot // After this, we can assume src_inst is a valid ptr - if (!src_inst && (src_slot_id < EQEmu::constants::WORLD_BEGIN || src_slot_id > EQEmu::constants::WORLD_END)) { + if (!src_inst && (src_slot_id < EQEmu::legacy::WORLD_BEGIN || src_slot_id > EQEmu::legacy::WORLD_END)) { if (dst_inst) { // If there is no source item, but there is a destination item, // move the slots around before deleting the invalid source slot item, @@ -1508,14 +1508,14 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return false; } //verify shared bank transactions in the database - if(src_inst && src_slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { + if (src_inst && src_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { if(!database.VerifyInventory(account_id, src_slot_id, src_inst)) { Log.Out(Logs::General, Logs::Error, "Player %s on account %s was found exploiting the shared bank.\n", GetName(), account_name); DeleteItemInInventory(dst_slot_id,0,true); return(false); } - if(src_slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::constants::SHARED_BANK_END && src_inst->IsType(ItemClassContainer)){ - for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::constants::ITEM_CONTAINER_SIZE; idx++) { + if (src_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::legacy::SHARED_BANK_END && src_inst->IsType(ItemClassContainer)){ + for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = src_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(src_slot_id, idx), baginst)){ DeleteItemInInventory(Inventory::CalcSlotId(src_slot_id, idx),0,false); @@ -1523,14 +1523,14 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } } } - if(dst_inst && dst_slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END) { + if (dst_inst && dst_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { if(!database.VerifyInventory(account_id, dst_slot_id, dst_inst)) { Log.Out(Logs::General, Logs::Error, "Player %s on account %s was found exploting the shared bank.\n", GetName(), account_name); DeleteItemInInventory(src_slot_id,0,true); return(false); } - if(dst_slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::constants::SHARED_BANK_END && dst_inst->IsType(ItemClassContainer)){ - for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::constants::ITEM_CONTAINER_SIZE; idx++) { + if (dst_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::legacy::SHARED_BANK_END && dst_inst->IsType(ItemClassContainer)){ + for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = dst_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(dst_slot_id, idx), baginst)){ DeleteItemInInventory(Inventory::CalcSlotId(dst_slot_id, idx),0,false); @@ -1542,8 +1542,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Check for No Drop Hacks Mob* with = trade->With(); - if (((with && with->IsClient() && dst_slot_id >= EQEmu::constants::TRADE_BEGIN && dst_slot_id <= EQEmu::constants::TRADE_END) || - (dst_slot_id >= EQEmu::constants::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END)) + if (((with && with->IsClient() && dst_slot_id >= EQEmu::legacy::TRADE_BEGIN && dst_slot_id <= EQEmu::legacy::TRADE_END) || + (dst_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END)) && GetInv().CheckNoDrop(src_slot_id) && RuleI(World, FVNoDropFlag) == 0 || RuleI(Character, MinStatusForNoDropExemptions) < Admin() && RuleI(World, FVNoDropFlag) == 2) { auto ndh_inst = m_inv[src_slot_id]; @@ -1573,7 +1573,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Step 3: Check for interaction with World Container (tradeskills) if(m_tradeskill_object != nullptr) { - if (src_slot_id >= EQEmu::constants::WORLD_BEGIN && src_slot_id <= EQEmu::constants::WORLD_END) { + if (src_slot_id >= EQEmu::legacy::WORLD_BEGIN && src_slot_id <= EQEmu::legacy::WORLD_END) { // Picking up item from world container ItemInst* inst = m_tradeskill_object->PopItem(Inventory::CalcBagIdx(src_slot_id)); if (inst) { @@ -1585,7 +1585,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return true; } - else if (dst_slot_id >= EQEmu::constants::WORLD_BEGIN && dst_slot_id <= EQEmu::constants::WORLD_END) { + else if (dst_slot_id >= EQEmu::legacy::WORLD_BEGIN && dst_slot_id <= EQEmu::legacy::WORLD_END) { // Putting item into world container, which may swap (or pile onto) with existing item uint8 world_idx = Inventory::CalcBagIdx(dst_slot_id); ItemInst* world_inst = m_tradeskill_object->PopItem(world_idx); @@ -1637,7 +1637,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } safe_delete(world_inst); - if (src_slot_id == SlotCursor) + if (src_slot_id == EQEmu::legacy::SlotCursor) { if (dstitemid == 0) { @@ -1658,15 +1658,15 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } // Step 4: Check for entity trade - if (dst_slot_id >= EQEmu::constants::TRADE_BEGIN && dst_slot_id <= EQEmu::constants::TRADE_END) { - if (src_slot_id != SlotCursor) { + if (dst_slot_id >= EQEmu::legacy::TRADE_BEGIN && dst_slot_id <= EQEmu::legacy::TRADE_END) { + if (src_slot_id != EQEmu::legacy::SlotCursor) { Kick(); return false; } if (with) { Log.Out(Logs::Detail, Logs::Inventory, "Trade item move from slot %d to slot %d (trade with %s)", src_slot_id, dst_slot_id, with->GetName()); // Fill Trade list with items from cursor - if (!m_inv[SlotCursor]) { + if (!m_inv[EQEmu::legacy::SlotCursor]) { Message(13, "Error: Cursor item not located on server!"); return false; } @@ -1686,7 +1686,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit SummonItem(src_inst->GetID(), src_inst->GetCharges()); - DeleteItemInInventory(SlotCursor); + DeleteItemInInventory(EQEmu::legacy::SlotCursor); return true; } @@ -1751,12 +1751,12 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } else { // Not dealing with charges - just do direct swap - if(src_inst && (dst_slot_id <= EQEmu::constants::EQUIPMENT_END || dst_slot_id == SlotPowerSource) && dst_slot_id >= EQEmu::constants::EQUIPMENT_BEGIN) { + if (src_inst && (dst_slot_id <= EQEmu::legacy::EQUIPMENT_END || dst_slot_id == EQEmu::legacy::SlotPowerSource) && dst_slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN) { if (src_inst->GetItem()->Attuneable) { src_inst->SetAttuned(true); } if (src_inst->IsAugmented()) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { if (src_inst->GetAugment(i)) { if (src_inst->GetAugment(i)->GetItem()->Attuneable) { src_inst->GetAugment(i)->SetAttuned(true); @@ -1769,7 +1769,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(!m_inv.SwapItem(src_slot_id, dst_slot_id)) { return false; } Log.Out(Logs::Detail, Logs::Inventory, "Moving entire item from slot %d to slot %d", src_slot_id, dst_slot_id); - if(src_slot_id <= EQEmu::constants::EQUIPMENT_END || src_slot_id == SlotPowerSource) { + if (src_slot_id <= EQEmu::legacy::EQUIPMENT_END || src_slot_id == EQEmu::legacy::SlotPowerSource) { if(src_inst) { parse->EventItem(EVENT_UNEQUIP_ITEM, this, src_inst, nullptr, "", src_slot_id); } @@ -1779,7 +1779,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } } - if(dst_slot_id <= EQEmu::constants::EQUIPMENT_END || dst_slot_id == SlotPowerSource) { + if (dst_slot_id <= EQEmu::legacy::EQUIPMENT_END || dst_slot_id == EQEmu::legacy::SlotPowerSource) { if(dst_inst) { parse->EventItem(EVENT_UNEQUIP_ITEM, this, dst_inst, nullptr, "", dst_slot_id); } @@ -1791,12 +1791,12 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } int matslot = SlotConvert2(dst_slot_id); - if (dst_slot_id <= EQEmu::constants::EQUIPMENT_END && matslot != MaterialHead) { // think this is to allow the client to update with /showhelm + if (dst_slot_id <= EQEmu::legacy::EQUIPMENT_END && matslot != EQEmu::legacy::MaterialHead) { // think this is to allow the client to update with /showhelm SendWearChange(matslot); } // Step 7: Save change to the database - if (src_slot_id == SlotCursor) { + if (src_slot_id == EQEmu::legacy::SlotCursor) { // If not swapping another item to cursor and stacking items were depleted if (dstitemid == 0 || all_to_stack == true) { @@ -1809,7 +1809,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { database.SaveInventory(character_id, m_inv.GetItem(src_slot_id), src_slot_id); } - if (dst_slot_id == SlotCursor) { + if (dst_slot_id == EQEmu::legacy::SlotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(character_id, s, e); } @@ -1833,7 +1833,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { Log.Out(Logs::Detail, Logs::Inventory, "Inventory desyncronization. (charname: %s, source: %i, destination: %i)", GetName(), move_slots->from_slot, move_slots->to_slot); Message(15, "Inventory Desyncronization detected: Resending slot data..."); - if((move_slots->from_slot >= EQEmu::constants::EQUIPMENT_BEGIN && move_slots->from_slot <= EQEmu::constants::CURSOR_BAG_END) || move_slots->from_slot == SlotPowerSource) { + if ((move_slots->from_slot >= EQEmu::legacy::EQUIPMENT_BEGIN && move_slots->from_slot <= EQEmu::legacy::CURSOR_BAG_END) || move_slots->from_slot == EQEmu::legacy::SlotPowerSource) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { // This prevents the client from crashing when closing any 'phantom' bags @@ -1876,7 +1876,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); } } - if((move_slots->to_slot >= EQEmu::constants::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::constants::CURSOR_BAG_END) || move_slots->to_slot == SlotPowerSource) { + if ((move_slots->to_slot >= EQEmu::legacy::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::legacy::CURSOR_BAG_END) || move_slots->to_slot == EQEmu::legacy::SlotPowerSource) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' @@ -2019,7 +2019,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { void Client::DyeArmor(DyeStruct* dye){ int16 slot=0; - for (int i = EQEmu::constants::MATERIAL_BEGIN; i <= EQEmu::constants::MATERIAL_TINT_END; i++) { + for (int i = EQEmu::legacy::MATERIAL_BEGIN; i <= EQEmu::legacy::MATERIAL_TINT_END; i++) { if ((m_pp.item_tint[i].Color & 0x00FFFFFF) != (dye->dye[i].Color & 0x00FFFFFF)) { slot = m_inv.HasItem(32557, 1, invWherePersonal); if (slot != INVALID_INDEX){ @@ -2058,7 +2058,7 @@ bool Client::DecreaseByItemType(uint32 type, uint8 amt) { const Item_Struct* TempItem = 0; ItemInst* ins; int x; - for(x=EQEmu::constants::POSSESSIONS_BEGIN; x <= EQEmu::constants::POSSESSIONS_END; x++) + for(x=EQEmu::legacy::POSSESSIONS_BEGIN; x <= EQEmu::legacy::POSSESSIONS_END; x++) { TempItem = 0; ins = GetInv().GetItem(x); @@ -2080,7 +2080,7 @@ bool Client::DecreaseByItemType(uint32 type, uint8 amt) { return true; } } - for(x=EQEmu::constants::GENERAL_BAGS_BEGIN; x <= EQEmu::constants::GENERAL_BAGS_END; x++) + for(x=EQEmu::legacy::GENERAL_BAGS_BEGIN; x <= EQEmu::legacy::GENERAL_BAGS_END; x++) { TempItem = 0; ins = GetInv().GetItem(x); @@ -2111,10 +2111,10 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) { ItemInst* ins = nullptr; int x; int num = 0; - for(x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::GENERAL_BAGS_END; x++) + for(x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::GENERAL_BAGS_END; x++) { - if (x == SlotCursor + 1) - x = EQEmu::constants::GENERAL_BAGS_BEGIN; + if (x == EQEmu::legacy::SlotCursor + 1) + x = EQEmu::legacy::GENERAL_BAGS_BEGIN; TempItem = nullptr; ins = GetInv().GetItem(x); if (ins) @@ -2128,10 +2128,10 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) { } if (num < amt) return false; - for(x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::GENERAL_BAGS_END; x++) // should this be CURSOR_BAG_END? + for(x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::GENERAL_BAGS_END; x++) // should this be CURSOR_BAG_END? { - if (x == SlotCursor + 1) - x = EQEmu::constants::GENERAL_BAGS_BEGIN; + if (x == EQEmu::legacy::SlotCursor + 1) + x = EQEmu::legacy::GENERAL_BAGS_BEGIN; TempItem = nullptr; ins = GetInv().GetItem(x); if (ins) @@ -2227,7 +2227,7 @@ static bool CopyBagContents(ItemInst* new_bag, const ItemInst* old_bag) void Client::DisenchantSummonedBags(bool client_update) { - for (auto slot_id = EQEmu::constants::GENERAL_BEGIN; slot_id <= EQEmu::constants::GENERAL_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::GENERAL_BEGIN; slot_id <= EQEmu::legacy::GENERAL_END; ++slot_id) { auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } @@ -2248,7 +2248,7 @@ void Client::DisenchantSummonedBags(bool client_update) safe_delete(new_inst); } - for (auto slot_id = EQEmu::constants::BANK_BEGIN; slot_id <= EQEmu::constants::BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::BANK_BEGIN; slot_id <= EQEmu::legacy::BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } @@ -2269,7 +2269,7 @@ void Client::DisenchantSummonedBags(bool client_update) safe_delete(new_inst); } - for (auto slot_id = EQEmu::constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::constants::SHARED_BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::SHARED_BANK_BEGIN; slot_id <= EQEmu::legacy::SHARED_BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } @@ -2291,7 +2291,7 @@ void Client::DisenchantSummonedBags(bool client_update) } while (!m_inv.CursorEmpty()) { - auto inst = m_inv[SlotCursor]; + auto inst = m_inv[EQEmu::legacy::SlotCursor]; if (!inst) { break; } if (!IsSummonedBagID(inst->GetItem()->ID)) { break; } if (inst->GetItem()->ItemClass != ItemClassContainer) { break; } @@ -2305,14 +2305,14 @@ void Client::DisenchantSummonedBags(bool client_update) if (!new_inst) { break; } if (CopyBagContents(new_inst, inst)) { - Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, SlotCursor); + Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, EQEmu::legacy::SlotCursor); std::list local; local.push_front(new_inst); - m_inv.PopItem(SlotCursor); + m_inv.PopItem(EQEmu::legacy::SlotCursor); safe_delete(inst); while (!m_inv.CursorEmpty()) { - auto limbo_inst = m_inv.PopItem(SlotCursor); + auto limbo_inst = m_inv.PopItem(EQEmu::legacy::SlotCursor); if (limbo_inst == nullptr) { continue; } local.push_back(limbo_inst); } @@ -2338,7 +2338,7 @@ void Client::DisenchantSummonedBags(bool client_update) void Client::RemoveNoRent(bool client_update) { - for (auto slot_id = EQEmu::constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::constants::EQUIPMENT_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::EQUIPMENT_BEGIN; slot_id <= EQEmu::legacy::EQUIPMENT_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2346,7 +2346,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EQEmu::constants::GENERAL_BEGIN; slot_id <= EQEmu::constants::GENERAL_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::GENERAL_BEGIN; slot_id <= EQEmu::legacy::GENERAL_END; ++slot_id) { auto inst = m_inv[slot_id]; if (inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2354,15 +2354,15 @@ void Client::RemoveNoRent(bool client_update) } } - if (m_inv[SlotPowerSource]) { - auto inst = m_inv[SlotPowerSource]; + if (m_inv[EQEmu::legacy::SlotPowerSource]) { + auto inst = m_inv[EQEmu::legacy::SlotPowerSource]; if (inst && !inst->GetItem()->NoRent) { - Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, SlotPowerSource); - DeleteItemInInventory(SlotPowerSource, 0, (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) ? client_update : false); // Ti slot non-existent + Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, EQEmu::legacy::SlotPowerSource); + DeleteItemInInventory(EQEmu::legacy::SlotPowerSource, 0, (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) ? client_update : false); // Ti slot non-existent } } - for (auto slot_id = EQEmu::constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::constants::CURSOR_BAG_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::legacy::CURSOR_BAG_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2370,7 +2370,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EQEmu::constants::BANK_BEGIN; slot_id <= EQEmu::constants::BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::BANK_BEGIN; slot_id <= EQEmu::legacy::BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2378,7 +2378,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EQEmu::constants::BANK_BAGS_BEGIN; slot_id <= EQEmu::constants::BANK_BAGS_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::BANK_BAGS_BEGIN; slot_id <= EQEmu::legacy::BANK_BAGS_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2386,7 +2386,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EQEmu::constants::SHARED_BANK_BEGIN; slot_id <= EQEmu::constants::SHARED_BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::SHARED_BANK_BEGIN; slot_id <= EQEmu::legacy::SHARED_BANK_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2394,7 +2394,7 @@ void Client::RemoveNoRent(bool client_update) } } - for (auto slot_id = EQEmu::constants::SHARED_BANK_BAGS_BEGIN; slot_id <= EQEmu::constants::SHARED_BANK_BAGS_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::SHARED_BANK_BAGS_BEGIN; slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END; ++slot_id) { auto inst = m_inv[slot_id]; if(inst && !inst->GetItem()->NoRent) { Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id); @@ -2406,7 +2406,7 @@ void Client::RemoveNoRent(bool client_update) std::list local; while (!m_inv.CursorEmpty()) { - auto inst = m_inv.PopItem(SlotCursor); + auto inst = m_inv.PopItem(EQEmu::legacy::SlotCursor); if (inst == nullptr) { continue; } local.push_back(inst); } @@ -2432,7 +2432,7 @@ void Client::RemoveNoRent(bool client_update) // Two new methods to alleviate perpetual login desyncs void Client::RemoveDuplicateLore(bool client_update) { - for (auto slot_id = EQEmu::constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::constants::EQUIPMENT_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::EQUIPMENT_BEGIN; slot_id <= EQEmu::legacy::EQUIPMENT_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2445,7 +2445,7 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - for (auto slot_id = EQEmu::constants::GENERAL_BEGIN; slot_id <= EQEmu::constants::GENERAL_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::GENERAL_BEGIN; slot_id <= EQEmu::legacy::GENERAL_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if (CheckLoreConflict(inst->GetItem())) { @@ -2458,21 +2458,21 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - if (m_inv[SlotPowerSource]) { - auto inst = m_inv.PopItem(SlotPowerSource); + if (m_inv[EQEmu::legacy::SlotPowerSource]) { + auto inst = m_inv.PopItem(EQEmu::legacy::SlotPowerSource); if (inst) { if (CheckLoreConflict(inst->GetItem())) { - Log.Out(Logs::Detail, Logs::Inventory, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, SlotPowerSource); - database.SaveInventory(character_id, nullptr, SlotPowerSource); + Log.Out(Logs::Detail, Logs::Inventory, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, EQEmu::legacy::SlotPowerSource); + database.SaveInventory(character_id, nullptr, EQEmu::legacy::SlotPowerSource); } else { - m_inv.PutItem(SlotPowerSource, *inst); + m_inv.PutItem(EQEmu::legacy::SlotPowerSource, *inst); } safe_delete(inst); } } - for (auto slot_id = EQEmu::constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::constants::CURSOR_BAG_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::legacy::CURSOR_BAG_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2485,7 +2485,7 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - for (auto slot_id = EQEmu::constants::BANK_BEGIN; slot_id <= EQEmu::constants::BANK_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::BANK_BEGIN; slot_id <= EQEmu::legacy::BANK_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2498,7 +2498,7 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - for (auto slot_id = EQEmu::constants::BANK_BAGS_BEGIN; slot_id <= EQEmu::constants::BANK_BAGS_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::BANK_BAGS_BEGIN; slot_id <= EQEmu::legacy::BANK_BAGS_END; ++slot_id) { auto inst = m_inv.PopItem(slot_id); if (inst == nullptr) { continue; } if(CheckLoreConflict(inst->GetItem())) { @@ -2518,7 +2518,7 @@ void Client::RemoveDuplicateLore(bool client_update) std::list local_2; while (!m_inv.CursorEmpty()) { - auto inst = m_inv.PopItem(SlotCursor); + auto inst = m_inv.PopItem(EQEmu::legacy::SlotCursor); if (inst == nullptr) { continue; } local_1.push_back(inst); } @@ -2559,7 +2559,7 @@ void Client::RemoveDuplicateLore(bool client_update) void Client::MoveSlotNotAllowed(bool client_update) { - for (auto slot_id = EQEmu::constants::EQUIPMENT_BEGIN; slot_id <= EQEmu::constants::EQUIPMENT_END; ++slot_id) { + for (auto slot_id = EQEmu::legacy::EQUIPMENT_BEGIN; slot_id <= EQEmu::legacy::EQUIPMENT_END; ++slot_id) { if(m_inv[slot_id] && !m_inv[slot_id]->IsSlotAllowed(slot_id)) { auto inst = m_inv.PopItem(slot_id); bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; @@ -2571,13 +2571,13 @@ void Client::MoveSlotNotAllowed(bool client_update) } } - if (m_inv[SlotPowerSource] && !m_inv[SlotPowerSource]->IsSlotAllowed(SlotPowerSource)) { - auto inst = m_inv.PopItem(SlotPowerSource); + if (m_inv[EQEmu::legacy::SlotPowerSource] && !m_inv[EQEmu::legacy::SlotPowerSource]->IsSlotAllowed(EQEmu::legacy::SlotPowerSource)) { + auto inst = m_inv.PopItem(EQEmu::legacy::SlotPowerSource); bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size, is_arrow); - Log.Out(Logs::Detail, Logs::Inventory, "Slot Assignment Error: Moving %s from slot %i to %i", inst->GetItem()->Name, SlotPowerSource, free_slot_id); + Log.Out(Logs::Detail, Logs::Inventory, "Slot Assignment Error: Moving %s from slot %i to %i", inst->GetItem()->Name, EQEmu::legacy::SlotPowerSource, free_slot_id); PutItemInInventory(free_slot_id, *inst, (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) ? client_update : false); - database.SaveInventory(character_id, nullptr, SlotPowerSource); + database.SaveInventory(character_id, nullptr, EQEmu::legacy::SlotPowerSource); safe_delete(inst); } @@ -2591,7 +2591,7 @@ uint32 Client::GetEquipment(uint8 material_slot) const int16 invslot; const ItemInst *item; - if(material_slot > EQEmu::constants::MATERIAL_END) + if(material_slot > EQEmu::legacy::MATERIAL_END) { return 0; } @@ -2629,7 +2629,7 @@ int32 Client::GetEquipmentMaterial(uint8 material_slot) uint32 Client::GetEquipmentColor(uint8 material_slot) const { - if (material_slot > EQEmu::constants::MATERIAL_END) + if (material_slot > EQEmu::legacy::MATERIAL_END) return 0; const Item_Struct *item = database.GetItem(GetEquipment(material_slot)); @@ -2695,13 +2695,13 @@ static int16 BandolierSlotToWeaponSlot(int BandolierSlot) switch (BandolierSlot) { case bandolierPrimary: - return SlotPrimary; + return EQEmu::legacy::SlotPrimary; case bandolierSecondary: - return SlotSecondary; + return EQEmu::legacy::SlotSecondary; case bandolierRange: - return SlotRange; + return EQEmu::legacy::SlotRange; default: - return SlotAmmo; + return EQEmu::legacy::SlotAmmo; } } @@ -2774,13 +2774,13 @@ void Client::SetBandolier(const EQApplicationPacket *app) // removed 'invWhereCursor' argument from above and implemented slots 30, 331-340 checks here if (slot == INVALID_INDEX) { - if (m_inv.GetItem(SlotCursor)) { - if (m_inv.GetItem(SlotCursor)->GetItem()->ID == m_pp.bandoliers[bss->Number].Items[BandolierSlot].ID && - m_inv.GetItem(SlotCursor)->GetCharges() >= 1) { // '> 0' the same, but this matches Inventory::_HasItem conditional check - slot = SlotCursor; + if (m_inv.GetItem(EQEmu::legacy::SlotCursor)) { + if (m_inv.GetItem(EQEmu::legacy::SlotCursor)->GetItem()->ID == m_pp.bandoliers[bss->Number].Items[BandolierSlot].ID && + m_inv.GetItem(EQEmu::legacy::SlotCursor)->GetCharges() >= 1) { // '> 0' the same, but this matches Inventory::_HasItem conditional check + slot = EQEmu::legacy::SlotCursor; } - else if (m_inv.GetItem(SlotCursor)->GetItem()->ItemClass == 1) { - for(int16 CursorBagSlot = EQEmu::constants::CURSOR_BAG_BEGIN; CursorBagSlot <= EQEmu::constants::CURSOR_BAG_END; CursorBagSlot++) { + else if (m_inv.GetItem(EQEmu::legacy::SlotCursor)->GetItem()->ItemClass == 1) { + for(int16 CursorBagSlot = EQEmu::legacy::CURSOR_BAG_BEGIN; CursorBagSlot <= EQEmu::legacy::CURSOR_BAG_END; CursorBagSlot++) { if (m_inv.GetItem(CursorBagSlot)) { if (m_inv.GetItem(CursorBagSlot)->GetItem()->ID == m_pp.bandoliers[bss->Number].Items[BandolierSlot].ID && m_inv.GetItem(CursorBagSlot)->GetCharges() >= 1) { // ditto @@ -2926,7 +2926,7 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { // if(ItemToReturn->IsStackable()) { - for (int16 i = EQEmu::constants::GENERAL_BEGIN; i <= SlotCursor; i++) { // changed slot max to 30 from 29. client will stack into slot 30 (bags too) before moving. + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::SlotCursor; i++) { // changed slot max to 30 from 29. client will stack into slot 30 (bags too) before moving. ItemInst* InvItem = m_inv.GetItem(i); @@ -2985,7 +2985,7 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { // We have tried stacking items, now just try and find an empty slot. - for (int16 i = EQEmu::constants::GENERAL_BEGIN; i <= SlotCursor; i++) { // changed slot max to 30 from 29. client will move into slot 30 (bags too) before pushing onto cursor. + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::SlotCursor; i++) { // changed slot max to 30 from 29. client will move into slot 30 (bags too) before pushing onto cursor. ItemInst* InvItem = m_inv.GetItem(i); @@ -3046,27 +3046,27 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool std::map instmap; // build reference map - for (int16 index = SLOT_BEGIN; index < EQEmu::constants::TYPE_POSSESSIONS_SIZE; ++index) { + for (int16 index = SLOT_BEGIN; index < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EQEmu::constants::TRIBUTE_BEGIN; index <= EQEmu::constants::TRIBUTE_END; ++index) { + for (int16 index = EQEmu::legacy::TRIBUTE_BEGIN; index <= EQEmu::legacy::TRIBUTE_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EQEmu::constants::BANK_BEGIN; index <= EQEmu::constants::BANK_END; ++index) { + for (int16 index = EQEmu::legacy::BANK_BEGIN; index <= EQEmu::legacy::BANK_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EQEmu::constants::SHARED_BANK_BEGIN; index <= EQEmu::constants::SHARED_BANK_END; ++index) { + for (int16 index = EQEmu::legacy::SHARED_BANK_BEGIN; index <= EQEmu::legacy::SHARED_BANK_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; } - for (int16 index = EQEmu::constants::TRADE_BEGIN; index <= EQEmu::constants::TRADE_END; ++index) { + for (int16 index = EQEmu::legacy::TRADE_BEGIN; index <= EQEmu::legacy::TRADE_END; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; @@ -3074,10 +3074,10 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool auto tsobject = GetTradeskillObject(); if (tsobject != nullptr) { - for (int16 index = SLOT_BEGIN; index < EQEmu::constants::TYPE_WORLD_SIZE; ++index) { + for (int16 index = SLOT_BEGIN; index < EQEmu::legacy::TYPE_WORLD_SIZE; ++index) { auto inst = tsobject->GetItem(index); if (inst == nullptr) { continue; } - instmap[EQEmu::constants::WORLD_BEGIN + index] = inst; + instmap[EQEmu::legacy::WORLD_BEGIN + index] = inst; } } @@ -3090,8 +3090,8 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool instmap[8000 + limbo] = *cursor_itr; } - if (m_inv[SlotPowerSource]) - instmap[SlotPowerSource] = m_inv[SlotPowerSource]; + if (m_inv[EQEmu::legacy::SlotPowerSource]) + instmap[EQEmu::legacy::SlotPowerSource] = m_inv[EQEmu::legacy::SlotPowerSource]; // call InterrogateInventory_ for error check for (std::map::iterator instmap_itr = instmap.begin(); (instmap_itr != instmap.end()) && (!error); ++instmap_itr) { @@ -3149,7 +3149,7 @@ void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 hea } else { if (inst) { - for (int16 sub = SUB_INDEX_BEGIN; (sub < EQEmu::constants::ITEM_CONTAINER_SIZE) && (!error); ++sub) { // treat any ItemInst as having the max internal slots available + for (int16 sub = SUB_INDEX_BEGIN; (sub < EQEmu::legacy::ITEM_CONTAINER_SIZE) && (!error); ++sub) { // treat any ItemInst as having the max internal slots available if (inst->GetItem(sub)) InterrogateInventory_(true, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1); } @@ -3179,7 +3179,7 @@ void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 hea } if (inst) { - for (int16 sub = SUB_INDEX_BEGIN; (sub < EQEmu::constants::ITEM_CONTAINER_SIZE); ++sub) { + for (int16 sub = SUB_INDEX_BEGIN; (sub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++sub) { if (inst->GetItem(sub)) InterrogateInventory_(false, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1); } @@ -3194,11 +3194,11 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* // very basic error checking - can be elaborated upon if more in-depth testing is needed... if ( - (head >= EQEmu::constants::EQUIPMENT_BEGIN && head <= EQEmu::constants::EQUIPMENT_END) || - (head >= EQEmu::constants::TRIBUTE_BEGIN && head <= EQEmu::constants::TRIBUTE_END) || - (head >= EQEmu::constants::WORLD_BEGIN && head <= EQEmu::constants::WORLD_END) || + (head >= EQEmu::legacy::EQUIPMENT_BEGIN && head <= EQEmu::legacy::EQUIPMENT_END) || + (head >= EQEmu::legacy::TRIBUTE_BEGIN && head <= EQEmu::legacy::TRIBUTE_END) || + (head >= EQEmu::legacy::WORLD_BEGIN && head <= EQEmu::legacy::WORLD_END) || (head >= 8000 && head <= 8101) || - (head == SlotPowerSource)) { + (head == EQEmu::legacy::SlotPowerSource)) { switch (depth) { case 0: // requirement: inst is extant @@ -3210,7 +3210,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* return true; if (!parent->IsType(ItemClassCommon)) return true; - if (index >= EQEmu::constants::ITEM_COMMON_SIZE) + if (index >= EQEmu::legacy::ITEM_COMMON_SIZE) return true; break; default: // requirement: none (something bad happened...) @@ -3218,11 +3218,11 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* } } else if ( - (head >= EQEmu::constants::GENERAL_BEGIN && head <= EQEmu::constants::GENERAL_END) || - (head == SlotCursor) || - (head >= EQEmu::constants::BANK_BEGIN && head <= EQEmu::constants::BANK_END) || - (head >= EQEmu::constants::SHARED_BANK_BEGIN && head <= EQEmu::constants::SHARED_BANK_END) || - (head >= EQEmu::constants::TRADE_BEGIN && head <= EQEmu::constants::TRADE_END)) { + (head >= EQEmu::legacy::GENERAL_BEGIN && head <= EQEmu::legacy::GENERAL_END) || + (head == EQEmu::legacy::SlotCursor) || + (head >= EQEmu::legacy::BANK_BEGIN && head <= EQEmu::legacy::BANK_END) || + (head >= EQEmu::legacy::SHARED_BANK_BEGIN && head <= EQEmu::legacy::SHARED_BANK_END) || + (head >= EQEmu::legacy::TRADE_BEGIN && head <= EQEmu::legacy::TRADE_END)) { switch (depth) { case 0: // requirement: inst is extant @@ -3239,7 +3239,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* if (parent->IsType(ItemClassCommon)) { if (!(inst->GetItem()->AugType > 0)) return true; - if (index >= EQEmu::constants::ITEM_COMMON_SIZE) + if (index >= EQEmu::legacy::ITEM_COMMON_SIZE) return true; } break; @@ -3253,7 +3253,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* if (parent->IsType(ItemClassCommon)) { if (!(inst->GetItem()->AugType > 0)) return true; - if (index >= EQEmu::constants::ITEM_COMMON_SIZE) + if (index >= EQEmu::legacy::ITEM_COMMON_SIZE) return true; } break; diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 4985f9d9f..86969ccca 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -272,7 +272,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge // it is an improvement. if (!item2->NoPet) { - for (int i = 0; !found && i < EQEmu::constants::EQUIPMENT_SIZE; i++) { + for (int i = 0; !found && i < EQEmu::legacy::EQUIPMENT_SIZE; i++) { uint32 slots = (1 << i); if (item2->Slots & slots) { if(equipment[i]) @@ -313,7 +313,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge // @merth: IDFile size has been increased, this needs to change uint16 emat; if(item2->Material <= 0 - || item2->Slots & (1 << SlotPrimary | 1 << SlotSecondary)) { + || item2->Slots & (1 << EQEmu::legacy::SlotPrimary | 1 << EQEmu::legacy::SlotSecondary)) { memset(newid, 0, sizeof(newid)); for(int i=0;i<7;i++){ if (!isalpha(item2->IDFile[i])){ @@ -327,17 +327,17 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge emat = item2->Material; } - if (foundslot == SlotPrimary) { + if (foundslot == EQEmu::legacy::SlotPrimary) { if (item2->Proc.Effect != 0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); - eslot = MaterialPrimary; + eslot = EQEmu::legacy::MaterialPrimary; if (item2->Damage > 0) SendAddPlayerState(PlayerState::PrimaryWeaponEquipped); if (item2->ItemType == ItemType2HBlunt || item2->ItemType == ItemType2HSlash || item2->ItemType == ItemType2HPiercing) SetTwoHanderEquipped(true); } - else if (foundslot == SlotSecondary + else if (foundslot == EQEmu::legacy::SlotSecondary && (GetOwner() != nullptr || (CanThisClassDualWield() && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) && (item2->ItemType == ItemType1HSlash || item2->ItemType == ItemType1HBlunt || item2->ItemType == ItemTypeShield || item2->ItemType == ItemType1HPiercing)) @@ -345,30 +345,30 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge if (item2->Proc.Effect!=0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); - eslot = MaterialSecondary; + eslot = EQEmu::legacy::MaterialSecondary; if (item2->Damage > 0) SendAddPlayerState(PlayerState::SecondaryWeaponEquipped); } - else if (foundslot == SlotHead) { - eslot = MaterialHead; + else if (foundslot == EQEmu::legacy::SlotHead) { + eslot = EQEmu::legacy::MaterialHead; } - else if (foundslot == SlotChest) { - eslot = MaterialChest; + else if (foundslot == EQEmu::legacy::SlotChest) { + eslot = EQEmu::legacy::MaterialChest; } - else if (foundslot == SlotArms) { - eslot = MaterialArms; + else if (foundslot == EQEmu::legacy::SlotArms) { + eslot = EQEmu::legacy::MaterialArms; } - else if (foundslot == SlotWrist1 || foundslot == SlotWrist2) { - eslot = MaterialWrist; + else if (foundslot == EQEmu::legacy::SlotWrist1 || foundslot == EQEmu::legacy::SlotWrist2) { + eslot = EQEmu::legacy::MaterialWrist; } - else if (foundslot == SlotHands) { - eslot = MaterialHands; + else if (foundslot == EQEmu::legacy::SlotHands) { + eslot = EQEmu::legacy::MaterialHands; } - else if (foundslot == SlotLegs) { - eslot = MaterialLegs; + else if (foundslot == EQEmu::legacy::SlotLegs) { + eslot = EQEmu::legacy::MaterialLegs; } - else if (foundslot == SlotFeet) { - eslot = MaterialFeet; + else if (foundslot == EQEmu::legacy::SlotFeet) { + eslot = EQEmu::legacy::MaterialFeet; } /* diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 5aec9c029..52eb2388f 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1757,47 +1757,47 @@ luabind::scope lua_register_slot() { return luabind::class_("Slot") .enum_("constants") [ - luabind::value("Charm", static_cast(SlotCharm)), - luabind::value("Ear1", static_cast(SlotEar1)), - luabind::value("Head", static_cast(SlotHead)), - luabind::value("Face", static_cast(SlotFace)), - luabind::value("Ear2", static_cast(SlotEar2)), - luabind::value("Neck", static_cast(SlotNeck)), - luabind::value("Shoulder", static_cast(SlotShoulders)), // deprecated - luabind::value("Shoulders", static_cast(SlotShoulders)), - luabind::value("Arms", static_cast(SlotArms)), - luabind::value("Back", static_cast(SlotBack)), - luabind::value("Bracer1", static_cast(SlotWrist1)), // deprecated - luabind::value("Wrist1", static_cast(SlotWrist1)), - luabind::value("Bracer2", static_cast(SlotWrist2)), // deprecated - luabind::value("Wrist2", static_cast(SlotWrist2)), - luabind::value("Range", static_cast(SlotRange)), - luabind::value("Hands", static_cast(SlotHands)), - luabind::value("Primary", static_cast(SlotPrimary)), - luabind::value("Secondary", static_cast(SlotSecondary)), - luabind::value("Ring1", static_cast(SlotFinger1)), // deprecated - luabind::value("Finger1", static_cast(SlotFinger1)), - luabind::value("Ring2", static_cast(SlotFinger2)), // deprecated - luabind::value("Finger2", static_cast(SlotFinger2)), - luabind::value("Chest", static_cast(SlotChest)), - luabind::value("Legs", static_cast(SlotLegs)), - luabind::value("Feet", static_cast(SlotFeet)), - luabind::value("Waist", static_cast(SlotWaist)), - luabind::value("PowerSource", static_cast(SlotPowerSource)), - luabind::value("Ammo", static_cast(SlotAmmo)), - luabind::value("General1", static_cast(SlotGeneral1)), - luabind::value("General2", static_cast(SlotGeneral2)), - luabind::value("General3", static_cast(SlotGeneral3)), - luabind::value("General4", static_cast(SlotGeneral4)), - luabind::value("General5", static_cast(SlotGeneral5)), - luabind::value("General6", static_cast(SlotGeneral6)), - luabind::value("General7", static_cast(SlotGeneral7)), - luabind::value("General8", static_cast(SlotGeneral8)), - luabind::value("Cursor", static_cast(SlotCursor)), - luabind::value("PersonalBegin", static_cast(EQEmu::constants::GENERAL_BEGIN)), // deprecated - luabind::value("GeneralBegin", static_cast(EQEmu::constants::GENERAL_BEGIN)), - luabind::value("PersonalEnd", static_cast(EQEmu::constants::GENERAL_END)), // deprecated - luabind::value("GeneralEnd", static_cast(EQEmu::constants::GENERAL_END)), + luabind::value("Charm", static_cast(EQEmu::legacy::SlotCharm)), + luabind::value("Ear1", static_cast(EQEmu::legacy::SlotEar1)), + luabind::value("Head", static_cast(EQEmu::legacy::SlotHead)), + luabind::value("Face", static_cast(EQEmu::legacy::SlotFace)), + luabind::value("Ear2", static_cast(EQEmu::legacy::SlotEar2)), + luabind::value("Neck", static_cast(EQEmu::legacy::SlotNeck)), + luabind::value("Shoulder", static_cast(EQEmu::legacy::SlotShoulders)), // deprecated + luabind::value("Shoulders", static_cast(EQEmu::legacy::SlotShoulders)), + luabind::value("Arms", static_cast(EQEmu::legacy::SlotArms)), + luabind::value("Back", static_cast(EQEmu::legacy::SlotBack)), + luabind::value("Bracer1", static_cast(EQEmu::legacy::SlotWrist1)), // deprecated + luabind::value("Wrist1", static_cast(EQEmu::legacy::SlotWrist1)), + luabind::value("Bracer2", static_cast(EQEmu::legacy::SlotWrist2)), // deprecated + luabind::value("Wrist2", static_cast(EQEmu::legacy::SlotWrist2)), + luabind::value("Range", static_cast(EQEmu::legacy::SlotRange)), + luabind::value("Hands", static_cast(EQEmu::legacy::SlotHands)), + luabind::value("Primary", static_cast(EQEmu::legacy::SlotPrimary)), + luabind::value("Secondary", static_cast(EQEmu::legacy::SlotSecondary)), + luabind::value("Ring1", static_cast(EQEmu::legacy::SlotFinger1)), // deprecated + luabind::value("Finger1", static_cast(EQEmu::legacy::SlotFinger1)), + luabind::value("Ring2", static_cast(EQEmu::legacy::SlotFinger2)), // deprecated + luabind::value("Finger2", static_cast(EQEmu::legacy::SlotFinger2)), + luabind::value("Chest", static_cast(EQEmu::legacy::SlotChest)), + luabind::value("Legs", static_cast(EQEmu::legacy::SlotLegs)), + luabind::value("Feet", static_cast(EQEmu::legacy::SlotFeet)), + luabind::value("Waist", static_cast(EQEmu::legacy::SlotWaist)), + luabind::value("PowerSource", static_cast(EQEmu::legacy::SlotPowerSource)), + luabind::value("Ammo", static_cast(EQEmu::legacy::SlotAmmo)), + luabind::value("General1", static_cast(EQEmu::legacy::SlotGeneral1)), + luabind::value("General2", static_cast(EQEmu::legacy::SlotGeneral2)), + luabind::value("General3", static_cast(EQEmu::legacy::SlotGeneral3)), + luabind::value("General4", static_cast(EQEmu::legacy::SlotGeneral4)), + luabind::value("General5", static_cast(EQEmu::legacy::SlotGeneral5)), + luabind::value("General6", static_cast(EQEmu::legacy::SlotGeneral6)), + luabind::value("General7", static_cast(EQEmu::legacy::SlotGeneral7)), + luabind::value("General8", static_cast(EQEmu::legacy::SlotGeneral8)), + luabind::value("Cursor", static_cast(EQEmu::legacy::SlotCursor)), + luabind::value("PersonalBegin", static_cast(EQEmu::legacy::GENERAL_BEGIN)), // deprecated + luabind::value("GeneralBegin", static_cast(EQEmu::legacy::GENERAL_BEGIN)), + luabind::value("PersonalEnd", static_cast(EQEmu::legacy::GENERAL_END)), // deprecated + luabind::value("GeneralEnd", static_cast(EQEmu::legacy::GENERAL_END)), luabind::value("CursorEnd", 0xFFFE), // deprecated luabind::value("Tradeskill", static_cast(EQEmu::legacy::SLOT_TRADESKILL)), // deprecated luabind::value("Augment", static_cast(EQEmu::legacy::SLOT_AUGMENT)), // deprecated @@ -1809,19 +1809,19 @@ luabind::scope lua_register_material() { return luabind::class_("Material") .enum_("constants") [ - luabind::value("Head", static_cast(MaterialHead)), - luabind::value("Chest", static_cast(MaterialChest)), - luabind::value("Arms", static_cast(MaterialArms)), - luabind::value("Bracer", static_cast(MaterialWrist)), // deprecated - luabind::value("Wrist", static_cast(MaterialWrist)), - luabind::value("Hands", static_cast(MaterialHands)), - luabind::value("Legs", static_cast(MaterialLegs)), - luabind::value("Feet", static_cast(MaterialFeet)), - luabind::value("Primary", static_cast(MaterialPrimary)), - luabind::value("Secondary", static_cast(MaterialSecondary)), - luabind::value("Max", static_cast(MaterialCount)), // deprecated - luabind::value("Count", static_cast(MaterialCount)), - luabind::value("Invalid", static_cast(MaterialInvalid)) + luabind::value("Head", static_cast(EQEmu::legacy::MaterialHead)), + luabind::value("Chest", static_cast(EQEmu::legacy::MaterialChest)), + luabind::value("Arms", static_cast(EQEmu::legacy::MaterialArms)), + luabind::value("Bracer", static_cast(EQEmu::legacy::MaterialWrist)), // deprecated + luabind::value("Wrist", static_cast(EQEmu::legacy::MaterialWrist)), + luabind::value("Hands", static_cast(EQEmu::legacy::MaterialHands)), + luabind::value("Legs", static_cast(EQEmu::legacy::MaterialLegs)), + luabind::value("Feet", static_cast(EQEmu::legacy::MaterialFeet)), + luabind::value("Primary", static_cast(EQEmu::legacy::MaterialPrimary)), + luabind::value("Secondary", static_cast(EQEmu::legacy::MaterialSecondary)), + luabind::value("Max", static_cast(EQEmu::legacy::MaterialCount)), // deprecated + luabind::value("Count", static_cast(EQEmu::legacy::MaterialCount)), + luabind::value("Invalid", static_cast(EQEmu::legacy::MaterialInvalid)) ]; } diff --git a/zone/merc.cpp b/zone/merc.cpp index ef2a4e7e6..606ce8a35 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -214,7 +214,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { unsigned int i; //should not include 21 (SLOT_AMMO) - for (i = 0; i < SlotAmmo; i++) { + for (i = 0; i < EQEmu::legacy::SlotAmmo; i++) { if(equipment[i] == 0) continue; const Item_Struct * itm = database.GetItem(equipment[i]); @@ -1559,24 +1559,24 @@ void Merc::AI_Process() { //try main hand first if(attack_timer.Check()) { - Attack(GetTarget(), SlotPrimary); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary); bool tripleSuccess = false; if(GetOwner() && GetTarget() && CanThisClassDoubleAttack()) { if(GetOwner()) { - Attack(GetTarget(), SlotPrimary, true); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); } if(GetOwner() && GetTarget() && GetSpecialAbility(SPECATK_TRIPLE)) { tripleSuccess = true; - Attack(GetTarget(), SlotPrimary, true); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); } //quad attack, does this belong here?? if(GetOwner() && GetTarget() && GetSpecialAbility(SPECATK_QUAD)) { - Attack(GetTarget(), SlotPrimary, true); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); } } @@ -1588,8 +1588,8 @@ void Merc::AI_Process() { if(zone->random.Roll(flurrychance)) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); - Attack(GetTarget(), SlotPrimary, false); - Attack(GetTarget(), SlotPrimary, false); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); } } @@ -1598,7 +1598,7 @@ void Merc::AI_Process() { if (GetTarget() && ExtraAttackChanceBonus) { if(zone->random.Roll(ExtraAttackChanceBonus)) { - Attack(GetTarget(), SlotPrimary, false); + Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); } } } @@ -1633,11 +1633,11 @@ void Merc::AI_Process() { // Max 78% of DW if (zone->random.Roll(DualWieldProbability)) { - Attack(GetTarget(), SlotSecondary); // Single attack with offhand + Attack(GetTarget(), EQEmu::legacy::SlotSecondary); // Single attack with offhand if(CanThisClassDoubleAttack()) { if(GetTarget() && GetTarget()->GetHP() > -10) - Attack(GetTarget(), SlotSecondary); // Single attack with offhand + Attack(GetTarget(), EQEmu::legacy::SlotSecondary); // Single attack with offhand } } } @@ -2552,7 +2552,7 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) { int16 focus_max_real = 0; //item focus - for (int x = 0; x < EQEmu::constants::EQUIPMENT_SIZE; ++x) + for (int x = 0; x < EQEmu::legacy::EQUIPMENT_SIZE; ++x) { TempItem = nullptr; if (equipment[x] == 0) @@ -5025,12 +5025,12 @@ void Merc::ScaleStats(int scalepercent, bool setmax) { void Merc::UpdateMercAppearance() { // Copied from Bot Code: uint32 itemID = NO_ITEM; - uint8 materialFromSlot = MaterialInvalid; - for (int i = EQEmu::constants::EQUIPMENT_BEGIN; i <= EQEmu::constants::EQUIPMENT_END; ++i) { + uint8 materialFromSlot = EQEmu::legacy::MaterialInvalid; + for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { itemID = equipment[i]; if(itemID != NO_ITEM) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); - if(materialFromSlot != MaterialInvalid) + if (materialFromSlot != EQEmu::legacy::MaterialInvalid) this->SendWearChange(materialFromSlot); } } @@ -5044,8 +5044,8 @@ void Merc::UpdateEquipmentLight() m_Light.Type.Equipment = 0; m_Light.Level.Equipment = 0; - for (int index = SLOT_BEGIN; index < EQEmu::constants::EQUIPMENT_SIZE; ++index) { - if (index == SlotAmmo) { continue; } + for (int index = SLOT_BEGIN; index < EQEmu::legacy::EQUIPMENT_SIZE; ++index) { + if (index == EQEmu::legacy::SlotAmmo) { continue; } auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } diff --git a/zone/merc.h b/zone/merc.h index 0efb3d568..b981e28b5 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -62,7 +62,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return (GetGroup() ? true : false); } @@ -288,7 +288,7 @@ protected: std::map timers; uint16 skills[HIGHEST_SKILL+1]; - uint32 equipment[EQEmu::constants::EQUIPMENT_SIZE]; //this is an array of item IDs + uint32 equipment[EQEmu::legacy::EQUIPMENT_SIZE]; //this is an array of item IDs uint16 d_melee_texture1; //this is an item Material value uint16 d_melee_texture2; //this is an item Material value (offhand) uint8 prim_melee_type; //Sets the Primary Weapon attack message and animation diff --git a/zone/mob.cpp b/zone/mob.cpp index e488a09cb..13a246ee4 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -73,7 +73,7 @@ Mob::Mob(const char* in_name, uint32 in_drakkin_heritage, uint32 in_drakkin_tattoo, uint32 in_drakkin_details, - uint32 in_armor_tint[MaterialCount], + uint32 in_armor_tint[EQEmu::legacy::MaterialCount], uint8 in_aa_title, uint8 in_see_invis, // see through invis/ivu @@ -280,7 +280,7 @@ Mob::Mob(const char* in_name, RangedProcs[j].level_override = -1; } - for (i = 0; i < MaterialCount; i++) + for (i = 0; i < EQEmu::legacy::MaterialCount; i++) { if (in_armor_tint) { @@ -2379,8 +2379,8 @@ bool Mob::CanThisClassDualWield(void) const { return(GetSkill(SkillDualWield) > 0); } else if(CastToClient()->HasSkill(SkillDualWield)) { - const ItemInst* pinst = CastToClient()->GetInv().GetItem(SlotPrimary); - const ItemInst* sinst = CastToClient()->GetInv().GetItem(SlotSecondary); + const ItemInst* pinst = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); + const ItemInst* sinst = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); // 2HS, 2HB, or 2HP if(pinst && pinst->IsWeapon()) { @@ -2865,7 +2865,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const if (item != 0) { // For primary and secondary we need the model, not the material - if (material_slot == MaterialPrimary || material_slot == MaterialSecondary) + if (material_slot == EQEmu::legacy::MaterialPrimary || material_slot == EQEmu::legacy::MaterialSecondary) { if (this->IsClient()) { @@ -2909,7 +2909,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const int32 Mob::GetHerosForgeModel(uint8 material_slot) const { uint32 HeroModel = 0; - if (material_slot >= 0 && material_slot < MaterialPrimary) + if (material_slot >= 0 && material_slot < EQEmu::legacy::MaterialPrimary) { uint32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); const Item_Struct *item; diff --git a/zone/mob.h b/zone/mob.h index d5040e93e..c276f212b 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -108,7 +108,7 @@ public: uint32 in_drakkin_heritage, uint32 in_drakkin_tattoo, uint32 in_drakkin_details, - uint32 in_armor_tint[MaterialCount], + uint32 in_armor_tint[EQEmu::legacy::MaterialCount], uint8 in_aa_title, uint8 in_see_invis, // see through invis uint8 in_see_invis_undead, // see through invis vs. undead @@ -148,7 +148,7 @@ public: virtual void ThrowingAttack(Mob* other) { } uint16 GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg); // 13 = Primary (default), 14 = secondary - virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) = 0; int MonkSpecialAttack(Mob* other, uint8 skill_used); virtual void TryBackstab(Mob *other,int ReuseTime = 10); @@ -379,7 +379,7 @@ public: inline uint8 GetDrakkinHeritage() const { return drakkin_heritage; } inline uint8 GetDrakkinTattoo() const { return drakkin_tattoo; } inline uint8 GetDrakkinDetails() const { return drakkin_details; } - inline uint32 GetArmorTint(uint8 i) const { return armor_tint[(i < MaterialCount) ? i : 0]; } + inline uint32 GetArmorTint(uint8 i) const { return armor_tint[(i < EQEmu::legacy::MaterialCount) ? i : 0]; } inline uint8 GetClass() const { return class_; } inline uint8 GetLevel() const { return level; } inline uint8 GetOrigLevel() const { return orig_level; } @@ -566,7 +566,7 @@ public: bool lookForAftArc = true); //Procs - void TriggerDefensiveProcs(Mob *on, uint16 hand = SlotPrimary, bool FromSkillProc=false, int damage = 0); + void TriggerDefensiveProcs(Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary, bool FromSkillProc = false, int damage = 0); bool AddRangedProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); bool RemoveRangedProc(uint16 spell_id, bool bAll = false); bool HasRangedProcs() const; @@ -1146,13 +1146,13 @@ protected: void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand = SlotCharm? bool PassLimitToSkill(uint16 spell_id, uint16 skill); bool PassLimitClass(uint32 Classes_, uint16 Class_); - void TryDefensiveProc(Mob *on, uint16 hand = SlotPrimary); - void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = SlotPrimary); - void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = SlotPrimary); - void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = SlotPrimary); + void TryDefensiveProc(Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); + void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); + void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); + void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on, int level_override = -1); - virtual float GetProcChances(float ProcBonus, uint16 hand = SlotPrimary); - virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = SlotPrimary, Mob *on = nullptr); + virtual float GetProcChances(float ProcBonus, uint16 hand = EQEmu::legacy::SlotPrimary); + virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = EQEmu::legacy::SlotPrimary, Mob *on = nullptr); virtual float GetSpecialProcChances(uint16 hand); virtual float GetAssassinateProcChances(uint16 ReuseTime); virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm? @@ -1243,7 +1243,7 @@ protected: uint32 drakkin_heritage; uint32 drakkin_tattoo; uint32 drakkin_details; - uint32 armor_tint[MaterialCount]; + uint32 armor_tint[EQEmu::legacy::MaterialCount]; uint8 aa_title; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 5d0493c62..b640da2b0 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -847,7 +847,7 @@ void Client::AI_Process() if (GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) { if (attack_timer.Check()) { // Should charmed clients not be procing? - DoAttackRounds(GetTarget(), SlotPrimary); + DoAttackRounds(GetTarget(), EQEmu::legacy::SlotPrimary); } } @@ -855,7 +855,7 @@ void Client::AI_Process() if (attack_dw_timer.Check()) { if (CheckDualWield()) { // Should charmed clients not be procing? - DoAttackRounds(GetTarget(), SlotSecondary); + DoAttackRounds(GetTarget(), EQEmu::legacy::SlotSecondary); } } } @@ -1106,7 +1106,7 @@ void Mob::AI_Process() { //try main hand first if(attack_timer.Check()) { DoMainHandAttackRounds(target); - TriggerDefensiveProcs(target, SlotPrimary, false); + TriggerDefensiveProcs(target, EQEmu::legacy::SlotPrimary, false); bool specialed = false; // NPCs can only do one of these a round if (GetSpecialAbility(SPECATK_FLURRY)) { @@ -1952,7 +1952,7 @@ bool Mob::Flurry(ExtraAttackOptions *opts) int num_attacks = GetSpecialAbilityParam(SPECATK_FLURRY, 1); num_attacks = num_attacks > 0 ? num_attacks : RuleI(Combat, MaxFlurryHits); for (int i = 0; i < num_attacks; i++) - Attack(target, SlotPrimary, false, false, false, opts); + Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts); } return true; } diff --git a/zone/npc.cpp b/zone/npc.cpp index ea123f32a..6d09aa96e 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -488,7 +488,7 @@ void NPC::CheckMinMaxLevel(Mob *them) if(themlevel < (*cur)->min_level || themlevel > (*cur)->max_level) { material = Inventory::CalcMaterialFromSlot((*cur)->equip_slot); - if (material != MaterialInvalid) + if (material != EQEmu::legacy::MaterialInvalid) SendWearChange(material); cur = itemlist.erase(cur); @@ -748,8 +748,8 @@ void NPC::UpdateEquipmentLight() m_Light.Type.Equipment = 0; m_Light.Level.Equipment = 0; - for (int index = SLOT_BEGIN; index < EQEmu::constants::EQUIPMENT_SIZE; ++index) { - if (index == SlotAmmo) { continue; } + for (int index = SLOT_BEGIN; index < EQEmu::legacy::EQUIPMENT_SIZE; ++index) { + if (index == EQEmu::legacy::SlotAmmo) { continue; } auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } @@ -1372,7 +1372,7 @@ uint32 ZoneDatabase::NPCSpawnDB(uint8 command, const char* zone, uint32 zone_ver int32 NPC::GetEquipmentMaterial(uint8 material_slot) const { - if (material_slot >= MaterialCount) + if (material_slot >= EQEmu::legacy::MaterialCount) return 0; int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); @@ -1383,23 +1383,23 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const { switch(material_slot) { - case MaterialHead: + case EQEmu::legacy::MaterialHead: return helmtexture; - case MaterialChest: + case EQEmu::legacy::MaterialChest: return texture; - case MaterialArms: + case EQEmu::legacy::MaterialArms: return armtexture; - case MaterialWrist: + case EQEmu::legacy::MaterialWrist: return bracertexture; - case MaterialHands: + case EQEmu::legacy::MaterialHands: return handtexture; - case MaterialLegs: + case EQEmu::legacy::MaterialLegs: return legtexture; - case MaterialFeet: + case EQEmu::legacy::MaterialFeet: return feettexture; - case MaterialPrimary: + case EQEmu::legacy::MaterialPrimary: return d_melee_texture1; - case MaterialSecondary: + case EQEmu::legacy::MaterialSecondary: return d_melee_texture2; default: //they have nothing in the slot, and its not a special slot... they get nothing. diff --git a/zone/npc.h b/zone/npc.h index c07ccc947..834211198 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -106,7 +106,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } @@ -495,7 +495,7 @@ protected: uint16 skills[HIGHEST_SKILL+1]; - uint32 equipment[EQEmu::constants::EQUIPMENT_SIZE]; //this is an array of item IDs + uint32 equipment[EQEmu::legacy::EQUIPMENT_SIZE]; //this is an array of item IDs uint32 herosforgemodel; //this is the Hero Forge Armor Model (i.e 63 or 84 or 203) uint16 d_melee_texture1; //this is an item Material value diff --git a/zone/object.cpp b/zone/object.cpp index 5c154b782..122db47ed 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -324,7 +324,7 @@ void Object::Delete(bool reset_state) } const ItemInst* Object::GetItem(uint8 index) { - if (index < EQEmu::constants::TYPE_WORLD_SIZE) { + if (index < EQEmu::legacy::TYPE_WORLD_SIZE) { return m_inst->GetItem(index); } @@ -362,7 +362,7 @@ void Object::Close() { ItemInst* container = this->m_inst; if(container != nullptr) { - for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::constants::ITEM_CONTAINER_SIZE; i++) + for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { ItemInst* inst = container->PopItem(i); if(inst != nullptr) @@ -503,11 +503,11 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) // Transfer item to client - sender->PutItemInInventory(SlotCursor, *m_inst, false); - sender->SendItemPacket(SlotCursor, m_inst, ItemPacketTrade); + sender->PutItemInInventory(EQEmu::legacy::SlotCursor, *m_inst, false); + sender->SendItemPacket(EQEmu::legacy::SlotCursor, m_inst, ItemPacketTrade); if(cursordelete) // delete the item if it's a duplicate lore. We have to do this because the client expects the item packet - sender->DeleteItemInInventory(SlotCursor); + sender->DeleteItemInInventory(EQEmu::legacy::SlotCursor); if(!m_ground_spawn) safe_delete(m_inst); @@ -583,7 +583,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) EQApplicationPacket* outapp=new EQApplicationPacket(OP_ClientReady,0); sender->QueuePacket(outapp); safe_delete(outapp); - for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::constants::ITEM_CONTAINER_SIZE; i++) { + for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { const ItemInst* inst = m_inst->GetItem(i); if (inst) { //sender->GetInv().PutItem(i+4000,inst); diff --git a/zone/pets.cpp b/zone/pets.cpp index 14d02097a..63e1a832c 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -417,12 +417,12 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, // the base items for the pet. These are always loaded // so that a rank 1 suspend minion does not kill things // like the special back items some focused pets may receive. - uint32 petinv[EQEmu::constants::EQUIPMENT_SIZE]; + uint32 petinv[EQEmu::legacy::EQUIPMENT_SIZE]; memset(petinv, 0, sizeof(petinv)); const Item_Struct *item = 0; if (database.GetBasePetItems(record.equipmentset, petinv)) { - for (int i = 0; i < EQEmu::constants::EQUIPMENT_SIZE; i++) + for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++) if (petinv[i]) { item = database.GetItem(petinv[i]); npc->AddLootDrop(item, &npc->itemlist, 0, 1, 127, true, true); @@ -572,7 +572,7 @@ void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) { strn0cpy(name, GetName(), 64); //save their items, we only care about what they are actually wearing - memcpy(items, equipment, sizeof(uint32) * EQEmu::constants::EQUIPMENT_SIZE); + memcpy(items, equipment, sizeof(uint32) * EQEmu::legacy::EQUIPMENT_SIZE); //save their buffs. for (int i=0; i < GetPetMaxTotalSlots(); i++) { @@ -660,7 +660,7 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { } //restore their equipment... - for (i = 0; i < EQEmu::constants::EQUIPMENT_SIZE; i++) { + for (i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++) { if(items[i] == 0) continue; @@ -722,7 +722,7 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) { { slot = atoi(row[0]); - if (slot >= EQEmu::constants::EQUIPMENT_SIZE) + if (slot >= EQEmu::legacy::EQUIPMENT_SIZE) continue; if (items[slot] == 0) diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 4ab6f4eb1..806f995e7 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2441,12 +2441,12 @@ int QuestManager::collectitems(uint32 item_id, bool remove) int quantity = 0; int slot_id; - for (slot_id = EQEmu::constants::GENERAL_BEGIN; slot_id <= EQEmu::constants::GENERAL_END; ++slot_id) + for (slot_id = EQEmu::legacy::GENERAL_BEGIN; slot_id <= EQEmu::legacy::GENERAL_END; ++slot_id) { quantity += collectitems_processSlot(slot_id, item_id, remove); } - for (slot_id = EQEmu::constants::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::constants::GENERAL_BAGS_END; ++slot_id) + for (slot_id = EQEmu::legacy::GENERAL_BAGS_BEGIN; slot_id <= EQEmu::legacy::GENERAL_BAGS_END; ++slot_id) { quantity += collectitems_processSlot(slot_id, item_id, remove); } diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 929cee001..6f9e276a2 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -69,17 +69,17 @@ void Mob::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) case SkillFlyingKick: case SkillRoundKick: case SkillKick: - item_slot = SlotFeet; + item_slot = EQEmu::legacy::SlotFeet; break; case SkillBash: - item_slot = SlotSecondary; + item_slot = EQEmu::legacy::SlotSecondary; break; case SkillDragonPunch: case SkillEagleStrike: case SkillTigerClaw: - item_slot = SlotHands; + item_slot = EQEmu::legacy::SlotHands; break; default: @@ -115,7 +115,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if(skill == SkillBash){ if(IsClient()){ - ItemInst *item = CastToClient()->GetInv().GetItem(SlotSecondary); + ItemInst *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); if(item) { if(item->GetItem()->ItemType == ItemTypeShield) @@ -133,14 +133,14 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, min_damage += min_damage * GetMeleeMinDamageMod_SE(skill) / 100; - int hand = SlotPrimary; // Avoid checks hand for throwing/archery exclusion, primary should work for most + int hand = EQEmu::legacy::SlotPrimary; // Avoid checks hand for throwing/archery exclusion, primary should work for most if (skill == SkillThrowing || skill == SkillArchery) - hand = SlotRange; + hand = EQEmu::legacy::SlotRange; if (who->AvoidDamage(this, max_damage, hand)) { if (max_damage == -3) DoRiposte(who); } else { - if (HitChance || who->CheckHitChance(this, skill, SlotPrimary)) { + if (HitChance || who->CheckHitChance(this, skill, EQEmu::legacy::SlotPrimary)) { who->MeleeMitigation(this, max_damage, min_damage); CommonOutgoingHitSuccess(who, max_damage, skill); } else { @@ -198,7 +198,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { //These two are not subject to the combat ability timer, as they //allready do their checking in conjunction with the attack timer //throwing weapons - if(ca_atk->m_atk == SlotRange) { + if (ca_atk->m_atk == EQEmu::legacy::SlotRange) { if (ca_atk->m_skill == SkillThrowing) { SetAttackTimer(); ThrowingAttack(GetTarget()); @@ -248,8 +248,8 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { DoAnim(animTailRake); int32 ht = 0; - if(GetWeaponDamage(GetTarget(), GetInv().GetItem(SlotSecondary)) <= 0 && - GetWeaponDamage(GetTarget(), GetInv().GetItem(SlotShoulders)) <= 0){ + if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::legacy::SlotSecondary)) <= 0 && + GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::legacy::SlotShoulders)) <= 0){ dmg = -5; } else{ @@ -325,7 +325,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { DoAnim(animKick); int32 ht = 0; - if(GetWeaponDamage(GetTarget(), GetInv().GetItem(SlotFeet)) <= 0){ + if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::legacy::SlotFeet)) <= 0){ dmg = -5; } else{ @@ -408,7 +408,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) int32 min_dmg = 1; int reuse = 0; SkillUseTypes skill_type; //to avoid casting... even though it "would work" - uint8 itemslot = SlotFeet; + uint8 itemslot = EQEmu::legacy::SlotFeet; switch(unchecked_type){ case SkillFlyingKick:{ @@ -423,7 +423,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) case SkillDragonPunch:{ skill_type = SkillDragonPunch; max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, DragonPunchBonus) / 100) + 26; - itemslot = SlotHands; + itemslot = EQEmu::legacy::SlotHands; ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animTailRake); reuse = TailRakeReuseTime; @@ -433,7 +433,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) case SkillEagleStrike:{ skill_type = SkillEagleStrike; max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, EagleStrikeBonus) / 100) + 19; - itemslot = SlotHands; + itemslot = EQEmu::legacy::SlotHands; ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animEagleStrike); reuse = EagleStrikeReuseTime; @@ -443,7 +443,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) case SkillTigerClaw:{ skill_type = SkillTigerClaw; max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, TigerClawBonus) / 100) + 12; - itemslot = SlotHands; + itemslot = EQEmu::legacy::SlotHands; ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animTigerClaw); reuse = TigerClawReuseTime; @@ -512,7 +512,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { //make sure we have a proper weapon if we are a client. if(IsClient()) { - const ItemInst *wpn = CastToClient()->GetInv().GetItem(SlotPrimary); + const ItemInst *wpn = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); if(!wpn || (wpn->GetItem()->ItemType != ItemType1HPiercing)){ Message_StringID(13, BACKSTAB_WEAPON); return; @@ -573,7 +573,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10); } else { //We do a single regular attack if we attack from the front without chaotic stab - Attack(other, SlotPrimary); + Attack(other, EQEmu::legacy::SlotPrimary); } } @@ -592,11 +592,11 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) if(IsClient()){ const ItemInst *wpn = nullptr; - wpn = CastToClient()->GetInv().GetItem(SlotPrimary); + wpn = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); if(wpn) { primaryweapondamage = GetWeaponDamage(other, wpn); backstab_dmg = wpn->GetItem()->BackstabDmg; - for (int i = 0; i < EQEmu::constants::ITEM_COMMON_SIZE; ++i) + for (int i = 0; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { ItemInst *aug = wpn->GetAugment(i); if(aug) @@ -671,7 +671,7 @@ void Mob::RogueAssassinate(Mob* other) { //can you dodge, parry, etc.. an assassinate?? //if so, use DoSpecialAttackDamage(other, BACKSTAB, 32000); instead - if(GetWeaponDamage(other, IsClient()?CastToClient()->GetInv().GetItem(SlotPrimary):(const ItemInst*)nullptr) > 0){ + if (GetWeaponDamage(other, IsClient() ? CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary) : (const ItemInst*)nullptr) > 0){ other->Damage(this, 32000, SPELL_UNKNOWN, SkillBackstab); }else{ other->Damage(this, -5, SPELL_UNKNOWN, SkillBackstab); @@ -691,20 +691,20 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { //Message(0, "Error: Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime()); return; } - const ItemInst* RangeWeapon = m_inv[SlotRange]; + const ItemInst* RangeWeapon = m_inv[EQEmu::legacy::SlotRange]; //locate ammo - int ammo_slot = SlotAmmo; - const ItemInst* Ammo = m_inv[SlotAmmo]; + int ammo_slot = EQEmu::legacy::SlotAmmo; + const ItemInst* Ammo = m_inv[EQEmu::legacy::SlotAmmo]; if (!RangeWeapon || !RangeWeapon->IsType(ItemClassCommon)) { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(SlotRange), SlotRange); - Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have no bow!", GetItemIDAt(SlotRange)); + Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(EQEmu::legacy::SlotRange), EQEmu::legacy::SlotRange); + Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have no bow!", GetItemIDAt(EQEmu::legacy::SlotRange)); return; } if (!Ammo || !Ammo->IsType(ItemClassCommon)) { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ammo item (%d) in slot %d", GetItemIDAt(SlotAmmo), SlotAmmo); - Message(0, "Error: Ammo: GetItem(%i)==0, you have no ammo!", GetItemIDAt(SlotAmmo)); + Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ammo item (%d) in slot %d", GetItemIDAt(EQEmu::legacy::SlotAmmo), EQEmu::legacy::SlotAmmo); + Message(0, "Error: Ammo: GetItem(%i)==0, you have no ammo!", GetItemIDAt(EQEmu::legacy::SlotAmmo)); return; } @@ -729,7 +729,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { //first look for quivers int r; bool found = false; - for(r = EQEmu::constants::GENERAL_BEGIN; r <= EQEmu::constants::GENERAL_END; r++) { + for (r = EQEmu::legacy::GENERAL_BEGIN; r <= EQEmu::legacy::GENERAL_END; r++) { const ItemInst *pi = m_inv[r]; if(pi == nullptr || !pi->IsType(ItemClassContainer)) continue; @@ -859,7 +859,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (IsClient()){ - _RangeWeapon = CastToClient()->m_inv[SlotRange]; + _RangeWeapon = CastToClient()->m_inv[EQEmu::legacy::SlotRange]; if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id) RangeWeapon = _RangeWeapon; @@ -875,7 +875,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite else if (AmmoItem) SendItemAnimation(other, AmmoItem, SkillArchery); - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillArchery, SlotPrimary, chance_mod))) { + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillArchery, EQEmu::legacy::SlotPrimary, chance_mod))) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ @@ -973,7 +973,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } if (!HeadShot) - other->AvoidDamage(this, TotalDmg, SlotRange); + other->AvoidDamage(this, TotalDmg, EQEmu::legacy::SlotRange); other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0){ @@ -997,7 +997,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (ReuseTime) TrySkillProc(other, SkillArchery, ReuseTime); else - TrySkillProc(other, SkillArchery, 0, true, SlotRange); + TrySkillProc(other, SkillArchery, 0, true, EQEmu::legacy::SlotRange); } } @@ -1006,20 +1006,20 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite //Weapon Proc if(RangeWeapon && other && !other->HasDied()) - TryWeaponProc(RangeWeapon, other, SlotRange); + TryWeaponProc(RangeWeapon, other, EQEmu::legacy::SlotRange); //Ammo Proc if (ammo_lost) - TryWeaponProc(nullptr, ammo_lost, other, SlotRange); + TryWeaponProc(nullptr, ammo_lost, other, EQEmu::legacy::SlotRange); else if(Ammo && other && !other->HasDied()) - TryWeaponProc(Ammo, other, SlotRange); + TryWeaponProc(Ammo, other, EQEmu::legacy::SlotRange); //Skill Proc if (HasSkillProcs() && other && !other->HasDied()){ if (ReuseTime) TrySkillProc(other, SkillArchery, ReuseTime); else - TrySkillProc(other, SkillArchery, 0, false, SlotRange); + TrySkillProc(other, SkillArchery, 0, false, EQEmu::legacy::SlotRange); } } @@ -1285,7 +1285,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha if (!chance_mod) chance_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2); - if (!other->CheckHitChance(this, skillInUse, SlotRange, chance_mod)) + if (!other->CheckHitChance(this, skillInUse, EQEmu::legacy::SlotRange, chance_mod)) { other->Damage(this, 0, SPELL_UNKNOWN, skillInUse); } @@ -1306,7 +1306,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha TotalDmg += TotalDmg * damage_mod / 100; - other->AvoidDamage(this, TotalDmg, SlotRange); + other->AvoidDamage(this, TotalDmg, EQEmu::legacy::SlotRange); other->MeleeMitigation(this, TotalDmg, MinDmg); if (TotalDmg > 0) @@ -1322,15 +1322,15 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillInUse); if (TotalDmg > 0 && HasSkillProcSuccess() && !other->HasDied()) - TrySkillProc(other, skillInUse, 0, true, SlotRange); + TrySkillProc(other, skillInUse, 0, true, EQEmu::legacy::SlotRange); } //try proc on hits and misses if(other && !other->HasDied()) - TrySpellProc(nullptr, (const Item_Struct*)nullptr, other, SlotRange); + TrySpellProc(nullptr, (const Item_Struct*)nullptr, other, EQEmu::legacy::SlotRange); if (HasSkillProcs() && other && !other->HasDied()) - TrySkillProc(other, skillInUse, 0, false, SlotRange); + TrySkillProc(other, skillInUse, 0, false, EQEmu::legacy::SlotRange); } uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) { @@ -1372,19 +1372,19 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 return; } - int ammo_slot = SlotRange; - const ItemInst* RangeWeapon = m_inv[SlotRange]; + int ammo_slot = EQEmu::legacy::SlotRange; + const ItemInst* RangeWeapon = m_inv[EQEmu::legacy::SlotRange]; if (!RangeWeapon || !RangeWeapon->IsType(ItemClassCommon)) { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(SlotRange), SlotRange); - Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(SlotRange)); + Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(EQEmu::legacy::SlotRange), EQEmu::legacy::SlotRange); + Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(EQEmu::legacy::SlotRange)); return; } const Item_Struct* item = RangeWeapon->GetItem(); if(item->ItemType != ItemTypeLargeThrowing && item->ItemType != ItemTypeSmallThrowing) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item %d is not a throwing weapon. type %d.", item->ItemType); - Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(SlotRange)); + Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(EQEmu::legacy::SlotRange)); return; } @@ -1392,11 +1392,11 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 if(RangeWeapon->GetCharges() == 1) { //first check ammo - const ItemInst* AmmoItem = m_inv[SlotAmmo]; + const ItemInst* AmmoItem = m_inv[EQEmu::legacy::SlotAmmo]; if(AmmoItem != nullptr && AmmoItem->GetID() == RangeWeapon->GetID()) { //more in the ammo slot, use it RangeWeapon = AmmoItem; - ammo_slot = SlotAmmo; + ammo_slot = EQEmu::legacy::SlotAmmo; Log.Out(Logs::Detail, Logs::Combat, "Using ammo from ammo slot, stack at slot %d. %d in stack.", ammo_slot, RangeWeapon->GetCharges()); } else { //look through our inventory for more @@ -1493,7 +1493,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite else if (AmmoItem) SendItemAnimation(other, AmmoItem, SkillThrowing); - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillThrowing, SlotPrimary, chance_mod))){ + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillThrowing, EQEmu::legacy::SlotPrimary, chance_mod))){ Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ TryProjectileAttack(other, AmmoItem, SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot, speed); @@ -1540,7 +1540,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite Log.Out(Logs::Detail, Logs::Combat, "Item DMG %d. Max Damage %d. Hit for damage %d", WDmg, MaxDmg, TotalDmg); if (!Assassinate_Dmg) - other->AvoidDamage(this, TotalDmg, SlotRange); + other->AvoidDamage(this, TotalDmg, EQEmu::legacy::SlotRange); other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0) @@ -1559,7 +1559,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (ReuseTime) TrySkillProc(other, SkillThrowing, ReuseTime); else - TrySkillProc(other, SkillThrowing, 0, true, SlotRange); + TrySkillProc(other, SkillThrowing, 0, true, EQEmu::legacy::SlotRange); } } @@ -1568,15 +1568,15 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite //Throwing item Proc if (ammo_lost) - TryWeaponProc(nullptr, ammo_lost, other, SlotRange); + TryWeaponProc(nullptr, ammo_lost, other, EQEmu::legacy::SlotRange); else if(RangeWeapon && other && !other->HasDied()) - TryWeaponProc(RangeWeapon, other, SlotRange); + TryWeaponProc(RangeWeapon, other, EQEmu::legacy::SlotRange); if (HasSkillProcs() && other && !other->HasDied()){ if (ReuseTime) TrySkillProc(other, SkillThrowing, ReuseTime); else - TrySkillProc(other, SkillThrowing, 0, false, SlotRange); + TrySkillProc(other, SkillThrowing, 0, false, EQEmu::legacy::SlotRange); } } @@ -1976,7 +1976,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if (ca_target!=this) { DoAnim(animTailRake); - if(GetWeaponDamage(ca_target, GetInv().GetItem(SlotSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(SlotShoulders)) <= 0){ + if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::legacy::SlotSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::legacy::SlotShoulders)) <= 0){ dmg = -5; } else{ @@ -2040,7 +2040,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if(ca_target!=this){ DoAnim(animKick); - if(GetWeaponDamage(ca_target, GetInv().GetItem(SlotFeet)) <= 0){ + if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::legacy::SlotFeet)) <= 0){ dmg = -5; } else{ @@ -2252,7 +2252,7 @@ uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { HeadShot_Level = itembonuses.HSLevel; if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){ - float ProcChance = GetSpecialProcChances(SlotRange); + float ProcChance = GetSpecialProcChances(EQEmu::legacy::SlotRange); if(zone->random.Roll(ProcChance)) return HeadShot_Dmg; } @@ -2315,7 +2315,7 @@ uint32 Mob::TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 Reuse float ProcChance = 0.0f; if (skillInUse == SkillThrowing) - ProcChance = GetSpecialProcChances(SlotRange); + ProcChance = GetSpecialProcChances(EQEmu::legacy::SlotRange); else ProcChance = GetAssassinateProcChances(ReuseTime); @@ -2366,7 +2366,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes int damage = 0; uint32 hate = 0; - int Hand = SlotPrimary; + int Hand = EQEmu::legacy::SlotPrimary; if (hate == 0 && weapon_damage > 1) hate = weapon_damage; if(weapon_damage > 0){ @@ -2390,7 +2390,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if(skillinuse == SkillBash){ if(IsClient()){ - ItemInst *item = CastToClient()->GetInv().GetItem(SlotSecondary); + ItemInst *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); if(item){ if(item->GetItem()->ItemType == ItemTypeShield) { hate += item->GetItem()->AC; @@ -2412,7 +2412,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes else damage = zone->random.Int(min_hit, max_hit); - if (other->AvoidDamage(this, damage, CanRiposte ? SlotRange : SlotPrimary)) { // SlotRange excludes ripo, primary doesn't have any extra behavior + if (other->AvoidDamage(this, damage, CanRiposte ? EQEmu::legacy::SlotRange : EQEmu::legacy::SlotPrimary)) { // SlotRange excludes ripo, primary doesn't have any extra behavior if (damage == -3) { DoRiposte(other); if (HasDied()) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ee97a287f..ab20371fa 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -616,7 +616,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Flesh To Bone"); #endif if(IsClient()){ - ItemInst* transI = CastToClient()->GetInv().GetItem(SlotCursor); + ItemInst* transI = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotCursor); if(transI && transI->IsType(ItemClassCommon) && transI->IsStackable()){ uint32 fcharges = transI->GetCharges(); //Does it sound like meat... maybe should check if it looks like meat too... @@ -626,7 +626,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove strstr(transI->GetItem()->Name, "Flesh") || strstr(transI->GetItem()->Name, "parts") || strstr(transI->GetItem()->Name, "Parts")){ - CastToClient()->DeleteItemInInventory(SlotCursor, fcharges, true); + CastToClient()->DeleteItemInInventory(EQEmu::legacy::SlotCursor, fcharges, true); CastToClient()->SummonItem(13073, fcharges); } else{ @@ -1157,7 +1157,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (SummonedItem) { c->PushItemOnCursor(*SummonedItem); - c->SendItemPacket(SlotCursor, SummonedItem, ItemPacketSummonItem); + c->SendItemPacket(EQEmu::legacy::SlotCursor, SummonedItem, ItemPacketSummonItem); safe_delete(SummonedItem); } SummonedItem = database.CreateItem(spell.base[i], charges); @@ -1429,7 +1429,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } } - for (int x = EQEmu::constants::MATERIAL_BEGIN; x <= EQEmu::constants::MATERIAL_TINT_END; x++) + for (int x = EQEmu::legacy::MATERIAL_BEGIN; x <= EQEmu::legacy::MATERIAL_TINT_END; x++) SendWearChange(x); if (caster == this && @@ -1455,7 +1455,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove ); caster->SendAppearancePacket(AT_Size, static_cast(caster->GetTarget()->GetSize())); - for (int x = EQEmu::constants::MATERIAL_BEGIN; x <= EQEmu::constants::MATERIAL_TINT_END; x++) + for (int x = EQEmu::legacy::MATERIAL_BEGIN; x <= EQEmu::legacy::MATERIAL_TINT_END; x++) caster->SendWearChange(x); } } @@ -2216,7 +2216,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Rampage"); #endif if(caster) - entity_list.AEAttack(caster, 30, SlotPrimary, 0, true); // on live wars dont get a duration ramp, its a one shot deal + entity_list.AEAttack(caster, 30, EQEmu::legacy::SlotPrimary, 0, true); // on live wars dont get a duration ramp, its a one shot deal break; } @@ -3014,7 +3014,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (SummonedItem) { Client *c=CastToClient(); c->PushItemOnCursor(*SummonedItem); - c->SendItemPacket(SlotCursor, SummonedItem, ItemPacketSummonItem); + c->SendItemPacket(EQEmu::legacy::SlotCursor, SummonedItem, ItemPacketSummonItem); safe_delete(SummonedItem); } @@ -3809,7 +3809,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) else{ SendAppearancePacket(AT_Size, 6); } - for (int x = EQEmu::constants::MATERIAL_BEGIN; x <= EQEmu::constants::MATERIAL_TINT_END; x++){ + for (int x = EQEmu::legacy::MATERIAL_BEGIN; x <= EQEmu::legacy::MATERIAL_TINT_END; x++){ SendWearChange(x); } break; @@ -5126,7 +5126,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { const Item_Struct* TempItem = 0; - for (int x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::EQUIPMENT_END; x++) + for (int x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::EQUIPMENT_END; x++) { if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; @@ -5146,7 +5146,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { } } - for (int y = AUG_INDEX_BEGIN; y < EQEmu::constants::ITEM_COMMON_SIZE; ++y) + for (int y = AUG_INDEX_BEGIN; y < EQEmu::legacy::ITEM_COMMON_SIZE; ++y) { if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; @@ -5261,7 +5261,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) int16 focus_max_real = 0; //item focus - for (int x = EQEmu::constants::EQUIPMENT_BEGIN; x <= EQEmu::constants::EQUIPMENT_END; x++) + for (int x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::EQUIPMENT_END; x++) { TempItem = nullptr; ItemInst* ins = GetInv().GetItem(x); @@ -5295,7 +5295,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) } } - for (int y = AUG_INDEX_BEGIN; y < EQEmu::constants::ITEM_COMMON_SIZE; ++y) + for (int y = AUG_INDEX_BEGIN; y < EQEmu::legacy::ITEM_COMMON_SIZE; ++y) { ItemInst *aug = nullptr; aug = ins->GetAugment(y); @@ -5333,7 +5333,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) } //Tribute Focus - for (int x = EQEmu::constants::TRIBUTE_BEGIN; x <= EQEmu::constants::TRIBUTE_END; ++x) + for (int x = EQEmu::legacy::TRIBUTE_BEGIN; x <= EQEmu::legacy::TRIBUTE_END; ++x) { TempItem = nullptr; ItemInst* ins = GetInv().GetItem(x); @@ -5533,7 +5533,7 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { int16 focus_max_real = 0; //item focus - for (int i = 0; i < EQEmu::constants::EQUIPMENT_SIZE; i++){ + for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++){ const Item_Struct *cur = database.GetItem(equipment[i]); if(!cur) diff --git a/zone/spells.cpp b/zone/spells.cpp index ffc644ff0..f0bc6e85a 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -291,7 +291,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, return(false); } } - if( itm && (itm->GetItem()->Click.Type == ET_EquipClick) && !(item_slot <= SlotAmmo || item_slot == SlotPowerSource) ){ + if (itm && (itm->GetItem()->Click.Type == ET_EquipClick) && !(item_slot <= EQEmu::legacy::SlotAmmo || item_slot == EQEmu::legacy::SlotPowerSource)){ if (CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoF) { // They are attempting to cast a must equip clicky without having it equipped Log.Out(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click an equip-only effect on item %s (id: %d) without equiping it!", CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID); @@ -1206,7 +1206,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, if (inst == nullptr) break; - for (int r = AUG_INDEX_BEGIN; r < EQEmu::constants::ITEM_COMMON_SIZE; r++) { + for (int r = AUG_INDEX_BEGIN; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { const ItemInst* aug_i = inst->GetAugment(r); if (!aug_i) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 1048e7c34..ffdafaeb1 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -69,7 +69,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme // Verify that no more than two items are in container to guarantee no inadvertant wipes. uint8 itemsFound = 0; - for (uint8 i = SLOT_BEGIN; i < EQEmu::constants::TYPE_WORLD_SIZE; i++) + for (uint8 i = SLOT_BEGIN; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) { const ItemInst* inst = container->GetItem(i); if (inst) @@ -222,7 +222,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme else { // Delete items in our inventory container... - for (uint8 i = SLOT_BEGIN; i < EQEmu::constants::TYPE_WORLD_SIZE; i++) + for (uint8 i = SLOT_BEGIN; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) { const ItemInst* inst = container->GetItem(i); if (inst) @@ -297,7 +297,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob const Item_Struct* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); - user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), SlotCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2)); + user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::legacy::SlotCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2)); user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name); if (RuleB(Inventory, DeleteTransformationMold)) user->DeleteItemInInventory(in_combine->container_slot, 0, true); @@ -317,7 +317,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob const Item_Struct* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); - user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), SlotCursor, 0, 0); + user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::legacy::SlotCursor, 0, 0); user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name); } else if (inst) { @@ -401,7 +401,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob safe_delete(outapp); database.DeleteWorldContainer(worldo->m_id, zone->GetZoneID()); } else{ - for (uint8 i = SLOT_BEGIN; i < EQEmu::constants::TYPE_WORLD_SIZE; i++) { + for (uint8 i = SLOT_BEGIN; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) { const ItemInst* inst = container->GetItem(i); if (inst) { user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot,i),0,true); @@ -1227,7 +1227,7 @@ bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint3 for (auto row = results.begin(); row != results.end(); ++row) { int ccnt = 0; - for (int x = SLOT_BEGIN; x < EQEmu::constants::TYPE_WORLD_SIZE; x++) { + for (int x = SLOT_BEGIN; x < EQEmu::legacy::TYPE_WORLD_SIZE; x++) { const ItemInst* inst = container->GetItem(x); if(!inst) continue; diff --git a/zone/trading.cpp b/zone/trading.cpp index d52a25543..ff9c60559 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -98,7 +98,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) { // Item always goes into trade bucket from cursor Client* client = owner->CastToClient(); - ItemInst* inst = client->GetInv().GetItem(SlotCursor); + ItemInst* inst = client->GetInv().GetItem(EQEmu::legacy::SlotCursor); if (!inst) { client->Message(13, "Error: Could not find item on your cursor!"); @@ -131,7 +131,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) { if (_stack_size > 0) inst->SetCharges(_stack_size); else - client->DeleteItemInInventory(SlotCursor); + client->DeleteItemInInventory(EQEmu::legacy::SlotCursor); SendItemData(inst2, trade_slot_id); } @@ -146,7 +146,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) { Log.Out(Logs::Detail, Logs::Trading, "%s added item '%s' to trade slot %i", owner->GetName(), inst->GetItem()->Name, trade_slot_id); client->PutItemInInventory(trade_slot_id, *inst); - client->DeleteItemInInventory(SlotCursor); + client->DeleteItemInInventory(EQEmu::legacy::SlotCursor); } } @@ -171,13 +171,13 @@ void Trade::SendItemData(const ItemInst* inst, int16 dest_slot_id) Client* with = mob->CastToClient(); Client* trader = owner->CastToClient(); if (with && with->IsClient()) { - with->SendItemPacket(dest_slot_id - EQEmu::constants::TRADE_BEGIN, inst, ItemPacketTradeView); + with->SendItemPacket(dest_slot_id - EQEmu::legacy::TRADE_BEGIN, inst, ItemPacketTradeView); if (inst->GetItem()->ItemClass == 1) { - for (uint16 i = SUB_INDEX_BEGIN; i < EQEmu::constants::ITEM_CONTAINER_SIZE; i++) { + for (uint16 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { uint16 bagslot_id = Inventory::CalcSlotId(dest_slot_id, i); const ItemInst* bagitem = trader->GetInv().GetItem(bagslot_id); if (bagitem) { - with->SendItemPacket(bagslot_id - EQEmu::constants::TRADE_BEGIN, bagitem, ItemPacketTradeView); + with->SendItemPacket(bagslot_id - EQEmu::legacy::TRADE_BEGIN, bagitem, ItemPacketTradeView); } } } @@ -199,7 +199,7 @@ void Trade::LogTrade() uint8 item_count = 0; if (zone->tradevar != 0) { - for (uint16 i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_END; i++) { + for (uint16 i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_END; i++) { if (trader->GetInv().GetItem(i)) item_count++; } @@ -251,7 +251,7 @@ void Trade::LogTrade() if (item_count > 0) { strcat(logtext, "items {"); - for (uint16 i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_END; i++) { + for (uint16 i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_END; i++) { const ItemInst* inst = trader->GetInv().GetItem(i); if (!comma) @@ -267,7 +267,7 @@ void Trade::LogTrade() strcat(logtext, item_num); if (inst->IsType(ItemClassContainer)) { - for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::constants::ITEM_CONTAINER_SIZE; j++) { + for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::legacy::ITEM_CONTAINER_SIZE; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { strcat(logtext, ","); @@ -303,7 +303,7 @@ void Trade::DumpTrade() return; Client* trader = owner->CastToClient(); - for (uint16 i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_END; i++) { + for (uint16 i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_END; i++) { const ItemInst* inst = trader->GetInv().GetItem(i); if (inst) { @@ -312,7 +312,7 @@ void Trade::DumpTrade() i, ((inst->IsType(ItemClassContainer)) ? "True" : "False")); if (inst->IsType(ItemClassContainer)) { - for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::constants::ITEM_CONTAINER_SIZE; j++) { + for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::legacy::ITEM_CONTAINER_SIZE; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { Log.Out(Logs::Detail, Logs::Trading, "\tBagItem %i (Charges=%i, Slot=%i)", @@ -332,7 +332,7 @@ void Client::ResetTrade() { AddMoneyToPP(trade->cp, trade->sp, trade->gp, trade->pp, true); // step 1: process bags - for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst && inst->IsType(ItemClassContainer)) { @@ -351,7 +351,7 @@ void Client::ResetTrade() { } // step 2a: process stackables - for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { @@ -359,7 +359,7 @@ void Client::ResetTrade() { // there's no built-in safety check against an infinite loop..but, it should break on one of the conditional checks int16 free_slot = m_inv.FindFreeSlotForTradeItem(inst); - if ((free_slot == SlotCursor) || (free_slot == INVALID_INDEX)) + if ((free_slot == EQEmu::legacy::SlotCursor) || (free_slot == INVALID_INDEX)) break; ItemInst* partial_inst = GetInv().GetItem(free_slot); @@ -398,11 +398,11 @@ void Client::ResetTrade() { // step 2b: adjust trade stack bias // (if any partial stacks exist before the final stack, FindFreeSlotForTradeItem() will return that slot in step 3 and an overwrite will occur) - for (int16 trade_slot = EQEmu::constants::TRADE_END; trade_slot >= EQEmu::constants::TRADE_BEGIN; --trade_slot) { + for (int16 trade_slot = EQEmu::legacy::TRADE_END; trade_slot >= EQEmu::legacy::TRADE_BEGIN; --trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { - for (int16 bias_slot = EQEmu::constants::TRADE_BEGIN; bias_slot <= EQEmu::constants::TRADE_END; ++bias_slot) { + for (int16 bias_slot = EQEmu::legacy::TRADE_BEGIN; bias_slot <= EQEmu::legacy::TRADE_END; ++bias_slot) { if (bias_slot >= trade_slot) break; @@ -432,7 +432,7 @@ void Client::ResetTrade() { } // step 3: process everything else - for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst) { @@ -487,7 +487,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } // step 1: process bags - for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst && inst->IsType(ItemClassContainer)) { @@ -523,7 +523,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st qs_audit->char1_count += detail->charges; //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { - for (uint8 sub_slot = SUB_INDEX_BEGIN; (sub_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items + for (uint8 sub_slot = SUB_INDEX_BEGIN; (sub_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items const ItemInst* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { @@ -571,7 +571,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } // step 2a: process stackables - for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { @@ -579,7 +579,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // there's no built-in safety check against an infinite loop..but, it should break on one of the conditional checks int16 partial_slot = other->GetInv().FindFreeSlotForTradeItem(inst); - if ((partial_slot == SlotCursor) || (partial_slot == INVALID_INDEX)) + if ((partial_slot == EQEmu::legacy::SlotCursor) || (partial_slot == INVALID_INDEX)) break; ItemInst* partial_inst = other->GetInv().GetItem(partial_slot); @@ -653,11 +653,11 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // step 2b: adjust trade stack bias // (if any partial stacks exist before the final stack, FindFreeSlotForTradeItem() will return that slot in step 3 and an overwrite will occur) - for (int16 trade_slot = EQEmu::constants::TRADE_END; trade_slot >= EQEmu::constants::TRADE_BEGIN; --trade_slot) { + for (int16 trade_slot = EQEmu::legacy::TRADE_END; trade_slot >= EQEmu::legacy::TRADE_BEGIN; --trade_slot) { ItemInst* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { - for (int16 bias_slot = EQEmu::constants::TRADE_BEGIN; bias_slot <= EQEmu::constants::TRADE_END; ++bias_slot) { + for (int16 bias_slot = EQEmu::legacy::TRADE_BEGIN; bias_slot <= EQEmu::legacy::TRADE_END; ++bias_slot) { if (bias_slot >= trade_slot) break; @@ -706,7 +706,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } // step 3: process everything else - for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; if (inst) { @@ -743,7 +743,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // 'step 3' should never really see containers..but, just in case... //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { - for (uint8 sub_slot = SUB_INDEX_BEGIN; (sub_slot < EQEmu::constants::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items + for (uint8 sub_slot = SUB_INDEX_BEGIN; (sub_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items const ItemInst* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { @@ -820,7 +820,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } if(qs_log) { // This can be incorporated below when revisions are made - for (int16 trade_slot = EQEmu::constants::TRADE_BEGIN; trade_slot <= EQEmu::constants::TRADE_NPC_END; ++trade_slot) { + for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_NPC_END; ++trade_slot) { const ItemInst* trade_inst = m_inv[trade_slot]; if(trade_inst) { @@ -875,7 +875,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st std::vector item_list; std::list items; - for (int i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_NPC_END; ++i) { + for (int i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_NPC_END; ++i) { ItemInst *inst = m_inv.GetItem(i); if(inst) { items.push_back(inst); @@ -948,8 +948,8 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } ItemInst *insts[4] = { 0 }; - for (int i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_NPC_END; ++i) { - insts[i - EQEmu::constants::TRADE_BEGIN] = m_inv.PopItem(i); + for (int i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_NPC_END; ++i) { + insts[i - EQEmu::legacy::TRADE_BEGIN] = m_inv.PopItem(i); database.SaveInventory(CharacterID(), nullptr, i); } @@ -968,7 +968,7 @@ bool Client::CheckTradeLoreConflict(Client* other) if (!other) return true; // Move each trade slot into free inventory slot - for (int16 i = EQEmu::constants::TRADE_BEGIN; i <= EQEmu::constants::TRADE_END; i++){ + for (int16 i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_END; i++){ const ItemInst* inst = m_inv[i]; if (inst && inst->GetItem()) { @@ -977,7 +977,7 @@ bool Client::CheckTradeLoreConflict(Client* other) } } - for (int16 i = EQEmu::constants::TRADE_BAGS_BEGIN; i <= EQEmu::constants::TRADE_BAGS_END; i++){ + for (int16 i = EQEmu::legacy::TRADE_BAGS_BEGIN; i <= EQEmu::legacy::TRADE_BAGS_END; i++){ const ItemInst* inst = m_inv[i]; if (inst && inst->GetItem()) { @@ -1232,10 +1232,10 @@ uint32 Client::FindTraderItemSerialNumber(int32 ItemID) { ItemInst* item = nullptr; uint16 SlotID = 0; - for (int i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++){ + for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++){ item = this->GetInv().GetItem(i); if (item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; x++) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1255,10 +1255,10 @@ ItemInst* Client::FindTraderItemBySerialNumber(int32 SerialNumber){ ItemInst* item = nullptr; uint16 SlotID = 0; - for (int i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++){ + for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++){ item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; x++) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1286,10 +1286,10 @@ GetItems_Struct* Client::GetTraderItems(){ uint8 ndx = 0; - for (int i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { + for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; x++) { + for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; x++) { SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1310,10 +1310,10 @@ uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){ const ItemInst* item= nullptr; uint16 SlotID = 0; - for (int i = EQEmu::constants::GENERAL_BEGIN; i <= EQEmu::constants::GENERAL_END; i++) { + for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_INDEX_BEGIN; x < EQEmu::constants::ITEM_CONTAINER_SIZE; x++){ + for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; x++){ SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); diff --git a/zone/tribute.cpp b/zone/tribute.cpp index 077e97bee..737b04151 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -66,7 +66,7 @@ void Client::ToggleTribute(bool enabled) { int r; uint32 cost = 0; uint32 level = GetLevel(); - for (r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::legacy::TRIBUTE_SIZE; r++) { uint32 tid = m_pp.tributes[r].tribute; if(tid == TRIBUTE_NONE) continue; @@ -119,7 +119,7 @@ void Client::DoTributeUpdate() { tis->tribute_master_id = tribute_master_id; //Dont know what this is for int r; - for (r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::legacy::TRIBUTE_SIZE; r++) { if(m_pp.tributes[r].tribute != TRIBUTE_NONE) { tis->tributes[r] = m_pp.tributes[r].tribute; tis->tiers[r] = m_pp.tributes[r].tier; @@ -134,24 +134,24 @@ void Client::DoTributeUpdate() { if(m_pp.tribute_active) { //send and equip tribute items... - for (r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::legacy::TRIBUTE_SIZE; r++) { uint32 tid = m_pp.tributes[r].tribute; if(tid == TRIBUTE_NONE) { - if (m_inv[EQEmu::constants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EQEmu::constants::TRIBUTE_BEGIN + r, 0, false); + if (m_inv[EQEmu::legacy::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::legacy::TRIBUTE_BEGIN + r, 0, false); continue; } if(tribute_list.count(tid) != 1) { - if (m_inv[EQEmu::constants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EQEmu::constants::TRIBUTE_BEGIN + r, 0, false); + if (m_inv[EQEmu::legacy::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::legacy::TRIBUTE_BEGIN + r, 0, false); continue; } //sanity check if(m_pp.tributes[r].tier >= MAX_TRIBUTE_TIERS) { - if (m_inv[EQEmu::constants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EQEmu::constants::TRIBUTE_BEGIN + r, 0, false); + if (m_inv[EQEmu::legacy::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::legacy::TRIBUTE_BEGIN + r, 0, false); m_pp.tributes[r].tier = 0; continue; } @@ -165,15 +165,15 @@ void Client::DoTributeUpdate() { if(inst == nullptr) continue; - PutItemInInventory(EQEmu::constants::TRIBUTE_BEGIN + r, *inst, false); - SendItemPacket(EQEmu::constants::TRIBUTE_BEGIN + r, inst, ItemPacketTributeItem); + PutItemInInventory(EQEmu::legacy::TRIBUTE_BEGIN + r, *inst, false); + SendItemPacket(EQEmu::legacy::TRIBUTE_BEGIN + r, inst, ItemPacketTributeItem); safe_delete(inst); } } else { //unequip tribute items... - for (r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { - if (m_inv[EQEmu::constants::TRIBUTE_BEGIN + r]) - DeleteItemInInventory(EQEmu::constants::TRIBUTE_BEGIN + r, 0, false); + for (r = 0; r < EQEmu::legacy::TRIBUTE_SIZE; r++) { + if (m_inv[EQEmu::legacy::TRIBUTE_BEGIN + r]) + DeleteItemInInventory(EQEmu::legacy::TRIBUTE_BEGIN + r, 0, false); } } CalcBonuses(); @@ -192,7 +192,7 @@ void Client::SendTributeTimer() { void Client::ChangeTributeSettings(TributeInfo_Struct *t) { int r; - for (r = 0; r < EQEmu::constants::TRIBUTE_SIZE; r++) { + for (r = 0; r < EQEmu::legacy::TRIBUTE_SIZE; r++) { m_pp.tributes[r].tribute = TRIBUTE_NONE; diff --git a/zone/tune.cpp b/zone/tune.cpp index 30692b5bb..bcaa69d4a 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -582,13 +582,13 @@ int32 Client::Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 mi int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) { - int Hand = SlotPrimary; + int Hand = EQEmu::legacy::SlotPrimary; if (!other) return 0; ItemInst* weapon; - weapon = GetInv().GetItem(SlotPrimary); + weapon = GetInv().GetItem(EQEmu::legacy::SlotPrimary); if(weapon != nullptr) { if (!weapon->IsWeapon()) { @@ -628,7 +628,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) int ucDamageBonus = 0; - if( Hand == SlotPrimary && GetLevel() >= 28 && IsWarriorClass() ) + if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); @@ -662,24 +662,24 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch if (attacker->IsClient()) {//Will check first equiped weapon for skill. Ie. remove wepaons to assess bow. ItemInst* weapon; - weapon = attacker->CastToClient()->GetInv().GetItem(SlotPrimary); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); if(weapon && weapon->IsWeapon()){ - attacker->CastToClient()->AttackAnimation(skillinuse, SlotPrimary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotPrimary, weapon); } else { - weapon = attacker->CastToClient()->GetInv().GetItem(SlotSecondary); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, SlotSecondary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotSecondary, weapon); else { - weapon = attacker->CastToClient()->GetInv().GetItem(SlotRange); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotRange); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, SlotRange, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotRange, weapon); } } } - tmp_hit_chance = Tune_CheckHitChance(defender,attacker, skillinuse, SlotPrimary,0,0,0, avoid_override); + tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, 0, 0, avoid_override); Message(0, "#Tune - Begin Parse [Interval %i Max Loop Iterations %i]", interval, max_loop); @@ -691,7 +691,7 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch for (int j=0; j < max_loop; j++) { - tmp_hit_chance =Tune_CheckHitChance(defender,attacker, skillinuse, SlotPrimary,0,false,0, avoid_override, add_acc); + tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, false, 0, avoid_override, add_acc); if (Msg >= 3) Message(15, "#Tune - Processing... [%i] [ACCURACY %i] Hit Chance %.2f ",j,add_acc,tmp_hit_chance); @@ -706,7 +706,7 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch if (end){ - Tune_CheckHitChance(defender,attacker, skillinuse, SlotPrimary,0,Msg,0,avoid_override);//Display Stat Report + Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, Msg, 0, avoid_override);//Display Stat Report Message(0, " "); @@ -742,24 +742,24 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ if (attacker->IsClient()) {//Will check first equiped weapon for skill. Ie. remove wepaons to assess bow. ItemInst* weapon; - weapon = attacker->CastToClient()->GetInv().GetItem(SlotPrimary); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); if(weapon && weapon->IsWeapon()){ - attacker->CastToClient()->AttackAnimation(skillinuse, SlotPrimary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotPrimary, weapon); } else { - weapon = attacker->CastToClient()->GetInv().GetItem(SlotSecondary); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, SlotSecondary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotSecondary, weapon); else { - weapon = attacker->CastToClient()->GetInv().GetItem(SlotRange); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotRange); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, SlotRange, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotRange, weapon); } } } - tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, SlotPrimary,0,0,acc_override, 0); + tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, 0, acc_override, 0); Message(0, "#Tune - Begin Parse [Interval %i Max Loop Iterations %i]", interval, max_loop); Message(0, "#Tune - Processing... Find Avoidance for hit chance on defender of (%.0f) pct from attacker. [Current Hit Chance %.2f]", hit_chance, tmp_hit_chance); @@ -769,7 +769,7 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ for (int j=0; j < max_loop; j++) { - tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, SlotPrimary, 0,0, acc_override, 0,0,add_avoid); + tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, 0, acc_override, 0, 0, add_avoid); if (Msg >= 3) Message(0, "#Tune - Processing... [%i] [AVOIDANCE %i] Hit Chance %.2f ",j,add_avoid,tmp_hit_chance); @@ -784,7 +784,7 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ if (end){ - Tune_CheckHitChance(defender,attacker, skillinuse, SlotPrimary,0,Msg,acc_override, 0);//Display Stat Report + Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, Msg, acc_override, 0);//Display Stat Report Message(0, " "); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 08d31578c..5b66b691d 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -487,7 +487,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, ItemInst* container) uint8 index = (uint8)atoi(row[0]); uint32 item_id = (uint32)atoi(row[1]); int8 charges = (int8)atoi(row[2]); - uint32 aug[EQEmu::constants::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::legacy::ITEM_COMMON_SIZE]; aug[0] = (uint32)atoi(row[3]); aug[1] = (uint32)atoi(row[4]); aug[2] = (uint32)atoi(row[5]); @@ -497,7 +497,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, ItemInst* container) ItemInst* inst = database.CreateItem(item_id, charges); if (inst && inst->GetItem()->ItemClass == ItemClassCommon) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) if (aug[i]) inst->PutAugment(&database, i, aug[i]); // Put item inside world container @@ -520,17 +520,17 @@ void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const It DeleteWorldContainer(parent_id,zone_id); // Save all 10 items, if they exist - for (uint8 index = SUB_INDEX_BEGIN; index < EQEmu::constants::ITEM_CONTAINER_SIZE; index++) { + for (uint8 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; index++) { ItemInst* inst = container->GetItem(index); if (!inst) continue; uint32 item_id = inst->GetItem()->ID; - uint32 augslot[EQEmu::constants::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; + uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; if (inst->IsType(ItemClassCommon)) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::constants::ITEM_COMMON_SIZE; i++) { + for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { ItemInst *auginst=inst->GetAugment(i); augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } @@ -1181,11 +1181,11 @@ bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp) { std::string query = StringFormat("SELECT `bandolier_id`, `bandolier_slot`, `item_id`, `icon`, `bandolier_name` FROM `character_bandolier` WHERE `id` = %u LIMIT %u", - character_id, EQEmu::constants::BANDOLIERS_SIZE); + character_id, EQEmu::legacy::BANDOLIERS_SIZE); auto results = database.QueryDatabase(query); int i = 0; int r = 0; int si = 0; - for (i = 0; i < EQEmu::constants::BANDOLIERS_SIZE; i++) { + for (i = 0; i < EQEmu::legacy::BANDOLIERS_SIZE; i++) { pp->bandoliers[i].Name[0] = '\0'; - for (int si = 0; si < EQEmu::constants::BANDOLIER_ITEM_COUNT; si++) { + for (int si = 0; si < EQEmu::legacy::BANDOLIER_ITEM_COUNT; si++) { pp->bandoliers[i].Items[si].ID = 0; pp->bandoliers[i].Items[si].Icon = 0; pp->bandoliers[i].Items[si].Name[0] = '\0'; @@ -1219,7 +1219,7 @@ bool ZoneDatabase::LoadCharacterTribute(uint32 character_id, PlayerProfile_Struc std::string query = StringFormat("SELECT `tier`, `tribute` FROM `character_tribute` WHERE `id` = %u", character_id); auto results = database.QueryDatabase(query); int i = 0; - for (i = 0; i < EQEmu::constants::TRIBUTE_SIZE; i++){ + for (i = 0; i < EQEmu::legacy::TRIBUTE_SIZE; i++){ pp->tributes[i].tribute = 0xFFFFFFFF; pp->tributes[i].tier = 0; } @@ -1238,10 +1238,10 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc { std::string query = StringFormat("SELECT `potion_id`, `item_id`, `icon` FROM `character_potionbelt` WHERE `id` = %u LIMIT %u", - character_id, EQEmu::constants::POTION_BELT_ITEM_COUNT); + character_id, EQEmu::legacy::POTION_BELT_ITEM_COUNT); auto results = database.QueryDatabase(query); int i = 0; - for (i = 0; i < EQEmu::constants::POTION_BELT_ITEM_COUNT; i++) { + for (i = 0; i < EQEmu::legacy::POTION_BELT_ITEM_COUNT; i++) { pp->potionbelt.Items[i].Icon = 0; pp->potionbelt.Items[i].ID = 0; pp->potionbelt.Items[i].Name[0] = '\0'; @@ -1339,7 +1339,7 @@ bool ZoneDatabase::SaveCharacterTribute(uint32 character_id, PlayerProfile_Struc std::string query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", character_id); QueryDatabase(query); /* Save Tributes only if we have values... */ - for (int i = 0; i < EQEmu::constants::TRIBUTE_SIZE; i++){ + for (int i = 0; i < EQEmu::legacy::TRIBUTE_SIZE; i++){ if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != TRIBUTE_NONE){ std::string query = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); QueryDatabase(query); @@ -2092,7 +2092,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load else { auto armorTint_row = armortint_results.begin(); - for (int index = EQEmu::constants::MATERIAL_BEGIN; index <= EQEmu::constants::MATERIAL_END; index++) { + for (int index = EQEmu::legacy::MATERIAL_BEGIN; index <= EQEmu::legacy::MATERIAL_END; index++) { temp_npctype_data->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; temp_npctype_data->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; temp_npctype_data->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); @@ -2102,7 +2102,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load } // Try loading npc_types tint fields if armor tint is 0 or query failed to get results if (armor_tint_id == 0) { - for (int index = MaterialChest; index < MaterialCount; index++) { + for (int index = EQEmu::legacy::MaterialChest; index < EQEmu::legacy::MaterialCount; index++) { temp_npctype_data->armor_tint[index] = temp_npctype_data->armor_tint[0]; } } @@ -2307,7 +2307,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; if (armor_tint_id == 0) - for (int index = MaterialChest; index <= EQEmu::constants::MATERIAL_END; index++) + for (int index = EQEmu::legacy::MaterialChest; index <= EQEmu::legacy::MATERIAL_END; index++) tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0]; else if (tmpNPCType->armor_tint[0] == 0) { std::string armorTint_query = StringFormat("SELECT red1h, grn1h, blu1h, " @@ -2327,7 +2327,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client else { auto armorTint_row = results.begin(); - for (int index = EQEmu::constants::MATERIAL_BEGIN; index <= EQEmu::constants::MATERIAL_END; index++) { + for (int index = EQEmu::legacy::MATERIAL_BEGIN; index <= EQEmu::legacy::MATERIAL_END; index++) { tmpNPCType->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); @@ -2684,7 +2684,7 @@ void ZoneDatabase::LoadMercEquipment(Merc *merc) { int itemCount = 0; for(auto row = results.begin(); row != results.end(); ++row) { - if (itemCount == EQEmu::constants::EQUIPMENT_SIZE) + if (itemCount == EQEmu::legacy::EQUIPMENT_SIZE) break; if(atoi(row[0]) == 0) @@ -3199,7 +3199,7 @@ void ZoneDatabase::SavePetInfo(Client *client) query.clear(); // pet inventory! - for (int index = EQEmu::constants::EQUIPMENT_BEGIN; index <= EQEmu::constants::EQUIPMENT_END; index++) { + for (int index = EQEmu::legacy::EQUIPMENT_BEGIN; index <= EQEmu::legacy::EQUIPMENT_END; index++) { if (!petinfo->Items[index]) continue; @@ -3331,7 +3331,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) continue; int slot = atoi(row[1]); - if (slot < EQEmu::constants::EQUIPMENT_BEGIN || slot > EQEmu::constants::EQUIPMENT_END) + if (slot < EQEmu::legacy::EQUIPMENT_BEGIN || slot > EQEmu::legacy::EQUIPMENT_END) continue; pi->Items[slot] = atoul(row[2]); diff --git a/zone/zonedb.h b/zone/zonedb.h index 3706131a9..a4fc5af7b 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -126,7 +126,7 @@ struct PetInfo { uint32 Mana; float size; SpellBuff_Struct Buffs[BUFF_COUNT]; - uint32 Items[EQEmu::constants::EQUIPMENT_SIZE]; + uint32 Items[EQEmu::legacy::EQUIPMENT_SIZE]; char Name[64]; }; diff --git a/zone/zonedump.h b/zone/zonedump.h index cc8fe2010..dcba99408 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -86,7 +86,7 @@ struct NPCType uint32 drakkin_heritage; uint32 drakkin_tattoo; uint32 drakkin_details; - uint32 armor_tint[MaterialCount]; + uint32 armor_tint[EQEmu::legacy::MaterialCount]; uint32 min_dmg; uint32 max_dmg; int16 attack_count; From 26aeeac1ce88f017bf9301efa283e300c786bf80 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 22 Apr 2016 18:29:25 -0400 Subject: [PATCH 060/693] Fix for travis-ci failure --- common/client_version.h | 2 +- common/inventory_version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/client_version.h b/common/client_version.h index fe0ceef53..f721c0337 100644 --- a/common/client_version.h +++ b/common/client_version.h @@ -60,7 +60,7 @@ namespace EQEmu }; static const ClientVersion LastClientVersion = ClientVersion::RoF2; - static const size_t ClientVersionCount = (static_cast(LastClientVersion) + 1); + static const size_t ClientVersionCount = (static_cast(LastClientVersion) + 1); extern bool IsValidClientVersion(ClientVersion client_version); extern ClientVersion ValidateClientVersion(ClientVersion client_version); diff --git a/common/inventory_version.h b/common/inventory_version.h index 70e295067..bee34bcf3 100644 --- a/common/inventory_version.h +++ b/common/inventory_version.h @@ -45,7 +45,7 @@ namespace EQEmu static const InventoryVersion LastInventoryVersion = InventoryVersion::Pet; static const InventoryVersion LastPCInventoryVersion = InventoryVersion::RoF2; static const InventoryVersion LastNonPCInventoryVersion = InventoryVersion::Pet; - static const size_t InventoryVersionCount = (static_cast(LastInventoryVersion) + 1); + static const size_t InventoryVersionCount = (static_cast(LastInventoryVersion) + 1); extern bool IsValidInventoryVersion(InventoryVersion inventory_version); extern bool IsValidPCInventoryVersion(InventoryVersion inventory_version); From f36e041176f742ff53c971f255768fe1a9b12d78 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 22 Apr 2016 19:30:32 -0400 Subject: [PATCH 061/693] Fix for travis-ci failure - attempt 2 --- common/client_version.h | 2 +- common/inventory_version.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/common/client_version.h b/common/client_version.h index f721c0337..7483f6be2 100644 --- a/common/client_version.h +++ b/common/client_version.h @@ -60,7 +60,7 @@ namespace EQEmu }; static const ClientVersion LastClientVersion = ClientVersion::RoF2; - static const size_t ClientVersionCount = (static_cast(LastClientVersion) + 1); + static const unsigned int ClientVersionCount = 8; //(static_cast(LastClientVersion) + 1); - travis either doesn't like this or decl 'size_t' extern bool IsValidClientVersion(ClientVersion client_version); extern ClientVersion ValidateClientVersion(ClientVersion client_version); diff --git a/common/inventory_version.h b/common/inventory_version.h index bee34bcf3..061011c6a 100644 --- a/common/inventory_version.h +++ b/common/inventory_version.h @@ -20,7 +20,6 @@ #ifndef COMMON_INVENTORY_VERSION_H #define COMMON_INVENTORY_VERSION_H -#include "types.h" #include "client_version.h" @@ -45,7 +44,7 @@ namespace EQEmu static const InventoryVersion LastInventoryVersion = InventoryVersion::Pet; static const InventoryVersion LastPCInventoryVersion = InventoryVersion::RoF2; static const InventoryVersion LastNonPCInventoryVersion = InventoryVersion::Pet; - static const size_t InventoryVersionCount = (static_cast(LastInventoryVersion) + 1); + static const unsigned int InventoryVersionCount = 12; //(static_cast(LastInventoryVersion) + 1); - travis either doesn't like this or decl 'size_t' extern bool IsValidInventoryVersion(InventoryVersion inventory_version); extern bool IsValidPCInventoryVersion(InventoryVersion inventory_version); From 7c0eb54df67b5d4ff9b7240558460130a0c6cd1e Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 22 Apr 2016 19:41:11 -0400 Subject: [PATCH 062/693] Updated EQEmu::deity naming conventions --- common/deity.cpp | 12 ++++++------ common/deity.h | 6 +++--- zone/mob.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/common/deity.cpp b/common/deity.cpp index 228a7a81e..2e76cd567 100644 --- a/common/deity.cpp +++ b/common/deity.cpp @@ -20,9 +20,9 @@ #include "deity.h" -EQEmu::deity::DeityTypeBit EQEmu::deity::ConvertDeityToDeityBit(DeityType deity) +EQEmu::deity::DeityTypeBit EQEmu::deity::ConvertDeityTypeToDeityTypeBit(DeityType deity_type) { - switch (deity) { + switch (deity_type) { case DeityBertoxxulous: return bit_DeityBertoxxulous; case DeityBrellSirilis: @@ -63,9 +63,9 @@ EQEmu::deity::DeityTypeBit EQEmu::deity::ConvertDeityToDeityBit(DeityType deity) }; } -EQEmu::deity::DeityType EQEmu::deity::ConvertDeityBitToDeity(DeityTypeBit deity_bit) +EQEmu::deity::DeityType EQEmu::deity::ConvertDeityTypeBitToDeityType(DeityTypeBit deity_type_bit) { - switch (deity_bit) { + switch (deity_type_bit) { case bit_DeityAgnostic: return DeityAgnostic; case bit_DeityBertoxxulous: @@ -105,9 +105,9 @@ EQEmu::deity::DeityType EQEmu::deity::ConvertDeityBitToDeity(DeityTypeBit deity_ }; } -const char* EQEmu::deity::DeityName(DeityType deity) +const char* EQEmu::deity::DeityName(DeityType deity_type) { - switch (deity) { + switch (deity_type) { case DeityBertoxxulous: return "Bertoxxulous"; case DeityBrellSirilis: diff --git a/common/deity.h b/common/deity.h index fe8dce938..b7a4a14b7 100644 --- a/common/deity.h +++ b/common/deity.h @@ -67,9 +67,9 @@ namespace EQEmu bit_DeityVeeshan = 0x00010000 }; - extern DeityTypeBit ConvertDeityToDeityBit(DeityType deity); - extern DeityType ConvertDeityBitToDeity(DeityTypeBit deity_bit); - extern const char* DeityName(DeityType deity); + extern DeityTypeBit ConvertDeityTypeToDeityTypeBit(DeityType deity_type); + extern DeityType ConvertDeityTypeBitToDeityType(DeityTypeBit deity_type_bit); + extern const char* DeityName(DeityType deity_type); } } diff --git a/zone/mob.h b/zone/mob.h index c276f212b..a3b759864 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -364,7 +364,7 @@ public: virtual inline uint16 GetBaseRace() const { return base_race; } virtual inline uint8 GetBaseGender() const { return base_gender; } virtual inline uint16 GetDeity() const { return deity; } - virtual EQEmu::deity::DeityTypeBit GetDeityBit() { return EQEmu::deity::ConvertDeityToDeityBit((EQEmu::deity::DeityType)deity); } + virtual EQEmu::deity::DeityTypeBit GetDeityBit() { return EQEmu::deity::ConvertDeityTypeToDeityTypeBit((EQEmu::deity::DeityType)deity); } inline uint16 GetRace() const { return race; } inline uint8 GetGender() const { return gender; } inline uint8 GetTexture() const { return texture; } From a1ea2052bf0f2bc9886f2254187e0bdfd2d3c2dc Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 22 Apr 2016 20:03:36 -0400 Subject: [PATCH 063/693] Fix for travis-ci failure - attempt 3 --- common/emu_legacy.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/common/emu_legacy.h b/common/emu_legacy.h index ba9d18515..9fe14af8d 100644 --- a/common/emu_legacy.h +++ b/common/emu_legacy.h @@ -260,13 +260,18 @@ namespace EQEmu static const uint16 ITEM_CONTAINER_SIZE = 10;//Titanium::consts::ITEM_CONTAINER_SIZE; // BANDOLIERS_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?) - static const size_t BANDOLIERS_SIZE = 20;//RoF2::consts::BANDOLIERS_SIZE; // number of bandolier instances - static const size_t BANDOLIER_ITEM_COUNT = 4;//RoF2::consts::BANDOLIER_ITEM_COUNT; // number of equipment slots in bandolier instance + //static const size_t BANDOLIERS_SIZE = 20;//RoF2::consts::BANDOLIERS_SIZE; // number of bandolier instances + static const unsigned int BANDOLIERS_SIZE = 20;//RoF2::consts::BANDOLIERS_SIZE; // number of bandolier instances + + //static const size_t BANDOLIER_ITEM_COUNT = 4;//RoF2::consts::BANDOLIER_ITEM_COUNT; // number of equipment slots in bandolier instance + static const unsigned int BANDOLIER_ITEM_COUNT = 4;//RoF2::consts::BANDOLIER_ITEM_COUNT; // number of equipment slots in bandolier instance // POTION_BELT_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?) - static const size_t POTION_BELT_ITEM_COUNT = 5;//RoF2::consts::POTION_BELT_ITEM_COUNT; + //static const size_t POTION_BELT_ITEM_COUNT = 5;//RoF2::consts::POTION_BELT_ITEM_COUNT; + static const unsigned int POTION_BELT_ITEM_COUNT = 5;//RoF2::consts::POTION_BELT_ITEM_COUNT; - static const size_t TEXT_LINK_BODY_LENGTH = 56;//RoF2::consts::TEXT_LINK_BODY_LENGTH; + //static const size_t TEXT_LINK_BODY_LENGTH = 56;//RoF2::consts::TEXT_LINK_BODY_LENGTH; + static const unsigned int TEXT_LINK_BODY_LENGTH = 56;//RoF2::consts::TEXT_LINK_BODY_LENGTH; } } From e2123689652376acc0a4f3238332e31e0fa95edf Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 22 Apr 2016 20:51:22 -0400 Subject: [PATCH 064/693] Revert (and proper fix) of 'size_t' issue (sneaky little gcc 4.6'es) --- common/client_version.h | 4 +++- common/emu_legacy.h | 15 ++++++--------- common/inventory_version.h | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/common/client_version.h b/common/client_version.h index 7483f6be2..86d9ebcab 100644 --- a/common/client_version.h +++ b/common/client_version.h @@ -22,6 +22,8 @@ #include "types.h" +#include + namespace EQEmu { @@ -60,7 +62,7 @@ namespace EQEmu }; static const ClientVersion LastClientVersion = ClientVersion::RoF2; - static const unsigned int ClientVersionCount = 8; //(static_cast(LastClientVersion) + 1); - travis either doesn't like this or decl 'size_t' + static const size_t ClientVersionCount = (static_cast(LastClientVersion) + 1); extern bool IsValidClientVersion(ClientVersion client_version); extern ClientVersion ValidateClientVersion(ClientVersion client_version); diff --git a/common/emu_legacy.h b/common/emu_legacy.h index 9fe14af8d..f8d4ea6b4 100644 --- a/common/emu_legacy.h +++ b/common/emu_legacy.h @@ -22,6 +22,8 @@ #include "types.h" +#include + namespace EQEmu { @@ -260,18 +262,13 @@ namespace EQEmu static const uint16 ITEM_CONTAINER_SIZE = 10;//Titanium::consts::ITEM_CONTAINER_SIZE; // BANDOLIERS_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?) - //static const size_t BANDOLIERS_SIZE = 20;//RoF2::consts::BANDOLIERS_SIZE; // number of bandolier instances - static const unsigned int BANDOLIERS_SIZE = 20;//RoF2::consts::BANDOLIERS_SIZE; // number of bandolier instances - - //static const size_t BANDOLIER_ITEM_COUNT = 4;//RoF2::consts::BANDOLIER_ITEM_COUNT; // number of equipment slots in bandolier instance - static const unsigned int BANDOLIER_ITEM_COUNT = 4;//RoF2::consts::BANDOLIER_ITEM_COUNT; // number of equipment slots in bandolier instance + static const size_t BANDOLIERS_SIZE = 20;//RoF2::consts::BANDOLIERS_SIZE; // number of bandolier instances + static const size_t BANDOLIER_ITEM_COUNT = 4;//RoF2::consts::BANDOLIER_ITEM_COUNT; // number of equipment slots in bandolier instance // POTION_BELT_SIZE sets maximum limit..active limit will need to be handled by the appropriate AA or spell (or item?) - //static const size_t POTION_BELT_ITEM_COUNT = 5;//RoF2::consts::POTION_BELT_ITEM_COUNT; - static const unsigned int POTION_BELT_ITEM_COUNT = 5;//RoF2::consts::POTION_BELT_ITEM_COUNT; + static const size_t POTION_BELT_ITEM_COUNT = 5;//RoF2::consts::POTION_BELT_ITEM_COUNT; - //static const size_t TEXT_LINK_BODY_LENGTH = 56;//RoF2::consts::TEXT_LINK_BODY_LENGTH; - static const unsigned int TEXT_LINK_BODY_LENGTH = 56;//RoF2::consts::TEXT_LINK_BODY_LENGTH; + static const size_t TEXT_LINK_BODY_LENGTH = 56;//RoF2::consts::TEXT_LINK_BODY_LENGTH; } } diff --git a/common/inventory_version.h b/common/inventory_version.h index 061011c6a..07ad991ff 100644 --- a/common/inventory_version.h +++ b/common/inventory_version.h @@ -44,7 +44,7 @@ namespace EQEmu static const InventoryVersion LastInventoryVersion = InventoryVersion::Pet; static const InventoryVersion LastPCInventoryVersion = InventoryVersion::RoF2; static const InventoryVersion LastNonPCInventoryVersion = InventoryVersion::Pet; - static const unsigned int InventoryVersionCount = 12; //(static_cast(LastInventoryVersion) + 1); - travis either doesn't like this or decl 'size_t' + static const size_t InventoryVersionCount = (static_cast(LastInventoryVersion) + 1); extern bool IsValidInventoryVersion(InventoryVersion inventory_version); extern bool IsValidPCInventoryVersion(InventoryVersion inventory_version); From 2fde9edb41617ec117c078650c10428ed446167c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 26 Apr 2016 16:06:24 -0400 Subject: [PATCH 065/693] Fix null bind issues --- common/database.cpp | 8 +++++++- world/client.cpp | 20 +++++++++++++++++++- world/worlddb.cpp | 28 +++++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index a54de2bd5..f223418ab 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -641,10 +641,16 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe /* Save Bind Points */ query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)" " VALUES (%u, %u, %u, %f, %f, %f, %f, %i), " + "(%u, %u, %u, %f, %f, %f, %f, %i), ", + "(%u, %u, %u, %f, %f, %f, %f, %i), ", + "(%u, %u, %u, %f, %f, %f, %f, %i), ", "(%u, %u, %u, %f, %f, %f, %f, %i)", character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading, 0, + character_id, pp->binds[1].zoneId, 0, pp->binds[1].x, pp->binds[1].y, pp->binds[1].z, pp->binds[1].heading, 1, + character_id, pp->binds[2].zoneId, 0, pp->binds[2].x, pp->binds[2].y, pp->binds[2].z, pp->binds[2].heading, 2, + character_id, pp->binds[3].zoneId, 0, pp->binds[3].x, pp->binds[3].y, pp->binds[3].z, pp->binds[3].heading, 3, character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 4 - ); results = QueryDatabase(query); + ); results = QueryDatabase(query); /* Save Skills */ int firstquery = 0; diff --git a/world/client.cpp b/world/client.cpp index 7137d785e..91c8cffb5 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1511,7 +1511,25 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) pp.x = pp.y = pp.z = -1; } - /* Set Home Binds */ + /* Set Home Binds -- yep, all of them */ + pp.binds[1].zoneId = pp.zone_id; + pp.binds[1].x = pp.x; + pp.binds[1].y = pp.y; + pp.binds[1].z = pp.z; + pp.binds[1].heading = pp.heading; + + pp.binds[2].zoneId = pp.zone_id; + pp.binds[2].x = pp.x; + pp.binds[2].y = pp.y; + pp.binds[2].z = pp.z; + pp.binds[2].heading = pp.heading; + + pp.binds[3].zoneId = pp.zone_id; + pp.binds[3].x = pp.x; + pp.binds[3].y = pp.y; + pp.binds[3].z = pp.z; + pp.binds[3].heading = pp.heading; + pp.binds[4].zoneId = pp.zone_id; pp.binds[4].x = pp.x; pp.binds[4].y = pp.y; diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 346f3a2e6..50513af1e 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -161,8 +161,20 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou /* Set Bind Point Data for any character that may possibly be missing it for any reason */ cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `slot` FROM `character_bind` WHERE `id` = %i LIMIT 5", character_id); auto results_bind = database.QueryDatabase(cquery); + auto bind_count = results_bind.RowCount(); for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) { - if (row_b[6] && atoi(row_b[6]) == 4){ has_home = 1; } + if (row_b[6] && atoi(row_b[6]) == 4) { + has_home = 1; + // If our bind count is less than 5, we need to actually make use of this data so lets parse it + if (bind_count < 5) { + pp.binds[4].zoneId = atoi(row_b[0]); + pp.binds[4].instance_id = atoi(row_b[1]); + pp.binds[4].x = atof(row_b[2]); + pp.binds[4].y = atof(row_b[3]); + pp.binds[4].z = atof(row_b[4]); + pp.binds[4].heading = atof(row_b[5]); + } + } if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; } } @@ -202,6 +214,20 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou auto results_bset = QueryDatabase(query); } } + /* If our bind count is less than 5, then we have null data that needs to be filled in. */ + if (bind_count < 5) { + // we know that home and main bind must be valid here, so we don't check those + // we also use home to fill in the null data like live does. + for (int i = 1; i < 4; i++) { + if (pp.binds[i].zoneId != 0) // we assume 0 is the only invalid one ... + continue; + + std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", + character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, i); + auto results_bset = QueryDatabase(query); + } + } /* Bind End */ /* Load Character Material Data for Char Select */ From 705295f4c4511b6d4bce6c2ccf5c8d44d6f4eea8 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Wed, 27 Apr 2016 21:49:12 -0700 Subject: [PATCH 066/693] Fix perl version of GetBuffSlotFromType --- zone/perl_mob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 2819d2bf2..8c7413a40 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -1464,7 +1464,7 @@ XS(XS_Mob_GetBuffSlotFromType) Mob * THIS; int8 RETVAL; dXSTARG; - uint8 type = (uint8)SvUV(ST(1)); + uint16 type = (uint16)SvUV(ST(1)); if (sv_derived_from(ST(0), "Mob")) { IV tmp = SvIV((SV*)SvRV(ST(0))); From 57b483f697b9dfc7483b3a112caaf7c16185fb60 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 3 May 2016 08:25:36 -0400 Subject: [PATCH 067/693] ExtraAttackOptions (for npc special attacks) additions. melee_damage_bonus_flat //(+/-) damage percent applied to out going damage skilldmgtaken_bonus_flat //(+/-) mitigation percent applied to out going damage *Note: These have not been applied to any ingame functions set. --- zone/attack.cpp | 24 +++++++++++++++--------- zone/common.h | 6 +++++- zone/mob.cpp | 5 ++++- zone/mob.h | 6 +++--- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index d605a0da6..62625cac5 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1217,7 +1217,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if (other->CheckHitChance(this, skillinuse, Hand, hit_chance_bonus)) { other->MeleeMitigation(this, damage, min_hit, opts); if (damage > 0) - CommonOutgoingHitSuccess(other, damage, skillinuse); + CommonOutgoingHitSuccess(other, damage, skillinuse,opts); Log.Out(Logs::Detail, Logs::Combat, "Final damage after all reductions: %d", damage); } else { Log.Out(Logs::Detail, Logs::Combat, "Attack missed. Damage set to 0."); @@ -1746,7 +1746,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool if(other->IsClient() && other->CastToClient()->IsSitting()) { Log.Out(Logs::Detail, Logs::Combat, "Client %s is sitting. Hitting for max damage (%d).", other->GetName(), (max_dmg+eleBane)); damage = (max_dmg+eleBane); - damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse); + damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse, opts) / 100) + GetSkillDmgAmt(skillinuse); if(opts) { damage *= opts->damage_percent; @@ -1777,7 +1777,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool } else { if (other->CheckHitChance(this, skillinuse, Hand, hit_chance_bonus)) { other->MeleeMitigation(this, damage, min_dmg+eleBane, opts); - CommonOutgoingHitSuccess(other, damage, skillinuse); + CommonOutgoingHitSuccess(other, damage, skillinuse, opts); } else { damage = 0; } @@ -4055,7 +4055,7 @@ void Mob::DoRiposte(Mob *defender) } } -void Mob::ApplyMeleeDamageBonus(uint16 skill, int32 &damage){ +void Mob::ApplyMeleeDamageBonus(uint16 skill, int32 &damage,ExtraAttackOptions *opts){ if(!RuleB(Combat, UseIntervalAC)){ if(IsNPC()){ //across the board NPC damage bonuses. @@ -4068,7 +4068,13 @@ void Mob::ApplyMeleeDamageBonus(uint16 skill, int32 &damage){ } } - damage += damage * GetMeleeDamageMod_SE(skill) / 100; + int dmgbonusmod = 0; + + dmgbonusmod += GetMeleeDamageMod_SE(skill); + if (opts) + dmgbonusmod += opts->melee_damage_bonus_flat; + + damage += damage * dmgbonusmod / 100; } bool Mob::HasDied() { @@ -4426,14 +4432,14 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type) return damage; } -void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse) +void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse, ExtraAttackOptions *opts) { if (!defender) return; - ApplyMeleeDamageBonus(skillInUse, damage); - damage += (damage * defender->GetSkillDmgTaken(skillInUse) / 100) + (GetSkillDmgAmt(skillInUse) + defender->GetFcDamageAmtIncoming(this, 0, true, skillInUse)); - TryCriticalHit(defender, skillInUse, damage); + ApplyMeleeDamageBonus(skillInUse, damage, opts); + damage += (damage * defender->GetSkillDmgTaken(skillInUse, opts) / 100) + (GetSkillDmgAmt(skillInUse) + defender->GetFcDamageAmtIncoming(this, 0, true, skillInUse)); + TryCriticalHit(defender, skillInUse, damage,opts); CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); } diff --git a/zone/common.h b/zone/common.h index bcae779a9..8a6d9c783 100644 --- a/zone/common.h +++ b/zone/common.h @@ -614,7 +614,8 @@ struct ExtraAttackOptions { : damage_percent(1.0f), damage_flat(0), armor_pen_percent(0.0f), armor_pen_flat(0), crit_percent(1.0f), crit_flat(0.0f), - hate_percent(1.0f), hate_flat(0), hit_chance(0) + hate_percent(1.0f), hate_flat(0), hit_chance(0), + melee_damage_bonus_flat(0), skilldmgtaken_bonus_flat(0) { } float damage_percent; @@ -626,6 +627,9 @@ struct ExtraAttackOptions { float hate_percent; int hate_flat; int hit_chance; + int melee_damage_bonus_flat; + int skilldmgtaken_bonus_flat; + }; #endif diff --git a/zone/mob.cpp b/zone/mob.cpp index 13a246ee4..05b6b828a 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3786,7 +3786,7 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining) return value; } -int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used) +int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used, ExtraAttackOptions *opts) { int skilldmg_mod = 0; @@ -3796,6 +3796,9 @@ int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used) skilldmg_mod += SkillDmgTaken_Mod[skill_used] + SkillDmgTaken_Mod[HIGHEST_SKILL+1]; + if (opts) + skilldmg_mod += opts->skilldmgtaken_bonus_flat; + if(skilldmg_mod < -100) skilldmg_mod = -100; diff --git a/zone/mob.h b/zone/mob.h index a3b759864..845b5fd00 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -160,13 +160,13 @@ public: uint32 TryHeadShot(Mob* defender, SkillUseTypes skillInUse); uint32 TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 ReuseTime); virtual void DoRiposte(Mob* defender); - void ApplyMeleeDamageBonus(uint16 skill, int32 &damage); + void ApplyMeleeDamageBonus(uint16 skill, int32 &damage,ExtraAttackOptions *opts = nullptr); virtual void MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts = nullptr); virtual int32 GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating); bool CombatRange(Mob* other); virtual inline bool IsBerserk() { return false; } // only clients void RogueEvade(Mob *other); - void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse); + void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse,ExtraAttackOptions *opts = nullptr); void BreakInvisibleSpells(); void CommonBreakInvisibleFromCombat(); bool HasDied(); @@ -645,7 +645,7 @@ public: int32 GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining); int32 GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill = false, uint16 skill=0); int32 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id); - int16 GetSkillDmgTaken(const SkillUseTypes skill_used); + int16 GetSkillDmgTaken(const SkillUseTypes skill_used,ExtraAttackOptions *opts=nullptr); void DoKnockback(Mob *caster, uint32 pushback, uint32 pushup); int16 CalcResistChanceBonus(); int16 CalcFearResistChance(); From bee5f316b74d45cf4dac5872d87e54239496d6fc Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Tue, 3 May 2016 12:49:05 -0400 Subject: [PATCH 068/693] Fix for special attacks that was causing most of them do to do the HitChance roll twice. --- zone/mob.h | 2 +- zone/special_attacks.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/mob.h b/zone/mob.h index 845b5fd00..7724dfaa8 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -787,7 +787,7 @@ public: int32 AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker); int32 ReduceAllDamage(int32 damage); - virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true); + virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool CheckHitChance=false, bool CanAvoid=true); virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* AmmoItem=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0, uint32 range_id=0, int AmmoSlot=0, float speed = 4.0f); virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime=0); virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0, uint32 range_id=0, uint32 ammo_id=0, const Item_Struct *AmmoItem=nullptr, int AmmoSlot=0, float speed= 4.0f); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 6f9e276a2..7d9bbc0d3 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -96,7 +96,7 @@ void Mob::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) } void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage, int32 hate_override,int ReuseTime, - bool HitChance, bool CanAvoid) { + bool CheckHitChance, bool CanAvoid) { //this really should go through the same code as normal melee damage to //pick up all the special behavior there @@ -140,7 +140,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if (max_damage == -3) DoRiposte(who); } else { - if (HitChance || who->CheckHitChance(this, skill, EQEmu::legacy::SlotPrimary)) { + if (!CheckHitChance || (CheckHitChance && who->CheckHitChance(this, skill, EQEmu::legacy::SlotPrimary))) { who->MeleeMitigation(this, max_damage, min_damage); CommonOutgoingHitSuccess(who, max_damage, skill); } else { From a49aef24c542ba1920fb48fdce2dbba863aa796c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 4 May 2016 03:00:56 -0400 Subject: [PATCH 069/693] Fix luabind::adl::object forward declare for clang clang didn't like this, and GCC likes both :P --- zone/lua_encounter.h | 6 ++++-- zone/lua_mob.h | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/zone/lua_encounter.h b/zone/lua_encounter.h index d4ce63bb9..f3d4598f7 100644 --- a/zone/lua_encounter.h +++ b/zone/lua_encounter.h @@ -8,7 +8,9 @@ class Encounter; namespace luabind { struct scope; - class object; + namespace adl { + class object; + } } luabind::scope lua_register_encounter(); @@ -27,4 +29,4 @@ public: }; #endif -#endif \ No newline at end of file +#endif diff --git a/zone/lua_mob.h b/zone/lua_mob.h index cbc34dc7d..48d1f3e14 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -11,7 +11,9 @@ class Lua_ItemInst; namespace luabind { struct scope; - class object; + namespace adl { + class object; + } } luabind::scope lua_register_mob(); From e304fe6558d89c4a8456fdb7ce584f6449cb6c63 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 4 May 2016 22:33:52 -0400 Subject: [PATCH 070/693] Clang appeasement --- zone/npc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index 6d09aa96e..dca6c2bcc 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1449,8 +1449,8 @@ void NPC::PickPocket(Client* thief) int steal_skill = thief->GetSkill(SkillPickPockets); int steal_chance = steal_skill * 100 / (5 * over_level + 5); - //Determine wheter to steal money or an item. - int money[6] = { 0, ((steal_skill >= 125) ? (GetPlatinum()) : (0)), ((steal_skill >= 60) ? (GetGold()) : (0)), GetSilver(), GetCopper(), 0 }; + // Determine whether to steal money or an item. + uint32 money[6] = { 0, ((steal_skill >= 125) ? (GetPlatinum()) : (0)), ((steal_skill >= 60) ? (GetGold()) : (0)), GetSilver(), GetCopper(), 0 }; bool has_coin = ((money[PickPocketPlatinum] | money[PickPocketGold] | money[PickPocketSilver] | money[PickPocketCopper]) != 0); bool steal_item = (steal_skill >= steal_chance && (zone->random.Roll(50) || !has_coin)); @@ -1539,7 +1539,7 @@ void NPC::PickPocket(Client* thief) return; } - thief->AddMoneyToPP(money[3], money[2], money[1], money[0], false); + thief->AddMoneyToPP(money[PickPocketCopper], money[PickPocketSilver], money[PickPocketGold], money[PickPocketPlatinum], false); thief->SendPickPocketResponse(this, coin_amount, coin_type); return; } From 3bf13c53492ddb32e0d3e574560bdb3000c2fb95 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 6 May 2016 13:34:13 -0400 Subject: [PATCH 071/693] Run the timeout_manager in loginserver (thanks image) --- loginserver/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 55d745b92..128bdd3c7 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -199,6 +199,7 @@ int main() Timer::SetCurrentTime(); server.client_manager->Process(); server.server_manager->Process(); + timeout_manager.CheckTimeouts(); Sleep(100); } From f85add14db33b5c994e745612f6d10463fd96bd0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 6 May 2016 21:31:46 -0400 Subject: [PATCH 072/693] Fix some undefined behavior issues? MakeAnyLenString results in UB (I think?) and is aggressively optimized out with clang GrantAlternateAdvancementAbility were missing return statements and clang had fun times with those functions too --- common/database.cpp | 8 +------- zone/lua_client.cpp | 4 ++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index f223418ab..f33569fd2 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -860,17 +860,11 @@ void Database::GetCharName(uint32 char_id, char* name) { } bool Database::LoadVariables() { - char *query = nullptr; - - auto results = QueryDatabase(query, LoadVariables_MQ(&query)); + auto results = QueryDatabase(StringFormat("SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= %d", varcache_lastupdate)); if (!results.Success()) - { - safe_delete_array(query); return false; - } - safe_delete_array(query); return LoadVariables_result(std::move(results)); } diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 331067d36..935516040 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1049,12 +1049,12 @@ void Lua_Client::IncrementAA(int aa) { bool Lua_Client::GrantAlternateAdvancementAbility(int aa_id, int points) { Lua_Safe_Call_Bool(); - self->GrantAlternateAdvancementAbility(aa_id, points); + return self->GrantAlternateAdvancementAbility(aa_id, points); } bool Lua_Client::GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost) { Lua_Safe_Call_Bool(); - self->GrantAlternateAdvancementAbility(aa_id, points, ignore_cost); + return self->GrantAlternateAdvancementAbility(aa_id, points, ignore_cost); } void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z) { From 20a36151b33ec267475579125ec1ae90ded6c8ef Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 6 May 2016 22:04:21 -0400 Subject: [PATCH 073/693] Make Client::TradeskillSearchResults take a reference --- zone/client.h | 2 +- zone/tradeskills.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client.h b/zone/client.h index a17e59f40..79413da98 100644 --- a/zone/client.h +++ b/zone/client.h @@ -699,7 +699,7 @@ public: inline uint16 MaxSkill(SkillUseTypes skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); } uint8 SkillTrainLevel(SkillUseTypes skillid, uint16 class_); - void TradeskillSearchResults(const std::string query, unsigned long objtype, unsigned long someid); + void TradeskillSearchResults(const std::string &query, unsigned long objtype, unsigned long someid); void SendTradeskillDetails(uint32 recipe_id); bool TradeskillExecute(DBTradeskillRecipe_Struct *spec); void CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float skillup_modifier, uint16 success_modifier, SkillUseTypes tradeskill); diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index ffdafaeb1..863a0603c 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -680,7 +680,7 @@ SkillUseTypes Object::TypeToSkill(uint32 type) return TradeskillUnknown; } -void Client::TradeskillSearchResults(const std::string query, unsigned long objtype, unsigned long someid) { +void Client::TradeskillSearchResults(const std::string &query, unsigned long objtype, unsigned long someid) { auto results = database.QueryDatabase(query); if (!results.Success()) { From 74b3fe9d61a41d8e0602a30e3c5a3ac128c65150 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 6 May 2016 22:42:19 -0400 Subject: [PATCH 074/693] Potential memory leak fix --- zone/doors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/doors.cpp b/zone/doors.cpp index 0a5227988..76bdbdb20 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -177,8 +177,8 @@ void Doors::HandleClick(Client* sender, uint8 trigger) ads->id = GetDoorDBID(); worldserver.SendPacket(pack); safe_delete(pack); - safe_delete(outapp); } + safe_delete(outapp); return; } } From 47c9182ba3ee2f5ad1c89d8b3e72a8f2389c86d0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 6 May 2016 22:58:45 -0400 Subject: [PATCH 075/693] Fix potential memory leaks (clang-tidy) --- zone/client.cpp | 162 +++++++++++++++++++++------------------- zone/client_packet.cpp | 1 + zone/command.cpp | 1 + zone/entity.cpp | 1 + zone/pets.cpp | 1 + zone/spawngroup.cpp | 163 +++++++++++++++++++++-------------------- zone/trading.cpp | 12 ++- 7 files changed, 183 insertions(+), 158 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index f2ca38474..a6b2f3243 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2568,25 +2568,25 @@ void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 } } -bool Client::BindWound(Mob* bindmob, bool start, bool fail){ - EQApplicationPacket* outapp = 0; - if(!fail) - { +bool Client::BindWound(Mob *bindmob, bool start, bool fail) +{ + EQApplicationPacket *outapp = nullptr; + if (!fail) { outapp = new EQApplicationPacket(OP_Bind_Wound, sizeof(BindWound_Struct)); - BindWound_Struct* bind_out = (BindWound_Struct*) outapp->pBuffer; + BindWound_Struct *bind_out = (BindWound_Struct *)outapp->pBuffer; // Start bind - if(!bindwound_timer.Enabled()) - { - //make sure we actually have a bandage... and consume it. - int16 bslot = m_inv.HasItemByUse(ItemTypeBandage, 1, invWhereWorn|invWherePersonal); + if (!bindwound_timer.Enabled()) { + // make sure we actually have a bandage... and consume it. + int16 bslot = m_inv.HasItemByUse(ItemTypeBandage, 1, invWhereWorn | invWherePersonal); if (bslot == INVALID_INDEX) { bind_out->type = 3; QueuePacket(outapp); - bind_out->type = 7; //this is the wrong message, dont know the right one. + bind_out->type = 7; // this is the wrong message, dont know the right one. QueuePacket(outapp); - return(true); + safe_delete(outapp); + return (true); } - DeleteItemInInventory(bslot, 1, true); //do we need client update? + DeleteItemInInventory(bslot, 1, true); // do we need client update? // start complete timer bindwound_timer.Start(10000); @@ -2597,51 +2597,46 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ QueuePacket(outapp); bind_out->type = 0; // Client Unlocked - if(!bindmob) { + if (!bindmob) { // send "bindmob dead" to client bind_out->type = 4; QueuePacket(outapp); bind_out->type = 0; bindwound_timer.Disable(); bindwound_target = 0; - } - else { + } else { // send bindmob "stand still" - if(!bindmob->IsAIControlled() && bindmob != this ) { - bindmob->CastToClient()->Message_StringID(clientMessageYellow, YOU_ARE_BEING_BANDAGED); - } - else if (bindmob->IsAIControlled() && bindmob != this ){ + if (!bindmob->IsAIControlled() && bindmob != this) { + bindmob->CastToClient()->Message_StringID(clientMessageYellow, + YOU_ARE_BEING_BANDAGED); + } else if (bindmob->IsAIControlled() && bindmob != this) { ; // Tell IPC to stand still? - } - else { + } else { ; // Binding self } } - } - else if (bindwound_timer.Check()) // Did the timer finish? + } else if (bindwound_timer.Check()) // Did the timer finish? { - // finish bind + // finish bind // disable complete timer bindwound_timer.Disable(); bindwound_target = 0; - if(!bindmob){ - // send "bindmob gone" to client - bind_out->type = 5; // not in zone - QueuePacket(outapp); - bind_out->type = 0; + if (!bindmob) { + // send "bindmob gone" to client + bind_out->type = 5; // not in zone + QueuePacket(outapp); + bind_out->type = 0; } else { - if (!GetFeigned() && (DistanceSquared(bindmob->GetPosition(), m_Position) <= 400)) { + if (!GetFeigned() && (DistanceSquared(bindmob->GetPosition(), m_Position) <= 400)) { // send bindmob bind done - if(!bindmob->IsAIControlled() && bindmob != this ) { + if (!bindmob->IsAIControlled() && bindmob != this) { - } - else if(bindmob->IsAIControlled() && bindmob != this ) { - // Tell IPC to resume?? - } - else { - // Binding self + } else if (bindmob->IsAIControlled() && bindmob != this) { + // Tell IPC to resume?? + } else { + // Binding self } // Send client bind done @@ -2650,58 +2645,61 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ bind_out->type = 0; CheckIncreaseSkill(SkillBindWound, nullptr, 5); - int maxHPBonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound + aabonuses.MaxBindWound; + int maxHPBonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound + + aabonuses.MaxBindWound; int max_percent = 50 + 10 * maxHPBonus; - if(GetClass() == MONK && GetSkill(SkillBindWound) > 200) { + if (GetClass() == MONK && GetSkill(SkillBindWound) > 200) { max_percent = 70 + 10 * maxHPBonus; } max_percent = mod_bindwound_percent(max_percent, bindmob); - int max_hp = bindmob->GetMaxHP()*max_percent/100; + int max_hp = bindmob->GetMaxHP() * max_percent / 100; // send bindmob new hp's - if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() <= (max_hp)-1){ + if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() <= (max_hp)-1) { // 0.120 per skill point, 0.60 per skill level, minimum 3 max 30 int bindhps = 3; - if (GetSkill(SkillBindWound) > 200) { - bindhps += GetSkill(SkillBindWound)*4/10; + bindhps += GetSkill(SkillBindWound) * 4 / 10; } else if (GetSkill(SkillBindWound) >= 10) { - bindhps += GetSkill(SkillBindWound)/4; + bindhps += GetSkill(SkillBindWound) / 4; } - //Implementation of aaMithanielsBinding is a guess (the multiplier) - int bindBonus = spellbonuses.BindWound + itembonuses.BindWound + aabonuses.BindWound; + // Implementation of aaMithanielsBinding is a guess (the multiplier) + int bindBonus = spellbonuses.BindWound + itembonuses.BindWound + + aabonuses.BindWound; - bindhps += bindhps*bindBonus / 100; + bindhps += bindhps * bindBonus / 100; bindhps = mod_bindwound_hp(bindhps, bindmob); - //if the bind takes them above the max bindable - //cap it at that value. Dont know if live does it this way - //but it makes sense to me. + // if the bind takes them above the max bindable + // cap it at that value. Dont know if live does it this way + // but it makes sense to me. int chp = bindmob->GetHP() + bindhps; - if(chp > max_hp) + if (chp > max_hp) chp = max_hp; bindmob->SetHP(chp); bindmob->SendHPUpdate(); - } - else { - //I dont have the real, live - Message(15, "You cannot bind wounds above %d%% hitpoints.", max_percent); - if(bindmob != this && bindmob->IsClient()) - bindmob->CastToClient()->Message(15, "You cannot have your wounds bound above %d%% hitpoints.", max_percent); + } else { + // I dont have the real, live + Message(15, "You cannot bind wounds above %d%% hitpoints.", + max_percent); + if (bindmob != this && bindmob->IsClient()) + bindmob->CastToClient()->Message( + 15, + "You cannot have your wounds bound above %d%% hitpoints.", + max_percent); // Too many hp message goes here. } - } - else { + } else { // Send client bind failed - if(bindmob != this) + if (bindmob != this) bind_out->type = 6; // They moved else bind_out->type = 7; // Bandager moved @@ -2711,11 +2709,10 @@ bool Client::BindWound(Mob* bindmob, bool start, bool fail){ } } } - } - else if (bindwound_timer.Enabled()) { + } else if (bindwound_timer.Enabled()) { // You moved outapp = new EQApplicationPacket(OP_Bind_Wound, sizeof(BindWound_Struct)); - BindWound_Struct* bind_out = (BindWound_Struct*) outapp->pBuffer; + BindWound_Struct *bind_out = (BindWound_Struct *)outapp->pBuffer; bindwound_timer.Disable(); bindwound_target = 0; bind_out->type = 7; @@ -3649,19 +3646,25 @@ void Client::SetEndurance(int32 newEnd) SendManaUpdatePacket(); } -void Client::SacrificeConfirm(Client *caster) { +void Client::SacrificeConfirm(Client *caster) +{ + EQApplicationPacket *outapp = new EQApplicationPacket(OP_Sacrifice, sizeof(Sacrifice_Struct)); + Sacrifice_Struct *ss = (Sacrifice_Struct *)outapp->pBuffer; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sacrifice, sizeof(Sacrifice_Struct)); - Sacrifice_Struct *ss = (Sacrifice_Struct*)outapp->pBuffer; - - if(!caster || PendingSacrifice) return; - - if(GetLevel() < RuleI(Spells, SacrificeMinLevel)){ - caster->Message_StringID(13, SAC_TOO_LOW); //This being is not a worthy sacrifice. + if (!caster || PendingSacrifice) { + safe_delete(outapp); return; } + + if (GetLevel() < RuleI(Spells, SacrificeMinLevel)) { + caster->Message_StringID(13, SAC_TOO_LOW); // This being is not a worthy sacrifice. + safe_delete(outapp); + return; + } + if (GetLevel() > RuleI(Spells, SacrificeMaxLevel)) { caster->Message_StringID(13, SAC_TOO_HIGH); + safe_delete(outapp); return; } @@ -3803,20 +3806,23 @@ void Client::SetHoTT(uint32 mobid) { safe_delete(outapp); } -void Client::SendPopupToClient(const char *Title, const char *Text, uint32 PopupID, uint32 Buttons, uint32 Duration) { +void Client::SendPopupToClient(const char *Title, const char *Text, uint32 PopupID, uint32 Buttons, uint32 Duration) +{ EQApplicationPacket *outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); - OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *) outapp->pBuffer; + OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *)outapp->pBuffer; - if((strlen(Title) > (sizeof(olms->Title)-1)) || - (strlen(Text) > (sizeof(olms->Text)-1))) return; + if ((strlen(Title) > (sizeof(olms->Title) - 1)) || (strlen(Text) > (sizeof(olms->Text) - 1))) { + safe_delete(outapp); + return; + } strcpy(olms->Title, Title); strcpy(olms->Text, Text); olms->Buttons = Buttons; - if(Duration > 0) + if (Duration > 0) olms->Duration = Duration * 1000; else olms->Duration = 0xffffffff; @@ -3843,8 +3849,10 @@ void Client::SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const EQApplicationPacket* app = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); OnLevelMessage_Struct* olms=(OnLevelMessage_Struct*)app->pBuffer; - if(strlen(Text) > (sizeof(olms->Text)-1)) + if(strlen(Text) > (sizeof(olms->Text)-1)) { + safe_delete(app); return; + } if(!target) title_type = 0; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 75ed6771e..5222ca96c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -13691,6 +13691,7 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app) else { Log.Out(Logs::Detail, Logs::Trading, "Client::Handle_OP_TraderShop: entity_list.GetClientByID(tcs->traderid)" " returned a nullptr pointer"); + safe_delete(outapp); return; } diff --git a/zone/command.cpp b/zone/command.cpp index 671a793cb..93f77c6a8 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -3171,6 +3171,7 @@ void command_equipitem(Client *c, const Seperator *sep) if (partialmove) { // remove this con check if someone can figure out removing charges from cursor stack issue below // mi->number_in_stack is always from_inst->GetCharges() when partialmove is false c->Message(13, "Error: Partial stack added to existing stack exceeds allowable stacksize"); + safe_delete(outapp); return; } else if(c->SwapItem(mi)) { diff --git a/zone/entity.cpp b/zone/entity.cpp index ee9d65b72..ccc546ad1 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -4567,6 +4567,7 @@ void EntityList::ExpeditionWarning(uint32 minutes_left) it->second->QueuePacket(outapp); ++it; } + safe_delete(outapp); } Mob *EntityList::GetClosestMobByBodyType(Mob *sender, bodyType BodyType) diff --git a/zone/pets.cpp b/zone/pets.cpp index 63e1a832c..00ffebc58 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -383,6 +383,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, "ORDER BY RAND() LIMIT 1", zone->GetShortName()); auto results = database.QueryDatabase(query); if (!results.Success()) { + safe_delete(npc_type); return; } diff --git a/zone/spawngroup.cpp b/zone/spawngroup.cpp index 1661e0fe8..a810cc9f8 100644 --- a/zone/spawngroup.cpp +++ b/zone/spawngroup.cpp @@ -139,90 +139,97 @@ bool SpawnGroupList::RemoveSpawnGroup(uint32 in_id) { return(true); } -bool ZoneDatabase::LoadSpawnGroups(const char* zone_name, uint16 version, SpawnGroupList* spawn_group_list) { - +bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnGroupList *spawn_group_list) +{ std::string query = StringFormat("SELECT DISTINCT(spawngroupID), spawngroup.name, spawngroup.spawn_limit, " - "spawngroup.dist, spawngroup.max_x, spawngroup.min_x, " - "spawngroup.max_y, spawngroup.min_y, spawngroup.delay, " - "spawngroup.despawn, spawngroup.despawn_timer, spawngroup.mindelay " - "FROM spawn2, spawngroup WHERE spawn2.spawngroupID = spawngroup.ID " - "AND spawn2.version = %u and zone = '%s'", version, zone_name); - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - SpawnGroup* newSpawnGroup = new SpawnGroup(atoi(row[0]), row[1], atoi(row[2]), atof(row[3]), - atof(row[4]), atof(row[5]), atof(row[6]), atof(row[7]), - atoi(row[8]), atoi(row[9]), atoi(row[10]), atoi(row[11])); - spawn_group_list->AddSpawnGroup(newSpawnGroup); - } - - query = StringFormat("SELECT DISTINCT spawnentry.spawngroupID, npcid, chance, " - "npc_types.spawn_limit AS sl " - "FROM spawnentry, spawn2, npc_types " - "WHERE spawnentry.npcID=npc_types.id " - "AND spawnentry.spawngroupID = spawn2.spawngroupID " - "AND zone = '%s'", zone_name); - results = QueryDatabase(query); - if (!results.Success()) { - Log.Out(Logs::General, Logs::Error, "Error2 in PopulateZoneLists query '%'", query.c_str()); - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - SpawnEntry* newSpawnEntry = new SpawnEntry( atoi(row[1]), atoi(row[2]), row[3]?atoi(row[3]):0); - SpawnGroup *sg = spawn_group_list->GetSpawnGroup(atoi(row[0])); - - if (!sg) { - continue; - } - - sg->AddSpawnEntry(newSpawnEntry); - } - - return true; -} - -bool ZoneDatabase::LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_group_list) { - - - std::string query = StringFormat("SELECT DISTINCT(spawngroup.id), spawngroup.name, spawngroup.spawn_limit, " - "spawngroup.dist, spawngroup.max_x, spawngroup.min_x, " - "spawngroup.max_y, spawngroup.min_y, spawngroup.delay, " - "spawngroup.despawn, spawngroup.despawn_timer, spawngroup.mindelay " - "FROM spawngroup WHERE spawngroup.ID = '%i'", spawngroupid); - auto results = QueryDatabase(query); - if (!results.Success()) { - Log.Out(Logs::General, Logs::Error, "Error2 in PopulateZoneLists query %s", query.c_str()); - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - SpawnGroup* newSpawnGroup = new SpawnGroup(atoi(row[0]), row[1], atoi(row[2]), atof(row[3]), atof(row[4]), atof(row[5]), atof(row[6]), atof(row[7]), atoi(row[8]), atoi(row[9]), atoi(row[10]), atoi(row[11])); - spawn_group_list->AddSpawnGroup(newSpawnGroup); - } - - query = StringFormat("SELECT DISTINCT(spawnentry.spawngroupID), spawnentry.npcid, " - "spawnentry.chance, spawngroup.spawn_limit FROM spawnentry, spawngroup " - "WHERE spawnentry.spawngroupID = '%i' AND spawngroup.spawn_limit = '0' " - "ORDER BY chance", spawngroupid); - results = QueryDatabase(query); + "spawngroup.dist, spawngroup.max_x, spawngroup.min_x, " + "spawngroup.max_y, spawngroup.min_y, spawngroup.delay, " + "spawngroup.despawn, spawngroup.despawn_timer, spawngroup.mindelay " + "FROM spawn2, spawngroup WHERE spawn2.spawngroupID = spawngroup.ID " + "AND spawn2.version = %u and zone = '%s'", + version, zone_name); + auto results = QueryDatabase(query); if (!results.Success()) { - Log.Out(Logs::General, Logs::Error, "Error3 in PopulateZoneLists query '%s'", query.c_str()); return false; } - for(auto row = results.begin(); row != results.end(); ++row) { - SpawnEntry* newSpawnEntry = new SpawnEntry( atoi(row[1]), atoi(row[2]), row[3]?atoi(row[3]):0); - SpawnGroup *sg = spawn_group_list->GetSpawnGroup(atoi(row[0])); - if (!sg) { - continue; - } + for (auto row = results.begin(); row != results.end(); ++row) { + SpawnGroup *newSpawnGroup = new SpawnGroup(atoi(row[0]), row[1], atoi(row[2]), atof(row[3]), + atof(row[4]), atof(row[5]), atof(row[6]), atof(row[7]), + atoi(row[8]), atoi(row[9]), atoi(row[10]), atoi(row[11])); + spawn_group_list->AddSpawnGroup(newSpawnGroup); + } - sg->AddSpawnEntry(newSpawnEntry); - } + query = StringFormat("SELECT DISTINCT spawnentry.spawngroupID, npcid, chance, " + "npc_types.spawn_limit AS sl " + "FROM spawnentry, spawn2, npc_types " + "WHERE spawnentry.npcID=npc_types.id " + "AND spawnentry.spawngroupID = spawn2.spawngroupID " + "AND zone = '%s'", + zone_name); + results = QueryDatabase(query); + if (!results.Success()) { + Log.Out(Logs::General, Logs::Error, "Error2 in PopulateZoneLists query '%'", query.c_str()); + return false; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + SpawnEntry *newSpawnEntry = new SpawnEntry(atoi(row[1]), atoi(row[2]), row[3] ? atoi(row[3]) : 0); + SpawnGroup *sg = spawn_group_list->GetSpawnGroup(atoi(row[0])); + + if (!sg) { + safe_delete(newSpawnEntry); + continue; + } + + sg->AddSpawnEntry(newSpawnEntry); + } + + return true; +} + +bool ZoneDatabase::LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList *spawn_group_list) +{ + std::string query = StringFormat("SELECT DISTINCT(spawngroup.id), spawngroup.name, spawngroup.spawn_limit, " + "spawngroup.dist, spawngroup.max_x, spawngroup.min_x, " + "spawngroup.max_y, spawngroup.min_y, spawngroup.delay, " + "spawngroup.despawn, spawngroup.despawn_timer, spawngroup.mindelay " + "FROM spawngroup WHERE spawngroup.ID = '%i'", + spawngroupid); + auto results = QueryDatabase(query); + if (!results.Success()) { + Log.Out(Logs::General, Logs::Error, "Error2 in PopulateZoneLists query %s", query.c_str()); + return false; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + SpawnGroup *newSpawnGroup = new SpawnGroup(atoi(row[0]), row[1], atoi(row[2]), atof(row[3]), + atof(row[4]), atof(row[5]), atof(row[6]), atof(row[7]), + atoi(row[8]), atoi(row[9]), atoi(row[10]), atoi(row[11])); + spawn_group_list->AddSpawnGroup(newSpawnGroup); + } + + query = StringFormat("SELECT DISTINCT(spawnentry.spawngroupID), spawnentry.npcid, " + "spawnentry.chance, spawngroup.spawn_limit FROM spawnentry, spawngroup " + "WHERE spawnentry.spawngroupID = '%i' AND spawngroup.spawn_limit = '0' " + "ORDER BY chance", + spawngroupid); + results = QueryDatabase(query); + if (!results.Success()) { + Log.Out(Logs::General, Logs::Error, "Error3 in PopulateZoneLists query '%s'", query.c_str()); + return false; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + SpawnEntry *newSpawnEntry = new SpawnEntry(atoi(row[1]), atoi(row[2]), row[3] ? atoi(row[3]) : 0); + SpawnGroup *sg = spawn_group_list->GetSpawnGroup(atoi(row[0])); + if (!sg) { + safe_delete(newSpawnEntry); + continue; + } + + sg->AddSpawnEntry(newSpawnEntry); + } return true; } diff --git a/zone/trading.cpp b/zone/trading.cpp index ff9c60559..fe83e4e67 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -2401,8 +2401,10 @@ void Client::SendBuyerResults(char* searchString, uint32 searchID) { const Item_Struct* item = database.GetItem(itemID); - if(!item) + if(!item) { + safe_delete(outapp); continue; + } // Save having to scan the client list when dealing with multiple buylines for the same Character. if(charID != lastCharID) { @@ -2410,8 +2412,10 @@ void Client::SendBuyerResults(char* searchString, uint32 searchID) { lastCharID = charID; } - if(!buyer) + if(!buyer) { + safe_delete(outapp); continue; + } VARSTRUCT_ENCODE_TYPE(uint32, buf, Barter_BuyerSearchResults); // Command VARSTRUCT_ENCODE_TYPE(uint32, buf, searchID); // Match up results with the request @@ -2493,8 +2497,10 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) { const Item_Struct* item = database.GetItem(ItemID); - if(!item) + if(!item) { + safe_delete(outapp); continue; + } VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerInspectWindow); VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot); From 907bc68e1c65142cc225708ade33ddbcca3c3afc Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 6 May 2016 23:14:48 -0400 Subject: [PATCH 076/693] Mismatched delete statement --- world/zonelist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/zonelist.cpp b/world/zonelist.cpp index 3332e0578..abd5c1057 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -598,7 +598,7 @@ void ZSList::RebootZone(const char* ip1,uint16 port,const char* ip2, uint32 skip iterator.Advance(); } if (y == 0) { - safe_delete(tmp); + safe_delete_array(tmp); return; } uint32 z = emu_random.Int(0, y-1); From 1a1f5ae61906a261944df1f4c0f24f9c59a30ac9 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 8 May 2016 20:21:50 -0400 Subject: [PATCH 077/693] Titanium::SerializeItem() rework --- changelog.txt | 3 + common/CMakeLists.txt | 32 ++-- common/patches/titanium.cpp | 305 ++++++++++++++++++++---------- common/patches/titanium_structs.h | 171 +++++++++++++++++ 4 files changed, 400 insertions(+), 111 deletions(-) diff --git a/changelog.txt b/changelog.txt index c4eff06b3..1bc585aa1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/08/2016 == +Uleat: Re-coded Titanium client translator 'SerializeItem()' to use coded property assignments over file enumerated ones + == 04/22/2016 == Uleat: Reworked ClientVersion into namespace EQEmu; Added InventoryVersion Uleat: Delinked current inventory slot enumeration and constants from EQEmu::constants and global definition (inv2 pre-work) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 12b656716..6c13aefbc 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -202,13 +202,13 @@ SET(common_headers patches/patches.h patches/sod.h patches/sod_constants.h - patches/sod_itemfields.h +# patches/sod_itemfields.h patches/sod_ops.h patches/sod_structs.h patches/sof.h patches/sof_constants.h - patches/sof_itemfields.h - patches/sof_opcode_list.h +# patches/sof_itemfields.h +# patches/sof_opcode_list.h patches/sof_ops.h patches/sof_structs.h patches/ss_declare.h @@ -216,23 +216,23 @@ SET(common_headers patches/ss_register.h patches/rof.h patches/rof_constants.h - patches/rof_itemfields.h +# patches/rof_itemfields.h patches/rof_ops.h patches/rof_structs.h patches/rof2.h patches/rof2_constants.h - patches/rof2_itemfields.h +# patches/rof2_itemfields.h patches/rof2_ops.h patches/rof2_structs.h patches/titanium.h patches/titanium_constants.h - patches/titanium_itemfields_a.h - patches/titanium_itemfields_b.h +# patches/titanium_itemfields_a.h +# patches/titanium_itemfields_b.h patches/titanium_ops.h patches/titanium_structs.h patches/uf.h patches/uf_constants.h - patches/uf_itemfields.h +# patches/uf_itemfields.h patches/uf_ops.h patches/uf_structs.h SocketLib/Base64.h @@ -255,13 +255,13 @@ SET(common_headers SOURCE_GROUP(Patches FILES patches/patches.h patches/sod.h - patches/sod_itemfields.h +# patches/sod_itemfields.h patches/sod_ops.h patches/sod_constants.h patches/sod_structs.h patches/sof.h - patches/sof_itemfields.h - patches/sof_opcode_list.h +# patches/sof_itemfields.h +# patches/sof_opcode_list.h patches/sof_ops.h patches/sof_constants.h patches/sof_structs.h @@ -269,23 +269,23 @@ SOURCE_GROUP(Patches FILES patches/ss_define.h patches/ss_register.h patches/rof.h - patches/rof_itemfields.h +# patches/rof_itemfields.h patches/rof_ops.h patches/rof_constants.h patches/rof_structs.h patches/rof2.h - patches/rof2_itemfields.h +# patches/rof2_itemfields.h patches/rof2_ops.h patches/rof2_constants.h patches/rof2_structs.h patches/titanium.h - patches/titanium_itemfields_a.h - patches/titanium_itemfields_b.h +# patches/titanium_itemfields_a.h +# patches/titanium_itemfields_b.h patches/titanium_ops.h patches/titanium_constants.h patches/titanium_structs.h patches/uf.h - patches/uf_itemfields.h +# patches/uf_itemfields.h patches/uf_ops.h patches/uf_constants.h patches/uf_structs.h diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index cb291150c..a8a25fd13 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -20,7 +20,7 @@ namespace Titanium static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth); + std::string SerializeItem(const ItemInst *inst, int16 slot_id_in, uint8 depth); // server to client inventory location converters static inline int16 ServerToTitaniumSlot(uint32 serverSlot); @@ -275,14 +275,12 @@ namespace Titanium InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; //do the transform... - int r; std::string serial_string; - for (r = 0; r < itemcount; r++, eq++) { - uint32 length; - char *serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &length, 0); - if (serialized) { - serial_string.append(serialized, length + 1); - safe_delete_array(serialized); + for (int r = 0; r < itemcount; r++, eq++) { + std::string serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, 0); // assumed move operation: string& = string&& + if (!serialized.empty()) { + serial_string.append(serialized); + serial_string.push_back('\0'); } else { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); @@ -290,9 +288,10 @@ namespace Titanium } - in->size = serial_string.length(); + // do we need to account for a trailing null escape? + in->size = serial_string.size(); in->pBuffer = new unsigned char[in->size]; - memcpy(in->pBuffer, serial_string.c_str(), serial_string.length()); + memcpy(in->pBuffer, serial_string.c_str(), serial_string.size()); delete[] __emu_buffer; @@ -725,22 +724,21 @@ namespace Titanium ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer; InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem); - uint32 length; - char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0); - - if (!serialized) { + std::string serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, 0); // assumed move operation: string& = string&& + if (serialized.empty()) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - in->size = length + 5; // ItemPacketType + Serialization + \0 + + in->size = serialized.size() + 5; // ItemPacketType + Serialization + \0 in->pBuffer = new unsigned char[in->size]; ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer; new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(new_item_pkt->SerializedItem, serialized, length + 1); + memcpy(new_item_pkt->SerializedItem, serialized.c_str(), serialized.size()); + new_item_pkt->SerializedItem[serialized.size()] = '\0'; delete[] __emu_buffer; - safe_delete_array(serialized); dest->FastQueuePacket(&in, ack_req); } @@ -2079,90 +2077,207 @@ namespace Titanium } // file scope helper methods - char *SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth) + std::string SerializeItem(const ItemInst *inst, int16 slot_id_in, uint8 depth) { - char *serialization = nullptr; - char *instance = nullptr; - const char *protection = (const char *)"\\\\\\\\\\"; - char *sub_items[10] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; - bool stackable = inst->IsStackable(); - int16 slot_id = ServerToTitaniumSlot(slot_id_in); - uint32 merchant_slot = inst->GetMerchantSlot(); - int16 charges = inst->GetCharges(); - const Item_Struct *item = inst->GetUnscaledItem(); - int i; - uint32 sub_length; + std::string serialization; + std::string instance; + std::string protection = "\\\\\\\\\\"; + const Item_Struct* item = inst->GetUnscaledItem(); - MakeAnyLenString(&instance, - "%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|", - stackable ? charges : 0, - 0, - //(merchant_slot == 0) ? slot_id : merchant_slot, // change when translator activated - (merchant_slot == 0) ? slot_id_in : merchant_slot, - inst->GetPrice(), - (merchant_slot == 0) ? 1 : inst->GetMerchantCount(), - inst->IsScaling() ? inst->GetExp() / 100 : 0, - //merchant_slot, //instance ID, bullshit for now - (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot, - inst->GetRecastTimestamp(), - (stackable ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : charges), - inst->IsAttuned() ? 1 : 0, - 0 - ); + instance = StringFormat("%i|", (inst->IsStackable() ? inst->GetCharges() : 0)); // stack count + instance.append("0|"); // unknown + instance.append(StringFormat("%i|", (!inst->GetMerchantSlot() ? slot_id_in : inst->GetMerchantSlot()))); // inst slot/merchant slot + instance.append(StringFormat("%i|", inst->GetPrice())); // merchant price + instance.append(StringFormat("%i|", (!inst->GetMerchantSlot() ? 1 : inst->GetMerchantCount()))); // inst count/merchant count + instance.append(StringFormat("%i|", (inst->IsScaling() ? (inst->GetExp() / 100) : 0))); // inst experience + instance.append(StringFormat("%i|", (!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot()))); // merchant serial number + instance.append(StringFormat("%i|", inst->GetRecastTimestamp())); // recast timestamp + instance.append(StringFormat("%i|", ((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges())))); // charge count + instance.append(StringFormat("%i|", (inst->IsAttuned() ? 1 : 0))); // inst attuned + instance.append("0|"); // unknown - for (i = 0; i<10; i++) { - ItemInst *sub = inst->GetItem(i); - if (sub) { - sub_items[i] = SerializeItem(sub, 0, &sub_length, depth + 1); + serialization = StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection.c_str(), (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; + serialization.append(StringFormat("%s", instance.c_str())); // Instance data + serialization.append(StringFormat("%.*s\"", depth, protection.c_str())); // Quotes (and protection, if needed) around static data + + serialization.append(StringFormat("%i", item->ItemClass)); // item->ItemClass so we can do |%s instead of %s| + +//#include "titanium_itemfields_a.h" - begin + serialization.append(StringFormat("|%s", item->Name)); + serialization.append(StringFormat("|%s", item->Lore)); + serialization.append(StringFormat("|%s", item->IDFile)); + serialization.append(StringFormat("|%i", item->ID)); +//#include "titanium_itemfields_a.h" - end + serialization.append(StringFormat("|%i", ((item->Weight > 255) ? 255 : item->Weight))); +//#include "titanium_itemfields_b.h" - begin + serialization.append(StringFormat("|%i", item->NoRent)); + serialization.append(StringFormat("|%i", item->NoDrop)); + serialization.append(StringFormat("|%i", item->Size)); + serialization.append(StringFormat("|%i", item->Slots)); + serialization.append(StringFormat("|%i", item->Price)); + serialization.append(StringFormat("|%i", item->Icon)); + serialization.append("|0"); // unknown + serialization.append("|0"); // unknown + serialization.append(StringFormat("|%i", item->BenefitFlag)); + serialization.append(StringFormat("|%i", item->Tradeskills)); + serialization.append(StringFormat("|%i", item->CR)); + serialization.append(StringFormat("|%i", item->DR)); + serialization.append(StringFormat("|%i", item->PR)); + serialization.append(StringFormat("|%i", item->MR)); + serialization.append(StringFormat("|%i", item->FR)); + serialization.append(StringFormat("|%i", item->AStr)); + serialization.append(StringFormat("|%i", item->ASta)); + serialization.append(StringFormat("|%i", item->AAgi)); + serialization.append(StringFormat("|%i", item->ADex)); + serialization.append(StringFormat("|%i", item->ACha)); + serialization.append(StringFormat("|%i", item->AInt)); + serialization.append(StringFormat("|%i", item->AWis)); + serialization.append(StringFormat("|%i", item->HP)); + serialization.append(StringFormat("|%i", item->Mana)); + serialization.append(StringFormat("|%i", item->AC)); + serialization.append(StringFormat("|%i", item->Deity)); + serialization.append(StringFormat("|%i", item->SkillModValue)); + serialization.append(StringFormat("|%i", item->SkillModMax)); + serialization.append(StringFormat("|%i", item->SkillModType)); + serialization.append(StringFormat("|%i", item->BaneDmgRace)); + serialization.append(StringFormat("|%i", item->BaneDmgAmt)); + serialization.append(StringFormat("|%i", item->BaneDmgBody)); + serialization.append(StringFormat("|%i", item->Magic)); + serialization.append(StringFormat("|%i", item->CastTime_)); + serialization.append(StringFormat("|%i", item->ReqLevel)); + serialization.append(StringFormat("|%i", item->BardType)); + serialization.append(StringFormat("|%i", item->BardValue)); + serialization.append(StringFormat("|%i", item->Light)); + serialization.append(StringFormat("|%i", item->Delay)); + serialization.append(StringFormat("|%i", item->RecLevel)); + serialization.append(StringFormat("|%i", item->RecSkill)); + serialization.append(StringFormat("|%i", item->ElemDmgType)); + serialization.append(StringFormat("|%i", item->ElemDmgAmt)); + serialization.append(StringFormat("|%i", item->Range)); + serialization.append(StringFormat("|%i", item->Damage)); + serialization.append(StringFormat("|%i", item->Color)); + serialization.append(StringFormat("|%i", item->Classes)); + serialization.append(StringFormat("|%i", item->Races)); + serialization.append("|0"); // unknown + serialization.append(StringFormat("|%i", item->MaxCharges)); + serialization.append(StringFormat("|%i", item->ItemType)); + serialization.append(StringFormat("|%i", item->Material)); + serialization.append(StringFormat("|%i", item->SellRate)); + serialization.append("|0"); // unknown + serialization.append(StringFormat("|%i", item->CastTime_)); + serialization.append("|0"); // unknown + serialization.append(StringFormat("|%i", item->ProcRate)); + serialization.append(StringFormat("|%i", item->CombatEffects)); + serialization.append(StringFormat("|%i", item->Shielding)); + serialization.append(StringFormat("|%i", item->StunResist)); + serialization.append(StringFormat("|%i", item->StrikeThrough)); + serialization.append(StringFormat("|%i", item->ExtraDmgSkill)); + serialization.append(StringFormat("|%i", item->ExtraDmgAmt)); + serialization.append(StringFormat("|%i", item->SpellShield)); + serialization.append(StringFormat("|%i", item->Avoidance)); + serialization.append(StringFormat("|%i", item->Accuracy)); + serialization.append(StringFormat("|%i", item->CharmFileID)); + serialization.append(StringFormat("|%i", item->FactionMod1)); + serialization.append(StringFormat("|%i", item->FactionMod2)); + serialization.append(StringFormat("|%i", item->FactionMod3)); + serialization.append(StringFormat("|%i", item->FactionMod4)); + serialization.append(StringFormat("|%i", item->FactionAmt1)); + serialization.append(StringFormat("|%i", item->FactionAmt2)); + serialization.append(StringFormat("|%i", item->FactionAmt3)); + serialization.append(StringFormat("|%i", item->FactionAmt4)); + serialization.append(StringFormat("|%s", item->CharmFile)); + serialization.append(StringFormat("|%i", item->AugType)); + serialization.append(StringFormat("|%i", item->AugSlotType[0])); + serialization.append(StringFormat("|%i", item->AugSlotVisible[0])); + serialization.append(StringFormat("|%i", item->AugSlotType[1])); + serialization.append(StringFormat("|%i", item->AugSlotVisible[1])); + serialization.append(StringFormat("|%i", item->AugSlotType[2])); + serialization.append(StringFormat("|%i", item->AugSlotVisible[2])); + serialization.append(StringFormat("|%i", item->AugSlotType[3])); + serialization.append(StringFormat("|%i", item->AugSlotVisible[3])); + serialization.append(StringFormat("|%i", item->AugSlotType[4])); + serialization.append(StringFormat("|%i", item->AugSlotVisible[4])); + serialization.append(StringFormat("|%i", item->LDoNTheme)); + serialization.append(StringFormat("|%i", item->LDoNPrice)); + serialization.append(StringFormat("|%i", item->LDoNSold)); + serialization.append(StringFormat("|%i", item->BagType)); + serialization.append(StringFormat("|%i", item->BagSlots)); + serialization.append(StringFormat("|%i", item->BagSize)); + serialization.append(StringFormat("|%i", item->BagWR)); + serialization.append(StringFormat("|%i", item->Book)); + serialization.append(StringFormat("|%i", item->BookType)); + serialization.append(StringFormat("|%s", item->Filename)); + serialization.append(StringFormat("|%i", item->BaneDmgRaceAmt)); + serialization.append(StringFormat("|%i", item->AugRestrict)); + serialization.append(StringFormat("|%i", item->LoreGroup)); + serialization.append(StringFormat("|%i", item->PendingLoreFlag)); + serialization.append(StringFormat("|%i", item->ArtifactFlag)); + serialization.append(StringFormat("|%i", item->SummonedFlag)); + serialization.append(StringFormat("|%i", item->Favor)); + serialization.append(StringFormat("|%i", item->FVNoDrop)); + serialization.append(StringFormat("|%i", item->Endur)); + serialization.append(StringFormat("|%i", item->DotShielding)); + serialization.append(StringFormat("|%i", item->Attack)); + serialization.append(StringFormat("|%i", item->Regen)); + serialization.append(StringFormat("|%i", item->ManaRegen)); + serialization.append(StringFormat("|%i", item->EnduranceRegen)); + serialization.append(StringFormat("|%i", item->Haste)); + serialization.append(StringFormat("|%i", item->DamageShield)); + serialization.append(StringFormat("|%i", item->RecastDelay)); + serialization.append(StringFormat("|%i", item->RecastType)); + serialization.append(StringFormat("|%i", item->GuildFavor)); + serialization.append(StringFormat("|%i", item->AugDistiller)); + serialization.append("|0"); // unknown + serialization.append("|0"); // unknown + serialization.append(StringFormat("|%i", item->Attuneable)); + serialization.append(StringFormat("|%i", item->NoPet)); + serialization.append("|0"); // unknown + serialization.append(StringFormat("|%i", item->PointType)); + serialization.append(StringFormat("|%i", item->PotionBelt)); + serialization.append(StringFormat("|%i", item->PotionBeltSlots)); + serialization.append(StringFormat("|%i", item->StackSize)); + serialization.append(StringFormat("|%i", item->NoTransfer)); + serialization.append(StringFormat("|%i", item->Stackable)); + serialization.append(StringFormat("|%i", item->Click.Effect)); + serialization.append(StringFormat("|%i", item->Click.Type)); + serialization.append(StringFormat("|%i", item->Click.Level2)); + serialization.append(StringFormat("|%i", item->Click.Level)); + serialization.append("|0"); // Click name + serialization.append(StringFormat("|%i", item->Proc.Effect)); + serialization.append(StringFormat("|%i", item->Proc.Type)); + serialization.append(StringFormat("|%i", item->Proc.Level2)); + serialization.append(StringFormat("|%i", item->Proc.Level)); + serialization.append("|0"); // Proc name + serialization.append(StringFormat("|%i", item->Worn.Effect)); + serialization.append(StringFormat("|%i", item->Worn.Type)); + serialization.append(StringFormat("|%i", item->Worn.Level2)); + serialization.append(StringFormat("|%i", item->Worn.Level)); + serialization.append("|0"); // Worn name + serialization.append(StringFormat("|%i", item->Focus.Effect)); + serialization.append(StringFormat("|%i", item->Focus.Type)); + serialization.append(StringFormat("|%i", item->Focus.Level2)); + serialization.append(StringFormat("|%i", item->Focus.Level)); + serialization.append("|0"); // Focus name + serialization.append(StringFormat("|%i", item->Scroll.Effect)); + serialization.append(StringFormat("|%i", item->Scroll.Type)); + serialization.append(StringFormat("|%i", item->Scroll.Level2)); + serialization.append(StringFormat("|%i", item->Scroll.Level)); + serialization.append("|0"); // Scroll name +//#include "titanium_itemfields_b.h" - end + + serialization.append(StringFormat("%.*s\"", depth, protection.c_str())); // Quotes (and protection, if needed) around static data + for (int index = SUB_INDEX_BEGIN; index < consts::ITEM_CONTAINER_SIZE; ++index) { + ItemInst *sub = inst->GetItem(index); + if (!sub) { + serialization.push_back('|'); // Sub items (empty) + } + else { + std::string sub_item = SerializeItem(sub, 0, (depth + 1)); + serialization.append(StringFormat("|%s", sub_item.c_str())); // Sub items } } + serialization.append(StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection.c_str(), (depth ? "\"" : ""))); // For trailing quotes (and protection) if a subitem; - *length = MakeAnyLenString(&serialization, - "%.*s%s" // For leading quotes (and protection) if a subitem; - "%s" // Instance data - "%.*s\"" // Quotes (and protection, if needed) around static data - "%i" // item->ItemClass so we can do |%s instead of %s| -#define I(field) "|%i" -#define C(field) "|%s" -#define S(field) "|%s" -#define F(field) "|%f" -#include "titanium_itemfields_a.h" - "|%i" // mask for item->Weight -#include "titanium_itemfields_b.h" - "%.*s\"" // Quotes (and protection, if needed) around static data - "|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s" // Sub items - "%.*s%s" // For trailing quotes (and protection) if a subitem; - , depth ? depth - 1 : 0, protection, (depth) ? "\"" : "" - , instance - , depth, protection - , item->ItemClass -#define I(field) ,item->field -#define C(field) ,field -#define S(field) ,item->field -#define F(field) ,item->field -#include "titanium_itemfields_a.h" - , ((item->Weight > 255) ? (255) : (item->Weight)) -#include "titanium_itemfields_b.h" - , depth, protection - , sub_items[0] ? sub_items[0] : "" - , sub_items[1] ? sub_items[1] : "" - , sub_items[2] ? sub_items[2] : "" - , sub_items[3] ? sub_items[3] : "" - , sub_items[4] ? sub_items[4] : "" - , sub_items[5] ? sub_items[5] : "" - , sub_items[6] ? sub_items[6] : "" - , sub_items[7] ? sub_items[7] : "" - , sub_items[8] ? sub_items[8] : "" - , sub_items[9] ? sub_items[9] : "" - , (depth) ? depth - 1 : 0, protection, (depth) ? "\"" : "" - ); - - for (i = 0; i<10; i++) { - if (sub_items[i]) - safe_delete_array(sub_items[i]); - } - - safe_delete_array(instance); return serialization; } diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 36cf2df3d..03d0ab06e 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -3341,6 +3341,177 @@ struct LFGuild_GuildToggle_Struct /*616*/ }; +//struct ItemEffect_Struct +//{ +// int16 Effect; +// uint8 Type; +// uint8 Level; +// uint8 Level2; +//}; +// +//struct Item_Struct +//{ +// // "titanium_itemfields_a.h" +// char Name; // "\0" +// char Lore; // "\0" +// char IDFile; // "\0" +// int ID; +// +// int Weight; +// +// // "titanium_itemfields_b.h" +// int NoRent; +// int NoDrop; +// int Size; +// int Slots; +// int Price; +// int Icon; +// char Unk1; // '0' +// char Unk2; // '0' +// int BenefitFlag; +// int Tradeskills; +// int CR; +// int DR; +// int PR; +// int MR; +// int FR; +// int AStr; +// int ASta; +// int AAgi; +// int ADex; +// int ACha; +// int AInt; +// int AWis; +// int HP; +// int Mana; +// int AC; +// int Deity; +// int SkillModValue; +// int SkillModMax; +// int SkillModType; +// int BaneDmgRace; +// int BaneDmgAmt; +// int BaneDmgBody; +// int Magic; +// int CastTime_; +// int ReqLevel; +// int BardType; +// int BardValue; +// int Light; +// int Delay; +// int RecLevel; +// int RecSkill; +// int ElemDmgType; +// int ElemDmgAmt; +// int Range; +// int Damage; +// int Color; +// int Classes; +// int Races; +// char Unk3; // '0' +// int MaxCharges; +// int ItemType; +// int Material; +// int SellRate; +// char Unk4; // '0' +// int _CastTime_; +// char Unk5; // '0' +// int ProcRate; +// int CombatEffects; +// int Shielding; +// int StunResist; +// int StrikeThrough; +// int ExtraDmgSkill; +// int ExtraDmgAmt; +// int SpellShield; +// int Avoidance; +// int Accuracy; +// int CharmFileID; +// int FactionMod1; +// int FactionMod2; +// int FactionMod3; +// int FactionMod4; +// int FactionAmt1; +// int FactionAmt2; +// int FactionAmt3; +// int FactionAmt4; +// char CharmFile; // "\0" +// int AugType; +// +// struct { +// int AugSlotType; +// int AugSlotVisible; +// } AugSlot[5]; +// +// int LDoNTheme; +// int LDoNPrice; +// int LDoNSold; +// int BagType; +// int BagSlots; +// int BagSize; +// int BagWR; +// int Book; +// int BookType; +// char Filename; // "\0" +// int BaneDmgRaceAmt; +// int AugRestrict; +// int LoreGroup; +// int PendingLoreFlag; +// int ArtifactFlag; +// int SummonedFlag; +// int Favor; +// int FVNoDrop; +// int Endur; +// int DotShielding; +// int Attack; +// int Regen; +// int ManaRegen; +// int EnduranceRegen; +// int Haste; +// int DamageShield; +// int RecastDelay; +// int RecastType; +// int GuildFavor; +// int AugDistiller; +// char Unk6; // '0' +// char Unk7; // '0' +// int Attunable; +// int NoPet; +// char Unk8; // '0' +// int PointType; +// int PotionBelt; +// int PotionBeltSlots; +// int StackSize; +// int NoTransfer; +// int Stackable; +// +// int ClickEffect; +// int ClickType; +// int ClickLevel2; +// int ClickLevel; +// char ClickName; // '0' +// int ProcEffect; +// int ProcType; +// int ProcLevel2; +// int ProcLevel; +// char ProcName; // '0' +// int WornEffect; +// int WornType; +// int WornLevel2; +// int WornLevel; +// char WornName; // '0' +// int FocusEffect; +// int FocusType; +// int FocusLevel2; +// int FocusLevel; +// char FocusName; // '0' +// int ScrollEffect; +// int ScrollType; +// int ScrollLevel2; +// int ScrollLevel; +// char ScrollName; // '0' +//}; + }; //end namespace structs }; //end namespace Titanium From 59728c51152d3ecb01377b217c67c2971fae9575 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 8 May 2016 23:43:47 -0400 Subject: [PATCH 078/693] Tweak for Titanium::SerializeItem() rework --- common/patches/titanium.cpp | 455 ++++++++++++++++++++++-------------- 1 file changed, 274 insertions(+), 181 deletions(-) diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index a8a25fd13..98b3b64f9 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -2080,192 +2080,284 @@ namespace Titanium std::string SerializeItem(const ItemInst *inst, int16 slot_id_in, uint8 depth) { std::string serialization; - std::string instance; - std::string protection = "\\\\\\\\\\"; + const char* protection = "\\\\\\\\\\"; const Item_Struct* item = inst->GetUnscaledItem(); - instance = StringFormat("%i|", (inst->IsStackable() ? inst->GetCharges() : 0)); // stack count - instance.append("0|"); // unknown - instance.append(StringFormat("%i|", (!inst->GetMerchantSlot() ? slot_id_in : inst->GetMerchantSlot()))); // inst slot/merchant slot - instance.append(StringFormat("%i|", inst->GetPrice())); // merchant price - instance.append(StringFormat("%i|", (!inst->GetMerchantSlot() ? 1 : inst->GetMerchantCount()))); // inst count/merchant count - instance.append(StringFormat("%i|", (inst->IsScaling() ? (inst->GetExp() / 100) : 0))); // inst experience - instance.append(StringFormat("%i|", (!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot()))); // merchant serial number - instance.append(StringFormat("%i|", inst->GetRecastTimestamp())); // recast timestamp - instance.append(StringFormat("%i|", ((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges())))); // charge count - instance.append(StringFormat("%i|", (inst->IsAttuned() ? 1 : 0))); // inst attuned - instance.append("0|"); // unknown - - serialization = StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection.c_str(), (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; - serialization.append(StringFormat("%s", instance.c_str())); // Instance data - serialization.append(StringFormat("%.*s\"", depth, protection.c_str())); // Quotes (and protection, if needed) around static data + serialization = StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; + + // Instance data + serialization.append( + StringFormat( + "%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|", + (inst->IsStackable() ? inst->GetCharges() : 0), // stack count + 0, // unknown + (!inst->GetMerchantSlot() ? slot_id_in : inst->GetMerchantSlot()), // inst slot/merchant slot + inst->GetPrice(), // merchant price + (!inst->GetMerchantSlot() ? 1 : inst->GetMerchantCount()), // inst count/merchant count + (inst->IsScaling() ? (inst->GetExp() / 100) : 0), // inst experience + (!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot()), // merchant serial number + inst->GetRecastTimestamp(), // recast timestamp + ((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges())), // charge count + (inst->IsAttuned() ? 1 : 0), // inst attuned + 0 // unknown + ) + ); + + serialization.append(StringFormat("%.*s\"", depth, protection)); // Quotes (and protection, if needed) around static data serialization.append(StringFormat("%i", item->ItemClass)); // item->ItemClass so we can do |%s instead of %s| + + serialization.append( + StringFormat( + "|%s|%s|%s|%i|%i|%i|%i|%i|%i|%i|%i|%s|%s|%i|%i", + item->Name, + item->Lore, + item->IDFile, + item->ID, + ((item->Weight > 255) ? 255 : item->Weight), + item->NoRent, + item->NoDrop, + item->Size, + item->Slots, + item->Price, + item->Icon, + "0", // unknown + "0", // unknown + item->BenefitFlag, + item->Tradeskills + ) + ); -//#include "titanium_itemfields_a.h" - begin - serialization.append(StringFormat("|%s", item->Name)); - serialization.append(StringFormat("|%s", item->Lore)); - serialization.append(StringFormat("|%s", item->IDFile)); - serialization.append(StringFormat("|%i", item->ID)); -//#include "titanium_itemfields_a.h" - end - serialization.append(StringFormat("|%i", ((item->Weight > 255) ? 255 : item->Weight))); -//#include "titanium_itemfields_b.h" - begin - serialization.append(StringFormat("|%i", item->NoRent)); - serialization.append(StringFormat("|%i", item->NoDrop)); - serialization.append(StringFormat("|%i", item->Size)); - serialization.append(StringFormat("|%i", item->Slots)); - serialization.append(StringFormat("|%i", item->Price)); - serialization.append(StringFormat("|%i", item->Icon)); - serialization.append("|0"); // unknown - serialization.append("|0"); // unknown - serialization.append(StringFormat("|%i", item->BenefitFlag)); - serialization.append(StringFormat("|%i", item->Tradeskills)); - serialization.append(StringFormat("|%i", item->CR)); - serialization.append(StringFormat("|%i", item->DR)); - serialization.append(StringFormat("|%i", item->PR)); - serialization.append(StringFormat("|%i", item->MR)); - serialization.append(StringFormat("|%i", item->FR)); - serialization.append(StringFormat("|%i", item->AStr)); - serialization.append(StringFormat("|%i", item->ASta)); - serialization.append(StringFormat("|%i", item->AAgi)); - serialization.append(StringFormat("|%i", item->ADex)); - serialization.append(StringFormat("|%i", item->ACha)); - serialization.append(StringFormat("|%i", item->AInt)); - serialization.append(StringFormat("|%i", item->AWis)); - serialization.append(StringFormat("|%i", item->HP)); - serialization.append(StringFormat("|%i", item->Mana)); - serialization.append(StringFormat("|%i", item->AC)); - serialization.append(StringFormat("|%i", item->Deity)); - serialization.append(StringFormat("|%i", item->SkillModValue)); - serialization.append(StringFormat("|%i", item->SkillModMax)); - serialization.append(StringFormat("|%i", item->SkillModType)); - serialization.append(StringFormat("|%i", item->BaneDmgRace)); - serialization.append(StringFormat("|%i", item->BaneDmgAmt)); - serialization.append(StringFormat("|%i", item->BaneDmgBody)); - serialization.append(StringFormat("|%i", item->Magic)); - serialization.append(StringFormat("|%i", item->CastTime_)); - serialization.append(StringFormat("|%i", item->ReqLevel)); - serialization.append(StringFormat("|%i", item->BardType)); - serialization.append(StringFormat("|%i", item->BardValue)); - serialization.append(StringFormat("|%i", item->Light)); - serialization.append(StringFormat("|%i", item->Delay)); - serialization.append(StringFormat("|%i", item->RecLevel)); - serialization.append(StringFormat("|%i", item->RecSkill)); - serialization.append(StringFormat("|%i", item->ElemDmgType)); - serialization.append(StringFormat("|%i", item->ElemDmgAmt)); - serialization.append(StringFormat("|%i", item->Range)); - serialization.append(StringFormat("|%i", item->Damage)); - serialization.append(StringFormat("|%i", item->Color)); - serialization.append(StringFormat("|%i", item->Classes)); - serialization.append(StringFormat("|%i", item->Races)); - serialization.append("|0"); // unknown - serialization.append(StringFormat("|%i", item->MaxCharges)); - serialization.append(StringFormat("|%i", item->ItemType)); - serialization.append(StringFormat("|%i", item->Material)); - serialization.append(StringFormat("|%i", item->SellRate)); - serialization.append("|0"); // unknown - serialization.append(StringFormat("|%i", item->CastTime_)); - serialization.append("|0"); // unknown - serialization.append(StringFormat("|%i", item->ProcRate)); - serialization.append(StringFormat("|%i", item->CombatEffects)); - serialization.append(StringFormat("|%i", item->Shielding)); - serialization.append(StringFormat("|%i", item->StunResist)); - serialization.append(StringFormat("|%i", item->StrikeThrough)); - serialization.append(StringFormat("|%i", item->ExtraDmgSkill)); - serialization.append(StringFormat("|%i", item->ExtraDmgAmt)); - serialization.append(StringFormat("|%i", item->SpellShield)); - serialization.append(StringFormat("|%i", item->Avoidance)); - serialization.append(StringFormat("|%i", item->Accuracy)); - serialization.append(StringFormat("|%i", item->CharmFileID)); - serialization.append(StringFormat("|%i", item->FactionMod1)); - serialization.append(StringFormat("|%i", item->FactionMod2)); - serialization.append(StringFormat("|%i", item->FactionMod3)); - serialization.append(StringFormat("|%i", item->FactionMod4)); - serialization.append(StringFormat("|%i", item->FactionAmt1)); - serialization.append(StringFormat("|%i", item->FactionAmt2)); - serialization.append(StringFormat("|%i", item->FactionAmt3)); - serialization.append(StringFormat("|%i", item->FactionAmt4)); - serialization.append(StringFormat("|%s", item->CharmFile)); - serialization.append(StringFormat("|%i", item->AugType)); - serialization.append(StringFormat("|%i", item->AugSlotType[0])); - serialization.append(StringFormat("|%i", item->AugSlotVisible[0])); - serialization.append(StringFormat("|%i", item->AugSlotType[1])); - serialization.append(StringFormat("|%i", item->AugSlotVisible[1])); - serialization.append(StringFormat("|%i", item->AugSlotType[2])); - serialization.append(StringFormat("|%i", item->AugSlotVisible[2])); - serialization.append(StringFormat("|%i", item->AugSlotType[3])); - serialization.append(StringFormat("|%i", item->AugSlotVisible[3])); - serialization.append(StringFormat("|%i", item->AugSlotType[4])); - serialization.append(StringFormat("|%i", item->AugSlotVisible[4])); - serialization.append(StringFormat("|%i", item->LDoNTheme)); - serialization.append(StringFormat("|%i", item->LDoNPrice)); - serialization.append(StringFormat("|%i", item->LDoNSold)); - serialization.append(StringFormat("|%i", item->BagType)); - serialization.append(StringFormat("|%i", item->BagSlots)); - serialization.append(StringFormat("|%i", item->BagSize)); - serialization.append(StringFormat("|%i", item->BagWR)); - serialization.append(StringFormat("|%i", item->Book)); - serialization.append(StringFormat("|%i", item->BookType)); - serialization.append(StringFormat("|%s", item->Filename)); - serialization.append(StringFormat("|%i", item->BaneDmgRaceAmt)); - serialization.append(StringFormat("|%i", item->AugRestrict)); - serialization.append(StringFormat("|%i", item->LoreGroup)); - serialization.append(StringFormat("|%i", item->PendingLoreFlag)); - serialization.append(StringFormat("|%i", item->ArtifactFlag)); - serialization.append(StringFormat("|%i", item->SummonedFlag)); - serialization.append(StringFormat("|%i", item->Favor)); - serialization.append(StringFormat("|%i", item->FVNoDrop)); - serialization.append(StringFormat("|%i", item->Endur)); - serialization.append(StringFormat("|%i", item->DotShielding)); - serialization.append(StringFormat("|%i", item->Attack)); - serialization.append(StringFormat("|%i", item->Regen)); - serialization.append(StringFormat("|%i", item->ManaRegen)); - serialization.append(StringFormat("|%i", item->EnduranceRegen)); - serialization.append(StringFormat("|%i", item->Haste)); - serialization.append(StringFormat("|%i", item->DamageShield)); - serialization.append(StringFormat("|%i", item->RecastDelay)); - serialization.append(StringFormat("|%i", item->RecastType)); - serialization.append(StringFormat("|%i", item->GuildFavor)); - serialization.append(StringFormat("|%i", item->AugDistiller)); - serialization.append("|0"); // unknown - serialization.append("|0"); // unknown - serialization.append(StringFormat("|%i", item->Attuneable)); - serialization.append(StringFormat("|%i", item->NoPet)); - serialization.append("|0"); // unknown - serialization.append(StringFormat("|%i", item->PointType)); - serialization.append(StringFormat("|%i", item->PotionBelt)); - serialization.append(StringFormat("|%i", item->PotionBeltSlots)); - serialization.append(StringFormat("|%i", item->StackSize)); - serialization.append(StringFormat("|%i", item->NoTransfer)); - serialization.append(StringFormat("|%i", item->Stackable)); - serialization.append(StringFormat("|%i", item->Click.Effect)); - serialization.append(StringFormat("|%i", item->Click.Type)); - serialization.append(StringFormat("|%i", item->Click.Level2)); - serialization.append(StringFormat("|%i", item->Click.Level)); - serialization.append("|0"); // Click name - serialization.append(StringFormat("|%i", item->Proc.Effect)); - serialization.append(StringFormat("|%i", item->Proc.Type)); - serialization.append(StringFormat("|%i", item->Proc.Level2)); - serialization.append(StringFormat("|%i", item->Proc.Level)); - serialization.append("|0"); // Proc name - serialization.append(StringFormat("|%i", item->Worn.Effect)); - serialization.append(StringFormat("|%i", item->Worn.Type)); - serialization.append(StringFormat("|%i", item->Worn.Level2)); - serialization.append(StringFormat("|%i", item->Worn.Level)); - serialization.append("|0"); // Worn name - serialization.append(StringFormat("|%i", item->Focus.Effect)); - serialization.append(StringFormat("|%i", item->Focus.Type)); - serialization.append(StringFormat("|%i", item->Focus.Level2)); - serialization.append(StringFormat("|%i", item->Focus.Level)); - serialization.append("|0"); // Focus name - serialization.append(StringFormat("|%i", item->Scroll.Effect)); - serialization.append(StringFormat("|%i", item->Scroll.Type)); - serialization.append(StringFormat("|%i", item->Scroll.Level2)); - serialization.append(StringFormat("|%i", item->Scroll.Level)); - serialization.append("|0"); // Scroll name -//#include "titanium_itemfields_b.h" - end + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i", + item->CR, + item->DR, + item->PR, + item->MR, + item->FR, + item->AStr, + item->ASta, + item->AAgi, + item->ADex, + item->ACha, + item->AInt, + item->AWis, + item->HP, + item->Mana, + item->AC + ) + ); + + + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i", + item->Deity, + item->SkillModValue, + item->SkillModMax, + item->SkillModType, + item->BaneDmgRace, + item->BaneDmgAmt, + item->BaneDmgBody, + item->Magic, + item->CastTime_, + item->ReqLevel, + item->BardType, + item->BardValue, + item->Light, + item->Delay + ) + ); + + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%s|%i|%i|%i|%i", + item->RecLevel, + item->RecSkill, + item->ElemDmgType, + item->ElemDmgAmt, + item->Range, + item->Damage, + item->Color, + item->Classes, + item->Races, + "0", // unknown + item->MaxCharges, + item->ItemType, + item->Material, + item->SellRate + ) + ); + + serialization.append( + StringFormat( + "|%s|%i|%s|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i", + "0", // unknown + item->CastTime_, + "0", // unknown + item->ProcRate, + item->CombatEffects, + item->Shielding, + item->StunResist, + item->StrikeThrough, + item->ExtraDmgSkill, + item->ExtraDmgAmt, + item->SpellShield, + item->Avoidance, + item->Accuracy, + item->CharmFileID + ) + ); + + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%i|%i|%i|%i|%s", + item->FactionMod1, + item->FactionMod2, + item->FactionMod3, + item->FactionMod4, + item->FactionAmt1, + item->FactionAmt2, + item->FactionAmt3, + item->FactionAmt4, + item->CharmFile + ) + ); + + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i", + item->AugType, + item->AugSlotType[0], + item->AugSlotVisible[0], + item->AugSlotType[1], + item->AugSlotVisible[1], + item->AugSlotType[2], + item->AugSlotVisible[2], + item->AugSlotType[3], + item->AugSlotVisible[3], + item->AugSlotType[4], + item->AugSlotVisible[4] + ) + ); + + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%s|%i|%i|%i|%i|%i|%i", + item->LDoNTheme, + item->LDoNPrice, + item->LDoNSold, + item->BagType, + item->BagSlots, + item->BagSize, + item->BagWR, + item->Book, + item->BookType, + item->Filename, + item->BaneDmgRaceAmt, + item->AugRestrict, + item->LoreGroup, + item->PendingLoreFlag, + item->ArtifactFlag, + item->SummonedFlag + ) + ); + + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i", + item->Favor, + item->FVNoDrop, + item->Endur, + item->DotShielding, + item->Attack, + item->Regen, + item->ManaRegen, + item->EnduranceRegen, + item->Haste, + item->DamageShield, + item->RecastDelay, + item->RecastType, + item->GuildFavor, + item->AugDistiller + ) + ); + + serialization.append( + StringFormat( + "|%s|%s|%i|%i|%s|%i|%i|%i|%i|%i|%i", + "0", // unknown + "0", // unknown + item->Attuneable, + item->NoPet, + "0", // unknown + item->PointType, + item->PotionBelt, + item->PotionBeltSlots, + item->StackSize, + item->NoTransfer, + item->Stackable + ) + ); + + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%s", + item->Click.Effect, + item->Click.Type, + item->Click.Level2, + item->Click.Level, + "0" // Click name + ) + ); + + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%s", + item->Proc.Effect, + item->Proc.Type, + item->Proc.Level2, + item->Proc.Level, + "0" // Proc name + ) + ); + + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%s", + item->Worn.Effect, + item->Worn.Type, + item->Worn.Level2, + item->Worn.Level, + "0" // Worn name + ) + ); + + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%s", + item->Focus.Effect, + item->Focus.Type, + item->Focus.Level2, + item->Focus.Level, + "0" // Focus name + ) + ); + + serialization.append( + StringFormat( + "|%i|%i|%i|%i|%s", + item->Scroll.Effect, + item->Scroll.Type, + item->Scroll.Level2, + item->Scroll.Level, + "0" // Scroll name + ) + ); + + serialization.append(StringFormat("%.*s\"", depth, protection)); // Quotes (and protection, if needed) around static data - serialization.append(StringFormat("%.*s\"", depth, protection.c_str())); // Quotes (and protection, if needed) around static data for (int index = SUB_INDEX_BEGIN; index < consts::ITEM_CONTAINER_SIZE; ++index) { ItemInst *sub = inst->GetItem(index); if (!sub) { @@ -2276,7 +2368,8 @@ namespace Titanium serialization.append(StringFormat("|%s", sub_item.c_str())); // Sub items } } - serialization.append(StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection.c_str(), (depth ? "\"" : ""))); // For trailing quotes (and protection) if a subitem; + + serialization.append(StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : ""))); // For trailing quotes (and protection) if a subitem; return serialization; } From c159b89e79d3a624f79ab60a73796b98a62cf615 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 9 May 2016 14:23:27 -0400 Subject: [PATCH 079/693] Rewrite VarCache_Struct Basically just remove manual memory management --- common/database.cpp | 142 +++++++++-------------------------------- common/database.h | 24 +++---- common/shareddb.cpp | 10 +-- shared_memory/main.cpp | 8 +-- world/client.cpp | 8 +-- world/cliententry.cpp | 8 +-- world/login_server.cpp | 4 +- world/net.cpp | 33 +++++----- zone/attack.cpp | 29 ++++----- zone/client.cpp | 25 +++----- zone/command.cpp | 30 ++++----- zone/corpse.cpp | 6 +- zone/guild_mgr.cpp | 20 +++--- zone/guild_mgr.h | 1 - zone/net.cpp | 26 ++++---- zone/zone.cpp | 11 ++-- 16 files changed, 146 insertions(+), 239 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index f33569fd2..95895dc5f 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -48,7 +49,6 @@ extern Client client; Database::Database () { - DBInitVars(); } /* @@ -57,7 +57,6 @@ Establish a connection to a mysql database with the supplied parameters Database::Database(const char* host, const char* user, const char* passwd, const char* database, uint32 port) { - DBInitVars(); Connect(host, user, passwd, database, port); } @@ -74,25 +73,12 @@ bool Database::Connect(const char* host, const char* user, const char* passwd, c } } -void Database::DBInitVars() { - varcache_array = 0; - varcache_max = 0; - varcache_lastupdate = 0; -} - /* Close the connection to the database */ Database::~Database() { - unsigned int x; - if (varcache_array) { - for (x=0; x= %d", varcache_lastupdate)); + auto results = QueryDatabase(StringFormat("SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= %d", varcache.last_update)); if (!results.Success()) return false; - return LoadVariables_result(std::move(results)); -} - -uint32 Database::LoadVariables_MQ(char** query) -{ - return MakeAnyLenString(query, "SELECT varname, value, unix_timestamp() FROM variables where unix_timestamp(ts) >= %d", varcache_lastupdate); -} - -// always returns true? not sure about this. -bool Database::LoadVariables_result(MySQLRequestResult results) -{ - uint32 i = 0; - LockMutex lock(&Mvarcache); - if (results.RowCount() == 0) return true; - if (!varcache_array) { - varcache_max = results.RowCount(); - varcache_array = new VarCache_Struct*[varcache_max]; - for (i=0; ivarname, row[0]) == 0) { - delete varcache_array[i]; - varcache_array[i] = (VarCache_Struct*) new uint8[sizeof(VarCache_Struct) + strlen(row[1]) + 1]; - strn0cpy(varcache_array[i]->varname, row[0], sizeof(varcache_array[i]->varname)); - strcpy(varcache_array[i]->value, row[1]); - break; - } - } - else { - varcache_array[i] = (VarCache_Struct*) new uint8[sizeof(VarCache_Struct) + strlen(row[1]) + 1]; - strcpy(varcache_array[i]->varname, row[0]); - strcpy(varcache_array[i]->value, row[1]); - break; - } - } + std::string key, value; + for (auto row = results.begin(); row != results.end(); ++row) { + varcache.last_update = atoi(row[2]); // ahh should we be comparing if this is newer? + key = row[0]; + value = row[1]; + std::transform(std::begin(key), std::end(key), std::begin(key), ::tolower); // keys are lower case, DB doesn't have to be + varcache.Add(key, value); } - uint32 max_used = 0; - for (i=0; i max_used) - max_used = i; - } - } - - varcache_max = max_used + 1; - return true; } // Gets variable from 'variables' table -bool Database::GetVariable(const char* varname, char* varvalue, uint16 varvalue_len) { - varvalue[0] = '\0'; +bool Database::GetVariable(std::string varname, std::string &varvalue) +{ + varvalue.clear(); LockMutex lock(&Mvarcache); - if (strlen(varname) <= 1) - return false; - for (uint32 i=0; ivarname, varname) == 0) { - snprintf(varvalue, varvalue_len, "%s", varcache_array[i]->value); - varvalue[varvalue_len-1] = 0; - return true; - } - } - else - return false; + if (varname.empty()) + return false; + + std::transform(std::begin(varname), std::end(varname), std::begin(varname), ::tolower); // all keys are lower case + auto tmp = varcache.Get(varname); + if (tmp) { + varvalue = *tmp; + return true; } return false; } -bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { - - char *varname,*varvalue; - - varname=(char *)malloc(strlen(varname_in)*2+1); - varvalue=(char *)malloc(strlen(varvalue_in)*2+1); - DoEscapeString(varname, varname_in, strlen(varname_in)); - DoEscapeString(varvalue, varvalue_in, strlen(varvalue_in)); - - std::string query = StringFormat("Update variables set value='%s' WHERE varname like '%s'", varvalue, varname); +bool Database::SetVariable(const std::string varname, const std::string &varvalue) +{ + std::string escaped_name = EscapeString(varname); + std::string escaped_value = EscapeString(varvalue); + std::string query = StringFormat("Update variables set value='%s' WHERE varname like '%s'", escaped_value.c_str(), escaped_name.c_str()); auto results = QueryDatabase(query); if (!results.Success()) - { - free(varname); - free(varvalue); return false; - } if (results.RowsAffected() == 1) { LoadVariables(); // refresh cache - free(varname); - free(varvalue); return true; } - query = StringFormat("Insert Into variables (varname, value) values ('%s', '%s')", varname, varvalue); + query = StringFormat("Insert Into variables (varname, value) values ('%s', '%s')", escaped_name.c_str(), escaped_value.c_str()); results = QueryDatabase(query); - free(varname); - free(varvalue); if (results.RowsAffected() != 1) return false; - + LoadVariables(); // refresh cache return true; } diff --git a/common/database.h b/common/database.h index 68197811f..ed08484b1 100644 --- a/common/database.h +++ b/common/database.h @@ -67,8 +67,14 @@ struct npcDecayTimes_Struct { struct VarCache_Struct { - char varname[26]; - char value[0]; + std::map m_cache; + uint32 last_update; + VarCache_Struct() : last_update(0) { } + void Add(const std::string &key, const std::string &value) { m_cache[key] = value; } + const std::string *Get(const std::string &key) { + auto it = m_cache.find(key); + return (it != m_cache.end() ? &it->second : nullptr); + } }; class PTimerList; @@ -215,11 +221,9 @@ public: /* Database Variables */ - bool GetVariable(const char* varname, char* varvalue, uint16 varvalue_len); - bool SetVariable(const char* varname, const char* varvalue); + bool GetVariable(std::string varname, std::string &varvalue); + bool SetVariable(const std::string varname, const std::string &varvalue); bool LoadVariables(); - uint32 LoadVariables_MQ(char** query); - bool LoadVariables_result(MySQLRequestResult results); /* General Queries */ @@ -256,14 +260,10 @@ public: void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings); private: - void DBInitVars(); - std::map zonename_array; - Mutex Mvarcache; - uint32 varcache_max; - VarCache_Struct** varcache_array; - uint32 varcache_lastupdate; + Mutex Mvarcache; + VarCache_Struct varcache; /* Groups, utility methods. */ void ClearAllGroupLeaders(); diff --git a/common/shareddb.cpp b/common/shareddb.cpp index ddf7b383f..f61255143 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -828,27 +828,27 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ { EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); - char ndbuffer[4]; + std::string ndbuffer; bool disableNoRent = false; - if (GetVariable("disablenorent", ndbuffer, 4)) { + if (GetVariable("disablenorent", ndbuffer)) { if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') { disableNoRent = true; } } bool disableNoDrop = false; - if (GetVariable("disablenodrop", ndbuffer, 4)) { + if (GetVariable("disablenodrop", ndbuffer)) { if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') { disableNoDrop = true; } } bool disableLoreGroup = false; - if (GetVariable("disablelore", ndbuffer, 4)) { + if (GetVariable("disablelore", ndbuffer)) { if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') { disableLoreGroup = true; } } bool disableNoTransfer = false; - if (GetVariable("disablenotransfer", ndbuffer, 4)) { + if (GetVariable("disablenotransfer", ndbuffer)) { if (ndbuffer[0] == '1' && ndbuffer[1] == '\0') { disableNoTransfer = true; } diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 11d21153b..8ad2b42ae 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -65,10 +65,10 @@ int main(int argc, char **argv) { database.LoadVariables(); /* If we're running shared memory and hotfix has no custom name, we probably want to start from scratch... */ - char db_hotfix_name[256] = { 0 }; - if (database.GetVariable("hotfix_name", db_hotfix_name, 256)) { - if (strlen(db_hotfix_name) > 0 && strcasecmp("hotfix_", db_hotfix_name) == 0) { - Log.Out(Logs::General, Logs::Status, "Current hotfix in variables is the default %s, clearing out variable", db_hotfix_name); + std::string db_hotfix_name; + if (database.GetVariable("hotfix_name", db_hotfix_name)) { + if (!db_hotfix_name.empty() && strcasecmp("hotfix_", db_hotfix_name.c_str()) == 0) { + Log.Out(Logs::General, Logs::Status, "Current hotfix in variables is the default %s, clearing out variable", db_hotfix_name.c_str()); std::string query = StringFormat("UPDATE `variables` SET `value`='' WHERE (`varname`='hotfix_name')"); database.QueryDatabase(query); } diff --git a/world/client.cpp b/world/client.cpp index 91c8cffb5..6250fb0b9 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -857,12 +857,12 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { } outapp = new EQApplicationPacket(OP_MOTD); - char tmp[500] = {0}; - if (database.GetVariable("MOTD", tmp, 500)) { - outapp->size = strlen(tmp)+1; + std::string tmp; + if (database.GetVariable("MOTD", tmp)) { + outapp->size = tmp.length(); outapp->pBuffer = new uchar[outapp->size]; memset(outapp->pBuffer,0,outapp->size); - strcpy((char*)outapp->pBuffer, tmp); + strcpy((char*)outapp->pBuffer, tmp.c_str()); } else { // Null Message of the Day. :) diff --git a/world/cliententry.cpp b/world/cliententry.cpp index 5e896dca0..a67c45c39 100644 --- a/world/cliententry.cpp +++ b/world/cliententry.cpp @@ -277,10 +277,10 @@ bool ClientListEntry::CheckAuth(uint32 iLSID, const char* iKey) { strn0cpy(paccountname, plsname, sizeof(paccountname)); padmin = tmpStatus; } - char lsworldadmin[15] = "0"; - database.GetVariable("honorlsworldadmin", lsworldadmin, sizeof(lsworldadmin)); - if (atoi(lsworldadmin) == 1 && pworldadmin != 0 && (padmin < pworldadmin || padmin == 0)) - padmin = pworldadmin; + std::string lsworldadmin; + if (database.GetVariable("honorlsworldadmin", lsworldadmin)) + if (atoi(lsworldadmin.c_str()) == 1 && pworldadmin != 0 && (padmin < pworldadmin || padmin == 0)) + padmin = pworldadmin; return true; } return false; diff --git a/world/login_server.cpp b/world/login_server.cpp index a6b46a6ea..8b17d9bc2 100644 --- a/world/login_server.cpp +++ b/world/login_server.cpp @@ -212,8 +212,8 @@ bool LoginServer::InitLoginServer() { } bool LoginServer::Connect() { - char tmp[25]; - if(database.GetVariable("loginType",tmp,sizeof(tmp)) && strcasecmp(tmp,"MinILogin") == 0){ + std::string tmp; + if(database.GetVariable("loginType", tmp) && strcasecmp(tmp.c_str(), "MinILogin") == 0) { minilogin = true; Log.Out(Logs::Detail, Logs::World_Server, "Setting World to MiniLogin Server type"); } diff --git a/world/net.cpp b/world/net.cpp index cd84c530a..90fb3e680 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -193,7 +193,7 @@ int main(int argc, char** argv) { bool ignore_db = false; if (argc >= 2) { - char tmp[2]; + std::string tmp; if (strcasecmp(argv[1], "help") == 0 || strcasecmp(argv[1], "?") == 0 || strcasecmp(argv[1], "/?") == 0 || strcasecmp(argv[1], "-?") == 0 || strcasecmp(argv[1], "-h") == 0 || strcasecmp(argv[1], "-help") == 0) { std::cout << "Worldserver command line commands:" << std::endl; std::cout << "adduser username password flag - adds a user account" << std::endl; @@ -206,8 +206,8 @@ int main(int argc, char** argv) { std::cout << "Reboot Zones mode ON" << std::endl; holdzones = true; } - else if (database.GetVariable("disablecommandline", tmp, 2)) { - if (strlen(tmp) == 1) { + else if (database.GetVariable("disablecommandline", tmp)) { + if (tmp.length() == 1) { if (tmp[0] == '1') { std::cerr << "Command line disabled in database... exiting" << std::endl; return 1; @@ -299,10 +299,10 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::World_Server, "Loading variables.."); database.LoadVariables(); - char hotfix_name[256] = { 0 }; - if(database.GetVariable("hotfix_name", hotfix_name, 256)) { - if(strlen(hotfix_name) > 0) { - Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: '%s'", hotfix_name); + std::string hotfix_name; + if(database.GetVariable("hotfix_name", hotfix_name)) { + if (!hotfix_name.empty()) { + Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: '%s'", hotfix_name.c_str()); } } @@ -326,17 +326,17 @@ int main(int argc, char** argv) { guild_mgr.LoadGuilds(); //rules: { - char tmp[64]; - if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) { - Log.Out(Logs::General, Logs::World_Server, "Loading rule set '%s'", tmp); - if(!RuleManager::Instance()->LoadRules(&database, tmp)) { - Log.Out(Logs::General, Logs::World_Server, "Failed to load ruleset '%s', falling back to defaults.", tmp); + std::string tmp; + if (database.GetVariable("RuleSet", tmp)) { + Log.Out(Logs::General, Logs::World_Server, "Loading rule set '%s'", tmp.c_str()); + if(!RuleManager::Instance()->LoadRules(&database, tmp.c_str())) { + Log.Out(Logs::General, Logs::World_Server, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str()); } } else { if(!RuleManager::Instance()->LoadRules(&database, "default")) { Log.Out(Logs::General, Logs::World_Server, "No rule set configured, using default rules"); } else { - Log.Out(Logs::General, Logs::World_Server, "Loaded default rule set 'default'", tmp); + Log.Out(Logs::General, Logs::World_Server, "Loaded default rule set 'default'", tmp.c_str()); } } } @@ -355,10 +355,9 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::World_Server, "Loading launcher list.."); launcher_list.LoadList(); - char tmp[20]; - tmp[0] = '\0'; - database.GetVariable("holdzones",tmp, 20); - if ((strcasecmp(tmp, "1") == 0)) { + std::string tmp; + database.GetVariable("holdzones",tmp); + if (tmp.length() == 1 && tmp[0] == '1') { holdzones = true; } Log.Out(Logs::General, Logs::World_Server, "Reboot zone modes %s",holdzones ? "ON" : "OFF"); diff --git a/zone/attack.cpp b/zone/attack.cpp index 62625cac5..712198733 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -687,25 +687,25 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac if (damage > 0 && myac > 0) { int acfail=1000; - char tmp[10]; + std::string tmp; - if (database.GetVariable("ACfail", tmp, 9)) { - acfail = (int) (atof(tmp) * 100); + if (database.GetVariable("ACfail", tmp)) { + acfail = (int) (atof(tmp.c_str()) * 100); if (acfail>100) acfail=100; } if (acfail<=0 || zone->random.Int(0, 100)>acfail) { float acreduction=1; int acrandom=300; - if (database.GetVariable("ACreduction", tmp, 9)) + if (database.GetVariable("ACreduction", tmp)) { - acreduction=atof(tmp); + acreduction=atof(tmp.c_str()); if (acreduction>100) acreduction=100; } - if (database.GetVariable("ACrandom", tmp, 9)) + if (database.GetVariable("ACrandom", tmp)) { - acrandom = (int) ((atof(tmp)+1) * 100); + acrandom = (int) ((atof(tmp.c_str())+1) * 100); if (acrandom>10100) acrandom=10100; } @@ -1497,15 +1497,14 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att // creating the corpse takes the cash/items off the player too Corpse *new_corpse = new Corpse(this, exploss); - char tmp[20]; - database.GetVariable("ServerType", tmp, 9); - if(atoi(tmp)==1 && killerMob != nullptr && killerMob->IsClient()){ - char tmp2[10] = {0}; - database.GetVariable("PvPreward", tmp, 9); - int reward = atoi(tmp); + std::string tmp; + database.GetVariable("ServerType", tmp); + if(tmp[0] == '1' && tmp[1] == '\0' && killerMob != nullptr && killerMob->IsClient()){ + database.GetVariable("PvPreward", tmp); + int reward = atoi(tmp.c_str()); if(reward==3){ - database.GetVariable("PvPitem", tmp2, 9); - int pvpitem = atoi(tmp2); + database.GetVariable("PvPitem", tmp); + int pvpitem = atoi(tmp.c_str()); if(pvpitem>0 && pvpitem<200000) new_corpse->SetPlayerKillItemID(pvpitem); } diff --git a/zone/client.cpp b/zone/client.cpp index a6b2f3243..6f7e6981b 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -3598,10 +3598,8 @@ void Client::GetRaidAAs(RaidLeadershipAA_Struct *into) const { void Client::EnteringMessages(Client* client) { //server rules - char *rules; - rules = new char [4096]; - - if(database.GetVariable("Rules", rules, 4096)) + std::string rules; + if(database.GetVariable("Rules", rules)) { uint8 flag = database.GetAgreementFlag(client->AccountID()); if(!flag) @@ -3612,25 +3610,18 @@ void Client::EnteringMessages(Client* client) client->SendAppearancePacket(AT_Anim, ANIM_FREEZE); } } - safe_delete_array(rules); } void Client::SendRules(Client* client) { - char *rules; - rules = new char [4096]; - char *ptr; + std::string rules; - database.GetVariable("Rules", rules, 4096); + if (!database.GetVariable("Rules", rules)) + return; - ptr = strtok(rules, "\n"); - while(ptr != nullptr) - { - - client->Message(0,"%s",ptr); - ptr = strtok(nullptr, "\n"); - } - safe_delete_array(rules); + auto lines = SplitString(rules, '\n'); + for (auto&& e : lines) + client->Message(0, "%s", e.c_str()); } void Client::SetEndurance(int32 newEnd) diff --git a/zone/command.cpp b/zone/command.cpp index 93f77c6a8..46f157015 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -856,9 +856,9 @@ char buffer[255]; void command_getvariable(Client *c, const Seperator *sep) { - char tmp[512]; - if (database.GetVariable(sep->argplus[1], tmp, sizeof(tmp))) - c->Message(0, "%s = %s", sep->argplus[1], tmp); + std::string tmp; + if (database.GetVariable(sep->argplus[1], tmp)) + c->Message(0, "%s = %s", sep->argplus[1], tmp.c_str()); else c->Message(0, "GetVariable(%s) returned false", sep->argplus[1]); } @@ -10735,12 +10735,11 @@ void command_reloadaa(Client *c, const Seperator *sep) { } void command_hotfix(Client *c, const Seperator *sep) { - char hotfix[256] = { 0 }; - database.GetVariable("hotfix_name", hotfix, 256); - std::string current_hotfix = hotfix; + std::string hotfix; + database.GetVariable("hotfix_name", hotfix); std::string hotfix_name; - if(!strcasecmp(current_hotfix.c_str(), "hotfix_")) { + if(!strcasecmp(hotfix.c_str(), "hotfix_")) { hotfix_name = ""; } else { hotfix_name = "hotfix_"; @@ -10762,7 +10761,7 @@ void command_hotfix(Client *c, const Seperator *sep) { system(StringFormat("./shared_memory").c_str()); } #endif - database.SetVariable("hotfix_name", hotfix_name.c_str()); + database.SetVariable("hotfix_name", hotfix_name); ServerPacket pack(ServerOP_ChangeSharedMem, hotfix_name.length() + 1); if(hotfix_name.length() > 0) { @@ -10777,12 +10776,11 @@ void command_hotfix(Client *c, const Seperator *sep) { } void command_load_shared_memory(Client *c, const Seperator *sep) { - char hotfix[256] = { 0 }; - database.GetVariable("hotfix_name", hotfix, 256); - std::string current_hotfix = hotfix; + std::string hotfix; + database.GetVariable("hotfix_name", hotfix); std::string hotfix_name; - if(strcasecmp(current_hotfix.c_str(), sep->arg[1]) == 0) { + if(strcasecmp(hotfix.c_str(), sep->arg[1]) == 0) { c->Message(0, "Cannot attempt to load this shared memory segment as it is already loaded."); return; } @@ -10811,12 +10809,12 @@ void command_load_shared_memory(Client *c, const Seperator *sep) { } void command_apply_shared_memory(Client *c, const Seperator *sep) { - char hotfix[256] = { 0 }; - database.GetVariable("hotfix_name", hotfix, 256); + std::string hotfix; + database.GetVariable("hotfix_name", hotfix); std::string hotfix_name = sep->arg[1]; - + c->Message(0, "Applying shared memory segment %s", hotfix_name.c_str()); - database.SetVariable("hotfix_name", hotfix_name.c_str()); + database.SetVariable("hotfix_name", hotfix_name); ServerPacket pack(ServerOP_ChangeSharedMem, hotfix_name.length() + 1); if(hotfix_name.length() > 0) { diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 90dad987d..6338cc412 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -883,7 +883,6 @@ void Corpse::AllowPlayerLoot(Mob *them, uint8 slot) { void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* app) { // Added 12/08. Started compressing loot struct on live. - char tmp[10]; if(player_corpse_depop) { SendLootReqErrorPacket(client, 0); return; @@ -914,8 +913,9 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a uint8 Loot_Request_Type = 1; bool loot_coin = false; - if(database.GetVariable("LootCoin", tmp, 9)) - loot_coin = (atoi(tmp) == 1); + std::string tmp; + if(database.GetVariable("LootCoin", tmp)) + loot_coin = tmp[0] == 1 && tmp[1] == '\0'; if (this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) { SendLootReqErrorPacket(client, 0); diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index 2ccb2bb1c..f7a7a2cc3 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -1406,8 +1406,9 @@ bool GuildApproval::ProcessApproval() GuildApproval::GuildApproval(const char* guildname, Client* owner,uint32 id) { - database.GetVariable("GuildCreation", founders, 3); - uint8 tmp = atoi(founders); + std::string founders; + database.GetVariable("GuildCreation", founders); + uint8 tmp = atoi(founders.c_str()); deletion_timer = new Timer(1800000); strcpy(guild,guildname); this->owner = owner; @@ -1425,8 +1426,9 @@ GuildApproval::~GuildApproval() bool GuildApproval::AddMemberApproval(Client* addition) { - database.GetVariable("GuildCreation", founders, 3); - uint8 tmp = atoi(founders); + std::string founders; + database.GetVariable("GuildCreation", founders); + uint8 tmp = atoi(founders.c_str()); for(int i=0;iCharacterID()); guild_mgr.SetGuild(owner->CharacterID(),tmpeq,2); owner->SendAppearancePacket(AT_GuildID,true,false); diff --git a/zone/guild_mgr.h b/zone/guild_mgr.h index b7dd6d7e4..d06473392 100644 --- a/zone/guild_mgr.h +++ b/zone/guild_mgr.h @@ -61,7 +61,6 @@ public: private: Timer* deletion_timer; char guild[16]; - char founders[3]; Client* owner; Client* members[6]; uint32 refid; diff --git a/zone/net.cpp b/zone/net.cpp index 194e017fe..761583900 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -254,20 +254,20 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::Zone_Server, "Mapping Incoming Opcodes"); MapOpcodes(); - + Log.Out(Logs::General, Logs::Zone_Server, "Loading Variables"); database.LoadVariables(); - - char hotfix_name[256] = { 0 }; - if(database.GetVariable("hotfix_name", hotfix_name, 256)) { - if(strlen(hotfix_name) > 0) { - Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: '%s'", hotfix_name); + + std::string hotfix_name; + if(database.GetVariable("hotfix_name", hotfix_name)) { + if(!hotfix_name.empty()) { + Log.Out(Logs::General, Logs::Zone_Server, "Current hotfix in use: '%s'", hotfix_name.c_str()); } } Log.Out(Logs::General, Logs::Zone_Server, "Loading zone names"); database.LoadZoneNames(); - + Log.Out(Logs::General, Logs::Zone_Server, "Loading items"); if(!database.LoadItems(hotfix_name)) { Log.Out(Logs::General, Logs::Error, "Loading items FAILED!"); @@ -326,17 +326,17 @@ int main(int argc, char** argv) { //rules: { - char tmp[64]; - if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) { - Log.Out(Logs::General, Logs::Zone_Server, "Loading rule set '%s'", tmp); - if(!RuleManager::Instance()->LoadRules(&database, tmp)) { - Log.Out(Logs::General, Logs::Error, "Failed to load ruleset '%s', falling back to defaults.", tmp); + std::string tmp; + if (database.GetVariable("RuleSet", tmp)) { + Log.Out(Logs::General, Logs::Zone_Server, "Loading rule set '%s'", tmp.c_str()); + if(!RuleManager::Instance()->LoadRules(&database, tmp.c_str())) { + Log.Out(Logs::General, Logs::Error, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str()); } } else { if(!RuleManager::Instance()->LoadRules(&database, "default")) { Log.Out(Logs::General, Logs::Zone_Server, "No rule set configured, using default rules"); } else { - Log.Out(Logs::General, Logs::Zone_Server, "Loaded default rule set 'default'", tmp); + Log.Out(Logs::General, Logs::Zone_Server, "Loaded default rule set 'default'", tmp.c_str()); } } } diff --git a/zone/zone.cpp b/zone/zone.cpp index 80d11fe8c..55ec64110 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -104,10 +104,11 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { zone->watermap = WaterMap::LoadWaterMapfile(zone->map_name); zone->pathing = PathManager::LoadPathFile(zone->map_name); - char tmp[10]; - if (database.GetVariable("loglevel",tmp, 9)) { + std::string tmp; + if (database.GetVariable("loglevel", tmp)) { int log_levels[4]; - if (atoi(tmp)>9){ //Server is using the new code + int tmp_i = atoi(tmp.c_str()); + if (tmp_i>9){ //Server is using the new code for(int i=0;i<4;i++){ if (((int)tmp[i]>=48) && ((int)tmp[i]<=57)) log_levels[i]=(int)tmp[i]-48; //get the value to convert it to an int from the ascii value @@ -124,12 +125,12 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { Log.Out(Logs::General, Logs::Status, "Loot logging level: %i", zone->lootvar); } else { - zone->loglevelvar = uint8(atoi(tmp)); //continue supporting only command logging (for now) + zone->loglevelvar = uint8(tmp_i); //continue supporting only command logging (for now) zone->merchantvar = 0; zone->tradevar = 0; zone->lootvar = 0; } - } + } is_zone_loaded = true; From de48d79b273195db5b837ccda518bc1ef18105a7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 9 May 2016 21:46:05 -0400 Subject: [PATCH 080/693] Need to account for null byte --- world/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/client.cpp b/world/client.cpp index 6250fb0b9..696da355b 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -859,7 +859,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { outapp = new EQApplicationPacket(OP_MOTD); std::string tmp; if (database.GetVariable("MOTD", tmp)) { - outapp->size = tmp.length(); + outapp->size = tmp.length() + 1; outapp->pBuffer = new uchar[outapp->size]; memset(outapp->pBuffer,0,outapp->size); strcpy((char*)outapp->pBuffer, tmp.c_str()); From 37b84c4db103886181f5b3ee7eb510a7bd46b0d2 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 10 May 2016 20:16:27 -0400 Subject: [PATCH 081/693] Reworked client translators' SerializeItem() to recursive, single buffer methodology --- changelog.txt | 3 + common/patches/rof.cpp | 357 ++++++++-------------- common/patches/rof2.cpp | 359 ++++++++-------------- common/patches/rof2_structs.h | 3 +- common/patches/rof_structs.h | 5 +- common/patches/sod.cpp | 298 ++++++------------- common/patches/sod_structs.h | 3 +- common/patches/sof.cpp | 296 +++++++------------ common/patches/sof_structs.h | 1 - common/patches/titanium.cpp | 540 +++++++++++++++------------------- common/patches/uf.cpp | 319 +++++++------------- common/patches/uf_structs.h | 3 +- 12 files changed, 808 insertions(+), 1379 deletions(-) diff --git a/changelog.txt b/changelog.txt index 1bc585aa1..402ef67de 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/10/2016 == +Uleat: Converted client translators' 'SerializeItem()' to recursive, single buffer methodology. Titanium SerializeItem() now adds a null term between parent items instead of the invoking function + == 05/08/2016 == Uleat: Re-coded Titanium client translator 'SerializeItem()' to use coded property assignments over file enumerated ones diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 2fb93343a..49e644412 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -24,7 +24,7 @@ namespace RoF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline structs::InventorySlot_Struct ServerToRoFSlot(uint32 serverSlot); @@ -531,70 +531,52 @@ namespace RoF ENCODE(OP_CharInventory) { //consume the packet - EQApplicationPacket *in = *p; - + EQApplicationPacket* in = *p; *p = nullptr; - if (in->size == 0) { - + if (!in->size) { in->size = 4; in->pBuffer = new uchar[in->size]; - - *((uint32 *)in->pBuffer) = 0; + memset(in->pBuffer, 0, in->size); dest->FastQueuePacket(&in, ack_req); return; } //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - - int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); - - if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + uchar* __emu_buffer = in->pBuffer; + int item_count = in->size / sizeof(InternalSerializedItem_Struct); + if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); delete in; - return; } - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - in->pBuffer = new uchar[4]; - *(uint32 *)in->pBuffer = ItemCount; - in->size = 4; + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); - for (int r = 0; r < ItemCount; r++, eq++) { + ss.write((const char*)&item_count, sizeof(uint32)); - uint32 Length = 0; + for (int index = 0; index < item_count; ++index, ++eq) { + SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ss.tellp() == last_pos) + Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); - - if (Serialized) { - - uchar *OldBuffer = in->pBuffer; - in->pBuffer = new uchar[in->size + Length]; - memcpy(in->pBuffer, OldBuffer, in->size); - - safe_delete_array(OldBuffer); - - memcpy(in->pBuffer + in->size, Serialized, Length); - in->size += Length; - - safe_delete_array(Serialized); - } - else { - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } + last_pos = ss.tellp(); } - delete[] __emu_buffer; + std::string serialized = ss.str(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); - //Log.Hex(Logs::Netcode, in->pBuffer, in->size); + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); + + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); } @@ -1505,29 +1487,37 @@ namespace RoF ENCODE(OP_ItemPacket) { //consume the packet - EQApplicationPacket *in = *p; + EQApplicationPacket* in = *p; *p = nullptr; - unsigned char *__emu_buffer = in->pBuffer; - ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer; - InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem); + //store away the emu struct + uchar* __emu_buffer = in->pBuffer; + //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; + //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - uint32 length; - char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0); + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); - if (!serialized) { + ss.write((const char*)__emu_buffer, 4); + + SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ss.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - in->size = length + 4; - in->pBuffer = new unsigned char[in->size]; - ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer; - new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(new_item_pkt->SerializedItem, serialized, length); + + std::string serialized = ss.str(); + + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; + //new_item_pkt->PacketType = old_item_pkt->PacketType; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); delete[] __emu_buffer; - safe_delete_array(serialized); + dest->FastQueuePacket(&in, ack_req); } @@ -5190,53 +5180,43 @@ namespace RoF return NextItemInstSerialNumber; } - char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth) + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - uint8 null_term = 0; - bool stackable = inst->IsStackable(); - uint32 merchant_slot = inst->GetMerchantSlot(); - uint32 charges = inst->GetCharges(); - if (!stackable && charges > 254) - charges = 0xFFFFFFFF; - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - const Item_Struct *item = inst->GetUnscaledItem(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); - + RoF::structs::ItemSerializationHeader hdr; //sprintf(hdr.unknown000, "06e0002Y1W00"); snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%016d", item->ID); - hdr.stacksize = stackable ? charges : 1; + hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1); hdr.unknown004 = 0; structs::InventorySlot_Struct slot_id = ServerToRoFSlot(slot_id_in); - hdr.slot_type = (merchant_slot == 0) ? slot_id.Type : 9; // 9 is merchant 20 is reclaim items? - hdr.main_slot = (merchant_slot == 0) ? slot_id.Slot : merchant_slot; - hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubIndex : 0xffff; - hdr.unknown013 = (merchant_slot == 0) ? slot_id.AugIndex : 0xffff; + hdr.slot_type = (inst->GetMerchantSlot() ? inventory::TypeMerchant : slot_id.Type); + hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot); + hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex); + hdr.aug_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.AugIndex); hdr.price = inst->GetPrice(); - hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); - //hdr.merchant_slot = (merchant_slot == 0) ? 1 : 0xffffffff; - hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; - hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot; + hdr.merchant_slot = (inst->GetMerchantSlot() ? inst->GetMerchantCount() : 1); + hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0); + hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber()); hdr.unknown028 = 0; hdr.last_cast_time = inst->GetRecastTimestamp(); - hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges); - hdr.inst_nodrop = inst->IsAttuned() ? 1 : 0; + hdr.charges = (inst->IsStackable() ? (item->MaxCharges ? 1 : 0) : ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges())); + hdr.inst_nodrop = (inst->IsAttuned() ? 1 : 0); hdr.unknown044 = 0; hdr.unknown048 = 0; hdr.unknown052 = 0; hdr.isEvolving = item->EvolvingItem; + ss.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader)); if (item->EvolvingItem > 0) { RoF::structs::EvolvingItem evotop; + evotop.unknown001 = 0; evotop.unknown002 = 0; evotop.unknown003 = 0; @@ -5245,31 +5225,36 @@ namespace RoF evotop.progress = 0; evotop.Activated = 1; evotop.evomaxlevel = item->EvolvingMax; + ss.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem)); } + //ORNAMENT IDFILE / ICON + int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); uint32 ornaIcon = 0; uint32 heroModel = 0; - if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) - { - char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); - //Mainhand - ss.write(tmp, strlen(tmp)); - ss.write((const char*)&null_term, sizeof(uint8)); - //Offhand - ss.write(tmp, strlen(tmp)); - ss.write((const char*)&null_term, sizeof(uint8)); + if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { ornaIcon = inst->GetOrnamentationIcon(); heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in)); + + char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); + + //Mainhand + ss.write(tmp, strlen(tmp)); + ss.write("\0", 1); + + //Offhand + ss.write(tmp, strlen(tmp)); + ss.write("\0", 1); } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); // no main hand Ornamentation - ss.write((const char*)&null_term, sizeof(uint8)); // no off hand Ornamentation + else { + ss.write("\0", 1); // no main hand Ornamentation + ss.write("\0", 1); // no off hand Ornamentation } RoF::structs::ItemSerializationHeaderFinish hdrf; + hdrf.ornamentIcon = ornaIcon; hdrf.unknowna1 = 0xffffffff; hdrf.ornamentHeroModel = heroModel; @@ -5282,37 +5267,19 @@ namespace RoF ss.write((const char*)&hdrf, sizeof(RoF::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) - { ss.write(item->Name, strlen(item->Name)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); if (strlen(item->Lore) > 0) - { ss.write(item->Lore, strlen(item->Lore)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); if (strlen(item->IDFile) > 0) - { ss.write(item->IDFile, strlen(item->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); - ss.write((const char*)&null_term, sizeof(uint8)); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody struct is %i bytes", sizeof(RoF::structs::ItemBodyStruct)); + ss.write("\0", 1); + RoF::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(RoF::structs::ItemBodyStruct)); @@ -5363,12 +5330,8 @@ namespace RoF ibs.BaneDmgAmt = item->BaneDmgAmt; ibs.Magic = item->Magic; ibs.CastTime_ = item->CastTime_; - ibs.ReqLevel = item->ReqLevel; - if (item->ReqLevel > 100) - ibs.ReqLevel = 100; - ibs.RecLevel = item->RecLevel; - if (item->RecLevel > 100) - ibs.RecLevel = 100; + ibs.ReqLevel = ((item->ReqLevel > 100) ? 100 : item->ReqLevel); + ibs.RecLevel = ((item->RecLevel > 100) ? 100 : item->RecLevel); ibs.RecSkill = item->RecSkill; ibs.BardType = item->BardType; ibs.BardValue = item->BardValue; @@ -5410,16 +5373,9 @@ namespace RoF //charm text if (strlen(item->CharmFile) > 0) - { ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody secondary struct is %i bytes", sizeof(RoF::structs::ItemSecondaryBodyStruct)); RoF::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(RoF::structs::ItemSecondaryBodyStruct)); @@ -5427,11 +5383,10 @@ namespace RoF isbs.augdistiller = 65535; isbs.augrestrict = item->AugRestrict; - for (int x = AUG_INDEX_BEGIN; x < consts::ITEM_COMMON_SIZE; x++) - { - isbs.augslots[x].type = item->AugSlotType[x]; - isbs.augslots[x].visible = item->AugSlotVisible[x]; - isbs.augslots[x].unknown = item->AugSlotUnk2[x]; + for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) { + isbs.augslots[index].type = item->AugSlotType[index]; + isbs.augslots[index].visible = item->AugSlotVisible[index]; + isbs.augslots[index].unknown = item->AugSlotUnk2[index]; } isbs.ldonpoint_type = item->PointType; @@ -5451,16 +5406,9 @@ namespace RoF ss.write((const char*)&isbs, sizeof(RoF::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - { ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody tertiary struct is %i bytes", sizeof(RoF::structs::ItemTertiaryBodyStruct)); RoF::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(RoF::structs::ItemTertiaryBodyStruct)); @@ -5482,7 +5430,7 @@ namespace RoF itbs.potion_belt_enabled = item->PotionBelt; itbs.potion_belt_slots = item->PotionBeltSlots; - itbs.stacksize = stackable ? item->StackSize : 0; + itbs.stacksize = (inst->IsStackable() ? item->StackSize : 0); itbs.no_transfer = item->NoTransfer; itbs.expendablearrow = item->ExpendableArrow; @@ -5499,7 +5447,6 @@ namespace RoF // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Click effect struct is %i bytes", sizeof(RoF::structs::ClickEffectStruct)); RoF::structs::ClickEffectStruct ices; memset(&ices, 0, sizeof(RoF::structs::ClickEffectStruct)); @@ -5515,18 +5462,11 @@ namespace RoF ss.write((const char*)&ices, sizeof(RoF::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - { ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody proc effect struct is %i bytes", sizeof(RoF::structs::ProcEffectStruct)); RoF::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(RoF::structs::ProcEffectStruct)); @@ -5539,18 +5479,11 @@ namespace RoF ss.write((const char*)&ipes, sizeof(RoF::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - { ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody worn effect struct is %i bytes", sizeof(RoF::structs::WornEffectStruct)); RoF::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(RoF::structs::WornEffectStruct)); @@ -5562,14 +5495,8 @@ namespace RoF ss.write((const char*)&iwes, sizeof(RoF::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - { ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -5584,14 +5511,8 @@ namespace RoF ss.write((const char*)&ifes, sizeof(RoF::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - { ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -5606,14 +5527,8 @@ namespace RoF ss.write((const char*)&ises, sizeof(RoF::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - { ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -5636,12 +5551,11 @@ namespace RoF ss.write((const char*)&null_term, sizeof(uint8)); } else */ - ss.write((const char*)&null_term, sizeof(uint8)); + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Quaternary effect struct is %i bytes", sizeof(RoF::structs::ItemQuaternaryBodyStruct)); RoF::structs::ItemQuaternaryBodyStruct iqbs; memset(&iqbs, 0, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); @@ -5667,70 +5581,47 @@ namespace RoF iqbs.HeroicSVCorrup = item->HeroicSVCorrup; iqbs.HealAmt = item->HealAmt; iqbs.SpellDmg = item->SpellDmg; - iqbs.clairvoyance = item->Clairvoyance; + iqbs.Clairvoyance = item->Clairvoyance; iqbs.unknown28 = 0; iqbs.unknown30 = 0; iqbs.unknown39 = 1; - - iqbs.subitem_count = 0; - - char *SubSerializations[10]; // - - uint32 SubLengths[10]; - - for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { - - SubSerializations[x] = nullptr; - - const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); - - if (subitem) { - - int SubSlotNumber; - - iqbs.subitem_count++; - - if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor? - //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) - //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) - //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x); - else - SubSlotNumber = slot_id_in; // ??????? - - /* - // TEST CODE: - SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); - */ - - SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); - } - } - + ss.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); - for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { + std::stringstream::pos_type count_pos = ss.tellp(); + uint32 subitem_count = 0; - if (SubSerializations[x]) { + ss.write((const char*)&subitem_count, sizeof(uint32)); - ss.write((const char*)&x, sizeof(uint32)); + for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { + ItemInst* sub = inst->GetItem(index); + if (!sub) + continue; - ss.write(SubSerializations[x], SubLengths[x]); + int SubSlotNumber = INVALID_INDEX; + if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1); + else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index); + else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); + else + SubSlotNumber = slot_id_in; - safe_delete_array(SubSerializations[x]); - } + ss.write((const char*)&index, sizeof(uint32)); + + SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + ++subitem_count; } - char* item_serial = new char[ss.tellp()]; - memset(item_serial, 0, ss.tellp()); - memcpy(item_serial, ss.str().c_str(), ss.tellp()); + if (subitem_count) { + std::stringstream::pos_type cur_pos = ss.tellp(); + ss.seekp(count_pos); - *length = ss.tellp(); - return item_serial; + ss.write((const char*)&subitem_count, sizeof(uint32)); + + ss.seekp(cur_pos); + } } static inline structs::InventorySlot_Struct ServerToRoFSlot(uint32 serverSlot) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 005b1d298..43cc31d55 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -24,7 +24,7 @@ namespace RoF2 static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth, ItemPacketType packet_type); + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth, ItemPacketType packet_type); // server to client inventory location converters static inline structs::InventorySlot_Struct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType = ItemPacketInvalid); @@ -602,70 +602,52 @@ namespace RoF2 ENCODE(OP_CharInventory) { //consume the packet - EQApplicationPacket *in = *p; - + EQApplicationPacket* in = *p; *p = nullptr; - if (in->size == 0) { - + if (!in->size) { in->size = 4; in->pBuffer = new uchar[in->size]; - - *((uint32 *)in->pBuffer) = 0; + memset(in->pBuffer, 0, in->size); dest->FastQueuePacket(&in, ack_req); return; } //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - - int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); - - if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + uchar* __emu_buffer = in->pBuffer; + int item_count = in->size / sizeof(InternalSerializedItem_Struct); + if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); delete in; - return; } - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - in->pBuffer = new uchar[4]; - *(uint32 *)in->pBuffer = ItemCount; - in->size = 4; + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); - for (int r = 0; r < ItemCount; r++, eq++) { + ss.write((const char*)&item_count, sizeof(uint32)); - uint32 Length = 0; + for (int index = 0; index < item_count; ++index, ++eq) { + SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory); + if (ss.tellp() == last_pos) + Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0, ItemPacketCharInventory); - - if (Serialized) { - - uchar *OldBuffer = in->pBuffer; - in->pBuffer = new uchar[in->size + Length]; - memcpy(in->pBuffer, OldBuffer, in->size); - - safe_delete_array(OldBuffer); - - memcpy(in->pBuffer + in->size, Serialized, Length); - in->size += Length; - - safe_delete_array(Serialized); - } - else { - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } + last_pos = ss.tellp(); } - delete[] __emu_buffer; + std::string serialized = ss.str(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); - //Log.Hex(Logs::Netcode, in->pBuffer, in->size); + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); + + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); } @@ -1576,29 +1558,37 @@ namespace RoF2 ENCODE(OP_ItemPacket) { //consume the packet - EQApplicationPacket *in = *p; + EQApplicationPacket* in = *p; *p = nullptr; - unsigned char *__emu_buffer = in->pBuffer; - ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer; - InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem); + //store away the emu struct + uchar* __emu_buffer = in->pBuffer; + ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; + //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - uint32 length; - char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0, old_item_pkt->PacketType); + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); - if (!serialized) { + ss.write((const char*)__emu_buffer, 4); + + SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType); + if (ss.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - in->size = length + 4; - in->pBuffer = new unsigned char[in->size]; - ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer; - new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(new_item_pkt->SerializedItem, serialized, length); + + std::string serialized = ss.str(); + + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; + //new_item_pkt->PacketType = old_item_pkt->PacketType; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); delete[] __emu_buffer; - safe_delete_array(serialized); + dest->FastQueuePacket(&in, ack_req); } @@ -5461,52 +5451,43 @@ namespace RoF2 return NextItemInstSerialNumber; } - char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth, ItemPacketType packet_type) + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type) { - int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - uint8 null_term = 0; - bool stackable = inst->IsStackable(); - uint32 merchant_slot = inst->GetMerchantSlot(); - uint32 charges = inst->GetCharges(); - if (!stackable && charges > 254) - charges = 0xFFFFFFFF; - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - const Item_Struct *item = inst->GetUnscaledItem(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); - + RoF2::structs::ItemSerializationHeader hdr; //sprintf(hdr.unknown000, "06e0002Y1W00"); snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%016d", item->ID); - hdr.stacksize = stackable ? charges : 1; + hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1); hdr.unknown004 = 0; structs::InventorySlot_Struct slot_id = ServerToRoF2Slot(slot_id_in, packet_type); - hdr.slot_type = (merchant_slot == 0) ? slot_id.Type : 9; // 9 is merchant 20 is reclaim items? - hdr.main_slot = (merchant_slot == 0) ? slot_id.Slot : merchant_slot; - hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubIndex : 0xffff; - hdr.aug_slot = (merchant_slot == 0) ? slot_id.AugIndex : 0xffff; + hdr.slot_type = (inst->GetMerchantSlot() ? inventory::TypeMerchant : slot_id.Type); + hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot); + hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex); + hdr.aug_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.AugIndex); hdr.price = inst->GetPrice(); - hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); - hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; - hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot; + hdr.merchant_slot = (inst->GetMerchantSlot() ? inst->GetMerchantCount() : 1); + hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0); + hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber()); hdr.unknown028 = 0; hdr.last_cast_time = inst->GetRecastTimestamp(); - hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges); - hdr.inst_nodrop = inst->IsAttuned() ? 1 : 0; + hdr.charges = (inst->IsStackable() ? (item->MaxCharges ? 1 : 0) : ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges())); + hdr.inst_nodrop = (inst->IsAttuned() ? 1 : 0); hdr.unknown044 = 0; hdr.unknown048 = 0; hdr.unknown052 = 0; hdr.isEvolving = item->EvolvingItem; + ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); if (item->EvolvingItem > 0) { RoF2::structs::EvolvingItem evotop; + evotop.unknown001 = 0; evotop.unknown002 = 0; evotop.unknown003 = 0; @@ -5515,31 +5496,36 @@ namespace RoF2 evotop.progress = 0; evotop.Activated = 1; evotop.evomaxlevel = item->EvolvingMax; + ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); } + //ORNAMENT IDFILE / ICON + int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); uint32 ornaIcon = 0; uint32 heroModel = 0; - if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) - { - char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); - //Mainhand - ss.write(tmp, strlen(tmp)); - ss.write((const char*)&null_term, sizeof(uint8)); - //Offhand - ss.write(tmp, strlen(tmp)); - ss.write((const char*)&null_term, sizeof(uint8)); + if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { ornaIcon = inst->GetOrnamentationIcon(); heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in)); + + char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); + + //Mainhand + ss.write(tmp, strlen(tmp)); + ss.write("\0", 1); + + //Offhand + ss.write(tmp, strlen(tmp)); + ss.write("\0", 1); } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); // no main hand Ornamentation - ss.write((const char*)&null_term, sizeof(uint8)); // no off hand Ornamentation + else { + ss.write("\0", 1); // no main hand Ornamentation + ss.write("\0", 1); // no off hand Ornamentation } RoF2::structs::ItemSerializationHeaderFinish hdrf; + hdrf.ornamentIcon = ornaIcon; hdrf.unknowna1 = 0xffffffff; hdrf.ornamentHeroModel = heroModel; @@ -5552,37 +5538,19 @@ namespace RoF2 ss.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) - { ss.write(item->Name, strlen(item->Name)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); if (strlen(item->Lore) > 0) - { ss.write(item->Lore, strlen(item->Lore)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); if (strlen(item->IDFile) > 0) - { ss.write(item->IDFile, strlen(item->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); - ss.write((const char*)&null_term, sizeof(uint8)); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody struct is %i bytes", sizeof(RoF2::structs::ItemBodyStruct)); + ss.write("\0", 1); + RoF2::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct)); @@ -5633,12 +5601,8 @@ namespace RoF2 ibs.BaneDmgAmt = item->BaneDmgAmt; ibs.Magic = item->Magic; ibs.CastTime_ = item->CastTime_; - ibs.ReqLevel = item->ReqLevel; - if (item->ReqLevel > 100) - ibs.ReqLevel = 100; - ibs.RecLevel = item->RecLevel; - if (item->RecLevel > 100) - ibs.RecLevel = 100; + ibs.ReqLevel = ((item->ReqLevel > 100) ? 100 : item->ReqLevel); + ibs.RecLevel = ((item->RecLevel > 100) ? 100 : item->RecLevel); ibs.RecSkill = item->RecSkill; ibs.BardType = item->BardType; ibs.BardValue = item->BardValue; @@ -5680,16 +5644,9 @@ namespace RoF2 //charm text if (strlen(item->CharmFile) > 0) - { ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody secondary struct is %i bytes", sizeof(RoF2::structs::ItemSecondaryBodyStruct)); RoF2::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); @@ -5697,11 +5654,10 @@ namespace RoF2 isbs.augrestrict2 = -1; isbs.augrestrict = item->AugRestrict; - for (int x = AUG_INDEX_BEGIN; x < consts::ITEM_COMMON_SIZE; x++) - { - isbs.augslots[x].type = item->AugSlotType[x]; - isbs.augslots[x].visible = item->AugSlotVisible[x]; - isbs.augslots[x].unknown = item->AugSlotUnk2[x]; + for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) { + isbs.augslots[index].type = item->AugSlotType[index]; + isbs.augslots[index].visible = item->AugSlotVisible[index]; + isbs.augslots[index].unknown = item->AugSlotUnk2[index]; } isbs.ldonpoint_type = item->PointType; @@ -5721,16 +5677,9 @@ namespace RoF2 ss.write((const char*)&isbs, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - { ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody tertiary struct is %i bytes", sizeof(RoF2::structs::ItemTertiaryBodyStruct)); RoF2::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); @@ -5752,7 +5701,7 @@ namespace RoF2 itbs.potion_belt_enabled = item->PotionBelt; itbs.potion_belt_slots = item->PotionBeltSlots; - itbs.stacksize = stackable ? item->StackSize : 0; + itbs.stacksize = (inst->IsStackable() ? item->StackSize : 0); itbs.no_transfer = item->NoTransfer; itbs.expendablearrow = item->ExpendableArrow; @@ -5769,7 +5718,6 @@ namespace RoF2 // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Click effect struct is %i bytes", sizeof(RoF2::structs::ClickEffectStruct)); RoF2::structs::ClickEffectStruct ices; memset(&ices, 0, sizeof(RoF2::structs::ClickEffectStruct)); @@ -5785,18 +5733,11 @@ namespace RoF2 ss.write((const char*)&ices, sizeof(RoF2::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - { ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody proc effect struct is %i bytes", sizeof(RoF2::structs::ProcEffectStruct)); RoF2::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(RoF2::structs::ProcEffectStruct)); @@ -5809,18 +5750,11 @@ namespace RoF2 ss.write((const char*)&ipes, sizeof(RoF2::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - { ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody worn effect struct is %i bytes", sizeof(RoF2::structs::WornEffectStruct)); RoF2::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(RoF2::structs::WornEffectStruct)); @@ -5832,14 +5766,8 @@ namespace RoF2 ss.write((const char*)&iwes, sizeof(RoF2::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - { ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -5854,14 +5782,8 @@ namespace RoF2 ss.write((const char*)&ifes, sizeof(RoF2::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - { ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -5876,14 +5798,8 @@ namespace RoF2 ss.write((const char*)&ises, sizeof(RoF2::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - { ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -5906,12 +5822,11 @@ namespace RoF2 ss.write((const char*)&null_term, sizeof(uint8)); } else */ - ss.write((const char*)&null_term, sizeof(uint8)); + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Quaternary effect struct is %i bytes", sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); RoF2::structs::ItemQuaternaryBodyStruct iqbs; memset(&iqbs, 0, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); @@ -5937,83 +5852,57 @@ namespace RoF2 iqbs.HeroicSVCorrup = item->HeroicSVCorrup; iqbs.HealAmt = item->HealAmt; iqbs.SpellDmg = item->SpellDmg; - iqbs.clairvoyance = item->Clairvoyance; + iqbs.Clairvoyance = item->Clairvoyance; //unknown18; //Power Source Capacity or evolve filename? //evolve_string; // Some String, but being evolution related is just a guess iqbs.Heirloom = 0; iqbs.Placeable = 0; - iqbs.unknown28 = -1; iqbs.unknown30 = -1; - iqbs.NoZone = 0; iqbs.NoGround = 0; iqbs.unknown37a = 0; // (guessed position) New to RoF2 iqbs.unknown38 = 0; - iqbs.unknown39 = 1; - - iqbs.subitem_count = 0; - - char *SubSerializations[10]; // - - uint32 SubLengths[10]; - - for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { - - SubSerializations[x] = nullptr; - - const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); - - if (subitem) { - - int SubSlotNumber; - - iqbs.subitem_count++; - - if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor? - //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) - //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) - //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x); - else - SubSlotNumber = slot_id_in; // ??????? - - /* - // TEST CODE: - SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); - */ - - SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1, packet_type); - } - } - + ss.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); - for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { + std::stringstream::pos_type count_pos = ss.tellp(); + uint32 subitem_count = 0; - if (SubSerializations[x]) { + ss.write((const char*)&subitem_count, sizeof(uint32)); - ss.write((const char*)&x, sizeof(uint32)); + for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { + ItemInst* sub = inst->GetItem(index); + if (!sub) + continue; - ss.write(SubSerializations[x], SubLengths[x]); + int SubSlotNumber = INVALID_INDEX; + if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1); + else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index); + else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); + else + SubSlotNumber = slot_id_in; - safe_delete_array(SubSerializations[x]); - } + ss.write((const char*)&index, sizeof(uint32)); + + SerializeItem(ss, sub, SubSlotNumber, (depth + 1), packet_type); + ++subitem_count; } - char* item_serial = new char[ss.tellp()]; - memset(item_serial, 0, ss.tellp()); - memcpy(item_serial, ss.str().c_str(), ss.tellp()); + if (subitem_count) { + std::stringstream::pos_type cur_pos = ss.tellp(); + ss.seekp(count_pos); - *length = ss.tellp(); - return item_serial; + ss.write((const char*)&subitem_count, sizeof(uint32)); + + ss.seekp(cur_pos); + } } static inline structs::InventorySlot_Struct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 0e457a0d1..7464f22cd 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4795,7 +4795,7 @@ struct ItemQuaternaryBodyStruct int32 HeroicSVCorrup; int32 HealAmt; int32 SpellDmg; - int32 clairvoyance; + int32 Clairvoyance; uint8 unknown18; //Power Source Capacity or evolve filename? uint32 evolve_string; // Some String, but being evolution related is just a guess uint8 unknown19; @@ -4833,7 +4833,6 @@ struct ItemQuaternaryBodyStruct uint8 unknown37a; // New to RoF2 - Probably variable length string uint8 unknown38; // 0 uint8 unknown39; // 1 - uint32 subitem_count; }; struct AugmentInfo_Struct diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 4c7ecc1c1..a143e32ce 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4530,7 +4530,7 @@ struct ItemSerializationHeader /*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ? /*026*/ uint16 main_slot; /*028*/ uint16 sub_slot; -/*030*/ uint16 unknown013; // 0xffff +/*030*/ uint16 aug_slot; // 0xffff /*032*/ uint32 price; /*036*/ uint32 merchant_slot; //1 if not a merchant item /*040*/ uint32 scaled_value; //0 @@ -4794,7 +4794,7 @@ struct ItemQuaternaryBodyStruct int32 HeroicSVCorrup; int32 HealAmt; int32 SpellDmg; - int32 clairvoyance; + int32 Clairvoyance; uint8 unknown18; //Power Source Capacity or evolve filename? uint32 evolve_string; // Some String, but being evolution related is just a guess uint8 unknown19; @@ -4821,7 +4821,6 @@ struct ItemQuaternaryBodyStruct uint32 unknown_RoF8; uint8 unknown38; // 0 uint8 unknown39; // 1 - uint32 subitem_count; }; struct AugmentInfo_Struct diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 48b7248ed..9902447b8 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -22,7 +22,7 @@ namespace SoD static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToSoDSlot(uint32 ServerSlot); @@ -335,30 +335,23 @@ namespace SoD ENCODE(OP_CharInventory) { //consume the packet - EQApplicationPacket *in = *p; - + EQApplicationPacket* in = *p; *p = nullptr; - if (in->size == 0) { - + if (!in->size) { in->size = 4; - in->pBuffer = new uchar[in->size]; - - *((uint32 *)in->pBuffer) = 0; + memset(in->pBuffer, 0, in->size); dest->FastQueuePacket(&in, ack_req); - return; } //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - - int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); - - if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + uchar* __emu_buffer = in->pBuffer; + int item_count = in->size / sizeof(InternalSerializedItem_Struct); + if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); @@ -366,39 +359,28 @@ namespace SoD return; } - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; - in->pBuffer = new uchar[4]; - *(uint32 *)in->pBuffer = ItemCount; - in->size = 4; + InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - for (int r = 0; r < ItemCount; r++, eq++) { + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); - uint32 Length = 0; - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); + ss.write((const char*)&item_count, sizeof(uint32)); - if (Serialized) { + for (int index = 0; index < item_count; ++index, ++eq) { + SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ss.tellp() == last_pos) + Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - uchar *OldBuffer = in->pBuffer; - in->pBuffer = new uchar[in->size + Length]; - memcpy(in->pBuffer, OldBuffer, in->size); - - safe_delete_array(OldBuffer); - - memcpy(in->pBuffer + in->size, Serialized, Length); - in->size += Length; - - safe_delete_array(Serialized); - - } - else { - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } + last_pos = ss.tellp(); } - delete[] __emu_buffer; + std::string serialized = ss.str(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); - //Log.Hex(Logs::Netcode, in->pBuffer, in->size); + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); + + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); } @@ -1036,29 +1018,37 @@ namespace SoD ENCODE(OP_ItemPacket) { //consume the packet - EQApplicationPacket *in = *p; + EQApplicationPacket* in = *p; *p = nullptr; - unsigned char *__emu_buffer = in->pBuffer; - ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer; - InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem); + //store away the emu struct + uchar* __emu_buffer = in->pBuffer; + //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; + //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - uint32 length; - char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0); + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); - if (!serialized) { + ss.write((const char*)__emu_buffer, 4); + + SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ss.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - in->size = length + 4; - in->pBuffer = new unsigned char[in->size]; - ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer; - new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(new_item_pkt->SerializedItem, serialized, length); + + std::string serialized = ss.str(); + + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; + //new_item_pkt->PacketType = old_item_pkt->PacketType; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); delete[] __emu_buffer; - safe_delete_array(serialized); + dest->FastQueuePacket(&in, ack_req); } @@ -3550,34 +3540,26 @@ namespace SoD return NextItemInstSerialNumber; } - char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth) + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - uint8 null_term = 0; - bool stackable = inst->IsStackable(); - uint32 merchant_slot = inst->GetMerchantSlot(); - uint32 charges = inst->GetCharges(); - if (!stackable && charges > 254) - charges = 0xFFFFFFFF; - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - const Item_Struct *item = inst->GetUnscaledItem(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); + SoD::structs::ItemSerializationHeader hdr; - hdr.stacksize = stackable ? charges : 1; + + hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1); hdr.unknown004 = 0; int32 slot_id = ServerToSoDSlot(slot_id_in); - hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot; + hdr.slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id); hdr.price = inst->GetPrice(); - hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); - hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; - hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot; + hdr.merchant_slot = (inst->GetMerchantSlot() ? inst->GetMerchantCount() : 1); + hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0); + hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber()); hdr.unknown028 = 0; hdr.last_cast_time = inst->GetRecastTimestamp(); - hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges); - hdr.inst_nodrop = inst->IsAttuned() ? 1 : 0; + hdr.charges = (inst->IsStackable() ? (item->MaxCharges ? 1 : 0) : ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges())); + hdr.inst_nodrop = (inst->IsAttuned() ? 1 : 0); hdr.unknown044 = 0; hdr.unknown048 = 0; hdr.unknown052 = 0; @@ -3590,41 +3572,23 @@ namespace SoD ss.write((const char*)&hdr, sizeof(SoD::structs::ItemSerializationHeader)); if (strlen(item->Name) > 0) - { ss.write(item->Name, strlen(item->Name)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); if (strlen(item->Lore) > 0) - { ss.write(item->Lore, strlen(item->Lore)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); if (strlen(item->IDFile) > 0) - { ss.write(item->IDFile, strlen(item->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); SoD::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(SoD::structs::ItemBodyStruct)); ibs.id = item->ID; // weight is uint8 in the struct, and some weights exceed that, so capping at 255. - ibs.weight = (item->Weight > 255) ? 255 : item->Weight; + ibs.weight = ((item->Weight > 255) ? 255 : item->Weight); ibs.norent = item->NoRent; ibs.nodrop = item->NoDrop; ibs.attune = item->Attuneable; @@ -3710,14 +3674,8 @@ namespace SoD //charm text if (strlen(item->CharmFile) > 0) - { ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); SoD::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(SoD::structs::ItemSecondaryBodyStruct)); @@ -3725,11 +3683,10 @@ namespace SoD isbs.augtype = item->AugType; isbs.augrestrict = item->AugRestrict; - for (int x = 0; x < consts::ITEM_COMMON_SIZE; x++) - { - isbs.augslots[x].type = item->AugSlotType[x]; - isbs.augslots[x].visible = item->AugSlotVisible[x]; - isbs.augslots[x].unknown = item->AugSlotUnk2[x]; + for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) { + isbs.augslots[index].type = item->AugSlotType[index]; + isbs.augslots[index].visible = item->AugSlotVisible[index]; + isbs.augslots[index].unknown = item->AugSlotUnk2[index]; } isbs.ldonpoint_type = item->PointType; @@ -3749,14 +3706,8 @@ namespace SoD ss.write((const char*)&isbs, sizeof(SoD::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - { ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); SoD::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(SoD::structs::ItemTertiaryBodyStruct)); @@ -3776,7 +3727,7 @@ namespace SoD itbs.potion_belt_enabled = item->PotionBelt; itbs.potion_belt_slots = item->PotionBeltSlots; - itbs.stacksize = stackable ? item->StackSize : 0; + itbs.stacksize = (inst->IsStackable() ? item->StackSize : 0); itbs.no_transfer = item->NoTransfer; itbs.expendablearrow = item->ExpendableArrow; @@ -3800,14 +3751,8 @@ namespace SoD ss.write((const char*)&ices, sizeof(SoD::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - { ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 @@ -3823,14 +3768,8 @@ namespace SoD ss.write((const char*)&ipes, sizeof(SoD::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - { ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 @@ -3845,14 +3784,8 @@ namespace SoD ss.write((const char*)&iwes, sizeof(SoD::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - { ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -3867,14 +3800,8 @@ namespace SoD ss.write((const char*)&ifes, sizeof(SoD::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - { ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -3889,14 +3816,8 @@ namespace SoD ss.write((const char*)&ises, sizeof(SoD::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - { ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects @@ -3926,67 +3847,44 @@ namespace SoD iqbs.HeroicSVCorrup = item->HeroicSVCorrup; iqbs.HealAmt = item->HealAmt; iqbs.SpellDmg = item->SpellDmg; - iqbs.clairvoyance = item->Clairvoyance; - - iqbs.subitem_count = 0; - - char *SubSerializations[10]; // - - uint32 SubLengths[10]; - - for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { - - SubSerializations[x] = nullptr; - - const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); - - if (subitem) { - - int SubSlotNumber; - - iqbs.subitem_count++; - - if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor? - //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) - //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) - //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x); - else - SubSlotNumber = slot_id_in; // ??????? - - /* - // TEST CODE: - SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); - */ - - SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); - } - } - + iqbs.Clairvoyance = item->Clairvoyance; + ss.write((const char*)&iqbs, sizeof(SoD::structs::ItemQuaternaryBodyStruct)); - for (int x = 0; x < 10; ++x) { + std::stringstream::pos_type count_pos = ss.tellp(); + uint32 subitem_count = 0; - if (SubSerializations[x]) { + ss.write((const char*)&subitem_count, sizeof(uint32)); - ss.write((const char*)&x, sizeof(uint32)); + for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { + ItemInst* sub = inst->GetItem(index); + if (!sub) + continue; - ss.write(SubSerializations[x], SubLengths[x]); + int SubSlotNumber = INVALID_INDEX; + if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1); + else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index); + else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); + else + SubSlotNumber = slot_id_in; - safe_delete_array(SubSerializations[x]); - } + ss.write((const char*)&index, sizeof(uint32)); + + SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + ++subitem_count; } - char* item_serial = new char[ss.tellp()]; - memset(item_serial, 0, ss.tellp()); - memcpy(item_serial, ss.str().c_str(), ss.tellp()); + if (subitem_count) { + std::stringstream::pos_type cur_pos = ss.tellp(); + ss.seekp(count_pos); - *length = ss.tellp(); - return item_serial; + ss.write((const char*)&subitem_count, sizeof(uint32)); + + ss.seekp(cur_pos); + } } static inline uint32 ServerToSoDSlot(uint32 serverSlot) diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 20e2a56b4..7f1b76d52 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -4184,10 +4184,9 @@ struct ItemQuaternaryBodyStruct int32 HeroicSVCorrup; int32 HealAmt; int32 SpellDmg; - int32 clairvoyance; + int32 Clairvoyance; uint8 unknown18; //Power Source Capacity or evolve filename? uint32 evolve_string; // Some String, but being evolution related is just a guess - uint32 subitem_count; }; struct AugmentInfo_Struct diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index ef0220f57..e2526cb45 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -22,7 +22,7 @@ namespace SoF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToSoFSlot(uint32 serverSlot); @@ -317,26 +317,23 @@ namespace SoF ENCODE(OP_CharInventory) { //consume the packet - EQApplicationPacket *in = *p; - + EQApplicationPacket* in = *p; *p = nullptr; - if (in->size == 0) { + if (!in->size) { in->size = 4; in->pBuffer = new uchar[in->size]; - *((uint32 *)in->pBuffer) = 0; + memset(in->pBuffer, 0, in->size); dest->FastQueuePacket(&in, ack_req); return; } //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - - int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); - - if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + uchar* __emu_buffer = in->pBuffer; + int item_count = in->size / sizeof(InternalSerializedItem_Struct); + if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); @@ -344,41 +341,28 @@ namespace SoF return; } - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - in->pBuffer = new uchar[4]; - *(uint32 *)in->pBuffer = ItemCount; - in->size = 4; + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); - for (int r = 0; r < ItemCount; r++, eq++) { + ss.write((const char*)&item_count, sizeof(uint32)); - uint32 Length = 0; + for (int index = 0; index < item_count; ++index, ++eq) { + SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ss.tellp() == last_pos) + Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); - - if (Serialized) { - uchar *OldBuffer = in->pBuffer; - - in->pBuffer = new uchar[in->size + Length]; - memcpy(in->pBuffer, OldBuffer, in->size); - - safe_delete_array(OldBuffer); - - memcpy(in->pBuffer + in->size, Serialized, Length); - in->size += Length; - - safe_delete_array(Serialized); - - } - else { - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } + last_pos = ss.tellp(); } - delete[] __emu_buffer; + std::string serialized = ss.str(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); - //Log.Hex(Logs::Netcode, in->pBuffer, in->size); + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); + + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); } @@ -834,29 +818,37 @@ namespace SoF ENCODE(OP_ItemPacket) { //consume the packet - EQApplicationPacket *in = *p; + EQApplicationPacket* in = *p; *p = nullptr; - unsigned char *__emu_buffer = in->pBuffer; - ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer; - InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem); + //store away the emu struct + uchar* __emu_buffer = in->pBuffer; + //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; + //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - uint32 length; - char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0); + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); - if (!serialized) { + ss.write((const char*)__emu_buffer, 4); + + SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ss.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - in->size = length + 4; - in->pBuffer = new unsigned char[in->size]; - ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer; - new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(new_item_pkt->SerializedItem, serialized, length); + + std::string serialized = ss.str(); + + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; + //new_item_pkt->PacketType = old_item_pkt->PacketType; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); delete[] __emu_buffer; - safe_delete_array(serialized); + dest->FastQueuePacket(&in, ack_req); } @@ -2873,34 +2865,26 @@ namespace SoF return NextItemInstSerialNumber; } - char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth) + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - uint8 null_term = 0; - bool stackable = inst->IsStackable(); - uint32 merchant_slot = inst->GetMerchantSlot(); - uint32 charges = inst->GetCharges(); - if (!stackable && charges > 254) - charges = 0xFFFFFFFF; - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - const Item_Struct *item = inst->GetUnscaledItem(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); + SoF::structs::ItemSerializationHeader hdr; - hdr.stacksize = stackable ? charges : 1; + + hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1); hdr.unknown004 = 0; int32 slot_id = ServerToSoFSlot(slot_id_in); - hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot; + hdr.slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id); hdr.price = inst->GetPrice(); - hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); - hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; - hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot; + hdr.merchant_slot = (inst->GetMerchantSlot() ? inst->GetMerchantCount() : 1); + hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0); + hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber()); hdr.unknown028 = 0; hdr.last_cast_time = inst->GetRecastTimestamp(); - hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges); - hdr.inst_nodrop = inst->IsAttuned() ? 1 : 0; + hdr.charges = (inst->IsStackable() ? (item->MaxCharges ? 1 : 0) : ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges())); + hdr.inst_nodrop = (inst->IsAttuned() ? 1 : 0); hdr.unknown044 = 0; hdr.unknown048 = 0; hdr.unknown052 = 0; @@ -2912,41 +2896,23 @@ namespace SoF ss.write((const char*)&hdr, sizeof(SoF::structs::ItemSerializationHeader)); if (strlen(item->Name) > 0) - { ss.write(item->Name, strlen(item->Name)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); if (strlen(item->Lore) > 0) - { ss.write(item->Lore, strlen(item->Lore)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); if (strlen(item->IDFile) > 0) - { ss.write(item->IDFile, strlen(item->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); SoF::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(SoF::structs::ItemBodyStruct)); ibs.id = item->ID; // weight is uint8 in the struct, and some weights exceed that, so capping at 255. - ibs.weight = (item->Weight > 255) ? 255 : item->Weight; + ibs.weight = ((item->Weight > 255) ? 255 : item->Weight); ibs.norent = item->NoRent; ibs.nodrop = item->NoDrop; ibs.attune = item->Attuneable; @@ -3032,14 +2998,8 @@ namespace SoF //charm text if (strlen(item->CharmFile) > 0) - { ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); SoF::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(SoF::structs::ItemSecondaryBodyStruct)); @@ -3047,11 +3007,10 @@ namespace SoF isbs.augtype = item->AugType; isbs.augrestrict = item->AugRestrict; - for (int x = 0; x < consts::ITEM_COMMON_SIZE; x++) - { - isbs.augslots[x].type = item->AugSlotType[x]; - isbs.augslots[x].visible = item->AugSlotVisible[x]; - isbs.augslots[x].unknown = item->AugSlotUnk2[x]; + for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) { + isbs.augslots[index].type = item->AugSlotType[index]; + isbs.augslots[index].visible = item->AugSlotVisible[index]; + isbs.augslots[index].unknown = item->AugSlotUnk2[index]; } isbs.ldonpoint_type = item->PointType; @@ -3071,14 +3030,8 @@ namespace SoF ss.write((const char*)&isbs, sizeof(SoF::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - { ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); SoF::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(SoF::structs::ItemTertiaryBodyStruct)); @@ -3098,7 +3051,7 @@ namespace SoF itbs.potion_belt_enabled = item->PotionBelt; itbs.potion_belt_slots = item->PotionBeltSlots; - itbs.stacksize = stackable ? item->StackSize : 0; + itbs.stacksize = (inst->IsStackable() ? item->StackSize : 0); itbs.no_transfer = item->NoTransfer; itbs.expendablearrow = item->ExpendableArrow; @@ -3122,14 +3075,8 @@ namespace SoF ss.write((const char*)&ices, sizeof(SoF::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - { ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 @@ -3145,14 +3092,8 @@ namespace SoF ss.write((const char*)&ipes, sizeof(SoF::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - { ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 @@ -3167,14 +3108,8 @@ namespace SoF ss.write((const char*)&iwes, sizeof(SoF::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - { ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -3189,14 +3124,8 @@ namespace SoF ss.write((const char*)&ifes, sizeof(SoF::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - { ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -3211,14 +3140,8 @@ namespace SoF ss.write((const char*)&ises, sizeof(SoF::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - { ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects @@ -3248,64 +3171,43 @@ namespace SoF iqbs.HeroicSVCorrup = item->HeroicSVCorrup; iqbs.HealAmt = item->HealAmt; iqbs.SpellDmg = item->SpellDmg; - //iqbs.clairvoyance = item->Clairvoyance; - - iqbs.subitem_count = 0; - - char *SubSerializations[10]; // - - uint32 SubLengths[10]; - - for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { - - SubSerializations[x] = nullptr; - const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); - - if (subitem) { - - int SubSlotNumber; - - iqbs.subitem_count++; - - if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor? - //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) - //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) - //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x); - else - SubSlotNumber = slot_id_in; // ??????? - - /* - // TEST CODE: - SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); - */ - - SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); - } - } - + ss.write((const char*)&iqbs, sizeof(SoF::structs::ItemQuaternaryBodyStruct)); - for (int x = 0; x < 10; ++x) { + std::stringstream::pos_type count_pos = ss.tellp(); + uint32 subitem_count = 0; - if (SubSerializations[x]) { - ss.write((const char*)&x, sizeof(uint32)); - ss.write(SubSerializations[x], SubLengths[x]); + ss.write((const char*)&subitem_count, sizeof(uint32)); - safe_delete_array(SubSerializations[x]); - } + for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { + ItemInst* sub = inst->GetItem(index); + if (!sub) + continue; + + int SubSlotNumber = INVALID_INDEX; + if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1); + else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index); + else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); + else + SubSlotNumber = slot_id_in; + + ss.write((const char*)&index, sizeof(uint32)); + + SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + ++subitem_count; } - char* item_serial = new char[ss.tellp()]; - memset(item_serial, 0, ss.tellp()); - memcpy(item_serial, ss.str().c_str(), ss.tellp()); + if (subitem_count) { + std::stringstream::pos_type cur_pos = ss.tellp(); + ss.seekp(count_pos); - *length = ss.tellp(); - return item_serial; + ss.write((const char*)&subitem_count, sizeof(uint32)); + + ss.seekp(cur_pos); + } } static inline uint32 ServerToSoFSlot(uint32 serverSlot) diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index d78277721..521d66477 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -4039,7 +4039,6 @@ struct ItemQuaternaryBodyStruct int32 HealAmt; int32 SpellDmg; uint32 evolve_string; // Some String, but being evolution related is just a guess - uint32 subitem_count; }; struct AugmentInfo_Struct diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 98b3b64f9..cdfbf0250 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -20,7 +20,7 @@ namespace Titanium static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - std::string SerializeItem(const ItemInst *inst, int16 slot_id_in, uint8 depth); + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth); // server to client inventory location converters static inline int16 ServerToTitaniumSlot(uint32 serverSlot); @@ -260,11 +260,11 @@ namespace Titanium ENCODE(OP_CharInventory) { //consume the packet - EQApplicationPacket *in = *p; + EQApplicationPacket* in = *p; *p = nullptr; //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; + uchar* __emu_buffer = in->pBuffer; int itemcount = in->size / sizeof(InternalSerializedItem_Struct); if (itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { @@ -272,26 +272,25 @@ namespace Titanium delete in; return; } - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; //do the transform... - std::string serial_string; - for (int r = 0; r < itemcount; r++, eq++) { - std::string serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, 0); // assumed move operation: string& = string&& - if (!serialized.empty()) { - serial_string.append(serialized); - serial_string.push_back('\0'); - } - else { - Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); + for (int r = 0; r < itemcount; r++, eq++) { + SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ss.tellp() == last_pos) + Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + + last_pos = ss.tellp(); } - // do we need to account for a trailing null escape? - in->size = serial_string.size(); - in->pBuffer = new unsigned char[in->size]; - memcpy(in->pBuffer, serial_string.c_str(), serial_string.size()); + std::string serialized = ss.str(); + + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); delete[] __emu_buffer; @@ -716,27 +715,34 @@ namespace Titanium ENCODE(OP_ItemPacket) { //consume the packet - EQApplicationPacket *in = *p; + EQApplicationPacket* in = *p; *p = nullptr; //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer; - InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem); + uchar* __emu_buffer = in->pBuffer; + //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; + //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::string serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, 0); // assumed move operation: string& = string&& - if (serialized.empty()) { + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); + + ss.write((const char*)__emu_buffer, 4); + + SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ss.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - in->size = serialized.size() + 5; // ItemPacketType + Serialization + \0 - in->pBuffer = new unsigned char[in->size]; - ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer; - new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(new_item_pkt->SerializedItem, serialized.c_str(), serialized.size()); - new_item_pkt->SerializedItem[serialized.size()] = '\0'; + std::string serialized = ss.str(); + + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; + //new_item_pkt->PacketType = old_item_pkt->PacketType; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); delete[] __emu_buffer; @@ -2077,301 +2083,241 @@ namespace Titanium } // file scope helper methods - std::string SerializeItem(const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - std::string serialization; const char* protection = "\\\\\\\\\\"; const Item_Struct* item = inst->GetUnscaledItem(); - serialization = StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; + ss << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; // Instance data - serialization.append( - StringFormat( - "%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|", - (inst->IsStackable() ? inst->GetCharges() : 0), // stack count - 0, // unknown - (!inst->GetMerchantSlot() ? slot_id_in : inst->GetMerchantSlot()), // inst slot/merchant slot - inst->GetPrice(), // merchant price - (!inst->GetMerchantSlot() ? 1 : inst->GetMerchantCount()), // inst count/merchant count - (inst->IsScaling() ? (inst->GetExp() / 100) : 0), // inst experience - (!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot()), // merchant serial number - inst->GetRecastTimestamp(), // recast timestamp - ((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges())), // charge count - (inst->IsAttuned() ? 1 : 0), // inst attuned - 0 // unknown - ) - ); - - serialization.append(StringFormat("%.*s\"", depth, protection)); // Quotes (and protection, if needed) around static data + ss << itoa((inst->IsStackable() ? inst->GetCharges() : 0)); // stack count + ss << '|' << itoa(0); // unknown + ss << '|' << itoa((!inst->GetMerchantSlot() ? slot_id_in : inst->GetMerchantSlot())); // inst slot/merchant slot + ss << '|' << itoa(inst->GetPrice()); // merchant price + ss << '|' << itoa((!inst->GetMerchantSlot() ? 1 : inst->GetMerchantCount())); // inst count/merchant count + ss << '|' << itoa((inst->IsScaling() ? (inst->GetExp() / 100) : 0)); // inst experience + ss << '|' << itoa((!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot())); // merchant serial number + ss << '|' << itoa(inst->GetRecastTimestamp()); // recast timestamp + ss << '|' << itoa(((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges()))); // charge count + ss << '|' << itoa((inst->IsAttuned() ? 1 : 0)); // inst attuned + ss << '|' << itoa(0); // unknown + ss << '|'; - serialization.append(StringFormat("%i", item->ItemClass)); // item->ItemClass so we can do |%s instead of %s| - - serialization.append( - StringFormat( - "|%s|%s|%s|%i|%i|%i|%i|%i|%i|%i|%i|%s|%s|%i|%i", - item->Name, - item->Lore, - item->IDFile, - item->ID, - ((item->Weight > 255) ? 255 : item->Weight), - item->NoRent, - item->NoDrop, - item->Size, - item->Slots, - item->Price, - item->Icon, - "0", // unknown - "0", // unknown - item->BenefitFlag, - item->Tradeskills - ) - ); + ss << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i", - item->CR, - item->DR, - item->PR, - item->MR, - item->FR, - item->AStr, - item->ASta, - item->AAgi, - item->ADex, - item->ACha, - item->AInt, - item->AWis, - item->HP, - item->Mana, - item->AC - ) - ); + // Item data + ss << itoa(item->ItemClass); + ss << '|' << item->Name; + ss << '|' << item->Lore; + ss << '|' << item->IDFile; + ss << '|' << itoa(item->ID); + ss << '|' << itoa(((item->Weight > 255) ? 255 : item->Weight)); + ss << '|' << itoa(item->NoRent); + ss << '|' << itoa(item->NoDrop); + ss << '|' << itoa(item->Size); + ss << '|' << itoa(item->Slots); + ss << '|' << itoa(item->Price); + ss << '|' << itoa(item->Icon); + ss << '|' << "0"; + ss << '|' << "0"; + ss << '|' << itoa(item->BenefitFlag); + ss << '|' << itoa(item->Tradeskills); - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i", - item->Deity, - item->SkillModValue, - item->SkillModMax, - item->SkillModType, - item->BaneDmgRace, - item->BaneDmgAmt, - item->BaneDmgBody, - item->Magic, - item->CastTime_, - item->ReqLevel, - item->BardType, - item->BardValue, - item->Light, - item->Delay - ) - ); + ss << '|' << itoa(item->CR); + ss << '|' << itoa(item->DR); + ss << '|' << itoa(item->PR); + ss << '|' << itoa(item->MR); + ss << '|' << itoa(item->FR); - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%s|%i|%i|%i|%i", - item->RecLevel, - item->RecSkill, - item->ElemDmgType, - item->ElemDmgAmt, - item->Range, - item->Damage, - item->Color, - item->Classes, - item->Races, - "0", // unknown - item->MaxCharges, - item->ItemType, - item->Material, - item->SellRate - ) - ); + ss << '|' << itoa(item->AStr); + ss << '|' << itoa(item->ASta); + ss << '|' << itoa(item->AAgi); + ss << '|' << itoa(item->ADex); + ss << '|' << itoa(item->ACha); + ss << '|' << itoa(item->AInt); + ss << '|' << itoa(item->AWis); - serialization.append( - StringFormat( - "|%s|%i|%s|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i", - "0", // unknown - item->CastTime_, - "0", // unknown - item->ProcRate, - item->CombatEffects, - item->Shielding, - item->StunResist, - item->StrikeThrough, - item->ExtraDmgSkill, - item->ExtraDmgAmt, - item->SpellShield, - item->Avoidance, - item->Accuracy, - item->CharmFileID - ) - ); + ss << '|' << itoa(item->HP); + ss << '|' << itoa(item->Mana); + ss << '|' << itoa(item->AC); + ss << '|' << itoa(item->Deity); - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%i|%i|%i|%i|%s", - item->FactionMod1, - item->FactionMod2, - item->FactionMod3, - item->FactionMod4, - item->FactionAmt1, - item->FactionAmt2, - item->FactionAmt3, - item->FactionAmt4, - item->CharmFile - ) - ); + ss << '|' << itoa(item->SkillModValue); + ss << '|' << itoa(item->SkillModMax); + ss << '|' << itoa(item->SkillModType); - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i", - item->AugType, - item->AugSlotType[0], - item->AugSlotVisible[0], - item->AugSlotType[1], - item->AugSlotVisible[1], - item->AugSlotType[2], - item->AugSlotVisible[2], - item->AugSlotType[3], - item->AugSlotVisible[3], - item->AugSlotType[4], - item->AugSlotVisible[4] - ) - ); + ss << '|' << itoa(item->BaneDmgRace); + ss << '|' << itoa(item->BaneDmgAmt); + ss << '|' << itoa(item->BaneDmgBody); - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%s|%i|%i|%i|%i|%i|%i", - item->LDoNTheme, - item->LDoNPrice, - item->LDoNSold, - item->BagType, - item->BagSlots, - item->BagSize, - item->BagWR, - item->Book, - item->BookType, - item->Filename, - item->BaneDmgRaceAmt, - item->AugRestrict, - item->LoreGroup, - item->PendingLoreFlag, - item->ArtifactFlag, - item->SummonedFlag - ) - ); + ss << '|' << itoa(item->Magic); + ss << '|' << itoa(item->CastTime_); + ss << '|' << itoa(item->ReqLevel); + ss << '|' << itoa(item->BardType); + ss << '|' << itoa(item->BardValue); + ss << '|' << itoa(item->Light); + ss << '|' << itoa(item->Delay); - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i", - item->Favor, - item->FVNoDrop, - item->Endur, - item->DotShielding, - item->Attack, - item->Regen, - item->ManaRegen, - item->EnduranceRegen, - item->Haste, - item->DamageShield, - item->RecastDelay, - item->RecastType, - item->GuildFavor, - item->AugDistiller - ) - ); + ss << '|' << itoa(item->RecLevel); + ss << '|' << itoa(item->RecSkill); - serialization.append( - StringFormat( - "|%s|%s|%i|%i|%s|%i|%i|%i|%i|%i|%i", - "0", // unknown - "0", // unknown - item->Attuneable, - item->NoPet, - "0", // unknown - item->PointType, - item->PotionBelt, - item->PotionBeltSlots, - item->StackSize, - item->NoTransfer, - item->Stackable - ) - ); + ss << '|' << itoa(item->ElemDmgType); + ss << '|' << itoa(item->ElemDmgAmt); - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%s", - item->Click.Effect, - item->Click.Type, - item->Click.Level2, - item->Click.Level, - "0" // Click name - ) - ); + ss << '|' << itoa(item->Range); + ss << '|' << itoa(item->Damage); - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%s", - item->Proc.Effect, - item->Proc.Type, - item->Proc.Level2, - item->Proc.Level, - "0" // Proc name - ) - ); + ss << '|' << itoa(item->Color); + ss << '|' << itoa(item->Classes); + ss << '|' << itoa(item->Races); + ss << '|' << "0"; - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%s", - item->Worn.Effect, - item->Worn.Type, - item->Worn.Level2, - item->Worn.Level, - "0" // Worn name - ) - ); + ss << '|' << itoa(item->MaxCharges); + ss << '|' << itoa(item->ItemType); + ss << '|' << itoa(item->Material); + ss << '|' << StringFormat("%f", item->SellRate); - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%s", - item->Focus.Effect, - item->Focus.Type, - item->Focus.Level2, - item->Focus.Level, - "0" // Focus name - ) - ); + ss << '|' << "0"; + ss << '|' << itoa(item->CastTime_); + ss << '|' << "0"; - serialization.append( - StringFormat( - "|%i|%i|%i|%i|%s", - item->Scroll.Effect, - item->Scroll.Type, - item->Scroll.Level2, - item->Scroll.Level, - "0" // Scroll name - ) - ); + ss << '|' << itoa(item->ProcRate); + ss << '|' << itoa(item->CombatEffects); + ss << '|' << itoa(item->Shielding); + ss << '|' << itoa(item->StunResist); + ss << '|' << itoa(item->StrikeThrough); + ss << '|' << itoa(item->ExtraDmgSkill); + ss << '|' << itoa(item->ExtraDmgAmt); + ss << '|' << itoa(item->SpellShield); + ss << '|' << itoa(item->Avoidance); + ss << '|' << itoa(item->Accuracy); - serialization.append(StringFormat("%.*s\"", depth, protection)); // Quotes (and protection, if needed) around static data + ss << '|' << itoa(item->CharmFileID); + ss << '|' << itoa(item->FactionMod1); + ss << '|' << itoa(item->FactionMod2); + ss << '|' << itoa(item->FactionMod3); + ss << '|' << itoa(item->FactionMod4); + + ss << '|' << itoa(item->FactionAmt1); + ss << '|' << itoa(item->FactionAmt2); + ss << '|' << itoa(item->FactionAmt3); + ss << '|' << itoa(item->FactionAmt4); + + ss << '|' << item->CharmFile; + + ss << '|' << itoa(item->AugType); + + ss << '|' << itoa(item->AugSlotType[0]); + ss << '|' << itoa(item->AugSlotVisible[0]); + ss << '|' << itoa(item->AugSlotType[1]); + ss << '|' << itoa(item->AugSlotVisible[1]); + ss << '|' << itoa(item->AugSlotType[2]); + ss << '|' << itoa(item->AugSlotVisible[2]); + ss << '|' << itoa(item->AugSlotType[3]); + ss << '|' << itoa(item->AugSlotVisible[3]); + ss << '|' << itoa(item->AugSlotType[4]); + ss << '|' << itoa(item->AugSlotVisible[4]); + + ss << '|' << itoa(item->LDoNTheme); + ss << '|' << itoa(item->LDoNPrice); + ss << '|' << itoa(item->LDoNSold); + + ss << '|' << itoa(item->BagType); + ss << '|' << itoa(item->BagSlots); + ss << '|' << itoa(item->BagSize); + ss << '|' << itoa(item->BagWR); + + ss << '|' << itoa(item->Book); + ss << '|' << itoa(item->BookType); + + ss << '|' << item->Filename; + + ss << '|' << itoa(item->BaneDmgRaceAmt); + ss << '|' << itoa(item->AugRestrict); + ss << '|' << itoa(item->LoreGroup); + ss << '|' << itoa(item->PendingLoreFlag); + ss << '|' << itoa(item->ArtifactFlag); + ss << '|' << itoa(item->SummonedFlag); + + ss << '|' << itoa(item->Favor); + ss << '|' << itoa(item->FVNoDrop); + ss << '|' << itoa(item->Endur); + ss << '|' << itoa(item->DotShielding); + ss << '|' << itoa(item->Attack); + ss << '|' << itoa(item->Regen); + ss << '|' << itoa(item->ManaRegen); + ss << '|' << itoa(item->EnduranceRegen); + ss << '|' << itoa(item->Haste); + ss << '|' << itoa(item->DamageShield); + ss << '|' << itoa(item->RecastDelay); + ss << '|' << itoa(item->RecastType); + ss << '|' << itoa(item->GuildFavor); + + ss << '|' << itoa(item->AugDistiller); + + ss << '|' << "0"; // unknown + ss << '|' << "0"; // unknown + ss << '|' << itoa(item->Attuneable); + ss << '|' << itoa(item->NoPet); + ss << '|' << "0"; // unknown + ss << '|' << itoa(item->PointType); + + ss << '|' << itoa(item->PotionBelt); + ss << '|' << itoa(item->PotionBeltSlots); + ss << '|' << itoa(item->StackSize); + ss << '|' << itoa(item->NoTransfer); + ss << '|' << itoa(item->Stackable); + + ss << '|' << itoa(item->Click.Effect); + ss << '|' << itoa(item->Click.Type); + ss << '|' << itoa(item->Click.Level2); + ss << '|' << itoa(item->Click.Level); + ss << '|' << "0"; // Click name + + ss << '|' << itoa(item->Proc.Effect); + ss << '|' << itoa(item->Proc.Type); + ss << '|' << itoa(item->Proc.Level2); + ss << '|' << itoa(item->Proc.Level); + ss << '|' << "0"; // Proc name + + ss << '|' << itoa(item->Worn.Effect); + ss << '|' << itoa(item->Worn.Type); + ss << '|' << itoa(item->Worn.Level2); + ss << '|' << itoa(item->Worn.Level); + ss << '|' << "0"; // Worn name + + ss << '|' << itoa(item->Focus.Effect); + ss << '|' << itoa(item->Focus.Type); + ss << '|' << itoa(item->Focus.Level2); + ss << '|' << itoa(item->Focus.Level); + ss << '|' << "0"; // Focus name + + ss << '|' << itoa(item->Scroll.Effect); + ss << '|' << itoa(item->Scroll.Type); + ss << '|' << itoa(item->Scroll.Level2); + ss << '|' << itoa(item->Scroll.Level); + ss << '|' << "0"; // Scroll name + + ss << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data + + // Sub data for (int index = SUB_INDEX_BEGIN; index < consts::ITEM_CONTAINER_SIZE; ++index) { - ItemInst *sub = inst->GetItem(index); - if (!sub) { - serialization.push_back('|'); // Sub items (empty) - } - else { - std::string sub_item = SerializeItem(sub, 0, (depth + 1)); - serialization.append(StringFormat("|%s", sub_item.c_str())); // Sub items - } + ss << '|'; + + ItemInst* sub = inst->GetItem(index); + if (!sub) + continue; + + SerializeItem(ss, sub, 0, (depth + 1)); } - serialization.append(StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : ""))); // For trailing quotes (and protection) if a subitem; + ss << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For trailing quotes (and protection) if a subitem; - return serialization; + if (!depth) + ss.write("\0", 1); } static inline int16 ServerToTitaniumSlot(uint32 serverSlot) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 28ff1d541..f864172bd 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -22,7 +22,7 @@ namespace UF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToUFSlot(uint32 serverSlot); @@ -473,27 +473,23 @@ namespace UF ENCODE(OP_CharInventory) { //consume the packet - EQApplicationPacket *in = *p; - + EQApplicationPacket* in = *p; *p = nullptr; - if (in->size == 0) { - + if (!in->size) { in->size = 4; in->pBuffer = new uchar[in->size]; - *((uint32 *)in->pBuffer) = 0; + memset(in->pBuffer, 0, in->size); dest->FastQueuePacket(&in, ack_req); return; } //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - - int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); - - if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + uchar* __emu_buffer = in->pBuffer; + int item_count = in->size / sizeof(InternalSerializedItem_Struct); + if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); @@ -501,39 +497,28 @@ namespace UF return; } - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - in->pBuffer = new uchar[4]; - *(uint32 *)in->pBuffer = ItemCount; - in->size = 4; + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); - for (int r = 0; r < ItemCount; r++, eq++) { + ss.write((const char*)&item_count, sizeof(uint32)); - uint32 Length = 0; - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); + for (int index = 0; index < item_count; ++index, ++eq) { + SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ss.tellp() == last_pos) + Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - if (Serialized) { - - uchar *OldBuffer = in->pBuffer; - in->pBuffer = new uchar[in->size + Length]; - memcpy(in->pBuffer, OldBuffer, in->size); - - safe_delete_array(OldBuffer); - - memcpy(in->pBuffer + in->size, Serialized, Length); - in->size += Length; - - safe_delete_array(Serialized); - } - else { - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } + last_pos = ss.tellp(); } - delete[] __emu_buffer; + std::string serialized = ss.str(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); - //Log.Hex(Logs::Netcode, in->pBuffer, in->size); + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); + + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); } @@ -1259,29 +1244,37 @@ namespace UF ENCODE(OP_ItemPacket) { //consume the packet - EQApplicationPacket *in = *p; + EQApplicationPacket* in = *p; *p = nullptr; - unsigned char *__emu_buffer = in->pBuffer; - ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer; - InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem); + //store away the emu struct + uchar* __emu_buffer = in->pBuffer; + //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; + //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - uint32 length; - char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0); + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); - if (!serialized) { + ss.write((const char*)__emu_buffer, 4); + + SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ss.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - in->size = length + 4; - in->pBuffer = new unsigned char[in->size]; - ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer; - new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(new_item_pkt->SerializedItem, serialized, length); + + std::string serialized = ss.str(); + + in->size = serialized.size(); + in->pBuffer = new uchar[in->size]; + //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; + //new_item_pkt->PacketType = old_item_pkt->PacketType; + memcpy(in->pBuffer, serialized.c_str(), serialized.size()); delete[] __emu_buffer; - safe_delete_array(serialized); + dest->FastQueuePacket(&in, ack_req); } @@ -3822,43 +3815,36 @@ namespace UF return NextItemInstSerialNumber; } - char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth) + void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - uint8 null_term = 0; - bool stackable = inst->IsStackable(); - uint32 merchant_slot = inst->GetMerchantSlot(); - uint32 charges = inst->GetCharges(); - if (!stackable && charges > 254) - charges = 0xFFFFFFFF; - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - const Item_Struct *item = inst->GetUnscaledItem(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); + UF::structs::ItemSerializationHeader hdr; - hdr.stacksize = stackable ? charges : 1; + + hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1); hdr.unknown004 = 0; int32 slot_id = ServerToUFSlot(slot_id_in); - hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot; + hdr.slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id); hdr.price = inst->GetPrice(); - hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); - hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; - hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot; + hdr.merchant_slot = (inst->GetMerchantSlot() ? inst->GetMerchantCount() : 1); + hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0); + hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber()); hdr.unknown028 = 0; hdr.last_cast_time = inst->GetRecastTimestamp(); - hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges); - hdr.inst_nodrop = inst->IsAttuned() ? 1 : 0; + hdr.charges = (inst->IsStackable() ? (item->MaxCharges ? 1 : 0) : ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges())); + hdr.inst_nodrop = (inst->IsAttuned() ? 1 : 0); hdr.unknown044 = 0; hdr.unknown048 = 0; hdr.unknown052 = 0; hdr.isEvolving = item->EvolvingItem; + ss.write((const char*)&hdr, sizeof(UF::structs::ItemSerializationHeader)); if (item->EvolvingItem > 0) { UF::structs::EvolvingItem evotop; + evotop.unknown001 = 0; evotop.unknown002 = 0; evotop.unknown003 = 0; @@ -3867,70 +3853,55 @@ namespace UF evotop.progress = 0; evotop.Activated = 1; evotop.evomaxlevel = item->EvolvingMax; + ss.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem)); } + //ORNAMENT IDFILE / ICON - + int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); uint16 ornaIcon = 0; if (inst->GetOrnamentationAug(ornamentationAugtype)) { const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); - ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); ornaIcon = aug_weap->Icon; + + ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); } else if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { - char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); - ss.write(tmp, strlen(tmp)); - ss.write((const char*)&null_term, sizeof(uint8)); ornaIcon = inst->GetOrnamentationIcon(); + char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); + + ss.write(tmp, strlen(tmp)); } - else { - ss.write((const char*)&null_term, sizeof(uint8)); //no idfile - } + ss.write("\0", 1); UF::structs::ItemSerializationHeaderFinish hdrf; + hdrf.ornamentIcon = ornaIcon; hdrf.unknown060 = 0; //This is Always 0.. or it breaks shit.. hdrf.unknown061 = 0; //possibly ornament / special ornament hdrf.isCopied = 0; //Flag for item to be 'Copied' hdrf.ItemClass = item->ItemClass; + ss.write((const char*)&hdrf, sizeof(UF::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) - { ss.write(item->Name, strlen(item->Name)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); if (strlen(item->Lore) > 0) - { ss.write(item->Lore, strlen(item->Lore)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); if (strlen(item->IDFile) > 0) - { ss.write(item->IDFile, strlen(item->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); UF::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(UF::structs::ItemBodyStruct)); ibs.id = item->ID; // weight is uint8 in the struct, and some weights exceed that, so capping at 255. - ibs.weight = (item->Weight > 255) ? 255 : item->Weight; + ibs.weight = ((item->Weight > 255) ? 255 : item->Weight); ibs.norent = item->NoRent; ibs.nodrop = item->NoDrop; ibs.attune = item->Attuneable; @@ -4016,14 +3987,8 @@ namespace UF //charm text if (strlen(item->CharmFile) > 0) - { ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); UF::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(UF::structs::ItemSecondaryBodyStruct)); @@ -4031,11 +3996,10 @@ namespace UF isbs.augtype = item->AugType; isbs.augrestrict = item->AugRestrict; - for (int x = 0; x < consts::ITEM_COMMON_SIZE; x++) - { - isbs.augslots[x].type = item->AugSlotType[x]; - isbs.augslots[x].visible = item->AugSlotVisible[x]; - isbs.augslots[x].unknown = item->AugSlotUnk2[x]; + for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) { + isbs.augslots[index].type = item->AugSlotType[index]; + isbs.augslots[index].visible = item->AugSlotVisible[index]; + isbs.augslots[index].unknown = item->AugSlotUnk2[index]; } isbs.ldonpoint_type = item->PointType; @@ -4055,14 +4019,8 @@ namespace UF ss.write((const char*)&isbs, sizeof(UF::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - { ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); UF::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(UF::structs::ItemTertiaryBodyStruct)); @@ -4082,7 +4040,7 @@ namespace UF itbs.potion_belt_enabled = item->PotionBelt; itbs.potion_belt_slots = item->PotionBeltSlots; - itbs.stacksize = stackable ? item->StackSize : 0; + itbs.stacksize = (inst->IsStackable() ? item->StackSize : 0); itbs.no_transfer = item->NoTransfer; itbs.expendablearrow = item->ExpendableArrow; @@ -4106,14 +4064,8 @@ namespace UF ss.write((const char*)&ices, sizeof(UF::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - { ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 @@ -4129,14 +4081,8 @@ namespace UF ss.write((const char*)&ipes, sizeof(UF::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - { ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 @@ -4151,14 +4097,8 @@ namespace UF ss.write((const char*)&iwes, sizeof(UF::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - { ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -4173,14 +4113,8 @@ namespace UF ss.write((const char*)&ifes, sizeof(UF::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - { ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -4195,14 +4129,8 @@ namespace UF ss.write((const char*)&ises, sizeof(UF::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - { ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 @@ -4225,7 +4153,7 @@ namespace UF ss.write((const char*)&null_term, sizeof(uint8)); } else */ - ss.write((const char*)&null_term, sizeof(uint8)); + ss.write("\0", 1); ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects @@ -4255,67 +4183,44 @@ namespace UF iqbs.HeroicSVCorrup = item->HeroicSVCorrup; iqbs.HealAmt = item->HealAmt; iqbs.SpellDmg = item->SpellDmg; - iqbs.clairvoyance = item->Clairvoyance; - - iqbs.subitem_count = 0; - - char *SubSerializations[10]; // - - uint32 SubLengths[10]; - - for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) { - - SubSerializations[x] = nullptr; - - const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); - - if (subitem) { - - int SubSlotNumber; - - iqbs.subitem_count++; - - if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor? - //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) - //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) - //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x); - else - SubSlotNumber = slot_id_in; // ??????? - - /* - // TEST CODE: - SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); - */ - - SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); - } - } - + iqbs.Clairvoyance = item->Clairvoyance; + ss.write((const char*)&iqbs, sizeof(UF::structs::ItemQuaternaryBodyStruct)); - for (int x = 0; x < 10; ++x) { + std::stringstream::pos_type count_pos = ss.tellp(); + uint32 subitem_count = 0; - if (SubSerializations[x]) { + ss.write((const char*)&subitem_count, sizeof(uint32)); - ss.write((const char*)&x, sizeof(uint32)); + for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { + ItemInst* sub = inst->GetItem(index); + if (!sub) + continue; - ss.write(SubSerializations[x], SubLengths[x]); + int SubSlotNumber = INVALID_INDEX; + if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) + SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1); + else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index); + else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); + else + SubSlotNumber = slot_id_in; - safe_delete_array(SubSerializations[x]); - } + ss.write((const char*)&index, sizeof(uint32)); + + SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + ++subitem_count; } - char* item_serial = new char[ss.tellp()]; - memset(item_serial, 0, ss.tellp()); - memcpy(item_serial, ss.str().c_str(), ss.tellp()); + if (subitem_count) { + std::stringstream::pos_type cur_pos = ss.tellp(); + ss.seekp(count_pos); - *length = ss.tellp(); - return item_serial; + ss.write((const char*)&subitem_count, sizeof(uint32)); + + ss.seekp(cur_pos); + } } static inline uint32 ServerToUFSlot(uint32 serverSlot) diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 75e590abd..f6a2c5553 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -4281,14 +4281,13 @@ struct ItemQuaternaryBodyStruct int32 HeroicSVCorrup; int32 HealAmt; int32 SpellDmg; - int32 clairvoyance; + int32 Clairvoyance; uint8 unknown18; //Power Source Capacity or evolve filename? uint32 evolve_string; // Some String, but being evolution related is just a guess uint8 unknown19; uint32 unknown20; // Bard Stuff? uint32 unknown21; uint32 unknown22; - uint32 subitem_count; }; struct AugmentInfo_Struct From 3e0574630b9efcf8e68993f3d1543adb99774590 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 10 May 2016 21:27:40 -0400 Subject: [PATCH 082/693] Reworked server 'BulkSendInventoryItems()' to use single buffer methodology --- changelog.txt | 1 + zone/client_process.cpp | 161 +++++++++++++--------------------------- 2 files changed, 51 insertions(+), 111 deletions(-) diff --git a/changelog.txt b/changelog.txt index 402ef67de..f37bad44d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 05/10/2016 == Uleat: Converted client translators' 'SerializeItem()' to recursive, single buffer methodology. Titanium SerializeItem() now adds a null term between parent items instead of the invoking function +Uleat: Converted server 'BulkSendInventoryItems()' to use single buffer methodology == 05/08/2016 == Uleat: Re-coded Titanium client translator 'SerializeItem()' to use coded property assignments over file enumerated ones diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 942139b26..0751ac0a9 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -733,16 +733,11 @@ void Client::OnDisconnect(bool hard_disconnect) { } // Sends the client complete inventory used in character login - -// DO WE STILL NEED THE 'ITEMCOMBINED' CONDITIONAL CODE? - -//#ifdef ITEMCOMBINED -void Client::BulkSendInventoryItems() { - int16 slot_id = 0; - +void Client::BulkSendInventoryItems() +{ // LINKDEAD TRADE ITEMS // Move trade slot items back into normal inventory..need them there now for the proceeding validity checks - for (slot_id = EQEmu::legacy::TRADE_BEGIN; slot_id <= EQEmu::legacy::TRADE_END; slot_id++) { + for (int16 slot_id = EQEmu::legacy::TRADE_BEGIN; slot_id <= EQEmu::legacy::TRADE_END; slot_id++) { ItemInst* inst = m_inv.PopItem(slot_id); if(inst) { bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; @@ -764,128 +759,72 @@ void Client::BulkSendInventoryItems() { RemoveDuplicateLore(false); MoveSlotNotAllowed(false); - // The previous three method calls took care of moving/removing expired/illegal item placements + std::stringstream ss(std::stringstream::in | std::stringstream::out); + std::stringstream::pos_type last_pos = ss.tellp(); - //TODO: this function is just retarded... it re-allocates the buffer for every - //new item. It should be changed to loop through once, gather the - //lengths, and item packet pointers into an array (fixed length), and - //then loop again to build the packet. - //EQApplicationPacket *packets[50]; - //unsigned long buflen = 0; - //unsigned long pos = 0; - //memset(packets, 0, sizeof(packets)); - //foreach item in the invendor sections - // packets[pos++] = ReturnItemPacket(...) - // buflen += temp->size - //... - //allocat the buffer - //for r from 0 to pos - // put pos[r]->pBuffer into the buffer - //for r from 0 to pos - // safe_delete(pos[r]); - - uint32 size = 0; - uint16 i = 0; - std::map ser_items; - std::map::iterator itr; - - //Inventory items - for (slot_id = SLOT_BEGIN; slot_id < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; slot_id++) { + // Possessions items + for (int16 slot_id = SLOT_BEGIN; slot_id < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; slot_id++) { const ItemInst* inst = m_inv[slot_id]; - if(inst) { - std::string packet = inst->Serialize(slot_id); - ser_items[i++] = packet; - size += packet.length(); - } + if (!inst) + continue; + + ss << inst->Serialize(slot_id); + + if (ss.tellp() == last_pos) + Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); + + last_pos = ss.tellp(); } - // Power Source + // PowerSource item if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { const ItemInst* inst = m_inv[EQEmu::legacy::SlotPowerSource]; - if(inst) { - std::string packet = inst->Serialize(EQEmu::legacy::SlotPowerSource); - ser_items[i++] = packet; - size += packet.length(); + if (inst) { + ss << inst->Serialize(EQEmu::legacy::SlotPowerSource); + + if (ss.tellp() == last_pos) + Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", EQEmu::legacy::SlotPowerSource); + + last_pos = ss.tellp(); } } // Bank items - for (slot_id = EQEmu::legacy::BANK_BEGIN; slot_id <= EQEmu::legacy::BANK_END; slot_id++) { + for (int16 slot_id = EQEmu::legacy::BANK_BEGIN; slot_id <= EQEmu::legacy::BANK_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; - if(inst) { - std::string packet = inst->Serialize(slot_id); - ser_items[i++] = packet; - size += packet.length(); - } + if (!inst) + continue; + + ss << inst->Serialize(slot_id); + + if (ss.tellp() == last_pos) + Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); + + last_pos = ss.tellp(); } - // Shared Bank items - for (slot_id = EQEmu::legacy::SHARED_BANK_BEGIN; slot_id <= EQEmu::legacy::SHARED_BANK_END; slot_id++) { + // SharedBank items + for (int16 slot_id = EQEmu::legacy::SHARED_BANK_BEGIN; slot_id <= EQEmu::legacy::SHARED_BANK_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; - if(inst) { - std::string packet = inst->Serialize(slot_id); - ser_items[i++] = packet; - size += packet.length(); - } + if (!inst) + continue; + + ss << inst->Serialize(slot_id); + + if (ss.tellp() == last_pos) + Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); + + last_pos = ss.tellp(); } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CharInventory, size); - uchar* ptr = outapp->pBuffer; - for(itr = ser_items.begin(); itr != ser_items.end(); ++itr){ - int length = itr->second.length(); - if(length > 5) { - memcpy(ptr, itr->second.c_str(), length); - ptr += length; - } - } + std::string serialized = ss.str(); + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_CharInventory, serialized.size()); + memcpy(outapp->pBuffer, serialized.c_str(), serialized.size()); + QueuePacket(outapp); safe_delete(outapp); } -/*#else -void Client::BulkSendInventoryItems() -{ - // Search all inventory buckets for items - bool deletenorent=database.NoRentExpired(GetName()); - // Worn items and Inventory items - int16 slot_id = 0; - if(deletenorent){//client was offline for more than 30 minutes, delete no rent items - RemoveNoRent(); - } - for (slot_id=EQEmu::constants::POSSESSIONS_BEGIN; slot_id<=EQEmu::constants::POSSESSIONS_END; slot_id++) { - const ItemInst* inst = m_inv[slot_id]; - if (inst){ - SendItemPacket(slot_id, inst, ItemPacketCharInventory); - } - } - // Bank items - for (slot_id=EQEmu::constants::BANK_BEGIN; slot_id<=EQEmu::constants::BANK_END; slot_id++) { // 2015... - const ItemInst* inst = m_inv[slot_id]; - if (inst){ - SendItemPacket(slot_id, inst, ItemPacketCharInventory); - } - } - - // Shared Bank items - for (slot_id=EQEmu::constants::SHARED_BANK_BEGIN; slot_id<=EQEmu::constants::SHARED_BANK_END; slot_id++) { - const ItemInst* inst = m_inv[slot_id]; - if (inst){ - SendItemPacket(slot_id, inst, ItemPacketCharInventory); - } - } - - // LINKDEAD TRADE ITEMS - // If player went LD during a trade, they have items in the trade inventory - // slots. These items are now being put into their inventory (then queue up on cursor) - for (int16 trade_slot_id=EQEmu::constants::TRADE_BEGIN; trade_slot_id<=EQEmu::constants::TRADE_END; trade_slot_id++) { - const ItemInst* inst = m_inv[slot_id]; - if (inst) { - int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size); - DeleteItemInInventory(trade_slot_id, 0, false); - PutItemInInventory(free_slot_id, *inst, true); - } - } -} -#endif*/ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { const Item_Struct* handyitem = nullptr; From 915f22d564ea5de138f564d93ac3ebf58b1734b0 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 11 May 2016 00:30:04 -0400 Subject: [PATCH 083/693] Added 'ItemInst::Serialize()' overload to make use of std::stringstream implementation --- changelog.txt | 1 + common/item.h | 4 +++- zone/client_process.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/changelog.txt b/changelog.txt index f37bad44d..971a49cb9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 05/10/2016 == Uleat: Converted client translators' 'SerializeItem()' to recursive, single buffer methodology. Titanium SerializeItem() now adds a null term between parent items instead of the invoking function Uleat: Converted server 'BulkSendInventoryItems()' to use single buffer methodology +Uleat: Added 'ItemInst::Serialize()' overload to make use of the above single buffer methodology == 05/08/2016 == Uleat: Re-coded Titanium client translator 'SerializeItem()' to use coded property assignments over file enumerated ones diff --git a/common/item.h b/common/item.h index 54bd519fc..22da54183 100644 --- a/common/item.h +++ b/common/item.h @@ -411,7 +411,9 @@ public: int8 GetMaxEvolveLvl() const; uint32 GetKillsNeeded(uint8 currentlevel); - std::string Serialize(int16 slot_id) const { InternalSerializedItem_Struct s; s.slot_id=slot_id; s.inst=(const void *)this; std::string ser; ser.assign((char *)&s,sizeof(InternalSerializedItem_Struct)); return ser; } + std::string Serialize(int16 slot_id) const { InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(InternalSerializedItem_Struct)); return ser; } + void Serialize(std::stringstream& ss, int16 slot_id) const { InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ss.write((const char*)&isi, sizeof(isi)); } + inline int32 GetSerialNumber() const { return m_SerialNumber; } inline void SetSerialNumber(int32 id) { m_SerialNumber = id; } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 0751ac0a9..8c58049ab 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -768,7 +768,7 @@ void Client::BulkSendInventoryItems() if (!inst) continue; - ss << inst->Serialize(slot_id); + inst->Serialize(ss, slot_id); if (ss.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); @@ -780,7 +780,7 @@ void Client::BulkSendInventoryItems() if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { const ItemInst* inst = m_inv[EQEmu::legacy::SlotPowerSource]; if (inst) { - ss << inst->Serialize(EQEmu::legacy::SlotPowerSource); + inst->Serialize(ss, EQEmu::legacy::SlotPowerSource); if (ss.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", EQEmu::legacy::SlotPowerSource); @@ -795,7 +795,7 @@ void Client::BulkSendInventoryItems() if (!inst) continue; - ss << inst->Serialize(slot_id); + inst->Serialize(ss, slot_id); if (ss.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); @@ -809,7 +809,7 @@ void Client::BulkSendInventoryItems() if (!inst) continue; - ss << inst->Serialize(slot_id); + inst->Serialize(ss, slot_id); if (ss.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); From cb39a35f3f789423d4dc7dba8b9736d09174d1a6 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 11 May 2016 19:11:25 -0400 Subject: [PATCH 084/693] Fix for stringstream failure --- common/item.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/item.h b/common/item.h index 22da54183..11e1ad151 100644 --- a/common/item.h +++ b/common/item.h @@ -33,6 +33,7 @@ class EvolveInfo; // Stores information about an evolving item family #include #include +#include namespace ItemField From edc42bf5b694b84b8d6e0295a76aaf17c7f40d09 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 13 May 2016 21:33:03 -0400 Subject: [PATCH 085/693] Add small chrono timer object This is just so if someone wants a quick way to measure how long something takes for benchmarking purposes they don't have to reinvent anything. See examples in comments --- common/timer.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/common/timer.h b/common/timer.h index 4b2719dc6..f06f5bbe4 100644 --- a/common/timer.h +++ b/common/timer.h @@ -19,6 +19,7 @@ #define TIMER_H #include "types.h" +#include // Disgrace: for windows compile #ifdef _WINDOWS @@ -65,4 +66,28 @@ private: bool pUseAcurateTiming; }; +/* Wrapper around chrono to make adding simple time based benching easy + * ex: + * void foo() { + * ... + * BenchTimer timer; + * ... (expensive work here) + * auto dur = timer.elapsed(); + * std::cout << "foo() took " << dur << seconds" << std::endl; + * ... + * } + * */ + +struct BenchTimer +{ + typedef std::chrono::high_resolution_clock clock; + + BenchTimer() : start_time(clock::now()) {} + void reset() { start_time = clock::now(); } + // this is seconds + double elapsed() { return std::chrono::duration (clock::now() - start_time).count(); } +private: + std::chrono::time_point start_time; +}; + #endif From d2888e6cca5aa66d87f38f396b252f86c63f66fd Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 16 May 2016 23:22:23 -0400 Subject: [PATCH 086/693] Fix mismatched new/delete --- ucs/database.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ucs/database.cpp b/ucs/database.cpp index 8cd1b73f5..c1721ffb9 100644 --- a/ucs/database.cpp +++ b/ucs/database.cpp @@ -200,19 +200,21 @@ bool Database::VerifyMailKey(std::string characterName, int IPAddress, std::stri return !strcmp(row[0], combinedKey); } -int Database::FindCharacter(const char *characterName) { - +int Database::FindCharacter(const char *characterName) +{ char *safeCharName = RemoveApostrophes(characterName); - std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name`='%s' LIMIT 1", safeCharName); - auto results = QueryDatabase(query); + std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name`='%s' LIMIT 1", safeCharName); + auto results = QueryDatabase(query); if (!results.Success()) { - safe_delete(safeCharName); + safe_delete_array(safeCharName); return -1; } - safe_delete(safeCharName); + + safe_delete_array(safeCharName); if (results.RowCount() != 1) { - Log.Out(Logs::Detail, Logs::UCS_Server, "Bad result from FindCharacter query for character %s", characterName); + Log.Out(Logs::Detail, Logs::UCS_Server, "Bad result from FindCharacter query for character %s", + characterName); return -1; } @@ -618,4 +620,4 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings){ Log.file_logs_enabled = true; } } -} \ No newline at end of file +} From 52bee3e8a0bad1a0f8a0fa565f35c7b02ab4ef44 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 16 May 2016 23:22:42 -0400 Subject: [PATCH 087/693] Rework Clientlist::Process to not skip clients ... --- ucs/clientlist.cpp | 173 +++++++++++++++++++-------------------------- 1 file changed, 72 insertions(+), 101 deletions(-) diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index bd79822ab..f39dfa590 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -572,46 +572,37 @@ void Clientlist::CheckForStaleConnections(Client *c) { } } -void Clientlist::Process() { +void Clientlist::Process() +{ std::shared_ptr eqs; - while((eqs = chatsf->Pop())) { - + while ((eqs = chatsf->Pop())) { struct in_addr in; - in.s_addr = eqs->GetRemoteIP(); - Log.Out(Logs::Detail, Logs::UCS_Server, "New Client UDP connection from %s:%d", inet_ntoa(in), ntohs(eqs->GetRemotePort())); + Log.Out(Logs::Detail, Logs::UCS_Server, "New Client UDP connection from %s:%d", inet_ntoa(in), + ntohs(eqs->GetRemotePort())); eqs->SetOpcodeManager(&ChatOpMgr); auto c = new Client(eqs); - ClientChatConnections.push_back(c); } - std::list::iterator Iterator; - - for(Iterator = ClientChatConnections.begin(); Iterator != ClientChatConnections.end(); ++Iterator) { - - (*Iterator)->AccountUpdate(); - if((*Iterator)->ClientStream->CheckClosed()) { - + auto it = ClientChatConnections.begin(); + while (it != ClientChatConnections.end()) { + (*it)->AccountUpdate(); + if ((*it)->ClientStream->CheckClosed()) { struct in_addr in; - - in.s_addr = (*Iterator)->ClientStream->GetRemoteIP(); + in.s_addr = (*it)->ClientStream->GetRemoteIP(); Log.Out(Logs::Detail, Logs::UCS_Server, "Client connection from %s:%d closed.", inet_ntoa(in), - ntohs((*Iterator)->ClientStream->GetRemotePort())); + ntohs((*it)->ClientStream->GetRemotePort())); - safe_delete((*Iterator)); - - Iterator = ClientChatConnections.erase(Iterator); - - if(Iterator == ClientChatConnections.end()) - break; + safe_delete((*it)); + it = ClientChatConnections.erase(it); continue; } @@ -619,114 +610,94 @@ void Clientlist::Process() { bool KeyValid = true; - while( KeyValid && !(*Iterator)->GetForceDisconnect() && - (app = (EQApplicationPacket *)(*Iterator)->ClientStream->PopPacket())) { - - + while (KeyValid && !(*it)->GetForceDisconnect() && (app = (EQApplicationPacket *)(*it)->ClientStream->PopPacket())) { EmuOpcode opcode = app->GetOpcode(); - switch(opcode) { + switch (opcode) { + case OP_MailLogin: { + char *PacketBuffer = (char *)app->pBuffer; + char MailBox[64]; + char Key[64]; + char ConnectionTypeIndicator; - case OP_MailLogin: { + VARSTRUCT_DECODE_STRING(MailBox, PacketBuffer); - char *PacketBuffer = (char *)app->pBuffer; + if (strlen(PacketBuffer) != 9) { + Log.Out(Logs::Detail, Logs::UCS_Server, + "Mail key is the wrong size. Version of world incompatible with UCS."); + KeyValid = false; + break; + } + ConnectionTypeIndicator = VARSTRUCT_DECODE_TYPE(char, PacketBuffer); - char MailBox[64]; + (*it)->SetConnectionType(ConnectionTypeIndicator); - char Key[64]; + VARSTRUCT_DECODE_STRING(Key, PacketBuffer); - char ConnectionTypeIndicator; + std::string MailBoxString = MailBox, CharacterName; - VARSTRUCT_DECODE_STRING(MailBox, PacketBuffer); + // Strip off the SOE.EQ.. + // + std::string::size_type LastPeriod = MailBoxString.find_last_of("."); - if(strlen(PacketBuffer) != 9) - { - Log.Out(Logs::Detail, Logs::UCS_Server, "Mail key is the wrong size. Version of world incompatible with UCS."); - KeyValid = false; - break; - } - ConnectionTypeIndicator = VARSTRUCT_DECODE_TYPE(char, PacketBuffer); + if (LastPeriod == std::string::npos) + CharacterName = MailBoxString; + else + CharacterName = MailBoxString.substr(LastPeriod + 1); - (*Iterator)->SetConnectionType(ConnectionTypeIndicator); - - VARSTRUCT_DECODE_STRING(Key, PacketBuffer); - - std::string MailBoxString = MailBox, CharacterName; - - // Strip off the SOE.EQ.. - // - std::string::size_type LastPeriod = MailBoxString.find_last_of("."); - - if(LastPeriod == std::string::npos) - CharacterName = MailBoxString; - else - CharacterName = MailBoxString.substr(LastPeriod + 1); - - Log.Out(Logs::Detail, Logs::UCS_Server, "Received login for user %s with key %s", MailBox, Key); - - if(!database.VerifyMailKey(CharacterName, (*Iterator)->ClientStream->GetRemoteIP(), Key)) { - - Log.Out(Logs::Detail, Logs::UCS_Server, "Chat Key for %s does not match, closing connection.", MailBox); - - KeyValid = false; - - break; - } - - (*Iterator)->SetAccountID(database.FindAccount(CharacterName.c_str(), (*Iterator))); - - database.GetAccountStatus((*Iterator)); - - if((*Iterator)->GetConnectionType() == ConnectionTypeCombined) - (*Iterator)->SendFriends(); - - (*Iterator)->SendMailBoxes(); - - CheckForStaleConnections((*Iterator)); + Log.Out(Logs::Detail, Logs::UCS_Server, "Received login for user %s with key %s", + MailBox, Key); + if (!database.VerifyMailKey(CharacterName, (*it)->ClientStream->GetRemoteIP(), Key)) { + Log.Out(Logs::Detail, Logs::UCS_Server, + "Chat Key for %s does not match, closing connection.", MailBox); + KeyValid = false; break; } - case OP_Mail: { + (*it)->SetAccountID(database.FindAccount(CharacterName.c_str(), (*it))); - std::string CommandString = (const char*)app->pBuffer; + database.GetAccountStatus((*it)); - ProcessOPMailCommand((*Iterator), CommandString); + if ((*it)->GetConnectionType() == ConnectionTypeCombined) + (*it)->SendFriends(); - break; - } + (*it)->SendMailBoxes(); - default: { + CheckForStaleConnections((*it)); + break; + } - Log.Out(Logs::Detail, Logs::UCS_Server, "Unhandled chat opcode %8X", opcode); - break; - } + case OP_Mail: { + std::string CommandString = (const char *)app->pBuffer; + ProcessOPMailCommand((*it), CommandString); + break; + } + + default: { + Log.Out(Logs::Detail, Logs::UCS_Server, "Unhandled chat opcode %8X", opcode); + break; + } } safe_delete(app); - } - if(!KeyValid || (*Iterator)->GetForceDisconnect()) { - + if (!KeyValid || (*it)->GetForceDisconnect()) { struct in_addr in; + in.s_addr = (*it)->ClientStream->GetRemoteIP(); - in.s_addr = (*Iterator)->ClientStream->GetRemoteIP(); + Log.Out(Logs::Detail, Logs::UCS_Server, + "Force disconnecting client: %s:%d, KeyValid=%i, GetForceDisconnect()=%i", + inet_ntoa(in), ntohs((*it)->ClientStream->GetRemotePort()), KeyValid, + (*it)->GetForceDisconnect()); - Log.Out(Logs::Detail, Logs::UCS_Server, "Force disconnecting client: %s:%d, KeyValid=%i, GetForceDisconnect()=%i", - inet_ntoa(in), ntohs((*Iterator)->ClientStream->GetRemotePort()), - KeyValid, (*Iterator)->GetForceDisconnect()); + (*it)->ClientStream->Close(); - (*Iterator)->ClientStream->Close(); + safe_delete((*it)); - safe_delete((*Iterator)); - - Iterator = ClientChatConnections.erase(Iterator); - - if(Iterator == ClientChatConnections.end()) - break; + it = ClientChatConnections.erase(it); } - + ++it; } - } void Clientlist::ProcessOPMailCommand(Client *c, std::string CommandString) From 046dfe3e123d264c6c4afaae6b516f3098e5d7ad Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 16 May 2016 23:25:27 -0400 Subject: [PATCH 088/693] Add missing continue to Clientlist::Process --- ucs/clientlist.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index f39dfa590..0601abeb6 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -695,6 +695,7 @@ void Clientlist::Process() safe_delete((*it)); it = ClientChatConnections.erase(it); + continue; } ++it; } From 38af4843686594eeddd13458946e9f6b7dd34d07 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 16 May 2016 23:47:01 -0400 Subject: [PATCH 089/693] Fix mismatch new/delete --- world/clientlist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/clientlist.cpp b/world/clientlist.cpp index 84da0fb08..8da2b013c 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -749,7 +749,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S //zoneserver_list.SendPacket(pack2); // NO NO NO WHY WOULD YOU SEND IT TO EVERY ZONE SERVER?!? SendPacket(to,pack2); safe_delete(pack2); - safe_delete(output); + safe_delete_array(output); } catch(...){ Log.Out(Logs::Detail, Logs::World_Server,"Unknown error in world's SendWhoAll (probably mem error), ignoring..."); From 29da15f38c701e7f4c2315feef34837bf90faf18 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 17 May 2016 15:11:23 -0400 Subject: [PATCH 090/693] Rename CL to g_Clientlist --- ucs/clientlist.cpp | 10 +++++----- ucs/database.cpp | 4 ++-- ucs/ucs.cpp | 8 ++++---- ucs/worldserver.cpp | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index 0601abeb6..62fd79096 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -38,7 +38,7 @@ extern Database database; extern std::string WorldShortName; extern std::string GetMailPrefix(); extern ChatChannelList *ChannelList; -extern Clientlist *CL; +extern Clientlist *g_Clientlist; extern uint32 ChatMessagesSent; extern uint32 MailMessagesSent; @@ -1749,7 +1749,7 @@ void Client::ChannelInvite(std::string CommandString) { Log.Out(Logs::Detail, Logs::UCS_Server, "[%s] invites [%s] to channel [%s]", GetName().c_str(), Invitee.c_str(), ChannelName.c_str()); - Client *RequiredClient = CL->FindCharacter(Invitee); + Client *RequiredClient = g_Clientlist->FindCharacter(Invitee); if(!RequiredClient) { @@ -1877,7 +1877,7 @@ void Client::ChannelGrantModerator(std::string CommandString) { Log.Out(Logs::Detail, Logs::UCS_Server, "[%s] gives [%s] moderator rights to channel [%s]", GetName().c_str(), Moderator.c_str(), ChannelName.c_str()); - Client *RequiredClient = CL->FindCharacter(Moderator); + Client *RequiredClient = g_Clientlist->FindCharacter(Moderator); if(!RequiredClient && (database.FindCharacter(Moderator.c_str()) < 0)) { @@ -1958,7 +1958,7 @@ void Client::ChannelGrantVoice(std::string CommandString) { Log.Out(Logs::Detail, Logs::UCS_Server, "[%s] gives [%s] voice to channel [%s]", GetName().c_str(), Voicee.c_str(), ChannelName.c_str()); - Client *RequiredClient = CL->FindCharacter(Voicee); + Client *RequiredClient = g_Clientlist->FindCharacter(Voicee); if(!RequiredClient && (database.FindCharacter(Voicee.c_str()) < 0)) { @@ -2046,7 +2046,7 @@ void Client::ChannelKick(std::string CommandString) { Log.Out(Logs::Detail, Logs::UCS_Server, "[%s] kicks [%s] from channel [%s]", GetName().c_str(), Kickee.c_str(), ChannelName.c_str()); - Client *RequiredClient = CL->FindCharacter(Kickee); + Client *RequiredClient = g_Clientlist->FindCharacter(Kickee); if(!RequiredClient) { diff --git a/ucs/database.cpp b/ucs/database.cpp index c1721ffb9..dbd0af504 100644 --- a/ucs/database.cpp +++ b/ucs/database.cpp @@ -48,7 +48,7 @@ #include "../common/string_util.h" #include "chatchannel.h" -extern Clientlist *CL; +extern Clientlist *g_Clientlist; extern std::string GetMailPrefix(); extern ChatChannelList *ChannelList; extern uint32 MailMessagesSent; @@ -463,7 +463,7 @@ bool Database::SendMail(std::string recipient, std::string from, std::string sub Log.Out(Logs::Detail, Logs::UCS_Server, "MessageID %i generated, from %s, to %s", results.LastInsertedID(), from.c_str(), recipient.c_str()); - Client *client = CL->IsCharacterOnline(characterName); + Client *client = g_Clientlist->IsCharacterOnline(characterName); if(client) { std::string FQN = GetMailPrefix() + from; diff --git a/ucs/ucs.cpp b/ucs/ucs.cpp index b6beeb268..877ff0d0c 100644 --- a/ucs/ucs.cpp +++ b/ucs/ucs.cpp @@ -34,7 +34,7 @@ #include ChatChannelList *ChannelList; -Clientlist *CL; +Clientlist *g_Clientlist; EQEmuLogSys Log; TimeoutManager timeout_manager; Database database; @@ -124,7 +124,7 @@ int main() { exit(1); } - CL = new Clientlist(Config->ChatPort); + g_Clientlist = new Clientlist(Config->ChatPort); ChannelList = new ChatChannelList(); @@ -147,7 +147,7 @@ int main() { Timer::SetCurrentTime(); - CL->Process(); + g_Clientlist->Process(); if(ChannelListProcessTimer.Check()) ChannelList->Process(); @@ -165,7 +165,7 @@ int main() { ChannelList->RemoveAllChannels(); - CL->CloseAllConnections(); + g_Clientlist->CloseAllConnections(); Log.CloseFileLogs(); diff --git a/ucs/worldserver.cpp b/ucs/worldserver.cpp index 395d72e59..4e11c39b7 100644 --- a/ucs/worldserver.cpp +++ b/ucs/worldserver.cpp @@ -34,7 +34,7 @@ #include "../common/md5.h" extern WorldServer worldserver; -extern Clientlist *CL; +extern Clientlist *g_Clientlist; extern const ucsconfig *Config; extern Database database; @@ -90,7 +90,7 @@ void WorldServer::Process() Log.Out(Logs::Detail, Logs::UCS_Server, "Player: %s, Sent Message: %s", From, Message.c_str()); - Client *c = CL->FindCharacter(From); + Client *c = g_Clientlist->FindCharacter(From); safe_delete_array(From); @@ -109,7 +109,7 @@ void WorldServer::Process() } else if(Message[0] == '[') { - CL->ProcessOPMailCommand(c, Message.substr(1, std::string::npos)); + g_Clientlist->ProcessOPMailCommand(c, Message.substr(1, std::string::npos)); } break; From 1a7a5aa8c851ea8dad90018666ee408a4774ed44 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 17 May 2016 16:52:04 -0400 Subject: [PATCH 091/693] More UCS refactoring --- ucs/chatchannel.cpp | 55 ++++++++++++++++----------------------------- ucs/chatchannel.h | 11 ++++----- ucs/clientlist.cpp | 3 +-- 3 files changed, 26 insertions(+), 43 deletions(-) diff --git a/ucs/chatchannel.cpp b/ucs/chatchannel.cpp index 890d3d908..d7d0136e6 100644 --- a/ucs/chatchannel.cpp +++ b/ucs/chatchannel.cpp @@ -23,6 +23,7 @@ #include "clientlist.h" #include "database.h" #include +#include extern Database database; extern uint32 ChatMessagesSent; @@ -307,17 +308,15 @@ bool ChatChannel::RemoveClient(Client *c) { return true; } -void ChatChannel::SendOPList(Client *c) { - - if(!c) return; +void ChatChannel::SendOPList(Client *c) +{ + if (!c) + return; c->GeneralChannelMessage("Channel " + Name + " op-list: (Owner=" + Owner + ")"); - std::list::iterator Iterator; - - for(Iterator = Moderators.begin(); Iterator != Moderators.end(); ++Iterator) - c->GeneralChannelMessage((*Iterator)); - + for (auto &&m : Moderators) + c->GeneralChannelMessage(m); } void ChatChannel::SendChannelMembers(Client *c) { @@ -607,10 +606,9 @@ bool ChatChannel::IsInvitee(std::string Invitee) { return false; } -void ChatChannel::AddModerator(std::string Moderator) { - - if(!IsModerator(Moderator)) { - +void ChatChannel::AddModerator(const std::string &Moderator) +{ + if (!IsModerator(Moderator)) { Moderators.push_back(Moderator); Log.Out(Logs::Detail, Logs::UCS_Server, "Added %s as moderator to channel %s", Moderator.c_str(), Name.c_str()); @@ -618,34 +616,19 @@ void ChatChannel::AddModerator(std::string Moderator) { } -void ChatChannel::RemoveModerator(std::string Moderator) { +void ChatChannel::RemoveModerator(const std::string &Moderator) +{ + auto it = std::find(std::begin(Moderators), std::end(Moderators), Moderator); - std::list::iterator Iterator; - - for(Iterator = Moderators.begin(); Iterator != Moderators.end(); ++Iterator) { - - if((*Iterator) == Moderator) { - - Moderators.erase(Iterator); - - Log.Out(Logs::Detail, Logs::UCS_Server, "Removed %s as moderator to channel %s", Moderator.c_str(), Name.c_str()); - - return; - } + if (it != std::end(Moderators)) { + Moderators.erase(it); + Log.Out(Logs::Detail, Logs::UCS_Server, "Removed %s as moderator to channel %s", Moderator.c_str(), Name.c_str()); } } -bool ChatChannel::IsModerator(std::string Moderator) { - - std::list::iterator Iterator; - - for(Iterator = Moderators.begin(); Iterator != Moderators.end(); ++Iterator) { - - if((*Iterator) == Moderator) - return true; - } - - return false; +bool ChatChannel::IsModerator(std::string Moderator) +{ + return std::find(std::begin(Moderators), std::end(Moderators), Moderator) != std::end(Moderators); } void ChatChannel::AddVoice(std::string inVoiced) { diff --git a/ucs/chatchannel.h b/ucs/chatchannel.h index 39fb24c8b..01b805eb9 100644 --- a/ucs/chatchannel.h +++ b/ucs/chatchannel.h @@ -6,6 +6,7 @@ #include "../common/timer.h" #include #include +#include class Client; @@ -21,9 +22,9 @@ public: bool IsClientInChannel(Client *c); int MemberCount(int Status); - std::string GetName() { return Name; } + const std::string &GetName() { return Name; } void SendMessageToChannel(std::string Message, Client* Sender); - bool CheckPassword(std::string inPassword) { return ((Password.length() == 0) || (Password == inPassword)); } + bool CheckPassword(std::string inPassword) { return Password.empty() || Password == inPassword; } void SetPassword(std::string inPassword); bool IsOwner(std::string Name) { return (Owner == Name); } void SetOwner(std::string inOwner); @@ -34,8 +35,8 @@ public: void AddInvitee(std::string Invitee); void RemoveInvitee(std::string Invitee); bool IsInvitee(std::string Invitee); - void AddModerator(std::string Moderator); - void RemoveModerator(std::string Modeerator); + void AddModerator(const std::string &Moderator); + void RemoveModerator(const std::string &Moderator); bool IsModerator(std::string Moderator); void AddVoice(std::string Voiced); void RemoveVoice(std::string Voiced); @@ -60,7 +61,7 @@ private: LinkedList ClientsInChannel; - std::list Moderators; + std::vector Moderators; std::list Invitees; std::list Voiced; diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index 62fd79096..f4156167f 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -574,7 +574,6 @@ void Clientlist::CheckForStaleConnections(Client *c) { void Clientlist::Process() { - std::shared_ptr eqs; while ((eqs = chatsf->Pop())) { @@ -610,7 +609,7 @@ void Clientlist::Process() bool KeyValid = true; - while (KeyValid && !(*it)->GetForceDisconnect() && (app = (EQApplicationPacket *)(*it)->ClientStream->PopPacket())) { + while (KeyValid && !(*it)->GetForceDisconnect() && (app = (*it)->ClientStream->PopPacket())) { EmuOpcode opcode = app->GetOpcode(); switch (opcode) { From f185257415fd9bc71aa9b355a978529609744201 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 17 May 2016 17:38:08 -0400 Subject: [PATCH 092/693] Refactor ChatChannel::Invitees to std::vector --- ucs/chatchannel.cpp | 40 ++++++++++++---------------------------- ucs/chatchannel.h | 4 ++-- 2 files changed, 14 insertions(+), 30 deletions(-) diff --git a/ucs/chatchannel.cpp b/ucs/chatchannel.cpp index d7d0136e6..0aeb8379b 100644 --- a/ucs/chatchannel.cpp +++ b/ucs/chatchannel.cpp @@ -565,10 +565,9 @@ void ChatChannelList::Process() { } } -void ChatChannel::AddInvitee(std::string Invitee) { - - if(!IsInvitee(Invitee)) { - +void ChatChannel::AddInvitee(const std::string &Invitee) +{ + if (!IsInvitee(Invitee)) { Invitees.push_back(Invitee); Log.Out(Logs::Detail, Logs::UCS_Server, "Added %s as invitee to channel %s", Invitee.c_str(), Name.c_str()); @@ -576,34 +575,19 @@ void ChatChannel::AddInvitee(std::string Invitee) { } -void ChatChannel::RemoveInvitee(std::string Invitee) { +void ChatChannel::RemoveInvitee(std::string Invitee) +{ + auto it = std::find(std::begin(Invitees), std::end(Invitees), Invitee); - std::list::iterator Iterator; - - for(Iterator = Invitees.begin(); Iterator != Invitees.end(); ++Iterator) { - - if((*Iterator) == Invitee) { - - Invitees.erase(Iterator); - - Log.Out(Logs::Detail, Logs::UCS_Server, "Removed %s as invitee to channel %s", Invitee.c_str(), Name.c_str()); - - return; - } + if(it != std::end(Invitees)) { + Invitees.erase(it); + Log.Out(Logs::Detail, Logs::UCS_Server, "Removed %s as invitee to channel %s", Invitee.c_str(), Name.c_str()); } } -bool ChatChannel::IsInvitee(std::string Invitee) { - - std::list::iterator Iterator; - - for(Iterator = Invitees.begin(); Iterator != Invitees.end(); ++Iterator) { - - if((*Iterator) == Invitee) - return true; - } - - return false; +bool ChatChannel::IsInvitee(std::string Invitee) +{ + return std::find(std::begin(Invitees), std::end(Invitees), Invitee) != std::end(Invitees); } void ChatChannel::AddModerator(const std::string &Moderator) diff --git a/ucs/chatchannel.h b/ucs/chatchannel.h index 01b805eb9..89828e627 100644 --- a/ucs/chatchannel.h +++ b/ucs/chatchannel.h @@ -32,7 +32,7 @@ public: int GetMinStatus() { return MinimumStatus; } bool ReadyToDelete() { return DeleteTimer.Check(); } void SendOPList(Client *c); - void AddInvitee(std::string Invitee); + void AddInvitee(const std::string &Invitee); void RemoveInvitee(std::string Invitee); bool IsInvitee(std::string Invitee); void AddModerator(const std::string &Moderator); @@ -62,7 +62,7 @@ private: LinkedList ClientsInChannel; std::vector Moderators; - std::list Invitees; + std::vector Invitees; std::list Voiced; }; From 981d3e6b6065a314f79b037d7284d1d7a22e722d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 17 May 2016 17:42:34 -0400 Subject: [PATCH 093/693] Refactor Clientlist::Voiced to std::vector --- ucs/chatchannel.cpp | 40 ++++++++++++---------------------------- ucs/chatchannel.h | 6 +++--- 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/ucs/chatchannel.cpp b/ucs/chatchannel.cpp index 0aeb8379b..9ab9db216 100644 --- a/ucs/chatchannel.cpp +++ b/ucs/chatchannel.cpp @@ -615,45 +615,29 @@ bool ChatChannel::IsModerator(std::string Moderator) return std::find(std::begin(Moderators), std::end(Moderators), Moderator) != std::end(Moderators); } -void ChatChannel::AddVoice(std::string inVoiced) { - - if(!HasVoice(inVoiced)) { - +void ChatChannel::AddVoice(const std::string &inVoiced) +{ + if (!HasVoice(inVoiced)) { Voiced.push_back(inVoiced); Log.Out(Logs::Detail, Logs::UCS_Server, "Added %s as voiced to channel %s", inVoiced.c_str(), Name.c_str()); } - } -void ChatChannel::RemoveVoice(std::string inVoiced) { +void ChatChannel::RemoveVoice(const std::string &inVoiced) +{ + auto it = std::find(std::begin(Voiced), std::end(Voiced), inVoiced); - std::list::iterator Iterator; + if (it != std::end(Voiced)) { + Voiced.erase(it); - for(Iterator = Voiced.begin(); Iterator != Voiced.end(); ++Iterator) { - - if((*Iterator) == inVoiced) { - - Voiced.erase(Iterator); - - Log.Out(Logs::Detail, Logs::UCS_Server, "Removed %s as voiced to channel %s", inVoiced.c_str(), Name.c_str()); - - return; - } + Log.Out(Logs::Detail, Logs::UCS_Server, "Removed %s as voiced to channel %s", inVoiced.c_str(), Name.c_str()); } } -bool ChatChannel::HasVoice(std::string inVoiced) { - - std::list::iterator Iterator; - - for(Iterator = Voiced.begin(); Iterator != Voiced.end(); ++Iterator) { - - if((*Iterator) == inVoiced) - return true; - } - - return false; +bool ChatChannel::HasVoice(std::string inVoiced) +{ + return std::find(std::begin(Voiced), std::end(Voiced), inVoiced) != std::end(Voiced); } std::string CapitaliseName(std::string inString) { diff --git a/ucs/chatchannel.h b/ucs/chatchannel.h index 89828e627..c5180587b 100644 --- a/ucs/chatchannel.h +++ b/ucs/chatchannel.h @@ -38,8 +38,8 @@ public: void AddModerator(const std::string &Moderator); void RemoveModerator(const std::string &Moderator); bool IsModerator(std::string Moderator); - void AddVoice(std::string Voiced); - void RemoveVoice(std::string Voiced); + void AddVoice(const std::string &Voiced); + void RemoveVoice(const std::string &Voiced); bool HasVoice(std::string Voiced); inline bool IsModerated() { return Moderated; } void SetModerated(bool inModerated); @@ -63,7 +63,7 @@ private: std::vector Moderators; std::vector Invitees; - std::list Voiced; + std::vector Voiced; }; From a8a4712fcea08dc8a27ddc1046766c4650a5b4c1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 17 May 2016 17:47:26 -0400 Subject: [PATCH 094/693] Remove unused header --- ucs/chatchannel.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ucs/chatchannel.h b/ucs/chatchannel.h index c5180587b..718ab8e4c 100644 --- a/ucs/chatchannel.h +++ b/ucs/chatchannel.h @@ -5,7 +5,6 @@ #include "../common/linked_list.h" #include "../common/timer.h" #include -#include #include class Client; From 0c311ad3fe44527a2e2c09800f13bdfa8476a498 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 17 May 2016 18:22:44 -0400 Subject: [PATCH 095/693] Fix Client::ChangeMailBox --- ucs/clientlist.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index f4156167f..dc96f31e9 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -2252,23 +2252,22 @@ void Client::SendNotification(int MailBoxNumber, std::string Subject, std::strin safe_delete(outapp); } -void Client::ChangeMailBox(int NewMailBox) { - +void Client::ChangeMailBox(int NewMailBox) +{ Log.Out(Logs::Detail, Logs::UCS_Server, "%s Change to mailbox %i", MailBoxName().c_str(), NewMailBox); SetMailBox(NewMailBox); + auto id = std::to_string(NewMailBox); Log.Out(Logs::Detail, Logs::UCS_Server, "New mailbox is %s", MailBoxName().c_str()); - auto outapp = new EQApplicationPacket(OP_MailboxChange, 2); + auto outapp = new EQApplicationPacket(OP_MailboxChange, id.length() + 1); char *buf = (char *)outapp->pBuffer; - VARSTRUCT_ENCODE_INTSTRING(buf, NewMailBox); - + VARSTRUCT_ENCODE_STRING(buf, id.c_str()); QueuePacket(outapp); - safe_delete(outapp); } From 67c92bf1712eb9ba95aa3d10715b19f4a4cc970a Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 18 May 2016 04:45:31 -0400 Subject: [PATCH 096/693] Changed client 'constants' files to 'limits' --- changelog.txt | 3 + common/CMakeLists.txt | 36 ++++++---- common/eq_limits.h | 12 ++-- ...mfields.h => deprecated_rof2_itemfields.h} | 0 ...emfields.h => deprecated_rof_itemfields.h} | 0 ...emfields.h => deprecated_sod_itemfields.h} | 0 ...emfields.h => deprecated_sof_itemfields.h} | 0 ...de_list.h => deprecated_sof_opcode_list.h} | 0 ...a.h => deprecated_titanium_itemfields_a.h} | 0 ...b.h => deprecated_titanium_itemfields_b.h} | 0 ...temfields.h => deprecated_uf_itemfields.h} | 0 common/patches/makepatch | 2 +- common/patches/rof2_limits.cpp | 18 +++++ .../{rof2_constants.h => rof2_limits.h} | 65 ++++++------------ common/patches/rof_limits.cpp | 18 +++++ .../patches/{rof_constants.h => rof_limits.h} | 65 ++++++------------ common/patches/sod_limits.cpp | 18 +++++ .../patches/{uf_constants.h => sod_limits.h} | 65 ++++++------------ common/patches/sof_limits.cpp | 18 +++++ .../patches/{sof_constants.h => sof_limits.h} | 68 ++++++------------- common/patches/template_constants.h | 20 ------ common/patches/template_limits.cpp | 18 +++++ common/patches/template_limits.h | 31 +++++++++ common/patches/titanium_limits.cpp | 18 +++++ ...titanium_constants.h => titanium_limits.h} | 65 ++++++------------ common/patches/uf_limits.cpp | 18 +++++ .../patches/{sod_constants.h => uf_limits.h} | 65 ++++++------------ 27 files changed, 317 insertions(+), 306 deletions(-) rename common/patches/{rof2_itemfields.h => deprecated_rof2_itemfields.h} (100%) rename common/patches/{rof_itemfields.h => deprecated_rof_itemfields.h} (100%) rename common/patches/{sod_itemfields.h => deprecated_sod_itemfields.h} (100%) rename common/patches/{sof_itemfields.h => deprecated_sof_itemfields.h} (100%) rename common/patches/{sof_opcode_list.h => deprecated_sof_opcode_list.h} (100%) rename common/patches/{titanium_itemfields_a.h => deprecated_titanium_itemfields_a.h} (100%) rename common/patches/{titanium_itemfields_b.h => deprecated_titanium_itemfields_b.h} (100%) rename common/patches/{uf_itemfields.h => deprecated_uf_itemfields.h} (100%) create mode 100644 common/patches/rof2_limits.cpp rename common/patches/{rof2_constants.h => rof2_limits.h} (77%) create mode 100644 common/patches/rof_limits.cpp rename common/patches/{rof_constants.h => rof_limits.h} (77%) create mode 100644 common/patches/sod_limits.cpp rename common/patches/{uf_constants.h => sod_limits.h} (79%) create mode 100644 common/patches/sof_limits.cpp rename common/patches/{sof_constants.h => sof_limits.h} (78%) delete mode 100644 common/patches/template_constants.h create mode 100644 common/patches/template_limits.cpp create mode 100644 common/patches/template_limits.h create mode 100644 common/patches/titanium_limits.cpp rename common/patches/{titanium_constants.h => titanium_limits.h} (79%) create mode 100644 common/patches/uf_limits.cpp rename common/patches/{sod_constants.h => uf_limits.h} (79%) diff --git a/changelog.txt b/changelog.txt index 971a49cb9..938c58927 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/18/2016 == +Uleat: Changed client 'constants' files to 'limits' + == 05/10/2016 == Uleat: Converted client translators' 'SerializeItem()' to recursive, single buffer methodology. Titanium SerializeItem() now adds a null term between parent items instead of the invoking function Uleat: Converted server 'BulkSendInventoryItems()' to use single buffer methodology diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 6c13aefbc..8c5ac6db7 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -74,11 +74,17 @@ SET(common_sources platform.cpp patches/patches.cpp patches/sod.cpp + patches/sod_limits.cpp patches/sof.cpp + patches/sof_limits.cpp patches/rof.cpp + patches/rof_limits.cpp patches/rof2.cpp + patches/rof2_limits.cpp patches/titanium.cpp + patches/titanium_limits.cpp patches/uf.cpp + patches/uf_limits.cpp SocketLib/Base64.cpp SocketLib/File.cpp SocketLib/HttpdCookies.cpp @@ -201,13 +207,13 @@ SET(common_headers zone_numbers.h patches/patches.h patches/sod.h - patches/sod_constants.h # patches/sod_itemfields.h + patches/sod_limits.h patches/sod_ops.h patches/sod_structs.h patches/sof.h - patches/sof_constants.h # patches/sof_itemfields.h + patches/sof_limits.h # patches/sof_opcode_list.h patches/sof_ops.h patches/sof_structs.h @@ -215,24 +221,24 @@ SET(common_headers patches/ss_define.h patches/ss_register.h patches/rof.h - patches/rof_constants.h # patches/rof_itemfields.h + patches/rof_limits.h patches/rof_ops.h patches/rof_structs.h patches/rof2.h - patches/rof2_constants.h # patches/rof2_itemfields.h + patches/rof2_limits.h patches/rof2_ops.h patches/rof2_structs.h patches/titanium.h - patches/titanium_constants.h # patches/titanium_itemfields_a.h # patches/titanium_itemfields_b.h + patches/titanium_limits.h patches/titanium_ops.h patches/titanium_structs.h patches/uf.h - patches/uf_constants.h # patches/uf_itemfields.h + patches/uf_limits.h patches/uf_ops.h patches/uf_structs.h SocketLib/Base64.h @@ -256,46 +262,52 @@ SOURCE_GROUP(Patches FILES patches/patches.h patches/sod.h # patches/sod_itemfields.h + patches/sod_limits.h patches/sod_ops.h - patches/sod_constants.h patches/sod_structs.h patches/sof.h # patches/sof_itemfields.h + patches/sof_limits.h # patches/sof_opcode_list.h patches/sof_ops.h - patches/sof_constants.h patches/sof_structs.h patches/ss_declare.h patches/ss_define.h patches/ss_register.h patches/rof.h # patches/rof_itemfields.h + patches/rof_limits.h patches/rof_ops.h - patches/rof_constants.h patches/rof_structs.h patches/rof2.h # patches/rof2_itemfields.h + patches/rof2_limits.h patches/rof2_ops.h - patches/rof2_constants.h patches/rof2_structs.h patches/titanium.h # patches/titanium_itemfields_a.h # patches/titanium_itemfields_b.h + patches/titanium_limits.h patches/titanium_ops.h - patches/titanium_constants.h patches/titanium_structs.h patches/uf.h # patches/uf_itemfields.h + patches/uf_limits.h patches/uf_ops.h - patches/uf_constants.h patches/uf_structs.h patches/patches.cpp patches/sod.cpp + patches/sod_limits.cpp patches/sof.cpp + patches/sof_limits.cpp patches/rof.cpp + patches/rof_limits.cpp patches/rof2.cpp + patches/rof2_limits.cpp patches/titanium.cpp + patches/titanium_limits.cpp patches/uf.cpp + patches/uf_limits.cpp ) SOURCE_GROUP(SocketLib FILES diff --git a/common/eq_limits.h b/common/eq_limits.h index 4c1db6252..eb9c983f0 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -23,12 +23,12 @@ #include "types.h" #include "eq_constants.h" #include "inventory_version.h" // inv2 watch -#include "../common/patches/titanium_constants.h" -#include "../common/patches/sof_constants.h" -#include "../common/patches/sod_constants.h" -#include "../common/patches/uf_constants.h" -#include "../common/patches/rof_constants.h" -#include "../common/patches/rof2_constants.h" +#include "../common/patches/titanium_limits.h" +#include "../common/patches/sof_limits.h" +#include "../common/patches/sod_limits.h" +#include "../common/patches/uf_limits.h" +#include "../common/patches/rof_limits.h" +#include "../common/patches/rof2_limits.h" // *** DO NOT CHANGE without a full understanding of the consequences..the server is set up to use these settings explicitly!! *** diff --git a/common/patches/rof2_itemfields.h b/common/patches/deprecated_rof2_itemfields.h similarity index 100% rename from common/patches/rof2_itemfields.h rename to common/patches/deprecated_rof2_itemfields.h diff --git a/common/patches/rof_itemfields.h b/common/patches/deprecated_rof_itemfields.h similarity index 100% rename from common/patches/rof_itemfields.h rename to common/patches/deprecated_rof_itemfields.h diff --git a/common/patches/sod_itemfields.h b/common/patches/deprecated_sod_itemfields.h similarity index 100% rename from common/patches/sod_itemfields.h rename to common/patches/deprecated_sod_itemfields.h diff --git a/common/patches/sof_itemfields.h b/common/patches/deprecated_sof_itemfields.h similarity index 100% rename from common/patches/sof_itemfields.h rename to common/patches/deprecated_sof_itemfields.h diff --git a/common/patches/sof_opcode_list.h b/common/patches/deprecated_sof_opcode_list.h similarity index 100% rename from common/patches/sof_opcode_list.h rename to common/patches/deprecated_sof_opcode_list.h diff --git a/common/patches/titanium_itemfields_a.h b/common/patches/deprecated_titanium_itemfields_a.h similarity index 100% rename from common/patches/titanium_itemfields_a.h rename to common/patches/deprecated_titanium_itemfields_a.h diff --git a/common/patches/titanium_itemfields_b.h b/common/patches/deprecated_titanium_itemfields_b.h similarity index 100% rename from common/patches/titanium_itemfields_b.h rename to common/patches/deprecated_titanium_itemfields_b.h diff --git a/common/patches/uf_itemfields.h b/common/patches/deprecated_uf_itemfields.h similarity index 100% rename from common/patches/uf_itemfields.h rename to common/patches/deprecated_uf_itemfields.h diff --git a/common/patches/makepatch b/common/patches/makepatch index e28b4bc2a..ef2271b29 100644 --- a/common/patches/makepatch +++ b/common/patches/makepatch @@ -5,7 +5,7 @@ if [ -z "$1" ]; then exit 1 fi -for ext in .cpp .h _ops.h _constants.h _structs.h +for ext in .cpp _limits.cpp .h _ops.h _limits.h _structs.h do cp template$ext $1$ext perl -pi -e "s/TEMPLATE/$1/g" $1$ext diff --git a/common/patches/rof2_limits.cpp b/common/patches/rof2_limits.cpp new file mode 100644 index 000000000..3f4711d4d --- /dev/null +++ b/common/patches/rof2_limits.cpp @@ -0,0 +1,18 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ diff --git a/common/patches/rof2_constants.h b/common/patches/rof2_limits.h similarity index 77% rename from common/patches/rof2_constants.h rename to common/patches/rof2_limits.h index e2886406b..b32d79d24 100644 --- a/common/patches/rof2_constants.h +++ b/common/patches/rof2_limits.h @@ -1,30 +1,30 @@ -/* -EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef ROF2_CONSTANTS_H_ -#define ROF2_CONSTANTS_H_ +#ifndef COMMON_ROF2_CONSTANTS_H +#define COMMON_ROF2_CONSTANTS_H #include "../types.h" -namespace RoF2 { + +namespace RoF2 +{ namespace inventory { typedef enum : int16 { TypePossessions = 0, @@ -194,29 +194,6 @@ namespace RoF2 { static const bool COIN_HAS_WEIGHT = false; } -}; //end namespace RoF2 +}; /*RoF2*/ -#endif /*ROF2_CONSTANTS_H_*/ - -/* -RoF2 Notes: - ** Structure-based inventory ** -ok Possessions: ( 0, { 0 .. 33 }, -1, -1 ) (Corpse: { 23 .. 56 } [Offset 23]) -ok [Equipment: ( 0, { 0 .. 22 }, -1, -1 )] -ok [General: ( 0, { 23 .. 32 }, -1, -1 )] -ok [Cursor: ( 0, 33, -1, -1 )] - General Bags: ( 0, { 23 .. 32 }, { 0 .. (maxsize - 1) }, -1 ) - Cursor Bags: ( 0, 33, { 0 .. (maxsize - 1) }, -1 ) - - Bank: ( 1, { 0 .. 23 }, -1, -1 ) - Bank Bags: ( 1, { 0 .. 23 }, { 0 .. (maxsize - 1)}, -1 ) - - Shared Bank: ( 2, { 0 .. 1 }, -1, -1 ) - Shared Bank Bags: ( 2, { 0 .. 1 }, { 0 .. (maxsize - 1) }, -1 ) - - Trade: ( 3, { 0 .. 8 }, -1, -1 ) - (Trade Bags: 3031 - 3110 -- server values) - - World: ( 4, { 0 .. 10 }, -1, -1 ) - -*/ +#endif /*COMMON_ROF2_CONSTANTS_H*/ diff --git a/common/patches/rof_limits.cpp b/common/patches/rof_limits.cpp new file mode 100644 index 000000000..3f4711d4d --- /dev/null +++ b/common/patches/rof_limits.cpp @@ -0,0 +1,18 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ diff --git a/common/patches/rof_constants.h b/common/patches/rof_limits.h similarity index 77% rename from common/patches/rof_constants.h rename to common/patches/rof_limits.h index c75602da4..20f38b90c 100644 --- a/common/patches/rof_constants.h +++ b/common/patches/rof_limits.h @@ -1,30 +1,30 @@ -/* -EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef ROF_CONSTANTS_H_ -#define ROF_CONSTANTS_H_ +#ifndef COMMON_ROF_CONSTANTS_H +#define COMMON_ROF_CONSTANTS_H #include "../types.h" -namespace RoF { + +namespace RoF +{ namespace inventory { typedef enum : int16 { TypePossessions = 0, @@ -193,29 +193,6 @@ namespace RoF { static const bool COIN_HAS_WEIGHT = false; } -}; //end namespace RoF +}; /*RoF*/ -#endif /*ROF_CONSTANTS_H_*/ - -/* -RoF Notes: - ** Structure-based inventory ** -ok Possessions: ( 0, { 0 .. 33 }, -1, -1 ) (Corpse: { 23 .. 56 } [Offset 23]) -ok [Equipment: ( 0, { 0 .. 22 }, -1, -1 )] -ok [General: ( 0, { 23 .. 32 }, -1, -1 )] -ok [Cursor: ( 0, 33, -1, -1 )] - General Bags: ( 0, { 23 .. 32 }, { 0 .. (maxsize - 1) }, -1 ) - Cursor Bags: ( 0, 33, { 0 .. (maxsize - 1) }, -1 ) - - Bank: ( 1, { 0 .. 23 }, -1, -1 ) - Bank Bags: ( 1, { 0 .. 23 }, { 0 .. (maxsize - 1)}, -1 ) - - Shared Bank: ( 2, { 0 .. 1 }, -1, -1 ) - Shared Bank Bags: ( 2, { 0 .. 1 }, { 0 .. (maxsize - 1) }, -1 ) - - Trade: ( 3, { 0 .. 8 }, -1, -1 ) - (Trade Bags: 3031 - 3110 -- server values) - - World: ( 4, { 0 .. 10 }, -1, -1 ) - -*/ +#endif /*COMMON_ROF_CONSTANTS_H*/ diff --git a/common/patches/sod_limits.cpp b/common/patches/sod_limits.cpp new file mode 100644 index 000000000..3f4711d4d --- /dev/null +++ b/common/patches/sod_limits.cpp @@ -0,0 +1,18 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ diff --git a/common/patches/uf_constants.h b/common/patches/sod_limits.h similarity index 79% rename from common/patches/uf_constants.h rename to common/patches/sod_limits.h index d254e66f6..83455d1e8 100644 --- a/common/patches/uf_constants.h +++ b/common/patches/sod_limits.h @@ -1,30 +1,30 @@ -/* -EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef UF_CONSTANTS_H_ -#define UF_CONSTANTS_H_ +#ifndef COMMON_SOD_CONSTANTS_H +#define COMMON_SOD_CONSTANTS_H #include "../types.h" -namespace UF { + +namespace SoD +{ namespace inventory { typedef enum : int16 { TypePossessions = 0, @@ -189,29 +189,6 @@ namespace UF { static const bool COIN_HAS_WEIGHT = false; } -}; //end namespace UF +}; /*SoD*/ -#endif /*UF_CONSTANTS_H_*/ - -/* -UF Notes: - ** Integer-based inventory ** -ok Possessions: 0 - 31 (Corpse: 23 - 54 [Offset 23]) -ok [Equipment: 0 - 22] -ok [General: 23 - 30] -ok [Cursor: 31] -ok General Bags: 262 - 341 -ok Cursor Bags: 342 - 351 - -ok Bank: 2000 - 2023 -ok Bank Bags: 2032 - 2271 - -ok Shared Bank: 2500 - 2501 -ok Shared Bank Bags: 2532 - 2551 - - Trade: 3000 - 3007 - (Trade Bags: 3031 - 3110 -- server values) - - World: 4000 - 4009 - -*/ +#endif /*COMMON_SOD_CONSTANTS_H*/ diff --git a/common/patches/sof_limits.cpp b/common/patches/sof_limits.cpp new file mode 100644 index 000000000..3f4711d4d --- /dev/null +++ b/common/patches/sof_limits.cpp @@ -0,0 +1,18 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ diff --git a/common/patches/sof_constants.h b/common/patches/sof_limits.h similarity index 78% rename from common/patches/sof_constants.h rename to common/patches/sof_limits.h index f556ac9d4..55e63db9b 100644 --- a/common/patches/sof_constants.h +++ b/common/patches/sof_limits.h @@ -1,30 +1,30 @@ -/* -EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef SOF_CONSTANTS_H_ -#define SOF_CONSTANTS_H_ +#ifndef COMMON_SOF_CONSTANTS_H +#define COMMON_SOF_CONSTANTS_H #include "../types.h" -namespace SoF { + +namespace SoF +{ namespace inventory { typedef enum : int16 { TypePossessions = 0, @@ -189,32 +189,6 @@ namespace SoF { static const bool COIN_HAS_WEIGHT = true; } -}; //end namespace SoF +}; /*SoF*/ -#endif /*SOF_CONSTANTS_H_*/ - -/* -SoF Notes: - ** Integer-based inventory ** -ok Possessions: 0 - 31 (Corpse: 23 - 54 [Offset 23]) -ok [Equipment: 0 - 22] -ok [General: 23 - 30] -ok [Cursor: 31] -ok General Bags: 262 - 341 -ok Cursor Bags: 342 - 351 - -ok Bank: 2000 - 2023 -ok Bank Bags: 2032 - 2271 - -ok Shared Bank: 2500 - 2501 -ok Shared Bank Bags: 2532 - 2551 - - Trade: 3000 - 3007 - (Trade Bags: 3031 - 3110 -- server values) - - World: 4000 - 4009 - -code file reviewed.. - ..SerializeItem() needs work - ..still needs timestamp redirect code -*/ +#endif /*COMMON_SOF_CONSTANTS_H*/ diff --git a/common/patches/template_constants.h b/common/patches/template_constants.h deleted file mode 100644 index f8dbc39e8..000000000 --- a/common/patches/template_constants.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef TEMPLATE_CONSTANTS_H_ -#define TEMPLATE_CONSTANTS_H_ - -namespace TEMPLATE { - - // put constants here and #include appropriately - -}; //end namespace TEMPLATE - -#endif /*TEMPLATE_CONSTANTS_H_*/ - - - - - - - - - - diff --git a/common/patches/template_limits.cpp b/common/patches/template_limits.cpp new file mode 100644 index 000000000..273e74a5c --- /dev/null +++ b/common/patches/template_limits.cpp @@ -0,0 +1,18 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ diff --git a/common/patches/template_limits.h b/common/patches/template_limits.h new file mode 100644 index 000000000..54690d3c1 --- /dev/null +++ b/common/patches/template_limits.h @@ -0,0 +1,31 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_TEMPLATE_LIMITS_H +#define COMMON_TEMPLATE_LIMITS_H + + +namespace TEMPLATE +{ + + // put constants here and #include appropriately + +}; /* TEMPLATE */ + +#endif /*COMMON_TEMPLATE_LIMITS_H*/ diff --git a/common/patches/titanium_limits.cpp b/common/patches/titanium_limits.cpp new file mode 100644 index 000000000..3f4711d4d --- /dev/null +++ b/common/patches/titanium_limits.cpp @@ -0,0 +1,18 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ diff --git a/common/patches/titanium_constants.h b/common/patches/titanium_limits.h similarity index 79% rename from common/patches/titanium_constants.h rename to common/patches/titanium_limits.h index b0a7353fa..2eba35b70 100644 --- a/common/patches/titanium_constants.h +++ b/common/patches/titanium_limits.h @@ -1,30 +1,30 @@ -/* -EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TITANIUM_CONSTANTS_H_ -#define TITANIUM_CONSTANTS_H_ +#ifndef COMMON_TITANIUM_CONSTANTS_H +#define COMMON_TITANIUM_CONSTANTS_H #include "../types.h" -namespace Titanium { + +namespace Titanium +{ namespace inventory { typedef enum : int16 { TypePossessions = 0, @@ -188,29 +188,6 @@ namespace Titanium { static const bool COIN_HAS_WEIGHT = true; } -}; //end namespace Titanium +}; /*Titanium*/ -#endif /*TITANIUM_CONSTANTS_H_*/ - -/* -Titanium Notes: - ** Integer-based inventory ** -ok Possessions: 0 - 30 (Corpse: 22 - 52 [Offset 22]) -ok [Equipment: 0 - 21] -ok [General: 22 - 29] -ok [Cursor: 30] -ok General Bags: 251 - 330 -ok Cursor Bags: 331 - 340 - -ok Bank: 2000 - 2015 -ok Bank Bags: 2031 - 2190 - -ok Shared Bank: 2500 - 2501 -ok Shared Bank Bags: 2531 - 2550 - - Trade: 3000 - 3007 - (Trade Bags: 3031 - 3110 -- server values) - - World: 4000 - 4009 - -*/ +#endif /*COMMON_TITANIUM_CONSTANTS_H*/ diff --git a/common/patches/uf_limits.cpp b/common/patches/uf_limits.cpp new file mode 100644 index 000000000..3f4711d4d --- /dev/null +++ b/common/patches/uf_limits.cpp @@ -0,0 +1,18 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ diff --git a/common/patches/sod_constants.h b/common/patches/uf_limits.h similarity index 79% rename from common/patches/sod_constants.h rename to common/patches/uf_limits.h index 418525032..64880ee14 100644 --- a/common/patches/sod_constants.h +++ b/common/patches/uf_limits.h @@ -1,30 +1,30 @@ -/* -EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY except by those people which sell it, which -are required to give you total support for your newly bought product; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef SOD_CONSTANTS_H_ -#define SOD_CONSTANTS_H_ +#ifndef COMMON_UF_CONSTANTS_H +#define COMMON_UF_CONSTANTS_H #include "../types.h" -namespace SoD { + +namespace UF +{ namespace inventory { typedef enum : int16 { TypePossessions = 0, @@ -189,29 +189,6 @@ namespace SoD { static const bool COIN_HAS_WEIGHT = false; } -}; //end namespace SoD +}; /*UF*/ -#endif /*SOD_CONSTANTS_H_*/ - -/* -SoD Notes: - ** Integer-based inventory ** -ok Possessions: 0 - 31 (Corpse: 23 - 54 [Offset 23]) -ok [Equipment: 0 - 22] -ok [General: 23 - 30] -ok [Cursor: 31] -ok General Bags: 262 - 341 -ok Cursor Bags: 342 - 351 - -ok Bank: 2000 - 2023 -ok Bank Bags: 2032 - 2271 - -ok Shared Bank: 2500 - 2501 -ok Shared Bank Bags: 2532 - 2551 - - Trade: 3000 - 3007 - (Trade Bags: 3031 - 3110 -- server values) - - World: 4000 - 4009 - -*/ +#endif /*COMMON_UF_CONSTANTS_H*/ From ffb88e0a8ff3230600de892fdac70d745a64549d Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 18 May 2016 22:38:41 -0400 Subject: [PATCH 097/693] Added EQEmu::OutBuffer() - stringstream-derived class with a few additional methods --- common/item.h | 6 +- common/patches/rof.cpp | 159 +++++++------- common/patches/rof2.cpp | 160 +++++++------- common/patches/sod.cpp | 137 ++++++------ common/patches/sof.cpp | 137 ++++++------ common/patches/titanium.cpp | 402 ++++++++++++++++++------------------ common/patches/uf.cpp | 157 +++++++------- common/string_util.cpp | 43 ++++ common/string_util.h | 32 +++ zone/client_process.cpp | 36 ++-- 10 files changed, 631 insertions(+), 638 deletions(-) diff --git a/common/item.h b/common/item.h index 11e1ad151..7d60afdac 100644 --- a/common/item.h +++ b/common/item.h @@ -31,9 +31,11 @@ class EvolveInfo; // Stores information about an evolving item family #include "../common/timer.h" #include "../common/bodytypes.h" +#include "string_util.h" + #include #include -#include +//#include namespace ItemField @@ -413,7 +415,7 @@ public: uint32 GetKillsNeeded(uint8 currentlevel); std::string Serialize(int16 slot_id) const { InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(InternalSerializedItem_Struct)); return ser; } - void Serialize(std::stringstream& ss, int16 slot_id) const { InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ss.write((const char*)&isi, sizeof(isi)); } + void Serialize(EQEmu::OutBuffer& ob, int16 slot_id) const { InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); } inline int32 GetSerialNumber() const { return m_SerialNumber; } inline void SetSerialNumber(int32 id) { m_SerialNumber = id; } diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 49e644412..dc57d0ba6 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -24,7 +24,7 @@ namespace RoF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline structs::InventorySlot_Struct ServerToRoFSlot(uint32 serverSlot); @@ -557,24 +557,21 @@ namespace RoF InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)&item_count, sizeof(uint32)); + ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); + in->size = ob.size(); + in->pBuffer = ob.detach(); delete[] __emu_buffer; @@ -1492,30 +1489,24 @@ namespace RoF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -5180,7 +5171,7 @@ namespace RoF return NextItemInstSerialNumber; } - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const Item_Struct *item = inst->GetUnscaledItem(); @@ -5212,7 +5203,7 @@ namespace RoF hdr.unknown052 = 0; hdr.isEvolving = item->EvolvingItem; - ss.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader)); + ob.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader)); if (item->EvolvingItem > 0) { RoF::structs::EvolvingItem evotop; @@ -5226,7 +5217,7 @@ namespace RoF evotop.Activated = 1; evotop.evomaxlevel = item->EvolvingMax; - ss.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem)); + ob.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem)); } //ORNAMENT IDFILE / ICON @@ -5241,16 +5232,16 @@ namespace RoF char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); //Mainhand - ss.write(tmp, strlen(tmp)); - ss.write("\0", 1); + ob.write(tmp, strlen(tmp)); + ob.write("\0", 1); //Offhand - ss.write(tmp, strlen(tmp)); - ss.write("\0", 1); + ob.write(tmp, strlen(tmp)); + ob.write("\0", 1); } else { - ss.write("\0", 1); // no main hand Ornamentation - ss.write("\0", 1); // no off hand Ornamentation + ob.write("\0", 1); // no main hand Ornamentation + ob.write("\0", 1); // no off hand Ornamentation } RoF::structs::ItemSerializationHeaderFinish hdrf; @@ -5264,21 +5255,21 @@ namespace RoF hdrf.unknowna5 = 0; hdrf.ItemClass = item->ItemClass; - ss.write((const char*)&hdrf, sizeof(RoF::structs::ItemSerializationHeaderFinish)); + ob.write((const char*)&hdrf, sizeof(RoF::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) - ss.write(item->Name, strlen(item->Name)); - ss.write("\0", 1); + ob.write(item->Name, strlen(item->Name)); + ob.write("\0", 1); if (strlen(item->Lore) > 0) - ss.write(item->Lore, strlen(item->Lore)); - ss.write("\0", 1); + ob.write(item->Lore, strlen(item->Lore)); + ob.write("\0", 1); if (strlen(item->IDFile) > 0) - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write("\0", 1); + ob.write(item->IDFile, strlen(item->IDFile)); + ob.write("\0", 1); - ss.write("\0", 1); + ob.write("\0", 1); RoF::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(RoF::structs::ItemBodyStruct)); @@ -5369,12 +5360,12 @@ namespace RoF ibs.FactionAmt4 = item->FactionAmt4; ibs.FactionMod4 = item->FactionMod4; - ss.write((const char*)&ibs, sizeof(RoF::structs::ItemBodyStruct)); + ob.write((const char*)&ibs, sizeof(RoF::structs::ItemBodyStruct)); //charm text if (strlen(item->CharmFile) > 0) - ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write("\0", 1); + ob.write((const char*)item->CharmFile, strlen(item->CharmFile)); + ob.write("\0", 1); RoF::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(RoF::structs::ItemSecondaryBodyStruct)); @@ -5403,11 +5394,11 @@ namespace RoF isbs.book = item->Book; isbs.booktype = item->BookType; - ss.write((const char*)&isbs, sizeof(RoF::structs::ItemSecondaryBodyStruct)); + ob.write((const char*)&isbs, sizeof(RoF::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write("\0", 1); + ob.write((const char*)item->Filename, strlen(item->Filename)); + ob.write("\0", 1); RoF::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(RoF::structs::ItemTertiaryBodyStruct)); @@ -5442,7 +5433,7 @@ namespace RoF itbs.unknown13 = 0; itbs.unknown14 = 0; - ss.write((const char*)&itbs, sizeof(RoF::structs::ItemTertiaryBodyStruct)); + ob.write((const char*)&itbs, sizeof(RoF::structs::ItemTertiaryBodyStruct)); // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; @@ -5459,13 +5450,13 @@ namespace RoF ices.recast = item->RecastDelay; ices.recast_type = item->RecastType; - ss.write((const char*)&ices, sizeof(RoF::structs::ClickEffectStruct)); + ob.write((const char*)&ices, sizeof(RoF::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write("\0", 1); + ob.write((const char*)item->ClickName, strlen(item->ClickName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + ob.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 RoF::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(RoF::structs::ProcEffectStruct)); @@ -5476,13 +5467,13 @@ namespace RoF ipes.level = item->Proc.Level; ipes.procrate = item->ProcRate; - ss.write((const char*)&ipes, sizeof(RoF::structs::ProcEffectStruct)); + ob.write((const char*)&ipes, sizeof(RoF::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write("\0", 1); + ob.write((const char*)item->ProcName, strlen(item->ProcName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 RoF::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(RoF::structs::WornEffectStruct)); @@ -5492,13 +5483,13 @@ namespace RoF iwes.type = item->Worn.Type; iwes.level = item->Worn.Level; - ss.write((const char*)&iwes, sizeof(RoF::structs::WornEffectStruct)); + ob.write((const char*)&iwes, sizeof(RoF::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write("\0", 1); + ob.write((const char*)item->WornName, strlen(item->WornName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 RoF::structs::WornEffectStruct ifes; memset(&ifes, 0, sizeof(RoF::structs::WornEffectStruct)); @@ -5508,13 +5499,13 @@ namespace RoF ifes.type = item->Focus.Type; ifes.level = item->Focus.Level; - ss.write((const char*)&ifes, sizeof(RoF::structs::WornEffectStruct)); + ob.write((const char*)&ifes, sizeof(RoF::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write("\0", 1); + ob.write((const char*)item->FocusName, strlen(item->FocusName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 RoF::structs::WornEffectStruct ises; memset(&ises, 0, sizeof(RoF::structs::WornEffectStruct)); @@ -5524,13 +5515,13 @@ namespace RoF ises.type = item->Scroll.Type; ises.level = item->Scroll.Level; - ss.write((const char*)&ises, sizeof(RoF::structs::WornEffectStruct)); + ob.write((const char*)&ises, sizeof(RoF::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write("\0", 1); + ob.write((const char*)item->ScrollName, strlen(item->ScrollName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // Bard Effect? RoF::structs::WornEffectStruct ibes; @@ -5542,7 +5533,7 @@ namespace RoF ibes.level = 0; //ibes.unknown6 = 0xffffffff; - ss.write((const char*)&ibes, sizeof(RoF::structs::WornEffectStruct)); + ob.write((const char*)&ibes, sizeof(RoF::structs::WornEffectStruct)); /* if(strlen(item->BardName) > 0) @@ -5551,9 +5542,9 @@ namespace RoF ss.write((const char*)&null_term, sizeof(uint8)); } else */ - ss.write("\0", 1); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects RoF::structs::ItemQuaternaryBodyStruct iqbs; @@ -5586,12 +5577,12 @@ namespace RoF iqbs.unknown30 = 0; iqbs.unknown39 = 1; - ss.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); + ob.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ss.tellp(); + std::stringstream::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; - ss.write((const char*)&subitem_count, sizeof(uint32)); + ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { ItemInst* sub = inst->GetItem(index); @@ -5608,20 +5599,14 @@ namespace RoF else SubSlotNumber = slot_id_in; - ss.write((const char*)&index, sizeof(uint32)); + ob.write((const char*)&index, sizeof(uint32)); - SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + SerializeItem(ob, sub, SubSlotNumber, (depth + 1)); ++subitem_count; } - if (subitem_count) { - std::stringstream::pos_type cur_pos = ss.tellp(); - ss.seekp(count_pos); - - ss.write((const char*)&subitem_count, sizeof(uint32)); - - ss.seekp(cur_pos); - } + if (subitem_count) + ob.overwrite(count_pos, (const char*)&subitem_count, sizeof(uint32)); } static inline structs::InventorySlot_Struct ServerToRoFSlot(uint32 serverSlot) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 43cc31d55..a7f63abe6 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -24,7 +24,7 @@ namespace RoF2 static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth, ItemPacketType packet_type); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth, ItemPacketType packet_type); // server to client inventory location converters static inline structs::InventorySlot_Struct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType = ItemPacketInvalid); @@ -628,24 +628,21 @@ namespace RoF2 InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)&item_count, sizeof(uint32)); + ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); + in->size = ob.size(); + in->pBuffer = ob.detach(); delete[] __emu_buffer; @@ -1563,29 +1560,24 @@ namespace RoF2 //store away the emu struct uchar* __emu_buffer = in->pBuffer; + ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); + in->size = ob.size(); + in->pBuffer = ob.detach(); delete[] __emu_buffer; @@ -5451,7 +5443,7 @@ namespace RoF2 return NextItemInstSerialNumber; } - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type) { const Item_Struct *item = inst->GetUnscaledItem(); @@ -5483,7 +5475,7 @@ namespace RoF2 hdr.unknown052 = 0; hdr.isEvolving = item->EvolvingItem; - ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); + ob.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); if (item->EvolvingItem > 0) { RoF2::structs::EvolvingItem evotop; @@ -5497,7 +5489,7 @@ namespace RoF2 evotop.Activated = 1; evotop.evomaxlevel = item->EvolvingMax; - ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); + ob.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); } //ORNAMENT IDFILE / ICON @@ -5512,16 +5504,16 @@ namespace RoF2 char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); //Mainhand - ss.write(tmp, strlen(tmp)); - ss.write("\0", 1); + ob.write(tmp, strlen(tmp)); + ob.write("\0", 1); //Offhand - ss.write(tmp, strlen(tmp)); - ss.write("\0", 1); + ob.write(tmp, strlen(tmp)); + ob.write("\0", 1); } else { - ss.write("\0", 1); // no main hand Ornamentation - ss.write("\0", 1); // no off hand Ornamentation + ob.write("\0", 1); // no main hand Ornamentation + ob.write("\0", 1); // no off hand Ornamentation } RoF2::structs::ItemSerializationHeaderFinish hdrf; @@ -5535,21 +5527,21 @@ namespace RoF2 hdrf.unknowna5 = 0; hdrf.ItemClass = item->ItemClass; - ss.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); + ob.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) - ss.write(item->Name, strlen(item->Name)); - ss.write("\0", 1); + ob.write(item->Name, strlen(item->Name)); + ob.write("\0", 1); if (strlen(item->Lore) > 0) - ss.write(item->Lore, strlen(item->Lore)); - ss.write("\0", 1); + ob.write(item->Lore, strlen(item->Lore)); + ob.write("\0", 1); if (strlen(item->IDFile) > 0) - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write("\0", 1); + ob.write(item->IDFile, strlen(item->IDFile)); + ob.write("\0", 1); - ss.write("\0", 1); + ob.write("\0", 1); RoF2::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct)); @@ -5640,12 +5632,12 @@ namespace RoF2 ibs.FactionAmt4 = item->FactionAmt4; ibs.FactionMod4 = item->FactionMod4; - ss.write((const char*)&ibs, sizeof(RoF2::structs::ItemBodyStruct)); + ob.write((const char*)&ibs, sizeof(RoF2::structs::ItemBodyStruct)); //charm text if (strlen(item->CharmFile) > 0) - ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write("\0", 1); + ob.write((const char*)item->CharmFile, strlen(item->CharmFile)); + ob.write("\0", 1); RoF2::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); @@ -5674,11 +5666,11 @@ namespace RoF2 isbs.book = item->Book; isbs.booktype = item->BookType; - ss.write((const char*)&isbs, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); + ob.write((const char*)&isbs, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write("\0", 1); + ob.write((const char*)item->Filename, strlen(item->Filename)); + ob.write("\0", 1); RoF2::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); @@ -5713,7 +5705,7 @@ namespace RoF2 itbs.unknown13 = 0; itbs.unknown14 = 0; - ss.write((const char*)&itbs, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + ob.write((const char*)&itbs, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; @@ -5730,13 +5722,13 @@ namespace RoF2 ices.recast = item->RecastDelay; ices.recast_type = item->RecastType; - ss.write((const char*)&ices, sizeof(RoF2::structs::ClickEffectStruct)); + ob.write((const char*)&ices, sizeof(RoF2::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write("\0", 1); + ob.write((const char*)item->ClickName, strlen(item->ClickName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + ob.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 RoF2::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(RoF2::structs::ProcEffectStruct)); @@ -5747,13 +5739,13 @@ namespace RoF2 ipes.level = item->Proc.Level; ipes.procrate = item->ProcRate; - ss.write((const char*)&ipes, sizeof(RoF2::structs::ProcEffectStruct)); + ob.write((const char*)&ipes, sizeof(RoF2::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write("\0", 1); + ob.write((const char*)item->ProcName, strlen(item->ProcName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 RoF2::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(RoF2::structs::WornEffectStruct)); @@ -5763,13 +5755,13 @@ namespace RoF2 iwes.type = item->Worn.Type; iwes.level = item->Worn.Level; - ss.write((const char*)&iwes, sizeof(RoF2::structs::WornEffectStruct)); + ob.write((const char*)&iwes, sizeof(RoF2::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write("\0", 1); + ob.write((const char*)item->WornName, strlen(item->WornName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 RoF2::structs::WornEffectStruct ifes; memset(&ifes, 0, sizeof(RoF2::structs::WornEffectStruct)); @@ -5779,13 +5771,13 @@ namespace RoF2 ifes.type = item->Focus.Type; ifes.level = item->Focus.Level; - ss.write((const char*)&ifes, sizeof(RoF2::structs::WornEffectStruct)); + ob.write((const char*)&ifes, sizeof(RoF2::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write("\0", 1); + ob.write((const char*)item->FocusName, strlen(item->FocusName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 RoF2::structs::WornEffectStruct ises; memset(&ises, 0, sizeof(RoF2::structs::WornEffectStruct)); @@ -5795,13 +5787,13 @@ namespace RoF2 ises.type = item->Scroll.Type; ises.level = item->Scroll.Level; - ss.write((const char*)&ises, sizeof(RoF2::structs::WornEffectStruct)); + ob.write((const char*)&ises, sizeof(RoF2::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write("\0", 1); + ob.write((const char*)item->ScrollName, strlen(item->ScrollName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // Bard Effect? RoF2::structs::WornEffectStruct ibes; @@ -5813,18 +5805,18 @@ namespace RoF2 ibes.level = item->Bard.Level; //ibes.unknown6 = 0xffffffff; - ss.write((const char*)&ibes, sizeof(RoF2::structs::WornEffectStruct)); + ob.write((const char*)&ibes, sizeof(RoF2::structs::WornEffectStruct)); /* if(strlen(item->BardName) > 0) { - ss.write((const char*)item->BardName, strlen(item->BardName)); - ss.write((const char*)&null_term, sizeof(uint8)); + ob.write((const char*)item->BardName, strlen(item->BardName)); + ob.write((const char*)&null_term, sizeof(uint8)); } else */ - ss.write("\0", 1); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects RoF2::structs::ItemQuaternaryBodyStruct iqbs; @@ -5867,12 +5859,12 @@ namespace RoF2 iqbs.unknown38 = 0; iqbs.unknown39 = 1; - ss.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); + ob.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ss.tellp(); + EQEmu::OutBuffer::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; - ss.write((const char*)&subitem_count, sizeof(uint32)); + ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { ItemInst* sub = inst->GetItem(index); @@ -5889,20 +5881,14 @@ namespace RoF2 else SubSlotNumber = slot_id_in; - ss.write((const char*)&index, sizeof(uint32)); + ob.write((const char*)&index, sizeof(uint32)); - SerializeItem(ss, sub, SubSlotNumber, (depth + 1), packet_type); + SerializeItem(ob, sub, SubSlotNumber, (depth + 1), packet_type); ++subitem_count; } - if (subitem_count) { - std::stringstream::pos_type cur_pos = ss.tellp(); - ss.seekp(count_pos); - - ss.write((const char*)&subitem_count, sizeof(uint32)); - - ss.seekp(cur_pos); - } + if (subitem_count) + ob.overwrite(count_pos, (const char*)&subitem_count, sizeof(uint32)); } static inline structs::InventorySlot_Struct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType) diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 9902447b8..b3c5d50d8 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -22,7 +22,7 @@ namespace SoD static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToSoDSlot(uint32 ServerSlot); @@ -361,25 +361,22 @@ namespace SoD InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)&item_count, sizeof(uint32)); + ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -1023,30 +1020,24 @@ namespace SoD //store away the emu struct uchar* __emu_buffer = in->pBuffer; - //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -3540,7 +3531,7 @@ namespace SoD return NextItemInstSerialNumber; } - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const Item_Struct *item = inst->GetUnscaledItem(); @@ -3569,19 +3560,19 @@ namespace SoD hdr.unknown062 = 0; hdr.ItemClass = item->ItemClass; - ss.write((const char*)&hdr, sizeof(SoD::structs::ItemSerializationHeader)); + ob.write((const char*)&hdr, sizeof(SoD::structs::ItemSerializationHeader)); if (strlen(item->Name) > 0) - ss.write(item->Name, strlen(item->Name)); - ss.write("\0", 1); + ob.write(item->Name, strlen(item->Name)); + ob.write("\0", 1); if (strlen(item->Lore) > 0) - ss.write(item->Lore, strlen(item->Lore)); - ss.write("\0", 1); + ob.write(item->Lore, strlen(item->Lore)); + ob.write("\0", 1); if (strlen(item->IDFile) > 0) - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write("\0", 1); + ob.write(item->IDFile, strlen(item->IDFile)); + ob.write("\0", 1); SoD::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(SoD::structs::ItemBodyStruct)); @@ -3670,12 +3661,12 @@ namespace SoD ibs.FactionAmt4 = item->FactionAmt4; ibs.FactionMod4 = item->FactionMod4; - ss.write((const char*)&ibs, sizeof(SoD::structs::ItemBodyStruct)); + ob.write((const char*)&ibs, sizeof(SoD::structs::ItemBodyStruct)); //charm text if (strlen(item->CharmFile) > 0) - ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write("\0", 1); + ob.write((const char*)item->CharmFile, strlen(item->CharmFile)); + ob.write("\0", 1); SoD::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(SoD::structs::ItemSecondaryBodyStruct)); @@ -3703,11 +3694,11 @@ namespace SoD isbs.book = item->Book; isbs.booktype = item->BookType; - ss.write((const char*)&isbs, sizeof(SoD::structs::ItemSecondaryBodyStruct)); + ob.write((const char*)&isbs, sizeof(SoD::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write("\0", 1); + ob.write((const char*)item->Filename, strlen(item->Filename)); + ob.write("\0", 1); SoD::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(SoD::structs::ItemTertiaryBodyStruct)); @@ -3731,7 +3722,7 @@ namespace SoD itbs.no_transfer = item->NoTransfer; itbs.expendablearrow = item->ExpendableArrow; - ss.write((const char*)&itbs, sizeof(SoD::structs::ItemTertiaryBodyStruct)); + ob.write((const char*)&itbs, sizeof(SoD::structs::ItemTertiaryBodyStruct)); // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; @@ -3748,13 +3739,13 @@ namespace SoD ices.recast = item->RecastDelay; ices.recast_type = item->RecastType; - ss.write((const char*)&ices, sizeof(SoD::structs::ClickEffectStruct)); + ob.write((const char*)&ices, sizeof(SoD::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write("\0", 1); + ob.write((const char*)item->ClickName, strlen(item->ClickName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + ob.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 SoD::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(SoD::structs::ProcEffectStruct)); @@ -3765,13 +3756,13 @@ namespace SoD ipes.level = item->Proc.Level; ipes.procrate = item->ProcRate; - ss.write((const char*)&ipes, sizeof(SoD::structs::ProcEffectStruct)); + ob.write((const char*)&ipes, sizeof(SoD::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write("\0", 1); + ob.write((const char*)item->ProcName, strlen(item->ProcName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 SoD::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(SoD::structs::WornEffectStruct)); @@ -3781,13 +3772,13 @@ namespace SoD iwes.type = item->Worn.Type; iwes.level = item->Worn.Level; - ss.write((const char*)&iwes, sizeof(SoD::structs::WornEffectStruct)); + ob.write((const char*)&iwes, sizeof(SoD::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write("\0", 1); + ob.write((const char*)item->WornName, strlen(item->WornName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 SoD::structs::WornEffectStruct ifes; memset(&ifes, 0, sizeof(SoD::structs::WornEffectStruct)); @@ -3797,13 +3788,13 @@ namespace SoD ifes.type = item->Focus.Type; ifes.level = item->Focus.Level; - ss.write((const char*)&ifes, sizeof(SoD::structs::WornEffectStruct)); + ob.write((const char*)&ifes, sizeof(SoD::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write("\0", 1); + ob.write((const char*)item->FocusName, strlen(item->FocusName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 SoD::structs::WornEffectStruct ises; memset(&ises, 0, sizeof(SoD::structs::WornEffectStruct)); @@ -3813,13 +3804,13 @@ namespace SoD ises.type = item->Scroll.Type; ises.level = item->Scroll.Level; - ss.write((const char*)&ises, sizeof(SoD::structs::WornEffectStruct)); + ob.write((const char*)&ises, sizeof(SoD::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write("\0", 1); + ob.write((const char*)item->ScrollName, strlen(item->ScrollName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects SoD::structs::ItemQuaternaryBodyStruct iqbs; @@ -3849,12 +3840,12 @@ namespace SoD iqbs.SpellDmg = item->SpellDmg; iqbs.Clairvoyance = item->Clairvoyance; - ss.write((const char*)&iqbs, sizeof(SoD::structs::ItemQuaternaryBodyStruct)); + ob.write((const char*)&iqbs, sizeof(SoD::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ss.tellp(); + std::stringstream::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; - ss.write((const char*)&subitem_count, sizeof(uint32)); + ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { ItemInst* sub = inst->GetItem(index); @@ -3871,20 +3862,14 @@ namespace SoD else SubSlotNumber = slot_id_in; - ss.write((const char*)&index, sizeof(uint32)); + ob.write((const char*)&index, sizeof(uint32)); - SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + SerializeItem(ob, sub, SubSlotNumber, (depth + 1)); ++subitem_count; } - if (subitem_count) { - std::stringstream::pos_type cur_pos = ss.tellp(); - ss.seekp(count_pos); - - ss.write((const char*)&subitem_count, sizeof(uint32)); - - ss.seekp(cur_pos); - } + if (subitem_count) + ob.overwrite(count_pos, (const char*)&subitem_count, sizeof(uint32)); } static inline uint32 ServerToSoDSlot(uint32 serverSlot) diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index e2526cb45..32383d4e9 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -22,7 +22,7 @@ namespace SoF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToSoFSlot(uint32 serverSlot); @@ -343,25 +343,22 @@ namespace SoF InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)&item_count, sizeof(uint32)); + ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -823,30 +820,24 @@ namespace SoF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -2865,7 +2856,7 @@ namespace SoF return NextItemInstSerialNumber; } - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const Item_Struct *item = inst->GetUnscaledItem(); @@ -2893,19 +2884,19 @@ namespace SoF hdr.unknown061 = 0; hdr.ItemClass = item->ItemClass; - ss.write((const char*)&hdr, sizeof(SoF::structs::ItemSerializationHeader)); + ob.write((const char*)&hdr, sizeof(SoF::structs::ItemSerializationHeader)); if (strlen(item->Name) > 0) - ss.write(item->Name, strlen(item->Name)); - ss.write("\0", 1); + ob.write(item->Name, strlen(item->Name)); + ob.write("\0", 1); if (strlen(item->Lore) > 0) - ss.write(item->Lore, strlen(item->Lore)); - ss.write("\0", 1); + ob.write(item->Lore, strlen(item->Lore)); + ob.write("\0", 1); if (strlen(item->IDFile) > 0) - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write("\0", 1); + ob.write(item->IDFile, strlen(item->IDFile)); + ob.write("\0", 1); SoF::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(SoF::structs::ItemBodyStruct)); @@ -2994,12 +2985,12 @@ namespace SoF ibs.FactionAmt4 = item->FactionAmt4; ibs.FactionMod4 = item->FactionMod4; - ss.write((const char*)&ibs, sizeof(SoF::structs::ItemBodyStruct)); + ob.write((const char*)&ibs, sizeof(SoF::structs::ItemBodyStruct)); //charm text if (strlen(item->CharmFile) > 0) - ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write("\0", 1); + ob.write((const char*)item->CharmFile, strlen(item->CharmFile)); + ob.write("\0", 1); SoF::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(SoF::structs::ItemSecondaryBodyStruct)); @@ -3027,11 +3018,11 @@ namespace SoF isbs.book = item->Book; isbs.booktype = item->BookType; - ss.write((const char*)&isbs, sizeof(SoF::structs::ItemSecondaryBodyStruct)); + ob.write((const char*)&isbs, sizeof(SoF::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write("\0", 1); + ob.write((const char*)item->Filename, strlen(item->Filename)); + ob.write("\0", 1); SoF::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(SoF::structs::ItemTertiaryBodyStruct)); @@ -3055,7 +3046,7 @@ namespace SoF itbs.no_transfer = item->NoTransfer; itbs.expendablearrow = item->ExpendableArrow; - ss.write((const char*)&itbs, sizeof(SoF::structs::ItemTertiaryBodyStruct)); + ob.write((const char*)&itbs, sizeof(SoF::structs::ItemTertiaryBodyStruct)); // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; @@ -3072,13 +3063,13 @@ namespace SoF ices.recast = item->RecastDelay; ices.recast_type = item->RecastType; - ss.write((const char*)&ices, sizeof(SoF::structs::ClickEffectStruct)); + ob.write((const char*)&ices, sizeof(SoF::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write("\0", 1); + ob.write((const char*)item->ClickName, strlen(item->ClickName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + ob.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 SoF::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(SoF::structs::ProcEffectStruct)); @@ -3089,13 +3080,13 @@ namespace SoF ipes.level = item->Proc.Level; ipes.procrate = item->ProcRate; - ss.write((const char*)&ipes, sizeof(SoF::structs::ProcEffectStruct)); + ob.write((const char*)&ipes, sizeof(SoF::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write("\0", 1); + ob.write((const char*)item->ProcName, strlen(item->ProcName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 SoF::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(SoF::structs::WornEffectStruct)); @@ -3105,13 +3096,13 @@ namespace SoF iwes.type = item->Worn.Type; iwes.level = item->Worn.Level; - ss.write((const char*)&iwes, sizeof(SoF::structs::WornEffectStruct)); + ob.write((const char*)&iwes, sizeof(SoF::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write("\0", 1); + ob.write((const char*)item->WornName, strlen(item->WornName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 SoF::structs::WornEffectStruct ifes; memset(&ifes, 0, sizeof(SoF::structs::WornEffectStruct)); @@ -3121,13 +3112,13 @@ namespace SoF ifes.type = item->Focus.Type; ifes.level = item->Focus.Level; - ss.write((const char*)&ifes, sizeof(SoF::structs::WornEffectStruct)); + ob.write((const char*)&ifes, sizeof(SoF::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write("\0", 1); + ob.write((const char*)item->FocusName, strlen(item->FocusName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 SoF::structs::WornEffectStruct ises; memset(&ises, 0, sizeof(SoF::structs::WornEffectStruct)); @@ -3137,13 +3128,13 @@ namespace SoF ises.type = item->Scroll.Type; ises.level = item->Scroll.Level; - ss.write((const char*)&ises, sizeof(SoF::structs::WornEffectStruct)); + ob.write((const char*)&ises, sizeof(SoF::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write("\0", 1); + ob.write((const char*)item->ScrollName, strlen(item->ScrollName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects SoF::structs::ItemQuaternaryBodyStruct iqbs; @@ -3172,12 +3163,12 @@ namespace SoF iqbs.HealAmt = item->HealAmt; iqbs.SpellDmg = item->SpellDmg; - ss.write((const char*)&iqbs, sizeof(SoF::structs::ItemQuaternaryBodyStruct)); + ob.write((const char*)&iqbs, sizeof(SoF::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ss.tellp(); + std::stringstream::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; - ss.write((const char*)&subitem_count, sizeof(uint32)); + ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { ItemInst* sub = inst->GetItem(index); @@ -3194,20 +3185,14 @@ namespace SoF else SubSlotNumber = slot_id_in; - ss.write((const char*)&index, sizeof(uint32)); + ob.write((const char*)&index, sizeof(uint32)); - SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + SerializeItem(ob, sub, SubSlotNumber, (depth + 1)); ++subitem_count; } - if (subitem_count) { - std::stringstream::pos_type cur_pos = ss.tellp(); - ss.seekp(count_pos); - - ss.write((const char*)&subitem_count, sizeof(uint32)); - - ss.seekp(cur_pos); - } + if (subitem_count) + ob.overwrite(count_pos, (const char*)&subitem_count, sizeof(uint32)); } static inline uint32 ServerToSoFSlot(uint32 serverSlot) diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index cdfbf0250..b3a27cb7b 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -20,7 +20,7 @@ namespace Titanium static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth); // server to client inventory location converters static inline int16 ServerToTitaniumSlot(uint32 serverSlot); @@ -272,26 +272,24 @@ namespace Titanium delete in; return; } + InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; //do the transform... - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); for (int r = 0; r < itemcount; r++, eq++) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -720,30 +718,24 @@ namespace Titanium //store away the emu struct uchar* __emu_buffer = in->pBuffer; - //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); + in->size = ob.size(); + in->pBuffer = ob.detach(); - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -2083,241 +2075,241 @@ namespace Titanium } // file scope helper methods - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const char* protection = "\\\\\\\\\\"; const Item_Struct* item = inst->GetUnscaledItem(); - ss << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; + ob << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; // Instance data - ss << itoa((inst->IsStackable() ? inst->GetCharges() : 0)); // stack count - ss << '|' << itoa(0); // unknown - ss << '|' << itoa((!inst->GetMerchantSlot() ? slot_id_in : inst->GetMerchantSlot())); // inst slot/merchant slot - ss << '|' << itoa(inst->GetPrice()); // merchant price - ss << '|' << itoa((!inst->GetMerchantSlot() ? 1 : inst->GetMerchantCount())); // inst count/merchant count - ss << '|' << itoa((inst->IsScaling() ? (inst->GetExp() / 100) : 0)); // inst experience - ss << '|' << itoa((!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot())); // merchant serial number - ss << '|' << itoa(inst->GetRecastTimestamp()); // recast timestamp - ss << '|' << itoa(((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges()))); // charge count - ss << '|' << itoa((inst->IsAttuned() ? 1 : 0)); // inst attuned - ss << '|' << itoa(0); // unknown - ss << '|'; + ob << itoa((inst->IsStackable() ? inst->GetCharges() : 0)); // stack count + ob << '|' << itoa(0); // unknown + ob << '|' << itoa((!inst->GetMerchantSlot() ? slot_id_in : inst->GetMerchantSlot())); // inst slot/merchant slot + ob << '|' << itoa(inst->GetPrice()); // merchant price + ob << '|' << itoa((!inst->GetMerchantSlot() ? 1 : inst->GetMerchantCount())); // inst count/merchant count + ob << '|' << itoa((inst->IsScaling() ? (inst->GetExp() / 100) : 0)); // inst experience + ob << '|' << itoa((!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot())); // merchant serial number + ob << '|' << itoa(inst->GetRecastTimestamp()); // recast timestamp + ob << '|' << itoa(((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges()))); // charge count + ob << '|' << itoa((inst->IsAttuned() ? 1 : 0)); // inst attuned + ob << '|' << itoa(0); // unknown + ob << '|'; - ss << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data + ob << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data // Item data - ss << itoa(item->ItemClass); - ss << '|' << item->Name; - ss << '|' << item->Lore; - ss << '|' << item->IDFile; - ss << '|' << itoa(item->ID); - ss << '|' << itoa(((item->Weight > 255) ? 255 : item->Weight)); + ob << itoa(item->ItemClass); + ob << '|' << item->Name; + ob << '|' << item->Lore; + ob << '|' << item->IDFile; + ob << '|' << itoa(item->ID); + ob << '|' << itoa(((item->Weight > 255) ? 255 : item->Weight)); - ss << '|' << itoa(item->NoRent); - ss << '|' << itoa(item->NoDrop); - ss << '|' << itoa(item->Size); - ss << '|' << itoa(item->Slots); - ss << '|' << itoa(item->Price); - ss << '|' << itoa(item->Icon); - ss << '|' << "0"; - ss << '|' << "0"; - ss << '|' << itoa(item->BenefitFlag); - ss << '|' << itoa(item->Tradeskills); + ob << '|' << itoa(item->NoRent); + ob << '|' << itoa(item->NoDrop); + ob << '|' << itoa(item->Size); + ob << '|' << itoa(item->Slots); + ob << '|' << itoa(item->Price); + ob << '|' << itoa(item->Icon); + ob << '|' << "0"; + ob << '|' << "0"; + ob << '|' << itoa(item->BenefitFlag); + ob << '|' << itoa(item->Tradeskills); - ss << '|' << itoa(item->CR); - ss << '|' << itoa(item->DR); - ss << '|' << itoa(item->PR); - ss << '|' << itoa(item->MR); - ss << '|' << itoa(item->FR); + ob << '|' << itoa(item->CR); + ob << '|' << itoa(item->DR); + ob << '|' << itoa(item->PR); + ob << '|' << itoa(item->MR); + ob << '|' << itoa(item->FR); - ss << '|' << itoa(item->AStr); - ss << '|' << itoa(item->ASta); - ss << '|' << itoa(item->AAgi); - ss << '|' << itoa(item->ADex); - ss << '|' << itoa(item->ACha); - ss << '|' << itoa(item->AInt); - ss << '|' << itoa(item->AWis); + ob << '|' << itoa(item->AStr); + ob << '|' << itoa(item->ASta); + ob << '|' << itoa(item->AAgi); + ob << '|' << itoa(item->ADex); + ob << '|' << itoa(item->ACha); + ob << '|' << itoa(item->AInt); + ob << '|' << itoa(item->AWis); - ss << '|' << itoa(item->HP); - ss << '|' << itoa(item->Mana); - ss << '|' << itoa(item->AC); - ss << '|' << itoa(item->Deity); + ob << '|' << itoa(item->HP); + ob << '|' << itoa(item->Mana); + ob << '|' << itoa(item->AC); + ob << '|' << itoa(item->Deity); - ss << '|' << itoa(item->SkillModValue); - ss << '|' << itoa(item->SkillModMax); - ss << '|' << itoa(item->SkillModType); + ob << '|' << itoa(item->SkillModValue); + ob << '|' << itoa(item->SkillModMax); + ob << '|' << itoa(item->SkillModType); - ss << '|' << itoa(item->BaneDmgRace); - ss << '|' << itoa(item->BaneDmgAmt); - ss << '|' << itoa(item->BaneDmgBody); + ob << '|' << itoa(item->BaneDmgRace); + ob << '|' << itoa(item->BaneDmgAmt); + ob << '|' << itoa(item->BaneDmgBody); - ss << '|' << itoa(item->Magic); - ss << '|' << itoa(item->CastTime_); - ss << '|' << itoa(item->ReqLevel); - ss << '|' << itoa(item->BardType); - ss << '|' << itoa(item->BardValue); - ss << '|' << itoa(item->Light); - ss << '|' << itoa(item->Delay); + ob << '|' << itoa(item->Magic); + ob << '|' << itoa(item->CastTime_); + ob << '|' << itoa(item->ReqLevel); + ob << '|' << itoa(item->BardType); + ob << '|' << itoa(item->BardValue); + ob << '|' << itoa(item->Light); + ob << '|' << itoa(item->Delay); - ss << '|' << itoa(item->RecLevel); - ss << '|' << itoa(item->RecSkill); + ob << '|' << itoa(item->RecLevel); + ob << '|' << itoa(item->RecSkill); - ss << '|' << itoa(item->ElemDmgType); - ss << '|' << itoa(item->ElemDmgAmt); + ob << '|' << itoa(item->ElemDmgType); + ob << '|' << itoa(item->ElemDmgAmt); - ss << '|' << itoa(item->Range); - ss << '|' << itoa(item->Damage); + ob << '|' << itoa(item->Range); + ob << '|' << itoa(item->Damage); - ss << '|' << itoa(item->Color); - ss << '|' << itoa(item->Classes); - ss << '|' << itoa(item->Races); - ss << '|' << "0"; + ob << '|' << itoa(item->Color); + ob << '|' << itoa(item->Classes); + ob << '|' << itoa(item->Races); + ob << '|' << "0"; - ss << '|' << itoa(item->MaxCharges); - ss << '|' << itoa(item->ItemType); - ss << '|' << itoa(item->Material); - ss << '|' << StringFormat("%f", item->SellRate); + ob << '|' << itoa(item->MaxCharges); + ob << '|' << itoa(item->ItemType); + ob << '|' << itoa(item->Material); + ob << '|' << StringFormat("%f", item->SellRate); - ss << '|' << "0"; - ss << '|' << itoa(item->CastTime_); - ss << '|' << "0"; + ob << '|' << "0"; + ob << '|' << itoa(item->CastTime_); + ob << '|' << "0"; - ss << '|' << itoa(item->ProcRate); - ss << '|' << itoa(item->CombatEffects); - ss << '|' << itoa(item->Shielding); - ss << '|' << itoa(item->StunResist); - ss << '|' << itoa(item->StrikeThrough); - ss << '|' << itoa(item->ExtraDmgSkill); - ss << '|' << itoa(item->ExtraDmgAmt); - ss << '|' << itoa(item->SpellShield); - ss << '|' << itoa(item->Avoidance); - ss << '|' << itoa(item->Accuracy); + ob << '|' << itoa(item->ProcRate); + ob << '|' << itoa(item->CombatEffects); + ob << '|' << itoa(item->Shielding); + ob << '|' << itoa(item->StunResist); + ob << '|' << itoa(item->StrikeThrough); + ob << '|' << itoa(item->ExtraDmgSkill); + ob << '|' << itoa(item->ExtraDmgAmt); + ob << '|' << itoa(item->SpellShield); + ob << '|' << itoa(item->Avoidance); + ob << '|' << itoa(item->Accuracy); - ss << '|' << itoa(item->CharmFileID); + ob << '|' << itoa(item->CharmFileID); - ss << '|' << itoa(item->FactionMod1); - ss << '|' << itoa(item->FactionMod2); - ss << '|' << itoa(item->FactionMod3); - ss << '|' << itoa(item->FactionMod4); + ob << '|' << itoa(item->FactionMod1); + ob << '|' << itoa(item->FactionMod2); + ob << '|' << itoa(item->FactionMod3); + ob << '|' << itoa(item->FactionMod4); - ss << '|' << itoa(item->FactionAmt1); - ss << '|' << itoa(item->FactionAmt2); - ss << '|' << itoa(item->FactionAmt3); - ss << '|' << itoa(item->FactionAmt4); + ob << '|' << itoa(item->FactionAmt1); + ob << '|' << itoa(item->FactionAmt2); + ob << '|' << itoa(item->FactionAmt3); + ob << '|' << itoa(item->FactionAmt4); - ss << '|' << item->CharmFile; + ob << '|' << item->CharmFile; - ss << '|' << itoa(item->AugType); + ob << '|' << itoa(item->AugType); - ss << '|' << itoa(item->AugSlotType[0]); - ss << '|' << itoa(item->AugSlotVisible[0]); - ss << '|' << itoa(item->AugSlotType[1]); - ss << '|' << itoa(item->AugSlotVisible[1]); - ss << '|' << itoa(item->AugSlotType[2]); - ss << '|' << itoa(item->AugSlotVisible[2]); - ss << '|' << itoa(item->AugSlotType[3]); - ss << '|' << itoa(item->AugSlotVisible[3]); - ss << '|' << itoa(item->AugSlotType[4]); - ss << '|' << itoa(item->AugSlotVisible[4]); + ob << '|' << itoa(item->AugSlotType[0]); + ob << '|' << itoa(item->AugSlotVisible[0]); + ob << '|' << itoa(item->AugSlotType[1]); + ob << '|' << itoa(item->AugSlotVisible[1]); + ob << '|' << itoa(item->AugSlotType[2]); + ob << '|' << itoa(item->AugSlotVisible[2]); + ob << '|' << itoa(item->AugSlotType[3]); + ob << '|' << itoa(item->AugSlotVisible[3]); + ob << '|' << itoa(item->AugSlotType[4]); + ob << '|' << itoa(item->AugSlotVisible[4]); - ss << '|' << itoa(item->LDoNTheme); - ss << '|' << itoa(item->LDoNPrice); - ss << '|' << itoa(item->LDoNSold); + ob << '|' << itoa(item->LDoNTheme); + ob << '|' << itoa(item->LDoNPrice); + ob << '|' << itoa(item->LDoNSold); - ss << '|' << itoa(item->BagType); - ss << '|' << itoa(item->BagSlots); - ss << '|' << itoa(item->BagSize); - ss << '|' << itoa(item->BagWR); + ob << '|' << itoa(item->BagType); + ob << '|' << itoa(item->BagSlots); + ob << '|' << itoa(item->BagSize); + ob << '|' << itoa(item->BagWR); - ss << '|' << itoa(item->Book); - ss << '|' << itoa(item->BookType); + ob << '|' << itoa(item->Book); + ob << '|' << itoa(item->BookType); - ss << '|' << item->Filename; + ob << '|' << item->Filename; - ss << '|' << itoa(item->BaneDmgRaceAmt); - ss << '|' << itoa(item->AugRestrict); - ss << '|' << itoa(item->LoreGroup); - ss << '|' << itoa(item->PendingLoreFlag); - ss << '|' << itoa(item->ArtifactFlag); - ss << '|' << itoa(item->SummonedFlag); + ob << '|' << itoa(item->BaneDmgRaceAmt); + ob << '|' << itoa(item->AugRestrict); + ob << '|' << itoa(item->LoreGroup); + ob << '|' << itoa(item->PendingLoreFlag); + ob << '|' << itoa(item->ArtifactFlag); + ob << '|' << itoa(item->SummonedFlag); - ss << '|' << itoa(item->Favor); - ss << '|' << itoa(item->FVNoDrop); - ss << '|' << itoa(item->Endur); - ss << '|' << itoa(item->DotShielding); - ss << '|' << itoa(item->Attack); - ss << '|' << itoa(item->Regen); - ss << '|' << itoa(item->ManaRegen); - ss << '|' << itoa(item->EnduranceRegen); - ss << '|' << itoa(item->Haste); - ss << '|' << itoa(item->DamageShield); - ss << '|' << itoa(item->RecastDelay); - ss << '|' << itoa(item->RecastType); - ss << '|' << itoa(item->GuildFavor); + ob << '|' << itoa(item->Favor); + ob << '|' << itoa(item->FVNoDrop); + ob << '|' << itoa(item->Endur); + ob << '|' << itoa(item->DotShielding); + ob << '|' << itoa(item->Attack); + ob << '|' << itoa(item->Regen); + ob << '|' << itoa(item->ManaRegen); + ob << '|' << itoa(item->EnduranceRegen); + ob << '|' << itoa(item->Haste); + ob << '|' << itoa(item->DamageShield); + ob << '|' << itoa(item->RecastDelay); + ob << '|' << itoa(item->RecastType); + ob << '|' << itoa(item->GuildFavor); - ss << '|' << itoa(item->AugDistiller); + ob << '|' << itoa(item->AugDistiller); - ss << '|' << "0"; // unknown - ss << '|' << "0"; // unknown - ss << '|' << itoa(item->Attuneable); - ss << '|' << itoa(item->NoPet); - ss << '|' << "0"; // unknown - ss << '|' << itoa(item->PointType); + ob << '|' << "0"; // unknown + ob << '|' << "0"; // unknown + ob << '|' << itoa(item->Attuneable); + ob << '|' << itoa(item->NoPet); + ob << '|' << "0"; // unknown + ob << '|' << itoa(item->PointType); - ss << '|' << itoa(item->PotionBelt); - ss << '|' << itoa(item->PotionBeltSlots); - ss << '|' << itoa(item->StackSize); - ss << '|' << itoa(item->NoTransfer); - ss << '|' << itoa(item->Stackable); + ob << '|' << itoa(item->PotionBelt); + ob << '|' << itoa(item->PotionBeltSlots); + ob << '|' << itoa(item->StackSize); + ob << '|' << itoa(item->NoTransfer); + ob << '|' << itoa(item->Stackable); - ss << '|' << itoa(item->Click.Effect); - ss << '|' << itoa(item->Click.Type); - ss << '|' << itoa(item->Click.Level2); - ss << '|' << itoa(item->Click.Level); - ss << '|' << "0"; // Click name + ob << '|' << itoa(item->Click.Effect); + ob << '|' << itoa(item->Click.Type); + ob << '|' << itoa(item->Click.Level2); + ob << '|' << itoa(item->Click.Level); + ob << '|' << "0"; // Click name - ss << '|' << itoa(item->Proc.Effect); - ss << '|' << itoa(item->Proc.Type); - ss << '|' << itoa(item->Proc.Level2); - ss << '|' << itoa(item->Proc.Level); - ss << '|' << "0"; // Proc name + ob << '|' << itoa(item->Proc.Effect); + ob << '|' << itoa(item->Proc.Type); + ob << '|' << itoa(item->Proc.Level2); + ob << '|' << itoa(item->Proc.Level); + ob << '|' << "0"; // Proc name - ss << '|' << itoa(item->Worn.Effect); - ss << '|' << itoa(item->Worn.Type); - ss << '|' << itoa(item->Worn.Level2); - ss << '|' << itoa(item->Worn.Level); - ss << '|' << "0"; // Worn name + ob << '|' << itoa(item->Worn.Effect); + ob << '|' << itoa(item->Worn.Type); + ob << '|' << itoa(item->Worn.Level2); + ob << '|' << itoa(item->Worn.Level); + ob << '|' << "0"; // Worn name - ss << '|' << itoa(item->Focus.Effect); - ss << '|' << itoa(item->Focus.Type); - ss << '|' << itoa(item->Focus.Level2); - ss << '|' << itoa(item->Focus.Level); - ss << '|' << "0"; // Focus name + ob << '|' << itoa(item->Focus.Effect); + ob << '|' << itoa(item->Focus.Type); + ob << '|' << itoa(item->Focus.Level2); + ob << '|' << itoa(item->Focus.Level); + ob << '|' << "0"; // Focus name - ss << '|' << itoa(item->Scroll.Effect); - ss << '|' << itoa(item->Scroll.Type); - ss << '|' << itoa(item->Scroll.Level2); - ss << '|' << itoa(item->Scroll.Level); - ss << '|' << "0"; // Scroll name + ob << '|' << itoa(item->Scroll.Effect); + ob << '|' << itoa(item->Scroll.Type); + ob << '|' << itoa(item->Scroll.Level2); + ob << '|' << itoa(item->Scroll.Level); + ob << '|' << "0"; // Scroll name - ss << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data + ob << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data // Sub data for (int index = SUB_INDEX_BEGIN; index < consts::ITEM_CONTAINER_SIZE; ++index) { - ss << '|'; + ob << '|'; ItemInst* sub = inst->GetItem(index); if (!sub) continue; - SerializeItem(ss, sub, 0, (depth + 1)); + SerializeItem(ob, sub, 0, (depth + 1)); } - ss << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For trailing quotes (and protection) if a subitem; + ob << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For trailing quotes (and protection) if a subitem; if (!depth) - ss.write("\0", 1); + ob.write("\0", 1); } static inline int16 ServerToTitaniumSlot(uint32 serverSlot) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index f864172bd..24b4b6cba 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -22,7 +22,7 @@ namespace UF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToUFSlot(uint32 serverSlot); @@ -499,25 +499,22 @@ namespace UF InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)&item_count, sizeof(uint32)); + ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -1249,30 +1246,24 @@ namespace UF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -3815,7 +3806,7 @@ namespace UF return NextItemInstSerialNumber; } - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const Item_Struct *item = inst->GetUnscaledItem(); @@ -3840,7 +3831,7 @@ namespace UF hdr.unknown052 = 0; hdr.isEvolving = item->EvolvingItem; - ss.write((const char*)&hdr, sizeof(UF::structs::ItemSerializationHeader)); + ob.write((const char*)&hdr, sizeof(UF::structs::ItemSerializationHeader)); if (item->EvolvingItem > 0) { UF::structs::EvolvingItem evotop; @@ -3854,7 +3845,7 @@ namespace UF evotop.Activated = 1; evotop.evomaxlevel = item->EvolvingMax; - ss.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem)); + ob.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem)); } //ORNAMENT IDFILE / ICON - @@ -3864,15 +3855,15 @@ namespace UF const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); ornaIcon = aug_weap->Icon; - ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); + ob.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); } else if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { ornaIcon = inst->GetOrnamentationIcon(); char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); - ss.write(tmp, strlen(tmp)); + ob.write(tmp, strlen(tmp)); } - ss.write("\0", 1); + ob.write("\0", 1); UF::structs::ItemSerializationHeaderFinish hdrf; @@ -3882,19 +3873,19 @@ namespace UF hdrf.isCopied = 0; //Flag for item to be 'Copied' hdrf.ItemClass = item->ItemClass; - ss.write((const char*)&hdrf, sizeof(UF::structs::ItemSerializationHeaderFinish)); + ob.write((const char*)&hdrf, sizeof(UF::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) - ss.write(item->Name, strlen(item->Name)); - ss.write("\0", 1); + ob.write(item->Name, strlen(item->Name)); + ob.write("\0", 1); if (strlen(item->Lore) > 0) - ss.write(item->Lore, strlen(item->Lore)); - ss.write("\0", 1); + ob.write(item->Lore, strlen(item->Lore)); + ob.write("\0", 1); if (strlen(item->IDFile) > 0) - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write("\0", 1); + ob.write(item->IDFile, strlen(item->IDFile)); + ob.write("\0", 1); UF::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(UF::structs::ItemBodyStruct)); @@ -3983,12 +3974,12 @@ namespace UF ibs.FactionAmt4 = item->FactionAmt4; ibs.FactionMod4 = item->FactionMod4; - ss.write((const char*)&ibs, sizeof(UF::structs::ItemBodyStruct)); + ob.write((const char*)&ibs, sizeof(UF::structs::ItemBodyStruct)); //charm text if (strlen(item->CharmFile) > 0) - ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write("\0", 1); + ob.write((const char*)item->CharmFile, strlen(item->CharmFile)); + ob.write("\0", 1); UF::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(UF::structs::ItemSecondaryBodyStruct)); @@ -4016,11 +4007,11 @@ namespace UF isbs.book = item->Book; isbs.booktype = item->BookType; - ss.write((const char*)&isbs, sizeof(UF::structs::ItemSecondaryBodyStruct)); + ob.write((const char*)&isbs, sizeof(UF::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write("\0", 1); + ob.write((const char*)item->Filename, strlen(item->Filename)); + ob.write("\0", 1); UF::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(UF::structs::ItemTertiaryBodyStruct)); @@ -4044,7 +4035,7 @@ namespace UF itbs.no_transfer = item->NoTransfer; itbs.expendablearrow = item->ExpendableArrow; - ss.write((const char*)&itbs, sizeof(UF::structs::ItemTertiaryBodyStruct)); + ob.write((const char*)&itbs, sizeof(UF::structs::ItemTertiaryBodyStruct)); // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; @@ -4061,13 +4052,13 @@ namespace UF ices.recast = item->RecastDelay; ices.recast_type = item->RecastType; - ss.write((const char*)&ices, sizeof(UF::structs::ClickEffectStruct)); + ob.write((const char*)&ices, sizeof(UF::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write("\0", 1); + ob.write((const char*)item->ClickName, strlen(item->ClickName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + ob.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 UF::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(UF::structs::ProcEffectStruct)); @@ -4078,13 +4069,13 @@ namespace UF ipes.level = item->Proc.Level; ipes.procrate = item->ProcRate; - ss.write((const char*)&ipes, sizeof(UF::structs::ProcEffectStruct)); + ob.write((const char*)&ipes, sizeof(UF::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write("\0", 1); + ob.write((const char*)item->ProcName, strlen(item->ProcName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 UF::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(UF::structs::WornEffectStruct)); @@ -4094,13 +4085,13 @@ namespace UF iwes.type = item->Worn.Type; iwes.level = item->Worn.Level; - ss.write((const char*)&iwes, sizeof(UF::structs::WornEffectStruct)); + ob.write((const char*)&iwes, sizeof(UF::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write("\0", 1); + ob.write((const char*)item->WornName, strlen(item->WornName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 UF::structs::WornEffectStruct ifes; memset(&ifes, 0, sizeof(UF::structs::WornEffectStruct)); @@ -4110,13 +4101,13 @@ namespace UF ifes.type = item->Focus.Type; ifes.level = item->Focus.Level; - ss.write((const char*)&ifes, sizeof(UF::structs::WornEffectStruct)); + ob.write((const char*)&ifes, sizeof(UF::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write("\0", 1); + ob.write((const char*)item->FocusName, strlen(item->FocusName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 UF::structs::WornEffectStruct ises; memset(&ises, 0, sizeof(UF::structs::WornEffectStruct)); @@ -4126,13 +4117,13 @@ namespace UF ises.type = item->Scroll.Type; ises.level = item->Scroll.Level; - ss.write((const char*)&ises, sizeof(UF::structs::WornEffectStruct)); + ob.write((const char*)&ises, sizeof(UF::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write("\0", 1); + ob.write((const char*)item->ScrollName, strlen(item->ScrollName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // Bard Effect? UF::structs::WornEffectStruct ibes; @@ -4144,18 +4135,18 @@ namespace UF ibes.level = item->Bard.Level; //ibes.unknown6 = 0xffffffff; - ss.write((const char*)&ibes, sizeof(UF::structs::WornEffectStruct)); + ob.write((const char*)&ibes, sizeof(UF::structs::WornEffectStruct)); /* if(strlen(item->BardName) > 0) { - ss.write((const char*)item->BardName, strlen(item->BardName)); - ss.write((const char*)&null_term, sizeof(uint8)); + ob.write((const char*)item->BardName, strlen(item->BardName)); + ob.write((const char*)&null_term, sizeof(uint8)); } else */ - ss.write("\0", 1); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects UF::structs::ItemQuaternaryBodyStruct iqbs; @@ -4185,12 +4176,12 @@ namespace UF iqbs.SpellDmg = item->SpellDmg; iqbs.Clairvoyance = item->Clairvoyance; - ss.write((const char*)&iqbs, sizeof(UF::structs::ItemQuaternaryBodyStruct)); + ob.write((const char*)&iqbs, sizeof(UF::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ss.tellp(); + std::stringstream::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; - ss.write((const char*)&subitem_count, sizeof(uint32)); + ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { ItemInst* sub = inst->GetItem(index); @@ -4207,20 +4198,14 @@ namespace UF else SubSlotNumber = slot_id_in; - ss.write((const char*)&index, sizeof(uint32)); + ob.write((const char*)&index, sizeof(uint32)); - SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + SerializeItem(ob, sub, SubSlotNumber, (depth + 1)); ++subitem_count; } - if (subitem_count) { - std::stringstream::pos_type cur_pos = ss.tellp(); - ss.seekp(count_pos); - - ss.write((const char*)&subitem_count, sizeof(uint32)); - - ss.seekp(cur_pos); - } + if (subitem_count) + ob.overwrite(count_pos, (const char*)&subitem_count, sizeof(uint32)); } static inline uint32 ServerToUFSlot(uint32 serverSlot) diff --git a/common/string_util.cpp b/common/string_util.cpp index e791eb7f6..96cfce310 100644 --- a/common/string_util.cpp +++ b/common/string_util.cpp @@ -415,3 +415,46 @@ void find_replace(std::string& string_subject, const std::string& search_string, index = string_subject.find_first_of(search_string); } } + + + +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +void EQEmu::OutBuffer::overwrite(OutBuffer::pos_type position, const char *_Str, std::streamsize _Count) +{ + auto last_pos = tellp(); + seekp(position); + write(_Str, _Count); + seekp(last_pos); +} + +uchar* EQEmu::OutBuffer::detach() +{ + size_t buffer_size = tellp(); + if (buffer_size == 0) + return nullptr; + + uchar* out_buffer = new uchar[buffer_size]; + memcpy(out_buffer, str().c_str(), buffer_size); + flush(); + + return out_buffer; +} diff --git a/common/string_util.h b/common/string_util.h index c69f01456..5b373a41b 100644 --- a/common/string_util.h +++ b/common/string_util.h @@ -53,4 +53,36 @@ void MakeLowerString(const char *source, char *target); void RemoveApostrophes(std::string &s); void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string); + + +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +namespace EQEmu +{ + class OutBuffer : public std::stringstream { + public: + inline size_t size() { return tellp(); } + void overwrite(OutBuffer::pos_type position, const char *_Str, std::streamsize _Count); + uchar* detach(); + }; +} + #endif diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 8c58049ab..6dcca861e 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -759,8 +759,8 @@ void Client::BulkSendInventoryItems() RemoveDuplicateLore(false); MoveSlotNotAllowed(false); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); // Possessions items for (int16 slot_id = SLOT_BEGIN; slot_id < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; slot_id++) { @@ -768,24 +768,24 @@ void Client::BulkSendInventoryItems() if (!inst) continue; - inst->Serialize(ss, slot_id); + inst->Serialize(ob, slot_id); - if (ss.tellp() == last_pos) + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } // PowerSource item if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { const ItemInst* inst = m_inv[EQEmu::legacy::SlotPowerSource]; if (inst) { - inst->Serialize(ss, EQEmu::legacy::SlotPowerSource); + inst->Serialize(ob, EQEmu::legacy::SlotPowerSource); - if (ss.tellp() == last_pos) + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", EQEmu::legacy::SlotPowerSource); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } } @@ -795,12 +795,12 @@ void Client::BulkSendInventoryItems() if (!inst) continue; - inst->Serialize(ss, slot_id); + inst->Serialize(ob, slot_id); - if (ss.tellp() == last_pos) + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } // SharedBank items @@ -809,19 +809,17 @@ void Client::BulkSendInventoryItems() if (!inst) continue; - inst->Serialize(ss, slot_id); + inst->Serialize(ob, slot_id); - if (ss.tellp() == last_pos) + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CharInventory, serialized.size()); - memcpy(outapp->pBuffer, serialized.c_str(), serialized.size()); - + EQApplicationPacket* outapp = new EQApplicationPacket(OP_CharInventory); + outapp->size = ob.size(); + outapp->pBuffer = ob.detach(); QueuePacket(outapp); safe_delete(outapp); } From d61e7446bbf66ff6e6a146aa04c18a2f4ceb4147 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 19 May 2016 07:21:10 -0400 Subject: [PATCH 098/693] Missed a couple of EQEmu::OutBuffer reference changes --- common/patches/rof.cpp | 2 +- common/patches/sod.cpp | 2 +- common/patches/sof.cpp | 2 +- common/patches/uf.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index dc57d0ba6..25927bec9 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -5579,7 +5579,7 @@ namespace RoF ob.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ob.tellp(); + EQEmu::OutBuffer::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; ob.write((const char*)&subitem_count, sizeof(uint32)); diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index b3c5d50d8..91675acf1 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -3842,7 +3842,7 @@ namespace SoD ob.write((const char*)&iqbs, sizeof(SoD::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ob.tellp(); + EQEmu::OutBuffer::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; ob.write((const char*)&subitem_count, sizeof(uint32)); diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 32383d4e9..39d5e108d 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -3165,7 +3165,7 @@ namespace SoF ob.write((const char*)&iqbs, sizeof(SoF::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ob.tellp(); + EQEmu::OutBuffer::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; ob.write((const char*)&subitem_count, sizeof(uint32)); diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 24b4b6cba..e243d0dae 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -4178,7 +4178,7 @@ namespace UF ob.write((const char*)&iqbs, sizeof(UF::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ob.tellp(); + EQEmu::OutBuffer::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; ob.write((const char*)&subitem_count, sizeof(uint32)); From 04f47f1e32558910c54780803328714fd4bd1623 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 19 May 2016 22:50:08 -0400 Subject: [PATCH 099/693] Formatting and GPL updates --- common/deity.cpp | 4 ++-- common/deity.h | 10 ++++++--- common/patches/patches.cpp | 25 ++++++++++++++++++++-- common/patches/patches.h | 26 ++++++++++++++++++++--- common/patches/rof.cpp | 24 +++++++++++++++++++-- common/patches/rof.h | 31 ++++++++++++++++++++++----- common/patches/rof2.cpp | 24 +++++++++++++++++++-- common/patches/rof2.h | 31 ++++++++++++++++++++++----- common/patches/rof2_limits.cpp | 2 +- common/patches/rof2_limits.h | 2 +- common/patches/rof2_ops.h | 20 ++++++++++++++++++ common/patches/rof2_structs.h | 34 ++++++++++++++++++++++++------ common/patches/rof_limits.cpp | 2 +- common/patches/rof_limits.h | 2 +- common/patches/rof_ops.h | 20 ++++++++++++++++++ common/patches/rof_structs.h | 34 ++++++++++++++++++++++++------ common/patches/sod.cpp | 24 +++++++++++++++++++-- common/patches/sod.h | 31 ++++++++++++++++++++++----- common/patches/sod_limits.cpp | 2 +- common/patches/sod_limits.h | 2 +- common/patches/sod_ops.h | 20 ++++++++++++++++++ common/patches/sod_structs.h | 34 ++++++++++++++++++++++++------ common/patches/sof.cpp | 24 +++++++++++++++++++-- common/patches/sof.h | 31 ++++++++++++++++++++++----- common/patches/sof_limits.cpp | 2 +- common/patches/sof_limits.h | 2 +- common/patches/sof_ops.h | 20 ++++++++++++++++++ common/patches/sof_structs.h | 34 ++++++++++++++++++++++++------ common/patches/ss_declare.h | 19 +++++++++++++++-- common/patches/ss_define.h | 18 ++++------------ common/patches/ss_register.h | 18 ++++++++++++++++ common/patches/titanium.cpp | 24 +++++++++++++++++++-- common/patches/titanium.h | 31 ++++++++++++++++++++++----- common/patches/titanium_limits.cpp | 2 +- common/patches/titanium_limits.h | 2 +- common/patches/titanium_ops.h | 20 ++++++++++++++++++ common/patches/titanium_structs.h | 34 ++++++++++++++++++++++++------ common/patches/uf.cpp | 24 +++++++++++++++++++-- common/patches/uf.h | 31 ++++++++++++++++++++++----- common/patches/uf_limits.cpp | 2 +- common/patches/uf_limits.h | 2 +- common/patches/uf_ops.h | 20 ++++++++++++++++++ common/patches/uf_structs.h | 34 ++++++++++++++++++++++++------ 43 files changed, 682 insertions(+), 116 deletions(-) diff --git a/common/deity.cpp b/common/deity.cpp index 2e76cd567..b8a2d87d7 100644 --- a/common/deity.cpp +++ b/common/deity.cpp @@ -1,5 +1,5 @@ -/* EQEMu: Everquest Server Emulator - +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify diff --git a/common/deity.h b/common/deity.h index b7a4a14b7..fa56a9d8f 100644 --- a/common/deity.h +++ b/common/deity.h @@ -1,4 +1,5 @@ /* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org) This program is free software; you can redistribute it and/or modify @@ -13,8 +14,9 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef COMMON_DEITY_H #define COMMON_DEITY_H @@ -70,7 +72,9 @@ namespace EQEmu extern DeityTypeBit ConvertDeityTypeToDeityTypeBit(DeityType deity_type); extern DeityType ConvertDeityTypeBitToDeityType(DeityTypeBit deity_type_bit); extern const char* DeityName(DeityType deity_type); - } -} + + } /*deity*/ + +} /*EQEmu*/ #endif /* COMMON_DEITY_H */ diff --git a/common/patches/patches.cpp b/common/patches/patches.cpp index 3147b89f6..775e4e3dc 100644 --- a/common/patches/patches.cpp +++ b/common/patches/patches.cpp @@ -1,3 +1,21 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ #include "../global_define.h" #include "patches.h" @@ -9,7 +27,9 @@ #include "rof.h" #include "rof2.h" -void RegisterAllPatches(EQStreamIdentifier &into) { + +void RegisterAllPatches(EQStreamIdentifier &into) +{ Titanium::Register(into); SoF::Register(into); SoD::Register(into); @@ -18,7 +38,8 @@ void RegisterAllPatches(EQStreamIdentifier &into) { RoF2::Register(into); } -void ReloadAllPatches() { +void ReloadAllPatches() +{ Titanium::Reload(); SoF::Reload(); SoD::Reload(); diff --git a/common/patches/patches.h b/common/patches/patches.h index 8383a17fa..38fd549be 100644 --- a/common/patches/patches.h +++ b/common/patches/patches.h @@ -1,5 +1,25 @@ -#ifndef PATCHES_H_ -#define PATCHES_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_PATCHES_H +#define COMMON_PATCHES_H + /*enum { Patch_062, @@ -12,4 +32,4 @@ class EQStreamIdentifier; void RegisterAllPatches(EQStreamIdentifier &into); void ReloadAllPatches(); -#endif /*PATCHES_H_*/ +#endif /*COMMON_PATCHES_H*/ diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 25927bec9..dd5113e0e 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -1,3 +1,22 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #include "../global_define.h" #include "../eqemu_logsys.h" #include "rof.h" @@ -18,6 +37,7 @@ #include #include + namespace RoF { static const char *name = "RoF"; @@ -5970,5 +5990,5 @@ namespace RoF } } } -} -// end namespace RoF + +} /*RoF*/ diff --git a/common/patches/rof.h b/common/patches/rof.h index a28293731..42d8c08ef 100644 --- a/common/patches/rof.h +++ b/common/patches/rof.h @@ -1,11 +1,32 @@ -#ifndef ROF_H_ -#define ROF_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_ROF_H +#define COMMON_ROF_H #include "../struct_strategy.h" + class EQStreamIdentifier; -namespace RoF { +namespace RoF +{ //these are the only public member of this namespace. extern void Register(EQStreamIdentifier &into); @@ -30,6 +51,6 @@ namespace RoF { #include "rof_ops.h" }; -}; +}; /*RoF*/ -#endif /*ROF_H_*/ +#endif /*COMMON_ROF_H*/ diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index a7f63abe6..e8205ba38 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1,3 +1,22 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #include "../global_define.h" #include "../eqemu_logsys.h" #include "rof2.h" @@ -18,6 +37,7 @@ #include #include + namespace RoF2 { static const char *name = "RoF2"; @@ -6255,5 +6275,5 @@ namespace RoF2 } } } -} -// end namespace RoF2 + +} /*RoF2*/ diff --git a/common/patches/rof2.h b/common/patches/rof2.h index 7b183c54e..af0b6f55d 100644 --- a/common/patches/rof2.h +++ b/common/patches/rof2.h @@ -1,11 +1,32 @@ -#ifndef ROF2_H_ -#define ROF2_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_ROF2_H +#define COMMON_ROF2_H #include "../struct_strategy.h" + class EQStreamIdentifier; -namespace RoF2 { +namespace RoF2 +{ //these are the only public member of this namespace. extern void Register(EQStreamIdentifier &into); @@ -30,6 +51,6 @@ namespace RoF2 { #include "rof2_ops.h" }; -}; +}; /*RoF2*/ -#endif /*ROF2_H_*/ +#endif /*COMMON_ROF2_H*/ diff --git a/common/patches/rof2_limits.cpp b/common/patches/rof2_limits.cpp index 3f4711d4d..93a5c7a3d 100644 --- a/common/patches/rof2_limits.cpp +++ b/common/patches/rof2_limits.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index b32d79d24..e26f19019 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index 9fe76e33c..b49784029 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -1,3 +1,23 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + // out-going packets that require an ENCODE translation: // Begin RoF2 Encodes diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 7464f22cd..e1716478e 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1,7 +1,28 @@ -#ifndef ROF2_STRUCTS_H_ -#define ROF2_STRUCTS_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -namespace RoF2 { + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_ROF2_STRUCTS_H +#define COMMON_ROF2_STRUCTS_H + + +namespace RoF2 +{ namespace structs { /* @@ -5067,7 +5088,8 @@ struct MercenaryMerchantResponse_Struct { /*0004*/ }; - }; //end namespace structs -}; //end namespace RoF2 + }; /*structs*/ -#endif /*ROF2_STRUCTS_H_*/ +}; /*RoF2*/ + +#endif /*COMMON_ROF2_STRUCTS_H*/ diff --git a/common/patches/rof_limits.cpp b/common/patches/rof_limits.cpp index 3f4711d4d..93a5c7a3d 100644 --- a/common/patches/rof_limits.cpp +++ b/common/patches/rof_limits.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index 20f38b90c..9b888d3af 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/rof_ops.h b/common/patches/rof_ops.h index 606c51c62..45221cfc5 100644 --- a/common/patches/rof_ops.h +++ b/common/patches/rof_ops.h @@ -1,3 +1,23 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + // out-going packets that require an ENCODE translation: E(OP_Action) E(OP_AdventureMerchantSell) diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index a143e32ce..d3d83fca6 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -1,7 +1,28 @@ -#ifndef ROF_STRUCTS_H_ -#define ROF_STRUCTS_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -namespace RoF { + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_ROF_STRUCTS_H +#define COMMON_ROF_STRUCTS_H + + +namespace RoF +{ namespace structs { /* @@ -5055,7 +5076,8 @@ struct MercenaryMerchantResponse_Struct { /*0004*/ }; - }; //end namespace structs -}; //end namespace RoF + }; /*structs*/ -#endif /*ROF_STRUCTS_H_*/ +}; /*RoF*/ + +#endif /*COMMON_ROF_STRUCTS_H*/ diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 91675acf1..8605bd7d4 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1,3 +1,22 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #include "../global_define.h" #include "../eqemu_logsys.h" #include "sod.h" @@ -16,6 +35,7 @@ #include #include + namespace SoD { static const char *name = "SoD"; @@ -3997,5 +4017,5 @@ namespace SoD } } } -} -// end namespace SoD + +} /*SoD*/ diff --git a/common/patches/sod.h b/common/patches/sod.h index 23eddccba..be5843ead 100644 --- a/common/patches/sod.h +++ b/common/patches/sod.h @@ -1,11 +1,32 @@ -#ifndef SOD_H_ -#define SOD_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_SOD_H +#define COMMON_SOD_H #include "../struct_strategy.h" + class EQStreamIdentifier; -namespace SoD { +namespace SoD +{ //these are the only public member of this namespace. extern void Register(EQStreamIdentifier &into); @@ -30,6 +51,6 @@ namespace SoD { #include "sod_ops.h" }; -}; +}; /*SoD*/ -#endif /*SOD_H_*/ +#endif /*COMMON_SOD_H*/ diff --git a/common/patches/sod_limits.cpp b/common/patches/sod_limits.cpp index 3f4711d4d..93a5c7a3d 100644 --- a/common/patches/sod_limits.cpp +++ b/common/patches/sod_limits.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index 83455d1e8..7a803f957 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/sod_ops.h b/common/patches/sod_ops.h index f599885c1..90c28b2eb 100644 --- a/common/patches/sod_ops.h +++ b/common/patches/sod_ops.h @@ -1,3 +1,23 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + // out-going packets that require an ENCODE translation: E(OP_Action) E(OP_AdventureMerchantSell) diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 7f1b76d52..67498f4ad 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1,7 +1,28 @@ -#ifndef SOD_STRUCTS_H_ -#define SOD_STRUCTS_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -namespace SoD { + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_SOD_STRUCTS_H +#define COMMON_SOD_STRUCTS_H + + +namespace SoD +{ namespace structs { @@ -4428,7 +4449,8 @@ struct MercenaryAssign_Struct { /*0012*/ }; - }; //end namespace structs -}; //end namespace SoD + }; /*structs*/ -#endif /*SOD_STRUCTS_H_*/ +}; /*SoD*/ + +#endif /*COMMON_SOD_STRUCTS_H*/ diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 39d5e108d..9beda55ad 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1,3 +1,22 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #include "../global_define.h" #include "../eqemu_logsys.h" #include "sof.h" @@ -16,6 +35,7 @@ #include #include + namespace SoF { static const char *name = "SoF"; @@ -3322,5 +3342,5 @@ namespace SoF } } } -} -// end namespace SoF + +} /*SoF*/ diff --git a/common/patches/sof.h b/common/patches/sof.h index 4b3a22a35..095c9dd4a 100644 --- a/common/patches/sof.h +++ b/common/patches/sof.h @@ -1,11 +1,32 @@ -#ifndef SOF_H_ -#define SOF_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_SOF_H +#define COMMON_SOF_H #include "../struct_strategy.h" + class EQStreamIdentifier; -namespace SoF { +namespace SoF +{ //these are the only public member of this namespace. extern void Register(EQStreamIdentifier &into); @@ -30,6 +51,6 @@ namespace SoF { #include "sof_ops.h" }; -}; +}; /*SoF*/ -#endif /*SOF_H_*/ +#endif /*COMMON_SOF_H*/ diff --git a/common/patches/sof_limits.cpp b/common/patches/sof_limits.cpp index 3f4711d4d..93a5c7a3d 100644 --- a/common/patches/sof_limits.cpp +++ b/common/patches/sof_limits.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 55e63db9b..48855a455 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/sof_ops.h b/common/patches/sof_ops.h index f7077f05b..01caf8674 100644 --- a/common/patches/sof_ops.h +++ b/common/patches/sof_ops.h @@ -1,3 +1,23 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + // out-going packets that require an ENCODE translation: E(OP_Action) E(OP_AdventureMerchantSell) diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 521d66477..79941cd38 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1,7 +1,28 @@ -#ifndef SOF_STRUCTS_H_ -#define SOF_STRUCTS_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -namespace SoF { + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_SOF_STRUCTS_H +#define COMMON_SOF_STRUCTS_H + + +namespace SoF +{ namespace structs { @@ -4133,7 +4154,8 @@ struct AltCurrencySellItem_Struct { /*010*/ uint32 cost; }; - }; //end namespace structs -}; //end namespace SoF + }; /*structs*/ -#endif /*SOF_STRUCTS_H_*/ +}; /*SoF*/ + +#endif /*COMMON_SOF_STRUCTS_H*/ diff --git a/common/patches/ss_declare.h b/common/patches/ss_declare.h index bc8d8f214..b4059f640 100644 --- a/common/patches/ss_declare.h +++ b/common/patches/ss_declare.h @@ -1,6 +1,21 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ #define E(x) static void Encode_##x(EQApplicationPacket **p, std::shared_ptr dest, bool ack_req); #define D(x) static void Decode_##x(EQApplicationPacket *p); - - diff --git a/common/patches/ss_define.h b/common/patches/ss_define.h index 3b2afb5b1..c5815eac8 100644 --- a/common/patches/ss_define.h +++ b/common/patches/ss_define.h @@ -1,5 +1,6 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -9,11 +10,11 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define ENCODE(x) void Strategy::Encode_##x(EQApplicationPacket **p, std::shared_ptr dest, bool ack_req) @@ -166,14 +167,3 @@ //forward this opcode to another decoder #define DECODE_FORWARD(other_op) \ Decode_##other_op(__packet); - - - - - - - - - - - diff --git a/common/patches/ss_register.h b/common/patches/ss_register.h index b9ada774c..f8613195f 100644 --- a/common/patches/ss_register.h +++ b/common/patches/ss_register.h @@ -1,3 +1,21 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ #define E(x) encoders[x] = Encode_##x; #define D(x) decoders[x] = Decode_##x; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index b3a27cb7b..57291ddd5 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1,3 +1,22 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #include "../global_define.h" #include "../eqemu_logsys.h" #include "titanium.h" @@ -14,6 +33,7 @@ #include "titanium_structs.h" #include + namespace Titanium { static const char *name = "Titanium"; @@ -2419,5 +2439,5 @@ namespace Titanium } } } -} -// end namespace Titanium + +} /*Titanium*/ diff --git a/common/patches/titanium.h b/common/patches/titanium.h index 2275c265d..eb193c872 100644 --- a/common/patches/titanium.h +++ b/common/patches/titanium.h @@ -1,11 +1,32 @@ -#ifndef TITANIUM_H_ -#define TITANIUM_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_TITANIUM_H +#define COMMON_TITANIUM_H #include "../struct_strategy.h" + class EQStreamIdentifier; -namespace Titanium { +namespace Titanium +{ //these are the only public member of this namespace. extern void Register(EQStreamIdentifier &into); @@ -30,6 +51,6 @@ namespace Titanium { #include "titanium_ops.h" }; -}; +}; /*Titanium*/ -#endif /*TITANIUM_H_*/ +#endif /*COMMON_TITANIUM_H*/ diff --git a/common/patches/titanium_limits.cpp b/common/patches/titanium_limits.cpp index 3f4711d4d..93a5c7a3d 100644 --- a/common/patches/titanium_limits.cpp +++ b/common/patches/titanium_limits.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index 2eba35b70..220ad99c7 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index 477adf140..be61ea692 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -1,3 +1,23 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + // out-going packets that require an ENCODE translation: E(OP_Action) E(OP_AdventureMerchantSell) diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 03d0ab06e..d3a382855 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -1,7 +1,28 @@ -#ifndef TITANIUM_STRUCTS_H_ -#define TITANIUM_STRUCTS_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -namespace Titanium { + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_TITANIUM_STRUCTS_H +#define COMMON_TITANIUM_STRUCTS_H + + +namespace Titanium +{ namespace structs { @@ -3512,7 +3533,8 @@ struct LFGuild_GuildToggle_Struct // char ScrollName; // '0' //}; - }; //end namespace structs -}; //end namespace Titanium + }; /*structs*/ -#endif /*TITANIUM_STRUCTS_H_*/ +}; /*Titanium*/ + +#endif /*COMMON_TITANIUM_STRUCTS_H*/ diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index e243d0dae..8563ad70c 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1,3 +1,22 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #include "../global_define.h" #include "../eqemu_logsys.h" #include "uf.h" @@ -16,6 +35,7 @@ #include #include + namespace UF { static const char *name = "UF"; @@ -4335,5 +4355,5 @@ namespace UF } } } -} -// end namespace UF + +} /*UF*/ diff --git a/common/patches/uf.h b/common/patches/uf.h index 3e0598cba..59c332bdc 100644 --- a/common/patches/uf.h +++ b/common/patches/uf.h @@ -1,11 +1,32 @@ -#ifndef UF_H_ -#define UF_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_UF_H +#define COMMON_UF_H #include "../struct_strategy.h" + class EQStreamIdentifier; -namespace UF { +namespace UF +{ //these are the only public member of this namespace. extern void Register(EQStreamIdentifier &into); @@ -30,6 +51,6 @@ namespace UF { #include "uf_ops.h" }; -}; +}; /*UF*/ -#endif /*UF_H_*/ +#endif /*COMMON_UF_H*/ diff --git a/common/patches/uf_limits.cpp b/common/patches/uf_limits.cpp index 3f4711d4d..93a5c7a3d 100644 --- a/common/patches/uf_limits.cpp +++ b/common/patches/uf_limits.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index 64880ee14..e19c6e014 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/patches/uf_ops.h b/common/patches/uf_ops.h index 7f5f500c5..2287f0cd1 100644 --- a/common/patches/uf_ops.h +++ b/common/patches/uf_ops.h @@ -1,3 +1,23 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + // out-going packets that require an ENCODE translation: E(OP_Action) E(OP_AdventureMerchantSell) diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index f6a2c5553..6c2f198bb 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1,7 +1,28 @@ -#ifndef UF_STRUCTS_H_ -#define UF_STRUCTS_H_ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) -namespace UF { + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_UF_STRUCTS_H +#define COMMON_UF_STRUCTS_H + + +namespace UF +{ namespace structs { @@ -4552,7 +4573,8 @@ struct MercenaryAssign_Struct { /*0012*/ }; - }; //end namespace structs -}; //end namespace UF + }; /*structs*/ -#endif /*UF_STRUCTS_H_*/ +}; /*UF*/ + +#endif /*COMMON_UF_STRUCTS_H*/ From ebe6f95e6e1b915f3ac03ef0e59094532179630b Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 20 May 2016 04:26:32 -0400 Subject: [PATCH 100/693] LightSourceProfile relocation and some more formatting changes --- common/client_version.cpp | 2 +- common/client_version.h | 10 +++-- common/inventory_version.cpp | 2 +- common/inventory_version.h | 10 +++-- common/light_source.cpp | 36 ++++++++-------- common/light_source.h | 81 ++++++++++++++++++++---------------- zone/bot.cpp | 3 +- zone/bot.h | 2 +- zone/client.cpp | 2 +- zone/client.h | 2 +- zone/corpse.cpp | 21 ++++------ zone/merc.cpp | 18 ++++---- zone/mob.cpp | 28 ++++++------- zone/mob.h | 16 +++---- zone/npc.cpp | 16 +++---- 15 files changed, 128 insertions(+), 121 deletions(-) diff --git a/common/client_version.cpp b/common/client_version.cpp index a9cb02a0b..b812e8744 100644 --- a/common/client_version.cpp +++ b/common/client_version.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/client_version.h b/common/client_version.h index 86d9ebcab..a04e5c10b 100644 --- a/common/client_version.h +++ b/common/client_version.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) @@ -70,7 +70,9 @@ namespace EQEmu extern uint32 ConvertClientVersionToClientVersionBit(ClientVersion client_version); extern ClientVersion ConvertClientVersionBitToClientVersion(uint32 client_version_bit); extern uint32 ConvertClientVersionToExpansion(ClientVersion client_version); - } -} + + } /*versions*/ -#endif /* COMMON_CLIENT_VERSION_H */ +} /*EQEmu*/ + +#endif /*COMMON_CLIENT_VERSION_H*/ diff --git a/common/inventory_version.cpp b/common/inventory_version.cpp index bc93e1408..13573eb68 100644 --- a/common/inventory_version.cpp +++ b/common/inventory_version.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/inventory_version.h b/common/inventory_version.h index 07ad991ff..61762e5bc 100644 --- a/common/inventory_version.h +++ b/common/inventory_version.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) @@ -55,7 +55,9 @@ namespace EQEmu extern const char* InventoryVersionName(InventoryVersion inventory_version); extern ClientVersion ConvertInventoryVersionToClientVersion(InventoryVersion inventory_version); extern InventoryVersion ConvertClientVersionToInventoryVersion(ClientVersion client_version); - } -} + + } /*versions*/ -#endif /* COMMON_INVENTORY_VERSION_H */ +} /*EQEmu*/ + +#endif /*COMMON_INVENTORY_VERSION_H*/ diff --git a/common/light_source.cpp b/common/light_source.cpp index c43395753..f3b7ab74e 100644 --- a/common/light_source.cpp +++ b/common/light_source.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) @@ -19,24 +19,8 @@ #include "light_source.h" +#include -EQEmu::lightsource::LightSourceProfile::LightSourceProfile() -{ - Clear(); -} - -void EQEmu::lightsource::LightSourceProfile::Clear() -{ - Type.Innate = 0; - Type.Equipment = 0; - Type.Spell = 0; - Type.Active = 0; - - Level.Innate = 0; - Level.Equipment = 0; - Level.Spell = 0; - Level.Active = 0; -} uint8 EQEmu::lightsource::TypeToLevel(uint8 light_type) { @@ -97,3 +81,19 @@ bool EQEmu::lightsource::IsLevelGreater(uint8 left_type, uint8 right_type) return (light_levels[left_type] > light_levels[right_type]); } + +EQEmu::lightsource::Light_Struct::Light_Struct() +{ + Clear(); +} + +void EQEmu::lightsource::Light_Struct::Clear() +{ + memset(&Slot, 0, (sizeof(uint8) * sizeof(Slot))); +} + +void EQEmu::LightSourceProfile::Clear() +{ + Type.Clear(); + Level.Clear(); +} diff --git a/common/light_source.h b/common/light_source.h index db93eaeb3..9c031712b 100644 --- a/common/light_source.h +++ b/common/light_source.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) @@ -26,6 +26,15 @@ namespace EQEmu { namespace lightsource { + enum LightSlot { + LightInnate = 0, // Defined by db field `npc_types`.`light` - where appropriate + LightEquipment, // Item_Struct::light value of worn/carried equipment + LightSpell, // Set value of any light-producing spell (can be modded to mimic equip_light behavior) + LightActive, // Highest value of all light sources + LightCount + }; + + enum LightType { LightTypeNone = 0, LightTypeCandle, @@ -61,47 +70,47 @@ namespace EQEmu LightLevelCount }; - struct LightSourceProfile { - /* - Current criteria (light types): - Equipment: { 0 .. 15 } - General: { 9 .. 13 } + struct Light_Struct { + uint8 Slot[LightCount]; - Notes: - - Initial character load and item movement updates use different light source update behaviors - -- Server procedure matches the item movement behavior since most updates occur post-character load - - MainAmmo is not considered when determining light sources - - No 'Sub' or 'Aug' items are recognized as light sources - - Light types '< 9' and '> 13' are not considered for general (carried) light sources - - If values > 0x0F are valid, then assignment limiters will need to be removed - - MainCursor 'appears' to be a valid light source update slot..but, have not experienced updates during debug sessions - - All clients have a bug regarding stackable items (light and sound updates are not processed when picking up an item) - -- The timer-based update cancels out the invalid light source - */ - LightSourceProfile(); + Light_Struct(); void Clear(); - // Light types (classifications) - struct { - uint8 Innate; // Defined by db field `npc_types`.`light` - where appropriate - uint8 Equipment; // Item_Struct::light value of worn/carried equipment - uint8 Spell; // Set value of any light-producing spell (can be modded to mimic equip_light behavior) - uint8 Active; // Highest value of all light sources - } Type; - - // Light levels (intensities) - used to determine which light source should be active - struct { - uint8 Innate; - uint8 Equipment; - uint8 Spell; - uint8 Active; - } Level; + inline uint8& operator[](LightSlot index) { return Slot[index]; } }; extern uint8 TypeToLevel(uint8 light_type); extern bool IsLevelGreater(uint8 left_type, uint8 right_type); - }; -} + + }; /*lightsource*/ -#endif /* COMMON_LIGHT_SOURCE_H */ + struct LightSourceProfile { + /* + Current criteria (light types): + Equipment: { 0 .. 15 } + General: { 9 .. 13 } + + Notes: + - Initial character load and item movement updates use different light source update behaviors + -- Server procedure matches the item movement behavior since most updates occur post-character load + - MainAmmo is not considered when determining light sources + - No 'Sub' or 'Aug' items are recognized as light sources + - Light types '< 9' and '> 13' are not considered for general (carried) light sources + - If values > 0x0F are valid, then assignment limiters will need to be removed + - MainCursor 'appears' to be a valid light source update slot..but, have not experienced updates during debug sessions + - All clients have a bug regarding stackable items (light and sound updates are not processed when picking up an item) + -- The timer-based update cancels out the invalid light source + */ + + lightsource::Light_Struct Type; // Light types (classifications) + lightsource::Light_Struct Level; // Light levels (intensities) - used to determine which light source should be active + + LightSourceProfile() { } + + void Clear(); + }; + +} /*EQEmu*/ + +#endif /*COMMON_LIGHT_SOURCE_H*/ diff --git a/zone/bot.cpp b/zone/bot.cpp index 862054037..592c7843c 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -93,7 +93,6 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm timers[i] = 0; strcpy(this->name, this->GetCleanName()); - memset(&m_Light, 0, sizeof(EQEmu::lightsource::LightSourceProfile)); memset(&_botInspectMessage, 0, sizeof(InspectMessage_Struct)); } @@ -2955,7 +2954,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.size = 0; ns->spawn.NPC = 0; // 0=player,1=npc,2=pc corpse,3=npc corpse UpdateActiveLight(); - ns->spawn.light = m_Light.Type.Active; + ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; ns->spawn.helm = helmtexture; //(GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.equip_chest2 = texture; //0xFF; const Item_Struct* item = 0; diff --git a/zone/bot.h b/zone/bot.h index 9cb0b4766..b8ccb7c5d 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -386,7 +386,7 @@ public: void BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true); void EquipBot(std::string* errorMessage); bool CheckLoreConflict(const Item_Struct* item); - virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); } + virtual void UpdateEquipmentLight() { m_Light.Type[EQEmu::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); } // Static Class Methods //static void DestroyBotRaidObjects(Client* client); // Can be removed after bot raids are dumped diff --git a/zone/client.cpp b/zone/client.cpp index 6f7e6981b..30d451d38 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1902,7 +1902,7 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) UpdateEquipmentLight(); UpdateActiveLight(); - ns->spawn.light = m_Light.Type.Active; + ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; } bool Client::GMHideMe(Client* client) { diff --git a/zone/client.h b/zone/client.h index 79413da98..165816502 100644 --- a/zone/client.h +++ b/zone/client.h @@ -737,7 +737,7 @@ public: #endif uint32 GetEquipment(uint8 material_slot) const; // returns item id uint32 GetEquipmentColor(uint8 material_slot) const; - virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = m_inv.FindBrightestLightType(); m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); } + virtual void UpdateEquipmentLight() { m_Light.Type[EQEmu::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); } inline bool AutoSplitEnabled() { return m_pp.autosplit != 0; } diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 6338cc412..011741900 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -139,10 +139,8 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std: pc->IsRezzed(rezzed); pc->become_npc = false; - pc->m_Light.Level.Innate = pc->m_Light.Type.Innate = 0; pc->UpdateEquipmentLight(); // itemlist populated above..need to determine actual values - pc->m_Light.Level.Spell = pc->m_Light.Type.Spell = 0; - + safe_delete_array(pcs); return pc; @@ -531,7 +529,6 @@ in_helmtexture, SetPlayerKillItemID(0); UpdateEquipmentLight(); - m_Light.Level.Spell = m_Light.Type.Spell = 0; UpdateActiveLight(); } @@ -1283,7 +1280,7 @@ void Corpse::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.NPC = 2; UpdateActiveLight(); - ns->spawn.light = m_Light.Type.Active; + ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; } void Corpse::QueryLoot(Client* to) { @@ -1432,8 +1429,8 @@ uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { void Corpse::UpdateEquipmentLight() { - m_Light.Type.Equipment = 0; - m_Light.Level.Equipment = 0; + m_Light.Type[EQEmu::lightsource::LightEquipment] = 0; + m_Light.Level[EQEmu::lightsource::LightEquipment] = 0; for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) { if (((*iter)->equip_slot < EQEmu::legacy::EQUIPMENT_BEGIN || (*iter)->equip_slot > EQEmu::legacy::EQUIPMENT_END) && (*iter)->equip_slot != EQEmu::legacy::SlotPowerSource) { continue; } @@ -1442,8 +1439,8 @@ void Corpse::UpdateEquipmentLight() auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } - if (EQEmu::lightsource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) - m_Light.Type.Equipment = item->Light; + if (EQEmu::lightsource::IsLevelGreater(item->Light, m_Light.Type[EQEmu::lightsource::LightEquipment])) + m_Light.Type[EQEmu::lightsource::LightEquipment] = item->Light; } uint8 general_light_type = 0; @@ -1460,10 +1457,10 @@ void Corpse::UpdateEquipmentLight() general_light_type = item->Light; } - if (EQEmu::lightsource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) - m_Light.Type.Equipment = general_light_type; + if (EQEmu::lightsource::IsLevelGreater(general_light_type, m_Light.Type[EQEmu::lightsource::LightEquipment])) + m_Light.Type[EQEmu::lightsource::LightEquipment] = general_light_type; - m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); + m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); } void Corpse::AddLooter(Mob* who) { diff --git a/zone/merc.cpp b/zone/merc.cpp index 606ce8a35..1305dc8bc 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1210,7 +1210,7 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.IsMercenary = 1; UpdateActiveLight(); - ns->spawn.light = m_Light.Type.Active; + ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; /* // Wear Slots are not setup for Mercs yet @@ -5041,8 +5041,8 @@ void Merc::UpdateMercAppearance() { void Merc::UpdateEquipmentLight() { - m_Light.Type.Equipment = 0; - m_Light.Level.Equipment = 0; + m_Light.Type[EQEmu::lightsource::LightEquipment] = 0; + m_Light.Level[EQEmu::lightsource::LightEquipment] = 0; for (int index = SLOT_BEGIN; index < EQEmu::legacy::EQUIPMENT_SIZE; ++index) { if (index == EQEmu::legacy::SlotAmmo) { continue; } @@ -5050,9 +5050,9 @@ void Merc::UpdateEquipmentLight() auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } - if (EQEmu::lightsource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) { - m_Light.Type.Equipment = item->Light; - m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); + if (EQEmu::lightsource::IsLevelGreater(item->Light, m_Light.Type[EQEmu::lightsource::LightEquipment])) { + m_Light.Type[EQEmu::lightsource::LightEquipment] = item->Light; + m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); } } @@ -5068,10 +5068,10 @@ void Merc::UpdateEquipmentLight() general_light_type = item->Light; } - if (EQEmu::lightsource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) - m_Light.Type.Equipment = general_light_type; + if (EQEmu::lightsource::IsLevelGreater(general_light_type, m_Light.Type[EQEmu::lightsource::LightEquipment])) + m_Light.Type[EQEmu::lightsource::LightEquipment] = general_light_type; - m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); + m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); } void Merc::AddItem(uint8 slot, uint32 item_id) { diff --git a/zone/mob.cpp b/zone/mob.cpp index 05b6b828a..a0a00d20d 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -178,12 +178,10 @@ Mob::Mob(const char* in_name, if (runspeed < 0 || runspeed > 20) runspeed = 1.25f; - m_Light.Type.Innate = in_light; - m_Light.Level.Innate = EQEmu::lightsource::TypeToLevel(m_Light.Type.Innate); - m_Light.Level.Equipment = m_Light.Type.Equipment = 0; - m_Light.Level.Spell = m_Light.Type.Spell = 0; - m_Light.Type.Active = m_Light.Type.Innate; - m_Light.Level.Active = m_Light.Level.Innate; + m_Light.Type[EQEmu::lightsource::LightInnate] = in_light; + m_Light.Level[EQEmu::lightsource::LightInnate] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightInnate]); + m_Light.Type[EQEmu::lightsource::LightActive] = m_Light.Type[EQEmu::lightsource::LightInnate]; + m_Light.Level[EQEmu::lightsource::LightActive] = m_Light.Level[EQEmu::lightsource::LightInnate]; texture = in_texture; helmtexture = in_helmtexture; @@ -1100,7 +1098,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.findable = findable?1:0; UpdateActiveLight(); - ns->spawn.light = m_Light.Type.Active; + ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0; @@ -2227,18 +2225,18 @@ void Mob::SetAppearance(EmuAppearance app, bool iIgnoreSelf) { bool Mob::UpdateActiveLight() { - uint8 old_light_level = m_Light.Level.Active; + uint8 old_light_level = m_Light.Level[EQEmu::lightsource::LightActive]; - m_Light.Type.Active = 0; - m_Light.Level.Active = 0; + m_Light.Type[EQEmu::lightsource::LightActive] = 0; + m_Light.Level[EQEmu::lightsource::LightActive] = 0; - if (EQEmu::lightsource::IsLevelGreater((m_Light.Type.Innate & 0x0F), m_Light.Type.Active)) { m_Light.Type.Active = m_Light.Type.Innate; } - if (m_Light.Level.Equipment > m_Light.Level.Active) { m_Light.Type.Active = m_Light.Type.Equipment; } // limiter in property handler - if (m_Light.Level.Spell > m_Light.Level.Active) { m_Light.Type.Active = m_Light.Type.Spell; } // limiter in property handler + if (EQEmu::lightsource::IsLevelGreater((m_Light.Type[EQEmu::lightsource::LightInnate] & 0x0F), m_Light.Type[EQEmu::lightsource::LightActive])) { m_Light.Type[EQEmu::lightsource::LightActive] = m_Light.Type[EQEmu::lightsource::LightInnate]; } + if (m_Light.Level[EQEmu::lightsource::LightEquipment] > m_Light.Level[EQEmu::lightsource::LightActive]) { m_Light.Type[EQEmu::lightsource::LightActive] = m_Light.Type[EQEmu::lightsource::LightEquipment]; } // limiter in property handler + if (m_Light.Level[EQEmu::lightsource::LightSpell] > m_Light.Level[EQEmu::lightsource::LightActive]) { m_Light.Type[EQEmu::lightsource::LightActive] = m_Light.Type[EQEmu::lightsource::LightSpell]; } // limiter in property handler - m_Light.Level.Active = EQEmu::lightsource::TypeToLevel(m_Light.Type.Active); + m_Light.Level[EQEmu::lightsource::LightActive] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightActive]); - return (m_Light.Level.Active != old_light_level); + return (m_Light.Level[EQEmu::lightsource::LightActive] != old_light_level); } void Mob::ChangeSize(float in_size = 0, bool bNoRestriction) { diff --git a/zone/mob.h b/zone/mob.h index 7724dfaa8..ac7670ff4 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -703,17 +703,17 @@ public: bool IsDestructibleObject() { return destructibleobject; } void SetDestructibleObject(bool in) { destructibleobject = in; } - inline uint8 GetInnateLightType() { return m_Light.Type.Innate; } - inline uint8 GetEquipmentLightType() { return m_Light.Type.Equipment; } - inline uint8 GetSpellLightType() { return m_Light.Type.Spell; } + inline uint8 GetInnateLightType() { return m_Light.Type[EQEmu::lightsource::LightInnate]; } + inline uint8 GetEquipmentLightType() { return m_Light.Type[EQEmu::lightsource::LightEquipment]; } + inline uint8 GetSpellLightType() { return m_Light.Type[EQEmu::lightsource::LightSpell]; } - virtual void UpdateEquipmentLight() { m_Light.Type.Equipment = 0; m_Light.Level.Equipment = 0; } - inline void SetSpellLightType(uint8 light_type) { m_Light.Type.Spell = (light_type & 0x0F); m_Light.Level.Spell = EQEmu::lightsource::TypeToLevel(m_Light.Type.Spell); } + virtual void UpdateEquipmentLight() { m_Light.Type[EQEmu::lightsource::LightEquipment] = 0; m_Light.Level[EQEmu::lightsource::LightEquipment] = 0; } + inline void SetSpellLightType(uint8 light_type) { m_Light.Type[EQEmu::lightsource::LightSpell] = (light_type & 0x0F); m_Light.Level[EQEmu::lightsource::LightSpell] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightSpell]); } - inline uint8 GetActiveLightType() { return m_Light.Type.Active; } + inline uint8 GetActiveLightType() { return m_Light.Type[EQEmu::lightsource::LightActive]; } bool UpdateActiveLight(); // returns true if change, false if no change - EQEmu::lightsource::LightSourceProfile* GetLightProfile() { return &m_Light; } + EQEmu::LightSourceProfile* GetLightProfile() { return &m_Light; } Mob* GetPet(); void SetPet(Mob* newpet); @@ -1185,7 +1185,7 @@ protected: glm::vec4 m_Delta; - EQEmu::lightsource::LightSourceProfile m_Light; + EQEmu::LightSourceProfile m_Light; float fixedZ; EmuAppearance _appearance; diff --git a/zone/npc.cpp b/zone/npc.cpp index dca6c2bcc..7c91d67a5 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -745,8 +745,8 @@ uint32 NPC::CountLoot() { void NPC::UpdateEquipmentLight() { - m_Light.Type.Equipment = 0; - m_Light.Level.Equipment = 0; + m_Light.Type[EQEmu::lightsource::LightEquipment] = 0; + m_Light.Level[EQEmu::lightsource::LightEquipment] = 0; for (int index = SLOT_BEGIN; index < EQEmu::legacy::EQUIPMENT_SIZE; ++index) { if (index == EQEmu::legacy::SlotAmmo) { continue; } @@ -754,9 +754,9 @@ void NPC::UpdateEquipmentLight() auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } - if (EQEmu::lightsource::IsLevelGreater(item->Light, m_Light.Type.Equipment)) { - m_Light.Type.Equipment = item->Light; - m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); + if (EQEmu::lightsource::IsLevelGreater(item->Light, m_Light.Type[EQEmu::lightsource::LightEquipment])) { + m_Light.Type[EQEmu::lightsource::LightEquipment] = item->Light; + m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); } } @@ -772,10 +772,10 @@ void NPC::UpdateEquipmentLight() general_light_type = item->Light; } - if (EQEmu::lightsource::IsLevelGreater(general_light_type, m_Light.Type.Equipment)) - m_Light.Type.Equipment = general_light_type; + if (EQEmu::lightsource::IsLevelGreater(general_light_type, m_Light.Type[EQEmu::lightsource::LightEquipment])) + m_Light.Type[EQEmu::lightsource::LightEquipment] = general_light_type; - m_Light.Level.Equipment = EQEmu::lightsource::TypeToLevel(m_Light.Type.Equipment); + m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); } void NPC::Depop(bool StartSpawnTimer) { From b997a040d7cb5a87607023e41be0420652eb4933 Mon Sep 17 00:00:00 2001 From: phredi Date: Fri, 20 May 2016 21:03:34 -0500 Subject: [PATCH 101/693] Config File Update Initial Update --- client_files/export/main.cpp | 7 ++-- client_files/import/main.cpp | 7 ++-- common/eqemu_config.cpp | 48 ++++++++++++++++++++++++++++ common/eqemu_config.h | 18 ++++++++--- common/eqemu_config_extern.h | 22 +++++++++++++ common/ipc_mutex.cpp | 6 ++-- common/patches/rof.cpp | 6 ++-- common/patches/rof.h | 1 + common/patches/rof2.cpp | 6 ++-- common/patches/rof2.h | 1 + common/patches/sod.cpp | 6 ++-- common/patches/sod.h | 1 + common/patches/sof.cpp | 6 ++-- common/patches/sof.h | 1 + common/patches/template.cpp | 6 ++-- common/patches/template.h | 1 + common/patches/titanium.cpp | 7 ++-- common/patches/titanium.h | 1 + common/patches/uf.cpp | 6 ++-- common/patches/uf.h | 1 + common/shareddb.cpp | 15 +++++---- eqlaunch/eqlaunch.cpp | 3 +- shared_memory/base_data.cpp | 2 +- shared_memory/base_data.h | 4 +++ shared_memory/items.cpp | 2 +- shared_memory/items.h | 3 ++ shared_memory/loot.cpp | 4 +-- shared_memory/loot.h | 3 ++ shared_memory/main.cpp | 8 ++--- shared_memory/npc_faction.cpp | 2 +- shared_memory/npc_faction.h | 3 ++ shared_memory/skill_caps.cpp | 2 +- shared_memory/skill_caps.h | 3 ++ shared_memory/spells.cpp | 2 +- shared_memory/spells.h | 3 ++ utils/defaults/eqemu_config.xml.full | 12 ++++--- world/net.cpp | 4 +-- zone/embperl.cpp | 16 ++++++---- zone/embperl.h | 3 ++ zone/lua_parser.cpp | 12 ++++--- zone/lua_parser.h | 4 +++ zone/map.cpp | 2 +- zone/map.h | 4 +++ zone/net.cpp | 6 ++-- zone/pathing.cpp | 2 +- zone/pathing.h | 4 ++- zone/quest_parser_collection.cpp | 45 +++++++++++++------------- zone/quest_parser_collection.h | 3 ++ zone/water_map.cpp | 4 +-- zone/water_map.h | 2 ++ 50 files changed, 247 insertions(+), 93 deletions(-) create mode 100644 common/eqemu_config_extern.h diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 708d48456..65023d9ce 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -27,6 +27,7 @@ #include "../../common/rulesys.h" #include "../../common/string_util.h" +const EQEmuConfig *Config; EQEmuLogSys Log; void ExportSpells(SharedDatabase *db); @@ -45,12 +46,12 @@ int main(int argc, char **argv) { return 1; } - const EQEmuConfig *config = EQEmuConfig::get(); + Config = EQEmuConfig::get(); SharedDatabase database; Log.Out(Logs::General, Logs::Status, "Connecting to database..."); - if(!database.Connect(config->DatabaseHost.c_str(), config->DatabaseUsername.c_str(), - config->DatabasePassword.c_str(), config->DatabaseDB.c_str(), config->DatabasePort)) { + if(!database.Connect(Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), + Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) { Log.Out(Logs::General, Logs::Error, "Unable to connect to the database, cannot continue without a " "database connection"); return 1; diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index 72ae6fd5d..254d25c42 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -25,6 +25,7 @@ #include "../../common/rulesys.h" #include "../../common/string_util.h" +const EQEmuConfig *Config; EQEmuLogSys Log; void ImportSpells(SharedDatabase *db); @@ -43,12 +44,12 @@ int main(int argc, char **argv) { return 1; } - const EQEmuConfig *config = EQEmuConfig::get(); + Config = EQEmuConfig::get(); SharedDatabase database; Log.Out(Logs::General, Logs::Status, "Connecting to database..."); - if(!database.Connect(config->DatabaseHost.c_str(), config->DatabaseUsername.c_str(), - config->DatabasePassword.c_str(), config->DatabaseDB.c_str(), config->DatabasePort)) { + if(!database.Connect(Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), + Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) { Log.Out(Logs::General, Logs::Error, "Unable to connect to the database, cannot continue without a " "database connection"); return 1; diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index fb295cec1..6368c8c8f 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -254,6 +254,10 @@ void EQEmuConfig::do_files(TiXmlElement *ele) if (text) { OpCodesFile = text; } + text = ParseTextBlock(ele, "plugin.pl", true); + if (text) { + PluginPlFile = text; + } } void EQEmuConfig::do_directories(TiXmlElement *ele) @@ -262,14 +266,38 @@ void EQEmuConfig::do_directories(TiXmlElement *ele) text = ParseTextBlock(ele, "maps", true); if (text) { MapDir = text; + if ( MapDir.back() != '/' ) + MapDir += '/'; } text = ParseTextBlock(ele, "quests", true); if (text) { QuestDir = text; + if ( QuestDir.back() != '/' ) + QuestDir += '/'; } text = ParseTextBlock(ele, "plugins", true); if (text) { PluginDir = text; + if ( PluginDir.back() != '/' ) + PluginDir += '/'; + } + text = ParseTextBlock(ele, "lua_modules", true); + if (text) { + LuaModuleDir = text; + if ( LuaModuleDir.back() != '/' ) + LuaModuleDir += '/'; + } + text = ParseTextBlock(ele, "patches", true); + if (text) { + PatchDir = text; + if ( PatchDir.back() != '/' ) + PatchDir += '/'; + } + text = ParseTextBlock(ele, "shared_memory", true); + if (text) { + SharedMemDir = text; + if ( SharedMemDir.back() != '/' ) + SharedMemDir += '/'; } } @@ -404,6 +432,9 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const if (var_name == "OpCodesFile") { return (OpCodesFile); } + if (var_name == "PluginPlFile") { + return (PluginPlFile); + } if (var_name == "MapDir") { return (MapDir); } @@ -413,6 +444,18 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const if (var_name == "PluginDir") { return (PluginDir); } + if (var_name == "LuaModuleDir") { + return (LuaModuleDir); + } + if (var_name == "PatchDir") { + return (PatchDir); + } + if (var_name == "SharedMemDir") { + return (SharedMemDir); + } + if (var_name == "LogDir") { + return (LogDir); + } if (var_name == "LogPrefix") { return (LogPrefix); } @@ -468,9 +511,14 @@ void EQEmuConfig::Dump() const std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl; std::cout << "SpellsFile = " << SpellsFile << std::endl; std::cout << "OpCodesFile = " << OpCodesFile << std::endl; + std::cout << "PluginPlFile = " << PluginPlFile << std::endl; std::cout << "MapDir = " << MapDir << std::endl; std::cout << "QuestDir = " << QuestDir << std::endl; std::cout << "PluginDir = " << PluginDir << std::endl; + std::cout << "LuaModuleDir = " << LuaModuleDir << std::endl; + std::cout << "PatchDir = " << PatchDir << std::endl; + std::cout << "SharedMemDir = " << SharedMemDir << std::endl; + std::cout << "LogDir = " << LogDir << std::endl; std::cout << "ZonePortLow = " << ZonePortLow << std::endl; std::cout << "ZonePortHigh = " << ZonePortHigh << std::endl; std::cout << "DefaultStatus = " << (int)DefaultStatus << std::endl; diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 039b6c327..10be15323 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -79,11 +79,15 @@ class EQEmuConfig : public XMLParser // From std::string SpellsFile; std::string OpCodesFile; + std::string PluginPlFile; // From std::string MapDir; std::string QuestDir; std::string PluginDir; + std::string LuaModuleDir; + std::string PatchDir; + std::string SharedMemDir; // From std::string LogPrefix; @@ -153,12 +157,18 @@ class EQEmuConfig : public XMLParser // Files SpellsFile = "spells_us.txt"; OpCodesFile = "opcodes.conf"; + PluginPlFile = "plugin.pl"; // Dirs - MapDir = "Maps"; - QuestDir = "quests"; - PluginDir = "plugins"; + MapDir = "Maps/"; + QuestDir = "quests/"; + PluginDir = "plugins/"; + LuaModuleDir = "lua_modules/"; + PatchDir = "./"; + SharedMemDir = "shared/"; + LogDir = "logs/"; + // Launcher - LogPrefix = "logs/zone-"; + LogPrefix = "zone-"; LogSuffix = ".log"; RestartWait = 10000; //milliseconds TerminateWait = 10000; //milliseconds diff --git a/common/eqemu_config_extern.h b/common/eqemu_config_extern.h new file mode 100644 index 000000000..1943c5d61 --- /dev/null +++ b/common/eqemu_config_extern.h @@ -0,0 +1,22 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "eqemu_config.h" + +extern const EQEmuConfig *Config; + diff --git a/common/ipc_mutex.cpp b/common/ipc_mutex.cpp index c05fb072c..13efd8b0b 100644 --- a/common/ipc_mutex.cpp +++ b/common/ipc_mutex.cpp @@ -27,7 +27,7 @@ #endif #include "types.h" #include "eqemu_exception.h" - +#include "eqemu_config_extern.h" namespace EQEmu { struct IPCMutex::Implementation { @@ -41,7 +41,7 @@ namespace EQEmu { IPCMutex::IPCMutex(std::string name) : locked_(false) { imp_ = new Implementation; #ifdef _WINDOWS - std::string final_name = "EQEmuMutex_"; + std::string final_name = Config->SharedMemDir + "EQEmuMutex_"; final_name += name; imp_->mut_ = CreateMutex(nullptr, @@ -52,7 +52,7 @@ namespace EQEmu { EQ_EXCEPT("IPC Mutex", "Could not create mutex."); } #else - std::string final_name = name; + std::string final_name = Config->SharedMemDir + name; final_name += ".lock"; #ifdef __DARWIN diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index dd5113e0e..2cf9751e3 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -67,7 +67,8 @@ namespace RoF //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; //load up the opcode manager. @@ -111,7 +112,8 @@ namespace RoF if (opcodes != nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; if (!opcodes->ReloadOpcodes(opfile.c_str())) { diff --git a/common/patches/rof.h b/common/patches/rof.h index 42d8c08ef..31c81fbf7 100644 --- a/common/patches/rof.h +++ b/common/patches/rof.h @@ -21,6 +21,7 @@ #define COMMON_ROF_H #include "../struct_strategy.h" +#include "../eqemu_config_extern.h" class EQStreamIdentifier; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index e8205ba38..bb7b516df 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -67,7 +67,8 @@ namespace RoF2 //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; //load up the opcode manager. @@ -111,7 +112,8 @@ namespace RoF2 if (opcodes != nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; if (!opcodes->ReloadOpcodes(opfile.c_str())) { diff --git a/common/patches/rof2.h b/common/patches/rof2.h index af0b6f55d..911286977 100644 --- a/common/patches/rof2.h +++ b/common/patches/rof2.h @@ -21,6 +21,7 @@ #define COMMON_ROF2_H #include "../struct_strategy.h" +#include "../eqemu_config_extern.h" class EQStreamIdentifier; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 8605bd7d4..4434c4c86 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -63,7 +63,8 @@ namespace SoD //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; //load up the opcode manager. @@ -107,7 +108,8 @@ namespace SoD if (opcodes != nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; if (!opcodes->ReloadOpcodes(opfile.c_str())) { diff --git a/common/patches/sod.h b/common/patches/sod.h index be5843ead..bcd788112 100644 --- a/common/patches/sod.h +++ b/common/patches/sod.h @@ -21,6 +21,7 @@ #define COMMON_SOD_H #include "../struct_strategy.h" +#include "../eqemu_config_extern.h" class EQStreamIdentifier; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 9beda55ad..c7996c46c 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -63,7 +63,8 @@ namespace SoF //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; //load up the opcode manager. @@ -107,7 +108,8 @@ namespace SoF if (opcodes != nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; if (!opcodes->ReloadOpcodes(opfile.c_str())) { diff --git a/common/patches/sof.h b/common/patches/sof.h index 095c9dd4a..8d8ff287b 100644 --- a/common/patches/sof.h +++ b/common/patches/sof.h @@ -21,6 +21,7 @@ #define COMMON_SOF_H #include "../struct_strategy.h" +#include "../eqemu_config_extern.h" class EQStreamIdentifier; diff --git a/common/patches/template.cpp b/common/patches/template.cpp index 5120a2ef2..5e075ea8a 100644 --- a/common/patches/template.cpp +++ b/common/patches/template.cpp @@ -16,7 +16,8 @@ static Strategy struct_strategy; void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already if(opcodes == NULL) { - string opfile = "patch_"; + string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; //load up the opcode manager. @@ -51,7 +52,8 @@ void Reload() { if(opcodes != NULL) { //TODO: get this file name from the config file - string opfile = "patch_"; + string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; if(!opcodes->ReloadOpcodes(opfile.c_str())) { diff --git a/common/patches/template.h b/common/patches/template.h index 1391516b1..f264cf3fd 100644 --- a/common/patches/template.h +++ b/common/patches/template.h @@ -2,6 +2,7 @@ #define TEMPLATE_H_ #include "../struct_strategy.h" +#include "../eqemu_config_extern.h" class EQStreamIdentifier; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 57291ddd5..aa9f9b978 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -31,6 +31,7 @@ #include "../string_util.h" #include "../item.h" #include "titanium_structs.h" + #include @@ -61,7 +62,8 @@ namespace Titanium //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; //load up the opcode manager. @@ -105,7 +107,8 @@ namespace Titanium if (opcodes != nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; if (!opcodes->ReloadOpcodes(opfile.c_str())) { diff --git a/common/patches/titanium.h b/common/patches/titanium.h index eb193c872..ba30712be 100644 --- a/common/patches/titanium.h +++ b/common/patches/titanium.h @@ -21,6 +21,7 @@ #define COMMON_TITANIUM_H #include "../struct_strategy.h" +#include "../eqemu_config_extern.h" class EQStreamIdentifier; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 8563ad70c..7513c9f60 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -63,7 +63,8 @@ namespace UF //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; //load up the opcode manager. @@ -107,7 +108,8 @@ namespace UF if (opcodes != nullptr) { //TODO: get this file name from the config file - std::string opfile = "patch_"; + std::string opfile = Config->PatchDir; + opfile += "patch_"; opfile += name; opfile += ".conf"; if (!opcodes->ReloadOpcodes(opfile.c_str())) { diff --git a/common/patches/uf.h b/common/patches/uf.h index 59c332bdc..8c244367b 100644 --- a/common/patches/uf.h +++ b/common/patches/uf.h @@ -21,6 +21,7 @@ #define COMMON_UF_H #include "../struct_strategy.h" +#include "../eqemu_config_extern.h" class EQStreamIdentifier; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index f61255143..a83665147 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -35,6 +35,7 @@ #include "mysql.h" #include "rulesys.h" #include "shareddb.h" +#include "eqemu_config_extern.h" #include "string_util.h" SharedDatabase::SharedDatabase() @@ -812,7 +813,7 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { try { EQEmu::IPCMutex mutex("items"); mutex.Lock(); - std::string file_name = std::string("shared/") + prefix + std::string("items"); + std::string file_name = Config->SharedMemDir + prefix + std::string("items"); items_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); items_hash = std::unique_ptr>(new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), items_mmf->Size())); mutex.Unlock(); @@ -1235,7 +1236,7 @@ bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) { try { EQEmu::IPCMutex mutex("faction"); mutex.Lock(); - std::string file_name = std::string("shared/") + prefix + std::string("faction"); + std::string file_name = Config->SharedMemDir + prefix + std::string("faction"); faction_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); faction_hash = std::unique_ptr>(new EQEmu::FixedMemoryHashSet(reinterpret_cast(faction_mmf->Get()), faction_mmf->Size())); mutex.Unlock(); @@ -1386,7 +1387,7 @@ bool SharedDatabase::LoadSkillCaps(const std::string &prefix) { try { EQEmu::IPCMutex mutex("skill_caps"); mutex.Lock(); - std::string file_name = std::string("shared/") + prefix + std::string("skill_caps"); + std::string file_name = Config->SharedMemDir + prefix + std::string("skill_caps"); skill_caps_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); mutex.Unlock(); } catch(std::exception &ex) { @@ -1542,7 +1543,7 @@ bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const EQEmu::IPCMutex mutex("spells"); mutex.Lock(); - std::string file_name = std::string("shared/") + prefix + std::string("spells"); + std::string file_name = Config->SharedMemDir + prefix + std::string("spells"); spells_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); *records = *reinterpret_cast(spells_mmf->Get()); *sp = reinterpret_cast((char*)spells_mmf->Get() + 4); @@ -1745,7 +1746,7 @@ bool SharedDatabase::LoadBaseData(const std::string &prefix) { EQEmu::IPCMutex mutex("base_data"); mutex.Lock(); - std::string file_name = std::string("shared/") + prefix + std::string("base_data"); + std::string file_name = Config->SharedMemDir + prefix + std::string("base_data"); base_data_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); mutex.Unlock(); } catch(std::exception& ex) { @@ -1983,12 +1984,12 @@ bool SharedDatabase::LoadLoot(const std::string &prefix) { try { EQEmu::IPCMutex mutex("loot"); mutex.Lock(); - std::string file_name_lt = std::string("shared/") + prefix + std::string("loot_table"); + std::string file_name_lt = Config->SharedMemDir + prefix + std::string("loot_table"); loot_table_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name_lt)); loot_table_hash = std::unique_ptr>(new EQEmu::FixedMemoryVariableHashSet( reinterpret_cast(loot_table_mmf->Get()), loot_table_mmf->Size())); - std::string file_name_ld = std::string("shared/") + prefix + std::string("loot_drop"); + std::string file_name_ld = Config->SharedMemDir + prefix + std::string("loot_drop"); loot_drop_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name_ld)); loot_drop_hash = std::unique_ptr>(new EQEmu::FixedMemoryVariableHashSet( reinterpret_cast(loot_drop_mmf->Get()), diff --git a/eqlaunch/eqlaunch.cpp b/eqlaunch/eqlaunch.cpp index 952b6198b..e4b63c6c1 100644 --- a/eqlaunch/eqlaunch.cpp +++ b/eqlaunch/eqlaunch.cpp @@ -32,6 +32,7 @@ #include EQEmuLogSys Log; +const EQEmuConfig *Config; bool RunLoops = false; @@ -56,7 +57,7 @@ int main(int argc, char *argv[]) { Log.Out(Logs::Detail, Logs::Launcher, "Loading server configuration failed."); return 1; } - const EQEmuConfig *Config = EQEmuConfig::get(); + Config = EQEmuConfig::get(); /* * Setup nice signal handlers diff --git a/shared_memory/base_data.cpp b/shared_memory/base_data.cpp index e82c5a2c1..6c43f4493 100644 --- a/shared_memory/base_data.cpp +++ b/shared_memory/base_data.cpp @@ -33,7 +33,7 @@ void LoadBaseData(SharedDatabase *database, const std::string &prefix) { uint32 size = records * 16 * sizeof(BaseDataStruct); - std::string file_name = std::string("shared/") + prefix + std::string("base_data"); + std::string file_name = Config->SharedMemDir + prefix + std::string("base_data"); EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); diff --git a/shared_memory/base_data.h b/shared_memory/base_data.h index afa799eea..401b57bd2 100644 --- a/shared_memory/base_data.h +++ b/shared_memory/base_data.h @@ -20,6 +20,10 @@ #define __EQEMU_SHARED_MEMORY_BASE_DATA_H #include +#include "../common/eqemu_config.h" + +extern const EQEmuConfig *Config; + class SharedDatabase; void LoadBaseData(SharedDatabase *database, const std::string &prefix); diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index 02a102a8f..4987d6735 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -37,7 +37,7 @@ void LoadItems(SharedDatabase *database, const std::string &prefix) { uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); - std::string file_name = std::string("shared/") + prefix + std::string("items"); + std::string file_name = Config->SharedMemDir + prefix + std::string("items"); EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); diff --git a/shared_memory/items.h b/shared_memory/items.h index cff9794fd..1d34c9467 100644 --- a/shared_memory/items.h +++ b/shared_memory/items.h @@ -20,6 +20,9 @@ #define __EQEMU_SHARED_MEMORY_ITEMS_H #include +#include "../common/eqemu_config.h" + +extern const EQEmuConfig *Config; class SharedDatabase; void LoadItems(SharedDatabase *database, const std::string &prefix); diff --git a/shared_memory/loot.cpp b/shared_memory/loot.cpp index 956383cd3..a659b05a5 100644 --- a/shared_memory/loot.cpp +++ b/shared_memory/loot.cpp @@ -44,8 +44,8 @@ void LoadLoot(SharedDatabase *database, const std::string &prefix) { (loot_drop_count * sizeof(LootDrop_Struct)) + //loot table headers (loot_drop_entries_count * sizeof(LootDropEntries_Struct)); //number of loot table entries - std::string file_name_lt = std::string("shared/") + prefix + std::string("loot_table"); - std::string file_name_ld = std::string("shared/") + prefix + std::string("loot_drop"); + std::string file_name_lt = Config->SharedMemDir + prefix + std::string("loot_table"); + std::string file_name_ld = Config->SharedMemDir + prefix + std::string("loot_drop"); EQEmu::MemoryMappedFile mmf_loot_table(file_name_lt, loot_table_size); EQEmu::MemoryMappedFile mmf_loot_drop(file_name_ld, loot_drop_size); diff --git a/shared_memory/loot.h b/shared_memory/loot.h index 27e812185..c9c55895b 100644 --- a/shared_memory/loot.h +++ b/shared_memory/loot.h @@ -20,6 +20,9 @@ #define __EQEMU_SHARED_MEMORY_LOOT_H #include +#include "../common/eqemu_config.h" + +extern const EQEmuConfig *Config; class SharedDatabase; void LoadLoot(SharedDatabase *database, const std::string &prefix); diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 8ad2b42ae..d37d23bd4 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -35,7 +35,7 @@ #include "base_data.h" EQEmuLogSys Log; - +const EQEmuConfig *Config; int main(int argc, char **argv) { RegisterExecutablePlatform(ExePlatformSharedMemory); Log.LoadLogSettingsDefaults(); @@ -47,12 +47,12 @@ int main(int argc, char **argv) { return 1; } - const EQEmuConfig *config = EQEmuConfig::get(); + Config = EQEmuConfig::get(); SharedDatabase database; Log.Out(Logs::General, Logs::Status, "Connecting to database..."); - if(!database.Connect(config->DatabaseHost.c_str(), config->DatabaseUsername.c_str(), - config->DatabasePassword.c_str(), config->DatabaseDB.c_str(), config->DatabasePort)) { + if(!database.Connect(Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), + Config->DatabasePassword.c_str(), Config->DatabaseDB.c_str(), Config->DatabasePort)) { Log.Out(Logs::General, Logs::Error, "Unable to connect to the database, cannot continue without a " "database connection"); return 1; diff --git a/shared_memory/npc_faction.cpp b/shared_memory/npc_faction.cpp index 9ac8510bd..5e8f86cfd 100644 --- a/shared_memory/npc_faction.cpp +++ b/shared_memory/npc_faction.cpp @@ -34,7 +34,7 @@ void LoadFactions(SharedDatabase *database, const std::string &prefix) { uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(lists, max_list)); - std::string file_name = std::string("shared/") + prefix + std::string("faction"); + std::string file_name = Config->SharedMemDir + prefix + std::string("faction"); EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); diff --git a/shared_memory/npc_faction.h b/shared_memory/npc_faction.h index 8fe5dbadb..598f8f01b 100644 --- a/shared_memory/npc_faction.h +++ b/shared_memory/npc_faction.h @@ -20,6 +20,9 @@ #define __EQEMU_SHARED_MEMORY_NPC_FACTION_H #include +#include "../common/eqemu_config.h" + +extern const EQEmuConfig *Config; class SharedDatabase; void LoadFactions(SharedDatabase *database, const std::string &prefix); diff --git a/shared_memory/skill_caps.cpp b/shared_memory/skill_caps.cpp index 153d06e13..6712d75c6 100644 --- a/shared_memory/skill_caps.cpp +++ b/shared_memory/skill_caps.cpp @@ -34,7 +34,7 @@ void LoadSkillCaps(SharedDatabase *database, const std::string &prefix) { uint32 level_count = HARD_LEVEL_CAP + 1; uint32 size = (class_count * skill_count * level_count * sizeof(uint16)); - std::string file_name = std::string("shared/") + prefix + std::string("skill_caps"); + std::string file_name = Config->SharedMemDir + prefix + std::string("skill_caps"); EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); diff --git a/shared_memory/skill_caps.h b/shared_memory/skill_caps.h index 90ae5733c..6e35d6fb5 100644 --- a/shared_memory/skill_caps.h +++ b/shared_memory/skill_caps.h @@ -20,6 +20,9 @@ #define __EQEMU_SHARED_MEMORY_SKILL_CAPS_H #include +#include "../common/eqemu_config.h" + +extern const EQEmuConfig *Config; class SharedDatabase; void LoadSkillCaps(SharedDatabase *database, const std::string &prefix); diff --git a/shared_memory/spells.cpp b/shared_memory/spells.cpp index 34cce35bc..2cb3d846e 100644 --- a/shared_memory/spells.cpp +++ b/shared_memory/spells.cpp @@ -34,7 +34,7 @@ void LoadSpells(SharedDatabase *database, const std::string &prefix) { uint32 size = records * sizeof(SPDat_Spell_Struct) + sizeof(uint32); - std::string file_name = std::string("shared/") + prefix + std::string("spells"); + std::string file_name = Config->SharedMemDir + prefix + std::string("spells"); EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); diff --git a/shared_memory/spells.h b/shared_memory/spells.h index bde0f8233..230e3779f 100644 --- a/shared_memory/spells.h +++ b/shared_memory/spells.h @@ -20,6 +20,9 @@ #define __EQEMU_SHARED_MEMORY_SPELLS_H #include +#include "../common/eqemu_config.h" + +extern const EQEmuConfig *Config; class SharedDatabase; void LoadSpells(SharedDatabase *database, const std::string &prefix); diff --git a/utils/defaults/eqemu_config.xml.full b/utils/defaults/eqemu_config.xml.full index ed1cc6002..b376b199a 100644 --- a/utils/defaults/eqemu_config.xml.full +++ b/utils/defaults/eqemu_config.xml.full @@ -68,7 +68,7 @@ - + @@ -80,11 +80,15 @@ + - - - + + + + + + diff --git a/world/net.cpp b/world/net.cpp index 90fb3e680..ee335aa7c 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -104,7 +104,7 @@ volatile bool RunLoops = true; uint32 numclients = 0; uint32 numzones = 0; bool holdzones = false; - +const WorldConfig *Config; EQEmuLogSys Log; extern ConsoleList console_list; @@ -135,7 +135,7 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::World_Server, "Loading server configuration failed."); return 1; } - const WorldConfig *Config=WorldConfig::get(); + Config=WorldConfig::get(); Log.Out(Logs::General, Logs::World_Server, "CURRENT_VERSION: %s", CURRENT_VERSION); diff --git a/zone/embperl.cpp b/zone/embperl.cpp index 4d27d1269..834a5f0b9 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -173,25 +173,27 @@ void Embperl::DoInit() { Log.Out(Logs::General, Logs::Quests, "Loading perlemb plugins."); try { - eval_pv("main::eval_file('plugin', 'plugin.pl');", FALSE); + std::string perl_command; + perl_command = "main::eval_file('plugin', '" + Config->PluginPlFile + "');"; + eval_pv(perl_command.c_str(), FALSE); } catch(const char *err) { - Log.Out(Logs::General, Logs::Quests, "Warning - plugin.pl: %s", err); + Log.Out(Logs::General, Logs::Quests, "Warning - %s: %s", Config->PluginPlFile.c_str(), err); } try { //should probably read the directory in c, instead, so that //I can echo filenames as I do it, but c'mon... I'm lazy and this 1 line reads in all the plugins - eval_pv( - "if(opendir(D,'plugins')) { " + std::string perl_command = + "if(opendir(D,'" + Config->PluginDir +"')) { " " my @d = readdir(D);" " closedir(D);" " foreach(@d){ " - " main::eval_file('plugin','plugins/'.$_)if/\\.pl$/;" + " main::eval_file('plugin','" + Config->PluginDir + "/'.$_)if/\\.pl$/;" " }" - "}" - ,FALSE); + "}"; + eval_pv(perl_command.c_str(),FALSE); } catch(const char *err) { diff --git a/zone/embperl.h b/zone/embperl.h index 919664d0a..e5d07a3d8 100644 --- a/zone/embperl.h +++ b/zone/embperl.h @@ -10,6 +10,8 @@ Eglin #ifdef EMBPERL +#include "zone_config.h" + #include #include #include @@ -57,6 +59,7 @@ extern "C" { //the perl headers dont do this for us... EXTERN_C void boot_DynaLoader(pTHX_ CV* cv); EXTERN_C void xs_init(pTHX); +extern const ZoneConfig *Config; class Embperl { private: diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index aeb1e3228..4f88eb88a 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -33,6 +33,7 @@ #include "lua_general.h" #include "questmgr.h" #include "zone.h" +#include "zone_config.h" #include "lua_parser.h" #include "lua_encounter.h" @@ -851,7 +852,7 @@ void LuaParser::ReloadQuests() { lua_getglobal(L, "package"); lua_getfield(L, -1, "path"); std::string module_path = lua_tostring(L,-1); - module_path += ";./lua_modules/?.lua"; + module_path += ";./" + Config->LuaModuleDir + "/?.lua"; lua_pop(L, 1); lua_pushstring(L, module_path.c_str()); lua_setfield(L, -2, "path"); @@ -860,7 +861,8 @@ void LuaParser::ReloadQuests() { MapFunctions(L); //load init - std::string path = "quests/"; + std::string path = Config->QuestDir; + path += "/"; path += QUEST_GLOBAL_DIRECTORY; path += "/script_init.lua"; @@ -876,7 +878,8 @@ void LuaParser::ReloadQuests() { //zone init - always loads after global if(zone) { - std::string zone_script = "quests/"; + std::string zone_script = Config->QuestDir; + zone_script += "/"; zone_script += zone->GetShortName(); zone_script += "/script_init_v"; zone_script += std::to_string(zone->GetInstanceVersion()); @@ -893,7 +896,8 @@ void LuaParser::ReloadQuests() { return; } - zone_script = "quests/"; + zone_script = Config->QuestDir; + zone_script += "/"; zone_script += zone->GetShortName(); zone_script += "/script_init.lua"; f = fopen(zone_script.c_str(), "r"); diff --git a/zone/lua_parser.h b/zone/lua_parser.h index 63d9facfe..1e4df4740 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -8,6 +8,10 @@ #include #include +#include "zone_config.h" + +extern const ZoneConfig *Config; + struct lua_State; class ItemInst; class Client; diff --git a/zone/map.cpp b/zone/map.cpp index 37f394626..c652d809c 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -227,7 +227,7 @@ bool Map::CheckLoS(glm::vec3 myloc, glm::vec3 oloc) const { } Map *Map::LoadMapFile(std::string file) { - std::string filename = MAP_DIR; + std::string filename = Config->MapDir; filename += "/"; std::transform(file.begin(), file.end(), file.begin(), ::tolower); filename += file; diff --git a/zone/map.h b/zone/map.h index f3e81fe20..5d1b08618 100644 --- a/zone/map.h +++ b/zone/map.h @@ -25,8 +25,12 @@ #include "position.h" #include +#include "zone_config.h" + #define BEST_Z_INVALID -99999 +extern const ZoneConfig *Config; + class Map { public: diff --git a/zone/net.cpp b/zone/net.cpp index 761583900..5c3996959 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -104,9 +104,9 @@ QueryServ *QServ = 0; TaskManager *taskmanager = 0; QuestParserCollection *parse = 0; EQEmuLogSys Log; - const SPDat_Spell_Struct* spells; int32 SPDAT_RECORDS = -1; +const ZoneConfig *Config; void Shutdown(); extern void MapOpcodes(); @@ -123,7 +123,7 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::Error, "Loading server configuration failed."); return 1; } - const ZoneConfig *Config = ZoneConfig::get(); + Config = ZoneConfig::get(); const char *zone_name; uint32 instance_id = 0; @@ -195,7 +195,7 @@ int main(int argc, char** argv) { } worldserver.SetPassword(Config->SharedKey.c_str()); - + Log.Out(Logs::General, Logs::Zone_Server, "Connecting to MySQL..."); if (!database.Connect( Config->DatabaseHost.c_str(), diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 32a55d73a..8c4b2e605 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -52,7 +52,7 @@ PathManager* PathManager::LoadPathFile(const char* ZoneName) strlwr(LowerCaseZoneName); - snprintf(ZonePathFileName, 250, MAP_DIR "/%s.path", LowerCaseZoneName); + snprintf(ZonePathFileName, 250, "%s/%s.path", Config->MapDir.c_str(),LowerCaseZoneName); if((PathFile = fopen(ZonePathFileName, "rb"))) { diff --git a/zone/pathing.h b/zone/pathing.h index c6cfd9c26..d65ebfdcf 100644 --- a/zone/pathing.h +++ b/zone/pathing.h @@ -2,9 +2,11 @@ #define PATHING_H #include "map.h" - +#include "zone_config.h" #include +extern const ZoneConfig *Config; + class Client; class Mob; diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index 4d2a2960a..33a18d379 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -24,6 +24,7 @@ #include "quest_interface.h" #include "zone.h" #include "questmgr.h" +#include "zone_config.h" #include @@ -459,7 +460,7 @@ int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounte QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string &filename) { //first look for /quests/zone/npcid.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += zone->GetShortName(); filename += "/"; filename += itoa(npcid); @@ -502,7 +503,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string } } - filename = "quests/"; + filename = Config->QuestDir; filename += zone->GetShortName(); filename += "/"; filename += npc_name; @@ -524,7 +525,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string } //third look for /quests/global/npcid.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += QUEST_GLOBAL_DIRECTORY; filename += "/"; filename += itoa(npcid); @@ -545,7 +546,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string } //fourth look for /quests/global/npcname.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += QUEST_GLOBAL_DIRECTORY; filename += "/"; filename += npc_name; @@ -566,7 +567,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string } //fifth look for /quests/zone/default.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += zone->GetShortName(); filename += "/"; filename += "default"; @@ -587,7 +588,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string } //last look for /quests/global/default.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += QUEST_GLOBAL_DIRECTORY; filename += "/"; filename += "default"; @@ -615,7 +616,7 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) return nullptr; //first look for /quests/zone/player_v[instance_version].ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += zone->GetShortName(); filename += "/"; filename += "player_v"; @@ -640,7 +641,7 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) } //second look for /quests/zone/player.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += zone->GetShortName(); filename += "/"; filename += "player"; @@ -662,7 +663,7 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) } //third look for /quests/global/player.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += QUEST_GLOBAL_DIRECTORY; filename += "/"; filename += "player"; @@ -687,7 +688,7 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) QuestInterface *QuestParserCollection::GetQIByGlobalNPCQuest(std::string &filename) { // simply look for /quests/global/global_npc.ext - filename = "quests/"; + filename = Config->QuestDir; filename += QUEST_GLOBAL_DIRECTORY; filename += "/"; filename += "global_npc"; @@ -715,7 +716,7 @@ QuestInterface *QuestParserCollection::GetQIByGlobalNPCQuest(std::string &filena QuestInterface *QuestParserCollection::GetQIByGlobalPlayerQuest(std::string &filename) { //first look for /quests/global/player.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += QUEST_GLOBAL_DIRECTORY; filename += "/"; filename += "global_player"; @@ -743,7 +744,7 @@ QuestInterface *QuestParserCollection::GetQIByGlobalPlayerQuest(std::string &fil QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::string &filename) { //first look for /quests/zone/spells/spell_id.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += zone->GetShortName(); filename += "/spells/"; filename += itoa(spell_id); @@ -767,7 +768,7 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s } //second look for /quests/global/spells/spell_id.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += QUEST_GLOBAL_DIRECTORY; filename += "/spells/"; filename += itoa(spell_id); @@ -789,7 +790,7 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s } //third look for /quests/zone/spells/default.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += zone->GetShortName(); filename += "/spells/default"; @@ -810,7 +811,7 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s } //last look for /quests/global/spells/default.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += QUEST_GLOBAL_DIRECTORY; filename += "/spells/default"; @@ -835,7 +836,7 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, std::string &filename) { //first look for /quests/zone/items/item_script.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += zone->GetShortName(); filename += "/items/"; filename += item_script; @@ -859,7 +860,7 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, } //second look for /quests/global/items/item_script.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += QUEST_GLOBAL_DIRECTORY; filename += "/items/"; filename += item_script; @@ -881,7 +882,7 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, } //third look for /quests/zone/items/default.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += zone->GetShortName(); filename += "/items/default"; @@ -902,7 +903,7 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, } //last look for /quests/global/items/default.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += QUEST_GLOBAL_DIRECTORY; filename += "/items/default"; @@ -927,7 +928,7 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, QuestInterface *QuestParserCollection::GetQIByEncounterQuest(std::string encounter_name, std::string &filename) { //first look for /quests/zone/encounters/encounter_name.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += zone->GetShortName(); filename += "/encounters/"; filename += encounter_name; @@ -951,7 +952,7 @@ QuestInterface *QuestParserCollection::GetQIByEncounterQuest(std::string encount } //second look for /quests/global/encounters/encounter_name.ext (precedence) - filename = "quests/"; + filename = Config->QuestDir; filename += QUEST_GLOBAL_DIRECTORY; filename += "/encounters/"; filename += encounter_name; @@ -1077,4 +1078,4 @@ void QuestParserCollection::LoadPerlEventExportSettings(PerlEventExportSettings* perl_event_export_settings[event_id].event_variables = atoi(row[6]); } -} \ No newline at end of file +} diff --git a/zone/quest_parser_collection.h b/zone/quest_parser_collection.h index 7a0cec274..c17e2ccda 100644 --- a/zone/quest_parser_collection.h +++ b/zone/quest_parser_collection.h @@ -34,12 +34,15 @@ #include "quest_interface.h" +#include "zone_config.h" + #include #include #define QuestFailedToLoad 0xFFFFFFFF #define QuestUnloaded 0x00 +extern const ZoneConfig *Config; class Client; class ItemInst; class Mob; diff --git a/zone/water_map.cpp b/zone/water_map.cpp index 604875ed6..c77e77f00 100644 --- a/zone/water_map.cpp +++ b/zone/water_map.cpp @@ -12,7 +12,7 @@ WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) { std::transform(zone_name.begin(), zone_name.end(), zone_name.begin(), ::tolower); - std::string file_path = MAP_DIR + std::string("/") + zone_name + std::string(".wtr"); + std::string file_path = Config->MapDir + zone_name + std::string(".wtr"); FILE *f = fopen(file_path.c_str(), "rb"); if(f) { char magic[10]; @@ -57,4 +57,4 @@ WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) { } return nullptr; -} \ No newline at end of file +} diff --git a/zone/water_map.h b/zone/water_map.h index 01936efbc..2b6e0ce3c 100644 --- a/zone/water_map.h +++ b/zone/water_map.h @@ -3,8 +3,10 @@ #include "../common/types.h" #include "position.h" +#include "zone_config.h" #include +extern const ZoneConfig *Config; enum WaterRegionType { RegionTypeUnsupported = -2, From 3031365e1f4283ecdf8ddeb415ebb5d4e7d84e19 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 21 May 2016 04:54:18 -0400 Subject: [PATCH 102/693] Moved struct Item_Struct into namespace EQEmu --- changelog.txt | 4 + common/CMakeLists.txt | 1 + common/emu_constants.h | 2 +- common/eq_constants.h | 332 +---------------- common/eq_packet_structs.h | 2 +- common/item.cpp | 199 +++++----- common/item.h | 44 ++- common/item_struct.cpp | 209 +++++++++++ common/item_struct.h | 705 ++++++++++++++++++++++++++---------- common/patches/rof.cpp | 12 +- common/patches/rof2.cpp | 12 +- common/patches/sod.cpp | 12 +- common/patches/sof.cpp | 12 +- common/patches/titanium.cpp | 15 +- common/patches/uf.cpp | 14 +- common/say_link.cpp | 6 +- common/say_link.h | 9 +- common/shareddb.cpp | 48 +-- common/shareddb.h | 12 +- shared_memory/items.cpp | 2 +- tests/fixed_memory_test.h | 46 +-- world/worlddb.cpp | 2 +- zone/aa.cpp | 2 +- zone/attack.cpp | 273 ++++++-------- zone/bonuses.cpp | 91 ++--- zone/bot.cpp | 148 ++++---- zone/bot.h | 2 +- zone/bot_command.cpp | 8 +- zone/client.cpp | 97 ++--- zone/client.h | 20 +- zone/client_mods.cpp | 12 +- zone/client_packet.cpp | 104 +++--- zone/client_process.cpp | 18 +- zone/command.cpp | 30 +- zone/corpse.cpp | 18 +- zone/doors.cpp | 2 +- zone/effects.cpp | 4 +- zone/embparser.cpp | 2 +- zone/embxs.cpp | 2 +- zone/entity.cpp | 4 +- zone/forage.cpp | 40 +- zone/guild_mgr.cpp | 20 +- zone/inventory.cpp | 187 +++++----- zone/loottables.cpp | 21 +- zone/lua_item.cpp | 2 +- zone/lua_item.h | 15 +- zone/lua_iteminst.cpp | 2 +- zone/lua_parser_events.cpp | 2 +- zone/merc.cpp | 21 +- zone/merc.h | 8 +- zone/mob.cpp | 112 +++--- zone/mob.h | 22 +- zone/mod_functions.cpp | 11 +- zone/npc.cpp | 10 +- zone/npc.h | 12 +- zone/object.cpp | 18 +- zone/object.h | 2 +- zone/perl_mob.cpp | 2 +- zone/perl_questitem.cpp | 2 +- zone/pets.cpp | 4 +- zone/questmgr.cpp | 12 +- zone/special_attacks.cpp | 64 ++-- zone/spell_effects.cpp | 24 +- zone/spells.cpp | 14 +- zone/tasks.cpp | 4 +- zone/tradeskills.cpp | 130 ++++--- zone/trading.cpp | 40 +- zone/tune.cpp | 2 +- zone/zone.cpp | 2 +- zone/zonedb.cpp | 12 +- 70 files changed, 1757 insertions(+), 1597 deletions(-) create mode 100644 common/item_struct.cpp diff --git a/changelog.txt b/changelog.txt index 938c58927..800eefa33 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/21/2016 == +Uleat: Moved struct Item_Struct into namespace EQEmu along with associated enumerations - enumerations into namespace EQEmu::item (run shared_memory) +Uleat: Fixed a few possible crash points in linux builds associated with augments/ornamentations + == 05/18/2016 == Uleat: Changed client 'constants' files to 'limits' diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 8c5ac6db7..5c4f364a9 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -37,6 +37,7 @@ SET(common_sources inventory_version.cpp ipc_mutex.cpp item.cpp + item_struct.cpp light_source.cpp md5.cpp memory_mapped_file.cpp diff --git a/common/emu_constants.h b/common/emu_constants.h index a012e8534..6c7f3e962 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) diff --git a/common/eq_constants.h b/common/eq_constants.h index a7dcf6d00..54f52620c 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -1,4 +1,5 @@ /* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -13,337 +14,16 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef EQ_CONSTANTS_H -#define EQ_CONSTANTS_H + +#ifndef COMMON_EQ_CONSTANTS_H +#define COMMON_EQ_CONSTANTS_H #include "skills.h" #include "types.h" -/* -** Item attributes -** -** (There are no grepwin hits other than these declarations... Do they have a use?) -*/ -enum ItemAttributes : uint32 -{ - ItemAttrNone = 0x00000000, - ItemAttrLore = 0x00000001, - ItemAttrArtifact = 0x00000002, - ItemAttrSummoned = 0x00000004, - ItemAttrMagic = 0x00000008, - ItemAttrAugment = 0x00000010, - ItemAttrPendingLore = 0x00000020, - ItemAttrUnknown = 0xFFFFFFFF -}; - -/* -** Item class types -** -*/ -enum ItemClassTypes -{ - ItemClassCommon = 0, - ItemClassContainer, - ItemClassBook, - _ItemClassCount -}; - -/* -** Item use types -** -** (ref: database and eqstr_us.txt) -** -** (Looking at a recent database, it's possible that some of the item values may be off [10-27-2013]) -*/ -enum ItemUseTypes : uint8 -{ -/*9138*/ ItemType1HSlash = 0, -/*9141*/ ItemType2HSlash, -/*9140*/ ItemType1HPiercing, -/*9139*/ ItemType1HBlunt, -/*9142*/ ItemType2HBlunt, -/*5504*/ ItemTypeBow, // 5 -/*----*/ ItemTypeUnknown1, -/*----*/ ItemTypeLargeThrowing, -/*5505*/ ItemTypeShield, -/*5506*/ ItemTypeScroll, -/*5507*/ ItemTypeArmor, // 10 -/*5508*/ ItemTypeMisc, // a lot of random crap has this item use. -/*7564*/ ItemTypeLockPick, -/*----*/ ItemTypeUnknown2, -/*5509*/ ItemTypeFood, -/*5510*/ ItemTypeDrink, // 15 -/*5511*/ ItemTypeLight, -/*5512*/ ItemTypeCombinable, // not all stackable items are this use... -/*5513*/ ItemTypeBandage, -/*----*/ ItemTypeSmallThrowing, -/*----*/ ItemTypeSpell, // 20 // spells and tomes -/*5514*/ ItemTypePotion, -/*----*/ ItemTypeUnknown3, -/*0406*/ ItemTypeWindInstrument, -/*0407*/ ItemTypeStringedInstrument, -/*0408*/ ItemTypeBrassInstrument, // 25 -/*0405*/ ItemTypePercussionInstrument, -/*5515*/ ItemTypeArrow, -/*----*/ ItemTypeUnknown4, -/*5521*/ ItemTypeJewelry, -/*----*/ ItemTypeSkull, // 30 -/*5516*/ ItemTypeBook, // skill-up tomes/books? (would probably need a pp flag if true...) -/*5517*/ ItemTypeNote, -/*5518*/ ItemTypeKey, -/*----*/ ItemTypeCoin, -/*5520*/ ItemType2HPiercing, // 35 -/*----*/ ItemTypeFishingPole, -/*----*/ ItemTypeFishingBait, -/*5519*/ ItemTypeAlcohol, -/*----*/ ItemTypeKey2, // keys and satchels?? (questable keys?) -/*----*/ ItemTypeCompass, // 40 -/*----*/ ItemTypeUnknown5, -/*----*/ ItemTypePoison, // might be wrong, but includes poisons -/*----*/ ItemTypeUnknown6, -/*----*/ ItemTypeUnknown7, -/*5522*/ ItemTypeMartial, // 45 -/*----*/ ItemTypeUnknown8, -/*----*/ ItemTypeUnknown9, -/*----*/ ItemTypeUnknown10, -/*----*/ ItemTypeUnknown11, -/*----*/ ItemTypeSinging, // 50 -/*5750*/ ItemTypeAllInstrumentTypes, -/*5776*/ ItemTypeCharm, -/*----*/ ItemTypeDye, -/*----*/ ItemTypeAugmentation, -/*----*/ ItemTypeAugmentationSolvent, // 55 -/*----*/ ItemTypeAugmentationDistiller, -/*----*/ ItemTypeUnknown12, -/*----*/ ItemTypeFellowshipKit, -/*----*/ ItemTypeUnknown13, -/*----*/ ItemTypeRecipe, // 60 -/*----*/ ItemTypeAdvancedRecipe, -/*----*/ ItemTypeJournal, // only one(1) database entry -/*----*/ ItemTypeAltCurrency, // alt-currency (as opposed to coinage) -/*5881*/ ItemTypePerfectedAugmentationDistiller, -/*----*/ _ItemTypeCount - -/* - Unknowns: - - Mounts? - Ornamentations? - GuildBanners? - Collectible? - Placeable? - (others?) -*/ -}; - -/* -** Augmentation use type bitmasks (1-based) -** -** (ref: dbstr_us.txt) -** -*/ -enum AugmentationUseTypeBitmasks : uint32 { - AugUseNone = 0x00000000, - AugUseGeneralSingleStat = 0x00000001, /*1^16^1 (General: Single Stat)^0*/ - AugUseGeneralMultipleStat = 0x00000002, /*2^16^2 (General: Multiple Stat)^0*/ - AugUseGeneralSpellEffect = 0x00000004, /*3^16^3 (General: Spell Effect)^0*/ - AugUseWeaponGeneral = 0x00000008, /*4^16^4 (Weapon: General)^0*/ - AugUseWeaponElemDamage = 0x00000010, /*5^16^5 (Weapon: Elem Damage)^0*/ - AugUseWeaponBaseDamage = 0x00000020, /*6^16^6 (Weapon: Base Damage)^0*/ - AugUseGeneralGroup = 0x00000040, /*7^16^7 (General: Group)^0*/ - AugUseGeneralRaid = 0x00000080, /*8^16^8 (General: Raid)^0*/ - AugUseGeneralDragonsPoints = 0x00000100, /*9^16^9 (General: Dragons Points)^0*/ - AugUseCraftedCommon = 0x00000200, /*10^16^10 (Crafted: Common)^0*/ - AugUseCraftedGroup1 = 0x00000400, /*11^16^11 (Crafted: Group)^0*/ - AugUseCraftedRaid1 = 0x00000800, /*12^16^12 (Crafted: Raid)^0*/ - AugUseEnergeiacGroup = 0x00001000, /*13^16^13 (Energeiac: Group)^0*/ - AugUseEnergeiacRaid = 0x00002000, /*14^16^14 (Energeiac: Raid)^0*/ - AugUseEmblem = 0x00004000, /*15^16^15 (Emblem)^0*/ - AugUseCraftedGroup2 = 0x00008000, /*16^16^16 (Crafted: Group)^0*/ - AugUseCraftedRaid2 = 0x00010000, /*17^16^17 (Crafted: Raid)^0*/ - AugUseUnknown1 = 0x00020000, /*18^16^18^0*/ - AugUseUnknown2 = 0x00040000, /*19^16^19^0*/ - AugUseOrnamentation = 0x00080000, /*20^16^20 (Ornamentation)^0*/ - AugUseSpecialOrnamentation = 0x00100000, /*21^16^21 (Special Ornamentation)^0*/ - AugUseUnknown3 = 0x00200000, /*22^16^22^0*/ - AugUseUnknown4 = 0x00400000, /*23^16^23^0*/ - AugUseUnknown5 = 0x00800000, /*24^16^24^0*/ - AugUseUnknown6 = 0x01000000, /*25^16^25^0*/ - AugUseUnknown7 = 0x02000000, /*26^16^26^0*/ - AugUseUnknown8 = 0x04000000, /*27^16^27^0*/ - AugUseUnknown9 = 0x08000000, /*28^16^28^0*/ - AugUseUnknown10 = 0x10000000, /*29^16^29^0*/ - AugUseEpic25 = 0x20000000, /*30^16^30^0*/ - AugUseTest = 0x40000000, /*31^16^Test^0*/ // listed as 31^16^31^0 in 5-10 client - AugUseAll = 0xFFFFFFFF -}; - -/* -** Augmentation use types (enumerated) -** -*/ -enum AugmentationUseTypes : uint8 { - AugTypeNone = 0, - AugTypeGeneralSingleStat, - AugTypeGeneralMultipleStat, - AugTypeGeneralSpellEffect, - AugTypeWeaponGeneral, - AugTypeWeaponElemDamage, // 5 - AugTypeWeaponBaseDamage, - AugTypeGeneralGroup, - AugTypeGeneralRaid, - AugTypeGeneralDragonsPoints, - AugTypeCraftedCommon, // 10 - AugTypeCraftedGroup1, - AugTypeCraftedRaid1, - AugTypeEnergeiacGroup, - AugTypeEnergeiacRaid, - AugTypeEmblem, // 15 - AugTypeCraftedGroup2, - AugTypeCraftedRaid2, - AugTypeUnknown1, - AugTypeUnknown2, - AugTypeOrnamentation, // 20 - AugTypeSpecialOrnamentation, - AugTypeUnknown3, - AugTypeUnknown4, - AugTypeUnknown5, - AugTypeUnknown6, // 25 - AugTypeUnknown7, - AugTypeUnknown8, - AugTypeUnknown9, - AugTypeUnknown10, - AugTypeEpic25, // 30 - AugTypeTest, - _AugTypeCount, - AugTypeAll = 255 -}; - -/* -** Augmentation restriction types (in-work) -** -** (ref: eqstr_us.txt) -** -*/ -enum AugmentationRestrictionTypes : uint8 { -/*4690*/ AugRestrAny = 0, -/*9134*/ AugRestrArmor, -/*9135*/ AugRestrWeapons, -/*9136*/ AugRestr1HWeapons, -/*9137*/ AugRestr2HWeapons, -/*9138*/ AugRestr1HSlash, // 5 -/*9139*/ AugRestr1HBlunt, -/*9140*/ AugRestrPiercing, -/*9148*/ AugRestrHandToHand, -/*9141*/ AugRestr2HSlash, -/*9142*/ AugRestr2HBlunt, // 10 -/*9143*/ AugRestr2HPierce, -/*9144*/ AugRestrBows, -/*9145*/ AugRestrShields, -/*8052*/ AugRestr1HSlash1HBluntOrHandToHand, -/*9200*/ AugRestr1HBluntOrHandToHand, // 15 // no listed peq entries - -// these three appear to be post-RoF (12-10-2012) and can not be verified until RoF (05-10-2013) is supported -/*????*/ AugRestrUnknown1, -/*????*/ AugRestrUnknown2, -/*????*/ AugRestrUnknown3, // last value in peq entries - _AugRestrCount - -/*4687*/ //AugTypeAllItems, // ?? unknown atm -/*4688*/ //AugTypePrestige, // ?? unknown atm -/*4689*/ //AugTypeNonPrestige, // ?? unknown atm -}; - -/* -** Container use types -** -** This correlates to world 'object.type' (object.h/Object.cpp) as well as Item_Struct.BagType -** -** (ref: database, web forums and eqstr_us.txt) -*/ -enum ContainerUseTypes : uint8 -{ -/*3400*/ BagTypeSmallBag = 0, -/*3401*/ BagTypeLargeBag, -/*3402*/ BagTypeQuiver, -/*3403*/ BagTypeBeltPouch, -/*3404*/ BagTypeWristPouch, -/*3405*/ BagTypeBackPack, // 5 -/*3406*/ BagTypeSmallChest, -/*3407*/ BagTypeLargeChest, -/*----*/ BagTypeBandolier, // <*Database Reference Only> -/*3408*/ BagTypeMedicineBag, -/*3409*/ BagTypeToolBox, // 10 -/*3410*/ BagTypeLexicon, -/*3411*/ BagTypeMortar, -/*3412*/ BagTypeSelfDusting, // Quest container (Auto-clear contents?) -/*3413*/ BagTypeMixingBowl, -/*3414*/ BagTypeOven, // 15 -/*3415*/ BagTypeSewingKit, -/*3416*/ BagTypeForge, -/*3417*/ BagTypeFletchingKit, -/*3418*/ BagTypeBrewBarrel, -/*3419*/ BagTypeJewelersKit, // 20 -/*3420*/ BagTypePotteryWheel, -/*3421*/ BagTypeKiln, -/*3422*/ BagTypeKeymaker, // (no database entries as of peq rev 69) -/*3423*/ BagTypeWizardsLexicon, -/*3424*/ BagTypeMagesLexicon, // 25 -/*3425*/ BagTypeNecromancersLexicon, -/*3426*/ BagTypeEnchantersLexicon, -/*----*/ BagTypeUnknown1, // (a coin pouch/purse?) (no database entries as of peq rev 69) -/*----*/ BagTypeConcordanceofResearch, // <*Database Reference Only> -/*3427*/ BagTypeAlwaysWorks, // 30 // Quest container (Never-fail combines?) -/*3428*/ BagTypeKoadaDalForge, // High Elf -/*3429*/ BagTypeTeirDalForge, // Dark Elf -/*3430*/ BagTypeOggokForge, // Ogre -/*3431*/ BagTypeStormguardForge, // Dwarf -/*3432*/ BagTypeAkanonForge, // 35 // Gnome -/*3433*/ BagTypeNorthmanForge, // Barbarian -/*----*/ BagTypeUnknown2, // (no database entries as of peq rev 69) -/*3434*/ BagTypeCabilisForge, // Iksar -/*3435*/ BagTypeFreeportForge, // Human 1 -/*3436*/ BagTypeRoyalQeynosForge, // 40 // Human 2 -/*3439*/ BagTypeHalflingTailoringKit, -/*3438*/ BagTypeErudTailoringKit, -/*3440*/ BagTypeFierDalTailoringKit, // Wood Elf -/*3441*/ BagTypeFierDalFletchingKit, // Wood Elf -/*3437*/ BagTypeIksarPotteryWheel, // 45 -/*3442*/ BagTypeTackleBox, -/*3443*/ BagTypeTrollForge, -/*3445*/ BagTypeFierDalForge, // Wood Elf -/*3444*/ BagTypeValeForge, // Halfling -/*3446*/ BagTypeErudForge, // 50 -/*----*/ BagTypeTradersSatchel, // <*Database Reference Only> (db: Yellow Trader's Satchel Token?) -/*5785*/ BagTypeGuktaForge, // Froglok (no database entries as of peq rev 69) -/*3359*/ BagTypeAugmentationSealer, -/*----*/ BagTypeIceCreamChurn, // <*Database Reference Only> -/*6325*/ BagTypeTransformationmold, // 55 // Ornamentation -/*6340*/ BagTypeDetransformationmold, // Ornamentation Stripper -/*5400*/ BagTypeUnattuner, -/*7684*/ BagTypeTradeskillBag, -/*7692*/ BagTypeCollectibleBag, -/*----*/ _BagTypeCount -}; - -/* -** Item Effect Types -** -*/ -enum { - ET_CombatProc = 0, - ET_ClickEffect = 1, - ET_WornEffect = 2, - ET_Expendable = 3, - ET_EquipClick = 4, - ET_ClickEffect2 = 5, //name unknown - ET_Focus = 6, - ET_Scroll = 7 -}; - //SpawnAppearance types: (compared two clients for server-originating types: SoF & RoF2) #define AT_Die 0 // this causes the client to keel over and zone to bind point (default action) #define AT_WhoLevel 1 // the level that shows up on /who @@ -848,4 +528,4 @@ static const uint8 SkillDamageTypes[HIGHEST_SKILL + 1] = // change to _SkillServ static const uint32 MAX_SPELL_DB_ID_VAL = 65535; -#endif +#endif /*COMMON_EQ_CONSTANTS_H*/ diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 2e470714b..0075f0cf0 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -2098,7 +2098,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + EQEmu::Item_Struct item; uint8 iss_unknown001[6]; };*/ diff --git a/common/item.cpp b/common/item.cpp index 25bf7d886..c00f137db 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -187,35 +187,35 @@ ItemInst* Inventory::GetItem(int16 slot_id) const else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { // Trade bag slots ItemInst* inst = _GetItem(m_trade, Inventory::CalcSlotId(slot_id)); - if (inst && inst->IsType(ItemClassContainer)) { + if (inst && inst->IsClassBag()) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { // Shared Bank bag slots ItemInst* inst = _GetItem(m_shbank, Inventory::CalcSlotId(slot_id)); - if (inst && inst->IsType(ItemClassContainer)) { + if (inst && inst->IsClassBag()) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { // Bank bag slots ItemInst* inst = _GetItem(m_bank, Inventory::CalcSlotId(slot_id)); - if (inst && inst->IsType(ItemClassContainer)) { + if (inst && inst->IsClassBag()) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { // Cursor bag slots ItemInst* inst = m_cursor.peek_front(); - if (inst && inst->IsType(ItemClassContainer)) { + if (inst && inst->IsClassBag()) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { // Personal inventory bag slots ItemInst* inst = _GetItem(m_inv, Inventory::CalcSlotId(slot_id)); - if (inst && inst->IsType(ItemClassContainer)) { + if (inst && inst->IsClassBag()) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } @@ -359,7 +359,7 @@ ItemInst* Inventory::PopItem(int16 slot_id) else { // Is slot inside bag? ItemInst* baginst = GetItem(Inventory::CalcSlotId(slot_id)); - if (baginst != nullptr && baginst->IsType(ItemClassContainer)) { + if (baginst != nullptr && baginst->IsClassBag()) { p = baginst->PopItem(Inventory::CalcBagIdx(slot_id)); } } @@ -368,7 +368,7 @@ ItemInst* Inventory::PopItem(int16 slot_id) return p; } -bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { +bool Inventory::HasSpaceForItem(const EQEmu::Item_Struct *ItemToTry, int16 Quantity) { if (ItemToTry->Stackable) { @@ -386,7 +386,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { Quantity -= ChargeSlotsLeft; } - if (InvItem && InvItem->IsType(ItemClassContainer)) { + if (InvItem && InvItem->IsClassBag()) { int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); uint8 BagSize = InvItem->GetItem()->BagSlots; @@ -430,7 +430,7 @@ bool Inventory::HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity) { } } - else if (InvItem->IsType(ItemClassContainer) && CanItemFitInContainer(ItemToTry, InvItem->GetItem())) { + else if (InvItem->IsClassBag() && CanItemFitInContainer(ItemToTry, InvItem->GetItem())) { int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); @@ -624,9 +624,9 @@ int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, boo if (!for_bag) { for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { const ItemInst* inst = GetItem(i); - if (inst && inst->IsType(ItemClassContainer) && inst->GetItem()->BagSize >= min_size) + if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size) { - if (inst->GetItem()->BagType == BagTypeQuiver && inst->GetItem()->ItemType != ItemTypeArrow) + if (inst->GetItem()->BagType == EQEmu::item::BagTypeQuiver && inst->GetItem()->ItemType != EQEmu::item::ItemTypeArrow) { continue; } @@ -666,7 +666,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { return INVALID_INDEX; // step 1: find room for bags (caller should really ask for slots for bags first to avoid sending them to cursor..and bag item loss) - if (inst->IsType(ItemClassContainer)) { + if (inst->IsClassBag()) { for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { if (!m_inv[free_slot]) return free_slot; @@ -693,7 +693,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { if (!main_inst) continue; - if (main_inst->IsType(ItemClassContainer)) { // if item-specific containers already have bad items, we won't fix it here... + if (main_inst->IsClassBag()) { // if item-specific containers already have bad items, we won't fix it here... for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { const ItemInst* sub_inst = main_inst->GetItem(free_bag_slot); @@ -708,11 +708,11 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { } // step 3a: find room for container-specific items (ItemClassArrow) - if (inst->GetItem()->ItemType == ItemTypeArrow) { + if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeArrow) { for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; - if (!main_inst || (main_inst->GetItem()->BagType != BagTypeQuiver) || !main_inst->IsType(ItemClassContainer)) + if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeQuiver) || !main_inst->IsClassBag()) continue; for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { @@ -723,11 +723,11 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { } // step 3b: find room for container-specific items (ItemClassSmallThrowing) - if (inst->GetItem()->ItemType == ItemTypeSmallThrowing) { + if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeSmallThrowing) { for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; - if (!main_inst || (main_inst->GetItem()->BagType != BagTypeBandolier) || !main_inst->IsType(ItemClassContainer)) + if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeBandolier) || !main_inst->IsClassBag()) continue; for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { @@ -748,8 +748,8 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { const ItemInst* main_inst = m_inv[free_slot]; - if (main_inst && main_inst->IsType(ItemClassContainer)) { - if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == BagTypeBandolier) || (main_inst->GetItem()->BagType == BagTypeQuiver)) + if (main_inst && main_inst->IsClassBag()) { + if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeBandolier) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeQuiver)) continue; for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { @@ -901,7 +901,7 @@ uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) } } -bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_Struct *Container) { +bool Inventory::CanItemFitInContainer(const EQEmu::Item_Struct *ItemToTry, const EQEmu::Item_Struct *Container) { if (!ItemToTry || !Container) return false; @@ -909,10 +909,10 @@ bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_S if (ItemToTry->Size > Container->BagSize) return false; - if ((Container->BagType == BagTypeQuiver) && (ItemToTry->ItemType != ItemTypeArrow)) + if ((Container->BagType == EQEmu::item::BagTypeQuiver) && (ItemToTry->ItemType != EQEmu::item::ItemTypeArrow)) return false; - if ((Container->BagType == BagTypeBandolier) && (ItemToTry->ItemType != ItemTypeSmallThrowing)) + if ((Container->BagType == EQEmu::item::BagTypeBandolier) && (ItemToTry->ItemType != EQEmu::item::ItemTypeSmallThrowing)) return false; return true; @@ -1019,7 +1019,7 @@ uint8 Inventory::FindBrightestLightType() auto item = inst->GetItem(); if (item == nullptr) { continue; } - if (item->ItemClass != ItemClassCommon) { continue; } + if (!item->IsClassCommon()) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } if (EQEmu::lightsource::TypeToLevel(item->Light)) @@ -1071,7 +1071,7 @@ int Inventory::GetSlotByItemInstCollection(const std::map &col return iter->first; } - if (t_inst && !t_inst->IsType(ItemClassContainer)) { + if (t_inst && !t_inst->IsClassBag()) { for (auto b_iter = t_inst->_cbegin(); b_iter != t_inst->_cend(); ++b_iter) { if (b_iter->second == inst) { return Inventory::CalcSlotId(iter->first, b_iter->first); @@ -1099,7 +1099,7 @@ void Inventory::dumpItemCollection(const std::map &collection) void Inventory::dumpBagContents(ItemInst *inst, std::map::const_iterator *it) { - if (!inst || !inst->IsType(ItemClassContainer)) + if (!inst || !inst->IsClassBag()) return; // Go through bag, if bag @@ -1177,7 +1177,7 @@ int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst) // Slot must be within a bag parentSlot = Inventory::CalcSlotId(slot_id); ItemInst* baginst = GetItem(parentSlot); // Get parent bag - if (baginst && baginst->IsType(ItemClassContainer)) + if (baginst && baginst->IsClassBag()) { baginst->_PutItem(Inventory::CalcBagIdx(slot_id), inst); result = slot_id; @@ -1212,7 +1212,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, ui return EQEmu::legacy::SLOT_AUGMENT; } - if (!inst->IsType(ItemClassContainer)) { continue; } + if (!inst->IsClassBag()) { continue; } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { auto bag_inst = bag_iter->second; @@ -1260,7 +1260,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) return EQEmu::legacy::SLOT_AUGMENT; } - if (!inst->IsType(ItemClassContainer)) { continue; } + if (!inst->IsClassBag()) { continue; } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { auto bag_inst = bag_iter->second; @@ -1294,19 +1294,19 @@ int16 Inventory::_HasItemByUse(std::map& bucket, uint8 use, ui auto inst = iter->second; if (inst == nullptr) { continue; } - if (inst->IsType(ItemClassCommon) && inst->GetItem()->ItemType == use) { + if (inst->IsClassCommon() && inst->GetItem()->ItemType == use) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); if (quantity_found >= quantity) return iter->first; } - if (!inst->IsType(ItemClassContainer)) { continue; } + if (!inst->IsClassBag()) { continue; } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { auto bag_inst = bag_iter->second; if (bag_inst == nullptr) { continue; } - if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->ItemType == use) { + if (bag_inst->IsClassCommon() && bag_inst->GetItem()->ItemType == use) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) return Inventory::CalcSlotId(iter->first, bag_iter->first); @@ -1326,19 +1326,19 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) auto inst = *iter; if (inst == nullptr) { continue; } - if (inst->IsType(ItemClassCommon) && inst->GetItem()->ItemType == use) { + if (inst->IsClassCommon() && inst->GetItem()->ItemType == use) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); if (quantity_found >= quantity) return EQEmu::legacy::SlotCursor; } - if (!inst->IsType(ItemClassContainer)) { continue; } + if (!inst->IsClassBag()) { continue; } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { auto bag_inst = bag_iter->second; if (bag_inst == nullptr) { continue; } - if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->ItemType == use) { + if (bag_inst->IsClassCommon() && bag_inst->GetItem()->ItemType == use) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) return Inventory::CalcSlotId(EQEmu::legacy::SlotCursor, bag_iter->first); @@ -1369,13 +1369,13 @@ int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 return EQEmu::legacy::SLOT_AUGMENT; } - if (!inst->IsType(ItemClassContainer)) { continue; } + if (!inst->IsClassBag()) { continue; } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { auto bag_inst = bag_iter->second; if (bag_inst == nullptr) { continue; } - if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup) + if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) return Inventory::CalcSlotId(iter->first, bag_iter->first); for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { @@ -1409,13 +1409,13 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) return EQEmu::legacy::SLOT_AUGMENT; } - if (!inst->IsType(ItemClassContainer)) { continue; } + if (!inst->IsClassBag()) { continue; } for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { auto bag_inst = bag_iter->second; if (bag_inst == nullptr) { continue; } - if (bag_inst->IsType(ItemClassCommon) && bag_inst->GetItem()->LoreGroup == loregroup) + if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) return Inventory::CalcSlotId(EQEmu::legacy::SlotCursor, bag_iter->first); for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { @@ -1438,10 +1438,10 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) // // class ItemInst // -ItemInst::ItemInst(const Item_Struct* item, int16 charges) { +ItemInst::ItemInst(const EQEmu::Item_Struct* item, int16 charges) { m_use_type = ItemInstNormal; if(item) { - m_item = new Item_Struct(*item); + m_item = new EQEmu::Item_Struct(*item); } else { m_item = nullptr; } @@ -1449,7 +1449,7 @@ ItemInst::ItemInst(const Item_Struct* item, int16 charges) { m_price = 0; m_attuned = false; m_merchantslot = 0; - if(m_item &&m_item->ItemClass == ItemClassCommon) + if (m_item && m_item->IsClassCommon()) m_color = m_item->Color; else m_color = 0; @@ -1472,7 +1472,7 @@ ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) { m_use_type = ItemInstNormal; m_item = db->GetItem(item_id); if(m_item) { - m_item = new Item_Struct(*m_item); + m_item = new EQEmu::Item_Struct(*m_item); } else { m_item = nullptr; @@ -1482,7 +1482,7 @@ ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) { m_price = 0; m_merchantslot = 0; m_attuned=false; - if(m_item && m_item->ItemClass == ItemClassCommon) + if (m_item && m_item->IsClassCommon()) m_color = m_item->Color; else m_color = 0; @@ -1527,7 +1527,7 @@ ItemInst::ItemInst(const ItemInst& copy) { m_use_type=copy.m_use_type; if(copy.m_item) - m_item = new Item_Struct(*copy.m_item); + m_item = new EQEmu::Item_Struct(*copy.m_item); else m_item = nullptr; @@ -1563,7 +1563,7 @@ ItemInst::ItemInst(const ItemInst& copy) m_evolveLvl = copy.m_evolveLvl; m_activated = copy.m_activated; if (copy.m_scaledItem) - m_scaledItem = new Item_Struct(*copy.m_scaledItem); + m_scaledItem = new EQEmu::Item_Struct(*copy.m_scaledItem); else m_scaledItem = nullptr; @@ -1589,12 +1589,12 @@ ItemInst::~ItemInst() } // Query item type -bool ItemInst::IsType(ItemClassTypes item_class) const +bool ItemInst::IsType(EQEmu::item::ItemClass item_class) const { // IsType() does not protect against 'm_item = nullptr' // Check usage type - if ((m_use_type == ItemInstWorldContainer) && (item_class == ItemClassContainer)) + if ((m_use_type == ItemInstWorldContainer) && (item_class == EQEmu::item::ItemClassBag)) return true; if (!m_item) @@ -1603,6 +1603,21 @@ bool ItemInst::IsType(ItemClassTypes item_class) const return (m_item->ItemClass == item_class); } +bool ItemInst::IsClassCommon() +{ + return (m_item && m_item->IsClassCommon()); +} + +bool ItemInst::IsClassBag() +{ + return (m_item && m_item->IsClassBag()); +} + +bool ItemInst::IsClassBook() +{ + return (m_item && m_item->IsClassBook()); +} + // Is item stackable? bool ItemInst::IsStackable() const { @@ -1667,7 +1682,7 @@ bool ItemInst::IsAugmentable() const bool ItemInst::AvailableWearSlot(uint32 aug_wear_slots) const { // TODO: check to see if incoming 'aug_wear_slots' "switches" bit assignments like above... // (if wrong, would only affect MainAmmo and MainPowerSource augments) - if (!m_item || m_item->ItemClass != ItemClassCommon) + if (!m_item || !m_item->IsClassCommon()) return false; int index = EQEmu::legacy::EQUIPMENT_BEGIN; @@ -1683,7 +1698,7 @@ bool ItemInst::AvailableWearSlot(uint32 aug_wear_slots) const { int8 ItemInst::AvailableAugmentSlot(int32 augtype) const { - if (!m_item || m_item->ItemClass != ItemClassCommon) + if (!m_item || !m_item->IsClassCommon()) return INVALID_INDEX; int index = AUG_INDEX_BEGIN; @@ -1698,7 +1713,7 @@ int8 ItemInst::AvailableAugmentSlot(int32 augtype) const bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const { - if (!m_item || m_item->ItemClass != ItemClassCommon) + if (!m_item || !m_item->IsClassCommon()) return false; if ((!GetItem(slot) && m_item->AugSlotVisible[slot]) && augtype == -1 || (m_item->AugSlotType[slot] && ((1 << (m_item->AugSlotType[slot] - 1)) & augtype))) { @@ -1783,7 +1798,7 @@ void ItemInst::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent) continue; } - const Item_Struct* item = inst->GetItem(); + const EQEmu::Item_Struct* item = inst->GetItem(); if (item == nullptr) { cur = m_contents.erase(cur); continue; @@ -1848,7 +1863,7 @@ uint8 ItemInst::GetTotalItemCount() const { uint8 item_count = 1; - if (m_item && m_item->ItemClass != ItemClassContainer) { return item_count; } + if (m_item && !m_item->IsClassBag()) { return item_count; } for (int index = SUB_INDEX_BEGIN; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } } @@ -1857,7 +1872,7 @@ uint8 ItemInst::GetTotalItemCount() const bool ItemInst::IsNoneEmptyContainer() { - if (!m_item || m_item->ItemClass != ItemClassContainer) + if (!m_item || !m_item->IsClassBag()) return false; for (int index = SUB_INDEX_BEGIN; index < m_item->BagSlots; ++index) { @@ -1871,7 +1886,7 @@ bool ItemInst::IsNoneEmptyContainer() // Retrieve augment inside item ItemInst* ItemInst::GetAugment(uint8 slot) const { - if (m_item && m_item->ItemClass == ItemClassCommon) + if (m_item && m_item->IsClassCommon()) return GetItem(slot); return nullptr; @@ -1879,7 +1894,7 @@ ItemInst* ItemInst::GetAugment(uint8 slot) const ItemInst* ItemInst::GetOrnamentationAug(int32 ornamentationAugtype) const { - if (!m_item || m_item->ItemClass != ItemClassCommon) { return nullptr; } + if (!m_item || !m_item->IsClassCommon()) { return nullptr; } if (ornamentationAugtype == 0) { return nullptr; } for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) @@ -1916,7 +1931,7 @@ uint32 ItemInst::GetOrnamentHeroModel(int32 material_slot) const { } bool ItemInst::UpdateOrnamentationInfo() { - if (!m_item || m_item->ItemClass != ItemClassCommon) + if (!m_item || !m_item->IsClassCommon()) return false; bool ornamentSet = false; @@ -1924,7 +1939,7 @@ bool ItemInst::UpdateOrnamentationInfo() { int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); if (GetOrnamentationAug(ornamentationAugtype)) { - const Item_Struct* ornamentItem; + const EQEmu::Item_Struct* ornamentItem; ornamentItem = GetOrnamentationAug(ornamentationAugtype)->GetItem(); if (ornamentItem != nullptr) { @@ -1951,10 +1966,10 @@ bool ItemInst::UpdateOrnamentationInfo() { return ornamentSet; } -bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll) { +bool ItemInst::CanTransform(const EQEmu::Item_Struct *ItemToTry, const EQEmu::Item_Struct *Container, bool AllowAll) { if (!ItemToTry || !Container) return false; - if (ItemToTry->ItemType == ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0) + if (ItemToTry->ItemType == EQEmu::item::ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0) return false; if (AllowAll && strncasecmp(Container->CharmFile, "ITEMTRANSFIGSHIELD", 18) && strncasecmp(Container->CharmFile, "ITEMTransfigBow", 15)) { @@ -1999,7 +2014,7 @@ bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Con uint32 ItemInst::GetAugmentItemID(uint8 slot) const { - if (!m_item || m_item->ItemClass != ItemClassCommon) + if (!m_item || !m_item->IsClassCommon()) return NO_ITEM; return GetItemID(slot); @@ -2008,7 +2023,7 @@ uint32 ItemInst::GetAugmentItemID(uint8 slot) const // Add an augment to the item void ItemInst::PutAugment(uint8 slot, const ItemInst& augment) { - if (!m_item || m_item->ItemClass != ItemClassCommon) + if (!m_item || !m_item->IsClassCommon()) return; PutItem(slot, augment); @@ -2029,7 +2044,7 @@ void ItemInst::PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id) // Remove augment from item and destroy it void ItemInst::DeleteAugment(uint8 index) { - if (!m_item || m_item->ItemClass != ItemClassCommon) + if (!m_item || !m_item->IsClassCommon()) return; DeleteItem(index); @@ -2038,7 +2053,7 @@ void ItemInst::DeleteAugment(uint8 index) // Remove augment from item and return it ItemInst* ItemInst::RemoveAugment(uint8 index) { - if (!m_item || m_item->ItemClass != ItemClassCommon) + if (!m_item || !m_item->IsClassCommon()) return nullptr; return PopItem(index); @@ -2046,7 +2061,7 @@ ItemInst* ItemInst::RemoveAugment(uint8 index) bool ItemInst::IsAugmented() { - if (!m_item || m_item->ItemClass != ItemClassCommon) + if (!m_item || !m_item->IsClassCommon()) return false; for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { @@ -2060,10 +2075,10 @@ bool ItemInst::IsAugmented() // Has attack/delay? bool ItemInst::IsWeapon() const { - if (!m_item || m_item->ItemClass != ItemClassCommon) + if (!m_item || !m_item->IsClassCommon()) return false; - if (m_item->ItemType == ItemTypeArrow && m_item->Damage != 0) + if (m_item->ItemType == EQEmu::item::ItemTypeArrow && m_item->Damage != 0) return true; else return ((m_item->Damage != 0) && (m_item->Delay != 0)); @@ -2074,9 +2089,9 @@ bool ItemInst::IsAmmo() const if (!m_item) return false; - if ((m_item->ItemType == ItemTypeArrow) || - (m_item->ItemType == ItemTypeLargeThrowing) || - (m_item->ItemType == ItemTypeSmallThrowing) + if ((m_item->ItemType == EQEmu::item::ItemTypeArrow) || + (m_item->ItemType == EQEmu::item::ItemTypeLargeThrowing) || + (m_item->ItemType == EQEmu::item::ItemTypeSmallThrowing) ) { return true; } @@ -2085,7 +2100,7 @@ bool ItemInst::IsAmmo() const } -const Item_Struct* ItemInst::GetItem() const +const EQEmu::Item_Struct* ItemInst::GetItem() const { if (!m_item) return nullptr; @@ -2096,7 +2111,7 @@ const Item_Struct* ItemInst::GetItem() const return m_item; } -const Item_Struct* ItemInst::GetUnscaledItem() const +const EQEmu::Item_Struct* ItemInst::GetUnscaledItem() const { // No operator calls and defaults to nullptr return m_item; @@ -2204,10 +2219,10 @@ void ItemInst::ScaleItem() { return; if (m_scaledItem) { - memcpy(m_scaledItem, m_item, sizeof(Item_Struct)); + memcpy(m_scaledItem, m_item, sizeof(EQEmu::Item_Struct)); } else { - m_scaledItem = new Item_Struct(*m_item); + m_scaledItem = new EQEmu::Item_Struct(*m_item); } float Mult = (float)(GetExp()) / 10000; // scaling is determined by exp, with 10,000 being full stats @@ -3051,41 +3066,3 @@ EvolveInfo::EvolveInfo(uint32 first, uint8 max, bool allkills, uint32 L2, uint32 EvolveInfo::~EvolveInfo() { } - - -// -// struct Item_Struct -// -bool Item_Struct::IsEquipable(uint16 Race, uint16 Class_) const -{ - bool IsRace = false; - bool IsClass = false; - - uint32 Classes_ = Classes; - uint32 Races_ = Races; - uint32 Race_ = GetPlayerRaceValue(Race); - - for (int CurrentClass = 1; CurrentClass <= PLAYER_CLASS_COUNT; ++CurrentClass) { - if (Classes_ & 1) { - if (CurrentClass == Class_) { - IsClass = true; - break; - } - } - Classes_ >>= 1; - } - - Race_ = (Race_ == 18 ? 16 : Race_); - - for (unsigned int CurrentRace = 1; CurrentRace <= PLAYER_RACE_COUNT; ++CurrentRace) { - if (Races_ & 1) { - if (CurrentRace == Race_) { - IsRace = true; - break; - } - } - Races_ >>= 1; - } - - return (IsRace && IsClass); -} diff --git a/common/item.h b/common/item.h index 7d60afdac..bc002fa6f 100644 --- a/common/item.h +++ b/common/item.h @@ -1,5 +1,6 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,15 +14,16 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA */ // @merth notes: // These classes could be optimized with database reads/writes by storing // a status flag indicating how object needs to interact with database -#ifndef __ITEM_H -#define __ITEM_H +#ifndef COMMON_ITEM_H +#define COMMON_ITEM_H + class ItemParse; // Parses item packets class EvolveInfo; // Stores information about an evolving item family @@ -173,7 +175,7 @@ public: ItemInst* PopItem(int16 slot_id); // Check whether there is space for the specified number of the specified item. - bool HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity); + bool HasSpaceForItem(const EQEmu::Item_Struct *ItemToTry, int16 Quantity); // Check whether item exists in inventory // where argument specifies OR'd list of invWhere constants to look @@ -198,7 +200,7 @@ public: static int16 CalcSlotFromMaterial(uint8 material); static uint8 CalcMaterialFromSlot(int16 equipslot); - static bool CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_Struct *Container); + static bool CanItemFitInContainer(const EQEmu::Item_Struct *ItemToTry, const EQEmu::Item_Struct *Container); // Test for valid inventory casting slot bool SupportsClickCasting(int16 slot_id); @@ -275,7 +277,7 @@ public: ///////////////////////// // Constructors/Destructor - ItemInst(const Item_Struct* item = nullptr, int16 charges = 0); + ItemInst(const EQEmu::Item_Struct* item = nullptr, int16 charges = 0); ItemInst(SharedDatabase *db, uint32 item_id, int16 charges = 0); @@ -286,7 +288,15 @@ public: ~ItemInst(); // Query item type - bool IsType(ItemClassTypes item_class) const; + bool IsType(EQEmu::item::ItemClass item_class) const; + + bool IsClassCommon(); + bool IsClassBag(); + bool IsClassBook(); + + bool IsClassCommon() const { return const_cast(this)->IsClassCommon(); } + bool IsClassBag() const { return const_cast(this)->IsClassBag(); } + bool IsClassBook() const { return const_cast(this)->IsClassBook(); } // Can item be stacked? bool IsStackable() const; @@ -305,7 +315,7 @@ public: bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const; inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : NO_ITEM); } - inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == ET_Expendable ) || (m_item->ItemType == ItemTypePotion)) : false); } + inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == EQEmu::item::ItemEffectExpendable) || (m_item->ItemType == EQEmu::item::ItemTypePotion)) : false); } // // Contents @@ -336,7 +346,7 @@ public: bool IsAugmented(); ItemInst* GetOrnamentationAug(int32 ornamentationAugtype) const; bool UpdateOrnamentationInfo(); - static bool CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll = false); + static bool CanTransform(const EQEmu::Item_Struct *ItemToTry, const EQEmu::Item_Struct *Container, bool AllowAll = false); // Has attack/delay? bool IsWeapon() const; @@ -345,8 +355,8 @@ public: // Accessors const uint32 GetID() const { return ((m_item) ? m_item->ID : NO_ITEM); } const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : NO_ITEM); } - const Item_Struct* GetItem() const; - const Item_Struct* GetUnscaledItem() const; + const EQEmu::Item_Struct* GetItem() const; + const EQEmu::Item_Struct* GetUnscaledItem() const; int16 GetCharges() const { return m_charges; } void SetCharges(int16 charges) { m_charges = charges; } @@ -414,8 +424,8 @@ public: int8 GetMaxEvolveLvl() const; uint32 GetKillsNeeded(uint8 currentlevel); - std::string Serialize(int16 slot_id) const { InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(InternalSerializedItem_Struct)); return ser; } - void Serialize(EQEmu::OutBuffer& ob, int16 slot_id) const { InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); } + std::string Serialize(int16 slot_id) const { EQEmu::InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(EQEmu::InternalSerializedItem_Struct)); return ser; } + void Serialize(EQEmu::OutBuffer& ob, int16 slot_id) const { EQEmu::InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); } inline int32 GetSerialNumber() const { return m_SerialNumber; } inline void SetSerialNumber(int32 id) { m_SerialNumber = id; } @@ -490,7 +500,7 @@ protected: void _PutItem(uint8 index, ItemInst* inst) { m_contents[index] = inst; } ItemInstTypes m_use_type; // Usage type for item - const Item_Struct* m_item; // Ptr to item data + const EQEmu::Item_Struct* m_item; // Ptr to item data int16 m_charges; // # of charges for chargeable items uint32 m_price; // Bazaar /trader price uint32 m_color; @@ -502,7 +512,7 @@ protected: uint32 m_exp; int8 m_evolveLvl; bool m_activated; - Item_Struct* m_scaledItem; + EQEmu::Item_Struct* m_scaledItem; EvolveInfo* m_evolveInfo; bool m_scaling; uint32 m_ornamenticon; @@ -531,4 +541,4 @@ public: ~EvolveInfo(); }; -#endif // #define __ITEM_H +#endif /*COMMON_ITEM_H*/ diff --git a/common/item_struct.cpp b/common/item_struct.cpp new file mode 100644 index 000000000..7bc202bdb --- /dev/null +++ b/common/item_struct.cpp @@ -0,0 +1,209 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "item_struct.h" +#include "classes.h" +#include "races.h" +//#include "deity.h" + + +uint32 EQEmu::item::ConvertAugTypeToAugTypeBit(uint8 aug_type) +{ + switch (aug_type) { + case AugTypeGeneralSingleStat: + return bit_AugTypeGeneralSingleStat; + case AugTypeGeneralMultipleStat: + return bit_AugTypeGeneralMultipleStat; + case AugTypeGeneralSpellEffect: + return bit_AugTypeGeneralSpellEffect; + case AugTypeWeaponGeneral: + return bit_AugTypeWeaponGeneral; + case AugTypeWeaponElemDamage: + return bit_AugTypeWeaponElemDamage; + case AugTypeWeaponBaseDamage: + return bit_AugTypeWeaponBaseDamage; + case AugTypeGeneralGroup: + return bit_AugTypeGeneralGroup; + case AugTypeGeneralRaid: + return bit_AugTypeGeneralRaid; + case AugTypeGeneralDragonsPoints: + return bit_AugTypeGeneralDragonsPoints; + case AugTypeCraftedCommon: + return bit_AugTypeCraftedCommon; + case AugTypeCraftedGroup1: + return bit_AugTypeCraftedGroup1; + case AugTypeCraftedRaid1: + return bit_AugTypeCraftedRaid1; + case AugTypeEnergeiacGroup: + return bit_AugTypeEnergeiacGroup; + case AugTypeEnergeiacRaid: + return bit_AugTypeEnergeiacRaid; + case AugTypeEmblem: + return bit_AugTypeEmblem; + case AugTypeCraftedGroup2: + return bit_AugTypeCraftedGroup2; + case AugTypeCraftedRaid2: + return bit_AugTypeCraftedRaid2; + case AugTypeUnknown1: + return bit_AugTypeUnknown1; + case AugTypeUnknown2: + return bit_AugTypeUnknown2; + case AugTypeOrnamentation: + return bit_AugTypeOrnamentation; + case AugTypeSpecialOrnamentation: + return bit_AugTypeSpecialOrnamentation; + case AugTypeUnknown3: + return bit_AugTypeUnknown3; + case AugTypeUnknown4: + return bit_AugTypeUnknown4; + case AugTypeUnknown5: + return bit_AugTypeUnknown5; + case AugTypeUnknown6: + return bit_AugTypeUnknown6; + case AugTypeUnknown7: + return bit_AugTypeUnknown7; + case AugTypeUnknown8: + return bit_AugTypeUnknown8; + case AugTypeUnknown9: + return bit_AugTypeUnknown9; + case AugTypeUnknown10: + return bit_AugTypeUnknown10; + case AugTypeEpic2_5: + return bit_AugTypeEpic2_5; + case AugTypeTest: + return bit_AugTypeTest; + case AugTypeAll: + return bit_AugTypeAll; + default: + return bit_AugTypeNone; + } +} + +uint8 EQEmu::item::ConvertAugTypeBitToAugType(uint32 aug_type_bit) +{ + switch (aug_type_bit) { + case bit_AugTypeGeneralSingleStat: + return AugTypeGeneralSingleStat; + case bit_AugTypeGeneralMultipleStat: + return AugTypeGeneralMultipleStat; + case bit_AugTypeGeneralSpellEffect: + return AugTypeGeneralSpellEffect; + case bit_AugTypeWeaponGeneral: + return AugTypeWeaponGeneral; + case bit_AugTypeWeaponElemDamage: + return AugTypeWeaponElemDamage; + case bit_AugTypeWeaponBaseDamage: + return AugTypeWeaponBaseDamage; + case bit_AugTypeGeneralGroup: + return AugTypeGeneralGroup; + case bit_AugTypeGeneralRaid: + return AugTypeGeneralRaid; + case bit_AugTypeGeneralDragonsPoints: + return AugTypeGeneralDragonsPoints; + case bit_AugTypeCraftedCommon: + return AugTypeCraftedCommon; + case bit_AugTypeCraftedGroup1: + return AugTypeCraftedGroup1; + case bit_AugTypeCraftedRaid1: + return AugTypeCraftedRaid1; + case bit_AugTypeEnergeiacGroup: + return AugTypeEnergeiacGroup; + case bit_AugTypeEnergeiacRaid: + return AugTypeEnergeiacRaid; + case bit_AugTypeEmblem: + return AugTypeEmblem; + case bit_AugTypeCraftedGroup2: + return AugTypeCraftedGroup2; + case bit_AugTypeCraftedRaid2: + return AugTypeCraftedRaid2; + case bit_AugTypeUnknown1: + return AugTypeUnknown1; + case bit_AugTypeUnknown2: + return AugTypeUnknown2; + case bit_AugTypeOrnamentation: + return AugTypeOrnamentation; + case bit_AugTypeSpecialOrnamentation: + return AugTypeSpecialOrnamentation; + case bit_AugTypeUnknown3: + return AugTypeUnknown3; + case bit_AugTypeUnknown4: + return AugTypeUnknown4; + case bit_AugTypeUnknown5: + return AugTypeUnknown5; + case bit_AugTypeUnknown6: + return AugTypeUnknown6; + case bit_AugTypeUnknown7: + return AugTypeUnknown7; + case bit_AugTypeUnknown8: + return AugTypeUnknown8; + case bit_AugTypeUnknown9: + return AugTypeUnknown9; + case bit_AugTypeUnknown10: + return AugTypeUnknown10; + case bit_AugTypeEpic2_5: + return AugTypeEpic2_5; + case bit_AugTypeTest: + return AugTypeTest; + case bit_AugTypeAll: + return AugTypeAll; + default: + return AugTypeNone; + } +} + +bool EQEmu::Item_Struct::IsEquipable(uint16 race_id, uint16 class_id) +{ + if (!(Races & GetPlayerRaceBit(GetPlayerRaceValue(race_id)))) + return false; + + if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) + return false; + + return true; +} + +bool EQEmu::Item_Struct::IsClassCommon() +{ + return (ItemClass == item::ItemClassCommon); +} + +bool EQEmu::Item_Struct::IsClassBag() +{ + return (ItemClass == item::ItemClassBag); +} + +bool EQEmu::Item_Struct::IsClassBook() +{ + return (ItemClass == item::ItemClassBook); +} + +bool EQEmu::Item_Struct::IsType1HWeapon() +{ + return ((ItemType == item::ItemType1HBlunt) || (ItemType == item::ItemType1HSlash) || (ItemType == item::ItemType1HPiercing)); +} + +bool EQEmu::Item_Struct::IsType2HWeapon() +{ + return ((ItemType == item::ItemType2HBlunt) || (ItemType == item::ItemType2HSlash) || (ItemType == item::ItemType2HPiercing)); +} + +bool EQEmu::Item_Struct::IsTypeShield() +{ + return (ItemType == item::ItemTypeShield); +} diff --git a/common/item_struct.h b/common/item_struct.h index 226458d70..c56d32a67 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -1,4 +1,5 @@ /* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -13,11 +14,12 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA */ -#ifndef ITEM_STRUCT_H -#define ITEM_STRUCT_H +#ifndef COMMON_ITEM_STRUCT_H +#define COMMON_ITEM_STRUCT_H + /* * Note: (Doodman) @@ -44,211 +46,520 @@ #include "emu_constants.h" + +namespace EQEmu +{ + namespace item { + enum ItemAttributeBit : uint32 { + bit_ItemAttributeNone = 0x00000000, + bit_ItemAttributeLore = 0x00000001, + bit_ItemAttributeArtifact = 0x00000002, + bit_ItemAttributeSummoned = 0x00000004, + bit_ItemAttributeMagic = 0x00000008, + bit_ItemAttributeAugment = 0x00000010, + bit_ItemAttributePendingLore = 0x00000020, + bit_ItemAttributeUnknown = 0xFFFFFFFF + }; + + enum ItemClass { + ItemClassCommon = 0, + ItemClassBag, + ItemClassBook, + ItemClassCount + }; + + enum ItemType : uint8 { +/*9138*/ ItemType1HSlash = 0, +/*9141*/ ItemType2HSlash, +/*9140*/ ItemType1HPiercing, +/*9139*/ ItemType1HBlunt, +/*9142*/ ItemType2HBlunt, +/*5504*/ ItemTypeBow, // 5 +/*----*/ ItemTypeUnknown1, +/*----*/ ItemTypeLargeThrowing, +/*5505*/ ItemTypeShield, +/*5506*/ ItemTypeScroll, +/*5507*/ ItemTypeArmor, // 10 +/*5508*/ ItemTypeMisc, // a lot of random crap has this item use. +/*7564*/ ItemTypeLockPick, +/*----*/ ItemTypeUnknown2, +/*5509*/ ItemTypeFood, +/*5510*/ ItemTypeDrink, // 15 +/*5511*/ ItemTypeLight, +/*5512*/ ItemTypeCombinable, // not all stackable items are this use... +/*5513*/ ItemTypeBandage, +/*----*/ ItemTypeSmallThrowing, +/*----*/ ItemTypeSpell, // 20 // spells and tomes +/*5514*/ ItemTypePotion, +/*----*/ ItemTypeUnknown3, +/*0406*/ ItemTypeWindInstrument, +/*0407*/ ItemTypeStringedInstrument, +/*0408*/ ItemTypeBrassInstrument, // 25 +/*0405*/ ItemTypePercussionInstrument, +/*5515*/ ItemTypeArrow, +/*----*/ ItemTypeUnknown4, +/*5521*/ ItemTypeJewelry, +/*----*/ ItemTypeSkull, // 30 +/*5516*/ ItemTypeBook, // skill-up tomes/books? (would probably need a pp flag if true...) +/*5517*/ ItemTypeNote, +/*5518*/ ItemTypeKey, +/*----*/ ItemTypeCoin, +/*5520*/ ItemType2HPiercing, // 35 +/*----*/ ItemTypeFishingPole, +/*----*/ ItemTypeFishingBait, +/*5519*/ ItemTypeAlcohol, +/*----*/ ItemTypeKey2, // keys and satchels?? (questable keys?) +/*----*/ ItemTypeCompass, // 40 +/*----*/ ItemTypeUnknown5, +/*----*/ ItemTypePoison, // might be wrong, but includes poisons +/*----*/ ItemTypeUnknown6, +/*----*/ ItemTypeUnknown7, +/*5522*/ ItemTypeMartial, // 45 +/*----*/ ItemTypeUnknown8, +/*----*/ ItemTypeUnknown9, +/*----*/ ItemTypeUnknown10, +/*----*/ ItemTypeUnknown11, +/*----*/ ItemTypeSinging, // 50 +/*5750*/ ItemTypeAllInstrumentTypes, +/*5776*/ ItemTypeCharm, +/*----*/ ItemTypeDye, +/*----*/ ItemTypeAugmentation, +/*----*/ ItemTypeAugmentationSolvent, // 55 +/*----*/ ItemTypeAugmentationDistiller, +/*----*/ ItemTypeUnknown12, +/*----*/ ItemTypeFellowshipKit, +/*----*/ ItemTypeUnknown13, +/*----*/ ItemTypeRecipe, // 60 +/*----*/ ItemTypeAdvancedRecipe, +/*----*/ ItemTypeJournal, // only one(1) database entry +/*----*/ ItemTypeAltCurrency, // alt-currency (as opposed to coinage) +/*5881*/ ItemTypePerfectedAugmentationDistiller, +/*----*/ ItemTypeCount + /* -** Child struct of Item_Struct: -** Effect data: Click, Proc, Focus, Worn, Scroll -** + Unknowns: + + Mounts? + Ornamentations? + GuildBanners? + Collectible? + Placeable? + (others?) */ -struct ItemEffect_Struct { - int32 Effect; - uint8 Type; - uint8 Level; - uint8 Level2; - //MaxCharges - //CastTime - //RecastDelay - //RecastType - //ProcRate -}; + }; -class ItemInst; + enum AugTypeBit : uint32 { + bit_AugTypeNone = 0x00000000, + bit_AugTypeGeneralSingleStat = 0x00000001, /*1^16^1 (General: Single Stat)^0*/ + bit_AugTypeGeneralMultipleStat = 0x00000002, /*2^16^2 (General: Multiple Stat)^0*/ + bit_AugTypeGeneralSpellEffect = 0x00000004, /*3^16^3 (General: Spell Effect)^0*/ + bit_AugTypeWeaponGeneral = 0x00000008, /*4^16^4 (Weapon: General)^0*/ + bit_AugTypeWeaponElemDamage = 0x00000010, /*5^16^5 (Weapon: Elem Damage)^0*/ + bit_AugTypeWeaponBaseDamage = 0x00000020, /*6^16^6 (Weapon: Base Damage)^0*/ + bit_AugTypeGeneralGroup = 0x00000040, /*7^16^7 (General: Group)^0*/ + bit_AugTypeGeneralRaid = 0x00000080, /*8^16^8 (General: Raid)^0*/ + bit_AugTypeGeneralDragonsPoints = 0x00000100, /*9^16^9 (General: Dragons Points)^0*/ + bit_AugTypeCraftedCommon = 0x00000200, /*10^16^10 (Crafted: Common)^0*/ + bit_AugTypeCraftedGroup1 = 0x00000400, /*11^16^11 (Crafted: Group)^0*/ + bit_AugTypeCraftedRaid1 = 0x00000800, /*12^16^12 (Crafted: Raid)^0*/ + bit_AugTypeEnergeiacGroup = 0x00001000, /*13^16^13 (Energeiac: Group)^0*/ + bit_AugTypeEnergeiacRaid = 0x00002000, /*14^16^14 (Energeiac: Raid)^0*/ + bit_AugTypeEmblem = 0x00004000, /*15^16^15 (Emblem)^0*/ + bit_AugTypeCraftedGroup2 = 0x00008000, /*16^16^16 (Crafted: Group)^0*/ + bit_AugTypeCraftedRaid2 = 0x00010000, /*17^16^17 (Crafted: Raid)^0*/ + bit_AugTypeUnknown1 = 0x00020000, /*18^16^18^0*/ + bit_AugTypeUnknown2 = 0x00040000, /*19^16^19^0*/ + bit_AugTypeOrnamentation = 0x00080000, /*20^16^20 (Ornamentation)^0*/ + bit_AugTypeSpecialOrnamentation = 0x00100000, /*21^16^21 (Special Ornamentation)^0*/ + bit_AugTypeUnknown3 = 0x00200000, /*22^16^22^0*/ + bit_AugTypeUnknown4 = 0x00400000, /*23^16^23^0*/ + bit_AugTypeUnknown5 = 0x00800000, /*24^16^24^0*/ + bit_AugTypeUnknown6 = 0x01000000, /*25^16^25^0*/ + bit_AugTypeUnknown7 = 0x02000000, /*26^16^26^0*/ + bit_AugTypeUnknown8 = 0x04000000, /*27^16^27^0*/ + bit_AugTypeUnknown9 = 0x08000000, /*28^16^28^0*/ + bit_AugTypeUnknown10 = 0x10000000, /*29^16^29^0*/ + bit_AugTypeEpic2_5 = 0x20000000, /*30^16^30^0*/ + bit_AugTypeTest = 0x40000000, /*31^16^Test^0*/ // listed as 31^16^31^0 in 5-10 client + bit_AugTypeAll = 0xFFFFFFFF + }; -struct InternalSerializedItem_Struct { - int16 slot_id; - const void * inst; -}; + enum AugType : uint8 { + AugTypeNone = 0, + AugTypeGeneralSingleStat, + AugTypeGeneralMultipleStat, + AugTypeGeneralSpellEffect, + AugTypeWeaponGeneral, + AugTypeWeaponElemDamage, // 5 + AugTypeWeaponBaseDamage, + AugTypeGeneralGroup, + AugTypeGeneralRaid, + AugTypeGeneralDragonsPoints, + AugTypeCraftedCommon, // 10 + AugTypeCraftedGroup1, + AugTypeCraftedRaid1, + AugTypeEnergeiacGroup, + AugTypeEnergeiacRaid, + AugTypeEmblem, // 15 + AugTypeCraftedGroup2, + AugTypeCraftedRaid2, + AugTypeUnknown1, + AugTypeUnknown2, + AugTypeOrnamentation, // 20 + AugTypeSpecialOrnamentation, + AugTypeUnknown3, + AugTypeUnknown4, + AugTypeUnknown5, + AugTypeUnknown6, // 25 + AugTypeUnknown7, + AugTypeUnknown8, + AugTypeUnknown9, + AugTypeUnknown10, + AugTypeEpic2_5, // 30 + AugTypeTest, + AugTypeCount, + AugTypeAll = 255 + }; -// use EmuConstants::ITEM_COMMON_SIZE -//#define MAX_AUGMENT_SLOTS 5 + enum AugRestriction : uint8 { +/*4690*/ AugRestrictionAny = 0, +/*9134*/ AugRestrictionArmor, +/*9135*/ AugRestrictionWeapons, +/*9136*/ AugRestriction1HWeapons, +/*9137*/ AugRestriction2HWeapons, +/*9138*/ AugRestriction1HSlash, // 5 +/*9139*/ AugRestriction1HBlunt, +/*9140*/ AugRestrictionPiercing, +/*9148*/ AugRestrictionHandToHand, +/*9141*/ AugRestriction2HSlash, +/*9142*/ AugRestriction2HBlunt, // 10 +/*9143*/ AugRestriction2HPierce, +/*9144*/ AugRestrictionBows, +/*9145*/ AugRestrictionShields, +/*8052*/ AugRestriction1HSlash1HBluntOrHandToHand, +/*9200*/ AugRestriction1HBluntOrHandToHand, // 15 // no listed peq entries -struct Item_Struct { - bool IsEquipable(uint16 Race, uint16 Class) const; - // Non packet based fields - uint8 MinStatus; + // these three appear to be post-RoF (12-10-2012) and can not be verified until RoF (05-10-2013) is supported +/*????*/ AugRestrictionUnknown1, +/*????*/ AugRestrictionUnknown2, +/*????*/ AugRestrictionUnknown3, // last value in peq entries + AugRestrictionCount - // Packet based fields - uint8 ItemClass; // Item Type: 0=common, 1=container, 2=book - char Name[64]; // Name - char Lore[80]; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore - char IDFile[30]; // Visible model - uint32 ID; // Unique ID (also PK for DB) - int32 Weight; // Item weight * 10 - uint8 NoRent; // No Rent: 0=norent, 255=not norent - uint8 NoDrop; // No Drop: 0=nodrop, 255=not nodrop - uint8 Size; // Size: 0=tiny, 1=small, 2=medium, 3=large, 4=giant - uint32 Slots; // Bitfield for which slots this item can be used in - uint32 Price; // Item cost (?) - uint32 Icon; // Icon Number - uint32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295) - bool LoreFlag; // This will be true if LoreGroup is non-zero - bool PendingLoreFlag; - bool ArtifactFlag; - bool SummonedFlag; - uint8 FVNoDrop; // Firiona Vie nodrop flag - uint32 Favor; // Individual favor - uint32 GuildFavor; // Guild favor - uint32 PointType; +/*4687*/ //AugTypeAllItems, // ?? unknown atm +/*4688*/ //AugTypePrestige, // ?? unknown atm +/*4689*/ //AugTypeNonPrestige, // ?? unknown atm + }; - //uint32 Unk117; - //uint32 Unk118; - //uint32 Unk121; - //uint32 Unk124; + enum BagType : uint8 { +/*3400*/ BagTypeSmallBag = 0, +/*3401*/ BagTypeLargeBag, +/*3402*/ BagTypeQuiver, +/*3403*/ BagTypeBeltPouch, +/*3404*/ BagTypeWristPouch, +/*3405*/ BagTypeBackPack, // 5 +/*3406*/ BagTypeSmallChest, +/*3407*/ BagTypeLargeChest, +/*----*/ BagTypeBandolier, // <*Database Reference Only> +/*3408*/ BagTypeMedicineBag, +/*3409*/ BagTypeToolBox, // 10 +/*3410*/ BagTypeLexicon, +/*3411*/ BagTypeMortar, +/*3412*/ BagTypeSelfDusting, // Quest container (Auto-clear contents?) +/*3413*/ BagTypeMixingBowl, +/*3414*/ BagTypeOven, // 15 +/*3415*/ BagTypeSewingKit, +/*3416*/ BagTypeForge, +/*3417*/ BagTypeFletchingKit, +/*3418*/ BagTypeBrewBarrel, +/*3419*/ BagTypeJewelersKit, // 20 +/*3420*/ BagTypePotteryWheel, +/*3421*/ BagTypeKiln, +/*3422*/ BagTypeKeymaker, // (no database entries as of peq rev 69) +/*3423*/ BagTypeWizardsLexicon, +/*3424*/ BagTypeMagesLexicon, // 25 +/*3425*/ BagTypeNecromancersLexicon, +/*3426*/ BagTypeEnchantersLexicon, +/*----*/ BagTypeUnknown1, // (a coin pouch/purse?) (no database entries as of peq rev 69) +/*----*/ BagTypeConcordanceofResearch, // <*Database Reference Only> +/*3427*/ BagTypeAlwaysWorks, // 30 // Quest container (Never-fail combines?) +/*3428*/ BagTypeKoadaDalForge, // High Elf +/*3429*/ BagTypeTeirDalForge, // Dark Elf +/*3430*/ BagTypeOggokForge, // Ogre +/*3431*/ BagTypeStormguardForge, // Dwarf +/*3432*/ BagTypeAkanonForge, // 35 // Gnome +/*3433*/ BagTypeNorthmanForge, // Barbarian +/*----*/ BagTypeUnknown2, // (no database entries as of peq rev 69) +/*3434*/ BagTypeCabilisForge, // Iksar +/*3435*/ BagTypeFreeportForge, // Human 1 +/*3436*/ BagTypeRoyalQeynosForge, // 40 // Human 2 +/*3439*/ BagTypeHalflingTailoringKit, +/*3438*/ BagTypeErudTailoringKit, +/*3440*/ BagTypeFierDalTailoringKit, // Wood Elf +/*3441*/ BagTypeFierDalFletchingKit, // Wood Elf +/*3437*/ BagTypeIksarPotteryWheel, // 45 +/*3442*/ BagTypeTackleBox, +/*3443*/ BagTypeTrollForge, +/*3445*/ BagTypeFierDalForge, // Wood Elf +/*3444*/ BagTypeValeForge, // Halfling +/*3446*/ BagTypeErudForge, // 50 +/*----*/ BagTypeTradersSatchel, // <*Database Reference Only> (db: Yellow Trader's Satchel Token?) +/*5785*/ BagTypeGuktaForge, // Froglok (no database entries as of peq rev 69) +/*3359*/ BagTypeAugmentationSealer, +/*----*/ BagTypeIceCreamChurn, // <*Database Reference Only> +/*6325*/ BagTypeTransformationmold, // 55 // Ornamentation +/*6340*/ BagTypeDetransformationmold, // Ornamentation Stripper +/*5400*/ BagTypeUnattuner, +/*7684*/ BagTypeTradeskillBag, +/*7692*/ BagTypeCollectibleBag, +/*----*/ BagTypeCount + }; - uint8 BagType; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types - uint8 BagSlots; // Number of slots: can only be 2, 4, 6, 8, or 10 - uint8 BagSize; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT - uint8 BagWR; // 0->100 + enum ItemEffect { + ItemEffectCombatProc = 0, + ItemEffectClick, + ItemEffectWorn, + ItemEffectExpendable, + ItemEffectEquipClick, + ItemEffectClick2, //5 //name unknown + ItemEffectFocus, + ItemEffectScroll, + ItemEffectCount + }; - bool BenefitFlag; - bool Tradeskills; // Is this a tradeskill item? - int8 CR; // Save vs Cold - int8 DR; // Save vs Disease - int8 PR; // Save vs Poison - int8 MR; // Save vs Magic - int8 FR; // Save vs Fire - int8 AStr; // Strength - int8 ASta; // Stamina - int8 AAgi; // Agility - int8 ADex; // Dexterity - int8 ACha; // Charisma - int8 AInt; // Intelligence - int8 AWis; // Wisdom - int32 HP; // HP - int32 Mana; // Mana - int32 AC; // AC - uint32 Deity; // Bitmask of Deities that can equip this item - //uint32 Unk033 - int32 SkillModValue; // % Mod to skill specified in SkillModType - int32 SkillModMax; // Max skill point modification - uint32 SkillModType; // Type of skill for SkillModValue to apply to - uint32 BaneDmgRace; // Bane Damage Race - int8 BaneDmgAmt; // Bane Damage Body Amount - uint32 BaneDmgBody; // Bane Damage Body - bool Magic; // True=Magic Item, False=not - int32 CastTime_; - uint8 ReqLevel; // Required Level to use item - uint32 BardType; // Bard Skill Type - int32 BardValue; // Bard Skill Amount - int8 Light; // Light - uint8 Delay; // Delay * 10 - uint8 RecLevel; // Recommended level to use item - uint8 RecSkill; // Recommended skill to use item (refers to primary skill of item) - uint8 ElemDmgType; // Elemental Damage Type (1=magic, 2=fire) - uint8 ElemDmgAmt; // Elemental Damage - uint8 Range; // Range of item - uint32 Damage; // Delay between item usage (in 0.1 sec increments) - uint32 Color; // RR GG BB 00 <-- as it appears in pc - uint32 Classes; // Bitfield of classes that can equip item (1 << class#) - uint32 Races; // Bitfield of races that can equip item (1 << race#) - //uint32 Unk054; - int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item - uint8 ItemType; // Item Type/Skill (itemClass* from above) - uint8 Material; // Item material type - uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?) - float SellRate; // Sell rate - //uint32 Unk059; - union { - uint32 Fulfilment; // Food fulfilment (How long it lasts) - uint32 CastTime; // Cast Time for clicky effects, in milliseconds + enum ItemSize : uint8 { + ItemSizeTiny = 0, + ItemSizeSmall, + ItemSizeMedium, + ItemSizeLarge, + ItemSizeGiant, + ItemSizeCount + }; + + enum ItemDataType : uint8 { + ItemDataTypeBase = 0, + ItemDataTypeScaling, + ItemDataTypeEvolving, + ItemDataTypeCount + }; + + struct ItemEffect_Struct { + int16 Effect; + uint8 Type; + uint8 Level; + uint8 Level2; + //MaxCharges + //CastTime + //RecastDelay + //RecastType + //ProcRate + }; + + extern uint32 ConvertAugTypeToAugTypeBit(uint8 aug_type); + extern uint8 ConvertAugTypeBitToAugType(uint32 aug_type_bit); + + } /*item*/ + + struct InternalSerializedItem_Struct { + int16 slot_id; + const void * inst; }; - uint32 EliteMaterial; - int32 ProcRate; - int8 CombatEffects; // PoP: Combat Effects + - int8 Shielding; // PoP: Shielding % - int8 StunResist; // PoP: Stun Resist % - int8 StrikeThrough; // PoP: Strike Through % - uint32 ExtraDmgSkill; - uint32 ExtraDmgAmt; - int8 SpellShield; // PoP: Spell Shield % - int8 Avoidance; // PoP: Avoidance + - int8 Accuracy; // PoP: Accuracy + - uint32 CharmFileID; - int32 FactionMod1; // Faction Mod 1 - int32 FactionMod2; // Faction Mod 2 - int32 FactionMod3; // Faction Mod 3 - int32 FactionMod4; // Faction Mod 4 - int32 FactionAmt1; // Faction Amt 1 - int32 FactionAmt2; // Faction Amt 2 - int32 FactionAmt3; // Faction Amt 3 - int32 FactionAmt4; // Faction Amt 4 - char CharmFile[32]; // ? - uint32 AugType; - uint8 AugSlotType[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Type - uint8 AugSlotVisible[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Visible - uint8 AugSlotUnk2[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related - uint32 LDoNTheme; - uint32 LDoNPrice; - uint32 LDoNSold; - uint32 BaneDmgRaceAmt; - uint32 AugRestrict; - uint32 Endur; - uint32 DotShielding; - uint32 Attack; - uint32 Regen; - uint32 ManaRegen; - uint32 EnduranceRegen; - uint32 Haste; - uint32 DamageShield; - uint32 RecastDelay; - uint32 RecastType; - uint32 AugDistiller; - bool Attuneable; - bool NoPet; - bool PotionBelt; - bool Stackable; - bool NoTransfer; - bool QuestItemFlag; - int16 StackSize; - uint8 PotionBeltSlots; - ItemEffect_Struct Click, Proc, Worn, Focus, Scroll, Bard; - uint8 Book; // 0=Not book, 1=Book - uint32 BookType; - char Filename[33]; // Filename for book data - // Begin SoF Fields - int32 SVCorruption; - uint32 Purity; - uint8 EvolvingItem; - uint32 EvolvingID; - uint8 EvolvingLevel; - uint8 EvolvingMax; - uint32 BackstabDmg; - uint32 DSMitigation; - int32 HeroicStr; - int32 HeroicInt; - int32 HeroicWis; - int32 HeroicAgi; - int32 HeroicDex; - int32 HeroicSta; - int32 HeroicCha; - int32 HeroicMR; - int32 HeroicFR; - int32 HeroicCR; - int32 HeroicDR; - int32 HeroicPR; - int32 HeroicSVCorrup; - int32 HealAmt; - int32 SpellDmg; - uint32 LDoNSellBackRate; - uint32 ScriptFileID; - uint16 ExpendableArrow; - uint32 Clairvoyance; - char ClickName[65]; - char ProcName[65]; - char WornName[65]; - char FocusName[65]; - char ScrollName[65]; + struct Item_Struct { + // Non packet based fields + uint8 MinStatus; + //uint8 ItemDataType; -}; + // Packet based fields + uint8 ItemClass; // Item Type: 0=common, 1=container, 2=book + char Name[64]; // Name + char Lore[80]; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore + char IDFile[30]; // Visible model + uint32 ID; // Unique ID (also PK for DB) + int32 Weight; // Item weight * 10 + uint8 NoRent; // No Rent: 0=norent, 255=not norent + uint8 NoDrop; // No Drop: 0=nodrop, 255=not nodrop + uint8 Size; // Size: 0=tiny, 1=small, 2=medium, 3=large, 4=giant + uint32 Slots; // Bitfield for which slots this item can be used in + uint32 Price; // Item cost (?) + uint32 Icon; // Icon Number + uint32 LoreGroup; // Later items use LoreGroup instead of LoreFlag. we might want to see about changing this to int32 since it is commonly -1 and is constantly being cast from signed (-1) to unsigned (4294967295) + bool LoreFlag; // This will be true if LoreGroup is non-zero + bool PendingLoreFlag; + bool ArtifactFlag; + bool SummonedFlag; + uint8 FVNoDrop; // Firiona Vie nodrop flag + uint32 Favor; // Individual favor + uint32 GuildFavor; // Guild favor + uint32 PointType; -#endif + //uint32 Unk117; + //uint32 Unk118; + //uint32 Unk121; + //uint32 Unk124; + + uint8 BagType; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types + uint8 BagSlots; // Number of slots: can only be 2, 4, 6, 8, or 10 + uint8 BagSize; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT + uint8 BagWR; // 0->100 + + bool BenefitFlag; + bool Tradeskills; // Is this a tradeskill item? + int8 CR; // Save vs Cold + int8 DR; // Save vs Disease + int8 PR; // Save vs Poison + int8 MR; // Save vs Magic + int8 FR; // Save vs Fire + int8 AStr; // Strength + int8 ASta; // Stamina + int8 AAgi; // Agility + int8 ADex; // Dexterity + int8 ACha; // Charisma + int8 AInt; // Intelligence + int8 AWis; // Wisdom + int32 HP; // HP + int32 Mana; // Mana + int32 AC; // AC + uint32 Deity; // Bitmask of Deities that can equip this item + //uint32 Unk033 + int32 SkillModValue; // % Mod to skill specified in SkillModType + int32 SkillModMax; // Max skill point modification + uint32 SkillModType; // Type of skill for SkillModValue to apply to + uint32 BaneDmgRace; // Bane Damage Race + int8 BaneDmgAmt; // Bane Damage Body Amount + uint32 BaneDmgBody; // Bane Damage Body + bool Magic; // True=Magic Item, False=not + int32 CastTime_; + uint8 ReqLevel; // Required Level to use item + uint32 BardType; // Bard Skill Type + int32 BardValue; // Bard Skill Amount + int8 Light; // Light + uint8 Delay; // Delay * 10 + uint8 RecLevel; // Recommended level to use item + uint8 RecSkill; // Recommended skill to use item (refers to primary skill of item) + uint8 ElemDmgType; // Elemental Damage Type (1=magic, 2=fire) + uint8 ElemDmgAmt; // Elemental Damage + uint8 Range; // Range of item + uint32 Damage; // Delay between item usage (in 0.1 sec increments) + uint32 Color; // RR GG BB 00 <-- as it appears in pc + uint32 Classes; // Bitfield of classes that can equip item (1 << class#) + uint32 Races; // Bitfield of races that can equip item (1 << race#) + //uint32 Unk054; + int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item + uint8 ItemType; // Item Type/Skill (itemClass* from above) + uint8 Material; // Item material type + uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?) + float SellRate; // Sell rate + //uint32 Unk059; + union { + uint32 Fulfilment; // Food fulfilment (How long it lasts) + uint32 CastTime; // Cast Time for clicky effects, in milliseconds + }; + uint32 EliteMaterial; + int32 ProcRate; + int8 CombatEffects; // PoP: Combat Effects + + int8 Shielding; // PoP: Shielding % + int8 StunResist; // PoP: Stun Resist % + int8 StrikeThrough; // PoP: Strike Through % + uint32 ExtraDmgSkill; + uint32 ExtraDmgAmt; + int8 SpellShield; // PoP: Spell Shield % + int8 Avoidance; // PoP: Avoidance + + int8 Accuracy; // PoP: Accuracy + + uint32 CharmFileID; + int32 FactionMod1; // Faction Mod 1 + int32 FactionMod2; // Faction Mod 2 + int32 FactionMod3; // Faction Mod 3 + int32 FactionMod4; // Faction Mod 4 + int32 FactionAmt1; // Faction Amt 1 + int32 FactionAmt2; // Faction Amt 2 + int32 FactionAmt3; // Faction Amt 3 + int32 FactionAmt4; // Faction Amt 4 + char CharmFile[32]; // ? + uint32 AugType; + uint8 AugSlotType[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Type + uint8 AugSlotVisible[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Visible + uint8 AugSlotUnk2[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related + uint32 LDoNTheme; + uint32 LDoNPrice; + uint32 LDoNSold; + uint32 BaneDmgRaceAmt; + uint32 AugRestrict; + uint32 Endur; + uint32 DotShielding; + uint32 Attack; + uint32 Regen; + uint32 ManaRegen; + uint32 EnduranceRegen; + uint32 Haste; + uint32 DamageShield; + uint32 RecastDelay; + uint32 RecastType; + uint32 AugDistiller; + bool Attuneable; + bool NoPet; + bool PotionBelt; + bool Stackable; + bool NoTransfer; + bool QuestItemFlag; + int16 StackSize; + uint8 PotionBeltSlots; + item::ItemEffect_Struct Click, Proc, Worn, Focus, Scroll, Bard; + + uint8 Book; // 0=Not book, 1=Book + uint32 BookType; + char Filename[33]; // Filename for book data + // Begin SoF Fields + int32 SVCorruption; + uint32 Purity; + uint8 EvolvingItem; + uint32 EvolvingID; + uint8 EvolvingLevel; + uint8 EvolvingMax; + uint32 BackstabDmg; + uint32 DSMitigation; + int32 HeroicStr; + int32 HeroicInt; + int32 HeroicWis; + int32 HeroicAgi; + int32 HeroicDex; + int32 HeroicSta; + int32 HeroicCha; + int32 HeroicMR; + int32 HeroicFR; + int32 HeroicCR; + int32 HeroicDR; + int32 HeroicPR; + int32 HeroicSVCorrup; + int32 HealAmt; + int32 SpellDmg; + uint32 LDoNSellBackRate; + uint32 ScriptFileID; + uint16 ExpendableArrow; + uint32 Clairvoyance; + char ClickName[65]; + char ProcName[65]; + char WornName[65]; + char FocusName[65]; + char ScrollName[65]; + //BardName + + bool IsEquipable(uint16 Race, uint16 Class); + bool IsClassCommon(); + bool IsClassBag(); + bool IsClassBook(); + bool IsType1HWeapon(); + bool IsType2HWeapon(); + bool IsTypeShield(); + + bool IsEquipable(uint16 Race, uint16 Class) const { return const_cast(this)->IsEquipable(Race, Class); } + bool IsClassCommon() const { return const_cast(this)->IsClassCommon(); } + bool IsClassBag() const { return const_cast(this)->IsClassBag(); } + bool IsClassBook() const { return const_cast(this)->IsClassBook(); } + bool IsType1HWeapon() const { return const_cast(this)->IsType1HWeapon(); } + bool IsType2HWeapon() const { return const_cast(this)->IsType2HWeapon(); } + bool IsTypeShield() const { return const_cast(this)->IsTypeShield(); } + }; + +} /*EQEmu*/ + +#endif /*COMMON_ITEM_STRUCT_H*/ diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index dd5113e0e..8f64ecade 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -566,16 +566,16 @@ namespace RoF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - int item_count = in->size / sizeof(InternalSerializedItem_Struct); - if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + int item_count = in->size / sizeof(EQEmu::InternalSerializedItem_Struct); + if (!item_count || (in->size % sizeof(EQEmu::InternalSerializedItem_Struct)) != 0) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", - opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(EQEmu::InternalSerializedItem_Struct)); delete in; return; } - InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; + EQEmu::InternalSerializedItem_Struct* eq = (EQEmu::InternalSerializedItem_Struct*)in->pBuffer; EQEmu::OutBuffer ob; EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); @@ -1510,7 +1510,7 @@ namespace RoF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); + EQEmu::InternalSerializedItem_Struct* int_struct = (EQEmu::InternalSerializedItem_Struct*)(&__emu_buffer[4]); EQEmu::OutBuffer ob; EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); @@ -5193,7 +5193,7 @@ namespace RoF void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - const Item_Struct *item = inst->GetUnscaledItem(); + const EQEmu::Item_Struct *item = inst->GetUnscaledItem(); RoF::structs::ItemSerializationHeader hdr; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index e8205ba38..2ecffbabe 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -637,16 +637,16 @@ namespace RoF2 //store away the emu struct uchar* __emu_buffer = in->pBuffer; - int item_count = in->size / sizeof(InternalSerializedItem_Struct); - if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + int item_count = in->size / sizeof(EQEmu::InternalSerializedItem_Struct); + if (!item_count || (in->size % sizeof(EQEmu::InternalSerializedItem_Struct)) != 0) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", - opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(EQEmu::InternalSerializedItem_Struct)); delete in; return; } - InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; + EQEmu::InternalSerializedItem_Struct* eq = (EQEmu::InternalSerializedItem_Struct*)in->pBuffer; EQEmu::OutBuffer ob; EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); @@ -1582,7 +1582,7 @@ namespace RoF2 uchar* __emu_buffer = in->pBuffer; ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); + EQEmu::InternalSerializedItem_Struct* int_struct = (EQEmu::InternalSerializedItem_Struct*)(&__emu_buffer[4]); EQEmu::OutBuffer ob; EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); @@ -5465,7 +5465,7 @@ namespace RoF2 void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type) { - const Item_Struct *item = inst->GetUnscaledItem(); + const EQEmu::Item_Struct *item = inst->GetUnscaledItem(); RoF2::structs::ItemSerializationHeader hdr; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 8605bd7d4..ed42dd330 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -370,16 +370,16 @@ namespace SoD //store away the emu struct uchar* __emu_buffer = in->pBuffer; - int item_count = in->size / sizeof(InternalSerializedItem_Struct); - if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + int item_count = in->size / sizeof(EQEmu::InternalSerializedItem_Struct); + if (!item_count || (in->size % sizeof(EQEmu::InternalSerializedItem_Struct)) != 0) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", - opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(EQEmu::InternalSerializedItem_Struct)); delete in; return; } - InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; + EQEmu::InternalSerializedItem_Struct* eq = (EQEmu::InternalSerializedItem_Struct*)in->pBuffer; EQEmu::OutBuffer ob; EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); @@ -1041,7 +1041,7 @@ namespace SoD //store away the emu struct uchar* __emu_buffer = in->pBuffer; - InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); + EQEmu::InternalSerializedItem_Struct* int_struct = (EQEmu::InternalSerializedItem_Struct*)(&__emu_buffer[4]); EQEmu::OutBuffer ob; EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); @@ -3553,7 +3553,7 @@ namespace SoD void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - const Item_Struct *item = inst->GetUnscaledItem(); + const EQEmu::Item_Struct *item = inst->GetUnscaledItem(); SoD::structs::ItemSerializationHeader hdr; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 9beda55ad..51a1f7435 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -352,16 +352,16 @@ namespace SoF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - int item_count = in->size / sizeof(InternalSerializedItem_Struct); - if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + int item_count = in->size / sizeof(EQEmu::InternalSerializedItem_Struct); + if (!item_count || (in->size % sizeof(EQEmu::InternalSerializedItem_Struct)) != 0) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", - opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(EQEmu::InternalSerializedItem_Struct)); delete in; return; } - InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; + EQEmu::InternalSerializedItem_Struct* eq = (EQEmu::InternalSerializedItem_Struct*)in->pBuffer; EQEmu::OutBuffer ob; EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); @@ -841,7 +841,7 @@ namespace SoF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); + EQEmu::InternalSerializedItem_Struct* int_struct = (EQEmu::InternalSerializedItem_Struct*)(&__emu_buffer[4]); EQEmu::OutBuffer ob; EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); @@ -2878,7 +2878,7 @@ namespace SoF void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - const Item_Struct *item = inst->GetUnscaledItem(); + const EQEmu::Item_Struct *item = inst->GetUnscaledItem(); SoF::structs::ItemSerializationHeader hdr; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 57291ddd5..f0698ac29 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -286,14 +286,15 @@ namespace Titanium //store away the emu struct uchar* __emu_buffer = in->pBuffer; - int itemcount = in->size / sizeof(InternalSerializedItem_Struct); - if (itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { - Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + int itemcount = in->size / sizeof(EQEmu::InternalSerializedItem_Struct); + if (itemcount == 0 || (in->size % sizeof(EQEmu::InternalSerializedItem_Struct)) != 0) { + Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", + opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(EQEmu::InternalSerializedItem_Struct)); delete in; return; } - InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; + EQEmu::InternalSerializedItem_Struct* eq = (EQEmu::InternalSerializedItem_Struct*)in->pBuffer; //do the transform... EQEmu::OutBuffer ob; @@ -739,7 +740,7 @@ namespace Titanium //store away the emu struct uchar* __emu_buffer = in->pBuffer; - InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); + EQEmu::InternalSerializedItem_Struct* int_struct = (EQEmu::InternalSerializedItem_Struct*)(&__emu_buffer[4]); EQEmu::OutBuffer ob; EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); @@ -2098,7 +2099,7 @@ namespace Titanium void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const char* protection = "\\\\\\\\\\"; - const Item_Struct* item = inst->GetUnscaledItem(); + const EQEmu::Item_Struct* item = inst->GetUnscaledItem(); ob << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; @@ -2111,7 +2112,7 @@ namespace Titanium ob << '|' << itoa((inst->IsScaling() ? (inst->GetExp() / 100) : 0)); // inst experience ob << '|' << itoa((!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot())); // merchant serial number ob << '|' << itoa(inst->GetRecastTimestamp()); // recast timestamp - ob << '|' << itoa(((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges()))); // charge count + ob << '|' << itoa(((inst->IsStackable() ? ((inst->GetItem()->ItemType == EQEmu::item::ItemTypePotion) ? 1 : 0) : inst->GetCharges()))); // charge count ob << '|' << itoa((inst->IsAttuned() ? 1 : 0)); // inst attuned ob << '|' << itoa(0); // unknown ob << '|'; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 8563ad70c..2cdf96b46 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -508,16 +508,16 @@ namespace UF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - int item_count = in->size / sizeof(InternalSerializedItem_Struct); - if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + int item_count = in->size / sizeof(EQEmu::InternalSerializedItem_Struct); + if (!item_count || (in->size % sizeof(EQEmu::InternalSerializedItem_Struct)) != 0) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", - opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(EQEmu::InternalSerializedItem_Struct)); delete in; return; } - InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; + EQEmu::InternalSerializedItem_Struct* eq = (EQEmu::InternalSerializedItem_Struct*)in->pBuffer; EQEmu::OutBuffer ob; EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); @@ -1267,7 +1267,7 @@ namespace UF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); + EQEmu::InternalSerializedItem_Struct* int_struct = (EQEmu::InternalSerializedItem_Struct*)(&__emu_buffer[4]); EQEmu::OutBuffer ob; EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); @@ -3828,7 +3828,7 @@ namespace UF void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - const Item_Struct *item = inst->GetUnscaledItem(); + const EQEmu::Item_Struct *item = inst->GetUnscaledItem(); UF::structs::ItemSerializationHeader hdr; @@ -3872,7 +3872,7 @@ namespace UF int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); uint16 ornaIcon = 0; if (inst->GetOrnamentationAug(ornamentationAugtype)) { - const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const EQEmu::Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); ornaIcon = aug_weap->Icon; ob.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); diff --git a/common/say_link.cpp b/common/say_link.cpp index 1cfe2635a..3cfc46878 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -98,7 +98,7 @@ void EQEmu::saylink::SayLinkEngine::generate_body() memset(&m_LinkBodyStruct, 0, sizeof(SayLinkBody_Struct)); - const Item_Struct* item_data = nullptr; + const EQEmu::Item_Struct* item_data = nullptr; switch (m_LinkType) { case SayLinkBlank: @@ -201,7 +201,7 @@ void EQEmu::saylink::SayLinkEngine::generate_text() return; } - const Item_Struct* item_data = nullptr; + const EQEmu::Item_Struct* item_data = nullptr; switch (m_LinkType) { case SayLinkBlank: @@ -274,4 +274,4 @@ bool EQEmu::saylink::GenerateLinkBody(std::string& say_link_body, const SayLinkB return false; return true; -} \ No newline at end of file +} diff --git a/common/say_link.h b/common/say_link.h index c422bf7b2..5230f7b15 100644 --- a/common/say_link.h +++ b/common/say_link.h @@ -25,13 +25,14 @@ #include -struct Item_Struct; struct ServerLootItem_Struct; class ItemInst; namespace EQEmu { + struct Item_Struct; + namespace saylink { struct SayLinkBody_Struct; // Current server mask: EQClientRoF2 @@ -73,7 +74,7 @@ public: SayLinkEngine(); void SetLinkType(SayLinkType link_type) { m_LinkType = link_type; } - void SetItemData(const Item_Struct* item_data) { m_ItemData = item_data; } + void SetItemData(const EQEmu::Item_Struct* item_data) { m_ItemData = item_data; } void SetLootData(const ServerLootItem_Struct* loot_data) { m_LootData = loot_data; } void SetItemInst(const ItemInst* item_inst) { m_ItemInst = item_inst; } @@ -109,7 +110,7 @@ private: void generate_text(); int m_LinkType; - const Item_Struct* m_ItemData; + const EQEmu::Item_Struct* m_ItemData; const ServerLootItem_Struct* m_LootData; const ItemInst* m_ItemInst; @@ -135,4 +136,4 @@ private: bool m_Error; }; -#endif /* COMMON_SAY_LINK_H */ +#endif /*COMMON_SAY_LINK_H*/ diff --git a/common/shareddb.cpp b/common/shareddb.cpp index f61255143..f75025dbf 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -191,11 +191,11 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 s bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer - uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; - if (inst->IsType(ItemClassCommon)) { + uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { 0, 0, 0, 0, 0, 0 }; + if (inst->IsClassCommon()) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { ItemInst *auginst = inst->GetItem(i); - augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM; + augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } } @@ -220,7 +220,7 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i auto results = QueryDatabase(query); // Save bag contents, if slot supports bag contents - if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) + if (inst->IsClassBag() && Inventory::SupportsContainers(slot_id)) // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { @@ -238,11 +238,11 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer - uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; - if (inst->IsType(ItemClassCommon)) { + uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { 0, 0, 0, 0, 0, 0 }; + if (inst->IsClassCommon()) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { ItemInst *auginst = inst->GetItem(i); - augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : NO_ITEM; + augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } } @@ -266,7 +266,7 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, auto results = QueryDatabase(query); // Save bag contents, if slot supports bag contents - if (inst->IsType(ItemClassContainer) && Inventory::SupportsContainers(slot_id)) { + if (inst->IsClassBag() && Inventory::SupportsContainers(slot_id)) { // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { @@ -363,7 +363,7 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) { bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) { - const Item_Struct* myitem; + const EQEmu::Item_Struct* myitem; std::string query = StringFormat("SELECT itemid, item_charges, slot FROM starting_items " "WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND " @@ -435,7 +435,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) aug[4] = (uint32)atoi(row[7]); aug[5] = (uint32)atoi(row[8]); - const Item_Struct *item = GetItem(item_id); + const EQEmu::Item_Struct *item = GetItem(item_id); if (!item) { Log.Out(Logs::General, Logs::Error, @@ -447,7 +447,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) int16 put_slot_id = INVALID_INDEX; ItemInst *inst = CreateBaseItem(item, charges); - if (inst && item->ItemClass == ItemClassCommon) { + if (inst && item->IsClassCommon()) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); @@ -537,7 +537,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) uint32 ornament_idfile = (uint32)atoul(row[13]); uint32 ornament_hero_model = (uint32)atoul(row[14]); - const Item_Struct *item = GetItem(item_id); + const EQEmu::Item_Struct *item = GetItem(item_id); if (!item) { Log.Out(Logs::General, Logs::Error, @@ -607,7 +607,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) inst->SetRecastTimestamp(0); } - if (item->ItemClass == ItemClassCommon) { + if (item->IsClassCommon()) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); @@ -678,7 +678,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) uint32 ornament_idfile = (uint32)atoul(row[13]); uint32 ornament_hero_model = (uint32)atoul(row[14]); - const Item_Struct *item = GetItem(item_id); + const EQEmu::Item_Struct *item = GetItem(item_id); int16 put_slot_id = INVALID_INDEX; if (!item) continue; @@ -725,7 +725,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) inst->SetCharges(charges); - if (item->ItemClass == ItemClassCommon) { + if (item->IsClassCommon()) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); @@ -814,7 +814,7 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { mutex.Lock(); std::string file_name = std::string("shared/") + prefix + std::string("items"); items_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); - items_hash = std::unique_ptr>(new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), items_mmf->Size())); + items_hash = std::unique_ptr>(new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), items_mmf->Size())); mutex.Unlock(); } catch(std::exception& ex) { Log.Out(Logs::General, Logs::Error, "Error Loading Items: %s", ex.what()); @@ -826,7 +826,7 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id) { - EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); + EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); std::string ndbuffer; bool disableNoRent = false; @@ -854,7 +854,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } } - Item_Struct item; + EQEmu::Item_Struct item; const std::string query = "SELECT source," #define F(x) "`"#x"`," @@ -867,7 +867,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } for (auto row = results.begin(); row != results.end(); ++row) { - memset(&item, 0, sizeof(Item_Struct)); + memset(&item, 0, sizeof(EQEmu::Item_Struct)); item.ItemClass = (uint8)atoi(row[ItemField::itemclass]); strcpy(item.Name, row[ItemField::name]); @@ -1084,7 +1084,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } } -const Item_Struct* SharedDatabase::GetItem(uint32 id) { +const EQEmu::Item_Struct* SharedDatabase::GetItem(uint32 id) { if (id == 0) { return nullptr; @@ -1103,7 +1103,7 @@ const Item_Struct* SharedDatabase::GetItem(uint32 id) { return nullptr; } -const Item_Struct* SharedDatabase::IterateItems(uint32* id) { +const EQEmu::Item_Struct* SharedDatabase::IterateItems(uint32* id) { if(!items_hash || !id) { return nullptr; } @@ -1250,7 +1250,7 @@ bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) { // Create appropriate ItemInst class ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) { - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; ItemInst* inst = nullptr; item = GetItem(item_id); @@ -1277,7 +1277,7 @@ ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, // Create appropriate ItemInst class -ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) +ItemInst* SharedDatabase::CreateItem(const EQEmu::Item_Struct* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) { ItemInst* inst = nullptr; if (item) { @@ -1301,7 +1301,7 @@ ItemInst* SharedDatabase::CreateItem(const Item_Struct* item, int16 charges, uin return inst; } -ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges) { +ItemInst* SharedDatabase::CreateBaseItem(const EQEmu::Item_Struct* item, int16 charges) { ItemInst* inst = nullptr; if (item) { // if maxcharges is -1 that means it is an unlimited use item. diff --git a/common/shareddb.h b/common/shareddb.h index 45db3e3c0..bf21313b7 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -39,12 +39,12 @@ struct BaseDataStruct; struct InspectMessage_Struct; struct PlayerProfile_Struct; struct SPDat_Spell_Struct; -struct Item_Struct; struct NPCFactionList; struct LootTable_Struct; struct LootDrop_Struct; namespace EQEmu { + struct Item_Struct; class MemoryMappedFile; } @@ -99,8 +99,8 @@ class SharedDatabase : public Database Item Methods */ ItemInst* CreateItem(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); - ItemInst* CreateItem(const Item_Struct* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); - ItemInst* CreateBaseItem(const Item_Struct* item, int16 charges = 0); + ItemInst* CreateItem(const EQEmu::Item_Struct* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); + ItemInst* CreateBaseItem(const EQEmu::Item_Struct* item, int16 charges = 0); /* Shared Memory crap @@ -110,8 +110,8 @@ class SharedDatabase : public Database void GetItemsCount(int32 &item_count, uint32 &max_id); void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id); bool LoadItems(const std::string &prefix); - const Item_Struct* IterateItems(uint32* id); - const Item_Struct* GetItem(uint32 id); + const EQEmu::Item_Struct* IterateItems(uint32* id); + const EQEmu::Item_Struct* GetItem(uint32 id); const EvolveInfo* GetEvolveInfo(uint32 loregroup); //faction lists @@ -148,7 +148,7 @@ class SharedDatabase : public Database std::unique_ptr skill_caps_mmf; std::unique_ptr items_mmf; - std::unique_ptr> items_hash; + std::unique_ptr> items_hash; std::unique_ptr faction_mmf; std::unique_ptr> faction_hash; std::unique_ptr loot_table_mmf; diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index 02a102a8f..a88717f74 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -35,7 +35,7 @@ void LoadItems(SharedDatabase *database, const std::string &prefix) { EQ_EXCEPT("Shared Memory", "Unable to get any items from the database."); } - uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); + uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); std::string file_name = std::string("shared/") + prefix + std::string("items"); EQEmu::MemoryMappedFile mmf(file_name, size); diff --git a/tests/fixed_memory_test.h b/tests/fixed_memory_test.h index fcff0c9e8..e0c74bac9 100644 --- a/tests/fixed_memory_test.h +++ b/tests/fixed_memory_test.h @@ -27,7 +27,7 @@ class FixedMemoryHashTest : public Test::Suite { typedef void(FixedMemoryHashTest::*TestFunction)(void); public: FixedMemoryHashTest() { - size_ = EQEmu::FixedMemoryHashSet::estimated_size(72000, 190000); + size_ = EQEmu::FixedMemoryHashSet::estimated_size(72000, 190000); data_ = new uint8[size_]; memset(data_, 0, size_); TEST_ADD(FixedMemoryHashTest::InitTest); @@ -49,7 +49,7 @@ public: private: void InitTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_, 72000, 190000); + EQEmu::FixedMemoryHashSet hash(data_, size_, 72000, 190000); TEST_ASSERT(!hash.exists(1001)); TEST_ASSERT(hash.size() == 0); TEST_ASSERT(hash.max_size() == 72000); @@ -57,7 +57,7 @@ public: } void LoadTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(!hash.exists(1001)); TEST_ASSERT(hash.size() == 0); TEST_ASSERT(hash.max_size() == 72000); @@ -65,8 +65,8 @@ public: } void InsertTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::Item_Struct item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Iron Sword"); item.ID = 1001; @@ -79,20 +79,20 @@ public: } void RetrieveTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 1); TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - Item_Struct item = hash[1001]; + EQEmu::Item_Struct item = hash[1001]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1001); } void OverwriteTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::Item_Struct item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Steel Sword"); item.ID = 1001; @@ -105,20 +105,20 @@ public: } void OverwriteRetrieveTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 1); TEST_ASSERT((hash.max_size() == 72000)); TEST_ASSERT(!hash.empty()); - Item_Struct item = hash[1001]; + EQEmu::Item_Struct item = hash[1001]; TEST_ASSERT(strcmp(item.Name, "Steel Sword") == 0); TEST_ASSERT(item.ID == 1001); } void InsertAgainTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::Item_Struct item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Iron Sword"); item.ID = 1000; @@ -132,14 +132,14 @@ public: } void RetrieveAgainTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 2); TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - Item_Struct item = hash[1000]; + EQEmu::Item_Struct item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); @@ -149,8 +149,8 @@ public: } void InsertBeginTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::Item_Struct item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Bronze Sword"); item.ID = 0; @@ -165,7 +165,7 @@ public: } void RetrieveBeginTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.exists(0)); @@ -173,7 +173,7 @@ public: TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - Item_Struct item = hash[1000]; + EQEmu::Item_Struct item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); @@ -187,8 +187,8 @@ public: } void InsertEndTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::Item_Struct item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Jade Sword"); item.ID = 190000; @@ -204,7 +204,7 @@ public: } void RetrieveEndTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.exists(0)); @@ -213,7 +213,7 @@ public: TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - Item_Struct item = hash[1000]; + EQEmu::Item_Struct item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 50513af1e..0deb8c052 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -245,7 +245,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou /* Load Inventory */ // If we ensure that the material data is updated appropriately, we can do away with inventory loads if (GetInventory(accountID, cse->Name, &inv)) { - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; const ItemInst* inst = nullptr; int16 invslot = 0; diff --git a/zone/aa.cpp b/zone/aa.cpp index 210e88cd2..58d72af55 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -423,7 +423,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) uint32 sitem = 0; sitem = CorpseToUse->GetWornItem(x); if(sitem){ - const Item_Struct * itm = database.GetItem(sitem); + const EQEmu::Item_Struct * itm = database.GetItem(sitem); npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 127, true, true); } } diff --git a/zone/attack.cpp b/zone/attack.cpp index 712198733..a401c71c5 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -54,110 +54,75 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w { // Determine animation int type = 0; - if (weapon && weapon->IsType(ItemClassCommon)) { - const Item_Struct* item = weapon->GetItem(); + if (weapon && weapon->IsClassCommon()) { + const EQEmu::Item_Struct* item = weapon->GetItem(); Log.Out(Logs::Detail, Logs::Attack, "Weapon skill : %i", item->ItemType); - switch (item->ItemType) - { - case ItemType1HSlash: // 1H Slashing - { - skillinuse = Skill1HSlashing; - type = anim1HWeapon; - break; - } - case ItemType2HSlash: // 2H Slashing - { - skillinuse = Skill2HSlashing; - type = anim2HSlashing; - break; - } - case ItemType1HPiercing: // Piercing - { + switch (item->ItemType) { + case EQEmu::item::ItemType1HSlash: // 1H Slashing + skillinuse = Skill1HSlashing; + type = anim1HWeapon; + break; + case EQEmu::item::ItemType2HSlash: // 2H Slashing + skillinuse = Skill2HSlashing; + type = anim2HSlashing; + break; + case EQEmu::item::ItemType1HPiercing: // Piercing + skillinuse = Skill1HPiercing; + type = anim1HPiercing; + break; + case EQEmu::item::ItemType1HBlunt: // 1H Blunt + skillinuse = Skill1HBlunt; + type = anim1HWeapon; + break; + case EQEmu::item::ItemType2HBlunt: // 2H Blunt + skillinuse = Skill2HBlunt; + type = anim2HSlashing; //anim2HWeapon + break; + case EQEmu::item::ItemType2HPiercing: // 2H Piercing + if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) skillinuse = Skill1HPiercing; - type = anim1HPiercing; - break; - } - case ItemType1HBlunt: // 1H Blunt - { - skillinuse = Skill1HBlunt; - type = anim1HWeapon; - break; - } - case ItemType2HBlunt: // 2H Blunt - { - skillinuse = Skill2HBlunt; - type = anim2HSlashing; //anim2HWeapon - break; - } - case ItemType2HPiercing: // 2H Piercing - { - if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) - skillinuse = Skill1HPiercing; - else - skillinuse = Skill2HPiercing; - type = anim2HWeapon; - break; - } - case ItemTypeMartial: - { - skillinuse = SkillHandtoHand; - type = animHand2Hand; - break; - } - default: - { - skillinuse = SkillHandtoHand; - type = animHand2Hand; - break; - } + else + skillinuse = Skill2HPiercing; + type = anim2HWeapon; + break; + case EQEmu::item::ItemTypeMartial: + skillinuse = SkillHandtoHand; + type = animHand2Hand; + break; + default: + skillinuse = SkillHandtoHand; + type = animHand2Hand; + break; }// switch } else if(IsNPC()) { - - switch (skillinuse) - { - case Skill1HSlashing: // 1H Slashing - { - type = anim1HWeapon; - break; - } - case Skill2HSlashing: // 2H Slashing - { - type = anim2HSlashing; - break; - } - case Skill1HPiercing: // Piercing - { - type = anim1HPiercing; - break; - } - case Skill1HBlunt: // 1H Blunt - { - type = anim1HWeapon; - break; - } - case Skill2HBlunt: // 2H Blunt - { - type = anim2HSlashing; //anim2HWeapon - break; - } - case Skill2HPiercing: // 2H Piercing - { - type = anim2HWeapon; - break; - } - case SkillHandtoHand: - { - type = animHand2Hand; - break; - } - default: - { - type = animHand2Hand; - break; - } + switch (skillinuse) { + case Skill1HSlashing: // 1H Slashing + type = anim1HWeapon; + break; + case Skill2HSlashing: // 2H Slashing + type = anim2HSlashing; + break; + case Skill1HPiercing: // Piercing + type = anim1HPiercing; + break; + case Skill1HBlunt: // 1H Blunt + type = anim1HWeapon; + break; + case Skill2HBlunt: // 2H Blunt + type = anim2HSlashing; //anim2HWeapon + break; + case Skill2HPiercing: // 2H Piercing + type = anim2HWeapon; + break; + case SkillHandtoHand: + type = animHand2Hand; + break; + default: + type = animHand2Hand; + break; }// switch } else { @@ -825,7 +790,7 @@ int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, //Else we know we can hit. //GetWeaponDamage(mob*, const Item_Struct*) is intended to be used for mobs or any other situation where we do not have a client inventory item //GetWeaponDamage(mob*, const ItemInst*) is intended to be used for situations where we have a client inventory item -int Mob::GetWeaponDamage(Mob *against, const Item_Struct *weapon_item) { +int Mob::GetWeaponDamage(Mob *against, const EQEmu::Item_Struct *weapon_item) { int dmg = 0; int banedmg = 0; @@ -1151,7 +1116,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); + ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const EQEmu::Item_Struct*) nullptr ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; @@ -1162,7 +1127,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if (Hand == EQEmu::legacy::SlotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr, true ); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::Item_Struct*) nullptr, true ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; @@ -1630,7 +1595,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool } //figure out what weapon they are using, if any - const Item_Struct* weapon = nullptr; + const EQEmu::Item_Struct* weapon = nullptr; if (Hand == EQEmu::legacy::SlotPrimary && equipment[EQEmu::legacy::SlotPrimary] > 0) weapon = database.GetItem(equipment[EQEmu::legacy::SlotPrimary]); else if (equipment[EQEmu::legacy::SlotSecondary]) @@ -1641,40 +1606,40 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool if(weapon) { Log.Out(Logs::Detail, Logs::Combat, "Attacking with weapon: %s (%d) (too bad im not using it for much)", weapon->Name, weapon->ID); - if (Hand == EQEmu::legacy::SlotSecondary && weapon->ItemType == ItemTypeShield){ + if (Hand == EQEmu::legacy::SlotSecondary && weapon->ItemType == EQEmu::item::ItemTypeShield){ Log.Out(Logs::Detail, Logs::Combat, "Attack with shield canceled."); return false; } - switch(weapon->ItemType){ - case ItemType1HSlash: - skillinuse = Skill1HSlashing; - break; - case ItemType2HSlash: - skillinuse = Skill2HSlashing; - break; - case ItemType1HPiercing: - skillinuse = Skill1HPiercing; - break; - case ItemType2HPiercing: - skillinuse = Skill2HPiercing; - break; - case ItemType1HBlunt: - skillinuse = Skill1HBlunt; - break; - case ItemType2HBlunt: - skillinuse = Skill2HBlunt; - break; - case ItemTypeBow: - skillinuse = SkillArchery; - break; - case ItemTypeLargeThrowing: - case ItemTypeSmallThrowing: - skillinuse = SkillThrowing; - break; - default: - skillinuse = SkillHandtoHand; - break; + switch(weapon->ItemType) { + case EQEmu::item::ItemType1HSlash: + skillinuse = Skill1HSlashing; + break; + case EQEmu::item::ItemType2HSlash: + skillinuse = Skill2HSlashing; + break; + case EQEmu::item::ItemType1HPiercing: + skillinuse = Skill1HPiercing; + break; + case EQEmu::item::ItemType2HPiercing: + skillinuse = Skill2HPiercing; + break; + case EQEmu::item::ItemType1HBlunt: + skillinuse = Skill1HBlunt; + break; + case EQEmu::item::ItemType2HBlunt: + skillinuse = Skill2HBlunt; + break; + case EQEmu::item::ItemTypeBow: + skillinuse = SkillArchery; + break; + case EQEmu::item::ItemTypeLargeThrowing: + case EQEmu::item::ItemTypeSmallThrowing: + skillinuse = SkillThrowing; + break; + default: + skillinuse = SkillHandtoHand; + break; } } @@ -2542,7 +2507,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) { } } -uint8 Mob::GetWeaponDamageBonus(const Item_Struct *weapon, bool offhand) +uint8 Mob::GetWeaponDamageBonus(const EQEmu::Item_Struct *weapon, bool offhand) { // dev quote with old and new formulas // https://forums.daybreakgames.com/eq/index.php?threads/test-update-09-17-15.226618/page-5#post-3326194 @@ -2554,8 +2519,7 @@ uint8 Mob::GetWeaponDamageBonus(const Item_Struct *weapon, bool offhand) return 1 + ((level - 28) / 3); // how does weaponless scale? auto delay = weapon->Delay; - if (weapon->ItemType == ItemType1HSlash || weapon->ItemType == ItemType1HBlunt || - weapon->ItemType == ItemTypeMartial || weapon->ItemType == ItemType1HPiercing) { + if (weapon->IsType1HWeapon() || weapon->ItemType == EQEmu::item::ItemTypeMartial) { // we assume sinister strikes is checked before calling here if (!offhand) { if (delay <= 39) @@ -3574,12 +3538,12 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { } if(!weapon_g) { - TrySpellProc(nullptr, (const Item_Struct*)nullptr, on); + TrySpellProc(nullptr, (const EQEmu::Item_Struct*)nullptr, on); return; } - if(!weapon_g->IsType(ItemClassCommon)) { - TrySpellProc(nullptr, (const Item_Struct*)nullptr, on); + if (!weapon_g->IsClassCommon()) { + TrySpellProc(nullptr, (const EQEmu::Item_Struct*)nullptr, on); return; } @@ -3592,7 +3556,7 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { return; } -void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand) +void Mob::TryWeaponProc(const ItemInst *inst, const EQEmu::Item_Struct *weapon, Mob *on, uint16 hand) { if (!weapon) @@ -3611,7 +3575,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on // We can proc once here, either weapon or one aug bool proced = false; // silly bool to prevent augs from going if weapon does skillinuse = GetSkillByItemType(weapon->ItemType); - if (weapon->Proc.Type == ET_CombatProc && IsValidSpell(weapon->Proc.Effect)) { + if (weapon->Proc.Type == EQEmu::item::ItemEffectCombatProc && IsValidSpell(weapon->Proc.Effect)) { float WPC = ProcChance * (100.0f + // Proc chance for this weapon static_cast(weapon->ProcRate)) / 100.0f; if (zone->random.Roll(WPC)) { // 255 dex = 0.084 chance of proc. No idea what this number should be really. @@ -3645,11 +3609,11 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on const ItemInst *aug_i = inst->GetAugment(r); if (!aug_i) // no aug, try next slot! continue; - const Item_Struct *aug = aug_i->GetItem(); + const EQEmu::Item_Struct *aug = aug_i->GetItem(); if (!aug) continue; - if (aug->Proc.Type == ET_CombatProc && IsValidSpell(aug->Proc.Effect)) { + if (aug->Proc.Type == EQEmu::item::ItemEffectCombatProc && IsValidSpell(aug->Proc.Effect)) { float APC = ProcChance * (100.0f + // Proc chance for this aug static_cast(aug->ProcRate)) / 100.0f; if (zone->random.Roll(APC)) { @@ -3675,7 +3639,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on return; } -void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand) +void Mob::TrySpellProc(const ItemInst *inst, const EQEmu::Item_Struct *weapon, Mob *on, uint16 hand) { float ProcBonus = static_cast(spellbonuses.SpellProcChance + itembonuses.SpellProcChance + aabonuses.SpellProcChance); @@ -3687,11 +3651,12 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, bool rangedattk = false; if (weapon && hand == EQEmu::legacy::SlotRange) { - if (weapon->ItemType == ItemTypeArrow || - weapon->ItemType == ItemTypeLargeThrowing || - weapon->ItemType == ItemTypeSmallThrowing || - weapon->ItemType == ItemTypeBow) + if (weapon->ItemType == EQEmu::item::ItemTypeArrow || + weapon->ItemType == EQEmu::item::ItemTypeLargeThrowing || + weapon->ItemType == EQEmu::item::ItemTypeSmallThrowing || + weapon->ItemType == EQEmu::item::ItemTypeBow) { rangedattk = true; + } } if (!weapon && hand == EQEmu::legacy::SlotRange && GetSpecialAbility(SPECATK_RANGED_ATK)) @@ -4531,7 +4496,7 @@ void Client::SetAttackTimer() else //invalid slot (hands will always hit this) continue; - const Item_Struct *ItemToUse = nullptr; + const EQEmu::Item_Struct *ItemToUse = nullptr; //find our item ItemInst *ci = GetInv().GetItem(i); @@ -4550,16 +4515,16 @@ void Client::SetAttackTimer() //see if we have a valid weapon if (ItemToUse != nullptr) { //check type and damage/delay - if (ItemToUse->ItemClass != ItemClassCommon - || ItemToUse->Damage == 0 - || ItemToUse->Delay == 0) { + if (!ItemToUse->IsClassCommon() + || ItemToUse->Damage == 0 + || ItemToUse->Delay == 0) { //no weapon ItemToUse = nullptr; } // Check to see if skill is valid - else if ((ItemToUse->ItemType > ItemTypeLargeThrowing) && - (ItemToUse->ItemType != ItemTypeMartial) && - (ItemToUse->ItemType != ItemType2HPiercing)) { + else if ((ItemToUse->ItemType > EQEmu::item::ItemTypeLargeThrowing) && + (ItemToUse->ItemType != EQEmu::item::ItemTypeMartial) && + (ItemToUse->ItemType != EQEmu::item::ItemType2HPiercing)) { //no weapon ItemToUse = nullptr; } @@ -4578,7 +4543,7 @@ void Client::SetAttackTimer() speed = delay / haste_mod; - if (ItemToUse && ItemToUse->ItemType == ItemTypeBow) { + if (ItemToUse && ItemToUse->ItemType == EQEmu::item::ItemTypeBow) { // Live actually had a bug here where they would return the non-modified attack speed // rather than the cap ... speed = std::max(speed - GetQuiverHaste(speed), RuleI(Combat, QuiverHasteCap)); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 899cee359..c5c1c92d2 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -152,14 +152,14 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { AddItemBonuses(inst, newbon, false, false, 0, (i == EQEmu::legacy::SlotAmmo)); //These are given special flags due to how often they are checked for various spell effects. - const Item_Struct *item = inst->GetItem(); - if (i == EQEmu::legacy::SlotSecondary && (item && item->ItemType == ItemTypeShield)) + const EQEmu::Item_Struct *item = inst->GetItem(); + if (i == EQEmu::legacy::SlotSecondary && (item && item->ItemType == EQEmu::item::ItemTypeShield)) SetShieldEquiped(true); - else if (i == EQEmu::legacy::SlotPrimary && (item && item->ItemType == ItemType2HBlunt)) { + else if (i == EQEmu::legacy::SlotPrimary && (item && item->ItemType == EQEmu::item::ItemType2HBlunt)) { SetTwoHandBluntEquiped(true); SetTwoHanderEquipped(true); } - else if (i == EQEmu::legacy::SlotPrimary && (item && (item->ItemType == ItemType2HSlash || item->ItemType == ItemType2HPiercing))) + else if (i == EQEmu::legacy::SlotPrimary && (item && (item->ItemType == EQEmu::item::ItemType2HSlash || item->ItemType == EQEmu::item::ItemType2HPiercing))) SetTwoHanderEquipped(true); } @@ -180,7 +180,7 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { } //Optional ability to have worn effects calculate as an addititive bonus instead of highest value - if (RuleI(Spells, AdditiveBonusWornType) && RuleI(Spells, AdditiveBonusWornType) != ET_WornEffect){ + if (RuleI(Spells, AdditiveBonusWornType) && RuleI(Spells, AdditiveBonusWornType) != EQEmu::item::ItemEffectWorn){ for (i = EQEmu::legacy::SlotCharm; i < EQEmu::legacy::SlotAmmo; i++) { const ItemInst* inst = m_inv[i]; if(inst == 0) @@ -210,7 +210,7 @@ void Client::ProcessItemCaps() void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAug, bool isTribute, int rec_override, bool ammo_slot_item) { - if (!inst || !inst->IsType(ItemClassCommon)) { + if (!inst || !inst->IsClassCommon()) { return; } @@ -218,10 +218,10 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu return; } - const Item_Struct *item = inst->GetItem(); + const EQEmu::Item_Struct *item = inst->GetItem(); if (!isTribute && !inst->IsEquipable(GetBaseRace(), GetClass())) { - if (item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink) + if (item->ItemType != EQEmu::item::ItemTypeFood && item->ItemType != EQEmu::item::ItemTypeDrink) return; } @@ -430,11 +430,11 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu else newbon->DSMitigation += item->DSMitigation; } - if (item->Worn.Effect > 0 && item->Worn.Type == ET_WornEffect) { // latent effects + if (item->Worn.Effect > 0 && item->Worn.Type == EQEmu::item::ItemEffectWorn) { // latent effects ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type); } - if (item->Focus.Effect > 0 && (item->Focus.Type == ET_Focus)) { // focus effects + if (item->Focus.Effect > 0 && (item->Focus.Type == EQEmu::item::ItemEffectFocus)) { // focus effects ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0); } @@ -544,13 +544,13 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool which will also stack with regular (worntype 2) effects. [Ie set rule = 3 and item worntype = 3] */ - if(!inst || !inst->IsType(ItemClassCommon)) + if (!inst || !inst->IsClassCommon()) return; if(inst->GetAugmentType()==0 && isAug == true) return; - const Item_Struct *item = inst->GetItem(); + const EQEmu::Item_Struct *item = inst->GetItem(); if(!inst->IsEquipable(GetBaseRace(),GetClass())) return; @@ -581,11 +581,11 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { if (food && drink) break; const ItemInst* inst = GetInv().GetItem(i); - if (inst && inst->GetItem() && inst->IsType(ItemClassCommon)) { - const Item_Struct *item=inst->GetItem(); - if (item->ItemType == ItemTypeFood && !food) + if (inst && inst->GetItem() && inst->IsClassCommon()) { + const EQEmu::Item_Struct *item=inst->GetItem(); + if (item->ItemType == EQEmu::item::ItemTypeFood && !food) food = true; - else if (item->ItemType == ItemTypeDrink && !drink) + else if (item->ItemType == EQEmu::item::ItemTypeDrink && !drink) drink = true; else continue; @@ -597,11 +597,11 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { if (food && drink) break; const ItemInst* inst = GetInv().GetItem(i); - if (inst && inst->GetItem() && inst->IsType(ItemClassCommon)) { - const Item_Struct *item=inst->GetItem(); - if (item->ItemType == ItemTypeFood && !food) + if (inst && inst->GetItem() && inst->IsClassCommon()) { + const EQEmu::Item_Struct *item=inst->GetItem(); + if (item->ItemType == EQEmu::item::ItemTypeFood && !food) food = true; - else if (item->ItemType == ItemTypeDrink && !drink) + else if (item->ItemType == EQEmu::item::ItemTypeDrink && !drink) drink = true; else continue; @@ -911,19 +911,19 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_AddSingingMod: switch (base2) { - case ItemTypeWindInstrument: + case EQEmu::item::ItemTypeWindInstrument: newbon->windMod += base1; break; - case ItemTypeStringedInstrument: + case EQEmu::item::ItemTypeStringedInstrument: newbon->stringedMod += base1; break; - case ItemTypeBrassInstrument: + case EQEmu::item::ItemTypeBrassInstrument: newbon->brassMod += base1; break; - case ItemTypePercussionInstrument: + case EQEmu::item::ItemTypePercussionInstrument: newbon->percussionMod += base1; break; - case ItemTypeSinging: + case EQEmu::item::ItemTypeSinging: newbon->singingMod += base1; break; } @@ -2753,23 +2753,24 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; case SE_AddSingingMod: - switch (base2) - { - case ItemTypeWindInstrument: - new_bonus->windMod += effect_value; - break; - case ItemTypeStringedInstrument: - new_bonus->stringedMod += effect_value; - break; - case ItemTypeBrassInstrument: - new_bonus->brassMod += effect_value; - break; - case ItemTypePercussionInstrument: - new_bonus->percussionMod += effect_value; - break; - case ItemTypeSinging: - new_bonus->singingMod += effect_value; - break; + switch (base2) { + case EQEmu::item::ItemTypeWindInstrument: + new_bonus->windMod += effect_value; + break; + case EQEmu::item::ItemTypeStringedInstrument: + new_bonus->stringedMod += effect_value; + break; + case EQEmu::item::ItemTypeBrassInstrument: + new_bonus->brassMod += effect_value; + break; + case EQEmu::item::ItemTypePercussionInstrument: + new_bonus->percussionMod += effect_value; + break; + case EQEmu::item::ItemTypeSinging: + new_bonus->singingMod += effect_value; + break; + default: + break; } break; @@ -3202,7 +3203,7 @@ void NPC::CalcItemBonuses(StatBonuses *newbon) if(newbon){ for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++){ - const Item_Struct *cur = database.GetItem(equipment[i]); + const EQEmu::Item_Struct *cur = database.GetItem(equipment[i]); if(cur){ //basic stats newbon->AC += cur->AC; @@ -3257,12 +3258,12 @@ void NPC::CalcItemBonuses(StatBonuses *newbon) if(cur->CombatEffects > 0) { newbon->ProcChance += cur->CombatEffects; } - if (cur->Worn.Effect>0 && (cur->Worn.Type == ET_WornEffect)) { // latent effects + if (cur->Worn.Effect>0 && (cur->Worn.Type == EQEmu::item::ItemEffectWorn)) { // latent effects ApplySpellsBonuses(cur->Worn.Effect, cur->Worn.Level, newbon, 0, cur->Worn.Type); } if (RuleB(Spells, NPC_UseFocusFromItems)){ - if (cur->Focus.Effect>0 && (cur->Focus.Type == ET_Focus)){ // focus effects + if (cur->Focus.Effect>0 && (cur->Focus.Type == EQEmu::item::ItemEffectFocus)){ // focus effects ApplySpellsBonuses(cur->Focus.Effect, cur->Focus.Level, newbon); } } diff --git a/zone/bot.cpp b/zone/bot.cpp index 592c7843c..0cb75e8a5 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -233,9 +233,9 @@ uint32 Bot::GetBotArcheryRange() { if (!range_inst || !ammo_inst) return 0; - const Item_Struct *range_item = range_inst->GetItem(); - const Item_Struct *ammo_item = ammo_inst->GetItem(); - if (!range_item || !ammo_item || range_item->ItemType != ItemTypeBow || ammo_item->ItemType != ItemTypeArrow) + const EQEmu::Item_Struct *range_item = range_inst->GetItem(); + const EQEmu::Item_Struct *ammo_item = ammo_inst->GetItem(); + if (!range_item || !ammo_item || range_item->ItemType != EQEmu::item::ItemTypeBow || ammo_item->ItemType != EQEmu::item::ItemTypeArrow) return 0; // everything is good! @@ -1180,38 +1180,30 @@ uint16 Bot::GetPrimarySkillValue() { else { uint8 type = m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType; //is this the best way to do this? switch(type) { - case ItemType1HSlash: { - skill = Skill1HSlashing; - break; - } - case ItemType2HSlash: { - skill = Skill2HSlashing; - break; - } - case ItemType1HPiercing: { - skill = Skill1HPiercing; - break; - } - case ItemType1HBlunt: { - skill = Skill1HBlunt; - break; - } - case ItemType2HBlunt: { - skill = Skill2HBlunt; - break; - } - case ItemType2HPiercing: { - skill = Skill2HPiercing; - break; - } - case ItemTypeMartial: { - skill = SkillHandtoHand; - break; - } - default: { - skill = SkillHandtoHand; - break; - } + case EQEmu::item::ItemType1HSlash: + skill = Skill1HSlashing; + break; + case EQEmu::item::ItemType2HSlash: + skill = Skill2HSlashing; + break; + case EQEmu::item::ItemType1HPiercing: + skill = Skill1HPiercing; + break; + case EQEmu::item::ItemType1HBlunt: + skill = Skill1HBlunt; + break; + case EQEmu::item::ItemType2HBlunt: + skill = Skill2HBlunt; + break; + case EQEmu::item::ItemType2HPiercing: + skill = Skill2HPiercing; + break; + case EQEmu::item::ItemTypeMartial: + skill = SkillHandtoHand; + break; + default: + skill = SkillHandtoHand; + break; } } @@ -1906,12 +1898,12 @@ void Bot::BotRangedAttack(Mob* other) { } ItemInst* rangedItem = GetBotItem(EQEmu::legacy::SlotRange); - const Item_Struct* RangeWeapon = 0; + const EQEmu::Item_Struct* RangeWeapon = 0; if(rangedItem) RangeWeapon = rangedItem->GetItem(); ItemInst* ammoItem = GetBotItem(EQEmu::legacy::SlotAmmo); - const Item_Struct* Ammo = 0; + const EQEmu::Item_Struct* Ammo = 0; if(ammoItem) Ammo = ammoItem->GetItem(); @@ -2020,7 +2012,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes int32 min_hit = 1; int32 max_hit = ((2 * weapon_damage * GetDamageTable(skillinuse)) / 100); if(GetLevel() >= 28 && IsWarriorClass()) { - int ucDamageBonus = GetWeaponDamageBonus((const Item_Struct*) nullptr); + int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::Item_Struct*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -2062,12 +2054,12 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if(skillinuse == SkillBash){ const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); - const Item_Struct* botweapon = 0; + const EQEmu::Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); if(botweapon) { - if(botweapon->ItemType == ItemTypeShield) + if (botweapon->ItemType == EQEmu::item::ItemTypeShield) hate += botweapon->AC; hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100); @@ -2122,7 +2114,7 @@ void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) if (item_slot >= EQEmu::legacy::EQUIPMENT_BEGIN){ const ItemInst* inst = GetBotItem(item_slot); - const Item_Struct* botweapon = 0; + const EQEmu::Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -2487,7 +2479,7 @@ void Bot::AI_Process() { if (GetTarget() && ExtraAttackChanceBonus) { ItemInst *wpn = GetBotItem(EQEmu::legacy::SlotPrimary); if(wpn) { - if(wpn->GetItem()->ItemType == ItemType2HSlash || wpn->GetItem()->ItemType == ItemType2HBlunt || wpn->GetItem()->ItemType == ItemType2HPiercing) { + if (wpn->GetItem()->IsType2HWeapon()) { if(zone->random.Int(0, 100) < ExtraAttackChanceBonus) Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); } @@ -2510,7 +2502,7 @@ void Bot::AI_Process() { //now off hand if(GetTarget() && attack_dw_timer.Check() && CanThisClassDualWield()) { const ItemInst* instweapon = GetBotItem(EQEmu::legacy::SlotSecondary); - const Item_Struct* weapon = 0; + const EQEmu::Item_Struct* weapon = 0; //can only dual wield without a weapon if you're a monk if(instweapon || (botClass == MONK)) { if(instweapon) @@ -2523,7 +2515,7 @@ void Bot::AI_Process() { bIsFist = false; } - if(bIsFist || ((weapontype != ItemType2HSlash) && (weapontype != ItemType2HPiercing) && (weapontype != ItemType2HBlunt))) { + if (bIsFist || !weapon->IsType2HWeapon()) { float DualWieldProbability = 0.0f; int32 Ambidexterity = (aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity); DualWieldProbability = ((GetSkill(SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f); // 78.0 max @@ -2957,7 +2949,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; ns->spawn.helm = helmtexture; //(GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.equip_chest2 = texture; //0xFF; - const Item_Struct* item = 0; + const EQEmu::Item_Struct* item = 0; const ItemInst* inst = 0; uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); @@ -3400,7 +3392,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli //EQoffline: will give the items to the bots and change the bot stats if(inst && (GetBotOwner() == client->CastToMob()) && !IsEngaged()) { std::string TempErrorMessage; - const Item_Struct* mWeaponItem = inst->GetItem(); + const EQEmu::Item_Struct* mWeaponItem = inst->GetItem(); bool failedLoreCheck = false; for (int m = AUG_INDEX_BEGIN; m < EQEmu::legacy::ITEM_COMMON_SIZE; ++m) { ItemInst *itm = inst->GetAugment(m); @@ -3435,9 +3427,9 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli how_many_slots++; if(!GetBotItem(j)) { if (j == EQEmu::legacy::SlotPrimary) { - if((mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) { + if (mWeaponItem->IsType2HWeapon()) { if (GetBotItem(EQEmu::legacy::SlotSecondary)) { - if(mWeaponItem && (mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) { + if (mWeaponItem && mWeaponItem->IsType2HWeapon()) { if (client->CheckLoreConflict(GetBotItem(EQEmu::legacy::SlotSecondary)->GetItem())) { failedLoreCheck = true; } @@ -3472,7 +3464,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli if(success) { if (GetBotItem(EQEmu::legacy::SlotPrimary)) { ItemInst* remove_item = GetBotItem(EQEmu::legacy::SlotPrimary); - if((remove_item->GetItem()->ItemType == ItemType2HSlash) || (remove_item->GetItem()->ItemType == ItemType2HBlunt) || (remove_item->GetItem()->ItemType == ItemType2HPiercing)) { + if (remove_item->GetItem()->IsType2HWeapon()) { BotTradeSwapItem(client, EQEmu::legacy::SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } @@ -3509,7 +3501,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } if(!failedLoreCheck) { if (j == EQEmu::legacy::SlotPrimary) { - if((mWeaponItem->ItemType == ItemType2HSlash) || (mWeaponItem->ItemType == ItemType2HBlunt) || (mWeaponItem->ItemType == ItemType2HPiercing)) { + if (mWeaponItem->IsType2HWeapon()) { if (GetBotItem(EQEmu::legacy::SlotSecondary)) { if (client->CheckLoreConflict(GetBotItem(EQEmu::legacy::SlotSecondary)->GetItem())) { failedLoreCheck = true; @@ -3543,7 +3535,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } if (success && GetBotItem(EQEmu::legacy::SlotPrimary)) { ItemInst* remove_item = GetBotItem(EQEmu::legacy::SlotPrimary); - if((remove_item->GetItem()->ItemType == ItemType2HSlash) || (remove_item->GetItem()->ItemType == ItemType2HBlunt) || (remove_item->GetItem()->ItemType == ItemType2HPiercing)) { + if (remove_item->GetItem()->IsType2HWeapon()) { BotTradeSwapItem(client, EQEmu::legacy::SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } @@ -3579,7 +3571,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } - const Item_Struct* item2 = 0; + const EQEmu::Item_Struct* item2 = 0; for(int y = beginSlotID; y <= endSlotID; ++y) { item2 = database.GetItem(items[y]); if(item2) { @@ -3818,7 +3810,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::Item_Struct*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -3827,7 +3819,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. if (Hand == EQEmu::legacy::SlotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const Item_Struct*) nullptr); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::Item_Struct*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -4285,8 +4277,8 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[bottype]) { - const Item_Struct* TempItem = 0; - const Item_Struct* UsedItem = 0; + const EQEmu::Item_Struct* TempItem = 0; + const EQEmu::Item_Struct* UsedItem = 0; const ItemInst* TempInst = 0; uint16 UsedFocusID = 0; int32 Total = 0; @@ -4322,7 +4314,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { ItemInst *aug = nullptr; aug = ins->GetAugment(y); if(aug) { - const Item_Struct* TempItemAug = aug->GetItem(); + const EQEmu::Item_Struct* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { focus_max = CalcBotFocusEffect(bottype, TempItemAug->Focus.Effect, spell_id, true); @@ -4870,12 +4862,12 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if(skill == SkillBash) { const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); - const Item_Struct* botweapon = 0; + const EQEmu::Item_Struct* botweapon = 0; if(inst) botweapon = inst->GetItem(); if(botweapon) { - if(botweapon->ItemType == ItemTypeShield) + if (botweapon->ItemType == EQEmu::item::ItemTypeShield) hate += botweapon->AC; hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100); @@ -4935,11 +4927,11 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { bool bIsBehind = false; bool bCanFrontalBS = false; const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotPrimary); - const Item_Struct* botpiercer = nullptr; + const EQEmu::Item_Struct* botpiercer = nullptr; if(inst) botpiercer = inst->GetItem(); - if(!botpiercer || (botpiercer->ItemType != ItemType1HPiercing)) { + if (!botpiercer || (botpiercer->ItemType != EQEmu::item::ItemType1HPiercing)) { BotGroupSay(this, "I can't backstab with this weapon!"); return; } @@ -5108,7 +5100,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { case WARRIOR: if(level >= RuleI(Combat, NPCBashKickLevel)){ bool canBash = false; - if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQEmu::legacy::SlotSecondary) && m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(EQEmu::legacy::SlotPrimary) && (m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) + if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQEmu::legacy::SlotSecondary) && m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType == EQEmu::item::ItemTypeShield) || (m_inv.GetItem(EQEmu::legacy::SlotPrimary) && m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->IsType2HWeapon() && GetAA(aa2HandBash) >= 1)) canBash = true; if(!canBash || zone->random.Int(0, 100) > 25) @@ -5127,7 +5119,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { case SHADOWKNIGHT: case PALADIN: if(level >= RuleI(Combat, NPCBashKickLevel)){ - if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQEmu::legacy::SlotSecondary) && m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType == ItemTypeShield) || (m_inv.GetItem(EQEmu::legacy::SlotPrimary) && (m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HSlash || m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HBlunt || m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType == ItemType2HPiercing) && GetAA(aa2HandBash) >= 1)) + if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQEmu::legacy::SlotSecondary) && m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType == EQEmu::item::ItemTypeShield) || (m_inv.GetItem(EQEmu::legacy::SlotPrimary) && m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->IsType2HWeapon() && GetAA(aa2HandBash) >= 1)) skill_to_use = SkillBash; } break; @@ -5372,7 +5364,7 @@ bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) { void Bot::EquipBot(std::string* errorMessage) { GetBotItems(m_inv, errorMessage); const ItemInst* inst = 0; - const Item_Struct* item = 0; + const EQEmu::Item_Struct* item = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { @@ -5499,7 +5491,7 @@ void Bot::SetAttackTimer() { float haste_mod = (GetHaste() * 0.01f); attack_timer.SetAtTrigger(4000, true); Timer* TimerToUse = nullptr; - const Item_Struct* PrimaryWeapon = nullptr; + const EQEmu::Item_Struct* PrimaryWeapon = nullptr; for (int i = EQEmu::legacy::SlotRange; i <= EQEmu::legacy::SlotSecondary; i++) { if (i == EQEmu::legacy::SlotPrimary) TimerToUse = &attack_timer; @@ -5510,14 +5502,14 @@ void Bot::SetAttackTimer() { else continue; - const Item_Struct* ItemToUse = nullptr; + const EQEmu::Item_Struct* ItemToUse = nullptr; ItemInst* ci = GetBotItem(i); if (ci) ItemToUse = ci->GetItem(); if (i == EQEmu::legacy::SlotSecondary) { if (PrimaryWeapon != nullptr) { - if (PrimaryWeapon->ItemClass == ItemClassCommon && (PrimaryWeapon->ItemType == ItemType2HSlash || PrimaryWeapon->ItemType == ItemType2HBlunt || PrimaryWeapon->ItemType == ItemType2HPiercing)) { + if (PrimaryWeapon->IsClassCommon() && PrimaryWeapon->IsType2HWeapon()) { attack_dw_timer.Disable(); continue; } @@ -5530,7 +5522,7 @@ void Bot::SetAttackTimer() { } if (ItemToUse != nullptr) { - if (ItemToUse->ItemClass != ItemClassCommon || ItemToUse->Damage == 0 || ItemToUse->Delay == 0 || ((ItemToUse->ItemType > ItemTypeLargeThrowing) && (ItemToUse->ItemType != ItemTypeMartial) && (ItemToUse->ItemType != ItemType2HPiercing))) + if (!ItemToUse->IsClassCommon() || ItemToUse->Damage == 0 || ItemToUse->Delay == 0 || ((ItemToUse->ItemType > EQEmu::item::ItemTypeLargeThrowing) && (ItemToUse->ItemType != EQEmu::item::ItemTypeMartial) && (ItemToUse->ItemType != EQEmu::item::ItemType2HPiercing))) ItemToUse = nullptr; } @@ -7185,7 +7177,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { insr->TargetID = inspectedBot->GetNPCTypeID(); insr->playerid = inspectedBot->GetID(); - const Item_Struct* item = 0; + const EQEmu::Item_Struct* item = 0; const ItemInst* inst = 0; // Modded to display power source items (will only show up on SoF+ client inspect windows though.) @@ -7237,7 +7229,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { void Bot::CalcItemBonuses(StatBonuses* newbon) { - const Item_Struct* itemtmp = 0; + const EQEmu::Item_Struct* itemtmp = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { const ItemInst* item = GetBotItem((i == 22 ? 9999 : i)); @@ -7258,7 +7250,7 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) } void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute, int rec_override) { - if(!inst || !inst->IsType(ItemClassCommon)) + if (!inst || !inst->IsClassCommon()) { return; } @@ -7268,11 +7260,11 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, return; } - const Item_Struct *item = inst->GetItem(); + const EQEmu::Item_Struct *item = inst->GetItem(); if(!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass())) { - if(item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink) + if (item->ItemType != EQEmu::item::ItemTypeFood && item->ItemType != EQEmu::item::ItemTypeDrink) return; } @@ -7479,11 +7471,11 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, else newbon->DSMitigation += item->DSMitigation; } - if (item->Worn.Effect > 0 && item->Worn.Type == ET_WornEffect) {// latent effects + if (item->Worn.Effect > 0 && item->Worn.Type == EQEmu::item::ItemEffectWorn) {// latent effects ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type); } - if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects + if (item->Focus.Effect>0 && (item->Focus.Type == EQEmu::item::ItemEffectFocus)) { // focus effects ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0); } @@ -7635,7 +7627,7 @@ void Bot::CalcBotStats(bool showtext) { } } -bool Bot::CheckLoreConflict(const Item_Struct* item) { +bool Bot::CheckLoreConflict(const EQEmu::Item_Struct* item) { if (!item || !(item->LoreFlag)) return false; @@ -8043,7 +8035,7 @@ int Bot::GetRawACNoShield(int &shield_ac) { shield_ac = 0; ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); if(inst) { - if(inst->GetItem()->ItemType == ItemTypeShield) { + if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; for (uint8 i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { @@ -8058,7 +8050,7 @@ int Bot::GetRawACNoShield(int &shield_ac) { } uint32 Bot::CalcCurrentWeight() { - const Item_Struct* TempItem = 0; + const EQEmu::Item_Struct* TempItem = 0; ItemInst* inst; uint32 Total = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { diff --git a/zone/bot.h b/zone/bot.h index b8ccb7c5d..b04481bd1 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -385,7 +385,7 @@ public: void BotTradeSwapItem(Client* client, int16 lootSlot, const ItemInst* inst, const ItemInst* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap = true); void BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true); void EquipBot(std::string* errorMessage); - bool CheckLoreConflict(const Item_Struct* item); + bool CheckLoreConflict(const EQEmu::Item_Struct* item); virtual void UpdateEquipmentLight() { m_Light.Type[EQEmu::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); } // Static Class Methods diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 2fa020635..92fd8cf44 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -7062,7 +7062,7 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) } const ItemInst* inst = nullptr; - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; bool is2Hweapon = false; std::string item_link; @@ -7081,7 +7081,7 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) } item = inst->GetItem(); - if ((i == EQEmu::legacy::SlotPrimary) && ((item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HPiercing))) { + if ((i == EQEmu::legacy::SlotPrimary) && item->IsType2HWeapon()) { is2Hweapon = true; } @@ -7131,7 +7131,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) return; } - const Item_Struct* itm = nullptr; + const EQEmu::Item_Struct* itm = nullptr; const ItemInst* itminst = my_bot->GetBotItem(slotId); if (itminst) itm = itminst->GetItem(); @@ -7234,7 +7234,7 @@ void bot_subcommand_inventory_window(Client *c, const Seperator *sep) //linker.SetLinkType(linker.linkItemInst); for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; const ItemInst* inst = my_bot->CastToBot()->GetBotItem(i == 22 ? EQEmu::legacy::SlotPowerSource : i); if (inst) item = inst->GetItem(); diff --git a/zone/client.cpp b/zone/client.cpp index 30d451d38..7940cf266 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2539,7 +2539,7 @@ void Client::SetFeigned(bool in_feigned) { feigned=in_feigned; } -void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const Item_Struct* item, bool buying) +void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::Item_Struct* item, bool buying) { if(!player || !merchant || !item) return; @@ -2577,7 +2577,7 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail) // Start bind if (!bindwound_timer.Enabled()) { // make sure we actually have a bandage... and consume it. - int16 bslot = m_inv.HasItemByUse(ItemTypeBandage, 1, invWhereWorn | invWherePersonal); + int16 bslot = m_inv.HasItemByUse(EQEmu::item::ItemTypeBandage, 1, invWhereWorn | invWherePersonal); if (bslot == INVALID_INDEX) { bind_out->type = 3; QueuePacket(outapp); @@ -2725,8 +2725,8 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail) } void Client::SetMaterial(int16 in_slot, uint32 item_id) { - const Item_Struct* item = database.GetItem(item_id); - if (item && (item->ItemClass==ItemClassCommon)) + const EQEmu::Item_Struct* item = database.GetItem(item_id); + if (item && item->IsClassCommon()) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); if (matslot != EQEmu::legacy::MaterialInvalid) @@ -3768,7 +3768,7 @@ void Client::SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID) { return; } -void Client::SendPickPocketResponse(Mob *from, uint32 amt, int type, const Item_Struct* item){ +void Client::SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu::Item_Struct* item){ EQApplicationPacket* outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); sPickPocket_Struct* pick_out = (sPickPocket_Struct*) outapp->pBuffer; pick_out->coin = amt; @@ -3945,7 +3945,7 @@ bool Client::KeyRingCheck(uint32 item_id) void Client::KeyRingList() { Message(4,"Keys on Keyring:"); - const Item_Struct *item = 0; + const EQEmu::Item_Struct *item = 0; for(std::list::iterator iter = keyring.begin(); iter != keyring.end(); ++iter) @@ -4212,51 +4212,34 @@ uint16 Client::GetPrimarySkillValue() uint8 type = m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType; //is this the best way to do this? - switch (type) - { - case ItemType1HSlash: // 1H Slashing - { - skill = Skill1HSlashing; - break; - } - case ItemType2HSlash: // 2H Slashing - { - skill = Skill2HSlashing; - break; - } - case ItemType1HPiercing: // Piercing - { + switch (type) { + case EQEmu::item::ItemType1HSlash: // 1H Slashing + skill = Skill1HSlashing; + break; + case EQEmu::item::ItemType2HSlash: // 2H Slashing + skill = Skill2HSlashing; + break; + case EQEmu::item::ItemType1HPiercing: // Piercing + skill = Skill1HPiercing; + break; + case EQEmu::item::ItemType1HBlunt: // 1H Blunt + skill = Skill1HBlunt; + break; + case EQEmu::item::ItemType2HBlunt: // 2H Blunt + skill = Skill2HBlunt; + break; + case EQEmu::item::ItemType2HPiercing: // 2H Piercing + if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) skill = Skill1HPiercing; - break; - } - case ItemType1HBlunt: // 1H Blunt - { - skill = Skill1HBlunt; - break; - } - case ItemType2HBlunt: // 2H Blunt - { - skill = Skill2HBlunt; - break; - } - case ItemType2HPiercing: // 2H Piercing - { - if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) - skill = Skill1HPiercing; - else - skill = Skill2HPiercing; - break; - } - case ItemTypeMartial: // Hand to Hand - { - skill = SkillHandtoHand; - break; - } - default: // All other types default to Hand to Hand - { - skill = SkillHandtoHand; - break; - } + else + skill = Skill2HPiercing; + break; + case EQEmu::item::ItemTypeMartial: // Hand to Hand + skill = SkillHandtoHand; + break; + default: // All other types default to Hand to Hand + skill = SkillHandtoHand; + break; } } @@ -5708,7 +5691,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { insr->TargetID = requester->GetID(); insr->playerid = requestee->GetID(); - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; const ItemInst* inst = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); for(int16 L = 0; L <= 20; L++) { @@ -5720,7 +5703,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { strcpy(insr->itemnames[L], item->Name); if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - const Item_Struct *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const EQEmu::Item_Struct *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); insr->itemicons[L] = aug_item->Icon; } else if (inst && inst->GetOrnamentationIcon()) @@ -6902,7 +6885,7 @@ void Client::SendAltCurrencies() { uint32 i = 0; std::list::iterator iter = zone->AlternateCurrencies.begin(); while(iter != zone->AlternateCurrencies.end()) { - const Item_Struct* item = database.GetItem((*iter).item_id); + const EQEmu::Item_Struct* item = database.GetItem((*iter).item_id); altc->entries[i].currency_number = (*iter).id; altc->entries[i].unknown00 = 1; altc->entries[i].currency_number2 = (*iter).id; @@ -7555,7 +7538,7 @@ void Client::DuplicateLoreMessage(uint32 ItemID) return; } - const Item_Struct *item = database.GetItem(ItemID); + const EQEmu::Item_Struct *item = database.GetItem(ItemID); if(!item) return; @@ -8272,7 +8255,7 @@ void Client::SetConsumption(int32 in_hunger, int32 in_thirst) safe_delete(outapp); } -void Client::Consume(const Item_Struct *item, uint8 type, int16 slot, bool auto_consume) +void Client::Consume(const EQEmu::Item_Struct *item, uint8 type, int16 slot, bool auto_consume) { if(!item) { return; } @@ -8285,7 +8268,7 @@ void Client::Consume(const Item_Struct *item, uint8 type, int16 slot, bool auto_ else cons_mod = cons_mod * RuleI(Character, ConsumptionMultiplier) / 100; - if(type == ItemTypeFood) + if (type == EQEmu::item::ItemTypeFood) { int hchange = item->CastTime * cons_mod; hchange = mod_food_value(item, hchange); @@ -8390,7 +8373,7 @@ int Client::GetQuiverHaste(int delay) const ItemInst *pi = nullptr; for (int r = EQEmu::legacy::GENERAL_BEGIN; r <= EQEmu::legacy::GENERAL_END; r++) { pi = GetInv().GetItem(r); - if (pi && pi->IsType(ItemClassContainer) && pi->GetItem()->BagType == BagTypeQuiver && + if (pi && pi->IsClassBag() && pi->GetItem()->BagType == EQEmu::item::BagTypeQuiver && pi->GetItem()->BagWR > 0) break; if (r == EQEmu::legacy::GENERAL_END) diff --git a/zone/client.h b/zone/client.h index 165816502..28da7ee72 100644 --- a/zone/client.h +++ b/zone/client.h @@ -27,7 +27,11 @@ class Object; class Raid; class Seperator; class ServerPacket; -struct Item_Struct; + +namespace EQEmu +{ + struct Item_Struct; +} #include "../common/timer.h" #include "../common/ptimer.h" @@ -290,7 +294,7 @@ public: void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); virtual bool Process(); - void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const Item_Struct* item, bool buying); + void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::Item_Struct* item, bool buying); void SendPacketQueue(bool Block = true); void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone); void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL); @@ -398,7 +402,7 @@ public: inline uint8 GetLanguageSkill(uint16 n) const { return m_pp.languages[n]; } - void SendPickPocketResponse(Mob *from, uint32 amt, int type, const Item_Struct* item = nullptr); + void SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu::Item_Struct* item = nullptr); inline const char* GetLastName() const { return lastname; } @@ -594,7 +598,7 @@ public: void AssignToInstance(uint16 instance_id); void RemoveFromInstance(uint16 instance_id); void WhoAll(); - bool CheckLoreConflict(const Item_Struct* item); + bool CheckLoreConflict(const EQEmu::Item_Struct* item); void ChangeLastName(const char* in_lastname); void GetGroupAAs(GroupLeadershipAA_Struct *into) const; void GetRaidAAs(RaidLeadershipAA_Struct *into) const; @@ -1173,7 +1177,7 @@ public: void LoadAccountFlags(); void SetAccountFlag(std::string flag, std::string val); std::string GetAccountFlag(std::string flag); float GetDamageMultiplier(SkillUseTypes); - void Consume(const Item_Struct *item, uint8 type, int16 slot, bool auto_consume); + void Consume(const EQEmu::Item_Struct *item, uint8 type, int16 slot, bool auto_consume); void PlayMP3(const char* fname); void ExpeditionSay(const char *str, int ExpID); int mod_client_damage(int damage, SkillUseTypes skillinuse, int hand, const ItemInst* weapon, Mob* other); @@ -1195,9 +1199,9 @@ public: int32 mod_client_xp(int32 in_exp, NPC *npc); uint32 mod_client_xp_for_level(uint32 xp, uint16 check_level); int mod_client_haste_cap(int cap); - int mod_consume(Item_Struct *item, ItemUseTypes type, int change); - int mod_food_value(const Item_Struct *item, int change); - int mod_drink_value(const Item_Struct *item, int change); + int mod_consume(EQEmu::Item_Struct *item, EQEmu::item::ItemType type, int change); + int mod_food_value(const EQEmu::Item_Struct *item, int change); + int mod_drink_value(const EQEmu::Item_Struct *item, int change); void SetEngagedRaidTarget(bool value) { EngagedRaidTarget = value; } bool GetEngagedRaidTarget() const { return EngagedRaidTarget; } diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 6e22cc514..c6860a52f 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -487,7 +487,7 @@ int32 Client::GetRawItemAC() // this skips MainAmmo..add an '=' conditional if that slot is required (original behavior) for (int16 slot_id = EQEmu::legacy::EQUIPMENT_BEGIN; slot_id < EQEmu::legacy::EQUIPMENT_END; slot_id++) { const ItemInst* inst = m_inv[slot_id]; - if (inst && inst->IsType(ItemClassCommon)) { + if (inst && inst->IsClassCommon()) { Total += inst->GetItem()->AC; } } @@ -1070,7 +1070,7 @@ int32 Client::CalcAC() bool equiped = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary); if (equiped) { uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType; - if (shield == ItemTypeShield) { + if (shield == EQEmu::item::ItemTypeShield) { displayed += itembonuses.HeroicSTR / 2; } } @@ -1099,7 +1099,7 @@ int32 Client::GetACMit() bool equiped = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary); if (equiped) { uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType; - if (shield == ItemTypeShield) { + if (shield == EQEmu::item::ItemTypeShield) { mitigation += itembonuses.HeroicSTR / 2; } } @@ -1302,7 +1302,7 @@ int32 Client::CalcManaRegenCap() uint32 Client::CalcCurrentWeight() { - const Item_Struct* TempItem = 0; + const EQEmu::Item_Struct* TempItem = 0; ItemInst* ins; uint32 Total = 0; int x; @@ -1337,7 +1337,7 @@ uint32 Client::CalcCurrentWeight() } } ItemInst* baginst = GetInv().GetItem(bagslot); - if (baginst && baginst->GetItem() && baginst->IsType(ItemClassContainer)) { + if (baginst && baginst->GetItem() && baginst->IsClassBag()) { reduction = baginst->GetItem()->BagWR; } if (reduction > 0) { @@ -2207,7 +2207,7 @@ int Client::GetRawACNoShield(int &shield_ac) const shield_ac = 0; const ItemInst *inst = m_inv.GetItem(EQEmu::legacy::SlotSecondary); if (inst) { - if (inst->GetItem()->ItemType == ItemTypeShield) { + if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; for (uint8 i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 5222ca96c..de35ccf2b 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1881,7 +1881,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) merchantid = tmp->CastToNPC()->MerchantType; - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; bool found = false; std::list merlist = zone->merchanttable[merchantid]; std::list::const_iterator itr; @@ -2057,7 +2057,7 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app) merchantid = tmp->CastToNPC()->MerchantType; tmp->CastToNPC()->FaceTarget(this->CastToMob()); - const Item_Struct *item = 0; + const EQEmu::Item_Struct *item = 0; std::list merlist = zone->merchanttable[merchantid]; std::list::const_iterator itr; for (itr = merlist.begin(); itr != merlist.end() && count<255; ++itr){ @@ -2156,7 +2156,7 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app) return; } - const Item_Struct* item = database.GetItem(itemid); + const EQEmu::Item_Struct* item = database.GetItem(itemid); ItemInst* inst = GetInv().GetItem(ams_in->slot); if (!item || !inst){ Message(13, "You seemed to have misplaced that item..."); @@ -2431,7 +2431,7 @@ void Client::Handle_OP_AltCurrencyMerchantRequest(const EQApplicationPacket *app ss << alt_cur_id << "|1|" << alt_cur_id; uint32 count = 0; uint32 merchant_id = tar->MerchantType; - const Item_Struct *item = nullptr; + const EQEmu::Item_Struct *item = nullptr; std::list merlist = zone->merchanttable[merchant_id]; std::list::const_iterator itr; @@ -2491,7 +2491,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) return; } - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2640,7 +2640,7 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) return; } - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2733,7 +2733,7 @@ void Client::Handle_OP_AltCurrencySellSelection(const EQApplicationPacket *app) return; } - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2815,7 +2815,7 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app) const ItemInst* SecondaryWeapon = GetInv().GetItem(EQEmu::legacy::SlotSecondary); const ItemInst* PoisonItemInstance = GetInv()[ApplyPoisonData->inventorySlot]; - bool IsPoison = PoisonItemInstance && (PoisonItemInstance->GetItem()->ItemType == ItemTypePoison); + bool IsPoison = PoisonItemInstance && (PoisonItemInstance->GetItem()->ItemType == EQEmu::item::ItemTypePoison); if (!IsPoison) { @@ -2826,8 +2826,8 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app) } else if (GetClass() == ROGUE) { - if ((PrimaryWeapon && PrimaryWeapon->GetItem()->ItemType == ItemType1HPiercing) || - (SecondaryWeapon && SecondaryWeapon->GetItem()->ItemType == ItemType1HPiercing)) { + if ((PrimaryWeapon && PrimaryWeapon->GetItem()->ItemType == EQEmu::item::ItemType1HPiercing) || + (SecondaryWeapon && SecondaryWeapon->GetItem()->ItemType == EQEmu::item::ItemType1HPiercing)) { float SuccessChance = (GetSkill(SkillApplyPoison) + GetLevel()) / 400.0f; double ChanceRoll = zone->random.Real(0, 1); @@ -2907,7 +2907,7 @@ void Client::Handle_OP_AugmentInfo(const EQApplicationPacket *app) } AugmentInfo_Struct* AugInfo = (AugmentInfo_Struct*)app->pBuffer; - const Item_Struct * item = database.GetItem(AugInfo->itemid); + const EQEmu::Item_Struct * item = database.GetItem(AugInfo->itemid); if (item) { strn0cpy(AugInfo->augment_info, item->Name, 64); @@ -2965,7 +2965,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) Message(13, "Error: Missing an augmentation distiller for safely removing this augment."); return; } - else if (solvent->GetItem()->ItemType == ItemUseTypes::ItemTypeAugmentationDistiller) + else if (solvent->GetItem()->ItemType == EQEmu::item::ItemTypeAugmentationDistiller) { old_aug = tobe_auged->GetAugment(in_augment->augment_index); @@ -2982,7 +2982,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) return; } } - else if (solvent->GetItem()->ItemType != ItemUseTypes::ItemTypePerfectedAugmentationDistiller) + else if (solvent->GetItem()->ItemType != EQEmu::item::ItemTypePerfectedAugmentationDistiller) { Log.Out(Logs::General, Logs::Error, "Player tried to safely remove an augment with a non-distiller item."); Message(13, "Error: Invalid augmentation distiller for safely removing this augment."); @@ -3489,7 +3489,7 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app) { BarterItemSearchLinkRequest_Struct* bislr = (BarterItemSearchLinkRequest_Struct*)app->pBuffer; - const Item_Struct* item = database.GetItem(bislr->ItemID); + const EQEmu::Item_Struct* item = database.GetItem(bislr->ItemID); if (!item) Message(13, "Error: This item does not exist!"); @@ -3522,7 +3522,7 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app) { BuyerItemSearchLinkRequest_Struct* bislr = (BuyerItemSearchLinkRequest_Struct*)app->pBuffer; - const Item_Struct* item = database.GetItem(bislr->ItemID); + const EQEmu::Item_Struct* item = database.GetItem(bislr->ItemID); if (!item) Message(13, "Error: This item does not exist!"); @@ -3561,7 +3561,7 @@ void Client::Handle_OP_BazaarInspect(const EQApplicationPacket *app) BazaarInspect_Struct* bis = (BazaarInspect_Struct*)app->pBuffer; - const Item_Struct* item = database.GetItem(bis->ItemID); + const EQEmu::Item_Struct* item = database.GetItem(bis->ItemID); if (!item) { Message(13, "Error: This item does not exist!"); @@ -4011,9 +4011,9 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) // packet field types will be reviewed as packet transistions occur const ItemInst* inst = m_inv[castspell->inventoryslot]; //slot values are int16, need to check packet on this field //bool cancast = true; - if (inst && inst->IsType(ItemClassCommon)) + if (inst && inst->IsClassCommon()) { - const Item_Struct* item = inst->GetItem(); + const EQEmu::Item_Struct* item = inst->GetItem(); if (item->Click.Effect != (uint32)castspell->spell_id) { database.SetMQDetectionFlag(account_name, name, "OP_CastSpell with item, tried to cast a different spell.", zone->GetShortName()); @@ -4021,7 +4021,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) return; } - if ((item->Click.Type == ET_ClickEffect) || (item->Click.Type == ET_Expendable) || (item->Click.Type == ET_EquipClick) || (item->Click.Type == ET_ClickEffect2)) + if ((item->Click.Type == EQEmu::item::ItemEffectClick) || (item->Click.Type == EQEmu::item::ItemEffectExpendable) || (item->Click.Type == EQEmu::item::ItemEffectEquipClick) || (item->Click.Type == EQEmu::item::ItemEffectClick2)) { if (item->Click.Level2 > 0) { @@ -4861,12 +4861,12 @@ void Client::Handle_OP_Consume(const EQApplicationPacket *app) return; } - const Item_Struct* eat_item = myitem->GetItem(); + const EQEmu::Item_Struct* eat_item = myitem->GetItem(); if (pcs->type == 0x01) { - Consume(eat_item, ItemTypeFood, pcs->slot, (pcs->auto_consumed == 0xffffffff)); + Consume(eat_item, EQEmu::item::ItemTypeFood, pcs->slot, (pcs->auto_consumed == 0xffffffff)); } else if (pcs->type == 0x02) { - Consume(eat_item, ItemTypeDrink, pcs->slot, (pcs->auto_consumed == 0xffffffff)); + Consume(eat_item, EQEmu::item::ItemTypeDrink, pcs->slot, (pcs->auto_consumed == 0xffffffff)); } else { Log.Out(Logs::General, Logs::Error, "OP_Consume: unknown type, type:%i", (int)pcs->type); @@ -5134,7 +5134,7 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app) DeleteItem_Struct* alc = (DeleteItem_Struct*)app->pBuffer; const ItemInst *inst = GetInv().GetItem(alc->from_slot); - if (inst && inst->GetItem()->ItemType == ItemTypeAlcohol) { + if (inst && inst->GetItem()->ItemType == EQEmu::item::ItemTypeAlcohol) { entity_list.MessageClose_StringID(this, true, 50, 0, DRINKING_MESSAGE, GetName(), inst->GetItem()->Name); CheckIncreaseSkill(SkillAlcoholTolerance, nullptr, 25); @@ -6918,7 +6918,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) return; } - const Item_Struct* CursorItem = CursorItemInst->GetItem(); + const EQEmu::Item_Struct* CursorItem = CursorItemInst->GetItem(); if (!CursorItem->NoDrop || CursorItemInst->IsAttuned()) { @@ -7991,7 +7991,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) EQApplicationPacket* outapp = app->Copy(); InspectResponse_Struct* insr = (InspectResponse_Struct*)outapp->pBuffer; Mob* tmp = entity_list.GetMob(insr->TargetID); - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); for (int16 L = EQEmu::legacy::EQUIPMENT_BEGIN; L <= EQEmu::legacy::SlotWaist; L++) { @@ -8001,7 +8001,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) if (item) { strcpy(insr->itemnames[L], item->Name); if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - const Item_Struct *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const EQEmu::Item_Struct *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); insr->itemicons[L] = aug_item->Icon; } else if (inst->GetOrnamentationIcon()) { @@ -8101,7 +8101,7 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) // todo: verify ivrs->link_hash based on a rule, in case we don't care about people being able to sniff data // from the item DB - const Item_Struct *item = database.GetItem(ivrs->item_id); + const EQEmu::Item_Struct *item = database.GetItem(ivrs->item_id); if (!item) { if (ivrs->item_id != SAYLINK_ITEM_ID) { Message(13, "Error: The item for the link you have clicked on does not exist!"); @@ -8192,7 +8192,7 @@ void Client::Handle_OP_ItemName(const EQApplicationPacket *app) return; } ItemNamePacket_Struct *p = (ItemNamePacket_Struct*)app->pBuffer; - const Item_Struct *item = 0; + const EQEmu::Item_Struct *item = 0; if ((item = database.GetItem(p->item_id)) != nullptr) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_ItemName, sizeof(ItemNamePacket_Struct)); p = (ItemNamePacket_Struct*)outapp->pBuffer; @@ -8208,7 +8208,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app) VERIFY_PACKET_LENGTH(OP_ItemPreview, app, ItemPreview_Struct); ItemPreview_Struct *ips = (ItemPreview_Struct *)app->pBuffer; - const Item_Struct* item = database.GetItem(ips->itemid); + const EQEmu::Item_Struct* item = database.GetItem(ips->itemid); if (item) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_ItemPreview, strlen(item->Name) + strlen(item->Lore) + strlen(item->IDFile) + 898); @@ -8424,7 +8424,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) return; } - const Item_Struct* item = inst->GetItem(); + const EQEmu::Item_Struct* item = inst->GetItem(); if (!item) { Message(0, "Error: item not found in inventory slot #%i", slot_id); DeleteItemInInventory(slot_id, 0, true); @@ -8458,7 +8458,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) Log.Out(Logs::General, Logs::None, "OP ItemVerifyRequest: spell=%i, target=%i, inv=%i", spell_id, target_id, slot_id); - if (m_inv.SupportsClickCasting(slot_id) || ((item->ItemType == ItemTypePotion || item->PotionBelt) && m_inv.SupportsPotionBeltCasting(slot_id))) // sanity check + if (m_inv.SupportsClickCasting(slot_id) || ((item->ItemType == EQEmu::item::ItemTypePotion || item->PotionBelt) && m_inv.SupportsPotionBeltCasting(slot_id))) // sanity check { ItemInst* p_inst = (ItemInst*)inst; @@ -8472,42 +8472,42 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) int r; bool tryaug = false; ItemInst* clickaug = 0; - Item_Struct* augitem = 0; + EQEmu::Item_Struct* augitem = 0; for (r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { const ItemInst* aug_i = inst->GetAugment(r); if (!aug_i) continue; - const Item_Struct* aug = aug_i->GetItem(); + const EQEmu::Item_Struct* aug = aug_i->GetItem(); if (!aug) continue; - if ((aug->Click.Type == ET_ClickEffect) || (aug->Click.Type == ET_Expendable) || (aug->Click.Type == ET_EquipClick) || (aug->Click.Type == ET_ClickEffect2)) + if ((aug->Click.Type == EQEmu::item::ItemEffectClick) || (aug->Click.Type == EQEmu::item::ItemEffectExpendable) || (aug->Click.Type == EQEmu::item::ItemEffectEquipClick) || (aug->Click.Type == EQEmu::item::ItemEffectClick2)) { tryaug = true; clickaug = (ItemInst*)aug_i; - augitem = (Item_Struct*)aug; + augitem = (EQEmu::Item_Struct*)aug; spell_id = aug->Click.Effect; break; } } - if ((spell_id <= 0) && (item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink && item->ItemType != ItemTypeAlcohol && item->ItemType != ItemTypeSpell)) + if ((spell_id <= 0) && (item->ItemType != EQEmu::item::ItemTypeFood && item->ItemType != EQEmu::item::ItemTypeDrink && item->ItemType != EQEmu::item::ItemTypeAlcohol && item->ItemType != EQEmu::item::ItemTypeSpell)) { Log.Out(Logs::General, Logs::None, "Item with no effect right clicked by %s", GetName()); } - else if (inst->IsType(ItemClassCommon)) + else if (inst->IsClassCommon()) { - if (item->ItemType == ItemTypeSpell && (strstr((const char*)item->Name, "Tome of ") || strstr((const char*)item->Name, "Skill: "))) + if (item->ItemType == EQEmu::item::ItemTypeSpell && (strstr((const char*)item->Name, "Tome of ") || strstr((const char*)item->Name, "Skill: "))) { DeleteItemInInventory(slot_id, 1, true); TrainDiscipline(item->ID); } - else if (item->ItemType == ItemTypeSpell) + else if (item->ItemType == EQEmu::item::ItemTypeSpell) { return; } - else if ((item->Click.Type == ET_ClickEffect) || (item->Click.Type == ET_Expendable) || (item->Click.Type == ET_EquipClick) || (item->Click.Type == ET_ClickEffect2)) + else if ((item->Click.Type == EQEmu::item::ItemEffectClick) || (item->Click.Type == EQEmu::item::ItemEffectExpendable) || (item->Click.Type == EQEmu::item::ItemEffectEquipClick) || (item->Click.Type == EQEmu::item::ItemEffectClick2)) { if (inst->GetCharges() == 0) { @@ -8565,22 +8565,22 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) { if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD && !inst->IsEquipable(GetBaseRace(), GetClass())) { - if (item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink && item->ItemType != ItemTypeAlcohol) + if (item->ItemType != EQEmu::item::ItemTypeFood && item->ItemType != EQEmu::item::ItemTypeDrink && item->ItemType != EQEmu::item::ItemTypeAlcohol) { Log.Out(Logs::General, Logs::None, "Error: unknown item->Click.Type (%i)", item->Click.Type); } else { //This is food/drink - consume it - if (item->ItemType == ItemTypeFood && m_pp.hunger_level < 5000) + if (item->ItemType == EQEmu::item::ItemTypeFood && m_pp.hunger_level < 5000) { Consume(item, item->ItemType, slot_id, false); } - else if (item->ItemType == ItemTypeDrink && m_pp.thirst_level < 5000) + else if (item->ItemType == EQEmu::item::ItemTypeDrink && m_pp.thirst_level < 5000) { Consume(item, item->ItemType, slot_id, false); } - else if (item->ItemType == ItemTypeAlcohol) + else if (item->ItemType == EQEmu::item::ItemTypeAlcohol) { #if EQDEBUG >= 1 Log.Out(Logs::General, Logs::None, "Drinking Alcohol from slot:%i", slot_id); @@ -9701,7 +9701,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) else { int16 from_parent = m_inv.CalcSlotId(mi->from_slot); if (!m_inv[from_parent]) { mi_hack = true; } - else if (!m_inv[from_parent]->IsType(ItemClassContainer)) { mi_hack = true; } + else if (!m_inv[from_parent]->IsClassBag()) { mi_hack = true; } else if (m_inv.CalcBagIdx(mi->from_slot) >= m_inv[from_parent]->GetItem()->BagSlots) { mi_hack = true; } } } @@ -9711,7 +9711,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) else { int16 to_parent = m_inv.CalcSlotId(mi->to_slot); if (!m_inv[to_parent]) { mi_hack = true; } - else if (!m_inv[to_parent]->IsType(ItemClassContainer)) { mi_hack = true; } + else if (!m_inv[to_parent]->IsClassBag()) { mi_hack = true; } else if (m_inv.CalcBagIdx(mi->to_slot) >= m_inv[to_parent]->GetItem()->BagSlots) { mi_hack = true; } } } @@ -10545,7 +10545,7 @@ void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) } if (mptbs->Action == 0) { - const Item_Struct *BaseItem = database.GetItem(mptbs->ItemID); + const EQEmu::Item_Struct *BaseItem = database.GetItem(mptbs->ItemID); if (BaseItem) { m_pp.potionbelt.Items[mptbs->SlotNumber].ID = BaseItem->ID; m_pp.potionbelt.Items[mptbs->SlotNumber].Icon = BaseItem->Icon; @@ -12028,8 +12028,8 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app) return; if (inst) { - const Item_Struct* shield = inst->GetItem(); - if (shield && shield->ItemType == ItemTypeShield) + const EQEmu::Item_Struct* shield = inst->GetItem(); + if (shield && shield->ItemType == EQEmu::item::ItemTypeShield) { for (int x = 0; x < 2; x++) { @@ -12136,7 +12136,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) break; } } - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; uint32 prevcharges = 0; if (item_id == 0) { //check to see if its on the temporary table std::list tmp_merlist = zone->tmpmerchanttable[tmp->GetNPCTypeID()]; @@ -12382,7 +12382,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) uint32 itemid = GetItemIDAt(mp->itemslot); if (itemid == 0) return; - const Item_Struct* item = database.GetItem(itemid); + const EQEmu::Item_Struct* item = database.GetItem(itemid); ItemInst* inst = GetInv().GetItem(mp->itemslot); if (!item || !inst){ Message(13, "You seemed to have misplaced that item.."); @@ -13479,7 +13479,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) TradeItemsValid = false; break; } - const Item_Struct *Item = database.GetItem(gis->Items[i]); + const EQEmu::Item_Struct *Item = database.GetItem(gis->Items[i]); if (!Item) { Message(13, "Unexpected error. Unable to start trader mode"); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 6dcca861e..72dd478c8 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -299,7 +299,7 @@ bool Client::Process() { ItemInst *ranged = GetInv().GetItem(EQEmu::legacy::SlotRange); if(ranged) { - if(ranged->GetItem() && ranged->GetItem()->ItemType == ItemTypeBow){ + if (ranged->GetItem() && ranged->GetItem()->ItemType == EQEmu::item::ItemTypeBow){ if(ranged_timer.Check(false)){ if(GetTarget() && (GetTarget()->IsNPC() || GetTarget()->IsClient())){ if(GetTarget()->InFrontMob(this, GetTarget()->GetX(), GetTarget()->GetY())){ @@ -319,7 +319,7 @@ bool Client::Process() { ranged_timer.Start(); } } - else if(ranged->GetItem() && (ranged->GetItem()->ItemType == ItemTypeLargeThrowing || ranged->GetItem()->ItemType == ItemTypeSmallThrowing)){ + else if (ranged->GetItem() && (ranged->GetItem()->ItemType == EQEmu::item::ItemTypeLargeThrowing || ranged->GetItem()->ItemType == EQEmu::item::ItemTypeSmallThrowing)){ if(ranged_timer.Check(false)){ if(GetTarget() && (GetTarget()->IsNPC() || GetTarget()->IsClient())){ if(GetTarget()->InFrontMob(this, GetTarget()->GetX(), GetTarget()->GetY())){ @@ -740,8 +740,8 @@ void Client::BulkSendInventoryItems() for (int16 slot_id = EQEmu::legacy::TRADE_BEGIN; slot_id <= EQEmu::legacy::TRADE_END; slot_id++) { ItemInst* inst = m_inv.PopItem(slot_id); if(inst) { - bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; - int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size, is_arrow); + bool is_arrow = (inst->GetItem()->ItemType == EQEmu::item::ItemTypeArrow) ? true : false; + int16 free_slot_id = m_inv.FindFreeSlot(inst->IsClassBag(), true, inst->GetItem()->Size, is_arrow); Log.Out(Logs::Detail, Logs::Inventory, "Incomplete Trade Transaction: Moving %s from slot %i to %i", inst->GetItem()->Name, slot_id, free_slot_id); PutItemInInventory(free_slot_id, *inst, false); database.SaveInventory(character_id, nullptr, slot_id); @@ -825,12 +825,12 @@ void Client::BulkSendInventoryItems() } void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { - const Item_Struct* handyitem = nullptr; + const EQEmu::Item_Struct* handyitem = nullptr; uint32 numItemSlots = 80; //The max number of items passed in the transaction. if (m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater) { // RoF+ can send 200 items numItemSlots = 200; } - const Item_Struct *item; + const EQEmu::Item_Struct *item; std::list merlist = zone->merchanttable[merchant_id]; std::list::const_iterator itr; Mob* merch = entity_list.GetMobByNpcTypeID(npcid); @@ -869,7 +869,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { else handychance--; int charges = 1; - if (item->ItemClass == ItemClassCommon) + if (item->IsClassCommon()) charges = item->MaxCharges; ItemInst* inst = database.CreateItem(item, charges); if (inst) { @@ -1086,9 +1086,9 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) case memSpellScribing: { // scribing spell to book const ItemInst* inst = m_inv[EQEmu::legacy::SlotCursor]; - if(inst && inst->IsType(ItemClassCommon)) + if (inst && inst->IsClassCommon()) { - const Item_Struct* item = inst->GetItem(); + const EQEmu::Item_Struct* item = inst->GetItem(); if (RuleB(Character, RestrictSpellScribing) && !item->IsEquipable(GetRace(), GetClass())) { Message_StringID(13, CANNOT_USE_ITEM); diff --git a/zone/command.cpp b/zone/command.cpp index 46f157015..2d341ef7d 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2543,7 +2543,7 @@ void command_peekinv(Client *c, const Seperator *sep) Client* targetClient = c->GetTarget()->CastToClient(); const ItemInst* inst_main = nullptr; const ItemInst* inst_sub = nullptr; - const Item_Struct* item_data = nullptr; + const EQEmu::Item_Struct* item_data = nullptr; std::string item_link; EQEmu::saylink::SayLinkEngine linker; linker.SetLinkType(linker.SayLinkItemInst); @@ -2584,7 +2584,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "InvSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2618,7 +2618,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "CursorSlot: %i, Depth: %i, Item: %i (%s), Charges: %i", EQEmu::legacy::SlotCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2655,7 +2655,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "BankSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2677,7 +2677,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "SharedBankSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2700,7 +2700,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "TradeSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2732,7 +2732,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "WorldSlot: %i, Item: %i (%s), Charges: %i", (EQEmu::legacy::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(ItemClassContainer) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(EQEmu::item::ItemClassBag) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -3146,7 +3146,7 @@ void command_equipitem(Client *c, const Seperator *sep) bool partialmove = false; int16 movecount; - if (from_inst && from_inst->IsType(ItemClassCommon)) { + if (from_inst && from_inst->IsClassCommon()) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer; mi->from_slot = EQEmu::legacy::SlotCursor; @@ -4357,10 +4357,10 @@ void command_iteminfo(Client *c, const Seperator *sep) c->Message(0, ">> NoDrop: %u, NoRent: %u, NoPet: %u, NoTransfer: %u, FVNoDrop: %u", item->NoDrop, item->NoRent, (uint8)item->NoPet, (uint8)item->NoTransfer, item->FVNoDrop); - if (item->ItemClass == ItemClassBook) { + if (item->IsClassBook()) { c->Message(0, "*** This item is a Book (filename:'%s') ***", item->Filename); } - else if (item->ItemClass == ItemClassContainer) { + else if (item->IsClassBag()) { c->Message(0, "*** This item is a Container (%u slots) ***", item->BagSlots); } else { @@ -5510,7 +5510,7 @@ void command_summonitem(Client *c, const Seperator *sep) } int16 item_status = 0; - const Item_Struct* item = database.GetItem(itemid); + const EQEmu::Item_Struct* item = database.GetItem(itemid); if (item) { item_status = static_cast(item->MinStatus); } @@ -5549,7 +5549,7 @@ void command_giveitem(Client *c, const Seperator *sep) Client *t = c->GetTarget()->CastToClient(); uint32 itemid = atoi(sep->arg[1]); int16 item_status = 0; - const Item_Struct* item = database.GetItem(itemid); + const EQEmu::Item_Struct* item = database.GetItem(itemid); if(item) { item_status = static_cast(item->MinStatus); } @@ -5602,7 +5602,7 @@ void command_itemsearch(Client *c, const Seperator *sep) { const char *search_criteria=sep->argplus[1]; - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; std::string item_link; EQEmu::saylink::SayLinkEngine linker; linker.SetLinkType(linker.SayLinkItemData); @@ -10225,7 +10225,7 @@ void command_zopp(Client *c, const Seperator *sep) uint32 itemid = atoi(sep->arg[3]); int16 charges = sep->argnum == 4 ? atoi(sep->arg[4]) : 1; // defaults to 1 charge if not specified - const Item_Struct* FakeItem = database.GetItem(itemid); + const EQEmu::Item_Struct* FakeItem = database.GetItem(itemid); if (!FakeItem) { c->Message(13, "Error: Item [%u] is not a valid item id.", itemid); @@ -10233,7 +10233,7 @@ void command_zopp(Client *c, const Seperator *sep) } int16 item_status = 0; - const Item_Struct* item = database.GetItem(itemid); + const EQEmu::Item_Struct* item = database.GetItem(itemid); if(item) { item_status = static_cast(item->MinStatus); } diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 011741900..ff8243003 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -407,7 +407,7 @@ void Corpse::MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, s removedList.push_back(equipSlot); while (true) { - if (!inst->IsType(ItemClassContainer)) { break; } + if (!inst->IsClassBag()) { break; } if (equipSlot < EQEmu::legacy::GENERAL_BEGIN || equipSlot > EQEmu::legacy::SlotCursor) { break; } for (auto sub_index = SUB_INDEX_BEGIN; sub_index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++sub_index) { @@ -977,7 +977,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a safe_delete(outapp); if(Loot_Request_Type == 5) { int pkitem = GetPlayerKillItem(); - const Item_Struct* item = database.GetItem(pkitem); + const EQEmu::Item_Struct* item = database.GetItem(pkitem); ItemInst* inst = database.CreateItem(item, item->MaxCharges); if(inst) { if (item->RecastDelay) @@ -992,7 +992,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a } int i = 0; - const Item_Struct* item = 0; + const EQEmu::Item_Struct* item = 0; ItemList::iterator cur,end; cur = itemlist.begin(); end = itemlist.end(); @@ -1107,7 +1107,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { being_looted_by = 0xFFFFFFFF; return; } - const Item_Struct* item = 0; + const EQEmu::Item_Struct* item = 0; ItemInst *inst = 0; ServerLootItem_Struct* item_data = nullptr, *bag_item_data[10]; @@ -1206,7 +1206,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } /* Remove Bag Contents */ - if (item->ItemClass == ItemClassContainer && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) { + if (item->IsClassBag() && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) { for (int i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { if (bag_item_data[i]) { /* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */ @@ -1302,7 +1302,7 @@ void Corpse::QueryLoot(Client* to) { else x < corpselootlimit ? sitem->lootslot = x : sitem->lootslot = 0xFFFF; - const Item_Struct* item = database.GetItem(sitem->item_id); + const EQEmu::Item_Struct* item = database.GetItem(sitem->item_id); if (item) to->Message((sitem->lootslot == 0xFFFF), "LootSlot: %i (EquipSlot: %i) Item: %s (%d), Count: %i", static_cast(sitem->lootslot), sitem->equip_slot, item->Name, item->ID, sitem->charges); @@ -1316,7 +1316,7 @@ void Corpse::QueryLoot(Client* to) { } else { sitem->lootslot=y; - const Item_Struct* item = database.GetItem(sitem->item_id); + const EQEmu::Item_Struct* item = database.GetItem(sitem->item_id); if (item) to->Message(0, "LootSlot: %i Item: %s (%d), Count: %i", sitem->lootslot, item->Name, item->ID, sitem->charges); @@ -1411,7 +1411,7 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { } uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { - const Item_Struct *item; + const EQEmu::Item_Struct *item; if (material_slot > EQEmu::legacy::MATERIAL_END) { return 0; @@ -1450,7 +1450,7 @@ void Corpse::UpdateEquipmentLight() auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } - if (item->ItemClass != ItemClassCommon) { continue; } + if (!item->IsClassCommon()) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } if (EQEmu::lightsource::TypeToLevel(item->Light)) diff --git a/zone/doors.cpp b/zone/doors.cpp index 76bdbdb20..b70da219e 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -285,7 +285,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) { if(sender->GetSkill(SkillPickLock)) { - if(lockpicks->GetItem()->ItemType == ItemTypeLockPick) + if(lockpicks->GetItem()->ItemType == EQEmu::item::ItemTypeLockPick) { float modskill=sender->GetSkill(SkillPickLock); sender->CheckIncreaseSkill(SkillPickLock, nullptr, 1); diff --git a/zone/effects.cpp b/zone/effects.cpp index 52b148fc9..69b5c0819 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -481,14 +481,14 @@ int32 Client::GetActSpellCasttime(uint16 spell_id, int32 casttime) bool Client::TrainDiscipline(uint32 itemid) { //get the item info - const Item_Struct *item = database.GetItem(itemid); + const EQEmu::Item_Struct *item = database.GetItem(itemid); if(item == nullptr) { Message(13, "Unable to find the tome you turned in!"); Log.Out(Logs::General, Logs::Error, "Unable to find turned in tome id %lu\n", (unsigned long)itemid); return(false); } - if(item->ItemClass != ItemClassCommon || item->ItemType != ItemTypeSpell) { + if (!item->IsClassCommon() || item->ItemType != EQEmu::item::ItemTypeSpell) { Message(13, "Invalid item type, you cannot learn from this item."); //summon them the item back... SummonItem(itemid); diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 037649366..3607bbe05 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -882,7 +882,7 @@ void PerlembParser::GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlaye } else if(isItemQuest) { // need a valid ItemInst pointer check here..unsure how to cancel this process - const Item_Struct* item = iteminst->GetItem(); + const EQEmu::Item_Struct* item = iteminst->GetItem(); package_name = "qst_item_"; package_name += itoa(item->ID); } diff --git a/zone/embxs.cpp b/zone/embxs.cpp index 8a1bde544..a24f3f070 100644 --- a/zone/embxs.cpp +++ b/zone/embxs.cpp @@ -33,7 +33,7 @@ const char *getItemName(unsigned itemid) { - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; item = database.GetItem(itemid); if (item) diff --git a/zone/entity.cpp b/zone/entity.cpp index ccc546ad1..4d6ca1459 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1955,7 +1955,7 @@ void EntityList::QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struc memcpy(outgbius, gbius, sizeof(GuildBankItemUpdate_Struct)); - const Item_Struct *Item = database.GetItem(gbius->ItemID); + const EQEmu::Item_Struct *Item = database.GetItem(gbius->ItemID); auto it = client_list.begin(); while (it != client_list.end()) { @@ -3821,7 +3821,7 @@ void EntityList::GroupMessage(uint32 gid, const char *from, const char *message) uint16 EntityList::CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time) { - const Item_Struct *is = database.GetItem(itemid); + const EQEmu::Item_Struct *is = database.GetItem(itemid); if (!is) return 0; diff --git a/zone/forage.cpp b/zone/forage.cpp index 0a9f81e77..991947f8d 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -154,20 +154,20 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, bool Client::CanFish() { //make sure we still have a fishing pole on: const ItemInst* Pole = m_inv[EQEmu::legacy::SlotPrimary]; - int32 bslot = m_inv.HasItemByUse(ItemTypeFishingBait, 1, invWhereWorn|invWherePersonal); + int32 bslot = m_inv.HasItemByUse(EQEmu::item::ItemTypeFishingBait, 1, invWhereWorn | invWherePersonal); const ItemInst* Bait = nullptr; if (bslot != INVALID_INDEX) Bait = m_inv.GetItem(bslot); - if(!Pole || !Pole->IsType(ItemClassCommon) || Pole->GetItem()->ItemType != ItemTypeFishingPole) { - if (m_inv.HasItemByUse(ItemTypeFishingPole, 1, invWhereWorn|invWherePersonal|invWhereBank|invWhereSharedBank|invWhereTrading|invWhereCursor)) //We have a fishing pole somewhere, just not equipped + if (!Pole || !Pole->IsClassCommon() || Pole->GetItem()->ItemType != EQEmu::item::ItemTypeFishingPole) { + if (m_inv.HasItemByUse(EQEmu::item::ItemTypeFishingPole, 1, invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor)) //We have a fishing pole somewhere, just not equipped Message_StringID(MT_Skills, FISHING_EQUIP_POLE); //You need to put your fishing pole in your primary hand. else //We don't have a fishing pole anywhere Message_StringID(MT_Skills, FISHING_NO_POLE); //You can't fish without a fishing pole, go buy one. return false; } - if (!Bait || !Bait->IsType(ItemClassCommon) || Bait->GetItem()->ItemType != ItemTypeFishingBait) { + if (!Bait || !Bait->IsClassCommon() || Bait->GetItem()->ItemType != EQEmu::item::ItemTypeFishingBait) { Message_StringID(MT_Skills, FISHING_NO_BAIT); //You can't fish without fishing bait, go buy some. return false; } @@ -252,7 +252,7 @@ void Client::GoFish() int fishing_skill = GetSkill(SkillFishing); //will take into account skill bonuses on pole & bait //make sure we still have a fishing pole on: - int32 bslot = m_inv.HasItemByUse(ItemTypeFishingBait, 1, invWhereWorn|invWherePersonal); + int32 bslot = m_inv.HasItemByUse(EQEmu::item::ItemTypeFishingBait, 1, invWhereWorn | invWherePersonal); const ItemInst* Bait = nullptr; if (bslot != INVALID_INDEX) Bait = m_inv.GetItem(bslot); @@ -304,7 +304,7 @@ void Client::GoFish() food_id = common_fish_ids[index]; } - const Item_Struct* food_item = database.GetItem(food_id); + const EQEmu::Item_Struct* food_item = database.GetItem(food_id); Message_StringID(MT_Skills, FISHING_SUCCESS); ItemInst* inst = database.CreateItem(food_item, 1); @@ -396,7 +396,7 @@ void Client::ForageItem(bool guarantee) { foragedfood = common_food_ids[index]; } - const Item_Struct* food_item = database.GetItem(foragedfood); + const EQEmu::Item_Struct* food_item = database.GetItem(foragedfood); if(!food_item) { Log.Out(Logs::General, Logs::Error, "nullptr returned from database.GetItem in ClientForageItem"); @@ -407,20 +407,18 @@ void Client::ForageItem(bool guarantee) { stringid = FORAGE_GRUBS; else switch(food_item->ItemType) { - - case ItemTypeFood: - stringid = FORAGE_FOOD; - break; - - case ItemTypeDrink: - if(strstr(food_item->Name, "ater")) - stringid = FORAGE_WATER; - else - stringid = FORAGE_DRINK; - break; - default: - break; - } + case EQEmu::item::ItemTypeFood: + stringid = FORAGE_FOOD; + break; + case EQEmu::item::ItemTypeDrink: + if(strstr(food_item->Name, "ater")) + stringid = FORAGE_WATER; + else + stringid = FORAGE_DRINK; + break; + default: + break; + } Message_StringID(MT_Skills, stringid); ItemInst* inst = database.CreateItem(food_item, 1); diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index f7a7a2cc3..a801dc895 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -694,7 +694,7 @@ void GuildBankManager::SendGuildBank(Client *c) if (c->ClientVersionBit() & EQEmu::versions::bit_RoFAndLater) { auto outapp = new EQApplicationPacket(OP_GuildBankItemList, sizeof(GuildBankItemListEntry_Struct) * 240); for (int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i) { - const Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); + const EQEmu::Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); if (Item) { outapp->WriteUInt8(1); outapp->WriteUInt32(guild_bank->Items.DepositArea[i].Permissions); @@ -718,7 +718,7 @@ void GuildBankManager::SendGuildBank(Client *c) outapp->SetWritePosition(outapp->GetWritePosition() + 20); // newer clients have 40 deposit slots, keep them 0 for now for (int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i) { - const Item_Struct *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); + const EQEmu::Item_Struct *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); if (Item) { outapp->WriteUInt8(1); outapp->WriteUInt32(guild_bank->Items.MainArea[i].Permissions); @@ -749,7 +749,7 @@ void GuildBankManager::SendGuildBank(Client *c) { if(guild_bank->Items.DepositArea[i].ItemID > 0) { - const Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); + const EQEmu::Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); if(!Item) continue; @@ -785,7 +785,7 @@ void GuildBankManager::SendGuildBank(Client *c) { if(guild_bank->Items.MainArea[i].ItemID > 0) { - const Item_Struct *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); + const EQEmu::Item_Struct *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); if(!Item) continue; @@ -916,7 +916,7 @@ bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32 return false; } - const Item_Struct *Item = database.GetItem(ItemID); + const EQEmu::Item_Struct *Item = database.GetItem(ItemID); GuildBankItemUpdate_Struct gbius; @@ -982,7 +982,7 @@ int GuildBankManager::Promote(uint32 guildID, int slotID) (*iter)->Items.DepositArea[slotID].ItemID = 0; - const Item_Struct *Item = database.GetItem((*iter)->Items.MainArea[mainSlot].ItemID); + const EQEmu::Item_Struct *Item = database.GetItem((*iter)->Items.MainArea[mainSlot].ItemID); GuildBankItemUpdate_Struct gbius; @@ -1038,7 +1038,7 @@ void GuildBankManager::SetPermissions(uint32 guildID, uint16 slotID, uint32 perm else (*iter)->Items.MainArea[slotID].WhoFor[0] = '\0'; - const Item_Struct *Item = database.GetItem((*iter)->Items.MainArea[slotID].ItemID); + const EQEmu::Item_Struct *Item = database.GetItem((*iter)->Items.MainArea[slotID].ItemID); GuildBankItemUpdate_Struct gbius; @@ -1169,7 +1169,7 @@ bool GuildBankManager::DeleteItem(uint32 guildID, uint16 area, uint16 slotID, ui bool deleted = true; - const Item_Struct *Item = database.GetItem(BankArea[slotID].ItemID); + const EQEmu::Item_Struct *Item = database.GetItem(BankArea[slotID].ItemID); if(!Item->Stackable || (quantity >= BankArea[slotID].Quantity)) { std::string query = StringFormat("DELETE FROM `guild_bank` WHERE `guildid` = %i " @@ -1230,7 +1230,7 @@ bool GuildBankManager::MergeStacks(uint32 GuildID, uint16 SlotID) if(BankArea[SlotID].ItemID == 0) return false; - const Item_Struct *Item = database.GetItem(BankArea[SlotID].ItemID); + const EQEmu::Item_Struct *Item = database.GetItem(BankArea[SlotID].ItemID); if(!Item->Stackable) return false; @@ -1328,7 +1328,7 @@ bool GuildBankManager::SplitStack(uint32 GuildID, uint16 SlotID, uint32 Quantity if(BankArea[SlotID].Quantity <= Quantity || Quantity == 0) return false; - const Item_Struct *Item = database.GetItem(BankArea[SlotID].ItemID); + const EQEmu::Item_Struct *Item = database.GetItem(BankArea[SlotID].ItemID); if(!Item->Stackable) return false; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 9d7c72f14..0ca5cc96e 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -177,7 +177,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } -bool Client::CheckLoreConflict(const Item_Struct* item) +bool Client::CheckLoreConflict(const EQEmu::Item_Struct* item) { if (!item) { return false; } if (!item->LoreFlag) { return false; } @@ -195,7 +195,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // TODO: update calling methods and script apis to handle a failure return - const Item_Struct* item = database.GetItem(item_id); + const EQEmu::Item_Struct* item = database.GetItem(item_id); // make sure the item exists if(item == nullptr) { @@ -213,7 +213,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, return false; } // check to make sure we are augmenting an augmentable item - else if (((item->ItemClass != ItemClassCommon) || (item->AugType > 0)) && (aug1 | aug2 | aug3 | aug4 | aug5 | aug6)) { + else if (((!item->IsClassCommon()) || (item->AugType > 0)) && (aug1 | aug2 | aug3 | aug4 | aug5 | aug6)) { Message(13, "You can not augment an augment or a non-common class item."); Log.Out(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to augment an augment or a non-common class item.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug5: %u)\n", GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); @@ -247,7 +247,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, bool enforceusable = RuleB(Inventory, EnforceAugmentUsability); for (int iter = AUG_INDEX_BEGIN; iter < EQEmu::legacy::ITEM_COMMON_SIZE; ++iter) { - const Item_Struct* augtest = database.GetItem(augments[iter]); + const EQEmu::Item_Struct* augtest = database.GetItem(augments[iter]); if(augtest == nullptr) { if(augments[iter]) { @@ -290,7 +290,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // check for augment type allowance if(enforcewear) { - if((item->AugSlotType[iter] == AugTypeNone) || !(((uint32)1 << (item->AugSlotType[iter] - 1)) & augtest->AugType)) { + if ((item->AugSlotType[iter] == EQEmu::item::AugTypeNone) || !(((uint32)1 << (item->AugSlotType[iter] - 1)) & augtest->AugType)) { Message(13, "Augment %u (Aug%i) is not acceptable wear on Item %u.", augments[iter], iter + 1, item->ID); Log.Out(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to augment an item with an unacceptable augment type (Aug%i).\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6); @@ -313,153 +313,153 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint8 it = item->ItemType; switch(augtest->AugRestrict) { - case AugRestrAny: + case EQEmu::item::AugRestrictionAny: break; - case AugRestrArmor: + case EQEmu::item::AugRestrictionArmor: switch(it) { - case ItemTypeArmor: + case EQEmu::item::ItemTypeArmor: break; default: restrictfail = true; break; } break; - case AugRestrWeapons: + case EQEmu::item::AugRestrictionWeapons: switch(it) { - case ItemType1HSlash: - case ItemType1HBlunt: - case ItemType1HPiercing: - case ItemTypeMartial: - case ItemType2HSlash: - case ItemType2HBlunt: - case ItemType2HPiercing: - case ItemTypeBow: + case EQEmu::item::ItemType1HSlash: + case EQEmu::item::ItemType1HBlunt: + case EQEmu::item::ItemType1HPiercing: + case EQEmu::item::ItemTypeMartial: + case EQEmu::item::ItemType2HSlash: + case EQEmu::item::ItemType2HBlunt: + case EQEmu::item::ItemType2HPiercing: + case EQEmu::item::ItemTypeBow: break; default: restrictfail = true; break; } break; - case AugRestr1HWeapons: + case EQEmu::item::AugRestriction1HWeapons: switch(it) { - case ItemType1HSlash: - case ItemType1HBlunt: - case ItemType1HPiercing: - case ItemTypeMartial: + case EQEmu::item::ItemType1HSlash: + case EQEmu::item::ItemType1HBlunt: + case EQEmu::item::ItemType1HPiercing: + case EQEmu::item::ItemTypeMartial: break; default: restrictfail = true; break; } break; - case AugRestr2HWeapons: + case EQEmu::item::AugRestriction2HWeapons: switch(it) { - case ItemType2HSlash: - case ItemType2HBlunt: - case ItemType2HPiercing: - case ItemTypeBow: + case EQEmu::item::ItemType2HSlash: + case EQEmu::item::ItemType2HBlunt: + case EQEmu::item::ItemType2HPiercing: + case EQEmu::item::ItemTypeBow: break; default: restrictfail = true; break; } break; - case AugRestr1HSlash: + case EQEmu::item::AugRestriction1HSlash: switch(it) { - case ItemType1HSlash: + case EQEmu::item::ItemType1HSlash: break; default: restrictfail = true; break; } break; - case AugRestr1HBlunt: + case EQEmu::item::AugRestriction1HBlunt: switch(it) { - case ItemType1HBlunt: + case EQEmu::item::ItemType1HBlunt: break; default: restrictfail = true; break; } break; - case AugRestrPiercing: + case EQEmu::item::AugRestrictionPiercing: switch(it) { - case ItemType1HPiercing: + case EQEmu::item::ItemType1HPiercing: break; default: restrictfail = true; break; } break; - case AugRestrHandToHand: + case EQEmu::item::AugRestrictionHandToHand: switch(it) { - case ItemTypeMartial: + case EQEmu::item::ItemTypeMartial: break; default: restrictfail = true; break; } break; - case AugRestr2HSlash: + case EQEmu::item::AugRestriction2HSlash: switch(it) { - case ItemType2HSlash: + case EQEmu::item::ItemType2HSlash: break; default: restrictfail = true; break; } break; - case AugRestr2HBlunt: + case EQEmu::item::AugRestriction2HBlunt: switch(it) { - case ItemType2HBlunt: + case EQEmu::item::ItemType2HBlunt: break; default: restrictfail = true; break; } break; - case AugRestr2HPierce: + case EQEmu::item::AugRestriction2HPierce: switch(it) { - case ItemType2HPiercing: + case EQEmu::item::ItemType2HPiercing: break; default: restrictfail = true; break; } break; - case AugRestrBows: + case EQEmu::item::AugRestrictionBows: switch(it) { - case ItemTypeBow: + case EQEmu::item::ItemTypeBow: break; default: restrictfail = true; break; } break; - case AugRestrShields: + case EQEmu::item::AugRestrictionShields: switch(it) { - case ItemTypeShield: + case EQEmu::item::ItemTypeShield: break; default: restrictfail = true; break; } break; - case AugRestr1HSlash1HBluntOrHandToHand: + case EQEmu::item::AugRestriction1HSlash1HBluntOrHandToHand: switch(it) { - case ItemType1HSlash: - case ItemType1HBlunt: - case ItemTypeMartial: + case EQEmu::item::ItemType1HSlash: + case EQEmu::item::ItemType1HBlunt: + case EQEmu::item::ItemTypeMartial: break; default: restrictfail = true; break; } break; - case AugRestr1HBluntOrHandToHand: + case EQEmu::item::AugRestriction1HBluntOrHandToHand: switch(it) { - case ItemType1HBlunt: - case ItemTypeMartial: + case EQEmu::item::ItemType1HBlunt: + case EQEmu::item::ItemTypeMartial: break; default: restrictfail = true; @@ -467,9 +467,9 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, } break; // These 3 are in-work - case AugRestrUnknown1: - case AugRestrUnknown2: - case AugRestrUnknown3: + case EQEmu::item::AugRestrictionUnknown1: + case EQEmu::item::AugRestrictionUnknown2: + case EQEmu::item::AugRestrictionUnknown3: default: restrictfail = true; break; @@ -760,7 +760,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd qsaudit->items[parent_offset].aug_4 = m_inv[slot_id]->GetAugmentItemID(4); qsaudit->items[parent_offset].aug_5 = m_inv[slot_id]->GetAugmentItemID(5); - if(m_inv[slot_id]->IsType(ItemClassContainer)) { + if (m_inv[slot_id]->IsClassBag()) { for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) { ItemInst* bagitem = m_inv[slot_id]->GetItem(bag_idx); @@ -986,7 +986,7 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_cursor, ServerLootItem_Struct** bag_item_data) { // #1: Try to auto equip - if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel<=level && (!inst.GetItem()->Attuneable || inst.IsAttuned()) && inst.GetItem()->ItemType != ItemTypeAugmentation) { + if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel <= level && (!inst.GetItem()->Attuneable || inst.IsAttuned()) && inst.GetItem()->ItemType != EQEmu::item::ItemTypeAugmentation) { // too messy as-is... for (int16 i = EQEmu::legacy::EQUIPMENT_BEGIN; i < EQEmu::legacy::SlotPowerSource; i++) { // originally (i < 22) if (i == EQEmu::legacy::GENERAL_BEGIN) { @@ -999,15 +999,14 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs if (!m_inv[i]) { if (i == EQEmu::legacy::SlotPrimary && inst.IsWeapon()) { // If item is primary slot weapon - if ((inst.GetItem()->ItemType == ItemType2HSlash) || (inst.GetItem()->ItemType == ItemType2HBlunt) || (inst.GetItem()->ItemType == ItemType2HPiercing)) { // and uses 2hs \ 2hb \ 2hp + if (inst.GetItem()->IsType2HWeapon()) { // and uses 2hs \ 2hb \ 2hp if (m_inv[EQEmu::legacy::SlotSecondary]) { // and if secondary slot is not empty continue; // Can't auto-equip } } } if (i == EQEmu::legacy::SlotSecondary && m_inv[EQEmu::legacy::SlotPrimary]) { // check to see if primary slot is a two hander - uint8 use = m_inv[EQEmu::legacy::SlotPrimary]->GetItem()->ItemType; - if (use == ItemType2HSlash || use == ItemType2HBlunt || use == ItemType2HPiercing) + if (m_inv[EQEmu::legacy::SlotPrimary]->GetItem()->IsType2HWeapon()) continue; } if (i == EQEmu::legacy::SlotSecondary && inst.IsWeapon() && !CanThisClassDualWield()) { @@ -1036,8 +1035,8 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs } // #3: put it in inventory - bool is_arrow = (inst.GetItem()->ItemType == ItemTypeArrow) ? true : false; - int16 slot_id = m_inv.FindFreeSlot(inst.IsType(ItemClassContainer), try_cursor, inst.GetItem()->Size, is_arrow); + bool is_arrow = (inst.GetItem()->ItemType == EQEmu::item::ItemTypeArrow) ? true : false; + int16 slot_id = m_inv.FindFreeSlot(inst.IsClassBag(), try_cursor, inst.GetItem()->Size, is_arrow); if (slot_id != INVALID_INDEX) { PutLootInInventory(slot_id, inst, bag_item_data); return true; @@ -1188,7 +1187,7 @@ int Client::GetItemLinkHash(const ItemInst* inst) { if (!inst) //have to have an item to make the hash return 0; - const Item_Struct* item = inst->GetItem(); + const EQEmu::Item_Struct* item = inst->GetItem(); char* hash_str = 0; /*register */int hash = 0; @@ -1282,7 +1281,7 @@ packet with the item number in it, but I cant seem to find it right now if (!inst) return; - const Item_Struct* item = inst->GetItem(); + const EQEmu::Item_Struct* item = inst->GetItem(); const char* name2 = &item->Name[0]; EQApplicationPacket* outapp = new EQApplicationPacket(OP_ItemLinkText,strlen(name2)+68); char buffer2[135] = {0}; @@ -1514,7 +1513,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { DeleteItemInInventory(dst_slot_id,0,true); return(false); } - if (src_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::legacy::SHARED_BANK_END && src_inst->IsType(ItemClassContainer)){ + if (src_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::legacy::SHARED_BANK_END && src_inst->IsClassBag()){ for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = src_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(src_slot_id, idx), baginst)){ @@ -1529,7 +1528,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { DeleteItemInInventory(src_slot_id,0,true); return(false); } - if (dst_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::legacy::SHARED_BANK_END && dst_inst->IsType(ItemClassContainer)){ + if (dst_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::legacy::SHARED_BANK_END && dst_inst->IsClassBag()){ for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { const ItemInst* baginst = dst_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(dst_slot_id, idx), baginst)){ @@ -1596,8 +1595,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { m_inv.DeleteItem(src_slot_id); } else { - const Item_Struct* world_item = world_inst->GetItem(); - const Item_Struct* src_item = src_inst->GetItem(); + const EQEmu::Item_Struct* world_item = world_inst->GetItem(); + const EQEmu::Item_Struct* src_item = src_inst->GetItem(); if (world_item && src_item) { // Case 2: Same item on cursor, stacks, transfer of charges needed if ((world_item->ID == src_item->ID) && src_inst->IsStackable()) { @@ -1837,7 +1836,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { // This prevents the client from crashing when closing any 'phantom' bags - const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' + const EQEmu::Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' ItemInst* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); @@ -1862,7 +1861,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { if(m_inv[resync_slot]) { - const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' + const EQEmu::Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' ItemInst* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); @@ -1879,7 +1878,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { if ((move_slots->to_slot >= EQEmu::legacy::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::legacy::CURSOR_BAG_END) || move_slots->to_slot == EQEmu::legacy::SlotPowerSource) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { - const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' + const EQEmu::Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' ItemInst* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); @@ -1904,7 +1903,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { if(m_inv[resync_slot]) { - const Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' + const EQEmu::Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' ItemInst* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); @@ -1956,7 +1955,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { qsaudit->items[move_count].aug_4 = from_inst->GetAugmentItemID(4); qsaudit->items[move_count++].aug_5 = from_inst->GetAugmentItemID(5); - if(from_inst->IsType(ItemClassContainer)) { + if (from_inst->IsType(EQEmu::item::ItemClassBag)) { for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < from_inst->GetItem()->BagSlots; bag_idx++) { const ItemInst* from_baginst = from_inst->GetItem(bag_idx); @@ -1989,7 +1988,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { qsaudit->items[move_count].aug_4 = to_inst->GetAugmentItemID(4); qsaudit->items[move_count++].aug_5 = to_inst->GetAugmentItemID(5); - if(to_inst->IsType(ItemClassContainer)) { + if (to_inst->IsType(EQEmu::item::ItemClassBag)) { for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < to_inst->GetItem()->BagSlots; bag_idx++) { const ItemInst* to_baginst = to_inst->GetItem(bag_idx); @@ -2107,7 +2106,7 @@ bool Client::DecreaseByItemType(uint32 type, uint8 amt) { #endif bool Client::DecreaseByID(uint32 type, uint8 amt) { - const Item_Struct* TempItem = nullptr; + const EQEmu::Item_Struct* TempItem = nullptr; ItemInst* ins = nullptr; int x; int num = 0; @@ -2231,7 +2230,7 @@ void Client::DisenchantSummonedBags(bool client_update) auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } - if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } + if (!inst->GetItem()->IsClassBag()) { continue; } if (inst->GetTotalItemCount() == 1) { continue; } auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); @@ -2252,7 +2251,7 @@ void Client::DisenchantSummonedBags(bool client_update) auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } - if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } + if (!inst->GetItem()->IsClassBag()) { continue; } if (inst->GetTotalItemCount() == 1) { continue; } auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); @@ -2273,7 +2272,7 @@ void Client::DisenchantSummonedBags(bool client_update) auto inst = m_inv[slot_id]; if (!inst) { continue; } if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; } - if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; } + if (!inst->GetItem()->IsClassBag()) { continue; } if (inst->GetTotalItemCount() == 1) { continue; } auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); @@ -2294,7 +2293,7 @@ void Client::DisenchantSummonedBags(bool client_update) auto inst = m_inv[EQEmu::legacy::SlotCursor]; if (!inst) { break; } if (!IsSummonedBagID(inst->GetItem()->ID)) { break; } - if (inst->GetItem()->ItemClass != ItemClassContainer) { break; } + if (!inst->GetItem()->IsClassBag()) { break; } if (inst->GetTotalItemCount() == 1) { break; } auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots); @@ -2562,8 +2561,8 @@ void Client::MoveSlotNotAllowed(bool client_update) for (auto slot_id = EQEmu::legacy::EQUIPMENT_BEGIN; slot_id <= EQEmu::legacy::EQUIPMENT_END; ++slot_id) { if(m_inv[slot_id] && !m_inv[slot_id]->IsSlotAllowed(slot_id)) { auto inst = m_inv.PopItem(slot_id); - bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; - int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size, is_arrow); + bool is_arrow = (inst->GetItem()->ItemType == EQEmu::item::ItemTypeArrow) ? true : false; + int16 free_slot_id = m_inv.FindFreeSlot(inst->IsClassBag(), true, inst->GetItem()->Size, is_arrow); Log.Out(Logs::Detail, Logs::Inventory, "Slot Assignment Error: Moving %s from slot %i to %i", inst->GetItem()->Name, slot_id, free_slot_id); PutItemInInventory(free_slot_id, *inst, client_update); database.SaveInventory(character_id, nullptr, slot_id); @@ -2573,8 +2572,8 @@ void Client::MoveSlotNotAllowed(bool client_update) if (m_inv[EQEmu::legacy::SlotPowerSource] && !m_inv[EQEmu::legacy::SlotPowerSource]->IsSlotAllowed(EQEmu::legacy::SlotPowerSource)) { auto inst = m_inv.PopItem(EQEmu::legacy::SlotPowerSource); - bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; - int16 free_slot_id = m_inv.FindFreeSlot(inst->IsType(ItemClassContainer), true, inst->GetItem()->Size, is_arrow); + bool is_arrow = (inst->GetItem()->ItemType == EQEmu::item::ItemTypeArrow) ? true : false; + int16 free_slot_id = m_inv.FindFreeSlot(inst->IsClassBag(), true, inst->GetItem()->Size, is_arrow); Log.Out(Logs::Detail, Logs::Inventory, "Slot Assignment Error: Moving %s from slot %i to %i", inst->GetItem()->Name, EQEmu::legacy::SlotPowerSource, free_slot_id); PutItemInInventory(free_slot_id, *inst, (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) ? client_update : false); database.SaveInventory(character_id, nullptr, EQEmu::legacy::SlotPowerSource); @@ -2632,7 +2631,7 @@ uint32 Client::GetEquipmentColor(uint8 material_slot) const if (material_slot > EQEmu::legacy::MATERIAL_END) return 0; - const Item_Struct *item = database.GetItem(GetEquipment(material_slot)); + const EQEmu::Item_Struct *item = database.GetItem(GetEquipment(material_slot)); if(item != nullptr) return ((m_pp.item_tint[material_slot].RGB.UseTint) ? m_pp.item_tint[material_slot].Color : item->Color); @@ -2716,7 +2715,7 @@ void Client::CreateBandolier(const EQApplicationPacket *app) strcpy(m_pp.bandoliers[bs->Number].Name, bs->Name); const ItemInst* InvItem = nullptr; - const Item_Struct *BaseItem = nullptr; + const EQEmu::Item_Struct *BaseItem = nullptr; int16 WeaponSlot = 0; for(int BandolierSlot = bandolierPrimary; BandolierSlot <= bandolierAmmo; BandolierSlot++) { @@ -2950,7 +2949,7 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { } // If there is a bag in this slot, look inside it. // - if (InvItem && InvItem->IsType(ItemClassContainer)) { + if (InvItem && InvItem->IsClassBag()) { int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); @@ -3002,7 +3001,7 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { return true; } - if(InvItem->IsType(ItemClassContainer) && Inventory::CanItemFitInContainer(ItemToReturn->GetItem(), InvItem->GetItem())) { + if (InvItem->IsClassBag() && Inventory::CanItemFitInContainer(ItemToReturn->GetItem(), InvItem->GetItem())) { int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); @@ -3208,7 +3207,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* case 1: // requirement: parent is common and inst is augment if ((!parent) || (!inst)) return true; - if (!parent->IsType(ItemClassCommon)) + if (!parent->IsType(EQEmu::item::ItemClassCommon)) return true; if (index >= EQEmu::legacy::ITEM_COMMON_SIZE) return true; @@ -3232,11 +3231,11 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* case 1: // requirement: parent is common and inst is augment ..or.. parent is container and inst is extant if ((!parent) || (!inst)) return true; - if (parent->IsType(ItemClassContainer)) + if (parent->IsType(EQEmu::item::ItemClassBag)) break; - if (parent->IsType(ItemClassBook)) + if (parent->IsClassBook()) return true; - if (parent->IsType(ItemClassCommon)) { + if (parent->IsClassCommon()) { if (!(inst->GetItem()->AugType > 0)) return true; if (index >= EQEmu::legacy::ITEM_COMMON_SIZE) @@ -3246,11 +3245,11 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* case 2: // requirement: parent is common and inst is augment if ((!parent) || (!inst)) return true; - if (parent->IsType(ItemClassContainer)) + if (parent->IsType(EQEmu::item::ItemClassBag)) return true; - if (parent->IsType(ItemClassBook)) + if (parent->IsClassBook()) return true; - if (parent->IsType(ItemClassCommon)) { + if (parent->IsClassCommon()) { if (!(inst->GetItem()->AugType > 0)) return true; if (index >= EQEmu::legacy::ITEM_COMMON_SIZE) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 86969ccca..1aab9eb51 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -119,7 +119,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml int charges = lds->Entries[i].multiplier; for(int j = 0; j < charges; ++j) { if(zone->random.Real(0.0, 100.0) <= lds->Entries[i].chance) { - const Item_Struct* dbitem = GetItem(lds->Entries[i].item_id); + const EQEmu::Item_Struct* dbitem = GetItem(lds->Entries[i].item_id); npc->AddLootDrop(dbitem, itemlist, lds->Entries[i].item_charges, lds->Entries[i].minlevel, lds->Entries[i].maxlevel, lds->Entries[i].equip_item > 0 ? true : false, false); } @@ -140,7 +140,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml float roll_t_min = 0.0f; bool active_item_list = false; for(uint32 i = 0; i < lds->NumEntries; ++i) { - const Item_Struct* db_item = GetItem(lds->Entries[i].item_id); + const EQEmu::Item_Struct* db_item = GetItem(lds->Entries[i].item_id); if(db_item) { roll_t += lds->Entries[i].chance; active_item_list = true; @@ -157,7 +157,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml for(int i = 0; i < mindrop; ++i) { float roll = (float)zone->random.Real(0.0, roll_t_min); for(uint32 j = 0; j < lds->NumEntries; ++j) { - const Item_Struct* db_item = GetItem(lds->Entries[j].item_id); + const EQEmu::Item_Struct* db_item = GetItem(lds->Entries[j].item_id); if(db_item) { if(roll < lds->Entries[j].chance) { npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, @@ -187,7 +187,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml for(int i = mindrop; i < droplimit; ++i) { float roll = (float)zone->random.Real(0.0, roll_t); for(uint32 j = 0; j < lds->NumEntries; ++j) { - const Item_Struct* db_item = GetItem(lds->Entries[j].item_id); + const EQEmu::Item_Struct* db_item = GetItem(lds->Entries[j].item_id); if(db_item) { if(roll < lds->Entries[j].chance) { npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, @@ -221,7 +221,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml } //if itemlist is null, just send wear changes -void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange) { +void NPC::AddLootDrop(const EQEmu::Item_Struct *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange) { if(item2 == nullptr) return; @@ -258,7 +258,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge if (equipit) { uint8 eslot = 0xFF; char newid[20]; - const Item_Struct* compitem = nullptr; + const EQEmu::Item_Struct* compitem = nullptr; bool found = false; // track if we found an empty slot we fit into int32 foundslot = -1; // for multi-slot items @@ -334,13 +334,12 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge eslot = EQEmu::legacy::MaterialPrimary; if (item2->Damage > 0) SendAddPlayerState(PlayerState::PrimaryWeaponEquipped); - if (item2->ItemType == ItemType2HBlunt || item2->ItemType == ItemType2HSlash || item2->ItemType == ItemType2HPiercing) + if (item2->IsType2HWeapon()) SetTwoHanderEquipped(true); } else if (foundslot == EQEmu::legacy::SlotSecondary && (GetOwner() != nullptr || (CanThisClassDualWield() && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) && - (item2->ItemType == ItemType1HSlash || item2->ItemType == ItemType1HBlunt || item2->ItemType == ItemTypeShield || - item2->ItemType == ItemType1HPiercing)) + (item2->IsType1HWeapon() || item2->ItemType == EQEmu::item::ItemTypeShield)) { if (item2->Proc.Effect!=0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); @@ -416,14 +415,14 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge SendAppearancePacket(AT_Light, GetActiveLightType()); } -void NPC::AddItem(const Item_Struct* item, uint16 charges, bool equipitem) { +void NPC::AddItem(const EQEmu::Item_Struct* item, uint16 charges, bool equipitem) { //slot isnt needed, its determined from the item. AddLootDrop(item, &itemlist, charges, 1, 127, equipitem, equipitem); } void NPC::AddItem(uint32 itemid, uint16 charges, bool equipitem) { //slot isnt needed, its determined from the item. - const Item_Struct * i = database.GetItem(itemid); + const EQEmu::Item_Struct * i = database.GetItem(itemid); if(i == nullptr) return; AddLootDrop(i, &itemlist, charges, 1, 127, equipitem, equipitem); diff --git a/zone/lua_item.cpp b/zone/lua_item.cpp index 16254c52e..429e140dc 100644 --- a/zone/lua_item.cpp +++ b/zone/lua_item.cpp @@ -7,7 +7,7 @@ #include "lua_item.h" Lua_Item::Lua_Item(uint32 item_id) { - const Item_Struct *t = database.GetItem(item_id); + const EQEmu::Item_Struct *t = database.GetItem(item_id); SetLuaPtrData(t); } diff --git a/zone/lua_item.h b/zone/lua_item.h index 961da1333..5e3e021c9 100644 --- a/zone/lua_item.h +++ b/zone/lua_item.h @@ -4,7 +4,10 @@ #include "lua_ptr.h" -struct Item_Struct; +namespace EQEmu +{ + struct Item_Struct; +} namespace luabind { struct scope; @@ -12,17 +15,17 @@ namespace luabind { luabind::scope lua_register_item(); -class Lua_Item : public Lua_Ptr +class Lua_Item : public Lua_Ptr { - typedef const Item_Struct NativeType; + typedef const EQEmu::Item_Struct NativeType; public: Lua_Item(uint32 item_id); Lua_Item() : Lua_Ptr(nullptr) { } - Lua_Item(const Item_Struct *d) : Lua_Ptr(d) { } + Lua_Item(const EQEmu::Item_Struct *d) : Lua_Ptr(d) { } virtual ~Lua_Item() { } - operator const Item_Struct*() { - return reinterpret_cast(GetLuaPtrData()); + operator const EQEmu::Item_Struct*() { + return reinterpret_cast(GetLuaPtrData()); } int GetMinStatus(); diff --git a/zone/lua_iteminst.cpp b/zone/lua_iteminst.cpp index 4ebc6908f..0b6981358 100644 --- a/zone/lua_iteminst.cpp +++ b/zone/lua_iteminst.cpp @@ -41,7 +41,7 @@ Lua_ItemInst::Lua_ItemInst(const Lua_ItemInst& o) { bool Lua_ItemInst::IsType(int item_class) { Lua_Safe_Call_Bool(); - return self->IsType(static_cast(item_class)); + return self->IsType(static_cast(item_class)); } bool Lua_ItemInst::IsStackable() { diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index 840bcb40d..88a117277 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -298,7 +298,7 @@ void handle_player_timer(QuestInterface *parse, lua_State* L, Client* client, st void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { - const Item_Struct *item = database.GetItem(extra_data); + const EQEmu::Item_Struct *item = database.GetItem(extra_data); if(item) { Lua_Item l_item(item); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); diff --git a/zone/merc.cpp b/zone/merc.cpp index 1305dc8bc..840c8ac38 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -217,7 +217,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { for (i = 0; i < EQEmu::legacy::SlotAmmo; i++) { if(equipment[i] == 0) continue; - const Item_Struct * itm = database.GetItem(equipment[i]); + const EQEmu::Item_Struct * itm = database.GetItem(equipment[i]); if(itm) AddItemBonuses(itm, newbon); } @@ -243,7 +243,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { SetAttackTimer(); } -void Merc::AddItemBonuses(const Item_Struct *item, StatBonuses* newbon) { +void Merc::AddItemBonuses(const EQEmu::Item_Struct *item, StatBonuses* newbon) { if(GetLevel() < item->ReqLevel) { @@ -456,11 +456,11 @@ void Merc::AddItemBonuses(const Item_Struct *item, StatBonuses* newbon) { else newbon->DSMitigation += item->DSMitigation; } - if (item->Worn.Effect>0 && (item->Worn.Type == ET_WornEffect)) { // latent effects + if (item->Worn.Effect>0 && (item->Worn.Type == EQEmu::item::ItemEffectWorn)) { // latent effects ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type); } - if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects + if (item->Focus.Effect>0 && (item->Focus.Type == EQEmu::item::ItemEffectFocus)) { // focus effects ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0); } @@ -1621,7 +1621,8 @@ void Merc::AI_Process() { int weapontype = 0; // No weapon type bool bIsFist = true; - if(bIsFist || ((weapontype != ItemType2HSlash) && (weapontype != ItemType2HPiercing) && (weapontype != ItemType2HBlunt))) + // why are we checking 'weapontype' when we know it's set to '0' above? + if (bIsFist || ((weapontype != EQEmu::item::ItemType2HSlash) && (weapontype != EQEmu::item::ItemType2HPiercing) && (weapontype != EQEmu::item::ItemType2HBlunt))) { float DualWieldProbability = 0.0f; @@ -2544,8 +2545,8 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) { //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[type]){ - const Item_Struct* TempItem = 0; - const Item_Struct* UsedItem = 0; + const EQEmu::Item_Struct* TempItem = 0; + const EQEmu::Item_Struct* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -4407,7 +4408,7 @@ void Merc::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ dmg = -5; } else{ @@ -4429,7 +4430,7 @@ void Merc::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ dmg = -5; } else{ @@ -5061,7 +5062,7 @@ void Merc::UpdateEquipmentLight() auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } - if (item->ItemClass != ItemClassCommon) { continue; } + if (!item->IsClassCommon()) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } if (EQEmu::lightsource::TypeToLevel(item->Light)) diff --git a/zone/merc.h b/zone/merc.h index b981e28b5..e9f993063 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -8,11 +8,15 @@ class Corpse; class Group; class Mob; class Raid; -struct Item_Struct; struct MercTemplate; struct NPCType; struct NewSpawn_Struct; +namespace EQEmu +{ + struct Item_Struct; +} + #define MAXMERCS 1 #define TANK 1 #define HEALER 2 @@ -279,7 +283,7 @@ public: protected: void CalcItemBonuses(StatBonuses* newbon); - void AddItemBonuses(const Item_Struct *item, StatBonuses* newbon); + void AddItemBonuses(const EQEmu::Item_Struct *item, StatBonuses* newbon); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); int16 GetFocusEffect(focusType type, uint16 spell_id); diff --git a/zone/mob.cpp b/zone/mob.cpp index a0a00d20d..5b1e132a9 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2382,9 +2382,9 @@ bool Mob::CanThisClassDualWield(void) const { // 2HS, 2HB, or 2HP if(pinst && pinst->IsWeapon()) { - const Item_Struct* item = pinst->GetItem(); + const EQEmu::Item_Struct* item = pinst->GetItem(); - if((item->ItemType == ItemType2HBlunt) || (item->ItemType == ItemType2HSlash) || (item->ItemType == ItemType2HPiercing)) + if (item->IsType2HWeapon()) return false; } @@ -2754,7 +2754,7 @@ void Mob::SendArmorAppearance(Client *one_client) { if (!IsClient()) { - const Item_Struct *item; + const EQEmu::Item_Struct *item; for (int i = 0; i < 7; ++i) { item = database.GetItem(GetEquipment(i)); @@ -2857,7 +2857,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const { uint32 equipmaterial = 0; int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - const Item_Struct *item; + const EQEmu::Item_Struct *item; item = database.GetItem(GetEquipment(material_slot)); if (item != 0) @@ -2910,7 +2910,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const if (material_slot >= 0 && material_slot < EQEmu::legacy::MaterialPrimary) { uint32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - const Item_Struct *item; + const EQEmu::Item_Struct *item; item = database.GetItem(GetEquipment(material_slot)); int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); @@ -2964,7 +2964,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const uint32 Mob::GetEquipmentColor(uint8 material_slot) const { - const Item_Struct *item; + const EQEmu::Item_Struct *item; if (armor_tint[material_slot]) { @@ -2980,7 +2980,7 @@ uint32 Mob::GetEquipmentColor(uint8 material_slot) const uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const { - const Item_Struct *item; + const EQEmu::Item_Struct *item; item = database.GetItem(GetEquipment(material_slot)); if(item != 0) @@ -3896,7 +3896,7 @@ int32 Mob::GetItemStat(uint32 itemid, const char *identifier) if (!inst) return 0; - const Item_Struct* item = inst->GetItem(); + const EQEmu::Item_Struct* item = inst->GetItem(); if (!item) return 0; @@ -5019,62 +5019,58 @@ void Mob::SlowMitigation(Mob* caster) uint16 Mob::GetSkillByItemType(int ItemType) { - switch (ItemType) - { - case ItemType1HSlash: - return Skill1HSlashing; - case ItemType2HSlash: - return Skill2HSlashing; - case ItemType1HPiercing: + switch (ItemType) { + case EQEmu::item::ItemType1HSlash: + return Skill1HSlashing; + case EQEmu::item::ItemType2HSlash: + return Skill2HSlashing; + case EQEmu::item::ItemType1HPiercing: + return Skill1HPiercing; + case EQEmu::item::ItemType1HBlunt: + return Skill1HBlunt; + case EQEmu::item::ItemType2HBlunt: + return Skill2HBlunt; + case EQEmu::item::ItemType2HPiercing: + if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) return Skill1HPiercing; - case ItemType1HBlunt: - return Skill1HBlunt; - case ItemType2HBlunt: - return Skill2HBlunt; - case ItemType2HPiercing: - if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) - return Skill1HPiercing; - else - return Skill2HPiercing; - case ItemTypeBow: - return SkillArchery; - case ItemTypeLargeThrowing: - case ItemTypeSmallThrowing: - return SkillThrowing; - case ItemTypeMartial: - return SkillHandtoHand; - default: - return SkillHandtoHand; + else + return Skill2HPiercing; + case EQEmu::item::ItemTypeBow: + return SkillArchery; + case EQEmu::item::ItemTypeLargeThrowing: + case EQEmu::item::ItemTypeSmallThrowing: + return SkillThrowing; + case EQEmu::item::ItemTypeMartial: + return SkillHandtoHand; + default: + return SkillHandtoHand; } - return SkillHandtoHand; } uint8 Mob::GetItemTypeBySkill(SkillUseTypes skill) { - switch (skill) - { - case SkillThrowing: - return ItemTypeSmallThrowing; - case SkillArchery: - return ItemTypeArrow; - case Skill1HSlashing: - return ItemType1HSlash; - case Skill2HSlashing: - return ItemType2HSlash; - case Skill1HPiercing: - return ItemType1HPiercing; - case Skill2HPiercing: // watch for undesired client behavior - return ItemType2HPiercing; - case Skill1HBlunt: - return ItemType1HBlunt; - case Skill2HBlunt: - return ItemType2HBlunt; - case SkillHandtoHand: - return ItemTypeMartial; - default: - return ItemTypeMartial; + switch (skill) { + case SkillThrowing: + return EQEmu::item::ItemTypeSmallThrowing; + case SkillArchery: + return EQEmu::item::ItemTypeArrow; + case Skill1HSlashing: + return EQEmu::item::ItemType1HSlash; + case Skill2HSlashing: + return EQEmu::item::ItemType2HSlash; + case Skill1HPiercing: + return EQEmu::item::ItemType1HPiercing; + case Skill2HPiercing: // watch for undesired client behavior + return EQEmu::item::ItemType2HPiercing; + case Skill1HBlunt: + return EQEmu::item::ItemType1HBlunt; + case Skill2HBlunt: + return EQEmu::item::ItemType2HBlunt; + case SkillHandtoHand: + return EQEmu::item::ItemTypeMartial; + default: + return EQEmu::item::ItemTypeMartial; } - return ItemTypeMartial; } @@ -5631,7 +5627,7 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot) bool Mob::CanClassEquipItem(uint32 item_id) { - const Item_Struct* itm = nullptr; + const EQEmu::Item_Struct* itm = nullptr; itm = database.GetItem(item_id); if (!itm) diff --git a/zone/mob.h b/zone/mob.h index ac7670ff4..18c46cb61 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -44,10 +44,14 @@ class Group; class ItemInst; class NPC; class Raid; -struct Item_Struct; struct NewSpawn_Struct; struct PlayerPositionUpdateServer_Struct; +namespace EQEmu +{ + struct Item_Struct; +} + class Mob : public Entity { public: enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD, @@ -763,7 +767,7 @@ public: virtual int GetHaste(); int32 GetMeleeMitigation(); - uint8 GetWeaponDamageBonus(const Item_Struct* weapon, bool offhand = false); + uint8 GetWeaponDamageBonus(const EQEmu::Item_Struct* weapon, bool offhand = false); uint16 GetDamageTable(SkillUseTypes skillinuse); virtual int GetHandToHandDamage(void); @@ -788,10 +792,10 @@ public: int32 ReduceAllDamage(int32 damage); virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool CheckHitChance=false, bool CanAvoid=true); - virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* AmmoItem=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0, uint32 range_id=0, int AmmoSlot=0, float speed = 4.0f); + virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const EQEmu::Item_Struct* AmmoItem=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0, uint32 range_id=0, int AmmoSlot=0, float speed = 4.0f); virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime=0); - virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0, uint32 range_id=0, uint32 ammo_id=0, const Item_Struct *AmmoItem=nullptr, int AmmoSlot=0, float speed= 4.0f); - bool TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed); + virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0, uint32 range_id=0, uint32 ammo_id=0, const EQEmu::Item_Struct *AmmoItem=nullptr, int AmmoSlot=0, float speed= 4.0f); + bool TryProjectileAttack(Mob* other, const EQEmu::Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed); void ProjectileAttack(); inline bool HasProjectileAttack() const { return ActiveProjectileATK; } inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; } @@ -909,7 +913,7 @@ public: // HP Event inline int GetNextHPEvent() const { return nexthpevent; } void SetNextHPEvent( int hpevent ); - void SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse, float velocity= 4.0); + void SendItemAnimation(Mob *to, const EQEmu::Item_Struct *item, SkillUseTypes skillInUse, float velocity= 4.0); inline int& GetNextIncHPEvent() { return nextinchpevent; } void SetNextIncHPEvent( int inchpevent ); @@ -1147,8 +1151,8 @@ protected: bool PassLimitToSkill(uint16 spell_id, uint16 skill); bool PassLimitClass(uint32 Classes_, uint16 Class_); void TryDefensiveProc(Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); - void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); - void TrySpellProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); + void TryWeaponProc(const ItemInst* inst, const EQEmu::Item_Struct* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); + void TrySpellProc(const ItemInst* inst, const EQEmu::Item_Struct* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on, int level_override = -1); virtual float GetProcChances(float ProcBonus, uint16 hand = EQEmu::legacy::SlotPrimary); @@ -1157,7 +1161,7 @@ protected: virtual float GetAssassinateProcChances(uint16 ReuseTime); virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm? uint16 GetWeaponSpeedbyHand(uint16 hand); - int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item); + int GetWeaponDamage(Mob *against, const EQEmu::Item_Struct *weapon_item); int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr); int GetKickDamage(); int GetBashDamage(); diff --git a/zone/mod_functions.cpp b/zone/mod_functions.cpp index 5c98541c0..e58945732 100644 --- a/zone/mod_functions.cpp +++ b/zone/mod_functions.cpp @@ -9,7 +9,10 @@ class ItemInst; class Spawn2; struct Consider_Struct; struct DBTradeskillRecipe_Struct; -struct Item_Struct; + +namespace { + struct Item_Struct; +} extern EntityList entity_list; extern Zone* zone; @@ -26,7 +29,7 @@ void Zone::mod_repop() { return; } void NPC::mod_prespawn(Spawn2 *sp) { return; } //Base damage from NPC::Attack -int NPC::mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const Item_Struct* weapon, Mob* other) { return(damage); } +int NPC::mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const EQEmu::Item_Struct* weapon, Mob* other) { return(damage); } //Mob c has been given credit for a kill. This is called after the regular EVENT_KILLED_MERIT event. void NPC::mod_npc_killed_merit(Mob* c) { return; } @@ -104,8 +107,8 @@ int32 Client::mod_client_xp(int32 in_xp, NPC *npc) { return(in_xp); } uint32 Client::mod_client_xp_for_level(uint32 xp, uint16 check_level) { return(xp); } //Food and drink values as computed by consume requests. Return < 0 to abort the request. -int Client::mod_food_value(const Item_Struct *item, int change) { return(change); } -int Client::mod_drink_value(const Item_Struct *item, int change) { return(change); } +int Client::mod_food_value(const EQEmu::Item_Struct *item, int change) { return(change); } +int Client::mod_drink_value(const EQEmu::Item_Struct *item, int change) { return(change); } //effect_vallue - Spell effect value as calculated by default formulas. You will want to ignore effects that don't lend themselves to scaling - pet ID's, gate coords, etc. int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster, uint16 caster_id) { return(effect_value); } diff --git a/zone/npc.cpp b/zone/npc.cpp index 7c91d67a5..8b09f448c 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -523,7 +523,7 @@ void NPC::QueryLoot(Client* to) int x = 0; for(ItemList::iterator cur = itemlist.begin(); cur != itemlist.end(); ++cur, ++x) { - const Item_Struct* item = database.GetItem((*cur)->item_id); + const EQEmu::Item_Struct* item = database.GetItem((*cur)->item_id); if (item == nullptr) { Log.Out(Logs::General, Logs::Error, "Database error, invalid item"); continue; @@ -765,7 +765,7 @@ void NPC::UpdateEquipmentLight() auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } - if (item->ItemClass != ItemClassCommon) { continue; } + if (!item->IsClassCommon()) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } if (EQEmu::lightsource::TypeToLevel(item->Light)) @@ -1456,13 +1456,13 @@ void NPC::PickPocket(Client* thief) // still needs to have FindFreeSlot vs PutItemInInventory issue worked out while (steal_item) { - std::vector> loot_selection; // + std::vector> loot_selection; // for (auto item_iter : itemlist) { if (!item_iter || !item_iter->item_id) continue; auto item_test = database.GetItem(item_iter->item_id); - if (item_test->Magic || !item_test->NoDrop || item_test->ItemType == ItemClassContainer || thief->CheckLoreConflict(item_test)) + if (item_test->Magic || !item_test->NoDrop || item_test->IsClassBag() || thief->CheckLoreConflict(item_test)) continue; loot_selection.push_back(std::make_pair(item_test, ((item_test->Stackable) ? (1) : (item_iter->charges)))); @@ -1473,7 +1473,7 @@ void NPC::PickPocket(Client* thief) } int random = zone->random.Int(0, (loot_selection.size() - 1)); - uint16 slot_id = thief->GetInv().FindFreeSlot(false, true, (loot_selection[random].first->Size), (loot_selection[random].first->ItemType == ItemTypeArrow)); + uint16 slot_id = thief->GetInv().FindFreeSlot(false, true, (loot_selection[random].first->Size), (loot_selection[random].first->ItemType == EQEmu::item::ItemTypeArrow)); if (slot_id == INVALID_INDEX) { steal_item = false; break; diff --git a/zone/npc.h b/zone/npc.h index 834211198..0456ca211 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -90,7 +90,11 @@ class Client; class Group; class Raid; class Spawn2; -struct Item_Struct; + +namespace EQEmu +{ + struct Item_Struct; +} class NPC : public Mob { @@ -174,7 +178,7 @@ public: virtual void SpellProcess(); virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); - void AddItem(const Item_Struct* item, uint16 charges, bool equipitem = true); + void AddItem(const EQEmu::Item_Struct* item, uint16 charges, bool equipitem = true); void AddItem(uint32 itemid, uint16 charges, bool equipitem = true); void AddLootTable(); void AddLootTable(uint32 ldid); @@ -266,7 +270,7 @@ public: bool IsTaunting() const { return taunting; } void PickPocket(Client* thief); void StartSwarmTimer(uint32 duration) { swarm_timer.Start(duration); } - void AddLootDrop(const Item_Struct*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); + void AddLootDrop(const EQEmu::Item_Struct*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); virtual void DoClassAttacks(Mob *target); void CheckSignal(); inline bool IsNotTargetableWithHotkey() const { return no_target_hotkey; } @@ -399,7 +403,7 @@ public: void SetMerchantProbability(uint8 amt) { probability = amt; } uint8 GetMerchantProbability() { return probability; } void mod_prespawn(Spawn2 *sp); - int mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const Item_Struct* weapon, Mob* other); + int mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const EQEmu::Item_Struct* weapon, Mob* other); void mod_npc_killed_merit(Mob* c); void mod_npc_killed(Mob* oos); void AISpellsList(Client *c); diff --git a/zone/object.cpp b/zone/object.cpp index 122db47ed..f6330d872 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -138,7 +138,7 @@ Object::Object(Client* client, const ItemInst* inst) // Set object name if (inst) { - const Item_Struct* item = inst->GetItem(); + const EQEmu::Item_Struct* item = inst->GetItem(); if (item && item->IDFile) { if (strlen(item->IDFile) == 0) { strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); @@ -194,7 +194,7 @@ Object::Object(const ItemInst *inst, float x, float y, float z, float heading, u // Set object name if (inst) { - const Item_Struct* item = inst->GetItem(); + const EQEmu::Item_Struct* item = inst->GetItem(); if (item && item->IDFile) { if (strlen(item->IDFile) == 0) { strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); @@ -339,7 +339,7 @@ void Object::PutItem(uint8 index, const ItemInst* inst) return; } - if (m_inst && m_inst->IsType(ItemClassContainer)) { + if (m_inst && m_inst->IsType(EQEmu::item::ItemClassBag)) { if (inst) { m_inst->PutItem(index, *inst); } @@ -380,7 +380,7 @@ void Object::Close() { // Remove item from container void Object::DeleteItem(uint8 index) { - if (m_inst && m_inst->IsType(ItemClassContainer)) { + if (m_inst && m_inst->IsType(EQEmu::item::ItemClassBag)) { m_inst->DeleteItem(index); // This is _highly_ inefficient, but for now it will work: Save entire object to database @@ -393,7 +393,7 @@ ItemInst* Object::PopItem(uint8 index) { ItemInst* inst = nullptr; - if (m_inst && m_inst->IsType(ItemClassContainer)) { + if (m_inst && m_inst->IsType(EQEmu::item::ItemClassBag)) { inst = m_inst->PopItem(index); // This is _highly_ inefficient, but for now it will work: Save entire object to database @@ -574,7 +574,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) // Send items inside of container - if (m_inst && m_inst->IsType(ItemClassContainer)) { + if (m_inst && m_inst->IsType(EQEmu::item::ItemClassBag)) { //Clear out no-drop and no-rent items first if different player opens it if(user != last_user) @@ -628,7 +628,7 @@ uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& ob } // Save container contents, if container - if (inst && inst->IsType(ItemClassContainer)) + if (inst && inst->IsType(EQEmu::item::ItemClassBag)) SaveWorldContainer(object.zone_id, database_id, inst); return database_id; @@ -665,7 +665,7 @@ void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Objec } // Save container contents, if container - if (inst && inst->IsType(ItemClassContainer)) + if (inst && inst->IsType(EQEmu::item::ItemClassBag)) SaveWorldContainer(object.zone_id, id, inst); } @@ -881,7 +881,7 @@ uint32 Object::GetItemID() return 0; } - const Item_Struct* item = this->m_inst->GetItem(); + const EQEmu::Item_Struct* item = this->m_inst->GetItem(); if (item == 0) { diff --git a/zone/object.h b/zone/object.h index 9e8fae05d..c39ee61c9 100644 --- a/zone/object.h +++ b/zone/object.h @@ -69,7 +69,7 @@ IT10714_ACTORDEF=Augmentation Sealer IT10725_ACTORDEF=Shuriken */ -#define OT_DROPPEDITEM BagTypeLargeBag +#define OT_DROPPEDITEM EQEmu::item::BagTypeLargeBag // Icon values: //0x0453 a pie diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 8c7413a40..c9c24b955 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -8131,7 +8131,7 @@ XS(XS_Mob_DoThrowingAttackDmg) Mob * THIS; Mob* target; ItemInst* RangeWeapon = nullptr; - Item_Struct* item = nullptr; + EQEmu::Item_Struct* item = nullptr; uint16 weapon_damage = (uint16)SvIV(ST(4)); int16 chance_mod = (int16)SvIV(ST(5)); int16 focus = (int16)SvIV(ST(6)); diff --git a/zone/perl_questitem.cpp b/zone/perl_questitem.cpp index 158ee64a4..fa186a9b5 100644 --- a/zone/perl_questitem.cpp +++ b/zone/perl_questitem.cpp @@ -134,7 +134,7 @@ XS(XS_QuestItem_IsType) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->IsType((ItemClassTypes)type); + RETVAL = THIS->IsType((EQEmu::item::ItemClass)type); ST(0) = boolSV(RETVAL); sv_2mortal(ST(0)); } diff --git a/zone/pets.cpp b/zone/pets.cpp index 00ffebc58..96c053e73 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -420,7 +420,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, // like the special back items some focused pets may receive. uint32 petinv[EQEmu::legacy::EQUIPMENT_SIZE]; memset(petinv, 0, sizeof(petinv)); - const Item_Struct *item = 0; + const EQEmu::Item_Struct *item = 0; if (database.GetBasePetItems(record.equipmentset, petinv)) { for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++) @@ -665,7 +665,7 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { if(items[i] == 0) continue; - const Item_Struct* item2 = database.GetItem(items[i]); + const EQEmu::Item_Struct* item2 = database.GetItem(items[i]); if (item2 && item2->NoDrop != 0) { //dont bother saving item charges for now, NPCs never use them //and nobody should be able to get them off the corpse..? diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 806f995e7..4a1980489 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -812,12 +812,12 @@ void QuestManager::traindisc(int discipline_tome_item_id) { } bool QuestManager::isdisctome(int item_id) { - const Item_Struct *item = database.GetItem(item_id); + const EQEmu::Item_Struct *item = database.GetItem(item_id); if(item == nullptr) { return(false); } - if(item->ItemClass != ItemClassCommon || item->ItemType != ItemTypeSpell) { + if (!item->IsClassCommon() || item->ItemType != EQEmu::item::ItemTypeSpell) { return(false); } @@ -1303,7 +1303,7 @@ void QuestManager::settime(uint8 new_hour, uint8 new_min, bool update_world /*= void QuestManager::itemlink(int item_id) { QuestManagerCurrentQuestVars(); if (initiator) { - const Item_Struct* item = database.GetItem(item_id); + const EQEmu::Item_Struct* item = database.GetItem(item_id); if (item == nullptr) return; @@ -2495,7 +2495,7 @@ void QuestManager::MerchantSetItem(uint32 NPCid, uint32 itemid, uint32 quantity) if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != MERCHANT)) return; // don't do anything if NPCid isn't a merchant - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; item = database.GetItem(itemid); if (!item) return; // if the item id doesn't correspond to a real item, do nothing @@ -2508,7 +2508,7 @@ uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) { if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != MERCHANT)) return 0; // if it isn't a merchant, it doesn't have any items - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; item = database.GetItem(itemid); if (!item) return 0; // if it isn't a valid item, the merchant doesn't have any @@ -2531,7 +2531,7 @@ uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) { // Item Link for use in Variables - "my $example_link = quest::varlink(item_id);" const char* QuestManager::varlink(char* perltext, int item_id) { QuestManagerCurrentQuestVars(); - const Item_Struct* item = database.GetItem(item_id); + const EQEmu::Item_Struct* item = database.GetItem(item_id); if (!item) return "INVALID ITEM ID IN VARLINK"; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 7d9bbc0d3..c54737475 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -118,11 +118,11 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, ItemInst *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); if(item) { - if(item->GetItem()->ItemType == ItemTypeShield) + if (item->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { hate += item->GetItem()->AC; } - const Item_Struct *itm = item->GetItem(); + const EQEmu::Item_Struct *itm = item->GetItem(); auto fbash = GetFuriousBash(itm->Focus.Effect); hate = hate * (100 + fbash) / 100; if (fbash) @@ -477,7 +477,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) } } else{ - if(GetWeaponDamage(other, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(other, (const EQEmu::Item_Struct*)nullptr) <= 0){ ndamage = -5; } } @@ -513,7 +513,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { //make sure we have a proper weapon if we are a client. if(IsClient()) { const ItemInst *wpn = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); - if(!wpn || (wpn->GetItem()->ItemType != ItemType1HPiercing)){ + if (!wpn || (wpn->GetItem()->ItemType != EQEmu::item::ItemType1HPiercing)){ Message_StringID(13, BACKSTAB_WEAPON); return; } @@ -697,28 +697,28 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { int ammo_slot = EQEmu::legacy::SlotAmmo; const ItemInst* Ammo = m_inv[EQEmu::legacy::SlotAmmo]; - if (!RangeWeapon || !RangeWeapon->IsType(ItemClassCommon)) { + if (!RangeWeapon || !RangeWeapon->IsClassCommon()) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(EQEmu::legacy::SlotRange), EQEmu::legacy::SlotRange); Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have no bow!", GetItemIDAt(EQEmu::legacy::SlotRange)); return; } - if (!Ammo || !Ammo->IsType(ItemClassCommon)) { + if (!Ammo || !Ammo->IsClassCommon()) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ammo item (%d) in slot %d", GetItemIDAt(EQEmu::legacy::SlotAmmo), EQEmu::legacy::SlotAmmo); Message(0, "Error: Ammo: GetItem(%i)==0, you have no ammo!", GetItemIDAt(EQEmu::legacy::SlotAmmo)); return; } - const Item_Struct* RangeItem = RangeWeapon->GetItem(); - const Item_Struct* AmmoItem = Ammo->GetItem(); + const EQEmu::Item_Struct* RangeItem = RangeWeapon->GetItem(); + const EQEmu::Item_Struct* AmmoItem = Ammo->GetItem(); - if(RangeItem->ItemType != ItemTypeBow) { + if (RangeItem->ItemType != EQEmu::item::ItemTypeBow) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item is not a bow. type %d.", RangeItem->ItemType); Message(0, "Error: Rangeweapon: Item %d is not a bow.", RangeWeapon->GetID()); return; } - if(AmmoItem->ItemType != ItemTypeArrow) { + if (AmmoItem->ItemType != EQEmu::item::ItemTypeArrow) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ammo item is not an arrow. type %d.", AmmoItem->ItemType); - Message(0, "Error: Ammo: type %d != %d, you have the wrong type of ammo!", AmmoItem->ItemType, ItemTypeArrow); + Message(0, "Error: Ammo: type %d != %d, you have the wrong type of ammo!", AmmoItem->ItemType, EQEmu::item::ItemTypeArrow); return; } @@ -731,10 +731,10 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { bool found = false; for (r = EQEmu::legacy::GENERAL_BEGIN; r <= EQEmu::legacy::GENERAL_END; r++) { const ItemInst *pi = m_inv[r]; - if(pi == nullptr || !pi->IsType(ItemClassContainer)) + if (pi == nullptr || !pi->IsClassBag()) continue; - const Item_Struct* bagitem = pi->GetItem(); - if(!bagitem || bagitem->BagType != BagTypeQuiver) + const EQEmu::Item_Struct* bagitem = pi->GetItem(); + if (!bagitem || bagitem->BagType != EQEmu::item::BagTypeQuiver) continue; //we found a quiver, look for the ammo in it @@ -812,7 +812,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { } void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, - uint32 range_id, uint32 ammo_id, const Item_Struct *AmmoItem, int AmmoSlot, float speed) { + uint32 range_id, uint32 ammo_id, const EQEmu::Item_Struct *AmmoItem, int AmmoSlot, float speed) { if ((other == nullptr || ((IsClient() && CastToClient()->dead) || @@ -827,7 +827,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite const ItemInst* _RangeWeapon = nullptr; const ItemInst* _Ammo = nullptr; - const Item_Struct* ammo_lost = nullptr; + const EQEmu::Item_Struct* ammo_lost = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -1023,7 +1023,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } } -bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed){ +bool Mob::TryProjectileAttack(Mob* other, const EQEmu::Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed){ if (!other) return false; @@ -1327,7 +1327,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha //try proc on hits and misses if(other && !other->HasDied()) - TrySpellProc(nullptr, (const Item_Struct*)nullptr, other, EQEmu::legacy::SlotRange); + TrySpellProc(nullptr, (const EQEmu::Item_Struct*)nullptr, other, EQEmu::legacy::SlotRange); if (HasSkillProcs() && other && !other->HasDied()) TrySkillProc(other, skillInUse, 0, false, EQEmu::legacy::SlotRange); @@ -1375,14 +1375,14 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 int ammo_slot = EQEmu::legacy::SlotRange; const ItemInst* RangeWeapon = m_inv[EQEmu::legacy::SlotRange]; - if (!RangeWeapon || !RangeWeapon->IsType(ItemClassCommon)) { + if (!RangeWeapon || !RangeWeapon->IsClassCommon()) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(EQEmu::legacy::SlotRange), EQEmu::legacy::SlotRange); Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(EQEmu::legacy::SlotRange)); return; } - const Item_Struct* item = RangeWeapon->GetItem(); - if(item->ItemType != ItemTypeLargeThrowing && item->ItemType != ItemTypeSmallThrowing) { + const EQEmu::Item_Struct* item = RangeWeapon->GetItem(); + if (item->ItemType != EQEmu::item::ItemTypeLargeThrowing && item->ItemType != EQEmu::item::ItemTypeSmallThrowing) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item %d is not a throwing weapon. type %d.", item->ItemType); Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(EQEmu::legacy::SlotRange)); return; @@ -1442,7 +1442,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 CommonBreakInvisibleFromCombat(); } -void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item_Struct* AmmoItem, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed) +void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQEmu::Item_Struct* AmmoItem, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed) { if ((other == nullptr || ((IsClient() && CastToClient()->dead) || @@ -1456,7 +1456,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } const ItemInst* _RangeWeapon = nullptr; - const Item_Struct* ammo_lost = nullptr; + const EQEmu::Item_Struct* ammo_lost = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -1580,7 +1580,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } } -void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse, float velocity) { +void Mob::SendItemAnimation(Mob *to, const EQEmu::Item_Struct *item, SkillUseTypes skillInUse, float velocity) { EQApplicationPacket *outapp = new EQApplicationPacket(OP_SomeItemPacketMaybe, sizeof(Arrow_Struct)); Arrow_Struct *as = (Arrow_Struct *) outapp->pBuffer; as->type = 1; @@ -1630,7 +1630,7 @@ void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, f if (!to) return; - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; uint8 item_type = 0; if(!item_id) { @@ -1771,7 +1771,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ dmg = -5; } else{ @@ -1792,7 +1792,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ dmg = -5; } else{ @@ -1845,7 +1845,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ dmg = -5; } else{ @@ -1870,7 +1870,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if(GetWeaponDamage(target, (const Item_Struct*)nullptr) <= 0){ + if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ dmg = -5; } else{ @@ -2382,7 +2382,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes int32 max_hit = (2 * weapon_damage*GetDamageTable(skillinuse)) / 100; if(GetLevel() >= 28 && IsWarriorClass() ) { - int ucDamageBonus = GetWeaponDamageBonus((const Item_Struct*) nullptr ); + int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::Item_Struct*) nullptr ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -2392,10 +2392,10 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if(IsClient()){ ItemInst *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); if(item){ - if(item->GetItem()->ItemType == ItemTypeShield) { + if (item->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { hate += item->GetItem()->AC; } - const Item_Struct *itm = item->GetItem(); + const EQEmu::Item_Struct *itm = item->GetItem(); hate = hate * (100 + GetFuriousBash(itm->Focus.Effect)) / 100; } } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ab20371fa..79dda2125 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -617,7 +617,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #endif if(IsClient()){ ItemInst* transI = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotCursor); - if(transI && transI->IsType(ItemClassCommon) && transI->IsStackable()){ + if (transI && transI->IsClassCommon() && transI->IsStackable()){ uint32 fcharges = transI->GetCharges(); //Does it sound like meat... maybe should check if it looks like meat too... if(strstr(transI->GetItem()->Name, "meat") || @@ -1132,7 +1132,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_SummonItem: { - const Item_Struct *item = database.GetItem(spell.base[i]); + const EQEmu::Item_Struct *item = database.GetItem(spell.base[i]); #ifdef SPELL_EFFECT_SPAM const char *itemname = item ? item->Name : "*Unknown Item*"; snprintf(effect_desc, _EDLEN, "Summon Item: %s (id %d)", itemname, spell.base[i]); @@ -1168,14 +1168,14 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } case SE_SummonItemIntoBag: { - const Item_Struct *item = database.GetItem(spell.base[i]); + const EQEmu::Item_Struct *item = database.GetItem(spell.base[i]); #ifdef SPELL_EFFECT_SPAM const char *itemname = item ? item->Name : "*Unknown Item*"; snprintf(effect_desc, _EDLEN, "Summon Item In Bag: %s (id %d)", itemname, spell.base[i]); #endif uint8 slot; - if (!SummonedItem || !SummonedItem->IsType(ItemClassContainer)) { + if (!SummonedItem || !SummonedItem->IsClassBag()) { if (caster) caster->Message(13, "SE_SummonItemIntoBag but no bag has been summoned!"); } else if ((slot = SummonedItem->FirstOpenSlot()) == 0xff) { @@ -5124,7 +5124,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { //item focus if (itembonuses.FocusEffects[type]){ - const Item_Struct* TempItem = 0; + const EQEmu::Item_Struct* TempItem = 0; for (int x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::EQUIPMENT_END; x++) { @@ -5155,7 +5155,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { aug = ins->GetAugment(y); if(aug) { - const Item_Struct* TempItemAug = aug->GetItem(); + const EQEmu::Item_Struct* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && IsValidSpell(TempItemAug->Focus.Effect)) { proc_spellid = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id); if (IsValidSpell(proc_spellid)){ @@ -5253,8 +5253,8 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[type]){ - const Item_Struct* TempItem = 0; - const Item_Struct* UsedItem = 0; + const EQEmu::Item_Struct* TempItem = 0; + const EQEmu::Item_Struct* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -5301,7 +5301,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) aug = ins->GetAugment(y); if(aug) { - const Item_Struct* TempItemAug = aug->GetItem(); + const EQEmu::Item_Struct* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { focus_max = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id, true); @@ -5525,8 +5525,8 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { if (RuleB(Spells, NPC_UseFocusFromItems) && itembonuses.FocusEffects[type]){ - const Item_Struct* TempItem = 0; - const Item_Struct* UsedItem = 0; + const EQEmu::Item_Struct* TempItem = 0; + const EQEmu::Item_Struct* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -5534,7 +5534,7 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { //item focus for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++){ - const Item_Struct *cur = database.GetItem(equipment[i]); + const EQEmu::Item_Struct *cur = database.GetItem(equipment[i]); if(!cur) continue; diff --git a/zone/spells.cpp b/zone/spells.cpp index f0bc6e85a..dbf89a5cc 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -258,7 +258,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int bitmask = 1; bitmask = bitmask << (CastToClient()->GetClass() - 1); if( itm && itm->GetItem()->Classes != 65535 ) { - if ((itm->GetItem()->Click.Type == ET_EquipClick) && !(itm->GetItem()->Classes & bitmask)) { + if ((itm->GetItem()->Click.Type == EQEmu::item::ItemEffectEquipClick) && !(itm->GetItem()->Classes & bitmask)) { if (CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoF) { // They are casting a spell from an item that requires equipping but shouldn't let them equip it Log.Out(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click an equip-only effect on item %s (id: %d) which they shouldn't be able to equip!", @@ -270,7 +270,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, } return(false); } - if ((itm->GetItem()->Click.Type == ET_ClickEffect2) && !(itm->GetItem()->Classes & bitmask)) { + if ((itm->GetItem()->Click.Type == EQEmu::item::ItemEffectClick2) && !(itm->GetItem()->Classes & bitmask)) { if (CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoF) { // They are casting a spell from an item that they don't meet the race/class requirements to cast Log.Out(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click a race/class restricted effect on item %s (id: %d) which they shouldn't be able to click!", @@ -291,7 +291,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, return(false); } } - if (itm && (itm->GetItem()->Click.Type == ET_EquipClick) && !(item_slot <= EQEmu::legacy::SlotAmmo || item_slot == EQEmu::legacy::SlotPowerSource)){ + if (itm && (itm->GetItem()->Click.Type == EQEmu::item::ItemEffectEquipClick) && !(item_slot <= EQEmu::legacy::SlotAmmo || item_slot == EQEmu::legacy::SlotPowerSource)){ if (CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoF) { // They are attempting to cast a must equip clicky without having it equipped Log.Out(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click an equip-only effect on item %s (id: %d) without equiping it!", CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID); @@ -1136,7 +1136,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, missingreags=true; } - const Item_Struct *item = database.GetItem(component); + const EQEmu::Item_Struct *item = database.GetItem(component); if(item) { c->Message_StringID(13, MISSING_SPELL_COMP_ITEM, item->Name); Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Canceled. Missing required reagent %s (%d)", spell_id, item->Name, component); @@ -1198,7 +1198,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, { bool fromaug = false; const ItemInst* inst = CastToClient()->GetInv()[inventory_slot]; - Item_Struct* augitem = 0; + EQEmu::Item_Struct* augitem = 0; uint32 recastdelay = 0; uint32 recasttype = 0; @@ -1211,7 +1211,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, if (!aug_i) continue; - const Item_Struct* aug = aug_i->GetItem(); + const EQEmu::Item_Struct* aug = aug_i->GetItem(); if (!aug) continue; @@ -1245,7 +1245,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, } } - if (inst && inst->IsType(ItemClassCommon) && (inst->GetItem()->Click.Effect == spell_id) && inst->GetCharges() || fromaug) + if (inst && inst->IsClassCommon() && (inst->GetItem()->Click.Effect == spell_id) && inst->GetCharges() || fromaug) { //const Item_Struct* item = inst->GetItem(); int16 charges = inst->GetItem()->MaxCharges; diff --git a/zone/tasks.cpp b/zone/tasks.cpp index fc51c5810..2c2a1c1b0 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1884,7 +1884,7 @@ void ClientTaskState::RewardTask(Client *c, TaskInformation *Task) { if(!Task || !c) return; - const Item_Struct* Item; + const EQEmu::Item_Struct* Item; std::vector RewardList; switch(Task->RewardMethod) { @@ -2777,7 +2777,7 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN } if(ItemID) { - const Item_Struct* reward_item = database.GetItem(ItemID); + const EQEmu::Item_Struct* reward_item = database.GetItem(ItemID); EQEmu::saylink::SayLinkEngine linker; linker.SetLinkType(linker.SayLinkItemData); diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 863a0603c..a5e931e62 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -61,8 +61,8 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme inst = user_inv.GetItem(in_augment->container_slot); if (inst) { - const Item_Struct* item = inst->GetItem(); - if (item && inst->IsType(ItemClassContainer) && item->BagType == 53) + const EQEmu::Item_Struct* item = inst->GetItem(); + if (item && inst->IsType(EQEmu::item::ItemClassBag) && item->BagType == 53) { // We have found an appropriate inventory augmentation sealer container = inst; @@ -166,8 +166,8 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme else { ItemInst *old_aug = nullptr; - bool isSolvent = auged_with->GetItem()->ItemType == ItemUseTypes::ItemTypeAugmentationSolvent; - if (!isSolvent && auged_with->GetItem()->ItemType != ItemUseTypes::ItemTypeAugmentationDistiller) + bool isSolvent = auged_with->GetItem()->ItemType == EQEmu::item::ItemTypeAugmentationSolvent; + if (!isSolvent && auged_with->GetItem()->ItemType != EQEmu::item::ItemTypeAugmentationDistiller) { Log.Out(Logs::General, Logs::Error, "Player tried to remove an augment without a solvent or distiller."); user->Message(13, "Error: Missing an augmentation solvent or distiller for removing this augment."); @@ -276,25 +276,25 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob else { inst = user_inv.GetItem(in_combine->container_slot); if (inst) { - const Item_Struct* item = inst->GetItem(); - if (item && inst->IsType(ItemClassContainer)) { + const EQEmu::Item_Struct* item = inst->GetItem(); + if (item && inst->IsType(EQEmu::item::ItemClassBag)) { c_type = item->BagType; some_id = item->ID; } } } - if (!inst || !inst->IsType(ItemClassContainer)) { + if (!inst || !inst->IsType(EQEmu::item::ItemClassBag)) { user->Message(13, "Error: Server does not recognize specified tradeskill container"); return; } container = inst; - if (container->GetItem() && container->GetItem()->BagType == BagTypeTransformationmold) { + if (container->GetItem() && container->GetItem()->BagType == EQEmu::item::BagTypeTransformationmold) { const ItemInst* inst = container->GetItem(0); bool AllowAll = RuleB(Inventory, AllowAnyWeaponTransformation); if (inst && ItemInst::CanTransform(inst->GetItem(), container->GetItem(), AllowAll)) { - const Item_Struct* new_weapon = inst->GetItem(); + const EQEmu::Item_Struct* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::legacy::SlotCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2)); @@ -311,10 +311,10 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob return; } - if (container->GetItem() && container->GetItem()->BagType == BagTypeDetransformationmold) { + if (container->GetItem() && container->GetItem()->BagType == EQEmu::item::BagTypeDetransformationmold) { const ItemInst* inst = container->GetItem(0); if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIcon()) { - const Item_Struct* new_weapon = inst->GetItem(); + const EQEmu::Item_Struct* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::legacy::SlotCursor, 0, 0); @@ -538,7 +538,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac for(std::list::iterator it = MissingItems.begin(); it != MissingItems.end(); ++it) { - const Item_Struct* item = database.GetItem(*it); + const EQEmu::Item_Struct* item = database.GetItem(*it); if(item) user->Message_StringID(MT_Skills, TRADESKILL_MISSING_ITEM, item->Name); @@ -607,77 +607,87 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac SkillUseTypes Object::TypeToSkill(uint32 type) { - switch(type) // grouped and ordered by SkillUseTypes name - new types need to be verified for proper SkillUseTypes and use - { + switch(type) { // grouped and ordered by SkillUseTypes name - new types need to be verified for proper SkillUseTypes and use /*SkillAlchemy*/ - case BagTypeMedicineBag: { return SkillAlchemy; } + case EQEmu::item::BagTypeMedicineBag: + return SkillAlchemy; /*SkillBaking*/ - // case BagTypeMixingBowl: // No idea... - case BagTypeOven: { return SkillBaking; } + //case EQEmu::item::BagTypeMixingBowl: // No idea... + case EQEmu::item::BagTypeOven: + return SkillBaking; /*SkillBlacksmithing*/ - case BagTypeForge: - // case BagTypeKoadaDalForge: - case BagTypeTeirDalForge: - case BagTypeOggokForge: - case BagTypeStormguardForge: - // case BagTypeAkanonForge: - // case BagTypeNorthmanForge: - // case BagTypeCabilisForge: - // case BagTypeFreeportForge: - // case BagTypeRoyalQeynosForge: - // case BagTypeTrollForge: - case BagTypeFierDalForge: - case BagTypeValeForge: { return SkillBlacksmithing; } // Delete return if BagTypeGuktaForge enabled - // case BagTypeErudForge: - // case BagTypeGuktaForge: { return SkillBlacksmithing; } + case EQEmu::item::BagTypeForge: + //case EQEmu::item::BagTypeKoadaDalForge: + case EQEmu::item::BagTypeTeirDalForge: + case EQEmu::item::BagTypeOggokForge: + case EQEmu::item::BagTypeStormguardForge: + //case EQEmu::item::BagTypeAkanonForge: + //case EQEmu::item::BagTypeNorthmanForge: + //case EQEmu::item::BagTypeCabilisForge: + //case EQEmu::item::BagTypeFreeportForge: + //case EQEmu::item::BagTypeRoyalQeynosForge: + //case EQEmu::item::BagTypeTrollForge: + case EQEmu::item::BagTypeFierDalForge: + case EQEmu::item::BagTypeValeForge: + //case EQEmu::item::BagTypeErudForge: + //case EQEmu::item::BagTypeGuktaForge: + return SkillBlacksmithing; /*SkillBrewing*/ - // case BagTypeIceCreamChurn: // No idea... - case BagTypeBrewBarrel: { return SkillBrewing; } + //case EQEmu::item::BagTypeIceCreamChurn: // No idea... + case EQEmu::item::BagTypeBrewBarrel: + return SkillBrewing; /*SkillFishing*/ - case BagTypeTackleBox: { return SkillFishing; } + case EQEmu::item::BagTypeTackleBox: + return SkillFishing; /*SkillFletching*/ - case BagTypeFletchingKit: { return SkillFletching; } // Delete return if BagTypeFierDalFletchingKit enabled - // case BagTypeFierDalFletchingKit: { return SkillFletching; } + case EQEmu::item::BagTypeFletchingKit: + //case EQEmu::item::BagTypeFierDalFletchingKit: + return SkillFletching; /*SkillJewelryMaking*/ - case BagTypeJewelersKit: { return SkillJewelryMaking; } + case EQEmu::item::BagTypeJewelersKit: + return SkillJewelryMaking; /*SkillMakePoison*/ - // This is a guess and needs to be verified... (Could be SkillAlchemy) - // case BagTypeMortar: { return SkillMakePoison; } + // This is a guess and needs to be verified... (Could be SkillAlchemy) + //case EQEmu::item::BagTypeMortar: + // return SkillMakePoison; /*SkillPottery*/ - case BagTypePotteryWheel: - case BagTypeKiln: { return SkillPottery; } // Delete return if BagTypeIksarPotteryWheel enabled - // case BagTypeIksarPotteryWheel: { return SkillPottery; } + case EQEmu::item::BagTypePotteryWheel: + case EQEmu::item::BagTypeKiln: + //case EQEmu::item::BagTypeIksarPotteryWheel: + return SkillPottery; /*SkillResearch*/ - // case BagTypeLexicon: - case BagTypeWizardsLexicon: - case BagTypeMagesLexicon: - case BagTypeNecromancersLexicon: - case BagTypeEnchantersLexicon: { return SkillResearch; } // Delete return if BagTypeConcordanceofResearch enabled - // case BagTypeConcordanceofResearch: { return SkillResearch; } + //case EQEmu::item::BagTypeLexicon: + case EQEmu::item::BagTypeWizardsLexicon: + case EQEmu::item::BagTypeMagesLexicon: + case EQEmu::item::BagTypeNecromancersLexicon: + case EQEmu::item::BagTypeEnchantersLexicon: + //case EQEmu::item::BagTypeConcordanceofResearch: + return SkillResearch; /*SkillTailoring*/ - case BagTypeSewingKit: { return SkillTailoring; } // Delete return if BagTypeFierDalTailoringKit enabled - // case BagTypeHalflingTailoringKit: - // case BagTypeErudTailoringKit: - // case BagTypeFierDalTailoringKit: { return SkillTailoring; } + case EQEmu::item::BagTypeSewingKit: + //case EQEmu::item::BagTypeHalflingTailoringKit: + //case EQEmu::item::BagTypeErudTailoringKit: + //case EQEmu::item::BagTypeFierDalTailoringKit: + return SkillTailoring; /*SkillTinkering*/ - case BagTypeToolBox: { return SkillTinkering; } + case EQEmu::item::BagTypeToolBox: + return SkillTinkering; /*Undefined*/ - default: { break; } + default: + return TradeskillUnknown; } - - return TradeskillUnknown; } void Client::TradeskillSearchResults(const std::string &query, unsigned long objtype, unsigned long someid) { @@ -952,7 +962,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { aa_chance = spellbonuses.ReduceTradeskillFail[spec->tradeskill] + itembonuses.ReduceTradeskillFail[spec->tradeskill] + aabonuses.ReduceTradeskillFail[spec->tradeskill]; - const Item_Struct* item = nullptr; + const EQEmu::Item_Struct* item = nullptr; chance = mod_tradeskill_chance(chance, spec); @@ -1103,7 +1113,7 @@ bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint3 if (!inst) continue; - const Item_Struct* item = GetItem(inst->GetItem()->ID); + const EQEmu::Item_Struct* item = GetItem(inst->GetItem()->ID); if (!item) continue; @@ -1232,7 +1242,7 @@ bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint3 if(!inst) continue; - const Item_Struct* item = GetItem(inst->GetItem()->ID); + const EQEmu::Item_Struct* item = GetItem(inst->GetItem()->ID); if (!item) continue; diff --git a/zone/trading.cpp b/zone/trading.cpp index fe83e4e67..e746e2122 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -266,7 +266,7 @@ void Trade::LogTrade() sprintf(item_num, "%i", inst->GetItem()->ID); strcat(logtext, item_num); - if (inst->IsType(ItemClassContainer)) { + if (inst->IsClassBag()) { for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::legacy::ITEM_CONTAINER_SIZE; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { @@ -309,9 +309,9 @@ void Trade::DumpTrade() if (inst) { Log.Out(Logs::Detail, Logs::Trading, "Item %i (Charges=%i, Slot=%i, IsBag=%s)", inst->GetItem()->ID, inst->GetCharges(), - i, ((inst->IsType(ItemClassContainer)) ? "True" : "False")); + i, ((inst->IsClassBag()) ? "True" : "False")); - if (inst->IsType(ItemClassContainer)) { + if (inst->IsClassBag()) { for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::legacy::ITEM_CONTAINER_SIZE; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { @@ -335,7 +335,7 @@ void Client::ResetTrade() { for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; - if (inst && inst->IsType(ItemClassContainer)) { + if (inst && inst->IsClassBag()) { int16 free_slot = m_inv.FindFreeSlotForTradeItem(inst); if (free_slot != INVALID_INDEX) { @@ -490,7 +490,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { const ItemInst* inst = m_inv[trade_slot]; - if (inst && inst->IsType(ItemClassContainer)) { + if (inst && inst->IsClassBag()) { Log.Out(Logs::Detail, Logs::Trading, "Giving container %s (%d) in slot %d to %s", inst->GetItem()->Name, inst->GetItem()->ID, trade_slot, other->GetName()); // TODO: need to check bag items/augments for no drop..everything for attuned... @@ -840,7 +840,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st event_details->push_back(detail); qs_audit->char_count += detail->charges; - if(trade_inst->IsType(ItemClassContainer)) { + if (trade_inst->IsClassBag()) { for (uint8 sub_slot = SUB_INDEX_BEGIN; sub_slot < trade_inst->GetItem()->BagSlots; ++sub_slot) { const ItemInst* trade_baginst = trade_inst->GetItem(sub_slot); @@ -885,16 +885,16 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st continue; } - const Item_Struct* item = inst->GetItem(); + const EQEmu::Item_Struct* item = inst->GetItem(); if(item && quest_npc == false) { // if it was not a NO DROP or Attuned item (or if a GM is trading), let the NPC have it if(GetGM() || (item->NoDrop != 0 && inst->IsAttuned() == false)) { // pets need to look inside bags and try to equip items found there - if(item->ItemClass == ItemClassContainer && item->BagSlots > 0) { + if (item->IsClassBag() && item->BagSlots > 0) { for (int16 bslot = SUB_INDEX_BEGIN; bslot < item->BagSlots; bslot++) { const ItemInst* baginst = inst->GetItem(bslot); if (baginst) { - const Item_Struct* bagitem = baginst->GetItem(); + const EQEmu::Item_Struct* bagitem = baginst->GetItem(); if (bagitem && (GetGM() || (bagitem->NoDrop != 0 && baginst->IsAttuned() == false))) { tradingWith->CastToNPC()->AddLootDrop(bagitem, &tradingWith->CastToNPC()->itemlist, baginst->GetCharges(), 1, 127, true, true); @@ -1158,7 +1158,7 @@ void Client::SendTraderItem(uint32 ItemID, uint16 Quantity) { std::string Packet; int16 FreeSlotID=0; - const Item_Struct* item = database.GetItem(ItemID); + const EQEmu::Item_Struct* item = database.GetItem(ItemID); if(!item){ Log.Out(Logs::Detail, Logs::Trading, "Bogus item deleted in Client::SendTraderItem!\n"); @@ -1169,7 +1169,7 @@ void Client::SendTraderItem(uint32 ItemID, uint16 Quantity) { if (inst) { - bool is_arrow = (inst->GetItem()->ItemType == ItemTypeArrow) ? true : false; + bool is_arrow = (inst->GetItem()->ItemType == EQEmu::item::ItemTypeArrow) ? true : false; FreeSlotID = m_inv.FindFreeSlot(false, true, inst->GetItem()->Size, is_arrow); PutItemInInventory(FreeSlotID, *inst); @@ -1192,7 +1192,7 @@ void Client::SendSingleTraderItem(uint32 CharID, int SerialNumber) { } void Client::BulkSendTraderInventory(uint32 char_id) { - const Item_Struct *item; + const EQEmu::Item_Struct *item; TraderCharges_Struct* TraderItems = database.LoadTraderItemWithCharges(char_id); @@ -2030,7 +2030,7 @@ static void UpdateTraderCustomerItemsAdded(uint32 CustomerID, TraderCharges_Stru if(!Customer) return; - const Item_Struct *item = database.GetItem(ItemID); + const EQEmu::Item_Struct *item = database.GetItem(ItemID); if(!item) return; @@ -2074,7 +2074,7 @@ static void UpdateTraderCustomerPriceChanged(uint32 CustomerID, TraderCharges_St if(!Customer) return; - const Item_Struct *item = database.GetItem(ItemID); + const EQEmu::Item_Struct *item = database.GetItem(ItemID); if(!item) return; @@ -2233,7 +2233,7 @@ void Client::HandleTraderPriceUpdate(const EQApplicationPacket *app) { } - const Item_Struct *item = 0; + const EQEmu::Item_Struct *item = 0; if(IDOfItemToAdd) item = database.GetItem(IDOfItemToAdd); @@ -2399,7 +2399,7 @@ void Client::SendBuyerResults(char* searchString, uint32 searchID) { char *buf = (char *)outapp->pBuffer; - const Item_Struct* item = database.GetItem(itemID); + const EQEmu::Item_Struct* item = database.GetItem(itemID); if(!item) { safe_delete(outapp); @@ -2495,7 +2495,7 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) { char *Buf = (char *)outapp->pBuffer; - const Item_Struct* item = database.GetItem(ItemID); + const EQEmu::Item_Struct* item = database.GetItem(ItemID); if(!item) { safe_delete(outapp); @@ -2539,7 +2539,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { /*uint32 BuyerID2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused /*uint32 Unknown3 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused - const Item_Struct *item = database.GetItem(ItemID); + const EQEmu::Item_Struct *item = database.GetItem(ItemID); if(!item || !Quantity || !Price || !QtyBuyerWants) return; @@ -2930,7 +2930,7 @@ void Client::UpdateBuyLine(const EQApplicationPacket *app) { /*uint32 UnknownZ =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused uint32 ItemCount = VARSTRUCT_DECODE_TYPE(uint32, Buf); - const Item_Struct *item = database.GetItem(ItemID); + const EQEmu::Item_Struct *item = database.GetItem(ItemID); if(!item) return; @@ -2994,7 +2994,7 @@ void Client::BuyerItemSearch(const EQApplicationPacket *app) { BuyerItemSearchResults_Struct* bisr = (BuyerItemSearchResults_Struct*)outapp->pBuffer; - const Item_Struct* item = 0; + const EQEmu::Item_Struct* item = 0; int Count=0; diff --git a/zone/tune.cpp b/zone/tune.cpp index bcaa69d4a..a6b55f02e 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -630,7 +630,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const Item_Struct*) nullptr ); + ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const EQEmu::Item_Struct*) nullptr ); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; diff --git a/zone/zone.cpp b/zone/zone.cpp index 55ec64110..5523f1e85 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -266,7 +266,7 @@ bool Zone::LoadZoneObjects() { } // Load child objects if container - if (inst && inst->IsType(ItemClassContainer)) { + if (inst && inst->IsType(EQEmu::item::ItemClassBag)) { database.LoadWorldContainer(id, inst); } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 5b66b691d..e2ea36fca 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -496,7 +496,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, ItemInst* container) aug[5] = (uint32)atoi(row[8]); ItemInst* inst = database.CreateItem(item_id, charges); - if (inst && inst->GetItem()->ItemClass == ItemClassCommon) { + if (inst && inst->GetItem()->IsClassCommon()) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) if (aug[i]) inst->PutAugment(&database, i, aug[i]); @@ -529,7 +529,7 @@ void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const It uint32 item_id = inst->GetItem()->ID; uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; - if (inst->IsType(ItemClassCommon)) { + if (inst->IsType(EQEmu::item::ItemClassCommon)) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { ItemInst *auginst=inst->GetAugment(i); augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; @@ -629,7 +629,7 @@ ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { int Charges = atoi(row[3]); int Cost = atoi(row[4]); - const Item_Struct *item = database.GetItem(ItemID); + const EQEmu::Item_Struct *item = database.GetItem(ItemID); if(!item) { Log.Out(Logs::Detail, Logs::Trading, "Unable to create item\n"); @@ -684,7 +684,7 @@ void ZoneDatabase::UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charg Log.Out(Logs::Detail, Logs::Trading, "ZoneDatabase::UpdateTraderPrice(%i, %i, %i, %i)", CharID, ItemID, Charges, NewPrice); - const Item_Struct *item = database.GetItem(ItemID); + const EQEmu::Item_Struct *item = database.GetItem(ItemID); if(!item) return; @@ -1197,7 +1197,7 @@ bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Str i = atoi(row[r]); /* Bandolier ID */ r++; si = atoi(row[r]); /* Bandolier Slot */ r++; - const Item_Struct* item_data = database.GetItem(atoi(row[r])); + const EQEmu::Item_Struct* item_data = database.GetItem(atoi(row[r])); if (item_data) { pp->bandoliers[i].Items[si].ID = item_data->ID; r++; pp->bandoliers[i].Items[si].Icon = atoi(row[r]); r++; // Must use db value in case an Ornamentation is assigned @@ -1249,7 +1249,7 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); - const Item_Struct *item_data = database.GetItem(atoi(row[1])); + const EQEmu::Item_Struct *item_data = database.GetItem(atoi(row[1])); if (!item_data) continue; pp->potionbelt.Items[i].ID = item_data->ID; From b28930b2ea702adc37ed7d52fcfd0f44aa84354a Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 21 May 2016 05:21:03 -0400 Subject: [PATCH 103/693] Fix for (possible) shared bank errors --- common/shareddb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index f75025dbf..ac0805978 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -407,13 +407,13 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) "sb.augslot1, sb.augslot2, sb.augslot3, " "sb.augslot4, sb.augslot5, sb.augslot6, sb.custom_data " "FROM sharedbank sb INNER JOIN character_data ch " - "ON ch.account_id=sb.acctid WHERE ch.id = %i", + "ON ch.account_id=sb.acctid WHERE ch.id = %i ORDER BY sb.slotid", id); else query = StringFormat("SELECT slotid, itemid, charges, " "augslot1, augslot2, augslot3, " "augslot4, augslot5, augslot6, custom_data " - "FROM sharedbank WHERE acctid=%i", + "FROM sharedbank WHERE acctid=%i ORDER BY slotid", id); auto results = QueryDatabase(query); if (!results.Success()) { From afd306f8cecb7e8025481a4d8cf07ab3d3112f1a Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 21 May 2016 14:55:43 -0400 Subject: [PATCH 104/693] Fix for GCC compile --- common/light_source.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/light_source.cpp b/common/light_source.cpp index f3b7ab74e..e88c80e6b 100644 --- a/common/light_source.cpp +++ b/common/light_source.cpp @@ -19,7 +19,7 @@ #include "light_source.h" -#include +#include uint8 EQEmu::lightsource::TypeToLevel(uint8 light_type) From 5f1b2475fbe7ab47414a7fb91466ac75082bb1ce Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 21 May 2016 15:01:29 -0400 Subject: [PATCH 105/693] Picky penguins... --- common/light_source.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/light_source.cpp b/common/light_source.cpp index e88c80e6b..730a5bd78 100644 --- a/common/light_source.cpp +++ b/common/light_source.cpp @@ -19,7 +19,7 @@ #include "light_source.h" -#include +#include uint8 EQEmu::lightsource::TypeToLevel(uint8 light_type) From 12905a3771c1a0020d94f572f32cb6a44074b4e9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 22 May 2016 18:02:46 -0400 Subject: [PATCH 106/693] Fix Item_Struct::IsEquipable issue --- common/item_struct.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/item_struct.cpp b/common/item_struct.cpp index 7bc202bdb..20c0ad1ee 100644 --- a/common/item_struct.cpp +++ b/common/item_struct.cpp @@ -169,7 +169,7 @@ uint8 EQEmu::item::ConvertAugTypeBitToAugType(uint32 aug_type_bit) bool EQEmu::Item_Struct::IsEquipable(uint16 race_id, uint16 class_id) { - if (!(Races & GetPlayerRaceBit(GetPlayerRaceValue(race_id)))) + if (!(Races & GetPlayerRaceBit(race_id))) return false; if (!(Classes & GetPlayerClassBit(GetPlayerClassValue(class_id)))) From 40845adbaec216a4f4fa464a843363cef3a163a7 Mon Sep 17 00:00:00 2001 From: phredi Date: Tue, 24 May 2016 20:00:54 -0500 Subject: [PATCH 107/693] initial logdir work(incomplete) --- common/eqemu_config.cpp | 7 +++++++ common/eqemu_config.h | 1 + 2 files changed, 8 insertions(+) diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index 6368c8c8f..977593291 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -299,6 +299,13 @@ void EQEmuConfig::do_directories(TiXmlElement *ele) if ( SharedMemDir.back() != '/' ) SharedMemDir += '/'; } + //Not Fully Implemented yet LogDir + text = ParseTextBlock(ele, "logs", true); + if (text) { + LogDir = text; + if ( LogDir.back() != '/' ) + LogDir += '/'; + } } void EQEmuConfig::do_launcher(TiXmlElement *ele) diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 10be15323..38995b796 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -88,6 +88,7 @@ class EQEmuConfig : public XMLParser std::string LuaModuleDir; std::string PatchDir; std::string SharedMemDir; + std::string LogDir; // From std::string LogPrefix; From 11b3571965722b953e95ce64ee6b0e31d03ac3a0 Mon Sep 17 00:00:00 2001 From: phredi Date: Tue, 24 May 2016 20:18:11 -0500 Subject: [PATCH 108/693] small fix for logdir --- common/eqemu_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 38995b796..58b1bee9b 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -169,7 +169,7 @@ class EQEmuConfig : public XMLParser LogDir = "logs/"; // Launcher - LogPrefix = "zone-"; + LogPrefix = "logs/zone-"; LogSuffix = ".log"; RestartWait = 10000; //milliseconds TerminateWait = 10000; //milliseconds From 109de629163790923bf82c218c439da89e4b2064 Mon Sep 17 00:00:00 2001 From: phredi Date: Tue, 24 May 2016 20:45:32 -0500 Subject: [PATCH 109/693] eqemu_config.xml.full update --- utils/defaults/eqemu_config.xml.full | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/defaults/eqemu_config.xml.full b/utils/defaults/eqemu_config.xml.full index b376b199a..3195352c5 100644 --- a/utils/defaults/eqemu_config.xml.full +++ b/utils/defaults/eqemu_config.xml.full @@ -90,5 +90,6 @@ + From 5cd052458a25146c49326de055152be8e7de080b Mon Sep 17 00:00:00 2001 From: phredi Date: Tue, 24 May 2016 21:53:37 -0500 Subject: [PATCH 110/693] fix for bin/tests to compile with configfileupdate --- tests/ipc_mutex_test.h | 3 +++ tests/main.cpp | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/tests/ipc_mutex_test.h b/tests/ipc_mutex_test.h index 69c70ca93..d465f869c 100644 --- a/tests/ipc_mutex_test.h +++ b/tests/ipc_mutex_test.h @@ -21,6 +21,9 @@ #include "cppunit/cpptest.h" #include "../common/ipc_mutex.h" +#include "../common/eqemu_config.h" + +extern const EQEmuConfig *Config; class IPCMutexTest : public Test::Suite { typedef void(IPCMutexTest::*TestFunction)(void); diff --git a/tests/main.cpp b/tests/main.cpp index d64dfead4..44adabbbd 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -29,8 +29,16 @@ #include "string_util_test.h" #include "data_verification_test.h" #include "skills_util_test.h" +#include "../common/eqemu_config.h" + +const EQEmuConfig *Config; int main() { + if(!EQEmuConfig::LoadConfig()) { + std::cout << "Problem loading configuration." << std::endl; + return 1; + } + Config = EQEmuConfig::get(); try { std::ofstream outfile("test_output.txt"); std::unique_ptr output(new Test::TextOutput(Test::TextOutput::Verbose, outfile)); From 455223df1cc57fb911cabfb50aaa4047265542e5 Mon Sep 17 00:00:00 2001 From: phredi Date: Tue, 24 May 2016 22:17:50 -0500 Subject: [PATCH 111/693] fix to pass tests --- tests/main.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/main.cpp b/tests/main.cpp index 44adabbbd..9d72da520 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -34,10 +34,7 @@ const EQEmuConfig *Config; int main() { - if(!EQEmuConfig::LoadConfig()) { - std::cout << "Problem loading configuration." << std::endl; - return 1; - } + auto ConfigLoadResult = EQEmuConfig::LoadConfig(); Config = EQEmuConfig::get(); try { std::ofstream outfile("test_output.txt"); From ca2ad5b049c43870148462e874687db5cda02cb2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 24 May 2016 22:57:12 -0500 Subject: [PATCH 112/693] Add eqemu_config_extern.h to cmake - add header blockers --- common/CMakeLists.txt | 1 + common/eqemu_config_extern.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 5c4f364a9..5bd3e0d27 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -132,6 +132,7 @@ SET(common_headers eqemu_exception.h eqemu_config.h eqemu_config_elements.h + eqemu_config_extern.h eqemu_logsys.h eq_limits.h eq_packet.h diff --git a/common/eqemu_config_extern.h b/common/eqemu_config_extern.h index 1943c5d61..6282f2738 100644 --- a/common/eqemu_config_extern.h +++ b/common/eqemu_config_extern.h @@ -16,7 +16,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifndef EQEMU_CONFIG_EXTERN +#define EQEMU_CONFIG_EXTERN + #include "eqemu_config.h" extern const EQEmuConfig *Config; +#endif \ No newline at end of file From fd693a671b88be9589ce584ecfbb288fdb0e796b Mon Sep 17 00:00:00 2001 From: phredi Date: Tue, 24 May 2016 23:24:49 -0500 Subject: [PATCH 113/693] FreeBSD Compile Fixes --- common/mysql_request_result.h | 6 ++++++ common/useperl.h | 10 ++++++++++ zone/embperl.h | 11 +++++++++++ 3 files changed, 27 insertions(+) diff --git a/common/mysql_request_result.h b/common/mysql_request_result.h index 2944f528b..4b2c56310 100644 --- a/common/mysql_request_result.h +++ b/common/mysql_request_result.h @@ -10,6 +10,12 @@ #include "types.h" #include "mysql_request_row.h" +#ifdef __FreeBSD__ + #include + #include + #include +#endif + class MySQLRequestResult { private: MYSQL_RES* m_Result; diff --git a/common/useperl.h b/common/useperl.h index 3c0bf8f1c..e9a02d604 100644 --- a/common/useperl.h +++ b/common/useperl.h @@ -46,6 +46,16 @@ extern "C" { //the perl headers dont do this for us... #undef THIS #endif +//These need to be cleaned up on FreeBSD +#ifdef __FreeBSD__ +#ifdef do_open +#undef do_open +#endif + +#ifdef do_close +#undef do_close +#endif +#endif #endif /*EMU_PERL_H_*/ diff --git a/zone/embperl.h b/zone/embperl.h index e5d07a3d8..ebd76fa0e 100644 --- a/zone/embperl.h +++ b/zone/embperl.h @@ -54,6 +54,17 @@ extern "C" { //the perl headers dont do this for us... #ifdef Zero #undef Zero #endif +//These need to be cleaned up on FreeBSD + +#ifdef __FreeBSD__ +#ifdef do_open +#undef do_open +#endif + +#ifdef do_close +#undef do_close +#endif +#endif //so embedded scripts can use xs extensions (ala 'use socket;') EXTERN_C void boot_DynaLoader(pTHX_ CV* cv); From 477bf1ba4591f9a436b3f36686d238b64242fb81 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 25 May 2016 01:20:09 -0500 Subject: [PATCH 114/693] Few more windows compile fix adjustments --- common/ipc_mutex.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/ipc_mutex.cpp b/common/ipc_mutex.cpp index 13efd8b0b..c4a8a90c8 100644 --- a/common/ipc_mutex.cpp +++ b/common/ipc_mutex.cpp @@ -18,7 +18,9 @@ #include "ipc_mutex.h" #ifdef _WINDOWS +#define WIN32_LEAN_AND_MEAN #include +#undef WIN32_LEAN_AND_MEAN #else #include #include From c059ff01ba8ba277e7441cafc2f2f14ef0b044d6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 25 May 2016 02:38:06 -0400 Subject: [PATCH 115/693] Nuke unused COLLECTOR defines --- common/eq_stream.cpp | 20 -------------------- common/global_define.h | 10 ++-------- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index 4b231dc9a..9655681b6 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -288,10 +288,8 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) } break; case OP_KeepAlive: { -#ifndef COLLECTOR NonSequencedPush(new EQProtocolPacket(p->opcode,p->pBuffer,p->size)); Log.Out(Logs::Detail, Logs::Netcode, _L "Received and queued reply to keep alive" __L); -#endif } break; case OP_Ack: { @@ -300,14 +298,12 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_Ack that was of malformed size" __L); break; } -#ifndef COLLECTOR uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); AckPackets(seq); if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { retransmittimer = Timer::GetCurrentTime(); } -#endif } break; case OP_SessionRequest: { @@ -316,7 +312,6 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest that was of malformed size" __L); break; } -#ifndef COLLECTOR if (GetState()==ESTABLISHED) { Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest in ESTABLISHED state (%d) streamactive (%i) attempt (%i)" __L, GetState(),streamactive,sessionAttempts); @@ -329,7 +324,6 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) break; } } -#endif sessionAttempts++; // we set established below, so statistics will not be reset for session attempts/stream active. init(GetState()!=ESTABLISHED); @@ -339,10 +333,8 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) SetMaxLen(ntohl(Request->MaxLength)); Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest: session %lu, maxlen %d" __L, (unsigned long)Session, MaxLen); SetState(ESTABLISHED); -#ifndef COLLECTOR Key=0x11223344; SendSessionResponse(); -#endif } break; case OP_SessionResponse: { @@ -408,7 +400,6 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck that was of malformed size" __L); break; } -#ifndef COLLECTOR uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); MOutboundQueue.lock(); @@ -449,7 +440,6 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) } MOutboundQueue.unlock(); -#endif } break; case OP_SessionStatRequest: { @@ -458,7 +448,6 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionStatRequest that was of malformed size" __L); break; } -#ifndef COLLECTOR ClientSessionStats *ClientStats=(ClientSessionStats *)p->pBuffer; Log.Out(Logs::Detail, Logs::Netcode, _L "Received Stats: %lu packets received, %lu packets sent, Deltas: local %lu, (%lu <- %lu -> %lu) remote %lu" __L, (unsigned long)ntohl(ClientStats->packets_received), (unsigned long)ntohl(ClientStats->packets_sent), (unsigned long)ntohl(ClientStats->last_local_delta), @@ -493,7 +482,6 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) ServerStats->packets_received = htonll(GetPacketsReceived()); NonSequencedPush(new EQProtocolPacket(OP_SessionStatResponse, p->pBuffer, p->size)); -#endif } break; case OP_SessionStatResponse: { @@ -612,9 +600,6 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) void EQStream::SequencedPush(EQProtocolPacket *p) { -#ifdef COLLECTOR - delete p; -#else MOutboundQueue.lock(); if (uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, @@ -633,19 +618,14 @@ void EQStream::SequencedPush(EQProtocolPacket *p) } MOutboundQueue.unlock(); -#endif } void EQStream::NonSequencedPush(EQProtocolPacket *p) { -#ifdef COLLECTOR - delete p; -#else MOutboundQueue.lock(); Log.Out(Logs::Detail, Logs::Netcode, _L "Pushing non-sequenced packet of length %d" __L, p->size); NonSequencedQueue.push(p); MOutboundQueue.unlock(); -#endif } void EQStream::SendAck(uint16 seq) diff --git a/common/global_define.h b/common/global_define.h index 0c5d32ee9..e27f313af 100644 --- a/common/global_define.h +++ b/common/global_define.h @@ -16,6 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +// WHY IS THIS UP HERE #if defined(_DEBUG) && defined(WIN32) #ifndef _CRTDBG_MAP_ALLOC #include @@ -26,16 +27,9 @@ #ifndef EQDEBUG_H #define EQDEBUG_H -#define _WINSOCKAPI_ //stupid windows, trying to fix the winsock2 vs. winsock issues -#if defined(WIN32) && ( defined(PACKETCOLLECTOR) || defined(COLLECTOR) ) - // Packet Collector on win32 requires winsock.h due to latest pcap.h - // winsock.h must come before windows.h - #include -#endif - #ifdef _WINDOWS - #include #include + #include #endif #endif From 9894c1b186854f886e8cdef3b2e7b434f5856049 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 24 May 2016 23:49:25 -0700 Subject: [PATCH 116/693] Compile fixes, needs cleaning up --- client_files/export/main.cpp | 3 +-- client_files/import/main.cpp | 3 +-- common/CMakeLists.txt | 1 - common/eqemu_config_extern.h | 26 -------------------------- common/ipc_mutex.cpp | 3 ++- common/patches/rof.cpp | 6 +++--- common/patches/rof.h | 2 -- common/patches/rof2.cpp | 3 +++ common/patches/rof2.h | 2 -- common/patches/sod.cpp | 3 +++ common/patches/sod.h | 2 -- common/patches/sof.cpp | 3 +++ common/patches/sof.h | 2 -- common/patches/titanium.cpp | 3 +++ common/patches/titanium.h | 2 -- common/patches/uf.cpp | 3 +++ common/patches/uf.h | 2 -- common/shareddb.cpp | 8 +++++++- eqlaunch/eqlaunch.cpp | 3 +-- shared_memory/base_data.cpp | 1 + shared_memory/base_data.h | 2 -- shared_memory/items.cpp | 1 + shared_memory/items.h | 2 -- shared_memory/loot.cpp | 1 + shared_memory/loot.h | 2 -- shared_memory/main.cpp | 4 ++-- shared_memory/npc_faction.cpp | 1 + shared_memory/npc_faction.h | 2 -- shared_memory/skill_caps.cpp | 1 + shared_memory/skill_caps.h | 2 -- shared_memory/spells.cpp | 1 + shared_memory/spells.h | 2 -- 32 files changed, 38 insertions(+), 64 deletions(-) delete mode 100644 common/eqemu_config_extern.h diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index 65023d9ce..2eda87411 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -27,7 +27,6 @@ #include "../../common/rulesys.h" #include "../../common/string_util.h" -const EQEmuConfig *Config; EQEmuLogSys Log; void ExportSpells(SharedDatabase *db); @@ -46,7 +45,7 @@ int main(int argc, char **argv) { return 1; } - Config = EQEmuConfig::get(); + auto Config = EQEmuConfig::get(); SharedDatabase database; Log.Out(Logs::General, Logs::Status, "Connecting to database..."); diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index 254d25c42..defd64f98 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -25,7 +25,6 @@ #include "../../common/rulesys.h" #include "../../common/string_util.h" -const EQEmuConfig *Config; EQEmuLogSys Log; void ImportSpells(SharedDatabase *db); @@ -44,7 +43,7 @@ int main(int argc, char **argv) { return 1; } - Config = EQEmuConfig::get(); + auto Config = EQEmuConfig::get(); SharedDatabase database; Log.Out(Logs::General, Logs::Status, "Connecting to database..."); diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 5bd3e0d27..5c4f364a9 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -132,7 +132,6 @@ SET(common_headers eqemu_exception.h eqemu_config.h eqemu_config_elements.h - eqemu_config_extern.h eqemu_logsys.h eq_limits.h eq_packet.h diff --git a/common/eqemu_config_extern.h b/common/eqemu_config_extern.h deleted file mode 100644 index 6282f2738..000000000 --- a/common/eqemu_config_extern.h +++ /dev/null @@ -1,26 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.org) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef EQEMU_CONFIG_EXTERN -#define EQEMU_CONFIG_EXTERN - -#include "eqemu_config.h" - -extern const EQEmuConfig *Config; - -#endif \ No newline at end of file diff --git a/common/ipc_mutex.cpp b/common/ipc_mutex.cpp index c4a8a90c8..0c92e2410 100644 --- a/common/ipc_mutex.cpp +++ b/common/ipc_mutex.cpp @@ -29,7 +29,7 @@ #endif #include "types.h" #include "eqemu_exception.h" -#include "eqemu_config_extern.h" +#include "eqemu_config.h" namespace EQEmu { struct IPCMutex::Implementation { @@ -43,6 +43,7 @@ namespace EQEmu { IPCMutex::IPCMutex(std::string name) : locked_(false) { imp_ = new Implementation; #ifdef _WINDOWS + auto Config = EQEmuConfig::get(); std::string final_name = Config->SharedMemDir + "EQEmuMutex_"; final_name += name; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 856e311a1..0674f06c1 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -31,6 +31,7 @@ #include "../item.h" #include "rof_structs.h" #include "../rulesys.h" +#include "../eqemu_config.h" #include #include @@ -67,6 +68,7 @@ namespace RoF //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file + auto Config = EQEmuConfig::get(); std::string opfile = Config->PatchDir; opfile += "patch_"; opfile += name; @@ -98,9 +100,6 @@ namespace RoF signature.first_length = sizeof(structs::ClientZoneEntry_Struct); signature.first_eq_opcode = opcodes->EmuToEQ(OP_ZoneEntry); into.RegisterPatch(signature, pname.c_str(), &opcodes, &struct_strategy); - - - Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Registered patch %s", name); } @@ -112,6 +111,7 @@ namespace RoF if (opcodes != nullptr) { //TODO: get this file name from the config file + auto Config = EQEmuConfig::get(); std::string opfile = Config->PatchDir; opfile += "patch_"; opfile += name; diff --git a/common/patches/rof.h b/common/patches/rof.h index 31c81fbf7..205998b32 100644 --- a/common/patches/rof.h +++ b/common/patches/rof.h @@ -21,8 +21,6 @@ #define COMMON_ROF_H #include "../struct_strategy.h" -#include "../eqemu_config_extern.h" - class EQStreamIdentifier; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index b4576ed44..cdb5d6c2e 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -31,6 +31,7 @@ #include "../item.h" #include "rof2_structs.h" #include "../rulesys.h" +#include "../eqemu_config.h" #include #include @@ -67,6 +68,7 @@ namespace RoF2 //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file + auto Config = EQEmuConfig::get(); std::string opfile = Config->PatchDir; opfile += "patch_"; opfile += name; @@ -112,6 +114,7 @@ namespace RoF2 if (opcodes != nullptr) { //TODO: get this file name from the config file + auto Config = EQEmuConfig::get(); std::string opfile = Config->PatchDir; opfile += "patch_"; opfile += name; diff --git a/common/patches/rof2.h b/common/patches/rof2.h index 911286977..9eef8e596 100644 --- a/common/patches/rof2.h +++ b/common/patches/rof2.h @@ -21,8 +21,6 @@ #define COMMON_ROF2_H #include "../struct_strategy.h" -#include "../eqemu_config_extern.h" - class EQStreamIdentifier; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 1f1edaf79..a6ecb80a9 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -31,6 +31,7 @@ #include "../item.h" #include "sod_structs.h" #include "../rulesys.h" +#include "../eqemu_config.h" #include #include @@ -63,6 +64,7 @@ namespace SoD //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file + auto Config = EQEmuConfig::get(); std::string opfile = Config->PatchDir; opfile += "patch_"; opfile += name; @@ -108,6 +110,7 @@ namespace SoD if (opcodes != nullptr) { //TODO: get this file name from the config file + auto Config = EQEmuConfig::get(); std::string opfile = Config->PatchDir; opfile += "patch_"; opfile += name; diff --git a/common/patches/sod.h b/common/patches/sod.h index bcd788112..977645231 100644 --- a/common/patches/sod.h +++ b/common/patches/sod.h @@ -21,8 +21,6 @@ #define COMMON_SOD_H #include "../struct_strategy.h" -#include "../eqemu_config_extern.h" - class EQStreamIdentifier; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index debf75621..187d841b0 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -31,6 +31,7 @@ #include "../item.h" #include "sof_structs.h" #include "../rulesys.h" +#include "../eqemu_config.h" #include #include @@ -63,6 +64,7 @@ namespace SoF //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file + auto Config = EQEmuConfig::get(); std::string opfile = Config->PatchDir; opfile += "patch_"; opfile += name; @@ -108,6 +110,7 @@ namespace SoF if (opcodes != nullptr) { //TODO: get this file name from the config file + auto Config = EQEmuConfig::get(); std::string opfile = Config->PatchDir; opfile += "patch_"; opfile += name; diff --git a/common/patches/sof.h b/common/patches/sof.h index 8d8ff287b..dde55f9a3 100644 --- a/common/patches/sof.h +++ b/common/patches/sof.h @@ -21,8 +21,6 @@ #define COMMON_SOF_H #include "../struct_strategy.h" -#include "../eqemu_config_extern.h" - class EQStreamIdentifier; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 6dcca92f5..67c745c78 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -30,6 +30,7 @@ #include "../misc_functions.h" #include "../string_util.h" #include "../item.h" +#include "../eqemu_config.h" #include "titanium_structs.h" #include @@ -59,6 +60,7 @@ namespace Titanium void Register(EQStreamIdentifier &into) { + auto Config = EQEmuConfig::get(); //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file @@ -107,6 +109,7 @@ namespace Titanium if (opcodes != nullptr) { //TODO: get this file name from the config file + auto Config = EQEmuConfig::get(); std::string opfile = Config->PatchDir; opfile += "patch_"; opfile += name; diff --git a/common/patches/titanium.h b/common/patches/titanium.h index ba30712be..2f063c9ad 100644 --- a/common/patches/titanium.h +++ b/common/patches/titanium.h @@ -21,8 +21,6 @@ #define COMMON_TITANIUM_H #include "../struct_strategy.h" -#include "../eqemu_config_extern.h" - class EQStreamIdentifier; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 1baf306c7..9142385ed 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -31,6 +31,7 @@ #include "../item.h" #include "uf_structs.h" #include "../rulesys.h" +#include "../eqemu_config.h" #include #include @@ -63,6 +64,7 @@ namespace UF //create our opcode manager if we havent already if (opcodes == nullptr) { //TODO: get this file name from the config file + auto Config = EQEmuConfig::get(); std::string opfile = Config->PatchDir; opfile += "patch_"; opfile += name; @@ -108,6 +110,7 @@ namespace UF if (opcodes != nullptr) { //TODO: get this file name from the config file + auto Config = EQEmuConfig::get(); std::string opfile = Config->PatchDir; opfile += "patch_"; opfile += name; diff --git a/common/patches/uf.h b/common/patches/uf.h index 8c244367b..c36d9e851 100644 --- a/common/patches/uf.h +++ b/common/patches/uf.h @@ -21,8 +21,6 @@ #define COMMON_UF_H #include "../struct_strategy.h" -#include "../eqemu_config_extern.h" - class EQStreamIdentifier; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 26156a895..968002baa 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -35,8 +35,8 @@ #include "mysql.h" #include "rulesys.h" #include "shareddb.h" -#include "eqemu_config_extern.h" #include "string_util.h" +#include "eqemu_config.h" SharedDatabase::SharedDatabase() : Database() @@ -811,6 +811,7 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { items_mmf.reset(nullptr); try { + auto Config = EQEmuConfig::get(); EQEmu::IPCMutex mutex("items"); mutex.Lock(); std::string file_name = Config->SharedMemDir + prefix + std::string("items"); @@ -1234,6 +1235,7 @@ bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) { faction_hash.reset(nullptr); try { + auto Config = EQEmuConfig::get(); EQEmu::IPCMutex mutex("faction"); mutex.Lock(); std::string file_name = Config->SharedMemDir + prefix + std::string("faction"); @@ -1385,6 +1387,7 @@ bool SharedDatabase::LoadSkillCaps(const std::string &prefix) { uint32 size = (class_count * skill_count * level_count * sizeof(uint16)); try { + auto Config = EQEmuConfig::get(); EQEmu::IPCMutex mutex("skill_caps"); mutex.Lock(); std::string file_name = Config->SharedMemDir + prefix + std::string("skill_caps"); @@ -1540,6 +1543,7 @@ bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const spells_mmf.reset(nullptr); try { + auto Config = EQEmuConfig::get(); EQEmu::IPCMutex mutex("spells"); mutex.Lock(); @@ -1743,6 +1747,7 @@ bool SharedDatabase::LoadBaseData(const std::string &prefix) { base_data_mmf.reset(nullptr); try { + auto Config = EQEmuConfig::get(); EQEmu::IPCMutex mutex("base_data"); mutex.Lock(); @@ -1982,6 +1987,7 @@ bool SharedDatabase::LoadLoot(const std::string &prefix) { loot_drop_mmf.reset(nullptr); try { + auto Config = EQEmuConfig::get(); EQEmu::IPCMutex mutex("loot"); mutex.Lock(); std::string file_name_lt = Config->SharedMemDir + prefix + std::string("loot_table"); diff --git a/eqlaunch/eqlaunch.cpp b/eqlaunch/eqlaunch.cpp index e4b63c6c1..da37b9d3b 100644 --- a/eqlaunch/eqlaunch.cpp +++ b/eqlaunch/eqlaunch.cpp @@ -32,7 +32,6 @@ #include EQEmuLogSys Log; -const EQEmuConfig *Config; bool RunLoops = false; @@ -57,7 +56,7 @@ int main(int argc, char *argv[]) { Log.Out(Logs::Detail, Logs::Launcher, "Loading server configuration failed."); return 1; } - Config = EQEmuConfig::get(); + auto Config = EQEmuConfig::get(); /* * Setup nice signal handlers diff --git a/shared_memory/base_data.cpp b/shared_memory/base_data.cpp index 6c43f4493..557d13ce5 100644 --- a/shared_memory/base_data.cpp +++ b/shared_memory/base_data.cpp @@ -33,6 +33,7 @@ void LoadBaseData(SharedDatabase *database, const std::string &prefix) { uint32 size = records * 16 * sizeof(BaseDataStruct); + auto Config = EQEmuConfig::get(); std::string file_name = Config->SharedMemDir + prefix + std::string("base_data"); EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); diff --git a/shared_memory/base_data.h b/shared_memory/base_data.h index 401b57bd2..81cd8dd1b 100644 --- a/shared_memory/base_data.h +++ b/shared_memory/base_data.h @@ -22,8 +22,6 @@ #include #include "../common/eqemu_config.h" -extern const EQEmuConfig *Config; - class SharedDatabase; void LoadBaseData(SharedDatabase *database, const std::string &prefix); diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index 886050d13..e2fb98f16 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -37,6 +37,7 @@ void LoadItems(SharedDatabase *database, const std::string &prefix) { uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); + auto Config = EQEmuConfig::get(); std::string file_name = Config->SharedMemDir + prefix + std::string("items"); EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); diff --git a/shared_memory/items.h b/shared_memory/items.h index 1d34c9467..47dcbaac9 100644 --- a/shared_memory/items.h +++ b/shared_memory/items.h @@ -22,8 +22,6 @@ #include #include "../common/eqemu_config.h" -extern const EQEmuConfig *Config; - class SharedDatabase; void LoadItems(SharedDatabase *database, const std::string &prefix); diff --git a/shared_memory/loot.cpp b/shared_memory/loot.cpp index a659b05a5..742f373bf 100644 --- a/shared_memory/loot.cpp +++ b/shared_memory/loot.cpp @@ -44,6 +44,7 @@ void LoadLoot(SharedDatabase *database, const std::string &prefix) { (loot_drop_count * sizeof(LootDrop_Struct)) + //loot table headers (loot_drop_entries_count * sizeof(LootDropEntries_Struct)); //number of loot table entries + auto Config = EQEmuConfig::get(); std::string file_name_lt = Config->SharedMemDir + prefix + std::string("loot_table"); std::string file_name_ld = Config->SharedMemDir + prefix + std::string("loot_drop"); diff --git a/shared_memory/loot.h b/shared_memory/loot.h index c9c55895b..694bba7ca 100644 --- a/shared_memory/loot.h +++ b/shared_memory/loot.h @@ -22,8 +22,6 @@ #include #include "../common/eqemu_config.h" -extern const EQEmuConfig *Config; - class SharedDatabase; void LoadLoot(SharedDatabase *database, const std::string &prefix); diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index d37d23bd4..79824251f 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -35,7 +35,7 @@ #include "base_data.h" EQEmuLogSys Log; -const EQEmuConfig *Config; + int main(int argc, char **argv) { RegisterExecutablePlatform(ExePlatformSharedMemory); Log.LoadLogSettingsDefaults(); @@ -47,7 +47,7 @@ int main(int argc, char **argv) { return 1; } - Config = EQEmuConfig::get(); + auto Config = EQEmuConfig::get(); SharedDatabase database; Log.Out(Logs::General, Logs::Status, "Connecting to database..."); diff --git a/shared_memory/npc_faction.cpp b/shared_memory/npc_faction.cpp index 5e8f86cfd..2c6ab0098 100644 --- a/shared_memory/npc_faction.cpp +++ b/shared_memory/npc_faction.cpp @@ -34,6 +34,7 @@ void LoadFactions(SharedDatabase *database, const std::string &prefix) { uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(lists, max_list)); + auto Config = EQEmuConfig::get(); std::string file_name = Config->SharedMemDir + prefix + std::string("faction"); EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); diff --git a/shared_memory/npc_faction.h b/shared_memory/npc_faction.h index 598f8f01b..0b8a047f0 100644 --- a/shared_memory/npc_faction.h +++ b/shared_memory/npc_faction.h @@ -22,8 +22,6 @@ #include #include "../common/eqemu_config.h" -extern const EQEmuConfig *Config; - class SharedDatabase; void LoadFactions(SharedDatabase *database, const std::string &prefix); diff --git a/shared_memory/skill_caps.cpp b/shared_memory/skill_caps.cpp index 6712d75c6..bd8eabb5a 100644 --- a/shared_memory/skill_caps.cpp +++ b/shared_memory/skill_caps.cpp @@ -34,6 +34,7 @@ void LoadSkillCaps(SharedDatabase *database, const std::string &prefix) { uint32 level_count = HARD_LEVEL_CAP + 1; uint32 size = (class_count * skill_count * level_count * sizeof(uint16)); + auto Config = EQEmuConfig::get(); std::string file_name = Config->SharedMemDir + prefix + std::string("skill_caps"); EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); diff --git a/shared_memory/skill_caps.h b/shared_memory/skill_caps.h index 6e35d6fb5..da2cebc51 100644 --- a/shared_memory/skill_caps.h +++ b/shared_memory/skill_caps.h @@ -22,8 +22,6 @@ #include #include "../common/eqemu_config.h" -extern const EQEmuConfig *Config; - class SharedDatabase; void LoadSkillCaps(SharedDatabase *database, const std::string &prefix); diff --git a/shared_memory/spells.cpp b/shared_memory/spells.cpp index 2cb3d846e..c653e26f5 100644 --- a/shared_memory/spells.cpp +++ b/shared_memory/spells.cpp @@ -34,6 +34,7 @@ void LoadSpells(SharedDatabase *database, const std::string &prefix) { uint32 size = records * sizeof(SPDat_Spell_Struct) + sizeof(uint32); + auto Config = EQEmuConfig::get(); std::string file_name = Config->SharedMemDir + prefix + std::string("spells"); EQEmu::MemoryMappedFile mmf(file_name, size); mmf.ZeroFile(); diff --git a/shared_memory/spells.h b/shared_memory/spells.h index 230e3779f..bdda1eac4 100644 --- a/shared_memory/spells.h +++ b/shared_memory/spells.h @@ -22,8 +22,6 @@ #include #include "../common/eqemu_config.h" -extern const EQEmuConfig *Config; - class SharedDatabase; void LoadSpells(SharedDatabase *database, const std::string &prefix); From a9ef83c59703c43fd0ba2e539340674ae4f0e4fe Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 24 May 2016 23:58:19 -0700 Subject: [PATCH 117/693] Missed config cause I'm totes not on gcc right now --- common/ipc_mutex.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/common/ipc_mutex.cpp b/common/ipc_mutex.cpp index 0c92e2410..75e0a63a1 100644 --- a/common/ipc_mutex.cpp +++ b/common/ipc_mutex.cpp @@ -55,6 +55,7 @@ namespace EQEmu { EQ_EXCEPT("IPC Mutex", "Could not create mutex."); } #else + auto Config = EQEmuConfig::get(); std::string final_name = Config->SharedMemDir + name; final_name += ".lock"; From c43d436b1f444b0e7e1f8488a25d1bd8ace98aa8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 25 May 2016 13:46:47 -0400 Subject: [PATCH 118/693] Fix more windows.h/winsock.h/winsock2.h issues We want to use winsock2.h rather than winsock.h. This was mostly enforced from the global_defines.h file, but I wanted to make it consistent. Most of these includes can be removed since they're included via global_defines.h, but someone on windows should clean that up --- common/base_packet.h | 4 ++-- common/dbcore.h | 2 +- common/eq_stream_factory.cpp | 2 +- common/mutex.h | 2 +- common/mysql_request_result.h | 2 +- common/mysql_request_row.h | 2 +- common/ptimer.cpp | 2 +- world/client.cpp | 2 +- world/login_server.cpp | 2 +- world/net.h | 2 +- zone/client_process.cpp | 2 +- zone/net.h | 2 +- zone/tribute.cpp | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/common/base_packet.h b/common/base_packet.h index 16a527ade..bdd774aa2 100644 --- a/common/base_packet.h +++ b/common/base_packet.h @@ -22,10 +22,10 @@ #include #include -#ifdef WIN32 +#ifdef _WINDOWS #include - #include #include + #include #else #include #include diff --git a/common/dbcore.h b/common/dbcore.h index b23d58a9e..6fd09218e 100644 --- a/common/dbcore.h +++ b/common/dbcore.h @@ -2,7 +2,7 @@ #define DBCORE_H #ifdef _WINDOWS - #include + #include #include #endif diff --git a/common/eq_stream_factory.cpp b/common/eq_stream_factory.cpp index ca5596410..bc435ef51 100644 --- a/common/eq_stream_factory.cpp +++ b/common/eq_stream_factory.cpp @@ -3,7 +3,7 @@ #include "eq_stream_factory.h" #ifdef _WINDOWS - #include + #include #include #include #include diff --git a/common/mutex.h b/common/mutex.h index b1a71c331..48f58bcac 100644 --- a/common/mutex.h +++ b/common/mutex.h @@ -18,7 +18,7 @@ #ifndef MYMUTEX_H #define MYMUTEX_H #ifdef _WINDOWS - #include + #include #include #else #include diff --git a/common/mysql_request_result.h b/common/mysql_request_result.h index 2944f528b..e859c6984 100644 --- a/common/mysql_request_result.h +++ b/common/mysql_request_result.h @@ -2,7 +2,7 @@ #define MYSQL_REQUEST_RESULT_H #ifdef _WINDOWS - #include + #include #include #endif diff --git a/common/mysql_request_row.h b/common/mysql_request_row.h index 06788025d..ddfbddee9 100644 --- a/common/mysql_request_row.h +++ b/common/mysql_request_row.h @@ -2,7 +2,7 @@ #define MYSQL_REQUEST_ROW_H #ifdef _WINDOWS - #include + #include #include #endif diff --git a/common/ptimer.cpp b/common/ptimer.cpp index c7f7b9046..273ac54d0 100644 --- a/common/ptimer.cpp +++ b/common/ptimer.cpp @@ -24,8 +24,8 @@ #include "string_util.h" #ifdef _WINDOWS + #include #include - #include int gettimeofday (timeval *tp, ...); #else #include diff --git a/world/client.cpp b/world/client.cpp index 696da355b..7065c79f5 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -61,8 +61,8 @@ // Disgrace: for windows compile #ifdef _WINDOWS + #include #include - #include #else #ifdef FREEBSD //Timothy Whitman - January 7, 2003 diff --git a/world/login_server.cpp b/world/login_server.cpp index 8b17d9bc2..b8c23d573 100644 --- a/world/login_server.cpp +++ b/world/login_server.cpp @@ -25,8 +25,8 @@ #ifdef _WINDOWS #include + #include #include - #include #define snprintf _snprintf #define strncasecmp _strnicmp diff --git a/world/net.h b/world/net.h index b343c8d68..5af1ef96a 100644 --- a/world/net.h +++ b/world/net.h @@ -26,8 +26,8 @@ #else #include #include + #include #include - #include #endif void CatchSignal(int sig_num); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 72dd478c8..e5fd2ec99 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -26,8 +26,8 @@ #include #ifdef _WINDOWS + #include #include - #include #define snprintf _snprintf #define strncasecmp _strnicmp #define strcasecmp _stricmp diff --git a/zone/net.h b/zone/net.h index 8908a3740..4d44b6058 100644 --- a/zone/net.h +++ b/zone/net.h @@ -16,8 +16,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef _WINDOWS + #include #include - #include #else #include #include diff --git a/zone/tribute.cpp b/zone/tribute.cpp index 737b04151..d40dfa6f2 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -25,8 +25,8 @@ #include #ifdef _WINDOWS + #include #include - #include #include #define snprintf _snprintf #define vsnprintf _vsnprintf From cdbeb24a058b9c191017c5c61f08de16b7bec19d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 25 May 2016 14:57:47 -0400 Subject: [PATCH 119/693] Change emptiness checks to empty() from size() [clang-tidy] This has two benefits, it's clear what we are checking and size() isn't always constant time, where empty is (performance!) --- common/eq_stream.cpp | 6 +++--- common/eq_stream_factory.cpp | 2 +- ucs/clientlist.cpp | 4 ++-- world/eqw_parser.cpp | 2 +- zone/aa.cpp | 2 +- zone/client.cpp | 2 +- zone/client_packet.cpp | 2 +- zone/embperl.cpp | 2 +- zone/entity.cpp | 6 +++--- zone/fearpath.cpp | 2 +- zone/merc.cpp | 4 ++-- zone/mob_ai.cpp | 6 +++--- zone/net.cpp | 6 +++--- zone/pathing.cpp | 24 ++++++++++++------------ zone/tasks.cpp | 12 ++++++------ zone/zone.cpp | 8 ++++---- 16 files changed, 45 insertions(+), 45 deletions(-) diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index 9655681b6..00f5b1b9a 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -939,7 +939,7 @@ EQApplicationPacket *EQStream::PopPacket() EQRawApplicationPacket *p=nullptr; MInboundQueue.lock(); - if (InboundQueue.size()) { + if (!InboundQueue.empty()) { std::vector::iterator itr=InboundQueue.begin(); p=*itr; InboundQueue.erase(itr); @@ -964,7 +964,7 @@ EQRawApplicationPacket *EQStream::PopRawPacket() EQRawApplicationPacket *p=nullptr; MInboundQueue.lock(); - if (InboundQueue.size()) { + if (!InboundQueue.empty()) { std::vector::iterator itr=InboundQueue.begin(); p=*itr; InboundQueue.erase(itr); @@ -991,7 +991,7 @@ EQRawApplicationPacket *EQStream::PeekPacket() EQRawApplicationPacket *p=nullptr; MInboundQueue.lock(); - if (InboundQueue.size()) { + if (!InboundQueue.empty()) { std::vector::iterator itr=InboundQueue.begin(); p=*itr; } diff --git a/common/eq_stream_factory.cpp b/common/eq_stream_factory.cpp index bc435ef51..6be3017f0 100644 --- a/common/eq_stream_factory.cpp +++ b/common/eq_stream_factory.cpp @@ -120,7 +120,7 @@ std::shared_ptr EQStreamFactory::Pop() { std::shared_ptr s = nullptr; MNewStreams.lock(); - if (NewStreams.size()) { + if (!NewStreams.empty()) { s = NewStreams.front(); NewStreams.pop(); s->PutInUse(); diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index dc96f31e9..47e0eb726 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -2326,7 +2326,7 @@ void Client::SendFriends() { std::string Client::MailBoxName() { - if((Characters.size() == 0) || (CurrentMailBox > (Characters.size() - 1))) + if((Characters.empty()) || (CurrentMailBox > (Characters.size() - 1))) { Log.Out(Logs::Detail, Logs::UCS_Server, "MailBoxName() called with CurrentMailBox set to %i and Characters.size() is %i", CurrentMailBox, Characters.size()); @@ -2343,7 +2343,7 @@ std::string Client::MailBoxName() { int Client::GetCharID() { - if(Characters.size() == 0) + if(Characters.empty()) return 0; return Characters[0].CharID; diff --git a/world/eqw_parser.cpp b/world/eqw_parser.cpp index 79e73ac22..e01f3db3b 100644 --- a/world/eqw_parser.cpp +++ b/world/eqw_parser.cpp @@ -227,7 +227,7 @@ bool EQWParser::dosub(const char * subname, const std::vector &args ENTER; // everything created after here SAVETMPS; // ...is a temporary variable PUSHMARK(SP); // remember the stack pointer - if(args.size() > 0) + if(!args.empty()) { for (auto i = args.begin(); i != args.end(); ++i) { /* push the arguments onto the perl stack */ XPUSHs(sv_2mortal(newSVpv(i->c_str(), i->length()))); diff --git a/zone/aa.cpp b/zone/aa.cpp index 58d72af55..7828d6654 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1141,7 +1141,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { } //make sure it is not a passive - if(rank->effects.size() > 0) { + if(!rank->effects.empty()) { return; } diff --git a/zone/client.cpp b/zone/client.cpp index 7940cf266..77e5e78d6 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -5333,7 +5333,7 @@ void Client::SendRewards() rewards.push_back(cr); } - if(rewards.size() == 0) + if(rewards.empty()) return; EQApplicationPacket *vetapp = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(InternalVeteranReward) * rewards.size())); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index de35ccf2b..5d11f315e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5656,7 +5656,7 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app) { std::deque pathlist = zone->pathing->FindRoute(Start, End); - if (pathlist.size() == 0) + if (pathlist.empty()) { EQApplicationPacket outapp(OP_FindPersonReply, 0); QueuePacket(&outapp); diff --git a/zone/embperl.cpp b/zone/embperl.cpp index 834a5f0b9..e86a3e187 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -278,7 +278,7 @@ int Embperl::dosub(const char * subname, const std::vector * args, ENTER; SAVETMPS; PUSHMARK(SP); - if(args && args->size()) + if(args && !args->empty()) { for(std::vector::const_iterator i = args->begin(); i != args->end(); ++i) { diff --git a/zone/entity.cpp b/zone/entity.cpp index 4d6ca1459..bdf59d8b0 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2702,7 +2702,7 @@ void EntityList::FindPathsToAllNPCs() glm::vec3 Node0 = zone->pathing->GetPathNodeCoordinates(0, false); glm::vec3 Dest(it->second->GetX(), it->second->GetY(), it->second->GetZ()); std::deque Route = zone->pathing->FindRoute(Node0, Dest); - if (Route.size() == 0) + if (Route.empty()) printf("Unable to find a route to %s\n", it->second->GetName()); else printf("Found a route to %s\n", it->second->GetName()); @@ -4503,7 +4503,7 @@ void EntityList::AddLootToNPCS(uint32 item_id, uint32 count) for (int j = 0; j < npc_count; ++j) selection.push_back(j); - while (selection.size() > 0 && count > 0) { + while (!selection.empty() && count > 0) { int k = zone->random.Int(0, selection.size() - 1); counts[selection[k]]++; count--; @@ -4683,7 +4683,7 @@ Mob *EntityList::GetTargetForVirus(Mob *spreader, int range) ++it; } - if(TargetsInRange.size() == 0) + if(TargetsInRange.empty()) return nullptr; return TargetsInRange[zone->random.Int(0, TargetsInRange.size() - 1)]; diff --git a/zone/fearpath.cpp b/zone/fearpath.cpp index bbcf4d4c6..aa369b4c9 100644 --- a/zone/fearpath.cpp +++ b/zone/fearpath.cpp @@ -137,7 +137,7 @@ void Mob::CalculateNewFearpoint() std::deque Route = zone->pathing->FindRoute(CurrentPosition, Loc); - if(Route.size() > 0) + if(!Route.empty()) { m_FearWalkTarget = glm::vec3(Loc.x, Loc.y, Loc.z); currently_fleeing = true; diff --git a/zone/merc.cpp b/zone/merc.cpp index 840c8ac38..369a8ef4f 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1747,7 +1747,7 @@ void Merc::AI_Start(int32 iMoveDelay) { if (!pAIControlled) return; - if (merc_spells.size() == 0) { + if (merc_spells.empty()) { AIautocastspell_timer->SetTimer(1000); AIautocastspell_timer->Disable(); } else { @@ -4688,7 +4688,7 @@ bool Merc::LoadMercSpells() { return a.slot > b.slot; }); - if (merc_spells.size() == 0) + if (merc_spells.empty()) AIautocastspell_timer->Disable(); else { HasAISpell = true; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index b640da2b0..7958035ab 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -516,7 +516,7 @@ void NPC::AI_Start(uint32 iMoveDelay) { if (!pAIControlled) return; - if (AIspells.size() == 0) { + if (AIspells.empty()) { AIautocastspell_timer = std::unique_ptr(new Timer(1000)); AIautocastspell_timer->Disable(); } else { @@ -679,7 +679,7 @@ void Client::AI_SpellCast() spell_to_cast = valid_spells[0]; slot_to_use = slots[0]; } - else if(valid_spells.size() == 0) + else if(valid_spells.empty()) { return; } @@ -2386,7 +2386,7 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { AISpellVar.idle_no_sp_recast_max = (_idle_no_sp_recast_max) ? _idle_no_sp_recast_max : RuleI(Spells, AI_IdleNoSpellMaxRecast); AISpellVar.idle_beneficial_chance = (_idle_beneficial_chance) ? _idle_beneficial_chance : RuleI(Spells, AI_IdleBeneficialChance); - if (AIspells.size() == 0) + if (AIspells.empty()) AIautocastspell_timer->Disable(); else AIautocastspell_timer->Trigger(); diff --git a/zone/net.cpp b/zone/net.cpp index 5c3996959..b173b67a0 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -133,7 +133,7 @@ int main(int argc, char** argv) { worldserver.SetLauncherName(argv[2]); auto zone_port = SplitString(argv[1], ':'); - if(zone_port.size() > 0) { + if(!zone_port.empty()) { z_name = zone_port[0]; } @@ -153,7 +153,7 @@ int main(int argc, char** argv) { worldserver.SetLauncherName(argv[2]); auto zone_port = SplitString(argv[1], ':'); - if(zone_port.size() > 0) { + if(!zone_port.empty()) { z_name = zone_port[0]; } @@ -172,7 +172,7 @@ int main(int argc, char** argv) { worldserver.SetLauncherName("NONE"); auto zone_port = SplitString(argv[1], ':'); - if(zone_port.size() > 0) { + if(!zone_port.empty()) { z_name = zone_port[0]; } diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 8c4b2e605..8c0271c06 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -224,7 +224,7 @@ std::deque PathManager::FindRoute(int startID, int endID) OpenList.push_back(AStarEntry); - while(OpenList.size() > 0) + while(!OpenList.empty()) { // The OpenList is maintained in sorted order, lowest to highest cost. @@ -610,7 +610,7 @@ void PathManager::MeshTest() std::deque Route = FindRoute(PathNodes[i].id, PathNodes[j].id); - if(Route.size() == 0) + if(Route.empty()) { ++NoConnections; printf("FindRoute(%i, %i) **** NO ROUTE FOUND ****\n", PathNodes[i].id, PathNodes[j].id); @@ -637,7 +637,7 @@ void PathManager::SimpleMeshTest() { std::deque Route = FindRoute(PathNodes[0].id, PathNodes[j].id); - if(Route.size() == 0) + if(Route.empty()) { ++NoConnections; printf("FindRoute(%i, %i) **** NO ROUTE FOUND ****\n", PathNodes[0].id, PathNodes[j].id); @@ -683,7 +683,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa { Log.Out(Logs::Detail, Logs::None, "appears to be stuck. Teleporting them to next position.", GetName()); - if(Route.size() == 0) + if(Route.empty()) { Teleport(To); @@ -715,7 +715,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa PathingLastPosition = From; } - if(Route.size() > 0) + if(!Route.empty()) { // If we are already pathing, and the destination is the same as before ... @@ -790,7 +790,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa WaypointChanged = true; // If there are more nodes on the route, return the coords of the next node - if(Route.size() > 0) + if(!Route.empty()) { NextNode = Route.front(); @@ -799,7 +799,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa // -1 indicates a teleport to the next node Route.pop_front(); - if(Route.size() == 0) + if(Route.empty()) { Log.Out(Logs::Detail, Logs::None, "Missing node after teleport."); return To; @@ -815,7 +815,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa Route.pop_front(); - if(Route.size() == 0) + if(Route.empty()) return To; NextNode = Route.front(); @@ -965,7 +965,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa WaypointChanged = true; - if(Route.size() > 0) + if(!Route.empty()) { NextNode = Route.front(); @@ -974,7 +974,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa // -1 indicates a teleport to the next node Route.pop_front(); - if(Route.size() == 0) + if(Route.empty()) { Log.Out(Logs::Detail, Logs::None, "Missing node after teleport."); return To; @@ -990,7 +990,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa Route.pop_front(); - if(Route.size() == 0) + if(Route.empty()) return To; NextNode = Route.front(); @@ -1061,7 +1061,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa PathingTraversedNodes = 0; - if(Route.size() == 0) + if(Route.empty()) { Log.Out(Logs::Detail, Logs::None, " No route available, running direct."); diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 2c2a1c1b0..8946673a4 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -714,7 +714,7 @@ void ClientTaskState::EnableTask(int characterID, int taskCount, int *tasks) { for(unsigned int i=0; i=MAXTASKSETS)) return 0; - if(TaskSets[TaskSetID].size() == 0) return 0; + if(TaskSets[TaskSetID].empty()) return 0; std::vector::iterator Iterator = TaskSets[TaskSetID].begin(); @@ -865,7 +865,7 @@ int TaskManager::LastTaskInSet(int TaskSetID) { if((TaskSetID<=0) || (TaskSetID>=MAXTASKSETS)) return 0; - if(TaskSets[TaskSetID].size() == 0) return 0; + if(TaskSets[TaskSetID].empty()) return 0; return TaskSets[TaskSetID][TaskSets[TaskSetID].size()-1]; } @@ -874,7 +874,7 @@ int TaskManager::NextTaskInSet(int TaskSetID, int TaskID) { if((TaskSetID<=0) || (TaskSetID>=MAXTASKSETS)) return 0; - if(TaskSets[TaskSetID].size() == 0) return 0; + if(TaskSets[TaskSetID].empty()) return 0; for(unsigned int i=0; i TaskID) return TaskSets[TaskSetID][i]; @@ -927,7 +927,7 @@ void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, i state->EnabledTasks.size()); if((TaskSetID<=0) || (TaskSetID>=MAXTASKSETS)) return; - if(TaskSets[TaskSetID].size() > 0) { + if(!TaskSets[TaskSetID].empty()) { // A TaskID of 0 in a TaskSet indicates that all Tasks in the set are enabled for all players. diff --git a/zone/zone.cpp b/zone/zone.cpp index 5523f1e85..6c58bea65 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -672,13 +672,13 @@ void Zone::Shutdown(bool quite) entity_list.StopMobAI(); std::map::iterator itr; - while(zone->npctable.size()) { + while(!zone->npctable.empty()) { itr=zone->npctable.begin(); delete itr->second; zone->npctable.erase(itr); } - while(zone->merctable.size()) { + while(!zone->merctable.empty()) { itr=zone->merctable.begin(); delete itr->second; zone->merctable.erase(itr); @@ -687,7 +687,7 @@ void Zone::Shutdown(bool quite) zone->adventure_entry_list_flavor.clear(); std::map::iterator itr4; - while(zone->ldon_trap_list.size()) + while(!zone->ldon_trap_list.empty()) { itr4 = zone->ldon_trap_list.begin(); delete itr4->second; @@ -1415,7 +1415,7 @@ bool Zone::Depop(bool StartSpawnTimer) { entity_list.Depop(StartSpawnTimer); /* Refresh npctable (cache), getting current info from database. */ - while(npctable.size()) { + while(!npctable.empty()) { itr = npctable.begin(); delete itr->second; npctable.erase(itr); From 60da544d3a8aca7cf29c84805e3e4bdb1a5b55b6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 25 May 2016 16:10:28 -0400 Subject: [PATCH 120/693] clang-tidy modernize-use-auto --- common/database.cpp | 5 +- common/dbcore.cpp | 4 +- common/emu_tcp_connection.cpp | 31 ++-- common/emu_tcp_server.cpp | 2 +- common/eq_packet.cpp | 6 +- common/eq_stream.cpp | 20 +-- common/eq_stream_factory.cpp | 2 +- common/eq_stream_ident.cpp | 2 +- common/eqdb.cpp | 2 +- common/eqemu_config.cpp | 2 +- common/guild_base.cpp | 30 ++-- common/item.cpp | 4 +- common/packet_dump.cpp | 4 +- common/packet_dump_file.cpp | 4 +- common/patches/rof.cpp | 44 +++--- common/patches/rof2.cpp | 44 +++--- common/patches/sod.cpp | 35 +++-- common/patches/sof.cpp | 18 ++- common/patches/titanium.cpp | 8 +- common/patches/uf.cpp | 44 +++--- common/proc_launcher.cpp | 4 +- common/rulesys.cpp | 4 +- common/shareddb.cpp | 2 +- common/string_util.cpp | 4 +- common/tcp_connection.cpp | 8 +- common/worldconn.cpp | 2 +- eqlaunch/worldserver.cpp | 10 +- eqlaunch/zone_launch.cpp | 2 +- queryserv/database.cpp | 8 +- queryserv/lfguild.cpp | 14 +- zone/aa.cpp | 30 ++-- zone/aggro.cpp | 2 +- zone/attack.cpp | 30 ++-- zone/client.cpp | 240 +++++++++++++++--------------- zone/client_packet.cpp | 242 +++++++++++++++++-------------- zone/client_process.cpp | 37 ++--- zone/command.cpp | 166 ++++++++++----------- zone/corpse.cpp | 58 ++++---- zone/doors.cpp | 15 +- zone/effects.cpp | 2 +- zone/embparser.cpp | 4 +- zone/embperl.cpp | 3 +- zone/entity.cpp | 66 ++++----- zone/exp.cpp | 8 +- zone/forage.cpp | 10 +- zone/groups.cpp | 45 +++--- zone/guild.cpp | 20 ++- zone/guild_mgr.cpp | 124 ++++++++-------- zone/hate_list.cpp | 2 +- zone/horse.cpp | 54 +++---- zone/inventory.cpp | 23 +-- zone/loottables.cpp | 2 +- zone/lua_general.cpp | 10 +- zone/map.cpp | 2 +- zone/merc.cpp | 103 +++++++------ zone/mob.cpp | 52 +++---- zone/mob_ai.cpp | 6 +- zone/net.cpp | 6 +- zone/npc.cpp | 16 +- zone/object.cpp | 56 +++---- zone/pathing.cpp | 42 +++--- zone/perl_entity.cpp | 12 +- zone/perlpacket.cpp | 4 +- zone/petitions.cpp | 6 +- zone/pets.cpp | 4 +- zone/qglobals.cpp | 6 +- zone/queryserv.cpp | 2 +- zone/quest_parser_collection.cpp | 96 ++++++------ zone/questmgr.cpp | 111 +++++++------- zone/raids.cpp | 68 ++++----- zone/raycast_mesh.cpp | 8 +- zone/spawn2.cpp | 10 +- zone/spawngroup.cpp | 16 +- zone/special_attacks.cpp | 4 +- zone/spell_effects.cpp | 27 ++-- zone/spells.cpp | 28 ++-- zone/tasks.cpp | 34 ++--- zone/titles.cpp | 16 +- zone/tradeskills.cpp | 25 ++-- zone/trading.cpp | 201 +++++++++++++------------ zone/trap.cpp | 10 +- zone/water_map.cpp | 4 +- zone/waypoints.cpp | 6 +- zone/worldserver.cpp | 85 ++++++----- zone/zone.cpp | 121 ++++++++-------- zone/zonedb.cpp | 16 +- zone/zoning.cpp | 40 ++--- 87 files changed, 1465 insertions(+), 1340 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index 95895dc5f..fc26cc636 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1474,8 +1474,9 @@ void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { QueryDatabase(query); } -void Database::AddReport(std::string who, std::string against, std::string lines) { - char *escape_str = new char[lines.size()*2+1]; +void Database::AddReport(std::string who, std::string against, std::string lines) +{ + auto escape_str = new char[lines.size() * 2 + 1]; DoEscapeString(escape_str, lines.c_str(), lines.size()); std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", EscapeString(who).c_str(), EscapeString(against).c_str(), escape_str); diff --git a/common/dbcore.cpp b/common/dbcore.cpp index 76e87cde1..0fcaa7678 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -98,14 +98,14 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo pStatus = Error; - char *errorBuffer = new char[MYSQL_ERRMSG_SIZE]; + auto errorBuffer = new char[MYSQL_ERRMSG_SIZE]; snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32)mysql_errno(&mysql), errorBuffer); } - char *errorBuffer = new char[MYSQL_ERRMSG_SIZE]; + auto errorBuffer = new char[MYSQL_ERRMSG_SIZE]; snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); /* Implement Logging at the Root */ diff --git a/common/emu_tcp_connection.cpp b/common/emu_tcp_connection.cpp index da34f1ee7..0a0444c69 100644 --- a/common/emu_tcp_connection.cpp +++ b/common/emu_tcp_connection.cpp @@ -456,21 +456,21 @@ void EmuTCPConnection::SendNetErrorPacket(const char* reason) { std::cout << reason; std::cout << "': " << inet_ntoa(in) << ":" << GetPort() << std::endl; #endif - ServerPacket* pack = new ServerPacket(0); - pack->size = 1; - if (reason) - pack->size += strlen(reason) + 1; - pack->pBuffer = new uchar[pack->size]; - memset(pack->pBuffer, 0, pack->size); - pack->pBuffer[0] = 255; - strcpy((char*) &pack->pBuffer[1], reason); - SendPacket(pack); - safe_delete(pack); + auto pack = new ServerPacket(0); + pack->size = 1; + if (reason) + pack->size += strlen(reason) + 1; + pack->pBuffer = new uchar[pack->size]; + memset(pack->pBuffer, 0, pack->size); + pack->pBuffer[0] = 255; + strcpy((char *)&pack->pBuffer[1], reason); + SendPacket(pack); + safe_delete(pack); } void EmuTCPConnection::RemoveRelay(EmuTCPConnection* relay, bool iSendRelayDisconnect) { if (iSendRelayDisconnect) { - ServerPacket* pack = new ServerPacket(0, 5); + auto pack = new ServerPacket(0, 5); pack->pBuffer[0] = 3; *((uint32*) &pack->pBuffer[1]) = relay->GetRemoteID(); SendPacket(pack); @@ -609,7 +609,7 @@ bool EmuTCPConnection::ProcessReceivedDataAsPackets(char* errbuf) { if (base >= recvbuf_used) { safe_delete_array(recvbuf); } else { - uchar* tmpbuf = new uchar[recvbuf_size - base]; + auto tmpbuf = new uchar[recvbuf_size - base]; memcpy(tmpbuf, &recvbuf[base], recvbuf_used - base); safe_delete_array(recvbuf); recvbuf = tmpbuf; @@ -683,7 +683,7 @@ bool EmuTCPConnection::ProcessReceivedDataAsOldPackets(char* errbuf) { safe_delete_array(recvbuf); } else { - uchar* tmpbuf = new uchar[recvbuf_size - base]; + auto tmpbuf = new uchar[recvbuf_size - base]; memcpy(tmpbuf, &recvbuf[base], recvbuf_used - base); safe_delete_array(recvbuf); recvbuf = tmpbuf; @@ -739,7 +739,8 @@ void EmuTCPConnection::ProcessNetworkLayerPacket(ServerPacket* pack) { SendNetErrorPacket("New RelayClient: illegal on outgoing connection"); break; } - EmuTCPConnection* con = new EmuTCPConnection(Server->GetNextID(), Server, this, *((uint32*) data), *((uint32*) &data[4]), *((uint16*) &data[8])); + auto con = new EmuTCPConnection(Server->GetNextID(), Server, this, *((uint32 *)data), + *((uint32 *)&data[4]), *((uint16 *)&data[8])); Server->AddConnection(con); RelayCount++; break; @@ -787,7 +788,7 @@ bool EmuTCPConnection::SendData(bool &sent_something, char* errbuf) { if(sent_something) keepalive_timer.Start(); else if (TCPMode == modePacket && keepalive_timer.Check()) { - ServerPacket* pack = new ServerPacket(0, 0); + auto pack = new ServerPacket(0, 0); SendPacket(pack); safe_delete(pack); #if TCPN_DEBUG >= 5 diff --git a/common/emu_tcp_server.cpp b/common/emu_tcp_server.cpp index 4509c399f..00a241859 100644 --- a/common/emu_tcp_server.cpp +++ b/common/emu_tcp_server.cpp @@ -24,7 +24,7 @@ void EmuTCPServer::Process() { void EmuTCPServer::CreateNewConnection(uint32 ID, SOCKET in_socket, uint32 irIP, uint16 irPort) { - EmuTCPConnection *conn = new EmuTCPConnection(ID, this, in_socket, irIP, irPort, pOldFormat); + auto conn = new EmuTCPConnection(ID, this, in_socket, irIP, irPort, pOldFormat); AddConnection(conn); } diff --git a/common/eq_packet.cpp b/common/eq_packet.cpp index e01f6a3f8..d7e607d77 100644 --- a/common/eq_packet.cpp +++ b/common/eq_packet.cpp @@ -260,7 +260,7 @@ bool EQProtocolPacket::combine(const EQProtocolPacket *rhs) { bool result=false; if (opcode==OP_Combined && size+rhs->size+5<256) { - unsigned char *tmpbuffer=new unsigned char [size+rhs->size+3]; + auto tmpbuffer = new unsigned char[size + rhs->size + 3]; memcpy(tmpbuffer,pBuffer,size); uint32 offset=size; tmpbuffer[offset++]=rhs->Size(); @@ -270,7 +270,7 @@ bool result=false; pBuffer=tmpbuffer; result=true; } else if (size+rhs->size+7<256) { - unsigned char *tmpbuffer=new unsigned char [size+rhs->size+6]; + auto tmpbuffer = new unsigned char[size + rhs->size + 6]; uint32 offset=0; tmpbuffer[offset++]=Size(); offset+=serialize(tmpbuffer+offset); @@ -457,7 +457,7 @@ EQApplicationPacket *EQApplicationPacket::Copy() const { } EQRawApplicationPacket *EQProtocolPacket::MakeAppPacket() const { - EQRawApplicationPacket *res = new EQRawApplicationPacket(opcode, pBuffer, size); + auto res = new EQRawApplicationPacket(opcode, pBuffer, size); res->copyInfo(this); return(res); } diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index 00f5b1b9a..5a272e201 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -561,12 +561,12 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2) Log.Out(Logs::Detail, Logs::Netcode, _L "Making oversized packet, len %d" __L, p->Size()); - unsigned char *tmpbuff=new unsigned char[p->size+3]; + auto tmpbuff = new unsigned char[p->size + 3]; length=p->serialize(opcode, tmpbuff); if (length != p->Size()) Log.Out(Logs::Detail, Logs::Netcode, _L "Packet adjustment, len %d to %d" __L, p->Size(), length); - EQProtocolPacket *out=new EQProtocolPacket(OP_Fragment,nullptr,MaxLen-4); + auto out = new EQProtocolPacket(OP_Fragment, nullptr, MaxLen - 4); *(uint32 *)(out->pBuffer+2)=htonl(length); used=MaxLen-10; memcpy(out->pBuffer+6,tmpbuff,used); @@ -587,10 +587,10 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) delete[] tmpbuff; } else { - unsigned char *tmpbuff=new unsigned char[p->Size()+3]; + auto tmpbuff = new unsigned char[p->Size() + 3]; length=p->serialize(opcode, tmpbuff+2) + 2; - EQProtocolPacket *out=new EQProtocolPacket(OP_Packet,tmpbuff,length); + auto out = new EQProtocolPacket(OP_Packet, tmpbuff, length); delete[] tmpbuff; SequencedPush(out); @@ -882,7 +882,7 @@ sockaddr_in address; void EQStream::SendSessionResponse() { -EQProtocolPacket *out=new EQProtocolPacket(OP_SessionResponse,nullptr,sizeof(SessionResponse)); + auto out = new EQProtocolPacket(OP_SessionResponse, nullptr, sizeof(SessionResponse)); SessionResponse *Response=(SessionResponse *)out->pBuffer; Response->Session=htonl(Session); Response->MaxLength=htonl(MaxLen); @@ -904,7 +904,7 @@ EQProtocolPacket *out=new EQProtocolPacket(OP_SessionResponse,nullptr,sizeof(Ses void EQStream::SendSessionRequest() { -EQProtocolPacket *out=new EQProtocolPacket(OP_SessionRequest,nullptr,sizeof(SessionRequest)); + auto out = new EQProtocolPacket(OP_SessionRequest, nullptr, sizeof(SessionRequest)); SessionRequest *Request=(SessionRequest *)out->pBuffer; memset(Request,0,sizeof(SessionRequest)); Request->Session=htonl(time(nullptr)); @@ -920,7 +920,7 @@ void EQStream::_SendDisconnect() if(GetState() == CLOSED) return; - EQProtocolPacket *out=new EQProtocolPacket(OP_SessionDisconnect,nullptr,sizeof(uint32)); + auto out = new EQProtocolPacket(OP_SessionDisconnect, nullptr, sizeof(uint32)); *(uint32 *)out->pBuffer=htonl(Session); NonSequencedPush(out); @@ -940,7 +940,7 @@ EQRawApplicationPacket *p=nullptr; MInboundQueue.lock(); if (!InboundQueue.empty()) { - std::vector::iterator itr=InboundQueue.begin(); + auto itr = InboundQueue.begin(); p=*itr; InboundQueue.erase(itr); } @@ -965,7 +965,7 @@ EQRawApplicationPacket *p=nullptr; MInboundQueue.lock(); if (!InboundQueue.empty()) { - std::vector::iterator itr=InboundQueue.begin(); + auto itr = InboundQueue.begin(); p=*itr; InboundQueue.erase(itr); } @@ -992,7 +992,7 @@ EQRawApplicationPacket *p=nullptr; MInboundQueue.lock(); if (!InboundQueue.empty()) { - std::vector::iterator itr=InboundQueue.begin(); + auto itr = InboundQueue.begin(); p=*itr; } MInboundQueue.unlock(); diff --git a/common/eq_stream_factory.cpp b/common/eq_stream_factory.cpp index 6be3017f0..d58995623 100644 --- a/common/eq_stream_factory.cpp +++ b/common/eq_stream_factory.cpp @@ -235,7 +235,7 @@ void EQStreamFactory::CheckTimeout() //give it a little time for everybody to finish with it } else { //everybody is done, we can delete it now - std::map, std::shared_ptr>::iterator temp = stream_itr; + auto temp = stream_itr; ++stream_itr; temp->second = nullptr; Streams.erase(temp); diff --git a/common/eq_stream_ident.cpp b/common/eq_stream_ident.cpp index 4640c75f1..89df25ab2 100644 --- a/common/eq_stream_ident.cpp +++ b/common/eq_stream_ident.cpp @@ -25,7 +25,7 @@ EQStreamIdentifier::~EQStreamIdentifier() { } void EQStreamIdentifier::RegisterPatch(const EQStream::Signature &sig, const char *name, OpcodeManager ** opcodes, const StructStrategy *structs) { - Patch *p = new Patch; + auto p = new Patch; p->signature = sig; p->name = name; p->opcodes = opcodes; diff --git a/common/eqdb.cpp b/common/eqdb.cpp index 2c912afba..a94be7768 100644 --- a/common/eqdb.cpp +++ b/common/eqdb.cpp @@ -63,7 +63,7 @@ EQDBRes * EQDB::query(Const_char *q) { //NOT THREAD SAFE! Const_char *EQDB::escape_string(Const_char *from) { int len = strlen(from); - char *res = new char[len*2+1]; + auto res = new char[len * 2 + 1]; mysql_real_escape_string(mysql_ref,res,from,len); diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index 977593291..900b83787 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -80,7 +80,7 @@ void EQEmuConfig::do_world(TiXmlElement *ele) sprintf(str, "loginserver%i", ++LoginCount); sub_ele = ele->FirstChildElement(str); if (sub_ele) { - LoginConfig* loginconfig = new LoginConfig; + auto loginconfig = new LoginConfig; text = ParseTextBlock(sub_ele, "host", true); if (text) { loginconfig->LoginHost = text; diff --git a/common/guild_base.cpp b/common/guild_base.cpp index aa4f7c509..ed4b508bc 100644 --- a/common/guild_base.cpp +++ b/common/guild_base.cpp @@ -179,7 +179,7 @@ BaseGuildManager::GuildInfo *BaseGuildManager::_CreateGuild(uint32 guild_id, con } //make the new entry and store it into the map. - GuildInfo *info = new GuildInfo; + auto info = new GuildInfo; info->name = guild_name; info->leader_char_id = leader_char_id; info->minstatus = minstatus; @@ -236,9 +236,9 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id) { results = m_db->QueryDatabase(query); //escape our strings. - char *name_esc = new char[info->name.length()*2+1]; - char *motd_esc = new char[info->motd.length()*2+1]; - char *motd_set_esc = new char[info->motd_setter.length()*2+1]; + auto name_esc = new char[info->name.length() * 2 + 1]; + auto motd_esc = new char[info->motd.length() * 2 + 1]; + auto motd_set_esc = new char[info->motd_setter.length() * 2 + 1]; m_db->DoEscapeString(name_esc, info->name.c_str(), info->name.length()); m_db->DoEscapeString(motd_esc, info->motd.c_str(), info->motd.length()); m_db->DoEscapeString(motd_set_esc, info->motd_setter.c_str(), info->motd_setter.length()); @@ -264,7 +264,7 @@ bool BaseGuildManager::_StoreGuildDB(uint32 guild_id) { for(rank = 0; rank <= GUILD_MAX_RANK; rank++) { const RankInfo &rankInfo = info->ranks[rank]; - char *title_esc = new char[rankInfo.name.length()*2+1]; + auto title_esc = new char[rankInfo.name.length() * 2 + 1]; m_db->DoEscapeString(title_esc, rankInfo.name.c_str(), rankInfo.name.length()); query = StringFormat("INSERT INTO guild_ranks " @@ -564,7 +564,7 @@ bool BaseGuildManager::DBRenameGuild(uint32 guild_id, const char* name) { //escape our strings. uint32 len = strlen(name); - char *esc = new char[len*2+1]; + auto esc = new char[len * 2 + 1]; m_db->DoEscapeString(esc, name, len); //insert the new `guilds` entry @@ -636,8 +636,8 @@ bool BaseGuildManager::DBSetGuildMOTD(uint32 guild_id, const char* motd, const c //escape our strings. uint32 len = strlen(motd); uint32 len2 = strlen(setter); - char *esc = new char[len*2+1]; - char *esc_set = new char[len2*2+1]; + auto esc = new char[len * 2 + 1]; + auto esc_set = new char[len2 * 2 + 1]; m_db->DoEscapeString(esc, motd, len); m_db->DoEscapeString(esc_set, setter, len2); @@ -675,7 +675,7 @@ bool BaseGuildManager::DBSetGuildURL(uint32 GuildID, const char* URL) //escape our strings. uint32 len = strlen(URL); - char *esc = new char[len*2+1]; + auto esc = new char[len * 2 + 1]; m_db->DoEscapeString(esc, URL, len); std::string query = StringFormat("UPDATE guilds SET url='%s' WHERE id=%d", esc, GuildID); @@ -709,7 +709,7 @@ bool BaseGuildManager::DBSetGuildChannel(uint32 GuildID, const char* Channel) //escape our strings. uint32 len = strlen(Channel); - char *esc = new char[len*2+1]; + auto esc = new char[len * 2 + 1]; m_db->DoEscapeString(esc, Channel, len); std::string query = StringFormat("UPDATE guilds SET channel='%s' WHERE id=%d", esc, GuildID); @@ -832,7 +832,7 @@ bool BaseGuildManager::DBSetPublicNote(uint32 charid, const char* note) { //escape our strings. uint32 len = strlen(note); - char *esc = new char[len*2+1]; + auto esc = new char[len * 2 + 1]; m_db->DoEscapeString(esc, note, len); //insert the new `guilds` entry @@ -918,8 +918,8 @@ bool BaseGuildManager::GetEntireGuild(uint32 guild_id, std::vectorDoEscapeString(esc, char_name, nl); //load up the rank info for each guild. @@ -994,7 +994,7 @@ uint8 *BaseGuildManager::MakeGuildList(const char *head_name, uint32 &length) co //dynamic structs will make this a lot less painful. length = sizeof(GuildsList_Struct); - uint8 *buffer = new uint8[length]; + auto buffer = new uint8[length]; //a bit little better than memsetting the whole thing... uint32 r,pos; diff --git a/common/item.cpp b/common/item.cpp index c00f137db..054bbda42 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -2119,7 +2119,7 @@ const EQEmu::Item_Struct* ItemInst::GetUnscaledItem() const std::string ItemInst::GetCustomDataString() const { std::string ret_val; - std::map::const_iterator iter = m_custom_data.begin(); + auto iter = m_custom_data.begin(); while (iter != m_custom_data.end()) { if (ret_val.length() > 0) { ret_val += "^"; @@ -2172,7 +2172,7 @@ void ItemInst::SetCustomData(std::string identifier, bool value) { } void ItemInst::DeleteCustomData(std::string identifier) { - std::map::iterator iter = m_custom_data.find(identifier); + auto iter = m_custom_data.find(identifier); if (iter != m_custom_data.end()) { m_custom_data.erase(iter); } diff --git a/common/packet_dump.cpp b/common/packet_dump.cpp index 4ab1fcbef..1e28c2616 100644 --- a/common/packet_dump.cpp +++ b/common/packet_dump.cpp @@ -54,7 +54,7 @@ void DumpPacketHex(const uchar* buf, uint32 size, uint32 cols, uint32 skip) { // Output as HEX char output[4]; int j = 0; - char* ascii = new char[cols+1]; + auto ascii = new char[cols + 1]; memset(ascii, 0, cols+1); uint32 i; for(i=skip; icount); + auto outapp = new EQApplicationPacket( + OP_AltCurrency, sizeof(structs::AltCurrencyPopulate_Struct) + + sizeof(structs::AltCurrencyPopulateEntry_Struct) * populate->count); structs::AltCurrencyPopulate_Struct *out_populate = (structs::AltCurrencyPopulate_Struct*)outapp->pBuffer; out_populate->opcode = populate->opcode; @@ -221,7 +222,7 @@ namespace RoF dest->FastQueuePacket(&outapp, ack_req); } else { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyUpdate_Struct)); memcpy(outapp->pBuffer, emu_buffer, sizeof(AltCurrencyUpdate_Struct)); dest->FastQueuePacket(&outapp, ack_req); } @@ -1046,7 +1047,8 @@ namespace RoF { //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupDisbandYou, sizeof(structs::GroupGeneric_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupDisbandYou, sizeof(structs::GroupGeneric_Struct)); structs::GroupGeneric_Struct *ggs = (structs::GroupGeneric_Struct*)outapp->pBuffer; memcpy(ggs->name1, gjs->yourname, sizeof(ggs->name1)); @@ -1064,7 +1066,8 @@ namespace RoF //if(gjs->action == groupActLeave) // Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupDisbandOther, sizeof(structs::GroupGeneric_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupDisbandOther, sizeof(structs::GroupGeneric_Struct)); structs::GroupGeneric_Struct *ggs = (structs::GroupGeneric_Struct*)outapp->pBuffer; memcpy(ggs->name1, gjs->yourname, sizeof(ggs->name1)); @@ -1101,7 +1104,7 @@ namespace RoF //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Leadername is %s", gu2->leadersname); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupUpdateB, PacketLength); + auto outapp = new EQApplicationPacket(OP_GroupUpdateB, PacketLength); char *Buffer = (char *)outapp->pBuffer; @@ -1167,7 +1170,8 @@ namespace RoF memcpy(eq->membername, emu->membername, sizeof(eq->membername)); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); GroupLeadershipAAUpdate_Struct *GLAAus = (GroupLeadershipAAUpdate_Struct*)outapp->pBuffer; GLAAus->NPCMarkerID = emu->NPCMarkerID; @@ -1637,7 +1641,7 @@ namespace RoF PacketSize += sizeof(structs::MercenaryStance_Struct) * emu->Mercs[r].StanceCount; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataResponse, PacketSize); + auto outapp = new EQApplicationPacket(OP_MercenaryDataResponse, PacketSize); Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercTypeCount); @@ -2025,7 +2029,7 @@ namespace RoF uint32 PacketSize = 40000; // Calculate this later - EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayerProfile, PacketSize); + auto outapp = new EQApplicationPacket(OP_PlayerProfile, PacketSize); outapp->WriteUInt32(0); // Checksum, we will update this later outapp->WriteUInt32(0); // Checksum size, we will update this later @@ -2698,7 +2702,7 @@ namespace RoF Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Player Profile Packet is %i bytes", outapp->GetWritePosition()); - unsigned char *NewBuffer = new unsigned char[outapp->GetWritePosition()]; + auto NewBuffer = new unsigned char[outapp->GetWritePosition()]; memcpy(NewBuffer, outapp->pBuffer, outapp->GetWritePosition()); safe_delete_array(outapp->pBuffer); outapp->pBuffer = NewBuffer; @@ -2720,7 +2724,7 @@ namespace RoF unsigned char * __emu_buffer = inapp->pBuffer; RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer; - EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer; general->action = 8; @@ -2743,7 +2747,7 @@ namespace RoF { RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer; add_member->raidGen.action = in_add_member->raidGen.action; @@ -2763,7 +2767,8 @@ namespace RoF else if (raid_gen->action == 35) { RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) + strlen(inmotd->motd) + 1); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) + + strlen(inmotd->motd) + 1); structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer; outmotd->general.action = inmotd->general.action; @@ -2774,7 +2779,8 @@ namespace RoF else if (raid_gen->action == 14 || raid_gen->action == 30) { RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct)); + auto outapp = + new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct)); structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer; outlaa->action = inlaa->action; @@ -2787,7 +2793,7 @@ namespace RoF { RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer; strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64); strn0cpy(raid_general->player_name, in_raid_general->player_name, 64); @@ -3240,7 +3246,7 @@ namespace RoF return; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ChangeSize, sizeof(ChangeSize_Struct)); + auto outapp = new EQApplicationPacket(OP_ChangeSize, sizeof(ChangeSize_Struct)); ChangeSize_Struct *css = (ChangeSize_Struct *)outapp->pBuffer; @@ -3474,7 +3480,7 @@ namespace RoF in->SetReadPosition(0); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_TaskHistoryReply, OutboundPacketSize); + auto outapp = new EQApplicationPacket(OP_TaskHistoryReply, OutboundPacketSize); outapp->WriteUInt32(in->ReadUInt32()); // Task index outapp->WriteUInt32(in->ReadUInt32()); // Activity count @@ -3786,7 +3792,7 @@ namespace RoF int Count = wars->playercount; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_WhoAllResponse, in->size + (Count * 4)); + auto outapp = new EQApplicationPacket(OP_WhoAllResponse, in->size + (Count * 4)); char *OutBuffer = (char *)outapp->pBuffer; @@ -3961,7 +3967,7 @@ namespace RoF SpawnSize = 3; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); + auto outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); Buffer = (char *)outapp->pBuffer; BufferStart = Buffer; VARSTRUCT_ENCODE_STRING(Buffer, emu->name); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index cdb5d6c2e..8e38d81f2 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -271,8 +271,9 @@ namespace RoF2 if (opcode == 8) { AltCurrencyPopulate_Struct *populate = (AltCurrencyPopulate_Struct*)emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(structs::AltCurrencyPopulate_Struct) - + sizeof(structs::AltCurrencyPopulateEntry_Struct) * populate->count); + auto outapp = new EQApplicationPacket( + OP_AltCurrency, sizeof(structs::AltCurrencyPopulate_Struct) + + sizeof(structs::AltCurrencyPopulateEntry_Struct) * populate->count); structs::AltCurrencyPopulate_Struct *out_populate = (structs::AltCurrencyPopulate_Struct*)outapp->pBuffer; out_populate->opcode = populate->opcode; @@ -290,7 +291,7 @@ namespace RoF2 dest->FastQueuePacket(&outapp, ack_req); } else { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyUpdate_Struct)); memcpy(outapp->pBuffer, emu_buffer, sizeof(AltCurrencyUpdate_Struct)); dest->FastQueuePacket(&outapp, ack_req); } @@ -1120,7 +1121,8 @@ namespace RoF2 { //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupDisbandYou, sizeof(structs::GroupGeneric_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupDisbandYou, sizeof(structs::GroupGeneric_Struct)); structs::GroupGeneric_Struct *ggs = (structs::GroupGeneric_Struct*)outapp->pBuffer; memcpy(ggs->name1, gjs->yourname, sizeof(ggs->name1)); @@ -1138,7 +1140,8 @@ namespace RoF2 //if(gjs->action == groupActLeave) // Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupDisbandOther, sizeof(structs::GroupGeneric_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupDisbandOther, sizeof(structs::GroupGeneric_Struct)); structs::GroupGeneric_Struct *ggs = (structs::GroupGeneric_Struct*)outapp->pBuffer; memcpy(ggs->name1, gjs->yourname, sizeof(ggs->name1)); @@ -1175,7 +1178,7 @@ namespace RoF2 //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Leadername is %s", gu2->leadersname); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupUpdateB, PacketLength); + auto outapp = new EQApplicationPacket(OP_GroupUpdateB, PacketLength); char *Buffer = (char *)outapp->pBuffer; @@ -1241,7 +1244,8 @@ namespace RoF2 memcpy(eq->membername, emu->membername, sizeof(eq->membername)); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); GroupLeadershipAAUpdate_Struct *GLAAus = (GroupLeadershipAAUpdate_Struct*)outapp->pBuffer; GLAAus->NPCMarkerID = emu->NPCMarkerID; @@ -1712,7 +1716,7 @@ namespace RoF2 PacketSize += sizeof(structs::MercenaryStance_Struct) * emu->Mercs[r].StanceCount; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataResponse, PacketSize); + auto outapp = new EQApplicationPacket(OP_MercenaryDataResponse, PacketSize); Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercTypeCount); @@ -2109,7 +2113,7 @@ namespace RoF2 uint32 PacketSize = 40000; // Calculate this later - EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayerProfile, PacketSize); + auto outapp = new EQApplicationPacket(OP_PlayerProfile, PacketSize); outapp->WriteUInt32(0); // Checksum, we will update this later outapp->WriteUInt32(0); // Checksum size, we will update this later @@ -2792,7 +2796,7 @@ namespace RoF2 Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Player Profile Packet is %i bytes", outapp->GetWritePosition()); - unsigned char *NewBuffer = new unsigned char[outapp->GetWritePosition()]; + auto NewBuffer = new unsigned char[outapp->GetWritePosition()]; memcpy(NewBuffer, outapp->pBuffer, outapp->GetWritePosition()); safe_delete_array(outapp->pBuffer); outapp->pBuffer = NewBuffer; @@ -2814,7 +2818,7 @@ namespace RoF2 unsigned char * __emu_buffer = inapp->pBuffer; RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer; - EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer; general->action = 8; @@ -2837,7 +2841,7 @@ namespace RoF2 { RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer; add_member->raidGen.action = in_add_member->raidGen.action; @@ -2857,7 +2861,8 @@ namespace RoF2 else if (raid_gen->action == 35) { RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) + strlen(inmotd->motd) + 1); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) + + strlen(inmotd->motd) + 1); structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer; outmotd->general.action = inmotd->general.action; @@ -2868,7 +2873,8 @@ namespace RoF2 else if (raid_gen->action == 14 || raid_gen->action == 30) { RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct)); + auto outapp = + new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct)); structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer; outlaa->action = inlaa->action; @@ -2881,7 +2887,7 @@ namespace RoF2 { RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer; strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64); strn0cpy(raid_general->player_name, in_raid_general->player_name, 64); @@ -3315,7 +3321,7 @@ namespace RoF2 return; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ChangeSize, sizeof(ChangeSize_Struct)); + auto outapp = new EQApplicationPacket(OP_ChangeSize, sizeof(ChangeSize_Struct)); ChangeSize_Struct *css = (ChangeSize_Struct *)outapp->pBuffer; @@ -3549,7 +3555,7 @@ namespace RoF2 in->SetReadPosition(0); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_TaskHistoryReply, OutboundPacketSize); + auto outapp = new EQApplicationPacket(OP_TaskHistoryReply, OutboundPacketSize); outapp->WriteUInt32(in->ReadUInt32()); // Task index outapp->WriteUInt32(in->ReadUInt32()); // Activity count @@ -3936,7 +3942,7 @@ namespace RoF2 int Count = wars->playercount; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_WhoAllResponse, in->size + (Count * 4)); + auto outapp = new EQApplicationPacket(OP_WhoAllResponse, in->size + (Count * 4)); char *OutBuffer = (char *)outapp->pBuffer; @@ -4122,7 +4128,7 @@ namespace RoF2 SpawnSize = 3; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); + auto outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); Buffer = (char *)outapp->pBuffer; BufferStart = Buffer; VARSTRUCT_ENCODE_STRING(Buffer, emu->name); diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index a6ecb80a9..244e63c71 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -778,7 +778,8 @@ namespace SoD { //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupDisbandYou, sizeof(structs::GroupGeneric_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupDisbandYou, sizeof(structs::GroupGeneric_Struct)); structs::GroupGeneric_Struct *ggs = (structs::GroupGeneric_Struct*)outapp->pBuffer; memcpy(ggs->name1, gjs->yourname, sizeof(ggs->name1)); @@ -796,7 +797,8 @@ namespace SoD //if(gjs->action == groupActLeave) // Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupDisbandOther, sizeof(structs::GroupGeneric_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupDisbandOther, sizeof(structs::GroupGeneric_Struct)); structs::GroupGeneric_Struct *ggs = (structs::GroupGeneric_Struct*)outapp->pBuffer; memcpy(ggs->name1, gjs->yourname, sizeof(ggs->name1)); @@ -833,7 +835,7 @@ namespace SoD //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Leadername is %s", gu2->leadersname); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupUpdateB, PacketLength); + auto outapp = new EQApplicationPacket(OP_GroupUpdateB, PacketLength); char *Buffer = (char *)outapp->pBuffer; // Header @@ -897,7 +899,8 @@ namespace SoD memcpy(eq->membername, emu->membername, sizeof(eq->membername)); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); GroupLeadershipAAUpdate_Struct *GLAAus = (GroupLeadershipAAUpdate_Struct*)outapp->pBuffer; GLAAus->NPCMarkerID = emu->NPCMarkerID; @@ -1160,7 +1163,7 @@ namespace SoD PacketSize += sizeof(structs::MercenaryStance_Struct) * emu->Mercs[r].StanceCount; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataResponse, PacketSize); + auto outapp = new EQApplicationPacket(OP_MercenaryDataResponse, PacketSize); Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercTypeCount); @@ -1772,7 +1775,7 @@ namespace SoD unsigned char * __emu_buffer = inapp->pBuffer; RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer; - EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer; general->action = 8; @@ -1795,7 +1798,7 @@ namespace SoD { RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer; add_member->raidGen.action = in_add_member->raidGen.action; @@ -1815,7 +1818,8 @@ namespace SoD else if (raid_gen->action == 35) { RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) + strlen(inmotd->motd) + 1); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) + + strlen(inmotd->motd) + 1); structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer; outmotd->general.action = inmotd->general.action; @@ -1826,7 +1830,8 @@ namespace SoD else if (raid_gen->action == 14 || raid_gen->action == 30) { RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct)); + auto outapp = + new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct)); structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer; outlaa->action = inlaa->action; @@ -1839,7 +1844,7 @@ namespace SoD { RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer; strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64); strn0cpy(raid_general->player_name, in_raid_general->player_name, 64); @@ -1873,7 +1878,8 @@ namespace SoD *p = nullptr; AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability)); + auto outapp = new EQApplicationPacket( + OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability)); structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer; inapp->SetReadPosition(sizeof(AARankInfo_Struct)); @@ -2372,7 +2378,8 @@ namespace SoD uint32 count = ((*p)->Size() / sizeof(InternalVeteranReward)); *p = nullptr; - EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward)*count)); + auto outapp_create = + new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward) * count)); uchar *old_data = __emu_buffer; uchar *data = outapp_create->pBuffer; for (unsigned int i = 0; i < count; ++i) @@ -2424,7 +2431,7 @@ namespace SoD int Count = wars->playercount; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_WhoAllResponse, in->size + (Count * 4)); + auto outapp = new EQApplicationPacket(OP_WhoAllResponse, in->size + (Count * 4)); char *OutBuffer = (char *)outapp->pBuffer; @@ -2589,7 +2596,7 @@ namespace SoD SpawnSize = 3; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); + auto outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_STRING(Buffer, emu->name); diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 187d841b0..5ea473904 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1431,7 +1431,7 @@ namespace SoF unsigned char * __emu_buffer = inapp->pBuffer; RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer; - EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer; general->action = 8; @@ -1454,7 +1454,7 @@ namespace SoF { RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer; add_member->raidGen.action = in_add_member->raidGen.action; @@ -1474,7 +1474,8 @@ namespace SoF else if (raid_gen->action == 35) { RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) + strlen(inmotd->motd) + 1); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) + + strlen(inmotd->motd) + 1); structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer; outmotd->general.action = inmotd->general.action; @@ -1485,7 +1486,8 @@ namespace SoF else if (raid_gen->action == 14 || raid_gen->action == 30) { RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct)); + auto outapp = + new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct)); structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer; outlaa->action = inlaa->action; @@ -1498,7 +1500,7 @@ namespace SoF { RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer; strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64); strn0cpy(raid_general->player_name, in_raid_general->player_name, 64); @@ -1532,7 +1534,8 @@ namespace SoF *p = nullptr; AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability)); + auto outapp = new EQApplicationPacket( + OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability)); structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer; inapp->SetReadPosition(sizeof(AARankInfo_Struct)); @@ -1958,7 +1961,8 @@ namespace SoF uint32 count = ((*p)->Size() / sizeof(InternalVeteranReward)); *p = nullptr; - EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward)*count)); + auto outapp_create = + new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward) * count)); uchar *old_data = __emu_buffer; uchar *data = outapp_create->pBuffer; for (uint32 i = 0; i < count; ++i) diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 67c745c78..3cde09beb 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -793,7 +793,7 @@ namespace Titanium return; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LFGuild, sizeof(structs::LFGuild_PlayerToggle_Struct)); + auto outapp = new EQApplicationPacket(OP_LFGuild, sizeof(structs::LFGuild_PlayerToggle_Struct)); memcpy(outapp->pBuffer, in->pBuffer, sizeof(structs::LFGuild_PlayerToggle_Struct)); @@ -1151,7 +1151,8 @@ namespace Titanium *p = nullptr; AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability)); + auto outapp = new EQApplicationPacket( + OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability)); structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer; inapp->SetReadPosition(sizeof(AARankInfo_Struct)); @@ -1479,7 +1480,8 @@ namespace Titanium uint32 count = ((*p)->Size() / sizeof(InternalVeteranReward)); *p = nullptr; - EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward)*count)); + auto outapp_create = + new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward) * count)); uchar *old_data = __emu_buffer; uchar *data = outapp_create->pBuffer; for (uint32 i = 0; i < count; ++i) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 9142385ed..d07914cb8 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -207,8 +207,9 @@ namespace UF if (opcode == 8) { AltCurrencyPopulate_Struct *populate = (AltCurrencyPopulate_Struct*)emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(structs::AltCurrencyPopulate_Struct) - + sizeof(structs::AltCurrencyPopulateEntry_Struct) * populate->count); + auto outapp = new EQApplicationPacket( + OP_AltCurrency, sizeof(structs::AltCurrencyPopulate_Struct) + + sizeof(structs::AltCurrencyPopulateEntry_Struct) * populate->count); structs::AltCurrencyPopulate_Struct *out_populate = (structs::AltCurrencyPopulate_Struct*)outapp->pBuffer; out_populate->opcode = populate->opcode; @@ -225,7 +226,7 @@ namespace UF dest->FastQueuePacket(&outapp, ack_req); } else { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyUpdate_Struct)); memcpy(outapp->pBuffer, emu_buffer, sizeof(AltCurrencyUpdate_Struct)); dest->FastQueuePacket(&outapp, ack_req); } @@ -937,7 +938,8 @@ namespace UF { //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupDisbandYou, sizeof(structs::GroupGeneric_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupDisbandYou, sizeof(structs::GroupGeneric_Struct)); structs::GroupGeneric_Struct *ggs = (structs::GroupGeneric_Struct*)outapp->pBuffer; memcpy(ggs->name1, gjs->yourname, sizeof(ggs->name1)); @@ -956,7 +958,8 @@ namespace UF //if(gjs->action == groupActLeave) // Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupDisbandOther, sizeof(structs::GroupGeneric_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupDisbandOther, sizeof(structs::GroupGeneric_Struct)); structs::GroupGeneric_Struct *ggs = (structs::GroupGeneric_Struct*)outapp->pBuffer; memcpy(ggs->name1, gjs->yourname, sizeof(ggs->name1)); @@ -993,7 +996,7 @@ namespace UF //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Leadername is %s", gu2->leadersname); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupUpdateB, PacketLength); + auto outapp = new EQApplicationPacket(OP_GroupUpdateB, PacketLength); char *Buffer = (char *)outapp->pBuffer; @@ -1057,7 +1060,8 @@ namespace UF memcpy(eq->membername, emu->membername, sizeof(eq->membername)); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); GroupLeadershipAAUpdate_Struct *GLAAus = (GroupLeadershipAAUpdate_Struct*)outapp->pBuffer; GLAAus->NPCMarkerID = emu->NPCMarkerID; @@ -1397,7 +1401,7 @@ namespace UF PacketSize += sizeof(structs::MercenaryStance_Struct) * emu->Mercs[r].StanceCount; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataResponse, PacketSize); + auto outapp = new EQApplicationPacket(OP_MercenaryDataResponse, PacketSize); Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercTypeCount); @@ -2039,7 +2043,7 @@ namespace UF unsigned char * __emu_buffer = inapp->pBuffer; RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer; - EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + auto outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer; general->action = 8; @@ -2062,7 +2066,7 @@ namespace UF { RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer; add_member->raidGen.action = in_add_member->raidGen.action; @@ -2082,7 +2086,8 @@ namespace UF else if (raid_gen->action == 35) { RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) + strlen(inmotd->motd) + 1); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) + + strlen(inmotd->motd) + 1); structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer; outmotd->general.action = inmotd->general.action; @@ -2093,7 +2098,8 @@ namespace UF else if (raid_gen->action == 14 || raid_gen->action == 30) { RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct)); + auto outapp = + new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct)); structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer; outlaa->action = inlaa->action; @@ -2106,7 +2112,7 @@ namespace UF { RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer; strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64); strn0cpy(raid_general->player_name, in_raid_general->player_name, 64); @@ -2161,7 +2167,8 @@ namespace UF *p = nullptr; AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability)); + auto outapp = new EQApplicationPacket( + OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability)); structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer; inapp->SetReadPosition(sizeof(AARankInfo_Struct)); @@ -2406,7 +2413,7 @@ namespace UF return; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ChangeSize, sizeof(ChangeSize_Struct)); + auto outapp = new EQApplicationPacket(OP_ChangeSize, sizeof(ChangeSize_Struct)); ChangeSize_Struct *css = (ChangeSize_Struct *)outapp->pBuffer; css->EntityID = sas->spawn_id; @@ -2650,7 +2657,8 @@ namespace UF uint32 count = ((*p)->Size() / sizeof(InternalVeteranReward)); *p = nullptr; - EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward)*count)); + auto outapp_create = + new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward) * count)); uchar *old_data = __emu_buffer; uchar *data = outapp_create->pBuffer; for (unsigned int i = 0; i < count; ++i) @@ -2702,7 +2710,7 @@ namespace UF int Count = wars->playercount; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_WhoAllResponse, in->size + (Count * 4)); + auto outapp = new EQApplicationPacket(OP_WhoAllResponse, in->size + (Count * 4)); char *OutBuffer = (char *)outapp->pBuffer; @@ -2864,7 +2872,7 @@ namespace UF SpawnSize = 3; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); + auto outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_STRING(Buffer, emu->name); diff --git a/common/proc_launcher.cpp b/common/proc_launcher.cpp index d44cc9c46..b59f4e852 100644 --- a/common/proc_launcher.cpp +++ b/common/proc_launcher.cpp @@ -212,7 +212,7 @@ ProcLauncher::ProcRef ProcLauncher::Launch(Spec *&to_launch) { #else //!WIN32 //build argv - char **argv = new char *[it->args.size()+2]; + auto argv = new char *[it->args.size() + 2]; unsigned int r; argv[0] = const_cast(it->program.c_str()); for(r = 1; r <= it->args.size(); r++) { @@ -276,7 +276,7 @@ ProcLauncher::ProcRef ProcLauncher::Launch(Spec *&to_launch) { //if graceful is true, we try to be nice about it if possible bool ProcLauncher::Terminate(const ProcRef &proc, bool graceful) { //we are only willing to kill things we started... - std::map::iterator res = m_running.find(proc); + auto res = m_running.find(proc); if(res == m_running.end()) return(false); diff --git a/common/rulesys.cpp b/common/rulesys.cpp index 56289b09a..770a1ab97 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -307,7 +307,7 @@ void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) { int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) { uint32 len = strlen(ruleset_name); - char* rst = new char[2 * len + 1]; + auto rst = new char[2 * len + 1]; database->DoEscapeString(rst, ruleset_name, len); std::string query = StringFormat("SELECT ruleset_id FROM rule_sets WHERE name='%s'", rst); @@ -331,7 +331,7 @@ int RuleManager::_FindOrCreateRuleset(Database *database, const char *in_ruleset return ruleset_id; //found and existing one... uint32 len = strlen(in_ruleset_name); - char* ruleset_name = new char[2 * len + 1]; + auto ruleset_name = new char[2 * len + 1]; database->DoEscapeString(ruleset_name, in_ruleset_name, len); std::string query = StringFormat("INSERT INTO rule_sets (ruleset_id, name) VALUES(0, '%s')", ruleset_name); diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 968002baa..e8046167b 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1368,7 +1368,7 @@ bool SharedDatabase::GetCommandSettings(std::map aliases = SplitString(row[2], '|'); - for (std::vector::iterator iter = aliases.begin(); iter != aliases.end(); ++iter) { + for (auto iter = aliases.begin(); iter != aliases.end(); ++iter) { if (iter->empty()) continue; command_settings[row[0]].second.push_back(*iter); diff --git a/common/string_util.cpp b/common/string_util.cpp index 96cfce310..b5717c1b7 100644 --- a/common/string_util.cpp +++ b/common/string_util.cpp @@ -288,7 +288,7 @@ void RemoveApostrophes(std::string &s) char *RemoveApostrophes(const char *s) { - char *NewString = new char[strlen(s) + 1]; + auto NewString = new char[strlen(s) + 1]; strcpy(NewString, s); @@ -452,7 +452,7 @@ uchar* EQEmu::OutBuffer::detach() if (buffer_size == 0) return nullptr; - uchar* out_buffer = new uchar[buffer_size]; + auto out_buffer = new uchar[buffer_size]; memcpy(out_buffer, str().c_str(), buffer_size); flush(); diff --git a/common/tcp_connection.cpp b/common/tcp_connection.cpp index aa687cc01..d13cf89cc 100644 --- a/common/tcp_connection.cpp +++ b/common/tcp_connection.cpp @@ -187,7 +187,7 @@ void TCPConnection::ServerSendQueuePushEnd(const uchar* data, int32 size) { } else if (size > (sendbuf_size - sendbuf_used)) { sendbuf_size += size + 1024; - uchar* tmp = new uchar[sendbuf_size]; + auto tmp = new uchar[sendbuf_size]; memcpy(tmp, sendbuf, sendbuf_used); safe_delete_array(sendbuf); sendbuf = tmp; @@ -209,7 +209,7 @@ void TCPConnection::ServerSendQueuePushEnd(uchar** data, int32 size) { } if (size > (sendbuf_size - sendbuf_used)) { sendbuf_size += size; - uchar* tmp = new uchar[sendbuf_size]; + auto tmp = new uchar[sendbuf_size]; memcpy(tmp, sendbuf, sendbuf_used); safe_delete_array(sendbuf); sendbuf = tmp; @@ -229,7 +229,7 @@ void TCPConnection::ServerSendQueuePushFront(uchar* data, int32 size) { } else if (size > (sendbuf_size - sendbuf_used)) { sendbuf_size += size; - uchar* tmp = new uchar[sendbuf_size]; + auto tmp = new uchar[sendbuf_size]; memcpy(&tmp[size], sendbuf, sendbuf_used); safe_delete_array(sendbuf); sendbuf = tmp; @@ -608,7 +608,7 @@ bool TCPConnection::RecvData(char* errbuf) { recvbuf_echo = 0; } else if ((recvbuf_size - recvbuf_used) < 2048) { - uchar* tmpbuf = new uchar[recvbuf_size + 5120]; + auto tmpbuf = new uchar[recvbuf_size + 5120]; memcpy(tmpbuf, recvbuf, recvbuf_used); recvbuf_size += 5120; safe_delete_array(recvbuf); diff --git a/common/worldconn.cpp b/common/worldconn.cpp index e85d24a75..432148f89 100644 --- a/common/worldconn.cpp +++ b/common/worldconn.cpp @@ -46,7 +46,7 @@ void WorldConnection::OnConnected() { const EQEmuConfig *Config=EQEmuConfig::get(); Log.Out(Logs::General, Logs::Netcode, "[WORLD] Connected to World: %s:%d", Config->WorldIP.c_str(), Config->WorldTCPPort); - ServerPacket* pack = new ServerPacket(ServerOP_ZAAuth, 16); + auto pack = new ServerPacket(ServerOP_ZAAuth, 16); MD5::Generate((const uchar*) m_password.c_str(), m_password.length(), pack->pBuffer); SendPacket(pack); safe_delete(pack); diff --git a/eqlaunch/worldserver.cpp b/eqlaunch/worldserver.cpp index c1bc0fc42..37c963eb3 100644 --- a/eqlaunch/worldserver.cpp +++ b/eqlaunch/worldserver.cpp @@ -38,7 +38,7 @@ WorldServer::~WorldServer() { void WorldServer::OnConnected() { WorldConnection::OnConnected(); - ServerPacket* pack = new ServerPacket(ServerOP_LauncherConnectInfo, sizeof(LauncherConnectInfo)); + auto pack = new ServerPacket(ServerOP_LauncherConnectInfo, sizeof(LauncherConnectInfo)); LauncherConnectInfo* sci = (LauncherConnectInfo*) pack->pBuffer; strn0cpy(sci->name, m_name, sizeof(sci->name)); // sci->port = net.GetZonePort(); @@ -92,13 +92,13 @@ void WorldServer::Process() { Log.Out(Logs::Detail, Logs::Launcher, "World told us to start zone %s, but it is already running.", lzr->short_name); } else { Log.Out(Logs::Detail, Logs::Launcher, "World told us to start zone %s.", lzr->short_name); - ZoneLaunch *l = new ZoneLaunch(this, m_name, lzr->short_name, lzr->port, m_config); + auto l = new ZoneLaunch(this, m_name, lzr->short_name, lzr->port, m_config); m_zones[lzr->short_name] = l; } break; } case ZR_Restart: { - std::map::iterator res = m_zones.find(lzr->short_name); + auto res = m_zones.find(lzr->short_name); if(res == m_zones.end()) { Log.Out(Logs::Detail, Logs::Launcher, "World told us to restart zone %s, but it is not running.", lzr->short_name); } else { @@ -108,7 +108,7 @@ void WorldServer::Process() { break; } case ZR_Stop: { - std::map::iterator res = m_zones.find(lzr->short_name); + auto res = m_zones.find(lzr->short_name); if(res == m_zones.end()) { Log.Out(Logs::Detail, Logs::Launcher, "World told us to stop zone %s, but it is not running.", lzr->short_name); } else { @@ -137,7 +137,7 @@ void WorldServer::Process() { void WorldServer::SendStatus(const char *short_name, uint32 start_count, bool running) { - ServerPacket* pack = new ServerPacket(ServerOP_LauncherZoneStatus, sizeof(LauncherZoneStatus)); + auto pack = new ServerPacket(ServerOP_LauncherZoneStatus, sizeof(LauncherZoneStatus)); LauncherZoneStatus* it =(LauncherZoneStatus*) pack->pBuffer; strn0cpy(it->short_name, short_name, 32); diff --git a/eqlaunch/zone_launch.cpp b/eqlaunch/zone_launch.cpp index 974cf5b3d..7af96c59f 100644 --- a/eqlaunch/zone_launch.cpp +++ b/eqlaunch/zone_launch.cpp @@ -60,7 +60,7 @@ void ZoneLaunch::SendStatus() const { } void ZoneLaunch::Start() { - ProcLauncher::Spec *spec = new ProcLauncher::Spec(); + auto spec = new ProcLauncher::Spec(); spec->program = m_config->ZoneExe; if(m_port) { diff --git a/queryserv/database.cpp b/queryserv/database.cpp index 2e86c449f..6216e112d 100644 --- a/queryserv/database.cpp +++ b/queryserv/database.cpp @@ -100,9 +100,9 @@ Database::~Database() void Database::AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type) { - char *escapedFrom = new char[strlen(from) * 2 + 1]; - char *escapedTo = new char[strlen(to) * 2 + 1]; - char *escapedMessage = new char[strlen(message) * 2 + 1]; + auto escapedFrom = new char[strlen(from) * 2 + 1]; + auto escapedTo = new char[strlen(to) * 2 + 1]; + auto escapedMessage = new char[strlen(message) * 2 + 1]; DoEscapeString(escapedFrom, from, strlen(from)); DoEscapeString(escapedTo, to, strlen(to)); DoEscapeString(escapedMessage, message, strlen(message)); @@ -350,7 +350,7 @@ void Database::GeneralQueryReceive(ServerPacket *pack) { /* These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again */ - char *queryBuffer = new char[pack->ReadUInt32() + 1]; + auto queryBuffer = new char[pack->ReadUInt32() + 1]; pack->ReadString(queryBuffer); std::string query(queryBuffer); diff --git a/queryserv/lfguild.cpp b/queryserv/lfguild.cpp index 340321f06..ff7271832 100644 --- a/queryserv/lfguild.cpp +++ b/queryserv/lfguild.cpp @@ -168,7 +168,7 @@ void LFGuildManager::SendPlayerMatches(uint32 FromZoneID, uint32 FromInstanceID, } - ServerPacket *pack = new ServerPacket(ServerOP_QueryServGeneric, PacketSize); + auto pack = new ServerPacket(ServerOP_QueryServGeneric, PacketSize); pack->WriteUInt32(FromZoneID); pack->WriteUInt32(FromInstanceID); @@ -211,7 +211,7 @@ void LFGuildManager::SendGuildMatches(uint32 FromZoneID, uint32 FromInstanceID, } - ServerPacket *pack = new ServerPacket(ServerOP_QueryServGeneric, PacketSize); + auto pack = new ServerPacket(ServerOP_QueryServGeneric, PacketSize); pack->WriteUInt32(FromZoneID); pack->WriteUInt32(FromInstanceID); @@ -255,7 +255,7 @@ void LFGuildManager::TogglePlayer(uint32 FromZoneID, uint32 FromInstanceID, char auto results = database.QueryDatabase(query); } - ServerPacket *pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(From) + strlen(Comments) + 30); + auto pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(From) + strlen(Comments) + 30); pack->WriteUInt32(FromZoneID); pack->WriteUInt32(FromInstanceID); @@ -300,7 +300,7 @@ void LFGuildManager::ToggleGuild(uint32 FromZoneID, uint32 FromInstanceID, char } - ServerPacket *pack = new ServerPacket(ServerOP_LFGuildUpdate, strlen(GuildName) + strlen(Comments) + 30); + auto pack = new ServerPacket(ServerOP_LFGuildUpdate, strlen(GuildName) + strlen(Comments) + 30); pack->WriteString(GuildName); pack->WriteString(Comments); @@ -352,7 +352,8 @@ void LFGuildManager::SendPlayerStatus(uint32 FromZoneID, uint32 FromInstanceID, { if(!strcasecmp((*it).Name.c_str(), From)) { - ServerPacket *pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(From) + (*it).Comments.length() + 30); + auto pack = + new ServerPacket(ServerOP_QueryServGeneric, strlen(From) + (*it).Comments.length() + 30); pack->WriteUInt32(FromZoneID); pack->WriteUInt32(FromInstanceID); @@ -379,7 +380,8 @@ void LFGuildManager::SendGuildStatus(uint32 FromZoneID, uint32 FromInstanceID, c { if(!strcasecmp((*it).Name.c_str(), GuildName)) { - ServerPacket *pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(From) + (*it).Comments.length() + 42); + auto pack = + new ServerPacket(ServerOP_QueryServGeneric, strlen(From) + (*it).Comments.length() + 42); pack->WriteUInt32(FromZoneID); pack->WriteUInt32(FromInstanceID); diff --git a/zone/aa.cpp b/zone/aa.cpp index 7828d6654..477de240e 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -120,7 +120,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u npca->SetFollowID(GetID()); if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; + auto nSI = new AA_SwarmPetInfo; npca->SetSwarmInfo(nSI); npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); } @@ -217,7 +217,7 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid npca->SetFollowID(GetID()); if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; + auto nSI = new AA_SwarmPetInfo; npca->SetSwarmInfo(nSI); npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); } @@ -260,7 +260,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) //assuming we have pets in our table; we take the first pet as a base type. const NPCType *base_type = database.LoadNPCTypesData(500); - NPCType *make_npc = new NPCType; + auto make_npc = new NPCType; memcpy(make_npc, base_type, sizeof(NPCType)); //combat stats @@ -397,10 +397,10 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) make_npc->d_melee_texture1 = 0; make_npc->d_melee_texture2 = 0; - NPC* npca = new NPC(make_npc, 0, GetPosition(), FlyMode3); + auto npca = new NPC(make_npc, 0, GetPosition(), FlyMode3); if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; + auto nSI = new AA_SwarmPetInfo; npca->SetSwarmInfo(nSI); npca->GetSwarmInfo()->duration = new Timer(duration*1000); } @@ -477,7 +477,7 @@ void Client::ResetAA() { void Client::SendClearAA() { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ClearLeadershipAbilities, 0); + auto outapp = new EQApplicationPacket(OP_ClearLeadershipAbilities, 0); FastQueuePacket(&outapp); outapp = new EQApplicationPacket(OP_ClearAA, 0); FastQueuePacket(&outapp); @@ -733,7 +733,7 @@ void Client::InspectBuffs(Client* Inspector, int Rank) if (!Inspector || Rank == 0) return; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_InspectBuffs, sizeof(InspectBuffs_Struct)); + auto outapp = new EQApplicationPacket(OP_InspectBuffs, sizeof(InspectBuffs_Struct)); InspectBuffs_Struct *ib = (InspectBuffs_Struct *)outapp->pBuffer; uint32 buff_count = GetMaxTotalSlots(); @@ -847,7 +847,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { } int size = sizeof(AARankInfo_Struct) + (sizeof(AARankEffect_Struct) * rank->effects.size()) + (sizeof(AARankPrereq_Struct) * rank->prereqs.size()); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, size); + auto outapp = new EQApplicationPacket(OP_SendAATable, size); AARankInfo_Struct *aai = (AARankInfo_Struct*)outapp->pBuffer; aai->id = rank->id; @@ -898,7 +898,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { } void Client::SendAlternateAdvancementStats() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); + auto outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer; aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP); aps->unspent = m_pp.aapoints; @@ -908,7 +908,7 @@ void Client::SendAlternateAdvancementStats() { } void Client::SendAlternateAdvancementPoints() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); + auto outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; int i = 0; @@ -933,7 +933,7 @@ void Client::SendAlternateAdvancementPoints() { } void Client::SendAlternateAdvancementTimer(int ability, int begin, int end) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction, sizeof(UseAA_Struct)); + auto outapp = new EQApplicationPacket(OP_AAAction, sizeof(UseAA_Struct)); UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; uaaout->ability = ability; uaaout->begin = begin; @@ -945,7 +945,7 @@ void Client::SendAlternateAdvancementTimer(int ability, int begin, int end) { //sends all AA timers. void Client::SendAlternateAdvancementTimers() { //we dont use SendAATimer because theres no reason to allocate the EQApplicationPacket every time - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction, sizeof(UseAA_Struct)); + auto outapp = new EQApplicationPacket(OP_AAAction, sizeof(UseAA_Struct)); UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; PTimerList::iterator c, e; @@ -974,7 +974,7 @@ void Client::ResetAlternateAdvancementTimer(int ability) { } void Client::ResetAlternateAdvancementTimers() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction, sizeof(UseAA_Struct)); + auto outapp = new EQApplicationPacket(OP_AAAction, sizeof(UseAA_Struct)); UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; PTimerList::iterator c, e; @@ -1592,7 +1592,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapid = atoi(row[0]); ability->name = row[1]; ability->category = atoi(row[2]); @@ -1624,7 +1624,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapid = atoi(row[0]); rank->upper_hotkey_sid = atoi(row[1]); rank->lower_hotkey_sid = atoi(row[2]); diff --git a/zone/aggro.cpp b/zone/aggro.cpp index a2ee52357..847c51e76 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -1218,7 +1218,7 @@ void Mob::RemoveFromFeignMemory(Client* attacker) { } void Mob::ClearFeignMemory() { - std::set::iterator RememberedCharID = feign_memory_list.begin(); + auto RememberedCharID = feign_memory_list.begin(); while (RememberedCharID != feign_memory_list.end()) { Client* remember_client = entity_list.GetClientByCharID(*RememberedCharID); diff --git a/zone/attack.cpp b/zone/attack.cpp index a401c71c5..354517279 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1460,7 +1460,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att if((RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel)) || RuleB(Character, LeaveNakedCorpses)) { // creating the corpse takes the cash/items off the player too - Corpse *new_corpse = new Corpse(this, exploss); + auto new_corpse = new Corpse(this, exploss); std::string tmp; database.GetVariable("ServerType", tmp); @@ -1901,7 +1901,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac uint8 killed_level = GetLevel(); if (GetClass() == LDON_TREASURE) { // open chest - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); + auto outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer; anim->spawnid = GetID(); anim->action = 0x0F; @@ -1910,7 +1910,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac safe_delete(outapp); } - EQApplicationPacket* app = new EQApplicationPacket(OP_Death, sizeof(Death_Struct)); + auto app = new EQApplicationPacket(OP_Death, sizeof(Death_Struct)); Death_Struct* d = (Death_Struct*)app->pBuffer; d->spawn_id = GetID(); d->killer_id = killer_mob ? killer_mob->GetID() : 0; @@ -2005,7 +2005,10 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac // QueryServ Logging - Raid Kills if (RuleB(QueryServ, PlayerLogNPCKills)) { - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); + auto pack = + new ServerPacket(ServerOP_QSPlayerLogNPCKills, + sizeof(QSPlayerLogNPCKill_Struct) + + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); PlayerCount = 0; QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; QS->s1.NPCID = this->GetNPCTypeID(); @@ -2052,7 +2055,10 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac // QueryServ Logging - Group Kills if (RuleB(QueryServ, PlayerLogNPCKills)) { - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); + auto pack = + new ServerPacket(ServerOP_QSPlayerLogNPCKills, + sizeof(QSPlayerLogNPCKill_Struct) + + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); PlayerCount = 0; QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; QS->s1.NPCID = this->GetNPCTypeID(); @@ -2096,7 +2102,9 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac // QueryServ Logging - Solo if (RuleB(QueryServ, PlayerLogNPCKills)) { - ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1)); + auto pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, + sizeof(QSPlayerLogNPCKill_Struct) + + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1)); QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; QS->s1.NPCID = this->GetNPCTypeID(); QS->s1.ZoneID = this->GetZoneID(); @@ -2126,7 +2134,9 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac entity_list.RemoveFromAutoXTargets(this); uint16 emoteid = this->GetEmoteID(); - Corpse* corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata, level>54 ? RuleI(NPC, MajorNPCCorpseDecayTimeMS) : RuleI(NPC, MinorNPCCorpseDecayTimeMS)); + auto corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata, + level > 54 ? RuleI(NPC, MajorNPCCorpseDecayTimeMS) + : RuleI(NPC, MinorNPCCorpseDecayTimeMS)); entity_list.LimitRemoveNPC(this); entity_list.AddCorpse(corpse, GetID()); @@ -2477,7 +2487,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) { } attacker->Damage(this, -DS, spellid, SkillAbjuration/*hackish*/, false); //we can assume there is a spell now - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); + auto outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct* cds = (CombatDamage_Struct*)outapp->pBuffer; cds->target = attacker->GetID(); cds->source = GetID(); @@ -3242,7 +3252,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons //send damage packet... if(!iBuffTic) { //buff ticks do not send damage, instead they just call SendHPUpdate(), which is done above - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); + auto outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer; a->target = GetID(); if (attacker == nullptr) @@ -4434,7 +4444,7 @@ void Mob::CommonBreakInvisibleFromCombat() if(hidden || improved_hidden){ hidden = false; improved_hidden = false; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; sa_out->spawn_id = GetID(); sa_out->type = 0x03; diff --git a/zone/client.cpp b/zone/client.cpp index 77e5e78d6..38e5d7c7e 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -424,7 +424,7 @@ void Client::SendZoneInPackets() { ////////////////////////////////////////////////////// // Spawn Appearance Packet - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* sa = (SpawnAppearance_Struct*)outapp->pBuffer; sa->type = AT_SpawnID; // Is 0x10 used to set the player id? sa->parameter = GetID(); // Four bytes for this parameter... @@ -486,7 +486,7 @@ void Client::SendZoneInPackets() void Client::SendLogoutPackets() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CancelTrade, sizeof(CancelTrade_Struct)); + auto outapp = new EQApplicationPacket(OP_CancelTrade, sizeof(CancelTrade_Struct)); CancelTrade_Struct* ct = (CancelTrade_Struct*) outapp->pBuffer; ct->fromid = GetID(); ct->action = groupActUpdate; @@ -683,7 +683,7 @@ bool Client::AddPacket(const EQApplicationPacket *pApp, bool bAckreq) { //drop the packet because it will never get sent. return(false); } - CLIENTPACKET *c = new CLIENTPACKET; + auto c = new CLIENTPACKET; c->ack_req = bAckreq; c->app = pApp->Copy(); @@ -700,7 +700,7 @@ bool Client::AddPacket(EQApplicationPacket** pApp, bool bAckreq) { //drop the packet because it will never get sent. return(false); } - CLIENTPACKET *c = new CLIENTPACKET; + auto c = new CLIENTPACKET; c->ack_req = bAckreq; c->app = *pApp; @@ -821,7 +821,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s /* Logs Player Chat */ if (RuleB(QueryServ, PlayerLogChat)) { - ServerPacket* pack = new ServerPacket(ServerOP_Speech, sizeof(Server_Speech_Struct) + strlen(message) + 1); + auto pack = new ServerPacket(ServerOP_Speech, sizeof(Server_Speech_Struct) + strlen(message) + 1); Server_Speech_Struct* sem = (Server_Speech_Struct*) pack->pBuffer; if(chan_num == 0) @@ -1123,7 +1123,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s if (msg_len > 512) message[512] = '\0'; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Emote, 4 + msg_len + strlen(GetName()) + 2); + auto outapp = new EQApplicationPacket(OP_Emote, 4 + msg_len + strlen(GetName()) + 2); Emote_Struct* es = (Emote_Struct*)outapp->pBuffer; char *Buffer = (char *)es; Buffer += 4; @@ -1218,7 +1218,7 @@ void Client::Message(uint32 type, const char* message, ...) { return; va_list argptr; - char *buffer = new char[4096]; + auto buffer = new char[4096]; va_start(argptr, message); vsnprintf(buffer, 4096, message, argptr); va_end(argptr); @@ -1231,7 +1231,7 @@ void Client::Message(uint32 type, const char* message, ...) { //len = 4096 - sizeof(SpecialMesg_Struct); uint32 len_packet = sizeof(SpecialMesg_Struct)+len; - EQApplicationPacket* app = new EQApplicationPacket(OP_SpecialMesg, len_packet); + auto app = new EQApplicationPacket(OP_SpecialMesg, len_packet); SpecialMesg_Struct* sm=(SpecialMesg_Struct*)app->pBuffer; sm->header[0] = 0x00; // Header used for #emote style messages.. sm->header[1] = 0x00; // Play around with these to see other types @@ -1262,7 +1262,7 @@ void Client::QuestJournalledMessage(const char *npcname, const char* message) { snprintf(OutMessage, MaxMessageLength, "%s", message); OutMessage[MaxMessageLength]='\0'; uint32 len_packet = sizeof(SpecialMesg_Struct) + strlen(OutNPCName) + strlen(OutMessage); - EQApplicationPacket* app = new EQApplicationPacket(OP_SpecialMesg, len_packet); + auto app = new EQApplicationPacket(OP_SpecialMesg, len_packet); SpecialMesg_Struct* sm=(SpecialMesg_Struct*)app->pBuffer; sm->header[0] = 0; @@ -1417,7 +1417,7 @@ bool Client::UpdateLDoNPoints(int32 points, uint32 theme) } m_pp.ldon_points_available += points; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventurePointsUpdate, sizeof(AdventurePoints_Update_Struct)); + auto 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; apus->ldon_guk_points = m_pp.ldon_points_guk; @@ -1440,7 +1440,7 @@ void Client::SetSkill(SkillUseTypes skillid, uint16 value) { database.SaveCharacterSkill(this->CharacterID(), skillid, value); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; skill->skillId=skillid; skill->value=value; @@ -1460,7 +1460,7 @@ void Client::IncreaseLanguageSkill(int skill_id, int value) { database.SaveCharacterLanguage(this->CharacterID(), skill_id, m_pp.languages[skill_id]); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; skill->skillId = 100 + skill_id; skill->value = m_pp.languages[skill_id]; @@ -1481,7 +1481,7 @@ void Client::AddSkill(SkillUseTypes skillid, uint16 value) { } void Client::SendSound(){//Makes a sound. - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sound, 68); + auto outapp = new EQApplicationPacket(OP_Sound, 68); unsigned char x[68]; memset(x, 0, 68); x[0]=0x22; @@ -1507,7 +1507,7 @@ void Client::UpdateWho(uint8 remove) { return; if (!worldserver.Connected()) return; - ServerPacket* pack = new ServerPacket(ServerOP_ClientList, sizeof(ServerClientList_Struct)); + auto pack = new ServerPacket(ServerOP_ClientList, sizeof(ServerClientList_Struct)); ServerClientList_Struct* scl = (ServerClientList_Struct*) pack->pBuffer; scl->remove = remove; scl->wid = this->GetWID(); @@ -1553,7 +1553,7 @@ void Client::WhoAll(Who_All_Struct* whom) { if (!worldserver.Connected()) Message(0, "Error: World server disconnected"); else { - ServerPacket* pack = new ServerPacket(ServerOP_Who, sizeof(ServerWhoAll_Struct)); + auto pack = new ServerPacket(ServerOP_Who, sizeof(ServerWhoAll_Struct)); ServerWhoAll_Struct* whoall = (ServerWhoAll_Struct*) pack->pBuffer; whoall->admin = this->Admin(); whoall->fromid=this->GetID(); @@ -1574,7 +1574,8 @@ void Client::FriendsWho(char *FriendsString) { if (!worldserver.Connected()) Message(0, "Error: World server disconnected"); else { - ServerPacket* pack = new ServerPacket(ServerOP_FriendsWho, sizeof(ServerFriendsWho_Struct) + strlen(FriendsString)); + auto pack = + new ServerPacket(ServerOP_FriendsWho, sizeof(ServerFriendsWho_Struct) + strlen(FriendsString)); ServerFriendsWho_Struct* FriendsWho = (ServerFriendsWho_Struct*) pack->pBuffer; FriendsWho->FromID = this->GetID(); strcpy(FriendsWho->FromName, GetName()); @@ -1609,7 +1610,7 @@ void Client::SetStats(uint8 type,int16 set_val){ printf("Error in Client::IncStats, received invalid type of: %i\n",type); return; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_IncreaseStats,sizeof(IncreaseStat_Struct)); + auto outapp = new EQApplicationPacket(OP_IncreaseStats, sizeof(IncreaseStat_Struct)); IncreaseStat_Struct* iss=(IncreaseStat_Struct*)outapp->pBuffer; switch(type){ case STAT_STR: @@ -1692,7 +1693,7 @@ void Client::IncStats(uint8 type,int16 increase_val){ printf("Error in Client::IncStats, received invalid type of: %i\n",type); return; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_IncreaseStats,sizeof(IncreaseStat_Struct)); + auto outapp = new EQApplicationPacket(OP_IncreaseStats, sizeof(IncreaseStat_Struct)); IncreaseStat_Struct* iss=(IncreaseStat_Struct*)outapp->pBuffer; switch(type){ case STAT_STR: @@ -1796,9 +1797,7 @@ void Client::SendManaUpdatePacket() { if (last_reported_mana != cur_mana || last_reported_endur != cur_end) { - - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct)); + auto outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct)); ManaChange_Struct* manachange = (ManaChange_Struct*)outapp->pBuffer; manachange->new_mana = cur_mana; manachange->stamina = cur_end; @@ -1812,7 +1811,8 @@ void Client::SendManaUpdatePacket() { if(g) { outapp = new EQApplicationPacket(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - EQApplicationPacket *outapp2 = new EQApplicationPacket(OP_MobEnduranceUpdate, sizeof(MobEnduranceUpdate_Struct)); + auto outapp2 = + new EQApplicationPacket(OP_MobEnduranceUpdate, sizeof(MobEnduranceUpdate_Struct)); MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp->pBuffer; MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp2->pBuffer; @@ -1843,7 +1843,7 @@ void Client::SendManaUpdatePacket() { // sends mana update to self void Client::SendManaUpdate() { - EQApplicationPacket* mana_app = new EQApplicationPacket(OP_ManaUpdate,sizeof(ManaUpdate_Struct)); + auto mana_app = new EQApplicationPacket(OP_ManaUpdate, sizeof(ManaUpdate_Struct)); ManaUpdate_Struct* mus = (ManaUpdate_Struct*)mana_app->pBuffer; mus->cur_mana = GetMana(); mus->max_mana = GetMaxMana(); @@ -1856,7 +1856,7 @@ void Client::SendManaUpdate() // sends endurance update to self void Client::SendEnduranceUpdate() { - EQApplicationPacket* end_app = new EQApplicationPacket(OP_EnduranceUpdate,sizeof(EnduranceUpdate_Struct)); + auto end_app = new EQApplicationPacket(OP_EnduranceUpdate, sizeof(EnduranceUpdate_Struct)); EnduranceUpdate_Struct* eus = (EnduranceUpdate_Struct*)end_app->pBuffer; eus->cur_end = GetEndurance(); eus->max_end = GetMaxEndurance(); @@ -1929,7 +1929,7 @@ void Client::Stand() { void Client::ChangeLastName(const char* in_lastname) { memset(m_pp.last_name, 0, sizeof(m_pp.last_name)); strn0cpy(m_pp.last_name, in_lastname, sizeof(m_pp.last_name)); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMLastName, sizeof(GMLastName_Struct)); + auto outapp = new EQApplicationPacket(OP_GMLastName, sizeof(GMLastName_Struct)); GMLastName_Struct* gmn = (GMLastName_Struct*)outapp->pBuffer; strcpy(gmn->name, name); strcpy(gmn->gmname, name); @@ -1962,7 +1962,7 @@ bool Client::ChangeFirstName(const char* in_firstname, const char* gmname) Save(); // send name update packet - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMNameChange, sizeof(GMName_Struct)); + auto outapp = new EQApplicationPacket(OP_GMNameChange, sizeof(GMName_Struct)); GMName_Struct* gmn=(GMName_Struct*)outapp->pBuffer; strn0cpy(gmn->gmname,gmname,64); strn0cpy(gmn->oldname,GetName(),64); @@ -2003,7 +2003,7 @@ void Client::ReadBook(BookRequest_Struct *book) { #if EQDEBUG >= 6 Log.Out(Logs::General, Logs::Normal, "Client::ReadBook() textfile:%s Text:%s", txtfile, booktxt2.c_str()); #endif - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ReadBook, length + sizeof(BookText_Struct)); + auto outapp = new EQApplicationPacket(OP_ReadBook, length + sizeof(BookText_Struct)); BookText_Struct *out = (BookText_Struct *) outapp->pBuffer; out->window = book->window; @@ -2031,7 +2031,7 @@ void Client::QuestReadBook(const char* text, uint8 type) { std::string booktxt2 = text; int length = booktxt2.length(); if (booktxt2[0] != '\0') { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ReadBook, length + sizeof(BookText_Struct)); + auto outapp = new EQApplicationPacket(OP_ReadBook, length + sizeof(BookText_Struct)); BookText_Struct *out = (BookText_Struct *) outapp->pBuffer; out->window = 0xFF; out->type = type; @@ -2043,7 +2043,7 @@ void Client::QuestReadBook(const char* text, uint8 type) { } void Client::SendClientMoneyUpdate(uint8 type,uint32 amount){ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeMoneyUpdate,sizeof(TradeMoneyUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_TradeMoneyUpdate, sizeof(TradeMoneyUpdate_Struct)); TradeMoneyUpdate_Struct* mus= (TradeMoneyUpdate_Struct*)outapp->pBuffer; mus->amount=amount; mus->trader=0; @@ -2241,7 +2241,7 @@ void Client::AddMoneyToPP(uint32 copper, uint32 silver, uint32 gold, uint32 plat } void Client::SendMoneyUpdate() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoneyUpdate,sizeof(MoneyUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_MoneyUpdate, sizeof(MoneyUpdate_Struct)); MoneyUpdate_Struct* mus= (MoneyUpdate_Struct*)outapp->pBuffer; mus->platinum = m_pp.platinum; @@ -2489,7 +2489,7 @@ void Client::SetPVP(bool toggle) { } void Client::WorldKick() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMKick, sizeof(GMKick_Struct)); + auto outapp = new EQApplicationPacket(OP_GMKick, sizeof(GMKick_Struct)); GMKick_Struct* gmk = (GMKick_Struct *)outapp->pBuffer; strcpy(gmk->name,GetName()); QueuePacket(outapp); @@ -2498,7 +2498,7 @@ void Client::WorldKick() { } void Client::GMKill() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMKill, sizeof(GMKill_Struct)); + auto outapp = new EQApplicationPacket(OP_GMKill, sizeof(GMKill_Struct)); GMKill_Struct* gmk = (GMKill_Struct *)outapp->pBuffer; strcpy(gmk->name,GetName()); QueuePacket(outapp); @@ -2513,7 +2513,7 @@ bool Client::CheckAccess(int16 iDBLevel, int16 iDefaultLevel) { } void Client::MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing){ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MemorizeSpell,sizeof(MemorizeSpell_Struct)); + auto outapp = new EQApplicationPacket(OP_MemorizeSpell, sizeof(MemorizeSpell_Struct)); MemorizeSpell_Struct* mss=(MemorizeSpell_Struct*)outapp->pBuffer; mss->scribing=scribing; mss->slot=slot; @@ -2859,7 +2859,7 @@ void Client::Message_StringID(uint32 type, uint32 string_id, uint32 distance) return; if (GetFilter(FilterSpellCrits) == FilterHide && type == MT_SpellCrits) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SimpleMessage,12); + auto outapp = new EQApplicationPacket(OP_SimpleMessage, 12); SimpleMessage_Struct* sms = (SimpleMessage_Struct*)outapp->pBuffer; sms->color=type; sms->string_id=string_id; @@ -2921,7 +2921,7 @@ void Client::Message_StringID(uint32 type, uint32 string_id, const char* message length += 1; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_FormattedMessage, sizeof(FormattedMessage_Struct) + length); + auto outapp = new EQApplicationPacket(OP_FormattedMessage, sizeof(FormattedMessage_Struct) + length); FormattedMessage_Struct *fm = (FormattedMessage_Struct *)outapp->pBuffer; fm->string_id = string_id; fm->type = type; @@ -2987,7 +2987,7 @@ void Client::FilteredMessage_StringID(Mob *sender, uint32 type, if (!FilteredMessageCheck(sender, filter)) return; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SimpleMessage, 12); + auto outapp = new EQApplicationPacket(OP_SimpleMessage, 12); SimpleMessage_Struct *sms = (SimpleMessage_Struct *)outapp->pBuffer; sms->color = type; sms->string_id = string_id; @@ -3035,7 +3035,7 @@ void Client::FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType fil length += 1; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_FormattedMessage, sizeof(FormattedMessage_Struct) + length); + auto outapp = new EQApplicationPacket(OP_FormattedMessage, sizeof(FormattedMessage_Struct) + length); FormattedMessage_Struct *fm = (FormattedMessage_Struct *)outapp->pBuffer; fm->string_id = string_id; fm->type = type; @@ -3113,7 +3113,7 @@ void Client::SetLanguageSkill(int langid, int value) m_pp.languages[langid] = value; database.SaveCharacterLanguage(this->CharacterID(), langid, value); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_SkillUpdate, sizeof(SkillUpdate_Struct)); SkillUpdate_Struct* skill = (SkillUpdate_Struct*)outapp->pBuffer; skill->skillId = 100 + langid; skill->value = m_pp.languages[langid]; @@ -3639,7 +3639,7 @@ void Client::SetEndurance(int32 newEnd) void Client::SacrificeConfirm(Client *caster) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_Sacrifice, sizeof(Sacrifice_Struct)); + auto outapp = new EQApplicationPacket(OP_Sacrifice, sizeof(Sacrifice_Struct)); Sacrifice_Struct *ss = (Sacrifice_Struct *)outapp->pBuffer; if (!caster || PendingSacrifice) { @@ -3712,7 +3712,7 @@ void Client::Sacrifice(Client *caster) } ClearAllProximities(); if(RuleB(Character, LeaveCorpses)){ - Corpse *new_corpse = new Corpse(this, 0); + auto new_corpse = new Corpse(this, 0); entity_list.AddCorpse(new_corpse, GetID()); SetID(0); entity_list.QueueClients(this, &app2, true); @@ -3734,7 +3734,7 @@ void Client::SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID) { const SPDat_Spell_Struct &Spell = spells[SpellID]; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Translocate, sizeof(Translocate_Struct)); + auto outapp = new EQApplicationPacket(OP_Translocate, sizeof(Translocate_Struct)); Translocate_Struct *ts = (Translocate_Struct*)outapp->pBuffer; strcpy(ts->Caster, Caster->GetName()); @@ -3769,28 +3769,28 @@ void Client::SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID) { return; } void Client::SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu::Item_Struct* item){ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); - sPickPocket_Struct* pick_out = (sPickPocket_Struct*) outapp->pBuffer; - pick_out->coin = amt; - pick_out->from = GetID(); - pick_out->to = from->GetID(); - pick_out->myskill = GetSkill(SkillPickPockets); + auto outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); + sPickPocket_Struct *pick_out = (sPickPocket_Struct *)outapp->pBuffer; + pick_out->coin = amt; + pick_out->from = GetID(); + pick_out->to = from->GetID(); + pick_out->myskill = GetSkill(SkillPickPockets); - if((type >= PickPocketPlatinum) && (type <= PickPocketCopper) && (amt == 0)) - type = PickPocketFailed; + if ((type >= PickPocketPlatinum) && (type <= PickPocketCopper) && (amt == 0)) + type = PickPocketFailed; - pick_out->type = type; - if(item) - strcpy(pick_out->itemname, item->Name); - else - pick_out->itemname[0] = '\0'; - //if we do not send this packet the client will lock up and require the player to relog. - QueuePacket(outapp); - safe_delete(outapp); + pick_out->type = type; + if (item) + strcpy(pick_out->itemname, item->Name); + else + pick_out->itemname[0] = '\0'; + // if we do not send this packet the client will lock up and require the player to relog. + QueuePacket(outapp); + safe_delete(outapp); } void Client::SetHoTT(uint32 mobid) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_TargetHoTT, sizeof(ClientTarget_Struct)); + auto outapp = new EQApplicationPacket(OP_TargetHoTT, sizeof(ClientTarget_Struct)); ClientTarget_Struct *ct = (ClientTarget_Struct *) outapp->pBuffer; ct->new_target = mobid; QueuePacket(outapp); @@ -3800,7 +3800,7 @@ void Client::SetHoTT(uint32 mobid) { void Client::SendPopupToClient(const char *Title, const char *Text, uint32 PopupID, uint32 Buttons, uint32 Duration) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); + auto outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *)outapp->pBuffer; if ((strlen(Title) > (sizeof(olms->Title) - 1)) || (strlen(Text) > (sizeof(olms->Text) - 1))) { @@ -3837,7 +3837,7 @@ void Client::SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const size_t len = strlen(buffer); - EQApplicationPacket* app = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); + auto app = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); OnLevelMessage_Struct* olms=(OnLevelMessage_Struct*)app->pBuffer; if(strlen(Text) > (sizeof(olms->Text)-1)) { @@ -3932,10 +3932,7 @@ void Client::KeyRingAdd(uint32 item_id) bool Client::KeyRingCheck(uint32 item_id) { - for(std::list::iterator iter = keyring.begin(); - iter != keyring.end(); - ++iter) - { + for (auto iter = keyring.begin(); iter != keyring.end(); ++iter) { if(*iter == item_id) return true; } @@ -3946,10 +3943,7 @@ void Client::KeyRingList() { Message(4,"Keys on Keyring:"); const EQEmu::Item_Struct *item = 0; - for(std::list::iterator iter = keyring.begin(); - iter != keyring.end(); - ++iter) - { + for (auto iter = keyring.begin(); iter != keyring.end(); ++iter) { if ((item = database.GetItem(*iter))!=nullptr) { Message(4,item->Name); } @@ -4124,7 +4118,7 @@ bool Client::GroupFollow(Client* inviter) { //Invite the inviter into the group first.....dont ask if (inviter->ClientVersion() < EQEmu::versions::ClientVersion::SoD) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* outgj = (GroupJoin_Struct*)outapp->pBuffer; strcpy(outgj->membername, inviter->GetName()); strcpy(outgj->yourname, inviter->GetName()); @@ -4396,7 +4390,7 @@ void Client::IncrementAggroCount() { if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RestState, 1); + auto outapp = new EQApplicationPacket(OP_RestState, 1); char *Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0x01); QueuePacket(outapp); @@ -4441,7 +4435,7 @@ void Client::DecrementAggroCount() { if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RestState, 5); + auto outapp = new EQApplicationPacket(OP_RestState, 5); char *Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0x00); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, (uint32)(time_until_rest / 1000)); @@ -4457,7 +4451,7 @@ void Client::SendPVPStats() // When the PVP Stats window is opened, no opcode is sent. Therefore this method should be called // from Client::CompleteConnect, and also when the player makes a PVP kill. // - EQApplicationPacket *outapp = new EQApplicationPacket(OP_PVPStats, sizeof(PVPStats_Struct)); + auto outapp = new EQApplicationPacket(OP_PVPStats, sizeof(PVPStats_Struct)); PVPStats_Struct *pvps = (PVPStats_Struct *)outapp->pBuffer; pvps->Kills = m_pp.PVPKills; @@ -4476,7 +4470,7 @@ void Client::SendPVPStats() void Client::SendCrystalCounts() { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_CrystalCountUpdate, sizeof(CrystalCountUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_CrystalCountUpdate, sizeof(CrystalCountUpdate_Struct)); CrystalCountUpdate_Struct *ccus = (CrystalCountUpdate_Struct *)outapp->pBuffer; ccus->CurrentRadiantCrystals = GetRadiantCrystals(); @@ -4492,7 +4486,7 @@ void Client::SendCrystalCounts() void Client::SendDisciplineTimers() { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DisciplineTimer, sizeof(DisciplineTimer_Struct)); + auto outapp = new EQApplicationPacket(OP_DisciplineTimer, sizeof(DisciplineTimer_Struct)); DisciplineTimer_Struct *dts = (DisciplineTimer_Struct *)outapp->pBuffer; for(unsigned int i = 0; i < MAX_DISCIPLINE_TIMERS; ++i) @@ -4556,7 +4550,7 @@ void Client::SendRespawnBinds() PacketLength += opt->name.size() + 1; //+1 for cstring } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespawnWindow, PacketLength); + auto outapp = new EQApplicationPacket(OP_RespawnWindow, PacketLength); char* buffer = (char*)outapp->pBuffer; //Packet header @@ -4820,7 +4814,7 @@ void Client::SummonAndRezzAllCorpses() { PendingRezzXP = -1; - ServerPacket *Pack = new ServerPacket(ServerOP_DepopAllPlayersCorpses, sizeof(ServerDepopAllPlayersCorpses_Struct)); + auto Pack = new ServerPacket(ServerOP_DepopAllPlayersCorpses, sizeof(ServerDepopAllPlayersCorpses_Struct)); ServerDepopAllPlayersCorpses_Struct *sdapcs = (ServerDepopAllPlayersCorpses_Struct*)Pack->pBuffer; @@ -4855,7 +4849,7 @@ void Client::SummonAllCorpses(const glm::vec4& position) if(IsOrigin(position) && position.w == 0.0f) summonLocation = GetPosition(); - ServerPacket *Pack = new ServerPacket(ServerOP_DepopAllPlayersCorpses, sizeof(ServerDepopAllPlayersCorpses_Struct)); + auto Pack = new ServerPacket(ServerOP_DepopAllPlayersCorpses, sizeof(ServerDepopAllPlayersCorpses_Struct)); ServerDepopAllPlayersCorpses_Struct *sdapcs = (ServerDepopAllPlayersCorpses_Struct*)Pack->pBuffer; @@ -4874,7 +4868,7 @@ void Client::SummonAllCorpses(const glm::vec4& position) void Client::DepopAllCorpses() { - ServerPacket *Pack = new ServerPacket(ServerOP_DepopAllPlayersCorpses, sizeof(ServerDepopAllPlayersCorpses_Struct)); + auto Pack = new ServerPacket(ServerOP_DepopAllPlayersCorpses, sizeof(ServerDepopAllPlayersCorpses_Struct)); ServerDepopAllPlayersCorpses_Struct *sdapcs = (ServerDepopAllPlayersCorpses_Struct*)Pack->pBuffer; @@ -4891,7 +4885,7 @@ void Client::DepopAllCorpses() void Client::DepopPlayerCorpse(uint32 dbid) { - ServerPacket *Pack = new ServerPacket(ServerOP_DepopPlayerCorpse, sizeof(ServerDepopPlayerCorpse_Struct)); + auto Pack = new ServerPacket(ServerOP_DepopPlayerCorpse, sizeof(ServerDepopPlayerCorpse_Struct)); ServerDepopPlayerCorpse_Struct *sdpcs = (ServerDepopPlayerCorpse_Struct*)Pack->pBuffer; @@ -4913,7 +4907,7 @@ void Client::BuryPlayerCorpses() void Client::NotifyNewTitlesAvailable() { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_NewTitlesAvailable, 0); + auto outapp = new EQApplicationPacket(OP_NewTitlesAvailable, 0); QueuePacket(outapp); @@ -5336,7 +5330,7 @@ void Client::SendRewards() if(rewards.empty()) return; - EQApplicationPacket *vetapp = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(InternalVeteranReward) * rewards.size())); + auto vetapp = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(InternalVeteranReward) * rewards.size())); uchar *data = vetapp->pBuffer; for(int i = 0; i < rewards.size(); ++i) { InternalVeteranReward *ivr = (InternalVeteranReward*)data; @@ -5686,7 +5680,7 @@ void Client::AddCrystals(uint32 Radiant, uint32 Ebon) // Processes a client request to inspect a SoF+ client's equipment. void Client::ProcessInspectRequest(Client* requestee, Client* requester) { if(requestee && requester) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_InspectAnswer, sizeof(InspectResponse_Struct)); + auto outapp = new EQApplicationPacket(OP_InspectAnswer, sizeof(InspectResponse_Struct)); InspectResponse_Struct* insr = (InspectResponse_Struct*) outapp->pBuffer; insr->TargetID = requester->GetID(); insr->playerid = requestee->GetID(); @@ -5758,7 +5752,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { void Client::GuildBankAck() { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankAck_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankAck_Struct)); GuildBankAck_Struct *gbas = (GuildBankAck_Struct*) outapp->pBuffer; @@ -5770,7 +5764,7 @@ void Client::GuildBankAck() void Client::GuildBankDepositAck(bool Fail, int8 action) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankDepositAck_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankDepositAck_Struct)); GuildBankDepositAck_Struct *gbdas = (GuildBankDepositAck_Struct*) outapp->pBuffer; @@ -5783,7 +5777,7 @@ void Client::GuildBankDepositAck(bool Fail, int8 action) void Client::ClearGuildBank() { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankClear_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankClear_Struct)); GuildBankClear_Struct *gbcs = (GuildBankClear_Struct*) outapp->pBuffer; @@ -5798,7 +5792,7 @@ void Client::SendGroupCreatePacket() { // For SoD and later clients, this is sent the Group Leader upon initial creation of the group // - EQApplicationPacket *outapp=new EQApplicationPacket(OP_GroupUpdateB, 32 + strlen(GetName())); + auto outapp = new EQApplicationPacket(OP_GroupUpdateB, 32 + strlen(GetName())); char *Buffer = (char *)outapp->pBuffer; // Header @@ -5824,7 +5818,7 @@ void Client::SendGroupLeaderChangePacket(const char *LeaderName) { // For SoD and later, send name of Group Leader to this client - EQApplicationPacket *outapp=new EQApplicationPacket(OP_GroupLeaderChange, sizeof(GroupLeaderChange_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupLeaderChange, sizeof(GroupLeaderChange_Struct)); GroupLeaderChange_Struct *glcs = (GroupLeaderChange_Struct*)outapp->pBuffer; @@ -5836,14 +5830,14 @@ void Client::SendGroupLeaderChangePacket(const char *LeaderName) void Client::SendGroupJoinAcknowledge() { // For SoD and later, This produces the 'You have joined the group' message. - EQApplicationPacket* outapp=new EQApplicationPacket(OP_GroupAcknowledge, 4); + auto outapp = new EQApplicationPacket(OP_GroupAcknowledge, 4); FastQueuePacket(&outapp); } void Client::SendAdventureError(const char *error) { size_t error_size = strlen(error); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureInfo, (error_size + 2)); + auto outapp = new EQApplicationPacket(OP_AdventureInfo, (error_size + 2)); strn0cpy((char*)outapp->pBuffer, error, error_size); FastQueuePacket(&outapp); } @@ -5853,7 +5847,7 @@ void Client::SendAdventureDetails() if(adv_data) { ServerSendAdventureData_Struct *ad = (ServerSendAdventureData_Struct*)adv_data; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureData, sizeof(AdventureRequestResponse_Struct)); + auto outapp = new EQApplicationPacket(OP_AdventureData, sizeof(AdventureRequestResponse_Struct)); AdventureRequestResponse_Struct *arr = (AdventureRequestResponse_Struct*)outapp->pBuffer; arr->unknown000 = 0xBFC40100; arr->unknown2080 = 0x0A; @@ -5882,14 +5876,14 @@ void Client::SendAdventureDetails() else { ServerSendAdventureData_Struct *ad = (ServerSendAdventureData_Struct*)adv_data; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureData, sizeof(AdventureRequestResponse_Struct)); + auto outapp = new EQApplicationPacket(OP_AdventureData, sizeof(AdventureRequestResponse_Struct)); FastQueuePacket(&outapp); } } void Client::SendAdventureCount(uint32 count, uint32 total) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureUpdate, sizeof(AdventureCountUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_AdventureUpdate, sizeof(AdventureCountUpdate_Struct)); AdventureCountUpdate_Struct *acu = (AdventureCountUpdate_Struct*)outapp->pBuffer; acu->current = count; acu->total = total; @@ -5899,7 +5893,7 @@ void Client::SendAdventureCount(uint32 count, uint32 total) void Client::NewAdventure(int id, int theme, const char *text, int member_count, const char *members) { size_t text_size = strlen(text); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureDetails, text_size + 2); + auto outapp = new EQApplicationPacket(OP_AdventureDetails, text_size + 2); strn0cpy((char*)outapp->pBuffer, text, text_size); FastQueuePacket(&outapp); @@ -5941,7 +5935,7 @@ void Client::LeaveAdventure() if(!GetPendingAdventureLeave()) { PendingAdventureLeave(); - ServerPacket *pack = new ServerPacket(ServerOP_AdventureLeave, 64); + auto pack = new ServerPacket(ServerOP_AdventureLeave, 64); strcpy((char*)pack->pBuffer, GetName()); pack->Deflate(); worldserver.SendPacket(pack); @@ -5978,7 +5972,7 @@ void Client::ClearCurrentAdventure() void Client::AdventureFinish(bool win, int theme, int points) { UpdateLDoNPoints(points, theme); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureFinish, sizeof(AdventureFinish_Struct)); + auto outapp = new EQApplicationPacket(OP_AdventureFinish, sizeof(AdventureFinish_Struct)); AdventureFinish_Struct *af = (AdventureFinish_Struct*)outapp->pBuffer; af->win_lose = win ? 1 : 0; af->points = points; @@ -6074,7 +6068,8 @@ void Client::CheckEmoteHail(Mob *target, const char* message) void Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 count) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_DzCompass, sizeof(ExpeditionInfo_Struct) + sizeof(ExpeditionCompassEntry_Struct) * count); + auto outapp = new EQApplicationPacket(OP_DzCompass, sizeof(ExpeditionInfo_Struct) + + sizeof(ExpeditionCompassEntry_Struct) * count); ExpeditionCompass_Struct *ecs = (ExpeditionCompass_Struct*)outapp->pBuffer; //ecs->clientid = GetID(); ecs->count = count; @@ -6105,7 +6100,7 @@ void Client::SendZonePoints() } uint32 zpsize = sizeof(ZonePoints) + ((count + 1) * sizeof(ZonePoint_Entry)); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendZonepoints, zpsize); + auto outapp = new EQApplicationPacket(OP_SendZonepoints, zpsize); ZonePoints* zp = (ZonePoints*)outapp->pBuffer; zp->count = count; @@ -6132,7 +6127,7 @@ void Client::SendZonePoints() void Client::SendTargetCommand(uint32 EntityID) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TargetCommand, sizeof(ClientTarget_Struct)); + auto outapp = new EQApplicationPacket(OP_TargetCommand, sizeof(ClientTarget_Struct)); ClientTarget_Struct *cts = (ClientTarget_Struct*)outapp->pBuffer; cts->new_target = EntityID; FastQueuePacket(&outapp); @@ -6322,7 +6317,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid FlyMode3); if(!npca->GetSwarmInfo()){ - AA_SwarmPetInfo* nSI = new AA_SwarmPetInfo; + auto nSI = new AA_SwarmPetInfo; npca->SetSwarmInfo(nSI); npca->GetSwarmInfo()->duration = new Timer(pet_duration*1000); } @@ -6773,10 +6768,7 @@ void Client::SendStatsWindow(Client* client, bool use_window) std::string faction_item_string = ""; char faction_buf[256]; - for(std::map ::iterator iter = item_faction_bonuses.begin(); - iter != item_faction_bonuses.end(); - ++iter) - { + for (auto iter = item_faction_bonuses.begin(); iter != item_faction_bonuses.end(); ++iter) { memset(&faction_buf, 0, sizeof(faction_buf)); if(!database.GetFactionName((int32)((*iter).first), faction_buf, sizeof(faction_buf))) @@ -6876,14 +6868,15 @@ void Client::SendAltCurrencies() { return; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_AltCurrency, - sizeof(AltCurrencyPopulate_Struct) + sizeof(AltCurrencyPopulateEntry_Struct) * count); + auto outapp = + new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyPopulate_Struct) + + sizeof(AltCurrencyPopulateEntry_Struct) * count); AltCurrencyPopulate_Struct *altc = (AltCurrencyPopulate_Struct*)outapp->pBuffer; altc->opcode = ALT_CURRENCY_OP_POPULATE; altc->count = count; uint32 i = 0; - std::list::iterator iter = zone->AlternateCurrencies.begin(); + auto iter = zone->AlternateCurrencies.begin(); while(iter != zone->AlternateCurrencies.end()) { const EQEmu::Item_Struct* item = database.GetItem((*iter).item_id); altc->entries[i].currency_number = (*iter).id; @@ -6934,7 +6927,7 @@ void Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 me } int new_value = 0; - std::map::iterator iter = alternate_currency.find(currency_id); + auto iter = alternate_currency.find(currency_id); if(iter == alternate_currency.end()) { new_value = amount; } else { @@ -6953,7 +6946,7 @@ void Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 me void Client::SendAlternateCurrencyValues() { - std::list::iterator iter = zone->AlternateCurrencies.begin(); + auto iter = zone->AlternateCurrencies.begin(); while(iter != zone->AlternateCurrencies.end()) { SendAlternateCurrencyValue((*iter).id, false); ++iter; @@ -6964,7 +6957,7 @@ void Client::SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null) { uint32 value = GetAlternateCurrencyValue(currency_id); if(value > 0 || (value == 0 && send_if_null)) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyUpdate_Struct)); AltCurrencyUpdate_Struct *update = (AltCurrencyUpdate_Struct*)outapp->pBuffer; update->opcode = 7; strcpy(update->name, GetName()); @@ -6977,7 +6970,7 @@ void Client::SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null) uint32 Client::GetAlternateCurrencyValue(uint32 currency_id) const { - std::map::const_iterator iter = alternate_currency.find(currency_id); + auto iter = alternate_currency.find(currency_id); if(iter == alternate_currency.end()) { return 0; } else { @@ -6997,7 +6990,7 @@ void Client::ProcessAlternateCurrencyQueue() { void Client::OpenLFGuildWindow() { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LFGuild, 8); + auto outapp = new EQApplicationPacket(OP_LFGuild, 8); outapp->WriteUInt32(6); @@ -7162,7 +7155,7 @@ void Client::SendXTargetPacket(uint32 Slot, Mob *m) PacketSize += strlen(XTargets[Slot].Name); } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_XTargetResponse, PacketSize); + auto outapp = new EQApplicationPacket(OP_XTargetResponse, PacketSize); outapp->WriteUInt32(GetMaxXTargets()); outapp->WriteUInt32(1); outapp->WriteUInt32(Slot); @@ -7300,7 +7293,7 @@ void Client::SetMaxXTargets(uint8 NewMax) XTargets[i].Name[0] = 0; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_XTargetResponse, 8); + auto outapp = new EQApplicationPacket(OP_XTargetResponse, 8); outapp->WriteUInt32(GetMaxXTargets()); outapp->WriteUInt32(0); FastQueuePacket(&outapp); @@ -7392,7 +7385,7 @@ void Client::SendWebLink(const char *website) size_t len = strlen(website) + 1; if(website != 0 && len > 1) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weblink, sizeof(Weblink_Struct) + len); + auto outapp = new EQApplicationPacket(OP_Weblink, sizeof(Weblink_Struct) + len); Weblink_Struct *wl = (Weblink_Struct*)outapp->pBuffer; memcpy(wl->weblink, website, len); wl->weblink[len] = '\0'; @@ -7425,7 +7418,8 @@ void Client::SendMercPersonalInfo() { if (mercCount > 0) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, sizeof(MercenaryDataUpdate_Struct)); + auto outapp = + new EQApplicationPacket(OP_MercenaryDataUpdate, sizeof(MercenaryDataUpdate_Struct)); MercenaryDataUpdate_Struct* mdus = (MercenaryDataUpdate_Struct*)outapp->pBuffer; mdus->MercStatus = 0; mdus->MercCount = mercCount; @@ -7449,7 +7443,7 @@ void Client::SendMercPersonalInfo() uint32 stanceindex = 0; if (mdus->MercData[i].StanceCount != 0) { - std::list::iterator iter = zone->merc_stance_list[mercData->MercTemplateID].begin(); + auto iter = zone->merc_stance_list[mercData->MercTemplateID].begin(); while(iter != zone->merc_stance_list[mercData->MercTemplateID].end()) { mdus->MercData[i].Stances[stanceindex].StanceIndex = stanceindex; @@ -7469,7 +7463,8 @@ void Client::SendMercPersonalInfo() { if(mercTypeCount > 0 && mercCount > 0) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataResponse, sizeof(MercenaryMerchantList_Struct)); + auto outapp = new EQApplicationPacket(OP_MercenaryDataResponse, + sizeof(MercenaryMerchantList_Struct)); MercenaryMerchantList_Struct* mml = (MercenaryMerchantList_Struct*)outapp->pBuffer; mml->MercTypeCount = mercTypeCount; //We should only have one merc entry. mml->MercGrades[i] = 1; @@ -7494,7 +7489,7 @@ void Client::SendMercPersonalInfo() int stanceindex = 0; if(mml->Mercs[i].StanceCount != 0) { - std::list::iterator iter = zone->merc_stance_list[mercData->MercTemplateID].begin(); + auto iter = zone->merc_stance_list[mercData->MercTemplateID].begin(); while(iter != zone->merc_stance_list[mercData->MercTemplateID].end()) { mml->Mercs[i].Stances[stanceindex].StanceIndex = stanceindex; @@ -7521,7 +7516,7 @@ void Client::SendMercPersonalInfo() void Client::SendClearMercInfo() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, sizeof(NoMercenaryHired_Struct)); + auto outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, sizeof(NoMercenaryHired_Struct)); NoMercenaryHired_Struct *nmhs = (NoMercenaryHired_Struct*)outapp->pBuffer; nmhs->MercStatus = -1; nmhs->MercCount = 0; @@ -8327,7 +8322,7 @@ void Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, ui void Client::PlayMP3(const char* fname) { std::string filename = fname; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayMP3, filename.length() + 1); + auto outapp = new EQApplicationPacket(OP_PlayMP3, filename.length() + 1); PlayMP3_Struct* buf = (PlayMP3_Struct*)outapp->pBuffer; strncpy(buf->filename, fname, filename.length()); QueuePacket(outapp); @@ -8388,8 +8383,7 @@ void Client::SendColoredText(uint32 color, std::string message) // arbitrary size limit if (message.size() > 512) // live does send this with empty strings sometimes ... return; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ColoredText, - sizeof(ColoredText_Struct) + message.size()); + auto outapp = new EQApplicationPacket(OP_ColoredText, sizeof(ColoredText_Struct) + message.size()); ColoredText_Struct *cts = (ColoredText_Struct *)outapp->pBuffer; cts->color = color; strcpy(cts->msg, message.c_str()); @@ -8400,7 +8394,7 @@ void Client::SendColoredText(uint32 color, std::string message) void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct)); + auto outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct)); memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); QuestReward_Struct* qr = (QuestReward_Struct*)outapp->pBuffer; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 5d11f315e..9712e031a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -841,7 +841,7 @@ void Client::CompleteConnect() } /** Request adventure info **/ - ServerPacket *pack = new ServerPacket(ServerOP_AdventureDataRequest, 64); + auto pack = new ServerPacket(ServerOP_AdventureDataRequest, 64); strcpy((char*)pack->pBuffer, GetName()); worldserver.SendPacket(pack); delete pack; @@ -1022,7 +1022,7 @@ void Client::Handle_Connect_OP_ReqClientSpawn(const EQApplicationPacket *app) { conn_state = ClientSpawnRequested; - EQApplicationPacket* outapp = new EQApplicationPacket; + auto outapp = new EQApplicationPacket; // Send Zone Doors if (entity_list.MakeDoorSpawnPacket(outapp, this)) @@ -1084,7 +1084,7 @@ void Client::Handle_Connect_OP_ReqNewZone(const EQApplicationPacket *app) void Client::Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app) { SendAlternateAdvancementTimers(); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAAStats, 0); + auto outapp = new EQApplicationPacket(OP_SendAAStats, 0); QueuePacket(outapp); safe_delete(outapp); return; @@ -1098,7 +1098,7 @@ void Client::Handle_Connect_OP_SendAATable(const EQApplicationPacket *app) void Client::Handle_Connect_OP_SendExpZonein(const EQApplicationPacket *app) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendExpZonein, 0); + auto outapp = new EQApplicationPacket(OP_SendExpZonein, 0); QueuePacket(outapp); safe_delete(outapp); @@ -1165,7 +1165,7 @@ void Client::Handle_Connect_OP_WearChange(const EQApplicationPacket *app) void Client::Handle_Connect_OP_WorldObjectsSent(const EQApplicationPacket *app) { // New for SoF+ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_WorldObjectsSent, 0); + auto outapp = new EQApplicationPacket(OP_WorldObjectsSent, 0); QueuePacket(outapp); safe_delete(outapp); @@ -1182,7 +1182,7 @@ void Client::Handle_Connect_OP_WorldObjectsSent(const EQApplicationPacket *app) void Client::Handle_Connect_OP_ZoneComplete(const EQApplicationPacket *app) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_0x0347, 0); + auto outapp = new EQApplicationPacket(OP_0x0347, 0); QueuePacket(outapp); safe_delete(outapp); return; @@ -1812,7 +1812,7 @@ void Client::Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app) it = zone->adventure_entry_list_flavor.find(m->CastToNPC()->GetAdventureTemplate()); if (it != zone->adventure_entry_list_flavor.end()) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureInfo, (it->second.size() + 2)); + auto outapp = new EQApplicationPacket(OP_AdventureInfo, (it->second.size() + 2)); strn0cpy((char*)outapp->pBuffer, it->second.c_str(), it->second.size()); FastQueuePacket(&outapp); } @@ -1821,7 +1821,7 @@ void Client::Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app) if (m->CastToNPC()->GetAdventureTemplate() != 0) { std::string text = "Choose your difficulty and preferred adventure type."; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureInfo, (text.size() + 2)); + auto outapp = new EQApplicationPacket(OP_AdventureInfo, (text.size() + 2)); strn0cpy((char*)outapp->pBuffer, text.c_str(), text.size()); FastQueuePacket(&outapp); } @@ -1842,7 +1842,7 @@ void Client::Handle_OP_AdventureLeaderboardRequest(const EQApplicationPacket *ap } adventure_leaderboard_timer = new Timer(4000); - ServerPacket *pack = new ServerPacket(ServerOP_AdventureLeaderboard, sizeof(ServerLeaderboardRequest_Struct)); + auto pack = new ServerPacket(ServerOP_AdventureLeaderboard, sizeof(ServerLeaderboardRequest_Struct)); ServerLeaderboardRequest_Struct *lr = (ServerLeaderboardRequest_Struct*)pack->pBuffer; strcpy(lr->player, GetName()); @@ -2220,7 +2220,7 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app) price *= ams_in->charges; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureMerchantSell, sizeof(Adventure_Sell_Struct)); + auto outapp = new EQApplicationPacket(OP_AdventureMerchantSell, sizeof(Adventure_Sell_Struct)); Adventure_Sell_Struct *ams = (Adventure_Sell_Struct*)outapp->pBuffer; ams->slot = ams_in->slot; ams->unknown000 = 1; @@ -2313,7 +2313,8 @@ void Client::Handle_OP_AdventureRequest(const EQApplicationPacket *app) return; } - ServerPacket *packet = new ServerPacket(ServerOP_AdventureRequest, sizeof(ServerAdventureRequest_Struct)+(64 * group_members)); + auto packet = + new ServerPacket(ServerOP_AdventureRequest, sizeof(ServerAdventureRequest_Struct) + (64 * group_members)); ServerAdventureRequest_Struct *sar = (ServerAdventureRequest_Struct*)packet->pBuffer; sar->member_count = group_members; sar->risk = ars->risk; @@ -2374,7 +2375,7 @@ void Client::Handle_OP_AdventureStatsRequest(const EQApplicationPacket *app) } adventure_stats_timer = new Timer(8000); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureStatsReply, sizeof(AdventureStats_Struct)); + auto outapp = new EQApplicationPacket(OP_AdventureStatsReply, sizeof(AdventureStats_Struct)); AdventureStats_Struct *as = (AdventureStats_Struct*)outapp->pBuffer; if (database.GetAdventureStats(CharacterID(), as)) @@ -2412,7 +2413,7 @@ void Client::Handle_OP_AltCurrencyMerchantRequest(const EQApplicationPacket *app return; } - std::list::iterator altc_iter = zone->AlternateCurrencies.begin(); + auto altc_iter = zone->AlternateCurrencies.begin(); bool found = false; while (altc_iter != zone->AlternateCurrencies.end()) { if ((*altc_iter).id == alt_cur_id) { @@ -2562,7 +2563,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) VERIFY_PACKET_LENGTH(OP_AltCurrencyReclaim, app, AltCurrencyReclaim_Struct); AltCurrencyReclaim_Struct *reclaim = (AltCurrencyReclaim_Struct*)app->pBuffer; uint32 item_id = 0; - std::list::iterator iter = zone->AlternateCurrencies.begin(); + auto iter = zone->AlternateCurrencies.begin(); while (iter != zone->AlternateCurrencies.end()) { if ((*iter).id == reclaim->currency_id) { item_id = (*iter).item_id; @@ -2772,7 +2773,8 @@ void Client::Handle_OP_AltCurrencySellSelection(const EQApplicationPacket *app) cost = 0; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AltCurrencySellSelection, sizeof(AltCurrencySelectItemReply_Struct)); + auto outapp = + new EQApplicationPacket(OP_AltCurrencySellSelection, sizeof(AltCurrencySelectItemReply_Struct)); AltCurrencySelectItemReply_Struct *reply = (AltCurrencySelectItemReply_Struct*)outapp->pBuffer; reply->unknown004 = 0xFF; reply->unknown005 = 0xFF; @@ -2846,7 +2848,7 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app) } } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ApplyPoison, nullptr, sizeof(ApplyPoison_Struct)); + auto outapp = new EQApplicationPacket(OP_ApplyPoison, nullptr, sizeof(ApplyPoison_Struct)); ApplyPoison_Struct* ApplyPoisonResult = (ApplyPoison_Struct*)outapp->pBuffer; ApplyPoisonResult->success = ApplyPoisonSuccessResult; ApplyPoisonResult->inventorySlot = ApplyPoisonData->inventorySlot; @@ -3332,7 +3334,7 @@ void Client::Handle_OP_BankerChange(const EQApplicationPacket *app) return; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_BankerChange, nullptr, sizeof(BankerChange_Struct)); + auto outapp = new EQApplicationPacket(OP_BankerChange, nullptr, sizeof(BankerChange_Struct)); BankerChange_Struct *bc = (BankerChange_Struct *)outapp->pBuffer; if (m_pp.platinum < 0) @@ -3621,7 +3623,7 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app) { Message(13, "Ability recovery time not yet met."); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Begging, sizeof(BeggingResponse_Struct)); + auto outapp = new EQApplicationPacket(OP_Begging, sizeof(BeggingResponse_Struct)); BeggingResponse_Struct *brs = (BeggingResponse_Struct*)outapp->pBuffer; brs->Result = 0; FastQueuePacket(&outapp); @@ -3636,7 +3638,7 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app) p_timers.Start(pTimerBeggingPickPocket, 8); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Begging, sizeof(BeggingResponse_Struct)); + auto outapp = new EQApplicationPacket(OP_Begging, sizeof(BeggingResponse_Struct)); BeggingResponse_Struct *brs = (BeggingResponse_Struct*)outapp->pBuffer; brs->Result = 0; // Default, Fail. @@ -3743,7 +3745,7 @@ void Client::Handle_OP_BlockedBuffs(const EQApplicationPacket *app) } } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_BlockedBuffs, sizeof(BlockedBuffs_Struct)); + auto outapp = new EQApplicationPacket(OP_BlockedBuffs, sizeof(BlockedBuffs_Struct)); BlockedBuffs_Struct *obbs = (BlockedBuffs_Struct*)outapp->pBuffer; @@ -3771,7 +3773,7 @@ void Client::Handle_OP_BlockedBuffs(const EQApplicationPacket *app) if ((bbs->Initialise == 0) && (bbs->Count > 0)) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_BlockedBuffs, sizeof(BlockedBuffs_Struct)); + auto outapp = new EQApplicationPacket(OP_BlockedBuffs, sizeof(BlockedBuffs_Struct)); BlockedBuffs_Struct *obbs = (BlockedBuffs_Struct*)outapp->pBuffer; @@ -4334,7 +4336,8 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) auto boatDelta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, ppu->delta_heading); boat->SetDelta(boatDelta); // send an update to everyone nearby except the client controlling the boat - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto outapp = + new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* ppus = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer; boat->MakeSpawnUpdate(ppus); entity_list.QueueCloseClients(boat,outapp,true,300,this,false); @@ -4532,7 +4535,8 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) hidden = false; improved_hidden = false; if(!invisible) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto outapp = + new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; sa_out->spawn_id = GetID(); sa_out->type = 0x03; @@ -4566,8 +4570,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) m_Position.w = tmpheading; animation = ppu->animation; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer; MakeSpawnUpdate(ppu); if (gmhideme) @@ -4624,7 +4627,7 @@ void Client::Handle_OP_Consent(const EQApplicationPacket *app) if(app->size<64){ Consent_Struct* c = (Consent_Struct*)app->pBuffer; if(strcmp(c->name, GetName()) != 0) { - ServerPacket* pack = new ServerPacket(ServerOP_Consent, sizeof(ServerOP_Consent_Struct)); + auto pack = new ServerPacket(ServerOP_Consent, sizeof(ServerOP_Consent_Struct)); ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer; strcpy(scs->grantname, c->name); strcpy(scs->ownername, GetName()); @@ -4647,7 +4650,7 @@ void Client::Handle_OP_ConsentDeny(const EQApplicationPacket *app) { if(app->size<64){ Consent_Struct* c = (Consent_Struct*)app->pBuffer; - ServerPacket* pack = new ServerPacket(ServerOP_Consent, sizeof(ServerOP_Consent_Struct)); + auto pack = new ServerPacket(ServerOP_Consent, sizeof(ServerOP_Consent_Struct)); ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)pack->pBuffer; strcpy(scs->grantname, c->name); strcpy(scs->ownername, GetName()); @@ -4680,7 +4683,7 @@ void Client::Handle_OP_Consider(const EQApplicationPacket *app) return; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Consider, sizeof(Consider_Struct)); + auto outapp = new EQApplicationPacket(OP_Consider, sizeof(Consider_Struct)); Consider_Struct* con = (Consider_Struct*)outapp->pBuffer; con->playerid = GetID(); con->targetid = conin->targetid; @@ -4920,7 +4923,7 @@ void Client::Handle_OP_ControlBoat(const EQApplicationPacket *app) else boat->SetTarget(0); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ControlBoat, 0); + auto outapp = new EQApplicationPacket(OP_ControlBoat, 0); FastQueuePacket(&outapp); safe_delete(outapp); // have the boat signal itself, so quests can be triggered by boat use @@ -5165,7 +5168,7 @@ void Client::Handle_OP_DeleteSpawn(const EQApplicationPacket *app) //eqs->RemoveData(); // Flushing the queue of packet data to allow for proper zoning //just make sure this gets out - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LogoutReply); + auto outapp = new EQApplicationPacket(OP_LogoutReply); FastQueuePacket(&outapp); outapp = new EQApplicationPacket(OP_DeleteSpawn, sizeof(EntityId_Struct)); @@ -5343,7 +5346,7 @@ void Client::Handle_OP_DuelResponse2(const EQApplicationPacket *app) Entity* initiator = entity_list.GetID(ds->duel_initiator); if (entity && initiator && entity == this && initiator->IsClient()) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RequestDuel, sizeof(Duel_Struct)); + auto outapp = new EQApplicationPacket(OP_RequestDuel, sizeof(Duel_Struct)); Duel_Struct* ds2 = (Duel_Struct*)outapp->pBuffer; ds2->duel_initiator = entity->GetID(); @@ -5411,7 +5414,7 @@ void Client::Handle_OP_Emote(const EQApplicationPacket *app) + len_msg + 1; // Construct outgoing packet - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Emote, len_packet); + auto outapp = new EQApplicationPacket(OP_Emote, len_packet); Emote_Struct* out = (Emote_Struct*)outapp->pBuffer; out->type = in->type; memcpy(out->message, name, len_name); @@ -5885,7 +5888,7 @@ void Client::Handle_OP_GMFind(const EQApplicationPacket *app) //Break down incoming GMSummon_Struct* request = (GMSummon_Struct*)app->pBuffer; //Create a new outgoing - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMSummon_Struct)); + auto outapp = new EQApplicationPacket(OP_GMFind, sizeof(GMSummon_Struct)); GMSummon_Struct* foundplayer = (GMSummon_Struct*)outapp->pBuffer; //Copy the constants strcpy(foundplayer->charname, request->charname); @@ -5924,7 +5927,7 @@ void Client::Handle_OP_GMGoto(const EQApplicationPacket *app) else if (!worldserver.Connected()) Message(0, "Error: World server disconnected."); else { - ServerPacket* pack = new ServerPacket(ServerOP_GMGoto, sizeof(ServerGMGoto_Struct)); + auto pack = new ServerPacket(ServerOP_GMGoto, sizeof(ServerGMGoto_Struct)); memset(pack->pBuffer, 0, pack->size); ServerGMGoto_Struct* wsgmg = (ServerGMGoto_Struct*)pack->pBuffer; strcpy(wsgmg->myname, this->GetName()); @@ -5970,7 +5973,7 @@ void Client::Handle_OP_GMKick(const EQApplicationPacket *app) if (!worldserver.Connected()) Message(0, "Error: World server disconnected"); else { - ServerPacket* pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); + auto pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*)pack->pBuffer; strcpy(skp->adminname, gmk->gmname); strcpy(skp->name, gmk->name); @@ -6012,7 +6015,7 @@ void Client::Handle_OP_GMKill(const EQApplicationPacket *app) if (!worldserver.Connected()) Message(0, "Error: World server disconnected"); else { - ServerPacket* pack = new ServerPacket(ServerOP_KillPlayer, sizeof(ServerKillPlayer_Struct)); + auto pack = new ServerPacket(ServerOP_KillPlayer, sizeof(ServerKillPlayer_Struct)); ServerKillPlayer_Struct* skp = (ServerKillPlayer_Struct*)pack->pBuffer; strcpy(skp->gmname, gmk->gmname); strcpy(skp->target, gmk->name); @@ -6122,7 +6125,7 @@ void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app) GMSearchCorpse_Struct *gmscs = (GMSearchCorpse_Struct *)app->pBuffer; gmscs->Name[63] = '\0'; - char *escSearchString = new char[129]; + auto escSearchString = new char[129]; database.DoEscapeString(escSearchString, gmscs->Name, strlen(gmscs->Name)); std::string query = StringFormat("SELECT charname, zone_id, x, y, z, time_of_death, is_rezzed, is_buried " @@ -6184,7 +6187,7 @@ void Client::Handle_OP_GMServers(const EQApplicationPacket *app) if (!worldserver.Connected()) Message(0, "Error: World server disconnected"); else { - ServerPacket* pack = new ServerPacket(ServerOP_ZoneStatus, strlen(this->GetName()) + 2); + auto pack = new ServerPacket(ServerOP_ZoneStatus, strlen(this->GetName()) + 2); memset(pack->pBuffer, (uint8)admin, 1); strcpy((char *)&pack->pBuffer[1], this->GetName()); worldserver.SendPacket(pack); @@ -6286,7 +6289,7 @@ void Client::Handle_OP_GMZoneRequest(const EQApplicationPacket *app) tarzone[0] = 0; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMZoneRequest, sizeof(GMZoneRequest_Struct)); + auto outapp = new EQApplicationPacket(OP_GMZoneRequest, sizeof(GMZoneRequest_Struct)); GMZoneRequest_Struct* gmzr2 = (GMZoneRequest_Struct*)outapp->pBuffer; strcpy(gmzr2->charname, this->GetName()); gmzr2->zone_id = gmzr->zone_id; @@ -6346,7 +6349,7 @@ void Client::Handle_OP_GroupCancelInvite(const EQApplicationPacket *app) } else { - ServerPacket* pack = new ServerPacket(ServerOP_GroupCancelInvite, sizeof(GroupCancel_Struct)); + auto pack = new ServerPacket(ServerOP_GroupCancelInvite, sizeof(GroupCancel_Struct)); memcpy(pack->pBuffer, gf, sizeof(GroupCancel_Struct)); worldserver.SendPacket(pack); safe_delete(pack); @@ -6582,7 +6585,7 @@ void Client::Handle_OP_GroupFollow2(const EQApplicationPacket *app) // Inviter is in another zone - Remove merc from group now if any LeaveGroup(); - ServerPacket* pack = new ServerPacket(ServerOP_GroupFollow, sizeof(ServerGroupFollow_Struct)); + auto pack = new ServerPacket(ServerOP_GroupFollow, sizeof(ServerGroupFollow_Struct)); ServerGroupFollow_Struct *sgfs = (ServerGroupFollow_Struct *)pack->pBuffer; sgfs->CharacterID = CharacterID(); strn0cpy(sgfs->gf.name1, gf->name1, sizeof(sgfs->gf.name1)); @@ -6626,7 +6629,8 @@ void Client::Handle_OP_GroupInvite2(const EQApplicationPacket *app) { //Make a new packet using all the same information but make sure it's a fixed GroupInvite opcode so we //Don't have to deal with GroupFollow2 crap. - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupInvite, sizeof(GroupInvite_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupInvite, sizeof(GroupInvite_Struct)); memcpy(outapp->pBuffer, app->pBuffer, outapp->size); Invitee->CastToClient()->QueuePacket(outapp); safe_delete(outapp); @@ -6647,7 +6651,7 @@ void Client::Handle_OP_GroupInvite2(const EQApplicationPacket *app) } else { - ServerPacket* pack = new ServerPacket(ServerOP_GroupInvite, sizeof(GroupInvite_Struct)); + auto pack = new ServerPacket(ServerOP_GroupInvite, sizeof(GroupInvite_Struct)); memcpy(pack->pBuffer, gis, sizeof(GroupInvite_Struct)); worldserver.SendPacket(pack); safe_delete(pack); @@ -7740,7 +7744,7 @@ void Client::Handle_OP_GuildRemove(const EQApplicationPacket *app) } if (!guild_mgr.SetGuild(char_id, GUILD_NONE, 0)) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildManageRemove, sizeof(GuildManageRemove_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildManageRemove, sizeof(GuildManageRemove_Struct)); GuildManageRemove_Struct* gm = (GuildManageRemove_Struct*)outapp->pBuffer; gm->guildeqid = GuildID(); strcpy(gm->member, gc->othername); @@ -7876,7 +7880,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app) float random = zone->random.Real(0, 100); CheckIncreaseSkill(SkillHide, nullptr, 5); if (random < hidechance) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; sa_out->spawn_id = GetID(); sa_out->type = 0x03; @@ -7891,7 +7895,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app) hidden = true; } if (GetClass() == ROGUE){ - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SimpleMessage, sizeof(SimpleMessage_Struct)); + auto outapp = new EQApplicationPacket(OP_SimpleMessage, sizeof(SimpleMessage_Struct)); SimpleMessage_Struct *msg = (SimpleMessage_Struct *)outapp->pBuffer; msg->color = 0x010E; Mob *evadetar = GetTarget(); @@ -8194,7 +8198,7 @@ void Client::Handle_OP_ItemName(const EQApplicationPacket *app) ItemNamePacket_Struct *p = (ItemNamePacket_Struct*)app->pBuffer; const EQEmu::Item_Struct *item = 0; if ((item = database.GetItem(p->item_id)) != nullptr) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ItemName, sizeof(ItemNamePacket_Struct)); + auto outapp = new EQApplicationPacket(OP_ItemName, sizeof(ItemNamePacket_Struct)); p = (ItemNamePacket_Struct*)outapp->pBuffer; memset(p, 0, sizeof(ItemNamePacket_Struct)); strcpy(p->name, item->Name); @@ -8211,7 +8215,8 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app) const EQEmu::Item_Struct* item = database.GetItem(ips->itemid); if (item) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ItemPreview, strlen(item->Name) + strlen(item->Lore) + strlen(item->IDFile) + 898); + auto outapp = new EQApplicationPacket(OP_ItemPreview, strlen(item->Name) + strlen(item->Lore) + + strlen(item->IDFile) + 898); int spacer; for (spacer = 0; spacer < 16; spacer++) { @@ -8658,7 +8663,9 @@ void Client::Handle_OP_LDoNButton(const EQApplicationPacket *app) bool* p = (bool*)app->pBuffer; if (*p == true) { - ServerPacket *pack = new ServerPacket(ServerOP_AdventureRequestCreate, sizeof(ServerAdventureRequestCreate_Struct)+(64 * adv_requested_member_count)); + auto pack = + new ServerPacket(ServerOP_AdventureRequestCreate, + sizeof(ServerAdventureRequestCreate_Struct) + (64 * adv_requested_member_count)); ServerAdventureRequestCreate_Struct *sac = (ServerAdventureRequestCreate_Struct*)pack->pBuffer; strcpy(sac->leader, GetName()); sac->id = adv_requested_id; @@ -8824,7 +8831,7 @@ void Client::Handle_OP_LFGCommand(const EQApplicationPacket *app) UpdateWho(); // Issue outgoing packet to notify other clients - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LFGAppearance, sizeof(LFG_Appearance_Struct)); + auto outapp = new EQApplicationPacket(OP_LFGAppearance, sizeof(LFG_Appearance_Struct)); LFG_Appearance_Struct* lfga = (LFG_Appearance_Struct*)outapp->pBuffer; lfga->spawn_id = this->GetID(); lfga->lfg = (uint8)LFG; @@ -8847,7 +8854,7 @@ void Client::Handle_OP_LFGGetMatchesRequest(const EQApplicationPacket *app) if (!worldserver.Connected()) Message(0, "Error: World server disconnected"); else { - ServerPacket* pack = new ServerPacket(ServerOP_LFGMatches, sizeof(ServerLFGMatchesRequest_Struct)); + auto pack = new ServerPacket(ServerOP_LFGMatches, sizeof(ServerLFGMatchesRequest_Struct)); ServerLFGMatchesRequest_Struct* smrs = (ServerLFGMatchesRequest_Struct*)pack->pBuffer; smrs->FromID = GetID(); smrs->QuerierLevel = GetLevel(); @@ -8885,7 +8892,7 @@ void Client::Handle_OP_LFGuild(const EQApplicationPacket *app) #endif // DARWIN return; - ServerPacket* pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(GetName()) + strlen(pts->Comment) + 38); + auto pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(GetName()) + strlen(pts->Comment) + 38); pack->WriteUInt32(zone->GetZoneID()); pack->WriteUInt32(zone->GetInstanceID()); @@ -8920,7 +8927,9 @@ void Client::Handle_OP_LFGuild(const EQApplicationPacket *app) #endif // __DARWIN return; - ServerPacket* pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(GetName()) + strlen(gts->Comment) + strlen(guild_mgr.GetGuildName(GuildID())) + 43); + auto pack = + new ServerPacket(ServerOP_QueryServGeneric, strlen(GetName()) + strlen(gts->Comment) + + strlen(guild_mgr.GetGuildName(GuildID())) + 43); pack->WriteUInt32(zone->GetZoneID()); pack->WriteUInt32(zone->GetInstanceID()); @@ -8945,7 +8954,7 @@ void Client::Handle_OP_LFGuild(const EQApplicationPacket *app) { VERIFY_PACKET_LENGTH(OP_LFGuild, app, LFGuild_SearchPlayer_Struct); - ServerPacket* pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(GetName()) + 37); + auto pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(GetName()) + 37); pack->WriteUInt32(zone->GetZoneID()); pack->WriteUInt32(zone->GetInstanceID()); @@ -8969,7 +8978,7 @@ void Client::Handle_OP_LFGuild(const EQApplicationPacket *app) { VERIFY_PACKET_LENGTH(OP_LFGuild, app, LFGuild_SearchGuild_Struct); - ServerPacket* pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(GetName()) + 33); + auto pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(GetName()) + 33); pack->WriteUInt32(zone->GetZoneID()); pack->WriteUInt32(zone->GetInstanceID()); @@ -9069,7 +9078,7 @@ void Client::Handle_OP_LFPGetMatchesRequest(const EQApplicationPacket *app) if (!worldserver.Connected()) Message(0, "Error: World server disconnected"); else { - ServerPacket* pack = new ServerPacket(ServerOP_LFPMatches, sizeof(ServerLFPMatchesRequest_Struct)); + auto pack = new ServerPacket(ServerOP_LFPMatches, sizeof(ServerLFPMatchesRequest_Struct)); ServerLFPMatchesRequest_Struct* smrs = (ServerLFPMatchesRequest_Struct*)pack->pBuffer; smrs->FromID = GetID(); smrs->FromLevel = gmrs->FromLevel; @@ -9104,7 +9113,7 @@ void Client::Handle_OP_Logout(const EQApplicationPacket *app) SendLogoutPackets(); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LogoutReply); + auto outapp = new EQApplicationPacket(OP_LogoutReply); FastQueuePacket(&outapp); Disconnect(); @@ -9181,7 +9190,7 @@ void Client::Handle_OP_LootRequest(const EQApplicationPacket *app) if (hidden || improved_hidden){ hidden = false; improved_hidden = false; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; sa_out->spawn_id = GetID(); sa_out->type = 0x03; @@ -9319,7 +9328,7 @@ void Client::Handle_OP_MercenaryCommand(const EQApplicationPacket *app) //get number of available stances for the current merc std::list mercStanceList = zone->merc_stance_list[merc->GetMercTemplateID()]; - std::list::iterator iter = mercStanceList.begin(); + auto iter = mercStanceList.begin(); while (iter != mercStanceList.end()) { numStances++; ++iter; @@ -9403,22 +9412,22 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app) int i = 0; int StanceCount = 0; - for (std::list::iterator mercListItr = mercDataList.begin(); mercListItr != mercDataList.end(); ++mercListItr) - { - std::list::iterator siter = zone->merc_stance_list[mercListItr->MercTemplateID].begin(); + for (auto mercListItr = mercDataList.begin(); mercListItr != mercDataList.end(); ++mercListItr) { + auto siter = zone->merc_stance_list[mercListItr->MercTemplateID].begin(); for (siter = zone->merc_stance_list[mercListItr->MercTemplateID].begin(); siter != zone->merc_stance_list[mercListItr->MercTemplateID].end(); ++siter) { StanceCount++; } } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataResponse, sizeof(MercenaryMerchantList_Struct)); + auto outapp = new EQApplicationPacket(OP_MercenaryDataResponse, sizeof(MercenaryMerchantList_Struct)); MercenaryMerchantList_Struct* mml = (MercenaryMerchantList_Struct*)outapp->pBuffer; mml->MercTypeCount = mercTypeCount; if (mercTypeCount > 0) { - for (std::list::iterator mercTypeListItr = mercTypeList.begin(); mercTypeListItr != mercTypeList.end(); ++mercTypeListItr) { + for (auto mercTypeListItr = mercTypeList.begin(); mercTypeListItr != mercTypeList.end(); + ++mercTypeListItr) { mml->MercGrades[i] = mercTypeListItr->Type; // DBStringID for Type i++; } @@ -9428,8 +9437,8 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app) if (mercCount > 0) { i = 0; - for (std::list::iterator mercListIter = mercDataList.begin(); mercListIter != mercDataList.end(); ++mercListIter) - { + for (auto mercListIter = mercDataList.begin(); mercListIter != mercDataList.end(); + ++mercListIter) { mml->Mercs[i].MercID = mercListIter->MercTemplateID; mml->Mercs[i].MercType = mercListIter->MercType; mml->Mercs[i].MercSubType = mercListIter->MercSubType; @@ -9444,7 +9453,7 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app) mml->Mercs[i].MerchantSlot = i + 1; mml->Mercs[i].MercUnk02 = 1; int mercStanceCount = 0; - std::list::iterator iter = zone->merc_stance_list[mercListIter->MercTemplateID].begin(); + auto iter = zone->merc_stance_list[mercListIter->MercTemplateID].begin(); for (iter = zone->merc_stance_list[mercListIter->MercTemplateID].begin(); iter != zone->merc_stance_list[mercListIter->MercTemplateID].end(); ++iter) { mercStanceCount++; @@ -9456,7 +9465,7 @@ void Client::Handle_OP_MercenaryDataRequest(const EQApplicationPacket *app) int stanceindex = 0; if (mercStanceCount > 0) { - std::list::iterator iter2 = zone->merc_stance_list[mercListIter->MercTemplateID].begin(); + auto iter2 = zone->merc_stance_list[mercListIter->MercTemplateID].begin(); while (iter2 != zone->merc_stance_list[mercListIter->MercTemplateID].end()) { mml->Mercs[i].Stances[stanceindex].StanceIndex = stanceindex; @@ -10255,7 +10264,7 @@ void Client::Handle_OP_Petition(const EQApplicationPacket *app) Message(0, "You already have a petition in the queue, you must wait for it to be answered or use /deletepetition to delete it."); return; } - Petition* pet = new Petition(CharacterID()); + auto pet = new Petition(CharacterID()); pet->SetAName(this->AccountName()); pet->SetClass(this->GetClass()); pet->SetLevel(this->GetLevel()); @@ -10335,7 +10344,7 @@ void Client::Handle_OP_PetitionDelete(const EQApplicationPacket *app) Log.Out(Logs::General, Logs::Error, "Wrong size: OP_PetitionDelete, size=%i, expected %i", app->size, sizeof(PetitionUpdate_Struct)); return; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_PetitionUpdate, sizeof(PetitionUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_PetitionUpdate, sizeof(PetitionUpdate_Struct)); PetitionUpdate_Struct* pet = (PetitionUpdate_Struct*)outapp->pBuffer; pet->petnumber = *((int*)app->pBuffer); pet->color = 0x00; @@ -10451,7 +10460,7 @@ void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) p_timers.Start(pTimerBeggingPickPocket, 8); if (victim == this){ Message(0, "You catch yourself red-handed."); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); + auto outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); sPickPocket_Struct* pick_out = (sPickPocket_Struct*)outapp->pBuffer; pick_out->coin = 0; pick_out->from = victim->GetID(); @@ -10464,7 +10473,7 @@ void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) } else if (victim->GetOwnerID()){ Message(0, "You cannot steal from pets!"); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); + auto outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); sPickPocket_Struct* pick_out = (sPickPocket_Struct*)outapp->pBuffer; pick_out->coin = 0; pick_out->from = victim->GetID(); @@ -10480,7 +10489,7 @@ void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) } else{ Message(0, "Stealing from clients not yet supported."); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); + auto outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); sPickPocket_Struct* pick_out = (sPickPocket_Struct*)outapp->pBuffer; pick_out->coin = 0; pick_out->from = victim->GetID(); @@ -10613,7 +10622,7 @@ void Client::Handle_OP_PurchaseLeadershipAA(const EQApplicationPacket *app) } //success, send them an update - EQApplicationPacket *outapp = new EQApplicationPacket(OP_UpdateLeadershipAA, sizeof(UpdateLeadershipAA_Struct)); + auto outapp = new EQApplicationPacket(OP_UpdateLeadershipAA, sizeof(UpdateLeadershipAA_Struct)); UpdateLeadershipAA_Struct *u = (UpdateLeadershipAA_Struct *)outapp->pBuffer; u->ability_id = aaid; u->new_rank = m_pp.leader_abilities.ranks[aaid]; @@ -10661,7 +10670,7 @@ void Client::Handle_OP_PVPLeaderBoardDetailsRequest(const EQApplicationPacket *a return; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_PVPLeaderBoardDetailsReply, sizeof(PVPLeaderBoardDetailsReply_Struct)); + auto outapp = new EQApplicationPacket(OP_PVPLeaderBoardDetailsReply, sizeof(PVPLeaderBoardDetailsReply_Struct)); PVPLeaderBoardDetailsReply_Struct *pvplbdrs = (PVPLeaderBoardDetailsReply_Struct *)outapp->pBuffer; // TODO: Record and send this data. @@ -10689,7 +10698,7 @@ void Client::Handle_OP_PVPLeaderBoardRequest(const EQApplicationPacket *app) } /*PVPLeaderBoardRequest_Struct *pvplbrs = (PVPLeaderBoardRequest_Struct *)app->pBuffer;*/ //unused - EQApplicationPacket *outapp = new EQApplicationPacket(OP_PVPLeaderBoardReply, sizeof(PVPLeaderBoard_Struct)); + auto outapp = new EQApplicationPacket(OP_PVPLeaderBoardReply, sizeof(PVPLeaderBoard_Struct)); /*PVPLeaderBoard_Struct *pvplb = (PVPLeaderBoard_Struct *)outapp->pBuffer;*/ //unused // TODO: Record and send this data. @@ -10725,7 +10734,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) break; } //This sends an "invite" to the client in question. - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer; strn0cpy(rg->leader_name, ri->leader_name, 64); strn0cpy(rg->player_name, ri->player_name, 64); @@ -11031,7 +11040,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) if (c) r->SendGroupDisband(c); else{ - ServerPacket *pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = + new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); rga->zoneid = zone->GetZoneID(); @@ -11086,7 +11096,10 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) } } else{ - ServerPacket *pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket( + ServerOP_RaidChangeGroup, + sizeof( + ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = r->GetID(); strn0cpy(rga->playername, r->members[x].membername, 64); @@ -11111,7 +11124,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) r->SendGroupDisband(c); } else{ - ServerPacket *pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_RaidGroupDisband, + sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = r->GetID(); rga->zoneid = zone->GetZoneID(); @@ -11155,7 +11169,9 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) } } else{ - ServerPacket *pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket( + ServerOP_RaidChangeGroup, + sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = r->GetID(); strn0cpy(rga->playername, r->members[x].membername, 64); @@ -11173,7 +11189,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) r->SendGroupDisband(c); } else{ - ServerPacket *pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_RaidGroupDisband, + sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = r->GetID(); rga->zoneid = zone->GetZoneID(); @@ -11301,7 +11318,7 @@ void Client::Handle_OP_RandomReq(const EQApplicationPacket *app) } randResult = zone->random.Int(randLow, randHigh); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RandomReply, sizeof(RandomReply_Struct)); + auto outapp = new EQApplicationPacket(OP_RandomReply, sizeof(RandomReply_Struct)); RandomReply_Struct* rr = (RandomReply_Struct*)outapp->pBuffer; rr->low = randLow; rr->high = randHigh; @@ -11504,7 +11521,7 @@ void Client::Handle_OP_RemoveBlockedBuffs(const EQApplicationPacket *app) { std::set::iterator Iterator; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RemoveBlockedBuffs, sizeof(BlockedBuffs_Struct)); + auto outapp = new EQApplicationPacket(OP_RemoveBlockedBuffs, sizeof(BlockedBuffs_Struct)); BlockedBuffs_Struct *obbs = (BlockedBuffs_Struct*)outapp->pBuffer; @@ -12156,7 +12173,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) if (!item){ //error finding item, client didnt get the update packet for whatever reason, roleplay a tad Message(15, "%s tells you 'Sorry, that item is for display purposes only.' as they take the item off the shelf.", tmp->GetCleanName()); - EQApplicationPacket* delitempacket = new EQApplicationPacket(OP_ShopDelItem, sizeof(Merchant_DelItem_Struct)); + auto delitempacket = new EQApplicationPacket(OP_ShopDelItem, sizeof(Merchant_DelItem_Struct)); Merchant_DelItem_Struct* delitem = (Merchant_DelItem_Struct*)delitempacket->pBuffer; delitem->itemslot = mp->itemslot; delitem->npcid = mp->npcid; @@ -12183,7 +12200,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) if (item->Stackable && mp->quantity > item->StackSize) mp->quantity = item->StackSize; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ShopPlayerBuy, sizeof(Merchant_Sell_Struct)); + auto outapp = new EQApplicationPacket(OP_ShopPlayerBuy, sizeof(Merchant_Sell_Struct)); Merchant_Sell_Struct* mpo = (Merchant_Sell_Struct*)outapp->pBuffer; mpo->quantity = mp->quantity; mpo->playerid = mp->playerid; @@ -12270,7 +12287,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) int32 new_charges = prevcharges - mp->quantity; zone->SaveTempItem(merchantid, tmp->GetNPCTypeID(), item_id, new_charges); if (new_charges <= 0){ - EQApplicationPacket* delitempacket = new EQApplicationPacket(OP_ShopDelItem, sizeof(Merchant_DelItem_Struct)); + auto delitempacket = new EQApplicationPacket(OP_ShopDelItem, sizeof(Merchant_DelItem_Struct)); Merchant_DelItem_Struct* delitem = (Merchant_DelItem_Struct*)delitempacket->pBuffer; delitem->itemslot = mp->itemslot; delitem->npcid = mp->npcid; @@ -12295,7 +12312,9 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) // start QS code // stacking purchases not supported at this time - entire process will need some work to catch them properly if (RuleB(QueryServ, PlayerLogMerchantTransactions)) { - ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, sizeof(QSMerchantLogTransaction_Struct)+sizeof(QSTransactionItems_Struct)); + auto qspack = + new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, + sizeof(QSMerchantLogTransaction_Struct) + sizeof(QSTransactionItems_Struct)); QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer; qsaudit->zone_id = zone->GetZoneID(); @@ -12457,7 +12476,9 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) // start QS code if (RuleB(QueryServ, PlayerLogMerchantTransactions)) { - ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, sizeof(QSMerchantLogTransaction_Struct)+sizeof(QSTransactionItems_Struct)); + auto qspack = + new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, + sizeof(QSMerchantLogTransaction_Struct) + sizeof(QSTransactionItems_Struct)); QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer; qsaudit->zone_id = zone->GetZoneID(); @@ -12499,7 +12520,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) if (inst->IsCharged()) mp->quantity = 1; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ShopPlayerSell, sizeof(Merchant_Purchase_Struct)); + auto outapp = new EQApplicationPacket(OP_ShopPlayerSell, sizeof(Merchant_Purchase_Struct)); Merchant_Purchase_Struct* mco = (Merchant_Purchase_Struct*)outapp->pBuffer; mco->npcid = vendor->GetID(); mco->itemslot = mp->itemslot; @@ -12541,7 +12562,7 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app) int action = 1; if (merchantid == 0) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ShopRequest, sizeof(Merchant_Click_Struct)); + auto outapp = new EQApplicationPacket(OP_ShopRequest, sizeof(Merchant_Click_Struct)); Merchant_Click_Struct* mco = (Merchant_Click_Struct*)outapp->pBuffer; mco->npcid = mc->npcid; mco->playerid = 0; @@ -12576,7 +12597,7 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app) action = 0; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ShopRequest, sizeof(Merchant_Click_Struct)); + auto outapp = new EQApplicationPacket(OP_ShopRequest, sizeof(Merchant_Click_Struct)); Merchant_Click_Struct* mco = (Merchant_Click_Struct*)outapp->pBuffer; mco->npcid = mc->npcid; @@ -12615,7 +12636,7 @@ void Client::Handle_OP_Sneak(const EQApplicationPacket *app) sneaking = false; hidden = false; improved_hidden = false; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; sa_out->spawn_id = GetID(); sa_out->type = 0x03; @@ -12631,7 +12652,7 @@ void Client::Handle_OP_Sneak(const EQApplicationPacket *app) if (!was && random < hidechance) { sneaking = true; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; sa_out->spawn_id = GetID(); sa_out->type = 0x0F; @@ -13039,7 +13060,7 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) { //Targeting something we shouldn't with /target //but the client allows this without MQ so you don't flag it - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TargetReject, sizeof(TargetReject_Struct)); + auto outapp = new EQApplicationPacket(OP_TargetReject, sizeof(TargetReject_Struct)); outapp->pBuffer[0] = 0x2f; outapp->pBuffer[1] = 0x01; outapp->pBuffer[4] = 0x0d; @@ -13060,7 +13081,7 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) } else { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TargetReject, sizeof(TargetReject_Struct)); + auto outapp = new EQApplicationPacket(OP_TargetReject, sizeof(TargetReject_Struct)); outapp->pBuffer[0] = 0x2f; outapp->pBuffer[1] = 0x01; outapp->pBuffer[4] = 0x0d; @@ -13291,14 +13312,18 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) event_entry._detail_count = event_details.size(); - ServerPacket* qs_pack = new ServerPacket(ServerOP_QSPlayerLogTrades, sizeof(QSPlayerLogTrade_Struct)+(sizeof(QSTradeItems_Struct)* event_entry._detail_count)); + auto qs_pack = new ServerPacket( + ServerOP_QSPlayerLogTrades, + sizeof(QSPlayerLogTrade_Struct) + + (sizeof(QSTradeItems_Struct) * event_entry._detail_count)); QSPlayerLogTrade_Struct* qs_buf = (QSPlayerLogTrade_Struct*)qs_pack->pBuffer; memcpy(qs_buf, &event_entry, sizeof(QSPlayerLogTrade_Struct)); int offset = 0; - for (std::list::iterator iter = event_details.begin(); iter != event_details.end(); ++iter, ++offset) { + for (auto iter = event_details.begin(); iter != event_details.end(); + ++iter, ++offset) { QSTradeItems_Struct* detail = reinterpret_cast(*iter); qs_buf->items[offset] = *detail; safe_delete(detail); @@ -13323,14 +13348,14 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) trade->Reset(); } // All done - EQApplicationPacket* outapp = new EQApplicationPacket(OP_FinishTrade, 0); + auto outapp = new EQApplicationPacket(OP_FinishTrade, 0); other->QueuePacket(outapp); this->FastQueuePacket(&outapp); } } // Trading with a Mob object that is not a Client. else if (with) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_FinishTrade, 0); + auto outapp = new EQApplicationPacket(OP_FinishTrade, 0); QueuePacket(outapp); safe_delete(outapp); if (with->IsNPC()) { @@ -13345,14 +13370,17 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) event_entry._detail_count = event_details.size(); - ServerPacket* qs_pack = new ServerPacket(ServerOP_QSPlayerLogHandins, sizeof(QSPlayerLogHandin_Struct)+(sizeof(QSHandinItems_Struct)* event_entry._detail_count)); + auto qs_pack = + new ServerPacket(ServerOP_QSPlayerLogHandins, + sizeof(QSPlayerLogHandin_Struct) + + (sizeof(QSHandinItems_Struct) * event_entry._detail_count)); QSPlayerLogHandin_Struct* qs_buf = (QSPlayerLogHandin_Struct*)qs_pack->pBuffer; memcpy(qs_buf, &event_entry, sizeof(QSPlayerLogHandin_Struct)); int offset = 0; - for (std::list::iterator iter = event_details.begin(); iter != event_details.end(); ++iter, ++offset) { + for (auto iter = event_details.begin(); iter != event_details.end(); ++iter, ++offset) { QSHandinItems_Struct* detail = reinterpret_cast(*iter); qs_buf->items[offset] = *detail; safe_delete(detail); @@ -13521,7 +13549,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) // This refreshes the Trader window to display the End Trader button if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Trader, sizeof(TraderStatus_Struct)); + auto outapp = new EQApplicationPacket(OP_Trader, sizeof(TraderStatus_Struct)); TraderStatus_Struct* tss = (TraderStatus_Struct*)outapp->pBuffer; tss->Code = BazaarTrader_StartTraderMode2; QueuePacket(outapp); @@ -13627,7 +13655,7 @@ void Client::Handle_OP_TradeRequest(const EQApplicationPacket *app) //npcs always accept trade->Start(msg->to_mob_id); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeRequestAck, sizeof(TradeRequest_Struct)); + auto outapp = new EQApplicationPacket(OP_TradeRequestAck, sizeof(TradeRequest_Struct)); TradeRequest_Struct* acc = (TradeRequest_Struct*)outapp->pBuffer; acc->from_mob_id = msg->to_mob_id; acc->to_mob_id = msg->from_mob_id; @@ -13677,7 +13705,7 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app) { // This is when a potential purchaser right clicks on this client who is in Trader mode to // browse their goods. - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderShop, sizeof(TraderClick_Struct)); + auto outapp = new EQApplicationPacket(OP_TraderShop, sizeof(TraderClick_Struct)); TraderClick_Struct* outtcs = (TraderClick_Struct*)outapp->pBuffer; @@ -13955,7 +13983,7 @@ void Client::Handle_OP_VetClaimRequest(const EQApplicationPacket *app) return; } // try to claim something! - EQApplicationPacket *vetapp = new EQApplicationPacket(OP_VetClaimReply, sizeof(VeteranClaim)); + auto vetapp = new EQApplicationPacket(OP_VetClaimReply, sizeof(VeteranClaim)); VeteranClaim *cr = (VeteranClaim *)vetapp->pBuffer; strcpy(cr->name, GetName()); cr->claim_id = vcr->claim_id; @@ -14279,7 +14307,7 @@ void Client::Handle_OP_XTargetRequest(const EQApplicationPacket *app) void Client::Handle_OP_YellForHelp(const EQApplicationPacket *app) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_YellForHelp, 4); + auto outapp = new EQApplicationPacket(OP_YellForHelp, 4); *(uint32 *)outapp->pBuffer = GetID(); entity_list.QueueCloseClients(this, outapp, true, 100.0); safe_delete(outapp); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index e5fd2ec99..984a66240 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -726,7 +726,7 @@ void Client::OnDisconnect(bool hard_disconnect) { /* Remove ourself from all proximities */ ClearAllProximities(); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LogoutReply); + auto outapp = new EQApplicationPacket(OP_LogoutReply); FastQueuePacket(&outapp); Disconnect(); @@ -817,7 +817,7 @@ void Client::BulkSendInventoryItems() last_pos = ob.tellp(); } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CharInventory); + auto outapp = new EQApplicationPacket(OP_CharInventory); outapp->size = ob.size(); outapp->pBuffer = ob.detach(); QueuePacket(outapp); @@ -1131,7 +1131,7 @@ void Client::BreakInvis() { if (invisible) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; sa_out->spawn_id = GetID(); sa_out->type = 0x03; @@ -1444,7 +1444,7 @@ void Client::OPMoveCoin(const EQApplicationPacket* app) trade->sp, trade->cp ); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeCoins,sizeof(TradeCoin_Struct)); + auto outapp = new EQApplicationPacket(OP_TradeCoins, sizeof(TradeCoin_Struct)); TradeCoin_Struct* tcs = (TradeCoin_Struct*)outapp->pBuffer; tcs->trader = trader->GetID(); tcs->slot = mc->cointype2; @@ -1513,7 +1513,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app) void Client::OPGMEndTraining(const EQApplicationPacket *app) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GMEndTrainingResponse, 0); + auto outapp = new EQApplicationPacket(OP_GMEndTrainingResponse, 0); GMTrainEnd_Struct *p = (GMTrainEnd_Struct *)app->pBuffer; FastQueuePacket(&outapp); @@ -1675,7 +1675,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app) // The following packet decreases the skill points left in the Training Window and // produces the 'You have increased your skill / learned the basics of' message. // - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMTrainSkillConfirm, sizeof(GMTrainSkillConfirm_Struct)); + auto outapp = new EQApplicationPacket(OP_GMTrainSkillConfirm, sizeof(GMTrainSkillConfirm_Struct)); GMTrainSkillConfirm_Struct *gmtsc = (GMTrainSkillConfirm_Struct *)outapp->pBuffer; gmtsc->SkillID = gmskill->skill_id; @@ -1733,7 +1733,7 @@ void Client::OPGMSummon(const EQApplicationPacket *app) } else if (tmp < '0' || tmp > '9') // dont send to world if it's not a player's name { - ServerPacket* pack = new ServerPacket(ServerOP_ZonePlayer, sizeof(ServerZonePlayer_Struct)); + auto pack = new ServerPacket(ServerOP_ZonePlayer, sizeof(ServerZonePlayer_Struct)); ServerZonePlayer_Struct* szp = (ServerZonePlayer_Struct*) pack->pBuffer; strcpy(szp->adminname, this->GetName()); szp->adminrank = this->Admin(); @@ -1775,7 +1775,7 @@ void Client::DoStaminaUpdate() { if(!stamina_timer.Check()) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); + auto outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer; if(zone->GetZoneID() != 151) { @@ -2001,7 +2001,8 @@ void Client::HandleRespawnFromHover(uint32 Option) m_Position.z = corpse->GetZ(); } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + 10); + auto outapp = + new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + 10); ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer; gmg->bind_zone_id = zone->GetZoneID(); @@ -2033,7 +2034,8 @@ void Client::HandleRespawnFromHover(uint32 Option) { PendingRezzSpellID = 0; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + chosen->name.length() + 1); + auto outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + + chosen->name.length() + 1); ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer; gmg->bind_zone_id = zone->GetZoneID(); @@ -2100,7 +2102,7 @@ void Client::ClearHover() // Our Entity ID is currently zero, set in Client::Death SetID(entity_list.GetFreeID()); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ZoneEntry, sizeof(ServerZoneEntry_Struct)); + auto outapp = new EQApplicationPacket(OP_ZoneEntry, sizeof(ServerZoneEntry_Struct)); ServerZoneEntry_Struct* sze = (ServerZoneEntry_Struct*)outapp->pBuffer; FillSpawnStruct(&sze->player,CastToMob()); @@ -2152,7 +2154,7 @@ void Client::HandleLFGuildResponse(ServerPacket *pack) --i; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LFGuild, PacketSize); + auto outapp = new EQApplicationPacket(OP_LFGuild, PacketSize); outapp->WriteUInt32(3); outapp->WriteUInt32(0xeb63); // Don't know the significance of this value. outapp->WriteUInt32(NumberOfMatches); @@ -2180,7 +2182,7 @@ void Client::HandleLFGuildResponse(ServerPacket *pack) } case QSG_LFGuild_RequestPlayerInfo: { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LFGuild, sizeof(LFGuild_PlayerToggle_Struct)); + auto outapp = new EQApplicationPacket(OP_LFGuild, sizeof(LFGuild_PlayerToggle_Struct)); LFGuild_PlayerToggle_Struct *pts = (LFGuild_PlayerToggle_Struct *)outapp->pBuffer; pts->Command = 0; @@ -2210,7 +2212,7 @@ void Client::HandleLFGuildResponse(ServerPacket *pack) --i; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LFGuild, PacketSize); + auto outapp = new EQApplicationPacket(OP_LFGuild, PacketSize); outapp->WriteUInt32(4); outapp->WriteUInt32(0xeb63); outapp->WriteUInt32(NumberOfMatches); @@ -2244,7 +2246,7 @@ void Client::HandleLFGuildResponse(ServerPacket *pack) TimeZone = pack->ReadUInt32(); TimePosted = pack->ReadUInt32(); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LFGuild, sizeof(LFGuild_GuildToggle_Struct)); + auto outapp = new EQApplicationPacket(OP_LFGuild, sizeof(LFGuild_GuildToggle_Struct)); LFGuild_GuildToggle_Struct *gts = (LFGuild_GuildToggle_Struct *)outapp->pBuffer; gts->Command = 1; @@ -2271,7 +2273,7 @@ void Client::HandleLFGuildResponse(ServerPacket *pack) void Client::SendLFGuildStatus() { - ServerPacket* pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(GetName()) + 17); + auto pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(GetName()) + 17); pack->WriteUInt32(zone->GetZoneID()); pack->WriteUInt32(zone->GetInstanceID()); @@ -2286,7 +2288,8 @@ void Client::SendLFGuildStatus() void Client::SendGuildLFGuildStatus() { - ServerPacket* pack = new ServerPacket(ServerOP_QueryServGeneric, strlen(GetName()) + +strlen(guild_mgr.GetGuildName(GuildID())) + 18); + auto pack = new ServerPacket(ServerOP_QueryServGeneric, + strlen(GetName()) + +strlen(guild_mgr.GetGuildName(GuildID())) + 18); pack->WriteUInt32(zone->GetZoneID()); pack->WriteUInt32(zone->GetInstanceID()); diff --git a/zone/command.cpp b/zone/command.cpp index 2d341ef7d..dd2b8941e 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -426,8 +426,8 @@ int command_init(void) database.GetCommandSettings(command_settings); std::map working_cl = commandlist; - for (std::map::iterator iter_cl = working_cl.begin(); iter_cl != working_cl.end(); ++iter_cl) { - std::map>>::iterator iter_cs = command_settings.find(iter_cl->first); + for (auto iter_cl = working_cl.begin(); iter_cl != working_cl.end(); ++iter_cl) { + auto iter_cs = command_settings.find(iter_cl->first); if (iter_cs == command_settings.end()) { if (iter_cl->second->access == 0) Log.Out(Logs::General, Logs::Commands, "command_init(): Warning: Command '%s' defaulting to access level 0!", iter_cl->first.c_str()); @@ -439,7 +439,8 @@ int command_init(void) if (iter_cs->second.second.empty()) continue; - for (std::vector::iterator iter_aka = iter_cs->second.second.begin(); iter_aka != iter_cs->second.second.end(); ++iter_aka) { + for (auto iter_aka = iter_cs->second.second.begin(); iter_aka != iter_cs->second.second.end(); + ++iter_aka) { if (iter_aka->empty()) continue; if (commandlist.find(*iter_aka) != commandlist.end()) { @@ -501,14 +502,14 @@ int command_add(std::string command_name, const char *desc, int access, CmdFuncP Log.Out(Logs::General, Logs::Error, "command_add() - Command '%s' is a duplicate command name - check command.cpp.", command_name.c_str()); return -1; } - for (std::map::iterator iter = commandlist.begin(); iter != commandlist.end(); ++iter) { + for (auto iter = commandlist.begin(); iter != commandlist.end(); ++iter) { if (iter->second->function != function) continue; Log.Out(Logs::General, Logs::Error, "command_add() - Command '%s' equates to an alias of '%s' - check command.cpp.", command_name.c_str(), iter->first.c_str()); return -1; } - CommandRecord *c = new CommandRecord; + auto c = new CommandRecord; c->access = access; c->desc = desc; c->function = function; @@ -995,7 +996,7 @@ void command_summon(Client *c, const Seperator *sep) //c->Message(0, "Summoning player from another zone not yet implemented."); //return; - ServerPacket* pack = new ServerPacket(ServerOP_ZonePlayer, sizeof(ServerZonePlayer_Struct)); + auto pack = new ServerPacket(ServerOP_ZonePlayer, sizeof(ServerZonePlayer_Struct)); ServerZonePlayer_Struct* szp = (ServerZonePlayer_Struct*) pack->pBuffer; strcpy(szp->adminname, c->GetName()); szp->adminrank = c->Admin(); @@ -1390,7 +1391,7 @@ void command_timezone(Client *c, const Seperator *sep) database.SetZoneTZ(zone->GetZoneID(), zone->GetInstanceVersion(), ntz); // Update all clients with new TZ. - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct)); + auto outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct)); TimeOfDay_Struct* tod = (TimeOfDay_Struct*)outapp->pBuffer; zone->zone_time.GetCurrentEQTimeOfDay(time(0), tod); entity_list.QueueClients(c, outapp); @@ -1503,7 +1504,7 @@ void command_zclip(Client *c, const Seperator *sep) zone->newzone_data.fog_maxclip[0]=atof(sep->arg[5]); if(sep->arg[6][0]!=0) zone->newzone_data.fog_maxclip[1]=atof(sep->arg[6]); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); + auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(c, outapp); safe_delete(outapp); @@ -1617,7 +1618,7 @@ void command_weather(Client *c, const Seperator *sep) if(sep->arg[2][0] != 0 && sep->arg[3][0] != 0) { c->Message(0, "Sending weather packet... TYPE=%s, INTENSITY=%s", sep->arg[2], sep->arg[3]); zone->zone_weather = atoi(sep->arg[2]); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weather, 8); + auto outapp = new EQApplicationPacket(OP_Weather, 8); outapp->pBuffer[0] = atoi(sep->arg[2]); outapp->pBuffer[4] = atoi(sep->arg[3]); // This number changes in the packets, intensity? entity_list.QueueClients(c, outapp); @@ -1630,7 +1631,7 @@ void command_weather(Client *c, const Seperator *sep) else if(sep->arg[1][0] == '2') { entity_list.Message(0, 0, "Snowflakes begin to fall from the sky."); zone->zone_weather = 2; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weather, 8); + auto outapp = new EQApplicationPacket(OP_Weather, 8); outapp->pBuffer[0] = 0x01; outapp->pBuffer[4] = 0x02; // This number changes in the packets, intensity? entity_list.QueueClients(c, outapp); @@ -1639,7 +1640,7 @@ void command_weather(Client *c, const Seperator *sep) else if(sep->arg[1][0] == '1') { entity_list.Message(0, 0, "Raindrops begin to fall from the sky."); zone->zone_weather = 1; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weather, 8); + auto outapp = new EQApplicationPacket(OP_Weather, 8); outapp->pBuffer[4] = 0x01; // This is how it's done in Fear, and you can see a decent distance with it at this value entity_list.QueueClients(c, outapp); safe_delete(outapp); @@ -1649,7 +1650,7 @@ void command_weather(Client *c, const Seperator *sep) if(zone->zone_weather == 1) { // Doing this because if you have rain/snow on, you can only turn one off. entity_list.Message(0, 0, "The sky clears as the rain ceases to fall."); zone->zone_weather = 0; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weather, 8); + auto outapp = new EQApplicationPacket(OP_Weather, 8); // To shutoff weather you send an empty 8 byte packet (You get this everytime you zone even if the sky is clear) entity_list.QueueClients(c, outapp); safe_delete(outapp); @@ -1657,7 +1658,7 @@ void command_weather(Client *c, const Seperator *sep) else if(zone->zone_weather == 2) { entity_list.Message(0, 0, "The sky clears as the snow stops falling."); zone->zone_weather = 0; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weather, 8); + auto outapp = new EQApplicationPacket(OP_Weather, 8); // To shutoff weather you send an empty 8 byte packet (You get this everytime you zone even if the sky is clear) outapp->pBuffer[0] = 0x01; // Snow has it's own shutoff packet entity_list.QueueClients(c, outapp); @@ -1666,7 +1667,7 @@ void command_weather(Client *c, const Seperator *sep) else { entity_list.Message(0, 0, "The sky clears."); zone->zone_weather = 0; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weather, 8); + auto outapp = new EQApplicationPacket(OP_Weather, 8); // To shutoff weather you send an empty 8 byte packet (You get this everytime you zone even if the sky is clear) entity_list.QueueClients(c, outapp); safe_delete(outapp); @@ -1688,7 +1689,7 @@ void command_zheader(Client *c, const Seperator *sep) c->Message(0, "Successfully loaded zone header for %s from database.", sep->argplus[1]); else c->Message(0, "Failed to load zone header %s from database", sep->argplus[1]); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); + auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(c, outapp); safe_delete(outapp); @@ -1704,7 +1705,7 @@ void command_zsky(Client *c, const Seperator *sep) c->Message(0, "ERROR: Sky type can not be less than 0 or greater than 255!"); else { zone->newzone_data.sky = atoi(sep->arg[1]); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); + auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(c, outapp); safe_delete(outapp); @@ -1728,7 +1729,7 @@ void command_zcolor(Client *c, const Seperator *sep) zone->newzone_data.fog_green[z] = atoi(sep->arg[2]); zone->newzone_data.fog_blue[z] = atoi(sep->arg[3]); } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); + auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(c, outapp); safe_delete(outapp); @@ -1742,7 +1743,7 @@ void command_spon(Client *c, const Seperator *sep) void command_spoff(Client *c, const Seperator *sep) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ManaChange, 0); + auto outapp = new EQApplicationPacket(OP_ManaChange, 0); outapp->priority = 5; c->QueuePacket(outapp); safe_delete(outapp); @@ -1761,7 +1762,7 @@ void command_itemtest(Client *c, const Seperator *sep) fread(chBuffer, sizeof(chBuffer), sizeof(char), f); fclose(f); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ItemLinkResponse, strlen(chBuffer)+5); + auto outapp = new EQApplicationPacket(OP_ItemLinkResponse, strlen(chBuffer) + 5); memcpy(&outapp->pBuffer[4], chBuffer, strlen(chBuffer)); c->QueuePacket(outapp); safe_delete(outapp); @@ -1884,7 +1885,7 @@ void command_worldshutdown(Client *c, const Seperator *sep) if(sep->IsNumber(1) && sep->IsNumber(2) && ((time=atoi(sep->arg[1]))>0) && ((interval=atoi(sep->arg[2]))>0)) { worldserver.SendEmoteMessage(0,0,15,":SYSTEM MSG:World coming down in %i minutes, everyone log out before this time.", (time / 60 )); c->Message(0, "Sending shutdown packet now, World will shutdown in: %i minutes with an interval of: %i seconds", (time / 60), interval); - ServerPacket* pack = new ServerPacket(ServerOP_ShutdownAll,sizeof(WorldShutDown_Struct)); + auto pack = new ServerPacket(ServerOP_ShutdownAll, sizeof(WorldShutDown_Struct)); WorldShutDown_Struct* wsd = (WorldShutDown_Struct*)pack->pBuffer; wsd->time=time*1000; wsd->interval=(interval*1000); @@ -1894,7 +1895,7 @@ void command_worldshutdown(Client *c, const Seperator *sep) else if(strcasecmp(sep->arg[1], "now") == 0){ worldserver.SendEmoteMessage(0,0,15,":SYSTEM MSG:World coming down, everyone log out now."); c->Message(0, "Sending shutdown packet"); - ServerPacket* pack = new ServerPacket; + auto pack = new ServerPacket; pack->opcode = ServerOP_ShutdownAll; pack->size=0; worldserver.SendPacket(pack); @@ -1902,7 +1903,7 @@ void command_worldshutdown(Client *c, const Seperator *sep) } else if(strcasecmp(sep->arg[1], "disable") == 0){ c->Message(0, "Shutdown prevented, next time I may not be so forgiving..."); - ServerPacket* pack = new ServerPacket(ServerOP_ShutdownAll,sizeof(WorldShutDown_Struct)); + auto pack = new ServerPacket(ServerOP_ShutdownAll, sizeof(WorldShutDown_Struct)); WorldShutDown_Struct* wsd = (WorldShutDown_Struct*)pack->pBuffer; wsd->time=0; wsd->interval=0; @@ -1991,7 +1992,7 @@ void command_setlsinfo(Client *c, const Seperator *sep) if(sep->argnum != 2) c->Message(0, "Format: #setlsinfo email password"); else { - ServerPacket* pack = new ServerPacket(ServerOP_LSAccountUpdate, sizeof(ServerLSAccountUpdate_Struct)); + auto pack = new ServerPacket(ServerOP_LSAccountUpdate, sizeof(ServerLSAccountUpdate_Struct)); ServerLSAccountUpdate_Struct* s = (ServerLSAccountUpdate_Struct *) pack->pBuffer; s->useraccountid = c->LSAccountID(); strn0cpy(s->useraccount, c->AccountName(), 30); @@ -2040,7 +2041,8 @@ void command_wp(Client *c, const Seperator *sep) void command_iplookup(Client *c, const Seperator *sep) { - ServerPacket* pack = new ServerPacket(ServerOP_IPLookup, sizeof(ServerGenericWorldQuery_Struct) + strlen(sep->argplus[1]) + 1); + auto pack = + new ServerPacket(ServerOP_IPLookup, sizeof(ServerGenericWorldQuery_Struct) + strlen(sep->argplus[1]) + 1); ServerGenericWorldQuery_Struct* s = (ServerGenericWorldQuery_Struct *) pack->pBuffer; strcpy(s->from, c->GetName()); s->admin = c->Admin(); @@ -2453,7 +2455,7 @@ void command_npctypespawn(Client *c, const Seperator *sep) const NPCType* tmp = 0; if ((tmp = database.LoadNPCTypesData(atoi(sep->arg[1])))) { //tmp->fixedZ = 1; - NPC* npc = new NPC(tmp, 0, c->GetPosition(), FlyMode3); + auto npc = new NPC(tmp, 0, c->GetPosition(), FlyMode3); if (npc && sep->IsNumber(2)) npc->SetNPCFactionID(atoi(sep->arg[2])); @@ -2900,12 +2902,13 @@ void command_findzone(Client *c, const Seperator *sep) std::string query; int id = atoi((const char *)sep->arg[1]); if (id == 0) { // If id evaluates to 0, then search as if user entered a string. - char *escName = new char[strlen(sep->arg[1]) * 2 + 1]; - database.DoEscapeString(escName, sep->arg[1], strlen(sep->arg[1])); + auto escName = new char[strlen(sep->arg[1]) * 2 + 1]; + database.DoEscapeString(escName, sep->arg[1], strlen(sep->arg[1])); - query = StringFormat("SELECT zoneidnumber, short_name, long_name FROM zone " - "WHERE long_name RLIKE '%s' AND version = 0", escName); - safe_delete_array(escName); + query = StringFormat("SELECT zoneidnumber, short_name, long_name FROM zone " + "WHERE long_name RLIKE '%s' AND version = 0", + escName); + safe_delete_array(escName); } else // Otherwise, look for just that zoneidnumber. query = StringFormat("SELECT zoneidnumber, short_name, long_name FROM zone " @@ -2983,7 +2986,7 @@ void command_reloadqst(Client *c, const Seperator *sep) void command_reloadworld(Client *c, const Seperator *sep) { c->Message(0, "Reloading quest cache and repopping zones worldwide."); - ServerPacket* pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct)); + auto pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct)); ReloadWorld_Struct* RW = (ReloadWorld_Struct*) pack->pBuffer; RW->Option = ((atoi(sep->arg[1]) == 1) ? 1 : 0); worldserver.SendPacket(pack); @@ -3016,7 +3019,7 @@ void command_zoneshutdown(Client *c, const Seperator *sep) else if (sep->arg[1][0] == 0) c->Message(0, "Usage: #zoneshutdown zoneshortname"); else { - ServerPacket* pack = new ServerPacket(ServerOP_ZoneShutdown, sizeof(ServerZoneStateChange_struct)); + auto pack = new ServerPacket(ServerOP_ZoneShutdown, sizeof(ServerZoneStateChange_struct)); ServerZoneStateChange_struct* s = (ServerZoneStateChange_struct *) pack->pBuffer; strcpy(s->adminname, c->GetName()); if (sep->arg[1][0] >= '0' && sep->arg[1][0] <= '9') @@ -3036,7 +3039,7 @@ void command_zonebootup(Client *c, const Seperator *sep) c->Message(0, "Usage: #zonebootup ZoneServerID# zoneshortname"); } else { - ServerPacket* pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_struct)); + auto pack = new ServerPacket(ServerOP_ZoneBootup, sizeof(ServerZoneStateChange_struct)); ServerZoneStateChange_struct* s = (ServerZoneStateChange_struct *) pack->pBuffer; s->ZoneServerID = atoi(sep->arg[1]); strcpy(s->adminname, c->GetName()); @@ -3056,7 +3059,7 @@ void command_kick(Client *c, const Seperator *sep) if (client != 0) { if (client->Admin() <= c->Admin()) { client->Message(0, "You have been kicked by %s", c->GetName()); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMKick,0); + auto outapp = new EQApplicationPacket(OP_GMKick, 0); client->QueuePacket(outapp); client->Kick(); c->Message(0, "Kick: local: kicking %s", sep->arg[1]); @@ -3065,7 +3068,7 @@ void command_kick(Client *c, const Seperator *sep) else if (!worldserver.Connected()) c->Message(0, "Error: World server disconnected"); else { - ServerPacket* pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); + auto pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer; strcpy(skp->adminname, c->GetName()); strcpy(skp->name, sep->arg[1]); @@ -3091,7 +3094,7 @@ void command_attack(Client *c, const Seperator *sep) void command_lock(Client *c, const Seperator *sep) { - ServerPacket* outpack = new ServerPacket(ServerOP_Lock, sizeof(ServerLock_Struct)); + auto outpack = new ServerPacket(ServerOP_Lock, sizeof(ServerLock_Struct)); ServerLock_Struct* lss = (ServerLock_Struct*) outpack->pBuffer; strcpy(lss->myname, c->GetName()); lss->mode = 1; @@ -3101,7 +3104,7 @@ void command_lock(Client *c, const Seperator *sep) void command_unlock(Client *c, const Seperator *sep) { - ServerPacket* outpack = new ServerPacket(ServerOP_Lock, sizeof(ServerLock_Struct)); + auto outpack = new ServerPacket(ServerOP_Lock, sizeof(ServerLock_Struct)); ServerLock_Struct* lss = (ServerLock_Struct*) outpack->pBuffer; strcpy(lss->myname, c->GetName()); lss->mode = 0; @@ -3111,7 +3114,7 @@ void command_unlock(Client *c, const Seperator *sep) void command_motd(Client *c, const Seperator *sep) { - ServerPacket* outpack = new ServerPacket(ServerOP_Motd, sizeof(ServerMotd_Struct)); + auto outpack = new ServerPacket(ServerOP_Motd, sizeof(ServerMotd_Struct)); ServerMotd_Struct* mss = (ServerMotd_Struct*) outpack->pBuffer; strn0cpy(mss->myname, c->GetName(),64); strn0cpy(mss->motd, sep->argplus[1],512); @@ -3147,7 +3150,7 @@ void command_equipitem(Client *c, const Seperator *sep) int16 movecount; if (from_inst && from_inst->IsClassCommon()) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); + auto outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer; mi->from_slot = EQEmu::legacy::SlotCursor; mi->to_slot = slot_id; @@ -3215,7 +3218,7 @@ void command_equipitem(Client *c, const Seperator *sep) void command_zonelock(Client *c, const Seperator *sep) { - ServerPacket* pack = new ServerPacket(ServerOP_LockZone, sizeof(ServerLockZone_Struct)); + auto pack = new ServerPacket(ServerOP_LockZone, sizeof(ServerLockZone_Struct)); ServerLockZone_Struct* s = (ServerLockZone_Struct*) pack->pBuffer; strn0cpy(s->adminname, c->GetName(), sizeof(s->adminname)); if (strcasecmp(sep->arg[1], "list") == 0) { @@ -3994,7 +3997,7 @@ void command_zuwcoords(Client *c, const Seperator *sep) zone->newzone_data.underworld = atof(sep->arg[1]); //float newdata = atof(sep->arg[1]); //memcpy(&zone->zone_header_data[130], &newdata, sizeof(float)); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); + auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(c, outapp); safe_delete(outapp); @@ -4026,7 +4029,7 @@ void command_zsafecoords(Client *c, const Seperator *sep) //memcpy(&zone->zone_header_data[118], &newdatay, sizeof(float)); //memcpy(&zone->zone_header_data[122], &newdataz, sizeof(float)); //zone->SetSafeCoords(); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); + auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(c, outapp); safe_delete(outapp); @@ -4385,7 +4388,7 @@ void command_uptime(Client *c, const Seperator *sep) c->Message(0, "Error: World server disconnected"); else { - ServerPacket* pack = new ServerPacket(ServerOP_Uptime, sizeof(ServerUptime_Struct)); + auto pack = new ServerPacket(ServerOP_Uptime, sizeof(ServerUptime_Struct)); ServerUptime_Struct* sus = (ServerUptime_Struct*) pack->pBuffer; strcpy(sus->adminname, c->GetName()); if (sep->IsNumber(1) && atoi(sep->arg[1]) > 0) @@ -4425,7 +4428,7 @@ void command_flag(Client *c, const Seperator *sep) c->Message(0, "Unable to set GM Flag."); else { c->Message(0, "Set GM Flag on account."); - ServerPacket* pack = new ServerPacket(ServerOP_FlagUpdate, 6); + auto pack = new ServerPacket(ServerOP_FlagUpdate, 6); *((uint32*) pack->pBuffer) = database.GetAccountIDByName(sep->argplus[2]); *((int16*) &pack->pBuffer[4]) = atoi(sep->arg[1]); worldserver.SendPacket(pack); @@ -4888,7 +4891,7 @@ void command_zonestatus(Client *c, const Seperator *sep) if (!worldserver.Connected()) c->Message(0, "Error: World server disconnected"); else { - ServerPacket* pack = new ServerPacket(ServerOP_ZoneStatus, strlen(c->GetName())+2); + auto pack = new ServerPacket(ServerOP_ZoneStatus, strlen(c->GetName()) + 2); memset(pack->pBuffer, (uint8) c->Admin(), 1); strcpy((char *) &pack->pBuffer[1], c->GetName()); worldserver.SendPacket(pack); @@ -4961,14 +4964,14 @@ void command_findaliases(Client *c, const Seperator *sep) c->Message(0, "Usage: #findaliases [alias | command]"); return; } - - std::map::iterator find_iter = commandaliases.find(sep->arg[1]); + + auto find_iter = commandaliases.find(sep->arg[1]); if (find_iter == commandaliases.end()) { c->Message(15, "No commands or aliases match '%s'", sep->arg[1]); return; } - std::map::iterator command_iter = commandlist.find(find_iter->second); + auto command_iter = commandlist.find(find_iter->second); if (find_iter->second.empty() || command_iter == commandlist.end()) { c->Message(0, "An unknown condition occurred..."); return; @@ -4977,7 +4980,7 @@ void command_findaliases(Client *c, const Seperator *sep) c->Message(0, "Available command aliases for '%s':", command_iter->first.c_str()); int commandaliasesshown = 0; - for (std::map::iterator alias_iter = commandaliases.begin(); alias_iter != commandaliases.end(); ++alias_iter) { + for (auto alias_iter = commandaliases.begin(); alias_iter != commandaliases.end(); ++alias_iter) { if (strcasecmp(find_iter->second.c_str(), alias_iter->second.c_str()) || c->Admin() < command_iter->second->access) continue; @@ -5845,7 +5848,7 @@ void command_suspend(Client *c, const Seperator *sep) } } - char *escName = new char[strlen(sep->arg[1]) * 2 + 1]; + auto escName = new char[strlen(sep->arg[1]) * 2 + 1]; database.DoEscapeString(escName, sep->arg[1], strlen(sep->arg[1])); int accountID = database.GetAccountIDByChar(escName); safe_delete_array(escName); @@ -5872,16 +5875,16 @@ void command_suspend(Client *c, const Seperator *sep) return; } - ServerPacket* pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); - ServerKickPlayer_Struct* sks = (ServerKickPlayer_Struct*) pack->pBuffer; + auto pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct)); + ServerKickPlayer_Struct *sks = (ServerKickPlayer_Struct *)pack->pBuffer; - strn0cpy(sks->adminname, c->GetName(), sizeof(sks->adminname)); - strn0cpy(sks->name, sep->arg[1], sizeof(sks->name)); - sks->adminrank = c->Admin(); + strn0cpy(sks->adminname, c->GetName(), sizeof(sks->adminname)); + strn0cpy(sks->name, sep->arg[1], sizeof(sks->name)); + sks->adminrank = c->Admin(); - worldserver.SendPacket(pack); + worldserver.SendPacket(pack); - safe_delete(pack); + safe_delete(pack); } void command_ipban(Client *c, const Seperator *sep) @@ -5926,13 +5929,13 @@ void command_revoke(Client *c, const Seperator *sep) c->Message(13, "#revoke: Couldn't find %s in this zone, passing request to worldserver.", sep->arg[1]); - ServerPacket * outapp = new ServerPacket (ServerOP_Revoke,sizeof(RevokeStruct)); - RevokeStruct* revoke = (RevokeStruct*)outapp->pBuffer; - strn0cpy(revoke->adminname, c->GetName(), 64); - strn0cpy(revoke->name, sep->arg[1], 64); - revoke->toggle = flag; - worldserver.SendPacket(outapp); - safe_delete(outapp); + auto outapp = new ServerPacket(ServerOP_Revoke, sizeof(RevokeStruct)); + RevokeStruct *revoke = (RevokeStruct *)outapp->pBuffer; + strn0cpy(revoke->adminname, c->GetName(), 64); + strn0cpy(revoke->name, sep->arg[1], 64); + revoke->toggle = flag; + worldserver.SendPacket(outapp); + safe_delete(outapp); } void command_oocmute(Client *c, const Seperator *sep) @@ -5940,10 +5943,10 @@ void command_oocmute(Client *c, const Seperator *sep) if(sep->arg[1][0] == 0 || !(sep->arg[1][0] == '1' || sep->arg[1][0] == '0')) c->Message(0, "Usage: #oocmute [1/0]"); else { - ServerPacket * outapp = new ServerPacket (ServerOP_OOCMute,1); - *(outapp->pBuffer)=atoi(sep->arg[1]); - worldserver.SendPacket(outapp); - safe_delete(outapp); + auto outapp = new ServerPacket(ServerOP_OOCMute, 1); + *(outapp->pBuffer) = atoi(sep->arg[1]); + worldserver.SendPacket(outapp); + safe_delete(outapp); } } @@ -7773,7 +7776,7 @@ void command_task(Client *c, const Seperator *sep) { } void command_reloadtitles(Client *c, const Seperator *sep) { - ServerPacket* pack = new ServerPacket(ServerOP_ReloadTitles, 0); + auto pack = new ServerPacket(ServerOP_ReloadTitles, 0); worldserver.SendPacket(pack); safe_delete(pack); c->Message(15, "Player Titles Reloaded."); @@ -9862,7 +9865,7 @@ void command_globalview(Client *c, const Seperator *sep) QGlobalCache::Combine(globalMap, zone_c->GetBucket(), ntype, c->CharacterID(), zone->GetZoneID()); } - std::list::iterator iter = globalMap.begin(); + auto iter = globalMap.begin(); uint32 gcount = 0; c->Message(0, "Name, Value"); @@ -9895,7 +9898,7 @@ void command_globalview(Client *c, const Seperator *sep) QGlobalCache::Combine(globalMap, zone_c->GetBucket(), ntype, c->CharacterID(), zone->GetZoneID()); } - std::list::iterator iter = globalMap.begin(); + auto iter = globalMap.begin(); uint32 gcount = 0; c->Message(0, "Name, Value"); @@ -9921,7 +9924,8 @@ void command_cvs(Client *c, const Seperator *sep) { if(c) { - ServerPacket *pack = new ServerPacket(ServerOP_ClientVersionSummary, sizeof(ServerRequestClientVersionSummary_Struct)); + auto pack = + new ServerPacket(ServerOP_ClientVersionSummary, sizeof(ServerRequestClientVersionSummary_Struct)); ServerRequestClientVersionSummary_Struct *srcvss = (ServerRequestClientVersionSummary_Struct*)pack->pBuffer; @@ -9981,7 +9985,7 @@ void command_reloadallrules(Client *c, const Seperator *sep) { if(c) { - ServerPacket *pack = new ServerPacket(ServerOP_ReloadRules, 0); + auto pack = new ServerPacket(ServerOP_ReloadRules, 0); worldserver.SendPacket(pack); c->Message(13, "Successfully sent the packet to world to reload rules globally. (including world)"); safe_delete(pack); @@ -9993,7 +9997,7 @@ void command_reloadworldrules(Client *c, const Seperator *sep) { if(c) { - ServerPacket *pack = new ServerPacket(ServerOP_ReloadRulesWorld, 0); + auto pack = new ServerPacket(ServerOP_ReloadRulesWorld, 0); worldserver.SendPacket(pack); c->Message(13, "Successfully sent the packet to world to reload rules. (only world)"); safe_delete(pack); @@ -10006,7 +10010,7 @@ void command_camerashake(Client *c, const Seperator *sep) { if(sep->arg[1][0] && sep->arg[2][0]) { - ServerPacket *pack = new ServerPacket(ServerOP_CameraShake, sizeof(ServerCameraShake_Struct)); + auto pack = new ServerPacket(ServerOP_CameraShake, sizeof(ServerCameraShake_Struct)); ServerCameraShake_Struct* scss = (ServerCameraShake_Struct*) pack->pBuffer; scss->duration = atoi(sep->arg[1]); scss->intensity = atoi(sep->arg[2]); @@ -10261,10 +10265,10 @@ void command_augmentitem(Client *c, const Seperator *sep) if (!c) return; - AugmentItem_Struct* in_augment = new AugmentItem_Struct[sizeof(AugmentItem_Struct)]; - in_augment->container_slot = 1000; // - in_augment->augment_slot = -1; - if(c->GetTradeskillObject() != nullptr) + auto in_augment = new AugmentItem_Struct[sizeof(AugmentItem_Struct)]; + in_augment->container_slot = 1000; // + in_augment->augment_slot = -1; + if (c->GetTradeskillObject() != nullptr) Object::HandleAugmentation(c, in_augment, c->GetTradeskillObject()); safe_delete_array(in_augment); } @@ -10629,7 +10633,7 @@ void command_logs(Client *c, const Seperator *sep){ if (sep->argnum > 0) { /* #logs reload_all */ if (strcasecmp(sep->arg[1], "reload_all") == 0){ - ServerPacket *pack = new ServerPacket(ServerOP_ReloadLogs, 0); + auto pack = new ServerPacket(ServerOP_ReloadLogs, 0); worldserver.SendPacket(pack); c->Message(13, "Successfully sent the packet to world to reload log settings from the database for all zones"); safe_delete(pack); @@ -10827,7 +10831,7 @@ void command_reloadperlexportsettings(Client *c, const Seperator *sep) { if (c) { - ServerPacket *pack = new ServerPacket(ServerOP_ReloadPerlExportSettings, 0); + auto pack = new ServerPacket(ServerOP_ReloadPerlExportSettings, 0); worldserver.SendPacket(pack); c->Message(13, "Successfully sent the packet to world to reload Perl Export settings"); safe_delete(pack); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index ff8243003..bb88e305b 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -58,13 +58,13 @@ extern WorldServer worldserver; extern npcDecayTimes_Struct npcCorpseDecayTimes[100]; void Corpse::SendEndLootErrorPacket(Client* client) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LootComplete, 0); + auto outapp = new EQApplicationPacket(OP_LootComplete, 0); client->QueuePacket(outapp); safe_delete(outapp); } void Corpse::SendLootReqErrorPacket(Client* client, uint8 response) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct)); + auto outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct)); moneyOnCorpseStruct* d = (moneyOnCorpseStruct*) outapp->pBuffer; d->response = response; d->unknown1 = 0x5a; @@ -75,7 +75,8 @@ void Corpse::SendLootReqErrorPacket(Client* client, uint8 response) { Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const glm::vec4& position, std::string time_of_death, bool rezzed, bool was_at_graveyard) { uint32 item_count = database.GetCharacterCorpseItemCount(in_dbid); - char *buffer = new char[sizeof(PlayerCorpse_Struct) + (item_count * sizeof(player_lootitem::ServerLootItem_Struct))]; + auto buffer = + new char[sizeof(PlayerCorpse_Struct) + (item_count * sizeof(player_lootitem::ServerLootItem_Struct))]; PlayerCorpse_Struct *pcs = (PlayerCorpse_Struct*)buffer; database.LoadCharacterCorpseData(in_dbid, pcs); @@ -89,27 +90,26 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std: } /* Create Corpse Entity */ - Corpse* pc = new Corpse( - in_dbid, // uint32 in_dbid - in_charid, // uint32 in_charid - in_charname.c_str(), // char* in_charname - &itemlist, // ItemList* in_itemlist - pcs->copper, // uint32 in_copper - pcs->silver, // uint32 in_silver - pcs->gold, // uint32 in_gold - pcs->plat, // uint32 in_plat - position, - pcs->size, // float in_size - pcs->gender, // uint8 in_gender - pcs->race, // uint16 in_race - pcs->class_, // uint8 in_class - pcs->deity, // uint8 in_deity - pcs->level, // uint8 in_level - pcs->texture, // uint8 in_texture - pcs->helmtexture, // uint8 in_helmtexture - pcs->exp, // uint32 in_rezexp - was_at_graveyard // bool wasAtGraveyard - ); + auto pc = new Corpse(in_dbid, // uint32 in_dbid + in_charid, // uint32 in_charid + in_charname.c_str(), // char* in_charname + &itemlist, // ItemList* in_itemlist + pcs->copper, // uint32 in_copper + pcs->silver, // uint32 in_silver + pcs->gold, // uint32 in_gold + pcs->plat, // uint32 in_plat + position, + pcs->size, // float in_size + pcs->gender, // uint8 in_gender + pcs->race, // uint16 in_race + pcs->class_, // uint8 in_class + pcs->deity, // uint8 in_deity + pcs->level, // uint8 in_level + pcs->texture, // uint8 in_texture + pcs->helmtexture, // uint8 in_helmtexture + pcs->exp, // uint32 in_rezexp + was_at_graveyard // bool wasAtGraveyard + ); if (pcs->locked) pc->Lock(); @@ -658,7 +658,7 @@ void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, ui is_corpse_changed = true; - ServerLootItem_Struct* item = new ServerLootItem_Struct; + auto item = new ServerLootItem_Struct; memset(item, 0, sizeof(ServerLootItem_Struct)); item->item_id = itemnum; @@ -798,7 +798,7 @@ bool Corpse::Process() { database.SendCharacterCorpseToGraveyard(corpse_db_id, zone->graveyard_zoneid(), (zone->GetZoneID() == zone->graveyard_zoneid()) ? zone->GetInstanceID() : 0, zone->GetGraveyardPoint()); corpse_graveyard_timer.Disable(); - ServerPacket* pack = new ServerPacket(ServerOP_SpawnPlayerCorpse, sizeof(SpawnPlayerCorpse_Struct)); + auto pack = new ServerPacket(ServerOP_SpawnPlayerCorpse, sizeof(SpawnPlayerCorpse_Struct)); SpawnPlayerCorpse_Struct* spc = (SpawnPlayerCorpse_Struct*)pack->pBuffer; spc->player_corpse_id = corpse_db_id; spc->zone_id = zone->graveyard_zoneid(); @@ -942,7 +942,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(Loot_Request_Type >= 2 || (Loot_Request_Type == 1 && client->Admin() >= 100 && client->GetGM())) { this->being_looted_by = client->GetID(); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct)); + auto outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct)); moneyOnCorpseStruct* d = (moneyOnCorpseStruct*) outapp->pBuffer; d->response = 1; @@ -1260,7 +1260,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } void Corpse::EndLoot(Client* client, const EQApplicationPacket* app) { - EQApplicationPacket* outapp = new EQApplicationPacket; + auto outapp = new EQApplicationPacket; outapp->SetOpcode(OP_LootComplete); outapp->size = 0; client->QueuePacket(outapp); @@ -1390,7 +1390,7 @@ void Corpse::CompleteResurrection(){ } void Corpse::Spawn() { - EQApplicationPacket* app = new EQApplicationPacket; + auto app = new EQApplicationPacket; this->CreateSpawnPacket(app, this); entity_list.QueueClients(this, app); safe_delete(app); diff --git a/zone/doors.cpp b/zone/doors.cpp index b70da219e..c80b749f9 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -115,7 +115,7 @@ bool Doors::Process() { if (opentype == 40 || GetTriggerType() == 1) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer; md->doorid = door_id; md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR; @@ -137,7 +137,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) Log.Out(Logs::Detail, Logs::Doors, " incline %d, opentype %d, lockpick %d, key %d, nokeyring %d, trigger %d type %d, param %d", incline, opentype, lockpick, keyitem, nokeyring, trigger_door, trigger_type, door_param); Log.Out(Logs::Detail, Logs::Doors, " size %d, invert %d, dest: %s %s", size, invert_state, dest_zone, to_string(m_Destination).c_str()); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); MoveDoor_Struct* md = (MoveDoor_Struct*)outapp->pBuffer; md->doorid = door_id; ///////////////////////////////////////////////////////////////// @@ -170,7 +170,8 @@ void Doors::HandleClick(Client* sender, uint8 trigger) if(!sender->GetPendingAdventureDoorClick()) { sender->PendingAdventureDoorClick(); - ServerPacket *pack = new ServerPacket(ServerOP_AdventureClickDoor, sizeof(ServerPlayerClickedAdventureDoor_Struct)); + auto pack = new ServerPacket(ServerOP_AdventureClickDoor, + sizeof(ServerPlayerClickedAdventureDoor_Struct)); ServerPlayerClickedAdventureDoor_Struct *ads = (ServerPlayerClickedAdventureDoor_Struct*)pack->pBuffer; strcpy(ads->player, sender->GetName()); ads->zone_id = zone->GetZoneID(); @@ -447,7 +448,7 @@ void Doors::NPCOpen(NPC* sender, bool alt_mode) return; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer; md->doorid = door_id; md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR; @@ -473,7 +474,7 @@ void Doors::NPCOpen(NPC* sender, bool alt_mode) void Doors::ForceOpen(Mob *sender, bool alt_mode) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer; md->doorid = door_id; md->action = invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR; @@ -498,7 +499,7 @@ void Doors::ForceOpen(Mob *sender, bool alt_mode) void Doors::ForceClose(Mob *sender, bool alt_mode) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer; md->doorid = door_id; md->action = invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR; // change from original (open to close) @@ -527,7 +528,7 @@ void Doors::ToggleState(Mob *sender) return; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); + auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct)); MoveDoor_Struct* md=(MoveDoor_Struct*)outapp->pBuffer; md->doorid = door_id; diff --git a/zone/effects.cpp b/zone/effects.cpp index 69b5c0819..ad9de822c 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -703,7 +703,7 @@ void Client::SendDisciplineTimer(uint32 timer_id, uint32 duration) { if (timer_id < MAX_DISCIPLINE_TIMERS) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DisciplineTimer, sizeof(DisciplineTimer_Struct)); + auto outapp = new EQApplicationPacket(OP_DisciplineTimer, sizeof(DisciplineTimer_Struct)); DisciplineTimer_Struct *dts = (DisciplineTimer_Struct *)outapp->pBuffer; dts->TimerID = timer_id; dts->Duration = duration; diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 3607bbe05..37be828ae 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -972,7 +972,7 @@ void PerlembParser::ExportQGlobals(bool isPlayerQuest, bool isGlobalPlayerQuest, QGlobalCache::Combine(globalMap, zone_c->GetBucket(), npcmob->GetNPCTypeID(), char_id, zone->GetZoneID()); } - std::list::iterator iter = globalMap.begin(); + auto iter = globalMap.begin(); while(iter != globalMap.end()) { globhash[(*iter).name] = (*iter).value; @@ -1020,7 +1020,7 @@ void PerlembParser::ExportQGlobals(bool isPlayerQuest, bool isGlobalPlayerQuest, QGlobalCache::Combine(globalMap, zone_c->GetBucket(), 0, char_id, zone->GetZoneID()); } - std::list::iterator iter = globalMap.begin(); + auto iter = globalMap.begin(); while(iter != globalMap.end()) { globhash[(*iter).name] = (*iter).value; diff --git a/zone/embperl.cpp b/zone/embperl.cpp index e86a3e187..d881cad5e 100644 --- a/zone/embperl.cpp +++ b/zone/embperl.cpp @@ -280,8 +280,7 @@ int Embperl::dosub(const char * subname, const std::vector * args, PUSHMARK(SP); if(args && !args->empty()) { - for(std::vector::const_iterator i = args->begin(); i != args->end(); ++i) - { + for (auto i = args->begin(); i != args->end(); ++i) { XPUSHs(sv_2mortal(newSVpv(i->c_str(), i->length()))); } } diff --git a/zone/entity.cpp b/zone/entity.cpp index bdf59d8b0..f788b06c2 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -650,14 +650,14 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) npc->SetSpawned(); if (SendSpawnPacket) { if (dontqueue) { // aka, SEND IT NOW BITCH! - EQApplicationPacket *app = new EQApplicationPacket; + auto app = new EQApplicationPacket; npc->CreateSpawnPacket(app, npc); QueueClients(npc, app); npc->SendArmorAppearance(); npc->SetAppearance(npc->GetGuardPointAnim(),false); safe_delete(app); } else { - NewSpawn_Struct *ns = new NewSpawn_Struct; + auto ns = new NewSpawn_Struct; memset(ns, 0, sizeof(NewSpawn_Struct)); npc->FillSpawnStruct(ns, nullptr); // Not working on player newspawns, so it's safe to use a ForWho of 0 AddToSpawnQueue(npc->GetID(), &ns); @@ -691,14 +691,14 @@ void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue) { if (dontqueue) { // Send immediately - EQApplicationPacket *outapp = new EQApplicationPacket(); + auto outapp = new EQApplicationPacket(); merc->CreateSpawnPacket(outapp); outapp->priority = 6; QueueClients(merc, outapp, true); safe_delete(outapp); } else { // Queue the packet - NewSpawn_Struct *ns = new NewSpawn_Struct; + auto ns = new NewSpawn_Struct; memset(ns, 0, sizeof(NewSpawn_Struct)); merc->FillSpawnStruct(ns, 0); AddToSpawnQueue(merc->GetID(), &ns); @@ -882,7 +882,7 @@ bool EntityList::MakeDoorSpawnPacket(EQApplicationPacket *app, Client *client) return false; uint32 length = count * sizeof(Door_Struct); - uchar *packet_buffer = new uchar[length]; + auto packet_buffer = new uchar[length]; memset(packet_buffer, 0, length); uchar *ptr = packet_buffer; Doors *door; @@ -1226,7 +1226,7 @@ void EntityList::SendZoneSpawnsBulk(Client *client) if (maxspawns > mob_list.size()) maxspawns = mob_list.size(); - BulkZoneSpawnPacket *bzsp = new BulkZoneSpawnPacket(client, maxspawns); + auto bzsp = new BulkZoneSpawnPacket(client, maxspawns); int32 race=-1; for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { @@ -1291,7 +1291,7 @@ void EntityList::SendZoneCorpsesBulk(Client *client) Corpse *spawn; uint32 maxspawns = 100; - BulkZoneSpawnPacket *bzsp = new BulkZoneSpawnPacket(client, maxspawns); + auto bzsp = new BulkZoneSpawnPacket(client, maxspawns); for (auto it = corpse_list.begin(); it != corpse_list.end(); ++it) { spawn = it->second; @@ -1308,7 +1308,7 @@ void EntityList::SendZoneObjects(Client *client) { auto it = object_list.begin(); while (it != object_list.end()) { - EQApplicationPacket *app = new EQApplicationPacket; + auto app = new EQApplicationPacket; it->second->CreateSpawnPacket(app); client->FastQueuePacket(&app); ++it; @@ -1949,7 +1949,7 @@ void EntityList::QueueClientsGuild(Mob *sender, const EQApplicationPacket *app, void EntityList::QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struct *gbius, uint32 GuildID) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankItemUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankItemUpdate_Struct)); GuildBankItemUpdate_Struct *outgbius = (GuildBankItemUpdate_Struct*)outapp->pBuffer; @@ -2132,7 +2132,7 @@ void EntityList::RemoveAllDoors() void EntityList::DespawnAllDoors() { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RemoveAllDoors, 0); + auto outapp = new EQApplicationPacket(OP_RemoveAllDoors, 0); this->QueueClients(0,outapp); safe_delete(outapp); } @@ -2142,7 +2142,7 @@ void EntityList::RespawnAllDoors() auto it = client_list.begin(); while (it != client_list.end()) { if (it->second) { - EQApplicationPacket *outapp = new EQApplicationPacket(); + auto outapp = new EQApplicationPacket(); MakeDoorSpawnPacket(outapp, it->second); it->second->FastQueuePacket(&outapp); } @@ -2631,7 +2631,7 @@ void EntityList::ListNPCs(Client* client, const char *arg1, const char *arg2, ui } } else if (searchtype == 1) { client->Message(0, "Searching by name method. (%s)",arg1); - char* tmp = new char[strlen(arg1) + 1]; + auto tmp = new char[strlen(arg1) + 1]; strcpy(tmp, arg1); strupr(tmp); while (it != npc_list.end()) { @@ -2746,7 +2746,7 @@ int32 EntityList::DeletePlayerCorpses() void EntityList::SendPetitionToAdmins() { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_PetitionUpdate,sizeof(PetitionUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_PetitionUpdate, sizeof(PetitionUpdate_Struct)); PetitionUpdate_Struct *pcus = (PetitionUpdate_Struct*) outapp->pBuffer; pcus->petnumber = 0; // Petition Number pcus->color = 0; @@ -2766,7 +2766,7 @@ void EntityList::SendPetitionToAdmins() void EntityList::SendPetitionToAdmins(Petition *pet) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_PetitionUpdate,sizeof(PetitionUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_PetitionUpdate, sizeof(PetitionUpdate_Struct)); PetitionUpdate_Struct *pcus = (PetitionUpdate_Struct*) outapp->pBuffer; pcus->petnumber = pet->GetID(); // Petition Number if (pet->CheckedOut()) { @@ -2799,7 +2799,7 @@ void EntityList::SendPetitionToAdmins(Petition *pet) void EntityList::ClearClientPetitionQueue() { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_PetitionUpdate,sizeof(PetitionUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_PetitionUpdate, sizeof(PetitionUpdate_Struct)); PetitionUpdate_Struct *pet = (PetitionUpdate_Struct*) outapp->pBuffer; pet->color = 0x00; pet->status = 0xFFFFFFFF; @@ -2867,7 +2867,7 @@ void BulkZoneSpawnPacket::SendBuffer() return; uint32 tmpBufSize = (index * sizeof(NewSpawn_Struct)); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZoneSpawns, (unsigned char *)data, tmpBufSize); + auto outapp = new EQApplicationPacket(OP_ZoneSpawns, (unsigned char *)data, tmpBufSize); if (pSendTo) { pSendTo->FastQueuePacket(&outapp); @@ -3034,7 +3034,7 @@ bool EntityList::MakeTrackPacket(Client *client) [](const std::pair &a, const std::pair &b) { return a.first->GetSpawnTimeStamp() > b.first->GetSpawnTimeStamp(); }); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_Track, sizeof(Track_Struct) * tracking_list.size()); + auto outapp = new EQApplicationPacket(OP_Track, sizeof(Track_Struct) * tracking_list.size()); Tracking_Struct *outtrack = (Tracking_Struct *)outapp->pBuffer; outapp->priority = 6; @@ -3686,7 +3686,7 @@ void EntityList::QuestJournalledSayClose(Mob *sender, Client *QuestInitiator, // Send the message to the quest initiator such that the client will enter it into the NPC Quest Journal if (QuestInitiator) { - char *buf = new char[strlen(mobname) + strlen(message) + 10]; + auto buf = new char[strlen(mobname) + strlen(message) + 10]; sprintf(buf, "%s says, '%s'", mobname, message); QuestInitiator->QuestJournalledMessage(mobname, buf); safe_delete_array(buf); @@ -3756,7 +3756,7 @@ void EntityList::SendGroupLeave(uint32 gid, const char *name) g = c->GetGroup(); if (g) { if (g->GetID() == gid) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer; strcpy(gj->membername, name); gj->action = groupActLeave; @@ -3785,7 +3785,7 @@ void EntityList::SendGroupJoin(uint32 gid, const char *name) g = it->second->GetGroup(); if (g) { if (g->GetID() == gid) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer; strcpy(gj->membername, name); gj->action = groupActJoin; @@ -3825,11 +3825,11 @@ uint16 EntityList::CreateGroundObject(uint32 itemid, const glm::vec4& position, if (!is) return 0; - ItemInst *i = new ItemInst(is, is->MaxCharges); + auto i = new ItemInst(is, is->MaxCharges); if (!i) return 0; - Object *object = new Object(i, position.x, position.y, position.z, position.w,decay_time); + auto object = new Object(i, position.x, position.y, position.z, position.w, decay_time); entity_list.AddObject(object, true); safe_delete(i); @@ -3844,7 +3844,7 @@ uint16 EntityList::CreateGroundObjectFromModel(const char *model, const glm::vec if (!model) return 0; - Object *object = new Object(model, position.x, position.y, position.z, position.w, type); + auto object = new Object(model, position.x, position.y, position.z, position.w, type); entity_list.AddObject(object, true); if (!object) @@ -3858,7 +3858,7 @@ uint16 EntityList::CreateDoor(const char *model, const glm::vec4& position, uint if (!model) return 0; // fell through everything, this is bad/incomplete from perl - Doors *door = new Doors(model, position, opentype, size); + auto door = new Doors(model, position, opentype, size); RemoveAllDoors(); zone->LoadZoneDoors(zone->GetShortName(), zone->GetInstanceVersion()); entity_list.AddDoor(door); @@ -4033,7 +4033,7 @@ void EntityList::ZoneWho(Client *c, Who_All_Struct *Who) } PacketLength = PacketLength + sizeof(WhoAllReturnStruct) + (47 * Entries); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_WhoAllResponse, PacketLength); + auto outapp = new EQApplicationPacket(OP_WhoAllResponse, PacketLength); char *Buffer = (char *)outapp->pBuffer; WhoAllReturnStruct *WARS = (WhoAllReturnStruct *)Buffer; WARS->id = 0; @@ -4219,7 +4219,7 @@ uint16 EntityList::GetClientCount(){ uint16 ClientCount = 0; std::list client_list; entity_list.GetClientList(client_list); - std::list::iterator iter = client_list.begin(); + auto iter = client_list.begin(); while (iter != client_list.end()) { Client *entry = (*iter); entry->GetCleanName(); @@ -4353,7 +4353,7 @@ void EntityList::SendFindableNPCList(Client *c) if (!c) return; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendFindableNPCs, sizeof(FindableNPC_Struct)); + auto outapp = new EQApplicationPacket(OP_SendFindableNPCs, sizeof(FindableNPC_Struct)); FindableNPC_Struct *fnpcs = (FindableNPC_Struct *)outapp->pBuffer; @@ -4388,7 +4388,7 @@ void EntityList::UpdateFindableNPCState(NPC *n, bool Remove) if (!n || !n->IsFindable()) return; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendFindableNPCs, sizeof(FindableNPC_Struct)); + auto outapp = new EQApplicationPacket(OP_SendFindableNPCs, sizeof(FindableNPC_Struct)); FindableNPC_Struct *fnpcs = (FindableNPC_Struct *)outapp->pBuffer; @@ -4479,9 +4479,9 @@ void EntityList::AddLootToNPCS(uint32 item_id, uint32 count) if (npc_count == 0) return; - NPC **npcs = new NPC*[npc_count]; - int *counts = new int[npc_count]; - bool *marked = new bool[npc_count]; + auto npcs = new NPC *[npc_count]; + auto counts = new int[npc_count]; + auto marked = new bool[npc_count]; memset(counts, 0, sizeof(int) * npc_count); memset(marked, 0, sizeof(bool) * npc_count); @@ -4523,7 +4523,7 @@ void EntityList::AddLootToNPCS(uint32 item_id, uint32 count) void EntityList::CameraEffect(uint32 duration, uint32 intensity) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CameraEffect, sizeof(Camera_Struct)); + auto outapp = new EQApplicationPacket(OP_CameraEffect, sizeof(Camera_Struct)); Camera_Struct* cs = (Camera_Struct*) outapp->pBuffer; cs->duration = duration; // Duration in milliseconds cs->intensity = ((intensity * 6710886) + 1023410176); // Intensity ranges from 1023410176 to 1090519040, so simplify it from 0 to 10. @@ -4557,7 +4557,7 @@ NPC *EntityList::GetClosestBanker(Mob *sender, uint32 &distance) void EntityList::ExpeditionWarning(uint32 minutes_left) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_DzExpeditionEndsWarning, sizeof(ExpeditionExpireWarning)); + auto outapp = new EQApplicationPacket(OP_DzExpeditionEndsWarning, sizeof(ExpeditionExpireWarning)); ExpeditionExpireWarning *ew = (ExpeditionExpireWarning*)outapp->pBuffer; ew->minutes_remaining = minutes_left; diff --git a/zone/exp.cpp b/zone/exp.cpp index 2e231cc36..93c689b7c 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -522,7 +522,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { uint32 tmpxp2 = GetEXPForLevel(GetLevel()); // Quag: crash bug fix... Divide by zero when tmpxp1 and 2 equalled each other, most likely the error case from GetEXPForLevel() (invalid class, etc) if (tmpxp1 != tmpxp2 && tmpxp1 != 0xFFFFFFFF && tmpxp2 != 0xFFFFFFFF) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ExpUpdate, sizeof(ExpUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_ExpUpdate, sizeof(ExpUpdate_Struct)); ExpUpdate_Struct* eu = (ExpUpdate_Struct*)outapp->pBuffer; float tmpxp = (float) ( (float) set_exp-tmpxp2 ) / ( (float) tmpxp1-tmpxp2 ); eu->exp = (uint32)(330.0f * tmpxp); @@ -545,7 +545,7 @@ void Client::SetLevel(uint8 set_level, bool command) return; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelUpdate, sizeof(LevelUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_LevelUpdate, sizeof(LevelUpdate_Struct)); LevelUpdate_Struct* lu = (LevelUpdate_Struct*)outapp->pBuffer; lu->level = set_level; if(m_pp.level2 != 0) @@ -838,7 +838,7 @@ void Client::AddLeadershipEXP(uint32 group_exp, uint32 raid_exp) { } void Client::SendLeadershipEXPUpdate() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LeadershipExpUpdate, sizeof(LeadershipExpUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_LeadershipExpUpdate, sizeof(LeadershipExpUpdate_Struct)); LeadershipExpUpdate_Struct* eu = (LeadershipExpUpdate_Struct *) outapp->pBuffer; eu->group_leadership_exp = m_pp.group_leadership_exp; @@ -860,7 +860,7 @@ uint32 Client::GetCharMaxLevelFromQGlobal() { QGlobalCache::Combine(globalMap, char_c->GetBucket(), ntype, this->CharacterID(), zone->GetZoneID()); } - std::list::iterator iter = globalMap.begin(); + auto iter = globalMap.begin(); uint32 gcount = 0; while(iter != globalMap.end()) { if((*iter).name.compare("CharMaxLevel") == 0){ diff --git a/zone/forage.cpp b/zone/forage.cpp index 991947f8d..be3e0a3b3 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -283,14 +283,14 @@ void Client::GoFish() if(tmp != nullptr) { auto positionNPC = GetPosition(); positionNPC.x = positionNPC.x + 3; - NPC* npc = new NPC(tmp, nullptr, positionNPC, FlyMode3); - npc->AddLootTable(); + auto npc = new NPC(tmp, nullptr, positionNPC, FlyMode3); + npc->AddLootTable(); - npc->AddToHateList(this, 1, 0, false); //no help yelling + npc->AddToHateList(this, 1, 0, false); // no help yelling - entity_list.AddNPC(npc); + entity_list.AddNPC(npc); - Message(MT_Emote, "You fish up a little more than you bargained for..."); + Message(MT_Emote, "You fish up a little more than you bargained for..."); } } } diff --git a/zone/groups.cpp b/zone/groups.cpp index 6ce658922..2162e735e 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -272,7 +272,7 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte int x=1; //build the template join packet - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer; strcpy(gj->membername, NewMemberName); gj->action = groupActJoin; @@ -534,7 +534,7 @@ void Group::SendGroupJoinOOZ(Mob* NewMember) { } //send updates to clients out of zone... - ServerPacket* pack = new ServerPacket(ServerOP_GroupJoin, sizeof(ServerGroupJoin_Struct)); + auto pack = new ServerPacket(ServerOP_GroupJoin, sizeof(ServerGroupJoin_Struct)); ServerGroupJoin_Struct* gj = (ServerGroupJoin_Struct*)pack->pBuffer; gj->gid = GetID(); gj->zoneid = zone->GetZoneID(); @@ -634,7 +634,7 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) return true; } - ServerPacket* pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct)); + auto pack = new ServerPacket(ServerOP_GroupLeave, sizeof(ServerGroupLeave_Struct)); ServerGroupLeave_Struct* gl = (ServerGroupLeave_Struct*)pack->pBuffer; gl->gid = GetID(); gl->zoneid = zone->GetZoneID(); @@ -643,7 +643,7 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) worldserver.SendPacket(pack); safe_delete(pack); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer; gu->action = groupActLeave; strcpy(gu->membername, oldmember->GetCleanName()); @@ -847,7 +847,8 @@ void Group::GroupMessage(Mob* sender, uint8 language, uint8 lang_skill, const ch members[i]->CastToClient()->ChannelMessageSend(sender->GetName(),members[i]->GetName(),2,language,lang_skill,message); } - ServerPacket* pack = new ServerPacket(ServerOP_OOZGroupMessage, sizeof(ServerGroupChannelMessage_Struct) + strlen(message) + 1); + auto pack = + new ServerPacket(ServerOP_OOZGroupMessage, sizeof(ServerGroupChannelMessage_Struct) + strlen(message) + 1); ServerGroupChannelMessage_Struct* gcm = (ServerGroupChannelMessage_Struct*)pack->pBuffer; gcm->zoneid = zone->GetZoneID(); gcm->groupid = GetID(); @@ -872,7 +873,7 @@ uint32 Group::GetTotalGroupDamage(Mob* other) { } void Group::DisbandGroup() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate_Struct)); GroupUpdate_Struct* gu = (GroupUpdate_Struct*) outapp->pBuffer; gu->action = groupActDisband; @@ -916,7 +917,7 @@ void Group::DisbandGroup() { ClearAllNPCMarks(); - ServerPacket* pack = new ServerPacket(ServerOP_DisbandGroup, sizeof(ServerDisbandGroup_Struct)); + auto pack = new ServerPacket(ServerOP_DisbandGroup, sizeof(ServerDisbandGroup_Struct)); ServerDisbandGroup_Struct* dg = (ServerDisbandGroup_Struct*)pack->pBuffer; dg->zoneid = zone->GetZoneID(); dg->groupid = GetID(); @@ -987,7 +988,7 @@ void Group::SendUpdate(uint32 type, Mob* member) if(!member->IsClient()) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate2_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate2_Struct)); GroupUpdate2_Struct* gu = (GroupUpdate2_Struct*)outapp->pBuffer; gu->action = type; strcpy(gu->yourname,member->GetName()); @@ -1021,7 +1022,7 @@ void Group::SendLeadershipAAUpdate() // If a group member is not in the same zone as the leader when the leader purchases a new AA, they will not become // aware of it until they are next in the same zone as the leader. - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gu = (GroupJoin_Struct*)outapp->pBuffer; gu->action = groupActAAUpdate; gu->leader_aas = LeaderAbilities; @@ -1428,7 +1429,7 @@ void Group::MarkNPC(Mob* Target, int Number) MarkedNPCs[Number - 1] = EntityID; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct)); + auto outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct)); MarkNPC_Struct* mnpcs = (MarkNPC_Struct *)outapp->pBuffer; @@ -1613,7 +1614,7 @@ void Group::NotifyMainTank(Client *c, uint8 toggle) } else { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; @@ -1646,7 +1647,7 @@ void Group::NotifyMainAssist(Client *c, uint8 toggle) if (c->ClientVersion() < EQEmu::versions::ClientVersion::SoD) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); + auto outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; @@ -1666,7 +1667,7 @@ void Group::NotifyMainAssist(Client *c, uint8 toggle) } else { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; @@ -1708,7 +1709,7 @@ void Group::NotifyPuller(Client *c, uint8 toggle) } else { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupRoles, sizeof(GroupRole_Struct)); GroupRole_Struct *grs = (GroupRole_Struct*)outapp->pBuffer; @@ -1760,7 +1761,7 @@ void Group::UnDelegateMainAssist(const char *OldMainAssistName, uint8 toggle) // informing them of the change and update the group_leaders table. // if(OldMainAssistName == MainAssistName) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); + auto outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; @@ -1918,7 +1919,7 @@ void Group::NotifyAssistTarget(Client *c) if(!c) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SetGroupTarget, sizeof(MarkNPC_Struct)); + auto outapp = new EQApplicationPacket(OP_SetGroupTarget, sizeof(MarkNPC_Struct)); MarkNPC_Struct* mnpcs = (MarkNPC_Struct *)outapp->pBuffer; @@ -1991,7 +1992,7 @@ void Group::NotifyMarkNPC(Client *c) if(!NPCMarkerName.size()) return; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); + auto outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; @@ -2033,7 +2034,7 @@ void Group::UnDelegateMarkNPC(const char *OldNPCMarkerName) if(!NPCMarkerName.size()) return; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); + auto outapp = new EQApplicationPacket(OP_DelegateAbility, sizeof(DelegateAbility_Struct)); DelegateAbility_Struct* das = (DelegateAbility_Struct*)outapp->pBuffer; @@ -2067,8 +2068,8 @@ void Group::SaveGroupLeaderAA() { // Stores the Group Leaders Leadership AA data from the Player Profile as a blob in the group_leaders table. // This is done so that group members not in the same zone as the Leader still have access to this information. - char *queryBuffer = new char[sizeof(GroupLeadershipAA_Struct) * 2 + 1]; - database.DoEscapeString(queryBuffer, (char*)&LeaderAbilities, sizeof(GroupLeadershipAA_Struct)); + auto queryBuffer = new char[sizeof(GroupLeadershipAA_Struct) * 2 + 1]; + database.DoEscapeString(queryBuffer, (char *)&LeaderAbilities, sizeof(GroupLeadershipAA_Struct)); std::string query = "UPDATE group_leaders SET leadershipaa = '"; query += queryBuffer; @@ -2117,7 +2118,7 @@ void Group::SendMarkedNPCsToMember(Client *c, bool Clear) if(!c) return; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct)); + auto outapp = new EQApplicationPacket(OP_MarkNPC, sizeof(MarkNPC_Struct)); MarkNPC_Struct *mnpcs = (MarkNPC_Struct *)outapp->pBuffer; @@ -2252,7 +2253,7 @@ void Group::ChangeLeader(Mob* newleader) Mob* oldleader = GetLeader(); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gu = (GroupJoin_Struct*) outapp->pBuffer; gu->action = groupActMakeLeader; diff --git a/zone/guild.cpp b/zone/guild.cpp index ceaa40fd4..6cba3677a 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -26,7 +26,7 @@ extern WorldServer worldserver; void Client::SendGuildMOTD(bool GetGuildMOTDReply) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildMOTD, sizeof(GuildMOTD_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildMOTD, sizeof(GuildMOTD_Struct)); // When the Client gets an OP_GuildMOTD, it compares the text to the version it has previously stored. // If the text in the OP_GuildMOTD packet is the same, it does nothing. If not the same, it displays @@ -68,7 +68,8 @@ void Client::SendGuildURL() if(IsInAGuild()) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildUpdateURLAndChannel, sizeof(GuildUpdateURLAndChannel_Struct)); + auto outapp = + new EQApplicationPacket(OP_GuildUpdateURLAndChannel, sizeof(GuildUpdateURLAndChannel_Struct)); GuildUpdateURLAndChannel_Struct *guuacs = (GuildUpdateURLAndChannel_Struct*) outapp->pBuffer; @@ -89,7 +90,8 @@ void Client::SendGuildChannel() if(IsInAGuild()) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildUpdateURLAndChannel, sizeof(GuildUpdateURLAndChannel_Struct)); + auto outapp = + new EQApplicationPacket(OP_GuildUpdateURLAndChannel, sizeof(GuildUpdateURLAndChannel_Struct)); GuildUpdateURLAndChannel_Struct *guuacs = (GuildUpdateURLAndChannel_Struct*) outapp->pBuffer; @@ -119,7 +121,8 @@ void Client::SendGuildRanks() { while(i < permissions) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildUpdateURLAndChannel, sizeof(GuildUpdateRanks_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildUpdateURLAndChannel, + sizeof(GuildUpdateRanks_Struct)); GuildUpdateRanks_Struct *guuacs = (GuildUpdateRanks_Struct*) outapp->pBuffer; //guuacs->Unknown0008 = this->GuildID(); strncpy(guuacs->Unknown0012, this->GetCleanName(), 64); @@ -187,7 +190,7 @@ void Client::SendGuildMembers() { if(data == nullptr) return; //invalid guild, shouldent happen. - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildMemberList); + auto outapp = new EQApplicationPacket(OP_GuildMemberList); outapp->size = len; outapp->pBuffer = data; data = nullptr; @@ -196,7 +199,8 @@ void Client::SendGuildMembers() { FastQueuePacket(&outapp); - ServerPacket* pack = new ServerPacket(ServerOP_RequestOnlineGuildMembers, sizeof(ServerRequestOnlineGuildMembers_Struct)); + auto pack = + new ServerPacket(ServerOP_RequestOnlineGuildMembers, sizeof(ServerRequestOnlineGuildMembers_Struct)); ServerRequestOnlineGuildMembers_Struct *srogms = (ServerRequestOnlineGuildMembers_Struct*)pack->pBuffer; @@ -235,7 +239,7 @@ void Client::RefreshGuildInfo() { if(WasBanker != GuildBanker) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SetGuildRank, sizeof(GuildSetRank_Struct)); + auto outapp = new EQApplicationPacket(OP_SetGuildRank, sizeof(GuildSetRank_Struct)); GuildSetRank_Struct *gsrs = (GuildSetRank_Struct*)outapp->pBuffer; @@ -328,7 +332,7 @@ void EntityList::SendGuildList() { } void Client::SendGuildJoin(GuildJoin_Struct* gj){ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildManageAdd, sizeof(GuildJoin_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildManageAdd, sizeof(GuildJoin_Struct)); GuildJoin_Struct* outgj=(GuildJoin_Struct*)outapp->pBuffer; outgj->class_ = gj->class_; outgj->guild_id = gj->guild_id; diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index a801dc895..dfd022541 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -33,7 +33,7 @@ extern volatile bool is_zone_loaded; void ZoneGuildManager::SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation) { Log.Out(Logs::Detail, Logs::Guilds, "Sending guild refresh for %d to world, changes: name=%d, motd=%d, rank=d, relation=%d", guild_id, name, motd, rank, relation); - ServerPacket* pack = new ServerPacket(ServerOP_RefreshGuild, sizeof(ServerGuildRefresh_Struct)); + auto pack = new ServerPacket(ServerOP_RefreshGuild, sizeof(ServerGuildRefresh_Struct)); ServerGuildRefresh_Struct *s = (ServerGuildRefresh_Struct *) pack->pBuffer; s->guild_id = guild_id; s->name_change = name; @@ -58,7 +58,7 @@ void ZoneGuildManager::SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uin Log.Out(Logs::Detail, Logs::Guilds, "Sending char refresh for %d from guild %d to world", charid, guild_id); - ServerPacket* pack = new ServerPacket(ServerOP_GuildCharRefresh, sizeof(ServerGuildCharRefresh_Struct)); + auto pack = new ServerPacket(ServerOP_GuildCharRefresh, sizeof(ServerGuildCharRefresh_Struct)); ServerGuildCharRefresh_Struct *s = (ServerGuildCharRefresh_Struct *) pack->pBuffer; s->guild_id = guild_id; s->old_guild_id = old_guild_id; @@ -74,7 +74,7 @@ void ZoneGuildManager::SendRankUpdate(uint32 CharID) if(!GetCharInfo(CharID, gci)) return; - ServerPacket* pack = new ServerPacket(ServerOP_GuildRankUpdate, sizeof(ServerGuildRankUpdate_Struct)); + auto pack = new ServerPacket(ServerOP_GuildRankUpdate, sizeof(ServerGuildRankUpdate_Struct)); ServerGuildRankUpdate_Struct *sgrus = (ServerGuildRankUpdate_Struct*)pack->pBuffer; @@ -90,7 +90,7 @@ void ZoneGuildManager::SendRankUpdate(uint32 CharID) void ZoneGuildManager::SendGuildDelete(uint32 guild_id) { Log.Out(Logs::Detail, Logs::Guilds, "Sending guild delete for guild %d to world", guild_id); - ServerPacket* pack = new ServerPacket(ServerOP_DeleteGuild, sizeof(ServerGuildID_Struct)); + auto pack = new ServerPacket(ServerOP_DeleteGuild, sizeof(ServerGuildID_Struct)); ServerGuildID_Struct *s = (ServerGuildID_Struct *) pack->pBuffer; s->guild_id = guild_id; worldserver.SendPacket(pack); @@ -346,7 +346,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) { ServerGuildRankUpdate_Struct *sgrus = (ServerGuildRankUpdate_Struct*)pack->pBuffer; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SetGuildRank, sizeof(GuildSetRank_Struct)); + auto outapp = new EQApplicationPacket(OP_SetGuildRank, sizeof(GuildSetRank_Struct)); GuildSetRank_Struct *gsrs = (GuildSetRank_Struct*)outapp->pBuffer; @@ -390,7 +390,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) { if(is_zone_loaded) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildMemberUpdate, sizeof(GuildMemberUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildMemberUpdate, sizeof(GuildMemberUpdate_Struct)); GuildMemberUpdate_Struct *gmus = (GuildMemberUpdate_Struct*)outapp->pBuffer; @@ -421,7 +421,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) { break; } Log.Out(Logs::Detail, Logs::Guilds,"Processing ServerOP_OnlineGuildMembersResponse"); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildMemberUpdate, sizeof(GuildMemberUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildMemberUpdate, sizeof(GuildMemberUpdate_Struct)); GuildMemberUpdate_Struct *gmus = (GuildMemberUpdate_Struct*)outapp->pBuffer; char Name[64]; gmus->LastSeen = time(nullptr); @@ -464,7 +464,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) { if(GuildID == GUILD_NONE) break; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LFGuild, sizeof(LFGuild_GuildToggle_Struct)); + auto outapp = new EQApplicationPacket(OP_LFGuild, sizeof(LFGuild_GuildToggle_Struct)); LFGuild_GuildToggle_Struct *gts = (LFGuild_GuildToggle_Struct *)outapp->pBuffer; gts->Command = 1; @@ -487,7 +487,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) { void ZoneGuildManager::SendGuildMemberUpdateToWorld(const char *MemberName, uint32 GuildID, uint16 ZoneID, uint32 LastSeen) { - ServerPacket* pack = new ServerPacket(ServerOP_GuildMemberUpdate, sizeof(ServerGuildMemberUpdate_Struct)); + auto pack = new ServerPacket(ServerOP_GuildMemberUpdate, sizeof(ServerGuildMemberUpdate_Struct)); ServerGuildMemberUpdate_Struct *sgmus = (ServerGuildMemberUpdate_Struct*)pack->pBuffer; sgmus->GuildID = GuildID; @@ -501,7 +501,8 @@ void ZoneGuildManager::SendGuildMemberUpdateToWorld(const char *MemberName, uint void ZoneGuildManager::RequestOnlineGuildMembers(uint32 FromID, uint32 GuildID) { - ServerPacket* pack = new ServerPacket(ServerOP_RequestOnlineGuildMembers, sizeof(ServerRequestOnlineGuildMembers_Struct)); + auto pack = + new ServerPacket(ServerOP_RequestOnlineGuildMembers, sizeof(ServerRequestOnlineGuildMembers_Struct)); ServerRequestOnlineGuildMembers_Struct *srogm = (ServerRequestOnlineGuildMembers_Struct*)pack->pBuffer; srogm->FromID = FromID; @@ -526,7 +527,7 @@ void ZoneGuildManager::ProcessApproval() void ZoneGuildManager::AddGuildApproval(const char* guildname,Client* owner) { - GuildApproval* tmp = new GuildApproval(guildname,owner,GetFreeID()); + auto tmp = new GuildApproval(guildname, owner, GetFreeID()); list.Insert(tmp); } @@ -586,7 +587,7 @@ GuildApproval* ZoneGuildManager::FindGuildByOwnerApproval(Client* owner) GuildBankManager::~GuildBankManager() { - std::list::iterator Iterator = Banks.begin(); + auto Iterator = Banks.begin(); while(Iterator != Banks.end()) { @@ -606,57 +607,56 @@ bool GuildBankManager::Load(uint32 guildID) return false; } - GuildBank *bank = new GuildBank; + auto bank = new GuildBank; - bank->GuildID = guildID; + bank->GuildID = guildID; - for(int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i) - bank->Items.MainArea[i].ItemID = 0; + for (int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i) + bank->Items.MainArea[i].ItemID = 0; - for(int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i) - bank->Items.DepositArea[i].ItemID = 0; + for (int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i) + bank->Items.DepositArea[i].ItemID = 0; - char donator[64], whoFor[64]; + char donator[64], whoFor[64]; - for (auto row = results.begin(); row != results.end(); ++row) - { - int area = atoi(row[0]); - int slot = atoi(row[1]); - int itemID = atoi(row[2]); - int qty = atoi(row[3]); + for (auto row = results.begin(); row != results.end(); ++row) { + int area = atoi(row[0]); + int slot = atoi(row[1]); + int itemID = atoi(row[2]); + int qty = atoi(row[3]); - if(row[4]) - strn0cpy(donator, row[4], sizeof(donator)); - else - donator[0] = '\0'; + if (row[4]) + strn0cpy(donator, row[4], sizeof(donator)); + else + donator[0] = '\0'; - int permissions = atoi(row[5]); + int permissions = atoi(row[5]); - if(row[6]) - strn0cpy(whoFor, row[6], sizeof(whoFor)); - else - whoFor[0] = '\0'; + if (row[6]) + strn0cpy(whoFor, row[6], sizeof(whoFor)); + else + whoFor[0] = '\0'; - if(slot < 0) - continue; + if (slot < 0) + continue; - GuildBankItem *itemSection = nullptr; + GuildBankItem *itemSection = nullptr; - if (area == GuildBankMainArea && slot < GUILD_BANK_MAIN_AREA_SIZE) - itemSection = bank->Items.MainArea; - else if (area != GuildBankMainArea && slot < GUILD_BANK_DEPOSIT_AREA_SIZE) - itemSection = bank->Items.DepositArea; - else - continue; + if (area == GuildBankMainArea && slot < GUILD_BANK_MAIN_AREA_SIZE) + itemSection = bank->Items.MainArea; + else if (area != GuildBankMainArea && slot < GUILD_BANK_DEPOSIT_AREA_SIZE) + itemSection = bank->Items.DepositArea; + else + continue; - itemSection[slot].ItemID = itemID; - itemSection[slot].Quantity = qty; + itemSection[slot].ItemID = itemID; + itemSection[slot].Quantity = qty; - strn0cpy(itemSection[slot].Donator, donator, sizeof(donator)); + strn0cpy(itemSection[slot].Donator, donator, sizeof(donator)); - itemSection[slot].Permissions = permissions; + itemSection[slot].Permissions = permissions; - strn0cpy(itemSection[slot].WhoFor, whoFor, sizeof(whoFor)); + strn0cpy(itemSection[slot].WhoFor, whoFor, sizeof(whoFor)); } Banks.push_back(bank); @@ -666,7 +666,7 @@ bool GuildBankManager::Load(uint32 guildID) bool GuildBankManager::IsLoaded(uint32 GuildID) { - std::list::iterator Iterator = GetGuildBank(GuildID); + auto Iterator = GetGuildBank(GuildID); return (Iterator != Banks.end()); } @@ -679,7 +679,7 @@ void GuildBankManager::SendGuildBank(Client *c) if(!IsLoaded(c->GuildID())) Load(c->GuildID()); - std::list::iterator Iterator = GetGuildBank(c->GuildID()); + auto Iterator = GetGuildBank(c->GuildID()); if(Iterator == Banks.end()) { @@ -754,7 +754,7 @@ void GuildBankManager::SendGuildBank(Client *c) if(!Item) continue; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankItemUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankItemUpdate_Struct)); GuildBankItemUpdate_Struct *gbius = (GuildBankItemUpdate_Struct*)outapp->pBuffer; @@ -792,7 +792,7 @@ void GuildBankManager::SendGuildBank(Client *c) bool Useable = Item->IsEquipable(c->GetBaseRace(), c->GetBaseClass()); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankItemUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_GuildBank, sizeof(GuildBankItemUpdate_Struct)); GuildBankItemUpdate_Struct *gbius = (GuildBankItemUpdate_Struct*)outapp->pBuffer; @@ -821,7 +821,7 @@ void GuildBankManager::SendGuildBank(Client *c) } bool GuildBankManager::IsAreaFull(uint32 GuildID, uint16 Area) { - std::list::iterator Iterator = GetGuildBank(GuildID); + auto Iterator = GetGuildBank(GuildID); if(Iterator == Banks.end()) return true; @@ -852,7 +852,7 @@ bool GuildBankManager::IsAreaFull(uint32 GuildID, uint16 Area) bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32 QtyOrCharges, const char *Donator, uint8 Permissions, const char *WhoFor) { - std::list::iterator Iterator = GetGuildBank(GuildID); + auto Iterator = GetGuildBank(GuildID); if(Iterator == Banks.end()) { @@ -1064,7 +1064,7 @@ void GuildBankManager::SetPermissions(uint32 guildID, uint16 slotID, uint32 perm ItemInst* GuildBankManager::GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity) { - std::list::iterator Iterator = GetGuildBank(GuildID); + auto Iterator = GetGuildBank(GuildID); if(Iterator == Banks.end()) return nullptr; @@ -1114,7 +1114,7 @@ ItemInst* GuildBankManager::GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, bool GuildBankManager::HasItem(uint32 GuildID, uint32 ItemID) { - std::list::iterator Iterator = GetGuildBank(GuildID); + auto Iterator = GetGuildBank(GuildID); if(Iterator == Banks.end()) return false; @@ -1132,7 +1132,7 @@ bool GuildBankManager::HasItem(uint32 GuildID, uint32 ItemID) std::list::iterator GuildBankManager::GetGuildBank(uint32 GuildID) { - std::list::iterator Iterator = Banks.begin(); + auto Iterator = Banks.begin(); while(Iterator != Banks.end()) { @@ -1220,7 +1220,7 @@ bool GuildBankManager::MergeStacks(uint32 GuildID, uint16 SlotID) if(SlotID > (GUILD_BANK_MAIN_AREA_SIZE - 1)) return false; - std::list::iterator Iterator = GetGuildBank(GuildID); + auto Iterator = GetGuildBank(GuildID); if(Iterator == Banks.end()) return false; @@ -1312,7 +1312,7 @@ bool GuildBankManager::SplitStack(uint32 GuildID, uint16 SlotID, uint32 Quantity if(SlotID > (GUILD_BANK_MAIN_AREA_SIZE - 1)) return false; - std::list::iterator Iterator = GetGuildBank(GuildID); + auto Iterator = GetGuildBank(GuildID); if(Iterator == Banks.end()) return false; @@ -1363,7 +1363,7 @@ bool GuildBankManager::AllowedToWithdraw(uint32 GuildID, uint16 Area, uint16 Slo if(SlotID > (GUILD_BANK_MAIN_AREA_SIZE - 1)) return false; - std::list::iterator Iterator = GetGuildBank(GuildID); + auto Iterator = GetGuildBank(GuildID); if(Iterator == Banks.end()) return false; @@ -1498,7 +1498,7 @@ void GuildApproval::GuildApproved() strncat(petitext,owner->CastToClient()->GetName(),len); strncat(petitext," Members:",len); strncat(petitext,gmembers,len); - Petition* pet = new Petition(owner->CastToClient()->CharacterID()); + auto pet = new Petition(owner->CastToClient()->CharacterID()); pet->SetAName(owner->CastToClient()->AccountName()); pet->SetClass(owner->CastToClient()->GetClass()); pet->SetLevel(owner->CastToClient()->GetLevel()); @@ -1514,7 +1514,7 @@ void GuildApproval::GuildApproved() petition_list.UpdateGMQueue(); petition_list.UpdateZoneListQueue(); worldserver.SendEmoteMessage(0, 0, 80, 15, "%s has made a petition. #%i", owner->CastToClient()->GetName(), pet->GetID()); - ServerPacket* pack = new ServerPacket; + auto pack = new ServerPacket; pack->opcode = ServerOP_RefreshGuild; pack->size = tmp; pack->pBuffer = new uchar[pack->size]; diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 962cfb010..b98ca6923 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -599,7 +599,7 @@ void HateList::SpellCast(Mob *caster, uint32 spell_id, float range, Mob* ae_cent ++iterator; } - std::list::iterator iter = id_list.begin(); + auto iter = id_list.begin(); while (iter != id_list.end()) { Mob *cur = entity_list.GetMobID((*iter)); diff --git a/zone/horse.cpp b/zone/horse.cpp index 2cf76886b..a2cebcdc9 100644 --- a/zone/horse.cpp +++ b/zone/horse.cpp @@ -83,35 +83,35 @@ const NPCType *Horse::BuildHorseType(uint16 spell_id) { auto row = results.begin(); - NPCType* npc_type = new NPCType; - memset(npc_type, 0, sizeof(NPCType)); - strcpy(npc_type->name,"Unclaimed_Mount"); //this should never get used + auto npc_type = new NPCType; + memset(npc_type, 0, sizeof(NPCType)); + strcpy(npc_type->name, "Unclaimed_Mount"); // this should never get used - strcpy(npc_type->special_abilities, "19,1^20,1^24,1"); - npc_type->cur_hp = 1; - npc_type->max_hp = 1; - npc_type->race = atoi(row[0]); - npc_type->gender = atoi(row[1]); // Drogmor's are female horses. Yuck. - npc_type->class_ = 1; - npc_type->deity= 1; - npc_type->level = 1; - npc_type->npc_id = 0; - npc_type->loottable_id = 0; - npc_type->texture = atoi(row[2]); // mount color - npc_type->helmtexture = atoi(row[2]); // mount color - npc_type->runspeed = atof(row[3]); + strcpy(npc_type->special_abilities, "19,1^20,1^24,1"); + npc_type->cur_hp = 1; + npc_type->max_hp = 1; + npc_type->race = atoi(row[0]); + npc_type->gender = atoi(row[1]); // Drogmor's are female horses. Yuck. + npc_type->class_ = 1; + npc_type->deity = 1; + npc_type->level = 1; + npc_type->npc_id = 0; + npc_type->loottable_id = 0; + npc_type->texture = atoi(row[2]); // mount color + npc_type->helmtexture = atoi(row[2]); // mount color + npc_type->runspeed = atof(row[3]); - npc_type->light = 0; - npc_type->STR = 75; - npc_type->STA = 75; - npc_type->DEX = 75; - npc_type->AGI = 75; - npc_type->INT = 75; - npc_type->WIS = 75; - npc_type->CHA = 75; - horses_auto_delete.Insert(npc_type); + npc_type->light = 0; + npc_type->STR = 75; + npc_type->STA = 75; + npc_type->DEX = 75; + npc_type->AGI = 75; + npc_type->INT = 75; + npc_type->WIS = 75; + npc_type->CHA = 75; + horses_auto_delete.Insert(npc_type); - return npc_type; + return npc_type; } void Client::SummonHorse(uint16 spell_id) { @@ -126,7 +126,7 @@ void Client::SummonHorse(uint16 spell_id) { // No Horse, lets get them one. - Horse* horse = new Horse(this, spell_id, GetPosition()); + auto horse = new Horse(this, spell_id, GetPosition()); //we want to manage the spawn packet ourself. //another reason is we dont want quests executing on it. diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 0ca5cc96e..29f4574e1 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -629,7 +629,7 @@ void Client::DropItem(int16 slot_id) return; // Package as zone object - Object* object = new Object(this, inst); + auto object = new Object(this, inst); entity_list.AddObject(object, true); object->StartDecay(); @@ -653,7 +653,7 @@ void Client::DropInst(const ItemInst* inst) } // Package as zone object - Object* object = new Object(this, inst); + auto object = new Object(this, inst); entity_list.AddObject(object, true); object->StartDecay(); } @@ -743,7 +743,9 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd if(m_inv[slot_id]) { delete_count += m_inv.GetItem(slot_id)->GetTotalItemCount(); } - ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogDeletes, sizeof(QSPlayerLogDelete_Struct) + (sizeof(QSDeleteItems_Struct) * delete_count)); + auto qspack = + new ServerPacket(ServerOP_QSPlayerLogDeletes, + sizeof(QSPlayerLogDelete_Struct) + (sizeof(QSDeleteItems_Struct) * delete_count)); QSPlayerLogDelete_Struct* qsaudit = (QSPlayerLogDelete_Struct*)qspack->pBuffer; uint16 parent_offset = 0; @@ -1283,7 +1285,7 @@ packet with the item number in it, but I cant seem to find it right now const EQEmu::Item_Struct* item = inst->GetItem(); const char* name2 = &item->Name[0]; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ItemLinkText,strlen(name2)+68); + auto outapp = new EQApplicationPacket(OP_ItemLinkText, strlen(name2) + 68); char buffer2[135] = {0}; char itemlink[135] = {0}; sprintf(itemlink,"%c0%06u0%05u-%05u-%05u-%05u-%05u00000000%c", @@ -1843,7 +1845,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { if(m_inv[resync_slot]) { SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade); } else { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); + auto outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); DeleteItem_Struct* delete_slot = (DeleteItem_Struct*)outapp->pBuffer; delete_slot->from_slot = resync_slot; delete_slot->to_slot = 0xFFFFFFFF; @@ -1885,7 +1887,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { if(m_inv[resync_slot]) { SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade); } else { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); + auto outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); DeleteItem_Struct* delete_slot = (DeleteItem_Struct*)outapp->pBuffer; delete_slot->from_slot = resync_slot; delete_slot->to_slot = 0xFFFFFFFF; @@ -1930,7 +1932,8 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { if(m_inv[from_slot_id]) { move_count += m_inv[from_slot_id]->GetTotalItemCount(); } if(to_slot_id != from_slot_id) { if(m_inv[to_slot_id]) { move_count += m_inv[to_slot_id]->GetTotalItemCount(); } } - ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogMoves, sizeof(QSPlayerLogMove_Struct) + (sizeof(QSMoveItems_Struct) * move_count)); + auto qspack = new ServerPacket(ServerOP_QSPlayerLogMoves, + sizeof(QSPlayerLogMove_Struct) + (sizeof(QSMoveItems_Struct) * move_count)); QSPlayerLogMove_Struct* qsaudit = (QSPlayerLogMove_Struct*)qspack->pBuffer; qsaudit->char_id = character_id; @@ -2046,7 +2049,7 @@ void Client::DyeArmor(DyeStruct* dye){ } } } - EQApplicationPacket* outapp=new EQApplicationPacket(OP_Dye,0); + auto outapp = new EQApplicationPacket(OP_Dye, 0); QueuePacket(outapp); safe_delete(outapp); @@ -3093,7 +3096,7 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool instmap[EQEmu::legacy::SlotPowerSource] = m_inv[EQEmu::legacy::SlotPowerSource]; // call InterrogateInventory_ for error check - for (std::map::iterator instmap_itr = instmap.begin(); (instmap_itr != instmap.end()) && (!error); ++instmap_itr) { + for (auto instmap_itr = instmap.begin(); (instmap_itr != instmap.end()) && (!error); ++instmap_itr) { InterrogateInventory_(true, requester, instmap_itr->first, INVALID_INDEX, instmap_itr->second, nullptr, log, silent, error, 0); } @@ -3108,7 +3111,7 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool } // call InterrogateInventory_ for report - for (std::map::iterator instmap_itr = instmap.begin(); (instmap_itr != instmap.end()); ++instmap_itr) { + for (auto instmap_itr = instmap.begin(); (instmap_itr != instmap.end()); ++instmap_itr) { InterrogateInventory_(false, requester, instmap_itr->first, INVALID_INDEX, instmap_itr->second, nullptr, log, silent, error, 0); } diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 1aab9eb51..65b21ff77 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -229,7 +229,7 @@ void NPC::AddLootDrop(const EQEmu::Item_Struct *item2, ItemList* itemlist, int16 if(!itemlist && !wearchange) return; - ServerLootItem_Struct* item = new ServerLootItem_Struct; + auto item = new ServerLootItem_Struct; #if EQDEBUG>=11 Log.Out(Logs::General, Logs::None, "Adding drop to npc: %s, Item: %i", GetName(), item2->ID); #endif diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 52eb2388f..320b084a0 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -46,7 +46,7 @@ void unregister_event(std::string package_name, std::string name, int evt); void load_encounter(std::string name) { if(lua_encounters_loaded.count(name) > 0) return; - Encounter *enc = new Encounter(name.c_str()); + auto enc = new Encounter(name.c_str()); entity_list.AddEncounter(enc); lua_encounters[name] = enc; lua_encounters_loaded[name] = true; @@ -56,7 +56,7 @@ void load_encounter(std::string name) { void load_encounter_with_data(std::string name, std::string info_str) { if(lua_encounters_loaded.count(name) > 0) return; - Encounter *enc = new Encounter(name.c_str()); + auto enc = new Encounter(name.c_str()); entity_list.AddEncounter(enc); lua_encounters[name] = enc; lua_encounters_loaded[name] = true; @@ -1216,8 +1216,8 @@ void lua_add_spawn_point(luabind::adl::object table) { lua_remove_spawn_point(spawn2_id); - Spawn2 *t = new Spawn2(spawn2_id, spawngroup_id, x, y, z, heading, respawn, variance, timeleft, grid, condition_id, - condition_min_value, enabled, static_cast(animation)); + auto t = new Spawn2(spawn2_id, spawngroup_id, x, y, z, heading, respawn, variance, timeleft, grid, + condition_id, condition_min_value, enabled, static_cast(animation)); zone->spawn2_list.Insert(t); } } @@ -1344,7 +1344,7 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float return; } - NPCType* npc_type = new NPCType; + auto npc_type = new NPCType; memset(npc_type, 0, sizeof(NPCType)); diff --git a/zone/map.cpp b/zone/map.cpp index c652d809c..5bfb3291b 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -233,7 +233,7 @@ Map *Map::LoadMapFile(std::string file) { filename += file; filename += ".map"; - Map *m = new Map(); + auto m = new Map(); if (m->Load(filename)) { return m; } diff --git a/zone/merc.cpp b/zone/merc.cpp index 369a8ef4f..51eac564d 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -2150,7 +2150,8 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) { std::list buffSpellList = GetMercSpellsBySpellType(this, SpellType_Buff); - for(std::list::iterator itr = buffSpellList.begin(); itr != buffSpellList.end(); ++itr) { + for (auto itr = buffSpellList.begin(); + itr != buffSpellList.end(); ++itr) { MercSpell selectedMercSpell = *itr; if(!((spells[selectedMercSpell.spellid].targettype == ST_Target || spells[selectedMercSpell.spellid].targettype == ST_Pet || @@ -2309,7 +2310,8 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) { std::list buffSpellList = GetMercSpellsBySpellType(this, SpellType_InCombatBuff); Mob* tar = this; - for(std::list::iterator itr = buffSpellList.begin(); itr != buffSpellList.end(); ++itr) { + for (auto itr = buffSpellList.begin(); + itr != buffSpellList.end(); ++itr) { MercSpell selectedMercSpell = *itr; if(!(spells[selectedMercSpell.spellid].targettype == ST_Self)) { @@ -2454,7 +2456,7 @@ void Merc::CheckHateList() { std::list npc_list; entity_list.GetNPCList(npc_list); - for(std::list::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) { + for (auto itr = npc_list.begin(); itr != npc_list.end(); ++itr) { NPC* npc = *itr; float dist = DistanceSquaredNoZ(m_Position, npc->GetPosition()); int radius = RuleI(Mercs, AggroRadius); @@ -2507,7 +2509,7 @@ bool Merc::CheckAENuke(Merc* caster, Mob* tar, uint16 spell_id, uint8 &numTarget std::list npc_list; entity_list.GetNPCList(npc_list); - for(std::list::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) { + for (auto itr = npc_list.begin(); itr != npc_list.end(); ++itr) { NPC* npc = *itr; if(DistanceSquaredNoZ(npc->GetPosition(), tar->GetPosition()) <= spells[spell_id].aoerange * spells[spell_id].aoerange) { @@ -3066,7 +3068,8 @@ MercSpell Merc::GetBestMercSpellForVeryFastHeal(Merc* caster) { if(caster) { std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsVeryFastHealSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { @@ -3098,7 +3101,8 @@ MercSpell Merc::GetBestMercSpellForFastHeal(Merc* caster) { if(caster) { std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsFastHealSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { @@ -3130,7 +3134,8 @@ MercSpell Merc::GetBestMercSpellForHealOverTime(Merc* caster) { if(caster) { std::list mercHoTSpellList = GetMercSpellsForSpellEffect(caster, SE_HealOverTime); - for(std::list::iterator mercSpellListItr = mercHoTSpellList.begin(); mercSpellListItr != mercHoTSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercHoTSpellList.begin(); mercSpellListItr != mercHoTSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsHealOverTimeSpell(mercSpellListItr->spellid)) { @@ -3170,7 +3175,8 @@ MercSpell Merc::GetBestMercSpellForPercentageHeal(Merc* caster) { if(caster && caster->AI_HasSpells()) { std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsCompleteHealSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { @@ -3202,7 +3208,8 @@ MercSpell Merc::GetBestMercSpellForRegularSingleTargetHeal(Merc* caster) { if(caster) { std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsRegularSingleTargetHealSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { @@ -3234,7 +3241,8 @@ MercSpell Merc::GetFirstMercSpellForSingleTargetHeal(Merc* caster) { if(caster) { std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if((IsRegularSingleTargetHealSpell(mercSpellListItr->spellid) || IsFastHealSpell(mercSpellListItr->spellid)) @@ -3267,7 +3275,8 @@ MercSpell Merc::GetBestMercSpellForGroupHeal(Merc* caster) { if(caster) { std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CurrentHP); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsRegularGroupHealSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { @@ -3299,7 +3308,8 @@ MercSpell Merc::GetBestMercSpellForGroupHealOverTime(Merc* caster) { if(caster) { std::list mercHoTSpellList = GetMercSpellsForSpellEffect(caster, SE_HealOverTime); - for(std::list::iterator mercSpellListItr = mercHoTSpellList.begin(); mercSpellListItr != mercHoTSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercHoTSpellList.begin(); mercSpellListItr != mercHoTSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsGroupHealOverTimeSpell(mercSpellListItr->spellid)) { @@ -3339,7 +3349,8 @@ MercSpell Merc::GetBestMercSpellForGroupCompleteHeal(Merc* caster) { if(caster) { std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_CompleteHeal); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsGroupCompleteHealSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { @@ -3371,7 +3382,8 @@ MercSpell Merc::GetBestMercSpellForAETaunt(Merc* caster) { if(caster) { std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_Taunt); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if((spells[mercSpellListItr->spellid].targettype == ST_AECaster || spells[mercSpellListItr->spellid].targettype == ST_AETarget @@ -3405,7 +3417,8 @@ MercSpell Merc::GetBestMercSpellForTaunt(Merc* caster) { if(caster) { std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_Taunt); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if((spells[mercSpellListItr->spellid].targettype == ST_Target) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { @@ -3437,7 +3450,8 @@ MercSpell Merc::GetBestMercSpellForHate(Merc* caster) { if(caster) { std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_InstantHate); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { result.spellid = mercSpellListItr->spellid; @@ -3493,7 +3507,7 @@ MercSpell Merc::GetBestMercSpellForCure(Merc* caster, Mob *tar) { //Check for group cure first if(countNeedsCured > 2) { - for(std::list::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) { + for (auto itr = cureList.begin(); itr != cureList.end(); ++itr) { MercSpell selectedMercSpell = *itr; if(IsGroupSpell(itr->spellid) && CheckSpellRecastTimers(caster, itr->spellid)) { @@ -3533,7 +3547,7 @@ MercSpell Merc::GetBestMercSpellForCure(Merc* caster, Mob *tar) { //no group cure for target- try to find single target spell if(!spellSelected) { - for(std::list::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) { + for (auto itr = cureList.begin(); itr != cureList.end(); ++itr) { MercSpell selectedMercSpell = *itr; if(CheckSpellRecastTimers(caster, itr->spellid)) { @@ -3589,7 +3603,8 @@ MercSpell Merc::GetBestMercSpellForStun(Merc* caster) { if(caster) { std::list mercSpellList = GetMercSpellsForSpellEffect(caster, SE_Stun); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { result.spellid = mercSpellListItr->spellid; @@ -3684,7 +3699,8 @@ MercSpell Merc::GetBestMercSpellForTargetedAENuke(Merc* caster, Mob* tar) { if(caster) { std::list mercSpellList = GetMercSpellsBySpellType(caster, SpellType_Nuke); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsAENukeSpell(mercSpellListItr->spellid) && !IsAERainNukeSpell(mercSpellListItr->spellid) && !IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { @@ -3735,7 +3751,8 @@ MercSpell Merc::GetBestMercSpellForPBAENuke(Merc* caster, Mob* tar) { if(caster) { std::list mercSpellList = GetMercSpellsBySpellType(caster, SpellType_Nuke); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { uint8 numTargets = 0; @@ -3785,7 +3802,8 @@ MercSpell Merc::GetBestMercSpellForAERainNuke(Merc* caster, Mob* tar) { if(caster) { std::list mercSpellList = GetMercSpellsBySpellType(caster, SpellType_Nuke); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsAERainNukeSpell(mercSpellListItr->spellid) && zone->random.Roll(castChance) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { uint8 numTargets = 0; @@ -3823,7 +3841,8 @@ MercSpell Merc::GetBestMercSpellForNuke(Merc* caster) { if(caster) { std::list mercSpellList = GetMercSpellsBySpellType(caster, SpellType_Nuke); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsPureNukeSpell(mercSpellListItr->spellid) && !IsAENukeSpell(mercSpellListItr->spellid) && zone->random.Roll(castChance) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { @@ -3866,7 +3885,8 @@ MercSpell Merc::GetBestMercSpellForNukeByTargetResists(Merc* caster, Mob* target std::list mercSpellList = GetMercSpellsBySpellType(caster, SpellType_Nuke); - for(std::list::iterator mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); ++mercSpellListItr) { + for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end(); + ++mercSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order if(IsPureNukeSpell(mercSpellListItr->spellid) && !IsAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) { @@ -4105,7 +4125,7 @@ bool Merc::CheckAETaunt() { std::list npc_list; entity_list.GetNPCList(npc_list); - for(std::list::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) { + for (auto itr = npc_list.begin(); itr != npc_list.end(); ++itr) { NPC* npc = *itr; float dist = DistanceSquaredNoZ(m_Position, npc->GetPosition()); int range = GetActSpellRange(mercSpell.spellid, spells[mercSpell.spellid].range); @@ -4168,7 +4188,7 @@ bool Merc::TryHide() { return false; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; sa_out->spawn_id = GetID(); sa_out->type = 0x03; @@ -4190,7 +4210,7 @@ bool Merc::CheckConfidence() { std::list npc_list; entity_list.GetNPCList(npc_list); - for(std::list::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) { + for (auto itr = npc_list.begin(); itr != npc_list.end(); ++itr) { NPC* mob = *itr; float ConRating = 1.0; int CurrentCon = 0; @@ -4667,7 +4687,7 @@ bool Merc::LoadMercSpells() { int16 attack_proc_spell = -1; int8 proc_chance = 0; - for (std::list::iterator mercSpellEntryItr = spellList.begin(); mercSpellEntryItr != spellList.end(); ++mercSpellEntryItr) { + for (auto mercSpellEntryItr = spellList.begin(); mercSpellEntryItr != spellList.end(); ++mercSpellEntryItr) { if (proficiency_id == mercSpellEntryItr->proficiencyid && GetLevel() >= mercSpellEntryItr->minlevel && GetLevel() <= mercSpellEntryItr->maxlevel && mercSpellEntryItr->spellid > 0) { MercSpell mercSpell; @@ -4725,7 +4745,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, if(npc_type_to_copy != nullptr) { //This is actually a very terrible method of assigning stats, and should be changed at some point. See the comment in merc's deconstructor. - NPCType* npc_type = new NPCType; + auto npc_type = new NPCType; memset(npc_type, 0, sizeof(NPCType)); memcpy(npc_type, npc_type_to_copy, sizeof(NPCType)); if(c && !updateFromDB) @@ -4771,7 +4791,7 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, npc_type->maxlevel = 0; //We should hard-set this to override scalerate's functionality in the NPC class when it is constructed. npc_type->no_target_hotkey = 1; - Merc* merc = new Merc(npc_type, c->GetX(), c->GetY(), c->GetZ(), 0); + auto merc = new Merc(npc_type, c->GetX(), c->GetY(), c->GetZ(), 0); merc->GiveNPCTypeData(npc_type); // for clean up, works a bit like pets if(merc) @@ -6063,7 +6083,7 @@ void Client::SendMercMerchantResponsePacket(int32 response_type) { // This response packet brings up the Mercenary Manager window if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryHire, sizeof(MercenaryMerchantResponse_Struct)); + auto outapp = new EQApplicationPacket(OP_MercenaryHire, sizeof(MercenaryMerchantResponse_Struct)); MercenaryMerchantResponse_Struct* mmr = (MercenaryMerchantResponse_Struct*)outapp->pBuffer; mmr->ResponseType = response_type; // send specified response type FastQueuePacket(&outapp); @@ -6073,7 +6093,7 @@ void Client::SendMercMerchantResponsePacket(int32 response_type) { void Client::SendMercenaryUnknownPacket(uint8 type) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryUnknown1, 1); + auto outapp = new EQApplicationPacket(OP_MercenaryUnknown1, 1); outapp->WriteUInt8(type); FastQueuePacket(&outapp); Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercenaryUnknownPacket Type: %i, Client: %s.", type, GetName()); @@ -6082,7 +6102,7 @@ void Client::SendMercenaryUnknownPacket(uint8 type) { void Client::SendMercenaryUnsuspendPacket(uint8 type) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryUnsuspendResponse, 1); + auto outapp = new EQApplicationPacket(OP_MercenaryUnsuspendResponse, 1); outapp->WriteUInt8(type); FastQueuePacket(&outapp); Log.Out(Logs::Moderate, Logs::Mercenaries, "Sent SendMercenaryUnsuspendPacket Type: %i, Client: %s.", type, GetName()); @@ -6091,7 +6111,7 @@ void Client::SendMercenaryUnsuspendPacket(uint8 type) { void Client::SendMercSuspendResponsePacket(uint32 suspended_time) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenarySuspendResponse, sizeof(SuspendMercenaryResponse_Struct)); + auto outapp = new EQApplicationPacket(OP_MercenarySuspendResponse, sizeof(SuspendMercenaryResponse_Struct)); SuspendMercenaryResponse_Struct* smr = (SuspendMercenaryResponse_Struct*)outapp->pBuffer; smr->SuspendTime = suspended_time; // Seen 0 (not suspended) or c9 c2 64 4f (suspended on Sat Mar 17 11:58:49 2012) - Unix Timestamp FastQueuePacket(&outapp); @@ -6102,7 +6122,7 @@ void Client::SendMercSuspendResponsePacket(uint32 suspended_time) { void Client::SendMercTimerPacket(int32 entity_id, int32 merc_state, int32 suspended_time, int32 update_interval, int32 unk01) { // Send Mercenary Status/Timer packet - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryTimer, sizeof(MercenaryStatus_Struct)); + auto outapp = new EQApplicationPacket(OP_MercenaryTimer, sizeof(MercenaryStatus_Struct)); MercenaryStatus_Struct* mss = (MercenaryStatus_Struct*)outapp->pBuffer; mss->MercEntityID = entity_id; // Seen 0 (no merc spawned) or unknown value when merc is spawned mss->MercState = merc_state; // Seen 5 (normal) or 1 (suspended) @@ -6115,7 +6135,7 @@ void Client::SendMercTimerPacket(int32 entity_id, int32 merc_state, int32 suspen } void Client::SendMercAssignPacket(uint32 entityID, uint32 unk01, uint32 unk02) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryAssign, sizeof(MercenaryAssign_Struct)); + auto outapp = new EQApplicationPacket(OP_MercenaryAssign, sizeof(MercenaryAssign_Struct)); MercenaryAssign_Struct* mas = (MercenaryAssign_Struct*)outapp->pBuffer; mas->MercEntityID = entityID; mas->MercUnk01 = unk01; @@ -6194,7 +6214,7 @@ int NPC::GetNumMercTypes(uint32 clientVersion) { int count = 0; std::list mercTypeList = GetMercTypesList(); - for(std::list::iterator mercTypeListItr = mercTypeList.begin(); mercTypeListItr != mercTypeList.end(); ++mercTypeListItr) { + for (auto mercTypeListItr = mercTypeList.begin(); mercTypeListItr != mercTypeList.end(); ++mercTypeListItr) { if(mercTypeListItr->ClientVersion <= clientVersion) count++; } @@ -6207,7 +6227,7 @@ int NPC::GetNumMercs(uint32 clientVersion) { int count = 0; std::list mercDataList = GetMercsList(); - for(std::list::iterator mercListItr = mercDataList.begin(); mercListItr != mercDataList.end(); ++mercListItr) { + for (auto mercListItr = mercDataList.begin(); mercListItr != mercDataList.end(); ++mercListItr) { if(mercListItr->ClientVersion <= clientVersion) count++; } @@ -6221,8 +6241,8 @@ std::list NPC::GetMercTypesList(uint32 clientVersion) { if(GetNumMercTypes() > 0) { - for(std::list::iterator mercTypeListItr = mercTypeList.begin(); mercTypeListItr != mercTypeList.end(); ++mercTypeListItr) - { + for (auto mercTypeListItr = mercTypeList.begin(); mercTypeListItr != mercTypeList.end(); + ++mercTypeListItr) { if(mercTypeListItr->ClientVersion <= clientVersion) { MercType mercType; @@ -6242,8 +6262,7 @@ std::list NPC::GetMercsList(uint32 clientVersion) { if(GetNumMercs() > 0) { - for(std::list::iterator mercListItr = mercDataList.begin(); mercListItr != mercDataList.end(); ++mercListItr) - { + for (auto mercListItr = mercDataList.begin(); mercListItr != mercDataList.end(); ++mercListItr) { if(mercListItr->ClientVersion <= clientVersion) { MercTemplate *merc_template = zone->GetMercTemplate(mercListItr->MercTemplateID); diff --git a/zone/mob.cpp b/zone/mob.cpp index 5b1e132a9..aa7862601 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1367,7 +1367,7 @@ void Mob::SendHPUpdate(bool skip_self) this->CastToClient()->SendHPUpdateMarquee(); - EQApplicationPacket* hp_app2 = new EQApplicationPacket(OP_HPUpdate,sizeof(SpawnHPUpdate_Struct)); + auto hp_app2 = new EQApplicationPacket(OP_HPUpdate, sizeof(SpawnHPUpdate_Struct)); SpawnHPUpdate_Struct* ds = (SpawnHPUpdate_Struct*)hp_app2->pBuffer; ds->cur_hp = CastToClient()->GetHP() - itembonuses.HP; ds->spawn_id = GetID(); @@ -1382,7 +1382,7 @@ void Mob::SendHPUpdate(bool skip_self) // this one just warps the mob to the current location void Mob::SendPosition() { - EQApplicationPacket* app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; MakeSpawnUpdateNoDelta(spu); move_tic_count = 0; @@ -1392,7 +1392,7 @@ void Mob::SendPosition() // this one is for mobs on the move, with deltas - this makes them walk void Mob::SendPosUpdate(uint8 iSendToSelf) { - EQApplicationPacket* app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; MakeSpawnUpdate(spu); @@ -1501,7 +1501,7 @@ void Mob::ShowStats(Client* client) } void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); + auto outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer; anim->spawnid = GetID(); if(type == 0){ @@ -1737,7 +1737,7 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture, } } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Illusion, sizeof(Illusion_Struct)); + auto outapp = new EQApplicationPacket(OP_Illusion, sizeof(Illusion_Struct)); Illusion_Struct* is = (Illusion_Struct*) outapp->pBuffer; is->spawnid = GetID(); strcpy(is->charname, GetCleanName()); @@ -2005,7 +2005,7 @@ uint8 Mob::GetDefaultGender(uint16 in_race, uint8 in_gender) { void Mob::SendAppearancePacket(uint32 type, uint32 value, bool WholeZone, bool iIgnoreSelf, Client *specific_target) { if (!GetID()) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* appearance = (SpawnAppearance_Struct*)outapp->pBuffer; appearance->spawn_id = this->GetID(); appearance->type = type; @@ -2020,7 +2020,7 @@ void Mob::SendAppearancePacket(uint32 type, uint32 value, bool WholeZone, bool i } void Mob::SendLevelAppearance(){ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer; la->parm1 = 0x4D; la->parm2 = la->parm1 + 1; @@ -2041,7 +2041,7 @@ void Mob::SendLevelAppearance(){ void Mob::SendStunAppearance() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer; la->parm1 = 58; la->parm2 = 60; @@ -2055,7 +2055,7 @@ void Mob::SendStunAppearance() } void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target){ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_LevelAppearance, sizeof(LevelAppearance_Struct)); LevelAppearance_Struct* la = (LevelAppearance_Struct*)outapp->pBuffer; la->spawn_id = GetID(); la->parm1 = parm1; @@ -2085,7 +2085,7 @@ void Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 } void Mob::SendTargetable(bool on, Client *specific_target) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Untargetable, sizeof(Untargetable_Struct)); + auto outapp = new EQApplicationPacket(OP_Untargetable, sizeof(Untargetable_Struct)); Untargetable_Struct *ut = (Untargetable_Struct*)outapp->pBuffer; ut->id = GetID(); ut->targetable_flag = on == true ? 1 : 0; @@ -2104,7 +2104,7 @@ void Mob::CameraEffect(uint32 duration, uint32 intensity, Client *c, bool global if(global == true) { - ServerPacket* pack = new ServerPacket(ServerOP_CameraShake, sizeof(ServerCameraShake_Struct)); + auto pack = new ServerPacket(ServerOP_CameraShake, sizeof(ServerCameraShake_Struct)); ServerCameraShake_Struct* scss = (ServerCameraShake_Struct*) pack->pBuffer; scss->duration = duration; scss->intensity = intensity; @@ -2113,7 +2113,7 @@ void Mob::CameraEffect(uint32 duration, uint32 intensity, Client *c, bool global return; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CameraEffect, sizeof(Camera_Struct)); + auto outapp = new EQApplicationPacket(OP_CameraEffect, sizeof(Camera_Struct)); Camera_Struct* cs = (Camera_Struct*) outapp->pBuffer; cs->duration = duration; // Duration in milliseconds cs->intensity = ((intensity * 6710886) + 1023410176); // Intensity ranges from 1023410176 to 1090519040, so simplify it from 0 to 10. @@ -2128,7 +2128,7 @@ void Mob::CameraEffect(uint32 duration, uint32 intensity, Client *c, bool global void Mob::SendSpellEffect(uint32 effectid, uint32 duration, uint32 finish_delay, bool zone_wide, uint32 unk020, bool perm_effect, Client *c) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpellEffect, sizeof(SpellEffect_Struct)); + auto outapp = new EQApplicationPacket(OP_SpellEffect, sizeof(SpellEffect_Struct)); SpellEffect_Struct* se = (SpellEffect_Struct*) outapp->pBuffer; se->EffectID = effectid; // ID of the Particle Effect se->EntityID = GetID(); @@ -2180,7 +2180,7 @@ void Mob::TempName(const char *newname) entity_list.MakeNameUnique(temp_name); // Send the new name to all clients - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MobRename, sizeof(MobRename_Struct)); + auto outapp = new EQApplicationPacket(OP_MobRename, sizeof(MobRename_Struct)); MobRename_Struct* mr = (MobRename_Struct*) outapp->pBuffer; strn0cpy(mr->old_name, old_name, 64); strn0cpy(mr->old_name_again, old_name, 64); @@ -2769,7 +2769,7 @@ void Mob::SendArmorAppearance(Client *one_client) void Mob::SendWearChange(uint8 material_slot, Client *one_client) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); + auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; wc->spawn_id = GetID(); @@ -2793,7 +2793,7 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client) void Mob::SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model, uint32 elite_material, uint32 unknown06, uint32 unknown18) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); + auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; wc->spawn_id = this->GetID(); @@ -2823,7 +2823,7 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin color |= (color) ? (0xFF << 24) : 0; armor_tint[material_slot] = color; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); + auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; wc->spawn_id = this->GetID(); @@ -2840,7 +2840,7 @@ void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 h { armor_tint[material_slot] = color; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); + auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; wc->spawn_id = this->GetID(); @@ -3447,7 +3447,7 @@ void Mob::SetEntityVariable(const char *id, const char *m_var) const char* Mob::GetEntityVariable(const char *id) { - std::map::iterator iter = m_EntityVariables.find(id); + auto iter = m_EntityVariables.find(id); if(iter != m_EntityVariables.end()) { return iter->second.c_str(); @@ -3457,7 +3457,7 @@ const char* Mob::GetEntityVariable(const char *id) bool Mob::EntityVariableExists(const char *id) { - std::map::iterator iter = m_EntityVariables.find(id); + auto iter = m_EntityVariables.find(id); if(iter != m_EntityVariables.end()) { return true; @@ -4253,7 +4253,7 @@ std::string Mob::GetGlobal(const char *varname) { if(qglobals) QGlobalCache::Combine(globalMap, qglobals->GetBucket(), qgNpcid, qgCharid, zone->GetZoneID()); - std::list::iterator iter = globalMap.begin(); + auto iter = globalMap.begin(); while(iter != globalMap.end()) { if ((*iter).name.compare(varname) == 0) return (*iter).value; @@ -4339,7 +4339,7 @@ void Mob::DelGlobal(const char *varname) { if(zone) { - ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); + auto pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct*)pack->pBuffer; qgu->npc_id = qgNpcid; @@ -4378,7 +4378,7 @@ void Mob::InsertQuestGlobal(int charid, int npcid, int zoneid, const char *varna if(zone) { //first delete our global - ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); + auto pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); ServerQGlobalDelete_Struct *qgd = (ServerQGlobalDelete_Struct*)pack->pBuffer; qgd->npc_id = npcid; qgd->char_id = charid; @@ -4491,7 +4491,7 @@ void Mob::DoKnockback(Mob *caster, uint32 pushback, uint32 pushup) { CastToClient()->SetKnockBackExemption(true); - EQApplicationPacket* outapp_push = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto outapp_push = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp_push->pBuffer; double look_heading = caster->CalculateHeadingToTarget(GetX(), GetY()); @@ -4880,7 +4880,7 @@ void Mob::RemoveNimbusEffect(int effectid) else if (effectid == nimbus_effect3) nimbus_effect3 = 0; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RemoveNimbusEffect, sizeof(RemoveNimbusEffect_Struct)); + auto outapp = new EQApplicationPacket(OP_RemoveNimbusEffect, sizeof(RemoveNimbusEffect_Struct)); RemoveNimbusEffect_Struct* rne = (RemoveNimbusEffect_Struct*)outapp->pBuffer; rne->spawnid = GetID(); rne->nimbus_effect = effectid; @@ -4904,7 +4904,7 @@ void Mob::SetBodyType(bodyType new_body, bool overwrite_orig) { bodytype = new_body; if(needs_spawn_packet) { - EQApplicationPacket* app = new EQApplicationPacket; + auto app = new EQApplicationPacket; CreateDespawnPacket(app, true); entity_list.QueueClients(this, app); CreateSpawnPacket(app, this); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 7958035ab..2b618e7e2 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -561,7 +561,7 @@ void Client::AI_Stop() { Mob::AI_Stop(); this->Message_StringID(13,PLAYER_REGAIN); - EQApplicationPacket *app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); + auto app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); Charm_Struct *ps = (Charm_Struct*)app->pBuffer; ps->owner_id = 0; ps->pet_id = this->GetID(); @@ -2526,7 +2526,7 @@ void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint16 iType, void NPC::RemoveSpellFromNPCList(int16 spell_id) { - std::vector::iterator iter = AIspells.begin(); + auto iter = AIspells.begin(); while(iter != AIspells.end()) { if((*iter).spellid == spell_id) @@ -2543,7 +2543,7 @@ void NPC::AISpellsList(Client *c) if (!c) return; - for (std::vector::iterator it = AIspells.begin(); it != AIspells.end(); ++it) + for (auto it = AIspells.begin(); it != AIspells.end(); ++it) c->Message(0, "%s (%d): Type %d, Priority %d", spells[it->spellid].name, it->spellid, it->type, it->priority); diff --git a/zone/net.cpp b/zone/net.cpp index b173b67a0..0f6ad0bbe 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -358,12 +358,12 @@ int main(int argc, char** argv) { parse = new QuestParserCollection(); #ifdef LUA_EQEMU - LuaParser *lua_parser = new LuaParser(); + auto lua_parser = new LuaParser(); parse->RegisterQuestInterface(lua_parser, "lua"); #endif #ifdef EMBPERL - PerlembParser *perl_parser = new PerlembParser(); + auto perl_parser = new PerlembParser(); parse->RegisterQuestInterface(perl_parser, "pl"); /* Load Perl Event Export Settings */ @@ -448,7 +448,7 @@ int main(int argc, char** argv) { struct in_addr in; in.s_addr = eqsi->GetRemoteIP(); Log.Out(Logs::Detail, Logs::World_Server, "New client from %s:%d", inet_ntoa(in), ntohs(eqsi->GetRemotePort())); - Client* client = new Client(eqsi); + auto client = new Client(eqsi); entity_list.AddClient(client); } diff --git a/zone/npc.cpp b/zone/npc.cpp index 8b09f448c..54c375f8c 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -303,7 +303,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if trap_list = trap_ent_iter->second; if(trap_list.size() > 0) { - std::list::iterator trap_list_iter = trap_list.begin(); + auto trap_list_iter = trap_list.begin(); std::advance(trap_list_iter, zone->random.Int(0, trap_list.size() - 1)); LDoNTrapTemplate* tt = (*trap_list_iter); if(tt) @@ -479,7 +479,7 @@ void NPC::CheckMinMaxLevel(Mob *them) uint16 themlevel = them->GetLevel(); uint8 material; - std::list::iterator cur = itemlist.begin(); + auto cur = itemlist.begin(); while(cur != itemlist.end()) { if(!(*cur)) @@ -522,7 +522,7 @@ void NPC::QueryLoot(Client* to) to->Message(0, "Coin: %ip %ig %is %ic", platinum, gold, silver, copper); int x = 0; - for(ItemList::iterator cur = itemlist.begin(); cur != itemlist.end(); ++cur, ++x) { + for (auto cur = itemlist.begin(); cur != itemlist.end(); ++cur, ++x) { const EQEmu::Item_Struct* item = database.GetItem((*cur)->item_id); if (item == nullptr) { Log.Out(Logs::General, Logs::Error, "Database error, invalid item"); @@ -848,7 +848,7 @@ bool NPC::SpawnZoneController(){ if (!RuleB(Zone, UseZoneController)) return false; - NPCType* npc_type = new NPCType; + auto npc_type = new NPCType; memset(npc_type, 0, sizeof(NPCType)); strncpy(npc_type->name, "zone_controller", 60); @@ -883,7 +883,7 @@ bool NPC::SpawnZoneController(){ point.y = 1000; point.z = 500; - NPC* npc = new NPC(npc_type, nullptr, point, FlyMode3); + auto npc = new NPC(npc_type, nullptr, point, FlyMode3); npc->GiveNPCTypeData(npc_type); entity_list.AddNPC(npc); @@ -1016,7 +1016,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* } //Time to create the NPC!! - NPCType* npc_type = new NPCType; + auto npc_type = new NPCType; memset(npc_type, 0, sizeof(NPCType)); strncpy(npc_type->name, sep.arg[0], 60); @@ -1050,7 +1050,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* npc_type->prim_melee_type = 28; npc_type->sec_melee_type = 28; - NPC* npc = new NPC(npc_type, nullptr, position, FlyMode3); + auto npc = new NPC(npc_type, nullptr, position, FlyMode3); npc->GiveNPCTypeData(npc_type); entity_list.AddNPC(npc); @@ -2464,7 +2464,7 @@ void NPC::DoQuestPause(Mob *other) { void NPC::ChangeLastName(const char* in_lastname) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GMLastName, sizeof(GMLastName_Struct)); + auto outapp = new EQApplicationPacket(OP_GMLastName, sizeof(GMLastName_Struct)); GMLastName_Struct* gmn = (GMLastName_Struct*)outapp->pBuffer; strcpy(gmn->name, GetName()); strcpy(gmn->gmname, GetName()); diff --git a/zone/object.cpp b/zone/object.cpp index f6330d872..f6338ab50 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -425,7 +425,7 @@ void Object::CreateDeSpawnPacket(EQApplicationPacket* app) bool Object::Process(){ if(m_type == OT_DROPPEDITEM && decay_timer.Enabled() && decay_timer.Check()) { // Send click to all clients (removes entity on client) - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct)); + auto outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct)); ClickObject_Struct* click_object = (ClickObject_Struct*)outapp->pBuffer; click_object->drop_id = GetID(); entity_list.QueueClients(nullptr, outapp, false); @@ -487,7 +487,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) args.push_back(m_inst); if(parse->EventPlayer(EVENT_PLAYER_PICKUP, sender, buf, this->GetID(), &args)) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct)); + auto outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct)); memcpy(outapp->pBuffer, click_object, sizeof(ClickObject_Struct)); ClickObject_Struct* co = (ClickObject_Struct*)outapp->pBuffer; co->drop_id = 0; @@ -518,7 +518,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) } // Send click to all clients (removes entity on client) - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct)); + auto outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct)); memcpy(outapp->pBuffer, click_object, sizeof(ClickObject_Struct)); entity_list.QueueClients(nullptr, outapp, false); safe_delete(outapp); @@ -529,7 +529,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) entity_list.RemoveEntity(this->GetID()); } else { // Tradeskill item - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClickObjectAction, sizeof(ClickObjectAction_Struct)); + auto outapp = new EQApplicationPacket(OP_ClickObjectAction, sizeof(ClickObjectAction_Struct)); ClickObjectAction_Struct* coa = (ClickObjectAction_Struct*)outapp->pBuffer; //TODO: there is prolly a better way to do this. @@ -580,7 +580,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) if(user != last_user) m_inst->ClearByFlags(byFlagSet, byFlagSet); - EQApplicationPacket* outapp=new EQApplicationPacket(OP_ClientReady,0); + auto outapp = new EQApplicationPacket(OP_ClientReady, 0); sender->QueuePacket(outapp); safe_delete(outapp); for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { @@ -610,7 +610,7 @@ uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& ob // SQL Escape object_name uint32 len = strlen(object.object_name) * 2 + 1; - char* object_name = new char[len]; + auto object_name = new char[len]; DoEscapeString(object_name, object.object_name, strlen(object.object_name)); // Save new record for object @@ -647,7 +647,7 @@ void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Objec // SQL Escape object_name uint32 len = strlen(object.object_name) * 2 + 1; - char* object_name = new char[len]; + auto object_name = new char[len]; DoEscapeString(object_name, object.object_name, strlen(object.object_name)); // Save new record for object @@ -754,8 +754,8 @@ void Object::SetX(float pos) { this->m_data.x = pos; - EQApplicationPacket* app = new EQApplicationPacket(); - EQApplicationPacket* app2 = new EQApplicationPacket(); + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); this->CreateSpawnPacket(app2); entity_list.QueueClients(0, app); @@ -768,8 +768,8 @@ void Object::SetY(float pos) { this->m_data.y = pos; - EQApplicationPacket* app = new EQApplicationPacket(); - EQApplicationPacket* app2 = new EQApplicationPacket(); + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); this->CreateSpawnPacket(app2); entity_list.QueueClients(0, app); @@ -780,7 +780,7 @@ void Object::SetY(float pos) void Object::Depop() { - EQApplicationPacket* app = new EQApplicationPacket(); + auto app = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); entity_list.QueueClients(0, app); safe_delete(app); @@ -789,8 +789,8 @@ void Object::Depop() void Object::Repop() { - EQApplicationPacket* app = new EQApplicationPacket(); - EQApplicationPacket* app2 = new EQApplicationPacket(); + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); this->CreateSpawnPacket(app2); entity_list.QueueClients(0, app); @@ -805,8 +805,8 @@ void Object::SetZ(float pos) { this->m_data.z = pos; - EQApplicationPacket* app = new EQApplicationPacket(); - EQApplicationPacket* app2 = new EQApplicationPacket(); + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); this->CreateSpawnPacket(app2); entity_list.QueueClients(0, app); @@ -818,8 +818,8 @@ void Object::SetZ(float pos) void Object::SetModelName(const char* modelname) { strn0cpy(m_data.object_name, modelname, sizeof(m_data.object_name)); // 32 is the max for chars in object_name, this should be safe - EQApplicationPacket* app = new EQApplicationPacket(); - EQApplicationPacket* app2 = new EQApplicationPacket(); + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); this->CreateSpawnPacket(app2); entity_list.QueueClients(0, app); @@ -831,8 +831,8 @@ void Object::SetModelName(const char* modelname) void Object::SetSize(uint16 size) { m_data.size = size; - EQApplicationPacket* app = new EQApplicationPacket(); - EQApplicationPacket* app2 = new EQApplicationPacket(); + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); this->CreateSpawnPacket(app2); entity_list.QueueClients(0, app); @@ -844,8 +844,8 @@ void Object::SetSize(uint16 size) void Object::SetSolidType(uint16 solidtype) { m_data.solidtype = solidtype; - EQApplicationPacket* app = new EQApplicationPacket(); - EQApplicationPacket* app2 = new EQApplicationPacket(); + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); this->CreateSpawnPacket(app2); entity_list.QueueClients(0, app); @@ -940,8 +940,8 @@ void Object::SetLocation(float x, float y, float z) this->m_data.x = x; this->m_data.y = y; this->m_data.z = z; - EQApplicationPacket* app = new EQApplicationPacket(); - EQApplicationPacket* app2 = new EQApplicationPacket(); + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); this->CreateSpawnPacket(app2); entity_list.QueueClients(0, app); @@ -961,8 +961,8 @@ void Object::GetHeading(float* heading) void Object::SetHeading(float heading) { this->m_data.heading = heading; - EQApplicationPacket* app = new EQApplicationPacket(); - EQApplicationPacket* app2 = new EQApplicationPacket(); + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); this->CreateDeSpawnPacket(app); this->CreateSpawnPacket(app2); entity_list.QueueClients(0, app); @@ -982,7 +982,7 @@ const char* Object::GetEntityVariable(const char *id) if(!id) return nullptr; - std::map::iterator iter = o_EntityVariables.find(id); + auto iter = o_EntityVariables.find(id); if(iter != o_EntityVariables.end()) { return iter->second.c_str(); @@ -995,7 +995,7 @@ bool Object::EntityVariableExists(const char * id) if(!id) return false; - std::map::iterator iter = o_EntityVariables.find(id); + auto iter = o_EntityVariables.find(id); if(iter != o_EntityVariables.end()) { return true; diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 8c0271c06..a39441564 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -546,7 +546,7 @@ void PathManager::SpawnPathNodes() for(uint32 i = 0; i < Head.PathNodeCount; ++i) { - NPCType* npc_type = new NPCType; + auto npc_type = new NPCType; memset(npc_type, 0, sizeof(NPCType)); if(PathNodes[i].id < 10) @@ -585,10 +585,10 @@ void PathManager::SpawnPathNodes() npc_type->findable = 1; auto position = glm::vec4(PathNodes[i].v.x, PathNodes[i].v.y, PathNodes[i].v.z, 0.0f); - NPC* npc = new NPC(npc_type, nullptr, position, FlyMode1); - npc->GiveNPCTypeData(npc_type); + auto npc = new NPC(npc_type, nullptr, position, FlyMode1); + npc->GiveNPCTypeData(npc_type); - entity_list.AddNPC(npc, true, true); + entity_list.AddNPC(npc, true, true); } } @@ -1311,7 +1311,7 @@ void Client::SendPathPacket(std::vector &points) { } int len = sizeof(FindPersonResult_Struct) + (points.size()+1) * sizeof(FindPerson_Point); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_FindPersonReply, len); + auto outapp = new EQApplicationPacket(OP_FindPersonReply, len); FindPersonResult_Struct* fpr=(FindPersonResult_Struct*)outapp->pBuffer; std::vector::iterator cur, end; @@ -1509,7 +1509,7 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques Head.PathNodeCount++; if(Head.PathNodeCount > 1) { - PathNode *t_PathNodes = new PathNode[Head.PathNodeCount]; + auto t_PathNodes = new PathNode[Head.PathNodeCount]; for(uint32 x = 0; x < (Head.PathNodeCount - 1); ++x) { t_PathNodes[x].v.x = PathNodes[x].v.x; @@ -1544,7 +1544,7 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques delete[] PathNodes; PathNodes = t_PathNodes; - NPCType* npc_type = new NPCType; + auto npc_type = new NPCType; memset(npc_type, 0, sizeof(NPCType)); if(new_id < 10) sprintf(npc_type->name, "%s", DigitToWord(new_id)); @@ -1581,13 +1581,13 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques npc_type->findable = 1; auto position = glm::vec4(new_node.v.x, new_node.v.y, new_node.v.z, 0.0f); - NPC* npc = new NPC(npc_type, nullptr, position, FlyMode1); - npc->GiveNPCTypeData(npc_type); - entity_list.AddNPC(npc, true, true); + auto npc = new NPC(npc_type, nullptr, position, FlyMode1); + npc->GiveNPCTypeData(npc_type); + entity_list.AddNPC(npc, true, true); - safe_delete_array(ClosedListFlag); - ClosedListFlag = new int[Head.PathNodeCount]; - return new_id; + safe_delete_array(ClosedListFlag); + ClosedListFlag = new int[Head.PathNodeCount]; + return new_id; } else { @@ -1605,7 +1605,7 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques PathNodes[0].Neighbours[n].Teleport = new_node.Neighbours[n].Teleport; } - NPCType* npc_type = new NPCType; + auto npc_type = new NPCType; memset(npc_type, 0, sizeof(NPCType)); if(new_id < 10) sprintf(npc_type->name, "%s", DigitToWord(new_id)); @@ -1642,13 +1642,13 @@ int32 PathManager::AddNode(float x, float y, float z, float best_z, int32 reques npc_type->findable = 1; auto position = glm::vec4(new_node.v.x, new_node.v.y, new_node.v.z, 0.0f); - NPC* npc = new NPC(npc_type, nullptr, position, FlyMode1); - npc->GiveNPCTypeData(npc_type); - entity_list.AddNPC(npc, true, true); + auto npc = new NPC(npc_type, nullptr, position, FlyMode1); + npc->GiveNPCTypeData(npc_type); + entity_list.AddNPC(npc, true, true); - ClosedListFlag = new int[Head.PathNodeCount]; + ClosedListFlag = new int[Head.PathNodeCount]; - return new_id; + return new_id; } } @@ -1684,7 +1684,7 @@ bool PathManager::DeleteNode(int32 id) if(Head.PathNodeCount > 1) { - PathNode *t_PathNodes = new PathNode[Head.PathNodeCount-1]; + auto t_PathNodes = new PathNode[Head.PathNodeCount - 1]; uint32 index = 0; for(uint32 x = 0; x < Head.PathNodeCount; x++) { @@ -2233,7 +2233,7 @@ void PathManager::SortNodes() sorted_vals.push_back(tmp); } - PathNode *t_PathNodes = new PathNode[Head.PathNodeCount]; + auto t_PathNodes = new PathNode[Head.PathNodeCount]; memcpy(t_PathNodes, PathNodes, sizeof(PathNode)*Head.PathNodeCount); for(uint32 i = 0; i < Head.PathNodeCount; ++i) { diff --git a/zone/perl_entity.cpp b/zone/perl_entity.cpp index c80b81c5d..eafc5c822 100644 --- a/zone/perl_entity.cpp +++ b/zone/perl_entity.cpp @@ -1904,7 +1904,7 @@ XS(XS_EntityList_GetMobList) std::list mob_list; entity_list.GetMobList(mob_list); - std::list::iterator iter = mob_list.begin(); + auto iter = mob_list.begin(); while(iter != mob_list.end()) { @@ -1941,7 +1941,7 @@ XS(XS_EntityList_GetClientList) std::list client_list; entity_list.GetClientList(client_list); - std::list::iterator iter = client_list.begin(); + auto iter = client_list.begin(); while(iter != client_list.end()) { @@ -1978,7 +1978,7 @@ XS(XS_EntityList_GetNPCList) std::list npc_list; entity_list.GetNPCList(npc_list); - std::list::iterator iter = npc_list.begin(); + auto iter = npc_list.begin(); while(iter != npc_list.end()) { @@ -2015,7 +2015,7 @@ XS(XS_EntityList_GetCorpseList) std::list corpse_list; entity_list.GetCorpseList(corpse_list); - std::list::iterator iter = corpse_list.begin(); + auto iter = corpse_list.begin(); while(iter != corpse_list.end()) { @@ -2052,7 +2052,7 @@ XS(XS_EntityList_GetObjectList) std::list object_list; entity_list.GetObjectList(object_list); - std::list::iterator iter = object_list.begin(); + auto iter = object_list.begin(); while(iter != object_list.end()) { @@ -2089,7 +2089,7 @@ XS(XS_EntityList_GetDoorsList) std::list door_list; entity_list.GetDoorsList(door_list); - std::list::iterator iter = door_list.begin(); + auto iter = door_list.begin(); while(iter != door_list.end()) { diff --git a/zone/perlpacket.cpp b/zone/perlpacket.cpp index ed0dd9cd3..9f423f089 100644 --- a/zone/perlpacket.cpp +++ b/zone/perlpacket.cpp @@ -62,7 +62,7 @@ void PerlPacket::SendTo(Client *who) { if(!who || op == OP_Unknown || (len > 0 && packet == nullptr)) return; - EQApplicationPacket *outapp = new EQApplicationPacket(op, len); + auto outapp = new EQApplicationPacket(op, len); if(len > 0) memcpy(outapp->pBuffer, packet, len); @@ -76,7 +76,7 @@ void PerlPacket::SendToAll() { if(op == OP_Unknown || (len > 0 && packet == nullptr)) return; - EQApplicationPacket *outapp = new EQApplicationPacket(op, len); + auto outapp = new EQApplicationPacket(op, len); if(len > 0) memcpy(outapp->pBuffer, packet, len); entity_list.QueueClients(nullptr, outapp, false); diff --git a/zone/petitions.cpp b/zone/petitions.cpp index 3e8a836e2..d3c350b5f 100644 --- a/zone/petitions.cpp +++ b/zone/petitions.cpp @@ -44,7 +44,7 @@ PetitionList petition_list; extern WorldServer worldserver; void Petition::SendPetitionToPlayer(Client* clientto) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_PetitionCheckout,sizeof(Petition_Struct)); + auto outapp = new EQApplicationPacket(OP_PetitionCheckout, sizeof(Petition_Struct)); Petition_Struct* pet = (Petition_Struct*) outapp->pBuffer; strcpy(pet->accountid,this->GetAccountName()); strcpy(pet->lastgm,this->GetLastGM()); @@ -136,7 +136,7 @@ bool PetitionList::DeletePetitionByCharName(const char* charname) { return false; } void PetitionList::UpdateZoneListQueue() { - ServerPacket* pack = new ServerPacket(ServerOP_Petition, sizeof(ServerPetitionUpdate_Struct)); + auto pack = new ServerPacket(ServerOP_Petition, sizeof(ServerPetitionUpdate_Struct)); ServerPetitionUpdate_Struct* pupdate = (ServerPetitionUpdate_Struct*) pack->pBuffer; pupdate->petid = 0x00; pupdate->status = 0x00; @@ -229,7 +229,7 @@ void ZoneDatabase::InsertPetitionToDB(Petition* wpet) { uint32 len = strlen(wpet->GetPetitionText()); - char* petitiontext = new char[2*len+1]; + auto petitiontext = new char[2 * len + 1]; memset(petitiontext, 0, 2*len+1); DoEscapeString(petitiontext, wpet->GetPetitionText(), len); diff --git a/zone/pets.cpp b/zone/pets.cpp index 96c053e73..6085cab53 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -264,7 +264,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, } //we copy the npc_type data because we need to edit it a bit - NPCType *npc_type = new NPCType; + auto npc_type = new NPCType; memcpy(npc_type, base, sizeof(NPCType)); // If pet power is set to -1 in the DB, use stat scaling @@ -412,7 +412,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, } //this takes ownership of the npc_type data - Pet *npc = new Pet(npc_type, this, (PetType)record.petcontrol, spell_id, record.petpower); + auto npc = new Pet(npc_type, this, (PetType)record.petcontrol, spell_id, record.petpower); // Now that we have an actual object to interact with, load // the base items for the pet. These are always loaded diff --git a/zone/qglobals.cpp b/zone/qglobals.cpp index 0dced7cb0..f1719def5 100644 --- a/zone/qglobals.cpp +++ b/zone/qglobals.cpp @@ -12,7 +12,7 @@ void QGlobalCache::AddGlobal(uint32 id, QGlobal global) void QGlobalCache::RemoveGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID) { - std::list::iterator iter = qGlobalBucket.begin(); + auto iter = qGlobalBucket.begin(); while(iter != qGlobalBucket.end()) { if(name.compare((*iter).name) == 0) @@ -31,7 +31,7 @@ void QGlobalCache::RemoveGlobal(std::string name, uint32 npcID, uint32 charID, u void QGlobalCache::Combine(std::list &cacheA, std::list cacheB, uint32 npcID, uint32 charID, uint32 zoneID) { - std::list::iterator iter = cacheB.begin(); + auto iter = cacheB.begin(); while(iter != cacheB.end()) { QGlobal cur = (*iter); @@ -123,7 +123,7 @@ void QGlobalCache::PurgeExpiredGlobals() if(!qGlobalBucket.size()) return; - std::list::iterator iter = qGlobalBucket.begin(); + auto iter = qGlobalBucket.begin(); while(iter != qGlobalBucket.end()) { QGlobal cur = (*iter); diff --git a/zone/queryserv.cpp b/zone/queryserv.cpp index d67ca46c7..691943a7c 100644 --- a/zone/queryserv.cpp +++ b/zone/queryserv.cpp @@ -35,7 +35,7 @@ QueryServ::~QueryServ(){ void QueryServ::SendQuery(std::string Query) { - ServerPacket* pack = new ServerPacket(ServerOP_QSSendQuery, Query.length() + 5); + auto pack = new ServerPacket(ServerOP_QSSendQuery, Query.length() + 5); pack->WriteUInt32(Query.length()); /* Pack Query String Size so it can be dynamically broken out at queryserv */ pack->WriteString(Query.c_str()); /* Query */ worldserver.SendPacket(pack); diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index 33a18d379..290b71ab9 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -53,7 +53,7 @@ void QuestParserCollection::ClearInterfaces() { } void QuestParserCollection::AddVar(std::string name, std::string val) { - std::list::iterator iter = _load_precedence.begin(); + auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { (*iter)->AddVar(name, val); ++iter; @@ -61,7 +61,7 @@ void QuestParserCollection::AddVar(std::string name, std::string val) { } void QuestParserCollection::Init() { - std::list::iterator iter = _load_precedence.begin(); + auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { (*iter)->Init(); ++iter; @@ -81,7 +81,7 @@ void QuestParserCollection::ReloadQuests(bool reset_timers) { _spell_quest_status.clear(); _item_quest_status.clear(); _encounter_quest_status.clear(); - std::list::iterator iter = _load_precedence.begin(); + auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { (*iter)->ReloadQuests(); ++iter; @@ -93,12 +93,12 @@ bool QuestParserCollection::HasQuestSub(uint32 npcid, QuestEventID evt) { } bool QuestParserCollection::HasQuestSubLocal(uint32 npcid, QuestEventID evt) { - std::map::iterator iter = _npc_quest_status.find(npcid); - + auto iter = _npc_quest_status.find(npcid); + if(iter != _npc_quest_status.end()) { //loaded or failed to load if(iter->second != QuestFailedToLoad) { - std::map::iterator qiter = _interfaces.find(iter->second); + auto qiter = _interfaces.find(iter->second); if(qiter->second->HasQuestSub(npcid, evt)) { return true; } @@ -133,7 +133,7 @@ bool QuestParserCollection::HasQuestSubGlobal(QuestEventID evt) { } } else { if(_global_npc_quest_status != QuestFailedToLoad) { - std::map::iterator qiter = _interfaces.find(_global_npc_quest_status); + auto qiter = _interfaces.find(_global_npc_quest_status); if(qiter->second->HasGlobalQuestSub(evt)) { return true; } @@ -156,7 +156,7 @@ bool QuestParserCollection::PlayerHasQuestSubLocal(QuestEventID evt) { return qi->PlayerHasQuestSub(evt); } } else if(_player_quest_status != QuestFailedToLoad) { - std::map::iterator iter = _interfaces.find(_player_quest_status); + auto iter = _interfaces.find(_player_quest_status); return iter->second->PlayerHasQuestSub(evt); } return false; @@ -172,18 +172,18 @@ bool QuestParserCollection::PlayerHasQuestSubGlobal(QuestEventID evt) { return qi->GlobalPlayerHasQuestSub(evt); } } else if(_global_player_quest_status != QuestFailedToLoad) { - std::map::iterator iter = _interfaces.find(_global_player_quest_status); + auto iter = _interfaces.find(_global_player_quest_status); return iter->second->GlobalPlayerHasQuestSub(evt); } return false; } bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID evt) { - std::map::iterator iter = _spell_quest_status.find(spell_id); + auto iter = _spell_quest_status.find(spell_id); if(iter != _spell_quest_status.end()) { //loaded or failed to load if(iter->second != QuestFailedToLoad) { - std::map::iterator qiter = _interfaces.find(iter->second); + auto qiter = _interfaces.find(iter->second); return qiter->second->SpellHasQuestSub(spell_id, evt); } } else { @@ -215,11 +215,11 @@ bool QuestParserCollection::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) { } uint32 item_id = itm->GetID(); - std::map::iterator iter = _item_quest_status.find(item_id); + auto iter = _item_quest_status.find(item_id); if(iter != _item_quest_status.end()) { //loaded or failed to load if(iter->second != QuestFailedToLoad) { - std::map::iterator qiter = _interfaces.find(iter->second); + auto qiter = _interfaces.find(iter->second); return qiter->second->ItemHasQuestSub(itm, evt); } } else { @@ -256,11 +256,11 @@ int QuestParserCollection::EventNPC(QuestEventID evt, NPC *npc, Mob *init, std:: int QuestParserCollection::EventNPCLocal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { - std::map::iterator iter = _npc_quest_status.find(npc->GetNPCTypeID()); + auto iter = _npc_quest_status.find(npc->GetNPCTypeID()); if(iter != _npc_quest_status.end()) { //loaded or failed to load if(iter->second != QuestFailedToLoad) { - std::map::iterator qiter = _interfaces.find(iter->second); + auto qiter = _interfaces.find(iter->second); return qiter->second->EventNPC(evt, npc, init, data, extra_data, extra_pointers); } } else { @@ -280,7 +280,7 @@ int QuestParserCollection::EventNPCLocal(QuestEventID evt, NPC* npc, Mob *init, int QuestParserCollection::EventNPCGlobal(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers) { if(_global_npc_quest_status != QuestUnloaded && _global_npc_quest_status != QuestFailedToLoad) { - std::map::iterator qiter = _interfaces.find(_global_npc_quest_status); + auto qiter = _interfaces.find(_global_npc_quest_status); return qiter->second->EventGlobalNPC(evt, npc, init, data, extra_data, extra_pointers); } else { std::string filename; @@ -326,7 +326,7 @@ int QuestParserCollection::EventPlayerLocal(QuestEventID evt, Client *client, st } } else { if(_player_quest_status != QuestFailedToLoad) { - std::map::iterator iter = _interfaces.find(_player_quest_status); + auto iter = _interfaces.find(_player_quest_status); return iter->second->EventPlayer(evt, client, data, extra_data, extra_pointers); } } @@ -345,7 +345,7 @@ int QuestParserCollection::EventPlayerGlobal(QuestEventID evt, Client *client, s } } else { if(_global_player_quest_status != QuestFailedToLoad) { - std::map::iterator iter = _interfaces.find(_global_player_quest_status); + auto iter = _interfaces.find(_global_player_quest_status); return iter->second->EventGlobalPlayer(evt, client, data, extra_data, extra_pointers); } } @@ -367,11 +367,11 @@ int QuestParserCollection::EventItem(QuestEventID evt, Client *client, ItemInst } uint32 item_id = item->GetID(); - std::map::iterator iter = _item_quest_status.find(item_id); + auto iter = _item_quest_status.find(item_id); if(iter != _item_quest_status.end()) { //loaded or failed to load if(iter->second != QuestFailedToLoad) { - std::map::iterator qiter = _interfaces.find(iter->second); + auto qiter = _interfaces.find(iter->second); int ret = DispatchEventItem(evt, client, item, mob, data, extra_data, extra_pointers); int i = qiter->second->EventItem(evt, client, item, mob, data, extra_data, extra_pointers); if(i != 0) { @@ -402,11 +402,11 @@ int QuestParserCollection::EventItem(QuestEventID evt, Client *client, ItemInst int QuestParserCollection::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers) { - std::map::iterator iter = _spell_quest_status.find(spell_id); + auto iter = _spell_quest_status.find(spell_id); if(iter != _spell_quest_status.end()) { //loaded or failed to load if(iter->second != QuestFailedToLoad) { - std::map::iterator qiter = _interfaces.find(iter->second); + auto qiter = _interfaces.find(iter->second); int ret = DispatchEventSpell(evt, npc, client, spell_id, extra_data, extra_pointers); int i = qiter->second->EventSpell(evt, npc, client, spell_id, extra_data, extra_pointers); if(i != 0) { @@ -441,7 +441,7 @@ int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounte if(iter != _encounter_quest_status.end()) { //loaded or failed to load if(iter->second != QuestFailedToLoad) { - std::map::iterator qiter = _interfaces.find(iter->second); + auto qiter = _interfaces.find(iter->second); return qiter->second->EventEncounter(evt, encounter_name, data, extra_data, extra_pointers); } } else { @@ -467,10 +467,10 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string std::string tmp; FILE *f = nullptr; - std::list::iterator iter = _load_precedence.begin(); + auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -511,7 +511,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -532,7 +532,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -553,7 +553,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -574,7 +574,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -595,7 +595,7 @@ QuestInterface *QuestParserCollection::GetQIByNPCQuest(uint32 npcid, std::string iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -624,10 +624,10 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) std::string tmp; FILE *f = nullptr; - std::list::iterator iter = _load_precedence.begin(); + auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -649,7 +649,7 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -670,7 +670,7 @@ QuestInterface *QuestParserCollection::GetQIByPlayerQuest(std::string &filename) iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -695,10 +695,10 @@ QuestInterface *QuestParserCollection::GetQIByGlobalNPCQuest(std::string &filena std::string tmp; FILE *f = nullptr; - std::list::iterator iter = _load_precedence.begin(); + auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -723,10 +723,10 @@ QuestInterface *QuestParserCollection::GetQIByGlobalPlayerQuest(std::string &fil std::string tmp; FILE *f = nullptr; - std::list::iterator iter = _load_precedence.begin(); + auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -751,10 +751,10 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s std::string tmp; FILE *f = nullptr; - std::list::iterator iter = _load_precedence.begin(); + auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -776,7 +776,7 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -797,7 +797,7 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -818,7 +818,7 @@ QuestInterface *QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -843,10 +843,10 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, std::string tmp; FILE *f = nullptr; - std::list::iterator iter = _load_precedence.begin(); + auto iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -868,7 +868,7 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -889,7 +889,7 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); @@ -910,7 +910,7 @@ QuestInterface *QuestParserCollection::GetQIByItemQuest(std::string item_script, iter = _load_precedence.begin(); while(iter != _load_precedence.end()) { tmp = filename; - std::map::iterator ext = _extensions.find((*iter)->GetIdentifier()); + auto ext = _extensions.find((*iter)->GetIdentifier()); tmp += "."; tmp += ext->second; f = fopen(tmp.c_str(), "r"); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 4a1980489..70c7c404f 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -207,7 +207,7 @@ Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& p const NPCType* tmp = 0; if (tmp = database.LoadNPCTypesData(npc_type)) { - NPC* npc = new NPC(tmp, nullptr, position, FlyMode3); + auto npc = new NPC(tmp, nullptr, position, FlyMode3); npc->AddLootTable(); entity_list.AddNPC(npc,true,true); if(grid > 0) @@ -229,7 +229,7 @@ Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, const glm::v const NPCType* tmp = 0; if (tmp = database.LoadNPCTypesData(npc_type)) { - NPC* npc = new NPC(tmp, nullptr, position, FlyMode3); + auto npc = new NPC(tmp, nullptr, position, FlyMode3); npc->AddLootTable(); entity_list.AddNPC(npc,true,true); if(grid > 0) @@ -303,19 +303,20 @@ Mob* QuestManager::spawn_from_spawn2(uint32 spawn2_id) found_spawn->SetCurrentNPCID(npcid); auto position = glm::vec4(found_spawn->GetX(), found_spawn->GetY(), found_spawn->GetZ(), found_spawn->GetHeading()); - NPC* npc = new NPC(tmp, found_spawn, position, FlyMode3); + auto npc = new NPC(tmp, found_spawn, position, FlyMode3); - found_spawn->SetNPCPointer(npc); - npc->AddLootTable(); - npc->SetSp2(found_spawn->SpawnGroupID()); - entity_list.AddNPC(npc); - entity_list.LimitAddNPC(npc); + found_spawn->SetNPCPointer(npc); + npc->AddLootTable(); + npc->SetSp2(found_spawn->SpawnGroupID()); + entity_list.AddNPC(npc); + entity_list.LimitAddNPC(npc); - if(sg->roamdist && sg->roambox[0] && sg->roambox[1] && sg->roambox[2] && sg->roambox[3] && sg->delay && sg->min_delay) - npc->AI_SetRoambox(sg->roamdist,sg->roambox[0],sg->roambox[1],sg->roambox[2],sg->roambox[3],sg->delay,sg->min_delay); - if(zone->InstantGrids()) - { - found_spawn->LoadGrid(); + if (sg->roamdist && sg->roambox[0] && sg->roambox[1] && sg->roambox[2] && sg->roambox[3] && sg->delay && + sg->min_delay) + npc->AI_SetRoambox(sg->roamdist, sg->roambox[0], sg->roambox[1], sg->roambox[2], sg->roambox[3], + sg->delay, sg->min_delay); + if (zone->InstantGrids()) { + found_spawn->LoadGrid(); } return npc; @@ -327,7 +328,7 @@ Mob* QuestManager::spawn_from_spawn2(uint32 spawn2_id) void QuestManager::enable_spawn2(uint32 spawn2_id) { database.UpdateSpawn2Status(spawn2_id, 1); - ServerPacket* pack = new ServerPacket(ServerOP_SpawnStatusChange, sizeof(ServerSpawnStatusChange_Struct)); + auto pack = new ServerPacket(ServerOP_SpawnStatusChange, sizeof(ServerSpawnStatusChange_Struct)); ServerSpawnStatusChange_Struct* ssc = (ServerSpawnStatusChange_Struct*) pack->pBuffer; ssc->id = spawn2_id; ssc->new_status = 1; @@ -338,7 +339,7 @@ void QuestManager::enable_spawn2(uint32 spawn2_id) void QuestManager::disable_spawn2(uint32 spawn2_id) { database.UpdateSpawn2Status(spawn2_id, 0); - ServerPacket* pack = new ServerPacket(ServerOP_SpawnStatusChange, sizeof(ServerSpawnStatusChange_Struct)); + auto pack = new ServerPacket(ServerOP_SpawnStatusChange, sizeof(ServerSpawnStatusChange_Struct)); ServerSpawnStatusChange_Struct* ssc = (ServerSpawnStatusChange_Struct*) pack->pBuffer; ssc->id = spawn2_id; ssc->new_status = 0; @@ -385,7 +386,7 @@ void QuestManager::Zone(const char *zone_name) { QuestManagerCurrentQuestVars(); if (initiator && initiator->IsClient()) { - ServerPacket* pack = new ServerPacket(ServerOP_ZoneToZoneRequest, sizeof(ZoneToZone_Struct)); + auto pack = new ServerPacket(ServerOP_ZoneToZoneRequest, sizeof(ZoneToZone_Struct)); ZoneToZone_Struct* ztz = (ZoneToZone_Struct*) pack->pBuffer; ztz->response = 0; ztz->current_zone_id = zone->GetZoneID(); @@ -880,7 +881,7 @@ void QuestManager::safemove() { void QuestManager::rain(int weather) { QuestManagerCurrentQuestVars(); zone->zone_weather = weather; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weather, 8); + auto outapp = new EQApplicationPacket(OP_Weather, 8); *((uint32*) &outapp->pBuffer[4]) = (uint32) weather; // Why not just use 0x01/2/3? entity_list.QueueClients(owner, outapp); safe_delete(outapp); @@ -889,7 +890,7 @@ void QuestManager::rain(int weather) { void QuestManager::snow(int weather) { QuestManagerCurrentQuestVars(); zone->zone_weather = weather + 1; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weather, 8); + auto outapp = new EQApplicationPacket(OP_Weather, 8); outapp->pBuffer[0] = 0x01; *((uint32*) &outapp->pBuffer[4]) = (uint32)weather; entity_list.QueueClients(initiator, outapp); @@ -1253,7 +1254,7 @@ void QuestManager::setsky(uint8 new_sky) { QuestManagerCurrentQuestVars(); if (zone) zone->newzone_data.sky = new_sky; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); + auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(initiator, outapp); safe_delete(outapp); @@ -1401,23 +1402,23 @@ int QuestManager::InsertQuestGlobal(int charid, int npcid, int zoneid, const cha return 0; /* Delete existing qglobal data and update zone processes */ - ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); - ServerQGlobalDelete_Struct *qgd = (ServerQGlobalDelete_Struct*)pack->pBuffer; - qgd->npc_id = npcid; - qgd->char_id = charid; - qgd->zone_id = zoneid; - qgd->from_zone_id = zone->GetZoneID(); - qgd->from_instance_id = zone->GetInstanceID(); - strcpy(qgd->name, varname); + auto pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); + ServerQGlobalDelete_Struct *qgd = (ServerQGlobalDelete_Struct *)pack->pBuffer; + qgd->npc_id = npcid; + qgd->char_id = charid; + qgd->zone_id = zoneid; + qgd->from_zone_id = zone->GetZoneID(); + qgd->from_instance_id = zone->GetInstanceID(); + strcpy(qgd->name, varname); - entity_list.DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); - zone->DeleteQGlobal(std::string((char*)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); + entity_list.DeleteQGlobal(std::string((char *)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); + zone->DeleteQGlobal(std::string((char *)qgd->name), qgd->npc_id, qgd->char_id, qgd->zone_id); - worldserver.SendPacket(pack); - safe_delete(pack); + worldserver.SendPacket(pack); + safe_delete(pack); - /* Create new qglobal data and update zone processes */ - pack = new ServerPacket(ServerOP_QGlobalUpdate, sizeof(ServerQGlobalUpdate_Struct)); + /* Create new qglobal data and update zone processes */ + pack = new ServerPacket(ServerOP_QGlobalUpdate, sizeof(ServerQGlobalUpdate_Struct)); ServerQGlobalUpdate_Struct *qgu = (ServerQGlobalUpdate_Struct*)pack->pBuffer; qgu->npc_id = npcid; qgu->char_id = charid; @@ -1481,19 +1482,19 @@ void QuestManager::delglobal(const char *varname) { if(!zone) return; - ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); - ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct*)pack->pBuffer; + auto pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct)); + ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct *)pack->pBuffer; - qgu->npc_id = qgNpcid; - qgu->char_id = qgCharid; - qgu->zone_id = qgZoneid; - strcpy(qgu->name, varname); + qgu->npc_id = qgNpcid; + qgu->char_id = qgCharid; + qgu->zone_id = qgZoneid; + strcpy(qgu->name, varname); - entity_list.DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); - zone->DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); + entity_list.DeleteQGlobal(std::string((char *)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); + zone->DeleteQGlobal(std::string((char *)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id); - worldserver.SendPacket(pack); - safe_delete(pack); + worldserver.SendPacket(pack); + safe_delete(pack); } // Converts duration string to duration value (in seconds) @@ -2479,7 +2480,7 @@ void QuestManager::UpdateSpawnTimer(uint32 id, uint32 newTime) { //Spawn wasn't in this zone... //Tell the other zones to update their spawn time for this spawn point - ServerPacket *pack = new ServerPacket(ServerOP_UpdateSpawn, sizeof(UpdateSpawnTimer_Struct)); + auto pack = new ServerPacket(ServerOP_UpdateSpawn, sizeof(UpdateSpawnTimer_Struct)); UpdateSpawnTimer_Struct *ust = (UpdateSpawnTimer_Struct*)pack->pBuffer; ust->id = id; ust->duration = newTime; @@ -2731,7 +2732,7 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam int sayid = 0; int sz = strlen(Phrase); - char *escaped_string = new char[sz * 2]; + auto escaped_string = new char[sz * 2]; database.DoEscapeString(escaped_string, Phrase, sz); // Query for an existing phrase and id in the saylink table @@ -2895,7 +2896,7 @@ void QuestManager::voicetell(const char *str, int macronum, int racenum, int gen if(c) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_VoiceMacroOut, sizeof(VoiceMacroOut_Struct)); + auto outapp = new EQApplicationPacket(OP_VoiceMacroOut, sizeof(VoiceMacroOut_Struct)); VoiceMacroOut_Struct* vmo = (VoiceMacroOut_Struct*)outapp->pBuffer; @@ -2929,7 +2930,7 @@ void QuestManager::SendMail(const char *to, const char *from, const char *subjec } uint32 message_len = strlen(message) + 1; - ServerPacket* pack = new ServerPacket(ServerOP_UCSMailMessage, sizeof(ServerMailMessageHeader_Struct) + message_len); + auto pack = new ServerPacket(ServerOP_UCSMailMessage, sizeof(ServerMailMessageHeader_Struct) + message_len); ServerMailMessageHeader_Struct* mail = (ServerMailMessageHeader_Struct*) pack->pBuffer; strn0cpy(mail->to, to, 64); @@ -2962,7 +2963,7 @@ const char* QuestManager::GetZoneLongName(const char *zone) { } void QuestManager::CrossZoneSignalNPCByNPCTypeID(uint32 npctype_id, uint32 data){ - ServerPacket* pack = new ServerPacket(ServerOP_CZSignalNPC, sizeof(CZNPCSignal_Struct)); + auto pack = new ServerPacket(ServerOP_CZSignalNPC, sizeof(CZNPCSignal_Struct)); CZNPCSignal_Struct* CZSN = (CZNPCSignal_Struct*)pack->pBuffer; CZSN->npctype_id = npctype_id; CZSN->data = data; @@ -2971,7 +2972,7 @@ void QuestManager::CrossZoneSignalNPCByNPCTypeID(uint32 npctype_id, uint32 data) } void QuestManager::CrossZoneSignalPlayerByCharID(int charid, uint32 data){ - ServerPacket* pack = new ServerPacket(ServerOP_CZSignalClient, sizeof(CZClientSignal_Struct)); + auto pack = new ServerPacket(ServerOP_CZSignalClient, sizeof(CZClientSignal_Struct)); CZClientSignal_Struct* CZSC = (CZClientSignal_Struct*) pack->pBuffer; CZSC->charid = charid; CZSC->data = data; @@ -2981,7 +2982,7 @@ void QuestManager::CrossZoneSignalPlayerByCharID(int charid, uint32 data){ void QuestManager::CrossZoneSignalPlayerByName(const char *CharName, uint32 data){ uint32 message_len = strlen(CharName) + 1; - ServerPacket* pack = new ServerPacket(ServerOP_CZSignalClientByName, sizeof(CZClientSignalByName_Struct) + message_len); + auto pack = new ServerPacket(ServerOP_CZSignalClientByName, sizeof(CZClientSignalByName_Struct) + message_len); CZClientSignalByName_Struct* CZSC = (CZClientSignalByName_Struct*) pack->pBuffer; strn0cpy(CZSC->Name, CharName, 64); CZSC->data = data; @@ -2992,7 +2993,8 @@ void QuestManager::CrossZoneSignalPlayerByName(const char *CharName, uint32 data void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message){ uint32 message_len = strlen(CharName) + 1; uint32 message_len2 = strlen(Message) + 1; - ServerPacket* pack = new ServerPacket(ServerOP_CZMessagePlayer, sizeof(CZMessagePlayer_Struct) + message_len + message_len2); + auto pack = + new ServerPacket(ServerOP_CZMessagePlayer, sizeof(CZMessagePlayer_Struct) + message_len + message_len2); CZMessagePlayer_Struct* CZSC = (CZMessagePlayer_Struct*) pack->pBuffer; CZSC->Type = Type; strn0cpy(CZSC->CharName, CharName, 64); @@ -3004,7 +3006,8 @@ void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharNam void QuestManager::CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var){ uint32 message_len = strlen(id) + 1; uint32 message_len2 = strlen(m_var) + 1; - ServerPacket* pack = new ServerPacket(ServerOP_CZSetEntityVariableByNPCTypeID, sizeof(CZSetEntVarByNPCTypeID_Struct) + message_len + message_len2); + auto pack = new ServerPacket(ServerOP_CZSetEntityVariableByNPCTypeID, + sizeof(CZSetEntVarByNPCTypeID_Struct) + message_len + message_len2); CZSetEntVarByNPCTypeID_Struct* CZSNBYNID = (CZSetEntVarByNPCTypeID_Struct*)pack->pBuffer; CZSNBYNID->npctype_id = npctype_id; strn0cpy(CZSNBYNID->id, id, 256); @@ -3152,8 +3155,8 @@ void QuestManager::UpdateZoneHeader(std::string type, std::string value) { zone->newzone_data.fog_density = atof(value.c_str()); else if (strcasecmp(type.c_str(), "suspendbuffs") == 0) zone->newzone_data.SuspendBuffs = atoi(value.c_str()); - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); + + auto outapp = new EQApplicationPacket(OP_NewZone, sizeof(NewZone_Struct)); memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(0, outapp); safe_delete(outapp); diff --git a/zone/raids.cpp b/zone/raids.cpp index 45866884f..ff9e84578 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -121,7 +121,7 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo c->SetRaidGrouped(true); SendRaidMOTD(c); - ServerPacket *pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); strn0cpy(rga->playername, c->GetName(), 64); @@ -146,7 +146,7 @@ void Raid::RemoveMember(const char *characterName) if(client) client->SetRaidGrouped(false); - ServerPacket *pack = new ServerPacket(ServerOP_RaidRemove, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_RaidRemove, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); rga->instance_id = zone->GetInstanceID(); @@ -165,7 +165,7 @@ void Raid::DisbandRaid() VerifyRaid(); SendRaidDisbandAll(); - ServerPacket *pack = new ServerPacket(ServerOP_RaidDisband, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_RaidDisband, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); strn0cpy(rga->playername, " ", 64); @@ -187,7 +187,7 @@ void Raid::MoveMember(const char *name, uint32 newGroup) VerifyRaid(); SendRaidMoveAll(name); - ServerPacket *pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_RaidChangeGroup, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); strn0cpy(rga->playername, name, 64); @@ -206,7 +206,7 @@ void Raid::SetGroupLeader(const char *who, bool glFlag) LearnMembers(); VerifyRaid(); - ServerPacket *pack = new ServerPacket(ServerOP_RaidGroupLeader, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_RaidGroupLeader, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); strn0cpy(rga->playername, who, 64); @@ -250,7 +250,7 @@ void Raid::SetRaidLeader(const char *wasLead, const char *name) VerifyRaid(); SendMakeLeaderPacket(name); - ServerPacket *pack = new ServerPacket(ServerOP_RaidLeader, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_RaidLeader, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); strn0cpy(rga->playername, name, 64); @@ -262,7 +262,7 @@ void Raid::SetRaidLeader(const char *wasLead, const char *name) void Raid::SaveGroupLeaderAA(uint32 gid) { - char *queryBuffer = new char[sizeof(GroupLeadershipAA_Struct) * 2 + 1]; + auto 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 = '"; @@ -276,7 +276,7 @@ void Raid::SaveGroupLeaderAA(uint32 gid) void Raid::SaveRaidLeaderAA() { - char *queryBuffer = new char[sizeof(RaidLeadershipAA_Struct) * 2 + 1]; + auto queryBuffer = new char[sizeof(RaidLeadershipAA_Struct) * 2 + 1]; database.DoEscapeString(queryBuffer, (char*)&raid_aa, sizeof(RaidLeadershipAA_Struct)); std::string query = "UPDATE raid_leaders SET leadershipaa = '"; @@ -414,7 +414,7 @@ void Raid::RaidSay(const char *msg, Client *c) if(!c) return; - ServerPacket *pack = new ServerPacket(ServerOP_RaidSay, sizeof(ServerRaidMessage_Struct) + strlen(msg) + 1); + auto pack = new ServerPacket(ServerOP_RaidSay, sizeof(ServerRaidMessage_Struct) + strlen(msg) + 1); ServerRaidMessage_Struct *rga = (ServerRaidMessage_Struct*)pack->pBuffer; rga->rid = GetID(); rga->gid = 0xFFFFFFFF; @@ -436,7 +436,7 @@ void Raid::RaidGroupSay(const char *msg, Client *c) if(groupToUse > 11) return; - ServerPacket *pack = new ServerPacket(ServerOP_RaidGroupSay, sizeof(ServerRaidMessage_Struct) + strlen(msg) + 1); + auto pack = new ServerPacket(ServerOP_RaidGroupSay, sizeof(ServerRaidMessage_Struct) + strlen(msg) + 1); ServerRaidMessage_Struct *rga = (ServerRaidMessage_Struct*)pack->pBuffer; rga->rid = GetID(); rga->gid = groupToUse; @@ -852,7 +852,7 @@ void Raid::AddRaidLooter(const char* looter) break; } } - ServerPacket *pack = new ServerPacket(ServerOP_DetailsChange, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_DetailsChange, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); rga->zoneid = zone->GetZoneID(); @@ -872,7 +872,7 @@ void Raid::RemoveRaidLooter(const char* looter) break; } - ServerPacket *pack = new ServerPacket(ServerOP_DetailsChange, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_DetailsChange, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); rga->zoneid = zone->GetZoneID(); @@ -925,7 +925,7 @@ void Raid::SendRaidCreate(Client *to){ if(!to) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidJoin,sizeof(RaidCreate_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidJoin, sizeof(RaidCreate_Struct)); RaidCreate_Struct *rc = (RaidCreate_Struct*)outapp->pBuffer; rc->action = raidCreate; strn0cpy(rc->leader_name, leadername, 64); @@ -943,7 +943,7 @@ void Raid::SendRaidAdd(const char *who, Client *to) { if(strcmp(members[x].membername, who) == 0) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidAddMember_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidAddMember_Struct)); RaidAddMember_Struct *ram = (RaidAddMember_Struct*)outapp->pBuffer; ram->raidGen.action = raidAdd; ram->raidGen.parameter = members[x].GroupNumber; @@ -965,7 +965,7 @@ void Raid::SendRaidAddAll(const char *who) { if(strcmp(members[x].membername, who) == 0) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidAddMember_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidAddMember_Struct)); RaidAddMember_Struct *ram = (RaidAddMember_Struct*)outapp->pBuffer; ram->raidGen.action = raidAdd; ram->raidGen.parameter = members[x].GroupNumber; @@ -990,7 +990,7 @@ void Raid::SendRaidRemove(const char *who, Client *to) { if(strcmp(members[x].membername, who) == 0) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer; rg->action = raidRemove2; strn0cpy(rg->leader_name, who, 64); @@ -1009,7 +1009,7 @@ void Raid::SendRaidRemoveAll(const char *who) { if(strcmp(members[x].membername, who) == 0) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer; rg->action = raidRemove2; strn0cpy(rg->leader_name, who, 64); @@ -1027,7 +1027,7 @@ void Raid::SendRaidDisband(Client *to) if(!to) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer; rg->action = raidDisband; strn0cpy(rg->leader_name, to->GetName(), 64); @@ -1039,7 +1039,7 @@ void Raid::SendRaidDisband(Client *to) void Raid::SendRaidDisbandAll() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer; rg->action = raidDisband; strn0cpy(rg->leader_name, "RaidMember", 64); @@ -1110,7 +1110,7 @@ void Raid::QueuePacket(const EQApplicationPacket *app, bool ack_req) void Raid::SendMakeLeaderPacket(const char *who) //30 { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct)); RaidLeadershipUpdate_Struct *rg = (RaidLeadershipUpdate_Struct*)outapp->pBuffer; rg->action = raidMakeLeader; strn0cpy(rg->leader_name, who, 64); @@ -1125,7 +1125,7 @@ void Raid::SendMakeLeaderPacketTo(const char *who, Client *to) if(!to) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct)); RaidLeadershipUpdate_Struct *rg = (RaidLeadershipUpdate_Struct*)outapp->pBuffer; rg->action = raidMakeLeader; strn0cpy(rg->leader_name, who, 64); @@ -1155,7 +1155,7 @@ void Raid::SendGroupUpdate(Client *to) if(!to) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupUpdate2_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate2_Struct)); GroupUpdate2_Struct* gu = (GroupUpdate2_Struct*)outapp->pBuffer; gu->action = groupActUpdate; int index = 0; @@ -1209,7 +1209,7 @@ void Raid::GroupUpdate(uint32 gid, bool initial) } } if(initial){ - ServerPacket *pack = new ServerPacket(ServerOP_UpdateGroup, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_UpdateGroup, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct* rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->gid = gid; rga->rid = GetID(); @@ -1222,7 +1222,7 @@ void Raid::GroupUpdate(uint32 gid, bool initial) void Raid::SendRaidLock() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer; rg->action = raidLock; strn0cpy(rg->leader_name, leadername, 64); @@ -1233,7 +1233,7 @@ void Raid::SendRaidLock() void Raid::SendRaidUnlock() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer; rg->action = raidUnlock; strn0cpy(rg->leader_name, leadername, 64); @@ -1247,7 +1247,7 @@ void Raid::SendRaidLockTo(Client *c) if(!c) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer; rg->action = raidLock; strn0cpy(rg->leader_name, c->GetName(), 64); @@ -1261,7 +1261,7 @@ void Raid::SendRaidUnlockTo(Client *c) if(!c) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct)); RaidGeneral_Struct *rg = (RaidGeneral_Struct*)outapp->pBuffer; rg->action = raidUnlock; strn0cpy(rg->leader_name, c->GetName(), 64); @@ -1275,7 +1275,7 @@ void Raid::SendGroupDisband(Client *to) if(!to) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate_Struct)); GroupUpdate_Struct* gu = (GroupUpdate_Struct*) outapp->pBuffer; gu->action = groupActDisband; strn0cpy(gu->leadersname, leadername, 64); @@ -1285,7 +1285,7 @@ void Raid::SendGroupDisband(Client *to) void Raid::SendRaidGroupAdd(const char *who, uint32 gid) { - ServerPacket *pack = new ServerPacket(ServerOP_RaidGroupAdd, sizeof(ServerRaidGroupAction_Struct)); + auto pack = new ServerPacket(ServerOP_RaidGroupAdd, sizeof(ServerRaidGroupAction_Struct)); ServerRaidGroupAction_Struct * rga = (ServerRaidGroupAction_Struct*)pack->pBuffer; rga->rid = GetID(); rga->gid = gid; @@ -1295,7 +1295,7 @@ void Raid::SendRaidGroupAdd(const char *who, uint32 gid) void Raid::SendRaidGroupRemove(const char *who, uint32 gid) { - ServerPacket *pack = new ServerPacket(ServerOP_RaidGroupRemove, sizeof(ServerRaidGroupAction_Struct)); + auto pack = new ServerPacket(ServerOP_RaidGroupRemove, sizeof(ServerRaidGroupAction_Struct)); ServerRaidGroupAction_Struct * rga = (ServerRaidGroupAction_Struct*)pack->pBuffer; rga->rid = GetID(); rga->gid = gid; @@ -1309,7 +1309,7 @@ void Raid::SendRaidMOTD(Client *c) return; size_t size = motd.size() + 1; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidMOTD_Struct) + size); + auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidMOTD_Struct) + size); RaidMOTD_Struct *rmotd = (RaidMOTD_Struct *)outapp->pBuffer; rmotd->general.action = raidSetMotd; strn0cpy(rmotd->general.player_name, c->GetName(), 64); @@ -1333,7 +1333,7 @@ void Raid::SendRaidMOTDToWorld() return; size_t size = motd.size() + 1; - ServerPacket *pack = new ServerPacket(ServerOP_RaidMOTD, sizeof(ServerRaidMOTD_Struct) + size); + auto pack = new ServerPacket(ServerOP_RaidMOTD, sizeof(ServerRaidMOTD_Struct) + size); ServerRaidMOTD_Struct *smotd = (ServerRaidMOTD_Struct *)pack->pBuffer; smotd->rid = GetID(); strn0cpy(smotd->motd, motd.c_str(), size); @@ -1343,7 +1343,7 @@ void Raid::SendRaidMOTDToWorld() void Raid::SendGroupLeadershipAA(Client *c, uint32 gid) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidLeadershipUpdate_Struct)); + auto 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); @@ -1381,7 +1381,7 @@ void Raid::LockRaid(bool lockFlag) else SendRaidUnlock(); - ServerPacket *pack = new ServerPacket(ServerOP_RaidLockFlag, sizeof(ServerRaidGeneralAction_Struct)); + auto pack = new ServerPacket(ServerOP_RaidLockFlag, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); rga->zoneid = zone->GetZoneID(); diff --git a/zone/raycast_mesh.cpp b/zone/raycast_mesh.cpp index 078f225a1..e2e88b100 100644 --- a/zone/raycast_mesh.cpp +++ b/zone/raycast_mesh.cpp @@ -518,8 +518,7 @@ public: // Copy the triangle indices into the leaf triangles array mLeafTriangleIndex = leafTriangles.size(); // assign the array start location for these leaf triangles. leafTriangles.push_back(count); - for (TriVector::const_iterator i=triangles.begin(); i!=triangles.end(); ++i) - { + for (auto i = triangles.begin(); i != triangles.end(); ++i) { RmUint32 tri = *i; leafTriangles.push_back(tri); } @@ -541,8 +540,7 @@ public: // Create two arrays; one of all triangles which intersect the 'left' half of the bounding volume node // and another array that includes all triangles which intersect the 'right' half of the bounding volume node. - for (TriVector::const_iterator i=triangles.begin(); i!=triangles.end(); ++i) - { + for (auto i = triangles.begin(); i != triangles.end(); ++i) { RmUint32 tri = (*i); @@ -934,7 +932,7 @@ RaycastMesh * createRaycastMesh(RmUint32 vcount, // The number of vertices in t RmReal minAxisSize // once a particular axis is less than this size, stop sub-dividing. ) { - MyRaycastMesh *m = new MyRaycastMesh(vcount,vertices,tcount,indices,maxDepth,minLeafSize,minAxisSize); + auto m = new MyRaycastMesh(vcount, vertices, tcount, indices, maxDepth, minLeafSize, minAxisSize); return static_cast< RaycastMesh * >(m); } diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index 7cb3b1f3c..ad5f3d89a 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -574,9 +574,9 @@ Spawn2* ZoneDatabase::LoadSpawn2(LinkedList &spawn2_list, uint32 spawn2 bool perl_enabled = atoi(row[11]) == 1 ? true : false; - Spawn2* newSpawn = new Spawn2(atoi(row[0]), atoi(row[1]), atof(row[2]), atof(row[3]), atof(row[4]), - atof(row[5]), atoi(row[6]), atoi(row[7]), timeleft, atoi(row[8]), - atoi(row[9]), atoi(row[10]), perl_enabled, (EmuAppearance)atoi(row[12])); + auto newSpawn = new Spawn2(atoi(row[0]), atoi(row[1]), atof(row[2]), atof(row[3]), atof(row[4]), atof(row[5]), + atoi(row[6]), atoi(row[7]), timeleft, atoi(row[8]), atoi(row[9]), atoi(row[10]), + perl_enabled, (EmuAppearance)atoi(row[12])); spawn2_list.Insert(newSpawn); @@ -1128,7 +1128,7 @@ void SpawnConditionManager::SetCondition(const char *zone_short, uint32 instance UpdateDBCondition(zone_short, instance_id, condition_id, new_value); - ServerPacket* pack = new ServerPacket(ServerOP_SpawnCondition, sizeof(ServerSpawnCondition_Struct)); + auto pack = new ServerPacket(ServerOP_SpawnCondition, sizeof(ServerSpawnCondition_Struct)); ServerSpawnCondition_Struct* ssc = (ServerSpawnCondition_Struct*)pack->pBuffer; ssc->zoneID = database.GetZoneID(zone_short); @@ -1260,7 +1260,7 @@ void SpawnConditionManager::ToggleEvent(uint32 event_id, bool enabled, bool stri //now notify the zone - ServerPacket* pack = new ServerPacket(ServerOP_SpawnEvent, sizeof(ServerSpawnEvent_Struct)); + auto pack = new ServerPacket(ServerOP_SpawnEvent, sizeof(ServerSpawnEvent_Struct)); ServerSpawnEvent_Struct* sse = (ServerSpawnEvent_Struct*)pack->pBuffer; sse->zoneID = database.GetZoneID(zone_short_name.c_str()); diff --git a/zone/spawngroup.cpp b/zone/spawngroup.cpp index a810cc9f8..94b2ed285 100644 --- a/zone/spawngroup.cpp +++ b/zone/spawngroup.cpp @@ -154,9 +154,9 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG } for (auto row = results.begin(); row != results.end(); ++row) { - SpawnGroup *newSpawnGroup = new SpawnGroup(atoi(row[0]), row[1], atoi(row[2]), atof(row[3]), - atof(row[4]), atof(row[5]), atof(row[6]), atof(row[7]), - atoi(row[8]), atoi(row[9]), atoi(row[10]), atoi(row[11])); + auto newSpawnGroup = new SpawnGroup(atoi(row[0]), row[1], atoi(row[2]), atof(row[3]), atof(row[4]), + atof(row[5]), atof(row[6]), atof(row[7]), atoi(row[8]), + atoi(row[9]), atoi(row[10]), atoi(row[11])); spawn_group_list->AddSpawnGroup(newSpawnGroup); } @@ -174,7 +174,7 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG } for (auto row = results.begin(); row != results.end(); ++row) { - SpawnEntry *newSpawnEntry = new SpawnEntry(atoi(row[1]), atoi(row[2]), row[3] ? atoi(row[3]) : 0); + auto newSpawnEntry = new SpawnEntry(atoi(row[1]), atoi(row[2]), row[3] ? atoi(row[3]) : 0); SpawnGroup *sg = spawn_group_list->GetSpawnGroup(atoi(row[0])); if (!sg) { @@ -203,9 +203,9 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList *spawn_g } for (auto row = results.begin(); row != results.end(); ++row) { - SpawnGroup *newSpawnGroup = new SpawnGroup(atoi(row[0]), row[1], atoi(row[2]), atof(row[3]), - atof(row[4]), atof(row[5]), atof(row[6]), atof(row[7]), - atoi(row[8]), atoi(row[9]), atoi(row[10]), atoi(row[11])); + auto newSpawnGroup = new SpawnGroup(atoi(row[0]), row[1], atoi(row[2]), atof(row[3]), atof(row[4]), + atof(row[5]), atof(row[6]), atof(row[7]), atoi(row[8]), + atoi(row[9]), atoi(row[10]), atoi(row[11])); spawn_group_list->AddSpawnGroup(newSpawnGroup); } @@ -221,7 +221,7 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList *spawn_g } for (auto row = results.begin(); row != results.end(); ++row) { - SpawnEntry *newSpawnEntry = new SpawnEntry(atoi(row[1]), atoi(row[2]), row[3] ? atoi(row[3]) : 0); + auto newSpawnEntry = new SpawnEntry(atoi(row[1]), atoi(row[2]), row[3] ? atoi(row[3]) : 0); SpawnGroup *sg = spawn_group_list->GetSpawnGroup(atoi(row[0])); if (!sg) { safe_delete(newSpawnEntry); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index c54737475..674c15d03 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1581,7 +1581,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQE } void Mob::SendItemAnimation(Mob *to, const EQEmu::Item_Struct *item, SkillUseTypes skillInUse, float velocity) { - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SomeItemPacketMaybe, sizeof(Arrow_Struct)); + auto outapp = new EQApplicationPacket(OP_SomeItemPacketMaybe, sizeof(Arrow_Struct)); Arrow_Struct *as = (Arrow_Struct *) outapp->pBuffer; as->type = 1; as->src_x = GetX(); @@ -1671,7 +1671,7 @@ void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, f item_IDFile = IDFile; // See SendItemAnimation() for some notes on this struct - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SomeItemPacketMaybe, sizeof(Arrow_Struct)); + auto outapp = new EQApplicationPacket(OP_SomeItemPacketMaybe, sizeof(Arrow_Struct)); Arrow_Struct *as = (Arrow_Struct *) outapp->pBuffer; as->type = 1; as->src_x = GetX(); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 79dda2125..35d1c64bd 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -765,7 +765,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove SetPetType(petCharmed); if(caster->IsClient()){ - EQApplicationPacket *app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); + auto app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); Charm_Struct *ps = (Charm_Struct*)app->pBuffer; ps->owner_id = caster->GetID(); ps->pet_id = this->GetID(); @@ -892,9 +892,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove { if(CastToClient()->GetGM() || RuleB(Character, BindAnywhere)) { - EQApplicationPacket *action_packet = new EQApplicationPacket(OP_Action, sizeof(Action_Struct)); + auto action_packet = + new EQApplicationPacket(OP_Action, sizeof(Action_Struct)); Action_Struct* action = (Action_Struct*) action_packet->pBuffer; - EQApplicationPacket *message_packet = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); + auto message_packet = + new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct *cd = (CombatDamage_Struct *)message_packet->pBuffer; action->target = GetID(); @@ -941,9 +943,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } else { - EQApplicationPacket *action_packet = new EQApplicationPacket(OP_Action, sizeof(Action_Struct)); + auto action_packet = new EQApplicationPacket( + OP_Action, sizeof(Action_Struct)); Action_Struct* action = (Action_Struct*) action_packet->pBuffer; - EQApplicationPacket *message_packet = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); + auto message_packet = new EQApplicationPacket( + OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct *cd = (CombatDamage_Struct *)message_packet->pBuffer; action->target = GetID(); @@ -977,9 +981,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } else { - EQApplicationPacket *action_packet = new EQApplicationPacket(OP_Action, sizeof(Action_Struct)); + auto action_packet = + new EQApplicationPacket(OP_Action, sizeof(Action_Struct)); Action_Struct* action = (Action_Struct*) action_packet->pBuffer; - EQApplicationPacket *message_packet = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); + auto message_packet = new EQApplicationPacket( + OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct *cd = (CombatDamage_Struct *)message_packet->pBuffer; action->target = GetID(); @@ -2064,7 +2070,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove double new_x = spells[spell_id].pushback * sin(double(look_heading * 3.141592 / 180.0)); double new_y = spells[spell_id].pushback * cos(double(look_heading * 3.141592 / 180.0)); - EQApplicationPacket* outapp_push = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto outapp_push = + new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp_push->pBuffer; spu->spawn_id = GetID(); @@ -3922,7 +3929,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) } if(tempmob && tempmob->IsClient()) { - EQApplicationPacket *app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); + auto app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); Charm_Struct *ps = (Charm_Struct*)app->pBuffer; ps->owner_id = tempmob->GetID(); ps->pet_id = this->GetID(); @@ -6782,7 +6789,7 @@ void Client::BreakSneakWhenCastOn(Mob* caster, bool IsResisted) //TODO: The skill buttons should reset when this occurs. Not sure how to force that yet. - Kayen hidden = false; improved_hidden = false; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; sa_out->spawn_id = GetID(); sa_out->type = 0x03; diff --git a/zone/spells.cpp b/zone/spells.cpp index dbf89a5cc..f4eb422cb 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1986,7 +1986,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 if(IsAEDurationSpell(spell_id)) { // the spells are AE target, but we aim them on a beacon Mob *beacon_loc = spell_target ? spell_target : this; - Beacon *beacon = new Beacon(beacon_loc, spells[spell_id].AEDuration); + auto beacon = new Beacon(beacon_loc, spells[spell_id].AEDuration); entity_list.AddBeacon(beacon); Log.Out(Logs::Detail, Logs::Spells, "Spell %d: AE duration beacon created, entity id %d", spell_id, beacon->GetName()); spell_target = nullptr; @@ -2335,7 +2335,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 database.UpdateItemRecastTimestamps( CastToClient()->CharacterID(), recast_type, CastToClient()->GetPTimers().Get(pTimerItemStart + recast_type)->GetReadyTimestamp()); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct)); + auto outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct)); ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer; ird->recast_delay = itm->GetItem()->RecastDelay; ird->recast_type = recast_type; @@ -2530,7 +2530,7 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) { //be a lot of traffic for no reason... //this may be the wrong packet... if(IsClient()) { - EQApplicationPacket *packet = new EQApplicationPacket(OP_Action, sizeof(Action_Struct)); + auto packet = new EQApplicationPacket(OP_Action, sizeof(Action_Struct)); Action_Struct* action = (Action_Struct*) packet->pBuffer; action->source = caster->GetID(); @@ -2558,7 +2558,8 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) { CastToClient()->SetKnockBackExemption(true); action->buff_unknown = 0; - EQApplicationPacket* outapp_push = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto outapp_push = new EQApplicationPacket( + OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp_push->pBuffer; double look_heading = caster->CalculateHeadingToTarget(GetX(), GetY()); @@ -2602,7 +2603,7 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) { CastToClient()->QueuePacket(packet); } - EQApplicationPacket *message_packet = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); + auto message_packet = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct *cd = (CombatDamage_Struct *)message_packet->pBuffer; cd->target = action->target; cd->source = action->source; @@ -3833,7 +3834,8 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r spelltar->CastToClient()->SetKnockBackExemption(true); action->buff_unknown = 0; - EQApplicationPacket* outapp_push = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto outapp_push = + new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp_push->pBuffer; double look_heading = CalculateHeadingToTarget(spelltar->GetX(), spelltar->GetY()); @@ -3923,7 +3925,7 @@ void Corpse::CastRezz(uint16 spellid, Mob* Caster) } */ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RezzRequest, sizeof(Resurrect_Struct)); + auto outapp = new EQApplicationPacket(OP_RezzRequest, sizeof(Resurrect_Struct)); Resurrect_Struct* rezz = (Resurrect_Struct*) outapp->pBuffer; // Why are we truncating these names to 30 characters ? memcpy(rezz->your_name,this->corpse_name,30); @@ -4695,7 +4697,7 @@ float Mob::GetAOERange(uint16 spell_id) { void Mob::Spin() { if(IsClient()) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Action, sizeof(Action_Struct)); + auto outapp = new EQApplicationPacket(OP_Action, sizeof(Action_Struct)); outapp->pBuffer[0] = 0x0B; outapp->pBuffer[1] = 0x0A; outapp->pBuffer[2] = 0x0B; @@ -4742,7 +4744,7 @@ void Mob::SendSpellBarEnable(uint16 spell_id) if(!IsClient()) return; - EQApplicationPacket *outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct)); + auto outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct)); ManaChange_Struct* manachange = (ManaChange_Struct*)outapp->pBuffer; manachange->new_mana = GetMana(); manachange->spell_id = spell_id; @@ -4786,7 +4788,7 @@ void Client::Stun(int duration) { Mob::Stun(duration); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Stun, sizeof(Stun_Struct)); + auto outapp = new EQApplicationPacket(OP_Stun, sizeof(Stun_Struct)); Stun_Struct* stunon = (Stun_Struct*) outapp->pBuffer; stunon->duration = duration; outapp->priority = 5; @@ -4797,7 +4799,7 @@ void Client::Stun(int duration) void Client::UnStun() { Mob::UnStun(); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Stun, sizeof(Stun_Struct)); + auto outapp = new EQApplicationPacket(OP_Stun, sizeof(Stun_Struct)); Stun_Struct* stunon = (Stun_Struct*) outapp->pBuffer; stunon->duration = 0; outapp->priority = 5; @@ -4973,7 +4975,7 @@ void Client::UnscribeSpell(int slot, bool update_client) database.DeleteCharacterSpell(this->CharacterID(), m_pp.spell_book[slot], slot); if(update_client) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_DeleteSpell, sizeof(DeleteSpell_Struct)); + auto outapp = new EQApplicationPacket(OP_DeleteSpell, sizeof(DeleteSpell_Struct)); DeleteSpell_Struct* del = (DeleteSpell_Struct*)outapp->pBuffer; del->spell_slot = slot; del->success = 1; @@ -5428,7 +5430,7 @@ void Mob::SendPetBuffsToClient() int PetBuffCount = 0; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_PetBuffWindow,sizeof(PetBuff_Struct)); + auto outapp = new EQApplicationPacket(OP_PetBuffWindow, sizeof(PetBuff_Struct)); PetBuff_Struct* pbs=(PetBuff_Struct*)outapp->pBuffer; memset(outapp->pBuffer,0,outapp->size); pbs->petid=GetID(); diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 8946673a4..fb5c867c9 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -850,7 +850,7 @@ int TaskManager::FirstTaskInSet(int TaskSetID) { if(TaskSets[TaskSetID].empty()) return 0; - std::vector::iterator Iterator = TaskSets[TaskSetID].begin(); + auto Iterator = TaskSets[TaskSetID].begin(); while(Iterator != TaskSets[TaskSetID].end()) { if((*Iterator) > 0) @@ -934,7 +934,7 @@ void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, i if(TaskSets[TaskSetID][0] == 0) { Log.Out(Logs::General, Logs::Tasks, "[UPDATE] TaskSets[%i][0] == 0. All Tasks in Set enabled.", TaskSetID); - std::vector::iterator Iterator = TaskSets[TaskSetID].begin(); + auto Iterator = TaskSets[TaskSetID].begin(); while((Iterator != TaskSets[TaskSetID].end()) && (TaskListIndex < MAXCHOOSERENTRIES)) { if(AppropriateLevel((*Iterator), PlayerLevel) && !state->IsTaskActive((*Iterator)) && @@ -1039,7 +1039,7 @@ void TaskManager::SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *Task if(ValidTasks == 0) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_OpenNewTasksWindow, PacketLength); + auto outapp = new EQApplicationPacket(OP_OpenNewTasksWindow, PacketLength); AvailableTaskHeader = (AvailableTaskHeader_Struct*)outapp->pBuffer; @@ -1164,7 +1164,7 @@ void TaskManager::SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *T if(ValidTasks == 0) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_OpenNewTasksWindow, PacketLength); + auto outapp = new EQApplicationPacket(OP_OpenNewTasksWindow, PacketLength); outapp->WriteUInt32(ValidTasks); // TaskCount outapp->WriteUInt32(2); // Unknown2 @@ -1333,7 +1333,7 @@ bool ClientTaskState::UnlockActivities(int CharID, int TaskIndex) { if(AllActivitiesComplete && RuleB(TaskSystem, RecordCompletedTasks)) { if(RuleB(TasksSystem, KeepOneRecordPerCompletedTask)) { Log.Out(Logs::General, Logs::Tasks, "[UPDATE] KeepOneRecord enabled"); - std::vector::iterator Iterator = CompletedTasks.begin(); + auto Iterator = CompletedTasks.begin(); int ErasedElements = 0; while(Iterator != CompletedTasks.end()) { int TaskID = (*Iterator).TaskID; @@ -1406,7 +1406,7 @@ bool ClientTaskState::UnlockActivities(int CharID, int TaskIndex) { // the same task again, erase the previous completed entry for this task. if(RuleB(TasksSystem, KeepOneRecordPerCompletedTask)) { Log.Out(Logs::General, Logs::Tasks, "[UPDATE] KeepOneRecord enabled"); - std::vector::iterator Iterator = CompletedTasks.begin(); + auto Iterator = CompletedTasks.begin(); int ErasedElements = 0; while(Iterator != CompletedTasks.end()) { int TaskID = (*Iterator).TaskID; @@ -2325,9 +2325,7 @@ void ClientTaskState::SendTaskHistory(Client *c, int TaskIndex) { } } - - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TaskHistoryReply, PacketLength); + auto outapp = new EQApplicationPacket(OP_TaskHistoryReply, PacketLength); ths = (TaskHistoryReplyHeader_Struct*)outapp->pBuffer; @@ -2370,7 +2368,7 @@ void Client::SendTaskActivityComplete(int TaskID, int ActivityID, int TaskIndex, TaskActivityComplete_Struct* tac; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TaskActivityComplete, sizeof(TaskActivityComplete_Struct)); + auto outapp = new EQApplicationPacket(OP_TaskActivityComplete, sizeof(TaskActivityComplete_Struct)); tac = (TaskActivityComplete_Struct*)outapp->pBuffer; @@ -2400,7 +2398,7 @@ void Client::SendTaskFailed(int TaskID, int TaskIndex) { TaskActivityComplete_Struct* tac; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TaskActivityComplete, sizeof(TaskActivityComplete_Struct)); + auto outapp = new EQApplicationPacket(OP_TaskActivityComplete, sizeof(TaskActivityComplete_Struct)); tac = (TaskActivityComplete_Struct*)outapp->pBuffer; @@ -2450,7 +2448,7 @@ void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *State) PacketLength = PacketLength + 8 + strlen(Tasks[TaskID]->Title) + 1; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CompletedTasks, PacketLength); + auto outapp = new EQApplicationPacket(OP_CompletedTasks, PacketLength); char *buf = (char*)outapp->pBuffer; //*(uint32 *)buf = State->CompletedTasks.size(); @@ -2487,7 +2485,7 @@ void TaskManager::SendTaskActivityShort(Client *c, int TaskID, int ActivityID, i if (c->ClientVersionBit() & EQEmu::versions::bit_RoFAndLater) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TaskActivity, 25); + auto outapp = new EQApplicationPacket(OP_TaskActivity, 25); outapp->WriteUInt32(ClientTaskIndex); outapp->WriteUInt32(2); outapp->WriteUInt32(TaskID); @@ -2500,7 +2498,7 @@ void TaskManager::SendTaskActivityShort(Client *c, int TaskID, int ActivityID, i return; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TaskActivity, sizeof(TaskActivityShort_Struct)); + auto outapp = new EQApplicationPacket(OP_TaskActivity, sizeof(TaskActivityShort_Struct)); tass = (TaskActivityShort_Struct*)outapp->pBuffer; @@ -2538,7 +2536,7 @@ void TaskManager::SendTaskActivityLong(Client *c, int TaskID, int ActivityID, in strlen(Tasks[TaskID]->Activity[ActivityID].Text2) + 1 + strlen(Tasks[TaskID]->Activity[ActivityID].Text3) + 1; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TaskActivity, PacketLength); + auto outapp = new EQApplicationPacket(OP_TaskActivity, PacketLength); tah = (TaskActivityHeader_Struct*)outapp->pBuffer; @@ -2619,7 +2617,7 @@ void TaskManager::SendTaskActivityNew(Client *c, int TaskID, int ActivityID, int ((strlen(itoa(Tasks[TaskID]->Activity[ActivityID].ZoneID)) + 1) * 2) + 3 + String2Len; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TaskActivity, PacketLength); + auto outapp = new EQApplicationPacket(OP_TaskActivity, PacketLength); outapp->WriteUInt32(ClientTaskIndex); // TaskSequenceNumber outapp->WriteUInt32(2); // unknown2 @@ -2805,7 +2803,7 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN TaskDescriptionData2_Struct* tdd2; TaskDescriptionTrailer_Struct* tdt; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TaskDescription, PacketLength); + auto outapp = new EQApplicationPacket(OP_TaskDescription, PacketLength); tdh = (TaskDescriptionHeader_Struct*)outapp->pBuffer; @@ -2924,7 +2922,7 @@ void ClientTaskState::CancelAllTasks(Client *c) { } void ClientTaskState::CancelTask(Client *c, int SequenceNumber, bool RemoveFromDB) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CancelTask, sizeof(CancelTask_Struct)); + auto outapp = new EQApplicationPacket(OP_CancelTask, sizeof(CancelTask_Struct)); CancelTask_Struct* cts = (CancelTask_Struct*)outapp->pBuffer; cts->SequenceNumber = SequenceNumber; diff --git a/zone/titles.cpp b/zone/titles.cpp index 8e6115aee..1e0cc7cb7 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -91,7 +91,7 @@ EQApplicationPacket *TitleManager::MakeTitlesPacket(Client *c) } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendTitleList, Length); + auto outapp = new EQApplicationPacket(OP_SendTitleList, Length); char *Buffer = (char *)outapp->pBuffer; @@ -243,7 +243,7 @@ void TitleManager::CreateNewPlayerTitle(Client *client, const char *title) if(!client || !title) return; - char *escTitle = new char[strlen(title) * 2 + 1]; + auto escTitle = new char[strlen(title) * 2 + 1]; client->SetAATitle(title); @@ -265,7 +265,7 @@ void TitleManager::CreateNewPlayerTitle(Client *client, const char *title) return; } - ServerPacket* pack = new ServerPacket(ServerOP_ReloadTitles, 0); + auto pack = new ServerPacket(ServerOP_ReloadTitles, 0); worldserver.SendPacket(pack); safe_delete(pack); } @@ -277,8 +277,8 @@ void TitleManager::CreateNewPlayerSuffix(Client *client, const char *suffix) client->SetTitleSuffix(suffix); - char *escSuffix = new char[strlen(suffix) * 2 + 1]; - database.DoEscapeString(escSuffix, suffix, strlen(suffix)); + auto escSuffix = new char[strlen(suffix) * 2 + 1]; + database.DoEscapeString(escSuffix, suffix, strlen(suffix)); std::string query = StringFormat("SELECT `id` FROM titles " "WHERE `suffix` = '%s' AND char_id = %i", @@ -297,7 +297,7 @@ void TitleManager::CreateNewPlayerSuffix(Client *client, const char *suffix) return; } - ServerPacket* pack = new ServerPacket(ServerOP_ReloadTitles, 0); + auto pack = new ServerPacket(ServerOP_ReloadTitles, 0); worldserver.SendPacket(pack); safe_delete(pack); } @@ -306,7 +306,7 @@ void Client::SetAATitle(const char *Title) { strn0cpy(m_pp.title, Title, sizeof(m_pp.title)); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct)); + auto outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct)); SetTitleReply_Struct *strs = (SetTitleReply_Struct *)outapp->pBuffer; @@ -323,7 +323,7 @@ void Client::SetTitleSuffix(const char *Suffix) { strn0cpy(m_pp.suffix, Suffix, sizeof(m_pp.suffix)); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct)); + auto outapp = new EQApplicationPacket(OP_SetTitleReply, sizeof(SetTitleReply_Struct)); SetTitleReply_Struct *strs = (SetTitleReply_Struct *)outapp->pBuffer; diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index a5e931e62..2a3a3cdfe 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -212,7 +212,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme if (worldo) { container->Clear(); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClearObject, sizeof(ClearObject_Struct)); + auto outapp = new EQApplicationPacket(OP_ClearObject, sizeof(ClearObject_Struct)); ClearObject_Struct *cos = (ClearObject_Struct *)outapp->pBuffer; cos->Clear = 1; user->QueuePacket(outapp); @@ -305,7 +305,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob else if (inst) { user->Message_StringID(4, TRANSFORM_FAILED, inst->GetItem()->Name); } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); safe_delete(outapp); return; @@ -323,7 +323,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob else if (inst) { user->Message_StringID(4, DETRANSFORM_FAILED, inst->GetItem()->Name); } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); safe_delete(outapp); return; @@ -332,7 +332,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob DBTradeskillRecipe_Struct spec; if (!database.GetTradeRecipe(container, c_type, some_id, user->CharacterID(), &spec)) { user->Message_StringID(MT_Emote,TRADESKILL_NOCOMBINE); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); safe_delete(outapp); return; @@ -347,7 +347,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob if ((spec.must_learn&0xF) == 1 && !spec.has_learnt) { // Made up message for the client. Just giving a DNC is the other option. user->Message(4, "You need to learn how to combine these first."); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); safe_delete(outapp); return; @@ -356,7 +356,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob if(spec.skill_needed > 0 && user->GetSkill(spec.tradeskill) < spec.skill_needed ) { // Notify client. user->Message(4, "You are not skilled enough."); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); safe_delete(outapp); return; @@ -387,7 +387,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob } // Send acknowledgement packets to client - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); + auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); safe_delete(outapp); @@ -441,7 +441,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac) { //get our packet ready, gotta send one no matter what... - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RecipeAutoCombine, sizeof(RecipeAutoCombine_Struct)); + auto outapp = new EQApplicationPacket(OP_RecipeAutoCombine, sizeof(RecipeAutoCombine_Struct)); RecipeAutoCombine_Struct *outp = (RecipeAutoCombine_Struct *)outapp->pBuffer; outp->object_type = rac->object_type; outp->some_id = rac->some_id; @@ -536,8 +536,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac user->Message_StringID(MT_Skills, TRADESKILL_MISSING_COMPONENTS); - for(std::list::iterator it = MissingItems.begin(); it != MissingItems.end(); ++it) - { + for (auto it = MissingItems.begin(); it != MissingItems.end(); ++it) { const EQEmu::Item_Struct* item = database.GetItem(*it); if(item) @@ -723,7 +722,7 @@ void Client::TradeskillSearchResults(const std::string &query, unsigned long obj && row[4] == nullptr) continue; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RecipeReply, sizeof(RecipeReply_Struct)); + auto outapp = new EQApplicationPacket(OP_RecipeReply, sizeof(RecipeReply_Struct)); RecipeReply_Struct *reply = (RecipeReply_Struct *) outapp->pBuffer; reply->object_type = objtype; @@ -762,7 +761,7 @@ void Client::SendTradeskillDetails(uint32 recipe_id) { //biggest this packet can ever be: // 64 * 10 + 8 * 10 + 4 + 4 * 10 = 764 - char *buf = new char[775]; //dynamic so we can just give it to EQApplicationPacket + auto buf = new char[775]; // dynamic so we can just give it to EQApplicationPacket uint8 r,k; uint32 *header = (uint32 *) buf; @@ -835,7 +834,7 @@ void Client::SendTradeskillDetails(uint32 recipe_id) { uint32 total = sizeof(uint32) + dist + datalen; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RecipeDetails); + auto outapp = new EQApplicationPacket(OP_RecipeDetails); outapp->size = total; outapp->pBuffer = (uchar*) buf; QueuePacket(outapp); diff --git a/zone/trading.cpp b/zone/trading.cpp index e746e2122..9d23bd721 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -501,7 +501,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (other->PutItemInInventory(free_slot, *inst, true)) { Log.Out(Logs::Detail, Logs::Trading, "Container %s (%d) successfully transferred, deleting from trade slot.", inst->GetItem()->Name, inst->GetItem()->ID); if (qs_log) { - QSTradeItems_Struct* detail = new QSTradeItems_Struct; + auto detail = new QSTradeItems_Struct; detail->from_id = this->character_id; detail->from_slot = trade_slot; @@ -612,7 +612,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st Log.Out(Logs::Detail, Logs::Trading, "Partial stack %s (%d) successfully transferred, deleting %i charges from trade slot.", inst->GetItem()->Name, inst->GetItem()->ID, (old_charges - inst->GetCharges())); if (qs_log) { - QSTradeItems_Struct* detail = new QSTradeItems_Struct; + auto detail = new QSTradeItems_Struct; detail->from_id = this->character_id; detail->from_slot = trade_slot; @@ -680,7 +680,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } if (qs_log) { - QSTradeItems_Struct* detail = new QSTradeItems_Struct; + auto detail = new QSTradeItems_Struct; detail->from_id = this->character_id; detail->from_slot = trade_slot; @@ -720,7 +720,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (other->PutItemInInventory(free_slot, *inst, true)) { Log.Out(Logs::Detail, Logs::Trading, "Item %s (%d) successfully transferred, deleting from trade slot.", inst->GetItem()->Name, inst->GetItem()->ID); if (qs_log) { - QSTradeItems_Struct* detail = new QSTradeItems_Struct; + auto detail = new QSTradeItems_Struct; detail->from_id = this->character_id; detail->from_slot = trade_slot; @@ -824,7 +824,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st const ItemInst* trade_inst = m_inv[trade_slot]; if(trade_inst) { - QSHandinItems_Struct* detail = new QSHandinItems_Struct; + auto detail = new QSHandinItems_Struct; strcpy(detail->action_type, "HANDIN"); @@ -990,7 +990,7 @@ bool Client::CheckTradeLoreConflict(Client* other) } void Client::Trader_ShowItems(){ - EQApplicationPacket* outapp= new EQApplicationPacket(OP_Trader, sizeof(Trader_Struct)); + auto outapp = new EQApplicationPacket(OP_Trader, sizeof(Trader_Struct)); Trader_Struct* outints = (Trader_Struct*)outapp->pBuffer; Trader_Struct* TraderItems = database.LoadTraderItem(this->CharacterID()); @@ -1011,7 +1011,7 @@ void Client::SendTraderPacket(Client* Trader, uint32 Unknown72) if(!Trader) return; - EQApplicationPacket* outapp= new EQApplicationPacket(OP_BecomeTrader, sizeof(BecomeTrader_Struct)); + auto outapp = new EQApplicationPacket(OP_BecomeTrader, sizeof(BecomeTrader_Struct)); BecomeTrader_Struct* bts = (BecomeTrader_Struct*)outapp->pBuffer; @@ -1031,7 +1031,7 @@ void Client::SendTraderPacket(Client* Trader, uint32 Unknown72) void Client::Trader_CustomerBrowsing(Client *Customer) { - EQApplicationPacket* outapp= new EQApplicationPacket(OP_Trader, sizeof(Trader_ShowItems_Struct)); + auto outapp = new EQApplicationPacket(OP_Trader, sizeof(Trader_ShowItems_Struct)); Trader_ShowItems_Struct* sis = (Trader_ShowItems_Struct*)outapp->pBuffer; @@ -1047,7 +1047,7 @@ void Client::Trader_StartTrader() { Trader=true; - EQApplicationPacket* outapp= new EQApplicationPacket(OP_Trader, sizeof(Trader_ShowItems_Struct)); + auto outapp = new EQApplicationPacket(OP_Trader, sizeof(Trader_ShowItems_Struct)); Trader_ShowItems_Struct* sis = (Trader_ShowItems_Struct*)outapp->pBuffer; @@ -1087,7 +1087,7 @@ void Client::Trader_EndTrader() { GetItems_Struct* gis=GetTraderItems(); if(Customer && gis) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderDelItem,sizeof(TraderDelItem_Struct)); + auto outapp = new EQApplicationPacket(OP_TraderDelItem, sizeof(TraderDelItem_Struct)); TraderDelItem_Struct* tdis = (TraderDelItem_Struct*)outapp->pBuffer; tdis->Unknown000 = 0; @@ -1121,7 +1121,7 @@ void Client::Trader_EndTrader() { // Notify other clients we are no longer in trader mode. // - EQApplicationPacket* outapp= new EQApplicationPacket(OP_BecomeTrader, sizeof(BecomeTrader_Struct)); + auto outapp = new EQApplicationPacket(OP_BecomeTrader, sizeof(BecomeTrader_Struct)); BecomeTrader_Struct* bts = (BecomeTrader_Struct*)outapp->pBuffer; @@ -1280,7 +1280,7 @@ GetItems_Struct* Client::GetTraderItems(){ const ItemInst* item = nullptr; uint16 SlotID = 0; - GetItems_Struct* gis= new GetItems_Struct; + auto gis = new GetItems_Struct; memset(gis,0,sizeof(GetItems_Struct)); @@ -1346,7 +1346,7 @@ void Client::NukeTraderItem(uint16 Slot,int16 Charges,uint16 Quantity,Client* Cu } else { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderDelItem,sizeof(TraderDelItem_Struct)); + auto outapp = new EQApplicationPacket(OP_TraderDelItem, sizeof(TraderDelItem_Struct)); TraderDelItem_Struct* tdis = (TraderDelItem_Struct*)outapp->pBuffer; tdis->Unknown000 = 0; @@ -1399,7 +1399,7 @@ void Client::NukeTraderItem(uint16 Slot,int16 Charges,uint16 Quantity,Client* Cu void Client::TraderUpdate(uint16 SlotID,uint32 TraderID){ // This method is no longer used. - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderItemUpdate,sizeof(TraderItemUpdate_Struct)); + auto outapp = new EQApplicationPacket(OP_TraderItemUpdate, sizeof(TraderItemUpdate_Struct)); TraderItemUpdate_Struct* tus=(TraderItemUpdate_Struct*)outapp->pBuffer; tus->Charges = 0xFFFF; tus->FromSlot = SlotID; @@ -1524,7 +1524,7 @@ void Client::TradeRequestFailed(const EQApplicationPacket* app) { TraderBuy_Struct* tbs = (TraderBuy_Struct*)app->pBuffer; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderBuy, sizeof(TraderBuy_Struct)); + auto outapp = new EQApplicationPacket(OP_TraderBuy, sizeof(TraderBuy_Struct)); TraderBuy_Struct* outtbs = (TraderBuy_Struct*)outapp->pBuffer; @@ -1558,7 +1558,7 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic return; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Trader, sizeof(TraderBuy_Struct)); + auto outapp = new EQApplicationPacket(OP_Trader, sizeof(TraderBuy_Struct)); TraderBuy_Struct* outtbs = (TraderBuy_Struct*)outapp->pBuffer; @@ -1927,98 +1927,95 @@ void Client::SendBazaarResults(uint32 TraderID, uint32 Class_, uint32 Race, uint RuleI(Bazaar, MaxSearchResults)); if(results.RowCount() == 0) { - EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarReturnDone_Struct)); - BazaarReturnDone_Struct* brds = (BazaarReturnDone_Struct*)outapp2->pBuffer; - brds->TraderID = ID; - brds->Type = BazaarSearchDone; - brds->Unknown008 = 0xFFFFFFFF; - brds->Unknown012 = 0xFFFFFFFF; - brds->Unknown016 = 0xFFFFFFFF; - this->QueuePacket(outapp2); - safe_delete(outapp2); - return; + auto outapp2 = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarReturnDone_Struct)); + BazaarReturnDone_Struct *brds = (BazaarReturnDone_Struct *)outapp2->pBuffer; + brds->TraderID = ID; + brds->Type = BazaarSearchDone; + brds->Unknown008 = 0xFFFFFFFF; + brds->Unknown012 = 0xFFFFFFFF; + brds->Unknown016 = 0xFFFFFFFF; + this->QueuePacket(outapp2); + safe_delete(outapp2); + return; } Size = results.RowCount() * sizeof(BazaarSearchResults_Struct); - uchar *buffer = new uchar[Size]; - uchar *bufptr = buffer; - memset(buffer, 0, Size); + auto buffer = new uchar[Size]; + uchar *bufptr = buffer; + memset(buffer, 0, Size); - int Action = BazaarSearchResults; - uint32 Cost = 0; - int32 SerialNumber = 0; - char temp_buffer[64] = {0}; - int Count = 0; - uint32 StatValue=0; + int Action = BazaarSearchResults; + uint32 Cost = 0; + int32 SerialNumber = 0; + char temp_buffer[64] = {0}; + int Count = 0; + uint32 StatValue = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Action); - Count = atoi(row[0]); - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Count); - SerialNumber = atoi(row[3]); - VARSTRUCT_ENCODE_TYPE(int32, bufptr, SerialNumber); - Client* Trader2=entity_list.GetClientByCharID(atoi(row[1])); - if(Trader2){ - ID = Trader2->GetID(); - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, ID); - } - else{ - Log.Out(Logs::Detail, Logs::Trading, "Unable to find trader: %i\n",atoi(row[1])); - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, 0); - } - Cost = atoi(row[5]); - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Cost); - StatValue = atoi(row[8]); - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, StatValue); - bool Stackable = atoi(row[10]); - if(Stackable) { - int Charges = atoi(row[9]); - sprintf(temp_buffer, "%s(%i)", row[7], Charges); - } - else - sprintf(temp_buffer,"%s(%i)",row[7], Count); + for (auto row = results.begin(); row != results.end(); ++row) { + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Action); + Count = atoi(row[0]); + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Count); + SerialNumber = atoi(row[3]); + VARSTRUCT_ENCODE_TYPE(int32, bufptr, SerialNumber); + Client *Trader2 = entity_list.GetClientByCharID(atoi(row[1])); + if (Trader2) { + ID = Trader2->GetID(); + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, ID); + } else { + Log.Out(Logs::Detail, Logs::Trading, "Unable to find trader: %i\n", atoi(row[1])); + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, 0); + } + Cost = atoi(row[5]); + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, Cost); + StatValue = atoi(row[8]); + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, StatValue); + bool Stackable = atoi(row[10]); + if (Stackable) { + int Charges = atoi(row[9]); + sprintf(temp_buffer, "%s(%i)", row[7], Charges); + } else + sprintf(temp_buffer, "%s(%i)", row[7], Count); - memcpy(bufptr,&temp_buffer, strlen(temp_buffer)); + memcpy(bufptr, &temp_buffer, strlen(temp_buffer)); - bufptr += 64; + bufptr += 64; - // Extra fields for SoD+ - // - if(Trader2) - sprintf(temp_buffer, "%s", Trader2->GetName()); - else - sprintf(temp_buffer, "Unknown"); + // Extra fields for SoD+ + // + if (Trader2) + sprintf(temp_buffer, "%s", Trader2->GetName()); + else + sprintf(temp_buffer, "Unknown"); - memcpy(bufptr,&temp_buffer, strlen(temp_buffer)); + memcpy(bufptr, &temp_buffer, strlen(temp_buffer)); - bufptr += 64; + bufptr += 64; - VARSTRUCT_ENCODE_TYPE(uint32, bufptr, atoi(row[1])); // ItemID + VARSTRUCT_ENCODE_TYPE(uint32, bufptr, atoi(row[1])); // ItemID } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_BazaarSearch, Size); + auto outapp = new EQApplicationPacket(OP_BazaarSearch, Size); - memcpy(outapp->pBuffer, buffer, Size); + memcpy(outapp->pBuffer, buffer, Size); - this->QueuePacket(outapp); + this->QueuePacket(outapp); + safe_delete(outapp); + safe_delete_array(buffer); - safe_delete(outapp); - safe_delete_array(buffer); + auto outapp2 = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarReturnDone_Struct)); + BazaarReturnDone_Struct *brds = (BazaarReturnDone_Struct *)outapp2->pBuffer; - EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_BazaarSearch, sizeof(BazaarReturnDone_Struct)); - BazaarReturnDone_Struct* brds = (BazaarReturnDone_Struct*)outapp2->pBuffer; + brds->TraderID = ID; + brds->Type = BazaarSearchDone; - brds->TraderID = ID; - brds->Type = BazaarSearchDone; + brds->Unknown008 = 0xFFFFFFFF; + brds->Unknown012 = 0xFFFFFFFF; + brds->Unknown016 = 0xFFFFFFFF; - brds->Unknown008 = 0xFFFFFFFF; - brds->Unknown012 = 0xFFFFFFFF; - brds->Unknown016 = 0xFFFFFFFF; + this->QueuePacket(outapp2); - this->QueuePacket(outapp2); - - safe_delete(outapp2); + safe_delete(outapp2); } static void UpdateTraderCustomerItemsAdded(uint32 CustomerID, TraderCharges_Struct* gis, uint32 ItemID) { @@ -2080,7 +2077,7 @@ static void UpdateTraderCustomerPriceChanged(uint32 CustomerID, TraderCharges_St if(NewPrice == 0) { // If the new price is 0, remove the item(s) from the window. - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderDelItem,sizeof(TraderDelItem_Struct)); + auto outapp = new EQApplicationPacket(OP_TraderDelItem, sizeof(TraderDelItem_Struct)); TraderDelItem_Struct* tdis = (TraderDelItem_Struct*)outapp->pBuffer; tdis->Unknown000 = 0; @@ -2354,7 +2351,7 @@ void Client::SendBuyerResults(char* searchString, uint32 searchID) { // Log.Out(Logs::Detail, Logs::None, "[CLIENT] Client::SendBuyerResults %s\n", searchString); - char* escSearchString = new char[strlen(searchString) * 2 + 1]; + auto escSearchString = new char[strlen(searchString) * 2 + 1]; database.DoEscapeString(escSearchString, searchString, strlen(searchString)); std::string query = StringFormat("SELECT * FROM buyer WHERE itemname LIKE '%%%s%%' ORDER BY charid LIMIT %i", @@ -2395,7 +2392,7 @@ void Client::SendBuyerResults(char* searchString, uint32 searchID) { // to allow item compensation, e.g. a buyer could offer to buy a Blade Of Carnage for 10000pp plus // other items in exchange. Item compensation is not currently supported in EQEmu. // - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, 940); + auto outapp = new EQApplicationPacket(OP_Barter, 940); char *buf = (char *)outapp->pBuffer; @@ -2465,7 +2462,7 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) { if(strlen(WelcomeMessagePointer) > 0) Message(10, "%s greets you, '%s'.", Buyer->GetName(), WelcomeMessagePointer); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, sizeof(BuyerBrowsing_Struct)); + auto outapp = new EQApplicationPacket(OP_Barter, sizeof(BuyerBrowsing_Struct)); BuyerBrowsing_Struct* bb = (BuyerBrowsing_Struct*)outapp->pBuffer; @@ -2491,7 +2488,7 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) { uint32 Quantity = atoi(row[4]); uint32 Price = atoi(row[5]); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, 936); + auto outapp = new EQApplicationPacket(OP_Barter, 936); char *Buf = (char *)outapp->pBuffer; @@ -2623,7 +2620,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { // Remove the item from inventory, clientside // - EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct)); + auto outapp2 = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; mis->from_slot = SellerSlot; @@ -2677,7 +2674,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { safe_delete(ItemToTransfer); // and tell the client to do the same. - EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct)); + auto outapp2 = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; mis->from_slot = SellerSlot; @@ -2709,7 +2706,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { safe_delete(ItemToTransfer); - EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct)); + auto outapp2 = new EQApplicationPacket(OP_DeleteItem, sizeof(MoveItem_Struct)); MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; mis->from_slot = SellerSlot; @@ -2743,7 +2740,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { // uint32 PacketLength = 1016; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, PacketLength); + auto outapp = new EQApplicationPacket(OP_Barter, PacketLength); Buf = (char *)outapp->pBuffer; @@ -2798,7 +2795,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { // Next we update the Seller's Barter Window to reflect the reduced quantity the Buyer is now looking to buy. // - EQApplicationPacket* outapp3 = new EQApplicationPacket(OP_Barter, 936); + auto outapp3 = new EQApplicationPacket(OP_Barter, 936); Buf = (char *)outapp3->pBuffer; @@ -2832,7 +2829,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { // The next packet updates the /buyer window with the reduced quantity, and toggles the buy line off if the // quantity they wanted to buy has been met. // - EQApplicationPacket* outapp4 = new EQApplicationPacket(OP_Barter, 936); + auto outapp4 = new EQApplicationPacket(OP_Barter, 936); Buf = (char*)outapp4->pBuffer; @@ -2867,7 +2864,7 @@ void Client::SendBuyerPacket(Client* Buyer) { // This is the Buyer Appearance packet. This method is called for each Buyer when a Client connects to the zone. // - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, 13 + strlen(GetName())); + auto outapp = new EQApplicationPacket(OP_Barter, 13 + strlen(GetName())); char* Buf = (char*)outapp->pBuffer; @@ -2882,7 +2879,7 @@ void Client::SendBuyerPacket(Client* Buyer) { void Client::ToggleBuyerMode(bool TurnOn) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, 13 + strlen(GetName())); + auto outapp = new EQApplicationPacket(OP_Barter, 13 + strlen(GetName())); char* Buf = (char*)outapp->pBuffer; @@ -2963,7 +2960,7 @@ void Client::UpdateBuyLine(const EQApplicationPacket *app) { else database.RemoveBuyLine(CharacterID(), BuySlot); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, 936); + auto outapp = new EQApplicationPacket(OP_Barter, 936); Buf = (char*)outapp->pBuffer; @@ -2990,7 +2987,7 @@ void Client::BuyerItemSearch(const EQApplicationPacket *app) { BuyerItemSearch_Struct* bis = (BuyerItemSearch_Struct*)app->pBuffer; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, sizeof(BuyerItemSearchResults_Struct)); + auto outapp = new EQApplicationPacket(OP_Barter, sizeof(BuyerItemSearchResults_Struct)); BuyerItemSearchResults_Struct* bisr = (BuyerItemSearchResults_Struct*)outapp->pBuffer; diff --git a/zone/trap.cpp b/zone/trap.cpp index 1cce48e19..5a644bb03 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -146,7 +146,7 @@ void Trap::Trigger(Mob* trigger) { auto randomOffset = glm::vec4(zone->random.Int(-5, 5),zone->random.Int(-5, 5),zone->random.Int(-5, 5), zone->random.Int(0, 249)); auto spawnPosition = randomOffset + glm::vec4(m_Position, 0.0f); - NPC* new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3); + auto new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3); new_npc->AddLootTable(); entity_list.AddNPC(new_npc); new_npc->AddToHateList(trigger,1); @@ -169,7 +169,7 @@ void Trap::Trigger(Mob* trigger) { auto randomOffset = glm::vec4(zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(0, 249)); auto spawnPosition = randomOffset + glm::vec4(m_Position, 0.0f); - NPC* new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3); + auto new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3); new_npc->AddLootTable(); entity_list.AddNPC(new_npc); new_npc->AddToHateList(trigger,1); @@ -187,7 +187,7 @@ void Trap::Trigger(Mob* trigger) } if(trigger->IsClient()) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); + auto outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer; int dmg = zone->random.Int(effectvalue, effectvalue2); trigger->SetHP(trigger->GetHP() - dmg); @@ -268,7 +268,7 @@ bool ZoneDatabase::LoadTraps(const char* zonename, int16 version) { } for (auto row = results.begin(); row != results.end(); ++row) { - Trap* trap = new Trap(); + auto trap = new Trap(); trap->trap_id = atoi(row[0]); trap->m_Position = glm::vec3(atof(row[1]), atof(row[2]), atof(row[3])); trap->effect = atoi(row[4]); @@ -295,7 +295,7 @@ void Trap::CreateHiddenTrigger() return; const NPCType *base_type = database.LoadNPCTypesData(500); - NPCType *make_npc = new NPCType; + auto make_npc = new NPCType; memcpy(make_npc, base_type, sizeof(NPCType)); make_npc->max_hp = 100000; make_npc->cur_hp = 100000; diff --git a/zone/water_map.cpp b/zone/water_map.cpp index c77e77f00..f3b4c58d8 100644 --- a/zone/water_map.cpp +++ b/zone/water_map.cpp @@ -33,7 +33,7 @@ WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) { } if(version == 1) { - WaterMapV1 *wm = new WaterMapV1(); + auto wm = new WaterMapV1(); if(!wm->Load(f)) { delete wm; wm = nullptr; @@ -42,7 +42,7 @@ WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) { fclose(f); return wm; } else if(version == 2) { - WaterMapV2 *wm = new WaterMapV2(); + auto wm = new WaterMapV2(); if(!wm->Load(f)) { delete wm; wm = nullptr; diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 51a7af4fb..f6c55a5eb 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -253,7 +253,7 @@ void NPC::CalculateNewWaypoint() { std::list closest; GetClosestWaypoint(closest, 10, glm::vec3(GetPosition())); - std::list::iterator iter = closest.begin(); + auto iter = closest.begin(); if(closest.size() != 0) { iter = closest.begin(); @@ -310,7 +310,7 @@ void NPC::CalculateNewWaypoint() std::list closest; GetClosestWaypoint(closest, 5, glm::vec3(GetPosition())); - std::list::iterator iter = closest.begin(); + auto iter = closest.begin(); while(iter != closest.end()) { if(CheckLosFN((*iter).x, (*iter).y, (*iter).z, GetSize())) @@ -380,7 +380,7 @@ void NPC::GetClosestWaypoint(std::list &wp_list, int count, const glm::v return a.dist < b.dist; }); - std::list::iterator iter = distances.begin(); + auto iter = distances.begin(); for(int i = 0; i < count; ++i) { wp_list.push_back(Waypoints[(*iter).index]); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index c9d3f4d5c..969c4b947 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -90,7 +90,7 @@ WorldServer::~WorldServer() { }*/ void WorldServer::SetZoneData(uint32 iZoneID, uint32 iInstanceID) { - ServerPacket* pack = new ServerPacket(ServerOP_SetZone, sizeof(SetZone_Struct)); + auto pack = new ServerPacket(ServerOP_SetZone, sizeof(SetZone_Struct)); SetZone_Struct* szs = (SetZone_Struct*) pack->pBuffer; szs->zoneid = iZoneID; szs->instanceid = iInstanceID; @@ -225,7 +225,7 @@ void WorldServer::Process() { ServerVoiceMacro_Struct* svm = (ServerVoiceMacro_Struct*) pack->pBuffer; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_VoiceMacroOut,sizeof(VoiceMacroOut_Struct)); + auto outapp = new EQApplicationPacket(OP_VoiceMacroOut, sizeof(VoiceMacroOut_Struct)); VoiceMacroOut_Struct* vmo = (VoiceMacroOut_Struct*)outapp->pBuffer; strcpy(vmo->From, svm->From); @@ -400,10 +400,10 @@ void WorldServer::Process() { if(pack->size==64)//no results client->Message_StringID(0,WHOALL_NO_RESULTS); else{ - EQApplicationPacket* outapp = new EQApplicationPacket(OP_WhoAllResponse, pack->size); - memcpy(outapp->pBuffer, pack->pBuffer, pack->size); - client->QueuePacket(outapp); - safe_delete(outapp); + auto outapp = new EQApplicationPacket(OP_WhoAllResponse, pack->size); + memcpy(outapp->pBuffer, pack->pBuffer, pack->size); + client->QueuePacket(outapp); + safe_delete(outapp); } } else { @@ -613,7 +613,7 @@ void WorldServer::Process() { Client* client = entity_list.GetClientByName(gmg->gotoname); if (client != 0) { SendEmoteMessage(gmg->myname, 0, 13, "Summoning you to: %s @ %s, %1.1f, %1.1f, %1.1f", client->GetName(), zone->GetShortName(), client->GetX(), client->GetY(), client->GetZ()); - ServerPacket* outpack = new ServerPacket(ServerOP_ZonePlayer, sizeof(ServerZonePlayer_Struct)); + auto outpack = new ServerPacket(ServerOP_ZonePlayer, sizeof(ServerZonePlayer_Struct)); ServerZonePlayer_Struct* szp = (ServerZonePlayer_Struct*) outpack->pBuffer; strcpy(szp->adminname, gmg->myname); strcpy(szp->name, gmg->myname); @@ -634,7 +634,7 @@ void WorldServer::Process() { ServerMultiLineMsg_Struct* mlm = (ServerMultiLineMsg_Struct*) pack->pBuffer; Client* client = entity_list.GetClientByName(mlm->to); if (client) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MultiLineMsg, strlen(mlm->message)); + auto outapp = new EQApplicationPacket(OP_MultiLineMsg, strlen(mlm->message)); strcpy((char*) outapp->pBuffer, mlm->message); client->QueuePacket(outapp); safe_delete(outapp); @@ -681,7 +681,8 @@ void WorldServer::Process() { { if(client->IsRezzPending()) { - ServerPacket * Response = new ServerPacket(ServerOP_RezzPlayerReject, strlen(srs->rez.rezzer_name) + 1); + auto Response = new ServerPacket(ServerOP_RezzPlayerReject, + strlen(srs->rez.rezzer_name) + 1); char *Buffer = (char *)Response->pBuffer; sprintf(Buffer, "%s", srs->rez.rezzer_name); @@ -694,12 +695,12 @@ void WorldServer::Process() { client->SetPendingRezzData(srs->exp, srs->dbid, srs->rez.spellid, srs->rez.corpse_name); Log.Out(Logs::Detail, Logs::Spells, "OP_RezzRequest in zone %s for %s, spellid:%i", zone->GetShortName(), client->GetName(), srs->rez.spellid); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RezzRequest, - sizeof(Resurrect_Struct)); - memcpy(outapp->pBuffer, &srs->rez, sizeof(Resurrect_Struct)); - client->QueuePacket(outapp); - safe_delete(outapp); - break; + auto outapp = new EQApplicationPacket(OP_RezzRequest, + sizeof(Resurrect_Struct)); + memcpy(outapp->pBuffer, &srs->rez, sizeof(Resurrect_Struct)); + client->QueuePacket(outapp); + safe_delete(outapp); + break; } } if (srs->rezzopcode == OP_RezzComplete){ @@ -741,7 +742,7 @@ void WorldServer::Process() { eqTimeOfDay* newtime = (eqTimeOfDay*)pack->pBuffer; zone->zone_time.SetCurrentEQTimeOfDay(newtime->start_eqtime, newtime->start_realtime); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct)); + auto outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct)); TimeOfDay_Struct* time_of_day = (TimeOfDay_Struct*)outapp->pBuffer; zone->zone_time.GetCurrentEQTimeOfDay(time(0), time_of_day); entity_list.QueueClients(0, outapp, false); @@ -825,7 +826,7 @@ void WorldServer::Process() { if(Invitee && Invitee->IsClient() && Invitee->CastToClient()->MercOnlyOrNoGroup() && !Invitee->IsRaidGrouped()) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupInvite, sizeof(GroupInvite_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupInvite, sizeof(GroupInvite_Struct)); memcpy(outapp->pBuffer, gis, sizeof(GroupInvite_Struct)); Invitee->CastToClient()->QueuePacket(outapp); safe_delete(outapp); @@ -866,7 +867,8 @@ void WorldServer::Process() { if (Inviter->CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoD) { - EQApplicationPacket* outapp=new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupJoin_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* outgj=(GroupJoin_Struct*)outapp->pBuffer; strcpy(outgj->membername, Inviter->GetName()); strcpy(outgj->yourname, Inviter->GetName()); @@ -889,7 +891,7 @@ void WorldServer::Process() { break; } - EQApplicationPacket* outapp=new EQApplicationPacket(OP_GroupFollow, sizeof(GroupGeneric_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupFollow, sizeof(GroupGeneric_Struct)); GroupGeneric_Struct *gg = (GroupGeneric_Struct *)outapp->pBuffer; strn0cpy(gg->name1, sgfs->gf.name1, sizeof(gg->name1)); strn0cpy(gg->name2, sgfs->gf.name2, sizeof(gg->name2)); @@ -902,7 +904,7 @@ void WorldServer::Process() { if(Inviter->CastToClient()->IsLFP()) Inviter->CastToClient()->UpdateLFP(); - ServerPacket* pack2 = new ServerPacket(ServerOP_GroupJoin, sizeof(ServerGroupJoin_Struct)); + auto pack2 = new ServerPacket(ServerOP_GroupJoin, sizeof(ServerGroupJoin_Struct)); ServerGroupJoin_Struct* gj = (ServerGroupJoin_Struct*)pack2->pBuffer; gj->gid = group->GetID(); gj->zoneid = zone->GetZoneID(); @@ -914,7 +916,8 @@ void WorldServer::Process() { // Send acknowledgement back to the Invitee to let them know we have added them to the group. - ServerPacket* pack3 = new ServerPacket(ServerOP_GroupFollowAck, sizeof(ServerGroupFollowAck_Struct)); + auto pack3 = + new ServerPacket(ServerOP_GroupFollowAck, sizeof(ServerGroupFollowAck_Struct)); ServerGroupFollowAck_Struct* sgfas = (ServerGroupFollowAck_Struct*)pack3->pBuffer; strn0cpy(sgfas->Name, sgfs->gf.name2, sizeof(sgfas->Name)); worldserver.SendPacket(pack3); @@ -1011,7 +1014,7 @@ void WorldServer::Process() { if(Inviter && Inviter->IsClient()) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupCancelInvite, sizeof(GroupCancel_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupCancelInvite, sizeof(GroupCancel_Struct)); memcpy(outapp->pBuffer, sgcs, sizeof(GroupCancel_Struct)); Inviter->CastToClient()->QueuePacket(outapp); safe_delete(outapp); @@ -1234,7 +1237,8 @@ void WorldServer::Process() { Client *c = entity_list.GetClientByName(rga->playername); if(c) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupUpdate_Struct)); + auto outapp = + new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate_Struct)); GroupUpdate_Struct* gu = (GroupUpdate_Struct*) outapp->pBuffer; gu->action = groupActDisband; strn0cpy(gu->leadersname, c->GetName(), 64); @@ -1252,7 +1256,7 @@ void WorldServer::Process() { if(r){ r->LearnMembers(); r->VerifyRaid(); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer; strn0cpy(gj->membername, rga->membername, 64); gj->action = groupActJoin; @@ -1283,7 +1287,7 @@ void WorldServer::Process() { if(r){ r->LearnMembers(); r->VerifyRaid(); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct)); GroupJoin_Struct* gj = (GroupJoin_Struct*) outapp->pBuffer; strn0cpy(gj->membername, rga->membername, 64); gj->action = groupActLeave; @@ -1387,7 +1391,8 @@ void WorldServer::Process() { else client->consent_list.remove(s->ownername); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ConsentResponse, sizeof(ConsentResponse_Struct)); + auto outapp = + new EQApplicationPacket(OP_ConsentResponse, sizeof(ConsentResponse_Struct)); ConsentResponse_Struct* crs = (ConsentResponse_Struct*)outapp->pBuffer; strcpy(crs->grantname, s->grantname); strcpy(crs->ownername, s->ownername); @@ -1404,7 +1409,8 @@ void WorldServer::Process() { // CONSENT_INVALID_NAME = 397 // TARGET_NOT_FOUND = 101 - ServerPacket *scs_pack = new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct)); + auto scs_pack = + new ServerPacket(ServerOP_Consent_Response, sizeof(ServerOP_Consent_Struct)); ServerOP_Consent_Struct* scs = (ServerOP_Consent_Struct*)scs_pack->pBuffer; strcpy(scs->grantname, s->grantname); strcpy(scs->ownername, s->ownername); @@ -1623,7 +1629,7 @@ void WorldServer::Process() { if(c) { c->ClearAdventureData(); - char * adv_data = new char[pack->size]; + auto adv_data = new char[pack->size]; memcpy(adv_data, pack->pBuffer, pack->size); c->SetAdventureData(adv_data); c->ClearPendingAdventureData(); @@ -1731,7 +1737,8 @@ void WorldServer::Process() { Client *c = entity_list.GetClientByName((const char*)pack->pBuffer); if(c) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AdventureLeaderboardReply, sizeof(AdventureLeaderboard_Struct)); + auto outapp = new EQApplicationPacket(OP_AdventureLeaderboardReply, + sizeof(AdventureLeaderboard_Struct)); memcpy(outapp->pBuffer, pack->pBuffer+64, sizeof(AdventureLeaderboard_Struct)); c->FastQueuePacket(&outapp); } @@ -1897,7 +1904,7 @@ bool WorldServer::SendChannelMessage(Client* from, const char* to, uint8 chan_nu va_end(argptr); buffer[511] = '\0'; - ServerPacket* pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen(buffer) + 1); + auto pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen(buffer) + 1); ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*) pack->pBuffer; if (from == 0) { @@ -1951,7 +1958,7 @@ bool WorldServer::SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to return false; } - ServerPacket* pack = new ServerPacket(ServerOP_EmoteMessage, sizeof(ServerEmoteMessage_Struct)+strlen(buffer)+1); + auto pack = new ServerPacket(ServerOP_EmoteMessage, sizeof(ServerEmoteMessage_Struct) + strlen(buffer) + 1); ServerEmoteMessage_Struct* sem = (ServerEmoteMessage_Struct*) pack->pBuffer; sem->type = type; if (to != 0) @@ -1971,7 +1978,7 @@ bool WorldServer::SendVoiceMacro(Client* From, uint32 Type, char* Target, uint32 if(!worldserver.Connected() || !From) return false; - ServerPacket* pack = new ServerPacket(ServerOP_VoiceMacro, sizeof(ServerVoiceMacro_Struct)); + auto pack = new ServerPacket(ServerOP_VoiceMacro, sizeof(ServerVoiceMacro_Struct)); ServerVoiceMacro_Struct* svm = (ServerVoiceMacro_Struct*) pack->pBuffer; @@ -2010,7 +2017,7 @@ bool WorldServer::SendVoiceMacro(Client* From, uint32 Type, char* Target, uint32 bool WorldServer::RezzPlayer(EQApplicationPacket* rpack, uint32 rezzexp, uint32 dbid, uint16 opcode) { Log.Out(Logs::Detail, Logs::Spells, "WorldServer::RezzPlayer rezzexp is %i (0 is normal for RezzComplete", rezzexp); - ServerPacket* pack = new ServerPacket(ServerOP_RezzPlayer, sizeof(RezzPlayer_Struct)); + auto pack = new ServerPacket(ServerOP_RezzPlayer, sizeof(RezzPlayer_Struct)); RezzPlayer_Struct* sem = (RezzPlayer_Struct*) pack->pBuffer; sem->rezzopcode = opcode; sem->rez = *(Resurrect_Struct*) rpack->pBuffer; @@ -2027,7 +2034,7 @@ bool WorldServer::RezzPlayer(EQApplicationPacket* rpack, uint32 rezzexp, uint32 } void WorldServer::SendReloadTasks(int Command, int TaskID) { - ServerPacket* pack = new ServerPacket(ServerOP_ReloadTasks, sizeof(ReloadTasks_Struct)); + auto pack = new ServerPacket(ServerOP_ReloadTasks, sizeof(ReloadTasks_Struct)); ReloadTasks_Struct* rts = (ReloadTasks_Struct*) pack->pBuffer; rts->Command = Command; @@ -2101,7 +2108,7 @@ uint32 WorldServer::NextGroupID() { } if(cur_groupid > (last_groupid - /*50*/995)) { //running low, request more - ServerPacket* pack = new ServerPacket(ServerOP_GroupIDReq); + auto pack = new ServerPacket(ServerOP_GroupIDReq); SendPacket(pack); safe_delete(pack); } @@ -2112,7 +2119,7 @@ uint32 WorldServer::NextGroupID() { void WorldServer::UpdateLFP(uint32 LeaderID, uint8 Action, uint8 MatchFilter, uint32 FromLevel, uint32 ToLevel, uint32 Classes, const char *Comments, GroupLFPMemberEntry *LFPMembers) { - ServerPacket* pack = new ServerPacket(ServerOP_LFPUpdate, sizeof(ServerLFPUpdate_Struct)); + auto pack = new ServerPacket(ServerOP_LFPUpdate, sizeof(ServerLFPUpdate_Struct)); ServerLFPUpdate_Struct* sus = (ServerLFPUpdate_Struct*) pack->pBuffer; sus->LeaderID = LeaderID; @@ -2159,7 +2166,7 @@ void WorldServer::HandleLFGMatches(ServerPacket *pack) { smrs++; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LFGGetMatchesResponse, PacketLength); + auto outapp = new EQApplicationPacket(OP_LFGGetMatchesResponse, PacketLength); smrs = (ServerLFGMatchesResponse_Struct*)Buffer; @@ -2206,7 +2213,7 @@ void WorldServer::HandleLFPMatches(ServerPacket *pack) { } smrs++; } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_LFPGetMatchesResponse, PacketLength); + auto outapp = new EQApplicationPacket(OP_LFPGetMatchesResponse, PacketLength); smrs = (ServerLFPMatchesResponse_Struct*)Buffer; @@ -2249,7 +2256,7 @@ void WorldServer::RequestTellQueue(const char *who) if (!who) return; - ServerPacket* pack = new ServerPacket(ServerOP_RequestTellQueue, sizeof(ServerRequestTellQueue_Struct)); + auto pack = new ServerPacket(ServerOP_RequestTellQueue, sizeof(ServerRequestTellQueue_Struct)); ServerRequestTellQueue_Struct* rtq = (ServerRequestTellQueue_Struct*) pack->pBuffer; strn0cpy(rtq->name, who, sizeof(rtq->name)); diff --git a/zone/zone.cpp b/zone/zone.cpp index 6c58bea65..df48d0cfa 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -137,7 +137,7 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { worldserver.SetZoneData(iZoneID, iInstanceID); if(iInstanceID != 0) { - ServerPacket *pack = new ServerPacket(ServerOP_AdventureZoneData, sizeof(uint16)); + auto pack = new ServerPacket(ServerOP_AdventureZoneData, sizeof(uint16)); *((uint16*)pack->pBuffer) = iInstanceID; worldserver.SendPacket(pack); delete pack; @@ -215,12 +215,12 @@ bool Zone::LoadZoneObjects() { d.incline = atoi(row[13]); // unknown20 = optional model incline value d.client_version_mask = 0xFFFFFFFF; //We should load the mask from the zone. - Doors* door = new Doors(&d); - entity_list.AddDoor(door); - } + auto door = new Doors(&d); + entity_list.AddDoor(door); + } - Object_Struct data = {0}; - uint32 id = 0; + Object_Struct data = {0}; + uint32 id = 0; uint32 icon = 0; uint32 type = 0; uint32 itemid = 0; @@ -270,12 +270,12 @@ bool Zone::LoadZoneObjects() { database.LoadWorldContainer(id, inst); } - Object* object = new Object(id, type, icon, data, inst); - entity_list.AddObject(object, false); - if(type == OT_DROPPEDITEM && itemid != 0) - entity_list.RemoveObject(object->GetID()); + auto object = new Object(id, type, icon, data, inst); + entity_list.AddObject(object, false); + if (type == OT_DROPPEDITEM && itemid != 0) + entity_list.RemoveObject(object->GetID()); - safe_delete(inst); + safe_delete(inst); } return true; @@ -301,7 +301,12 @@ bool Zone::LoadGroundSpawns() { if(inst){ name = groundspawn.spawn[gsindex].name; for(ix=0;ix::iterator iter = cur->second.begin(); + auto iter = cur->second.begin(); bool found = false; while (iter != cur->second.end()) { if ((*iter).item == ml.id) { @@ -722,7 +727,7 @@ void Zone::LoadZoneDoors(const char* zone, int16 version) return; } - Door *dlist = new Door[count]; + auto dlist = new Door[count]; if(!database.LoadDoors(count, dlist, zone, version)) { Log.Out(Logs::General, Logs::Error, "... Failed to load doors."); @@ -733,7 +738,7 @@ void Zone::LoadZoneDoors(const char* zone, int16 version) int r; Door *d = dlist; for(r = 0; r < count; r++, d++) { - Doors* newdoor = new Doors(d); + auto newdoor = new Doors(d); entity_list.AddDoor(newdoor); Log.Out(Logs::Detail, Logs::Doors, "Door Add to Entity List, index: %u db id: %u, door_id %u", r, dlist[r].db_id, dlist[r].door_id); } @@ -1076,7 +1081,7 @@ bool Zone::SaveZoneCFG() { } void Zone::AddAuth(ServerZoneIncomingClient_Struct* szic) { - ZoneClientAuth_Struct* zca = new ZoneClientAuth_Struct; + auto zca = new ZoneClientAuth_Struct; memset(zca, 0, sizeof(ZoneClientAuth_Struct)); zca->ip = szic->ip; zca->wid = szic->wid; @@ -1495,7 +1500,7 @@ void Zone::Repop(uint32 delay) { void Zone::GetTimeSync() { if (worldserver.Connected() && !zone_has_current_time) { - ServerPacket* pack = new ServerPacket(ServerOP_GetWorldTime, 0); + auto pack = new ServerPacket(ServerOP_GetWorldTime, 0); worldserver.SendPacket(pack); safe_delete(pack); } @@ -1504,7 +1509,7 @@ void Zone::GetTimeSync() void Zone::SetDate(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute) { if (worldserver.Connected()) { - ServerPacket* pack = new ServerPacket(ServerOP_SetWorldTime, sizeof(eqTimeOfDay)); + auto pack = new ServerPacket(ServerOP_SetWorldTime, sizeof(eqTimeOfDay)); eqTimeOfDay* eqtod = (eqTimeOfDay*)pack->pBuffer; eqtod->start_eqtime.minute=minute; eqtod->start_eqtime.hour=hour; @@ -1521,7 +1526,7 @@ void Zone::SetDate(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute void Zone::SetTime(uint8 hour, uint8 minute, bool update_world /*= true*/) { if (worldserver.Connected()) { - ServerPacket* pack = new ServerPacket(ServerOP_SetWorldTime, sizeof(eqTimeOfDay)); + auto pack = new ServerPacket(ServerOP_SetWorldTime, sizeof(eqTimeOfDay)); eqTimeOfDay* eq_time_of_day = (eqTimeOfDay*)pack->pBuffer; zone_time.GetCurrentEQTimeOfDay(time(0), &eq_time_of_day->start_eqtime); @@ -1544,7 +1549,7 @@ void Zone::SetTime(uint8 hour, uint8 minute, bool update_world /*= true*/) Log.Out(Logs::General, Logs::Zone_Server, "Setting zone localized time..."); zone->zone_time.SetCurrentEQTimeOfDay(eq_time_of_day->start_eqtime, eq_time_of_day->start_realtime); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct)); + auto outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct)); TimeOfDay_Struct* time_of_day = (TimeOfDay_Struct*)outapp->pBuffer; zone->zone_time.GetCurrentEQTimeOfDay(time(0), time_of_day); entity_list.QueueClients(0, outapp, false); @@ -1652,39 +1657,39 @@ ZonePoint* Zone::GetClosestZonePointWithoutZone(float x, float y, float z, Clien bool ZoneDatabase::LoadStaticZonePoints(LinkedList* zone_point_list, const char* zonename, uint32 version) { - zone_point_list->Clear(); zone->numzonepoints = 0; std::string query = StringFormat("SELECT x, y, z, target_x, target_y, " - "target_z, target_zone_id, heading, target_heading, " - "number, target_instance, client_version_mask " - "FROM zone_points WHERE zone='%s' AND (version=%i OR version=-1) " - "ORDER BY number", zonename, version); + "target_z, target_zone_id, heading, target_heading, " + "number, target_instance, client_version_mask " + "FROM zone_points WHERE zone='%s' AND (version=%i OR version=-1) " + "ORDER BY number", + zonename, version); auto results = QueryDatabase(query); if (!results.Success()) { return false; } - for (auto row = results.begin(); row != results.end(); ++row) { - ZonePoint* zp = new ZonePoint; + for (auto row = results.begin(); row != results.end(); ++row) { + auto zp = new ZonePoint; - zp->x = atof(row[0]); - zp->y = atof(row[1]); - zp->z = atof(row[2]); - zp->target_x = atof(row[3]); - zp->target_y = atof(row[4]); - zp->target_z = atof(row[5]); - zp->target_zone_id = atoi(row[6]); - zp->heading = atof(row[7]); - zp->target_heading = atof(row[8]); - zp->number = atoi(row[9]); - zp->target_zone_instance = atoi(row[10]); - zp->client_version_mask = (uint32)strtoul(row[11], nullptr, 0); + zp->x = atof(row[0]); + zp->y = atof(row[1]); + zp->z = atof(row[2]); + zp->target_x = atof(row[3]); + zp->target_y = atof(row[4]); + zp->target_z = atof(row[5]); + zp->target_zone_id = atoi(row[6]); + zp->heading = atof(row[7]); + zp->target_heading = atof(row[8]); + zp->number = atoi(row[9]); + zp->target_zone_instance = atoi(row[10]); + zp->client_version_mask = (uint32)strtoul(row[11], nullptr, 0); - zone_point_list->Insert(zp); + zone_point_list->Insert(zp); - zone->numzonepoints++; - } + zone->numzonepoints++; + } return true; } @@ -1838,7 +1843,7 @@ bool ZoneDatabase::GetDecayTimes(npcDecayTimes_Struct* npcCorpseDecayTimes) { void Zone::weatherSend() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Weather, 8); + auto outapp = new EQApplicationPacket(OP_Weather, 8); if(zone_weather>0) outapp->pBuffer[0] = zone_weather-1; if(zone_weather>0) @@ -2001,13 +2006,13 @@ void Zone::LoadLDoNTraps() } for (auto row = results.begin();row != results.end(); ++row) { - LDoNTrapTemplate *lt = new LDoNTrapTemplate; - lt->id = atoi(row[0]); - lt->type = (LDoNChestTypes)atoi(row[1]); - lt->spell_id = atoi(row[2]); - lt->skill = atoi(row[3]); - lt->locked = atoi(row[4]); - ldon_trap_list[lt->id] = lt; + auto lt = new LDoNTrapTemplate; + lt->id = atoi(row[0]); + lt->type = (LDoNChestTypes)atoi(row[1]); + lt->spell_id = atoi(row[2]); + lt->skill = atoi(row[3]); + lt->locked = atoi(row[4]); + ldon_trap_list[lt->id] = lt; } } @@ -2166,7 +2171,7 @@ void Zone::DoAdventureCountIncrease() if(sr->count < sr->total) { sr->count++; - ServerPacket *pack = new ServerPacket(ServerOP_AdventureCountUpdate, sizeof(uint16)); + auto pack = new ServerPacket(ServerOP_AdventureCountUpdate, sizeof(uint16)); *((uint16*)pack->pBuffer) = instanceid; worldserver.SendPacket(pack); delete pack; @@ -2179,7 +2184,7 @@ void Zone::DoAdventureAssassinationCountIncrease() if(sr->assa_count < RuleI(Adventure, NumberKillsForBossSpawn)) { sr->assa_count++; - ServerPacket *pack = new ServerPacket(ServerOP_AdventureAssaCountUpdate, sizeof(uint16)); + auto pack = new ServerPacket(ServerOP_AdventureAssaCountUpdate, sizeof(uint16)); *((uint16*)pack->pBuffer) = instanceid; worldserver.SendPacket(pack); delete pack; @@ -2229,12 +2234,12 @@ void Zone::LoadNPCEmotes(LinkedList* NPCEmoteList) for (auto row = results.begin(); row != results.end(); ++row) { - NPC_Emote_Struct* nes = new NPC_Emote_Struct; - nes->emoteid = atoi(row[0]); - nes->event_ = atoi(row[1]); - nes->type = atoi(row[2]); - strn0cpy(nes->text, row[3], sizeof(nes->text)); - NPCEmoteList->Insert(nes); + auto nes = new NPC_Emote_Struct; + nes->emoteid = atoi(row[0]); + nes->event_ = atoi(row[1]); + nes->type = atoi(row[2]); + strn0cpy(nes->text, row[3], sizeof(nes->text)); + NPCEmoteList->Insert(nes); } } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index e2ea36fca..7adafb63f 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -315,8 +315,8 @@ bool ZoneDatabase::logevents(const char* accountname,uint32 accountid,uint8 stat uint32 len = strlen(description); uint32 len2 = strlen(target); - char* descriptiontext = new char[2*len+1]; - char* targetarr = new char[2*len2+1]; + auto descriptiontext = new char[2 * len + 1]; + auto targetarr = new char[2 * len2 + 1]; memset(descriptiontext, 0, 2*len+1); memset(targetarr, 0, 2*len2+1); DoEscapeString(descriptiontext, description, len); @@ -382,7 +382,7 @@ void ZoneDatabase::UpdateBug(BugStruct* bug) { void ZoneDatabase::UpdateBug(PetitionBug_Struct* bug){ uint32 len = strlen(bug->text); - char* bugtext = new char[2*len+1]; + auto bugtext = new char[2 * len + 1]; memset(bugtext, 0, 2*len+1); DoEscapeString(bugtext, bug->text, len); @@ -562,7 +562,7 @@ void ZoneDatabase::DeleteWorldContainer(uint32 parent_id, uint32 zone_id) Trader_Struct* ZoneDatabase::LoadTraderItem(uint32 char_id) { - Trader_Struct* loadti = new Trader_Struct; + auto loadti = new Trader_Struct; memset(loadti,0,sizeof(Trader_Struct)); std::string query = StringFormat("SELECT * FROM trader WHERE char_id = %i ORDER BY slot_id LIMIT 80", char_id); @@ -587,7 +587,7 @@ Trader_Struct* ZoneDatabase::LoadTraderItem(uint32 char_id) TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id) { - TraderCharges_Struct* loadti = new TraderCharges_Struct; + auto loadti = new TraderCharges_Struct; memset(loadti,0,sizeof(TraderCharges_Struct)); std::string query = StringFormat("SELECT * FROM trader WHERE char_id=%i ORDER BY slot_id LIMIT 80", char_id); @@ -2791,7 +2791,7 @@ void ZoneDatabase::RefreshGroupFromDB(Client *client){ if(!group) return; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate,sizeof(GroupUpdate2_Struct)); + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate2_Struct)); GroupUpdate2_Struct* gu = (GroupUpdate2_Struct*)outapp->pBuffer; gu->action = groupActUpdate; @@ -3366,7 +3366,7 @@ bool ZoneDatabase::GetFactionData(FactionMods* fm, uint32 class_mod, uint32 race char str[32]; sprintf(str, "r%u", race_mod); - std::map::iterator iter = faction_array[faction_id]->mods.find(str); + auto iter = faction_array[faction_id]->mods.find(str); if(iter != faction_array[faction_id]->mods.end()) { fm->race_mod = iter->second; } else { @@ -3380,7 +3380,7 @@ bool ZoneDatabase::GetFactionData(FactionMods* fm, uint32 class_mod, uint32 race char str[32]; sprintf(str, "d%u", deity_mod); - std::map::iterator iter = faction_array[faction_id]->mods.find(str); + auto iter = faction_array[faction_id]->mods.find(str); if(iter != faction_array[faction_id]->mods.end()) { fm->deity_mod = iter->second; } else { diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 8a387216e..16130f8e2 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -365,7 +365,7 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc if (zone_id == zone->GetZoneID() && instance_id == zone->GetInstanceID()) { // No need to ask worldserver if we're zoning to ourselves (most // likely to a bind point), also fixes a bug since the default response was failure - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZoneChange,sizeof(ZoneChange_Struct)); + auto outapp = new EQApplicationPacket(OP_ZoneChange, sizeof(ZoneChange_Struct)); ZoneChange_Struct* zc2 = (ZoneChange_Struct*) outapp->pBuffer; strcpy(zc2->char_name, GetName()); zc2->zoneID = zone_id; @@ -378,19 +378,19 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc } else { // vesuvias - zoneing to another zone so we need to the let the world server //handle things with the client for a while - ServerPacket* pack = new ServerPacket(ServerOP_ZoneToZoneRequest, sizeof(ZoneToZone_Struct)); - ZoneToZone_Struct* ztz = (ZoneToZone_Struct*) pack->pBuffer; - ztz->response = 0; - ztz->current_zone_id = zone->GetZoneID(); - ztz->current_instance_id = zone->GetInstanceID(); - ztz->requested_zone_id = zone_id; - ztz->requested_instance_id = instance_id; - ztz->admin = admin; - ztz->ignorerestrictions = ignore_r; - strcpy(ztz->name, GetName()); - ztz->guild_id = GuildID(); - worldserver.SendPacket(pack); - safe_delete(pack); + auto pack = new ServerPacket(ServerOP_ZoneToZoneRequest, sizeof(ZoneToZone_Struct)); + ZoneToZone_Struct *ztz = (ZoneToZone_Struct *)pack->pBuffer; + ztz->response = 0; + ztz->current_zone_id = zone->GetZoneID(); + ztz->current_instance_id = zone->GetInstanceID(); + ztz->requested_zone_id = zone_id; + ztz->requested_instance_id = instance_id; + ztz->admin = admin; + ztz->ignorerestrictions = ignore_r; + strcpy(ztz->name, GetName()); + ztz->guild_id = GuildID(); + worldserver.SendPacket(pack); + safe_delete(pack); } //reset to unsolicited. @@ -582,7 +582,8 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z zone_mode = zm; if (zm == ZoneToBindPoint) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_ZonePlayerToBind, sizeof(ZonePlayerToBind_Struct) + iZoneNameLength); + auto outapp = new EQApplicationPacket(OP_ZonePlayerToBind, + sizeof(ZonePlayerToBind_Struct) + iZoneNameLength); ZonePlayerToBind_Struct* gmg = (ZonePlayerToBind_Struct*) outapp->pBuffer; // If we are SoF and later and are respawning from hover, we want the real zone ID, else zero to use the old hack. @@ -607,7 +608,8 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z safe_delete(outapp); } else if(zm == ZoneSolicited || zm == ZoneToSafeCoords) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RequestClientZoneChange, sizeof(RequestClientZoneChange_Struct)); + auto outapp = + new EQApplicationPacket(OP_RequestClientZoneChange, sizeof(RequestClientZoneChange_Struct)); RequestClientZoneChange_Struct* gmg = (RequestClientZoneChange_Struct*) outapp->pBuffer; gmg->zone_id = zoneID; @@ -623,7 +625,8 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z safe_delete(outapp); } else if(zm == EvacToSafeCoords) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RequestClientZoneChange, sizeof(RequestClientZoneChange_Struct)); + auto outapp = + new EQApplicationPacket(OP_RequestClientZoneChange, sizeof(RequestClientZoneChange_Struct)); RequestClientZoneChange_Struct* gmg = (RequestClientZoneChange_Struct*) outapp->pBuffer; // if we are in the same zone we want to evac to, client will not send OP_ZoneChange back to do an actual @@ -665,7 +668,8 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z SendPosition(); } - EQApplicationPacket* outapp = new EQApplicationPacket(OP_RequestClientZoneChange, sizeof(RequestClientZoneChange_Struct)); + auto outapp = + new EQApplicationPacket(OP_RequestClientZoneChange, sizeof(RequestClientZoneChange_Struct)); RequestClientZoneChange_Struct* gmg = (RequestClientZoneChange_Struct*) outapp->pBuffer; gmg->zone_id = zoneID; From 615158e701501f94bbaf5f4fb849e0b40860cd4f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 25 May 2016 16:29:39 -0400 Subject: [PATCH 121/693] Make EQStreamIdentifier::Record ctor take advantage of move semantics [clang-tidy] --- common/eq_stream_ident.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/eq_stream_ident.cpp b/common/eq_stream_ident.cpp index 89df25ab2..cb0810467 100644 --- a/common/eq_stream_ident.cpp +++ b/common/eq_stream_ident.cpp @@ -1,3 +1,5 @@ +#include + #include "global_define.h" #include "eqemu_logsys.h" #include "eq_stream_ident.h" @@ -156,7 +158,7 @@ EQStreamInterface *EQStreamIdentifier::PopIdentified() { } EQStreamIdentifier::Record::Record(std::shared_ptr s) -: stream(s), +: stream(std::move(s)), expire(STREAM_IDENT_WAIT_MS) { } From a715accc5f6349fb73b04fa641e0a1154acbfbb2 Mon Sep 17 00:00:00 2001 From: phredi Date: Wed, 25 May 2016 17:35:47 -0500 Subject: [PATCH 122/693] reording includes fixes patch file location problem --- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/patches/sod.cpp | 2 +- common/patches/sof.cpp | 2 +- common/patches/titanium.cpp | 2 +- common/patches/uf.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index c0be7f070..385a79f4f 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -18,6 +18,7 @@ */ #include "../global_define.h" +#include "../eqemu_config.h" #include "../eqemu_logsys.h" #include "rof.h" #include "../opcodemgr.h" @@ -31,7 +32,6 @@ #include "../item.h" #include "rof_structs.h" #include "../rulesys.h" -#include "../eqemu_config.h" #include #include diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 8e38d81f2..0b3c3632a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -18,6 +18,7 @@ */ #include "../global_define.h" +#include "../eqemu_config.h" #include "../eqemu_logsys.h" #include "rof2.h" #include "../opcodemgr.h" @@ -31,7 +32,6 @@ #include "../item.h" #include "rof2_structs.h" #include "../rulesys.h" -#include "../eqemu_config.h" #include #include diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 244e63c71..3c98617db 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -18,6 +18,7 @@ */ #include "../global_define.h" +#include "../eqemu_config.h" #include "../eqemu_logsys.h" #include "sod.h" #include "../opcodemgr.h" @@ -31,7 +32,6 @@ #include "../item.h" #include "sod_structs.h" #include "../rulesys.h" -#include "../eqemu_config.h" #include #include diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 5ea473904..b17a9b241 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -18,6 +18,7 @@ */ #include "../global_define.h" +#include "../eqemu_config.h" #include "../eqemu_logsys.h" #include "sof.h" #include "../opcodemgr.h" @@ -31,7 +32,6 @@ #include "../item.h" #include "sof_structs.h" #include "../rulesys.h" -#include "../eqemu_config.h" #include #include diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 3cde09beb..d18f752be 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -18,6 +18,7 @@ */ #include "../global_define.h" +#include "../eqemu_config.h" #include "../eqemu_logsys.h" #include "titanium.h" #include "../opcodemgr.h" @@ -30,7 +31,6 @@ #include "../misc_functions.h" #include "../string_util.h" #include "../item.h" -#include "../eqemu_config.h" #include "titanium_structs.h" #include diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index d07914cb8..dc31fc1f8 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -18,6 +18,7 @@ */ #include "../global_define.h" +#include "../eqemu_config.h" #include "../eqemu_logsys.h" #include "uf.h" #include "../opcodemgr.h" @@ -31,7 +32,6 @@ #include "../item.h" #include "uf_structs.h" #include "../rulesys.h" -#include "../eqemu_config.h" #include #include From 71f128731fa059f9e815a241133c75fb46952d45 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 25 May 2016 18:50:26 -0400 Subject: [PATCH 123/693] Renamed and moved SkillUseTypes enumeration to EQEmu::skills::SkillType; eq_dictionary work --- changelog.txt | 4 + common/CMakeLists.txt | 2 + common/emu_constants.cpp | 238 -------- common/emu_constants.h | 45 +- common/emu_limits.cpp | 18 + common/emu_limits.h | 56 ++ common/eq_constants.h | 2 +- common/eq_limits.cpp | 907 +++++++++++++---------------- common/eq_limits.h | 55 +- common/eq_packet_structs.h | 27 +- common/item.cpp | 4 +- common/item.h | 2 + common/patches/rof.cpp | 74 +-- common/patches/rof2.cpp | 78 +-- common/patches/rof2_limits.cpp | 248 ++++++++ common/patches/rof2_limits.h | 392 ++++++++----- common/patches/rof2_structs.h | 10 +- common/patches/rof_limits.cpp | 244 ++++++++ common/patches/rof_limits.h | 382 +++++++----- common/patches/rof_structs.h | 10 +- common/patches/sod.cpp | 42 +- common/patches/sod_limits.cpp | 237 ++++++++ common/patches/sod_limits.h | 402 ++++++++----- common/patches/sod_structs.h | 6 +- common/patches/sof.cpp | 42 +- common/patches/sof_limits.cpp | 237 ++++++++ common/patches/sof_limits.h | 402 ++++++++----- common/patches/sof_structs.h | 6 +- common/patches/titanium.cpp | 20 +- common/patches/titanium_limits.cpp | 235 ++++++++ common/patches/titanium_limits.h | 400 ++++++++----- common/patches/titanium_structs.h | 6 +- common/patches/uf.cpp | 42 +- common/patches/uf_limits.cpp | 237 ++++++++ common/patches/uf_limits.h | 403 ++++++++----- common/patches/uf_structs.h | 6 +- common/say_link.cpp | 1 + common/shareddb.cpp | 18 +- common/shareddb.h | 4 +- common/skills.cpp | 178 +++++- common/skills.h | 117 ++-- common/spdat.h | 2 +- shared_memory/skill_caps.cpp | 2 +- tests/skills_util_test.h | 8 +- world/client.cpp | 50 +- world/worlddb.cpp | 6 +- zone/attack.cpp | 178 +++--- zone/beacon.h | 4 +- zone/bonuses.cpp | 142 ++--- zone/bot.cpp | 207 +++---- zone/bot.h | 20 +- zone/bot_command.cpp | 11 +- zone/client.cpp | 107 ++-- zone/client.h | 41 +- zone/client_mods.cpp | 42 +- zone/client_packet.cpp | 116 ++-- zone/client_process.cpp | 52 +- zone/command.cpp | 37 +- zone/common.h | 32 +- zone/corpse.cpp | 5 +- zone/corpse.h | 4 +- zone/doors.cpp | 6 +- zone/encounter.h | 4 +- zone/entity.cpp | 6 +- zone/forage.cpp | 12 +- zone/lua_client.cpp | 16 +- zone/lua_mob.cpp | 34 +- zone/merc.cpp | 38 +- zone/merc.h | 14 +- zone/mob.cpp | 114 ++-- zone/mob.h | 51 +- zone/mod_functions.cpp | 10 +- zone/npc.cpp | 19 +- zone/npc.h | 12 +- zone/object.h | 2 +- zone/perl_client.cpp | 16 +- zone/perl_mob.cpp | 14 +- zone/questmgr.cpp | 15 +- zone/special_attacks.cpp | 414 +++++++------ zone/spell_effects.cpp | 27 +- zone/spells.cpp | 84 +-- zone/tasks.cpp | 1 + zone/titles.cpp | 6 +- zone/tradeskills.cpp | 165 +++--- zone/tune.cpp | 74 +-- zone/zonedb.h | 2 +- 86 files changed, 4987 insertions(+), 3074 deletions(-) create mode 100644 common/emu_limits.cpp create mode 100644 common/emu_limits.h diff --git a/changelog.txt b/changelog.txt index 800eefa33..63a2a8908 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/25/2016 == +Uleat: Renamed and moved enumeration SkillUseTypes to EQEmu::skill::SkillType - added class EQEmu::SkillProfile, though not implemented at this time +Uleat: Some more work on eq_dictionary + == 05/21/2016 == Uleat: Moved struct Item_Struct into namespace EQEmu along with associated enumerations - enumerations into namespace EQEmu::item (run shared_memory) Uleat: Fixed a few possible crash points in linux builds associated with augments/ornamentations diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 5c4f364a9..034cf415a 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -15,6 +15,7 @@ SET(common_sources deity.cpp emu_constants.cpp emu_legacy.cpp + emu_limits.cpp emu_opcodes.cpp emu_tcp_connection.cpp emu_tcp_server.cpp @@ -121,6 +122,7 @@ SET(common_headers deity.h emu_constants.h emu_legacy.h + emu_limits.h emu_opcodes.h emu_oplist.h emu_tcp_connection.h diff --git a/common/emu_constants.cpp b/common/emu_constants.cpp index 8085f3004..a8fa73d1c 100644 --- a/common/emu_constants.cpp +++ b/common/emu_constants.cpp @@ -18,241 +18,3 @@ */ #include "emu_constants.h" -#include "string_util.h" - - -uint16 EQEmu::constants::InventoryTypeSize(int16 type_index) -{ - switch (type_index) { - case legacy::TypePossessions: - return legacy::TYPE_POSSESSIONS_SIZE; - case legacy::TypeBank: - return legacy::TYPE_BANK_SIZE; - case legacy::TypeSharedBank: - return legacy::TYPE_SHARED_BANK_SIZE; - case legacy::TypeTrade: - return legacy::TYPE_TRADE_SIZE; - case legacy::TypeWorld: - return legacy::TYPE_WORLD_SIZE; - case legacy::TypeLimbo: - return legacy::TYPE_LIMBO_SIZE; - case legacy::TypeTribute: - return legacy::TYPE_TRIBUTE_SIZE; - case legacy::TypeTrophyTribute: - return legacy::TYPE_TROPHY_TRIBUTE_SIZE; - case legacy::TypeGuildTribute: - return legacy::TYPE_GUILD_TRIBUTE_SIZE; - case legacy::TypeMerchant: - return legacy::TYPE_MERCHANT_SIZE; - case legacy::TypeDeleted: - return legacy::TYPE_DELETED_SIZE; - case legacy::TypeCorpse: - return legacy::TYPE_CORPSE_SIZE; - case legacy::TypeBazaar: - return legacy::TYPE_BAZAAR_SIZE; - case legacy::TypeInspect: - return legacy::TYPE_INSPECT_SIZE; - case legacy::TypeRealEstate: - return legacy::TYPE_REAL_ESTATE_SIZE; - case legacy::TypeViewMODPC: - return legacy::TYPE_VIEW_MOD_PC_SIZE; - case legacy::TypeViewMODBank: - return legacy::TYPE_VIEW_MOD_BANK_SIZE; - case legacy::TypeViewMODSharedBank: - return legacy::TYPE_VIEW_MOD_SHARED_BANK_SIZE; - case legacy::TypeViewMODLimbo: - return legacy::TYPE_VIEW_MOD_LIMBO_SIZE; - case legacy::TypeAltStorage: - return legacy::TYPE_ALT_STORAGE_SIZE; - case legacy::TypeArchived: - return legacy::TYPE_ARCHIVED_SIZE; - case legacy::TypeMail: - return legacy::TYPE_MAIL_SIZE; - case legacy::TypeGuildTrophyTribute: - return legacy::TYPE_GUILD_TROPHY_TRIBUTE_SIZE; - case legacy::TypeKrono: - return legacy::TYPE_KRONO_SIZE; - case legacy::TypeOther: - return legacy::TYPE_OTHER_SIZE; - default: - return NOT_USED; - } -} - -/* -const char* EQEmu::constants::InventoryLocationName(Location_Struct location) -{ - // not ready for implementation... - std::string ret_str; - StringFormat(ret_str, "%s, %s, %s, %s", InventoryMapName(location.map), InventoryMainName(location.main), InventorySubName(location.sub), InventoryAugName(location.aug)); - return ret_str; -} -*/ - -const char* EQEmu::constants::InventoryTypeName(int16 type_index) -{ - switch (type_index) { - case INVALID_INDEX: - return "Invalid Type"; - case legacy::TypePossessions: - return "Possessions"; - case legacy::TypeBank: - return "Bank"; - case legacy::TypeSharedBank: - return "SharedBank"; - case legacy::TypeTrade: - return "Trade"; - case legacy::TypeWorld: - return "World"; - case legacy::TypeLimbo: - return "Limbo"; - case legacy::TypeTribute: - return "Tribute"; - case legacy::TypeTrophyTribute: - return "TrophyTribute"; - case legacy::TypeGuildTribute: - return "GuildTribute"; - case legacy::TypeMerchant: - return "Merchant"; - case legacy::TypeDeleted: - return "Deleted"; - case legacy::TypeCorpse: - return "Corpse"; - case legacy::TypeBazaar: - return "Bazaar"; - case legacy::TypeInspect: - return "Inspect"; - case legacy::TypeRealEstate: - return "RealEstate"; - case legacy::TypeViewMODPC: - return "ViewMODPC"; - case legacy::TypeViewMODBank: - return "ViewMODBank"; - case legacy::TypeViewMODSharedBank: - return "ViewMODSharedBank"; - case legacy::TypeViewMODLimbo: - return "ViewMODLimbo"; - case legacy::TypeAltStorage: - return "AltStorage"; - case legacy::TypeArchived: - return "Archived"; - case legacy::TypeMail: - return "Mail"; - case legacy::TypeGuildTrophyTribute: - return "GuildTrophyTribute"; - case legacy::TypeKrono: - return "Krono"; - case legacy::TypeOther: - return "Other"; - default: - return "Unknown Type"; - } -} - -const char* EQEmu::constants::InventorySlotName(int16 slot_index) -{ - switch (slot_index) { - case INVALID_INDEX: - return "Invalid Slot"; - case legacy::SlotCharm: - return "Charm"; - case legacy::SlotEar1: - return "Ear1"; - case legacy::SlotHead: - return "Head"; - case legacy::SlotFace: - return "Face"; - case legacy::SlotEar2: - return "Ear2"; - case legacy::SlotNeck: - return "Neck"; - case legacy::SlotShoulders: - return "Shoulders"; - case legacy::SlotArms: - return "Arms"; - case legacy::SlotBack: - return "Back"; - case legacy::SlotWrist1: - return "Wrist1"; - case legacy::SlotWrist2: - return "Wrist2"; - case legacy::SlotRange: - return "Range"; - case legacy::SlotHands: - return "Hands"; - case legacy::SlotPrimary: - return "Primary"; - case legacy::SlotSecondary: - return "Secondary"; - case legacy::SlotFinger1: - return "Finger1"; - case legacy::SlotFinger2: - return "Finger2"; - case legacy::SlotChest: - return "Chest"; - case legacy::SlotLegs: - return "Legs"; - case legacy::SlotFeet: - return "Feet"; - case legacy::SlotWaist: - return "Waist"; - case legacy::SlotPowerSource: - return "PowerSource"; - case legacy::SlotAmmo: - return "Ammo"; - case legacy::SlotGeneral1: - return "General1"; - case legacy::SlotGeneral2: - return "General2"; - case legacy::SlotGeneral3: - return "General3"; - case legacy::SlotGeneral4: - return "General4"; - case legacy::SlotGeneral5: - return "General5"; - case legacy::SlotGeneral6: - return "General6"; - case legacy::SlotGeneral7: - return "General7"; - case legacy::SlotGeneral8: - return "General8"; - /* - case legacy::SlotGeneral9: - return "General9"; - case legacy::SlotGeneral10: - return "General10"; - */ - case legacy::SlotCursor: - return "Cursor"; - default: - return "Unknown Slot"; - } -} - -const char* EQEmu::constants::InventorySubName(int16 sub_index) -{ - if (sub_index == INVALID_INDEX) - return "Invalid Sub"; - - if ((uint16)sub_index >= legacy::ITEM_CONTAINER_SIZE) - return "Unknown Sub"; - - static std::string ret_str; - ret_str = StringFormat("Container%i", (sub_index + 1)); // zero-based index..but, count starts at one - - return ret_str.c_str(); -} - -const char* EQEmu::constants::InventoryAugName(int16 aug_index) -{ - if (aug_index == INVALID_INDEX) - return "Invalid Aug"; - - if ((uint16)aug_index >= legacy::ITEM_COMMON_SIZE) - return "Unknown Aug"; - - static std::string ret_str; - ret_str = StringFormat("Augment%i", (aug_index + 1)); // zero-based index..but, count starts at one - - return ret_str.c_str(); -} diff --git a/common/emu_constants.h b/common/emu_constants.h index 6c7f3e962..5e279d21c 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -21,41 +21,32 @@ #define COMMON_EMU_CONSTANTS_H #include "eq_limits.h" -// (future use) -//using namespace RoF2::maps; // server inventory maps enumeration (code and database sync'd to reference) -//using namespace RoF::slots; // server possessions slots enumeration (code and database sync'd to reference) - #include "emu_legacy.h" #include "inventory_version.h" -#include "light_source.h" -#include "deity.h" -#include "say_link.h" +//#include "deity.h" +//#include "say_link.h" #include -// *** DO NOT CHANGE without a full understanding of the consequences..the server is set up to use these settings explicitly!! *** -// *** You will cause compilation failures and corrupt your database if partial or incorrect attempts to change them are made!! *** - -// Hard-coded values usually indicate that further research is needed and the values given are from the old (known) system - - namespace EQEmu { - // an immutable value is required to initialize arrays, etc... use this class as a repository for those + namespace inventory { + //using namespace RoF2::invtype; + //using namespace RoF2::invslot; + //using namespace RoF2::invbag; + //using namespace RoF2::invaug; + + } /*inventory*/ + namespace constants { - // database - static const EQEmu::versions::ClientVersion CharacterCreationClient = EQEmu::versions::ClientVersion::RoF2; - static const size_t CharacterCreationLimit = RoF2::consts::CHARACTER_CREATION_LIMIT; + const EQEmu::versions::ClientVersion CharacterCreationClient = EQEmu::versions::ClientVersion::RoF2; + const size_t CharacterCreationMax = RoF2::constants::CharacterCreationLimit; - // inventory - extern uint16 InventoryTypeSize(int16 type_index); - //extern const char* InventoryLocationName(Location_Struct location); - extern const char* InventoryTypeName(int16 type_index); - extern const char* InventorySlotName(int16 slot_index); - extern const char* InventorySubName(int16 sub_index); - extern const char* InventoryAugName(int16 aug_index); - } -} + const size_t SayLinkBodySize = RoF2::constants::SayLinkBodySize; -#endif /* COMMON_EMU_CONSTANTS_H */ + } /*constants*/ + +} /*EQEmu*/ + +#endif /*COMMON_EMU_CONSTANTS_H*/ diff --git a/common/emu_limits.cpp b/common/emu_limits.cpp new file mode 100644 index 000000000..64d038a54 --- /dev/null +++ b/common/emu_limits.cpp @@ -0,0 +1,18 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ diff --git a/common/emu_limits.h b/common/emu_limits.h new file mode 100644 index 000000000..e5b66faeb --- /dev/null +++ b/common/emu_limits.h @@ -0,0 +1,56 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_EMU_LIMITS_H +#define COMMON_EMU_LIMITS_H + +#include "types.h" + +#include + + +namespace EntityLimits +{ + namespace npc { + enum : int { Invalid = -1, Null, Safety }; + + enum : bool { False = false, True = true }; + } + + namespace merc { + enum : int { Invalid = -1, Null, Safety }; + + enum : bool { False = false, True = true }; + } + + namespace bot { + enum : int { Invalid = -1, Null, Safety }; + + enum : bool { False = false, True = true }; + } + + namespace pet { + enum : int { Invalid = -1, Null, Safety }; + + enum : bool { False = false, True = true }; + } + +}; /*EntityLimits*/ + +#endif /*COMMON_EMU_LIMITS_H*/ diff --git a/common/eq_constants.h b/common/eq_constants.h index 54f52620c..e23089ce6 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -399,7 +399,7 @@ static const uint8 DamageTypeUnknown = 0xFF; ** ** (indexed by 'Skill' of SkillUseTypes) */ -static const uint8 SkillDamageTypes[HIGHEST_SKILL + 1] = // change to _SkillServerArraySize once activated +static const uint8 SkillDamageTypes[EQEmu::skills::HIGHEST_SKILL + 1] = // change to _SkillServerArraySize once activated { /*1HBlunt*/ 0, /*1HSlashing*/ 1, diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 94d71a0c3..cd705add6 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -18,422 +18,381 @@ */ #include "emu_constants.h" +#include "emu_limits.h" -// database -size_t EQEmu::limits::CharacterCreationLimit(versions::ClientVersion client_version) +size_t EQEmu::constants::CharacterCreationLimit(versions::ClientVersion client_version) { static const size_t local[versions::InventoryVersionCount] = { -/*Unknown*/ NOT_USED, -/*Client62*/ NOT_USED, -/*Titanium*/ Titanium::consts::CHARACTER_CREATION_LIMIT, -/*SoF*/ SoF::consts::CHARACTER_CREATION_LIMIT, -/*SoD*/ SoD::consts::CHARACTER_CREATION_LIMIT, -/*UF*/ UF::consts::CHARACTER_CREATION_LIMIT, -/*RoF*/ RoF::consts::CHARACTER_CREATION_LIMIT, -/*RoF2*/ RoF2::consts::CHARACTER_CREATION_LIMIT, - -/*MobNPC*/ NOT_USED, -/*MobMerc*/ NOT_USED, -/*MobBot*/ NOT_USED, -/*MobPet*/ NOT_USED + ClientUnknown::Null, + Client62::Null, + Titanium::constants::CharacterCreationLimit, + SoF::constants::CharacterCreationLimit, + SoD::constants::CharacterCreationLimit, + UF::constants::CharacterCreationLimit, + RoF::constants::CharacterCreationLimit, + RoF2::constants::CharacterCreationLimit, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }; return local[static_cast(versions::ValidateClientVersion(client_version))]; } -// inventory -uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_version, int16 inv_type) +uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_version, int16 inv_type) { - // not all maps will have an instantiated container..some are references for queue generators (i.e., bazaar, mail, etc...) - // a zero '0' indicates a needed value..otherwise, change to '_NOTUSED' for a null value so indices requiring research can be identified - // ALL of these values need to be verified before pushing to live - // - // make sure that you transcribe the actual value from 'defaults' to here before updating or client crashes will ensue..and/or... - // insert older clients inside of the progression of client order - // - // TYPE_POSSESSIONS_SIZE does not reflect all actual _constants size due to bitmask-use compatibility - // - // when setting NPC-based values, try to adhere to an constants:: or NOT_USED value to avoid unnecessary issues - static const uint16 local[legacy::TypeCount][versions::InventoryVersionCount] = { - // server and database are sync'd to current TypePossessions's client as set in 'using namespace RoF::slots;' and - // 'constants::TYPE_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() - // for partial range validation checks and 'constants::TYPE_POSSESSIONS_SIZE' for full range iterations { // local[TypePossessions] -/*Unknown*/ NOT_USED, -/*62*/ legacy::TYPE_POSSESSIONS_SIZE, -/*Titanium*/ legacy::TYPE_POSSESSIONS_SIZE, -/*SoF*/ legacy::TYPE_POSSESSIONS_SIZE, -/*SoD*/ legacy::TYPE_POSSESSIONS_SIZE, -/*Underfoot*/ legacy::TYPE_POSSESSIONS_SIZE, -/*RoF*/ legacy::TYPE_POSSESSIONS_SIZE, -/*RoF2*/ legacy::TYPE_POSSESSIONS_SIZE, - -/*NPC*/ legacy::TYPE_POSSESSIONS_SIZE, -/*Merc*/ legacy::TYPE_POSSESSIONS_SIZE, -/*Bot*/ legacy::TYPE_POSSESSIONS_SIZE, -/*Pet*/ legacy::TYPE_POSSESSIONS_SIZE + ClientUnknown::Null, + Client62::Null, + legacy::TYPE_POSSESSIONS_SIZE, + legacy::TYPE_POSSESSIONS_SIZE, + legacy::TYPE_POSSESSIONS_SIZE, + legacy::TYPE_POSSESSIONS_SIZE, + legacy::TYPE_POSSESSIONS_SIZE, + legacy::TYPE_POSSESSIONS_SIZE, + legacy::TYPE_POSSESSIONS_SIZE, + legacy::TYPE_POSSESSIONS_SIZE, + legacy::TYPE_POSSESSIONS_SIZE, + legacy::TYPE_POSSESSIONS_SIZE }, { // local[TypeBank] -/*Unknown*/ NOT_USED, -/*62*/ NOT_USED, -/*Titanium*/ Titanium::consts::TYPE_BANK_SIZE, -/*SoF*/ legacy::TYPE_BANK_SIZE, -/*SoD*/ legacy::TYPE_BANK_SIZE, -/*Underfoot*/ legacy::TYPE_BANK_SIZE, -/*RoF*/ legacy::TYPE_BANK_SIZE, -/*RoF2*/ legacy::TYPE_BANK_SIZE, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED + ClientUnknown::Null, + Client62::Null, + Titanium::invtype::InvTypeBankSize, + legacy::TYPE_BANK_SIZE, + legacy::TYPE_BANK_SIZE, + legacy::TYPE_BANK_SIZE, + legacy::TYPE_BANK_SIZE, + legacy::TYPE_BANK_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeSharedBank] -/*Unknown*/ NOT_USED, -/*62*/ legacy::TYPE_SHARED_BANK_SIZE, -/*Titanium*/ legacy::TYPE_SHARED_BANK_SIZE, -/*SoF*/ legacy::TYPE_SHARED_BANK_SIZE, -/*SoD*/ legacy::TYPE_SHARED_BANK_SIZE, -/*Underfoot*/ legacy::TYPE_SHARED_BANK_SIZE, -/*RoF*/ legacy::TYPE_SHARED_BANK_SIZE, -/*RoF2*/ legacy::TYPE_SHARED_BANK_SIZE, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED + ClientUnknown::Null, + Client62::Null, + legacy::TYPE_SHARED_BANK_SIZE, + legacy::TYPE_SHARED_BANK_SIZE, + legacy::TYPE_SHARED_BANK_SIZE, + legacy::TYPE_SHARED_BANK_SIZE, + legacy::TYPE_SHARED_BANK_SIZE, + legacy::TYPE_SHARED_BANK_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeTrade] -/*Unknown*/ NOT_USED, -/*62*/ legacy::TYPE_TRADE_SIZE, -/*Titanium*/ legacy::TYPE_TRADE_SIZE, -/*SoF*/ legacy::TYPE_TRADE_SIZE, -/*SoD*/ legacy::TYPE_TRADE_SIZE, -/*Underfoot*/ legacy::TYPE_TRADE_SIZE, -/*RoF*/ legacy::TYPE_TRADE_SIZE, -/*RoF2*/ legacy::TYPE_TRADE_SIZE, - -/*NPC*/ 4, -/*Merc*/ 4, -/*Bot*/ legacy::TYPE_TRADE_SIZE, // client thinks this is another client -/*Pet*/ 4 + ClientUnknown::Null, + Client62::Null, + legacy::TYPE_TRADE_SIZE, + legacy::TYPE_TRADE_SIZE, + legacy::TYPE_TRADE_SIZE, + legacy::TYPE_TRADE_SIZE, + legacy::TYPE_TRADE_SIZE, + legacy::TYPE_TRADE_SIZE, + 4, + 4, + legacy::TYPE_TRADE_SIZE, // client thinks this is another client + 4 }, { // local[TypeWorld] -/*Unknown*/ NOT_USED, -/*62*/ legacy::TYPE_WORLD_SIZE, -/*Titanium*/ legacy::TYPE_WORLD_SIZE, -/*SoF*/ legacy::TYPE_WORLD_SIZE, -/*SoD*/ legacy::TYPE_WORLD_SIZE, -/*Underfoot*/ legacy::TYPE_WORLD_SIZE, -/*RoF*/ legacy::TYPE_WORLD_SIZE, -/*RoF2*/ legacy::TYPE_WORLD_SIZE, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED + ClientUnknown::Null, + Client62::Null, + legacy::TYPE_WORLD_SIZE, + legacy::TYPE_WORLD_SIZE, + legacy::TYPE_WORLD_SIZE, + legacy::TYPE_WORLD_SIZE, + legacy::TYPE_WORLD_SIZE, + legacy::TYPE_WORLD_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeLimbo] -/*Unknown*/ NOT_USED, -/*62*/ legacy::TYPE_LIMBO_SIZE, -/*Titanium*/ legacy::TYPE_LIMBO_SIZE, -/*SoF*/ legacy::TYPE_LIMBO_SIZE, -/*SoD*/ legacy::TYPE_LIMBO_SIZE, -/*Underfoot*/ legacy::TYPE_LIMBO_SIZE, -/*RoF*/ legacy::TYPE_LIMBO_SIZE, -/*RoF2*/ legacy::TYPE_LIMBO_SIZE, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED + ClientUnknown::Null, + Client62::Null, + legacy::TYPE_LIMBO_SIZE, + legacy::TYPE_LIMBO_SIZE, + legacy::TYPE_LIMBO_SIZE, + legacy::TYPE_LIMBO_SIZE, + legacy::TYPE_LIMBO_SIZE, + legacy::TYPE_LIMBO_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeTribute] -/*Unknown*/ NOT_USED, -/*62*/ legacy::TYPE_TRIBUTE_SIZE, -/*Titanium*/ legacy::TYPE_TRIBUTE_SIZE, -/*SoF*/ legacy::TYPE_TRIBUTE_SIZE, -/*SoD*/ legacy::TYPE_TRIBUTE_SIZE, -/*Underfoot*/ legacy::TYPE_TRIBUTE_SIZE, -/*RoF*/ legacy::TYPE_TRIBUTE_SIZE, -/*RoF2*/ legacy::TYPE_TRIBUTE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + legacy::TYPE_TRIBUTE_SIZE, + legacy::TYPE_TRIBUTE_SIZE, + legacy::TYPE_TRIBUTE_SIZE, + legacy::TYPE_TRIBUTE_SIZE, + legacy::TYPE_TRIBUTE_SIZE, + legacy::TYPE_TRIBUTE_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeTrophyTribute] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ legacy::TYPE_TROPHY_TRIBUTE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_TROPHY_TRIBUTE_SIZE, + legacy::TYPE_TROPHY_TRIBUTE_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeGuildTribute] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_GUILD_TRIBUTE_SIZE, -/*RoF2*/ legacy::TYPE_GUILD_TRIBUTE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_GUILD_TRIBUTE_SIZE, + legacy::TYPE_GUILD_TRIBUTE_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeMerchant] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_MERCHANT_SIZE, -/*RoF2*/ legacy::TYPE_MERCHANT_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_MERCHANT_SIZE, + legacy::TYPE_MERCHANT_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeDeleted] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_DELETED_SIZE, -/*RoF2*/ legacy::TYPE_DELETED_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_DELETED_SIZE, + legacy::TYPE_DELETED_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeCorpse] -/*Unknown*/ NOT_USED, -/*62*/ NOT_USED, -/*Titanium*/ Titanium::consts::TYPE_CORPSE_SIZE, -/*SoF*/ SoF::consts::TYPE_CORPSE_SIZE, -/*SoD*/ SoD::consts::TYPE_CORPSE_SIZE, -/*Underfoot*/ UF::consts::TYPE_CORPSE_SIZE, -/*RoF*/ RoF::consts::TYPE_CORPSE_SIZE, -/*RoF2*/ RoF2::consts::TYPE_CORPSE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::invtype::InvTypeCorpseSize, + SoF::invtype::InvTypeCorpseSize, + SoD::invtype::InvTypeCorpseSize, + UF::invtype::InvTypeCorpseSize, + RoF::invtype::InvTypeCorpseSize, + RoF2::invtype::InvTypeCorpseSize, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeBazaar] -/*Unknown*/ NOT_USED, -/*62*/ legacy::TYPE_BAZAAR_SIZE, -/*Titanium*/ legacy::TYPE_BAZAAR_SIZE, -/*SoF*/ legacy::TYPE_BAZAAR_SIZE, -/*SoD*/ legacy::TYPE_BAZAAR_SIZE, -/*Underfoot*/ legacy::TYPE_BAZAAR_SIZE, -/*RoF*/ legacy::TYPE_BAZAAR_SIZE, -/*RoF2*/ legacy::TYPE_BAZAAR_SIZE, - -/*NPC*/ 0, // this may need to be 'legacy::TYPE_BAZAAR_SIZE' if offline client traders respawn as an npc -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + legacy::TYPE_BAZAAR_SIZE, + legacy::TYPE_BAZAAR_SIZE, + legacy::TYPE_BAZAAR_SIZE, + legacy::TYPE_BAZAAR_SIZE, + legacy::TYPE_BAZAAR_SIZE, + legacy::TYPE_BAZAAR_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeInspect] -/*Unknown*/ NOT_USED, -/*62*/ NOT_USED, -/*Titanium*/ Titanium::consts::TYPE_INSPECT_SIZE, -/*SoF*/ SoF::consts::TYPE_INSPECT_SIZE, -/*SoD*/ SoD::consts::TYPE_INSPECT_SIZE, -/*Underfoot*/ UF::consts::TYPE_INSPECT_SIZE, -/*RoF*/ RoF::consts::TYPE_INSPECT_SIZE, -/*RoF2*/ RoF2::consts::TYPE_INSPECT_SIZE, - -/*NPC*/ NOT_USED, -/*Merc*/ NOT_USED, -/*Bot*/ NOT_USED, -/*Pet*/ NOT_USED + ClientUnknown::Null, + Client62::Null, + Titanium::invtype::InvTypeInspectSize, + SoF::invtype::InvTypeInspectSize, + SoD::invtype::InvTypeInspectSize, + UF::invtype::InvTypeInspectSize, + RoF::invtype::InvTypeInspectSize, + RoF2::invtype::InvTypeInspectSize, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeRealEstate] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_REAL_ESTATE_SIZE, -/*RoF2*/ legacy::TYPE_REAL_ESTATE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_REAL_ESTATE_SIZE, + legacy::TYPE_REAL_ESTATE_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeViewMODPC] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_VIEW_MOD_PC_SIZE, -/*RoF2*/ legacy::TYPE_VIEW_MOD_PC_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_VIEW_MOD_PC_SIZE, + legacy::TYPE_VIEW_MOD_PC_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeViewMODBank] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_VIEW_MOD_BANK_SIZE, -/*RoF2*/ legacy::TYPE_VIEW_MOD_BANK_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_VIEW_MOD_BANK_SIZE, + legacy::TYPE_VIEW_MOD_BANK_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeViewMODSharedBank] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_VIEW_MOD_SHARED_BANK_SIZE, -/*RoF2*/ legacy::TYPE_VIEW_MOD_SHARED_BANK_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_VIEW_MOD_SHARED_BANK_SIZE, + legacy::TYPE_VIEW_MOD_SHARED_BANK_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeViewMODLimbo] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_VIEW_MOD_LIMBO_SIZE, -/*RoF2*/ legacy::TYPE_VIEW_MOD_LIMBO_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_VIEW_MOD_LIMBO_SIZE, + legacy::TYPE_VIEW_MOD_LIMBO_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeAltStorage] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_ALT_STORAGE_SIZE, -/*RoF2*/ legacy::TYPE_ALT_STORAGE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_ALT_STORAGE_SIZE, + legacy::TYPE_ALT_STORAGE_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeArchived] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_ARCHIVED_SIZE, -/*RoF2*/ legacy::TYPE_ARCHIVED_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_ARCHIVED_SIZE, + legacy::TYPE_ARCHIVED_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeMail] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_MAIL_SIZE, -/*RoF2*/ legacy::TYPE_MAIL_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_MAIL_SIZE, + legacy::TYPE_MAIL_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeGuildTrophyTribute] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ legacy::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, + legacy::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeKrono] -/*Unknown*/ NOT_USED, -/*62*/ NOT_USED, -/*Titanium*/ NOT_USED, -/*SoF*/ NOT_USED, -/*SoD*/ NOT_USED, -/*Underfoot*/ NOT_USED, -/*RoF*/ legacy::TYPE_KRONO_SIZE, -/*RoF2*/ legacy::TYPE_KRONO_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_KRONO_SIZE, + legacy::TYPE_KRONO_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }, { // local[TypeOther] -/*Unknown*/ NOT_USED, -/*62*/ 0, -/*Titanium*/ 0, -/*SoF*/ 0, -/*SoD*/ 0, -/*Underfoot*/ 0, -/*RoF*/ legacy::TYPE_OTHER_SIZE, -/*RoF2*/ legacy::TYPE_OTHER_SIZE, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + legacy::TYPE_OTHER_SIZE, + legacy::TYPE_OTHER_SIZE, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null } }; @@ -443,201 +402,123 @@ uint16 EQEmu::limits::InventoryTypeSize(versions::InventoryVersion inventory_ver return NOT_USED; } -uint64 EQEmu::limits::PossessionsBitmask(versions::InventoryVersion inventory_version) +uint64 EQEmu::inventory::PossessionsBitmask(versions::InventoryVersion inventory_version) { - // these are for the new inventory system (RoF)..not the current (Ti) one... - // 0x0000000000200000 is SlotPowerSource (SoF+) - // 0x0000000080000000 is SlotGeneral9 (RoF+) - // 0x0000000100000000 is SlotGeneral10 (RoF+) - static const uint64 local[versions::InventoryVersionCount] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x000000027FDFFFFF, -/*Titanium*/ 0x000000027FDFFFFF, -/*SoF*/ 0x000000027FFFFFFF, -/*SoD*/ 0x000000027FFFFFFF, -/*Underfoot*/ 0x000000027FFFFFFF, -/*RoF*/ 0x00000003FFFFFFFF, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 + ClientUnknown::Null, + Client62::Null, + 0x000000027FDFFFFF, + 0x000000027FFFFFFF, + 0x000000027FFFFFFF, + 0x000000027FFFFFFF, + 0x00000003FFFFFFFF, + 0x00000003FFFFFFFF, + EntityLimits::npc::Null, + EntityLimits::merc::Null, + EntityLimits::bot::Null, + EntityLimits::pet::Null }; return NOT_USED; //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -uint64 EQEmu::limits::EquipmentBitmask(versions::InventoryVersion inventory_version) -{ - static const uint64 local[versions::InventoryVersionCount] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x00000000005FFFFF, -/*Titanium*/ 0x00000000005FFFFF, -/*SoF*/ 0x00000000007FFFFF, -/*SoD*/ 0x00000000007FFFFF, -/*Underfoot*/ 0x00000000007FFFFF, -/*RoF*/ 0x00000000007FFFFF, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }; - - return NOT_USED; - //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; -} - -uint64 EQEmu::limits::GeneralBitmask(versions::InventoryVersion inventory_version) -{ - static const uint64 local[versions::InventoryVersionCount] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x000000007F800000, -/*Titanium*/ 0x000000007F800000, -/*SoF*/ 0x000000007F800000, -/*SoD*/ 0x000000007F800000, -/*Underfoot*/ 0x000000007F800000, -/*RoF*/ 0x00000001FF800000, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }; - - return NOT_USED; - //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; -} - -uint64 EQEmu::limits::CursorBitmask(versions::InventoryVersion inventory_version) -{ - static const uint64 local[versions::InventoryVersionCount] = { -/*Unknown*/ NOT_USED, -/*62*/ 0x0000000200000000, -/*Titanium*/ 0x0000000200000000, -/*SoF*/ 0x0000000200000000, -/*SoD*/ 0x0000000200000000, -/*Underfoot*/ 0x0000000200000000, -/*RoF*/ 0x0000000200000000, -/*RoF2*/ 0, - -/*NPC*/ 0, -/*Merc*/ 0, -/*Bot*/ 0, -/*Pet*/ 0 - }; - - return NOT_USED; - //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; -} - -bool EQEmu::limits::AllowEmptyBagInBag(versions::InventoryVersion inventory_version) +bool EQEmu::inventory::AllowEmptyBagInBag(versions::InventoryVersion inventory_version) { static const bool local[versions::InventoryVersionCount] = { -/*Unknown*/ false, -/*62*/ false, -/*Titanium*/ Titanium::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*SoF*/ SoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*SoD*/ SoD::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*Underfoot*/ UF::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*RoF*/ RoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*RoF2*/ RoF2::limits::ALLOWS_EMPTY_BAG_IN_BAG, - -/*NPC*/ false, -/*Merc*/ false, -/*Bot*/ false, -/*Pet*/ false + ClientUnknown::False, + Client62::False, + Titanium::behavior::AllowEmptyBagInBag, + SoF::behavior::AllowEmptyBagInBag, + SoD::behavior::AllowEmptyBagInBag, + UF::behavior::AllowEmptyBagInBag, + RoF::behavior::AllowEmptyBagInBag, + RoF2::behavior::AllowEmptyBagInBag, + EntityLimits::npc::False, + EntityLimits::merc::False, + EntityLimits::bot::False, + EntityLimits::pet::False }; - return false; // not implemented + return false; //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -bool EQEmu::limits::AllowClickCastFromBag(versions::InventoryVersion inventory_version) +bool EQEmu::inventory::AllowClickCastFromBag(versions::InventoryVersion inventory_version) { static const bool local[versions::InventoryVersionCount] = { -/*Unknown*/ false, -/*62*/ false, -/*Titanium*/ Titanium::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*SoF*/ SoF::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*SoD*/ SoD::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*Underfoot*/ UF::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*RoF*/ RoF::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*RoF2*/ RoF2::limits::ALLOWS_CLICK_CAST_FROM_BAG, - -/*NPC*/ false, -/*Merc*/ false, -/*Bot*/ false, -/*Pet*/ false + ClientUnknown::False, + Client62::False, + Titanium::behavior::AllowClickCastFromBag, + SoF::behavior::AllowClickCastFromBag, + SoD::behavior::AllowClickCastFromBag, + UF::behavior::AllowClickCastFromBag, + RoF::behavior::AllowClickCastFromBag, + RoF2::behavior::AllowClickCastFromBag, + EntityLimits::npc::False, + EntityLimits::merc::False, + EntityLimits::bot::False, + EntityLimits::pet::False }; return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -// items -uint16 EQEmu::limits::ItemCommonSize(versions::InventoryVersion inventory_version) +uint16 EQEmu::inventory::ItemAugSize(versions::InventoryVersion inventory_version) { static const uint16 local[versions::InventoryVersionCount] = { -/*Unknown*/ NOT_USED, -/*62*/ legacy::ITEM_COMMON_SIZE, -/*Titanium*/ legacy::ITEM_COMMON_SIZE, -/*SoF*/ legacy::ITEM_COMMON_SIZE, -/*SoD*/ legacy::ITEM_COMMON_SIZE, -/*Underfoot*/ legacy::ITEM_COMMON_SIZE, -/*RoF*/ legacy::ITEM_COMMON_SIZE, -/*RoF2*/ legacy::ITEM_COMMON_SIZE, - -/*NPC*/ legacy::ITEM_COMMON_SIZE, -/*Merc*/ legacy::ITEM_COMMON_SIZE, -/*Bot*/ legacy::ITEM_COMMON_SIZE, -/*Pet*/ legacy::ITEM_COMMON_SIZE + ClientUnknown::Null, + Client62::Null, + legacy::ITEM_COMMON_SIZE, + legacy::ITEM_COMMON_SIZE, + legacy::ITEM_COMMON_SIZE, + legacy::ITEM_COMMON_SIZE, + legacy::ITEM_COMMON_SIZE, + legacy::ITEM_COMMON_SIZE, + legacy::ITEM_COMMON_SIZE, + legacy::ITEM_COMMON_SIZE, + legacy::ITEM_COMMON_SIZE, + legacy::ITEM_COMMON_SIZE }; return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -uint16 EQEmu::limits::ItemContainerSize(versions::InventoryVersion inventory_version) +uint16 EQEmu::inventory::ItemBagSize(versions::InventoryVersion inventory_version) { static const uint16 local[versions::InventoryVersionCount] = { -/*Unknown*/ NOT_USED, -/*62*/ legacy::ITEM_CONTAINER_SIZE, -/*Titanium*/ legacy::ITEM_CONTAINER_SIZE, -/*SoF*/ legacy::ITEM_CONTAINER_SIZE, -/*SoD*/ legacy::ITEM_CONTAINER_SIZE, -/*Underfoot*/ legacy::ITEM_CONTAINER_SIZE, -/*RoF*/ legacy::ITEM_CONTAINER_SIZE, -/*RoF2*/ legacy::ITEM_CONTAINER_SIZE, - -/*NPC*/ legacy::ITEM_CONTAINER_SIZE, -/*Merc*/ legacy::ITEM_CONTAINER_SIZE, -/*Bot*/ legacy::ITEM_CONTAINER_SIZE, -/*Pet*/ legacy::ITEM_CONTAINER_SIZE + ClientUnknown::Null, + Client62::Null, + legacy::ITEM_CONTAINER_SIZE, + legacy::ITEM_CONTAINER_SIZE, + legacy::ITEM_CONTAINER_SIZE, + legacy::ITEM_CONTAINER_SIZE, + legacy::ITEM_CONTAINER_SIZE, + legacy::ITEM_CONTAINER_SIZE, + legacy::ITEM_CONTAINER_SIZE, + legacy::ITEM_CONTAINER_SIZE, + legacy::ITEM_CONTAINER_SIZE, + legacy::ITEM_CONTAINER_SIZE }; return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -bool EQEmu::limits::CoinHasWeight(versions::InventoryVersion inventory_version) +bool EQEmu::profile::CoinHasWeight(versions::InventoryVersion inventory_version) { static const bool local[versions::InventoryVersionCount] = { -/*Unknown*/ true, -/*62*/ true, -/*Titanium*/ Titanium::limits::COIN_HAS_WEIGHT, -/*SoF*/ SoF::limits::COIN_HAS_WEIGHT, -/*SoD*/ SoD::limits::COIN_HAS_WEIGHT, -/*Underfoot*/ UF::limits::COIN_HAS_WEIGHT, -/*RoF*/ RoF::limits::COIN_HAS_WEIGHT, -/*RoF2*/ RoF::limits::COIN_HAS_WEIGHT, - -/*NPC*/ true, -/*Merc*/ true, -/*Bot*/ true, -/*Pet*/ true + ClientUnknown::True, + Client62::True, + Titanium::behavior::CoinHasWeight, + SoF::behavior::CoinHasWeight, + SoD::behavior::CoinHasWeight, + UF::behavior::CoinHasWeight, + RoF::behavior::CoinHasWeight, + RoF::behavior::CoinHasWeight, + EntityLimits::npc::True, + EntityLimits::merc::True, + EntityLimits::bot::True, + EntityLimits::pet::True }; return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; diff --git a/common/eq_limits.h b/common/eq_limits.h index eb9c983f0..d6b03d070 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -22,7 +22,7 @@ #include "types.h" #include "eq_constants.h" -#include "inventory_version.h" // inv2 watch +#include "inventory_version.h" #include "../common/patches/titanium_limits.h" #include "../common/patches/sof_limits.h" #include "../common/patches/sod_limits.h" @@ -31,35 +31,50 @@ #include "../common/patches/rof2_limits.h" -// *** DO NOT CHANGE without a full understanding of the consequences..the server is set up to use these settings explicitly!! *** -// *** You will cause compilation failures and corrupt your database if partial or incorrect attempts to change them are made!! *** - -// Hard-coded values usually indicate that further research is needed and the values given are from the old (known) system - - namespace EQEmu { - namespace limits { - // database + namespace constants { extern size_t CharacterCreationLimit(versions::ClientVersion client_version); - // inventory + } /*constants*/ + + namespace inventory { extern uint16 InventoryTypeSize(versions::InventoryVersion inventory_version, int16 inv_type); extern uint64 PossessionsBitmask(versions::InventoryVersion inventory_version); - extern uint64 EquipmentBitmask(versions::InventoryVersion inventory_version); - extern uint64 GeneralBitmask(versions::InventoryVersion inventory_version); - extern uint64 CursorBitmask(versions::InventoryVersion inventory_version); extern bool AllowEmptyBagInBag(versions::InventoryVersion inventory_version); extern bool AllowClickCastFromBag(versions::InventoryVersion inventory_version); - // items - extern uint16 ItemCommonSize(versions::InventoryVersion inventory_version); - extern uint16 ItemContainerSize(versions::InventoryVersion inventory_version); + extern uint16 ItemAugSize(versions::InventoryVersion inventory_version); + extern uint16 ItemBagSize(versions::InventoryVersion inventory_version); - // player profile + extern bool ConcatenateInvTypeLimbo(versions::InventoryVersion inventory_version); + + extern bool AllowOverLevelEquipment(versions::InventoryVersion inventory_version); + + } /*inventory*/ + + namespace profile { extern bool CoinHasWeight(versions::InventoryVersion inventory_version); - } -} -#endif /* COMMON_EQ_LIMITS_H */ + } /*profile*/ + +} /*EQEmu*/ + +namespace ClientUnknown +{ + enum : int { Invalid = -1, Null, Safety }; + + enum : bool { False = false, True = true }; + +} /*ClientUnknown*/ + +namespace Client62 +{ + enum : int { Invalid = -1, Null, Safety }; + + enum : bool { False = false, True = true }; + +} /*Client62*/ + +#endif /*COMMON_EQ_LIMITS_H*/ diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 0075f0cf0..0434e8947 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1517,17 +1517,38 @@ struct ExpUpdate_Struct enum ItemPacketType { ItemPacketViewLink = 0x00, + ItemPacketMerchant = 0x64, ItemPacketTradeView = 0x65, ItemPacketLoot = 0x66, ItemPacketTrade = 0x67, ItemPacketCharInventory = 0x69, ItemPacketSummonItem = 0x6A, - ItemPacketTributeItem = 0x6C, - ItemPacketMerchant = 0x64, ItemPacketWorldContainer = 0x6B, - ItemPacketCharmUpdate = 0x6E, + ItemPacketTributeItem = 0x6C, + ItemPacketGuildTribute = 0x6D, + ItemPacketCharmUpdate = 0x6E, // noted as incorrect ItemPacketInvalid = 0xFF }; + +//enum ItemPacketType +//{ +// ItemPacketMerchant = /*100*/ 0x64, // Titanium+ +// ItemPacketTradeView = /*101*/ 0x65, +// ItemPacketLoot = /*102*/ 0x66, +// ItemPacketTrade = /*103*/ 0x67, +// ItemPacketCharInventory = /*105*/ 0x69, +// ItemPacketLimbo = /*106*/ 0x6A, // name change +// ItemPacketWorldContainer = /*107*/ 0x6B, +// ItemPacketTributeItem = /*108*/ 0x6C, +// ItemPacketGuildTribute = /*109*/ 0x6D, // missing from EQEmu +// ItemPacket10 = /*110*/ 0x6E, +// ItemPacket11 = /*111*/ 0x6F, // UF+ (equipment slots only) (RoF+ checks '(WORD*)slot + 4 != -1' [(WORD*)]slot + 2 would be bag index - if used) (guess) +// ItemPacket12 = /*112*/ 0x70, // RoF+ (causes stat update) (could be TrophyTribute and GuildTrophyTribute together - two case methodology - is it checking for GuildID?) +// ItemPacketRecovery = /*113*/ 0x71, (same handler as merchant..exception: parameter is '1' versus merchant '0' looks like tab id) +// ItemPacket14 = /*115*/ 0x73, (real estate/moving crate?) +// ItemPacket__ = /*xxx*/ 0xXX // switch 'default' - all clients +//}; + struct ItemPacket_Struct { /*00*/ ItemPacketType PacketType; diff --git a/common/item.cpp b/common/item.cpp index 054bbda42..fb824afc1 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -24,6 +24,8 @@ #include "shareddb.h" #include "string_util.h" +#include "../common/light_source.h" + #include #include @@ -927,7 +929,7 @@ bool Inventory::SupportsClickCasting(int16 slot_id) } else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { - if (EQEmu::limits::AllowClickCastFromBag(m_inventory_version)) + if (EQEmu::inventory::AllowClickCastFromBag(m_inventory_version)) return true; } diff --git a/common/item.h b/common/item.h index bc002fa6f..181c57d9c 100644 --- a/common/item.h +++ b/common/item.h @@ -32,6 +32,7 @@ class EvolveInfo; // Stores information about an evolving item family #include "../common/item_struct.h" #include "../common/timer.h" #include "../common/bodytypes.h" +#include "../common/deity.h" // aren't we already in '/common'? #include "string_util.h" @@ -77,6 +78,7 @@ enum { invWhereCursor = 0x20 }; +class ItemInst; // ######################################## // Class: Queue diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index c0be7f070..9acc62a95 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2346,12 +2346,12 @@ namespace RoF outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt32(consts::BANDOLIERS_SIZE); + outapp->WriteUInt32(profile::BandoliersSize); // Copy bandoliers where server and client indexes converge - for (uint32 r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < profile::BandoliersSize; ++r) { outapp->WriteString(emu->bandoliers[r].Name); - for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true + for (uint32 j = 0; j < profile::BandolierItemCount; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(emu->bandoliers[r].Items[j].Name); outapp->WriteUInt32(emu->bandoliers[r].Items[j].ID); if (emu->bandoliers[r].Items[j].Icon) { @@ -2364,19 +2364,19 @@ namespace RoF } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = EQEmu::legacy::BANDOLIERS_SIZE; r < profile::BandoliersSize; ++r) { outapp->WriteString(""); - for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true + for (uint32 j = 0; j < profile::BandolierItemCount; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(""); outapp->WriteUInt32(0); outapp->WriteSInt32(-1); } } - outapp->WriteUInt32(consts::POTION_BELT_ITEM_COUNT); + outapp->WriteUInt32(profile::PotionBeltSize); // Copy potion belt where server and client indexes converge - for (uint32 r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < profile::PotionBeltSize; ++r) { outapp->WriteString(emu->potionbelt.Items[r].Name); outapp->WriteUInt32(emu->potionbelt.Items[r].ID); if (emu->potionbelt.Items[r].Icon) { @@ -2388,7 +2388,7 @@ namespace RoF } } // Nullify potion belt where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < profile::PotionBeltSize; ++r) { outapp->WriteString(""); outapp->WriteUInt32(0); outapp->WriteSInt32(-1); @@ -3002,7 +3002,7 @@ namespace RoF size_t names_length = 0; size_t character_count = 0; - for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) { + for (; character_count < emu->CharCount && character_count < constants::SayLinkBodySize; ++character_count) { emu_cse = (CharacterSelectEntry_Struct *)emu_ptr; names_length += strlen(emu_cse->Name); emu_ptr += sizeof(CharacterSelectEntry_Struct); @@ -5214,7 +5214,7 @@ namespace RoF structs::InventorySlot_Struct slot_id = ServerToRoFSlot(slot_id_in); - hdr.slot_type = (inst->GetMerchantSlot() ? inventory::TypeMerchant : slot_id.Type); + hdr.slot_type = (inst->GetMerchantSlot() ? invtype::InvTypeMerchant : slot_id.Type); hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot); hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex); hdr.aug_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.AugIndex); @@ -5402,7 +5402,7 @@ namespace RoF isbs.augdistiller = 65535; isbs.augrestrict = item->AugRestrict; - for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) { + for (int index = 0; index < invaug::ItemAugSize; ++index) { isbs.augslots[index].type = item->AugSlotType[index]; isbs.augslots[index].visible = item->AugSlotVisible[index]; isbs.augslots[index].unknown = item->AugSlotUnk2[index]; @@ -5650,11 +5650,11 @@ namespace RoF uint32 TempSlot = 0; if (serverSlot < 56 || serverSlot == EQEmu::legacy::SlotPowerSource) { // Main Inventory and Cursor - RoFSlot.Type = inventory::TypePossessions; + RoFSlot.Type = invtype::InvTypePossessions; RoFSlot.Slot = serverSlot; if (serverSlot == EQEmu::legacy::SlotPowerSource) - RoFSlot.Slot = inventory::SlotPowerSource; + RoFSlot.Slot = invslot::PossessionsPowerSource; else if (serverSlot >= EQEmu::legacy::SlotCursor) // Cursor and Extended Corpse Inventory RoFSlot.Slot += 3; @@ -5669,22 +5669,22 @@ namespace RoF }*/ else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) { // (> 250 && < 341) - RoFSlot.Type = inventory::TypePossessions; + RoFSlot.Type = invtype::InvTypePossessions; TempSlot = serverSlot - 1; RoFSlot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 2; RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::legacy::ITEM_CONTAINER_SIZE); - if (RoFSlot.Slot >= inventory::SlotGeneral9) // (> 30) - RoFSlot.Slot = inventory::SlotCursor; + if (RoFSlot.Slot >= invslot::PossessionsGeneral9) // (> 30) + RoFSlot.Slot = invslot::PossessionsCursor; } else if (serverSlot >= EQEmu::legacy::TRIBUTE_BEGIN && serverSlot <= EQEmu::legacy::TRIBUTE_END) { // Tribute - RoFSlot.Type = inventory::TypeTribute; + RoFSlot.Type = invtype::InvTypeTribute; RoFSlot.Slot = serverSlot - EQEmu::legacy::TRIBUTE_BEGIN; } else if (serverSlot >= EQEmu::legacy::BANK_BEGIN && serverSlot <= EQEmu::legacy::BANK_BAGS_END) { - RoFSlot.Type = inventory::TypeBank; + RoFSlot.Type = invtype::InvTypeBank; TempSlot = serverSlot - EQEmu::legacy::BANK_BEGIN; RoFSlot.Slot = TempSlot; @@ -5695,7 +5695,7 @@ namespace RoF } else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) { - RoFSlot.Type = inventory::TypeSharedBank; + RoFSlot.Type = invtype::InvTypeSharedBank; TempSlot = serverSlot - EQEmu::legacy::SHARED_BANK_BEGIN; RoFSlot.Slot = TempSlot; @@ -5706,7 +5706,7 @@ namespace RoF } else if (serverSlot >= EQEmu::legacy::TRADE_BEGIN && serverSlot <= EQEmu::legacy::TRADE_BAGS_END) { - RoFSlot.Type = inventory::TypeTrade; + RoFSlot.Type = invtype::InvTypeTrade; TempSlot = serverSlot - EQEmu::legacy::TRADE_BEGIN; RoFSlot.Slot = TempSlot; @@ -5730,7 +5730,7 @@ namespace RoF } else if (serverSlot >= EQEmu::legacy::WORLD_BEGIN && serverSlot <= EQEmu::legacy::WORLD_END) { - RoFSlot.Type = inventory::TypeWorld; + RoFSlot.Type = invtype::InvTypeWorld; TempSlot = serverSlot - EQEmu::legacy::WORLD_BEGIN; RoFSlot.Slot = TempSlot; } @@ -5754,7 +5754,7 @@ namespace RoF RoFSlot.Slot = serverSlot; if (serverSlot == EQEmu::legacy::SlotPowerSource) - RoFSlot.Slot = inventory::SlotPowerSource; + RoFSlot.Slot = invslot::PossessionsPowerSource; else if (serverSlot >= EQEmu::legacy::SlotCursor) // Cursor and Extended Corpse Inventory RoFSlot.Slot += 3; @@ -5791,11 +5791,11 @@ namespace RoF uint32 ServerSlot = INVALID_INDEX; uint32 TempSlot = 0; - if (rofSlot.Type == inventory::TypePossessions && rofSlot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 51) - if (rofSlot.Slot == inventory::SlotPowerSource) + if (rofSlot.Type == invtype::InvTypePossessions && rofSlot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 51) + if (rofSlot.Slot == invslot::PossessionsPowerSource) TempSlot = EQEmu::legacy::SlotPowerSource; - else if (rofSlot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory + else if (rofSlot.Slot >= invslot::PossessionsCursor) // Cursor and Extended Corpse Inventory TempSlot = rofSlot.Slot - 3; /*else if (RoFSlot.MainSlot == slots::MainGeneral9 || RoFSlot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF inventory/corpse slots @@ -5809,7 +5809,7 @@ namespace RoF // For now, it's probably best to leave as-is and let this work itself out in the inventory rework. }*/ - else if (rofSlot.Slot >= inventory::SlotAmmo) // Ammo and Main Inventory + else if (rofSlot.Slot >= invslot::PossessionsAmmo) // Ammo and Main Inventory TempSlot = rofSlot.Slot - 1; else // Worn Slots @@ -5821,7 +5821,7 @@ namespace RoF ServerSlot = TempSlot; } - else if (rofSlot.Type == inventory::TypeBank) { + else if (rofSlot.Type == invtype::InvTypeBank) { TempSlot = EQEmu::legacy::BANK_BEGIN; if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) @@ -5833,7 +5833,7 @@ namespace RoF ServerSlot = TempSlot; } - else if (rofSlot.Type == inventory::TypeSharedBank) { + else if (rofSlot.Type == invtype::InvTypeSharedBank) { TempSlot = EQEmu::legacy::SHARED_BANK_BEGIN; if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) @@ -5845,7 +5845,7 @@ namespace RoF ServerSlot = TempSlot; } - else if (rofSlot.Type == inventory::TypeTrade) { + else if (rofSlot.Type == invtype::InvTypeTrade) { TempSlot = EQEmu::legacy::TRADE_BEGIN; if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) @@ -5859,7 +5859,7 @@ namespace RoF ServerSlot = TempSlot; } - else if (rofSlot.Type == inventory::TypeWorld) { + else if (rofSlot.Type == invtype::InvTypeWorld) { TempSlot = EQEmu::legacy::WORLD_BEGIN; if (rofSlot.Slot >= SUB_INDEX_BEGIN) @@ -5877,7 +5877,7 @@ namespace RoF ServerSlot = TempSlot; }*/ - else if (rofSlot.Type == inventory::TypeGuildTribute) { + else if (rofSlot.Type == invtype::InvTypeGuildTribute) { ServerSlot = INVALID_INDEX; } @@ -5892,10 +5892,10 @@ namespace RoF uint32 TempSlot = 0; if (rofSlot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 33) - if (rofSlot.Slot == inventory::SlotPowerSource) + if (rofSlot.Slot == invslot::PossessionsPowerSource) TempSlot = EQEmu::legacy::SlotPowerSource; - else if (rofSlot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory + else if (rofSlot.Slot >= invslot::PossessionsCursor) // Cursor and Extended Corpse Inventory TempSlot = rofSlot.Slot - 3; /*else if (RoFSlot.MainSlot == slots::MainGeneral9 || RoFSlot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF inventory slots @@ -5904,7 +5904,7 @@ namespace RoF // Same as above }*/ - else if (rofSlot.Slot >= inventory::SlotAmmo) // Main Inventory and Ammo Slots + else if (rofSlot.Slot >= invslot::PossessionsAmmo) // Main Inventory and Ammo Slots TempSlot = rofSlot.Slot - 1; else @@ -5928,7 +5928,7 @@ namespace RoF static inline void ServerToRoFTextLink(std::string& rofTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { rofTextLink = serverTextLink; return; } @@ -5967,7 +5967,7 @@ namespace RoF static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink) { - if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rofTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (rofTextLink.find('\x12') == std::string::npos)) { serverTextLink = rofTextLink; return; } @@ -5976,7 +5976,7 @@ namespace RoF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= constants::SayLinkBodySize) { serverTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 8e38d81f2..9bca53ec4 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2429,12 +2429,12 @@ namespace RoF2 outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt32(consts::BANDOLIERS_SIZE); + outapp->WriteUInt32(profile::BandoliersSize); // Copy bandoliers where server and client indexes converge - for (uint32 r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < profile::BandoliersSize; ++r) { outapp->WriteString(emu->bandoliers[r].Name); - for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true + for (uint32 j = 0; j < profile::BandolierItemCount; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(emu->bandoliers[r].Items[j].Name); outapp->WriteUInt32(emu->bandoliers[r].Items[j].ID); if (emu->bandoliers[r].Items[j].Icon) { @@ -2447,19 +2447,19 @@ namespace RoF2 } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (uint32 r = EQEmu::legacy::BANDOLIERS_SIZE; r < profile::BandoliersSize; ++r) { outapp->WriteString(""); - for (uint32 j = 0; j < consts::BANDOLIER_ITEM_COUNT; ++j) { // Will need adjusting if 'server != client' is ever true + for (uint32 j = 0; j < profile::BandolierItemCount; ++j) { // Will need adjusting if 'server != client' is ever true outapp->WriteString(""); outapp->WriteUInt32(0); outapp->WriteSInt32(-1); } } - outapp->WriteUInt32(consts::POTION_BELT_ITEM_COUNT); + outapp->WriteUInt32(profile::PotionBeltSize); // Copy potion belt where server and client indexes converge - for (uint32 r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < profile::PotionBeltSize; ++r) { outapp->WriteString(emu->potionbelt.Items[r].Name); outapp->WriteUInt32(emu->potionbelt.Items[r].ID); if (emu->potionbelt.Items[r].Icon) { @@ -2471,7 +2471,7 @@ namespace RoF2 } } // Nullify potion belt where server and client indexes diverge, with a client bias - for (uint32 r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (uint32 r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < profile::PotionBeltSize; ++r) { outapp->WriteString(""); outapp->WriteUInt32(0); outapp->WriteSInt32(-1); @@ -3095,7 +3095,7 @@ namespace RoF2 size_t names_length = 0; size_t character_count = 0; - for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) { + for (; character_count < emu->CharCount && character_count < constants::CharacterCreationLimit; ++character_count) { emu_cse = (CharacterSelectEntry_Struct *)emu_ptr; names_length += strlen(emu_cse->Name); emu_ptr += sizeof(CharacterSelectEntry_Struct); @@ -5489,7 +5489,7 @@ namespace RoF2 structs::InventorySlot_Struct slot_id = ServerToRoF2Slot(slot_id_in, packet_type); - hdr.slot_type = (inst->GetMerchantSlot() ? inventory::TypeMerchant : slot_id.Type); + hdr.slot_type = (inst->GetMerchantSlot() ? invtype::InvTypeMerchant : slot_id.Type); hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot); hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex); hdr.aug_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.AugIndex); @@ -5677,7 +5677,7 @@ namespace RoF2 isbs.augrestrict2 = -1; isbs.augrestrict = item->AugRestrict; - for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) { + for (int index = 0; index < invaug::ItemAugSize; ++index) { isbs.augslots[index].type = item->AugSlotType[index]; isbs.augslots[index].visible = item->AugSlotVisible[index]; isbs.augslots[index].unknown = item->AugSlotUnk2[index]; @@ -5937,17 +5937,17 @@ namespace RoF2 if (serverSlot < 56 || serverSlot == EQEmu::legacy::SlotPowerSource) { // Main Inventory and Cursor if (PacketType == ItemPacketLoot) { - RoF2Slot.Type = inventory::TypeCorpse; + RoF2Slot.Type = invtype::InvTypeCorpse; RoF2Slot.Slot = serverSlot - EQEmu::legacy::CORPSE_BEGIN; } else { - RoF2Slot.Type = inventory::TypePossessions; + RoF2Slot.Type = invtype::InvTypePossessions; RoF2Slot.Slot = serverSlot; } if (serverSlot == EQEmu::legacy::SlotPowerSource) - RoF2Slot.Slot = inventory::SlotPowerSource; + RoF2Slot.Slot = invslot::PossessionsPowerSource; else if (serverSlot >= EQEmu::legacy::SlotCursor && PacketType != ItemPacketLoot) // Cursor and Extended Corpse Inventory RoF2Slot.Slot += 3; @@ -5962,22 +5962,22 @@ namespace RoF2 }*/ else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) { // (> 250 && < 341) - RoF2Slot.Type = inventory::TypePossessions; + RoF2Slot.Type = invtype::InvTypePossessions; TempSlot = serverSlot - 1; RoF2Slot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 2; RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::legacy::ITEM_CONTAINER_SIZE); - if (RoF2Slot.Slot >= inventory::SlotGeneral9) // (> 30) - RoF2Slot.Slot = inventory::SlotCursor; + if (RoF2Slot.Slot >= invslot::PossessionsGeneral9) // (> 30) + RoF2Slot.Slot = invslot::PossessionsCursor; } else if (serverSlot >= EQEmu::legacy::TRIBUTE_BEGIN && serverSlot <= EQEmu::legacy::TRIBUTE_END) { // Tribute - RoF2Slot.Type = inventory::TypeTribute; + RoF2Slot.Type = invtype::InvTypeTribute; RoF2Slot.Slot = serverSlot - EQEmu::legacy::TRIBUTE_BEGIN; } else if (serverSlot >= EQEmu::legacy::BANK_BEGIN && serverSlot <= EQEmu::legacy::BANK_BAGS_END) { - RoF2Slot.Type = inventory::TypeBank; + RoF2Slot.Type = invtype::InvTypeBank; TempSlot = serverSlot - EQEmu::legacy::BANK_BEGIN; RoF2Slot.Slot = TempSlot; @@ -5988,7 +5988,7 @@ namespace RoF2 } else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) { - RoF2Slot.Type = inventory::TypeSharedBank; + RoF2Slot.Type = invtype::InvTypeSharedBank; TempSlot = serverSlot - EQEmu::legacy::SHARED_BANK_BEGIN; RoF2Slot.Slot = TempSlot; @@ -5999,7 +5999,7 @@ namespace RoF2 } else if (serverSlot >= EQEmu::legacy::TRADE_BEGIN && serverSlot <= EQEmu::legacy::TRADE_BAGS_END) { - RoF2Slot.Type = inventory::TypeTrade; + RoF2Slot.Type = invtype::InvTypeTrade; TempSlot = serverSlot - EQEmu::legacy::TRADE_BEGIN; RoF2Slot.Slot = TempSlot; @@ -6023,7 +6023,7 @@ namespace RoF2 } else if (serverSlot >= EQEmu::legacy::WORLD_BEGIN && serverSlot <= EQEmu::legacy::WORLD_END) { - RoF2Slot.Type = inventory::TypeWorld; + RoF2Slot.Type = invtype::InvTypeWorld; TempSlot = serverSlot - EQEmu::legacy::WORLD_BEGIN; RoF2Slot.Slot = TempSlot; } @@ -6047,7 +6047,7 @@ namespace RoF2 RoF2Slot.Slot = serverSlot; if (serverSlot == EQEmu::legacy::SlotPowerSource) - RoF2Slot.Slot = inventory::SlotPowerSource; + RoF2Slot.Slot = invslot::PossessionsPowerSource; else if (serverSlot >= EQEmu::legacy::SlotCursor) // Cursor and Extended Corpse Inventory RoF2Slot.Slot += 3; @@ -6084,11 +6084,11 @@ namespace RoF2 uint32 ServerSlot = INVALID_INDEX; uint32 TempSlot = 0; - if (rof2Slot.Type == inventory::TypePossessions && rof2Slot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 51) - if (rof2Slot.Slot == inventory::SlotPowerSource) + if (rof2Slot.Type == invtype::InvTypePossessions && rof2Slot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 51) + if (rof2Slot.Slot == invslot::PossessionsPowerSource) TempSlot = EQEmu::legacy::SlotPowerSource; - else if (rof2Slot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory + else if (rof2Slot.Slot >= invslot::PossessionsCursor) // Cursor and Extended Corpse Inventory TempSlot = rof2Slot.Slot - 3; /*else if (RoF2Slot.MainSlot == slots::MainGeneral9 || RoF2Slot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF2 inventory/corpse slots @@ -6102,7 +6102,7 @@ namespace RoF2 // For now, it's probably best to leave as-is and let this work itself out in the inventory rework. }*/ - else if (rof2Slot.Slot >= inventory::SlotAmmo) // Ammo and Main Inventory + else if (rof2Slot.Slot >= invslot::PossessionsAmmo) // Ammo and Main Inventory TempSlot = rof2Slot.Slot - 1; else // Worn Slots @@ -6114,7 +6114,7 @@ namespace RoF2 ServerSlot = TempSlot; } - else if (rof2Slot.Type == inventory::TypeBank) { + else if (rof2Slot.Type == invtype::InvTypeBank) { TempSlot = EQEmu::legacy::BANK_BEGIN; if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) @@ -6126,7 +6126,7 @@ namespace RoF2 ServerSlot = TempSlot; } - else if (rof2Slot.Type == inventory::TypeSharedBank) { + else if (rof2Slot.Type == invtype::InvTypeSharedBank) { TempSlot = EQEmu::legacy::SHARED_BANK_BEGIN; if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) @@ -6138,7 +6138,7 @@ namespace RoF2 ServerSlot = TempSlot; } - else if (rof2Slot.Type == inventory::TypeTrade) { + else if (rof2Slot.Type == invtype::InvTypeTrade) { TempSlot = EQEmu::legacy::TRADE_BEGIN; if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) @@ -6152,7 +6152,7 @@ namespace RoF2 ServerSlot = TempSlot; } - else if (rof2Slot.Type == inventory::TypeWorld) { + else if (rof2Slot.Type == invtype::InvTypeWorld) { TempSlot = EQEmu::legacy::WORLD_BEGIN; if (rof2Slot.Slot >= SUB_INDEX_BEGIN) @@ -6170,11 +6170,11 @@ namespace RoF2 ServerSlot = TempSlot; }*/ - else if (rof2Slot.Type == inventory::TypeGuildTribute) { + else if (rof2Slot.Type == invtype::InvTypeGuildTribute) { ServerSlot = INVALID_INDEX; } - else if (rof2Slot.Type == inventory::TypeCorpse) { + else if (rof2Slot.Type == invtype::InvTypeCorpse) { ServerSlot = rof2Slot.Slot + EQEmu::legacy::CORPSE_BEGIN; } @@ -6189,10 +6189,10 @@ namespace RoF2 uint32 TempSlot = 0; if (rof2Slot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 33) - if (rof2Slot.Slot == inventory::SlotPowerSource) + if (rof2Slot.Slot == invslot::PossessionsPowerSource) TempSlot = EQEmu::legacy::SlotPowerSource; - else if (rof2Slot.Slot >= inventory::SlotCursor) // Cursor and Extended Corpse Inventory + else if (rof2Slot.Slot >= invslot::PossessionsCursor) // Cursor and Extended Corpse Inventory TempSlot = rof2Slot.Slot - 3; /*else if (RoF2Slot.MainSlot == slots::MainGeneral9 || RoF2Slot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF2 inventory slots @@ -6201,7 +6201,7 @@ namespace RoF2 // Same as above }*/ - else if (rof2Slot.Slot >= inventory::SlotAmmo) // Main Inventory and Ammo Slots + else if (rof2Slot.Slot >= invslot::PossessionsAmmo) // Main Inventory and Ammo Slots TempSlot = rof2Slot.Slot - 1; else @@ -6225,7 +6225,7 @@ namespace RoF2 static inline void ServerToRoF2TextLink(std::string& rof2TextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { rof2TextLink = serverTextLink; return; } @@ -6257,7 +6257,7 @@ namespace RoF2 static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink) { - if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (rof2TextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (rof2TextLink.find('\x12') == std::string::npos)) { serverTextLink = rof2TextLink; return; } @@ -6266,7 +6266,7 @@ namespace RoF2 for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= constants::SayLinkBodySize) { serverTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; diff --git a/common/patches/rof2_limits.cpp b/common/patches/rof2_limits.cpp index 93a5c7a3d..05ece56ca 100644 --- a/common/patches/rof2_limits.cpp +++ b/common/patches/rof2_limits.cpp @@ -16,3 +16,251 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "rof2_limits.h" + +#include "../string_util.h" + + +size_t RoF2::invtype::InvTypeSize(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + return invtype::InvTypePossessionsSize; + case invtype::InvTypeBank: + return invtype::InvTypeBankSize; + case invtype::InvTypeSharedBank: + return invtype::InvTypeSharedBankSize; + case invtype::InvTypeTrade: + return invtype::InvTypeTradeSize; + case invtype::InvTypeWorld: + return invtype::InvTypeWorldSize; + case invtype::InvTypeLimbo: + return invtype::InvTypeLimboSize; + case invtype::InvTypeTribute: + return invtype::InvTypeTributeSize; + case invtype::InvTypeTrophyTribute: + return invtype::InvTypeTrophyTributeSize; + case invtype::InvTypeGuildTribute: + return invtype::InvTypeGuildTributeSize; + case invtype::InvTypeMerchant: + return invtype::InvTypeMerchantSize; + case invtype::InvTypeDeleted: + return invtype::InvTypeDeletedSize; + case invtype::InvTypeCorpse: + return invtype::InvTypeCorpseSize; + case invtype::InvTypeBazaar: + return invtype::InvTypeBazaarSize; + case invtype::InvTypeInspect: + return invtype::InvTypeInspectSize; + case invtype::InvTypeRealEstate: + return invtype::InvTypeRealEstateSize; + case invtype::InvTypeViewMODPC: + return invtype::InvTypeViewMODPCSize; + case invtype::InvTypeViewMODBank: + return invtype::InvTypeViewMODBankSize; + case invtype::InvTypeViewMODSharedBank: + return invtype::InvTypeViewMODSharedBankSize; + case invtype::InvTypeViewMODLimbo: + return invtype::InvTypeViewMODLimboSize; + case invtype::InvTypeAltStorage: + return invtype::InvTypeAltStorageSize; + case invtype::InvTypeArchived: + return invtype::InvTypeArchivedSize; + case invtype::InvTypeMail: + return invtype::InvTypeMailSize; + case invtype::InvTypeGuildTrophyTribute: + return invtype::InvTypeGuildTrophyTributeSize; + case invtype::InvTypeKrono: + return invtype::InvTypeKronoSize; + case invtype::InvTypeOther: + return invtype::InvTypeOtherSize; + default: + return 0; + } +} + +const char* RoF2::invtype::InvTypeName(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypeInvalid: + return "Invalid Type"; + case invtype::InvTypePossessions: + return "Possessions"; + case invtype::InvTypeBank: + return "Bank"; + case invtype::InvTypeSharedBank: + return "Shared Bank"; + case invtype::InvTypeTrade: + return "Trade"; + case invtype::InvTypeWorld: + return "World"; + case invtype::InvTypeLimbo: + return "Limbo"; + case invtype::InvTypeTribute: + return "Tribute"; + case invtype::InvTypeTrophyTribute: + return "Trophy Tribute"; + case invtype::InvTypeGuildTribute: + return "Guild Tribute"; + case invtype::InvTypeMerchant: + return "Merchant"; + case invtype::InvTypeDeleted: + return "Deleted"; + case invtype::InvTypeCorpse: + return "Corpse"; + case invtype::InvTypeBazaar: + return "Bazaar"; + case invtype::InvTypeInspect: + return "Inspect"; + case invtype::InvTypeRealEstate: + return "Real Estate"; + case invtype::InvTypeViewMODPC: + return "View MOD PC"; + case invtype::InvTypeViewMODBank: + return "View MOD Bank"; + case invtype::InvTypeViewMODSharedBank: + return "View MOD Shared Bank"; + case invtype::InvTypeViewMODLimbo: + return "View MOD Limbo"; + case invtype::InvTypeAltStorage: + return "Alt Storage"; + case invtype::InvTypeArchived: + return "Archived"; + case invtype::InvTypeMail: + return "Mail"; + case invtype::InvTypeGuildTrophyTribute: + return "Guild Trophy Tribute"; + case invtype::InvTypeKrono: + return "Krono"; + case invtype::InvTypeOther: + return "Other"; + default: + return "Unknown Type"; + } +} + +const char* RoF2::invslot::InvPossessionsSlotName(int inv_slot) +{ + switch (inv_slot) { + case invslot::InvSlotInvalid: + return "Invalid Slot"; + case invslot::PossessionsCharm: + return "Charm"; + case invslot::PossessionsEar1: + return "Ear 1"; + case invslot::PossessionsHead: + return "Head"; + case invslot::PossessionsFace: + return "Face"; + case invslot::PossessionsEar2: + return "Ear 2"; + case invslot::PossessionsNeck: + return "Neck"; + case invslot::PossessionsShoulders: + return "Shoulders"; + case invslot::PossessionsArms: + return "Arms"; + case invslot::PossessionsBack: + return "Back"; + case invslot::PossessionsWrist1: + return "Wrist 1"; + case invslot::PossessionsWrist2: + return "Wrist 2"; + case invslot::PossessionsRange: + return "Range"; + case invslot::PossessionsHands: + return "Hands"; + case invslot::PossessionsPrimary: + return "Primary"; + case invslot::PossessionsSecondary: + return "Secondary"; + case invslot::PossessionsFinger1: + return "Finger 1"; + case invslot::PossessionsFinger2: + return "Finger 2"; + case invslot::PossessionsChest: + return "Chest"; + case invslot::PossessionsLegs: + return "Legs"; + case invslot::PossessionsFeet: + return "Feet"; + case invslot::PossessionsWaist: + return "Waist"; + case invslot::PossessionsPowerSource: + return "Power Source"; + case invslot::PossessionsAmmo: + return "Ammo"; + case invslot::PossessionsGeneral1: + return "General 1"; + case invslot::PossessionsGeneral2: + return "General 2"; + case invslot::PossessionsGeneral3: + return "General 3"; + case invslot::PossessionsGeneral4: + return "General 4"; + case invslot::PossessionsGeneral5: + return "General 5"; + case invslot::PossessionsGeneral6: + return "General 6"; + case invslot::PossessionsGeneral7: + return "General 7"; + case invslot::PossessionsGeneral8: + return "General 8"; + case invslot::PossessionsGeneral9: + return "General 9"; + case invslot::PossessionsGeneral10: + return "General 10"; + case invslot::PossessionsCursor: + return "Cursor"; + default: + return "Unknown Slot"; + } +} + +const char* RoF2::invslot::InvSlotName(int inv_type, int inv_slot) +{ + if (inv_type == invtype::InvTypePossessions) + return invslot::InvPossessionsSlotName(inv_slot); + + size_t type_size = invtype::InvTypeSize(inv_type); + + if (!type_size || inv_slot == invslot::InvSlotInvalid) + return "Invalid Slot"; + + if ((size_t)(inv_slot + 1) >= type_size) + return "Unknown Slot"; + + static std::string ret_str; + ret_str = StringFormat("Slot %i", (inv_slot + 1)); + + return ret_str.c_str(); +} + +const char* RoF2::invbag::InvBagIndexName(int bag_index) +{ + if (bag_index == invbag::InvBagInvalid) + return "Invalid Bag"; + + if ((size_t)bag_index >= invbag::ItemBagSize) + return "Unknown Bag"; + + static std::string ret_str; + ret_str = StringFormat("Bag %i", (bag_index + 1)); + + return ret_str.c_str(); +} + +const char* RoF2::invaug::InvAugIndexName(int aug_index) +{ + if (aug_index == invaug::InvAugInvalid) + return "Invalid Augment"; + + if ((size_t)aug_index >= invaug::ItemAugSize) + return "Unknown Augment"; + + static std::string ret_str; + ret_str = StringFormat("Augment %i", (aug_index + 1)); + + return ret_str.c_str(); +} diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index e26f19019..70ce833b6 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -17,183 +17,269 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_ROF2_CONSTANTS_H -#define COMMON_ROF2_CONSTANTS_H +#ifndef COMMON_ROF2_LIMITS_H +#define COMMON_ROF2_LIMITS_H #include "../types.h" +#include "../client_version.h" +#include "../skills.h" namespace RoF2 { - namespace inventory { - typedef enum : int16 { - TypePossessions = 0, - TypeBank, - TypeSharedBank, - TypeTrade, - TypeWorld, - TypeLimbo, - TypeTribute, - TypeTrophyTribute, - TypeGuildTribute, - TypeMerchant, - TypeDeleted, - TypeCorpse, - TypeBazaar, - TypeInspect, - TypeRealEstate, - TypeViewMODPC, - TypeViewMODBank, - TypeViewMODSharedBank, - TypeViewMODLimbo, - TypeAltStorage, - TypeArchived, - TypeMail, - TypeGuildTrophyTribute, - TypeKrono, - TypeOther, - TypeCount - } InventoryTypes; + enum : int { Invalid = -1, Null, Safety }; - typedef enum : int16 { - SlotCharm = 0, - SlotEar1, - SlotHead, - SlotFace, - SlotEar2, - SlotNeck, - SlotShoulders, - SlotArms, - SlotBack, - SlotWrist1, - SlotWrist2, - SlotRange, - SlotHands, - SlotPrimary, - SlotSecondary, - SlotFinger1, - SlotFinger2, - SlotChest, - SlotLegs, - SlotFeet, - SlotWaist, - SlotPowerSource, - SlotAmmo, - SlotGeneral1, - SlotGeneral2, - SlotGeneral3, - SlotGeneral4, - SlotGeneral5, - SlotGeneral6, - SlotGeneral7, - SlotGeneral8, - SlotGeneral9, - SlotGeneral10, - SlotCursor, - SlotCount, - SlotEquipmentBegin = SlotCharm, - SlotEquipmentEnd = SlotAmmo, - SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), - SlotGeneralBegin = SlotGeneral1, - SlotGeneralEnd = SlotGeneral10, - SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) - } PossessionsSlots; - } + enum : bool { False = false, True = true }; - namespace consts { - static const size_t CHARACTER_CREATION_LIMIT = 12; + // pre-declarations + namespace invtype { + inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::RoF2; } - static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; - static const uint16 TYPE_BANK_SIZE = 24; - static const uint16 TYPE_SHARED_BANK_SIZE = 2; - static const uint16 TYPE_TRADE_SIZE = 8; - static const uint16 TYPE_WORLD_SIZE = 10; - static const uint16 TYPE_LIMBO_SIZE = 36; - static const uint16 TYPE_TRIBUTE_SIZE = 0; //? - static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; - static const uint16 TYPE_MERCHANT_SIZE = 0; - static const uint16 TYPE_DELETED_SIZE = 0; - static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; - static const uint16 TYPE_BAZAAR_SIZE = 200; - static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; - static const uint16 TYPE_REAL_ESTATE_SIZE = 0; - static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; - static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; - static const uint16 TYPE_ALT_STORAGE_SIZE = 0; - static const uint16 TYPE_ARCHIVED_SIZE = 0; - static const uint16 TYPE_MAIL_SIZE = 0; - static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_KRONO_SIZE = NOT_USED; - static const uint16 TYPE_OTHER_SIZE = 0; + enum : int { InvTypeInvalid = -1, InvTypeBegin }; - // most of these definitions will go away with the structure-based system..this maintains compatibility for now - // (bag slots and main slots beyond Possessions are assigned for compatibility with current server coding) - static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; - static const int16 EQUIPMENT_END = inventory::SlotAmmo; - static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; + enum InventoryType : int { + InvTypePossessions = InvTypeBegin, + InvTypeBank, + InvTypeSharedBank, + InvTypeTrade, + InvTypeWorld, + InvTypeLimbo, + InvTypeTribute, + InvTypeTrophyTribute, + InvTypeGuildTribute, + InvTypeMerchant, + InvTypeDeleted, + InvTypeCorpse, + InvTypeBazaar, + InvTypeInspect, + InvTypeRealEstate, + InvTypeViewMODPC, + InvTypeViewMODBank, + InvTypeViewMODSharedBank, + InvTypeViewMODLimbo, + InvTypeAltStorage, + InvTypeArchived, + InvTypeMail, + InvTypeGuildTrophyTribute, + InvTypeKrono, + InvTypeOther, + InvTypeCount + }; - static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; - static const int16 GENERAL_END = inventory::SlotGeneral10; - static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; - static const int16 GENERAL_BAGS_BEGIN = 251; - static const int16 GENERAL_BAGS_END_OFFSET = 99; - static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; + } /*invtype*/ - static const int16 CURSOR = inventory::SlotCursor; - static const int16 CURSOR_BAG_BEGIN = 351; - static const int16 CURSOR_BAG_END_OFFSET = 9; - static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; + namespace invslot { + inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::RoF2; } - static const int16 BANK_BEGIN = 2000; - static const int16 BANK_END = 2023; - static const int16 BANK_BAGS_BEGIN = 2031; - static const int16 BANK_BAGS_END_OFFSET = 239; - static const int16 BANK_BAGS_END = BANK_BAGS_BEGIN + BANK_BAGS_END_OFFSET; + enum : int { InvSlotInvalid = -1, InvSlotBegin }; - static const int16 SHARED_BANK_BEGIN = 2500; - static const int16 SHARED_BANK_END = 2501; - static const int16 SHARED_BANK_BAGS_BEGIN = 2531; - static const int16 SHARED_BANK_BAGS_END_OFFSET = 19; - static const int16 SHARED_BANK_BAGS_END = SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_END_OFFSET; + enum PossessionsSlot : int { + PossessionsCharm = InvSlotBegin, + PossessionsEar1, + PossessionsHead, + PossessionsFace, + PossessionsEar2, + PossessionsNeck, + PossessionsShoulders, + PossessionsArms, + PossessionsBack, + PossessionsWrist1, + PossessionsWrist2, + PossessionsRange, + PossessionsHands, + PossessionsPrimary, + PossessionsSecondary, + PossessionsFinger1, + PossessionsFinger2, + PossessionsChest, + PossessionsLegs, + PossessionsFeet, + PossessionsWaist, + PossessionsPowerSource, + PossessionsAmmo, + PossessionsGeneral1, + PossessionsGeneral2, + PossessionsGeneral3, + PossessionsGeneral4, + PossessionsGeneral5, + PossessionsGeneral6, + PossessionsGeneral7, + PossessionsGeneral8, + PossessionsGeneral9, + PossessionsGeneral10, + PossessionsCursor, + PossessionsCount + }; - static const int16 TRADE_BEGIN = 3000; - static const int16 TRADE_END = 3007; - static const int16 TRADE_NPC_END = 3003; - static const int16 TRADE_BAGS_BEGIN = 3031; - static const int16 TRADE_BAGS_END_OFFSET = 79; - static const int16 TRADE_BAGS_END = TRADE_BAGS_BEGIN + TRADE_BAGS_END_OFFSET; + const int EquipmentBegin = PossessionsCharm; + const int EquipmentEnd = PossessionsAmmo; + const int EquipmentCount = (EquipmentEnd - EquipmentBegin + 1); - static const int16 WORLD_BEGIN = 4000; - static const int16 WORLD_END = 4009; + const int GeneralBegin = PossessionsGeneral1; + const int GeneralEnd = PossessionsGeneral10; + const int GeneralCount = (GeneralEnd - GeneralBegin + 1); - static const int16 TRIBUTE_BEGIN = 400; - static const int16 TRIBUTE_END = 404; + } /*invslot*/ - static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; - static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; + namespace invbag { + inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::RoF2; } - static const uint16 ITEM_COMMON_SIZE = 6; - static const uint16 ITEM_CONTAINER_SIZE = 255; // 255; (server max will be 255..unsure what actual client is - test) + enum : int { InvBagInvalid = -1, InvBagBegin }; - static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances - static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance + } /*invbag*/ - static const size_t POTION_BELT_ITEM_COUNT = 5; + namespace invaug { + inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::RoF2; } - static const size_t TEXT_LINK_BODY_LENGTH = 56; + enum : int { InvAugInvalid = -1, InvAugBegin }; - static const size_t PLAYER_PROFILE_SKILL_MAX = Skill2HPiercing; - } + } /*invaug*/ - namespace limits { - static const bool ALLOWS_EMPTY_BAG_IN_BAG = true; - static const bool ALLOWS_CLICK_CAST_FROM_BAG = true; - static const bool COIN_HAS_WEIGHT = false; - } + namespace item { + inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::RoF2; } + + //enum Unknown : int { // looks like item class..but, RoF has it too - nothing in UF- + // Unknown1 = 0, + // Unknown2 = 1, + // Unknown3 = 2, + // Unknown4 = 5 // krono? + //}; + + enum ItemPacketType : int { + ItemPacketMerchant = 100, + ItemPacketTradeView = 101, + ItemPacketLoot = 102, + ItemPacketTrade = 103, + ItemPacketCharInventory = 105, + ItemPacketLimbo = 106, + ItemPacketWorldContainer = 107, + ItemPacketTributeItem = 108, + ItemPacketGuildTribute = 109, + ItemPacket10 = 110, + ItemPacket11 = 111, + ItemPacket12 = 112, + ItemPacketRecovery = 113, + ItemPacket14 = 115 + }; + + } /*item*/ + + namespace profile { + inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::RoF2; } + + } /*profile*/ + + namespace constants { + inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::RoF2; } + + } /*constants*/ + + namespace behavior { + inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::RoF2; } + + } /*behavior*/ + + namespace skills { + inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::RoF2; } + + } /*skills*/ + + + // declarations + namespace invtype { + const size_t InvTypePossessionsSize = invslot::PossessionsCount; + const size_t InvTypeBankSize = 24; + const size_t InvTypeSharedBankSize = 2; + const size_t InvTypeTradeSize = 8; + const size_t InvTypeWorldSize = 10; + const size_t InvTypeLimboSize = 36; + const size_t InvTypeTributeSize = 5; + const size_t InvTypeTrophyTributeSize = 0;//unknown + const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeMerchantSize = 200; + const size_t InvTypeDeletedSize = 0;//unknown - "Recovery Tab" + const size_t InvTypeCorpseSize = InvTypePossessionsSize; + const size_t InvTypeBazaarSize = 200; + const size_t InvTypeInspectSize = invslot::EquipmentCount; + const size_t InvTypeRealEstateSize = 0;//unknown + const size_t InvTypeViewMODPCSize = InvTypePossessionsSize; + const size_t InvTypeViewMODBankSize = InvTypeBankSize; + const size_t InvTypeViewMODSharedBankSize = InvTypeSharedBankSize; + const size_t InvTypeViewMODLimboSize = InvTypeLimboSize; + const size_t InvTypeAltStorageSize = 0;//unknown - "Shroud Bank" + const size_t InvTypeArchivedSize = 0;//unknown + const size_t InvTypeMailSize = 0;//unknown + const size_t InvTypeGuildTrophyTributeSize = 0;//unknown + const size_t InvTypeKronoSize = 0;//unknown + const size_t InvTypeOtherSize = 0;//unknown + + const size_t NPCTradeSize = 4; + + extern size_t InvTypeSize(int inv_type); + extern const char* InvTypeName(int inv_type); + + } /*invtype*/ + + namespace invslot { + extern const char* InvPossessionsSlotName(int inv_slot); + extern const char* InvSlotName(int inv_type, int inv_slot); + + } /*invslot*/ + + namespace invbag { + const size_t ItemBagSize = 255; // server Size will be 255..unsure what actual client is (test) + + extern const char* InvBagIndexName(int bag_index); + + } /*invbag*/ + + namespace invaug { + const size_t ItemAugSize = 6; + + extern const char* InvAugIndexName(int aug_index); + + } /*invaug*/ + + namespace item { + + } /*item*/ + + namespace profile { + const size_t TributeSize = invtype::InvTypeTributeSize; + + const size_t BandoliersSize = 20; // number of bandolier instances + const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance + + const size_t PotionBeltSize = 5; + + const size_t SkillArraySize = 100; + + } /*profile*/ + + namespace constants { + const size_t CharacterCreationLimit = 12; + + const size_t SayLinkBodySize = 56; + + } /*constants*/ + + namespace behavior { + const bool ConcatenateInvTypeLimbo = false; + + const bool AllowOverLevelEquipment = true; + + const bool AllowEmptyBagInBag = true; + const bool AllowClickCastFromBag = true; + + const bool CoinHasWeight = false; + + } /*behavior*/ + + namespace skills { + const size_t LastUsableSkill = EQEmu::skills::Skill2HPiercing; + + } /*skills*/ }; /*RoF2*/ -#endif /*COMMON_ROF2_CONSTANTS_H*/ +#endif /*COMMON_ROF2_LIMITS_H*/ diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index e1716478e..6d764857f 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -948,13 +948,13 @@ struct BandolierItem_Struct_Old struct Bandolier_Struct { char Name[1]; // Variable Length - BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT]; + BandolierItem_Struct Items[profile::BandolierItemCount]; }; struct Bandolier_Struct_Old { char Name[32]; - BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT]; + BandolierItem_Struct Items[profile::BandolierItemCount]; }; struct PotionBeltItem_Struct @@ -974,12 +974,12 @@ struct PotionBeltItem_Struct_Old struct PotionBelt_Struct { - PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT]; + PotionBeltItem_Struct Items[profile::PotionBeltSize]; }; struct PotionBelt_Struct_Old { - PotionBeltItem_Struct_Old Items[consts::POTION_BELT_ITEM_COUNT]; + PotionBeltItem_Struct_Old Items[profile::PotionBeltSize]; }; struct GroupLeadershipAA_Struct { @@ -1189,7 +1189,7 @@ union /*12949*/ uint32 aapoints; // Unspent AA points - Seen 1 /*12953*/ uint16 unknown_rof20; // /*12955*/ uint32 bandolier_count; // Seen 20 -/*12959*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents +/*12959*/ Bandolier_Struct bandoliers[profile::BandoliersSize]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents /*13699*/ uint32 potionbelt_count; // Seen 5 /*13703*/ PotionBelt_Struct potionbelt; // [5] 45 bytes potion belt - (Variable Name Sizes) /*13748*/ int32 unknown_rof21; // Seen -1 diff --git a/common/patches/rof_limits.cpp b/common/patches/rof_limits.cpp index 93a5c7a3d..94ed6039f 100644 --- a/common/patches/rof_limits.cpp +++ b/common/patches/rof_limits.cpp @@ -16,3 +16,247 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "rof_limits.h" + +#include "../string_util.h" + + +size_t RoF::invtype::InvTypeSize(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + return invtype::InvTypePossessionsSize; + case invtype::InvTypeBank: + return invtype::InvTypeBankSize; + case invtype::InvTypeSharedBank: + return invtype::InvTypeSharedBankSize; + case invtype::InvTypeTrade: + return invtype::InvTypeTradeSize; + case invtype::InvTypeWorld: + return invtype::InvTypeWorldSize; + case invtype::InvTypeLimbo: + return invtype::InvTypeLimboSize; + case invtype::InvTypeTribute: + return invtype::InvTypeTributeSize; + case invtype::InvTypeTrophyTribute: + return invtype::InvTypeTrophyTributeSize; + case invtype::InvTypeGuildTribute: + return invtype::InvTypeGuildTributeSize; + case invtype::InvTypeMerchant: + return invtype::InvTypeMerchantSize; + case invtype::InvTypeDeleted: + return invtype::InvTypeDeletedSize; + case invtype::InvTypeCorpse: + return invtype::InvTypeCorpseSize; + case invtype::InvTypeBazaar: + return invtype::InvTypeBazaarSize; + case invtype::InvTypeInspect: + return invtype::InvTypeInspectSize; + case invtype::InvTypeRealEstate: + return invtype::InvTypeRealEstateSize; + case invtype::InvTypeViewMODPC: + return invtype::InvTypeViewMODPCSize; + case invtype::InvTypeViewMODBank: + return invtype::InvTypeViewMODBankSize; + case invtype::InvTypeViewMODSharedBank: + return invtype::InvTypeViewMODSharedBankSize; + case invtype::InvTypeViewMODLimbo: + return invtype::InvTypeViewMODLimboSize; + case invtype::InvTypeAltStorage: + return invtype::InvTypeAltStorageSize; + case invtype::InvTypeArchived: + return invtype::InvTypeArchivedSize; + case invtype::InvTypeMail: + return invtype::InvTypeMailSize; + case invtype::InvTypeGuildTrophyTribute: + return invtype::InvTypeGuildTrophyTributeSize; + case invtype::InvTypeOther: + return invtype::InvTypeOtherSize; + default: + return 0; + } +} + +const char* RoF::invtype::InvTypeName(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypeInvalid: + return "Invalid Type"; + case invtype::InvTypePossessions: + return "Possessions"; + case invtype::InvTypeBank: + return "Bank"; + case invtype::InvTypeSharedBank: + return "Shared Bank"; + case invtype::InvTypeTrade: + return "Trade"; + case invtype::InvTypeWorld: + return "World"; + case invtype::InvTypeLimbo: + return "Limbo"; + case invtype::InvTypeTribute: + return "Tribute"; + case invtype::InvTypeTrophyTribute: + return "Trophy Tribute"; + case invtype::InvTypeGuildTribute: + return "Guild Tribute"; + case invtype::InvTypeMerchant: + return "Merchant"; + case invtype::InvTypeDeleted: + return "Deleted"; + case invtype::InvTypeCorpse: + return "Corpse"; + case invtype::InvTypeBazaar: + return "Bazaar"; + case invtype::InvTypeInspect: + return "Inspect"; + case invtype::InvTypeRealEstate: + return "Real Estate"; + case invtype::InvTypeViewMODPC: + return "View MOD PC"; + case invtype::InvTypeViewMODBank: + return "View MOD Bank"; + case invtype::InvTypeViewMODSharedBank: + return "View MOD Shared Bank"; + case invtype::InvTypeViewMODLimbo: + return "View MOD Limbo"; + case invtype::InvTypeAltStorage: + return "Alt Storage"; + case invtype::InvTypeArchived: + return "Archived"; + case invtype::InvTypeMail: + return "Mail"; + case invtype::InvTypeGuildTrophyTribute: + return "Guild Trophy Tribute"; + case invtype::InvTypeOther: + return "Other"; + default: + return "Unknown Type"; + } +} + +const char* RoF::invslot::InvPossessionsSlotName(int inv_slot) +{ + switch (inv_slot) { + case invslot::InvSlotInvalid: + return "Invalid Slot"; + case invslot::PossessionsCharm: + return "Charm"; + case invslot::PossessionsEar1: + return "Ear 1"; + case invslot::PossessionsHead: + return "Head"; + case invslot::PossessionsFace: + return "Face"; + case invslot::PossessionsEar2: + return "Ear 2"; + case invslot::PossessionsNeck: + return "Neck"; + case invslot::PossessionsShoulders: + return "Shoulders"; + case invslot::PossessionsArms: + return "Arms"; + case invslot::PossessionsBack: + return "Back"; + case invslot::PossessionsWrist1: + return "Wrist 1"; + case invslot::PossessionsWrist2: + return "Wrist 2"; + case invslot::PossessionsRange: + return "Range"; + case invslot::PossessionsHands: + return "Hands"; + case invslot::PossessionsPrimary: + return "Primary"; + case invslot::PossessionsSecondary: + return "Secondary"; + case invslot::PossessionsFinger1: + return "Finger 1"; + case invslot::PossessionsFinger2: + return "Finger 2"; + case invslot::PossessionsChest: + return "Chest"; + case invslot::PossessionsLegs: + return "Legs"; + case invslot::PossessionsFeet: + return "Feet"; + case invslot::PossessionsWaist: + return "Waist"; + case invslot::PossessionsPowerSource: + return "Power Source"; + case invslot::PossessionsAmmo: + return "Ammo"; + case invslot::PossessionsGeneral1: + return "General 1"; + case invslot::PossessionsGeneral2: + return "General 2"; + case invslot::PossessionsGeneral3: + return "General 3"; + case invslot::PossessionsGeneral4: + return "General 4"; + case invslot::PossessionsGeneral5: + return "General 5"; + case invslot::PossessionsGeneral6: + return "General 6"; + case invslot::PossessionsGeneral7: + return "General 7"; + case invslot::PossessionsGeneral8: + return "General 8"; + case invslot::PossessionsGeneral9: + return "General 9"; + case invslot::PossessionsGeneral10: + return "General 10"; + case invslot::PossessionsCursor: + return "Cursor"; + default: + return "Unknown Slot"; + } +} + +const char* RoF::invslot::InvSlotName(int inv_type, int inv_slot) +{ + if (inv_type == invtype::InvTypePossessions) + return invslot::InvPossessionsSlotName(inv_slot); + + size_t type_size = invtype::InvTypeSize(inv_type); + + if (!type_size || inv_slot == invslot::InvSlotInvalid) + return "Invalid Slot"; + + if ((size_t)(inv_slot + 1) >= type_size) + return "Unknown Slot"; + + static std::string ret_str; + ret_str = StringFormat("Slot %i", (inv_slot + 1)); + + return ret_str.c_str(); +} + +const char* RoF::invbag::InvBagIndexName(int bag_index) +{ + if (bag_index == invbag::InvBagInvalid) + return "Invalid Bag"; + + if ((size_t)bag_index >= invbag::ItemBagSize) + return "Unknown Bag"; + + static std::string ret_str; + ret_str = StringFormat("Bag %i", (bag_index + 1)); + + return ret_str.c_str(); +} + +const char* RoF::invaug::InvAugIndexName(int aug_index) +{ + if (aug_index == invaug::InvAugInvalid) + return "Invalid Augment"; + + if ((size_t)aug_index >= invaug::ItemAugSize) + return "Unknown Augment"; + + static std::string ret_str; + ret_str = StringFormat("Augment %i", (aug_index + 1)); + + return ret_str.c_str(); +} diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index 9b888d3af..8b3d95591 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -17,182 +17,260 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_ROF_CONSTANTS_H -#define COMMON_ROF_CONSTANTS_H +#ifndef COMMON_ROF_LIMITS_H +#define COMMON_ROF_LIMITS_H #include "../types.h" +#include "../client_version.h" +#include "../skills.h" namespace RoF { - namespace inventory { - typedef enum : int16 { - TypePossessions = 0, - TypeBank, - TypeSharedBank, - TypeTrade, - TypeWorld, - TypeLimbo, - TypeTribute, - TypeTrophyTribute, - TypeGuildTribute, - TypeMerchant, - TypeDeleted, - TypeCorpse, - TypeBazaar, - TypeInspect, - TypeRealEstate, - TypeViewMODPC, - TypeViewMODBank, - TypeViewMODSharedBank, - TypeViewMODLimbo, - TypeAltStorage, - TypeArchived, - TypeMail, - TypeGuildTrophyTribute, - TypeOther, - TypeCount - } InventoryTypes; + enum : int { Invalid = -1, Null, Safety }; - typedef enum : int16 { - SlotCharm = 0, - SlotEar1, - SlotHead, - SlotFace, - SlotEar2, - SlotNeck, - SlotShoulders, - SlotArms, - SlotBack, - SlotWrist1, - SlotWrist2, - SlotRange, - SlotHands, - SlotPrimary, - SlotSecondary, - SlotFinger1, - SlotFinger2, - SlotChest, - SlotLegs, - SlotFeet, - SlotWaist, - SlotPowerSource, - SlotAmmo, - SlotGeneral1, - SlotGeneral2, - SlotGeneral3, - SlotGeneral4, - SlotGeneral5, - SlotGeneral6, - SlotGeneral7, - SlotGeneral8, - SlotGeneral9, - SlotGeneral10, - SlotCursor, - SlotCount, - SlotEquipmentBegin = SlotCharm, - SlotEquipmentEnd = SlotAmmo, - SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), - SlotGeneralBegin = SlotGeneral1, - SlotGeneralEnd = SlotGeneral10, - SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) - } PossessionsSlots; - } + enum : bool { False = false, True = true }; - namespace consts { - static const size_t CHARACTER_CREATION_LIMIT = 12; + // pre-declarations + namespace invtype { + inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::RoF; } - static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; - static const uint16 TYPE_BANK_SIZE = 24; - static const uint16 TYPE_SHARED_BANK_SIZE = 2; - static const uint16 TYPE_TRADE_SIZE = 8; - static const uint16 TYPE_WORLD_SIZE = 10; - static const uint16 TYPE_LIMBO_SIZE = 36; - static const uint16 TYPE_TRIBUTE_SIZE = 0; //? - static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; - static const uint16 TYPE_MERCHANT_SIZE = 0; - static const uint16 TYPE_DELETED_SIZE = 0; - static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; - static const uint16 TYPE_BAZAAR_SIZE = 200; - static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; - static const uint16 TYPE_REAL_ESTATE_SIZE = 0; - static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; - static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; - static const uint16 TYPE_ALT_STORAGE_SIZE = 0; - static const uint16 TYPE_ARCHIVED_SIZE = 0; - static const uint16 TYPE_MAIL_SIZE = 0; - static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_KRONO_SIZE = NOT_USED; - static const uint16 TYPE_OTHER_SIZE = 0; + enum : int { InvTypeInvalid = -1, InvTypeBegin }; - // most of these definitions will go away with the structure-based system..this maintains compatibility for now - // (bag slots and main slots beyond Possessions are assigned for compatibility with current server coding) - static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; - static const int16 EQUIPMENT_END = inventory::SlotAmmo; - static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; + enum InventoryType : int { + InvTypePossessions = InvTypeBegin, + InvTypeBank, + InvTypeSharedBank, + InvTypeTrade, + InvTypeWorld, + InvTypeLimbo, + InvTypeTribute, + InvTypeTrophyTribute, + InvTypeGuildTribute, + InvTypeMerchant, + InvTypeDeleted, + InvTypeCorpse, + InvTypeBazaar, + InvTypeInspect, + InvTypeRealEstate, + InvTypeViewMODPC, + InvTypeViewMODBank, + InvTypeViewMODSharedBank, + InvTypeViewMODLimbo, + InvTypeAltStorage, + InvTypeArchived, + InvTypeMail, + InvTypeGuildTrophyTribute, + InvTypeOther, + InvTypeCount + }; - static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; - static const int16 GENERAL_END = inventory::SlotGeneral10; - static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; - static const int16 GENERAL_BAGS_BEGIN = 251; - static const int16 GENERAL_BAGS_END_OFFSET = 99; - static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; + } /*invtype*/ - static const int16 CURSOR = inventory::SlotCursor; - static const int16 CURSOR_BAG_BEGIN = 351; - static const int16 CURSOR_BAG_END_OFFSET = 9; - static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; + namespace invslot { + inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::RoF; } - static const int16 BANK_BEGIN = 2000; - static const int16 BANK_END = 2023; - static const int16 BANK_BAGS_BEGIN = 2031; - static const int16 BANK_BAGS_END_OFFSET = 239; - static const int16 BANK_BAGS_END = BANK_BAGS_BEGIN + BANK_BAGS_END_OFFSET; + enum : int { InvSlotInvalid = -1, InvSlotBegin }; - static const int16 SHARED_BANK_BEGIN = 2500; - static const int16 SHARED_BANK_END = 2501; - static const int16 SHARED_BANK_BAGS_BEGIN = 2531; - static const int16 SHARED_BANK_BAGS_END_OFFSET = 19; - static const int16 SHARED_BANK_BAGS_END = SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_END_OFFSET; + enum PossessionsSlot : int { + PossessionsCharm = InvSlotBegin, + PossessionsEar1, + PossessionsHead, + PossessionsFace, + PossessionsEar2, + PossessionsNeck, + PossessionsShoulders, + PossessionsArms, + PossessionsBack, + PossessionsWrist1, + PossessionsWrist2, + PossessionsRange, + PossessionsHands, + PossessionsPrimary, + PossessionsSecondary, + PossessionsFinger1, + PossessionsFinger2, + PossessionsChest, + PossessionsLegs, + PossessionsFeet, + PossessionsWaist, + PossessionsPowerSource, + PossessionsAmmo, + PossessionsGeneral1, + PossessionsGeneral2, + PossessionsGeneral3, + PossessionsGeneral4, + PossessionsGeneral5, + PossessionsGeneral6, + PossessionsGeneral7, + PossessionsGeneral8, + PossessionsGeneral9, + PossessionsGeneral10, + PossessionsCursor, + PossessionsCount + }; - static const int16 TRADE_BEGIN = 3000; - static const int16 TRADE_END = 3007; - static const int16 TRADE_NPC_END = 3003; - static const int16 TRADE_BAGS_BEGIN = 3031; - static const int16 TRADE_BAGS_END_OFFSET = 79; - static const int16 TRADE_BAGS_END = TRADE_BAGS_BEGIN + TRADE_BAGS_END_OFFSET; + const int EquipmentBegin = PossessionsCharm; + const int EquipmentEnd = PossessionsAmmo; + const int EquipmentCount = (EquipmentEnd - EquipmentBegin + 1); - static const int16 WORLD_BEGIN = 4000; - static const int16 WORLD_END = 4009; + const int GeneralBegin = PossessionsGeneral1; + const int GeneralEnd = PossessionsGeneral10; + const int GeneralCount = (GeneralEnd - GeneralBegin + 1); - static const int16 TRIBUTE_BEGIN = 400; - static const int16 TRIBUTE_END = 404; + } /*invslot*/ - static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; - static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; + namespace invbag { + inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::RoF; } - static const uint16 ITEM_COMMON_SIZE = 6; - static const uint16 ITEM_CONTAINER_SIZE = 255; // 255; (server max will be 255..unsure what actual client is - test) + enum : int { InvBagInvalid = -1, InvBagBegin }; - static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances - static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance + } /*invbag*/ - static const size_t POTION_BELT_ITEM_COUNT = 5; + namespace invaug { + inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::RoF; } - static const size_t TEXT_LINK_BODY_LENGTH = 55; + enum : int { InvAugInvalid = -1, InvAugBegin }; - static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; - } + } /*invaug*/ - namespace limits { - static const bool ALLOWS_EMPTY_BAG_IN_BAG = true; - static const bool ALLOWS_CLICK_CAST_FROM_BAG = true; - static const bool COIN_HAS_WEIGHT = false; - } + namespace item { + inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::RoF; } + + enum ItemPacketType : int { + ItemPacketMerchant = 100, + ItemPacketTradeView = 101, + ItemPacketLoot = 102, + ItemPacketTrade = 103, + ItemPacketCharInventory = 105, + ItemPacketLimbo = 106, + ItemPacketWorldContainer = 107, + ItemPacketTributeItem = 108, + ItemPacketGuildTribute = 109, + ItemPacket10 = 110, + ItemPacket11 = 111, + ItemPacket12 = 112, + ItemPacketRecovery = 113, + ItemPacket14 = 115 + }; + + } /*item*/ + + namespace profile { + inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::RoF; } + + } /*profile*/ + + namespace constants { + inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::RoF; } + + } /*constants*/ + + namespace behavior { + inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::RoF; } + + } /*behavior*/ + + namespace skills { + inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::RoF; } + + } /*skills*/ + + + // declarations + namespace invtype { + const size_t InvTypePossessionsSize = invslot::PossessionsCount; + const size_t InvTypeBankSize = 24; + const size_t InvTypeSharedBankSize = 2; + const size_t InvTypeTradeSize = 8; + const size_t InvTypeWorldSize = 10; + const size_t InvTypeLimboSize = 36; + const size_t InvTypeTributeSize = 5; + const size_t InvTypeTrophyTributeSize = 0;//unknown + const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeMerchantSize = 200; + const size_t InvTypeDeletedSize = 0;//unknown - "Recovery Tab" + const size_t InvTypeCorpseSize = InvTypePossessionsSize; + const size_t InvTypeBazaarSize = 200; + const size_t InvTypeInspectSize = invslot::EquipmentCount; + const size_t InvTypeRealEstateSize = 0;//unknown + const size_t InvTypeViewMODPCSize = InvTypePossessionsSize; + const size_t InvTypeViewMODBankSize = InvTypeBankSize; + const size_t InvTypeViewMODSharedBankSize = InvTypeSharedBankSize; + const size_t InvTypeViewMODLimboSize = InvTypeLimboSize; + const size_t InvTypeAltStorageSize = 0;//unknown - "Shroud Bank" + const size_t InvTypeArchivedSize = 0;//unknown + const size_t InvTypeMailSize = 0;//unknown + const size_t InvTypeGuildTrophyTributeSize = 0;//unknown + const size_t InvTypeOtherSize = 0;//unknown + + const size_t NPCTradeSize = 4; + + extern size_t InvTypeSize(int inv_type); + extern const char* InvTypeName(int inv_type); + + } /*invtype*/ + + namespace invslot { + extern const char* InvPossessionsSlotName(int inv_slot); + extern const char* InvSlotName(int inv_type, int inv_slot); + + } /*invslot*/ + + namespace invbag { + const size_t ItemBagSize = 255; // server Size will be 255..unsure what actual client is (test) + + extern const char* InvBagIndexName(int bag_index); + + } /*invbag*/ + + namespace invaug { + const size_t ItemAugSize = 6; + + extern const char* InvAugIndexName(int aug_index); + + } /*invaug*/ + + namespace item { + + } /*item*/ + + namespace profile { + const size_t TributeSize = invtype::InvTypeTributeSize; + + const size_t BandoliersSize = 20; // number of bandolier instances + const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance + + const size_t PotionBeltSize = 5; + + const size_t SkillArraySize = 100; + + } /*profile*/ + + namespace constants { + const size_t CharacterCreationLimit = 12; + + const size_t SayLinkBodySize = 55; + + } /*constants*/ + + namespace behavior { + const bool ConcatenateInvTypeLimbo = false; + + const bool AllowOverLevelEquipment = true; + + const bool AllowEmptyBagInBag = true; + const bool AllowClickCastFromBag = true; + + const bool CoinHasWeight = false; + + } /*behavior*/ + + namespace skills { + const size_t LastUsableSkill = EQEmu::skills::SkillTripleAttack; + + } /*skills*/ }; /*RoF*/ -#endif /*COMMON_ROF_CONSTANTS_H*/ +#endif /*COMMON_ROF_LIMITS_H*/ diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index d3d83fca6..a0d95f841 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -931,13 +931,13 @@ struct BandolierItem_Struct_Old struct Bandolier_Struct { char Name[1]; // Variable Length - BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT]; + BandolierItem_Struct Items[profile::BandolierItemCount]; }; struct Bandolier_Struct_Old { char Name[32]; - BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT]; + BandolierItem_Struct Items[profile::BandolierItemCount]; }; struct PotionBeltItem_Struct @@ -957,12 +957,12 @@ struct PotionBeltItem_Struct_Old struct PotionBelt_Struct { - PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT]; + PotionBeltItem_Struct Items[profile::PotionBeltSize]; }; struct PotionBelt_Struct_Old { - PotionBeltItem_Struct_Old Items[consts::POTION_BELT_ITEM_COUNT]; + PotionBeltItem_Struct_Old Items[profile::PotionBeltSize]; }; struct GroupLeadershipAA_Struct { @@ -1172,7 +1172,7 @@ union /*12949*/ uint32 aapoints; // Unspent AA points - Seen 1 /*12953*/ uint16 unknown_rof20; // /*12955*/ uint32 bandolier_count; // Seen 20 -/*12959*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents +/*12959*/ Bandolier_Struct bandoliers[profile::BandoliersSize]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents /*13699*/ uint32 potionbelt_count; // Seen 5 /*13703*/ PotionBelt_Struct potionbelt; // [5] 45 bytes potion belt - (Variable Name Sizes) /*13748*/ int32 unknown_rof21; // Seen -1 diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 244e63c71..f915743c1 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1623,18 +1623,18 @@ namespace SoD // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < profile::BandoliersSize; ++r) { OUT_str(bandoliers[r].Name); - for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true + for (uint32 k = 0; k < profile::BandolierItemCount; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); OUT(bandoliers[r].Items[k].Icon); OUT_str(bandoliers[r].Items[k].Name); } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < profile::BandoliersSize; ++r) { eq->bandoliers[r].Name[0] = '\0'; - for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true + for (uint32 k = 0; k < profile::BandolierItemCount; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; eq->bandoliers[r].Items[k].Icon = 0; eq->bandoliers[r].Items[k].Name[0] = '\0'; @@ -1644,13 +1644,13 @@ namespace SoD // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < profile::PotionBeltSize; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < profile::PotionBeltSize; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -1938,8 +1938,8 @@ namespace SoD eq->CharCount = emu->CharCount; eq->TotalChars = emu->TotalChars; - if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT) - eq->TotalChars = consts::CHARACTER_CREATION_LIMIT; + if (eq->TotalChars > constants::CharacterCreationLimit) + eq->TotalChars = constants::CharacterCreationLimit; FINISH_ENCODE(); return; @@ -1951,7 +1951,7 @@ namespace SoD size_t names_length = 0; size_t character_count = 0; - for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) { + for (; character_count < emu->CharCount && character_count < constants::CharacterCreationLimit; ++character_count) { emu_cse = (CharacterSelectEntry_Struct *)emu_ptr; names_length += strlen(emu_cse->Name); emu_ptr += sizeof(CharacterSelectEntry_Struct); @@ -1967,8 +1967,8 @@ namespace SoD eq->CharCount = character_count; eq->TotalChars = emu->TotalChars; - if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT) - eq->TotalChars = consts::CHARACTER_CREATION_LIMIT; + if (eq->TotalChars > constants::CharacterCreationLimit) + eq->TotalChars = constants::CharacterCreationLimit; emu_ptr = __emu_buffer; emu_ptr += sizeof(CharacterSelect_Struct); @@ -3706,7 +3706,7 @@ namespace SoD isbs.augtype = item->AugType; isbs.augrestrict = item->AugRestrict; - for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) { + for (int index = 0; index < invaug::ItemAugSize; ++index) { isbs.augslots[index].type = item->AugSlotType[index]; isbs.augslots[index].visible = item->AugSlotVisible[index]; isbs.augslots[index].unknown = item->AugSlotUnk2[index]; @@ -3917,7 +3917,7 @@ namespace SoD else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) SoDSlot = serverSlot + 1; else if (serverSlot == EQEmu::legacy::SlotPowerSource) - SoDSlot = inventory::SlotPowerSource; + SoDSlot = invslot::PossessionsPowerSource; else SoDSlot = serverSlot; return SoDSlot; @@ -3933,15 +3933,15 @@ namespace SoD { uint32 ServerSlot = 0; - if (sodSlot >= inventory::SlotAmmo && sodSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (sodSlot >= invslot::PossessionsAmmo && sodSlot <= invslot::CorpseEnd) // Cursor/Ammo/Power Source and Normal Inventory Slots ServerSlot = sodSlot - 1; - else if (sodSlot >= consts::GENERAL_BAGS_BEGIN && sodSlot <= consts::CURSOR_BAG_END) + else if (sodSlot >= invbag::GeneralBagsBegin && sodSlot <= invbag::CursorBagEnd) ServerSlot = sodSlot - 11; - else if (sodSlot >= consts::BANK_BAGS_BEGIN && sodSlot <= consts::BANK_BAGS_END) + else if (sodSlot >= invbag::BankBagsBegin && sodSlot <= invbag::BankBagsEnd) ServerSlot = sodSlot - 1; - else if (sodSlot >= consts::SHARED_BANK_BAGS_BEGIN && sodSlot <= consts::SHARED_BANK_BAGS_END) + else if (sodSlot >= invbag::SharedBankBagsBegin && sodSlot <= invbag::SharedBankBagsEnd) ServerSlot = sodSlot - 1; - else if (sodSlot == inventory::SlotPowerSource) + else if (sodSlot == invslot::PossessionsPowerSource) ServerSlot = EQEmu::legacy::SlotPowerSource; else ServerSlot = sodSlot; @@ -3956,7 +3956,7 @@ namespace SoD static inline void ServerToSoDTextLink(std::string& sodTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { sodTextLink = serverTextLink; return; } @@ -3996,7 +3996,7 @@ namespace SoD static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink) { - if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sodTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (sodTextLink.find('\x12') == std::string::npos)) { serverTextLink = sodTextLink; return; } @@ -4005,7 +4005,7 @@ namespace SoD for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= constants::SayLinkBodySize) { serverTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; diff --git a/common/patches/sod_limits.cpp b/common/patches/sod_limits.cpp index 93a5c7a3d..de1abba02 100644 --- a/common/patches/sod_limits.cpp +++ b/common/patches/sod_limits.cpp @@ -16,3 +16,240 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "sod_limits.h" + +#include "../string_util.h" + + +size_t SoD::invtype::InvTypeSize(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + return invtype::InvTypePossessionsSize; + case invtype::InvTypeBank: + return invtype::InvTypeBankSize; + case invtype::InvTypeSharedBank: + return invtype::InvTypeSharedBankSize; + case invtype::InvTypeTrade: + return invtype::InvTypeTradeSize; + case invtype::InvTypeWorld: + return invtype::InvTypeWorldSize; + case invtype::InvTypeLimbo: + return invtype::InvTypeLimboSize; + case invtype::InvTypeTribute: + return invtype::InvTypeTributeSize; + case invtype::InvTypeGuildTribute: + return invtype::InvTypeGuildTributeSize; + case invtype::InvTypeMerchant: + return invtype::InvTypeMerchantSize; + case invtype::InvTypeCorpse: + return invtype::InvTypeCorpseSize; + case invtype::InvTypeBazaar: + return invtype::InvTypeBazaarSize; + case invtype::InvTypeInspect: + return invtype::InvTypeInspectSize; + case invtype::InvTypeViewMODPC: + return invtype::InvTypeViewMODPCSize; + case invtype::InvTypeViewMODBank: + return invtype::InvTypeViewMODBankSize; + case invtype::InvTypeViewMODSharedBank: + return invtype::InvTypeViewMODSharedBankSize; + case invtype::InvTypeViewMODLimbo: + return invtype::InvTypeViewMODLimboSize; + case invtype::InvTypeAltStorage: + return invtype::InvTypeAltStorageSize; + case invtype::InvTypeArchived: + return invtype::InvTypeArchivedSize; + case invtype::InvTypeOther: + return invtype::InvTypeOtherSize; + default: + return 0; + } +} + +const char* SoD::invtype::InvTypeName(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypeInvalid: + return "Invalid Type"; + case invtype::InvTypePossessions: + return "Possessions"; + case invtype::InvTypeBank: + return "Bank"; + case invtype::InvTypeSharedBank: + return "Shared Bank"; + case invtype::InvTypeTrade: + return "Trade"; + case invtype::InvTypeWorld: + return "World"; + case invtype::InvTypeLimbo: + return "Limbo"; + case invtype::InvTypeTribute: + return "Tribute"; + case invtype::InvTypeGuildTribute: + return "Guild Tribute"; + case invtype::InvTypeMerchant: + return "Merchant"; + case invtype::InvTypeCorpse: + return "Corpse"; + case invtype::InvTypeBazaar: + return "Bazaar"; + case invtype::InvTypeInspect: + return "Inspect"; + case invtype::InvTypeViewMODPC: + return "View MOD PC"; + case invtype::InvTypeViewMODBank: + return "View MOD Bank"; + case invtype::InvTypeViewMODSharedBank: + return "View MOD Shared Bank"; + case invtype::InvTypeViewMODLimbo: + return "View MOD Limbo"; + case invtype::InvTypeAltStorage: + return "Alt Storage"; + case invtype::InvTypeArchived: + return "Archived"; + case invtype::InvTypeOther: + return "Other"; + default: + return "Unknown Type"; + } +} + +const char* SoD::invslot::InvPossessionsSlotName(int inv_slot) +{ + switch (inv_slot) { + case invslot::InvSlotInvalid: + return "Invalid Slot"; + case invslot::PossessionsCharm: + return "Charm"; + case invslot::PossessionsEar1: + return "Ear 1"; + case invslot::PossessionsHead: + return "Head"; + case invslot::PossessionsFace: + return "Face"; + case invslot::PossessionsEar2: + return "Ear 2"; + case invslot::PossessionsNeck: + return "Neck"; + case invslot::PossessionsShoulders: + return "Shoulders"; + case invslot::PossessionsArms: + return "Arms"; + case invslot::PossessionsBack: + return "Back"; + case invslot::PossessionsWrist1: + return "Wrist 1"; + case invslot::PossessionsWrist2: + return "Wrist 2"; + case invslot::PossessionsRange: + return "Range"; + case invslot::PossessionsHands: + return "Hands"; + case invslot::PossessionsPrimary: + return "Primary"; + case invslot::PossessionsSecondary: + return "Secondary"; + case invslot::PossessionsFinger1: + return "Finger 1"; + case invslot::PossessionsFinger2: + return "Finger 2"; + case invslot::PossessionsChest: + return "Chest"; + case invslot::PossessionsLegs: + return "Legs"; + case invslot::PossessionsFeet: + return "Feet"; + case invslot::PossessionsWaist: + return "Waist"; + case invslot::PossessionsPowerSource: + return "Power Source"; + case invslot::PossessionsAmmo: + return "Ammo"; + case invslot::PossessionsGeneral1: + return "General 1"; + case invslot::PossessionsGeneral2: + return "General 2"; + case invslot::PossessionsGeneral3: + return "General 3"; + case invslot::PossessionsGeneral4: + return "General 4"; + case invslot::PossessionsGeneral5: + return "General 5"; + case invslot::PossessionsGeneral6: + return "General 6"; + case invslot::PossessionsGeneral7: + return "General 7"; + case invslot::PossessionsGeneral8: + return "General 8"; + case invslot::PossessionsCursor: + return "Cursor"; + default: + return "Unknown Slot"; + } +} + +const char* SoD::invslot::InvCorpseSlotName(int inv_slot) +{ + if (!invtype::InvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) + return "Invalid Slot"; + + // needs work + if ((size_t)(inv_slot + 1) < invslot::CorpseBegin || (size_t)(inv_slot + 1) >= invslot::CorpseEnd) + return "Unknown Slot"; + + static std::string ret_str; + ret_str = StringFormat("Slot %i", (inv_slot + 1)); + + return ret_str.c_str(); +} + +const char* SoD::invslot::InvSlotName(int inv_type, int inv_slot) +{ + if (inv_type == invtype::InvTypePossessions) + return invslot::InvPossessionsSlotName(inv_slot); + else if (inv_type == invtype::InvTypeCorpse) + return invslot::InvCorpseSlotName(inv_slot); + + size_t type_size = invtype::InvTypeSize(inv_type); + + if (!type_size || inv_slot == invslot::InvSlotInvalid) + return "Invalid Slot"; + + if ((size_t)(inv_slot + 1) >= type_size) + return "Unknown Slot"; + + static std::string ret_str; + ret_str = StringFormat("Slot %i", (inv_slot + 1)); + + return ret_str.c_str(); +} + +const char* SoD::invbag::InvBagIndexName(int bag_index) +{ + if (bag_index == invbag::InvBagInvalid) + return "Invalid Bag"; + + if ((size_t)bag_index >= invbag::ItemBagSize) + return "Unknown Bag"; + + static std::string ret_str; + ret_str = StringFormat("Bag %i", (bag_index + 1)); + + return ret_str.c_str(); +} + +const char* SoD::invaug::InvAugIndexName(int aug_index) +{ + if (aug_index == invaug::InvAugInvalid) + return "Invalid Augment"; + + if ((size_t)aug_index >= invaug::ItemAugSize) + return "Unknown Augment"; + + static std::string ret_str; + ret_str = StringFormat("Augment %i", (aug_index + 1)); + + return ret_str.c_str(); +} diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index 7a803f957..1d364a431 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -17,178 +17,284 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_SOD_CONSTANTS_H -#define COMMON_SOD_CONSTANTS_H +#ifndef COMMON_SOD_LIMITS_H +#define COMMON_SOD_LIMITS_H #include "../types.h" +#include "../client_version.h" +#include "../skills.h" namespace SoD { - namespace inventory { - typedef enum : int16 { - TypePossessions = 0, - TypeBank, - TypeSharedBank, - TypeTrade, - TypeWorld, - TypeLimbo, - TypeTribute, - TypeTrophyTribute, - TypeGuildTribute, - TypeMerchant, - TypeDeleted, - TypeCorpse, - TypeBazaar, - TypeInspect, - TypeRealEstate, - TypeViewMODPC, - TypeViewMODBank, - TypeViewMODSharedBank, - TypeViewMODLimbo, - TypeAltStorage, - TypeArchived, - TypeMail, - TypeGuildTrophyTribute, - TypeOther, - TypeCount - } InventoryTypes; + enum : int { Invalid = -1, Null, Safety }; - typedef enum : int16 { - SlotCharm = 0, - SlotEar1, - SlotHead, - SlotFace, - SlotEar2, - SlotNeck, - SlotShoulders, - SlotArms, - SlotBack, - SlotWrist1, - SlotWrist2, - SlotRange, - SlotHands, - SlotPrimary, - SlotSecondary, - SlotFinger1, - SlotFinger2, - SlotChest, - SlotLegs, - SlotFeet, - SlotWaist, - SlotPowerSource, - SlotAmmo, - SlotGeneral1, - SlotGeneral2, - SlotGeneral3, - SlotGeneral4, - SlotGeneral5, - SlotGeneral6, - SlotGeneral7, - SlotGeneral8, - SlotCursor, - SlotCount, - SlotEquipmentBegin = SlotCharm, - SlotEquipmentEnd = SlotAmmo, - SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), - SlotGeneralBegin = SlotGeneral1, - SlotGeneralEnd = SlotGeneral8, - SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) - } PossessionsSlots; - } + enum : bool { False = false, True = true }; - namespace consts { - static const size_t CHARACTER_CREATION_LIMIT = 12; + // pre-declarations + namespace invtype { + inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::SoD; } - static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; - static const uint16 TYPE_BANK_SIZE = 24; - static const uint16 TYPE_SHARED_BANK_SIZE = 2; - static const uint16 TYPE_TRADE_SIZE = 8; - static const uint16 TYPE_WORLD_SIZE = 10; - static const uint16 TYPE_LIMBO_SIZE = 36; - static const uint16 TYPE_TRIBUTE_SIZE = 0; //? - static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; - static const uint16 TYPE_MERCHANT_SIZE = 0; - static const uint16 TYPE_DELETED_SIZE = 0; - static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; - static const uint16 TYPE_BAZAAR_SIZE = 80; - static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; - static const uint16 TYPE_REAL_ESTATE_SIZE = 0; - static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; - static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; - static const uint16 TYPE_ALT_STORAGE_SIZE = 0; - static const uint16 TYPE_ARCHIVED_SIZE = 0; - static const uint16 TYPE_MAIL_SIZE = 0; - static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_KRONO_SIZE = NOT_USED; - static const uint16 TYPE_OTHER_SIZE = 0; + enum : int { InvTypeInvalid = -1, InvTypeBegin }; - static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; - static const int16 EQUIPMENT_END = inventory::SlotAmmo; - static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; + enum InventoryType : int { + InvTypePossessions = InvTypeBegin, + InvTypeBank, + InvTypeSharedBank, + InvTypeTrade, + InvTypeWorld, + InvTypeLimbo, + InvTypeTribute, + InvTypeGuildTribute, + InvTypeMerchant, + InvTypeCorpse, + InvTypeBazaar, + InvTypeInspect, + InvTypeViewMODPC, + InvTypeViewMODBank, + InvTypeViewMODSharedBank, + InvTypeViewMODLimbo, + InvTypeAltStorage, + InvTypeArchived, + InvTypeOther, + InvTypeCount + }; - static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; - static const int16 GENERAL_END = inventory::SlotGeneral8; - static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; - static const int16 GENERAL_BAGS_BEGIN = 262; - static const int16 GENERAL_BAGS_END_OFFSET = 79; - static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; + } /*invtype*/ - static const int16 CURSOR = inventory::SlotCursor; - static const int16 CURSOR_BAG_BEGIN = 342; - static const int16 CURSOR_BAG_END_OFFSET = 9; - static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; + namespace invslot { + inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::SoD; } - static const int16 BANK_BEGIN = 2000; - static const int16 BANK_END = 2023; - static const int16 BANK_BAGS_BEGIN = 2032; - static const int16 BANK_BAGS_END_OFFSET = 239; - static const int16 BANK_BAGS_END = BANK_BAGS_BEGIN + BANK_BAGS_END_OFFSET; + enum : int { InvSlotInvalid = -1, InvSlotBegin }; - static const int16 SHARED_BANK_BEGIN = 2500; - static const int16 SHARED_BANK_END = 2501; - static const int16 SHARED_BANK_BAGS_BEGIN = 2532; - static const int16 SHARED_BANK_BAGS_END_OFFSET = 19; - static const int16 SHARED_BANK_BAGS_END = SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_END_OFFSET; + enum PossessionsSlot : int { + PossessionsCharm = InvSlotBegin, + PossessionsEar1, + PossessionsHead, + PossessionsFace, + PossessionsEar2, + PossessionsNeck, + PossessionsShoulders, + PossessionsArms, + PossessionsBack, + PossessionsWrist1, + PossessionsWrist2, + PossessionsRange, + PossessionsHands, + PossessionsPrimary, + PossessionsSecondary, + PossessionsFinger1, + PossessionsFinger2, + PossessionsChest, + PossessionsLegs, + PossessionsFeet, + PossessionsWaist, + PossessionsPowerSource, + PossessionsAmmo, + PossessionsGeneral1, + PossessionsGeneral2, + PossessionsGeneral3, + PossessionsGeneral4, + PossessionsGeneral5, + PossessionsGeneral6, + PossessionsGeneral7, + PossessionsGeneral8, + PossessionsCursor, + PossessionsCount + }; - static const int16 TRADE_BEGIN = 3000; - static const int16 TRADE_END = 3007; - static const int16 TRADE_NPC_END = 3003; - static const int16 TRADE_BAGS_BEGIN = 3031; - static const int16 TRADE_BAGS_END_OFFSET = 79; - static const int16 TRADE_BAGS_END = TRADE_BAGS_BEGIN + TRADE_BAGS_END_OFFSET; + const int EquipmentBegin = PossessionsCharm; + const int EquipmentEnd = PossessionsAmmo; + const int EquipmentCount = (EquipmentEnd - EquipmentBegin + 1); - static const int16 WORLD_BEGIN = 4000; - static const int16 WORLD_END = 4009; + const int GeneralBegin = PossessionsGeneral1; + const int GeneralEnd = PossessionsGeneral8; + const int GeneralCount = (GeneralEnd - GeneralBegin + 1); - static const int16 TRIBUTE_BEGIN = 400; - static const int16 TRIBUTE_END = 404; + } /*invslot*/ - static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; - static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; + namespace invbag { + inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::SoD; } - static const uint16 ITEM_COMMON_SIZE = 5; - static const uint16 ITEM_CONTAINER_SIZE = 10; + enum : int { InvBagInvalid = -1, InvBagBegin }; - static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances - static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance + } /*invbag*/ - static const size_t POTION_BELT_ITEM_COUNT = 5; + namespace invaug { + inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::SoD; } - static const size_t TEXT_LINK_BODY_LENGTH = 50; + enum : int { InvAugInvalid = -1, InvAugBegin }; - static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; - } + } /*invaug*/ - namespace limits { - static const bool ALLOWS_EMPTY_BAG_IN_BAG = false; - static const bool ALLOWS_CLICK_CAST_FROM_BAG = false; - static const bool COIN_HAS_WEIGHT = false; - } + namespace item { + inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::SoD; } + + enum ItemPacketType : int { + ItemPacketMerchant = 100, + ItemPacketTradeView = 101, + ItemPacketLoot = 102, + ItemPacketTrade = 103, + ItemPacketCharInventory = 105, + ItemPacketLimbo = 106, + ItemPacketWorldContainer = 107, + ItemPacketTributeItem = 108, + ItemPacketGuildTribute = 109, + ItemPacketCharmUpdate = 110 + }; + + } /*item*/ + + namespace profile { + inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::SoD; } + + } /*profile*/ + + namespace constants { + inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::SoD; } + + } /*constants*/ + + namespace behavior { + inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::SoD; } + + } /*behavior*/ + + namespace skills { + inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::SoD; } + + } /*skills*/ + + + // declarations + namespace invtype { + const size_t InvTypePossessionsSize = invslot::PossessionsCount; + const size_t InvTypeBankSize = 24; + const size_t InvTypeSharedBankSize = 2; + const size_t InvTypeTradeSize = 8; + const size_t InvTypeWorldSize = 10; + const size_t InvTypeLimboSize = 36; + const size_t InvTypeTributeSize = 5; + const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeMerchantSize = 80; + const size_t InvTypeCorpseSize = InvTypePossessionsSize; + const size_t InvTypeBazaarSize = 80; + const size_t InvTypeInspectSize = invslot::EquipmentCount; + const size_t InvTypeViewMODPCSize = InvTypePossessionsSize; + const size_t InvTypeViewMODBankSize = InvTypeBankSize; + const size_t InvTypeViewMODSharedBankSize = InvTypeSharedBankSize; + const size_t InvTypeViewMODLimboSize = InvTypeLimboSize; + const size_t InvTypeAltStorageSize = 0;//unknown - "Shroud Bank" + const size_t InvTypeArchivedSize = 0;//unknown + const size_t InvTypeOtherSize = 0;//unknown + + const size_t NPCTradeSize = 4; + + extern size_t InvTypeSize(int inv_type); + extern const char* InvTypeName(int inv_type); + + } /*invtype*/ + + namespace invslot { + const int BankBegin = 2000; + const int BankEnd = (BankBegin + invtype::InvTypeBankSize) - 1; + + const int SharedBankBegin = 2500; + const int SharedBankEnd = (SharedBankBegin + invtype::InvTypeSharedBankSize) - 1; + + const int TradeBegin = 3000; + const int TradeEnd = (TradeBegin + invtype::InvTypeTradeSize) - 1; + const int TradeNPCEnd = 3003; + + const int WorldBegin = 4000; + const int WorldEnd = (WorldBegin + invtype::InvTypeWorldSize) - 1; + + const int TributeBegin = 400; + const int TributeEnd = 404; + + const int CorpseBegin = invslot::PossessionsGeneral1; + const int CorpseEnd = invslot::PossessionsGeneral1 + invslot::PossessionsCursor; + + extern const char* InvPossessionsSlotName(int inv_slot); + extern const char* InvCorpseSlotName(int inv_slot); + extern const char* InvSlotName(int inv_type, int inv_slot); + + } /*invslot*/ + + namespace invbag { + const size_t ItemBagSize = 10; + + const int GeneralBagsBegin = 262; + const int GeneralBagsSize = invslot::GeneralCount * ItemBagSize; + const int GeneralBagsEnd = (GeneralBagsBegin + GeneralBagsSize) - 1; + + const int CursorBagBegin = 342; + const int CursorBagSize = ItemBagSize; + const int CursorBagEnd = (CursorBagBegin + CursorBagSize) - 1; + + const int BankBagsBegin = 2032; + const int BankBagsSize = (invtype::InvTypeBankSize * ItemBagSize); + const int BankBagsEnd = (BankBagsBegin + BankBagsSize) - 1; + + const int SharedBankBagsBegin = 2532; + const int SharedBankBagsSize = invtype::InvTypeSharedBankSize * ItemBagSize; + const int SharedBankBagsEnd = (SharedBankBagsBegin + SharedBankBagsSize) - 1; + + const int TradeBagsBegin = 3031; + const int TradeBagsSize = invtype::InvTypeTradeSize * ItemBagSize; + const int TradeBagsEnd = (TradeBagsBegin + TradeBagsSize) - 1; + + extern const char* InvBagIndexName(int bag_index); + + } /*invbag*/ + + namespace invaug { + const size_t ItemAugSize = 5; + + extern const char* InvAugIndexName(int aug_index); + + } /*invaug*/ + + namespace item { + + } /*item*/ + + namespace profile { + const size_t TributeSize = invtype::InvTypeTributeSize; + + const size_t BandoliersSize = 20; // number of bandolier instances + const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance + + const size_t PotionBeltSize = 5; + + const size_t SkillArraySize = 100; + + } /*profile*/ + + namespace constants { + const size_t CharacterCreationLimit = 12; + + const size_t SayLinkBodySize = 50; + + } /*constants*/ + + namespace behavior { + const bool ConcatenateInvTypeLimbo = true; + + const bool AllowOverLevelEquipment = false; + + const bool AllowEmptyBagInBag = false; + const bool AllowClickCastFromBag = false; + + const bool CoinHasWeight = false; + + } /*behavior*/ + + namespace skills { + const size_t LastUsableSkill = EQEmu::skills::SkillTripleAttack; + + } /*skills*/ }; /*SoD*/ -#endif /*COMMON_SOD_CONSTANTS_H*/ +#endif /*COMMON_SOD_LIMITS_H*/ diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 67498f4ad..5acb51ad1 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -726,7 +726,7 @@ struct BandolierItem_Struct struct Bandolier_Struct { char Name[32]; - BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT]; + BandolierItem_Struct Items[profile::BandolierItemCount]; }; //len = 72 @@ -740,7 +740,7 @@ struct PotionBeltItem_Struct //len = 288 struct PotionBelt_Struct { - PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT]; + PotionBeltItem_Struct Items[profile::PotionBeltSize]; }; static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16; @@ -960,7 +960,7 @@ struct PlayerProfile_Struct /*08288*/ uint32 aapoints_spent; // Number of spent AA points /*08292*/ uint32 aapoints; // Unspent AA points /*08296*/ uint8 unknown06160[4]; -/*08300*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [6400] bandolier contents +/*08300*/ Bandolier_Struct bandoliers[profile::BandoliersSize]; // [6400] bandolier contents /*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot /*15060*/ uint8 unknown12852[8]; /*15068*/ uint32 available_slots; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 5ea473904..819fd45a8 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1279,18 +1279,18 @@ namespace SoF // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < profile::BandoliersSize; ++r) { OUT_str(bandoliers[r].Name); - for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true + for (uint32 k = 0; k < profile::BandolierItemCount; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); OUT(bandoliers[r].Items[k].Icon); OUT_str(bandoliers[r].Items[k].Name); } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < profile::BandoliersSize; ++r) { eq->bandoliers[r].Name[0] = '\0'; - for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true + for (uint32 k = 0; k < profile::BandolierItemCount; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; eq->bandoliers[r].Items[k].Icon = 0; eq->bandoliers[r].Items[k].Name[0] = '\0'; @@ -1300,13 +1300,13 @@ namespace SoF // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < profile::PotionBeltSize; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < profile::PotionBeltSize; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -1594,8 +1594,8 @@ namespace SoF eq->CharCount = emu->CharCount; eq->TotalChars = emu->TotalChars; - if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT) - eq->TotalChars = consts::CHARACTER_CREATION_LIMIT; + if (eq->TotalChars > constants::CharacterCreationLimit) + eq->TotalChars = constants::CharacterCreationLimit; FINISH_ENCODE(); return; @@ -1607,7 +1607,7 @@ namespace SoF size_t names_length = 0; size_t character_count = 0; - for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) { + for (; character_count < emu->CharCount && character_count < constants::CharacterCreationLimit; ++character_count) { emu_cse = (CharacterSelectEntry_Struct *)emu_ptr; names_length += strlen(emu_cse->Name); emu_ptr += sizeof(CharacterSelectEntry_Struct); @@ -1623,8 +1623,8 @@ namespace SoF eq->CharCount = character_count; eq->TotalChars = emu->TotalChars; - if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT) - eq->TotalChars = consts::CHARACTER_CREATION_LIMIT; + if (eq->TotalChars > constants::CharacterCreationLimit) + eq->TotalChars = constants::CharacterCreationLimit; emu_ptr = __emu_buffer; emu_ptr += sizeof(CharacterSelect_Struct); @@ -3027,7 +3027,7 @@ namespace SoF isbs.augtype = item->AugType; isbs.augrestrict = item->AugRestrict; - for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) { + for (int index = 0; index < invaug::ItemAugSize; ++index) { isbs.augslots[index].type = item->AugSlotType[index]; isbs.augslots[index].visible = item->AugSlotVisible[index]; isbs.augslots[index].unknown = item->AugSlotUnk2[index]; @@ -3237,7 +3237,7 @@ namespace SoF else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) SoFSlot = serverSlot + 1; else if (serverSlot == EQEmu::legacy::SlotPowerSource) - SoFSlot = inventory::SlotPowerSource; + SoFSlot = invslot::PossessionsPowerSource; else SoFSlot = serverSlot; @@ -3254,15 +3254,15 @@ namespace SoF { uint32 ServerSlot = 0; - if (sofSlot >= inventory::SlotAmmo && sofSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (sofSlot >= invslot::PossessionsAmmo && sofSlot <= invslot::CorpseEnd) // Cursor/Ammo/Power Source and Normal Inventory Slots ServerSlot = sofSlot - 1; - else if (sofSlot >= consts::GENERAL_BAGS_BEGIN && sofSlot <= consts::CURSOR_BAG_END) + else if (sofSlot >= invbag::GeneralBagsBegin && sofSlot <= invbag::CursorBagEnd) ServerSlot = sofSlot - 11; - else if (sofSlot >= consts::BANK_BAGS_BEGIN && sofSlot <= consts::BANK_BAGS_END) + else if (sofSlot >= invbag::BankBagsBegin && sofSlot <= invbag::BankBagsEnd) ServerSlot = sofSlot - 1; - else if (sofSlot >= consts::SHARED_BANK_BAGS_BEGIN && sofSlot <= consts::SHARED_BANK_BAGS_END) + else if (sofSlot >= invbag::SharedBankBagsBegin && sofSlot <= invbag::SharedBankBagsEnd) ServerSlot = sofSlot - 1; - else if (sofSlot == inventory::SlotPowerSource) + else if (sofSlot == invslot::PossessionsPowerSource) ServerSlot = EQEmu::legacy::SlotPowerSource; else ServerSlot = sofSlot; @@ -3278,7 +3278,7 @@ namespace SoF static inline void ServerToSoFTextLink(std::string& sofTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { sofTextLink = serverTextLink; return; } @@ -3318,7 +3318,7 @@ namespace SoF static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink) { - if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (sofTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (sofTextLink.find('\x12') == std::string::npos)) { serverTextLink = sofTextLink; return; } @@ -3327,7 +3327,7 @@ namespace SoF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= constants::SayLinkBodySize) { serverTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; diff --git a/common/patches/sof_limits.cpp b/common/patches/sof_limits.cpp index 93a5c7a3d..2e81eef1d 100644 --- a/common/patches/sof_limits.cpp +++ b/common/patches/sof_limits.cpp @@ -16,3 +16,240 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "sof_limits.h" + +#include "../string_util.h" + + +size_t SoF::invtype::InvTypeSize(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + return invtype::InvTypePossessionsSize; + case invtype::InvTypeBank: + return invtype::InvTypeBankSize; + case invtype::InvTypeSharedBank: + return invtype::InvTypeSharedBankSize; + case invtype::InvTypeTrade: + return invtype::InvTypeTradeSize; + case invtype::InvTypeWorld: + return invtype::InvTypeWorldSize; + case invtype::InvTypeLimbo: + return invtype::InvTypeLimboSize; + case invtype::InvTypeTribute: + return invtype::InvTypeTributeSize; + case invtype::InvTypeGuildTribute: + return invtype::InvTypeGuildTributeSize; + case invtype::InvTypeMerchant: + return invtype::InvTypeMerchantSize; + case invtype::InvTypeCorpse: + return invtype::InvTypeCorpseSize; + case invtype::InvTypeBazaar: + return invtype::InvTypeBazaarSize; + case invtype::InvTypeInspect: + return invtype::InvTypeInspectSize; + case invtype::InvTypeViewMODPC: + return invtype::InvTypeViewMODPCSize; + case invtype::InvTypeViewMODBank: + return invtype::InvTypeViewMODBankSize; + case invtype::InvTypeViewMODSharedBank: + return invtype::InvTypeViewMODSharedBankSize; + case invtype::InvTypeViewMODLimbo: + return invtype::InvTypeViewMODLimboSize; + case invtype::InvTypeAltStorage: + return invtype::InvTypeAltStorageSize; + case invtype::InvTypeArchived: + return invtype::InvTypeArchivedSize; + case invtype::InvTypeOther: + return invtype::InvTypeOtherSize; + default: + return 0; + } +} + +const char* SoF::invtype::InvTypeName(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypeInvalid: + return "Invalid Type"; + case invtype::InvTypePossessions: + return "Possessions"; + case invtype::InvTypeBank: + return "Bank"; + case invtype::InvTypeSharedBank: + return "Shared Bank"; + case invtype::InvTypeTrade: + return "Trade"; + case invtype::InvTypeWorld: + return "World"; + case invtype::InvTypeLimbo: + return "Limbo"; + case invtype::InvTypeTribute: + return "Tribute"; + case invtype::InvTypeGuildTribute: + return "Guild Tribute"; + case invtype::InvTypeMerchant: + return "Merchant"; + case invtype::InvTypeCorpse: + return "Corpse"; + case invtype::InvTypeBazaar: + return "Bazaar"; + case invtype::InvTypeInspect: + return "Inspect"; + case invtype::InvTypeViewMODPC: + return "View MOD PC"; + case invtype::InvTypeViewMODBank: + return "View MOD Bank"; + case invtype::InvTypeViewMODSharedBank: + return "View MOD Shared Bank"; + case invtype::InvTypeViewMODLimbo: + return "View MOD Limbo"; + case invtype::InvTypeAltStorage: + return "Alt Storage"; + case invtype::InvTypeArchived: + return "Archived"; + case invtype::InvTypeOther: + return "Other"; + default: + return "Unknown Type"; + } +} + +const char* SoF::invslot::InvPossessionsSlotName(int inv_slot) +{ + switch (inv_slot) { + case invslot::InvSlotInvalid: + return "Invalid Slot"; + case invslot::PossessionsCharm: + return "Charm"; + case invslot::PossessionsEar1: + return "Ear 1"; + case invslot::PossessionsHead: + return "Head"; + case invslot::PossessionsFace: + return "Face"; + case invslot::PossessionsEar2: + return "Ear 2"; + case invslot::PossessionsNeck: + return "Neck"; + case invslot::PossessionsShoulders: + return "Shoulders"; + case invslot::PossessionsArms: + return "Arms"; + case invslot::PossessionsBack: + return "Back"; + case invslot::PossessionsWrist1: + return "Wrist 1"; + case invslot::PossessionsWrist2: + return "Wrist 2"; + case invslot::PossessionsRange: + return "Range"; + case invslot::PossessionsHands: + return "Hands"; + case invslot::PossessionsPrimary: + return "Primary"; + case invslot::PossessionsSecondary: + return "Secondary"; + case invslot::PossessionsFinger1: + return "Finger 1"; + case invslot::PossessionsFinger2: + return "Finger 2"; + case invslot::PossessionsChest: + return "Chest"; + case invslot::PossessionsLegs: + return "Legs"; + case invslot::PossessionsFeet: + return "Feet"; + case invslot::PossessionsWaist: + return "Waist"; + case invslot::PossessionsPowerSource: + return "Power Source"; + case invslot::PossessionsAmmo: + return "Ammo"; + case invslot::PossessionsGeneral1: + return "General 1"; + case invslot::PossessionsGeneral2: + return "General 2"; + case invslot::PossessionsGeneral3: + return "General 3"; + case invslot::PossessionsGeneral4: + return "General 4"; + case invslot::PossessionsGeneral5: + return "General 5"; + case invslot::PossessionsGeneral6: + return "General 6"; + case invslot::PossessionsGeneral7: + return "General 7"; + case invslot::PossessionsGeneral8: + return "General 8"; + case invslot::PossessionsCursor: + return "Cursor"; + default: + return "Unknown Slot"; + } +} + +const char* SoF::invslot::InvCorpseSlotName(int inv_slot) +{ + if (!invtype::InvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) + return "Invalid Slot"; + + // needs work + if ((size_t)(inv_slot + 1) < invslot::CorpseBegin || (size_t)(inv_slot + 1) >= invslot::CorpseEnd) + return "Unknown Slot"; + + static std::string ret_str; + ret_str = StringFormat("Slot %i", (inv_slot + 1)); + + return ret_str.c_str(); +} + +const char* SoF::invslot::InvSlotName(int inv_type, int inv_slot) +{ + if (inv_type == invtype::InvTypePossessions) + return invslot::InvPossessionsSlotName(inv_slot); + else if (inv_type == invtype::InvTypeCorpse) + return invslot::InvCorpseSlotName(inv_slot); + + size_t type_size = invtype::InvTypeSize(inv_type); + + if (!type_size || inv_slot == invslot::InvSlotInvalid) + return "Invalid Slot"; + + if ((size_t)(inv_slot + 1) >= type_size) + return "Unknown Slot"; + + static std::string ret_str; + ret_str = StringFormat("Slot %i", (inv_slot + 1)); + + return ret_str.c_str(); +} + +const char* SoF::invbag::InvBagIndexName(int bag_index) +{ + if (bag_index == invbag::InvBagInvalid) + return "Invalid Bag"; + + if ((size_t)bag_index >= invbag::ItemBagSize) + return "Unknown Bag"; + + static std::string ret_str; + ret_str = StringFormat("Bag %i", (bag_index + 1)); + + return ret_str.c_str(); +} + +const char* SoF::invaug::InvAugIndexName(int aug_index) +{ + if (aug_index == invaug::InvAugInvalid) + return "Invalid Augment"; + + if ((size_t)aug_index >= invaug::ItemAugSize) + return "Unknown Augment"; + + static std::string ret_str; + ret_str = StringFormat("Augment %i", (aug_index + 1)); + + return ret_str.c_str(); +} diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 48855a455..1a91ba942 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -17,178 +17,284 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_SOF_CONSTANTS_H -#define COMMON_SOF_CONSTANTS_H +#ifndef COMMON_SOF_LIMITS_H +#define COMMON_SOF_LIMITS_H #include "../types.h" +#include "../client_version.h" +#include "../skills.h" namespace SoF { - namespace inventory { - typedef enum : int16 { - TypePossessions = 0, - TypeBank, - TypeSharedBank, - TypeTrade, - TypeWorld, - TypeLimbo, - TypeTribute, - TypeTrophyTribute, - TypeGuildTribute, - TypeMerchant, - TypeDeleted, - TypeCorpse, - TypeBazaar, - TypeInspect, - TypeRealEstate, - TypeViewMODPC, - TypeViewMODBank, - TypeViewMODSharedBank, - TypeViewMODLimbo, - TypeAltStorage, - TypeArchived, - TypeMail, - TypeGuildTrophyTribute, - TypeOther, - TypeCount - } InventoryTypes; + enum : int { Invalid = -1, Null, Safety }; - typedef enum : int16 { - SlotCharm = 0, - SlotEar1, - SlotHead, - SlotFace, - SlotEar2, - SlotNeck, - SlotShoulders, - SlotArms, - SlotBack, - SlotWrist1, - SlotWrist2, - SlotRange, - SlotHands, - SlotPrimary, - SlotSecondary, - SlotFinger1, - SlotFinger2, - SlotChest, - SlotLegs, - SlotFeet, - SlotWaist, - SlotPowerSource, - SlotAmmo, - SlotGeneral1, - SlotGeneral2, - SlotGeneral3, - SlotGeneral4, - SlotGeneral5, - SlotGeneral6, - SlotGeneral7, - SlotGeneral8, - SlotCursor, - SlotCount, - SlotEquipmentBegin = SlotCharm, - SlotEquipmentEnd = SlotAmmo, - SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), - SlotGeneralBegin = SlotGeneral1, - SlotGeneralEnd = SlotGeneral8, - SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) - } PossessionsSlots; - } + enum : bool { False = false, True = true }; - namespace consts { - static const size_t CHARACTER_CREATION_LIMIT = 12; + // pre-declarations + namespace invtype { + inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::SoF; } - static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; - static const uint16 TYPE_BANK_SIZE = 24; - static const uint16 TYPE_SHARED_BANK_SIZE = 2; - static const uint16 TYPE_TRADE_SIZE = 8; - static const uint16 TYPE_WORLD_SIZE = 10; - static const uint16 TYPE_LIMBO_SIZE = 36; - static const uint16 TYPE_TRIBUTE_SIZE = 0; //? - static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; - static const uint16 TYPE_MERCHANT_SIZE = 0; - static const uint16 TYPE_DELETED_SIZE = 0; - static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; - static const uint16 TYPE_BAZAAR_SIZE = 80; - static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; - static const uint16 TYPE_REAL_ESTATE_SIZE = 0; - static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; - static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; - static const uint16 TYPE_ALT_STORAGE_SIZE = 0; - static const uint16 TYPE_ARCHIVED_SIZE = 0; - static const uint16 TYPE_MAIL_SIZE = 0; - static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_KRONO_SIZE = NOT_USED; - static const uint16 TYPE_OTHER_SIZE = 0; + enum : int { InvTypeInvalid = -1, InvTypeBegin }; - static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; - static const int16 EQUIPMENT_END = inventory::SlotAmmo; - static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; + enum InventoryType : int { + InvTypePossessions = InvTypeBegin, + InvTypeBank, + InvTypeSharedBank, + InvTypeTrade, + InvTypeWorld, + InvTypeLimbo, + InvTypeTribute, + InvTypeGuildTribute, + InvTypeMerchant, + InvTypeCorpse, + InvTypeBazaar, + InvTypeInspect, + InvTypeViewMODPC, + InvTypeViewMODBank, + InvTypeViewMODSharedBank, + InvTypeViewMODLimbo, + InvTypeAltStorage, + InvTypeArchived, + InvTypeOther, + InvTypeCount + }; - static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; - static const int16 GENERAL_END = inventory::SlotGeneral8; - static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; - static const int16 GENERAL_BAGS_BEGIN = 262; - static const int16 GENERAL_BAGS_END_OFFSET = 79; - static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; + } /*invtype*/ - static const int16 CURSOR = inventory::SlotCursor; - static const int16 CURSOR_BAG_BEGIN = 342; - static const int16 CURSOR_BAG_END_OFFSET = 9; - static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; + namespace invslot { + inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::SoF; } - static const int16 BANK_BEGIN = 2000; - static const int16 BANK_END = 2023; - static const int16 BANK_BAGS_BEGIN = 2032; - static const int16 BANK_BAGS_END_OFFSET = 239; - static const int16 BANK_BAGS_END = BANK_BAGS_BEGIN + BANK_BAGS_END_OFFSET; + enum : int { InvSlotInvalid = -1, InvSlotBegin }; - static const int16 SHARED_BANK_BEGIN = 2500; - static const int16 SHARED_BANK_END = 2501; - static const int16 SHARED_BANK_BAGS_BEGIN = 2532; - static const int16 SHARED_BANK_BAGS_END_OFFSET = 19; - static const int16 SHARED_BANK_BAGS_END = SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_END_OFFSET; + enum PossessionsSlot : int { + PossessionsCharm = InvSlotBegin, + PossessionsEar1, + PossessionsHead, + PossessionsFace, + PossessionsEar2, + PossessionsNeck, + PossessionsShoulders, + PossessionsArms, + PossessionsBack, + PossessionsWrist1, + PossessionsWrist2, + PossessionsRange, + PossessionsHands, + PossessionsPrimary, + PossessionsSecondary, + PossessionsFinger1, + PossessionsFinger2, + PossessionsChest, + PossessionsLegs, + PossessionsFeet, + PossessionsWaist, + PossessionsPowerSource, + PossessionsAmmo, + PossessionsGeneral1, + PossessionsGeneral2, + PossessionsGeneral3, + PossessionsGeneral4, + PossessionsGeneral5, + PossessionsGeneral6, + PossessionsGeneral7, + PossessionsGeneral8, + PossessionsCursor, + PossessionsCount + }; - static const int16 TRADE_BEGIN = 3000; - static const int16 TRADE_END = 3007; - static const int16 TRADE_NPC_END = 3003; - static const int16 TRADE_BAGS_BEGIN = 3031; - static const int16 TRADE_BAGS_END_OFFSET = 79; - static const int16 TRADE_BAGS_END = TRADE_BAGS_BEGIN + TRADE_BAGS_END_OFFSET; + const int EquipmentBegin = PossessionsCharm; + const int EquipmentEnd = PossessionsAmmo; + const int EquipmentCount = (EquipmentEnd - EquipmentBegin + 1); - static const int16 WORLD_BEGIN = 4000; - static const int16 WORLD_END = 4009; + const int GeneralBegin = PossessionsGeneral1; + const int GeneralEnd = PossessionsGeneral8; + const int GeneralCount = (GeneralEnd - GeneralBegin + 1); - static const int16 TRIBUTE_BEGIN = 400; - static const int16 TRIBUTE_END = 404; + } /*invslot*/ - static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; - static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; + namespace invbag { + inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::SoF; } - static const uint16 ITEM_COMMON_SIZE = 5; - static const uint16 ITEM_CONTAINER_SIZE = 10; + enum : int { InvBagInvalid = -1, InvBagBegin }; - static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances - static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance + } /*invbag*/ - static const size_t POTION_BELT_ITEM_COUNT = 5; + namespace invaug { + inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::SoF; } - static const size_t TEXT_LINK_BODY_LENGTH = 50; + enum : int { InvAugInvalid = -1, InvAugBegin }; - static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; - } + } /*invaug*/ - namespace limits { - static const bool ALLOWS_EMPTY_BAG_IN_BAG = false; - static const bool ALLOWS_CLICK_CAST_FROM_BAG = false; - static const bool COIN_HAS_WEIGHT = true; - } + namespace item { + inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::SoF; } + + enum ItemPacketType : int { + ItemPacketMerchant = 100, + ItemPacketTradeView = 101, + ItemPacketLoot = 102, + ItemPacketTrade = 103, + ItemPacketCharInventory = 105, + ItemPacketLimbo = 106, + ItemPacketWorldContainer = 107, + ItemPacketTributeItem = 108, + ItemPacketGuildTribute = 109, + ItemPacketCharmUpdate = 110 + }; + + } /*item*/ + + namespace profile { + inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::SoF; } + + } /*profile*/ + + namespace constants { + inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::SoF; } + + } /*constants*/ + + namespace behavior { + inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::SoF; } + + } /*behavior*/ + + namespace skills { + inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::SoF; } + + } /*skills*/ + + + // declarations + namespace invtype { + const size_t InvTypePossessionsSize = invslot::PossessionsCount; + const size_t InvTypeBankSize = 24; + const size_t InvTypeSharedBankSize = 2; + const size_t InvTypeTradeSize = 8; + const size_t InvTypeWorldSize = 10; + const size_t InvTypeLimboSize = 36; + const size_t InvTypeTributeSize = 5; + const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeMerchantSize = 80; + const size_t InvTypeCorpseSize = InvTypePossessionsSize; + const size_t InvTypeBazaarSize = 80; + const size_t InvTypeInspectSize = invslot::EquipmentCount; + const size_t InvTypeViewMODPCSize = InvTypePossessionsSize; + const size_t InvTypeViewMODBankSize = InvTypeBankSize; + const size_t InvTypeViewMODSharedBankSize = InvTypeSharedBankSize; + const size_t InvTypeViewMODLimboSize = InvTypeLimboSize; + const size_t InvTypeAltStorageSize = 0;//unknown - "Shroud Bank" + const size_t InvTypeArchivedSize = 0;//unknown + const size_t InvTypeOtherSize = 0;//unknown + + const size_t NPCTradeSize = 4; + + extern size_t InvTypeSize(int inv_type); + extern const char* InvTypeName(int inv_type); + + } /*invtype*/ + + namespace invslot { + const int BankBegin = 2000; + const int BankEnd = (BankBegin + invtype::InvTypeBankSize) - 1; + + const int SharedBankBegin = 2500; + const int SharedBankEnd = (SharedBankBegin + invtype::InvTypeSharedBankSize) - 1; + + const int TradeBegin = 3000; + const int TradeEnd = (TradeBegin + invtype::InvTypeTradeSize) - 1; + const int TradeNPCEnd = 3003; + + const int WorldBegin = 4000; + const int WorldEnd = (WorldBegin + invtype::InvTypeWorldSize) - 1; + + const int TributeBegin = 400; + const int TributeEnd = 404; + + const int CorpseBegin = PossessionsGeneral1; + const int CorpseEnd = PossessionsGeneral1 + PossessionsCursor; + + extern const char* InvPossessionsSlotName(int inv_slot); + extern const char* InvCorpseSlotName(int inv_slot); + extern const char* InvSlotName(int inv_type, int inv_slot); + + } /*invslot*/ + + namespace invbag { + const size_t ItemBagSize = 10; + + const int GeneralBagsBegin = 262; + const int GeneralBagsSize = invslot::GeneralCount * ItemBagSize; + const int GeneralBagsEnd = (GeneralBagsBegin + GeneralBagsSize) - 1; + + const int CursorBagBegin = 342; + const int CursorBagSize = ItemBagSize; + const int CursorBagEnd = (CursorBagBegin + CursorBagSize) - 1; + + const int BankBagsBegin = 2032; + const int BankBagsSize = (invtype::InvTypeBankSize * ItemBagSize); + const int BankBagsEnd = (BankBagsBegin + BankBagsSize) - 1; + + const int SharedBankBagsBegin = 2532; + const int SharedBankBagsSize = invtype::InvTypeSharedBankSize * ItemBagSize; + const int SharedBankBagsEnd = (SharedBankBagsBegin + SharedBankBagsSize) - 1; + + const int TradeBagsBegin = 3031; + const int TradeBagsSize = invtype::InvTypeTradeSize * ItemBagSize; + const int TradeBagsEnd = (TradeBagsBegin + TradeBagsSize) - 1; + + extern const char* InvBagIndexName(int bag_index); + + } /*invbag*/ + + namespace invaug { + const size_t ItemAugSize = 5; + + extern const char* InvAugIndexName(int aug_index); + + } /*invaug*/ + + namespace item { + + } /*item*/ + + namespace profile { + const size_t TributeSize = invtype::InvTypeTributeSize; + + const size_t BandoliersSize = 20; // number of bandolier instances + const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance + + const size_t PotionBeltSize = 5; + + const size_t SkillArraySize = 100; + + } /*profile*/ + + namespace constants { + const size_t CharacterCreationLimit = 12; + + const size_t SayLinkBodySize = 50; + + } /*constants*/ + + namespace behavior { + const bool ConcatenateInvTypeLimbo = true; + + const bool AllowOverLevelEquipment = false; + + const bool AllowEmptyBagInBag = false; + const bool AllowClickCastFromBag = false; + + const bool CoinHasWeight = true; + + } /*behavior*/ + + namespace skills { + const size_t LastUsableSkill = EQEmu::skills::SkillTripleAttack; + + } /*skills*/ }; /*SoF*/ -#endif /*COMMON_SOF_CONSTANTS_H*/ +#endif /*COMMON_SOF_LIMITS_H*/ diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 79941cd38..98fecd469 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -705,7 +705,7 @@ struct BandolierItem_Struct struct Bandolier_Struct { char Name[32]; - BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT]; + BandolierItem_Struct Items[profile::BandolierItemCount]; }; //len = 72 @@ -719,7 +719,7 @@ struct PotionBeltItem_Struct //len = 288 struct PotionBelt_Struct { - PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT]; + PotionBeltItem_Struct Items[profile::PotionBeltSize]; }; static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16; @@ -938,7 +938,7 @@ struct PlayerProfile_Struct //23576 Octets /*08288*/ uint32 aapoints_spent; // Number of spent AA points /*08292*/ uint32 aapoints; // Unspent AA points /*08296*/ uint8 unknown06160[4]; -/*08300*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [6400] bandolier contents +/*08300*/ Bandolier_Struct bandoliers[profile::BandoliersSize]; // [6400] bandolier contents /*14700*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot /*15060*/ uint8 unknown12852[8]; /*15068*/ uint32 available_slots; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 3cde09beb..0cdb9e848 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -966,18 +966,18 @@ namespace Titanium // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < profile::BandoliersSize; ++r) { OUT_str(bandoliers[r].Name); - for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true + for (uint32 k = 0; k < profile::BandolierItemCount; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); OUT(bandoliers[r].Items[k].Icon); OUT_str(bandoliers[r].Items[k].Name); } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < profile::BandoliersSize; ++r) { eq->bandoliers[r].Name[0] = '\0'; - for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true + for (uint32 k = 0; k < profile::BandolierItemCount; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; eq->bandoliers[r].Items[k].Icon = 0; eq->bandoliers[r].Items[k].Name[0] = '\0'; @@ -987,13 +987,13 @@ namespace Titanium // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < profile::PotionBeltSize; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < profile::PotionBeltSize; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -2325,7 +2325,7 @@ namespace Titanium ob << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data // Sub data - for (int index = SUB_INDEX_BEGIN; index < consts::ITEM_CONTAINER_SIZE; ++index) { + for (int index = SUB_INDEX_BEGIN; index < invbag::ItemBagSize; ++index) { ob << '|'; ItemInst* sub = inst->GetItem(index); @@ -2373,7 +2373,7 @@ namespace Titanium static inline void ServerToTitaniumTextLink(std::string& titaniumTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { titaniumTextLink = serverTextLink; return; } @@ -2413,7 +2413,7 @@ namespace Titanium static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink) { - if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (titaniumTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (titaniumTextLink.find('\x12') == std::string::npos)) { serverTextLink = titaniumTextLink; return; } @@ -2422,7 +2422,7 @@ namespace Titanium for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= constants::SayLinkBodySize) { serverTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; diff --git a/common/patches/titanium_limits.cpp b/common/patches/titanium_limits.cpp index 93a5c7a3d..2d5faac6b 100644 --- a/common/patches/titanium_limits.cpp +++ b/common/patches/titanium_limits.cpp @@ -16,3 +16,238 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "titanium_limits.h" + +#include "../string_util.h" + + +size_t Titanium::invtype::InvTypeSize(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + return invtype::InvTypePossessionsSize; + case invtype::InvTypeBank: + return invtype::InvTypeBankSize; + case invtype::InvTypeSharedBank: + return invtype::InvTypeSharedBankSize; + case invtype::InvTypeTrade: + return invtype::InvTypeTradeSize; + case invtype::InvTypeWorld: + return invtype::InvTypeWorldSize; + case invtype::InvTypeLimbo: + return invtype::InvTypeLimboSize; + case invtype::InvTypeTribute: + return invtype::InvTypeTributeSize; + case invtype::InvTypeGuildTribute: + return invtype::InvTypeGuildTributeSize; + case invtype::InvTypeMerchant: + return invtype::InvTypeMerchantSize; + case invtype::InvTypeCorpse: + return invtype::InvTypeCorpseSize; + case invtype::InvTypeBazaar: + return invtype::InvTypeBazaarSize; + case invtype::InvTypeInspect: + return invtype::InvTypeInspectSize; + case invtype::InvTypeViewMODPC: + return invtype::InvTypeViewMODPCSize; + case invtype::InvTypeViewMODBank: + return invtype::InvTypeViewMODBankSize; + case invtype::InvTypeViewMODSharedBank: + return invtype::InvTypeViewMODSharedBankSize; + case invtype::InvTypeViewMODLimbo: + return invtype::InvTypeViewMODLimboSize; + case invtype::InvTypeAltStorage: + return invtype::InvTypeAltStorageSize; + case invtype::InvTypeArchived: + return invtype::InvTypeArchivedSize; + case invtype::InvTypeOther: + return invtype::InvTypeOtherSize; + default: + return 0; + } +} + +const char* Titanium::invtype::InvTypeName(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypeInvalid: + return "Invalid Type"; + case invtype::InvTypePossessions: + return "Possessions"; + case invtype::InvTypeBank: + return "Bank"; + case invtype::InvTypeSharedBank: + return "Shared Bank"; + case invtype::InvTypeTrade: + return "Trade"; + case invtype::InvTypeWorld: + return "World"; + case invtype::InvTypeLimbo: + return "Limbo"; + case invtype::InvTypeTribute: + return "Tribute"; + case invtype::InvTypeGuildTribute: + return "Guild Tribute"; + case invtype::InvTypeMerchant: + return "Merchant"; + case invtype::InvTypeCorpse: + return "Corpse"; + case invtype::InvTypeBazaar: + return "Bazaar"; + case invtype::InvTypeInspect: + return "Inspect"; + case invtype::InvTypeViewMODPC: + return "View MOD PC"; + case invtype::InvTypeViewMODBank: + return "View MOD Bank"; + case invtype::InvTypeViewMODSharedBank: + return "View MOD Shared Bank"; + case invtype::InvTypeViewMODLimbo: + return "View MOD Limbo"; + case invtype::InvTypeAltStorage: + return "Alt Storage"; + case invtype::InvTypeArchived: + return "Archived"; + case invtype::InvTypeOther: + return "Other"; + default: + return "Unknown Type"; + } +} + +const char* Titanium::invslot::InvPossessionsSlotName(int inv_slot) +{ + switch (inv_slot) { + case invslot::InvSlotInvalid: + return "Invalid Slot"; + case invslot::PossessionsCharm: + return "Charm"; + case invslot::PossessionsEar1: + return "Ear 1"; + case invslot::PossessionsHead: + return "Head"; + case invslot::PossessionsFace: + return "Face"; + case invslot::PossessionsEar2: + return "Ear 2"; + case invslot::PossessionsNeck: + return "Neck"; + case invslot::PossessionsShoulders: + return "Shoulders"; + case invslot::PossessionsArms: + return "Arms"; + case invslot::PossessionsBack: + return "Back"; + case invslot::PossessionsWrist1: + return "Wrist 1"; + case invslot::PossessionsWrist2: + return "Wrist 2"; + case invslot::PossessionsRange: + return "Range"; + case invslot::PossessionsHands: + return "Hands"; + case invslot::PossessionsPrimary: + return "Primary"; + case invslot::PossessionsSecondary: + return "Secondary"; + case invslot::PossessionsFinger1: + return "Finger 1"; + case invslot::PossessionsFinger2: + return "Finger 2"; + case invslot::PossessionsChest: + return "Chest"; + case invslot::PossessionsLegs: + return "Legs"; + case invslot::PossessionsFeet: + return "Feet"; + case invslot::PossessionsWaist: + return "Waist"; + case invslot::PossessionsAmmo: + return "Ammo"; + case invslot::PossessionsGeneral1: + return "General 1"; + case invslot::PossessionsGeneral2: + return "General 2"; + case invslot::PossessionsGeneral3: + return "General 3"; + case invslot::PossessionsGeneral4: + return "General 4"; + case invslot::PossessionsGeneral5: + return "General 5"; + case invslot::PossessionsGeneral6: + return "General 6"; + case invslot::PossessionsGeneral7: + return "General 7"; + case invslot::PossessionsGeneral8: + return "General 8"; + case invslot::PossessionsCursor: + return "Cursor"; + default: + return "Unknown Slot"; + } +} + +const char* Titanium::invslot::InvCorpseSlotName(int inv_slot) +{ + if (!invtype::InvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) + return "Invalid Slot"; + + // needs work + if ((size_t)(inv_slot + 1) < invslot::CorpseBegin || (size_t)(inv_slot + 1) >= invslot::CorpseEnd) + return "Unknown Slot"; + + static std::string ret_str; + ret_str = StringFormat("Slot %i", (inv_slot + 1)); + + return ret_str.c_str(); +} + +const char* Titanium::invslot::InvSlotName(int inv_type, int inv_slot) +{ + if (inv_type == invtype::InvTypePossessions) + return invslot::InvPossessionsSlotName(inv_slot); + else if (inv_type == invtype::InvTypeCorpse) + return invslot::InvCorpseSlotName(inv_slot); + + size_t type_size = invtype::InvTypeSize(inv_type); + + if (!type_size || inv_slot == invslot::InvSlotInvalid) + return "Invalid Slot"; + + if ((size_t)(inv_slot + 1) >= type_size) + return "Unknown Slot"; + + static std::string ret_str; + ret_str = StringFormat("Slot %i", (inv_slot + 1)); + + return ret_str.c_str(); +} + +const char* Titanium::invbag::InvBagIndexName(int bag_index) +{ + if (bag_index == invbag::InvBagInvalid) + return "Invalid Bag"; + + if ((size_t)bag_index >= invbag::ItemBagSize) + return "Unknown Bag"; + + static std::string ret_str; + ret_str = StringFormat("Bag %i", (bag_index + 1)); + + return ret_str.c_str(); +} + +const char* Titanium::invaug::InvAugIndexName(int aug_index) +{ + if (aug_index == invaug::InvAugInvalid) + return "Invalid Augment"; + + if ((size_t)aug_index >= invaug::ItemAugSize) + return "Unknown Augment"; + + static std::string ret_str; + ret_str = StringFormat("Augment %i", (aug_index + 1)); + + return ret_str.c_str(); +} diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index 220ad99c7..cbb023efd 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -17,177 +17,283 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_TITANIUM_CONSTANTS_H -#define COMMON_TITANIUM_CONSTANTS_H +#ifndef COMMON_TITANIUM_LIMITS_H +#define COMMON_TITANIUM_LIMITS_H #include "../types.h" +#include "../client_version.h" +#include "../skills.h" namespace Titanium { - namespace inventory { - typedef enum : int16 { - TypePossessions = 0, - TypeBank, - TypeSharedBank, - TypeTrade, - TypeWorld, - TypeLimbo, - TypeTribute, - TypeTrophyTribute, - TypeGuildTribute, - TypeMerchant, - TypeDeleted, - TypeCorpse, - TypeBazaar, - TypeInspect, - TypeRealEstate, - TypeViewMODPC, - TypeViewMODBank, - TypeViewMODSharedBank, - TypeViewMODLimbo, - TypeAltStorage, - TypeArchived, - TypeMail, - TypeGuildTrophyTribute, - TypeOther, - TypeCount - } InventoryTypes; + enum : int { Invalid = -1, Null, Safety }; - typedef enum : int16 { - SlotCharm = 0, - SlotEar1, - SlotHead, - SlotFace, - SlotEar2, - SlotNeck, - SlotShoulders, - SlotArms, - SlotBack, - SlotWrist1, - SlotWrist2, - SlotRange, - SlotHands, - SlotPrimary, - SlotSecondary, - SlotFinger1, - SlotFinger2, - SlotChest, - SlotLegs, - SlotFeet, - SlotWaist, - SlotAmmo, - SlotGeneral1, - SlotGeneral2, - SlotGeneral3, - SlotGeneral4, - SlotGeneral5, - SlotGeneral6, - SlotGeneral7, - SlotGeneral8, - SlotCursor, - SlotCount, - SlotEquipmentBegin = SlotCharm, - SlotEquipmentEnd = SlotAmmo, - SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), - SlotGeneralBegin = SlotGeneral1, - SlotGeneralEnd = SlotGeneral8, - SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) - } PossessionsSlots; - } + enum : bool { False = false, True = true }; + + // pre-declarations + namespace invtype { + inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::Titanium; } - namespace consts { - static const size_t CHARACTER_CREATION_LIMIT = 8; // Hard-coded in client - DO NOT ALTER + enum : int { InvTypeInvalid = -1, InvTypeBegin }; - static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; - static const uint16 TYPE_BANK_SIZE = 16; - static const uint16 TYPE_SHARED_BANK_SIZE = 2; - static const uint16 TYPE_TRADE_SIZE = 8; - static const uint16 TYPE_WORLD_SIZE = 10; - static const uint16 TYPE_LIMBO_SIZE = 36; - static const uint16 TYPE_TRIBUTE_SIZE = 0; //? - static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; - static const uint16 TYPE_MERCHANT_SIZE = 0; - static const uint16 TYPE_DELETED_SIZE = 0; - static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; - static const uint16 TYPE_BAZAAR_SIZE = 80; - static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; - static const uint16 TYPE_REAL_ESTATE_SIZE = 0; - static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; - static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; - static const uint16 TYPE_ALT_STORAGE_SIZE = 0; - static const uint16 TYPE_ARCHIVED_SIZE = 0; - static const uint16 TYPE_MAIL_SIZE = 0; - static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_KRONO_SIZE = NOT_USED; - static const uint16 TYPE_OTHER_SIZE = 0; + enum InventoryType : int { + InvTypePossessions = InvTypeBegin, + InvTypeBank, + InvTypeSharedBank, + InvTypeTrade, + InvTypeWorld, + InvTypeLimbo, + InvTypeTribute, + InvTypeGuildTribute, + InvTypeMerchant, + InvTypeCorpse, + InvTypeBazaar, + InvTypeInspect, + InvTypeViewMODPC, + InvTypeViewMODBank, + InvTypeViewMODSharedBank, + InvTypeViewMODLimbo, + InvTypeAltStorage, + InvTypeArchived, + InvTypeOther, + InvTypeCount + }; - static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; - static const int16 EQUIPMENT_END = inventory::SlotAmmo; - static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; + } /*invtype*/ - static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; - static const int16 GENERAL_END = inventory::SlotGeneral8; - static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; - static const int16 GENERAL_BAGS_BEGIN = 251; - static const int16 GENERAL_BAGS_END_OFFSET = 79; - static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; + namespace invslot { + inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::Titanium; } - static const int16 CURSOR = inventory::SlotCursor; - static const int16 CURSOR_BAG_BEGIN = 331; - static const int16 CURSOR_BAG_END_OFFSET = 9; - static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; + enum : int { InvSlotInvalid = -1, InvSlotBegin }; - static const int16 BANK_BEGIN = 2000; - static const int16 BANK_END = 2015; - static const int16 BANK_BAGS_BEGIN = 2031; - static const int16 BANK_BAGS_END_OFFSET = 159; - static const int16 BANK_BAGS_END = BANK_BAGS_BEGIN + BANK_BAGS_END_OFFSET; + enum PossessionsSlot : int { + PossessionsCharm = InvSlotBegin, + PossessionsEar1, + PossessionsHead, + PossessionsFace, + PossessionsEar2, + PossessionsNeck, + PossessionsShoulders, + PossessionsArms, + PossessionsBack, + PossessionsWrist1, + PossessionsWrist2, + PossessionsRange, + PossessionsHands, + PossessionsPrimary, + PossessionsSecondary, + PossessionsFinger1, + PossessionsFinger2, + PossessionsChest, + PossessionsLegs, + PossessionsFeet, + PossessionsWaist, + PossessionsAmmo, + PossessionsGeneral1, + PossessionsGeneral2, + PossessionsGeneral3, + PossessionsGeneral4, + PossessionsGeneral5, + PossessionsGeneral6, + PossessionsGeneral7, + PossessionsGeneral8, + PossessionsCursor, + PossessionsCount + }; - static const int16 SHARED_BANK_BEGIN = 2500; - static const int16 SHARED_BANK_END = 2501; - static const int16 SHARED_BANK_BAGS_BEGIN = 2531; - static const int16 SHARED_BANK_BAGS_END_OFFSET = 19; - static const int16 SHARED_BANK_BAGS_END = SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_END_OFFSET; + const int EquipmentBegin = PossessionsCharm; + const int EquipmentEnd = PossessionsAmmo; + const int EquipmentCount = (EquipmentEnd - EquipmentBegin + 1); - static const int16 TRADE_BEGIN = 3000; - static const int16 TRADE_END = 3007; - static const int16 TRADE_NPC_END = 3003; - static const int16 TRADE_BAGS_BEGIN = 3031; - static const int16 TRADE_BAGS_END_OFFSET = 79; - static const int16 TRADE_BAGS_END = TRADE_BAGS_BEGIN + TRADE_BAGS_END_OFFSET; + const int GeneralBegin = PossessionsGeneral1; + const int GeneralEnd = PossessionsGeneral8; + const int GeneralCount = (GeneralEnd - GeneralBegin + 1); - static const int16 WORLD_BEGIN = 4000; - static const int16 WORLD_END = 4009; + } /*invslot*/ - static const int16 TRIBUTE_BEGIN = 400; - static const int16 TRIBUTE_END = 404; + namespace invbag { + inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::Titanium; } - static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; - static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; + enum : int { InvBagInvalid = -1, InvBagBegin }; - static const uint16 ITEM_COMMON_SIZE = 5; - static const uint16 ITEM_CONTAINER_SIZE = 10; + } /*invbag*/ - static const size_t BANDOLIERS_SIZE = 4; // number of bandolier instances - static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance + namespace invaug { + inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::Titanium; } - static const size_t POTION_BELT_ITEM_COUNT = 4; + enum : int { InvAugInvalid = -1, InvAugBegin }; - static const size_t TEXT_LINK_BODY_LENGTH = 45; + } /*invaug*/ - static const size_t PLAYER_PROFILE_SKILL_MAX = SkillFrenzy; - } + namespace item { + inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::Titanium; } - namespace limits { - static const bool ALLOWS_EMPTY_BAG_IN_BAG = false; - static const bool ALLOWS_CLICK_CAST_FROM_BAG = false; - static const bool COIN_HAS_WEIGHT = true; - } + enum ItemPacketType : int { + ItemPacketMerchant = 100, + ItemPacketTradeView = 101, + ItemPacketLoot = 102, + ItemPacketTrade = 103, + ItemPacketCharInventory = 105, + ItemPacketLimbo = 106, + ItemPacketWorldContainer = 107, + ItemPacketTributeItem = 108, + ItemPacketGuildTribute = 109, + ItemPacketCharmUpdate = 110 + }; + + } /*item*/ + + namespace profile { + inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::Titanium; } + + } /*profile*/ + + namespace constants { + inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::Titanium; } + + } /*constants*/ + + namespace behavior { + inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::Titanium; } + + } /*behavior*/ + + namespace skills { + inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::Titanium; } + + } /*skills*/ + + + // declarations + namespace invtype { + const size_t InvTypePossessionsSize = invslot::PossessionsCount; + const size_t InvTypeBankSize = 16; + const size_t InvTypeSharedBankSize = 2; + const size_t InvTypeTradeSize = 8; + const size_t InvTypeWorldSize = 10; + const size_t InvTypeLimboSize = 36; + const size_t InvTypeTributeSize = 5; + const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeMerchantSize = 80; + const size_t InvTypeCorpseSize = InvTypePossessionsSize; + const size_t InvTypeBazaarSize = 80; + const size_t InvTypeInspectSize = invslot::EquipmentCount; + const size_t InvTypeViewMODPCSize = InvTypePossessionsSize; + const size_t InvTypeViewMODBankSize = InvTypeBankSize; + const size_t InvTypeViewMODSharedBankSize = InvTypeSharedBankSize; + const size_t InvTypeViewMODLimboSize = InvTypeLimboSize; + const size_t InvTypeAltStorageSize = 0;//unknown - "Shroud Bank" + const size_t InvTypeArchivedSize = 0;//unknown + const size_t InvTypeOtherSize = 0;//unknown + + const size_t NPCTradeSize = 4; + + extern size_t InvTypeSize(int inv_type); + extern const char* InvTypeName(int inv_type); + + } /*invtype*/ + + namespace invslot { + const int BankBegin = 2000; + const int BankEnd = (BankBegin + invtype::InvTypeBankSize) - 1; + + const int SharedBankBegin = 2500; + const int SharedBankEnd = (SharedBankBegin + invtype::InvTypeSharedBankSize) - 1; + + const int TradeBegin = 3000; + const int TradeEnd = (TradeBegin + invtype::InvTypeTradeSize) - 1; + const int TradeNPCEnd = 3003; + + const int WorldBegin = 4000; + const int WorldEnd = (WorldBegin + invtype::InvTypeWorldSize) - 1; + + const int TributeBegin = 400; + const int TributeEnd = 404; + + const int CorpseBegin = PossessionsGeneral1; + const int CorpseEnd = PossessionsGeneral1 + PossessionsCursor; + + extern const char* InvPossessionsSlotName(int inv_slot); + extern const char* InvCorpseSlotName(int inv_slot); + extern const char* InvSlotName(int inv_type, int inv_slot); + + } /*invslot*/ + + namespace invbag { + const size_t ItemBagSize = 10; + + const int GeneralBagsBegin = 251; + const int GeneralBagsSize = invslot::GeneralCount * ItemBagSize; + const int GeneralBagsEnd = (GeneralBagsBegin + GeneralBagsSize) - 1; + + const int CursorBagBegin = 331; + const int CursorBagSize = ItemBagSize; + const int CursorBagEnd = (CursorBagBegin + CursorBagSize) - 1; + + const int BankBagsBegin = 2031; + const int BankBagsSize = (invtype::InvTypeBankSize * ItemBagSize); + const int BankBagsEnd = (BankBagsBegin + BankBagsSize) - 1; + + const int SharedBankBagsBegin = 2531; + const int SharedBankBagsSize = invtype::InvTypeSharedBankSize * ItemBagSize; + const int SharedBankBagsEnd = (SharedBankBagsBegin + SharedBankBagsSize) - 1; + + const int TradeBagsBegin = 3031; + const int TradeBagsSize = invtype::InvTypeTradeSize * ItemBagSize; + const int TradeBagsEnd = (TradeBagsBegin + TradeBagsSize) - 1; + + extern const char* InvBagIndexName(int bag_index); + + } /*invbag*/ + + namespace invaug { + const size_t ItemAugSize = 5; + + extern const char* InvAugIndexName(int aug_index); + + } /*invaug*/ + + namespace item { + + } /*item*/ + + namespace profile { + const size_t TributeSize = invtype::InvTypeTributeSize; + + const size_t BandoliersSize = 4; // number of bandolier instances + const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance + + const size_t PotionBeltSize = 4; + + const size_t SkillArraySize = 100; + + } /*profile*/ + + namespace constants { + const size_t CharacterCreationLimit = 8; // Hard-coded in client - DO NOT ALTER + + const size_t SayLinkBodySize = 45; + + } /*constants*/ + + namespace behavior { + const bool ConcatenateInvTypeLimbo = true; + + const bool AllowOverLevelEquipment = false; + + const bool AllowEmptyBagInBag = false; + const bool AllowClickCastFromBag = false; + + const bool CoinHasWeight = true; + + } /*behavior*/ + + namespace skills { + const size_t LastUsableSkill = EQEmu::skills::SkillFrenzy; + + } /*skills*/ }; /*Titanium*/ -#endif /*COMMON_TITANIUM_CONSTANTS_H*/ +#endif /*COMMON_TITANIUM_LIMITS_H*/ diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index d3a382855..141966b09 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -633,7 +633,7 @@ struct BandolierItem_Struct struct Bandolier_Struct { char Name[32]; - BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT]; + BandolierItem_Struct Items[profile::BandolierItemCount]; }; //len = 72 @@ -647,7 +647,7 @@ struct PotionBeltItem_Struct //len = 288 struct PotionBelt_Struct { - PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT]; + PotionBeltItem_Struct Items[profile::PotionBeltSize]; }; static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16; @@ -851,7 +851,7 @@ struct PlayerProfile_Struct /*06152*/ uint32 aapoints_spent; // Number of spent AA points /*06156*/ uint32 aapoints; // Unspent AA points /*06160*/ uint8 unknown06160[4]; -/*06164*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // bandolier contents +/*06164*/ Bandolier_Struct bandoliers[profile::BandoliersSize]; // bandolier contents /*07444*/ uint8 unknown07444[5120]; /*12564*/ PotionBelt_Struct potionbelt; // potion belt /*12852*/ uint8 unknown12852[8]; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index d07914cb8..cb3fc68e3 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1891,18 +1891,18 @@ namespace UF // OUT(unknown06160[4]); // Copy bandoliers where server and client indexes converge - for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < consts::BANDOLIERS_SIZE; ++r) { + for (r = 0; r < EQEmu::legacy::BANDOLIERS_SIZE && r < profile::BandoliersSize; ++r) { OUT_str(bandoliers[r].Name); - for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true + for (uint32 k = 0; k < profile::BandolierItemCount; ++k) { // Will need adjusting if 'server != client' is ever true OUT(bandoliers[r].Items[k].ID); OUT(bandoliers[r].Items[k].Icon); OUT_str(bandoliers[r].Items[k].Name); } } // Nullify bandoliers where server and client indexes diverge, with a client bias - for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < consts::BANDOLIERS_SIZE; ++r) { + for (r = EQEmu::legacy::BANDOLIERS_SIZE; r < profile::BandoliersSize; ++r) { eq->bandoliers[r].Name[0] = '\0'; - for (uint32 k = 0; k < consts::BANDOLIER_ITEM_COUNT; ++k) { // Will need adjusting if 'server != client' is ever true + for (uint32 k = 0; k < profile::BandolierItemCount; ++k) { // Will need adjusting if 'server != client' is ever true eq->bandoliers[r].Items[k].ID = 0; eq->bandoliers[r].Items[k].Icon = 0; eq->bandoliers[r].Items[k].Name[0] = '\0'; @@ -1912,13 +1912,13 @@ namespace UF // OUT(unknown07444[5120]); // Copy potion belt where server and client indexes converge - for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = 0; r < EQEmu::legacy::POTION_BELT_ITEM_COUNT && r < profile::PotionBeltSize; ++r) { OUT(potionbelt.Items[r].ID); OUT(potionbelt.Items[r].Icon); OUT_str(potionbelt.Items[r].Name); } // Nullify potion belt where server and client indexes diverge, with a client bias - for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < consts::POTION_BELT_ITEM_COUNT; ++r) { + for (r = EQEmu::legacy::POTION_BELT_ITEM_COUNT; r < profile::PotionBeltSize; ++r) { eq->potionbelt.Items[r].ID = 0; eq->potionbelt.Items[r].Icon = 0; eq->potionbelt.Items[r].Name[0] = '\0'; @@ -2227,8 +2227,8 @@ namespace UF eq->CharCount = emu->CharCount; eq->TotalChars = emu->TotalChars; - if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT) - eq->TotalChars = consts::CHARACTER_CREATION_LIMIT; + if (eq->TotalChars > constants::CharacterCreationLimit) + eq->TotalChars = constants::CharacterCreationLimit; // Special Underfoot adjustment - field should really be 'AdditionalChars' or 'BonusChars' uint32 adjusted_total = eq->TotalChars - 8; // Yes, it rolls under for '< 8' - probably an int32 field @@ -2244,7 +2244,7 @@ namespace UF size_t names_length = 0; size_t character_count = 0; - for (; character_count < emu->CharCount && character_count < consts::CHARACTER_CREATION_LIMIT; ++character_count) { + for (; character_count < emu->CharCount && character_count < constants::CharacterCreationLimit; ++character_count) { emu_cse = (CharacterSelectEntry_Struct *)emu_ptr; names_length += strlen(emu_cse->Name); emu_ptr += sizeof(CharacterSelectEntry_Struct); @@ -2260,8 +2260,8 @@ namespace UF eq->CharCount = character_count; eq->TotalChars = emu->TotalChars; - if (eq->TotalChars > consts::CHARACTER_CREATION_LIMIT) - eq->TotalChars = consts::CHARACTER_CREATION_LIMIT; + if (eq->TotalChars > constants::CharacterCreationLimit) + eq->TotalChars = constants::CharacterCreationLimit; // Special Underfoot adjustment - field should really be 'AdditionalChars' or 'BonusChars' in this client uint32 adjusted_total = eq->TotalChars - 8; // Yes, it rolls under for '< 8' - probably an int32 field @@ -4020,7 +4020,7 @@ namespace UF isbs.augtype = item->AugType; isbs.augrestrict = item->AugRestrict; - for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) { + for (int index = 0; index < invaug::ItemAugSize; ++index) { isbs.augslots[index].type = item->AugSlotType[index]; isbs.augslots[index].visible = item->AugSlotVisible[index]; isbs.augslots[index].unknown = item->AugSlotUnk2[index]; @@ -4254,7 +4254,7 @@ namespace UF else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) UnderfootSlot = serverSlot + 1; else if (serverSlot == EQEmu::legacy::SlotPowerSource) - UnderfootSlot = inventory::SlotPowerSource; + UnderfootSlot = invslot::PossessionsPowerSource; else UnderfootSlot = serverSlot; @@ -4271,15 +4271,15 @@ namespace UF { uint32 ServerSlot = 0; - if (ufSlot >= inventory::SlotAmmo && ufSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (ufSlot >= invslot::PossessionsAmmo && ufSlot <= invslot::CorpseEnd) // Cursor/Ammo/Power Source and Normal Inventory Slots ServerSlot = ufSlot - 1; - else if (ufSlot >= consts::GENERAL_BAGS_BEGIN && ufSlot <= consts::CURSOR_BAG_END) + else if (ufSlot >= invbag::GeneralBagsBegin && ufSlot <= invbag::CursorBagEnd) ServerSlot = ufSlot - 11; - else if (ufSlot >= consts::BANK_BAGS_BEGIN && ufSlot <= consts::BANK_BAGS_END) + else if (ufSlot >= invbag::BankBagsBegin && ufSlot <= invbag::BankBagsEnd) ServerSlot = ufSlot - 1; - else if (ufSlot >= consts::SHARED_BANK_BAGS_BEGIN && ufSlot <= consts::SHARED_BANK_BAGS_END) + else if (ufSlot >= invbag::SharedBankBagsBegin && ufSlot <= invbag::SharedBankBagsEnd) ServerSlot = ufSlot - 1; - else if (ufSlot == inventory::SlotPowerSource) + else if (ufSlot == invslot::PossessionsPowerSource) ServerSlot = EQEmu::legacy::SlotPowerSource; else ServerSlot = ufSlot; @@ -4295,7 +4295,7 @@ namespace UF static inline void ServerToUFTextLink(std::string& ufTextLink, const std::string& serverTextLink) { - if ((consts::TEXT_LINK_BODY_LENGTH == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { + if ((constants::SayLinkBodySize == EQEmu::legacy::TEXT_LINK_BODY_LENGTH) || (serverTextLink.find('\x12') == std::string::npos)) { ufTextLink = serverTextLink; return; } @@ -4335,7 +4335,7 @@ namespace UF static inline void UFToServerTextLink(std::string& serverTextLink, const std::string& ufTextLink) { - if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == consts::TEXT_LINK_BODY_LENGTH) || (ufTextLink.find('\x12') == std::string::npos)) { + if ((EQEmu::legacy::TEXT_LINK_BODY_LENGTH == constants::SayLinkBodySize) || (ufTextLink.find('\x12') == std::string::npos)) { serverTextLink = ufTextLink; return; } @@ -4344,7 +4344,7 @@ namespace UF for (size_t segment_iter = 0; segment_iter < segments.size(); ++segment_iter) { if (segment_iter & 1) { - if (segments[segment_iter].length() <= consts::TEXT_LINK_BODY_LENGTH) { + if (segments[segment_iter].length() <= constants::SayLinkBodySize) { serverTextLink.append(segments[segment_iter]); // TODO: log size mismatch error continue; diff --git a/common/patches/uf_limits.cpp b/common/patches/uf_limits.cpp index 93a5c7a3d..8e72b8b03 100644 --- a/common/patches/uf_limits.cpp +++ b/common/patches/uf_limits.cpp @@ -16,3 +16,240 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "uf_limits.h" + +#include "../string_util.h" + + +size_t UF::invtype::InvTypeSize(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + return invtype::InvTypePossessionsSize; + case invtype::InvTypeBank: + return invtype::InvTypeBankSize; + case invtype::InvTypeSharedBank: + return invtype::InvTypeSharedBankSize; + case invtype::InvTypeTrade: + return invtype::InvTypeTradeSize; + case invtype::InvTypeWorld: + return invtype::InvTypeWorldSize; + case invtype::InvTypeLimbo: + return invtype::InvTypeLimboSize; + case invtype::InvTypeTribute: + return invtype::InvTypeTributeSize; + case invtype::InvTypeGuildTribute: + return invtype::InvTypeGuildTributeSize; + case invtype::InvTypeMerchant: + return invtype::InvTypeMerchantSize; + case invtype::InvTypeCorpse: + return invtype::InvTypeCorpseSize; + case invtype::InvTypeBazaar: + return invtype::InvTypeBazaarSize; + case invtype::InvTypeInspect: + return invtype::InvTypeInspectSize; + case invtype::InvTypeViewMODPC: + return invtype::InvTypeViewMODPCSize; + case invtype::InvTypeViewMODBank: + return invtype::InvTypeViewMODBankSize; + case invtype::InvTypeViewMODSharedBank: + return invtype::InvTypeViewMODSharedBankSize; + case invtype::InvTypeViewMODLimbo: + return invtype::InvTypeViewMODLimboSize; + case invtype::InvTypeAltStorage: + return invtype::InvTypeAltStorageSize; + case invtype::InvTypeArchived: + return invtype::InvTypeArchivedSize; + case invtype::InvTypeOther: + return invtype::InvTypeOtherSize; + default: + return 0; + } +} + +const char* UF::invtype::InvTypeName(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypeInvalid: + return "Invalid Type"; + case invtype::InvTypePossessions: + return "Possessions"; + case invtype::InvTypeBank: + return "Bank"; + case invtype::InvTypeSharedBank: + return "Shared Bank"; + case invtype::InvTypeTrade: + return "Trade"; + case invtype::InvTypeWorld: + return "World"; + case invtype::InvTypeLimbo: + return "Limbo"; + case invtype::InvTypeTribute: + return "Tribute"; + case invtype::InvTypeGuildTribute: + return "Guild Tribute"; + case invtype::InvTypeMerchant: + return "Merchant"; + case invtype::InvTypeCorpse: + return "Corpse"; + case invtype::InvTypeBazaar: + return "Bazaar"; + case invtype::InvTypeInspect: + return "Inspect"; + case invtype::InvTypeViewMODPC: + return "View MOD PC"; + case invtype::InvTypeViewMODBank: + return "View MOD Bank"; + case invtype::InvTypeViewMODSharedBank: + return "View MOD Shared Bank"; + case invtype::InvTypeViewMODLimbo: + return "View MOD Limbo"; + case invtype::InvTypeAltStorage: + return "Alt Storage"; + case invtype::InvTypeArchived: + return "Archived"; + case invtype::InvTypeOther: + return "Other"; + default: + return "Unknown Type"; + } +} + +const char* UF::invslot::InvPossessionsSlotName(int inv_slot) +{ + switch (inv_slot) { + case invslot::InvSlotInvalid: + return "Invalid Slot"; + case invslot::PossessionsCharm: + return "Charm"; + case invslot::PossessionsEar1: + return "Ear 1"; + case invslot::PossessionsHead: + return "Head"; + case invslot::PossessionsFace: + return "Face"; + case invslot::PossessionsEar2: + return "Ear 2"; + case invslot::PossessionsNeck: + return "Neck"; + case invslot::PossessionsShoulders: + return "Shoulders"; + case invslot::PossessionsArms: + return "Arms"; + case invslot::PossessionsBack: + return "Back"; + case invslot::PossessionsWrist1: + return "Wrist 1"; + case invslot::PossessionsWrist2: + return "Wrist 2"; + case invslot::PossessionsRange: + return "Range"; + case invslot::PossessionsHands: + return "Hands"; + case invslot::PossessionsPrimary: + return "Primary"; + case invslot::PossessionsSecondary: + return "Secondary"; + case invslot::PossessionsFinger1: + return "Finger 1"; + case invslot::PossessionsFinger2: + return "Finger 2"; + case invslot::PossessionsChest: + return "Chest"; + case invslot::PossessionsLegs: + return "Legs"; + case invslot::PossessionsFeet: + return "Feet"; + case invslot::PossessionsWaist: + return "Waist"; + case invslot::PossessionsPowerSource: + return "Power Source"; + case invslot::PossessionsAmmo: + return "Ammo"; + case invslot::PossessionsGeneral1: + return "General 1"; + case invslot::PossessionsGeneral2: + return "General 2"; + case invslot::PossessionsGeneral3: + return "General 3"; + case invslot::PossessionsGeneral4: + return "General 4"; + case invslot::PossessionsGeneral5: + return "General 5"; + case invslot::PossessionsGeneral6: + return "General 6"; + case invslot::PossessionsGeneral7: + return "General 7"; + case invslot::PossessionsGeneral8: + return "General 8"; + case invslot::PossessionsCursor: + return "Cursor"; + default: + return "Unknown Slot"; + } +} + +const char* UF::invslot::InvCorpseSlotName(int inv_slot) +{ + if (!invtype::InvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) + return "Invalid Slot"; + + // needs work + if ((size_t)(inv_slot + 1) < invslot::CorpseBegin || (size_t)(inv_slot + 1) >= invslot::CorpseEnd) + return "Unknown Slot"; + + static std::string ret_str; + ret_str = StringFormat("Slot %i", (inv_slot + 1)); + + return ret_str.c_str(); +} + +const char* UF::invslot::InvSlotName(int inv_type, int inv_slot) +{ + if (inv_type == invtype::InvTypePossessions) + return invslot::InvPossessionsSlotName(inv_slot); + else if (inv_type == invtype::InvTypeCorpse) + return invslot::InvCorpseSlotName(inv_slot); + + size_t type_size = invtype::InvTypeSize(inv_type); + + if (!type_size || inv_slot == invslot::InvSlotInvalid) + return "Invalid Slot"; + + if ((size_t)(inv_slot + 1) >= type_size) + return "Unknown Slot"; + + static std::string ret_str; + ret_str = StringFormat("Slot %i", (inv_slot + 1)); + + return ret_str.c_str(); +} + +const char* UF::invbag::InvBagIndexName(int bag_index) +{ + if (bag_index == invbag::InvBagInvalid) + return "Invalid Bag"; + + if ((size_t)bag_index >= invbag::ItemBagSize) + return "Unknown Bag"; + + static std::string ret_str; + ret_str = StringFormat("Bag %i", (bag_index + 1)); + + return ret_str.c_str(); +} + +const char* UF::invaug::InvAugIndexName(int aug_index) +{ + if (aug_index == invaug::InvAugInvalid) + return "Invalid Augment"; + + if ((size_t)aug_index >= invaug::ItemAugSize) + return "Unknown Augment"; + + static std::string ret_str; + ret_str = StringFormat("Augment %i", (aug_index + 1)); + + return ret_str.c_str(); +} diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index e19c6e014..e44d7f856 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -17,178 +17,285 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_UF_CONSTANTS_H -#define COMMON_UF_CONSTANTS_H +#ifndef COMMON_UF_LIMITS_H +#define COMMON_UF_LIMITS_H #include "../types.h" +#include "../client_version.h" +#include "../skills.h" namespace UF { - namespace inventory { - typedef enum : int16 { - TypePossessions = 0, - TypeBank, - TypeSharedBank, - TypeTrade, - TypeWorld, - TypeLimbo, - TypeTribute, - TypeTrophyTribute, - TypeGuildTribute, - TypeMerchant, - TypeDeleted, - TypeCorpse, - TypeBazaar, - TypeInspect, - TypeRealEstate, - TypeViewMODPC, - TypeViewMODBank, - TypeViewMODSharedBank, - TypeViewMODLimbo, - TypeAltStorage, - TypeArchived, - TypeMail, - TypeGuildTrophyTribute, - TypeOther, - TypeCount - } InventoryTypes; + enum : int { Invalid = -1, Null, Safety }; - typedef enum : int16 { - SlotCharm = 0, - SlotEar1, - SlotHead, - SlotFace, - SlotEar2, - SlotNeck, - SlotShoulders, - SlotArms, - SlotBack, - SlotWrist1, - SlotWrist2, - SlotRange, - SlotHands, - SlotPrimary, - SlotSecondary, - SlotFinger1, - SlotFinger2, - SlotChest, - SlotLegs, - SlotFeet, - SlotWaist, - SlotPowerSource, - SlotAmmo, - SlotGeneral1, - SlotGeneral2, - SlotGeneral3, - SlotGeneral4, - SlotGeneral5, - SlotGeneral6, - SlotGeneral7, - SlotGeneral8, - SlotCursor, - SlotCount, - SlotEquipmentBegin = SlotCharm, - SlotEquipmentEnd = SlotAmmo, - SlotEquipmentCount = (SlotEquipmentEnd - SlotEquipmentBegin + 1), - SlotGeneralBegin = SlotGeneral1, - SlotGeneralEnd = SlotGeneral8, - SlotGeneralCount = (SlotGeneralEnd - SlotGeneralBegin + 1) - } PossessionsSlots; - } + enum : bool { False = false, True = true }; - namespace consts { - static const size_t CHARACTER_CREATION_LIMIT = 12; + // pre-declarations + namespace invtype { + inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::UF; } - static const uint16 TYPE_POSSESSIONS_SIZE = inventory::SlotCount; - static const uint16 TYPE_BANK_SIZE = 24; - static const uint16 TYPE_SHARED_BANK_SIZE = 2; - static const uint16 TYPE_TRADE_SIZE = 8; - static const uint16 TYPE_WORLD_SIZE = 10; - static const uint16 TYPE_LIMBO_SIZE = 36; - static const uint16 TYPE_TRIBUTE_SIZE = 0; //? - static const uint16 TYPE_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; - static const uint16 TYPE_MERCHANT_SIZE = 0; - static const uint16 TYPE_DELETED_SIZE = 0; - static const uint16 TYPE_CORPSE_SIZE = inventory::SlotCount; - static const uint16 TYPE_BAZAAR_SIZE = 80; - static const uint16 TYPE_INSPECT_SIZE = inventory::SlotEquipmentCount; - static const uint16 TYPE_REAL_ESTATE_SIZE = 0; - static const uint16 TYPE_VIEW_MOD_PC_SIZE = TYPE_POSSESSIONS_SIZE; - static const uint16 TYPE_VIEW_MOD_BANK_SIZE = TYPE_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_SHARED_BANK_SIZE = TYPE_SHARED_BANK_SIZE; - static const uint16 TYPE_VIEW_MOD_LIMBO_SIZE = TYPE_LIMBO_SIZE; - static const uint16 TYPE_ALT_STORAGE_SIZE = 0; - static const uint16 TYPE_ARCHIVED_SIZE = 0; - static const uint16 TYPE_MAIL_SIZE = 0; - static const uint16 TYPE_GUILD_TROPHY_TRIBUTE_SIZE = 0; - static const uint16 TYPE_KRONO_SIZE = NOT_USED; - static const uint16 TYPE_OTHER_SIZE = 0; + enum : int { InvTypeInvalid = -1, InvTypeBegin }; - static const int16 EQUIPMENT_BEGIN = inventory::SlotCharm; - static const int16 EQUIPMENT_END = inventory::SlotAmmo; - static const uint16 EQUIPMENT_SIZE = inventory::SlotEquipmentCount; + enum InventoryType : int { + InvTypePossessions = InvTypeBegin, + InvTypeBank, + InvTypeSharedBank, + InvTypeTrade, + InvTypeWorld, + InvTypeLimbo, + InvTypeTribute, + InvTypeGuildTribute, + InvTypeMerchant, + InvTypeCorpse, + InvTypeBazaar, + InvTypeInspect, + InvTypeViewMODPC, + InvTypeViewMODBank, + InvTypeViewMODSharedBank, + InvTypeViewMODLimbo, + InvTypeAltStorage, + InvTypeArchived, + InvTypeOther, + InvTypeCount + }; + + } /*invtype*/ - static const int16 GENERAL_BEGIN = inventory::SlotGeneral1; - static const int16 GENERAL_END = inventory::SlotGeneral8; - static const uint16 GENERAL_SIZE = inventory::SlotGeneralCount; - static const int16 GENERAL_BAGS_BEGIN = 262; - static const int16 GENERAL_BAGS_END_OFFSET = 79; - static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; + namespace invslot { + inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::UF; } - static const int16 CURSOR = inventory::SlotCursor; - static const int16 CURSOR_BAG_BEGIN = 342; - static const int16 CURSOR_BAG_END_OFFSET = 9; - static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; + enum : int { InvSlotInvalid = -1, InvSlotBegin }; - static const int16 BANK_BEGIN = 2000; - static const int16 BANK_END = 2023; - static const int16 BANK_BAGS_BEGIN = 2032; - static const int16 BANK_BAGS_END_OFFSET = 239; - static const int16 BANK_BAGS_END = BANK_BAGS_BEGIN + BANK_BAGS_END_OFFSET; + enum PossessionsSlot : int { + PossessionsCharm = InvSlotBegin, + PossessionsEar1, + PossessionsHead, + PossessionsFace, + PossessionsEar2, + PossessionsNeck, + PossessionsShoulders, + PossessionsArms, + PossessionsBack, + PossessionsWrist1, + PossessionsWrist2, + PossessionsRange, + PossessionsHands, + PossessionsPrimary, + PossessionsSecondary, + PossessionsFinger1, + PossessionsFinger2, + PossessionsChest, + PossessionsLegs, + PossessionsFeet, + PossessionsWaist, + PossessionsPowerSource, + PossessionsAmmo, + PossessionsGeneral1, + PossessionsGeneral2, + PossessionsGeneral3, + PossessionsGeneral4, + PossessionsGeneral5, + PossessionsGeneral6, + PossessionsGeneral7, + PossessionsGeneral8, + PossessionsCursor, + PossessionsCount + }; - static const int16 SHARED_BANK_BEGIN = 2500; - static const int16 SHARED_BANK_END = 2501; - static const int16 SHARED_BANK_BAGS_BEGIN = 2532; - static const int16 SHARED_BANK_BAGS_END_OFFSET = 19; - static const int16 SHARED_BANK_BAGS_END = SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_END_OFFSET; + const int EquipmentBegin = PossessionsCharm; + const int EquipmentEnd = PossessionsAmmo; + const int EquipmentCount = (EquipmentEnd - EquipmentBegin + 1); - static const int16 TRADE_BEGIN = 3000; - static const int16 TRADE_END = 3007; - static const int16 TRADE_NPC_END = 3003; - static const int16 TRADE_BAGS_BEGIN = 3031; - static const int16 TRADE_BAGS_END_OFFSET = 79; - static const int16 TRADE_BAGS_END = TRADE_BAGS_BEGIN + TRADE_BAGS_END_OFFSET; + const int GeneralBegin = PossessionsGeneral1; + const int GeneralEnd = PossessionsGeneral8; + const int GeneralCount = (GeneralEnd - GeneralBegin + 1); + + } /*invslot*/ - static const int16 WORLD_BEGIN = 4000; - static const int16 WORLD_END = 4009; + namespace invbag { + inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::UF; } - static const int16 TRIBUTE_BEGIN = 400; - static const int16 TRIBUTE_END = 404; + enum : int { InvBagInvalid = -1, InvBagBegin }; + + } /*invbag*/ - static const int16 CORPSE_BEGIN = inventory::SlotGeneral1; - static const int16 CORPSE_END = inventory::SlotGeneral1 + inventory::SlotCursor; + namespace invaug { + inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::UF; } - static const uint16 ITEM_COMMON_SIZE = 5; - static const uint16 ITEM_CONTAINER_SIZE = 10; + enum : int { InvAugInvalid = -1, InvAugBegin }; + + } /*invaug*/ - static const size_t BANDOLIERS_SIZE = 20; // number of bandolier instances - static const size_t BANDOLIER_ITEM_COUNT = 4; // number of equipment slots in bandolier instance + namespace item { + inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::UF; } - static const size_t POTION_BELT_ITEM_COUNT = 5; + enum ItemPacketType : int { + ItemPacketMerchant = 100, + ItemPacketTradeView = 101, + ItemPacketLoot = 102, + ItemPacketTrade = 103, + ItemPacketCharInventory = 105, + ItemPacketLimbo = 106, + ItemPacketWorldContainer = 107, + ItemPacketTributeItem = 108, + ItemPacketGuildTribute = 109, + ItemPacketCharmUpdate = 110, + ItemPacket11 = 111 + }; + + } /*item*/ - static const size_t TEXT_LINK_BODY_LENGTH = 50; + namespace profile { + inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::UF; } + + } /*profile*/ - static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; - } + namespace constants { + inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::UF; } + + } /*constants*/ - namespace limits { - static const bool ALLOWS_EMPTY_BAG_IN_BAG = false; - static const bool ALLOWS_CLICK_CAST_FROM_BAG = false; - static const bool COIN_HAS_WEIGHT = false; - } + namespace behavior { + inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::UF; } + + } /*behavior*/ + + namespace skills { + inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::UF; } + + } /*skills*/ + + + // declarations + namespace invtype { + const size_t InvTypePossessionsSize = invslot::PossessionsCount; + const size_t InvTypeBankSize = 24; + const size_t InvTypeSharedBankSize = 2; + const size_t InvTypeTradeSize = 8; + const size_t InvTypeWorldSize = 10; + const size_t InvTypeLimboSize = 36; + const size_t InvTypeTributeSize = 5; + const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeMerchantSize = 80; + const size_t InvTypeCorpseSize = InvTypePossessionsSize; + const size_t InvTypeBazaarSize = 80; + const size_t InvTypeInspectSize = invslot::EquipmentCount; + const size_t InvTypeViewMODPCSize = InvTypePossessionsSize; + const size_t InvTypeViewMODBankSize = InvTypeBankSize; + const size_t InvTypeViewMODSharedBankSize = InvTypeSharedBankSize; + const size_t InvTypeViewMODLimboSize = InvTypeLimboSize; + const size_t InvTypeAltStorageSize = 0;//unknown - "Shroud Bank" + const size_t InvTypeArchivedSize = 0;//unknown + const size_t InvTypeOtherSize = 0;//unknown + + const size_t NPCTradeSize = 4; + + extern size_t InvTypeSize(int inv_type); + extern const char* InvTypeName(int inv_type); + + } /*invtype*/ + + namespace invslot { + const int BankBegin = 2000; + const int BankEnd = (BankBegin + invtype::InvTypeBankSize) - 1; + + const int SharedBankBegin = 2500; + const int SharedBankEnd = (SharedBankBegin + invtype::InvTypeSharedBankSize) - 1; + + const int TradeBegin = 3000; + const int TradeEnd = (TradeBegin + invtype::InvTypeTradeSize) - 1; + const int TradeNPCEnd = 3003; + + const int WorldBegin = 4000; + const int WorldEnd = (WorldBegin + invtype::InvTypeWorldSize) - 1; + + const int TributeBegin = 400; + const int TributeEnd = 404; + + const int CorpseBegin = invslot::PossessionsGeneral1; + const int CorpseEnd = invslot::PossessionsGeneral1 + invslot::PossessionsCursor; + + extern const char* InvPossessionsSlotName(int inv_slot); + extern const char* InvCorpseSlotName(int inv_slot); + extern const char* InvSlotName(int inv_type, int inv_slot); + + } /*invslot*/ + + namespace invbag { + const size_t ItemBagSize = 10; + + const int GeneralBagsBegin = 262; + const int GeneralBagsSize = invslot::GeneralCount * ItemBagSize; + const int GeneralBagsEnd = (GeneralBagsBegin + GeneralBagsSize) - 1; + + const int CursorBagBegin = 342; + const int CursorBagSize = ItemBagSize; + const int CursorBagEnd = (CursorBagBegin + CursorBagSize) - 1; + + const int BankBagsBegin = 2032; + const int BankBagsSize = (invtype::InvTypeBankSize * ItemBagSize); + const int BankBagsEnd = (BankBagsBegin + BankBagsSize) - 1; + + const int SharedBankBagsBegin = 2532; + const int SharedBankBagsSize = invtype::InvTypeSharedBankSize * ItemBagSize; + const int SharedBankBagsEnd = (SharedBankBagsBegin + SharedBankBagsSize) - 1; + + const int TradeBagsBegin = 3031; + const int TradeBagsSize = invtype::InvTypeTradeSize * ItemBagSize; + const int TradeBagsEnd = (TradeBagsBegin + TradeBagsSize) - 1; + + extern const char* InvBagIndexName(int bag_index); + + } /*invbag*/ + + namespace invaug { + const size_t ItemAugSize = 5; + + extern const char* InvAugIndexName(int aug_index); + + } /*invaug*/ + + namespace item { + + } /*item*/ + + namespace profile { + const size_t TributeSize = invtype::InvTypeTributeSize; + + const size_t BandoliersSize = 20; // number of bandolier instances + const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance + + const size_t PotionBeltSize = 5; + + const size_t SkillArraySize = 100; + + } /*profile*/ + + namespace constants { + const size_t CharacterCreationLimit = 12; + + const size_t SayLinkBodySize = 50; + + } /*constants*/ + + namespace behavior { + const bool ConcatenateInvTypeLimbo = true; + + const bool AllowOverLevelEquipment = true; + + const bool AllowEmptyBagInBag = false; + const bool AllowClickCastFromBag = false; + + const bool CoinHasWeight = false; + + } /*behavior*/ + + namespace skills { + const size_t LastUsableSkill = EQEmu::skills::SkillTripleAttack; + + } /*skills*/ }; /*UF*/ -#endif /*COMMON_UF_CONSTANTS_H*/ +#endif /*COMMON_UF_LIMITS_H*/ diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 6c2f198bb..808cef4df 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -773,7 +773,7 @@ struct BandolierItem_Struct struct Bandolier_Struct { char Name[32]; - BandolierItem_Struct Items[consts::BANDOLIER_ITEM_COUNT]; + BandolierItem_Struct Items[profile::BandolierItemCount]; }; //len = 72 @@ -787,7 +787,7 @@ struct PotionBeltItem_Struct //len = 288 struct PotionBelt_Struct { - PotionBeltItem_Struct Items[consts::POTION_BELT_ITEM_COUNT]; + PotionBeltItem_Struct Items[profile::PotionBeltSize]; }; static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16; @@ -1010,7 +1010,7 @@ struct PlayerProfile_Struct /*11236*/ uint32 aapoints_spent; // Number of spent AA points /*11240*/ uint32 aapoints; // Unspent AA points /*11244*/ uint8 unknown11244[4]; -/*11248*/ Bandolier_Struct bandoliers[consts::BANDOLIERS_SIZE]; // [6400] bandolier contents +/*11248*/ Bandolier_Struct bandoliers[profile::BandoliersSize]; // [6400] bandolier contents /*17648*/ PotionBelt_Struct potionbelt; // [360] potion belt 72 extra octets by adding 1 more belt slot /*18008*/ uint8 unknown18008[8]; /*18016*/ uint32 available_slots; diff --git a/common/say_link.cpp b/common/say_link.cpp index 3cfc46878..6d64837e3 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -17,6 +17,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "say_link.h" #include "emu_constants.h" #include "string_util.h" diff --git a/common/shareddb.cpp b/common/shareddb.cpp index e8046167b..634a2b0b1 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1382,7 +1382,7 @@ bool SharedDatabase::LoadSkillCaps(const std::string &prefix) { skill_caps_mmf.reset(nullptr); uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; + uint32 skill_count = EQEmu::skills::HIGHEST_SKILL + 1; uint32 level_count = HARD_LEVEL_CAP + 1; uint32 size = (class_count * skill_count * level_count * sizeof(uint16)); @@ -1403,7 +1403,7 @@ bool SharedDatabase::LoadSkillCaps(const std::string &prefix) { void SharedDatabase::LoadSkillCaps(void *data) { uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; + uint32 skill_count = EQEmu::skills::HIGHEST_SKILL + 1; uint32 level_count = HARD_LEVEL_CAP + 1; uint16 *skill_caps_table = reinterpret_cast(data); @@ -1428,7 +1428,7 @@ void SharedDatabase::LoadSkillCaps(void *data) { } } -uint16 SharedDatabase::GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Level) { +uint16 SharedDatabase::GetSkillCap(uint8 Class_, EQEmu::skills::SkillType Skill, uint8 Level) { if(!skill_caps_mmf) { return 0; } @@ -1442,7 +1442,7 @@ uint16 SharedDatabase::GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Leve } uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; + uint32 skill_count = EQEmu::skills::HIGHEST_SKILL + 1; uint32 level_count = HARD_LEVEL_CAP + 1; if(Class_ > class_count || static_cast(Skill) > skill_count || Level > level_count) { return 0; @@ -1457,7 +1457,7 @@ uint16 SharedDatabase::GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Leve return skill_caps_table[index]; } -uint8 SharedDatabase::GetTrainLevel(uint8 Class_, SkillUseTypes Skill, uint8 Level) { +uint8 SharedDatabase::GetTrainLevel(uint8 Class_, EQEmu::skills::SkillType Skill, uint8 Level) { if(!skill_caps_mmf) { return 0; } @@ -1471,7 +1471,7 @@ uint8 SharedDatabase::GetTrainLevel(uint8 Class_, SkillUseTypes Skill, uint8 Lev } uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; + uint32 skill_count = EQEmu::skills::HIGHEST_SKILL + 1; uint32 level_count = HARD_LEVEL_CAP + 1; if(Class_ > class_count || static_cast(Skill) > skill_count || Level > level_count) { return 0; @@ -1642,10 +1642,10 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { int tmp_skill = atoi(row[100]);; - if(tmp_skill < 0 || tmp_skill > HIGHEST_SKILL) - sp[tempid].skill = SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated + if (tmp_skill < 0 || tmp_skill > EQEmu::skills::HIGHEST_SKILL) + sp[tempid].skill = EQEmu::skills::SkillBegging; /* not much better we can do. */ // can probably be changed to client-based 'SkillNone' once activated else - sp[tempid].skill = (SkillUseTypes) tmp_skill; + sp[tempid].skill = (EQEmu::skills::SkillType) tmp_skill; sp[tempid].zonetype=atoi(row[101]); sp[tempid].EnvironmentType=atoi(row[102]); diff --git a/common/shareddb.h b/common/shareddb.h index bf21313b7..719735ecd 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -131,8 +131,8 @@ class SharedDatabase : public Database void LoadSkillCaps(void *data); bool LoadSkillCaps(const std::string &prefix); - uint16 GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Level); - uint8 GetTrainLevel(uint8 Class_, SkillUseTypes Skill, uint8 Level); + uint16 GetSkillCap(uint8 Class_, EQEmu::skills::SkillType Skill, uint8 Level); + uint8 GetTrainLevel(uint8 Class_, EQEmu::skills::SkillType Skill, uint8 Level); int GetMaxSpellID(); bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp); diff --git a/common/skills.cpp b/common/skills.cpp index bc5942fcd..1e6827490 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -1,5 +1,6 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -9,17 +10,20 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "types.h" #include "skills.h" -bool EQEmu::IsTradeskill(SkillUseTypes skill) +#include + + +bool EQEmu::skills::IsTradeskill(SkillType skill) { switch (skill) { case SkillFishing: @@ -40,7 +44,7 @@ bool EQEmu::IsTradeskill(SkillUseTypes skill) } } -bool EQEmu::IsSpecializedSkill(SkillUseTypes skill) +bool EQEmu::skills::IsSpecializedSkill(SkillType skill) { // this could be a simple if, but if this is more portable if any IDs change (probably won't) // or any other specialized are added (also unlikely) @@ -56,7 +60,7 @@ bool EQEmu::IsSpecializedSkill(SkillUseTypes skill) } } -float EQEmu::GetSkillMeleePushForce(SkillUseTypes skill) +float EQEmu::skills::GetSkillMeleePushForce(SkillType skill) { // This is the force/magnitude of the push from an attack of this skill type // You can find these numbers in the clients skill struct @@ -93,7 +97,7 @@ float EQEmu::GetSkillMeleePushForce(SkillUseTypes skill) } } -bool EQEmu::IsBardInstrumentSkill(SkillUseTypes skill) +bool EQEmu::skills::IsBardInstrumentSkill(SkillType skill) { switch (skill) { case SkillBrassInstruments: @@ -107,7 +111,7 @@ bool EQEmu::IsBardInstrumentSkill(SkillUseTypes skill) } } -const std::map& EQEmu::GetSkillUseTypesMap() +const std::map& EQEmu::skills::GetSkillTypeMap() { /* VS2013 code static const std::map skill_use_types_map = { @@ -194,7 +198,7 @@ const std::map& EQEmu::GetSkillUseTypesMap() /* VS2012 code - begin */ - static const char* skill_use_names[_EmuSkillCount] = { + static const char* skill_use_names[SkillCount] = { "1H Blunt", "1H Slashing", "2H Blunt", @@ -275,14 +279,160 @@ const std::map& EQEmu::GetSkillUseTypesMap() "2H Piercing" }; - static std::map skill_use_types_map; + static std::map skill_type_map; - skill_use_types_map.clear(); + skill_type_map.clear(); - for (int i = Skill1HBlunt; i < _EmuSkillCount; ++i) - skill_use_types_map[(SkillUseTypes)i] = skill_use_names[i]; + for (int i = Skill1HBlunt; i < SkillCount; ++i) + skill_type_map[(SkillType)i] = skill_use_names[i]; /* VS2012 code - end */ - return skill_use_types_map; + return skill_type_map; +} + +struct EQEmu::SkillProfile // prototype - not implemented +{ + union { + struct { + uint32 _1HBlunt; + uint32 _1HSlashing; + uint32 _2HBlunt; + uint32 _2HSlashing; + uint32 Abjuration; + uint32 Alteration; + uint32 ApplyPoison; + uint32 Archery; + uint32 Backstab; + uint32 BindWound; + uint32 Bash; + uint32 Block; + uint32 BrassInstruments; + uint32 Channeling; + uint32 Conjuration; + uint32 Defense; + uint32 Disarm; + uint32 DisarmTraps; + uint32 Divination; + uint32 Dodge; + uint32 DoubleAttack; + union { + uint32 DragonPunch; + uint32 TailRake; + }; + uint32 DualWield; + uint32 EagleStrike; + uint32 Evocation; + uint32 FeignDeath; + uint32 FlyingKick; + uint32 Forage; + uint32 HandtoHand; + uint32 Hide; + uint32 Kick; + uint32 Meditate; + uint32 Mend; + uint32 Offense; + uint32 Parry; + uint32 PickLock; + uint32 _1HPiercing; + uint32 Riposte; + uint32 RoundKick; + uint32 SafeFall; + uint32 SenseHeading; + uint32 Singing; + uint32 Sneak; + uint32 SpecializeAbjure; + uint32 SpecializeAlteration; + uint32 SpecializeConjuration; + uint32 SpecializeDivination; + uint32 SpecializeEvocation; + uint32 PickPockets; + uint32 StringedInstruments; + uint32 Swimming; + uint32 Throwing; + uint32 TigerClaw; + uint32 Tracking; + uint32 WindInstruments; + uint32 Fishing; + uint32 MakePoison; + uint32 Tinkering; + uint32 Research; + uint32 Alchemy; + uint32 Baking; + uint32 Tailoring; + uint32 SenseTraps; + uint32 Blacksmithing; + uint32 Fletching; + uint32 Brewing; + uint32 AlcoholTolerance; + uint32 Begging; + uint32 JewelryMaking; + uint32 Pottery; + uint32 PercussionInstruments; + uint32 Intimidation; + uint32 Berserking; + uint32 Taunt; + uint32 Frenzy; + uint32 RemoveTraps; + uint32 TripleAttack; + uint32 _2HPiercing; + uint32 unused1; + uint32 unused2; + uint32 unused3; + uint32 unused4; + uint32 unused5; + uint32 unused6; + uint32 unused7; + uint32 unused8; + uint32 unused9; + uint32 unused10; + uint32 unused11; + uint32 unused12; + uint32 unused13; + uint32 unused14; + uint32 unused15; + uint32 unused16; + uint32 unused17; + uint32 unused18; + uint32 unused19; + uint32 unused20; + uint32 unused21; + uint32 unused22; + }; + uint32 skill[PACKET_SKILL_ARRAY_SIZE]; + }; + + SkillProfile(); + + uint32* GetSkills() { return reinterpret_cast(&skill); } + + skills::SkillType GetLastUseableSkill() { return EQEmu::skills::Skill2HPiercing; } + + size_t GetSkillsArraySize() { return PACKET_SKILL_ARRAY_SIZE; } + uint32 GetSkill(int skill_id); + + uint32 operator[](int skill_id) { return GetSkill(skill_id); } + + // const + uint32* GetSkills() const { return const_cast(this)->GetSkills(); } + + skills::SkillType GetLastUseableSkill() const { return const_cast(this)->GetLastUseableSkill(); } + + size_t GetSkillsArraySize() const { return const_cast(this)->GetSkillsArraySize(); } + uint32 GetSkill(int skill_id) const { return const_cast(this)->GetSkill(skill_id); } + + uint32 operator[](int skill_id) const { return const_cast(this)->GetSkill(skill_id); } +}; + +EQEmu::SkillProfile::SkillProfile() +{ + memset(&skill, 0, (sizeof(uint32) * PACKET_SKILL_ARRAY_SIZE)); +} + +uint32 EQEmu::SkillProfile::GetSkill(int skill_id) +{ + if (skill_id < 0 || skill_id >= PACKET_SKILL_ARRAY_SIZE) + return 0; + + return skill[skill_id]; } diff --git a/common/skills.h b/common/skills.h index 0868c3329..af8f4a543 100644 --- a/common/skills.h +++ b/common/skills.h @@ -1,5 +1,6 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2002 EQEMu Development Team (http://eqemulator.org) + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -9,25 +10,24 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef SKILLS_H -#define SKILLS_H + +#ifndef COMMON_SKILLS_H +#define COMMON_SKILLS_H #include #include -/* -** Skill use types -** -** (ref: eqstr_us.txt [05-10-2013]) -*/ -enum SkillUseTypes + +namespace EQEmu { + namespace skills { + enum SkillType : int { /*13855*/ Skill1HBlunt = 0, /*13856*/ Skill1HSlashing, /*13857*/ Skill2HBlunt, @@ -111,78 +111,65 @@ enum SkillUseTypes // RoF2+ specific skills /*00789*/ Skill2HPiercing, // 77 -// /*01216*/ SkillNone, // This needs to move down as new skills are added +// /*01216*/ SkillNone, // This needs to move down as new skills are added -/*00000*/ _EmuSkillCount // move to last position of active enumeration labels +/*00000*/ SkillCount // move to last position of active enumeration labels // Skill Counts -// /*-----*/ _SkillCount_62 = 75, // use for Ti and earlier max skill checks -// /*-----*/ _SkillCount_SoF = 77, // use for SoF thru RoF1 max skill checks -// /*-----*/ _SkillCount_RoF2 = 78, // use for RoF2 max skill checks +// /*-----*/ SkillCount_62 = 75, // use for Ti and earlier max skill checks +// /*-----*/ SkillCount_SoF = 77, // use for SoF thru RoF1 max skill checks +// /*-----*/ SkillCount_RoF2 = 78, // use for RoF2 max skill checks // Support values -// /*-----*/ _SkillServerArraySize = _SkillCount_RoF2, // Should reflect last client '_SkillCount' +// /*-----*/ SkillServerArraySize = _SkillCount_RoF2, // Should reflect last client '_SkillCount' // Superfluous additions to SkillUseTypes..server-use only // /*-----*/ ExtSkillGenericTradeskill = 100 -/* ([EQClientVersion] [0] - Unknown, [3] - SoF, [7] - RoF2[05-10-2013]) - [Skill] [index] | [0] [1] [2] [3] [4] [5] [6] [7] - Frenzy (05837) | --- 074 074 074 074 074 074 074 - Remove Traps (03670) | --- --- --- 075 075 075 075 075 - Triple Attack (13049) | --- --- --- 076 076 076 076 076 - 2H Piercing (00789) | --- --- --- --- --- --- --- 077 -*/ + /* ([EQClientVersion] [0] - Unknown, [3] - SoF, [7] - RoF2[05-10-2013]) + [Skill] [index] | [0] [1] [2] [3] [4] [5] [6] [7] + Frenzy (05837) | --- 074 074 074 074 074 074 074 + Remove Traps (03670) | --- --- --- 075 075 075 075 075 + Triple Attack (13049) | --- --- --- 076 076 076 076 076 + 2H Piercing (00789) | --- --- --- --- --- --- --- 077 + */ -/* - [SkillCaps.txt] (SoF+) - a^b^c^d(^e) (^e is RoF+, but cursory glance appears to be all zeros) + /* + [SkillCaps.txt] (SoF+) + a^b^c^d(^e) (^e is RoF+, but cursory glance appears to be all zeros) - a - Class - b - Skill - c - Level - d - Max Value - (e - Unknown) -*/ + a - Class + b - Skill + c - Level + d - Max Value + (e - Unknown) + */ -/* - NOTE: Disregard this until it is sorted out + /* + Changed (tradeskill==75) to ExtSkillGenericTradeskill in tradeskills.cpp for both instances. If it's a pseudo-enumeration of + an AA ability, then use the 'ExtSkill' ('ExtendedSkill') prefix with a value >= 100. (current implementation) + */ + }; - I changed (tradeskill==75) to ExtSkillGenericTradeskill in tradeskills.cpp for both instances. If it's a pseudo-enumeration of - an AA ability, then use the 'ExtSkill' ('ExtendedSkill') prefix with a value >= 100. (current implementation) - - We probably need to recode ALL of the skill checks to use the new Skill2HPiercing and ensure that the animation value is - properly changed in the patch files. As far as earlier clients using this new skill, it can be done, but we just need to ensure - that skill address is not inadvertently passed to the client..and we can just send an actual message for the skill-up. Use of a - command can tell the player what that particular skill value is. - - Nothing on SkillTripleAttack just yet..haven't looked into its current implementation. - - In addition to the above re-coding, we're probably going to need to rework the database pp blob to reserve space for the current - 100-dword buffer allocation. This way, we can just add new ones without having to rework it each time. - (Wasn't done for this in particular..but, thanks Akkadius!) - - -U -*/ -}; - -// temporary until it can be sorted out... + // temporary until it can be sorted out... #define HIGHEST_SKILL Skill2HPiercing -// Spell Effects use this value to determine if an effect applies to all skills. + // Spell Effects use this value to determine if an effect applies to all skills. #define ALL_SKILLS -1 -// server profile does not reflect this yet..so, prefixed with 'PACKET_' + // server profile does not reflect this yet..so, prefixed with 'PACKET_' #define PACKET_SKILL_ARRAY_SIZE 100 + extern bool IsTradeskill(SkillType skill); + extern bool IsSpecializedSkill(SkillType skill); + extern float GetSkillMeleePushForce(SkillType skill); + extern bool IsBardInstrumentSkill(SkillType skill); -// for skill related helper functions -namespace EQEmu { - bool IsTradeskill(SkillUseTypes skill); - bool IsSpecializedSkill(SkillUseTypes skill); - float GetSkillMeleePushForce(SkillUseTypes skill); - bool IsBardInstrumentSkill(SkillUseTypes skill); + extern const std::map& GetSkillTypeMap(); - const std::map& GetSkillUseTypesMap(); -} + } /*skills*/ -#endif + struct SkillProfile; + +} /*EQEmu*/ + +#endif /*COMMON_SKILLS_H*/ diff --git a/common/spdat.h b/common/spdat.h index 0e9096f1a..d083f0dbd 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -681,7 +681,7 @@ struct SPDat_Spell_Struct /* 086 */ int effectid[EFFECT_COUNT]; // Spell's effects /* 098 */ SpellTargetType targettype; // Spell's Target /* 099 */ int basediff; // base difficulty fizzle adjustment -/* 100 */ SkillUseTypes skill; +/* 100 */ EQEmu::skills::SkillType skill; /* 101 */ int8 zonetype; // 01=Outdoors, 02=dungeons, ff=Any /* 102 */ int8 EnvironmentType; /* 103 */ int8 TimeOfDay; diff --git a/shared_memory/skill_caps.cpp b/shared_memory/skill_caps.cpp index bd8eabb5a..758ce6955 100644 --- a/shared_memory/skill_caps.cpp +++ b/shared_memory/skill_caps.cpp @@ -30,7 +30,7 @@ void LoadSkillCaps(SharedDatabase *database, const std::string &prefix) { mutex.Lock(); uint32 class_count = PLAYER_CLASS_COUNT; - uint32 skill_count = HIGHEST_SKILL + 1; + uint32 skill_count = EQEmu::skills::HIGHEST_SKILL + 1; uint32 level_count = HARD_LEVEL_CAP + 1; uint32 size = (class_count * skill_count * level_count * sizeof(uint16)); diff --git a/tests/skills_util_test.h b/tests/skills_util_test.h index 96507256e..478de4206 100644 --- a/tests/skills_util_test.h +++ b/tests/skills_util_test.h @@ -35,13 +35,13 @@ public: private: void IsTradeskill() { - TEST_ASSERT(EQEmu::IsTradeskill(SkillPottery)); - TEST_ASSERT(!EQEmu::IsTradeskill(SkillParry)); + TEST_ASSERT(EQEmu::skills::IsTradeskill(EQEmu::skills::SkillPottery)); + TEST_ASSERT(!EQEmu::skills::IsTradeskill(EQEmu::skills::SkillParry)); } void IsSpecializedSkill() { - TEST_ASSERT(EQEmu::IsSpecializedSkill(SkillSpecializeConjuration)); - TEST_ASSERT(!EQEmu::IsSpecializedSkill(SkillConjuration)) + TEST_ASSERT(EQEmu::skills::IsSpecializedSkill(EQEmu::skills::SkillSpecializeConjuration)); + TEST_ASSERT(!EQEmu::skills::IsSpecializedSkill(EQEmu::skills::SkillConjuration)) } }; diff --git a/world/client.cpp b/world/client.cpp index 7065c79f5..057db0961 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -211,9 +211,9 @@ void Client::SendMaxCharCreate() { auto outapp = new EQApplicationPacket(OP_SendMaxCharacters, sizeof(MaxCharacters_Struct)); MaxCharacters_Struct* mc = (MaxCharacters_Struct*)outapp->pBuffer; - mc->max_chars = EQEmu::limits::CharacterCreationLimit(m_ClientVersion); - if (mc->max_chars > EQEmu::constants::CharacterCreationLimit) - mc->max_chars = EQEmu::constants::CharacterCreationLimit; + mc->max_chars = EQEmu::constants::CharacterCreationLimit(m_ClientVersion); + if (mc->max_chars > EQEmu::constants::CharacterCreationMax) + mc->max_chars = EQEmu::constants::CharacterCreationMax; QueuePacket(outapp); safe_delete(outapp); @@ -746,8 +746,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { // This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above) // (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration) if (!pZoning) { - size_t character_limit = EQEmu::limits::CharacterCreationLimit(eqs->ClientVersion()); - if (character_limit > EQEmu::constants::CharacterCreationLimit) { character_limit = EQEmu::constants::CharacterCreationLimit; } + size_t character_limit = EQEmu::constants::CharacterCreationLimit(eqs->ClientVersion()); + if (character_limit > EQEmu::constants::CharacterCreationMax) { character_limit = EQEmu::constants::CharacterCreationMax; } if (eqs->ClientVersion() == EQEmu::versions::ClientVersion::Titanium) { character_limit = 8; } std::string tgh_query = StringFormat( @@ -1464,8 +1464,8 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) SetClassStartingSkills(&pp); SetClassLanguages(&pp); - pp.skills[SkillSwimming] = RuleI(Skills, SwimmingStartValue); - pp.skills[SkillSenseHeading] = RuleI(Skills, SenseHeadingStartValue); + pp.skills[EQEmu::skills::SkillSwimming] = RuleI(Skills, SwimmingStartValue); + pp.skills[EQEmu::skills::SkillSenseHeading] = RuleI(Skills, SenseHeadingStartValue); // strcpy(pp.servername, WorldConfig::get()->ShortName.c_str()); @@ -1839,21 +1839,21 @@ bool CheckCharCreateInfoTitanium(CharCreate_Struct *cc) void Client::SetClassStartingSkills(PlayerProfile_Struct *pp) { - for (uint32 i = 0; i <= HIGHEST_SKILL; ++i) { + for (uint32 i = 0; i <= EQEmu::skills::HIGHEST_SKILL; ++i) { if (pp->skills[i] == 0) { // Skip specialized, tradeskills (fishing excluded), Alcohol Tolerance, and Bind Wound - if (EQEmu::IsSpecializedSkill((SkillUseTypes)i) || - (EQEmu::IsTradeskill((SkillUseTypes)i) && i != SkillFishing) || - i == SkillAlcoholTolerance || i == SkillBindWound) + if (EQEmu::skills::IsSpecializedSkill((EQEmu::skills::SkillType)i) || + (EQEmu::skills::IsTradeskill((EQEmu::skills::SkillType)i) && i != EQEmu::skills::SkillFishing) || + i == EQEmu::skills::SkillAlcoholTolerance || i == EQEmu::skills::SkillBindWound) continue; - pp->skills[i] = database.GetSkillCap(pp->class_, (SkillUseTypes)i, 1); + pp->skills[i] = database.GetSkillCap(pp->class_, (EQEmu::skills::SkillType)i, 1); } } if (cle->GetClientVersion() < static_cast(EQEmu::versions::ClientVersion::RoF2) && pp->class_ == BERSERKER) { - pp->skills[Skill1HPiercing] = pp->skills[Skill2HPiercing]; - pp->skills[Skill2HPiercing] = 0; + pp->skills[EQEmu::skills::Skill1HPiercing] = pp->skills[EQEmu::skills::Skill2HPiercing]; + pp->skills[EQEmu::skills::Skill2HPiercing] = 0; } } @@ -1876,41 +1876,41 @@ void Client::SetRaceStartingSkills( PlayerProfile_Struct *pp ) } case DARK_ELF: { - pp->skills[SkillHide] = 50; + pp->skills[EQEmu::skills::SkillHide] = 50; break; } case FROGLOK: { - pp->skills[SkillSwimming] = 125; + pp->skills[EQEmu::skills::SkillSwimming] = 125; break; } case GNOME: { - pp->skills[SkillTinkering] = 50; + pp->skills[EQEmu::skills::SkillTinkering] = 50; break; } case HALFLING: { - pp->skills[SkillHide] = 50; - pp->skills[SkillSneak] = 50; + pp->skills[EQEmu::skills::SkillHide] = 50; + pp->skills[EQEmu::skills::SkillSneak] = 50; break; } case IKSAR: { - pp->skills[SkillForage] = 50; - pp->skills[SkillSwimming] = 100; + pp->skills[EQEmu::skills::SkillForage] = 50; + pp->skills[EQEmu::skills::SkillSwimming] = 100; break; } case WOOD_ELF: { - pp->skills[SkillForage] = 50; - pp->skills[SkillHide] = 50; + pp->skills[EQEmu::skills::SkillForage] = 50; + pp->skills[EQEmu::skills::SkillHide] = 50; break; } case VAHSHIR: { - pp->skills[SkillSafeFall] = 50; - pp->skills[SkillSneak] = 50; + pp->skills[EQEmu::skills::SkillSafeFall] = 50; + pp->skills[EQEmu::skills::SkillSneak] = 50; break; } } diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 0deb8c052..b41672a33 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -37,11 +37,11 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou { /* Set Character Creation Limit */ EQEmu::versions::ClientVersion client_version = EQEmu::versions::ConvertClientVersionBitToClientVersion(clientVersionBit); - size_t character_limit = EQEmu::limits::CharacterCreationLimit(client_version); + size_t character_limit = EQEmu::constants::CharacterCreationLimit(client_version); // Validate against absolute server max - if (character_limit > EQEmu::constants::CharacterCreationLimit) - character_limit = EQEmu::constants::CharacterCreationLimit; + if (character_limit > EQEmu::constants::CharacterCreationMax) + character_limit = EQEmu::constants::CharacterCreationMax; // Force Titanium clients to use '8' if (client_version == EQEmu::versions::ClientVersion::Titanium) diff --git a/zone/attack.cpp b/zone/attack.cpp index 354517279..8cf3971f8 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -50,7 +50,7 @@ extern WorldServer worldserver; extern EntityList entity_list; extern Zone* zone; -bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* weapon) +bool Mob::AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const ItemInst* weapon) { // Determine animation int type = 0; @@ -61,63 +61,63 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w switch (item->ItemType) { case EQEmu::item::ItemType1HSlash: // 1H Slashing - skillinuse = Skill1HSlashing; + skillinuse = EQEmu::skills::Skill1HSlashing; type = anim1HWeapon; break; case EQEmu::item::ItemType2HSlash: // 2H Slashing - skillinuse = Skill2HSlashing; + skillinuse = EQEmu::skills::Skill2HSlashing; type = anim2HSlashing; break; case EQEmu::item::ItemType1HPiercing: // Piercing - skillinuse = Skill1HPiercing; + skillinuse = EQEmu::skills::Skill1HPiercing; type = anim1HPiercing; break; case EQEmu::item::ItemType1HBlunt: // 1H Blunt - skillinuse = Skill1HBlunt; + skillinuse = EQEmu::skills::Skill1HBlunt; type = anim1HWeapon; break; case EQEmu::item::ItemType2HBlunt: // 2H Blunt - skillinuse = Skill2HBlunt; + skillinuse = EQEmu::skills::Skill2HBlunt; type = anim2HSlashing; //anim2HWeapon break; case EQEmu::item::ItemType2HPiercing: // 2H Piercing if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) - skillinuse = Skill1HPiercing; + skillinuse = EQEmu::skills::Skill1HPiercing; else - skillinuse = Skill2HPiercing; + skillinuse = EQEmu::skills::Skill2HPiercing; type = anim2HWeapon; break; case EQEmu::item::ItemTypeMartial: - skillinuse = SkillHandtoHand; + skillinuse = EQEmu::skills::SkillHandtoHand; type = animHand2Hand; break; default: - skillinuse = SkillHandtoHand; + skillinuse = EQEmu::skills::SkillHandtoHand; type = animHand2Hand; break; }// switch } else if(IsNPC()) { switch (skillinuse) { - case Skill1HSlashing: // 1H Slashing + case EQEmu::skills::Skill1HSlashing: // 1H Slashing type = anim1HWeapon; break; - case Skill2HSlashing: // 2H Slashing + case EQEmu::skills::Skill2HSlashing: // 2H Slashing type = anim2HSlashing; break; - case Skill1HPiercing: // Piercing + case EQEmu::skills::Skill1HPiercing: // Piercing type = anim1HPiercing; break; - case Skill1HBlunt: // 1H Blunt + case EQEmu::skills::Skill1HBlunt: // 1H Blunt type = anim1HWeapon; break; - case Skill2HBlunt: // 2H Blunt + case EQEmu::skills::Skill2HBlunt: // 2H Blunt type = anim2HSlashing; //anim2HWeapon break; - case Skill2HPiercing: // 2H Piercing + case EQEmu::skills::Skill2HPiercing: // 2H Piercing type = anim2HWeapon; break; - case SkillHandtoHand: + case EQEmu::skills::SkillHandtoHand: type = animHand2Hand; break; default: @@ -126,7 +126,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w }// switch } else { - skillinuse = SkillHandtoHand; + skillinuse = EQEmu::skills::SkillHandtoHand; type = animHand2Hand; } @@ -140,7 +140,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w // called when a mob is attacked, does the checks to see if it's a hit // and does other mitigation checks. 'this' is the mob being attacked. -bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 chance_mod) +bool Mob::CheckHitChance(Mob* other, EQEmu::skills::SkillType skillinuse, int Hand, int16 chance_mod) { /*/ //Reworked a lot of this code to achieve better balance at higher levels. @@ -218,7 +218,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c if(defender->IsClient()) { - chancetohit += (RuleR(Combat,WeaponSkillFalloff) * (defender->CastToClient()->MaxSkill(SkillDefense) - defender->GetSkill(SkillDefense))); + chancetohit += (RuleR(Combat, WeaponSkillFalloff) * (defender->CastToClient()->MaxSkill(EQEmu::skills::SkillDefense) - defender->GetSkill(EQEmu::skills::SkillDefense))); Log.Out(Logs::Detail, Logs::Attack, "Chance to hit after weapon falloff calc (defense) %.2f", chancetohit); } @@ -254,15 +254,15 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c hitBonus += attacker->itembonuses.HitChanceEffect[skillinuse] + attacker->spellbonuses.HitChanceEffect[skillinuse]+ attacker->aabonuses.HitChanceEffect[skillinuse]+ - attacker->itembonuses.HitChanceEffect[HIGHEST_SKILL+1] + - attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1] + - attacker->aabonuses.HitChanceEffect[HIGHEST_SKILL+1]; + attacker->itembonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->spellbonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->aabonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1]; //Accuracy = Spell Effect , HitChance = 'Accuracy' from Item Effect //Only AA derived accuracy can be skill limited. ie (Precision of the Pathfinder, Dead Aim) - hitBonus += (attacker->itembonuses.Accuracy[HIGHEST_SKILL+1] + - attacker->spellbonuses.Accuracy[HIGHEST_SKILL+1] + - attacker->aabonuses.Accuracy[HIGHEST_SKILL+1] + + hitBonus += (attacker->itembonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->spellbonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->aabonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + attacker->aabonuses.Accuracy[skillinuse] + attacker->itembonuses.HitChance) / 15.0f; //Item Mod 'Accuracy' @@ -271,7 +271,7 @@ bool Mob::CheckHitChance(Mob* other, SkillUseTypes skillinuse, int Hand, int16 c if(attacker->IsNPC()) hitBonus += (attacker->CastToNPC()->GetAccuracyRating() / 10.0f); //Modifier from database - if(skillinuse == SkillArchery) + if (skillinuse == EQEmu::skills::SkillArchery) hitBonus -= hitBonus*RuleR(Combat, ArcheryHitPenalty); //Calculate final chance to hit @@ -382,13 +382,13 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) // Need to check if we have something in MainHand to actually attack with (or fists) if (hand != EQEmu::legacy::SlotRange && CanThisClassRiposte() && InFront && !ImmuneRipo) { if (IsClient()) - CastToClient()->CheckIncreaseSkill(SkillRiposte, other, -10); + CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillRiposte, other, -10); // check auto discs ... I guess aa/items too :P if (spellbonuses.RiposteChance == 10000 || aabonuses.RiposteChance == 10000 || itembonuses.RiposteChance == 10000) { damage = -3; return true; } - int chance = GetSkill(SkillRiposte) + 100; + int chance = GetSkill(EQEmu::skills::SkillRiposte) + 100; chance += (chance * (aabonuses.RiposteChance + spellbonuses.RiposteChance + itembonuses.RiposteChance)) / 100; chance /= 50; chance += itembonuses.HeroicDEX / 25; // live has "heroic strickthrough" here to counter @@ -420,14 +420,14 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) if (CanThisClassBlock() && (InFront || bBlockFromRear)) { if (IsClient()) - CastToClient()->CheckIncreaseSkill(SkillBlock, other, -10); + CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillBlock, other, -10); // check auto discs ... I guess aa/items too :P if (spellbonuses.IncreaseBlockChance == 10000 || aabonuses.IncreaseBlockChance == 10000 || itembonuses.IncreaseBlockChance == 10000) { damage = -1; return true; } - int chance = GetSkill(SkillBlock) + 100; + int chance = GetSkill(EQEmu::skills::SkillBlock) + 100; chance += (chance * (aabonuses.IncreaseBlockChance + spellbonuses.IncreaseBlockChance + itembonuses.IncreaseBlockChance)) / 100; chance /= 25; chance += itembonuses.HeroicDEX / 25; // live has "heroic strickthrough" here to counter @@ -444,13 +444,13 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) // parry if (CanThisClassParry() && InFront && hand != EQEmu::legacy::SlotRange) { if (IsClient()) - CastToClient()->CheckIncreaseSkill(SkillParry, other, -10); + CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillParry, other, -10); // check auto discs ... I guess aa/items too :P if (spellbonuses.ParryChance == 10000 || aabonuses.ParryChance == 10000 || itembonuses.ParryChance == 10000) { damage = -2; return true; } - int chance = GetSkill(SkillParry) + 100; + int chance = GetSkill(EQEmu::skills::SkillParry) + 100; chance += (chance * (aabonuses.ParryChance + spellbonuses.ParryChance + itembonuses.ParryChance)) / 100; chance /= 45; chance += itembonuses.HeroicDEX / 25; // live has "heroic strickthrough" here to counter @@ -467,13 +467,13 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) // dodge if (CanThisClassDodge() && (InFront || GetClass() == MONK) ) { if (IsClient()) - CastToClient()->CheckIncreaseSkill(SkillDodge, other, -10); + CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillDodge, other, -10); // check auto discs ... I guess aa/items too :P if (spellbonuses.DodgeChance == 10000 || aabonuses.DodgeChance == 10000 || itembonuses.DodgeChance == 10000) { damage = -4; return true; } - int chance = GetSkill(SkillDodge) + 100; + int chance = GetSkill(EQEmu::skills::SkillDodge) + 100; chance += (chance * (aabonuses.DodgeChance + spellbonuses.DodgeChance + itembonuses.DodgeChance)) / 100; chance /= 45; chance += itembonuses.HeroicAGI / 25; // live has "heroic strickthrough" here to counter @@ -525,7 +525,7 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac spellbonuses.CombatStability) / 100.0f; if (RuleB(Combat, UseIntervalAC)) { - float softcap = (GetSkill(SkillDefense) + GetLevel()) * + float softcap = (GetSkill(EQEmu::skills::SkillDefense) + GetLevel()) * RuleR(Combat, SoftcapFactor) * (1.0 + aa_mit); float mitigation_rating = 0.0; float attack_rating = 0.0; @@ -625,17 +625,17 @@ void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttac if (GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == NECROMANCER || GetClass() == ENCHANTER) - mitigation_rating = ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10) / 4.0) + armor + 1; + mitigation_rating = ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 4.0) + armor + 1; else - mitigation_rating = ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10) / 3.0) + (armor * 1.333333) + 1; + mitigation_rating = ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 3.0) + (armor * 1.333333) + 1; mitigation_rating *= 0.847; mitigation_rating = mod_mitigation_rating(mitigation_rating, attacker); if (attacker->IsClient()) - attack_rating = (attacker->CastToClient()->CalcATK() + ((attacker->GetSTR()-66) * 0.9) + (attacker->GetSkill(SkillOffense)*1.345)); + attack_rating = (attacker->CastToClient()->CalcATK() + ((attacker->GetSTR() - 66) * 0.9) + (attacker->GetSkill(EQEmu::skills::SkillOffense)*1.345)); else - attack_rating = (attacker->GetATK() + (attacker->GetSkill(SkillOffense)*1.345) + ((attacker->GetSTR()-66) * 0.9)); + attack_rating = (attacker->GetATK() + (attacker->GetSkill(EQEmu::skills::SkillOffense)*1.345) + ((attacker->GetSTR() - 66) * 0.9)); attack_rating = attacker->mod_attack_rating(attack_rating, this); @@ -1059,7 +1059,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b // calculate attack_skill and skillinuse depending on hand and weapon // also send Packet to near clients - SkillUseTypes skillinuse; + EQEmu::skills::SkillType skillinuse; AttackAnimation(skillinuse, Hand, weapon); Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse); @@ -1095,7 +1095,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b max_hit = (RuleI(Combat, HitCapPre20)); CheckIncreaseSkill(skillinuse, other, -15); - CheckIncreaseSkill(SkillOffense, other, -15); + CheckIncreaseSkill(EQEmu::skills::SkillOffense, other, -15); // *************************************************************** // *** Calculate the damage bonus, if applicable, for this hit *** @@ -1236,7 +1236,7 @@ void Mob::Heal() SendHPUpdate(); } -void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) +void Client::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(dead || IsCorpse()) return; @@ -1249,7 +1249,7 @@ void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes att //Don't do PvP mitigation if the caster is damaging himself if(other && other->IsClient() && (other != this) && damage > 0) { int PvPMitigation = 100; - if(attack_skill == SkillArchery) + if (attack_skill == EQEmu::skills::SkillArchery) PvPMitigation = 80; else PvPMitigation = 67; @@ -1265,11 +1265,11 @@ void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes att if (damage > 0) { if (spell_id == SPELL_UNKNOWN) - CheckIncreaseSkill(SkillDefense, other, -15); + CheckIncreaseSkill(EQEmu::skills::SkillDefense, other, -15); } } -bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) +bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::SkillType attack_skill) { if(!ClientFinishedLoading()) return false; @@ -1584,13 +1584,13 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool FaceTarget(GetTarget()); - SkillUseTypes skillinuse = SkillHandtoHand; + EQEmu::skills::SkillType skillinuse = EQEmu::skills::SkillHandtoHand; if (Hand == EQEmu::legacy::SlotPrimary) { - skillinuse = static_cast(GetPrimSkill()); + skillinuse = static_cast(GetPrimSkill()); OffHandAtk(false); } if (Hand == EQEmu::legacy::SlotSecondary) { - skillinuse = static_cast(GetSecSkill()); + skillinuse = static_cast(GetSecSkill()); OffHandAtk(true); } @@ -1613,32 +1613,32 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool switch(weapon->ItemType) { case EQEmu::item::ItemType1HSlash: - skillinuse = Skill1HSlashing; + skillinuse = EQEmu::skills::Skill1HSlashing; break; case EQEmu::item::ItemType2HSlash: - skillinuse = Skill2HSlashing; + skillinuse = EQEmu::skills::Skill2HSlashing; break; case EQEmu::item::ItemType1HPiercing: - skillinuse = Skill1HPiercing; + skillinuse = EQEmu::skills::Skill1HPiercing; break; case EQEmu::item::ItemType2HPiercing: - skillinuse = Skill2HPiercing; + skillinuse = EQEmu::skills::Skill2HPiercing; break; case EQEmu::item::ItemType1HBlunt: - skillinuse = Skill1HBlunt; + skillinuse = EQEmu::skills::Skill1HBlunt; break; case EQEmu::item::ItemType2HBlunt: - skillinuse = Skill2HBlunt; + skillinuse = EQEmu::skills::Skill2HBlunt; break; case EQEmu::item::ItemTypeBow: - skillinuse = SkillArchery; + skillinuse = EQEmu::skills::SkillArchery; break; case EQEmu::item::ItemTypeLargeThrowing: case EQEmu::item::ItemTypeSmallThrowing: - skillinuse = SkillThrowing; + skillinuse = EQEmu::skills::SkillThrowing; break; default: - skillinuse = SkillHandtoHand; + skillinuse = EQEmu::skills::SkillHandtoHand; break; } } @@ -1795,7 +1795,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool return false; } -void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { +void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(spell_id==0) spell_id = SPELL_UNKNOWN; @@ -1838,7 +1838,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack } } -bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attack_skill) +bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::SkillType attack_skill) { Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", ((killer_mob) ? (killer_mob->GetName()) : ("[nullptr]")), damage, spell, attack_skill); @@ -2485,7 +2485,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) { } DS -= DS * attacker->itembonuses.DSMitigation / 100; } - attacker->Damage(this, -DS, spellid, SkillAbjuration/*hackish*/, false); + attacker->Damage(this, -DS, spellid, EQEmu::skills::SkillAbjuration/*hackish*/, false); //we can assume there is a spell now auto outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct)); CombatDamage_Struct* cds = (CombatDamage_Struct*)outapp->pBuffer; @@ -2512,7 +2512,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) { if(rev_ds < 0) { Log.Out(Logs::Detail, Logs::Combat, "Applying Reverse Damage Shield of value %d to %s", rev_ds, attacker->GetName()); - attacker->Damage(this, -rev_ds, rev_ds_spell_id, SkillAbjuration/*hackish*/, false); //"this" (us) will get the hate, etc. not sure how this works on Live, but it'll works for now, and tanks will love us for this + attacker->Damage(this, -rev_ds, rev_ds_spell_id, EQEmu::skills::SkillAbjuration/*hackish*/, false); //"this" (us) will get the hate, etc. not sure how this works on Live, but it'll works for now, and tanks will love us for this //do we need to send a damage packet here also? } } @@ -2584,7 +2584,7 @@ int Mob::GetHandToHandDamage(void) { if (RuleB(Combat, UseRevampHandToHand)) { // everyone uses this in the revamp! - int skill = GetSkill(SkillHandtoHand); + int skill = GetSkill(EQEmu::skills::SkillHandtoHand); int epic = 0; if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652 && GetLevel() > 46) epic = 280; @@ -2625,7 +2625,7 @@ int Mob::GetHandToHandDelay(void) { if (RuleB(Combat, UseRevampHandToHand)) { // everyone uses this in the revamp! - int skill = GetSkill(SkillHandtoHand); + int skill = GetSkill(EQEmu::skills::SkillHandtoHand); int epic = 0; int iksar = 0; if (IsClient() && CastToClient()->GetItemIDAt(12) == 10652 && GetLevel() > 46) @@ -2968,7 +2968,7 @@ bool Mob::HasRangedProcs() const bool Client::CheckDoubleAttack() { int chance = 0; - int skill = GetSkill(SkillDoubleAttack); + int skill = GetSkill(EQEmu::skills::SkillDoubleAttack); //Check for bonuses that give you a double attack chance regardless of skill (ie Bestial Frenzy/Harmonious Attack AA) int bonusGiveDA = aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack; if (skill > 0) @@ -2989,7 +2989,7 @@ bool Client::CheckDoubleAttack() // with varying triple attack skill (1-3% error at least) bool Client::CheckTripleAttack() { - int chance = GetSkill(SkillTripleAttack); + int chance = GetSkill(EQEmu::skills::SkillTripleAttack); if (chance < 1) return false; @@ -3013,7 +3013,7 @@ bool Mob::CheckDoubleAttack() { // Not 100% certain pets follow this or if it's just from pets not always // having the same skills as most mobs - int chance = GetSkill(SkillDoubleAttack); + int chance = GetSkill(EQEmu::skills::SkillDoubleAttack); if (GetLevel() > 35) chance += GetLevel(); @@ -3024,9 +3024,9 @@ bool Mob::CheckDoubleAttack() return zone->random.Int(1, 500) <= chance; } -void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, const SkillUseTypes skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special) { +void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, const EQEmu::skills::SkillType skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special) { // This method is called with skill_used=ABJURE for Damage Shield damage. - bool FromDamageShield = (skill_used == SkillAbjuration); + bool FromDamageShield = (skill_used == EQEmu::skills::SkillAbjuration); Log.Out(Logs::Detail, Logs::Combat, "Applying damage %d done by %s with skill %d and spell %d, avoidable? %s, is %sa buff tic in slot %d", damage, attacker?attacker->GetName():"NOBODY", skill_used, spell_id, avoidable?"yes":"no", iBuffTic?"":"not ", buffslot); @@ -3041,7 +3041,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons // only apply DS if physical damage (no spell damage) // damage shield calls this function with spell_id set, so its unavoidable - if (attacker && damage > 0 && spell_id == SPELL_UNKNOWN && skill_used != SkillArchery && skill_used != SkillThrowing) { + if (attacker && damage > 0 && spell_id == SPELL_UNKNOWN && skill_used != EQEmu::skills::SkillArchery && skill_used != EQEmu::skills::SkillThrowing) { DamageShield(attacker); } @@ -3167,7 +3167,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons } //check stun chances if bashing - if (damage > 0 && ((skill_used == SkillBash || skill_used == SkillKick) && attacker)) { + if (damage > 0 && ((skill_used == EQEmu::skills::SkillBash || skill_used == EQEmu::skills::SkillKick) && attacker)) { // NPCs can stun with their bash/kick as soon as they receive it. // Clients can stun mobs under level 56 with their kick when they get level 55 or greater. // Clients have a chance to stun if the mob is 56+ @@ -3181,15 +3181,15 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons // Less than base immunity // Client vs. Client always uses the chance if (!IsClient() && GetLevel() <= RuleI(Spells, BaseImmunityLevel)) { - if (skill_used == SkillBash) // Bash always will + if (skill_used == EQEmu::skills::SkillBash) // Bash always will stun_chance = 100; else if (attacker->GetLevel() >= RuleI(Combat, ClientStunLevel)) stun_chance = 100; // only if you're over level 55 and using kick } else { // higher than base immunity or Client vs. Client // not sure on this number, use same as NPC for now - if (skill_used == SkillKick && attacker->GetLevel() < RuleI(Combat, ClientStunLevel)) + if (skill_used == EQEmu::skills::SkillKick && attacker->GetLevel() < RuleI(Combat, ClientStunLevel)) stun_chance = RuleI(Combat, NPCBashKickStunChance); - else if (skill_used == SkillBash) + else if (skill_used == EQEmu::skills::SkillBash) stun_chance = RuleI(Combat, NPCBashKickStunChance) + attacker->spellbonuses.StunBashChance + attacker->itembonuses.StunBashChance + @@ -3268,7 +3268,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons a->meleepush_xy = attacker->GetHeading() * 2.0f; if (RuleB(Combat, MeleePush) && damage > 0 && !IsRooted() && (IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) { - a->force = EQEmu::GetSkillMeleePushForce(skill_used); + a->force = EQEmu::skills::GetSkillMeleePushForce(skill_used); // update NPC stuff auto new_pos = glm::vec3(m_Position.x + (a->force * std::sin(a->meleepush_xy) + m_Delta.x), m_Position.y + (a->force * std::cos(a->meleepush_xy) + m_Delta.y), m_Position.z); @@ -3868,10 +3868,10 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack int deadlyChance = 0; int deadlyMod = 0; - if(skill == SkillArchery && GetClass() == RANGER && GetSkill(SkillArchery) >= 65) + if (skill == EQEmu::skills::SkillArchery && GetClass() == RANGER && GetSkill(EQEmu::skills::SkillArchery) >= 65) critChance += 6; - if (skill == SkillThrowing && GetClass() == ROGUE && GetSkill(SkillThrowing) >= 65) { + if (skill == EQEmu::skills::SkillThrowing && GetClass() == ROGUE && GetSkill(EQEmu::skills::SkillThrowing) >= 65) { critChance += RuleI(Combat, RogueCritThrowingChance); deadlyChance = RuleI(Combat, RogueDeadlyStrikeChance); deadlyMod = RuleI(Combat, RogueDeadlyStrikeMod); @@ -3952,7 +3952,7 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack } } -bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) +bool Mob::TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse) { if (defender && !defender->IsClient() && defender->GetHPRatio() < 10){ @@ -4024,7 +4024,7 @@ void Mob::DoRiposte(Mob *defender) if (defender->GetClass() == MONK) defender->MonkSpecialAttack(this, defender->aabonuses.GiveDoubleRiposte[2]); - else if (defender->IsClient() && defender->CastToClient()->HasSkill((SkillUseTypes)defender->aabonuses.GiveDoubleRiposte[2])) + else if (defender->IsClient() && defender->CastToClient()->HasSkill((EQEmu::skills::SkillType)defender->aabonuses.GiveDoubleRiposte[2])) defender->CastToClient()->DoClassAttacks(this, defender->aabonuses.GiveDoubleRiposte[2], true); } } @@ -4063,7 +4063,7 @@ bool Mob::HasDied() { return Result; } -uint16 Mob::GetDamageTable(SkillUseTypes skillinuse) +uint16 Mob::GetDamageTable(EQEmu::skills::SkillType skillinuse) { if(GetLevel() <= 51) { @@ -4156,7 +4156,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui ProcMod = static_cast(spells[base_spell_id].base2[i]); } - else if (spells[base_spell_id].effectid[i] == SE_LimitToSkill && spells[base_spell_id].base[i] <= HIGHEST_SKILL) { + else if (spells[base_spell_id].effectid[i] == SE_LimitToSkill && spells[base_spell_id].base[i] <= EQEmu::skills::HIGHEST_SKILL) { if (CanProc && spells[base_spell_id].base[i] == skill && IsValidSpell(proc_spell_id)) { float final_chance = chance * (ProcMod / 100.0f); @@ -4200,7 +4200,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui ProcMod = static_cast(spells[base_spell_id].base2[i]); } - else if (spells[base_spell_id].effectid[i] == SE_LimitToSkill && spells[base_spell_id].base[i] <= HIGHEST_SKILL) { + else if (spells[base_spell_id].effectid[i] == SE_LimitToSkill && spells[base_spell_id].base[i] <= EQEmu::skills::HIGHEST_SKILL) { if (CanProc && spells[base_spell_id].base[i] == skill && IsValidSpell(proc_spell_id)) { float final_chance = chance * (ProcMod / 100.0f); @@ -4261,7 +4261,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui proc_spell_id = base1; ProcMod = static_cast(base2); } - else if(effect_id == SE_LimitToSkill && base1 <= HIGHEST_SKILL) { + else if (effect_id == SE_LimitToSkill && base1 <= EQEmu::skills::HIGHEST_SKILL) { if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) { float final_chance = chance * (ProcMod / 100.0f); @@ -4406,7 +4406,7 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type) return damage; } -void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse, ExtraAttackOptions *opts) +void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts) { if (!defender) return; @@ -4623,15 +4623,15 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) // extra off hand non-sense, can only double with skill of 150 or above // or you have any amount of GiveDoubleAttack if (candouble && hand == EQEmu::legacy::SlotSecondary) - candouble = GetSkill(SkillDoubleAttack) > 149 || (aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack) > 0; + candouble = GetSkill(EQEmu::skills::SkillDoubleAttack) > 149 || (aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack) > 0; if (candouble) { - CheckIncreaseSkill(SkillDoubleAttack, target, -10); + CheckIncreaseSkill(EQEmu::skills::SkillDoubleAttack, target, -10); if (CheckDoubleAttack()) { Attack(target, hand, false, false, IsFromSpell); // you can only triple from the main hand if (hand == EQEmu::legacy::SlotPrimary && CanThisClassTripleAttack()) { - CheckIncreaseSkill(SkillTripleAttack, target, -10); + CheckIncreaseSkill(EQEmu::skills::SkillTripleAttack, target, -10); if (CheckTripleAttack()) Attack(target, hand, false, false, IsFromSpell); } @@ -4659,7 +4659,7 @@ bool Mob::CheckDualWield() { // Pets /might/ follow a slightly different progression // although it could all be from pets having different skills than most mobs - int chance = GetSkill(SkillDualWield); + int chance = GetSkill(EQEmu::skills::SkillDualWield); if (GetLevel() > 35) chance += GetLevel(); @@ -4673,7 +4673,7 @@ bool Mob::CheckDualWield() bool Client::CheckDualWield() { - int chance = GetSkill(SkillDualWield) + GetLevel(); + int chance = GetSkill(EQEmu::skills::SkillDualWield) + GetLevel(); chance += aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity; int per_inc = spellbonuses.DualWieldChance + aabonuses.DualWieldChance + itembonuses.DualWieldChance; diff --git a/zone/beacon.h b/zone/beacon.h index bc09dae4b..398c9680e 100644 --- a/zone/beacon.h +++ b/zone/beacon.h @@ -34,8 +34,8 @@ public: ~Beacon(); //abstract virtual function implementations requird by base abstract class - virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } + virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; } + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index c5c1c92d2..ab15326cc 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -507,7 +507,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu } } - if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= HIGHEST_SKILL) { + if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= EQEmu::skills::HIGHEST_SKILL) { if ((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); @@ -517,7 +517,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu } // Process when ammo_slot_item = true or false - if (item->SkillModValue != 0 && item->SkillModType <= HIGHEST_SKILL) { + if (item->SkillModValue != 0 && item->SkillModType <= EQEmu::skills::HIGHEST_SKILL) { if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) || (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) { @@ -672,10 +672,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) // Note: AA effects that use accuracy are skill limited, while spell effect is not. case SE_Accuracy: // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; - if ((base2 == ALL_SKILLS) && (newbon->Accuracy[HIGHEST_SKILL + 1] < base1)) - newbon->Accuracy[HIGHEST_SKILL + 1] = base1; + if ((base2 == ALL_SKILLS) && (newbon->Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] < base1)) + newbon->Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] = base1; else if (newbon->Accuracy[base2] < base1) newbon->Accuracy[base2] += base1; break; @@ -1015,10 +1015,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_HitChance: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if (base2 == ALL_SKILLS) - newbon->HitChanceEffect[HIGHEST_SKILL + 1] += base1; + newbon->HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] += base1; else newbon->HitChanceEffect[base2] += base1; } @@ -1069,21 +1069,21 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_CriticalHitChance: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if (base2 == ALL_SKILLS) - newbon->CriticalHitChance[HIGHEST_SKILL + 1] += base1; + newbon->CriticalHitChance[EQEmu::skills::HIGHEST_SKILL + 1] += base1; else newbon->CriticalHitChance[base2] += base1; } break; case SE_CriticalDamageMob: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; // base1 = effect value, base2 = skill restrictions(-1 for all) if (base2 == ALL_SKILLS) - newbon->CritDmgMob[HIGHEST_SKILL + 1] += base1; + newbon->CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] += base1; else newbon->CritDmgMob[base2] += base1; break; @@ -1109,10 +1109,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_SkillDamageAmount: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if (base2 == ALL_SKILLS) - newbon->SkillDamageAmount[HIGHEST_SKILL + 1] += base1; + newbon->SkillDamageAmount[EQEmu::skills::HIGHEST_SKILL + 1] += base1; else newbon->SkillDamageAmount[base2] += base1; break; @@ -1128,10 +1128,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_DamageModifier: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if (base2 == ALL_SKILLS) - newbon->DamageModifier[HIGHEST_SKILL + 1] += base1; + newbon->DamageModifier[EQEmu::skills::HIGHEST_SKILL + 1] += base1; else newbon->DamageModifier[base2] += base1; break; @@ -1139,10 +1139,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_DamageModifier2: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if (base2 == ALL_SKILLS) - newbon->DamageModifier2[HIGHEST_SKILL + 1] += base1; + newbon->DamageModifier2[EQEmu::skills::HIGHEST_SKILL + 1] += base1; else newbon->DamageModifier2[base2] += base1; break; @@ -1178,7 +1178,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) // Physically raises skill cap ie if 55/55 it will raise to 55/60 case SE_RaiseSkillCap: { - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if (newbon->RaiseSkillCap[base2] < base1) @@ -1350,9 +1350,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_LimitToSkill: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; - if (base1 <= HIGHEST_SKILL) + if (base1 <= EQEmu::skills::HIGHEST_SKILL) newbon->LimitToSkill[base1] = true; break; } @@ -1416,7 +1416,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_ReduceTradeskillFail:{ - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; newbon->ReduceTradeskillFail[base2] += base1; @@ -1938,26 +1938,26 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_CriticalHitChance: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if (AdditiveWornBonus) { if(base2 == ALL_SKILLS) - new_bonus->CriticalHitChance[HIGHEST_SKILL+1] += effect_value; + new_bonus->CriticalHitChance[EQEmu::skills::HIGHEST_SKILL + 1] += effect_value; else new_bonus->CriticalHitChance[base2] += effect_value; } else if(effect_value < 0) { - if(base2 == ALL_SKILLS && new_bonus->CriticalHitChance[HIGHEST_SKILL+1] > effect_value) - new_bonus->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; + if (base2 == ALL_SKILLS && new_bonus->CriticalHitChance[EQEmu::skills::HIGHEST_SKILL + 1] > effect_value) + new_bonus->CriticalHitChance[EQEmu::skills::HIGHEST_SKILL + 1] = effect_value; else if(base2 != ALL_SKILLS && new_bonus->CriticalHitChance[base2] > effect_value) new_bonus->CriticalHitChance[base2] = effect_value; } - else if(base2 == ALL_SKILLS && new_bonus->CriticalHitChance[HIGHEST_SKILL+1] < effect_value) - new_bonus->CriticalHitChance[HIGHEST_SKILL+1] = effect_value; + else if (base2 == ALL_SKILLS && new_bonus->CriticalHitChance[EQEmu::skills::HIGHEST_SKILL + 1] < effect_value) + new_bonus->CriticalHitChance[EQEmu::skills::HIGHEST_SKILL + 1] = effect_value; else if(base2 != ALL_SKILLS && new_bonus->CriticalHitChance[base2] < effect_value) new_bonus->CriticalHitChance[base2] = effect_value; @@ -2144,24 +2144,24 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_HitChance: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if (AdditiveWornBonus){ if(base2 == ALL_SKILLS) - new_bonus->HitChanceEffect[HIGHEST_SKILL+1] += effect_value; + new_bonus->HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] += effect_value; else new_bonus->HitChanceEffect[base2] += effect_value; } else if(base2 == ALL_SKILLS){ - if ((effect_value < 0) && (new_bonus->HitChanceEffect[HIGHEST_SKILL+1] > effect_value)) - new_bonus->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; + if ((effect_value < 0) && (new_bonus->HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] > effect_value)) + new_bonus->HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] = effect_value; - else if (!new_bonus->HitChanceEffect[HIGHEST_SKILL+1] || - ((new_bonus->HitChanceEffect[HIGHEST_SKILL+1] > 0) && (new_bonus->HitChanceEffect[HIGHEST_SKILL+1] < effect_value))) - new_bonus->HitChanceEffect[HIGHEST_SKILL+1] = effect_value; + else if (!new_bonus->HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] || + ((new_bonus->HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] > 0) && (new_bonus->HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] < effect_value))) + new_bonus->HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] = effect_value; } else { @@ -2181,9 +2181,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_DamageModifier: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; - int skill = base2 == ALL_SKILLS ? HIGHEST_SKILL + 1 : base2; + int skill = base2 == ALL_SKILLS ? EQEmu::skills::HIGHEST_SKILL + 1 : base2; if (effect_value < 0 && new_bonus->DamageModifier[skill] > effect_value) new_bonus->DamageModifier[skill] = effect_value; else if (effect_value > 0 && new_bonus->DamageModifier[skill] < effect_value) @@ -2194,9 +2194,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_DamageModifier2: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; - int skill = base2 == ALL_SKILLS ? HIGHEST_SKILL + 1 : base2; + int skill = base2 == ALL_SKILLS ? EQEmu::skills::HIGHEST_SKILL + 1 : base2; if (effect_value < 0 && new_bonus->DamageModifier2[skill] > effect_value) new_bonus->DamageModifier2[skill] = effect_value; else if (effect_value > 0 && new_bonus->DamageModifier2[skill] < effect_value) @@ -2207,9 +2207,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_MinDamageModifier: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; - int skill = base2 == ALL_SKILLS ? HIGHEST_SKILL + 1 : base2; + int skill = base2 == ALL_SKILLS ? EQEmu::skills::HIGHEST_SKILL + 1 : base2; if (effect_value < 0 && new_bonus->MinDamageModifier[skill] > effect_value) new_bonus->MinDamageModifier[skill] = effect_value; else if (effect_value > 0 && new_bonus->MinDamageModifier[skill] < effect_value) @@ -2284,14 +2284,14 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_Accuracy: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; - if ((effect_value < 0) && (new_bonus->Accuracy[HIGHEST_SKILL+1] > effect_value)) - new_bonus->Accuracy[HIGHEST_SKILL+1] = effect_value; + if ((effect_value < 0) && (new_bonus->Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] > effect_value)) + new_bonus->Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] = effect_value; - else if (!new_bonus->Accuracy[HIGHEST_SKILL+1] || - ((new_bonus->Accuracy[HIGHEST_SKILL+1] > 0) && (new_bonus->Accuracy[HIGHEST_SKILL+1] < effect_value))) - new_bonus->Accuracy[HIGHEST_SKILL+1] = effect_value; + else if (!new_bonus->Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] || + ((new_bonus->Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] > 0) && (new_bonus->Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] < effect_value))) + new_bonus->Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] = effect_value; break; } @@ -2310,19 +2310,19 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_SkillDamageTaken: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; //When using npc_spells_effects if MAX value set, use stackable quest based modifier. if (IsAISpellEffect && max){ if(base2 == ALL_SKILLS) - SkillDmgTaken_Mod[HIGHEST_SKILL+1] = effect_value; + SkillDmgTaken_Mod[EQEmu::skills::HIGHEST_SKILL + 1] = effect_value; else SkillDmgTaken_Mod[base2] = effect_value; } else { if(base2 == ALL_SKILLS) - new_bonus->SkillDmgTaken[HIGHEST_SKILL+1] += effect_value; + new_bonus->SkillDmgTaken[EQEmu::skills::HIGHEST_SKILL + 1] += effect_value; else new_bonus->SkillDmgTaken[base2] += effect_value; @@ -2431,10 +2431,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_CriticalDamageMob: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if(base2 == ALL_SKILLS) - new_bonus->CritDmgMob[HIGHEST_SKILL+1] += effect_value; + new_bonus->CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] += effect_value; else new_bonus->CritDmgMob[base2] += effect_value; break; @@ -2450,10 +2450,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_SkillDamageAmount: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if(base2 == ALL_SKILLS) - new_bonus->SkillDamageAmount[HIGHEST_SKILL+1] += effect_value; + new_bonus->SkillDamageAmount[EQEmu::skills::HIGHEST_SKILL + 1] += effect_value; else new_bonus->SkillDamageAmount[base2] += effect_value; break; @@ -2558,10 +2558,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_SkillDamageAmount2: { // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if(base2 == ALL_SKILLS) - new_bonus->SkillDamageAmount2[HIGHEST_SKILL+1] += effect_value; + new_bonus->SkillDamageAmount2[EQEmu::skills::HIGHEST_SKILL + 1] += effect_value; else new_bonus->SkillDamageAmount2[base2] += effect_value; break; @@ -3096,9 +3096,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_LimitToSkill:{ // Bad data or unsupported new skill - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; - if (effect_value <= HIGHEST_SKILL){ + if (effect_value <= EQEmu::skills::HIGHEST_SKILL){ new_bonus->LimitToSkill[effect_value] = true; } break; @@ -3155,7 +3155,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_ReduceTradeskillFail:{ - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; new_bonus->ReduceTradeskillFail[base2] += effect_value; @@ -3168,7 +3168,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; case SE_RaiseSkillCap: { - if (base2 > HIGHEST_SKILL) + if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if (new_bonus->RaiseSkillCap[base2] < effect_value) @@ -3866,7 +3866,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) case SE_CriticalHitChance: { - for(int e = 0; e < HIGHEST_SKILL+1; e++) + for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { spellbonuses.CriticalHitChance[e] = effect_value; aabonuses.CriticalHitChance[e] = effect_value; @@ -3984,7 +3984,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) case SE_HitChance: { - for(int e = 0; e < HIGHEST_SKILL+1; e++) + for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { spellbonuses.HitChanceEffect[e] = effect_value; aabonuses.HitChanceEffect[e] = effect_value; @@ -3995,7 +3995,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) case SE_DamageModifier: { - for(int e = 0; e < HIGHEST_SKILL+1; e++) + for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { spellbonuses.DamageModifier[e] = effect_value; aabonuses.DamageModifier[e] = effect_value; @@ -4006,7 +4006,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) case SE_DamageModifier2: { - for(int e = 0; e < HIGHEST_SKILL+1; e++) + for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { spellbonuses.DamageModifier2[e] = effect_value; aabonuses.DamageModifier2[e] = effect_value; @@ -4017,7 +4017,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) case SE_MinDamageModifier: { - for(int e = 0; e < HIGHEST_SKILL+1; e++) + for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { spellbonuses.MinDamageModifier[e] = effect_value; aabonuses.MinDamageModifier[e] = effect_value; @@ -4058,10 +4058,10 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) case SE_Accuracy: { - spellbonuses.Accuracy[HIGHEST_SKILL+1] = effect_value; - itembonuses.Accuracy[HIGHEST_SKILL+1] = effect_value; + spellbonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] = effect_value; + itembonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] = effect_value; - for(int e = 0; e < HIGHEST_SKILL+1; e++) + for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { aabonuses.Accuracy[e] = effect_value; } @@ -4088,7 +4088,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) case SE_SkillDamageTaken: { - for(int e = 0; e < HIGHEST_SKILL+1; e++) + for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { spellbonuses.SkillDmgTaken[e] = effect_value; aabonuses.SkillDmgTaken[e] = effect_value; @@ -4193,7 +4193,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) case SE_CriticalDamageMob: { - for(int e = 0; e < HIGHEST_SKILL+1; e++) + for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { spellbonuses.CritDmgMob[e] = effect_value; aabonuses.CritDmgMob[e] = effect_value; @@ -4204,7 +4204,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) case SE_SkillDamageAmount: { - for(int e = 0; e < HIGHEST_SKILL+1; e++) + for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { spellbonuses.SkillDamageAmount[e] = effect_value; aabonuses.SkillDamageAmount[e] = effect_value; @@ -4255,7 +4255,7 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) case SE_SkillDamageAmount2: { - for(int e = 0; e < HIGHEST_SKILL+1; e++) + for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { spellbonuses.SkillDamageAmount2[e] = effect_value; aabonuses.SkillDamageAmount2[e] = effect_value; diff --git a/zone/bot.cpp b/zone/bot.cpp index 0cb75e8a5..a72c8f142 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -23,6 +23,7 @@ #include "doors.h" #include "quest_parser_collection.h" #include "../common/string_util.h" +#include "../common/say_link.h" extern volatile bool is_zone_loaded; @@ -1139,16 +1140,16 @@ int32 Bot::acmod() { void Bot::GenerateArmorClass() { /// new formula int avoidance = 0; - avoidance = (acmod() + ((GetSkill(SkillDefense) * 16) / 9)); + avoidance = (acmod() + ((GetSkill(EQEmu::skills::SkillDefense) * 16) / 9)); if(avoidance < 0) avoidance = 0; int mitigation = 0; if(GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == NECROMANCER || GetClass() == ENCHANTER) { - mitigation = (GetSkill(SkillDefense) / 4 + (itembonuses.AC + 1)); + mitigation = (GetSkill(EQEmu::skills::SkillDefense) / 4 + (itembonuses.AC + 1)); mitigation -= 4; } else { - mitigation = (GetSkill(SkillDefense) / 3 + ((itembonuses.AC * 4) / 3)); + mitigation = (GetSkill(EQEmu::skills::SkillDefense) / 3 + ((itembonuses.AC * 4) / 3)); if(GetClass() == MONK) mitigation += (GetLevel() * 13 / 10); //the 13/10 might be wrong, but it is close... } @@ -1173,36 +1174,36 @@ void Bot::GenerateArmorClass() { } uint16 Bot::GetPrimarySkillValue() { - SkillUseTypes skill = HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill + EQEmu::skills::SkillType skill = EQEmu::skills::HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill bool equiped = m_inv.GetItem(EQEmu::legacy::SlotPrimary); if(!equiped) - skill = SkillHandtoHand; + skill = EQEmu::skills::SkillHandtoHand; else { uint8 type = m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType; //is this the best way to do this? switch(type) { case EQEmu::item::ItemType1HSlash: - skill = Skill1HSlashing; + skill = EQEmu::skills::Skill1HSlashing; break; case EQEmu::item::ItemType2HSlash: - skill = Skill2HSlashing; + skill = EQEmu::skills::Skill2HSlashing; break; case EQEmu::item::ItemType1HPiercing: - skill = Skill1HPiercing; + skill = EQEmu::skills::Skill1HPiercing; break; case EQEmu::item::ItemType1HBlunt: - skill = Skill1HBlunt; + skill = EQEmu::skills::Skill1HBlunt; break; case EQEmu::item::ItemType2HBlunt: - skill = Skill2HBlunt; + skill = EQEmu::skills::Skill2HBlunt; break; case EQEmu::item::ItemType2HPiercing: - skill = Skill2HPiercing; + skill = EQEmu::skills::Skill2HPiercing; break; case EQEmu::item::ItemTypeMartial: - skill = SkillHandtoHand; + skill = EQEmu::skills::SkillHandtoHand; break; default: - skill = SkillHandtoHand; + skill = EQEmu::skills::SkillHandtoHand; break; } } @@ -1210,7 +1211,7 @@ uint16 Bot::GetPrimarySkillValue() { return GetSkill(skill); } -uint16 Bot::MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const { +uint16 Bot::MaxSkill(EQEmu::skills::SkillType skillid, uint16 class_, uint16 level) const { return(database.GetSkillCap(class_, skillid, level)); } @@ -1218,7 +1219,7 @@ uint32 Bot::GetTotalATK() { uint32 AttackRating = 0; uint32 WornCap = itembonuses.ATK; if(IsBot()) { - AttackRating = ((WornCap * 1.342) + (GetSkill(SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69)); + AttackRating = ((WornCap * 1.342) + (GetSkill(EQEmu::skills::SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69)); AttackRating += aabonuses.ATK + GroupLeadershipAAOffenseEnhancement(); if (AttackRating < 10) AttackRating = 10; @@ -1233,7 +1234,7 @@ uint32 Bot::GetTotalATK() { uint32 Bot::GetATKRating() { uint32 AttackRating = 0; if(IsBot()) { - AttackRating = (GetSkill(SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69); + AttackRating = (GetSkill(EQEmu::skills::SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69); if (AttackRating < 10) AttackRating = 10; } @@ -1914,7 +1915,7 @@ void Bot::BotRangedAttack(Mob* other) { if(!IsAttackAllowed(other) || IsCasting() || DivineAura() || IsStunned() || IsMezzed() || (GetAppearance() == eaDead)) return; - SendItemAnimation(other, Ammo, SkillArchery); + SendItemAnimation(other, Ammo, EQEmu::skills::SkillArchery); //DoArcheryAttackDmg(GetTarget(), rangedItem, ammoItem); DoArcheryAttackDmg(other, rangedItem, ammoItem); // watch @@ -1959,12 +1960,12 @@ bool Bot::CheckBotDoubleAttack(bool tripleAttack) { //Check for bonuses that give you a double attack chance regardless of skill (ie Bestial Frenzy/Harmonious Attack AA) uint32 bonusGiveDA = (aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack); // If you don't have the double attack skill, return - if(!GetSkill(SkillDoubleAttack) && !(GetClass() == BARD || GetClass() == BEASTLORD)) + if (!GetSkill(EQEmu::skills::SkillDoubleAttack) && !(GetClass() == BARD || GetClass() == BEASTLORD)) return false; // You start with no chance of double attacking float chance = 0.0f; - uint16 skill = GetSkill(SkillDoubleAttack); + uint16 skill = GetSkill(EQEmu::skills::SkillDoubleAttack); int32 bonusDA = (aabonuses.DoubleAttackChance + spellbonuses.DoubleAttackChance + itembonuses.DoubleAttackChance); //Use skill calculations otherwise, if you only have AA applied GiveDoubleAttack chance then use that value as the base. if (skill) @@ -1989,13 +1990,13 @@ bool Bot::CheckBotDoubleAttack(bool tripleAttack) { return false; } -void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime) { +void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime) { if (!CanDoSpecialAttack(other)) return; //For spells using skill value 98 (feral swipe ect) server sets this to 67 automatically. - if (skillinuse == SkillBegging) - skillinuse = SkillOffense; + if (skillinuse == EQEmu::skills::SkillBegging) + skillinuse = EQEmu::skills::SkillOffense; int damage = 0; uint32 hate = 0; @@ -2052,7 +2053,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes else damage = -5; - if(skillinuse == SkillBash){ + if (skillinuse == EQEmu::skills::SkillBash){ const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); const EQEmu::Item_Struct* botweapon = 0; if(inst) @@ -2069,8 +2070,8 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes other->AddToHateList(this, hate); bool CanSkillProc = true; - if (skillinuse == SkillOffense){ //Hack to allow damage to display. - skillinuse = SkillTigerClaw; //'strike' your opponent - Arbitrary choice for message. + if (skillinuse == EQEmu::skills::SkillOffense){ //Hack to allow damage to display. + skillinuse = EQEmu::skills::SkillTigerClaw; //'strike' your opponent - Arbitrary choice for message. CanSkillProc = false; //Disable skill procs } @@ -2081,7 +2082,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes if (damage > 0) CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); - if((skillinuse == SkillDragonPunch) && GetAA(aaDragonPunch) && zone->random.Int(0, 99) < 25){ + if ((skillinuse == EQEmu::skills::SkillDragonPunch) && GetAA(aaDragonPunch) && zone->random.Int(0, 99) < 25){ SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff); other->Stun(100); } @@ -2093,23 +2094,23 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes TrySkillProc(other, skillinuse, ReuseTime, true); } -void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) { +void Bot::ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int32 &mindmg) { int item_slot = -1; //1: Apply bonus from AC (BOOT/SHIELD/HANDS) est. 40AC=6dmg switch (skill) { - case SkillFlyingKick: - case SkillRoundKick: - case SkillKick: - item_slot = EQEmu::legacy::SlotFeet; - break; - case SkillBash: - item_slot = EQEmu::legacy::SlotSecondary; - break; - case SkillDragonPunch: - case SkillEagleStrike: - case SkillTigerClaw: - item_slot = EQEmu::legacy::SlotHands; - break; + case EQEmu::skills::SkillFlyingKick: + case EQEmu::skills::SkillRoundKick: + case EQEmu::skills::SkillKick: + item_slot = EQEmu::legacy::SlotFeet; + break; + case EQEmu::skills::SkillBash: + item_slot = EQEmu::legacy::SlotSecondary; + break; + case EQEmu::skills::SkillDragonPunch: + case EQEmu::skills::SkillEagleStrike: + case EQEmu::skills::SkillTigerClaw: + item_slot = EQEmu::legacy::SlotHands; + break; } if (item_slot >= EQEmu::legacy::EQUIPMENT_BEGIN){ @@ -2518,7 +2519,7 @@ void Bot::AI_Process() { if (bIsFist || !weapon->IsType2HWeapon()) { float DualWieldProbability = 0.0f; int32 Ambidexterity = (aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity); - DualWieldProbability = ((GetSkill(SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f); // 78.0 max + DualWieldProbability = ((GetSkill(EQEmu::skills::SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f); // 78.0 max int32 DWBonus = (spellbonuses.DualWieldChance + itembonuses.DualWieldChance); DualWieldProbability += (DualWieldProbability * float(DWBonus) / 100.0f); float random = zone->random.Real(0, 1); @@ -2739,7 +2740,7 @@ void Bot::PetAIProcess() { // Ok now, let's check pet's offhand. if (botPet->GetAttackDWTimer().Check() && botPet->GetOwnerID() && botPet->GetOwner() && ((botPet->GetOwner()->GetClass() == MAGICIAN) || (botPet->GetOwner()->GetClass() == NECROMANCER) || (botPet->GetOwner()->GetClass() == SHADOWKNIGHT) || (botPet->GetOwner()->GetClass() == BEASTLORD))) { if(botPet->GetOwner()->GetLevel() >= 24) { - float DualWieldProbability = ((botPet->GetSkill(SkillDualWield) + botPet->GetLevel()) / 400.0f); + float DualWieldProbability = ((botPet->GetSkill(EQEmu::skills::SkillDualWield) + botPet->GetLevel()) / 400.0f); DualWieldProbability -= zone->random.Real(0, 1); if(DualWieldProbability < 0) { botPet->Attack(botPet->GetTarget(), EQEmu::legacy::SlotSecondary); @@ -3586,7 +3587,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } -bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { +bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { if(!NPC::Death(killerMob, damage, spell_id, attack_skill)) return false; @@ -3661,7 +3662,7 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att return true; } -void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { +void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(spell_id == 0) spell_id = SPELL_UNKNOWN; @@ -3758,7 +3759,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b // calculate attack_skill and skillinuse depending on hand and weapon // also send Packet to near clients - SkillUseTypes skillinuse; + EQEmu::skills::SkillType skillinuse; AttackAnimation(skillinuse, Hand, weapon); Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse); /// Now figure out damage @@ -4776,7 +4777,7 @@ float Bot::GetProcChances(float ProcBonus, uint16 hand) { int Bot::GetHandToHandDamage(void) { if (RuleB(Combat, UseRevampHandToHand)) { // everyone uses this in the revamp! - int skill = GetSkill(SkillHandtoHand); + int skill = GetSkill(EQEmu::skills::SkillHandtoHand); int epic = 0; if (CastToNPC()->GetEquipment(EQEmu::legacy::MaterialHands) == 10652 && GetLevel() > 46) epic = 280; @@ -4813,7 +4814,7 @@ int Bot::GetHandToHandDamage(void) { return 2; } -bool Bot::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse) { +bool Bot::TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse) { if (!defender) return false; @@ -4855,12 +4856,12 @@ void Bot::DoRiposte(Mob* defender) { } } -void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage, int32 hate_override,int ReuseTime, bool HitChance) { +void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool HitChance) { int32 hate = max_damage; if(hate_override > -1) hate = hate_override; - if(skill == SkillBash) { + if (skill == EQEmu::skills::SkillBash) { const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); const EQEmu::Item_Struct* botweapon = 0; if(inst) @@ -4876,7 +4877,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, min_damage += (min_damage * GetMeleeMinDamageMod_SE(skill) / 100); int hand = EQEmu::legacy::SlotPrimary; - if (skill == SkillThrowing || skill == SkillArchery) + if (skill == EQEmu::skills::SkillThrowing || skill == EQEmu::skills::SkillArchery) hand = EQEmu::legacy::SlotRange; if (who->AvoidDamage(this, max_damage, hand)) { if (max_damage == -3) @@ -4953,7 +4954,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { } else { RogueBackstab(other); if (level > 54) { - float DoubleAttackProbability = ((GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f); + float DoubleAttackProbability = ((GetSkill(EQEmu::skills::SkillDoubleAttack) + GetLevel()) / 500.0f); if(zone->random.Real(0, 1) < DoubleAttackProbability) { if(other->GetHP() > 0) RogueBackstab(other,false,ReuseTime); @@ -4966,7 +4967,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { } else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) { RogueBackstab(other, true); if (level > 54) { - float DoubleAttackProbability = ((GetSkill(SkillDoubleAttack) + GetLevel()) / 500.0f); + float DoubleAttackProbability = ((GetSkill(EQEmu::skills::SkillDoubleAttack) + GetLevel()) / 500.0f); if(zone->random.Real(0, 1) < DoubleAttackProbability) if(other->GetHP() > 0) RogueBackstab(other,true, ReuseTime); @@ -5002,11 +5003,11 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { if(primaryweapondamage > 0) { if(level > 25) { - max_hit = (((((2 * backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + ((level - 25) / 3) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); - hate = (20 * backstab_dmg * GetSkill(SkillBackstab) / 355); + max_hit = (((((2 * backstab_dmg) * GetDamageTable(EQEmu::skills::SkillBackstab) / 100) * 10 * GetSkill(EQEmu::skills::SkillBackstab) / 355) + ((level - 25) / 3) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); + hate = (20 * backstab_dmg * GetSkill(EQEmu::skills::SkillBackstab) / 355); } else { - max_hit = (((((2 * backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); - hate = (20 * backstab_dmg * GetSkill(SkillBackstab) / 355); + max_hit = (((((2 * backstab_dmg) * GetDamageTable(EQEmu::skills::SkillBackstab) / 100) * 10 * GetSkill(EQEmu::skills::SkillBackstab) / 355) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); + hate = (20 * backstab_dmg * GetSkill(EQEmu::skills::SkillBackstab) / 355); } if (level < 51) @@ -5014,7 +5015,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { else min_hit = ((level * ( level * 5 - 105)) / 100); - if(!other->CheckHitChance(this, SkillBackstab, 0)) + if (!other->CheckHitChance(this, EQEmu::skills::SkillBackstab, 0)) ndamage = 0; else { if (min_damage) { @@ -5029,7 +5030,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { } else ndamage = -5; - DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime); + DoSpecialAttackDamage(other, EQEmu::skills::SkillBackstab, ndamage, min_hit, hate, ReuseTime); DoAnim(anim1HPiercing); } @@ -5037,9 +5038,9 @@ void Bot::RogueAssassinate(Mob* other) { ItemInst* botweaponInst = GetBotItem(EQEmu::legacy::SlotPrimary); if(botweaponInst) { if(GetWeaponDamage(other, botweaponInst)) - other->Damage(this, 32000, SPELL_UNKNOWN, SkillBackstab); + other->Damage(this, 32000, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab); else - other->Damage(this, -5, SPELL_UNKNOWN, SkillBackstab); + other->Damage(this, -5, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab); } DoAnim(anim1HPiercing); @@ -5104,54 +5105,54 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { canBash = true; if(!canBash || zone->random.Int(0, 100) > 25) - skill_to_use = SkillKick; + skill_to_use = EQEmu::skills::SkillKick; else - skill_to_use = SkillBash; + skill_to_use = EQEmu::skills::SkillBash; } case RANGER: case BEASTLORD: - skill_to_use = SkillKick; + skill_to_use = EQEmu::skills::SkillKick; break; case BERSERKER: - skill_to_use = SkillFrenzy; + skill_to_use = EQEmu::skills::SkillFrenzy; break; case CLERIC: case SHADOWKNIGHT: case PALADIN: if(level >= RuleI(Combat, NPCBashKickLevel)){ if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQEmu::legacy::SlotSecondary) && m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType == EQEmu::item::ItemTypeShield) || (m_inv.GetItem(EQEmu::legacy::SlotPrimary) && m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->IsType2HWeapon() && GetAA(aa2HandBash) >= 1)) - skill_to_use = SkillBash; + skill_to_use = EQEmu::skills::SkillBash; } break; case MONK: if(GetLevel() >= 30) - skill_to_use = SkillFlyingKick; + skill_to_use = EQEmu::skills::SkillFlyingKick; else if(GetLevel() >= 25) - skill_to_use = SkillDragonPunch; + skill_to_use = EQEmu::skills::SkillDragonPunch; else if(GetLevel() >= 20) - skill_to_use = SkillEagleStrike; + skill_to_use = EQEmu::skills::SkillEagleStrike; else if(GetLevel() >= 10) - skill_to_use = SkillTigerClaw; + skill_to_use = EQEmu::skills::SkillTigerClaw; else if(GetLevel() >= 5) - skill_to_use = SkillRoundKick; + skill_to_use = EQEmu::skills::SkillRoundKick; else - skill_to_use = SkillKick; + skill_to_use = EQEmu::skills::SkillKick; break; case ROGUE: - skill_to_use = SkillBackstab; + skill_to_use = EQEmu::skills::SkillBackstab; break; } if(skill_to_use == -1) return; - if(skill_to_use == SkillBash) { + if (skill_to_use == EQEmu::skills::SkillBash) { if (target != this) { DoAnim(animTailRake); if (GetWeaponDamage(target, GetBotItem(EQEmu::legacy::SlotSecondary)) <= 0 && GetWeaponDamage(target, GetBotItem(EQEmu::legacy::SlotShoulders)) <= 0) dmg = -5; else { - if(!target->CheckHitChance(this, SkillBash, 0)) + if (!target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) dmg = 0; else { if(RuleB(Combat, UseIntervalAC)) @@ -5161,16 +5162,16 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { } } reuse = (BashReuseTime * 1000); - DoSpecialAttackDamage(target, SkillBash, dmg, 1, -1,reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, 1, -1, reuse); did_attack = true; } } - if(skill_to_use == SkillFrenzy) { + if (skill_to_use == EQEmu::skills::SkillFrenzy) { int AtkRounds = 3; int skillmod = 0; - if(MaxSkill(SkillFrenzy) > 0) - skillmod = (100 * GetSkill(SkillFrenzy)/MaxSkill(SkillFrenzy)); + if (MaxSkill(EQEmu::skills::SkillFrenzy) > 0) + skillmod = (100 * GetSkill(EQEmu::skills::SkillFrenzy) / MaxSkill(EQEmu::skills::SkillFrenzy)); int32 max_dmg = (26 + ((((GetLevel() - 6) * 2) * skillmod) / 100)) * ((100 + RuleI(Combat, FrenzyBonus)) / 100); int32 min_dmg = 0; @@ -5188,20 +5189,20 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { did_attack = true; while(AtkRounds > 0) { if (GetTarget() && (AtkRounds == 1 || zone->random.Int(0, 100) < 75)) { - DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg, reuse, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, min_dmg, max_dmg, reuse, true); } AtkRounds--; } } - if(skill_to_use == SkillKick) { + if (skill_to_use == EQEmu::skills::SkillKick) { if(target != this) { DoAnim(animKick); if (GetWeaponDamage(target, GetBotItem(EQEmu::legacy::SlotFeet)) <= 0) dmg = -5; else { - if(!target->CheckHitChance(this, SkillKick, 0)) + if (!target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) dmg = 0; else { if(RuleB(Combat, UseIntervalAC)) @@ -5211,17 +5212,17 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { } } reuse = (KickReuseTime * 1000); - DoSpecialAttackDamage(target, SkillKick, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, 1, -1, reuse); did_attack = true; } } - if(skill_to_use == SkillFlyingKick || skill_to_use == SkillDragonPunch || skill_to_use == SkillEagleStrike || skill_to_use == SkillTigerClaw || skill_to_use == SkillRoundKick) { + if (skill_to_use == EQEmu::skills::SkillFlyingKick || skill_to_use == EQEmu::skills::SkillDragonPunch || skill_to_use == EQEmu::skills::SkillEagleStrike || skill_to_use == EQEmu::skills::SkillTigerClaw || skill_to_use == EQEmu::skills::SkillRoundKick) { reuse = (MonkSpecialAttack(target, skill_to_use) - 1); MonkSpecialAttack(target, skill_to_use); uint32 bDoubleSpecialAttack = (itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack); if(bDoubleSpecialAttack && (bDoubleSpecialAttack >= 100 || bDoubleSpecialAttack > zone->random.Int(0, 100))) { - int MonkSPA [5] = { SkillFlyingKick, SkillDragonPunch, SkillEagleStrike, SkillTigerClaw, SkillRoundKick }; + int MonkSPA[5] = { EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, EQEmu::skills::SkillRoundKick }; MonkSpecialAttack(target, MonkSPA[zone->random.Int(0, 4)]); int TripleChance = 25; if (bDoubleSpecialAttack > 100) @@ -5235,7 +5236,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { did_attack = true; } - if(skill_to_use == SkillBackstab) { + if (skill_to_use == EQEmu::skills::SkillBackstab) { reuse = (BackstabReuseTime * 1000); did_attack = true; if (IsRiposte) @@ -5246,9 +5247,9 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { classattack_timer.Start(reuse / HasteModifier); } -bool Bot::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { +bool Bot::TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse) { bool Result = false; - if(defender && (defender->GetBodyType() == BT_Humanoid) && (skillInUse == SkillArchery) && (GetClass() == RANGER) && (GetLevel() >= 62)) { + if (defender && (defender->GetBodyType() == BT_Humanoid) && (skillInUse == EQEmu::skills::SkillArchery) && (GetClass() == RANGER) && (GetLevel() >= 62)) { int defenderLevel = defender->GetLevel(); int rangerLevel = GetLevel(); if(GetAA(aaHeadshot) && ((defenderLevel - 46) <= GetAA(aaHeadshot) * 2)) { @@ -5515,7 +5516,7 @@ void Bot::SetAttackTimer() { } } - if (!GetSkill(SkillDualWield)) { + if (!GetSkill(EQEmu::skills::SkillDualWield)) { attack_dw_timer.Disable(); continue; } @@ -6731,7 +6732,7 @@ int32 Bot::CalcManaRegen() { if (IsSitting()) { BuffFadeBySitModifier(); if(botclass != WARRIOR && botclass != MONK && botclass != ROGUE && botclass != BERSERKER) { - regen = ((((GetSkill(SkillMeditate) / 10) + (level - (level / 4))) / 4) + 4); + regen = ((((GetSkill(EQEmu::skills::SkillMeditate) / 10) + (level - (level / 4))) / 4) + 4); regen += (spellbonuses.ManaRegen + itembonuses.ManaRegen); } else regen = (2 + spellbonuses.ManaRegen + itembonuses.ManaRegen); @@ -7202,11 +7203,11 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { if(inst) { item = inst->GetItem(); if(item) { - strcpy(insr->itemnames[SoF::inventory::SlotPowerSource], item->Name); - insr->itemicons[SoF::inventory::SlotPowerSource] = item->Icon; + strcpy(insr->itemnames[SoF::invslot::PossessionsPowerSource], item->Name); + insr->itemicons[SoF::invslot::PossessionsPowerSource] = item->Icon; } else - insr->itemicons[SoF::inventory::SlotPowerSource] = 0xFFFFFFFF; + insr->itemicons[SoF::invslot::PossessionsPowerSource] = 0xFFFFFFFF; } inst = inspectedBot->GetBotItem(EQEmu::legacy::SlotAmmo); @@ -7214,11 +7215,11 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { if(inst) { item = inst->GetItem(); if(item) { - strcpy(insr->itemnames[SoF::inventory::SlotAmmo], item->Name); - insr->itemicons[SoF::inventory::SlotAmmo] = item->Icon; + strcpy(insr->itemnames[SoF::invslot::PossessionsAmmo], item->Name); + insr->itemicons[SoF::invslot::PossessionsAmmo] = item->Icon; } else - insr->itemicons[SoF::inventory::SlotAmmo] = 0xFFFFFFFF; + insr->itemicons[SoF::invslot::PossessionsAmmo] = 0xFFFFFFFF; } strcpy(insr->text, inspectedBot->GetInspectMessage().text); @@ -7527,7 +7528,7 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, } } - if (item->SkillModValue != 0 && item->SkillModType <= HIGHEST_SKILL){ + if (item->SkillModValue != 0 && item->SkillModType <= EQEmu::skills::HIGHEST_SKILL){ if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) || (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) { @@ -7535,7 +7536,7 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, } } - if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= HIGHEST_SKILL) { + if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= EQEmu::skills::HIGHEST_SKILL) { if((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); else @@ -7598,7 +7599,7 @@ void Bot::CalcBotStats(bool showtext) { // Test Code if(GetClass() == BARD) GetBotOwner()->Message(15, "Bard Skills-- Brass: %i, Percussion: %i, Singing: %i, Stringed: %i, Wind: %i", - GetSkill(SkillBrassInstruments), GetSkill(SkillPercussionInstruments), GetSkill(SkillSinging), GetSkill(SkillStringedInstruments), GetSkill(SkillWindInstruments)); + GetSkill(EQEmu::skills::SkillBrassInstruments), GetSkill(EQEmu::skills::SkillPercussionInstruments), GetSkill(EQEmu::skills::SkillSinging), GetSkill(EQEmu::skills::SkillStringedInstruments), GetSkill(EQEmu::skills::SkillWindInstruments)); } /*if(this->Save()) @@ -7617,11 +7618,11 @@ void Bot::CalcBotStats(bool showtext) { // Test Code if(GetClass() == BARD) { GetBotOwner()->Message(15, "Bard Skills-- Brass: %i, Percussion: %i, Singing: %i, Stringed: %i, Wind: %i", - GetSkill(SkillBrassInstruments) + GetBrassMod(), - GetSkill(SkillPercussionInstruments) + GetPercMod(), - GetSkill(SkillSinging) + GetSingMod(), - GetSkill(SkillStringedInstruments) + GetStringMod(), - GetSkill(SkillWindInstruments) + GetWindMod()); + GetSkill(EQEmu::skills::SkillBrassInstruments) + GetBrassMod(), + GetSkill(EQEmu::skills::SkillPercussionInstruments) + GetPercMod(), + GetSkill(EQEmu::skills::SkillSinging) + GetSingMod(), + GetSkill(EQEmu::skills::SkillStringedInstruments) + GetStringMod(), + GetSkill(EQEmu::skills::SkillWindInstruments) + GetWindMod()); GetBotOwner()->Message(15, "Bard Skill Mods-- Brass: %i, Percussion: %i, Singing: %i, Stringed: %i, Wind: %i", GetBrassMod(), GetPercMod(), GetSingMod(), GetStringMod(), GetWindMod()); } } diff --git a/zone/bot.h b/zone/bot.h index b04481bd1..da42147a2 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -205,8 +205,8 @@ public: Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData); //abstract virtual function implementations requird by base abstract class - virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); + virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } @@ -239,23 +239,23 @@ public: uint16 BotGetSpellPriority(int spellslot) { return AIspells[spellslot].priority; } virtual float GetProcChances(float ProcBonus, uint16 hand); virtual int GetHandToHandDamage(void); - virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse); + virtual bool TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse); virtual void DoRiposte(Mob* defender); - inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(SkillOffense)) * 9 / 10); } + inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQEmu::skills::SkillOffense)) * 9 / 10); } inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } uint32 GetTotalATK(); uint32 GetATKRating(); uint16 GetPrimarySkillValue(); - uint16 MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const; - inline uint16 MaxSkill(SkillUseTypes skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); } - virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false); + uint16 MaxSkill(EQEmu::skills::SkillType skillid, uint16 class_, uint16 level) const; + inline uint16 MaxSkill(EQEmu::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); } + virtual void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance = false); virtual void TryBackstab(Mob *other,int ReuseTime = 10); virtual void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10); virtual void RogueAssassinate(Mob* other); virtual void DoClassAttacks(Mob *target, bool IsRiposte=false); - virtual bool TryHeadShot(Mob* defender, SkillUseTypes skillInUse); - virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime =0); - virtual void ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg); + virtual bool TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse); + virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0); + virtual void ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int32 &mindmg); bool CanDoSpecialAttack(Mob *other); virtual int32 CheckAggroAmount(uint16 spellid); virtual void CalcBonuses(); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 92fd8cf44..2884ec838 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -54,6 +54,7 @@ #include "../common/rulesys.h" #include "../common/serverinfo.h" #include "../common/string_util.h" +#include "../common/say_link.h" #include "../common/eqemu_logsys.h" @@ -335,11 +336,11 @@ public: while (spells[spell_id].typedescnum == 27) { if (!spells[spell_id].goodEffect) break; - if (spells[spell_id].skill != SkillOffense && spells[spell_id].skill != SkillDefense) + if (spells[spell_id].skill != EQEmu::skills::SkillOffense && spells[spell_id].skill != EQEmu::skills::SkillDefense) break; entry_prototype = new STStanceEntry(); - if (spells[spell_id].skill == SkillOffense) + if (spells[spell_id].skill == EQEmu::skills::SkillOffense) entry_prototype->SafeCastToStance()->stance_type = BCEnum::StT_Aggressive; else entry_prototype->SafeCastToStance()->stance_type = BCEnum::StT_Defensive; @@ -2388,7 +2389,7 @@ namespace ActionableBots sbl.remove_if([bot_owner](Bot* l) { return (!l->IsBotArcher()); }); } - static void Filter_ByHighestSkill(Client* bot_owner, std::list& sbl, SkillUseTypes skill_type, float& skill_value) { + static void Filter_ByHighestSkill(Client* bot_owner, std::list& sbl, EQEmu::skills::SkillType skill_type, float& skill_value) { sbl.remove_if([bot_owner](Bot* l) { return (!MyBots::IsMyBot(bot_owner, l)); }); skill_value = 0.0f; @@ -2425,7 +2426,7 @@ namespace ActionableBots sbl.remove_if([bot_owner](const Bot* l) { return (l->GetClass() == ROGUE && l->GetLevel() < 5); }); sbl.remove_if([bot_owner](const Bot* l) { return (l->GetClass() == BARD && l->GetLevel() < 40); }); - ActionableBots::Filter_ByHighestSkill(bot_owner, sbl, SkillPickLock, pick_lock_value); + ActionableBots::Filter_ByHighestSkill(bot_owner, sbl, EQEmu::skills::SkillPickLock, pick_lock_value); } }; @@ -3906,7 +3907,7 @@ void bot_command_taunt(Client *c, const Seperator *sep) int taunting_count = 0; for (auto bot_iter : sbl) { - if (!bot_iter->GetSkill(SkillTaunt)) + if (!bot_iter->GetSkill(EQEmu::skills::SkillTaunt)) continue; if (toggle_taunt) diff --git a/zone/client.cpp b/zone/client.cpp index 38e5d7c7e..4027bb6e1 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1433,8 +1433,8 @@ bool Client::UpdateLDoNPoints(int32 points, uint32 theme) return(false); } -void Client::SetSkill(SkillUseTypes skillid, uint16 value) { - if (skillid > HIGHEST_SKILL) +void Client::SetSkill(EQEmu::skills::SkillType skillid, uint16 value) { + if (skillid > EQEmu::skills::HIGHEST_SKILL) return; m_pp.skills[skillid] = value; // We need to be able to #setskill 254 and 255 to reset skills @@ -1470,8 +1470,8 @@ void Client::IncreaseLanguageSkill(int skill_id, int value) { Message_StringID( MT_Skills, LANG_SKILL_IMPROVED ); //Notify client } -void Client::AddSkill(SkillUseTypes skillid, uint16 value) { - if (skillid > HIGHEST_SKILL) +void Client::AddSkill(EQEmu::skills::SkillType skillid, uint16 value) { + if (skillid > EQEmu::skills::HIGHEST_SKILL) return; value = GetRawSkill(skillid) + value; uint16 max = GetMaxSkillAfterSpecializationRules(skillid, MaxSkill(skillid)); @@ -2289,12 +2289,12 @@ uint64 Client::GetAllMoney() { (static_cast(m_pp.platinum_shared) * 1000))))); } -bool Client::CheckIncreaseSkill(SkillUseTypes skillid, Mob *against_who, int chancemodi) { +bool Client::CheckIncreaseSkill(EQEmu::skills::SkillType skillid, Mob *against_who, int chancemodi) { if (IsDead() || IsUnconscious()) return false; if (IsAIControlled()) // no skillups while chamred =p return false; - if (skillid > HIGHEST_SKILL) + if (skillid > EQEmu::skills::HIGHEST_SKILL) return false; int skillval = GetRawSkill(skillid); int maxskill = GetMaxSkillAfterSpecializationRules(skillid, MaxSkill(skillid)); @@ -2359,34 +2359,34 @@ void Client::CheckLanguageSkillIncrease(uint8 langid, uint8 TeacherSkill) { } } -bool Client::HasSkill(SkillUseTypes skill_id) const { +bool Client::HasSkill(EQEmu::skills::SkillType skill_id) const { return((GetSkill(skill_id) > 0) && CanHaveSkill(skill_id)); } -bool Client::CanHaveSkill(SkillUseTypes skill_id) const { - if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2 && class_ == BERSERKER && skill_id == Skill1HPiercing) - skill_id = Skill2HPiercing; +bool Client::CanHaveSkill(EQEmu::skills::SkillType skill_id) const { + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2 && class_ == BERSERKER && skill_id == EQEmu::skills::Skill1HPiercing) + skill_id = EQEmu::skills::Skill2HPiercing; return(database.GetSkillCap(GetClass(), skill_id, RuleI(Character, MaxLevel)) > 0); //if you don't have it by max level, then odds are you never will? } -uint16 Client::MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const { - if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2 && class_ == BERSERKER && skillid == Skill1HPiercing) - skillid = Skill2HPiercing; +uint16 Client::MaxSkill(EQEmu::skills::SkillType skillid, uint16 class_, uint16 level) const { + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2 && class_ == BERSERKER && skillid == EQEmu::skills::Skill1HPiercing) + skillid = EQEmu::skills::Skill2HPiercing; return(database.GetSkillCap(class_, skillid, level)); } -uint8 Client::SkillTrainLevel(SkillUseTypes skillid, uint16 class_) +uint8 Client::SkillTrainLevel(EQEmu::skills::SkillType skillid, uint16 class_) { - if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2 && class_ == BERSERKER && skillid == Skill1HPiercing) - skillid = Skill2HPiercing; + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2 && class_ == BERSERKER && skillid == EQEmu::skills::Skill1HPiercing) + skillid = EQEmu::skills::Skill2HPiercing; return(database.GetTrainLevel(class_, skillid, RuleI(Character, MaxLevel))); } -uint16 Client::GetMaxSkillAfterSpecializationRules(SkillUseTypes skillid, uint16 maxSkill) +uint16 Client::GetMaxSkillAfterSpecializationRules(EQEmu::skills::SkillType skillid, uint16 maxSkill) { uint16 Result = maxSkill; @@ -2396,13 +2396,13 @@ uint16 Client::GetMaxSkillAfterSpecializationRules(SkillUseTypes skillid, uint16 uint16 MaxSpecializations = GetAA(aaSecondaryForte) ? 2 : 1; - if(skillid >= SkillSpecializeAbjure && skillid <= SkillSpecializeEvocation) + if (skillid >= EQEmu::skills::SkillSpecializeAbjure && skillid <= EQEmu::skills::SkillSpecializeEvocation) { bool HasPrimarySpecSkill = false; int NumberOfPrimarySpecSkills = 0; - for(int i = SkillSpecializeAbjure; i <= SkillSpecializeEvocation; ++i) + for (int i = EQEmu::skills::SkillSpecializeAbjure; i <= EQEmu::skills::SkillSpecializeEvocation; ++i) { if(m_pp.skills[i] > 50) { @@ -2459,8 +2459,8 @@ uint16 Client::GetMaxSkillAfterSpecializationRules(SkillUseTypes skillid, uint16 Message(13, "Your spell casting specializations skills have been reset. " "Only %i primary specialization skill is allowed.", MaxSpecializations); - for(int i = SkillSpecializeAbjure; i <= SkillSpecializeEvocation; ++i) - SetSkill((SkillUseTypes)i, 1); + for (int i = EQEmu::skills::SkillSpecializeAbjure; i <= EQEmu::skills::SkillSpecializeEvocation; ++i) + SetSkill((EQEmu::skills::SkillType)i, 1); Save(); @@ -2643,14 +2643,14 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail) bind_out->type = 1; // Done QueuePacket(outapp); bind_out->type = 0; - CheckIncreaseSkill(SkillBindWound, nullptr, 5); + CheckIncreaseSkill(EQEmu::skills::SkillBindWound, nullptr, 5); int maxHPBonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound + aabonuses.MaxBindWound; int max_percent = 50 + 10 * maxHPBonus; - if (GetClass() == MONK && GetSkill(SkillBindWound) > 200) { + if (GetClass() == MONK && GetSkill(EQEmu::skills::SkillBindWound) > 200) { max_percent = 70 + 10 * maxHPBonus; } @@ -2663,10 +2663,11 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail) // 0.120 per skill point, 0.60 per skill level, minimum 3 max 30 int bindhps = 3; - if (GetSkill(SkillBindWound) > 200) { - bindhps += GetSkill(SkillBindWound) * 4 / 10; - } else if (GetSkill(SkillBindWound) >= 10) { - bindhps += GetSkill(SkillBindWound) / 4; + if (GetSkill(EQEmu::skills::SkillBindWound) > 200) { + bindhps += GetSkill(EQEmu::skills::SkillBindWound) * 4 / 10; + } + else if (GetSkill(EQEmu::skills::SkillBindWound) >= 10) { + bindhps += GetSkill(EQEmu::skills::SkillBindWound) / 4; } // Implementation of aaMithanielsBinding is a guess (the multiplier) @@ -3774,7 +3775,7 @@ void Client::SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu pick_out->coin = amt; pick_out->from = GetID(); pick_out->to = from->GetID(); - pick_out->myskill = GetSkill(SkillPickPockets); + pick_out->myskill = GetSkill(EQEmu::skills::SkillPickPockets); if ((type >= PickPocketPlatinum) && (type <= PickPocketCopper) && (amt == 0)) type = PickPocketFailed; @@ -4196,11 +4197,11 @@ bool Client::GroupFollow(Client* inviter) { uint16 Client::GetPrimarySkillValue() { - SkillUseTypes skill = HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill + EQEmu::skills::SkillType skill = EQEmu::skills::HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill bool equiped = m_inv.GetItem(EQEmu::legacy::SlotPrimary); if (!equiped) - skill = SkillHandtoHand; + skill = EQEmu::skills::SkillHandtoHand; else { @@ -4208,31 +4209,31 @@ uint16 Client::GetPrimarySkillValue() switch (type) { case EQEmu::item::ItemType1HSlash: // 1H Slashing - skill = Skill1HSlashing; + skill = EQEmu::skills::Skill1HSlashing; break; case EQEmu::item::ItemType2HSlash: // 2H Slashing - skill = Skill2HSlashing; + skill = EQEmu::skills::Skill2HSlashing; break; case EQEmu::item::ItemType1HPiercing: // Piercing - skill = Skill1HPiercing; + skill = EQEmu::skills::Skill1HPiercing; break; case EQEmu::item::ItemType1HBlunt: // 1H Blunt - skill = Skill1HBlunt; + skill = EQEmu::skills::Skill1HBlunt; break; case EQEmu::item::ItemType2HBlunt: // 2H Blunt - skill = Skill2HBlunt; + skill = EQEmu::skills::Skill2HBlunt; break; case EQEmu::item::ItemType2HPiercing: // 2H Piercing if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) - skill = Skill1HPiercing; + skill = EQEmu::skills::Skill1HPiercing; else - skill = Skill2HPiercing; + skill = EQEmu::skills::Skill2HPiercing; break; case EQEmu::item::ItemTypeMartial: // Hand to Hand - skill = SkillHandtoHand; + skill = EQEmu::skills::SkillHandtoHand; break; default: // All other types default to Hand to Hand - skill = SkillHandtoHand; + skill = EQEmu::skills::SkillHandtoHand; break; } } @@ -4246,7 +4247,7 @@ uint32 Client::GetTotalATK() uint32 WornCap = itembonuses.ATK; if(IsClient()) { - AttackRating = ((WornCap * 1.342) + (GetSkill(SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69)); + AttackRating = ((WornCap * 1.342) + (GetSkill(EQEmu::skills::SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69)); AttackRating += aabonuses.ATK + GroupLeadershipAAOffenseEnhancement(); if (AttackRating < 10) @@ -4264,7 +4265,7 @@ uint32 Client::GetATKRating() { uint32 AttackRating = 0; if(IsClient()) { - AttackRating = (GetSkill(SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69); + AttackRating = (GetSkill(EQEmu::skills::SkillOffense) * 1.345) + ((GetSTR() - 66) * 0.9) + (GetPrimarySkillValue() * 2.69); if (AttackRating < 10) AttackRating = 10; @@ -4639,7 +4640,7 @@ void Client::HandleLDoNOpen(NPC *target) AddEXP(target->GetLevel()*target->GetLevel()*2625/10, GetLevelCon(target->GetLevel())); } } - target->Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); + target->Death(this, 0, SPELL_UNKNOWN, EQEmu::skills::SkillHandtoHand); } } } @@ -4952,14 +4953,14 @@ void Client::ShowSkillsWindow() { const char *WindowTitle = "Skills"; std::string WindowText; - std::map Skills = EQEmu::GetSkillUseTypesMap(); + std::map Skills = EQEmu::skills::GetSkillTypeMap(); if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2) - Skills[Skill1HPiercing] = "Piercing"; + Skills[EQEmu::skills::Skill1HPiercing] = "Piercing"; // print out all available skills for (auto skills_iter : Skills) { - if (skills_iter.first == Skill2HPiercing && ClientVersion() < EQEmu::versions::ClientVersion::RoF2) + if (skills_iter.first == EQEmu::skills::Skill2HPiercing && ClientVersion() < EQEmu::versions::ClientVersion::RoF2) continue; if (!GetSkill(skills_iter.first) && !MaxSkill(skills_iter.first)) continue; @@ -5721,11 +5722,11 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { if(item) { // we shouldn't do this..but, that's the way it's coded atm... // (this type of action should be handled exclusively in the client translator) - strcpy(insr->itemnames[SoF::inventory::SlotPowerSource], item->Name); - insr->itemicons[SoF::inventory::SlotPowerSource] = item->Icon; + strcpy(insr->itemnames[SoF::invslot::PossessionsPowerSource], item->Name); + insr->itemicons[SoF::invslot::PossessionsPowerSource] = item->Icon; } else - insr->itemicons[SoF::inventory::SlotPowerSource] = 0xFFFFFFFF; + insr->itemicons[SoF::invslot::PossessionsPowerSource] = 0xFFFFFFFF; } inst = requestee->GetInv().GetItem(EQEmu::legacy::SlotAmmo); @@ -5733,11 +5734,11 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { if(inst) { item = inst->GetItem(); if(item) { - strcpy(insr->itemnames[SoF::inventory::SlotAmmo], item->Name); - insr->itemicons[SoF::inventory::SlotAmmo] = item->Icon; + strcpy(insr->itemnames[SoF::invslot::PossessionsAmmo], item->Name); + insr->itemicons[SoF::invslot::PossessionsAmmo] = item->Icon; } else - insr->itemicons[SoF::inventory::SlotAmmo] = 0xFFFFFFFF; + insr->itemicons[SoF::invslot::PossessionsAmmo] = 0xFFFFFFFF; } strcpy(insr->text, requestee->GetInspectMessage().text); @@ -6750,7 +6751,7 @@ void Client::SendStatsWindow(Client* client, bool use_window) }; std::string skill_mods = ""; - for(int j = 0; j <= HIGHEST_SKILL; j++) { + for (int j = 0; j <= EQEmu::skills::HIGHEST_SKILL; j++) { if(itembonuses.skillmod[j] > 0) skill_mods += indP + skill_list[j] + " : +" + itoa(itembonuses.skillmod[j]) + "%
"; else if(itembonuses.skillmod[j] < 0) @@ -6758,7 +6759,7 @@ void Client::SendStatsWindow(Client* client, bool use_window) } std::string skill_dmgs = ""; - for(int j = 0; j <= HIGHEST_SKILL; j++) { + for (int j = 0; j <= EQEmu::skills::HIGHEST_SKILL; j++) { if((itembonuses.SkillDamageAmount[j] + spellbonuses.SkillDamageAmount[j]) > 0) skill_dmgs += indP + skill_list[j] + " : +" + itoa(itembonuses.SkillDamageAmount[j] + spellbonuses.SkillDamageAmount[j]) + "
"; else if((itembonuses.SkillDamageAmount[j] + spellbonuses.SkillDamageAmount[j]) < 0) diff --git a/zone/client.h b/zone/client.h index 28da7ee72..ca26c8fcb 100644 --- a/zone/client.h +++ b/zone/client.h @@ -220,8 +220,8 @@ public: ~Client(); //abstract virtual function implementations required by base abstract class - virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); + virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } @@ -306,7 +306,7 @@ public: void VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber); void SendSound(); void LearnRecipe(uint32 recipeID); - bool CanIncreaseTradeskill(SkillUseTypes tradeskill); + bool CanIncreaseTradeskill(EQEmu::skills::SkillType tradeskill); EQApplicationPacket* ReturnItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType packet_type); @@ -418,7 +418,7 @@ public: virtual void CalcBonuses(); //these are all precalculated now inline virtual int32 GetAC() const { return AC; } - inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(SkillOffense)) * 9 / 10); } + inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQEmu::skills::SkillOffense)) * 9 / 10); } inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } inline virtual int GetHaste() const { return Haste; } int GetRawACNoShield(int &shield_ac) const; @@ -682,31 +682,31 @@ public: uint16 GetSkillPoints() { return m_pp.points;} void SetSkillPoints(int inp) { m_pp.points = inp;} - void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= HIGHEST_SKILL) { m_pp.skills[skill_id] += value; } } + void IncreaseSkill(int skill_id, int value = 1) { if (skill_id <= EQEmu::skills::HIGHEST_SKILL) { m_pp.skills[skill_id] += value; } } void IncreaseLanguageSkill(int skill_id, int value = 1); - virtual uint16 GetSkill(SkillUseTypes skill_id) const {if (skill_id <= HIGHEST_SKILL) {return(itembonuses.skillmod[skill_id] > 0 ? (itembonuses.skillmodmax[skill_id] > 0 ? std::min(m_pp.skills[skill_id] + itembonuses.skillmodmax[skill_id], m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100) : m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100) : m_pp.skills[skill_id]);} return 0;} - uint32 GetRawSkill(SkillUseTypes skill_id) const { if (skill_id <= HIGHEST_SKILL) { return(m_pp.skills[skill_id]); } return 0; } - bool HasSkill(SkillUseTypes skill_id) const; - bool CanHaveSkill(SkillUseTypes skill_id) const; - void SetSkill(SkillUseTypes skill_num, uint16 value); - void AddSkill(SkillUseTypes skillid, uint16 value); + virtual uint16 GetSkill(EQEmu::skills::SkillType skill_id) const { if (skill_id <= EQEmu::skills::HIGHEST_SKILL) { return(itembonuses.skillmod[skill_id] > 0 ? (itembonuses.skillmodmax[skill_id] > 0 ? std::min(m_pp.skills[skill_id] + itembonuses.skillmodmax[skill_id], m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100) : m_pp.skills[skill_id] * (100 + itembonuses.skillmod[skill_id]) / 100) : m_pp.skills[skill_id]); } return 0; } + uint32 GetRawSkill(EQEmu::skills::SkillType skill_id) const { if (skill_id <= EQEmu::skills::HIGHEST_SKILL) { return(m_pp.skills[skill_id]); } return 0; } + bool HasSkill(EQEmu::skills::SkillType skill_id) const; + bool CanHaveSkill(EQEmu::skills::SkillType skill_id) const; + void SetSkill(EQEmu::skills::SkillType skill_num, uint16 value); + void AddSkill(EQEmu::skills::SkillType skillid, uint16 value); void CheckSpecializeIncrease(uint16 spell_id); void CheckSongSkillIncrease(uint16 spell_id); - bool CheckIncreaseSkill(SkillUseTypes skillid, Mob *against_who, int chancemodi = 0); + bool CheckIncreaseSkill(EQEmu::skills::SkillType skillid, Mob *against_who, int chancemodi = 0); void CheckLanguageSkillIncrease(uint8 langid, uint8 TeacherSkill); void SetLanguageSkill(int langid, int value); void SetHoTT(uint32 mobid); void ShowSkillsWindow(); void SendStatsWindow(Client* client, bool use_window); - uint16 MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const; - inline uint16 MaxSkill(SkillUseTypes skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); } - uint8 SkillTrainLevel(SkillUseTypes skillid, uint16 class_); + uint16 MaxSkill(EQEmu::skills::SkillType skillid, uint16 class_, uint16 level) const; + inline uint16 MaxSkill(EQEmu::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); } + uint8 SkillTrainLevel(EQEmu::skills::SkillType skillid, uint16 class_); void TradeskillSearchResults(const std::string &query, unsigned long objtype, unsigned long someid); void SendTradeskillDetails(uint32 recipe_id); bool TradeskillExecute(DBTradeskillRecipe_Struct *spec); - void CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float skillup_modifier, uint16 success_modifier, SkillUseTypes tradeskill); + void CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float skillup_modifier, uint16 success_modifier, EQEmu::skills::SkillType tradeskill); void GMKill(); inline bool IsMedding() const {return medding;} @@ -928,7 +928,7 @@ public: int GetNextAvailableSpellBookSlot(int starting_slot = 0); inline uint32 GetSpellByBookSlot(int book_slot) { return m_pp.spell_book[book_slot]; } inline bool HasSpellScribed(int spellid) { return (FindSpellBookSlotBySpellID(spellid) != -1 ? true : false); } - uint16 GetMaxSkillAfterSpecializationRules(SkillUseTypes skillid, uint16 maxSkill); + uint16 GetMaxSkillAfterSpecializationRules(EQEmu::skills::SkillType skillid, uint16 maxSkill); void SendPopupToClient(const char *Title, const char *Text, uint32 PopupID = 0, uint32 Buttons = 0, uint32 Duration = 0); void SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 Duration, int title_type, Client* target, const char *Title, const char *Text, ...); bool PendingTranslocate; @@ -1176,13 +1176,14 @@ public: int32 GetActCHA() { return( std::min(GetMaxCHA(), GetCHA()) ); } void LoadAccountFlags(); void SetAccountFlag(std::string flag, std::string val); - std::string GetAccountFlag(std::string flag); float GetDamageMultiplier(SkillUseTypes); + std::string GetAccountFlag(std::string flag); + float GetDamageMultiplier(EQEmu::skills::SkillType how_long_has_this_been_missing); void Consume(const EQEmu::Item_Struct *item, uint8 type, int16 slot, bool auto_consume); void PlayMP3(const char* fname); void ExpeditionSay(const char *str, int ExpID); - int mod_client_damage(int damage, SkillUseTypes skillinuse, int hand, const ItemInst* weapon, Mob* other); + int mod_client_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const ItemInst* weapon, Mob* other); bool mod_client_message(char* message, uint8 chan_num); - bool mod_can_increase_skill(SkillUseTypes skillid, Mob* against_who); + bool mod_can_increase_skill(EQEmu::skills::SkillType skillid, Mob* against_who); int16 mod_increase_skill_chance(int16 chance, Mob* against_who); int mod_bindwound_percent(int max_percent, Mob* bindmob); int mod_bindwound_hp(int bindhps, Mob* bindmob); diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index c6860a52f..1311f7b53 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1032,7 +1032,7 @@ int32 Client::acmod() int32 Client::CalcAC() { // new formula - int avoidance = (acmod() + ((GetSkill(SkillDefense) + itembonuses.HeroicAGI / 10) * 16) / 9); + int avoidance = (acmod() + ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) * 16) / 9); if (avoidance < 0) { avoidance = 0; } @@ -1040,13 +1040,13 @@ int32 Client::CalcAC() if (m_pp.class_ == WIZARD || m_pp.class_ == MAGICIAN || m_pp.class_ == NECROMANCER || m_pp.class_ == ENCHANTER) { //something is wrong with this, naked casters have the wrong natural AC // mitigation = (spellbonuses.AC/3) + (GetSkill(DEFENSE)/2) + (itembonuses.AC+1); - mitigation = (GetSkill(SkillDefense) + itembonuses.HeroicAGI / 10) / 4 + (itembonuses.AC + 1); + mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 4 + (itembonuses.AC + 1); //this might be off by 4.. mitigation -= 4; } else { // mitigation = (spellbonuses.AC/4) + (GetSkill(DEFENSE)/3) + ((itembonuses.AC*4)/3); - mitigation = (GetSkill(SkillDefense) + itembonuses.HeroicAGI / 10) / 3 + ((itembonuses.AC * 4) / 3); + mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 3 + ((itembonuses.AC * 4) / 3); if (m_pp.class_ == MONK) { mitigation += GetLevel() * 13 / 10; //the 13/10 might be wrong, but it is close... } @@ -1085,11 +1085,11 @@ int32 Client::GetACMit() { int mitigation = 0; if (m_pp.class_ == WIZARD || m_pp.class_ == MAGICIAN || m_pp.class_ == NECROMANCER || m_pp.class_ == ENCHANTER) { - mitigation = (GetSkill(SkillDefense) + itembonuses.HeroicAGI / 10) / 4 + (itembonuses.AC + 1); + mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 4 + (itembonuses.AC + 1); mitigation -= 4; } else { - mitigation = (GetSkill(SkillDefense) + itembonuses.HeroicAGI / 10) / 3 + ((itembonuses.AC * 4) / 3); + mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 3 + ((itembonuses.AC * 4) / 3); if (m_pp.class_ == MONK) { mitigation += GetLevel() * 13 / 10; //the 13/10 might be wrong, but it is close... } @@ -1109,7 +1109,7 @@ int32 Client::GetACMit() int32 Client::GetACAvoid() { - int32 avoidance = (acmod() + ((GetSkill(SkillDefense) + itembonuses.HeroicAGI / 10) * 16) / 9); + int32 avoidance = (acmod() + ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) * 16) / 9); if (avoidance < 0) { avoidance = 0; } @@ -1247,8 +1247,8 @@ int32 Client::CalcBaseManaRegen() uint8 clevel = GetLevel(); int32 regen = 0; if (IsSitting() || (GetHorseId() != 0)) { - if (HasSkill(SkillMeditate)) { - regen = (((GetSkill(SkillMeditate) / 10) + (clevel - (clevel / 4))) / 4) + 4; + if (HasSkill(EQEmu::skills::SkillMeditate)) { + regen = (((GetSkill(EQEmu::skills::SkillMeditate) / 10) + (clevel - (clevel / 4))) / 4) + 4; } else { regen = 2; @@ -1267,11 +1267,11 @@ int32 Client::CalcManaRegen() //this should be changed so we dont med while camping, etc... if (IsSitting() || (GetHorseId() != 0)) { BuffFadeBySitModifier(); - if (HasSkill(SkillMeditate)) { + if (HasSkill(EQEmu::skills::SkillMeditate)) { this->medding = true; - regen = (((GetSkill(SkillMeditate) / 10) + (clevel - (clevel / 4))) / 4) + 4; + regen = (((GetSkill(EQEmu::skills::SkillMeditate) / 10) + (clevel - (clevel / 4))) / 4) + 4; regen += spellbonuses.ManaRegen + itembonuses.ManaRegen; - CheckIncreaseSkill(SkillMeditate, nullptr, -5); + CheckIncreaseSkill(EQEmu::skills::SkillMeditate, nullptr, -5); } else { regen = 2 + spellbonuses.ManaRegen + itembonuses.ManaRegen; @@ -1355,7 +1355,7 @@ uint32 Client::CalcCurrentWeight() This is the ONLY instance I have seen where the client is hard coded to particular Item IDs to set a certain property for an item. It is very odd. */ // SoD+ client has no weight for coin - if (EQEmu::limits::CoinHasWeight(EQEmu::versions::ConvertClientVersionToInventoryVersion(ClientVersion()))) { + if (EQEmu::profile::CoinHasWeight(EQEmu::versions::ConvertClientVersionToInventoryVersion(ClientVersion()))) { Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4; } float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat; @@ -2046,10 +2046,10 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const // clickies (Symphony of Battle) that have a song skill don't get AA bonus for some reason // but clickies that are songs (selo's on Composers Greaves) do get AA mod as well switch (spells[spell_id].skill) { - case SkillPercussionInstruments: + case EQEmu::skills::SkillPercussionInstruments: if (itembonuses.percussionMod == 0 && spellbonuses.percussionMod == 0) effectmod = 10; - else if (GetSkill(SkillPercussionInstruments) == 0) + else if (GetSkill(EQEmu::skills::SkillPercussionInstruments) == 0) effectmod = 10; else if (itembonuses.percussionMod > spellbonuses.percussionMod) effectmod = itembonuses.percussionMod; @@ -2058,10 +2058,10 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const if (IsBardSong(spell_id)) effectmod += aabonuses.percussionMod; break; - case SkillStringedInstruments: + case EQEmu::skills::SkillStringedInstruments: if (itembonuses.stringedMod == 0 && spellbonuses.stringedMod == 0) effectmod = 10; - else if (GetSkill(SkillStringedInstruments) == 0) + else if (GetSkill(EQEmu::skills::SkillStringedInstruments) == 0) effectmod = 10; else if (itembonuses.stringedMod > spellbonuses.stringedMod) effectmod = itembonuses.stringedMod; @@ -2070,10 +2070,10 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const if (IsBardSong(spell_id)) effectmod += aabonuses.stringedMod; break; - case SkillWindInstruments: + case EQEmu::skills::SkillWindInstruments: if (itembonuses.windMod == 0 && spellbonuses.windMod == 0) effectmod = 10; - else if (GetSkill(SkillWindInstruments) == 0) + else if (GetSkill(EQEmu::skills::SkillWindInstruments) == 0) effectmod = 10; else if (itembonuses.windMod > spellbonuses.windMod) effectmod = itembonuses.windMod; @@ -2082,10 +2082,10 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const if (IsBardSong(spell_id)) effectmod += aabonuses.windMod; break; - case SkillBrassInstruments: + case EQEmu::skills::SkillBrassInstruments: if (itembonuses.brassMod == 0 && spellbonuses.brassMod == 0) effectmod = 10; - else if (GetSkill(SkillBrassInstruments) == 0) + else if (GetSkill(EQEmu::skills::SkillBrassInstruments) == 0) effectmod = 10; else if (itembonuses.brassMod > spellbonuses.brassMod) effectmod = itembonuses.brassMod; @@ -2094,7 +2094,7 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const if (IsBardSong(spell_id)) effectmod += aabonuses.brassMod; break; - case SkillSinging: + case EQEmu::skills::SkillSinging: if (itembonuses.singingMod == 0 && spellbonuses.singingMod == 0) effectmod = 10; else if (itembonuses.singingMod > spellbonuses.singingMod) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 9712e031a..ac4466aab 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2830,10 +2830,10 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app) { if ((PrimaryWeapon && PrimaryWeapon->GetItem()->ItemType == EQEmu::item::ItemType1HPiercing) || (SecondaryWeapon && SecondaryWeapon->GetItem()->ItemType == EQEmu::item::ItemType1HPiercing)) { - float SuccessChance = (GetSkill(SkillApplyPoison) + GetLevel()) / 400.0f; + float SuccessChance = (GetSkill(EQEmu::skills::SkillApplyPoison) + GetLevel()) / 400.0f; double ChanceRoll = zone->random.Real(0, 1); - CheckIncreaseSkill(SkillApplyPoison, nullptr, 10); + CheckIncreaseSkill(EQEmu::skills::SkillApplyPoison, nullptr, 10); if (ChanceRoll < SuccessChance) { ApplyPoisonSuccessResult = 1; @@ -3630,7 +3630,7 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app) return; } - if (!HasSkill(SkillBegging) || !GetTarget()) + if (!HasSkill(EQEmu::skills::SkillBegging) || !GetTarget()) return; if (GetTarget()->GetClass() == LDON_TREASURE) @@ -3668,7 +3668,7 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app) return; } - uint16 CurrentSkill = GetSkill(SkillBegging); + uint16 CurrentSkill = GetSkill(EQEmu::skills::SkillBegging); float ChanceToBeg = ((float)(CurrentSkill / 700.0f) + 0.15f) * 100; @@ -3690,7 +3690,7 @@ void Client::Handle_OP_Begging(const EQApplicationPacket *app) } QueuePacket(outapp); safe_delete(outapp); - CheckIncreaseSkill(SkillBegging, nullptr, -10); + CheckIncreaseSkill(EQEmu::skills::SkillBegging, nullptr, -10); } void Client::Handle_OP_Bind_Wound(const EQApplicationPacket *app) @@ -4526,7 +4526,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) if(IsTracking() && ((m_Position.x!=ppu->x_pos) || (m_Position.y!=ppu->y_pos))){ if(zone->random.Real(0, 100) < 70)//should be good - CheckIncreaseSkill(SkillTracking, nullptr, -20); + CheckIncreaseSkill(EQEmu::skills::SkillTracking, nullptr, -20); } // Break Hide if moving without sneaking and set rewind timer if moved @@ -4581,7 +4581,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) } if(zone->watermap && zone->watermap->InLiquid(glm::vec3(m_Position))) - CheckIncreaseSkill(SkillSwimming, nullptr, -17); + CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17); return; } @@ -5070,7 +5070,7 @@ void Client::Handle_OP_Death(const EQApplicationPacket *app) Death_Struct* ds = (Death_Struct*)app->pBuffer; //I think this attack_skill value is really a value from SkillDamageTypes... - if (ds->attack_skill > HIGHEST_SKILL) { + if (ds->attack_skill > EQEmu::skills::HIGHEST_SKILL) { return; } @@ -5078,7 +5078,7 @@ void Client::Handle_OP_Death(const EQApplicationPacket *app) return; Mob* killer = entity_list.GetMob(ds->killer_id); - Death(killer, ds->damage, ds->spell_id, (SkillUseTypes)ds->attack_skill); + Death(killer, ds->damage, ds->spell_id, (EQEmu::skills::SkillType)ds->attack_skill); return; } @@ -5139,9 +5139,9 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app) const ItemInst *inst = GetInv().GetItem(alc->from_slot); if (inst && inst->GetItem()->ItemType == EQEmu::item::ItemTypeAlcohol) { entity_list.MessageClose_StringID(this, true, 50, 0, DRINKING_MESSAGE, GetName(), inst->GetItem()->Name); - CheckIncreaseSkill(SkillAlcoholTolerance, nullptr, 25); + CheckIncreaseSkill(EQEmu::skills::SkillAlcoholTolerance, nullptr, 25); - int16 AlcoholTolerance = GetSkill(SkillAlcoholTolerance); + int16 AlcoholTolerance = GetSkill(EQEmu::skills::SkillAlcoholTolerance); int16 IntoxicationIncrease; if (ClientVersion() < EQEmu::versions::ClientVersion::SoD) @@ -5209,7 +5209,7 @@ void Client::Handle_OP_DeleteSpell(const EQApplicationPacket *app) void Client::Handle_OP_DisarmTraps(const EQApplicationPacket *app) { - if (!HasSkill(SkillDisarmTraps)) + if (!HasSkill(EQEmu::skills::SkillDisarmTraps)) return; if (!p_timers.Expired(&database, pTimerDisarmTraps, false)) { @@ -5217,7 +5217,7 @@ void Client::Handle_OP_DisarmTraps(const EQApplicationPacket *app) return; } - int reuse = DisarmTrapsReuseTime - GetSkillReuseTime(SkillDisarmTraps); + int reuse = DisarmTrapsReuseTime - GetSkillReuseTime(EQEmu::skills::SkillDisarmTraps); if (reuse < 1) reuse = 1; @@ -5227,7 +5227,7 @@ void Client::Handle_OP_DisarmTraps(const EQApplicationPacket *app) Trap* trap = entity_list.FindNearbyTrap(this, 60); if (trap && trap->detected) { - int uskill = GetSkill(SkillDisarmTraps); + int uskill = GetSkill(EQEmu::skills::SkillDisarmTraps); if ((zone->random.Int(0, 49) + uskill) >= (zone->random.Int(0, 49) + trap->skill)) { Message(MT_Skills, "You disarm a trap."); @@ -5245,7 +5245,7 @@ void Client::Handle_OP_DisarmTraps(const EQApplicationPacket *app) Message(MT_Skills, "You failed to disarm a trap."); } } - CheckIncreaseSkill(SkillDisarmTraps, nullptr); + CheckIncreaseSkill(EQEmu::skills::SkillDisarmTraps, nullptr); return; } Message(MT_Skills, "You did not find any traps close enough to disarm."); @@ -5527,7 +5527,7 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app) if (GetHP() <= 0) { mod_client_death_env(); - Death(0, 32000, SPELL_UNKNOWN, SkillHandtoHand); + Death(0, 32000, SPELL_UNKNOWN, EQEmu::skills::SkillHandtoHand); } SendHPUpdate(); return; @@ -5571,7 +5571,7 @@ void Client::Handle_OP_FeignDeath(const EQApplicationPacket *app) } int reuse = FeignDeathReuseTime; - reuse -= GetSkillReuseTime(SkillFeignDeath); + reuse -= GetSkillReuseTime(EQEmu::skills::SkillFeignDeath); if (reuse < 1) reuse = 1; @@ -5580,8 +5580,8 @@ void Client::Handle_OP_FeignDeath(const EQApplicationPacket *app) //BreakInvis(); - uint16 primfeign = GetSkill(SkillFeignDeath); - uint16 secfeign = GetSkill(SkillFeignDeath); + uint16 primfeign = GetSkill(EQEmu::skills::SkillFeignDeath); + uint16 secfeign = GetSkill(EQEmu::skills::SkillFeignDeath); if (primfeign > 100) { primfeign = 100; secfeign = secfeign - 100; @@ -5599,7 +5599,7 @@ void Client::Handle_OP_FeignDeath(const EQApplicationPacket *app) SetFeigned(true); } - CheckIncreaseSkill(SkillFeignDeath, nullptr, 5); + CheckIncreaseSkill(EQEmu::skills::SkillFeignDeath, nullptr, 5); return; } @@ -7859,7 +7859,7 @@ void Client::Handle_OP_Heartbeat(const EQApplicationPacket *app) void Client::Handle_OP_Hide(const EQApplicationPacket *app) { - if (!HasSkill(SkillHide) && GetSkill(SkillHide) == 0) + if (!HasSkill(EQEmu::skills::SkillHide) && GetSkill(EQEmu::skills::SkillHide) == 0) { //Can not be able to train hide but still have it from racial though return; //You cannot hide if you do not have hide @@ -7869,16 +7869,16 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app) Message(13, "Ability recovery time not yet met."); return; } - int reuse = HideReuseTime - GetSkillReuseTime(SkillHide); + int reuse = HideReuseTime - GetSkillReuseTime(EQEmu::skills::SkillHide); if (reuse < 1) reuse = 1; p_timers.Start(pTimerHide, reuse - 1); - float hidechance = ((GetSkill(SkillHide) / 250.0f) + .25) * 100; + float hidechance = ((GetSkill(EQEmu::skills::SkillHide) / 250.0f) + .25) * 100; float random = zone->random.Real(0, 100); - CheckIncreaseSkill(SkillHide, nullptr, 5); + CheckIncreaseSkill(EQEmu::skills::SkillHide, nullptr, 5); if (random < hidechance) { auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; @@ -7901,7 +7901,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app) Mob *evadetar = GetTarget(); if (!auto_attack && (evadetar && evadetar->CheckAggro(this) && evadetar->IsNPC())) { - if (zone->random.Int(0, 260) < (int)GetSkill(SkillHide)) { + if (zone->random.Int(0, 260) < (int)GetSkill(EQEmu::skills::SkillHide)) { msg->string_id = EVADE_SUCCESS; RogueEvade(evadetar); } @@ -8023,10 +8023,10 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) if (item) { // another one..I did these, didn't I!!? - strcpy(insr->itemnames[SoF::inventory::SlotAmmo], item->Name); - insr->itemicons[SoF::inventory::SlotAmmo] = item->Icon; + strcpy(insr->itemnames[SoF::invslot::PossessionsAmmo], item->Name); + insr->itemicons[SoF::invslot::PossessionsAmmo] = item->Icon; } - else { insr->itemicons[SoF::inventory::SlotAmmo] = 0xFFFFFFFF; } + else { insr->itemicons[SoF::invslot::PossessionsAmmo] = 0xFFFFFFFF; } InspectMessage_Struct* newmessage = (InspectMessage_Struct*)insr->text; InspectMessage_Struct& playermessage = this->GetInspectMessage(); @@ -8689,14 +8689,14 @@ void Client::Handle_OP_LDoNDisarmTraps(const EQApplicationPacket *app) Mob * target = GetTarget(); if (target->IsNPC()) { - if (HasSkill(SkillDisarmTraps)) + if (HasSkill(EQEmu::skills::SkillDisarmTraps)) { if (DistanceSquaredNoZ(m_Position, target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) { Message(13, "%s is too far away.", target->GetCleanName()); return; } - HandleLDoNDisarm(target->CastToNPC(), GetSkill(SkillDisarmTraps), LDoNTypeMechanical); + HandleLDoNDisarm(target->CastToNPC(), GetSkill(EQEmu::skills::SkillDisarmTraps), LDoNTypeMechanical); } else Message(13, "You do not have the disarm trap skill."); @@ -8722,14 +8722,14 @@ void Client::Handle_OP_LDoNPickLock(const EQApplicationPacket *app) Mob * target = GetTarget(); if (target->IsNPC()) { - if (HasSkill(SkillPickLock)) + if (HasSkill(EQEmu::skills::SkillPickLock)) { if (DistanceSquaredNoZ(m_Position, target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) { Message(13, "%s is too far away.", target->GetCleanName()); return; } - HandleLDoNPickLock(target->CastToNPC(), GetSkill(SkillPickLock), LDoNTypeMechanical); + HandleLDoNPickLock(target->CastToNPC(), GetSkill(EQEmu::skills::SkillPickLock), LDoNTypeMechanical); } else Message(13, "You do not have the pick locks skill."); @@ -8741,14 +8741,14 @@ void Client::Handle_OP_LDoNSenseTraps(const EQApplicationPacket *app) Mob * target = GetTarget(); if (target->IsNPC()) { - if (HasSkill(SkillSenseTraps)) + if (HasSkill(EQEmu::skills::SkillSenseTraps)) { if (DistanceSquaredNoZ(m_Position, target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) { Message(13, "%s is too far away.", target->GetCleanName()); return; } - HandleLDoNSenseTraps(target->CastToNPC(), GetSkill(SkillSenseTraps), LDoNTypeMechanical); + HandleLDoNSenseTraps(target->CastToNPC(), GetSkill(EQEmu::skills::SkillSenseTraps), LDoNTypeMechanical); } else Message(13, "You do not have the sense traps skill."); @@ -9251,7 +9251,7 @@ void Client::Handle_OP_MemorizeSpell(const EQApplicationPacket *app) void Client::Handle_OP_Mend(const EQApplicationPacket *app) { - if (!HasSkill(SkillMend)) + if (!HasSkill(EQEmu::skills::SkillMend)) return; if (!p_timers.Expired(&database, pTimerMend, false)) { @@ -9262,7 +9262,7 @@ void Client::Handle_OP_Mend(const EQApplicationPacket *app) int mendhp = GetMaxHP() / 4; int currenthp = GetHP(); - if (zone->random.Int(0, 199) < (int)GetSkill(SkillMend)) { + if (zone->random.Int(0, 199) < (int)GetSkill(EQEmu::skills::SkillMend)) { int criticalchance = spellbonuses.CriticalMend + itembonuses.CriticalMend + aabonuses.CriticalMend; @@ -9281,7 +9281,7 @@ void Client::Handle_OP_Mend(const EQApplicationPacket *app) 0 skill - 25% chance to worsen 20 skill - 23% chance to worsen 50 skill - 16% chance to worsen */ - if ((GetSkill(SkillMend) <= 75) && (zone->random.Int(GetSkill(SkillMend), 100) < 75) && (zone->random.Int(1, 3) == 1)) + if ((GetSkill(EQEmu::skills::SkillMend) <= 75) && (zone->random.Int(GetSkill(EQEmu::skills::SkillMend), 100) < 75) && (zone->random.Int(1, 3) == 1)) { SetHP(currenthp > mendhp ? (GetHP() - mendhp) : 1); SendHPUpdate(); @@ -9291,7 +9291,7 @@ void Client::Handle_OP_Mend(const EQApplicationPacket *app) Message_StringID(4, MEND_FAIL); } - CheckIncreaseSkill(SkillMend, nullptr, 10); + CheckIncreaseSkill(EQEmu::skills::SkillMend, nullptr, 10); return; } @@ -10440,7 +10440,7 @@ void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) DumpPacket(app); } - if (!HasSkill(SkillPickPockets)) + if (!HasSkill(EQEmu::skills::SkillPickPockets)) { return; } @@ -10465,7 +10465,7 @@ void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) pick_out->coin = 0; pick_out->from = victim->GetID(); pick_out->to = GetID(); - pick_out->myskill = GetSkill(SkillPickPockets); + pick_out->myskill = GetSkill(EQEmu::skills::SkillPickPockets); pick_out->type = 0; //if we do not send this packet the client will lock up and require the player to relog. QueuePacket(outapp); @@ -10478,7 +10478,7 @@ void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) pick_out->coin = 0; pick_out->from = victim->GetID(); pick_out->to = GetID(); - pick_out->myskill = GetSkill(SkillPickPockets); + pick_out->myskill = GetSkill(EQEmu::skills::SkillPickPockets); pick_out->type = 0; //if we do not send this packet the client will lock up and require the player to relog. QueuePacket(outapp); @@ -10494,7 +10494,7 @@ void Client::Handle_OP_PickPocket(const EQApplicationPacket *app) pick_out->coin = 0; pick_out->from = victim->GetID(); pick_out->to = GetID(); - pick_out->myskill = GetSkill(SkillPickPockets); + pick_out->myskill = GetSkill(EQEmu::skills::SkillPickPockets); pick_out->type = 0; //if we do not send this packet the client will lock up and require the player to relog. QueuePacket(outapp); @@ -11739,8 +11739,8 @@ void Client::Handle_OP_Sacrifice(const EQApplicationPacket *app) void Client::Handle_OP_SafeFallSuccess(const EQApplicationPacket *app) // bit of a misnomer, sent whenever safe fall is used (success of fail) { - if (HasSkill(SkillSafeFall)) //this should only get called if the client has safe fall, but just in case... - CheckIncreaseSkill(SkillSafeFall, nullptr); //check for skill up + if (HasSkill(EQEmu::skills::SkillSafeFall)) //this should only get called if the client has safe fall, but just in case... + CheckIncreaseSkill(EQEmu::skills::SkillSafeFall, nullptr); //check for skill up } void Client::Handle_OP_SafePoint(const EQApplicationPacket *app) @@ -11777,7 +11777,7 @@ void Client::Handle_OP_SelectTribute(const EQApplicationPacket *app) void Client::Handle_OP_SenseHeading(const EQApplicationPacket *app) { - if (!HasSkill(SkillSenseHeading)) + if (!HasSkill(EQEmu::skills::SkillSenseHeading)) return; int chancemod=0; @@ -11791,14 +11791,14 @@ void Client::Handle_OP_SenseHeading(const EQApplicationPacket *app) if (GetLevel() <= 8) chancemod += (9-level) * 10; - CheckIncreaseSkill(SkillSenseHeading, nullptr, chancemod); + CheckIncreaseSkill(EQEmu::skills::SkillSenseHeading, nullptr, chancemod); return; } void Client::Handle_OP_SenseTraps(const EQApplicationPacket *app) { - if (!HasSkill(SkillSenseTraps)) + if (!HasSkill(EQEmu::skills::SkillSenseTraps)) return; if (!p_timers.Expired(&database, pTimerSenseTraps, false)) { @@ -11806,7 +11806,7 @@ void Client::Handle_OP_SenseTraps(const EQApplicationPacket *app) return; } - int reuse = SenseTrapsReuseTime - GetSkillReuseTime(SkillSenseTraps); + int reuse = SenseTrapsReuseTime - GetSkillReuseTime(EQEmu::skills::SkillSenseTraps); if (reuse < 1) reuse = 1; @@ -11815,10 +11815,10 @@ void Client::Handle_OP_SenseTraps(const EQApplicationPacket *app) Trap* trap = entity_list.FindNearbyTrap(this, 800); - CheckIncreaseSkill(SkillSenseTraps, nullptr); + CheckIncreaseSkill(EQEmu::skills::SkillSenseTraps, nullptr); if (trap && trap->skill > 0) { - int uskill = GetSkill(SkillSenseTraps); + int uskill = GetSkill(EQEmu::skills::SkillSenseTraps); if ((zone->random.Int(0, 99) + uskill) >= (zone->random.Int(0, 99) + trap->skill*0.75)) { auto diff = trap->m_Position - glm::vec3(GetPosition()); @@ -12621,7 +12621,7 @@ void Client::Handle_OP_ShopRequest(const EQApplicationPacket *app) void Client::Handle_OP_Sneak(const EQApplicationPacket *app) { - if (!HasSkill(SkillSneak) && GetSkill(SkillSneak) == 0) { + if (!HasSkill(EQEmu::skills::SkillSneak) && GetSkill(EQEmu::skills::SkillSneak) == 0) { return; //You cannot sneak if you do not have sneak } @@ -12645,9 +12645,9 @@ void Client::Handle_OP_Sneak(const EQApplicationPacket *app) safe_delete(outapp); } else { - CheckIncreaseSkill(SkillSneak, nullptr, 5); + CheckIncreaseSkill(EQEmu::skills::SkillSneak, nullptr, 5); } - float hidechance = ((GetSkill(SkillSneak) / 300.0f) + .25) * 100; + float hidechance = ((GetSkill(EQEmu::skills::SkillSneak) / 300.0f) + .25) * 100; float random = zone->random.Real(0, 99); if (!was && random < hidechance) { sneaking = true; @@ -12688,7 +12688,7 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app) if (sa->type == AT_Invis) { if (sa->parameter != 0) { - if (!HasSkill(SkillHide) && GetSkill(SkillHide) == 0) + if (!HasSkill(EQEmu::skills::SkillHide) && GetSkill(EQEmu::skills::SkillHide) == 0) { if (ClientVersion() < EQEmu::versions::ClientVersion::SoF) { @@ -12790,7 +12790,7 @@ void Client::Handle_OP_SpawnAppearance(const EQApplicationPacket *app) if (sa->parameter != 0) { - if (!HasSkill(SkillSneak)) + if (!HasSkill(EQEmu::skills::SkillSneak)) { char *hack_str = nullptr; MakeAnyLenString(&hack_str, "Player sent OP_SpawnAppearance with AT_Sneak: %i", sa->parameter); @@ -13234,10 +13234,10 @@ void Client::Handle_OP_Track(const EQApplicationPacket *app) if (GetClass() != RANGER && GetClass() != DRUID && GetClass() != BARD) return; - if (GetSkill(SkillTracking) == 0) - SetSkill(SkillTracking, 1); + if (GetSkill(EQEmu::skills::SkillTracking) == 0) + SetSkill(EQEmu::skills::SkillTracking, 1); else - CheckIncreaseSkill(SkillTracking, nullptr, 15); + CheckIncreaseSkill(EQEmu::skills::SkillTracking, nullptr, 15); if (!entity_list.MakeTrackPacket(this)) Log.Out(Logs::General, Logs::Error, "Unable to generate OP_Track packet requested by client."); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 984a66240..b0e742901 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -428,7 +428,7 @@ bool Client::Process() { //you can't see your target } else if(auto_attack_target->GetHP() > -10) { - CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10); + CheckIncreaseSkill(EQEmu::skills::SkillDualWield, auto_attack_target, -10); if (CheckDualWield()) { ItemInst *wpn = GetInv().GetItem(EQEmu::legacy::SlotSecondary); TryWeaponProc(wpn, auto_attack_target, EQEmu::legacy::SlotSecondary); @@ -1481,19 +1481,19 @@ void Client::OPGMTraining(const EQApplicationPacket *app) // if this for-loop acts up again (crashes linux), try enabling the before and after #pragmas //#pragma GCC push_options //#pragma GCC optimize ("O0") - for (int sk = Skill1HBlunt; sk <= HIGHEST_SKILL; ++sk) { - if(sk == SkillTinkering && GetRace() != GNOME) { + for (int sk = EQEmu::skills::Skill1HBlunt; sk <= EQEmu::skills::HIGHEST_SKILL; ++sk) { + if (sk == EQEmu::skills::SkillTinkering && GetRace() != GNOME) { gmtrain->skills[sk] = 0; //Non gnomes can't tinker! } else { - gmtrain->skills[sk] = GetMaxSkillAfterSpecializationRules((SkillUseTypes)sk, MaxSkill((SkillUseTypes)sk, GetClass(), RuleI(Character, MaxLevel))); + gmtrain->skills[sk] = GetMaxSkillAfterSpecializationRules((EQEmu::skills::SkillType)sk, MaxSkill((EQEmu::skills::SkillType)sk, GetClass(), RuleI(Character, MaxLevel))); //this is the highest level that the trainer can train you to, this is enforced clientside so we can't just //Set it to 1 with CanHaveSkill or you wont be able to train past 1. } } if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2 && GetClass() == BERSERKER) { - gmtrain->skills[Skill1HPiercing] = gmtrain->skills[Skill2HPiercing]; - gmtrain->skills[Skill2HPiercing] = 0; + gmtrain->skills[EQEmu::skills::Skill1HPiercing] = gmtrain->skills[EQEmu::skills::Skill2HPiercing]; + gmtrain->skills[EQEmu::skills::Skill2HPiercing] = 0; } //#pragma GCC pop_options @@ -1578,14 +1578,14 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app) else if (gmskill->skillbank == 0x00) { // normal skills go here - if (gmskill->skill_id > HIGHEST_SKILL) + if (gmskill->skill_id > EQEmu::skills::HIGHEST_SKILL) { std::cout << "Wrong Training Skill (abilities)" << std::endl; DumpPacket(app); return; } - SkillUseTypes skill = (SkillUseTypes) gmskill->skill_id; + EQEmu::skills::SkillType skill = (EQEmu::skills::SkillType)gmskill->skill_id; if(!CanHaveSkill(skill)) { Log.Out(Logs::Detail, Logs::Skills, "Tried to train skill %d, which is not allowed.", skill); @@ -1610,27 +1610,27 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app) SetSkill(skill, t_level); } else { switch(skill) { - case SkillBrewing: - case SkillMakePoison: - case SkillTinkering: - case SkillResearch: - case SkillAlchemy: - case SkillBaking: - case SkillTailoring: - case SkillBlacksmithing: - case SkillFletching: - case SkillJewelryMaking: - case SkillPottery: + case EQEmu::skills::SkillBrewing: + case EQEmu::skills::SkillMakePoison: + case EQEmu::skills::SkillTinkering: + case EQEmu::skills::SkillResearch: + case EQEmu::skills::SkillAlchemy: + case EQEmu::skills::SkillBaking: + case EQEmu::skills::SkillTailoring: + case EQEmu::skills::SkillBlacksmithing: + case EQEmu::skills::SkillFletching: + case EQEmu::skills::SkillJewelryMaking: + case EQEmu::skills::SkillPottery: if(skilllevel >= RuleI(Skills, MaxTrainTradeskills)) { Message_StringID(13, MORE_SKILLED_THAN_I, pTrainer->GetCleanName()); return; } break; - case SkillSpecializeAbjure: - case SkillSpecializeAlteration: - case SkillSpecializeConjuration: - case SkillSpecializeDivination: - case SkillSpecializeEvocation: + case EQEmu::skills::SkillSpecializeAbjure: + case EQEmu::skills::SkillSpecializeAlteration: + case EQEmu::skills::SkillSpecializeConjuration: + case EQEmu::skills::SkillSpecializeDivination: + case EQEmu::skills::SkillSpecializeEvocation: if(skilllevel >= RuleI(Skills, MaxTrainSpecializations)) { Message_StringID(13, MORE_SKILLED_THAN_I, pTrainer->GetCleanName()); return; @@ -1647,7 +1647,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app) return; } - if(gmskill->skill_id >= SkillSpecializeAbjure && gmskill->skill_id <= SkillSpecializeEvocation) + if (gmskill->skill_id >= EQEmu::skills::SkillSpecializeAbjure && gmskill->skill_id <= EQEmu::skills::SkillSpecializeEvocation) { int MaxSpecSkill = GetMaxSkillAfterSpecializationRules(skill, MaxSkillValue); if (skilllevel >= MaxSpecSkill) @@ -1685,7 +1685,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app) gmtsc->SkillID += 100; } else - gmtsc->NewSkill = (GetRawSkill((SkillUseTypes)gmtsc->SkillID) == 1); + gmtsc->NewSkill = (GetRawSkill((EQEmu::skills::SkillType)gmtsc->SkillID) == 1); gmtsc->Cost = Cost; diff --git a/zone/command.cpp b/zone/command.cpp index dd2b8941e..92116485c 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -52,6 +52,7 @@ #include "../common/rulesys.h" #include "../common/serverinfo.h" #include "../common/string_util.h" +#include "../say_link.h" #include "../common/eqemu_logsys.h" @@ -2129,7 +2130,7 @@ void command_showskills(Client *c, const Seperator *sep) t=c->GetTarget()->CastToClient(); c->Message(0, "Skills for %s", t->GetName()); - for (SkillUseTypes i=Skill1HBlunt; i <= HIGHEST_SKILL; i=(SkillUseTypes)(i+1)) + for (EQEmu::skills::SkillType i = EQEmu::skills::Skill1HBlunt; i <= EQEmu::skills::HIGHEST_SKILL; i = (EQEmu::skills::SkillType)(i + 1)) c->Message(0, "Skill [%d] is at [%d] - %u", i, t->GetSkill(i), t->GetRawSkill(i)); } @@ -2277,20 +2278,20 @@ void command_setskill(Client *c, const Seperator *sep) c->Message(0, "Error: #setskill: Target must be a client."); } else if ( - !sep->IsNumber(1) || atoi(sep->arg[1]) < 0 || atoi(sep->arg[1]) > HIGHEST_SKILL || + !sep->IsNumber(1) || atoi(sep->arg[1]) < 0 || atoi(sep->arg[1]) > EQEmu::skills::HIGHEST_SKILL || !sep->IsNumber(2) || atoi(sep->arg[2]) < 0 || atoi(sep->arg[2]) > HIGHEST_CAN_SET_SKILL ) { c->Message(0, "Usage: #setskill skill x "); - c->Message(0, " skill = 0 to %d", HIGHEST_SKILL); + c->Message(0, " skill = 0 to %d", EQEmu::skills::HIGHEST_SKILL); c->Message(0, " x = 0 to %d", HIGHEST_CAN_SET_SKILL); } else { Log.Out(Logs::General, Logs::Normal, "Set skill request from %s, target:%s skill_id:%i value:%i", c->GetName(), c->GetTarget()->GetName(), atoi(sep->arg[1]), atoi(sep->arg[2]) ); int skill_num = atoi(sep->arg[1]); uint16 skill_value = atoi(sep->arg[2]); - if(skill_num <= HIGHEST_SKILL) - c->GetTarget()->CastToClient()->SetSkill((SkillUseTypes)skill_num, skill_value); + if (skill_num <= EQEmu::skills::HIGHEST_SKILL) + c->GetTarget()->CastToClient()->SetSkill((EQEmu::skills::SkillType)skill_num, skill_value); } } @@ -2308,7 +2309,7 @@ void command_setskillall(Client *c, const Seperator *sep) if (c->Admin() >= commandSetSkillsOther || c->GetTarget()==c || c->GetTarget()==0) { Log.Out(Logs::General, Logs::Normal, "Set ALL skill request from %s, target:%s", c->GetName(), c->GetTarget()->GetName()); uint16 level = atoi(sep->arg[1]); - for(SkillUseTypes skill_num=Skill1HBlunt;skill_num <= HIGHEST_SKILL;skill_num=(SkillUseTypes)(skill_num+1)) { + for (EQEmu::skills::SkillType skill_num = EQEmu::skills::Skill1HBlunt; skill_num <= EQEmu::skills::HIGHEST_SKILL; skill_num = (EQEmu::skills::SkillType)(skill_num + 1)) { c->GetTarget()->CastToClient()->SetSkill(skill_num, level); } } @@ -4197,7 +4198,7 @@ void command_damage(Client *c, const Seperator *sep) if (nkdmg > 2100000000) c->Message(0, "Enter a value less then 2,100,000,000."); else - c->GetTarget()->Damage(c, nkdmg, SPELL_UNKNOWN, SkillHandtoHand, false); + c->GetTarget()->Damage(c, nkdmg, SPELL_UNKNOWN, EQEmu::skills::SkillHandtoHand, false); } } @@ -9942,16 +9943,16 @@ void command_max_all_skills(Client *c, const Seperator *sep) { if(c) { - for(int i = 0; i <= HIGHEST_SKILL; ++i) + for (int i = 0; i <= EQEmu::skills::HIGHEST_SKILL; ++i) { - if(i >= SkillSpecializeAbjure && i <= SkillSpecializeEvocation) + if (i >= EQEmu::skills::SkillSpecializeAbjure && i <= EQEmu::skills::SkillSpecializeEvocation) { - c->SetSkill((SkillUseTypes)i, 50); + c->SetSkill((EQEmu::skills::SkillType)i, 50); } else { - int max_skill_level = database.GetSkillCap(c->GetClass(), (SkillUseTypes)i, c->GetLevel()); - c->SetSkill((SkillUseTypes)i, max_skill_level); + int max_skill_level = database.GetSkillCap(c->GetClass(), (EQEmu::skills::SkillType)i, c->GetLevel()); + c->SetSkill((EQEmu::skills::SkillType)i, max_skill_level); } } } @@ -10037,14 +10038,14 @@ void command_disarmtrap(Client *c, const Seperator *sep) if(target->IsNPC()) { - if(c->HasSkill(SkillDisarmTraps)) + if (c->HasSkill(EQEmu::skills::SkillDisarmTraps)) { if(DistanceSquaredNoZ(c->GetPosition(), target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) { c->Message(13, "%s is too far away.", target->GetCleanName()); return; } - c->HandleLDoNDisarm(target->CastToNPC(), c->GetSkill(SkillDisarmTraps), LDoNTypeMechanical); + c->HandleLDoNDisarm(target->CastToNPC(), c->GetSkill(EQEmu::skills::SkillDisarmTraps), LDoNTypeMechanical); } else c->Message(13, "You do not have the disarm trap skill."); @@ -10062,14 +10063,14 @@ void command_sensetrap(Client *c, const Seperator *sep) if(target->IsNPC()) { - if(c->HasSkill(SkillSenseTraps)) + if (c->HasSkill(EQEmu::skills::SkillSenseTraps)) { if(DistanceSquaredNoZ(c->GetPosition(), target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) { c->Message(13, "%s is too far away.", target->GetCleanName()); return; } - c->HandleLDoNSenseTraps(target->CastToNPC(), c->GetSkill(SkillSenseTraps), LDoNTypeMechanical); + c->HandleLDoNSenseTraps(target->CastToNPC(), c->GetSkill(EQEmu::skills::SkillSenseTraps), LDoNTypeMechanical); } else c->Message(13, "You do not have the sense traps skill."); @@ -10087,14 +10088,14 @@ void command_picklock(Client *c, const Seperator *sep) if(target->IsNPC()) { - if(c->HasSkill(SkillPickLock)) + if (c->HasSkill(EQEmu::skills::SkillPickLock)) { if(DistanceSquaredNoZ(c->GetPosition(), target->GetPosition()) > RuleI(Adventure, LDoNTrapDistanceUse)) { c->Message(13, "%s is too far away.", target->GetCleanName()); return; } - c->HandleLDoNPickLock(target->CastToNPC(), c->GetSkill(SkillPickLock), LDoNTypeMechanical); + c->HandleLDoNPickLock(target->CastToNPC(), c->GetSkill(EQEmu::skills::SkillPickLock), LDoNTypeMechanical); } else c->Message(13, "You do not have the pick locks skill."); diff --git a/zone/common.h b/zone/common.h index 8a6d9c783..d517bb721 100644 --- a/zone/common.h +++ b/zone/common.h @@ -277,8 +277,8 @@ struct StatBonuses { int32 inhibitmelee; float AggroRange; // when calculate just replace original value with this float AssistRange; - int32 skillmod[HIGHEST_SKILL+1]; - int32 skillmodmax[HIGHEST_SKILL+1]; + int32 skillmod[EQEmu::skills::HIGHEST_SKILL + 1]; + int32 skillmodmax[EQEmu::skills::HIGHEST_SKILL + 1]; int effective_casting_level; int reflect_chance; // chance to reflect incoming spell uint32 singingMod; @@ -294,7 +294,7 @@ struct StatBonuses { int32 StrikeThrough; // PoP: Strike Through % int32 MeleeMitigation; //i = Shielding int32 MeleeMitigationEffect; //i = Spell Effect Melee Mitigation - int32 CriticalHitChance[HIGHEST_SKILL+2]; //i + int32 CriticalHitChance[EQEmu::skills::HIGHEST_SKILL + 2]; //i int32 CriticalSpellChance; //i int32 SpellCritDmgIncrease; //i int32 SpellCritDmgIncNoStack; // increase @@ -321,10 +321,10 @@ struct StatBonuses { int32 MeleeSkillCheck; //i uint8 MeleeSkillCheckSkill; int32 HitChance; //HitChance/15 == % increase i = Accuracy (Item: Accuracy) - int32 HitChanceEffect[HIGHEST_SKILL+2]; //Spell effect Chance to Hit, straight percent increase - int32 DamageModifier[HIGHEST_SKILL+2]; //i - int32 DamageModifier2[HIGHEST_SKILL+2]; //i - int32 MinDamageModifier[HIGHEST_SKILL+2]; //i + int32 HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 2]; //Spell effect Chance to Hit, straight percent increase + int32 DamageModifier[EQEmu::skills::HIGHEST_SKILL + 2]; //i + int32 DamageModifier2[EQEmu::skills::HIGHEST_SKILL + 2]; //i + int32 MinDamageModifier[EQEmu::skills::HIGHEST_SKILL + 2]; //i int32 ProcChance; // ProcChance/10 == % increase i = CombatEffects int32 ProcChanceSPA; // ProcChance from spell effects int32 ExtraAttackChance; @@ -332,13 +332,13 @@ struct StatBonuses { int32 DivineSaveChance[2]; // Second Chance (base1 = chance, base2 = spell on trigger) uint32 DeathSave[4]; // Death Pact [0](value = 1 partial 2 = full) [1]=slot [2]=LvLimit [3]=HealAmt int32 FlurryChance; - int32 Accuracy[HIGHEST_SKILL+2]; //Accuracy/15 == % increase [Spell Effect: Accuracy) + int32 Accuracy[EQEmu::skills::HIGHEST_SKILL + 2]; //Accuracy/15 == % increase [Spell Effect: Accuracy) int32 HundredHands; //extra haste, stacks with all other haste i int32 MeleeLifetap; //i int32 Vampirism; //i int32 HealRate; // Spell effect that influences effectiveness of heals int32 MaxHPChange; // Spell Effect - int16 SkillDmgTaken[HIGHEST_SKILL+2]; // All Skills + -1 + int16 SkillDmgTaken[EQEmu::skills::HIGHEST_SKILL + 2]; // All Skills + -1 int32 HealAmt; // Item Effect int32 SpellDmg; // Item Effect int32 Clairvoyance; // Item Effect @@ -347,9 +347,9 @@ struct StatBonuses { uint32 SpellTriggers[MAX_SPELL_TRIGGER]; // Innate/Spell/Item Spells that trigger when you cast uint32 SpellOnKill[MAX_SPELL_TRIGGER*3]; // Chance to proc after killing a mob uint32 SpellOnDeath[MAX_SPELL_TRIGGER*2]; // Chance to have effect cast when you die - int32 CritDmgMob[HIGHEST_SKILL+2]; // All Skills + -1 - int32 SkillReuseTime[HIGHEST_SKILL+1]; // Reduces skill timers - int32 SkillDamageAmount[HIGHEST_SKILL+2]; // All Skills + -1 + int32 CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 2]; // All Skills + -1 + int32 SkillReuseTime[EQEmu::skills::HIGHEST_SKILL + 1]; // Reduces skill timers + int32 SkillDamageAmount[EQEmu::skills::HIGHEST_SKILL + 2]; // All Skills + -1 int32 TwoHandBluntBlock; // chance to block when wielding two hand blunt weapon uint32 ItemManaRegenCap; // Increases the amount of mana you have can over the cap(aa effect) int32 GravityEffect; // Indictor of spell effect @@ -372,7 +372,7 @@ struct StatBonuses { uint8 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have. int16 FocusEffectsWorn[HIGHEST_FOCUS+1]; // Optional to allow focus effects to be applied additively from worn slot bool NegateEffects; // Check if you contain a buff with negate effect. (only spellbonuses) - int32 SkillDamageAmount2[HIGHEST_SKILL+2]; // Adds skill specific damage + int32 SkillDamageAmount2[EQEmu::skills::HIGHEST_SKILL + 2]; // Adds skill specific damage uint32 NegateAttacks[3]; // 0 = bool HasEffect 1 = Buff Slot 2 = Max damage absorbed per hit uint32 MitigateMeleeRune[4]; // 0 = Mitigation value 1 = Buff Slot 2 = Max mitigation per hit 3 = Rune Amt uint32 MeleeThresholdGuard[3]; // 0 = Mitigation value 1 = Buff Slot 2 = Min damage to trigger. @@ -405,7 +405,7 @@ struct StatBonuses { int32 Metabolism; // Food/drink consumption rates. bool Sanctuary; // Sanctuary effect, lowers place on hate list until cast on others. int32 FactionModPct; // Modifies amount of faction gained. - bool LimitToSkill[HIGHEST_SKILL+2]; // Determines if we need to search for a skill proc. + bool LimitToSkill[EQEmu::skills::HIGHEST_SKILL + 2]; // Determines if we need to search for a skill proc. uint32 SkillProc[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs. uint32 SkillProcSuccess[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs_success. uint32 PC_Pet_Rampage[2]; // 0= % chance to rampage, 1=damage modifier @@ -440,7 +440,7 @@ struct StatBonuses { int32 CombatStability; // Melee damage mitigation. int32 DoubleRiposte; // Chance to double riposte int32 GiveDoubleRiposte[3]; // 0=Regular Chance, 1=Skill Attack Chance, 2=Skill - uint32 RaiseSkillCap[HIGHEST_SKILL+1]; // Raise a specific skill cap (base1= value, base2=skill) + uint32 RaiseSkillCap[EQEmu::skills::HIGHEST_SKILL + 1]; // Raise a specific skill cap (base1= value, base2=skill) int32 Ambidexterity; // Increase chance to duel wield by adding bonus 'skill'. int32 PetMaxHP; // Increase the max hp of your pet. int32 PetFlurry; // Chance for pet to flurry. @@ -470,7 +470,7 @@ struct StatBonuses { uint16 extra_xtargets; // extra xtarget entries bool ShroudofStealth; // rogue improved invisiblity uint16 ReduceFallDamage; // reduce fall damage by percent - int32 ReduceTradeskillFail[HIGHEST_SKILL+1]; // Reduces chance for trade skills to fail by percent. + int32 ReduceTradeskillFail[EQEmu::skills::HIGHEST_SKILL + 1]; // Reduces chance for trade skills to fail by percent. uint8 TradeSkillMastery; // Allow number of tradeskills to exceed 200 skill. int16 NoBreakAESneak; // Percent value int16 FeignedCastOnChance; // Percent Value diff --git a/zone/corpse.cpp b/zone/corpse.cpp index bb88e305b..2286e5e71 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -34,6 +34,7 @@ Child of the Mob class. #include "../common/eqemu_logsys.h" #include "../common/rulesys.h" #include "../common/string_util.h" +#include "../common/say_link.h" #include "client.h" #include "corpse.h" @@ -997,7 +998,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::limits::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()), EQEmu::legacy::TypeCorpse); + int corpselootlimit = EQEmu::inventory::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()), EQEmu::legacy::TypeCorpse); for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; @@ -1291,7 +1292,7 @@ void Corpse::QueryLoot(Client* to) { cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::limits::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()), EQEmu::legacy::TypeCorpse); + int corpselootlimit = EQEmu::inventory::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()), EQEmu::legacy::TypeCorpse); for(; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; diff --git a/zone/corpse.h b/zone/corpse.h index d96a38bdd..03a48dd87 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -47,8 +47,8 @@ class Corpse : public Mob { static Corpse* LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std::string in_charname, const glm::vec4& position, std::string time_of_death, bool rezzed, bool was_at_graveyard); /* Corpse: General */ - virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } + virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; } + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } diff --git a/zone/doors.cpp b/zone/doors.cpp index c80b749f9..9b1f41370 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -284,12 +284,12 @@ void Doors::HandleClick(Client* sender, uint8 trigger) } else if(lockpicks != nullptr) { - if(sender->GetSkill(SkillPickLock)) + if (sender->GetSkill(EQEmu::skills::SkillPickLock)) { if(lockpicks->GetItem()->ItemType == EQEmu::item::ItemTypeLockPick) { - float modskill=sender->GetSkill(SkillPickLock); - sender->CheckIncreaseSkill(SkillPickLock, nullptr, 1); + float modskill = sender->GetSkill(EQEmu::skills::SkillPickLock); + sender->CheckIncreaseSkill(EQEmu::skills::SkillPickLock, nullptr, 1); Log.Out(Logs::General, Logs::Skills, "Client has lockpicks: skill=%f", modskill); diff --git a/zone/encounter.h b/zone/encounter.h index 05c1b075b..ed8faec34 100644 --- a/zone/encounter.h +++ b/zone/encounter.h @@ -34,8 +34,8 @@ public: ~Encounter(); //abstract virtual function implementations required by base abstract class - virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; } - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } + virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; } + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; diff --git a/zone/entity.cpp b/zone/entity.cpp index f788b06c2..e5c5c193d 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -3008,11 +3008,11 @@ bool EntityList::MakeTrackPacket(Client *client) float MobDistance; if (client->GetClass() == DRUID) - distance = (client->GetSkill(SkillTracking) * 10); + distance = (client->GetSkill(EQEmu::skills::SkillTracking) * 10); else if (client->GetClass() == RANGER) - distance = (client->GetSkill(SkillTracking) * 12); + distance = (client->GetSkill(EQEmu::skills::SkillTracking) * 12); else if (client->GetClass() == BARD) - distance = (client->GetSkill(SkillTracking) * 7); + distance = (client->GetSkill(EQEmu::skills::SkillTracking) * 7); if (distance <= 0) return false; if (distance < 300) diff --git a/zone/forage.cpp b/zone/forage.cpp index be3e0a3b3..eb54d674d 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -249,7 +249,7 @@ void Client::GoFish() //success formula is not researched at all - int fishing_skill = GetSkill(SkillFishing); //will take into account skill bonuses on pole & bait + int fishing_skill = GetSkill(EQEmu::skills::SkillFishing); //will take into account skill bonuses on pole & bait //make sure we still have a fishing pole on: int32 bslot = m_inv.HasItemByUse(EQEmu::item::ItemTypeFishingBait, 1, invWhereWorn | invWherePersonal); @@ -258,7 +258,7 @@ void Client::GoFish() Bait = m_inv.GetItem(bslot); //if the bait isnt equipped, need to add its skill bonus - if (bslot >= EQEmu::legacy::GENERAL_BEGIN && Bait != nullptr && Bait->GetItem()->SkillModType == SkillFishing) { + if (bslot >= EQEmu::legacy::GENERAL_BEGIN && Bait != nullptr && Bait->GetItem()->SkillModType == EQEmu::skills::SkillFishing) { fishing_skill += Bait->GetItem()->SkillModValue; } @@ -357,16 +357,16 @@ void Client::GoFish() DeleteItemInInventory(EQEmu::legacy::SlotPrimary, 0, true); } - if(CheckIncreaseSkill(SkillFishing, nullptr, 5)) + if (CheckIncreaseSkill(EQEmu::skills::SkillFishing, nullptr, 5)) { - if(title_manager.IsNewTradeSkillTitleAvailable(SkillFishing, GetRawSkill(SkillFishing))) + if (title_manager.IsNewTradeSkillTitleAvailable(EQEmu::skills::SkillFishing, GetRawSkill(EQEmu::skills::SkillFishing))) NotifyNewTitlesAvailable(); } } void Client::ForageItem(bool guarantee) { - int skill_level = GetSkill(SkillForage); + int skill_level = GetSkill(EQEmu::skills::SkillForage); //be wary of the string ids in switch below when changing this. uint32 common_food_ids[MAX_COMMON_FOOD_IDS] = { @@ -457,7 +457,7 @@ void Client::ForageItem(bool guarantee) { parse->EventPlayer(EVENT_FORAGE_FAILURE, this, "", 0); } - CheckIncreaseSkill(SkillForage, nullptr, 5); + CheckIncreaseSkill(EQEmu::skills::SkillForage, nullptr, 5); } diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 935516040..6c2345856 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -432,27 +432,27 @@ void Lua_Client::IncreaseLanguageSkill(int skill_id, int value) { int Lua_Client::GetRawSkill(int skill_id) { Lua_Safe_Call_Int(); - return self->GetRawSkill(static_cast(skill_id)); + return self->GetRawSkill(static_cast(skill_id)); } bool Lua_Client::HasSkill(int skill_id) { Lua_Safe_Call_Bool(); - return self->HasSkill(static_cast(skill_id)); + return self->HasSkill(static_cast(skill_id)); } bool Lua_Client::CanHaveSkill(int skill_id) { Lua_Safe_Call_Bool(); - return self->CanHaveSkill(static_cast(skill_id)); + return self->CanHaveSkill(static_cast(skill_id)); } void Lua_Client::SetSkill(int skill_id, int value) { Lua_Safe_Call_Void(); - self->SetSkill(static_cast(skill_id), value); + self->SetSkill(static_cast(skill_id), value); } void Lua_Client::AddSkill(int skill_id, int value) { Lua_Safe_Call_Void(); - self->AddSkill(static_cast(skill_id), value); + self->AddSkill(static_cast(skill_id), value); } void Lua_Client::CheckSpecializeIncrease(int spell_id) { @@ -462,12 +462,12 @@ void Lua_Client::CheckSpecializeIncrease(int spell_id) { void Lua_Client::CheckIncreaseSkill(int skill_id, Lua_Mob target) { Lua_Safe_Call_Void(); - self->CheckIncreaseSkill(static_cast(skill_id), target); + self->CheckIncreaseSkill(static_cast(skill_id), target); } void Lua_Client::CheckIncreaseSkill(int skill_id, Lua_Mob target, int chance_mod) { Lua_Safe_Call_Void(); - self->CheckIncreaseSkill(static_cast(skill_id), target, chance_mod); + self->CheckIncreaseSkill(static_cast(skill_id), target, chance_mod); } void Lua_Client::SetLanguageSkill(int language, int value) { @@ -477,7 +477,7 @@ void Lua_Client::SetLanguageSkill(int language, int value) { int Lua_Client::MaxSkill(int skill_id) { Lua_Safe_Call_Int(); - return self->MaxSkill(static_cast(skill_id)); + return self->MaxSkill(static_cast(skill_id)); } bool Lua_Client::IsMedding() { diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 38fd80cc7..124726b3f 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -178,22 +178,22 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket void Lua_Mob::Damage(Lua_Mob from, int damage, int spell_id, int attack_skill) { Lua_Safe_Call_Void(); - return self->Damage(from, damage, spell_id, static_cast(attack_skill)); + return self->Damage(from, damage, spell_id, static_cast(attack_skill)); } void Lua_Mob::Damage(Lua_Mob from, int damage, int spell_id, int attack_skill, bool avoidable) { Lua_Safe_Call_Void(); - return self->Damage(from, damage, spell_id, static_cast(attack_skill), avoidable); + return self->Damage(from, damage, spell_id, static_cast(attack_skill), avoidable); } void Lua_Mob::Damage(Lua_Mob from, int damage, int spell_id, int attack_skill, bool avoidable, int buffslot) { Lua_Safe_Call_Void(); - return self->Damage(from, damage, spell_id, static_cast(attack_skill), avoidable, buffslot); + return self->Damage(from, damage, spell_id, static_cast(attack_skill), avoidable, buffslot); } void Lua_Mob::Damage(Lua_Mob from, int damage, int spell_id, int attack_skill, bool avoidable, int buffslot, bool buff_tic) { Lua_Safe_Call_Void(); - return self->Damage(from, damage, spell_id, static_cast(attack_skill), avoidable, buffslot, buff_tic); + return self->Damage(from, damage, spell_id, static_cast(attack_skill), avoidable, buffslot, buff_tic); } void Lua_Mob::RangedAttack(Lua_Mob other) { @@ -1252,28 +1252,28 @@ bool Lua_Mob::CombatRange(Lua_Mob other) { void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage) { Lua_Safe_Call_Void(); - self->DoSpecialAttackDamage(other, static_cast(skill), max_damage); + self->DoSpecialAttackDamage(other, static_cast(skill), max_damage); } void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage) { Lua_Safe_Call_Void(); - self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage); + self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage); } void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override) { Lua_Safe_Call_Void(); - self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage, hate_override); + self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage, hate_override); } void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override, int reuse_time) { Lua_Safe_Call_Void(); - self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage, hate_override, reuse_time); + self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage, hate_override, reuse_time); } void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override, int reuse_time, bool hit_chance) { Lua_Safe_Call_Void(); - self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage, hate_override, reuse_time, hit_chance); + self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage, hate_override, reuse_time, hit_chance); } void Lua_Mob::DoThrowingAttackDmg(Lua_Mob other) { @@ -1309,22 +1309,22 @@ void Lua_Mob::DoThrowingAttackDmg(Lua_Mob other, Lua_ItemInst range_weapon, Lua_ void Lua_Mob::DoMeleeSkillAttackDmg(Lua_Mob other, int weapon_damage, int skill) { Lua_Safe_Call_Void(); - self->DoMeleeSkillAttackDmg(other, weapon_damage, static_cast(skill)); + self->DoMeleeSkillAttackDmg(other, weapon_damage, static_cast(skill)); } void Lua_Mob::DoMeleeSkillAttackDmg(Lua_Mob other, int weapon_damage, int skill, int chance_mod) { Lua_Safe_Call_Void(); - self->DoMeleeSkillAttackDmg(other, weapon_damage, static_cast(skill), chance_mod); + self->DoMeleeSkillAttackDmg(other, weapon_damage, static_cast(skill), chance_mod); } void Lua_Mob::DoMeleeSkillAttackDmg(Lua_Mob other, int weapon_damage, int skill, int chance_mod, int focus) { Lua_Safe_Call_Void(); - self->DoMeleeSkillAttackDmg(other, weapon_damage, static_cast(skill), chance_mod, focus); + self->DoMeleeSkillAttackDmg(other, weapon_damage, static_cast(skill), chance_mod, focus); } void Lua_Mob::DoMeleeSkillAttackDmg(Lua_Mob other, int weapon_damage, int skill, int chance_mod, int focus, bool can_riposte) { Lua_Safe_Call_Void(); - self->DoMeleeSkillAttackDmg(other, weapon_damage, static_cast(skill), chance_mod, focus, can_riposte); + self->DoMeleeSkillAttackDmg(other, weapon_damage, static_cast(skill), chance_mod, focus, can_riposte); } void Lua_Mob::DoArcheryAttackDmg(Lua_Mob other) { @@ -1713,17 +1713,17 @@ void Lua_Mob::SetTargetable(bool on) { void Lua_Mob::ModSkillDmgTaken(int skill, int value) { Lua_Safe_Call_Void(); - self->ModSkillDmgTaken(static_cast(skill), value); + self->ModSkillDmgTaken(static_cast(skill), value); } int Lua_Mob::GetModSkillDmgTaken(int skill) { Lua_Safe_Call_Int(); - return self->GetModSkillDmgTaken(static_cast(skill)); + return self->GetModSkillDmgTaken(static_cast(skill)); } int Lua_Mob::GetSkillDmgTaken(int skill) { Lua_Safe_Call_Int(); - return self->GetSkillDmgTaken(static_cast(skill)); + return self->GetSkillDmgTaken(static_cast(skill)); } void Lua_Mob::SetAllowBeneficial(bool value) { @@ -1773,7 +1773,7 @@ int Lua_Mob::GetFlurryChance() { int Lua_Mob::GetSkill(int skill) { Lua_Safe_Call_Int(); - return self->GetSkill(static_cast(skill)); + return self->GetSkill(static_cast(skill)); } int Lua_Mob::GetSpecialAbility(int ability) { diff --git a/zone/merc.cpp b/zone/merc.cpp index 51eac564d..d4ecabdd8 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -70,8 +70,8 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading) rest_timer.Disable(); int r; - for(r = 0; r <= HIGHEST_SKILL; r++) { - skills[r] = database.GetSkillCap(GetClass(),(SkillUseTypes)r,GetLevel()); + for (r = 0; r <= EQEmu::skills::HIGHEST_SKILL; r++) { + skills[r] = database.GetSkillCap(GetClass(), (EQEmu::skills::SkillType)r, GetLevel()); } size = d->size; @@ -512,7 +512,7 @@ void Merc::AddItemBonuses(const EQEmu::Item_Struct *item, StatBonuses* newbon) { } } - if (item->SkillModValue != 0 && item->SkillModType <= HIGHEST_SKILL){ + if (item->SkillModValue != 0 && item->SkillModType <= EQEmu::skills::HIGHEST_SKILL){ if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) || (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) { @@ -566,7 +566,7 @@ void Merc::AddItemBonuses(const EQEmu::Item_Struct *item, StatBonuses* newbon) { } } - if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= HIGHEST_SKILL) { + if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= EQEmu::skills::HIGHEST_SKILL) { if((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); else @@ -931,8 +931,8 @@ int32 Merc::CalcBaseManaRegen() int32 regen = 0; if (IsSitting()) { - if(HasSkill(SkillMeditate)) - regen = (((GetSkill(SkillMeditate) / 10) + (clevel - (clevel / 4))) / 4) + 4; + if (HasSkill(EQEmu::skills::SkillMeditate)) + regen = (((GetSkill(EQEmu::skills::SkillMeditate) / 10) + (clevel - (clevel / 4))) / 4) + 4; else regen = 2; } @@ -948,9 +948,9 @@ int32 Merc::CalcManaRegen() if (IsSitting()) { BuffFadeBySitModifier(); - if(HasSkill(SkillMeditate)) { + if (HasSkill(EQEmu::skills::SkillMeditate)) { this->_medding = true; - regen = ((GetSkill(SkillMeditate) / 10) + mana_regen); + regen = ((GetSkill(EQEmu::skills::SkillMeditate) / 10) + mana_regen); regen += spellbonuses.ManaRegen + itembonuses.ManaRegen; } else @@ -1179,16 +1179,16 @@ void Merc::CalcRestState() { RestRegenEndurance = (GetMaxEndurance() * RuleI(Character, RestRegenPercent) / 100); } -bool Merc::HasSkill(SkillUseTypes skill_id) const { +bool Merc::HasSkill(EQEmu::skills::SkillType skill_id) const { return((GetSkill(skill_id) > 0) && CanHaveSkill(skill_id)); } -bool Merc::CanHaveSkill(SkillUseTypes skill_id) const { +bool Merc::CanHaveSkill(EQEmu::skills::SkillType skill_id) const { return(database.GetSkillCap(GetClass(), skill_id, RuleI(Character, MaxLevel)) > 0); //if you don't have it by max level, then odds are you never will? } -uint16 Merc::MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const { +uint16 Merc::MaxSkill(EQEmu::skills::SkillType skillid, uint16 class_, uint16 level) const { return(database.GetSkillCap(class_, skillid, level)); } @@ -1627,7 +1627,7 @@ void Merc::AI_Process() { float DualWieldProbability = 0.0f; int16 Ambidexterity = aabonuses.Ambidexterity + spellbonuses.Ambidexterity + itembonuses.Ambidexterity; - DualWieldProbability = (GetSkill(SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f; // 78.0 max + DualWieldProbability = (GetSkill(EQEmu::skills::SkillDualWield) + GetLevel() + Ambidexterity) / 400.0f; // 78.0 max int16 DWBonus = spellbonuses.DualWieldChance + itembonuses.DualWieldChance; DualWieldProbability += DualWieldProbability*float(DWBonus)/ 100.0f; @@ -2318,7 +2318,7 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) { continue; } - if(spells[selectedMercSpell.spellid].skill == SkillBackstab && spells[selectedMercSpell.spellid].targettype == ST_Self) { + if (spells[selectedMercSpell.spellid].skill == EQEmu::skills::SkillBackstab && spells[selectedMercSpell.spellid].targettype == ST_Self) { if(!hidden) { continue; } @@ -4432,7 +4432,7 @@ void Merc::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if(target->CheckHitChance(this, SkillKick, 0)) { + if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) { if(RuleB(Combat, UseIntervalAC)) dmg = GetKickDamage(); else @@ -4442,7 +4442,7 @@ void Merc::DoClassAttacks(Mob *target) { } reuse = KickReuseTime * 1000; - DoSpecialAttackDamage(target, SkillKick, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, 1, -1, reuse); did_attack = true; } else @@ -4454,7 +4454,7 @@ void Merc::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if(target->CheckHitChance(this, SkillBash, 0)) { + if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) { if(RuleB(Combat, UseIntervalAC)) dmg = GetBashDamage(); else @@ -4463,7 +4463,7 @@ void Merc::DoClassAttacks(Mob *target) { } reuse = BashReuseTime * 1000; - DoSpecialAttackDamage(target, SkillBash, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, 1, -1, reuse); did_attack = true; } } @@ -4485,7 +4485,7 @@ bool Merc::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, boo return NPC::Attack(other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts); } -void Merc::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) +void Merc::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { if(IsDead() || IsCorpse()) return; @@ -4526,7 +4526,7 @@ Mob* Merc::GetOwnerOrSelf() { return Result; } -bool Merc::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack_skill) +bool Merc::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::SkillType attack_skill) { if(!NPC::Death(killerMob, damage, spell, attack_skill)) { diff --git a/zone/merc.h b/zone/merc.h index e9f993063..275417adb 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -64,8 +64,8 @@ public: virtual ~Merc(); //abstract virtual function implementations requird by base abstract class - virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); + virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } @@ -181,10 +181,10 @@ public: inline const uint8 GetClientVersion() const { return _OwnerClientVersion; } virtual void SetTarget(Mob* mob); - bool HasSkill(SkillUseTypes skill_id) const; - bool CanHaveSkill(SkillUseTypes skill_id) const; - uint16 MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const; - inline uint16 MaxSkill(SkillUseTypes skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); } + bool HasSkill(EQEmu::skills::SkillType skill_id) const; + bool CanHaveSkill(EQEmu::skills::SkillType skill_id) const; + uint16 MaxSkill(EQEmu::skills::SkillType skillid, uint16 class_, uint16 level) const; + inline uint16 MaxSkill(EQEmu::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); } virtual void DoClassAttacks(Mob *target); void CheckHateList(); bool CheckTaunt(); @@ -291,7 +291,7 @@ protected: std::vector merc_spells; std::map timers; - uint16 skills[HIGHEST_SKILL+1]; + uint16 skills[EQEmu::skills::HIGHEST_SKILL + 1]; uint32 equipment[EQEmu::legacy::EQUIPMENT_SIZE]; //this is an array of item IDs uint16 d_melee_texture1; //this is an item Material value uint16 d_melee_texture2; //this is an item Material value (offhand) diff --git a/zone/mob.cpp b/zone/mob.cpp index aa7862601..7f2224deb 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -427,7 +427,7 @@ Mob::Mob(const char* in_name, m_AllowBeneficial = false; m_DisableMelee = false; - for (int i = 0; i < HIGHEST_SKILL+2; i++) { SkillDmgTaken_Mod[i] = 0; } + for (int i = 0; i < EQEmu::skills::HIGHEST_SKILL + 2; i++) { SkillDmgTaken_Mod[i] = 0; } for (int i = 0; i < HIGHEST_RESIST+2; i++) { Vulnerability_Mod[i] = 0; } emoteid = 0; @@ -2369,14 +2369,14 @@ void Mob::SetZone(uint32 zone_id, uint32 instance_id) } void Mob::Kill() { - Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); + Death(this, 0, SPELL_UNKNOWN, EQEmu::skills::SkillHandtoHand); } bool Mob::CanThisClassDualWield(void) const { if(!IsClient()) { - return(GetSkill(SkillDualWield) > 0); + return(GetSkill(EQEmu::skills::SkillDualWield) > 0); } - else if(CastToClient()->HasSkill(SkillDualWield)) { + else if (CastToClient()->HasSkill(EQEmu::skills::SkillDualWield)) { const ItemInst* pinst = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); const ItemInst* sinst = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); @@ -2406,12 +2406,12 @@ bool Mob::CanThisClassDualWield(void) const { bool Mob::CanThisClassDoubleAttack(void) const { if(!IsClient()) { - return(GetSkill(SkillDoubleAttack) > 0); + return(GetSkill(EQEmu::skills::SkillDoubleAttack) > 0); } else { if(aabonuses.GiveDoubleAttack || itembonuses.GiveDoubleAttack || spellbonuses.GiveDoubleAttack) { return true; } - return(CastToClient()->HasSkill(SkillDoubleAttack)); + return(CastToClient()->HasSkill(EQEmu::skills::SkillDoubleAttack)); } } @@ -2420,7 +2420,7 @@ bool Mob::CanThisClassTripleAttack() const if (!IsClient()) return false; // When they added the real triple attack skill, mobs lost the ability to triple else - return CastToClient()->HasSkill(SkillTripleAttack); + return CastToClient()->HasSkill(EQEmu::skills::SkillTripleAttack); } bool Mob::IsWarriorClass(void) const @@ -2459,36 +2459,36 @@ bool Mob::IsWarriorClass(void) const bool Mob::CanThisClassParry(void) const { if(!IsClient()) { - return(GetSkill(SkillParry) > 0); + return(GetSkill(EQEmu::skills::SkillParry) > 0); } else { - return(CastToClient()->HasSkill(SkillParry)); + return(CastToClient()->HasSkill(EQEmu::skills::SkillParry)); } } bool Mob::CanThisClassDodge(void) const { if(!IsClient()) { - return(GetSkill(SkillDodge) > 0); + return(GetSkill(EQEmu::skills::SkillDodge) > 0); } else { - return(CastToClient()->HasSkill(SkillDodge)); + return(CastToClient()->HasSkill(EQEmu::skills::SkillDodge)); } } bool Mob::CanThisClassRiposte(void) const { if(!IsClient()) { - return(GetSkill(SkillRiposte) > 0); + return(GetSkill(EQEmu::skills::SkillRiposte) > 0); } else { - return(CastToClient()->HasSkill(SkillRiposte)); + return(CastToClient()->HasSkill(EQEmu::skills::SkillRiposte)); } } bool Mob::CanThisClassBlock(void) const { if(!IsClient()) { - return(GetSkill(SkillBlock) > 0); + return(GetSkill(EQEmu::skills::SkillBlock) > 0); } else { - return(CastToClient()->HasSkill(SkillBlock)); + return(CastToClient()->HasSkill(EQEmu::skills::SkillBlock)); } } /* @@ -3411,19 +3411,19 @@ void Mob::TriggerDefensiveProcs(Mob *on, uint16 hand, bool FromSkillProc, int da uint16 skillinuse = 0; switch (damage) { case (-1): - skillinuse = SkillBlock; + skillinuse = EQEmu::skills::SkillBlock; break; case (-2): - skillinuse = SkillParry; + skillinuse = EQEmu::skills::SkillParry; break; case (-3): - skillinuse = SkillRiposte; + skillinuse = EQEmu::skills::SkillRiposte; break; case (-4): - skillinuse = SkillDodge; + skillinuse = EQEmu::skills::SkillDodge; break; } @@ -3784,15 +3784,15 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining) return value; } -int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used, ExtraAttackOptions *opts) +int16 Mob::GetSkillDmgTaken(const EQEmu::skills::SkillType skill_used, ExtraAttackOptions *opts) { int skilldmg_mod = 0; // All skill dmg mod + Skill specific - skilldmg_mod += itembonuses.SkillDmgTaken[HIGHEST_SKILL+1] + spellbonuses.SkillDmgTaken[HIGHEST_SKILL+1] + + skilldmg_mod += itembonuses.SkillDmgTaken[EQEmu::skills::HIGHEST_SKILL + 1] + spellbonuses.SkillDmgTaken[EQEmu::skills::HIGHEST_SKILL + 1] + itembonuses.SkillDmgTaken[skill_used] + spellbonuses.SkillDmgTaken[skill_used]; - skilldmg_mod += SkillDmgTaken_Mod[skill_used] + SkillDmgTaken_Mod[HIGHEST_SKILL+1]; + skilldmg_mod += SkillDmgTaken_Mod[skill_used] + SkillDmgTaken_Mod[EQEmu::skills::HIGHEST_SKILL + 1]; if (opts) skilldmg_mod += opts->skilldmgtaken_bonus_flat; @@ -4606,7 +4606,7 @@ int16 Mob::GetCritDmgMob(uint16 skill) int critDmg_mod = 0; // All skill dmg mod + Skill specific - critDmg_mod += itembonuses.CritDmgMob[HIGHEST_SKILL+1] + spellbonuses.CritDmgMob[HIGHEST_SKILL+1] + aabonuses.CritDmgMob[HIGHEST_SKILL+1] + + critDmg_mod += itembonuses.CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] + spellbonuses.CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] + aabonuses.CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] + itembonuses.CritDmgMob[skill] + spellbonuses.CritDmgMob[skill] + aabonuses.CritDmgMob[skill]; if(critDmg_mod < -100) @@ -4651,7 +4651,7 @@ int16 Mob::GetCriticalChanceBonus(uint16 skill) int critical_chance = 0; // All skills + Skill specific - critical_chance += itembonuses.CriticalHitChance[HIGHEST_SKILL+1] + spellbonuses.CriticalHitChance[HIGHEST_SKILL+1] + aabonuses.CriticalHitChance[HIGHEST_SKILL+1] + + critical_chance += itembonuses.CriticalHitChance[EQEmu::skills::HIGHEST_SKILL + 1] + spellbonuses.CriticalHitChance[EQEmu::skills::HIGHEST_SKILL + 1] + aabonuses.CriticalHitChance[EQEmu::skills::HIGHEST_SKILL + 1] + itembonuses.CriticalHitChance[skill] + spellbonuses.CriticalHitChance[skill] + aabonuses.CriticalHitChance[skill]; if(critical_chance < -100) @@ -4665,10 +4665,10 @@ int16 Mob::GetMeleeDamageMod_SE(uint16 skill) int dmg_mod = 0; // All skill dmg mod + Skill specific - dmg_mod += itembonuses.DamageModifier[HIGHEST_SKILL+1] + spellbonuses.DamageModifier[HIGHEST_SKILL+1] + aabonuses.DamageModifier[HIGHEST_SKILL+1] + + dmg_mod += itembonuses.DamageModifier[EQEmu::skills::HIGHEST_SKILL + 1] + spellbonuses.DamageModifier[EQEmu::skills::HIGHEST_SKILL + 1] + aabonuses.DamageModifier[EQEmu::skills::HIGHEST_SKILL + 1] + itembonuses.DamageModifier[skill] + spellbonuses.DamageModifier[skill] + aabonuses.DamageModifier[skill]; - dmg_mod += itembonuses.DamageModifier2[HIGHEST_SKILL+1] + spellbonuses.DamageModifier2[HIGHEST_SKILL+1] + aabonuses.DamageModifier2[HIGHEST_SKILL+1] + + dmg_mod += itembonuses.DamageModifier2[EQEmu::skills::HIGHEST_SKILL + 1] + spellbonuses.DamageModifier2[EQEmu::skills::HIGHEST_SKILL + 1] + aabonuses.DamageModifier2[EQEmu::skills::HIGHEST_SKILL + 1] + itembonuses.DamageModifier2[skill] + spellbonuses.DamageModifier2[skill] + aabonuses.DamageModifier2[skill]; if (HasShieldEquiped() && !IsOffHandAtk()) @@ -4685,7 +4685,7 @@ int16 Mob::GetMeleeMinDamageMod_SE(uint16 skill) int dmg_mod = 0; dmg_mod = itembonuses.MinDamageModifier[skill] + spellbonuses.MinDamageModifier[skill] + - itembonuses.MinDamageModifier[HIGHEST_SKILL+1] + spellbonuses.MinDamageModifier[HIGHEST_SKILL+1]; + itembonuses.MinDamageModifier[EQEmu::skills::HIGHEST_SKILL + 1] + spellbonuses.MinDamageModifier[EQEmu::skills::HIGHEST_SKILL + 1]; if(dmg_mod < -100) dmg_mod = -100; @@ -4717,10 +4717,10 @@ int16 Mob::GetSkillDmgAmt(uint16 skill) int skill_dmg = 0; // All skill dmg(only spells do this) + Skill specific - skill_dmg += spellbonuses.SkillDamageAmount[HIGHEST_SKILL+1] + itembonuses.SkillDamageAmount[HIGHEST_SKILL+1] + aabonuses.SkillDamageAmount[HIGHEST_SKILL+1] + skill_dmg += spellbonuses.SkillDamageAmount[EQEmu::skills::HIGHEST_SKILL + 1] + itembonuses.SkillDamageAmount[EQEmu::skills::HIGHEST_SKILL + 1] + aabonuses.SkillDamageAmount[EQEmu::skills::HIGHEST_SKILL + 1] + itembonuses.SkillDamageAmount[skill] + spellbonuses.SkillDamageAmount[skill] + aabonuses.SkillDamageAmount[skill]; - skill_dmg += spellbonuses.SkillDamageAmount2[HIGHEST_SKILL+1] + itembonuses.SkillDamageAmount2[HIGHEST_SKILL+1] + skill_dmg += spellbonuses.SkillDamageAmount2[EQEmu::skills::HIGHEST_SKILL + 1] + itembonuses.SkillDamageAmount2[EQEmu::skills::HIGHEST_SKILL + 1] + itembonuses.SkillDamageAmount2[skill] + spellbonuses.SkillDamageAmount2[skill]; return skill_dmg; @@ -4740,7 +4740,7 @@ void Mob::MeleeLifeTap(int32 damage) { if (lifetap_amt > 0) HealDamage(lifetap_amt); //Heal self for modified damage amount. else - Damage(this, -lifetap_amt,0, SkillEvocation,false); //Dmg self for modified damage amount. + Damage(this, -lifetap_amt, 0, EQEmu::skills::SkillEvocation, false); //Dmg self for modified damage amount. } } @@ -4914,21 +4914,21 @@ void Mob::SetBodyType(bodyType new_body, bool overwrite_orig) { } -void Mob::ModSkillDmgTaken(SkillUseTypes skill_num, int value) +void Mob::ModSkillDmgTaken(EQEmu::skills::SkillType skill_num, int value) { if (skill_num == ALL_SKILLS) - SkillDmgTaken_Mod[HIGHEST_SKILL+1] = value; + SkillDmgTaken_Mod[EQEmu::skills::HIGHEST_SKILL + 1] = value; - else if (skill_num >= 0 && skill_num <= HIGHEST_SKILL) + else if (skill_num >= 0 && skill_num <= EQEmu::skills::HIGHEST_SKILL) SkillDmgTaken_Mod[skill_num] = value; } -int16 Mob::GetModSkillDmgTaken(const SkillUseTypes skill_num) +int16 Mob::GetModSkillDmgTaken(const EQEmu::skills::SkillType skill_num) { if (skill_num == ALL_SKILLS) - return SkillDmgTaken_Mod[HIGHEST_SKILL+1]; + return SkillDmgTaken_Mod[EQEmu::skills::HIGHEST_SKILL + 1]; - else if (skill_num >= 0 && skill_num <= HIGHEST_SKILL) + else if (skill_num >= 0 && skill_num <= EQEmu::skills::HIGHEST_SKILL) return SkillDmgTaken_Mod[skill_num]; return 0; @@ -5021,52 +5021,52 @@ uint16 Mob::GetSkillByItemType(int ItemType) { switch (ItemType) { case EQEmu::item::ItemType1HSlash: - return Skill1HSlashing; + return EQEmu::skills::Skill1HSlashing; case EQEmu::item::ItemType2HSlash: - return Skill2HSlashing; + return EQEmu::skills::Skill2HSlashing; case EQEmu::item::ItemType1HPiercing: - return Skill1HPiercing; + return EQEmu::skills::Skill1HPiercing; case EQEmu::item::ItemType1HBlunt: - return Skill1HBlunt; + return EQEmu::skills::Skill1HBlunt; case EQEmu::item::ItemType2HBlunt: - return Skill2HBlunt; + return EQEmu::skills::Skill2HBlunt; case EQEmu::item::ItemType2HPiercing: if (IsClient() && CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::RoF2) - return Skill1HPiercing; + return EQEmu::skills::Skill1HPiercing; else - return Skill2HPiercing; + return EQEmu::skills::Skill2HPiercing; case EQEmu::item::ItemTypeBow: - return SkillArchery; + return EQEmu::skills::SkillArchery; case EQEmu::item::ItemTypeLargeThrowing: case EQEmu::item::ItemTypeSmallThrowing: - return SkillThrowing; + return EQEmu::skills::SkillThrowing; case EQEmu::item::ItemTypeMartial: - return SkillHandtoHand; + return EQEmu::skills::SkillHandtoHand; default: - return SkillHandtoHand; + return EQEmu::skills::SkillHandtoHand; } } -uint8 Mob::GetItemTypeBySkill(SkillUseTypes skill) +uint8 Mob::GetItemTypeBySkill(EQEmu::skills::SkillType skill) { switch (skill) { - case SkillThrowing: + case EQEmu::skills::SkillThrowing: return EQEmu::item::ItemTypeSmallThrowing; - case SkillArchery: + case EQEmu::skills::SkillArchery: return EQEmu::item::ItemTypeArrow; - case Skill1HSlashing: + case EQEmu::skills::Skill1HSlashing: return EQEmu::item::ItemType1HSlash; - case Skill2HSlashing: + case EQEmu::skills::Skill2HSlashing: return EQEmu::item::ItemType2HSlash; - case Skill1HPiercing: + case EQEmu::skills::Skill1HPiercing: return EQEmu::item::ItemType1HPiercing; - case Skill2HPiercing: // watch for undesired client behavior + case EQEmu::skills::Skill2HPiercing: // watch for undesired client behavior return EQEmu::item::ItemType2HPiercing; - case Skill1HBlunt: + case EQEmu::skills::Skill1HBlunt: return EQEmu::item::ItemType1HBlunt; - case Skill2HBlunt: + case EQEmu::skills::Skill2HBlunt: return EQEmu::item::ItemType2HBlunt; - case SkillHandtoHand: + case EQEmu::skills::SkillHandtoHand: return EQEmu::item::ItemTypeMartial; default: return EQEmu::item::ItemTypeMartial; diff --git a/zone/mob.h b/zone/mob.h index 18c46cb61..ed6dc1154 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -25,6 +25,7 @@ #include "position.h" #include "aa_ability.h" #include "aa.h" +#include "../common/light_source.h" #include #include #include @@ -157,12 +158,12 @@ public: int MonkSpecialAttack(Mob* other, uint8 skill_used); virtual void TryBackstab(Mob *other,int ReuseTime = 10); bool AvoidDamage(Mob* attacker, int32 &damage, int hand); - virtual bool CheckHitChance(Mob* attacker, SkillUseTypes skillinuse, int Hand, int16 chance_mod = 0); + virtual bool CheckHitChance(Mob* attacker, EQEmu::skills::SkillType skillinuse, int Hand, int16 chance_mod = 0); virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts = nullptr); void TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage); - virtual bool TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse); - uint32 TryHeadShot(Mob* defender, SkillUseTypes skillInUse); - uint32 TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 ReuseTime); + virtual bool TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse); + uint32 TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse); + uint32 TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, uint16 ReuseTime); virtual void DoRiposte(Mob* defender); void ApplyMeleeDamageBonus(uint16 skill, int32 &damage,ExtraAttackOptions *opts = nullptr); virtual void MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts = nullptr); @@ -170,7 +171,7 @@ public: bool CombatRange(Mob* other); virtual inline bool IsBerserk() { return false; } // only clients void RogueEvade(Mob *other); - void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, SkillUseTypes skillInUse,ExtraAttackOptions *opts = nullptr); + void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts = nullptr); void BreakInvisibleSpells(); void CommonBreakInvisibleFromCombat(); bool HasDied(); @@ -203,7 +204,7 @@ public: virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model = 0); void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone); void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0, - float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr, SkillUseTypes skillInUse = SkillArchery); + float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr, EQEmu::skills::SkillType skillInUse = EQEmu::skills::SkillArchery); void ChangeSize(float in_size, bool bNoRestriction = false); inline uint8 SeeInvisible() const { return see_invis; } inline bool SeeInvisibleUndead() const { return see_invis_undead; } @@ -211,7 +212,7 @@ public: inline bool SeeImprovedHide() const { return see_improved_hide; } bool IsInvisible(Mob* other = 0) const; void SetInvisible(uint8 state); - bool AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* weapon); + bool AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const ItemInst* weapon); //Song bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1); @@ -348,7 +349,7 @@ public: inline void SetTwoHandBluntEquiped(bool val) { has_twohandbluntequiped = val; } bool HasTwoHanderEquipped() { return has_twohanderequipped; } void SetTwoHanderEquipped(bool val) { has_twohanderequipped = val; } - virtual uint16 GetSkill(SkillUseTypes skill_num) const { return 0; } + virtual uint16 GetSkill(EQEmu::skills::SkillType skill_num) const { return 0; } virtual uint32 GetEquipment(uint8 material_slot) const { return(0); } virtual int32 GetEquipmentMaterial(uint8 material_slot) const; virtual int32 GetHerosForgeModel(uint8 material_slot) const; @@ -356,8 +357,8 @@ public: virtual uint32 IsEliteMaterialItem(uint8 material_slot) const; bool CanClassEquipItem(uint32 item_id); bool AffectedBySpellExcludingSlot(int slot, int effect); - virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) = 0; - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, + virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) = 0; + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) = 0; inline virtual void SetHP(int32 hp) { if (hp >= max_hp) cur_hp = max_hp; else cur_hp = hp;} bool ChangeHP(Mob* other, int32 amount, uint16 spell_id = 0, int8 buffslot = -1, bool iBuffTic = false); @@ -556,7 +557,7 @@ public: static uint8 GetDefaultGender(uint16 in_race, uint8 in_gender = 0xFF); static bool IsPlayerRace(uint16 in_race); uint16 GetSkillByItemType(int ItemType); - uint8 GetItemTypeBySkill(SkillUseTypes skill); + uint8 GetItemTypeBySkill(EQEmu::skills::SkillType skill); virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr); virtual void MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, const char *petname = nullptr, float in_size = 0.0f); bool IsWarriorClass() const; @@ -649,7 +650,7 @@ public: int32 GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining); int32 GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill = false, uint16 skill=0); int32 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id); - int16 GetSkillDmgTaken(const SkillUseTypes skill_used,ExtraAttackOptions *opts=nullptr); + int16 GetSkillDmgTaken(const EQEmu::skills::SkillType skill_used, ExtraAttackOptions *opts = nullptr); void DoKnockback(Mob *caster, uint32 pushback, uint32 pushup); int16 CalcResistChanceBonus(); int16 CalcFearResistChance(); @@ -682,8 +683,8 @@ public: inline void SetSpellPowerDistanceMod(int16 value) { SpellPowerDistanceMod = value; }; int32 GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot = 0); - void ModSkillDmgTaken(SkillUseTypes skill_num, int value); - int16 GetModSkillDmgTaken(const SkillUseTypes skill_num); + void ModSkillDmgTaken(EQEmu::skills::SkillType skill_num, int value); + int16 GetModSkillDmgTaken(const EQEmu::skills::SkillType skill_num); void ModVulnerability(uint8 resist, int16 value); int16 GetModVulnerability(const uint8 resist); @@ -768,7 +769,7 @@ public: int32 GetMeleeMitigation(); uint8 GetWeaponDamageBonus(const EQEmu::Item_Struct* weapon, bool offhand = false); - uint16 GetDamageTable(SkillUseTypes skillinuse); + uint16 GetDamageTable(EQEmu::skills::SkillType skillinuse); virtual int GetHandToHandDamage(void); bool CanThisClassDoubleAttack(void) const; @@ -791,11 +792,11 @@ public: int32 AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker); int32 ReduceAllDamage(int32 damage); - virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool CheckHitChance=false, bool CanAvoid=true); + virtual void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool CheckHitChance = false, bool CanAvoid = true); virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const EQEmu::Item_Struct* AmmoItem=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0, uint32 range_id=0, int AmmoSlot=0, float speed = 4.0f); - virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime=0); + virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0); virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0, uint32 range_id=0, uint32 ammo_id=0, const EQEmu::Item_Struct *AmmoItem=nullptr, int AmmoSlot=0, float speed= 4.0f); - bool TryProjectileAttack(Mob* other, const EQEmu::Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed); + bool TryProjectileAttack(Mob* other, const EQEmu::Item_Struct *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed); void ProjectileAttack(); inline bool HasProjectileAttack() const { return ActiveProjectileATK; } inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; } @@ -913,7 +914,7 @@ public: // HP Event inline int GetNextHPEvent() const { return nexthpevent; } void SetNextHPEvent( int hpevent ); - void SendItemAnimation(Mob *to, const EQEmu::Item_Struct *item, SkillUseTypes skillInUse, float velocity= 4.0); + void SendItemAnimation(Mob *to, const EQEmu::Item_Struct *item, EQEmu::skills::SkillType skillInUse, float velocity = 4.0); inline int& GetNextIncHPEvent() { return nextinchpevent; } void SetNextIncHPEvent( int inchpevent ); @@ -964,7 +965,7 @@ public: bool HasSpellEffect(int effectid); int mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster, uint16 caster_id); - float mod_hit_chance(float chancetohit, SkillUseTypes skillinuse, Mob* attacker); + float mod_hit_chance(float chancetohit, EQEmu::skills::SkillType skillinuse, Mob* attacker); float mod_riposte_chance(float ripostchance, Mob* attacker); float mod_block_chance(float blockchance, Mob* attacker); float mod_parry_chance(float parrychance, Mob* attacker); @@ -975,7 +976,7 @@ public: int32 mod_kick_damage(int32 dmg); int32 mod_bash_damage(int32 dmg); int32 mod_frenzy_damage(int32 dmg); - int32 mod_monk_special_damage(int32 ndamage, SkillUseTypes skill_type); + int32 mod_monk_special_damage(int32 ndamage, EQEmu::skills::SkillType skill_type); int32 mod_backstab_damage(int32 ndamage); int mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon); uint32 mod_archery_bonus_damage(uint32 MaxDmg, const ItemInst* RangeWeapon); @@ -994,7 +995,7 @@ public: uint32 Tune_GetMeanDamage(Mob* GM, Mob *attacker, int32 damage, int32 minhit, ExtraAttackOptions *opts = nullptr, int Msg = 0,int ac_override=0, int atk_override=0, int add_ac=0, int add_atk = 0); void Tune_FindATKByPctMitigation(Mob* defender, Mob *attacker, float pct_mitigation, int interval = 50, int max_loop = 100, int ac_override=0,int Msg =0); void Tune_FindACByPctMitigation(Mob* defender, Mob *attacker, float pct_mitigation, int interval = 50, int max_loop = 100, int atk_override=0,int Msg =0); - float Tune_CheckHitChance(Mob* defender, Mob* attacker, SkillUseTypes skillinuse, int Hand, int16 chance_mod, int Msg = 1,int acc_override=0, int avoid_override=0, int add_acc=0, int add_avoid = 0); + float Tune_CheckHitChance(Mob* defender, Mob* attacker, EQEmu::skills::SkillType skillinuse, int Hand, int16 chance_mod, int Msg = 1, int acc_override = 0, int avoid_override = 0, int add_acc = 0, int add_avoid = 0); void Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int avoid_override, int Msg = 0); void Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int acc_override, int Msg = 0); @@ -1031,7 +1032,7 @@ public: #endif protected: - void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special = 0); + void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const EQEmu::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special = 0); static uint16 GetProcID(uint16 spell_id, uint8 effect_index); float _GetMovementSpeed(int mod) const; int _GetWalkSpeed() const; @@ -1049,7 +1050,7 @@ protected: std::vector RampageArray; std::map m_EntityVariables; - int16 SkillDmgTaken_Mod[HIGHEST_SKILL+2]; + int16 SkillDmgTaken_Mod[EQEmu::skills::HIGHEST_SKILL + 2]; int16 Vulnerability_Mod[HIGHEST_RESIST+2]; bool m_AllowBeneficial; bool m_DisableMelee; @@ -1165,7 +1166,7 @@ protected: int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr); int GetKickDamage(); int GetBashDamage(); - virtual void ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg); + virtual void ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int32 &mindmg); virtual int16 GetFocusEffect(focusType type, uint16 spell_id) { return 0; } void CalculateNewFearpoint(); float FindGroundZ(float new_x, float new_y, float z_offset=0.0); diff --git a/zone/mod_functions.cpp b/zone/mod_functions.cpp index e58945732..a38003504 100644 --- a/zone/mod_functions.cpp +++ b/zone/mod_functions.cpp @@ -29,7 +29,7 @@ void Zone::mod_repop() { return; } void NPC::mod_prespawn(Spawn2 *sp) { return; } //Base damage from NPC::Attack -int NPC::mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const EQEmu::Item_Struct* weapon, Mob* other) { return(damage); } +int NPC::mod_npc_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::Item_Struct* weapon, Mob* other) { return(damage); } //Mob c has been given credit for a kill. This is called after the regular EVENT_KILLED_MERIT event. void NPC::mod_npc_killed_merit(Mob* c) { return; } @@ -38,7 +38,7 @@ void NPC::mod_npc_killed_merit(Mob* c) { return; } void NPC::mod_npc_killed(Mob* oos) { return; } //Base damage from Client::Attack - can cover myriad skill types -int Client::mod_client_damage(int damage, SkillUseTypes skillinuse, int hand, const ItemInst* weapon, Mob* other) { return(damage); } +int Client::mod_client_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const ItemInst* weapon, Mob* other) { return(damage); } //message is char[4096], don't screw it up. Return true for normal behavior, false to return immediately. // Channels: @@ -58,7 +58,7 @@ bool Client::mod_client_message(char* message, uint8 chan_num) { return(true); } //Skillup override. When this is called the regular skillup check has failed. Return false to proceed with default behavior. //This will NOT allow a client to increase skill past a cap. -bool Client::mod_can_increase_skill(SkillUseTypes skillid, Mob* against_who) { return(false); } +bool Client::mod_can_increase_skill(EQEmu::skills::SkillType skillid, Mob* against_who) { return(false); } //chance of general skill increase, rolled against 0-99 where higher chance is better. int16 Client::mod_increase_skill_chance(int16 chance, Mob* against_who) { return(chance); } @@ -114,7 +114,7 @@ int Client::mod_drink_value(const EQEmu::Item_Struct *item, int change) { return int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster, uint16 caster_id) { return(effect_value); } //chancetohit - 0 to 100 percent - set over 1000 for a guaranteed hit -float Mob::mod_hit_chance(float chancetohit, SkillUseTypes skillinuse, Mob* attacker) { return(chancetohit); } +float Mob::mod_hit_chance(float chancetohit, EQEmu::skills::SkillType skillinuse, Mob* attacker) { return(chancetohit); } //Final riposte chance float Mob::mod_riposte_chance(float ripostechance, Mob* attacker) { return(ripostechance); } @@ -146,7 +146,7 @@ int32 Mob::mod_bash_damage(int32 dmg) { return(dmg); } int32 Mob::mod_frenzy_damage(int32 dmg) { return(dmg); } //Special attack damage after all other bonuses are applied. -int32 Mob::mod_monk_special_damage(int32 ndamage, SkillUseTypes skill_type) { return(ndamage); } +int32 Mob::mod_monk_special_damage(int32 ndamage, EQEmu::skills::SkillType skill_type) { return(ndamage); } //ndamage - Backstab damage as calculated by default formulas int32 Mob::mod_backstab_damage(int32 ndamage) { return(ndamage); } diff --git a/zone/npc.cpp b/zone/npc.cpp index 54c375f8c..b875a2d1b 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -30,6 +30,7 @@ #include "../common/item_struct.h" #include "../common/linked_list.h" #include "../common/servertalk.h" +#include "../common/say_link.h" #include "client.h" #include "entity.h" @@ -276,20 +277,20 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if //give NPCs skill values... int r; - for(r = 0; r <= HIGHEST_SKILL; r++) { - skills[r] = database.GetSkillCap(GetClass(),(SkillUseTypes)r,moblevel); + for (r = 0; r <= EQEmu::skills::HIGHEST_SKILL; r++) { + skills[r] = database.GetSkillCap(GetClass(), (EQEmu::skills::SkillType)r, moblevel); } // some overrides -- really we need to be able to set skills for mobs in the DB // There are some known low level SHM/BST pets that do not follow this, which supports // the theory of needing to be able to set skills for each mob separately if (moblevel > 50) { - skills[SkillDoubleAttack] = 250; - skills[SkillDualWield] = 250; + skills[EQEmu::skills::SkillDoubleAttack] = 250; + skills[EQEmu::skills::SkillDualWield] = 250; } else if (moblevel > 3) { - skills[SkillDoubleAttack] = moblevel * 5; - skills[SkillDualWield] = skills[SkillDoubleAttack]; + skills[EQEmu::skills::SkillDoubleAttack] = moblevel * 5; + skills[EQEmu::skills::SkillDualWield] = skills[EQEmu::skills::SkillDoubleAttack]; } else { - skills[SkillDoubleAttack] = moblevel * 5; + skills[EQEmu::skills::SkillDoubleAttack] = moblevel * 5; } if(d->trap_template > 0) @@ -1427,7 +1428,7 @@ uint32 NPC::GetMaxDamage(uint8 tlevel) void NPC::PickPocket(Client* thief) { - thief->CheckIncreaseSkill(SkillPickPockets, nullptr, 5); + thief->CheckIncreaseSkill(EQEmu::skills::SkillPickPockets, nullptr, 5); //make sure were allowed to target them: int over_level = GetLevel(); @@ -1446,7 +1447,7 @@ void NPC::PickPocket(Client* thief) return; } - int steal_skill = thief->GetSkill(SkillPickPockets); + int steal_skill = thief->GetSkill(EQEmu::skills::SkillPickPockets); int steal_chance = steal_skill * 100 / (5 * over_level + 5); // Determine whether to steal money or an item. diff --git a/zone/npc.h b/zone/npc.h index 0456ca211..5131eb569 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -108,8 +108,8 @@ public: virtual ~NPC(); //abstract virtual function implementations requird by base abstract class - virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); + virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } @@ -142,7 +142,7 @@ public: void CalcNPCDamage(); virtual void SetTarget(Mob* mob); - virtual uint16 GetSkill(SkillUseTypes skill_num) const { if (skill_num <= HIGHEST_SKILL) { return skills[skill_num]; } return 0; } + virtual uint16 GetSkill(EQEmu::skills::SkillType skill_num) const { if (skill_num <= EQEmu::skills::HIGHEST_SKILL) { return skills[skill_num]; } return 0; } void CalcItemBonuses(StatBonuses *newbon); virtual void CalcBonuses(); @@ -161,7 +161,7 @@ public: virtual void RangedAttack(Mob* other); virtual void ThrowingAttack(Mob* other) { } int32 GetNumberOfAttacks() const { return attack_count; } - void DoRangedAttackDmg(Mob* other, bool Launch=true, int16 damage_mod=0, int16 chance_mod=0, SkillUseTypes skill=SkillArchery, float speed=4.0f, const char *IDFile = nullptr); + void DoRangedAttackDmg(Mob* other, bool Launch = true, int16 damage_mod = 0, int16 chance_mod = 0, EQEmu::skills::SkillType skill = EQEmu::skills::SkillArchery, float speed = 4.0f, const char *IDFile = nullptr); bool DatabaseCastAccepted(int spell_id); bool IsFactionListAlly(uint32 other_faction); @@ -403,7 +403,7 @@ public: void SetMerchantProbability(uint8 amt) { probability = amt; } uint8 GetMerchantProbability() { return probability; } void mod_prespawn(Spawn2 *sp); - int mod_npc_damage(int damage, SkillUseTypes skillinuse, int hand, const EQEmu::Item_Struct* weapon, Mob* other); + int mod_npc_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::Item_Struct* weapon, Mob* other); void mod_npc_killed_merit(Mob* c); void mod_npc_killed(Mob* oos); void AISpellsList(Client *c); @@ -497,7 +497,7 @@ protected: uint32 roambox_delay; uint32 roambox_min_delay; - uint16 skills[HIGHEST_SKILL+1]; + uint16 skills[EQEmu::skills::HIGHEST_SKILL + 1]; uint32 equipment[EQEmu::legacy::EQUIPMENT_SIZE]; //this is an array of item IDs diff --git a/zone/object.h b/zone/object.h index c39ee61c9..c7ebdd677 100644 --- a/zone/object.h +++ b/zone/object.h @@ -108,7 +108,7 @@ public: static void HandleAugmentation(Client* user, const AugmentItem_Struct* in_augment, Object *worldo); static void HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac); - static SkillUseTypes TypeToSkill(uint32 type); + static EQEmu::skills::SkillType TypeToSkill(uint32 type); // Packet functions void CreateSpawnPacket(EQApplicationPacket* app); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 129dafd73..76c085714 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -1940,7 +1940,7 @@ XS(XS_Client_GetSkill) Client * THIS; uint16 RETVAL; dXSTARG; - SkillUseTypes skill_id = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skill_id = (EQEmu::skills::SkillType)SvUV(ST(1)); if (sv_derived_from(ST(0), "Client")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -1967,7 +1967,7 @@ XS(XS_Client_GetRawSkill) Client * THIS; uint32 RETVAL; dXSTARG; - SkillUseTypes skill_id = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skill_id = (EQEmu::skills::SkillType)SvUV(ST(1)); if (sv_derived_from(ST(0), "Client")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -1993,7 +1993,7 @@ XS(XS_Client_HasSkill) { Client * THIS; bool RETVAL; - SkillUseTypes skill_id = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skill_id = (EQEmu::skills::SkillType)SvUV(ST(1)); if (sv_derived_from(ST(0), "Client")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -2020,7 +2020,7 @@ XS(XS_Client_CanHaveSkill) { Client * THIS; bool RETVAL; - SkillUseTypes skill_id = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skill_id = (EQEmu::skills::SkillType)SvUV(ST(1)); if (sv_derived_from(ST(0), "Client")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -2046,7 +2046,7 @@ XS(XS_Client_SetSkill) Perl_croak(aTHX_ "Usage: Client::SetSkill(THIS, skill_num, value)"); { Client * THIS; - SkillUseTypes skill_num = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skill_num = (EQEmu::skills::SkillType)SvUV(ST(1)); uint16 value = (uint16)SvUV(ST(2)); if (sv_derived_from(ST(0), "Client")) { @@ -2071,7 +2071,7 @@ XS(XS_Client_AddSkill) Perl_croak(aTHX_ "Usage: Client::AddSkill(THIS, skillid, value)"); { Client * THIS; - SkillUseTypes skillid = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skillid = (EQEmu::skills::SkillType)SvUV(ST(1)); uint16 value = (uint16)SvUV(ST(2)); if (sv_derived_from(ST(0), "Client")) { @@ -2121,7 +2121,7 @@ XS(XS_Client_CheckIncreaseSkill) { Client * THIS; bool RETVAL; - SkillUseTypes skillid = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skillid = (EQEmu::skills::SkillType)SvUV(ST(1)); int chancemodi; if (sv_derived_from(ST(0), "Client")) { @@ -2180,7 +2180,7 @@ XS(XS_Client_MaxSkill) { Client * THIS; uint16 RETVAL; - SkillUseTypes skillid = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skillid = (EQEmu::skills::SkillType)SvUV(ST(1)); uint16 class_ = 0; uint16 level = 0; dXSTARG; diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index c9c24b955..89c94e7e3 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -619,7 +619,7 @@ XS(XS_Mob_GetSkill) Mob * THIS; uint32 RETVAL; dXSTARG; - SkillUseTypes skill_num = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skill_num = (EQEmu::skills::SkillType)SvUV(ST(1)); if (sv_derived_from(ST(0), "Mob")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -901,7 +901,7 @@ XS(XS_Mob_Damage) Mob* from; int32 damage = (int32)SvIV(ST(2)); uint16 spell_id = (uint16)SvUV(ST(3)); - SkillUseTypes attack_skill = (SkillUseTypes)SvUV(ST(4)); + EQEmu::skills::SkillType attack_skill = (EQEmu::skills::SkillType)SvUV(ST(4)); bool avoidable; int8 buffslot; bool iBuffTic; @@ -6836,7 +6836,7 @@ XS(XS_Mob_DoSpecialAttackDamage) { Mob * THIS; Mob* target; - SkillUseTypes attack_skill = (SkillUseTypes)SvUV(ST(2)); + EQEmu::skills::SkillType attack_skill = (EQEmu::skills::SkillType)SvUV(ST(2)); int32 max_damage = (int32)SvIV(ST(3)); int32 min_damage = 1; int32 hate_override = -11; @@ -7835,7 +7835,7 @@ XS(XS_Mob_ModSkillDmgTaken) Perl_croak(aTHX_ "Usage: Mob::ModSkillDmgTaken(THIS, skill, value)"); { Mob * THIS; - SkillUseTypes skill_num = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skill_num = (EQEmu::skills::SkillType)SvUV(ST(1)); int16 value = (int16)SvIV(ST(2)); if (sv_derived_from(ST(0), "Mob")) { @@ -7862,7 +7862,7 @@ XS(XS_Mob_GetModSkillDmgTaken) Mob * THIS; int16 RETVAL; dXSTARG; - SkillUseTypes skill_num = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skill_num = (EQEmu::skills::SkillType)SvUV(ST(1)); if (sv_derived_from(ST(0), "Mob")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -7889,7 +7889,7 @@ XS(XS_Mob_GetSkillDmgTaken) Mob * THIS; int32 RETVAL; dXSTARG; - SkillUseTypes skill_num = (SkillUseTypes)SvUV(ST(1)); + EQEmu::skills::SkillType skill_num = (EQEmu::skills::SkillType)SvUV(ST(1)); if (sv_derived_from(ST(0), "Mob")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -8055,7 +8055,7 @@ XS(XS_Mob_DoMeleeSkillAttackDmg) Mob * THIS; Mob* target; uint16 weapon_damage = (uint16)SvIV(ST(2)); - SkillUseTypes skill = (SkillUseTypes)SvUV(ST(3)); + EQEmu::skills::SkillType skill = (EQEmu::skills::SkillType)SvUV(ST(3)); int16 chance_mod = (int16)SvIV(ST(4)); int16 focus = (int16)SvIV(ST(5)); uint8 CanRiposte = (uint8)SvIV(ST(6)); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 70c7c404f..f28755efb 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -22,6 +22,7 @@ #include "../common/skills.h" #include "../common/spdat.h" #include "../common/string_util.h" +#include "../common/say_link.h" #include "entity.h" #include "event_codes.h" @@ -1152,10 +1153,10 @@ void QuestManager::doanim(int anim_id) { void QuestManager::addskill(int skill_id, int value) { QuestManagerCurrentQuestVars(); - if(skill_id < 0 || skill_id > HIGHEST_SKILL) + if (skill_id < 0 || skill_id > EQEmu::skills::HIGHEST_SKILL) return; if (initiator && initiator->IsClient()) - initiator->AddSkill((SkillUseTypes) skill_id, value); + initiator->AddSkill((EQEmu::skills::SkillType) skill_id, value); } void QuestManager::setlanguage(int skill_id, int value) { @@ -1166,10 +1167,10 @@ void QuestManager::setlanguage(int skill_id, int value) { void QuestManager::setskill(int skill_id, int value) { QuestManagerCurrentQuestVars(); - if(skill_id < 0 || skill_id > HIGHEST_SKILL) + if (skill_id < 0 || skill_id > EQEmu::skills::HIGHEST_SKILL) return; if (initiator && initiator->IsClient()) - initiator->SetSkill((SkillUseTypes) skill_id, value); + initiator->SetSkill((EQEmu::skills::SkillType) skill_id, value); } void QuestManager::setallskill(int value) { @@ -1177,8 +1178,8 @@ void QuestManager::setallskill(int value) { if (!initiator) return; if (initiator && initiator->IsClient()) { - SkillUseTypes sk; - for (sk = Skill1HBlunt; sk <= HIGHEST_SKILL; sk = (SkillUseTypes)(sk+1)) { + EQEmu::skills::SkillType sk; + for (sk = EQEmu::skills::Skill1HBlunt; sk <= EQEmu::skills::HIGHEST_SKILL; sk = (EQEmu::skills::SkillType)(sk + 1)) { initiator->SetSkill(sk, value); } } @@ -1772,7 +1773,7 @@ void QuestManager::clear_zone_flag(int zone_id) { void QuestManager::sethp(int hpperc) { QuestManagerCurrentQuestVars(); int newhp = (owner->GetMaxHP() * (100 - hpperc)) / 100; - owner->Damage(owner, newhp, SPELL_UNKNOWN, SkillHandtoHand, false, 0, false); + owner->Damage(owner, newhp, SPELL_UNKNOWN, EQEmu::skills::SkillHandtoHand, false, 0, false); } bool QuestManager::summonburiedplayercorpse(uint32 char_id, const glm::vec4& position) { diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 674c15d03..dd6f72b8b 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -30,14 +30,14 @@ int Mob::GetKickDamage() { int multiple=(GetLevel()*100/5); multiple += 100; - int32 dmg=(((GetSkill(SkillKick) + GetSTR() + GetLevel())*100 / 9000) * multiple) + 600; //Set a base of 6 damage, 1 seemed too low at the sub level 30 level. + int32 dmg = (((GetSkill(EQEmu::skills::SkillKick) + GetSTR() + GetLevel()) * 100 / 9000) * multiple) + 600; //Set a base of 6 damage, 1 seemed too low at the sub level 30 level. if(GetClass() == WARRIOR || GetClass() == WARRIORGM ||GetClass() == BERSERKER || GetClass() == BERSERKERGM) { dmg*=12/10;//small increase for warriors } dmg /= 100; int32 mindmg = 1; - ApplySpecialAttackMod(SkillKick, dmg,mindmg); + ApplySpecialAttackMod(EQEmu::skills::SkillKick, dmg, mindmg); dmg = mod_kick_damage(dmg); @@ -49,41 +49,37 @@ int Mob::GetBashDamage() { multiple += 100; //this is complete shite - int32 dmg=((((GetSkill(SkillBash) + GetSTR())*100 + GetLevel()*100/2) / 10000) * multiple) + 600; //Set a base of 6 damage, 1 seemed too low at the sub level 30 level. + int32 dmg = ((((GetSkill(EQEmu::skills::SkillBash) + GetSTR()) * 100 + GetLevel() * 100 / 2) / 10000) * multiple) + 600; //Set a base of 6 damage, 1 seemed too low at the sub level 30 level. dmg /= 100; int32 mindmg = 1; - ApplySpecialAttackMod(SkillBash, dmg, mindmg); + ApplySpecialAttackMod(EQEmu::skills::SkillBash, dmg, mindmg); dmg = mod_bash_damage(dmg); return(dmg); } -void Mob::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) { +void Mob::ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int32 &mindmg) { int item_slot = -1; //1: Apply bonus from AC (BOOT/SHIELD/HANDS) est. 40AC=6dmg if (IsClient()){ - switch (skill){ - - case SkillFlyingKick: - case SkillRoundKick: - case SkillKick: - item_slot = EQEmu::legacy::SlotFeet; - break; - - case SkillBash: - item_slot = EQEmu::legacy::SlotSecondary; - break; - - case SkillDragonPunch: - case SkillEagleStrike: - case SkillTigerClaw: - item_slot = EQEmu::legacy::SlotHands; - break; - - default: - break; + switch (skill) { + case EQEmu::skills::SkillFlyingKick: + case EQEmu::skills::SkillRoundKick: + case EQEmu::skills::SkillKick: + item_slot = EQEmu::legacy::SlotFeet; + break; + case EQEmu::skills::SkillBash: + item_slot = EQEmu::legacy::SlotSecondary; + break; + case EQEmu::skills::SkillDragonPunch: + case EQEmu::skills::SkillEagleStrike: + case EQEmu::skills::SkillTigerClaw: + item_slot = EQEmu::legacy::SlotHands; + break; + default: + break; } if (item_slot >= 0){ @@ -95,7 +91,7 @@ void Mob::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) } } -void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage, int32 hate_override,int ReuseTime, +void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool CheckHitChance, bool CanAvoid) { //this really should go through the same code as normal melee damage to //pick up all the special behavior there @@ -106,14 +102,14 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, if(who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE)) max_damage = -5; - if (who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE) && skill != SkillBackstab) + if (who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE) && skill != EQEmu::skills::SkillBackstab) max_damage = -5; uint32 hate = max_damage; if(hate_override > -1) hate = hate_override; - if(skill == SkillBash){ + if (skill == EQEmu::skills::SkillBash){ if(IsClient()){ ItemInst *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); if(item) @@ -134,7 +130,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, min_damage += min_damage * GetMeleeMinDamageMod_SE(skill) / 100; int hand = EQEmu::legacy::SlotPrimary; // Avoid checks hand for throwing/archery exclusion, primary should work for most - if (skill == SkillThrowing || skill == SkillArchery) + if (skill == EQEmu::skills::SkillThrowing || skill == EQEmu::skills::SkillArchery) hand = EQEmu::legacy::SlotRange; if (who->AvoidDamage(this, max_damage, hand)) { if (max_damage == -3) @@ -182,11 +178,11 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { pTimerType timer = pTimerCombatAbility; // RoF2+ Tiger Claw is unlinked from other monk skills, if they ever do that for other classes there will need // to be more checks here - if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF2 && ca_atk->m_skill == SkillTigerClaw) + if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF2 && ca_atk->m_skill == EQEmu::skills::SkillTigerClaw) timer = pTimerCombatAbility2; /* Check to see if actually have skill */ - if (!MaxSkill(static_cast(ca_atk->m_skill))) + if (!MaxSkill(static_cast(ca_atk->m_skill))) return; if(GetTarget()->GetID() != ca_atk->m_target) @@ -199,7 +195,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { //allready do their checking in conjunction with the attack timer //throwing weapons if (ca_atk->m_atk == EQEmu::legacy::SlotRange) { - if (ca_atk->m_skill == SkillThrowing) { + if (ca_atk->m_skill == EQEmu::skills::SkillThrowing) { SetAttackTimer(); ThrowingAttack(GetTarget()); if (CheckDoubleRangedAttack()) @@ -207,7 +203,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { return; } //ranged attack (archery) - if (ca_atk->m_skill == SkillArchery) { + if (ca_atk->m_skill == EQEmu::skills::SkillArchery) { SetAttackTimer(); RangedAttack(GetTarget()); if (CheckDoubleRangedAttack()) @@ -241,10 +237,10 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { int32 skill_reduction = this->GetSkillReuseTime(ca_atk->m_skill); // not sure what the '100' indicates..if ->m_atk is not used as 'slot' reference, then change SlotRange above back to '11' - if ((ca_atk->m_atk == 100) && (ca_atk->m_skill == SkillBash)) { // SLAM - Bash without a shield equipped + if ((ca_atk->m_atk == 100) && (ca_atk->m_skill == EQEmu::skills::SkillBash)) { // SLAM - Bash without a shield equipped if (GetTarget() != this) { - CheckIncreaseSkill(SkillBash, GetTarget(), 10); + CheckIncreaseSkill(EQEmu::skills::SkillBash, GetTarget(), 10); DoAnim(animTailRake); int32 ht = 0; @@ -253,7 +249,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { dmg = -5; } else{ - if(!GetTarget()->CheckHitChance(this, SkillBash, 0)) { + if (!GetTarget()->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) { dmg = 0; ht = GetBashDamage(); } @@ -268,7 +264,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { ReuseTime = BashReuseTime-1-skill_reduction; ReuseTime = (ReuseTime*HasteMod)/100; - DoSpecialAttackDamage(GetTarget(), SkillBash, dmg, 1, ht, ReuseTime); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillBash, dmg, 1, ht, ReuseTime); if(ReuseTime > 0) { p_timers.Start(timer, ReuseTime); @@ -277,10 +273,10 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { return; } - if ((ca_atk->m_atk == 100) && (ca_atk->m_skill == SkillFrenzy)){ - CheckIncreaseSkill(SkillFrenzy, GetTarget(), 10); + if ((ca_atk->m_atk == 100) && (ca_atk->m_skill == EQEmu::skills::SkillFrenzy)){ + CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10); int AtkRounds = 3; - int skillmod = 100*GetSkill(SkillFrenzy)/MaxSkill(SkillFrenzy); + int skillmod = 100 * GetSkill(EQEmu::skills::SkillFrenzy) / MaxSkill(EQEmu::skills::SkillFrenzy); int32 max_dmg = (26 + ((((GetLevel()-6) * 2)*skillmod)/100)) * ((100+RuleI(Combat, FrenzyBonus))/100); int32 min_dmg = 0; DoAnim(anim2HSlashing); @@ -301,7 +297,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { //Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit. while(AtkRounds > 0) { if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { - DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg , ReuseTime, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, min_dmg, max_dmg, ReuseTime, true); } AtkRounds--; } @@ -317,11 +313,11 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { case WARRIOR: case RANGER: case BEASTLORD: - if (ca_atk->m_atk != 100 || ca_atk->m_skill != SkillKick) { + if (ca_atk->m_atk != 100 || ca_atk->m_skill != EQEmu::skills::SkillKick) { break; } if (GetTarget() != this) { - CheckIncreaseSkill(SkillKick, GetTarget(), 10); + CheckIncreaseSkill(EQEmu::skills::SkillKick, GetTarget(), 10); DoAnim(animKick); int32 ht = 0; @@ -329,7 +325,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { dmg = -5; } else{ - if(!GetTarget()->CheckHitChance(this, SkillKick, 0)) { + if (!GetTarget()->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) { dmg = 0; ht = GetKickDamage(); } @@ -342,7 +338,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { } ReuseTime = KickReuseTime-1-skill_reduction; - DoSpecialAttackDamage(GetTarget(), SkillKick, dmg, 1, ht, ReuseTime); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillKick, dmg, 1, ht, ReuseTime); } break; @@ -353,7 +349,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; if (wuchance) { if (wuchance >= 100 || zone->random.Roll(wuchance)) { - int MonkSPA [5] = { SkillFlyingKick, SkillDragonPunch, SkillEagleStrike, SkillTigerClaw, SkillRoundKick }; + int MonkSPA[5] = { EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, EQEmu::skills::SkillRoundKick }; int extra = 1; // always 1/4 of the double attack chance, 25% at rank 5 (100/4) if (zone->random.Roll(wuchance / 4)) @@ -373,12 +369,12 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { //hackish... but we return a huge reuse time if this is an // invalid skill, otherwise, we can safely assume it is a // valid monk skill and just cast it to a SkillType - CheckIncreaseSkill((SkillUseTypes) ca_atk->m_skill, GetTarget(), 10); + CheckIncreaseSkill((EQEmu::skills::SkillType) ca_atk->m_skill, GetTarget(), 10); } break; } case ROGUE: { - if (ca_atk->m_atk != 100 || ca_atk->m_skill != SkillBackstab) { + if (ca_atk->m_atk != 100 || ca_atk->m_skill != EQEmu::skills::SkillBackstab) { break; } ReuseTime = BackstabReuseTime-1 - skill_reduction; @@ -407,68 +403,58 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) int32 max_dmg = 0; int32 min_dmg = 1; int reuse = 0; - SkillUseTypes skill_type; //to avoid casting... even though it "would work" + EQEmu::skills::SkillType skill_type; //to avoid casting... even though it "would work" uint8 itemslot = EQEmu::legacy::SlotFeet; - switch(unchecked_type){ - case SkillFlyingKick:{ - skill_type = SkillFlyingKick; - max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, FlyingKickBonus) / 100) + 35; - min_dmg = ((level*8)/10); - ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); - DoAnim(animFlyingKick); - reuse = FlyingKickReuseTime; - break; - } - case SkillDragonPunch:{ - skill_type = SkillDragonPunch; - max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, DragonPunchBonus) / 100) + 26; - itemslot = EQEmu::legacy::SlotHands; - ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); - DoAnim(animTailRake); - reuse = TailRakeReuseTime; - break; - } - - case SkillEagleStrike:{ - skill_type = SkillEagleStrike; - max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, EagleStrikeBonus) / 100) + 19; - itemslot = EQEmu::legacy::SlotHands; - ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); - DoAnim(animEagleStrike); - reuse = EagleStrikeReuseTime; - break; - } - - case SkillTigerClaw:{ - skill_type = SkillTigerClaw; - max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, TigerClawBonus) / 100) + 12; - itemslot = EQEmu::legacy::SlotHands; - ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); - DoAnim(animTigerClaw); - reuse = TigerClawReuseTime; - break; - } - - case SkillRoundKick:{ - skill_type = SkillRoundKick; - max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, RoundKickBonus) / 100) + 10; - ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); - DoAnim(animRoundKick); - reuse = RoundKickReuseTime; - break; - } - - case SkillKick:{ - skill_type = SkillKick; - max_dmg = GetKickDamage(); - DoAnim(animKick); - reuse = KickReuseTime; - break; - } - default: - Log.Out(Logs::Detail, Logs::Attack, "Invalid special attack type %d attempted", unchecked_type); - return(1000); /* nice long delay for them, the caller depends on this! */ + switch(unchecked_type) { + case EQEmu::skills::SkillFlyingKick: + skill_type = EQEmu::skills::SkillFlyingKick; + max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, FlyingKickBonus) / 100) + 35; + min_dmg = ((level*8)/10); + ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); + DoAnim(animFlyingKick); + reuse = FlyingKickReuseTime; + break; + case EQEmu::skills::SkillDragonPunch: + skill_type = EQEmu::skills::SkillDragonPunch; + max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, DragonPunchBonus) / 100) + 26; + itemslot = EQEmu::legacy::SlotHands; + ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); + DoAnim(animTailRake); + reuse = TailRakeReuseTime; + break; + case EQEmu::skills::SkillEagleStrike: + skill_type = EQEmu::skills::SkillEagleStrike; + max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, EagleStrikeBonus) / 100) + 19; + itemslot = EQEmu::legacy::SlotHands; + ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); + DoAnim(animEagleStrike); + reuse = EagleStrikeReuseTime; + break; + case EQEmu::skills::SkillTigerClaw: + skill_type = EQEmu::skills::SkillTigerClaw; + max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, TigerClawBonus) / 100) + 12; + itemslot = EQEmu::legacy::SlotHands; + ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); + DoAnim(animTigerClaw); + reuse = TigerClawReuseTime; + break; + case EQEmu::skills::SkillRoundKick: + skill_type = EQEmu::skills::SkillRoundKick; + max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, RoundKickBonus) / 100) + 10; + ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); + DoAnim(animRoundKick); + reuse = RoundKickReuseTime; + break; + case EQEmu::skills::SkillKick: + skill_type = EQEmu::skills::SkillKick; + max_dmg = GetKickDamage(); + DoAnim(animKick); + reuse = KickReuseTime; + break; + default: + Log.Out(Logs::Detail, Logs::Attack, "Invalid special attack type %d attempted", unchecked_type); + return(1000); /* nice long delay for them, the caller depends on this! */ } if(IsClient()){ @@ -550,7 +536,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { } if(IsClient()) - CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10); + CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillBackstab, other, 10); } //Live AA - Chaotic Backstab @@ -570,7 +556,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { } if(IsClient()) - CastToClient()->CheckIncreaseSkill(SkillBackstab, other, 10); + CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillBackstab, other, 10); } else { //We do a single regular attack if we attack from the front without chaotic stab Attack(other, EQEmu::legacy::SlotPrimary); @@ -613,12 +599,12 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) if(primaryweapondamage > 0){ if(level > 25){ - max_hit = (((((2*backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + ((level-25)/3) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); - hate = 20 * backstab_dmg * GetSkill(SkillBackstab) / 355; + max_hit = (((((2 * backstab_dmg) * GetDamageTable(EQEmu::skills::SkillBackstab) / 100) * 10 * GetSkill(EQEmu::skills::SkillBackstab) / 355) + ((level - 25) / 3) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); + hate = 20 * backstab_dmg * GetSkill(EQEmu::skills::SkillBackstab) / 355; } else{ - max_hit = (((((2*backstab_dmg) * GetDamageTable(SkillBackstab) / 100) * 10 * GetSkill(SkillBackstab) / 355) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); - hate = 20 * backstab_dmg * GetSkill(SkillBackstab) / 355; + max_hit = (((((2 * backstab_dmg) * GetDamageTable(EQEmu::skills::SkillBackstab) / 100) * 10 * GetSkill(EQEmu::skills::SkillBackstab) / 355) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); + hate = 20 * backstab_dmg * GetSkill(EQEmu::skills::SkillBackstab) / 355; } // determine minimum hits @@ -630,7 +616,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) min_hit = (level * ( level*5 - 105)) / 100; } - if(!other->CheckHitChance(this, SkillBackstab, 0)) { + if (!other->CheckHitChance(this, EQEmu::skills::SkillBackstab, 0)) { ndamage = 0; } else{ @@ -655,14 +641,14 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) ndamage = mod_backstab_damage(ndamage); uint32 Assassinate_Dmg = 0; - Assassinate_Dmg = TryAssassinate(other, SkillBackstab, ReuseTime); + Assassinate_Dmg = TryAssassinate(other, EQEmu::skills::SkillBackstab, ReuseTime); if (Assassinate_Dmg) { ndamage = Assassinate_Dmg; entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); } - DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime, false, false); + DoSpecialAttackDamage(other, EQEmu::skills::SkillBackstab, ndamage, min_hit, hate, ReuseTime, false, false); DoAnim(anim1HPiercing); } @@ -672,9 +658,9 @@ void Mob::RogueAssassinate(Mob* other) //can you dodge, parry, etc.. an assassinate?? //if so, use DoSpecialAttackDamage(other, BACKSTAB, 32000); instead if (GetWeaponDamage(other, IsClient() ? CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary) : (const ItemInst*)nullptr) > 0){ - other->Damage(this, 32000, SPELL_UNKNOWN, SkillBackstab); + other->Damage(this, 32000, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab); }else{ - other->Damage(this, -5, SPELL_UNKNOWN, SkillBackstab); + other->Damage(this, -5, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab); } DoAnim(anim1HPiercing); //piercing animation } @@ -807,7 +793,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { Log.Out(Logs::Detail, Logs::Combat, "Endless Quiver prevented ammo consumption."); } - CheckIncreaseSkill(SkillArchery, GetTarget(), -15); + CheckIncreaseSkill(EQEmu::skills::SkillArchery, GetTarget(), -15); CommonBreakInvisibleFromCombat(); } @@ -873,22 +859,22 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } } else if (AmmoItem) - SendItemAnimation(other, AmmoItem, SkillArchery); + SendItemAnimation(other, AmmoItem, EQEmu::skills::SkillArchery); - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillArchery, EQEmu::legacy::SlotPrimary, chance_mod))) { + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillArchery, EQEmu::legacy::SlotPrimary, chance_mod))) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ - TryProjectileAttack(other, AmmoItem, SkillArchery, 0, RangeWeapon, Ammo, AmmoSlot, speed); + TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillArchery, 0, RangeWeapon, Ammo, AmmoSlot, speed); return; } else - other->Damage(this, 0, SPELL_UNKNOWN, SkillArchery); + other->Damage(this, 0, SPELL_UNKNOWN, EQEmu::skills::SkillArchery); } else { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack hit %s.", other->GetName()); bool HeadShot = false; - uint32 HeadShot_Dmg = TryHeadShot(other, SkillArchery); + uint32 HeadShot_Dmg = TryHeadShot(other, EQEmu::skills::SkillArchery); if (HeadShot_Dmg) HeadShot = true; @@ -904,7 +890,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite WDmg = weapon_damage; if (LaunchProjectile){//1: Shoot the Projectile once we calculate weapon damage. - TryProjectileAttack(other, AmmoItem, SkillArchery, (WDmg + ADmg), RangeWeapon, Ammo, AmmoSlot, speed); + TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillArchery, (WDmg + ADmg), RangeWeapon, Ammo, AmmoSlot, speed); return; } @@ -916,7 +902,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite WDmg = 0; if(ADmg < 0) ADmg = 0; - uint32 MaxDmg = (RuleR(Combat, ArcheryBaseDamageBonus)*(WDmg+ADmg)*GetDamageTable(SkillArchery)) / 100; + uint32 MaxDmg = (RuleR(Combat, ArcheryBaseDamageBonus)*(WDmg + ADmg)*GetDamageTable(EQEmu::skills::SkillArchery)) / 100; hate = ((WDmg+ADmg)); if (HeadShot) @@ -968,7 +954,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite //twice, for ammo and weapon TotalDmg += (2*((GetLevel()-25)/3)); minDmg += (2*((GetLevel()-25)/3)); - minDmg += minDmg * GetMeleeMinDamageMod_SE(SkillArchery) / 100; + minDmg += minDmg * GetMeleeMinDamageMod_SE(EQEmu::skills::SkillArchery) / 100; hate += (2*((GetLevel()-25)/3)); } @@ -977,7 +963,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0){ - CommonOutgoingHitSuccess(other, TotalDmg, SkillArchery); + CommonOutgoingHitSuccess(other, TotalDmg, EQEmu::skills::SkillArchery); TotalDmg = mod_archery_damage(TotalDmg, dobonus, RangeWeapon); } } @@ -990,14 +976,14 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite if (IsClient() && !CastToClient()->GetFeigned()) other->AddToHateList(this, hate, 0, false); - other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillArchery); + other->Damage(this, TotalDmg, SPELL_UNKNOWN, EQEmu::skills::SkillArchery); //Skill Proc Success if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()){ if (ReuseTime) - TrySkillProc(other, SkillArchery, ReuseTime); + TrySkillProc(other, EQEmu::skills::SkillArchery, ReuseTime); else - TrySkillProc(other, SkillArchery, 0, true, EQEmu::legacy::SlotRange); + TrySkillProc(other, EQEmu::skills::SkillArchery, 0, true, EQEmu::legacy::SlotRange); } } @@ -1017,13 +1003,13 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite //Skill Proc if (HasSkillProcs() && other && !other->HasDied()){ if (ReuseTime) - TrySkillProc(other, SkillArchery, ReuseTime); + TrySkillProc(other, EQEmu::skills::SkillArchery, ReuseTime); else - TrySkillProc(other, SkillArchery, 0, false, EQEmu::legacy::SlotRange); + TrySkillProc(other, EQEmu::skills::SkillArchery, 0, false, EQEmu::legacy::SlotRange); } } -bool Mob::TryProjectileAttack(Mob* other, const EQEmu::Item_Struct *item, SkillUseTypes skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed){ +bool Mob::TryProjectileAttack(Mob* other, const EQEmu::Item_Struct *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed){ if (!other) return false; @@ -1108,21 +1094,21 @@ void Mob::ProjectileAttack() if (target){ if (IsNPC()){ - if (ProjectileAtk[i].skill == SkillConjuration){ + if (ProjectileAtk[i].skill == EQEmu::skills::SkillConjuration){ if (IsValidSpell(ProjectileAtk[i].wpn_dmg)) SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true); } else - CastToNPC()->DoRangedAttackDmg(target, false, ProjectileAtk[i].wpn_dmg,0, static_cast(ProjectileAtk[i].skill)); + CastToNPC()->DoRangedAttackDmg(target, false, ProjectileAtk[i].wpn_dmg, 0, static_cast(ProjectileAtk[i].skill)); } else { - if (ProjectileAtk[i].skill == SkillArchery) + if (ProjectileAtk[i].skill == EQEmu::skills::SkillArchery) DoArcheryAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0,ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_id, nullptr, ProjectileAtk[i].ammo_slot); - else if (ProjectileAtk[i].skill == SkillThrowing) + else if (ProjectileAtk[i].skill == EQEmu::skills::SkillThrowing) DoThrowingAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0, ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_slot); - else if (ProjectileAtk[i].skill == SkillConjuration && IsValidSpell(ProjectileAtk[i].wpn_dmg)) + else if (ProjectileAtk[i].skill == EQEmu::skills::SkillConjuration && IsValidSpell(ProjectileAtk[i].wpn_dmg)) SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true); } } @@ -1247,7 +1233,7 @@ void NPC::RangedAttack(Mob* other) } } -void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, SkillUseTypes skill, float speed, const char *IDFile) { +void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile) { if ((other == nullptr || (other->HasDied())) || @@ -1259,7 +1245,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha return; } - SkillUseTypes skillInUse = static_cast(GetRangedSkill()); + EQEmu::skills::SkillType skillInUse = static_cast(GetRangedSkill()); if (skill != skillInUse) skillInUse = skill; @@ -1334,7 +1320,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha } uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) { - uint16 MaxDmg = (((2 * wDmg) * GetDamageTable(SkillThrowing)) / 100); + uint16 MaxDmg = (((2 * wDmg) * GetDamageTable(EQEmu::skills::SkillThrowing)) / 100); if (MaxDmg == 0) MaxDmg = 1; @@ -1348,7 +1334,7 @@ uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) { if(GetLevel() > 25){ TotalDmg += ((GetLevel()-25)/3); minDmg += ((GetLevel()-25)/3); - minDmg += minDmg * GetMeleeMinDamageMod_SE(SkillThrowing) / 100; + minDmg += minDmg * GetMeleeMinDamageMod_SE(EQEmu::skills::SkillThrowing) / 100; } if(MaxDmg < minDmg) @@ -1438,7 +1424,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 //consume ammo DeleteItemInInventory(ammo_slot, 1, true); - CheckIncreaseSkill(SkillThrowing, GetTarget()); + CheckIncreaseSkill(EQEmu::skills::SkillThrowing, GetTarget()); CommonBreakInvisibleFromCombat(); } @@ -1491,16 +1477,16 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQE } } else if (AmmoItem) - SendItemAnimation(other, AmmoItem, SkillThrowing); + SendItemAnimation(other, AmmoItem, EQEmu::skills::SkillThrowing); - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, SkillThrowing, EQEmu::legacy::SlotPrimary, chance_mod))){ + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillThrowing, EQEmu::legacy::SlotPrimary, chance_mod))){ Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ - TryProjectileAttack(other, AmmoItem, SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot, speed); + TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot, speed); return; } else - other->Damage(this, 0, SPELL_UNKNOWN, SkillThrowing); + other->Damage(this, 0, SPELL_UNKNOWN, EQEmu::skills::SkillThrowing); } else { Log.Out(Logs::Detail, Logs::Combat, "Throwing attack hit %s.", other->GetName()); @@ -1513,7 +1499,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQE WDmg = GetWeaponDamage(other, AmmoItem); if (LaunchProjectile){ - TryProjectileAttack(other, AmmoItem, SkillThrowing, WDmg, RangeWeapon, nullptr, AmmoSlot, speed); + TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillThrowing, WDmg, RangeWeapon, nullptr, AmmoSlot, speed); return; } } @@ -1527,7 +1513,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQE uint32 Assassinate_Dmg = 0; if (GetClass() == ROGUE && (BehindMob(other, GetX(), GetY()))) - Assassinate_Dmg = TryAssassinate(other, SkillThrowing, ranged_timer.GetDuration()); + Assassinate_Dmg = TryAssassinate(other, EQEmu::skills::SkillThrowing, ranged_timer.GetDuration()); if(WDmg > 0){ int minDmg = 1; @@ -1544,7 +1530,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQE other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0) - CommonOutgoingHitSuccess(other, TotalDmg, SkillThrowing); + CommonOutgoingHitSuccess(other, TotalDmg, EQEmu::skills::SkillThrowing); } else @@ -1553,13 +1539,13 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQE if (IsClient() && !CastToClient()->GetFeigned()) other->AddToHateList(this, 2*WDmg, 0, false); - other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillThrowing); + other->Damage(this, TotalDmg, SPELL_UNKNOWN, EQEmu::skills::SkillThrowing); if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()){ if (ReuseTime) - TrySkillProc(other, SkillThrowing, ReuseTime); + TrySkillProc(other, EQEmu::skills::SkillThrowing, ReuseTime); else - TrySkillProc(other, SkillThrowing, 0, true, EQEmu::legacy::SlotRange); + TrySkillProc(other, EQEmu::skills::SkillThrowing, 0, true, EQEmu::legacy::SlotRange); } } @@ -1574,13 +1560,13 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQE if (HasSkillProcs() && other && !other->HasDied()){ if (ReuseTime) - TrySkillProc(other, SkillThrowing, ReuseTime); + TrySkillProc(other, EQEmu::skills::SkillThrowing, ReuseTime); else - TrySkillProc(other, SkillThrowing, 0, false, EQEmu::legacy::SlotRange); + TrySkillProc(other, EQEmu::skills::SkillThrowing, 0, false, EQEmu::legacy::SlotRange); } } -void Mob::SendItemAnimation(Mob *to, const EQEmu::Item_Struct *item, SkillUseTypes skillInUse, float velocity) { +void Mob::SendItemAnimation(Mob *to, const EQEmu::Item_Struct *item, EQEmu::skills::SkillType skillInUse, float velocity) { auto outapp = new EQApplicationPacket(OP_SomeItemPacketMaybe, sizeof(Arrow_Struct)); Arrow_Struct *as = (Arrow_Struct *) outapp->pBuffer; as->type = 1; @@ -1626,7 +1612,7 @@ void Mob::SendItemAnimation(Mob *to, const EQEmu::Item_Struct *item, SkillUseTyp safe_delete(outapp); } -void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, float angle, float tilt, float arc, const char *IDFile, SkillUseTypes skillInUse) { +void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, float angle, float tilt, float arc, const char *IDFile, EQEmu::skills::SkillType skillInUse) { if (!to) return; @@ -1753,12 +1739,12 @@ void NPC::DoClassAttacks(Mob *target) { } break; case MONK: case MONKGM: { - uint8 satype = SkillKick; - if(level > 29) { satype = SkillFlyingKick; } - else if(level > 24) { satype = SkillDragonPunch; } - else if(level > 19) { satype = SkillEagleStrike; } - else if(level > 9) { satype = SkillTigerClaw; } - else if(level > 4) { satype = SkillRoundKick; } + uint8 satype = EQEmu::skills::SkillKick; + if (level > 29) { satype = EQEmu::skills::SkillFlyingKick; } + else if (level > 24) { satype = EQEmu::skills::SkillDragonPunch; } + else if (level > 19) { satype = EQEmu::skills::SkillEagleStrike; } + else if (level > 9) { satype = EQEmu::skills::SkillTigerClaw; } + else if (level > 4) { satype = EQEmu::skills::SkillRoundKick; } reuse = MonkSpecialAttack(target, satype); reuse *= 1000; @@ -1775,7 +1761,7 @@ void NPC::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if(target->CheckHitChance(this, SkillKick, 0)) { + if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) { if(RuleB(Combat, UseIntervalAC)) dmg = GetKickDamage(); else @@ -1785,7 +1771,7 @@ void NPC::DoClassAttacks(Mob *target) { } reuse = (KickReuseTime + 3) * 1000; - DoSpecialAttackDamage(target, SkillKick, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, 1, -1, reuse); did_attack = true; } else { @@ -1796,7 +1782,7 @@ void NPC::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if(target->CheckHitChance(this, SkillBash, 0)) { + if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) { if(RuleB(Combat, UseIntervalAC)) dmg = GetBashDamage(); else @@ -1805,7 +1791,7 @@ void NPC::DoClassAttacks(Mob *target) { } reuse = (BashReuseTime + 3) * 1000; - DoSpecialAttackDamage(target, SkillBash, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, 1, -1, reuse); did_attack = true; } } @@ -1829,7 +1815,7 @@ void NPC::DoClassAttacks(Mob *target) { while(AtkRounds > 0) { if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { - DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, -1 , reuse, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, min_dmg, -1, reuse, true); } AtkRounds--; } @@ -1849,7 +1835,7 @@ void NPC::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if(target->CheckHitChance(this, SkillKick, 0)) { + if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) { if(RuleB(Combat, UseIntervalAC)) dmg = GetKickDamage(); else @@ -1858,7 +1844,7 @@ void NPC::DoClassAttacks(Mob *target) { } reuse = (KickReuseTime + 3) * 1000; - DoSpecialAttackDamage(target, SkillKick, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, 1, -1, reuse); did_attack = true; } break; @@ -1874,7 +1860,7 @@ void NPC::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if(target->CheckHitChance(this, SkillBash, 0)) { + if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) { if(RuleB(Combat, UseIntervalAC)) dmg = GetBashDamage(); else @@ -1883,7 +1869,7 @@ void NPC::DoClassAttacks(Mob *target) { } reuse = (BashReuseTime + 3) * 1000; - DoSpecialAttackDamage(target, SkillBash, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, 1, -1, reuse); did_attack = true; } break; @@ -1925,43 +1911,43 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) case WARRIOR: case RANGER: case BEASTLORD: - skill_to_use = SkillKick; + skill_to_use = EQEmu::skills::SkillKick; break; case BERSERKER: - skill_to_use = SkillFrenzy; + skill_to_use = EQEmu::skills::SkillFrenzy; break; case SHADOWKNIGHT: case PALADIN: - skill_to_use = SkillBash; + skill_to_use = EQEmu::skills::SkillBash; break; case MONK: if(GetLevel() >= 30) { - skill_to_use = SkillFlyingKick; + skill_to_use = EQEmu::skills::SkillFlyingKick; } else if(GetLevel() >= 25) { - skill_to_use = SkillDragonPunch; + skill_to_use = EQEmu::skills::SkillDragonPunch; } else if(GetLevel() >= 20) { - skill_to_use = SkillEagleStrike; + skill_to_use = EQEmu::skills::SkillEagleStrike; } else if(GetLevel() >= 10) { - skill_to_use = SkillTigerClaw; + skill_to_use = EQEmu::skills::SkillTigerClaw; } else if(GetLevel() >= 5) { - skill_to_use = SkillRoundKick; + skill_to_use = EQEmu::skills::SkillRoundKick; } else { - skill_to_use = SkillKick; + skill_to_use = EQEmu::skills::SkillKick; } break; case ROGUE: - skill_to_use = SkillBackstab; + skill_to_use = EQEmu::skills::SkillBackstab; break; } } @@ -1972,7 +1958,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if(skill_to_use == -1) return; - if(skill_to_use == SkillBash) { + if (skill_to_use == EQEmu::skills::SkillBash) { if (ca_target!=this) { DoAnim(animTailRake); @@ -1980,7 +1966,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) dmg = -5; } else{ - if(!ca_target->CheckHitChance(this, SkillBash, 0)) { + if (!ca_target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) { dmg = 0; } else{ @@ -1994,7 +1980,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) ReuseTime = (BashReuseTime - 1) / HasteMod; - DoSpecialAttackDamage(ca_target, SkillBash, dmg, 1,-1,ReuseTime); + DoSpecialAttackDamage(ca_target, EQEmu::skills::SkillBash, dmg, 1, -1, ReuseTime); if(ReuseTime > 0 && !IsRiposte) { p_timers.Start(pTimerCombatAbility, ReuseTime); @@ -2003,10 +1989,10 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) return; } - if(skill_to_use == SkillFrenzy){ - CheckIncreaseSkill(SkillFrenzy, GetTarget(), 10); + if (skill_to_use == EQEmu::skills::SkillFrenzy){ + CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10); int AtkRounds = 3; - int skillmod = 100*GetSkill(SkillFrenzy)/MaxSkill(SkillFrenzy); + int skillmod = 100 * GetSkill(EQEmu::skills::SkillFrenzy) / MaxSkill(EQEmu::skills::SkillFrenzy); int32 max_dmg = (26 + ((((GetLevel()-6) * 2)*skillmod)/100)) * ((100+RuleI(Combat, FrenzyBonus))/100); int32 min_dmg = 0; DoAnim(anim2HSlashing); @@ -2025,7 +2011,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) while(AtkRounds > 0) { if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { - DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, max_dmg , ReuseTime, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, min_dmg, max_dmg, ReuseTime, true); } AtkRounds--; } @@ -2036,7 +2022,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) return; } - if(skill_to_use == SkillKick){ + if (skill_to_use == EQEmu::skills::SkillKick){ if(ca_target!=this){ DoAnim(animKick); @@ -2044,7 +2030,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) dmg = -5; } else{ - if(!ca_target->CheckHitChance(this, SkillKick, 0)) { + if (!ca_target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) { dmg = 0; } else{ @@ -2057,11 +2043,11 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) ReuseTime = KickReuseTime-1; - DoSpecialAttackDamage(ca_target, SkillKick, dmg, 1,-1, ReuseTime); + DoSpecialAttackDamage(ca_target, EQEmu::skills::SkillKick, dmg, 1, -1, ReuseTime); } } - if(skill_to_use == SkillFlyingKick || skill_to_use == SkillDragonPunch || skill_to_use == SkillEagleStrike || skill_to_use == SkillTigerClaw || skill_to_use == SkillRoundKick) { + if (skill_to_use == EQEmu::skills::SkillFlyingKick || skill_to_use == EQEmu::skills::SkillDragonPunch || skill_to_use == EQEmu::skills::SkillEagleStrike || skill_to_use == EQEmu::skills::SkillTigerClaw || skill_to_use == EQEmu::skills::SkillRoundKick) { ReuseTime = MonkSpecialAttack(ca_target, skill_to_use) - 1; MonkSpecialAttack(ca_target, skill_to_use); @@ -2072,7 +2058,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; if (wuchance) { if (wuchance >= 100 || zone->random.Roll(wuchance)) { - int MonkSPA [5] = { SkillFlyingKick, SkillDragonPunch, SkillEagleStrike, SkillTigerClaw, SkillRoundKick }; + int MonkSPA[5] = { EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, EQEmu::skills::SkillRoundKick }; int extra = 1; if (zone->random.Roll(wuchance / 4)) extra++; @@ -2088,7 +2074,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) } } - if(skill_to_use == SkillBackstab){ + if (skill_to_use == EQEmu::skills::SkillBackstab){ ReuseTime = BackstabReuseTime-1; if (IsRiposte) @@ -2115,7 +2101,7 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus, bool FromSpel return; if(!always_succeed && IsClient()) - CastToClient()->CheckIncreaseSkill(SkillTaunt, who, 10); + CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillTaunt, who, 10); Mob *hate_top = who->GetHateMost(); @@ -2154,7 +2140,7 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus, bool FromSpel //TauntSkillFalloff rate is not based on any real data. Default of 33% gives a reasonable result. if (IsClient() && !always_succeed) - tauntchance -= (RuleR(Combat,TauntSkillFalloff) * (CastToClient()->MaxSkill(SkillTaunt) - GetSkill(SkillTaunt))); + tauntchance -= (RuleR(Combat, TauntSkillFalloff) * (CastToClient()->MaxSkill(EQEmu::skills::SkillTaunt) - GetSkill(EQEmu::skills::SkillTaunt))); //From SE_Taunt (Does a taunt with a chance modifier) if (chance_bonus) @@ -2186,10 +2172,10 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus, bool FromSpel Message_StringID(MT_SpellFailure,FAILED_TAUNT); if (HasSkillProcs()) - TrySkillProc(who, SkillTaunt, TauntReuseTime*1000); + TrySkillProc(who, EQEmu::skills::SkillTaunt, TauntReuseTime * 1000); if (Success && HasSkillProcSuccess()) - TrySkillProc(who, SkillTaunt, TauntReuseTime*1000, true); + TrySkillProc(who, EQEmu::skills::SkillTaunt, TauntReuseTime * 1000, true); } @@ -2209,14 +2195,14 @@ void Mob::InstillDoubt(Mob *who) { return; if(IsClient()) { - CastToClient()->CheckIncreaseSkill(SkillIntimidation, who, 10); + CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillIntimidation, who, 10); } //I think this formula needs work int value = 0; //user's bonus - value += GetSkill(SkillIntimidation) + GetCHA()/4; + value += GetSkill(EQEmu::skills::SkillIntimidation) + GetCHA() / 4; //target's counters value -= target->GetLevel()*4 + who->GetWIS()/4; @@ -2238,10 +2224,10 @@ void Mob::InstillDoubt(Mob *who) { } } -uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) { +uint32 Mob::TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse) { //Only works on YOUR target. if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() - && (skillInUse == SkillArchery) && (GetTarget() == defender)) { + && (skillInUse == EQEmu::skills::SkillArchery) && (GetTarget() == defender)) { uint32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1]; uint8 HeadShot_Level = 0; //Get Highest Headshot Level @@ -2289,10 +2275,10 @@ float Mob::GetSpecialProcChances(uint16 hand) return ProcChance; } -uint32 Mob::TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 ReuseTime) { +uint32 Mob::TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, uint16 ReuseTime) { if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() && - (skillInUse == SkillBackstab || skillInUse == SkillThrowing)) { + (skillInUse == EQEmu::skills::SkillBackstab || skillInUse == EQEmu::skills::SkillThrowing)) { uint32 Assassinate_Dmg = aabonuses.Assassinate[1] + spellbonuses.Assassinate[1] + itembonuses.Assassinate[1]; @@ -2314,7 +2300,7 @@ uint32 Mob::TryAssassinate(Mob* defender, SkillUseTypes skillInUse, uint16 Reuse if(Assassinate_Dmg && Assassinate_Level && (defender->GetLevel() <= Assassinate_Level)){ float ProcChance = 0.0f; - if (skillInUse == SkillThrowing) + if (skillInUse == EQEmu::skills::SkillThrowing) ProcChance = GetSpecialProcChances(EQEmu::legacy::SlotRange); else ProcChance = GetAssassinateProcChances(ReuseTime); @@ -2352,7 +2338,7 @@ float Mob::GetAssassinateProcChances(uint16 ReuseTime) return ProcChance; } -void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime) +void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime) { if (!CanDoSpecialAttack(other)) return; @@ -2361,8 +2347,8 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes For spells using skill value 98 (feral swipe ect) server sets this to 67 automatically. Kayen: This is unlikely to be completely accurate but use OFFENSE skill value for these effects. */ - if (skillinuse == SkillBegging) - skillinuse = SkillOffense; + if (skillinuse == EQEmu::skills::SkillBegging) + skillinuse = EQEmu::skills::SkillOffense; int damage = 0; uint32 hate = 0; @@ -2388,7 +2374,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes hate += ucDamageBonus; } - if(skillinuse == SkillBash){ + if (skillinuse == EQEmu::skills::SkillBash){ if(IsClient()){ ItemInst *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); if(item){ @@ -2433,8 +2419,8 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes damage = -5; bool CanSkillProc = true; - if (skillinuse == SkillOffense){ //Hack to allow damage to display. - skillinuse = SkillTigerClaw; //'strike' your opponent - Arbitrary choice for message. + if (skillinuse == EQEmu::skills::SkillOffense){ //Hack to allow damage to display. + skillinuse = EQEmu::skills::SkillTigerClaw; //'strike' your opponent - Arbitrary choice for message. CanSkillProc = false; //Disable skill procs } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 35d1c64bd..6508d6fc6 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2271,18 +2271,15 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove focus = caster->GetFocusEffect(focusFcBaseEffects, spell_id); - switch(spells[spell_id].skill) - { - case SkillThrowing: - caster->DoThrowingAttackDmg(this, nullptr, nullptr, spells[spell_id].base[i],spells[spell_id].base2[i], focus, ReuseTime); + switch(spells[spell_id].skill) { + case EQEmu::skills::SkillThrowing: + caster->DoThrowingAttackDmg(this, nullptr, nullptr, spells[spell_id].base[i],spells[spell_id].base2[i], focus, ReuseTime); break; - - case SkillArchery: - caster->DoArcheryAttackDmg(this, nullptr, nullptr, spells[spell_id].base[i],spells[spell_id].base2[i],focus, ReuseTime); + case EQEmu::skills::SkillArchery: + caster->DoArcheryAttackDmg(this, nullptr, nullptr, spells[spell_id].base[i],spells[spell_id].base2[i],focus, ReuseTime); break; - - default: - caster->DoMeleeSkillAttackDmg(this, spells[spell_id].base[i], spells[spell_id].skill, spells[spell_id].base2[i], focus, false, ReuseTime); + default: + caster->DoMeleeSkillAttackDmg(this, spells[spell_id].base[i], spells[spell_id].skill, spells[spell_id].base2[i], focus, false, ReuseTime); break; } break; @@ -3046,7 +3043,7 @@ int Mob::CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level, effect_value = CalcSpellEffectValue_formula(formula, base, max, caster_level, spell_id, ticsremaining); // this doesn't actually need to be a song to get mods, just the right skill - if (EQEmu::IsBardInstrumentSkill(spells[spell_id].skill) && + if (EQEmu::skills::IsBardInstrumentSkill(spells[spell_id].skill) && spells[spell_id].effectid[effect_id] != SE_AttackSpeed && spells[spell_id].effectid[effect_id] != SE_AttackSpeed2 && spells[spell_id].effectid[effect_id] != SE_AttackSpeed3 && @@ -3613,13 +3610,13 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) if (!IsBardSong(buff.spellid)) { double break_chance = 2.0; if (caster) { - break_chance -= (2 * (((double)caster->GetSkill(SkillDivination) + + break_chance -= (2 * (((double)caster->GetSkill(EQEmu::skills::SkillDivination) + ((double)caster->GetLevel() * 3.0)) / 650.0)); } else { break_chance -= (2 * - (((double)GetSkill(SkillDivination) + ((double)GetLevel() * 3.0)) / + (((double)GetSkill(EQEmu::skills::SkillDivination) + ((double)GetLevel() * 3.0)) / 650.0)); } @@ -6564,7 +6561,7 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed){ ProjectileAtk[slot].origin_x = GetX(); ProjectileAtk[slot].origin_y = GetY(); ProjectileAtk[slot].origin_z = GetZ(); - ProjectileAtk[slot].skill = SkillConjuration; + ProjectileAtk[slot].skill = EQEmu::skills::SkillConjuration; ProjectileAtk[slot].speed_mod = speed_mod; SetProjectileAttack(true); @@ -6619,7 +6616,7 @@ void Mob::ResourceTap(int32 damage, uint16 spellid) if (damage > 0) HealDamage(damage); else - Damage(this, -damage, 0, SkillEvocation, false); + Damage(this, -damage, 0, EQEmu::skills::SkillEvocation, false); } if (spells[spellid].base2[i] == 1) // Mana Tap diff --git a/zone/spells.cpp b/zone/spells.cpp index f4eb422cb..c48baa00d 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -556,16 +556,16 @@ bool Mob::DoCastingChecks() uint16 Mob::GetSpecializeSkillValue(uint16 spell_id) const { switch(spells[spell_id].skill) { - case SkillAbjuration: - return(GetSkill(SkillSpecializeAbjure)); - case SkillAlteration: - return(GetSkill(SkillSpecializeAlteration)); - case SkillConjuration: - return(GetSkill(SkillSpecializeConjuration)); - case SkillDivination: - return(GetSkill(SkillSpecializeDivination)); - case SkillEvocation: - return(GetSkill(SkillSpecializeEvocation)); + case EQEmu::skills::SkillAbjuration: + return(GetSkill(EQEmu::skills::SkillSpecializeAbjure)); + case EQEmu::skills::SkillAlteration: + return(GetSkill(EQEmu::skills::SkillSpecializeAlteration)); + case EQEmu::skills::SkillConjuration: + return(GetSkill(EQEmu::skills::SkillSpecializeConjuration)); + case EQEmu::skills::SkillDivination: + return(GetSkill(EQEmu::skills::SkillSpecializeDivination)); + case EQEmu::skills::SkillEvocation: + return(GetSkill(EQEmu::skills::SkillSpecializeEvocation)); default: //wtf... break; @@ -584,20 +584,20 @@ void Client::CheckSpecializeIncrease(uint16 spell_id) { */ switch(spells[spell_id].skill) { - case SkillAbjuration: - CheckIncreaseSkill(SkillSpecializeAbjure, nullptr); + case EQEmu::skills::SkillAbjuration: + CheckIncreaseSkill(EQEmu::skills::SkillSpecializeAbjure, nullptr); break; - case SkillAlteration: - CheckIncreaseSkill(SkillSpecializeAlteration, nullptr); + case EQEmu::skills::SkillAlteration: + CheckIncreaseSkill(EQEmu::skills::SkillSpecializeAlteration, nullptr); break; - case SkillConjuration: - CheckIncreaseSkill(SkillSpecializeConjuration, nullptr); + case EQEmu::skills::SkillConjuration: + CheckIncreaseSkill(EQEmu::skills::SkillSpecializeConjuration, nullptr); break; - case SkillDivination: - CheckIncreaseSkill(SkillSpecializeDivination, nullptr); + case EQEmu::skills::SkillDivination: + CheckIncreaseSkill(EQEmu::skills::SkillSpecializeDivination, nullptr); break; - case SkillEvocation: - CheckIncreaseSkill(SkillSpecializeEvocation, nullptr); + case EQEmu::skills::SkillEvocation: + CheckIncreaseSkill(EQEmu::skills::SkillSpecializeEvocation, nullptr); break; default: //wtf... @@ -617,48 +617,48 @@ void Client::CheckSongSkillIncrease(uint16 spell_id){ switch(spells[spell_id].skill) { - case SkillSinging: - CheckIncreaseSkill(SkillSinging, nullptr, -15); + case EQEmu::skills::SkillSinging: + CheckIncreaseSkill(EQEmu::skills::SkillSinging, nullptr, -15); break; - case SkillPercussionInstruments: + case EQEmu::skills::SkillPercussionInstruments: if(this->itembonuses.percussionMod > 0) { - if(GetRawSkill(SkillPercussionInstruments) > 0) // no skill increases if not trained in the instrument - CheckIncreaseSkill(SkillPercussionInstruments, nullptr, -15); + if (GetRawSkill(EQEmu::skills::SkillPercussionInstruments) > 0) // no skill increases if not trained in the instrument + CheckIncreaseSkill(EQEmu::skills::SkillPercussionInstruments, nullptr, -15); else Message_StringID(13,NO_INSTRUMENT_SKILL); // tell the client that they need instrument training } else - CheckIncreaseSkill(SkillSinging, nullptr, -15); + CheckIncreaseSkill(EQEmu::skills::SkillSinging, nullptr, -15); break; - case SkillStringedInstruments: + case EQEmu::skills::SkillStringedInstruments: if(this->itembonuses.stringedMod > 0) { - if(GetRawSkill(SkillStringedInstruments) > 0) - CheckIncreaseSkill(SkillStringedInstruments, nullptr, -15); + if (GetRawSkill(EQEmu::skills::SkillStringedInstruments) > 0) + CheckIncreaseSkill(EQEmu::skills::SkillStringedInstruments, nullptr, -15); else Message_StringID(13,NO_INSTRUMENT_SKILL); } else - CheckIncreaseSkill(SkillSinging, nullptr, -15); + CheckIncreaseSkill(EQEmu::skills::SkillSinging, nullptr, -15); break; - case SkillWindInstruments: + case EQEmu::skills::SkillWindInstruments: if(this->itembonuses.windMod > 0) { - if(GetRawSkill(SkillWindInstruments) > 0) - CheckIncreaseSkill(SkillWindInstruments, nullptr, -15); + if (GetRawSkill(EQEmu::skills::SkillWindInstruments) > 0) + CheckIncreaseSkill(EQEmu::skills::SkillWindInstruments, nullptr, -15); else Message_StringID(13,NO_INSTRUMENT_SKILL); } else - CheckIncreaseSkill(SkillSinging, nullptr, -15); + CheckIncreaseSkill(EQEmu::skills::SkillSinging, nullptr, -15); break; - case SkillBrassInstruments: + case EQEmu::skills::SkillBrassInstruments: if(this->itembonuses.brassMod > 0) { - if(GetRawSkill(SkillBrassInstruments) > 0) - CheckIncreaseSkill(SkillBrassInstruments, nullptr, -15); + if (GetRawSkill(EQEmu::skills::SkillBrassInstruments) > 0) + CheckIncreaseSkill(EQEmu::skills::SkillBrassInstruments, nullptr, -15); else Message_StringID(13,NO_INSTRUMENT_SKILL); } else - CheckIncreaseSkill(SkillSinging, nullptr, -15); + CheckIncreaseSkill(EQEmu::skills::SkillSinging, nullptr, -15); break; default: break; @@ -991,7 +991,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, channelbonuses += spellbonuses.ChannelChanceSpells + itembonuses.ChannelChanceSpells + aabonuses.ChannelChanceSpells; // max 93% chance at 252 skill - channelchance = 30 + GetSkill(SkillChanneling) / 400.0f * 100; + channelchance = 30 + GetSkill(EQEmu::skills::SkillChanneling) / 400.0f * 100; channelchance -= attacked_count * 2; channelchance += channelchance * channelbonuses / 100.0f; } @@ -1005,7 +1005,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, channelbonuses += spellbonuses.ChannelChanceSpells + itembonuses.ChannelChanceSpells + aabonuses.ChannelChanceSpells; // max 93% chance at 252 skill - channelchance = 30 + GetSkill(SkillChanneling) / 400.0f * 100; + channelchance = 30 + GetSkill(EQEmu::skills::SkillChanneling) / 400.0f * 100; channelchance -= attacked_count * 2; channelchance += channelchance * channelbonuses / 100.0f; } @@ -1037,7 +1037,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, } } - Log.Out(Logs::Detail, Logs::Spells, "Checking Interruption: spell x: %f spell y: %f cur x: %f cur y: %f channelchance %f channeling skill %d\n", GetSpellX(), GetSpellY(), GetX(), GetY(), channelchance, GetSkill(SkillChanneling)); + Log.Out(Logs::Detail, Logs::Spells, "Checking Interruption: spell x: %f spell y: %f cur x: %f cur y: %f channelchance %f channeling skill %d\n", GetSpellX(), GetSpellY(), GetX(), GetY(), channelchance, GetSkill(EQEmu::skills::SkillChanneling)); if(!spells[spell_id].uninterruptable && zone->random.Real(0, 100) > channelchance) { Log.Out(Logs::Detail, Logs::Spells, "Casting of %d canceled: interrupted.", spell_id); @@ -1330,7 +1330,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, c->CheckIncreaseSkill(spells[spell_id].skill, nullptr); // increased chance of gaining channel skill if you regained concentration - c->CheckIncreaseSkill(SkillChanneling, nullptr, regain_conc ? 5 : 0); + c->CheckIncreaseSkill(EQEmu::skills::SkillChanneling, nullptr, regain_conc ? 5 : 0); c->CheckSpecializeIncrease(spell_id); } diff --git a/zone/tasks.cpp b/zone/tasks.cpp index fb5c867c9..0fc22dffa 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -29,6 +29,7 @@ Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net) #include "../common/misc_functions.h" #include "../common/rulesys.h" #include "../common/string_util.h" +#include "../common/say_link.h" #include "client.h" #include "entity.h" diff --git a/zone/titles.cpp b/zone/titles.cpp index 1e0cc7cb7..388f12997 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -46,7 +46,7 @@ bool TitleManager::LoadTitles() for (auto row = results.begin(); row != results.end(); ++row) { TitleEntry Title; Title.TitleID = atoi(row[0]); - Title.SkillID = (SkillUseTypes) atoi(row[1]); + Title.SkillID = (EQEmu::skills::SkillType) atoi(row[1]); Title.MinSkillValue = atoi(row[2]); Title.MaxSkillValue = atoi(row[3]); Title.MinAAPoints = atoi(row[4]); @@ -187,10 +187,10 @@ bool TitleManager::IsClientEligibleForTitle(Client *c, std::vector:: if(Title->SkillID >= 0) { - if((Title->MinSkillValue >= 0) && (c->GetRawSkill(static_cast(Title->SkillID)) < static_cast(Title->MinSkillValue))) + if ((Title->MinSkillValue >= 0) && (c->GetRawSkill(static_cast(Title->SkillID)) < static_cast(Title->MinSkillValue))) return false; - if((Title->MaxSkillValue >= 0) && (c->GetRawSkill(static_cast(Title->SkillID)) > static_cast(Title->MaxSkillValue))) + if ((Title->MaxSkillValue >= 0) && (c->GetRawSkill(static_cast(Title->SkillID)) > static_cast(Title->MaxSkillValue))) return false; } diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 2a3a3cdfe..6c0dc667a 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -36,7 +36,7 @@ extern QueryServ* QServ; -static const SkillUseTypes TradeskillUnknown = Skill1HBlunt; /* an arbitrary non-tradeskill */ +static const EQEmu::skills::SkillType TradeskillUnknown = EQEmu::skills::Skill1HBlunt; /* an arbitrary non-tradeskill */ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augment, Object *worldo) { @@ -363,7 +363,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob } //changing from a switch to string of if's since we don't need to iterate through all of the skills in the SkillType enum - if (spec.tradeskill == SkillAlchemy) { + if (spec.tradeskill == EQEmu::skills::SkillAlchemy) { if (user_pp.class_ != SHAMAN) { user->Message(13, "This tradeskill can only be performed by a shaman."); return; @@ -373,13 +373,13 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob return; } } - else if (spec.tradeskill == SkillTinkering) { + else if (spec.tradeskill == EQEmu::skills::SkillTinkering) { if (user_pp.race != GNOME) { user->Message(13, "Only gnomes can tinker."); return; } } - else if (spec.tradeskill == SkillMakePoison) { + else if (spec.tradeskill == EQEmu::skills::SkillMakePoison) { if (user_pp.class_ != ROGUE) { user->Message(13, "Only rogues can mix poisons."); return; @@ -604,17 +604,17 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac parse->EventPlayer(EVENT_COMBINE_FAILURE, user, spec.name.c_str(), spec.recipe_id); } -SkillUseTypes Object::TypeToSkill(uint32 type) +EQEmu::skills::SkillType Object::TypeToSkill(uint32 type) { switch(type) { // grouped and ordered by SkillUseTypes name - new types need to be verified for proper SkillUseTypes and use /*SkillAlchemy*/ case EQEmu::item::BagTypeMedicineBag: - return SkillAlchemy; + return EQEmu::skills::SkillAlchemy; /*SkillBaking*/ //case EQEmu::item::BagTypeMixingBowl: // No idea... case EQEmu::item::BagTypeOven: - return SkillBaking; + return EQEmu::skills::SkillBaking; /*SkillBlacksmithing*/ case EQEmu::item::BagTypeForge: @@ -632,25 +632,25 @@ SkillUseTypes Object::TypeToSkill(uint32 type) case EQEmu::item::BagTypeValeForge: //case EQEmu::item::BagTypeErudForge: //case EQEmu::item::BagTypeGuktaForge: - return SkillBlacksmithing; + return EQEmu::skills::SkillBlacksmithing; /*SkillBrewing*/ //case EQEmu::item::BagTypeIceCreamChurn: // No idea... case EQEmu::item::BagTypeBrewBarrel: - return SkillBrewing; + return EQEmu::skills::SkillBrewing; /*SkillFishing*/ case EQEmu::item::BagTypeTackleBox: - return SkillFishing; + return EQEmu::skills::SkillFishing; /*SkillFletching*/ case EQEmu::item::BagTypeFletchingKit: //case EQEmu::item::BagTypeFierDalFletchingKit: - return SkillFletching; + return EQEmu::skills::SkillFletching; /*SkillJewelryMaking*/ case EQEmu::item::BagTypeJewelersKit: - return SkillJewelryMaking; + return EQEmu::skills::SkillJewelryMaking; /*SkillMakePoison*/ // This is a guess and needs to be verified... (Could be SkillAlchemy) @@ -661,7 +661,7 @@ SkillUseTypes Object::TypeToSkill(uint32 type) case EQEmu::item::BagTypePotteryWheel: case EQEmu::item::BagTypeKiln: //case EQEmu::item::BagTypeIksarPotteryWheel: - return SkillPottery; + return EQEmu::skills::SkillPottery; /*SkillResearch*/ //case EQEmu::item::BagTypeLexicon: @@ -670,18 +670,18 @@ SkillUseTypes Object::TypeToSkill(uint32 type) case EQEmu::item::BagTypeNecromancersLexicon: case EQEmu::item::BagTypeEnchantersLexicon: //case EQEmu::item::BagTypeConcordanceofResearch: - return SkillResearch; + return EQEmu::skills::SkillResearch; /*SkillTailoring*/ case EQEmu::item::BagTypeSewingKit: //case EQEmu::item::BagTypeHalflingTailoringKit: //case EQEmu::item::BagTypeErudTailoringKit: //case EQEmu::item::BagTypeFierDalTailoringKit: - return SkillTailoring; + return EQEmu::skills::SkillTailoring; /*SkillTinkering*/ case EQEmu::item::BagTypeToolBox: - return SkillTinkering; + return EQEmu::skills::SkillTinkering; /*Undefined*/ default: @@ -718,7 +718,7 @@ void Client::TradeskillSearchResults(const std::string &query, unsigned long obj // Recipes that have either been made before or were // explicitly learned are excempt from that limit if (RuleB(Skills, UseLimitTradeskillSearchSkillDiff) - && ((int32)trivial - (int32)GetSkill((SkillUseTypes)tradeskill)) > RuleI(Skills, MaxTradeskillSearchSkillDiff) + && ((int32)trivial - (int32)GetSkill((EQEmu::skills::SkillType)tradeskill)) > RuleI(Skills, MaxTradeskillSearchSkillDiff) && row[4] == nullptr) continue; @@ -866,49 +866,50 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { // Some tradeskills are more eqal then others. ;-) // If you want to customize the stage1 success rate do it here. // Remember: skillup_modifier is (float). Lower is better - switch(spec->tradeskill) { - case SkillFletching: - skillup_modifier = RuleI(Character, TradeskillUpFletching); - break; - case SkillAlchemy: - skillup_modifier = RuleI(Character, TradeskillUpAlchemy); - break; - case SkillJewelryMaking: - skillup_modifier = RuleI(Character, TradeskillUpJewelcrafting); - break; - case SkillPottery: - skillup_modifier = RuleI(Character, TradeskillUpPottery); - break; - case SkillBaking: - skillup_modifier = RuleI(Character, TradeskillUpBaking); - break; - case SkillBrewing: - skillup_modifier = RuleI(Character, TradeskillUpBrewing); - break; - case SkillBlacksmithing: - skillup_modifier = RuleI(Character, TradeskillUpBlacksmithing); - break; - case SkillResearch: - skillup_modifier = RuleI(Character, TradeskillUpResearch); - break; - case SkillMakePoison: - skillup_modifier = RuleI(Character, TradeskillUpMakePoison); - break; - case SkillTinkering: - skillup_modifier = RuleI(Character, TradeskillUpTinkering); - break; - default: - skillup_modifier = 2; - break; - } + switch(spec->tradeskill) { + case EQEmu::skills::SkillFletching: + skillup_modifier = RuleI(Character, TradeskillUpFletching); + break; + case EQEmu::skills::SkillAlchemy: + skillup_modifier = RuleI(Character, TradeskillUpAlchemy); + break; + case EQEmu::skills::SkillJewelryMaking: + skillup_modifier = RuleI(Character, TradeskillUpJewelcrafting); + break; + case EQEmu::skills::SkillPottery: + skillup_modifier = RuleI(Character, TradeskillUpPottery); + break; + case EQEmu::skills::SkillBaking: + skillup_modifier = RuleI(Character, TradeskillUpBaking); + break; + case EQEmu::skills::SkillBrewing: + skillup_modifier = RuleI(Character, TradeskillUpBrewing); + break; + case EQEmu::skills::SkillBlacksmithing: + skillup_modifier = RuleI(Character, TradeskillUpBlacksmithing); + break; + case EQEmu::skills::SkillResearch: + skillup_modifier = RuleI(Character, TradeskillUpResearch); + break; + case EQEmu::skills::SkillMakePoison: + skillup_modifier = RuleI(Character, TradeskillUpMakePoison); + break; + case EQEmu::skills::SkillTinkering: + skillup_modifier = RuleI(Character, TradeskillUpTinkering); + break; + default: + skillup_modifier = 2; + break; + } // Some tradeskills take the higher of one additional stat beside INT and WIS // to determine the skillup rate. Additionally these tradeskills do not have an // -15 modifier on their statbonus. - if (spec->tradeskill == SkillFletching || spec->tradeskill == SkillMakePoison) { + if (spec->tradeskill == EQEmu::skills::SkillFletching || spec->tradeskill == EQEmu::skills::SkillMakePoison) { thirdstat = GetDEX(); stat_modifier = 0; - } else if (spec->tradeskill == SkillBlacksmithing) { + } + else if (spec->tradeskill == EQEmu::skills::SkillBlacksmithing) { thirdstat = GetSTR(); stat_modifier = 0; } @@ -1045,7 +1046,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { return(false); } -void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float skillup_modifier, uint16 success_modifier, SkillUseTypes tradeskill) +void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float skillup_modifier, uint16 success_modifier, EQEmu::skills::SkillType tradeskill) { uint16 current_raw_skill = GetRawSkill(tradeskill); @@ -1290,7 +1291,7 @@ bool ZoneDatabase::GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id return false;//just not found i guess.. auto row = results.begin(); - spec->tradeskill = (SkillUseTypes)atoi(row[1]); + spec->tradeskill = (EQEmu::skills::SkillType)atoi(row[1]); spec->skill_needed = (int16)atoi(row[2]); spec->trivial = (uint16)atoi(row[3]); spec->nofail = atoi(row[4]) ? true : false; @@ -1406,43 +1407,43 @@ void Client::LearnRecipe(uint32 recipeID) results = database.QueryDatabase(query); } -bool Client::CanIncreaseTradeskill(SkillUseTypes tradeskill) { +bool Client::CanIncreaseTradeskill(EQEmu::skills::SkillType tradeskill) { uint32 rawskill = GetRawSkill(tradeskill); uint16 maxskill = MaxSkill(tradeskill); if (rawskill >= maxskill) //Max skill sanity check return false; - uint8 Baking = (GetRawSkill(SkillBaking) > 200) ? 1 : 0; - uint8 Smithing = (GetRawSkill(SkillBlacksmithing) > 200) ? 1 : 0; - uint8 Brewing = (GetRawSkill(SkillBrewing) > 200) ? 1 : 0; - uint8 Fletching = (GetRawSkill(SkillFletching) > 200) ? 1 : 0; - uint8 Jewelry = (GetRawSkill(SkillJewelryMaking) > 200) ? 1 : 0; - uint8 Pottery = (GetRawSkill(SkillPottery) > 200) ? 1 : 0; - uint8 Tailoring = (GetRawSkill(SkillTailoring) > 200) ? 1 : 0; + uint8 Baking = (GetRawSkill(EQEmu::skills::SkillBaking) > 200) ? 1 : 0; + uint8 Smithing = (GetRawSkill(EQEmu::skills::SkillBlacksmithing) > 200) ? 1 : 0; + uint8 Brewing = (GetRawSkill(EQEmu::skills::SkillBrewing) > 200) ? 1 : 0; + uint8 Fletching = (GetRawSkill(EQEmu::skills::SkillFletching) > 200) ? 1 : 0; + uint8 Jewelry = (GetRawSkill(EQEmu::skills::SkillJewelryMaking) > 200) ? 1 : 0; + uint8 Pottery = (GetRawSkill(EQEmu::skills::SkillPottery) > 200) ? 1 : 0; + uint8 Tailoring = (GetRawSkill(EQEmu::skills::SkillTailoring) > 200) ? 1 : 0; uint8 SkillTotal = Baking + Smithing + Brewing + Fletching + Jewelry + Pottery + Tailoring; //Tradeskills above 200 //New Tanaan AA: Each level allows an additional tradeskill above 200 (first one is free) uint8 aaLevel = spellbonuses.TradeSkillMastery + itembonuses.TradeSkillMastery + aabonuses.TradeSkillMastery; switch (tradeskill) { - case SkillBaking: - case SkillBlacksmithing: - case SkillBrewing: - case SkillFletching: - case SkillJewelryMaking: - case SkillPottery: - case SkillTailoring: - if (aaLevel == 6) - break; //Maxed AA - if (SkillTotal == 0) - break; //First tradeskill freebie - if ((SkillTotal == (aaLevel + 1)) && (rawskill > 200)) - break; //One of the tradeskills already allowed to go over 200 - if ((SkillTotal >= (aaLevel + 1)) && (rawskill >= 200)) - return false; //One or more tradeskills already at or beyond limit - break; - default: - break; //Other skills unchecked and ability to increase assumed true + case EQEmu::skills::SkillBaking: + case EQEmu::skills::SkillBlacksmithing: + case EQEmu::skills::SkillBrewing: + case EQEmu::skills::SkillFletching: + case EQEmu::skills::SkillJewelryMaking: + case EQEmu::skills::SkillPottery: + case EQEmu::skills::SkillTailoring: + if (aaLevel == 6) + break; //Maxed AA + if (SkillTotal == 0) + break; //First tradeskill freebie + if ((SkillTotal == (aaLevel + 1)) && (rawskill > 200)) + break; //One of the tradeskills already allowed to go over 200 + if ((SkillTotal >= (aaLevel + 1)) && (rawskill >= 200)) + return false; //One or more tradeskills already at or beyond limit + break; + default: + break; //Other skills unchecked and ability to increase assumed true } return true; } diff --git a/zone/tune.cpp b/zone/tune.cpp index a6b55f02e..76fb97b89 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -255,7 +255,7 @@ int32 Mob::Tune_MeleeMitigation(Mob* GM, Mob *attacker, int32 damage, int32 minh } if (RuleB(Combat, UseIntervalAC)) { - float softcap = (GetSkill(SkillDefense) + GetLevel()) * + float softcap = (GetSkill(EQEmu::skills::SkillDefense) + GetLevel()) * RuleR(Combat, SoftcapFactor) * (1.0 + aa_mit); float mitigation_rating = 0.0; float attack_rating = 0.0; @@ -410,14 +410,14 @@ int32 Mob::Tune_MeleeMitigation(Mob* GM, Mob *attacker, int32 damage, int32 minh int tmp_armor = armor; if (GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == NECROMANCER || GetClass() == ENCHANTER){ - mitigation_rating = ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10) / 4.0) + armor + 1; + mitigation_rating = ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 4.0) + armor + 1; if (Msg >= 2) - GM->Message(0, "# + %.2f #### DEFENDER Armor Bonus [Defense Skill %i Heroic Agi %i]", mitigation_rating - tmp_armor, GetSkill(SkillDefense), itembonuses.HeroicAGI); + GM->Message(0, "# + %.2f #### DEFENDER Armor Bonus [Defense Skill %i Heroic Agi %i]", mitigation_rating - tmp_armor, GetSkill(EQEmu::skills::SkillDefense), itembonuses.HeroicAGI); } else{ - mitigation_rating = ((GetSkill(SkillDefense) + itembonuses.HeroicAGI/10) / 3.0) + (armor * 1.333333) + 1; + mitigation_rating = ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 3.0) + (armor * 1.333333) + 1; if (Msg >= 2) - GM->Message(0, "# + %.2f #### DEFENDER Armor Bonus [Defense Skill %i Heroic Agi %i]", mitigation_rating - tmp_armor, GetSkill(SkillDefense), itembonuses.HeroicAGI); + GM->Message(0, "# + %.2f #### DEFENDER Armor Bonus [Defense Skill %i Heroic Agi %i]", mitigation_rating - tmp_armor, GetSkill(EQEmu::skills::SkillDefense), itembonuses.HeroicAGI); } mitigation_rating *= 0.847; @@ -443,16 +443,16 @@ int32 Mob::Tune_MeleeMitigation(Mob* GM, Mob *attacker, int32 damage, int32 minh if (attacker->IsClient()){ if (atk_override) - attack_rating = (atk_override + ((attacker->GetSTR()-66) * 0.9) + (attacker->GetSkill(SkillOffense)*1.345)); + attack_rating = (atk_override + ((attacker->GetSTR() - 66) * 0.9) + (attacker->GetSkill(EQEmu::skills::SkillOffense)*1.345)); else - attack_rating = ((attacker->CastToClient()->CalcATK() + add_atk) + ((attacker->GetSTR()-66) * 0.9) + (attacker->GetSkill(SkillOffense)*1.345)); + attack_rating = ((attacker->CastToClient()->CalcATK() + add_atk) + ((attacker->GetSTR() - 66) * 0.9) + (attacker->GetSkill(EQEmu::skills::SkillOffense)*1.345)); } else{ if (atk_override) - attack_rating = (atk_override + (attacker->GetSkill(SkillOffense)*1.345) + ((attacker->GetSTR()-66) * 0.9)); + attack_rating = (atk_override + (attacker->GetSkill(EQEmu::skills::SkillOffense)*1.345) + ((attacker->GetSTR() - 66) * 0.9)); else - attack_rating = ((attacker->GetATK() + add_atk) + (attacker->GetSkill(SkillOffense)*1.345) + ((attacker->GetSTR()-66) * 0.9)); + attack_rating = ((attacker->GetATK() + add_atk) + (attacker->GetSkill(EQEmu::skills::SkillOffense)*1.345) + ((attacker->GetSTR() - 66) * 0.9)); } attack_rating = attacker->mod_attack_rating(attack_rating, this); @@ -468,7 +468,7 @@ int32 Mob::Tune_MeleeMitigation(Mob* GM, Mob *attacker, int32 damage, int32 minh GM->Message(0, "# %i #### ATTACKER Worn/Equip ATK Bonus", attacker->itembonuses.ATK); GM->Message(0, "# %i #### ATTACKER Worn/Equip ATK Bonus", attacker->itembonuses.ATK); GM->Message(0, "# %.2f #### ATTACKER Strength Stat ATK Bonus [Stat Amt: %i]", ((attacker->GetSTR()-66) * 0.9),attacker->GetSTR()); - GM->Message(0, "# %.2f #### ATTACKER Offensive Skill ATK Bonus [Stat Amt: %i]", (attacker->GetSkill(SkillOffense)*1.345) ,attacker->GetSkill(SkillOffense)); + GM->Message(0, "# %.2f #### ATTACKER Offensive Skill ATK Bonus [Stat Amt: %i]", (attacker->GetSkill(EQEmu::skills::SkillOffense)*1.345), attacker->GetSkill(EQEmu::skills::SkillOffense)); } else{ @@ -476,7 +476,7 @@ int32 Mob::Tune_MeleeMitigation(Mob* GM, Mob *attacker, int32 damage, int32 minh GM->Message(0, "# %i #### ATTACKER SE_ATK(2) spell Bonus", attacker->spellbonuses.ATK); GM->Message(0, "# %i #### ATTACKER NPC ATK Stat", attacker->CastToNPC()->ATK); GM->Message(0, "# %.2f #### ATTACKER Strength Stat ATK Bonus [Stat Amt: %i]", ((attacker->GetSTR()-66) * 0.9),attacker->GetSTR()); - GM->Message(0, "# %.2f #### ATTACKER Offensive Skill ATK Bonus [Stat Amt: %i]", (attacker->GetSkill(SkillOffense)*1.345) ,attacker->GetSkill(SkillOffense)); + GM->Message(0, "# %.2f #### ATTACKER Offensive Skill ATK Bonus [Stat Amt: %i]", (attacker->GetSkill(EQEmu::skills::SkillOffense)*1.345), attacker->GetSkill(EQEmu::skills::SkillOffense)); } } @@ -596,7 +596,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) } } - SkillUseTypes skillinuse; + EQEmu::skills::SkillType skillinuse; AttackAnimation(skillinuse, Hand, weapon); int damage = 0; @@ -621,7 +621,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) max_hit = (RuleI(Combat, HitCapPre20)); CheckIncreaseSkill(skillinuse, other, -15); - CheckIncreaseSkill(SkillOffense, other, -15); + CheckIncreaseSkill(EQEmu::skills::SkillOffense, other, -15); #ifndef EQEMU_NO_WEAPON_DAMAGE_BONUS @@ -658,7 +658,7 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch float tmp_hit_chance = 0.0f; bool end = false; - SkillUseTypes skillinuse = SkillHandtoHand; + EQEmu::skills::SkillType skillinuse = EQEmu::skills::SkillHandtoHand; if (attacker->IsClient()) {//Will check first equiped weapon for skill. Ie. remove wepaons to assess bow. ItemInst* weapon; @@ -738,7 +738,7 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ float tmp_hit_chance = 0.0f; bool end = false; - SkillUseTypes skillinuse = SkillHandtoHand; + EQEmu::skills::SkillType skillinuse = EQEmu::skills::SkillHandtoHand; if (attacker->IsClient()) {//Will check first equiped weapon for skill. Ie. remove wepaons to assess bow. ItemInst* weapon; @@ -809,7 +809,7 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ } -float Mob::Tune_CheckHitChance(Mob* defender, Mob* attacker, SkillUseTypes skillinuse, int Hand, int16 chance_mod, int Msg,int acc_override, int avoid_override, int add_acc, int add_avoid) +float Mob::Tune_CheckHitChance(Mob* defender, Mob* attacker, EQEmu::skills::SkillType skillinuse, int Hand, int16 chance_mod, int Msg, int acc_override, int avoid_override, int add_acc, int add_avoid) { float chancetohit = RuleR(Combat, BaseHitChance); @@ -897,9 +897,9 @@ float Mob::Tune_CheckHitChance(Mob* defender, Mob* attacker, SkillUseTypes skill if(defender->IsClient()) { - chancetohit += (RuleR(Combat,WeaponSkillFalloff) * (defender->CastToClient()->MaxSkill(SkillDefense) - defender->GetSkill(SkillDefense))); + chancetohit += (RuleR(Combat, WeaponSkillFalloff) * (defender->CastToClient()->MaxSkill(EQEmu::skills::SkillDefense) - defender->GetSkill(EQEmu::skills::SkillDefense))); if (Msg >= 2) - Message(0, "# + %.2f Total: %.2f #### DEFENDER Defense Skill Mod", (RuleR(Combat,WeaponSkillFalloff) * (defender->CastToClient()->MaxSkill(SkillDefense) - defender->GetSkill(SkillDefense))), chancetohit); + Message(0, "# + %.2f Total: %.2f #### DEFENDER Defense Skill Mod", (RuleR(Combat, WeaponSkillFalloff) * (defender->CastToClient()->MaxSkill(EQEmu::skills::SkillDefense) - defender->GetSkill(EQEmu::skills::SkillDefense))), chancetohit); } @@ -988,17 +988,17 @@ float Mob::Tune_CheckHitChance(Mob* defender, Mob* attacker, SkillUseTypes skill hitBonus += attacker->itembonuses.HitChanceEffect[skillinuse] + attacker->spellbonuses.HitChanceEffect[skillinuse]+ attacker->aabonuses.HitChanceEffect[skillinuse]+ - attacker->itembonuses.HitChanceEffect[HIGHEST_SKILL+1] + - attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1] + - attacker->aabonuses.HitChanceEffect[HIGHEST_SKILL+1]; + attacker->itembonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->spellbonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->aabonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1]; if (Msg >= 2){ - if (attacker->aabonuses.HitChanceEffect[HIGHEST_SKILL+1]) - Message(0, "# %i #### ATTACKER SE_HitChance(184) AA Bonus [All Skills]", attacker->aabonuses.HitChanceEffect[HIGHEST_SKILL+1]); - if (attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1]) - Message(0, "# %i #### ATTACKER SE_HitChance(184) Spell Bonus [All Skills]", attacker->spellbonuses.HitChanceEffect[HIGHEST_SKILL+1]); - if (attacker->itembonuses.HitChanceEffect[HIGHEST_SKILL+1]) - Message(0, "# %i #### ATTACKER SE_HitChance(184) Worn Bonus [All Skills]", attacker->itembonuses.HitChanceEffect[HIGHEST_SKILL+1]); + if (attacker->aabonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1]) + Message(0, "# %i #### ATTACKER SE_HitChance(184) AA Bonus [All Skills]", attacker->aabonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1]); + if (attacker->spellbonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1]) + Message(0, "# %i #### ATTACKER SE_HitChance(184) Spell Bonus [All Skills]", attacker->spellbonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1]); + if (attacker->itembonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1]) + Message(0, "# %i #### ATTACKER SE_HitChance(184) Worn Bonus [All Skills]", attacker->itembonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1]); if (attacker->itembonuses.HitChanceEffect[skillinuse]) Message(0, "# %i #### ATTACKER SE_HitChance(184) AA Bonus [Skill]", attacker->aabonuses.HitChanceEffect[skillinuse]); if (attacker->spellbonuses.HitChanceEffect[skillinuse]) @@ -1009,19 +1009,19 @@ float Mob::Tune_CheckHitChance(Mob* defender, Mob* attacker, SkillUseTypes skill //Accuracy = Spell Effect , HitChance = 'Accuracy' from Item Effect //Only AA derived accuracy can be skill limited. ie (Precision of the Pathfinder, Dead Aim) - hitBonus += (attacker->itembonuses.Accuracy[HIGHEST_SKILL+1] + - attacker->spellbonuses.Accuracy[HIGHEST_SKILL+1] + - attacker->aabonuses.Accuracy[HIGHEST_SKILL+1] + + hitBonus += (attacker->itembonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->spellbonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->aabonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + attacker->aabonuses.Accuracy[skillinuse] + attacker->itembonuses.HitChance) / 15.0f; //Item Mod 'Accuracy' if (Msg >= 2) { - if (attacker->aabonuses.Accuracy[HIGHEST_SKILL+1]) - Message(0, "# %.2f #### ATTACKER SE_Accuracy(216) AA Bonus [All Skills] [Stat Amt: %i]", static_cast(attacker->aabonuses.Accuracy[HIGHEST_SKILL+1])/15.0f,attacker->aabonuses.Accuracy[HIGHEST_SKILL+1]); - if (attacker->spellbonuses.Accuracy[HIGHEST_SKILL+1]) - Message(0, "# %.2f #### ATTACKER SE_Accuracy(216) Spell Bonus [All Skills] [Stat Amt: %i]", static_cast(attacker->spellbonuses.Accuracy[HIGHEST_SKILL+1])/15.0f,attacker->spellbonuses.Accuracy[HIGHEST_SKILL+1]); - if (attacker->itembonuses.Accuracy[HIGHEST_SKILL+1]) - Message(0, "# %.2f #### ATTACKER SE_Accuracy(216) Worn Bonus [All Skills] [Stat Amt: %i]", static_cast(attacker->itembonuses.Accuracy[HIGHEST_SKILL+1])/15.0f,attacker->itembonuses.Accuracy[HIGHEST_SKILL+1]); + if (attacker->aabonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1]) + Message(0, "# %.2f #### ATTACKER SE_Accuracy(216) AA Bonus [All Skills] [Stat Amt: %i]", static_cast(attacker->aabonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1]) / 15.0f, attacker->aabonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1]); + if (attacker->spellbonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1]) + Message(0, "# %.2f #### ATTACKER SE_Accuracy(216) Spell Bonus [All Skills] [Stat Amt: %i]", static_cast(attacker->spellbonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1]) / 15.0f, attacker->spellbonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1]); + if (attacker->itembonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1]) + Message(0, "# %.2f #### ATTACKER SE_Accuracy(216) Worn Bonus [All Skills] [Stat Amt: %i]", static_cast(attacker->itembonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1]) / 15.0f, attacker->itembonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1]); if (attacker->aabonuses.Accuracy[skillinuse]) Message(0, "# %.2f #### ATTACKER SE_Accuracy(216) AA Bonus [Skill] [Stat Amt: %i]", static_cast(attacker->aabonuses.Accuracy[skillinuse])/15.0f,attacker->aabonuses.Accuracy[skillinuse]); if (attacker->itembonuses.HitChance) @@ -1053,7 +1053,7 @@ float Mob::Tune_CheckHitChance(Mob* defender, Mob* attacker, SkillUseTypes skill hitBonus += (add_acc / 15.0f); //Modifier from database } - if(skillinuse == SkillArchery){ + if (skillinuse == EQEmu::skills::SkillArchery){ hitBonus -= hitBonus*RuleR(Combat, ArcheryHitPenalty); if (Msg >= 2) Message(0, "# %.2f pct #### RuleR(Combat, ArcheryHitPenalty) ", RuleR(Combat, ArcheryHitPenalty)); diff --git a/zone/zonedb.h b/zone/zonedb.h index a4fc5af7b..ef5a6810d 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -92,7 +92,7 @@ struct DBnpcspellseffects_Struct { }; struct DBTradeskillRecipe_Struct { - SkillUseTypes tradeskill; + EQEmu::skills::SkillType tradeskill; int16 skill_needed; uint16 trivial; bool nofail; From b5f09d435fa917a752851475541585bb98b98108 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 25 May 2016 19:45:16 -0400 Subject: [PATCH 124/693] Updated argument type..but, forgot to change methodology --- common/eq_limits.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index cd705add6..8dffc71f9 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -23,7 +23,7 @@ size_t EQEmu::constants::CharacterCreationLimit(versions::ClientVersion client_version) { - static const size_t local[versions::InventoryVersionCount] = { + static const size_t local[versions::ClientVersionCount] = { ClientUnknown::Null, Client62::Null, Titanium::constants::CharacterCreationLimit, @@ -31,11 +31,7 @@ size_t EQEmu::constants::CharacterCreationLimit(versions::ClientVersion client_v SoD::constants::CharacterCreationLimit, UF::constants::CharacterCreationLimit, RoF::constants::CharacterCreationLimit, - RoF2::constants::CharacterCreationLimit, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null + RoF2::constants::CharacterCreationLimit }; return local[static_cast(versions::ValidateClientVersion(client_version))]; From 4c3947efa6eadea3f819ad7845adfd6052fa023c Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 17 Jan 2016 17:40:29 -0800 Subject: [PATCH 125/693] Changes to UF and above clients on how spell buff tics are synced. --- common/eq_packet_structs.h | 1 + common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/patches/sod.cpp | 19 ------------------- common/patches/uf.cpp | 2 +- zone/spells.cpp | 2 ++ 6 files changed, 6 insertions(+), 22 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 0434e8947..fce0d3197 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4816,6 +4816,7 @@ struct BuffIcon_Struct uint8 all_buffs; uint16 count; uint8 type; // 0 = self buff window, 1 = self target window, 4 = group, 5 = PC, 7 = NPC + int32 tic_timer; BuffIconEntry_Struct entries[0]; }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 251ce28a3..72d3b75de 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -458,7 +458,7 @@ namespace RoF memset(__packet->pBuffer, 0, sz); __packet->WriteUInt32(emu->entity_id); - __packet->WriteUInt32(0); // PlayerID ? + __packet->WriteUInt32(emu->tic_timer); __packet->WriteUInt8(emu->all_buffs); // 1 indicates all buffs on the player (0 to add or remove a single buff) __packet->WriteUInt16(emu->count); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index b1487b2a3..9f906f991 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -527,7 +527,7 @@ namespace RoF2 memset(__packet->pBuffer, 0, sz); __packet->WriteUInt32(emu->entity_id); - __packet->WriteUInt32(0); // PlayerID ? + __packet->WriteUInt32(emu->tic_timer); __packet->WriteUInt8(emu->all_buffs); // 1 indicates all buffs on the player (0 to add or remove a single buff) __packet->WriteUInt16(emu->count); diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index d5fdec0b1..43f0d4b63 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -2219,25 +2219,6 @@ namespace SoD ptr += sizeof(uint32); ptr += 1; } - /*std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - - uint8 write_var8 = 1; - ss.write((const char*)&emu->entity_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint16)); - write_var8 = 0; - for(uint16 i = 0; i < emu->count; ++i) - { - ss.write((const char*)&emu->entries[i].buff_slot, sizeof(uint32)); - ss.write((const char*)&emu->entries[i].spell_id, sizeof(uint32)); - ss.write((const char*)&emu->entries[i].tics_remaining, sizeof(uint32)); - ss.write((const char*)&write_var8, sizeof(uint8)); - } - - __packet->size = ss.str().length(); - __packet->pBuffer = new unsigned char[__packet->size]; - memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); - */ - FINISH_ENCODE(); } diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index a0bca8e69..e16fce125 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -391,7 +391,7 @@ namespace UF memset(__packet->pBuffer, 0, sz); __packet->WriteUInt32(emu->entity_id); - __packet->WriteUInt32(0); + __packet->WriteUInt32(emu->tic_timer); __packet->WriteUInt8(emu->all_buffs); // 1 = all buffs, 0 = 1 buff __packet->WriteUInt16(emu->count); diff --git a/zone/spells.cpp b/zone/spells.cpp index c48baa00d..d648ba027 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5413,6 +5413,7 @@ void Client::SendBuffNumHitPacket(Buffs_Struct &buff, int slot) bi->entity_id = GetID(); bi->count = 1; bi->all_buffs = 0; + bi->tic_timer = tic_timer.GetRemainingTime(); bi->entries[0].buff_slot = slot; bi->entries[0].spell_id = buff.spellid; @@ -5493,6 +5494,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) buff->entity_id = GetID(); buff->count = count; buff->all_buffs = 1; + buff->tic_timer = tic_timer.GetRemainingTime(); // there are more types, the client doesn't seem to really care though. The others are also currently hard to fill in here ... // (see comment in common/eq_packet_structs.h) if (for_target) From 772fa200ac062a7dab2e4a22df61aab3ed70da6b Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 26 May 2016 05:27:21 -0400 Subject: [PATCH 126/693] Update to client limits --- common/patches/rof2_limits.h | 2 +- common/patches/rof_limits.h | 2 +- common/patches/sod_limits.h | 2 +- common/patches/sof_limits.h | 2 +- common/patches/titanium_limits.h | 2 +- common/patches/uf_limits.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index 70ce833b6..b38e88d7a 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -195,7 +195,7 @@ namespace RoF2 const size_t InvTypeLimboSize = 36; const size_t InvTypeTributeSize = 5; const size_t InvTypeTrophyTributeSize = 0;//unknown - const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeGuildTributeSize = 2;//unverified const size_t InvTypeMerchantSize = 200; const size_t InvTypeDeletedSize = 0;//unknown - "Recovery Tab" const size_t InvTypeCorpseSize = InvTypePossessionsSize; diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index 8b3d95591..14f9e32a1 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -187,7 +187,7 @@ namespace RoF const size_t InvTypeLimboSize = 36; const size_t InvTypeTributeSize = 5; const size_t InvTypeTrophyTributeSize = 0;//unknown - const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeGuildTributeSize = 2;//unverified const size_t InvTypeMerchantSize = 200; const size_t InvTypeDeletedSize = 0;//unknown - "Recovery Tab" const size_t InvTypeCorpseSize = InvTypePossessionsSize; diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index 1d364a431..e4f4ba3d7 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -175,7 +175,7 @@ namespace SoD const size_t InvTypeWorldSize = 10; const size_t InvTypeLimboSize = 36; const size_t InvTypeTributeSize = 5; - const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeGuildTributeSize = 2; const size_t InvTypeMerchantSize = 80; const size_t InvTypeCorpseSize = InvTypePossessionsSize; const size_t InvTypeBazaarSize = 80; diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 1a91ba942..81c6727b1 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -175,7 +175,7 @@ namespace SoF const size_t InvTypeWorldSize = 10; const size_t InvTypeLimboSize = 36; const size_t InvTypeTributeSize = 5; - const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeGuildTributeSize = 2; const size_t InvTypeMerchantSize = 80; const size_t InvTypeCorpseSize = InvTypePossessionsSize; const size_t InvTypeBazaarSize = 80; diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index cbb023efd..79351bad7 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -174,7 +174,7 @@ namespace Titanium const size_t InvTypeWorldSize = 10; const size_t InvTypeLimboSize = 36; const size_t InvTypeTributeSize = 5; - const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeGuildTributeSize = 2; const size_t InvTypeMerchantSize = 80; const size_t InvTypeCorpseSize = InvTypePossessionsSize; const size_t InvTypeBazaarSize = 80; diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index e44d7f856..533ba87ab 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -176,7 +176,7 @@ namespace UF const size_t InvTypeWorldSize = 10; const size_t InvTypeLimboSize = 36; const size_t InvTypeTributeSize = 5; - const size_t InvTypeGuildTributeSize = 0;//unknown + const size_t InvTypeGuildTributeSize = 2; const size_t InvTypeMerchantSize = 80; const size_t InvTypeCorpseSize = InvTypePossessionsSize; const size_t InvTypeBazaarSize = 80; From a144ecd21b919dca1637eac55e580cb7fde93aec Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 26 May 2016 17:23:57 -0400 Subject: [PATCH 127/693] ItemPacketType note update --- common/eq_packet_structs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index fce0d3197..e95f0eb0a 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1544,7 +1544,7 @@ enum ItemPacketType // ItemPacket10 = /*110*/ 0x6E, // ItemPacket11 = /*111*/ 0x6F, // UF+ (equipment slots only) (RoF+ checks '(WORD*)slot + 4 != -1' [(WORD*)]slot + 2 would be bag index - if used) (guess) // ItemPacket12 = /*112*/ 0x70, // RoF+ (causes stat update) (could be TrophyTribute and GuildTrophyTribute together - two case methodology - is it checking for GuildID?) -// ItemPacketRecovery = /*113*/ 0x71, (same handler as merchant..exception: parameter is '1' versus merchant '0' looks like tab id) +// ItemPacketMerchantRecovery = /*113*/ 0x71, // ItemPacket14 = /*115*/ 0x73, (real estate/moving crate?) // ItemPacket__ = /*xxx*/ 0xXX // switch 'default' - all clients //}; From 0ecc70261203cf1f2432561b6a78ab2d6937d752 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 27 May 2016 03:38:13 -0400 Subject: [PATCH 128/693] ItemPacketType updates --- common/eq_packet_structs.h | 6 +++--- common/patches/sod_limits.h | 5 ++++- common/patches/sof_limits.h | 5 ++++- common/patches/titanium_limits.h | 5 ++++- common/patches/uf_limits.h | 5 ++++- zone/client_packet.cpp | 4 ++-- zone/command.cpp | 2 +- zone/forage.cpp | 4 ++-- zone/inventory.cpp | 10 +++++----- zone/spell_effects.cpp | 4 ++-- 10 files changed, 31 insertions(+), 19 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index e95f0eb0a..0692aa6a5 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1522,7 +1522,7 @@ enum ItemPacketType ItemPacketLoot = 0x66, ItemPacketTrade = 0x67, ItemPacketCharInventory = 0x69, - ItemPacketSummonItem = 0x6A, + ItemPacketLimbo = 0x6A, ItemPacketWorldContainer = 0x6B, ItemPacketTributeItem = 0x6C, ItemPacketGuildTribute = 0x6D, @@ -1536,8 +1536,8 @@ enum ItemPacketType // ItemPacketTradeView = /*101*/ 0x65, // ItemPacketLoot = /*102*/ 0x66, // ItemPacketTrade = /*103*/ 0x67, -// ItemPacketCharInventory = /*105*/ 0x69, -// ItemPacketLimbo = /*106*/ 0x6A, // name change +// ItemPacketCharInventory = /*105*/ 0x69, // 105 looks like raw item packet (no appearance update) thru shared bank..110, possibly possessions with appearance update +// ItemPacketLimbo = /*106*/ 0x6A, // ItemPacketWorldContainer = /*107*/ 0x6B, // ItemPacketTributeItem = /*108*/ 0x6C, // ItemPacketGuildTribute = /*109*/ 0x6D, // missing from EQEmu diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index e4f4ba3d7..8bdac4150 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -210,7 +210,10 @@ namespace SoD const int WorldEnd = (WorldBegin + invtype::InvTypeWorldSize) - 1; const int TributeBegin = 400; - const int TributeEnd = 404; + const int TributeEnd = (TributeBegin + invtype::InvTypeTributeSize) - 1; + + const int GuildTributeBegin = 450; + const int GuildTributeEnd = (GuildTributeBegin + invtype::InvTypeGuildTributeSize) - 1; const int CorpseBegin = invslot::PossessionsGeneral1; const int CorpseEnd = invslot::PossessionsGeneral1 + invslot::PossessionsCursor; diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 81c6727b1..bd755c820 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -210,7 +210,10 @@ namespace SoF const int WorldEnd = (WorldBegin + invtype::InvTypeWorldSize) - 1; const int TributeBegin = 400; - const int TributeEnd = 404; + const int TributeEnd = (TributeBegin + invtype::InvTypeTributeSize) - 1; + + const int GuildTributeBegin = 450; + const int GuildTributeEnd = (GuildTributeBegin + invtype::InvTypeGuildTributeSize) - 1; const int CorpseBegin = PossessionsGeneral1; const int CorpseEnd = PossessionsGeneral1 + PossessionsCursor; diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index 79351bad7..a4ce67faf 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -209,7 +209,10 @@ namespace Titanium const int WorldEnd = (WorldBegin + invtype::InvTypeWorldSize) - 1; const int TributeBegin = 400; - const int TributeEnd = 404; + const int TributeEnd = (TributeBegin + invtype::InvTypeTributeSize) - 1; + + const int GuildTributeBegin = 450; + const int GuildTributeEnd = (GuildTributeBegin + invtype::InvTypeGuildTributeSize) - 1; const int CorpseBegin = PossessionsGeneral1; const int CorpseEnd = PossessionsGeneral1 + PossessionsCursor; diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index 533ba87ab..fb2370a4c 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -211,7 +211,10 @@ namespace UF const int WorldEnd = (WorldBegin + invtype::InvTypeWorldSize) - 1; const int TributeBegin = 400; - const int TributeEnd = 404; + const int TributeEnd = (TributeBegin + invtype::InvTypeTributeSize) - 1; + + const int GuildTributeBegin = 450; + const int GuildTributeEnd = (GuildTributeBegin + invtype::InvTypeGuildTributeSize) - 1; const int CorpseBegin = invslot::PossessionsGeneral1; const int CorpseEnd = invslot::PossessionsGeneral1 + invslot::PossessionsCursor; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index ac4466aab..e30f06741 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1689,7 +1689,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (iter == m_inv.cursor_cbegin()) continue; const ItemInst *inst = *iter; - SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketLimbo); } } @@ -7024,7 +7024,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) { PushItemOnCursor(*inst); - SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketLimbo); GuildBanks->DeleteItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity); } diff --git a/zone/command.cpp b/zone/command.cpp index 92116485c..332713f43 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -10223,7 +10223,7 @@ void command_zopp(Client *c, const Seperator *sep) packettype = ItemPacketTrade; } else { - packettype = ItemPacketSummonItem; + packettype = ItemPacketLimbo; } int16 slotid = atoi(sep->arg[2]); diff --git a/zone/forage.cpp b/zone/forage.cpp index eb54d674d..e00d835b4 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -317,7 +317,7 @@ void Client::GoFish() else { PushItemOnCursor(*inst); - SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketLimbo); if(RuleB(TaskSystem, EnableTaskSystem)) UpdateTasksForItem(ActivityFish, food_id); @@ -431,7 +431,7 @@ void Client::ForageItem(bool guarantee) { } else { PushItemOnCursor(*inst); - SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketLimbo); if(RuleB(TaskSystem, EnableTaskSystem)) UpdateTasksForItem(ActivityForage, foragedfood); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 29f4574e1..8902f4e23 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -569,7 +569,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // put item into inventory if (to_slot == EQEmu::legacy::SlotCursor) { PushItemOnCursor(*inst); - SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketLimbo); } else { PutItemInInventory(to_slot, *inst, true); @@ -710,7 +710,7 @@ void Client::SendCursorBuffer() SendCursorBuffer(); } else { - SendItemPacket(EQEmu::legacy::SlotCursor, test_inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, test_inst, ItemPacketLimbo); } } @@ -842,7 +842,7 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update) m_inv.PushCursor(inst); if (client_update) { - SendItemPacket(EQEmu::legacy::SlotCursor, &inst, ItemPacketSummonItem); + SendItemPacket(EQEmu::legacy::SlotCursor, &inst, ItemPacketLimbo); } auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); @@ -865,7 +865,7 @@ bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client if (client_update) { - SendItemPacket(slot_id, &inst, ((slot_id == EQEmu::legacy::SlotCursor) ? ItemPacketSummonItem : ItemPacketTrade)); + SendItemPacket(slot_id, &inst, ((slot_id == EQEmu::legacy::SlotCursor) ? ItemPacketLimbo : ItemPacketTrade)); //SendWearChange(Inventory::CalcMaterialFromSlot(slot_id)); } @@ -901,7 +901,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI if (slot_id == EQEmu::legacy::SlotCursor && !cursor_empty) { // RoF+ currently has a specialized cursor handler if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) - SendItemPacket(slot_id, &inst, ItemPacketSummonItem); + SendItemPacket(slot_id, &inst, ItemPacketLimbo); } else { SendLootItemInPacket(&inst, slot_id); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 6508d6fc6..4a8b43365 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1163,7 +1163,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (SummonedItem) { c->PushItemOnCursor(*SummonedItem); - c->SendItemPacket(EQEmu::legacy::SlotCursor, SummonedItem, ItemPacketSummonItem); + c->SendItemPacket(EQEmu::legacy::SlotCursor, SummonedItem, ItemPacketLimbo); safe_delete(SummonedItem); } SummonedItem = database.CreateItem(spell.base[i], charges); @@ -3018,7 +3018,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (SummonedItem) { Client *c=CastToClient(); c->PushItemOnCursor(*SummonedItem); - c->SendItemPacket(EQEmu::legacy::SlotCursor, SummonedItem, ItemPacketSummonItem); + c->SendItemPacket(EQEmu::legacy::SlotCursor, SummonedItem, ItemPacketLimbo); safe_delete(SummonedItem); } From a37a811014ef1438dac8cc44fe869df9ba6b0081 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 27 May 2016 20:39:11 -0400 Subject: [PATCH 129/693] Imported memory_buffer files from inv2 branch --- common/CMakeLists.txt | 2 + common/item.h | 6 +- common/memory_buffer.cpp | 277 +++++++++++++++++++++++++++++++++++++++ common/memory_buffer.h | 134 +++++++++++++++++++ common/string_util.cpp | 43 ------ common/string_util.h | 32 ----- 6 files changed, 415 insertions(+), 79 deletions(-) create mode 100644 common/memory_buffer.cpp create mode 100644 common/memory_buffer.h diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 034cf415a..6e78e1016 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -41,6 +41,7 @@ SET(common_sources item_struct.cpp light_source.cpp md5.cpp + memory_buffer.cpp memory_mapped_file.cpp misc.cpp misc_functions.cpp @@ -165,6 +166,7 @@ SET(common_headers loottable.h mail_oplist.h md5.h + memory_buffer.h memory_mapped_file.h misc.h misc_functions.h diff --git a/common/item.h b/common/item.h index 181c57d9c..7c3cd87bb 100644 --- a/common/item.h +++ b/common/item.h @@ -32,13 +32,11 @@ class EvolveInfo; // Stores information about an evolving item family #include "../common/item_struct.h" #include "../common/timer.h" #include "../common/bodytypes.h" -#include "../common/deity.h" // aren't we already in '/common'? - -#include "string_util.h" +#include "../common/deity.h" +#include "../common/memory_buffer.h" #include #include -//#include namespace ItemField diff --git a/common/memory_buffer.cpp b/common/memory_buffer.cpp new file mode 100644 index 000000000..898851cb3 --- /dev/null +++ b/common/memory_buffer.cpp @@ -0,0 +1,277 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "memory_buffer.h" + + +EQEmu::MemoryBuffer::MemoryBuffer() +{ + buffer_ = nullptr; + size_ = 0; + capacity_ = 0; + read_pos_ = 0; + write_pos_ = 0; +} + +EQEmu::MemoryBuffer::MemoryBuffer(size_t sz) +{ + buffer_ = nullptr; + size_ = 0; + capacity_ = 0; + read_pos_ = 0; + write_pos_ = 0; + Resize(sz); +} + +EQEmu::MemoryBuffer::MemoryBuffer(const MemoryBuffer &other) +{ + if(other.capacity_) { + buffer_ = new uchar[other.capacity_]; + memcpy(buffer_, other.buffer_, other.capacity_); + } else { + buffer_ = nullptr; + } + + size_ = other.size_; + capacity_ = other.capacity_; + write_pos_ = other.write_pos_; + read_pos_ = other.read_pos_; +} + +EQEmu::MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) +{ + uchar *tbuf = other.buffer_; + size_t tsz = other.size_; + size_t tcapacity = other.capacity_; + size_t twrite_pos = other.write_pos_; + size_t tread_pos = other.read_pos_; + + other.buffer_ = nullptr; + other.size_ = 0; + other.capacity_ = 0; + other.read_pos_ = 0; + other.write_pos_ = 0; + + buffer_ = tbuf; + size_ = tsz; + capacity_ = tcapacity; + write_pos_ = twrite_pos; + read_pos_ = tread_pos; +} + +EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(const MemoryBuffer &other) +{ + if(this == &other) { + return *this; + } + + if(buffer_) { + delete[] buffer_; + } + + if(other.capacity_) { + buffer_ = new uchar[other.capacity_]; + memcpy(buffer_, other.buffer_, other.capacity_); + } + else { + buffer_ = nullptr; + } + + size_ = other.size_; + capacity_ = other.capacity_; + write_pos_ = other.write_pos_; + read_pos_ = other.read_pos_; + return *this; +} + +EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(MemoryBuffer &&other) +{ + uchar *tbuf = other.buffer_; + size_t tsz = other.size_; + size_t tcapacity = other.capacity_; + size_t twrite_pos = other.write_pos_; + size_t tread_pos = other.read_pos_; + + other.buffer_ = nullptr; + other.size_ = 0; + other.capacity_ = 0; + other.read_pos_ = 0; + other.write_pos_ = 0; + + buffer_ = tbuf; + size_ = tsz; + capacity_ = tcapacity; + write_pos_ = twrite_pos; + read_pos_ = tread_pos; + return *this; +} + +EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator+=(const MemoryBuffer &rhs) +{ + if(!rhs.buffer_) { + return *this; + } + + if(buffer_) { + size_t old_size = size_; + Resize(size_ + rhs.size_); + memcpy(&buffer_[old_size], rhs.buffer_, rhs.size_); + } else { + buffer_ = new uchar[rhs.capacity_]; + memcpy(buffer_, rhs.buffer_, rhs.capacity_); + size_ = rhs.size_; + capacity_ = rhs.capacity_; + } + + return *this; +} + +EQEmu::MemoryBuffer::~MemoryBuffer() +{ + Clear(); +} + +uchar& EQEmu::MemoryBuffer::operator[](size_t pos) +{ + return buffer_[pos]; +} + +const uchar& EQEmu::MemoryBuffer::operator[](size_t pos) const +{ + return buffer_[pos]; +} + +bool EQEmu::MemoryBuffer::Empty() +{ + return size_ == 0; +} + +bool EQEmu::MemoryBuffer::Empty() const +{ + return size_ == 0; +} + +size_t EQEmu::MemoryBuffer::Size() +{ + return size_; +} + +size_t EQEmu::MemoryBuffer::Size() const +{ + return size_; +} + +size_t EQEmu::MemoryBuffer::Capacity() +{ + return capacity_; +} + +size_t EQEmu::MemoryBuffer::Capacity() const +{ + return capacity_; +} + +void EQEmu::MemoryBuffer::Resize(size_t sz) +{ + if(!buffer_) { + size_t new_size = sz + 64; + buffer_ = new uchar[new_size]; + capacity_ = new_size; + size_ = sz; + memset(buffer_, 0, capacity_); + return; + } + + if(sz > capacity_) { + size_t new_size = sz + 32; + uchar *temp = new uchar[new_size]; + memcpy(temp, buffer_, capacity_); + delete[] buffer_; + buffer_ = temp; + + capacity_ = new_size; + size_ = sz; + } + else { + size_ = sz; + } +} + +void EQEmu::MemoryBuffer::Clear() +{ + if(buffer_) { + delete[] buffer_; + buffer_ = nullptr; + } + + size_ = 0; + capacity_ = 0; + write_pos_ = 0; + read_pos_ = 0; +} + +void EQEmu::MemoryBuffer::Zero() +{ + if(buffer_) { + memset(buffer_, 0, capacity_); + } +} + +void EQEmu::MemoryBuffer::Write(const char *val, size_t len) +{ + size_t size_needed = write_pos_ + len; + Resize(size_needed); + + memcpy(&buffer_[write_pos_], val, len); + write_pos_ += len; +} + +void EQEmu::MemoryBuffer::Read(uchar *buf, size_t len) +{ + memcpy(buf, &buffer_[read_pos_], len); + read_pos_ += len; +} + +void EQEmu::MemoryBuffer::Read(char *str) +{ + size_t len = strlen((const char*)&buffer_[read_pos_]); + memcpy(str, &buffer_[read_pos_], len); + read_pos_ += len; +} + +void EQEmu::OutBuffer::overwrite(OutBuffer::pos_type position, const char *_Str, std::streamsize _Count) +{ + auto last_pos = tellp(); + seekp(position); + write(_Str, _Count); + seekp(last_pos); +} + +uchar* EQEmu::OutBuffer::detach() +{ + size_t buffer_size = tellp(); + if (buffer_size == 0) + return nullptr; + + auto out_buffer = new uchar[buffer_size]; + memcpy(out_buffer, str().c_str(), buffer_size); + flush(); + + return out_buffer; +} diff --git a/common/memory_buffer.h b/common/memory_buffer.h new file mode 100644 index 000000000..880b860ae --- /dev/null +++ b/common/memory_buffer.h @@ -0,0 +1,134 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_MEMORY_BUFFER +#define COMMON_MEMORY_BUFFER + +#include "types.h" + +#include +#include +#include +#include + + +namespace EQEmu +{ + class MemoryBuffer { + public: + MemoryBuffer(); + MemoryBuffer(size_t sz); + MemoryBuffer(const MemoryBuffer &other); + MemoryBuffer(MemoryBuffer &&other); + MemoryBuffer& operator=(const MemoryBuffer &other); + MemoryBuffer& operator=(MemoryBuffer &&other); + MemoryBuffer& operator+=(const MemoryBuffer &rhs); + friend MemoryBuffer operator+(MemoryBuffer lhs, const MemoryBuffer& rhs) { return lhs += rhs; } + ~MemoryBuffer(); + + uchar& operator[](size_t pos); + const uchar& operator[](size_t pos) const; + + template + operator T*() { + return reinterpret_cast(buffer_); + } + + template + operator T*() const { + return reinterpret_cast(buffer_); + } + + operator bool() { return buffer_ != nullptr; } + operator bool() const { return buffer_ != nullptr; } + + bool Empty(); + bool Empty() const; + size_t Size(); + size_t Size() const; + size_t Capacity(); + size_t Capacity() const; + + void Resize(size_t sz); + void Clear(); + void Zero(); + + template + void Write(T val) { + static_assert(std::is_pod::value, "MemoryBuffer::Write(T val) only works on pod and string types."); + Write((const char*)&val, sizeof(T)); + } + + template + T Read() { + static_assert(std::is_pod::value, "MemoryBuffer::Read() only works on pod and string types."); + T temp; + Read((uchar*)&temp, sizeof(T)); + return temp; + } + + void Write(const std::string &val) { + Write(val.c_str(), val.length()); + Write((uint8)0); + } + + void Write(const char *val) { + size_t len = strlen(val); + Write(val, len); + Write((uint8)0); + } + + std::string ReadString() { + std::string ret; + size_t len = strlen((const char*)&buffer_[read_pos_]); + ret.resize(len); + memcpy(&ret[0], &buffer_[read_pos_], len); + read_pos_ += len + 1; + return ret; + } + + void Write(const char *val, size_t len); + void Read(uchar *buf, size_t len); + void Read(char *str); + + inline size_t GetWritePosition() { return write_pos_; } + inline void SetWritePosition(size_t wp) { write_pos_ = wp; } + inline void WriteSkipBytes(size_t skip) { write_pos_ += skip; } + inline size_t GetReadPosition() { return read_pos_; } + inline void SetReadPosition(size_t rp) { read_pos_ = rp; } + inline void ReadSkipBytes(size_t skip) { read_pos_ += skip; } + + private: + uchar *buffer_; + size_t size_; + size_t capacity_; + size_t write_pos_; + size_t read_pos_; + }; + + class OutBuffer : public std::stringstream { + public: + inline size_t size() { return tellp(); } + void overwrite(OutBuffer::pos_type position, const char *_Str, std::streamsize _Count); + uchar* detach(); + }; + +} /*EQEmu*/ + +#endif /*COMMON_MEMORY_BUFFER*/ diff --git a/common/string_util.cpp b/common/string_util.cpp index b5717c1b7..902d13335 100644 --- a/common/string_util.cpp +++ b/common/string_util.cpp @@ -415,46 +415,3 @@ void find_replace(std::string& string_subject, const std::string& search_string, index = string_subject.find_first_of(search_string); } } - - - -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -void EQEmu::OutBuffer::overwrite(OutBuffer::pos_type position, const char *_Str, std::streamsize _Count) -{ - auto last_pos = tellp(); - seekp(position); - write(_Str, _Count); - seekp(last_pos); -} - -uchar* EQEmu::OutBuffer::detach() -{ - size_t buffer_size = tellp(); - if (buffer_size == 0) - return nullptr; - - auto out_buffer = new uchar[buffer_size]; - memcpy(out_buffer, str().c_str(), buffer_size); - flush(); - - return out_buffer; -} diff --git a/common/string_util.h b/common/string_util.h index 5b373a41b..c69f01456 100644 --- a/common/string_util.h +++ b/common/string_util.h @@ -53,36 +53,4 @@ void MakeLowerString(const char *source, char *target); void RemoveApostrophes(std::string &s); void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string); - - -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -namespace EQEmu -{ - class OutBuffer : public std::stringstream { - public: - inline size_t size() { return tellp(); } - void overwrite(OutBuffer::pos_type position, const char *_Str, std::streamsize _Count); - uchar* detach(); - }; -} - #endif From 579efe83afaec0f149494bac115371f222bb9126 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 27 May 2016 22:22:19 -0400 Subject: [PATCH 130/693] Renamed EQEmu::Item_Struct to EQEmu::ItemBase to coincide with new inventory naming conventions (re-run shared_memory.exe) --- changelog.txt | 3 ++ common/CMakeLists.txt | 4 +- common/eq_packet_structs.h | 6 +-- common/item.cpp | 28 ++++++------ common/item.h | 18 ++++---- common/{item_struct.cpp => item_base.cpp} | 16 +++---- common/{item_struct.h => item_base.h} | 32 ++++++------- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/patches/rof2_structs.h | 2 +- common/patches/rof_structs.h | 2 +- common/patches/sod.cpp | 2 +- common/patches/sod_structs.h | 2 +- common/patches/sof.cpp | 2 +- common/patches/titanium.cpp | 2 +- common/patches/uf.cpp | 4 +- common/patches/uf_structs.h | 2 +- common/say_link.cpp | 6 +-- common/say_link.h | 6 +-- common/shareddb.cpp | 26 +++++------ common/shareddb.h | 13 +++--- shared_memory/items.cpp | 4 +- tests/fixed_memory_test.h | 46 +++++++++---------- world/worlddb.cpp | 2 +- zone/aa.cpp | 2 +- zone/attack.cpp | 26 +++++------ zone/bonuses.cpp | 12 ++--- zone/bot.cpp | 52 ++++++++++----------- zone/bot.h | 2 +- zone/bot_command.cpp | 6 +-- zone/client.cpp | 18 ++++---- zone/client.h | 24 +++++----- zone/client_mods.cpp | 2 +- zone/client_packet.cpp | 56 +++++++++++------------ zone/client_process.cpp | 6 +-- zone/command.cpp | 12 ++--- zone/corpse.cpp | 12 ++--- zone/effects.cpp | 2 +- zone/embparser.cpp | 2 +- zone/embxs.cpp | 2 +- zone/entity.cpp | 4 +- zone/forage.cpp | 4 +- zone/guild_mgr.cpp | 20 ++++---- zone/inventory.cpp | 36 +++++++-------- zone/loottables.cpp | 16 +++---- zone/lua_item.cpp | 2 +- zone/lua_item.h | 12 ++--- zone/lua_parser_events.cpp | 2 +- zone/merc.cpp | 14 +++--- zone/merc.h | 4 +- zone/mob.cpp | 16 +++---- zone/mob.h | 18 ++++---- zone/mod_functions.cpp | 10 ++-- zone/npc.cpp | 6 +-- zone/npc.h | 8 ++-- zone/object.cpp | 6 +-- zone/perl_mob.cpp | 2 +- zone/pets.cpp | 4 +- zone/questmgr.cpp | 10 ++-- zone/special_attacks.cpp | 40 ++++++++-------- zone/spell_effects.cpp | 20 ++++---- zone/spells.cpp | 8 ++-- zone/tasks.cpp | 4 +- zone/tradeskills.cpp | 16 +++---- zone/trading.cpp | 24 +++++----- zone/tune.cpp | 2 +- zone/zonedb.cpp | 8 ++-- 67 files changed, 391 insertions(+), 393 deletions(-) rename common/{item_struct.cpp => item_base.cpp} (94%) rename common/{item_struct.h => item_base.h} (95%) diff --git a/changelog.txt b/changelog.txt index 63a2a8908..b300d865d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/27/2016 == +Uleat: Renamed EQEmu::Item_Struct to EQEmu::ItemBase (and appropriate files) to coincide with new inventory naming conventions + == 05/25/2016 == Uleat: Renamed and moved enumeration SkillUseTypes to EQEmu::skill::SkillType - added class EQEmu::SkillProfile, though not implemented at this time Uleat: Some more work on eq_dictionary diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 6e78e1016..71c78b177 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -38,7 +38,7 @@ SET(common_sources inventory_version.cpp ipc_mutex.cpp item.cpp - item_struct.cpp + item_base.cpp light_source.cpp md5.cpp memory_buffer.cpp @@ -158,8 +158,8 @@ SET(common_headers inventory_version.h ipc_mutex.h item.h + item_base.h item_fieldlist.h - item_struct.h languages.h light_source.h linked_list.h diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 0692aa6a5..c4fce9d8c 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -25,7 +25,8 @@ #include #include #include "../common/version.h" -//#include "../common/item_struct.h" +#include "emu_constants.h" + static const uint32 BUFF_COUNT = 25; static const uint32 MAX_MERC = 100; @@ -33,7 +34,6 @@ static const uint32 MAX_MERC_GRADES = 10; static const uint32 MAX_MERC_STANCES = 10; static const uint32 BLOCKED_BUFF_COUNT = 20; -#include "emu_constants.h" /* ** Compiler override to ensure @@ -2119,7 +2119,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - EQEmu::Item_Struct item; + EQEmu::ItemBase item; uint8 iss_unknown001[6]; };*/ diff --git a/common/item.cpp b/common/item.cpp index fb824afc1..6e40ac6bc 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -370,7 +370,7 @@ ItemInst* Inventory::PopItem(int16 slot_id) return p; } -bool Inventory::HasSpaceForItem(const EQEmu::Item_Struct *ItemToTry, int16 Quantity) { +bool Inventory::HasSpaceForItem(const EQEmu::ItemBase *ItemToTry, int16 Quantity) { if (ItemToTry->Stackable) { @@ -903,7 +903,7 @@ uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) } } -bool Inventory::CanItemFitInContainer(const EQEmu::Item_Struct *ItemToTry, const EQEmu::Item_Struct *Container) { +bool Inventory::CanItemFitInContainer(const EQEmu::ItemBase *ItemToTry, const EQEmu::ItemBase *Container) { if (!ItemToTry || !Container) return false; @@ -1440,10 +1440,10 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) // // class ItemInst // -ItemInst::ItemInst(const EQEmu::Item_Struct* item, int16 charges) { +ItemInst::ItemInst(const EQEmu::ItemBase* item, int16 charges) { m_use_type = ItemInstNormal; if(item) { - m_item = new EQEmu::Item_Struct(*item); + m_item = new EQEmu::ItemBase(*item); } else { m_item = nullptr; } @@ -1474,7 +1474,7 @@ ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) { m_use_type = ItemInstNormal; m_item = db->GetItem(item_id); if(m_item) { - m_item = new EQEmu::Item_Struct(*m_item); + m_item = new EQEmu::ItemBase(*m_item); } else { m_item = nullptr; @@ -1529,7 +1529,7 @@ ItemInst::ItemInst(const ItemInst& copy) { m_use_type=copy.m_use_type; if(copy.m_item) - m_item = new EQEmu::Item_Struct(*copy.m_item); + m_item = new EQEmu::ItemBase(*copy.m_item); else m_item = nullptr; @@ -1565,7 +1565,7 @@ ItemInst::ItemInst(const ItemInst& copy) m_evolveLvl = copy.m_evolveLvl; m_activated = copy.m_activated; if (copy.m_scaledItem) - m_scaledItem = new EQEmu::Item_Struct(*copy.m_scaledItem); + m_scaledItem = new EQEmu::ItemBase(*copy.m_scaledItem); else m_scaledItem = nullptr; @@ -1800,7 +1800,7 @@ void ItemInst::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent) continue; } - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); if (item == nullptr) { cur = m_contents.erase(cur); continue; @@ -1941,7 +1941,7 @@ bool ItemInst::UpdateOrnamentationInfo() { int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); if (GetOrnamentationAug(ornamentationAugtype)) { - const EQEmu::Item_Struct* ornamentItem; + const EQEmu::ItemBase* ornamentItem; ornamentItem = GetOrnamentationAug(ornamentationAugtype)->GetItem(); if (ornamentItem != nullptr) { @@ -1968,7 +1968,7 @@ bool ItemInst::UpdateOrnamentationInfo() { return ornamentSet; } -bool ItemInst::CanTransform(const EQEmu::Item_Struct *ItemToTry, const EQEmu::Item_Struct *Container, bool AllowAll) { +bool ItemInst::CanTransform(const EQEmu::ItemBase *ItemToTry, const EQEmu::ItemBase *Container, bool AllowAll) { if (!ItemToTry || !Container) return false; if (ItemToTry->ItemType == EQEmu::item::ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0) @@ -2102,7 +2102,7 @@ bool ItemInst::IsAmmo() const } -const EQEmu::Item_Struct* ItemInst::GetItem() const +const EQEmu::ItemBase* ItemInst::GetItem() const { if (!m_item) return nullptr; @@ -2113,7 +2113,7 @@ const EQEmu::Item_Struct* ItemInst::GetItem() const return m_item; } -const EQEmu::Item_Struct* ItemInst::GetUnscaledItem() const +const EQEmu::ItemBase* ItemInst::GetUnscaledItem() const { // No operator calls and defaults to nullptr return m_item; @@ -2221,10 +2221,10 @@ void ItemInst::ScaleItem() { return; if (m_scaledItem) { - memcpy(m_scaledItem, m_item, sizeof(EQEmu::Item_Struct)); + memcpy(m_scaledItem, m_item, sizeof(EQEmu::ItemBase)); } else { - m_scaledItem = new EQEmu::Item_Struct(*m_item); + m_scaledItem = new EQEmu::ItemBase(*m_item); } float Mult = (float)(GetExp()) / 10000; // scaling is determined by exp, with 10,000 being full stats diff --git a/common/item.h b/common/item.h index 7c3cd87bb..f20b41fac 100644 --- a/common/item.h +++ b/common/item.h @@ -29,7 +29,7 @@ class ItemParse; // Parses item packets class EvolveInfo; // Stores information about an evolving item family #include "../common/eq_constants.h" -#include "../common/item_struct.h" +#include "../common/item_base.h" #include "../common/timer.h" #include "../common/bodytypes.h" #include "../common/deity.h" @@ -175,7 +175,7 @@ public: ItemInst* PopItem(int16 slot_id); // Check whether there is space for the specified number of the specified item. - bool HasSpaceForItem(const EQEmu::Item_Struct *ItemToTry, int16 Quantity); + bool HasSpaceForItem(const EQEmu::ItemBase *ItemToTry, int16 Quantity); // Check whether item exists in inventory // where argument specifies OR'd list of invWhere constants to look @@ -200,7 +200,7 @@ public: static int16 CalcSlotFromMaterial(uint8 material); static uint8 CalcMaterialFromSlot(int16 equipslot); - static bool CanItemFitInContainer(const EQEmu::Item_Struct *ItemToTry, const EQEmu::Item_Struct *Container); + static bool CanItemFitInContainer(const EQEmu::ItemBase *ItemToTry, const EQEmu::ItemBase *Container); // Test for valid inventory casting slot bool SupportsClickCasting(int16 slot_id); @@ -277,7 +277,7 @@ public: ///////////////////////// // Constructors/Destructor - ItemInst(const EQEmu::Item_Struct* item = nullptr, int16 charges = 0); + ItemInst(const EQEmu::ItemBase* item = nullptr, int16 charges = 0); ItemInst(SharedDatabase *db, uint32 item_id, int16 charges = 0); @@ -346,7 +346,7 @@ public: bool IsAugmented(); ItemInst* GetOrnamentationAug(int32 ornamentationAugtype) const; bool UpdateOrnamentationInfo(); - static bool CanTransform(const EQEmu::Item_Struct *ItemToTry, const EQEmu::Item_Struct *Container, bool AllowAll = false); + static bool CanTransform(const EQEmu::ItemBase *ItemToTry, const EQEmu::ItemBase *Container, bool AllowAll = false); // Has attack/delay? bool IsWeapon() const; @@ -355,8 +355,8 @@ public: // Accessors const uint32 GetID() const { return ((m_item) ? m_item->ID : NO_ITEM); } const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : NO_ITEM); } - const EQEmu::Item_Struct* GetItem() const; - const EQEmu::Item_Struct* GetUnscaledItem() const; + const EQEmu::ItemBase* GetItem() const; + const EQEmu::ItemBase* GetUnscaledItem() const; int16 GetCharges() const { return m_charges; } void SetCharges(int16 charges) { m_charges = charges; } @@ -500,7 +500,7 @@ protected: void _PutItem(uint8 index, ItemInst* inst) { m_contents[index] = inst; } ItemInstTypes m_use_type; // Usage type for item - const EQEmu::Item_Struct* m_item; // Ptr to item data + const EQEmu::ItemBase* m_item; // Ptr to item data int16 m_charges; // # of charges for chargeable items uint32 m_price; // Bazaar /trader price uint32 m_color; @@ -512,7 +512,7 @@ protected: uint32 m_exp; int8 m_evolveLvl; bool m_activated; - EQEmu::Item_Struct* m_scaledItem; + EQEmu::ItemBase* m_scaledItem; EvolveInfo* m_evolveInfo; bool m_scaling; uint32 m_ornamenticon; diff --git a/common/item_struct.cpp b/common/item_base.cpp similarity index 94% rename from common/item_struct.cpp rename to common/item_base.cpp index 20c0ad1ee..c2cef6918 100644 --- a/common/item_struct.cpp +++ b/common/item_base.cpp @@ -17,7 +17,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "item_struct.h" +#include "item_base.h" #include "classes.h" #include "races.h" //#include "deity.h" @@ -167,7 +167,7 @@ uint8 EQEmu::item::ConvertAugTypeBitToAugType(uint32 aug_type_bit) } } -bool EQEmu::Item_Struct::IsEquipable(uint16 race_id, uint16 class_id) +bool EQEmu::ItemBase::IsEquipable(uint16 race_id, uint16 class_id) { if (!(Races & GetPlayerRaceBit(race_id))) return false; @@ -178,32 +178,32 @@ bool EQEmu::Item_Struct::IsEquipable(uint16 race_id, uint16 class_id) return true; } -bool EQEmu::Item_Struct::IsClassCommon() +bool EQEmu::ItemBase::IsClassCommon() { return (ItemClass == item::ItemClassCommon); } -bool EQEmu::Item_Struct::IsClassBag() +bool EQEmu::ItemBase::IsClassBag() { return (ItemClass == item::ItemClassBag); } -bool EQEmu::Item_Struct::IsClassBook() +bool EQEmu::ItemBase::IsClassBook() { return (ItemClass == item::ItemClassBook); } -bool EQEmu::Item_Struct::IsType1HWeapon() +bool EQEmu::ItemBase::IsType1HWeapon() { return ((ItemType == item::ItemType1HBlunt) || (ItemType == item::ItemType1HSlash) || (ItemType == item::ItemType1HPiercing)); } -bool EQEmu::Item_Struct::IsType2HWeapon() +bool EQEmu::ItemBase::IsType2HWeapon() { return ((ItemType == item::ItemType2HBlunt) || (ItemType == item::ItemType2HSlash) || (ItemType == item::ItemType2HPiercing)); } -bool EQEmu::Item_Struct::IsTypeShield() +bool EQEmu::ItemBase::IsTypeShield() { return (ItemType == item::ItemTypeShield); } diff --git a/common/item_struct.h b/common/item_base.h similarity index 95% rename from common/item_struct.h rename to common/item_base.h index c56d32a67..1ecba6734 100644 --- a/common/item_struct.h +++ b/common/item_base.h @@ -17,8 +17,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA */ -#ifndef COMMON_ITEM_STRUCT_H -#define COMMON_ITEM_STRUCT_H +#ifndef COMMON_ITEM_BASE_H +#define COMMON_ITEM_BASE_H /* @@ -336,10 +336,10 @@ namespace EQEmu }; enum ItemDataType : uint8 { - ItemDataTypeBase = 0, - ItemDataTypeScaling, - ItemDataTypeEvolving, - ItemDataTypeCount + ItemDataBase = 0, + ItemDataScaling, + ItemDataEvolving, + ItemDataCount }; struct ItemEffect_Struct { @@ -364,10 +364,10 @@ namespace EQEmu const void * inst; }; - struct Item_Struct { + struct ItemBase { // Non packet based fields uint8 MinStatus; - //uint8 ItemDataType; + uint8 ItemDataType; // memset to item::ItemDataBase ('0') during mmf load // Packet based fields uint8 ItemClass; // Item Type: 0=common, 1=container, 2=book @@ -551,15 +551,15 @@ namespace EQEmu bool IsType2HWeapon(); bool IsTypeShield(); - bool IsEquipable(uint16 Race, uint16 Class) const { return const_cast(this)->IsEquipable(Race, Class); } - bool IsClassCommon() const { return const_cast(this)->IsClassCommon(); } - bool IsClassBag() const { return const_cast(this)->IsClassBag(); } - bool IsClassBook() const { return const_cast(this)->IsClassBook(); } - bool IsType1HWeapon() const { return const_cast(this)->IsType1HWeapon(); } - bool IsType2HWeapon() const { return const_cast(this)->IsType2HWeapon(); } - bool IsTypeShield() const { return const_cast(this)->IsTypeShield(); } + bool IsEquipable(uint16 Race, uint16 Class) const { return const_cast(this)->IsEquipable(Race, Class); } + bool IsClassCommon() const { return const_cast(this)->IsClassCommon(); } + bool IsClassBag() const { return const_cast(this)->IsClassBag(); } + bool IsClassBook() const { return const_cast(this)->IsClassBook(); } + bool IsType1HWeapon() const { return const_cast(this)->IsType1HWeapon(); } + bool IsType2HWeapon() const { return const_cast(this)->IsType2HWeapon(); } + bool IsTypeShield() const { return const_cast(this)->IsTypeShield(); } }; } /*EQEmu*/ -#endif /*COMMON_ITEM_STRUCT_H*/ +#endif /*COMMON_ITEM_BASE_H*/ diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 72d3b75de..2c185e1d1 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -5201,7 +5201,7 @@ namespace RoF void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - const EQEmu::Item_Struct *item = inst->GetUnscaledItem(); + const EQEmu::ItemBase *item = inst->GetUnscaledItem(); RoF::structs::ItemSerializationHeader hdr; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 9f906f991..c44caba92 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -5476,7 +5476,7 @@ namespace RoF2 void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type) { - const EQEmu::Item_Struct *item = inst->GetUnscaledItem(); + const EQEmu::ItemBase *item = inst->GetUnscaledItem(); RoF2::structs::ItemSerializationHeader hdr; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 6d764857f..3f7130f1b 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -2446,7 +2446,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + ItemBase item; uint8 iss_unknown001[6]; };*/ diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index a0d95f841..03cad1ef8 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -2473,7 +2473,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + ItemBase item; uint8 iss_unknown001[6]; };*/ diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 43f0d4b63..4be952131 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -3546,7 +3546,7 @@ namespace SoD void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - const EQEmu::Item_Struct *item = inst->GetUnscaledItem(); + const EQEmu::ItemBase *item = inst->GetUnscaledItem(); SoD::structs::ItemSerializationHeader hdr; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 5acb51ad1..ea9046a78 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1995,7 +1995,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + ItemBase item; uint8 iss_unknown001[6]; };*/ diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 229031801..877489676 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2887,7 +2887,7 @@ namespace SoF void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - const EQEmu::Item_Struct *item = inst->GetUnscaledItem(); + const EQEmu::ItemBase *item = inst->GetUnscaledItem(); SoF::structs::ItemSerializationHeader hdr; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 201f69629..5d3ae0318 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -2107,7 +2107,7 @@ namespace Titanium void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const char* protection = "\\\\\\\\\\"; - const EQEmu::Item_Struct* item = inst->GetUnscaledItem(); + const EQEmu::ItemBase* item = inst->GetUnscaledItem(); ob << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index e16fce125..89199dee9 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -3841,7 +3841,7 @@ namespace UF void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { - const EQEmu::Item_Struct *item = inst->GetUnscaledItem(); + const EQEmu::ItemBase *item = inst->GetUnscaledItem(); UF::structs::ItemSerializationHeader hdr; @@ -3885,7 +3885,7 @@ namespace UF int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); uint16 ornaIcon = 0; if (inst->GetOrnamentationAug(ornamentationAugtype)) { - const EQEmu::Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const EQEmu::ItemBase *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); ornaIcon = aug_weap->Icon; ob.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 808cef4df..21fbdf15f 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -2054,7 +2054,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - Item_Struct item; + ItemBase item; uint8 iss_unknown001[6]; };*/ diff --git a/common/say_link.cpp b/common/say_link.cpp index 6d64837e3..12c1d80d1 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -22,7 +22,7 @@ #include "string_util.h" #include "item.h" -#include "item_struct.h" +#include "item_base.h" #include "../zone/zonedb.h" @@ -99,7 +99,7 @@ void EQEmu::saylink::SayLinkEngine::generate_body() memset(&m_LinkBodyStruct, 0, sizeof(SayLinkBody_Struct)); - const EQEmu::Item_Struct* item_data = nullptr; + const EQEmu::ItemBase* item_data = nullptr; switch (m_LinkType) { case SayLinkBlank: @@ -202,7 +202,7 @@ void EQEmu::saylink::SayLinkEngine::generate_text() return; } - const EQEmu::Item_Struct* item_data = nullptr; + const EQEmu::ItemBase* item_data = nullptr; switch (m_LinkType) { case SayLinkBlank: diff --git a/common/say_link.h b/common/say_link.h index 5230f7b15..dcc327cad 100644 --- a/common/say_link.h +++ b/common/say_link.h @@ -31,7 +31,7 @@ class ItemInst; namespace EQEmu { - struct Item_Struct; + struct ItemBase; namespace saylink { struct SayLinkBody_Struct; // Current server mask: EQClientRoF2 @@ -74,7 +74,7 @@ public: SayLinkEngine(); void SetLinkType(SayLinkType link_type) { m_LinkType = link_type; } - void SetItemData(const EQEmu::Item_Struct* item_data) { m_ItemData = item_data; } + void SetItemData(const EQEmu::ItemBase* item_data) { m_ItemData = item_data; } void SetLootData(const ServerLootItem_Struct* loot_data) { m_LootData = loot_data; } void SetItemInst(const ItemInst* item_inst) { m_ItemInst = item_inst; } @@ -110,7 +110,7 @@ private: void generate_text(); int m_LinkType; - const EQEmu::Item_Struct* m_ItemData; + const EQEmu::ItemBase* m_ItemData; const ServerLootItem_Struct* m_LootData; const ItemInst* m_ItemInst; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 634a2b0b1..6748300d4 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -364,7 +364,7 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) { bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) { - const EQEmu::Item_Struct* myitem; + const EQEmu::ItemBase* myitem; std::string query = StringFormat("SELECT itemid, item_charges, slot FROM starting_items " "WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND " @@ -436,7 +436,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) aug[4] = (uint32)atoi(row[7]); aug[5] = (uint32)atoi(row[8]); - const EQEmu::Item_Struct *item = GetItem(item_id); + const EQEmu::ItemBase *item = GetItem(item_id); if (!item) { Log.Out(Logs::General, Logs::Error, @@ -538,7 +538,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) uint32 ornament_idfile = (uint32)atoul(row[13]); uint32 ornament_hero_model = (uint32)atoul(row[14]); - const EQEmu::Item_Struct *item = GetItem(item_id); + const EQEmu::ItemBase *item = GetItem(item_id); if (!item) { Log.Out(Logs::General, Logs::Error, @@ -679,7 +679,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) uint32 ornament_idfile = (uint32)atoul(row[13]); uint32 ornament_hero_model = (uint32)atoul(row[14]); - const EQEmu::Item_Struct *item = GetItem(item_id); + const EQEmu::ItemBase *item = GetItem(item_id); int16 put_slot_id = INVALID_INDEX; if (!item) continue; @@ -816,7 +816,7 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { mutex.Lock(); std::string file_name = Config->SharedMemDir + prefix + std::string("items"); items_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); - items_hash = std::unique_ptr>(new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), items_mmf->Size())); + items_hash = std::unique_ptr>(new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), items_mmf->Size())); mutex.Unlock(); } catch(std::exception& ex) { Log.Out(Logs::General, Logs::Error, "Error Loading Items: %s", ex.what()); @@ -828,7 +828,7 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id) { - EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); + EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); std::string ndbuffer; bool disableNoRent = false; @@ -856,7 +856,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } } - EQEmu::Item_Struct item; + EQEmu::ItemBase item; const std::string query = "SELECT source," #define F(x) "`"#x"`," @@ -869,7 +869,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } for (auto row = results.begin(); row != results.end(); ++row) { - memset(&item, 0, sizeof(EQEmu::Item_Struct)); + memset(&item, 0, sizeof(EQEmu::ItemBase)); item.ItemClass = (uint8)atoi(row[ItemField::itemclass]); strcpy(item.Name, row[ItemField::name]); @@ -1086,7 +1086,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } } -const EQEmu::Item_Struct* SharedDatabase::GetItem(uint32 id) { +const EQEmu::ItemBase* SharedDatabase::GetItem(uint32 id) { if (id == 0) { return nullptr; @@ -1105,7 +1105,7 @@ const EQEmu::Item_Struct* SharedDatabase::GetItem(uint32 id) { return nullptr; } -const EQEmu::Item_Struct* SharedDatabase::IterateItems(uint32* id) { +const EQEmu::ItemBase* SharedDatabase::IterateItems(uint32* id) { if(!items_hash || !id) { return nullptr; } @@ -1253,7 +1253,7 @@ bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) { // Create appropriate ItemInst class ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) { - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; ItemInst* inst = nullptr; item = GetItem(item_id); @@ -1280,7 +1280,7 @@ ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, // Create appropriate ItemInst class -ItemInst* SharedDatabase::CreateItem(const EQEmu::Item_Struct* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) +ItemInst* SharedDatabase::CreateItem(const EQEmu::ItemBase* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) { ItemInst* inst = nullptr; if (item) { @@ -1304,7 +1304,7 @@ ItemInst* SharedDatabase::CreateItem(const EQEmu::Item_Struct* item, int16 charg return inst; } -ItemInst* SharedDatabase::CreateBaseItem(const EQEmu::Item_Struct* item, int16 charges) { +ItemInst* SharedDatabase::CreateBaseItem(const EQEmu::ItemBase* item, int16 charges) { ItemInst* inst = nullptr; if (item) { // if maxcharges is -1 that means it is an unlimited use item. diff --git a/common/shareddb.h b/common/shareddb.h index 719735ecd..68e1821d3 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -42,9 +42,10 @@ struct SPDat_Spell_Struct; struct NPCFactionList; struct LootTable_Struct; struct LootDrop_Struct; + namespace EQEmu { - struct Item_Struct; + struct ItemBase; class MemoryMappedFile; } @@ -99,8 +100,8 @@ class SharedDatabase : public Database Item Methods */ ItemInst* CreateItem(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); - ItemInst* CreateItem(const EQEmu::Item_Struct* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); - ItemInst* CreateBaseItem(const EQEmu::Item_Struct* item, int16 charges = 0); + ItemInst* CreateItem(const EQEmu::ItemBase* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); + ItemInst* CreateBaseItem(const EQEmu::ItemBase* item, int16 charges = 0); /* Shared Memory crap @@ -110,8 +111,8 @@ class SharedDatabase : public Database void GetItemsCount(int32 &item_count, uint32 &max_id); void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id); bool LoadItems(const std::string &prefix); - const EQEmu::Item_Struct* IterateItems(uint32* id); - const EQEmu::Item_Struct* GetItem(uint32 id); + const EQEmu::ItemBase* IterateItems(uint32* id); + const EQEmu::ItemBase* GetItem(uint32 id); const EvolveInfo* GetEvolveInfo(uint32 loregroup); //faction lists @@ -148,7 +149,7 @@ class SharedDatabase : public Database std::unique_ptr skill_caps_mmf; std::unique_ptr items_mmf; - std::unique_ptr> items_hash; + std::unique_ptr> items_hash; std::unique_ptr faction_mmf; std::unique_ptr> faction_hash; std::unique_ptr loot_table_mmf; diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index e2fb98f16..e4c938af2 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -22,7 +22,7 @@ #include "../common/ipc_mutex.h" #include "../common/memory_mapped_file.h" #include "../common/eqemu_exception.h" -#include "../common/item_struct.h" +#include "../common/item_base.h" void LoadItems(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("items"); @@ -35,7 +35,7 @@ void LoadItems(SharedDatabase *database, const std::string &prefix) { EQ_EXCEPT("Shared Memory", "Unable to get any items from the database."); } - uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); + uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); auto Config = EQEmuConfig::get(); std::string file_name = Config->SharedMemDir + prefix + std::string("items"); diff --git a/tests/fixed_memory_test.h b/tests/fixed_memory_test.h index e0c74bac9..06b529f3c 100644 --- a/tests/fixed_memory_test.h +++ b/tests/fixed_memory_test.h @@ -27,7 +27,7 @@ class FixedMemoryHashTest : public Test::Suite { typedef void(FixedMemoryHashTest::*TestFunction)(void); public: FixedMemoryHashTest() { - size_ = EQEmu::FixedMemoryHashSet::estimated_size(72000, 190000); + size_ = EQEmu::FixedMemoryHashSet::estimated_size(72000, 190000); data_ = new uint8[size_]; memset(data_, 0, size_); TEST_ADD(FixedMemoryHashTest::InitTest); @@ -49,7 +49,7 @@ public: private: void InitTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_, 72000, 190000); + EQEmu::FixedMemoryHashSet hash(data_, size_, 72000, 190000); TEST_ASSERT(!hash.exists(1001)); TEST_ASSERT(hash.size() == 0); TEST_ASSERT(hash.max_size() == 72000); @@ -57,7 +57,7 @@ public: } void LoadTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(!hash.exists(1001)); TEST_ASSERT(hash.size() == 0); TEST_ASSERT(hash.max_size() == 72000); @@ -65,8 +65,8 @@ public: } void InsertTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - EQEmu::Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::ItemBase item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Iron Sword"); item.ID = 1001; @@ -79,20 +79,20 @@ public: } void RetrieveTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 1); TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - EQEmu::Item_Struct item = hash[1001]; + EQEmu::ItemBase item = hash[1001]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1001); } void OverwriteTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - EQEmu::Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::ItemBase item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Steel Sword"); item.ID = 1001; @@ -105,20 +105,20 @@ public: } void OverwriteRetrieveTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 1); TEST_ASSERT((hash.max_size() == 72000)); TEST_ASSERT(!hash.empty()); - EQEmu::Item_Struct item = hash[1001]; + EQEmu::ItemBase item = hash[1001]; TEST_ASSERT(strcmp(item.Name, "Steel Sword") == 0); TEST_ASSERT(item.ID == 1001); } void InsertAgainTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - EQEmu::Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::ItemBase item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Iron Sword"); item.ID = 1000; @@ -132,14 +132,14 @@ public: } void RetrieveAgainTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 2); TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - EQEmu::Item_Struct item = hash[1000]; + EQEmu::ItemBase item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); @@ -149,8 +149,8 @@ public: } void InsertBeginTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - EQEmu::Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::ItemBase item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Bronze Sword"); item.ID = 0; @@ -165,7 +165,7 @@ public: } void RetrieveBeginTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.exists(0)); @@ -173,7 +173,7 @@ public: TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - EQEmu::Item_Struct item = hash[1000]; + EQEmu::ItemBase item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); @@ -187,8 +187,8 @@ public: } void InsertEndTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - EQEmu::Item_Struct item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::ItemBase item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Jade Sword"); item.ID = 190000; @@ -204,7 +204,7 @@ public: } void RetrieveEndTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.exists(0)); @@ -213,7 +213,7 @@ public: TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - EQEmu::Item_Struct item = hash[1000]; + EQEmu::ItemBase item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); diff --git a/world/worlddb.cpp b/world/worlddb.cpp index b41672a33..684ab0d64 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -245,7 +245,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou /* Load Inventory */ // If we ensure that the material data is updated appropriately, we can do away with inventory loads if (GetInventory(accountID, cse->Name, &inv)) { - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; const ItemInst* inst = nullptr; int16 invslot = 0; diff --git a/zone/aa.cpp b/zone/aa.cpp index 477de240e..1473a1bee 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -423,7 +423,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) uint32 sitem = 0; sitem = CorpseToUse->GetWornItem(x); if(sitem){ - const EQEmu::Item_Struct * itm = database.GetItem(sitem); + const EQEmu::ItemBase * itm = database.GetItem(sitem); npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 127, true, true); } } diff --git a/zone/attack.cpp b/zone/attack.cpp index 8cf3971f8..8b7d5dba0 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -55,7 +55,7 @@ bool Mob::AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const // Determine animation int type = 0; if (weapon && weapon->IsClassCommon()) { - const EQEmu::Item_Struct* item = weapon->GetItem(); + const EQEmu::ItemBase* item = weapon->GetItem(); Log.Out(Logs::Detail, Logs::Attack, "Weapon skill : %i", item->ItemType); @@ -788,9 +788,9 @@ int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, //Returns the weapon damage against the input mob //if we cannot hit the mob with the current weapon we will get a value less than or equal to zero //Else we know we can hit. -//GetWeaponDamage(mob*, const Item_Struct*) is intended to be used for mobs or any other situation where we do not have a client inventory item +//GetWeaponDamage(mob*, const ItemBase*) is intended to be used for mobs or any other situation where we do not have a client inventory item //GetWeaponDamage(mob*, const ItemInst*) is intended to be used for situations where we have a client inventory item -int Mob::GetWeaponDamage(Mob *against, const EQEmu::Item_Struct *weapon_item) { +int Mob::GetWeaponDamage(Mob *against, const EQEmu::ItemBase *weapon_item) { int dmg = 0; int banedmg = 0; @@ -1116,7 +1116,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const EQEmu::Item_Struct*) nullptr ); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemBase*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; @@ -1127,7 +1127,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if (Hand == EQEmu::legacy::SlotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::Item_Struct*) nullptr, true ); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemBase*) nullptr, true); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; @@ -1595,7 +1595,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool } //figure out what weapon they are using, if any - const EQEmu::Item_Struct* weapon = nullptr; + const EQEmu::ItemBase* weapon = nullptr; if (Hand == EQEmu::legacy::SlotPrimary && equipment[EQEmu::legacy::SlotPrimary] > 0) weapon = database.GetItem(equipment[EQEmu::legacy::SlotPrimary]); else if (equipment[EQEmu::legacy::SlotSecondary]) @@ -2517,7 +2517,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) { } } -uint8 Mob::GetWeaponDamageBonus(const EQEmu::Item_Struct *weapon, bool offhand) +uint8 Mob::GetWeaponDamageBonus(const EQEmu::ItemBase *weapon, bool offhand) { // dev quote with old and new formulas // https://forums.daybreakgames.com/eq/index.php?threads/test-update-09-17-15.226618/page-5#post-3326194 @@ -3548,12 +3548,12 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { } if(!weapon_g) { - TrySpellProc(nullptr, (const EQEmu::Item_Struct*)nullptr, on); + TrySpellProc(nullptr, (const EQEmu::ItemBase*)nullptr, on); return; } if (!weapon_g->IsClassCommon()) { - TrySpellProc(nullptr, (const EQEmu::Item_Struct*)nullptr, on); + TrySpellProc(nullptr, (const EQEmu::ItemBase*)nullptr, on); return; } @@ -3566,7 +3566,7 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { return; } -void Mob::TryWeaponProc(const ItemInst *inst, const EQEmu::Item_Struct *weapon, Mob *on, uint16 hand) +void Mob::TryWeaponProc(const ItemInst *inst, const EQEmu::ItemBase *weapon, Mob *on, uint16 hand) { if (!weapon) @@ -3619,7 +3619,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const EQEmu::Item_Struct *weapon, const ItemInst *aug_i = inst->GetAugment(r); if (!aug_i) // no aug, try next slot! continue; - const EQEmu::Item_Struct *aug = aug_i->GetItem(); + const EQEmu::ItemBase *aug = aug_i->GetItem(); if (!aug) continue; @@ -3649,7 +3649,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const EQEmu::Item_Struct *weapon, return; } -void Mob::TrySpellProc(const ItemInst *inst, const EQEmu::Item_Struct *weapon, Mob *on, uint16 hand) +void Mob::TrySpellProc(const ItemInst *inst, const EQEmu::ItemBase *weapon, Mob *on, uint16 hand) { float ProcBonus = static_cast(spellbonuses.SpellProcChance + itembonuses.SpellProcChance + aabonuses.SpellProcChance); @@ -4506,7 +4506,7 @@ void Client::SetAttackTimer() else //invalid slot (hands will always hit this) continue; - const EQEmu::Item_Struct *ItemToUse = nullptr; + const EQEmu::ItemBase *ItemToUse = nullptr; //find our item ItemInst *ci = GetInv().GetItem(i); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index ab15326cc..2a8a0c790 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -152,7 +152,7 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { AddItemBonuses(inst, newbon, false, false, 0, (i == EQEmu::legacy::SlotAmmo)); //These are given special flags due to how often they are checked for various spell effects. - const EQEmu::Item_Struct *item = inst->GetItem(); + const EQEmu::ItemBase *item = inst->GetItem(); if (i == EQEmu::legacy::SlotSecondary && (item && item->ItemType == EQEmu::item::ItemTypeShield)) SetShieldEquiped(true); else if (i == EQEmu::legacy::SlotPrimary && (item && item->ItemType == EQEmu::item::ItemType2HBlunt)) { @@ -218,7 +218,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu return; } - const EQEmu::Item_Struct *item = inst->GetItem(); + const EQEmu::ItemBase *item = inst->GetItem(); if (!isTribute && !inst->IsEquipable(GetBaseRace(), GetClass())) { if (item->ItemType != EQEmu::item::ItemTypeFood && item->ItemType != EQEmu::item::ItemTypeDrink) @@ -550,7 +550,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool if(inst->GetAugmentType()==0 && isAug == true) return; - const EQEmu::Item_Struct *item = inst->GetItem(); + const EQEmu::ItemBase *item = inst->GetItem(); if(!inst->IsEquipable(GetBaseRace(),GetClass())) return; @@ -582,7 +582,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { break; const ItemInst* inst = GetInv().GetItem(i); if (inst && inst->GetItem() && inst->IsClassCommon()) { - const EQEmu::Item_Struct *item=inst->GetItem(); + const EQEmu::ItemBase *item = inst->GetItem(); if (item->ItemType == EQEmu::item::ItemTypeFood && !food) food = true; else if (item->ItemType == EQEmu::item::ItemTypeDrink && !drink) @@ -598,7 +598,7 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { break; const ItemInst* inst = GetInv().GetItem(i); if (inst && inst->GetItem() && inst->IsClassCommon()) { - const EQEmu::Item_Struct *item=inst->GetItem(); + const EQEmu::ItemBase *item = inst->GetItem(); if (item->ItemType == EQEmu::item::ItemTypeFood && !food) food = true; else if (item->ItemType == EQEmu::item::ItemTypeDrink && !drink) @@ -3203,7 +3203,7 @@ void NPC::CalcItemBonuses(StatBonuses *newbon) if(newbon){ for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++){ - const EQEmu::Item_Struct *cur = database.GetItem(equipment[i]); + const EQEmu::ItemBase *cur = database.GetItem(equipment[i]); if(cur){ //basic stats newbon->AC += cur->AC; diff --git a/zone/bot.cpp b/zone/bot.cpp index a72c8f142..3af2d161f 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -234,8 +234,8 @@ uint32 Bot::GetBotArcheryRange() { if (!range_inst || !ammo_inst) return 0; - const EQEmu::Item_Struct *range_item = range_inst->GetItem(); - const EQEmu::Item_Struct *ammo_item = ammo_inst->GetItem(); + const EQEmu::ItemBase *range_item = range_inst->GetItem(); + const EQEmu::ItemBase *ammo_item = ammo_inst->GetItem(); if (!range_item || !ammo_item || range_item->ItemType != EQEmu::item::ItemTypeBow || ammo_item->ItemType != EQEmu::item::ItemTypeArrow) return 0; @@ -1899,12 +1899,12 @@ void Bot::BotRangedAttack(Mob* other) { } ItemInst* rangedItem = GetBotItem(EQEmu::legacy::SlotRange); - const EQEmu::Item_Struct* RangeWeapon = 0; + const EQEmu::ItemBase* RangeWeapon = 0; if(rangedItem) RangeWeapon = rangedItem->GetItem(); ItemInst* ammoItem = GetBotItem(EQEmu::legacy::SlotAmmo); - const EQEmu::Item_Struct* Ammo = 0; + const EQEmu::ItemBase* Ammo = 0; if(ammoItem) Ammo = ammoItem->GetItem(); @@ -2013,7 +2013,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: int32 min_hit = 1; int32 max_hit = ((2 * weapon_damage * GetDamageTable(skillinuse)) / 100); if(GetLevel() >= 28 && IsWarriorClass()) { - int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::Item_Struct*) nullptr); + int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::ItemBase*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -2055,7 +2055,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: if (skillinuse == EQEmu::skills::SkillBash){ const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); - const EQEmu::Item_Struct* botweapon = 0; + const EQEmu::ItemBase* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -2115,7 +2115,7 @@ void Bot::ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int3 if (item_slot >= EQEmu::legacy::EQUIPMENT_BEGIN){ const ItemInst* inst = GetBotItem(item_slot); - const EQEmu::Item_Struct* botweapon = 0; + const EQEmu::ItemBase* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -2503,7 +2503,7 @@ void Bot::AI_Process() { //now off hand if(GetTarget() && attack_dw_timer.Check() && CanThisClassDualWield()) { const ItemInst* instweapon = GetBotItem(EQEmu::legacy::SlotSecondary); - const EQEmu::Item_Struct* weapon = 0; + const EQEmu::ItemBase* weapon = 0; //can only dual wield without a weapon if you're a monk if(instweapon || (botClass == MONK)) { if(instweapon) @@ -2950,7 +2950,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; ns->spawn.helm = helmtexture; //(GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.equip_chest2 = texture; //0xFF; - const EQEmu::Item_Struct* item = 0; + const EQEmu::ItemBase* item = 0; const ItemInst* inst = 0; uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); @@ -3393,7 +3393,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli //EQoffline: will give the items to the bots and change the bot stats if(inst && (GetBotOwner() == client->CastToMob()) && !IsEngaged()) { std::string TempErrorMessage; - const EQEmu::Item_Struct* mWeaponItem = inst->GetItem(); + const EQEmu::ItemBase* mWeaponItem = inst->GetItem(); bool failedLoreCheck = false; for (int m = AUG_INDEX_BEGIN; m < EQEmu::legacy::ITEM_COMMON_SIZE; ++m) { ItemInst *itm = inst->GetAugment(m); @@ -3572,7 +3572,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } - const EQEmu::Item_Struct* item2 = 0; + const EQEmu::ItemBase* item2 = 0; for(int y = beginSlotID; y <= endSlotID; ++y) { item2 = database.GetItem(items[y]); if(item2) { @@ -3811,7 +3811,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::Item_Struct*) nullptr); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemBase*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -3820,7 +3820,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. if (Hand == EQEmu::legacy::SlotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::Item_Struct*) nullptr); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemBase*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -4278,8 +4278,8 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[bottype]) { - const EQEmu::Item_Struct* TempItem = 0; - const EQEmu::Item_Struct* UsedItem = 0; + const EQEmu::ItemBase* TempItem = 0; + const EQEmu::ItemBase* UsedItem = 0; const ItemInst* TempInst = 0; uint16 UsedFocusID = 0; int32 Total = 0; @@ -4315,7 +4315,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { ItemInst *aug = nullptr; aug = ins->GetAugment(y); if(aug) { - const EQEmu::Item_Struct* TempItemAug = aug->GetItem(); + const EQEmu::ItemBase* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { focus_max = CalcBotFocusEffect(bottype, TempItemAug->Focus.Effect, spell_id, true); @@ -4863,7 +4863,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 if (skill == EQEmu::skills::SkillBash) { const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); - const EQEmu::Item_Struct* botweapon = 0; + const EQEmu::ItemBase* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -4928,7 +4928,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { bool bIsBehind = false; bool bCanFrontalBS = false; const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotPrimary); - const EQEmu::Item_Struct* botpiercer = nullptr; + const EQEmu::ItemBase* botpiercer = nullptr; if(inst) botpiercer = inst->GetItem(); @@ -5365,7 +5365,7 @@ bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) { void Bot::EquipBot(std::string* errorMessage) { GetBotItems(m_inv, errorMessage); const ItemInst* inst = 0; - const EQEmu::Item_Struct* item = 0; + const EQEmu::ItemBase* item = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { @@ -5492,7 +5492,7 @@ void Bot::SetAttackTimer() { float haste_mod = (GetHaste() * 0.01f); attack_timer.SetAtTrigger(4000, true); Timer* TimerToUse = nullptr; - const EQEmu::Item_Struct* PrimaryWeapon = nullptr; + const EQEmu::ItemBase* PrimaryWeapon = nullptr; for (int i = EQEmu::legacy::SlotRange; i <= EQEmu::legacy::SlotSecondary; i++) { if (i == EQEmu::legacy::SlotPrimary) TimerToUse = &attack_timer; @@ -5503,7 +5503,7 @@ void Bot::SetAttackTimer() { else continue; - const EQEmu::Item_Struct* ItemToUse = nullptr; + const EQEmu::ItemBase* ItemToUse = nullptr; ItemInst* ci = GetBotItem(i); if (ci) ItemToUse = ci->GetItem(); @@ -7178,7 +7178,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { insr->TargetID = inspectedBot->GetNPCTypeID(); insr->playerid = inspectedBot->GetID(); - const EQEmu::Item_Struct* item = 0; + const EQEmu::ItemBase* item = 0; const ItemInst* inst = 0; // Modded to display power source items (will only show up on SoF+ client inspect windows though.) @@ -7230,7 +7230,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { void Bot::CalcItemBonuses(StatBonuses* newbon) { - const EQEmu::Item_Struct* itemtmp = 0; + const EQEmu::ItemBase* itemtmp = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { const ItemInst* item = GetBotItem((i == 22 ? 9999 : i)); @@ -7261,7 +7261,7 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, return; } - const EQEmu::Item_Struct *item = inst->GetItem(); + const EQEmu::ItemBase *item = inst->GetItem(); if(!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass())) { @@ -7628,7 +7628,7 @@ void Bot::CalcBotStats(bool showtext) { } } -bool Bot::CheckLoreConflict(const EQEmu::Item_Struct* item) { +bool Bot::CheckLoreConflict(const EQEmu::ItemBase* item) { if (!item || !(item->LoreFlag)) return false; @@ -8051,7 +8051,7 @@ int Bot::GetRawACNoShield(int &shield_ac) { } uint32 Bot::CalcCurrentWeight() { - const EQEmu::Item_Struct* TempItem = 0; + const EQEmu::ItemBase* TempItem = 0; ItemInst* inst; uint32 Total = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { diff --git a/zone/bot.h b/zone/bot.h index da42147a2..9e88e0072 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -385,7 +385,7 @@ public: void BotTradeSwapItem(Client* client, int16 lootSlot, const ItemInst* inst, const ItemInst* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap = true); void BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true); void EquipBot(std::string* errorMessage); - bool CheckLoreConflict(const EQEmu::Item_Struct* item); + bool CheckLoreConflict(const EQEmu::ItemBase* item); virtual void UpdateEquipmentLight() { m_Light.Type[EQEmu::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); } // Static Class Methods diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 2884ec838..a413dfed2 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -7063,7 +7063,7 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) } const ItemInst* inst = nullptr; - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; bool is2Hweapon = false; std::string item_link; @@ -7132,7 +7132,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) return; } - const EQEmu::Item_Struct* itm = nullptr; + const EQEmu::ItemBase* itm = nullptr; const ItemInst* itminst = my_bot->GetBotItem(slotId); if (itminst) itm = itminst->GetItem(); @@ -7235,7 +7235,7 @@ void bot_subcommand_inventory_window(Client *c, const Seperator *sep) //linker.SetLinkType(linker.linkItemInst); for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; const ItemInst* inst = my_bot->CastToBot()->GetBotItem(i == 22 ? EQEmu::legacy::SlotPowerSource : i); if (inst) item = inst->GetItem(); diff --git a/zone/client.cpp b/zone/client.cpp index 4027bb6e1..2dba5ca35 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2539,7 +2539,7 @@ void Client::SetFeigned(bool in_feigned) { feigned=in_feigned; } -void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::Item_Struct* item, bool buying) +void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::ItemBase* item, bool buying) { if(!player || !merchant || !item) return; @@ -2726,7 +2726,7 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail) } void Client::SetMaterial(int16 in_slot, uint32 item_id) { - const EQEmu::Item_Struct* item = database.GetItem(item_id); + const EQEmu::ItemBase* item = database.GetItem(item_id); if (item && item->IsClassCommon()) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); @@ -3769,7 +3769,7 @@ void Client::SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID) { return; } -void Client::SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu::Item_Struct* item){ +void Client::SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu::ItemBase* item){ auto outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); sPickPocket_Struct *pick_out = (sPickPocket_Struct *)outapp->pBuffer; pick_out->coin = amt; @@ -3943,7 +3943,7 @@ bool Client::KeyRingCheck(uint32 item_id) void Client::KeyRingList() { Message(4,"Keys on Keyring:"); - const EQEmu::Item_Struct *item = 0; + const EQEmu::ItemBase *item = 0; for (auto iter = keyring.begin(); iter != keyring.end(); ++iter) { if ((item = database.GetItem(*iter))!=nullptr) { Message(4,item->Name); @@ -5686,7 +5686,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { insr->TargetID = requester->GetID(); insr->playerid = requestee->GetID(); - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; const ItemInst* inst = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); for(int16 L = 0; L <= 20; L++) { @@ -5698,7 +5698,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { strcpy(insr->itemnames[L], item->Name); if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - const EQEmu::Item_Struct *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const EQEmu::ItemBase *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); insr->itemicons[L] = aug_item->Icon; } else if (inst && inst->GetOrnamentationIcon()) @@ -6879,7 +6879,7 @@ void Client::SendAltCurrencies() { uint32 i = 0; auto iter = zone->AlternateCurrencies.begin(); while(iter != zone->AlternateCurrencies.end()) { - const EQEmu::Item_Struct* item = database.GetItem((*iter).item_id); + const EQEmu::ItemBase* item = database.GetItem((*iter).item_id); altc->entries[i].currency_number = (*iter).id; altc->entries[i].unknown00 = 1; altc->entries[i].currency_number2 = (*iter).id; @@ -7534,7 +7534,7 @@ void Client::DuplicateLoreMessage(uint32 ItemID) return; } - const EQEmu::Item_Struct *item = database.GetItem(ItemID); + const EQEmu::ItemBase *item = database.GetItem(ItemID); if(!item) return; @@ -8251,7 +8251,7 @@ void Client::SetConsumption(int32 in_hunger, int32 in_thirst) safe_delete(outapp); } -void Client::Consume(const EQEmu::Item_Struct *item, uint8 type, int16 slot, bool auto_consume) +void Client::Consume(const EQEmu::ItemBase *item, uint8 type, int16 slot, bool auto_consume) { if(!item) { return; } diff --git a/zone/client.h b/zone/client.h index ca26c8fcb..b401eac53 100644 --- a/zone/client.h +++ b/zone/client.h @@ -30,15 +30,14 @@ class ServerPacket; namespace EQEmu { - struct Item_Struct; + struct ItemBase; } #include "../common/timer.h" #include "../common/ptimer.h" #include "../common/emu_opcodes.h" #include "../common/eq_packet_structs.h" -//#include "../common/eq_constants.h" -#include "../common/emu_constants.h" // inv2 watch +#include "../common/emu_constants.h" #include "../common/eq_stream_intf.h" #include "../common/eq_packet.h" #include "../common/linked_list.h" @@ -47,8 +46,7 @@ namespace EQEmu #include "../common/seperator.h" #include "../common/item.h" #include "../common/guilds.h" -#include "../common/item_struct.h" -//#include "../common/clientversions.h" +#include "../common/item_base.h" #include "common.h" #include "merc.h" @@ -294,7 +292,7 @@ public: void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); virtual bool Process(); - void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::Item_Struct* item, bool buying); + void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::ItemBase* item, bool buying); void SendPacketQueue(bool Block = true); void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone); void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL); @@ -402,7 +400,7 @@ public: inline uint8 GetLanguageSkill(uint16 n) const { return m_pp.languages[n]; } - void SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu::Item_Struct* item = nullptr); + void SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu::ItemBase* item = nullptr); inline const char* GetLastName() const { return lastname; } @@ -598,7 +596,7 @@ public: void AssignToInstance(uint16 instance_id); void RemoveFromInstance(uint16 instance_id); void WhoAll(); - bool CheckLoreConflict(const EQEmu::Item_Struct* item); + bool CheckLoreConflict(const EQEmu::ItemBase* item); void ChangeLastName(const char* in_lastname); void GetGroupAAs(GroupLeadershipAA_Struct *into) const; void GetRaidAAs(RaidLeadershipAA_Struct *into) const; @@ -823,7 +821,7 @@ public: void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); - int GetItemLinkHash(const ItemInst* inst); // move to Item_Struct..or make use of the pre-calculated database field + int GetItemLinkHash(const ItemInst* inst); // move to ItemBase..or make use of the pre-calculated database field void SendItemLink(const ItemInst* inst, bool sendtoall=false); void SendLootItemInPacket(const ItemInst* inst, int16 slot_id); @@ -1178,7 +1176,7 @@ public: void SetAccountFlag(std::string flag, std::string val); std::string GetAccountFlag(std::string flag); float GetDamageMultiplier(EQEmu::skills::SkillType how_long_has_this_been_missing); - void Consume(const EQEmu::Item_Struct *item, uint8 type, int16 slot, bool auto_consume); + void Consume(const EQEmu::ItemBase *item, uint8 type, int16 slot, bool auto_consume); void PlayMP3(const char* fname); void ExpeditionSay(const char *str, int ExpID); int mod_client_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const ItemInst* weapon, Mob* other); @@ -1200,9 +1198,9 @@ public: int32 mod_client_xp(int32 in_exp, NPC *npc); uint32 mod_client_xp_for_level(uint32 xp, uint16 check_level); int mod_client_haste_cap(int cap); - int mod_consume(EQEmu::Item_Struct *item, EQEmu::item::ItemType type, int change); - int mod_food_value(const EQEmu::Item_Struct *item, int change); - int mod_drink_value(const EQEmu::Item_Struct *item, int change); + int mod_consume(EQEmu::ItemBase *item, EQEmu::item::ItemType type, int change); + int mod_food_value(const EQEmu::ItemBase *item, int change); + int mod_drink_value(const EQEmu::ItemBase *item, int change); void SetEngagedRaidTarget(bool value) { EngagedRaidTarget = value; } bool GetEngagedRaidTarget() const { return EngagedRaidTarget; } diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 1311f7b53..fbbce59ce 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1302,7 +1302,7 @@ int32 Client::CalcManaRegenCap() uint32 Client::CalcCurrentWeight() { - const EQEmu::Item_Struct* TempItem = 0; + const EQEmu::ItemBase* TempItem = 0; ItemInst* ins; uint32 Total = 0; int x; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e30f06741..5a5a2ca47 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1881,7 +1881,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) merchantid = tmp->CastToNPC()->MerchantType; - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; bool found = false; std::list merlist = zone->merchanttable[merchantid]; std::list::const_iterator itr; @@ -2057,7 +2057,7 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app) merchantid = tmp->CastToNPC()->MerchantType; tmp->CastToNPC()->FaceTarget(this->CastToMob()); - const EQEmu::Item_Struct *item = 0; + const EQEmu::ItemBase *item = 0; std::list merlist = zone->merchanttable[merchantid]; std::list::const_iterator itr; for (itr = merlist.begin(); itr != merlist.end() && count<255; ++itr){ @@ -2156,7 +2156,7 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app) return; } - const EQEmu::Item_Struct* item = database.GetItem(itemid); + const EQEmu::ItemBase* item = database.GetItem(itemid); ItemInst* inst = GetInv().GetItem(ams_in->slot); if (!item || !inst){ Message(13, "You seemed to have misplaced that item..."); @@ -2432,7 +2432,7 @@ void Client::Handle_OP_AltCurrencyMerchantRequest(const EQApplicationPacket *app ss << alt_cur_id << "|1|" << alt_cur_id; uint32 count = 0; uint32 merchant_id = tar->MerchantType; - const EQEmu::Item_Struct *item = nullptr; + const EQEmu::ItemBase *item = nullptr; std::list merlist = zone->merchanttable[merchant_id]; std::list::const_iterator itr; @@ -2492,7 +2492,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) return; } - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2641,7 +2641,7 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) return; } - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2734,7 +2734,7 @@ void Client::Handle_OP_AltCurrencySellSelection(const EQApplicationPacket *app) return; } - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2909,7 +2909,7 @@ void Client::Handle_OP_AugmentInfo(const EQApplicationPacket *app) } AugmentInfo_Struct* AugInfo = (AugmentInfo_Struct*)app->pBuffer; - const EQEmu::Item_Struct * item = database.GetItem(AugInfo->itemid); + const EQEmu::ItemBase * item = database.GetItem(AugInfo->itemid); if (item) { strn0cpy(AugInfo->augment_info, item->Name, 64); @@ -3491,7 +3491,7 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app) { BarterItemSearchLinkRequest_Struct* bislr = (BarterItemSearchLinkRequest_Struct*)app->pBuffer; - const EQEmu::Item_Struct* item = database.GetItem(bislr->ItemID); + const EQEmu::ItemBase* item = database.GetItem(bislr->ItemID); if (!item) Message(13, "Error: This item does not exist!"); @@ -3524,7 +3524,7 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app) { BuyerItemSearchLinkRequest_Struct* bislr = (BuyerItemSearchLinkRequest_Struct*)app->pBuffer; - const EQEmu::Item_Struct* item = database.GetItem(bislr->ItemID); + const EQEmu::ItemBase* item = database.GetItem(bislr->ItemID); if (!item) Message(13, "Error: This item does not exist!"); @@ -3563,7 +3563,7 @@ void Client::Handle_OP_BazaarInspect(const EQApplicationPacket *app) BazaarInspect_Struct* bis = (BazaarInspect_Struct*)app->pBuffer; - const EQEmu::Item_Struct* item = database.GetItem(bis->ItemID); + const EQEmu::ItemBase* item = database.GetItem(bis->ItemID); if (!item) { Message(13, "Error: This item does not exist!"); @@ -4015,7 +4015,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) //bool cancast = true; if (inst && inst->IsClassCommon()) { - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); if (item->Click.Effect != (uint32)castspell->spell_id) { database.SetMQDetectionFlag(account_name, name, "OP_CastSpell with item, tried to cast a different spell.", zone->GetShortName()); @@ -4864,7 +4864,7 @@ void Client::Handle_OP_Consume(const EQApplicationPacket *app) return; } - const EQEmu::Item_Struct* eat_item = myitem->GetItem(); + const EQEmu::ItemBase* eat_item = myitem->GetItem(); if (pcs->type == 0x01) { Consume(eat_item, EQEmu::item::ItemTypeFood, pcs->slot, (pcs->auto_consumed == 0xffffffff)); } @@ -6922,7 +6922,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) return; } - const EQEmu::Item_Struct* CursorItem = CursorItemInst->GetItem(); + const EQEmu::ItemBase* CursorItem = CursorItemInst->GetItem(); if (!CursorItem->NoDrop || CursorItemInst->IsAttuned()) { @@ -7995,7 +7995,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) EQApplicationPacket* outapp = app->Copy(); InspectResponse_Struct* insr = (InspectResponse_Struct*)outapp->pBuffer; Mob* tmp = entity_list.GetMob(insr->TargetID); - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); for (int16 L = EQEmu::legacy::EQUIPMENT_BEGIN; L <= EQEmu::legacy::SlotWaist; L++) { @@ -8005,7 +8005,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) if (item) { strcpy(insr->itemnames[L], item->Name); if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - const EQEmu::Item_Struct *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const EQEmu::ItemBase *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); insr->itemicons[L] = aug_item->Icon; } else if (inst->GetOrnamentationIcon()) { @@ -8105,7 +8105,7 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) // todo: verify ivrs->link_hash based on a rule, in case we don't care about people being able to sniff data // from the item DB - const EQEmu::Item_Struct *item = database.GetItem(ivrs->item_id); + const EQEmu::ItemBase *item = database.GetItem(ivrs->item_id); if (!item) { if (ivrs->item_id != SAYLINK_ITEM_ID) { Message(13, "Error: The item for the link you have clicked on does not exist!"); @@ -8196,7 +8196,7 @@ void Client::Handle_OP_ItemName(const EQApplicationPacket *app) return; } ItemNamePacket_Struct *p = (ItemNamePacket_Struct*)app->pBuffer; - const EQEmu::Item_Struct *item = 0; + const EQEmu::ItemBase *item = 0; if ((item = database.GetItem(p->item_id)) != nullptr) { auto outapp = new EQApplicationPacket(OP_ItemName, sizeof(ItemNamePacket_Struct)); p = (ItemNamePacket_Struct*)outapp->pBuffer; @@ -8212,7 +8212,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app) VERIFY_PACKET_LENGTH(OP_ItemPreview, app, ItemPreview_Struct); ItemPreview_Struct *ips = (ItemPreview_Struct *)app->pBuffer; - const EQEmu::Item_Struct* item = database.GetItem(ips->itemid); + const EQEmu::ItemBase* item = database.GetItem(ips->itemid); if (item) { auto outapp = new EQApplicationPacket(OP_ItemPreview, strlen(item->Name) + strlen(item->Lore) + @@ -8429,7 +8429,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) return; } - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); if (!item) { Message(0, "Error: item not found in inventory slot #%i", slot_id); DeleteItemInInventory(slot_id, 0, true); @@ -8477,13 +8477,13 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) int r; bool tryaug = false; ItemInst* clickaug = 0; - EQEmu::Item_Struct* augitem = 0; + EQEmu::ItemBase* augitem = 0; for (r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { const ItemInst* aug_i = inst->GetAugment(r); if (!aug_i) continue; - const EQEmu::Item_Struct* aug = aug_i->GetItem(); + const EQEmu::ItemBase* aug = aug_i->GetItem(); if (!aug) continue; @@ -8491,7 +8491,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) { tryaug = true; clickaug = (ItemInst*)aug_i; - augitem = (EQEmu::Item_Struct*)aug; + augitem = (EQEmu::ItemBase*)aug; spell_id = aug->Click.Effect; break; } @@ -10554,7 +10554,7 @@ void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) } if (mptbs->Action == 0) { - const EQEmu::Item_Struct *BaseItem = database.GetItem(mptbs->ItemID); + const EQEmu::ItemBase *BaseItem = database.GetItem(mptbs->ItemID); if (BaseItem) { m_pp.potionbelt.Items[mptbs->SlotNumber].ID = BaseItem->ID; m_pp.potionbelt.Items[mptbs->SlotNumber].Icon = BaseItem->Icon; @@ -12045,7 +12045,7 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app) return; if (inst) { - const EQEmu::Item_Struct* shield = inst->GetItem(); + const EQEmu::ItemBase* shield = inst->GetItem(); if (shield && shield->ItemType == EQEmu::item::ItemTypeShield) { for (int x = 0; x < 2; x++) @@ -12153,7 +12153,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) break; } } - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; uint32 prevcharges = 0; if (item_id == 0) { //check to see if its on the temporary table std::list tmp_merlist = zone->tmpmerchanttable[tmp->GetNPCTypeID()]; @@ -12401,7 +12401,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) uint32 itemid = GetItemIDAt(mp->itemslot); if (itemid == 0) return; - const EQEmu::Item_Struct* item = database.GetItem(itemid); + const EQEmu::ItemBase* item = database.GetItem(itemid); ItemInst* inst = GetInv().GetItem(mp->itemslot); if (!item || !inst){ Message(13, "You seemed to have misplaced that item.."); @@ -13507,7 +13507,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) TradeItemsValid = false; break; } - const EQEmu::Item_Struct *Item = database.GetItem(gis->Items[i]); + const EQEmu::ItemBase *Item = database.GetItem(gis->Items[i]); if (!Item) { Message(13, "Unexpected error. Unable to start trader mode"); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index b0e742901..f61b475bc 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -825,12 +825,12 @@ void Client::BulkSendInventoryItems() } void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { - const EQEmu::Item_Struct* handyitem = nullptr; + const EQEmu::ItemBase* handyitem = nullptr; uint32 numItemSlots = 80; //The max number of items passed in the transaction. if (m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater) { // RoF+ can send 200 items numItemSlots = 200; } - const EQEmu::Item_Struct *item; + const EQEmu::ItemBase *item; std::list merlist = zone->merchanttable[merchant_id]; std::list::const_iterator itr; Mob* merch = entity_list.GetMobByNpcTypeID(npcid); @@ -1088,7 +1088,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) if (inst && inst->IsClassCommon()) { - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); if (RuleB(Character, RestrictSpellScribing) && !item->IsEquipable(GetRace(), GetClass())) { Message_StringID(13, CANNOT_USE_ITEM); diff --git a/zone/command.cpp b/zone/command.cpp index 332713f43..d0143a0ad 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2546,7 +2546,7 @@ void command_peekinv(Client *c, const Seperator *sep) Client* targetClient = c->GetTarget()->CastToClient(); const ItemInst* inst_main = nullptr; const ItemInst* inst_sub = nullptr; - const EQEmu::Item_Struct* item_data = nullptr; + const EQEmu::ItemBase* item_data = nullptr; std::string item_link; EQEmu::saylink::SayLinkEngine linker; linker.SetLinkType(linker.SayLinkItemInst); @@ -5514,7 +5514,7 @@ void command_summonitem(Client *c, const Seperator *sep) } int16 item_status = 0; - const EQEmu::Item_Struct* item = database.GetItem(itemid); + const EQEmu::ItemBase* item = database.GetItem(itemid); if (item) { item_status = static_cast(item->MinStatus); } @@ -5553,7 +5553,7 @@ void command_giveitem(Client *c, const Seperator *sep) Client *t = c->GetTarget()->CastToClient(); uint32 itemid = atoi(sep->arg[1]); int16 item_status = 0; - const EQEmu::Item_Struct* item = database.GetItem(itemid); + const EQEmu::ItemBase* item = database.GetItem(itemid); if(item) { item_status = static_cast(item->MinStatus); } @@ -5606,7 +5606,7 @@ void command_itemsearch(Client *c, const Seperator *sep) { const char *search_criteria=sep->argplus[1]; - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; std::string item_link; EQEmu::saylink::SayLinkEngine linker; linker.SetLinkType(linker.SayLinkItemData); @@ -10230,7 +10230,7 @@ void command_zopp(Client *c, const Seperator *sep) uint32 itemid = atoi(sep->arg[3]); int16 charges = sep->argnum == 4 ? atoi(sep->arg[4]) : 1; // defaults to 1 charge if not specified - const EQEmu::Item_Struct* FakeItem = database.GetItem(itemid); + const EQEmu::ItemBase* FakeItem = database.GetItem(itemid); if (!FakeItem) { c->Message(13, "Error: Item [%u] is not a valid item id.", itemid); @@ -10238,7 +10238,7 @@ void command_zopp(Client *c, const Seperator *sep) } int16 item_status = 0; - const EQEmu::Item_Struct* item = database.GetItem(itemid); + const EQEmu::ItemBase* item = database.GetItem(itemid); if(item) { item_status = static_cast(item->MinStatus); } diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 2286e5e71..9245099e4 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -978,7 +978,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a safe_delete(outapp); if(Loot_Request_Type == 5) { int pkitem = GetPlayerKillItem(); - const EQEmu::Item_Struct* item = database.GetItem(pkitem); + const EQEmu::ItemBase* item = database.GetItem(pkitem); ItemInst* inst = database.CreateItem(item, item->MaxCharges); if(inst) { if (item->RecastDelay) @@ -993,7 +993,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a } int i = 0; - const EQEmu::Item_Struct* item = 0; + const EQEmu::ItemBase* item = 0; ItemList::iterator cur,end; cur = itemlist.begin(); end = itemlist.end(); @@ -1108,7 +1108,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { being_looted_by = 0xFFFFFFFF; return; } - const EQEmu::Item_Struct* item = 0; + const EQEmu::ItemBase* item = 0; ItemInst *inst = 0; ServerLootItem_Struct* item_data = nullptr, *bag_item_data[10]; @@ -1303,7 +1303,7 @@ void Corpse::QueryLoot(Client* to) { else x < corpselootlimit ? sitem->lootslot = x : sitem->lootslot = 0xFFFF; - const EQEmu::Item_Struct* item = database.GetItem(sitem->item_id); + const EQEmu::ItemBase* item = database.GetItem(sitem->item_id); if (item) to->Message((sitem->lootslot == 0xFFFF), "LootSlot: %i (EquipSlot: %i) Item: %s (%d), Count: %i", static_cast(sitem->lootslot), sitem->equip_slot, item->Name, item->ID, sitem->charges); @@ -1317,7 +1317,7 @@ void Corpse::QueryLoot(Client* to) { } else { sitem->lootslot=y; - const EQEmu::Item_Struct* item = database.GetItem(sitem->item_id); + const EQEmu::ItemBase* item = database.GetItem(sitem->item_id); if (item) to->Message(0, "LootSlot: %i Item: %s (%d), Count: %i", sitem->lootslot, item->Name, item->ID, sitem->charges); @@ -1412,7 +1412,7 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { } uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { - const EQEmu::Item_Struct *item; + const EQEmu::ItemBase *item; if (material_slot > EQEmu::legacy::MATERIAL_END) { return 0; diff --git a/zone/effects.cpp b/zone/effects.cpp index ad9de822c..7d0b9af02 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -481,7 +481,7 @@ int32 Client::GetActSpellCasttime(uint16 spell_id, int32 casttime) bool Client::TrainDiscipline(uint32 itemid) { //get the item info - const EQEmu::Item_Struct *item = database.GetItem(itemid); + const EQEmu::ItemBase *item = database.GetItem(itemid); if(item == nullptr) { Message(13, "Unable to find the tome you turned in!"); Log.Out(Logs::General, Logs::Error, "Unable to find turned in tome id %lu\n", (unsigned long)itemid); diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 37be828ae..43f4c3cdc 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -882,7 +882,7 @@ void PerlembParser::GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlaye } else if(isItemQuest) { // need a valid ItemInst pointer check here..unsure how to cancel this process - const EQEmu::Item_Struct* item = iteminst->GetItem(); + const EQEmu::ItemBase* item = iteminst->GetItem(); package_name = "qst_item_"; package_name += itoa(item->ID); } diff --git a/zone/embxs.cpp b/zone/embxs.cpp index a24f3f070..5c8769895 100644 --- a/zone/embxs.cpp +++ b/zone/embxs.cpp @@ -33,7 +33,7 @@ const char *getItemName(unsigned itemid) { - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; item = database.GetItem(itemid); if (item) diff --git a/zone/entity.cpp b/zone/entity.cpp index e5c5c193d..d398c9bf6 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1955,7 +1955,7 @@ void EntityList::QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struc memcpy(outgbius, gbius, sizeof(GuildBankItemUpdate_Struct)); - const EQEmu::Item_Struct *Item = database.GetItem(gbius->ItemID); + const EQEmu::ItemBase *Item = database.GetItem(gbius->ItemID); auto it = client_list.begin(); while (it != client_list.end()) { @@ -3821,7 +3821,7 @@ void EntityList::GroupMessage(uint32 gid, const char *from, const char *message) uint16 EntityList::CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time) { - const EQEmu::Item_Struct *is = database.GetItem(itemid); + const EQEmu::ItemBase *is = database.GetItem(itemid); if (!is) return 0; diff --git a/zone/forage.cpp b/zone/forage.cpp index e00d835b4..324467025 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -304,7 +304,7 @@ void Client::GoFish() food_id = common_fish_ids[index]; } - const EQEmu::Item_Struct* food_item = database.GetItem(food_id); + const EQEmu::ItemBase* food_item = database.GetItem(food_id); Message_StringID(MT_Skills, FISHING_SUCCESS); ItemInst* inst = database.CreateItem(food_item, 1); @@ -396,7 +396,7 @@ void Client::ForageItem(bool guarantee) { foragedfood = common_food_ids[index]; } - const EQEmu::Item_Struct* food_item = database.GetItem(foragedfood); + const EQEmu::ItemBase* food_item = database.GetItem(foragedfood); if(!food_item) { Log.Out(Logs::General, Logs::Error, "nullptr returned from database.GetItem in ClientForageItem"); diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index dfd022541..57f83a981 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -694,7 +694,7 @@ void GuildBankManager::SendGuildBank(Client *c) if (c->ClientVersionBit() & EQEmu::versions::bit_RoFAndLater) { auto outapp = new EQApplicationPacket(OP_GuildBankItemList, sizeof(GuildBankItemListEntry_Struct) * 240); for (int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i) { - const EQEmu::Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); + const EQEmu::ItemBase *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); if (Item) { outapp->WriteUInt8(1); outapp->WriteUInt32(guild_bank->Items.DepositArea[i].Permissions); @@ -718,7 +718,7 @@ void GuildBankManager::SendGuildBank(Client *c) outapp->SetWritePosition(outapp->GetWritePosition() + 20); // newer clients have 40 deposit slots, keep them 0 for now for (int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i) { - const EQEmu::Item_Struct *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); + const EQEmu::ItemBase *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); if (Item) { outapp->WriteUInt8(1); outapp->WriteUInt32(guild_bank->Items.MainArea[i].Permissions); @@ -749,7 +749,7 @@ void GuildBankManager::SendGuildBank(Client *c) { if(guild_bank->Items.DepositArea[i].ItemID > 0) { - const EQEmu::Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); + const EQEmu::ItemBase *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); if(!Item) continue; @@ -785,7 +785,7 @@ void GuildBankManager::SendGuildBank(Client *c) { if(guild_bank->Items.MainArea[i].ItemID > 0) { - const EQEmu::Item_Struct *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); + const EQEmu::ItemBase *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); if(!Item) continue; @@ -916,7 +916,7 @@ bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32 return false; } - const EQEmu::Item_Struct *Item = database.GetItem(ItemID); + const EQEmu::ItemBase *Item = database.GetItem(ItemID); GuildBankItemUpdate_Struct gbius; @@ -982,7 +982,7 @@ int GuildBankManager::Promote(uint32 guildID, int slotID) (*iter)->Items.DepositArea[slotID].ItemID = 0; - const EQEmu::Item_Struct *Item = database.GetItem((*iter)->Items.MainArea[mainSlot].ItemID); + const EQEmu::ItemBase *Item = database.GetItem((*iter)->Items.MainArea[mainSlot].ItemID); GuildBankItemUpdate_Struct gbius; @@ -1038,7 +1038,7 @@ void GuildBankManager::SetPermissions(uint32 guildID, uint16 slotID, uint32 perm else (*iter)->Items.MainArea[slotID].WhoFor[0] = '\0'; - const EQEmu::Item_Struct *Item = database.GetItem((*iter)->Items.MainArea[slotID].ItemID); + const EQEmu::ItemBase *Item = database.GetItem((*iter)->Items.MainArea[slotID].ItemID); GuildBankItemUpdate_Struct gbius; @@ -1169,7 +1169,7 @@ bool GuildBankManager::DeleteItem(uint32 guildID, uint16 area, uint16 slotID, ui bool deleted = true; - const EQEmu::Item_Struct *Item = database.GetItem(BankArea[slotID].ItemID); + const EQEmu::ItemBase *Item = database.GetItem(BankArea[slotID].ItemID); if(!Item->Stackable || (quantity >= BankArea[slotID].Quantity)) { std::string query = StringFormat("DELETE FROM `guild_bank` WHERE `guildid` = %i " @@ -1230,7 +1230,7 @@ bool GuildBankManager::MergeStacks(uint32 GuildID, uint16 SlotID) if(BankArea[SlotID].ItemID == 0) return false; - const EQEmu::Item_Struct *Item = database.GetItem(BankArea[SlotID].ItemID); + const EQEmu::ItemBase *Item = database.GetItem(BankArea[SlotID].ItemID); if(!Item->Stackable) return false; @@ -1328,7 +1328,7 @@ bool GuildBankManager::SplitStack(uint32 GuildID, uint16 SlotID, uint32 Quantity if(BankArea[SlotID].Quantity <= Quantity || Quantity == 0) return false; - const EQEmu::Item_Struct *Item = database.GetItem(BankArea[SlotID].ItemID); + const EQEmu::ItemBase *Item = database.GetItem(BankArea[SlotID].ItemID); if(!Item->Stackable) return false; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 8902f4e23..bd19b69ad 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -177,7 +177,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } -bool Client::CheckLoreConflict(const EQEmu::Item_Struct* item) +bool Client::CheckLoreConflict(const EQEmu::ItemBase* item) { if (!item) { return false; } if (!item->LoreFlag) { return false; } @@ -195,7 +195,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // TODO: update calling methods and script apis to handle a failure return - const EQEmu::Item_Struct* item = database.GetItem(item_id); + const EQEmu::ItemBase* item = database.GetItem(item_id); // make sure the item exists if(item == nullptr) { @@ -247,7 +247,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, bool enforceusable = RuleB(Inventory, EnforceAugmentUsability); for (int iter = AUG_INDEX_BEGIN; iter < EQEmu::legacy::ITEM_COMMON_SIZE; ++iter) { - const EQEmu::Item_Struct* augtest = database.GetItem(augments[iter]); + const EQEmu::ItemBase* augtest = database.GetItem(augments[iter]); if(augtest == nullptr) { if(augments[iter]) { @@ -1074,7 +1074,7 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type) #if 0 // TODO: needs clean-up to save references -bool MakeItemLink(char* &ret_link, const Item_Struct *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint8 evolving, uint8 evolvedlevel) { +bool MakeItemLink(char* &ret_link, const ItemBase *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint8 evolving, uint8 evolvedlevel) { //we're sending back the entire "link", minus the null characters & item name //that way, we can use it for regular links & Task links //note: initiator needs to pass us ret_link @@ -1189,7 +1189,7 @@ int Client::GetItemLinkHash(const ItemInst* inst) { if (!inst) //have to have an item to make the hash return 0; - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); char* hash_str = 0; /*register */int hash = 0; @@ -1283,7 +1283,7 @@ packet with the item number in it, but I cant seem to find it right now if (!inst) return; - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); const char* name2 = &item->Name[0]; auto outapp = new EQApplicationPacket(OP_ItemLinkText, strlen(name2) + 68); char buffer2[135] = {0}; @@ -1555,7 +1555,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { else { auto ndh_item = ndh_inst->GetItem(); if (ndh_item == nullptr) { - ndh_item_data.append("[nullptr on Item_Struct*]"); + ndh_item_data.append("[nullptr on ItemBase*]"); } else { ndh_item_data.append(StringFormat("name=%s", ndh_item->Name)); @@ -1597,8 +1597,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { m_inv.DeleteItem(src_slot_id); } else { - const EQEmu::Item_Struct* world_item = world_inst->GetItem(); - const EQEmu::Item_Struct* src_item = src_inst->GetItem(); + const EQEmu::ItemBase* world_item = world_inst->GetItem(); + const EQEmu::ItemBase* src_item = src_inst->GetItem(); if (world_item && src_item) { // Case 2: Same item on cursor, stacks, transfer of charges needed if ((world_item->ID == src_item->ID) && src_inst->IsStackable()) { @@ -1838,7 +1838,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { // This prevents the client from crashing when closing any 'phantom' bags - const EQEmu::Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' + const EQEmu::ItemBase* token_struct = database.GetItem(22292); // 'Copper Coin' ItemInst* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); @@ -1863,7 +1863,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { if(m_inv[resync_slot]) { - const EQEmu::Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' + const EQEmu::ItemBase* token_struct = database.GetItem(22292); // 'Copper Coin' ItemInst* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); @@ -1880,7 +1880,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { if ((move_slots->to_slot >= EQEmu::legacy::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::legacy::CURSOR_BAG_END) || move_slots->to_slot == EQEmu::legacy::SlotPowerSource) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { - const EQEmu::Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' + const EQEmu::ItemBase* token_struct = database.GetItem(22292); // 'Copper Coin' ItemInst* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); @@ -1905,7 +1905,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { if(m_inv[resync_slot]) { - const EQEmu::Item_Struct* token_struct = database.GetItem(22292); // 'Copper Coin' + const EQEmu::ItemBase* token_struct = database.GetItem(22292); // 'Copper Coin' ItemInst* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); @@ -2057,7 +2057,7 @@ void Client::DyeArmor(DyeStruct* dye){ #if 0 bool Client::DecreaseByItemType(uint32 type, uint8 amt) { - const Item_Struct* TempItem = 0; + const ItemBase* TempItem = 0; ItemInst* ins; int x; for(x=EQEmu::legacy::POSSESSIONS_BEGIN; x <= EQEmu::legacy::POSSESSIONS_END; x++) @@ -2109,7 +2109,7 @@ bool Client::DecreaseByItemType(uint32 type, uint8 amt) { #endif bool Client::DecreaseByID(uint32 type, uint8 amt) { - const EQEmu::Item_Struct* TempItem = nullptr; + const EQEmu::ItemBase* TempItem = nullptr; ItemInst* ins = nullptr; int x; int num = 0; @@ -2617,7 +2617,7 @@ uint32 Client::GetEquipment(uint8 material_slot) const #if 0 int32 Client::GetEquipmentMaterial(uint8 material_slot) { - const Item_Struct *item; + const ItemBase *item; item = database.GetItem(GetEquipment(material_slot)); if(item != 0) @@ -2634,7 +2634,7 @@ uint32 Client::GetEquipmentColor(uint8 material_slot) const if (material_slot > EQEmu::legacy::MATERIAL_END) return 0; - const EQEmu::Item_Struct *item = database.GetItem(GetEquipment(material_slot)); + const EQEmu::ItemBase *item = database.GetItem(GetEquipment(material_slot)); if(item != nullptr) return ((m_pp.item_tint[material_slot].RGB.UseTint) ? m_pp.item_tint[material_slot].Color : item->Color); @@ -2718,7 +2718,7 @@ void Client::CreateBandolier(const EQApplicationPacket *app) strcpy(m_pp.bandoliers[bs->Number].Name, bs->Name); const ItemInst* InvItem = nullptr; - const EQEmu::Item_Struct *BaseItem = nullptr; + const EQEmu::ItemBase *BaseItem = nullptr; int16 WeaponSlot = 0; for(int BandolierSlot = bandolierPrimary; BandolierSlot <= bandolierAmmo; BandolierSlot++) { diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 65b21ff77..4673d74dc 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -119,7 +119,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml int charges = lds->Entries[i].multiplier; for(int j = 0; j < charges; ++j) { if(zone->random.Real(0.0, 100.0) <= lds->Entries[i].chance) { - const EQEmu::Item_Struct* dbitem = GetItem(lds->Entries[i].item_id); + const EQEmu::ItemBase* dbitem = GetItem(lds->Entries[i].item_id); npc->AddLootDrop(dbitem, itemlist, lds->Entries[i].item_charges, lds->Entries[i].minlevel, lds->Entries[i].maxlevel, lds->Entries[i].equip_item > 0 ? true : false, false); } @@ -140,7 +140,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml float roll_t_min = 0.0f; bool active_item_list = false; for(uint32 i = 0; i < lds->NumEntries; ++i) { - const EQEmu::Item_Struct* db_item = GetItem(lds->Entries[i].item_id); + const EQEmu::ItemBase* db_item = GetItem(lds->Entries[i].item_id); if(db_item) { roll_t += lds->Entries[i].chance; active_item_list = true; @@ -157,7 +157,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml for(int i = 0; i < mindrop; ++i) { float roll = (float)zone->random.Real(0.0, roll_t_min); for(uint32 j = 0; j < lds->NumEntries; ++j) { - const EQEmu::Item_Struct* db_item = GetItem(lds->Entries[j].item_id); + const EQEmu::ItemBase* db_item = GetItem(lds->Entries[j].item_id); if(db_item) { if(roll < lds->Entries[j].chance) { npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, @@ -187,7 +187,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml for(int i = mindrop; i < droplimit; ++i) { float roll = (float)zone->random.Real(0.0, roll_t); for(uint32 j = 0; j < lds->NumEntries; ++j) { - const EQEmu::Item_Struct* db_item = GetItem(lds->Entries[j].item_id); + const EQEmu::ItemBase* db_item = GetItem(lds->Entries[j].item_id); if(db_item) { if(roll < lds->Entries[j].chance) { npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, @@ -221,7 +221,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml } //if itemlist is null, just send wear changes -void NPC::AddLootDrop(const EQEmu::Item_Struct *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange) { +void NPC::AddLootDrop(const EQEmu::ItemBase *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange) { if(item2 == nullptr) return; @@ -258,7 +258,7 @@ void NPC::AddLootDrop(const EQEmu::Item_Struct *item2, ItemList* itemlist, int16 if (equipit) { uint8 eslot = 0xFF; char newid[20]; - const EQEmu::Item_Struct* compitem = nullptr; + const EQEmu::ItemBase* compitem = nullptr; bool found = false; // track if we found an empty slot we fit into int32 foundslot = -1; // for multi-slot items @@ -415,14 +415,14 @@ void NPC::AddLootDrop(const EQEmu::Item_Struct *item2, ItemList* itemlist, int16 SendAppearancePacket(AT_Light, GetActiveLightType()); } -void NPC::AddItem(const EQEmu::Item_Struct* item, uint16 charges, bool equipitem) { +void NPC::AddItem(const EQEmu::ItemBase* item, uint16 charges, bool equipitem) { //slot isnt needed, its determined from the item. AddLootDrop(item, &itemlist, charges, 1, 127, equipitem, equipitem); } void NPC::AddItem(uint32 itemid, uint16 charges, bool equipitem) { //slot isnt needed, its determined from the item. - const EQEmu::Item_Struct * i = database.GetItem(itemid); + const EQEmu::ItemBase * i = database.GetItem(itemid); if(i == nullptr) return; AddLootDrop(i, &itemlist, charges, 1, 127, equipitem, equipitem); diff --git a/zone/lua_item.cpp b/zone/lua_item.cpp index 429e140dc..d6846abc0 100644 --- a/zone/lua_item.cpp +++ b/zone/lua_item.cpp @@ -7,7 +7,7 @@ #include "lua_item.h" Lua_Item::Lua_Item(uint32 item_id) { - const EQEmu::Item_Struct *t = database.GetItem(item_id); + const EQEmu::ItemBase *t = database.GetItem(item_id); SetLuaPtrData(t); } diff --git a/zone/lua_item.h b/zone/lua_item.h index 5e3e021c9..74294f2a5 100644 --- a/zone/lua_item.h +++ b/zone/lua_item.h @@ -6,7 +6,7 @@ namespace EQEmu { - struct Item_Struct; + struct ItemBase; } namespace luabind { @@ -15,17 +15,17 @@ namespace luabind { luabind::scope lua_register_item(); -class Lua_Item : public Lua_Ptr +class Lua_Item : public Lua_Ptr { - typedef const EQEmu::Item_Struct NativeType; + typedef const EQEmu::ItemBase NativeType; public: Lua_Item(uint32 item_id); Lua_Item() : Lua_Ptr(nullptr) { } - Lua_Item(const EQEmu::Item_Struct *d) : Lua_Ptr(d) { } + Lua_Item(const EQEmu::ItemBase *d) : Lua_Ptr(d) { } virtual ~Lua_Item() { } - operator const EQEmu::Item_Struct*() { - return reinterpret_cast(GetLuaPtrData()); + operator const EQEmu::ItemBase*() { + return reinterpret_cast(GetLuaPtrData()); } int GetMinStatus(); diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index 88a117277..030e43689 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -298,7 +298,7 @@ void handle_player_timer(QuestInterface *parse, lua_State* L, Client* client, st void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { - const EQEmu::Item_Struct *item = database.GetItem(extra_data); + const EQEmu::ItemBase *item = database.GetItem(extra_data); if(item) { Lua_Item l_item(item); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); diff --git a/zone/merc.cpp b/zone/merc.cpp index d4ecabdd8..a516c34b3 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -217,7 +217,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { for (i = 0; i < EQEmu::legacy::SlotAmmo; i++) { if(equipment[i] == 0) continue; - const EQEmu::Item_Struct * itm = database.GetItem(equipment[i]); + const EQEmu::ItemBase * itm = database.GetItem(equipment[i]); if(itm) AddItemBonuses(itm, newbon); } @@ -243,7 +243,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { SetAttackTimer(); } -void Merc::AddItemBonuses(const EQEmu::Item_Struct *item, StatBonuses* newbon) { +void Merc::AddItemBonuses(const EQEmu::ItemBase *item, StatBonuses* newbon) { if(GetLevel() < item->ReqLevel) { @@ -1221,7 +1221,7 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { { continue; } - const Item_Struct* item = database.GetItem(equipment[i]); + const ItemBase* item = database.GetItem(equipment[i]); if(item) { ns->spawn.equipment[i].material = item->Material; @@ -2547,8 +2547,8 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) { //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[type]){ - const EQEmu::Item_Struct* TempItem = 0; - const EQEmu::Item_Struct* UsedItem = 0; + const EQEmu::ItemBase* TempItem = 0; + const EQEmu::ItemBase* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -4428,7 +4428,7 @@ void Merc::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ dmg = -5; } else{ @@ -4450,7 +4450,7 @@ void Merc::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ dmg = -5; } else{ diff --git a/zone/merc.h b/zone/merc.h index 275417adb..00c953288 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -14,7 +14,7 @@ struct NewSpawn_Struct; namespace EQEmu { - struct Item_Struct; + struct ItemBase; } #define MAXMERCS 1 @@ -283,7 +283,7 @@ public: protected: void CalcItemBonuses(StatBonuses* newbon); - void AddItemBonuses(const EQEmu::Item_Struct *item, StatBonuses* newbon); + void AddItemBonuses(const EQEmu::ItemBase *item, StatBonuses* newbon); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); int16 GetFocusEffect(focusType type, uint16 spell_id); diff --git a/zone/mob.cpp b/zone/mob.cpp index 7f2224deb..78e56e8bc 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2382,7 +2382,7 @@ bool Mob::CanThisClassDualWield(void) const { // 2HS, 2HB, or 2HP if(pinst && pinst->IsWeapon()) { - const EQEmu::Item_Struct* item = pinst->GetItem(); + const EQEmu::ItemBase* item = pinst->GetItem(); if (item->IsType2HWeapon()) return false; @@ -2754,7 +2754,7 @@ void Mob::SendArmorAppearance(Client *one_client) { if (!IsClient()) { - const EQEmu::Item_Struct *item; + const EQEmu::ItemBase *item; for (int i = 0; i < 7; ++i) { item = database.GetItem(GetEquipment(i)); @@ -2857,7 +2857,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const { uint32 equipmaterial = 0; int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - const EQEmu::Item_Struct *item; + const EQEmu::ItemBase *item; item = database.GetItem(GetEquipment(material_slot)); if (item != 0) @@ -2910,7 +2910,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const if (material_slot >= 0 && material_slot < EQEmu::legacy::MaterialPrimary) { uint32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - const EQEmu::Item_Struct *item; + const EQEmu::ItemBase *item; item = database.GetItem(GetEquipment(material_slot)); int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); @@ -2964,7 +2964,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const uint32 Mob::GetEquipmentColor(uint8 material_slot) const { - const EQEmu::Item_Struct *item; + const EQEmu::ItemBase *item; if (armor_tint[material_slot]) { @@ -2980,7 +2980,7 @@ uint32 Mob::GetEquipmentColor(uint8 material_slot) const uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const { - const EQEmu::Item_Struct *item; + const EQEmu::ItemBase *item; item = database.GetItem(GetEquipment(material_slot)); if(item != 0) @@ -3896,7 +3896,7 @@ int32 Mob::GetItemStat(uint32 itemid, const char *identifier) if (!inst) return 0; - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); if (!item) return 0; @@ -5627,7 +5627,7 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot) bool Mob::CanClassEquipItem(uint32 item_id) { - const EQEmu::Item_Struct* itm = nullptr; + const EQEmu::ItemBase* itm = nullptr; itm = database.GetItem(item_id); if (!itm) diff --git a/zone/mob.h b/zone/mob.h index ed6dc1154..124eb471b 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -50,7 +50,7 @@ struct PlayerPositionUpdateServer_Struct; namespace EQEmu { - struct Item_Struct; + struct ItemBase; } class Mob : public Entity { @@ -768,7 +768,7 @@ public: virtual int GetHaste(); int32 GetMeleeMitigation(); - uint8 GetWeaponDamageBonus(const EQEmu::Item_Struct* weapon, bool offhand = false); + uint8 GetWeaponDamageBonus(const EQEmu::ItemBase* weapon, bool offhand = false); uint16 GetDamageTable(EQEmu::skills::SkillType skillinuse); virtual int GetHandToHandDamage(void); @@ -793,10 +793,10 @@ public: int32 ReduceAllDamage(int32 damage); virtual void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool CheckHitChance = false, bool CanAvoid = true); - virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const EQEmu::Item_Struct* AmmoItem=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0, uint32 range_id=0, int AmmoSlot=0, float speed = 4.0f); + virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon = nullptr, const EQEmu::ItemBase* AmmoItem = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, int AmmoSlot = 0, float speed = 4.0f); virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0); - virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0, uint32 range_id=0, uint32 ammo_id=0, const EQEmu::Item_Struct *AmmoItem=nullptr, int AmmoSlot=0, float speed= 4.0f); - bool TryProjectileAttack(Mob* other, const EQEmu::Item_Struct *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed); + virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon = nullptr, const ItemInst* Ammo = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, uint32 ammo_id = 0, const EQEmu::ItemBase *AmmoItem = nullptr, int AmmoSlot = 0, float speed = 4.0f); + bool TryProjectileAttack(Mob* other, const EQEmu::ItemBase *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed); void ProjectileAttack(); inline bool HasProjectileAttack() const { return ActiveProjectileATK; } inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; } @@ -914,7 +914,7 @@ public: // HP Event inline int GetNextHPEvent() const { return nexthpevent; } void SetNextHPEvent( int hpevent ); - void SendItemAnimation(Mob *to, const EQEmu::Item_Struct *item, EQEmu::skills::SkillType skillInUse, float velocity = 4.0); + void SendItemAnimation(Mob *to, const EQEmu::ItemBase *item, EQEmu::skills::SkillType skillInUse, float velocity = 4.0); inline int& GetNextIncHPEvent() { return nextinchpevent; } void SetNextIncHPEvent( int inchpevent ); @@ -1152,8 +1152,8 @@ protected: bool PassLimitToSkill(uint16 spell_id, uint16 skill); bool PassLimitClass(uint32 Classes_, uint16 Class_); void TryDefensiveProc(Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); - void TryWeaponProc(const ItemInst* inst, const EQEmu::Item_Struct* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); - void TrySpellProc(const ItemInst* inst, const EQEmu::Item_Struct* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); + void TryWeaponProc(const ItemInst* inst, const EQEmu::ItemBase* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); + void TrySpellProc(const ItemInst* inst, const EQEmu::ItemBase* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on, int level_override = -1); virtual float GetProcChances(float ProcBonus, uint16 hand = EQEmu::legacy::SlotPrimary); @@ -1162,7 +1162,7 @@ protected: virtual float GetAssassinateProcChances(uint16 ReuseTime); virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm? uint16 GetWeaponSpeedbyHand(uint16 hand); - int GetWeaponDamage(Mob *against, const EQEmu::Item_Struct *weapon_item); + int GetWeaponDamage(Mob *against, const EQEmu::ItemBase *weapon_item); int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr); int GetKickDamage(); int GetBashDamage(); diff --git a/zone/mod_functions.cpp b/zone/mod_functions.cpp index a38003504..601041361 100644 --- a/zone/mod_functions.cpp +++ b/zone/mod_functions.cpp @@ -10,10 +10,6 @@ class Spawn2; struct Consider_Struct; struct DBTradeskillRecipe_Struct; -namespace { - struct Item_Struct; -} - extern EntityList entity_list; extern Zone* zone; @@ -29,7 +25,7 @@ void Zone::mod_repop() { return; } void NPC::mod_prespawn(Spawn2 *sp) { return; } //Base damage from NPC::Attack -int NPC::mod_npc_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::Item_Struct* weapon, Mob* other) { return(damage); } +int NPC::mod_npc_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::ItemBase* weapon, Mob* other) { return(damage); } //Mob c has been given credit for a kill. This is called after the regular EVENT_KILLED_MERIT event. void NPC::mod_npc_killed_merit(Mob* c) { return; } @@ -107,8 +103,8 @@ int32 Client::mod_client_xp(int32 in_xp, NPC *npc) { return(in_xp); } uint32 Client::mod_client_xp_for_level(uint32 xp, uint16 check_level) { return(xp); } //Food and drink values as computed by consume requests. Return < 0 to abort the request. -int Client::mod_food_value(const EQEmu::Item_Struct *item, int change) { return(change); } -int Client::mod_drink_value(const EQEmu::Item_Struct *item, int change) { return(change); } +int Client::mod_food_value(const EQEmu::ItemBase *item, int change) { return(change); } +int Client::mod_drink_value(const EQEmu::ItemBase *item, int change) { return(change); } //effect_vallue - Spell effect value as calculated by default formulas. You will want to ignore effects that don't lend themselves to scaling - pet ID's, gate coords, etc. int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster, uint16 caster_id) { return(effect_value); } diff --git a/zone/npc.cpp b/zone/npc.cpp index b875a2d1b..1df16ca12 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -27,7 +27,7 @@ #include "../common/client_version.h" // inv2 watch #include "../common/features.h" #include "../common/item.h" -#include "../common/item_struct.h" +#include "../common/item_base.h" #include "../common/linked_list.h" #include "../common/servertalk.h" #include "../common/say_link.h" @@ -524,7 +524,7 @@ void NPC::QueryLoot(Client* to) int x = 0; for (auto cur = itemlist.begin(); cur != itemlist.end(); ++cur, ++x) { - const EQEmu::Item_Struct* item = database.GetItem((*cur)->item_id); + const EQEmu::ItemBase* item = database.GetItem((*cur)->item_id); if (item == nullptr) { Log.Out(Logs::General, Logs::Error, "Database error, invalid item"); continue; @@ -1457,7 +1457,7 @@ void NPC::PickPocket(Client* thief) // still needs to have FindFreeSlot vs PutItemInInventory issue worked out while (steal_item) { - std::vector> loot_selection; // + std::vector> loot_selection; // for (auto item_iter : itemlist) { if (!item_iter || !item_iter->item_id) continue; diff --git a/zone/npc.h b/zone/npc.h index 5131eb569..0023d4273 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -93,7 +93,7 @@ class Spawn2; namespace EQEmu { - struct Item_Struct; + struct ItemBase; } class NPC : public Mob @@ -178,7 +178,7 @@ public: virtual void SpellProcess(); virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); - void AddItem(const EQEmu::Item_Struct* item, uint16 charges, bool equipitem = true); + void AddItem(const EQEmu::ItemBase* item, uint16 charges, bool equipitem = true); void AddItem(uint32 itemid, uint16 charges, bool equipitem = true); void AddLootTable(); void AddLootTable(uint32 ldid); @@ -270,7 +270,7 @@ public: bool IsTaunting() const { return taunting; } void PickPocket(Client* thief); void StartSwarmTimer(uint32 duration) { swarm_timer.Start(duration); } - void AddLootDrop(const EQEmu::Item_Struct*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); + void AddLootDrop(const EQEmu::ItemBase*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); virtual void DoClassAttacks(Mob *target); void CheckSignal(); inline bool IsNotTargetableWithHotkey() const { return no_target_hotkey; } @@ -403,7 +403,7 @@ public: void SetMerchantProbability(uint8 amt) { probability = amt; } uint8 GetMerchantProbability() { return probability; } void mod_prespawn(Spawn2 *sp); - int mod_npc_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::Item_Struct* weapon, Mob* other); + int mod_npc_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::ItemBase* weapon, Mob* other); void mod_npc_killed_merit(Mob* c); void mod_npc_killed(Mob* oos); void AISpellsList(Client *c); diff --git a/zone/object.cpp b/zone/object.cpp index f6338ab50..f74d2dd0d 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -138,7 +138,7 @@ Object::Object(Client* client, const ItemInst* inst) // Set object name if (inst) { - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); if (item && item->IDFile) { if (strlen(item->IDFile) == 0) { strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); @@ -194,7 +194,7 @@ Object::Object(const ItemInst *inst, float x, float y, float z, float heading, u // Set object name if (inst) { - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); if (item && item->IDFile) { if (strlen(item->IDFile) == 0) { strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); @@ -881,7 +881,7 @@ uint32 Object::GetItemID() return 0; } - const EQEmu::Item_Struct* item = this->m_inst->GetItem(); + const EQEmu::ItemBase* item = this->m_inst->GetItem(); if (item == 0) { diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 89c94e7e3..4a6fab4e4 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -8131,7 +8131,7 @@ XS(XS_Mob_DoThrowingAttackDmg) Mob * THIS; Mob* target; ItemInst* RangeWeapon = nullptr; - EQEmu::Item_Struct* item = nullptr; + EQEmu::ItemBase* item = nullptr; uint16 weapon_damage = (uint16)SvIV(ST(4)); int16 chance_mod = (int16)SvIV(ST(5)); int16 focus = (int16)SvIV(ST(6)); diff --git a/zone/pets.cpp b/zone/pets.cpp index 6085cab53..020abf2f4 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -420,7 +420,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, // like the special back items some focused pets may receive. uint32 petinv[EQEmu::legacy::EQUIPMENT_SIZE]; memset(petinv, 0, sizeof(petinv)); - const EQEmu::Item_Struct *item = 0; + const EQEmu::ItemBase *item = 0; if (database.GetBasePetItems(record.equipmentset, petinv)) { for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++) @@ -665,7 +665,7 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { if(items[i] == 0) continue; - const EQEmu::Item_Struct* item2 = database.GetItem(items[i]); + const EQEmu::ItemBase* item2 = database.GetItem(items[i]); if (item2 && item2->NoDrop != 0) { //dont bother saving item charges for now, NPCs never use them //and nobody should be able to get them off the corpse..? diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index f28755efb..15f651763 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -814,7 +814,7 @@ void QuestManager::traindisc(int discipline_tome_item_id) { } bool QuestManager::isdisctome(int item_id) { - const EQEmu::Item_Struct *item = database.GetItem(item_id); + const EQEmu::ItemBase *item = database.GetItem(item_id); if(item == nullptr) { return(false); } @@ -1305,7 +1305,7 @@ void QuestManager::settime(uint8 new_hour, uint8 new_min, bool update_world /*= void QuestManager::itemlink(int item_id) { QuestManagerCurrentQuestVars(); if (initiator) { - const EQEmu::Item_Struct* item = database.GetItem(item_id); + const EQEmu::ItemBase* item = database.GetItem(item_id); if (item == nullptr) return; @@ -2497,7 +2497,7 @@ void QuestManager::MerchantSetItem(uint32 NPCid, uint32 itemid, uint32 quantity) if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != MERCHANT)) return; // don't do anything if NPCid isn't a merchant - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; item = database.GetItem(itemid); if (!item) return; // if the item id doesn't correspond to a real item, do nothing @@ -2510,7 +2510,7 @@ uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) { if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != MERCHANT)) return 0; // if it isn't a merchant, it doesn't have any items - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; item = database.GetItem(itemid); if (!item) return 0; // if it isn't a valid item, the merchant doesn't have any @@ -2533,7 +2533,7 @@ uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) { // Item Link for use in Variables - "my $example_link = quest::varlink(item_id);" const char* QuestManager::varlink(char* perltext, int item_id) { QuestManagerCurrentQuestVars(); - const EQEmu::Item_Struct* item = database.GetItem(item_id); + const EQEmu::ItemBase* item = database.GetItem(item_id); if (!item) return "INVALID ITEM ID IN VARLINK"; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index dd6f72b8b..8b4cf0af8 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -118,7 +118,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 { hate += item->GetItem()->AC; } - const EQEmu::Item_Struct *itm = item->GetItem(); + const EQEmu::ItemBase *itm = item->GetItem(); auto fbash = GetFuriousBash(itm->Focus.Effect); hate = hate * (100 + fbash) / 100; if (fbash) @@ -463,7 +463,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) } } else{ - if(GetWeaponDamage(other, (const EQEmu::Item_Struct*)nullptr) <= 0){ + if (GetWeaponDamage(other, (const EQEmu::ItemBase*)nullptr) <= 0){ ndamage = -5; } } @@ -694,8 +694,8 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { return; } - const EQEmu::Item_Struct* RangeItem = RangeWeapon->GetItem(); - const EQEmu::Item_Struct* AmmoItem = Ammo->GetItem(); + const EQEmu::ItemBase* RangeItem = RangeWeapon->GetItem(); + const EQEmu::ItemBase* AmmoItem = Ammo->GetItem(); if (RangeItem->ItemType != EQEmu::item::ItemTypeBow) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item is not a bow. type %d.", RangeItem->ItemType); @@ -719,7 +719,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { const ItemInst *pi = m_inv[r]; if (pi == nullptr || !pi->IsClassBag()) continue; - const EQEmu::Item_Struct* bagitem = pi->GetItem(); + const EQEmu::ItemBase* bagitem = pi->GetItem(); if (!bagitem || bagitem->BagType != EQEmu::item::BagTypeQuiver) continue; @@ -798,7 +798,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { } void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, - uint32 range_id, uint32 ammo_id, const EQEmu::Item_Struct *AmmoItem, int AmmoSlot, float speed) { + uint32 range_id, uint32 ammo_id, const EQEmu::ItemBase *AmmoItem, int AmmoSlot, float speed) { if ((other == nullptr || ((IsClient() && CastToClient()->dead) || @@ -813,7 +813,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite const ItemInst* _RangeWeapon = nullptr; const ItemInst* _Ammo = nullptr; - const EQEmu::Item_Struct* ammo_lost = nullptr; + const EQEmu::ItemBase* ammo_lost = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -1009,7 +1009,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } } -bool Mob::TryProjectileAttack(Mob* other, const EQEmu::Item_Struct *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed){ +bool Mob::TryProjectileAttack(Mob* other, const EQEmu::ItemBase *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed){ if (!other) return false; @@ -1313,7 +1313,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha //try proc on hits and misses if(other && !other->HasDied()) - TrySpellProc(nullptr, (const EQEmu::Item_Struct*)nullptr, other, EQEmu::legacy::SlotRange); + TrySpellProc(nullptr, (const EQEmu::ItemBase*)nullptr, other, EQEmu::legacy::SlotRange); if (HasSkillProcs() && other && !other->HasDied()) TrySkillProc(other, skillInUse, 0, false, EQEmu::legacy::SlotRange); @@ -1367,7 +1367,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 return; } - const EQEmu::Item_Struct* item = RangeWeapon->GetItem(); + const EQEmu::ItemBase* item = RangeWeapon->GetItem(); if (item->ItemType != EQEmu::item::ItemTypeLargeThrowing && item->ItemType != EQEmu::item::ItemTypeSmallThrowing) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item %d is not a throwing weapon. type %d.", item->ItemType); Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(EQEmu::legacy::SlotRange)); @@ -1428,7 +1428,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 CommonBreakInvisibleFromCombat(); } -void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQEmu::Item_Struct* AmmoItem, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed) +void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQEmu::ItemBase* AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed) { if ((other == nullptr || ((IsClient() && CastToClient()->dead) || @@ -1442,7 +1442,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQE } const ItemInst* _RangeWeapon = nullptr; - const EQEmu::Item_Struct* ammo_lost = nullptr; + const EQEmu::ItemBase* ammo_lost = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -1566,7 +1566,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQE } } -void Mob::SendItemAnimation(Mob *to, const EQEmu::Item_Struct *item, EQEmu::skills::SkillType skillInUse, float velocity) { +void Mob::SendItemAnimation(Mob *to, const EQEmu::ItemBase *item, EQEmu::skills::SkillType skillInUse, float velocity) { auto outapp = new EQApplicationPacket(OP_SomeItemPacketMaybe, sizeof(Arrow_Struct)); Arrow_Struct *as = (Arrow_Struct *) outapp->pBuffer; as->type = 1; @@ -1616,7 +1616,7 @@ void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, f if (!to) return; - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; uint8 item_type = 0; if(!item_id) { @@ -1757,7 +1757,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ dmg = -5; } else{ @@ -1778,7 +1778,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ dmg = -5; } else{ @@ -1831,7 +1831,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ dmg = -5; } else{ @@ -1856,7 +1856,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if(GetWeaponDamage(target, (const EQEmu::Item_Struct*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ dmg = -5; } else{ @@ -2368,7 +2368,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: int32 max_hit = (2 * weapon_damage*GetDamageTable(skillinuse)) / 100; if(GetLevel() >= 28 && IsWarriorClass() ) { - int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::Item_Struct*) nullptr ); + int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::ItemBase*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -2381,7 +2381,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: if (item->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { hate += item->GetItem()->AC; } - const EQEmu::Item_Struct *itm = item->GetItem(); + const EQEmu::ItemBase *itm = item->GetItem(); hate = hate * (100 + GetFuriousBash(itm->Focus.Effect)) / 100; } } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 4a8b43365..e5391b514 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1138,7 +1138,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_SummonItem: { - const EQEmu::Item_Struct *item = database.GetItem(spell.base[i]); + const EQEmu::ItemBase *item = database.GetItem(spell.base[i]); #ifdef SPELL_EFFECT_SPAM const char *itemname = item ? item->Name : "*Unknown Item*"; snprintf(effect_desc, _EDLEN, "Summon Item: %s (id %d)", itemname, spell.base[i]); @@ -1174,7 +1174,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } case SE_SummonItemIntoBag: { - const EQEmu::Item_Struct *item = database.GetItem(spell.base[i]); + const EQEmu::ItemBase *item = database.GetItem(spell.base[i]); #ifdef SPELL_EFFECT_SPAM const char *itemname = item ? item->Name : "*Unknown Item*"; snprintf(effect_desc, _EDLEN, "Summon Item In Bag: %s (id %d)", itemname, spell.base[i]); @@ -5128,7 +5128,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { //item focus if (itembonuses.FocusEffects[type]){ - const EQEmu::Item_Struct* TempItem = 0; + const EQEmu::ItemBase* TempItem = 0; for (int x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::EQUIPMENT_END; x++) { @@ -5159,7 +5159,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { aug = ins->GetAugment(y); if(aug) { - const EQEmu::Item_Struct* TempItemAug = aug->GetItem(); + const EQEmu::ItemBase* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && IsValidSpell(TempItemAug->Focus.Effect)) { proc_spellid = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id); if (IsValidSpell(proc_spellid)){ @@ -5257,8 +5257,8 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[type]){ - const EQEmu::Item_Struct* TempItem = 0; - const EQEmu::Item_Struct* UsedItem = 0; + const EQEmu::ItemBase* TempItem = 0; + const EQEmu::ItemBase* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -5305,7 +5305,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) aug = ins->GetAugment(y); if(aug) { - const EQEmu::Item_Struct* TempItemAug = aug->GetItem(); + const EQEmu::ItemBase* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { focus_max = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id, true); @@ -5529,8 +5529,8 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { if (RuleB(Spells, NPC_UseFocusFromItems) && itembonuses.FocusEffects[type]){ - const EQEmu::Item_Struct* TempItem = 0; - const EQEmu::Item_Struct* UsedItem = 0; + const EQEmu::ItemBase* TempItem = 0; + const EQEmu::ItemBase* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -5538,7 +5538,7 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { //item focus for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++){ - const EQEmu::Item_Struct *cur = database.GetItem(equipment[i]); + const EQEmu::ItemBase *cur = database.GetItem(equipment[i]); if(!cur) continue; diff --git a/zone/spells.cpp b/zone/spells.cpp index d648ba027..a8fe41087 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1136,7 +1136,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, missingreags=true; } - const EQEmu::Item_Struct *item = database.GetItem(component); + const EQEmu::ItemBase *item = database.GetItem(component); if(item) { c->Message_StringID(13, MISSING_SPELL_COMP_ITEM, item->Name); Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Canceled. Missing required reagent %s (%d)", spell_id, item->Name, component); @@ -1198,7 +1198,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, { bool fromaug = false; const ItemInst* inst = CastToClient()->GetInv()[inventory_slot]; - EQEmu::Item_Struct* augitem = 0; + EQEmu::ItemBase* augitem = 0; uint32 recastdelay = 0; uint32 recasttype = 0; @@ -1211,7 +1211,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, if (!aug_i) continue; - const EQEmu::Item_Struct* aug = aug_i->GetItem(); + const EQEmu::ItemBase* aug = aug_i->GetItem(); if (!aug) continue; @@ -1247,7 +1247,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, if (inst && inst->IsClassCommon() && (inst->GetItem()->Click.Effect == spell_id) && inst->GetCharges() || fromaug) { - //const Item_Struct* item = inst->GetItem(); + //const ItemBase* item = inst->GetItem(); int16 charges = inst->GetItem()->MaxCharges; if(fromaug) { charges = -1; } //Don't destroy the parent item diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 0fc22dffa..9b453847f 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1885,7 +1885,7 @@ void ClientTaskState::RewardTask(Client *c, TaskInformation *Task) { if(!Task || !c) return; - const EQEmu::Item_Struct* Item; + const EQEmu::ItemBase* Item; std::vector RewardList; switch(Task->RewardMethod) { @@ -2776,7 +2776,7 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN } if(ItemID) { - const EQEmu::Item_Struct* reward_item = database.GetItem(ItemID); + const EQEmu::ItemBase* reward_item = database.GetItem(ItemID); EQEmu::saylink::SayLinkEngine linker; linker.SetLinkType(linker.SayLinkItemData); diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 6c0dc667a..cdbd7b993 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -61,7 +61,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme inst = user_inv.GetItem(in_augment->container_slot); if (inst) { - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); if (item && inst->IsType(EQEmu::item::ItemClassBag) && item->BagType == 53) { // We have found an appropriate inventory augmentation sealer @@ -276,7 +276,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob else { inst = user_inv.GetItem(in_combine->container_slot); if (inst) { - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); if (item && inst->IsType(EQEmu::item::ItemClassBag)) { c_type = item->BagType; some_id = item->ID; @@ -294,7 +294,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob const ItemInst* inst = container->GetItem(0); bool AllowAll = RuleB(Inventory, AllowAnyWeaponTransformation); if (inst && ItemInst::CanTransform(inst->GetItem(), container->GetItem(), AllowAll)) { - const EQEmu::Item_Struct* new_weapon = inst->GetItem(); + const EQEmu::ItemBase* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::legacy::SlotCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2)); @@ -314,7 +314,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob if (container->GetItem() && container->GetItem()->BagType == EQEmu::item::BagTypeDetransformationmold) { const ItemInst* inst = container->GetItem(0); if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIcon()) { - const EQEmu::Item_Struct* new_weapon = inst->GetItem(); + const EQEmu::ItemBase* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::legacy::SlotCursor, 0, 0); @@ -537,7 +537,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac user->Message_StringID(MT_Skills, TRADESKILL_MISSING_COMPONENTS); for (auto it = MissingItems.begin(); it != MissingItems.end(); ++it) { - const EQEmu::Item_Struct* item = database.GetItem(*it); + const EQEmu::ItemBase* item = database.GetItem(*it); if(item) user->Message_StringID(MT_Skills, TRADESKILL_MISSING_ITEM, item->Name); @@ -962,7 +962,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { aa_chance = spellbonuses.ReduceTradeskillFail[spec->tradeskill] + itembonuses.ReduceTradeskillFail[spec->tradeskill] + aabonuses.ReduceTradeskillFail[spec->tradeskill]; - const EQEmu::Item_Struct* item = nullptr; + const EQEmu::ItemBase* item = nullptr; chance = mod_tradeskill_chance(chance, spec); @@ -1113,7 +1113,7 @@ bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint3 if (!inst) continue; - const EQEmu::Item_Struct* item = GetItem(inst->GetItem()->ID); + const EQEmu::ItemBase* item = GetItem(inst->GetItem()->ID); if (!item) continue; @@ -1242,7 +1242,7 @@ bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint3 if(!inst) continue; - const EQEmu::Item_Struct* item = GetItem(inst->GetItem()->ID); + const EQEmu::ItemBase* item = GetItem(inst->GetItem()->ID); if (!item) continue; diff --git a/zone/trading.cpp b/zone/trading.cpp index 9d23bd721..aab8ac8ac 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -885,7 +885,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st continue; } - const EQEmu::Item_Struct* item = inst->GetItem(); + const EQEmu::ItemBase* item = inst->GetItem(); if(item && quest_npc == false) { // if it was not a NO DROP or Attuned item (or if a GM is trading), let the NPC have it if(GetGM() || (item->NoDrop != 0 && inst->IsAttuned() == false)) { @@ -894,7 +894,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st for (int16 bslot = SUB_INDEX_BEGIN; bslot < item->BagSlots; bslot++) { const ItemInst* baginst = inst->GetItem(bslot); if (baginst) { - const EQEmu::Item_Struct* bagitem = baginst->GetItem(); + const EQEmu::ItemBase* bagitem = baginst->GetItem(); if (bagitem && (GetGM() || (bagitem->NoDrop != 0 && baginst->IsAttuned() == false))) { tradingWith->CastToNPC()->AddLootDrop(bagitem, &tradingWith->CastToNPC()->itemlist, baginst->GetCharges(), 1, 127, true, true); @@ -1158,7 +1158,7 @@ void Client::SendTraderItem(uint32 ItemID, uint16 Quantity) { std::string Packet; int16 FreeSlotID=0; - const EQEmu::Item_Struct* item = database.GetItem(ItemID); + const EQEmu::ItemBase* item = database.GetItem(ItemID); if(!item){ Log.Out(Logs::Detail, Logs::Trading, "Bogus item deleted in Client::SendTraderItem!\n"); @@ -1192,7 +1192,7 @@ void Client::SendSingleTraderItem(uint32 CharID, int SerialNumber) { } void Client::BulkSendTraderInventory(uint32 char_id) { - const EQEmu::Item_Struct *item; + const EQEmu::ItemBase *item; TraderCharges_Struct* TraderItems = database.LoadTraderItemWithCharges(char_id); @@ -2027,7 +2027,7 @@ static void UpdateTraderCustomerItemsAdded(uint32 CustomerID, TraderCharges_Stru if(!Customer) return; - const EQEmu::Item_Struct *item = database.GetItem(ItemID); + const EQEmu::ItemBase *item = database.GetItem(ItemID); if(!item) return; @@ -2071,7 +2071,7 @@ static void UpdateTraderCustomerPriceChanged(uint32 CustomerID, TraderCharges_St if(!Customer) return; - const EQEmu::Item_Struct *item = database.GetItem(ItemID); + const EQEmu::ItemBase *item = database.GetItem(ItemID); if(!item) return; @@ -2230,7 +2230,7 @@ void Client::HandleTraderPriceUpdate(const EQApplicationPacket *app) { } - const EQEmu::Item_Struct *item = 0; + const EQEmu::ItemBase *item = 0; if(IDOfItemToAdd) item = database.GetItem(IDOfItemToAdd); @@ -2396,7 +2396,7 @@ void Client::SendBuyerResults(char* searchString, uint32 searchID) { char *buf = (char *)outapp->pBuffer; - const EQEmu::Item_Struct* item = database.GetItem(itemID); + const EQEmu::ItemBase* item = database.GetItem(itemID); if(!item) { safe_delete(outapp); @@ -2492,7 +2492,7 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) { char *Buf = (char *)outapp->pBuffer; - const EQEmu::Item_Struct* item = database.GetItem(ItemID); + const EQEmu::ItemBase* item = database.GetItem(ItemID); if(!item) { safe_delete(outapp); @@ -2536,7 +2536,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { /*uint32 BuyerID2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused /*uint32 Unknown3 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused - const EQEmu::Item_Struct *item = database.GetItem(ItemID); + const EQEmu::ItemBase *item = database.GetItem(ItemID); if(!item || !Quantity || !Price || !QtyBuyerWants) return; @@ -2927,7 +2927,7 @@ void Client::UpdateBuyLine(const EQApplicationPacket *app) { /*uint32 UnknownZ =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused uint32 ItemCount = VARSTRUCT_DECODE_TYPE(uint32, Buf); - const EQEmu::Item_Struct *item = database.GetItem(ItemID); + const EQEmu::ItemBase *item = database.GetItem(ItemID); if(!item) return; @@ -2991,7 +2991,7 @@ void Client::BuyerItemSearch(const EQApplicationPacket *app) { BuyerItemSearchResults_Struct* bisr = (BuyerItemSearchResults_Struct*)outapp->pBuffer; - const EQEmu::Item_Struct* item = 0; + const EQEmu::ItemBase* item = 0; int Count=0; diff --git a/zone/tune.cpp b/zone/tune.cpp index 76fb97b89..ea93a43f3 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -630,7 +630,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { - ucDamageBonus = GetWeaponDamageBonus( weapon ? weapon->GetItem() : (const EQEmu::Item_Struct*) nullptr ); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemBase*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 7adafb63f..493b95d21 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -629,7 +629,7 @@ ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { int Charges = atoi(row[3]); int Cost = atoi(row[4]); - const EQEmu::Item_Struct *item = database.GetItem(ItemID); + const EQEmu::ItemBase *item = database.GetItem(ItemID); if(!item) { Log.Out(Logs::Detail, Logs::Trading, "Unable to create item\n"); @@ -684,7 +684,7 @@ void ZoneDatabase::UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charg Log.Out(Logs::Detail, Logs::Trading, "ZoneDatabase::UpdateTraderPrice(%i, %i, %i, %i)", CharID, ItemID, Charges, NewPrice); - const EQEmu::Item_Struct *item = database.GetItem(ItemID); + const EQEmu::ItemBase *item = database.GetItem(ItemID); if(!item) return; @@ -1197,7 +1197,7 @@ bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Str i = atoi(row[r]); /* Bandolier ID */ r++; si = atoi(row[r]); /* Bandolier Slot */ r++; - const EQEmu::Item_Struct* item_data = database.GetItem(atoi(row[r])); + const EQEmu::ItemBase* item_data = database.GetItem(atoi(row[r])); if (item_data) { pp->bandoliers[i].Items[si].ID = item_data->ID; r++; pp->bandoliers[i].Items[si].Icon = atoi(row[r]); r++; // Must use db value in case an Ornamentation is assigned @@ -1249,7 +1249,7 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); - const EQEmu::Item_Struct *item_data = database.GetItem(atoi(row[1])); + const EQEmu::ItemBase *item_data = database.GetItem(atoi(row[1])); if (!item_data) continue; pp->potionbelt.Items[i].ID = item_data->ID; From a0898204645c66aacfc4952b6eec4b5c8e31c8c4 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 28 May 2016 04:44:14 -0400 Subject: [PATCH 131/693] Merged client_version and inventory_version into emu_versions files --- changelog.txt | 3 + common/CMakeLists.txt | 6 +- common/client_version.cpp | 128 ------------------ common/emu_constants.h | 4 +- ...inventory_version.cpp => emu_versions.cpp} | 109 ++++++++++++++- common/{client_version.h => emu_versions.h} | 45 +++++- common/eq_limits.h | 2 +- common/eq_stream_intf.h | 2 +- common/inventory_version.h | 63 --------- common/patches/rof2_limits.h | 2 +- common/patches/rof_limits.h | 2 +- common/patches/sod_limits.h | 2 +- common/patches/sof_limits.h | 2 +- common/patches/titanium_limits.h | 2 +- common/patches/uf_limits.h | 2 +- common/struct_strategy.h | 2 +- world/client.cpp | 2 +- zone/npc.cpp | 2 +- 18 files changed, 164 insertions(+), 216 deletions(-) delete mode 100644 common/client_version.cpp rename common/{inventory_version.cpp => emu_versions.cpp} (59%) rename common/{client_version.h => emu_versions.h} (61%) delete mode 100644 common/inventory_version.h diff --git a/changelog.txt b/changelog.txt index b300d865d..d5ec9f62a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/28/2016 == +Uleat: Merged client_version and inventory_version into emu_versions files + == 05/27/2016 == Uleat: Renamed EQEmu::Item_Struct to EQEmu::ItemBase (and appropriate files) to coincide with new inventory naming conventions diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 71c78b177..fa9e6b342 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -3,7 +3,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) SET(common_sources base_packet.cpp classes.cpp - client_version.cpp condition.cpp crash.cpp crc16.cpp @@ -19,6 +18,7 @@ SET(common_sources emu_opcodes.cpp emu_tcp_connection.cpp emu_tcp_server.cpp + emu_versions.cpp eqdb.cpp eqdb_res.cpp eqemu_exception.cpp @@ -35,7 +35,6 @@ SET(common_sources faction.cpp guild_base.cpp guilds.cpp - inventory_version.cpp ipc_mutex.cpp item.cpp item_base.cpp @@ -112,7 +111,6 @@ SET(common_headers base_data.h bodytypes.h classes.h - client_version.h condition.h crash.h crc16.h @@ -128,6 +126,7 @@ SET(common_headers emu_oplist.h emu_tcp_connection.h emu_tcp_server.h + emu_versions.h eq_constants.h eq_packet_structs.h eqdb.h @@ -155,7 +154,6 @@ SET(common_headers global_define.h guild_base.h guilds.h - inventory_version.h ipc_mutex.h item.h item_base.h diff --git a/common/client_version.cpp b/common/client_version.cpp deleted file mode 100644 index b812e8744..000000000 --- a/common/client_version.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "client_version.h" - - -bool EQEmu::versions::IsValidClientVersion(ClientVersion client_version) -{ - if (client_version <= ClientVersion::Unknown || client_version > LastClientVersion) - return false; - - return true; -} - -EQEmu::versions::ClientVersion EQEmu::versions::ValidateClientVersion(ClientVersion client_version) -{ - if (client_version <= ClientVersion::Unknown || client_version > LastClientVersion) - return ClientVersion::Unknown; - - return client_version; -} - -const char* EQEmu::versions::ClientVersionName(ClientVersion client_version) -{ - switch (client_version) { - case ClientVersion::Unknown: - return "Unknown Version"; - case ClientVersion::Client62: - return "Client 6.2"; - case ClientVersion::Titanium: - return "Titanium"; - case ClientVersion::SoF: - return "SoF"; - case ClientVersion::SoD: - return "SoD"; - case ClientVersion::UF: - return "UF"; - case ClientVersion::RoF: - return "RoF"; - case ClientVersion::RoF2: - return "RoF2"; - default: - return "Invalid Version"; - }; -} - -uint32 EQEmu::versions::ConvertClientVersionToClientVersionBit(ClientVersion client_version) -{ - switch (client_version) { - case ClientVersion::Unknown: - case ClientVersion::Client62: - return bit_Unknown; - case ClientVersion::Titanium: - return bit_Titanium; - case ClientVersion::SoF: - return bit_SoF; - case ClientVersion::SoD: - return bit_SoD; - case ClientVersion::UF: - return bit_UF; - case ClientVersion::RoF: - return bit_RoF; - case ClientVersion::RoF2: - return bit_RoF2; - default: - return bit_Unknown; - } -} - -EQEmu::versions::ClientVersion EQEmu::versions::ConvertClientVersionBitToClientVersion(uint32 client_version_bit) -{ - switch (client_version_bit) { - case (uint32)static_cast(ClientVersion::Unknown) : - case ((uint32)1 << (static_cast(ClientVersion::Client62) - 1)) : - return ClientVersion::Unknown; - case ((uint32)1 << (static_cast(ClientVersion::Titanium) - 1)) : - return ClientVersion::Titanium; - case ((uint32)1 << (static_cast(ClientVersion::SoF) - 1)) : - return ClientVersion::SoF; - case ((uint32)1 << (static_cast(ClientVersion::SoD) - 1)) : - return ClientVersion::SoD; - case ((uint32)1 << (static_cast(ClientVersion::UF) - 1)) : - return ClientVersion::UF; - case ((uint32)1 << (static_cast(ClientVersion::RoF) - 1)) : - return ClientVersion::RoF; - case ((uint32)1 << (static_cast(ClientVersion::RoF2) - 1)) : - return ClientVersion::RoF2; - default: - return ClientVersion::Unknown; - } -} - -uint32 EQEmu::versions::ConvertClientVersionToExpansion(ClientVersion client_version) -{ - switch (client_version) { - case ClientVersion::Unknown: - case ClientVersion::Client62: - case ClientVersion::Titanium: - return 0x000007FFU; - case ClientVersion::SoF: - return 0x00007FFFU; - case ClientVersion::SoD: - return 0x0000FFFFU; - case ClientVersion::UF: - return 0x0001FFFFU; - case ClientVersion::RoF: - case ClientVersion::RoF2: - return 0x000FFFFFU; - default: - return 0; - } -} diff --git a/common/emu_constants.h b/common/emu_constants.h index 5e279d21c..799161aa8 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -22,9 +22,7 @@ #include "eq_limits.h" #include "emu_legacy.h" -#include "inventory_version.h" -//#include "deity.h" -//#include "say_link.h" +#include "emu_versions.h" #include diff --git a/common/inventory_version.cpp b/common/emu_versions.cpp similarity index 59% rename from common/inventory_version.cpp rename to common/emu_versions.cpp index 13573eb68..1de91a503 100644 --- a/common/inventory_version.cpp +++ b/common/emu_versions.cpp @@ -17,9 +17,116 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "inventory_version.h" +#include "emu_versions.h" +bool EQEmu::versions::IsValidClientVersion(ClientVersion client_version) +{ + if (client_version <= ClientVersion::Unknown || client_version > LastClientVersion) + return false; + + return true; +} + +EQEmu::versions::ClientVersion EQEmu::versions::ValidateClientVersion(ClientVersion client_version) +{ + if (client_version <= ClientVersion::Unknown || client_version > LastClientVersion) + return ClientVersion::Unknown; + + return client_version; +} + +const char* EQEmu::versions::ClientVersionName(ClientVersion client_version) +{ + switch (client_version) { + case ClientVersion::Unknown: + return "Unknown Version"; + case ClientVersion::Client62: + return "Client 6.2"; + case ClientVersion::Titanium: + return "Titanium"; + case ClientVersion::SoF: + return "SoF"; + case ClientVersion::SoD: + return "SoD"; + case ClientVersion::UF: + return "UF"; + case ClientVersion::RoF: + return "RoF"; + case ClientVersion::RoF2: + return "RoF2"; + default: + return "Invalid Version"; + }; +} + +uint32 EQEmu::versions::ConvertClientVersionToClientVersionBit(ClientVersion client_version) +{ + switch (client_version) { + case ClientVersion::Unknown: + case ClientVersion::Client62: + return bit_Unknown; + case ClientVersion::Titanium: + return bit_Titanium; + case ClientVersion::SoF: + return bit_SoF; + case ClientVersion::SoD: + return bit_SoD; + case ClientVersion::UF: + return bit_UF; + case ClientVersion::RoF: + return bit_RoF; + case ClientVersion::RoF2: + return bit_RoF2; + default: + return bit_Unknown; + } +} + +EQEmu::versions::ClientVersion EQEmu::versions::ConvertClientVersionBitToClientVersion(uint32 client_version_bit) +{ + switch (client_version_bit) { + case (uint32)static_cast(ClientVersion::Unknown) : + case ((uint32)1 << (static_cast(ClientVersion::Client62) - 1)) : + return ClientVersion::Unknown; + case ((uint32)1 << (static_cast(ClientVersion::Titanium) - 1)) : + return ClientVersion::Titanium; + case ((uint32)1 << (static_cast(ClientVersion::SoF) - 1)) : + return ClientVersion::SoF; + case ((uint32)1 << (static_cast(ClientVersion::SoD) - 1)) : + return ClientVersion::SoD; + case ((uint32)1 << (static_cast(ClientVersion::UF) - 1)) : + return ClientVersion::UF; + case ((uint32)1 << (static_cast(ClientVersion::RoF) - 1)) : + return ClientVersion::RoF; + case ((uint32)1 << (static_cast(ClientVersion::RoF2) - 1)) : + return ClientVersion::RoF2; + default: + return ClientVersion::Unknown; + } +} + +uint32 EQEmu::versions::ConvertClientVersionToExpansion(ClientVersion client_version) +{ + switch (client_version) { + case ClientVersion::Unknown: + case ClientVersion::Client62: + case ClientVersion::Titanium: + return 0x000007FFU; + case ClientVersion::SoF: + return 0x00007FFFU; + case ClientVersion::SoD: + return 0x0000FFFFU; + case ClientVersion::UF: + return 0x0001FFFFU; + case ClientVersion::RoF: + case ClientVersion::RoF2: + return 0x000FFFFFU; + default: + return 0; + } +} + bool EQEmu::versions::IsValidInventoryVersion(InventoryVersion inventory_version) { if (inventory_version <= InventoryVersion::Unknown || inventory_version > LastInventoryVersion) diff --git a/common/client_version.h b/common/emu_versions.h similarity index 61% rename from common/client_version.h rename to common/emu_versions.h index a04e5c10b..45bb4ddb1 100644 --- a/common/client_version.h +++ b/common/emu_versions.h @@ -17,8 +17,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef COMMON_CLIENT_VERSION_H -#define COMMON_CLIENT_VERSION_H +#ifndef COMMON_EMU_VERSIONS_H +#define COMMON_EMU_VERSIONS_H #include "types.h" @@ -61,8 +61,8 @@ namespace EQEmu bit_AllClients = 0xFFFFFFFF }; - static const ClientVersion LastClientVersion = ClientVersion::RoF2; - static const size_t ClientVersionCount = (static_cast(LastClientVersion) + 1); + const ClientVersion LastClientVersion = ClientVersion::RoF2; + const size_t ClientVersionCount = (static_cast(LastClientVersion) + 1); extern bool IsValidClientVersion(ClientVersion client_version); extern ClientVersion ValidateClientVersion(ClientVersion client_version); @@ -70,9 +70,42 @@ namespace EQEmu extern uint32 ConvertClientVersionToClientVersionBit(ClientVersion client_version); extern ClientVersion ConvertClientVersionBitToClientVersion(uint32 client_version_bit); extern uint32 ConvertClientVersionToExpansion(ClientVersion client_version); - + + } /*versions*/ + + namespace versions { + enum class InventoryVersion { + Unknown = 0, + Client62, + Titanium, + SoF, + SoD, + UF, + RoF, + RoF2, + NPC, + Merc, + Bot, + Pet + }; + + const InventoryVersion LastInventoryVersion = InventoryVersion::Pet; + const InventoryVersion LastPCInventoryVersion = InventoryVersion::RoF2; + const InventoryVersion LastNonPCInventoryVersion = InventoryVersion::Pet; + const size_t InventoryVersionCount = (static_cast(LastInventoryVersion) + 1); + + extern bool IsValidInventoryVersion(InventoryVersion inventory_version); + extern bool IsValidPCInventoryVersion(InventoryVersion inventory_version); + extern bool IsValidNonPCInventoryVersion(InventoryVersion inventory_version); + extern InventoryVersion ValidateInventoryVersion(InventoryVersion inventory_version); + extern InventoryVersion ValidatePCInventoryVersion(InventoryVersion inventory_version); + extern InventoryVersion ValidateNonPCInventoryVersion(InventoryVersion inventory_version); + extern const char* InventoryVersionName(InventoryVersion inventory_version); + extern ClientVersion ConvertInventoryVersionToClientVersion(InventoryVersion inventory_version); + extern InventoryVersion ConvertClientVersionToInventoryVersion(ClientVersion client_version); + } /*versions*/ } /*EQEmu*/ -#endif /*COMMON_CLIENT_VERSION_H*/ +#endif /*COMMON_EMU_VERSIONS_H*/ diff --git a/common/eq_limits.h b/common/eq_limits.h index d6b03d070..a1168d348 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -22,7 +22,7 @@ #include "types.h" #include "eq_constants.h" -#include "inventory_version.h" +#include "emu_versions.h" #include "../common/patches/titanium_limits.h" #include "../common/patches/sof_limits.h" #include "../common/patches/sod_limits.h" diff --git a/common/eq_stream_intf.h b/common/eq_stream_intf.h index f357eb27b..917a13a86 100644 --- a/common/eq_stream_intf.h +++ b/common/eq_stream_intf.h @@ -4,7 +4,7 @@ //this is the only part of an EQStream that is seen by the application. #include -#include "client_version.h" // inv2 watch +#include "emu_versions.h" typedef enum { ESTABLISHED, diff --git a/common/inventory_version.h b/common/inventory_version.h deleted file mode 100644 index 61762e5bc..000000000 --- a/common/inventory_version.h +++ /dev/null @@ -1,63 +0,0 @@ -/* EQEMu: Everquest Server Emulator - - Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY except by those people which sell it, which - are required to give you total support for your newly bought product; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef COMMON_INVENTORY_VERSION_H -#define COMMON_INVENTORY_VERSION_H - -#include "client_version.h" - - -namespace EQEmu -{ - namespace versions { - enum class InventoryVersion { - Unknown = 0, - Client62, - Titanium, - SoF, - SoD, - UF, - RoF, - RoF2, - NPC, - Merc, - Bot, - Pet - }; - - static const InventoryVersion LastInventoryVersion = InventoryVersion::Pet; - static const InventoryVersion LastPCInventoryVersion = InventoryVersion::RoF2; - static const InventoryVersion LastNonPCInventoryVersion = InventoryVersion::Pet; - static const size_t InventoryVersionCount = (static_cast(LastInventoryVersion) + 1); - - extern bool IsValidInventoryVersion(InventoryVersion inventory_version); - extern bool IsValidPCInventoryVersion(InventoryVersion inventory_version); - extern bool IsValidNonPCInventoryVersion(InventoryVersion inventory_version); - extern InventoryVersion ValidateInventoryVersion(InventoryVersion inventory_version); - extern InventoryVersion ValidatePCInventoryVersion(InventoryVersion inventory_version); - extern InventoryVersion ValidateNonPCInventoryVersion(InventoryVersion inventory_version); - extern const char* InventoryVersionName(InventoryVersion inventory_version); - extern ClientVersion ConvertInventoryVersionToClientVersion(InventoryVersion inventory_version); - extern InventoryVersion ConvertClientVersionToInventoryVersion(ClientVersion client_version); - - } /*versions*/ - -} /*EQEmu*/ - -#endif /*COMMON_INVENTORY_VERSION_H*/ diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index b38e88d7a..79218f67f 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -21,7 +21,7 @@ #define COMMON_ROF2_LIMITS_H #include "../types.h" -#include "../client_version.h" +#include "../emu_versions.h" #include "../skills.h" diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index 14f9e32a1..5275bfaad 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -21,7 +21,7 @@ #define COMMON_ROF_LIMITS_H #include "../types.h" -#include "../client_version.h" +#include "../emu_versions.h" #include "../skills.h" diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index 8bdac4150..e50790793 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -21,7 +21,7 @@ #define COMMON_SOD_LIMITS_H #include "../types.h" -#include "../client_version.h" +#include "../emu_versions.h" #include "../skills.h" diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index bd755c820..5243b289b 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -21,7 +21,7 @@ #define COMMON_SOF_LIMITS_H #include "../types.h" -#include "../client_version.h" +#include "../emu_versions.h" #include "../skills.h" diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index a4ce67faf..0d4620997 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -21,7 +21,7 @@ #define COMMON_TITANIUM_LIMITS_H #include "../types.h" -#include "../client_version.h" +#include "../emu_versions.h" #include "../skills.h" diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index fb2370a4c..7f1ec33a8 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -21,7 +21,7 @@ #define COMMON_UF_LIMITS_H #include "../types.h" -#include "../client_version.h" +#include "../emu_versions.h" #include "../skills.h" diff --git a/common/struct_strategy.h b/common/struct_strategy.h index b7417de8c..fdb596891 100644 --- a/common/struct_strategy.h +++ b/common/struct_strategy.h @@ -4,7 +4,7 @@ class EQApplicationPacket; class EQStream; #include "emu_opcodes.h" -#include "client_version.h" // inv2 watch +#include "emu_versions.h" #include #include diff --git a/world/client.cpp b/world/client.cpp index 057db0961..fdccc8f7d 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -32,7 +32,7 @@ #include "../common/skills.h" #include "../common/extprofile.h" #include "../common/string_util.h" -#include "../common/client_version.h" // inv2 watch +#include "../common/emu_versions.h" #include "../common/random.h" #include "../common/shareddb.h" diff --git a/zone/npc.cpp b/zone/npc.cpp index 1df16ca12..d38ad92b3 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -24,7 +24,7 @@ #include "../common/seperator.h" #include "../common/spdat.h" #include "../common/string_util.h" -#include "../common/client_version.h" // inv2 watch +#include "../common/emu_versions.h" #include "../common/features.h" #include "../common/item.h" #include "../common/item_base.h" From 2a74d0463589721f3f0a7c58ba5bee21cea8f699 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 29 May 2016 20:30:03 -0400 Subject: [PATCH 132/693] Added offline client inventory version definitions and convertors --- common/emu_versions.cpp | 108 +++++++++++++++++ common/emu_versions.h | 19 ++- common/eq_limits.cpp | 248 +++++++++++++++++++++++++++++++++++----- 3 files changed, 342 insertions(+), 33 deletions(-) diff --git a/common/emu_versions.cpp b/common/emu_versions.cpp index 1de91a503..3104b6832 100644 --- a/common/emu_versions.cpp +++ b/common/emu_versions.cpp @@ -151,6 +151,14 @@ bool EQEmu::versions::IsValidNonPCInventoryVersion(InventoryVersion inventory_ve return true; } +bool EQEmu::versions::IsValidOfflinePCInventoryVersion(InventoryVersion inventory_version) +{ + if (inventory_version <= LastNonPCInventoryVersion || inventory_version > LastOfflinePCInventoryVersion) + return false; + + return true; +} + EQEmu::versions::InventoryVersion EQEmu::versions::ValidateInventoryVersion(InventoryVersion inventory_version) { if (inventory_version <= InventoryVersion::Unknown || inventory_version > LastInventoryVersion) @@ -175,6 +183,14 @@ EQEmu::versions::InventoryVersion EQEmu::versions::ValidateNonPCInventoryVersion return inventory_version; } +EQEmu::versions::InventoryVersion EQEmu::versions::ValidateOfflinePCInventoryVersion(InventoryVersion inventory_version) +{ + if (inventory_version <= LastNonPCInventoryVersion || inventory_version > LastOfflinePCInventoryVersion) + return InventoryVersion::Unknown; + + return inventory_version; +} + const char* EQEmu::versions::InventoryVersionName(InventoryVersion inventory_version) { switch (inventory_version) { @@ -202,6 +218,18 @@ const char* EQEmu::versions::InventoryVersionName(InventoryVersion inventory_ver return "Bot"; case InventoryVersion::Pet: return "Pet"; + case InventoryVersion::OfflineTitanium: + return "Offline Titanium"; + case InventoryVersion::OfflineSoF: + return "Offline SoF"; + case InventoryVersion::OfflineSoD: + return "Offline SoD"; + case InventoryVersion::OfflineUF: + return "Offline UF"; + case InventoryVersion::OfflineRoF: + return "Offline RoF"; + case InventoryVersion::OfflineRoF2: + return "Offline RoF2"; default: return "Invalid Version"; }; @@ -252,3 +280,83 @@ EQEmu::versions::InventoryVersion EQEmu::versions::ConvertClientVersionToInvento return InventoryVersion::Unknown; } } + +EQEmu::versions::InventoryVersion EQEmu::versions::ConvertPCInventoryVersionToOfflinePCInventoryVersion(InventoryVersion inventory_version) +{ + switch (inventory_version) { + case InventoryVersion::Titanium: + return InventoryVersion::OfflineTitanium; + case InventoryVersion::SoF: + return InventoryVersion::OfflineSoF; + case InventoryVersion::SoD: + return InventoryVersion::OfflineSoD; + case InventoryVersion::UF: + return InventoryVersion::OfflineUF; + case InventoryVersion::RoF: + return InventoryVersion::OfflineRoF; + case InventoryVersion::RoF2: + return InventoryVersion::OfflineRoF2; + default: + return InventoryVersion::Unknown; + } +} + +EQEmu::versions::InventoryVersion EQEmu::versions::ConvertOfflinePCInventoryVersionToPCInventoryVersion(InventoryVersion inventory_version) +{ + switch (inventory_version) { + case InventoryVersion::OfflineTitanium: + return InventoryVersion::Titanium; + case InventoryVersion::OfflineSoF: + return InventoryVersion::SoF; + case InventoryVersion::OfflineSoD: + return InventoryVersion::SoD; + case InventoryVersion::OfflineUF: + return InventoryVersion::UF; + case InventoryVersion::OfflineRoF: + return InventoryVersion::RoF; + case InventoryVersion::OfflineRoF2: + return InventoryVersion::RoF2; + default: + return InventoryVersion::Unknown; + } +} + +EQEmu::versions::ClientVersion EQEmu::versions::ConvertOfflinePCInventoryVersionToClientVersion(InventoryVersion inventory_version) +{ + switch (inventory_version) { + case InventoryVersion::OfflineTitanium: + return ClientVersion::Titanium; + case InventoryVersion::OfflineSoF: + return ClientVersion::SoF; + case InventoryVersion::OfflineSoD: + return ClientVersion::SoD; + case InventoryVersion::OfflineUF: + return ClientVersion::UF; + case InventoryVersion::OfflineRoF: + return ClientVersion::RoF; + case InventoryVersion::OfflineRoF2: + return ClientVersion::RoF2; + default: + return ClientVersion::Unknown; + } +} + +EQEmu::versions::InventoryVersion EQEmu::versions::ConvertClientVersionToOfflinePCInventoryVersion(ClientVersion client_version) +{ + switch (client_version) { + case ClientVersion::Titanium: + return InventoryVersion::OfflineTitanium; + case ClientVersion::SoF: + return InventoryVersion::OfflineSoF; + case ClientVersion::SoD: + return InventoryVersion::OfflineSoD; + case ClientVersion::UF: + return InventoryVersion::OfflineUF; + case ClientVersion::RoF: + return InventoryVersion::OfflineRoF; + case ClientVersion::RoF2: + return InventoryVersion::OfflineRoF2; + default: + return InventoryVersion::Unknown; + } +} diff --git a/common/emu_versions.h b/common/emu_versions.h index 45bb4ddb1..82244f039 100644 --- a/common/emu_versions.h +++ b/common/emu_versions.h @@ -86,23 +86,38 @@ namespace EQEmu NPC, Merc, Bot, - Pet + Pet, + OfflineTitanium, + OfflineSoF, + OfflineSoD, + OfflineUF, + OfflineRoF, + OfflineRoF2 }; - const InventoryVersion LastInventoryVersion = InventoryVersion::Pet; + const InventoryVersion LastInventoryVersion = InventoryVersion::OfflineRoF2; const InventoryVersion LastPCInventoryVersion = InventoryVersion::RoF2; const InventoryVersion LastNonPCInventoryVersion = InventoryVersion::Pet; + const InventoryVersion LastOfflinePCInventoryVersion = InventoryVersion::OfflineRoF2; const size_t InventoryVersionCount = (static_cast(LastInventoryVersion) + 1); extern bool IsValidInventoryVersion(InventoryVersion inventory_version); extern bool IsValidPCInventoryVersion(InventoryVersion inventory_version); extern bool IsValidNonPCInventoryVersion(InventoryVersion inventory_version); + extern bool IsValidOfflinePCInventoryVersion(InventoryVersion inventory_version); + extern InventoryVersion ValidateInventoryVersion(InventoryVersion inventory_version); extern InventoryVersion ValidatePCInventoryVersion(InventoryVersion inventory_version); extern InventoryVersion ValidateNonPCInventoryVersion(InventoryVersion inventory_version); + extern InventoryVersion ValidateOfflinePCInventoryVersion(InventoryVersion inventory_version); + extern const char* InventoryVersionName(InventoryVersion inventory_version); extern ClientVersion ConvertInventoryVersionToClientVersion(InventoryVersion inventory_version); extern InventoryVersion ConvertClientVersionToInventoryVersion(ClientVersion client_version); + extern InventoryVersion ConvertPCInventoryVersionToOfflinePCInventoryVersion(InventoryVersion inventory_version); + extern InventoryVersion ConvertOfflinePCInventoryVersionToPCInventoryVersion(InventoryVersion inventory_version); + extern ClientVersion ConvertOfflinePCInventoryVersionToClientVersion(InventoryVersion inventory_version); + extern InventoryVersion ConvertClientVersionToOfflinePCInventoryVersion(ClientVersion client_version); } /*versions*/ diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 8dffc71f9..2c40a98b9 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -52,7 +52,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ legacy::TYPE_POSSESSIONS_SIZE, legacy::TYPE_POSSESSIONS_SIZE, legacy::TYPE_POSSESSIONS_SIZE, - legacy::TYPE_POSSESSIONS_SIZE + legacy::TYPE_POSSESSIONS_SIZE, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeBank] ClientUnknown::Null, @@ -66,7 +72,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeSharedBank] ClientUnknown::Null, @@ -80,7 +92,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeTrade] ClientUnknown::Null, @@ -94,7 +112,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ 4, 4, legacy::TYPE_TRADE_SIZE, // client thinks this is another client - 4 + 4, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeWorld] ClientUnknown::Null, @@ -108,7 +132,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeLimbo] ClientUnknown::Null, @@ -122,7 +152,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeTribute] ClientUnknown::Null, @@ -136,7 +172,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeTrophyTribute] ClientUnknown::Null, @@ -150,7 +192,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeGuildTribute] ClientUnknown::Null, @@ -164,7 +212,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeMerchant] ClientUnknown::Null, @@ -178,7 +232,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeDeleted] ClientUnknown::Null, @@ -192,7 +252,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeCorpse] ClientUnknown::Null, @@ -206,7 +272,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeBazaar] ClientUnknown::Null, @@ -220,7 +292,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeInspect] ClientUnknown::Null, @@ -234,7 +312,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeRealEstate] ClientUnknown::Null, @@ -248,7 +332,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeViewMODPC] ClientUnknown::Null, @@ -262,7 +352,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeViewMODBank] ClientUnknown::Null, @@ -276,7 +372,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeViewMODSharedBank] ClientUnknown::Null, @@ -290,7 +392,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeViewMODLimbo] ClientUnknown::Null, @@ -304,7 +412,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeAltStorage] ClientUnknown::Null, @@ -318,7 +432,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeArchived] ClientUnknown::Null, @@ -332,7 +452,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeMail] ClientUnknown::Null, @@ -346,7 +472,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeGuildTrophyTribute] ClientUnknown::Null, @@ -360,7 +492,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeKrono] ClientUnknown::Null, @@ -374,7 +512,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }, { // local[TypeOther] ClientUnknown::Null, @@ -388,7 +532,13 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null } }; @@ -412,7 +562,13 @@ uint64 EQEmu::inventory::PossessionsBitmask(versions::InventoryVersion inventory EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, - EntityLimits::pet::Null + EntityLimits::pet::Null, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }; return NOT_USED; @@ -433,7 +589,13 @@ bool EQEmu::inventory::AllowEmptyBagInBag(versions::InventoryVersion inventory_v EntityLimits::npc::False, EntityLimits::merc::False, EntityLimits::bot::False, - EntityLimits::pet::False + EntityLimits::pet::False, + Titanium::False, + SoF::False, + SoD::False, + UF::False, + RoF::False, + RoF2::False }; return false; @@ -454,7 +616,13 @@ bool EQEmu::inventory::AllowClickCastFromBag(versions::InventoryVersion inventor EntityLimits::npc::False, EntityLimits::merc::False, EntityLimits::bot::False, - EntityLimits::pet::False + EntityLimits::pet::False, + Titanium::False, + SoF::False, + SoD::False, + UF::False, + RoF::False, + RoF2::False }; return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; @@ -474,7 +642,13 @@ uint16 EQEmu::inventory::ItemAugSize(versions::InventoryVersion inventory_versio legacy::ITEM_COMMON_SIZE, legacy::ITEM_COMMON_SIZE, legacy::ITEM_COMMON_SIZE, - legacy::ITEM_COMMON_SIZE + legacy::ITEM_COMMON_SIZE, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }; return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; @@ -494,7 +668,13 @@ uint16 EQEmu::inventory::ItemBagSize(versions::InventoryVersion inventory_versio legacy::ITEM_CONTAINER_SIZE, legacy::ITEM_CONTAINER_SIZE, legacy::ITEM_CONTAINER_SIZE, - legacy::ITEM_CONTAINER_SIZE + legacy::ITEM_CONTAINER_SIZE, + Titanium::Null, + SoF::Null, + SoD::Null, + UF::Null, + RoF::Null, + RoF2::Null }; return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; @@ -514,7 +694,13 @@ bool EQEmu::profile::CoinHasWeight(versions::InventoryVersion inventory_version) EntityLimits::npc::True, EntityLimits::merc::True, EntityLimits::bot::True, - EntityLimits::pet::True + EntityLimits::pet::True, + Titanium::False, + SoF::False, + SoD::False, + UF::False, + RoF::False, + RoF2::False }; return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; From ecc9e41ab2fd0c1a51905463d9059712cfefcd54 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 30 May 2016 03:03:55 -0400 Subject: [PATCH 133/693] Fix for server crash related to deleting a bot with a spawned pet --- zone/bot.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/bot.cpp b/zone/bot.cpp index 3af2d161f..76f537a5b 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1795,6 +1795,8 @@ bool Bot::DeletePet() NPC* pet_inst = GetPet()->CastToNPC(); pet_inst->SetOwnerID(0); + SetPet(nullptr); + return true; } From b155a603aab62d4ef189f270d2490a1ba923b0f9 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 30 May 2016 03:32:01 -0400 Subject: [PATCH 134/693] Added multi-type EQEmu::ValueWithin function --- common/data_verification.h | 47 ++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/common/data_verification.h b/common/data_verification.h index 9da85a579..fe1152cb4 100644 --- a/common/data_verification.h +++ b/common/data_verification.h @@ -1,5 +1,6 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,36 +14,42 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef COMMON_DATA_VERIFICATION_H #define COMMON_DATA_VERIFICATION_H #include + namespace EQEmu { + template + T Clamp(const T& value, const T& lower, const T& upper) { + return std::max(lower, std::min(value, upper)); + } -template -T Clamp(const T& value, const T& lower, const T& upper) { - return std::max(lower, std::min(value, upper)); -} + template + T ClampLower(const T& value, const T& lower) { + return std::max(lower, value); + } -template -T ClampLower(const T& value, const T& lower) { - return std::max(lower, value); -} + template + T ClampUpper(const T& value, const T& upper) { + return std::min(value, upper); + } -template -T ClampUpper(const T& value, const T& upper) { - return std::min(value, upper); -} + template + bool ValueWithin(const T& value, const T& lower, const T& upper) { + return value >= lower && value <= upper; + } -template -bool ValueWithin(const T& value, const T& lower, const T& upper) { - return value >= lower && value <= upper; -} + template + bool ValueWithin(const T1& value, const T2& lower, const T3& upper) { + return value >= (T1)lower && value <= (T1)upper; + } -} +} /*EQEmu*/ -#endif +#endif /*COMMON_DATA_VERIFICATION_H*/ From 16895910e41decb1c287fffc6ebc054b9635a28a Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 30 May 2016 06:52:25 -0400 Subject: [PATCH 135/693] Another eq_dictionary pass --- common/emu_limits.cpp | 4 +- common/emu_limits.h | 24 +- common/eq_constants.h | 1 - common/eq_limits.cpp | 568 ++++++++++++++++------------- common/eq_limits.h | 28 +- common/eq_packet_structs.h | 2 +- common/item.cpp | 2 +- common/patches/rof.cpp | 6 +- common/patches/rof2.cpp | 6 +- common/patches/rof2_limits.cpp | 18 +- common/patches/rof2_limits.h | 54 +-- common/patches/rof_limits.cpp | 18 +- common/patches/rof_limits.h | 54 +-- common/patches/sod_limits.cpp | 24 +- common/patches/sod_limits.h | 56 +-- common/patches/sof_limits.cpp | 24 +- common/patches/sof_limits.h | 56 +-- common/patches/titanium_limits.cpp | 24 +- common/patches/titanium_limits.h | 56 +-- common/patches/uf_limits.cpp | 24 +- common/patches/uf_limits.h | 56 +-- common/say_link.cpp | 26 +- world/client.cpp | 4 +- world/worlddb.cpp | 2 +- zone/bot.cpp | 2 +- zone/client_mods.cpp | 2 +- zone/command.cpp | 4 +- zone/corpse.cpp | 4 +- zone/tasks.cpp | 2 +- 29 files changed, 630 insertions(+), 521 deletions(-) diff --git a/common/emu_limits.cpp b/common/emu_limits.cpp index 64d038a54..a9e74898d 100644 --- a/common/emu_limits.cpp +++ b/common/emu_limits.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software diff --git a/common/emu_limits.h b/common/emu_limits.h index e5b66faeb..5c72315a0 100644 --- a/common/emu_limits.h +++ b/common/emu_limits.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -31,25 +31,37 @@ namespace EntityLimits enum : int { Invalid = -1, Null, Safety }; enum : bool { False = false, True = true }; - } + + const size_t InvTypeTradeSize = 4; + + } /*npc*/ namespace merc { enum : int { Invalid = -1, Null, Safety }; enum : bool { False = false, True = true }; - } + + const size_t InvTypeTradeSize = 4; + + } /*merc*/ namespace bot { enum : int { Invalid = -1, Null, Safety }; enum : bool { False = false, True = true }; - } + + const size_t InvTypeTradeSize = 8; + + } /*bot*/ namespace pet { enum : int { Invalid = -1, Null, Safety }; enum : bool { False = false, True = true }; - } + + const size_t InvTypeTradeSize = 4; + + } /*pet*/ }; /*EntityLimits*/ diff --git a/common/eq_constants.h b/common/eq_constants.h index e23089ce6..0fe5ccf48 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -516,7 +516,6 @@ static const uint8 SkillDamageTypes[EQEmu::skills::HIGHEST_SKILL + 1] = // chang */ #define INVALID_INDEX -1 -#define NOT_USED 0 #define NO_ITEM 0 // yes..these are redundant... but, they help to identify and define what is actually being performed diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 2c40a98b9..f9bee1c71 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -21,7 +21,7 @@ #include "emu_limits.h" -size_t EQEmu::constants::CharacterCreationLimit(versions::ClientVersion client_version) +size_t EQEmu::constants::GetCharacterCreationLimit(versions::ClientVersion client_version) { static const size_t local[versions::ClientVersionCount] = { ClientUnknown::Null, @@ -37,22 +37,22 @@ size_t EQEmu::constants::CharacterCreationLimit(versions::ClientVersion client_v return local[static_cast(versions::ValidateClientVersion(client_version))]; } -uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_version, int16 inv_type) +size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion inventory_version, int inv_type) { - static const uint16 local[legacy::TypeCount][versions::InventoryVersionCount] = { + static const size_t local[legacy::TypeCount][versions::InventoryVersionCount] = { { // local[TypePossessions] ClientUnknown::Null, Client62::Null, - legacy::TYPE_POSSESSIONS_SIZE, - legacy::TYPE_POSSESSIONS_SIZE, - legacy::TYPE_POSSESSIONS_SIZE, - legacy::TYPE_POSSESSIONS_SIZE, - legacy::TYPE_POSSESSIONS_SIZE, - legacy::TYPE_POSSESSIONS_SIZE, - legacy::TYPE_POSSESSIONS_SIZE, - legacy::TYPE_POSSESSIONS_SIZE, - legacy::TYPE_POSSESSIONS_SIZE, - legacy::TYPE_POSSESSIONS_SIZE, + legacy::TYPE_POSSESSIONS_SIZE, //Titanium::invtype::InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //SoF::invtype::InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //SoD::invtype::InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //UF::invtype::InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //RoF::invtype::InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //RoF2::invtype::InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, Titanium::Null, SoF::Null, SoD::Null, @@ -64,11 +64,11 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ ClientUnknown::Null, Client62::Null, Titanium::invtype::InvTypeBankSize, - legacy::TYPE_BANK_SIZE, - legacy::TYPE_BANK_SIZE, - legacy::TYPE_BANK_SIZE, - legacy::TYPE_BANK_SIZE, - legacy::TYPE_BANK_SIZE, + SoF::invtype::InvTypeBankSize, + SoD::invtype::InvTypeBankSize, + UF::invtype::InvTypeBankSize, + RoF::invtype::InvTypeBankSize, + RoF2::invtype::InvTypeBankSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -83,12 +83,12 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ { // local[TypeSharedBank] ClientUnknown::Null, Client62::Null, - legacy::TYPE_SHARED_BANK_SIZE, - legacy::TYPE_SHARED_BANK_SIZE, - legacy::TYPE_SHARED_BANK_SIZE, - legacy::TYPE_SHARED_BANK_SIZE, - legacy::TYPE_SHARED_BANK_SIZE, - legacy::TYPE_SHARED_BANK_SIZE, + Titanium::invtype::InvTypeSharedBankSize, + SoF::invtype::InvTypeSharedBankSize, + SoD::invtype::InvTypeSharedBankSize, + UF::invtype::InvTypeSharedBankSize, + RoF::invtype::InvTypeSharedBankSize, + RoF2::invtype::InvTypeSharedBankSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -103,32 +103,32 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ { // local[TypeTrade] ClientUnknown::Null, Client62::Null, - legacy::TYPE_TRADE_SIZE, - legacy::TYPE_TRADE_SIZE, - legacy::TYPE_TRADE_SIZE, - legacy::TYPE_TRADE_SIZE, - legacy::TYPE_TRADE_SIZE, - legacy::TYPE_TRADE_SIZE, - 4, - 4, - legacy::TYPE_TRADE_SIZE, // client thinks this is another client - 4, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null + Titanium::invtype::InvTypeTradeSize, + SoF::invtype::InvTypeTradeSize, + SoD::invtype::InvTypeTradeSize, + UF::invtype::InvTypeTradeSize, + RoF::invtype::InvTypeTradeSize, + RoF2::invtype::InvTypeTradeSize, + EntityLimits::npc::InvTypeTradeSize, + EntityLimits::merc::InvTypeTradeSize, + EntityLimits::bot::InvTypeTradeSize, // client thinks this is another client + EntityLimits::pet::InvTypeTradeSize, + Titanium::invtype::InvTypeTradeSize, + SoF::invtype::InvTypeTradeSize, + SoD::invtype::InvTypeTradeSize, + UF::invtype::InvTypeTradeSize, + RoF::invtype::InvTypeTradeSize, + RoF2::invtype::InvTypeTradeSize }, { // local[TypeWorld] ClientUnknown::Null, Client62::Null, - legacy::TYPE_WORLD_SIZE, - legacy::TYPE_WORLD_SIZE, - legacy::TYPE_WORLD_SIZE, - legacy::TYPE_WORLD_SIZE, - legacy::TYPE_WORLD_SIZE, - legacy::TYPE_WORLD_SIZE, + Titanium::invtype::InvTypeWorldSize, + SoF::invtype::InvTypeWorldSize, + SoD::invtype::InvTypeWorldSize, + UF::invtype::InvTypeWorldSize, + RoF::invtype::InvTypeWorldSize, + RoF2::invtype::InvTypeWorldSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -143,12 +143,12 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ { // local[TypeLimbo] ClientUnknown::Null, Client62::Null, - legacy::TYPE_LIMBO_SIZE, - legacy::TYPE_LIMBO_SIZE, - legacy::TYPE_LIMBO_SIZE, - legacy::TYPE_LIMBO_SIZE, - legacy::TYPE_LIMBO_SIZE, - legacy::TYPE_LIMBO_SIZE, + Titanium::invtype::InvTypeLimboSize, + SoF::invtype::InvTypeLimboSize, + SoD::invtype::InvTypeLimboSize, + UF::invtype::InvTypeLimboSize, + RoF::invtype::InvTypeLimboSize, + RoF2::invtype::InvTypeLimboSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -163,12 +163,12 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ { // local[TypeTribute] ClientUnknown::Null, Client62::Null, - legacy::TYPE_TRIBUTE_SIZE, - legacy::TYPE_TRIBUTE_SIZE, - legacy::TYPE_TRIBUTE_SIZE, - legacy::TYPE_TRIBUTE_SIZE, - legacy::TYPE_TRIBUTE_SIZE, - legacy::TYPE_TRIBUTE_SIZE, + Titanium::invtype::InvTypeTributeSize, + SoF::invtype::InvTypeTributeSize, + SoD::invtype::InvTypeTributeSize, + UF::invtype::InvTypeTributeSize, + RoF::invtype::InvTypeTributeSize, + RoF2::invtype::InvTypeTributeSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -187,8 +187,8 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ SoF::Null, SoD::Null, UF::Null, - legacy::TYPE_TROPHY_TRIBUTE_SIZE, - legacy::TYPE_TROPHY_TRIBUTE_SIZE, + RoF::Null, //RoF::invtype::InvTypeTrophyTributeSize, + RoF2::Null, //RoF2::invtype::InvTypeTrophyTributeSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -203,12 +203,12 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ { // local[TypeGuildTribute] ClientUnknown::Null, Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - legacy::TYPE_GUILD_TRIBUTE_SIZE, - legacy::TYPE_GUILD_TRIBUTE_SIZE, + Titanium::Null, //Titanium::invtype::InvTypeGuildTributeSize, + SoF::Null, //SoF::invtype::InvTypeGuildTributeSize, + SoD::Null, //SoD::invtype::InvTypeGuildTributeSize, + UF::Null, //UF::invtype::InvTypeGuildTributeSize, + RoF::Null, //RoF::invtype::InvTypeGuildTributeSize, + RoF2::Null, //RoF2::invtype::InvTypeGuildTributeSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -223,22 +223,22 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ { // local[TypeMerchant] ClientUnknown::Null, Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - legacy::TYPE_MERCHANT_SIZE, - legacy::TYPE_MERCHANT_SIZE, + Titanium::invtype::InvTypeMerchantSize, + SoF::invtype::InvTypeMerchantSize, + SoD::invtype::InvTypeMerchantSize, + UF::invtype::InvTypeMerchantSize, + RoF::invtype::InvTypeMerchantSize, + RoF2::invtype::InvTypeMerchantSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, EntityLimits::pet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null + Titanium::invtype::InvTypeMerchantSize, + SoF::invtype::InvTypeMerchantSize, + SoD::invtype::InvTypeMerchantSize, + UF::invtype::InvTypeMerchantSize, + RoF::invtype::InvTypeMerchantSize, + RoF2::invtype::InvTypeMerchantSize }, { // local[TypeDeleted] ClientUnknown::Null, @@ -247,8 +247,8 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ SoF::Null, SoD::Null, UF::Null, - legacy::TYPE_DELETED_SIZE, - legacy::TYPE_DELETED_SIZE, + RoF::Null, //RoF::invtype::InvTypeDeletedSize, + RoF2::Null, //RoF2::invtype::InvTypeDeletedSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -269,10 +269,10 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ UF::invtype::InvTypeCorpseSize, RoF::invtype::InvTypeCorpseSize, RoF2::invtype::InvTypeCorpseSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::npc::Null, //InvTypeCorpseSize, + EntityLimits::merc::Null, //InvTypeCorpseSize, + EntityLimits::bot::Null, //InvTypeCorpseSize, + EntityLimits::pet::Null, //InvTypeCorpseSize, Titanium::Null, SoF::Null, SoD::Null, @@ -283,22 +283,22 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ { // local[TypeBazaar] ClientUnknown::Null, Client62::Null, - legacy::TYPE_BAZAAR_SIZE, - legacy::TYPE_BAZAAR_SIZE, - legacy::TYPE_BAZAAR_SIZE, - legacy::TYPE_BAZAAR_SIZE, - legacy::TYPE_BAZAAR_SIZE, - legacy::TYPE_BAZAAR_SIZE, + legacy::TYPE_BAZAAR_SIZE, //Titanium::invtype::InvTypeBazaarSize, + legacy::TYPE_BAZAAR_SIZE, //SoF::invtype::InvTypeBazaarSize, + legacy::TYPE_BAZAAR_SIZE, //SoD::invtype::InvTypeBazaarSize, + legacy::TYPE_BAZAAR_SIZE, //UF::invtype::InvTypeBazaarSize, + legacy::TYPE_BAZAAR_SIZE, //RoF::invtype::InvTypeBazaarSize, + legacy::TYPE_BAZAAR_SIZE, //RoF2::invtype::InvTypeBazaarSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, EntityLimits::pet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null + Titanium::Null, //Titanium::invtype::InvTypeBazaarSize, + SoF::Null, //SoF::invtype::InvTypeBazaarSize, + SoD::Null, //SoD::invtype::InvTypeBazaarSize, + UF::Null, //UF::invtype::InvTypeBazaarSize, + RoF::Null, //RoF::invtype::InvTypeBazaarSize, + RoF2::Null //RoF2::invtype::InvTypeBazaarSize, }, { // local[TypeInspect] ClientUnknown::Null, @@ -313,12 +313,12 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ EntityLimits::merc::Null, EntityLimits::bot::Null, EntityLimits::pet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null + Titanium::invtype::InvTypeInspectSize, + SoF::invtype::InvTypeInspectSize, + SoD::invtype::InvTypeInspectSize, + UF::invtype::InvTypeInspectSize, + RoF::invtype::InvTypeInspectSize, + RoF2::invtype::InvTypeInspectSize }, { // local[TypeRealEstate] ClientUnknown::Null, @@ -327,8 +327,8 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ SoF::Null, SoD::Null, UF::Null, - legacy::TYPE_REAL_ESTATE_SIZE, - legacy::TYPE_REAL_ESTATE_SIZE, + RoF::Null, //RoF::invtype::InvTypeRealEstateSize, + RoF2::Null, //RoF2::invtype::InvTypeRealEstateSize EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -343,92 +343,92 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ { // local[TypeViewMODPC] ClientUnknown::Null, Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - legacy::TYPE_VIEW_MOD_PC_SIZE, - legacy::TYPE_VIEW_MOD_PC_SIZE, + Titanium::invtype::InvTypeViewMODPCSize, + SoF::invtype::InvTypeViewMODPCSize, + SoD::invtype::InvTypeViewMODPCSize, + UF::invtype::InvTypeViewMODPCSize, + RoF::invtype::InvTypeViewMODPCSize, + RoF2::invtype::InvTypeViewMODPCSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, EntityLimits::pet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null + Titanium::invtype::InvTypeViewMODPCSize, + SoF::invtype::InvTypeViewMODPCSize, + SoD::invtype::InvTypeViewMODPCSize, + UF::invtype::InvTypeViewMODPCSize, + RoF::invtype::InvTypeViewMODPCSize, + RoF2::invtype::InvTypeViewMODPCSize }, { // local[TypeViewMODBank] ClientUnknown::Null, Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - legacy::TYPE_VIEW_MOD_BANK_SIZE, - legacy::TYPE_VIEW_MOD_BANK_SIZE, + Titanium::invtype::InvTypeViewMODBankSize, + SoF::invtype::InvTypeViewMODBankSize, + SoD::invtype::InvTypeViewMODBankSize, + UF::invtype::InvTypeViewMODBankSize, + RoF::invtype::InvTypeViewMODBankSize, + RoF2::invtype::InvTypeViewMODBankSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, EntityLimits::pet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null + Titanium::invtype::InvTypeViewMODBankSize, + SoF::invtype::InvTypeViewMODBankSize, + SoD::invtype::InvTypeViewMODBankSize, + UF::invtype::InvTypeViewMODBankSize, + RoF::invtype::InvTypeViewMODBankSize, + RoF2::invtype::InvTypeViewMODBankSize }, { // local[TypeViewMODSharedBank] ClientUnknown::Null, Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - legacy::TYPE_VIEW_MOD_SHARED_BANK_SIZE, - legacy::TYPE_VIEW_MOD_SHARED_BANK_SIZE, + Titanium::invtype::InvTypeViewMODSharedBankSize, + SoF::invtype::InvTypeViewMODSharedBankSize, + SoD::invtype::InvTypeViewMODSharedBankSize, + UF::invtype::InvTypeViewMODSharedBankSize, + RoF::invtype::InvTypeViewMODSharedBankSize, + RoF2::invtype::InvTypeViewMODSharedBankSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, EntityLimits::pet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null + Titanium::invtype::InvTypeViewMODSharedBankSize, + SoF::invtype::InvTypeViewMODSharedBankSize, + SoD::invtype::InvTypeViewMODSharedBankSize, + UF::invtype::InvTypeViewMODSharedBankSize, + RoF::invtype::InvTypeViewMODSharedBankSize, + RoF2::invtype::InvTypeViewMODSharedBankSize }, { // local[TypeViewMODLimbo] ClientUnknown::Null, Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - legacy::TYPE_VIEW_MOD_LIMBO_SIZE, - legacy::TYPE_VIEW_MOD_LIMBO_SIZE, + Titanium::invtype::InvTypeViewMODLimboSize, + SoF::invtype::InvTypeViewMODLimboSize, + SoD::invtype::InvTypeViewMODLimboSize, + UF::invtype::InvTypeViewMODLimboSize, + RoF::invtype::InvTypeViewMODLimboSize, + RoF2::invtype::InvTypeViewMODLimboSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, EntityLimits::pet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null + Titanium::invtype::InvTypeViewMODLimboSize, + SoF::invtype::InvTypeViewMODLimboSize, + SoD::invtype::InvTypeViewMODLimboSize, + UF::invtype::InvTypeViewMODLimboSize, + RoF::invtype::InvTypeViewMODLimboSize, + RoF2::invtype::InvTypeViewMODLimboSize }, { // local[TypeAltStorage] ClientUnknown::Null, Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - legacy::TYPE_ALT_STORAGE_SIZE, - legacy::TYPE_ALT_STORAGE_SIZE, + Titanium::invtype::InvTypeAltStorageSize, + SoF::invtype::InvTypeAltStorageSize, + SoD::invtype::InvTypeAltStorageSize, + UF::invtype::InvTypeAltStorageSize, + RoF::invtype::InvTypeAltStorageSize, + RoF2::invtype::InvTypeAltStorageSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -443,12 +443,12 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ { // local[TypeArchived] ClientUnknown::Null, Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - legacy::TYPE_ARCHIVED_SIZE, - legacy::TYPE_ARCHIVED_SIZE, + Titanium::invtype::InvTypeArchivedSize, + SoF::invtype::InvTypeArchivedSize, + SoD::invtype::InvTypeArchivedSize, + UF::invtype::InvTypeArchivedSize, + RoF::invtype::InvTypeArchivedSize, + RoF2::invtype::InvTypeArchivedSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -467,8 +467,8 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ SoF::Null, SoD::Null, UF::Null, - legacy::TYPE_MAIL_SIZE, - legacy::TYPE_MAIL_SIZE, + RoF::invtype::InvTypeMailSize, + RoF2::invtype::InvTypeMailSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -487,8 +487,8 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ SoF::Null, SoD::Null, UF::Null, - legacy::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, - legacy::TYPE_GUILD_TROPHY_TRIBUTE_SIZE, + RoF::invtype::InvTypeGuildTrophyTributeSize, + RoF2::invtype::InvTypeGuildTrophyTributeSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -507,8 +507,8 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ SoF::Null, SoD::Null, UF::Null, - legacy::TYPE_KRONO_SIZE, - legacy::TYPE_KRONO_SIZE, + RoF::Null, + RoF2::invtype::InvTypeKronoSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -523,12 +523,12 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ { // local[TypeOther] ClientUnknown::Null, Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - legacy::TYPE_OTHER_SIZE, - legacy::TYPE_OTHER_SIZE, + Titanium::invtype::InvTypeOtherSize, + SoF::invtype::InvTypeOtherSize, + SoD::invtype::InvTypeOtherSize, + UF::invtype::InvTypeOtherSize, + RoF::invtype::InvTypeOtherSize, + RoF2::invtype::InvTypeOtherSize, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -542,23 +542,23 @@ uint16 EQEmu::inventory::InventoryTypeSize(versions::InventoryVersion inventory_ } }; - if ((uint16)inv_type < legacy::TypeCount) - return local[inv_type][static_cast(versions::ValidateInventoryVersion(inventory_version))]; + if (inv_type < 0 || inv_type >= legacy::TypeCount) + return 0; - return NOT_USED; + return local[inv_type][static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -uint64 EQEmu::inventory::PossessionsBitmask(versions::InventoryVersion inventory_version) +uint64 EQEmu::inventory::GetPossessionsBitmask(versions::InventoryVersion inventory_version) { static const uint64 local[versions::InventoryVersionCount] = { ClientUnknown::Null, Client62::Null, - 0x000000027FDFFFFF, - 0x000000027FFFFFFF, - 0x000000027FFFFFFF, - 0x000000027FFFFFFF, - 0x00000003FFFFFFFF, - 0x00000003FFFFFFFF, + Titanium::Null, //0x000000027FDFFFFF, + SoF::Null, //0x000000027FFFFFFF, + SoD::Null, //0x000000027FFFFFFF, + UF::Null, //0x000000027FFFFFFF, + RoF::Null, //0x00000003FFFFFFFF, + RoF2::Null, //0x00000003FFFFFFFF, EntityLimits::npc::Null, EntityLimits::merc::Null, EntityLimits::bot::Null, @@ -571,48 +571,20 @@ uint64 EQEmu::inventory::PossessionsBitmask(versions::InventoryVersion inventory RoF2::Null }; - return NOT_USED; - //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; + return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -bool EQEmu::inventory::AllowEmptyBagInBag(versions::InventoryVersion inventory_version) +bool EQEmu::inventory::GetAllowEmptyBagInBag(versions::InventoryVersion inventory_version) { static const bool local[versions::InventoryVersionCount] = { ClientUnknown::False, Client62::False, - Titanium::behavior::AllowEmptyBagInBag, - SoF::behavior::AllowEmptyBagInBag, - SoD::behavior::AllowEmptyBagInBag, - UF::behavior::AllowEmptyBagInBag, - RoF::behavior::AllowEmptyBagInBag, - RoF2::behavior::AllowEmptyBagInBag, - EntityLimits::npc::False, - EntityLimits::merc::False, - EntityLimits::bot::False, - EntityLimits::pet::False, - Titanium::False, - SoF::False, - SoD::False, - UF::False, - RoF::False, - RoF2::False - }; - - return false; - //return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; -} - -bool EQEmu::inventory::AllowClickCastFromBag(versions::InventoryVersion inventory_version) -{ - static const bool local[versions::InventoryVersionCount] = { - ClientUnknown::False, - Client62::False, - Titanium::behavior::AllowClickCastFromBag, - SoF::behavior::AllowClickCastFromBag, - SoD::behavior::AllowClickCastFromBag, - UF::behavior::AllowClickCastFromBag, - RoF::behavior::AllowClickCastFromBag, - RoF2::behavior::AllowClickCastFromBag, + Titanium::inventory::AllowEmptyBagInBag, + SoF::inventory::AllowEmptyBagInBag, + SoD::inventory::AllowEmptyBagInBag, + UF::inventory::AllowEmptyBagInBag, + RoF::False, //RoF::inventory::AllowEmptyBagInBag, + RoF2::False, //RoF2::inventory::AllowEmptyBagInBag, EntityLimits::npc::False, EntityLimits::merc::False, EntityLimits::bot::False, @@ -628,21 +600,99 @@ bool EQEmu::inventory::AllowClickCastFromBag(versions::InventoryVersion inventor return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -uint16 EQEmu::inventory::ItemAugSize(versions::InventoryVersion inventory_version) +bool EQEmu::inventory::GetAllowClickCastFromBag(versions::InventoryVersion inventory_version) { - static const uint16 local[versions::InventoryVersionCount] = { + static const bool local[versions::InventoryVersionCount] = { + ClientUnknown::False, + Client62::False, + Titanium::inventory::AllowClickCastFromBag, + SoF::inventory::AllowClickCastFromBag, + SoD::inventory::AllowClickCastFromBag, + UF::inventory::AllowClickCastFromBag, + RoF::inventory::AllowClickCastFromBag, + RoF2::inventory::AllowClickCastFromBag, + EntityLimits::npc::False, + EntityLimits::merc::False, + EntityLimits::bot::False, + EntityLimits::pet::False, + Titanium::False, + SoF::False, + SoD::False, + UF::False, + RoF::False, + RoF2::False + }; + + return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; +} + +bool EQEmu::inventory::GetConcatenateInvTypeLimbo(versions::InventoryVersion inventory_version) +{ + static const bool local[versions::InventoryVersionCount] = { + ClientUnknown::False, + Client62::False, + Titanium::inventory::ConcatenateInvTypeLimbo, + SoF::inventory::ConcatenateInvTypeLimbo, + SoD::inventory::ConcatenateInvTypeLimbo, + UF::inventory::ConcatenateInvTypeLimbo, + RoF::inventory::ConcatenateInvTypeLimbo, + RoF2::inventory::ConcatenateInvTypeLimbo, + EntityLimits::npc::False, + EntityLimits::merc::False, + EntityLimits::bot::False, + EntityLimits::pet::False, + Titanium::False, + SoF::False, + SoD::False, + UF::False, + RoF::False, + RoF2::False + }; + + return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; +} + +bool EQEmu::inventory::GetAllowOverLevelEquipment(versions::InventoryVersion inventory_version) +{ + static const bool local[versions::InventoryVersionCount] = { + ClientUnknown::False, + Client62::False, + Titanium::inventory::AllowOverLevelEquipment, + SoF::inventory::AllowOverLevelEquipment, + SoD::inventory::AllowOverLevelEquipment, + UF::inventory::AllowOverLevelEquipment, + RoF::inventory::AllowOverLevelEquipment, + RoF2::inventory::AllowOverLevelEquipment, + EntityLimits::npc::False, + EntityLimits::merc::False, + EntityLimits::bot::False, + EntityLimits::pet::False, + Titanium::False, + SoF::False, + SoD::False, + UF::False, + RoF::False, + RoF2::False + }; + + return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; +} + +size_t EQEmu::inventory::GetItemAugSize(versions::InventoryVersion inventory_version) +{ + static const size_t local[versions::InventoryVersionCount] = { ClientUnknown::Null, Client62::Null, - legacy::ITEM_COMMON_SIZE, - legacy::ITEM_COMMON_SIZE, - legacy::ITEM_COMMON_SIZE, - legacy::ITEM_COMMON_SIZE, - legacy::ITEM_COMMON_SIZE, - legacy::ITEM_COMMON_SIZE, - legacy::ITEM_COMMON_SIZE, - legacy::ITEM_COMMON_SIZE, - legacy::ITEM_COMMON_SIZE, - legacy::ITEM_COMMON_SIZE, + legacy::ITEM_COMMON_SIZE, //Titanium::invaug::ItemAugSize, + legacy::ITEM_COMMON_SIZE, //SoF::invaug::ItemAugSize, + legacy::ITEM_COMMON_SIZE, //SoD::invaug::ItemAugSize, + legacy::ITEM_COMMON_SIZE, //UF::invaug::ItemAugSize, + legacy::ITEM_COMMON_SIZE, //RoF::invaug::ItemAugSize, + legacy::ITEM_COMMON_SIZE, //RoF2::invaug::ItemAugSize, + legacy::ITEM_COMMON_SIZE, //ItemAugSize, + legacy::ITEM_COMMON_SIZE, //ItemAugSize, + legacy::ITEM_COMMON_SIZE, //ItemAugSize, + legacy::ITEM_COMMON_SIZE, //ItemAugSize, Titanium::Null, SoF::Null, SoD::Null, @@ -654,33 +704,33 @@ uint16 EQEmu::inventory::ItemAugSize(versions::InventoryVersion inventory_versio return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -uint16 EQEmu::inventory::ItemBagSize(versions::InventoryVersion inventory_version) +size_t EQEmu::inventory::GetItemBagSize(versions::InventoryVersion inventory_version) { - static const uint16 local[versions::InventoryVersionCount] = { + static const size_t local[versions::InventoryVersionCount] = { ClientUnknown::Null, Client62::Null, - legacy::ITEM_CONTAINER_SIZE, - legacy::ITEM_CONTAINER_SIZE, - legacy::ITEM_CONTAINER_SIZE, - legacy::ITEM_CONTAINER_SIZE, - legacy::ITEM_CONTAINER_SIZE, - legacy::ITEM_CONTAINER_SIZE, - legacy::ITEM_CONTAINER_SIZE, - legacy::ITEM_CONTAINER_SIZE, - legacy::ITEM_CONTAINER_SIZE, - legacy::ITEM_CONTAINER_SIZE, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null + legacy::ITEM_CONTAINER_SIZE, //Titanium::invbag::ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //SoF::invbag::ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //SoD::invbag::ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //UF::invbag::ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //RoF::invbag::ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //RoF2::invbag::ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //Titanium::Null, + legacy::ITEM_CONTAINER_SIZE, //SoF::Null, + legacy::ITEM_CONTAINER_SIZE, //SoD::Null, + legacy::ITEM_CONTAINER_SIZE, //UF::Null, + legacy::ITEM_CONTAINER_SIZE, //RoF::Null, + legacy::ITEM_CONTAINER_SIZE, //RoF2::Null }; return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -bool EQEmu::profile::CoinHasWeight(versions::InventoryVersion inventory_version) +bool EQEmu::behavior::GetCoinHasWeight(versions::InventoryVersion inventory_version) { static const bool local[versions::InventoryVersionCount] = { ClientUnknown::True, @@ -691,10 +741,10 @@ bool EQEmu::profile::CoinHasWeight(versions::InventoryVersion inventory_version) UF::behavior::CoinHasWeight, RoF::behavior::CoinHasWeight, RoF::behavior::CoinHasWeight, - EntityLimits::npc::True, - EntityLimits::merc::True, - EntityLimits::bot::True, - EntityLimits::pet::True, + EntityLimits::npc::True, //CoinHasWeight, + EntityLimits::merc::True, //CoinHasWeight, + EntityLimits::bot::True, //CoinHasWeight, + EntityLimits::pet::True, //CoinHasWeight, Titanium::False, SoF::False, SoD::False, diff --git a/common/eq_limits.h b/common/eq_limits.h index a1168d348..d843474ec 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -34,30 +34,30 @@ namespace EQEmu { namespace constants { - extern size_t CharacterCreationLimit(versions::ClientVersion client_version); + extern size_t GetCharacterCreationLimit(versions::ClientVersion client_version); } /*constants*/ namespace inventory { - extern uint16 InventoryTypeSize(versions::InventoryVersion inventory_version, int16 inv_type); - extern uint64 PossessionsBitmask(versions::InventoryVersion inventory_version); + extern size_t GetInventoryTypeSize(versions::InventoryVersion inventory_version, int inv_type); + extern uint64 GetPossessionsBitmask(versions::InventoryVersion inventory_version); - extern bool AllowEmptyBagInBag(versions::InventoryVersion inventory_version); - extern bool AllowClickCastFromBag(versions::InventoryVersion inventory_version); + extern bool GetAllowEmptyBagInBag(versions::InventoryVersion inventory_version); + extern bool GetAllowClickCastFromBag(versions::InventoryVersion inventory_version); - extern uint16 ItemAugSize(versions::InventoryVersion inventory_version); - extern uint16 ItemBagSize(versions::InventoryVersion inventory_version); + extern bool GetConcatenateInvTypeLimbo(versions::InventoryVersion inventory_version); - extern bool ConcatenateInvTypeLimbo(versions::InventoryVersion inventory_version); + extern bool GetAllowOverLevelEquipment(versions::InventoryVersion inventory_version); - extern bool AllowOverLevelEquipment(versions::InventoryVersion inventory_version); + extern size_t GetItemAugSize(versions::InventoryVersion inventory_version); + extern size_t GetItemBagSize(versions::InventoryVersion inventory_version); } /*inventory*/ - namespace profile { - extern bool CoinHasWeight(versions::InventoryVersion inventory_version); + namespace behavior { + extern bool GetCoinHasWeight(versions::InventoryVersion inventory_version); - } /*profile*/ + } /*behavior*/ } /*EQEmu*/ diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index c4fce9d8c..e94264b34 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1542,7 +1542,7 @@ enum ItemPacketType // ItemPacketTributeItem = /*108*/ 0x6C, // ItemPacketGuildTribute = /*109*/ 0x6D, // missing from EQEmu // ItemPacket10 = /*110*/ 0x6E, -// ItemPacket11 = /*111*/ 0x6F, // UF+ (equipment slots only) (RoF+ checks '(WORD*)slot + 4 != -1' [(WORD*)]slot + 2 would be bag index - if used) (guess) +// ItemPacket11 = /*111*/ 0x6F, // UF+ (equipment slots only) (RoF+ checks '(WORD*)slot + 4 != -1' [(WORD*)]slot + 2 would be bag index - if used) (guess) (appearance (over-level) items?) // ItemPacket12 = /*112*/ 0x70, // RoF+ (causes stat update) (could be TrophyTribute and GuildTrophyTribute together - two case methodology - is it checking for GuildID?) // ItemPacketMerchantRecovery = /*113*/ 0x71, // ItemPacket14 = /*115*/ 0x73, (real estate/moving crate?) diff --git a/common/item.cpp b/common/item.cpp index 6e40ac6bc..7437c9339 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -929,7 +929,7 @@ bool Inventory::SupportsClickCasting(int16 slot_id) } else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { - if (EQEmu::inventory::AllowClickCastFromBag(m_inventory_version)) + if (EQEmu::inventory::GetAllowClickCastFromBag(m_inventory_version)) return true; } diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 2c185e1d1..edad92dfb 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -5641,11 +5641,11 @@ namespace RoF { structs::InventorySlot_Struct RoFSlot; RoFSlot.Type = INVALID_INDEX; - RoFSlot.Unknown02 = NOT_USED; + RoFSlot.Unknown02 = 0; RoFSlot.Slot = INVALID_INDEX; RoFSlot.SubIndex = INVALID_INDEX; RoFSlot.AugIndex = INVALID_INDEX; - RoFSlot.Unknown01 = NOT_USED; + RoFSlot.Unknown01 = 0; uint32 TempSlot = 0; @@ -5746,7 +5746,7 @@ namespace RoF RoFSlot.Slot = INVALID_INDEX; RoFSlot.SubIndex = INVALID_INDEX; RoFSlot.AugIndex = INVALID_INDEX; - RoFSlot.Unknown01 = NOT_USED; + RoFSlot.Unknown01 = 0; uint32 TempSlot = 0; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index c44caba92..75329b8bb 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -5926,11 +5926,11 @@ namespace RoF2 { structs::InventorySlot_Struct RoF2Slot; RoF2Slot.Type = INVALID_INDEX; - RoF2Slot.Unknown02 = NOT_USED; + RoF2Slot.Unknown02 = 0; RoF2Slot.Slot = INVALID_INDEX; RoF2Slot.SubIndex = INVALID_INDEX; RoF2Slot.AugIndex = INVALID_INDEX; - RoF2Slot.Unknown01 = NOT_USED; + RoF2Slot.Unknown01 = 0; uint32 TempSlot = 0; @@ -6039,7 +6039,7 @@ namespace RoF2 RoF2Slot.Slot = INVALID_INDEX; RoF2Slot.SubIndex = INVALID_INDEX; RoF2Slot.AugIndex = INVALID_INDEX; - RoF2Slot.Unknown01 = NOT_USED; + RoF2Slot.Unknown01 = 0; uint32 TempSlot = 0; diff --git a/common/patches/rof2_limits.cpp b/common/patches/rof2_limits.cpp index 05ece56ca..c515e2512 100644 --- a/common/patches/rof2_limits.cpp +++ b/common/patches/rof2_limits.cpp @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -22,7 +22,7 @@ #include "../string_util.h" -size_t RoF2::invtype::InvTypeSize(int inv_type) +size_t RoF2::invtype::GetInvTypeSize(int inv_type) { switch (inv_type) { case invtype::InvTypePossessions: @@ -80,7 +80,7 @@ size_t RoF2::invtype::InvTypeSize(int inv_type) } } -const char* RoF2::invtype::InvTypeName(int inv_type) +const char* RoF2::invtype::GetInvTypeName(int inv_type) { switch (inv_type) { case invtype::InvTypeInvalid: @@ -140,7 +140,7 @@ const char* RoF2::invtype::InvTypeName(int inv_type) } } -const char* RoF2::invslot::InvPossessionsSlotName(int inv_slot) +const char* RoF2::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { case invslot::InvSlotInvalid: @@ -218,12 +218,12 @@ const char* RoF2::invslot::InvPossessionsSlotName(int inv_slot) } } -const char* RoF2::invslot::InvSlotName(int inv_type, int inv_slot) +const char* RoF2::invslot::GetInvSlotName(int inv_type, int inv_slot) { if (inv_type == invtype::InvTypePossessions) - return invslot::InvPossessionsSlotName(inv_slot); + return invslot::GetInvPossessionsSlotName(inv_slot); - size_t type_size = invtype::InvTypeSize(inv_type); + size_t type_size = invtype::GetInvTypeSize(inv_type); if (!type_size || inv_slot == invslot::InvSlotInvalid) return "Invalid Slot"; @@ -237,7 +237,7 @@ const char* RoF2::invslot::InvSlotName(int inv_type, int inv_slot) return ret_str.c_str(); } -const char* RoF2::invbag::InvBagIndexName(int bag_index) +const char* RoF2::invbag::GetInvBagIndexName(int bag_index) { if (bag_index == invbag::InvBagInvalid) return "Invalid Bag"; @@ -251,7 +251,7 @@ const char* RoF2::invbag::InvBagIndexName(int bag_index) return ret_str.c_str(); } -const char* RoF2::invaug::InvAugIndexName(int aug_index) +const char* RoF2::invaug::GetInvAugIndexName(int aug_index) { if (aug_index == invaug::InvAugInvalid) return "Invalid Augment"; diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index 79218f67f..2320c1393 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -32,8 +32,13 @@ namespace RoF2 enum : bool { False = false, True = true }; // pre-declarations + namespace inventory { + inline EQEmu::versions::ClientVersion GetInventoryRef() { return EQEmu::versions::ClientVersion::RoF2; } + + } /*inventory*/ + namespace invtype { - inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::RoF2; } + inline EQEmu::versions::ClientVersion GetInvTypeRef() { return EQEmu::versions::ClientVersion::RoF2; } enum : int { InvTypeInvalid = -1, InvTypeBegin }; @@ -69,7 +74,7 @@ namespace RoF2 } /*invtype*/ namespace invslot { - inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::RoF2; } + inline EQEmu::versions::ClientVersion GetInvSlotRef() { return EQEmu::versions::ClientVersion::RoF2; } enum : int { InvSlotInvalid = -1, InvSlotBegin }; @@ -122,21 +127,21 @@ namespace RoF2 } /*invslot*/ namespace invbag { - inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::RoF2; } + inline EQEmu::versions::ClientVersion GetInvBagRef() { return EQEmu::versions::ClientVersion::RoF2; } enum : int { InvBagInvalid = -1, InvBagBegin }; } /*invbag*/ namespace invaug { - inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::RoF2; } + inline EQEmu::versions::ClientVersion GetInvAugRef() { return EQEmu::versions::ClientVersion::RoF2; } enum : int { InvAugInvalid = -1, InvAugBegin }; } /*invaug*/ namespace item { - inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::RoF2; } + inline EQEmu::versions::ClientVersion GetItemRef() { return EQEmu::versions::ClientVersion::RoF2; } //enum Unknown : int { // looks like item class..but, RoF has it too - nothing in UF- // Unknown1 = 0, @@ -165,27 +170,37 @@ namespace RoF2 } /*item*/ namespace profile { - inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::RoF2; } + inline EQEmu::versions::ClientVersion GetProfileRef() { return EQEmu::versions::ClientVersion::RoF2; } } /*profile*/ namespace constants { - inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::RoF2; } + inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::RoF2; } } /*constants*/ namespace behavior { - inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::RoF2; } + inline EQEmu::versions::ClientVersion GetBehaviorRef() { return EQEmu::versions::ClientVersion::RoF2; } } /*behavior*/ namespace skills { - inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::RoF2; } + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::RoF2; } } /*skills*/ // declarations + namespace inventory { + const bool ConcatenateInvTypeLimbo = false; + + const bool AllowOverLevelEquipment = true; + + const bool AllowEmptyBagInBag = true; + const bool AllowClickCastFromBag = true; + + } /*inventory*/ + namespace invtype { const size_t InvTypePossessionsSize = invslot::PossessionsCount; const size_t InvTypeBankSize = 24; @@ -215,28 +230,28 @@ namespace RoF2 const size_t NPCTradeSize = 4; - extern size_t InvTypeSize(int inv_type); - extern const char* InvTypeName(int inv_type); + extern size_t GetInvTypeSize(int inv_type); + extern const char* GetInvTypeName(int inv_type); } /*invtype*/ namespace invslot { - extern const char* InvPossessionsSlotName(int inv_slot); - extern const char* InvSlotName(int inv_type, int inv_slot); + extern const char* GetInvPossessionsSlotName(int inv_slot); + extern const char* GetInvSlotName(int inv_type, int inv_slot); } /*invslot*/ namespace invbag { const size_t ItemBagSize = 255; // server Size will be 255..unsure what actual client is (test) - extern const char* InvBagIndexName(int bag_index); + extern const char* GetInvBagIndexName(int bag_index); } /*invbag*/ namespace invaug { const size_t ItemAugSize = 6; - extern const char* InvAugIndexName(int aug_index); + extern const char* GetInvAugIndexName(int aug_index); } /*invaug*/ @@ -264,13 +279,6 @@ namespace RoF2 } /*constants*/ namespace behavior { - const bool ConcatenateInvTypeLimbo = false; - - const bool AllowOverLevelEquipment = true; - - const bool AllowEmptyBagInBag = true; - const bool AllowClickCastFromBag = true; - const bool CoinHasWeight = false; } /*behavior*/ diff --git a/common/patches/rof_limits.cpp b/common/patches/rof_limits.cpp index 94ed6039f..48639d52c 100644 --- a/common/patches/rof_limits.cpp +++ b/common/patches/rof_limits.cpp @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -22,7 +22,7 @@ #include "../string_util.h" -size_t RoF::invtype::InvTypeSize(int inv_type) +size_t RoF::invtype::GetInvTypeSize(int inv_type) { switch (inv_type) { case invtype::InvTypePossessions: @@ -78,7 +78,7 @@ size_t RoF::invtype::InvTypeSize(int inv_type) } } -const char* RoF::invtype::InvTypeName(int inv_type) +const char* RoF::invtype::GetInvTypeName(int inv_type) { switch (inv_type) { case invtype::InvTypeInvalid: @@ -136,7 +136,7 @@ const char* RoF::invtype::InvTypeName(int inv_type) } } -const char* RoF::invslot::InvPossessionsSlotName(int inv_slot) +const char* RoF::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { case invslot::InvSlotInvalid: @@ -214,12 +214,12 @@ const char* RoF::invslot::InvPossessionsSlotName(int inv_slot) } } -const char* RoF::invslot::InvSlotName(int inv_type, int inv_slot) +const char* RoF::invslot::GetInvSlotName(int inv_type, int inv_slot) { if (inv_type == invtype::InvTypePossessions) - return invslot::InvPossessionsSlotName(inv_slot); + return invslot::GetInvPossessionsSlotName(inv_slot); - size_t type_size = invtype::InvTypeSize(inv_type); + size_t type_size = invtype::GetInvTypeSize(inv_type); if (!type_size || inv_slot == invslot::InvSlotInvalid) return "Invalid Slot"; @@ -233,7 +233,7 @@ const char* RoF::invslot::InvSlotName(int inv_type, int inv_slot) return ret_str.c_str(); } -const char* RoF::invbag::InvBagIndexName(int bag_index) +const char* RoF::invbag::GetInvBagIndexName(int bag_index) { if (bag_index == invbag::InvBagInvalid) return "Invalid Bag"; @@ -247,7 +247,7 @@ const char* RoF::invbag::InvBagIndexName(int bag_index) return ret_str.c_str(); } -const char* RoF::invaug::InvAugIndexName(int aug_index) +const char* RoF::invaug::GetInvAugIndexName(int aug_index) { if (aug_index == invaug::InvAugInvalid) return "Invalid Augment"; diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index 5275bfaad..94e55a47a 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -32,8 +32,13 @@ namespace RoF enum : bool { False = false, True = true }; // pre-declarations + namespace inventory { + inline EQEmu::versions::ClientVersion GetInventoryRef() { return EQEmu::versions::ClientVersion::RoF; } + + } /*inventory*/ + namespace invtype { - inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::RoF; } + inline EQEmu::versions::ClientVersion GetInvTypeRef() { return EQEmu::versions::ClientVersion::RoF; } enum : int { InvTypeInvalid = -1, InvTypeBegin }; @@ -68,7 +73,7 @@ namespace RoF } /*invtype*/ namespace invslot { - inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::RoF; } + inline EQEmu::versions::ClientVersion GetInvSlotRef() { return EQEmu::versions::ClientVersion::RoF; } enum : int { InvSlotInvalid = -1, InvSlotBegin }; @@ -121,21 +126,21 @@ namespace RoF } /*invslot*/ namespace invbag { - inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::RoF; } + inline EQEmu::versions::ClientVersion GetInvBagRef() { return EQEmu::versions::ClientVersion::RoF; } enum : int { InvBagInvalid = -1, InvBagBegin }; } /*invbag*/ namespace invaug { - inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::RoF; } + inline EQEmu::versions::ClientVersion GetInvAugRef() { return EQEmu::versions::ClientVersion::RoF; } enum : int { InvAugInvalid = -1, InvAugBegin }; } /*invaug*/ namespace item { - inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::RoF; } + inline EQEmu::versions::ClientVersion GetItemRef() { return EQEmu::versions::ClientVersion::RoF; } enum ItemPacketType : int { ItemPacketMerchant = 100, @@ -157,27 +162,37 @@ namespace RoF } /*item*/ namespace profile { - inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::RoF; } + inline EQEmu::versions::ClientVersion GetProfileRef() { return EQEmu::versions::ClientVersion::RoF; } } /*profile*/ namespace constants { - inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::RoF; } + inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::RoF; } } /*constants*/ namespace behavior { - inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::RoF; } + inline EQEmu::versions::ClientVersion GetBehaviorRef() { return EQEmu::versions::ClientVersion::RoF; } } /*behavior*/ namespace skills { - inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::RoF; } + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::RoF; } } /*skills*/ // declarations + namespace inventory { + const bool ConcatenateInvTypeLimbo = false; + + const bool AllowOverLevelEquipment = true; + + const bool AllowEmptyBagInBag = true; + const bool AllowClickCastFromBag = true; + + } /*inventory*/ + namespace invtype { const size_t InvTypePossessionsSize = invslot::PossessionsCount; const size_t InvTypeBankSize = 24; @@ -206,28 +221,28 @@ namespace RoF const size_t NPCTradeSize = 4; - extern size_t InvTypeSize(int inv_type); - extern const char* InvTypeName(int inv_type); + extern size_t GetInvTypeSize(int inv_type); + extern const char* GetInvTypeName(int inv_type); } /*invtype*/ namespace invslot { - extern const char* InvPossessionsSlotName(int inv_slot); - extern const char* InvSlotName(int inv_type, int inv_slot); + extern const char* GetInvPossessionsSlotName(int inv_slot); + extern const char* GetInvSlotName(int inv_type, int inv_slot); } /*invslot*/ namespace invbag { const size_t ItemBagSize = 255; // server Size will be 255..unsure what actual client is (test) - extern const char* InvBagIndexName(int bag_index); + extern const char* GetInvBagIndexName(int bag_index); } /*invbag*/ namespace invaug { const size_t ItemAugSize = 6; - extern const char* InvAugIndexName(int aug_index); + extern const char* GetInvAugIndexName(int aug_index); } /*invaug*/ @@ -255,13 +270,6 @@ namespace RoF } /*constants*/ namespace behavior { - const bool ConcatenateInvTypeLimbo = false; - - const bool AllowOverLevelEquipment = true; - - const bool AllowEmptyBagInBag = true; - const bool AllowClickCastFromBag = true; - const bool CoinHasWeight = false; } /*behavior*/ diff --git a/common/patches/sod_limits.cpp b/common/patches/sod_limits.cpp index de1abba02..7991801e3 100644 --- a/common/patches/sod_limits.cpp +++ b/common/patches/sod_limits.cpp @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -22,7 +22,7 @@ #include "../string_util.h" -size_t SoD::invtype::InvTypeSize(int inv_type) +size_t SoD::invtype::GetInvTypeSize(int inv_type) { switch (inv_type) { case invtype::InvTypePossessions: @@ -68,7 +68,7 @@ size_t SoD::invtype::InvTypeSize(int inv_type) } } -const char* SoD::invtype::InvTypeName(int inv_type) +const char* SoD::invtype::GetInvTypeName(int inv_type) { switch (inv_type) { case invtype::InvTypeInvalid: @@ -116,7 +116,7 @@ const char* SoD::invtype::InvTypeName(int inv_type) } } -const char* SoD::invslot::InvPossessionsSlotName(int inv_slot) +const char* SoD::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { case invslot::InvSlotInvalid: @@ -190,9 +190,9 @@ const char* SoD::invslot::InvPossessionsSlotName(int inv_slot) } } -const char* SoD::invslot::InvCorpseSlotName(int inv_slot) +const char* SoD::invslot::GetInvCorpseSlotName(int inv_slot) { - if (!invtype::InvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) + if (!invtype::GetInvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) return "Invalid Slot"; // needs work @@ -205,14 +205,14 @@ const char* SoD::invslot::InvCorpseSlotName(int inv_slot) return ret_str.c_str(); } -const char* SoD::invslot::InvSlotName(int inv_type, int inv_slot) +const char* SoD::invslot::GetInvSlotName(int inv_type, int inv_slot) { if (inv_type == invtype::InvTypePossessions) - return invslot::InvPossessionsSlotName(inv_slot); + return invslot::GetInvPossessionsSlotName(inv_slot); else if (inv_type == invtype::InvTypeCorpse) - return invslot::InvCorpseSlotName(inv_slot); + return invslot::GetInvCorpseSlotName(inv_slot); - size_t type_size = invtype::InvTypeSize(inv_type); + size_t type_size = invtype::GetInvTypeSize(inv_type); if (!type_size || inv_slot == invslot::InvSlotInvalid) return "Invalid Slot"; @@ -226,7 +226,7 @@ const char* SoD::invslot::InvSlotName(int inv_type, int inv_slot) return ret_str.c_str(); } -const char* SoD::invbag::InvBagIndexName(int bag_index) +const char* SoD::invbag::GetInvBagIndexName(int bag_index) { if (bag_index == invbag::InvBagInvalid) return "Invalid Bag"; @@ -240,7 +240,7 @@ const char* SoD::invbag::InvBagIndexName(int bag_index) return ret_str.c_str(); } -const char* SoD::invaug::InvAugIndexName(int aug_index) +const char* SoD::invaug::GetInvAugIndexName(int aug_index) { if (aug_index == invaug::InvAugInvalid) return "Invalid Augment"; diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index e50790793..48d56cfab 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -32,8 +32,13 @@ namespace SoD enum : bool { False = false, True = true }; // pre-declarations + namespace inventory { + inline EQEmu::versions::ClientVersion GetInventoryRef() { return EQEmu::versions::ClientVersion::SoD; } + + } /*inventory*/ + namespace invtype { - inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::SoD; } + inline EQEmu::versions::ClientVersion GetInvTypeRef() { return EQEmu::versions::ClientVersion::SoD; } enum : int { InvTypeInvalid = -1, InvTypeBegin }; @@ -63,7 +68,7 @@ namespace SoD } /*invtype*/ namespace invslot { - inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::SoD; } + inline EQEmu::versions::ClientVersion GetInvSlotRef() { return EQEmu::versions::ClientVersion::SoD; } enum : int { InvSlotInvalid = -1, InvSlotBegin }; @@ -114,21 +119,21 @@ namespace SoD } /*invslot*/ namespace invbag { - inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::SoD; } + inline EQEmu::versions::ClientVersion GetInvBagRef() { return EQEmu::versions::ClientVersion::SoD; } enum : int { InvBagInvalid = -1, InvBagBegin }; } /*invbag*/ namespace invaug { - inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::SoD; } + inline EQEmu::versions::ClientVersion GetInvAugRef() { return EQEmu::versions::ClientVersion::SoD; } enum : int { InvAugInvalid = -1, InvAugBegin }; } /*invaug*/ namespace item { - inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::SoD; } + inline EQEmu::versions::ClientVersion GetItemRef() { return EQEmu::versions::ClientVersion::SoD; } enum ItemPacketType : int { ItemPacketMerchant = 100, @@ -146,27 +151,37 @@ namespace SoD } /*item*/ namespace profile { - inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::SoD; } + inline EQEmu::versions::ClientVersion GetProfileRef() { return EQEmu::versions::ClientVersion::SoD; } } /*profile*/ namespace constants { - inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::SoD; } + inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::SoD; } } /*constants*/ namespace behavior { - inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::SoD; } + inline EQEmu::versions::ClientVersion GetBehaviorRef() { return EQEmu::versions::ClientVersion::SoD; } } /*behavior*/ namespace skills { - inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::SoD; } + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::SoD; } } /*skills*/ // declarations + namespace inventory { + const bool ConcatenateInvTypeLimbo = true; + + const bool AllowOverLevelEquipment = false; + + const bool AllowEmptyBagInBag = false; + const bool AllowClickCastFromBag = false; + + } /*inventory*/ + namespace invtype { const size_t InvTypePossessionsSize = invslot::PossessionsCount; const size_t InvTypeBankSize = 24; @@ -190,8 +205,8 @@ namespace SoD const size_t NPCTradeSize = 4; - extern size_t InvTypeSize(int inv_type); - extern const char* InvTypeName(int inv_type); + extern size_t GetInvTypeSize(int inv_type); + extern const char* GetInvTypeName(int inv_type); } /*invtype*/ @@ -218,9 +233,9 @@ namespace SoD const int CorpseBegin = invslot::PossessionsGeneral1; const int CorpseEnd = invslot::PossessionsGeneral1 + invslot::PossessionsCursor; - extern const char* InvPossessionsSlotName(int inv_slot); - extern const char* InvCorpseSlotName(int inv_slot); - extern const char* InvSlotName(int inv_type, int inv_slot); + extern const char* GetInvPossessionsSlotName(int inv_slot); + extern const char* GetInvCorpseSlotName(int inv_slot); + extern const char* GetInvSlotName(int inv_type, int inv_slot); } /*invslot*/ @@ -247,14 +262,14 @@ namespace SoD const int TradeBagsSize = invtype::InvTypeTradeSize * ItemBagSize; const int TradeBagsEnd = (TradeBagsBegin + TradeBagsSize) - 1; - extern const char* InvBagIndexName(int bag_index); + extern const char* GetInvBagIndexName(int bag_index); } /*invbag*/ namespace invaug { const size_t ItemAugSize = 5; - extern const char* InvAugIndexName(int aug_index); + extern const char* GetInvAugIndexName(int aug_index); } /*invaug*/ @@ -282,13 +297,6 @@ namespace SoD } /*constants*/ namespace behavior { - const bool ConcatenateInvTypeLimbo = true; - - const bool AllowOverLevelEquipment = false; - - const bool AllowEmptyBagInBag = false; - const bool AllowClickCastFromBag = false; - const bool CoinHasWeight = false; } /*behavior*/ diff --git a/common/patches/sof_limits.cpp b/common/patches/sof_limits.cpp index 2e81eef1d..7b7cc408b 100644 --- a/common/patches/sof_limits.cpp +++ b/common/patches/sof_limits.cpp @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -22,7 +22,7 @@ #include "../string_util.h" -size_t SoF::invtype::InvTypeSize(int inv_type) +size_t SoF::invtype::GetInvTypeSize(int inv_type) { switch (inv_type) { case invtype::InvTypePossessions: @@ -68,7 +68,7 @@ size_t SoF::invtype::InvTypeSize(int inv_type) } } -const char* SoF::invtype::InvTypeName(int inv_type) +const char* SoF::invtype::GetInvTypeName(int inv_type) { switch (inv_type) { case invtype::InvTypeInvalid: @@ -116,7 +116,7 @@ const char* SoF::invtype::InvTypeName(int inv_type) } } -const char* SoF::invslot::InvPossessionsSlotName(int inv_slot) +const char* SoF::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { case invslot::InvSlotInvalid: @@ -190,9 +190,9 @@ const char* SoF::invslot::InvPossessionsSlotName(int inv_slot) } } -const char* SoF::invslot::InvCorpseSlotName(int inv_slot) +const char* SoF::invslot::GetInvCorpseSlotName(int inv_slot) { - if (!invtype::InvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) + if (!invtype::GetInvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) return "Invalid Slot"; // needs work @@ -205,14 +205,14 @@ const char* SoF::invslot::InvCorpseSlotName(int inv_slot) return ret_str.c_str(); } -const char* SoF::invslot::InvSlotName(int inv_type, int inv_slot) +const char* SoF::invslot::GetInvSlotName(int inv_type, int inv_slot) { if (inv_type == invtype::InvTypePossessions) - return invslot::InvPossessionsSlotName(inv_slot); + return invslot::GetInvPossessionsSlotName(inv_slot); else if (inv_type == invtype::InvTypeCorpse) - return invslot::InvCorpseSlotName(inv_slot); + return invslot::GetInvCorpseSlotName(inv_slot); - size_t type_size = invtype::InvTypeSize(inv_type); + size_t type_size = invtype::GetInvTypeSize(inv_type); if (!type_size || inv_slot == invslot::InvSlotInvalid) return "Invalid Slot"; @@ -226,7 +226,7 @@ const char* SoF::invslot::InvSlotName(int inv_type, int inv_slot) return ret_str.c_str(); } -const char* SoF::invbag::InvBagIndexName(int bag_index) +const char* SoF::invbag::GetInvBagIndexName(int bag_index) { if (bag_index == invbag::InvBagInvalid) return "Invalid Bag"; @@ -240,7 +240,7 @@ const char* SoF::invbag::InvBagIndexName(int bag_index) return ret_str.c_str(); } -const char* SoF::invaug::InvAugIndexName(int aug_index) +const char* SoF::invaug::GetInvAugIndexName(int aug_index) { if (aug_index == invaug::InvAugInvalid) return "Invalid Augment"; diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 5243b289b..42033b2f6 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -32,8 +32,13 @@ namespace SoF enum : bool { False = false, True = true }; // pre-declarations + namespace inventory { + inline EQEmu::versions::ClientVersion GetInventoryRef() { return EQEmu::versions::ClientVersion::SoF; } + + } /*inventory*/ + namespace invtype { - inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::SoF; } + inline EQEmu::versions::ClientVersion GetInvTypeRef() { return EQEmu::versions::ClientVersion::SoF; } enum : int { InvTypeInvalid = -1, InvTypeBegin }; @@ -63,7 +68,7 @@ namespace SoF } /*invtype*/ namespace invslot { - inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::SoF; } + inline EQEmu::versions::ClientVersion GetInvSlotRef() { return EQEmu::versions::ClientVersion::SoF; } enum : int { InvSlotInvalid = -1, InvSlotBegin }; @@ -114,21 +119,21 @@ namespace SoF } /*invslot*/ namespace invbag { - inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::SoF; } + inline EQEmu::versions::ClientVersion GetInvBagRef() { return EQEmu::versions::ClientVersion::SoF; } enum : int { InvBagInvalid = -1, InvBagBegin }; } /*invbag*/ namespace invaug { - inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::SoF; } + inline EQEmu::versions::ClientVersion GetInvAugRef() { return EQEmu::versions::ClientVersion::SoF; } enum : int { InvAugInvalid = -1, InvAugBegin }; } /*invaug*/ namespace item { - inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::SoF; } + inline EQEmu::versions::ClientVersion GetItemRef() { return EQEmu::versions::ClientVersion::SoF; } enum ItemPacketType : int { ItemPacketMerchant = 100, @@ -146,27 +151,37 @@ namespace SoF } /*item*/ namespace profile { - inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::SoF; } + inline EQEmu::versions::ClientVersion GetProfileRef() { return EQEmu::versions::ClientVersion::SoF; } } /*profile*/ namespace constants { - inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::SoF; } + inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::SoF; } } /*constants*/ namespace behavior { - inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::SoF; } + inline EQEmu::versions::ClientVersion GetBehaviorRef() { return EQEmu::versions::ClientVersion::SoF; } } /*behavior*/ namespace skills { - inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::SoF; } + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::SoF; } } /*skills*/ // declarations + namespace inventory { + const bool ConcatenateInvTypeLimbo = true; + + const bool AllowOverLevelEquipment = false; + + const bool AllowEmptyBagInBag = false; + const bool AllowClickCastFromBag = false; + + } /*inventory*/ + namespace invtype { const size_t InvTypePossessionsSize = invslot::PossessionsCount; const size_t InvTypeBankSize = 24; @@ -190,8 +205,8 @@ namespace SoF const size_t NPCTradeSize = 4; - extern size_t InvTypeSize(int inv_type); - extern const char* InvTypeName(int inv_type); + extern size_t GetInvTypeSize(int inv_type); + extern const char* GetInvTypeName(int inv_type); } /*invtype*/ @@ -218,9 +233,9 @@ namespace SoF const int CorpseBegin = PossessionsGeneral1; const int CorpseEnd = PossessionsGeneral1 + PossessionsCursor; - extern const char* InvPossessionsSlotName(int inv_slot); - extern const char* InvCorpseSlotName(int inv_slot); - extern const char* InvSlotName(int inv_type, int inv_slot); + extern const char* GetInvPossessionsSlotName(int inv_slot); + extern const char* GetInvCorpseSlotName(int inv_slot); + extern const char* GetInvSlotName(int inv_type, int inv_slot); } /*invslot*/ @@ -247,14 +262,14 @@ namespace SoF const int TradeBagsSize = invtype::InvTypeTradeSize * ItemBagSize; const int TradeBagsEnd = (TradeBagsBegin + TradeBagsSize) - 1; - extern const char* InvBagIndexName(int bag_index); + extern const char* GetInvBagIndexName(int bag_index); } /*invbag*/ namespace invaug { const size_t ItemAugSize = 5; - extern const char* InvAugIndexName(int aug_index); + extern const char* GetInvAugIndexName(int aug_index); } /*invaug*/ @@ -282,13 +297,6 @@ namespace SoF } /*constants*/ namespace behavior { - const bool ConcatenateInvTypeLimbo = true; - - const bool AllowOverLevelEquipment = false; - - const bool AllowEmptyBagInBag = false; - const bool AllowClickCastFromBag = false; - const bool CoinHasWeight = true; } /*behavior*/ diff --git a/common/patches/titanium_limits.cpp b/common/patches/titanium_limits.cpp index 2d5faac6b..fba7db270 100644 --- a/common/patches/titanium_limits.cpp +++ b/common/patches/titanium_limits.cpp @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -22,7 +22,7 @@ #include "../string_util.h" -size_t Titanium::invtype::InvTypeSize(int inv_type) +size_t Titanium::invtype::GetInvTypeSize(int inv_type) { switch (inv_type) { case invtype::InvTypePossessions: @@ -68,7 +68,7 @@ size_t Titanium::invtype::InvTypeSize(int inv_type) } } -const char* Titanium::invtype::InvTypeName(int inv_type) +const char* Titanium::invtype::GetInvTypeName(int inv_type) { switch (inv_type) { case invtype::InvTypeInvalid: @@ -116,7 +116,7 @@ const char* Titanium::invtype::InvTypeName(int inv_type) } } -const char* Titanium::invslot::InvPossessionsSlotName(int inv_slot) +const char* Titanium::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { case invslot::InvSlotInvalid: @@ -188,9 +188,9 @@ const char* Titanium::invslot::InvPossessionsSlotName(int inv_slot) } } -const char* Titanium::invslot::InvCorpseSlotName(int inv_slot) +const char* Titanium::invslot::GetInvCorpseSlotName(int inv_slot) { - if (!invtype::InvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) + if (!invtype::GetInvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) return "Invalid Slot"; // needs work @@ -203,14 +203,14 @@ const char* Titanium::invslot::InvCorpseSlotName(int inv_slot) return ret_str.c_str(); } -const char* Titanium::invslot::InvSlotName(int inv_type, int inv_slot) +const char* Titanium::invslot::GetInvSlotName(int inv_type, int inv_slot) { if (inv_type == invtype::InvTypePossessions) - return invslot::InvPossessionsSlotName(inv_slot); + return invslot::GetInvPossessionsSlotName(inv_slot); else if (inv_type == invtype::InvTypeCorpse) - return invslot::InvCorpseSlotName(inv_slot); + return invslot::GetInvCorpseSlotName(inv_slot); - size_t type_size = invtype::InvTypeSize(inv_type); + size_t type_size = invtype::GetInvTypeSize(inv_type); if (!type_size || inv_slot == invslot::InvSlotInvalid) return "Invalid Slot"; @@ -224,7 +224,7 @@ const char* Titanium::invslot::InvSlotName(int inv_type, int inv_slot) return ret_str.c_str(); } -const char* Titanium::invbag::InvBagIndexName(int bag_index) +const char* Titanium::invbag::GetInvBagIndexName(int bag_index) { if (bag_index == invbag::InvBagInvalid) return "Invalid Bag"; @@ -238,7 +238,7 @@ const char* Titanium::invbag::InvBagIndexName(int bag_index) return ret_str.c_str(); } -const char* Titanium::invaug::InvAugIndexName(int aug_index) +const char* Titanium::invaug::GetInvAugIndexName(int aug_index) { if (aug_index == invaug::InvAugInvalid) return "Invalid Augment"; diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index 0d4620997..51651ea38 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -32,8 +32,13 @@ namespace Titanium enum : bool { False = false, True = true }; // pre-declarations + namespace inventory { + inline EQEmu::versions::ClientVersion GetInventoryRef() { return EQEmu::versions::ClientVersion::Titanium; } + + } /*inventory*/ + namespace invtype { - inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::Titanium; } + inline EQEmu::versions::ClientVersion GetInvTypeRef() { return EQEmu::versions::ClientVersion::Titanium; } enum : int { InvTypeInvalid = -1, InvTypeBegin }; @@ -63,7 +68,7 @@ namespace Titanium } /*invtype*/ namespace invslot { - inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::Titanium; } + inline EQEmu::versions::ClientVersion GetInvSlotRef() { return EQEmu::versions::ClientVersion::Titanium; } enum : int { InvSlotInvalid = -1, InvSlotBegin }; @@ -113,21 +118,21 @@ namespace Titanium } /*invslot*/ namespace invbag { - inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::Titanium; } + inline EQEmu::versions::ClientVersion GetInvBagRef() { return EQEmu::versions::ClientVersion::Titanium; } enum : int { InvBagInvalid = -1, InvBagBegin }; } /*invbag*/ namespace invaug { - inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::Titanium; } + inline EQEmu::versions::ClientVersion GetInvAugRef() { return EQEmu::versions::ClientVersion::Titanium; } enum : int { InvAugInvalid = -1, InvAugBegin }; } /*invaug*/ namespace item { - inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::Titanium; } + inline EQEmu::versions::ClientVersion GetItemRef() { return EQEmu::versions::ClientVersion::Titanium; } enum ItemPacketType : int { ItemPacketMerchant = 100, @@ -145,27 +150,37 @@ namespace Titanium } /*item*/ namespace profile { - inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::Titanium; } + inline EQEmu::versions::ClientVersion GetProfileRef() { return EQEmu::versions::ClientVersion::Titanium; } } /*profile*/ namespace constants { - inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::Titanium; } + inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::Titanium; } } /*constants*/ namespace behavior { - inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::Titanium; } + inline EQEmu::versions::ClientVersion GetBehaviorRef() { return EQEmu::versions::ClientVersion::Titanium; } } /*behavior*/ namespace skills { - inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::Titanium; } + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::Titanium; } } /*skills*/ // declarations + namespace inventory { + const bool ConcatenateInvTypeLimbo = true; + + const bool AllowOverLevelEquipment = false; + + const bool AllowEmptyBagInBag = false; + const bool AllowClickCastFromBag = false; + + } /*inventory*/ + namespace invtype { const size_t InvTypePossessionsSize = invslot::PossessionsCount; const size_t InvTypeBankSize = 16; @@ -189,8 +204,8 @@ namespace Titanium const size_t NPCTradeSize = 4; - extern size_t InvTypeSize(int inv_type); - extern const char* InvTypeName(int inv_type); + extern size_t GetInvTypeSize(int inv_type); + extern const char* GetInvTypeName(int inv_type); } /*invtype*/ @@ -217,9 +232,9 @@ namespace Titanium const int CorpseBegin = PossessionsGeneral1; const int CorpseEnd = PossessionsGeneral1 + PossessionsCursor; - extern const char* InvPossessionsSlotName(int inv_slot); - extern const char* InvCorpseSlotName(int inv_slot); - extern const char* InvSlotName(int inv_type, int inv_slot); + extern const char* GetInvPossessionsSlotName(int inv_slot); + extern const char* GetInvCorpseSlotName(int inv_slot); + extern const char* GetInvSlotName(int inv_type, int inv_slot); } /*invslot*/ @@ -246,14 +261,14 @@ namespace Titanium const int TradeBagsSize = invtype::InvTypeTradeSize * ItemBagSize; const int TradeBagsEnd = (TradeBagsBegin + TradeBagsSize) - 1; - extern const char* InvBagIndexName(int bag_index); + extern const char* GetInvBagIndexName(int bag_index); } /*invbag*/ namespace invaug { const size_t ItemAugSize = 5; - extern const char* InvAugIndexName(int aug_index); + extern const char* GetInvAugIndexName(int aug_index); } /*invaug*/ @@ -281,13 +296,6 @@ namespace Titanium } /*constants*/ namespace behavior { - const bool ConcatenateInvTypeLimbo = true; - - const bool AllowOverLevelEquipment = false; - - const bool AllowEmptyBagInBag = false; - const bool AllowClickCastFromBag = false; - const bool CoinHasWeight = true; } /*behavior*/ diff --git a/common/patches/uf_limits.cpp b/common/patches/uf_limits.cpp index 8e72b8b03..28a1d7c3f 100644 --- a/common/patches/uf_limits.cpp +++ b/common/patches/uf_limits.cpp @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -22,7 +22,7 @@ #include "../string_util.h" -size_t UF::invtype::InvTypeSize(int inv_type) +size_t UF::invtype::GetInvTypeSize(int inv_type) { switch (inv_type) { case invtype::InvTypePossessions: @@ -68,7 +68,7 @@ size_t UF::invtype::InvTypeSize(int inv_type) } } -const char* UF::invtype::InvTypeName(int inv_type) +const char* UF::invtype::GetInvTypeName(int inv_type) { switch (inv_type) { case invtype::InvTypeInvalid: @@ -116,7 +116,7 @@ const char* UF::invtype::InvTypeName(int inv_type) } } -const char* UF::invslot::InvPossessionsSlotName(int inv_slot) +const char* UF::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { case invslot::InvSlotInvalid: @@ -190,9 +190,9 @@ const char* UF::invslot::InvPossessionsSlotName(int inv_slot) } } -const char* UF::invslot::InvCorpseSlotName(int inv_slot) +const char* UF::invslot::GetInvCorpseSlotName(int inv_slot) { - if (!invtype::InvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) + if (!invtype::GetInvTypeSize(invtype::InvTypeCorpse) || inv_slot == invslot::InvSlotInvalid) return "Invalid Slot"; // needs work @@ -205,14 +205,14 @@ const char* UF::invslot::InvCorpseSlotName(int inv_slot) return ret_str.c_str(); } -const char* UF::invslot::InvSlotName(int inv_type, int inv_slot) +const char* UF::invslot::GetInvSlotName(int inv_type, int inv_slot) { if (inv_type == invtype::InvTypePossessions) - return invslot::InvPossessionsSlotName(inv_slot); + return invslot::GetInvPossessionsSlotName(inv_slot); else if (inv_type == invtype::InvTypeCorpse) - return invslot::InvCorpseSlotName(inv_slot); + return invslot::GetInvCorpseSlotName(inv_slot); - size_t type_size = invtype::InvTypeSize(inv_type); + size_t type_size = invtype::GetInvTypeSize(inv_type); if (!type_size || inv_slot == invslot::InvSlotInvalid) return "Invalid Slot"; @@ -226,7 +226,7 @@ const char* UF::invslot::InvSlotName(int inv_type, int inv_slot) return ret_str.c_str(); } -const char* UF::invbag::InvBagIndexName(int bag_index) +const char* UF::invbag::GetInvBagIndexName(int bag_index) { if (bag_index == invbag::InvBagInvalid) return "Invalid Bag"; @@ -240,7 +240,7 @@ const char* UF::invbag::InvBagIndexName(int bag_index) return ret_str.c_str(); } -const char* UF::invaug::InvAugIndexName(int aug_index) +const char* UF::invaug::GetInvAugIndexName(int aug_index) { if (aug_index == invaug::InvAugInvalid) return "Invalid Augment"; diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index 7f1ec33a8..b71937fa6 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -32,8 +32,13 @@ namespace UF enum : bool { False = false, True = true }; // pre-declarations + namespace inventory { + inline EQEmu::versions::ClientVersion GetInventoryRef() { return EQEmu::versions::ClientVersion::UF; } + + } /*inventory*/ + namespace invtype { - inline EQEmu::versions::ClientVersion InvTypeRef() { return EQEmu::versions::ClientVersion::UF; } + inline EQEmu::versions::ClientVersion GetInvTypeRef() { return EQEmu::versions::ClientVersion::UF; } enum : int { InvTypeInvalid = -1, InvTypeBegin }; @@ -63,7 +68,7 @@ namespace UF } /*invtype*/ namespace invslot { - inline EQEmu::versions::ClientVersion InvSlotRef() { return EQEmu::versions::ClientVersion::UF; } + inline EQEmu::versions::ClientVersion GetInvSlotRef() { return EQEmu::versions::ClientVersion::UF; } enum : int { InvSlotInvalid = -1, InvSlotBegin }; @@ -114,21 +119,21 @@ namespace UF } /*invslot*/ namespace invbag { - inline EQEmu::versions::ClientVersion InvBagRef() { return EQEmu::versions::ClientVersion::UF; } + inline EQEmu::versions::ClientVersion GetInvBagRef() { return EQEmu::versions::ClientVersion::UF; } enum : int { InvBagInvalid = -1, InvBagBegin }; } /*invbag*/ namespace invaug { - inline EQEmu::versions::ClientVersion InvAugRef() { return EQEmu::versions::ClientVersion::UF; } + inline EQEmu::versions::ClientVersion GetInvAugRef() { return EQEmu::versions::ClientVersion::UF; } enum : int { InvAugInvalid = -1, InvAugBegin }; } /*invaug*/ namespace item { - inline EQEmu::versions::ClientVersion ItemRef() { return EQEmu::versions::ClientVersion::UF; } + inline EQEmu::versions::ClientVersion GetItemRef() { return EQEmu::versions::ClientVersion::UF; } enum ItemPacketType : int { ItemPacketMerchant = 100, @@ -147,27 +152,37 @@ namespace UF } /*item*/ namespace profile { - inline EQEmu::versions::ClientVersion ProfileRef() { return EQEmu::versions::ClientVersion::UF; } + inline EQEmu::versions::ClientVersion GetProfileRef() { return EQEmu::versions::ClientVersion::UF; } } /*profile*/ namespace constants { - inline EQEmu::versions::ClientVersion ConstantsRef() { return EQEmu::versions::ClientVersion::UF; } + inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::UF; } } /*constants*/ namespace behavior { - inline EQEmu::versions::ClientVersion BehaviorRef() { return EQEmu::versions::ClientVersion::UF; } + inline EQEmu::versions::ClientVersion GetBehaviorRef() { return EQEmu::versions::ClientVersion::UF; } } /*behavior*/ namespace skills { - inline EQEmu::versions::ClientVersion SkillsRef() { return EQEmu::versions::ClientVersion::UF; } + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::UF; } } /*skills*/ // declarations + namespace inventory { + const bool ConcatenateInvTypeLimbo = true; + + const bool AllowOverLevelEquipment = true; + + const bool AllowEmptyBagInBag = false; + const bool AllowClickCastFromBag = false; + + } /*inventory*/ + namespace invtype { const size_t InvTypePossessionsSize = invslot::PossessionsCount; const size_t InvTypeBankSize = 24; @@ -191,8 +206,8 @@ namespace UF const size_t NPCTradeSize = 4; - extern size_t InvTypeSize(int inv_type); - extern const char* InvTypeName(int inv_type); + extern size_t GetInvTypeSize(int inv_type); + extern const char* GetInvTypeName(int inv_type); } /*invtype*/ @@ -219,9 +234,9 @@ namespace UF const int CorpseBegin = invslot::PossessionsGeneral1; const int CorpseEnd = invslot::PossessionsGeneral1 + invslot::PossessionsCursor; - extern const char* InvPossessionsSlotName(int inv_slot); - extern const char* InvCorpseSlotName(int inv_slot); - extern const char* InvSlotName(int inv_type, int inv_slot); + extern const char* GetInvPossessionsSlotName(int inv_slot); + extern const char* GetInvCorpseSlotName(int inv_slot); + extern const char* GetInvSlotName(int inv_type, int inv_slot); } /*invslot*/ @@ -248,14 +263,14 @@ namespace UF const int TradeBagsSize = invtype::InvTypeTradeSize * ItemBagSize; const int TradeBagsEnd = (TradeBagsBegin + TradeBagsSize) - 1; - extern const char* InvBagIndexName(int bag_index); + extern const char* GetInvBagIndexName(int bag_index); } /*invbag*/ namespace invaug { const size_t ItemAugSize = 5; - extern const char* InvAugIndexName(int aug_index); + extern const char* GetInvAugIndexName(int aug_index); } /*invaug*/ @@ -283,13 +298,6 @@ namespace UF } /*constants*/ namespace behavior { - const bool ConcatenateInvTypeLimbo = true; - - const bool AllowOverLevelEquipment = true; - - const bool AllowEmptyBagInBag = false; - const bool AllowClickCastFromBag = false; - const bool CoinHasWeight = false; } /*behavior*/ diff --git a/common/say_link.cpp b/common/say_link.cpp index 12c1d80d1..bbadc0c92 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -65,19 +65,19 @@ void EQEmu::saylink::SayLinkEngine::Reset() m_ItemData = nullptr; m_LootData = nullptr; m_ItemInst = nullptr; - m_Proxy_unknown_1 = NOT_USED; - m_ProxyItemID = NOT_USED; - m_ProxyAugment1ID = NOT_USED; - m_ProxyAugment2ID = NOT_USED; - m_ProxyAugment3ID = NOT_USED; - m_ProxyAugment4ID = NOT_USED; - m_ProxyAugment5ID = NOT_USED; - m_ProxyAugment6ID = NOT_USED; - m_ProxyIsEvolving = NOT_USED; - m_ProxyEvolveGroup = NOT_USED; - m_ProxyEvolveLevel = NOT_USED; - m_ProxyOrnamentIcon = NOT_USED; - m_ProxyHash = NOT_USED; + m_Proxy_unknown_1 = 0; + m_ProxyItemID = 0; + m_ProxyAugment1ID = 0; + m_ProxyAugment2ID = 0; + m_ProxyAugment3ID = 0; + m_ProxyAugment4ID = 0; + m_ProxyAugment5ID = 0; + m_ProxyAugment6ID = 0; + m_ProxyIsEvolving = 0; + m_ProxyEvolveGroup = 0; + m_ProxyEvolveLevel = 0; + m_ProxyOrnamentIcon = 0; + m_ProxyHash = 0; m_ProxyText = nullptr; m_TaskUse = false; m_Link.clear(); diff --git a/world/client.cpp b/world/client.cpp index fdccc8f7d..1fc2a93f8 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -211,7 +211,7 @@ void Client::SendMaxCharCreate() { auto outapp = new EQApplicationPacket(OP_SendMaxCharacters, sizeof(MaxCharacters_Struct)); MaxCharacters_Struct* mc = (MaxCharacters_Struct*)outapp->pBuffer; - mc->max_chars = EQEmu::constants::CharacterCreationLimit(m_ClientVersion); + mc->max_chars = EQEmu::constants::GetCharacterCreationLimit(m_ClientVersion); if (mc->max_chars > EQEmu::constants::CharacterCreationMax) mc->max_chars = EQEmu::constants::CharacterCreationMax; @@ -746,7 +746,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { // This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above) // (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration) if (!pZoning) { - size_t character_limit = EQEmu::constants::CharacterCreationLimit(eqs->ClientVersion()); + size_t character_limit = EQEmu::constants::GetCharacterCreationLimit(eqs->ClientVersion()); if (character_limit > EQEmu::constants::CharacterCreationMax) { character_limit = EQEmu::constants::CharacterCreationMax; } if (eqs->ClientVersion() == EQEmu::versions::ClientVersion::Titanium) { character_limit = 8; } diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 684ab0d64..9a447640b 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -37,7 +37,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou { /* Set Character Creation Limit */ EQEmu::versions::ClientVersion client_version = EQEmu::versions::ConvertClientVersionBitToClientVersion(clientVersionBit); - size_t character_limit = EQEmu::constants::CharacterCreationLimit(client_version); + size_t character_limit = EQEmu::constants::GetCharacterCreationLimit(client_version); // Validate against absolute server max if (character_limit > EQEmu::constants::CharacterCreationMax) diff --git a/zone/bot.cpp b/zone/bot.cpp index 76f537a5b..9975881f3 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -347,7 +347,7 @@ NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::str BotNPCType.hp_regen = 1; BotNPCType.mana_regen = 1; BotNPCType.maxlevel = botLevel; - BotNPCType.light = NOT_USED; // due to the way that bots are coded..this is sent post-spawn + BotNPCType.light = 0; // due to the way that bots are coded..this is sent post-spawn return BotNPCType; } diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index fbbce59ce..266f5540b 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1355,7 +1355,7 @@ uint32 Client::CalcCurrentWeight() This is the ONLY instance I have seen where the client is hard coded to particular Item IDs to set a certain property for an item. It is very odd. */ // SoD+ client has no weight for coin - if (EQEmu::profile::CoinHasWeight(EQEmu::versions::ConvertClientVersionToInventoryVersion(ClientVersion()))) { + if (EQEmu::behavior::GetCoinHasWeight(EQEmu::versions::ConvertClientVersionToInventoryVersion(ClientVersion()))) { Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4; } float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat; diff --git a/zone/command.cpp b/zone/command.cpp index d0143a0ad..4b7c6e929 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5627,13 +5627,13 @@ void command_itemsearch(Client *c, const Seperator *sep) return; } - int count = NOT_USED; + int count = 0; char sName[64]; char sCriteria[255]; strn0cpy(sCriteria, search_criteria, sizeof(sCriteria)); strupr(sCriteria); char* pdest; - uint32 it = NOT_USED; + uint32 it = 0; while ((item = database.IterateItems(&it))) { strn0cpy(sName, item->Name, sizeof(sName)); strupr(sName); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 9245099e4..48bd46fed 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -998,7 +998,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::inventory::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()), EQEmu::legacy::TypeCorpse); + int corpselootlimit = EQEmu::inventory::GetInventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()), EQEmu::legacy::TypeCorpse); for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; @@ -1292,7 +1292,7 @@ void Corpse::QueryLoot(Client* to) { cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::inventory::InventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()), EQEmu::legacy::TypeCorpse); + int corpselootlimit = EQEmu::inventory::GetInventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()), EQEmu::legacy::TypeCorpse); for(; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 9b453847f..1dbdcab11 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -2759,7 +2759,7 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN + sizeof(TaskDescriptionData2_Struct) + 1 + sizeof(TaskDescriptionTrailer_Struct); std::string reward_text; - int ItemID = NOT_USED; + int ItemID = 0; // If there is an item make the Reward text into a link to the item (only the first item if a list // is specified). I have been unable to get multiple item links to work. From 6c1af93f5884d213302a58b0aadb63af77de5f22 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 30 May 2016 08:39:49 -0400 Subject: [PATCH 136/693] Another lightsource/saylink/skills pass --- common/light_source.cpp | 6 +- common/light_source.h | 27 +++---- common/say_link.cpp | 128 ++++++++++++++--------------- common/say_link.h | 173 +++++++++++++++++++--------------------- common/skills.cpp | 138 +------------------------------- common/skills.h | 134 ++++++++++++++++++++++++++++++- zone/bot.cpp | 4 +- zone/bot_command.cpp | 4 +- zone/command.cpp | 14 ++-- zone/corpse.cpp | 4 +- zone/npc.cpp | 4 +- zone/questmgr.cpp | 10 +-- zone/tasks.cpp | 4 +- 13 files changed, 321 insertions(+), 329 deletions(-) diff --git a/common/light_source.cpp b/common/light_source.cpp index 730a5bd78..939676ee0 100644 --- a/common/light_source.cpp +++ b/common/light_source.cpp @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -82,12 +82,12 @@ bool EQEmu::lightsource::IsLevelGreater(uint8 left_type, uint8 right_type) return (light_levels[left_type] > light_levels[right_type]); } -EQEmu::lightsource::Light_Struct::Light_Struct() +EQEmu::LightSource_Struct::LightSource_Struct() { Clear(); } -void EQEmu::lightsource::Light_Struct::Clear() +void EQEmu::LightSource_Struct::Clear() { memset(&Slot, 0, (sizeof(uint8) * sizeof(Slot))); } diff --git a/common/light_source.h b/common/light_source.h index 9c031712b..a77049e4f 100644 --- a/common/light_source.h +++ b/common/light_source.h @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -34,7 +34,6 @@ namespace EQEmu LightCount }; - enum LightType { LightTypeNone = 0, LightTypeCandle, @@ -70,21 +69,21 @@ namespace EQEmu LightLevelCount }; - struct Light_Struct { - uint8 Slot[LightCount]; - - Light_Struct(); - - void Clear(); - - inline uint8& operator[](LightSlot index) { return Slot[index]; } - }; - extern uint8 TypeToLevel(uint8 light_type); extern bool IsLevelGreater(uint8 left_type, uint8 right_type); }; /*lightsource*/ + struct LightSource_Struct { + uint8 Slot[lightsource::LightCount]; + + LightSource_Struct(); + + void Clear(); + + inline uint8& operator[](lightsource::LightSlot index) { return Slot[index]; } + }; + struct LightSourceProfile { /* Current criteria (light types): @@ -103,8 +102,8 @@ namespace EQEmu -- The timer-based update cancels out the invalid light source */ - lightsource::Light_Struct Type; // Light types (classifications) - lightsource::Light_Struct Level; // Light levels (intensities) - used to determine which light source should be active + LightSource_Struct Type; // Light types (classifications) + LightSource_Struct Level; // Light levels (intensities) - used to determine which light source should be active LightSourceProfile() { } diff --git a/common/say_link.cpp b/common/say_link.cpp index bbadc0c92..3c9fe7c6e 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -26,12 +26,60 @@ #include "../zone/zonedb.h" -EQEmu::saylink::SayLinkEngine::SayLinkEngine() +bool EQEmu::saylink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct, const std::string& say_link_body) +{ + memset(&say_link_body_struct, 0, sizeof(say_link_body_struct)); + if (say_link_body.length() != EQEmu::legacy::TEXT_LINK_BODY_LENGTH) + return false; + + say_link_body_struct.unknown_1 = (uint8)strtol(say_link_body.substr(0, 1).c_str(), nullptr, 16); + say_link_body_struct.item_id = (uint32)strtol(say_link_body.substr(1, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_1 = (uint32)strtol(say_link_body.substr(6, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_2 = (uint32)strtol(say_link_body.substr(11, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_3 = (uint32)strtol(say_link_body.substr(16, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_4 = (uint32)strtol(say_link_body.substr(21, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_5 = (uint32)strtol(say_link_body.substr(26, 5).c_str(), nullptr, 16); + say_link_body_struct.augment_6 = (uint32)strtol(say_link_body.substr(31, 5).c_str(), nullptr, 16); + say_link_body_struct.is_evolving = (uint8)strtol(say_link_body.substr(36, 1).c_str(), nullptr, 16); + say_link_body_struct.evolve_group = (uint32)strtol(say_link_body.substr(37, 4).c_str(), nullptr, 16); + say_link_body_struct.evolve_level = (uint8)strtol(say_link_body.substr(41, 2).c_str(), nullptr, 16); + say_link_body_struct.ornament_icon = (uint32)strtol(say_link_body.substr(43, 5).c_str(), nullptr, 16); + say_link_body_struct.hash = (int)strtol(say_link_body.substr(48, 8).c_str(), nullptr, 16); + + return true; +} + +bool EQEmu::saylink::GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct) +{ + say_link_body = StringFormat( + "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X", + (0x0F & say_link_body_struct.unknown_1), + (0x000FFFFF & say_link_body_struct.item_id), + (0x000FFFFF & say_link_body_struct.augment_1), + (0x000FFFFF & say_link_body_struct.augment_2), + (0x000FFFFF & say_link_body_struct.augment_3), + (0x000FFFFF & say_link_body_struct.augment_4), + (0x000FFFFF & say_link_body_struct.augment_5), + (0x000FFFFF & say_link_body_struct.augment_6), + (0x0F & say_link_body_struct.is_evolving), + (0x0000FFFF & say_link_body_struct.evolve_group), + (0xFF & say_link_body_struct.evolve_level), + (0x000FFFFF & say_link_body_struct.ornament_icon), + (0xFFFFFFFF & say_link_body_struct.hash) + ); + + if (say_link_body.length() != EQEmu::legacy::TEXT_LINK_BODY_LENGTH) + return false; + + return true; +} + +EQEmu::SayLinkEngine::SayLinkEngine() { Reset(); } -std::string EQEmu::saylink::SayLinkEngine::GenerateLink() +std::string EQEmu::SayLinkEngine::GenerateLink() { m_Link.clear(); m_LinkBody.clear(); @@ -59,9 +107,9 @@ std::string EQEmu::saylink::SayLinkEngine::GenerateLink() return m_Link; } -void EQEmu::saylink::SayLinkEngine::Reset() +void EQEmu::SayLinkEngine::Reset() { - m_LinkType = SayLinkBlank; + m_LinkType = saylink::SayLinkBlank; m_ItemData = nullptr; m_LootData = nullptr; m_ItemInst = nullptr; @@ -86,7 +134,7 @@ void EQEmu::saylink::SayLinkEngine::Reset() m_Error = false; } -void EQEmu::saylink::SayLinkEngine::generate_body() +void EQEmu::SayLinkEngine::generate_body() { /* Current server mask: EQClientRoF2 @@ -102,16 +150,16 @@ void EQEmu::saylink::SayLinkEngine::generate_body() const EQEmu::ItemBase* item_data = nullptr; switch (m_LinkType) { - case SayLinkBlank: + case saylink::SayLinkBlank: break; - case SayLinkItemData: + case saylink::SayLinkItemData: if (m_ItemData == nullptr) { break; } m_LinkBodyStruct.item_id = m_ItemData->ID; m_LinkBodyStruct.evolve_group = m_ItemData->LoreGroup; // this probably won't work for all items //m_LinkBodyStruct.evolve_level = m_ItemData->EvolvingLevel; // TODO: add hash call break; - case SayLinkLootItem: + case saylink::SayLinkLootItem: if (m_LootData == nullptr) { break; } item_data = database.GetItem(m_LootData->item_id); if (item_data == nullptr) { break; } @@ -126,7 +174,7 @@ void EQEmu::saylink::SayLinkEngine::generate_body() //m_LinkBodyStruct.evolve_level = item_data->EvolvingLevel; // TODO: add hash call break; - case SayLinkItemInst: + case saylink::SayLinkItemInst: if (m_ItemInst == nullptr) { break; } if (m_ItemInst->GetItem() == nullptr) { break; } m_LinkBodyStruct.item_id = m_ItemInst->GetItem()->ID; @@ -195,7 +243,7 @@ void EQEmu::saylink::SayLinkEngine::generate_body() ); } -void EQEmu::saylink::SayLinkEngine::generate_text() +void EQEmu::SayLinkEngine::generate_text() { if (m_ProxyText != nullptr) { m_LinkText = m_ProxyText; @@ -205,19 +253,19 @@ void EQEmu::saylink::SayLinkEngine::generate_text() const EQEmu::ItemBase* item_data = nullptr; switch (m_LinkType) { - case SayLinkBlank: + case saylink::SayLinkBlank: break; - case SayLinkItemData: + case saylink::SayLinkItemData: if (m_ItemData == nullptr) { break; } m_LinkText = m_ItemData->Name; return; - case SayLinkLootItem: + case saylink::SayLinkLootItem: if (m_LootData == nullptr) { break; } item_data = database.GetItem(m_LootData->item_id); if (item_data == nullptr) { break; } m_LinkText = item_data->Name; return; - case SayLinkItemInst: + case saylink::SayLinkItemInst: if (m_ItemInst == nullptr) { break; } if (m_ItemInst->GetItem() == nullptr) { break; } m_LinkText = m_ItemInst->GetItem()->Name; @@ -228,51 +276,3 @@ void EQEmu::saylink::SayLinkEngine::generate_text() m_LinkText = "null"; } - -bool EQEmu::saylink::DegenerateLinkBody(SayLinkBody_Struct& say_link_body_struct, const std::string& say_link_body) -{ - memset(&say_link_body_struct, 0, sizeof(say_link_body_struct)); - if (say_link_body.length() != EQEmu::legacy::TEXT_LINK_BODY_LENGTH) - return false; - - say_link_body_struct.unknown_1 = (uint8)strtol(say_link_body.substr(0, 1).c_str(), nullptr, 16); - say_link_body_struct.item_id = (uint32)strtol(say_link_body.substr(1, 5).c_str(), nullptr, 16); - say_link_body_struct.augment_1 = (uint32)strtol(say_link_body.substr(6, 5).c_str(), nullptr, 16); - say_link_body_struct.augment_2 = (uint32)strtol(say_link_body.substr(11, 5).c_str(), nullptr, 16); - say_link_body_struct.augment_3 = (uint32)strtol(say_link_body.substr(16, 5).c_str(), nullptr, 16); - say_link_body_struct.augment_4 = (uint32)strtol(say_link_body.substr(21, 5).c_str(), nullptr, 16); - say_link_body_struct.augment_5 = (uint32)strtol(say_link_body.substr(26, 5).c_str(), nullptr, 16); - say_link_body_struct.augment_6 = (uint32)strtol(say_link_body.substr(31, 5).c_str(), nullptr, 16); - say_link_body_struct.is_evolving = (uint8)strtol(say_link_body.substr(36, 1).c_str(), nullptr, 16); - say_link_body_struct.evolve_group = (uint32)strtol(say_link_body.substr(37, 4).c_str(), nullptr, 16); - say_link_body_struct.evolve_level = (uint8)strtol(say_link_body.substr(41, 2).c_str(), nullptr, 16); - say_link_body_struct.ornament_icon = (uint32)strtol(say_link_body.substr(43, 5).c_str(), nullptr, 16); - say_link_body_struct.hash = (int)strtol(say_link_body.substr(48, 8).c_str(), nullptr, 16); - - return true; -} - -bool EQEmu::saylink::GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct) -{ - say_link_body = StringFormat( - "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X", - (0x0F & say_link_body_struct.unknown_1), - (0x000FFFFF & say_link_body_struct.item_id), - (0x000FFFFF & say_link_body_struct.augment_1), - (0x000FFFFF & say_link_body_struct.augment_2), - (0x000FFFFF & say_link_body_struct.augment_3), - (0x000FFFFF & say_link_body_struct.augment_4), - (0x000FFFFF & say_link_body_struct.augment_5), - (0x000FFFFF & say_link_body_struct.augment_6), - (0x0F & say_link_body_struct.is_evolving), - (0x0000FFFF & say_link_body_struct.evolve_group), - (0xFF & say_link_body_struct.evolve_level), - (0x000FFFFF & say_link_body_struct.ornament_icon), - (0xFFFFFFFF & say_link_body_struct.hash) - ); - - if (say_link_body.length() != EQEmu::legacy::TEXT_LINK_BODY_LENGTH) - return false; - - return true; -} diff --git a/common/say_link.h b/common/say_link.h index dcc327cad..0bbac2e36 100644 --- a/common/say_link.h +++ b/common/say_link.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) @@ -10,7 +10,7 @@ but WITHOUT ANY WARRANTY except by those people which sell it, which are required to give you total support for your newly bought product; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. + A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software @@ -28,112 +28,107 @@ struct ServerLootItem_Struct; class ItemInst; - namespace EQEmu { struct ItemBase; - - namespace saylink { - struct SayLinkBody_Struct; // Current server mask: EQClientRoF2 + struct SayLinkBody_Struct; - class SayLinkEngine; + namespace saylink { + enum SayLinkType { + SayLinkBlank = 0, + SayLinkItemData, + SayLinkLootItem, + SayLinkItemInst + }; extern bool DegenerateLinkBody(SayLinkBody_Struct& say_Link_body_struct, const std::string& say_link_body); extern bool GenerateLinkBody(std::string& say_link_body, const SayLinkBody_Struct& say_link_body_struct); - } -} + } /*saylink*/ -struct EQEmu::saylink::SayLinkBody_Struct -{ - uint8 unknown_1; /* %1X */ - uint32 item_id; /* %05X */ - uint32 augment_1; /* %05X */ - uint32 augment_2; /* %05X */ - uint32 augment_3; /* %05X */ - uint32 augment_4; /* %05X */ - uint32 augment_5; /* %05X */ - uint32 augment_6; /* %05X */ - uint8 is_evolving; /* %1X */ - uint32 evolve_group; /* %05X */ - uint8 evolve_level; /* %02X */ - uint32 ornament_icon; /* %05X */ - int hash; /* %08X */ -}; - -class EQEmu::saylink::SayLinkEngine -{ -public: - enum SayLinkType { - SayLinkBlank = 0, - SayLinkItemData, - SayLinkLootItem, - SayLinkItemInst + struct SayLinkBody_Struct { + uint8 unknown_1; /* %1X */ + uint32 item_id; /* %05X */ + uint32 augment_1; /* %05X */ + uint32 augment_2; /* %05X */ + uint32 augment_3; /* %05X */ + uint32 augment_4; /* %05X */ + uint32 augment_5; /* %05X */ + uint32 augment_6; /* %05X */ + uint8 is_evolving; /* %1X */ + uint32 evolve_group; /* %05X */ + uint8 evolve_level; /* %02X */ + uint32 ornament_icon; /* %05X */ + int hash; /* %08X */ }; - SayLinkEngine(); + class SayLinkEngine { + public: + SayLinkEngine(); - void SetLinkType(SayLinkType link_type) { m_LinkType = link_type; } - void SetItemData(const EQEmu::ItemBase* item_data) { m_ItemData = item_data; } - void SetLootData(const ServerLootItem_Struct* loot_data) { m_LootData = loot_data; } - void SetItemInst(const ItemInst* item_inst) { m_ItemInst = item_inst; } + void SetLinkType(saylink::SayLinkType link_type) { m_LinkType = link_type; } + void SetItemData(const EQEmu::ItemBase* item_data) { m_ItemData = item_data; } + void SetLootData(const ServerLootItem_Struct* loot_data) { m_LootData = loot_data; } + void SetItemInst(const ItemInst* item_inst) { m_ItemInst = item_inst; } - // mainly for saylinks..but, not limited to - void SetProxyUnknown1(uint8 proxy_unknown_1) { m_Proxy_unknown_1 = proxy_unknown_1; } - void SetProxyItemID(uint32 proxy_item_id) { m_ProxyItemID = proxy_item_id; } - void SetProxyAugment1ID(uint32 proxy_augment_id) { m_ProxyAugment1ID = proxy_augment_id; } - void SetProxyAugment2ID(uint32 proxy_augment_id) { m_ProxyAugment2ID = proxy_augment_id; } - void SetProxyAugment3ID(uint32 proxy_augment_id) { m_ProxyAugment3ID = proxy_augment_id; } - void SetProxyAugment4ID(uint32 proxy_augment_id) { m_ProxyAugment4ID = proxy_augment_id; } - void SetProxyAugment5ID(uint32 proxy_augment_id) { m_ProxyAugment5ID = proxy_augment_id; } - void SetProxyAugment6ID(uint32 proxy_augment_id) { m_ProxyAugment6ID = proxy_augment_id; } - void SetProxyIsEvolving(uint8 proxy_is_evolving) { m_ProxyIsEvolving = proxy_is_evolving; } - void SetProxyEvolveGroup(uint32 proxy_evolve_group) { m_ProxyEvolveGroup = proxy_evolve_group; } - void SetProxyEvolveLevel(uint8 proxy_evolve_level) { m_ProxyEvolveLevel = proxy_evolve_level; } - void SetProxyOrnamentIcon(uint32 proxy_ornament_icon) { m_ProxyOrnamentIcon = proxy_ornament_icon; } - void SetProxyHash(int proxy_hash) { m_ProxyHash = proxy_hash; } + // mainly for saylinks..but, not limited to + void SetProxyUnknown1(uint8 proxy_unknown_1) { m_Proxy_unknown_1 = proxy_unknown_1; } + void SetProxyItemID(uint32 proxy_item_id) { m_ProxyItemID = proxy_item_id; } + void SetProxyAugment1ID(uint32 proxy_augment_id) { m_ProxyAugment1ID = proxy_augment_id; } + void SetProxyAugment2ID(uint32 proxy_augment_id) { m_ProxyAugment2ID = proxy_augment_id; } + void SetProxyAugment3ID(uint32 proxy_augment_id) { m_ProxyAugment3ID = proxy_augment_id; } + void SetProxyAugment4ID(uint32 proxy_augment_id) { m_ProxyAugment4ID = proxy_augment_id; } + void SetProxyAugment5ID(uint32 proxy_augment_id) { m_ProxyAugment5ID = proxy_augment_id; } + void SetProxyAugment6ID(uint32 proxy_augment_id) { m_ProxyAugment6ID = proxy_augment_id; } + void SetProxyIsEvolving(uint8 proxy_is_evolving) { m_ProxyIsEvolving = proxy_is_evolving; } + void SetProxyEvolveGroup(uint32 proxy_evolve_group) { m_ProxyEvolveGroup = proxy_evolve_group; } + void SetProxyEvolveLevel(uint8 proxy_evolve_level) { m_ProxyEvolveLevel = proxy_evolve_level; } + void SetProxyOrnamentIcon(uint32 proxy_ornament_icon) { m_ProxyOrnamentIcon = proxy_ornament_icon; } + void SetProxyHash(int proxy_hash) { m_ProxyHash = proxy_hash; } - void SetProxyText(const char* proxy_text) { m_ProxyText = proxy_text; } // overrides standard text use - void SetTaskUse() { m_TaskUse = true; } + void SetProxyText(const char* proxy_text) { m_ProxyText = proxy_text; } // overrides standard text use + void SetTaskUse() { m_TaskUse = true; } - std::string GenerateLink(); - bool LinkError() { return m_Error; } + std::string GenerateLink(); + bool LinkError() { return m_Error; } - std::string Link() { return m_Link; } // contains full string format: '/12x' '' '' '/12x' - std::string LinkBody() { return m_LinkBody; } // contains string format: '' - std::string LinkText() { return m_LinkText; } // contains string format: '' + std::string Link() { return m_Link; } // contains full string format: '/12x' '' '' '/12x' + std::string LinkBody() { return m_LinkBody; } // contains string format: '' + std::string LinkText() { return m_LinkText; } // contains string format: '' - void Reset(); + void Reset(); -private: - void generate_body(); - void generate_text(); + private: + void generate_body(); + void generate_text(); - int m_LinkType; - const EQEmu::ItemBase* m_ItemData; - const ServerLootItem_Struct* m_LootData; - const ItemInst* m_ItemInst; + int m_LinkType; + const ItemBase* m_ItemData; + const ServerLootItem_Struct* m_LootData; + const ItemInst* m_ItemInst; - uint8 m_Proxy_unknown_1; - uint32 m_ProxyItemID; - uint32 m_ProxyAugment1ID; - uint32 m_ProxyAugment2ID; - uint32 m_ProxyAugment3ID; - uint32 m_ProxyAugment4ID; - uint32 m_ProxyAugment5ID; - uint32 m_ProxyAugment6ID; - uint8 m_ProxyIsEvolving; - uint32 m_ProxyEvolveGroup; - uint8 m_ProxyEvolveLevel; - uint32 m_ProxyOrnamentIcon; - int m_ProxyHash; - const char* m_ProxyText; - bool m_TaskUse; - SayLinkBody_Struct m_LinkBodyStruct; - std::string m_Link; - std::string m_LinkBody; - std::string m_LinkText; - bool m_Error; -}; + uint8 m_Proxy_unknown_1; + uint32 m_ProxyItemID; + uint32 m_ProxyAugment1ID; + uint32 m_ProxyAugment2ID; + uint32 m_ProxyAugment3ID; + uint32 m_ProxyAugment4ID; + uint32 m_ProxyAugment5ID; + uint32 m_ProxyAugment6ID; + uint8 m_ProxyIsEvolving; + uint32 m_ProxyEvolveGroup; + uint8 m_ProxyEvolveLevel; + uint32 m_ProxyOrnamentIcon; + int m_ProxyHash; + const char* m_ProxyText; + bool m_TaskUse; + SayLinkBody_Struct m_LinkBodyStruct; + std::string m_Link; + std::string m_LinkBody; + std::string m_LinkText; + bool m_Error; + }; + +} /*EQEmu*/ #endif /*COMMON_SAY_LINK_H*/ diff --git a/common/skills.cpp b/common/skills.cpp index 1e6827490..9be28781f 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -17,7 +17,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "types.h" #include "skills.h" #include @@ -291,142 +290,9 @@ const std::map& EQEmu::skills::GetSkillTy return skill_type_map; } -struct EQEmu::SkillProfile // prototype - not implemented -{ - union { - struct { - uint32 _1HBlunt; - uint32 _1HSlashing; - uint32 _2HBlunt; - uint32 _2HSlashing; - uint32 Abjuration; - uint32 Alteration; - uint32 ApplyPoison; - uint32 Archery; - uint32 Backstab; - uint32 BindWound; - uint32 Bash; - uint32 Block; - uint32 BrassInstruments; - uint32 Channeling; - uint32 Conjuration; - uint32 Defense; - uint32 Disarm; - uint32 DisarmTraps; - uint32 Divination; - uint32 Dodge; - uint32 DoubleAttack; - union { - uint32 DragonPunch; - uint32 TailRake; - }; - uint32 DualWield; - uint32 EagleStrike; - uint32 Evocation; - uint32 FeignDeath; - uint32 FlyingKick; - uint32 Forage; - uint32 HandtoHand; - uint32 Hide; - uint32 Kick; - uint32 Meditate; - uint32 Mend; - uint32 Offense; - uint32 Parry; - uint32 PickLock; - uint32 _1HPiercing; - uint32 Riposte; - uint32 RoundKick; - uint32 SafeFall; - uint32 SenseHeading; - uint32 Singing; - uint32 Sneak; - uint32 SpecializeAbjure; - uint32 SpecializeAlteration; - uint32 SpecializeConjuration; - uint32 SpecializeDivination; - uint32 SpecializeEvocation; - uint32 PickPockets; - uint32 StringedInstruments; - uint32 Swimming; - uint32 Throwing; - uint32 TigerClaw; - uint32 Tracking; - uint32 WindInstruments; - uint32 Fishing; - uint32 MakePoison; - uint32 Tinkering; - uint32 Research; - uint32 Alchemy; - uint32 Baking; - uint32 Tailoring; - uint32 SenseTraps; - uint32 Blacksmithing; - uint32 Fletching; - uint32 Brewing; - uint32 AlcoholTolerance; - uint32 Begging; - uint32 JewelryMaking; - uint32 Pottery; - uint32 PercussionInstruments; - uint32 Intimidation; - uint32 Berserking; - uint32 Taunt; - uint32 Frenzy; - uint32 RemoveTraps; - uint32 TripleAttack; - uint32 _2HPiercing; - uint32 unused1; - uint32 unused2; - uint32 unused3; - uint32 unused4; - uint32 unused5; - uint32 unused6; - uint32 unused7; - uint32 unused8; - uint32 unused9; - uint32 unused10; - uint32 unused11; - uint32 unused12; - uint32 unused13; - uint32 unused14; - uint32 unused15; - uint32 unused16; - uint32 unused17; - uint32 unused18; - uint32 unused19; - uint32 unused20; - uint32 unused21; - uint32 unused22; - }; - uint32 skill[PACKET_SKILL_ARRAY_SIZE]; - }; - - SkillProfile(); - - uint32* GetSkills() { return reinterpret_cast(&skill); } - - skills::SkillType GetLastUseableSkill() { return EQEmu::skills::Skill2HPiercing; } - - size_t GetSkillsArraySize() { return PACKET_SKILL_ARRAY_SIZE; } - uint32 GetSkill(int skill_id); - - uint32 operator[](int skill_id) { return GetSkill(skill_id); } - - // const - uint32* GetSkills() const { return const_cast(this)->GetSkills(); } - - skills::SkillType GetLastUseableSkill() const { return const_cast(this)->GetLastUseableSkill(); } - - size_t GetSkillsArraySize() const { return const_cast(this)->GetSkillsArraySize(); } - uint32 GetSkill(int skill_id) const { return const_cast(this)->GetSkill(skill_id); } - - uint32 operator[](int skill_id) const { return const_cast(this)->GetSkill(skill_id); } -}; - EQEmu::SkillProfile::SkillProfile() { - memset(&skill, 0, (sizeof(uint32) * PACKET_SKILL_ARRAY_SIZE)); + memset(&Skill, 0, (sizeof(uint32) * PACKET_SKILL_ARRAY_SIZE)); } uint32 EQEmu::SkillProfile::GetSkill(int skill_id) @@ -434,5 +300,5 @@ uint32 EQEmu::SkillProfile::GetSkill(int skill_id) if (skill_id < 0 || skill_id >= PACKET_SKILL_ARRAY_SIZE) return 0; - return skill[skill_id]; + return Skill[skill_id]; } diff --git a/common/skills.h b/common/skills.h index af8f4a543..cd7603667 100644 --- a/common/skills.h +++ b/common/skills.h @@ -20,6 +20,8 @@ #ifndef COMMON_SKILLS_H #define COMMON_SKILLS_H +#include "types.h" + #include #include @@ -168,7 +170,137 @@ namespace EQEmu } /*skills*/ - struct SkillProfile; + struct SkillProfile { // prototype - not implemented + union { + struct { + uint32 _1HBlunt; + uint32 _1HSlashing; + uint32 _2HBlunt; + uint32 _2HSlashing; + uint32 Abjuration; + uint32 Alteration; + uint32 ApplyPoison; + uint32 Archery; + uint32 Backstab; + uint32 BindWound; + uint32 Bash; + uint32 Block; + uint32 BrassInstruments; + uint32 Channeling; + uint32 Conjuration; + uint32 Defense; + uint32 Disarm; + uint32 DisarmTraps; + uint32 Divination; + uint32 Dodge; + uint32 DoubleAttack; + union { + uint32 DragonPunch; + uint32 TailRake; + }; + uint32 DualWield; + uint32 EagleStrike; + uint32 Evocation; + uint32 FeignDeath; + uint32 FlyingKick; + uint32 Forage; + uint32 HandtoHand; + uint32 Hide; + uint32 Kick; + uint32 Meditate; + uint32 Mend; + uint32 Offense; + uint32 Parry; + uint32 PickLock; + uint32 _1HPiercing; + uint32 Riposte; + uint32 RoundKick; + uint32 SafeFall; + uint32 SenseHeading; + uint32 Singing; + uint32 Sneak; + uint32 SpecializeAbjure; + uint32 SpecializeAlteration; + uint32 SpecializeConjuration; + uint32 SpecializeDivination; + uint32 SpecializeEvocation; + uint32 PickPockets; + uint32 StringedInstruments; + uint32 Swimming; + uint32 Throwing; + uint32 TigerClaw; + uint32 Tracking; + uint32 WindInstruments; + uint32 Fishing; + uint32 MakePoison; + uint32 Tinkering; + uint32 Research; + uint32 Alchemy; + uint32 Baking; + uint32 Tailoring; + uint32 SenseTraps; + uint32 Blacksmithing; + uint32 Fletching; + uint32 Brewing; + uint32 AlcoholTolerance; + uint32 Begging; + uint32 JewelryMaking; + uint32 Pottery; + uint32 PercussionInstruments; + uint32 Intimidation; + uint32 Berserking; + uint32 Taunt; + uint32 Frenzy; + uint32 RemoveTraps; + uint32 TripleAttack; + uint32 _2HPiercing; + uint32 unused1; + uint32 unused2; + uint32 unused3; + uint32 unused4; + uint32 unused5; + uint32 unused6; + uint32 unused7; + uint32 unused8; + uint32 unused9; + uint32 unused10; + uint32 unused11; + uint32 unused12; + uint32 unused13; + uint32 unused14; + uint32 unused15; + uint32 unused16; + uint32 unused17; + uint32 unused18; + uint32 unused19; + uint32 unused20; + uint32 unused21; + uint32 unused22; + }; + uint32 Skill[PACKET_SKILL_ARRAY_SIZE]; + }; + + SkillProfile(); + + uint32* GetSkills() { return reinterpret_cast(&Skill); } + + skills::SkillType GetLastUseableSkill() { return EQEmu::skills::Skill2HPiercing; } + + size_t GetSkillsArraySize() { return PACKET_SKILL_ARRAY_SIZE; } + uint32 GetSkill(int skill_id); + + uint32 operator[](int skill_id) { return GetSkill(skill_id); } + + // const + uint32* GetSkills() const { return const_cast(this)->GetSkills(); } + + skills::SkillType GetLastUseableSkill() const { return const_cast(this)->GetLastUseableSkill(); } + + size_t GetSkillsArraySize() const { return const_cast(this)->GetSkillsArraySize(); } + uint32 GetSkill(int skill_id) const { return const_cast(this)->GetSkill(skill_id); } + + uint32 operator[](int skill_id) const { return const_cast(this)->GetSkill(skill_id); } + }; } /*EQEmu*/ diff --git a/zone/bot.cpp b/zone/bot.cpp index 9975881f3..e5a5d3673 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -8463,8 +8463,8 @@ std::string Bot::CreateSayLink(Client* c, const char* message, const char* name) uint32 saylink_id = database.LoadSaylinkID(escaped_string); safe_delete_array(escaped_string); - EQEmu::saylink::SayLinkEngine linker; - linker.SetLinkType(linker.SayLinkItemData); + EQEmu::SayLinkEngine linker; + linker.SetLinkType(EQEmu::saylink::SayLinkItemData); linker.SetProxyItemID(SAYLINK_ITEM_ID); linker.SetProxyAugment1ID(saylink_id); linker.SetProxyText(name); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index a413dfed2..46173e5ec 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -7067,8 +7067,8 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) bool is2Hweapon = false; std::string item_link; - EQEmu::saylink::SayLinkEngine linker; - linker.SetLinkType(linker.SayLinkItemInst); + EQEmu::SayLinkEngine linker; + linker.SetLinkType(EQEmu::saylink::SayLinkItemInst); uint32 inventory_count = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { diff --git a/zone/command.cpp b/zone/command.cpp index 4b7c6e929..6c4ab90bf 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2548,8 +2548,8 @@ void command_peekinv(Client *c, const Seperator *sep) const ItemInst* inst_sub = nullptr; const EQEmu::ItemBase* item_data = nullptr; std::string item_link; - EQEmu::saylink::SayLinkEngine linker; - linker.SetLinkType(linker.SayLinkItemInst); + EQEmu::SayLinkEngine linker; + linker.SetLinkType(EQEmu::saylink::SayLinkItemInst); c->Message(0, "Displaying inventory for %s...", targetClient->GetName()); @@ -4346,8 +4346,8 @@ void command_iteminfo(Client *c, const Seperator *sep) c->Message(13, "Error: This item has no data reference"); } - EQEmu::saylink::SayLinkEngine linker; - linker.SetLinkType(linker.SayLinkItemInst); + EQEmu::SayLinkEngine linker; + linker.SetLinkType(EQEmu::saylink::SayLinkItemInst); linker.SetItemInst(inst); auto item_link = linker.GenerateLink(); @@ -5497,7 +5497,7 @@ void command_summonitem(Client *c, const Seperator *sep) size_t link_open = cmd_msg.find('\x12'); size_t link_close = cmd_msg.find_last_of('\x12'); if (link_open != link_close && (cmd_msg.length() - link_open) > EQEmu::legacy::TEXT_LINK_BODY_LENGTH) { - EQEmu::saylink::SayLinkBody_Struct link_body; + EQEmu::SayLinkBody_Struct link_body; EQEmu::saylink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EQEmu::legacy::TEXT_LINK_BODY_LENGTH)); itemid = link_body.item_id; } @@ -5608,8 +5608,8 @@ void command_itemsearch(Client *c, const Seperator *sep) const EQEmu::ItemBase* item = nullptr; std::string item_link; - EQEmu::saylink::SayLinkEngine linker; - linker.SetLinkType(linker.SayLinkItemData); + EQEmu::SayLinkEngine linker; + linker.SetLinkType(EQEmu::saylink::SayLinkItemData); if (Seperator::IsNumber(search_criteria)) { item = database.GetItem(atoi(search_criteria)); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 48bd46fed..329c5c40e 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1223,8 +1223,8 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } /* Send message with item link to groups and such */ - EQEmu::saylink::SayLinkEngine linker; - linker.SetLinkType(linker.SayLinkItemInst); + EQEmu::SayLinkEngine linker; + linker.SetLinkType(EQEmu::saylink::SayLinkItemInst); linker.SetItemInst(inst); auto item_link = linker.GenerateLink(); diff --git a/zone/npc.cpp b/zone/npc.cpp index d38ad92b3..a965bfad0 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -530,8 +530,8 @@ void NPC::QueryLoot(Client* to) continue; } - EQEmu::saylink::SayLinkEngine linker; - linker.SetLinkType(linker.SayLinkItemData); + EQEmu::SayLinkEngine linker; + linker.SetLinkType(EQEmu::saylink::SayLinkItemData); linker.SetItemData(item); auto item_link = linker.GenerateLink(); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 15f651763..fdd9c3df2 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1309,8 +1309,8 @@ void QuestManager::itemlink(int item_id) { if (item == nullptr) return; - EQEmu::saylink::SayLinkEngine linker; - linker.SetLinkType(linker.SayLinkItemData); + EQEmu::SayLinkEngine linker; + linker.SetLinkType(EQEmu::saylink::SayLinkItemData); linker.SetItemData(item); auto item_link = linker.GenerateLink(); @@ -2537,8 +2537,8 @@ const char* QuestManager::varlink(char* perltext, int item_id) { if (!item) return "INVALID ITEM ID IN VARLINK"; - EQEmu::saylink::SayLinkEngine linker; - linker.SetLinkType(linker.SayLinkItemData); + EQEmu::SayLinkEngine linker; + linker.SetLinkType(EQEmu::saylink::SayLinkItemData); linker.SetItemData(item); auto item_link = linker.GenerateLink(); @@ -2763,7 +2763,7 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam safe_delete_array(escaped_string); //Create the say link as an item link hash - EQEmu::saylink::SayLinkEngine linker; + EQEmu::SayLinkEngine linker; linker.SetProxyItemID(SAYLINK_ITEM_ID); if (silent) linker.SetProxyAugment2ID(sayid); diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 1dbdcab11..97368db77 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -2778,8 +2778,8 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN if(ItemID) { const EQEmu::ItemBase* reward_item = database.GetItem(ItemID); - EQEmu::saylink::SayLinkEngine linker; - linker.SetLinkType(linker.SayLinkItemData); + EQEmu::SayLinkEngine linker; + linker.SetLinkType(EQEmu::saylink::SayLinkItemData); linker.SetItemData(reward_item); linker.SetTaskUse(); if (strlen(Tasks[TaskID]->Reward) != 0) From 0f54984966bf6afdc2f6891630fdebf12a0b0a56 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 31 May 2016 01:52:51 -0400 Subject: [PATCH 137/693] Missed a few out of my working stash... --- common/light_source.cpp | 2 +- common/patches/rof2_limits.h | 3 +-- common/patches/rof_limits.h | 3 +-- common/patches/sod_limits.h | 3 +-- common/patches/sof_limits.h | 3 +-- common/patches/titanium_limits.h | 3 +-- common/patches/uf_limits.h | 3 +-- 7 files changed, 7 insertions(+), 13 deletions(-) diff --git a/common/light_source.cpp b/common/light_source.cpp index 939676ee0..476f315b8 100644 --- a/common/light_source.cpp +++ b/common/light_source.cpp @@ -89,7 +89,7 @@ EQEmu::LightSource_Struct::LightSource_Struct() void EQEmu::LightSource_Struct::Clear() { - memset(&Slot, 0, (sizeof(uint8) * sizeof(Slot))); + memset(&Slot, 0, (sizeof(uint8) * lightsource::LightCount)); } void EQEmu::LightSourceProfile::Clear() diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index 2320c1393..605073ad7 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -228,8 +228,6 @@ namespace RoF2 const size_t InvTypeKronoSize = 0;//unknown const size_t InvTypeOtherSize = 0;//unknown - const size_t NPCTradeSize = 4; - extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); @@ -261,6 +259,7 @@ namespace RoF2 namespace profile { const size_t TributeSize = invtype::InvTypeTributeSize; + const size_t GuildTributeSize = invtype::InvTypeGuildTributeSize; const size_t BandoliersSize = 20; // number of bandolier instances const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index 94e55a47a..765d61c00 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -219,8 +219,6 @@ namespace RoF const size_t InvTypeGuildTrophyTributeSize = 0;//unknown const size_t InvTypeOtherSize = 0;//unknown - const size_t NPCTradeSize = 4; - extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); @@ -252,6 +250,7 @@ namespace RoF namespace profile { const size_t TributeSize = invtype::InvTypeTributeSize; + const size_t GuildTributeSize = invtype::InvTypeGuildTributeSize; const size_t BandoliersSize = 20; // number of bandolier instances const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index 48d56cfab..430ae5b21 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -203,8 +203,6 @@ namespace SoD const size_t InvTypeArchivedSize = 0;//unknown const size_t InvTypeOtherSize = 0;//unknown - const size_t NPCTradeSize = 4; - extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); @@ -279,6 +277,7 @@ namespace SoD namespace profile { const size_t TributeSize = invtype::InvTypeTributeSize; + const size_t GuildTributeSize = invtype::InvTypeGuildTributeSize; const size_t BandoliersSize = 20; // number of bandolier instances const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 42033b2f6..0317fd72a 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -203,8 +203,6 @@ namespace SoF const size_t InvTypeArchivedSize = 0;//unknown const size_t InvTypeOtherSize = 0;//unknown - const size_t NPCTradeSize = 4; - extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); @@ -279,6 +277,7 @@ namespace SoF namespace profile { const size_t TributeSize = invtype::InvTypeTributeSize; + const size_t GuildTributeSize = invtype::InvTypeGuildTributeSize; const size_t BandoliersSize = 20; // number of bandolier instances const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index 51651ea38..643b75be7 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -202,8 +202,6 @@ namespace Titanium const size_t InvTypeArchivedSize = 0;//unknown const size_t InvTypeOtherSize = 0;//unknown - const size_t NPCTradeSize = 4; - extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); @@ -278,6 +276,7 @@ namespace Titanium namespace profile { const size_t TributeSize = invtype::InvTypeTributeSize; + const size_t GuildTributeSize = invtype::InvTypeGuildTributeSize; const size_t BandoliersSize = 4; // number of bandolier instances const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index b71937fa6..e199899dd 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -204,8 +204,6 @@ namespace UF const size_t InvTypeArchivedSize = 0;//unknown const size_t InvTypeOtherSize = 0;//unknown - const size_t NPCTradeSize = 4; - extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); @@ -280,6 +278,7 @@ namespace UF namespace profile { const size_t TributeSize = invtype::InvTypeTributeSize; + const size_t GuildTributeSize = invtype::InvTypeGuildTributeSize; const size_t BandoliersSize = 20; // number of bandolier instances const size_t BandolierItemCount = 4; // number of equipment slots in bandolier instance From a38417bf5442953f7fd22acf32ebae37c7645d8f Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 31 May 2016 19:12:54 -0400 Subject: [PATCH 138/693] More eq_dictionary work - added invtype persistence checks --- common/patches/rof2_limits.cpp | 18 ++++++++++++++++++ common/patches/rof2_limits.h | 2 ++ common/patches/rof_limits.cpp | 18 ++++++++++++++++++ common/patches/rof_limits.h | 2 ++ common/patches/sod_limits.cpp | 17 +++++++++++++++++ common/patches/sod_limits.h | 2 ++ common/patches/sof_limits.cpp | 17 +++++++++++++++++ common/patches/sof_limits.h | 2 ++ common/patches/titanium_limits.cpp | 17 +++++++++++++++++ common/patches/titanium_limits.h | 2 ++ common/patches/uf_limits.cpp | 17 +++++++++++++++++ common/patches/uf_limits.h | 2 ++ 12 files changed, 116 insertions(+) diff --git a/common/patches/rof2_limits.cpp b/common/patches/rof2_limits.cpp index c515e2512..85e15e21d 100644 --- a/common/patches/rof2_limits.cpp +++ b/common/patches/rof2_limits.cpp @@ -140,6 +140,24 @@ const char* RoF2::invtype::GetInvTypeName(int inv_type) } } +bool RoF2::invtype::IsInvTypePersistent(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + case invtype::InvTypeBank: + case invtype::InvTypeSharedBank: + case invtype::InvTypeTrade: + case invtype::InvTypeWorld: + case invtype::InvTypeLimbo: + case invtype::InvTypeTribute: + case invtype::InvTypeTrophyTribute: + case invtype::InvTypeGuildTribute: + return true; + default: + return false; + } +} + const char* RoF2::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index 605073ad7..fb2f997ca 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -231,6 +231,8 @@ namespace RoF2 extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); + extern bool IsInvTypePersistent(int inv_type); + } /*invtype*/ namespace invslot { diff --git a/common/patches/rof_limits.cpp b/common/patches/rof_limits.cpp index 48639d52c..c78ffc59d 100644 --- a/common/patches/rof_limits.cpp +++ b/common/patches/rof_limits.cpp @@ -136,6 +136,24 @@ const char* RoF::invtype::GetInvTypeName(int inv_type) } } +bool RoF::invtype::IsInvTypePersistent(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + case invtype::InvTypeBank: + case invtype::InvTypeSharedBank: + case invtype::InvTypeTrade: + case invtype::InvTypeWorld: + case invtype::InvTypeLimbo: + case invtype::InvTypeTribute: + case invtype::InvTypeTrophyTribute: + case invtype::InvTypeGuildTribute: + return true; + default: + return false; + } +} + const char* RoF::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index 765d61c00..ed0b9a6d0 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -222,6 +222,8 @@ namespace RoF extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); + extern bool IsInvTypePersistent(int inv_type); + } /*invtype*/ namespace invslot { diff --git a/common/patches/sod_limits.cpp b/common/patches/sod_limits.cpp index 7991801e3..8ff257665 100644 --- a/common/patches/sod_limits.cpp +++ b/common/patches/sod_limits.cpp @@ -116,6 +116,23 @@ const char* SoD::invtype::GetInvTypeName(int inv_type) } } +bool SoD::invtype::IsInvTypePersistent(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + case invtype::InvTypeBank: + case invtype::InvTypeSharedBank: + case invtype::InvTypeTrade: + case invtype::InvTypeWorld: + case invtype::InvTypeLimbo: + case invtype::InvTypeTribute: + case invtype::InvTypeGuildTribute: + return true; + default: + return false; + } +} + const char* SoD::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index 430ae5b21..fa2c29317 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -206,6 +206,8 @@ namespace SoD extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); + extern bool IsInvTypePersistent(int inv_type); + } /*invtype*/ namespace invslot { diff --git a/common/patches/sof_limits.cpp b/common/patches/sof_limits.cpp index 7b7cc408b..b33943905 100644 --- a/common/patches/sof_limits.cpp +++ b/common/patches/sof_limits.cpp @@ -116,6 +116,23 @@ const char* SoF::invtype::GetInvTypeName(int inv_type) } } +bool SoF::invtype::IsInvTypePersistent(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + case invtype::InvTypeBank: + case invtype::InvTypeSharedBank: + case invtype::InvTypeTrade: + case invtype::InvTypeWorld: + case invtype::InvTypeLimbo: + case invtype::InvTypeTribute: + case invtype::InvTypeGuildTribute: + return true; + default: + return false; + } +} + const char* SoF::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 0317fd72a..575df39ba 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -206,6 +206,8 @@ namespace SoF extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); + extern bool IsInvTypePersistent(int inv_type); + } /*invtype*/ namespace invslot { diff --git a/common/patches/titanium_limits.cpp b/common/patches/titanium_limits.cpp index fba7db270..3976e8217 100644 --- a/common/patches/titanium_limits.cpp +++ b/common/patches/titanium_limits.cpp @@ -116,6 +116,23 @@ const char* Titanium::invtype::GetInvTypeName(int inv_type) } } +bool Titanium::invtype::IsInvTypePersistent(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + case invtype::InvTypeBank: + case invtype::InvTypeSharedBank: + case invtype::InvTypeTrade: + case invtype::InvTypeWorld: + case invtype::InvTypeLimbo: + case invtype::InvTypeTribute: + case invtype::InvTypeGuildTribute: + return true; + default: + return false; + } +} + const char* Titanium::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index 643b75be7..e631f8492 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -205,6 +205,8 @@ namespace Titanium extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); + extern bool IsInvTypePersistent(int inv_type); + } /*invtype*/ namespace invslot { diff --git a/common/patches/uf_limits.cpp b/common/patches/uf_limits.cpp index 28a1d7c3f..ae415ddd8 100644 --- a/common/patches/uf_limits.cpp +++ b/common/patches/uf_limits.cpp @@ -116,6 +116,23 @@ const char* UF::invtype::GetInvTypeName(int inv_type) } } +bool UF::invtype::IsInvTypePersistent(int inv_type) +{ + switch (inv_type) { + case invtype::InvTypePossessions: + case invtype::InvTypeBank: + case invtype::InvTypeSharedBank: + case invtype::InvTypeTrade: + case invtype::InvTypeWorld: + case invtype::InvTypeLimbo: + case invtype::InvTypeTribute: + case invtype::InvTypeGuildTribute: + return true; + default: + return false; + } +} + const char* UF::invslot::GetInvPossessionsSlotName(int inv_slot) { switch (inv_slot) { diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index e199899dd..2e799ac0c 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -206,6 +206,8 @@ namespace UF extern size_t GetInvTypeSize(int inv_type); extern const char* GetInvTypeName(int inv_type); + + extern bool IsInvTypePersistent(int inv_type); } /*invtype*/ From ea8f81feecbd02129e75ee03ff471ff6a1631436 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 31 May 2016 22:07:02 -0400 Subject: [PATCH 139/693] Converted enumeration MaterialSlots to EQEmu::textures::TextureSlot --- changelog.txt | 3 + common/CMakeLists.txt | 2 + common/database_conversions.cpp | 8 +-- common/emu_legacy.h | 19 ------ common/eq_packet_structs.h | 15 +++-- common/extprofile.h | 2 +- common/item.cpp | 38 +++++------ common/patches/rof.cpp | 6 +- common/patches/rof2.cpp | 6 +- common/patches/rof2_structs.h | 6 +- common/patches/sod.cpp | 6 +- common/patches/sof.cpp | 2 +- common/patches/titanium.cpp | 8 +-- common/patches/uf.cpp | 10 +-- common/textures.cpp | 109 ++++++++++++++++++++++++++++++++ common/textures.h | 61 ++++++++++++++++++ world/worlddb.cpp | 6 +- zone/attack.cpp | 2 +- zone/bot.cpp | 26 ++++---- zone/bot_command.cpp | 6 +- zone/client.cpp | 42 ++++++------ zone/client_packet.cpp | 8 +-- zone/command.cpp | 6 +- zone/corpse.cpp | 6 +- zone/inventory.cpp | 10 +-- zone/loottables.cpp | 18 +++--- zone/lua_general.cpp | 26 ++++---- zone/merc.cpp | 4 +- zone/mob.cpp | 8 +-- zone/mob.h | 6 +- zone/npc.cpp | 22 +++---- zone/spell_effects.cpp | 6 +- zone/zonedb.cpp | 8 +-- zone/zonedump.h | 2 +- 34 files changed, 335 insertions(+), 178 deletions(-) create mode 100644 common/textures.cpp create mode 100644 common/textures.h diff --git a/changelog.txt b/changelog.txt index d5ec9f62a..e5e33b2a0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 05/31/2016 == +Uleat: Converted enumeration MaterialSlots to EQEmu::textures::TextureSlot + == 05/28/2016 == Uleat: Merged client_version and inventory_version into emu_versions files diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index fa9e6b342..3ed2862ce 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -68,6 +68,7 @@ SET(common_sources struct_strategy.cpp tcp_connection.cpp tcp_server.cpp + textures.cpp timeoutmgr.cpp timer.cpp unix.cpp @@ -199,6 +200,7 @@ SET(common_headers tcp_basic_server.h tcp_connection.h tcp_server.h + textures.h timeoutmgr.h timer.h types.h diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index 058c3ad2c..f6fd6c04a 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -186,7 +186,7 @@ namespace Convert { /*002*/ uint32 HP; /*006*/ uint32 Mana; /*010*/ Convert::SpellBuff_Struct Buffs[BUFF_COUNT]; - /*510*/ uint32 Items[EQEmu::legacy::MaterialCount]; + /*510*/ uint32 Items[EQEmu::textures::TextureCount]; /*546*/ char Name[64]; /*610*/ }; @@ -227,9 +227,9 @@ namespace Convert { /*0304*/ uint8 ability_time_minutes; /*0305*/ uint8 ability_time_hours; //place holder /*0306*/ uint8 unknown0306[6]; // @bp Spacer/Flag? - /*0312*/ uint32 item_material[EQEmu::legacy::MaterialCount]; // Item texture/material of worn/held items + /*0312*/ uint32 item_material[EQEmu::textures::TextureCount]; // Item texture/material of worn/held items /*0348*/ uint8 unknown0348[44]; - /*0392*/ Convert::Color_Struct item_tint[EQEmu::legacy::MaterialCount]; + /*0392*/ Convert::Color_Struct item_tint[EQEmu::textures::TextureCount]; /*0428*/ Convert::AA_Array aa_array[MAX_PP_AA_ARRAY]; /*2348*/ float unknown2384; //seen ~128, ~47 /*2352*/ char servername[32]; // length probably not right @@ -1416,7 +1416,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){ if (rquery != ""){ results = QueryDatabase(rquery); } /* Run Material Color Convert */ first_entry = 0; rquery = ""; - for (i = 0; i < EQEmu::legacy::MaterialCount; i++){ + for (i = 0; i < EQEmu::textures::TextureCount; i++){ if (pp->item_tint[i].color > 0){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); diff --git a/common/emu_legacy.h b/common/emu_legacy.h index f8d4ea6b4..98829eae4 100644 --- a/common/emu_legacy.h +++ b/common/emu_legacy.h @@ -163,20 +163,6 @@ namespace EQEmu SlotCount }; - enum MaterialSlots : uint8 { - MaterialHead = 0, - MaterialChest, - MaterialArms, - MaterialWrist, - MaterialHands, - MaterialLegs, // 5 - MaterialFeet, - MaterialPrimary, - MaterialSecondary, - MaterialCount, - MaterialInvalid = 255 - }; - // these are currently hard-coded for existing inventory system..do not use in place of special client version handlers until ready static const uint16 TYPE_POSSESSIONS_SIZE = SlotCount; static const uint16 TYPE_BANK_SIZE = 24; @@ -251,11 +237,6 @@ namespace EQEmu static const int16 CORPSE_BEGIN = 22; //static const int16 CORPSE_END = RoF::consts::CORPSE_END; // not ready for use - static const int16 MATERIAL_BEGIN = MaterialHead; - static const int16 MATERIAL_END = MaterialSecondary; - static const int16 MATERIAL_TINT_END = MaterialFeet; - static const int16 MATERIAL_SIZE = MaterialCount; - // items // common and container sizes will not increase until the new 'location' struct is implemented static const uint16 ITEM_COMMON_SIZE = 6;//RoF::consts::ITEM_COMMON_SIZE; diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index e94264b34..5ca9b530d 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -26,6 +26,7 @@ #include #include "../common/version.h" #include "emu_constants.h" +#include "textures.h" static const uint32 BUFF_COUNT = 25; @@ -293,7 +294,7 @@ struct Spawn_Struct { /*0000*/ EquipStruct equip_primary; // Equipment: Main visual /*0000*/ EquipStruct equip_secondary; // Equipment: Off visual } equip; - /*0000*/ EquipStruct equipment[EQEmu::legacy::MaterialCount]; + /*0000*/ EquipStruct equipment[EQEmu::textures::TextureCount]; }; /*0233*/ float runspeed; // Speed when running /*0036*/ uint8 afk; // 0=no, 1=afk @@ -339,7 +340,7 @@ union /*0376*/ Color_Struct color_primary; // Color of primary item /*0380*/ Color_Struct color_secondary; // Color of secondary item } equipment_colors; - /*0348*/ Color_Struct colors[EQEmu::legacy::MaterialCount]; // Array elements correspond to struct equipment_colors above + /*0348*/ Color_Struct colors[EQEmu::textures::TextureCount]; // Array elements correspond to struct equipment_colors above }; /*0384*/ uint8 lfg; // 0=off, 1=lfg on /*0385*/ @@ -881,7 +882,7 @@ struct SuspendedMinion_Struct /*002*/ uint32 HP; /*006*/ uint32 Mana; /*010*/ SpellBuff_Struct Buffs[BUFF_COUNT]; - /*510*/ uint32 Items[EQEmu::legacy::MaterialCount]; + /*510*/ uint32 Items[EQEmu::textures::TextureCount]; /*546*/ char Name[64]; /*610*/ }; @@ -989,9 +990,9 @@ struct PlayerProfile_Struct /*0304*/ uint8 ability_time_minutes; /*0305*/ uint8 ability_time_hours; //place holder /*0306*/ uint8 unknown0306[6]; // @bp Spacer/Flag? -/*0312*/ uint32 item_material[EQEmu::legacy::MaterialCount]; // Item texture/material of worn/held items +/*0312*/ uint32 item_material[EQEmu::textures::TextureCount]; // Item texture/material of worn/held items /*0348*/ uint8 unknown0348[44]; -/*0392*/ Color_Struct item_tint[EQEmu::legacy::MaterialCount]; +/*0392*/ Color_Struct item_tint[EQEmu::textures::TextureCount]; /*0428*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; /*2348*/ float unknown2384; //seen ~128, ~47 /*2352*/ char servername[32]; // length probably not right @@ -2145,7 +2146,7 @@ struct Illusion_Struct { //size: 256 - SoF /*092*/ uint32 drakkin_heritage; // /*096*/ uint32 drakkin_tattoo; // /*100*/ uint32 drakkin_details; // -/*104*/ uint32 armor_tint[EQEmu::legacy::MaterialCount]; // +/*104*/ uint32 armor_tint[EQEmu::textures::TextureCount]; // /*140*/ uint8 eyecolor1; // Field Not Identified in any Illusion Struct /*141*/ uint8 eyecolor2; // Field Not Identified in any Illusion Struct /*142*/ uint8 unknown138[114]; // @@ -3432,7 +3433,7 @@ struct DyeStruct struct Color_Struct secondary; // or this } dyes; - struct Color_Struct dye[EQEmu::legacy::MaterialCount]; + struct Color_Struct dye[EQEmu::textures::TextureCount]; }; }; diff --git a/common/extprofile.h b/common/extprofile.h index 9713c2e60..b376a9edd 100644 --- a/common/extprofile.h +++ b/common/extprofile.h @@ -40,7 +40,7 @@ struct ExtendedProfile_Struct { uint16 old_pet_hp; /* Not Used */ uint16 old_pet_mana; /* Not Used */ SpellBuff_Struct pet_buffs[BUFF_COUNT]; /* Not Used */ - uint32 pet_items[EQEmu::legacy::MaterialCount]; /* Not Used */ + uint32 pet_items[EQEmu::textures::TextureCount]; /* Not Used */ char merc_name[64]; /* Used */ uint32 aa_effects; /* Used */ diff --git a/common/item.cpp b/common/item.cpp index 7437c9339..ae0de2795 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -852,23 +852,23 @@ int16 Inventory::CalcSlotFromMaterial(uint8 material) { switch (material) { - case EQEmu::legacy::MaterialHead: + case EQEmu::textures::TextureHead: return EQEmu::legacy::SlotHead; - case EQEmu::legacy::MaterialChest: + case EQEmu::textures::TextureChest: return EQEmu::legacy::SlotChest; - case EQEmu::legacy::MaterialArms: + case EQEmu::textures::TextureArms: return EQEmu::legacy::SlotArms; - case EQEmu::legacy::MaterialWrist: + case EQEmu::textures::TextureWrist: return EQEmu::legacy::SlotWrist1; // there's 2 bracers, only one bracer material - case EQEmu::legacy::MaterialHands: + case EQEmu::textures::TextureHands: return EQEmu::legacy::SlotHands; - case EQEmu::legacy::MaterialLegs: + case EQEmu::textures::TextureLegs: return EQEmu::legacy::SlotLegs; - case EQEmu::legacy::MaterialFeet: + case EQEmu::textures::TextureFeet: return EQEmu::legacy::SlotFeet; - case EQEmu::legacy::MaterialPrimary: + case EQEmu::textures::TexturePrimary: return EQEmu::legacy::SlotPrimary; - case EQEmu::legacy::MaterialSecondary: + case EQEmu::textures::TextureSecondary: return EQEmu::legacy::SlotSecondary; default: return INVALID_INDEX; @@ -880,26 +880,26 @@ uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) switch (equipslot) { case EQEmu::legacy::SlotHead: - return EQEmu::legacy::MaterialHead; + return EQEmu::textures::TextureHead; case EQEmu::legacy::SlotChest: - return EQEmu::legacy::MaterialChest; + return EQEmu::textures::TextureChest; case EQEmu::legacy::SlotArms: - return EQEmu::legacy::MaterialArms; + return EQEmu::textures::TextureArms; case EQEmu::legacy::SlotWrist1: //case SLOT_BRACER02: // non-live behavior - return EQEmu::legacy::MaterialWrist; + return EQEmu::textures::TextureWrist; case EQEmu::legacy::SlotHands: - return EQEmu::legacy::MaterialHands; + return EQEmu::textures::TextureHands; case EQEmu::legacy::SlotLegs: - return EQEmu::legacy::MaterialLegs; + return EQEmu::textures::TextureLegs; case EQEmu::legacy::SlotFeet: - return EQEmu::legacy::MaterialFeet; + return EQEmu::textures::TextureFeet; case EQEmu::legacy::SlotPrimary: - return EQEmu::legacy::MaterialPrimary; + return EQEmu::textures::TexturePrimary; case EQEmu::legacy::SlotSecondary: - return EQEmu::legacy::MaterialSecondary; + return EQEmu::textures::TextureSecondary; default: - return EQEmu::legacy::MaterialInvalid; + return EQEmu::textures::TextureInvalid; } } diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index edad92dfb..11531d8ae 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3046,7 +3046,7 @@ namespace RoF eq_cse->Gender = emu_cse->Gender; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < EQEmu::legacy::MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -4110,13 +4110,13 @@ namespace RoF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialPrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TexturePrimary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TextureSecondary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 75329b8bb..0ee12ebd8 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3139,7 +3139,7 @@ namespace RoF2 eq_cse->Gender = emu_cse->Gender; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < EQEmu::legacy::MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -4333,13 +4333,13 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialPrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TexturePrimary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TextureSecondary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 3f7130f1b..6a7056902 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1105,11 +1105,11 @@ union /*00184*/ EquipStruct equipment[22]; // Total Slots }; /*00624*/ uint32 equip2_count; // Seen 9 -/*00628*/ EquipStruct equipment2[EQEmu::legacy::MaterialCount]; // Appears to be Visible slots, but all 0s +/*00628*/ EquipStruct equipment2[EQEmu::textures::TextureCount]; // Appears to be Visible slots, but all 0s /*00808*/ uint32 tint_count; // Seen 9 -/*00812*/ Color_Struct item_tint[EQEmu::legacy::MaterialCount]; // RR GG BB 00 +/*00812*/ Color_Struct item_tint[EQEmu::textures::TextureCount]; // RR GG BB 00 /*00848*/ uint32 tint_count2; // Seen 9 -/*00852*/ Color_Struct item_tint2[EQEmu::legacy::MaterialCount]; // RR GG BB 00 +/*00852*/ Color_Struct item_tint2[EQEmu::textures::TextureCount]; // RR GG BB 00 /*00888*/ uint8 haircolor; // Player hair color /*00889*/ uint8 beardcolor; // Player beard color /*00890*/ uint32 unknown_rof5; // diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 4be952131..57549f240 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1993,7 +1993,7 @@ namespace SoD eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < EQEmu::legacy::MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -2773,11 +2773,11 @@ namespace SoD VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialPrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TexturePrimary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TextureSecondary].Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); } diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 877489676..50a3bb51f 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1649,7 +1649,7 @@ namespace SoF eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < EQEmu::legacy::MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 5d3ae0318..cee33cb8e 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1223,14 +1223,14 @@ namespace Titanium if (eq->Race[char_index] > 473) eq->Race[char_index] = 1; - for (int index = 0; index < EQEmu::legacy::MaterialCount; ++index) { + for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { eq->CS_Colors[char_index][index].Color = emu_cse->Equip[index].Color.Color; } eq->BeardColor[char_index] = emu_cse->BeardColor; eq->HairStyle[char_index] = emu_cse->HairStyle; - for (int index = 0; index < EQEmu::legacy::MaterialCount; ++index) { + for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { eq->Equip[char_index][index] = emu_cse->Equip[index].Material; } @@ -1260,14 +1260,14 @@ namespace Titanium for (; char_index < 10; ++char_index) { eq->Race[char_index] = 0; - for (int index = 0; index < EQEmu::legacy::MaterialCount; ++index) { + for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { eq->CS_Colors[char_index][index].Color = 0; } eq->BeardColor[char_index] = 0; eq->HairStyle[char_index] = 0; - for (int index = 0; index < EQEmu::legacy::MaterialCount; ++index) { + for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { eq->Equip[char_index][index] = 0; } diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 89199dee9..2a9a4862a 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2290,7 +2290,7 @@ namespace UF eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < EQEmu::legacy::MaterialCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; @@ -3070,19 +3070,19 @@ namespace UF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - if (emu->equipment[EQEmu::legacy::MaterialPrimary].Material > 99999) { + if (emu->equipment[EQEmu::textures::TexturePrimary].Material > 99999) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63); } else { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialPrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TexturePrimary].Material); } VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - if (emu->equipment[EQEmu::legacy::MaterialSecondary].Material > 99999) { + if (emu->equipment[EQEmu::textures::TextureSecondary].Material > 99999) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63); } else { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::legacy::MaterialSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TextureSecondary].Material); } VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); diff --git a/common/textures.cpp b/common/textures.cpp new file mode 100644 index 000000000..424255341 --- /dev/null +++ b/common/textures.cpp @@ -0,0 +1,109 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "textures.h" +//#include "inventory_slot.h" + +#include // temp + + +//int EQEmu::textures::ConvertEquipmentSlotToTextureSlot(int equipment_slot) +//{ +// switch (equipment_slot) { +// case inventory::PossessionsHead: +// return textures::TextureHead; +// case inventory::PossessionsChest: +// return textures::TextureChest; +// case inventory::PossessionsArms: +// return textures::TextureArms; +// case inventory::PossessionsWrist1: +// return textures::TextureWrist; +// case inventory::PossessionsHands: +// return textures::TextureHands; +// case inventory::PossessionsLegs: +// return textures::TextureLegs; +// case inventory::PossessionsFeet: +// return textures::TextureFeet; +// case inventory::PossessionsPrimary: +// return textures::TexturePrimary; +// case inventory::PossessionsSecondary: +// return textures::TextureSecondary; +// default: +// return textures::TextureInvalid; +// } +//} + +//int EQEmu::textures::ConvertEquipmentSlotToTextureSlot(const InventorySlot &equipment_slot) +//{ +// if (equipment_slot.Type() != inventory::InvTypePossessions || equipment_slot.Bag() != inventory::InvBagInvalid || equipment_slot.Aug() != inventory::InvAugInvalid) +// return textures::TextureInvalid; +// +// return ConvertEquipmentSlotToTextureSlot(equipment_slot.Slot()); +//} + +//EQEmu::InventorySlot EQEmu::textures::ConvertTextureSlotToEquipmentSlot(int texture_slot) +//{ +// switch (texture_slot) { +// case textures::TextureHead: +// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsHead); +// case textures::TextureChest: +// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsChest); +// case textures::TextureArms: +// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsArms); +// case textures::TextureWrist: +// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsWrist1); +// case textures::TextureHands: +// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsHands); +// case textures::TextureLegs: +// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsLegs); +// case textures::TextureFeet: +// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsFeet); +// case textures::TexturePrimary: +// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsPrimary); +// case textures::TextureSecondary: +// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsSecondary); +// default: +// return EQEmu::InventorySlot(); +// } +//} + +struct EQEmu::TextureProfile +{ + union { + struct { + uint32 Head; + uint32 Chest; + uint32 Arms; + uint32 Wrist; + uint32 Hands; + uint32 Legs; + uint32 Feet; + uint32 Primary; + uint32 Secondary; + }; + uint32 Texture[textures::TextureCount]; + }; + + TextureProfile(); +}; + +EQEmu::TextureProfile::TextureProfile() +{ + memset(&Texture, 0, (sizeof(uint32) * textures::TextureCount)); +} diff --git a/common/textures.h b/common/textures.h new file mode 100644 index 000000000..a6baead67 --- /dev/null +++ b/common/textures.h @@ -0,0 +1,61 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_TEXTURES_H +#define COMMON_TEXTURES_H + +#include "types.h" + + +namespace EQEmu +{ + //class InventorySlot; + + namespace textures { + //enum : int { TextureInvalid = -1, TextureBegin }; + enum : uint8 { TextureInvalid = -1, TextureBegin }; + + //enum TextureSlot : int { + enum TextureSlot : uint8 { + TextureHead = TextureBegin, + TextureChest, + TextureArms, + TextureWrist, + TextureHands, + TextureLegs, + TextureFeet, + TexturePrimary, + TextureSecondary, + TextureCount + }; + + const int LastTexture = TextureSecondary; + const int LastTintableTexture = TextureFeet; + + //extern int ConvertEquipmentSlotToTextureSlot(int equipment_slot); + //extern int ConvertEquipmentSlotToTextureSlot(const InventorySlot &equipment_slot); + //extern InventorySlot ConvertTextureSlotToEquipmentSlot(int texture_slot); + + } /*textures*/ + + struct TextureProfile; + +} /*EQEmu*/ + +#endif /*COMMON_TEXTURES_H*/ diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 9a447640b..ac61e7b64 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -117,7 +117,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou cse->Gender = (uint8)atoi(row[2]); cse->Face = (uint8)atoi(row[15]); - for (uint32 matslot = 0; matslot < EQEmu::legacy::MaterialCount; matslot++) { // Processed below + for (uint32 matslot = 0; matslot < EQEmu::textures::TextureCount; matslot++) { // Processed below cse->Equip[matslot].Material = 0; cse->Equip[matslot].Unknown1 = 0; cse->Equip[matslot].EliteMaterial = 0; @@ -249,7 +249,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou const ItemInst* inst = nullptr; int16 invslot = 0; - for (uint32 matslot = 0; matslot < EQEmu::legacy::MaterialCount; matslot++) { + for (uint32 matslot = 0; matslot < EQEmu::textures::TextureCount; matslot++) { invslot = Inventory::CalcSlotFromMaterial(matslot); if (invslot == INVALID_INDEX) { continue; } inst = inv.GetItem(invslot); @@ -270,7 +270,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou cse->Equip[matslot].Material = idfile; } } - if (matslot == EQEmu::legacy::MaterialPrimary) { + if (matslot == EQEmu::textures::TexturePrimary) { cse->PrimaryIDFile = idfile; } else { diff --git a/zone/attack.cpp b/zone/attack.cpp index 8b7d5dba0..15081785c 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4747,7 +4747,7 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int speci // For now, SPECATK_QUAD means innate DW when Combat:UseLiveCombatRounds is true if ((GetSpecialAbility(SPECATK_INNATE_DW) || (RuleB(Combat, UseLiveCombatRounds) && GetSpecialAbility(SPECATK_QUAD))) || - GetEquipment(EQEmu::legacy::MaterialSecondary) != 0) { + GetEquipment(EQEmu::textures::TextureSecondary) != 0) { if (CheckDualWield()) { Attack(target, EQEmu::legacy::SlotSecondary, false, false, false, opts, special); if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()){ diff --git a/zone/bot.cpp b/zone/bot.cpp index e5a5d3673..e94783d2a 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2956,7 +2956,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { const ItemInst* inst = 0; uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); - for (int i = 0; i < EQEmu::legacy::MaterialPrimary; i++) { + for (int i = 0; i < EQEmu::textures::TexturePrimary; i++) { inst = GetBotItem(i); if (inst) { item = inst->GetItem(); @@ -2980,9 +2980,9 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { item = inst->GetItem(); if(item) { if(strlen(item->IDFile) > 2) - ns->spawn.equipment[EQEmu::legacy::MaterialPrimary].Material = atoi(&item->IDFile[2]); + ns->spawn.equipment[EQEmu::textures::TexturePrimary].Material = atoi(&item->IDFile[2]); - ns->spawn.colors[EQEmu::legacy::MaterialPrimary].Color = GetEquipmentColor(EQEmu::legacy::MaterialPrimary); + ns->spawn.colors[EQEmu::textures::TexturePrimary].Color = GetEquipmentColor(EQEmu::textures::TexturePrimary); } } @@ -2991,9 +2991,9 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { item = inst->GetItem(); if(item) { if(strlen(item->IDFile) > 2) - ns->spawn.equipment[EQEmu::legacy::MaterialSecondary].Material = atoi(&item->IDFile[2]); + ns->spawn.equipment[EQEmu::textures::TextureSecondary].Material = atoi(&item->IDFile[2]); - ns->spawn.colors[EQEmu::legacy::MaterialSecondary].Color = GetEquipmentColor(EQEmu::legacy::MaterialSecondary); + ns->spawn.colors[EQEmu::textures::TextureSecondary].Color = GetEquipmentColor(EQEmu::textures::TextureSecondary); } } } @@ -3237,7 +3237,7 @@ void Bot::BotAddEquipItem(int slot, uint32 id) { if(slot > 0 && id > 0) { uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); - if (materialFromSlot != EQEmu::legacy::MaterialInvalid) { + if (materialFromSlot != EQEmu::textures::TextureInvalid) { equipment[slot] = id; // npc has more than just material slots. Valid material should mean valid inventory index SendWearChange(materialFromSlot); } @@ -3253,11 +3253,11 @@ void Bot::BotRemoveEquipItem(int slot) { if(slot > 0) { uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); - if (materialFromSlot != EQEmu::legacy::MaterialInvalid) { + if (materialFromSlot != EQEmu::textures::TextureInvalid) { equipment[slot] = 0; // npc has more than just material slots. Valid material should mean valid inventory index SendWearChange(materialFromSlot); - if (materialFromSlot == EQEmu::legacy::MaterialChest) - SendWearChange(EQEmu::legacy::MaterialArms); + if (materialFromSlot == EQEmu::textures::TextureChest) + SendWearChange(EQEmu::textures::TextureArms); } UpdateEquipmentLight(); @@ -4781,7 +4781,7 @@ int Bot::GetHandToHandDamage(void) { // everyone uses this in the revamp! int skill = GetSkill(EQEmu::skills::SkillHandtoHand); int epic = 0; - if (CastToNPC()->GetEquipment(EQEmu::legacy::MaterialHands) == 10652 && GetLevel() > 46) + if (CastToNPC()->GetEquipment(EQEmu::textures::TextureHands) == 10652 && GetLevel() > 46) epic = 280; if (epic > skill) skill = epic; @@ -4803,7 +4803,7 @@ int Bot::GetHandToHandDamage(void) { 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, // 31-40 10, 11, 11, 11, 11, 11, 11, 12, 12}; // 41-49 if (GetClass() == MONK) { - if (CastToNPC()->GetEquipment(EQEmu::legacy::MaterialHands) == 10652 && GetLevel() > 50) + if (CastToNPC()->GetEquipment(EQEmu::textures::TextureHands) == 10652 && GetLevel() > 50) return 9; if (level > 62) return 15; @@ -8415,7 +8415,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) if (slot_id != INVALID_INDEX) return false; - for (uint8 i = 0; i < EQEmu::legacy::MaterialPrimary; ++i) { + for (uint8 i = 0; i < EQEmu::textures::TexturePrimary; ++i) { uint8 inv_slot = Inventory::CalcSlotFromMaterial(i); ItemInst* inst = m_inv.GetItem(inv_slot); if (!inst) @@ -8427,7 +8427,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) } else { uint8 mat_slot = Inventory::CalcMaterialFromSlot(slot_id); - if (mat_slot == EQEmu::legacy::MaterialInvalid || mat_slot >= EQEmu::legacy::MaterialPrimary) + if (mat_slot == EQEmu::textures::TextureInvalid || mat_slot >= EQEmu::textures::TexturePrimary) return false; ItemInst* inst = m_inv.GetItem(slot_id); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 46173e5ec..e3b16219a 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -4358,7 +4358,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) // TODO: Trouble-shoot model update issue const std::string msg_matslot = StringFormat("mat_slot: %c(All), %i(Head), %i(Chest), %i(Arms), %i(Wrists), %i(Hands), %i(Legs), %i(Feet)", - '*', EQEmu::legacy::MaterialHead, EQEmu::legacy::MaterialChest, EQEmu::legacy::MaterialArms, EQEmu::legacy::MaterialWrist, EQEmu::legacy::MaterialHands, EQEmu::legacy::MaterialLegs, EQEmu::legacy::MaterialFeet); + '*', EQEmu::textures::TextureHead, EQEmu::textures::TextureChest, EQEmu::textures::TextureArms, EQEmu::textures::TextureWrist, EQEmu::textures::TextureHands, EQEmu::textures::TextureLegs, EQEmu::textures::TextureFeet); if (helper_command_alias_fail(c, "bot_subcommand_bot_dye_armor", sep->arg[0], "botdyearmor")) return; @@ -4369,7 +4369,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) } const int ab_mask = ActionableBots::ABM_NoFilter; - uint8 material_slot = EQEmu::legacy::MaterialInvalid; + uint8 material_slot = EQEmu::textures::TextureInvalid; int16 slot_id = INVALID_INDEX; bool dye_all = (sep->arg[1][0] == '*'); @@ -4377,7 +4377,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) material_slot = atoi(sep->arg[1]); slot_id = Inventory::CalcSlotFromMaterial(material_slot); - if (!sep->IsNumber(1) || slot_id == INVALID_INDEX || material_slot > EQEmu::legacy::MaterialFeet) { + if (!sep->IsNumber(1) || slot_id == INVALID_INDEX || material_slot > EQEmu::textures::TextureFeet) { c->Message(m_fail, "Valid [mat_slot]s for this command are:"); c->Message(m_fail, msg_matslot.c_str()); return; diff --git a/zone/client.cpp b/zone/client.cpp index 2dba5ca35..a3da174a9 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2730,7 +2730,7 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) { if (item && item->IsClassCommon()) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); - if (matslot != EQEmu::legacy::MaterialInvalid) + if (matslot != EQEmu::textures::TextureInvalid) { m_pp.item_material[matslot] = GetEquipmentMaterial(matslot); } @@ -3072,7 +3072,7 @@ void Client::SetTint(int16 in_slot, uint32 color) { void Client::SetTint(int16 in_slot, Color_Struct& color) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); - if (matslot != EQEmu::legacy::MaterialInvalid) + if (matslot != EQEmu::textures::TextureInvalid) { m_pp.item_tint[matslot].Color = color.Color; database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.Color); @@ -3151,25 +3151,25 @@ uint8 Client::SlotConvert(uint8 slot,bool bracer){ if(bracer) return EQEmu::legacy::SlotWrist2; switch(slot) { - case EQEmu::legacy::MaterialHead: + case EQEmu::textures::TextureHead: slot2 = EQEmu::legacy::SlotHead; break; - case EQEmu::legacy::MaterialChest: + case EQEmu::textures::TextureChest: slot2 = EQEmu::legacy::SlotChest; break; - case EQEmu::legacy::MaterialArms: + case EQEmu::textures::TextureArms: slot2 = EQEmu::legacy::SlotArms; break; - case EQEmu::legacy::MaterialWrist: + case EQEmu::textures::TextureWrist: slot2 = EQEmu::legacy::SlotWrist1; break; - case EQEmu::legacy::MaterialHands: + case EQEmu::textures::TextureHands: slot2 = EQEmu::legacy::SlotHands; break; - case EQEmu::legacy::MaterialLegs: + case EQEmu::textures::TextureLegs: slot2 = EQEmu::legacy::SlotLegs; break; - case EQEmu::legacy::MaterialFeet: + case EQEmu::textures::TextureFeet: slot2 = EQEmu::legacy::SlotFeet; break; } @@ -3180,25 +3180,25 @@ uint8 Client::SlotConvert2(uint8 slot){ uint8 slot2 = 0; // same as above... switch(slot){ case EQEmu::legacy::SlotHead: - slot2 = EQEmu::legacy::MaterialHead; + slot2 = EQEmu::textures::TextureHead; break; case EQEmu::legacy::SlotChest: - slot2 = EQEmu::legacy::MaterialChest; + slot2 = EQEmu::textures::TextureChest; break; case EQEmu::legacy::SlotArms: - slot2 = EQEmu::legacy::MaterialArms; + slot2 = EQEmu::textures::TextureArms; break; case EQEmu::legacy::SlotWrist1: - slot2 = EQEmu::legacy::MaterialWrist; + slot2 = EQEmu::textures::TextureWrist; break; case EQEmu::legacy::SlotHands: - slot2 = EQEmu::legacy::MaterialHands; + slot2 = EQEmu::textures::TextureHands; break; case EQEmu::legacy::SlotLegs: - slot2 = EQEmu::legacy::MaterialLegs; + slot2 = EQEmu::textures::TextureLegs; break; case EQEmu::legacy::SlotFeet: - slot2 = EQEmu::legacy::MaterialFeet; + slot2 = EQEmu::textures::TextureFeet; break; } return slot2; @@ -6271,8 +6271,8 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid made_npc->Corrup = GetCorrup(); made_npc->PhR = GetPhR(); // looks - made_npc->texture = GetEquipmentMaterial(EQEmu::legacy::MaterialChest); - made_npc->helmtexture = GetEquipmentMaterial(EQEmu::legacy::MaterialHead); + made_npc->texture = GetEquipmentMaterial(EQEmu::textures::TextureChest); + made_npc->helmtexture = GetEquipmentMaterial(EQEmu::textures::TextureHead); made_npc->haircolor = GetHairColor(); made_npc->beardcolor = GetBeardColor(); made_npc->eyecolor1 = GetEyeColor1(); @@ -6283,9 +6283,9 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid made_npc->drakkin_heritage = GetDrakkinHeritage(); made_npc->drakkin_tattoo = GetDrakkinTattoo(); made_npc->drakkin_details = GetDrakkinDetails(); - made_npc->d_melee_texture1 = GetEquipmentMaterial(EQEmu::legacy::MaterialPrimary); - made_npc->d_melee_texture2 = GetEquipmentMaterial(EQEmu::legacy::MaterialSecondary); - for (int i = EQEmu::legacy::MATERIAL_BEGIN; i <= EQEmu::legacy::MATERIAL_END; i++) { + made_npc->d_melee_texture1 = GetEquipmentMaterial(EQEmu::textures::TexturePrimary); + made_npc->d_melee_texture2 = GetEquipmentMaterial(EQEmu::textures::TextureSecondary); + for (int i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTexture; i++) { made_npc->armor_tint[i] = GetEquipmentColor(i); } made_npc->loottable_id = 0; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 5a5a2ca47..af40253a3 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1313,7 +1313,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) } /* Set item material tint */ - for (int i = EQEmu::legacy::MATERIAL_BEGIN; i <= EQEmu::legacy::MATERIAL_END; i++) + for (int i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTexture; i++) { if (m_pp.item_tint[i].RGB.UseTint == 1 || m_pp.item_tint[i].RGB.UseTint == 255) { @@ -3078,7 +3078,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != EQEmu::legacy::MaterialInvalid) + if (mat != EQEmu::textures::TextureInvalid) { SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. } @@ -3143,7 +3143,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != EQEmu::legacy::MaterialInvalid) + if (mat != EQEmu::textures::TextureInvalid) { SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. } @@ -3198,7 +3198,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != EQEmu::legacy::MaterialInvalid) + if (mat != EQEmu::textures::TextureInvalid) { SendWearChange(mat); } diff --git a/zone/command.cpp b/zone/command.cpp index 6c4ab90bf..beb405d26 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2416,14 +2416,14 @@ void command_texture(Client *c, const Seperator *sep) // Player Races Wear Armor, so Wearchange is sent instead int i; if (!c->GetTarget()) - for (i = EQEmu::legacy::MATERIAL_BEGIN; i <= EQEmu::legacy::MATERIAL_TINT_END; i++) + for (i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTintableTexture; i++) { c->SendTextureWC(i, texture); } else if ((c->GetTarget()->GetRace() > 0 && c->GetTarget()->GetRace() <= 12) || c->GetTarget()->GetRace() == 128 || c->GetTarget()->GetRace() == 130 || c->GetTarget()->GetRace() == 330 || c->GetTarget()->GetRace() == 522) { - for (i = EQEmu::legacy::MATERIAL_BEGIN; i <= EQEmu::legacy::MATERIAL_TINT_END; i++) + for (i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTintableTexture; i++) { c->GetTarget()->SendTextureWC(i, texture); } @@ -7119,7 +7119,7 @@ void command_path(Client *c, const Seperator *sep) } void Client::Undye() { - for (int cur_slot = EQEmu::legacy::MATERIAL_BEGIN; cur_slot <= EQEmu::legacy::MATERIAL_END; cur_slot++) { + for (int cur_slot = EQEmu::textures::TextureBegin; cur_slot <= EQEmu::textures::LastTexture; cur_slot++) { uint8 slot2=SlotConvert(cur_slot); ItemInst* inst = m_inv.GetItem(slot2); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 329c5c40e..d42801590 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -746,7 +746,7 @@ void Corpse::RemoveItem(ServerLootItem_Struct* item_data) itemlist.erase(iter); uint8 material = Inventory::CalcMaterialFromSlot(sitem->equip_slot); // autos to unsigned char - if (material != EQEmu::legacy::MaterialInvalid) + if (material != EQEmu::textures::TextureInvalid) SendWearChange(material); UpdateEquipmentLight(); @@ -1400,7 +1400,7 @@ void Corpse::Spawn() { uint32 Corpse::GetEquipment(uint8 material_slot) const { int16 invslot; - if (material_slot > EQEmu::legacy::MATERIAL_END) { + if (material_slot > EQEmu::textures::LastTexture) { return NO_ITEM; } @@ -1414,7 +1414,7 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { const EQEmu::ItemBase *item; - if (material_slot > EQEmu::legacy::MATERIAL_END) { + if (material_slot > EQEmu::textures::LastTexture) { return 0; } diff --git a/zone/inventory.cpp b/zone/inventory.cpp index bd19b69ad..360e3a070 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -1019,7 +1019,7 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs //send worn to everyone... PutLootInInventory(i, inst); uint8 worn_slot_material = Inventory::CalcMaterialFromSlot(i); - if (worn_slot_material != EQEmu::legacy::MaterialInvalid) { + if (worn_slot_material != EQEmu::textures::TextureInvalid) { SendWearChange(worn_slot_material); } @@ -1792,7 +1792,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } int matslot = SlotConvert2(dst_slot_id); - if (dst_slot_id <= EQEmu::legacy::EQUIPMENT_END && matslot != EQEmu::legacy::MaterialHead) { // think this is to allow the client to update with /showhelm + if (dst_slot_id <= EQEmu::legacy::EQUIPMENT_END && matslot != EQEmu::textures::TextureHead) { // think this is to allow the client to update with /showhelm SendWearChange(matslot); } @@ -2021,7 +2021,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { void Client::DyeArmor(DyeStruct* dye){ int16 slot=0; - for (int i = EQEmu::legacy::MATERIAL_BEGIN; i <= EQEmu::legacy::MATERIAL_TINT_END; i++) { + for (int i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTintableTexture; i++) { if ((m_pp.item_tint[i].Color & 0x00FFFFFF) != (dye->dye[i].Color & 0x00FFFFFF)) { slot = m_inv.HasItem(32557, 1, invWherePersonal); if (slot != INVALID_INDEX){ @@ -2593,7 +2593,7 @@ uint32 Client::GetEquipment(uint8 material_slot) const int16 invslot; const ItemInst *item; - if(material_slot > EQEmu::legacy::MATERIAL_END) + if(material_slot > EQEmu::textures::LastTexture) { return 0; } @@ -2631,7 +2631,7 @@ int32 Client::GetEquipmentMaterial(uint8 material_slot) uint32 Client::GetEquipmentColor(uint8 material_slot) const { - if (material_slot > EQEmu::legacy::MATERIAL_END) + if (material_slot > EQEmu::textures::LastTexture) return 0; const EQEmu::ItemBase *item = database.GetItem(GetEquipment(material_slot)); diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 4673d74dc..9dbfa37ac 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -331,7 +331,7 @@ void NPC::AddLootDrop(const EQEmu::ItemBase *item2, ItemList* itemlist, int16 ch if (item2->Proc.Effect != 0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); - eslot = EQEmu::legacy::MaterialPrimary; + eslot = EQEmu::textures::TexturePrimary; if (item2->Damage > 0) SendAddPlayerState(PlayerState::PrimaryWeaponEquipped); if (item2->IsType2HWeapon()) @@ -344,30 +344,30 @@ void NPC::AddLootDrop(const EQEmu::ItemBase *item2, ItemList* itemlist, int16 ch if (item2->Proc.Effect!=0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); - eslot = EQEmu::legacy::MaterialSecondary; + eslot = EQEmu::textures::TextureSecondary; if (item2->Damage > 0) SendAddPlayerState(PlayerState::SecondaryWeaponEquipped); } else if (foundslot == EQEmu::legacy::SlotHead) { - eslot = EQEmu::legacy::MaterialHead; + eslot = EQEmu::textures::TextureHead; } else if (foundslot == EQEmu::legacy::SlotChest) { - eslot = EQEmu::legacy::MaterialChest; + eslot = EQEmu::textures::TextureChest; } else if (foundslot == EQEmu::legacy::SlotArms) { - eslot = EQEmu::legacy::MaterialArms; + eslot = EQEmu::textures::TextureArms; } else if (foundslot == EQEmu::legacy::SlotWrist1 || foundslot == EQEmu::legacy::SlotWrist2) { - eslot = EQEmu::legacy::MaterialWrist; + eslot = EQEmu::textures::TextureWrist; } else if (foundslot == EQEmu::legacy::SlotHands) { - eslot = EQEmu::legacy::MaterialHands; + eslot = EQEmu::textures::TextureHands; } else if (foundslot == EQEmu::legacy::SlotLegs) { - eslot = EQEmu::legacy::MaterialLegs; + eslot = EQEmu::textures::TextureLegs; } else if (foundslot == EQEmu::legacy::SlotFeet) { - eslot = EQEmu::legacy::MaterialFeet; + eslot = EQEmu::textures::TextureFeet; } /* diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 320b084a0..59103cf9e 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1809,19 +1809,19 @@ luabind::scope lua_register_material() { return luabind::class_("Material") .enum_("constants") [ - luabind::value("Head", static_cast(EQEmu::legacy::MaterialHead)), - luabind::value("Chest", static_cast(EQEmu::legacy::MaterialChest)), - luabind::value("Arms", static_cast(EQEmu::legacy::MaterialArms)), - luabind::value("Bracer", static_cast(EQEmu::legacy::MaterialWrist)), // deprecated - luabind::value("Wrist", static_cast(EQEmu::legacy::MaterialWrist)), - luabind::value("Hands", static_cast(EQEmu::legacy::MaterialHands)), - luabind::value("Legs", static_cast(EQEmu::legacy::MaterialLegs)), - luabind::value("Feet", static_cast(EQEmu::legacy::MaterialFeet)), - luabind::value("Primary", static_cast(EQEmu::legacy::MaterialPrimary)), - luabind::value("Secondary", static_cast(EQEmu::legacy::MaterialSecondary)), - luabind::value("Max", static_cast(EQEmu::legacy::MaterialCount)), // deprecated - luabind::value("Count", static_cast(EQEmu::legacy::MaterialCount)), - luabind::value("Invalid", static_cast(EQEmu::legacy::MaterialInvalid)) + luabind::value("Head", static_cast(EQEmu::textures::TextureHead)), + luabind::value("Chest", static_cast(EQEmu::textures::TextureChest)), + luabind::value("Arms", static_cast(EQEmu::textures::TextureArms)), + luabind::value("Bracer", static_cast(EQEmu::textures::TextureWrist)), // deprecated + luabind::value("Wrist", static_cast(EQEmu::textures::TextureWrist)), + luabind::value("Hands", static_cast(EQEmu::textures::TextureHands)), + luabind::value("Legs", static_cast(EQEmu::textures::TextureLegs)), + luabind::value("Feet", static_cast(EQEmu::textures::TextureFeet)), + luabind::value("Primary", static_cast(EQEmu::textures::TexturePrimary)), + luabind::value("Secondary", static_cast(EQEmu::textures::TextureSecondary)), + luabind::value("Max", static_cast(EQEmu::textures::TextureCount)), // deprecated + luabind::value("Count", static_cast(EQEmu::textures::TextureCount)), + luabind::value("Invalid", static_cast(EQEmu::textures::TextureInvalid)) ]; } diff --git a/zone/merc.cpp b/zone/merc.cpp index a516c34b3..4ff8e8d90 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -5046,12 +5046,12 @@ void Merc::ScaleStats(int scalepercent, bool setmax) { void Merc::UpdateMercAppearance() { // Copied from Bot Code: uint32 itemID = NO_ITEM; - uint8 materialFromSlot = EQEmu::legacy::MaterialInvalid; + uint8 materialFromSlot = EQEmu::textures::TextureInvalid; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { itemID = equipment[i]; if(itemID != NO_ITEM) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); - if (materialFromSlot != EQEmu::legacy::MaterialInvalid) + if (materialFromSlot != EQEmu::textures::TextureInvalid) this->SendWearChange(materialFromSlot); } } diff --git a/zone/mob.cpp b/zone/mob.cpp index 78e56e8bc..d2e02a970 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -73,7 +73,7 @@ Mob::Mob(const char* in_name, uint32 in_drakkin_heritage, uint32 in_drakkin_tattoo, uint32 in_drakkin_details, - uint32 in_armor_tint[EQEmu::legacy::MaterialCount], + uint32 in_armor_tint[EQEmu::textures::TextureCount], uint8 in_aa_title, uint8 in_see_invis, // see through invis/ivu @@ -278,7 +278,7 @@ Mob::Mob(const char* in_name, RangedProcs[j].level_override = -1; } - for (i = 0; i < EQEmu::legacy::MaterialCount; i++) + for (i = 0; i < EQEmu::textures::TextureCount; i++) { if (in_armor_tint) { @@ -2863,7 +2863,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const if (item != 0) { // For primary and secondary we need the model, not the material - if (material_slot == EQEmu::legacy::MaterialPrimary || material_slot == EQEmu::legacy::MaterialSecondary) + if (material_slot == EQEmu::textures::TexturePrimary || material_slot == EQEmu::textures::TextureSecondary) { if (this->IsClient()) { @@ -2907,7 +2907,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const int32 Mob::GetHerosForgeModel(uint8 material_slot) const { uint32 HeroModel = 0; - if (material_slot >= 0 && material_slot < EQEmu::legacy::MaterialPrimary) + if (material_slot >= 0 && material_slot < EQEmu::textures::TexturePrimary) { uint32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); const EQEmu::ItemBase *item; diff --git a/zone/mob.h b/zone/mob.h index 124eb471b..e4c9ad875 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -113,7 +113,7 @@ public: uint32 in_drakkin_heritage, uint32 in_drakkin_tattoo, uint32 in_drakkin_details, - uint32 in_armor_tint[EQEmu::legacy::MaterialCount], + uint32 in_armor_tint[EQEmu::textures::TextureCount], uint8 in_aa_title, uint8 in_see_invis, // see through invis uint8 in_see_invis_undead, // see through invis vs. undead @@ -384,7 +384,7 @@ public: inline uint8 GetDrakkinHeritage() const { return drakkin_heritage; } inline uint8 GetDrakkinTattoo() const { return drakkin_tattoo; } inline uint8 GetDrakkinDetails() const { return drakkin_details; } - inline uint32 GetArmorTint(uint8 i) const { return armor_tint[(i < EQEmu::legacy::MaterialCount) ? i : 0]; } + inline uint32 GetArmorTint(uint8 i) const { return armor_tint[(i < EQEmu::textures::TextureCount) ? i : 0]; } inline uint8 GetClass() const { return class_; } inline uint8 GetLevel() const { return level; } inline uint8 GetOrigLevel() const { return orig_level; } @@ -1248,7 +1248,7 @@ protected: uint32 drakkin_heritage; uint32 drakkin_tattoo; uint32 drakkin_details; - uint32 armor_tint[EQEmu::legacy::MaterialCount]; + uint32 armor_tint[EQEmu::textures::TextureCount]; uint8 aa_title; diff --git a/zone/npc.cpp b/zone/npc.cpp index a965bfad0..77f6d492f 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -489,7 +489,7 @@ void NPC::CheckMinMaxLevel(Mob *them) if(themlevel < (*cur)->min_level || themlevel > (*cur)->max_level) { material = Inventory::CalcMaterialFromSlot((*cur)->equip_slot); - if (material != EQEmu::legacy::MaterialInvalid) + if (material != EQEmu::textures::TextureInvalid) SendWearChange(material); cur = itemlist.erase(cur); @@ -1373,7 +1373,7 @@ uint32 ZoneDatabase::NPCSpawnDB(uint8 command, const char* zone, uint32 zone_ver int32 NPC::GetEquipmentMaterial(uint8 material_slot) const { - if (material_slot >= EQEmu::legacy::MaterialCount) + if (material_slot >= EQEmu::textures::TextureCount) return 0; int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); @@ -1384,23 +1384,23 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const { switch(material_slot) { - case EQEmu::legacy::MaterialHead: + case EQEmu::textures::TextureHead: return helmtexture; - case EQEmu::legacy::MaterialChest: + case EQEmu::textures::TextureChest: return texture; - case EQEmu::legacy::MaterialArms: + case EQEmu::textures::TextureArms: return armtexture; - case EQEmu::legacy::MaterialWrist: + case EQEmu::textures::TextureWrist: return bracertexture; - case EQEmu::legacy::MaterialHands: + case EQEmu::textures::TextureHands: return handtexture; - case EQEmu::legacy::MaterialLegs: + case EQEmu::textures::TextureLegs: return legtexture; - case EQEmu::legacy::MaterialFeet: + case EQEmu::textures::TextureFeet: return feettexture; - case EQEmu::legacy::MaterialPrimary: + case EQEmu::textures::TexturePrimary: return d_melee_texture1; - case EQEmu::legacy::MaterialSecondary: + case EQEmu::textures::TextureSecondary: return d_melee_texture2; default: //they have nothing in the slot, and its not a special slot... they get nothing. diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index e5391b514..e1bd31220 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1435,7 +1435,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } } - for (int x = EQEmu::legacy::MATERIAL_BEGIN; x <= EQEmu::legacy::MATERIAL_TINT_END; x++) + for (int x = EQEmu::textures::TextureBegin; x <= EQEmu::textures::LastTintableTexture; x++) SendWearChange(x); if (caster == this && @@ -1461,7 +1461,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove ); caster->SendAppearancePacket(AT_Size, static_cast(caster->GetTarget()->GetSize())); - for (int x = EQEmu::legacy::MATERIAL_BEGIN; x <= EQEmu::legacy::MATERIAL_TINT_END; x++) + for (int x = EQEmu::textures::TextureBegin; x <= EQEmu::textures::LastTintableTexture; x++) caster->SendWearChange(x); } } @@ -3813,7 +3813,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) else{ SendAppearancePacket(AT_Size, 6); } - for (int x = EQEmu::legacy::MATERIAL_BEGIN; x <= EQEmu::legacy::MATERIAL_TINT_END; x++){ + for (int x = EQEmu::textures::TextureBegin; x <= EQEmu::textures::LastTintableTexture; x++){ SendWearChange(x); } break; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 493b95d21..405cd0daa 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2092,7 +2092,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load else { auto armorTint_row = armortint_results.begin(); - for (int index = EQEmu::legacy::MATERIAL_BEGIN; index <= EQEmu::legacy::MATERIAL_END; index++) { + for (int index = EQEmu::textures::TextureBegin; index <= EQEmu::textures::LastTexture; index++) { temp_npctype_data->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; temp_npctype_data->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; temp_npctype_data->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); @@ -2102,7 +2102,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load } // Try loading npc_types tint fields if armor tint is 0 or query failed to get results if (armor_tint_id == 0) { - for (int index = EQEmu::legacy::MaterialChest; index < EQEmu::legacy::MaterialCount; index++) { + for (int index = EQEmu::textures::TextureChest; index < EQEmu::textures::TextureCount; index++) { temp_npctype_data->armor_tint[index] = temp_npctype_data->armor_tint[0]; } } @@ -2307,7 +2307,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; if (armor_tint_id == 0) - for (int index = EQEmu::legacy::MaterialChest; index <= EQEmu::legacy::MATERIAL_END; index++) + for (int index = EQEmu::textures::TextureChest; index <= EQEmu::textures::LastTexture; index++) tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0]; else if (tmpNPCType->armor_tint[0] == 0) { std::string armorTint_query = StringFormat("SELECT red1h, grn1h, blu1h, " @@ -2327,7 +2327,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client else { auto armorTint_row = results.begin(); - for (int index = EQEmu::legacy::MATERIAL_BEGIN; index <= EQEmu::legacy::MATERIAL_END; index++) { + for (int index = EQEmu::textures::TextureBegin; index <= EQEmu::textures::LastTexture; index++) { tmpNPCType->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); diff --git a/zone/zonedump.h b/zone/zonedump.h index dcba99408..be82b1967 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -86,7 +86,7 @@ struct NPCType uint32 drakkin_heritage; uint32 drakkin_tattoo; uint32 drakkin_details; - uint32 armor_tint[EQEmu::legacy::MaterialCount]; + uint32 armor_tint[EQEmu::textures::TextureCount]; uint32 min_dmg; uint32 max_dmg; int16 attack_count; From c07fe35908cc4894808a44cd68cced0a37bafcb3 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 31 May 2016 22:17:58 -0400 Subject: [PATCH 140/693] Fix for gcc failure --- common/textures.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/textures.h b/common/textures.h index a6baead67..e13776279 100644 --- a/common/textures.h +++ b/common/textures.h @@ -29,7 +29,7 @@ namespace EQEmu namespace textures { //enum : int { TextureInvalid = -1, TextureBegin }; - enum : uint8 { TextureInvalid = -1, TextureBegin }; + enum : uint8 { TextureInvalid = 255, TextureBegin = 0 }; //enum TextureSlot : int { enum TextureSlot : uint8 { From 767dfaef702e8111f7d2f0a5a473040d4fd219ba Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 31 May 2016 22:28:31 -0400 Subject: [PATCH 141/693] Another penguin bite... --- common/textures.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/textures.cpp b/common/textures.cpp index 424255341..bbfda39a2 100644 --- a/common/textures.cpp +++ b/common/textures.cpp @@ -20,7 +20,7 @@ #include "textures.h" //#include "inventory_slot.h" -#include // temp +#include // temp //int EQEmu::textures::ConvertEquipmentSlotToTextureSlot(int equipment_slot) From ae3c98c69202121c0427343a73a926fff91f37de Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 1 Jun 2016 04:58:52 -0400 Subject: [PATCH 142/693] Implemented EQEmu::TintProfile --- changelog.txt | 3 ++ common/eq_packet_structs.h | 57 ++------------------------ common/patches/rof.cpp | 6 +-- common/patches/rof2.cpp | 6 +-- common/patches/rof2_structs.h | 67 +++++++++++-------------------- common/patches/rof_structs.h | 67 +++++++++++-------------------- common/patches/sod.cpp | 4 +- common/patches/sod_structs.h | 65 +++++++++++------------------- common/patches/sof.cpp | 6 +-- common/patches/sof_structs.h | 65 +++++++++++------------------- common/patches/titanium.cpp | 8 ++-- common/patches/titanium_structs.h | 65 +++++++++++------------------- common/patches/uf.cpp | 4 +- common/patches/uf_structs.h | 67 +++++++++++-------------------- common/textures.cpp | 25 +++--------- common/textures.h | 52 +++++++++++++++++++++++- world/worlddb.cpp | 12 +++--- zone/bot.cpp | 10 ++--- zone/client.cpp | 6 +-- zone/client.h | 4 +- zone/client_packet.cpp | 10 ++--- zone/command.cpp | 2 +- zone/corpse.cpp | 32 +++++++-------- zone/corpse.h | 2 +- zone/inventory.cpp | 20 ++++----- zone/mob.cpp | 2 +- zone/zonedb.cpp | 50 +++++++++++------------ zone/zonedump.h | 2 +- 28 files changed, 296 insertions(+), 423 deletions(-) diff --git a/changelog.txt b/changelog.txt index e5e33b2a0..8708d1cd9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 06/01/2016 == +Uleat: Implemented EQEmu::TintProfile + == 05/31/2016 == Uleat: Converted enumeration MaterialSlots to EQEmu::textures::TextureSlot diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 5ca9b530d..23a92082c 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -126,19 +126,6 @@ struct LDoNTrapTemplate // All clients translate the character select information to some degree -struct Color_Struct -{ - union { - struct { - uint8 Blue; - uint8 Green; - uint8 Red; - uint8 UseTint; // if there's a tint this is FF - } RGB; - uint32 Color; - }; -}; - struct EquipStruct { uint32 Material; @@ -155,7 +142,7 @@ struct CharSelectEquip uint32 EliteMaterial; uint32 HeroForgeModel; uint32 Material2; - Color_Struct Color; + EQEmu::Tint_Struct Color; }; // RoF2-based hybrid struct @@ -326,22 +313,7 @@ union /*0340*/ uint32 spawnId; // Spawn Id /*0344*/ uint8 unknown0344[3]; /*0347*/ uint8 IsMercenary; -/*0348*/ union - { - struct - { - /*0348*/ Color_Struct color_helmet; // Color of helmet item - /*0352*/ Color_Struct color_chest; // Color of chest item - /*0356*/ Color_Struct color_arms; // Color of arms item - /*0360*/ Color_Struct color_bracers; // Color of bracers item - /*0364*/ Color_Struct color_hands; // Color of hands item - /*0368*/ Color_Struct color_legs; // Color of legs item - /*0372*/ Color_Struct color_feet; // Color of feet item - /*0376*/ Color_Struct color_primary; // Color of primary item - /*0380*/ Color_Struct color_secondary; // Color of secondary item - } equipment_colors; - /*0348*/ Color_Struct colors[EQEmu::textures::TextureCount]; // Array elements correspond to struct equipment_colors above - }; +/*0348*/ EQEmu::TintProfile equipment_tint; /*0384*/ uint8 lfg; // 0=off, 1=lfg on /*0385*/ @@ -992,7 +964,7 @@ struct PlayerProfile_Struct /*0306*/ uint8 unknown0306[6]; // @bp Spacer/Flag? /*0312*/ uint32 item_material[EQEmu::textures::TextureCount]; // Item texture/material of worn/held items /*0348*/ uint8 unknown0348[44]; -/*0392*/ Color_Struct item_tint[EQEmu::textures::TextureCount]; +/*0392*/ EQEmu::TintProfile item_tint; /*0428*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; /*2348*/ float unknown2384; //seen ~128, ~47 /*2352*/ char servername[32]; // length probably not right @@ -1227,7 +1199,7 @@ struct WearChange_Struct{ /*010*/ uint32 elite_material; // 1 for Drakkin Elite Material /*014*/ uint32 hero_forge_model; // New to VoA /*018*/ uint32 unknown18; // New to RoF -/*022*/ Color_Struct color; +/*022*/ EQEmu::Tint_Struct color; /*026*/ uint8 wear_slot_id; /*027*/ }; @@ -3416,27 +3388,6 @@ struct PetitionBug_Struct{ char text[1028]; }; -struct DyeStruct -{ - union - { - struct - { - struct Color_Struct head; - struct Color_Struct chest; - struct Color_Struct arms; - struct Color_Struct wrists; - struct Color_Struct hands; - struct Color_Struct legs; - struct Color_Struct feet; - struct Color_Struct primary; // you can't actually dye this - struct Color_Struct secondary; // or this - } - dyes; - struct Color_Struct dye[EQEmu::textures::TextureCount]; - }; -}; - struct ApproveZone_Struct { char name[64]; uint32 zoneid; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 11531d8ae..d14cfb810 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2103,7 +2103,7 @@ namespace RoF for (int r = 0; r < 7; r++) { - outapp->WriteUInt32(emu->item_tint[r].Color); + outapp->WriteUInt32(emu->item_tint.Slot[r].Color); } // Write zeroes for extra two tint values outapp->WriteUInt32(0); @@ -2113,7 +2113,7 @@ namespace RoF for (int r = 0; r < 7; r++) { - outapp->WriteUInt32(emu->item_tint[r].Color); + outapp->WriteUInt32(emu->item_tint.Slot[r].Color); } // Write zeroes for extra two tint values outapp->WriteUInt32(0); @@ -4086,7 +4086,7 @@ namespace RoF for (k = 0; k < 9; ++k) { { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].Color); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); } } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 0ee12ebd8..d05dbf027 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2187,7 +2187,7 @@ namespace RoF2 for (int r = 0; r < 7; r++) { - outapp->WriteUInt32(emu->item_tint[r].Color); + outapp->WriteUInt32(emu->item_tint.Slot[r].Color); } // Write zeroes for extra two tint values outapp->WriteUInt32(0); @@ -2197,7 +2197,7 @@ namespace RoF2 for (int r = 0; r < 7; r++) { - outapp->WriteUInt32(emu->item_tint[r].Color); + outapp->WriteUInt32(emu->item_tint.Slot[r].Color); } // Write zeroes for extra two tint values outapp->WriteUInt32(0); @@ -4309,7 +4309,7 @@ namespace RoF2 for (k = 0; k < 9; ++k) { { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].Color); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); } } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 6a7056902..4c84174b7 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -163,7 +163,7 @@ struct AdventureInfo { ** Merth: Gave struct a name so gcc 2.96 would compile ** */ -struct Color_Struct +struct Tint_Struct { union { struct { @@ -171,11 +171,28 @@ struct Color_Struct uint8 Green; uint8 Red; uint8 UseTint; // if there's a tint this is FF - } RGB; + }; uint32 Color; }; }; +struct TintProfile { + union { + struct { + Tint_Struct Head; + Tint_Struct Chest; + Tint_Struct Arms; + Tint_Struct Wrist; + Tint_Struct Hands; + Tint_Struct Legs; + Tint_Struct Feet; + Tint_Struct Primary; + Tint_Struct Secondary; + }; + Tint_Struct Slot[EQEmu::textures::TextureCount]; + }; +}; + struct CharSelectEquip { uint32 Material; @@ -183,7 +200,7 @@ struct CharSelectEquip uint32 EliteMaterial; uint32 HeroForgeModel; uint32 Material2; - Color_Struct Color; + Tint_Struct Color; }; struct CharacterSelectEntry_Struct @@ -447,22 +464,7 @@ struct Spawn_Struct /*0000*/ uint32 unknown18; /*0000*/ uint32 unknown19; Spawn_Struct_Position Position; -/*0000*/ union - { - struct - { - /*0000*/ Color_Struct color_helmet; // Color of helmet item - /*0000*/ Color_Struct color_chest; // Color of chest item - /*0000*/ Color_Struct color_arms; // Color of arms item - /*0000*/ Color_Struct color_bracers; // Color of bracers item - /*0000*/ Color_Struct color_hands; // Color of hands item - /*0000*/ Color_Struct color_legs; // Color of legs item - /*0000*/ Color_Struct color_feet; // Color of feet item - /*0000*/ Color_Struct color_primary; // Color of primary item - /*0000*/ Color_Struct color_secondary; // Color of secondary item - } equipment_colors; - /*0000*/ Color_Struct colors[9]; // Array elements correspond to struct equipment_colors above - }; +/*0000*/ TintProfile equipment_tint; // skip these bytes if not a valid player race /*0000*/ union @@ -1107,9 +1109,9 @@ union /*00624*/ uint32 equip2_count; // Seen 9 /*00628*/ EquipStruct equipment2[EQEmu::textures::TextureCount]; // Appears to be Visible slots, but all 0s /*00808*/ uint32 tint_count; // Seen 9 -/*00812*/ Color_Struct item_tint[EQEmu::textures::TextureCount]; // RR GG BB 00 +/*00812*/ TintProfile item_tint; // RR GG BB 00 /*00848*/ uint32 tint_count2; // Seen 9 -/*00852*/ Color_Struct item_tint2[EQEmu::textures::TextureCount]; // RR GG BB 00 +/*00852*/ TintProfile item_tint2; // RR GG BB 00 /*00888*/ uint8 haircolor; // Player hair color /*00889*/ uint8 beardcolor; // Player beard color /*00890*/ uint32 unknown_rof5; // @@ -1385,7 +1387,7 @@ struct WearChange_Struct{ /*010*/ uint32 elite_material; // 1 for Drakkin Elite Material /*014*/ uint32 hero_forge_model; // New to VoA /*018*/ uint32 unknown18; // New to RoF2 -/*022*/ Color_Struct color; +/*022*/ Tint_Struct color; /*026*/ uint8 wear_slot_id; /*027*/ }; @@ -3634,27 +3636,6 @@ struct PetitionBug_Struct{ char text[1028]; }; -struct DyeStruct -{ - union - { - struct - { - struct Color_Struct head; - struct Color_Struct chest; - struct Color_Struct arms; - struct Color_Struct wrists; - struct Color_Struct hands; - struct Color_Struct legs; - struct Color_Struct feet; - struct Color_Struct primary; // you can't actually dye this - struct Color_Struct secondary; // or this - } - dyes; - struct Color_Struct dye[9]; - }; -}; - struct ApproveZone_Struct { char name[64]; uint32 zoneid; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 03cad1ef8..6c884bbeb 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -163,7 +163,7 @@ struct AdventureInfo { ** Merth: Gave struct a name so gcc 2.96 would compile ** */ -struct Color_Struct +struct Tint_Struct { union { struct { @@ -171,11 +171,28 @@ struct Color_Struct uint8 Green; uint8 Red; uint8 UseTint; // if there's a tint this is FF - } RGB; + }; uint32 Color; }; }; +struct TintProfile { + union { + struct { + Tint_Struct Head; + Tint_Struct Chest; + Tint_Struct Arms; + Tint_Struct Wrist; + Tint_Struct Hands; + Tint_Struct Legs; + Tint_Struct Feet; + Tint_Struct Primary; + Tint_Struct Secondary; + }; + Tint_Struct Slot[EQEmu::textures::TextureCount]; + }; +}; + struct CharSelectEquip { uint32 Material; @@ -183,7 +200,7 @@ struct CharSelectEquip uint32 EliteMaterial; uint32 HeroForgeModel; uint32 Material2; - Color_Struct Color; + Tint_Struct Color; }; struct CharacterSelectEntry_Struct @@ -441,22 +458,7 @@ struct Spawn_Struct /*0000*/ uint32 unknown18; /*0000*/ uint32 unknown19; Spawn_Struct_Position Position; -/*0000*/ union - { - struct - { - /*0000*/ Color_Struct color_helmet; // Color of helmet item - /*0000*/ Color_Struct color_chest; // Color of chest item - /*0000*/ Color_Struct color_arms; // Color of arms item - /*0000*/ Color_Struct color_bracers; // Color of bracers item - /*0000*/ Color_Struct color_hands; // Color of hands item - /*0000*/ Color_Struct color_legs; // Color of legs item - /*0000*/ Color_Struct color_feet; // Color of feet item - /*0000*/ Color_Struct color_primary; // Color of primary item - /*0000*/ Color_Struct color_secondary; // Color of secondary item - } equipment_colors; - /*0000*/ Color_Struct colors[9]; // Array elements correspond to struct equipment_colors above - }; +/*0000*/ TintProfile equipment_tint; // skip these bytes if not a valid player race /*0000*/ union @@ -1090,9 +1092,9 @@ union /*00624*/ uint32 equip2_count; // Seen 9 /*00628*/ EquipStruct equipment2[9]; // Appears to be Visible slots, but all 0s /*00808*/ uint32 tint_count; // Seen 9 -/*00812*/ Color_Struct item_tint[9]; // RR GG BB 00 +/*00812*/ TintProfile item_tint; // RR GG BB 00 /*00848*/ uint32 tint_count2; // Seen 9 -/*00852*/ Color_Struct item_tint2[9]; // RR GG BB 00 +/*00852*/ TintProfile item_tint2; // RR GG BB 00 /*00888*/ uint8 haircolor; // Player hair color /*00889*/ uint8 beardcolor; // Player beard color /*00890*/ uint32 unknown_rof5; // @@ -1415,7 +1417,7 @@ struct WearChange_Struct{ /*010*/ uint32 elite_material; // 1 for Drakkin Elite Material /*014*/ uint32 hero_forge_model; // New to VoA /*018*/ uint32 unknown18; // New to RoF -/*022*/ Color_Struct color; +/*022*/ Tint_Struct color; /*026*/ uint8 wear_slot_id; /*027*/ }; @@ -3634,27 +3636,6 @@ struct PetitionBug_Struct{ char text[1028]; }; -struct DyeStruct -{ - union - { - struct - { - struct Color_Struct head; - struct Color_Struct chest; - struct Color_Struct arms; - struct Color_Struct wrists; - struct Color_Struct hands; - struct Color_Struct legs; - struct Color_Struct feet; - struct Color_Struct primary; // you can't actually dye this - struct Color_Struct secondary; // or this - } - dyes; - struct Color_Struct dye[9]; - }; -}; - struct ApproveZone_Struct { char name[64]; uint32 zoneid; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 57549f240..ccc0edf15 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1560,7 +1560,7 @@ namespace SoD //eq->colors[r].color = emu->colors[r].color; } for (r = 0; r < 7; r++) { - OUT(item_tint[r].Color); + OUT(item_tint.Slot[r].Color); } // OUT(unknown00224[48]); //NOTE: new client supports 300 AAs, our internal rep/PP @@ -2763,7 +2763,7 @@ namespace SoD for (k = 0; k < 9; ++k) { { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].Color); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); } } } diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index ea9046a78..bf45e2fda 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -122,7 +122,7 @@ struct AdventureInfo { ** Merth: Gave struct a name so gcc 2.96 would compile ** */ -struct Color_Struct +struct Tint_Struct { union { struct { @@ -130,17 +130,34 @@ struct Color_Struct uint8 Green; uint8 Red; uint8 UseTint; // if there's a tint this is FF - } RGB; + }; uint32 Color; }; }; +struct TintProfile { + union { + struct { + Tint_Struct Head; + Tint_Struct Chest; + Tint_Struct Arms; + Tint_Struct Wrist; + Tint_Struct Hands; + Tint_Struct Legs; + Tint_Struct Feet; + Tint_Struct Primary; + Tint_Struct Secondary; + }; + Tint_Struct Slot[EQEmu::textures::TextureCount]; + }; +}; + struct CharSelectEquip { uint32 Material; uint32 Unknown1; uint32 EliteMaterial; - Color_Struct Color; + Tint_Struct Color; }; struct CharacterSelectEntry_Struct @@ -314,22 +331,7 @@ struct Spawn_Struct /*0000*/ uint32 unknown18; /*0000*/ uint32 unknown19; Spawn_Struct_Position Position; -/*0000*/ union - { - struct - { - /*0000*/ Color_Struct color_helmet; // Color of helmet item - /*0000*/ Color_Struct color_chest; // Color of chest item - /*0000*/ Color_Struct color_arms; // Color of arms item - /*0000*/ Color_Struct color_bracers; // Color of bracers item - /*0000*/ Color_Struct color_hands; // Color of hands item - /*0000*/ Color_Struct color_legs; // Color of legs item - /*0000*/ Color_Struct color_feet; // Color of feet item - /*0000*/ Color_Struct color_primary; // Color of primary item - /*0000*/ Color_Struct color_secondary; // Color of secondary item - } equipment_colors; - /*0000*/ Color_Struct colors[9]; // Array elements correspond to struct equipment_colors above - }; +/*0000*/ TintProfile equipment_tint; // skip these bytes if not a valid player race /*0000*/ union @@ -920,7 +922,7 @@ struct PlayerProfile_Struct /*00228*/ EquipStruct equipment[9]; //Live Shows [108] for this part }; /*00340*/ uint8 unknown00224[156]; // Live Shows [160] -/*00496*/ Color_Struct item_tint[9]; // RR GG BB 00 +/*00496*/ TintProfile item_tint; // RR GG BB 00 /*00532*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // [3600] AAs 12 bytes each /*04132*/ uint32 points; // Unspent Practice points - RELOCATED??? /*04136*/ uint32 mana; // Current mana @@ -1177,7 +1179,7 @@ struct WearChange_Struct{ /*002*/ uint32 material; /*006*/ uint32 unknown06; /*010*/ uint32 elite_material; // 1 for Drakkin Elite Material -/*014*/ Color_Struct color; +/*014*/ Tint_Struct color; /*018*/ uint8 wear_slot_id; /*019*/ }; @@ -3091,27 +3093,6 @@ struct PetitionBug_Struct{ char text[1028]; }; -struct DyeStruct -{ - union - { - struct - { - struct Color_Struct head; - struct Color_Struct chest; - struct Color_Struct arms; - struct Color_Struct wrists; - struct Color_Struct hands; - struct Color_Struct legs; - struct Color_Struct feet; - struct Color_Struct primary; // you can't actually dye this - struct Color_Struct secondary; // or this - } - dyes; - struct Color_Struct dye[9]; - }; -}; - struct ApproveZone_Struct { char name[64]; uint32 zoneid; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 50a3bb51f..1ef8240dc 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1216,7 +1216,7 @@ namespace SoF //eq->colors[r].color = emu->colors[r].color; } for (r = 0; r < 7; r++) { - OUT(item_tint[r].Color); + OUT(item_tint.Slot[r].Color); } // OUT(unknown00224[48]); //NOTE: new client supports 300 AAs, our internal rep/PP @@ -2084,7 +2084,7 @@ namespace SoF eq->equipment[k].Material = emu->equipment[k].Material; eq->equipment[k].Unknown1 = emu->equipment[k].Unknown1; eq->equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial; - eq->colors[k].Color = emu->colors[k].Color; + eq->equipment_tint.Slot[k].Color = emu->equipment_tint.Slot[k].Color; } eq->StandState = emu->StandState; eq->guildID = emu->guildID; @@ -2147,7 +2147,7 @@ namespace SoF eq->petOwnerId = emu->petOwnerId; eq->pvp = 0; // 0 = non-pvp colored name, 1 = red pvp name for (k = 0; k < 9; k++) { - eq->colors[k].Color = emu->colors[k].Color; + eq->equipment_tint.Slot[k].Color = emu->equipment_tint.Slot[k].Color; } eq->anon = emu->anon; eq->face = emu->face; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 98fecd469..19e413082 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -122,7 +122,7 @@ struct AdventureInfo { ** Merth: Gave struct a name so gcc 2.96 would compile ** */ -struct Color_Struct +struct Tint_Struct { union { struct { @@ -130,17 +130,34 @@ struct Color_Struct uint8 Green; uint8 Red; uint8 UseTint; // if there's a tint this is FF - } RGB; + }; uint32 Color; }; }; +struct TintProfile { + union { + struct { + Tint_Struct Head; + Tint_Struct Chest; + Tint_Struct Arms; + Tint_Struct Wrist; + Tint_Struct Hands; + Tint_Struct Legs; + Tint_Struct Feet; + Tint_Struct Primary; + Tint_Struct Secondary; + }; + Tint_Struct Slot[EQEmu::textures::TextureCount]; + }; +}; + struct CharSelectEquip { uint32 Material; uint32 Unknown1; uint32 EliteMaterial; - Color_Struct Color; + Tint_Struct Color; }; struct CharacterSelectEntry_Struct @@ -314,22 +331,7 @@ union /*0775*/ char name[64]; // Player's Name /*0839*/ uint32 petOwnerId; // If this is a pet, the spawn id of owner /*0843*/ uint8 pvp; // 0 = normal name color, 2 = PVP name color -/*0844*/ union - { - struct - { - /*0844*/ Color_Struct color_helmet; // Color of helmet item - /*0848*/ Color_Struct color_chest; // Color of chest item - /*0852*/ Color_Struct color_arms; // Color of arms item - /*0856*/ Color_Struct color_bracers; // Color of bracers item - /*0860*/ Color_Struct color_hands; // Color of hands item - /*0864*/ Color_Struct color_legs; // Color of legs item - /*0868*/ Color_Struct color_feet; // Color of feet item - /*0872*/ Color_Struct color_primary; // Color of primary item - /*0876*/ Color_Struct color_secondary; // Color of secondary item - } equipment_colors; - /*0844*/ Color_Struct colors[9]; // Array elements correspond to struct equipment_colors above - }; +/*0844*/ TintProfile equipment_tint; /*0880*/ uint8 anon; // 0=normal, 1=anon, 2=roleplay /*0881*/ uint8 face; /*0882*/ uint8 drakkin_details; // Face Details (Spikes) on Drakkin 0 - 7 @@ -899,7 +901,7 @@ struct PlayerProfile_Struct //23576 Octets /*00228*/ EquipStruct equipment[9]; //Live Shows [108] for this part }; /*00336*/ uint8 unknown00224[156]; // Live Shows [160] -/*00496*/ Color_Struct item_tint[9]; // RR GG BB 00 +/*00496*/ TintProfile item_tint; // RR GG BB 00 /*00544*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // [3600] AAs 12 bytes each /*04132*/ uint32 points; // Unspent Practice points - RELOCATED??? /*04136*/ uint32 mana; // Current mana @@ -1155,7 +1157,7 @@ struct WearChange_Struct{ /*002*/ uint32 material; /*006*/ uint32 unknown06; /*010*/ uint32 elite_material; // 1 for Drakkin Elite Material -/*014*/ Color_Struct color; +/*014*/ Tint_Struct color; /*018*/ uint8 wear_slot_id; /*019*/ }; @@ -2954,27 +2956,6 @@ struct PetitionBug_Struct{ char text[1028]; }; -struct DyeStruct -{ - union - { - struct - { - struct Color_Struct head; - struct Color_Struct chest; - struct Color_Struct arms; - struct Color_Struct wrists; - struct Color_Struct hands; - struct Color_Struct legs; - struct Color_Struct feet; - struct Color_Struct primary; // you can't actually dye this - struct Color_Struct secondary; // or this - } - dyes; - struct Color_Struct dye[9]; - }; -}; - struct ApproveZone_Struct { char name[64]; uint32 zoneid; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index cee33cb8e..36941d421 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -905,7 +905,7 @@ namespace Titanium // OUT(unknown00178[10]); for (r = 0; r < 9; r++) { OUT(item_material[r]); - OUT(item_tint[r].Color); + OUT(item_tint.Slot[r].Color); } // OUT(unknown00224[48]); for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) { @@ -1224,7 +1224,7 @@ namespace Titanium eq->Race[char_index] = 1; for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { - eq->CS_Colors[char_index][index].Color = emu_cse->Equip[index].Color.Color; + eq->CS_Colors[char_index].Slot[index].Color = emu_cse->Equip[index].Color.Color; } eq->BeardColor[char_index] = emu_cse->BeardColor; @@ -1261,7 +1261,7 @@ namespace Titanium eq->Race[char_index] = 0; for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { - eq->CS_Colors[char_index][index].Color = 0; + eq->CS_Colors[char_index].Slot[index].Color = 0; } eq->BeardColor[char_index] = 0; @@ -1601,7 +1601,7 @@ namespace Titanium // eq->unknown0194[3] = emu->unknown0194[3]; for (k = 0; k < 9; k++) { eq->equipment[k] = emu->equipment[k].Material; - eq->colors[k].Color = emu->colors[k].Color; + eq->equipment_tint.Slot[k].Color = emu->equipment_tint.Slot[k].Color; } for (k = 0; k < 8; k++) { eq->set_to_0xFF[k] = 0xFF; diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 141966b09..21364e070 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -118,7 +118,7 @@ struct AdventureInfo { ** Merth: Gave struct a name so gcc 2.96 would compile ** */ -struct Color_Struct +struct Tint_Struct { union { struct { @@ -126,11 +126,28 @@ struct Color_Struct uint8 Green; uint8 Red; uint8 UseTint; // if there's a tint this is FF - } RGB; + }; uint32 Color; }; }; +struct TintProfile { + union { + struct { + Tint_Struct Head; + Tint_Struct Chest; + Tint_Struct Arms; + Tint_Struct Wrist; + Tint_Struct Hands; + Tint_Struct Legs; + Tint_Struct Feet; + Tint_Struct Primary; + Tint_Struct Secondary; + }; + Tint_Struct Slot[EQEmu::textures::TextureCount]; + }; +}; + /* ** Character Selection Struct ** Length: 1704 Bytes @@ -139,7 +156,7 @@ struct Color_Struct struct CharacterSelect_Struct { /*0000*/ uint32 Race[10]; // Characters Race -/*0040*/ Color_Struct CS_Colors[10][9]; // Characters Equipment Colors +/*0040*/ TintProfile CS_Colors[10]; // Characters Equipment Colors - packet requires length for 10 characters..but, client is limited to 8 /*0400*/ uint8 BeardColor[10]; // Characters beard Color /*0410*/ uint8 HairStyle[10]; // Characters hair style /*0420*/ uint32 Equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be) @@ -284,22 +301,7 @@ union }; /*0340*/ uint32 spawnId; // Spawn Id /*0344*/ uint8 unknown0344[4]; -/*0348*/ union - { - struct - { - /*0348*/ Color_Struct color_helmet; // Color of helmet item - /*0352*/ Color_Struct color_chest; // Color of chest item - /*0356*/ Color_Struct color_arms; // Color of arms item - /*0360*/ Color_Struct color_bracers; // Color of bracers item - /*0364*/ Color_Struct color_hands; // Color of hands item - /*0368*/ Color_Struct color_legs; // Color of legs item - /*0372*/ Color_Struct color_feet; // Color of feet item - /*0376*/ Color_Struct color_primary; // Color of primary item - /*0380*/ Color_Struct color_secondary; // Color of secondary item - } equipment_colors; - /*0348*/ Color_Struct colors[9]; // Array elements correspond to struct equipment_colors above - }; +/*0348*/ TintProfile equipment_tint; /*0384*/ uint8 lfg; // 0=off, 1=lfg on /*0385*/ @@ -812,7 +814,7 @@ struct PlayerProfile_Struct /*00178*/ uint8 unknown00178[10]; /*00188*/ uint32 item_material[9]; // Item texture/material of worn items /*00224*/ uint8 unknown00224[44]; -/*00268*/ Color_Struct item_tint[9]; // RR GG BB 00 +/*00268*/ TintProfile item_tint; // RR GG BB 00 /*00304*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // AAs /*02224*/ uint32 points; // Unspent Practice points /*02228*/ uint32 mana; // Current mana @@ -1035,7 +1037,7 @@ struct SpecialMesg_Struct struct WearChange_Struct{ /*000*/ uint16 spawn_id; /*002*/ uint16 material; -/*004*/ Color_Struct color; +/*004*/ Tint_Struct color; /*009*/ uint8 wear_slot_id; }; @@ -2591,27 +2593,6 @@ struct PetitionBug_Struct{ char text[1028]; }; -struct DyeStruct -{ - union - { - struct - { - struct Color_Struct head; - struct Color_Struct chest; - struct Color_Struct arms; - struct Color_Struct wrists; - struct Color_Struct hands; - struct Color_Struct legs; - struct Color_Struct feet; - struct Color_Struct primary; // you can't actually dye this - struct Color_Struct secondary; // or this - } - dyes; - struct Color_Struct dye[9]; - }; -}; - struct ApproveZone_Struct { char name[64]; uint32 zoneid; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 2a9a4862a..8472c1034 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1813,7 +1813,7 @@ namespace UF //eq->colors[r].color = emu->colors[r].color; } for (r = 0; r < 7; r++) { - OUT(item_tint[r].Color); + OUT(item_tint.Slot[r].Color); } // OUT(unknown00224[48]); //NOTE: new client supports 300 AAs, our internal rep/PP @@ -3060,7 +3060,7 @@ namespace UF for (k = 0; k < 9; ++k) { { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].Color); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); } } } diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 21fbdf15f..00a2e4aad 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -122,25 +122,42 @@ struct AdventureInfo { ** Merth: Gave struct a name so gcc 2.96 would compile ** */ -struct Color_Struct +struct Tint_Struct { union { struct { - uint8 blue; + uint8 Blue; uint8 Green; uint8 Red; uint8 UseTint; // if there's a tint this is FF - } RGB; + }; uint32 Color; }; }; +struct TintProfile { + union { + struct { + Tint_Struct Head; + Tint_Struct Chest; + Tint_Struct Arms; + Tint_Struct Wrist; + Tint_Struct Hands; + Tint_Struct Legs; + Tint_Struct Feet; + Tint_Struct Primary; + Tint_Struct Secondary; + }; + Tint_Struct Slot[EQEmu::textures::TextureCount]; + }; +}; + struct CharSelectEquip { uint32 Material; uint32 Unknown1; uint32 EliteMaterial; - Color_Struct Color; + Tint_Struct Color; }; struct CharacterSelectEntry_Struct @@ -314,22 +331,7 @@ struct Spawn_Struct /*0000*/ uint32 unknown18; /*0000*/ uint32 unknown19; Spawn_Struct_Position Position; -/*0000*/ union - { - struct - { - /*0000*/ Color_Struct color_helmet; // Color of helmet item - /*0000*/ Color_Struct color_chest; // Color of chest item - /*0000*/ Color_Struct color_arms; // Color of arms item - /*0000*/ Color_Struct color_bracers; // Color of bracers item - /*0000*/ Color_Struct color_hands; // Color of hands item - /*0000*/ Color_Struct color_legs; // Color of legs item - /*0000*/ Color_Struct color_feet; // Color of feet item - /*0000*/ Color_Struct color_primary; // Color of primary item - /*0000*/ Color_Struct color_secondary; // Color of secondary item - } equipment_colors; - /*0000*/ Color_Struct colors[9]; // Array elements correspond to struct equipment_colors above - }; +/*0000*/ TintProfile equipment_tint; // skip these bytes if not a valid player race /*0000*/ union @@ -969,7 +971,7 @@ struct PlayerProfile_Struct /*00236*/ EquipStruct equipment[9]; //Underfoot Shows [108] for this part }; /*00344*/ uint8 unknown00344[168]; // Underfoot Shows [160] -/*00512*/ Color_Struct item_tint[9]; // RR GG BB 00 +/*00512*/ TintProfile item_tint; // RR GG BB 00 /*00548*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // [3600] AAs 12 bytes each /*04148*/ uint32 points; // Unspent Practice points - RELOCATED??? /*04152*/ uint32 mana; // Current mana @@ -1232,7 +1234,7 @@ struct WearChange_Struct{ /*002*/ uint32 material; /*006*/ uint32 unknown06; /*010*/ uint32 elite_material; // 1 for Drakkin Elite Material -/*014*/ Color_Struct color; +/*014*/ Tint_Struct color; /*018*/ uint8 wear_slot_id; /*019*/ }; @@ -3162,27 +3164,6 @@ struct PetitionBug_Struct{ char text[1028]; }; -struct DyeStruct -{ - union - { - struct - { - struct Color_Struct head; - struct Color_Struct chest; - struct Color_Struct arms; - struct Color_Struct wrists; - struct Color_Struct hands; - struct Color_Struct legs; - struct Color_Struct feet; - struct Color_Struct primary; // you can't actually dye this - struct Color_Struct secondary; // or this - } - dyes; - struct Color_Struct dye[9]; - }; -}; - struct ApproveZone_Struct { char name[64]; uint32 zoneid; diff --git a/common/textures.cpp b/common/textures.cpp index bbfda39a2..bbad13b26 100644 --- a/common/textures.cpp +++ b/common/textures.cpp @@ -83,27 +83,12 @@ // } //} -struct EQEmu::TextureProfile -{ - union { - struct { - uint32 Head; - uint32 Chest; - uint32 Arms; - uint32 Wrist; - uint32 Hands; - uint32 Legs; - uint32 Feet; - uint32 Primary; - uint32 Secondary; - }; - uint32 Texture[textures::TextureCount]; - }; - - TextureProfile(); -}; - EQEmu::TextureProfile::TextureProfile() { memset(&Texture, 0, (sizeof(uint32) * textures::TextureCount)); } + +EQEmu::TintProfile::TintProfile() +{ + memset(&Slot, 0, (sizeof(uint32) * textures::TextureCount)); +} diff --git a/common/textures.h b/common/textures.h index e13776279..598f5dd3a 100644 --- a/common/textures.h +++ b/common/textures.h @@ -54,7 +54,57 @@ namespace EQEmu } /*textures*/ - struct TextureProfile; + struct TextureProfile { + union { + struct { + uint32 Head; + uint32 Chest; + uint32 Arms; + uint32 Wrist; + uint32 Hands; + uint32 Legs; + uint32 Feet; + uint32 Primary; + uint32 Secondary; + }; + uint32 Texture[textures::TextureCount]; + }; + + TextureProfile(); + }; + + struct Tint_Struct { + union { + struct { + uint8 Blue; + uint8 Green; + uint8 Red; + uint8 UseTint; // if there's a tint this is FF + }; + uint32 Color; + }; + + //Tint_Struct(); + }; + + struct TintProfile { + union { + struct { + Tint_Struct Head; + Tint_Struct Chest; + Tint_Struct Arms; + Tint_Struct Wrist; + Tint_Struct Hands; + Tint_Struct Legs; + Tint_Struct Feet; + Tint_Struct Primary; + Tint_Struct Secondary; + }; + Tint_Struct Slot[textures::TextureCount]; + }; + + TintProfile(); + }; } /*EQEmu*/ diff --git a/world/worlddb.cpp b/world/worlddb.cpp index ac61e7b64..7df66b85a 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -235,10 +235,10 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou auto results_b = database.QueryDatabase(cquery); uint8 slot = 0; for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) { slot = atoi(row_b[0]); - pp.item_tint[slot].RGB.Red = atoi(row_b[1]); - pp.item_tint[slot].RGB.Green = atoi(row_b[2]); - pp.item_tint[slot].RGB.Blue = atoi(row_b[3]); - pp.item_tint[slot].RGB.UseTint = atoi(row_b[4]); + pp.item_tint.Slot[slot].Red = atoi(row_b[1]); + pp.item_tint.Slot[slot].Green = atoi(row_b[2]); + pp.item_tint.Slot[slot].Blue = atoi(row_b[3]); + pp.item_tint.Slot[slot].UseTint = atoi(row_b[4]); } /* Character Material Data End */ @@ -279,8 +279,8 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou } else { uint32 color = 0; - if (pp.item_tint[matslot].RGB.UseTint) { - color = pp.item_tint[matslot].Color; + if (pp.item_tint.Slot[matslot].UseTint) { + color = pp.item_tint.Slot[matslot].Color; } else { color = inst->GetColor(); diff --git a/zone/bot.cpp b/zone/bot.cpp index e94783d2a..67b7beb82 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2965,12 +2965,12 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.equipment[i].EliteMaterial = item->EliteMaterial; ns->spawn.equipment[i].HeroForgeModel = item->HerosForgeModel; if (armor_tint[i]) - ns->spawn.colors[i].Color = armor_tint[i]; + ns->spawn.equipment_tint.Slot[i].Color = armor_tint[i]; else - ns->spawn.colors[i].Color = item->Color; + ns->spawn.equipment_tint.Slot[i].Color = item->Color; } else { if (armor_tint[i]) - ns->spawn.colors[i].Color = armor_tint[i]; + ns->spawn.equipment_tint.Slot[i].Color = armor_tint[i]; } } } @@ -2982,7 +2982,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { if(strlen(item->IDFile) > 2) ns->spawn.equipment[EQEmu::textures::TexturePrimary].Material = atoi(&item->IDFile[2]); - ns->spawn.colors[EQEmu::textures::TexturePrimary].Color = GetEquipmentColor(EQEmu::textures::TexturePrimary); + ns->spawn.equipment_tint.Primary.Color = GetEquipmentColor(EQEmu::textures::TexturePrimary); } } @@ -2993,7 +2993,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { if(strlen(item->IDFile) > 2) ns->spawn.equipment[EQEmu::textures::TextureSecondary].Material = atoi(&item->IDFile[2]); - ns->spawn.colors[EQEmu::textures::TextureSecondary].Color = GetEquipmentColor(EQEmu::textures::TextureSecondary); + ns->spawn.equipment_tint.Secondary.Color = GetEquipmentColor(EQEmu::textures::TextureSecondary); } } } diff --git a/zone/client.cpp b/zone/client.cpp index a3da174a9..6ec655dc7 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -3062,19 +3062,19 @@ void Client::Tell_StringID(uint32 string_id, const char *who, const char *messag } void Client::SetTint(int16 in_slot, uint32 color) { - Color_Struct new_color; + EQEmu::Tint_Struct new_color; new_color.Color = color; SetTint(in_slot, new_color); database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color); } // Still need to reconcile bracer01 versus bracer02 -void Client::SetTint(int16 in_slot, Color_Struct& color) { +void Client::SetTint(int16 in_slot, EQEmu::Tint_Struct& color) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); if (matslot != EQEmu::textures::TextureInvalid) { - m_pp.item_tint[matslot].Color = color.Color; + m_pp.item_tint.Slot[matslot].Color = color.Color; database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.Color); } diff --git a/zone/client.h b/zone/client.h index b401eac53..b3965b031 100644 --- a/zone/client.h +++ b/zone/client.h @@ -253,7 +253,7 @@ public: void SendBuyerPacket(Client* Buyer); GetItems_Struct* GetTraderItems(); void SendBazaarWelcome(); - void DyeArmor(DyeStruct* dye); + void DyeArmor(EQEmu::TintProfile* dye); uint8 SlotConvert(uint8 slot,bool bracer=false); void Message_StringID(uint32 type, uint32 string_id, uint32 distance = 0); void Message_StringID(uint32 type, uint32 string_id, const char* message,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0, uint32 distance = 0); @@ -802,7 +802,7 @@ public: uint32 NukeItem(uint32 itemnum, uint8 where_to_check = (invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor)); void SetTint(int16 slot_id, uint32 color); - void SetTint(int16 slot_id, Color_Struct& color); + void SetTint(int16 slot_id, EQEmu::Tint_Struct& color); void SetMaterial(int16 slot_id, uint32 item_id); void Undye(); int32 GetItemIDAt(int16 slot_id); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index af40253a3..69f0781af 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1315,9 +1315,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /* Set item material tint */ for (int i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTexture; i++) { - if (m_pp.item_tint[i].RGB.UseTint == 1 || m_pp.item_tint[i].RGB.UseTint == 255) + if (m_pp.item_tint.Slot[i].UseTint == 1 || m_pp.item_tint.Slot[i].UseTint == 255) { - m_pp.item_tint[i].RGB.UseTint = 0xFF; + m_pp.item_tint.Slot[i].UseTint = 0xFF; } } @@ -5379,10 +5379,10 @@ void Client::Handle_OP_DumpName(const EQApplicationPacket *app) void Client::Handle_OP_Dye(const EQApplicationPacket *app) { - if (app->size != sizeof(DyeStruct)) - printf("Wrong size of DyeStruct, Got: %i, Expected: %zu\n", app->size, sizeof(DyeStruct)); + if (app->size != sizeof(EQEmu::TintProfile)) + printf("Wrong size of DyeStruct, Got: %i, Expected: %zu\n", app->size, sizeof(EQEmu::TintProfile)); else{ - DyeStruct* dye = (DyeStruct*)app->pBuffer; + EQEmu::TintProfile* dye = (EQEmu::TintProfile*)app->pBuffer; DyeArmor(dye); } return; diff --git a/zone/command.cpp b/zone/command.cpp index beb405d26..c52b613db 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -7128,7 +7128,7 @@ void Client::Undye() { database.SaveInventory(CharacterID(), inst, slot2); } - m_pp.item_tint[cur_slot].Color = 0; + m_pp.item_tint.Slot[cur_slot].Color = 0; SendWearChange(cur_slot); } diff --git a/zone/corpse.cpp b/zone/corpse.cpp index d42801590..e5d12b8dd 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -116,15 +116,15 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std: pc->Lock(); /* Load Item Tints */ - pc->item_tint[0].Color = pcs->item_tint[0].Color; - pc->item_tint[1].Color = pcs->item_tint[1].Color; - pc->item_tint[2].Color = pcs->item_tint[2].Color; - pc->item_tint[3].Color = pcs->item_tint[3].Color; - pc->item_tint[4].Color = pcs->item_tint[4].Color; - pc->item_tint[5].Color = pcs->item_tint[5].Color; - pc->item_tint[6].Color = pcs->item_tint[6].Color; - pc->item_tint[7].Color = pcs->item_tint[7].Color; - pc->item_tint[8].Color = pcs->item_tint[8].Color; + pc->item_tint.Head.Color = pcs->item_tint.Head.Color; + pc->item_tint.Chest.Color = pcs->item_tint.Chest.Color; + pc->item_tint.Arms.Color = pcs->item_tint.Arms.Color; + pc->item_tint.Wrist.Color = pcs->item_tint.Wrist.Color; + pc->item_tint.Hands.Color = pcs->item_tint.Hands.Color; + pc->item_tint.Legs.Color = pcs->item_tint.Legs.Color; + pc->item_tint.Feet.Color = pcs->item_tint.Feet.Color; + pc->item_tint.Primary.Color = pcs->item_tint.Primary.Color; + pc->item_tint.Secondary.Color = pcs->item_tint.Secondary.Color; /* Load Physical Appearance */ pc->haircolor = pcs->haircolor; @@ -162,7 +162,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP { corpse_graveyard_timer.Disable(); - memset(item_tint, 0, sizeof(item_tint)); + //memset(item_tint, 0, sizeof(item_tint)); is_corpse_changed = false; is_player_corpse = false; @@ -277,7 +277,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( corpse_graveyard_timer.Disable(); } - memset(item_tint, 0, sizeof(item_tint)); + //memset(item_tint, 0, sizeof(item_tint)); for (i = 0; i < MAX_LOOTERS; i++){ allowed_looters[i] = 0; @@ -321,7 +321,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( } // get their tints - memcpy(item_tint, &client->GetPP().item_tint, sizeof(item_tint)); + memcpy(&item_tint.Slot, &client->GetPP().item_tint, sizeof(item_tint)); // TODO soulbound items need not be added to corpse, but they need // to go into the regular slots on the player, out of bags @@ -502,7 +502,7 @@ in_helmtexture, if (!zone->HasGraveyard() || wasAtGraveyard) corpse_graveyard_timer.Disable(); - memset(item_tint, 0, sizeof(item_tint)); + //memset(item_tint, 0, sizeof(item_tint)); is_corpse_changed = false; is_player_corpse = true; @@ -591,7 +591,7 @@ bool Corpse::Save() { dbpc->helmtexture = this->helmtexture; dbpc->exp = rez_experience; - memcpy(dbpc->item_tint, item_tint, sizeof(dbpc->item_tint)); + memcpy(&dbpc->item_tint.Slot, &item_tint.Slot, sizeof(dbpc->item_tint)); dbpc->haircolor = haircolor; dbpc->beardcolor = beardcolor; dbpc->eyecolor2 = eyecolor1; @@ -1420,9 +1420,7 @@ uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { item = database.GetItem(GetEquipment(material_slot)); if(item != NO_ITEM) { - return item_tint[material_slot].RGB.UseTint ? - item_tint[material_slot].Color : - item->Color; + return (item_tint.Slot[material_slot].UseTint ? item_tint.Slot[material_slot].Color : item->Color); } return 0; diff --git a/zone/corpse.h b/zone/corpse.h index 03a48dd87..c08bece02 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -154,7 +154,7 @@ private: Timer corpse_delay_timer; Timer corpse_graveyard_timer; Timer loot_cooldown_timer; /* Delay between loot actions on the corpse entity */ - Color_Struct item_tint[9]; + EQEmu::TintProfile item_tint; }; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 360e3a070..8eacb8b62 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -2019,28 +2019,28 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { safe_delete(qspack); } -void Client::DyeArmor(DyeStruct* dye){ +void Client::DyeArmor(EQEmu::TintProfile* dye){ int16 slot=0; for (int i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTintableTexture; i++) { - if ((m_pp.item_tint[i].Color & 0x00FFFFFF) != (dye->dye[i].Color & 0x00FFFFFF)) { + if ((m_pp.item_tint.Slot[i].Color & 0x00FFFFFF) != (dye->Slot[i].Color & 0x00FFFFFF)) { slot = m_inv.HasItem(32557, 1, invWherePersonal); if (slot != INVALID_INDEX){ DeleteItemInInventory(slot,1,true); uint8 slot2=SlotConvert(i); ItemInst* inst = this->m_inv.GetItem(slot2); if(inst){ - uint32 armor_color = ((uint32)dye->dye[i].RGB.Red << 16) | ((uint32)dye->dye[i].RGB.Green << 8) | ((uint32)dye->dye[i].RGB.Blue); + uint32 armor_color = ((uint32)dye->Slot[i].Red << 16) | ((uint32)dye->Slot[i].Green << 8) | ((uint32)dye->Slot[i].Blue); inst->SetColor(armor_color); database.SaveCharacterMaterialColor(this->CharacterID(), i, armor_color); database.SaveInventory(CharacterID(),inst,slot2); - if(dye->dye[i].RGB.UseTint) - m_pp.item_tint[i].RGB.UseTint = 0xFF; + if(dye->Slot[i].UseTint) + m_pp.item_tint.Slot[i].UseTint = 0xFF; else - m_pp.item_tint[i].RGB.UseTint=0x00; + m_pp.item_tint.Slot[i].UseTint=0x00; } - m_pp.item_tint[i].RGB.Blue=dye->dye[i].RGB.Blue; - m_pp.item_tint[i].RGB.Red=dye->dye[i].RGB.Red; - m_pp.item_tint[i].RGB.Green=dye->dye[i].RGB.Green; + m_pp.item_tint.Slot[i].Blue=dye->Slot[i].Blue; + m_pp.item_tint.Slot[i].Red=dye->Slot[i].Red; + m_pp.item_tint.Slot[i].Green=dye->Slot[i].Green; SendWearChange(i); } else{ @@ -2636,7 +2636,7 @@ uint32 Client::GetEquipmentColor(uint8 material_slot) const const EQEmu::ItemBase *item = database.GetItem(GetEquipment(material_slot)); if(item != nullptr) - return ((m_pp.item_tint[material_slot].RGB.UseTint) ? m_pp.item_tint[material_slot].Color : item->Color); + return ((m_pp.item_tint.Slot[material_slot].UseTint) ? m_pp.item_tint.Slot[material_slot].Color : item->Color); return 0; } diff --git a/zone/mob.cpp b/zone/mob.cpp index d2e02a970..2918aa413 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1162,7 +1162,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.equipment[i].Material = GetEquipmentMaterial(i); ns->spawn.equipment[i].EliteMaterial = IsEliteMaterialItem(i); ns->spawn.equipment[i].HeroForgeModel = GetHerosForgeModel(i); - ns->spawn.colors[i].Color = GetEquipmentColor(i); + ns->spawn.equipment_tint.Slot[i].Color = GetEquipmentColor(i); } } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 405cd0daa..62120accb 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1170,10 +1170,10 @@ bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile for (auto row = results.begin(); row != results.end(); ++row) { r = 0; i = atoi(row[r]); /* Slot */ r++; - pp->item_tint[i].RGB.Blue = atoi(row[r]); r++; - pp->item_tint[i].RGB.Green = atoi(row[r]); r++; - pp->item_tint[i].RGB.Red = atoi(row[r]); r++; - pp->item_tint[i].RGB.UseTint = atoi(row[r]); + pp->item_tint.Slot[i].Blue = atoi(row[r]); r++; + pp->item_tint.Slot[i].Green = atoi(row[r]); r++; + pp->item_tint.Slot[i].Red = atoi(row[r]); r++; + pp->item_tint.Slot[i].UseTint = atoi(row[r]); } return true; } @@ -3627,9 +3627,9 @@ uint32 ZoneDatabase::UpdateCharacterCorpse(uint32 db_id, uint32 char_id, const c dbpc->plat, dbpc->haircolor, dbpc->beardcolor, dbpc->eyecolor1, dbpc->eyecolor2, dbpc->hairstyle, dbpc->face, dbpc->beard, dbpc->drakkin_heritage, dbpc->drakkin_tattoo, dbpc->drakkin_details, - dbpc->item_tint[0].Color, dbpc->item_tint[1].Color, dbpc->item_tint[2].Color, - dbpc->item_tint[3].Color, dbpc->item_tint[4].Color, dbpc->item_tint[5].Color, - dbpc->item_tint[6].Color, dbpc->item_tint[7].Color, dbpc->item_tint[8].Color, + dbpc->item_tint.Head.Color, dbpc->item_tint.Chest.Color, dbpc->item_tint.Arms.Color, + dbpc->item_tint.Wrist.Color, dbpc->item_tint.Hands.Color, dbpc->item_tint.Legs.Color, + dbpc->item_tint.Feet.Color, dbpc->item_tint.Primary.Color, dbpc->item_tint.Secondary.Color, db_id); auto results = QueryDatabase(query); @@ -3720,15 +3720,15 @@ uint32 ZoneDatabase::SaveCharacterCorpse(uint32 charid, const char* charname, ui dbpc->drakkin_heritage, dbpc->drakkin_tattoo, dbpc->drakkin_details, - dbpc->item_tint[0].Color, - dbpc->item_tint[1].Color, - dbpc->item_tint[2].Color, - dbpc->item_tint[3].Color, - dbpc->item_tint[4].Color, - dbpc->item_tint[5].Color, - dbpc->item_tint[6].Color, - dbpc->item_tint[7].Color, - dbpc->item_tint[8].Color + dbpc->item_tint.Head.Color, + dbpc->item_tint.Chest.Color, + dbpc->item_tint.Arms.Color, + dbpc->item_tint.Wrist.Color, + dbpc->item_tint.Hands.Color, + dbpc->item_tint.Legs.Color, + dbpc->item_tint.Feet.Color, + dbpc->item_tint.Primary.Color, + dbpc->item_tint.Secondary.Color ); auto results = QueryDatabase(query); uint32 last_insert_id = results.LastInsertedID(); @@ -3900,15 +3900,15 @@ bool ZoneDatabase::LoadCharacterCorpseData(uint32 corpse_id, PlayerCorpse_Struct pcs->drakkin_heritage = atoul(row[i++]); // drakkin_heritage, pcs->drakkin_tattoo = atoul(row[i++]); // drakkin_tattoo, pcs->drakkin_details = atoul(row[i++]); // drakkin_details, - pcs->item_tint[0].Color = atoul(row[i++]); // wc_1, - pcs->item_tint[1].Color = atoul(row[i++]); // wc_2, - pcs->item_tint[2].Color = atoul(row[i++]); // wc_3, - pcs->item_tint[3].Color = atoul(row[i++]); // wc_4, - pcs->item_tint[4].Color = atoul(row[i++]); // wc_5, - pcs->item_tint[5].Color = atoul(row[i++]); // wc_6, - pcs->item_tint[6].Color = atoul(row[i++]); // wc_7, - pcs->item_tint[7].Color = atoul(row[i++]); // wc_8, - pcs->item_tint[8].Color = atoul(row[i++]); // wc_9 + pcs->item_tint.Head.Color = atoul(row[i++]); // wc_1, + pcs->item_tint.Chest.Color = atoul(row[i++]); // wc_2, + pcs->item_tint.Arms.Color = atoul(row[i++]); // wc_3, + pcs->item_tint.Wrist.Color = atoul(row[i++]); // wc_4, + pcs->item_tint.Hands.Color = atoul(row[i++]); // wc_5, + pcs->item_tint.Legs.Color = atoul(row[i++]); // wc_6, + pcs->item_tint.Feet.Color = atoul(row[i++]); // wc_7, + pcs->item_tint.Primary.Color = atoul(row[i++]); // wc_8, + pcs->item_tint.Secondary.Color = atoul(row[i++]); // wc_9 } query = StringFormat( "SELECT \n" diff --git a/zone/zonedump.h b/zone/zonedump.h index be82b1967..743e1a94c 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -169,7 +169,7 @@ struct PlayerCorpse_Struct { uint32 silver; uint32 gold; uint32 plat; - Color_Struct item_tint[9]; + EQEmu::TintProfile item_tint; uint8 haircolor; uint8 beardcolor; uint8 eyecolor1; From cd8cd90a38a1bb48c9258cf06337d6d1db1762f6 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 1 Jun 2016 08:54:26 -0400 Subject: [PATCH 143/693] Implemented EQEmu::TextureProfile --- changelog.txt | 1 + common/eq_packet_structs.h | 40 ++-------- common/extprofile.h | 2 +- common/patches/rof.cpp | 30 ++++---- common/patches/rof2.cpp | 30 ++++---- common/patches/rof2_structs.h | 120 +++++++++++++++++------------- common/patches/rof_structs.h | 120 +++++++++++++++++------------- common/patches/sod.cpp | 28 +++---- common/patches/sod_structs.h | 83 +++++++++------------ common/patches/sof.cpp | 18 ++--- common/patches/sof_structs.h | 83 +++++++++------------ common/patches/titanium.cpp | 8 +- common/patches/titanium_structs.h | 46 +++++++----- common/patches/uf.cpp | 34 ++++----- common/patches/uf_structs.h | 83 +++++++++------------ common/textures.cpp | 7 +- common/textures.h | 51 ++++++++++--- world/worlddb.cpp | 20 ++--- zone/beacon.cpp | 2 +- zone/bot.cpp | 18 ++--- zone/client.cpp | 6 +- zone/corpse.cpp | 6 +- zone/encounter.cpp | 2 +- zone/lua_general.cpp | 18 ++--- zone/mob.cpp | 25 +++---- zone/mob.h | 6 +- zone/npc.cpp | 2 +- zone/zonedb.cpp | 38 +++++----- zone/zonedump.h | 2 +- 29 files changed, 467 insertions(+), 462 deletions(-) diff --git a/changelog.txt b/changelog.txt index 8708d1cd9..003ac4555 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 06/01/2016 == Uleat: Implemented EQEmu::TintProfile +Uleat: Implemented EQEmu::TextureProfile == 05/31/2016 == Uleat: Converted enumeration MaterialSlots to EQEmu::textures::TextureSlot diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 23a92082c..7674f138f 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -126,22 +126,9 @@ struct LDoNTrapTemplate // All clients translate the character select information to some degree -struct EquipStruct -{ - uint32 Material; - uint32 Unknown1; - uint32 EliteMaterial; - uint32 HeroForgeModel; - uint32 Material2; // Same as material? -}; - struct CharSelectEquip { - uint32 Material; - uint32 Unknown1; - uint32 EliteMaterial; - uint32 HeroForgeModel; - uint32 Material2; + EQEmu::Texture_Struct Textures; EQEmu::Tint_Struct Color; }; @@ -158,7 +145,7 @@ struct CharacterSelectEntry_Struct uint16 Instance; uint8 Gender; uint8 Face; - CharSelectEquip Equip[9]; + CharSelectEquip Equip[EQEmu::textures::TextureCount]; uint8 Unknown15; // Seen FF uint8 Unknown19; // Seen FF uint32 DrakkinTattoo; @@ -267,22 +254,7 @@ struct Spawn_Struct { /*0189*/ uint32 petOwnerId; // If this is a pet, the spawn id of owner /*0193*/ uint8 guildrank; // 0=normal, 1=officer, 2=leader /*0194*/ uint8 unknown0194[3]; -/*0197*/ union -{ - struct - { - /*0000*/ EquipStruct equip_helmet; // Equipment: Helmet visual - /*0000*/ EquipStruct equip_chest; // Equipment: Chest visual - /*0000*/ EquipStruct equip_arms; // Equipment: Arms visual - /*0000*/ EquipStruct equip_bracers; // Equipment: Wrist visual - /*0000*/ EquipStruct equip_hands; // Equipment: Hands visual - /*0000*/ EquipStruct equip_legs; // Equipment: Legs visual - /*0000*/ EquipStruct equip_feet; // Equipment: Boots visual - /*0000*/ EquipStruct equip_primary; // Equipment: Main visual - /*0000*/ EquipStruct equip_secondary; // Equipment: Off visual - } equip; - /*0000*/ EquipStruct equipment[EQEmu::textures::TextureCount]; -}; +/*0197*/ EQEmu::TextureProfile equipment; /*0233*/ float runspeed; // Speed when running /*0036*/ uint8 afk; // 0=no, 1=afk /*0238*/ uint32 guildID; // Current guild @@ -854,7 +826,7 @@ struct SuspendedMinion_Struct /*002*/ uint32 HP; /*006*/ uint32 Mana; /*010*/ SpellBuff_Struct Buffs[BUFF_COUNT]; - /*510*/ uint32 Items[EQEmu::textures::TextureCount]; + /*510*/ EQEmu::TextureShortProfile Items; /*546*/ char Name[64]; /*610*/ }; @@ -962,7 +934,7 @@ struct PlayerProfile_Struct /*0304*/ uint8 ability_time_minutes; /*0305*/ uint8 ability_time_hours; //place holder /*0306*/ uint8 unknown0306[6]; // @bp Spacer/Flag? -/*0312*/ uint32 item_material[EQEmu::textures::TextureCount]; // Item texture/material of worn/held items +/*0312*/ EQEmu::TextureShortProfile item_material; // Item texture/material of worn/held items /*0348*/ uint8 unknown0348[44]; /*0392*/ EQEmu::TintProfile item_tint; /*0428*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; @@ -2118,7 +2090,7 @@ struct Illusion_Struct { //size: 256 - SoF /*092*/ uint32 drakkin_heritage; // /*096*/ uint32 drakkin_tattoo; // /*100*/ uint32 drakkin_details; // -/*104*/ uint32 armor_tint[EQEmu::textures::TextureCount]; // +/*104*/ EQEmu::TintProfile armor_tint; // /*140*/ uint8 eyecolor1; // Field Not Identified in any Illusion Struct /*141*/ uint8 eyecolor2; // Field Not Identified in any Illusion Struct /*142*/ uint8 unknown138[114]; // diff --git a/common/extprofile.h b/common/extprofile.h index b376a9edd..e53480631 100644 --- a/common/extprofile.h +++ b/common/extprofile.h @@ -40,7 +40,7 @@ struct ExtendedProfile_Struct { uint16 old_pet_hp; /* Not Used */ uint16 old_pet_mana; /* Not Used */ SpellBuff_Struct pet_buffs[BUFF_COUNT]; /* Not Used */ - uint32 pet_items[EQEmu::textures::TextureCount]; /* Not Used */ + EQEmu::TextureShortProfile pet_items; /* Not Used */ char merc_name[64]; /* Used */ uint32 aa_effects; /* Used */ diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index d14cfb810..61c9c1105 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2070,7 +2070,7 @@ namespace RoF for (int r = 0; r < 9; r++) { - outapp->WriteUInt32(emu->item_material[r]); + outapp->WriteUInt32(emu->item_material.Slot[r].Material); outapp->WriteUInt32(0); outapp->WriteUInt32(0); outapp->WriteUInt32(0); @@ -3047,11 +3047,11 @@ namespace RoF eq_cse->Face = emu_cse->Face; for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { - eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; - eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; - eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; - eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HeroForgeModel; - eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Material2; + eq_cse->Equip[equip_index].Textures.Material = emu_cse->Equip[equip_index].Textures.Material; + eq_cse->Equip[equip_index].Textures.Unknown1 = emu_cse->Equip[equip_index].Textures.Unknown1; + eq_cse->Equip[equip_index].Textures.EliteMaterial = emu_cse->Equip[equip_index].Textures.EliteMaterial; + eq_cse->Equip[equip_index].Textures.HeroForgeModel = emu_cse->Equip[equip_index].Textures.HeroForgeModel; + eq_cse->Equip[equip_index].Textures.Material2 = emu_cse->Equip[equip_index].Textures.Material2; eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color; } @@ -4090,17 +4090,17 @@ namespace RoF } } - structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; + structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; for (k = 0; k < 9; k++) { - Equipment[k].Material = emu->equipment[k].Material; - Equipment[k].Unknown1 = emu->equipment[k].Unknown1; - Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial; - Equipment[k].HeroForgeModel = emu->equipment[k].HeroForgeModel; - Equipment[k].Material2 = emu->equipment[k].Material2; + Equipment[k].Material = emu->equipment.Slot[k].Material; + Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; + Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; + Equipment[k].HeroForgeModel = emu->equipment.Slot[k].HeroForgeModel; + Equipment[k].Material2 = emu->equipment.Slot[k].Material2; } - Buffer += (sizeof(structs::EquipStruct) * 9); + Buffer += (sizeof(structs::Texture_Struct) * 9); } else { @@ -4110,13 +4110,13 @@ namespace RoF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TexturePrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment.Primary.Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TextureSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment.Secondary.Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index d05dbf027..0638b4ad3 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2154,7 +2154,7 @@ namespace RoF2 for (int r = 0; r < 9; r++) { - outapp->WriteUInt32(emu->item_material[r]); + outapp->WriteUInt32(emu->item_material.Slot[r].Material); outapp->WriteUInt32(0); outapp->WriteUInt32(0); outapp->WriteUInt32(0); @@ -3140,11 +3140,11 @@ namespace RoF2 eq_cse->Face = emu_cse->Face; for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { - eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; - eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; - eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; - eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HeroForgeModel; - eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Material2; + eq_cse->Equip[equip_index].Textures.Material = emu_cse->Equip[equip_index].Textures.Material; + eq_cse->Equip[equip_index].Textures.Unknown1 = emu_cse->Equip[equip_index].Textures.Unknown1; + eq_cse->Equip[equip_index].Textures.EliteMaterial = emu_cse->Equip[equip_index].Textures.EliteMaterial; + eq_cse->Equip[equip_index].Textures.HeroForgeModel = emu_cse->Equip[equip_index].Textures.HeroForgeModel; + eq_cse->Equip[equip_index].Textures.Material2 = emu_cse->Equip[equip_index].Textures.Material2; eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color; } @@ -4313,17 +4313,17 @@ namespace RoF2 } } - structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; + structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; for (k = 0; k < 9; k++) { - Equipment[k].Material = emu->equipment[k].Material; - Equipment[k].Unknown1 = emu->equipment[k].Unknown1; - Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial; - Equipment[k].HeroForgeModel = emu->equipment[k].HeroForgeModel; - Equipment[k].Material2 = emu->equipment[k].Material2; + Equipment[k].Material = emu->equipment.Slot[k].Material; + Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; + Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; + Equipment[k].HeroForgeModel = emu->equipment.Slot[k].HeroForgeModel; + Equipment[k].Material2 = emu->equipment.Slot[k].Material2; } - Buffer += (sizeof(structs::EquipStruct) * 9); + Buffer += (sizeof(structs::Texture_Struct) * 9); } else { @@ -4333,13 +4333,13 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TexturePrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment.Primary.Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TextureSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment.Secondary.Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 4c84174b7..ee9ae9c29 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -176,7 +176,8 @@ struct Tint_Struct }; }; -struct TintProfile { +struct TintProfile +{ union { struct { Tint_Struct Head; @@ -193,13 +194,43 @@ struct TintProfile { }; }; -struct CharSelectEquip +/* +* Visible equiptment. +* Size: 20 Octets +*/ +struct Texture_Struct { uint32 Material; uint32 Unknown1; uint32 EliteMaterial; uint32 HeroForgeModel; - uint32 Material2; + uint32 Material2; // Same as material? +}; + +// Needs more research regarding new slots +//struct TextureProfile +//{ +// union { +// struct { +// Texture_Struct Head; +// Texture_Struct Chest; +// Texture_Struct Arms; +// Texture_Struct Wrist; +// Texture_Struct Hands; +// Texture_Struct Legs; +// Texture_Struct Feet; +// Texture_Struct Primary; +// Texture_Struct Secondary; +// }; +// Texture_Struct Slot[EQEmu::textures::TextureCount]; +// }; +// +// TextureProfile(); +//}; + +struct CharSelectEquip +{ + Texture_Struct Textures; Tint_Struct Color; }; @@ -248,21 +279,6 @@ struct CharacterSelect_Struct /*004*/ CharacterSelectEntry_Struct Entries[0]; }; -/* -* Visible equiptment. -* Size: 20 Octets -*/ -struct EquipStruct -{ - /*00*/ uint32 Material; - /*04*/ uint32 Unknown1; - /*08*/ uint32 EliteMaterial; - /*12*/ uint32 HeroForgeModel; - /*16*/ uint32 Material2; // Same as material? - /*20*/ -}; - - struct Membership_Entry_Struct { /*000*/ uint32 purchase_id; // Seen 1, then increments 90287 to 90300 @@ -471,17 +487,17 @@ struct Spawn_Struct { struct { - /*0000*/ EquipStruct equip_helmet; // Equiptment: Helmet visual - /*0000*/ EquipStruct equip_chest; // Equiptment: Chest visual - /*0000*/ EquipStruct equip_arms; // Equiptment: Arms visual - /*0000*/ EquipStruct equip_bracers; // Equiptment: Wrist visual - /*0000*/ EquipStruct equip_hands; // Equiptment: Hands visual - /*0000*/ EquipStruct equip_legs; // Equiptment: Legs visual - /*0000*/ EquipStruct equip_feet; // Equiptment: Boots visual - /*0000*/ EquipStruct equip_primary; // Equiptment: Main visual - /*0000*/ EquipStruct equip_secondary; // Equiptment: Off visual + /*0000*/ Texture_Struct equip_helmet; // Equiptment: Helmet visual + /*0000*/ Texture_Struct equip_chest; // Equiptment: Chest visual + /*0000*/ Texture_Struct equip_arms; // Equiptment: Arms visual + /*0000*/ Texture_Struct equip_bracers; // Equiptment: Wrist visual + /*0000*/ Texture_Struct equip_hands; // Equiptment: Hands visual + /*0000*/ Texture_Struct equip_legs; // Equiptment: Legs visual + /*0000*/ Texture_Struct equip_feet; // Equiptment: Boots visual + /*0000*/ Texture_Struct equip_primary; // Equiptment: Main visual + /*0000*/ Texture_Struct equip_secondary; // Equiptment: Off visual } equip; - /*0000*/ EquipStruct equipment[9]; + /*0000*/ Texture_Struct equipment[9]; }; /*0000*/ //char title[0]; // only read if(hasTitleOrSuffix & 4) @@ -1080,34 +1096,34 @@ union { struct { - /*00184*/ EquipStruct equip_helmet; // Equipment: Helmet visual - /*00204*/ EquipStruct equip_chest; // Equipment: Chest visual - /*00224*/ EquipStruct equip_arms; // Equipment: Arms visual - /*00244*/ EquipStruct equip_bracers; // Equipment: Wrist visual - /*00264*/ EquipStruct equip_hands; // Equipment: Hands visual - /*00284*/ EquipStruct equip_legs; // Equipment: Legs visual - /*00304*/ EquipStruct equip_feet; // Equipment: Boots visual - /*00324*/ EquipStruct equip_primary; // Equipment: Main visual - /*00344*/ EquipStruct equip_secondary; // Equipment: Off visual + /*00184*/ Texture_Struct equip_helmet; // Equipment: Helmet visual + /*00204*/ Texture_Struct equip_chest; // Equipment: Chest visual + /*00224*/ Texture_Struct equip_arms; // Equipment: Arms visual + /*00244*/ Texture_Struct equip_bracers; // Equipment: Wrist visual + /*00264*/ Texture_Struct equip_hands; // Equipment: Hands visual + /*00284*/ Texture_Struct equip_legs; // Equipment: Legs visual + /*00304*/ Texture_Struct equip_feet; // Equipment: Boots visual + /*00324*/ Texture_Struct equip_primary; // Equipment: Main visual + /*00344*/ Texture_Struct equip_secondary; // Equipment: Off visual // Below slots are just guesses, but all 0s anyway... - /*00364*/ EquipStruct equip_charm; // Equipment: Non-visual - /*00384*/ EquipStruct equip_ear1; // Equipment: Non-visual - /*00404*/ EquipStruct equip_ear2; // Equipment: Non-visual - /*00424*/ EquipStruct equip_face; // Equipment: Non-visual - /*00444*/ EquipStruct equip_neck; // Equipment: Non-visual - /*00464*/ EquipStruct equip_shoulder; // Equipment: Non-visual - /*00484*/ EquipStruct equip_bracer2; // Equipment: Non-visual - /*00504*/ EquipStruct equip_range; // Equipment: Non-visual - /*00524*/ EquipStruct equip_ring1; // Equipment: Non-visual - /*00544*/ EquipStruct equip_ring2; // Equipment: Non-visual - /*00564*/ EquipStruct equip_waist; // Equipment: Non-visual - /*00584*/ EquipStruct equip_powersource;// Equipment: Non-visual - /*00604*/ EquipStruct equip_ammo; // Equipment: Non-visual + /*00364*/ Texture_Struct equip_charm; // Equipment: Non-visual + /*00384*/ Texture_Struct equip_ear1; // Equipment: Non-visual + /*00404*/ Texture_Struct equip_ear2; // Equipment: Non-visual + /*00424*/ Texture_Struct equip_face; // Equipment: Non-visual + /*00444*/ Texture_Struct equip_neck; // Equipment: Non-visual + /*00464*/ Texture_Struct equip_shoulder; // Equipment: Non-visual + /*00484*/ Texture_Struct equip_bracer2; // Equipment: Non-visual + /*00504*/ Texture_Struct equip_range; // Equipment: Non-visual + /*00524*/ Texture_Struct equip_ring1; // Equipment: Non-visual + /*00544*/ Texture_Struct equip_ring2; // Equipment: Non-visual + /*00564*/ Texture_Struct equip_waist; // Equipment: Non-visual + /*00584*/ Texture_Struct equip_powersource;// Equipment: Non-visual + /*00604*/ Texture_Struct equip_ammo; // Equipment: Non-visual } equip; - /*00184*/ EquipStruct equipment[22]; // Total Slots + /*00184*/ Texture_Struct equipment[22]; // Total Slots }; /*00624*/ uint32 equip2_count; // Seen 9 -/*00628*/ EquipStruct equipment2[EQEmu::textures::TextureCount]; // Appears to be Visible slots, but all 0s +/*00628*/ Texture_Struct equipment2[EQEmu::textures::TextureCount]; // Appears to be Visible slots, but all 0s /*00808*/ uint32 tint_count; // Seen 9 /*00812*/ TintProfile item_tint; // RR GG BB 00 /*00848*/ uint32 tint_count2; // Seen 9 diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 6c884bbeb..1c957889a 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -176,7 +176,8 @@ struct Tint_Struct }; }; -struct TintProfile { +struct TintProfile +{ union { struct { Tint_Struct Head; @@ -193,13 +194,43 @@ struct TintProfile { }; }; -struct CharSelectEquip +/* +* Visible equiptment. +* Size: 20 Octets +*/ +struct Texture_Struct { uint32 Material; uint32 Unknown1; uint32 EliteMaterial; uint32 HeroForgeModel; - uint32 Material2; + uint32 Material2; // Same as material? +}; + +// Needs more research regarding new slots +//struct TextureProfile +//{ +// union { +// struct { +// Texture_Struct Head; +// Texture_Struct Chest; +// Texture_Struct Arms; +// Texture_Struct Wrist; +// Texture_Struct Hands; +// Texture_Struct Legs; +// Texture_Struct Feet; +// Texture_Struct Primary; +// Texture_Struct Secondary; +// }; +// Texture_Struct Slot[EQEmu::textures::TextureCount]; +// }; +// +// TextureProfile(); +//}; + +struct CharSelectEquip +{ + Texture_Struct Textures; Tint_Struct Color; }; @@ -248,21 +279,6 @@ struct CharacterSelect_Struct /*004*/ CharacterSelectEntry_Struct Entries[0]; }; -/* -* Visible equiptment. -* Size: 20 Octets -*/ -struct EquipStruct -{ - /*00*/ uint32 Material; - /*04*/ uint32 Unknown1; - /*08*/ uint32 EliteMaterial; - /*12*/ uint32 HeroForgeModel; - /*16*/ uint32 Material2; // Same as material? - /*20*/ -}; - - struct Membership_Entry_Struct { /*000*/ uint32 purchase_id; // Seen 1, then increments 90287 to 90300 @@ -465,17 +481,17 @@ struct Spawn_Struct { struct { - /*0000*/ EquipStruct equip_helmet; // Equiptment: Helmet visual - /*0000*/ EquipStruct equip_chest; // Equiptment: Chest visual - /*0000*/ EquipStruct equip_arms; // Equiptment: Arms visual - /*0000*/ EquipStruct equip_bracers; // Equiptment: Wrist visual - /*0000*/ EquipStruct equip_hands; // Equiptment: Hands visual - /*0000*/ EquipStruct equip_legs; // Equiptment: Legs visual - /*0000*/ EquipStruct equip_feet; // Equiptment: Boots visual - /*0000*/ EquipStruct equip_primary; // Equiptment: Main visual - /*0000*/ EquipStruct equip_secondary; // Equiptment: Off visual + /*0000*/ Texture_Struct equip_helmet; // Equiptment: Helmet visual + /*0000*/ Texture_Struct equip_chest; // Equiptment: Chest visual + /*0000*/ Texture_Struct equip_arms; // Equiptment: Arms visual + /*0000*/ Texture_Struct equip_bracers; // Equiptment: Wrist visual + /*0000*/ Texture_Struct equip_hands; // Equiptment: Hands visual + /*0000*/ Texture_Struct equip_legs; // Equiptment: Legs visual + /*0000*/ Texture_Struct equip_feet; // Equiptment: Boots visual + /*0000*/ Texture_Struct equip_primary; // Equiptment: Main visual + /*0000*/ Texture_Struct equip_secondary; // Equiptment: Off visual } equip; - /*0000*/ EquipStruct equipment[9]; + /*0000*/ Texture_Struct equipment[9]; }; /*0000*/ //char title[0]; // only read if(hasTitleOrSuffix & 4) @@ -1063,34 +1079,34 @@ union { struct { - /*00184*/ EquipStruct equip_helmet; // Equiptment: Helmet visual - /*00204*/ EquipStruct equip_chest; // Equiptment: Chest visual - /*00224*/ EquipStruct equip_arms; // Equiptment: Arms visual - /*00244*/ EquipStruct equip_bracers; // Equiptment: Wrist visual - /*00264*/ EquipStruct equip_hands; // Equiptment: Hands visual - /*00284*/ EquipStruct equip_legs; // Equiptment: Legs visual - /*00304*/ EquipStruct equip_feet; // Equiptment: Boots visual - /*00324*/ EquipStruct equip_primary; // Equiptment: Main visual - /*00344*/ EquipStruct equip_secondary; // Equiptment: Off visual + /*00184*/ Texture_Struct equip_helmet; // Equiptment: Helmet visual + /*00204*/ Texture_Struct equip_chest; // Equiptment: Chest visual + /*00224*/ Texture_Struct equip_arms; // Equiptment: Arms visual + /*00244*/ Texture_Struct equip_bracers; // Equiptment: Wrist visual + /*00264*/ Texture_Struct equip_hands; // Equiptment: Hands visual + /*00284*/ Texture_Struct equip_legs; // Equiptment: Legs visual + /*00304*/ Texture_Struct equip_feet; // Equiptment: Boots visual + /*00324*/ Texture_Struct equip_primary; // Equiptment: Main visual + /*00344*/ Texture_Struct equip_secondary; // Equiptment: Off visual // Below slots are just guesses, but all 0s anyway... - /*00364*/ EquipStruct equip_charm; // Equiptment: Non-visual - /*00384*/ EquipStruct equip_ear1; // Equiptment: Non-visual - /*00404*/ EquipStruct equip_ear2; // Equiptment: Non-visual - /*00424*/ EquipStruct equip_face; // Equiptment: Non-visual - /*00444*/ EquipStruct equip_neck; // Equiptment: Non-visual - /*00464*/ EquipStruct equip_shoulder; // Equiptment: Non-visual - /*00484*/ EquipStruct equip_bracer2; // Equiptment: Non-visual - /*00504*/ EquipStruct equip_range; // Equiptment: Non-visual - /*00524*/ EquipStruct equip_ring1; // Equiptment: Non-visual - /*00544*/ EquipStruct equip_ring2; // Equiptment: Non-visual - /*00564*/ EquipStruct equip_waist; // Equiptment: Non-visual - /*00584*/ EquipStruct equip_powersource; // Equiptment: Non-visual - /*00604*/ EquipStruct equip_ammo; // Equiptment: Non-visual + /*00364*/ Texture_Struct equip_charm; // Equiptment: Non-visual + /*00384*/ Texture_Struct equip_ear1; // Equiptment: Non-visual + /*00404*/ Texture_Struct equip_ear2; // Equiptment: Non-visual + /*00424*/ Texture_Struct equip_face; // Equiptment: Non-visual + /*00444*/ Texture_Struct equip_neck; // Equiptment: Non-visual + /*00464*/ Texture_Struct equip_shoulder; // Equiptment: Non-visual + /*00484*/ Texture_Struct equip_bracer2; // Equiptment: Non-visual + /*00504*/ Texture_Struct equip_range; // Equiptment: Non-visual + /*00524*/ Texture_Struct equip_ring1; // Equiptment: Non-visual + /*00544*/ Texture_Struct equip_ring2; // Equiptment: Non-visual + /*00564*/ Texture_Struct equip_waist; // Equiptment: Non-visual + /*00584*/ Texture_Struct equip_powersource; // Equiptment: Non-visual + /*00604*/ Texture_Struct equip_ammo; // Equiptment: Non-visual } equip; - /*00184*/ EquipStruct equipment[22]; + /*00184*/ Texture_Struct equipment[22]; }; /*00624*/ uint32 equip2_count; // Seen 9 -/*00628*/ EquipStruct equipment2[9]; // Appears to be Visible slots, but all 0s +/*00628*/ Texture_Struct equipment2[9]; // Appears to be Visible slots, but all 0s /*00808*/ uint32 tint_count; // Seen 9 /*00812*/ TintProfile item_tint; // RR GG BB 00 /*00848*/ uint32 tint_count2; // Seen 9 diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index ccc0edf15..916333041 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1554,9 +1554,9 @@ namespace SoD OUT(beard); // OUT(unknown00178[10]); for (r = 0; r < 9; r++) { - eq->equipment[r].Material = emu->item_material[r]; - eq->equipment[r].Unknown1 = 0; - eq->equipment[r].EliteMaterial = 0; + eq->equipment.Slot[r].Material = emu->item_material.Slot[r].Material; + eq->equipment.Slot[r].Unknown1 = 0; + eq->equipment.Slot[r].EliteMaterial = 0; //eq->colors[r].color = emu->colors[r].color; } for (r = 0; r < 7; r++) { @@ -1994,9 +1994,9 @@ namespace SoD eq_cse->Face = emu_cse->Face; for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { - eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; - eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; - eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; + eq_cse->Equip[equip_index].Textures.Material = emu_cse->Equip[equip_index].Textures.Material; + eq_cse->Equip[equip_index].Textures.Unknown1 = emu_cse->Equip[equip_index].Textures.Unknown1; + eq_cse->Equip[equip_index].Textures.EliteMaterial = emu_cse->Equip[equip_index].Textures.EliteMaterial; eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color; } @@ -2563,7 +2563,7 @@ namespace SoD float SpawnSize = emu->size; if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) { - PacketSize -= (sizeof(structs::EquipStruct) * 9); + PacketSize -= (sizeof(structs::Texture_Struct) * 9); if (emu->size == 0) { @@ -2773,11 +2773,11 @@ namespace SoD VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TexturePrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment.Primary.Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TextureSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment.Secondary.Material); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); } @@ -2785,15 +2785,15 @@ namespace SoD if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { - structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; + structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; for (k = 0; k < 9; k++) { - Equipment[k].Material = emu->equipment[k].Material; - Equipment[k].Unknown1 = emu->equipment[k].Unknown1; - Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial; + Equipment[k].Material = emu->equipment.Slot[k].Material; + Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; + Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; } - Buffer += (sizeof(structs::EquipStruct) * 9); + Buffer += (sizeof(structs::Texture_Struct) * 9); } if (strlen(emu->title)) { diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index bf45e2fda..6affabfe3 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -135,7 +135,8 @@ struct Tint_Struct }; }; -struct TintProfile { +struct TintProfile +{ union { struct { Tint_Struct Head; @@ -152,11 +153,40 @@ struct TintProfile { }; }; -struct CharSelectEquip +/* +* Visible equiptment. +* Size: 12 Octets +*/ +struct Texture_Struct { uint32 Material; uint32 Unknown1; uint32 EliteMaterial; +}; + +struct TextureProfile +{ + union { + struct { + Texture_Struct Head; + Texture_Struct Chest; + Texture_Struct Arms; + Texture_Struct Wrist; + Texture_Struct Hands; + Texture_Struct Legs; + Texture_Struct Feet; + Texture_Struct Primary; + Texture_Struct Secondary; + }; + Texture_Struct Slot[EQEmu::textures::TextureCount]; + }; + + TextureProfile(); +}; + +struct CharSelectEquip +{ + Texture_Struct Textures; Tint_Struct Color; }; @@ -169,7 +199,7 @@ struct CharacterSelectEntry_Struct /*0000*/ uint8 Beard; // /*0001*/ uint8 HairColor; // /*0000*/ uint8 Face; // -/*0000*/ CharSelectEquip Equip[9]; +/*0000*/ CharSelectEquip Equip[EQEmu::textures::TextureCount]; /*0000*/ uint32 PrimaryIDFile; // /*0000*/ uint32 SecondaryIDFile; // /*0000*/ uint8 Unknown15; // 0xff @@ -202,19 +232,6 @@ struct CharacterSelect_Struct /*0008*/ CharacterSelectEntry_Struct Entries[0]; }; -/* -* Visible equiptment. -* Size: 12 Octets -*/ -struct EquipStruct -{ -/*00*/ uint32 Material; -/*04*/ uint32 Unknown1; -/*08*/ uint32 EliteMaterial; -/*12*/ -}; - - /* ** Generic Spawn Struct ** Length: 897 Octets @@ -334,22 +351,7 @@ struct Spawn_Struct /*0000*/ TintProfile equipment_tint; // skip these bytes if not a valid player race -/*0000*/ union - { - struct - { - /*0000*/ EquipStruct equip_helmet; // Equiptment: Helmet visual - /*0000*/ EquipStruct equip_chest; // Equiptment: Chest visual - /*0000*/ EquipStruct equip_arms; // Equiptment: Arms visual - /*0000*/ EquipStruct equip_bracers; // Equiptment: Wrist visual - /*0000*/ EquipStruct equip_hands; // Equiptment: Hands visual - /*0000*/ EquipStruct equip_legs; // Equiptment: Legs visual - /*0000*/ EquipStruct equip_feet; // Equiptment: Boots visual - /*0000*/ EquipStruct equip_primary; // Equiptment: Main visual - /*0000*/ EquipStruct equip_secondary; // Equiptment: Off visual - } equip; - /*0000*/ EquipStruct equipment[9]; - }; +/*0000*/ TextureProfile equipment; /*0000*/ //char title[0]; // only read if(hasTitleOrSuffix & 4) /*0000*/ //char suffix[0]; // only read if(hasTitleOrSuffix & 8) @@ -905,22 +907,7 @@ struct PlayerProfile_Struct /*00216*/ uint8 hairstyle; // Player hair style /*00217*/ uint8 beard; // Player beard type /*00218*/ uint8 unknown00178[14]; //[10]14 on Live? was 10 -/*00232*/ union - { - struct - { - /*00228*/ EquipStruct equip_helmet; // Equiptment: Helmet visual - /*00240*/ EquipStruct equip_chest; // Equiptment: Chest visual - /*00252*/ EquipStruct equip_arms; // Equiptment: Arms visual - /*00264*/ EquipStruct equip_bracers; // Equiptment: Wrist visual - /*00276*/ EquipStruct equip_hands; // Equiptment: Hands visual - /*00288*/ EquipStruct equip_legs; // Equiptment: Legs visual - /*00300*/ EquipStruct equip_feet; // Equiptment: Boots visual - /*00312*/ EquipStruct equip_primary; // Equiptment: Main visual - /*00324*/ EquipStruct equip_secondary; // Equiptment: Off visual - } equip; - /*00228*/ EquipStruct equipment[9]; //Live Shows [108] for this part - }; +/*00232*/ TextureProfile equipment; /*00340*/ uint8 unknown00224[156]; // Live Shows [160] /*00496*/ TintProfile item_tint; // RR GG BB 00 /*00532*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // [3600] AAs 12 bytes each diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 1ef8240dc..7944605f4 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1210,9 +1210,9 @@ namespace SoF OUT(beard); // OUT(unknown00178[10]); for (r = 0; r < 9; r++) { - eq->equipment[r].Material = emu->item_material[r]; - eq->equipment[r].Unknown1 = 0; - eq->equipment[r].EliteMaterial = 0; + eq->equipment.Slot[r].Material = emu->item_material.Slot[r].Material; + eq->equipment.Slot[r].Unknown1 = 0; + eq->equipment.Slot[r].EliteMaterial = 0; //eq->colors[r].color = emu->colors[r].color; } for (r = 0; r < 7; r++) { @@ -1650,9 +1650,9 @@ namespace SoF eq_cse->Face = emu_cse->Face; for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { - eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; - eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; - eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; + eq_cse->Equip[equip_index].Textures.Material = emu_cse->Equip[equip_index].Textures.Material; + eq_cse->Equip[equip_index].Textures.Unknown1 = emu_cse->Equip[equip_index].Textures.Unknown1; + eq_cse->Equip[equip_index].Textures.EliteMaterial = emu_cse->Equip[equip_index].Textures.EliteMaterial; eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color; } @@ -2081,9 +2081,9 @@ namespace SoF eq->drakkin_heritage = emu->drakkin_heritage; eq->gender = emu->gender; for (k = 0; k < 9; k++) { - eq->equipment[k].Material = emu->equipment[k].Material; - eq->equipment[k].Unknown1 = emu->equipment[k].Unknown1; - eq->equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial; + eq->equipment.Slot[k].Material = emu->equipment.Slot[k].Material; + eq->equipment.Slot[k].Unknown1 = emu->equipment.Slot[k].Unknown1; + eq->equipment.Slot[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; eq->equipment_tint.Slot[k].Color = emu->equipment_tint.Slot[k].Color; } eq->StandState = emu->StandState; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 19e413082..66c3f93bf 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -135,7 +135,8 @@ struct Tint_Struct }; }; -struct TintProfile { +struct TintProfile +{ union { struct { Tint_Struct Head; @@ -152,11 +153,40 @@ struct TintProfile { }; }; -struct CharSelectEquip +/* +* Visible equiptment. +* Size: 12 Octets +*/ +struct Texture_Struct { uint32 Material; uint32 Unknown1; uint32 EliteMaterial; +}; + +struct TextureProfile +{ + union { + struct { + Texture_Struct Head; + Texture_Struct Chest; + Texture_Struct Arms; + Texture_Struct Wrist; + Texture_Struct Hands; + Texture_Struct Legs; + Texture_Struct Feet; + Texture_Struct Primary; + Texture_Struct Secondary; + }; + Texture_Struct Slot[EQEmu::textures::TextureCount]; + }; + + TextureProfile(); +}; + +struct CharSelectEquip +{ + Texture_Struct Textures; Tint_Struct Color; }; @@ -169,7 +199,7 @@ struct CharacterSelectEntry_Struct /*0000*/ uint8 Beard; // /*0001*/ uint8 HairColor; // /*0000*/ uint8 Face; // -/*0000*/ CharSelectEquip Equip[9]; +/*0000*/ CharSelectEquip Equip[EQEmu::textures::TextureCount]; /*0000*/ uint32 PrimaryIDFile; // /*0000*/ uint32 SecondaryIDFile; // /*0000*/ uint8 Unknown15; // 0xff @@ -200,19 +230,6 @@ struct CharacterSelect_Struct /*0008*/ CharacterSelectEntry_Struct Entries[0]; }; -/* -* Visible equiptment. -* Size: 12 Octets -*/ -struct EquipStruct -{ -/*00*/ uint32 Material; -/*04*/ uint32 Unknown1; -/*08*/ uint32 EliteMaterial; -/*12*/ -}; - - /* ** Generic Spawn Struct ** Length: 897 Octets @@ -239,22 +256,7 @@ struct Spawn_Struct { /*0018*/ uint8 unknown0018[4]; // /*0022*/ uint8 gender; // Gender (0=male, 1=female, 2=monster) /*0023*/ uint8 unknown0023[4]; // -/*0027*/ union - { - struct - { - /*0027*/ EquipStruct equip_helmet; // Equiptment: Helmet visual - /*0039*/ EquipStruct equip_chest; // Equiptment: Chest visual - /*0051*/ EquipStruct equip_arms; // Equiptment: Arms visual - /*0063*/ EquipStruct equip_bracers; // Equiptment: Wrist visual - /*0075*/ EquipStruct equip_hands; // Equiptment: Hands visual - /*0087*/ EquipStruct equip_legs; // Equiptment: Legs visual - /*0099*/ EquipStruct equip_feet; // Equiptment: Boots visual - /*0111*/ EquipStruct equip_primary; // Equiptment: Main visual - /*0123*/ EquipStruct equip_secondary; // Equiptment: Off visual - } equip; - /*0027*/ EquipStruct equipment[9]; - }; +/*0027*/ TextureProfile equipment; /*0135*/ uint8 StandState; // Seems to be required to be set to 0x64 for normal animation. /*0136*/ uint8 unknown0136; @@ -884,22 +886,7 @@ struct PlayerProfile_Struct //23576 Octets /*00216*/ uint8 hairstyle; // Player hair style /*00217*/ uint8 beard; // Player beard type /*00218*/ uint8 unknown00178[10]; //[10]14 on Live? -/*00228*/ union - { - struct - { - /*00228*/ EquipStruct equip_helmet; // Equiptment: Helmet visual - /*00240*/ EquipStruct equip_chest; // Equiptment: Chest visual - /*00252*/ EquipStruct equip_arms; // Equiptment: Arms visual - /*00264*/ EquipStruct equip_bracers; // Equiptment: Wrist visual - /*00276*/ EquipStruct equip_hands; // Equiptment: Hands visual - /*00288*/ EquipStruct equip_legs; // Equiptment: Legs visual - /*00300*/ EquipStruct equip_feet; // Equiptment: Boots visual - /*00312*/ EquipStruct equip_primary; // Equiptment: Main visual - /*00324*/ EquipStruct equip_secondary; // Equiptment: Off visual - } equip; - /*00228*/ EquipStruct equipment[9]; //Live Shows [108] for this part - }; +/*00228*/ TextureProfile equipment; /*00336*/ uint8 unknown00224[156]; // Live Shows [160] /*00496*/ TintProfile item_tint; // RR GG BB 00 /*00544*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // [3600] AAs 12 bytes each diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 36941d421..2f971de8a 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -904,7 +904,7 @@ namespace Titanium OUT(beard); // OUT(unknown00178[10]); for (r = 0; r < 9; r++) { - OUT(item_material[r]); + OUT(item_material.Slot[r].Material); OUT(item_tint.Slot[r].Color); } // OUT(unknown00224[48]); @@ -1231,7 +1231,7 @@ namespace Titanium eq->HairStyle[char_index] = emu_cse->HairStyle; for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { - eq->Equip[char_index][index] = emu_cse->Equip[index].Material; + eq->Equip[char_index].Slot[index].Material = emu_cse->Equip[index].Textures.Material; } eq->SecondaryIDFile[char_index] = emu_cse->SecondaryIDFile; @@ -1268,7 +1268,7 @@ namespace Titanium eq->HairStyle[char_index] = 0; for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { - eq->Equip[char_index][index] = 0; + eq->Equip[char_index].Slot[index].Material = 0; } eq->SecondaryIDFile[char_index] = 0; @@ -1600,7 +1600,7 @@ namespace Titanium eq->guildrank = emu->guildrank; // eq->unknown0194[3] = emu->unknown0194[3]; for (k = 0; k < 9; k++) { - eq->equipment[k] = emu->equipment[k].Material; + eq->equipment.Slot[k].Material = emu->equipment.Slot[k].Material; eq->equipment_tint.Slot[k].Color = emu->equipment_tint.Slot[k].Color; } for (k = 0; k < 8; k++) { diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 21364e070..997aecc5d 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -148,6 +148,31 @@ struct TintProfile { }; }; +struct Texture_Struct +{ + uint32 Material; +}; + +struct TextureProfile +{ + union { + struct { + Texture_Struct Head; + Texture_Struct Chest; + Texture_Struct Arms; + Texture_Struct Wrist; + Texture_Struct Hands; + Texture_Struct Legs; + Texture_Struct Feet; + Texture_Struct Primary; + Texture_Struct Secondary; + }; + Texture_Struct Slot[EQEmu::textures::TextureCount]; + }; + + TextureProfile(); +}; + /* ** Character Selection Struct ** Length: 1704 Bytes @@ -159,7 +184,7 @@ struct CharacterSelect_Struct /*0040*/ TintProfile CS_Colors[10]; // Characters Equipment Colors - packet requires length for 10 characters..but, client is limited to 8 /*0400*/ uint8 BeardColor[10]; // Characters beard Color /*0410*/ uint8 HairStyle[10]; // Characters hair style -/*0420*/ uint32 Equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be) +/*0420*/ TextureProfile Equip[10]; // Characters texture array /*0780*/ uint32 SecondaryIDFile[10]; // Characters secondary IDFile number /*0820*/ uint8 Unknown820[10]; // 10x ff /*0830*/ uint8 Unknown830[2]; // 2x 00 @@ -256,22 +281,7 @@ struct Spawn_Struct { /*0189*/ uint32 petOwnerId; // If this is a pet, the spawn id of owner /*0193*/ uint8 guildrank; // 0=normal, 1=officer, 2=leader /*0194*/ uint8 unknown0194[3]; -/*0197*/ union - { - struct - { - /*0197*/ uint32 equip_helmet; // Equipment: Helmet Visual - /*0201*/ uint32 equip_chest; // Equipment: Chest Visual - /*0205*/ uint32 equip_arms; // Equipment: Arms Visual - /*0209*/ uint32 equip_bracers; // Equipment: Bracers Visual - /*0213*/ uint32 equip_hands; // Equipment: Hands Visual - /*0217*/ uint32 equip_legs; // Equipment: Legs Visual - /*0221*/ uint32 equip_feet; // Equipment: Feet Visual - /*0225*/ uint32 equip_primary; // Equipment: Primary Visual - /*0229*/ uint32 equip_secondary; // Equipment: Secondary Visual - } equip; - /*0197*/ uint32 equipment[9]; // Array elements correspond to struct equipment above - }; +/*0197*/ TextureProfile equipment; /*0233*/ float runspeed; // Speed when running /*0036*/ uint8 afk; // 0=no, 1=afk /*0238*/ uint32 guildID; // Current guild @@ -812,7 +822,7 @@ struct PlayerProfile_Struct /*00176*/ uint8 hairstyle; // Player hair style /*00177*/ uint8 beard; // Player beard type /*00178*/ uint8 unknown00178[10]; -/*00188*/ uint32 item_material[9]; // Item texture/material of worn items +/*00188*/ TextureProfile item_material; // Item texture/material of worn items /*00224*/ uint8 unknown00224[44]; /*00268*/ TintProfile item_tint; // RR GG BB 00 /*00304*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // AAs diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 8472c1034..66bc0b777 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1807,9 +1807,9 @@ namespace UF OUT(beard); // OUT(unknown00178[10]); for (r = 0; r < 9; r++) { - eq->equipment[r].Material = emu->item_material[r]; - eq->equipment[r].Unknown1 = 0; - eq->equipment[r].EliteMaterial = 0; + eq->equipment.Slot[r].Material = emu->item_material.Slot[r].Material; + eq->equipment.Slot[r].Unknown1 = 0; + eq->equipment.Slot[r].EliteMaterial = 0; //eq->colors[r].color = emu->colors[r].color; } for (r = 0; r < 7; r++) { @@ -2291,9 +2291,9 @@ namespace UF eq_cse->Face = emu_cse->Face; for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { - eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; - eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; - eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; + eq_cse->Equip[equip_index].Textures.Material = emu_cse->Equip[equip_index].Textures.Material; + eq_cse->Equip[equip_index].Textures.Unknown1 = emu_cse->Equip[equip_index].Textures.Unknown1; + eq_cse->Equip[equip_index].Textures.EliteMaterial = emu_cse->Equip[equip_index].Textures.EliteMaterial; eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color; } @@ -2858,7 +2858,7 @@ namespace UF float SpawnSize = emu->size; if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) { - PacketSize -= (sizeof(structs::EquipStruct) * 9); + PacketSize -= (sizeof(structs::Texture_Struct) * 9); if (emu->size == 0) { @@ -3070,19 +3070,19 @@ namespace UF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - if (emu->equipment[EQEmu::textures::TexturePrimary].Material > 99999) { + if (emu->equipment.Primary.Material > 99999) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63); } else { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TexturePrimary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment.Primary.Material); } VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - if (emu->equipment[EQEmu::textures::TextureSecondary].Material > 99999) { + if (emu->equipment.Secondary.Material > 99999) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63); } else { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[EQEmu::textures::TextureSecondary].Material); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment.Secondary.Material); } VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); @@ -3091,19 +3091,19 @@ namespace UF if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { - structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; + structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; for (k = 0; k < 9; k++) { - if (emu->equipment[k].Material > 99999) { + if (emu->equipment.Slot[k].Material > 99999) { Equipment[k].Material = 63; } else { - Equipment[k].Material = emu->equipment[k].Material; + Equipment[k].Material = emu->equipment.Slot[k].Material; } - Equipment[k].Unknown1 = emu->equipment[k].Unknown1; - Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial; + Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; + Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; } - Buffer += (sizeof(structs::EquipStruct) * 9); + Buffer += (sizeof(structs::Texture_Struct) * 9); } if (strlen(emu->title)) { diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 00a2e4aad..284e8a336 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -135,7 +135,8 @@ struct Tint_Struct }; }; -struct TintProfile { +struct TintProfile +{ union { struct { Tint_Struct Head; @@ -152,11 +153,40 @@ struct TintProfile { }; }; -struct CharSelectEquip +/* +* Visible equiptment. +* Size: 12 Octets +*/ +struct Texture_Struct { uint32 Material; uint32 Unknown1; uint32 EliteMaterial; +}; + +struct TextureProfile +{ + union { + struct { + Texture_Struct Head; + Texture_Struct Chest; + Texture_Struct Arms; + Texture_Struct Wrist; + Texture_Struct Hands; + Texture_Struct Legs; + Texture_Struct Feet; + Texture_Struct Primary; + Texture_Struct Secondary; + }; + Texture_Struct Slot[EQEmu::textures::TextureCount]; + }; + + TextureProfile(); +}; + +struct CharSelectEquip +{ + Texture_Struct Textures; Tint_Struct Color; }; @@ -169,7 +199,7 @@ struct CharacterSelectEntry_Struct /*0000*/ uint8 Beard; // /*0001*/ uint8 HairColor; // /*0000*/ uint8 Face; // -/*0000*/ CharSelectEquip Equip[9]; +/*0000*/ CharSelectEquip Equip[EQEmu::textures::TextureCount]; /*0000*/ uint32 PrimaryIDFile; // /*0000*/ uint32 SecondaryIDFile; // /*0000*/ uint8 Unknown15; // 0xff @@ -202,19 +232,6 @@ struct CharacterSelect_Struct /*0008*/ CharacterSelectEntry_Struct Entries[0]; }; -/* -* Visible equiptment. -* Size: 12 Octets -*/ -struct EquipStruct -{ -/*00*/ uint32 Material; -/*04*/ uint32 Unknown1; -/*08*/ uint32 EliteMaterial; -/*12*/ -}; - - /* ** Generic Spawn Struct ** Length: 897 Octets @@ -334,22 +351,7 @@ struct Spawn_Struct /*0000*/ TintProfile equipment_tint; // skip these bytes if not a valid player race -/*0000*/ union - { - struct - { - /*0000*/ EquipStruct equip_helmet; // Equiptment: Helmet visual - /*0000*/ EquipStruct equip_chest; // Equiptment: Chest visual - /*0000*/ EquipStruct equip_arms; // Equiptment: Arms visual - /*0000*/ EquipStruct equip_bracers; // Equiptment: Wrist visual - /*0000*/ EquipStruct equip_hands; // Equiptment: Hands visual - /*0000*/ EquipStruct equip_legs; // Equiptment: Legs visual - /*0000*/ EquipStruct equip_feet; // Equiptment: Boots visual - /*0000*/ EquipStruct equip_primary; // Equiptment: Main visual - /*0000*/ EquipStruct equip_secondary; // Equiptment: Off visual - } equip; - /*0000*/ EquipStruct equipment[9]; - }; +/*0000*/ TextureProfile equipment; /*0000*/ //char title[0]; // only read if(hasTitleOrSuffix & 4) /*0000*/ //char suffix[0]; // only read if(hasTitleOrSuffix & 8) @@ -954,22 +956,7 @@ struct PlayerProfile_Struct /*00230*/ uint8 hairstyle; // Player hair style /*00231*/ uint8 beard; // Player beard type /*00232*/ uint8 unknown00232[4]; // was 14 -/*00236*/ union - { - struct - { - /*00236*/ EquipStruct equip_helmet; // Equiptment: Helmet visual - /*00248*/ EquipStruct equip_chest; // Equiptment: Chest visual - /*00260*/ EquipStruct equip_arms; // Equiptment: Arms visual - /*00272*/ EquipStruct equip_bracers; // Equiptment: Wrist visual - /*00284*/ EquipStruct equip_hands; // Equiptment: Hands visual - /*00296*/ EquipStruct equip_legs; // Equiptment: Legs visual - /*00308*/ EquipStruct equip_feet; // Equiptment: Boots visual - /*00320*/ EquipStruct equip_primary; // Equiptment: Main visual - /*00332*/ EquipStruct equip_secondary; // Equiptment: Off visual - } equip; - /*00236*/ EquipStruct equipment[9]; //Underfoot Shows [108] for this part - }; +/*00236*/ TextureProfile equipment; /*00344*/ uint8 unknown00344[168]; // Underfoot Shows [160] /*00512*/ TintProfile item_tint; // RR GG BB 00 /*00548*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // [3600] AAs 12 bytes each diff --git a/common/textures.cpp b/common/textures.cpp index bbad13b26..7993ec384 100644 --- a/common/textures.cpp +++ b/common/textures.cpp @@ -85,7 +85,12 @@ EQEmu::TextureProfile::TextureProfile() { - memset(&Texture, 0, (sizeof(uint32) * textures::TextureCount)); + memset(&Slot, 0, (sizeof(Texture_Struct) * textures::TextureCount)); +} + +EQEmu::TextureShortProfile::TextureShortProfile() +{ + memset(&Slot, 0, (sizeof(uint32) * textures::TextureCount)); } EQEmu::TintProfile::TintProfile() diff --git a/common/textures.h b/common/textures.h index 598f5dd3a..a6333a03f 100644 --- a/common/textures.h +++ b/common/textures.h @@ -54,25 +54,56 @@ namespace EQEmu } /*textures*/ + struct Texture_Struct { + uint32 Material; + uint32 Unknown1; + uint32 EliteMaterial; + uint32 HeroForgeModel; + uint32 Material2; // Same as material? + }; + struct TextureProfile { union { struct { - uint32 Head; - uint32 Chest; - uint32 Arms; - uint32 Wrist; - uint32 Hands; - uint32 Legs; - uint32 Feet; - uint32 Primary; - uint32 Secondary; + Texture_Struct Head; + Texture_Struct Chest; + Texture_Struct Arms; + Texture_Struct Wrist; + Texture_Struct Hands; + Texture_Struct Legs; + Texture_Struct Feet; + Texture_Struct Primary; + Texture_Struct Secondary; }; - uint32 Texture[textures::TextureCount]; + Texture_Struct Slot[textures::TextureCount]; }; TextureProfile(); }; + struct TextureShort_Struct { + uint32 Material; + }; + + struct TextureShortProfile { + union { + struct { + TextureShort_Struct Head; + TextureShort_Struct Chest; + TextureShort_Struct Arms; + TextureShort_Struct Wrist; + TextureShort_Struct Hands; + TextureShort_Struct Legs; + TextureShort_Struct Feet; + TextureShort_Struct Primary; + TextureShort_Struct Secondary; + }; + TextureShort_Struct Slot[textures::TextureCount]; + }; + + TextureShortProfile(); + }; + struct Tint_Struct { union { struct { diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 7df66b85a..c1995535f 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -118,11 +118,11 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou cse->Face = (uint8)atoi(row[15]); for (uint32 matslot = 0; matslot < EQEmu::textures::TextureCount; matslot++) { // Processed below - cse->Equip[matslot].Material = 0; - cse->Equip[matslot].Unknown1 = 0; - cse->Equip[matslot].EliteMaterial = 0; - cse->Equip[matslot].HeroForgeModel = 0; - cse->Equip[matslot].Material2 = 0; + cse->Equip[matslot].Textures.Material = 0; + cse->Equip[matslot].Textures.Unknown1 = 0; + cse->Equip[matslot].Textures.EliteMaterial = 0; + cse->Equip[matslot].Textures.HeroForgeModel = 0; + cse->Equip[matslot].Textures.Material2 = 0; cse->Equip[matslot].Color.Color = 0; } @@ -262,12 +262,12 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou // Weapon Models if (inst->GetOrnamentationIDFile() != 0) { idfile = inst->GetOrnamentationIDFile(); - cse->Equip[matslot].Material = idfile; + cse->Equip[matslot].Textures.Material = idfile; } else { if (strlen(item->IDFile) > 2) { idfile = atoi(&item->IDFile[2]); - cse->Equip[matslot].Material = idfile; + cse->Equip[matslot].Textures.Material = idfile; } } if (matslot == EQEmu::textures::TexturePrimary) { @@ -287,9 +287,9 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou } // Armor Materials/Models - cse->Equip[matslot].Material = item->Material; - cse->Equip[matslot].EliteMaterial = item->EliteMaterial; - cse->Equip[matslot].HeroForgeModel = inst->GetOrnamentHeroModel(matslot); + cse->Equip[matslot].Textures.Material = item->Material; + cse->Equip[matslot].Textures.EliteMaterial = item->EliteMaterial; + cse->Equip[matslot].Textures.HeroForgeModel = inst->GetOrnamentHeroModel(matslot); cse->Equip[matslot].Color.Color = color; } } diff --git a/zone/beacon.cpp b/zone/beacon.cpp index 21943ecee..27f86fce7 100644 --- a/zone/beacon.cpp +++ b/zone/beacon.cpp @@ -56,7 +56,7 @@ Beacon::Beacon(Mob *at_mob, int lifetime) :Mob ( nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, at_mob->GetPosition(), 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQEmu::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), remove_timer(lifetime), spell_timer(0) diff --git a/zone/bot.cpp b/zone/bot.cpp index 67b7beb82..edbc4e8eb 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2961,16 +2961,16 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { if (inst) { item = inst->GetItem(); if (item != 0) { - ns->spawn.equipment[i].Material = item->Material; - ns->spawn.equipment[i].EliteMaterial = item->EliteMaterial; - ns->spawn.equipment[i].HeroForgeModel = item->HerosForgeModel; - if (armor_tint[i]) - ns->spawn.equipment_tint.Slot[i].Color = armor_tint[i]; + ns->spawn.equipment.Slot[i].Material = item->Material; + ns->spawn.equipment.Slot[i].EliteMaterial = item->EliteMaterial; + ns->spawn.equipment.Slot[i].HeroForgeModel = item->HerosForgeModel; + if (armor_tint.Slot[i].Color) + ns->spawn.equipment_tint.Slot[i].Color = armor_tint.Slot[i].Color; else ns->spawn.equipment_tint.Slot[i].Color = item->Color; } else { - if (armor_tint[i]) - ns->spawn.equipment_tint.Slot[i].Color = armor_tint[i]; + if (armor_tint.Slot[i].Color) + ns->spawn.equipment_tint.Slot[i].Color = armor_tint.Slot[i].Color; } } } @@ -2980,7 +2980,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { item = inst->GetItem(); if(item) { if(strlen(item->IDFile) > 2) - ns->spawn.equipment[EQEmu::textures::TexturePrimary].Material = atoi(&item->IDFile[2]); + ns->spawn.equipment.Primary.Material = atoi(&item->IDFile[2]); ns->spawn.equipment_tint.Primary.Color = GetEquipmentColor(EQEmu::textures::TexturePrimary); } @@ -2991,7 +2991,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { item = inst->GetItem(); if(item) { if(strlen(item->IDFile) > 2) - ns->spawn.equipment[EQEmu::textures::TextureSecondary].Material = atoi(&item->IDFile[2]); + ns->spawn.equipment.Secondary.Material = atoi(&item->IDFile[2]); ns->spawn.equipment_tint.Secondary.Color = GetEquipmentColor(EQEmu::textures::TextureSecondary); } diff --git a/zone/client.cpp b/zone/client.cpp index 6ec655dc7..c10a26312 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -100,7 +100,7 @@ Client::Client(EQStreamInterface* ieqs) 0, // Drakkin Heritage 0, // Drakkin Tattoo 0, // Drakkin Details - 0, // Armor Tint + EQEmu::TintProfile(), // Armor Tint 0xff, // AA Title 0, // see_invis 0, // see_invis_undead @@ -2732,7 +2732,7 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); if (matslot != EQEmu::textures::TextureInvalid) { - m_pp.item_material[matslot] = GetEquipmentMaterial(matslot); + m_pp.item_material.Slot[matslot].Material = GetEquipmentMaterial(matslot); } } } @@ -6286,7 +6286,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid made_npc->d_melee_texture1 = GetEquipmentMaterial(EQEmu::textures::TexturePrimary); made_npc->d_melee_texture2 = GetEquipmentMaterial(EQEmu::textures::TextureSecondary); for (int i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTexture; i++) { - made_npc->armor_tint[i] = GetEquipmentColor(i); + made_npc->armor_tint.Slot[i].Color = GetEquipmentColor(i); } made_npc->loottable_id = 0; diff --git a/zone/corpse.cpp b/zone/corpse.cpp index e5d12b8dd..98fd4923f 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -153,7 +153,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP in_npc->GetDeity(),in_npc->GetLevel(),in_npc->GetNPCTypeID(),in_npc->GetSize(),0, in_npc->GetPosition(), in_npc->GetInnateLightType(), in_npc->GetTexture(),in_npc->GetHelmTexture(), 0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0,0,0,0,0,0), + 0,0,0,0,0,0,0,0,0,0,EQEmu::TintProfile(),0xff,0,0,0,0,0,0,0,0,0,0,0,0,0,0), corpse_decay_timer(in_decaytime), corpse_rez_timer(0), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), @@ -244,7 +244,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( client->GetPP().drakkin_heritage, // uint32 in_drakkin_heritage, client->GetPP().drakkin_tattoo, // uint32 in_drakkin_tattoo, client->GetPP().drakkin_details, // uint32 in_drakkin_details, - 0, // uint32 in_armor_tint[_MaterialCount], + EQEmu::TintProfile(), // uint32 in_armor_tint[_MaterialCount], 0xff, // uint8 in_aa_title, 0, // uint8 in_see_invis, // see through invis 0, // uint8 in_see_invis_undead, // see through invis vs. undead @@ -474,7 +474,7 @@ in_helmtexture, 0, 0, 0, -0, +EQEmu::TintProfile(), 0xff, 0, 0, diff --git a/zone/encounter.cpp b/zone/encounter.cpp index 01d4ef670..1eff0ca59 100644 --- a/zone/encounter.cpp +++ b/zone/encounter.cpp @@ -36,7 +36,7 @@ Encounter::Encounter(const char* enc_name) :Mob ( nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, glm::vec4(0,0,0,0), 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQEmu::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) { encounter_name[0] = 0; diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 59103cf9e..d47420fe1 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1400,15 +1400,15 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float LuaCreateNPCParse(drakkin_heritage, uint32, 0); LuaCreateNPCParse(drakkin_tattoo, uint32, 0); LuaCreateNPCParse(drakkin_details, uint32, 0); - LuaCreateNPCParse(armor_tint[0], uint32, 0); - LuaCreateNPCParse(armor_tint[1], uint32, 0); - LuaCreateNPCParse(armor_tint[2], uint32, 0); - LuaCreateNPCParse(armor_tint[3], uint32, 0); - LuaCreateNPCParse(armor_tint[4], uint32, 0); - LuaCreateNPCParse(armor_tint[5], uint32, 0); - LuaCreateNPCParse(armor_tint[6], uint32, 0); - LuaCreateNPCParse(armor_tint[7], uint32, 0); - LuaCreateNPCParse(armor_tint[8], uint32, 0); + LuaCreateNPCParse(armor_tint.Head.Color, uint32, 0); + LuaCreateNPCParse(armor_tint.Chest.Color, uint32, 0); + LuaCreateNPCParse(armor_tint.Arms.Color, uint32, 0); + LuaCreateNPCParse(armor_tint.Wrist.Color, uint32, 0); + LuaCreateNPCParse(armor_tint.Hands.Color, uint32, 0); + LuaCreateNPCParse(armor_tint.Legs.Color, uint32, 0); + LuaCreateNPCParse(armor_tint.Feet.Color, uint32, 0); + LuaCreateNPCParse(armor_tint.Primary.Color, uint32, 0); + LuaCreateNPCParse(armor_tint.Secondary.Color, uint32, 0); LuaCreateNPCParse(min_dmg, uint32, 2); LuaCreateNPCParse(max_dmg, uint32, 4); LuaCreateNPCParse(attack_count, int16, 0); diff --git a/zone/mob.cpp b/zone/mob.cpp index 2918aa413..f76902da9 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -73,7 +73,7 @@ Mob::Mob(const char* in_name, uint32 in_drakkin_heritage, uint32 in_drakkin_tattoo, uint32 in_drakkin_details, - uint32 in_armor_tint[EQEmu::textures::TextureCount], + EQEmu::TintProfile in_armor_tint, uint8 in_aa_title, uint8 in_see_invis, // see through invis/ivu @@ -280,14 +280,7 @@ Mob::Mob(const char* in_name, for (i = 0; i < EQEmu::textures::TextureCount; i++) { - if (in_armor_tint) - { - armor_tint[i] = in_armor_tint[i]; - } - else - { - armor_tint[i] = 0; - } + armor_tint.Slot[i].Color = in_armor_tint.Slot[i].Color; } m_Delta = glm::vec4(); @@ -1159,9 +1152,9 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) // Only Player Races Wear Armor if (Mob::IsPlayerRace(race) || i > 6) { - ns->spawn.equipment[i].Material = GetEquipmentMaterial(i); - ns->spawn.equipment[i].EliteMaterial = IsEliteMaterialItem(i); - ns->spawn.equipment[i].HeroForgeModel = GetHerosForgeModel(i); + ns->spawn.equipment.Slot[i].Material = GetEquipmentMaterial(i); + ns->spawn.equipment.Slot[i].EliteMaterial = IsEliteMaterialItem(i); + ns->spawn.equipment.Slot[i].HeroForgeModel = GetHerosForgeModel(i); ns->spawn.equipment_tint.Slot[i].Color = GetEquipmentColor(i); } } @@ -2821,7 +2814,7 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin color |= (green_tint & 0xFF) << 8; color |= (blue_tint & 0xFF); color |= (color) ? (0xFF << 24) : 0; - armor_tint[material_slot] = color; + armor_tint.Slot[material_slot].Color = color; auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; @@ -2838,7 +2831,7 @@ void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uin void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model) { - armor_tint[material_slot] = color; + armor_tint.Slot[material_slot].Color = color; auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct)); WearChange_Struct* wc = (WearChange_Struct*)outapp->pBuffer; @@ -2966,9 +2959,9 @@ uint32 Mob::GetEquipmentColor(uint8 material_slot) const { const EQEmu::ItemBase *item; - if (armor_tint[material_slot]) + if (armor_tint.Slot[material_slot].Color) { - return armor_tint[material_slot]; + return armor_tint.Slot[material_slot].Color; } item = database.GetItem(GetEquipment(material_slot)); diff --git a/zone/mob.h b/zone/mob.h index e4c9ad875..a282fb89c 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -113,7 +113,7 @@ public: uint32 in_drakkin_heritage, uint32 in_drakkin_tattoo, uint32 in_drakkin_details, - uint32 in_armor_tint[EQEmu::textures::TextureCount], + EQEmu::TintProfile in_armor_tint, uint8 in_aa_title, uint8 in_see_invis, // see through invis uint8 in_see_invis_undead, // see through invis vs. undead @@ -384,7 +384,7 @@ public: inline uint8 GetDrakkinHeritage() const { return drakkin_heritage; } inline uint8 GetDrakkinTattoo() const { return drakkin_tattoo; } inline uint8 GetDrakkinDetails() const { return drakkin_details; } - inline uint32 GetArmorTint(uint8 i) const { return armor_tint[(i < EQEmu::textures::TextureCount) ? i : 0]; } + inline uint32 GetArmorTint(uint8 i) const { return armor_tint.Slot[(i < EQEmu::textures::TextureCount) ? i : 0].Color; } inline uint8 GetClass() const { return class_; } inline uint8 GetLevel() const { return level; } inline uint8 GetOrigLevel() const { return orig_level; } @@ -1248,7 +1248,7 @@ protected: uint32 drakkin_heritage; uint32 drakkin_tattoo; uint32 drakkin_details; - uint32 armor_tint[EQEmu::textures::TextureCount]; + EQEmu::TintProfile armor_tint; uint8 aa_title; diff --git a/zone/npc.cpp b/zone/npc.cpp index 77f6d492f..d1d9e8a44 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -94,7 +94,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if d->drakkin_heritage, d->drakkin_tattoo, d->drakkin_details, - (uint32*)d->armor_tint, + d->armor_tint, 0, d->see_invis, // pass see_invis/see_ivu flags to mob constructor d->see_invis_undead, diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 62120accb..1c37d4689 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2068,10 +2068,10 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load uint32 armor_tint_id = atoi(row[63]); - temp_npctype_data->armor_tint[0] = (atoi(row[64]) & 0xFF) << 16; - temp_npctype_data->armor_tint[0] |= (atoi(row[65]) & 0xFF) << 8; - temp_npctype_data->armor_tint[0] |= (atoi(row[66]) & 0xFF); - temp_npctype_data->armor_tint[0] |= (temp_npctype_data->armor_tint[0]) ? (0xFF << 24) : 0; + temp_npctype_data->armor_tint.Head.Color = (atoi(row[64]) & 0xFF) << 16; + temp_npctype_data->armor_tint.Head.Color |= (atoi(row[65]) & 0xFF) << 8; + temp_npctype_data->armor_tint.Head.Color |= (atoi(row[66]) & 0xFF); + temp_npctype_data->armor_tint.Head.Color |= (temp_npctype_data->armor_tint.Head.Color) ? (0xFF << 24) : 0; if (armor_tint_id != 0) { std::string armortint_query = StringFormat( @@ -2093,17 +2093,17 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load auto armorTint_row = armortint_results.begin(); for (int index = EQEmu::textures::TextureBegin; index <= EQEmu::textures::LastTexture; index++) { - temp_npctype_data->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; - temp_npctype_data->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; - temp_npctype_data->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); - temp_npctype_data->armor_tint[index] |= (temp_npctype_data->armor_tint[index]) ? (0xFF << 24) : 0; + temp_npctype_data->armor_tint.Slot[index].Color = atoi(armorTint_row[index * 3]) << 16; + temp_npctype_data->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 1]) << 8; + temp_npctype_data->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 2]); + temp_npctype_data->armor_tint.Slot[index].Color |= (temp_npctype_data->armor_tint.Slot[index].Color) ? (0xFF << 24) : 0; } } } // Try loading npc_types tint fields if armor tint is 0 or query failed to get results if (armor_tint_id == 0) { for (int index = EQEmu::textures::TextureChest; index < EQEmu::textures::TextureCount; index++) { - temp_npctype_data->armor_tint[index] = temp_npctype_data->armor_tint[0]; + temp_npctype_data->armor_tint.Slot[index].Color = temp_npctype_data->armor_tint.Slot[0].Color; // odd way to 'zero-out' the array... } } @@ -2301,15 +2301,15 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client tmpNPCType->bodytype = 1; uint32 armor_tint_id = atoi(row[36]); - tmpNPCType->armor_tint[0] = (atoi(row[37]) & 0xFF) << 16; - tmpNPCType->armor_tint[0] |= (atoi(row[38]) & 0xFF) << 8; - tmpNPCType->armor_tint[0] |= (atoi(row[39]) & 0xFF); - tmpNPCType->armor_tint[0] |= (tmpNPCType->armor_tint[0]) ? (0xFF << 24) : 0; + tmpNPCType->armor_tint.Slot[0].Color = (atoi(row[37]) & 0xFF) << 16; + tmpNPCType->armor_tint.Slot[0].Color |= (atoi(row[38]) & 0xFF) << 8; + tmpNPCType->armor_tint.Slot[0].Color |= (atoi(row[39]) & 0xFF); + tmpNPCType->armor_tint.Slot[0].Color |= (tmpNPCType->armor_tint.Slot[0].Color) ? (0xFF << 24) : 0; if (armor_tint_id == 0) for (int index = EQEmu::textures::TextureChest; index <= EQEmu::textures::LastTexture; index++) - tmpNPCType->armor_tint[index] = tmpNPCType->armor_tint[0]; - else if (tmpNPCType->armor_tint[0] == 0) { + tmpNPCType->armor_tint.Slot[index].Color = tmpNPCType->armor_tint.Slot[0].Color; + else if (tmpNPCType->armor_tint.Slot[0].Color == 0) { std::string armorTint_query = StringFormat("SELECT red1h, grn1h, blu1h, " "red2c, grn2c, blu2c, " "red3a, grn3a, blu3a, " @@ -2328,10 +2328,10 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client auto armorTint_row = results.begin(); for (int index = EQEmu::textures::TextureBegin; index <= EQEmu::textures::LastTexture; index++) { - tmpNPCType->armor_tint[index] = atoi(armorTint_row[index * 3]) << 16; - tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 1]) << 8; - tmpNPCType->armor_tint[index] |= atoi(armorTint_row[index * 3 + 2]); - tmpNPCType->armor_tint[index] |= (tmpNPCType->armor_tint[index]) ? (0xFF << 24) : 0; + tmpNPCType->armor_tint.Slot[index].Color = atoi(armorTint_row[index * 3]) << 16; + tmpNPCType->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 1]) << 8; + tmpNPCType->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 2]); + tmpNPCType->armor_tint.Slot[index].Color |= (tmpNPCType->armor_tint.Slot[index].Color) ? (0xFF << 24) : 0; } } } else diff --git a/zone/zonedump.h b/zone/zonedump.h index 743e1a94c..6782881fe 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -86,7 +86,7 @@ struct NPCType uint32 drakkin_heritage; uint32 drakkin_tattoo; uint32 drakkin_details; - uint32 armor_tint[EQEmu::textures::TextureCount]; + EQEmu::TintProfile armor_tint; uint32 min_dmg; uint32 max_dmg; int16 attack_count; From ca0b26f89f1fcf34e498975e8366f4ae8f3b917c Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 1 Jun 2016 09:34:16 -0400 Subject: [PATCH 144/693] Implementation clean-up --- common/patches/rof.cpp | 16 ++++++++-------- common/patches/rof2.cpp | 16 ++++++++-------- common/patches/sod.cpp | 10 +++++----- common/patches/sof.cpp | 6 +++--- common/patches/titanium.cpp | 4 ++-- common/patches/uf.cpp | 10 +++++----- zone/corpse.cpp | 6 ------ 7 files changed, 31 insertions(+), 37 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 61c9c1105..3b1e890bc 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2068,7 +2068,7 @@ namespace RoF outapp->WriteUInt32(22); // Equipment count - for (int r = 0; r < 9; r++) + for (int r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { outapp->WriteUInt32(emu->item_material.Slot[r].Material); outapp->WriteUInt32(0); @@ -2088,9 +2088,9 @@ namespace RoF outapp->WriteUInt32(0); } - outapp->WriteUInt32(9); // Equipment2 count + outapp->WriteUInt32(EQEmu::textures::TextureCount); // Equipment2 count - for (int r = 0; r < 9; r++) + for (int r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { outapp->WriteUInt32(0); outapp->WriteUInt32(0); @@ -2099,7 +2099,7 @@ namespace RoF outapp->WriteUInt32(0); } - outapp->WriteUInt32(9); // Tint Count + outapp->WriteUInt32(EQEmu::textures::TextureCount); // Tint Count for (int r = 0; r < 7; r++) { @@ -2109,7 +2109,7 @@ namespace RoF outapp->WriteUInt32(0); outapp->WriteUInt32(0); - outapp->WriteUInt32(9); // Tint2 Count + outapp->WriteUInt32(EQEmu::textures::TextureCount); // Tint2 Count for (int r = 0; r < 7; r++) { @@ -4083,7 +4083,7 @@ namespace RoF if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { - for (k = 0; k < 9; ++k) + for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; ++k) { { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); @@ -4092,7 +4092,7 @@ namespace RoF structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; - for (k = 0; k < 9; k++) { + for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { Equipment[k].Material = emu->equipment.Slot[k].Material; Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; @@ -4100,7 +4100,7 @@ namespace RoF Equipment[k].Material2 = emu->equipment.Slot[k].Material2; } - Buffer += (sizeof(structs::Texture_Struct) * 9); + Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); } else { diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 0638b4ad3..5011cacb0 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2152,7 +2152,7 @@ namespace RoF2 outapp->WriteUInt32(22); // Equipment count - for (int r = 0; r < 9; r++) + for (int r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { outapp->WriteUInt32(emu->item_material.Slot[r].Material); outapp->WriteUInt32(0); @@ -2172,9 +2172,9 @@ namespace RoF2 outapp->WriteUInt32(0); } - outapp->WriteUInt32(9); // Equipment2 count + outapp->WriteUInt32(EQEmu::textures::TextureCount); // Equipment2 count - for (int r = 0; r < 9; r++) + for (int r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { outapp->WriteUInt32(0); outapp->WriteUInt32(0); @@ -2183,7 +2183,7 @@ namespace RoF2 outapp->WriteUInt32(0); } - outapp->WriteUInt32(9); // Tint Count + outapp->WriteUInt32(EQEmu::textures::TextureCount); // Tint Count for (int r = 0; r < 7; r++) { @@ -2193,7 +2193,7 @@ namespace RoF2 outapp->WriteUInt32(0); outapp->WriteUInt32(0); - outapp->WriteUInt32(9); // Tint2 Count + outapp->WriteUInt32(EQEmu::textures::TextureCount); // Tint2 Count for (int r = 0; r < 7; r++) { @@ -4306,7 +4306,7 @@ namespace RoF2 if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { - for (k = 0; k < 9; ++k) + for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; ++k) { { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); @@ -4315,7 +4315,7 @@ namespace RoF2 structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; - for (k = 0; k < 9; k++) { + for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { Equipment[k].Material = emu->equipment.Slot[k].Material; Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; @@ -4323,7 +4323,7 @@ namespace RoF2 Equipment[k].Material2 = emu->equipment.Slot[k].Material2; } - Buffer += (sizeof(structs::Texture_Struct) * 9); + Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); } else { diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 916333041..fd99fa0e9 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1553,7 +1553,7 @@ namespace SoD OUT(hairstyle); OUT(beard); // OUT(unknown00178[10]); - for (r = 0; r < 9; r++) { + for (r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { eq->equipment.Slot[r].Material = emu->item_material.Slot[r].Material; eq->equipment.Slot[r].Unknown1 = 0; eq->equipment.Slot[r].EliteMaterial = 0; @@ -2563,7 +2563,7 @@ namespace SoD float SpawnSize = emu->size; if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) { - PacketSize -= (sizeof(structs::Texture_Struct) * 9); + PacketSize -= (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); if (emu->size == 0) { @@ -2760,7 +2760,7 @@ namespace SoD if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { - for (k = 0; k < 9; ++k) + for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; ++k) { { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); @@ -2787,13 +2787,13 @@ namespace SoD { structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; - for (k = 0; k < 9; k++) { + for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { Equipment[k].Material = emu->equipment.Slot[k].Material; Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; } - Buffer += (sizeof(structs::Texture_Struct) * 9); + Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); } if (strlen(emu->title)) { diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 7944605f4..38e004cac 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1209,7 +1209,7 @@ namespace SoF OUT(hairstyle); OUT(beard); // OUT(unknown00178[10]); - for (r = 0; r < 9; r++) { + for (r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { eq->equipment.Slot[r].Material = emu->item_material.Slot[r].Material; eq->equipment.Slot[r].Unknown1 = 0; eq->equipment.Slot[r].EliteMaterial = 0; @@ -2080,7 +2080,7 @@ namespace SoF eq->deity = emu->deity; eq->drakkin_heritage = emu->drakkin_heritage; eq->gender = emu->gender; - for (k = 0; k < 9; k++) { + for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { eq->equipment.Slot[k].Material = emu->equipment.Slot[k].Material; eq->equipment.Slot[k].Unknown1 = emu->equipment.Slot[k].Unknown1; eq->equipment.Slot[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; @@ -2146,7 +2146,7 @@ namespace SoF strcpy(eq->name, emu->name); eq->petOwnerId = emu->petOwnerId; eq->pvp = 0; // 0 = non-pvp colored name, 1 = red pvp name - for (k = 0; k < 9; k++) { + for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { eq->equipment_tint.Slot[k].Color = emu->equipment_tint.Slot[k].Color; } eq->anon = emu->anon; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 2f971de8a..17112cf68 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -903,7 +903,7 @@ namespace Titanium OUT(hairstyle); OUT(beard); // OUT(unknown00178[10]); - for (r = 0; r < 9; r++) { + for (r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { OUT(item_material.Slot[r].Material); OUT(item_tint.Slot[r].Color); } @@ -1599,7 +1599,7 @@ namespace Titanium eq->petOwnerId = emu->petOwnerId; eq->guildrank = emu->guildrank; // eq->unknown0194[3] = emu->unknown0194[3]; - for (k = 0; k < 9; k++) { + for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { eq->equipment.Slot[k].Material = emu->equipment.Slot[k].Material; eq->equipment_tint.Slot[k].Color = emu->equipment_tint.Slot[k].Color; } diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 66bc0b777..0a720ea2e 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1806,7 +1806,7 @@ namespace UF OUT(hairstyle); OUT(beard); // OUT(unknown00178[10]); - for (r = 0; r < 9; r++) { + for (r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { eq->equipment.Slot[r].Material = emu->item_material.Slot[r].Material; eq->equipment.Slot[r].Unknown1 = 0; eq->equipment.Slot[r].EliteMaterial = 0; @@ -2858,7 +2858,7 @@ namespace UF float SpawnSize = emu->size; if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) { - PacketSize -= (sizeof(structs::Texture_Struct) * 9); + PacketSize -= (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); if (emu->size == 0) { @@ -3057,7 +3057,7 @@ namespace UF if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { - for (k = 0; k < 9; ++k) + for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; ++k) { { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); @@ -3093,7 +3093,7 @@ namespace UF { structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; - for (k = 0; k < 9; k++) { + for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { if (emu->equipment.Slot[k].Material > 99999) { Equipment[k].Material = 63; } else { @@ -3103,7 +3103,7 @@ namespace UF Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; } - Buffer += (sizeof(structs::Texture_Struct) * 9); + Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); } if (strlen(emu->title)) { diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 98fd4923f..ef948350a 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -162,8 +162,6 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP { corpse_graveyard_timer.Disable(); - //memset(item_tint, 0, sizeof(item_tint)); - is_corpse_changed = false; is_player_corpse = false; is_locked = false; @@ -277,8 +275,6 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( corpse_graveyard_timer.Disable(); } - //memset(item_tint, 0, sizeof(item_tint)); - for (i = 0; i < MAX_LOOTERS; i++){ allowed_looters[i] = 0; } @@ -502,8 +498,6 @@ EQEmu::TintProfile(), if (!zone->HasGraveyard() || wasAtGraveyard) corpse_graveyard_timer.Disable(); - //memset(item_tint, 0, sizeof(item_tint)); - is_corpse_changed = false; is_player_corpse = true; is_locked = false; From 62888170b06c19b1a0a7c4f389dab69cad5a45d4 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 2 Jun 2016 07:14:54 -0400 Subject: [PATCH 145/693] Better the second time around... --- common/eq_packet_structs.h | 6 +----- common/patches/rof.cpp | 12 ++++++------ common/patches/rof2.cpp | 12 ++++++------ common/patches/rof2_structs.h | 6 +----- common/patches/rof_structs.h | 6 +----- common/patches/sod.cpp | 8 ++++---- common/patches/sod_structs.h | 6 +----- common/patches/sof.cpp | 8 ++++---- common/patches/sof_structs.h | 6 +----- common/patches/titanium.cpp | 4 ++-- common/patches/uf.cpp | 8 ++++---- common/patches/uf_structs.h | 6 +----- world/worlddb.cpp | 24 ++++++++++++------------ 13 files changed, 44 insertions(+), 68 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 7674f138f..504f8aed3 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -126,11 +126,7 @@ struct LDoNTrapTemplate // All clients translate the character select information to some degree -struct CharSelectEquip -{ - EQEmu::Texture_Struct Textures; - EQEmu::Tint_Struct Color; -}; +struct CharSelectEquip : EQEmu::Texture_Struct, EQEmu::Tint_Struct {}; // RoF2-based hybrid struct struct CharacterSelectEntry_Struct diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 3b1e890bc..b60e0534f 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3047,12 +3047,12 @@ namespace RoF eq_cse->Face = emu_cse->Face; for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { - eq_cse->Equip[equip_index].Textures.Material = emu_cse->Equip[equip_index].Textures.Material; - eq_cse->Equip[equip_index].Textures.Unknown1 = emu_cse->Equip[equip_index].Textures.Unknown1; - eq_cse->Equip[equip_index].Textures.EliteMaterial = emu_cse->Equip[equip_index].Textures.EliteMaterial; - eq_cse->Equip[equip_index].Textures.HeroForgeModel = emu_cse->Equip[equip_index].Textures.HeroForgeModel; - eq_cse->Equip[equip_index].Textures.Material2 = emu_cse->Equip[equip_index].Textures.Material2; - eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color; + eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; + eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; + eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; + eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HeroForgeModel; + eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Material2; + eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } eq_cse->Unknown15 = emu_cse->Unknown15; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 5011cacb0..30941a1bf 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3140,12 +3140,12 @@ namespace RoF2 eq_cse->Face = emu_cse->Face; for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { - eq_cse->Equip[equip_index].Textures.Material = emu_cse->Equip[equip_index].Textures.Material; - eq_cse->Equip[equip_index].Textures.Unknown1 = emu_cse->Equip[equip_index].Textures.Unknown1; - eq_cse->Equip[equip_index].Textures.EliteMaterial = emu_cse->Equip[equip_index].Textures.EliteMaterial; - eq_cse->Equip[equip_index].Textures.HeroForgeModel = emu_cse->Equip[equip_index].Textures.HeroForgeModel; - eq_cse->Equip[equip_index].Textures.Material2 = emu_cse->Equip[equip_index].Textures.Material2; - eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color; + eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; + eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; + eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; + eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HeroForgeModel; + eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Material2; + eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } eq_cse->Unknown15 = emu_cse->Unknown15; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index ee9ae9c29..ed34d44b8 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -228,11 +228,7 @@ struct Texture_Struct // TextureProfile(); //}; -struct CharSelectEquip -{ - Texture_Struct Textures; - Tint_Struct Color; -}; +struct CharSelectEquip : Texture_Struct, Tint_Struct {}; struct CharacterSelectEntry_Struct { diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 1c957889a..9846b1e9e 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -228,11 +228,7 @@ struct Texture_Struct // TextureProfile(); //}; -struct CharSelectEquip -{ - Texture_Struct Textures; - Tint_Struct Color; -}; +struct CharSelectEquip : Texture_Struct, Tint_Struct {}; struct CharacterSelectEntry_Struct { diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index fd99fa0e9..58997a9a5 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1994,10 +1994,10 @@ namespace SoD eq_cse->Face = emu_cse->Face; for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { - eq_cse->Equip[equip_index].Textures.Material = emu_cse->Equip[equip_index].Textures.Material; - eq_cse->Equip[equip_index].Textures.Unknown1 = emu_cse->Equip[equip_index].Textures.Unknown1; - eq_cse->Equip[equip_index].Textures.EliteMaterial = emu_cse->Equip[equip_index].Textures.EliteMaterial; - eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color; + eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; + eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; + eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; + eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } eq_cse->PrimaryIDFile = emu_cse->PrimaryIDFile; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 6affabfe3..11331552a 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -184,11 +184,7 @@ struct TextureProfile TextureProfile(); }; -struct CharSelectEquip -{ - Texture_Struct Textures; - Tint_Struct Color; -}; +struct CharSelectEquip : Texture_Struct, Tint_Struct {}; struct CharacterSelectEntry_Struct { diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 38e004cac..c2402f1e2 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1650,10 +1650,10 @@ namespace SoF eq_cse->Face = emu_cse->Face; for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { - eq_cse->Equip[equip_index].Textures.Material = emu_cse->Equip[equip_index].Textures.Material; - eq_cse->Equip[equip_index].Textures.Unknown1 = emu_cse->Equip[equip_index].Textures.Unknown1; - eq_cse->Equip[equip_index].Textures.EliteMaterial = emu_cse->Equip[equip_index].Textures.EliteMaterial; - eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color; + eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; + eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; + eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; + eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } eq_cse->PrimaryIDFile = emu_cse->PrimaryIDFile; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 66c3f93bf..881259e3e 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -184,11 +184,7 @@ struct TextureProfile TextureProfile(); }; -struct CharSelectEquip -{ - Texture_Struct Textures; - Tint_Struct Color; -}; +struct CharSelectEquip : Texture_Struct, Tint_Struct {}; struct CharacterSelectEntry_Struct { diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 17112cf68..849f898f7 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1224,14 +1224,14 @@ namespace Titanium eq->Race[char_index] = 1; for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { - eq->CS_Colors[char_index].Slot[index].Color = emu_cse->Equip[index].Color.Color; + eq->CS_Colors[char_index].Slot[index].Color = emu_cse->Equip[index].Color; } eq->BeardColor[char_index] = emu_cse->BeardColor; eq->HairStyle[char_index] = emu_cse->HairStyle; for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { - eq->Equip[char_index].Slot[index].Material = emu_cse->Equip[index].Textures.Material; + eq->Equip[char_index].Slot[index].Material = emu_cse->Equip[index].Material; } eq->SecondaryIDFile[char_index] = emu_cse->SecondaryIDFile; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 0a720ea2e..2756ae6dd 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2291,10 +2291,10 @@ namespace UF eq_cse->Face = emu_cse->Face; for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { - eq_cse->Equip[equip_index].Textures.Material = emu_cse->Equip[equip_index].Textures.Material; - eq_cse->Equip[equip_index].Textures.Unknown1 = emu_cse->Equip[equip_index].Textures.Unknown1; - eq_cse->Equip[equip_index].Textures.EliteMaterial = emu_cse->Equip[equip_index].Textures.EliteMaterial; - eq_cse->Equip[equip_index].Color.Color = emu_cse->Equip[equip_index].Color.Color; + eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; + eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; + eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; + eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } eq_cse->PrimaryIDFile = emu_cse->PrimaryIDFile; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 284e8a336..f4f78f1c5 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -184,11 +184,7 @@ struct TextureProfile TextureProfile(); }; -struct CharSelectEquip -{ - Texture_Struct Textures; - Tint_Struct Color; -}; +struct CharSelectEquip : Texture_Struct, Tint_Struct {}; struct CharacterSelectEntry_Struct { diff --git a/world/worlddb.cpp b/world/worlddb.cpp index c1995535f..0eaa474a0 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -118,12 +118,12 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou cse->Face = (uint8)atoi(row[15]); for (uint32 matslot = 0; matslot < EQEmu::textures::TextureCount; matslot++) { // Processed below - cse->Equip[matslot].Textures.Material = 0; - cse->Equip[matslot].Textures.Unknown1 = 0; - cse->Equip[matslot].Textures.EliteMaterial = 0; - cse->Equip[matslot].Textures.HeroForgeModel = 0; - cse->Equip[matslot].Textures.Material2 = 0; - cse->Equip[matslot].Color.Color = 0; + cse->Equip[matslot].Material = 0; + cse->Equip[matslot].Unknown1 = 0; + cse->Equip[matslot].EliteMaterial = 0; + cse->Equip[matslot].HeroForgeModel = 0; + cse->Equip[matslot].Material2 = 0; + cse->Equip[matslot].Color = 0; } cse->Unknown15 = 0xFF; @@ -262,12 +262,12 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou // Weapon Models if (inst->GetOrnamentationIDFile() != 0) { idfile = inst->GetOrnamentationIDFile(); - cse->Equip[matslot].Textures.Material = idfile; + cse->Equip[matslot].Material = idfile; } else { if (strlen(item->IDFile) > 2) { idfile = atoi(&item->IDFile[2]); - cse->Equip[matslot].Textures.Material = idfile; + cse->Equip[matslot].Material = idfile; } } if (matslot == EQEmu::textures::TexturePrimary) { @@ -287,10 +287,10 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou } // Armor Materials/Models - cse->Equip[matslot].Textures.Material = item->Material; - cse->Equip[matslot].Textures.EliteMaterial = item->EliteMaterial; - cse->Equip[matslot].Textures.HeroForgeModel = inst->GetOrnamentHeroModel(matslot); - cse->Equip[matslot].Color.Color = color; + cse->Equip[matslot].Material = item->Material; + cse->Equip[matslot].EliteMaterial = item->EliteMaterial; + cse->Equip[matslot].HeroForgeModel = inst->GetOrnamentHeroModel(matslot); + cse->Equip[matslot].Color = color; } } } From 542dc167525f786e2f4c9a9e56ee6aeb64c44db2 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 2 Jun 2016 20:07:25 -0400 Subject: [PATCH 146/693] Fix for bandolier 2H-weapon exploit --- zone/inventory.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 8eacb8b62..d03cac310 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -2721,6 +2721,8 @@ void Client::CreateBandolier(const EQApplicationPacket *app) const EQEmu::ItemBase *BaseItem = nullptr; int16 WeaponSlot = 0; + database.DeleteCharacterBandolier(this->CharacterID(), bs->Number); + for(int BandolierSlot = bandolierPrimary; BandolierSlot <= bandolierAmmo; BandolierSlot++) { WeaponSlot = BandolierSlotToWeaponSlot(BandolierSlot); InvItem = GetInv()[WeaponSlot]; From e843f66135a815cd0b60c6ca181dc9d947d3d451 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 2 Jun 2016 20:19:40 -0400 Subject: [PATCH 147/693] Cosmetic fix to match existing naming conventions --- common/emu_limits.h | 16 +-- common/eq_limits.cpp | 240 +++++++++++++++++++++---------------------- 2 files changed, 128 insertions(+), 128 deletions(-) diff --git a/common/emu_limits.h b/common/emu_limits.h index 5c72315a0..93c4ad8f8 100644 --- a/common/emu_limits.h +++ b/common/emu_limits.h @@ -27,41 +27,41 @@ namespace EntityLimits { - namespace npc { + namespace NPC { enum : int { Invalid = -1, Null, Safety }; enum : bool { False = false, True = true }; const size_t InvTypeTradeSize = 4; - } /*npc*/ + } /*NPC*/ - namespace merc { + namespace Merc { enum : int { Invalid = -1, Null, Safety }; enum : bool { False = false, True = true }; const size_t InvTypeTradeSize = 4; - } /*merc*/ + } /*Merc*/ - namespace bot { + namespace Bot { enum : int { Invalid = -1, Null, Safety }; enum : bool { False = false, True = true }; const size_t InvTypeTradeSize = 8; - } /*bot*/ + } /*Bot*/ - namespace pet { + namespace Pet { enum : int { Invalid = -1, Null, Safety }; enum : bool { False = false, True = true }; const size_t InvTypeTradeSize = 4; - } /*pet*/ + } /*Pet*/ }; /*EntityLimits*/ diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index f9bee1c71..57175311a 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -69,10 +69,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeBankSize, RoF::invtype::InvTypeBankSize, RoF2::invtype::InvTypeBankSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -89,10 +89,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeSharedBankSize, RoF::invtype::InvTypeSharedBankSize, RoF2::invtype::InvTypeSharedBankSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -109,10 +109,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeTradeSize, RoF::invtype::InvTypeTradeSize, RoF2::invtype::InvTypeTradeSize, - EntityLimits::npc::InvTypeTradeSize, - EntityLimits::merc::InvTypeTradeSize, - EntityLimits::bot::InvTypeTradeSize, // client thinks this is another client - EntityLimits::pet::InvTypeTradeSize, + EntityLimits::NPC::InvTypeTradeSize, + EntityLimits::Merc::InvTypeTradeSize, + EntityLimits::Bot::InvTypeTradeSize, // client thinks this is another client + EntityLimits::Pet::InvTypeTradeSize, Titanium::invtype::InvTypeTradeSize, SoF::invtype::InvTypeTradeSize, SoD::invtype::InvTypeTradeSize, @@ -129,10 +129,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeWorldSize, RoF::invtype::InvTypeWorldSize, RoF2::invtype::InvTypeWorldSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -149,10 +149,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeLimboSize, RoF::invtype::InvTypeLimboSize, RoF2::invtype::InvTypeLimboSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -169,10 +169,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeTributeSize, RoF::invtype::InvTypeTributeSize, RoF2::invtype::InvTypeTributeSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -189,10 +189,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::Null, RoF::Null, //RoF::invtype::InvTypeTrophyTributeSize, RoF2::Null, //RoF2::invtype::InvTypeTrophyTributeSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -209,10 +209,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::Null, //UF::invtype::InvTypeGuildTributeSize, RoF::Null, //RoF::invtype::InvTypeGuildTributeSize, RoF2::Null, //RoF2::invtype::InvTypeGuildTributeSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -229,10 +229,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeMerchantSize, RoF::invtype::InvTypeMerchantSize, RoF2::invtype::InvTypeMerchantSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::invtype::InvTypeMerchantSize, SoF::invtype::InvTypeMerchantSize, SoD::invtype::InvTypeMerchantSize, @@ -249,10 +249,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::Null, RoF::Null, //RoF::invtype::InvTypeDeletedSize, RoF2::Null, //RoF2::invtype::InvTypeDeletedSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -269,10 +269,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeCorpseSize, RoF::invtype::InvTypeCorpseSize, RoF2::invtype::InvTypeCorpseSize, - EntityLimits::npc::Null, //InvTypeCorpseSize, - EntityLimits::merc::Null, //InvTypeCorpseSize, - EntityLimits::bot::Null, //InvTypeCorpseSize, - EntityLimits::pet::Null, //InvTypeCorpseSize, + EntityLimits::NPC::Null, //InvTypeCorpseSize, + EntityLimits::Merc::Null, //InvTypeCorpseSize, + EntityLimits::Bot::Null, //InvTypeCorpseSize, + EntityLimits::Pet::Null, //InvTypeCorpseSize, Titanium::Null, SoF::Null, SoD::Null, @@ -289,10 +289,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento legacy::TYPE_BAZAAR_SIZE, //UF::invtype::InvTypeBazaarSize, legacy::TYPE_BAZAAR_SIZE, //RoF::invtype::InvTypeBazaarSize, legacy::TYPE_BAZAAR_SIZE, //RoF2::invtype::InvTypeBazaarSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, //Titanium::invtype::InvTypeBazaarSize, SoF::Null, //SoF::invtype::InvTypeBazaarSize, SoD::Null, //SoD::invtype::InvTypeBazaarSize, @@ -309,10 +309,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeInspectSize, RoF::invtype::InvTypeInspectSize, RoF2::invtype::InvTypeInspectSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::invtype::InvTypeInspectSize, SoF::invtype::InvTypeInspectSize, SoD::invtype::InvTypeInspectSize, @@ -329,10 +329,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::Null, RoF::Null, //RoF::invtype::InvTypeRealEstateSize, RoF2::Null, //RoF2::invtype::InvTypeRealEstateSize - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -349,10 +349,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeViewMODPCSize, RoF::invtype::InvTypeViewMODPCSize, RoF2::invtype::InvTypeViewMODPCSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::invtype::InvTypeViewMODPCSize, SoF::invtype::InvTypeViewMODPCSize, SoD::invtype::InvTypeViewMODPCSize, @@ -369,10 +369,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeViewMODBankSize, RoF::invtype::InvTypeViewMODBankSize, RoF2::invtype::InvTypeViewMODBankSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::invtype::InvTypeViewMODBankSize, SoF::invtype::InvTypeViewMODBankSize, SoD::invtype::InvTypeViewMODBankSize, @@ -389,10 +389,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeViewMODSharedBankSize, RoF::invtype::InvTypeViewMODSharedBankSize, RoF2::invtype::InvTypeViewMODSharedBankSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::invtype::InvTypeViewMODSharedBankSize, SoF::invtype::InvTypeViewMODSharedBankSize, SoD::invtype::InvTypeViewMODSharedBankSize, @@ -409,10 +409,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeViewMODLimboSize, RoF::invtype::InvTypeViewMODLimboSize, RoF2::invtype::InvTypeViewMODLimboSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::invtype::InvTypeViewMODLimboSize, SoF::invtype::InvTypeViewMODLimboSize, SoD::invtype::InvTypeViewMODLimboSize, @@ -429,10 +429,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeAltStorageSize, RoF::invtype::InvTypeAltStorageSize, RoF2::invtype::InvTypeAltStorageSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -449,10 +449,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeArchivedSize, RoF::invtype::InvTypeArchivedSize, RoF2::invtype::InvTypeArchivedSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -469,10 +469,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::Null, RoF::invtype::InvTypeMailSize, RoF2::invtype::InvTypeMailSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -489,10 +489,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::Null, RoF::invtype::InvTypeGuildTrophyTributeSize, RoF2::invtype::InvTypeGuildTrophyTributeSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -509,10 +509,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::Null, RoF::Null, RoF2::invtype::InvTypeKronoSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -529,10 +529,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento UF::invtype::InvTypeOtherSize, RoF::invtype::InvTypeOtherSize, RoF2::invtype::InvTypeOtherSize, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -559,10 +559,10 @@ uint64 EQEmu::inventory::GetPossessionsBitmask(versions::InventoryVersion invent UF::Null, //0x000000027FFFFFFF, RoF::Null, //0x00000003FFFFFFFF, RoF2::Null, //0x00000003FFFFFFFF, - EntityLimits::npc::Null, - EntityLimits::merc::Null, - EntityLimits::bot::Null, - EntityLimits::pet::Null, + EntityLimits::NPC::Null, + EntityLimits::Merc::Null, + EntityLimits::Bot::Null, + EntityLimits::Pet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -585,10 +585,10 @@ bool EQEmu::inventory::GetAllowEmptyBagInBag(versions::InventoryVersion inventor UF::inventory::AllowEmptyBagInBag, RoF::False, //RoF::inventory::AllowEmptyBagInBag, RoF2::False, //RoF2::inventory::AllowEmptyBagInBag, - EntityLimits::npc::False, - EntityLimits::merc::False, - EntityLimits::bot::False, - EntityLimits::pet::False, + EntityLimits::NPC::False, + EntityLimits::Merc::False, + EntityLimits::Bot::False, + EntityLimits::Pet::False, Titanium::False, SoF::False, SoD::False, @@ -611,10 +611,10 @@ bool EQEmu::inventory::GetAllowClickCastFromBag(versions::InventoryVersion inven UF::inventory::AllowClickCastFromBag, RoF::inventory::AllowClickCastFromBag, RoF2::inventory::AllowClickCastFromBag, - EntityLimits::npc::False, - EntityLimits::merc::False, - EntityLimits::bot::False, - EntityLimits::pet::False, + EntityLimits::NPC::False, + EntityLimits::Merc::False, + EntityLimits::Bot::False, + EntityLimits::Pet::False, Titanium::False, SoF::False, SoD::False, @@ -637,10 +637,10 @@ bool EQEmu::inventory::GetConcatenateInvTypeLimbo(versions::InventoryVersion inv UF::inventory::ConcatenateInvTypeLimbo, RoF::inventory::ConcatenateInvTypeLimbo, RoF2::inventory::ConcatenateInvTypeLimbo, - EntityLimits::npc::False, - EntityLimits::merc::False, - EntityLimits::bot::False, - EntityLimits::pet::False, + EntityLimits::NPC::False, + EntityLimits::Merc::False, + EntityLimits::Bot::False, + EntityLimits::Pet::False, Titanium::False, SoF::False, SoD::False, @@ -663,10 +663,10 @@ bool EQEmu::inventory::GetAllowOverLevelEquipment(versions::InventoryVersion inv UF::inventory::AllowOverLevelEquipment, RoF::inventory::AllowOverLevelEquipment, RoF2::inventory::AllowOverLevelEquipment, - EntityLimits::npc::False, - EntityLimits::merc::False, - EntityLimits::bot::False, - EntityLimits::pet::False, + EntityLimits::NPC::False, + EntityLimits::Merc::False, + EntityLimits::Bot::False, + EntityLimits::Pet::False, Titanium::False, SoF::False, SoD::False, @@ -741,10 +741,10 @@ bool EQEmu::behavior::GetCoinHasWeight(versions::InventoryVersion inventory_vers UF::behavior::CoinHasWeight, RoF::behavior::CoinHasWeight, RoF::behavior::CoinHasWeight, - EntityLimits::npc::True, //CoinHasWeight, - EntityLimits::merc::True, //CoinHasWeight, - EntityLimits::bot::True, //CoinHasWeight, - EntityLimits::pet::True, //CoinHasWeight, + EntityLimits::NPC::True, //CoinHasWeight, + EntityLimits::Merc::True, //CoinHasWeight, + EntityLimits::Bot::True, //CoinHasWeight, + EntityLimits::Pet::True, //CoinHasWeight, Titanium::False, SoF::False, SoD::False, From 51d8f00418f5bc6de91117ddef011f1914a04417 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 2 Jun 2016 20:12:41 -0700 Subject: [PATCH 148/693] Add appveyor badge to readme (wip but still). --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0c973ed43..154703a75 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ EQEmu === -[![Build Status](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) +[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) +[![Windows CI](https://ci.appveyor.com/api/projects/status/d0cvokm7u732v8vl/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server/branch/master) Overview --- From c29219f2147edd8a0d7b605024da9d2ea256e840 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 4 Jun 2016 07:04:31 -0400 Subject: [PATCH 149/693] Split InventoryVersion::Pet into discrete sub-types --- common/emu_limits.h | 29 +++++++- common/emu_versions.cpp | 10 ++- common/emu_versions.h | 7 +- common/eq_limits.cpp | 159 ++++++++++++++++++++++++++++++++-------- 4 files changed, 170 insertions(+), 35 deletions(-) diff --git a/common/emu_limits.h b/common/emu_limits.h index 93c4ad8f8..444ff8dc0 100644 --- a/common/emu_limits.h +++ b/common/emu_limits.h @@ -54,7 +54,34 @@ namespace EntityLimits } /*Bot*/ - namespace Pet { + namespace ClientPet { + enum : int { Invalid = -1, Null, Safety }; + + enum : bool { False = false, True = true }; + + const size_t InvTypeTradeSize = 4; + + } /*Pet*/ + + namespace NPCPet { + enum : int { Invalid = -1, Null, Safety }; + + enum : bool { False = false, True = true }; + + const size_t InvTypeTradeSize = 4; + + } /*Pet*/ + + namespace MercPet { + enum : int { Invalid = -1, Null, Safety }; + + enum : bool { False = false, True = true }; + + const size_t InvTypeTradeSize = 4; + + } /*Pet*/ + + namespace BotPet { enum : int { Invalid = -1, Null, Safety }; enum : bool { False = false, True = true }; diff --git a/common/emu_versions.cpp b/common/emu_versions.cpp index 3104b6832..71c6282aa 100644 --- a/common/emu_versions.cpp +++ b/common/emu_versions.cpp @@ -216,8 +216,14 @@ const char* EQEmu::versions::InventoryVersionName(InventoryVersion inventory_ver return "Merc"; case InventoryVersion::Bot: return "Bot"; - case InventoryVersion::Pet: - return "Pet"; + case InventoryVersion::ClientPet: + return "Client Pet"; + case InventoryVersion::NPCPet: + return "NPC Pet"; + case InventoryVersion::MercPet: + return "Merc Pet"; + case InventoryVersion::BotPet: + return "Bot Pet"; case InventoryVersion::OfflineTitanium: return "Offline Titanium"; case InventoryVersion::OfflineSoF: diff --git a/common/emu_versions.h b/common/emu_versions.h index 82244f039..4b1f95262 100644 --- a/common/emu_versions.h +++ b/common/emu_versions.h @@ -86,7 +86,10 @@ namespace EQEmu NPC, Merc, Bot, - Pet, + ClientPet, + NPCPet, + MercPet, + BotPet, OfflineTitanium, OfflineSoF, OfflineSoD, @@ -97,7 +100,7 @@ namespace EQEmu const InventoryVersion LastInventoryVersion = InventoryVersion::OfflineRoF2; const InventoryVersion LastPCInventoryVersion = InventoryVersion::RoF2; - const InventoryVersion LastNonPCInventoryVersion = InventoryVersion::Pet; + const InventoryVersion LastNonPCInventoryVersion = InventoryVersion::BotPet; const InventoryVersion LastOfflinePCInventoryVersion = InventoryVersion::OfflineRoF2; const size_t InventoryVersionCount = (static_cast(LastInventoryVersion) + 1); diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 57175311a..b83c0fa44 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -53,6 +53,9 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, + legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, Titanium::Null, SoF::Null, SoD::Null, @@ -72,7 +75,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -92,7 +98,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -112,7 +121,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::InvTypeTradeSize, EntityLimits::Merc::InvTypeTradeSize, EntityLimits::Bot::InvTypeTradeSize, // client thinks this is another client - EntityLimits::Pet::InvTypeTradeSize, + EntityLimits::ClientPet::InvTypeTradeSize, + EntityLimits::NPCPet::InvTypeTradeSize, + EntityLimits::MercPet::InvTypeTradeSize, + EntityLimits::BotPet::InvTypeTradeSize, Titanium::invtype::InvTypeTradeSize, SoF::invtype::InvTypeTradeSize, SoD::invtype::InvTypeTradeSize, @@ -132,7 +144,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -152,7 +167,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -172,7 +190,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -192,7 +213,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -212,7 +236,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -232,7 +259,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::invtype::InvTypeMerchantSize, SoF::invtype::InvTypeMerchantSize, SoD::invtype::InvTypeMerchantSize, @@ -252,7 +282,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -272,7 +305,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, //InvTypeCorpseSize, EntityLimits::Merc::Null, //InvTypeCorpseSize, EntityLimits::Bot::Null, //InvTypeCorpseSize, - EntityLimits::Pet::Null, //InvTypeCorpseSize, + EntityLimits::ClientPet::Null, //InvTypeCorpseSize, + EntityLimits::NPCPet::Null, //InvTypeCorpseSize, + EntityLimits::MercPet::Null, //InvTypeCorpseSize, + EntityLimits::BotPet::Null, //InvTypeCorpseSize, Titanium::Null, SoF::Null, SoD::Null, @@ -292,7 +328,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, //Titanium::invtype::InvTypeBazaarSize, SoF::Null, //SoF::invtype::InvTypeBazaarSize, SoD::Null, //SoD::invtype::InvTypeBazaarSize, @@ -312,7 +351,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::invtype::InvTypeInspectSize, SoF::invtype::InvTypeInspectSize, SoD::invtype::InvTypeInspectSize, @@ -332,7 +374,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -352,7 +397,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::invtype::InvTypeViewMODPCSize, SoF::invtype::InvTypeViewMODPCSize, SoD::invtype::InvTypeViewMODPCSize, @@ -372,7 +420,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::invtype::InvTypeViewMODBankSize, SoF::invtype::InvTypeViewMODBankSize, SoD::invtype::InvTypeViewMODBankSize, @@ -392,7 +443,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::invtype::InvTypeViewMODSharedBankSize, SoF::invtype::InvTypeViewMODSharedBankSize, SoD::invtype::InvTypeViewMODSharedBankSize, @@ -412,7 +466,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::invtype::InvTypeViewMODLimboSize, SoF::invtype::InvTypeViewMODLimboSize, SoD::invtype::InvTypeViewMODLimboSize, @@ -432,7 +489,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -452,7 +512,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -472,7 +535,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -492,7 +558,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -512,7 +581,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -532,7 +604,10 @@ size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion invento EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -562,7 +637,10 @@ uint64 EQEmu::inventory::GetPossessionsBitmask(versions::InventoryVersion invent EntityLimits::NPC::Null, EntityLimits::Merc::Null, EntityLimits::Bot::Null, - EntityLimits::Pet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::BotPet::Null, Titanium::Null, SoF::Null, SoD::Null, @@ -588,7 +666,10 @@ bool EQEmu::inventory::GetAllowEmptyBagInBag(versions::InventoryVersion inventor EntityLimits::NPC::False, EntityLimits::Merc::False, EntityLimits::Bot::False, - EntityLimits::Pet::False, + EntityLimits::ClientPet::False, + EntityLimits::NPCPet::False, + EntityLimits::MercPet::False, + EntityLimits::BotPet::False, Titanium::False, SoF::False, SoD::False, @@ -614,7 +695,10 @@ bool EQEmu::inventory::GetAllowClickCastFromBag(versions::InventoryVersion inven EntityLimits::NPC::False, EntityLimits::Merc::False, EntityLimits::Bot::False, - EntityLimits::Pet::False, + EntityLimits::ClientPet::False, + EntityLimits::NPCPet::False, + EntityLimits::MercPet::False, + EntityLimits::BotPet::False, Titanium::False, SoF::False, SoD::False, @@ -640,7 +724,10 @@ bool EQEmu::inventory::GetConcatenateInvTypeLimbo(versions::InventoryVersion inv EntityLimits::NPC::False, EntityLimits::Merc::False, EntityLimits::Bot::False, - EntityLimits::Pet::False, + EntityLimits::ClientPet::False, + EntityLimits::NPCPet::False, + EntityLimits::MercPet::False, + EntityLimits::BotPet::False, Titanium::False, SoF::False, SoD::False, @@ -666,7 +753,10 @@ bool EQEmu::inventory::GetAllowOverLevelEquipment(versions::InventoryVersion inv EntityLimits::NPC::False, EntityLimits::Merc::False, EntityLimits::Bot::False, - EntityLimits::Pet::False, + EntityLimits::ClientPet::False, + EntityLimits::NPCPet::False, + EntityLimits::MercPet::False, + EntityLimits::BotPet::False, Titanium::False, SoF::False, SoD::False, @@ -693,6 +783,9 @@ size_t EQEmu::inventory::GetItemAugSize(versions::InventoryVersion inventory_ver legacy::ITEM_COMMON_SIZE, //ItemAugSize, legacy::ITEM_COMMON_SIZE, //ItemAugSize, legacy::ITEM_COMMON_SIZE, //ItemAugSize, + legacy::ITEM_COMMON_SIZE, //ItemAugSize, + legacy::ITEM_COMMON_SIZE, //ItemAugSize, + legacy::ITEM_COMMON_SIZE, //ItemAugSize, Titanium::Null, SoF::Null, SoD::Null, @@ -719,6 +812,9 @@ size_t EQEmu::inventory::GetItemBagSize(versions::InventoryVersion inventory_ver legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, + legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, legacy::ITEM_CONTAINER_SIZE, //Titanium::Null, legacy::ITEM_CONTAINER_SIZE, //SoF::Null, legacy::ITEM_CONTAINER_SIZE, //SoD::Null, @@ -744,7 +840,10 @@ bool EQEmu::behavior::GetCoinHasWeight(versions::InventoryVersion inventory_vers EntityLimits::NPC::True, //CoinHasWeight, EntityLimits::Merc::True, //CoinHasWeight, EntityLimits::Bot::True, //CoinHasWeight, - EntityLimits::Pet::True, //CoinHasWeight, + EntityLimits::ClientPet::True, //CoinHasWeight, + EntityLimits::NPCPet::True, //CoinHasWeight, + EntityLimits::MercPet::True, //CoinHasWeight, + EntityLimits::BotPet::True, //CoinHasWeight, Titanium::False, SoF::False, SoD::False, From 4b15121f70f9415467ee7434c4a9e0c8c71fc734 Mon Sep 17 00:00:00 2001 From: JJ Date: Sat, 4 Jun 2016 19:53:22 -0400 Subject: [PATCH 150/693] No need to have extra slash anymore due to b997a040d7cb5a87607023e41be0420652eb4933 --- zone/pathing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/pathing.cpp b/zone/pathing.cpp index a39441564..16b340d94 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -52,7 +52,7 @@ PathManager* PathManager::LoadPathFile(const char* ZoneName) strlwr(LowerCaseZoneName); - snprintf(ZonePathFileName, 250, "%s/%s.path", Config->MapDir.c_str(),LowerCaseZoneName); + snprintf(ZonePathFileName, 250, "%s%s.path", Config->MapDir.c_str(), LowerCaseZoneName); if((PathFile = fopen(ZonePathFileName, "rb"))) { From 9ec299247cb9cdaf3a67d91d4f78e3e327c69bf7 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 6 Jun 2016 21:59:42 -0400 Subject: [PATCH 151/693] Reworked EQEmuDictionary to use class LookupEntry --- changelog.txt | 3 + common/emu_limits.h | 9 + common/emu_versions.cpp | 2 + common/emu_versions.h | 1 + common/eq_limits.cpp | 1161 ++++++++++++--------------------------- common/eq_limits.h | 36 +- common/item.cpp | 2 +- world/client.cpp | 4 +- world/worlddb.cpp | 2 +- zone/client_mods.cpp | 2 +- zone/corpse.cpp | 4 +- 11 files changed, 390 insertions(+), 836 deletions(-) diff --git a/changelog.txt b/changelog.txt index 003ac4555..f3dcd8117 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 06/06/2016 == +Uleat: Reworked EQEmuDictionary to use class LookupEntry + == 06/01/2016 == Uleat: Implemented EQEmu::TintProfile Uleat: Implemented EQEmu::TextureProfile diff --git a/common/emu_limits.h b/common/emu_limits.h index 444ff8dc0..76034906b 100644 --- a/common/emu_limits.h +++ b/common/emu_limits.h @@ -36,6 +36,15 @@ namespace EntityLimits } /*NPC*/ + namespace NPCMerchant { + enum : int { Invalid = -1, Null, Safety }; + + enum : bool { False = false, True = true }; + + const size_t InvTypeTradeSize = 4; + + } /*NPCMerchant*/ + namespace Merc { enum : int { Invalid = -1, Null, Safety }; diff --git a/common/emu_versions.cpp b/common/emu_versions.cpp index 71c6282aa..92766e407 100644 --- a/common/emu_versions.cpp +++ b/common/emu_versions.cpp @@ -212,6 +212,8 @@ const char* EQEmu::versions::InventoryVersionName(InventoryVersion inventory_ver return "RoF2"; case InventoryVersion::NPC: return "NPC"; + case InventoryVersion::NPCMerchant: + return "NPC Merchant"; case InventoryVersion::Merc: return "Merc"; case InventoryVersion::Bot: diff --git a/common/emu_versions.h b/common/emu_versions.h index 4b1f95262..8a806e8fc 100644 --- a/common/emu_versions.h +++ b/common/emu_versions.h @@ -84,6 +84,7 @@ namespace EQEmu RoF, RoF2, NPC, + NPCMerchant, Merc, Bot, ClientPet, diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index b83c0fa44..800206d0d 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -21,836 +21,361 @@ #include "emu_limits.h" -size_t EQEmu::constants::GetCharacterCreationLimit(versions::ClientVersion client_version) +static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versions::ClientVersionCount] = { - static const size_t local[versions::ClientVersionCount] = { - ClientUnknown::Null, - Client62::Null, - Titanium::constants::CharacterCreationLimit, - SoF::constants::CharacterCreationLimit, - SoD::constants::CharacterCreationLimit, - UF::constants::CharacterCreationLimit, - RoF::constants::CharacterCreationLimit, + { // Unknown + ClientUnknown::Null + }, + { // Client62 + Client62::Null + }, + { // Titanium + Titanium::constants::CharacterCreationLimit + }, + { // SoF + SoF::constants::CharacterCreationLimit + }, + { // SoD + SoD::constants::CharacterCreationLimit + }, + { // UF + UF::constants::CharacterCreationLimit + }, + { // RoF + RoF::constants::CharacterCreationLimit + }, + { // RoF2 RoF2::constants::CharacterCreationLimit - }; + } +}; - return local[static_cast(versions::ValidateClientVersion(client_version))]; +const EQEmu::constants::LookupEntry* EQEmu::constants::Lookup(versions::ClientVersion client_version) +{ + return &constants_lookup_entries[static_cast(versions::ValidateClientVersion(client_version))]; } -size_t EQEmu::inventory::GetInventoryTypeSize(versions::InventoryVersion inventory_version, int inv_type) +static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versions::InventoryVersionCount] = { - static const size_t local[legacy::TypeCount][versions::InventoryVersionCount] = { - { // local[TypePossessions] - ClientUnknown::Null, - Client62::Null, - legacy::TYPE_POSSESSIONS_SIZE, //Titanium::invtype::InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //SoF::invtype::InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //SoD::invtype::InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //UF::invtype::InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //RoF::invtype::InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //RoF2::invtype::InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, - legacy::TYPE_POSSESSIONS_SIZE, //InvTypePossessionsSize, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeBank] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeBankSize, - SoF::invtype::InvTypeBankSize, - SoD::invtype::InvTypeBankSize, - UF::invtype::InvTypeBankSize, - RoF::invtype::InvTypeBankSize, - RoF2::invtype::InvTypeBankSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeSharedBank] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeSharedBankSize, - SoF::invtype::InvTypeSharedBankSize, - SoD::invtype::InvTypeSharedBankSize, - UF::invtype::InvTypeSharedBankSize, - RoF::invtype::InvTypeSharedBankSize, - RoF2::invtype::InvTypeSharedBankSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeTrade] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeTradeSize, - SoF::invtype::InvTypeTradeSize, - SoD::invtype::InvTypeTradeSize, - UF::invtype::InvTypeTradeSize, - RoF::invtype::InvTypeTradeSize, - RoF2::invtype::InvTypeTradeSize, - EntityLimits::NPC::InvTypeTradeSize, - EntityLimits::Merc::InvTypeTradeSize, - EntityLimits::Bot::InvTypeTradeSize, // client thinks this is another client - EntityLimits::ClientPet::InvTypeTradeSize, - EntityLimits::NPCPet::InvTypeTradeSize, - EntityLimits::MercPet::InvTypeTradeSize, - EntityLimits::BotPet::InvTypeTradeSize, - Titanium::invtype::InvTypeTradeSize, - SoF::invtype::InvTypeTradeSize, - SoD::invtype::InvTypeTradeSize, - UF::invtype::InvTypeTradeSize, - RoF::invtype::InvTypeTradeSize, - RoF2::invtype::InvTypeTradeSize - }, - { // local[TypeWorld] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeWorldSize, - SoF::invtype::InvTypeWorldSize, - SoD::invtype::InvTypeWorldSize, - UF::invtype::InvTypeWorldSize, - RoF::invtype::InvTypeWorldSize, - RoF2::invtype::InvTypeWorldSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeLimbo] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeLimboSize, - SoF::invtype::InvTypeLimboSize, - SoD::invtype::InvTypeLimboSize, - UF::invtype::InvTypeLimboSize, - RoF::invtype::InvTypeLimboSize, - RoF2::invtype::InvTypeLimboSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeTribute] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeTributeSize, - SoF::invtype::InvTypeTributeSize, - SoD::invtype::InvTypeTributeSize, - UF::invtype::InvTypeTributeSize, - RoF::invtype::InvTypeTributeSize, - RoF2::invtype::InvTypeTributeSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeTrophyTribute] - ClientUnknown::Null, - Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, //RoF::invtype::InvTypeTrophyTributeSize, - RoF2::Null, //RoF2::invtype::InvTypeTrophyTributeSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeGuildTribute] - ClientUnknown::Null, - Client62::Null, - Titanium::Null, //Titanium::invtype::InvTypeGuildTributeSize, - SoF::Null, //SoF::invtype::InvTypeGuildTributeSize, - SoD::Null, //SoD::invtype::InvTypeGuildTributeSize, - UF::Null, //UF::invtype::InvTypeGuildTributeSize, - RoF::Null, //RoF::invtype::InvTypeGuildTributeSize, - RoF2::Null, //RoF2::invtype::InvTypeGuildTributeSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeMerchant] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeMerchantSize, - SoF::invtype::InvTypeMerchantSize, - SoD::invtype::InvTypeMerchantSize, - UF::invtype::InvTypeMerchantSize, - RoF::invtype::InvTypeMerchantSize, - RoF2::invtype::InvTypeMerchantSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::invtype::InvTypeMerchantSize, - SoF::invtype::InvTypeMerchantSize, - SoD::invtype::InvTypeMerchantSize, - UF::invtype::InvTypeMerchantSize, - RoF::invtype::InvTypeMerchantSize, - RoF2::invtype::InvTypeMerchantSize - }, - { // local[TypeDeleted] - ClientUnknown::Null, - Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, //RoF::invtype::InvTypeDeletedSize, - RoF2::Null, //RoF2::invtype::InvTypeDeletedSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeCorpse] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeCorpseSize, - SoF::invtype::InvTypeCorpseSize, - SoD::invtype::InvTypeCorpseSize, - UF::invtype::InvTypeCorpseSize, - RoF::invtype::InvTypeCorpseSize, - RoF2::invtype::InvTypeCorpseSize, - EntityLimits::NPC::Null, //InvTypeCorpseSize, - EntityLimits::Merc::Null, //InvTypeCorpseSize, - EntityLimits::Bot::Null, //InvTypeCorpseSize, - EntityLimits::ClientPet::Null, //InvTypeCorpseSize, - EntityLimits::NPCPet::Null, //InvTypeCorpseSize, - EntityLimits::MercPet::Null, //InvTypeCorpseSize, - EntityLimits::BotPet::Null, //InvTypeCorpseSize, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeBazaar] - ClientUnknown::Null, - Client62::Null, - legacy::TYPE_BAZAAR_SIZE, //Titanium::invtype::InvTypeBazaarSize, - legacy::TYPE_BAZAAR_SIZE, //SoF::invtype::InvTypeBazaarSize, - legacy::TYPE_BAZAAR_SIZE, //SoD::invtype::InvTypeBazaarSize, - legacy::TYPE_BAZAAR_SIZE, //UF::invtype::InvTypeBazaarSize, - legacy::TYPE_BAZAAR_SIZE, //RoF::invtype::InvTypeBazaarSize, - legacy::TYPE_BAZAAR_SIZE, //RoF2::invtype::InvTypeBazaarSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, //Titanium::invtype::InvTypeBazaarSize, - SoF::Null, //SoF::invtype::InvTypeBazaarSize, - SoD::Null, //SoD::invtype::InvTypeBazaarSize, - UF::Null, //UF::invtype::InvTypeBazaarSize, - RoF::Null, //RoF::invtype::InvTypeBazaarSize, - RoF2::Null //RoF2::invtype::InvTypeBazaarSize, - }, - { // local[TypeInspect] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeInspectSize, - SoF::invtype::InvTypeInspectSize, - SoD::invtype::InvTypeInspectSize, - UF::invtype::InvTypeInspectSize, - RoF::invtype::InvTypeInspectSize, - RoF2::invtype::InvTypeInspectSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::invtype::InvTypeInspectSize, - SoF::invtype::InvTypeInspectSize, - SoD::invtype::InvTypeInspectSize, - UF::invtype::InvTypeInspectSize, - RoF::invtype::InvTypeInspectSize, - RoF2::invtype::InvTypeInspectSize - }, - { // local[TypeRealEstate] - ClientUnknown::Null, - Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, //RoF::invtype::InvTypeRealEstateSize, - RoF2::Null, //RoF2::invtype::InvTypeRealEstateSize - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeViewMODPC] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeViewMODPCSize, - SoF::invtype::InvTypeViewMODPCSize, - SoD::invtype::InvTypeViewMODPCSize, - UF::invtype::InvTypeViewMODPCSize, - RoF::invtype::InvTypeViewMODPCSize, - RoF2::invtype::InvTypeViewMODPCSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::invtype::InvTypeViewMODPCSize, - SoF::invtype::InvTypeViewMODPCSize, - SoD::invtype::InvTypeViewMODPCSize, - UF::invtype::InvTypeViewMODPCSize, - RoF::invtype::InvTypeViewMODPCSize, - RoF2::invtype::InvTypeViewMODPCSize - }, - { // local[TypeViewMODBank] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeViewMODBankSize, - SoF::invtype::InvTypeViewMODBankSize, - SoD::invtype::InvTypeViewMODBankSize, - UF::invtype::InvTypeViewMODBankSize, - RoF::invtype::InvTypeViewMODBankSize, - RoF2::invtype::InvTypeViewMODBankSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::invtype::InvTypeViewMODBankSize, - SoF::invtype::InvTypeViewMODBankSize, - SoD::invtype::InvTypeViewMODBankSize, - UF::invtype::InvTypeViewMODBankSize, - RoF::invtype::InvTypeViewMODBankSize, - RoF2::invtype::InvTypeViewMODBankSize - }, - { // local[TypeViewMODSharedBank] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeViewMODSharedBankSize, - SoF::invtype::InvTypeViewMODSharedBankSize, - SoD::invtype::InvTypeViewMODSharedBankSize, - UF::invtype::InvTypeViewMODSharedBankSize, - RoF::invtype::InvTypeViewMODSharedBankSize, - RoF2::invtype::InvTypeViewMODSharedBankSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::invtype::InvTypeViewMODSharedBankSize, - SoF::invtype::InvTypeViewMODSharedBankSize, - SoD::invtype::InvTypeViewMODSharedBankSize, - UF::invtype::InvTypeViewMODSharedBankSize, - RoF::invtype::InvTypeViewMODSharedBankSize, - RoF2::invtype::InvTypeViewMODSharedBankSize - }, - { // local[TypeViewMODLimbo] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeViewMODLimboSize, - SoF::invtype::InvTypeViewMODLimboSize, - SoD::invtype::InvTypeViewMODLimboSize, - UF::invtype::InvTypeViewMODLimboSize, - RoF::invtype::InvTypeViewMODLimboSize, - RoF2::invtype::InvTypeViewMODLimboSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::invtype::InvTypeViewMODLimboSize, - SoF::invtype::InvTypeViewMODLimboSize, - SoD::invtype::InvTypeViewMODLimboSize, - UF::invtype::InvTypeViewMODLimboSize, - RoF::invtype::InvTypeViewMODLimboSize, - RoF2::invtype::InvTypeViewMODLimboSize - }, - { // local[TypeAltStorage] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeAltStorageSize, - SoF::invtype::InvTypeAltStorageSize, - SoD::invtype::InvTypeAltStorageSize, - UF::invtype::InvTypeAltStorageSize, - RoF::invtype::InvTypeAltStorageSize, - RoF2::invtype::InvTypeAltStorageSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeArchived] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeArchivedSize, - SoF::invtype::InvTypeArchivedSize, - SoD::invtype::InvTypeArchivedSize, - UF::invtype::InvTypeArchivedSize, - RoF::invtype::InvTypeArchivedSize, - RoF2::invtype::InvTypeArchivedSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeMail] - ClientUnknown::Null, - Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::invtype::InvTypeMailSize, - RoF2::invtype::InvTypeMailSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeGuildTrophyTribute] - ClientUnknown::Null, - Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::invtype::InvTypeGuildTrophyTributeSize, - RoF2::invtype::InvTypeGuildTrophyTributeSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeKrono] - ClientUnknown::Null, - Client62::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::invtype::InvTypeKronoSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }, - { // local[TypeOther] - ClientUnknown::Null, - Client62::Null, - Titanium::invtype::InvTypeOtherSize, - SoF::invtype::InvTypeOtherSize, - SoD::invtype::InvTypeOtherSize, - UF::invtype::InvTypeOtherSize, - RoF::invtype::InvTypeOtherSize, - RoF2::invtype::InvTypeOtherSize, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - } - }; + { // Unknown + ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, + ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, + ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, + ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, + ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, - if (inv_type < 0 || inv_type >= legacy::TypeCount) - return 0; + ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, - return local[inv_type][static_cast(versions::ValidateInventoryVersion(inventory_version))]; + ClientUnknown::False, ClientUnknown::False, ClientUnknown::False, ClientUnknown::False + }, + { // Client62 + Client62::Null, Client62::Null, Client62::Null, Client62::Null, Client62::Null, + Client62::Null, Client62::Null, Client62::Null, Client62::Null, Client62::Null, + Client62::Null, Client62::Null, Client62::Null, Client62::Null, Client62::Null, + Client62::Null, Client62::Null, Client62::Null, Client62::Null, Client62::Null, + Client62::Null, Client62::Null, Client62::Null, Client62::Null, Client62::Null, + + Client62::Null, Client62::Null, Client62::Null, + + Client62::False, Client62::False, Client62::False, Client62::False + }, + { // Titanium + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*Titanium::invtype::InvTypePossessionsSize,*/ Titanium::invtype::InvTypeBankSize, Titanium::invtype::InvTypeSharedBankSize, Titanium::invtype::InvTypeTradeSize, Titanium::invtype::InvTypeWorldSize, + Titanium::invtype::InvTypeLimboSize, Titanium::invtype::InvTypeTributeSize, Titanium::Null, Titanium::Null, /*Titanium::invtype::InvTypeGuildTributeSize,*/ Titanium::invtype::InvTypeMerchantSize, + Titanium::Null, Titanium::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*Titanium::invtype::InvTypeBazaarSize,*/ Titanium::invtype::InvTypeInspectSize, Titanium::Null, + Titanium::invtype::InvTypeViewMODPCSize, Titanium::invtype::InvTypeViewMODBankSize, Titanium::invtype::InvTypeViewMODSharedBankSize, Titanium::invtype::InvTypeViewMODLimboSize, Titanium::invtype::InvTypeAltStorageSize, + Titanium::invtype::InvTypeArchivedSize, Titanium::Null, Titanium::Null, Titanium::Null, Titanium::invtype::InvTypeOtherSize, + + Titanium::Null, /*0x000000027FDFFFFF,*/ EQEmu::legacy::ITEM_CONTAINER_SIZE, /*Titanium::invbag::ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*Titanium::invaug::ItemAugSize,*/ + + Titanium::inventory::AllowEmptyBagInBag, Titanium::inventory::AllowClickCastFromBag, Titanium::inventory::ConcatenateInvTypeLimbo, Titanium::inventory::AllowOverLevelEquipment + }, + { // SoF + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*SoF::invtype::InvTypePossessionsSize,*/ SoF::invtype::InvTypeBankSize, SoF::invtype::InvTypeSharedBankSize, SoF::invtype::InvTypeTradeSize, SoF::invtype::InvTypeWorldSize, + SoF::invtype::InvTypeLimboSize, SoF::invtype::InvTypeTributeSize, SoF::Null, SoF::Null, /*SoF::invtype::InvTypeGuildTributeSize,*/ SoF::invtype::InvTypeMerchantSize, + SoF::Null, SoF::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*SoF::invtype::InvTypeBazaarSize,*/ SoF::invtype::InvTypeInspectSize, SoF::Null, + SoF::invtype::InvTypeViewMODPCSize, SoF::invtype::InvTypeViewMODBankSize, SoF::invtype::InvTypeViewMODSharedBankSize, SoF::invtype::InvTypeViewMODLimboSize, SoF::invtype::InvTypeAltStorageSize, + SoF::invtype::InvTypeArchivedSize, SoF::Null, SoF::Null, SoF::Null, SoF::invtype::InvTypeOtherSize, + + SoF::Null, /*0x000000027FFFFFFF,*/ EQEmu::legacy::ITEM_CONTAINER_SIZE, /*SoF::invbag::ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*SoF::invaug::ItemAugSize,*/ + + SoF::inventory::AllowEmptyBagInBag, SoF::inventory::AllowClickCastFromBag, SoF::inventory::ConcatenateInvTypeLimbo, SoF::inventory::AllowOverLevelEquipment + }, + { // SoD + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*SoD::invtype::InvTypePossessionsSize,*/ SoD::invtype::InvTypeBankSize, SoD::invtype::InvTypeSharedBankSize, SoD::invtype::InvTypeTradeSize, SoD::invtype::InvTypeWorldSize, + SoD::invtype::InvTypeLimboSize, SoD::invtype::InvTypeTributeSize, SoD::Null, SoD::Null, /*SoD::invtype::InvTypeGuildTributeSize,*/ SoD::invtype::InvTypeMerchantSize, + SoD::Null, SoD::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*SoD::invtype::InvTypeBazaarSize,*/ SoD::invtype::InvTypeInspectSize, SoD::Null, + SoD::invtype::InvTypeViewMODPCSize, SoD::invtype::InvTypeViewMODBankSize, SoD::invtype::InvTypeViewMODSharedBankSize, SoD::invtype::InvTypeViewMODLimboSize, SoD::invtype::InvTypeAltStorageSize, + SoD::invtype::InvTypeArchivedSize, SoD::Null, SoD::Null, SoD::Null, SoD::invtype::InvTypeOtherSize, + + SoD::Null, /*0x000000027FFFFFFF,*/ EQEmu::legacy::ITEM_CONTAINER_SIZE, /*SoD::invbag::ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*SoD::invaug::ItemAugSize,*/ + + SoD::inventory::AllowEmptyBagInBag, SoD::inventory::AllowClickCastFromBag, SoD::inventory::ConcatenateInvTypeLimbo, SoD::inventory::AllowOverLevelEquipment + }, + { // UF + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*UF::invtype::InvTypePossessionsSize,*/ UF::invtype::InvTypeBankSize, UF::invtype::InvTypeSharedBankSize, UF::invtype::InvTypeTradeSize, UF::invtype::InvTypeWorldSize, + UF::invtype::InvTypeLimboSize, UF::invtype::InvTypeTributeSize, UF::Null, UF::Null, /*UF::invtype::InvTypeGuildTributeSize,*/ UF::invtype::InvTypeMerchantSize, + UF::Null, UF::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*UF::invtype::InvTypeBazaarSize,*/ UF::invtype::InvTypeInspectSize, UF::Null, + UF::invtype::InvTypeViewMODPCSize, UF::invtype::InvTypeViewMODBankSize, UF::invtype::InvTypeViewMODSharedBankSize, UF::invtype::InvTypeViewMODLimboSize, UF::invtype::InvTypeAltStorageSize, + UF::invtype::InvTypeArchivedSize, UF::Null, UF::Null, UF::Null, UF::invtype::InvTypeOtherSize, + + UF::Null, /*0x000000027FFFFFFF,*/ EQEmu::legacy::ITEM_CONTAINER_SIZE, /*UF::invbag::ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*UF::invaug::ItemAugSize,*/ + + UF::inventory::AllowEmptyBagInBag, UF::inventory::AllowClickCastFromBag, UF::inventory::ConcatenateInvTypeLimbo, UF::inventory::AllowOverLevelEquipment + }, + { // RoF + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*RoF::invtype::InvTypePossessionsSize,*/ RoF::invtype::InvTypeBankSize, RoF::invtype::InvTypeSharedBankSize, RoF::invtype::InvTypeTradeSize, RoF::invtype::InvTypeWorldSize, + RoF::invtype::InvTypeLimboSize, RoF::invtype::InvTypeTributeSize, RoF::Null, /*RoF::invtype::InvTypeTrophyTributeSize,*/ RoF::Null, /*RoF::invtype::InvTypeGuildTributeSize,*/ RoF::invtype::InvTypeMerchantSize, + RoF::Null, /*RoF::invtype::InvTypeDeletedSize,*/ RoF::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*RoF::invtype::InvTypeBazaarSize,*/ RoF::invtype::InvTypeInspectSize, RoF::Null, /*RoF::invtype::InvTypeRealEstateSize,*/ + RoF::invtype::InvTypeViewMODPCSize, RoF::invtype::InvTypeViewMODBankSize, RoF::invtype::InvTypeViewMODSharedBankSize, RoF::invtype::InvTypeViewMODLimboSize, RoF::invtype::InvTypeAltStorageSize, + RoF::invtype::InvTypeArchivedSize, RoF::invtype::InvTypeMailSize, RoF::invtype::InvTypeGuildTrophyTributeSize, RoF::Null, RoF::invtype::InvTypeOtherSize, + + RoF::Null, /*0x00000003FFFFFFFF,*/ EQEmu::legacy::ITEM_CONTAINER_SIZE, /*RoF::invbag::ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*RoF::invaug::ItemAugSize,*/ + + RoF::False, /*RoF::inventory::AllowEmptyBagInBag,*/ RoF::inventory::AllowClickCastFromBag, RoF::inventory::ConcatenateInvTypeLimbo, RoF::inventory::AllowOverLevelEquipment + }, + { // RoF2 + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*RoF2::invtype::InvTypePossessionsSize,*/ RoF2::invtype::InvTypeBankSize, RoF2::invtype::InvTypeSharedBankSize, RoF2::invtype::InvTypeTradeSize, RoF2::invtype::InvTypeWorldSize, + RoF2::invtype::InvTypeLimboSize, RoF2::invtype::InvTypeTributeSize, RoF2::Null, /*RoF2::invtype::InvTypeTrophyTributeSize,*/ RoF2::Null, /*RoF2::invtype::InvTypeGuildTributeSize,*/ RoF2::invtype::InvTypeMerchantSize, + RoF2::Null, /*RoF2::invtype::InvTypeDeletedSize,*/ RoF2::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*RoF2::invtype::InvTypeBazaarSize,*/ RoF2::invtype::InvTypeInspectSize, RoF2::Null, /*RoF2::invtype::InvTypeRealEstateSize*/ + RoF2::invtype::InvTypeViewMODPCSize, RoF2::invtype::InvTypeViewMODBankSize, RoF2::invtype::InvTypeViewMODSharedBankSize, RoF2::invtype::InvTypeViewMODLimboSize, RoF2::invtype::InvTypeAltStorageSize, + RoF2::invtype::InvTypeArchivedSize, RoF2::invtype::InvTypeMailSize, RoF2::invtype::InvTypeGuildTrophyTributeSize, RoF2::invtype::InvTypeKronoSize, RoF2::invtype::InvTypeOtherSize, + + RoF2::Null, /*0x00000003FFFFFFFF,*/ EQEmu::legacy::ITEM_CONTAINER_SIZE, /*RoF2::invbag::ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*RoF2::invaug::ItemAugSize,*/ + + RoF2::False, /*RoF2::inventory::AllowEmptyBagInBag,*/ RoF2::inventory::AllowClickCastFromBag, RoF2::inventory::ConcatenateInvTypeLimbo, RoF2::inventory::AllowOverLevelEquipment + }, + { // NPC + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::InvTypeTradeSize, EntityLimits::NPC::Null, + EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, + EntityLimits::NPC::Null, EntityLimits::NPC::Null, /*InvTypeCorpseSize,*/ EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, + EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, + EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, + + EntityLimits::NPC::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*ItemAugSize,*/ + + EntityLimits::NPC::False, EntityLimits::NPC::False, EntityLimits::NPC::False, EntityLimits::NPC::False + }, + { // NPCMerchant + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::InvTypeTradeSize, EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, /*InvTypeCorpseSize,*/ EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, + + EntityLimits::NPCMerchant::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*ItemAugSize,*/ + + EntityLimits::NPCMerchant::False, EntityLimits::NPCMerchant::False, EntityLimits::NPCMerchant::False, EntityLimits::NPCMerchant::False + }, + { // Merc + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::InvTypeTradeSize, EntityLimits::Merc::Null, + EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, + EntityLimits::Merc::Null, EntityLimits::Merc::Null, /*InvTypeCorpseSize,*/ EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, + EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, + EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, + + EntityLimits::Merc::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*ItemAugSize,*/ + + EntityLimits::Merc::False, EntityLimits::Merc::False, EntityLimits::Merc::False, EntityLimits::Merc::False + }, + { // Bot + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::InvTypeTradeSize, EntityLimits::Bot::Null, + EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, + EntityLimits::Bot::Null, EntityLimits::Bot::Null, /*InvTypeCorpseSize,*/ EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, + EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, + EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, + + EntityLimits::Bot::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*ItemAugSize,*/ + + EntityLimits::Bot::False, EntityLimits::Bot::False, EntityLimits::Bot::False, EntityLimits::Bot::False + }, + { // ClientPet + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::InvTypeTradeSize, EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, /*InvTypeCorpseSize,*/ EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, + + EntityLimits::ClientPet::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*ItemAugSize,*/ + + EntityLimits::ClientPet::False, EntityLimits::ClientPet::False, EntityLimits::ClientPet::False, EntityLimits::ClientPet::False + }, + { // NPCPet + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::InvTypeTradeSize, EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, /*InvTypeCorpseSize,*/ EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, + + EntityLimits::NPCPet::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*ItemAugSize,*/ + + EntityLimits::NPCPet::False, EntityLimits::NPCPet::False, EntityLimits::NPCPet::False, EntityLimits::NPCPet::False + }, + { // MercPet + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::InvTypeTradeSize, EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, /*InvTypeCorpseSize,*/ EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, + + EntityLimits::MercPet::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*ItemAugSize,*/ + + EntityLimits::MercPet::False, EntityLimits::MercPet::False, EntityLimits::MercPet::False, EntityLimits::MercPet::False + }, + { // BotPet + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::InvTypeTradeSize, EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, /*InvTypeCorpseSize,*/ EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, + + EntityLimits::BotPet::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*ItemBagSize,*/ EQEmu::legacy::ITEM_COMMON_SIZE, /*ItemAugSize,*/ + + EntityLimits::BotPet::False, EntityLimits::BotPet::False, EntityLimits::BotPet::False, EntityLimits::BotPet::False + }, + { // OfflineTitanium + Titanium::Null, Titanium::Null, Titanium::Null, Titanium::invtype::InvTypeTradeSize, Titanium::Null, + Titanium::Null, Titanium::Null, Titanium::Null, Titanium::Null, Titanium::invtype::InvTypeMerchantSize, + Titanium::Null, Titanium::Null, Titanium::Null, /*Titanium::invtype::InvTypeBazaarSize,*/ Titanium::invtype::InvTypeInspectSize, Titanium::Null, + Titanium::invtype::InvTypeViewMODPCSize, Titanium::invtype::InvTypeViewMODBankSize, Titanium::invtype::InvTypeViewMODSharedBankSize, Titanium::invtype::InvTypeViewMODLimboSize, Titanium::Null, + Titanium::Null, Titanium::Null, Titanium::Null, Titanium::Null, Titanium::Null, + + Titanium::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*Titanium::Null,*/ Titanium::Null, + + Titanium::False, Titanium::False, Titanium::False, Titanium::False + }, + { // OfflineSoF + SoF::Null, SoF::Null, SoF::Null, SoF::invtype::InvTypeTradeSize, SoF::Null, + SoF::Null, SoF::Null, SoF::Null, SoF::Null, SoF::invtype::InvTypeMerchantSize, + SoF::Null, SoF::Null, SoF::Null, /*SoF::invtype::InvTypeBazaarSize,*/ SoF::invtype::InvTypeInspectSize, SoF::Null, + SoF::invtype::InvTypeViewMODPCSize, SoF::invtype::InvTypeViewMODBankSize, SoF::invtype::InvTypeViewMODSharedBankSize, SoF::invtype::InvTypeViewMODLimboSize, SoF::Null, + SoF::Null, SoF::Null, SoF::Null, SoF::Null, SoF::Null, + + SoF::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*SoF::Null,*/ SoF::Null, + + SoF::False, SoF::False, SoF::False, SoF::False + }, + { // OfflineSoD + SoD::Null, SoD::Null, SoD::Null, SoD::invtype::InvTypeTradeSize, SoD::Null, + SoD::Null, SoD::Null, SoD::Null, SoD::Null, SoD::invtype::InvTypeMerchantSize, + SoD::Null, SoD::Null, SoD::Null, /*SoD::invtype::InvTypeBazaarSize,*/ SoD::invtype::InvTypeInspectSize, SoD::Null, + SoD::invtype::InvTypeViewMODPCSize, SoD::invtype::InvTypeViewMODBankSize, SoD::invtype::InvTypeViewMODSharedBankSize, SoD::invtype::InvTypeViewMODLimboSize, SoD::Null, + SoD::Null, SoD::Null, SoD::Null, SoD::Null, SoD::Null, + + SoD::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*SoD::Null,*/ SoD::Null, + + SoD::False, SoD::False, SoD::False, SoD::False + }, + { // OfflineUF + UF::Null, UF::Null, UF::Null, UF::invtype::InvTypeTradeSize, UF::Null, + UF::Null, UF::Null, UF::Null, UF::Null, UF::invtype::InvTypeMerchantSize, + UF::Null, UF::Null, UF::Null, /*UF::invtype::InvTypeBazaarSize,*/ UF::invtype::InvTypeInspectSize, UF::Null, + UF::invtype::InvTypeViewMODPCSize, UF::invtype::InvTypeViewMODBankSize, UF::invtype::InvTypeViewMODSharedBankSize, UF::invtype::InvTypeViewMODLimboSize, UF::Null, + UF::Null, UF::Null, UF::Null, UF::Null, UF::Null, + + UF::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*UF::Null,*/ UF::Null, + + UF::False, UF::False, UF::False, UF::False + }, + { // OfflineRoF + RoF::Null, RoF::Null, RoF::Null, RoF::invtype::InvTypeTradeSize, RoF::Null, + RoF::Null, RoF::Null, RoF::Null, RoF::Null, RoF::invtype::InvTypeMerchantSize, + RoF::Null, RoF::Null, RoF::Null, /*RoF::invtype::InvTypeBazaarSize,*/ RoF::invtype::InvTypeInspectSize, RoF::Null, + RoF::invtype::InvTypeViewMODPCSize, RoF::invtype::InvTypeViewMODBankSize, RoF::invtype::InvTypeViewMODSharedBankSize, RoF::invtype::InvTypeViewMODLimboSize, RoF::Null, + RoF::Null, RoF::Null, RoF::Null, RoF::Null, RoF::Null, + + RoF::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*RoF::Null,*/ RoF::Null, + + RoF::False, RoF::False, RoF::False, RoF::False + }, + { // OfflineRoF2 + RoF2::Null, RoF2::Null, RoF2::Null, RoF2::invtype::InvTypeTradeSize, RoF2::Null, + RoF2::Null, RoF2::Null, RoF2::Null, RoF2::Null, RoF2::invtype::InvTypeMerchantSize, + RoF2::Null, RoF2::Null, RoF2::Null, /*RoF2::invtype::InvTypeBazaarSize,*/ RoF2::invtype::InvTypeInspectSize, RoF2::Null, + RoF2::invtype::InvTypeViewMODPCSize, RoF2::invtype::InvTypeViewMODBankSize, RoF2::invtype::InvTypeViewMODSharedBankSize, RoF2::invtype::InvTypeViewMODLimboSize, RoF2::Null, + RoF2::Null, RoF2::Null, RoF2::Null, RoF2::Null, RoF2::Null, + + RoF2::Null, EQEmu::legacy::ITEM_CONTAINER_SIZE, /*RoF2::Null,*/ RoF2::Null, + + RoF2::False, RoF2::False, RoF2::False, RoF2::False + } +}; + +const EQEmu::inventory::LookupEntry* EQEmu::inventory::Lookup(versions::InventoryVersion inventory_version) +{ + return &inventory_lookup_entries[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } -uint64 EQEmu::inventory::GetPossessionsBitmask(versions::InventoryVersion inventory_version) +static const EQEmu::behavior::LookupEntry behavior_lookup_entries[EQEmu::versions::InventoryVersionCount] = { - static const uint64 local[versions::InventoryVersionCount] = { - ClientUnknown::Null, - Client62::Null, - Titanium::Null, //0x000000027FDFFFFF, - SoF::Null, //0x000000027FFFFFFF, - SoD::Null, //0x000000027FFFFFFF, - UF::Null, //0x000000027FFFFFFF, - RoF::Null, //0x00000003FFFFFFFF, - RoF2::Null, //0x00000003FFFFFFFF, - EntityLimits::NPC::Null, - EntityLimits::Merc::Null, - EntityLimits::Bot::Null, - EntityLimits::ClientPet::Null, - EntityLimits::NPCPet::Null, - EntityLimits::MercPet::Null, - EntityLimits::BotPet::Null, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }; - - return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; -} - -bool EQEmu::inventory::GetAllowEmptyBagInBag(versions::InventoryVersion inventory_version) -{ - static const bool local[versions::InventoryVersionCount] = { - ClientUnknown::False, - Client62::False, - Titanium::inventory::AllowEmptyBagInBag, - SoF::inventory::AllowEmptyBagInBag, - SoD::inventory::AllowEmptyBagInBag, - UF::inventory::AllowEmptyBagInBag, - RoF::False, //RoF::inventory::AllowEmptyBagInBag, - RoF2::False, //RoF2::inventory::AllowEmptyBagInBag, - EntityLimits::NPC::False, - EntityLimits::Merc::False, - EntityLimits::Bot::False, - EntityLimits::ClientPet::False, - EntityLimits::NPCPet::False, - EntityLimits::MercPet::False, - EntityLimits::BotPet::False, - Titanium::False, - SoF::False, - SoD::False, - UF::False, - RoF::False, + { // Unknown + ClientUnknown::True + }, + { // Client62 + Client62::True + }, + { // Titanium + Titanium::behavior::CoinHasWeight + }, + { // SoF + SoF::behavior::CoinHasWeight + }, + { // SoD + SoD::behavior::CoinHasWeight + }, + { // UF + UF::behavior::CoinHasWeight + }, + { // RoF + RoF::behavior::CoinHasWeight + }, + { // RoF2 + RoF2::behavior::CoinHasWeight + }, + { // NPC + EntityLimits::NPC::True /*CoinHasWeight*/ + }, + { // NPCMerchant + EntityLimits::NPC::True /*CoinHasWeight*/ + }, + { // Merc + EntityLimits::Merc::True /*CoinHasWeight*/ + }, + { // Bot + EntityLimits::Bot::True /*CoinHasWeight*/ + }, + { // ClientPet + EntityLimits::ClientPet::True /*CoinHasWeight*/ + }, + { // NPCPet + EntityLimits::NPCPet::True /*CoinHasWeight*/ + }, + { // MercPet + EntityLimits::MercPet::True /*CoinHasWeight*/ + }, + { // BotPet + EntityLimits::BotPet::True /*CoinHasWeight*/ + }, + { // OfflineTitanium + Titanium::False + }, + { // OfflineSoF + SoF::False + }, + { // OfflineSoD + SoD::False + }, + { // OfflineUF + UF::False + }, + { // OfflineRoF + RoF::False + }, + { // OfflineRoF2 RoF2::False - }; + } +}; - return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; -} - -bool EQEmu::inventory::GetAllowClickCastFromBag(versions::InventoryVersion inventory_version) +const EQEmu::behavior::LookupEntry* EQEmu::behavior::Lookup(versions::InventoryVersion inventory_version) { - static const bool local[versions::InventoryVersionCount] = { - ClientUnknown::False, - Client62::False, - Titanium::inventory::AllowClickCastFromBag, - SoF::inventory::AllowClickCastFromBag, - SoD::inventory::AllowClickCastFromBag, - UF::inventory::AllowClickCastFromBag, - RoF::inventory::AllowClickCastFromBag, - RoF2::inventory::AllowClickCastFromBag, - EntityLimits::NPC::False, - EntityLimits::Merc::False, - EntityLimits::Bot::False, - EntityLimits::ClientPet::False, - EntityLimits::NPCPet::False, - EntityLimits::MercPet::False, - EntityLimits::BotPet::False, - Titanium::False, - SoF::False, - SoD::False, - UF::False, - RoF::False, - RoF2::False - }; - - return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; -} - -bool EQEmu::inventory::GetConcatenateInvTypeLimbo(versions::InventoryVersion inventory_version) -{ - static const bool local[versions::InventoryVersionCount] = { - ClientUnknown::False, - Client62::False, - Titanium::inventory::ConcatenateInvTypeLimbo, - SoF::inventory::ConcatenateInvTypeLimbo, - SoD::inventory::ConcatenateInvTypeLimbo, - UF::inventory::ConcatenateInvTypeLimbo, - RoF::inventory::ConcatenateInvTypeLimbo, - RoF2::inventory::ConcatenateInvTypeLimbo, - EntityLimits::NPC::False, - EntityLimits::Merc::False, - EntityLimits::Bot::False, - EntityLimits::ClientPet::False, - EntityLimits::NPCPet::False, - EntityLimits::MercPet::False, - EntityLimits::BotPet::False, - Titanium::False, - SoF::False, - SoD::False, - UF::False, - RoF::False, - RoF2::False - }; - - return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; -} - -bool EQEmu::inventory::GetAllowOverLevelEquipment(versions::InventoryVersion inventory_version) -{ - static const bool local[versions::InventoryVersionCount] = { - ClientUnknown::False, - Client62::False, - Titanium::inventory::AllowOverLevelEquipment, - SoF::inventory::AllowOverLevelEquipment, - SoD::inventory::AllowOverLevelEquipment, - UF::inventory::AllowOverLevelEquipment, - RoF::inventory::AllowOverLevelEquipment, - RoF2::inventory::AllowOverLevelEquipment, - EntityLimits::NPC::False, - EntityLimits::Merc::False, - EntityLimits::Bot::False, - EntityLimits::ClientPet::False, - EntityLimits::NPCPet::False, - EntityLimits::MercPet::False, - EntityLimits::BotPet::False, - Titanium::False, - SoF::False, - SoD::False, - UF::False, - RoF::False, - RoF2::False - }; - - return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; -} - -size_t EQEmu::inventory::GetItemAugSize(versions::InventoryVersion inventory_version) -{ - static const size_t local[versions::InventoryVersionCount] = { - ClientUnknown::Null, - Client62::Null, - legacy::ITEM_COMMON_SIZE, //Titanium::invaug::ItemAugSize, - legacy::ITEM_COMMON_SIZE, //SoF::invaug::ItemAugSize, - legacy::ITEM_COMMON_SIZE, //SoD::invaug::ItemAugSize, - legacy::ITEM_COMMON_SIZE, //UF::invaug::ItemAugSize, - legacy::ITEM_COMMON_SIZE, //RoF::invaug::ItemAugSize, - legacy::ITEM_COMMON_SIZE, //RoF2::invaug::ItemAugSize, - legacy::ITEM_COMMON_SIZE, //ItemAugSize, - legacy::ITEM_COMMON_SIZE, //ItemAugSize, - legacy::ITEM_COMMON_SIZE, //ItemAugSize, - legacy::ITEM_COMMON_SIZE, //ItemAugSize, - legacy::ITEM_COMMON_SIZE, //ItemAugSize, - legacy::ITEM_COMMON_SIZE, //ItemAugSize, - legacy::ITEM_COMMON_SIZE, //ItemAugSize, - Titanium::Null, - SoF::Null, - SoD::Null, - UF::Null, - RoF::Null, - RoF2::Null - }; - - return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; -} - -size_t EQEmu::inventory::GetItemBagSize(versions::InventoryVersion inventory_version) -{ - static const size_t local[versions::InventoryVersionCount] = { - ClientUnknown::Null, - Client62::Null, - legacy::ITEM_CONTAINER_SIZE, //Titanium::invbag::ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //SoF::invbag::ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //SoD::invbag::ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //UF::invbag::ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //RoF::invbag::ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //RoF2::invbag::ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //ItemBagSize, - legacy::ITEM_CONTAINER_SIZE, //Titanium::Null, - legacy::ITEM_CONTAINER_SIZE, //SoF::Null, - legacy::ITEM_CONTAINER_SIZE, //SoD::Null, - legacy::ITEM_CONTAINER_SIZE, //UF::Null, - legacy::ITEM_CONTAINER_SIZE, //RoF::Null, - legacy::ITEM_CONTAINER_SIZE, //RoF2::Null - }; - - return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; -} - -bool EQEmu::behavior::GetCoinHasWeight(versions::InventoryVersion inventory_version) -{ - static const bool local[versions::InventoryVersionCount] = { - ClientUnknown::True, - Client62::True, - Titanium::behavior::CoinHasWeight, - SoF::behavior::CoinHasWeight, - SoD::behavior::CoinHasWeight, - UF::behavior::CoinHasWeight, - RoF::behavior::CoinHasWeight, - RoF::behavior::CoinHasWeight, - EntityLimits::NPC::True, //CoinHasWeight, - EntityLimits::Merc::True, //CoinHasWeight, - EntityLimits::Bot::True, //CoinHasWeight, - EntityLimits::ClientPet::True, //CoinHasWeight, - EntityLimits::NPCPet::True, //CoinHasWeight, - EntityLimits::MercPet::True, //CoinHasWeight, - EntityLimits::BotPet::True, //CoinHasWeight, - Titanium::False, - SoF::False, - SoD::False, - UF::False, - RoF::False, - RoF2::False - }; - - return local[static_cast(versions::ValidateInventoryVersion(inventory_version))]; + return &behavior_lookup_entries[static_cast(versions::ValidateInventoryVersion(inventory_version))]; } diff --git a/common/eq_limits.h b/common/eq_limits.h index d843474ec..82539f2b1 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -20,6 +20,7 @@ #ifndef COMMON_EQ_LIMITS_H #define COMMON_EQ_LIMITS_H +#include "emu_legacy.h" #include "types.h" #include "eq_constants.h" #include "emu_versions.h" @@ -34,28 +35,41 @@ namespace EQEmu { namespace constants { - extern size_t GetCharacterCreationLimit(versions::ClientVersion client_version); + class LookupEntry { + public: + size_t CharacterCreationLimit; + }; + + const LookupEntry* Lookup(versions::ClientVersion client_version); } /*constants*/ namespace inventory { - extern size_t GetInventoryTypeSize(versions::InventoryVersion inventory_version, int inv_type); - extern uint64 GetPossessionsBitmask(versions::InventoryVersion inventory_version); + class LookupEntry { + public: + size_t InventoryTypeSize[legacy::TypeCount]; - extern bool GetAllowEmptyBagInBag(versions::InventoryVersion inventory_version); - extern bool GetAllowClickCastFromBag(versions::InventoryVersion inventory_version); + uint64 PossessionsBitmask; + size_t ItemBagSize; + size_t ItemAugSize; - extern bool GetConcatenateInvTypeLimbo(versions::InventoryVersion inventory_version); + bool AllowEmptyBagInBag; + bool AllowClickCastFromBag; + bool ConcatenateInvTypeLimbo; + bool AllowOverLevelEquipment; + }; - extern bool GetAllowOverLevelEquipment(versions::InventoryVersion inventory_version); - - extern size_t GetItemAugSize(versions::InventoryVersion inventory_version); - extern size_t GetItemBagSize(versions::InventoryVersion inventory_version); + const LookupEntry* Lookup(versions::InventoryVersion inventory_version); } /*inventory*/ namespace behavior { - extern bool GetCoinHasWeight(versions::InventoryVersion inventory_version); + class LookupEntry { + public: + bool CoinHasWeight; + }; + + const LookupEntry* Lookup(versions::InventoryVersion inventory_version); } /*behavior*/ diff --git a/common/item.cpp b/common/item.cpp index ae0de2795..41e3d86c3 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -929,7 +929,7 @@ bool Inventory::SupportsClickCasting(int16 slot_id) } else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { - if (EQEmu::inventory::GetAllowClickCastFromBag(m_inventory_version)) + if (EQEmu::inventory::Lookup(m_inventory_version)->AllowClickCastFromBag) return true; } diff --git a/world/client.cpp b/world/client.cpp index 1fc2a93f8..5b94846be 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -211,7 +211,7 @@ void Client::SendMaxCharCreate() { auto outapp = new EQApplicationPacket(OP_SendMaxCharacters, sizeof(MaxCharacters_Struct)); MaxCharacters_Struct* mc = (MaxCharacters_Struct*)outapp->pBuffer; - mc->max_chars = EQEmu::constants::GetCharacterCreationLimit(m_ClientVersion); + mc->max_chars = EQEmu::constants::Lookup(m_ClientVersion)->CharacterCreationLimit; if (mc->max_chars > EQEmu::constants::CharacterCreationMax) mc->max_chars = EQEmu::constants::CharacterCreationMax; @@ -746,7 +746,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { // This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above) // (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration) if (!pZoning) { - size_t character_limit = EQEmu::constants::GetCharacterCreationLimit(eqs->ClientVersion()); + size_t character_limit = EQEmu::constants::Lookup(eqs->ClientVersion())->CharacterCreationLimit; if (character_limit > EQEmu::constants::CharacterCreationMax) { character_limit = EQEmu::constants::CharacterCreationMax; } if (eqs->ClientVersion() == EQEmu::versions::ClientVersion::Titanium) { character_limit = 8; } diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 0eaa474a0..8d65f7a78 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -37,7 +37,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou { /* Set Character Creation Limit */ EQEmu::versions::ClientVersion client_version = EQEmu::versions::ConvertClientVersionBitToClientVersion(clientVersionBit); - size_t character_limit = EQEmu::constants::GetCharacterCreationLimit(client_version); + size_t character_limit = EQEmu::constants::Lookup(client_version)->CharacterCreationLimit; // Validate against absolute server max if (character_limit > EQEmu::constants::CharacterCreationMax) diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 266f5540b..804e8df62 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1355,7 +1355,7 @@ uint32 Client::CalcCurrentWeight() This is the ONLY instance I have seen where the client is hard coded to particular Item IDs to set a certain property for an item. It is very odd. */ // SoD+ client has no weight for coin - if (EQEmu::behavior::GetCoinHasWeight(EQEmu::versions::ConvertClientVersionToInventoryVersion(ClientVersion()))) { + if (EQEmu::behavior::Lookup(EQEmu::versions::ConvertClientVersionToInventoryVersion(ClientVersion()))->CoinHasWeight) { Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4; } float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat; diff --git a/zone/corpse.cpp b/zone/corpse.cpp index ef948350a..0fc02a2ac 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -992,7 +992,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::inventory::GetInventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()), EQEmu::legacy::TypeCorpse); + int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()))->InventoryTypeSize[EQEmu::legacy::TypeCorpse]; for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; @@ -1286,7 +1286,7 @@ void Corpse::QueryLoot(Client* to) { cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::inventory::GetInventoryTypeSize(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()), EQEmu::legacy::TypeCorpse); + int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()))->InventoryTypeSize[EQEmu::legacy::TypeCorpse]; for(; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; From c1a6a23e06a8c90b015cb4e8a45fa20259ac4dc4 Mon Sep 17 00:00:00 2001 From: Drajor Date: Sat, 11 Jun 2016 12:48:16 +1000 Subject: [PATCH 152/693] Fixes #527 --- zone/client_packet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 69f0781af..e661d3022 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2188,7 +2188,7 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app) return; } - int32 price = item->LDoNPrice * 70 / 100; + int32 price = ceil((float)item->LDoNPrice * item->LDoNSellBackRate / 100); if (price == 0) { From 1b6974ade3b4beab1ae3c052ac5e9f5fcb6b653e Mon Sep 17 00:00:00 2001 From: Drajor Date: Sat, 11 Jun 2016 13:29:56 +1000 Subject: [PATCH 153/693] Alternate currency sell price now matches RoF2 client calculation --- zone/client_packet.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e661d3022..e0de70add 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2188,7 +2188,8 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app) return; } - int32 price = ceil((float)item->LDoNPrice * item->LDoNSellBackRate / 100); + // 06/11/2016 This formula matches RoF2 client side calculation. + int32 price = (item->LDoNPrice + 1) * item->LDoNSellBackRate / 100; if (price == 0) { From 73e91be2817dd917d202c838e79cb678b0717514 Mon Sep 17 00:00:00 2001 From: Drajor Date: Sat, 11 Jun 2016 19:53:19 +1000 Subject: [PATCH 154/693] Fixed vulnerability in handling of OP_CrystalCreate --- zone/client_packet.cpp | 71 ++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e0de70add..7f77a2eb9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5004,38 +5004,49 @@ void Client::Handle_OP_CrystalCreate(const EQApplicationPacket *app) VERIFY_PACKET_LENGTH(OP_CrystalCreate, app, CrystalReclaim_Struct); CrystalReclaim_Struct *cr = (CrystalReclaim_Struct*)app->pBuffer; - if (cr->type == 5) { - if (cr->amount > GetEbonCrystals()) { - SummonItem(RuleI(Zone, EbonCrystalItemID), GetEbonCrystals()); - m_pp.currentEbonCrystals = 0; - m_pp.careerEbonCrystals = 0; - SaveCurrency(); - SendCrystalCounts(); - } - else { - SummonItem(RuleI(Zone, EbonCrystalItemID), cr->amount); - m_pp.currentEbonCrystals -= cr->amount; - m_pp.careerEbonCrystals -= cr->amount; - SaveCurrency(); - SendCrystalCounts(); - } + const uint32 requestQty = cr->amount; + const bool isRadiant = cr->type == 4; + const bool isEbon = cr->type == 5; + + // Check: Valid type requested. + if (!isRadiant && !isEbon) { + return; } - else if (cr->type == 4) { - if (cr->amount > GetRadiantCrystals()) { - SummonItem(RuleI(Zone, RadiantCrystalItemID), GetRadiantCrystals()); - m_pp.currentRadCrystals = 0; - m_pp.careerRadCrystals = 0; - SaveCurrency(); - SendCrystalCounts(); - } - else { - SummonItem(RuleI(Zone, RadiantCrystalItemID), cr->amount); - m_pp.currentRadCrystals -= cr->amount; - m_pp.careerRadCrystals -= cr->amount; - SaveCurrency(); - SendCrystalCounts(); - } + // Check: Valid quantity requested. + if (requestQty < 1) { + return; } + + // Check: Valid client state to make request. + // In this situation the client is either desynced or attempting an exploit. + const uint32 currentQty = isRadiant ? GetRadiantCrystals() : GetEbonCrystals(); + if (currentQty == 0) { + return; + } + + // Prevent the client from creating more than they have. + const uint32 amount = EQEmu::ClampUpper(requestQty, currentQty); + const uint32 itemID = isRadiant ? RuleI(Zone, RadiantCrystalItemID) : RuleI(Zone, EbonCrystalItemID); + + // Summon crystals for player. + const bool success = SummonItem(itemID, amount); + + if (!success) { + return; + } + + // Deduct crystals from client and update them. + if (isRadiant) { + m_pp.currentRadCrystals -= amount; + m_pp.careerRadCrystals -= amount; + } + else if (isEbon) { + m_pp.currentEbonCrystals -= amount; + m_pp.careerEbonCrystals -= amount; + } + + SaveCurrency(); + SendCrystalCounts(); } void Client::Handle_OP_CrystalReclaim(const EQApplicationPacket *app) From 3e25a3df5ceb9c5ec4cfc0fc52c8454e44e77bce Mon Sep 17 00:00:00 2001 From: Drajor Date: Sat, 11 Jun 2016 20:24:36 +1000 Subject: [PATCH 155/693] Implemented RoF2 encoder for OP_CrystalCountUpdate (0x467f) --- common/patches/rof2.cpp | 13 +++++++++++++ common/patches/rof2_ops.h | 1 + common/patches/rof2_structs.h | 9 +++++++++ 3 files changed, 23 insertions(+) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 30941a1bf..114238d83 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4389,6 +4389,19 @@ namespace RoF2 delete in; } + ENCODE(OP_CrystalCountUpdate) + { + ENCODE_LENGTH_EXACT(CrystalCountUpdate_Struct); + SETUP_DIRECT_ENCODE(CrystalCountUpdate_Struct, structs::CrystalCountUpdate_Struct); + + OUT(CurrentRadiantCrystals); + OUT(CareerRadiantCrystals); + OUT(CurrentEbonCrystals); + OUT(CareerEbonCrystals); + + FINISH_ENCODE(); + } + // DECODE methods DECODE(OP_AdventureMerchantSell) diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index b49784029..1ca7063f4 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -141,6 +141,7 @@ E(OP_ZoneEntry) E(OP_ZonePlayerToBind) E(OP_ZoneServerInfo) E(OP_ZoneSpawns) +E(OP_CrystalCountUpdate) // Begin RoF Decodes D(OP_AdventureMerchantSell) D(OP_AltCurrencySell) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index ed34d44b8..0b638660e 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -5081,6 +5081,15 @@ struct MercenaryMerchantResponse_Struct { /*0004*/ }; +// Sent by Server to update character crystals. +struct CrystalCountUpdate_Struct +{ + /*000*/ uint32 CurrentRadiantCrystals; + /*004*/ uint32 CareerRadiantCrystals; + /*008*/ uint32 CurrentEbonCrystals; + /*012*/ uint32 CareerEbonCrystals; +}; + }; /*structs*/ }; /*RoF2*/ From 83bb10b32b393cfddd7cc213ff9099ff1678637e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 11 Jun 2016 13:23:52 -0400 Subject: [PATCH 156/693] Add support for sub folder style lua modules Ex. lua_modules/?/init.lua will work (which some lua modules do use) --- zone/lua_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 4f88eb88a..95e98f6a6 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -852,7 +852,7 @@ void LuaParser::ReloadQuests() { lua_getglobal(L, "package"); lua_getfield(L, -1, "path"); std::string module_path = lua_tostring(L,-1); - module_path += ";./" + Config->LuaModuleDir + "/?.lua"; + module_path += ";./" + Config->LuaModuleDir + "?.lua;./" + Config->LuaModuleDir + "?/init.lua"; lua_pop(L, 1); lua_pushstring(L, module_path.c_str()); lua_setfield(L, -2, "path"); From 2b2ebc75b0fb9caad25c13d256d4319680927b53 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 11 Jun 2016 15:59:46 -0400 Subject: [PATCH 157/693] Add luarocks support This allows one to use the lua_modules folder as their luarocks tree ex (from the server folder with lua_modules using default location) luarocks --tree=lua_modules install luasql-mysql MYSQL_INCDIR=/usr/include This will install the luasql mysql module so you can now do queries from lua --- zone/lua_parser.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 95e98f6a6..ea23df73f 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -847,17 +847,49 @@ void LuaParser::ReloadQuests() { lua_pushnil(L); lua_setglobal(L, "loadfile"); +#endif + + // lua 5.2+ defines these +#if defined(LUA_VERSION_MAJOR) && defined(LUA_VERSION_MINOR) + const char lua_version[] = LUA_VERSION_MAJOR "." LUA_VERSION_MINOR; +#elif LUA_VERSION_NUM == 501 + const char lua_version[] = "5.1"; +#else +#error Incompatible lua version +#endif + +#ifdef WINDOWS + const char libext[] = ".dll"; +#else + // lua doesn't care OSX doesn't use sonames + const char libext[] = ".so"; #endif lua_getglobal(L, "package"); lua_getfield(L, -1, "path"); std::string module_path = lua_tostring(L,-1); module_path += ";./" + Config->LuaModuleDir + "?.lua;./" + Config->LuaModuleDir + "?/init.lua"; + // luarock paths using lua_modules as tree + // to path it adds foo/share/lua/5.1/?.lua and foo/share/lua/5.1/?/init.lua + module_path += ";./" + Config->LuaModuleDir + "share/lua/" + lua_version + "/?.lua"; + module_path += ";./" + Config->LuaModuleDir + "share/lua/" + lua_version + "/?/init.lua"; lua_pop(L, 1); lua_pushstring(L, module_path.c_str()); lua_setfield(L, -2, "path"); lua_pop(L, 1); + lua_getglobal(L, "package"); + lua_getfield(L, -1, "cpath"); + module_path = lua_tostring(L, -1); + module_path += ";./" + Config->LuaModuleDir + "?" + libext; + // luarock paths using lua_modules as tree + // luarocks adds foo/lib/lua/5.1/?.so for cpath + module_path += ";./" + Config->LuaModuleDir + "lib/lua/" + lua_version + "/?" + libext; + lua_pop(L, 1); + lua_pushstring(L, module_path.c_str()); + lua_setfield(L, -2, "cpath"); + lua_pop(L, 1); + MapFunctions(L); //load init From 306ecf003a4c1c62f80bc0b6010ead03c20055a7 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Mon, 13 Jun 2016 09:06:44 -0400 Subject: [PATCH 158/693] Spells like listless power and dread touch should be taking down/blocking spells like augmentation and strenthen respectively. The stacking code was being bypassed when a beneficial spell and a detrimental spell for the same effect were being compared. With this code removed, the spells are compared and the stonger of the two spells wins and replaces or blocks the other. Without this change, for example, dread touch takes down strengthen on the client, but the server still things strength is up, causing a mismatch. With this change, client/server match. --- zone/spells.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index a8fe41087..cb0d0f4d8 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2983,18 +2983,6 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, return (-1); } - /* - If the effects are the same and - sp1 = beneficial & sp2 = detrimental or - sp1 = detrimental & sp2 = beneficial - Then this effect should be ignored for stacking purposes. - */ - if(sp_det_mismatch) - { - Log.Out(Logs::Detail, Logs::Spells, "The effects are the same but the spell types are not, passing the effect"); - continue; - } - /* If the spells aren't the same and the effect is a dot we can go ahead and stack it From b10187f9de8ec9de883db54d212580cfa9610648 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Mon, 13 Jun 2016 14:04:23 -0400 Subject: [PATCH 159/693] Changed personal faction earned min/max values to -2000/2000. --- changelog.txt | 3 +++ common/features.h | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index f3dcd8117..005945fd1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 06/13/2016 == +Noudess: Changes personal faction earned min/max to -2000/2000 from -3000/1200 + == 06/06/2016 == Uleat: Reworked EQEmuDictionary to use class LookupEntry diff --git a/common/features.h b/common/features.h index 9ceddb31b..27390e745 100644 --- a/common/features.h +++ b/common/features.h @@ -213,8 +213,8 @@ enum { //some random constants #define MAX_NPC_FACTIONS 20 //individual faction pool -#define MAX_PERSONAL_FACTION 1200 -#define MIN_PERSONAL_FACTION -3000 +#define MAX_PERSONAL_FACTION 2000 +#define MIN_PERSONAL_FACTION -2000 //The Level Cap: //#define LEVEL_CAP RuleI(Character, MaxLevel) //hard cap is 127 From 3889da7301fad519bc642fdedb76b760d2050879 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 15 Jun 2016 02:02:32 -0500 Subject: [PATCH 160/693] Update eqemu_update.pl [skip ci] --- utils/scripts/eqemu_update.pl | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 6d9be10a2..e1b895712 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -157,13 +157,7 @@ if($ARGV[0] eq "installer"){ get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); #::: Server scripts - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_database_backup.bat", "t_database_backup.bat", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_server_crash_report.pl", "t_server_crash_report.pl", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server.bat", "t_start_server.bat", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_stop_server.bat", "t_stop_server.bat", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/win_server_launcher.pl", "win_server_launcher.pl", 1); - + fetch_utility_scripts(); #::: Database Routines print "MariaDB :: Creating Database 'peq'\n"; @@ -269,6 +263,21 @@ sub do_update_self{ die "Rerun eqemu_update.pl"; } +sub fetch_utility_scripts { + if($OS eq "Windows"){ + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_database_backup.bat", "t_database_backup.bat", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server.bat", "t_start_server.bat", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_stop_server.bat", "t_stop_server.bat", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_server_crash_report,pl", "t_server_crash_report.pl", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/win_server_launcher,pl", "win_server_launcher.pl", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat", 1); + } + else { + print "No scripts found for OS: " . $OS . "...\n"; + } +} + sub show_menu_prompt { my %dispatch = ( 1 => \&database_dump, @@ -285,6 +294,7 @@ sub show_menu_prompt { 12 => \&fetch_server_dlls, 13 => \&do_windows_login_server_setup, 14 => \&remove_duplicate_rule_values, + 15 => \&fetch_utility_scripts, 19 => \&do_bots_db_schema_drop, 20 => \&do_update_self, 0 => \&script_exit, @@ -363,6 +373,7 @@ return < Date: Thu, 16 Jun 2016 02:17:11 -0500 Subject: [PATCH 161/693] Update eqemu_update.pl --- utils/scripts/eqemu_update.pl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index e1b895712..6a4693d3b 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -265,13 +265,13 @@ sub do_update_self{ sub fetch_utility_scripts { if($OS eq "Windows"){ - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_database_backup.bat", "t_database_backup.bat", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server.bat", "t_start_server.bat", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_stop_server.bat", "t_stop_server.bat", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_server_crash_report,pl", "t_server_crash_report.pl", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/win_server_launcher,pl", "win_server_launcher.pl", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_database_backup.bat", "t_database_backup.bat"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server.bat", "t_start_server.bat"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_stop_server.bat", "t_stop_server.bat"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_server_crash_report,pl", "t_server_crash_report.pl"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/win_server_launcher,pl", "win_server_launcher.pl"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat"); } else { print "No scripts found for OS: " . $OS . "...\n"; From c72749790d7180c28305a673b0d5078ad80167f8 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 16 Jun 2016 13:14:27 -0500 Subject: [PATCH 162/693] Update eqemu_update.pl --- utils/scripts/eqemu_update.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 6a4693d3b..0af555ce5 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -269,8 +269,8 @@ sub fetch_utility_scripts { get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server.bat", "t_start_server.bat"); get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat"); get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_stop_server.bat", "t_stop_server.bat"); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_server_crash_report,pl", "t_server_crash_report.pl"); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/win_server_launcher,pl", "win_server_launcher.pl"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_server_crash_report.pl", "t_server_crash_report.pl"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/win_server_launcher.pl", "win_server_launcher.pl"); get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat"); } else { From 7b04b9ef4a2d1f16332447897b69422c7c7d5d6f Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sat, 18 Jun 2016 23:36:13 -0700 Subject: [PATCH 163/693] Fix for #bot command crashing the zone when sent with no text following "#bot" --- zone/command.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index c52b613db..c7aaef59a 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -10848,8 +10848,13 @@ void command_reloadperlexportsettings(Client *c, const Seperator *sep) void command_bot(Client *c, const Seperator *sep) { std::string bot_message = sep->msg; - bot_message = bot_message.substr(bot_message.find_first_not_of("#bot")); - bot_message[0] = BOT_COMMAND_CHAR; + if (bot_message.compare("#bot") == 0) { + bot_message[0] = BOT_COMMAND_CHAR; + } + else { + bot_message = bot_message.substr(bot_message.find_first_not_of("#bot")); + bot_message[0] = BOT_COMMAND_CHAR; + } if (bot_command_dispatch(c, bot_message.c_str()) == -2) { if (parse->PlayerHasQuestSub(EVENT_COMMAND)) { From 1a2537f5d860078f82de497c845184bdfb69cb2d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 20 Jun 2016 14:25:05 -0500 Subject: [PATCH 164/693] Adjust default lootdrop max level --- zone/mob_ai.cpp | 3 ++- zone/pets.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 2b618e7e2..b79b6118a 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1570,9 +1570,10 @@ void NPC::AI_DoMovement() { if (m_CurrentWayPoint.w >= 0.0) { SetHeading(m_CurrentWayPoint.w); } - SendPosition(); } + SendPosition(); + //kick off event_waypoint arrive char temp[16]; sprintf(temp, "%d", cur_wp); diff --git a/zone/pets.cpp b/zone/pets.cpp index 020abf2f4..23680cd88 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -669,7 +669,7 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { if (item2 && item2->NoDrop != 0) { //dont bother saving item charges for now, NPCs never use them //and nobody should be able to get them off the corpse..? - AddLootDrop(item2, &itemlist, 0, 1, 127, true, true); + AddLootDrop(item2, &itemlist, 0, 1, 255, true, true); } } } From fe630bf7cafeb8a198423ebdc3b3a4791a49c7f7 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 20 Jun 2016 14:27:01 -0500 Subject: [PATCH 165/693] Adjust default lootdrop max level --- zone/aa.cpp | 2 +- zone/loottables.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 1473a1bee..18cb4cfc2 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -424,7 +424,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) sitem = CorpseToUse->GetWornItem(x); if(sitem){ const EQEmu::ItemBase * itm = database.GetItem(sitem); - npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 127, true, true); + npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 255, true, true); } } diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 9dbfa37ac..910331e27 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -417,7 +417,7 @@ void NPC::AddLootDrop(const EQEmu::ItemBase *item2, ItemList* itemlist, int16 ch void NPC::AddItem(const EQEmu::ItemBase* item, uint16 charges, bool equipitem) { //slot isnt needed, its determined from the item. - AddLootDrop(item, &itemlist, charges, 1, 127, equipitem, equipitem); + AddLootDrop(item, &itemlist, charges, 1, 255, equipitem, equipitem); } void NPC::AddItem(uint32 itemid, uint16 charges, bool equipitem) { @@ -425,7 +425,7 @@ void NPC::AddItem(uint32 itemid, uint16 charges, bool equipitem) { const EQEmu::ItemBase * i = database.GetItem(itemid); if(i == nullptr) return; - AddLootDrop(i, &itemlist, charges, 1, 127, equipitem, equipitem); + AddLootDrop(i, &itemlist, charges, 1, 255, equipitem, equipitem); } void NPC::AddLootTable() { From 951f3239f10a2d7eb31622467392bce9d12b212f Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 23 Jun 2016 22:25:57 -0400 Subject: [PATCH 166/693] Added rule Bots:AllowCamelCaseNames --- common/ruletypes.h | 1 + common/version.h | 2 +- utils/sql/git/bots/bots_db_update_manifest.txt | 1 + .../git/bots/required/2016_06_23_bots_camel_case_name_rule.sql | 2 ++ zone/bot.cpp | 2 +- 5 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 utils/sql/git/bots/required/2016_06_23_bots_camel_case_name_rule.sql diff --git a/common/ruletypes.h b/common/ruletypes.h index 6c253722a..c3ba0c0e9 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -531,6 +531,7 @@ RULE_CATEGORY_END() #ifdef BOTS RULE_CATEGORY(Bots) RULE_INT(Bots, AAExpansion, 8) // Bots get AAs through this expansion +RULE_BOOL(Bots, AllowCamelCaseNames, false) // Allows the use of 'MyBot' type names RULE_INT(Bots, CommandSpellRank, 1) // Filters bot command spells by rank (1, 2 and 3 are valid filters - any other number allows all ranks) RULE_INT(Bots, CreationLimit, 150) // Number of bots that each account can create RULE_BOOL(Bots, FinishBuffing, false) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat. diff --git a/common/version.h b/common/version.h index e5a4e6322..2b621b1c3 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9096 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9006 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9007 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 0bfabf0ff..cda433dc1 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -5,6 +5,7 @@ 9004|2016_04_07_bots_heal_override_target.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'healrotationclearhot'|empty| 9005|2016_04_08_bots_heal_rotations.sql|SHOW TABLES LIKE 'bot_heal_rotations'|empty| 9006|2016_04_12_bots_inventory_window.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'inventorywindow'|empty| +9007|2016_06_23_bots_camel_case_name_rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AllowCamelCaseNames'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2016_06_23_bots_camel_case_name_rule.sql b/utils/sql/git/bots/required/2016_06_23_bots_camel_case_name_rule.sql new file mode 100644 index 000000000..6a758f28a --- /dev/null +++ b/utils/sql/git/bots/required/2016_06_23_bots_camel_case_name_rule.sql @@ -0,0 +1,2 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES +(1, 'Bots:AllowCamelCaseNames', 'false', 'Allows the use of \'MyBot\' type names'); diff --git a/zone/bot.cpp b/zone/bot.cpp index edbc4e8eb..b4d0718be 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1538,7 +1538,7 @@ bool Bot::IsValidName(std::string& name) return false; for (int i = 1; i < name.length(); ++i) { - if (!islower(name[i]) && name[i] != '_') { + if ((!RuleB(Bots, AllowCamelCaseNames) && !islower(name[i])) && name[i] != '_') { return false; } } From 8615df0a039c20b63fc40f5061d9a25e392e03db Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sat, 25 Jun 2016 18:04:23 -0700 Subject: [PATCH 167/693] Bot names skip player name filter to allow for longer bot names. RoF/RoF2/UF item packets allow for 1000 stack items again.. not capped at 254 --- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/patches/uf.cpp | 2 +- zone/bot_database.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index b60e0534f..0b45b98e6 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -5209,7 +5209,7 @@ namespace RoF snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%016d", item->ID); - hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1); + hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 1000) ? 0xFFFFFFFF : inst->GetCharges()) : 1); hdr.unknown004 = 0; structs::InventorySlot_Struct slot_id = ServerToRoFSlot(slot_id_in); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 114238d83..57f823ce2 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -5497,7 +5497,7 @@ namespace RoF2 snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%016d", item->ID); - hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1); + hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 1000) ? 0xFFFFFFFF : inst->GetCharges()) : 1); hdr.unknown004 = 0; structs::InventorySlot_Struct slot_id = ServerToRoF2Slot(slot_id_in, packet_type); diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 2756ae6dd..d613c8867 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -3845,7 +3845,7 @@ namespace UF UF::structs::ItemSerializationHeader hdr; - hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1); + hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 1000) ? 0xFFFFFFFF : inst->GetCharges()) : 1); hdr.unknown004 = 0; int32 slot_id = ServerToUFSlot(slot_id_in); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 3f8a60c0d..7a746c721 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -86,7 +86,7 @@ bool BotDatabase::LoadBotCommandSettings(std::map 15 || !database.CheckNameFilter(bot_name.c_str()) || !database.CheckUsedName(bot_name.c_str())) + if (bot_name.empty() || bot_name.size() > 60 || !database.CheckUsedName(bot_name.c_str())) return false; query = StringFormat("SELECT `id` FROM `vw_bot_character_mobs` WHERE `name` LIKE '%s' LIMIT 1", bot_name.c_str()); From 02ec76d2aa02c6ae61b2329fae94e5adb4fa1a5c Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Mon, 27 Jun 2016 11:14:33 -0400 Subject: [PATCH 168/693] Res effects now block certain buffs like on live. Blocked spells generate message as on live. --- zone/spells.cpp | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index cb0d0f4d8..acdd4c58e 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2775,23 +2775,6 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, int modval = mod_spell_stack(spellid1, caster_level1, caster1, spellid2, caster_level2, caster2); if(modval < 2) { return(modval); } - //resurrection effects wont count for overwrite/block stacking - switch(spellid1) - { - case 756: - case 757: - case 5249: - return (0); - } - - switch (spellid2) - { - case 756: - case 757: - case 5249: - return (0); - } - /* One of these is a bard song and one isn't and they're both beneficial so they should stack. */ @@ -3135,6 +3118,9 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid if (ret == -1) { // stop the spell Log.Out(Logs::Detail, Logs::Spells, "Adding buff %d failed: stacking prevented by spell %d in slot %d with caster level %d", spell_id, curbuf.spellid, buffslot, curbuf.casterlevel); + if (caster->IsClient()) { + caster->Message(13, "Your %s did not take hold on %s. (Blocked by %s.)", spells[spell_id].name, this->GetName(), spells[curbuf.spellid].name); + } return -1; } if (ret == 1) { // set a flag to indicate that there will be overwriting @@ -3295,6 +3281,7 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite) firstfree = i; } if(ret == -1) { + Log.Out(Logs::Detail, Logs::AI, "Buff %d would conflict with %d in slot %d, reporting stack failure", spellid, curbuf.spellid, i); return -1; // stop the spell, can't stack it } From 3d6fe8acbaed698c18c79f887335d069206b0309 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 28 Jun 2016 07:58:38 -0400 Subject: [PATCH 169/693] Fix for bot inventory save failure involving items with unlimited charges --- changelog.txt | 3 +++ common/shareddb.cpp | 3 +-- common/version.h | 2 +- utils/sql/git/bots/bots_db_update_manifest.txt | 1 + .../2016_06_28_bots_inventory_charges_update.sql | 1 + zone/bot_database.cpp | 12 ++++++++++-- 6 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 utils/sql/git/bots/required/2016_06_28_bots_inventory_charges_update.sql diff --git a/changelog.txt b/changelog.txt index 005945fd1..8c5523df6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 06/28/2016 == +Uleat: Fix for bot inventory save failure involving items with unlimited charges + == 06/13/2016 == Noudess: Changes personal faction earned min/max to -2000/2000 from -3000/1200 diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 6748300d4..163c8d6b9 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -595,8 +595,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) if (charges == 0x7FFF) inst->SetCharges(-1); - else if (charges == 0 && - inst->IsStackable()) // Stackable items need a minimum charge of 1 remain moveable. + else if (charges == 0 && inst->IsStackable()) // Stackable items need a minimum charge of 1 remain moveable. inst->SetCharges(1); else inst->SetCharges(charges); diff --git a/common/version.h b/common/version.h index 2b621b1c3..93d3b1779 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9096 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9007 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index cda433dc1..50677d60e 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -6,6 +6,7 @@ 9005|2016_04_08_bots_heal_rotations.sql|SHOW TABLES LIKE 'bot_heal_rotations'|empty| 9006|2016_04_12_bots_inventory_window.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'inventorywindow'|empty| 9007|2016_06_23_bots_camel_case_name_rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AllowCamelCaseNames'|empty| +9008|2016_06_28_bots_inventory_charges_update.sql|SELECT * FROM `information_schema`.`COLUMNS` isc WHERE isc.`TABLE_SCHEMA` = DATABASE() AND isc.`TABLE_NAME` = 'bot_inventories' AND isc.`COLUMN_NAME` = 'inst_charges' AND isc.`DATA_TYPE` = 'tinyint'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2016_06_28_bots_inventory_charges_update.sql b/utils/sql/git/bots/required/2016_06_28_bots_inventory_charges_update.sql new file mode 100644 index 000000000..1315c3e9e --- /dev/null +++ b/utils/sql/git/bots/required/2016_06_28_bots_inventory_charges_update.sql @@ -0,0 +1 @@ +ALTER TABLE `bot_inventories` MODIFY COLUMN `inst_charges` SMALLINT(3) UNSIGNED NULL DEFAULT '0'; diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 7a746c721..0fade9c9d 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1079,8 +1079,10 @@ bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) continue; } - if (item_charges == 255) + if (item_charges == 0x7FFF) item_inst->SetCharges(-1); + else if (item_charges == 0 && item_inst->IsStackable()) // Stackable items need a minimum charge of 1 remain moveable. + item_inst->SetCharges(1); else item_inst->SetCharges(item_charges); @@ -1190,6 +1192,12 @@ bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const Item for (int augment_iter = 0; augment_iter < EQEmu::legacy::ITEM_COMMON_SIZE; ++augment_iter) augment_id[augment_iter] = item_inst->GetAugmentItemID(augment_iter); + uint16 item_charges = 0; + if (item_inst->GetCharges() >= 0) + item_charges = item_inst->GetCharges(); + else + item_charges = 0x7FFF; + query = StringFormat( "INSERT INTO `bot_inventories` (" "`bot_id`," @@ -1230,7 +1238,7 @@ bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const Item (unsigned long)bot_inst->GetBotID(), (unsigned long)slot_id, (unsigned long)item_inst->GetID(), - (unsigned long)item_inst->GetCharges(), + (unsigned long)item_charges, (unsigned long)item_inst->GetColor(), (unsigned long)(item_inst->IsAttuned() ? 1 : 0), item_inst->GetCustomDataString().c_str(), From 9a010a90a96d957a15f928e221f074728b175410 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Tue, 28 Jun 2016 08:27:31 -0400 Subject: [PATCH 170/693] Added Client:UseLiveBlockedMessage rule --- changelog.txt | 5 +++++ common/ruletypes.h | 1 + zone/spells.cpp | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 005945fd1..1669a2a37 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 06/28/2016 +Noudess: Resurrection effects now block certain buffs like on live. +Noudess: Added message about why spells are blocked (rule based) +Noudess: Added new rule: Client:UseLiveBlockedMessage + == 06/13/2016 == Noudess: Changes personal faction earned min/max to -2000/2000 from -3000/1200 diff --git a/common/ruletypes.h b/common/ruletypes.h index c3ba0c0e9..83f1f2b94 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -665,6 +665,7 @@ RULE_CATEGORY_END() RULE_CATEGORY(Client) RULE_BOOL(Client, UseLiveFactionMessage, false) // Allows players to see faction adjustments like Live +RULE_BOOL(Client, UseLiveBlockedMessage, false) // Allows players to see faction adjustments like Live RULE_CATEGORY_END() #undef RULE_CATEGORY diff --git a/zone/spells.cpp b/zone/spells.cpp index acdd4c58e..e7a090e57 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3118,7 +3118,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid if (ret == -1) { // stop the spell Log.Out(Logs::Detail, Logs::Spells, "Adding buff %d failed: stacking prevented by spell %d in slot %d with caster level %d", spell_id, curbuf.spellid, buffslot, curbuf.casterlevel); - if (caster->IsClient()) { + if (caster->IsClient() && RuleB(Client, UseLiveBlockedMessage)) { caster->Message(13, "Your %s did not take hold on %s. (Blocked by %s.)", spells[spell_id].name, this->GetName(), spells[curbuf.spellid].name); } return -1; From a5d79b25db1e8f7587db93a26ba60e1995a627a6 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 28 Jun 2016 16:56:42 -0400 Subject: [PATCH 171/693] Grr... --- utils/sql/git/bots/bots_db_update_manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 50677d60e..3122545a0 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -6,7 +6,7 @@ 9005|2016_04_08_bots_heal_rotations.sql|SHOW TABLES LIKE 'bot_heal_rotations'|empty| 9006|2016_04_12_bots_inventory_window.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'inventorywindow'|empty| 9007|2016_06_23_bots_camel_case_name_rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AllowCamelCaseNames'|empty| -9008|2016_06_28_bots_inventory_charges_update.sql|SELECT * FROM `information_schema`.`COLUMNS` isc WHERE isc.`TABLE_SCHEMA` = DATABASE() AND isc.`TABLE_NAME` = 'bot_inventories' AND isc.`COLUMN_NAME` = 'inst_charges' AND isc.`DATA_TYPE` = 'tinyint'|empty| +9008|2016_06_28_bots_inventory_charges_update.sql|SELECT * FROM `information_schema`.`COLUMNS` isc WHERE isc.`TABLE_SCHEMA` = DATABASE() AND isc.`TABLE_NAME` = 'bot_inventories' AND isc.`COLUMN_NAME` = 'inst_charges' AND isc.`DATA_TYPE` = 'tinyint'|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From 3e0af2928bc1a97e3421db35942aca27d1f4f10c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 30 Jun 2016 01:30:51 -0400 Subject: [PATCH 172/693] Remove duped code from CommonBreakInvisibleFromCombat --- zone/attack.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 15081785c..7fb450c6f 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4438,9 +4438,6 @@ void Mob::CommonBreakInvisibleFromCombat() invisible_animals = false; } - if (spellbonuses.NegateIfCombat) - BuffFadeByEffect(SE_NegateIfCombat); - if(hidden || improved_hidden){ hidden = false; improved_hidden = false; From a64343689ca719a7ff10c67676925da5ade2cdf0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 30 Jun 2016 14:00:18 -0400 Subject: [PATCH 173/693] Refactor loot response a bit Invis is dropped after ALL error checking now Identified all the response types --- zone/client_packet.cpp | 32 -------------------------------- zone/common.h | 10 ++++++++++ zone/corpse.cpp | 30 +++++++++++++++++++----------- zone/corpse.h | 2 +- zone/mob.cpp | 17 +++++++++++++++++ zone/mob.h | 1 + 6 files changed, 48 insertions(+), 44 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7f77a2eb9..fc376c64e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9177,39 +9177,7 @@ void Client::Handle_OP_LootRequest(const EQApplicationPacket *app) if (ent->IsCorpse()) { SetLooting(ent->GetID()); //store the entity we are looting - Corpse *ent_corpse = ent->CastToCorpse(); - if (DistanceSquaredNoZ(m_Position, ent_corpse->GetPosition()) > 625) - { - Message(13, "Corpse too far away."); - Corpse::SendLootReqErrorPacket(this); - return; - } - if (invisible) { - BuffFadeByEffect(SE_Invisibility); - BuffFadeByEffect(SE_Invisibility2); - invisible = false; - } - if (invisible_undead) { - BuffFadeByEffect(SE_InvisVsUndead); - BuffFadeByEffect(SE_InvisVsUndead2); - invisible_undead = false; - } - if (invisible_animals){ - BuffFadeByEffect(SE_InvisVsAnimals); - invisible_animals = false; - } - if (hidden || improved_hidden){ - hidden = false; - improved_hidden = false; - auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; - sa_out->spawn_id = GetID(); - sa_out->type = 0x03; - sa_out->parameter = 0; - entity_list.QueueClients(this, outapp, true); - safe_delete(outapp); - } ent->CastToCorpse()->MakeLootRequestPackets(this, app); return; } diff --git a/zone/common.h b/zone/common.h index d517bb721..97bb1a50b 100644 --- a/zone/common.h +++ b/zone/common.h @@ -189,6 +189,16 @@ enum class PlayerState : uint32 { SecondaryWeaponEquipped = 128 }; +enum class LootResponse : uint8 { + SomeoneElse = 0, + Normal = 1, + NotAtThisTime = 2, + Normal2 = 3, // acts exactly the same as Normal, maybe group vs ungroup? No idea + Hostiles = 4, + TooFar = 5, + LootAll = 6 // SoD+ +}; + //this is our internal representation of the BUFF struct, can put whatever we want in it struct Buffs_Struct { uint16 spellid; diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 0fc02a2ac..ff5e4806b 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -64,10 +64,10 @@ void Corpse::SendEndLootErrorPacket(Client* client) { safe_delete(outapp); } -void Corpse::SendLootReqErrorPacket(Client* client, uint8 response) { +void Corpse::SendLootReqErrorPacket(Client* client, LootResponse response) { auto outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct)); moneyOnCorpseStruct* d = (moneyOnCorpseStruct*) outapp->pBuffer; - d->response = response; + d->response = static_cast(response); d->unknown1 = 0x5a; d->unknown2 = 0x40; client->QueuePacket(outapp); @@ -876,7 +876,7 @@ void Corpse::AllowPlayerLoot(Mob *them, uint8 slot) { void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* app) { // Added 12/08. Started compressing loot struct on live. if(player_corpse_depop) { - SendLootReqErrorPacket(client, 0); + SendLootReqErrorPacket(client, LootResponse::SomeoneElse); return; } @@ -888,7 +888,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a } if(is_locked && client->Admin() < 100) { - SendLootReqErrorPacket(client, 0); + SendLootReqErrorPacket(client, LootResponse::SomeoneElse); client->Message(13, "Error: Corpse locked by GM."); return; } @@ -899,7 +899,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(this->being_looted_by != 0xFFFFFFFF) { // lets double check.... Entity* looter = entity_list.GetID(this->being_looted_by); - if(looter == 0) + if(looter == nullptr) this->being_looted_by = 0xFFFFFFFF; } @@ -909,8 +909,14 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(database.GetVariable("LootCoin", tmp)) loot_coin = tmp[0] == 1 && tmp[1] == '\0'; - if (this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) { - SendLootReqErrorPacket(client, 0); + if (DistanceSquaredNoZ(client->GetPosition(), m_Position) > 625) { + SendLootReqErrorPacket(client, LootResponse::TooFar); + // not sure if we need to send the packet back in this case? Didn't before! + // Will just return for now + return; + } + else if (this->being_looted_by != 0xFFFFFFFF && this->being_looted_by != client->GetID()) { + SendLootReqErrorPacket(client, LootResponse::SomeoneElse); Loot_Request_Type = 0; } else if (IsPlayerCorpse() && char_id == client->CharacterID()) { @@ -931,16 +937,17 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if (Loot_Request_Type == 1) { if (client->Admin() < 100 || !client->GetGM()) { - SendLootReqErrorPacket(client, 2); + SendLootReqErrorPacket(client, LootResponse::NotAtThisTime); } } if(Loot_Request_Type >= 2 || (Loot_Request_Type == 1 && client->Admin() >= 100 && client->GetGM())) { + client->CommonBreakInvisible(); // we should be "all good" so lets break invis now instead of earlier before all error checking is done this->being_looted_by = client->GetID(); auto outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct)); moneyOnCorpseStruct* d = (moneyOnCorpseStruct*) outapp->pBuffer; - d->response = 1; + d->response = static_cast(LootResponse::Normal); d->unknown1 = 0x42; d->unknown2 = 0xef; @@ -1052,7 +1059,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a // This is required for the 'Loot All' feature to work for SoD clients. I expect it is to tell the client that the // server has now sent all the items on the corpse. - if (client->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { SendLootReqErrorPacket(client, 6); } + if (client->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) + SendLootReqErrorPacket(client, LootResponse::LootAll); } void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { @@ -1092,7 +1100,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { return; } if (is_locked && client->Admin() < 100) { - SendLootReqErrorPacket(client, 0); + SendLootReqErrorPacket(client, LootResponse::SomeoneElse); client->Message(13, "Error: Corpse locked by GM."); return; } diff --git a/zone/corpse.h b/zone/corpse.h index c08bece02..509899827 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -37,7 +37,7 @@ class Corpse : public Mob { public: static void SendEndLootErrorPacket(Client* client); - static void SendLootReqErrorPacket(Client* client, uint8 response = 2); + static void SendLootReqErrorPacket(Client* client, LootResponse response = LootResponse::NotAtThisTime); Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NPCType** in_npctypedata, uint32 in_decaytime = 600000); Corpse(Client* client, int32 in_rezexp); diff --git a/zone/mob.cpp b/zone/mob.cpp index f76902da9..a4aa4e15a 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5854,6 +5854,23 @@ int Mob::CheckBaneDamage(const ItemInst *item) return damage; } +void Mob::CommonBreakInvisible() +{ + BreakInvisibleSpells(); + + if (hidden || improved_hidden) { + hidden = false; + improved_hidden = false; + auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); + SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; + sa_out->spawn_id = GetID(); + sa_out->type = 0x03; + sa_out->parameter = 0; + entity_list.QueueClients(this, outapp, true); + safe_delete(outapp); + } +} + #ifdef BOTS bool Mob::JoinHealRotationTargetPool(std::shared_ptr* heal_rotation) { diff --git a/zone/mob.h b/zone/mob.h index a282fb89c..3608efa9c 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -173,6 +173,7 @@ public: void RogueEvade(Mob *other); void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts = nullptr); void BreakInvisibleSpells(); + void CommonBreakInvisible(); void CommonBreakInvisibleFromCombat(); bool HasDied(); virtual bool CheckDualWield(); From 54de212214a9cfe8aaa52365daede58b3d8f1deb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 30 Jun 2016 17:50:31 -0400 Subject: [PATCH 174/693] Implement OP_CancelSneakHide Didn't test every client, but they should all work --- common/emu_oplist.h | 1 + utils/patches/patch_RoF.conf | 1 + utils/patches/patch_RoF2.conf | 1 + utils/patches/patch_SoD.conf | 1 + utils/patches/patch_SoF.conf | 1 + utils/patches/patch_Titanium.conf | 1 + utils/patches/patch_UF.conf | 1 + zone/client.h | 1 + zone/client_packet.cpp | 8 ++++++++ zone/client_process.cpp | 15 +++++++++++++++ zone/mob.cpp | 10 +++++++--- zone/mob.h | 1 + 12 files changed, 39 insertions(+), 3 deletions(-) diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 936595afa..8b913095b 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -64,6 +64,7 @@ N(OP_BuffRemoveRequest), N(OP_Bug), N(OP_CameraEffect), N(OP_Camp), +N(OP_CancelSneakHide), N(OP_CancelTask), N(OP_CancelTrade), N(OP_CastSpell), diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index 466043c39..00682d57f 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -357,6 +357,7 @@ OP_Weblink=0x7cce OP_OpenContainer=0x654f OP_Marquee=0x288a OP_Fling=0x6b8e +OP_CancelSneakHide=0x265f OP_DzQuit=0x5fc8 OP_DzListTimers=0x67b9 diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 8582ab503..9237a0238 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -358,6 +358,7 @@ OP_ItemRecastDelay=0x15a9 #OP_OpenInventory=0x0000 # Likely does not exist in RoF -U OP_ResetAA=0x1669 OP_Fling=0x6f80 +OP_CancelSneakHide=0x0927 # Expeditions OP_DzAddPlayer=0x4701 diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index 1c362111b..4944b0ef3 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -352,6 +352,7 @@ OP_OpenInventory=0x1003 OP_OpenContainer=0x3278 OP_Marquee=0x7dc9 OP_Fling=0x2b88 +OP_CancelSneakHide=0x7705 # Expedition OP_DzQuit=0x054e diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index 9c58b5684..113038e49 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -334,6 +334,7 @@ OP_OpenInventory=0x66c8 OP_OpenContainer=0x10e3 OP_Marquee=0x2f75 OP_Untargetable=0x3e36 +OP_CancelSneakHide=0x5335 #expedition OP_DzQuit=0x20d6 diff --git a/utils/patches/patch_Titanium.conf b/utils/patches/patch_Titanium.conf index 99ef322a0..a48de92b5 100644 --- a/utils/patches/patch_Titanium.conf +++ b/utils/patches/patch_Titanium.conf @@ -286,6 +286,7 @@ OP_RemoveNimbusEffect=0x0000 OP_CrystalReclaim=0x7cfe OP_CrystalCreate=0x62c3 OP_Marquee=0x1d4d +OP_CancelSneakHide=0x48C2 OP_DzQuit=0x486d OP_DzListTimers=0x39aa diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index cb7d11851..4b650176f 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -362,6 +362,7 @@ OP_InspectMessageUpdate=0x7fa1 # C OP_OpenContainer=0x041a OP_Marquee=0x3675 OP_Fling=0x51b1 +OP_CancelSneakHide=0x7686 OP_DzQuit=0x1539 OP_DzListTimers=0x21e9 diff --git a/zone/client.h b/zone/client.h index b3965b031..9bd22f815 100644 --- a/zone/client.h +++ b/zone/client.h @@ -834,6 +834,7 @@ public: eqFilterMode GetFilter(eqFilterType filter_id) const { return ClientFilters[filter_id]; } void SetFilter(eqFilterType filter_id, eqFilterMode value) { ClientFilters[filter_id]=value; } + void CancelSneakHide(); void BreakInvis(); void BreakSneakWhenCastOn(Mob* caster, bool IsResisted); void BreakFeignDeathWhenCastOn(bool IsResisted); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index fc376c64e..2dfaec3b9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -7871,6 +7871,14 @@ void Client::Handle_OP_Heartbeat(const EQApplicationPacket *app) void Client::Handle_OP_Hide(const EQApplicationPacket *app) { + // newer client respond to OP_CancelSneakHide with OP_Hide with a size of 4 and 0 data + if (app->size == 4) { + auto data = app->ReadUInt32(0); + if (data) + Log.Out(Logs::Detail, Logs::None, "Got OP_Hide with unexpected data %d", data); + return; + } + if (!HasSkill(EQEmu::skills::SkillHide) && GetSkill(EQEmu::skills::SkillHide) == 0) { //Can not be able to train hide but still have it from racial though diff --git a/zone/client_process.cpp b/zone/client_process.cpp index f61b475bc..ecab035b6 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1127,6 +1127,21 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) Save(); } +void Client::CancelSneakHide() +{ + if (hidden || improved_hidden) { + auto app = new EQApplicationPacket(OP_CancelSneakHide, 0); + FastQueuePacket(&app); + // SoF and Tit send back a OP_SpawnAppearance turning off AT_Invis + // so we need to handle our sneaking flag only + // The later clients send back a OP_Hide (this has a size but data is 0) + // as well as OP_SpawnAppearance with AT_Invis and one with AT_Sneak + // So we don't have to handle any of those flags + if (ClientVersionBit() & EQEmu::versions::bit_SoFAndEarlier) + sneaking = false; + } +} + void Client::BreakInvis() { if (invisible) diff --git a/zone/mob.cpp b/zone/mob.cpp index a4aa4e15a..b2dd61687 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5854,10 +5854,8 @@ int Mob::CheckBaneDamage(const ItemInst *item) return damage; } -void Mob::CommonBreakInvisible() +void Mob::CancelSneakHide() { - BreakInvisibleSpells(); - if (hidden || improved_hidden) { hidden = false; improved_hidden = false; @@ -5871,6 +5869,12 @@ void Mob::CommonBreakInvisible() } } +void Mob::CommonBreakInvisible() +{ + BreakInvisibleSpells(); + CancelSneakHide(); +} + #ifdef BOTS bool Mob::JoinHealRotationTargetPool(std::shared_ptr* heal_rotation) { diff --git a/zone/mob.h b/zone/mob.h index 3608efa9c..841e3a24e 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -173,6 +173,7 @@ public: void RogueEvade(Mob *other); void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts = nullptr); void BreakInvisibleSpells(); + virtual void CancelSneakHide(); void CommonBreakInvisible(); void CommonBreakInvisibleFromCombat(); bool HasDied(); From 37b46d128916b560fa4d4bce9e86158c0e40f3ed Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 30 Jun 2016 21:49:00 -0400 Subject: [PATCH 175/693] Make more usage of CancelSneakHide --- zone/attack.cpp | 12 +----------- zone/spell_effects.cpp | 43 +++++++++++------------------------------- 2 files changed, 12 insertions(+), 43 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 7fb450c6f..2f3eb26aa 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4438,17 +4438,7 @@ void Mob::CommonBreakInvisibleFromCombat() invisible_animals = false; } - if(hidden || improved_hidden){ - hidden = false; - improved_hidden = false; - auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; - sa_out->spawn_id = GetID(); - sa_out->type = 0x03; - sa_out->parameter = 0; - entity_list.QueueClients(this, outapp, true); - safe_delete(outapp); - } + CancelSneakHide(); if (spellbonuses.NegateIfCombat) BuffFadeByEffect(SE_NegateIfCombat); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index e1bd31220..a9ac289bb 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6759,49 +6759,28 @@ void Mob::BreakInvisibleSpells() } } -void Client::BreakSneakWhenCastOn(Mob* caster, bool IsResisted) +void Client::BreakSneakWhenCastOn(Mob *caster, bool IsResisted) { - bool IsCastersTarget = false; //Chance to avoid only applies to AOE spells when not targeted. - if(hidden || improved_hidden){ - - if (caster){ - Mob* target = nullptr; + bool IsCastersTarget = false; // Chance to avoid only applies to AOE spells when not targeted. + if (hidden || improved_hidden) { + if (caster) { + Mob *target = nullptr; target = caster->GetTarget(); - if (target && target == this){ - IsCastersTarget = true; - } + IsCastersTarget = target && target == this; } - if (!IsCastersTarget){ - - int chance = spellbonuses.NoBreakAESneak + itembonuses.NoBreakAESneak + aabonuses.NoBreakAESneak; + if (!IsCastersTarget) { + int chance = + spellbonuses.NoBreakAESneak + itembonuses.NoBreakAESneak + aabonuses.NoBreakAESneak; if (IsResisted) chance *= 2; - if(chance && (zone->random.Roll(chance))) + if (chance && zone->random.Roll(chance)) return; // Do not drop Sneak/Hide } - - //TODO: The skill buttons should reset when this occurs. Not sure how to force that yet. - Kayen - hidden = false; - improved_hidden = false; - auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; - sa_out->spawn_id = GetID(); - sa_out->type = 0x03; - sa_out->parameter = 0; - entity_list.QueueClients(this, outapp, false); - safe_delete(outapp); - Message_StringID(MT_Skills,NO_LONGER_HIDDEN); - - //Sneaking alone will not be disabled from spells, only hide+sneak. - if (sneaking){ - sneaking = false; - SendAppearancePacket(AT_Sneak, 0); - Message_StringID(MT_Skills,STOP_SNEAKING); - } + CancelSneakHide(); } } From bcec9501b79b65ee64bf7acc1e8277fd0ebfedef Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 30 Jun 2016 21:49:20 -0400 Subject: [PATCH 176/693] Fix issue with invis not dropping for new item clicks Clients using OP_ItemVerifyRequest couldn't break the invis themselves, so we gotta for them --- zone/client_packet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2dfaec3b9..1e35170ff 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8550,6 +8550,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } if (i == 0) { + CommonBreakInvisible(); // client can't do this for us :( CastSpell(item->Click.Effect, target_id, USE_ITEM_SPELL_SLOT, item->CastTime, 0, 0, slot_id); } } @@ -8577,6 +8578,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } if (i == 0) { + CommonBreakInvisible(); // client can't do this for us :( CastSpell(augitem->Click.Effect, target_id, USE_ITEM_SPELL_SLOT, augitem->CastTime, 0, 0, slot_id); } } From 860ee81a38bb5ae07173bbdbd6b9dfbfbaf27276 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 30 Jun 2016 21:59:50 -0400 Subject: [PATCH 177/693] Break invis for AA casts --- zone/aa.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/aa.cpp b/zone/aa.cpp index 18cb4cfc2..2407286fa 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1179,6 +1179,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { cooldown = 0; } + CommonBreakInvisible(); // Bards can cast instant cast AAs while they are casting another song if(spells[rank->spell].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), ALTERNATE_ABILITY_SPELL_SLOT, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) { From bacaf6453e6c7b3df73893aea6b84cc09dc5860d Mon Sep 17 00:00:00 2001 From: Josh Endries Date: Sun, 3 Jul 2016 15:13:34 -0400 Subject: [PATCH 178/693] Add FreeBSD as a peer with Linux in eqemu_update.pl OS detection --- utils/scripts/eqemu_update.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 0af555ce5..116c587c5 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -19,7 +19,7 @@ use Time::HiRes qw(usleep); $time_stamp = strftime('%m-%d-%Y', gmtime()); $console_output .= " Operating System is: $Config{osname}\n"; -if($Config{osname}=~/linux/i){ $OS = "Linux"; } +if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } #::: If current version is less than what world is reporting, then download a new one... From 3d61df253d5580ad54d8909cdb81ebf1ac0ae5e9 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 3 Jul 2016 19:44:45 -0400 Subject: [PATCH 179/693] Added rule 'NPC:UseClassAsLastName' to allow certain npcs' class names to be hidden --- common/ruletypes.h | 1 + common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + utils/sql/git/required/2016_07_03_npc_class_as_last_name.sql | 2 ++ zone/mob.cpp | 2 +- 5 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 utils/sql/git/required/2016_07_03_npc_class_as_last_name.sql diff --git a/common/ruletypes.h b/common/ruletypes.h index 83f1f2b94..41dbeacd2 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -502,6 +502,7 @@ RULE_BOOL(NPC, LiveLikeEnrage, false) // If set to true then only player control RULE_BOOL(NPC, EnableMeritBasedFaction, false) // If set to true, faction will given in the same way as experience (solo/group/raid) RULE_INT(NPC, NPCToNPCAggroTimerMin, 500) RULE_INT(NPC, NPCToNPCAggroTimerMax, 6000) +RULE_BOOL(NPC, UseClassAsLastName, true) // Uses class archetype as LastName for npcs with none RULE_CATEGORY_END() RULE_CATEGORY(Aggro) diff --git a/common/version.h b/common/version.h index 93d3b1779..38731b3ba 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9096 +#define CURRENT_BINARY_DATABASE_VERSION 9097 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 6f48f983e..283500c3b 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -350,6 +350,7 @@ 9094|2015_12_29_quest_zone_events.sql|SELECT * FROM perl_event_export_settings WHERE event_description = 'EVENT_SPAWN_ZONE'|empty| 9095|2016_01_08_command_find_aliases.sql|SELECT * FROM `command_settings` WHERE `command` LIKE 'findaliases'|empty| 9096|2016_03_05_secondary_recall.sql|SHOW COLUMNS FROM `character_bind` LIKE 'slot'|empty| +9097|2016_07_03_npc_class_as_last_name.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'NPC:UseClassAsLastName'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2016_07_03_npc_class_as_last_name.sql b/utils/sql/git/required/2016_07_03_npc_class_as_last_name.sql new file mode 100644 index 000000000..75f4b5296 --- /dev/null +++ b/utils/sql/git/required/2016_07_03_npc_class_as_last_name.sql @@ -0,0 +1,2 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES +(1, 'NPC:UseClassAsLastName', 'true', 'Uses class archetype as LastName for npcs with none'); diff --git a/zone/mob.cpp b/zone/mob.cpp index b2dd61687..590751bd0 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -909,7 +909,7 @@ void Mob::CreateSpawnPacket(EQApplicationPacket* app, Mob* ForWho) { NewSpawn_Struct* ns = (NewSpawn_Struct*)app->pBuffer; FillSpawnStruct(ns, ForWho); - if(strlen(ns->spawn.lastName) == 0) + if(RuleB(NPC, UseClassAsLastName) && strlen(ns->spawn.lastName) == 0) { switch(ns->spawn.class_) { From 542d454fe0c8624410b1ff75dd781c1fdfbf76c7 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 5 Jul 2016 15:20:46 -0400 Subject: [PATCH 180/693] Added rule 'NPC:UseClassAsLastName' to second spawn packet handler --- zone/mob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 590751bd0..7dcbbcb15 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -990,7 +990,7 @@ void Mob::CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns) { strcpy(ns2->spawn.name, ns->spawn.name); // Set default Last Names for certain Classes if not defined - if (strlen(ns->spawn.lastName) == 0) + if (RuleB(NPC, UseClassAsLastName) && strlen(ns->spawn.lastName) == 0) { switch (ns->spawn.class_) { From 4b57f69cba09895939d9da70ba1bc07b4802658e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 7 Jul 2016 16:17:13 -0400 Subject: [PATCH 181/693] Fix illusions on zone --- zone/client_packet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 1e35170ff..c46fb8936 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -606,14 +606,14 @@ void Client::CompleteConnect() gender = 1; SendIllusionPacket(GetRace(), gender, 0xFF, 0xFF); } - else if (spell.base[x1] == -2) + else if (spell.base[x1] == -2) // WTF IS THIS { if (GetRace() == 128 || GetRace() == 130 || GetRace() <= 12) - SendIllusionPacket(GetRace(), GetGender(), spell.max[x1], spell.max[x1]); + SendIllusionPacket(GetRace(), GetGender(), spell.base2[x1], spell.max[x1]); } else if (spell.max[x1] > 0) { - SendIllusionPacket(spell.base[x1], 0xFF, spell.max[x1], spell.max[x1]); + SendIllusionPacket(spell.base[x1], 0xFF, spell.base2[x1], spell.max[x1]); } else { From b44da7c13a7611a0f7c694afba78593640764b2e Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 8 Jul 2016 15:33:36 -0400 Subject: [PATCH 182/693] Fix for command #traindisc not saving disciplines when not used on self --- zone/command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index c7aaef59a..68049cc43 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -7839,7 +7839,7 @@ void command_traindisc(Client *c, const Seperator *sep) break; //continue the 1st loop } else if(t->GetPP().disciplines.values[r] == 0) { t->GetPP().disciplines.values[r] = curspell; - database.SaveCharacterDisc(c->CharacterID(), r, curspell); + database.SaveCharacterDisc(t->CharacterID(), r, curspell); t->SendDisciplineUpdate(); t->Message(0, "You have learned a new discipline!"); count++; //success counter From bc196f2e50749027fd8ef8efead01ada53a9bf4c Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 8 Jul 2016 16:19:14 -0400 Subject: [PATCH 183/693] Changed world server zone boot-up failure message to 'General' level to facilitate world-initiated zone boot-up issues --- world/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/client.cpp b/world/client.cpp index 5b94846be..33c6a259a 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1057,7 +1057,7 @@ bool Client::Process() { to.sin_addr.s_addr = ip; if (autobootup_timeout.Check()) { - Log.Out(Logs::Detail, Logs::World_Server, "Zone bootup timer expired, bootup failed or too slow."); + Log.Out(Logs::General, Logs::World_Server, "Zone bootup timer expired, bootup failed or too slow."); ZoneUnavail(); } if(connect.Check()){ From 402353affad843e61f01ea0f258f98091586a2aa Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 9 Jul 2016 03:10:54 -0400 Subject: [PATCH 184/693] Important fix for mob pathing (see changelog.txt) --- changelog.txt | 6 ++++++ zone/mob_ai.cpp | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index dc8f3af8e..efa9b257a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 07/09/2016 == +Uleat: Important fix for mob pathing + - This should fix failed pathing issues (and high cpu usage for zone.exe) for mobs in affect zones + - Changed variable 'gridno' type from int16 to int32 to reflect actual return value of fetch (values do exceed 32767 aka int16.max) + - Precision loss from int32 to int16 conversion was causing grid id to be changed to quest controlled movement in cases where (gridno & 0x8000 == true) + == 06/28/2016 == Noudess: Resurrection effects now block certain buffs like on live. Noudess: Added message about why spells are blocked (rule based) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index b79b6118a..6ed6eee99 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1551,7 +1551,7 @@ void NPC::AI_DoMovement() { } - int16 gridno = CastToNPC()->GetGrid(); + int32 gridno = CastToNPC()->GetGrid(); if (gridno > 0 || cur_wp==-2) { if (movetimercompleted==true) { // time to pause at wp is over From 56fcabc11970ace09f4c114e464099fc88426a5c Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 9 Jul 2016 15:40:19 -0400 Subject: [PATCH 185/693] Fix Voice Graft to allow you to speak by targetting yourself. --- zone/client.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index c10a26312..46f4da4c1 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -886,7 +886,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s } case 3: { /* Shout */ Mob *sender = this; - if (GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetTarget() != this && GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); @@ -924,7 +924,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s else if(!RuleB(Chat, ServerWideAuction)) { Mob *sender = this; - if (GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetTarget() != this && GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, message); @@ -971,7 +971,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s { Mob *sender = this; - if (GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetTarget() != this && GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, message); @@ -1069,7 +1069,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s #endif Mob* sender = this; - if (GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetTarget() != this && GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); From 1ba7f0cd65bed913a44e7e6b9871769f1982e460 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 9 Jul 2016 16:35:57 -0400 Subject: [PATCH 186/693] Fix so you can still speak to NPCS (patch to last patch for voice graft) --- zone/client.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 46f4da4c1..bb7403930 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -886,7 +886,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s } case 3: { /* Shout */ Mob *sender = this; - if (GetTarget() != this && GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetTarget() == GetPet() && GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); @@ -924,7 +924,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s else if(!RuleB(Chat, ServerWideAuction)) { Mob *sender = this; - if (GetTarget() != this && GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetTarget() == GetPet() && GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, message); @@ -971,7 +971,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s { Mob *sender = this; - if (GetTarget() != this && GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetTarget() == GetPet() && GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, message); @@ -1069,7 +1069,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s #endif Mob* sender = this; - if (GetTarget() != this && GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetTarget() == GetPet() && GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); From a9ff40765773f09a1ef46d4b7074fb9ba14cf112 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 10 Jul 2016 23:18:26 -0400 Subject: [PATCH 187/693] Optimize Mapp:RotateVertex() This function can get rather expensive and waste a surprisingly large amount of time. Using moors as a test zone simply switching from the C math API cos/sin to std::cos/std::sin seemed to help 11.11% Map::RotateVertex(glm::tvec3&, float, float, float) 4.16% Map::RotateVertex(glm::tvec3&, float, float, float) --- zone/map.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zone/map.cpp b/zone/map.cpp index 5bfb3291b..0fb1036d5 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -897,18 +897,18 @@ bool Map::LoadV2(FILE *f) { void Map::RotateVertex(glm::vec3 &v, float rx, float ry, float rz) { glm::vec3 nv = v; - nv.y = (cos(rx) * v.y) - (sin(rx) * v.z); - nv.z = (sin(rx) * v.y) + (cos(rx) * v.z); + nv.y = (std::cos(rx) * v.y) - (std::sin(rx) * v.z); + nv.z = (std::sin(rx) * v.y) + (std::cos(rx) * v.z); v = nv; - nv.x = (cos(ry) * v.x) + (sin(ry) * v.z); - nv.z = -(sin(ry) * v.x) + (cos(ry) * v.z); + nv.x = (std::cos(ry) * v.x) + (std::sin(ry) * v.z); + nv.z = -(std::sin(ry) * v.x) + (std::cos(ry) * v.z); v = nv; - nv.x = (cos(rz) * v.x) - (sin(rz) * v.y); - nv.y = (sin(rz) * v.x) + (cos(rz) * v.y); + nv.x = (std::cos(rz) * v.x) - (std::sin(rz) * v.y); + nv.y = (std::sin(rz) * v.x) + (std::cos(rz) * v.y); v = nv; } From 7457d832f8877eb63e35e69844ed5f5f8c7f7f8a Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 12 Jul 2016 20:22:14 -0400 Subject: [PATCH 188/693] Changed query in BotDatabase::LoadGroupedBotsByGroupID() to use standard table query over view use (should help in cases where players time-out when zoning) --- zone/bot_database.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 0fade9c9d..300f4c8b4 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -2390,21 +2390,33 @@ bool BotDatabase::LoadBotGroupsListByOwnerID(const uint32 owner_id, std::list& group_list) { if (!group_id) return false; query = StringFormat( - "SELECT g.`mob_id` AS bot_id" - " FROM `vw_groups` AS g" - " JOIN `bot_data` AS b" - " ON g.`mob_id` = b.`bot_id`" - " AND g.`mob_type` = 'B'" - " WHERE g.`group_id` = '%u'", + "SELECT `charid`" + " FROM `group_id`" + " WHERE `groupid` = '%u'" + " AND `charid` IN (" + " SELECT `bot_id`" + " FROM `bot_data`" + " WHERE `owner_id` IN (" + " SELECT `charid`" + " FROM `group_id`" + " WHERE `groupid` = '%u'" + " AND `name` IN (" + " SELECT `name`" + " FROM `character_data`" + " )" + " )" + " )", + group_id, group_id ); + auto results = QueryDatabase(query); if (!results.Success()) return false; From 871fcd1fc8c4a679d1dc4d5e33a2c5782a34f38d Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 14 Jul 2016 12:47:55 -0400 Subject: [PATCH 189/693] Fix for quest enabletask/disabletask api queries --- zone/tasks.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 97368db77..7420f5c18 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -723,8 +723,14 @@ void ClientTaskState::EnableTask(int characterID, int taskCount, int *tasks) { queryStream << ( i ? ", " : "" ) << StringFormat("(%i, %i)", characterID, tasksEnabled[i]); std::string query = queryStream.str(); - Log.Out(Logs::General, Logs::Tasks, "[UPDATE] Executing query %s", query.c_str()); - database.QueryDatabase(query); + + if (tasksEnabled.size()) { + Log.Out(Logs::General, Logs::Tasks, "[UPDATE] Executing query %s", query.c_str()); + database.QueryDatabase(query); + } + else { + Log.Out(Logs::General, Logs::Tasks, "[UPDATE] EnableTask called for characterID: %u .. but, no tasks exist!", characterID); + } } void ClientTaskState::DisableTask(int charID, int taskCount, int *taskList) { @@ -765,12 +771,19 @@ void ClientTaskState::DisableTask(int charID, int taskCount, int *taskList) { std::stringstream queryStream(StringFormat("DELETE FROM character_enabledtasks WHERE charid = %i AND (", charID)); for(unsigned int i=0; i Date: Thu, 14 Jul 2016 13:22:36 -0400 Subject: [PATCH 190/693] Changed tuple use to struct in maps.cpp (LoadV2) (should help in client drops where slow zone boot-ups are a factor) --- changelog.txt | 9 ++++++++- zone/map.cpp | 30 +++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/changelog.txt b/changelog.txt index efa9b257a..a051fb6e2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,8 +1,15 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 07/14/2016 == +Uleat: Changed LoadV2Map usage of std::tuplet to struct PointEntry () + - This appears to help with zone boot times when V2 maps are used on windows systems - unverified on linux systems as of this time + - Current visual studio implementation for tuples is to pass by value whereas structs are passed by reference. The overhead is noticeable when processing VLS data objects (~33 seconds versus ~9 seconds in 'moors' for the affected code with my system) + - This change, in addition to the recent sin/cos change by mackal, should improve zone boot times and help alleviate client dumps on zoning due to time-outs - in some cases + - Please report any issues observed by this or any other change + == 07/09/2016 == Uleat: Important fix for mob pathing - - This should fix failed pathing issues (and high cpu usage for zone.exe) for mobs in affect zones + - This should fix failed pathing issues (and high cpu usage for zone.exe) for mobs in affected zones - Changed variable 'gridno' type from int16 to int32 to reflect actual return value of fetch (values do exceed 32767 aka int16.max) - Precision loss from int32 to int16 conversion was causing grid id to be changed to quest controlled movement in cases where (gridno & 0x8000 == true) diff --git a/zone/map.cpp b/zone/map.cpp index 0fb1036d5..a5c677f6b 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -348,6 +348,18 @@ struct ModelEntry std::vector polys; }; +struct PointEntry +{ + PointEntry(float x, float y, float z) { x_val = x; y_val = y; z_val = z; } + void set(float x, float y, float z) { x_val = x; y_val = y; z_val = z; } + bool operator==(const PointEntry& r) const { return (x_val == r.x_val && y_val == r.y_val && z_val == r.z_val); } + bool operator<(const PointEntry& r) const { return (x_val < r.x_val && y_val < r.y_val && z_val < r.z_val); } + + float x_val; + float y_val; + float z_val; +}; + bool Map::LoadV2(FILE *f) { uint32 data_size; if (fread(&data_size, sizeof(data_size), 1, f) != 1) { @@ -792,7 +804,7 @@ bool Map::LoadV2(FILE *f) { } int row_number = -1; - std::map, uint32> cur_verts; + std::map cur_verts; for (uint32 quad = 0; quad < ter_quad_count; ++quad) { if ((quad % quads_per_tile) == 0) { ++row_number; @@ -818,7 +830,7 @@ bool Map::LoadV2(FILE *f) { float QuadVertex4Z = floats[quad + row_number + 1]; uint32 i1, i2, i3, i4; - std::tuple t = std::make_tuple(QuadVertex1X, QuadVertex1Y, QuadVertex1Z); + PointEntry t(QuadVertex1X, QuadVertex1Y, QuadVertex1Z); auto iter = cur_verts.find(t); if (iter != cur_verts.end()) { i1 = iter->second; @@ -826,10 +838,10 @@ bool Map::LoadV2(FILE *f) { else { i1 = (uint32)verts.size(); verts.push_back(glm::vec3(QuadVertex1X, QuadVertex1Y, QuadVertex1Z)); - cur_verts[std::make_tuple(QuadVertex1X, QuadVertex1Y, QuadVertex1Z)] = i1; + cur_verts[t] = i1; } - t = std::make_tuple(QuadVertex2X, QuadVertex2Y, QuadVertex2Z); + t.set(QuadVertex2X, QuadVertex2Y, QuadVertex2Z); iter = cur_verts.find(t); if (iter != cur_verts.end()) { i2 = iter->second; @@ -837,10 +849,10 @@ bool Map::LoadV2(FILE *f) { else { i2 = (uint32)verts.size(); verts.push_back(glm::vec3(QuadVertex2X, QuadVertex2Y, QuadVertex2Z)); - cur_verts[std::make_tuple(QuadVertex2X, QuadVertex2Y, QuadVertex2Z)] = i2; + cur_verts[t] = i2; } - t = std::make_tuple(QuadVertex3X, QuadVertex3Y, QuadVertex3Z); + t.set(QuadVertex3X, QuadVertex3Y, QuadVertex3Z); iter = cur_verts.find(t); if (iter != cur_verts.end()) { i3 = iter->second; @@ -848,10 +860,10 @@ bool Map::LoadV2(FILE *f) { else { i3 = (uint32)verts.size(); verts.push_back(glm::vec3(QuadVertex3X, QuadVertex3Y, QuadVertex3Z)); - cur_verts[std::make_tuple(QuadVertex3X, QuadVertex3Y, QuadVertex3Z)] = i3; + cur_verts[t] = i3; } - t = std::make_tuple(QuadVertex4X, QuadVertex4Y, QuadVertex4Z); + t.set(QuadVertex4X, QuadVertex4Y, QuadVertex4Z); iter = cur_verts.find(t); if (iter != cur_verts.end()) { i4 = iter->second; @@ -859,7 +871,7 @@ bool Map::LoadV2(FILE *f) { else { i4 = (uint32)verts.size(); verts.push_back(glm::vec3(QuadVertex4X, QuadVertex4Y, QuadVertex4Z)); - cur_verts[std::make_tuple(QuadVertex4X, QuadVertex4Y, QuadVertex4Z)] = i4; + cur_verts[t] = i4; } indices.push_back(i4); From bbf4d19de39a7b9be9a1e9c150dcd9b52ea89376 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 15 Jul 2016 15:20:36 -0400 Subject: [PATCH 191/693] Revert "Changed tuple use to struct in maps.cpp (LoadV2) (should help in client drops where slow zone boot-ups are a factor)" This reverts commit 02cedce54eaf590d0ac02fc7dd52c8feb9313f2c. This is breaks moors! --- changelog.txt | 9 +-------- zone/map.cpp | 30 +++++++++--------------------- 2 files changed, 10 insertions(+), 29 deletions(-) diff --git a/changelog.txt b/changelog.txt index a051fb6e2..efa9b257a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,15 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- -== 07/14/2016 == -Uleat: Changed LoadV2Map usage of std::tuplet to struct PointEntry () - - This appears to help with zone boot times when V2 maps are used on windows systems - unverified on linux systems as of this time - - Current visual studio implementation for tuples is to pass by value whereas structs are passed by reference. The overhead is noticeable when processing VLS data objects (~33 seconds versus ~9 seconds in 'moors' for the affected code with my system) - - This change, in addition to the recent sin/cos change by mackal, should improve zone boot times and help alleviate client dumps on zoning due to time-outs - in some cases - - Please report any issues observed by this or any other change - == 07/09/2016 == Uleat: Important fix for mob pathing - - This should fix failed pathing issues (and high cpu usage for zone.exe) for mobs in affected zones + - This should fix failed pathing issues (and high cpu usage for zone.exe) for mobs in affect zones - Changed variable 'gridno' type from int16 to int32 to reflect actual return value of fetch (values do exceed 32767 aka int16.max) - Precision loss from int32 to int16 conversion was causing grid id to be changed to quest controlled movement in cases where (gridno & 0x8000 == true) diff --git a/zone/map.cpp b/zone/map.cpp index a5c677f6b..0fb1036d5 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -348,18 +348,6 @@ struct ModelEntry std::vector polys; }; -struct PointEntry -{ - PointEntry(float x, float y, float z) { x_val = x; y_val = y; z_val = z; } - void set(float x, float y, float z) { x_val = x; y_val = y; z_val = z; } - bool operator==(const PointEntry& r) const { return (x_val == r.x_val && y_val == r.y_val && z_val == r.z_val); } - bool operator<(const PointEntry& r) const { return (x_val < r.x_val && y_val < r.y_val && z_val < r.z_val); } - - float x_val; - float y_val; - float z_val; -}; - bool Map::LoadV2(FILE *f) { uint32 data_size; if (fread(&data_size, sizeof(data_size), 1, f) != 1) { @@ -804,7 +792,7 @@ bool Map::LoadV2(FILE *f) { } int row_number = -1; - std::map cur_verts; + std::map, uint32> cur_verts; for (uint32 quad = 0; quad < ter_quad_count; ++quad) { if ((quad % quads_per_tile) == 0) { ++row_number; @@ -830,7 +818,7 @@ bool Map::LoadV2(FILE *f) { float QuadVertex4Z = floats[quad + row_number + 1]; uint32 i1, i2, i3, i4; - PointEntry t(QuadVertex1X, QuadVertex1Y, QuadVertex1Z); + std::tuple t = std::make_tuple(QuadVertex1X, QuadVertex1Y, QuadVertex1Z); auto iter = cur_verts.find(t); if (iter != cur_verts.end()) { i1 = iter->second; @@ -838,10 +826,10 @@ bool Map::LoadV2(FILE *f) { else { i1 = (uint32)verts.size(); verts.push_back(glm::vec3(QuadVertex1X, QuadVertex1Y, QuadVertex1Z)); - cur_verts[t] = i1; + cur_verts[std::make_tuple(QuadVertex1X, QuadVertex1Y, QuadVertex1Z)] = i1; } - t.set(QuadVertex2X, QuadVertex2Y, QuadVertex2Z); + t = std::make_tuple(QuadVertex2X, QuadVertex2Y, QuadVertex2Z); iter = cur_verts.find(t); if (iter != cur_verts.end()) { i2 = iter->second; @@ -849,10 +837,10 @@ bool Map::LoadV2(FILE *f) { else { i2 = (uint32)verts.size(); verts.push_back(glm::vec3(QuadVertex2X, QuadVertex2Y, QuadVertex2Z)); - cur_verts[t] = i2; + cur_verts[std::make_tuple(QuadVertex2X, QuadVertex2Y, QuadVertex2Z)] = i2; } - t.set(QuadVertex3X, QuadVertex3Y, QuadVertex3Z); + t = std::make_tuple(QuadVertex3X, QuadVertex3Y, QuadVertex3Z); iter = cur_verts.find(t); if (iter != cur_verts.end()) { i3 = iter->second; @@ -860,10 +848,10 @@ bool Map::LoadV2(FILE *f) { else { i3 = (uint32)verts.size(); verts.push_back(glm::vec3(QuadVertex3X, QuadVertex3Y, QuadVertex3Z)); - cur_verts[t] = i3; + cur_verts[std::make_tuple(QuadVertex3X, QuadVertex3Y, QuadVertex3Z)] = i3; } - t.set(QuadVertex4X, QuadVertex4Y, QuadVertex4Z); + t = std::make_tuple(QuadVertex4X, QuadVertex4Y, QuadVertex4Z); iter = cur_verts.find(t); if (iter != cur_verts.end()) { i4 = iter->second; @@ -871,7 +859,7 @@ bool Map::LoadV2(FILE *f) { else { i4 = (uint32)verts.size(); verts.push_back(glm::vec3(QuadVertex4X, QuadVertex4Y, QuadVertex4Z)); - cur_verts[t] = i4; + cur_verts[std::make_tuple(QuadVertex4X, QuadVertex4Y, QuadVertex4Z)] = i4; } indices.push_back(i4); From 6cb2fdd7371a8ba161723b6f1e972cccd6a375e9 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 15 Jul 2016 19:32:46 -0400 Subject: [PATCH 192/693] Changed constructor call for stringstream in ClientTaskState::EnableTask/DisableTask (write position issues) --- zone/tasks.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 7420f5c18..40e7d8b67 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -718,9 +718,10 @@ void ClientTaskState::EnableTask(int characterID, int taskCount, int *tasks) { if(tasksEnabled.empty() ) return; - std::stringstream queryStream("REPLACE INTO character_enabledtasks (charid, taskid) VALUES "); + std::stringstream queryStream; + queryStream << "REPLACE INTO character_enabledtasks (charid, taskid) VALUES "; for(unsigned int i=0; i Date: Sat, 16 Jul 2016 18:18:10 -0400 Subject: [PATCH 193/693] Tweak spell dot stacking exempt based on client --- common/shareddb.cpp | 2 +- common/spdat.cpp | 11 +++++++++++ common/spdat.h | 3 ++- zone/spells.cpp | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 163c8d6b9..f35967d50 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1663,7 +1663,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].uninterruptable=atoi(row[146]) != 0; sp[tempid].ResistDiff=atoi(row[147]); - sp[tempid].dot_stacking_exempt=atoi(row[148]); + sp[tempid].dot_stacking_exempt = atoi(row[148]) != 0; sp[tempid].RecourseLink = atoi(row[150]); sp[tempid].no_partial_resist = atoi(row[151]) != 0; diff --git a/common/spdat.cpp b/common/spdat.cpp index 02803b173..695b11dab 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1100,6 +1100,17 @@ bool NoDetrimentalSpellAggro(uint16 spell_id) return false; } +bool IsStackableDot(uint16 spell_id) +{ + // rules according to client + if (!IsValidSpell(spell_id)) + return false; + const auto &spell = spells[spell_id]; + if (spell.dot_stacking_exempt || spell.goodEffect || !spell.buffdurationformula) + return false; + return IsEffectInSpell(spell_id, SE_CurrentHP) || IsEffectInSpell(spell_id, SE_GravityEffect); +} + uint32 GetNimbusEffect(uint16 spell_id) { if (IsValidSpell(spell_id)) diff --git a/common/spdat.h b/common/spdat.h index d083f0dbd..f6405d737 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -700,7 +700,7 @@ struct SPDat_Spell_Struct /* 145 */ //int16 spellanim; // Doesn't look like it's the same as #doanim, so not sure what this is /* 146 */ int8 uninterruptable; // Looks like anything != 0 is uninterruptable. Values are mostly -1, 0, & 1 (Fetid Breath = 90?) /* 147 */ int16 ResistDiff; -/* 148 */ int8 dot_stacking_exempt; // If 1 doesn't stack with self cast by others. If -1 (not implemented) doesn't stack with same effect (???) +/* 148 */ bool dot_stacking_exempt; /* 149 */ //int deletable; /* 150 */ uint16 RecourseLink; /* 151 */ bool no_partial_resist; // 151: -1, 0, or 1 @@ -882,6 +882,7 @@ uint32 GetPartialMagicRuneReduction(uint32 spell_id); uint32 GetPartialMeleeRuneAmount(uint32 spell_id); uint32 GetPartialMagicRuneAmount(uint32 spell_id); bool NoDetrimentalSpellAggro(uint16 spell_id); +bool IsStackableDot(uint16 spell_id); int CalcPetHp(int levelb, int classb, int STA = 75); const char *GetRandPetName(); diff --git a/zone/spells.cpp b/zone/spells.cpp index e7a090e57..4dcda4889 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2763,7 +2763,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, // Same Spells and dot exemption is set to 1 or spell is Manaburn if (spellid1 == spellid2) { - if (sp1.dot_stacking_exempt == 1 && caster1 != caster2) { // same caster can refresh + if (IsStackableDot(spellid1) && caster1 != caster2) { // same caster can refresh Log.Out(Logs::Detail, Logs::Spells, "Blocking spell due to dot stacking exemption."); return -1; } else if (spellid1 == 2751) { From d4df2e73518668120c975d20fdbea9e2b1db4ce2 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 16 Jul 2016 19:33:36 -0400 Subject: [PATCH 194/693] Exclude Minor Illusion and Illusion: Tree from perma --- zone/spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 4dcda4889..334923f2f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2663,7 +2663,7 @@ int Mob::CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caste int res = CalcBuffDuration_formula(castlevel, formula, duration); if (caster == target && (target->aabonuses.IllusionPersistence || target->spellbonuses.IllusionPersistence || target->itembonuses.IllusionPersistence) && - IsEffectInSpell(spell_id, SE_Illusion)) + spell_id != 287 && spell_id != 601 && IsEffectInSpell(spell_id, SE_Illusion)) res = 10000; // ~16h override res = mod_buff_duration(res, caster, target, spell_id); From 921136c987fea3ea327d20b06c2b2804d82c688d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 16 Jul 2016 19:40:20 -0400 Subject: [PATCH 195/693] Exclude in other Perma Illusion spot --- zone/spell_effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index a9ac289bb..70e7118f8 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1438,7 +1438,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove for (int x = EQEmu::textures::TextureBegin; x <= EQEmu::textures::LastTintableTexture; x++) SendWearChange(x); - if (caster == this && + if (caster == this && spell.id != 287 && spell.id != 601 && (spellbonuses.IllusionPersistence || aabonuses.IllusionPersistence || itembonuses.IllusionPersistence)) buffs[buffslot].persistant_buff = 1; From 7cd613e5f2e5eb9503de8d7e6a4acd637fee8348 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 17 Jul 2016 02:13:13 -0400 Subject: [PATCH 196/693] Comment spell struct with official names for each field --- common/spdat.h | 276 ++++++++++++++++++++++++++----------------------- 1 file changed, 148 insertions(+), 128 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index f6405d737..84d094bd8 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -643,139 +643,159 @@ typedef enum { struct SPDat_Spell_Struct { -/* 000 */ int id; // not used -/* 001 */ char name[64]; // Name of the spell -/* 002 */ char player_1[32]; // "PLAYER_1" -/* 003 */ char teleport_zone[64]; // Teleport zone, pet name summoned, or item summoned -/* 004 */ char you_cast[64]; // Message when you cast -/* 005 */ char other_casts[64]; // Message when other casts -/* 006 */ char cast_on_you[64]; // Message when spell is cast on you -/* 007 */ char cast_on_other[64]; // Message when spell is cast on someone else -/* 008 */ char spell_fades[64]; // Spell fades -/* 009 */ float range; -/* 010 */ float aoerange; -/* 011 */ float pushback; -/* 012 */ float pushup; -/* 013 */ uint32 cast_time; // Cast time -/* 014 */ uint32 recovery_time; // Recovery time -/* 015 */ uint32 recast_time; // Recast same spell time -/* 016 */ uint32 buffdurationformula; -/* 017 */ uint32 buffduration; -/* 018 */ uint32 AEDuration; // sentinel, rain of something -/* 019 */ uint16 mana; // Mana Used -/* 020 */ int base[EFFECT_COUNT]; //various purposes -/* 032 */ int base2[EFFECT_COUNT]; //various purposes -/* 044 */ int32 max[EFFECT_COUNT]; -/* 056 */ //uint16 icon; // Spell icon -/* 057 */ //uint16 memicon; // Icon on membarthing -/* 058 */ int32 components[4]; // reagents -/* 062 */ int component_counts[4]; // amount of regents used +/* 000 */ int id; // not used -- SPELLINDEX +/* 001 */ char name[64]; // Name of the spell -- SPELLNAME +/* 002 */ char player_1[32]; // "PLAYER_1" -- ACTORTAG +/* 003 */ char teleport_zone[64]; // Teleport zone, pet name summoned, or item summoned -- NPC_FILENAME +/* 004 */ char you_cast[64]; // Message when you cast -- CASTERMETXT +/* 005 */ char other_casts[64]; // Message when other casts -- CASTEROTHERTXT +/* 006 */ char cast_on_you[64]; // Message when spell is cast on you -- CASTEDMETXT +/* 007 */ char cast_on_other[64]; // Message when spell is cast on someone else -- CASTEDOTHERTXT +/* 008 */ char spell_fades[64]; // Spell fades -- SPELLGONE +/* 009 */ float range; // -- RANGE +/* 010 */ float aoerange; // -- IMPACTRANGE +/* 011 */ float pushback; // -- OUTFORCE +/* 012 */ float pushup; // -- UPFORCE +/* 013 */ uint32 cast_time; // Cast time -- CASTINGTIME +/* 014 */ uint32 recovery_time; // Recovery time -- RECOVERYDELAY +/* 015 */ uint32 recast_time; // Recast same spell time -- SPELLDELAY +/* 016 */ uint32 buffdurationformula; // -- DURATIONBASE +/* 017 */ uint32 buffduration; // -- DURATIONCAP +/* 018 */ uint32 AEDuration; // sentinel, rain of something -- IMPACTDURATION +/* 019 */ uint16 mana; // Mana Used -- MANACOST +/* 020 */ int base[EFFECT_COUNT]; //various purposes -- BASEAFFECT1 .. BASEAFFECT12 +/* 032 */ int base2[EFFECT_COUNT]; //various purposes -- BASE_EFFECT2_1 ... BASE_EFFECT2_12 +/* 044 */ int32 max[EFFECT_COUNT]; // -- AFFECT1CAP ... AFFECT12CAP +/* 056 */ //uint16 icon; // Spell icon -- IMAGENUMBER +/* 057 */ //uint16 memicon; // Icon on membarthing -- MEMIMAGENUMBER +/* 058 */ int32 components[4]; // reagents -- EXPENDREAGENT1 ... EXPENDREAGENT4 +/* 062 */ int component_counts[4]; // amount of regents used -- EXPENDQTY1 ... EXPENDQTY4 /* 066 */ int NoexpendReagent[4]; // focus items (Need but not used; Flame Lick has a Fire Beetle Eye focus.) // If it is a number between 1-4 it means components[number] is a focus and not to expend it // If it is a valid itemid it means this item is a focus as well -/* 070 */ uint16 formula[EFFECT_COUNT]; // Spell's value formula -/* 082 */ //int LightType; // probaly another effecttype flag -/* 083 */ int8 goodEffect; //0=detrimental, 1=Beneficial, 2=Beneficial, Group Only -/* 084 */ int Activated; // probably another effecttype flag -/* 085 */ int resisttype; -/* 086 */ int effectid[EFFECT_COUNT]; // Spell's effects -/* 098 */ SpellTargetType targettype; // Spell's Target -/* 099 */ int basediff; // base difficulty fizzle adjustment -/* 100 */ EQEmu::skills::SkillType skill; -/* 101 */ int8 zonetype; // 01=Outdoors, 02=dungeons, ff=Any -/* 102 */ int8 EnvironmentType; -/* 103 */ int8 TimeOfDay; -/* 104 */ uint8 classes[PLAYER_CLASS_COUNT]; // Classes, and their min levels -/* 120 */ uint8 CastingAnim; -/* 121 */ //uint8 TargetAnim; -/* 122 */ //uint32 TravelType; -/* 123 */ uint16 SpellAffectIndex; -/* 124 */ int8 disallow_sit; // 124: high-end Yaulp spells (V, VI, VII, VIII [Rk 1, 2, & 3], & Gallenite's Bark of Fury -/* 125 */ int8 diety_agnostic;// 125: Words of the Skeptic + // -- NOEXPENDREAGENT1 ... NOEXPENDREAGENT4 +/* 070 */ uint16 formula[EFFECT_COUNT]; // Spell's value formula -- LEVELAFFECT1MOD ... LEVELAFFECT12MOD +/* 082 */ //int LightType; // probaly another effecttype flag -- LIGHTTYPE +/* 083 */ int8 goodEffect; //0=detrimental, 1=Beneficial, 2=Beneficial, Group Only -- BENEFICIAL +/* 084 */ int Activated; // probably another effecttype flag -- ACTIVATED +/* 085 */ int resisttype; // -- RESISTTYPE +/* 086 */ int effectid[EFFECT_COUNT]; // Spell's effects -- SPELLAFFECT1 ... SPELLAFFECT12 +/* 098 */ SpellTargetType targettype; // Spell's Target -- TYPENUMBER +/* 099 */ int basediff; // base difficulty fizzle adjustment -- BASEDIFFICULTY +/* 100 */ EQEmu::skills::SkillType skill; // -- CASTINGSKILL +/* 101 */ int8 zonetype; // 01=Outdoors, 02=dungeons, ff=Any -- ZONETYPE +/* 102 */ int8 EnvironmentType; // -- ENVIRONMENTTYPE +/* 103 */ int8 TimeOfDay; // -- TIMEOFDAY +/* 104 */ uint8 classes[PLAYER_CLASS_COUNT]; // Classes, and their min levels -- WARRIORMIN ... BERSERKERMIN +/* 120 */ uint8 CastingAnim; // -- CASTINGANIM +/* 121 */ //uint8 TargetAnim; // -- TARGETANIM +/* 122 */ //uint32 TravelType; // -- TRAVELTYPE +/* 123 */ uint16 SpellAffectIndex; // -- SPELLAFFECTINDEX +/* 124 */ int8 disallow_sit; // 124: high-end Yaulp spells (V, VI, VII, VIII [Rk 1, 2, & 3], & Gallenite's Bark of Fury -- CANCELONSIT +/* 125 */ int8 diety_agnostic;// 125: Words of the Skeptic -- DIETY_AGNOSTIC /* 126 */ int8 deities[16]; // Deity check. 201 - 216 per http://www.eqemulator.net/wiki/wikka.php?wakka=DeityList // -1: Restrict to Deity; 1: Restrict to Deity, but only used on non-Live (Test Server "Blessing of ...") spells; 0: Don't restrict -/* 142 */ // 142: between 0 & 100 - // 143: always set to 0 -/* 144 */ //int16 new_icon // Spell icon used by the client in uifiles/default/spells??.tga, both for spell gems & buff window. Looks to depreciate icon & memicon -/* 145 */ //int16 spellanim; // Doesn't look like it's the same as #doanim, so not sure what this is -/* 146 */ int8 uninterruptable; // Looks like anything != 0 is uninterruptable. Values are mostly -1, 0, & 1 (Fetid Breath = 90?) -/* 147 */ int16 ResistDiff; -/* 148 */ bool dot_stacking_exempt; -/* 149 */ //int deletable; -/* 150 */ uint16 RecourseLink; -/* 151 */ bool no_partial_resist; // 151: -1, 0, or 1 - // 152 & 153: all set to 0 -/* 154 */ int8 short_buff_box; // != 0, goes to short buff box. -/* 155 */ int descnum; // eqstr of description of spell -/* 156 */ int typedescnum; // eqstr of type description -/* 157 */ int effectdescnum; // eqstr of effect description -/* 158 */ //Category Desc ID 3 -/* 159 */ bool npc_no_los; -/* 161 */ bool reflectable; -/* 162 */ int bonushate; -/* 163 */ -/* 164 */ // for most spells this appears to mimic ResistDiff -/* 165 */ bool ldon_trap; //Flag found on all LDON trap / chest related spells. -/* 166 */ int EndurCost; -/* 167 */ int8 EndurTimerIndex; -/* 168 */ bool IsDisciplineBuff; //Will goto the combat window when cast -/* 169 - 172*/ //These are zero for ALL spells -/* 173 */ int HateAdded; -/* 174 */ int EndurUpkeep; -/* 175 */ int numhitstype; // defines which type of behavior will tick down the numhit counter. -/* 176 */ int numhits; -/* 177 */ int pvpresistbase; -/* 178 */ int pvpresistcalc; -/* 179 */ int pvpresistcap; -/* 180 */ int spell_category; -/* 181 */ //unknown - likely buff duration related -/* 182 */ //unknown - likely buff duration related -/* 183 */ -/* 184 */ -/* 185 */ int8 can_mgb; // 0=no, -1 or 1 = yes -/* 186 */ int dispel_flag; -/* 187 */ //int npc_category; -/* 188 */ //int npc_usefulness; -/* 189 */ int MinResist; -/* 190 */ int MaxResist; -/* 191 */ uint8 viral_targets; -/* 192 */ uint8 viral_timer; -/* 193 */ int NimbusEffect; -/* 194 */ float directional_start; //Cone Start Angle: -/* 195 */ float directional_end; // Cone End Angle: -/* 196 */ bool sneak; // effect can only be used if sneaking (rogue 'Daggerfall' ect) -/* 197 */ bool not_focusable; //prevents focus effects from being applied to spell -/* 198 */ bool no_detrimental_spell_aggro; -/* 199 */ -/* 200 */ bool suspendable; // buff is suspended in suspended buff zones -/* 201 */ int viral_range; -/* 202 */ int songcap; // individual song cap -/* 203 */ -/* 204 */ -/* 205 */ bool no_block; -/* 206 */ -/* 207 */ int spellgroup; -/* 208 */ int rank; //increments AA effects with same name -/* 209 */ int no_resist; //makes spells unresistable, which makes charms unbreakable as well. -/* 210 */ // bool DurationFrozen; ??? -/* 211 */ int CastRestriction; //Various restriction categories for spells most seem targetable race related but have also seen others for instance only castable if target hp 20% or lower or only if target out of combat -/* 212 */ bool AllowRest; -/* 213 */ bool InCombat; //Allow spell if target is in combat -/* 214 */ bool OutofCombat; //Allow spell if target is out of combat -/* 215 - 216 */ -/* 217 */ int override_crit_chance; //Places a cap on the max chance to critical -/* 218 */ int aemaxtargets; //Is used for various AE effects -/* 219 */ int no_heal_damage_item_mod; -/* 220 - 223 */ -/* 224 */ bool persistdeath; // buff doesn't get stripped on death -/* 225 - 226 */ -/* 227 */ float min_dist; //spell power modified by distance from caster (Min Distance) -/* 228 */ float min_dist_mod; //spell power modified by distance from caster (Modifier at Min Distance) -/* 229 */ float max_dist; //spell power modified by distance from caster (Max Distance) -/* 230 */ float max_dist_mod; //spell power modified by distance from caster (Modifier at Max Distance) -/* 231 */ float min_range; //Min casting range -/* 232 */ bool no_remove; //prevents buff from being removed by click -/* 233 - 236 */ + // the client actually stores deities in a single int32_t + // -- DIETY_BERTOXXULOUS ... DIETY_VEESHAN +/* 142 */ //int8 npc_no_cast; // 142: between 0 & 100 -- NPC_NO_CAST +/* 143 */ //int ai_pt_bonus; // 143: always set to 0, client doesn't save this -- AI_PT_BONUS +/* 144 */ //int16 new_icon // Spell icon used by the client in uifiles/default/spells??.tga, both for spell gems & buff window. Looks to depreciate icon & memicon -- NEW_ICON +/* 145 */ //int16 spellanim; // Doesn't look like it's the same as #doanim, so not sure what this is, particles I think -- SPELL_EFFECT_INDEX +/* 146 */ bool uninterruptable; // Looks like anything != 0 is uninterruptable. Values are mostly -1, 0, & 1 (Fetid Breath = 90?) -- NO_INTERRUPT +/* 147 */ int16 ResistDiff; // -- RESIST_MOD +/* 148 */ bool dot_stacking_exempt; // -- NOT_STACKABLE_DOT +/* 149 */ //int deletable; // -- DELETE_OK +/* 150 */ uint16 RecourseLink; // -- REFLECT_SPELLINDEX +/* 151 */ bool no_partial_resist; // 151: -1, 0, or 1 -- NO_PARTIAL_SAVE +/* 152 */ //bool small_targets_only; // -- SMALL_TARGETS_ONLY +/* 153 */ //bool uses_persistent_particles; // -- USES_PERSISTENT_PARTICLES +/* 154 */ int8 short_buff_box; // != 0, goes to short buff box. -- BARD_BUFF_BOX +/* 155 */ int descnum; // eqstr of description of spell -- DESCRIPTION_INDEX +/* 156 */ int typedescnum; // eqstr of type description -- PRIMARY_CATEGORY +/* 157 */ int effectdescnum; // eqstr of effect description -- SECONDARY_CATEGORY_1 +/* 158 */ //int secondary_category_2; //Category Desc ID 3 -- SECONDARY_CATEGORY_2 +/* 159 */ bool npc_no_los; // -- NO_NPC_LOS +/* 160 */ //bool feedbackable; // -- FEEDBACKABLE +/* 161 */ bool reflectable; // -- REFLECTABLE +/* 162 */ int bonushate; // -- HATE_MOD +/* 163 */ //int resist_per_level; // -- RESIST_PER_LEVEL +/* 164 */ //int resist_cap; // for most spells this appears to mimic ResistDiff -- RESIST_CAP +/* 165 */ bool ldon_trap; //Flag found on all LDON trap / chest related spells. -- AFFECT_INANIMATE +/* 166 */ int EndurCost; // -- STAMINA_COST +/* 167 */ int8 EndurTimerIndex; // bad name, used for all spells -- TIMER_INDEX +/* 168 */ bool IsDisciplineBuff; //Will goto the combat window when cast -- IS_SKILL +/* 169 - 172*/ //These are zero for ALL spells, also removed from live -- ATTACK_OPENING, DEFENSE_OPENING, SKILL_OPENING, NPC_ERROR_OPENING +/* 173 */ int HateAdded; // -- SPELL_HATE_GIVEN +/* 174 */ int EndurUpkeep; // -- ENDUR_UPKEEP +/* 175 */ int numhitstype; // defines which type of behavior will tick down the numhit counter. -- LIMITED_USE_TYPE +/* 176 */ int numhits; // -- LIMITED_USE_COUNT +/* 177 */ int pvpresistbase; // -- PVP_RESIST_MOD +/* 178 */ int pvpresistcalc; // -- PVP_RESIST_PER_LEVEL +/* 179 */ int pvpresistcap; // -- PVP_RESIST_CAP +/* 180 */ int spell_category; // -- GLOBAL_GROUP +/* 181 */ //int pvp_duration; // buffdurationformula for PvP -- PVP_DURATION +/* 182 */ //int pvp_duration_cap; // buffduration for PvP -- PVP_DURATION_CAP +/* 183 */ //int pcnpc_only_flag; // valid values are 0, 1, and 2 -- PCNPC_ONLY_FLAG +/* 184 */ //bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell -- CAST_NOT_STANDING +/* 185 */ bool can_mgb; // 0=no, -1 or 1 = yes -- CAN_MGB +/* 186 */ int dispel_flag; // -- NO_DISPELL +/* 187 */ //int npc_category; // -- NPC_MEM_CATEGORY +/* 188 */ //int npc_usefulness; // -- NPC_USEFULNESS +/* 189 */ int MinResist; // -- MIN_RESIST +/* 190 */ int MaxResist; // -- MAX_RESIST +/* 191 */ uint8 viral_targets; // -- MIN_SPREAD_TIME +/* 192 */ uint8 viral_timer; // -- MAX_SPREAD_TIME +/* 193 */ int NimbusEffect; // -- DURATION_PARTICLE_EFFECT +/* 194 */ float directional_start; //Cone Start Angle: -- CONE_START_ANGLE +/* 195 */ float directional_end; // Cone End Angle: -- CONE_END_ANGLE +/* 196 */ bool sneak; // effect can only be used if sneaking (rogue 'Daggerfall' ect) -- SNEAK_ATTACK +/* 197 */ bool not_focusable; //prevents focus effects from being applied to spell -- NOT_FOCUSABLE +/* 198 */ bool no_detrimental_spell_aggro; // -- NO_DETRIMENTAL_SPELL_AGGRO +/* 199 */ //bool show_wear_off_message; // -- SHOW_WEAR_OFF_MESSAGE +/* 200 */ bool suspendable; // buff is suspended in suspended buff zones -- IS_COUNTDOWN_HELD +/* 201 */ int viral_range; // -- SPREAD_RADIUS +/* 202 */ int songcap; // individual song cap -- BASE_EFFECTS_FOCUS_CAP +/* 203 */ //bool stacks_with_self; // -- STACKS_WITH_SELF +/* 204 */ //int not_shown_to_player; // client skips this -- NOT_SHOWN_TO_PLAYER +/* 205 */ bool no_block; // -- NO_BUFF_BLOCK +/* 206 */ //int8 anim_variation; // -- ANIM_VARIATION +/* 207 */ int spellgroup; // -- SPELL_GROUP +/* 208 */ int rank; //increments AA effects with same name -- SPELL_GROUP_RANK +/* 209 */ int no_resist; //makes spells unresistable, which makes charms unbreakable as well. -- NO_RESIST +/* 210 */ // bool allow_spellscribe; // -- ALLOW_SPELLSCRIBE +/* 211 */ int CastRestriction; //Various restriction categories for spells most seem targetable race related but have also seen others for instance only castable if target hp 20% or lower or only if target out of combat -- SPELL_REQ_ASSOCIATION_ID +/* 212 */ bool AllowRest; // -- BYPASS_REGEN_CHECK +/* 213 */ bool InCombat; //Allow spell if target is in combat -- CAN_CAST_IN_COMBAT +/* 214 */ bool OutofCombat; //Allow spell if target is out of combat -- CAN_CAST_OUT_OF_COMBAT +/* 215 */ //bool show_dot_message; // -- SHOW_DOT_MESSAGE +/* 216 */ //bool invalid; // -- INVALID +/* 217 */ int override_crit_chance; //Places a cap on the max chance to critical -- OVERRIDE_CRIT_CHANCE +/* 218 */ int aemaxtargets; //Is used for various AE effects -- MAX_TARGETS +/* 219 */ int no_heal_damage_item_mod; // -- NO_HEAL_DAMAGE_ITEM_MOD +/* 220 */ //int caster_requirement_id; // -- CASTER_REQUIREMENT_ID +/* 221 */ //int spell_class; // -- SPELL_CLASS +/* 222 */ //int spell_subclass; // -- SPELL_SUBCLASS +/* 223 */ //int ai_valid_targets; // -- AI_VALID_TARGETS +/* 224 */ bool persistdeath; // buff doesn't get stripped on death -- NO_STRIP_ON_DEATH +/* 225 */ //float base_effects_focus_slope; // -- BASE_EFFECTS_FOCUS_SLOPE +/* 226 */ //float base_effects_focus_offset; // -- BASE_EFFECTS_FOCUS_OFFSET +/* 227 */ float min_dist; //spell power modified by distance from caster (Min Distance) -- DISTANCE_MOD_CLOSE_DIST +/* 228 */ float min_dist_mod; //spell power modified by distance from caster (Modifier at Min Distance) -- DISTANCE_MOD_CLOSE_MULT +/* 229 */ float max_dist; //spell power modified by distance from caster (Max Distance) -- DISTANCE_MOD_FAR_DIST +/* 230 */ float max_dist_mod; //spell power modified by distance from caster (Modifier at Max Distance) -- DISTANCE_MOD_FAR_MULT +/* The client also does this + * v26 = *(float *)&v4->DistanceModFarDist - *(float *)&v4->DistanceModCloseDist; + * if ( v26 > -0.00000011920929 && v26 < 0.00000011920929 ) + * v26 = 1.0; + * v27 = (st7_0 - *(float *)&v4->DistanceModCloseMult) / v26; + * *(float *)&v4->DistanceMod = v27; + */ +/* 231 */ float min_range; //Min casting range -- MIN_RANGE +/* 232 */ bool no_remove; //prevents buff from being removed by click -- NO_REMOVE +/* 233 */ //int spell_recourse_type; // -- SPELL_RECOURSE_TYPE +/* 234 */ //bool only_during_fast_regen; // -- ONLY_DURING_FAST_REGEN +/* 235 */ //bool is_beta_only; // -- IS_BETA_ONLY +/* 236 */ //int spell_subgroup; // -- SPELL_SUBGROUP uint8 DamageShieldType; // This field does not exist in spells_us.txt }; From 3ed43d50f24ff2b4df3dd1d7e4f4264a2cadeedc Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 17 Jul 2016 19:07:48 -0500 Subject: [PATCH 197/693] Resolving glitchy/choppy mob pathing issues --- zone/mob_ai.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 6ed6eee99..ef7d222dd 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1563,13 +1563,12 @@ void NPC::AI_DoMovement() { if (m_CurrentWayPoint.x == GetX() && m_CurrentWayPoint.y == GetY()) { // are we there yet? then stop Log.Out(Logs::Detail, Logs::AI, "We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d", cur_wp, GetX(), GetY(), GetZ(), GetGrid()); - if (cur_wp_pause != 0) { - SetWaypointPause(); - SetAppearance(eaStanding, false); - SetMoving(false); - if (m_CurrentWayPoint.w >= 0.0) { - SetHeading(m_CurrentWayPoint.w); - } + + SetWaypointPause(); + SetAppearance(eaStanding, false); + SetMoving(false); + if (m_CurrentWayPoint.w >= 0.0) { + SetHeading(m_CurrentWayPoint.w); } SendPosition(); From f437232db176a3dd46f9b99d353d45c7e1afd55c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 17 Jul 2016 20:45:58 -0500 Subject: [PATCH 198/693] Overhauled worldserver logging - Now displays account logins - Zoning from character select - Zoning from zone to zone - When any other server process connects to world - Adjust some zone bootup messages etc. Adjusted logging code bits all over and refactored variables for readability etc. --- world/client.cpp | 166 +++++++++++++++++++++++-------------------- world/client.h | 18 ++--- world/clientlist.cpp | 2 +- world/net.cpp | 29 ++++++-- world/zoneserver.cpp | 10 +-- 5 files changed, 128 insertions(+), 97 deletions(-) diff --git a/world/client.cpp b/world/client.cpp index 33c6a259a..8265ab03a 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -98,12 +98,12 @@ Client::Client(EQStreamInterface* ieqs) autobootup_timeout.Disable(); connect.Disable(); - seencharsel = false; + seen_character_select = false; cle = 0; - zoneID = 0; + zone_id = 0; char_name[0] = 0; charid = 0; - pwaitingforbootup = 0; + zone_waiting_for_bootup = 0; StartInTutorial = false; m_ClientVersion = eqs->ClientVersion(); @@ -113,7 +113,7 @@ Client::Client(EQStreamInterface* ieqs) } Client::~Client() { - if (RunLoops && cle && zoneID == 0) + if (RunLoops && cle && zone_id == 0) cle->SetOnline(CLE_Status_Offline); numclients--; @@ -152,7 +152,7 @@ void Client::SendLogServer() void Client::SendEnterWorld(std::string name) { char char_name[64] = { 0 }; - if (pZoning && database.GetLiveChar(GetAccountID(), char_name)) { + if (is_player_zoning && database.GetLiveChar(GetAccountID(), char_name)) { if(database.GetAccountIDByChar(char_name) != GetAccountID()) { eqs->Close(); return; @@ -192,7 +192,7 @@ void Client::SendCharInfo() { SendMembershipSettings(); } - seencharsel = true; + seen_character_select = true; // Send OP_SendCharInfo EQApplicationPacket *outapp = nullptr; @@ -411,7 +411,7 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) { return false; } - pZoning=(li->zoning==1); + is_player_zoning=(li->zoning==1); #ifdef IPBASED_AUTH_HACK struct in_addr tmpip; @@ -436,32 +436,33 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) { #ifdef IPBASED_AUTH_HACK if ((cle = zoneserver_list.CheckAuth(inet_ntoa(tmpip), password))) #else - if (loginserverlist.Connected() == false && !pZoning) { - Log.Out(Logs::Detail, Logs::World_Server,"Error: Login server login while not connected to login server."); + if (loginserverlist.Connected() == false && !is_player_zoning) { + Log.Out(Logs::General, Logs::World_Server,"Error: Login server login while not connected to login server."); return false; } if (((cle = client_list.CheckAuth(name, password)) || (cle = client_list.CheckAuth(id, password)))) #endif { if (cle->AccountID() == 0 || (!minilogin && cle->LSID()==0)) { - Log.Out(Logs::Detail, Logs::World_Server,"ID is 0. Is this server connected to minilogin?"); + Log.Out(Logs::General, Logs::World_Server,"ID is 0. Is this server connected to minilogin?"); if(!minilogin) - Log.Out(Logs::Detail, Logs::World_Server,"If so you forget the minilogin variable..."); + Log.Out(Logs::General, Logs::World_Server,"If so you forget the minilogin variable..."); else - Log.Out(Logs::Detail, Logs::World_Server,"Could not find a minilogin account, verify ip address logging into minilogin is the same that is in your account table."); + Log.Out(Logs::General, Logs::World_Server,"Could not find a minilogin account, verify ip address logging into minilogin is the same that is in your account table."); return false; } cle->SetOnline(); - Log.Out(Logs::Detail, Logs::World_Server,"Logged in. Mode=%s",pZoning ? "(Zoning)" : "(CharSel)"); - if(minilogin){ WorldConfig::DisableStats(); - Log.Out(Logs::Detail, Logs::World_Server,"MiniLogin Account #%d",cle->AccountID()); + Log.Out(Logs::General, Logs::World_Server, "MiniLogin Account #%d",cle->AccountID()); } else { - Log.Out(Logs::Detail, Logs::World_Server,"LS Account #%d",cle->LSID()); + if (!is_player_zoning) { + Log.Out(Logs::General, Logs::World_Server, + "Account (%s) Logging in :: LSID: %d ", cle->AccountName(), cle->LSID()); + } } const WorldConfig *Config=WorldConfig::get(); @@ -479,13 +480,14 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) { safe_delete(pack); } - if (!pZoning) + if (!is_player_zoning) SendGuildList(); + SendLogServer(); SendApproveWorld(); SendEnterWorld(cle->name()); SendPostEnterWorld(); - if (!pZoning) { + if (!is_player_zoning) { SendExpansionInfo(); SendCharInfo(); database.LoginIP(cle->AccountID(), long2ip(GetIP()).c_str()); @@ -729,7 +731,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { EQApplicationPacket *outapp; uint32 tmpaccid = 0; - charid = database.GetCharacterInfo(char_name, &tmpaccid, &zoneID, &instanceID); + charid = database.GetCharacterInfo(char_name, &tmpaccid, &zone_id, &instance_id); if (charid == 0 || tmpaccid != GetAccountID()) { Log.Out(Logs::Detail, Logs::World_Server,"Could not get CharInfo for '%s'",char_name); eqs->Close(); @@ -745,7 +747,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { // This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above) // (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration) - if (!pZoning) { + if (!is_player_zoning) { size_t character_limit = EQEmu::constants::Lookup(eqs->ClientVersion())->CharacterCreationLimit; if (character_limit > EQEmu::constants::CharacterCreationMax) { character_limit = EQEmu::constants::CharacterCreationMax; } if (eqs->ClientVersion() == EQEmu::versions::ClientVersion::Titanium) { character_limit = 8; } @@ -777,7 +779,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { } if (home_enabled) { - zoneID = database.MoveCharacterToBind(charid, 4); + zone_id = database.MoveCharacterToBind(charid, 4); } else { Log.Out(Logs::Detail, Logs::World_Server, "'%s' is trying to go home before they're able...", char_name); @@ -800,8 +802,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { } if (tutorial_enabled) { - zoneID = RuleI(World, TutorialZoneID); - database.MoveCharacterToZone(charid, database.GetZoneName(zoneID)); + zone_id = RuleI(World, TutorialZoneID); + database.MoveCharacterToZone(charid, database.GetZoneName(zone_id)); } else { Log.Out(Logs::Detail, Logs::World_Server, "'%s' is trying to go to tutorial but are not allowed...", char_name); @@ -812,30 +814,30 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { } } - if (zoneID == 0 || !database.GetZoneName(zoneID)) { + if (zone_id == 0 || !database.GetZoneName(zone_id)) { // This is to save people in an invalid zone, once it's removed from the DB database.MoveCharacterToZone(charid, "arena"); - Log.Out(Logs::Detail, Logs::World_Server, "Zone not found in database zone_id=%i, moveing char to arena character:%s", zoneID, char_name); + Log.Out(Logs::Detail, Logs::World_Server, "Zone not found in database zone_id=%i, moveing char to arena character:%s", zone_id, char_name); } - if(instanceID > 0) + if(instance_id > 0) { - if(!database.VerifyInstanceAlive(instanceID, GetCharID())) + if(!database.VerifyInstanceAlive(instance_id, GetCharID())) { - zoneID = database.MoveCharacterToBind(charid); - instanceID = 0; + zone_id = database.MoveCharacterToBind(charid); + instance_id = 0; } else { - if(!database.VerifyZoneInstance(zoneID, instanceID)) + if(!database.VerifyZoneInstance(zone_id, instance_id)) { - zoneID = database.MoveCharacterToBind(charid); - instanceID = 0; + zone_id = database.MoveCharacterToBind(charid); + instance_id = 0; } } } - if(!pZoning) { + if(!is_player_zoning) { database.SetGroupID(char_name, 0, charid); database.SetLoginFlags(charid, false, false, 1); } @@ -1058,7 +1060,7 @@ bool Client::Process() { if (autobootup_timeout.Check()) { Log.Out(Logs::General, Logs::World_Server, "Zone bootup timer expired, bootup failed or too slow."); - ZoneUnavail(); + TellClientZoneUnavailable(); } if(connect.Check()){ SendGuildList();// Send OPCode: OP_GuildsList @@ -1099,63 +1101,63 @@ bool Client::Process() { } void Client::EnterWorld(bool TryBootup) { - if (zoneID == 0) + if (zone_id == 0) return; - ZoneServer* zs = nullptr; - if(instanceID > 0) + ZoneServer* zone_server = nullptr; + if(instance_id > 0) { - if(database.VerifyInstanceAlive(instanceID, GetCharID())) + if(database.VerifyInstanceAlive(instance_id, GetCharID())) { - if(database.VerifyZoneInstance(zoneID, instanceID)) + if(database.VerifyZoneInstance(zone_id, instance_id)) { - zs = zoneserver_list.FindByInstanceID(instanceID); + zone_server = zoneserver_list.FindByInstanceID(instance_id); } else { - instanceID = 0; - zs = nullptr; + instance_id = 0; + zone_server = nullptr; database.MoveCharacterToBind(GetCharID()); - ZoneUnavail(); + TellClientZoneUnavailable(); return; } } else { - instanceID = 0; - zs = nullptr; + instance_id = 0; + zone_server = nullptr; database.MoveCharacterToBind(GetCharID()); - ZoneUnavail(); + TellClientZoneUnavailable(); return; } } else - zs = zoneserver_list.FindByZoneID(zoneID); + zone_server = zoneserver_list.FindByZoneID(zone_id); - const char *zone_name=database.GetZoneName(zoneID, true); - if (zs) { + const char *zone_name = database.GetZoneName(zone_id, true); + if (zone_server) { // warn the world we're comming, so it knows not to shutdown - zs->IncomingClient(this); + zone_server->IncomingClient(this); } else { if (TryBootup) { - Log.Out(Logs::Detail, Logs::World_Server,"Attempting autobootup of %s (%d:%d)",zone_name,zoneID,instanceID); + Log.Out(Logs::General, Logs::World_Server, "Attempting autobootup of %s (%d:%d)", zone_name, zone_id, instance_id); autobootup_timeout.Start(); - pwaitingforbootup = zoneserver_list.TriggerBootup(zoneID, instanceID); - if (pwaitingforbootup == 0) { - Log.Out(Logs::Detail, Logs::World_Server,"No zoneserver available to boot up."); - ZoneUnavail(); + zone_waiting_for_bootup = zoneserver_list.TriggerBootup(zone_id, instance_id); + if (zone_waiting_for_bootup == 0) { + Log.Out(Logs::General, Logs::World_Server, "No zoneserver available to boot up."); + TellClientZoneUnavailable(); } return; } else { - Log.Out(Logs::Detail, Logs::World_Server,"Requested zone %s is not running.",zone_name); - ZoneUnavail(); + Log.Out(Logs::General, Logs::World_Server, "Requested zone %s is not running.", zone_name); + TellClientZoneUnavailable(); return; } } - pwaitingforbootup = 0; + zone_waiting_for_bootup = 0; if(!cle) { return; @@ -1163,12 +1165,20 @@ void Client::EnterWorld(bool TryBootup) { cle->SetChar(charid, char_name); database.UpdateLiveChar(char_name, GetAccountID()); - Log.Out(Logs::Detail, Logs::World_Server,"%s %s (%d:%d)",seencharsel ? "Entering zone" : "Zoning to",zone_name,zoneID,instanceID); - if (seencharsel) { - if (GetAdmin() < 80 && zoneserver_list.IsZoneLocked(zoneID)) { - Log.Out(Logs::Detail, Logs::World_Server,"Enter world failed. Zone is locked."); - ZoneUnavail(); + Log.Out(Logs::General, Logs::World_Server, + "(%s) %s %s (Zone ID %d: Instance ID: %d) ", + char_name, + (seen_character_select ? "Zoning from character select" : "Zoning to"), + zone_name, + zone_id, + instance_id + ); + + if (seen_character_select) { + if (GetAdmin() < 80 && zoneserver_list.IsZoneLocked(zone_id)) { + Log.Out(Logs::General, Logs::World_Server, "Enter world failed. Zone is locked."); + TellClientZoneUnavailable(); return; } @@ -1180,7 +1190,7 @@ void Client::EnterWorld(bool TryBootup) { WorldToZone_Struct* wtz = (WorldToZone_Struct*) pack->pBuffer; wtz->account_id = GetAccountID(); wtz->response = 0; - zs->SendPacket(pack); + zone_server->SendPacket(pack); delete pack; } else { // if they havent seen character select screen, we can assume this is a zone @@ -1192,13 +1202,13 @@ void Client::EnterWorld(bool TryBootup) { void Client::Clearance(int8 response) { ZoneServer* zs = nullptr; - if(instanceID > 0) + if(instance_id > 0) { - zs = zoneserver_list.FindByInstanceID(instanceID); + zs = zoneserver_list.FindByInstanceID(instance_id); } else { - zs = zoneserver_list.FindByZoneID(zoneID); + zs = zoneserver_list.FindByZoneID(zone_id); } if(zs == 0 || response == -1 || response == 0) @@ -1210,7 +1220,7 @@ void Client::Clearance(int8 response) Log.Out(Logs::Detail, Logs::World_Server, "Invalid response %d in Client::Clearance", response); } - ZoneUnavail(); + TellClientZoneUnavailable(); return; } @@ -1218,20 +1228,20 @@ void Client::Clearance(int8 response) if (zs->GetCAddress() == nullptr) { Log.Out(Logs::Detail, Logs::World_Server, "Unable to do zs->GetCAddress() in Client::Clearance!!"); - ZoneUnavail(); + TellClientZoneUnavailable(); return; } - if (zoneID == 0) { + if (zone_id == 0) { Log.Out(Logs::Detail, Logs::World_Server, "zoneID is nullptr in Client::Clearance!!"); - ZoneUnavail(); + TellClientZoneUnavailable(); return; } - const char* zonename = database.GetZoneName(zoneID); + const char* zonename = database.GetZoneName(zone_id); if (zonename == 0) { Log.Out(Logs::Detail, Logs::World_Server, "zonename is nullptr in Client::Clearance!!"); - ZoneUnavail(); + TellClientZoneUnavailable(); return; } @@ -1270,7 +1280,7 @@ void Client::Clearance(int8 response) strcpy(zsi->ip, zs_addr); zsi->port =zs->GetCPort(); - Log.Out(Logs::Detail, Logs::World_Server,"Sending client to zone %s (%d:%d) at %s:%d",zonename,zoneID,instanceID,zsi->ip,zsi->port); + Log.Out(Logs::Detail, Logs::World_Server,"Sending client to zone %s (%d:%d) at %s:%d",zonename,zone_id,instance_id,zsi->ip,zsi->port); QueuePacket(outapp); safe_delete(outapp); @@ -1278,17 +1288,17 @@ void Client::Clearance(int8 response) cle->SetOnline(CLE_Status_Zoning); } -void Client::ZoneUnavail() { +void Client::TellClientZoneUnavailable() { auto outapp = new EQApplicationPacket(OP_ZoneUnavail, sizeof(ZoneUnavail_Struct)); ZoneUnavail_Struct* ua = (ZoneUnavail_Struct*)outapp->pBuffer; - const char* zonename = database.GetZoneName(zoneID); + const char* zonename = database.GetZoneName(zone_id); if (zonename) strcpy(ua->zonename, zonename); QueuePacket(outapp); delete outapp; - zoneID = 0; - pwaitingforbootup = 0; + zone_id = 0; + zone_waiting_for_bootup = 0; autobootup_timeout.Disable(); } diff --git a/world/client.h b/world/client.h index b3e10db8a..391a20c1d 100644 --- a/world/client.h +++ b/world/client.h @@ -45,7 +45,7 @@ public: void SendMembership(); void SendMembershipSettings(); void EnterWorld(bool TryBootup = true); - void ZoneUnavail(); + void TellClientZoneUnavailable(); void QueuePacket(const EQApplicationPacket* app, bool ack_req = true); void Clearance(int8 response); void SendGuildList(); @@ -58,9 +58,9 @@ public: inline uint32 GetIP() { return ip; } inline uint16 GetPort() { return port; } - inline uint32 GetZoneID() { return zoneID; } - inline uint32 GetInstanceID() { return instanceID; } - inline uint32 WaitingForBootup() { return pwaitingforbootup; } + inline uint32 GetZoneID() { return zone_id; } + inline uint32 GetInstanceID() { return instance_id; } + inline uint32 WaitingForBootup() { return zone_waiting_for_bootup; } inline const char * GetAccountName() { if (cle) { return cle->AccountName(); } return "NOCLE"; } inline int16 GetAdmin() { if (cle) { return cle->Admin(); } return 0; } inline uint32 GetAccountID() { if (cle) { return cle->AccountID(); } return 0; } @@ -77,11 +77,11 @@ private: uint16 port; uint32 charid; char char_name[64]; - uint32 zoneID; - uint32 instanceID; - bool pZoning; + uint32 zone_id; + uint32 instance_id; + bool is_player_zoning; Timer autobootup_timeout; - uint32 pwaitingforbootup; + uint32 zone_waiting_for_bootup; bool StartInTutorial; EQEmu::versions::ClientVersion m_ClientVersion; @@ -97,7 +97,7 @@ private: Timer CLE_keepalive_timer; Timer connect; bool firstlogin; - bool seencharsel; + bool seen_character_select; bool realfirstlogin; bool HandlePacket(const EQApplicationPacket *app); diff --git a/world/clientlist.cpp b/world/clientlist.cpp index 8da2b013c..7c83701f4 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -1184,7 +1184,7 @@ void ClientList::ZoneBootup(ZoneServer* zs) { iterator.GetData()->EnterWorld(false); } else if (iterator.GetData()->WaitingForBootup() == zs->GetID()) { - iterator.GetData()->ZoneUnavail(); + iterator.GetData()->TellClientZoneUnavailable(); } } iterator.Advance(); diff --git a/world/net.cpp b/world/net.cpp index ee335aa7c..94a24205a 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -426,7 +426,7 @@ int main(int argc, char** argv) { //structures and opcodes for that patch. struct in_addr in; in.s_addr = eqs->GetRemoteIP(); - Log.Out(Logs::General, Logs::World_Server, "New connection from %s:%d", inet_ntoa(in),ntohs(eqs->GetRemotePort())); + Log.Out(Logs::Detail, Logs::World_Server, "New connection from IP %s:%d", inet_ntoa(in),ntohs(eqs->GetRemotePort())); stream_identifier.AddStream(eqs); //takes the stream } @@ -441,9 +441,9 @@ int main(int argc, char** argv) { struct in_addr in; in.s_addr = eqsi->GetRemoteIP(); if (RuleB(World, UseBannedIPsTable)){ //Lieka: Check to see if we have the responsibility for blocking IPs. - Log.Out(Logs::General, Logs::World_Server, "Checking inbound connection %s against BannedIPs table", inet_ntoa(in)); + Log.Out(Logs::Detail, Logs::World_Server, "Checking inbound connection %s against BannedIPs table", inet_ntoa(in)); if (!database.CheckBannedIPs(inet_ntoa(in))){ //Lieka: Check inbound IP against banned IP table. - Log.Out(Logs::General, Logs::World_Server, "Connection %s PASSED banned IPs check. Processing connection.", inet_ntoa(in)); + Log.Out(Logs::Detail, Logs::World_Server, "Connection %s PASSED banned IPs check. Processing connection.", inet_ntoa(in)); auto client = new Client(eqsi); // @merth: client->zoneattempt=0; client_list.Add(client); @@ -453,7 +453,7 @@ int main(int argc, char** argv) { } } if (!RuleB(World, UseBannedIPsTable)){ - Log.Out(Logs::General, Logs::World_Server, "New connection from %s:%d, processing connection", inet_ntoa(in), ntohs(eqsi->GetRemotePort())); + Log.Out(Logs::Detail, Logs::World_Server, "New connection from %s:%d, processing connection", inet_ntoa(in), ntohs(eqsi->GetRemotePort())); auto client = new Client(eqsi); // @merth: client->zoneattempt=0; client_list.Add(client); @@ -465,7 +465,26 @@ int main(int argc, char** argv) { while ((tcpc = tcps.NewQueuePop())) { struct in_addr in; in.s_addr = tcpc->GetrIP(); - Log.Out(Logs::General, Logs::World_Server, "New TCP connection from %s:%d", inet_ntoa(in),tcpc->GetrPort()); + + /* World - Tell what is being connected */ + if (tcpc->GetMode() == EmuTCPConnection::modePacket) { + if (tcpc->GetPacketMode() == EmuTCPConnection::packetModeZone) { + Log.Out(Logs::General, Logs::World_Server, "New Zone Server from %s:%d", inet_ntoa(in), tcpc->GetrPort()); + } + else if (tcpc->GetPacketMode() == EmuTCPConnection::packetModeLauncher) { + Log.Out(Logs::General, Logs::World_Server, "New Launcher from %s:%d", inet_ntoa(in), tcpc->GetrPort()); + } + else if (tcpc->GetPacketMode() == EmuTCPConnection::packetModeUCS) { + Log.Out(Logs::General, Logs::World_Server, "New UCS Connection from %s:%d", inet_ntoa(in), tcpc->GetrPort()); + } + else if (tcpc->GetPacketMode() == EmuTCPConnection::packetModeQueryServ) { + Log.Out(Logs::General, Logs::World_Server, "New QS Connection from %s:%d", inet_ntoa(in), tcpc->GetrPort()); + } + else { + Log.Out(Logs::General, Logs::World_Server, "Unsupported packet mode from %s:%d", inet_ntoa(in), tcpc->GetrPort()); + } + } + console_list.Add(new Console(tcpc)); } diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 580053a3b..abe6e0e18 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -187,12 +187,14 @@ bool ZoneServer::Process() { if (pack->opcode == ServerOP_ZAAuth && pack->size == 16) { uint8 tmppass[16]; MD5::Generate((const uchar*) WorldConfig::get()->SharedKey.c_str(), WorldConfig::get()->SharedKey.length(), tmppass); - if (memcmp(pack->pBuffer, tmppass, 16) == 0) + if (memcmp(pack->pBuffer, tmppass, 16) == 0) { is_authenticated = true; + Log.Out(Logs::Detail, Logs::World_Server, "Zone process connected."); + } else { struct in_addr in; in.s_addr = GetIP(); - Log.Out(Logs::Detail, Logs::World_Server,"Zone authorization failed."); + Log.Out(Logs::General, Logs::Error, "Zone authorization failed."); auto pack = new ServerPacket(ServerOP_ZAAuthFailed); SendPacket(pack); safe_delete(pack); @@ -203,7 +205,7 @@ bool ZoneServer::Process() { else { struct in_addr in; in.s_addr = GetIP(); - Log.Out(Logs::Detail, Logs::World_Server,"Zone authorization failed."); + Log.Out(Logs::General, Logs::Error, "Zone authorization failed."); auto pack = new ServerPacket(ServerOP_ZAAuthFailed); SendPacket(pack); safe_delete(pack); @@ -213,7 +215,7 @@ bool ZoneServer::Process() { } else { - Log.Out(Logs::Detail, Logs::World_Server,"**WARNING** You have not configured a world shared key in your config file. You should add a STRING element to your element to prevent unauthroized zone access."); + Log.Out(Logs::General, Logs::Error, "**WARNING** You have not configured a world shared key in your config file. You should add a STRING element to your element to prevent unauthroized zone access."); is_authenticated = true; } } From c41521c31013b4eb3d6633ee05a85dab876b6b27 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 17 Jul 2016 22:50:00 -0400 Subject: [PATCH 199/693] Fix saving binds on charcreate --- common/database.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index fc26cc636..6ecbb75dd 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -627,9 +627,9 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe /* Save Bind Points */ query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)" " VALUES (%u, %u, %u, %f, %f, %f, %f, %i), " - "(%u, %u, %u, %f, %f, %f, %f, %i), ", - "(%u, %u, %u, %f, %f, %f, %f, %i), ", - "(%u, %u, %u, %f, %f, %f, %f, %i), ", + "(%u, %u, %u, %f, %f, %f, %f, %i), " + "(%u, %u, %u, %f, %f, %f, %f, %i), " + "(%u, %u, %u, %f, %f, %f, %f, %i), " "(%u, %u, %u, %f, %f, %f, %f, %i)", character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading, 0, character_id, pp->binds[1].zoneId, 0, pp->binds[1].x, pp->binds[1].y, pp->binds[1].z, pp->binds[1].heading, 1, From f431e820efa2ae73b62ff82441a291aab6fb23f5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 17 Jul 2016 23:35:18 -0400 Subject: [PATCH 200/693] Optimize Map::LoadV2 a bit Microbenchmarking showed ~33% increase in loading moors Real world testing showed ~48% --- zone/map.cpp | 120 ++++++++++++++++++++------------------------------- 1 file changed, 47 insertions(+), 73 deletions(-) diff --git a/zone/map.cpp b/zone/map.cpp index 0fb1036d5..1558e70d4 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -360,13 +360,13 @@ bool Map::LoadV2(FILE *f) { } std::vector data; - data.resize(data_size); + data.reserve(data_size); if (fread(&data[0], data_size, 1, f) != 1) { return false; } std::vector buffer; - buffer.resize(buffer_size); + buffer.reserve(buffer_size); uint32 v = InflateData(&data[0], data_size, &buffer[0], buffer_size); char *buf = &buffer[0]; @@ -412,7 +412,9 @@ bool Map::LoadV2(FILE *f) { buf += sizeof(float); std::vector verts; + verts.reserve(vert_count); std::vector indices; + indices.reserve(ind_count); for (uint32 i = 0; i < vert_count; ++i) { float x; @@ -428,16 +430,12 @@ bool Map::LoadV2(FILE *f) { z = *(float*)buf; buf += sizeof(float); - glm::vec3 vert(x, y, z); - verts.push_back(vert); + verts.emplace_back(x, y, z); } for (uint32 i = 0; i < ind_count; ++i) { - uint32 index; - index = *(uint32*)buf; + indices.emplace_back(*(uint32 *)buf); buf += sizeof(uint32); - - indices.push_back(index); } for (uint32 i = 0; i < nc_vert_count; ++i) { @@ -460,7 +458,7 @@ bool Map::LoadV2(FILE *f) { uint32 poly_count = *(uint32*)buf; buf += sizeof(uint32); - me->verts.resize(vert_count); + me->verts.reserve(vert_count); for (uint32 j = 0; j < vert_count; ++j) { float x = *(float*)buf; buf += sizeof(float); @@ -469,10 +467,10 @@ bool Map::LoadV2(FILE *f) { float z = *(float*)buf; buf += sizeof(float); - me->verts[j] = glm::vec3(x, y, z); + me->verts.emplace_back(x, y, z); } - me->polys.resize(poly_count); + me->polys.reserve(poly_count); for (uint32 j = 0; j < poly_count; ++j) { uint32 v1 = *(uint32*)buf; buf += sizeof(uint32); @@ -527,6 +525,8 @@ bool Map::LoadV2(FILE *f) { auto &mod_verts = model->verts; for (uint32 j = 0; j < mod_polys.size(); ++j) { auto ¤t_poly = mod_polys[j]; + if (current_poly.vis == 0) + continue; auto v1 = mod_verts[current_poly.v1]; auto v2 = mod_verts[current_poly.v2]; auto v3 = mod_verts[current_poly.v3]; @@ -543,27 +543,13 @@ bool Map::LoadV2(FILE *f) { TranslateVertex(v2, x, y, z); TranslateVertex(v3, x, y, z); - float t = v1.x; - v1.x = v1.y; - v1.y = t; + verts.emplace_back(v1.y, v1.x, v1.z); // x/y swapped + verts.emplace_back(v2.y, v2.x, v2.z); + verts.emplace_back(v3.y, v3.x, v3.z); - t = v2.x; - v2.x = v2.y; - v2.y = t; - - t = v3.x; - v3.x = v3.y; - v3.y = t; - - if (current_poly.vis != 0) { - verts.push_back(v1); - verts.push_back(v2); - verts.push_back(v3); - - indices.push_back((uint32)verts.size() - 3); - indices.push_back((uint32)verts.size() - 2); - indices.push_back((uint32)verts.size() - 1); - } + indices.emplace_back((uint32)verts.size() - 3); + indices.emplace_back((uint32)verts.size() - 2); + indices.emplace_back((uint32)verts.size() - 1); } } @@ -631,6 +617,8 @@ bool Map::LoadV2(FILE *f) { for (size_t k = 0; k < model->polys.size(); ++k) { auto &poly = model->polys[k]; + if (poly.vis == 0) + continue; glm::vec3 v1, v2, v3; v1 = model->verts[poly.v1]; @@ -693,27 +681,13 @@ bool Map::LoadV2(FILE *f) { TranslateVertex(v2, x, y, z); TranslateVertex(v3, x, y, z); - float t = v1.x; - v1.x = v1.y; - v1.y = t; + verts.emplace_back(v1.y, v1.x, v1.z); // x/y swapped + verts.emplace_back(v2.y, v2.x, v2.z); + verts.emplace_back(v3.y, v3.x, v3.z); - t = v2.x; - v2.x = v2.y; - v2.y = t; - - t = v3.x; - v3.x = v3.y; - v3.y = t; - - if (poly.vis != 0) { - verts.push_back(v1); - verts.push_back(v2); - verts.push_back(v3); - - indices.push_back((uint32)verts.size() - 3); - indices.push_back((uint32)verts.size() - 2); - indices.push_back((uint32)verts.size() - 1); - } + indices.emplace_back((uint32)verts.size() - 3); + indices.emplace_back((uint32)verts.size() - 2); + indices.emplace_back((uint32)verts.size() - 1); } } } @@ -722,8 +696,8 @@ bool Map::LoadV2(FILE *f) { uint32 ter_vert_count = ((quads_per_tile + 1) * (quads_per_tile + 1)); std::vector flags; std::vector floats; - flags.resize(ter_quad_count); - floats.resize(ter_vert_count); + flags.reserve(ter_quad_count); + floats.reserve(ter_vert_count); for (uint32 i = 0; i < tile_count; ++i) { bool flat; flat = *(bool*)buf; @@ -759,18 +733,18 @@ bool Map::LoadV2(FILE *f) { float QuadVertex4Z = QuadVertex1Z; uint32 current_vert = (uint32)verts.size() + 3; - verts.push_back(glm::vec3(QuadVertex1X, QuadVertex1Y, QuadVertex1Z)); - verts.push_back(glm::vec3(QuadVertex2X, QuadVertex2Y, QuadVertex2Z)); - verts.push_back(glm::vec3(QuadVertex3X, QuadVertex3Y, QuadVertex3Z)); - verts.push_back(glm::vec3(QuadVertex4X, QuadVertex4Y, QuadVertex4Z)); + verts.emplace_back(QuadVertex1X, QuadVertex1Y, QuadVertex1Z); + verts.emplace_back(QuadVertex2X, QuadVertex2Y, QuadVertex2Z); + verts.emplace_back(QuadVertex3X, QuadVertex3Y, QuadVertex3Z); + verts.emplace_back(QuadVertex4X, QuadVertex4Y, QuadVertex4Z); - indices.push_back(current_vert); - indices.push_back(current_vert - 2); - indices.push_back(current_vert - 1); + indices.emplace_back(current_vert); + indices.emplace_back(current_vert - 2); + indices.emplace_back(current_vert - 1); - indices.push_back(current_vert); - indices.push_back(current_vert - 3); - indices.push_back(current_vert - 2); + indices.emplace_back(current_vert); + indices.emplace_back(current_vert - 3); + indices.emplace_back(current_vert - 2); } else { //read flags @@ -825,7 +799,7 @@ bool Map::LoadV2(FILE *f) { } else { i1 = (uint32)verts.size(); - verts.push_back(glm::vec3(QuadVertex1X, QuadVertex1Y, QuadVertex1Z)); + verts.emplace_back(QuadVertex1X, QuadVertex1Y, QuadVertex1Z); cur_verts[std::make_tuple(QuadVertex1X, QuadVertex1Y, QuadVertex1Z)] = i1; } @@ -836,7 +810,7 @@ bool Map::LoadV2(FILE *f) { } else { i2 = (uint32)verts.size(); - verts.push_back(glm::vec3(QuadVertex2X, QuadVertex2Y, QuadVertex2Z)); + verts.emplace_back(QuadVertex2X, QuadVertex2Y, QuadVertex2Z); cur_verts[std::make_tuple(QuadVertex2X, QuadVertex2Y, QuadVertex2Z)] = i2; } @@ -847,7 +821,7 @@ bool Map::LoadV2(FILE *f) { } else { i3 = (uint32)verts.size(); - verts.push_back(glm::vec3(QuadVertex3X, QuadVertex3Y, QuadVertex3Z)); + verts.emplace_back(QuadVertex3X, QuadVertex3Y, QuadVertex3Z); cur_verts[std::make_tuple(QuadVertex3X, QuadVertex3Y, QuadVertex3Z)] = i3; } @@ -858,17 +832,17 @@ bool Map::LoadV2(FILE *f) { } else { i4 = (uint32)verts.size(); - verts.push_back(glm::vec3(QuadVertex4X, QuadVertex4Y, QuadVertex4Z)); + verts.emplace_back(QuadVertex4X, QuadVertex4Y, QuadVertex4Z); cur_verts[std::make_tuple(QuadVertex4X, QuadVertex4Y, QuadVertex4Z)] = i4; } - indices.push_back(i4); - indices.push_back(i2); - indices.push_back(i3); + indices.emplace_back(i4); + indices.emplace_back(i2); + indices.emplace_back(i3); - indices.push_back(i4); - indices.push_back(i1); - indices.push_back(i2); + indices.emplace_back(i4); + indices.emplace_back(i1); + indices.emplace_back(i2); } } } From aeff31ba7ac8e2811b91b7365a3b2e644da98626 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 18 Jul 2016 13:57:14 -0400 Subject: [PATCH 201/693] Fix error with /setstartcity --- zone/client_packet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index c46fb8936..67d9d600b 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -11964,7 +11964,7 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app) if (!results.Success()) return; - Message(15, "Use \"/startcity #\" to choose a home city from the following list:"); + Message(15, "Use \"/setstartcity #\" to choose a home city from the following list:"); for (auto row = results.begin(); row != results.end(); ++row) { if (atoi(row[1]) != 0) From 84c90715be43df1a4bf8d3aed456d043ceb9f2c8 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Mon, 18 Jul 2016 14:37:21 -0400 Subject: [PATCH 202/693] Reverse checks for voice graft to short curcuit when no pet. --- zone/client.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index bb7403930..732485a60 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -886,7 +886,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s } case 3: { /* Shout */ Mob *sender = this; - if (GetTarget() == GetPet() && GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); @@ -924,7 +924,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s else if(!RuleB(Chat, ServerWideAuction)) { Mob *sender = this; - if (GetTarget() == GetPet() && GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, message); @@ -971,7 +971,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s { Mob *sender = this; - if (GetTarget() == GetPet() && GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, message); @@ -1069,7 +1069,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s #endif Mob* sender = this; - if (GetTarget() == GetPet() && GetPet() && GetPet()->FindType(SE_VoiceGraft)) + if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft)) sender = GetPet(); entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message); From 9349d5d47355cfaa59f54a6ffe70563bffc9a131 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Mon, 18 Jul 2016 15:30:55 -0400 Subject: [PATCH 203/693] Another fix for when BuffDurationPacket breaks client effects on spells. In this case run speed spells like SoW. --- zone/spells.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index e7a090e57..7daa1b050 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5359,6 +5359,19 @@ void Client::SendBuffDurationPacket(Buffs_Struct &buff) // level. sbf->effect = 46; } + else if (IsEffectInSpell(buff.spellid, SE_MovementSpeed)) + { + index = GetSpellEffectIndex(buff.spellid, SE_MovementSpeed); + + // So MovementSpeed spells react to effect values as follows: + // 0- cancels the effect (buff stays up - run speed is normal) + // 1-45 - A formula of change where 1-9 yield about a .1 to .9 + // reduction of the spell effect, 10 yields about the same, and + // 11-45 gets faster very quickly until the effect well exceeds + // any intended max. + // 46 - seems to do nothing - which is what we need. + sbf->effect = 46; + } else if (IsEffectInSpell(buff.spellid, SE_CHA)) { index = GetSpellEffectIndex(buff.spellid, SE_CHA); From ccb5427b45190ed2cf9fe1b94fa358e87a5b1be8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 18 Jul 2016 21:57:25 -0400 Subject: [PATCH 204/693] Make VS debug mode happy This actually hurts microbenchmarking I couldn't get the ModelEntry::polys vector to play nice with benchmarking so it will just be using push_back so I don't have write a new ctor (writing a new ctor and using emplace_back vs push_back were equal) --- zone/map.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zone/map.cpp b/zone/map.cpp index 1558e70d4..f06c590ad 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -360,13 +360,13 @@ bool Map::LoadV2(FILE *f) { } std::vector data; - data.reserve(data_size); + data.resize(data_size); if (fread(&data[0], data_size, 1, f) != 1) { return false; } std::vector buffer; - buffer.reserve(buffer_size); + buffer.resize(buffer_size); uint32 v = InflateData(&data[0], data_size, &buffer[0], buffer_size); char *buf = &buffer[0]; @@ -486,7 +486,7 @@ bool Map::LoadV2(FILE *f) { p.v2 = v2; p.v3 = v3; p.vis = vis; - me->polys[j] = p; + me->polys.push_back(p); } models[name] = std::move(me); @@ -696,8 +696,8 @@ bool Map::LoadV2(FILE *f) { uint32 ter_vert_count = ((quads_per_tile + 1) * (quads_per_tile + 1)); std::vector flags; std::vector floats; - flags.reserve(ter_quad_count); - floats.reserve(ter_vert_count); + flags.resize(ter_quad_count); + floats.resize(ter_vert_count); for (uint32 i = 0; i < tile_count; ++i) { bool flat; flat = *(bool*)buf; From aadc4b5e6bdefdbd12a46cce0c0f015e7613b948 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 20 Jul 2016 14:15:00 -0500 Subject: [PATCH 205/693] Update eqemu_update.pl --- utils/scripts/eqemu_update.pl | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 116c587c5..6d1e32c3a 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -295,6 +295,7 @@ sub show_menu_prompt { 13 => \&do_windows_login_server_setup, 14 => \&remove_duplicate_rule_values, 15 => \&fetch_utility_scripts, + 18 => \&fetch_latest_windows_binaries_bots, 19 => \&do_bots_db_schema_drop, 20 => \&do_update_self, 0 => \&script_exit, @@ -374,6 +375,7 @@ return < Date: Wed, 20 Jul 2016 16:26:58 -0400 Subject: [PATCH 206/693] Add buff level restrictions for pets --- zone/pets.cpp | 7 +++++++ zone/pets.h | 1 + 2 files changed, 8 insertions(+) diff --git a/zone/pets.cpp b/zone/pets.cpp index 23680cd88..28d6bdf91 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -738,3 +738,10 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) { return true; } +bool Pet::CheckSpellLevelRestriction(uint16 spell_id) +{ + auto owner = GetOwner(); + if (owner) + return owner->CheckSpellLevelRestriction(spell_id); + return true; +} diff --git a/zone/pets.h b/zone/pets.h index 32ca00eac..8d14d8a48 100644 --- a/zone/pets.h +++ b/zone/pets.h @@ -40,6 +40,7 @@ class Pet : public NPC { public: Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power); virtual void SetTarget(Mob *mob); + virtual bool CheckSpellLevelRestriction(uint16 spell_id); }; From 527ee56fb20f8dbdf7cd7dc7eefba3321a1fdf2f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 20 Jul 2016 17:49:33 -0400 Subject: [PATCH 207/693] Fix Distance Mod scaling The client clamps the distance between the min/max --- zone/spell_effects.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 70e7118f8..57c1ace64 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -24,6 +24,7 @@ #include "../common/rulesys.h" #include "../common/skills.h" #include "../common/spdat.h" +#include "../common/data_verification.h" #include "quest_parser_collection.h" #include "string_ids.h" @@ -6731,9 +6732,11 @@ void Mob::CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster) else distance = sqrt(range); + distance = EQEmu::Clamp(distance, spells[spell_id].min_dist, spells[spell_id].max_dist); + float dm_range = spells[spell_id].max_dist - spells[spell_id].min_dist; float dm_mod_interval = spells[spell_id].max_dist_mod - spells[spell_id].min_dist_mod; - float dist_from_min = distance - spells[spell_id].min_dist; + float dist_from_min = distance - spells[spell_id].min_dist; float mod = spells[spell_id].min_dist_mod + (dist_from_min * (dm_mod_interval/dm_range)); mod *= 100.0f; From 5f111f159b4c5c24041305804ced4fe2b60dfbe0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 21 Jul 2016 14:05:29 -0400 Subject: [PATCH 208/693] Update comment [skip ci] --- common/spdat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/spdat.h b/common/spdat.h index 84d094bd8..ae31f6817 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -736,7 +736,7 @@ struct SPDat_Spell_Struct /* 181 */ //int pvp_duration; // buffdurationformula for PvP -- PVP_DURATION /* 182 */ //int pvp_duration_cap; // buffduration for PvP -- PVP_DURATION_CAP /* 183 */ //int pcnpc_only_flag; // valid values are 0, 1, and 2 -- PCNPC_ONLY_FLAG -/* 184 */ //bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell -- CAST_NOT_STANDING +/* 184 */ //bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell, this also blocks SE_InterruptCasting from affecting this spell -- CAST_NOT_STANDING /* 185 */ bool can_mgb; // 0=no, -1 or 1 = yes -- CAN_MGB /* 186 */ int dispel_flag; // -- NO_DISPELL /* 187 */ //int npc_category; // -- NPC_MEM_CATEGORY From 1f5dcb69654f3f633b949217a29ff3327ee3f9c4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 21 Jul 2016 20:27:08 -0400 Subject: [PATCH 209/693] Make SE_SpellResistReduction not complain --- zone/spell_effects.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 57c1ace64..bbea43771 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2996,6 +2996,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_PetMeleeMitigation: case SE_SkillProc: case SE_SkillProcSuccess: + case SE_SpellResistReduction: { break; } From 5f588934a9179110c39b689378a33dd839e373e1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 23 Jul 2016 13:55:36 -0400 Subject: [PATCH 210/693] Make decaying spell bonuses not depend on CaclBonuses being called some other way This just sets a flag that will tell us we need to recalc bonuses every tick Before these kind of depended on it being caused some other way --- zone/mob.cpp | 1 + zone/mob.h | 1 + zone/spell_effects.cpp | 55 ++++++++++++++++++++++++++++++------------ 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 7dcbbcb15..580e154e7 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -425,6 +425,7 @@ Mob::Mob(const char* in_name, emoteid = 0; endur_upkeep = false; + degenerating_effects = false; PrimaryAggro = false; AssistAggro = false; npc_assist_cap = 0; diff --git a/zone/mob.h b/zone/mob.h index 841e3a24e..f663e0027 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1277,6 +1277,7 @@ protected: bool last_los_check; bool pseudo_rooted; bool endur_upkeep; + bool degenerating_effects; // true if we have a buff that needs to be recalced every tick // Bind wound Timer bindwound_timer; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index bbea43771..ca3331ced 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3144,10 +3144,23 @@ snare has both of them negative, yet their range should work the same: result = updownsign * (ubase + (caster_level * 4)); break; case 107: - //Used on Reckless Strength, I think it should decay over time - result = updownsign * (ubase + (caster_level / 2)); break; + { + int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - (ticsremaining - 1); + if (ticdif < 0) + ticdif = 0; + result = updownsign * (ubase - ticdif); + degenerating_effects = true; + break; + } case 108: - result = updownsign * (ubase + (caster_level / 3)); break; + { + int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - (ticsremaining - 1); + if (ticdif < 0) + ticdif = 0; + result = updownsign * (ubase - (2 * ticdif)); + degenerating_effects = true; + break; + } case 109: // confirmed 2/6/04 result = updownsign * (ubase + (caster_level / 4)); break; @@ -3192,16 +3205,25 @@ snare has both of them negative, yet their range should work the same: case 119: // confirmed 2/6/04 result = ubase + (caster_level / 8); break; + case 120: + { + int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - (ticsremaining - 1); + if (ticdif < 0) + ticdif = 0; + result = updownsign * (ubase - (5 * ticdif)); + degenerating_effects = true; + break; + } case 121: // corrected 2/6/04 result = ubase + (caster_level / 3); break; case 122: { - // May need to account for duration focus effects - int ticdif = spells[spell_id].buffduration - (ticsremaining - 1); + int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - (ticsremaining - 1); if(ticdif < 0) ticdif = 0; result = updownsign * (ubase - (12 * ticdif)); + degenerating_effects = true; break; } case 123: // added 2/6/04 @@ -3308,11 +3330,12 @@ snare has both of them negative, yet their range should work the same: { // These work like splurt, accept instead of being hard coded to 12, it is formula - 1000. // Formula 1999 seems to have a slightly different effect, so is not included here - int ticdif = spells[spell_id].buffduration - (ticsremaining - 1); + int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - (ticsremaining - 1); if(ticdif < 0) ticdif = 0; result = updownsign * (ubase - ((formula - 1000) * ticdif)); + degenerating_effects = true; } else if((formula >= 2000) && (formula <= 2650)) { @@ -3658,16 +3681,6 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) if (IsClient() && (CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoDAndLater)) CastToClient()->LocateCorpse(); } - case SE_TotalHP: { - if (spell.formula[i] > 1000 && spell.formula[i] < 1999) { - // These formulas can affect Max HP each tick - // Maybe there is a more efficient way to recalculate this for just Max HP each tic... - // CalcBonuses(); - CalcSpellBonuses(&spellbonuses); - CalcMaxHP(); - } - break; - } case SE_DistanceRemoval: { if (spellbonuses.DistanceRemoval) { @@ -3704,6 +3717,14 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) if (!IsValidSpell(buff.spellid)) // if we faded we're no longer valid! break; } + + /* Is this the best place for this? + * Ideally we would only recalc spell bonuses + * but we would also have to call all the Calc functions like Max HP + * so lets just call the main CalcBonuses + */ + if (degenerating_effects) + CalcBonuses(); } // removes the buff in the buff slot 'slot' @@ -4139,6 +4160,8 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) CastToClient()->FastQueuePacket(&outapp); } + // we will eventually call CalcBonuses() even if we skip it right here, so should correct itself if we still have them + degenerating_effects = false; if (iRecalcBonuses) CalcBonuses(); } From 83548ee405b47200b168892cfda89196dd15b0e8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 23 Jul 2016 17:41:16 -0400 Subject: [PATCH 211/693] Fix buff tics This will not fade buffs at 6s :P --- zone/spell_effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ca3331ced..02d51915b 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3394,7 +3394,7 @@ void Mob::BuffProcess() { --buffs[buffs_i].ticsremaining; - if ((buffs[buffs_i].ticsremaining == 0 && !(IsShortDurationBuff(buffs[buffs_i].spellid) || IsBardSong(buffs[buffs_i].spellid))) || buffs[buffs_i].ticsremaining < 0) { + if (buffs[buffs_i].ticsremaining < 0) { Log.Out(Logs::Detail, Logs::Spells, "Buff %d in slot %d has expired. Fading.", buffs[buffs_i].spellid, buffs_i); BuffFadeBySlot(buffs_i); } From cd9a7f1d5dfac1ca211c5a261dc65ebf8ed7e751 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 23 Jul 2016 17:52:30 -0400 Subject: [PATCH 212/693] Cap tic diff to 0 for duration based calcs This will match Splurt with the double 191 --- zone/spell_effects.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 02d51915b..8ad235915 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3145,7 +3145,7 @@ snare has both of them negative, yet their range should work the same: case 107: { - int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - (ticsremaining - 1); + int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - std::max((ticsremaining - 1), 0); if (ticdif < 0) ticdif = 0; result = updownsign * (ubase - ticdif); @@ -3154,7 +3154,7 @@ snare has both of them negative, yet their range should work the same: } case 108: { - int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - (ticsremaining - 1); + int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - std::max((ticsremaining - 1), 0); if (ticdif < 0) ticdif = 0; result = updownsign * (ubase - (2 * ticdif)); @@ -3207,7 +3207,7 @@ snare has both of them negative, yet their range should work the same: result = ubase + (caster_level / 8); break; case 120: { - int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - (ticsremaining - 1); + int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - std::max((ticsremaining - 1), 0); if (ticdif < 0) ticdif = 0; result = updownsign * (ubase - (5 * ticdif)); @@ -3218,7 +3218,7 @@ snare has both of them negative, yet their range should work the same: result = ubase + (caster_level / 3); break; case 122: { - int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - (ticsremaining - 1); + int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - std::max((ticsremaining - 1), 0); if(ticdif < 0) ticdif = 0; @@ -3330,7 +3330,7 @@ snare has both of them negative, yet their range should work the same: { // These work like splurt, accept instead of being hard coded to 12, it is formula - 1000. // Formula 1999 seems to have a slightly different effect, so is not included here - int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - (ticsremaining - 1); + int ticdif = CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration) - std::max((ticsremaining - 1), 0); if(ticdif < 0) ticdif = 0; From f428a8a56a146ef2e888e8395cce84de335cb8b4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 23 Jul 2016 18:07:56 -0400 Subject: [PATCH 213/693] Add a CastWhileInvis check and fix some issues --- common/spdat.cpp | 10 ++++++++++ common/spdat.h | 1 + zone/aa.cpp | 3 ++- zone/client_packet.cpp | 6 ++++-- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index 695b11dab..2b6630dfa 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1111,6 +1111,16 @@ bool IsStackableDot(uint16 spell_id) return IsEffectInSpell(spell_id, SE_CurrentHP) || IsEffectInSpell(spell_id, SE_GravityEffect); } +bool IsCastWhileInvis(uint16 spell_id) +{ + if (!IsValidSpell(spell_id)) + return false; + const auto &spell = spells[spell_id]; + if (spell.sneak) + return true; + return false; +} + uint32 GetNimbusEffect(uint16 spell_id) { if (IsValidSpell(spell_id)) diff --git a/common/spdat.h b/common/spdat.h index ae31f6817..e236d8fbe 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -903,6 +903,7 @@ uint32 GetPartialMeleeRuneAmount(uint32 spell_id); uint32 GetPartialMagicRuneAmount(uint32 spell_id); bool NoDetrimentalSpellAggro(uint16 spell_id); bool IsStackableDot(uint16 spell_id); +bool IsCastWhileInvis(uint16 spell_id); int CalcPetHp(int levelb, int classb, int STA = 75); const char *GetRandPetName(); diff --git a/zone/aa.cpp b/zone/aa.cpp index 2407286fa..d18936956 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1179,7 +1179,8 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { cooldown = 0; } - CommonBreakInvisible(); + if (!IsCastWhileInvis(rank->spell)) + CommonBreakInvisible(); // Bards can cast instant cast AAs while they are casting another song if(spells[rank->spell].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), ALTERNATE_ABILITY_SPELL_SLOT, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 67d9d600b..4bf5b0968 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8550,7 +8550,8 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } if (i == 0) { - CommonBreakInvisible(); // client can't do this for us :( + if (!IsCastWhileInvis(item->Click.Effect)) + CommonBreakInvisible(); // client can't do this for us :( CastSpell(item->Click.Effect, target_id, USE_ITEM_SPELL_SLOT, item->CastTime, 0, 0, slot_id); } } @@ -8578,7 +8579,8 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } if (i == 0) { - CommonBreakInvisible(); // client can't do this for us :( + if (!IsCastWhileInvis(augitem->Click.Effect)) + CommonBreakInvisible(); // client can't do this for us :( CastSpell(augitem->Click.Effect, target_id, USE_ITEM_SPELL_SLOT, augitem->CastTime, 0, 0, slot_id); } } From 343b781e74b3063c8403195ef4e50654c70296c8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 23 Jul 2016 18:40:17 -0400 Subject: [PATCH 214/693] Implement cast_not_standing and fix Cazic Touch No idea why this spell field does this, but that's what the client is doing with it ... --- common/shareddb.cpp | 1 + common/spdat.cpp | 2 +- common/spdat.h | 2 +- zone/attack.cpp | 5 ++++- zone/spell_effects.cpp | 3 ++- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index f35967d50..c9213f3a2 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1688,6 +1688,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].pvpresistcalc=atoi(row[178]); sp[tempid].pvpresistcap=atoi(row[179]); sp[tempid].spell_category=atoi(row[180]); + sp[tempid].cast_not_standing = atoi(row[184]) != 0; sp[tempid].can_mgb=atoi(row[185]); sp[tempid].dispel_flag = atoi(row[186]); sp[tempid].MinResist = atoi(row[189]); diff --git a/common/spdat.cpp b/common/spdat.cpp index 2b6630dfa..572df1afb 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1116,7 +1116,7 @@ bool IsCastWhileInvis(uint16 spell_id) if (!IsValidSpell(spell_id)) return false; const auto &spell = spells[spell_id]; - if (spell.sneak) + if (spell.sneak || spell.cast_not_standing) return true; return false; } diff --git a/common/spdat.h b/common/spdat.h index e236d8fbe..b06c50293 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -736,7 +736,7 @@ struct SPDat_Spell_Struct /* 181 */ //int pvp_duration; // buffdurationformula for PvP -- PVP_DURATION /* 182 */ //int pvp_duration_cap; // buffduration for PvP -- PVP_DURATION_CAP /* 183 */ //int pcnpc_only_flag; // valid values are 0, 1, and 2 -- PCNPC_ONLY_FLAG -/* 184 */ //bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell, this also blocks SE_InterruptCasting from affecting this spell -- CAST_NOT_STANDING +/* 184 */ bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell, this also blocks SE_InterruptCasting from affecting this spell -- CAST_NOT_STANDING /* 185 */ bool can_mgb; // 0=no, -1 or 1 = yes -- CAN_MGB /* 186 */ int dispel_flag; // -- NO_DISPELL /* 187 */ //int npc_category; // -- NPC_MEM_CATEGORY diff --git a/zone/attack.cpp b/zone/attack.cpp index 2f3eb26aa..1c7796f42 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3027,11 +3027,14 @@ bool Mob::CheckDoubleAttack() void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, const EQEmu::skills::SkillType skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special) { // This method is called with skill_used=ABJURE for Damage Shield damage. bool FromDamageShield = (skill_used == EQEmu::skills::SkillAbjuration); + bool ignore_invul = false; + if (IsValidSpell(spell_id)) + ignore_invul = spell_id == 982 || spells[spell_id].cast_not_standing; // cazic touch Log.Out(Logs::Detail, Logs::Combat, "Applying damage %d done by %s with skill %d and spell %d, avoidable? %s, is %sa buff tic in slot %d", damage, attacker?attacker->GetName():"NOBODY", skill_used, spell_id, avoidable?"yes":"no", iBuffTic?"":"not ", buffslot); - if (GetInvul() || DivineAura()) { + if (!ignore_invul && (GetInvul() || DivineAura())) { Log.Out(Logs::Detail, Logs::Combat, "Avoiding %d damage due to invulnerability.", damage); damage = -5; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 8ad235915..45225421b 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3660,7 +3660,8 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) } case SE_InterruptCasting: { if (IsCasting()) { - if (zone->random.Roll(spells[buff.spellid].base[i])) { + const auto &spell = spells[casting_spell_id]; + if (!spell.cast_not_standing && zone->random.Roll(spells[buff.spellid].base[i])) { InterruptSpell(); } } From 37cb9f00f632458daf2a6a66019c80d988fc5c10 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 24 Jul 2016 18:01:14 -0400 Subject: [PATCH 215/693] Removed another unneeded slash --- zone/map.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/zone/map.cpp b/zone/map.cpp index f06c590ad..d266f9834 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -228,7 +228,6 @@ bool Map::CheckLoS(glm::vec3 myloc, glm::vec3 oloc) const { Map *Map::LoadMapFile(std::string file) { std::string filename = Config->MapDir; - filename += "/"; std::transform(file.begin(), file.end(), file.begin(), ::tolower); filename += file; filename += ".map"; From f42b0351fd279e829b2be8f0d7656b62f8e410ce Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 24 Jul 2016 22:24:53 -0400 Subject: [PATCH 216/693] Improve list of skipped effects in stacking code This is the list according to the client (RoF2) Please report any stacking anomalies --- common/spdat.cpp | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ common/spdat.h | 1 + zone/spells.cpp | 24 ++------------- 3 files changed, 80 insertions(+), 22 deletions(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index 572df1afb..74362cea0 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -1121,6 +1121,83 @@ bool IsCastWhileInvis(uint16 spell_id) return false; } +bool IsEffectIgnoredInStacking(int spa) +{ + // this should match RoF2 + switch (spa) { + case SE_SeeInvis: + case SE_DiseaseCounter: + case SE_PoisonCounter: + case SE_Levitate: + case SE_InfraVision: + case SE_UltraVision: + case SE_CurrentHPOnce: + case SE_CurseCounter: + case SE_ImprovedDamage: + case SE_ImprovedHeal: + case SE_SpellResistReduction: + case SE_IncreaseSpellHaste: + case SE_IncreaseSpellDuration: + case SE_IncreaseRange: + case SE_SpellHateMod: + case SE_ReduceReagentCost: + case SE_ReduceManaCost: + case SE_FcStunTimeMod: + case SE_LimitMaxLevel: + case SE_LimitResist: + case SE_LimitTarget: + case SE_LimitEffect: + case SE_LimitSpellType: + case SE_LimitSpell: + case SE_LimitMinDur: + case SE_LimitInstant: + case SE_LimitMinLevel: + case SE_LimitCastTimeMin: + case SE_LimitCastTimeMax: + case SE_StackingCommand_Block: + case SE_StackingCommand_Overwrite: + case SE_PetPowerIncrease: + case SE_SkillDamageAmount: + case SE_ChannelChanceSpells: + case SE_Blank: + case SE_FcDamageAmt: + case SE_SpellDurationIncByTic: + case SE_FcSpellVulnerability: + case SE_FcDamageAmtIncoming: + case SE_FcDamagePctCrit: + case SE_FcDamageAmtCrit: + case SE_ReduceReuseTimer: + case SE_LimitCombatSkills: + case SE_BlockNextSpellFocus: + case SE_SpellTrigger: + case SE_LimitManaMin: + case SE_CorruptionCounter: + case SE_ApplyEffect: + case SE_NegateSpellEffect: + case SE_LimitSpellGroup: + case SE_LimitManaMax: + case SE_FcHealAmt: + case SE_FcHealPctIncoming: + case SE_FcHealAmtIncoming: + case SE_FcHealPctCritIncoming: + case SE_FcHealAmtCrit: + case SE_LimitClass: + case SE_LimitRace: + case SE_FcBaseEffects: + case 415: + case SE_SkillDamageAmount2: + case SE_FcLimitUse: + case SE_FcIncreaseNumHits: + case SE_LimitUseMin: + case SE_LimitUseType: + case SE_GravityEffect: + case 425: + return true; + default: + return false; + } +} + uint32 GetNimbusEffect(uint16 spell_id) { if (IsValidSpell(spell_id)) diff --git a/common/spdat.h b/common/spdat.h index b06c50293..e44bf8e08 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -904,6 +904,7 @@ uint32 GetPartialMagicRuneAmount(uint32 spell_id); bool NoDetrimentalSpellAggro(uint16 spell_id); bool IsStackableDot(uint16 spell_id); bool IsCastWhileInvis(uint16 spell_id); +bool IsEffectIgnoredInStacking(int spa); int CalcPetHp(int levelb, int classb, int STA = 75); const char *GetRandPetName(); diff --git a/zone/spells.cpp b/zone/spells.cpp index 4b12e7c4e..9e8297e3a 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2926,28 +2926,8 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, if(effect1 != effect2) continue; - //Effects which really aren't going to affect stacking. - if(effect1 == SE_CurrentHPOnce || - effect1 == SE_CurseCounter || - effect1 == SE_DiseaseCounter || - effect1 == SE_PoisonCounter){ - continue; - } - - /* - Skip check if effect is SE_Limit* - skip checking effect2 since we know they are equal - */ - if(effect1 == SE_LimitMaxLevel || - effect1 == SE_LimitResist || - effect1 == SE_LimitTarget || - effect1 == SE_LimitEffect || - effect1 == SE_LimitSpellType || - effect1 == SE_LimitSpell || - effect1 == SE_LimitMinDur || - effect1 == SE_LimitInstant || - effect1 == SE_LimitMinLevel || - effect1 == SE_LimitCastTimeMin) + // big ol' list according to the client, wasn't that nice! + if (IsEffectIgnoredInStacking(effect1)) continue; /* From 3963897fe4c9589a3935ce59514527b0dc31f2c2 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 24 Jul 2016 22:53:57 -0400 Subject: [PATCH 217/693] There is a different rez spell depending on race --- common/spdat.cpp | 2 +- zone/client_process.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index 74362cea0..ab9150122 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -704,7 +704,7 @@ bool IsCombatSkill(uint16 spell_id) bool IsResurrectionEffects(uint16 spell_id) { // spell id 756 is Resurrection Effects spell - if(IsValidSpell(spell_id) && spell_id == 756) + if(IsValidSpell(spell_id) && (spell_id == 756 || spell_id == 757)) return true; return false; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index ecab035b6..12c3c8d68 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1016,7 +1016,10 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I if((SpellEffectDescNum == 82) || (SpellEffectDescNum == 39067)) { SetMana(0); SetHP(GetMaxHP()/5); - SpellOnTarget(756, this); // Rezz effects + int rez_eff = 756; + if (GetRace() == BARBARIAN || GetRace() == DWARF || GetRace() == TROLL || GetRace() == OGRE) + rez_eff = 757 + SpellOnTarget(rez_eff, this); // Rezz effects } else { SetMana(GetMaxMana()); From a7fd9312d063d6605c3a9c2b342da6a88d209737 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 24 Jul 2016 22:58:48 -0400 Subject: [PATCH 218/693] Fix syntax error --- zone/client_process.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 12c3c8d68..354d5b6aa 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1018,7 +1018,7 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I SetHP(GetMaxHP()/5); int rez_eff = 756; if (GetRace() == BARBARIAN || GetRace() == DWARF || GetRace() == TROLL || GetRace() == OGRE) - rez_eff = 757 + rez_eff = 757; SpellOnTarget(rez_eff, this); // Rezz effects } else { From bda4fcfb26b37ace2db6ae67ad3c28de7d4b48a0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 25 Jul 2016 16:22:48 -0400 Subject: [PATCH 219/693] Fix up SpellBuff struct Please report any bugs you find. There shouldn't be unless I messed up the struct for a client I didn't throughly test for --- changelog.txt | 5 ++ common/eq_packet_structs.h | 36 ++++----- common/opcode_dispatch.h | 4 +- common/patches/rof.cpp | 70 +++++++++-------- common/patches/rof2.cpp | 74 ++++++++++-------- common/patches/rof2_structs.h | 72 ++++------------- common/patches/rof_structs.h | 72 ++++------------- common/patches/sod.cpp | 36 +++++---- common/patches/sod_structs.h | 32 +++----- common/patches/sof.cpp | 37 +++++---- common/patches/sof_structs.h | 33 +++----- common/patches/titanium.cpp | 42 +++++++++- common/patches/titanium_ops.h | 2 + common/patches/titanium_structs.h | 19 ++--- common/patches/uf.cpp | 61 ++++++++------- common/patches/uf_structs.h | 53 ++++--------- zone/client.h | 2 +- zone/client_packet.cpp | 18 +++-- zone/pets.cpp | 14 ++-- zone/spell_effects.cpp | 2 +- zone/spells.cpp | 124 ++++++++---------------------- zone/zonedb.cpp | 2 +- 22 files changed, 350 insertions(+), 460 deletions(-) diff --git a/changelog.txt b/changelog.txt index efa9b257a..7607bcf14 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 07/25/216 == +mackal: Fix up the SpellBuff struct + - THERE MAYBE BUGS + - there shouldn't though, most of the hackery was from badly named fields causing confusion + == 07/09/2016 == Uleat: Important fix for mob pathing - This should fix failed pathing issues (and high cpu usage for zone.exe) for mobs in affect zones diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 504f8aed3..3252d07cc 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -488,30 +488,28 @@ struct SpawnAppearance_Struct // this is used inside profile struct SpellBuff_Struct { -/*000*/ uint8 slotid; //badly named... seems to be 2 for a real buff, 0 otherwise -/*001*/ uint8 level; +/*000*/ uint8 effect_type; // 0 = no buff, 2 = buff, 4 = inverse affects of buff +/*001*/ uint8 level; /*002*/ uint8 bard_modifier; -/*003*/ uint8 effect; //not real +/*003*/ uint8 unknown003; // MQ2 used to call this "damage shield" -- don't see client referencing it, so maybe server side DS type tracking? -- OSX client calls this "activated" /*004*/ uint32 spellid; -/*008*/ int32 duration; -/*012*/ uint32 counters; -/*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages -/*020*/ +/*008*/ int32 duration; +/*012*/ uint32 counters; // single book keeping value (counters, rune/vie) +/*016*/ uint32 player_id; // caster ID, pretty sure just zone ID +// extra stuff for newer packets +/*020*/ uint32 num_hits; +/*024*/ float y; // referenced by SPA 441 +/*028*/ float x; // unsure if all buffs get them +/*032*/ float z; // as valid data +/*036*/ }; -struct SpellBuffFade_Struct { +struct SpellBuffPacket_Struct { /*000*/ uint32 entityid; -/*004*/ uint8 slot; -/*005*/ uint8 level; -/*006*/ uint8 effect; -/*007*/ uint8 unknown7; -/*008*/ uint32 spellid; -/*012*/ int32 duration; -/*016*/ uint32 num_hits; -/*020*/ uint32 unknown020; //prolly global player ID -/*024*/ uint32 slotid; -/*028*/ uint32 bufffade; -/*032*/ +/*004*/ SpellBuff_Struct buff; +/*040*/ uint32 slotid; +/*044*/ uint32 bufffade; +/*048*/ }; // Underfoot & later struct. diff --git a/common/opcode_dispatch.h b/common/opcode_dispatch.h index a88391bce..496dcdea3 100644 --- a/common/opcode_dispatch.h +++ b/common/opcode_dispatch.h @@ -173,7 +173,7 @@ IN(OP_TradeAcceptClick, TradeAccept_Struct); IN(OP_BoardBoat, EntityId_Struct); //not really the struct, just 4 bytes INz(OP_LeaveBoat); //? IN(OP_RandomReq, RandomReq_Struct); -IN(OP_Buff, SpellBuffFade_Struct); +IN(OP_Buff, SpellBuffPacket_Struct); IN(OP_GMHideMe, SpawnAppearance_Struct); IN(OP_GMNameChange, GMName_Struct); IN(OP_GMKill, GMKill_Struct); @@ -415,7 +415,7 @@ OUTv(OP_SendAATable, SendAA_Struct); OUT(OP_AAAction, UseAA_Struct); OUT(OP_Bazaar, BazaarReturnDone_Struct); //alt:OUT(OP_Bazaar, BazaarWelcome_Struct); -OUT(OP_Buff, SpellBuffFade_Struct); +OUT(OP_Buff, SpellBuffPacket_Struct); OUT(OP_ClickObject, ClickObject_Struct); OUT(OP_ClientUpdate, PlayerPositionUpdateServer_Struct); OUT(OP_SpawnPositionUpdate, SpawnPositionUpdate_Struct); diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 0b45b98e6..4bf8ed63d 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -405,22 +405,31 @@ namespace RoF ENCODE(OP_Buff) { - ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); - SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Live); + ENCODE_LENGTH_EXACT(SpellBuffPacket_Struct); + SETUP_DIRECT_ENCODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); OUT(entityid); - eq->unknown004 = 2; - //eq->level = 80; - //eq->effect = 0; - OUT(level); - OUT(effect); - eq->unknown007 = 0; - eq->unknown008 = 1.0f; - OUT(spellid); - OUT(duration); - eq->playerId = 0x7cde; - OUT(slotid); - OUT(num_hits); + OUT(buff.effect_type); + OUT(buff.level); + // just so we're 100% sure we get a 1.0f ... + eq->buff.bard_modifier = emu->buff.bard_modifier == 10 ? 1.0f : emu->buff.bard_modifier / 10.0f; + OUT(buff.spellid); + OUT(buff.duration); + OUT(buff.player_id); + OUT(buff.num_hits); + OUT(buff.y); + OUT(buff.x); + OUT(buff.z); + uint16 buffslot = emu->slotid; + // Not sure if this is needs amending for RoF yet. + if (buffslot >= 25) + { + buffslot += 17; + } + + // TODO: implement slot_data stuff + eq->slotid = buffslot; + if (emu->bufffade == 1) eq->bufffade = 1; else @@ -432,10 +441,10 @@ namespace RoF { outapp = new EQApplicationPacket(OP_BuffCreate, 29); outapp->WriteUInt32(emu->entityid); - outapp->WriteUInt32(0x0271); // Unk + outapp->WriteUInt32(0); // tic timer outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ? outapp->WriteUInt16(1); // 1 buff in this packet - outapp->WriteUInt32(emu->slotid); + outapp->WriteUInt32(buffslot); outapp->WriteUInt32(0xffffffff); // SpellID (0xffff to remove) outapp->WriteUInt32(0); // Duration outapp->WriteUInt32(0); // ? @@ -2274,31 +2283,32 @@ namespace RoF for (uint32 r = 0; r < BUFF_COUNT; r++) { float instrument_mod = 0.0f; - uint8 slotid = emu->buffs[r].slotid; + uint8 effect_type = emu->buffs[r].effect_type; uint32 player_id = emu->buffs[r].player_id;; if (emu->buffs[r].spellid != 0xFFFF && emu->buffs[r].spellid != 0) { instrument_mod = 1.0f + (emu->buffs[r].bard_modifier - 10) / 10.0f; - slotid = 2; + effect_type = 2; player_id = 0x000717fd; } else { - slotid = 0; + effect_type = 0; } - outapp->WriteUInt8(0); // Had this as slot, but always appears to be 0 on live. + // this is different than the client struct for some reason :P + // missing a few things, shuffled around + outapp->WriteUInt8(0); // this is an unknown outapp->WriteFloat(instrument_mod); outapp->WriteUInt32(player_id); outapp->WriteUInt8(0); outapp->WriteUInt32(emu->buffs[r].counters); - //outapp->WriteUInt8(emu->buffs[r].bard_modifier); outapp->WriteUInt32(emu->buffs[r].duration); outapp->WriteUInt8(emu->buffs[r].level); outapp->WriteUInt32(emu->buffs[r].spellid); - outapp->WriteUInt32(slotid); // Only ever seen 2 + outapp->WriteUInt8(effect_type); // Only ever seen 2 + outapp->WriteUInt32(emu->buffs[r].num_hits); outapp->WriteUInt32(0); - outapp->WriteUInt8(0); outapp->WriteUInt32(emu->buffs[r].counters); // Appears twice ? for (uint32 j = 0; j < 44; ++j) @@ -4290,15 +4300,15 @@ namespace RoF DECODE(OP_Buff) { - DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct_Live); - SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Live); + DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct); + SETUP_DIRECT_DECODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); IN(entityid); - //IN(slot); - IN(level); - IN(effect); - IN(spellid); - IN(duration); + IN(buff.effect_type); + IN(buff.level); + IN(buff.unknown003); + IN(buff.spellid); + IN(buff.duration); IN(slotid); IN(bufffade); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 57f823ce2..41d34a50a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -474,22 +474,34 @@ namespace RoF2 ENCODE(OP_Buff) { - ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); - SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Live); + ENCODE_LENGTH_EXACT(SpellBuffPacket_Struct); + SETUP_DIRECT_ENCODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); OUT(entityid); - eq->unknown004 = 2; - //eq->level = 80; - //eq->effect = 0; - OUT(level); - OUT(effect); - eq->unknown007 = 0; - eq->unknown008 = 1.0f; - OUT(spellid); - OUT(duration); - eq->playerId = 0x7cde; - OUT(slotid); - OUT(num_hits); + OUT(buff.effect_type); + OUT(buff.level); + // just so we're 100% sure we get a 1.0f ... + eq->buff.bard_modifier = emu->buff.bard_modifier == 10 ? 1.0f : emu->buff.bard_modifier / 10.0f; + OUT(buff.spellid); + OUT(buff.duration); + OUT(buff.player_id); + OUT(buff.num_hits); + OUT(buff.y); + OUT(buff.x); + OUT(buff.z); + uint16 buffslot = emu->slotid; + // Not sure if this is needs amending for RoF2 yet. + if (buffslot >= 25) + { + buffslot += 17; + } + // TODO: We should really just deal with these "server side" + // so we can have clients not limited to other clients. + // This fixes discs, songs were changed to 20 + if (buffslot == 54) + buffslot = 62; + eq->slotid = buffslot; + // TODO: implement slot_data stuff if (emu->bufffade == 1) eq->bufffade = 1; else @@ -501,10 +513,10 @@ namespace RoF2 { outapp = new EQApplicationPacket(OP_BuffCreate, 29); outapp->WriteUInt32(emu->entityid); - outapp->WriteUInt32(0x0271); // Unk + outapp->WriteUInt32(0); // tic timer outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ? outapp->WriteUInt16(1); // 1 buff in this packet - outapp->WriteUInt32(emu->slotid); + outapp->WriteUInt32(buffslot); outapp->WriteUInt32(0xffffffff); // SpellID (0xffff to remove) outapp->WriteUInt32(0); // Duration outapp->WriteUInt32(0); // ? @@ -2358,31 +2370,33 @@ namespace RoF2 for (uint32 r = 0; r < BUFF_COUNT; r++) { float instrument_mod = 0.0f; - uint8 slotid = emu->buffs[r].slotid; + uint8 effect_type = emu->buffs[r].effect_type; uint32 player_id = emu->buffs[r].player_id;; if (emu->buffs[r].spellid != 0xFFFF && emu->buffs[r].spellid != 0) { instrument_mod = 1.0f + (emu->buffs[r].bard_modifier - 10) / 10.0f; - slotid = 2; + effect_type = 2; player_id = 0x000717fd; } else { - slotid = 0; + effect_type = 0; } - outapp->WriteUInt8(0); // Had this as slot, but always appears to be 0 on live. + + // this is different than the client struct for some reason :P + // missing a few things, shuffled around + outapp->WriteUInt8(0); // this is an unknown outapp->WriteFloat(instrument_mod); outapp->WriteUInt32(player_id); outapp->WriteUInt8(0); outapp->WriteUInt32(emu->buffs[r].counters); - //outapp->WriteUInt8(emu->buffs[r].bard_modifier); outapp->WriteUInt32(emu->buffs[r].duration); outapp->WriteUInt8(emu->buffs[r].level); outapp->WriteUInt32(emu->buffs[r].spellid); - outapp->WriteUInt32(slotid); // Only ever seen 2 + outapp->WriteUInt8(effect_type); // Only ever seen 2 + outapp->WriteUInt32(emu->buffs[r].num_hits); outapp->WriteUInt32(0); - outapp->WriteUInt8(0); outapp->WriteUInt32(emu->buffs[r].counters); // Appears twice ? for (uint32 j = 0; j < 44; ++j) @@ -4526,15 +4540,15 @@ namespace RoF2 DECODE(OP_Buff) { - DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct_Live); - SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Live); + DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct); + SETUP_DIRECT_DECODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); IN(entityid); - //IN(slot); - IN(level); - IN(effect); - IN(spellid); - IN(duration); + IN(buff.effect_type); + IN(buff.level); + IN(buff.unknown003); + IN(buff.spellid); + IN(buff.duration); IN(slotid); IN(bufffade); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 0b638660e..61cbb0d0b 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -719,69 +719,31 @@ struct SpawnAppearance_Struct struct SpellBuff_Struct { -/*000*/ uint8 slotid; // badly named... seems to be 2 for a real buff, 0 otherwise -/*001*/ float unknown004; // Seen 1 for no buff -/*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages -/*009*/ uint32 unknown016; -/*013*/ uint8 bard_modifier; -/*014*/ int32 duration; -/*018*/ uint8 level; -/*019*/ uint32 spellid; -/*023*/ uint32 counters; -/*027*/ uint8 unknown0028[53]; -/*080*/ -}; - -struct SpellBuff_Struct_Old -{ -/*000*/ uint8 slotid; // badly named... seems to be 2 for a real buff, 0 otherwise -/*001*/ uint8 level; -/*002*/ uint8 bard_modifier; -/*003*/ uint8 effect; // not real -/*004*/ float unknown004; // Seen 1 for no buff -/*008*/ uint32 spellid; -/*012*/ int32 duration; -/*016*/ uint32 unknown016; -/*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages -/*024*/ uint32 counters; -/*028*/ uint8 unknown0028[60]; +/*000*/ uint8 effect_type; // 0 = no buff, 2 = buff, 4 = inverse affects of buff +/*001*/ uint8 level; // Seen 1 for no buff +/*002*/ uint8 unknown002; //pretty sure padding now +/*003*/ uint8 unknown003; // MQ2 used to call this "damage shield" -- don't see client referencing it, so maybe server side DS type tracking? +/*004*/ float bard_modifier; +/*008*/ uint32 spellid; +/*012*/ uint32 duration; +/*016*/ uint32 player_id; // caster ID, pretty sure just zone ID +/*020*/ uint32 num_hits; +/*024*/ float y; // referenced by SPA 441 +/*028*/ float x; // unsure if all buffs get them +/*032*/ float z; // as valid data +/*036*/ uint32 unknown036; +/*040*/ int32 slot_data[12]; // book keeping stuff per slot (counters, rune/vie) /*088*/ }; -// Not functional yet, but this is what the packet looks like on Live -struct SpellBuffFade_Struct_Live { -/*000*/ uint32 entityid; // Player id who cast the buff -/*004*/ uint8 unknown004; -/*005*/ uint8 level; -/*006*/ uint8 effect; -/*007*/ uint8 unknown007; -/*008*/ float unknown008; -/*012*/ uint32 spellid; -/*016*/ int32 duration; -/*020*/ uint32 playerId; // Global player ID? -/*024*/ uint32 num_hits; -/*028*/ uint8 unknown0028[64]; +struct SpellBuffPacket_Struct { +/*000*/ uint32 entityid; // Player id who cast the buff +/*004*/ SpellBuff_Struct buff; /*092*/ uint32 slotid; /*096*/ uint32 bufffade; /*100*/ }; -struct SpellBuffFade_Struct { -/*000*/ uint32 entityid; -/*004*/ uint8 slot; -/*005*/ uint8 level; -/*006*/ uint8 effect; -/*007*/ uint8 unknown7; -/*008*/ uint32 spellid; -/*012*/ int32 duration; -/*016*/ uint32 num_hits; -/*020*/ uint32 unknown020; // Global player ID? -/*024*/ uint32 playerId; // Player id who cast the buff -/*028*/ uint32 slotid; -/*032*/ uint32 bufffade; -/*036*/ -}; - struct BuffRemoveRequest_Struct { /*00*/ uint32 SlotID; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 9846b1e9e..9c5aa8ab8 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -708,69 +708,31 @@ struct SpawnAppearance_Struct struct SpellBuff_Struct { -/*000*/ uint8 slotid; // badly named... seems to be 2 for a real buff, 0 otherwise -/*001*/ float unknown004; // Seen 1 for no buff -/*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages -/*009*/ uint32 unknown016; -/*013*/ uint8 bard_modifier; -/*014*/ int32 duration; -/*018*/ uint8 level; -/*019*/ uint32 spellid; -/*023*/ uint32 counters; -/*027*/ uint8 unknown0028[53]; -/*080*/ -}; - -struct SpellBuff_Struct_Old -{ -/*000*/ uint8 slotid; // badly named... seems to be 2 for a real buff, 0 otherwise -/*001*/ uint8 level; -/*002*/ uint8 bard_modifier; -/*003*/ uint8 effect; // not real -/*004*/ float unknown004; // Seen 1 for no buff -/*008*/ uint32 spellid; -/*012*/ int32 duration; -/*016*/ uint32 unknown016; -/*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages -/*024*/ uint32 counters; -/*028*/ uint8 unknown0028[60]; +/*000*/ uint8 effect_type; // 0 = no buff, 2 = buff, 4 = inverse affects of buff +/*001*/ uint8 level; // Seen 1 for no buff +/*002*/ uint8 unknown002; //pretty sure padding now +/*003*/ uint8 unknown003; // MQ2 used to call this "damage shield" -- don't see client referencing it, so maybe server side DS type tracking? +/*004*/ float bard_modifier; +/*008*/ uint32 spellid; +/*012*/ uint32 duration; +/*016*/ uint32 player_id; // caster ID, pretty sure just zone ID +/*020*/ uint32 num_hits; +/*024*/ float y; // referenced by SPA 441 +/*028*/ float x; // unsure if all buffs get them +/*032*/ float z; // as valid data +/*036*/ uint32 unknown036; +/*040*/ int32 slot_data[12]; // book keeping stuff per slot (counters, rune/vie) /*088*/ }; -// Not functional yet, but this is what the packet looks like on Live -struct SpellBuffFade_Struct_Live { -/*000*/ uint32 entityid; // Player id who cast the buff -/*004*/ uint8 unknown004; -/*005*/ uint8 level; -/*006*/ uint8 effect; -/*007*/ uint8 unknown007; -/*008*/ float unknown008; -/*012*/ uint32 spellid; -/*016*/ int32 duration; -/*020*/ uint32 playerId; // Global player ID? -/*024*/ uint32 num_hits; -/*028*/ uint8 unknown0028[64]; +struct SpellBuffPacket_Struct { +/*000*/ uint32 entityid; // Player id who cast the buff +/*004*/ SpellBuff_Struct buff; /*092*/ uint32 slotid; /*096*/ uint32 bufffade; /*100*/ }; -struct SpellBuffFade_Struct { -/*000*/ uint32 entityid; -/*004*/ uint8 slot; -/*005*/ uint8 level; -/*006*/ uint8 effect; -/*007*/ uint8 unknown7; -/*008*/ uint32 spellid; -/*012*/ int32 duration; -/*016*/ uint32 num_hits; -/*020*/ uint32 unknown020; // Global player ID? -/*024*/ uint32 playerId; // Player id who cast the buff -/*028*/ uint32 slotid; -/*032*/ uint32 bufffade; -/*036*/ -}; - struct BuffRemoveRequest_Struct { /*00*/ uint32 SlotID; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 58997a9a5..c148a02be 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -301,16 +301,17 @@ namespace SoD ENCODE(OP_Buff) { - ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); - SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); + ENCODE_LENGTH_EXACT(SpellBuffPacket_Struct); + SETUP_DIRECT_ENCODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); OUT(entityid); - OUT(slot); - OUT(level); - OUT(effect); - //eq->unknown7 = 10; - OUT(spellid); - OUT(duration); + OUT(buff.effect_type); + OUT(buff.level); + OUT(buff.bard_modifier); + OUT(buff.spellid); + OUT(buff.duration); + OUT(buff.counters); + OUT(buff.player_id); OUT(slotid); OUT(bufffade); @@ -1602,10 +1603,10 @@ namespace SoD OUT(thirst_level); OUT(hunger_level); for (r = 0; r < structs::BUFF_COUNT; r++) { - OUT(buffs[r].slotid); + OUT(buffs[r].effect_type); OUT(buffs[r].level); OUT(buffs[r].bard_modifier); - OUT(buffs[r].effect); + OUT(buffs[r].unknown003); OUT(buffs[r].spellid); OUT(buffs[r].duration); OUT(buffs[r].counters); @@ -2907,15 +2908,16 @@ namespace SoD DECODE(OP_Buff) { - DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct); - SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); + DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct); + SETUP_DIRECT_DECODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); IN(entityid); - IN(slot); - IN(level); - IN(effect); - IN(spellid); - IN(duration); + IN(buff.effect_type); + IN(buff.level); + IN(buff.bard_modifier); + IN(buff.spellid); + IN(buff.duration); + IN(buff.counters) IN(slotid); IN(bufffade); diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 11331552a..191d048e9 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -563,32 +563,22 @@ struct SpawnAppearance_Struct // this is used inside profile struct SpellBuff_Struct { -/*000*/ uint8 slotid; //badly named... seems to be 2 for a real buff, 0 otherwise -/*001*/ uint8 level; -/*002*/ uint8 bard_modifier; -/*003*/ uint8 effect; //not real -/*004*/ uint32 spellid; -/*008*/ int32 duration; -/*012*/ uint32 counters; -/*016*/ uint32 unknown004; //Might need to be swapped with player_id -/*020*/ uint32 player_id; //'global' ID of the caster, for wearoff messages +/*000*/ uint8 effect_type; // 0 = no buff, 2 = buff, 4 = inverse affects of buff +/*001*/ uint8 level; // Seen 1 for no buff +/*002*/ uint8 bard_modifier; +/*003*/ uint8 unknown003; // MQ2 used to call this "damage shield" -- don't see client referencing it, so maybe server side DS type tracking? +/*004*/ uint32 spellid; +/*008*/ uint32 duration; +/*012*/ uint32 counters; +/*016*/ uint32 unknown016; +/*020*/ uint32 player_id; // caster ID, pretty sure just zone ID /*024*/ - - }; -struct SpellBuffFade_Struct { +struct SpellBuffPacket_Struct { /*000*/ uint32 entityid; -/*004*/ uint8 slot; -/*005*/ uint8 level; -/*006*/ uint8 effect; -/*007*/ uint8 unknown7; -/*008*/ uint32 spellid; -/*012*/ int32 duration; -/*016*/ uint32 unknown016; -/*020*/ uint32 unknown020; //prolly global player ID -/*024*/ uint32 playerId; // Player id who cast the buff +/*004*/ SpellBuff_Struct buff; /*028*/ uint32 slotid; /*032*/ uint32 bufffade; /*036*/ diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index c2402f1e2..7984debd9 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -283,16 +283,17 @@ namespace SoF ENCODE(OP_Buff) { - ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); - SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); + ENCODE_LENGTH_EXACT(SpellBuffPacket_Struct); + SETUP_DIRECT_ENCODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); OUT(entityid); - OUT(slot); - OUT(level); - OUT(effect); - //eq->unknown7 = 10; - OUT(spellid); - OUT(duration); + OUT(buff.effect_type); + OUT(buff.level); + OUT(buff.bard_modifier); + OUT(buff.spellid); + OUT(buff.duration); + OUT(buff.counters); + OUT(buff.player_id); OUT(slotid); OUT(bufffade); @@ -1258,10 +1259,10 @@ namespace SoF OUT(thirst_level); OUT(hunger_level); for (r = 0; r < structs::BUFF_COUNT; r++) { - OUT(buffs[r].slotid); + OUT(buffs[r].effect_type); OUT(buffs[r].level); OUT(buffs[r].bard_modifier); - OUT(buffs[r].effect); + OUT(buffs[r].unknown003); OUT(buffs[r].spellid); OUT(buffs[r].duration); OUT(buffs[r].counters); @@ -2343,15 +2344,17 @@ namespace SoF DECODE(OP_Buff) { - DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct); - SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); + DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct); + SETUP_DIRECT_DECODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); IN(entityid); - IN(slot); - IN(level); - IN(effect); - IN(spellid); - IN(duration); + IN(buff.effect_type); + IN(buff.level); + IN(buff.bard_modifier); + IN(buff.spellid); + IN(buff.duration); + IN(buff.counters); + IN(buff.player_id); IN(slotid); IN(bufffade); diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 881259e3e..86dc91e14 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -542,32 +542,23 @@ struct SpawnAppearance_Struct // this is used inside profile struct SpellBuff_Struct { -/*000*/ uint8 slotid; //badly named... seems to be 2 for a real buff, 0 otherwise -/*001*/ uint8 level; -/*002*/ uint8 bard_modifier; -/*003*/ uint8 effect; //not real -/*004*/ uint32 spellid; -/*008*/ int32 duration; -/*012*/ uint32 counters; -/*016*/ uint32 unknown004; //Might need to be swapped with player_id -/*020*/ uint32 player_id; //'global' ID of the caster, for wearoff messages +/*000*/ uint8 effect_type; // 0 = no buff, 2 = buff, 4 = inverse affects of buff +/*001*/ uint8 level; // Seen 1 for no buff +/*002*/ uint8 bard_modifier; +/*003*/ uint8 unknown003; // MQ2 used to call this "damage shield" -- don't see client referencing it, so maybe server side DS type tracking? +/*004*/ uint32 spellid; +/*008*/ uint32 duration; +/*012*/ uint32 counters; +/*016*/ uint32 unknown016; +/*020*/ uint32 player_id; // caster ID, pretty sure just zone ID + /*024*/ - - }; -struct SpellBuffFade_Struct { +struct SpellBuffPacket_Struct { /*000*/ uint32 entityid; -/*004*/ uint8 slot; -/*005*/ uint8 level; -/*006*/ uint8 effect; -/*007*/ uint8 unknown7; -/*008*/ uint32 spellid; -/*012*/ int32 duration; -/*016*/ uint32 unknown016; -/*020*/ uint32 unknown020; //prolly global player ID -/*024*/ uint32 playerId; // Player id who cast the buff +/*004*/ SpellBuff_Struct buff; /*028*/ uint32 slotid; /*032*/ uint32 bufffade; /*036*/ diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 849f898f7..919267132 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -254,6 +254,25 @@ namespace Titanium FINISH_ENCODE(); } + ENCODE(OP_Buff) + { + ENCODE_LENGTH_EXACT(SpellBuffPacket_Struct); + SETUP_DIRECT_ENCODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); + + OUT(entityid); + OUT(buff.effect_type); + OUT(buff.level); + OUT(buff.bard_modifier); + OUT(buff.spellid); + OUT(buff.duration); + OUT(buff.counters); + OUT(buff.player_id); + OUT(slotid); + OUT(bufffade); + + FINISH_ENCODE(); + } + ENCODE(OP_ChannelMessage) { EQApplicationPacket *in = *p; @@ -945,10 +964,10 @@ namespace Titanium OUT(thirst_level); OUT(hunger_level); for (r = 0; r < structs::BUFF_COUNT; r++) { - OUT(buffs[r].slotid); + OUT(buffs[r].effect_type); OUT(buffs[r].level); OUT(buffs[r].bard_modifier); - OUT(buffs[r].effect); + OUT(buffs[r].unknown003); OUT(buffs[r].spellid); OUT(buffs[r].duration); OUT(buffs[r].counters); @@ -1688,6 +1707,25 @@ namespace Titanium FINISH_DIRECT_DECODE(); } + DECODE(OP_Buff) + { + DECODE_LENGTH_EXACT(SpellBuffPacket_Struct); + SETUP_DIRECT_DECODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); + + IN(entityid); + IN(buff.effect_type); + IN(buff.level); + IN(buff.bard_modifier); + IN(buff.spellid); + IN(buff.duration); + IN(buff.counters); + IN(buff.player_id); + IN(slotid); + IN(bufffade); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_CastSpell) { DECODE_LENGTH_EXACT(structs::CastSpell_Struct); diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index be61ea692..f878fbd76 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -24,6 +24,7 @@ E(OP_AdventureMerchantSell) E(OP_ApplyPoison) E(OP_BazaarSearch) E(OP_BecomeTrader) +E(OP_Buff) E(OP_ChannelMessage) E(OP_CharInventory) E(OP_Damage) @@ -74,6 +75,7 @@ E(OP_ZoneSpawns) D(OP_AdventureMerchantSell) D(OP_ApplyPoison) D(OP_AugmentItem) +D(OP_Buff) D(OP_CastSpell) D(OP_ChannelMessage) D(OP_CharacterCreate) diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 997aecc5d..caa798da0 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -473,26 +473,19 @@ struct SpawnAppearance_Struct // this is used inside profile struct SpellBuff_Struct { -/*000*/ uint8 slotid; //badly named... seems to be 2 for a real buff, 0 otherwise +/*000*/ uint8 effect_type; // 0 = no buff, 2 = buff, 4 = inverse affects of buff /*001*/ uint8 level; /*002*/ uint8 bard_modifier; -/*003*/ uint8 effect; //not real +/*003*/ uint8 unknown003; // MQ2 used to call this "damage shield" -- don't see client referencing it, so maybe server side DS type tracking? /*004*/ uint32 spellid; /*008*/ int32 duration; -/*012*/ uint32 counters; -/*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages +/*012*/ uint32 counters; // single book keeping value (counters, rune/vie) +/*016*/ uint32 player_id; // caster ID, pretty sure just zone ID }; -struct SpellBuffFade_Struct { +struct SpellBuffPacket_Struct { /*000*/ uint32 entityid; -/*004*/ uint8 slot; -/*005*/ uint8 level; -/*006*/ uint8 effect; -/*007*/ uint8 unknown7; -/*008*/ uint32 spellid; -/*012*/ int32 duration; -/*016*/ uint32 unknown016; -/*020*/ uint32 unknown020; //prolly global player ID +/*004*/ SpellBuff_Struct buff; /*024*/ uint32 slotid; /*028*/ uint32 bufffade; /*032*/ diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index d613c8867..a65e9cef0 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -363,20 +363,29 @@ namespace UF ENCODE(OP_Buff) { - ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); - SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Underfoot); + ENCODE_LENGTH_EXACT(SpellBuffPacket_Struct); + SETUP_DIRECT_ENCODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); OUT(entityid); - OUT(slot); - OUT(level); - OUT(effect); - //eq->unknown7 = 10; - OUT(spellid); - OUT(duration); - OUT(slotid); + OUT(buff.effect_type); + OUT(buff.level); + // just so we're 100% sure we get a 1.0f ... + eq->buff.bard_modifier = emu->buff.bard_modifier == 10 ? 1.0f : emu->buff.bard_modifier / 10.0f; + OUT(buff.spellid); + OUT(buff.duration); + OUT(buff.num_hits); + uint16 buffslot = emu->slotid; + if (buffslot >= 25 && buffslot < 37) + { + buffslot += 5; + } + else if (buffslot >= 37) + { + buffslot += 14; + } + // TODO: implement slot_data stuff + eq->slotid = buffslot; 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(); } @@ -1862,22 +1871,22 @@ namespace UF { if (emu->buffs[r].spellid != 0xFFFF && emu->buffs[r].spellid != 0) { - eq->buffs[r].unknown004 = 0x3f800000; - eq->buffs[r].slotid = 2; + eq->buffs[r].bard_modifier = 1.0f; + eq->buffs[r].effect_type= 2; eq->buffs[r].player_id = 0x000717fd; } else { - eq->buffs[r].slotid = 0; + eq->buffs[r].effect_type = 0; } - //OUT(buffs[r].slotid); + OUT(buffs[r].effect_type); OUT(buffs[r].level); - //OUT(buffs[r].bard_modifier); - //OUT(buffs[r].effect); + OUT(buffs[r].bard_modifier); + OUT(buffs[r].unknown003); OUT(buffs[r].spellid); OUT(buffs[r].duration); - OUT(buffs[r].counters); - //OUT(buffs[r].player_id); + OUT(buffs[r].num_hits); + OUT(buffs[r].player_id); } for (r = 0; r < MAX_PP_DISCIPLINES; r++) { OUT(disciplines.values[r]); @@ -3216,15 +3225,15 @@ namespace UF DECODE(OP_Buff) { - DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct_Underfoot); - SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Underfoot); + DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct); + SETUP_DIRECT_DECODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); IN(entityid); - IN(slot); - IN(level); - IN(effect); - IN(spellid); - IN(duration); + IN(buff.effect_type); + IN(buff.level); + IN(buff.unknown003); + IN(buff.spellid); + IN(buff.duration); IN(slotid); IN(bufffade); diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index f4f78f1c5..932213827 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -566,55 +566,28 @@ struct SpawnAppearance_Struct // Size 76 (was 24) struct SpellBuff_Struct { -/*000*/ uint8 slotid; // badly named... seems to be 2 for a real buff, 0 otherwise -/*001*/ uint8 level; -/*002*/ uint8 bard_modifier; -/*003*/ uint8 effect; // not real -/*004*/ uint32 unknown004; // Seen 1 for no buff -/*008*/ uint32 spellid; -/*012*/ int32 duration; -/*016*/ uint32 unknown016; -/*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages -/*024*/ uint32 counters; -/*028*/ uint8 unknown0028[48]; -/*076*/ +/*000*/ uint8 effect_type; // 0 = no buff, 2 = buff, 4 = inverse affects of buff +/*001*/ uint8 level; // Seen 1 for no buff +/*002*/ uint8 unknown002; //pretty sure padding now +/*003*/ uint8 unknown003; // MQ2 used to call this "damage shield" -- don't see client referencing it, so maybe server side DS type tracking? +/*004*/ float bard_modifier; +/*008*/ uint32 spellid; +/*012*/ uint32 duration; +/*016*/ uint32 num_hits; +/*020*/ uint32 player_id; // caster ID, pretty sure just zone ID +/*024*/ uint32 unknown036; +/*028*/ int32 slot_data[12]; // book keeping stuff per slot (counters, rune/vie) }; // Not functional yet, but this is what the packet looks like on Underfoot -struct SpellBuffFade_Struct_Underfoot { +struct SpellBuffPacket_Struct { /*000*/ uint32 entityid; // Player id who cast the buff -/*004*/ uint8 slot; -/*005*/ uint8 level; -/*006*/ uint8 effect; -/*007*/ uint8 unknown7; -/*008*/ float unknown008; -/*012*/ uint32 spellid; -/*016*/ int32 duration; -/*020*/ uint32 num_hits; -/*024*/ uint32 playerId; // Global player ID? -/*028*/ uint32 unknown020; -/*032*/ uint8 unknown0028[48]; +/*004*/ SpellBuff_Struct buff; /*080*/ uint32 slotid; /*084*/ uint32 bufffade; /*088*/ }; -struct SpellBuffFade_Struct { -/*000*/ uint32 entityid; -/*004*/ uint8 slot; -/*005*/ uint8 level; -/*006*/ uint8 effect; -/*007*/ uint8 unknown7; -/*008*/ uint32 spellid; -/*012*/ int32 duration; -/*016*/ uint32 unknown016; -/*020*/ uint32 unknown020; // Global player ID? -/*024*/ uint32 playerId; // Player id who cast the buff -/*028*/ uint32 slotid; -/*032*/ uint32 bufffade; -/*036*/ -}; - #if 0 struct BuffIconEntry_Struct { /*000*/ uint32 buff_slot; diff --git a/zone/client.h b/zone/client.h index 9bd22f815..1d30b97ce 100644 --- a/zone/client.h +++ b/zone/client.h @@ -918,7 +918,7 @@ 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(Buffs_Struct &buff); + void SendBuffDurationPacket(Buffs_Struct &buff, int slot); void SendBuffNumHitPacket(Buffs_Struct &buff, int slot); void ProcessInspectRequest(Client* requestee, Client* requester); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 4bf5b0968..39574274a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1463,22 +1463,24 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (buffs[i].spellid != SPELL_UNKNOWN) { m_pp.buffs[i].spellid = buffs[i].spellid; m_pp.buffs[i].bard_modifier = buffs[i].instrument_mod; - m_pp.buffs[i].slotid = 2; + m_pp.buffs[i].effect_type = 2; m_pp.buffs[i].player_id = 0x2211; m_pp.buffs[i].level = buffs[i].casterlevel; - m_pp.buffs[i].effect = 0; + m_pp.buffs[i].unknown003 = 0; m_pp.buffs[i].duration = buffs[i].ticsremaining; m_pp.buffs[i].counters = buffs[i].counters; + m_pp.buffs[i].num_hits = buffs[i].numhits; } else { m_pp.buffs[i].spellid = SPELLBOOK_UNKNOWN; m_pp.buffs[i].bard_modifier = 10; - m_pp.buffs[i].slotid = 0; + m_pp.buffs[i].effect_type = 0; m_pp.buffs[i].player_id = 0; m_pp.buffs[i].level = 0; - m_pp.buffs[i].effect = 0; + m_pp.buffs[i].unknown003 = 0; m_pp.buffs[i].duration = 0; m_pp.buffs[i].counters = 0; + m_pp.buffs[i].num_hits = 0; } } } @@ -3833,15 +3835,15 @@ void Client::Handle_OP_BoardBoat(const EQApplicationPacket *app) void Client::Handle_OP_Buff(const EQApplicationPacket *app) { - if (app->size != sizeof(SpellBuffFade_Struct)) + if (app->size != sizeof(SpellBuffPacket_Struct)) { - Log.Out(Logs::General, Logs::Error, "Size mismatch in OP_Buff. expected %i got %i", sizeof(SpellBuffFade_Struct), app->size); + Log.Out(Logs::General, Logs::Error, "Size mismatch in OP_Buff. expected %i got %i", sizeof(SpellBuffPacket_Struct), app->size); DumpPacket(app); return; } - SpellBuffFade_Struct* sbf = (SpellBuffFade_Struct*)app->pBuffer; - uint32 spid = sbf->spellid; + SpellBuffPacket_Struct* sbf = (SpellBuffPacket_Struct*)app->pBuffer; + uint32 spid = sbf->buff.spellid; Log.Out(Logs::Detail, Logs::Spells, "Client requested that buff with spell id %d be canceled.", spid); //something about IsDetrimentalSpell() crashes this portion of code.. diff --git a/zone/pets.cpp b/zone/pets.cpp index 28d6bdf91..e527d80ce 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -579,10 +579,10 @@ void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) { for (int i=0; i < GetPetMaxTotalSlots(); i++) { if (buffs[i].spellid != SPELL_UNKNOWN) { pet_buffs[i].spellid = buffs[i].spellid; - pet_buffs[i].slotid = i+1; + pet_buffs[i].effect_type = i+1; pet_buffs[i].duration = buffs[i].ticsremaining; pet_buffs[i].level = buffs[i].casterlevel; - pet_buffs[i].effect = 10; + pet_buffs[i].bard_modifier = 10; pet_buffs[i].counters = buffs[i].counters; pet_buffs[i].bard_modifier = buffs[i].instrument_mod; } @@ -590,7 +590,7 @@ void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) { pet_buffs[i].spellid = SPELL_UNKNOWN; pet_buffs[i].duration = 0; pet_buffs[i].level = 0; - pet_buffs[i].effect = 0; + pet_buffs[i].bard_modifier = 10; pet_buffs[i].counters = 0; } } @@ -623,10 +623,10 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { else { buffs[i].spellid = SPELL_UNKNOWN; pet_buffs[i].spellid = 0xFFFFFFFF; - pet_buffs[i].slotid = 0; + pet_buffs[i].effect_type = 0; pet_buffs[i].level = 0; pet_buffs[i].duration = 0; - pet_buffs[i].effect = 0; + pet_buffs[i].bard_modifier = 0; } } for (int j1=0; j1 < GetPetMaxTotalSlots(); j1++) { @@ -648,10 +648,10 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { case SE_Illusion: buffs[j1].spellid = SPELL_UNKNOWN; pet_buffs[j1].spellid = SPELLBOOK_UNKNOWN; - pet_buffs[j1].slotid = 0; + pet_buffs[j1].effect_type = 0; pet_buffs[j1].level = 0; pet_buffs[j1].duration = 0; - pet_buffs[j1].effect = 0; + pet_buffs[j1].bard_modifier = 0; x1 = EFFECT_COUNT; break; // We can't send appearance packets yet, put down at CompleteConnect diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 45225421b..0209ba4df 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3413,7 +3413,7 @@ void Mob::BuffProcess() { if(buffs[buffs_i].UpdateClient == true) { - CastToClient()->SendBuffDurationPacket(buffs[buffs_i]); + CastToClient()->SendBuffDurationPacket(buffs[buffs_i], buffs_i); // Hack to get UF to play nicer, RoF seems fine without it if (CastToClient()->ClientVersion() == EQEmu::versions::ClientVersion::UF && buffs[buffs_i].numhits > 0) CastToClient()->SendBuffNumHitPacket(buffs[buffs_i], buffs_i); diff --git a/zone/spells.cpp b/zone/spells.cpp index 9e8297e3a..ab6c5d48e 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4797,17 +4797,17 @@ void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message) { EQApplicationPacket* outapp; - outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffFade_Struct)); - SpellBuffFade_Struct* sbf = (SpellBuffFade_Struct*) outapp->pBuffer; + outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffPacket_Struct)); + SpellBuffPacket_Struct* sbf = (SpellBuffPacket_Struct*) outapp->pBuffer; - sbf->entityid=GetID(); + sbf->entityid = GetID(); // i dont know why but this works.. for now - sbf->slot=2; + sbf->buff.effect_type = 2; // sbf->slot=m_pp.buffs[slot_id].slotid; // sbf->level=m_pp.buffs[slot_id].level; // sbf->effect=m_pp.buffs[slot_id].effect; - sbf->spellid=spell_id; - sbf->slotid=slot_id; + sbf->buff.spellid = spell_id; + sbf->slotid = slot_id; sbf->bufffade = 1; #if EQDEBUG >= 11 printf("Sending SBF 1 from server:\n"); @@ -4820,7 +4820,7 @@ void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message) sbf->level=0; sbf->slot=0; */ - sbf->spellid=0xffffffff; + sbf->buff.spellid = 0xffffffff; #if EQDEBUG >= 11 printf("Sending SBF 2 from server:\n"); DumpPacket(outapp); @@ -4838,7 +4838,6 @@ void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message) QueuePacket(outapp); safe_delete(outapp); } - } void Client::MemSpell(uint16 spell_id, int slot, bool update_client) @@ -5274,99 +5273,36 @@ 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(Buffs_Struct &buff) +void Client::SendBuffDurationPacket(Buffs_Struct &buff, int slot) { EQApplicationPacket* outapp; - outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffFade_Struct)); - SpellBuffFade_Struct* sbf = (SpellBuffFade_Struct*) outapp->pBuffer; - int index; + outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffPacket_Struct)); + SpellBuffPacket_Struct* sbf = (SpellBuffPacket_Struct*) outapp->pBuffer; sbf->entityid = GetID(); - sbf->slot = 2; - sbf->spellid = buff.spellid; - sbf->slotid = 0; - sbf->level = buff.casterlevel > 0 ? buff.casterlevel : GetLevel(); - // We really don't know what to send as sbf->effect. - // The code used to send level (and still does for cases we don't know) - // - // The fixes below address known issues with sending level in this field. - // Typically, when the packet is sent, or when the user - // next does something on the UI that causes an update (like opening a - // pack), the stats updated by the spell in question get corrupted. - // - // The values were determined by trial and error. I could not find a - // pattern or find a field in spells_new that would work. + sbf->buff.effect_type = 2; - sbf->effect=sbf->level; - - if (IsEffectInSpell(buff.spellid, SE_TotalHP)) - { - // If any of the lower 6 bits are set, the GUI changes MAX_HP AGAIN. - // If its set to 0 the effect is cancelled. - // 128 seems to work (ie: change only duration). - sbf->effect = 128; - } - else if (IsEffectInSpell(buff.spellid, SE_CurrentHP)) - { - // This is mostly a problem when we try and update duration on a - // dot or a hp->mana conversion. Zero cancels the effect - // Sending teh actual change again seems to work. - index = GetSpellEffectIndex(buff.spellid, SE_CurrentHP); - sbf->effect = abs(spells[buff.spellid].base[index]); - } - else if (IsEffectInSpell(buff.spellid, SE_SeeInvis)) - { - // 10 seems to not break SeeInvis spells. Level, - // which is what the old client sends breaks the client at at - // least level 9, maybe more. - sbf->effect = 10; - } - else if (IsEffectInSpell(buff.spellid, SE_ArmorClass) || - IsEffectInSpell(buff.spellid, SE_ResistFire) || - IsEffectInSpell(buff.spellid, SE_ResistCold) || - IsEffectInSpell(buff.spellid, SE_ResistPoison) || - IsEffectInSpell(buff.spellid, SE_ResistDisease) || - IsEffectInSpell(buff.spellid, SE_ResistMagic) || - IsEffectInSpell(buff.spellid, SE_STR) || - IsEffectInSpell(buff.spellid, SE_STA) || - IsEffectInSpell(buff.spellid, SE_DEX) || - IsEffectInSpell(buff.spellid, SE_WIS) || - IsEffectInSpell(buff.spellid, SE_INT) || - IsEffectInSpell(buff.spellid, SE_AGI)) - { - // This seems to work. Previosly stats got corrupted when sending - // level. - sbf->effect = 46; - } - else if (IsEffectInSpell(buff.spellid, SE_MovementSpeed)) - { - index = GetSpellEffectIndex(buff.spellid, SE_MovementSpeed); - - // So MovementSpeed spells react to effect values as follows: - // 0- cancels the effect (buff stays up - run speed is normal) - // 1-45 - A formula of change where 1-9 yield about a .1 to .9 - // reduction of the spell effect, 10 yields about the same, and - // 11-45 gets faster very quickly until the effect well exceeds - // any intended max. - // 46 - seems to do nothing - which is what we need. - sbf->effect = 46; - } - else if (IsEffectInSpell(buff.spellid, SE_CHA)) - { - index = GetSpellEffectIndex(buff.spellid, SE_CHA); - sbf->effect = abs(spells[buff.spellid].base[index]); - // Only use this valie if its not a spacer. - if (sbf->effect != 0) - { - // Same as other stats, need this to prevent a double update. - sbf->effect = 46; - } - } + sbf->buff.level = buff.casterlevel > 0 ? buff.casterlevel : GetLevel(); + sbf->buff.bard_modifier = buff.instrument_mod; + sbf->buff.spellid = buff.spellid; + sbf->buff.duration = buff.ticsremaining; + if (buff.dot_rune) + sbf->buff.counters = buff.dot_rune; + else if (buff.magic_rune) + sbf->buff.counters = buff.magic_rune; + else if (buff.melee_rune) + sbf->buff.counters = buff.melee_rune; + else if (buff.counters) + sbf->buff.counters = buff.counters; + sbf->buff.player_id = buff.casterid; + sbf->buff.num_hits = buff.numhits; + sbf->buff.y = buff.caston_y; + sbf->buff.x = buff.caston_x; + sbf->buff.z = buff.caston_z; + sbf->slotid = slot; sbf->bufffade = 0; - sbf->duration = buff.ticsremaining; - sbf->num_hits = buff.numhits; FastQueuePacket(&outapp); } @@ -5496,7 +5432,7 @@ void Mob::BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration) buffs[i].ticsremaining = newDuration; if(IsClient()) { - CastToClient()->SendBuffDurationPacket(buffs[i]); + CastToClient()->SendBuffDurationPacket(buffs[i], i); } } } diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 1c37d4689..d0c80f37f 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3305,7 +3305,7 @@ void ZoneDatabase::LoadPetInfo(Client *client) pi->Buffs[slot_id].spellid = spell_id; pi->Buffs[slot_id].level = caster_level; pi->Buffs[slot_id].player_id = caster_id; - pi->Buffs[slot_id].slotid = 2; // Always 2 in buffs struct for real buffs + pi->Buffs[slot_id].effect_type = 2; // Always 2 in buffs struct for real buffs pi->Buffs[slot_id].duration = ticsremaining; pi->Buffs[slot_id].counters = counters; From 11e017ccb9206e2015c00ba0980306abe0867c6a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 25 Jul 2016 16:37:27 -0400 Subject: [PATCH 220/693] Fix bard mod in PP for UF --- common/patches/uf.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index a65e9cef0..80a266ebe 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1871,17 +1871,17 @@ namespace UF { if (emu->buffs[r].spellid != 0xFFFF && emu->buffs[r].spellid != 0) { - eq->buffs[r].bard_modifier = 1.0f; + eq->buffs[r].bard_modifier = 1.0f + (emu->buffs[r].bard_modifier - 10) / 10.0f; eq->buffs[r].effect_type= 2; eq->buffs[r].player_id = 0x000717fd; } else { eq->buffs[r].effect_type = 0; + eq->buffs[r].bard_modifier = 1.0f; } OUT(buffs[r].effect_type); OUT(buffs[r].level); - OUT(buffs[r].bard_modifier); OUT(buffs[r].unknown003); OUT(buffs[r].spellid); OUT(buffs[r].duration); From 7674b3a077d28dabe351b6ab7cba1a29379fcdc3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 26 Jul 2016 16:25:19 -0400 Subject: [PATCH 221/693] Fix some same spell stacking issues --- zone/spells.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index ab6c5d48e..670ba45b4 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2763,12 +2763,26 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, // Same Spells and dot exemption is set to 1 or spell is Manaburn if (spellid1 == spellid2) { - if (IsStackableDot(spellid1) && caster1 != caster2) { // same caster can refresh + bool stackable_dot = IsStackableDot(spellid1); + if (stackable_dot && caster1 != caster2) { // same caster can refresh Log.Out(Logs::Detail, Logs::Spells, "Blocking spell due to dot stacking exemption."); return -1; } else if (spellid1 == 2751) { Log.Out(Logs::Detail, Logs::Spells, "Blocking spell because manaburn does not stack with itself."); return -1; + } else if (!stackable_dot) { + if (caster_level1 > caster_level2) { // cur buff higher level than new + if (IsEffectInSpell(spellid1, SE_ImprovedTaunt)) { + Log.Out(Logs::Detail, Logs::Spells, "SE_ImprovedTaunt level exception, overwriting."); + return 1; + } else { + Log.Out(Logs::Detail, Logs::Spells, "Spells the same but existing is higher level, stopping."); + return -1; + } + } else { + Log.Out(Logs::Detail, Logs::Spells, "Spells the same but newer is higher level, overwriting."); + return 1; + } } } From de5170c5cb0c0a2d4234dfdfa09894cd07fb58f5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 26 Jul 2016 17:10:06 -0400 Subject: [PATCH 222/693] Fix mana burn --- zone/spells.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 670ba45b4..877bb19a9 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2761,16 +2761,8 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, Log.Out(Logs::Detail, Logs::Spells, "Check Stacking on old %s (%d) @ lvl %d (by %s) vs. new %s (%d) @ lvl %d (by %s)", sp1.name, spellid1, caster_level1, (caster1==nullptr)?"Nobody":caster1->GetName(), sp2.name, spellid2, caster_level2, (caster2==nullptr)?"Nobody":caster2->GetName()); - // Same Spells and dot exemption is set to 1 or spell is Manaburn - if (spellid1 == spellid2) { - bool stackable_dot = IsStackableDot(spellid1); - if (stackable_dot && caster1 != caster2) { // same caster can refresh - Log.Out(Logs::Detail, Logs::Spells, "Blocking spell due to dot stacking exemption."); - return -1; - } else if (spellid1 == 2751) { - Log.Out(Logs::Detail, Logs::Spells, "Blocking spell because manaburn does not stack with itself."); - return -1; - } else if (!stackable_dot) { + if (spellid1 == spellid2 ) { + if (!IsStackableDot(spellid1) && !IsEffectInSpell(spellid1, SE_ManaBurn)) { // mana burn spells we need to use the stacking command blocks live actually checks those first, we should probably rework to that too if (caster_level1 > caster_level2) { // cur buff higher level than new if (IsEffectInSpell(spellid1, SE_ImprovedTaunt)) { Log.Out(Logs::Detail, Logs::Spells, "SE_ImprovedTaunt level exception, overwriting."); @@ -2780,9 +2772,12 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, return -1; } } else { - Log.Out(Logs::Detail, Logs::Spells, "Spells the same but newer is higher level, overwriting."); + Log.Out(Logs::Detail, Logs::Spells, "Spells the same but newer is higher or equal level, overwriting."); return 1; } + } else if (spellid1 == 2751) { + Log.Out(Logs::Detail, Logs::Spells, "Blocking spell because manaburn does not stack with itself."); + return -1; } } From 345f3d630162344f676922b412b9c419b17696b6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 27 Jul 2016 19:58:24 -0400 Subject: [PATCH 223/693] Fix Tit OP_Buff decode --- common/patches/titanium.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 919267132..98ece403c 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1709,7 +1709,7 @@ namespace Titanium DECODE(OP_Buff) { - DECODE_LENGTH_EXACT(SpellBuffPacket_Struct); + DECODE_LENGTH_EXACT(structs::SpellBuffPacket_Struct); SETUP_DIRECT_DECODE(SpellBuffPacket_Struct, structs::SpellBuffPacket_Struct); IN(entityid); From 84db0ec2c5dd3f2fa9e48d501109ed1a16369652 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 28 Jul 2016 22:50:06 -0400 Subject: [PATCH 224/693] Zone MMF Implementation (for map files) --- CMakeLists.txt | 6 + changelog.txt | 14 +- utils/scripts/convert_maps_to_mmfs.pl | 34 ++++ zone/map.cpp | 261 +++++++++++++++++++++++++- zone/map.h | 11 ++ zone/net.cpp | 21 +++ zone/raycast_mesh.cpp | 254 +++++++++++++++++++++++++ zone/raycast_mesh.h | 6 + 8 files changed, 605 insertions(+), 2 deletions(-) create mode 100644 utils/scripts/convert_maps_to_mmfs.pl diff --git a/CMakeLists.txt b/CMakeLists.txt index 494959cbc..ec126b241 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ #EQEMU_BUILD_LUA #EQEMU_SANITIZE_LUA_LIBS #EQEMU_BUILD_CLIENT_FILES +#EQEMU_USE_MAP_MMFS #EQEMU_MAP_DIR #We set a fairly new version (as of 2013) because I found finding perl was a bit... buggy on older ones @@ -275,6 +276,11 @@ IF(EQEMU_BUILD_LUA) ADD_DEFINITIONS(-DLUA_EQEMU) ENDIF(EQEMU_BUILD_LUA) +OPTION(EQEMU_USE_MAP_MMFS "Create and use Zone Map MMF files." OFF) +IF(EQEMU_USE_MAP_MMFS) + ADD_DEFINITIONS(-DUSE_MAP_MMFS) +ENDIF(EQEMU_USE_MAP_MMFS) + SET(EQEMU_MAP_DIR "./Maps" CACHE STRING "The dir that maps, water maps, and paths are located in.") ADD_DEFINITIONS(-DEQDEBUG=${EQEMU_DEBUG_LEVEL}) diff --git a/changelog.txt b/changelog.txt index 7607bcf14..f1af1009a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,18 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- -== 07/25/216 == +== 07/28/2016 == +Uleat: Implemented zone memory-mapped file usage + - Zone map files are converted to pre-loaded binary files, bypassing the (sometimes) time-consuming raw data transform process + - There are three ways to convert files: + -- Do nothing! The zone bootup process will check for a mmf file and load it, if found, or create it after the 'normal' transform process is complete + -- Use the command line option: zone convert_map .map (for singular conversions) + -- Drop the 'convert_maps_to_mmfs.pl' into your server directory and execute it for a batch conversion + -- Note: Any zone maps not pre-converted will be processed once a zone is booted up that does not have one + - To enable this feature, you must have the 'USE_MAP_MMFS' option checked in cmake and have built binaries on that + - To disable this feature, or if you encouter problems, disable the 'USE_MAP_MMFS' option and rebuild your binaries + - This feature will test the validity of your zlib library. If you get errors/crashes upon conversion, then your zlib1.dll is most likely suspect (check our forum for solutions) + +== 07/25/2016 == mackal: Fix up the SpellBuff struct - THERE MAYBE BUGS - there shouldn't though, most of the hackery was from badly named fields causing confusion diff --git a/utils/scripts/convert_maps_to_mmfs.pl b/utils/scripts/convert_maps_to_mmfs.pl new file mode 100644 index 000000000..4c68c7e18 --- /dev/null +++ b/utils/scripts/convert_maps_to_mmfs.pl @@ -0,0 +1,34 @@ +#!/usr/bin/perl + +########################################################### +#::: Automatic (Map-to-MMF) Conversion Script +#::: Author: Uleat +#::: Purpose: To convert existing zone maps to memory-mapped files +########################################################### + +use Config; + +print("\n"); +print("Zone Map-to-MMF Batch convertor\n"); +print("===============================\n"); +print("\n"); + +if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } +if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } +print("Operating System is: $Config{osname}\n"); +print("\n"); + +opendir(D, "maps") || die "Can't find directory maps: $!\n"; +my @mapfiles = grep { /\.map$/ && !/_lit/ } readdir(D); +closedir(D); + +foreach my $mapfile (@mapfiles) { + my $result = "Unknown action..\n"; + print("processing map: '$mapfile'\n"); + if($OS eq "Windows"){ $result = `zone convert_map $mapfile`; } + if($OS eq "Linux"){ $result = `./zone convert_map $mapfile`; } + print("-- $result"); +} + +print("\n"); +print("Batch processing complete\n") diff --git a/zone/map.cpp b/zone/map.cpp index d266f9834..5ae79e8ef 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -12,6 +12,48 @@ #include #include + +uint32 EstimateDeflateBuffer(uint32_t len) { + z_stream zstream; + memset(&zstream, 0, sizeof(zstream)); + + zstream.zalloc = Z_NULL; + zstream.zfree = Z_NULL; + zstream.opaque = Z_NULL; + if (deflateInit(&zstream, Z_FINISH) != Z_OK) + return 0; + + return deflateBound(&zstream, len); +} + +uint32_t DeflateData(const char *buffer, uint32_t len, char *out_buffer, uint32_t out_len_max) { + z_stream zstream; + memset(&zstream, 0, sizeof(zstream)); + int zerror; + + zstream.next_in = const_cast(reinterpret_cast(buffer)); + zstream.avail_in = len; + zstream.zalloc = Z_NULL; + zstream.zfree = Z_NULL; + zstream.opaque = Z_NULL; + deflateInit(&zstream, Z_FINISH); + + zstream.next_out = reinterpret_cast(out_buffer); + zstream.avail_out = out_len_max; + zerror = deflate(&zstream, Z_FINISH); + + if (zerror == Z_STREAM_END) + { + deflateEnd(&zstream); + return (uint32_t)zstream.total_out; + } + else + { + zerror = deflateEnd(&zstream); + return 0; + } +} + uint32 InflateData(const char* buffer, uint32 len, char* out_buffer, uint32 out_len_max) { z_stream zstream; int zerror = 0; @@ -241,7 +283,16 @@ Map *Map::LoadMapFile(std::string file) { return nullptr; } -bool Map::Load(std::string filename) { +#ifdef USE_MAP_MMFS +bool Map::Load(std::string filename, bool force_mmf_overwrite) +{ + if (LoadMMF(filename, force_mmf_overwrite)) + return true; +#else +bool Map::Load(std::string filename) +{ +#endif /*USE_MAP_MMFS*/ + FILE *f = fopen(filename.c_str(), "rb"); if(f) { uint32 version; @@ -253,10 +304,22 @@ bool Map::Load(std::string filename) { if(version == 0x01000000) { bool v = LoadV1(f); fclose(f); + +#ifdef USE_MAP_MMFS + if (v) + return SaveMMF(filename, force_mmf_overwrite); +#endif /*USE_MAP_MMFS*/ + return v; } else if(version == 0x02000000) { bool v = LoadV2(f); fclose(f); + +#ifdef USE_MAP_MMFS + if (v) + return SaveMMF(filename, force_mmf_overwrite); +#endif /*USE_MAP_MMFS*/ + return v; } else { fclose(f); @@ -897,3 +960,199 @@ void Map::TranslateVertex(glm::vec3 &v, float tx, float ty, float tz) { v.y = v.y + ty; v.z = v.z + tz; } + +#ifdef USE_MAP_MMFS +inline void strip_map_extension(std::string& map_file_name) +{ + auto ext_off = map_file_name.find(".map"); + if (ext_off != std::string::npos) + map_file_name.erase(ext_off, strlen(".map")); +} + +inline bool add_mmf_extension(std::string& mmf_file_name) +{ + if (mmf_file_name.empty()) + return false; + + mmf_file_name.append(".mmf"); + size_t dot_check = std::count(mmf_file_name.begin(), mmf_file_name.end(), '.'); + + return (dot_check == 1); +} + +bool Map::LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite) +{ + if (force_mmf_overwrite) + return false; + + std::string mmf_file_name = map_file_name; + strip_map_extension(mmf_file_name); + if (!add_mmf_extension(mmf_file_name)) { + Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s'", mmf_file_name.c_str()); + return false; + } + + FILE *f = fopen(mmf_file_name.c_str(), "rb"); + if (!f) { + Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - could not open file", mmf_file_name.c_str()); + return false; + } + + uint32 file_version; + if (fread(&file_version, sizeof(uint32), 1, f) != 1) { + fclose(f); + Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - f@file_version", mmf_file_name.c_str()); + return false; + } + + uint32 rm_buffer_size; + if (fread(&rm_buffer_size, sizeof(uint32), 1, f) != 1) { + fclose(f); + Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - f@rm_buffer_size", mmf_file_name.c_str()); + return false; + } + + uint32 rm_buffer_crc32; + if (fread(&rm_buffer_crc32, sizeof(uint32), 1, f) != 1) { + fclose(f); + Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - f@rm_buffer_crc32", mmf_file_name.c_str()); + return false; + } + if (rm_buffer_crc32 != /*crc32_check*/ 0) { + fclose(f); + Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - bad rm_buffer checksum", mmf_file_name.c_str()); + return false; + } + + uint32 mmf_buffer_size; + if (fread(&mmf_buffer_size, sizeof(uint32), 1, f) != 1) { + fclose(f); + Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - f@mmf_buffer_size", mmf_file_name.c_str()); + return false; + } + + std::vector mmf_buffer(mmf_buffer_size); + if (fread(mmf_buffer.data(), mmf_buffer_size, 1, f) != 1) { + fclose(f); + Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - f@mmf_buffer", mmf_file_name.c_str()); + return false; + } + + fclose(f); + + std::vector rm_buffer(rm_buffer_size); + uint32 v = InflateData(mmf_buffer.data(), mmf_buffer_size, rm_buffer.data(), rm_buffer_size); + + if (imp) { + imp->rm->release(); + imp->rm = nullptr; + } + else { + imp = new impl; + } + + bool load_success = false; + imp->rm = loadRaycastMesh(rm_buffer, load_success); + if (imp->rm && !load_success) { + imp->rm->release(); + imp->rm = nullptr; + } + + if (!imp->rm) { + delete imp; + imp = nullptr; + Log.Out(Logs::General, Logs::Zone_Server, "Failed to load Map MMF file: '%s' - null RaycastMesh", mmf_file_name.c_str()); + return false; + } + + return true; +} + +bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) +{ + if (!imp || !imp->rm) { + Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file - No implementation (map_file_name: '%s')", map_file_name.c_str()); + return false; + } + + std::string mmf_file_name = map_file_name; + strip_map_extension(mmf_file_name); + if (!add_mmf_extension(mmf_file_name)) { + Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s'", mmf_file_name.c_str()); + return false; + } + + FILE* f = fopen(mmf_file_name.c_str(), "rb"); + if (f) { + fclose(f); + if (!force_mmf_overwrite) + return true; + } + + std::vector rm_buffer; // size set in MyRaycastMesh::serialize() + serializeRaycastMesh(imp->rm, rm_buffer); + if (rm_buffer.empty()) { + Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - empty RaycastMesh buffer", mmf_file_name.c_str()); + return false; + } + + uint32 rm_buffer_size = rm_buffer.size(); + uint32 mmf_buffer_size = EstimateDeflateBuffer(rm_buffer.size()); + + std::vector mmf_buffer(mmf_buffer_size); + + mmf_buffer_size = DeflateData(rm_buffer.data(), rm_buffer.size(), mmf_buffer.data(), mmf_buffer.size()); + if (!mmf_buffer_size) { + Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - null MMF buffer size", mmf_file_name.c_str()); + return false; + } + + f = fopen(mmf_file_name.c_str(), "wb"); + if (!f) { + Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - could not open file", mmf_file_name.c_str()); + return false; + } + + uint32 file_version = 0; + if (fwrite(&file_version, sizeof(uint32), 1, f) != 1) { + fclose(f); + std::remove(mmf_file_name.c_str()); + Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - f@file_version", mmf_file_name.c_str()); + return false; + } + + if (fwrite(&rm_buffer_size, sizeof(uint32), 1, f) != 1) { + fclose(f); + std::remove(mmf_file_name.c_str()); + Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - f@rm_buffer_size", mmf_file_name.c_str()); + return false; + } + + uint32 rm_buffer_crc32 = 0; + if (fwrite(&rm_buffer_crc32, sizeof(uint32), 1, f) != 1) { + fclose(f); + std::remove(mmf_file_name.c_str()); + Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - f@rm_buffer_crc32", mmf_file_name.c_str()); + return false; + } + + if (fwrite(&mmf_buffer_size, sizeof(uint32), 1, f) != 1) { + fclose(f); + std::remove(mmf_file_name.c_str()); + Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - f@mmf_buffer_size", mmf_file_name.c_str()); + return false; + } + + if (fwrite(mmf_buffer.data(), mmf_buffer_size, 1, f) != 1) { + fclose(f); + std::remove(mmf_file_name.c_str()); + Log.Out(Logs::General, Logs::Zone_Server, "Failed to save Map MMF file: '%s' - f@mmf_buffer", mmf_file_name.c_str()); + return false; + } + + fclose(f); + + return true; +} + +#endif /*USE_MAP_MMFS*/ diff --git a/zone/map.h b/zone/map.h index 5d1b08618..35b5baeda 100644 --- a/zone/map.h +++ b/zone/map.h @@ -42,7 +42,13 @@ public: bool LineIntersectsZone(glm::vec3 start, glm::vec3 end, float step, glm::vec3 *result) const; bool LineIntersectsZoneNoZLeaps(glm::vec3 start, glm::vec3 end, float step_mag, glm::vec3 *result) const; bool CheckLoS(glm::vec3 myloc, glm::vec3 oloc) const; + +#ifdef USE_MAP_MMFS + bool Load(std::string filename, bool force_mmf_overwrite = false); +#else bool Load(std::string filename); +#endif + static Map *LoadMapFile(std::string file); private: void RotateVertex(glm::vec3 &v, float rx, float ry, float rz); @@ -51,6 +57,11 @@ private: bool LoadV1(FILE *f); bool LoadV2(FILE *f); +#ifdef USE_MAP_MMFS + bool LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite); + bool SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite); +#endif /*USE_MAP_MMFS*/ + struct impl; impl *imp; }; diff --git a/zone/net.cpp b/zone/net.cpp index 0f6ad0bbe..25d6f65df 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -116,6 +116,27 @@ int main(int argc, char** argv) { Log.LoadLogSettingsDefaults(); set_exception_handler(); + +#ifdef USE_MAP_MMFS + if (argc == 3 && strcasecmp(argv[1], "convert_map") == 0) { + if (!ZoneConfig::LoadConfig()) + return 1; + Config = ZoneConfig::get(); + + std::string mapfile = argv[2]; + std::transform(mapfile.begin(), mapfile.end(), mapfile.begin(), ::tolower); + std::string filename = Config->MapDir; + filename += mapfile; + + auto m = new Map(); + auto success = m->Load(filename, true); + delete m; + std::cout << mapfile.c_str() << " conversion " << (success ? "succeeded" : "failed") << std::endl; + + return 0; + } +#endif /*USE_MAP_MMFS*/ + QServ = new QueryServ; Log.Out(Logs::General, Logs::Zone_Server, "Loading server configuration.."); diff --git a/zone/raycast_mesh.cpp b/zone/raycast_mesh.cpp index e2e88b100..28427339e 100644 --- a/zone/raycast_mesh.cpp +++ b/zone/raycast_mesh.cpp @@ -914,6 +914,11 @@ public: RmUint32 mMaxNodeCount; NodeAABB *mNodes; TriVector mLeafTriangles; + +#ifdef USE_MAP_MMFS + MyRaycastMesh(std::vector& rm_buffer); + void serialize(std::vector& rm_buffer); +#endif /*USE_MAP_MMFS*/ }; }; @@ -936,4 +941,253 @@ RaycastMesh * createRaycastMesh(RmUint32 vcount, // The number of vertices in t return static_cast< RaycastMesh * >(m); } +#ifdef USE_MAP_MMFS +RaycastMesh* loadRaycastMesh(std::vector& rm_buffer, bool& load_success) +{ + if (rm_buffer.empty()) + return nullptr; + auto m = new MyRaycastMesh(rm_buffer); + load_success = (m->mNodes != nullptr); + + return static_cast(m); +} + +void serializeRaycastMesh(RaycastMesh* rm, std::vector& rm_buffer) +{ + if (!rm) { + rm_buffer.clear(); + return; + } + + static_cast(rm)->serialize(rm_buffer); +} + +MyRaycastMesh::MyRaycastMesh(std::vector& rm_buffer) +{ + mVcount = 0; + mVertices = nullptr; + mTcount = 0; + mIndices = nullptr; + mRaycastTriangles = nullptr; + mFaceNormals = nullptr; + mRaycastFrame = 0; + mMaxNodeCount = 0; + mNodeCount = 0; + mNodes = nullptr; + mRoot = nullptr; + + size_t chunk_size = 0; + size_t bytes_read = 0; + size_t rm_buffer_size_ = rm_buffer.size(); + if (!rm_buffer_size_) + return; + + char* buf = rm_buffer.data(); + + chunk_size = sizeof(RmUint32); + memcpy(&mVcount, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + chunk_size = (sizeof(RmReal) * (3 * mVcount)); + mVertices = (RmReal *)::malloc(chunk_size); + memcpy(mVertices, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + chunk_size = sizeof(RmUint32); + memcpy(&mTcount, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + chunk_size = (sizeof(RmUint32) * (3 * mTcount)); + mIndices = (RmUint32 *)::malloc(chunk_size); + memcpy(mIndices, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + chunk_size = (sizeof(RmUint32) * mTcount); + mRaycastTriangles = (RmUint32 *)::malloc(chunk_size); + memcpy(mRaycastTriangles, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + chunk_size = (sizeof(RmReal) * (3 * mTcount)); + mFaceNormals = (RmReal *)::malloc(chunk_size); + memcpy(mFaceNormals, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + chunk_size = sizeof(RmUint32); + memcpy(&mRaycastFrame, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + RmUint32 lt_size; + chunk_size = sizeof(RmUint32); + memcpy(<_size, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + if (lt_size) { + mLeafTriangles.resize(lt_size); + chunk_size = (sizeof(RmUint32) * lt_size); + memcpy(&mLeafTriangles[0], buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + } + + chunk_size = sizeof(RmUint32); + memcpy(&mNodeCount, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + mMaxNodeCount = mNodeCount; + + mNodes = new NodeAABB[mMaxNodeCount]; + mRoot = &mNodes[0]; + + for (int index = 0; index < mNodeCount; ++index) { + chunk_size = (sizeof(RmReal) * 3); + memcpy(&mNodes[index].mBounds.mMin, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + chunk_size = (sizeof(RmReal) * 3); + memcpy(&mNodes[index].mBounds.mMax, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + chunk_size = sizeof(RmUint32); + memcpy(&mNodes[index].mLeafTriangleIndex, buf, chunk_size); + buf += chunk_size; + bytes_read += chunk_size; + + RmUint32 lNodeIndex; + chunk_size = sizeof(RmUint32); + memcpy(&lNodeIndex, buf, chunk_size); + if (lNodeIndex != TRI_EOF) + mNodes[index].mLeft = &mNodes[lNodeIndex]; + buf += chunk_size; + bytes_read += chunk_size; + + RmUint32 rNodeIndex; + chunk_size = sizeof(RmUint32); + memcpy(&rNodeIndex, buf, chunk_size); + if (rNodeIndex != TRI_EOF) + mNodes[index].mRight = &mNodes[rNodeIndex]; + buf += chunk_size; + bytes_read += chunk_size; + } + + if (bytes_read != rm_buffer_size_) { + delete[] mNodes; + ::free(mVertices); + ::free(mIndices); + ::free(mFaceNormals); + ::free(mRaycastTriangles); + + mVcount = 0; + mVertices = nullptr; + mTcount = 0; + mIndices = nullptr; + mRaycastTriangles = nullptr; + mFaceNormals = nullptr; + mRaycastFrame = 0; + mLeafTriangles.clear(); + mMaxNodeCount = 0; + mNodeCount = 0; + mNodes = nullptr; + mRoot = nullptr; + } +} + +void MyRaycastMesh::serialize(std::vector& rm_buffer) +{ + rm_buffer.clear(); + + size_t rm_buffer_size_ = 0; + + rm_buffer_size_ += sizeof(RmUint32); // mVcount + rm_buffer_size_ += (sizeof(RmReal) * (3 * mVcount)); // mVertices + rm_buffer_size_ += sizeof(RmUint32); // mTcount + rm_buffer_size_ += (sizeof(RmUint32) * (3 * mTcount)); // mIndices + rm_buffer_size_ += (sizeof(RmUint32) * mTcount); // mRaycastTriangles + rm_buffer_size_ += (sizeof(RmReal) * (3 * mTcount)); // mFaceNormals + rm_buffer_size_ += sizeof(RmUint32); // mRaycastFrame + rm_buffer_size_ += sizeof(RmUint32); // mLeafTriangles.size() + rm_buffer_size_ += (sizeof(RmUint32) * (RmUint32)mLeafTriangles.size()); // mLeafTriangles + rm_buffer_size_ += sizeof(RmUint32); // mNodeCount + rm_buffer_size_ += (sizeof(RmReal) * (3 * mNodeCount)); // mNodes.mBounds.mMin + rm_buffer_size_ += (sizeof(RmReal) * (3 * mNodeCount)); // mNodes.mBounds.mMax + rm_buffer_size_ += (sizeof(RmUint32) * mNodeCount); // mNodes.mLeafTriangleIndex + rm_buffer_size_ += (sizeof(RmUint32) * mNodeCount); // mNodes.mLeft[Index] + rm_buffer_size_ += (sizeof(RmUint32) * mNodeCount); // mNodes.mRight[Index] + + rm_buffer.resize(rm_buffer_size_); + + char* buf = rm_buffer.data(); + + memcpy(buf, &mVcount, sizeof(RmUint32)); + buf += sizeof(RmUint32); + + memcpy(buf, mVertices, (sizeof(RmReal) * (3 * mVcount))); + buf += (sizeof(RmReal) * (3 * mVcount)); + + memcpy(buf, &mTcount, sizeof(RmUint32)); + buf += sizeof(RmUint32); + + memcpy(buf, mIndices, (sizeof(RmUint32) * (3 * mTcount))); + buf += (sizeof(RmUint32) * (3 * mTcount)); + + memcpy(buf, mRaycastTriangles, (sizeof(RmUint32) * mTcount)); + buf += (sizeof(RmUint32) * mTcount); + + if (!mFaceNormals) { + RmReal save_face[3]; + getFaceNormal(0, &save_face[0]); + } + + memcpy(buf, mFaceNormals, (sizeof(RmReal) * (3 * mTcount))); + buf += (sizeof(RmReal) * (3 * mTcount)); + + memcpy(buf, &mRaycastFrame, sizeof(RmUint32)); + buf += sizeof(RmUint32); + + RmUint32 lt_size = (RmUint32)mLeafTriangles.size(); + memcpy(buf, <_size, sizeof(RmUint32)); + buf += sizeof(RmUint32); + + if (lt_size) { + memcpy(buf, &mLeafTriangles[0], (sizeof(RmUint32) * lt_size)); + buf += (sizeof(RmUint32) * lt_size); + } + + memcpy(buf, &mNodeCount, sizeof(RmUint32)); + buf += sizeof(RmUint32); + + for (RmUint32 index = 0; index < mNodeCount; ++index) { + memcpy(buf, &mNodes[index].mBounds.mMin, (sizeof(RmReal) * 3)); + buf += (sizeof(RmReal) * 3); + + memcpy(buf, &mNodes[index].mBounds.mMax, (sizeof(RmReal) * 3)); + buf += (sizeof(RmReal) * 3); + + memcpy(buf, &mNodes[index].mLeafTriangleIndex, sizeof(RmUint32)); + buf += sizeof(RmUint32); + + RmUint32 lNodeIndex = TRI_EOF; + if (mNodes[index].mLeft) + lNodeIndex = ((RmUint32)mNodes[index].mLeft - (RmUint32)mNodes) / sizeof(NodeAABB); + memcpy(buf, &lNodeIndex, sizeof(RmUint32)); + buf += sizeof(RmUint32); + + RmUint32 rNodeIndex = TRI_EOF; + if (mNodes[index].mRight) + rNodeIndex = ((RmUint32)mNodes[index].mRight - (RmUint32)mNodes) / sizeof(NodeAABB); + memcpy(buf, &rNodeIndex, sizeof(RmUint32)); + buf += sizeof(RmUint32); + } +} +#endif /*USE_MAP_MMFS*/ diff --git a/zone/raycast_mesh.h b/zone/raycast_mesh.h index eec2e0ba4..1aaa100cb 100644 --- a/zone/raycast_mesh.h +++ b/zone/raycast_mesh.h @@ -56,5 +56,11 @@ RaycastMesh * createRaycastMesh(RmUint32 vcount, // The number of vertices in t RmReal minAxisSize=0.01f // once a particular axis is less than this size, stop sub-dividing. ); +#ifdef USE_MAP_MMFS +#include + +RaycastMesh* loadRaycastMesh(std::vector& rm_buffer, bool& load_success); +void serializeRaycastMesh(RaycastMesh* rm, std::vector& rm_buffer); +#endif /*USE_MAP_MMFS*/ #endif \ No newline at end of file From f6c62af82ee17471b4bd601ce4b35eb95d6252d9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 Jul 2016 02:26:26 -0400 Subject: [PATCH 225/693] Update comment [skip ci] --- common/spdat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/spdat.h b/common/spdat.h index e44bf8e08..c82d95b74 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -735,7 +735,7 @@ struct SPDat_Spell_Struct /* 180 */ int spell_category; // -- GLOBAL_GROUP /* 181 */ //int pvp_duration; // buffdurationformula for PvP -- PVP_DURATION /* 182 */ //int pvp_duration_cap; // buffduration for PvP -- PVP_DURATION_CAP -/* 183 */ //int pcnpc_only_flag; // valid values are 0, 1, and 2 -- PCNPC_ONLY_FLAG +/* 183 */ //int pcnpc_only_flag; // valid values are 0, 1 = PCs (and mercs), and 2 = NPCs (and not mercs) -- PCNPC_ONLY_FLAG /* 184 */ bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell, this also blocks SE_InterruptCasting from affecting this spell -- CAST_NOT_STANDING /* 185 */ bool can_mgb; // 0=no, -1 or 1 = yes -- CAN_MGB /* 186 */ int dispel_flag; // -- NO_DISPELL From 239c478f316fed4d93d6b28283ad892a5fa3729e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 Jul 2016 02:55:43 -0400 Subject: [PATCH 226/693] Add some comments to target types [skip ci] --- common/spdat.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index c82d95b74..cb6e49fc9 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -100,23 +100,23 @@ typedef enum { /* 09 */ ST_Animal = 0x09, /* 10 */ ST_Undead = 0x0a, /* 11 */ ST_Summoned = 0x0b, -/* 12 */ // NOT USED +/* 12 */ // NOT USED error is 218 (This spell only works on things that are flying.) /* 13 */ ST_Tap = 0x0d, /* 14 */ ST_Pet = 0x0e, /* 15 */ ST_Corpse = 0x0f, /* 16 */ ST_Plant = 0x10, /* 17 */ ST_Giant = 0x11, //special giant /* 18 */ ST_Dragon = 0x12, //special dragon -/* 19 */ // NOT USED +/* 19 */ // NOT USED error is 227 (This spell only works on specific coldain.) /* 20 */ ST_TargetAETap = 0x14, -/* 21 */ // NOT USED -/* 22 */ // NOT USED -/* 23 */ // NOT USED +/* 21 */ // NOT USED same switch case as ST_Undead +/* 22 */ // NOT USED same switch case as ST_Summoned +/* 23 */ // NOT USED same switch case as ST_Animal /* 24 */ ST_UndeadAE = 0x18, /* 25 */ ST_SummonedAE = 0x19, /* 26 */ // NOT USED -/* 27 */ // NOT USED -/* 28 */ // NOT USED +/* 27 */ // NOT USED error is 223 (This spell only works on insects.) +/* 28 */ // NOT USED error is 223 (This spell only works on insects.) /* 29 */ // NOT USED /* 30 */ // NOT USED /* 31 */ // NOT USED From 2a2ce6da5d6632668e425715431c8c4e5d552bb2 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 Jul 2016 15:14:26 -0400 Subject: [PATCH 227/693] Fix item clicks being TGBable --- zone/bot.cpp | 4 ++-- zone/bot.h | 2 +- zone/mob.h | 2 +- zone/spells.cpp | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index b4d0718be..10f8c12f4 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -6084,7 +6084,7 @@ bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) { return Result; } -bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction) { +bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, uint16 slot) { bool Result = false; SpellTargetType targetType = spells[spell_id].targettype; if(targetType == ST_GroupClientAndPet) { @@ -6093,7 +6093,7 @@ bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce return true; } } - Result = Mob::DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction); + Result = Mob::DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction, slot); return Result; } diff --git a/zone/bot.h b/zone/bot.h index 9e88e0072..b294fa108 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -378,7 +378,7 @@ public: uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr, uint32 aa_id = 0); virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar); virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); - virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction); + virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, uint16 slot); virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0); // Bot Equipment & Inventory Class Methods diff --git a/zone/mob.h b/zone/mob.h index f663e0027..3106df4ff 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -264,7 +264,7 @@ public: bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1); virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1); virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, - CastAction_type &CastAction); + CastAction_type &CastAction, uint16 slot); virtual bool CheckFizzle(uint16 spell_id); virtual bool CheckSpellLevelRestriction(uint16 spell_id); virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); diff --git a/zone/spells.cpp b/zone/spells.cpp index 877bb19a9..b1565be7f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1348,7 +1348,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, } -bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction) { +bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, uint16 slot) { /* The basic types of spells: @@ -1682,7 +1682,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce case ST_Group: case ST_GroupNoPets: { - if(IsClient() && CastToClient()->TGB() && IsTGBCompatibleSpell(spell_id)) { + if(IsClient() && CastToClient()->TGB() && IsTGBCompatibleSpell(spell_id) && slot != USE_ITEM_SPELL_SLOT) { if( (!target) || (target->IsNPC() && !(target->GetOwner() && target->GetOwner()->IsClient())) || (target->IsCorpse()) ) @@ -1974,7 +1974,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 //determine the type of spell target we have CastAction_type CastAction; - if(!DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction)) + if(!DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction, slot)) return(false); Log.Out(Logs::Detail, Logs::Spells, "Spell %d: target type %d, target %s, AE center %s", spell_id, CastAction, spell_target?spell_target->GetName():"NONE", ae_center?ae_center->GetName():"NONE"); @@ -2370,7 +2370,7 @@ bool Mob::ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, uint16 slot) { //determine the type of spell target we have Mob *ae_center = nullptr; CastAction_type CastAction; - if(!DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction)) { + if(!DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction, slot)) { Log.Out(Logs::Detail, Logs::Spells, "Bard Song Pulse %d: was unable to determine target. Stopping.", spell_id); return(false); } From 3a4b341ad6ef56133ba35388b8681fc628958e8d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 29 Jul 2016 15:29:28 -0400 Subject: [PATCH 228/693] Allow quest controlled TS to have no returns --- zone/tradeskills.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index cdbd7b993..6deb51778 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -1317,7 +1317,7 @@ bool ZoneDatabase::GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id return false; } - if(results.RowCount() < 1) { + if(results.RowCount() < 1 && !spec->quest) { Log.Out(Logs::General, Logs::Error, "Error in GetTradeRecept success: no success items returned"); return false; } From 6b3078d0f77af8a943b69edb1e093055699cde37 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 29 Jul 2016 18:26:23 -0400 Subject: [PATCH 229/693] Fix for 64-bit Zone MMF compiles --- zone/raycast_mesh.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/zone/raycast_mesh.cpp b/zone/raycast_mesh.cpp index 28427339e..0fa411836 100644 --- a/zone/raycast_mesh.cpp +++ b/zone/raycast_mesh.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -1048,7 +1049,7 @@ MyRaycastMesh::MyRaycastMesh(std::vector& rm_buffer) mNodes = new NodeAABB[mMaxNodeCount]; mRoot = &mNodes[0]; - for (int index = 0; index < mNodeCount; ++index) { + for (RmUint32 index = 0; index < mNodeCount; ++index) { chunk_size = (sizeof(RmReal) * 3); memcpy(&mNodes[index].mBounds.mMin, buf, chunk_size); buf += chunk_size; @@ -1179,13 +1180,13 @@ void MyRaycastMesh::serialize(std::vector& rm_buffer) RmUint32 lNodeIndex = TRI_EOF; if (mNodes[index].mLeft) - lNodeIndex = ((RmUint32)mNodes[index].mLeft - (RmUint32)mNodes) / sizeof(NodeAABB); + lNodeIndex = ((uintptr_t)mNodes[index].mLeft - (uintptr_t)mNodes) / sizeof(NodeAABB); memcpy(buf, &lNodeIndex, sizeof(RmUint32)); buf += sizeof(RmUint32); RmUint32 rNodeIndex = TRI_EOF; if (mNodes[index].mRight) - rNodeIndex = ((RmUint32)mNodes[index].mRight - (RmUint32)mNodes) / sizeof(NodeAABB); + rNodeIndex = ((uintptr_t)mNodes[index].mRight - (uintptr_t)mNodes) / sizeof(NodeAABB); memcpy(buf, &rNodeIndex, sizeof(RmUint32)); buf += sizeof(RmUint32); } From 4decdb3e4dc615c1174b50bac3d8a8c606dad4da Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 29 Jul 2016 21:58:42 -0400 Subject: [PATCH 230/693] Added zone map mmf discovery message --- zone/map.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/map.cpp b/zone/map.cpp index 5ae79e8ef..630e277c2 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -286,8 +286,10 @@ Map *Map::LoadMapFile(std::string file) { #ifdef USE_MAP_MMFS bool Map::Load(std::string filename, bool force_mmf_overwrite) { - if (LoadMMF(filename, force_mmf_overwrite)) + if (LoadMMF(filename, force_mmf_overwrite)) { + Log.Out(Logs::General, Logs::Zone_Server, "Zone map mmf found - using it in lieu of '%s'", filename.c_str()); return true; + } #else bool Map::Load(std::string filename) { From 4c4b0aba0c740f0f003a9393315fc64623473ede Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 30 Jul 2016 12:50:50 -0400 Subject: [PATCH 231/693] Switch trading to call CommonBreakInvisible() --- zone/client_packet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 39574274a..f0de676f9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -13632,7 +13632,7 @@ void Client::Handle_OP_TradeRequest(const EQApplicationPacket *app) // Client requesting a trade session from an npc/client // Trade session not started until OP_TradeRequestAck is sent - BreakInvis(); + CommonBreakInvisible(); // Pass trade request on to recipient TradeRequest_Struct* msg = (TradeRequest_Struct*)app->pBuffer; From ef2c17748e612959d75328c023b6abb9c364ef1b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 31 Jul 2016 17:16:23 -0400 Subject: [PATCH 232/693] Implement extra spell gems! New limits: Tit: 9 SoF: 9 SoD: 10 UF: 12 RoF: 12 RoF2: 12 The SoF client doesn't actually support 10 like SoF should RoF/RoF2 actually have 4 extra broken spell gems in the UI. They don't work and will likely crash your client Quest stuff assumes you are passing in valid slots. (note the old default of 10 should be 22) There are still somethings to do like clean up the memmed spells if one switches to an older client that doesn't support as many as their previous client. --- changelog.txt | 10 ++++ common/emu_constants.h | 20 +++++++ common/eq_packet_structs.h | 8 +-- common/patches/rof.cpp | 93 +++++++++++++++++++++++++++---- common/patches/rof.h | 18 ++++++ common/patches/rof2.cpp | 93 +++++++++++++++++++++++++++---- common/patches/rof2.h | 18 ++++++ common/patches/rof2_structs.h | 2 +- common/patches/rof_structs.h | 2 +- common/patches/sod.cpp | 72 ++++++++++++++++++++++++ common/patches/sod.h | 16 ++++++ common/patches/sod_structs.h | 2 +- common/patches/sof.cpp | 92 +++++++++++++++++++++++++++++- common/patches/sof.h | 17 ++++++ common/patches/sof_ops.h | 1 + common/patches/sof_structs.h | 2 +- common/patches/titanium.cpp | 92 +++++++++++++++++++++++++++++- common/patches/titanium.h | 17 ++++++ common/patches/titanium_ops.h | 1 + common/patches/titanium_structs.h | 2 +- common/patches/uf.cpp | 84 ++++++++++++++++++++++++++-- common/patches/uf.h | 18 ++++++ common/patches/uf_structs.h | 2 +- world/client.cpp | 2 +- zone/aa.cpp | 4 +- zone/attack.cpp | 4 +- zone/bot.cpp | 26 ++++----- zone/bot.h | 12 ++-- zone/bot_command.cpp | 2 +- zone/client.cpp | 6 +- zone/client.h | 1 + zone/client_packet.cpp | 38 ++++++------- zone/command.cpp | 8 +-- zone/common.h | 7 --- zone/effects.cpp | 6 +- zone/lua_mob.cpp | 22 ++++---- zone/merc.cpp | 4 +- zone/mob.cpp | 51 ++++++++--------- zone/mob.h | 17 +++--- zone/mob_ai.cpp | 8 +-- zone/perl_mob.cpp | 10 ++-- zone/questmgr.cpp | 4 +- zone/special_attacks.cpp | 4 +- zone/spell_effects.cpp | 8 +-- zone/spells.cpp | 73 ++++++++++++------------ zone/trap.cpp | 2 +- 46 files changed, 800 insertions(+), 201 deletions(-) diff --git a/changelog.txt b/changelog.txt index f1af1009a..5221f170b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,15 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 07/31/2016 == +mackal: Implement more spell gems! + - There are a few things still left to due like make dealing with losing gems nice (reset AAs, going to an older client etc) + - Sadly SoF disc release doesn't support gem 10 like one might expect :( + - So changed clients: + - SoD = 10 + - UF = 12 + - RoF/RoF2 = 12. I know the UI supports 16, but the client does not and can cause client crashes + - The quest APIs assume you pass a valid spell gem ... + == 07/28/2016 == Uleat: Implemented zone memory-mapped file usage - Zone map files are converted to pre-loaded binary files, bypassing the (sometimes) time-consuming raw data transform process diff --git a/common/emu_constants.h b/common/emu_constants.h index 799161aa8..bf8189acc 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -44,6 +44,26 @@ namespace EQEmu const size_t SayLinkBodySize = RoF2::constants::SayLinkBodySize; } /*constants*/ + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Gem10 = 9, + Gem11 = 10, + Gem12 = 11, + MaxGems = 12, + Ability = 20, // HT/LoH for Tit + PotionBelt = 21, // Tit uses a different slot for PB + Item = 22, + Discipline = 23, + AltAbility = 0xFF + }; } /*EQEmu*/ diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 3252d07cc..ab0447cb8 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -386,7 +386,7 @@ struct MemorizeSpell_Struct { uint32 slot; // Spot in the spell book/memorized slot uint32 spell_id; // Spell id (200 or c8 is minor healing, etc) uint32 scribing; // 1 if memorizing a spell, set to 0 if scribing to book, 2 if un-memming -uint32 unknown12; +uint32 reduction; // lower reuse }; /* @@ -834,7 +834,7 @@ struct SuspendedMinion_Struct */ static const uint32 MAX_PP_LANGUAGE = 28; static const uint32 MAX_PP_SPELLBOOK = 480; // Set for all functions -static const uint32 MAX_PP_MEMSPELL = 9; // Set to latest client so functions can work right +static const uint32 MAX_PP_MEMSPELL = static_cast(EQEmu::CastingSlot::MaxGems); // Set to latest client so functions can work right -- 12 static const uint32 MAX_PP_REF_SPELLBOOK = 480; // Set for Player Profile size retain static const uint32 MAX_PP_REF_MEMSPELL = 9; // Set for Player Profile size retain @@ -915,7 +915,7 @@ struct PlayerProfile_Struct /*0245*/ uint8 guildbanker; /*0246*/ uint8 unknown0246[6]; // /*0252*/ uint32 intoxication; -/*0256*/ uint32 spellSlotRefresh[MAX_PP_REF_MEMSPELL]; //in ms +/*0256*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; //in ms /*0292*/ uint32 abilitySlotRefresh; /*0296*/ uint8 haircolor; // Player hair color /*0297*/ uint8 beardcolor; // Player beard color @@ -956,7 +956,7 @@ struct PlayerProfile_Struct /*2580*/ uint8 unknown2616[4]; /*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK]; /*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff -/*4632*/ uint32 mem_spells[MAX_PP_REF_MEMSPELL]; +/*4632*/ uint32 mem_spells[MAX_PP_MEMSPELL]; /*4668*/ uint8 unknown4704[32]; // /*4700*/ float y; // Player y position /*4704*/ float x; // Player x position diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 4bf8ed63d..014e6f8d9 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -63,6 +63,9 @@ namespace RoF // client to server text link converter static inline void RoFToServerTextLink(std::string& serverTextLink, const std::string& rofTextLink); + static inline CastingSlot ServerToRoFCastingSlot(EQEmu::CastingSlot slot); + static inline EQEmu::CastingSlot RoFToServerCastingSlot(CastingSlot slot); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -507,10 +510,7 @@ namespace RoF ENCODE_LENGTH_EXACT(CastSpell_Struct); SETUP_DIRECT_ENCODE(CastSpell_Struct, structs::CastSpell_Struct); - if (emu->slot == 10) - eq->slot = 13; - else - OUT(slot); + eq->slot = static_cast(ServerToRoFCastingSlot(static_cast(emu->slot))); OUT(spell_id); eq->inventory_slot = ServerToRoFSlot(emu->inventoryslot); @@ -2259,11 +2259,11 @@ namespace RoF outapp->WriteUInt32(structs::MAX_PP_MEMSPELL); // Memorised spell slots - for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) + for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) // first 12 { outapp->WriteUInt32(emu->mem_spells[r]); } - // zeroes for the rest of the slots + // zeroes for the rest of the slots -- the other 4 which don't work at all! for (uint32 r = 0; r < structs::MAX_PP_MEMSPELL - MAX_PP_MEMSPELL; r++) { outapp->WriteUInt32(0xFFFFFFFFU); @@ -4334,10 +4334,7 @@ namespace RoF DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - if (eq->slot == 13) - emu->slot = 10; - else - IN(slot); + emu->slot = static_cast(RoFToServerCastingSlot(static_cast(eq->slot))); IN(spell_id); emu->inventoryslot = RoFToServerSlot(eq->inventory_slot); @@ -6009,4 +6006,80 @@ namespace RoF } } + static inline CastingSlot ServerToRoFCastingSlot(EQEmu::CastingSlot slot) + { + switch (slot) { + case EQEmu::CastingSlot::Gem1: + return CastingSlot::Gem1; + case EQEmu::CastingSlot::Gem2: + return CastingSlot::Gem2; + case EQEmu::CastingSlot::Gem3: + return CastingSlot::Gem3; + case EQEmu::CastingSlot::Gem4: + return CastingSlot::Gem4; + case EQEmu::CastingSlot::Gem5: + return CastingSlot::Gem5; + case EQEmu::CastingSlot::Gem6: + return CastingSlot::Gem6; + case EQEmu::CastingSlot::Gem7: + return CastingSlot::Gem7; + case EQEmu::CastingSlot::Gem8: + return CastingSlot::Gem8; + case EQEmu::CastingSlot::Gem9: + return CastingSlot::Gem9; + case EQEmu::CastingSlot::Gem10: + return CastingSlot::Gem10; + case EQEmu::CastingSlot::Gem11: + return CastingSlot::Gem11; + case EQEmu::CastingSlot::Gem12: + return CastingSlot::Gem12; + case EQEmu::CastingSlot::Item: + case EQEmu::CastingSlot::PotionBelt: + return CastingSlot::Item; + case EQEmu::CastingSlot::Discipline: + return CastingSlot::Discipline; + case EQEmu::CastingSlot::AltAbility: + return CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return CastingSlot::Discipline; + } + } + + static inline EQEmu::CastingSlot RoFToServerCastingSlot(CastingSlot slot) + { + switch (slot) { + case CastingSlot::Gem1: + return EQEmu::CastingSlot::Gem1; + case CastingSlot::Gem2: + return EQEmu::CastingSlot::Gem2; + case CastingSlot::Gem3: + return EQEmu::CastingSlot::Gem3; + case CastingSlot::Gem4: + return EQEmu::CastingSlot::Gem4; + case CastingSlot::Gem5: + return EQEmu::CastingSlot::Gem5; + case CastingSlot::Gem6: + return EQEmu::CastingSlot::Gem6; + case CastingSlot::Gem7: + return EQEmu::CastingSlot::Gem7; + case CastingSlot::Gem8: + return EQEmu::CastingSlot::Gem8; + case CastingSlot::Gem9: + return EQEmu::CastingSlot::Gem9; + case CastingSlot::Gem10: + return EQEmu::CastingSlot::Gem10; + case CastingSlot::Gem11: + return EQEmu::CastingSlot::Gem11; + case CastingSlot::Gem12: + return EQEmu::CastingSlot::Gem12; + case CastingSlot::Discipline: + return EQEmu::CastingSlot::Discipline; + case CastingSlot::Item: + return EQEmu::CastingSlot::Item; + case CastingSlot::AltAbility: + return EQEmu::CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return EQEmu::CastingSlot::Discipline; + } + } } /*RoF*/ diff --git a/common/patches/rof.h b/common/patches/rof.h index 205998b32..146b34f1f 100644 --- a/common/patches/rof.h +++ b/common/patches/rof.h @@ -50,6 +50,24 @@ namespace RoF #include "rof_ops.h" }; + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Gem10 = 9, + Gem11 = 10, + Gem12 = 11, + Item = 12, + Discipline = 13, + AltAbility = 0xFF + }; + }; /*RoF*/ #endif /*COMMON_ROF_H*/ diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 41d34a50a..79802e262 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -63,6 +63,9 @@ namespace RoF2 // client to server text link converter static inline void RoF2ToServerTextLink(std::string& serverTextLink, const std::string& rof2TextLink); + static inline CastingSlot ServerToRoF2CastingSlot(EQEmu::CastingSlot slot); + static inline EQEmu::CastingSlot RoF2ToServerCastingSlot(CastingSlot slot); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -584,10 +587,7 @@ namespace RoF2 ENCODE_LENGTH_EXACT(CastSpell_Struct); SETUP_DIRECT_ENCODE(CastSpell_Struct, structs::CastSpell_Struct); - if (emu->slot == 10) - eq->slot = 13; - else - OUT(slot); + eq->slot = static_cast(ServerToRoF2CastingSlot(static_cast(emu->slot))); OUT(spell_id); eq->inventory_slot = ServerToRoF2Slot(emu->inventoryslot); @@ -2346,11 +2346,11 @@ namespace RoF2 outapp->WriteUInt32(structs::MAX_PP_MEMSPELL); // Memorised spell slots - for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) + for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) // write first 12 { outapp->WriteUInt32(emu->mem_spells[r]); } - // zeroes for the rest of the slots + // zeroes for the rest of the slots the other 4, which actually don't work on the client at all :D for (uint32 r = 0; r < structs::MAX_PP_MEMSPELL - MAX_PP_MEMSPELL; r++) { outapp->WriteUInt32(0xFFFFFFFFU); @@ -4574,10 +4574,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - if (eq->slot == 13) - emu->slot = 10; - else - IN(slot); + emu->slot = static_cast(RoF2ToServerCastingSlot(static_cast(eq->slot))); IN(spell_id); emu->inventoryslot = RoF2ToServerSlot(eq->inventory_slot); @@ -6314,4 +6311,80 @@ namespace RoF2 } } + static inline CastingSlot ServerToRoF2CastingSlot(EQEmu::CastingSlot slot) + { + switch (slot) { + case EQEmu::CastingSlot::Gem1: + return CastingSlot::Gem1; + case EQEmu::CastingSlot::Gem2: + return CastingSlot::Gem2; + case EQEmu::CastingSlot::Gem3: + return CastingSlot::Gem3; + case EQEmu::CastingSlot::Gem4: + return CastingSlot::Gem4; + case EQEmu::CastingSlot::Gem5: + return CastingSlot::Gem5; + case EQEmu::CastingSlot::Gem6: + return CastingSlot::Gem6; + case EQEmu::CastingSlot::Gem7: + return CastingSlot::Gem7; + case EQEmu::CastingSlot::Gem8: + return CastingSlot::Gem8; + case EQEmu::CastingSlot::Gem9: + return CastingSlot::Gem9; + case EQEmu::CastingSlot::Gem10: + return CastingSlot::Gem10; + case EQEmu::CastingSlot::Gem11: + return CastingSlot::Gem11; + case EQEmu::CastingSlot::Gem12: + return CastingSlot::Gem12; + case EQEmu::CastingSlot::Item: + case EQEmu::CastingSlot::PotionBelt: + return CastingSlot::Item; + case EQEmu::CastingSlot::Discipline: + return CastingSlot::Discipline; + case EQEmu::CastingSlot::AltAbility: + return CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return CastingSlot::Discipline; + } + } + + static inline EQEmu::CastingSlot RoF2ToServerCastingSlot(CastingSlot slot) + { + switch (slot) { + case CastingSlot::Gem1: + return EQEmu::CastingSlot::Gem1; + case CastingSlot::Gem2: + return EQEmu::CastingSlot::Gem2; + case CastingSlot::Gem3: + return EQEmu::CastingSlot::Gem3; + case CastingSlot::Gem4: + return EQEmu::CastingSlot::Gem4; + case CastingSlot::Gem5: + return EQEmu::CastingSlot::Gem5; + case CastingSlot::Gem6: + return EQEmu::CastingSlot::Gem6; + case CastingSlot::Gem7: + return EQEmu::CastingSlot::Gem7; + case CastingSlot::Gem8: + return EQEmu::CastingSlot::Gem8; + case CastingSlot::Gem9: + return EQEmu::CastingSlot::Gem9; + case CastingSlot::Gem10: + return EQEmu::CastingSlot::Gem10; + case CastingSlot::Gem11: + return EQEmu::CastingSlot::Gem11; + case CastingSlot::Gem12: + return EQEmu::CastingSlot::Gem12; + case CastingSlot::Discipline: + return EQEmu::CastingSlot::Discipline; + case CastingSlot::Item: + return EQEmu::CastingSlot::Item; + case CastingSlot::AltAbility: + return EQEmu::CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return EQEmu::CastingSlot::Discipline; + } + } } /*RoF2*/ diff --git a/common/patches/rof2.h b/common/patches/rof2.h index 9eef8e596..4fb94a1d4 100644 --- a/common/patches/rof2.h +++ b/common/patches/rof2.h @@ -50,6 +50,24 @@ namespace RoF2 #include "rof2_ops.h" }; + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Gem10 = 9, + Gem11 = 10, + Gem12 = 11, + Item = 12, + Discipline = 13, + AltAbility = 0xFF + }; + }; /*RoF2*/ #endif /*COMMON_ROF2_H*/ diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 61cbb0d0b..971ebd5e0 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -635,7 +635,7 @@ struct MemorizeSpell_Struct { uint32 slot; // Spot in the spell book/memorized slot uint32 spell_id; // Spell id (200 or c8 is minor healing, etc) uint32 scribing; // 1 if memorizing a spell, set to 0 if scribing to book, 2 if un-memming -uint32 unknown12; +uint32 reduction; // lowers reuse }; /* diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 9c5aa8ab8..24c4b15f8 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -624,7 +624,7 @@ struct MemorizeSpell_Struct { uint32 slot; // Spot in the spell book/memorized slot uint32 spell_id; // Spell id (200 or c8 is minor healing, etc) uint32 scribing; // 1 if memorizing a spell, set to 0 if scribing to book, 2 if un-memming -uint32 unknown12; +uint32 reduction; // lowers reuse }; /* diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index c148a02be..52bbdc309 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -59,6 +59,9 @@ namespace SoD // client to server text link converter static inline void SoDToServerTextLink(std::string& serverTextLink, const std::string& sodTextLink); + static inline CastingSlot ServerToSoDCastingSlot(EQEmu::CastingSlot slot); + static inline EQEmu::CastingSlot SoDToServerCastingSlot(CastingSlot slot); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -2948,6 +2951,7 @@ namespace SoD DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); + emu->slot = static_cast(SoDToServerCastingSlot(static_cast(eq->slot))); IN(slot); IN(spell_id); emu->inventoryslot = SoDToServerSlot(eq->inventoryslot); @@ -4013,4 +4017,72 @@ namespace SoD } } + static inline CastingSlot ServerToSoDCastingSlot(EQEmu::CastingSlot slot) + { + switch (slot) { + case EQEmu::CastingSlot::Gem1: + return CastingSlot::Gem1; + case EQEmu::CastingSlot::Gem2: + return CastingSlot::Gem2; + case EQEmu::CastingSlot::Gem3: + return CastingSlot::Gem3; + case EQEmu::CastingSlot::Gem4: + return CastingSlot::Gem4; + case EQEmu::CastingSlot::Gem5: + return CastingSlot::Gem5; + case EQEmu::CastingSlot::Gem6: + return CastingSlot::Gem6; + case EQEmu::CastingSlot::Gem7: + return CastingSlot::Gem7; + case EQEmu::CastingSlot::Gem8: + return CastingSlot::Gem8; + case EQEmu::CastingSlot::Gem9: + return CastingSlot::Gem9; + case EQEmu::CastingSlot::Gem10: + return CastingSlot::Gem10; + case EQEmu::CastingSlot::Item: + case EQEmu::CastingSlot::PotionBelt: + return CastingSlot::Item; + case EQEmu::CastingSlot::Discipline: + return CastingSlot::Discipline; + case EQEmu::CastingSlot::AltAbility: + return CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return CastingSlot::Discipline; + } + } + + static inline EQEmu::CastingSlot SoDToServerCastingSlot(CastingSlot slot) + { + switch (slot) { + case CastingSlot::Gem1: + return EQEmu::CastingSlot::Gem1; + case CastingSlot::Gem2: + return EQEmu::CastingSlot::Gem2; + case CastingSlot::Gem3: + return EQEmu::CastingSlot::Gem3; + case CastingSlot::Gem4: + return EQEmu::CastingSlot::Gem4; + case CastingSlot::Gem5: + return EQEmu::CastingSlot::Gem5; + case CastingSlot::Gem6: + return EQEmu::CastingSlot::Gem6; + case CastingSlot::Gem7: + return EQEmu::CastingSlot::Gem7; + case CastingSlot::Gem8: + return EQEmu::CastingSlot::Gem8; + case CastingSlot::Gem9: + return EQEmu::CastingSlot::Gem9; + case CastingSlot::Gem10: + return EQEmu::CastingSlot::Gem10; + case CastingSlot::Discipline: + return EQEmu::CastingSlot::Discipline; + case CastingSlot::Item: + return EQEmu::CastingSlot::Item; + case CastingSlot::AltAbility: + return EQEmu::CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return EQEmu::CastingSlot::Discipline; + } + } } /*SoD*/ diff --git a/common/patches/sod.h b/common/patches/sod.h index 977645231..5c29e36c0 100644 --- a/common/patches/sod.h +++ b/common/patches/sod.h @@ -50,6 +50,22 @@ namespace SoD #include "sod_ops.h" }; + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Gem10 = 9, + Item = 10, + Discipline = 11, + AltAbility = 0xFF + }; + }; /*SoD*/ #endif /*COMMON_SOD_H*/ diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 191d048e9..bdf6a6fd3 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -479,7 +479,7 @@ struct MemorizeSpell_Struct { uint32 slot; // Spot in the spell book/memorized slot uint32 spell_id; // Spell id (200 or c8 is minor healing, etc) uint32 scribing; // 1 if memorizing a spell, set to 0 if scribing to book, 2 if un-memming -//uint32 unknown12; +uint32 reduction; // lowers reuse }; /* diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 7984debd9..4f804bb03 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -59,6 +59,9 @@ namespace SoF // client to server text link converter static inline void SoFToServerTextLink(std::string& serverTextLink, const std::string& sofTextLink); + static inline CastingSlot ServerToSoFCastingSlot(EQEmu::CastingSlot slot); + static inline EQEmu::CastingSlot SoFToServerCastingSlot(CastingSlot slot, uint32 itemlocation); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -938,6 +941,22 @@ namespace SoF FINISH_ENCODE(); } + ENCODE(OP_MemorizeSpell) + { + ENCODE_LENGTH_EXACT(MemorizeSpell_Struct); + SETUP_DIRECT_ENCODE(MemorizeSpell_Struct, structs::MemorizeSpell_Struct); + + // Since HT/LoH are translated up, we need to translate down only for memSpellSpellbar case + if (emu->scribing == 3) + eq->slot = static_cast(ServerToSoFCastingSlot(static_cast(emu->slot))); + else + OUT(slot); + OUT(spell_id); + OUT(scribing); + + FINISH_ENCODE(); + } + ENCODE(OP_MoveItem) { ENCODE_LENGTH_EXACT(MoveItem_Struct); @@ -2366,7 +2385,7 @@ namespace SoF DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - IN(slot); + emu->slot = static_cast(SoFToServerCastingSlot(static_cast(eq->slot), eq->inventoryslot)); IN(spell_id); emu->inventoryslot = SoFToServerSlot(eq->inventoryslot); IN(target_id); @@ -3355,4 +3374,75 @@ namespace SoF } } + static inline CastingSlot ServerToSoFCastingSlot(EQEmu::CastingSlot slot) + { + switch (slot) { + case EQEmu::CastingSlot::Gem1: + return CastingSlot::Gem1; + case EQEmu::CastingSlot::Gem2: + return CastingSlot::Gem2; + case EQEmu::CastingSlot::Gem3: + return CastingSlot::Gem3; + case EQEmu::CastingSlot::Gem4: + return CastingSlot::Gem4; + case EQEmu::CastingSlot::Gem5: + return CastingSlot::Gem5; + case EQEmu::CastingSlot::Gem6: + return CastingSlot::Gem6; + case EQEmu::CastingSlot::Gem7: + return CastingSlot::Gem7; + case EQEmu::CastingSlot::Gem8: + return CastingSlot::Gem8; + case EQEmu::CastingSlot::Gem9: + return CastingSlot::Gem9; + case EQEmu::CastingSlot::Item: + return CastingSlot::Item; + case EQEmu::CastingSlot::PotionBelt: + return CastingSlot::PotionBelt; + case EQEmu::CastingSlot::Discipline: + return CastingSlot::Discipline; + case EQEmu::CastingSlot::AltAbility: + return CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return CastingSlot::Discipline; + } + } + + static inline EQEmu::CastingSlot SoFToServerCastingSlot(CastingSlot slot, uint32 itemlocation) + { + switch (slot) { + case CastingSlot::Gem1: + return EQEmu::CastingSlot::Gem1; + case CastingSlot::Gem2: + return EQEmu::CastingSlot::Gem2; + case CastingSlot::Gem3: + return EQEmu::CastingSlot::Gem3; + case CastingSlot::Gem4: + return EQEmu::CastingSlot::Gem4; + case CastingSlot::Gem5: + return EQEmu::CastingSlot::Gem5; + case CastingSlot::Gem6: + return EQEmu::CastingSlot::Gem6; + case CastingSlot::Gem7: + return EQEmu::CastingSlot::Gem7; + case CastingSlot::Gem8: + return EQEmu::CastingSlot::Gem8; + case CastingSlot::Gem9: + return EQEmu::CastingSlot::Gem9; + case CastingSlot::Ability: + return EQEmu::CastingSlot::Ability; + // Tit uses 10 for item and discipline casting, but items have a valid location + case CastingSlot::Item: + if (itemlocation == INVALID_INDEX) + return EQEmu::CastingSlot::Discipline; + else + return EQEmu::CastingSlot::Item; + case CastingSlot::PotionBelt: + return EQEmu::CastingSlot::PotionBelt; + case CastingSlot::AltAbility: + return EQEmu::CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return EQEmu::CastingSlot::Discipline; + } + } } /*SoF*/ diff --git a/common/patches/sof.h b/common/patches/sof.h index dde55f9a3..47c023471 100644 --- a/common/patches/sof.h +++ b/common/patches/sof.h @@ -50,6 +50,23 @@ namespace SoF #include "sof_ops.h" }; + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Ability = 9, + Item = 10, + Discipline = 10, + PotionBelt = 11, + AltAbility = 0xFF + }; + }; /*SoF*/ #endif /*COMMON_SOF_H*/ diff --git a/common/patches/sof_ops.h b/common/patches/sof_ops.h index 01caf8674..68ff402f1 100644 --- a/common/patches/sof_ops.h +++ b/common/patches/sof_ops.h @@ -57,6 +57,7 @@ E(OP_LeadershipExpUpdate) E(OP_LogServer) E(OP_LootItem) E(OP_ManaChange) +E(OP_MemorizeSpell) E(OP_MoveItem) E(OP_NewSpawn) E(OP_NewZone) diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 86dc91e14..06604e71d 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -458,7 +458,7 @@ struct MemorizeSpell_Struct { uint32 slot; // Spot in the spell book/memorized slot uint32 spell_id; // Spell id (200 or c8 is minor healing, etc) uint32 scribing; // 1 if memorizing a spell, set to 0 if scribing to book, 2 if un-memming -//uint32 unknown12; +uint32 reduction; // lowers reuse }; /* diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 98ece403c..28984a26f 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -58,6 +58,9 @@ namespace Titanium // client to server text link converter static inline void TitaniumToServerTextLink(std::string& serverTextLink, const std::string& titaniumTextLink); + static inline CastingSlot ServerToTitaniumCastingSlot(EQEmu::CastingSlot slot); + static inline EQEmu::CastingSlot TitaniumToServerCastingSlot(CastingSlot slot, uint32 itemlocation); + void Register(EQStreamIdentifier &into) { auto Config = EQEmuConfig::get(); @@ -833,6 +836,22 @@ namespace Titanium FINISH_ENCODE(); } + ENCODE(OP_MemorizeSpell) + { + ENCODE_LENGTH_EXACT(MemorizeSpell_Struct); + SETUP_DIRECT_ENCODE(MemorizeSpell_Struct, structs::MemorizeSpell_Struct); + + // Since HT/LoH are translated up, we need to translate down only for memSpellSpellbar case + if (emu->scribing == 3) + eq->slot = static_cast(ServerToTitaniumCastingSlot(static_cast(emu->slot))); + else + OUT(slot); + OUT(spell_id); + OUT(scribing); + + FINISH_ENCODE(); + } + ENCODE(OP_MoveItem) { ENCODE_LENGTH_EXACT(MoveItem_Struct); @@ -1731,7 +1750,7 @@ namespace Titanium DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - IN(slot); + emu->slot = static_cast(TitaniumToServerCastingSlot(static_cast(eq->slot), eq->inventoryslot)); IN(spell_id); emu->inventoryslot = TitaniumToServerSlot(eq->inventoryslot); IN(target_id); @@ -2487,4 +2506,75 @@ namespace Titanium } } + static inline CastingSlot ServerToTitaniumCastingSlot(EQEmu::CastingSlot slot) + { + switch (slot) { + case EQEmu::CastingSlot::Gem1: + return CastingSlot::Gem1; + case EQEmu::CastingSlot::Gem2: + return CastingSlot::Gem2; + case EQEmu::CastingSlot::Gem3: + return CastingSlot::Gem3; + case EQEmu::CastingSlot::Gem4: + return CastingSlot::Gem4; + case EQEmu::CastingSlot::Gem5: + return CastingSlot::Gem5; + case EQEmu::CastingSlot::Gem6: + return CastingSlot::Gem6; + case EQEmu::CastingSlot::Gem7: + return CastingSlot::Gem7; + case EQEmu::CastingSlot::Gem8: + return CastingSlot::Gem8; + case EQEmu::CastingSlot::Gem9: + return CastingSlot::Gem9; + case EQEmu::CastingSlot::Item: + return CastingSlot::Item; + case EQEmu::CastingSlot::PotionBelt: + return CastingSlot::PotionBelt; + case EQEmu::CastingSlot::Discipline: + return CastingSlot::Discipline; + case EQEmu::CastingSlot::AltAbility: + return CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return CastingSlot::Discipline; + } + } + + static inline EQEmu::CastingSlot TitaniumToServerCastingSlot(CastingSlot slot, uint32 itemlocation) + { + switch (slot) { + case CastingSlot::Gem1: + return EQEmu::CastingSlot::Gem1; + case CastingSlot::Gem2: + return EQEmu::CastingSlot::Gem2; + case CastingSlot::Gem3: + return EQEmu::CastingSlot::Gem3; + case CastingSlot::Gem4: + return EQEmu::CastingSlot::Gem4; + case CastingSlot::Gem5: + return EQEmu::CastingSlot::Gem5; + case CastingSlot::Gem6: + return EQEmu::CastingSlot::Gem6; + case CastingSlot::Gem7: + return EQEmu::CastingSlot::Gem7; + case CastingSlot::Gem8: + return EQEmu::CastingSlot::Gem8; + case CastingSlot::Gem9: + return EQEmu::CastingSlot::Gem9; + case CastingSlot::Ability: + return EQEmu::CastingSlot::Ability; + // Tit uses 10 for item and discipline casting, but items have a valid location + case CastingSlot::Item: + if (itemlocation == INVALID_INDEX) + return EQEmu::CastingSlot::Discipline; + else + return EQEmu::CastingSlot::Item; + case CastingSlot::PotionBelt: + return EQEmu::CastingSlot::PotionBelt; + case CastingSlot::AltAbility: + return EQEmu::CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return EQEmu::CastingSlot::Discipline; + } + } } /*Titanium*/ diff --git a/common/patches/titanium.h b/common/patches/titanium.h index 2f063c9ad..ea68dd59a 100644 --- a/common/patches/titanium.h +++ b/common/patches/titanium.h @@ -50,6 +50,23 @@ namespace Titanium #include "titanium_ops.h" }; + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Ability = 9, + Item = 10, + Discipline = 10, + PotionBelt = 11, + AltAbility = 0xFF + }; + }; /*Titanium*/ #endif /*COMMON_TITANIUM_H*/ diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index f878fbd76..9ca0ba770 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -50,6 +50,7 @@ E(OP_ItemPacket) E(OP_LeadershipExpUpdate) E(OP_LFGuild) E(OP_LootItem) +E(OP_MemorizeSpell) E(OP_MoveItem) E(OP_OnLevelMessage) E(OP_PetBuffWindow) diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index caa798da0..b7b2bac67 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -390,7 +390,7 @@ struct MemorizeSpell_Struct { uint32 slot; // Spot in the spell book/memorized slot uint32 spell_id; // Spell id (200 or c8 is minor healing, etc) uint32 scribing; // 1 if memorizing a spell, set to 0 if scribing to book, 2 if un-memming -uint32 unknown12; +uint32 reduction; // lowers reuse }; /* diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 80a266ebe..735243f09 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -59,6 +59,9 @@ namespace UF // client to server text link converter static inline void UFToServerTextLink(std::string& serverTextLink, const std::string& ufTextLink); + static inline CastingSlot ServerToUFCastingSlot(EQEmu::CastingSlot slot); + static inline EQEmu::CastingSlot UFToServerCastingSlot(CastingSlot slot); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -3259,10 +3262,7 @@ namespace UF DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - if (eq->slot == 13) - emu->slot = 10; - else - IN(slot); + emu->slot = static_cast(UFToServerCastingSlot(static_cast(eq->slot))); IN(spell_id); emu->inventoryslot = UFToServerSlot(eq->inventoryslot); @@ -4378,4 +4378,80 @@ namespace UF } } + static inline CastingSlot ServerToUFCastingSlot(EQEmu::CastingSlot slot) + { + switch (slot) { + case EQEmu::CastingSlot::Gem1: + return CastingSlot::Gem1; + case EQEmu::CastingSlot::Gem2: + return CastingSlot::Gem2; + case EQEmu::CastingSlot::Gem3: + return CastingSlot::Gem3; + case EQEmu::CastingSlot::Gem4: + return CastingSlot::Gem4; + case EQEmu::CastingSlot::Gem5: + return CastingSlot::Gem5; + case EQEmu::CastingSlot::Gem6: + return CastingSlot::Gem6; + case EQEmu::CastingSlot::Gem7: + return CastingSlot::Gem7; + case EQEmu::CastingSlot::Gem8: + return CastingSlot::Gem8; + case EQEmu::CastingSlot::Gem9: + return CastingSlot::Gem9; + case EQEmu::CastingSlot::Gem10: + return CastingSlot::Gem10; + case EQEmu::CastingSlot::Gem11: + return CastingSlot::Gem11; + case EQEmu::CastingSlot::Gem12: + return CastingSlot::Gem12; + case EQEmu::CastingSlot::Item: + case EQEmu::CastingSlot::PotionBelt: + return CastingSlot::Item; + case EQEmu::CastingSlot::Discipline: + return CastingSlot::Discipline; + case EQEmu::CastingSlot::AltAbility: + return CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return CastingSlot::Discipline; + } + } + + static inline EQEmu::CastingSlot UFToServerCastingSlot(CastingSlot slot) + { + switch (slot) { + case CastingSlot::Gem1: + return EQEmu::CastingSlot::Gem1; + case CastingSlot::Gem2: + return EQEmu::CastingSlot::Gem2; + case CastingSlot::Gem3: + return EQEmu::CastingSlot::Gem3; + case CastingSlot::Gem4: + return EQEmu::CastingSlot::Gem4; + case CastingSlot::Gem5: + return EQEmu::CastingSlot::Gem5; + case CastingSlot::Gem6: + return EQEmu::CastingSlot::Gem6; + case CastingSlot::Gem7: + return EQEmu::CastingSlot::Gem7; + case CastingSlot::Gem8: + return EQEmu::CastingSlot::Gem8; + case CastingSlot::Gem9: + return EQEmu::CastingSlot::Gem9; + case CastingSlot::Gem10: + return EQEmu::CastingSlot::Gem10; + case CastingSlot::Gem11: + return EQEmu::CastingSlot::Gem11; + case CastingSlot::Gem12: + return EQEmu::CastingSlot::Gem12; + case CastingSlot::Discipline: + return EQEmu::CastingSlot::Discipline; + case CastingSlot::Item: + return EQEmu::CastingSlot::Item; + case CastingSlot::AltAbility: + return EQEmu::CastingSlot::AltAbility; + default: // we shouldn't have any issues with other slots ... just return something + return EQEmu::CastingSlot::Discipline; + } + } } /*UF*/ diff --git a/common/patches/uf.h b/common/patches/uf.h index c36d9e851..1dc5046c3 100644 --- a/common/patches/uf.h +++ b/common/patches/uf.h @@ -50,6 +50,24 @@ namespace UF #include "uf_ops.h" }; + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Gem10 = 9, + Gem11 = 10, + Gem12 = 11, + Item = 12, + Discipline = 13, + AltAbility = 0xFF + }; + }; /*UF*/ #endif /*COMMON_UF_H*/ diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 932213827..7ef766d86 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -479,7 +479,7 @@ struct MemorizeSpell_Struct { uint32 slot; // Spot in the spell book/memorized slot uint32 spell_id; // Spell id (200 or c8 is minor healing, etc) uint32 scribing; // 1 if memorizing a spell, set to 0 if scribing to book, 2 if un-memming -//uint32 unknown12; +uint32 reduction; // lowers reuse }; /* diff --git a/world/client.cpp b/world/client.cpp index 8265ab03a..460fa294d 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1483,7 +1483,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++) pp.spell_book[i] = 0xFFFFFFFF; - for(i = 0; i < MAX_PP_REF_MEMSPELL; i++) + for(i = 0; i < MAX_PP_MEMSPELL; i++) pp.mem_spells[i] = 0xFFFFFFFF; for(i = 0; i < BUFF_COUNT; i++) diff --git a/zone/aa.cpp b/zone/aa.cpp index d18936956..f6facec8c 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1183,12 +1183,12 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { CommonBreakInvisible(); // Bards can cast instant cast AAs while they are casting another song if(spells[rank->spell].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { - if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), ALTERNATE_ABILITY_SPELL_SLOT, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) { + if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) { return; } ExpendAlternateAdvancementCharge(ability->id); } else { - if(!CastSpell(rank->spell, target_id, ALTERNATE_ABILITY_SPELL_SLOT, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) { + if(!CastSpell(rank->spell, target_id, EQEmu::CastingSlot::AltAbility, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) { return; } } diff --git a/zone/attack.cpp b/zone/attack.cpp index 1c7796f42..54f98c97a 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1205,7 +1205,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b IsValidSpell(aabonuses.SkillAttackProc[2])) { float chance = aabonuses.SkillAttackProc[0] / 1000.0f; if (zone->random.Roll(chance)) - SpellFinished(aabonuses.SkillAttackProc[2], other, 10, 0, -1, + SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, true, -1, false, special); @@ -1821,7 +1821,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::Skill if(IsLDoNTrapped()) { Message_StringID(13, LDON_ACCIDENT_SETOFF2); - SpellFinished(GetLDoNTrapSpellID(), other, 10, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false); + SpellFinished(GetLDoNTrapSpellID(), other, EQEmu::CastingSlot::Item, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false); SetLDoNTrapSpellID(0); SetLDoNTrapped(false); SetLDoNTrapDetected(false); diff --git a/zone/bot.cpp b/zone/bot.cpp index 10f8c12f4..e4c9f0038 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2085,7 +2085,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); if ((skillinuse == EQEmu::skills::SkillDragonPunch) && GetAA(aaDragonPunch) && zone->random.Int(0, 99) < 25){ - SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff); + SpellFinished(904, other, EQEmu::CastingSlot::Item, 0, -1, spells[904].ResistDiff); other->Stun(100); } @@ -5900,7 +5900,7 @@ void Bot::DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster) { Mob::DoBuffTic(buff, slot, caster); } -bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, +bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust, uint32 aa_id) { bool Result = false; if(zone && !zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))) { @@ -5920,7 +5920,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t Message_StringID(13, MELEE_SILENCE); if(casting_spell_id) - AI_Event_SpellCastFinished(false, casting_spell_slot); + AI_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); return false; } @@ -5929,7 +5929,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t if(IsDetrimentalSpell(spell_id) && !zone->CanDoCombat()){ Message_StringID(13, SPELL_WOULDNT_HOLD); if(casting_spell_id) - AI_Event_SpellCastFinished(false, casting_spell_slot); + AI_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); return false; } @@ -5940,7 +5940,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t return false; } - if(slot < MAX_PP_MEMSPELL && !CheckFizzle(spell_id)) { + if(slot < EQEmu::CastingSlot::MaxGems && !CheckFizzle(spell_id)) { int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE; InterruptSpell(fizzle_msg, 0x121, spell_id); @@ -5954,7 +5954,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_t Log.Out(Logs::Detail, Logs::Spells, "Casting a new spell/song while singing a song. Killing old song %d.", bardsong); bardsong = 0; bardsong_target_id = 0; - bardsong_slot = 0; + bardsong_slot = EQEmu::CastingSlot::Gem1; bardsong_timer.Disable(); } @@ -6084,7 +6084,7 @@ bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) { return Result; } -bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, uint16 slot) { +bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::CastingSlot slot) { bool Result = false; SpellTargetType targetType = spells[spell_id].targettype; if(targetType == ST_GroupClientAndPet) { @@ -6097,7 +6097,7 @@ bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce return Result; } -bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 aa_id) { +bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 aa_id) { bool Result = false; if(GetClass() == BARD) cast_time = 0; @@ -6201,7 +6201,7 @@ void Bot::GenerateSpecialAttacks() { SetSpecialAbility(SPECATK_TRIPLE, 1); } -bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool& stopLogic) { +bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) { if(GetClass() == BARD) { if(!ApplyNextBardPulse(bardsong, this, bardsong_slot)) InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong); @@ -6211,7 +6211,7 @@ bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, uint16 slot return true; } -bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool& stopLogic) { +bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) { if(spellTarget) { if(IsGrouped() && (spellTarget->IsBot() || spellTarget->IsClient()) && RuleB(Bots, GroupBuffing)) { bool noGroupSpell = false; @@ -6223,7 +6223,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 bool spelltypeequal = ((spelltype == 2) || (spelltype == 16) || (spelltype == 32)); bool spelltypetargetequal = ((spelltype == 8) && (spells[thespell].targettype == ST_Self)); bool spelltypeclassequal = ((spelltype == 1024) && (GetClass() == SHAMAN)); - bool slotequal = (slot == USE_ITEM_SPELL_SLOT); + bool slotequal = (slot == EQEmu::CastingSlot::Item); if(spellequal || slotequal) { if((spelltypeequal || spelltypetargetequal) || spelltypeclassequal || slotequal) { if(((spells[thespell].effectid[0] == 0) && (spells[thespell].base[0] < 0)) && @@ -6262,7 +6262,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 return true; } -bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool& stopLogic) { +bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) { bool isMainGroupMGB = false; if(isMainGroupMGB && (GetClass() != BARD)) { BotGroupSay(this, "MGB %s", spells[spell_id].name); @@ -8251,7 +8251,7 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) { if(IsCasting()) InterruptSpell(); - CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT); + CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline); return true; } diff --git a/zone/bot.h b/zone/bot.h index b294fa108..3d45475a3 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -274,9 +274,9 @@ public: virtual void SetAttackTimer(); uint32 GetClassHPFactor(); virtual int32 CalcMaxHP(); - bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool &stopLogic); - bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool &stopLogic); - bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, uint16 slot, bool &stopLogic); + bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic); + bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic); + bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic); void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color); void Camp(bool databaseSave = true); virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false); @@ -374,12 +374,12 @@ public: virtual float GetAOERange(uint16 spell_id); virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100); virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr); - virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, + virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr, uint32 aa_id = 0); virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar); virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); - virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, uint16 slot); - virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0); + virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::CastingSlot slot); + virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0); // Bot Equipment & Inventory Class Methods void BotTradeSwapItem(Client* client, int16 lootSlot, const ItemInst* inst, const ItemInst* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap = true); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index e3b16219a..6b07bbdda 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -7613,7 +7613,7 @@ bool helper_cast_standard_spell(Bot* casting_bot, Mob* target_mob, int spell_id, if (annouce_cast) Bot::BotGroupSay(casting_bot, "Attempting to cast '%s' on %s", spells[spell_id].name, target_mob->GetCleanName()); - return casting_bot->CastSpell(spell_id, target_mob->GetID(), 1, -1, -1, dont_root_before); + return casting_bot->CastSpell(spell_id, target_mob->GetID(), EQEmu::CastingSlot::Gem2, -1, -1, dont_root_before); } bool helper_command_alias_fail(Client *bot_owner, const char* command_handler, const char *alias, const char *command) diff --git a/zone/client.cpp b/zone/client.cpp index 732485a60..bdc89e3b9 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4604,7 +4604,7 @@ void Client::HandleLDoNOpen(NPC *target) if(target->GetLDoNTrapSpellID() != 0) { Message_StringID(13, LDON_ACCIDENT_SETOFF2); - target->SpellFinished(target->GetLDoNTrapSpellID(), this, 10, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); + target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); target->SetLDoNTrapSpellID(0); target->SetLDoNTrapped(false); target->SetLDoNTrapDetected(false); @@ -4726,7 +4726,7 @@ void Client::HandleLDoNDisarm(NPC *target, uint16 skill, uint8 type) break; case -1: Message_StringID(13, LDON_ACCIDENT_SETOFF2); - target->SpellFinished(target->GetLDoNTrapSpellID(), this, 10, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); + target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); target->SetLDoNTrapSpellID(0); target->SetLDoNTrapped(false); target->SetLDoNTrapDetected(false); @@ -4745,7 +4745,7 @@ void Client::HandleLDoNPickLock(NPC *target, uint16 skill, uint8 type) if(target->IsLDoNTrapped()) { Message_StringID(13, LDON_ACCIDENT_SETOFF2); - target->SpellFinished(target->GetLDoNTrapSpellID(), this, 10, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); + target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); target->SetLDoNTrapSpellID(0); target->SetLDoNTrapped(false); target->SetLDoNTrapDetected(false); diff --git a/zone/client.h b/zone/client.h index 1d30b97ce..a17392518 100644 --- a/zone/client.h +++ b/zone/client.h @@ -105,6 +105,7 @@ enum { //Type arguments to the Message* routines. #define SPELLBAR_UNLOCK 0x2bc enum { //scribing argument to MemorizeSpell + memSpellUnknown = -1, // this modifies some state data memSpellScribing = 0, memSpellMemorize = 1, memSpellForget = 2, diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f0de676f9..a827a3008 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -3966,6 +3966,7 @@ void Client::Handle_OP_CancelTrade(const EQApplicationPacket *app) void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) { + using EQEmu::CastingSlot; if (app->size != sizeof(CastSpell_Struct)) { std::cout << "Wrong size: OP_CastSpell, size=" << app->size << ", expected " << sizeof(CastSpell_Struct) << std::endl; return; @@ -3978,13 +3979,13 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) CastSpell_Struct* castspell = (CastSpell_Struct*)app->pBuffer; - m_TargetRing = glm::vec3(castspell->x_pos, castspell->y_pos, castspell->z_pos); + m_TargetRing = glm::vec3(castspell->x_pos, castspell->y_pos, castspell->z_pos); Log.Out(Logs::General, Logs::Spells, "OP CastSpell: slot=%d, spell=%d, target=%d, inv=%lx", castspell->slot, castspell->spell_id, castspell->target_id, (unsigned long)castspell->inventoryslot); + CastingSlot slot = static_cast(castspell->slot); /* Memorized Spell */ - if (m_pp.mem_spells[castspell->slot] && m_pp.mem_spells[castspell->slot] == castspell->spell_id){ - + if (m_pp.mem_spells[castspell->slot] && m_pp.mem_spells[castspell->slot] == castspell->spell_id) { uint16 spell_to_cast = 0; if (castspell->slot < MAX_PP_MEMSPELL) { spell_to_cast = m_pp.mem_spells[castspell->slot]; @@ -3998,20 +3999,12 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) return; } - CastSpell(spell_to_cast, castspell->target_id, castspell->slot); + CastSpell(spell_to_cast, castspell->target_id, slot); } /* Spell Slot or Potion Belt Slot */ - else if ((castspell->slot == USE_ITEM_SPELL_SLOT) || (castspell->slot == POTION_BELT_SPELL_SLOT)|| (castspell->slot == TARGET_RING_SPELL_SLOT)) // ITEM or POTION cast + else if (slot == CastingSlot::Item || slot == CastingSlot::PotionBelt) // ITEM or POTION cast { - //discipline, using the item spell slot - if (castspell->inventoryslot == INVALID_INDEX) { - if (!UseDiscipline(castspell->spell_id, castspell->target_id)) { - Log.Out(Logs::General, Logs::Spells, "Unknown ability being used by %s, spell being cast is: %i\n", GetName(), castspell->spell_id); - InterruptSpell(castspell->spell_id); - } - return; - } - else if (m_inv.SupportsClickCasting(castspell->inventoryslot) || (castspell->slot == POTION_BELT_SPELL_SLOT) || (castspell->slot == TARGET_RING_SPELL_SLOT)) // sanity check + if (m_inv.SupportsClickCasting(castspell->inventoryslot) || slot == CastingSlot::PotionBelt) // sanity check { // packet field types will be reviewed as packet transistions occur const ItemInst* inst = m_inv[castspell->inventoryslot]; //slot values are int16, need to check packet on this field @@ -4036,7 +4029,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot); if (i == 0) { - CastSpell(item->Click.Effect, castspell->target_id, castspell->slot, item->CastTime, 0, 0, castspell->inventoryslot); + CastSpell(item->Click.Effect, castspell->target_id, slot, item->CastTime, 0, 0, castspell->inventoryslot); } else { InterruptSpell(castspell->spell_id); @@ -4056,7 +4049,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot); if (i == 0) { - CastSpell(item->Click.Effect, castspell->target_id, castspell->slot, item->CastTime, 0, 0, castspell->inventoryslot); + CastSpell(item->Click.Effect, castspell->target_id, slot, item->CastTime, 0, 0, castspell->inventoryslot); } else { InterruptSpell(castspell->spell_id); @@ -4081,8 +4074,8 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) InterruptSpell(castspell->spell_id); } } - /* Discipline */ - else if (castspell->slot == DISCIPLINE_SPELL_SLOT) { + /* Discipline -- older clients use the same slot as items, but we translate to it's own */ + else if (slot == CastingSlot::Discipline) { if (!UseDiscipline(castspell->spell_id, castspell->target_id)) { Log.Out(Logs::General, Logs::Spells, "Unknown ability being used by %s, spell being cast is: %i\n", GetName(), castspell->spell_id); InterruptSpell(castspell->spell_id); @@ -4090,7 +4083,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) } } /* ABILITY cast (LoH and Harm Touch) */ - else if (castspell->slot == ABILITY_SPELL_SLOT) { + else if (slot == CastingSlot::Ability) { uint16 spell_to_cast = 0; if (castspell->spell_id == SPELL_LAY_ON_HANDS && GetClass() == PALADIN) { @@ -4120,7 +4113,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) } if (spell_to_cast > 0) // if we've matched LoH or HT, cast now - CastSpell(spell_to_cast, castspell->target_id, castspell->slot); + CastSpell(spell_to_cast, castspell->target_id, slot); } return; } @@ -8410,6 +8403,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app) void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) { + using EQEmu::CastingSlot; if (app->size != sizeof(ItemVerifyRequest_Struct)) { Log.Out(Logs::General, Logs::Error, "OP size error: OP_ItemVerifyRequest expected:%i got:%i", sizeof(ItemVerifyRequest_Struct), app->size); @@ -8554,7 +8548,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) if (i == 0) { if (!IsCastWhileInvis(item->Click.Effect)) CommonBreakInvisible(); // client can't do this for us :( - CastSpell(item->Click.Effect, target_id, USE_ITEM_SPELL_SLOT, item->CastTime, 0, 0, slot_id); + CastSpell(item->Click.Effect, target_id, CastingSlot::Item, item->CastTime, 0, 0, slot_id); } } else @@ -8583,7 +8577,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) if (i == 0) { if (!IsCastWhileInvis(augitem->Click.Effect)) CommonBreakInvisible(); // client can't do this for us :( - CastSpell(augitem->Click.Effect, target_id, USE_ITEM_SPELL_SLOT, augitem->CastTime, 0, 0, slot_id); + CastSpell(augitem->Click.Effect, target_id, CastingSlot::Item, augitem->CastTime, 0, 0, slot_id); } } else diff --git a/zone/command.cpp b/zone/command.cpp index 68049cc43..95770097d 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2199,14 +2199,14 @@ void command_castspell(Client *c, const Seperator *sep) else if (c->GetTarget() == 0) if(c->Admin() >= commandInstacast) - c->SpellFinished(spellid, 0, USE_ITEM_SPELL_SLOT, 0, -1, spells[spellid].ResistDiff); + c->SpellFinished(spellid, 0, EQEmu::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff); else - c->CastSpell(spellid, 0, USE_ITEM_SPELL_SLOT, 0); + c->CastSpell(spellid, 0, EQEmu::CastingSlot::Item, 0); else if(c->Admin() >= commandInstacast) - c->SpellFinished(spellid, c->GetTarget(), 10, 0, -1, spells[spellid].ResistDiff); + c->SpellFinished(spellid, c->GetTarget(), EQEmu::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff); else - c->CastSpell(spellid, c->GetTarget()->GetID(), USE_ITEM_SPELL_SLOT, 0); + c->CastSpell(spellid, c->GetTarget()->GetID(), EQEmu::CastingSlot::Item, 0); } } diff --git a/zone/common.h b/zone/common.h index 97bb1a50b..9a5768c56 100644 --- a/zone/common.h +++ b/zone/common.h @@ -17,13 +17,6 @@ #define _NPCPET(x) (x && x->IsNPC() && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsNPC()) #define _BECOMENPCPET(x) (x && x->CastToMob()->GetOwner() && x->CastToMob()->GetOwner()->IsClient() && x->CastToMob()->GetOwner()->CastToClient()->IsBecomeNPC()) -#define USE_ITEM_SPELL_SLOT 10 -#define POTION_BELT_SPELL_SLOT 11 -#define TARGET_RING_SPELL_SLOT 12 -#define DISCIPLINE_SPELL_SLOT 10 -#define ABILITY_SPELL_SLOT 9 -#define ALTERNATE_ABILITY_SPELL_SLOT 0xFF - //LOS Parameters: #define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from #define SEE_POSITION 0.5f //ratio of GetSize() where NPCs try to see for LOS diff --git a/zone/effects.cpp b/zone/effects.cpp index 7d0b9af02..5b022f97d 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -684,9 +684,9 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { } if (reduced_recast > 0) - CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast); + CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast); else{ - CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT); + CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline); return true; } @@ -694,7 +694,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { } else { - CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT); + CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline); } return(true); } diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 124726b3f..f5b8c8382 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -759,28 +759,28 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id) { bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot) { Lua_Safe_Call_Bool(); - return self->CastSpell(spell_id, target_id, slot); + return self->CastSpell(spell_id, target_id, static_cast(slot)); } bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time) { Lua_Safe_Call_Bool(); - return self->CastSpell(spell_id, target_id, slot, cast_time); + return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time); } bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost) { Lua_Safe_Call_Bool(); - return self->CastSpell(spell_id, target_id, slot, cast_time, mana_cost); + return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost); } bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot) { Lua_Safe_Call_Bool(); - return self->CastSpell(spell_id, target_id, slot, cast_time, mana_cost, nullptr, static_cast(item_slot)); + return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost, nullptr, static_cast(item_slot)); } bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot, int timer, int timer_duration) { Lua_Safe_Call_Bool(); - return self->CastSpell(spell_id, target_id, slot, cast_time, mana_cost, nullptr, static_cast(item_slot), + return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost, nullptr, static_cast(item_slot), static_cast(timer), static_cast(timer_duration)); } @@ -789,7 +789,7 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, in Lua_Safe_Call_Bool(); int16 res = resist_adjust; - return self->CastSpell(spell_id, target_id, slot, cast_time, mana_cost, nullptr, static_cast(item_slot), + return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost, nullptr, static_cast(item_slot), static_cast(timer), static_cast(timer_duration), &res); } @@ -800,27 +800,27 @@ bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target) { bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot) { Lua_Safe_Call_Bool(); - return self->SpellFinished(spell_id, target, slot); + return self->SpellFinished(spell_id, target, static_cast(slot)); } bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used) { Lua_Safe_Call_Bool(); - return self->SpellFinished(spell_id, target, slot, mana_used); + return self->SpellFinished(spell_id, target, static_cast(slot), mana_used); } bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot) { Lua_Safe_Call_Bool(); - return self->SpellFinished(spell_id, target, slot, mana_used, inventory_slot); + return self->SpellFinished(spell_id, target, static_cast(slot), mana_used, inventory_slot); } bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot, int resist_adjust) { Lua_Safe_Call_Bool(); - return self->SpellFinished(spell_id, target, slot, mana_used, inventory_slot, resist_adjust); + return self->SpellFinished(spell_id, target, static_cast(slot), mana_used, inventory_slot, resist_adjust); } bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot, int resist_adjust, bool proc) { Lua_Safe_Call_Bool(); - return self->SpellFinished(spell_id, target, slot, mana_used, inventory_slot, resist_adjust, proc); + return self->SpellFinished(spell_id, target, static_cast(slot), mana_used, inventory_slot, resist_adjust, proc); } void Lua_Mob::SpellEffect(Lua_Mob caster, int spell_id, double partial) { diff --git a/zone/merc.cpp b/zone/merc.cpp index 4ff8e8d90..c787d00c8 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1963,7 +1963,7 @@ bool Merc::AIDoSpellCast(uint16 spellid, Mob* tar, int32 mana_cost, uint32* oDon SendPosition(); SetMoving(false); - result = CastSpell(spellid, tar->GetID(), 1, -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0); + result = CastSpell(spellid, tar->GetID(), EQEmu::CastingSlot::Gem2, -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0); if(IsCasting() && IsSitting()) Stand(); @@ -4015,7 +4015,7 @@ bool Merc::UseDiscipline(int32 spell_id, int32 target) { if(IsCasting()) InterruptSpell(); - CastSpell(spell_id, target, DISCIPLINE_SPELL_SLOT); + CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline); return(true); } diff --git a/zone/mob.cpp b/zone/mob.cpp index 580e154e7..63737617e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3225,12 +3225,12 @@ void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on, int lev twinproc = true; if (IsBeneficialSpell(spell_id)) { - SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff, true, level_override); + SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override); if(twinproc) SpellOnTarget(spell_id, this, false, false, 0, true, level_override); } else if(!(on->IsClient() && on->CastToClient()->dead)) { //dont proc on dead clients - SpellFinished(spell_id, on, 10, 0, -1, spells[spell_id].ResistDiff, true, level_override); + SpellFinished(spell_id, on, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override); if(twinproc) SpellOnTarget(spell_id, on, false, false, 0, true, level_override); } @@ -3518,10 +3518,9 @@ void Mob::TryTriggerOnCast(uint32 spell_id, bool aa_trigger) } } - void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger) { - if(!IsValidSpell(focus_spell) || !IsValidSpell(spell_id)) + if (!IsValidSpell(focus_spell) || !IsValidSpell(spell_id)) return; uint32 trigger_spell_id = 0; @@ -3532,15 +3531,17 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger) if (rank) trigger_spell_id = CastToClient()->CalcAAFocus(focusTriggerOnCast, *rank, spell_id); - if(IsValidSpell(trigger_spell_id) && GetTarget()) - SpellFinished(trigger_spell_id, GetTarget(), 10, 0, -1, spells[trigger_spell_id].ResistDiff); + if (IsValidSpell(trigger_spell_id) && GetTarget()) + SpellFinished(trigger_spell_id, GetTarget(), EQEmu::CastingSlot::Item, 0, -1, + spells[trigger_spell_id].ResistDiff); } - else{ + else { trigger_spell_id = CalcFocusEffect(focusTriggerOnCast, focus_spell, spell_id); - if(IsValidSpell(trigger_spell_id) && GetTarget()){ - SpellFinished(trigger_spell_id, GetTarget(),10, 0, -1, spells[trigger_spell_id].ResistDiff); + if (IsValidSpell(trigger_spell_id) && GetTarget()) { + SpellFinished(trigger_spell_id, GetTarget(), EQEmu::CastingSlot::Item, 0, -1, + spells[trigger_spell_id].ResistDiff); CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell); } } @@ -3570,7 +3571,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) { // If we trigger an effect then its over. if (IsValidSpell(spells[spell_id].base2[i])){ - SpellFinished(spells[spell_id].base2[i], target, 10, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); + SpellFinished(spells[spell_id].base2[i], target, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); return true; } } @@ -3589,7 +3590,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) if(zone->random.Int(0, 100) <= spells[spell_id].base[effect]) { if (IsValidSpell(spells[spell_id].base2[effect])){ - SpellFinished(spells[spell_id].base2[effect], target, 10, 0, -1, spells[spells[spell_id].base2[effect]].ResistDiff); + SpellFinished(spells[spell_id].base2[effect], target, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[effect]].ResistDiff); return true; //Only trigger once of these per spell effect. } } @@ -3666,7 +3667,7 @@ void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsP } if (use_spell){ - SpellFinished(spells[spell_id].base[i], this, 10, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spells[spell_id].base[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); if(!TryFadeEffect(e)) BuffFadeBySlot(e); @@ -3694,7 +3695,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id) if(zone->random.Roll(focus)) { Message(MT_Spells,"You twincast %s!",spells[spell_id].name); - SpellFinished(spell_id, target, 10, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, target, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } } } @@ -3712,7 +3713,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id) { if(zone->random.Roll(focus)) { - SpellFinished(spell_id, target, 10, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, target, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } } } @@ -3831,10 +3832,10 @@ bool Mob::TryFadeEffect(int slot) if(IsValidSpell(spell_id)) { if (IsBeneficialSpell(spell_id)) { - SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } else if(!(IsClient() && CastToClient()->dead)) { - SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } return true; } @@ -3868,7 +3869,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) SpellFinished(focus_trigger, target); else - SpellFinished(focus_trigger, this, 10, 0, -1, spells[focus_trigger].ResistDiff); + SpellFinished(focus_trigger, this, EQEmu::CastingSlot::Item, 0, -1, spells[focus_trigger].ResistDiff); } // For detrimental spells, if the triggered spell is beneficial, then it will land on the caster // if the triggered spell is also detrimental, then it will land on the target @@ -3878,7 +3879,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) SpellFinished(focus_trigger, this); else - SpellFinished(focus_trigger, target, 10, 0, -1, spells[focus_trigger].ResistDiff); + SpellFinished(focus_trigger, target, EQEmu::CastingSlot::Item, 0, -1, spells[focus_trigger].ResistDiff); } CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell); @@ -4529,7 +4530,7 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) if (IsValidSpell(spells[spell_id].base2[i]) && spells[spell_id].max[i] <= level) { if(zone->random.Roll(spells[spell_id].base[i])) - SpellFinished(spells[spell_id].base2[i], this, 10, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); + SpellFinished(spells[spell_id].base2[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); } } } @@ -4544,17 +4545,17 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) if(aabonuses.SpellOnKill[i] && IsValidSpell(aabonuses.SpellOnKill[i]) && (level >= aabonuses.SpellOnKill[i + 2])) { if(zone->random.Roll(static_cast(aabonuses.SpellOnKill[i + 1]))) - SpellFinished(aabonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); + SpellFinished(aabonuses.SpellOnKill[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); } if(itembonuses.SpellOnKill[i] && IsValidSpell(itembonuses.SpellOnKill[i]) && (level >= itembonuses.SpellOnKill[i + 2])){ if(zone->random.Roll(static_cast(itembonuses.SpellOnKill[i + 1]))) - SpellFinished(itembonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); + SpellFinished(itembonuses.SpellOnKill[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); } if(spellbonuses.SpellOnKill[i] && IsValidSpell(spellbonuses.SpellOnKill[i]) && (level >= spellbonuses.SpellOnKill[i + 2])) { if(zone->random.Roll(static_cast(spellbonuses.SpellOnKill[i + 1]))) - SpellFinished(spellbonuses.SpellOnKill[i], this, 10, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); + SpellFinished(spellbonuses.SpellOnKill[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); } } @@ -4571,19 +4572,19 @@ bool Mob::TrySpellOnDeath() for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) { if(IsClient() && aabonuses.SpellOnDeath[i] && IsValidSpell(aabonuses.SpellOnDeath[i])) { if(zone->random.Roll(static_cast(aabonuses.SpellOnDeath[i + 1]))) { - SpellFinished(aabonuses.SpellOnDeath[i], this, 10, 0, -1, spells[aabonuses.SpellOnDeath[i]].ResistDiff); + SpellFinished(aabonuses.SpellOnDeath[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnDeath[i]].ResistDiff); } } if(itembonuses.SpellOnDeath[i] && IsValidSpell(itembonuses.SpellOnDeath[i])) { if(zone->random.Roll(static_cast(itembonuses.SpellOnDeath[i + 1]))) { - SpellFinished(itembonuses.SpellOnDeath[i], this, 10, 0, -1, spells[itembonuses.SpellOnDeath[i]].ResistDiff); + SpellFinished(itembonuses.SpellOnDeath[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[itembonuses.SpellOnDeath[i]].ResistDiff); } } if(spellbonuses.SpellOnDeath[i] && IsValidSpell(spellbonuses.SpellOnDeath[i])) { if(zone->random.Roll(static_cast(spellbonuses.SpellOnDeath[i + 1]))) { - SpellFinished(spellbonuses.SpellOnDeath[i], this, 10, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff); + SpellFinished(spellbonuses.SpellOnDeath[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff); } } } diff --git a/zone/mob.h b/zone/mob.h index 3106df4ff..365cf672f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -26,6 +26,7 @@ #include "aa_ability.h" #include "aa.h" #include "../common/light_source.h" +#include "../common/emu_constants.h" #include #include #include @@ -218,7 +219,7 @@ public: //Song bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1); - bool ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, uint16 slot); + bool ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, EQEmu::CastingSlot slot); void BardPulse(uint16 spell_id, Mob *caster); //Spell @@ -248,23 +249,23 @@ public: void SendSpellBarEnable(uint16 spellid); void ZeroCastingVars(); virtual void SpellProcess(); - virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, + virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 *resist_adjust = nullptr, uint32 aa_id = 0); - virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, + virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 resist_adjust = 0, uint32 aa_id = 0); - void CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, uint16 mana_used, + void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQEmu::CastingSlot slot, uint16 mana_used, uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0); - bool SpellFinished(uint16 spell_id, Mob *target, uint16 slot = 10, uint16 mana_used = 0, + bool SpellFinished(uint16 spell_id, Mob *target, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, uint16 mana_used = 0, uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1); virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect = false, bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1); virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1); virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, - CastAction_type &CastAction, uint16 slot); + CastAction_type &CastAction, EQEmu::CastingSlot slot); virtual bool CheckFizzle(uint16 spell_id); virtual bool CheckSpellLevelRestriction(uint16 spell_id); virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); @@ -1215,7 +1216,7 @@ protected: int attacked_count; bool delaytimer; uint16 casting_spell_targetid; - uint16 casting_spell_slot; + EQEmu::CastingSlot casting_spell_slot; uint16 casting_spell_mana; uint32 casting_spell_inventory_slot; uint32 casting_spell_timer; @@ -1225,7 +1226,7 @@ protected: uint32 casting_spell_aa_id; bool casting_spell_checks; uint16 bardsong; - uint8 bardsong_slot; + EQEmu::CastingSlot bardsong_slot; uint32 bardsong_target_id; bool ActiveProjectileATK; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index ef7d222dd..eb795f6c3 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -341,7 +341,7 @@ bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain SetCurrentSpeed(0); } - return CastSpell(AIspells[i].spellid, tar->GetID(), 1, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust)); + return CastSpell(AIspells[i].spellid, tar->GetID(), EQEmu::CastingSlot::Gem2, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust)); } bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint16 iSpellTypes) { @@ -673,11 +673,11 @@ void Client::AI_SpellCast() } uint32 spell_to_cast = 0xFFFFFFFF; - uint32 slot_to_use = 10; + EQEmu::CastingSlot slot_to_use = EQEmu::CastingSlot::Item; if(valid_spells.size() == 1) { spell_to_cast = valid_spells[0]; - slot_to_use = slots[0]; + slot_to_use = static_cast(slots[0]); } else if(valid_spells.empty()) { @@ -687,7 +687,7 @@ void Client::AI_SpellCast() { uint32 idx = zone->random.Int(0, (valid_spells.size()-1)); spell_to_cast = valid_spells[idx]; - slot_to_use = slots[idx]; + slot_to_use = static_cast(slots[idx]); } if(IsMezSpell(spell_to_cast) || IsFearSpell(spell_to_cast)) diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 4a6fab4e4..f171d8d79 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -3982,12 +3982,12 @@ XS(XS_Mob_CastSpell) { dXSARGS; if (items < 3 || items > 7) - Perl_croak(aTHX_ "Usage: Mob::CastSpell(THIS, spell_id, target_id, slot= 10, casttime= -1, mana_cost= -1, resist_adjust = 0)"); + Perl_croak(aTHX_ "Usage: Mob::CastSpell(THIS, spell_id, target_id, slot= 22, casttime= -1, mana_cost= -1, resist_adjust = 0)"); { Mob * THIS; uint16 spell_id = (uint16)SvUV(ST(1)); uint16 target_id = (uint16)SvUV(ST(2)); - uint16 slot; + EQEmu::CastingSlot slot; int32 casttime; int32 mana_cost; int16 resist_adjust; @@ -4002,9 +4002,9 @@ XS(XS_Mob_CastSpell) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); if (items < 4) - slot = 10; + slot = EQEmu::CastingSlot::Item; else { - slot = (uint16)SvUV(ST(3)); + slot = static_cast(SvUV(ST(3))); } if (items < 5) @@ -4085,7 +4085,7 @@ XS(XS_Mob_SpellFinished) resist_diff = spells[spell_id].ResistDiff; } - THIS->SpellFinished(spell_id, spell_target, 10, mana_cost, -1, resist_diff); + THIS->SpellFinished(spell_id, spell_target, EQEmu::CastingSlot::Item, mana_cost, -1, resist_diff); } XSRETURN_EMPTY; } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index fdd9c3df2..78fc2b206 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -365,14 +365,14 @@ void QuestManager::castspell(int spell_id, int target_id) { if (owner) { Mob *tgt = entity_list.GetMob(target_id); if(tgt != nullptr) - owner->SpellFinished(spell_id, tgt, 10, 0, -1, spells[spell_id].ResistDiff); + owner->SpellFinished(spell_id, tgt, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } } void QuestManager::selfcast(int spell_id) { QuestManagerCurrentQuestVars(); if (initiator) - initiator->SpellFinished(spell_id, initiator, 10, 0, -1, spells[spell_id].ResistDiff); + initiator->SpellFinished(spell_id, initiator, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } void QuestManager::addloot(int item_id, int charges, bool equipitem) { diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 8b4cf0af8..41fb18ef2 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -149,7 +149,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 IsValidSpell(aabonuses.SkillAttackProc[2])) { float chance = aabonuses.SkillAttackProc[0] / 1000.0f; if (zone->random.Roll(chance)) - SpellFinished(aabonuses.SkillAttackProc[2], who, 10, 0, -1, + SpellFinished(aabonuses.SkillAttackProc[2], who, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } who->Damage(this, max_damage, SPELL_UNKNOWN, skill, false); @@ -2429,7 +2429,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: IsValidSpell(aabonuses.SkillAttackProc[2])) { float chance = aabonuses.SkillAttackProc[0] / 1000.0f; if (zone->random.Roll(chance)) - SpellFinished(aabonuses.SkillAttackProc[2], other, 10, 0, -1, + SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 0209ba4df..4c5b805ad 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2745,7 +2745,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (caster && IsValidSpell(spells[spell_id].base2[i])){ if(zone->random.Roll(spells[spell_id].base[i])) - caster->SpellFinished(spells[spell_id].base2[i], this, 10, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); + caster->SpellFinished(spells[spell_id].base2[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); } break; } @@ -5135,7 +5135,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo if (Caston_spell_id) { if (IsValidSpell(Caston_spell_id) && (Caston_spell_id != spell_id)) - SpellFinished(Caston_spell_id, this, 10, 0, -1, spells[Caston_spell_id].ResistDiff); + SpellFinished(Caston_spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[Caston_spell_id].ResistDiff); } return (value * lvlModifier / 100); @@ -6683,10 +6683,10 @@ void Mob::TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker){ if (IsValidSpell(spell_id)) { if (IsBeneficialSpell(spell_id)) - SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); else if(attacker) - SpellFinished(spell_id, attacker, 10, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, attacker, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } } } diff --git a/zone/spells.cpp b/zone/spells.cpp index b1565be7f..6ae4d3920 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -104,6 +104,8 @@ extern Zone* zone; extern volatile bool is_zone_loaded; extern WorldServer worldserver; +using EQEmu::CastingSlot; + // this is run constantly for every mob void Mob::SpellProcess() { @@ -145,13 +147,13 @@ void NPC::SpellProcess() // the rule is you can cast one triggered (usually timed) spell at a time // but things like SpellFinished() can run concurrent with a triggered cast // to allow procs to work -bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, +bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 timer, uint32 timer_duration, int16 *resist_adjust, uint32 aa_id) { Log.Out(Logs::Detail, Logs::Spells, "CastSpell called for spell %s (%d) on entity %d, slot %d, time %d, mana %d, from item slot %d", - (IsValidSpell(spell_id))?spells[spell_id].name:"UNKNOWN SPELL", spell_id, target_id, slot, cast_time, mana_cost, (item_slot==0xFFFFFFFF)?999:item_slot); + (IsValidSpell(spell_id))?spells[spell_id].name:"UNKNOWN SPELL", spell_id, target_id, static_cast(slot), cast_time, mana_cost, (item_slot==0xFFFFFFFF)?999:item_slot); if(casting_spell_id == spell_id) ZeroCastingVars(); @@ -178,7 +180,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, if(IsClient()) CastToClient()->SendSpellBarEnable(spell_id); if(casting_spell_id && IsNPC()) - CastToNPC()->AI_Event_SpellCastFinished(false, casting_spell_slot); + CastToNPC()->AI_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); return(false); } //It appears that the Sanctuary effect is removed by a check on the client side (keep this however for redundancy) @@ -201,7 +203,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, if(IsClient()) CastToClient()->SendSpellBarEnable(spell_id); if(casting_spell_id && IsNPC()) - CastToNPC()->AI_Event_SpellCastFinished(false, casting_spell_slot); + CastToNPC()->AI_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); return(false); } @@ -231,7 +233,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, // check for fizzle // note that CheckFizzle itself doesn't let NPCs fizzle, // but this code allows for it. - if(slot < MAX_PP_MEMSPELL && !CheckFizzle(spell_id)) + if(slot < CastingSlot::MaxGems && !CheckFizzle(spell_id)) { int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE; InterruptSpell(fizzle_msg, 0x121, spell_id); @@ -252,7 +254,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, } //Added to prevent MQ2 exploitation of equipping normally-unequippable/clickable items with effects and clicking them for benefits. - if(item_slot && IsClient() && ((slot == USE_ITEM_SPELL_SLOT) || (slot == POTION_BELT_SPELL_SLOT) || (slot == TARGET_RING_SPELL_SLOT))) + if(item_slot && IsClient() && (slot == CastingSlot::Item || slot == CastingSlot::PotionBelt)) { ItemInst *itm = CastToClient()->GetInv().GetItem(item_slot); int bitmask = 1; @@ -336,7 +338,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, // this is the 2nd phase of CastSpell, broken up like this to make it easier // to repeat a spell for bard songs // -bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, +bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 timer, uint32 timer_duration, int16 resist_adjust, uint32 aa_id) @@ -353,7 +355,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, const SPDat_Spell_Struct &spell = spells[spell_id]; Log.Out(Logs::Detail, Logs::Spells, "DoCastSpell called for spell %s (%d) on entity %d, slot %d, time %d, mana %d, from item %d", - spell.name, spell_id, target_id, slot, cast_time, mana_cost, item_slot==0xFFFFFFFF?999:item_slot); + spell.name, spell_id, target_id, static_cast(slot), cast_time, mana_cost, item_slot==0xFFFFFFFF?999:item_slot); casting_spell_id = spell_id; casting_spell_slot = slot; @@ -418,7 +420,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, // If you're at full mana, let it cast even if you dont have enough mana // we calculated this above, now enforce it - if(mana_cost > 0 && slot != USE_ITEM_SPELL_SLOT) + if(mana_cost > 0 && slot != CastingSlot::Item) { int my_curmana = GetMana(); int my_maxmana = GetMaxMana(); @@ -487,7 +489,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, safe_delete(outapp); outapp = nullptr; - if (IsClient() && slot == USE_ITEM_SPELL_SLOT &&item_slot != 0xFFFFFFFF) { + if (IsClient() && slot == CastingSlot::Item && item_slot != 0xFFFFFFFF) { auto item = CastToClient()->GetInv().GetItem(item_slot); if (item && item->GetItem()) Message_StringID(MT_Spells, BEGINS_TO_GLOW, item->GetItem()->Name); @@ -767,7 +769,7 @@ void Mob::ZeroCastingVars() spellend_timer.Disable(); casting_spell_id = 0; casting_spell_targetid = 0; - casting_spell_slot = 0; + casting_spell_slot = CastingSlot::Gem1; casting_spell_mana = 0; casting_spell_inventory_slot = 0; casting_spell_timer = 0; @@ -802,7 +804,7 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) } if(casting_spell_id && IsNPC()) { - CastToNPC()->AI_Event_SpellCastFinished(false, casting_spell_slot); + CastToNPC()->AI_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); } if(casting_spell_aa_id && IsClient()) { //Rest AA Timer on failed cast @@ -880,12 +882,12 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) // NOTE: do not put range checking, etc into this function. this should // just check timed spell specific things before passing off to SpellFinished // which figures out proper targets etc -void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, +void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slot, uint16 mana_used, uint32 inventory_slot, int16 resist_adjust) { bool IsFromItem = false; - if(IsClient() && slot != USE_ITEM_SPELL_SLOT && slot != POTION_BELT_SPELL_SLOT && slot != TARGET_RING_SPELL_SLOT && spells[spell_id].recast_time > 1000) { // 10 is item + if(IsClient() && slot != CastingSlot::Item && slot != CastingSlot::Item && spells[spell_id].recast_time > 1000) { // 10 is item if(!CastToClient()->GetPTimers().Expired(&database, pTimerSpellStart + spell_id, false)) { //should we issue a message or send them a spell gem packet? Message_StringID(13, SPELL_RECAST); @@ -895,7 +897,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, } } - if(IsClient() && ((slot == USE_ITEM_SPELL_SLOT) || (slot == POTION_BELT_SPELL_SLOT) || (slot == TARGET_RING_SPELL_SLOT))) + if(IsClient() && (slot == CastingSlot::Item || slot == CastingSlot::PotionBelt)) { IsFromItem = true; ItemInst *itm = CastToClient()->GetInv().GetItem(inventory_slot); @@ -1193,7 +1195,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, int16 DeleteChargeFromSlot = -1; - if(IsClient() && ((slot == USE_ITEM_SPELL_SLOT) || (slot == POTION_BELT_SPELL_SLOT) || (slot == TARGET_RING_SPELL_SLOT)) + if(IsClient() && (slot == CastingSlot::Item || slot == CastingSlot::PotionBelt) && inventory_slot != 0xFFFFFFFF) // 10 is an item { bool fromaug = false; @@ -1307,7 +1309,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, if(IsClient()) { this->CastToClient()->CheckSongSkillIncrease(spell_id); - this->CastToClient()->MemorizeSpell(slot, spell_id, memSpellSpellbar); + this->CastToClient()->MemorizeSpell(static_cast(slot), spell_id, memSpellSpellbar); } Log.Out(Logs::Detail, Logs::Spells, "Bard song %d should be started", spell_id); } @@ -1319,21 +1321,18 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, SendSpellBarEnable(spell_id); // this causes the delayed refresh of the spell bar gems - c->MemorizeSpell(slot, spell_id, memSpellSpellbar); + c->MemorizeSpell(static_cast(slot), spell_id, memSpellSpellbar); // this tells the client that casting may happen again SetMana(GetMana()); // skills - if(slot < MAX_PP_MEMSPELL) - { - c->CheckIncreaseSkill(spells[spell_id].skill, nullptr); + c->CheckIncreaseSkill(spells[spell_id].skill, nullptr); - // increased chance of gaining channel skill if you regained concentration - c->CheckIncreaseSkill(EQEmu::skills::SkillChanneling, nullptr, regain_conc ? 5 : 0); + // increased chance of gaining channel skill if you regained concentration + c->CheckIncreaseSkill(EQEmu::skills::SkillChanneling, nullptr, regain_conc ? 5 : 0); - c->CheckSpecializeIncrease(spell_id); - } + c->CheckSpecializeIncrease(spell_id); } } @@ -1348,8 +1347,8 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, } -bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, uint16 slot) { - +bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, CastingSlot slot) +{ /* The basic types of spells: @@ -1682,7 +1681,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce case ST_Group: case ST_GroupNoPets: { - if(IsClient() && CastToClient()->TGB() && IsTGBCompatibleSpell(spell_id) && slot != USE_ITEM_SPELL_SLOT) { + if(IsClient() && CastToClient()->TGB() && IsTGBCompatibleSpell(spell_id) && slot != CastingSlot::Item) { if( (!target) || (target->IsNPC() && !(target->GetOwner() && target->GetOwner()->IsClient())) || (target->IsCorpse()) ) @@ -1904,7 +1903,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce // only used from CastedSpellFinished, and procs // we can't interrupt in this, or anything called from this! // if you need to abort the casting, return false -bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 mana_used, +bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, uint16 mana_used, uint32 inventory_slot, int16 resist_adjust, bool isproc, int level_override) { //EQApplicationPacket *outapp = nullptr; @@ -2263,7 +2262,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 bool mgb = HasMGB() && spells[spell_id].can_mgb; // if this was a spell slot or an ability use up the mana for it - if(slot != USE_ITEM_SPELL_SLOT && slot != POTION_BELT_SPELL_SLOT && slot != TARGET_RING_SPELL_SLOT && mana_used > 0) + if(slot != CastingSlot::Item && slot != CastingSlot::PotionBelt && mana_used > 0) { mana_used = GetActSpellCost(spell_id, mana_used); if (mgb) { @@ -2326,7 +2325,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 } } - if(IsClient() && ((slot == USE_ITEM_SPELL_SLOT) || (slot == POTION_BELT_SPELL_SLOT) || (slot == TARGET_RING_SPELL_SLOT))) + if(IsClient() && (slot == CastingSlot::Item || slot == CastingSlot::PotionBelt)) { ItemInst *itm = CastToClient()->GetInv().GetItem(inventory_slot); if(itm && itm->GetItem()->RecastDelay > 0){ @@ -2345,7 +2344,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 } if(IsNPC()) - CastToNPC()->AI_Event_SpellCastFinished(true, slot); + CastToNPC()->AI_Event_SpellCastFinished(true, static_cast(slot)); return true; } @@ -2360,8 +2359,8 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 * * return false to stop the song */ -bool Mob::ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, uint16 slot) { - if(slot == USE_ITEM_SPELL_SLOT) { +bool Mob::ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, CastingSlot slot) { + if(slot == CastingSlot::Item) { //bard songs should never come from items... Log.Out(Logs::Detail, Logs::Spells, "Bard Song Pulse %d: Supposidly cast from an item. Killing song.", spell_id); return(false); @@ -3769,7 +3768,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r } if (IsValidSpell(spells[spell_id].RecourseLink) && spells[spell_id].RecourseLink != spell_id) - SpellFinished(spells[spell_id].RecourseLink, this, 10, 0, -1, spells[spells[spell_id].RecourseLink].ResistDiff); + SpellFinished(spells[spell_id].RecourseLink, this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].RecourseLink].ResistDiff); if (IsDetrimentalSpell(spell_id)) { @@ -5245,7 +5244,7 @@ bool Mob::UseBardSpellLogic(uint16 spell_id, int slot) spell_id = casting_spell_id; if(slot == -1) - slot = casting_spell_slot; + slot = static_cast(casting_spell_slot); // should we treat this as a bard singing? return @@ -5273,7 +5272,7 @@ void Mob::_StopSong() { bardsong = 0; bardsong_target_id = 0; - bardsong_slot = 0; + bardsong_slot = CastingSlot::Gem1; bardsong_timer.Disable(); } diff --git a/zone/trap.cpp b/zone/trap.cpp index 5a644bb03..87000f940 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -115,7 +115,7 @@ void Trap::Trigger(Mob* trigger) entity_list.MessageClose(trigger,false,100,13,"%s",message.c_str()); } if(hiddenTrigger){ - hiddenTrigger->SpellFinished(effectvalue, trigger, 10, 0, -1, spells[effectvalue].ResistDiff); + hiddenTrigger->SpellFinished(effectvalue, trigger, EQEmu::CastingSlot::Item, 0, -1, spells[effectvalue].ResistDiff); } break; case trapTypeAlarm: From f612f8be429a9dfdf15965cd72a29d6186b95927 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 31 Jul 2016 17:35:33 -0400 Subject: [PATCH 233/693] Fix typo --- zone/spells.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 6ae4d3920..e605bfca8 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -887,7 +887,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo { bool IsFromItem = false; - if(IsClient() && slot != CastingSlot::Item && slot != CastingSlot::Item && spells[spell_id].recast_time > 1000) { // 10 is item + if(IsClient() && slot != CastingSlot::Item && slot != CastingSlot::PotionBelt && spells[spell_id].recast_time > 1000) { // 10 is item if(!CastToClient()->GetPTimers().Expired(&database, pTimerSpellStart + spell_id, false)) { //should we issue a message or send them a spell gem packet? Message_StringID(13, SPELL_RECAST); @@ -3768,7 +3768,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r } if (IsValidSpell(spells[spell_id].RecourseLink) && spells[spell_id].RecourseLink != spell_id) - SpellFinished(spells[spell_id].RecourseLink, this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].RecourseLink].ResistDiff); + SpellFinished(spells[spell_id].RecourseLink, this, CastingSlot::Item, 0, -1, spells[spells[spell_id].RecourseLink].ResistDiff); if (IsDetrimentalSpell(spell_id)) { From e862994716c14a7df14279525e109d192d9f93aa Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 31 Jul 2016 18:09:04 -0400 Subject: [PATCH 234/693] RoF/RoF2 spell gem refresh in PP This fixes issues with long recast spells --- common/patches/rof.cpp | 7 ++++--- common/patches/rof2.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 014e6f8d9..b7cde6af8 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2269,12 +2269,13 @@ namespace RoF outapp->WriteUInt32(0xFFFFFFFFU); } - outapp->WriteUInt32(13); // Unknown count + outapp->WriteUInt32(13); // gem refresh count - for (uint32 r = 0; r < 13; r++) + for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) { - outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(emu->spellSlotRefresh[r]); // spell gem refresh } + outapp->WriteUInt32(0); // also refresh -- historically HT/LoH :P outapp->WriteUInt8(0); // Unknown diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 79802e262..1699eefae 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2356,12 +2356,13 @@ namespace RoF2 outapp->WriteUInt32(0xFFFFFFFFU); } - outapp->WriteUInt32(13); // Unknown count + outapp->WriteUInt32(13); // gem refresh counts - for (uint32 r = 0; r < 13; r++) + for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) { - outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(emu->spellSlotRefresh[r]); // spell gem refresh } + outapp->WriteUInt32(0); // also refresh -- historically HT/LoH :P outapp->WriteUInt8(0); // Unknown From 2bae779a9b72c9637a299a6ff7cbb780681cc5cf Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 2 Aug 2016 16:48:58 -0400 Subject: [PATCH 235/693] NPCs don't have separate buff windows --- zone/client.h | 2 ++ zone/mob.h | 2 ++ zone/spells.cpp | 42 ++++++++++++++++++++++++++++++------------ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/zone/client.h b/zone/client.h index a17392518..32d0e176c 100644 --- a/zone/client.h +++ b/zone/client.h @@ -511,6 +511,8 @@ public: virtual int GetMaxSongSlots() const { return 12; } virtual int GetMaxDiscSlots() const { return 1; } virtual int GetMaxTotalSlots() const { return 38; } + virtual uint32 GetFirstBuffSlot(bool disc, bool song); + virtual uint32 GetLastBuffSlot(bool disc, bool song); virtual void InitializeBuffSlots(); virtual void UninitializeBuffSlots(); diff --git a/zone/mob.h b/zone/mob.h index 365cf672f..a01a4b8f5 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -307,6 +307,8 @@ public: virtual int GetMaxSongSlots() const { return 0; } virtual int GetMaxDiscSlots() const { return 0; } virtual int GetMaxTotalSlots() const { return 0; } + virtual uint32 GetFirstBuffSlot(bool disc, bool song); + virtual uint32 GetLastBuffSlot(bool disc, bool song); virtual void InitializeBuffSlots() { buffs = nullptr; current_buff_count = 0; } virtual void UninitializeBuffSlots() { } EQApplicationPacket *MakeBuffsPacket(bool for_target = true); diff --git a/zone/spells.cpp b/zone/spells.cpp index e605bfca8..38d30b53b 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3046,6 +3046,34 @@ bool Client::CheckSpellLevelRestriction(uint16 spell_id) return true; } +uint32 Mob::GetFirstBuffSlot(bool disc, bool song) +{ + return 0; +} + +uint32 Mob::GetLastBuffSlot(bool disc, bool song) +{ + return GetCurrentBuffSlots(); +} + +uint32 Client::GetFirstBuffSlot(bool disc, bool song) +{ + if (disc) + return GetMaxBuffSlots() + GetMaxSongSlots(); + if (song) + return GetMaxBuffSlots(); + return 0; +} + +uint32 Client::GetLastBuffSlot(bool disc, bool song) +{ + if (disc) + return GetMaxBuffSlots() + GetMaxSongSlots() + GetCurrentDiscSlots(); + if (song) + return GetMaxBuffSlots() + GetCurrentSongSlots(); + return GetCurrentBuffSlots(); +} + // returns the slot the buff was added to, -1 if it wasn't added due to // stacking problems, and -2 if this is not a buff // if caster is null, the buff will be added with the caster level being @@ -3083,18 +3111,8 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid // we also check if overwriting will occur. this is so after this loop // we can determine if there will be room for this buff int buff_count = GetMaxTotalSlots(); - uint32 start_slot = 0; - uint32 end_slot = 0; - if (IsDisciplineBuff(spell_id)) { - start_slot = GetMaxBuffSlots() + GetMaxSongSlots(); - end_slot = start_slot + GetCurrentDiscSlots(); - } else if(spells[spell_id].short_buff_box) { - start_slot = GetMaxBuffSlots(); - end_slot = start_slot + GetCurrentSongSlots(); - } else { - start_slot = 0; - end_slot = GetCurrentBuffSlots(); - } + uint32 start_slot = GetFirstBuffSlot(IsDisciplineBuff(spell_id), spells[spell_id].short_buff_box); + uint32 end_slot = GetLastBuffSlot(IsDisciplineBuff(spell_id), spells[spell_id].short_buff_box); for (buffslot = 0; buffslot < buff_count; buffslot++) { const Buffs_Struct &curbuf = buffs[buffslot]; From 7c9bd80c1e5dc482ec1880dcc51f14dff1012ea5 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 2 Aug 2016 17:49:08 -0400 Subject: [PATCH 236/693] Changed SendZoneSpawnsBulk to a more like-like behavior --- changelog.txt | 6 ++++++ zone/entity.cpp | 29 +++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/changelog.txt b/changelog.txt index 5221f170b..db7133b0b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/02/2016 == +Uleat: Changed 'SendZoneSpawnsBulk' behavior to use near/far criteria (live-like) when sending packets. + - Zone-to-Zone client loading will see a small decrease in time (less than 10~15%) + - World-to-Zone client loading appears to greatly benefit from this (tested 'devastation' - pre-change: ~22 seconds, post-change: 12~15 seconds) + - This change does not affect the final spawning of mobs in the client + == 07/31/2016 == mackal: Implement more spell gems! - There are a few things still left to due like make dealing with losing gems nice (reset AAs, going to an older client etc) diff --git a/zone/entity.cpp b/zone/entity.cpp index d398c9bf6..5da1190d0 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1228,7 +1228,9 @@ void EntityList::SendZoneSpawnsBulk(Client *client) maxspawns = mob_list.size(); auto bzsp = new BulkZoneSpawnPacket(client, maxspawns); - int32 race=-1; + bool delaypkt = false; + const glm::vec4& cpos = client->GetPosition(); + const float dmax = 600.0 * 600.0; for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { spawn = it->second; if (spawn && spawn->GetID() > 0 && spawn->Spawned()) { @@ -1236,8 +1238,30 @@ void EntityList::SendZoneSpawnsBulk(Client *client) spawn->CastToClient()->IsHoveringForRespawn())) continue; - race = spawn->GetRace(); +#if 1 + const glm::vec4& spos = spawn->GetPosition(); + + delaypkt = false; + if (DistanceSquared(cpos, spos) > dmax || (spawn->IsClient() && (spawn->GetRace() == MINOR_ILL_OBJ || spawn->GetRace() == TREE))) + delaypkt = true; + + if (delaypkt) { + app = new EQApplicationPacket; + spawn->CreateSpawnPacket(app); + client->QueuePacket(app, true, Client::CLIENT_CONNECTED); + safe_delete(app); + } + else { + memset(&ns, 0, sizeof(NewSpawn_Struct)); + spawn->FillSpawnStruct(&ns, client); + bzsp->AddSpawn(&ns); + } + spawn->SendArmorAppearance(client); +#else + /* original code kept for spawn packet research */ + int32 race = spawn->GetRace(); + // Illusion races on PCs don't work as a mass spawn // But they will work as an add_spawn AFTER CLIENT_CONNECTED. if (spawn->IsClient() && (race == MINOR_ILL_OBJ || race == TREE)) { @@ -1255,6 +1279,7 @@ void EntityList::SendZoneSpawnsBulk(Client *client) // Despite being sent in the OP_ZoneSpawns packet, the client // does not display worn armor correctly so display it. spawn->SendArmorAppearance(client); +#endif } } safe_delete(bzsp); From 64cf613189abe6ce195ae1db2ca9130b90695a06 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 2 Aug 2016 19:00:33 -0400 Subject: [PATCH 237/693] Update GetCurrentBuffSlots() for TSS free slots The client also checks if you have any bonus from spells and items so why not check that as well --- zone/spells.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 38d30b53b..fbda108f0 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5466,10 +5466,14 @@ void Mob::BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration) int Client::GetCurrentBuffSlots() const { - if(15 + aabonuses.BuffSlotIncrease > 25) - return 25; - else - return 15 + aabonuses.BuffSlotIncrease; + int numbuffs = 15; + // client does check spells and items + numbuffs += aabonuses.BuffSlotIncrease + spellbonuses.BuffSlotIncrease + itembonuses.BuffSlotIncrease; + if (GetLevel() > 70) + numbuffs++; + if (GetLevel() > 74) + numbuffs++; + return EQEmu::ClampUpper(numbuffs, GetMaxBuffSlots()); } int Client::GetCurrentSongSlots() const From d68a3b191e7f8429e0db6d96207565b0e366da25 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 2 Aug 2016 21:08:05 -0400 Subject: [PATCH 238/693] Give pets 30 buff because that's what they got --- common/eq_packet_structs.h | 5 +++-- common/patches/rof.cpp | 6 +++--- common/patches/rof2.cpp | 6 +++--- common/patches/sod.cpp | 4 ++-- common/patches/sof.cpp | 4 ++-- common/patches/titanium.cpp | 4 ++-- common/patches/uf.cpp | 6 +++--- common/ruletypes.h | 2 +- zone/bot.cpp | 8 ++++---- zone/bot_database.cpp | 4 ++-- zone/spells.cpp | 4 ++-- zone/zonedb.cpp | 3 ++- zone/zonedb.h | 2 +- 13 files changed, 30 insertions(+), 28 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index ab0447cb8..fc1c9f9e7 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -30,6 +30,7 @@ static const uint32 BUFF_COUNT = 25; +static const uint32 PET_BUFF_COUNT = 30; static const uint32 MAX_MERC = 100; static const uint32 MAX_MERC_GRADES = 10; static const uint32 MAX_MERC_STANCES = 10; @@ -522,8 +523,8 @@ struct BuffRemoveRequest_Struct struct PetBuff_Struct { /*000*/ uint32 petid; -/*004*/ uint32 spellid[BUFF_COUNT+5]; -/*124*/ int32 ticsremaining[BUFF_COUNT+5]; +/*004*/ uint32 spellid[PET_BUFF_COUNT]; +/*124*/ int32 ticsremaining[PET_BUFF_COUNT]; /*244*/ uint32 buffcount; }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index b7cde6af8..bee434ec3 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2012,18 +2012,18 @@ namespace RoF __packet->WriteUInt8(1); // 1 indicates all buffs on the pet (0 to add or remove a single buff) __packet->WriteUInt16(emu->buffcount); - for (uint16 i = 0; i < BUFF_COUNT; ++i) + for (uint16 i = 0; i < PET_BUFF_COUNT; ++i) { if (emu->spellid[i]) { __packet->WriteUInt32(i); __packet->WriteUInt32(emu->spellid[i]); __packet->WriteUInt32(emu->ticsremaining[i]); - __packet->WriteUInt32(0); // Unknown + __packet->WriteUInt32(0); // numhits __packet->WriteString(""); } } - __packet->WriteUInt8(0); // Unknown + __packet->WriteUInt8(0); // some sort of type FINISH_ENCODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 1699eefae..52fdeb02b 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2099,18 +2099,18 @@ namespace RoF2 __packet->WriteUInt8(1); // 1 indicates all buffs on the pet (0 to add or remove a single buff) __packet->WriteUInt16(emu->buffcount); - for (uint16 i = 0; i < BUFF_COUNT; ++i) + for (uint16 i = 0; i < PET_BUFF_COUNT; ++i) { if (emu->spellid[i]) { __packet->WriteUInt32(i); __packet->WriteUInt32(emu->spellid[i]); __packet->WriteUInt32(emu->ticsremaining[i]); - __packet->WriteUInt32(0); // Unknown + __packet->WriteUInt32(0); // num hits __packet->WriteString(""); } } - __packet->WriteUInt8(0); // Unknown + __packet->WriteUInt8(0); // some sort of type FINISH_ENCODE(); } diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 52bbdc309..4def89212 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1502,7 +1502,7 @@ namespace SoD VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petid); VARSTRUCT_ENCODE_TYPE(uint16, Buffer, emu->buffcount); - for (unsigned int i = 0; i < BUFF_COUNT; ++i) + for (unsigned int i = 0; i < PET_BUFF_COUNT; ++i) { if (emu->spellid[i]) { @@ -1513,7 +1513,7 @@ namespace SoD } } - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->buffcount); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->buffcount); // I think this is actually some sort of type delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 4f804bb03..a34e5029a 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1177,9 +1177,9 @@ namespace SoF OUT(petid); OUT(buffcount); - int EQBuffSlot = 0; + int EQBuffSlot = 0; // do we really want to shuffle them around like this? - for (uint32 EmuBuffSlot = 0; EmuBuffSlot < BUFF_COUNT; ++EmuBuffSlot) + for (uint32 EmuBuffSlot = 0; EmuBuffSlot < PET_BUFF_COUNT; ++EmuBuffSlot) { if (emu->spellid[EmuBuffSlot]) { diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 28984a26f..cc10f6487 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -891,9 +891,9 @@ namespace Titanium OUT(petid); OUT(buffcount); - int EQBuffSlot = 0; + int EQBuffSlot = 0; // do we really want to shuffle them around like this? - for (uint32 EmuBuffSlot = 0; EmuBuffSlot < BUFF_COUNT; ++EmuBuffSlot) + for (uint32 EmuBuffSlot = 0; EmuBuffSlot < PET_BUFF_COUNT; ++EmuBuffSlot) { if (emu->spellid[EmuBuffSlot]) { diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 735243f09..3e03c8bb2 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1764,18 +1764,18 @@ namespace UF VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); VARSTRUCT_ENCODE_TYPE(uint16, Buffer, emu->buffcount); - for (unsigned int i = 0; i < BUFF_COUNT; ++i) + for (unsigned int i = 0; i < PET_BUFF_COUNT; ++i) { if (emu->spellid[i]) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, i); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spellid[i]); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->ticsremaining[i]); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // numhits VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string. Name of the caster of the buff. } } - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->buffcount); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->buffcount); /// I think this is actually some sort of type delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); diff --git a/common/ruletypes.h b/common/ruletypes.h index 41dbeacd2..1a64b1ebd 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -329,7 +329,7 @@ RULE_INT(Spells, MaxBuffSlotsNPC, 25) RULE_INT(Spells, MaxSongSlotsNPC, 10) RULE_INT(Spells, MaxDiscSlotsNPC, 1) RULE_INT(Spells, MaxTotalSlotsNPC, 36) -RULE_INT(Spells, MaxTotalSlotsPET, 25) // do not set this higher than 25 until the player profile is removed from the blob +RULE_INT(Spells, MaxTotalSlotsPET, 30) // do not set this higher than 25 until the player profile is removed from the blob RULE_BOOL (Spells, EnableBlockedBuffs, true) RULE_INT(Spells, ReflectType, 1) //0 = disabled, 1 = single target player spells only, 2 = all player spells, 3 = all single target spells, 4 = all spells RULE_INT(Spells, VirusSpreadDistance, 30) // The distance a viral spell will jump to its next victim diff --git a/zone/bot.cpp b/zone/bot.cpp index e4c9f0038..14acc9b57 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1709,8 +1709,8 @@ bool Bot::LoadPet() NPC *pet_inst = GetPet()->CastToNPC(); - SpellBuff_Struct pet_buffs[BUFF_COUNT]; - memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * BUFF_COUNT)); + SpellBuff_Struct pet_buffs[PET_BUFF_COUNT]; + memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * PET_BUFF_COUNT)); if (!botdb.LoadPetBuffs(GetBotID(), pet_buffs)) bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetBuffs(), GetCleanName()); @@ -1741,11 +1741,11 @@ bool Bot::SavePet() return false; char* pet_name = new char[64]; - SpellBuff_Struct pet_buffs[BUFF_COUNT]; + SpellBuff_Struct pet_buffs[PET_BUFF_COUNT]; uint32 pet_items[EQEmu::legacy::EQUIPMENT_SIZE]; memset(pet_name, 0, 64); - memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * BUFF_COUNT)); + memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * PET_BUFF_COUNT)); memset(pet_items, 0, (sizeof(uint32) * EQEmu::legacy::EQUIPMENT_SIZE)); pet_inst->GetPetState(pet_buffs, pet_items, pet_name); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 300f4c8b4..db9827a8a 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1472,7 +1472,7 @@ bool BotDatabase::LoadPetBuffs(const uint32 bot_id, SpellBuff_Struct* pet_buffs) return true; int buff_index = 0; - for (auto row = results.begin(); row != results.end() && buff_index < BUFF_COUNT; ++row) { + for (auto row = results.begin(); row != results.end() && buff_index < PET_BUFF_COUNT; ++row) { pet_buffs[buff_index].spellid = atoi(row[0]); pet_buffs[buff_index].level = atoi(row[1]); pet_buffs[buff_index].duration = atoi(row[2]); @@ -1509,7 +1509,7 @@ bool BotDatabase::SavePetBuffs(const uint32 bot_id, const SpellBuff_Struct* pet_ if (!saved_pet_index) return true; - for (int buff_index = 0; buff_index < BUFF_COUNT; ++buff_index) { + for (int buff_index = 0; buff_index < PET_BUFF_COUNT; ++buff_index) { if (!pet_buffs[buff_index].spellid || pet_buffs[buff_index].spellid == SPELL_UNKNOWN) continue; diff --git a/zone/spells.cpp b/zone/spells.cpp index fbda108f0..60837381e 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5368,8 +5368,8 @@ void Mob::SendPetBuffsToClient() int MaxSlots = GetMaxTotalSlots(); - if(MaxSlots > BUFF_COUNT) - MaxSlots = BUFF_COUNT; + if(MaxSlots > PET_BUFF_COUNT) + MaxSlots = PET_BUFF_COUNT; for(int buffslot = 0; buffslot < MaxSlots; buffslot++) { diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index d0c80f37f..7f86f5110 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3178,7 +3178,8 @@ void ZoneDatabase::SavePetInfo(Client *client) query.clear(); // pet buffs! - for (int index = 0; index < RuleI(Spells, MaxTotalSlotsPET); index++) { + int max_slots = RuleI(Spells, MaxTotalSlotsPET); + for (int index = 0; index < max_slots; index++) { if (petinfo->Buffs[index].spellid == SPELL_UNKNOWN || petinfo->Buffs[index].spellid == 0) continue; if (query.length() == 0) diff --git a/zone/zonedb.h b/zone/zonedb.h index ef5a6810d..689f9a82f 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -125,7 +125,7 @@ struct PetInfo { uint32 HP; uint32 Mana; float size; - SpellBuff_Struct Buffs[BUFF_COUNT]; + SpellBuff_Struct Buffs[PET_BUFF_COUNT]; uint32 Items[EQEmu::legacy::EQUIPMENT_SIZE]; char Name[64]; }; From 37ecc690882f19da4765910a68521fe80a2cd22f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 2 Aug 2016 21:10:32 -0400 Subject: [PATCH 239/693] Update UF packet stuff to have 30 BUFF_COUNT --- common/patches/uf.cpp | 2 +- common/patches/uf_structs.h | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 3e03c8bb2..1ff6c8e82 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1870,7 +1870,7 @@ namespace UF OUT(thirst_level); OUT(hunger_level); //PS this needs to be figured out more; but it was 'good enough' - for (r = 0; r < structs::BUFF_COUNT; r++) + for (r = 0; r < BUFF_COUNT; r++) { if (emu->buffs[r].spellid != 0xFFFF && emu->buffs[r].spellid != 0) { diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 7ef766d86..3c582e6e6 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -26,7 +26,7 @@ namespace UF namespace structs { -static const uint32 BUFF_COUNT = 25; +static const uint32 BUFF_COUNT = 30; /* ** Compiler override to ensure @@ -958,8 +958,7 @@ struct PlayerProfile_Struct /*07880*/ uint32 toxicity; // Potion Toxicity (15=too toxic, each potion adds 3) /*07884*/ uint32 thirst_level; // Drink (ticks till next drink) /*07888*/ uint32 hunger_level; // Food (ticks till next eat) -/*07892*/ SpellBuff_Struct buffs[BUFF_COUNT]; // [1900] Buffs currently on the player (30 Max) - (Each Size 76) -/*09792*/ uint8 unknown09792[380]; // BUFF_COUNT has been left at 25. These are the extra 5 buffs in Underfoot +/*07892*/ SpellBuff_Struct buffs[BUFF_COUNT]; // [2280] Buffs currently on the player (30 Max) - (Each Size 76) /*10172*/ Disciplines_Struct disciplines; // [400] Known disciplines /*10972*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (UNIX Time of last use) /*11052*/ uint8 unknown11052[160]; // Some type of Timers @@ -2167,9 +2166,7 @@ struct GroupFollow_Struct { // Underfoot Follow Struct struct InspectBuffs_Struct { /*000*/ uint32 spell_id[BUFF_COUNT]; -/*100*/ uint32 filler100[5]; // BUFF_COUNT is really 30... /*120*/ int32 tics_remaining[BUFF_COUNT]; -/*220*/ uint32 filler220[5]; // BUFF_COUNT is really 30... }; From 69db67efe581d690057c5895ac52bbcd524ee67d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 2 Aug 2016 23:32:37 -0400 Subject: [PATCH 240/693] Remove extra save --- zone/mob.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 63737617e..e056a81c2 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2357,7 +2357,6 @@ void Mob::SetZone(uint32 zone_id, uint32 instance_id) { CastToClient()->GetPP().zone_id = zone_id; CastToClient()->GetPP().zoneInstance = instance_id; - CastToClient()->Save(); } Save(); } From 16125c38af323b5c3df347298e12fefe5003bd2d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 Aug 2016 00:13:47 -0400 Subject: [PATCH 241/693] Lets not save here if we're zoning --- zone/client_process.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 354d5b6aa..06054e620 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -624,7 +624,7 @@ bool Client::Process() { { //client logged out or errored out //ResetTrade(); - if (client_state != CLIENT_KICKED) { + if (client_state != CLIENT_KICKED && !zoning) { Save(); } From acb5bb3e3ed160bde02aa40449254ab15196750b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 Aug 2016 00:33:22 -0400 Subject: [PATCH 242/693] If this flag is set, we JUST saved Also saved due to an OP_Save very recently ... --- zone/client_process.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 06054e620..e1a769743 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -624,7 +624,7 @@ bool Client::Process() { { //client logged out or errored out //ResetTrade(); - if (client_state != CLIENT_KICKED && !zoning) { + if (client_state != CLIENT_KICKED && !zoning && !instalog) { Save(); } From f26dce39c33c1eac53a453f3629fa98f1b101473 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 Aug 2016 01:13:51 -0400 Subject: [PATCH 243/693] Rate limit saving to at most once a second There are A LOT of unneeded saves ... This will prevent a lot of excessive database hits at least with very little room to exploit --- zone/client.cpp | 8 +++++++- zone/client.h | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index bdc89e3b9..7cfdf512f 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -155,7 +155,8 @@ Client::Client(EQStreamInterface* ieqs) m_Proximity(FLT_MAX, FLT_MAX, FLT_MAX), //arbitrary large number m_ZoneSummonLocation(-2.0f,-2.0f,-2.0f), m_AutoAttackPosition(0.0f, 0.0f, 0.0f, 0.0f), - m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f) + m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f), + m_lastsave(-1) { for(int cf=0; cf < _FilterCount; cf++) ClientFilters[cf] = FilterShow; @@ -569,6 +570,10 @@ bool Client::Save(uint8 iCommitNow) { if(!ClientDataLoaded()) return false; + // saved less than 2 seconds ago, lets just skip for now + if ((time(nullptr) - m_lastsave) < 2) + return true; + /* Wrote current basics to PP for saves */ m_pp.x = m_Position.x; m_pp.y = m_Position.y; @@ -658,6 +663,7 @@ bool Client::Save(uint8 iCommitNow) { database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp, &m_epp); /* Save Character Data */ + m_lastsave = time(nullptr); return true; } diff --git a/zone/client.h b/zone/client.h index 32d0e176c..e7b7b50b9 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1458,6 +1458,9 @@ private: Timer helm_toggle_timer; Timer light_update_timer; + + time_t m_lastsave; + glm::vec3 m_Proximity; void BulkSendInventoryItems(); From 538d6a2a33561ad95dbc624edcce653885f7167c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 Aug 2016 01:44:33 -0400 Subject: [PATCH 244/693] Hack to fix RNG Nature Veil line --- common/spdat.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index ab9150122..eeaf2be60 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -235,8 +235,11 @@ bool IsBeneficialSpell(uint16 spell_id) // If the resisttype is magic and SpellAffectIndex is Calm/memblur/dispell sight // it's not beneficial if (spells[spell_id].resisttype == RESIST_MAGIC) { - if (sai == SAI_Calm || sai == SAI_Dispell_Sight || - sai == SAI_Memory_Blur || sai == SAI_Calm_Song) + // checking these SAI cause issues with the rng defensive proc line + // So I guess instead of fixing it for real, just a quick hack :P + if (spells[spell_id].effectid[0] != SE_DefensiveProc && + (sai == SAI_Calm || sai == SAI_Dispell_Sight || sai == SAI_Memory_Blur || + sai == SAI_Calm_Song)) return false; } else { // If the resisttype is not magic and spell is Bind Sight or Cast Sight From 60f2d14caa9bcadc72a9a47ea0324b5e109fc7b3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 Aug 2016 17:37:09 -0400 Subject: [PATCH 245/693] Rework bash/kick stun based on client This is what the client is doing. It doesn't reuse all the old rules, so those can't be tweaked unless someone wants to add them back in --- common/races.h | 1 + common/spdat.h | 2 +- zone/attack.cpp | 106 ++++++++++++++++++++++------------------------ zone/string_ids.h | 3 +- 4 files changed, 55 insertions(+), 57 deletions(-) diff --git a/common/races.h b/common/races.h index 050b2fd78..d34d9b754 100644 --- a/common/races.h +++ b/common/races.h @@ -45,6 +45,7 @@ #define TIGER 63 #define ELEMENTAL 75 #define ALLIGATOR 91 +#define OGGOK_CITIZEN 93 #define EYE_OF_ZOMM 108 #define WOLF_ELEMENTAL 120 #define INVISIBLE_MAN 127 diff --git a/common/spdat.h b/common/spdat.h index cb6e49fc9..2734f6078 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -446,7 +446,7 @@ typedef enum { #define SE_IncreaseRunSpeedCap 290 // implemented[AA] - increases run speed over the hard cap #define SE_Purify 291 // implemented - Removes determental effects #define SE_StrikeThrough2 292 // implemented[AA] - increasing chance of bypassing an opponent's special defenses, such as dodge, block, parry, and riposte. -#define SE_FrontalStunResist 293 // implemented[AA] - Reduce chance to be stunned from front. +#define SE_FrontalStunResist 293 // implemented[AA] - Reduce chance to be stunned from front. -- live descriptions sounds like this isn't limited to frontal anymore #define SE_CriticalSpellChance 294 // implemented - increase chance to critical hit and critical damage modifier. //#define SE_ReduceTimerSpecial 295 // not used #define SE_FcSpellVulnerability 296 // implemented - increase in incoming spell damage diff --git a/zone/attack.cpp b/zone/attack.cpp index 54f98c97a..d4d8f141c 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -23,6 +23,7 @@ #include "../common/skills.h" #include "../common/spdat.h" #include "../common/string_util.h" +#include "../common/data_verification.h" #include "queryserv.h" #include "quest_parser_collection.h" #include "string_ids.h" @@ -3169,68 +3170,63 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons BuffFadeByEffect(SE_Mez); } - //check stun chances if bashing - if (damage > 0 && ((skill_used == EQEmu::skills::SkillBash || skill_used == EQEmu::skills::SkillKick) && attacker)) { - // NPCs can stun with their bash/kick as soon as they receive it. - // Clients can stun mobs under level 56 with their kick when they get level 55 or greater. - // Clients have a chance to stun if the mob is 56+ - - // Calculate the chance to stun - int stun_chance = 0; - if (!GetSpecialAbility(UNSTUNABLE)) { - if (attacker->IsNPC()) { - stun_chance = RuleI(Combat, NPCBashKickStunChance); - } else if (attacker->IsClient()) { - // Less than base immunity - // Client vs. Client always uses the chance - if (!IsClient() && GetLevel() <= RuleI(Spells, BaseImmunityLevel)) { - if (skill_used == EQEmu::skills::SkillBash) // Bash always will - stun_chance = 100; - else if (attacker->GetLevel() >= RuleI(Combat, ClientStunLevel)) - stun_chance = 100; // only if you're over level 55 and using kick - } else { // higher than base immunity or Client vs. Client - // not sure on this number, use same as NPC for now - if (skill_used == EQEmu::skills::SkillKick && attacker->GetLevel() < RuleI(Combat, ClientStunLevel)) - stun_chance = RuleI(Combat, NPCBashKickStunChance); - else if (skill_used == EQEmu::skills::SkillBash) - stun_chance = RuleI(Combat, NPCBashKickStunChance) + - attacker->spellbonuses.StunBashChance + - attacker->itembonuses.StunBashChance + - attacker->aabonuses.StunBashChance; - } - } + // broken up for readability + // This is based on what the client is doing + // We had a bunch of stuff like BaseImmunityLevel checks, which I think is suppose to just be for spells + // This is missing some merc checks, but those mostly just skipped the spell bonuses I think ... + bool can_stun = false; + int stunbash_chance = 0; // bonus + if (attacker) { + if (skill_used == EQEmu::skills::SkillBash) { + can_stun = true; + if (attacker->IsClient()) + stunbash_chance = attacker->spellbonuses.StunBashChance + + attacker->itembonuses.StunBashChance + + attacker->aabonuses.StunBashChance; + } else if (skill_used == EQEmu::skills::SkillKick && + (attacker->GetLevel() > 55 || attacker->IsNPC()) && GetClass() == WARRIOR) { + can_stun = true; } - if (stun_chance && zone->random.Roll(stun_chance)) { - // Passed stun, try to resist now - int stun_resist = itembonuses.StunResist + spellbonuses.StunResist; - int frontal_stun_resist = itembonuses.FrontalStunResist + spellbonuses.FrontalStunResist; - - Log.Out(Logs::Detail, Logs::Combat, "Stun passed, checking resists. Was %d chance.", stun_chance); - if (IsClient()) { - stun_resist += aabonuses.StunResist; - frontal_stun_resist += aabonuses.FrontalStunResist; - } - - // frontal stun check for ogres/bonuses - if (((GetBaseRace() == OGRE && IsClient()) || - (frontal_stun_resist && zone->random.Roll(frontal_stun_resist))) && - !attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) { - Log.Out(Logs::Detail, Logs::Combat, "Frontal stun resisted. %d chance.", frontal_stun_resist); - - } else { - // Normal stun resist check. - if (stun_resist && zone->random.Roll(stun_resist)) { + if ((GetBaseRace() == OGRE || GetBaseRace() == OGGOK_CITIZEN) && + !attacker->BehindMob(this, attacker->GetX(), attacker->GetY())) + can_stun = false; + if (GetSpecialAbility(UNSTUNABLE)) + can_stun = false; + } + if (can_stun) { + int bashsave_roll = zone->random.Int(0, 100); + if (bashsave_roll > 98 || bashsave_roll > (55 - stunbash_chance)) { + // did stun -- roll other resists + // SE_FrontalStunResist description says any angle now a days + int stun_resist2 = spellbonuses.FrontalStunResist + itembonuses.FrontalStunResist + + aabonuses.FrontalStunResist; + if (zone->random.Int(1, 100) > stun_resist2) { + // stun resist 2 failed + // time to check SE_StunResist and mod2 stun resist + int stun_resist = + spellbonuses.StunResist + itembonuses.StunResist + aabonuses.StunResist; + if (zone->random.Int(0, 100) >= stun_resist) { + // did stun + // nothing else to check! + Stun(2000); // straight 2 seconds every time + } else { + // stun resist passed! if (IsClient()) Message_StringID(MT_Stun, SHAKE_OFF_STUN); - Log.Out(Logs::Detail, Logs::Combat, "Stun Resisted. %d chance.", stun_resist); - } else { - Log.Out(Logs::Detail, Logs::Combat, "Stunned. %d resist chance.", stun_resist); - Stun(zone->random.Int(0, 2) * 1000); // 0-2 seconds } + } else { + // stun resist 2 passed! + if (IsClient()) + Message_StringID(MT_Stun, AVOID_STUNNING_BLOW); } } else { - Log.Out(Logs::Detail, Logs::Combat, "Stun failed. %d chance.", stun_chance); + // main stun failed -- extra interrupt roll + if (IsCasting() && + !EQEmu::ValueWithin(casting_spell_id, 859, 1023)) // these spells are excluded + // 90% chance >< -- stun immune won't reach this branch though :( + if (zone->random.Int(0, 9) > 1) + InterruptSpell(); } } diff --git a/zone/string_ids.h b/zone/string_ids.h index be05b1eb2..e1fb4de7c 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -297,6 +297,7 @@ #define ADVENTURE_COMPLETE 5147 //You received %1 points for successfully completing the adventure. #define SUCCOR_FAIL 5169 //The portal collapes before you can escape! #define PET_ATTACKING 5501 //%1 tells you, 'Attacking %2 Master.' +#define AVOID_STUNNING_BLOW 5753 //You avoid the stunning blow. #define FATAL_BOW_SHOT 5745 //%1 performs a FATAL BOW SHOT!! #define MELEE_SILENCE 5806 //You *CANNOT* use this melee ability, you are suffering from amnesia! #define DISCIPLINE_REUSE_MSG 5807 //You can use the ability %1 again in %2 hour(s) %3 minute(s) %4 seconds. @@ -354,7 +355,7 @@ #define HIT_NON_MELEE 9073 //%1 hit %2 for %3 points of non-melee damage. #define GLOWS_BLUE 9074 //Your %1 glows blue. #define GLOWS_RED 9075 //Your %1 glows red. -#define SHAKE_OFF_STUN 9077 +#define SHAKE_OFF_STUN 9077 //You shake off the stun effect! #define STRIKETHROUGH_STRING 9078 //You strike through your opponent's defenses! #define SPELL_REFLECT 9082 //%1's spell has been reflected by %2. #define NEW_SPELLS_AVAIL 9149 //You have new spells available to you. Check the merchants near your guild master. From 66fec40169ea4236ce007dfd64cf8af7147ecfd4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 Aug 2016 22:38:33 -0400 Subject: [PATCH 246/693] Move Enrage check to after the immune ripo check --- zone/attack.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index d4d8f141c..2b37be197 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -370,18 +370,15 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) counter_dodge = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 4); } - ////////////////////////////////////////////////////////// - // make enrage same as riposte - ///////////////////////////////////////////////////////// - if (IsEnraged() && InFront) { - damage = -3; - Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack."); - } - // riposte -- it may seem crazy, but if the attacker has SPA 173 on them, they are immune to Ripo bool ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance; // Need to check if we have something in MainHand to actually attack with (or fists) if (hand != EQEmu::legacy::SlotRange && CanThisClassRiposte() && InFront && !ImmuneRipo) { + if (IsEnraged()) { + damage = -3; + Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack."); + return true; + } if (IsClient()) CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillRiposte, other, -10); // check auto discs ... I guess aa/items too :P From c81a5e078370e48d8ed6626e7bc6da530ae964ac Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 Aug 2016 23:06:00 -0400 Subject: [PATCH 247/693] Limit casting skill ups to casting skills --- common/skills.cpp | 13 +++++++++++++ common/skills.h | 9 +++++---- zone/spells.cpp | 10 ++++++---- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/common/skills.cpp b/common/skills.cpp index 9be28781f..b1cf59c12 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -110,6 +110,19 @@ bool EQEmu::skills::IsBardInstrumentSkill(SkillType skill) } } +bool EQEmu::skills::IsCastingSkill(SkillType skill) +{ + switch (skill) { + case SkillAbjuration: + case SkillAlteration: + case SkillConjuration: + case SkillEvocation: + return true; + default: + return false; + } +} + const std::map& EQEmu::skills::GetSkillTypeMap() { /* VS2013 code diff --git a/common/skills.h b/common/skills.h index cd7603667..19a996729 100644 --- a/common/skills.h +++ b/common/skills.h @@ -161,10 +161,11 @@ namespace EQEmu // server profile does not reflect this yet..so, prefixed with 'PACKET_' #define PACKET_SKILL_ARRAY_SIZE 100 - extern bool IsTradeskill(SkillType skill); - extern bool IsSpecializedSkill(SkillType skill); - extern float GetSkillMeleePushForce(SkillType skill); - extern bool IsBardInstrumentSkill(SkillType skill); + bool IsTradeskill(SkillType skill); + bool IsSpecializedSkill(SkillType skill); + float GetSkillMeleePushForce(SkillType skill); + bool IsBardInstrumentSkill(SkillType skill); + bool IsCastingSkill(SkillType skill); extern const std::map& GetSkillTypeMap(); diff --git a/zone/spells.cpp b/zone/spells.cpp index 60837381e..0eebcb082 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1327,12 +1327,14 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo SetMana(GetMana()); // skills - c->CheckIncreaseSkill(spells[spell_id].skill, nullptr); + if (EQEmu::skills::IsCastingSkill(spells[spell_id].skill)) { + c->CheckIncreaseSkill(spells[spell_id].skill, nullptr); - // increased chance of gaining channel skill if you regained concentration - c->CheckIncreaseSkill(EQEmu::skills::SkillChanneling, nullptr, regain_conc ? 5 : 0); + // increased chance of gaining channel skill if you regained concentration + c->CheckIncreaseSkill(EQEmu::skills::SkillChanneling, nullptr, regain_conc ? 5 : 0); - c->CheckSpecializeIncrease(spell_id); + c->CheckSpecializeIncrease(spell_id); + } } } From 33407ee0daeb140eedda654cc53313f2835e9bf9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 Aug 2016 23:14:02 -0400 Subject: [PATCH 248/693] Forgot divination --- common/skills.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/common/skills.cpp b/common/skills.cpp index b1cf59c12..a23d77a7b 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -116,6 +116,7 @@ bool EQEmu::skills::IsCastingSkill(SkillType skill) case SkillAbjuration: case SkillAlteration: case SkillConjuration: + case SkillDivination: case SkillEvocation: return true; default: From d0fbbed20d42f119b21cd7849a79efaa9cb7530d Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 4 Aug 2016 07:09:34 -0400 Subject: [PATCH 249/693] Added a trap for Bot::GetNeedsCured() random crash (bot server admins: watch your logs!) --- zone/bot.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 14acc9b57..a3dd19b2d 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -8159,7 +8159,25 @@ bool Bot::GetNeedsCured(Mob *tar) { int buffsWithCounters = 0; needCured = true; for (unsigned int j = 0; j < buff_count; j++) { - if(tar->GetBuffs()[j].spellid != SPELL_UNKNOWN) { + // this should prevent crashes until the cause can be found + if (!tar->GetBuffs()) { + std::string mob_type = "Unknown"; + if (tar->IsClient()) + mob_type = "Client"; + else if (tar->IsBot()) + mob_type = "Bot"; + else if (tar->IsMerc()) + mob_type = "Merc"; + else if (tar->IsPet()) + mob_type = "Pet"; + else if (tar->IsNPC()) + mob_type = "NPC"; + + Log.Out(Logs::General, Logs::Error, "Bot::GetNeedsCured() processed mob type '%s' with a null buffs pointer (mob: '%s')", mob_type.c_str(), tar->GetName()); + + continue; + } + else if(tar->GetBuffs()[j].spellid != SPELL_UNKNOWN) { if(CalculateCounters(tar->GetBuffs()[j].spellid) > 0) { buffsWithCounters++; if(buffsWithCounters == 1 && (tar->GetBuffs()[j].ticsremaining < 2 || (int32)((tar->GetBuffs()[j].ticsremaining * 6) / tar->GetBuffs()[j].counters) < 2)) { From 8dc8e5321889635a8b15318e0bd298918e7e4df8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 Aug 2016 13:50:20 -0400 Subject: [PATCH 250/693] Added some more comments to PassCastRestrictions --- zone/spell_effects.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 4c5b805ad..5708541d4 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6226,7 +6226,7 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama { /*If return TRUE spell met all restrictions and can continue (this = target). This check is used when the spell_new field CastRestriction is defined OR spell effect '0'(DD/Heal) has a defined limit - Range 1 : UNKNOWN + Range 1 : UNKNOWN -- the spells with this seem to not have a restiction, true for now Range 100 : *Animal OR Humanoid Range 101 : *Dragon Range 102 : *Animal OR Insect @@ -6253,7 +6253,10 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama Range 124 : *Undead HP < 10% Range 125 : *Clockwork HP < 10% Range 126 : *Wisp HP < 10% - Range 127-130 : UNKNOWN + Range 127 : UNKNOWN + Range 128 : pure melee -- guess + Range 129 : pure caster -- guess + Range 130 : hybrid -- guess Range 150 : UNKNOWN Range 190 : No Raid boss flag *not implemented Range 191 : This spell will deal less damage to 'exceptionally strong targets' - Raid boss flag *not implemented @@ -6265,12 +6268,17 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama Range 300 - 303 : UNKOWN *not implemented Range 304 : Chain + Plate class (buffs) Range 399 - 409 : Heal if HP within a specified range (400 = 0-25% 401 = 25 - 35% 402 = 35-45% ect) - Range 410 - 411 : UNKOWN + Range 410 - 411 : UNKOWN -- examples are auras that cast on NPCs maybe in combat/out of combat? Range 500 - 599 : Heal if HP less than a specified value Range 600 - 699 : Limit to Body Type [base2 - 600 = Body] Range 700 : NPC only -- from patch notes "Wizard - Arcane Fusion no longer deals damage to non-NPC targets. This should ensure that wizards who fail their Bucolic Gambit are slightly less likely to annihilate themselves." Range 701 : NOT PET - Range 800 : UKNOWN + Range 800 : UKNOWN -- Target's Target Test (16598) + Range 812 : UNKNOWN -- triggered by Thaumatize Owner + Range 814 : UNKNOWN -- Vegetentacles + Range 815 : UNKNOWN -- Pumpkin Pulp Splash + Range 816 : UNKNOWN -- Rotten Fruit Splash + Range 817 : UNKNOWN -- Tainted Bixie Pollen Splash Range 818 - 819 : If Undead/If Not Undead Range 820 - 822 : UKNOWN Range 835 : Unknown *not implemented @@ -6290,6 +6298,9 @@ bool Mob::PassCastRestriction(bool UseCastRestriction, int16 value, bool IsDama switch(value) { + case 1: + return true; + case 100: if ((GetBodyType() == BT_Animal) || (GetBodyType() == BT_Humanoid)) return true; From e89fa01d8977901b1e014df803a5959b259d7c95 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 Aug 2016 20:33:29 -0400 Subject: [PATCH 251/693] Port Aggro:UseLevelAggro from EQMacEmu This will make level 18+ mobs braver --- common/ruletypes.h | 1 + zone/aggro.cpp | 58 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 1a64b1ebd..14288391e 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -518,6 +518,7 @@ RULE_REAL(Aggro, TunnelVisionAggroMod, 0.75) //people not currently the top hate RULE_INT(Aggro, MaxScalingProcAggro, 400) // Set to -1 for no limit. Maxmimum amount of aggro that HP scaling SPA effect in a proc will add. RULE_INT(Aggro, IntAggroThreshold, 75) // Int <= this will aggro regardless of level difference. RULE_BOOL(Aggro, AllowTickPulling, false) // tick pulling is an exploit in an NPC's call for help fixed sometime in 2006 on live +RULE_BOOL(Aggro, UseLevelAggro, true) // Level 18+ and Undead will aggro regardless of level difference. (this will disabled Rule:IntAggroThreshold if set to true) RULE_CATEGORY_END() RULE_CATEGORY(TaskSystem) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 847c51e76..4cf403545 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -156,10 +156,21 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) { return; } - if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GREEN ) { - towho->Message(0, "...%s is red to me (basically)", mob->GetName(), - dist2, iAggroRange2); - return; + if (RuleB(Aggro, UseLevelAggro)) + { + if (GetLevel() < 18 && mob->GetLevelCon(GetLevel()) == CON_GREEN && GetBodyType() != 3) + { + towho->Message(0, "...%s is red to me (basically)", mob->GetName(), dist2, iAggroRange2); + return; + } + } + else + { + if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GREEN ) { + towho->Message(0, "...%s is red to me (basically)", mob->GetName(), + dist2, iAggroRange2); + return; + } } if(verbose) { @@ -321,11 +332,12 @@ bool Mob::CheckWillAggro(Mob *mob) { int heroicCHA_mod = mob->itembonuses.HeroicCHA/25; // 800 Heroic CHA cap if(heroicCHA_mod > THREATENLY_ARRGO_CHANCE) heroicCHA_mod = THREATENLY_ARRGO_CHANCE; - if + if (RuleB(Aggro, UseLevelAggro) && ( //old InZone check taken care of above by !mob->CastToClient()->Connected() ( - ( GetINT() <= RuleI(Aggro, IntAggroThreshold) ) + ( GetLevel() >= 18 ) + ||(GetBodyType() == 3) ||( mob->IsClient() && mob->CastToClient()->IsSitting() ) ||( mob->GetLevelCon(GetLevel()) != CON_GREEN ) @@ -344,6 +356,7 @@ bool Mob::CheckWillAggro(Mob *mob) { ) ) ) + ) { //FatherNiwtit: make sure we can see them. last since it is very expensive if(CheckLosFN(mob)) { @@ -351,6 +364,39 @@ bool Mob::CheckWillAggro(Mob *mob) { return( mod_will_aggro(mob, this) ); } } + else + { + if + ( + //old InZone check taken care of above by !mob->CastToClient()->Connected() + ( + ( GetINT() <= RuleI(Aggro, IntAggroThreshold) ) + ||( mob->IsClient() && mob->CastToClient()->IsSitting() ) + ||( mob->GetLevelCon(GetLevel()) != CON_GREEN ) + + ) + && + ( + ( + fv == FACTION_SCOWLS + || + (mob->GetPrimaryFaction() != GetPrimaryFaction() && mob->GetPrimaryFaction() == -4 && GetOwner() == nullptr) + || + ( + fv == FACTION_THREATENLY + && zone->random.Roll(THREATENLY_ARRGO_CHANCE - heroicCHA_mod) + ) + ) + ) + ) + { + //FatherNiwtit: make sure we can see them. last since it is very expensive + if(CheckLosFN(mob)) { + Log.Out(Logs::Detail, Logs::Aggro, "Check aggro for %s target %s.", GetName(), mob->GetName()); + return( mod_will_aggro(mob, this) ); + } + } + } Log.Out(Logs::Detail, Logs::Aggro, "Is In zone?:%d\n", mob->InZone()); Log.Out(Logs::Detail, Logs::Aggro, "Dist^2: %f\n", dist2); From 1d12f92934c0a1fb9defeed43dd4ac914e666cb9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 Aug 2016 20:36:15 -0400 Subject: [PATCH 252/693] Level 50+ NPCs will now respond to yells for help regardless of con color --- zone/aggro.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 4cf403545..d50c1d43e 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -508,7 +508,7 @@ void EntityList::AIYellForHelp(Mob* sender, Mob* attacker) { { //if they are in range, make sure we are not green... //then jump in if they are our friend - if(attacker->GetLevelCon(mob->GetLevel()) != CON_GREEN) + if(mob->GetLevel() >= 50 || attacker->GetLevelCon(mob->GetLevel()) != CON_GREEN) { bool useprimfaction = false; if(mob->GetPrimaryFaction() == sender->CastToNPC()->GetPrimaryFaction()) From d53d569020a41f5d013b893a9fdf8e90688898cb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 Aug 2016 22:12:33 -0400 Subject: [PATCH 253/693] Port EQMacEmu's improved NPC stat scaling formula Old formula can be used by setting NPC::NewLevelSacling to false --- common/ruletypes.h | 1 + zone/npc.cpp | 116 +++++++++++++++++++++++++++++++-------------- 2 files changed, 82 insertions(+), 35 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 14288391e..8ef840c96 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -503,6 +503,7 @@ RULE_BOOL(NPC, EnableMeritBasedFaction, false) // If set to true, faction will g RULE_INT(NPC, NPCToNPCAggroTimerMin, 500) RULE_INT(NPC, NPCToNPCAggroTimerMax, 6000) RULE_BOOL(NPC, UseClassAsLastName, true) // Uses class archetype as LastName for npcs with none +RULE_BOOL(NPC, NewLevelScaling, true) // Better level scaling, use old if new formulas would break your server RULE_CATEGORY_END() RULE_CATEGORY(Aggro) diff --git a/zone/npc.cpp b/zone/npc.cpp index d1d9e8a44..15e96f3bf 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -2006,44 +2006,90 @@ void NPC::LevelScale() { float scaling = (((random_level / (float)level) - 1) * (scalerate / 100.0f)); - // Compensate for scale rates at low levels so they don't add too much - uint8 scale_adjust = 1; - if(level > 0 && level <= 5) - scale_adjust = 10; - if(level > 5 && level <= 10) - scale_adjust = 5; - if(level > 10 && level <= 15) - scale_adjust = 3; - if(level > 15 && level <= 25) - scale_adjust = 2; + if (RuleB(NPC, NewLevelScaling)) { + if (scalerate == 0 || maxlevel <= 25) { + // pre-pop seems to scale by 20 HP increments while newer by 100 + // We also don't want 100 increments on newer noobie zones, check level + if (zone->GetZoneID() < 200 || level < 48) { + max_hp += (random_level - level) * 20; + base_hp += (random_level - level) * 20; + } else { + max_hp += (random_level - level) * 100; + base_hp += (random_level - level) * 100; + } - base_hp += (int)(base_hp * scaling); - max_hp += (int)(max_hp * scaling); - cur_hp = max_hp; - STR += (int)(STR * scaling / scale_adjust); - STA += (int)(STA * scaling / scale_adjust); - AGI += (int)(AGI * scaling / scale_adjust); - DEX += (int)(DEX * scaling / scale_adjust); - INT += (int)(INT * scaling / scale_adjust); - WIS += (int)(WIS * scaling / scale_adjust); - CHA += (int)(CHA * scaling / scale_adjust); - if (MR) - MR += (int)(MR * scaling / scale_adjust); - if (CR) - CR += (int)(CR * scaling / scale_adjust); - if (DR) - DR += (int)(DR * scaling / scale_adjust); - if (FR) - FR += (int)(FR * scaling / scale_adjust); - if (PR) - PR += (int)(PR * scaling / scale_adjust); + cur_hp = max_hp; + max_dmg += (random_level - level) * 2; + } else { + uint8 scale_adjust = 1; + + base_hp += (int)(base_hp * scaling); + max_hp += (int)(max_hp * scaling); + cur_hp = max_hp; + + if (max_dmg) { + max_dmg += (int)(max_dmg * scaling / scale_adjust); + min_dmg += (int)(min_dmg * scaling / scale_adjust); + } + + STR += (int)(STR * scaling / scale_adjust); + STA += (int)(STA * scaling / scale_adjust); + AGI += (int)(AGI * scaling / scale_adjust); + DEX += (int)(DEX * scaling / scale_adjust); + INT += (int)(INT * scaling / scale_adjust); + WIS += (int)(WIS * scaling / scale_adjust); + CHA += (int)(CHA * scaling / scale_adjust); + if (MR) + MR += (int)(MR * scaling / scale_adjust); + if (CR) + CR += (int)(CR * scaling / scale_adjust); + if (DR) + DR += (int)(DR * scaling / scale_adjust); + if (FR) + FR += (int)(FR * scaling / scale_adjust); + if (PR) + PR += (int)(PR * scaling / scale_adjust); + } + } else { + // Compensate for scale rates at low levels so they don't add too much + uint8 scale_adjust = 1; + if(level > 0 && level <= 5) + scale_adjust = 10; + if(level > 5 && level <= 10) + scale_adjust = 5; + if(level > 10 && level <= 15) + scale_adjust = 3; + if(level > 15 && level <= 25) + scale_adjust = 2; + + base_hp += (int)(base_hp * scaling); + max_hp += (int)(max_hp * scaling); + cur_hp = max_hp; + STR += (int)(STR * scaling / scale_adjust); + STA += (int)(STA * scaling / scale_adjust); + AGI += (int)(AGI * scaling / scale_adjust); + DEX += (int)(DEX * scaling / scale_adjust); + INT += (int)(INT * scaling / scale_adjust); + WIS += (int)(WIS * scaling / scale_adjust); + CHA += (int)(CHA * scaling / scale_adjust); + if (MR) + MR += (int)(MR * scaling / scale_adjust); + if (CR) + CR += (int)(CR * scaling / scale_adjust); + if (DR) + DR += (int)(DR * scaling / scale_adjust); + if (FR) + FR += (int)(FR * scaling / scale_adjust); + if (PR) + PR += (int)(PR * scaling / scale_adjust); + + if (max_dmg) + { + max_dmg += (int)(max_dmg * scaling / scale_adjust); + min_dmg += (int)(min_dmg * scaling / scale_adjust); + } - if (max_dmg) - { - max_dmg += (int)(max_dmg * scaling / scale_adjust); - min_dmg += (int)(min_dmg * scaling / scale_adjust); } - level = random_level; return; From 68df09a5701ac47ae5b2ec3e890441f87cc79dd7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 Aug 2016 23:56:08 -0400 Subject: [PATCH 254/693] Implement PVP regions --- zone/client.cpp | 40 ++++++++++++++++++++++++++++++++++------ zone/client.h | 8 ++++++-- zone/client_packet.cpp | 7 +++++-- zone/water_map.h | 3 ++- zone/water_map_v1.cpp | 4 ++++ zone/water_map_v1.h | 1 + zone/water_map_v2.cpp | 4 ++++ zone/water_map_v2.h | 1 + 8 files changed, 57 insertions(+), 11 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 7cfdf512f..eebe204ee 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -44,6 +44,7 @@ extern volatile bool RunLoops; #include "zonedb.h" #include "petitions.h" #include "command.h" +#include "water_map.h" #ifdef BOTS #include "bot_command.h" #endif @@ -156,7 +157,8 @@ Client::Client(EQStreamInterface* ieqs) m_ZoneSummonLocation(-2.0f,-2.0f,-2.0f), m_AutoAttackPosition(0.0f, 0.0f, 0.0f, 0.0f), m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f), - m_lastsave(-1) + m_lastsave(-1), + last_region_type(RegionTypeUnsupported) { for(int cf=0; cf < _FilterCount; cf++) ClientFilters[cf] = FilterShow; @@ -2482,13 +2484,15 @@ uint16 Client::GetMaxSkillAfterSpecializationRules(EQEmu::skills::SkillType skil return Result; } -void Client::SetPVP(bool toggle) { +void Client::SetPVP(bool toggle, bool message) { m_pp.pvp = toggle ? 1 : 0; - if(GetPVP()) - this->Message_StringID(MT_Shout,PVP_ON); - else - Message(13, "You no longer follow the ways of discord."); + if (message) { + if(GetPVP()) + this->Message_StringID(MT_Shout,PVP_ON); + else + Message(13, "You no longer follow the ways of discord."); + } SendAppearancePacket(AT_PVP, GetPVP()); Save(); @@ -8533,3 +8537,27 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) { int Client::GetAccountAge() { return (time(nullptr) - GetAccountCreation()); } + +void Client::CheckRegionTypeChanges() +{ + if (!zone->HasWaterMap()) + return; + + auto new_region = zone->watermap->ReturnRegionType(glm::vec3(m_Position)); + + // still same region, do nothing + if (last_region_type == new_region) + return; + + // region type changed + last_region_type = new_region; + + // PVP is the only state we need to keep track of, so we can just return now for PVP servers + if (RuleI(World, PVPSettings) > 0) + return; + + if (last_region_type == RegionTypePVP) + SetPVP(true, false); + else if (GetPVP()) + SetPVP(false, false); +} diff --git a/zone/client.h b/zone/client.h index e7b7b50b9..3bd2b29c5 100644 --- a/zone/client.h +++ b/zone/client.h @@ -27,6 +27,7 @@ class Object; class Raid; class Seperator; class ServerPacket; +enum WaterRegionType : int; namespace EQEmu { @@ -360,9 +361,9 @@ public: int32 LevelRegen(); void HPTick(); void SetGM(bool toggle); - void SetPVP(bool toggle); + void SetPVP(bool toggle, bool message = true); - inline bool GetPVP() const { return zone->GetZoneID() == 77 ? true : (m_pp.pvp != 0); } + inline bool GetPVP() const { return m_pp.pvp != 0; } inline bool GetGM() const { return m_pp.gm != 0; } inline void SetBaseClass(uint32 i) { m_pp.class_=i; } @@ -1233,6 +1234,8 @@ public: void SendHPUpdateMarquee(); + void CheckRegionTypeChanges(); + protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); @@ -1417,6 +1420,7 @@ private: uint8 zonesummon_ignorerestrictions; ZoneMode zone_mode; + WaterRegionType last_region_type; Timer position_timer; uint8 position_timer_counter; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a827a3008..2da75b364 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4576,8 +4576,11 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) safe_delete(outapp); } - if(zone->watermap && zone->watermap->InLiquid(glm::vec3(m_Position))) - CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17); + if (zone->watermap) { + if (zone->watermap->InLiquid(glm::vec3(m_Position))) + CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17); + CheckRegionTypeChanges(); + } return; } diff --git a/zone/water_map.h b/zone/water_map.h index 2b6e0ce3c..1d6f6a34f 100644 --- a/zone/water_map.h +++ b/zone/water_map.h @@ -8,7 +8,7 @@ extern const ZoneConfig *Config; -enum WaterRegionType { +enum WaterRegionType : int { RegionTypeUnsupported = -2, RegionTypeUntagged = -1, RegionTypeNormal = 0, @@ -33,6 +33,7 @@ public: virtual bool InVWater(const glm::vec3& location) const = 0; virtual bool InLava(const glm::vec3& location) const = 0; virtual bool InLiquid(const glm::vec3& location) const = 0; + virtual bool InPvP(const glm::vec3& location) const = 0; protected: virtual bool Load(FILE *fp) { return false; } diff --git a/zone/water_map_v1.cpp b/zone/water_map_v1.cpp index 431df4224..dd2e1539c 100644 --- a/zone/water_map_v1.cpp +++ b/zone/water_map_v1.cpp @@ -30,6 +30,10 @@ bool WaterMapV1::InLiquid(const glm::vec3& location) const { return InWater(location) || InLava(location); } +bool WaterMapV1::InPvP(const glm::vec3& location) const { + return ReturnRegionType(location) == RegionTypePVP; +} + bool WaterMapV1::Load(FILE *fp) { uint32 bsp_tree_size; if (fread(&bsp_tree_size, sizeof(bsp_tree_size), 1, fp) != 1) { diff --git a/zone/water_map_v1.h b/zone/water_map_v1.h index 6697aa0c8..e4cb167d7 100644 --- a/zone/water_map_v1.h +++ b/zone/water_map_v1.h @@ -24,6 +24,7 @@ public: virtual bool InVWater(const glm::vec3& location) const; virtual bool InLava(const glm::vec3& location) const; virtual bool InLiquid(const glm::vec3& location) const; + virtual bool InPvP(const glm::vec3& location) const; protected: virtual bool Load(FILE *fp); diff --git a/zone/water_map_v2.cpp b/zone/water_map_v2.cpp index a57999a48..48383fe3c 100644 --- a/zone/water_map_v2.cpp +++ b/zone/water_map_v2.cpp @@ -33,6 +33,10 @@ bool WaterMapV2::InLiquid(const glm::vec3& location) const { return InWater(location) || InLava(location); } +bool WaterMapV2::InPvP(const glm::vec3& location) const { + return ReturnRegionType(location) == RegionTypePVP; +} + bool WaterMapV2::Load(FILE *fp) { uint32 region_count; if (fread(®ion_count, sizeof(region_count), 1, fp) != 1) { diff --git a/zone/water_map_v2.h b/zone/water_map_v2.h index 6429937f0..523191fe3 100644 --- a/zone/water_map_v2.h +++ b/zone/water_map_v2.h @@ -17,6 +17,7 @@ public: virtual bool InVWater(const glm::vec3& location) const; virtual bool InLava(const glm::vec3& location) const; virtual bool InLiquid(const glm::vec3& location) const; + virtual bool InPvP(const glm::vec3& location) const; protected: virtual bool Load(FILE *fp); From 6a7ea65dd0c68c05639f52ed6880af4c272ffc20 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Aug 2016 01:07:12 -0400 Subject: [PATCH 255/693] Ask water map if we're in a zoneline to prevent false positives I don't think this should open up any chance to exploit Trying to use a ZL to go somewhere else is still detected etc This should really cut down on false positives and we really can't see real cheater from all the noise this creates --- zone/water_map.h | 1 + zone/water_map_v1.cpp | 4 ++++ zone/water_map_v1.h | 1 + zone/water_map_v2.cpp | 4 ++++ zone/water_map_v2.h | 1 + zone/zone.cpp | 4 +++- 6 files changed, 14 insertions(+), 1 deletion(-) diff --git a/zone/water_map.h b/zone/water_map.h index 1d6f6a34f..975703b40 100644 --- a/zone/water_map.h +++ b/zone/water_map.h @@ -34,6 +34,7 @@ public: virtual bool InLava(const glm::vec3& location) const = 0; virtual bool InLiquid(const glm::vec3& location) const = 0; virtual bool InPvP(const glm::vec3& location) const = 0; + virtual bool InZoneLine(const glm::vec3& location) const = 0; protected: virtual bool Load(FILE *fp) { return false; } diff --git a/zone/water_map_v1.cpp b/zone/water_map_v1.cpp index dd2e1539c..7d2479a3b 100644 --- a/zone/water_map_v1.cpp +++ b/zone/water_map_v1.cpp @@ -34,6 +34,10 @@ bool WaterMapV1::InPvP(const glm::vec3& location) const { return ReturnRegionType(location) == RegionTypePVP; } +bool WaterMapV1::InZoneLine(const glm::vec3& location) const { + return ReturnRegionType(location) == RegionTypeZoneLine; +} + bool WaterMapV1::Load(FILE *fp) { uint32 bsp_tree_size; if (fread(&bsp_tree_size, sizeof(bsp_tree_size), 1, fp) != 1) { diff --git a/zone/water_map_v1.h b/zone/water_map_v1.h index e4cb167d7..af4d4966f 100644 --- a/zone/water_map_v1.h +++ b/zone/water_map_v1.h @@ -25,6 +25,7 @@ public: virtual bool InLava(const glm::vec3& location) const; virtual bool InLiquid(const glm::vec3& location) const; virtual bool InPvP(const glm::vec3& location) const; + virtual bool InZoneLine(const glm::vec3& location) const; protected: virtual bool Load(FILE *fp); diff --git a/zone/water_map_v2.cpp b/zone/water_map_v2.cpp index 48383fe3c..939b9be97 100644 --- a/zone/water_map_v2.cpp +++ b/zone/water_map_v2.cpp @@ -37,6 +37,10 @@ bool WaterMapV2::InPvP(const glm::vec3& location) const { return ReturnRegionType(location) == RegionTypePVP; } +bool WaterMapV2::InZoneLine(const glm::vec3& location) const { + return ReturnRegionType(location) == RegionTypeZoneLine; +} + bool WaterMapV2::Load(FILE *fp) { uint32 region_count; if (fread(®ion_count, sizeof(region_count), 1, fp) != 1) { diff --git a/zone/water_map_v2.h b/zone/water_map_v2.h index 523191fe3..704d1a119 100644 --- a/zone/water_map_v2.h +++ b/zone/water_map_v2.h @@ -18,6 +18,7 @@ public: virtual bool InLava(const glm::vec3& location) const; virtual bool InLiquid(const glm::vec3& location) const; virtual bool InPvP(const glm::vec3& location) const; + virtual bool InZoneLine(const glm::vec3& location) const; protected: virtual bool Load(FILE *fp); diff --git a/zone/zone.cpp b/zone/zone.cpp index df48d0cfa..1165d7e9b 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1594,7 +1594,9 @@ ZonePoint* Zone::GetClosestZonePoint(const glm::vec3& location, uint32 to, Clien iterator.Advance(); } - if(closest_dist > 400.0f && closest_dist < max_distance2) + // if we have a water map and it says we're in a zoneline, lets assume it's just a really big zone line + // this shouldn't open up any exploits since those situations are detected later on + if ((zone->HasWaterMap() && !zone->watermap->InZoneLine(glm::vec3(client->GetPosition()))) || (!zone->HasWaterMap() && closest_dist > 400.0f && closest_dist < max_distance2)) { if(client) client->CheatDetected(MQZoneUnknownDest, location.x, location.y, location.z); // Someone is trying to use /zone From e5746c3b2eecfb8d7a5f86c3d0d9ea2805916245 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 Aug 2016 22:14:20 -0400 Subject: [PATCH 256/693] Fix EVENT_LOOT broken by b43cfa126 --- zone/corpse.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/corpse.cpp b/zone/corpse.cpp index ff5e4806b..ca32fc528 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1163,9 +1163,9 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } char buf[88]; - char corpse_name[64]; - strcpy(corpse_name, corpse_name); - snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(corpse_name)); + char q_corpse_name[64]; + strcpy(q_corpse_name, corpse_name); + snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(q_corpse_name)); buf[87] = '\0'; std::vector args; args.push_back(inst); From e86d11250b49ac3eb644be003d8d4427ec035c5c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 7 Aug 2016 14:32:30 -0400 Subject: [PATCH 257/693] Actually remove expendable AAs from the DB --- zone/aa.cpp | 4 ++++ zone/client.cpp | 5 +++++ zone/client.h | 1 + 3 files changed, 10 insertions(+) diff --git a/zone/aa.cpp b/zone/aa.cpp index f6facec8c..1640a9eff 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1240,6 +1240,10 @@ void Mob::ExpendAlternateAdvancementCharge(uint32 aa_id) { CastToClient()->GetEPP().expended_aa += r->cost; } } + if (IsClient()) { + auto c = CastToClient(); + c->RemoveExpendedAA(ability->first_rank_id); + } aa_ranks.erase(iter.first); } diff --git a/zone/client.cpp b/zone/client.cpp index eebe204ee..11799fb9e 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -568,6 +568,11 @@ bool Client::SaveAA() { return true; } +void Client::RemoveExpendedAA(int aa_id) +{ + database.QueryDatabase(StringFormat("DELETE from `character_alternate_abilities` WHERE `id` = %d and `aa_id` = %d", character_id, aa_id)); +} + bool Client::Save(uint8 iCommitNow) { if(!ClientDataLoaded()) return false; diff --git a/zone/client.h b/zone/client.h index 3bd2b29c5..819d6ed17 100644 --- a/zone/client.h +++ b/zone/client.h @@ -328,6 +328,7 @@ public: /* New PP Save Functions */ bool SaveCurrency(){ return database.SaveCharacterCurrency(this->CharacterID(), &m_pp); } bool SaveAA(); + void RemoveExpendedAA(int aa_id); inline bool ClientDataLoaded() const { return client_data_loaded; } inline bool Connected() const { return (client_state == CLIENT_CONNECTED); } From 4b93ef0a98990266e07d9a675695d4ca6f3bc5da Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 7 Aug 2016 18:17:39 -0400 Subject: [PATCH 258/693] Fix SE_CastOnFadeEffect --- zone/spell_effects.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 5708541d4..2a48b9e99 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3668,10 +3668,11 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) break; } // These effects always trigger when they fade. + // Should we have this triggered from else where? case SE_CastOnFadeEffect: case SE_CastOnFadeEffectNPC: case SE_CastOnFadeEffectAlways: { - if (buff.ticsremaining == 1) { + if (buff.ticsremaining == 0) { SpellOnTarget(spells[buff.spellid].base[i], this); } break; From bdb083eac7675ab3141f51b04be99d9020ba2a6f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 7 Aug 2016 18:55:02 -0400 Subject: [PATCH 259/693] Previous disc buff check incorrectly excluded Savage Spirit AA line This still doesn't fix Untamed Rage ... unsure on that one :( --- common/spdat.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index eeaf2be60..f22a82000 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -672,9 +672,7 @@ bool IsDisciplineBuff(uint16 spell_id) if (!IsValidSpell(spell_id)) return false; - if (spells[spell_id].mana == 0 && spells[spell_id].short_buff_box == 0 && - (spells[spell_id].EndurCost || spells[spell_id].EndurUpkeep) && - spells[spell_id].targettype == ST_Self) + if (spells[spell_id].IsDisciplineBuff && spells[spell_id].targettype == ST_Self) return true; return false; From 051f9ffab9e8ad5728a7fd70f0a4ddfe9d25f109 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 8 Aug 2016 15:22:26 -0400 Subject: [PATCH 260/693] fix bard song mods on instant spells (nukes, procs) --- zone/spell_effects.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 2a48b9e99..b567bae83 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -201,7 +201,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove continue; effect = spell.effectid[i]; - effect_value = CalcSpellEffectValue(spell_id, i, caster_level, buffslot > -1 ? buffs[buffslot].instrument_mod : 10, caster ? caster : this); + // if buff slot, use instrument mod there, otherwise calc it + uint32 inst = buffslot > -1 ? buffs[buffslot].instrument_mod : caster ? caster->GetInstrumentMod(spell_id) : 10; + effect_value = CalcSpellEffectValue(spell_id, i, caster_level, inst, caster ? caster : this); if(spell_id == SPELL_LAY_ON_HANDS && caster && caster->GetAA(aaImprovedLayOnHands)) effect_value = GetMaxHP(); From 27f6826fd34ccb6f87a31df424ada722bbf8b2ba Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 8 Aug 2016 20:21:38 -0400 Subject: [PATCH 261/693] Add rule Spells:AllowItemTGB for custom servers --- common/ruletypes.h | 1 + zone/spells.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 8ef840c96..562d4580f 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -379,6 +379,7 @@ RULE_BOOL(Spells, UseAdditiveFocusFromWornSlot, false) // Allows an additive foc RULE_BOOL(Spells, AlwaysSendTargetsBuffs, false) // ignore LAA level if true RULE_BOOL(Spells, FlatItemExtraSpellAmt, false) // allow SpellDmg stat to affect all spells, regardless of cast time/cooldown/etc RULE_BOOL(Spells, IgnoreSpellDmgLvlRestriction, false) // ignore the 5 level spread on applying SpellDmg +RULE_BOOL(Spells, AllowItemTGB, false) // TGB doesn't work with items on live, custom servers want it though RULE_CATEGORY_END() RULE_CATEGORY(Combat) diff --git a/zone/spells.cpp b/zone/spells.cpp index 0eebcb082..838d37162 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1683,7 +1683,7 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce case ST_Group: case ST_GroupNoPets: { - if(IsClient() && CastToClient()->TGB() && IsTGBCompatibleSpell(spell_id) && slot != CastingSlot::Item) { + if(IsClient() && CastToClient()->TGB() && IsTGBCompatibleSpell(spell_id) && (slot != CastingSlot::Item || RuleB(Spells, AllowItemTGB))) { if( (!target) || (target->IsNPC() && !(target->GetOwner() && target->GetOwner()->IsClient())) || (target->IsCorpse()) ) From 7d62b208ca7aca46289079e7974668e86a4ebfb7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 9 Aug 2016 21:30:10 -0400 Subject: [PATCH 262/693] Revert "Rate limit saving to at most once a second" This reverts commit f26dce39c33c1eac53a453f3629fa98f1b101473. No easy mode I guess --- zone/client.cpp | 6 ------ zone/client.h | 3 --- 2 files changed, 9 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 11799fb9e..cc07fff2c 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -157,7 +157,6 @@ Client::Client(EQStreamInterface* ieqs) m_ZoneSummonLocation(-2.0f,-2.0f,-2.0f), m_AutoAttackPosition(0.0f, 0.0f, 0.0f, 0.0f), m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f), - m_lastsave(-1), last_region_type(RegionTypeUnsupported) { for(int cf=0; cf < _FilterCount; cf++) @@ -577,10 +576,6 @@ bool Client::Save(uint8 iCommitNow) { if(!ClientDataLoaded()) return false; - // saved less than 2 seconds ago, lets just skip for now - if ((time(nullptr) - m_lastsave) < 2) - return true; - /* Wrote current basics to PP for saves */ m_pp.x = m_Position.x; m_pp.y = m_Position.y; @@ -670,7 +665,6 @@ bool Client::Save(uint8 iCommitNow) { database.SaveCharacterData(this->CharacterID(), this->AccountID(), &m_pp, &m_epp); /* Save Character Data */ - m_lastsave = time(nullptr); return true; } diff --git a/zone/client.h b/zone/client.h index 819d6ed17..dc04fbc1e 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1463,9 +1463,6 @@ private: Timer helm_toggle_timer; Timer light_update_timer; - - time_t m_lastsave; - glm::vec3 m_Proximity; void BulkSendInventoryItems(); From 38d3f9b7c0a8764cb5252f7056734fb4779c69d9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Aug 2016 13:16:32 -0400 Subject: [PATCH 263/693] Client checks song flag first This fixes bugs with buffs marked as disc and song (they go to the song window now) Before the client got confused and gave up displaying them at all! --- zone/spells.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 838d37162..6f7cc47b7 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3060,19 +3060,19 @@ uint32 Mob::GetLastBuffSlot(bool disc, bool song) uint32 Client::GetFirstBuffSlot(bool disc, bool song) { - if (disc) - return GetMaxBuffSlots() + GetMaxSongSlots(); if (song) return GetMaxBuffSlots(); + if (disc) + return GetMaxBuffSlots() + GetMaxSongSlots(); return 0; } uint32 Client::GetLastBuffSlot(bool disc, bool song) { - if (disc) - return GetMaxBuffSlots() + GetMaxSongSlots() + GetCurrentDiscSlots(); if (song) return GetMaxBuffSlots() + GetCurrentSongSlots(); + if (disc) + return GetMaxBuffSlots() + GetMaxSongSlots() + GetCurrentDiscSlots(); return GetCurrentBuffSlots(); } From e90e141a796fadbc0d099179c0cc0afc20fed692 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 10 Aug 2016 23:51:06 -0400 Subject: [PATCH 264/693] std::unordered_map::count is much slower than find --- zone/entity.cpp | 45 +++++++++++++++++++++++++++++++++++---------- zone/entity.h | 42 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 71 insertions(+), 16 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index 5da1190d0..2e2f79058 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -923,12 +923,18 @@ bool EntityList::MakeDoorSpawnPacket(EQApplicationPacket *app, Client *client) Entity *EntityList::GetEntityMob(uint16 id) { - return mob_list.count(id) ? mob_list.at(id) : nullptr; + auto it = mob_list.find(id); + if (it != mob_list.end()) + return it->second; + return nullptr; } Entity *EntityList::GetEntityMerc(uint16 id) { - return merc_list.count(id) ? merc_list.at(id) : nullptr; + auto it = merc_list.find(id); + if (it != merc_list.end()) + return it->second; + return nullptr; } Entity *EntityList::GetEntityMob(const char *name) @@ -948,12 +954,18 @@ Entity *EntityList::GetEntityMob(const char *name) Entity *EntityList::GetEntityDoor(uint16 id) { - return door_list.count(id) ? door_list.at(id) : nullptr; + auto it = door_list.find(id); + if (it != door_list.end()) + return it->second; + return nullptr; } Entity *EntityList::GetEntityCorpse(uint16 id) { - return corpse_list.count(id) ? corpse_list.at(id) : nullptr; + auto it = corpse_list.find(id); + if (it != corpse_list.end()) + return it->second; + return nullptr; } Entity *EntityList::GetEntityCorpse(const char *name) @@ -973,22 +985,34 @@ Entity *EntityList::GetEntityCorpse(const char *name) Entity *EntityList::GetEntityTrap(uint16 id) { - return trap_list.count(id) ? trap_list.at(id) : nullptr; + auto it = trap_list.find(id); + if (it != trap_list.end()) + return it->second; + return nullptr; } Entity *EntityList::GetEntityObject(uint16 id) { - return object_list.count(id) ? object_list.at(id) : nullptr; + auto it = object_list.find(id); + if (it != object_list.end()) + return it->second; + return nullptr; } Entity *EntityList::GetEntityBeacon(uint16 id) { - return beacon_list.count(id) ? beacon_list.at(id) : nullptr; + auto it = beacon_list.find(id); + if (it != beacon_list.end()) + return it->second; + return nullptr; } Entity *EntityList::GetEntityEncounter(uint16 id) { - return encounter_list.count(id) ? encounter_list.at(id) : nullptr; + auto it = encounter_list.find(id); + if (it != encounter_list.end()) + return it->second; + return nullptr; } Entity *EntityList::GetID(uint16 get_id) @@ -1184,6 +1208,8 @@ void EntityList::ChannelMessage(Mob *from, uint8 chan_num, uint8 language, void EntityList::ChannelMessageSend(Mob *to, uint8 chan_num, uint8 language, const char *message, ...) { + if (!to->IsClient()) + return; va_list argptr; char buffer[4096]; @@ -1191,8 +1217,7 @@ void EntityList::ChannelMessageSend(Mob *to, uint8 chan_num, uint8 language, con vsnprintf(buffer, 4096, message, argptr); va_end(argptr); - if (client_list.count(to->GetID())) - client_list.at(to->GetID())->ChannelMessageSend(0, 0, chan_num, language, buffer); + to->CastToClient()->ChannelMessageSend(0, 0, chan_num, language, buffer); } void EntityList::SendZoneSpawns(Client *client) diff --git a/zone/entity.h b/zone/entity.h index 90a372af8..8abb34ca2 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -148,14 +148,29 @@ public: bool IsMobSpawnedByNpcTypeID(uint32 get_id); Mob *GetTargetForVirus(Mob* spreader, int range); inline NPC *GetNPCByID(uint16 id) - { return npc_list.count(id) ? npc_list.at(id) : nullptr; } + { + auto it = npc_list.find(id); + if (it != npc_list.end()) + return it->second; + return nullptr; + } NPC *GetNPCByNPCTypeID(uint32 npc_id); inline Merc *GetMercByID(uint16 id) - { return merc_list.count(id) ? merc_list.at(id) : nullptr; } + { + auto it = merc_list.find(id); + if (it != merc_list.end()) + return it->second; + return nullptr; + } Client *GetClientByName(const char *name); Client *GetClientByAccID(uint32 accid); inline Client *GetClientByID(uint16 id) - { return client_list.count(id) ? client_list.at(id) : nullptr; } + { + auto it = client_list.find(id); + if (it != client_list.end()) + return it->second; + return nullptr; + } Client *GetClientByCharID(uint32 iCharID); Client *GetClientByWID(uint32 iWID); Client *GetClient(uint32 ip, uint16 port); @@ -172,7 +187,12 @@ public: Corpse *GetCorpseByOwner(Client* client); Corpse *GetCorpseByOwnerWithinRange(Client* client, Mob* center, int range); inline Corpse *GetCorpseByID(uint16 id) - { return corpse_list.count(id) ? corpse_list.at(id) : nullptr; } + { + auto it = corpse_list.find(id); + if (it != corpse_list.end()) + return it->second; + return nullptr; + } Corpse *GetCorpseByDBID(uint32 dbid); Corpse *GetCorpseByName(const char* name); @@ -181,10 +201,20 @@ public: Client* FindCorpseDragger(uint16 CorpseID); inline Object *GetObjectByID(uint16 id) - { return object_list.count(id) ? object_list.at(id) : nullptr; } + { + auto it = object_list.find(id); + if (it != object_list.end()) + return it->second; + return nullptr; + } Object *GetObjectByDBID(uint32 id); inline Doors *GetDoorsByID(uint16 id) - { return door_list.count(id) ? door_list.at(id) : nullptr; } + { + auto it = door_list.find(id); + if (it != door_list.end()) + return it->second; + return nullptr; + } Doors *GetDoorsByDoorID(uint32 id); Doors *GetDoorsByDBID(uint32 id); void RemoveAllCorpsesByCharID(uint32 charid); From c1c9ec2790586aa5f275afd919f4087d3556feef Mon Sep 17 00:00:00 2001 From: Russell Kinasz Date: Thu, 11 Aug 2016 11:04:03 -0700 Subject: [PATCH 265/693] Prevent crash in spell casting when group doesn't exist --- zone/spells.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 6f7cc47b7..855a2917c 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1729,7 +1729,9 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce { if(IsGrouped()) { - group_id_caster = GetGroup()->GetID(); + if (Group* group = GetGroup()) { + group_id_caster = group->GetID(); + } } else if(IsRaidGrouped()) { @@ -1744,7 +1746,9 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce Mob *owner = GetOwner(); if(owner->IsGrouped()) { - group_id_caster = owner->GetGroup()->GetID(); + if (Group* group = owner->GetGroup()) { + group_id_caster = group->GetID(); + } } else if(owner->IsRaidGrouped()) { @@ -1773,7 +1777,9 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce { if(spell_target->IsGrouped()) { - group_id_target = spell_target->GetGroup()->GetID(); + if (Group* group = spell_target->GetGroup()) { + group_id_target = group->GetID(); + } } else if(spell_target->IsRaidGrouped()) { @@ -1788,7 +1794,9 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce Mob *owner = spell_target->GetOwner(); if(owner->IsGrouped()) { - group_id_target = owner->GetGroup()->GetID(); + if (Group* group = owner->GetGroup()) { + group_id_target = group->GetID(); + } } else if(owner->IsRaidGrouped()) { From 039e0fbb83bd704d978d78d66bae12cfbab97f8a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 12 Aug 2016 21:52:46 -0400 Subject: [PATCH 266/693] NPC innate procs overwrite TargetType to ST_Target --- zone/mob.cpp | 2 +- zone/mob.h | 2 +- zone/mob_ai.cpp | 4 +++- zone/npc.cpp | 1 + zone/npc.h | 2 ++ zone/spells.cpp | 9 +++++++-- 6 files changed, 15 insertions(+), 5 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index e056a81c2..accd36bb0 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3223,7 +3223,7 @@ void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on, int lev if(twinproc_chance && zone->random.Roll(twinproc_chance)) twinproc = true; - if (IsBeneficialSpell(spell_id)) { + if (IsBeneficialSpell(spell_id) && (!IsNPC() || (IsNPC() && CastToNPC()->GetInnateProcSpellID() != spell_id))) { // NPC innate procs don't take this path ever SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override); if(twinproc) SpellOnTarget(spell_id, this, false, false, 0, true, level_override); diff --git a/zone/mob.h b/zone/mob.h index a01a4b8f5..b80667b02 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -265,7 +265,7 @@ public: bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1); virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1); virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, - CastAction_type &CastAction, EQEmu::CastingSlot slot); + CastAction_type &CastAction, EQEmu::CastingSlot slot, bool isproc = false); virtual bool CheckFizzle(uint16 spell_id); virtual bool CheckSpellLevelRestriction(uint16 spell_id); virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index eb795f6c3..eb14865ce 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2362,8 +2362,10 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { return a.priority > b.priority; }); - if (IsValidSpell(attack_proc_spell)) + if (IsValidSpell(attack_proc_spell)) { AddProcToWeapon(attack_proc_spell, true, proc_chance); + innate_proc_spell_id = attack_proc_spell; + } if (IsValidSpell(range_proc_spell)) AddRangedProc(range_proc_spell, (rproc_chance + 100)); diff --git a/zone/npc.cpp b/zone/npc.cpp index 15e96f3bf..1fc27dc5a 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -233,6 +233,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if npc_spells_id = 0; HasAISpell = false; HasAISpellEffects = false; + innate_proc_spell_id = 0; if(GetClass() == MERCERNARY_MASTER && RuleB(Mercs, AllowMercs)) { diff --git a/zone/npc.h b/zone/npc.h index 0023d4273..d3e7928a2 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -407,6 +407,7 @@ public: void mod_npc_killed_merit(Mob* c); void mod_npc_killed(Mob* oos); void AISpellsList(Client *c); + uint16 GetInnateProcSpellID() const { return innate_proc_spell_id; } uint32 GetHeroForgeModel() const { return herosforgemodel; } void SetHeroForgeModel(uint32 model) { herosforgemodel = model; } @@ -454,6 +455,7 @@ protected: virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); AISpellsVar_Struct AISpellVar; int16 GetFocusEffect(focusType type, uint16 spell_id); + uint16 innate_proc_spell_id; uint32 npc_spells_effects_id; std::vector AIspellsEffects; diff --git a/zone/spells.cpp b/zone/spells.cpp index 855a2917c..38c38b212 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1349,7 +1349,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo } -bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, CastingSlot slot) +bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, CastingSlot slot, bool isproc) { /* The basic types of spells: @@ -1396,6 +1396,11 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce targetType = ST_GroupClientAndPet; } + // NPC innate procs override the target type to single target. + // Yes. This code will cause issues if they have the proc as innate AND on a weapon. Oh well. + if (isproc && IsNPC() && CastToNPC()->GetInnateProcSpellID() == spell_id) + targetType = ST_Target; + if (spell_target && !spell_target->PassCastRestriction(true, spells[spell_id].CastRestriction)){ Message_StringID(13,SPELL_NEED_TAR); return false; @@ -1983,7 +1988,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui //determine the type of spell target we have CastAction_type CastAction; - if(!DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction, slot)) + if(!DetermineSpellTargets(spell_id, spell_target, ae_center, CastAction, slot, isproc)) return(false); Log.Out(Logs::Detail, Logs::Spells, "Spell %d: target type %d, target %s, AE center %s", spell_id, CastAction, spell_target?spell_target->GetName():"NONE", ae_center?ae_center->GetName():"NONE"); From 4e4d82857c09e40e68155aa7e5ff44572aec2644 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 12 Aug 2016 22:07:03 -0400 Subject: [PATCH 267/693] Move OP_BeginCast above instant cast shortcut For casted seplls, we should always see this. Mostly this shortcut breaks spell awareness for NPC spells. (most of them are instant cast) --- zone/spells.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 38c38b212..2144d3276 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -345,7 +345,6 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, { Mob* pMob = nullptr; int32 orgcasttime; - EQApplicationPacket *outapp = nullptr; if(!IsValidSpell(spell_id)) { InterruptSpell(); @@ -455,6 +454,18 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Casting time %d (orig %d), mana cost %d", spell_id, cast_time, orgcasttime, mana_cost); + // now tell the people in the area -- we ALWAYS want to send this, even instant cast spells. + // The only time this is skipped is for NPC innate procs and weapon procs. Procs from buffs + // oddly still send this. Since those cases don't reach here, we don't need to check them + auto outapp = new EQApplicationPacket(OP_BeginCast,sizeof(BeginCast_Struct)); + BeginCast_Struct* begincast = (BeginCast_Struct*)outapp->pBuffer; + begincast->caster_id = GetID(); + begincast->spell_id = spell_id; + begincast->cast_time = orgcasttime; // client calculates reduced time by itself + outapp->priority = 3; + entity_list.QueueCloseClients(this, outapp, false, 200, 0, true); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS); + safe_delete(outapp); + // cast time is 0, just finish it right now and be done with it if(cast_time == 0) { CastedSpellFinished(spell_id, target_id, slot, mana_cost, item_slot, resist_adjust); @@ -478,17 +489,6 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, if (oSpellWillFinish) *oSpellWillFinish = Timer::GetCurrentTime() + cast_time + 100; - // now tell the people in the area - outapp = new EQApplicationPacket(OP_BeginCast,sizeof(BeginCast_Struct)); - BeginCast_Struct* begincast = (BeginCast_Struct*)outapp->pBuffer; - begincast->caster_id = GetID(); - begincast->spell_id = spell_id; - begincast->cast_time = orgcasttime; // client calculates reduced time by itself - outapp->priority = 3; - entity_list.QueueCloseClients(this, outapp, false, 200, 0, true); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS); - safe_delete(outapp); - outapp = nullptr; - if (IsClient() && slot == CastingSlot::Item && item_slot != 0xFFFFFFFF) { auto item = CastToClient()->GetInv().GetItem(item_slot); if (item && item->GetItem()) From 50de63117d25d97f9450f9628c2a8c36e9a04e1f Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sat, 13 Aug 2016 07:19:58 -0400 Subject: [PATCH 268/693] Added optional avoidance cap rules. Check changelog.txt. --- changelog.txt | 7 +++++++ common/ruletypes.h | 2 ++ zone/client_mods.cpp | 14 ++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/changelog.txt b/changelog.txt index db7133b0b..4f71af6d5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/13/2016 == +Kinglykrab: Implemented optional avoidance cap rules. + - Serves to eliminate God-like characters on custom servers with high item stats + - Rule Names: + - Character:EnableAvoidanceCap (default is false) + - Character:AvoidanceCap (default is 750, beyond 1,000 seems to make characters dodge all attacks) + == 08/02/2016 == Uleat: Changed 'SendZoneSpawnsBulk' behavior to use near/far criteria (live-like) when sending packets. - Zone-to-Zone client loading will see a small decrease in time (less than 10~15%) diff --git a/common/ruletypes.h b/common/ruletypes.h index 562d4580f..c19ebee45 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -142,6 +142,8 @@ RULE_INT(Character, InvSnapshotMinRetryM, 30) // Time (in minutes) to re-attempt RULE_INT(Character, InvSnapshotHistoryD, 30) // Time (in days) to keep snapshot entries RULE_BOOL(Character, RestrictSpellScribing, false) // Restricts spell scribing to allowable races/classes of spell scroll, if true RULE_BOOL(Character, UseStackablePickPocketing, true) // Allows stackable pickpocketed items to stack instead of only being allowed in empty inventory slots +RULE_BOOL(Character, EnableAvoidanceCap, false) +RULE_INT(Character, AvoidanceCap, 750) // 750 Is a pretty good value, seen people dodge all attacks beyond 1,000 Avoidance RULE_CATEGORY_END() RULE_CATEGORY(Mercs) diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 804e8df62..c57fc340f 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1036,6 +1036,13 @@ int32 Client::CalcAC() if (avoidance < 0) { avoidance = 0; } + + if (RuleB(Character, EnableAvoidanceCap)) { + if (avoidance > RuleI(Character, AvoidanceCap)) { + avoidance = RuleI(Character, AvoidanceCap); + } + } + int mitigation = 0; if (m_pp.class_ == WIZARD || m_pp.class_ == MAGICIAN || m_pp.class_ == NECROMANCER || m_pp.class_ == ENCHANTER) { //something is wrong with this, naked casters have the wrong natural AC @@ -1113,6 +1120,13 @@ int32 Client::GetACAvoid() if (avoidance < 0) { avoidance = 0; } + + if (RuleB(Character, EnableAvoidanceCap)) { + if ((avoidance * 1000 / 847) > RuleI(Character, AvoidanceCap)) { + return RuleI(Character, AvoidanceCap); + } + } + return (avoidance * 1000 / 847); } From f01c8909664c3521809de46a1a2e49fe2a0c2660 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 15:09:43 -0400 Subject: [PATCH 269/693] Crash fix The other thing needs to be looked at too, but I guess we never run into an issue where this actually is a nullptr because bad things would happen here ... --- common/shareddb.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index c9213f3a2..fd89831c0 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -455,7 +455,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) } } - if (row[9]) { + if (inst && row[9]) { std::string data_str(row[9]); std::string idAsString; std::string value; @@ -480,6 +480,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) } } + // theoretically inst can be nullptr ... this would be very bad ... put_slot_id = inv->PutItem(slot_id, *inst); safe_delete(inst); From 97dc0a84dd57d96afb30906c1a75332e354b8bd6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 15:14:31 -0400 Subject: [PATCH 270/693] Fix logic paren issue --- world/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/client.cpp b/world/client.cpp index 460fa294d..d2ca3705a 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -142,7 +142,7 @@ void Client::SendLogServer() if(RuleB(World, IsGMPetitionWindowEnabled)) l->enable_petition_wnd = 1; - if(RuleI(World, FVNoDropFlag) == 1 || RuleI(World, FVNoDropFlag) == 2 && GetAdmin() > RuleI(Character, MinStatusForNoDropExemptions)) + if((RuleI(World, FVNoDropFlag) == 1 || RuleI(World, FVNoDropFlag) == 2) && GetAdmin() > RuleI(Character, MinStatusForNoDropExemptions)) l->enable_FV = 1; QueuePacket(outapp); From 488c4941d2fb988545f4fe430e75d37f496d2be5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 15:19:10 -0400 Subject: [PATCH 271/693] Fix potential crash --- world/zonelist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/zonelist.cpp b/world/zonelist.cpp index abd5c1057..55600c367 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -88,7 +88,7 @@ void ZSList::Process() { Process(); CatchSignal(2); } - if(reminder && reminder->Check()){ + if(reminder && reminder->Check() && shutdowntimer){ SendEmoteMessage(0,0,0,15,":SYSTEM MSG:World coming down, everyone log out now. World will shut down in %i minutes...", ((shutdowntimer->GetRemainingTime()/1000) / 60)); } LinkedListIterator iterator(list); From 7a4c9b36a8300824ee4f1f7c5caafd08a456aa72 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 15:20:48 -0400 Subject: [PATCH 272/693] Fix logic issue in SendAlternateAdvancementRank --- zone/aa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 1640a9eff..97b444311 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -867,7 +867,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { aai->max_level = ability->GetMaxLevel(this); aai->prev_id = rank->prev_id; - if(rank->next && !CanUseAlternateAdvancementRank(rank->next) || ability->charges > 0) { + if((rank->next && !CanUseAlternateAdvancementRank(rank->next)) || ability->charges > 0) { aai->next_id = -1; } else { aai->next_id = rank->next_id; From 00cfe2d25fd68b448e0532c48f2e6ae8543b945e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 15:26:07 -0400 Subject: [PATCH 273/693] Fix potential crashes in attack.cpp --- zone/attack.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 2b37be197..af5a90540 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3261,7 +3261,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons a->damage = damage; a->spellid = spell_id; a->special = special; - a->meleepush_xy = attacker->GetHeading() * 2.0f; + a->meleepush_xy = attacker ? attacker->GetHeading() * 2.0f : 0.0f; if (RuleB(Combat, MeleePush) && damage > 0 && !IsRooted() && (IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) { a->force = EQEmu::skills::GetSkillMeleePushForce(skill_used); @@ -3798,7 +3798,7 @@ void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage) void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts) { - if(damage < 1) + if(damage < 1 || !defender) return; // decided to branch this into it's own function since it's going to be duplicating a lot of the @@ -3819,8 +3819,8 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack bool IsBerskerSPA = false; //1: Try Slay Undead - if (defender && (defender->GetBodyType() == BT_Undead || - defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire)) { + if (defender->GetBodyType() == BT_Undead || + defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire) { int32 SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0]; if (SlayRateBonus) { float slayChance = static_cast(SlayRateBonus) / 10000.0f; From ef3cf099b84a062202c307ed5b4df2c7794334e1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 15:35:28 -0400 Subject: [PATCH 274/693] Fix potential crash in Sacrifice --- zone/client.cpp | 98 ++++++++++++++++++++++++------------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index cc07fff2c..a943598c0 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -3683,58 +3683,58 @@ void Client::SacrificeConfirm(Client *caster) //Essentially a special case death function void Client::Sacrifice(Client *caster) { - if(GetLevel() >= RuleI(Spells, SacrificeMinLevel) && GetLevel() <= RuleI(Spells, SacrificeMaxLevel)){ - int exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000); - if(exploss < GetEXP()){ - SetEXP(GetEXP()-exploss, GetAAXP()); - SendLogoutPackets(); + if (GetLevel() >= RuleI(Spells, SacrificeMinLevel) && GetLevel() <= RuleI(Spells, SacrificeMaxLevel)) { + int exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000); + if (exploss < GetEXP()) { + SetEXP(GetEXP() - exploss, GetAAXP()); + SendLogoutPackets(); - //make our become corpse packet, and queue to ourself before OP_Death. - EQApplicationPacket app2(OP_BecomeCorpse, sizeof(BecomeCorpse_Struct)); - BecomeCorpse_Struct* bc = (BecomeCorpse_Struct*)app2.pBuffer; - bc->spawn_id = GetID(); - bc->x = GetX(); - bc->y = GetY(); - bc->z = GetZ(); - QueuePacket(&app2); + // make our become corpse packet, and queue to ourself before OP_Death. + EQApplicationPacket app2(OP_BecomeCorpse, sizeof(BecomeCorpse_Struct)); + BecomeCorpse_Struct *bc = (BecomeCorpse_Struct *)app2.pBuffer; + bc->spawn_id = GetID(); + bc->x = GetX(); + bc->y = GetY(); + bc->z = GetZ(); + QueuePacket(&app2); - // make death packet - EQApplicationPacket app(OP_Death, sizeof(Death_Struct)); - Death_Struct* d = (Death_Struct*)app.pBuffer; - d->spawn_id = GetID(); - d->killer_id = caster ? caster->GetID() : 0; - d->bindzoneid = GetPP().binds[0].zoneId; - d->spell_id = SPELL_UNKNOWN; - d->attack_skill = 0xe7; - d->damage = 0; - app.priority = 6; - entity_list.QueueClients(this, &app); + // make death packet + EQApplicationPacket app(OP_Death, sizeof(Death_Struct)); + Death_Struct *d = (Death_Struct *)app.pBuffer; + d->spawn_id = GetID(); + d->killer_id = caster ? caster->GetID() : 0; + d->bindzoneid = GetPP().binds[0].zoneId; + d->spell_id = SPELL_UNKNOWN; + d->attack_skill = 0xe7; + d->damage = 0; + app.priority = 6; + entity_list.QueueClients(this, &app); - BuffFadeAll(); - UnmemSpellAll(); - Group *g = GetGroup(); - if(g){ - g->MemberZoned(this); - } - Raid *r = entity_list.GetRaidByClient(this); - if(r){ - r->MemberZoned(this); - } - ClearAllProximities(); - if(RuleB(Character, LeaveCorpses)){ - auto new_corpse = new Corpse(this, 0); - entity_list.AddCorpse(new_corpse, GetID()); - SetID(0); - entity_list.QueueClients(this, &app2, true); - } - Save(); - GoToDeath(); - caster->SummonItem(RuleI(Spells, SacrificeItemID)); - } - } - else{ - caster->Message_StringID(13, SAC_TOO_LOW); //This being is not a worthy sacrifice. - } + BuffFadeAll(); + UnmemSpellAll(); + Group *g = GetGroup(); + if (g) { + g->MemberZoned(this); + } + Raid *r = entity_list.GetRaidByClient(this); + if (r) { + r->MemberZoned(this); + } + ClearAllProximities(); + if (RuleB(Character, LeaveCorpses)) { + auto new_corpse = new Corpse(this, 0); + entity_list.AddCorpse(new_corpse, GetID()); + SetID(0); + entity_list.QueueClients(this, &app2, true); + } + Save(); + GoToDeath(); + if (caster) // I guess it's possible? + caster->SummonItem(RuleI(Spells, SacrificeItemID)); + } + } else { + caster->Message_StringID(13, SAC_TOO_LOW); // This being is not a worthy sacrifice. + } } void Client::SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID) { From ab35f8b842753c3c7ddf1dde5057d25a4dccc1aa Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 15:39:08 -0400 Subject: [PATCH 275/693] Fix memset in QuestReward --- zone/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index a943598c0..76e3ce8c4 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8405,7 +8405,7 @@ void Client::SendColoredText(uint32 color, std::string message) void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction) { auto outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct)); - memset(outapp->pBuffer, 0, sizeof(outapp->pBuffer)); + memset(outapp->pBuffer, 0, sizeof(QuestReward_Struct)); QuestReward_Struct* qr = (QuestReward_Struct*)outapp->pBuffer; qr->mob_id = target->GetID(); // Entity ID for the from mob name From a8db4532d020e4fbd051c69145477019d0836742 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 15:46:35 -0400 Subject: [PATCH 276/693] Fix potential crash in #iteminfo --- zone/command.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index 95770097d..16001d670 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -4339,7 +4339,10 @@ void command_goto(Client *c, const Seperator *sep) void command_iteminfo(Client *c, const Seperator *sep) { auto inst = c->GetInv()[EQEmu::legacy::SlotCursor]; - if (!inst) { c->Message(13, "Error: You need an item on your cursor for this command"); } + if (!inst) { + c->Message(13, "Error: You need an item on your cursor for this command"); + return; + } auto item = inst->GetItem(); if (!item) { Log.Out(Logs::General, Logs::Inventory, "(%s) Command #iteminfo processed an item with no data pointer"); From 3efc925264f1ba8b940bd5432f3662f1751b7b8c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 15:47:44 -0400 Subject: [PATCH 277/693] And another --- zone/command.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/command.cpp b/zone/command.cpp index 16001d670..4c60ad65b 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -4347,6 +4347,7 @@ void command_iteminfo(Client *c, const Seperator *sep) if (!item) { Log.Out(Logs::General, Logs::Inventory, "(%s) Command #iteminfo processed an item with no data pointer"); c->Message(13, "Error: This item has no data reference"); + return; } EQEmu::SayLinkEngine linker; From f06a9b3dcea8cd721675f3b3765591b6de800b77 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 15:58:02 -0400 Subject: [PATCH 278/693] use std::abs in Map::FindClosestZ --- zone/map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/map.cpp b/zone/map.cpp index 630e277c2..29a386331 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -163,7 +163,7 @@ float Map::FindClosestZ(glm::vec3 &start, glm::vec3 *result) const { to.z = -BEST_Z_INVALID; hit = imp->rm->raycast((const RmReal*)&from, (const RmReal*)&to, (RmReal*)result, nullptr, &hit_distance); if (hit) { - if (abs(from.z - result->z) < abs(ClosestZ - from.z)) + if (std::abs(from.z - result->z) < std::abs(ClosestZ - from.z)) return result->z; } From 8ce2921e3d3d9efd143ebdf27ce88b43e78e169d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 16:45:32 -0400 Subject: [PATCH 279/693] Fix potential crashes in Mob::SpellEffect --- zone/spell_effects.cpp | 71 +++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b567bae83..9dee868c7 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -357,8 +357,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; int32 val = 0; - val = 7500*effect_value; - val = caster->GetActSpellHealing(spell_id, val, this); + val = 7500 * effect_value; + if (caster) + val = caster->GetActSpellHealing(spell_id, val, this); if (val > 0) HealDamage(val, caster); @@ -377,12 +378,14 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Current Mana: %+i", effect_value); #endif SetMana(GetMana() + effect_value); - caster->SetMana(caster->GetMana() + std::abs(effect_value)); + if (caster) + caster->SetMana(caster->GetMana() + std::abs(effect_value)); if (effect_value < 0) TryTriggerOnValueAmount(false, true); #ifdef SPELL_EFFECT_SPAM - caster->Message(0, "You have gained %+i mana!", effect_value); + if (caster) + caster->Message(0, "You have gained %+i mana!", effect_value); #endif } } @@ -534,7 +537,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } } - if (effect == SE_GateCastersBindpoint && caster->IsClient()) + if (effect == SE_GateCastersBindpoint && caster && caster->IsClient()) { // Teleport Bind uses caster's bind point int index = spells[spell_id].base[i] - 1; if (index < 0 || index > 4) @@ -650,7 +653,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove //Added client messages to give some indication this effect is active. // Is there a message generated? Too disgusted by raids. uint32 time = spell.base[i] * 10 * 1000; - if (caster->IsClient()) { + if (caster && caster->IsClient()) { if (caster->IsGrouped()) { auto group = caster->GetGroup(); for (int i = 0; i < 6; ++i) @@ -697,7 +700,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove ((GetLevel() > max_level) && caster && (!caster->IsNPC() || (caster->IsNPC() && !RuleB(Spells, NPCIgnoreBaseImmunity)))))) { - caster->Message_StringID(MT_SpellFailure, IMMUNE_STUN); + if (caster) + caster->Message_StringID(MT_SpellFailure, IMMUNE_STUN); } else { int stun_resist = itembonuses.StunResist+spellbonuses.StunResist; if (IsClient()) @@ -706,7 +710,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (stun_resist <= 0 || zone->random.Int(0,99) >= stun_resist) { Log.Out(Logs::Detail, Logs::Combat, "Stunned. We had %d percent resist chance.", stun_resist); - if (caster->IsClient()) + if (caster && caster->IsClient()) effect_value += effect_value*caster->GetFocusEffect(focusFcStunTimeMod, spell_id)/100; Stun(effect_value); @@ -918,11 +922,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove cd->meleepush_xy = action->sequence; CastToClient()->QueuePacket(action_packet); - if(caster->IsClient() && caster != this) + if(caster && caster->IsClient() && caster != this) caster->CastToClient()->QueuePacket(action_packet); CastToClient()->QueuePacket(message_packet); - if(caster->IsClient() && caster != this) + if(caster && caster->IsClient() && caster != this) caster->CastToClient()->QueuePacket(message_packet); CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1); @@ -1033,7 +1037,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if(zone->random.Roll(effect_value)) Gate(spells[spell_id].base2[i] - 1); - else + else if (caster) caster->Message_StringID(MT_SpellFailure,GATE_FAIL); } break; @@ -1045,7 +1049,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Cancel Magic: %d", effect_value); #endif if(GetSpecialAbility(UNDISPELLABLE)){ - caster->Message_StringID(MT_SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name); + if (caster) + caster->Message_StringID(MT_SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name); break; } @@ -1055,7 +1060,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove spells[buffs[slot].spellid].dispel_flag == 0 && !IsDiscipline(buffs[slot].spellid)) { - if (TryDispel(caster->GetLevel(),buffs[slot].casterlevel, effect_value)){ + if (caster && TryDispel(caster->GetLevel(),buffs[slot].casterlevel, effect_value)){ BuffFadeBySlot(slot); slot = buff_count; } @@ -1070,7 +1075,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Dispel Detrimental: %d", effect_value); #endif if(GetSpecialAbility(UNDISPELLABLE)){ - caster->Message_StringID(MT_SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name); + if (caster) + caster->Message_StringID(MT_SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name); break; } @@ -1080,7 +1086,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove IsDetrimentalSpell(buffs[slot].spellid) && spells[buffs[slot].spellid].dispel_flag == 0) { - if (TryDispel(caster->GetLevel(),buffs[slot].casterlevel, effect_value)){ + if (caster && TryDispel(caster->GetLevel(),buffs[slot].casterlevel, effect_value)){ BuffFadeBySlot(slot); slot = buff_count; } @@ -1095,7 +1101,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Dispel Beneficial: %d", effect_value); #endif if(GetSpecialAbility(UNDISPELLABLE)){ - caster->Message_StringID(MT_SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name); + if (caster) + caster->Message_StringID(MT_SpellFailure, SPELL_NO_EFFECT, spells[spell_id].name); break; } @@ -1105,7 +1112,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove IsBeneficialSpell(buffs[slot].spellid) && spells[buffs[slot].spellid].dispel_flag == 0) { - if (TryDispel(caster->GetLevel(),buffs[slot].casterlevel, effect_value)){ + if (caster && TryDispel(caster->GetLevel(),buffs[slot].casterlevel, effect_value)){ BuffFadeBySlot(slot); slot = buff_count; } @@ -1122,7 +1129,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (buffs[slot].spellid != SPELL_UNKNOWN && IsDetrimentalSpell(buffs[slot].spellid)) { - if (TryDispel(caster->GetLevel(),buffs[slot].casterlevel, effect_value)){ + if (caster && TryDispel(caster->GetLevel(),buffs[slot].casterlevel, effect_value)){ BuffFadeBySlot(slot); } } @@ -1511,7 +1518,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove ((GetLevel() > max_level) && caster && (!caster->IsNPC() || (caster->IsNPC() && !RuleB(Spells, NPCIgnoreBaseImmunity))))) { - caster->Message_StringID(MT_Shout, IMMUNE_STUN); + if (caster) + caster->Message_StringID(MT_Shout, IMMUNE_STUN); } else { @@ -1728,7 +1736,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } } - else { + else if (client) { Raid *r = entity_list.GetRaidByClient(caster->CastToClient()); if(r) { @@ -1768,7 +1776,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove Message_StringID(4, CORPSE_CANT_SENSE); } } - else + else if (caster) caster->Message_StringID(MT_SpellFailure, SPELL_LEVEL_REQ); } else { @@ -2115,7 +2123,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Sacrifice"); #endif - if(!IsClient() || !caster->IsClient()){ + if(!caster || !IsClient() || !caster->IsClient()){ break; } CastToClient()->SacrificeConfirm(caster->CastToClient()); @@ -2124,12 +2132,15 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_SummonPC: { - if(IsClient()){ - CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), caster->GetX(), caster->GetY(), caster->GetZ(), caster->GetHeading(), 2, SummonPC); + if (!caster) + break; + if (IsClient()) { + CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), caster->GetX(), + caster->GetY(), caster->GetZ(), caster->GetHeading(), 2, + SummonPC); Message(15, "You have been summoned!"); entity_list.ClearAggro(this); - } - else + } else caster->Message(13, "This spell can only be cast on players."); break; @@ -2176,6 +2187,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_TemporaryPets: //Dook- swarms and wards: { + if (!caster) + break; // this makes necro epic 1.5/2.0 proc work properly if((spell_id != 6882) && (spell_id != 6884)) // Chaotic Jester/Steadfast Servant { @@ -2271,6 +2284,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove */ int16 focus = 0; int ReuseTime = spells[spell_id].recast_time + spells[spell_id].recovery_time; + if (!caster) + break; focus = caster->GetFocusEffect(focusFcBaseEffects, spell_id); @@ -2294,7 +2309,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Wake The Dead"); #endif //meh dupe issue with npc casting this - if(caster->IsClient()){ + if(caster && caster->IsClient()){ int dur = spells[spell_id].max[i]; if (!dur) dur = 60; @@ -2659,7 +2674,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_Taunt: { - if (IsNPC()){ + if (caster && IsNPC()){ caster->Taunt(this->CastToNPC(), false, static_cast(spell.base[i]), true, spell.base2[i]); } break; From 48fb483de6899aa32dbce039b9f8a6ed04458c00 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 17:05:48 -0400 Subject: [PATCH 280/693] Fix typo --- zone/spell_effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 9dee868c7..0b67ea523 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1736,7 +1736,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } } - else if (client) { + else if (caster) { Raid *r = entity_list.GetRaidByClient(caster->CastToClient()); if(r) { From 69f06f736c3fd24f24d7f46331781ed41f84828d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 17:15:00 -0400 Subject: [PATCH 281/693] Fix potential crashes in zone/spells.cpp --- zone/spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 2144d3276..ea8067b8c 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3139,7 +3139,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid if (ret == -1) { // stop the spell Log.Out(Logs::Detail, Logs::Spells, "Adding buff %d failed: stacking prevented by spell %d in slot %d with caster level %d", spell_id, curbuf.spellid, buffslot, curbuf.casterlevel); - if (caster->IsClient() && RuleB(Client, UseLiveBlockedMessage)) { + if (caster && caster->IsClient() && RuleB(Client, UseLiveBlockedMessage)) { caster->Message(13, "Your %s did not take hold on %s. (Blocked by %s.)", spells[spell_id].name, this->GetName(), spells[curbuf.spellid].name); } return -1; From 35c1eccbe1415d2ee2acf908527308e05d0cc256 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 17:15:57 -0400 Subject: [PATCH 282/693] Fix potential crash in zone/worldserver.cpp --- zone/worldserver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 969c4b947..0f00ed0c5 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -765,7 +765,7 @@ void WorldServer::Process() { zone->SetZoneHasCurrentTime(true); } - if (zone->is_zone_time_localized){ + if (zone && zone->is_zone_time_localized){ Log.Out(Logs::General, Logs::Zone_Server, "Received request to sync time from world, but our time is localized currently"); } break; From fd1e425abc6bd3d8e6fee94aa3eacf6b4f3e95d6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 13 Aug 2016 17:19:20 -0400 Subject: [PATCH 283/693] Fix potential crash in ucs/clientlist.cpp --- ucs/clientlist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index 47e0eb726..f49e02986 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -1985,7 +1985,7 @@ void Client::ChannelGrantVoice(std::string CommandString) { return; } - if(RequiredChannel->IsOwner(RequiredClient->GetName()) || RequiredChannel->IsModerator(RequiredClient->GetName())) { + if(RequiredClient && (RequiredChannel->IsOwner(RequiredClient->GetName()) || RequiredChannel->IsModerator(RequiredClient->GetName()))) { GeneralChannelMessage("The channel owner and moderators automatically have voice."); return; From 7f9af238f8803667dfe66b8abb68207255d6f078 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 13 Aug 2016 19:51:12 -0400 Subject: [PATCH 284/693] Fix for potential crash in ItemInst::GetTotalItemCount() --- common/item.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/item.cpp b/common/item.cpp index 41e3d86c3..61e7f926a 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -1863,6 +1863,9 @@ uint8 ItemInst::FirstOpenSlot() const uint8 ItemInst::GetTotalItemCount() const { + if (!m_item) + return 0; + uint8 item_count = 1; if (m_item && !m_item->IsClassBag()) { return item_count; } From e894e96404181af7cf715ed18028688d252723de Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 14 Aug 2016 23:32:27 -0400 Subject: [PATCH 285/693] Implement Linked Spell Reuse Timers They started linked spells at OoW launch (I think) At least canni was linked then. This is rather user unfriendly, but that's live like. Ex. the spells aren't actually put on cool down so you can attempt to cast them still but you will be interrupted. Titanium is particularly unfriendly with large differences in reuse times --- changelog.txt | 6 ++++++ common/emu_oplist.h | 1 + common/eq_packet_structs.h | 12 +++++++++++ common/ptimer.h | 4 +++- utils/patches/patch_RoF.conf | 1 + utils/patches/patch_RoF2.conf | 1 + utils/patches/patch_SoD.conf | 1 + utils/patches/patch_SoF.conf | 1 + utils/patches/patch_Titanium.conf | 1 + utils/patches/patch_UF.conf | 1 + zone/client.h | 3 +++ zone/spells.cpp | 35 +++++++++++++++++++++++++++++-- 12 files changed, 64 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index 4f71af6d5..7647ea8ec 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/14/2016 == +mackal: Implement Linked Spell Reuse Timers + - For whatever reason this is a bit unfriendly, but that's how it is on live. + - Titanium is especially unfriendly with large differences in reuse times (ex higher canni and the first 4) + - Unsure when this went live for spells, but canni was at least linked at OoW launch + == 08/13/2016 == Kinglykrab: Implemented optional avoidance cap rules. - Serves to eliminate God-like characters on custom servers with high item stats diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 8b913095b..6b7c58841 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -289,6 +289,7 @@ N(OP_LFGuild), N(OP_LFPCommand), N(OP_LFPGetMatchesRequest), N(OP_LFPGetMatchesResponse), +N(OP_LinkedReuse), N(OP_LoadSpellSet), N(OP_LocInfo), N(OP_LockoutTimerInfo), diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index fc1c9f9e7..12a08fa36 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -390,6 +390,18 @@ uint32 scribing; // 1 if memorizing a spell, set to 0 if scribing to book, 2 if uint32 reduction; // lower reuse }; +/* +** Linked Spell Reuse Timer +** Length: 12 +** Comes before the OP_Memorize +** Live (maybe TDS steam) has an extra DWORD after timer_id +*/ +struct LinkedSpellReuseTimer_Struct { + uint32 timer_id; // Timer ID of the spell + uint32 end_time; // timestamp of when it will be ready + uint32 start_time; // timestamp of when it started +}; + /* ** Make Charmed Pet ** Length: 12 Bytes diff --git a/common/ptimer.h b/common/ptimer.h index 7194ab49b..d7398bea3 100644 --- a/common/ptimer.h +++ b/common/ptimer.h @@ -37,10 +37,12 @@ enum { //values for pTimerType pTimerSenseTraps = 12, pTimerDisarmTraps = 13, pTimerDisciplineReuseStart = 14, - pTimerDisciplineReuseEnd = 24, + pTimerDisciplineReuseEnd = 24, // client actually has 20 ids, but still no disc go that high even on live pTimerCombatAbility = 25, pTimerCombatAbility2 = 26, // RoF2+ Tiger Claw is unlinked from other monk skills, generic in case other classes ever need it pTimerBeggingPickPocket = 27, + pTimerLinkedSpellReuseStart = 28, + pTimerLinkedSpellReuseEnd = 48, pTimerLayHands = 87, //these IDs are used by client too pTimerHarmTouch = 89, //so dont change them diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index 00682d57f..aefcd8dbc 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -172,6 +172,7 @@ OP_BeginCast=0x17ff OP_ColoredText=0x41cb OP_ConsentResponse=0x183d OP_MemorizeSpell=0x2fac +OP_LinkedReuse=0x3ac0 OP_SwapSpell=0x4736 OP_CastSpell=0x1cb5 OP_Consider=0x4d8d diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 9237a0238..19ef8d842 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -171,6 +171,7 @@ OP_BeginCast=0x318f OP_ColoredText=0x43af OP_ConsentResponse=0x384a OP_MemorizeSpell=0x217c +OP_LinkedReuse=0x1619 OP_SwapSpell=0x0efa OP_CastSpell=0x1287 OP_Consider=0x742b diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index 4944b0ef3..08e072d33 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -171,6 +171,7 @@ OP_BeginCast=0x0d5a # C OP_ColoredText=0x569a # C OP_ConsentResponse=0x6e47 # C OP_MemorizeSpell=0x8543 # C +OP_LinkedReuse=0x6ef9 OP_SwapSpell=0x3fd2 # C OP_CastSpell=0x3582 # C OP_Consider=0x6024 # C diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index 113038e49..d758daea9 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -169,6 +169,7 @@ OP_BeginCast=0x5A50 #SEQ 12/04/08 OP_ColoredText=0x3BC7 #SEQ 12/04/08 OP_ConsentResponse=0x4D30 #SEQ 12/04/08 OP_MemorizeSpell=0x6A93 #SEQ 12/04/08 +OP_LinkedReuse=0x2c26 OP_SwapSpell=0x1418 #SEQ 12/04/08 OP_CastSpell=0x7F5D #SEQ 12/04/08 OP_Consider=0x32E1 #SEQ 12/04/08 diff --git a/utils/patches/patch_Titanium.conf b/utils/patches/patch_Titanium.conf index a48de92b5..23f07109f 100644 --- a/utils/patches/patch_Titanium.conf +++ b/utils/patches/patch_Titanium.conf @@ -170,6 +170,7 @@ OP_Save=0x736b # ShowEQ 10/27/05 OP_Camp=0x78c1 # ShowEQ 10/27/05 OP_EndLootRequest=0x2316 # ShowEQ 10/27/05 OP_MemorizeSpell=0x308e # ShowEQ 10/27/05 +OP_LinkedReuse=0x6a00 OP_SwapSpell=0x2126 # ShowEQ 10/27/05 OP_CastSpell=0x304b # ShowEQ 10/27/05 OP_DeleteSpell=0x4f37 diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index 4b650176f..f41b62740 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -173,6 +173,7 @@ OP_BeginCast=0x0d5a # C OP_ColoredText=0x71bf # C OP_ConsentResponse=0x0e87 # C OP_MemorizeSpell=0x3887 # C +OP_LinkedReuse=0x1b26 OP_SwapSpell=0x5805 # C OP_CastSpell=0x50c2 # C OP_Consider=0x3c2d # C diff --git a/zone/client.h b/zone/client.h index dc04fbc1e..df7c1fce3 100644 --- a/zone/client.h +++ b/zone/client.h @@ -894,6 +894,9 @@ public: void SendDisciplineTimer(uint32 timer_id, uint32 duration); bool UseDiscipline(uint32 spell_id, uint32 target); + void SetLinkedSpellReuseTimer(uint32 timer_id, uint32 duration); + bool IsLinkedSpellReuseTimerReady(uint32 timer_id); + bool CheckTitle(int titleset); void EnableTitle(int titleset); void RemoveTitle(int titleset); diff --git a/zone/spells.cpp b/zone/spells.cpp index ea8067b8c..d310589b1 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -552,6 +552,10 @@ bool Mob::DoCastingChecks() } } + if (IsClient() && spells[spell_id].EndurTimerIndex > 0 && casting_spell_slot < CastingSlot::MaxGems) + if (!CastToClient()->IsLinkedSpellReuseTimerReady(spells[spell_id].EndurTimerIndex)) + return false; + casting_spell_checks = true; return true; } @@ -1308,8 +1312,11 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo { if(IsClient()) { - this->CastToClient()->CheckSongSkillIncrease(spell_id); - this->CastToClient()->MemorizeSpell(static_cast(slot), spell_id, memSpellSpellbar); + Client *c = CastToClient(); + c->CheckSongSkillIncrease(spell_id); + if (spells[spell_id].EndurTimerIndex > 0 && slot < CastingSlot::MaxGems) + c->SetLinkedSpellReuseTimer(spells[spell_id].EndurTimerIndex, spells[spell_id].recast_time / 1000); + c->MemorizeSpell(static_cast(slot), spell_id, memSpellSpellbar); } Log.Out(Logs::Detail, Logs::Spells, "Bard song %d should be started", spell_id); } @@ -1321,6 +1328,8 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo SendSpellBarEnable(spell_id); // this causes the delayed refresh of the spell bar gems + if (spells[spell_id].EndurTimerIndex > 0 && slot < CastingSlot::MaxGems) + c->SetLinkedSpellReuseTimer(spells[spell_id].EndurTimerIndex, spells[spell_id].recast_time / 1000); c->MemorizeSpell(static_cast(slot), spell_id, memSpellSpellbar); // this tells the client that casting may happen again @@ -5680,3 +5689,25 @@ void Mob::ConeDirectional(uint16 spell_id, int16 resist_adjust) ++iter; } } + +// duration in seconds +void Client::SetLinkedSpellReuseTimer(uint32 timer_id, uint32 duration) +{ + if (timer_id > 19) + return; + GetPTimers().Start(pTimerLinkedSpellReuseStart + timer_id, duration); + auto outapp = new EQApplicationPacket(OP_LinkedReuse, sizeof(LinkedSpellReuseTimer_Struct)); + auto lr = (LinkedSpellReuseTimer_Struct *)outapp->pBuffer; + lr->timer_id = timer_id; + lr->start_time = Timer::GetCurrentTime() / 1000; + lr->end_time = lr->start_time + duration; + FastQueuePacket(&outapp); +} + +bool Client::IsLinkedSpellReuseTimerReady(uint32 timer_id) +{ + if (timer_id > 19) + return true; + return GetPTimers().Expired(&database, pTimerLinkedSpellReuseStart + timer_id); +} + From ae5689ffb4f778143dec3492e2eab1c593f9c76a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 15 Aug 2016 01:17:53 -0400 Subject: [PATCH 286/693] Clean up OP_ManaChange --- common/eq_packet_structs.h | 9 +++++---- common/patches/rof.cpp | 3 ++- common/patches/rof2.cpp | 3 ++- common/patches/rof2_structs.h | 11 ++++++----- common/patches/rof_structs.h | 11 ++++++----- common/patches/sod.cpp | 3 ++- common/patches/sod_structs.h | 11 ++++++----- common/patches/sof.cpp | 3 ++- common/patches/sof_structs.h | 11 ++++++----- common/patches/titanium_structs.h | 10 +++++----- common/patches/uf.cpp | 3 ++- common/patches/uf_structs.h | 11 ++++++----- zone/client.cpp | 1 + zone/spells.cpp | 1 + 14 files changed, 52 insertions(+), 39 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 12a08fa36..a1b614b97 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -432,10 +432,11 @@ struct DeleteSpell_Struct struct ManaChange_Struct { - uint32 new_mana; // New Mana AMount - uint32 stamina; - uint32 spell_id; - uint32 unknown12; +/*00*/ uint32 new_mana; // New Mana AMount +/*04*/ uint32 stamina; +/*08*/ uint32 spell_id; +/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting? +/*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like }; struct SwapSpell_Struct diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index bee434ec3..939ad03fa 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -1623,7 +1623,8 @@ namespace RoF OUT(new_mana); OUT(stamina); OUT(spell_id); - eq->unknown16 = -1; // Self Interrupt/Success = -1, Fizzle = 1, Other Interrupt = 2? + OUT(keepcasting); + eq->slot = -1; // this is spell gem slot. It's -1 in normal operation FINISH_ENCODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 52fdeb02b..118419f48 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1701,7 +1701,8 @@ namespace RoF2 OUT(new_mana); OUT(stamina); OUT(spell_id); - eq->unknown16 = -1; // Self Interrupt/Success = -1, Fizzle = 1, Other Interrupt = 2? + OUT(keepcasting); + eq->slot = -1; // this is spell gem slot. It's -1 in normal operation FINISH_ENCODE(); } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 971ebd5e0..ae4d2c799 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -668,11 +668,12 @@ struct DeleteSpell_Struct struct ManaChange_Struct { - uint32 new_mana; // New Mana AMount - uint32 stamina; - uint32 spell_id; - uint32 unknown12; - uint32 unknown16; +/*00*/ uint32 new_mana; // New Mana AMount +/*04*/ uint32 stamina; +/*08*/ uint32 spell_id; +/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting? +/*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like +/*16*/ int32 slot; // -1 for normal usage slot for when we want silent interrupt? I think it does timer stuff or something. Linked Spell Reuse interrupt uses it }; struct SwapSpell_Struct diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 24c4b15f8..74b47c09e 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -657,11 +657,12 @@ struct DeleteSpell_Struct struct ManaChange_Struct { - uint32 new_mana; // New Mana AMount - uint32 stamina; - uint32 spell_id; - uint32 unknown12; - uint32 unknown16; +/*00*/ uint32 new_mana; // New Mana AMount +/*04*/ uint32 stamina; +/*08*/ uint32 spell_id; +/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting? +/*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like +/*16*/ int32 slot; // -1 for normal usage slot for when we want silent interrupt? I think it does timer stuff or something. Linked Spell Reuse interrupt uses it }; struct SwapSpell_Struct diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 4def89212..e23c1ca78 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1139,7 +1139,8 @@ namespace SoD OUT(new_mana); OUT(stamina); OUT(spell_id); - eq->unknown16 = -1; // Self Interrupt/Success = -1, Fizzle = 1, Other Interrupt = 2? + OUT(keepcasting); + eq->slot = -1; // this is spell gem slot. It's -1 in normal operation FINISH_ENCODE(); } diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index bdf6a6fd3..6a73b7283 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -512,11 +512,12 @@ struct DeleteSpell_Struct struct ManaChange_Struct { - uint32 new_mana; // New Mana AMount - uint32 stamina; - uint32 spell_id; - uint32 unknown12; - uint32 unknown16; +/*00*/ uint32 new_mana; // New Mana AMount +/*04*/ uint32 stamina; +/*08*/ uint32 spell_id; +/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting? +/*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like +/*16*/ int32 slot; // -1 for normal usage slot for when we want silent interrupt? I think it does timer stuff or something. Linked Spell Reuse interrupt uses it }; struct SwapSpell_Struct diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index a34e5029a..3ab4a7631 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -936,7 +936,8 @@ namespace SoF OUT(new_mana); OUT(stamina); OUT(spell_id); - eq->unknown16 = -1; // Self Interrupt/Success = -1, Fizzle = 1, Other Interrupt = 2? + OUT(keepcasting); + eq->slot = -1; // this is spell gem slot. It's -1 in normal operation FINISH_ENCODE(); } diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 06604e71d..0256132bd 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -491,11 +491,12 @@ struct DeleteSpell_Struct struct ManaChange_Struct { - uint32 new_mana; // New Mana AMount - uint32 stamina; - uint32 spell_id; - uint32 unknown12; - uint32 unknown16; +/*00*/ uint32 new_mana; // New Mana AMount +/*04*/ uint32 stamina; +/*08*/ uint32 spell_id; +/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting? +/*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like +/*16*/ int32 slot; // -1 for normal usage slot for when we want silent interrupt? I think it does timer stuff or something. Linked Spell Reuse interrupt uses it }; struct SwapSpell_Struct diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index b7b2bac67..8d258871f 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -420,13 +420,13 @@ struct DeleteSpell_Struct /*005*/uint8 unknowndss006[3]; /*008*/ }; - struct ManaChange_Struct { - uint32 new_mana; // New Mana AMount - uint32 stamina; - uint32 spell_id; - uint32 unknown12; +/*00*/ uint32 new_mana; // New Mana AMount +/*04*/ uint32 stamina; +/*08*/ uint32 spell_id; +/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting? +/*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like }; struct SwapSpell_Struct diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 1ff6c8e82..6a1a03a09 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1386,7 +1386,8 @@ namespace UF OUT(new_mana); OUT(stamina); OUT(spell_id); - eq->unknown16 = -1; // Self Interrupt/Success = -1, Fizzle = 1, Other Interrupt = 2? + OUT(keepcasting); + eq->slot = -1; // this is spell gem slot. It's -1 in normal operation FINISH_ENCODE(); } diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 3c582e6e6..46e5b21cb 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -512,11 +512,12 @@ struct DeleteSpell_Struct struct ManaChange_Struct { - uint32 new_mana; // New Mana AMount - uint32 stamina; - uint32 spell_id; - uint32 unknown12; - uint32 unknown16; +/*00*/ uint32 new_mana; // New Mana AMount +/*04*/ uint32 stamina; +/*08*/ uint32 spell_id; +/*12*/ uint8 keepcasting; // won't stop the cast. Change mana while casting? +/*13*/ uint8 padding[3]; // client doesn't read it, garbage data seems like +/*16*/ int32 slot; // -1 for normal usage slot for when we want silent interrupt? I think it does timer stuff or something. Linked Spell Reuse interrupt uses it }; struct SwapSpell_Struct diff --git a/zone/client.cpp b/zone/client.cpp index 76e3ce8c4..b4bbfaefc 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1809,6 +1809,7 @@ void Client::SendManaUpdatePacket() { manachange->new_mana = cur_mana; manachange->stamina = cur_end; manachange->spell_id = casting_spell_id; //always going to be 0... since we check IsCasting() + manachange->keepcasting = 1; outapp->priority = 6; QueuePacket(outapp); safe_delete(outapp); diff --git a/zone/spells.cpp b/zone/spells.cpp index d310589b1..417cdb5a5 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4754,6 +4754,7 @@ void Mob::SendSpellBarEnable(uint16 spell_id) manachange->new_mana = GetMana(); manachange->spell_id = spell_id; manachange->stamina = CastToClient()->GetEndurance(); + manachange->keepcasting = 0; outapp->priority = 6; CastToClient()->QueuePacket(outapp); safe_delete(outapp); From 3c95545ea380feb9734eee42f537bfd7cbcabd90 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 15 Aug 2016 01:23:47 -0400 Subject: [PATCH 287/693] Remove IsCasting check from Client::SendManaUpdatePacket --- zone/client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index b4bbfaefc..59998bfdb 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1794,7 +1794,7 @@ const int32& Client::SetMana(int32 amount) { } void Client::SendManaUpdatePacket() { - if (!Connected() || IsCasting()) + if (!Connected()) return; if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { @@ -1808,7 +1808,7 @@ void Client::SendManaUpdatePacket() { ManaChange_Struct* manachange = (ManaChange_Struct*)outapp->pBuffer; manachange->new_mana = cur_mana; manachange->stamina = cur_end; - manachange->spell_id = casting_spell_id; //always going to be 0... since we check IsCasting() + manachange->spell_id = casting_spell_id; manachange->keepcasting = 1; outapp->priority = 6; QueuePacket(outapp); From 26772b721cff59b283a88ee0edca0bcdc1b45ef5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 15 Aug 2016 14:21:39 -0400 Subject: [PATCH 288/693] Fix overhaste stack check --- zone/spells.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 417cdb5a5..0271ea687 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2995,8 +2995,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, if ( effect1 == SE_AttackSpeed || - effect1 == SE_AttackSpeed2 || - effect1 == SE_AttackSpeed3 + effect1 == SE_AttackSpeed2 ) { sp1_value -= 100; From 3d64878e60f6bafaf966e59d2d13100badf12327 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 15 Aug 2016 15:23:37 -0400 Subject: [PATCH 289/693] Skip OP_BeginCast for discs --- zone/spells.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 0271ea687..701f0355f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -457,14 +457,16 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, // now tell the people in the area -- we ALWAYS want to send this, even instant cast spells. // The only time this is skipped is for NPC innate procs and weapon procs. Procs from buffs // oddly still send this. Since those cases don't reach here, we don't need to check them - auto outapp = new EQApplicationPacket(OP_BeginCast,sizeof(BeginCast_Struct)); - BeginCast_Struct* begincast = (BeginCast_Struct*)outapp->pBuffer; - begincast->caster_id = GetID(); - begincast->spell_id = spell_id; - begincast->cast_time = orgcasttime; // client calculates reduced time by itself - outapp->priority = 3; - entity_list.QueueCloseClients(this, outapp, false, 200, 0, true); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS); - safe_delete(outapp); + if (slot != CastingSlot::Discipline) { + auto outapp = new EQApplicationPacket(OP_BeginCast,sizeof(BeginCast_Struct)); + BeginCast_Struct* begincast = (BeginCast_Struct*)outapp->pBuffer; + begincast->caster_id = GetID(); + begincast->spell_id = spell_id; + begincast->cast_time = orgcasttime; // client calculates reduced time by itself + outapp->priority = 3; + entity_list.QueueCloseClients(this, outapp, false, 200, 0, true); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS); + safe_delete(outapp); + } // cast time is 0, just finish it right now and be done with it if(cast_time == 0) { From 5a0d2b527bc7e0742d9e3ad84b1de8788a931dd4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 16 Aug 2016 17:52:14 -0400 Subject: [PATCH 290/693] Add a StopCasting function and make some use of it Unsure if all of these cases should use interrupt or stop casting --- zone/mob.h | 1 + zone/spells.cpp | 32 +++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/zone/mob.h b/zone/mob.h index b80667b02..927ecf862 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -272,6 +272,7 @@ public: virtual float GetAOERange(uint16 spell_id); void InterruptSpell(uint16 spellid = SPELL_UNKNOWN); void InterruptSpell(uint16, uint16, uint16 spellid = SPELL_UNKNOWN); + void StopCasting(); inline bool IsCasting() const { return((casting_spell_id != 0)); } uint16 CastingSpellID() const { return casting_spell_id; } bool DoCastingChecks(); diff --git a/zone/spells.cpp b/zone/spells.cpp index 701f0355f..4e79ede91 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -470,6 +470,10 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, // cast time is 0, just finish it right now and be done with it if(cast_time == 0) { + if (!DoCastingChecks()) { + StopCasting(); + return false; + } CastedSpellFinished(spell_id, target_id, slot, mana_cost, item_slot, resist_adjust); return(true); } @@ -498,7 +502,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, } if (!DoCastingChecks()) { - InterruptSpell(); + StopCasting(); return false; } @@ -882,6 +886,32 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) } +// this is like interrupt, just it doesn't spam interrupt packets to everyone +// There are a few cases where this is what live does :P +void Mob::StopCasting() +{ + if (casting_spell_id && IsNPC()) { + CastToNPC()->AI_Event_SpellCastFinished(false, static_cast(casting_spell_slot)); + } + + if (IsClient()) { + auto c = CastToClient(); + if (casting_spell_aa_id) { //Rest AA Timer on failed cast + c->Message_StringID(MT_SpellFailure, ABILITY_FAILED); + c->ResetAlternateAdvancementTimer(casting_spell_aa_id); + } + + auto outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct)); + auto mc = (ManaChange_Struct *)outapp->pBuffer; + mc->new_mana = GetMana(); + mc->stamina = GetEndurance(); + mc->spell_id = casting_spell_id; + mc->keepcasting = 0; + c->FastQueuePacket(&outapp); + } + ZeroCastingVars(); +} + // this is called after the timer is up and the spell is finished // casting. everything goes through here, including items with zero cast time // only to be used from SpellProcess From d3afde1aa14fdba385dec64ec4ac92e0dc37b320 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 16 Aug 2016 19:36:26 -0500 Subject: [PATCH 291/693] Travis Discord test --- utils/scripts/eqemu_update.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 6d1e32c3a..e54c7e73a 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -4,7 +4,7 @@ #::: Automatic (Database) Upgrade Script #::: Author: Akkadius #::: Purpose: To upgrade databases with ease and maintain versioning -########################################################### +########################################################### $menu_displayed = 0; From 94fabc87f00155cd9eafeb6c644574b648681d7a Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 16 Aug 2016 19:50:12 -0500 Subject: [PATCH 292/693] Travis Discord test 2 --- utils/scripts/eqemu_update.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index e54c7e73a..6be6f030b 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -1,10 +1,10 @@ #!/usr/bin/perl -########################################################### +########################################################### #::: Automatic (Database) Upgrade Script #::: Author: Akkadius #::: Purpose: To upgrade databases with ease and maintain versioning -########################################################### +########################################################### $menu_displayed = 0; From b85d5a6d98f2f81acd899d47c987669ae5b14015 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 16 Aug 2016 20:44:04 -0500 Subject: [PATCH 293/693] Discord final test --- utils/scripts/eqemu_update.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 6be6f030b..c28d078c3 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -4,7 +4,7 @@ #::: Automatic (Database) Upgrade Script #::: Author: Akkadius #::: Purpose: To upgrade databases with ease and maintain versioning -########################################################### +########################################################### $menu_displayed = 0; From 1def512b4c8284920f3d7d84607748092c76d137 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 16 Aug 2016 21:56:43 -0500 Subject: [PATCH 294/693] One more test --- utils/scripts/eqemu_update.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index c28d078c3..6d1e32c3a 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -########################################################### +########################################################### #::: Automatic (Database) Upgrade Script #::: Author: Akkadius #::: Purpose: To upgrade databases with ease and maintain versioning From f9f3a8f3bd78c9eae3cd923ffb29e7d7e64f7610 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 17 Aug 2016 01:10:37 -0400 Subject: [PATCH 295/693] Expendable Arrows ignore EQ --- zone/special_attacks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 41fb18ef2..eb7f5aac1 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -786,7 +786,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { //EndlessQuiver AA base1 = 100% Chance to avoid consumption arrow. int ChanceAvoidConsume = aabonuses.ConsumeProjectile + itembonuses.ConsumeProjectile + spellbonuses.ConsumeProjectile; - if (!ChanceAvoidConsume || (ChanceAvoidConsume < 100 && zone->random.Int(0,99) > ChanceAvoidConsume)){ + if (RangeItem->ExpendableArrow || !ChanceAvoidConsume || (ChanceAvoidConsume < 100 && zone->random.Int(0,99) > ChanceAvoidConsume)){ DeleteItemInInventory(ammo_slot, 1, true); Log.Out(Logs::Detail, Logs::Combat, "Consumed one arrow from slot %d", ammo_slot); } else { From a07149919d1d21bf5624d9404d016e5e51f91ee5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 18 Aug 2016 17:28:32 -0500 Subject: [PATCH 296/693] Pets now don't actually spawn until the player has fully entered the zone (Live-like) --- zone/client_packet.cpp | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2da75b364..37108697c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -502,6 +502,27 @@ void Client::CompleteConnect() SetDuelTarget(0); SetDueling(false); + database.LoadPetInfo(this); + /* + This was moved before the spawn packets are sent + in hopes that it adds more consistency... + Remake pet + */ + if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) { + MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, m_petinfo.Name, m_petinfo.size); + if (GetPet() && GetPet()->IsNPC()) { + NPC *pet = GetPet()->CastToNPC(); + pet->SetPetState(m_petinfo.Buffs, m_petinfo.Items); + pet->CalcBonuses(); + pet->SetHP(m_petinfo.HP); + pet->SetMana(m_petinfo.Mana); + } + m_petinfo.SpellID = 0; + } + /* Moved here so it's after where we load the pet data. */ + if (!GetAA(aaPersistentMinion)) + memset(&m_suspendedminion, 0, sizeof(PetInfo)); + EnteringMessages(this); LoadZoneFlags(); @@ -1628,27 +1649,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (m_pp.RestTimer) rest_timer.Start(m_pp.RestTimer * 1000); - database.LoadPetInfo(this); - /* - This was moved before the spawn packets are sent - in hopes that it adds more consistency... - Remake pet - */ - if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) { - MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, m_petinfo.Name, m_petinfo.size); - if (GetPet() && GetPet()->IsNPC()) { - NPC *pet = GetPet()->CastToNPC(); - pet->SetPetState(m_petinfo.Buffs, m_petinfo.Items); - pet->CalcBonuses(); - pet->SetHP(m_petinfo.HP); - pet->SetMana(m_petinfo.Mana); - } - m_petinfo.SpellID = 0; - } - /* Moved here so it's after where we load the pet data. */ - if (!GetAA(aaPersistentMinion)) - memset(&m_suspendedminion, 0, sizeof(PetInfo)); - /* Server Zone Entry Packet */ outapp = new EQApplicationPacket(OP_ZoneEntry, sizeof(ServerZoneEntry_Struct)); ServerZoneEntry_Struct* sze = (ServerZoneEntry_Struct*)outapp->pBuffer; From 0789d10d3e69d185394e678a9e9c5afa8ae0327e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 18 Aug 2016 20:51:58 -0400 Subject: [PATCH 297/693] Add logging message for setting linked reuse --- zone/spells.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index 4e79ede91..fe2ad1946 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5727,6 +5727,7 @@ void Client::SetLinkedSpellReuseTimer(uint32 timer_id, uint32 duration) { if (timer_id > 19) return; + Log.Out(Logs::Detail, Logs::Spells, "Setting Linked Spell Reuse %d for %d", timer_id, duration); GetPTimers().Start(pTimerLinkedSpellReuseStart + timer_id, duration); auto outapp = new EQApplicationPacket(OP_LinkedReuse, sizeof(LinkedSpellReuseTimer_Struct)); auto lr = (LinkedSpellReuseTimer_Struct *)outapp->pBuffer; From f67cd057f3ba3dbe67f4f274a13490ff41439491 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 18 Aug 2016 21:09:02 -0400 Subject: [PATCH 298/693] Fix issue with linked spell timers --- zone/spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index fe2ad1946..e12f8042f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5741,6 +5741,6 @@ bool Client::IsLinkedSpellReuseTimerReady(uint32 timer_id) { if (timer_id > 19) return true; - return GetPTimers().Expired(&database, pTimerLinkedSpellReuseStart + timer_id); + return GetPTimers().Expired(&database, pTimerLinkedSpellReuseStart + timer_id, false); } From 6daf207323d90b2e67e64e5b1054b1f49226555b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 19 Aug 2016 16:31:46 -0500 Subject: [PATCH 299/693] Quick test --- utils/scripts/eqemu_update.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 6d1e32c3a..c28d078c3 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -########################################################### +########################################################### #::: Automatic (Database) Upgrade Script #::: Author: Akkadius #::: Purpose: To upgrade databases with ease and maintain versioning From 696c02c0f022da9622cce59053406e513ac8d9dd Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 20 Aug 2016 14:30:21 -0400 Subject: [PATCH 300/693] Move instrument mod outside of the EFFECT lop in SpellEffect --- zone/spell_effects.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 0b67ea523..8f66345d2 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -194,6 +194,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove bool SE_SpellTrigger_HasCast = false; + // if buff slot, use instrument mod there, otherwise calc it + uint32 instrument_mod = buffslot > -1 ? buffs[buffslot].instrument_mod : caster ? caster->GetInstrumentMod(spell_id) : 10; // iterate through the effects in the spell for (i = 0; i < EFFECT_COUNT; i++) { @@ -201,9 +203,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove continue; effect = spell.effectid[i]; - // if buff slot, use instrument mod there, otherwise calc it - uint32 inst = buffslot > -1 ? buffs[buffslot].instrument_mod : caster ? caster->GetInstrumentMod(spell_id) : 10; - effect_value = CalcSpellEffectValue(spell_id, i, caster_level, inst, caster ? caster : this); + effect_value = CalcSpellEffectValue(spell_id, i, caster_level, instrument_mod, caster ? caster : this); if(spell_id == SPELL_LAY_ON_HANDS && caster && caster->GetAA(aaImprovedLayOnHands)) effect_value = GetMaxHP(); From f5a7117bdfae8c80cb1429cc78c124b9087135c3 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 20 Aug 2016 23:13:16 -0500 Subject: [PATCH 301/693] Add character_table_list.txt for database backup script reference --- utils/sql/character_table_list.txt | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 utils/sql/character_table_list.txt diff --git a/utils/sql/character_table_list.txt b/utils/sql/character_table_list.txt new file mode 100644 index 000000000..b0fdd2c06 --- /dev/null +++ b/utils/sql/character_table_list.txt @@ -0,0 +1,34 @@ +adventure_stats +char_recipe_list +character_activities +character_alt_currency +character_alternate_abilities +character_bandolier +character_bind +character_currency +character_data +character_data +character_disciplines +character_enabledtasks +character_inspect_messages +character_languages +character_leadership_abilities +character_material +character_memmed_spells +character_potionbelt +character_skills +character_spells +character_tribute +completed_tasks +faction_values +friends +guild_members +instance_list_player +inventory +keyring +mail +player_titlesets +quest_globals +timers +titles +zone_flags \ No newline at end of file From afe42ccdaf89b7321012e72f46d5000f82358aae Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 20 Aug 2016 23:23:17 -0500 Subject: [PATCH 302/693] Update db_dumper.pl --- utils/scripts/db_dumper.pl | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/utils/scripts/db_dumper.pl b/utils/scripts/db_dumper.pl index 5b4bb229d..4abf2c2c9 100644 --- a/utils/scripts/db_dumper.pl +++ b/utils/scripts/db_dumper.pl @@ -32,7 +32,6 @@ if(!$ARGV[0]){ print " database=\"dbname\" - Manually specify databasename, default is database in eqemu_config.xml\n"; print " tables=\"table1,table2,table3\" - Manually specify tables, default is to dump all tables from database\n"; print " compress - Compress Database with 7-ZIP, will fallback to WinRAR depending on what is installed (Must be installed to default program dir)...\n"; - print " nolock - Does not lock tables, meant for backuping while the server is running..\n"; print ' Example: perl DB_Dumper.pl Loc="E:\Backups"' . "\n\n"; print "######################################################\n"; exit; @@ -60,9 +59,6 @@ print "Arguments\n" if $Debug; $n = 0; while($ARGV[$n]){ print $n . ': ' . $ARGV[$n] . "\n" if $Debug; - if($ARGV[$n]=~/nolock/i){ - $no_lock = 1; - } if($ARGV[$n]=~/compress/i){ print "Compression SET\n"; $Compress = 1; @@ -108,15 +104,12 @@ else { } if($t_tables ne ""){ - $tables_f_l = substr($t_tables_l, 0, 20) . '...'; + $tables_f_l = substr($t_tables_l, 0, 20) . '-'; $target_file = '' . $tables_f_l . '_' . $date . ''; print "Performing table based backup...\n"; #::: Backup Database... print "Backing up Database " . $db . "... \n\n"; - if($no_lock == 1){ - $added_parameters .= " --skip-lock-tables "; - } - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' ' . $t_tables . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; + $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' ' . $t_tables . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; printcmd($cmd); system($cmd); } @@ -124,10 +117,7 @@ else{ #::: Entire DB Backup $target_file = '' . $db . '_' . $date . ''; #::: Backup Database... print "Backing up Database " . $db . "... \n\n"; - if($no_lock == 1){ - $added_parameters .= " --skip-lock-tables "; - } - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; + $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; printcmd($cmd); system($cmd); } From 8dd18a43a0bb5f08682d4babba0a40adbc20ec38 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 20 Aug 2016 23:31:34 -0500 Subject: [PATCH 303/693] Update db_dumper [skip ci] --- utils/scripts/db_dumper.pl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/utils/scripts/db_dumper.pl b/utils/scripts/db_dumper.pl index 4abf2c2c9..cf460252b 100644 --- a/utils/scripts/db_dumper.pl +++ b/utils/scripts/db_dumper.pl @@ -32,6 +32,7 @@ if(!$ARGV[0]){ print " database=\"dbname\" - Manually specify databasename, default is database in eqemu_config.xml\n"; print " tables=\"table1,table2,table3\" - Manually specify tables, default is to dump all tables from database\n"; print " compress - Compress Database with 7-ZIP, will fallback to WinRAR depending on what is installed (Must be installed to default program dir)...\n"; + print " nolock - Does not lock tables, meant for backuping while the server is running..\n"; print ' Example: perl DB_Dumper.pl Loc="E:\Backups"' . "\n\n"; print "######################################################\n"; exit; @@ -59,6 +60,9 @@ print "Arguments\n" if $Debug; $n = 0; while($ARGV[$n]){ print $n . ': ' . $ARGV[$n] . "\n" if $Debug; + if($ARGV[$n]=~/nolock/i){ + $no_lock = 1; + } if($ARGV[$n]=~/compress/i){ print "Compression SET\n"; $Compress = 1; @@ -109,7 +113,10 @@ if($t_tables ne ""){ print "Performing table based backup...\n"; #::: Backup Database... print "Backing up Database " . $db . "... \n\n"; - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' ' . $t_tables . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; + if($no_lock == 1){ + $added_parameters .= " --skip-lock-tables "; + } + $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' ' . $t_tables . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; printcmd($cmd); system($cmd); } @@ -117,7 +124,10 @@ else{ #::: Entire DB Backup $target_file = '' . $db . '_' . $date . ''; #::: Backup Database... print "Backing up Database " . $db . "... \n\n"; - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; + if($no_lock == 1){ + $added_parameters .= " --skip-lock-tables "; + } + $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; printcmd($cmd); system($cmd); } From 93464e396377def98f15cc6e9a6f86db53e93881 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 20 Aug 2016 23:32:01 -0500 Subject: [PATCH 304/693] Remove duplicate table [skip ci] --- utils/sql/character_table_list.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/sql/character_table_list.txt b/utils/sql/character_table_list.txt index b0fdd2c06..2a902d009 100644 --- a/utils/sql/character_table_list.txt +++ b/utils/sql/character_table_list.txt @@ -7,7 +7,6 @@ character_bandolier character_bind character_currency character_data -character_data character_disciplines character_enabledtasks character_inspect_messages @@ -31,4 +30,4 @@ player_titlesets quest_globals timers titles -zone_flags \ No newline at end of file +zone_flags From 0b06044dcedd59df3bd6c2c00613e02ff0408103 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 20 Aug 2016 23:47:53 -0500 Subject: [PATCH 305/693] Update db_dumper [skip ci] Fix issues with file name output when no compression is set Add option to set backup_name="backup_name" to prefix backup outputs --- utils/scripts/db_dumper.pl | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/utils/scripts/db_dumper.pl b/utils/scripts/db_dumper.pl index cf460252b..47f14feef 100644 --- a/utils/scripts/db_dumper.pl +++ b/utils/scripts/db_dumper.pl @@ -33,6 +33,7 @@ if(!$ARGV[0]){ print " tables=\"table1,table2,table3\" - Manually specify tables, default is to dump all tables from database\n"; print " compress - Compress Database with 7-ZIP, will fallback to WinRAR depending on what is installed (Must be installed to default program dir)...\n"; print " nolock - Does not lock tables, meant for backuping while the server is running..\n"; + print " backup_name=\"name\" - Sets database backup prefix name\n"; print ' Example: perl DB_Dumper.pl Loc="E:\Backups"' . "\n\n"; print "######################################################\n"; exit; @@ -72,6 +73,11 @@ while($ARGV[$n]){ print "Database is " . $DB_NAME[1] . "\n"; $db = $DB_NAME[1]; } + if($ARGV[$n]=~/backup_name=/i){ + @data = split('=', $ARGV[$n]); + print "Backup Name is " . $data[1] . "\n"; + $backup_name = $data[1]; + } if($ARGV[$n]=~/loc=/i){ @B_LOC = split('=', $ARGV[$n]); print "Backup Directory: " . $B_LOC[1] . "\n"; @@ -109,7 +115,13 @@ else { if($t_tables ne ""){ $tables_f_l = substr($t_tables_l, 0, 20) . '-'; - $target_file = '' . $tables_f_l . '_' . $date . ''; + if($backup_name){ + $target_file = $backup_name . '_' . $date . ''; + } + else { + $target_file = '' . $tables_f_l . '_' . $date . ''; + } + print "Performing table based backup...\n"; #::: Backup Database... print "Backing up Database " . $db . "... \n\n"; @@ -121,7 +133,14 @@ if($t_tables ne ""){ system($cmd); } else{ #::: Entire DB Backup - $target_file = '' . $db . '_' . $date . ''; + + if($backup_name){ + $target_file = $backup_name . '_' . $db . '_' . $date . ''; + } + else { + $target_file = '' . $db . '_' . $date . ''; + } + #::: Backup Database... print "Backing up Database " . $db . "... \n\n"; if($no_lock == 1){ @@ -195,6 +214,9 @@ if($Compress == 1){ $final_file = $target_file . ".tar.gz"; } } +else { + $final_file = $target_file . ".sql"; +} #::: Get Final File Location for display if($B_LOC[1] ne ""){ $final_loc = $B_LOC[1] . '' . $file_app . ""; } From 4065df7930d34f14bf202165fd68f9ecd0c15ea5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 20 Aug 2016 23:49:51 -0500 Subject: [PATCH 306/693] Update eqemu_update.pl [skip ci] Add option 21) Dump DB Player tables (Exports to backups\player_tables_export_(date).sql) Player table list is referenced/maintained in utils/sql/character_table_list.txt --- utils/scripts/eqemu_update.pl | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index c28d078c3..67ab528cf 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl -########################################################### +########################################################### #::: Automatic (Database) Upgrade Script #::: Author: Akkadius #::: Purpose: To upgrade databases with ease and maintain versioning @@ -295,9 +295,10 @@ sub show_menu_prompt { 13 => \&do_windows_login_server_setup, 14 => \&remove_duplicate_rule_values, 15 => \&fetch_utility_scripts, - 18 => \&fetch_latest_windows_binaries_bots, + 16 => \&fetch_latest_windows_binaries_bots, 19 => \&do_bots_db_schema_drop, 20 => \&do_update_self, + 21 => \&database_dump_player_tables, 0 => \&script_exit, ); @@ -378,6 +379,7 @@ return <){ + chomp; + $o = $_; + $tables .= $o . ","; + } + $tables = substr($tables, 0, -1); + + print `perl db_dumper.pl database="$db" loc="backups" tables="$tables" backup_name="player_tables_export" nolock`; + + print "\nPress any key to continue...\n"; + + <>; #Read from STDIN + +} + sub database_dump_compress { check_for_database_dump_script(); print "Performing database backup....\n"; From a8ba56363277753f83a31096587fd805d382977e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 20 Aug 2016 23:50:59 -0500 Subject: [PATCH 307/693] Update eqemu_update.pl [skip ci] --- utils/scripts/eqemu_update.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index 67ab528cf..a7da3c792 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -295,7 +295,7 @@ sub show_menu_prompt { 13 => \&do_windows_login_server_setup, 14 => \&remove_duplicate_rule_values, 15 => \&fetch_utility_scripts, - 16 => \&fetch_latest_windows_binaries_bots, + 18 => \&fetch_latest_windows_binaries_bots, 19 => \&do_bots_db_schema_drop, 20 => \&do_update_self, 21 => \&database_dump_player_tables, From c2b31bd6e2a447567bc636a73ba7b4b8249575e5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 21 Aug 2016 20:26:54 -0400 Subject: [PATCH 308/693] Fix EVENT_ATTACK crash (thanks image) Note: I guess we need to check if it's null in the actual quest too --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index af5a90540..ed6a26daf 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1800,7 +1800,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::Skill //handle EVENT_ATTACK. Resets after we have not been attacked for 12 seconds if(attacked_timer.Check()) { - Log.Out(Logs::Detail, Logs::Combat, "Triggering EVENT_ATTACK due to attack by %s", other->GetName()); + Log.Out(Logs::Detail, Logs::Combat, "Triggering EVENT_ATTACK due to attack by %s", other ? other->GetName() : "nullptr"); parse->EventNPC(EVENT_ATTACK, this, other, "", 0); } attacked_timer.Start(CombatEventTimer_expire); From 2c3107fbe909708bc46de41b93aa5c96c7210bd6 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 22 Aug 2016 16:07:44 -0500 Subject: [PATCH 309/693] Uploading initial eqemu_server.pl (was eqemu_update.pl) to start deprecrating of eqemu_update.pl and re-working of the structure of the script, more to come. --- utils/scripts/eqemu_server.pl | 1552 +++++++++++++++++++++++++++++++++ 1 file changed, 1552 insertions(+) create mode 100644 utils/scripts/eqemu_server.pl diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl new file mode 100644 index 000000000..b575bb1cf --- /dev/null +++ b/utils/scripts/eqemu_server.pl @@ -0,0 +1,1552 @@ +#!/usr/bin/perl + +########################################################### +#::: Automatic (Database) Upgrade Script +#::: Author: Akkadius +#::: Purpose: To upgrade databases with ease and maintain versioning +########################################################### + +$menu_displayed = 0; + +use Config; +use File::Copy qw(copy); +use POSIX qw(strftime); +use File::Path; +use File::Find; +use URI::Escape; +use Time::HiRes qw(usleep); + +$time_stamp = strftime('%m-%d-%Y', gmtime()); + +$console_output .= " Operating System is: $Config{osname}\n"; +if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } +if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } + +#::: If current version is less than what world is reporting, then download a new one... +$current_version = 14; + +if($ARGV[0] eq "V"){ + if($ARGV[1] > $current_version){ + print "eqemu_update.pl Automatic Database Upgrade Needs updating...\n"; + print " Current version: " . $current_version . "\n"; + print " New version: " . $ARGV[1] . "\n"; + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); + exit; + } + else{ + print "[Upgrade Script] No script update necessary \n"; + } + exit; +} + +#::: Sets database run stage check +$db_run_stage = 0; + +$perl_version = $^V; +$perl_version =~s/v//g; +print "Perl Version is " . $perl_version . "\n"; +if($perl_version > 5.12){ no warnings 'uninitialized'; } +no warnings; + +($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); + +my $confile = "eqemu_config.xml"; #default +open(F, "<$confile"); +my $indb = 0; +while() { + s/\r//g; + if(//i) { $indb = 1; } + next unless($indb == 1); + if(/<\/database>/i) { $indb = 0; last; } + if(/(.*)<\/host>/i) { $host = $1; } + elsif(/(.*)<\/username>/i) { $user = $1; } + elsif(/(.*)<\/password>/i) { $pass = $1; } + elsif(/(.*)<\/db>/i) { $db = $1; } +} + +$console_output = +"============================================================ + EQEmu: Automatic Upgrade Check +============================================================ +"; + +if($OS eq "Windows"){ + $has_mysql_path = `echo %PATH%`; + if($has_mysql_path=~/MySQL|MariaDB/i){ + @mysql = split(';', $has_mysql_path); + foreach my $v (@mysql){ + if($v=~/MySQL|MariaDB/i){ + $v =~s/\n//g; + $path = trim($v) . "/mysql"; + last; + } + } + $console_output .= " (Windows) MySQL is in system path \n"; + $console_output .= " Path = " . $path . "\n"; + $console_output .= "============================================================\n"; + } +} + +#::: Linux Check +if($OS eq "Linux"){ + $path = `which mysql`; + if ($path eq "") { + $path = `which mariadb`; + } + $path =~s/\n//g; + + $console_output .= " (Linux) MySQL is in system path \n"; + $console_output .= " Path = " . $path . "\n"; + $console_output .= "============================================================\n"; +} + +#::: Path not found, error and exit +if($path eq ""){ + print "MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; + print "script_exiting...\n"; + exit; +} + +if($ARGV[0] eq "install_peq_db"){ + + $db_name = "peq"; + if($ARGV[1]){ + $db_name = $ARGV[1]; + } + + $db = $db_name; + + #::: Database Routines + print "MariaDB :: Creating Database '" . $db_name . "'\n"; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; + if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } + if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } + $bin_db_ver = trim($db_version[1]); + check_db_version_table(); + $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + fetch_peq_db_full(); + print "\nFetching Latest Database Updates...\n"; + main_db_management(); + print "\nApplying Latest Database Updates...\n"; + main_db_management(); + + print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); +} + +if($ARGV[0] eq "remove_duplicate_rules"){ + remove_duplicate_rule_values(); + exit; +} + +if($ARGV[0] eq "installer"){ + print "Running EQEmu Server installer routines...\n"; + mkdir('logs'); + mkdir('updates_staged'); + mkdir('shared'); + fetch_latest_windows_binaries(); + map_files_fetch_bulk(); + opcodes_fetch(); + plugins_fetch(); + quest_files_fetch(); + lua_modules_fetch(); + + #::: Binary dll's + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); + + #::: Server scripts + fetch_utility_scripts(); + + #::: Database Routines + print "MariaDB :: Creating Database 'peq'\n"; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS peq;"`; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE peq"`; + if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } + if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } + $bin_db_ver = trim($db_version[1]); + check_db_version_table(); + $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + fetch_peq_db_full(); + print "\nFetching Latest Database Updates...\n"; + main_db_management(); + print "\nApplying Latest Database Updates...\n"; + main_db_management(); + + print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); + + if($OS eq "Windows"){ + check_windows_firewall_rules(); + do_windows_login_server_setup(); + } + exit; +} + +if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } +if($ARGV[0] eq "login_server_setup"){ + do_windows_login_server_setup(); + exit; +} + +#::: Create db_update working directory if not created +mkdir('db_update'); + +#::: Check if db_version table exists... +if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ + print get_mysql_result("DROP TABLE db_version"); + print "Old db_version table present, dropping...\n\n"; +} + +sub check_db_version_table{ + if(get_mysql_result("SHOW TABLES LIKE 'db_version'") eq "" && $db){ + print get_mysql_result(" + CREATE TABLE db_version ( + version int(11) DEFAULT '0' + ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + INSERT INTO db_version (version) VALUES ('1000');"); + print "Table 'db_version' does not exists.... Creating...\n\n"; + } +} + +check_db_version_table(); + +if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } +if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } + +$bin_db_ver = trim($db_version[1]); +$local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + +#::: If ran from Linux startup script, supress output +if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_start"){ + print "Database up to date...\n"; + exit; +} +else{ + print $console_output if $db; +} + +if($db){ + print " Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; + + #::: Bots + #::: Make sure we're running a bots binary to begin with + if(trim($db_version[2]) > 0){ + $bots_local_db_version = get_bots_db_version(); + if($bots_local_db_version > 0){ + print " (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; + } + } + + #::: If World ran this script, and our version is up to date, continue... + if($bin_db_ver <= $local_db_ver && $ARGV[0] eq "ran_from_world"){ + print " Database up to Date: Continuing World Bootup...\n"; + print "============================================================\n"; + exit; + } + +} + +if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){ + print "You have missing database updates, type 1 or 2 to backup your database before running them as recommended...\n\n"; + #::: Display Menu + show_menu_prompt(); +} +else{ + #::: Most likely ran standalone + print "\n"; + show_menu_prompt(); +} + +sub do_update_self{ + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); + die "Rerun eqemu_update.pl"; +} + +sub fetch_utility_scripts { + if($OS eq "Windows"){ + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_database_backup.bat", "t_database_backup.bat"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server.bat", "t_start_server.bat"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_stop_server.bat", "t_stop_server.bat"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_server_crash_report.pl", "t_server_crash_report.pl"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/win_server_launcher.pl", "win_server_launcher.pl"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat"); + } + else { + print "No scripts found for OS: " . $OS . "...\n"; + } +} + +sub show_menu_prompt { + my %dispatch = ( + 1 => \&database_dump, + 2 => \&database_dump_compress, + 3 => \&main_db_management, + 4 => \&bots_db_management, + 5 => \&opcodes_fetch, + 6 => \&map_files_fetch, + 7 => \&plugins_fetch, + 8 => \&quest_files_fetch, + 9 => \&lua_modules_fetch, + 10 => \&aa_fetch, + 11 => \&fetch_latest_windows_binaries, + 12 => \&fetch_server_dlls, + 13 => \&do_windows_login_server_setup, + 14 => \&remove_duplicate_rule_values, + 15 => \&fetch_utility_scripts, + 18 => \&fetch_latest_windows_binaries_bots, + 19 => \&do_bots_db_schema_drop, + 20 => \&do_update_self, + 21 => \&database_dump_player_tables, + 0 => \&script_exit, + ); + + while (1) { + { + local $| = 1; + if(!$menu_show && ($ARGV[0] eq "ran_from_world" || $ARGV[0] eq "ran_from_start")){ + $menu_show++; + next; + } + print menu_options(), '> '; + $menu_displayed++; + if($menu_displayed > 50){ + print "Safety: Menu looping too many times, exiting...\n"; + exit; + } + } + + my $choice = <>; + + $choice =~ s/\A\s+//; + $choice =~ s/\s+\z//; + + if (defined(my $handler = $dispatch{$choice})) { + my $result = $handler->(); + unless (defined $result) { + exit 0; + } + } + else { + if($ARGV[0] ne "ran_from_world"){ + # warn "\n\nInvalid selection\n\n"; + } + } + } +} + +sub menu_options { + if(@total_updates){ + if($bots_db_management == 1){ + $option[3] = "Check and stage pending REQUIRED Database updates"; + $bots_management = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; + } + else{ + $option[3] = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; + if(get_mysql_result("SHOW TABLES LIKE 'bots'") eq ""){ + $bots_management = "Install bots database pre-requisites (Requires bots server binaries)"; + } + else{ + $bots_management = "Check for Bot pending REQUIRED database updates... (Must have bots enabled)"; + } + } + } + else{ + $option[3] = "Check and stage pending REQUIRED Database updates"; + $bots_management = "Check for Bot REQUIRED database updates... (Must have bots enabled)"; + } + +return <){ + chomp; + $o = $_; + $tables .= $o . ","; + } + $tables = substr($tables, 0, -1); + + print `perl db_dumper.pl database="$db" loc="backups" tables="$tables" backup_name="player_tables_export" nolock`; + + print "\nPress any key to continue...\n"; + + <>; #Read from STDIN + +} + +sub database_dump_compress { + check_for_database_dump_script(); + print "Performing database backup....\n"; + print `perl db_dumper.pl database="$db" loc="backups" compress`; +} + +sub script_exit{ + #::: Cleanup staged folder... + rmtree("updates_staged/"); + exit; +} + +#::: Returns Tab Delimited MySQL Result from Command Line +sub get_mysql_result{ + my $run_query = $_[0]; + if(!$db){ return; } + if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`; } + if($OS eq "Linux"){ + $run_query =~s/`//g; + return `$path --user="$user" --host $host --password="$pass" $db -N -B -e "$run_query"`; + } +} + +sub get_mysql_result_from_file{ + my $update_file = $_[0]; + if(!$db){ return; } + if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } + if($OS eq "Linux"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } +} + +#::: Gets Remote File based on URL (1st Arg), and saves to destination file (2nd Arg) +#::: Example: get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); +sub get_remote_file{ + my $URL = $_[0]; + my $Dest_File = $_[1]; + my $content_type = $_[2]; + + #::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary + if($Dest_File=~/\//i){ + my @dir_path = split('/', $Dest_File); + $build_path = ""; + $di = 0; + while($dir_path[$di]){ + $build_path .= $dir_path[$di] . "/"; + #::: If path does not exist, create the directory... + if (!-d $build_path) { + mkdir($build_path); + } + if(!$dir_path[$di + 2] && $dir_path[$di + 1]){ + # print $actual_path . "\n"; + $actual_path = $build_path; + last; + } + $di++; + } + } + + if($OS eq "Windows"){ + #::: For non-text type requests... + if($content_type == 1){ + $break = 0; + while($break == 0) { + use LWP::Simple qw(getstore); + if(!getstore($URL, $Dest_File)){ + # print "Error, no connection or failed request...\n\n"; + } + # sleep(1); + #::: Make sure the file exists before continuing... + if(-e $Dest_File) { + $break = 1; + print " [URL] :: " . $URL . "\n"; + print " [Saved] :: " . $Dest_File . "\n"; + } else { $break = 0; } + usleep(500); + } + } + else{ + $break = 0; + while($break == 0) { + require LWP::UserAgent; + my $ua = LWP::UserAgent->new; + $ua->timeout(10); + $ua->env_proxy; + my $response = $ua->get($URL); + if ($response->is_success){ + open (FILE, '> ' . $Dest_File . ''); + print FILE $response->decoded_content; + close (FILE); + } + else { + # print "Error, no connection or failed request...\n\n"; + } + if(-e $Dest_File) { + $break = 1; + print " [URL] :: " . $URL . "\n"; + print " [Saved] :: " . $Dest_File . "\n"; + } else { $break = 0; } + usleep(500); + } + } + } + if($OS eq "Linux"){ + #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt + $wget = `wget --no-check-certificate --quiet -O $Dest_File $URL`; + print " o URL: (" . $URL . ")\n"; + print " o Saved: (" . $Dest_File . ") \n"; + if($wget=~/unable to resolve/i){ + print "Error, no connection or failed request...\n\n"; + #die; + } + } +} + +#::: Trim Whitespaces +sub trim { + my $string = $_[0]; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} + +#::: Fetch Latest PEQ AA's +sub aa_fetch{ + if(!$db){ + print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n"; + return; + } + + print "Pulling down PEQ AA Tables...\n"; + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); + print "\n\nInstalling AA Tables...\n"; + print get_mysql_result_from_file("db_update/peq_aa_tables_post_rework.sql"); + print "\nDone...\n\n"; +} + +#::: Fetch Latest Opcodes +sub opcodes_fetch{ + print "Pulling down latest opcodes...\n"; + %opcodes = ( + 1 => ["opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/opcodes.conf"], + 2 => ["mail_opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/mail_opcodes.conf"], + 3 => ["Titanium", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Titanium.conf"], + 4 => ["Secrets of Faydwer", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoF.conf"], + 5 => ["Seeds of Destruction", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoD.conf"], + 6 => ["Underfoot", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_UF.conf"], + 7 => ["Rain of Fear", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF.conf"], + 8 => ["Rain of Fear 2", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF2.conf"], + ); + $loop = 1; + while($opcodes{$loop}[0]){ + #::: Split the URL by the patches folder to get the file name from URL + @real_file = split("patches/", $opcodes{$loop}[1]); + $find = 0; + while($real_file[$find]){ + $file_name = $real_file[$find]; + $find++; + } + + print "\nDownloading (" . $opcodes{$loop}[0] . ") File: '" . $file_name . "'...\n\n"; + get_remote_file($opcodes{$loop}[1], $file_name); + $loop++; + } + print "\nDone...\n\n"; +} + +sub remove_duplicate_rule_values{ + $ruleset_id = trim(get_mysql_result("SELECT `ruleset_id` FROM `rule_sets` WHERE `name` = 'default'")); + print "Default Ruleset ID: " . $ruleset_id . "\n"; + + $total_removed = 0; + #::: Store Default values... + $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` = " . $ruleset_id); + my @lines = split("\n", $mysql_result); + foreach my $val (@lines){ + my @values = split("\t", $val); + $rule_set_values{$values[1]}[0] = $values[2]; + } + #::: Compare default values against other rulesets to check for duplicates... + $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` != " . $ruleset_id); + my @lines = split("\n", $mysql_result); + foreach my $val (@lines){ + my @values = split("\t", $val); + if($values[2] == $rule_set_values{$values[1]}[0]){ + print "DUPLICATE : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . ", removing...\n"; + get_mysql_result("DELETE FROM `rule_values` WHERE `ruleset_id` = " . $values[0] . " AND `rule_name` = '" . $values[1] . "'"); + $total_removed++; + } + } + + print "Total duplicate rules removed... " . $total_removed . "\n"; +} + +sub copy_file{ + $l_source_file = $_[0]; + $l_dest_file = $_[1]; + if($l_dest_file=~/\//i){ + my @dir_path = split('/', $l_dest_file); + $build_path = ""; + $di = 0; + while($dir_path[$di]){ + $build_path .= $dir_path[$di] . "/"; + #::: If path does not exist, create the directory... + if (!-d $build_path) { + mkdir($build_path); + } + if(!$dir_path[$di + 2] && $dir_path[$di + 1]){ + # print $actual_path . "\n"; + $actual_path = $build_path; + last; + } + $di++; + } + } + copy $l_source_file, $l_dest_file; +} + +sub fetch_latest_windows_binaries{ + print "\n --- Fetching Latest Windows Binaries... --- \n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); + print "\n --- Fetched Latest Windows Binaries... --- \n"; + print "\n --- Extracting... --- \n"; + unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); + my @files; + my $start_dir = "updates_staged/binaries"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + $dest_file = $file; + $dest_file =~s/updates_staged\/binaries\///g; + print "Installing :: " . $dest_file . "\n"; + copy_file($file, $dest_file); + } + print "\n --- Done... --- \n"; + + rmtree('updates_staged'); +} + +sub fetch_latest_windows_binaries_bots{ + print "\n --- Fetching Latest Windows Binaries with Bots... --- \n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); + print "\n --- Fetched Latest Windows Binaries with Bots... --- \n"; + print "\n --- Extracting... --- \n"; + unzip('updates_staged/master_windows_build_bots.zip', 'updates_staged/binaries/'); + my @files; + my $start_dir = "updates_staged/binaries"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + $dest_file = $file; + $dest_file =~s/updates_staged\/binaries\///g; + print "Installing :: " . $dest_file . "\n"; + copy_file($file, $dest_file); + } + print "\n --- Done... --- \n"; + + rmtree('updates_staged'); +} + +sub do_windows_login_server_setup{ + print "\n --- Fetching Loginserver... --- \n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server.zip", "updates_staged/login_server.zip", 1); + print "\n --- Extracting... --- \n"; + unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); + my @files; + my $start_dir = "updates_staged/login_server"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + $dest_file = $file; + $dest_file =~s/updates_staged\/login_server\///g; + print "Installing :: " . $dest_file . "\n"; + copy_file($file, $dest_file); + } + print "\n Done... \n"; + + print "Pulling down Loginserver database tables...\n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server_tables.sql", "db_update/login_server_tables.sql"); + print "\n\nInstalling Loginserver tables...\n"; + print get_mysql_result_from_file("db_update/login_server_tables.sql"); + print "\nDone...\n\n"; + + add_login_server_firewall_rules(); + + rmtree('updates_staged'); + rmtree('db_update'); + + print "\nPress any key to continue...\n"; + + <>; #Read from STDIN + +} + +sub add_login_server_firewall_rules{ + #::: Check Loginserver Firewall install for Windows + if($OS eq "Windows"){ + $output = `netsh advfirewall firewall show rule name=all`; + @output_buffer = split("\n", $output); + $has_loginserver_rules_titanium = 0; + $has_loginserver_rules_sod = 0; + foreach my $val (@output_buffer){ + if($val=~/Rule Name/i){ + $val=~s/Rule Name://g; + if($val=~/EQEmu Loginserver/i && $val=~/Titanium/i){ + $has_loginserver_rules_titanium = 1; + print "Found existing rule :: " . trim($val) . "\n"; + } + if($val=~/EQEmu Loginserver/i && $val=~/SOD/i){ + $has_loginserver_rules_sod = 1; + print "Found existing rule :: " . trim($val) . "\n"; + } + } + } + + if($has_loginserver_rules_titanium == 0){ + print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; + print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) TCP" dir=in action=allow protocol=TCP localport=5998`; + print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; + print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) UDP" dir=in action=allow protocol=UDP localport=5998`; + } + if($has_loginserver_rules_sod == 0){ + print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; + print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) TCP" dir=in action=allow protocol=TCP localport=5999`; + print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; + print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) UDP" dir=in action=allow protocol=UDP localport=5999`; + } + + print "If firewall rules don't add you must run this script (eqemu_update.pl) as administrator\n"; + print "\n"; + print "#::: Instructions \n"; + print "In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; + print " + + login.eqemulator.net + 5998 + + + + + 127.0.0.1 + 5998 + + + + "; + print "\nWhen done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; + } +} + +sub check_windows_firewall_rules{ + $output = `netsh advfirewall firewall show rule name=all`; + @output_buffer = split("\n", $output); + $has_world_rules = 0; + $has_zone_rules = 0; + foreach my $val (@output_buffer){ + if($val=~/Rule Name/i){ + $val=~s/Rule Name://g; + if($val=~/EQEmu World/i){ + $has_world_rules = 1; + print "Found existing rule :: " . trim($val) . "\n"; + } + if($val=~/EQEmu Zone/i){ + $has_zone_rules = 1; + print "Found existing rule :: " . trim($val) . "\n"; + } + } + } + + if($has_world_rules == 0){ + print "Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; + print `netsh advfirewall firewall add rule name="EQEmu World (9000) TCP" dir=in action=allow protocol=TCP localport=9000`; + print "Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; + print `netsh advfirewall firewall add rule name="EQEmu World (9000) UDP" dir=in action=allow protocol=UDP localport=9000`; + } + if($has_zone_rules == 0){ + print "Attempting to add EQEmu Zones (7000-7500) TCP \n"; + print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) TCP" dir=in action=allow protocol=TCP localport=7000-7500`; + print "Attempting to add EQEmu Zones (7000-7500) UDP \n"; + print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) UDP" dir=in action=allow protocol=UDP localport=7000-7500`; + } +} + +sub fetch_server_dlls{ + print "Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); +} + +sub fetch_peq_db_full{ + print "Downloading latest PEQ Database... Please wait...\n"; + get_remote_file("http://edit.peqtgc.com/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1); + print "Downloaded latest PEQ Database... Extracting...\n"; + unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); + my $start_dir = "updates_staged\\peq_db"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + $dest_file = $file; + $dest_file =~s/updates_staged\\peq_db\///g; + if($file=~/peqbeta|player_tables/i){ + print "MariaDB :: Installing :: " . $dest_file . "\n"; + get_mysql_result_from_file($file); + } + if($file=~/eqtime/i){ + print "Installing eqtime.cfg\n"; + copy_file($file, "eqtime.cfg"); + } + } +} + +sub map_files_fetch_bulk{ + print "\n --- Fetching Latest Maps... (This could take a few minutes...) --- \n"; + get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1); + unzip('maps/maps.zip', 'maps/'); + my @files; + my $start_dir = "maps\\EQEmuMaps-master\\maps"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + $dest_file = $file; + $dest_file =~s/maps\\EQEmuMaps-master\\maps\///g; + print "Installing :: " . $dest_file . "\n"; + copy_file($file, "maps/" . $new_file); + } + print "\n --- Fetched Latest Maps... --- \n"; + + rmtree('maps/EQEmuMaps-master'); + unlink('maps/maps.zip'); +} + +sub map_files_fetch{ + print "\n --- Fetching Latest Maps --- \n"; + + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt"); + + #::: Get Data from manifest + open (FILE, "updates_staged/eqemu_maps_manifest.txt"); + $i = 0; + while (){ + chomp; + $o = $_; + @manifest_map_data = split(',', $o); + if($manifest_map_data[0] ne ""){ + $maps_manifest[$i] = [$manifest_map_data[0], $manifest_map_data[1]]; + $i++; + } + } + + #::: Download + $fc = 0; + for($m = 0; $m <= $i; $m++){ + my $file_existing = $maps_manifest[$m][0]; + my $file_existing_size = (stat $file_existing)[7]; + if($file_existing_size != $maps_manifest[$m][1]){ + print "Updating: '" . $maps_manifest[$m][0] . "'\n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1); + $fc++; + } + } + + if($fc == 0){ + print "\nNo Map Updates found... \n\n"; + } +} + +sub quest_files_fetch{ + if (!-e "updates_staged/Quests-Plugins-master/quests/") { + print "\n --- Fetching Latest Quests --- \n"; + get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); + print "\nFetched latest quests...\n"; + mkdir('updates_staged'); + unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); + } + + $fc = 0; + use File::Find; + use File::Compare; + + my @files; + my $start_dir = "updates_staged/Quests-Plugins-master/quests/"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + if($file=~/\.pl|\.lua|\.ext/i){ + $staged_file = $file; + $dest_file = $file; + $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; + + if (!-e $dest_file) { + copy_file($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n"; + $fc++; + } + else{ + $diff = do_file_diff($dest_file, $staged_file); + if($diff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; + + print $diff . "\n"; + print "\nFile Different :: '" . $dest_file . "'\n"; + print "\nDo you wish to update this Quest? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + my $input = ; + if($input=~/N/i){} + else{ + #::: Make a backup + copy_file($dest_file, $backup_dest); + #::: Copy staged to running + copy($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n\n"; + } + $fc++; + } + } + } + } + + rmtree('updates_staged'); + + if($fc == 0){ + print "\nNo Quest Updates found... \n\n"; + } +} + +sub lua_modules_fetch{ + if (!-e "updates_staged/Quests-Plugins-master/quests/lua_modules/") { + print "\n --- Fetching Latest LUA Modules --- \n"; + get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); + print "\nFetched latest LUA Modules...\n"; + unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); + } + + $fc = 0; + use File::Find; + use File::Compare; + + my @files; + my $start_dir = "updates_staged/Quests-Plugins-master/quests/lua_modules/"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + if($file=~/\.pl|\.lua|\.ext/i){ + $staged_file = $file; + $dest_file = $file; + $dest_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; + + if (!-e $dest_file) { + copy_file($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n"; + $fc++; + } + else{ + $diff = do_file_diff($dest_file, $staged_file); + if($diff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; + print $diff . "\n"; + print "\nFile Different :: '" . $dest_file . "'\n"; + print "\nDo you wish to update this LUA Module? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + my $input = ; + if($input=~/N/i){} + else{ + #::: Make a backup + copy_file($dest_file, $backup_dest); + #::: Copy staged to running + copy($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n\n"; + } + $fc++; + } + } + } + } + + if($fc == 0){ + print "\nNo LUA Modules Updates found... \n\n"; + } +} + +sub plugins_fetch{ + if (!-e "updates_staged/Quests-Plugins-master/plugins/") { + print "\n --- Fetching Latest Plugins --- \n"; + get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); + print "\nFetched latest plugins...\n"; + unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); + } + + $fc = 0; + use File::Find; + use File::Compare; + + my @files; + my $start_dir = "updates_staged/Quests-Plugins-master/plugins/"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + if($file=~/\.pl|\.lua|\.ext/i){ + $staged_file = $file; + $dest_file = $file; + $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; + + if (!-e $dest_file) { + copy_file($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n"; + $fc++; + } + else{ + $diff = do_file_diff($dest_file, $staged_file); + if($diff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; + print $diff . "\n"; + print "\nFile Different :: '" . $dest_file . "'\n"; + print "\nDo you wish to update this Plugin? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + my $input = ; + if($input=~/N/i){} + else{ + #::: Make a backup + copy_file($dest_file, $backup_dest); + #::: Copy staged to running + copy($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n\n"; + } + $fc++; + } + } + } + } + + if($fc == 0){ + print "\nNo Plugin Updates found... \n\n"; + } +} + +sub do_file_diff{ + $file_1 = $_[0]; + $file_2 = $_[1]; + if($OS eq "Windows"){ + eval "use Text::Diff"; + $diff = diff($file_1, $file_2, { STYLE => "Unified" }); + return $diff; + } + if($OS eq "Linux"){ + # print 'diff -u "$file_1" "$file_2"' . "\n"; + return `diff -u "$file_1" "$file_2"`; + } +} + +sub unzip{ + $archive_to_unzip = $_[0]; + $dest_folder = $_[1]; + + if($OS eq "Windows"){ + eval "use Archive::Zip qw( :ERROR_CODES :CONSTANTS )"; + my $zip = Archive::Zip->new(); + unless ( $zip->read($archive_to_unzip) == AZ_OK ) { + die 'read error'; + } + print "Extracting...\n"; + $zip->extractTree('', $dest_folder); + } + if($OS eq "Linux"){ + print `unzip -o "$archive_to_unzip" -d "$dest_folder"`; + } +} + +sub are_file_sizes_different{ + $file_1 = $_[0]; + $file_2 = $_[1]; + my $file_1 = (stat $file_1)[7]; + my $file_2 = (stat $file_2)[7]; + # print $file_1 . " :: " . $file_2 . "\n"; + if($file_1 != $file_2){ + return 1; + } + return; +} + +sub do_bots_db_schema_drop{ + #"drop_bots.sql" is run before reverting database back to 'normal' + print "Fetching drop_bots.sql...\n"; + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); + print get_mysql_result_from_file("db_update/drop_bots.sql"); + + print "Restoring normality...\n"; + print get_mysql_result("DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots:%';"); + + if(get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && $db){ + print get_mysql_result("DELETE FROM `commands` WHERE `command` LIKE 'bot';"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && $db){ + print get_mysql_result("DELETE FROM `command_settings` WHERE `command` LIKE 'bot';"); + } + + if(get_mysql_result("SHOW KEYS FROM `group_id` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ + print get_mysql_result("ALTER TABLE `group_id` DROP PRIMARY KEY;"); + } + print get_mysql_result("ALTER TABLE `group_id` ADD PRIMARY KEY (`groupid`, `charid`, `ismerc`);"); + + if(get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ + print get_mysql_result("ALTER TABLE `guild_members` DROP PRIMARY KEY;"); + } + print get_mysql_result("ALTER TABLE `guild_members` ADD PRIMARY KEY (`char_id`);"); + + print get_mysql_result("UPDATE `spawn2` SET `enabled` = 0 WHERE `id` IN (59297,59298);"); + + if(get_mysql_result("SHOW COLUMNS FROM `db_version` LIKE 'bots_version'") ne "" && $db){ + print get_mysql_result("UPDATE `db_version` SET `bots_version` = 0;"); + } +} + +sub modify_db_for_bots{ + #Called after the db bots schema (2015_09_30_bots.sql) has been loaded + print "Modifying database for bots...\n"; + print get_mysql_result("UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298);"); + + if(get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ + print get_mysql_result("ALTER TABLE `guild_members` DROP PRIMARY KEY;"); + } + + if(get_mysql_result("SHOW KEYS FROM `group_id` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ + print get_mysql_result("ALTER TABLE `group_id` DROP PRIMARY KEY;"); + } + print get_mysql_result("ALTER TABLE `group_id` ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`);"); + + if(get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && get_mysql_result("SELECT `command` FROM `command_settings` WHERE `command` LIKE 'bot'") eq "" && $db){ + print get_mysql_result("INSERT INTO `command_settings` VALUES ('bot', '0', '');"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && get_mysql_result("SELECT `command` FROM `commands` WHERE `command` LIKE 'bot'") eq "" && $db){ + print get_mysql_result("INSERT INTO `commands` VALUES ('bot', '0');"); + } + + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotAAExpansion'") ne "" && $db){ + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:AAExpansion' WHERE `rule_name` LIKE 'Bots:BotAAExpansion';"); + } + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AAExpansion'") eq "" && $db){ + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:AAExpansion', '8', 'The expansion through which bots will obtain AAs');"); + } + + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreateBotCount'") ne "" && $db){ + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:CreationLimit' WHERE `rule_name` LIKE 'Bots:CreateBotCount';"); + } + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreationLimit'") eq "" && $db){ + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:CreationLimit', '150', 'Number of bots that each account can create');"); + } + + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotFinishBuffing'") ne "" && $db){ + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:FinishBuffing' WHERE `rule_name` LIKE 'Bots:BotFinishBuffing';"); + } + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:FinishBuffing'") eq "" && $db){ + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:FinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.');"); + } + + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotGroupBuffing'") ne "" && $db){ + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:GroupBuffing' WHERE `rule_name` LIKE 'Bots:BotGroupBuffing';"); + } + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:GroupBuffing'") eq "" && $db){ + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:GroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.');"); + } + + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotManaRegen'") ne "" && $db){ + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:ManaRegen' WHERE `rule_name` LIKE 'Bots:BotManaRegen';"); + } + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:ManaRegen'") eq "" && $db){ + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:ManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.');"); + } + + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotQuest'") ne "" && $db){ + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpawnLimit' WHERE `rule_name` LIKE 'Bots:BotQuest';"); + } + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpawnLimit'") eq "" && $db){ + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpawnLimit', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl');"); + } + + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotSpellQuest'") ne "" && $db){ + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpells' WHERE `rule_name` LIKE 'Bots:BotSpellQuest';"); + } + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpells'") eq "" && $db){ + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpells', 'false', 'Anita Thrall\\\'s (Anita_Thrall.pl) Bot Spell Scriber quests.');"); + } + + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnBotCount'") ne "" && $db){ + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:SpawnLimit' WHERE `rule_name` LIKE 'Bots:SpawnBotCount';"); + } + if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnLimit'") eq "" && $db){ + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:SpawnLimit', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid');"); + } + + convert_existing_bot_data(); +} + +sub convert_existing_bot_data{ + if(get_mysql_result("SHOW TABLES LIKE 'bots'") ne "" && $db){ + print "Converting existing bot data...\n"; + print get_mysql_result("INSERT INTO `bot_data` (`bot_id`, `owner_id`, `spells_id`, `name`, `last_name`, `zone_id`, `gender`, `race`, `class`, `level`, `creation_day`, `last_spawn`, `time_spawned`, `size`, `face`, `hair_color`, `hair_style`, `beard`, `beard_color`, `eye_color_1`, `eye_color_2`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `ac`, `atk`, `hp`, `mana`, `str`, `sta`, `cha`, `dex`, `int`, `agi`, `wis`, `fire`, `cold`, `magic`, `poison`, `disease`, `corruption`) SELECT `BotID`, `BotOwnerCharacterID`, `BotSpellsID`, `Name`, `LastName`, `LastZoneId`, `Gender`, `Race`, `Class`, `BotLevel`, UNIX_TIMESTAMP(`BotCreateDate`), UNIX_TIMESTAMP(`LastSpawnDate`), `TotalPlayTime`, `Size`, `Face`, `LuclinHairColor`, `LuclinHairStyle`, `LuclinBeard`, `LuclinBeardColor`, `LuclinEyeColor`, `LuclinEyeColor2`, `DrakkinHeritage`, `DrakkinTattoo`, `DrakkinDetails`, `AC`, `ATK`, `HP`, `Mana`, `STR`, `STA`, `CHA`, `DEX`, `_INT`, `AGI`, `WIS`, `FR`, `CR`, `MR`, `PR`, `DR`, `Corrup` FROM `bots`;"); + + print get_mysql_result("INSERT INTO `bot_inspect_messages` (`bot_id`, `inspect_message`) SELECT `BotID`, `BotInspectMessage` FROM `bots`;"); + + print get_mysql_result("RENAME TABLE `bots` TO `bots_old`;"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'botstances'") ne "" && $db){ + print get_mysql_result("INSERT INTO `bot_stances` (`bot_id`, `stance_id`) SELECT bs.`BotID`, bs.`StanceID` FROM `botstances` bs INNER JOIN `bot_data` bd ON bs.`BotID` = bd.`bot_id`;"); + + print get_mysql_result("RENAME TABLE `botstances` TO `botstances_old`;"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'bottimers'") ne "" && $db){ + print get_mysql_result("INSERT INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) SELECT bt.`BotID`, bt.`TimerID`, bt.`Value` FROM `bottimers` bt INNER JOIN `bot_data` bd ON bt.`BotID` = bd.`bot_id`;"); + + print get_mysql_result("RENAME TABLE `bottimers` TO `bottimers_old`;"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'botbuffs'") ne "" && $db){ + print get_mysql_result("INSERT INTO `bot_buffs` (`buffs_index`, `bot_id`, `spell_id`, `caster_level`, `duration_formula`, `tics_remaining`, `poison_counters`, `disease_counters`, `curse_counters`, `corruption_counters`, `numhits`, `melee_rune`, `magic_rune`, `persistent`) SELECT bb.`BotBuffId`, bb.`BotId`, bb.`SpellId`, bb.`CasterLevel`, bb.`DurationFormula`, bb.`TicsRemaining`, bb.`PoisonCounters`, bb.`DiseaseCounters`, bb.`CurseCounters`, bb.`CorruptionCounters`, bb.`HitCount`, bb.`MeleeRune`, bb.`MagicRune`, bb.`Persistent` FROM `botbuffs` bb INNER JOIN `bot_data` bd ON bb.`BotId` = bd.`bot_id`;"); + + if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'dot_rune'") ne "" && $db){ + print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`dot_rune` = bbo.`dot_rune` WHERE bb.`bot_id` = bbo.`BotID`;"); + } + + if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_x'") ne "" && $db){ + print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_x` = bbo.`caston_x` WHERE bb.`bot_id` = bbo.`BotID`;"); + } + + if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_y'") ne "" && $db){ + print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_y` = bbo.`caston_y` WHERE bb.`bot_id` = bbo.`BotID`;"); + } + + if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_z'") ne "" && $db){ + print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_z` = bbo.`caston_z` WHERE bb.`bot_id` = bbo.`BotID`;"); + } + + if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'ExtraDIChance'") ne "" && $db){ + print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`extra_di_chance` = bbo.`ExtraDIChance` WHERE bb.`bot_id` = bbo.`BotID`;"); + } + + print get_mysql_result("RENAME TABLE `botbuffs` TO `botbuffs_old`;"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'botinventory'") ne "" && $db){ + print get_mysql_result("INSERT INTO `bot_inventories` (`inventories_index`, `bot_id`, `slot_id`, `item_id`, `inst_charges`, `inst_color`, `inst_no_drop`, `augment_1`, `augment_2`, `augment_3`, `augment_4`, `augment_5`) SELECT bi.`BotInventoryID`, bi.`BotID`, bi.`SlotID`, bi.`ItemID`, bi.`charges`, bi.`color`, bi.`instnodrop`, bi.`augslot1`, bi.`augslot2`, bi.`augslot3`, bi.`augslot4`, bi.`augslot5` FROM `botinventory` bi INNER JOIN `bot_data` bd ON bi.`BotID` = bd.`bot_id`;"); + + if(get_mysql_result("SHOW COLUMNS FROM `botinventory` LIKE 'augslot6'") ne "" && $db){ + print get_mysql_result("UPDATE `bot_inventories` bi INNER JOIN `botinventory` bio ON bi.`inventories_index` = bio.`BotInventoryID` SET bi.`augment_6` = bio.`augslot6` WHERE bi.`bot_id` = bio.`BotID`;"); + } + + print get_mysql_result("RENAME TABLE `botinventory` TO `botinventory_old`;"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'botpets'") ne "" && $db){ + print get_mysql_result("INSERT INTO `bot_pets` (`pets_index`, `pet_id`, `bot_id`, `name`, `mana`, `hp`) SELECT bp.`BotPetsId`, bp.`PetId`, bp.`BotId`, bp.`Name`, bp.`Mana`, bp.`HitPoints` FROM `botpets` bp INNER JOIN `bot_data` bd ON bp.`BotId` = bd.`bot_id`;"); + + print get_mysql_result("RENAME TABLE `botpets` TO `botpets_old`;"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'botpetbuffs'") ne "" && $db){ + print get_mysql_result("INSERT INTO `bot_pet_buffs` (`pet_buffs_index`, `pets_index`, `spell_id`, `caster_level`, `duration`) SELECT bpb.`BotPetBuffId`, bpb.`BotPetsId`, bpb.`SpellId`, bpb.`CasterLevel`, bpb.`Duration` FROM `botpetbuffs` bpb INNER JOIN `bot_pets` bp ON bpb.`BotPetsId` = bp.`pets_index`;"); + + print get_mysql_result("RENAME TABLE `botpetbuffs` TO `botpetbuffs_old`;"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'botpetinventory'") ne "" && $db){ + print get_mysql_result("INSERT INTO `bot_pet_inventories` (`pet_inventories_index`, `pets_index`, `item_id`) SELECT bpi.`BotPetInventoryId`, bpi.`BotPetsId`, bpi.`ItemId` FROM `botpetinventory` bpi INNER JOIN `bot_pets` bp ON bpi.`BotPetsId` = bp.`pets_index`;"); + + print get_mysql_result("RENAME TABLE `botpetinventory` TO `botpetinventory_old`;"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'botgroup'") ne "" && $db){ + print get_mysql_result("INSERT INTO `bot_groups` (`groups_index`, `group_leader_id`, `group_name`) SELECT bg.`BotGroupId`, bg.`BotGroupLeaderBotId`, bg.`BotGroupName` FROM `botgroup` bg INNER JOIN `bot_data` bd ON bg.`BotGroupLeaderBotId` = bd.`bot_id`;"); + + print get_mysql_result("RENAME TABLE `botgroup` TO `botgroup_old`;"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'botgroupmembers'") ne "" && $db){ + print get_mysql_result("INSERT INTO `bot_group_members` (`group_members_index`, `groups_index`, `bot_id`) SELECT bgm.`BotGroupMemberId`, bgm.`BotGroupId`, bgm.`BotId` FROM `botgroupmembers` bgm INNER JOIN `bot_groups` bg ON bgm.`BotGroupId` = bg.`groups_index` INNER JOIN `bot_data` bd ON bgm.`BotId` = bd.`bot_id`;"); + + print get_mysql_result("RENAME TABLE `botgroupmembers` TO `botgroupmembers_old`;"); + } + + if(get_mysql_result("SHOW TABLES LIKE 'botguildmembers'") ne "" && $db){ + print get_mysql_result("INSERT INTO `bot_guild_members` (`bot_id`, `guild_id`, `rank`, `tribute_enable`, `total_tribute`, `last_tribute`, `banker`, `public_note`, `alt`) SELECT bgm.`char_id`, bgm.`guild_id`, bgm.`rank`, bgm.`tribute_enable`, bgm.`total_tribute`, bgm.`last_tribute`, bgm.`banker`, bgm.`public_note`, bgm.`alt` FROM `botguildmembers` bgm INNER JOIN `guilds` g ON bgm.`guild_id` = g.`id` INNER JOIN `bot_data` bd ON bgm.`char_id` = bd.`bot_id`;"); + + print get_mysql_result("RENAME TABLE `botguildmembers` TO `botguildmembers_old`;"); + } +} + +sub get_bots_db_version{ + #::: Check if bots_version column exists... + if(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db){ + print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;"); + print "\nColumn 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; + } + $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); + return $bots_local_db_version; +} + +sub bots_db_management{ + #::: Main Binary Database version + $bin_db_ver = trim($db_version[2]); + + #::: If we have stale data from main db run + if($db_run_stage > 0 && $bots_db_management == 0){ + clear_database_runs(); + } + + if($bin_db_ver == 0){ + print "Your server binaries (world/zone) are not compiled for bots...\n"; + return; + } + + #::: Set on flag for running bot updates... + $bots_db_management = 1; + + $bots_local_db_version = get_bots_db_version(); + + run_database_check(); +} + +sub main_db_management{ + #::: If we have stale data from bots db run + if($db_run_stage > 0 && $bots_db_management == 1){ + clear_database_runs(); + } + + #::: Main Binary Database version + $bin_db_ver = trim($db_version[1]); + + $bots_db_management = 0; + run_database_check(); +} + +sub clear_database_runs{ + # print "DEBUG :: clear_database_runs\n\n"; + #::: Clear manifest data... + %m_d = (); + #::: Clear updates... + @total_updates = (); + #::: Clear stage + $db_run_stage = 0; +} + +#::: Responsible for Database Upgrade Routines +sub run_database_check{ + + if(!$db){ + print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n"; + return; + } + + if(!@total_updates){ + #::: Pull down bots database manifest + if($bots_db_management == 1){ + print "Retrieving latest bots database manifest...\n"; + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); + } + #::: Pull down mainstream database manifest + else{ + print "Retrieving latest database manifest...\n"; + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); + } + } + + #::: Run 2 - Running pending updates... + if(@total_updates){ + @total_updates = sort @total_updates; + foreach my $val (@total_updates){ + $file_name = trim($m_d{$val}[1]); + print "Running Update: " . $val . " - " . $file_name . "\n"; + print get_mysql_result_from_file("db_update/$file_name"); + print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val"); + + if($bots_db_management == 1 && $val == 9000){ + modify_db_for_bots(); + } + } + $db_run_stage = 2; + } + #::: Run 1 - Initial checking of needed updates... + else{ + print "Reading manifest...\n\n"; + use Data::Dumper; + open (FILE, "db_update/db_update_manifest.txt"); + while () { + chomp; + $o = $_; + if($o=~/#/i){ next; } + @manifest = split('\|', $o); + $m_d{$manifest[0]} = [@manifest]; + } + #::: Setting Manifest stage... + $db_run_stage = 1; + } + + @total_updates = (); + + #::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest... + $revision_check = 1000; + if(get_mysql_result("SHOW TABLES LIKE 'character_data'") ne ""){ + $revision_check = 9000; + } + + #::: Iterate through Manifest backwards from binary version down to local version... + for($i = $bin_db_ver; $i > $revision_check; $i--){ + if(!defined($m_d{$i}[0])){ next; } + + $file_name = trim($m_d{$i}[1]); + $query_check = trim($m_d{$i}[2]); + $match_type = trim($m_d{$i}[3]); + $match_text = trim($m_d{$i}[4]); + + #::: Match type update + if($match_type eq "contains"){ + if(trim(get_mysql_result($query_check))=~/$match_text/i){ + print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + fetch_missing_db_update($i, $file_name); + push(@total_updates, $i); + } + else{ + print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + } + print_match_debug(); + print_break(); + } + if($match_type eq "missing"){ + if(get_mysql_result($query_check)=~/$match_text/i){ + print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + next; + } + else{ + print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + fetch_missing_db_update($i, $file_name); + push(@total_updates, $i); + } + print_match_debug(); + print_break(); + } + if($match_type eq "empty"){ + if(get_mysql_result($query_check) eq ""){ + print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + fetch_missing_db_update($i, $file_name); + push(@total_updates, $i); + } + else{ + print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + } + print_match_debug(); + print_break(); + } + if($match_type eq "not_empty"){ + if(get_mysql_result($query_check) ne ""){ + print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + fetch_missing_db_update($i, $file_name); + push(@total_updates, $i); + } + else{ + print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + } + print_match_debug(); + print_break(); + } + } + print "\n"; + + if(scalar (@total_updates) == 0 && $db_run_stage == 2){ + print "No updates need to be run...\n"; + if($bots_db_management == 1){ + print "Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; + get_mysql_result("UPDATE db_version SET bots_version = $bin_db_ver"); + } + else{ + print "Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; + get_mysql_result("UPDATE db_version SET version = $bin_db_ver"); + } + + clear_database_runs(); + } +} + +sub fetch_missing_db_update{ + $db_update = $_[0]; + $update_file = $_[1]; + if($db_update >= 9000){ + if($bots_db_management == 1){ + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); + } + else{ + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); + } + } + elsif($db_update >= 5000 && $db_update <= 9000){ + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); + } +} + +sub print_match_debug{ + if(!$debug){ return; } + print " Match Type: '" . $match_type . "'\n"; + print " Match Text: '" . $match_text . "'\n"; + print " Query Check: '" . $query_check . "'\n"; + print " Result: '" . trim(get_mysql_result($query_check)) . "'\n"; +} +sub print_break{ + if(!$debug){ return; } + print "\n==============================================\n"; +} \ No newline at end of file From ecdc0f709609f88b41f965cafd832e477994ac11 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Tue, 23 Aug 2016 13:54:51 -0400 Subject: [PATCH 310/693] Fixed so mobs that depop at end of pathgrid still path and depop whiel zones are empty. This makes these mobs no longer always appear at start locations for the 1st person in a zone after long idle. --- zone/entity.cpp | 16 ++++++++++------ zone/mob.h | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index d398c9bf6..975b793e9 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -478,14 +478,18 @@ void EntityList::MobProcess() size_t sz = mob_list.size(); #ifdef IDLE_WHEN_EMPTY - // spawn_events can cause spawns and deaths while zone empty. - // At the very least, process that. - if (numclients < 1) { - mob_dead = mob->CastToNPC()->GetDepop(); - } - else { + if (numclients > 0 || + mob->GetWanderType() == 4 || mob->GetWanderType() == 6) { + // Normal processing, or assuring that spawns that should + // path and depop do that. Otherwise all of these type mobs + // will be up and at starting positions when idle zone wakes up. mob_dead = !mob->Process(); } + else { + // spawn_events can cause spawns and deaths while zone empty. + // At the very least, process that. + mob_dead = mob->CastToNPC()->GetDepop(); + } #else mob_dead = !mob->Process(); #endif diff --git a/zone/mob.h b/zone/mob.h index 3106df4ff..ff4879edd 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -843,6 +843,7 @@ public: inline void SetFocused(bool nState) { focused = nState; } inline const bool IsFocused() const { return focused; } inline const bool IsRoamer() const { return roamer; } + inline const int GetWanderType() const { return wandertype; } inline const bool IsRooted() const { return rooted || permarooted; } inline const bool HasVirus() const { return has_virus; } int GetSnaredAmount(); From 5039aa07a5a5cbf89b212df44375682247f189d9 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Tue, 23 Aug 2016 14:50:29 -0400 Subject: [PATCH 311/693] updated changelog --- changelog.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/changelog.txt b/changelog.txt index 7647ea8ec..cde46e646 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/23/2016 == +noudess: Force mobs on a depop @ end pathgrid to still do this on idle zones. +This makes them be more random after a zone is idle, rather than always showing +up at start point when 1st person logs into an idle zone. Much more like live. +I dion't think this will be much of a performance problem. Once they path and +depop, no mkore cpu usage. + == 08/14/2016 == mackal: Implement Linked Spell Reuse Timers - For whatever reason this is a bit unfriendly, but that's how it is on live. From f6b6fcc2c5483f532c5e0750aaefb859fc51937d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 24 Aug 2016 20:38:56 -0500 Subject: [PATCH 312/693] Update eqemu_server.pl --- utils/scripts/eqemu_server.pl | 819 +++++++++++++++++++++------------- 1 file changed, 504 insertions(+), 315 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index b575bb1cf..b28e5f082 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -1,8 +1,12 @@ #!/usr/bin/perl ########################################################### -#::: Automatic (Database) Upgrade Script -#::: Author: Akkadius +#::: General EQEmu Server Administration Script +#::: Purpose - Handles: +#::: Automatic database versioning (bots and normal DB) +#::: Updating server assets (binary, opcodes, maps, configuration files) +#::: Original Author: Akkadius +#::: Contributors: Uleat #::: Purpose: To upgrade databases with ease and maintain versioning ########################################################### @@ -13,9 +17,14 @@ use File::Copy qw(copy); use POSIX qw(strftime); use File::Path; use File::Find; -use URI::Escape; -use Time::HiRes qw(usleep); +use Time::HiRes qw(usleep); +#::: Variables + +$install_repository_request_url = "https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/"; +$eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/master/"; + +#::: Globals $time_stamp = strftime('%m-%d-%Y', gmtime()); $console_output .= " Operating System is: $Config{osname}\n"; @@ -27,14 +36,14 @@ $current_version = 14; if($ARGV[0] eq "V"){ if($ARGV[1] > $current_version){ - print "eqemu_update.pl Automatic Database Upgrade Needs updating...\n"; - print " Current version: " . $current_version . "\n"; - print " New version: " . $ARGV[1] . "\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); + print "[Update] eqemu_server.pl Automatic Database Upgrade Needs updating...\n"; + print "[Update] Current version: " . $current_version . "\n"; + print "[Update] New version: " . $ARGV[1] . "\n"; + get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "eqemu_server.pl"); exit; } else{ - print "[Upgrade Script] No script update necessary \n"; + print "[Update] No script update necessary \n"; } exit; } @@ -44,8 +53,10 @@ $db_run_stage = 0; $perl_version = $^V; $perl_version =~s/v//g; -print "Perl Version is " . $perl_version . "\n"; -if($perl_version > 5.12){ no warnings 'uninitialized'; } +print "[Update] Perl Version is " . $perl_version . "\n"; +if($perl_version > 5.12){ + no warnings 'uninitialized'; +} no warnings; ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); @@ -64,11 +75,7 @@ while() { elsif(/(.*)<\/db>/i) { $db = $1; } } -$console_output = -"============================================================ - EQEmu: Automatic Upgrade Check -============================================================ -"; +$console_output = "[Update] EQEmu: Automatic Database Upgrade Check\n"; if($OS eq "Windows"){ $has_mysql_path = `echo %PATH%`; @@ -81,9 +88,8 @@ if($OS eq "Windows"){ last; } } - $console_output .= " (Windows) MySQL is in system path \n"; - $console_output .= " Path = " . $path . "\n"; - $console_output .= "============================================================\n"; + $console_output .= "[Update] (Windows) MySQL is in system path \n"; + $console_output .= "[Update] Path = " . $path . "\n"; } } @@ -95,9 +101,8 @@ if($OS eq "Linux"){ } $path =~s/\n//g; - $console_output .= " (Linux) MySQL is in system path \n"; - $console_output .= " Path = " . $path . "\n"; - $console_output .= "============================================================\n"; + $console_output .= "[Update] (Linux) MySQL is in system path \n"; + $console_output .= "[Update] Path = " . $path . "\n"; } #::: Path not found, error and exit @@ -107,87 +112,6 @@ if($path eq ""){ exit; } -if($ARGV[0] eq "install_peq_db"){ - - $db_name = "peq"; - if($ARGV[1]){ - $db_name = $ARGV[1]; - } - - $db = $db_name; - - #::: Database Routines - print "MariaDB :: Creating Database '" . $db_name . "'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); - - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); -} - -if($ARGV[0] eq "remove_duplicate_rules"){ - remove_duplicate_rule_values(); - exit; -} - -if($ARGV[0] eq "installer"){ - print "Running EQEmu Server installer routines...\n"; - mkdir('logs'); - mkdir('updates_staged'); - mkdir('shared'); - fetch_latest_windows_binaries(); - map_files_fetch_bulk(); - opcodes_fetch(); - plugins_fetch(); - quest_files_fetch(); - lua_modules_fetch(); - - #::: Binary dll's - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); - - #::: Server scripts - fetch_utility_scripts(); - - #::: Database Routines - print "MariaDB :: Creating Database 'peq'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS peq;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE peq"`; - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); - - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); - - if($OS eq "Windows"){ - check_windows_firewall_rules(); - do_windows_login_server_setup(); - } - exit; -} - -if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } -if($ARGV[0] eq "login_server_setup"){ - do_windows_login_server_setup(); - exit; -} #::: Create db_update working directory if not created mkdir('db_update'); @@ -218,124 +142,377 @@ $bin_db_ver = trim($db_version[1]); $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); #::: If ran from Linux startup script, supress output -if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_start"){ - print "Database up to date...\n"; +if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_world"){ + print "[Update] Database up to date...\n"; exit; } -else{ - print $console_output if $db; +else { + + #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup + if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){ + print "[Update] Database not up to date with binaries... Automatically updating...\n"; + print "[Update] Issuing database backup first...\n"; + database_dump_compress(); + print "[Update] Updating database...\n"; + sleep(1); + main_db_management(); + main_db_management(); + print "[Update] Continuing bootup\n"; + exit; + } + + if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } + show_menu_prompt(); } if($db){ - print " Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; + print "[Update] Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; #::: Bots #::: Make sure we're running a bots binary to begin with if(trim($db_version[2]) > 0){ $bots_local_db_version = get_bots_db_version(); if($bots_local_db_version > 0){ - print " (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; + print "[Update] (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; } } #::: If World ran this script, and our version is up to date, continue... if($bin_db_ver <= $local_db_ver && $ARGV[0] eq "ran_from_world"){ - print " Database up to Date: Continuing World Bootup...\n"; - print "============================================================\n"; + print "[Update] Database up to Date: Continuing World Bootup...\n"; exit; } +} + +sub get_installation_variables{ + #::: Fetch installation variables before building the config + open (INSTALL_VARS, "../install_variables.txt"); + while (){ + chomp; + $o = $_; + @data = split(":", $o); + $installation_variables{trim($data[0])} = trim($data[1]); + } + close (INSTALL_VARS); } -if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){ - print "You have missing database updates, type 1 or 2 to backup your database before running them as recommended...\n\n"; - #::: Display Menu - show_menu_prompt(); +sub do_install_config_xml { + get_installation_variables(); + + #::: Fetch XML template + get_remote_file($install_repository_request_url . "eqemu_config.xml", "eqemu_config_template.xml"); + + #::: Open new config file + open (NEW_CONFIG, '>', 'eqemu_config.xml'); + + $in_database_tag = 0; + + #::: Iterate through template and replace variables... + open (FILE_TEMPLATE, "eqemu_config_template.xml"); + while (){ + chomp; + $o = $_; + + #::: Find replace variables + + if($o=~/\<\!--/i){ + next; + } + + if($o=~/database/i && $o=~/\<\//i){ + $in_database_tag = 0; + } + if($o=~/database/i){ + $in_database_tag = 1; + } + + if($o=~/key/i){ + my($replace_key) = $o =~ />(\w+)/i && $in_database_tag){ + my($replace_username) = $o =~ />(\w+)/i && $in_database_tag){ + my($replace_password) = $o =~ />(\w+)/i){ + my($replace_db_name) = $o =~ />(\w+) \&database_dump, - 2 => \&database_dump_compress, - 3 => \&main_db_management, - 4 => \&bots_db_management, - 5 => \&opcodes_fetch, - 6 => \&map_files_fetch, - 7 => \&plugins_fetch, - 8 => \&quest_files_fetch, - 9 => \&lua_modules_fetch, - 10 => \&aa_fetch, - 11 => \&fetch_latest_windows_binaries, - 12 => \&fetch_server_dlls, - 13 => \&do_windows_login_server_setup, - 14 => \&remove_duplicate_rule_values, - 15 => \&fetch_utility_scripts, - 18 => \&fetch_latest_windows_binaries_bots, - 19 => \&do_bots_db_schema_drop, - 20 => \&do_update_self, - 21 => \&database_dump_player_tables, - 0 => \&script_exit, + # "backup_database" => \&database_dump, + # 2 => \&database_dump_compress, + 3 => \&main_db_management, + 4 => \&bots_db_management, + # 5 => \&opcodes_fetch, + # 6 => \&map_files_fetch, + #7 => \&plugins_fetch, + #8 => \&quest_files_fetch, + # 9 => \&lua_modules_fetch, + # 10 => \&aa_fetch, + # 11 => \&fetch_latest_windows_binaries, + # 12 => \&fetch_server_dlls, + # 13 => \&do_windows_login_server_setup, + # 14 => \&remove_duplicate_rule_values, + # 15 => \&fetch_utility_scripts, + # 18 => \&fetch_latest_windows_binaries_bots, + # 19 => \&do_bots_db_schema_drop, + 20 => \&do_update_self, + # 21 => \&database_dump_player_tables, + 0 => \&script_exit, ); - while (1) { - { - local $| = 1; - if(!$menu_show && ($ARGV[0] eq "ran_from_world" || $ARGV[0] eq "ran_from_start")){ - $menu_show++; - next; - } - print menu_options(), '> '; - $menu_displayed++; - if($menu_displayed > 50){ - print "Safety: Menu looping too many times, exiting...\n"; - exit; - } + $dc = 0; + while (1) { + $input = trim($input); + + $errored_command = 0; + + if($input eq "database"){ + print "====================================================\n"; + print "Database Menu:\n-------------\n"; + print " backup_database Back up database to backups/ directory\n"; + print " backup_player_tables Back up player tables to backups/ directory\n"; + print " backup_database_compressed Back up database compressed to backups/ directory\n"; + print " - \n"; + print " check_db_updates Checks for database updates manually\n"; + print " check_bot_db_updates Checks for bot database updates\n"; + print " - \n"; + print " aa_tables Downloads and installs clean slate AA data from PEQ\n"; + print " remove_duplicate_rules Removes duplicate rules from rule_values table\n"; + print " drop_bots_db_schema Removes bot database schema\n"; + + print " \nmain - go back to main menu\n"; + $last_menu = trim($input); } - - my $choice = <>; - - $choice =~ s/\A\s+//; - $choice =~ s/\s+\z//; - - if (defined(my $handler = $dispatch{$choice})) { - my $result = $handler->(); - unless (defined $result) { - exit 0; + elsif($input eq "server_assets"){ + print "====================================================\n"; + print "Server Assets Menu:\n"; + print " maps Download latest maps\n"; + print " opcodes Download opcodes (Patches for eq clients)\n"; + print " quests Download latest quests\n"; + print " plugins Download latest plugins\n"; + print " lua_modules Download latest lua_modules\n"; + print " utility_scripts Download utility scripts to run and operate the EQEmu Server\n"; + if($OS eq "Windows"){ + print "--- Windows\n"; + print " windows_server_download Updates server code from latest stable\n"; + print " windows_server_download_bots Updates server code (bots enabled) from latest\n"; + print " fetch_dlls Grabs dll's needed to run windows binaries\n"; + print " setup_loginserver Sets up loginserver for Windows\n"; } + print " \nmain - go back to main menu\n"; + $last_menu = trim($input); + } + elsif($input eq "backup_database"){ database_dump(); $dc = 1; } + elsif($input eq "backup_player_tables"){ database_dump_player_tables(); $dc = 1; } + elsif($input eq "backup_database_compressed"){ database_dump_compress(); $dc = 1; } + elsif($input eq "aa_tables"){ aa_fetch(); $dc = 1; } + elsif($input eq "remove_duplicate_rules"){ remove_duplicate_rule_values(); $dc = 1; } + elsif($input eq "maps"){ map_files_fetch_bulk(); $dc = 1; } + elsif($input eq "opcodes"){ opcodes_fetch(); $dc = 1; } + elsif($input eq "plugins"){ plugins_fetch(); $dc = 1; } + elsif($input eq "quests"){ quest_files_fetch(); $dc = 1; } + elsif($input eq "lua_modules"){ lua_modules_fetch(); $dc = 1; } + elsif($input eq "windows_server_download"){ fetch_latest_windows_binaries(); $dc = 1; } + elsif($input eq "windows_server_download_bots"){ fetch_latest_windows_binaries_bots(); $dc = 1; } + elsif($input eq "fetch_dlls"){ fetch_server_dlls(); $dc = 1; } + elsif($input eq "utility_scripts"){ fetch_utility_scripts(); $dc = 1; } + elsif($input eq "check_db_updates"){ main_db_management(); $dc = 1; } + elsif($input eq "check_bot_db_updates"){ bots_db_management(); $dc = 1; } + elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; } + elsif($input eq "exit"){ + exit; + } + elsif($input eq "main"){ + print "Returning to main menu...\n"; + print_main_menu(); + $last_menu = trim($input); + } + elsif($input eq "" && $last_menu ne ""){ + $errored_command = 1; + } + elsif($input ne ""){ + print "Invalid command '" . $input . "'\n"; + $errored_command = 1; } else { - if($ARGV[0] ne "ran_from_world"){ - # warn "\n\nInvalid selection\n\n"; - } + print_main_menu(); } + + #::: Errored command checking + if($errored_command == 1){ + $input = $last_menu; + } + elsif($dc == 1){ $dc = 0; $input = ""; } + else { + $input = <>; + } + } } +sub print_main_menu { + print "====================================================\n"; + print "#::: EQEmu Server Tool Menu\n"; + print "====================================================\n"; + print " database Enter database management menu \n"; + print " server_assets Manage server assets \n"; + print " exit \n"; + print "\n"; +} + sub menu_options { if(@total_updates){ if($bots_db_management == 1){ @@ -358,9 +535,9 @@ sub menu_options { } return <new; $ua->timeout(10); $ua->env_proxy; - my $response = $ua->get($URL); + my $response = $ua->get($request_url); if ($response->is_success){ - open (FILE, '> ' . $Dest_File . ''); + open (FILE, '> ' . $destination_file . ''); print FILE $response->decoded_content; close (FILE); } else { # print "Error, no connection or failed request...\n\n"; } - if(-e $Dest_File) { + if(-e $destination_file) { $break = 1; - print " [URL] :: " . $URL . "\n"; - print " [Saved] :: " . $Dest_File . "\n"; + print " Saved: (" . $destination_file . ") from " . $request_url . "\n"; } else { $break = 0; } usleep(500); } @@ -533,9 +715,8 @@ sub get_remote_file{ } if($OS eq "Linux"){ #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt - $wget = `wget --no-check-certificate --quiet -O $Dest_File $URL`; - print " o URL: (" . $URL . ")\n"; - print " o Saved: (" . $Dest_File . ") \n"; + $wget = `wget --no-check-certificate --quiet -O $destination_file $request_url`; + print " Saved: (" . $destination_file . ") from " . $request_url . "\n"; if($wget=~/unable to resolve/i){ print "Error, no connection or failed request...\n\n"; #die; @@ -559,7 +740,7 @@ sub aa_fetch{ } print "Pulling down PEQ AA Tables...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); + get_remote_file($eqemu_repository_request_url . "utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); print "\n\nInstalling AA Tables...\n"; print get_mysql_result_from_file("db_update/peq_aa_tables_post_rework.sql"); print "\nDone...\n\n"; @@ -569,33 +750,32 @@ sub aa_fetch{ sub opcodes_fetch{ print "Pulling down latest opcodes...\n"; %opcodes = ( - 1 => ["opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/opcodes.conf"], - 2 => ["mail_opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/mail_opcodes.conf"], - 3 => ["Titanium", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Titanium.conf"], - 4 => ["Secrets of Faydwer", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoF.conf"], - 5 => ["Seeds of Destruction", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoD.conf"], - 6 => ["Underfoot", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_UF.conf"], - 7 => ["Rain of Fear", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF.conf"], - 8 => ["Rain of Fear 2", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF2.conf"], + 1 => ["opcodes", $eqemu_repository_request_url . "utils/patches/opcodes.conf"], + 2 => ["mail_opcodes", $eqemu_repository_request_url . "utils/patches/mail_opcodes.conf"], + 3 => ["Titanium", $eqemu_repository_request_url . "utils/patches/patch_Titanium.conf"], + 4 => ["Secrets of Faydwer", $eqemu_repository_request_url . "utils/patches/patch_SoF.conf"], + 5 => ["Seeds of Destruction", $eqemu_repository_request_url . "utils/patches/patch_SoD.conf"], + 6 => ["Underfoot", $eqemu_repository_request_url . "utils/patches/patch_UF.conf"], + 7 => ["Rain of Fear", $eqemu_repository_request_url . "utils/patches/patch_RoF.conf"], + 8 => ["Rain of Fear 2", $eqemu_repository_request_url . "utils/patches/patch_RoF2.conf"], ); $loop = 1; while($opcodes{$loop}[0]){ - #::: Split the URL by the patches folder to get the file name from URL + #::: Split the request_url by the patches folder to get the file name from request_url @real_file = split("patches/", $opcodes{$loop}[1]); $find = 0; while($real_file[$find]){ $file_name = $real_file[$find]; $find++; } - - print "\nDownloading (" . $opcodes{$loop}[0] . ") File: '" . $file_name . "'...\n\n"; + get_remote_file($opcodes{$loop}[1], $file_name); $loop++; } print "\nDone...\n\n"; } -sub remove_duplicate_rule_values{ +sub remove_duplicate_rule_values { $ruleset_id = trim(get_mysql_result("SELECT `ruleset_id` FROM `rule_sets` WHERE `name` = 'default'")); print "Default Ruleset ID: " . $ruleset_id . "\n"; @@ -622,33 +802,33 @@ sub remove_duplicate_rule_values{ print "Total duplicate rules removed... " . $total_removed . "\n"; } -sub copy_file{ +sub copy_file { $l_source_file = $_[0]; - $l_dest_file = $_[1]; - if($l_dest_file=~/\//i){ - my @dir_path = split('/', $l_dest_file); + $l_destination_file = $_[1]; + if($l_destination_file=~/\//i){ + my @dir_path = split('/', $l_destination_file); $build_path = ""; - $di = 0; - while($dir_path[$di]){ - $build_path .= $dir_path[$di] . "/"; + $directory_index = 0; + while($directory_indexr_path[$directory_index]){ + $build_path .= $directory_indexr_path[$directory_index] . "/"; #::: If path does not exist, create the directory... if (!-d $build_path) { mkdir($build_path); } - if(!$dir_path[$di + 2] && $dir_path[$di + 1]){ + if(!$directory_indexr_path[$directory_index + 2] && $directory_indexr_path[$directory_index + 1]){ # print $actual_path . "\n"; $actual_path = $build_path; last; } - $di++; + $directory_index++; } } - copy $l_source_file, $l_dest_file; + copy $l_source_file, $l_destination_file; } -sub fetch_latest_windows_binaries{ +sub fetch_latest_windows_binaries { print "\n --- Fetching Latest Windows Binaries... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); + get_remote_file($install_repository_request_url . "master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); print "\n --- Fetched Latest Windows Binaries... --- \n"; print "\n --- Extracting... --- \n"; unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); @@ -659,19 +839,19 @@ sub fetch_latest_windows_binaries{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/binaries\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/binaries\///g; + print "Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } print "\n --- Done... --- \n"; rmtree('updates_staged'); } -sub fetch_latest_windows_binaries_bots{ +sub fetch_latest_windows_binaries_bots { print "\n --- Fetching Latest Windows Binaries with Bots... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); + get_remote_file($install_repository_request_url . "master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); print "\n --- Fetched Latest Windows Binaries with Bots... --- \n"; print "\n --- Extracting... --- \n"; unzip('updates_staged/master_windows_build_bots.zip', 'updates_staged/binaries/'); @@ -682,19 +862,19 @@ sub fetch_latest_windows_binaries_bots{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/binaries\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/binaries\///g; + print "Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } print "\n --- Done... --- \n"; rmtree('updates_staged'); } -sub do_windows_login_server_setup{ +sub do_windows_login_server_setup { print "\n --- Fetching Loginserver... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server.zip", "updates_staged/login_server.zip", 1); + get_remote_file($install_repository_request_url . "login_server.zip", "updates_staged/login_server.zip", 1); print "\n --- Extracting... --- \n"; unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); my @files; @@ -704,15 +884,15 @@ sub do_windows_login_server_setup{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/login_server\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/login_server\///g; + print "Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } print "\n Done... \n"; print "Pulling down Loginserver database tables...\n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server_tables.sql", "db_update/login_server_tables.sql"); + get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); print "\n\nInstalling Loginserver tables...\n"; print get_mysql_result_from_file("db_update/login_server_tables.sql"); print "\nDone...\n\n"; @@ -728,7 +908,7 @@ sub do_windows_login_server_setup{ } -sub add_login_server_firewall_rules{ +sub add_login_server_firewall_rules { #::: Check Loginserver Firewall install for Windows if($OS eq "Windows"){ $output = `netsh advfirewall firewall show rule name=all`; @@ -762,7 +942,7 @@ sub add_login_server_firewall_rules{ print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) UDP" dir=in action=allow protocol=UDP localport=5999`; } - print "If firewall rules don't add you must run this script (eqemu_update.pl) as administrator\n"; + print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n"; print "\n"; print "#::: Instructions \n"; print "In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; @@ -819,9 +999,9 @@ sub check_windows_firewall_rules{ sub fetch_server_dlls{ print "Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); + get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); + get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); + get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); } sub fetch_peq_db_full{ @@ -829,16 +1009,16 @@ sub fetch_peq_db_full{ get_remote_file("http://edit.peqtgc.com/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1); print "Downloaded latest PEQ Database... Extracting...\n"; unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); - my $start_dir = "updates_staged\\peq_db"; + my $start_dir = "updates_staged/peq_db"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\\peq_db\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/peq_db\///g; if($file=~/peqbeta|player_tables/i){ - print "MariaDB :: Installing :: " . $dest_file . "\n"; + print "MariaDB :: Installing :: maps/" . $destination_file . "\n"; get_mysql_result_from_file($file); } if($file=~/eqtime/i){ @@ -853,15 +1033,15 @@ sub map_files_fetch_bulk{ get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1); unzip('maps/maps.zip', 'maps/'); my @files; - my $start_dir = "maps\\EQEmuMaps-master\\maps"; + my $start_dir = "maps/EQEmuMaps-master/maps"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/maps\\EQEmuMaps-master\\maps\///g; - print "Installing :: " . $dest_file . "\n"; + $destination_file = $file; + $destination_file =~s/maps\/EQEmuMaps-master\/maps\///g; + print "Installing :: " . $destination_file . "\n"; copy_file($file, "maps/" . $new_file); } print "\n --- Fetched Latest Maps... --- \n"; @@ -927,30 +1107,30 @@ sub quest_files_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this Quest? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + print $directory_indexff . "\n"; + print "\nFile Different :: '" . $destination_file . "'\n"; + print "\nDo you wish to update this Quest? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -986,29 +1166,29 @@ sub lua_modules_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this LUA Module? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + print $directory_indexff . "\n"; + print "\nFile Different :: '" . $destination_file . "'\n"; + print "\nDo you wish to update this LUA Module? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -1042,29 +1222,29 @@ sub plugins_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this Plugin? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + print $directory_indexff . "\n"; + print "\nFile Different :: '" . $destination_file . "'\n"; + print "\nDo you wish to update this Plugin? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -1082,8 +1262,8 @@ sub do_file_diff{ $file_2 = $_[1]; if($OS eq "Windows"){ eval "use Text::Diff"; - $diff = diff($file_1, $file_2, { STYLE => "Unified" }); - return $diff; + $directory_indexff = diff($file_1, $file_2, { STYLE => "Unified" }); + return $directory_indexff; } if($OS eq "Linux"){ # print 'diff -u "$file_1" "$file_2"' . "\n"; @@ -1124,7 +1304,7 @@ sub are_file_sizes_different{ sub do_bots_db_schema_drop{ #"drop_bots.sql" is run before reverting database back to 'normal' print "Fetching drop_bots.sql...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); print get_mysql_result_from_file("db_update/drop_bots.sql"); print "Restoring normality...\n"; @@ -1351,7 +1531,7 @@ sub bots_db_management{ } if($bin_db_ver == 0){ - print "Your server binaries (world/zone) are not compiled for bots...\n"; + print "Your server binaries (world/zone) are not compiled for bots...\n\n"; return; } @@ -1398,17 +1578,17 @@ sub run_database_check{ #::: Pull down bots database manifest if($bots_db_management == 1){ print "Retrieving latest bots database manifest...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); } #::: Pull down mainstream database manifest else{ print "Retrieving latest database manifest...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); + get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); } } #::: Run 2 - Running pending updates... - if(@total_updates){ + if(@total_updates || $db_run_stage == 1){ @total_updates = sort @total_updates; foreach my $val (@total_updates){ $file_name = trim($m_d{$val}[1]); @@ -1514,7 +1694,7 @@ sub run_database_check{ print "Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; get_mysql_result("UPDATE db_version SET bots_version = $bin_db_ver"); } - else{ + else{ print "Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; get_mysql_result("UPDATE db_version SET version = $bin_db_ver"); } @@ -1528,14 +1708,14 @@ sub fetch_missing_db_update{ $update_file = $_[1]; if($db_update >= 9000){ if($bots_db_management == 1){ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); } else{ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); } } elsif($db_update >= 5000 && $db_update <= 9000){ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); } } @@ -1549,4 +1729,13 @@ sub print_match_debug{ sub print_break{ if(!$debug){ return; } print "\n==============================================\n"; -} \ No newline at end of file +} + +sub generate_random_password { + my $passwordsize = shift; + my @alphanumeric = ('a'..'z', 'A'..'Z', 0..9); + my $randpassword = join '', + map $alphanumeric[rand @alphanumeric], 0..$passwordsize; + + return $randpassword; +} From 3afc5d089080eb97cfd13814f26d5c3006df69bc Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 24 Aug 2016 21:03:23 -0500 Subject: [PATCH 313/693] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 75 +---------------------------------- 1 file changed, 2 insertions(+), 73 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index b28e5f082..894d142c4 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -390,28 +390,6 @@ sub fetch_utility_scripts { } sub show_menu_prompt { - my %dispatch = ( - # "backup_database" => \&database_dump, - # 2 => \&database_dump_compress, - 3 => \&main_db_management, - 4 => \&bots_db_management, - # 5 => \&opcodes_fetch, - # 6 => \&map_files_fetch, - #7 => \&plugins_fetch, - #8 => \&quest_files_fetch, - # 9 => \&lua_modules_fetch, - # 10 => \&aa_fetch, - # 11 => \&fetch_latest_windows_binaries, - # 12 => \&fetch_server_dlls, - # 13 => \&do_windows_login_server_setup, - # 14 => \&remove_duplicate_rule_values, - # 15 => \&fetch_utility_scripts, - # 18 => \&fetch_latest_windows_binaries_bots, - # 19 => \&do_bots_db_schema_drop, - 20 => \&do_update_self, - # 21 => \&database_dump_player_tables, - 0 => \&script_exit, - ); $dc = 0; while (1) { @@ -472,6 +450,7 @@ sub show_menu_prompt { elsif($input eq "check_db_updates"){ main_db_management(); $dc = 1; } elsif($input eq "check_bot_db_updates"){ bots_db_management(); $dc = 1; } elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; } + elsif($input eq "update_script"){ do_update_self(); $dc = 1; } elsif($input eq "exit"){ exit; } @@ -509,61 +488,11 @@ sub print_main_menu { print "====================================================\n"; print " database Enter database management menu \n"; print " server_assets Manage server assets \n"; + print " update_script Updates this management script \n"; print " exit \n"; print "\n"; } -sub menu_options { - if(@total_updates){ - if($bots_db_management == 1){ - $option[3] = "Check and stage pending REQUIRED Database updates"; - $bots_management = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; - } - else{ - $option[3] = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; - if(get_mysql_result("SHOW TABLES LIKE 'bots'") eq ""){ - $bots_management = "Install bots database pre-requisites (Requires bots server binaries)"; - } - else{ - $bots_management = "Check for Bot pending REQUIRED database updates... (Must have bots enabled)"; - } - } - } - else{ - $option[3] = "Check and stage pending REQUIRED Database updates"; - $bots_management = "Check for Bot REQUIRED database updates... (Must have bots enabled)"; - } - -return < Date: Wed, 24 Aug 2016 23:15:31 -0400 Subject: [PATCH 314/693] Only correct spell slots when we're sending to self This will fix display issues with lots of buffs on NPCs --- common/patches/rof.cpp | 9 +++++---- common/patches/rof2.cpp | 17 ++++++++--------- common/patches/uf.cpp | 12 +++++------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 939ad03fa..7c5f302cb 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -477,10 +477,11 @@ namespace RoF for (uint16 i = 0; i < emu->count; ++i) { uint16 buffslot = emu->entries[i].buff_slot; - // Not sure if this is needs amending for RoF yet. - if (emu->entries[i].buff_slot >= 25) - { - buffslot += 17; + if (emu->type == 0) { // only correct for self packets + if (emu->entries[i].buff_slot >= 25) + buffslot += 17; + if (buffslot == 54) + buffslot = 62; } __packet->WriteUInt32(buffslot); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 118419f48..5bb93f14a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -549,16 +549,15 @@ namespace RoF2 for (uint16 i = 0; i < emu->count; ++i) { uint16 buffslot = emu->entries[i].buff_slot; - // Not sure if this is needs amending for RoF2 yet. - if (emu->entries[i].buff_slot >= 25) - { - buffslot += 17; + if (emu->type == 0) { // only correct for self packets + if (emu->entries[i].buff_slot >= 25) + buffslot += 17; + // TODO: We should really just deal with these "server side" + // so we can have clients not limited to other clients. + // This fixes discs, songs were changed to 20 + if (buffslot == 54) + buffslot = 62; } - // TODO: We should really just deal with these "server side" - // so we can have clients not limited to other clients. - // This fixes discs, songs were changed to 20 - if (buffslot == 54) - buffslot = 62; __packet->WriteUInt32(buffslot); __packet->WriteUInt32(emu->entries[i].spell_id); diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 6a1a03a09..af81fea06 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -410,13 +410,11 @@ namespace UF for (uint16 i = 0; i < emu->count; ++i) { uint16 buffslot = emu->entries[i].buff_slot; - if (emu->entries[i].buff_slot >= 25 && emu->entries[i].buff_slot < 37) - { - buffslot += 5; - } - else if (emu->entries[i].buff_slot >= 37) - { - buffslot += 14; + if (emu->type == 0) { // only correct for self packets + if (emu->entries[i].buff_slot >= 25 && emu->entries[i].buff_slot < 37) + buffslot += 5; + else if (emu->entries[i].buff_slot >= 37) + buffslot += 14; } __packet->WriteUInt32(buffslot); From 37b87e98f47f0c9cc277e342b3f0176021ad4cc9 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 01:18:03 -0500 Subject: [PATCH 315/693] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 292 +++++++++++++++++++--------------- 1 file changed, 168 insertions(+), 124 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 894d142c4..02f101cc5 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -61,19 +61,7 @@ no warnings; ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); -my $confile = "eqemu_config.xml"; #default -open(F, "<$confile"); -my $indb = 0; -while() { - s/\r//g; - if(//i) { $indb = 1; } - next unless($indb == 1); - if(/<\/database>/i) { $indb = 0; last; } - if(/(.*)<\/host>/i) { $host = $1; } - elsif(/(.*)<\/username>/i) { $user = $1; } - elsif(/(.*)<\/password>/i) { $pass = $1; } - elsif(/(.*)<\/db>/i) { $db = $1; } -} +read_eqemu_config_xml(); $console_output = "[Update] EQEmu: Automatic Database Upgrade Check\n"; @@ -112,7 +100,6 @@ if($path eq ""){ exit; } - #::: Create db_update working directory if not created mkdir('db_update'); @@ -161,8 +148,11 @@ else { exit; } - if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } - show_menu_prompt(); + #::: Make sure that we didn't pass any arugments to the script + if(!$ARGV[0]){ + if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } + show_menu_prompt(); + } } if($db){ @@ -185,6 +175,112 @@ if($db){ } + +if($ARGV[0] eq "install_peq_db"){ + + get_installation_variables(); + + $db_name = "peq"; + if($ARGV[1]){ + $db_name = $ARGV[1]; + } + elsif($installation_variables{"mysql_eqemu_db_name"}){ + $db_name = $installation_variables{"mysql_eqemu_db_name"}; + } + + $db = $db_name; + + #::: Database Routines + print "MariaDB :: Creating Database '" . $db_name . "'\n"; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; + if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } + if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } + $bin_db_ver = trim($db_version[1]); + check_db_version_table(); + $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + fetch_peq_db_full(); + print "\nFetching Latest Database Updates...\n"; + main_db_management(); + print "\nApplying Latest Database Updates...\n"; + main_db_management(); + + print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); +} + +if($ARGV[0] eq "remove_duplicate_rules"){ + remove_duplicate_rule_values(); + exit; +} + +if($ARGV[0] eq "map_files_fetch_bulk"){ + map_files_fetch_bulk(); + exit; +} + +if($ARGV[0] eq "installer"){ + print "Running EQEmu Server installer routines...\n"; + mkdir('logs'); + mkdir('updates_staged'); + mkdir('shared'); + + do_install_config_xml(); + read_eqemu_config_xml(); + + get_installation_variables(); + + $db_name = "peq"; + if($installation_variables{"mysql_eqemu_db_name"}){ + $db_name = $installation_variables{"mysql_eqemu_db_name"}; + } + + if($OS eq "Windows"){ + #::: Binary dll's + fetch_latest_windows_binaries(); + get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); + get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); + get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); + } + + map_files_fetch_bulk(); + opcodes_fetch(); + plugins_fetch(); + quest_files_fetch(); + lua_modules_fetch(); + + #::: Server scripts + fetch_utility_scripts(); + + #::: Database Routines + print "MariaDB :: Creating Database '" . $db_name . "'\n"; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; + if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } + if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } + $bin_db_ver = trim($db_version[1]); + check_db_version_table(); + $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + fetch_peq_db_full(); + print "\nFetching Latest Database Updates...\n"; + main_db_management(); + print "\nApplying Latest Database Updates...\n"; + main_db_management(); + + print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); + + if($OS eq "Windows"){ + check_windows_firewall_rules(); + do_windows_login_server_setup(); + } + exit; +} + +if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } +if($ARGV[0] eq "login_server_setup"){ + do_windows_login_server_setup(); + exit; +} + sub get_installation_variables{ #::: Fetch installation variables before building the config open (INSTALL_VARS, "../install_variables.txt"); @@ -261,110 +357,6 @@ sub do_install_config_xml { unlink("eqemu_config_template.xml"); } -if($ARGV[0] eq "install_peq_db"){ - - get_installation_variables(); - - $db_name = "peq"; - if($ARGV[1]){ - $db_name = $ARGV[1]; - } - elsif($installation_variables{"mysql_eqemu_db_name"}){ - $db_name = $installation_variables{"mysql_eqemu_db_name"}; - } - - $db = $db_name; - - #::: Database Routines - print "MariaDB :: Creating Database '" . $db_name . "'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); - - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); -} - -if($ARGV[0] eq "remove_duplicate_rules"){ - remove_duplicate_rule_values(); - exit; -} - -if($ARGV[0] eq "map_files_fetch_bulk"){ - map_files_fetch_bulk(); - exit; -} - -if($ARGV[0] eq "installer"){ - print "Running EQEmu Server installer routines...\n"; - mkdir('logs'); - mkdir('updates_staged'); - mkdir('shared'); - - do_install_config_xml(); - - get_installation_variables(); - - $db_name = "peq"; - if($installation_variables{"mysql_eqemu_db_name"}){ - $db_name = $installation_variables{"mysql_eqemu_db_name"}; - } - - if($OS eq "Windows"){ - #::: Binary dll's - fetch_latest_windows_binaries(); - get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); - get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); - get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); - } - - map_files_fetch_bulk(); - opcodes_fetch(); - plugins_fetch(); - quest_files_fetch(); - lua_modules_fetch(); - - #::: Server scripts - fetch_utility_scripts(); - - #::: Database Routines - print "MariaDB :: Creating Database '" . $db_name . "'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); - - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); - - if($OS eq "Windows"){ - check_windows_firewall_rules(); - do_windows_login_server_setup(); - } - exit; -} - -if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } -if($ARGV[0] eq "login_server_setup"){ - do_windows_login_server_setup(); - exit; -} - sub do_update_self{ get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "eqemu_server.pl"); die "Rerun eqemu_server.pl"; @@ -661,6 +653,22 @@ sub trim { return $string; } +sub read_eqemu_config_xml { + my $confile = "eqemu_config.xml"; #default + open(F, "<$confile"); + my $indb = 0; + while() { + s/\r//g; + if(//i) { $indb = 1; } + next unless($indb == 1); + if(/<\/database>/i) { $indb = 0; last; } + if(/(.*)<\/host>/i) { $host = $1; } + elsif(/(.*)<\/username>/i) { $user = $1; } + elsif(/(.*)<\/password>/i) { $pass = $1; } + elsif(/(.*)<\/db>/i) { $db = $1; } + } +} + #::: Fetch Latest PEQ AA's sub aa_fetch{ if(!$db){ @@ -735,16 +743,16 @@ sub copy_file { $l_source_file = $_[0]; $l_destination_file = $_[1]; if($l_destination_file=~/\//i){ - my @dir_path = split('/', $l_destination_file); + my @directory_path = split('/', $l_destination_file); $build_path = ""; $directory_index = 0; - while($directory_indexr_path[$directory_index]){ - $build_path .= $directory_indexr_path[$directory_index] . "/"; + while($directory_path[$directory_index]){ + $build_path .= $directory_path[$directory_index] . "/"; #::: If path does not exist, create the directory... if (!-d $build_path) { mkdir($build_path); } - if(!$directory_indexr_path[$directory_index + 2] && $directory_indexr_path[$directory_index + 1]){ + if(!$directory_path[$directory_index + 2] && $directory_path[$directory_index + 1]){ # print $actual_path . "\n"; $actual_path = $build_path; last; @@ -833,6 +841,42 @@ sub do_windows_login_server_setup { print "\nPress any key to continue...\n"; + <>; #Read from STDIN + +} + +sub do_linux_login_server_setup { + print "\n --- Fetching Loginserver... --- \n"; + get_remote_file($install_repository_request_url . "login_server.zip", "updates_staged/login_server.zip", 1); + print "\n --- Extracting... --- \n"; + unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); + my @files; + my $start_dir = "updates_staged/login_server"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + $destination_file = $file; + $destination_file =~s/updates_staged\/login_server\///g; + print "Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); + } + print "\n Done... \n"; + + print "Pulling down Loginserver database tables...\n"; + get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); + print "\n\nInstalling Loginserver tables...\n"; + print get_mysql_result_from_file("db_update/login_server_tables.sql"); + print "\nDone...\n\n"; + + add_login_server_firewall_rules(); + + rmtree('updates_staged'); + rmtree('db_update'); + + print "\nPress any key to continue...\n"; + <>; #Read from STDIN } From 6e1a5eac944cebb1b4ec6c0af8937f85f77788d9 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 12:17:24 -0500 Subject: [PATCH 316/693] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 53 +++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 02f101cc5..2c57e6a1a 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -218,6 +218,11 @@ if($ARGV[0] eq "map_files_fetch_bulk"){ exit; } +if($ARGV[0] eq "loginserver_install_linux"){ + do_linux_login_server_setup(); + exit; +} + if($ARGV[0] eq "installer"){ print "Running EQEmu Server installer routines...\n"; mkdir('logs'); @@ -272,6 +277,10 @@ if($ARGV[0] eq "installer"){ check_windows_firewall_rules(); do_windows_login_server_setup(); } + if($OS eq "Linux"){ + do_linux_login_server_setup(); + } + exit; } @@ -846,16 +855,7 @@ sub do_windows_login_server_setup { } sub do_linux_login_server_setup { - print "\n --- Fetching Loginserver... --- \n"; - get_remote_file($install_repository_request_url . "login_server.zip", "updates_staged/login_server.zip", 1); - print "\n --- Extracting... --- \n"; - unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); - my @files; - my $start_dir = "updates_staged/login_server"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); + for my $file (@files) { $destination_file = $file; $destination_file =~s/updates_staged\/login_server\///g; @@ -870,11 +870,39 @@ sub do_linux_login_server_setup { print get_mysql_result_from_file("db_update/login_server_tables.sql"); print "\nDone...\n\n"; - add_login_server_firewall_rules(); - rmtree('updates_staged'); rmtree('db_update'); + get_remote_file($install_repository_request_url . "linux/login.ini", "login_template.ini"); + get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes.conf"); + get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes_sod.conf"); + + get_installation_variables(); + + my $db_name = $installation_variables{"mysql_eqemu_db_name"}; + my $db_user = $installation_variables{"mysql_eqemu_user"}; + my $db_password = $installation_variables{"mysql_eqemu_password"}; + + #::: Open new config file + open (NEW_CONFIG, '>', 'login.ini'); + + #::: Iterate through template and replace variables... + open (FILE_TEMPLATE, "login_template.ini"); + while (){ + chomp; + $o = $_; + #::: Find replace variables + if($o=~/db/i){ $o = "db = " . $db_name; } + if($o=~/user/i){ $o = "user = " . $db_user; } + if($o=~/password/i){ $o = "password = " . $db_password; } + + print NEW_CONFIG $o . "\n"; + } + + close(FILE_TEMPLATE); + close(NEW_CONFIG); + unlink("login_template.ini"); + print "\nPress any key to continue...\n"; <>; #Read from STDIN @@ -1699,6 +1727,7 @@ sub print_match_debug{ print " Query Check: '" . $query_check . "'\n"; print " Result: '" . trim(get_mysql_result($query_check)) . "'\n"; } + sub print_break{ if(!$debug){ return; } print "\n==============================================\n"; From a70291f20f8ce7427d331bb6691c811cf2aefbc1 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 12:50:26 -0500 Subject: [PATCH 317/693] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 116 +++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 45 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 2c57e6a1a..78c32d436 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -26,7 +26,7 @@ $eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/ #::: Globals $time_stamp = strftime('%m-%d-%Y', gmtime()); - +$db_run_stage = 0; #::: Sets database run stage check $console_output .= " Operating System is: $Config{osname}\n"; if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } @@ -34,22 +34,7 @@ if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } #::: If current version is less than what world is reporting, then download a new one... $current_version = 14; -if($ARGV[0] eq "V"){ - if($ARGV[1] > $current_version){ - print "[Update] eqemu_server.pl Automatic Database Upgrade Needs updating...\n"; - print "[Update] Current version: " . $current_version . "\n"; - print "[Update] New version: " . $ARGV[1] . "\n"; - get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "eqemu_server.pl"); - exit; - } - else{ - print "[Update] No script update necessary \n"; - } - exit; -} - -#::: Sets database run stage check -$db_run_stage = 0; +do_self_update_check_routine(); $perl_version = $^V; $perl_version =~s/v//g; @@ -290,6 +275,46 @@ if($ARGV[0] eq "login_server_setup"){ exit; } +sub do_self_update_check_routine { + #::: Check Version passed from world to update script + if($ARGV[0] eq "V") { + get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1); + + if(-e "updates_staged/eqemu_server.pl") { + + my $remote_script_size = -s "updates_staged/eqemu_server.pl"; + my $local_script_size = -s "eqemu_server.pl"; + + if($remote_script_size != $local_script_size){ + print "[Update] Script has been updated, updating...\n"; + + my @files; + my $start_dir = "updates_staged/"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + if($file=~/eqemu_server/i){ + $destination_file = $file; + $destination_file =~s/updates_staged\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); + } + } + print "[Install] Done\n"; + } + else { + print "[Update] No script update necessary...\n"; + } + + unlink("updates_staged/eqemu_server.pl"); + } + + exit; + } +} + sub get_installation_variables{ #::: Fetch installation variables before building the config open (INSTALL_VARS, "../install_variables.txt"); @@ -366,11 +391,6 @@ sub do_install_config_xml { unlink("eqemu_config_template.xml"); } -sub do_update_self{ - get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "eqemu_server.pl"); - die "Rerun eqemu_server.pl"; -} - sub fetch_utility_scripts { if($OS eq "Windows"){ get_remote_file($install_repository_request_url . "t_database_backup.bat", "t_database_backup.bat"); @@ -451,7 +471,6 @@ sub show_menu_prompt { elsif($input eq "check_db_updates"){ main_db_management(); $dc = 1; } elsif($input eq "check_bot_db_updates"){ bots_db_management(); $dc = 1; } elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; } - elsif($input eq "update_script"){ do_update_self(); $dc = 1; } elsif($input eq "exit"){ exit; } @@ -489,7 +508,6 @@ sub print_main_menu { print "====================================================\n"; print " database Enter database management menu \n"; print " server_assets Manage server assets \n"; - print " update_script Updates this management script \n"; print " exit \n"; print "\n"; } @@ -573,9 +591,9 @@ sub get_remote_file{ my $request_url = $_[0]; my $destination_file = $_[1]; my $content_type = $_[2]; + my $no_retry = $_[3]; #::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary - # print "destination file is " . $destination_file . "\n"; if($destination_file=~/\//i){ my @directory_path = split('/', $destination_file); @@ -614,9 +632,13 @@ sub get_remote_file{ #::: Make sure the file exists before continuing... if(-e $destination_file) { $break = 1; - print " Saved: (" . $destination_file . ") from " . $request_url . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n"; } else { $break = 0; } usleep(500); + + if($no_retry){ + $break = 1; + } } } else{ @@ -633,21 +655,25 @@ sub get_remote_file{ close (FILE); } else { - # print "Error, no connection or failed request...\n\n"; + print "Error, no connection or failed request...\n\n"; } if(-e $destination_file) { $break = 1; - print " Saved: (" . $destination_file . ") from " . $request_url . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n"; } else { $break = 0; } usleep(500); + + if($no_retry){ + $break = 1; + } } } } if($OS eq "Linux"){ #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt $wget = `wget --no-check-certificate --quiet -O $destination_file $request_url`; - print " Saved: (" . $destination_file . ") from " . $request_url . "\n"; - if($wget=~/unable to resolve/i){ + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n"; + if($wget=~/unable to resolve/i){ print "Error, no connection or failed request...\n\n"; #die; } @@ -687,7 +713,7 @@ sub aa_fetch{ print "Pulling down PEQ AA Tables...\n"; get_remote_file($eqemu_repository_request_url . "utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); - print "\n\nInstalling AA Tables...\n"; + print "\n\n[Install] Installing AA Tables...\n"; print get_mysql_result_from_file("db_update/peq_aa_tables_post_rework.sql"); print "\nDone...\n\n"; } @@ -787,7 +813,7 @@ sub fetch_latest_windows_binaries { for my $file (@files) { $destination_file = $file; $destination_file =~s/updates_staged\/binaries\///g; - print "Installing :: " . $destination_file . "\n"; + print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, $destination_file); } print "\n --- Done... --- \n"; @@ -810,7 +836,7 @@ sub fetch_latest_windows_binaries_bots { for my $file (@files) { $destination_file = $file; $destination_file =~s/updates_staged\/binaries\///g; - print "Installing :: " . $destination_file . "\n"; + print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, $destination_file); } print "\n --- Done... --- \n"; @@ -832,14 +858,14 @@ sub do_windows_login_server_setup { for my $file (@files) { $destination_file = $file; $destination_file =~s/updates_staged\/login_server\///g; - print "Installing :: " . $destination_file . "\n"; + print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, $destination_file); } print "\n Done... \n"; print "Pulling down Loginserver database tables...\n"; get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); - print "\n\nInstalling Loginserver tables...\n"; + print "\n\n[Install] Installing Loginserver tables...\n"; print get_mysql_result_from_file("db_update/login_server_tables.sql"); print "\nDone...\n\n"; @@ -859,14 +885,14 @@ sub do_linux_login_server_setup { for my $file (@files) { $destination_file = $file; $destination_file =~s/updates_staged\/login_server\///g; - print "Installing :: " . $destination_file . "\n"; + print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, $destination_file); } print "\n Done... \n"; print "Pulling down Loginserver database tables...\n"; get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); - print "\n\nInstalling Loginserver tables...\n"; + print "\n\n[Install] Installing Loginserver tables...\n"; print get_mysql_result_from_file("db_update/login_server_tables.sql"); print "\nDone...\n\n"; @@ -1023,7 +1049,7 @@ sub fetch_peq_db_full{ get_mysql_result_from_file($file); } if($file=~/eqtime/i){ - print "Installing eqtime.cfg\n"; + print "[Install] Installing eqtime.cfg\n"; copy_file($file, "eqtime.cfg"); } } @@ -1042,7 +1068,7 @@ sub map_files_fetch_bulk{ for my $file (@files) { $destination_file = $file; $destination_file =~s/maps\/EQEmuMaps-master\/maps\///g; - print "Installing :: " . $destination_file . "\n"; + print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, "maps/" . $new_file); } print "\n --- Fetched Latest Maps... --- \n"; @@ -1113,7 +1139,7 @@ sub quest_files_fetch{ if (!-e $destination_file) { copy_file($staged_file, $destination_file); - print "Installing :: '" . $destination_file . "'\n"; + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ @@ -1131,7 +1157,7 @@ sub quest_files_fetch{ copy_file($destination_file, $backup_dest); #::: Copy staged to running copy($staged_file, $destination_file); - print "Installing :: '" . $destination_file . "'\n\n"; + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -1172,7 +1198,7 @@ sub lua_modules_fetch{ if (!-e $destination_file) { copy_file($staged_file, $destination_file); - print "Installing :: '" . $destination_file . "'\n"; + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ @@ -1189,7 +1215,7 @@ sub lua_modules_fetch{ copy_file($destination_file, $backup_dest); #::: Copy staged to running copy($staged_file, $destination_file); - print "Installing :: '" . $destination_file . "'\n\n"; + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -1228,7 +1254,7 @@ sub plugins_fetch{ if (!-e $destination_file) { copy_file($staged_file, $destination_file); - print "Installing :: '" . $destination_file . "'\n"; + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ @@ -1245,7 +1271,7 @@ sub plugins_fetch{ copy_file($destination_file, $backup_dest); #::: Copy staged to running copy($staged_file, $destination_file); - print "Installing :: '" . $destination_file . "'\n\n"; + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } From 24856b6a2de3d78ae62deb8e5af39c8112fcc977 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 12:56:30 -0500 Subject: [PATCH 318/693] Update eqemu_server.pl [skip ci] Testing self update --- utils/scripts/eqemu_server.pl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 78c32d436..ef36f1752 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -20,7 +20,6 @@ use File::Find; use Time::HiRes qw(usleep); #::: Variables - $install_repository_request_url = "https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/"; $eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/master/"; @@ -31,9 +30,7 @@ $console_output .= " Operating System is: $Config{osname}\n"; if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } -#::: If current version is less than what world is reporting, then download a new one... -$current_version = 14; - +#::: Check for script self update do_self_update_check_routine(); $perl_version = $^V; @@ -70,7 +67,7 @@ if($OS eq "Windows"){ if($OS eq "Linux"){ $path = `which mysql`; if ($path eq "") { - $path = `which mariadb`; + $path = `which mariadb`; } $path =~s/\n//g; @@ -299,7 +296,8 @@ sub do_self_update_check_routine { $destination_file = $file; $destination_file =~s/updates_staged\///g; print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); + unlink($destination_file); + copy_file($file, $destination_file); } } print "[Install] Done\n"; From 75694e87972375aaa443067aa3ac8ef679fecf52 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 13:00:57 -0500 Subject: [PATCH 319/693] Update eqemu_server.pl [skip ci] Testing self update --- utils/scripts/eqemu_server.pl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index ef36f1752..644dc511d 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -292,12 +292,16 @@ sub do_self_update_check_routine { $start_dir ); for my $file (@files) { - if($file=~/eqemu_server/i){ + if($file=~/eqemu_server/i){ $destination_file = $file; $destination_file =~s/updates_staged\///g; print "[Install] Installing :: " . $destination_file . "\n"; unlink($destination_file); copy_file($file, $destination_file); + if($OS eq "Linux"){ + system("chmod 755 eqemu_server.pl"); + system("chown eqemu eqemu_server.pl"); + } } } print "[Install] Done\n"; From 69913c0897e0c2fb2f476876c174b58ff1584ff8 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 15:01:59 -0500 Subject: [PATCH 320/693] Update eqemu_server.pl [skip ci] - More cleanup --- utils/scripts/eqemu_server.pl | 126 ++++++++++++++++------------------ 1 file changed, 60 insertions(+), 66 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 644dc511d..e01e153b8 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -10,8 +10,6 @@ #::: Purpose: To upgrade databases with ease and maintain versioning ########################################################### -$menu_displayed = 0; - use Config; use File::Copy qw(copy); use POSIX qw(strftime); @@ -33,6 +31,7 @@ if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } #::: Check for script self update do_self_update_check_routine(); +#::: Check Perl version $perl_version = $^V; $perl_version =~s/v//g; print "[Update] Perl Version is " . $perl_version . "\n"; @@ -45,8 +44,6 @@ no warnings; read_eqemu_config_xml(); -$console_output = "[Update] EQEmu: Automatic Database Upgrade Check\n"; - if($OS eq "Windows"){ $has_mysql_path = `echo %PATH%`; if($has_mysql_path=~/MySQL|MariaDB/i){ @@ -58,8 +55,6 @@ if($OS eq "Windows"){ last; } } - $console_output .= "[Update] (Windows) MySQL is in system path \n"; - $console_output .= "[Update] Path = " . $path . "\n"; } } @@ -70,15 +65,11 @@ if($OS eq "Linux"){ $path = `which mariadb`; } $path =~s/\n//g; - - $console_output .= "[Update] (Linux) MySQL is in system path \n"; - $console_output .= "[Update] Path = " . $path . "\n"; } #::: Path not found, error and exit if($path eq ""){ - print "MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; - print "script_exiting...\n"; + print "[Error:eqemu_server.pl] MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; exit; } @@ -138,6 +129,7 @@ else { } if($db){ + print "[Update] MySQL Path/Location: " . $path . "\n"; print "[Update] Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; #::: Bots @@ -149,15 +141,13 @@ if($db){ } } - #::: If World ran this script, and our version is up to date, continue... + #::: If World ran this script, and our version is up to date, continue... if($bin_db_ver <= $local_db_ver && $ARGV[0] eq "ran_from_world"){ print "[Update] Database up to Date: Continuing World Bootup...\n"; exit; } - } - if($ARGV[0] eq "install_peq_db"){ get_installation_variables(); @@ -301,6 +291,7 @@ sub do_self_update_check_routine { if($OS eq "Linux"){ system("chmod 755 eqemu_server.pl"); system("chown eqemu eqemu_server.pl"); + system("perl eqemu_server.pl"); } } } @@ -459,6 +450,7 @@ sub show_menu_prompt { elsif($input eq "backup_database"){ database_dump(); $dc = 1; } elsif($input eq "backup_player_tables"){ database_dump_player_tables(); $dc = 1; } elsif($input eq "backup_database_compressed"){ database_dump_compress(); $dc = 1; } + elsif($input eq "drop_bots_db_schema"){ do_bots_db_schema_drop(); $dc = 1; } elsif($input eq "aa_tables"){ aa_fetch(); $dc = 1; } elsif($input eq "remove_duplicate_rules"){ remove_duplicate_rule_values(); $dc = 1; } elsif($input eq "maps"){ map_files_fetch_bulk(); $dc = 1; } @@ -713,16 +705,16 @@ sub aa_fetch{ return; } - print "Pulling down PEQ AA Tables...\n"; + print "[Install] Pulling down PEQ AA Tables...\n"; get_remote_file($eqemu_repository_request_url . "utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); - print "\n\n[Install] Installing AA Tables...\n"; + print "[Install] Installing AA Tables...\n"; print get_mysql_result_from_file("db_update/peq_aa_tables_post_rework.sql"); - print "\nDone...\n\n"; + print "[Install] Done...\n\n"; } #::: Fetch Latest Opcodes sub opcodes_fetch{ - print "Pulling down latest opcodes...\n"; + print "[Update] Pulling down latest opcodes...\n"; %opcodes = ( 1 => ["opcodes", $eqemu_repository_request_url . "utils/patches/opcodes.conf"], 2 => ["mail_opcodes", $eqemu_repository_request_url . "utils/patches/mail_opcodes.conf"], @@ -746,14 +738,15 @@ sub opcodes_fetch{ get_remote_file($opcodes{$loop}[1], $file_name); $loop++; } - print "\nDone...\n\n"; + print "[Update] Done...\n"; } sub remove_duplicate_rule_values { $ruleset_id = trim(get_mysql_result("SELECT `ruleset_id` FROM `rule_sets` WHERE `name` = 'default'")); - print "Default Ruleset ID: " . $ruleset_id . "\n"; + print "[Database] Default Ruleset ID: " . $ruleset_id . "\n"; $total_removed = 0; + #::: Store Default values... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` = " . $ruleset_id); my @lines = split("\n", $mysql_result); @@ -761,19 +754,20 @@ sub remove_duplicate_rule_values { my @values = split("\t", $val); $rule_set_values{$values[1]}[0] = $values[2]; } + #::: Compare default values against other rulesets to check for duplicates... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` != " . $ruleset_id); my @lines = split("\n", $mysql_result); foreach my $val (@lines){ my @values = split("\t", $val); if($values[2] == $rule_set_values{$values[1]}[0]){ - print "DUPLICATE : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . ", removing...\n"; + print "[Database] Removing duplicate : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . "\n"; get_mysql_result("DELETE FROM `rule_values` WHERE `ruleset_id` = " . $values[0] . " AND `rule_name` = '" . $values[1] . "'"); $total_removed++; } } - print "Total duplicate rules removed... " . $total_removed . "\n"; + print "[Database] Total duplicate rules removed... " . $total_removed . "\n"; } sub copy_file { @@ -801,10 +795,10 @@ sub copy_file { } sub fetch_latest_windows_binaries { - print "\n --- Fetching Latest Windows Binaries... --- \n"; + print "[Update] Fetching Latest Windows Binaries... \n"; get_remote_file($install_repository_request_url . "master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); - print "\n --- Fetched Latest Windows Binaries... --- \n"; - print "\n --- Extracting... --- \n"; + print "[Update] Fetched Latest Windows Binaries... \n"; + print "[Update] Extracting... --- \n"; unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; @@ -815,19 +809,19 @@ sub fetch_latest_windows_binaries { for my $file (@files) { $destination_file = $file; $destination_file =~s/updates_staged\/binaries\///g; - print "[Install] Installing :: " . $destination_file . "\n"; + print "[Update] Installing :: " . $destination_file . "\n"; copy_file($file, $destination_file); } - print "\n --- Done... --- \n"; + print "[Update] Done\n"; rmtree('updates_staged'); } sub fetch_latest_windows_binaries_bots { - print "\n --- Fetching Latest Windows Binaries with Bots... --- \n"; + print "[Update] Fetching Latest Windows Binaries with Bots...\n"; get_remote_file($install_repository_request_url . "master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); - print "\n --- Fetched Latest Windows Binaries with Bots... --- \n"; - print "\n --- Extracting... --- \n"; + print "[Update] Fetched Latest Windows Binaries with Bots...\n"; + print "[Update] Extracting...\n"; unzip('updates_staged/master_windows_build_bots.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; @@ -841,15 +835,15 @@ sub fetch_latest_windows_binaries_bots { print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, $destination_file); } - print "\n --- Done... --- \n"; + print "[Update] Done...\n"; rmtree('updates_staged'); } sub do_windows_login_server_setup { - print "\n --- Fetching Loginserver... --- \n"; + print "[Install] Fetching Loginserver... \n"; get_remote_file($install_repository_request_url . "login_server.zip", "updates_staged/login_server.zip", 1); - print "\n --- Extracting... --- \n"; + print "[Install] Extracting... \n"; unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); my @files; my $start_dir = "updates_staged/login_server"; @@ -863,20 +857,20 @@ sub do_windows_login_server_setup { print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, $destination_file); } - print "\n Done... \n"; + print "[Install] Done... \n"; - print "Pulling down Loginserver database tables...\n"; + print "[Install] Pulling down Loginserver database tables...\n"; get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); - print "\n\n[Install] Installing Loginserver tables...\n"; + print "[Install] Installing Loginserver tables...\n"; print get_mysql_result_from_file("db_update/login_server_tables.sql"); - print "\nDone...\n\n"; + print "[Install] Done...\n"; add_login_server_firewall_rules(); rmtree('updates_staged'); rmtree('db_update'); - print "\nPress any key to continue...\n"; + print "[Install] Press any key to continue...\n"; <>; #Read from STDIN @@ -892,9 +886,9 @@ sub do_linux_login_server_setup { } print "\n Done... \n"; - print "Pulling down Loginserver database tables...\n"; + print "[Install] Pulling down Loginserver database tables...\n"; get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); - print "\n\n[Install] Installing Loginserver tables...\n"; + print "[Install] Installing Loginserver tables...\n"; print get_mysql_result_from_file("db_update/login_server_tables.sql"); print "\nDone...\n\n"; @@ -906,7 +900,6 @@ sub do_linux_login_server_setup { get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes_sod.conf"); get_installation_variables(); - my $db_name = $installation_variables{"mysql_eqemu_db_name"}; my $db_user = $installation_variables{"mysql_eqemu_user"}; my $db_password = $installation_variables{"mysql_eqemu_password"}; @@ -931,7 +924,7 @@ sub do_linux_login_server_setup { close(NEW_CONFIG); unlink("login_template.ini"); - print "\nPress any key to continue...\n"; + print "[Install] Press any key to continue...\n"; <>; #Read from STDIN @@ -1034,9 +1027,9 @@ sub fetch_server_dlls{ } sub fetch_peq_db_full{ - print "Downloading latest PEQ Database... Please wait...\n"; + print "[Install] Downloading latest PEQ Database... Please wait...\n"; get_remote_file("http://edit.peqtgc.com/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1); - print "Downloaded latest PEQ Database... Extracting...\n"; + print "[Install] Downloaded latest PEQ Database... Extracting...\n"; unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); my $start_dir = "updates_staged/peq_db"; find( @@ -1047,7 +1040,7 @@ sub fetch_peq_db_full{ $destination_file = $file; $destination_file =~s/updates_staged\/peq_db\///g; if($file=~/peqbeta|player_tables/i){ - print "MariaDB :: Installing :: maps/" . $destination_file . "\n"; + print "[Install] DB :: Installing :: " . $destination_file . "\n"; get_mysql_result_from_file($file); } if($file=~/eqtime/i){ @@ -1058,7 +1051,7 @@ sub fetch_peq_db_full{ } sub map_files_fetch_bulk{ - print "\n --- Fetching Latest Maps... (This could take a few minutes...) --- \n"; + print "[Install] Fetching Latest Maps... (This could take a few minutes...)\n"; get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1); unzip('maps/maps.zip', 'maps/'); my @files; @@ -1073,7 +1066,7 @@ sub map_files_fetch_bulk{ print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, "maps/" . $new_file); } - print "\n --- Fetched Latest Maps... --- \n"; + print "[Install] Fetched Latest Maps\n"; rmtree('maps/EQEmuMaps-master'); unlink('maps/maps.zip'); @@ -1332,11 +1325,11 @@ sub are_file_sizes_different{ sub do_bots_db_schema_drop{ #"drop_bots.sql" is run before reverting database back to 'normal' - print "Fetching drop_bots.sql...\n"; + print "[Database] Fetching drop_bots.sql...\n"; get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); print get_mysql_result_from_file("db_update/drop_bots.sql"); - print "Restoring normality...\n"; + print "[Database] Removing bot database tables...\n"; print get_mysql_result("DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots:%';"); if(get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && $db){ @@ -1362,11 +1355,12 @@ sub do_bots_db_schema_drop{ if(get_mysql_result("SHOW COLUMNS FROM `db_version` LIKE 'bots_version'") ne "" && $db){ print get_mysql_result("UPDATE `db_version` SET `bots_version` = 0;"); } + print "[Database] Done...\n"; } sub modify_db_for_bots{ #Called after the db bots schema (2015_09_30_bots.sql) has been loaded - print "Modifying database for bots...\n"; + print "[Database] Modifying database for bots...\n"; print get_mysql_result("UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298);"); if(get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ @@ -1447,7 +1441,7 @@ sub modify_db_for_bots{ sub convert_existing_bot_data{ if(get_mysql_result("SHOW TABLES LIKE 'bots'") ne "" && $db){ - print "Converting existing bot data...\n"; + print "[Database] Converting existing bot data...\n"; print get_mysql_result("INSERT INTO `bot_data` (`bot_id`, `owner_id`, `spells_id`, `name`, `last_name`, `zone_id`, `gender`, `race`, `class`, `level`, `creation_day`, `last_spawn`, `time_spawned`, `size`, `face`, `hair_color`, `hair_style`, `beard`, `beard_color`, `eye_color_1`, `eye_color_2`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `ac`, `atk`, `hp`, `mana`, `str`, `sta`, `cha`, `dex`, `int`, `agi`, `wis`, `fire`, `cold`, `magic`, `poison`, `disease`, `corruption`) SELECT `BotID`, `BotOwnerCharacterID`, `BotSpellsID`, `Name`, `LastName`, `LastZoneId`, `Gender`, `Race`, `Class`, `BotLevel`, UNIX_TIMESTAMP(`BotCreateDate`), UNIX_TIMESTAMP(`LastSpawnDate`), `TotalPlayTime`, `Size`, `Face`, `LuclinHairColor`, `LuclinHairStyle`, `LuclinBeard`, `LuclinBeardColor`, `LuclinEyeColor`, `LuclinEyeColor2`, `DrakkinHeritage`, `DrakkinTattoo`, `DrakkinDetails`, `AC`, `ATK`, `HP`, `Mana`, `STR`, `STA`, `CHA`, `DEX`, `_INT`, `AGI`, `WIS`, `FR`, `CR`, `MR`, `PR`, `DR`, `Corrup` FROM `bots`;"); print get_mysql_result("INSERT INTO `bot_inspect_messages` (`bot_id`, `inspect_message`) SELECT `BotID`, `BotInspectMessage` FROM `bots`;"); @@ -1606,12 +1600,12 @@ sub run_database_check{ if(!@total_updates){ #::: Pull down bots database manifest if($bots_db_management == 1){ - print "Retrieving latest bots database manifest...\n"; + print "[Database] Retrieving latest bots database manifest...\n"; get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); } #::: Pull down mainstream database manifest else{ - print "Retrieving latest database manifest...\n"; + print "[Database] Retrieving latest database manifest...\n"; get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); } } @@ -1621,7 +1615,7 @@ sub run_database_check{ @total_updates = sort @total_updates; foreach my $val (@total_updates){ $file_name = trim($m_d{$val}[1]); - print "Running Update: " . $val . " - " . $file_name . "\n"; + print "[Database] Running Update: " . $val . " - " . $file_name . "\n"; print get_mysql_result_from_file("db_update/$file_name"); print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val"); @@ -1633,7 +1627,7 @@ sub run_database_check{ } #::: Run 1 - Initial checking of needed updates... else{ - print "Reading manifest...\n\n"; + print "[Database] Reading manifest...\n"; use Data::Dumper; open (FILE, "db_update/db_update_manifest.txt"); while () { @@ -1667,23 +1661,23 @@ sub run_database_check{ #::: Match type update if($match_type eq "contains"){ if(trim(get_mysql_result($query_check))=~/$match_text/i){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "missing"){ if(get_mysql_result($query_check)=~/$match_text/i){ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; next; } else{ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } @@ -1692,24 +1686,24 @@ sub run_database_check{ } if($match_type eq "empty"){ if(get_mysql_result($query_check) eq ""){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "not_empty"){ if(get_mysql_result($query_check) ne ""){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); @@ -1718,13 +1712,13 @@ sub run_database_check{ print "\n"; if(scalar (@total_updates) == 0 && $db_run_stage == 2){ - print "No updates need to be run...\n"; + print "[Database] No updates need to be run...\n"; if($bots_db_management == 1){ - print "Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; + print "[Database] Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; get_mysql_result("UPDATE db_version SET bots_version = $bin_db_ver"); } else{ - print "Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; + print "[Database] Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; get_mysql_result("UPDATE db_version SET version = $bin_db_ver"); } From f99523dc4898b82118bfe7fbd2771505301540cc Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 16:32:21 -0500 Subject: [PATCH 321/693] Migration to new EQEmu Server management script interface --- common/database_conversions.cpp | 23 +--- utils/scripts/eqemu_server.pl | 226 ++++++++++++++------------------ 2 files changed, 106 insertions(+), 143 deletions(-) diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index f6fd6c04a..aad81cb7b 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -472,31 +472,18 @@ bool Database::CheckDatabaseConversions() { CheckDatabaseConvertPPDeblob(); CheckDatabaseConvertCorpseDeblob(); - /* Fetch Automatic Upgrade Script */ + /* Fetch EQEmu Server script */ if (!std::ifstream("eqemu_update.pl")){ std::cout << "Pulling down automatic database upgrade script..." << std::endl; #ifdef _WIN32 - system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl'); if ($response->is_success){ open(FILE, '> eqemu_update.pl'); print FILE $response->decoded_content; close(FILE); }\""); + system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl'); if ($response->is_success){ open(FILE, '> eqemu_update.pl'); print FILE $response->decoded_content; close(FILE); }\""); #else - system("wget --no-check-certificate -O eqemu_update.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl"); + system("wget --no-check-certificate -O eqemu_update.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl"); #endif } - /* - Automatic (Database) Upgrade Script - Script: eqemu_update.pl V 1 - the number that world passes to the script will - force the script to check for a newer version to update itself with - eqemu_update.pl ran_from_world - won't bring up a menu if your database versions match - eqemu_update.pl - ran standalone will bring up a menu prompt - */ - - /* Check for a new version of this script, the arg passed - would have to be higher than the copy they have downloaded - locally and they will re fetch */ - system("perl eqemu_update.pl V 14"); - - /* Run Automatic Database Upgrade Script */ - system("perl eqemu_update.pl ran_from_world"); + /* Run EQEmu Server script (Checks for database updates) */ + system("perl eqemu_server.pl ran_from_world"); return true; } diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index e01e153b8..b128a854c 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -40,6 +40,11 @@ if($perl_version > 5.12){ } no warnings; +#::: Remove old eqemu_update.pl +if(-e "eqemu_update.pl"){ + unlink("eqemu_update.pl"); +} + ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); read_eqemu_config_xml(); @@ -148,38 +153,6 @@ if($db){ } } -if($ARGV[0] eq "install_peq_db"){ - - get_installation_variables(); - - $db_name = "peq"; - if($ARGV[1]){ - $db_name = $ARGV[1]; - } - elsif($installation_variables{"mysql_eqemu_db_name"}){ - $db_name = $installation_variables{"mysql_eqemu_db_name"}; - } - - $db = $db_name; - - #::: Database Routines - print "MariaDB :: Creating Database '" . $db_name . "'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); - - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); -} - if($ARGV[0] eq "remove_duplicate_rules"){ remove_duplicate_rule_values(); exit; @@ -196,14 +169,15 @@ if($ARGV[0] eq "loginserver_install_linux"){ } if($ARGV[0] eq "installer"){ - print "Running EQEmu Server installer routines...\n"; + print "[Install] Running EQEmu Server installer routines...\n"; + + #::: Make some local server directories... mkdir('logs'); mkdir('updates_staged'); mkdir('shared'); do_install_config_xml(); read_eqemu_config_xml(); - get_installation_variables(); $db_name = "peq"; @@ -211,39 +185,40 @@ if($ARGV[0] eq "installer"){ $db_name = $installation_variables{"mysql_eqemu_db_name"}; } + #::: Download assets if($OS eq "Windows"){ - #::: Binary dll's fetch_latest_windows_binaries(); get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); } - map_files_fetch_bulk(); opcodes_fetch(); plugins_fetch(); quest_files_fetch(); lua_modules_fetch(); - - #::: Server scripts fetch_utility_scripts(); #::: Database Routines - print "MariaDB :: Creating Database '" . $db_name . "'\n"; + print "[Database] Creating Database '" . $db_name . "'\n"; print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; + + #::: Get Binary DB version if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } $bin_db_ver = trim($db_version[1]); + + #::: Local DB Version check_db_version_table(); $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); + #::: Download PEQ latest + fetch_peq_db_full(); + print "[Database] Fetching Latest Database Updates...\n"; + main_db_management(); + print "[Database] Applying Latest Database Updates...\n"; + main_db_management(); if($OS eq "Windows"){ check_windows_firewall_rules(); @@ -251,6 +226,8 @@ if($ARGV[0] eq "installer"){ } if($OS eq "Linux"){ do_linux_login_server_setup(); + + print "[Install] Installation complete!\n"; } exit; @@ -264,7 +241,7 @@ if($ARGV[0] eq "login_server_setup"){ sub do_self_update_check_routine { #::: Check Version passed from world to update script - if($ARGV[0] eq "V") { + if($ARGV[0] eq "ran_from_world") { get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1); if(-e "updates_staged/eqemu_server.pl") { @@ -412,31 +389,30 @@ sub show_menu_prompt { $errored_command = 0; if($input eq "database"){ - print "====================================================\n"; - print "Database Menu:\n-------------\n"; - print " backup_database Back up database to backups/ directory\n"; - print " backup_player_tables Back up player tables to backups/ directory\n"; - print " backup_database_compressed Back up database compressed to backups/ directory\n"; - print " - \n"; - print " check_db_updates Checks for database updates manually\n"; - print " check_bot_db_updates Checks for bot database updates\n"; - print " - \n"; - print " aa_tables Downloads and installs clean slate AA data from PEQ\n"; - print " remove_duplicate_rules Removes duplicate rules from rule_values table\n"; - print " drop_bots_db_schema Removes bot database schema\n"; + print "\n>>> Database Menu\n\n"; + print " [backup_database] Back up database to backups/ directory\n"; + print " [backup_player_tables] Back up player tables to backups/ directory\n"; + print " [backup_database_compressed] Back up database compressed to backups/ directory\n"; + print " \n"; + print " [check_db_updates] Checks for database updates manually\n"; + print " [check_bot_db_updates] Checks for bot database updates\n"; + print " \n"; + print " [aa_tables] Downloads and installs clean slate AA data from PEQ\n"; + print " [remove_duplicate_rules] Removes duplicate rules from rule_values table\n"; + print " [drop_bots_db_schema] Removes bot database schema\n"; - print " \nmain - go back to main menu\n"; + print " \n> main - go back to main menu\n"; + print "Enter a command #> "; $last_menu = trim($input); } - elsif($input eq "server_assets"){ - print "====================================================\n"; - print "Server Assets Menu:\n"; - print " maps Download latest maps\n"; - print " opcodes Download opcodes (Patches for eq clients)\n"; - print " quests Download latest quests\n"; - print " plugins Download latest plugins\n"; - print " lua_modules Download latest lua_modules\n"; - print " utility_scripts Download utility scripts to run and operate the EQEmu Server\n"; + elsif($input eq "assets"){ + print "\n>>> Server Assets Menu\n\n"; + print " [maps] Download latest maps\n"; + print " [opcodes] Download opcodes (Patches for eq clients)\n"; + print " [quests] Download latest quests\n"; + print " [plugins] Download latest plugins\n"; + print " [lua_modules] Download latest lua_modules\n"; + print " [utility_scripts] Download utility scripts to run and operate the EQEmu Server\n"; if($OS eq "Windows"){ print "--- Windows\n"; print " windows_server_download Updates server code from latest stable\n"; @@ -444,7 +420,8 @@ sub show_menu_prompt { print " fetch_dlls Grabs dll's needed to run windows binaries\n"; print " setup_loginserver Sets up loginserver for Windows\n"; } - print " \nmain - go back to main menu\n"; + print " \n> main - go back to main menu\n"; + print "Enter a command #> "; $last_menu = trim($input); } elsif($input eq "backup_database"){ database_dump(); $dc = 1; } @@ -488,22 +465,25 @@ sub show_menu_prompt { if($errored_command == 1){ $input = $last_menu; } - elsif($dc == 1){ $dc = 0; $input = ""; } + elsif($dc == 1){ + $dc = 0; + $input = ""; + } else { $input = <>; } - } } sub print_main_menu { - print "====================================================\n"; - print "#::: EQEmu Server Tool Menu\n"; - print "====================================================\n"; - print " database Enter database management menu \n"; - print " server_assets Manage server assets \n"; + print "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"; + print ">>> EQEmu Server Main Menu >>>>>>>>>>>>\n"; + print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"; + print " [database] Enter database management menu \n"; + print " [assets] Manage server assets \n\n"; print " exit \n"; print "\n"; + print "Enter a command #> "; } sub check_for_database_dump_script{ @@ -511,24 +491,20 @@ sub check_for_database_dump_script{ return; } else{ - print "db_dumper.pl not found... retrieving...\n\n"; + print "[Database] db_dumper.pl not found... retrieving...\n"; get_remote_file($eqemu_repository_request_url . "utils/scripts/db_dumper.pl", "db_dumper.pl"); } } -sub ran_from_world { - print "Running from world...\n"; -} - sub database_dump { check_for_database_dump_script(); - print "Performing database backup....\n"; + print "[Database] Performing database backup....\n"; print `perl db_dumper.pl database="$db" loc="backups"`; } sub database_dump_player_tables { check_for_database_dump_script(); - print "Performing database backup of player tables....\n"; + print "[Database] Performing database backup of player tables....\n"; get_remote_file($eqemu_repository_request_url . "utils/sql/character_table_list.txt", "backups/character_table_list.txt"); $tables = ""; @@ -543,7 +519,7 @@ sub database_dump_player_tables { print `perl db_dumper.pl database="$db" loc="backups" tables="$tables" backup_name="player_tables_export" nolock`; - print "\nPress any key to continue...\n"; + print "[Database] Press any key to continue...\n"; <>; #Read from STDIN @@ -551,7 +527,7 @@ sub database_dump_player_tables { sub database_dump_compress { check_for_database_dump_script(); - print "Performing database backup....\n"; + print "[Database] Performing database backup....\n"; print `perl db_dumper.pl database="$db" loc="backups" compress`; } @@ -598,7 +574,7 @@ sub get_remote_file{ # print "checking '" . $build_path . "'\n"; #::: If path does not exist, create the directory... if (!-d $build_path) { - print "folder doesn't exist, creating '" . $build_path . "'\n"; + print "[Copy] folder doesn't exist, creating '" . $build_path . "'\n"; mkdir($build_path); } if(!$directory_indexr_path[$directory_index + 2] && $directory_indexr_path[$directory_index + 1]){ @@ -620,7 +596,7 @@ sub get_remote_file{ # print "request is " . $request_url . "\n"; # print "destination file is supposed to be " . $destination_file . "\n"; if(!getstore($request_url, $destination_file)){ - print "Error, no connection or failed request...\n\n"; + print "[Download] Error, no connection or failed request...\n\n"; } # sleep(1); #::: Make sure the file exists before continuing... @@ -649,7 +625,7 @@ sub get_remote_file{ close (FILE); } else { - print "Error, no connection or failed request...\n\n"; + print "[Download] Error, no connection or failed request...\n\n"; } if(-e $destination_file) { $break = 1; @@ -890,7 +866,7 @@ sub do_linux_login_server_setup { get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); print "[Install] Installing Loginserver tables...\n"; print get_mysql_result_from_file("db_update/login_server_tables.sql"); - print "\nDone...\n\n"; + print "[Install] Done...\n\n"; rmtree('updates_staged'); rmtree('db_update'); @@ -952,22 +928,22 @@ sub add_login_server_firewall_rules { } if($has_loginserver_rules_titanium == 0){ - print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) TCP" dir=in action=allow protocol=TCP localport=5998`; - print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) UDP" dir=in action=allow protocol=UDP localport=5998`; } if($has_loginserver_rules_sod == 0){ - print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) TCP" dir=in action=allow protocol=TCP localport=5999`; - print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) UDP" dir=in action=allow protocol=UDP localport=5999`; } print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n"; print "\n"; - print "#::: Instructions \n"; - print "In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; + print "[Install] Instructions \n"; + print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; print " login.eqemulator.net @@ -982,7 +958,7 @@ sub add_login_server_firewall_rules { "; - print "\nWhen done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; + print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; } } @@ -996,31 +972,31 @@ sub check_windows_firewall_rules{ $val=~s/Rule Name://g; if($val=~/EQEmu World/i){ $has_world_rules = 1; - print "Found existing rule :: " . trim($val) . "\n"; + print "[Install] Found existing rule :: " . trim($val) . "\n"; } if($val=~/EQEmu Zone/i){ $has_zone_rules = 1; - print "Found existing rule :: " . trim($val) . "\n"; + print "[Install] Found existing rule :: " . trim($val) . "\n"; } } } if($has_world_rules == 0){ - print "Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; + print "[Install] Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; print `netsh advfirewall firewall add rule name="EQEmu World (9000) TCP" dir=in action=allow protocol=TCP localport=9000`; - print "Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; + print "[Install] Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; print `netsh advfirewall firewall add rule name="EQEmu World (9000) UDP" dir=in action=allow protocol=UDP localport=9000`; } if($has_zone_rules == 0){ - print "Attempting to add EQEmu Zones (7000-7500) TCP \n"; + print "[Install] Attempting to add EQEmu Zones (7000-7500) TCP \n"; print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) TCP" dir=in action=allow protocol=TCP localport=7000-7500`; - print "Attempting to add EQEmu Zones (7000-7500) UDP \n"; + print "[Install] Attempting to add EQEmu Zones (7000-7500) UDP \n"; print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) UDP" dir=in action=allow protocol=UDP localport=7000-7500`; } } sub fetch_server_dlls{ - print "Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; + print "[Download] Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); @@ -1073,7 +1049,7 @@ sub map_files_fetch_bulk{ } sub map_files_fetch{ - print "\n --- Fetching Latest Maps --- \n"; + print "[Install] Fetching Latest Maps --- \n"; get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt"); @@ -1096,22 +1072,22 @@ sub map_files_fetch{ my $file_existing = $maps_manifest[$m][0]; my $file_existing_size = (stat $file_existing)[7]; if($file_existing_size != $maps_manifest[$m][1]){ - print "Updating: '" . $maps_manifest[$m][0] . "'\n"; + print "[Install] Updating: '" . $maps_manifest[$m][0] . "'\n"; get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1); $fc++; } } if($fc == 0){ - print "\nNo Map Updates found... \n\n"; + print "[Install] No Map Updates found... \n\n"; } } sub quest_files_fetch{ if (!-e "updates_staged/Quests-Plugins-master/quests/") { - print "\n --- Fetching Latest Quests --- \n"; + print "[Update] Fetching Latest Quests --- \n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest quests...\n"; + print "[Install] Fetched latest quests...\n"; mkdir('updates_staged'); unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -1143,8 +1119,8 @@ sub quest_files_fetch{ $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; print $directory_indexff . "\n"; - print "\nFile Different :: '" . $destination_file . "'\n"; - print "\nDo you wish to update this Quest? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this Quest? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ @@ -1163,15 +1139,15 @@ sub quest_files_fetch{ rmtree('updates_staged'); if($fc == 0){ - print "\nNo Quest Updates found... \n\n"; + print "[Update] No Quest Updates found... \n\n"; } } -sub lua_modules_fetch{ +sub lua_modules_fetch { if (!-e "updates_staged/Quests-Plugins-master/quests/lua_modules/") { - print "\n --- Fetching Latest LUA Modules --- \n"; + print "[Update] Fetching Latest LUA Modules --- \n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest LUA Modules...\n"; + print "[Update] Fetched latest LUA Modules...\n"; unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -1201,8 +1177,8 @@ sub lua_modules_fetch{ if($directory_indexff ne ""){ $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; print $directory_indexff . "\n"; - print "\nFile Different :: '" . $destination_file . "'\n"; - print "\nDo you wish to update this LUA Module? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this LUA Module? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ @@ -1219,15 +1195,15 @@ sub lua_modules_fetch{ } if($fc == 0){ - print "\nNo LUA Modules Updates found... \n\n"; + print "[Update] No LUA Modules Updates found... \n\n"; } } sub plugins_fetch{ if (!-e "updates_staged/Quests-Plugins-master/plugins/") { - print "\n --- Fetching Latest Plugins --- \n"; + print "[Update] Fetching Latest Plugins\n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest plugins...\n"; + print "[Update] Fetched latest plugins\n"; unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -1257,8 +1233,8 @@ sub plugins_fetch{ if($directory_indexff ne ""){ $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; print $directory_indexff . "\n"; - print "\nFile Different :: '" . $destination_file . "'\n"; - print "\nDo you wish to update this Plugin? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this Plugin? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ @@ -1275,7 +1251,7 @@ sub plugins_fetch{ } if($fc == 0){ - print "\nNo Plugin Updates found... \n\n"; + print "[Update] No Plugin Updates found... \n\n"; } } @@ -1293,7 +1269,7 @@ sub do_file_diff{ } } -sub unzip{ +sub unzip { $archive_to_unzip = $_[0]; $dest_folder = $_[1]; @@ -1307,7 +1283,7 @@ sub unzip{ $zip->extractTree('', $dest_folder); } if($OS eq "Linux"){ - print `unzip -o "$archive_to_unzip" -d "$dest_folder"`; + print `unzip -o -q "$archive_to_unzip" -d "$dest_folder"`; } } @@ -1762,4 +1738,4 @@ sub generate_random_password { map $alphanumeric[rand @alphanumeric], 0..$passwordsize; return $randpassword; -} +} \ No newline at end of file From 2b2d6e1ef5a2b22f64c2e6c6f2a6c2c4f4a7ad24 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 16:33:50 -0500 Subject: [PATCH 322/693] Less fail [skip ci] --- common/database_conversions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index aad81cb7b..030430f5f 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -473,7 +473,7 @@ bool Database::CheckDatabaseConversions() { CheckDatabaseConvertCorpseDeblob(); /* Fetch EQEmu Server script */ - if (!std::ifstream("eqemu_update.pl")){ + if (!std::ifstream("eqemu_server.pl")){ std::cout << "Pulling down automatic database upgrade script..." << std::endl; #ifdef _WIN32 system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl'); if ($response->is_success){ open(FILE, '> eqemu_update.pl'); print FILE $response->decoded_content; close(FILE); }\""); From d5864aea3e9c67afa436e2688aa8f6d098c8bef2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 16:36:48 -0500 Subject: [PATCH 323/693] Few more adjustments [skip ci] --- common/database_conversions.cpp | 2 +- utils/scripts/eqemu_server.pl | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index 030430f5f..406995b34 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -476,7 +476,7 @@ bool Database::CheckDatabaseConversions() { if (!std::ifstream("eqemu_server.pl")){ std::cout << "Pulling down automatic database upgrade script..." << std::endl; #ifdef _WIN32 - system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl'); if ($response->is_success){ open(FILE, '> eqemu_update.pl'); print FILE $response->decoded_content; close(FILE); }\""); + system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl'); if ($response->is_success){ open(FILE, '> eqemu_server.pl'); print FILE $response->decoded_content; close(FILE); }\""); #else system("wget --no-check-certificate -O eqemu_update.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl"); #endif diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index b128a854c..c778846b4 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -279,9 +279,7 @@ sub do_self_update_check_routine { } unlink("updates_staged/eqemu_server.pl"); - } - - exit; + } } } From f7cc1053f16f4a90d773b0a9d26eed3bd3cd2cb4 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 16:39:35 -0500 Subject: [PATCH 324/693] eqemu_server.pl - Update regardless of run condition [skip ci] --- utils/scripts/eqemu_server.pl | 68 +++++++++++++++++------------------ 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index c778846b4..9a0f13b2a 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -237,49 +237,47 @@ if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } if($ARGV[0] eq "login_server_setup"){ do_windows_login_server_setup(); exit; -} +} sub do_self_update_check_routine { #::: Check Version passed from world to update script - if($ARGV[0] eq "ran_from_world") { - get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1); + get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1); + + if(-e "updates_staged/eqemu_server.pl") { - if(-e "updates_staged/eqemu_server.pl") { - - my $remote_script_size = -s "updates_staged/eqemu_server.pl"; - my $local_script_size = -s "eqemu_server.pl"; - - if($remote_script_size != $local_script_size){ - print "[Update] Script has been updated, updating...\n"; - - my @files; - my $start_dir = "updates_staged/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - if($file=~/eqemu_server/i){ - $destination_file = $file; - $destination_file =~s/updates_staged\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - unlink($destination_file); - copy_file($file, $destination_file); - if($OS eq "Linux"){ - system("chmod 755 eqemu_server.pl"); - system("chown eqemu eqemu_server.pl"); - system("perl eqemu_server.pl"); - } + my $remote_script_size = -s "updates_staged/eqemu_server.pl"; + my $local_script_size = -s "eqemu_server.pl"; + + if($remote_script_size != $local_script_size){ + print "[Update] Script has been updated, updating...\n"; + + my @files; + my $start_dir = "updates_staged/"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + if($file=~/eqemu_server/i){ + $destination_file = $file; + $destination_file =~s/updates_staged\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + unlink($destination_file); + copy_file($file, $destination_file); + if($OS eq "Linux"){ + system("chmod 755 eqemu_server.pl"); + system("chown eqemu eqemu_server.pl"); + system("perl eqemu_server.pl"); } } - print "[Install] Done\n"; } - else { - print "[Update] No script update necessary...\n"; - } - - unlink("updates_staged/eqemu_server.pl"); + print "[Install] Done\n"; } + else { + print "[Update] No script update necessary...\n"; + } + + unlink("updates_staged/eqemu_server.pl"); } } From 35c83db432cb1cfb6bc0dacaf03267cdd5f2fc44 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 16:43:35 -0500 Subject: [PATCH 325/693] eqemu_server.pl - Run script after self upgrade regardless of OS [skip ci] --- utils/scripts/eqemu_server.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 9a0f13b2a..944617723 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -267,8 +267,8 @@ sub do_self_update_check_routine { if($OS eq "Linux"){ system("chmod 755 eqemu_server.pl"); system("chown eqemu eqemu_server.pl"); - system("perl eqemu_server.pl"); } + system("perl eqemu_server.pl"); } } print "[Install] Done\n"; From 357a92dfeea088d0d0e5571aef0825a39ba95ef8 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 16:46:34 -0500 Subject: [PATCH 326/693] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 944617723..47955266d 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -31,6 +31,8 @@ if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } #::: Check for script self update do_self_update_check_routine(); +print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n"; + #::: Check Perl version $perl_version = $^V; $perl_version =~s/v//g; @@ -268,7 +270,7 @@ sub do_self_update_check_routine { system("chmod 755 eqemu_server.pl"); system("chown eqemu eqemu_server.pl"); } - system("perl eqemu_server.pl"); + system("perl eqemu_server.pl start_from_world"); } } print "[Install] Done\n"; From 25de25a7773b4d1374d2e39533a9108817120ca9 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 18:00:13 -0500 Subject: [PATCH 327/693] Update eqemu_server.pl - Add internet connection checks for people using EQEmu locally [skip ci] --- utils/scripts/eqemu_update.pl | 1205 +++++++++++++++++++-------------- 1 file changed, 713 insertions(+), 492 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index a7da3c792..e794a3710 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -1,74 +1,56 @@ #!/usr/bin/perl ########################################################### -#::: Automatic (Database) Upgrade Script -#::: Author: Akkadius +#::: General EQEmu Server Administration Script +#::: Purpose - Handles: +#::: Automatic database versioning (bots and normal DB) +#::: Updating server assets (binary, opcodes, maps, configuration files) +#::: Original Author: Akkadius +#::: Contributors: Uleat #::: Purpose: To upgrade databases with ease and maintain versioning ########################################################### -$menu_displayed = 0; - use Config; use File::Copy qw(copy); use POSIX qw(strftime); use File::Path; use File::Find; -use URI::Escape; -use Time::HiRes qw(usleep); +use Time::HiRes qw(usleep); +#::: Variables +$install_repository_request_url = "https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/"; +$eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/master/"; + +#::: Globals $time_stamp = strftime('%m-%d-%Y', gmtime()); - +$db_run_stage = 0; #::: Sets database run stage check $console_output .= " Operating System is: $Config{osname}\n"; if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } +$has_internet_connection = check_internet_connection(); -#::: If current version is less than what world is reporting, then download a new one... -$current_version = 14; +#::: Check for script self update +do_self_update_check_routine(); -if($ARGV[0] eq "V"){ - if($ARGV[1] > $current_version){ - print "eqemu_update.pl Automatic Database Upgrade Needs updating...\n"; - print " Current version: " . $current_version . "\n"; - print " New version: " . $ARGV[1] . "\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); - exit; - } - else{ - print "[Upgrade Script] No script update necessary \n"; - } - exit; -} - -#::: Sets database run stage check -$db_run_stage = 0; +print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n"; +#::: Check Perl version $perl_version = $^V; $perl_version =~s/v//g; -print "Perl Version is " . $perl_version . "\n"; -if($perl_version > 5.12){ no warnings 'uninitialized'; } +print "[Update] Perl Version is " . $perl_version . "\n"; +if($perl_version > 5.12){ + no warnings 'uninitialized'; +} no warnings; +#::: Remove old eqemu_update.pl +if(-e "eqemu_update.pl"){ + unlink("eqemu_update.pl"); +} + ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); -my $confile = "eqemu_config.xml"; #default -open(F, "<$confile"); -my $indb = 0; -while() { - s/\r//g; - if(//i) { $indb = 1; } - next unless($indb == 1); - if(/<\/database>/i) { $indb = 0; last; } - if(/(.*)<\/host>/i) { $host = $1; } - elsif(/(.*)<\/username>/i) { $user = $1; } - elsif(/(.*)<\/password>/i) { $pass = $1; } - elsif(/(.*)<\/db>/i) { $db = $1; } -} - -$console_output = -"============================================================ - EQEmu: Automatic Upgrade Check -============================================================ -"; +read_eqemu_config_xml(); if($OS eq "Windows"){ $has_mysql_path = `echo %PATH%`; @@ -81,9 +63,6 @@ if($OS eq "Windows"){ last; } } - $console_output .= " (Windows) MySQL is in system path \n"; - $console_output .= " Path = " . $path . "\n"; - $console_output .= "============================================================\n"; } } @@ -91,101 +70,14 @@ if($OS eq "Windows"){ if($OS eq "Linux"){ $path = `which mysql`; if ($path eq "") { - $path = `which mariadb`; + $path = `which mariadb`; } $path =~s/\n//g; - - $console_output .= " (Linux) MySQL is in system path \n"; - $console_output .= " Path = " . $path . "\n"; - $console_output .= "============================================================\n"; } #::: Path not found, error and exit if($path eq ""){ - print "MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; - print "script_exiting...\n"; - exit; -} - -if($ARGV[0] eq "install_peq_db"){ - - $db_name = "peq"; - if($ARGV[1]){ - $db_name = $ARGV[1]; - } - - $db = $db_name; - - #::: Database Routines - print "MariaDB :: Creating Database '" . $db_name . "'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); - - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); -} - -if($ARGV[0] eq "remove_duplicate_rules"){ - remove_duplicate_rule_values(); - exit; -} - -if($ARGV[0] eq "installer"){ - print "Running EQEmu Server installer routines...\n"; - mkdir('logs'); - mkdir('updates_staged'); - mkdir('shared'); - fetch_latest_windows_binaries(); - map_files_fetch_bulk(); - opcodes_fetch(); - plugins_fetch(); - quest_files_fetch(); - lua_modules_fetch(); - - #::: Binary dll's - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); - - #::: Server scripts - fetch_utility_scripts(); - - #::: Database Routines - print "MariaDB :: Creating Database 'peq'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS peq;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE peq"`; - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); - - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); - - if($OS eq "Windows"){ - check_windows_firewall_rules(); - do_windows_login_server_setup(); - } - exit; -} - -if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } -if($ARGV[0] eq "login_server_setup"){ - do_windows_login_server_setup(); + print "[Error:eqemu_server.pl] MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; exit; } @@ -195,7 +87,7 @@ mkdir('db_update'); #::: Check if db_version table exists... if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ print get_mysql_result("DROP TABLE db_version"); - print "Old db_version table present, dropping...\n\n"; + print "[Database] Old db_version table present, dropping...\n\n"; } sub check_db_version_table{ @@ -205,7 +97,7 @@ sub check_db_version_table{ version int(11) DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO db_version (version) VALUES ('1000');"); - print "Table 'db_version' does not exists.... Creating...\n\n"; + print "[Database] Table 'db_version' does not exists.... Creating...\n\n"; } } @@ -218,173 +110,406 @@ $bin_db_ver = trim($db_version[1]); $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); #::: If ran from Linux startup script, supress output -if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_start"){ - print "Database up to date...\n"; +if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_world"){ + print "[Update] Database up to date...\n"; exit; } -else{ - print $console_output if $db; +else { + + #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup + if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){ + print "[Update] Database not up to date with binaries... Automatically updating...\n"; + print "[Update] Issuing database backup first...\n"; + database_dump_compress(); + print "[Update] Updating database...\n"; + sleep(1); + main_db_management(); + main_db_management(); + print "[Update] Continuing bootup\n"; + exit; + } + + #::: Make sure that we didn't pass any arugments to the script + if(!$ARGV[0]){ + if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } + show_menu_prompt(); + } } if($db){ - print " Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; + print "[Update] MySQL Path/Location: " . $path . "\n"; + print "[Update] Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; #::: Bots #::: Make sure we're running a bots binary to begin with if(trim($db_version[2]) > 0){ $bots_local_db_version = get_bots_db_version(); if($bots_local_db_version > 0){ - print " (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; + print "[Update] (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; } } - #::: If World ran this script, and our version is up to date, continue... + #::: If World ran this script, and our version is up to date, continue... if($bin_db_ver <= $local_db_ver && $ARGV[0] eq "ran_from_world"){ - print " Database up to Date: Continuing World Bootup...\n"; - print "============================================================\n"; + print "[Update] Database up to Date: Continuing World Bootup...\n"; exit; } +} +if($ARGV[0] eq "remove_duplicate_rules"){ + remove_duplicate_rule_values(); + exit; } -if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){ - print "You have missing database updates, type 1 or 2 to backup your database before running them as recommended...\n\n"; - #::: Display Menu - show_menu_prompt(); -} -else{ - #::: Most likely ran standalone - print "\n"; - show_menu_prompt(); +if($ARGV[0] eq "map_files_fetch_bulk"){ + map_files_fetch_bulk(); + exit; } -sub do_update_self{ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); - die "Rerun eqemu_update.pl"; +if($ARGV[0] eq "loginserver_install_linux"){ + do_linux_login_server_setup(); + exit; +} + +if($ARGV[0] eq "installer"){ + print "[Install] Running EQEmu Server installer routines...\n"; + + #::: Make some local server directories... + mkdir('logs'); + mkdir('updates_staged'); + mkdir('shared'); + + do_install_config_xml(); + read_eqemu_config_xml(); + get_installation_variables(); + + $db_name = "peq"; + if($installation_variables{"mysql_eqemu_db_name"}){ + $db_name = $installation_variables{"mysql_eqemu_db_name"}; + } + + #::: Download assets + if($OS eq "Windows"){ + fetch_latest_windows_binaries(); + get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); + get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); + get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); + } + map_files_fetch_bulk(); + opcodes_fetch(); + plugins_fetch(); + quest_files_fetch(); + lua_modules_fetch(); + fetch_utility_scripts(); + + #::: Database Routines + print "[Database] Creating Database '" . $db_name . "'\n"; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; + + #::: Get Binary DB version + if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } + if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } + $bin_db_ver = trim($db_version[1]); + + #::: Local DB Version + check_db_version_table(); + $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + + #::: Download PEQ latest + fetch_peq_db_full(); + print "[Database] Fetching Latest Database Updates...\n"; + main_db_management(); + print "[Database] Applying Latest Database Updates...\n"; + main_db_management(); + + if($OS eq "Windows"){ + check_windows_firewall_rules(); + do_windows_login_server_setup(); + } + if($OS eq "Linux"){ + do_linux_login_server_setup(); + + print "[Install] Installation complete!\n"; + } + + exit; +} + +if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } +if($ARGV[0] eq "login_server_setup"){ + do_windows_login_server_setup(); + exit; +} + +sub check_internet_connection { + if($OS eq "Linux"){ + $count = "c"; + } + if($OS eq "Windows"){ + $count = "n"; + } + + if (`ping 8.8.8.8 -$count 1 -w 500`=~/Reply from|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + elsif (`ping 4.2.2.2 -$count 1 -w 500`=~/Reply from|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + else{ + print "[Update] No connection to the internet, can't check update\n"; + return; + } +} + +sub do_self_update_check_routine { + #::: Check Version passed from world to update script + get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); + + if(!$has_internet_connection){ + print "[Update] Cannot check update without internet connection...\n"; + return; + } + + if(-e "updates_staged/eqemu_server.pl") { + + my $remote_script_size = -s "updates_staged/eqemu_server.pl"; + my $local_script_size = -s "eqemu_server.pl"; + + if($remote_script_size != $local_script_size){ + print "[Update] Script has been updated, updating...\n"; + + my @files; + my $start_dir = "updates_staged/"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + if($file=~/eqemu_server/i){ + $destination_file = $file; + $destination_file =~s/updates_staged\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + unlink($destination_file); + copy_file($file, $destination_file); + if($OS eq "Linux"){ + system("chmod 755 eqemu_server.pl"); + system("chown eqemu eqemu_server.pl"); + } + system("perl eqemu_server.pl start_from_world"); + } + } + print "[Install] Done\n"; + } + else { + print "[Update] No script update necessary...\n"; + } + + unlink("updates_staged/eqemu_server.pl"); + } +} + +sub get_installation_variables{ + #::: Fetch installation variables before building the config + open (INSTALL_VARS, "../install_variables.txt"); + while (){ + chomp; + $o = $_; + @data = split(":", $o); + $installation_variables{trim($data[0])} = trim($data[1]); + } + close (INSTALL_VARS); +} + +sub do_install_config_xml { + get_installation_variables(); + + #::: Fetch XML template + get_remote_file($install_repository_request_url . "eqemu_config.xml", "eqemu_config_template.xml"); + + #::: Open new config file + open (NEW_CONFIG, '>', 'eqemu_config.xml'); + + $in_database_tag = 0; + + #::: Iterate through template and replace variables... + open (FILE_TEMPLATE, "eqemu_config_template.xml"); + while (){ + chomp; + $o = $_; + + #::: Find replace variables + + if($o=~/\<\!--/i){ + next; + } + + if($o=~/database/i && $o=~/\<\//i){ + $in_database_tag = 0; + } + if($o=~/database/i){ + $in_database_tag = 1; + } + + if($o=~/key/i){ + my($replace_key) = $o =~ />(\w+)/i && $in_database_tag){ + my($replace_username) = $o =~ />(\w+)/i && $in_database_tag){ + my($replace_password) = $o =~ />(\w+)/i){ + my($replace_db_name) = $o =~ />(\w+) \&database_dump, - 2 => \&database_dump_compress, - 3 => \&main_db_management, - 4 => \&bots_db_management, - 5 => \&opcodes_fetch, - 6 => \&map_files_fetch, - 7 => \&plugins_fetch, - 8 => \&quest_files_fetch, - 9 => \&lua_modules_fetch, - 10 => \&aa_fetch, - 11 => \&fetch_latest_windows_binaries, - 12 => \&fetch_server_dlls, - 13 => \&do_windows_login_server_setup, - 14 => \&remove_duplicate_rule_values, - 15 => \&fetch_utility_scripts, - 18 => \&fetch_latest_windows_binaries_bots, - 19 => \&do_bots_db_schema_drop, - 20 => \&do_update_self, - 21 => \&database_dump_player_tables, - 0 => \&script_exit, - ); - while (1) { - { - local $| = 1; - if(!$menu_show && ($ARGV[0] eq "ran_from_world" || $ARGV[0] eq "ran_from_start")){ - $menu_show++; - next; - } - print menu_options(), '> '; - $menu_displayed++; - if($menu_displayed > 50){ - print "Safety: Menu looping too many times, exiting...\n"; - exit; - } + $dc = 0; + while (1) { + $input = trim($input); + + $errored_command = 0; + + if($input eq "database"){ + print "\n>>> Database Menu\n\n"; + print " [backup_database] Back up database to backups/ directory\n"; + print " [backup_player_tables] Back up player tables to backups/ directory\n"; + print " [backup_database_compressed] Back up database compressed to backups/ directory\n"; + print " \n"; + print " [check_db_updates] Checks for database updates manually\n"; + print " [check_bot_db_updates] Checks for bot database updates\n"; + print " \n"; + print " [aa_tables] Downloads and installs clean slate AA data from PEQ\n"; + print " [remove_duplicate_rules] Removes duplicate rules from rule_values table\n"; + print " [drop_bots_db_schema] Removes bot database schema\n"; + + print " \n> main - go back to main menu\n"; + print "Enter a command #> "; + $last_menu = trim($input); } - - my $choice = <>; - - $choice =~ s/\A\s+//; - $choice =~ s/\s+\z//; - - if (defined(my $handler = $dispatch{$choice})) { - my $result = $handler->(); - unless (defined $result) { - exit 0; + elsif($input eq "assets"){ + print "\n>>> Server Assets Menu\n\n"; + print " [maps] Download latest maps\n"; + print " [opcodes] Download opcodes (Patches for eq clients)\n"; + print " [quests] Download latest quests\n"; + print " [plugins] Download latest plugins\n"; + print " [lua_modules] Download latest lua_modules\n"; + print " [utility_scripts] Download utility scripts to run and operate the EQEmu Server\n"; + if($OS eq "Windows"){ + print "--- Windows\n"; + print " windows_server_download Updates server code from latest stable\n"; + print " windows_server_download_bots Updates server code (bots enabled) from latest\n"; + print " fetch_dlls Grabs dll's needed to run windows binaries\n"; + print " setup_loginserver Sets up loginserver for Windows\n"; } + print " \n> main - go back to main menu\n"; + print "Enter a command #> "; + $last_menu = trim($input); + } + elsif($input eq "backup_database"){ database_dump(); $dc = 1; } + elsif($input eq "backup_player_tables"){ database_dump_player_tables(); $dc = 1; } + elsif($input eq "backup_database_compressed"){ database_dump_compress(); $dc = 1; } + elsif($input eq "drop_bots_db_schema"){ do_bots_db_schema_drop(); $dc = 1; } + elsif($input eq "aa_tables"){ aa_fetch(); $dc = 1; } + elsif($input eq "remove_duplicate_rules"){ remove_duplicate_rule_values(); $dc = 1; } + elsif($input eq "maps"){ map_files_fetch_bulk(); $dc = 1; } + elsif($input eq "opcodes"){ opcodes_fetch(); $dc = 1; } + elsif($input eq "plugins"){ plugins_fetch(); $dc = 1; } + elsif($input eq "quests"){ quest_files_fetch(); $dc = 1; } + elsif($input eq "lua_modules"){ lua_modules_fetch(); $dc = 1; } + elsif($input eq "windows_server_download"){ fetch_latest_windows_binaries(); $dc = 1; } + elsif($input eq "windows_server_download_bots"){ fetch_latest_windows_binaries_bots(); $dc = 1; } + elsif($input eq "fetch_dlls"){ fetch_server_dlls(); $dc = 1; } + elsif($input eq "utility_scripts"){ fetch_utility_scripts(); $dc = 1; } + elsif($input eq "check_db_updates"){ main_db_management(); $dc = 1; } + elsif($input eq "check_bot_db_updates"){ bots_db_management(); $dc = 1; } + elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; } + elsif($input eq "exit"){ + exit; + } + elsif($input eq "main"){ + print "Returning to main menu...\n"; + print_main_menu(); + $last_menu = trim($input); + } + elsif($input eq "" && $last_menu ne ""){ + $errored_command = 1; + } + elsif($input ne ""){ + print "Invalid command '" . $input . "'\n"; + $errored_command = 1; } else { - if($ARGV[0] ne "ran_from_world"){ - # warn "\n\nInvalid selection\n\n"; - } + print_main_menu(); + } + + #::: Errored command checking + if($errored_command == 1){ + $input = $last_menu; + } + elsif($dc == 1){ + $dc = 0; + $input = ""; + } + else { + $input = <>; } } } -sub menu_options { - if(@total_updates){ - if($bots_db_management == 1){ - $option[3] = "Check and stage pending REQUIRED Database updates"; - $bots_management = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; - } - else{ - $option[3] = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; - if(get_mysql_result("SHOW TABLES LIKE 'bots'") eq ""){ - $bots_management = "Install bots database pre-requisites (Requires bots server binaries)"; - } - else{ - $bots_management = "Check for Bot pending REQUIRED database updates... (Must have bots enabled)"; - } - } - } - else{ - $option[3] = "Check and stage pending REQUIRED Database updates"; - $bots_management = "Check for Bot REQUIRED database updates... (Must have bots enabled)"; - } - -return <>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"; + print ">>> EQEmu Server Main Menu >>>>>>>>>>>>\n"; + print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"; + print " [database] Enter database management menu \n"; + print " [assets] Manage server assets \n\n"; + print " exit \n"; + print "\n"; + print "Enter a command #> "; } sub check_for_database_dump_script{ @@ -392,25 +517,21 @@ sub check_for_database_dump_script{ return; } else{ - print "db_dumper.pl not found... retrieving...\n\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/db_dumper.pl", "db_dumper.pl"); + print "[Database] db_dumper.pl not found... retrieving...\n"; + get_remote_file($eqemu_repository_request_url . "utils/scripts/db_dumper.pl", "db_dumper.pl"); } } -sub ran_from_world { - print "Running from world...\n"; -} - sub database_dump { check_for_database_dump_script(); - print "Performing database backup....\n"; + print "[Database] Performing database backup....\n"; print `perl db_dumper.pl database="$db" loc="backups"`; } sub database_dump_player_tables { check_for_database_dump_script(); - print "Performing database backup of player tables....\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/character_table_list.txt", "backups/character_table_list.txt"); + print "[Database] Performing database backup of player tables....\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/character_table_list.txt", "backups/character_table_list.txt"); $tables = ""; open (FILE, "backups/character_table_list.txt"); @@ -424,7 +545,7 @@ sub database_dump_player_tables { print `perl db_dumper.pl database="$db" loc="backups" tables="$tables" backup_name="player_tables_export" nolock`; - print "\nPress any key to continue...\n"; + print "[Database] Press any key to continue...\n"; <>; #Read from STDIN @@ -432,7 +553,7 @@ sub database_dump_player_tables { sub database_dump_compress { check_for_database_dump_script(); - print "Performing database backup....\n"; + print "[Database] Performing database backup....\n"; print `perl db_dumper.pl database="$db" loc="backups" compress`; } @@ -460,30 +581,40 @@ sub get_mysql_result_from_file{ if($OS eq "Linux"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } } -#::: Gets Remote File based on URL (1st Arg), and saves to destination file (2nd Arg) -#::: Example: get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); +#::: Gets Remote File based on request_url (1st Arg), and saves to destination file (2nd Arg) +#::: Example: get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); sub get_remote_file{ - my $URL = $_[0]; - my $Dest_File = $_[1]; + my $request_url = $_[0]; + my $destination_file = $_[1]; my $content_type = $_[2]; + my $no_retry = $_[3]; + my $silent_download = $_[4]; + + if(!$has_internet_connection){ + print "[Download] Cannot download without internet connection...\n"; + return; + } #::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary - if($Dest_File=~/\//i){ - my @dir_path = split('/', $Dest_File); + + if($destination_file=~/\//i){ + my @directory_path = split('/', $destination_file); $build_path = ""; - $di = 0; - while($dir_path[$di]){ - $build_path .= $dir_path[$di] . "/"; + $directory_index = 0; + while($directory_path[$directory_index] && $directory_path[$directory_index + 1]){ + $build_path .= $directory_path[$directory_index] . "/"; + # print "checking '" . $build_path . "'\n"; #::: If path does not exist, create the directory... - if (!-d $build_path) { + if (!-d $build_path) { + print "[Copy] folder doesn't exist, creating '" . $build_path . "'\n"; mkdir($build_path); } - if(!$dir_path[$di + 2] && $dir_path[$di + 1]){ + if(!$directory_indexr_path[$directory_index + 2] && $directory_indexr_path[$directory_index + 1]){ # print $actual_path . "\n"; $actual_path = $build_path; last; } - $di++; + $directory_index++; } } @@ -492,51 +623,59 @@ sub get_remote_file{ if($content_type == 1){ $break = 0; while($break == 0) { - use LWP::Simple qw(getstore); - if(!getstore($URL, $Dest_File)){ - # print "Error, no connection or failed request...\n\n"; + eval "use LWP::Simple qw(getstore);"; + # use LWP::Simple qw(getstore); + # print "request is " . $request_url . "\n"; + # print "destination file is supposed to be " . $destination_file . "\n"; + if(!getstore($request_url, $destination_file)){ + print "[Download] Error, no connection or failed request...\n\n"; } # sleep(1); #::: Make sure the file exists before continuing... - if(-e $Dest_File) { + if(-e $destination_file) { $break = 1; - print " [URL] :: " . $URL . "\n"; - print " [Saved] :: " . $Dest_File . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; } else { $break = 0; } usleep(500); + + if($no_retry){ + $break = 1; + } } } else{ $break = 0; while($break == 0) { require LWP::UserAgent; - my $ua = LWP::UserAgent->new; + my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; - my $response = $ua->get($URL); + my $response = $ua->get($request_url); if ($response->is_success){ - open (FILE, '> ' . $Dest_File . ''); + open (FILE, '> ' . $destination_file . ''); print FILE $response->decoded_content; close (FILE); } else { - # print "Error, no connection or failed request...\n\n"; + print "[Download] Error, no connection or failed request...\n\n"; } - if(-e $Dest_File) { + if(-e $destination_file) { $break = 1; - print " [URL] :: " . $URL . "\n"; - print " [Saved] :: " . $Dest_File . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; } else { $break = 0; } usleep(500); + + if($no_retry){ + $break = 1; + } } } } if($OS eq "Linux"){ #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt - $wget = `wget --no-check-certificate --quiet -O $Dest_File $URL`; - print " o URL: (" . $URL . ")\n"; - print " o Saved: (" . $Dest_File . ") \n"; - if($wget=~/unable to resolve/i){ + $wget = `wget --no-check-certificate --quiet -O $destination_file $request_url`; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; + if($wget=~/unable to resolve/i){ print "Error, no connection or failed request...\n\n"; #die; } @@ -551,6 +690,22 @@ sub trim { return $string; } +sub read_eqemu_config_xml { + my $confile = "eqemu_config.xml"; #default + open(F, "<$confile"); + my $indb = 0; + while() { + s/\r//g; + if(//i) { $indb = 1; } + next unless($indb == 1); + if(/<\/database>/i) { $indb = 0; last; } + if(/(.*)<\/host>/i) { $host = $1; } + elsif(/(.*)<\/username>/i) { $user = $1; } + elsif(/(.*)<\/password>/i) { $pass = $1; } + elsif(/(.*)<\/db>/i) { $db = $1; } + } +} + #::: Fetch Latest PEQ AA's sub aa_fetch{ if(!$db){ @@ -558,48 +713,48 @@ sub aa_fetch{ return; } - print "Pulling down PEQ AA Tables...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); - print "\n\nInstalling AA Tables...\n"; + print "[Install] Pulling down PEQ AA Tables...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); + print "[Install] Installing AA Tables...\n"; print get_mysql_result_from_file("db_update/peq_aa_tables_post_rework.sql"); - print "\nDone...\n\n"; + print "[Install] Done...\n\n"; } #::: Fetch Latest Opcodes sub opcodes_fetch{ - print "Pulling down latest opcodes...\n"; + print "[Update] Pulling down latest opcodes...\n"; %opcodes = ( - 1 => ["opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/opcodes.conf"], - 2 => ["mail_opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/mail_opcodes.conf"], - 3 => ["Titanium", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Titanium.conf"], - 4 => ["Secrets of Faydwer", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoF.conf"], - 5 => ["Seeds of Destruction", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoD.conf"], - 6 => ["Underfoot", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_UF.conf"], - 7 => ["Rain of Fear", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF.conf"], - 8 => ["Rain of Fear 2", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF2.conf"], + 1 => ["opcodes", $eqemu_repository_request_url . "utils/patches/opcodes.conf"], + 2 => ["mail_opcodes", $eqemu_repository_request_url . "utils/patches/mail_opcodes.conf"], + 3 => ["Titanium", $eqemu_repository_request_url . "utils/patches/patch_Titanium.conf"], + 4 => ["Secrets of Faydwer", $eqemu_repository_request_url . "utils/patches/patch_SoF.conf"], + 5 => ["Seeds of Destruction", $eqemu_repository_request_url . "utils/patches/patch_SoD.conf"], + 6 => ["Underfoot", $eqemu_repository_request_url . "utils/patches/patch_UF.conf"], + 7 => ["Rain of Fear", $eqemu_repository_request_url . "utils/patches/patch_RoF.conf"], + 8 => ["Rain of Fear 2", $eqemu_repository_request_url . "utils/patches/patch_RoF2.conf"], ); $loop = 1; while($opcodes{$loop}[0]){ - #::: Split the URL by the patches folder to get the file name from URL + #::: Split the request_url by the patches folder to get the file name from request_url @real_file = split("patches/", $opcodes{$loop}[1]); $find = 0; while($real_file[$find]){ $file_name = $real_file[$find]; $find++; } - - print "\nDownloading (" . $opcodes{$loop}[0] . ") File: '" . $file_name . "'...\n\n"; + get_remote_file($opcodes{$loop}[1], $file_name); $loop++; } - print "\nDone...\n\n"; + print "[Update] Done...\n"; } -sub remove_duplicate_rule_values{ +sub remove_duplicate_rule_values { $ruleset_id = trim(get_mysql_result("SELECT `ruleset_id` FROM `rule_sets` WHERE `name` = 'default'")); - print "Default Ruleset ID: " . $ruleset_id . "\n"; + print "[Database] Default Ruleset ID: " . $ruleset_id . "\n"; $total_removed = 0; + #::: Store Default values... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` = " . $ruleset_id); my @lines = split("\n", $mysql_result); @@ -607,50 +762,51 @@ sub remove_duplicate_rule_values{ my @values = split("\t", $val); $rule_set_values{$values[1]}[0] = $values[2]; } + #::: Compare default values against other rulesets to check for duplicates... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` != " . $ruleset_id); my @lines = split("\n", $mysql_result); foreach my $val (@lines){ my @values = split("\t", $val); if($values[2] == $rule_set_values{$values[1]}[0]){ - print "DUPLICATE : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . ", removing...\n"; + print "[Database] Removing duplicate : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . "\n"; get_mysql_result("DELETE FROM `rule_values` WHERE `ruleset_id` = " . $values[0] . " AND `rule_name` = '" . $values[1] . "'"); $total_removed++; } } - print "Total duplicate rules removed... " . $total_removed . "\n"; + print "[Database] Total duplicate rules removed... " . $total_removed . "\n"; } -sub copy_file{ +sub copy_file { $l_source_file = $_[0]; - $l_dest_file = $_[1]; - if($l_dest_file=~/\//i){ - my @dir_path = split('/', $l_dest_file); + $l_destination_file = $_[1]; + if($l_destination_file=~/\//i){ + my @directory_path = split('/', $l_destination_file); $build_path = ""; - $di = 0; - while($dir_path[$di]){ - $build_path .= $dir_path[$di] . "/"; + $directory_index = 0; + while($directory_path[$directory_index]){ + $build_path .= $directory_path[$directory_index] . "/"; #::: If path does not exist, create the directory... if (!-d $build_path) { mkdir($build_path); } - if(!$dir_path[$di + 2] && $dir_path[$di + 1]){ + if(!$directory_path[$directory_index + 2] && $directory_path[$directory_index + 1]){ # print $actual_path . "\n"; $actual_path = $build_path; last; } - $di++; + $directory_index++; } } - copy $l_source_file, $l_dest_file; + copy $l_source_file, $l_destination_file; } -sub fetch_latest_windows_binaries{ - print "\n --- Fetching Latest Windows Binaries... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); - print "\n --- Fetched Latest Windows Binaries... --- \n"; - print "\n --- Extracting... --- \n"; +sub fetch_latest_windows_binaries { + print "[Update] Fetching Latest Windows Binaries... \n"; + get_remote_file($install_repository_request_url . "master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); + print "[Update] Fetched Latest Windows Binaries... \n"; + print "[Update] Extracting... --- \n"; unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; @@ -659,21 +815,21 @@ sub fetch_latest_windows_binaries{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/binaries\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/binaries\///g; + print "[Update] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } - print "\n --- Done... --- \n"; + print "[Update] Done\n"; rmtree('updates_staged'); } -sub fetch_latest_windows_binaries_bots{ - print "\n --- Fetching Latest Windows Binaries with Bots... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); - print "\n --- Fetched Latest Windows Binaries with Bots... --- \n"; - print "\n --- Extracting... --- \n"; +sub fetch_latest_windows_binaries_bots { + print "[Update] Fetching Latest Windows Binaries with Bots...\n"; + get_remote_file($install_repository_request_url . "master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); + print "[Update] Fetched Latest Windows Binaries with Bots...\n"; + print "[Update] Extracting...\n"; unzip('updates_staged/master_windows_build_bots.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; @@ -682,20 +838,20 @@ sub fetch_latest_windows_binaries_bots{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/binaries\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/binaries\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } - print "\n --- Done... --- \n"; + print "[Update] Done...\n"; rmtree('updates_staged'); } -sub do_windows_login_server_setup{ - print "\n --- Fetching Loginserver... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server.zip", "updates_staged/login_server.zip", 1); - print "\n --- Extracting... --- \n"; +sub do_windows_login_server_setup { + print "[Install] Fetching Loginserver... \n"; + get_remote_file($install_repository_request_url . "login_server.zip", "updates_staged/login_server.zip", 1); + print "[Install] Extracting... \n"; unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); my @files; my $start_dir = "updates_staged/login_server"; @@ -704,31 +860,85 @@ sub do_windows_login_server_setup{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/login_server\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/login_server\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } - print "\n Done... \n"; + print "[Install] Done... \n"; - print "Pulling down Loginserver database tables...\n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server_tables.sql", "db_update/login_server_tables.sql"); - print "\n\nInstalling Loginserver tables...\n"; + print "[Install] Pulling down Loginserver database tables...\n"; + get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); + print "[Install] Installing Loginserver tables...\n"; print get_mysql_result_from_file("db_update/login_server_tables.sql"); - print "\nDone...\n\n"; + print "[Install] Done...\n"; add_login_server_firewall_rules(); rmtree('updates_staged'); rmtree('db_update'); - print "\nPress any key to continue...\n"; + print "[Install] Press any key to continue...\n"; + + <>; #Read from STDIN + +} + +sub do_linux_login_server_setup { + + for my $file (@files) { + $destination_file = $file; + $destination_file =~s/updates_staged\/login_server\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); + } + print "\n Done... \n"; + + print "[Install] Pulling down Loginserver database tables...\n"; + get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); + print "[Install] Installing Loginserver tables...\n"; + print get_mysql_result_from_file("db_update/login_server_tables.sql"); + print "[Install] Done...\n\n"; + + rmtree('updates_staged'); + rmtree('db_update'); + + get_remote_file($install_repository_request_url . "linux/login.ini", "login_template.ini"); + get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes.conf"); + get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes_sod.conf"); + + get_installation_variables(); + my $db_name = $installation_variables{"mysql_eqemu_db_name"}; + my $db_user = $installation_variables{"mysql_eqemu_user"}; + my $db_password = $installation_variables{"mysql_eqemu_password"}; + + #::: Open new config file + open (NEW_CONFIG, '>', 'login.ini'); + + #::: Iterate through template and replace variables... + open (FILE_TEMPLATE, "login_template.ini"); + while (){ + chomp; + $o = $_; + #::: Find replace variables + if($o=~/db/i){ $o = "db = " . $db_name; } + if($o=~/user/i){ $o = "user = " . $db_user; } + if($o=~/password/i){ $o = "password = " . $db_password; } + + print NEW_CONFIG $o . "\n"; + } + + close(FILE_TEMPLATE); + close(NEW_CONFIG); + unlink("login_template.ini"); + + print "[Install] Press any key to continue...\n"; <>; #Read from STDIN } -sub add_login_server_firewall_rules{ +sub add_login_server_firewall_rules { #::: Check Loginserver Firewall install for Windows if($OS eq "Windows"){ $output = `netsh advfirewall firewall show rule name=all`; @@ -750,22 +960,22 @@ sub add_login_server_firewall_rules{ } if($has_loginserver_rules_titanium == 0){ - print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) TCP" dir=in action=allow protocol=TCP localport=5998`; - print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) UDP" dir=in action=allow protocol=UDP localport=5998`; } if($has_loginserver_rules_sod == 0){ - print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) TCP" dir=in action=allow protocol=TCP localport=5999`; - print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) UDP" dir=in action=allow protocol=UDP localport=5999`; } - print "If firewall rules don't add you must run this script (eqemu_update.pl) as administrator\n"; + print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n"; print "\n"; - print "#::: Instructions \n"; - print "In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; + print "[Install] Instructions \n"; + print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; print " login.eqemulator.net @@ -780,7 +990,7 @@ sub add_login_server_firewall_rules{ "; - print "\nWhen done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; + print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; } } @@ -794,84 +1004,84 @@ sub check_windows_firewall_rules{ $val=~s/Rule Name://g; if($val=~/EQEmu World/i){ $has_world_rules = 1; - print "Found existing rule :: " . trim($val) . "\n"; + print "[Install] Found existing rule :: " . trim($val) . "\n"; } if($val=~/EQEmu Zone/i){ $has_zone_rules = 1; - print "Found existing rule :: " . trim($val) . "\n"; + print "[Install] Found existing rule :: " . trim($val) . "\n"; } } } if($has_world_rules == 0){ - print "Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; + print "[Install] Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; print `netsh advfirewall firewall add rule name="EQEmu World (9000) TCP" dir=in action=allow protocol=TCP localport=9000`; - print "Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; + print "[Install] Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; print `netsh advfirewall firewall add rule name="EQEmu World (9000) UDP" dir=in action=allow protocol=UDP localport=9000`; } if($has_zone_rules == 0){ - print "Attempting to add EQEmu Zones (7000-7500) TCP \n"; + print "[Install] Attempting to add EQEmu Zones (7000-7500) TCP \n"; print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) TCP" dir=in action=allow protocol=TCP localport=7000-7500`; - print "Attempting to add EQEmu Zones (7000-7500) UDP \n"; + print "[Install] Attempting to add EQEmu Zones (7000-7500) UDP \n"; print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) UDP" dir=in action=allow protocol=UDP localport=7000-7500`; } } sub fetch_server_dlls{ - print "Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); + print "[Download] Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; + get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); + get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); + get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); } sub fetch_peq_db_full{ - print "Downloading latest PEQ Database... Please wait...\n"; + print "[Install] Downloading latest PEQ Database... Please wait...\n"; get_remote_file("http://edit.peqtgc.com/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1); - print "Downloaded latest PEQ Database... Extracting...\n"; + print "[Install] Downloaded latest PEQ Database... Extracting...\n"; unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); - my $start_dir = "updates_staged\\peq_db"; + my $start_dir = "updates_staged/peq_db"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\\peq_db\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/peq_db\///g; if($file=~/peqbeta|player_tables/i){ - print "MariaDB :: Installing :: " . $dest_file . "\n"; + print "[Install] DB :: Installing :: " . $destination_file . "\n"; get_mysql_result_from_file($file); } if($file=~/eqtime/i){ - print "Installing eqtime.cfg\n"; + print "[Install] Installing eqtime.cfg\n"; copy_file($file, "eqtime.cfg"); } } } sub map_files_fetch_bulk{ - print "\n --- Fetching Latest Maps... (This could take a few minutes...) --- \n"; + print "[Install] Fetching Latest Maps... (This could take a few minutes...)\n"; get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1); unzip('maps/maps.zip', 'maps/'); my @files; - my $start_dir = "maps\\EQEmuMaps-master\\maps"; + my $start_dir = "maps/EQEmuMaps-master/maps"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/maps\\EQEmuMaps-master\\maps\///g; - print "Installing :: " . $dest_file . "\n"; + $destination_file = $file; + $destination_file =~s/maps\/EQEmuMaps-master\/maps\///g; + print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, "maps/" . $new_file); } - print "\n --- Fetched Latest Maps... --- \n"; + print "[Install] Fetched Latest Maps\n"; rmtree('maps/EQEmuMaps-master'); unlink('maps/maps.zip'); } sub map_files_fetch{ - print "\n --- Fetching Latest Maps --- \n"; + print "[Install] Fetching Latest Maps --- \n"; get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt"); @@ -894,22 +1104,22 @@ sub map_files_fetch{ my $file_existing = $maps_manifest[$m][0]; my $file_existing_size = (stat $file_existing)[7]; if($file_existing_size != $maps_manifest[$m][1]){ - print "Updating: '" . $maps_manifest[$m][0] . "'\n"; + print "[Install] Updating: '" . $maps_manifest[$m][0] . "'\n"; get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1); $fc++; } } if($fc == 0){ - print "\nNo Map Updates found... \n\n"; + print "[Install] No Map Updates found... \n\n"; } } sub quest_files_fetch{ if (!-e "updates_staged/Quests-Plugins-master/quests/") { - print "\n --- Fetching Latest Quests --- \n"; + print "[Update] Fetching Latest Quests --- \n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest quests...\n"; + print "[Install] Fetched latest quests...\n"; mkdir('updates_staged'); unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -927,30 +1137,30 @@ sub quest_files_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this Quest? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this Quest? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -961,15 +1171,15 @@ sub quest_files_fetch{ rmtree('updates_staged'); if($fc == 0){ - print "\nNo Quest Updates found... \n\n"; + print "[Update] No Quest Updates found... \n\n"; } } -sub lua_modules_fetch{ +sub lua_modules_fetch { if (!-e "updates_staged/Quests-Plugins-master/quests/lua_modules/") { - print "\n --- Fetching Latest LUA Modules --- \n"; + print "[Update] Fetching Latest LUA Modules --- \n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest LUA Modules...\n"; + print "[Update] Fetched latest LUA Modules...\n"; unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -986,29 +1196,29 @@ sub lua_modules_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this LUA Module? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this LUA Module? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -1017,15 +1227,15 @@ sub lua_modules_fetch{ } if($fc == 0){ - print "\nNo LUA Modules Updates found... \n\n"; + print "[Update] No LUA Modules Updates found... \n\n"; } } sub plugins_fetch{ if (!-e "updates_staged/Quests-Plugins-master/plugins/") { - print "\n --- Fetching Latest Plugins --- \n"; + print "[Update] Fetching Latest Plugins\n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest plugins...\n"; + print "[Update] Fetched latest plugins\n"; unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -1042,29 +1252,29 @@ sub plugins_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this Plugin? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this Plugin? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -1073,7 +1283,7 @@ sub plugins_fetch{ } if($fc == 0){ - print "\nNo Plugin Updates found... \n\n"; + print "[Update] No Plugin Updates found... \n\n"; } } @@ -1082,8 +1292,8 @@ sub do_file_diff{ $file_2 = $_[1]; if($OS eq "Windows"){ eval "use Text::Diff"; - $diff = diff($file_1, $file_2, { STYLE => "Unified" }); - return $diff; + $directory_indexff = diff($file_1, $file_2, { STYLE => "Unified" }); + return $directory_indexff; } if($OS eq "Linux"){ # print 'diff -u "$file_1" "$file_2"' . "\n"; @@ -1091,7 +1301,7 @@ sub do_file_diff{ } } -sub unzip{ +sub unzip { $archive_to_unzip = $_[0]; $dest_folder = $_[1]; @@ -1101,11 +1311,11 @@ sub unzip{ unless ( $zip->read($archive_to_unzip) == AZ_OK ) { die 'read error'; } - print "Extracting...\n"; + print "[Unzip] Extracting...\n"; $zip->extractTree('', $dest_folder); } if($OS eq "Linux"){ - print `unzip -o "$archive_to_unzip" -d "$dest_folder"`; + print `unzip -o -q "$archive_to_unzip" -d "$dest_folder"`; } } @@ -1123,11 +1333,11 @@ sub are_file_sizes_different{ sub do_bots_db_schema_drop{ #"drop_bots.sql" is run before reverting database back to 'normal' - print "Fetching drop_bots.sql...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); + print "[Database] Fetching drop_bots.sql...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); print get_mysql_result_from_file("db_update/drop_bots.sql"); - print "Restoring normality...\n"; + print "[Database] Removing bot database tables...\n"; print get_mysql_result("DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots:%';"); if(get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && $db){ @@ -1153,11 +1363,12 @@ sub do_bots_db_schema_drop{ if(get_mysql_result("SHOW COLUMNS FROM `db_version` LIKE 'bots_version'") ne "" && $db){ print get_mysql_result("UPDATE `db_version` SET `bots_version` = 0;"); } + print "[Database] Done...\n"; } sub modify_db_for_bots{ #Called after the db bots schema (2015_09_30_bots.sql) has been loaded - print "Modifying database for bots...\n"; + print "[Database] Modifying database for bots...\n"; print get_mysql_result("UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298);"); if(get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ @@ -1238,7 +1449,7 @@ sub modify_db_for_bots{ sub convert_existing_bot_data{ if(get_mysql_result("SHOW TABLES LIKE 'bots'") ne "" && $db){ - print "Converting existing bot data...\n"; + print "[Database] Converting existing bot data...\n"; print get_mysql_result("INSERT INTO `bot_data` (`bot_id`, `owner_id`, `spells_id`, `name`, `last_name`, `zone_id`, `gender`, `race`, `class`, `level`, `creation_day`, `last_spawn`, `time_spawned`, `size`, `face`, `hair_color`, `hair_style`, `beard`, `beard_color`, `eye_color_1`, `eye_color_2`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `ac`, `atk`, `hp`, `mana`, `str`, `sta`, `cha`, `dex`, `int`, `agi`, `wis`, `fire`, `cold`, `magic`, `poison`, `disease`, `corruption`) SELECT `BotID`, `BotOwnerCharacterID`, `BotSpellsID`, `Name`, `LastName`, `LastZoneId`, `Gender`, `Race`, `Class`, `BotLevel`, UNIX_TIMESTAMP(`BotCreateDate`), UNIX_TIMESTAMP(`LastSpawnDate`), `TotalPlayTime`, `Size`, `Face`, `LuclinHairColor`, `LuclinHairStyle`, `LuclinBeard`, `LuclinBeardColor`, `LuclinEyeColor`, `LuclinEyeColor2`, `DrakkinHeritage`, `DrakkinTattoo`, `DrakkinDetails`, `AC`, `ATK`, `HP`, `Mana`, `STR`, `STA`, `CHA`, `DEX`, `_INT`, `AGI`, `WIS`, `FR`, `CR`, `MR`, `PR`, `DR`, `Corrup` FROM `bots`;"); print get_mysql_result("INSERT INTO `bot_inspect_messages` (`bot_id`, `inspect_message`) SELECT `BotID`, `BotInspectMessage` FROM `bots`;"); @@ -1335,7 +1546,7 @@ sub get_bots_db_version{ #::: Check if bots_version column exists... if(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db){ print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;"); - print "\nColumn 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; + print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; } $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); return $bots_local_db_version; @@ -1351,7 +1562,7 @@ sub bots_db_management{ } if($bin_db_ver == 0){ - print "Your server binaries (world/zone) are not compiled for bots...\n"; + print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n"; return; } @@ -1397,22 +1608,22 @@ sub run_database_check{ if(!@total_updates){ #::: Pull down bots database manifest if($bots_db_management == 1){ - print "Retrieving latest bots database manifest...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); + print "[Database] Retrieving latest bots database manifest...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); } #::: Pull down mainstream database manifest else{ - print "Retrieving latest database manifest...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); + print "[Database] Retrieving latest database manifest...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); } } #::: Run 2 - Running pending updates... - if(@total_updates){ + if(@total_updates || $db_run_stage == 1){ @total_updates = sort @total_updates; foreach my $val (@total_updates){ $file_name = trim($m_d{$val}[1]); - print "Running Update: " . $val . " - " . $file_name . "\n"; + print "[Database] Running Update: " . $val . " - " . $file_name . "\n"; print get_mysql_result_from_file("db_update/$file_name"); print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val"); @@ -1424,7 +1635,7 @@ sub run_database_check{ } #::: Run 1 - Initial checking of needed updates... else{ - print "Reading manifest...\n\n"; + print "[Database] Reading manifest...\n"; use Data::Dumper; open (FILE, "db_update/db_update_manifest.txt"); while () { @@ -1458,23 +1669,23 @@ sub run_database_check{ #::: Match type update if($match_type eq "contains"){ if(trim(get_mysql_result($query_check))=~/$match_text/i){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "missing"){ if(get_mysql_result($query_check)=~/$match_text/i){ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; next; } else{ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } @@ -1483,24 +1694,24 @@ sub run_database_check{ } if($match_type eq "empty"){ if(get_mysql_result($query_check) eq ""){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "not_empty"){ if(get_mysql_result($query_check) ne ""){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); @@ -1509,13 +1720,13 @@ sub run_database_check{ print "\n"; if(scalar (@total_updates) == 0 && $db_run_stage == 2){ - print "No updates need to be run...\n"; + print "[Database] No updates need to be run...\n"; if($bots_db_management == 1){ - print "Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; + print "[Database] Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; get_mysql_result("UPDATE db_version SET bots_version = $bin_db_ver"); } - else{ - print "Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; + else{ + print "[Database] Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; get_mysql_result("UPDATE db_version SET version = $bin_db_ver"); } @@ -1528,14 +1739,14 @@ sub fetch_missing_db_update{ $update_file = $_[1]; if($db_update >= 9000){ if($bots_db_management == 1){ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); } else{ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); } } elsif($db_update >= 5000 && $db_update <= 9000){ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); } } @@ -1546,7 +1757,17 @@ sub print_match_debug{ print " Query Check: '" . $query_check . "'\n"; print " Result: '" . trim(get_mysql_result($query_check)) . "'\n"; } + sub print_break{ if(!$debug){ return; } print "\n==============================================\n"; } + +sub generate_random_password { + my $passwordsize = shift; + my @alphanumeric = ('a'..'z', 'A'..'Z', 0..9); + my $randpassword = join '', + map $alphanumeric[rand @alphanumeric], 0..$passwordsize; + + return $randpassword; +} From 85c28185a2da449c1a2b8f7305082ec398d5f412 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 18:01:17 -0500 Subject: [PATCH 328/693] Update eqemu_server.pl - Add internet connection checks for people who are using EQEmu locally [skip ci] --- utils/scripts/eqemu_server.pl | 58 +++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 47955266d..e794a3710 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -27,6 +27,7 @@ $db_run_stage = 0; #::: Sets database run stage check $console_output .= " Operating System is: $Config{osname}\n"; if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } +$has_internet_connection = check_internet_connection(); #::: Check for script self update do_self_update_check_routine(); @@ -86,7 +87,7 @@ mkdir('db_update'); #::: Check if db_version table exists... if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ print get_mysql_result("DROP TABLE db_version"); - print "Old db_version table present, dropping...\n\n"; + print "[Database] Old db_version table present, dropping...\n\n"; } sub check_db_version_table{ @@ -96,7 +97,7 @@ sub check_db_version_table{ version int(11) DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO db_version (version) VALUES ('1000');"); - print "Table 'db_version' does not exists.... Creating...\n\n"; + print "[Database] Table 'db_version' does not exists.... Creating...\n\n"; } } @@ -241,10 +242,37 @@ if($ARGV[0] eq "login_server_setup"){ exit; } +sub check_internet_connection { + if($OS eq "Linux"){ + $count = "c"; + } + if($OS eq "Windows"){ + $count = "n"; + } + + if (`ping 8.8.8.8 -$count 1 -w 500`=~/Reply from|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + elsif (`ping 4.2.2.2 -$count 1 -w 500`=~/Reply from|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + else{ + print "[Update] No connection to the internet, can't check update\n"; + return; + } +} + sub do_self_update_check_routine { #::: Check Version passed from world to update script - get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1); + get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); + if(!$has_internet_connection){ + print "[Update] Cannot check update without internet connection...\n"; + return; + } + if(-e "updates_staged/eqemu_server.pl") { my $remote_script_size = -s "updates_staged/eqemu_server.pl"; @@ -560,6 +588,12 @@ sub get_remote_file{ my $destination_file = $_[1]; my $content_type = $_[2]; my $no_retry = $_[3]; + my $silent_download = $_[4]; + + if(!$has_internet_connection){ + print "[Download] Cannot download without internet connection...\n"; + return; + } #::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary @@ -600,7 +634,7 @@ sub get_remote_file{ #::: Make sure the file exists before continuing... if(-e $destination_file) { $break = 1; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; } else { $break = 0; } usleep(500); @@ -613,7 +647,7 @@ sub get_remote_file{ $break = 0; while($break == 0) { require LWP::UserAgent; - my $ua = LWP::UserAgent->new; + my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get($request_url); @@ -627,7 +661,7 @@ sub get_remote_file{ } if(-e $destination_file) { $break = 1; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; } else { $break = 0; } usleep(500); @@ -640,7 +674,7 @@ sub get_remote_file{ if($OS eq "Linux"){ #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt $wget = `wget --no-check-certificate --quiet -O $destination_file $request_url`; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; if($wget=~/unable to resolve/i){ print "Error, no connection or failed request...\n\n"; #die; @@ -853,7 +887,7 @@ sub do_windows_login_server_setup { sub do_linux_login_server_setup { for my $file (@files) { - $destination_file = $file; + $destination_file = $file; $destination_file =~s/updates_staged\/login_server\///g; print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, $destination_file); @@ -1277,7 +1311,7 @@ sub unzip { unless ( $zip->read($archive_to_unzip) == AZ_OK ) { die 'read error'; } - print "Extracting...\n"; + print "[Unzip] Extracting...\n"; $zip->extractTree('', $dest_folder); } if($OS eq "Linux"){ @@ -1512,7 +1546,7 @@ sub get_bots_db_version{ #::: Check if bots_version column exists... if(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db){ print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;"); - print "\nColumn 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; + print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; } $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); return $bots_local_db_version; @@ -1528,7 +1562,7 @@ sub bots_db_management{ } if($bin_db_ver == 0){ - print "Your server binaries (world/zone) are not compiled for bots...\n\n"; + print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n"; return; } @@ -1736,4 +1770,4 @@ sub generate_random_password { map $alphanumeric[rand @alphanumeric], 0..$passwordsize; return $randpassword; -} \ No newline at end of file +} From 385823461b7f77050d5b5f661f9baac6fe887a61 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 25 Aug 2016 18:30:04 -0500 Subject: [PATCH 329/693] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index e794a3710..e91df2914 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -202,6 +202,8 @@ if($ARGV[0] eq "installer"){ lua_modules_fetch(); fetch_utility_scripts(); + + #::: Database Routines print "[Database] Creating Database '" . $db_name . "'\n"; print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; @@ -313,7 +315,12 @@ sub do_self_update_check_routine { sub get_installation_variables{ #::: Fetch installation variables before building the config - open (INSTALL_VARS, "../install_variables.txt"); + if($OS eq "Linux"){ + open (INSTALL_VARS, "../install_variables.txt"); + } + if($OS eq "Windows"){ + open (INSTALL_VARS, "install_variables.txt"); + } while (){ chomp; $o = $_; @@ -440,14 +447,14 @@ sub show_menu_prompt { print " [lua_modules] Download latest lua_modules\n"; print " [utility_scripts] Download utility scripts to run and operate the EQEmu Server\n"; if($OS eq "Windows"){ - print "--- Windows\n"; - print " windows_server_download Updates server code from latest stable\n"; - print " windows_server_download_bots Updates server code (bots enabled) from latest\n"; - print " fetch_dlls Grabs dll's needed to run windows binaries\n"; - print " setup_loginserver Sets up loginserver for Windows\n"; + print ">>> Windows\n"; + print " [windows_server_download] Updates server code from latest stable\n"; + print " [windows_server_download_bots] Updates server code (bots enabled) from latest\n"; + print " [fetch_dlls] Grabs dll's needed to run windows binaries\n"; + print " [setup_loginserver] Sets up loginserver for Windows\n"; } print " \n> main - go back to main menu\n"; - print "Enter a command #> "; + print "Enter a command #> "; $last_menu = trim($input); } elsif($input eq "backup_database"){ database_dump(); $dc = 1; } From 4de9b2c53e56f59941d2cceec2153d14e06ee714 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Fri, 26 Aug 2016 06:34:51 -0700 Subject: [PATCH 330/693] Add TiltX and TiltY manipulation to objects (Perl) Translate OP_GroundSpawn for Titanium #perl plugin http://wiki.eqemulator.org/i?Module=Pastebin&Paste=u9IbA6Ql --- common/eq_packet_structs.h | 24 ++-- common/patches/rof.cpp | 4 +- common/patches/rof2.cpp | 4 +- common/patches/titanium.cpp | 40 +++++++ common/patches/titanium_ops.h | 1 + common/patches/uf.cpp | 4 +- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../required/2016_08_26_object_size_tilt.sql | 4 + zone/object.cpp | 51 +++++++- zone/object.h | 8 +- zone/perl_object.cpp | 110 +++++++++++++++++- zone/zone.cpp | 8 +- 13 files changed, 232 insertions(+), 29 deletions(-) create mode 100644 utils/sql/git/required/2016_08_26_object_size_tilt.sql diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index a1b614b97..cf411ef72 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -2509,23 +2509,25 @@ struct BookRequest_Struct { */ struct Object_Struct { /*00*/ uint32 linked_list_addr[2];// They are, get this, prev and next, ala linked list -/*08*/ uint16 size; // +/*08*/ float size; // /*10*/ uint16 solidtype; // /*12*/ uint32 drop_id; // Unique object id for zone /*16*/ uint16 zone_id; // Redudant, but: Zone the object appears in /*18*/ uint16 zone_instance; // /*20*/ uint32 unknown020; // /*24*/ uint32 unknown024; // -/*28*/ float heading; // heading -/*32*/ float z; // z coord -/*36*/ float x; // x coord -/*40*/ float y; // y coord -/*44*/ char object_name[32]; // Name of object, usually something like IT63_ACTORDEF -/*76*/ uint32 unknown076; // -/*80*/ uint32 object_type; // Type of object, not directly translated to OP_OpenObject -/*84*/ uint32 unknown084; //set to 0xFF -/*88*/ uint32 spawn_id; // Spawn Id of client interacting with object -/*92*/ +/*28*/ float tilt_x; +/*32*/ float tilt_y; +/*36*/ float heading; // heading +/*40*/ float z; // z coord +/*44*/ float x; // x coord +/*76*/ float y; // y coord +/*80*/ char object_name[32]; // Name of object, usually something like IT63_ACTORDEF +/*84*/ uint32 unknown076; // +/*88*/ uint32 object_type; // Type of object, not directly translated to OP_OpenObject +/*92*/ uint32 unknown084; //set to 0xFF + uint32 spawn_id; // Spawn Id of client interacting with object + }; // 01 = generic drop, 02 = armor, 19 = weapon //[13:40] and 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 7c5f302cb..8ab38905f 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -987,8 +987,8 @@ namespace RoF VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); // Some unique id VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading); - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // X tilt - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Y tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_x); // X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_y); // Y tilt VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt. VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 5bb93f14a..aedd7b592 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1062,8 +1062,8 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); // Some unique id VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading); - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // X tilt - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Y tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_x); // X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_y); // Y tilt VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt. VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index cc10f6487..9e93051b1 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -595,6 +595,46 @@ namespace Titanium dest->FastQueuePacket(&in, ack_req); } + ENCODE(OP_GroundSpawn) + { + // We are not encoding the spawn_id field here, but it doesn't appear to matter. + // + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + Object_Struct *emu = (Object_Struct *)__emu_buffer; + + in->size = strlen(emu->object_name) + sizeof(structs::Object_Struct) - 1; + in->pBuffer = new unsigned char[in->size]; + + structs::Object_Struct *eq = (structs::Object_Struct *) in->pBuffer; + + eq->drop_id = emu->drop_id; + eq->heading = emu->heading; + eq->linked_list_addr[0] = 0; + eq->linked_list_addr[1] = 0; + strcpy(eq->object_name, emu->object_name); + eq->object_type = emu->object_type; + eq->spawn_id = 0; + eq->unknown008[0] = 0; + eq->unknown008[1] = 0; + eq->unknown020 = 0; + eq->unknown024 = 0; + eq->unknown076 = 0; + eq->unknown084 = 0xffffffff; + eq->z = emu->z; + eq->x = emu->x; + eq->y = emu->y; + eq->zone_id = emu->zone_id; + eq->zone_instance = emu->zone_instance; + + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + ENCODE(OP_GuildMemberList) { //consume the packet diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index 9ca0ba770..5e65dd7c0 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -40,6 +40,7 @@ E(OP_DzLeaderStatus) E(OP_DzMemberList) E(OP_Emote) E(OP_FormattedMessage) +E(OP_GroundSpawn) E(OP_GuildMemberLevelUpdate) E(OP_GuildMemberList) E(OP_Illusion) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index af81fea06..ba5bf7622 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -875,8 +875,8 @@ namespace UF // This next field is actually a float. There is a groundspawn in freeportwest (sack of money sitting on some barrels) which requires this // field to be set to (float)255.0 to appear at all, and also the size field below to be 5, to be the correct size. I think SoD has the same // issue. - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); //X tilt - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); //Y tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_x); //X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->tilt_y); //Y tilt VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt. VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); diff --git a/common/version.h b/common/version.h index 38731b3ba..f06a68c05 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9097 +#define CURRENT_BINARY_DATABASE_VERSION 9098 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 283500c3b..4030395c3 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -351,6 +351,7 @@ 9095|2016_01_08_command_find_aliases.sql|SELECT * FROM `command_settings` WHERE `command` LIKE 'findaliases'|empty| 9096|2016_03_05_secondary_recall.sql|SHOW COLUMNS FROM `character_bind` LIKE 'slot'|empty| 9097|2016_07_03_npc_class_as_last_name.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'NPC:UseClassAsLastName'|empty| +9098|2016_08_26_object_size_tilt.sql|SHOW COLUMNS FROM `object` LIKE 'size'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2016_08_26_object_size_tilt.sql b/utils/sql/git/required/2016_08_26_object_size_tilt.sql new file mode 100644 index 000000000..ded4d841d --- /dev/null +++ b/utils/sql/git/required/2016_08_26_object_size_tilt.sql @@ -0,0 +1,4 @@ +ALTER TABLE `object` + ADD COLUMN `size` FLOAT NOT NULL DEFAULT '100' AFTER `unknown84`, + ADD COLUMN `tilt_x` FLOAT NOT NULL DEFAULT '0' AFTER `size`, + ADD COLUMN `tilt_y` FLOAT NOT NULL DEFAULT '0' AFTER `tilt_x`; \ No newline at end of file diff --git a/zone/object.cpp b/zone/object.cpp index f74d2dd0d..a9672ee4f 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -63,6 +63,9 @@ Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, // Set drop_id to zero - it will be set when added to zone with SetID() m_data.drop_id = 0; + m_data.size = object.size; + m_data.tilt_x = object.tilt_x; + m_data.tilt_y = object.tilt_y; } //creating a re-ocurring ground spawn. @@ -653,10 +656,12 @@ void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Objec // Save new record for object std::string query = StringFormat("UPDATE object SET " "zoneid = %i, xpos = %f, ypos = %f, zpos = %f, heading = %f, " - "itemid = %i, charges = %i, objectname = '%s', type = %i, icon = %i " + "itemid = %i, charges = %i, objectname = '%s', type = %i, icon = %i, " + "size = %f, tilt_x = %f, tilt_y = %f " "WHERE id = %i", object.zone_id, object.x, object.y, object.z, object.heading, - item_id, charges, object_name, type, icon, id); + item_id, charges, object_name, type, icon, + object.size, object.tilt_x, object.tilt_y, id); safe_delete_array(object_name); auto results = QueryDatabase(query); if (!results.Success()) { @@ -750,6 +755,16 @@ float Object::GetHeadingData() return this->m_data.heading; } +float Object::GetTiltX() +{ + return this->m_data.tilt_x; +} + +float Object::GetTiltY() +{ + return this->m_data.tilt_y; +} + void Object::SetX(float pos) { this->m_data.x = pos; @@ -778,6 +793,34 @@ void Object::SetY(float pos) safe_delete(app2); } +void Object::SetTiltX(float pos) +{ + this->m_data.tilt_x = pos; + + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); + this->CreateDeSpawnPacket(app); + this->CreateSpawnPacket(app2); + entity_list.QueueClients(0, app); + entity_list.QueueClients(0, app2); + safe_delete(app); + safe_delete(app2); +} + +void Object::SetTiltY(float pos) +{ + this->m_data.tilt_y = pos; + + auto app = new EQApplicationPacket(); + auto app2 = new EQApplicationPacket(); + this->CreateDeSpawnPacket(app); + this->CreateSpawnPacket(app2); + entity_list.QueueClients(0, app); + entity_list.QueueClients(0, app2); + safe_delete(app); + safe_delete(app2); +} + void Object::Depop() { auto app = new EQApplicationPacket(); @@ -828,7 +871,7 @@ void Object::SetModelName(const char* modelname) safe_delete(app2); } -void Object::SetSize(uint16 size) +void Object::SetSize(float size) { m_data.size = size; auto app = new EQApplicationPacket(); @@ -854,7 +897,7 @@ void Object::SetSolidType(uint16 solidtype) safe_delete(app2); } -uint16 Object::GetSize() +float Object::GetSize() { return m_data.size; } diff --git a/zone/object.h b/zone/object.h index c7ebdd677..896fc4276 100644 --- a/zone/object.h +++ b/zone/object.h @@ -154,10 +154,14 @@ public: void SetX(float pos); void SetY(float pos); void SetZ(float pos); + void SetTiltX(float pos); + void SetTiltY(float pos); + float GetTiltX(); + float GetTiltY(); void SetModelName(const char* modelname); const char* GetModelName(); - uint16 GetSize(); - void SetSize(uint16 size); + float GetSize(); + void SetSize(float size); uint16 GetSolidType(); void SetSolidType(uint16 size); diff --git a/zone/perl_object.cpp b/zone/perl_object.cpp index be52fef1d..f8fc9a4ee 100644 --- a/zone/perl_object.cpp +++ b/zone/perl_object.cpp @@ -968,7 +968,7 @@ XS(XS_Object_GetSize) Perl_croak(aTHX_ "Usage: Object::GetSize(THIS)"); { Object * THIS; - uint16 RETVAL; + float RETVAL; dXSTARG; if (sv_derived_from(ST(0), "Object")) { @@ -981,7 +981,7 @@ XS(XS_Object_GetSize) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); RETVAL = THIS->GetSize(); - XSprePUSH; PUSHu((UV)RETVAL); + XSprePUSH; PUSHn((double)RETVAL); } XSRETURN(1); } @@ -995,7 +995,7 @@ XS(XS_Object_SetSize) Perl_croak(aTHX_ "Usage: Object::SetSize(THIS, type)"); { Object * THIS; - uint16 size = (uint16)SvUV(ST(1)); + float size = (float)SvNV(ST(1)); if (sv_derived_from(ST(0), "Object")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -1011,6 +1011,106 @@ XS(XS_Object_SetSize) XSRETURN_EMPTY; } +XS(XS_Object_SetTiltX); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Object_SetTiltX) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Object::SetTiltX(THIS, pos)"); + { + Object * THIS; + float pos = (float)SvNV(ST(1)); + + if (sv_derived_from(ST(0), "Object")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Object *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Object"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetTiltX(pos); + } + XSRETURN_EMPTY; +} + +XS(XS_Object_SetTiltY); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Object_SetTiltY) +{ + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Object::SetTiltY(THIS, pos)"); + { + Object * THIS; + float pos = (float)SvNV(ST(1)); + + if (sv_derived_from(ST(0), "Object")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Object *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Object"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->SetTiltY(pos); + } + XSRETURN_EMPTY; +} + +XS(XS_Object_GetTiltX); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Object_GetTiltX) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Object::GetSize(THIS)"); + { + Object * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "Object")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Object *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Object"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetTiltX(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Object_GetTiltY); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Object_GetTiltY) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Object::GetSize(THIS)"); + { + Object * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "Object")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Object *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Object"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetTiltY(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -1066,6 +1166,10 @@ XS(boot_Object) newXSproto(strcpy(buf, "GetSolidType"),XS_Object_GetSolidType, file, "$"); newXSproto(strcpy(buf, "SetSize"),XS_Object_SetSize, file, "$$"); newXSproto(strcpy(buf, "GetSize"),XS_Object_GetSize, file, "$"); + newXSproto(strcpy(buf, "SetTiltX"),XS_Object_SetTiltX, file, "$$"); + newXSproto(strcpy(buf, "SetTiltY"),XS_Object_SetTiltY, file, "$"); + newXSproto(strcpy(buf, "GetTiltX"),XS_Object_GetTiltX, file, "$$"); + newXSproto(strcpy(buf, "GetTiltY"),XS_Object_GetTiltY, file, "$"); XSRETURN_YES; } #endif //EMBPERL_XS_CLASSES diff --git a/zone/zone.cpp b/zone/zone.cpp index 1165d7e9b..3dd8e55d8 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -161,7 +161,8 @@ bool Zone::LoadZoneObjects() { std::string query = StringFormat("SELECT id, zoneid, xpos, ypos, zpos, heading, " "itemid, charges, objectname, type, icon, unknown08, " - "unknown10, unknown20, unknown24, unknown76 fROM object " + "unknown10, unknown20, unknown24, unknown76, size, tilt_x, " + "tilt_y FROM object " "WHERE zoneid = %i AND (version = %u OR version = -1)", zoneid, instanceversion); auto results = database.QueryDatabase(query); @@ -241,11 +242,14 @@ bool Zone::LoadZoneObjects() { data.object_type = type; data.linked_list_addr[0] = 0; data.linked_list_addr[1] = 0; - data.size = (uint32)atoi(row[11]); + data.solidtype = (uint32)atoi(row[12]); data.unknown020 = (uint32)atoi(row[13]); data.unknown024 = (uint32)atoi(row[14]); data.unknown076 = (uint32)atoi(row[15]); + data.size = atof(row[16]); + data.tilt_x = atof(row[17]); + data.tilt_y = atof(row[18]); data.unknown084 = 0; ItemInst* inst = nullptr; From 3f8ff1373ce39948713f0194238f0b4941126981 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 26 Aug 2016 15:02:12 -0500 Subject: [PATCH 331/693] Fix script call issue [skip ci] --- common/database_conversions.cpp | 2 +- utils/scripts/eqemu_server.pl | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index 406995b34..c282acc94 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -478,7 +478,7 @@ bool Database::CheckDatabaseConversions() { #ifdef _WIN32 system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl'); if ($response->is_success){ open(FILE, '> eqemu_server.pl'); print FILE $response->decoded_content; close(FILE); }\""); #else - system("wget --no-check-certificate -O eqemu_update.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl"); + system("wget --no-check-certificate -O eqemu_server.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl"); #endif } diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 47955266d..39c2a9fd3 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -86,7 +86,7 @@ mkdir('db_update'); #::: Check if db_version table exists... if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ print get_mysql_result("DROP TABLE db_version"); - print "Old db_version table present, dropping...\n\n"; + print "[Database] Old db_version table present, dropping...\n\n"; } sub check_db_version_table{ @@ -96,7 +96,7 @@ sub check_db_version_table{ version int(11) DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO db_version (version) VALUES ('1000');"); - print "Table 'db_version' does not exists.... Creating...\n\n"; + print "[Database] Table 'db_version' does not exists.... Creating...\n\n"; } } @@ -853,7 +853,7 @@ sub do_windows_login_server_setup { sub do_linux_login_server_setup { for my $file (@files) { - $destination_file = $file; + $destination_file = $file; $destination_file =~s/updates_staged\/login_server\///g; print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, $destination_file); @@ -1277,7 +1277,7 @@ sub unzip { unless ( $zip->read($archive_to_unzip) == AZ_OK ) { die 'read error'; } - print "Extracting...\n"; + print "[Unzip] Extracting...\n"; $zip->extractTree('', $dest_folder); } if($OS eq "Linux"){ @@ -1512,7 +1512,7 @@ sub get_bots_db_version{ #::: Check if bots_version column exists... if(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db){ print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;"); - print "\nColumn 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; + print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; } $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); return $bots_local_db_version; @@ -1528,7 +1528,7 @@ sub bots_db_management{ } if($bin_db_ver == 0){ - print "Your server binaries (world/zone) are not compiled for bots...\n\n"; + print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n"; return; } From 28c5b326247b4764351bf997bcb246f22a202a35 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Fri, 26 Aug 2016 18:01:34 -0400 Subject: [PATCH 332/693] Modified quantity in Merchant_Sell_Struct to be uint32 in accordance with Merchant_Purchase_Struct. This will allow you to buy stacks of items beyond 255. (Tested with a stack of 1,000 Arrows.) --- common/eq_packet_structs.h | 3 +-- common/patches/sod_structs.h | 3 +-- common/patches/sof_structs.h | 3 +-- common/patches/titanium_structs.h | 3 +-- common/patches/uf_structs.h | 3 +-- 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index cf411ef72..fec5af412 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1934,8 +1934,7 @@ struct Merchant_Sell_Struct { /*004*/ uint32 playerid; // Player's entity id /*008*/ uint32 itemslot; uint32 unknown12; -/*016*/ uint8 quantity; // Already sold -/*017*/ uint8 Unknown016[3]; +/*016*/ uint32 quantity; /*020*/ uint32 price; }; struct Merchant_Purchase_Struct { diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 6a73b7283..bd428c653 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1880,8 +1880,7 @@ struct Merchant_Sell_Struct { /*004*/ uint32 playerid; // Player's entity id /*008*/ uint32 itemslot; /*012*/ uint32 unknown12; -/*016*/ uint8 quantity; // Already sold -/*017*/ uint8 Unknown017[3]; +/*016*/ uint32 quantity; /*020*/ uint32 Unknown020; /*024*/ uint32 price; /*028*/ uint32 pricehighorderbits; // It appears the price is 64 bits in SoD+ diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 0256132bd..3c0861f42 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1859,8 +1859,7 @@ struct Merchant_Sell_Struct { /*004*/ uint32 playerid; // Player's entity id /*008*/ uint32 itemslot; uint32 unknown12; -/*016*/ uint8 quantity; // Already sold -/*017*/ uint8 Unknown016[3]; +/*016*/ uint32 quantity; /*020*/ uint32 price; }; struct Merchant_Purchase_Struct { diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 8d258871f..c6a5e6a49 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -1657,8 +1657,7 @@ struct Merchant_Sell_Struct { /*004*/ uint32 playerid; // Player's entity id /*008*/ uint32 itemslot; uint32 unknown12; -/*016*/ uint8 quantity; // Already sold -/*017*/ uint8 Unknown016[3]; +/*016*/ uint32 quantity; /*020*/ uint32 price; }; struct Merchant_Purchase_Struct { diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 46e5b21cb..1ba5616dd 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1921,8 +1921,7 @@ struct Merchant_Sell_Struct { /*004*/ uint32 playerid; // Player's entity id /*008*/ uint32 itemslot; /*012*/ uint32 unknown12; -/*016*/ uint8 quantity; // Already sold -/*017*/ uint8 Unknown017[3]; +/*016*/ uint32 quantity; /*020*/ uint32 Unknown020; /*024*/ uint32 price; /*028*/ uint32 pricehighorderbits; // It appears the price is 64 bits in Underfoot+ From db380944ac0191f2ae5090f384354b1a7453230e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Aug 2016 00:46:45 -0500 Subject: [PATCH 333/693] Prevent horses (player mounts) from being depopped during a #repop --- zone/entity.cpp | 3 +++ zone/horse.cpp | 2 ++ zone/mob.h | 2 ++ 3 files changed, 7 insertions(+) diff --git a/zone/entity.cpp b/zone/entity.cpp index 08e1534c8..4eda2e75e 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2510,6 +2510,9 @@ void EntityList::Depop(bool StartSpawnTimer) if (own && own->IsClient()) continue; + if (pnpc->IsHorse) + continue; + if (pnpc->IsFindable()) UpdateFindableNPCState(pnpc, true); diff --git a/zone/horse.cpp b/zone/horse.cpp index a2cebcdc9..2d1f04f01 100644 --- a/zone/horse.cpp +++ b/zone/horse.cpp @@ -36,6 +36,8 @@ Horse::Horse(Client *_owner, uint16 spell_id, const glm::vec4& position) strn0cpy(name, _owner->GetCleanName(), 55); strcat(name,"`s_Mount00"); + is_horse = true; + owner = _owner; } diff --git a/zone/mob.h b/zone/mob.h index 22e4bf357..4c09dc200 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1405,6 +1405,8 @@ protected: std::unordered_map> aa_ranks; Timer aa_timers[aaTimerMax]; + bool is_horse; + private: void _StopSong(); //this is not what you think it is Mob* target; From 2dee62c850233f34ffe3fc35f8f143dd885dd3f1 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Aug 2016 00:47:55 -0500 Subject: [PATCH 334/693] Refactor didn't save (oops) --- zone/horse.cpp | 2 +- zone/mob.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/horse.cpp b/zone/horse.cpp index 2d1f04f01..62254a6b0 100644 --- a/zone/horse.cpp +++ b/zone/horse.cpp @@ -36,7 +36,7 @@ Horse::Horse(Client *_owner, uint16 spell_id, const glm::vec4& position) strn0cpy(name, _owner->GetCleanName(), 55); strcat(name,"`s_Mount00"); - is_horse = true; + IsHorse = true; owner = _owner; } diff --git a/zone/mob.h b/zone/mob.h index 4c09dc200..c09da4e0b 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1405,7 +1405,7 @@ protected: std::unordered_map> aa_ranks; Timer aa_timers[aaTimerMax]; - bool is_horse; + bool IsHorse; private: void _StopSong(); //this is not what you think it is From f2a075d43249a4390864d3c43a5b0f245071de45 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Aug 2016 00:52:48 -0500 Subject: [PATCH 335/693] Keep eqemu_server.pl from chown'ing the script to a pre-fixed user [skip ci] --- utils/scripts/eqemu_server.pl | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index e91df2914..fb8bf6e00 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -298,7 +298,6 @@ sub do_self_update_check_routine { copy_file($file, $destination_file); if($OS eq "Linux"){ system("chmod 755 eqemu_server.pl"); - system("chown eqemu eqemu_server.pl"); } system("perl eqemu_server.pl start_from_world"); } From 32c4c360bd35845c1c0dcf7ad03614b6378f35f7 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Aug 2016 01:21:23 -0500 Subject: [PATCH 336/693] Add IsHorse to default false in Mob constructor --- utils/scripts/eqemu_update.pl | 1205 ++++++++++++++------------------- zone/mob.cpp | 3 + 2 files changed, 495 insertions(+), 713 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index e794a3710..a7da3c792 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -1,56 +1,74 @@ #!/usr/bin/perl ########################################################### -#::: General EQEmu Server Administration Script -#::: Purpose - Handles: -#::: Automatic database versioning (bots and normal DB) -#::: Updating server assets (binary, opcodes, maps, configuration files) -#::: Original Author: Akkadius -#::: Contributors: Uleat +#::: Automatic (Database) Upgrade Script +#::: Author: Akkadius #::: Purpose: To upgrade databases with ease and maintain versioning ########################################################### +$menu_displayed = 0; + use Config; use File::Copy qw(copy); use POSIX qw(strftime); use File::Path; use File::Find; -use Time::HiRes qw(usleep); +use URI::Escape; +use Time::HiRes qw(usleep); -#::: Variables -$install_repository_request_url = "https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/"; -$eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/master/"; - -#::: Globals $time_stamp = strftime('%m-%d-%Y', gmtime()); -$db_run_stage = 0; #::: Sets database run stage check + $console_output .= " Operating System is: $Config{osname}\n"; if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } -$has_internet_connection = check_internet_connection(); -#::: Check for script self update -do_self_update_check_routine(); +#::: If current version is less than what world is reporting, then download a new one... +$current_version = 14; -print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n"; +if($ARGV[0] eq "V"){ + if($ARGV[1] > $current_version){ + print "eqemu_update.pl Automatic Database Upgrade Needs updating...\n"; + print " Current version: " . $current_version . "\n"; + print " New version: " . $ARGV[1] . "\n"; + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); + exit; + } + else{ + print "[Upgrade Script] No script update necessary \n"; + } + exit; +} + +#::: Sets database run stage check +$db_run_stage = 0; -#::: Check Perl version $perl_version = $^V; $perl_version =~s/v//g; -print "[Update] Perl Version is " . $perl_version . "\n"; -if($perl_version > 5.12){ - no warnings 'uninitialized'; -} +print "Perl Version is " . $perl_version . "\n"; +if($perl_version > 5.12){ no warnings 'uninitialized'; } no warnings; -#::: Remove old eqemu_update.pl -if(-e "eqemu_update.pl"){ - unlink("eqemu_update.pl"); -} - ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); -read_eqemu_config_xml(); +my $confile = "eqemu_config.xml"; #default +open(F, "<$confile"); +my $indb = 0; +while() { + s/\r//g; + if(//i) { $indb = 1; } + next unless($indb == 1); + if(/<\/database>/i) { $indb = 0; last; } + if(/(.*)<\/host>/i) { $host = $1; } + elsif(/(.*)<\/username>/i) { $user = $1; } + elsif(/(.*)<\/password>/i) { $pass = $1; } + elsif(/(.*)<\/db>/i) { $db = $1; } +} + +$console_output = +"============================================================ + EQEmu: Automatic Upgrade Check +============================================================ +"; if($OS eq "Windows"){ $has_mysql_path = `echo %PATH%`; @@ -63,6 +81,9 @@ if($OS eq "Windows"){ last; } } + $console_output .= " (Windows) MySQL is in system path \n"; + $console_output .= " Path = " . $path . "\n"; + $console_output .= "============================================================\n"; } } @@ -70,14 +91,101 @@ if($OS eq "Windows"){ if($OS eq "Linux"){ $path = `which mysql`; if ($path eq "") { - $path = `which mariadb`; + $path = `which mariadb`; } $path =~s/\n//g; + + $console_output .= " (Linux) MySQL is in system path \n"; + $console_output .= " Path = " . $path . "\n"; + $console_output .= "============================================================\n"; } #::: Path not found, error and exit if($path eq ""){ - print "[Error:eqemu_server.pl] MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; + print "MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; + print "script_exiting...\n"; + exit; +} + +if($ARGV[0] eq "install_peq_db"){ + + $db_name = "peq"; + if($ARGV[1]){ + $db_name = $ARGV[1]; + } + + $db = $db_name; + + #::: Database Routines + print "MariaDB :: Creating Database '" . $db_name . "'\n"; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; + if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } + if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } + $bin_db_ver = trim($db_version[1]); + check_db_version_table(); + $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + fetch_peq_db_full(); + print "\nFetching Latest Database Updates...\n"; + main_db_management(); + print "\nApplying Latest Database Updates...\n"; + main_db_management(); + + print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); +} + +if($ARGV[0] eq "remove_duplicate_rules"){ + remove_duplicate_rule_values(); + exit; +} + +if($ARGV[0] eq "installer"){ + print "Running EQEmu Server installer routines...\n"; + mkdir('logs'); + mkdir('updates_staged'); + mkdir('shared'); + fetch_latest_windows_binaries(); + map_files_fetch_bulk(); + opcodes_fetch(); + plugins_fetch(); + quest_files_fetch(); + lua_modules_fetch(); + + #::: Binary dll's + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); + + #::: Server scripts + fetch_utility_scripts(); + + #::: Database Routines + print "MariaDB :: Creating Database 'peq'\n"; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS peq;"`; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE peq"`; + if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } + if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } + $bin_db_ver = trim($db_version[1]); + check_db_version_table(); + $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + fetch_peq_db_full(); + print "\nFetching Latest Database Updates...\n"; + main_db_management(); + print "\nApplying Latest Database Updates...\n"; + main_db_management(); + + print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); + + if($OS eq "Windows"){ + check_windows_firewall_rules(); + do_windows_login_server_setup(); + } + exit; +} + +if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } +if($ARGV[0] eq "login_server_setup"){ + do_windows_login_server_setup(); exit; } @@ -87,7 +195,7 @@ mkdir('db_update'); #::: Check if db_version table exists... if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ print get_mysql_result("DROP TABLE db_version"); - print "[Database] Old db_version table present, dropping...\n\n"; + print "Old db_version table present, dropping...\n\n"; } sub check_db_version_table{ @@ -97,7 +205,7 @@ sub check_db_version_table{ version int(11) DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO db_version (version) VALUES ('1000');"); - print "[Database] Table 'db_version' does not exists.... Creating...\n\n"; + print "Table 'db_version' does not exists.... Creating...\n\n"; } } @@ -110,406 +218,173 @@ $bin_db_ver = trim($db_version[1]); $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); #::: If ran from Linux startup script, supress output -if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_world"){ - print "[Update] Database up to date...\n"; +if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_start"){ + print "Database up to date...\n"; exit; } -else { - - #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup - if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){ - print "[Update] Database not up to date with binaries... Automatically updating...\n"; - print "[Update] Issuing database backup first...\n"; - database_dump_compress(); - print "[Update] Updating database...\n"; - sleep(1); - main_db_management(); - main_db_management(); - print "[Update] Continuing bootup\n"; - exit; - } - - #::: Make sure that we didn't pass any arugments to the script - if(!$ARGV[0]){ - if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } - show_menu_prompt(); - } +else{ + print $console_output if $db; } if($db){ - print "[Update] MySQL Path/Location: " . $path . "\n"; - print "[Update] Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; + print " Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; #::: Bots #::: Make sure we're running a bots binary to begin with if(trim($db_version[2]) > 0){ $bots_local_db_version = get_bots_db_version(); if($bots_local_db_version > 0){ - print "[Update] (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; + print " (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; } } - #::: If World ran this script, and our version is up to date, continue... + #::: If World ran this script, and our version is up to date, continue... if($bin_db_ver <= $local_db_ver && $ARGV[0] eq "ran_from_world"){ - print "[Update] Database up to Date: Continuing World Bootup...\n"; + print " Database up to Date: Continuing World Bootup...\n"; + print "============================================================\n"; exit; } -} -if($ARGV[0] eq "remove_duplicate_rules"){ - remove_duplicate_rule_values(); - exit; } -if($ARGV[0] eq "map_files_fetch_bulk"){ - map_files_fetch_bulk(); - exit; +if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){ + print "You have missing database updates, type 1 or 2 to backup your database before running them as recommended...\n\n"; + #::: Display Menu + show_menu_prompt(); +} +else{ + #::: Most likely ran standalone + print "\n"; + show_menu_prompt(); } -if($ARGV[0] eq "loginserver_install_linux"){ - do_linux_login_server_setup(); - exit; -} - -if($ARGV[0] eq "installer"){ - print "[Install] Running EQEmu Server installer routines...\n"; - - #::: Make some local server directories... - mkdir('logs'); - mkdir('updates_staged'); - mkdir('shared'); - - do_install_config_xml(); - read_eqemu_config_xml(); - get_installation_variables(); - - $db_name = "peq"; - if($installation_variables{"mysql_eqemu_db_name"}){ - $db_name = $installation_variables{"mysql_eqemu_db_name"}; - } - - #::: Download assets - if($OS eq "Windows"){ - fetch_latest_windows_binaries(); - get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); - get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); - get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); - } - map_files_fetch_bulk(); - opcodes_fetch(); - plugins_fetch(); - quest_files_fetch(); - lua_modules_fetch(); - fetch_utility_scripts(); - - #::: Database Routines - print "[Database] Creating Database '" . $db_name . "'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; - - #::: Get Binary DB version - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - - #::: Local DB Version - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - - #::: Download PEQ latest - fetch_peq_db_full(); - print "[Database] Fetching Latest Database Updates...\n"; - main_db_management(); - print "[Database] Applying Latest Database Updates...\n"; - main_db_management(); - - if($OS eq "Windows"){ - check_windows_firewall_rules(); - do_windows_login_server_setup(); - } - if($OS eq "Linux"){ - do_linux_login_server_setup(); - - print "[Install] Installation complete!\n"; - } - - exit; -} - -if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } -if($ARGV[0] eq "login_server_setup"){ - do_windows_login_server_setup(); - exit; -} - -sub check_internet_connection { - if($OS eq "Linux"){ - $count = "c"; - } - if($OS eq "Windows"){ - $count = "n"; - } - - if (`ping 8.8.8.8 -$count 1 -w 500`=~/Reply from|1 received/i) { - # print "[Update] We have a connection to the internet, continuing...\n"; - return 1; - } - elsif (`ping 4.2.2.2 -$count 1 -w 500`=~/Reply from|1 received/i) { - # print "[Update] We have a connection to the internet, continuing...\n"; - return 1; - } - else{ - print "[Update] No connection to the internet, can't check update\n"; - return; - } -} - -sub do_self_update_check_routine { - #::: Check Version passed from world to update script - get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); - - if(!$has_internet_connection){ - print "[Update] Cannot check update without internet connection...\n"; - return; - } - - if(-e "updates_staged/eqemu_server.pl") { - - my $remote_script_size = -s "updates_staged/eqemu_server.pl"; - my $local_script_size = -s "eqemu_server.pl"; - - if($remote_script_size != $local_script_size){ - print "[Update] Script has been updated, updating...\n"; - - my @files; - my $start_dir = "updates_staged/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - if($file=~/eqemu_server/i){ - $destination_file = $file; - $destination_file =~s/updates_staged\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - unlink($destination_file); - copy_file($file, $destination_file); - if($OS eq "Linux"){ - system("chmod 755 eqemu_server.pl"); - system("chown eqemu eqemu_server.pl"); - } - system("perl eqemu_server.pl start_from_world"); - } - } - print "[Install] Done\n"; - } - else { - print "[Update] No script update necessary...\n"; - } - - unlink("updates_staged/eqemu_server.pl"); - } -} - -sub get_installation_variables{ - #::: Fetch installation variables before building the config - open (INSTALL_VARS, "../install_variables.txt"); - while (){ - chomp; - $o = $_; - @data = split(":", $o); - $installation_variables{trim($data[0])} = trim($data[1]); - } - close (INSTALL_VARS); -} - -sub do_install_config_xml { - get_installation_variables(); - - #::: Fetch XML template - get_remote_file($install_repository_request_url . "eqemu_config.xml", "eqemu_config_template.xml"); - - #::: Open new config file - open (NEW_CONFIG, '>', 'eqemu_config.xml'); - - $in_database_tag = 0; - - #::: Iterate through template and replace variables... - open (FILE_TEMPLATE, "eqemu_config_template.xml"); - while (){ - chomp; - $o = $_; - - #::: Find replace variables - - if($o=~/\<\!--/i){ - next; - } - - if($o=~/database/i && $o=~/\<\//i){ - $in_database_tag = 0; - } - if($o=~/database/i){ - $in_database_tag = 1; - } - - if($o=~/key/i){ - my($replace_key) = $o =~ />(\w+)/i && $in_database_tag){ - my($replace_username) = $o =~ />(\w+)/i && $in_database_tag){ - my($replace_password) = $o =~ />(\w+)/i){ - my($replace_db_name) = $o =~ />(\w+) \&database_dump, + 2 => \&database_dump_compress, + 3 => \&main_db_management, + 4 => \&bots_db_management, + 5 => \&opcodes_fetch, + 6 => \&map_files_fetch, + 7 => \&plugins_fetch, + 8 => \&quest_files_fetch, + 9 => \&lua_modules_fetch, + 10 => \&aa_fetch, + 11 => \&fetch_latest_windows_binaries, + 12 => \&fetch_server_dlls, + 13 => \&do_windows_login_server_setup, + 14 => \&remove_duplicate_rule_values, + 15 => \&fetch_utility_scripts, + 18 => \&fetch_latest_windows_binaries_bots, + 19 => \&do_bots_db_schema_drop, + 20 => \&do_update_self, + 21 => \&database_dump_player_tables, + 0 => \&script_exit, + ); - $dc = 0; - while (1) { - $input = trim($input); - - $errored_command = 0; - - if($input eq "database"){ - print "\n>>> Database Menu\n\n"; - print " [backup_database] Back up database to backups/ directory\n"; - print " [backup_player_tables] Back up player tables to backups/ directory\n"; - print " [backup_database_compressed] Back up database compressed to backups/ directory\n"; - print " \n"; - print " [check_db_updates] Checks for database updates manually\n"; - print " [check_bot_db_updates] Checks for bot database updates\n"; - print " \n"; - print " [aa_tables] Downloads and installs clean slate AA data from PEQ\n"; - print " [remove_duplicate_rules] Removes duplicate rules from rule_values table\n"; - print " [drop_bots_db_schema] Removes bot database schema\n"; - - print " \n> main - go back to main menu\n"; - print "Enter a command #> "; - $last_menu = trim($input); - } - elsif($input eq "assets"){ - print "\n>>> Server Assets Menu\n\n"; - print " [maps] Download latest maps\n"; - print " [opcodes] Download opcodes (Patches for eq clients)\n"; - print " [quests] Download latest quests\n"; - print " [plugins] Download latest plugins\n"; - print " [lua_modules] Download latest lua_modules\n"; - print " [utility_scripts] Download utility scripts to run and operate the EQEmu Server\n"; - if($OS eq "Windows"){ - print "--- Windows\n"; - print " windows_server_download Updates server code from latest stable\n"; - print " windows_server_download_bots Updates server code (bots enabled) from latest\n"; - print " fetch_dlls Grabs dll's needed to run windows binaries\n"; - print " setup_loginserver Sets up loginserver for Windows\n"; + while (1) { + { + local $| = 1; + if(!$menu_show && ($ARGV[0] eq "ran_from_world" || $ARGV[0] eq "ran_from_start")){ + $menu_show++; + next; + } + print menu_options(), '> '; + $menu_displayed++; + if($menu_displayed > 50){ + print "Safety: Menu looping too many times, exiting...\n"; + exit; } - print " \n> main - go back to main menu\n"; - print "Enter a command #> "; - $last_menu = trim($input); } - elsif($input eq "backup_database"){ database_dump(); $dc = 1; } - elsif($input eq "backup_player_tables"){ database_dump_player_tables(); $dc = 1; } - elsif($input eq "backup_database_compressed"){ database_dump_compress(); $dc = 1; } - elsif($input eq "drop_bots_db_schema"){ do_bots_db_schema_drop(); $dc = 1; } - elsif($input eq "aa_tables"){ aa_fetch(); $dc = 1; } - elsif($input eq "remove_duplicate_rules"){ remove_duplicate_rule_values(); $dc = 1; } - elsif($input eq "maps"){ map_files_fetch_bulk(); $dc = 1; } - elsif($input eq "opcodes"){ opcodes_fetch(); $dc = 1; } - elsif($input eq "plugins"){ plugins_fetch(); $dc = 1; } - elsif($input eq "quests"){ quest_files_fetch(); $dc = 1; } - elsif($input eq "lua_modules"){ lua_modules_fetch(); $dc = 1; } - elsif($input eq "windows_server_download"){ fetch_latest_windows_binaries(); $dc = 1; } - elsif($input eq "windows_server_download_bots"){ fetch_latest_windows_binaries_bots(); $dc = 1; } - elsif($input eq "fetch_dlls"){ fetch_server_dlls(); $dc = 1; } - elsif($input eq "utility_scripts"){ fetch_utility_scripts(); $dc = 1; } - elsif($input eq "check_db_updates"){ main_db_management(); $dc = 1; } - elsif($input eq "check_bot_db_updates"){ bots_db_management(); $dc = 1; } - elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; } - elsif($input eq "exit"){ - exit; - } - elsif($input eq "main"){ - print "Returning to main menu...\n"; - print_main_menu(); - $last_menu = trim($input); - } - elsif($input eq "" && $last_menu ne ""){ - $errored_command = 1; - } - elsif($input ne ""){ - print "Invalid command '" . $input . "'\n"; - $errored_command = 1; + + my $choice = <>; + + $choice =~ s/\A\s+//; + $choice =~ s/\s+\z//; + + if (defined(my $handler = $dispatch{$choice})) { + my $result = $handler->(); + unless (defined $result) { + exit 0; + } } else { - print_main_menu(); - } - - #::: Errored command checking - if($errored_command == 1){ - $input = $last_menu; - } - elsif($dc == 1){ - $dc = 0; - $input = ""; - } - else { - $input = <>; + if($ARGV[0] ne "ran_from_world"){ + # warn "\n\nInvalid selection\n\n"; + } } } } -sub print_main_menu { - print "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"; - print ">>> EQEmu Server Main Menu >>>>>>>>>>>>\n"; - print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"; - print " [database] Enter database management menu \n"; - print " [assets] Manage server assets \n\n"; - print " exit \n"; - print "\n"; - print "Enter a command #> "; +sub menu_options { + if(@total_updates){ + if($bots_db_management == 1){ + $option[3] = "Check and stage pending REQUIRED Database updates"; + $bots_management = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; + } + else{ + $option[3] = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; + if(get_mysql_result("SHOW TABLES LIKE 'bots'") eq ""){ + $bots_management = "Install bots database pre-requisites (Requires bots server binaries)"; + } + else{ + $bots_management = "Check for Bot pending REQUIRED database updates... (Must have bots enabled)"; + } + } + } + else{ + $option[3] = "Check and stage pending REQUIRED Database updates"; + $bots_management = "Check for Bot REQUIRED database updates... (Must have bots enabled)"; + } + +return <; #Read from STDIN @@ -553,7 +432,7 @@ sub database_dump_player_tables { sub database_dump_compress { check_for_database_dump_script(); - print "[Database] Performing database backup....\n"; + print "Performing database backup....\n"; print `perl db_dumper.pl database="$db" loc="backups" compress`; } @@ -581,40 +460,30 @@ sub get_mysql_result_from_file{ if($OS eq "Linux"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } } -#::: Gets Remote File based on request_url (1st Arg), and saves to destination file (2nd Arg) -#::: Example: get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); +#::: Gets Remote File based on URL (1st Arg), and saves to destination file (2nd Arg) +#::: Example: get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); sub get_remote_file{ - my $request_url = $_[0]; - my $destination_file = $_[1]; + my $URL = $_[0]; + my $Dest_File = $_[1]; my $content_type = $_[2]; - my $no_retry = $_[3]; - my $silent_download = $_[4]; - - if(!$has_internet_connection){ - print "[Download] Cannot download without internet connection...\n"; - return; - } #::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary - - if($destination_file=~/\//i){ - my @directory_path = split('/', $destination_file); + if($Dest_File=~/\//i){ + my @dir_path = split('/', $Dest_File); $build_path = ""; - $directory_index = 0; - while($directory_path[$directory_index] && $directory_path[$directory_index + 1]){ - $build_path .= $directory_path[$directory_index] . "/"; - # print "checking '" . $build_path . "'\n"; + $di = 0; + while($dir_path[$di]){ + $build_path .= $dir_path[$di] . "/"; #::: If path does not exist, create the directory... - if (!-d $build_path) { - print "[Copy] folder doesn't exist, creating '" . $build_path . "'\n"; + if (!-d $build_path) { mkdir($build_path); } - if(!$directory_indexr_path[$directory_index + 2] && $directory_indexr_path[$directory_index + 1]){ + if(!$dir_path[$di + 2] && $dir_path[$di + 1]){ # print $actual_path . "\n"; $actual_path = $build_path; last; } - $directory_index++; + $di++; } } @@ -623,59 +492,51 @@ sub get_remote_file{ if($content_type == 1){ $break = 0; while($break == 0) { - eval "use LWP::Simple qw(getstore);"; - # use LWP::Simple qw(getstore); - # print "request is " . $request_url . "\n"; - # print "destination file is supposed to be " . $destination_file . "\n"; - if(!getstore($request_url, $destination_file)){ - print "[Download] Error, no connection or failed request...\n\n"; + use LWP::Simple qw(getstore); + if(!getstore($URL, $Dest_File)){ + # print "Error, no connection or failed request...\n\n"; } # sleep(1); #::: Make sure the file exists before continuing... - if(-e $destination_file) { + if(-e $Dest_File) { $break = 1; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; + print " [URL] :: " . $URL . "\n"; + print " [Saved] :: " . $Dest_File . "\n"; } else { $break = 0; } usleep(500); - - if($no_retry){ - $break = 1; - } } } else{ $break = 0; while($break == 0) { require LWP::UserAgent; - my $ua = LWP::UserAgent->new; + my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; - my $response = $ua->get($request_url); + my $response = $ua->get($URL); if ($response->is_success){ - open (FILE, '> ' . $destination_file . ''); + open (FILE, '> ' . $Dest_File . ''); print FILE $response->decoded_content; close (FILE); } else { - print "[Download] Error, no connection or failed request...\n\n"; + # print "Error, no connection or failed request...\n\n"; } - if(-e $destination_file) { + if(-e $Dest_File) { $break = 1; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; + print " [URL] :: " . $URL . "\n"; + print " [Saved] :: " . $Dest_File . "\n"; } else { $break = 0; } usleep(500); - - if($no_retry){ - $break = 1; - } } } } if($OS eq "Linux"){ #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt - $wget = `wget --no-check-certificate --quiet -O $destination_file $request_url`; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; - if($wget=~/unable to resolve/i){ + $wget = `wget --no-check-certificate --quiet -O $Dest_File $URL`; + print " o URL: (" . $URL . ")\n"; + print " o Saved: (" . $Dest_File . ") \n"; + if($wget=~/unable to resolve/i){ print "Error, no connection or failed request...\n\n"; #die; } @@ -690,22 +551,6 @@ sub trim { return $string; } -sub read_eqemu_config_xml { - my $confile = "eqemu_config.xml"; #default - open(F, "<$confile"); - my $indb = 0; - while() { - s/\r//g; - if(//i) { $indb = 1; } - next unless($indb == 1); - if(/<\/database>/i) { $indb = 0; last; } - if(/(.*)<\/host>/i) { $host = $1; } - elsif(/(.*)<\/username>/i) { $user = $1; } - elsif(/(.*)<\/password>/i) { $pass = $1; } - elsif(/(.*)<\/db>/i) { $db = $1; } - } -} - #::: Fetch Latest PEQ AA's sub aa_fetch{ if(!$db){ @@ -713,48 +558,48 @@ sub aa_fetch{ return; } - print "[Install] Pulling down PEQ AA Tables...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); - print "[Install] Installing AA Tables...\n"; + print "Pulling down PEQ AA Tables...\n"; + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); + print "\n\nInstalling AA Tables...\n"; print get_mysql_result_from_file("db_update/peq_aa_tables_post_rework.sql"); - print "[Install] Done...\n\n"; + print "\nDone...\n\n"; } #::: Fetch Latest Opcodes sub opcodes_fetch{ - print "[Update] Pulling down latest opcodes...\n"; + print "Pulling down latest opcodes...\n"; %opcodes = ( - 1 => ["opcodes", $eqemu_repository_request_url . "utils/patches/opcodes.conf"], - 2 => ["mail_opcodes", $eqemu_repository_request_url . "utils/patches/mail_opcodes.conf"], - 3 => ["Titanium", $eqemu_repository_request_url . "utils/patches/patch_Titanium.conf"], - 4 => ["Secrets of Faydwer", $eqemu_repository_request_url . "utils/patches/patch_SoF.conf"], - 5 => ["Seeds of Destruction", $eqemu_repository_request_url . "utils/patches/patch_SoD.conf"], - 6 => ["Underfoot", $eqemu_repository_request_url . "utils/patches/patch_UF.conf"], - 7 => ["Rain of Fear", $eqemu_repository_request_url . "utils/patches/patch_RoF.conf"], - 8 => ["Rain of Fear 2", $eqemu_repository_request_url . "utils/patches/patch_RoF2.conf"], + 1 => ["opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/opcodes.conf"], + 2 => ["mail_opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/mail_opcodes.conf"], + 3 => ["Titanium", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Titanium.conf"], + 4 => ["Secrets of Faydwer", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoF.conf"], + 5 => ["Seeds of Destruction", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoD.conf"], + 6 => ["Underfoot", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_UF.conf"], + 7 => ["Rain of Fear", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF.conf"], + 8 => ["Rain of Fear 2", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF2.conf"], ); $loop = 1; while($opcodes{$loop}[0]){ - #::: Split the request_url by the patches folder to get the file name from request_url + #::: Split the URL by the patches folder to get the file name from URL @real_file = split("patches/", $opcodes{$loop}[1]); $find = 0; while($real_file[$find]){ $file_name = $real_file[$find]; $find++; } - + + print "\nDownloading (" . $opcodes{$loop}[0] . ") File: '" . $file_name . "'...\n\n"; get_remote_file($opcodes{$loop}[1], $file_name); $loop++; } - print "[Update] Done...\n"; + print "\nDone...\n\n"; } -sub remove_duplicate_rule_values { +sub remove_duplicate_rule_values{ $ruleset_id = trim(get_mysql_result("SELECT `ruleset_id` FROM `rule_sets` WHERE `name` = 'default'")); - print "[Database] Default Ruleset ID: " . $ruleset_id . "\n"; + print "Default Ruleset ID: " . $ruleset_id . "\n"; $total_removed = 0; - #::: Store Default values... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` = " . $ruleset_id); my @lines = split("\n", $mysql_result); @@ -762,51 +607,50 @@ sub remove_duplicate_rule_values { my @values = split("\t", $val); $rule_set_values{$values[1]}[0] = $values[2]; } - #::: Compare default values against other rulesets to check for duplicates... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` != " . $ruleset_id); my @lines = split("\n", $mysql_result); foreach my $val (@lines){ my @values = split("\t", $val); if($values[2] == $rule_set_values{$values[1]}[0]){ - print "[Database] Removing duplicate : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . "\n"; + print "DUPLICATE : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . ", removing...\n"; get_mysql_result("DELETE FROM `rule_values` WHERE `ruleset_id` = " . $values[0] . " AND `rule_name` = '" . $values[1] . "'"); $total_removed++; } } - print "[Database] Total duplicate rules removed... " . $total_removed . "\n"; + print "Total duplicate rules removed... " . $total_removed . "\n"; } -sub copy_file { +sub copy_file{ $l_source_file = $_[0]; - $l_destination_file = $_[1]; - if($l_destination_file=~/\//i){ - my @directory_path = split('/', $l_destination_file); + $l_dest_file = $_[1]; + if($l_dest_file=~/\//i){ + my @dir_path = split('/', $l_dest_file); $build_path = ""; - $directory_index = 0; - while($directory_path[$directory_index]){ - $build_path .= $directory_path[$directory_index] . "/"; + $di = 0; + while($dir_path[$di]){ + $build_path .= $dir_path[$di] . "/"; #::: If path does not exist, create the directory... if (!-d $build_path) { mkdir($build_path); } - if(!$directory_path[$directory_index + 2] && $directory_path[$directory_index + 1]){ + if(!$dir_path[$di + 2] && $dir_path[$di + 1]){ # print $actual_path . "\n"; $actual_path = $build_path; last; } - $directory_index++; + $di++; } } - copy $l_source_file, $l_destination_file; + copy $l_source_file, $l_dest_file; } -sub fetch_latest_windows_binaries { - print "[Update] Fetching Latest Windows Binaries... \n"; - get_remote_file($install_repository_request_url . "master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); - print "[Update] Fetched Latest Windows Binaries... \n"; - print "[Update] Extracting... --- \n"; +sub fetch_latest_windows_binaries{ + print "\n --- Fetching Latest Windows Binaries... --- \n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); + print "\n --- Fetched Latest Windows Binaries... --- \n"; + print "\n --- Extracting... --- \n"; unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; @@ -815,21 +659,21 @@ sub fetch_latest_windows_binaries { $start_dir ); for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/binaries\///g; - print "[Update] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); + $dest_file = $file; + $dest_file =~s/updates_staged\/binaries\///g; + print "Installing :: " . $dest_file . "\n"; + copy_file($file, $dest_file); } - print "[Update] Done\n"; + print "\n --- Done... --- \n"; rmtree('updates_staged'); } -sub fetch_latest_windows_binaries_bots { - print "[Update] Fetching Latest Windows Binaries with Bots...\n"; - get_remote_file($install_repository_request_url . "master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); - print "[Update] Fetched Latest Windows Binaries with Bots...\n"; - print "[Update] Extracting...\n"; +sub fetch_latest_windows_binaries_bots{ + print "\n --- Fetching Latest Windows Binaries with Bots... --- \n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); + print "\n --- Fetched Latest Windows Binaries with Bots... --- \n"; + print "\n --- Extracting... --- \n"; unzip('updates_staged/master_windows_build_bots.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; @@ -838,20 +682,20 @@ sub fetch_latest_windows_binaries_bots { $start_dir ); for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/binaries\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); + $dest_file = $file; + $dest_file =~s/updates_staged\/binaries\///g; + print "Installing :: " . $dest_file . "\n"; + copy_file($file, $dest_file); } - print "[Update] Done...\n"; + print "\n --- Done... --- \n"; rmtree('updates_staged'); } -sub do_windows_login_server_setup { - print "[Install] Fetching Loginserver... \n"; - get_remote_file($install_repository_request_url . "login_server.zip", "updates_staged/login_server.zip", 1); - print "[Install] Extracting... \n"; +sub do_windows_login_server_setup{ + print "\n --- Fetching Loginserver... --- \n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server.zip", "updates_staged/login_server.zip", 1); + print "\n --- Extracting... --- \n"; unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); my @files; my $start_dir = "updates_staged/login_server"; @@ -860,85 +704,31 @@ sub do_windows_login_server_setup { $start_dir ); for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/login_server\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); + $dest_file = $file; + $dest_file =~s/updates_staged\/login_server\///g; + print "Installing :: " . $dest_file . "\n"; + copy_file($file, $dest_file); } - print "[Install] Done... \n"; + print "\n Done... \n"; - print "[Install] Pulling down Loginserver database tables...\n"; - get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); - print "[Install] Installing Loginserver tables...\n"; + print "Pulling down Loginserver database tables...\n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server_tables.sql", "db_update/login_server_tables.sql"); + print "\n\nInstalling Loginserver tables...\n"; print get_mysql_result_from_file("db_update/login_server_tables.sql"); - print "[Install] Done...\n"; + print "\nDone...\n\n"; add_login_server_firewall_rules(); rmtree('updates_staged'); rmtree('db_update'); - print "[Install] Press any key to continue...\n"; - - <>; #Read from STDIN - -} - -sub do_linux_login_server_setup { - - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/login_server\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); - } - print "\n Done... \n"; - - print "[Install] Pulling down Loginserver database tables...\n"; - get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); - print "[Install] Installing Loginserver tables...\n"; - print get_mysql_result_from_file("db_update/login_server_tables.sql"); - print "[Install] Done...\n\n"; - - rmtree('updates_staged'); - rmtree('db_update'); - - get_remote_file($install_repository_request_url . "linux/login.ini", "login_template.ini"); - get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes.conf"); - get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes_sod.conf"); - - get_installation_variables(); - my $db_name = $installation_variables{"mysql_eqemu_db_name"}; - my $db_user = $installation_variables{"mysql_eqemu_user"}; - my $db_password = $installation_variables{"mysql_eqemu_password"}; - - #::: Open new config file - open (NEW_CONFIG, '>', 'login.ini'); - - #::: Iterate through template and replace variables... - open (FILE_TEMPLATE, "login_template.ini"); - while (){ - chomp; - $o = $_; - #::: Find replace variables - if($o=~/db/i){ $o = "db = " . $db_name; } - if($o=~/user/i){ $o = "user = " . $db_user; } - if($o=~/password/i){ $o = "password = " . $db_password; } - - print NEW_CONFIG $o . "\n"; - } - - close(FILE_TEMPLATE); - close(NEW_CONFIG); - unlink("login_template.ini"); - - print "[Install] Press any key to continue...\n"; + print "\nPress any key to continue...\n"; <>; #Read from STDIN } -sub add_login_server_firewall_rules { +sub add_login_server_firewall_rules{ #::: Check Loginserver Firewall install for Windows if($OS eq "Windows"){ $output = `netsh advfirewall firewall show rule name=all`; @@ -960,22 +750,22 @@ sub add_login_server_firewall_rules { } if($has_loginserver_rules_titanium == 0){ - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; + print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) TCP" dir=in action=allow protocol=TCP localport=5998`; - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; + print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) UDP" dir=in action=allow protocol=UDP localport=5998`; } if($has_loginserver_rules_sod == 0){ - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; + print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) TCP" dir=in action=allow protocol=TCP localport=5999`; - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; + print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) UDP" dir=in action=allow protocol=UDP localport=5999`; } - print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n"; + print "If firewall rules don't add you must run this script (eqemu_update.pl) as administrator\n"; print "\n"; - print "[Install] Instructions \n"; - print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; + print "#::: Instructions \n"; + print "In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; print " login.eqemulator.net @@ -990,7 +780,7 @@ sub add_login_server_firewall_rules { "; - print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; + print "\nWhen done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; } } @@ -1004,84 +794,84 @@ sub check_windows_firewall_rules{ $val=~s/Rule Name://g; if($val=~/EQEmu World/i){ $has_world_rules = 1; - print "[Install] Found existing rule :: " . trim($val) . "\n"; + print "Found existing rule :: " . trim($val) . "\n"; } if($val=~/EQEmu Zone/i){ $has_zone_rules = 1; - print "[Install] Found existing rule :: " . trim($val) . "\n"; + print "Found existing rule :: " . trim($val) . "\n"; } } } if($has_world_rules == 0){ - print "[Install] Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; + print "Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; print `netsh advfirewall firewall add rule name="EQEmu World (9000) TCP" dir=in action=allow protocol=TCP localport=9000`; - print "[Install] Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; + print "Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; print `netsh advfirewall firewall add rule name="EQEmu World (9000) UDP" dir=in action=allow protocol=UDP localport=9000`; } if($has_zone_rules == 0){ - print "[Install] Attempting to add EQEmu Zones (7000-7500) TCP \n"; + print "Attempting to add EQEmu Zones (7000-7500) TCP \n"; print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) TCP" dir=in action=allow protocol=TCP localport=7000-7500`; - print "[Install] Attempting to add EQEmu Zones (7000-7500) UDP \n"; + print "Attempting to add EQEmu Zones (7000-7500) UDP \n"; print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) UDP" dir=in action=allow protocol=UDP localport=7000-7500`; } } sub fetch_server_dlls{ - print "[Download] Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; - get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); - get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); - get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); + print "Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); } sub fetch_peq_db_full{ - print "[Install] Downloading latest PEQ Database... Please wait...\n"; + print "Downloading latest PEQ Database... Please wait...\n"; get_remote_file("http://edit.peqtgc.com/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1); - print "[Install] Downloaded latest PEQ Database... Extracting...\n"; + print "Downloaded latest PEQ Database... Extracting...\n"; unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); - my $start_dir = "updates_staged/peq_db"; + my $start_dir = "updates_staged\\peq_db"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/peq_db\///g; + $dest_file = $file; + $dest_file =~s/updates_staged\\peq_db\///g; if($file=~/peqbeta|player_tables/i){ - print "[Install] DB :: Installing :: " . $destination_file . "\n"; + print "MariaDB :: Installing :: " . $dest_file . "\n"; get_mysql_result_from_file($file); } if($file=~/eqtime/i){ - print "[Install] Installing eqtime.cfg\n"; + print "Installing eqtime.cfg\n"; copy_file($file, "eqtime.cfg"); } } } sub map_files_fetch_bulk{ - print "[Install] Fetching Latest Maps... (This could take a few minutes...)\n"; + print "\n --- Fetching Latest Maps... (This could take a few minutes...) --- \n"; get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1); unzip('maps/maps.zip', 'maps/'); my @files; - my $start_dir = "maps/EQEmuMaps-master/maps"; + my $start_dir = "maps\\EQEmuMaps-master\\maps"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { - $destination_file = $file; - $destination_file =~s/maps\/EQEmuMaps-master\/maps\///g; - print "[Install] Installing :: " . $destination_file . "\n"; + $dest_file = $file; + $dest_file =~s/maps\\EQEmuMaps-master\\maps\///g; + print "Installing :: " . $dest_file . "\n"; copy_file($file, "maps/" . $new_file); } - print "[Install] Fetched Latest Maps\n"; + print "\n --- Fetched Latest Maps... --- \n"; rmtree('maps/EQEmuMaps-master'); unlink('maps/maps.zip'); } sub map_files_fetch{ - print "[Install] Fetching Latest Maps --- \n"; + print "\n --- Fetching Latest Maps --- \n"; get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt"); @@ -1104,22 +894,22 @@ sub map_files_fetch{ my $file_existing = $maps_manifest[$m][0]; my $file_existing_size = (stat $file_existing)[7]; if($file_existing_size != $maps_manifest[$m][1]){ - print "[Install] Updating: '" . $maps_manifest[$m][0] . "'\n"; + print "Updating: '" . $maps_manifest[$m][0] . "'\n"; get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1); $fc++; } } if($fc == 0){ - print "[Install] No Map Updates found... \n\n"; + print "\nNo Map Updates found... \n\n"; } } sub quest_files_fetch{ if (!-e "updates_staged/Quests-Plugins-master/quests/") { - print "[Update] Fetching Latest Quests --- \n"; + print "\n --- Fetching Latest Quests --- \n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "[Install] Fetched latest quests...\n"; + print "\nFetched latest quests...\n"; mkdir('updates_staged'); unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -1137,30 +927,30 @@ sub quest_files_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $destination_file = $file; - $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; + $dest_file = $file; + $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; - if (!-e $destination_file) { - copy_file($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n"; + if (!-e $dest_file) { + copy_file($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n"; $fc++; } else{ - $directory_indexff = do_file_diff($destination_file, $staged_file); - if($directory_indexff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + $diff = do_file_diff($dest_file, $staged_file); + if($diff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; - print $directory_indexff . "\n"; - print "[Update] File Different :: '" . $destination_file . "'\n"; - print "[Update] Do you wish to update this Quest? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + print $diff . "\n"; + print "\nFile Different :: '" . $dest_file . "'\n"; + print "\nDo you wish to update this Quest? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($destination_file, $backup_dest); + copy_file($dest_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n\n"; + copy($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n\n"; } $fc++; } @@ -1171,15 +961,15 @@ sub quest_files_fetch{ rmtree('updates_staged'); if($fc == 0){ - print "[Update] No Quest Updates found... \n\n"; + print "\nNo Quest Updates found... \n\n"; } } -sub lua_modules_fetch { +sub lua_modules_fetch{ if (!-e "updates_staged/Quests-Plugins-master/quests/lua_modules/") { - print "[Update] Fetching Latest LUA Modules --- \n"; + print "\n --- Fetching Latest LUA Modules --- \n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "[Update] Fetched latest LUA Modules...\n"; + print "\nFetched latest LUA Modules...\n"; unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -1196,29 +986,29 @@ sub lua_modules_fetch { for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $destination_file = $file; - $destination_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; + $dest_file = $file; + $dest_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; - if (!-e $destination_file) { - copy_file($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n"; + if (!-e $dest_file) { + copy_file($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n"; $fc++; } else{ - $directory_indexff = do_file_diff($destination_file, $staged_file); - if($directory_indexff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - print $directory_indexff . "\n"; - print "[Update] File Different :: '" . $destination_file . "'\n"; - print "[Update] Do you wish to update this LUA Module? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + $diff = do_file_diff($dest_file, $staged_file); + if($diff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; + print $diff . "\n"; + print "\nFile Different :: '" . $dest_file . "'\n"; + print "\nDo you wish to update this LUA Module? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($destination_file, $backup_dest); + copy_file($dest_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n\n"; + copy($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n\n"; } $fc++; } @@ -1227,15 +1017,15 @@ sub lua_modules_fetch { } if($fc == 0){ - print "[Update] No LUA Modules Updates found... \n\n"; + print "\nNo LUA Modules Updates found... \n\n"; } } sub plugins_fetch{ if (!-e "updates_staged/Quests-Plugins-master/plugins/") { - print "[Update] Fetching Latest Plugins\n"; + print "\n --- Fetching Latest Plugins --- \n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "[Update] Fetched latest plugins\n"; + print "\nFetched latest plugins...\n"; unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -1252,29 +1042,29 @@ sub plugins_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $destination_file = $file; - $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; + $dest_file = $file; + $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; - if (!-e $destination_file) { - copy_file($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n"; + if (!-e $dest_file) { + copy_file($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n"; $fc++; } else{ - $directory_indexff = do_file_diff($destination_file, $staged_file); - if($directory_indexff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - print $directory_indexff . "\n"; - print "[Update] File Different :: '" . $destination_file . "'\n"; - print "[Update] Do you wish to update this Plugin? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + $diff = do_file_diff($dest_file, $staged_file); + if($diff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; + print $diff . "\n"; + print "\nFile Different :: '" . $dest_file . "'\n"; + print "\nDo you wish to update this Plugin? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($destination_file, $backup_dest); + copy_file($dest_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n\n"; + copy($staged_file, $dest_file); + print "Installing :: '" . $dest_file . "'\n\n"; } $fc++; } @@ -1283,7 +1073,7 @@ sub plugins_fetch{ } if($fc == 0){ - print "[Update] No Plugin Updates found... \n\n"; + print "\nNo Plugin Updates found... \n\n"; } } @@ -1292,8 +1082,8 @@ sub do_file_diff{ $file_2 = $_[1]; if($OS eq "Windows"){ eval "use Text::Diff"; - $directory_indexff = diff($file_1, $file_2, { STYLE => "Unified" }); - return $directory_indexff; + $diff = diff($file_1, $file_2, { STYLE => "Unified" }); + return $diff; } if($OS eq "Linux"){ # print 'diff -u "$file_1" "$file_2"' . "\n"; @@ -1301,7 +1091,7 @@ sub do_file_diff{ } } -sub unzip { +sub unzip{ $archive_to_unzip = $_[0]; $dest_folder = $_[1]; @@ -1311,11 +1101,11 @@ sub unzip { unless ( $zip->read($archive_to_unzip) == AZ_OK ) { die 'read error'; } - print "[Unzip] Extracting...\n"; + print "Extracting...\n"; $zip->extractTree('', $dest_folder); } if($OS eq "Linux"){ - print `unzip -o -q "$archive_to_unzip" -d "$dest_folder"`; + print `unzip -o "$archive_to_unzip" -d "$dest_folder"`; } } @@ -1333,11 +1123,11 @@ sub are_file_sizes_different{ sub do_bots_db_schema_drop{ #"drop_bots.sql" is run before reverting database back to 'normal' - print "[Database] Fetching drop_bots.sql...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); + print "Fetching drop_bots.sql...\n"; + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); print get_mysql_result_from_file("db_update/drop_bots.sql"); - print "[Database] Removing bot database tables...\n"; + print "Restoring normality...\n"; print get_mysql_result("DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots:%';"); if(get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && $db){ @@ -1363,12 +1153,11 @@ sub do_bots_db_schema_drop{ if(get_mysql_result("SHOW COLUMNS FROM `db_version` LIKE 'bots_version'") ne "" && $db){ print get_mysql_result("UPDATE `db_version` SET `bots_version` = 0;"); } - print "[Database] Done...\n"; } sub modify_db_for_bots{ #Called after the db bots schema (2015_09_30_bots.sql) has been loaded - print "[Database] Modifying database for bots...\n"; + print "Modifying database for bots...\n"; print get_mysql_result("UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298);"); if(get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ @@ -1449,7 +1238,7 @@ sub modify_db_for_bots{ sub convert_existing_bot_data{ if(get_mysql_result("SHOW TABLES LIKE 'bots'") ne "" && $db){ - print "[Database] Converting existing bot data...\n"; + print "Converting existing bot data...\n"; print get_mysql_result("INSERT INTO `bot_data` (`bot_id`, `owner_id`, `spells_id`, `name`, `last_name`, `zone_id`, `gender`, `race`, `class`, `level`, `creation_day`, `last_spawn`, `time_spawned`, `size`, `face`, `hair_color`, `hair_style`, `beard`, `beard_color`, `eye_color_1`, `eye_color_2`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `ac`, `atk`, `hp`, `mana`, `str`, `sta`, `cha`, `dex`, `int`, `agi`, `wis`, `fire`, `cold`, `magic`, `poison`, `disease`, `corruption`) SELECT `BotID`, `BotOwnerCharacterID`, `BotSpellsID`, `Name`, `LastName`, `LastZoneId`, `Gender`, `Race`, `Class`, `BotLevel`, UNIX_TIMESTAMP(`BotCreateDate`), UNIX_TIMESTAMP(`LastSpawnDate`), `TotalPlayTime`, `Size`, `Face`, `LuclinHairColor`, `LuclinHairStyle`, `LuclinBeard`, `LuclinBeardColor`, `LuclinEyeColor`, `LuclinEyeColor2`, `DrakkinHeritage`, `DrakkinTattoo`, `DrakkinDetails`, `AC`, `ATK`, `HP`, `Mana`, `STR`, `STA`, `CHA`, `DEX`, `_INT`, `AGI`, `WIS`, `FR`, `CR`, `MR`, `PR`, `DR`, `Corrup` FROM `bots`;"); print get_mysql_result("INSERT INTO `bot_inspect_messages` (`bot_id`, `inspect_message`) SELECT `BotID`, `BotInspectMessage` FROM `bots`;"); @@ -1546,7 +1335,7 @@ sub get_bots_db_version{ #::: Check if bots_version column exists... if(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db){ print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;"); - print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; + print "\nColumn 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; } $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); return $bots_local_db_version; @@ -1562,7 +1351,7 @@ sub bots_db_management{ } if($bin_db_ver == 0){ - print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n"; + print "Your server binaries (world/zone) are not compiled for bots...\n"; return; } @@ -1608,22 +1397,22 @@ sub run_database_check{ if(!@total_updates){ #::: Pull down bots database manifest if($bots_db_management == 1){ - print "[Database] Retrieving latest bots database manifest...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); + print "Retrieving latest bots database manifest...\n"; + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); } #::: Pull down mainstream database manifest else{ - print "[Database] Retrieving latest database manifest...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); + print "Retrieving latest database manifest...\n"; + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); } } #::: Run 2 - Running pending updates... - if(@total_updates || $db_run_stage == 1){ + if(@total_updates){ @total_updates = sort @total_updates; foreach my $val (@total_updates){ $file_name = trim($m_d{$val}[1]); - print "[Database] Running Update: " . $val . " - " . $file_name . "\n"; + print "Running Update: " . $val . " - " . $file_name . "\n"; print get_mysql_result_from_file("db_update/$file_name"); print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val"); @@ -1635,7 +1424,7 @@ sub run_database_check{ } #::: Run 1 - Initial checking of needed updates... else{ - print "[Database] Reading manifest...\n"; + print "Reading manifest...\n\n"; use Data::Dumper; open (FILE, "db_update/db_update_manifest.txt"); while () { @@ -1669,23 +1458,23 @@ sub run_database_check{ #::: Match type update if($match_type eq "contains"){ if(trim(get_mysql_result($query_check))=~/$match_text/i){ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; + print "Missing DB Update " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "missing"){ if(get_mysql_result($query_check)=~/$match_text/i){ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; next; } else{ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; + print "Missing DB Update " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } @@ -1694,24 +1483,24 @@ sub run_database_check{ } if($match_type eq "empty"){ if(get_mysql_result($query_check) eq ""){ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; + print "Missing DB Update " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "not_empty"){ if(get_mysql_result($query_check) ne ""){ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; + print "Missing DB Update " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); @@ -1720,13 +1509,13 @@ sub run_database_check{ print "\n"; if(scalar (@total_updates) == 0 && $db_run_stage == 2){ - print "[Database] No updates need to be run...\n"; + print "No updates need to be run...\n"; if($bots_db_management == 1){ - print "[Database] Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; + print "Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; get_mysql_result("UPDATE db_version SET bots_version = $bin_db_ver"); } - else{ - print "[Database] Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; + else{ + print "Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; get_mysql_result("UPDATE db_version SET version = $bin_db_ver"); } @@ -1739,14 +1528,14 @@ sub fetch_missing_db_update{ $update_file = $_[1]; if($db_update >= 9000){ if($bots_db_management == 1){ - get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); } else{ - get_remote_file($eqemu_repository_request_url . "utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); } } elsif($db_update >= 5000 && $db_update <= 9000){ - get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); } } @@ -1757,17 +1546,7 @@ sub print_match_debug{ print " Query Check: '" . $query_check . "'\n"; print " Result: '" . trim(get_mysql_result($query_check)) . "'\n"; } - sub print_break{ if(!$debug){ return; } print "\n==============================================\n"; } - -sub generate_random_password { - my $passwordsize = shift; - my @alphanumeric = ('a'..'z', 'A'..'Z', 0..9); - my $randpassword = join '', - map $alphanumeric[rand @alphanumeric], 0..$passwordsize; - - return $randpassword; -} diff --git a/zone/mob.cpp b/zone/mob.cpp index accd36bb0..8aa889719 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -289,6 +289,9 @@ Mob::Mob(const char* in_name, logging_enabled = false; isgrouped = false; israidgrouped = false; + + IsHorse = false; + entity_id_being_looted = 0; _appearance = eaStanding; pRunAnimSpeed = 0; From d85e6ae495235f37429dd255b6aa76c92495cdf0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Aug 2016 01:23:03 -0500 Subject: [PATCH 337/693] Set eqemu_server.pl to check database manifest for only updates that are higher than the local database version - this will prevent false previous match conditions [skip ci] --- utils/scripts/eqemu_update.pl | 1303 +++++++++++++++++++-------------- 1 file changed, 770 insertions(+), 533 deletions(-) diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl index a7da3c792..cb94dca0a 100644 --- a/utils/scripts/eqemu_update.pl +++ b/utils/scripts/eqemu_update.pl @@ -1,185 +1,156 @@ #!/usr/bin/perl ########################################################### -#::: Automatic (Database) Upgrade Script -#::: Author: Akkadius +#::: General EQEmu Server Administration Script +#::: Purpose - Handles: +#::: Automatic database versioning (bots and normal DB) +#::: Updating server assets (binary, opcodes, maps, configuration files) +#::: Original Author: Akkadius +#::: Contributors: Uleat #::: Purpose: To upgrade databases with ease and maintain versioning ########################################################### -$menu_displayed = 0; - use Config; use File::Copy qw(copy); use POSIX qw(strftime); use File::Path; use File::Find; -use URI::Escape; -use Time::HiRes qw(usleep); +use Time::HiRes qw(usleep); +#::: Variables +$install_repository_request_url = "https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/"; +$eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/master/"; + +#::: Globals $time_stamp = strftime('%m-%d-%Y', gmtime()); - -$console_output .= " Operating System is: $Config{osname}\n"; +$db_run_stage = 0; #::: Sets database run stage check if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } - -#::: If current version is less than what world is reporting, then download a new one... -$current_version = 14; - -if($ARGV[0] eq "V"){ - if($ARGV[1] > $current_version){ - print "eqemu_update.pl Automatic Database Upgrade Needs updating...\n"; - print " Current version: " . $current_version . "\n"; - print " New version: " . $ARGV[1] . "\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); - exit; - } - else{ - print "[Upgrade Script] No script update necessary \n"; - } - exit; -} - -#::: Sets database run stage check -$db_run_stage = 0; - -$perl_version = $^V; -$perl_version =~s/v//g; -print "Perl Version is " . $perl_version . "\n"; -if($perl_version > 5.12){ no warnings 'uninitialized'; } -no warnings; - +$has_internet_connection = check_internet_connection(); ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); -my $confile = "eqemu_config.xml"; #default -open(F, "<$confile"); -my $indb = 0; -while() { - s/\r//g; - if(//i) { $indb = 1; } - next unless($indb == 1); - if(/<\/database>/i) { $indb = 0; last; } - if(/(.*)<\/host>/i) { $host = $1; } - elsif(/(.*)<\/username>/i) { $user = $1; } - elsif(/(.*)<\/password>/i) { $pass = $1; } - elsif(/(.*)<\/db>/i) { $db = $1; } +#::: Check for script self update +do_self_update_check_routine(); +get_perl_version(); +read_eqemu_config_xml(); +get_mysql_path(); + +#::: Remove old eqemu_update.pl +if(-e "eqemu_update.pl"){ + unlink("eqemu_update.pl"); +} +#::: Create db_update working directory if not created +mkdir('db_update'); + +print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n"; + +#::: Check if db_version table exists... +if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ + print get_mysql_result("DROP TABLE db_version"); + print "[Database] Old db_version table present, dropping...\n\n"; } -$console_output = -"============================================================ - EQEmu: Automatic Upgrade Check -============================================================ -"; +check_db_version_table(); -if($OS eq "Windows"){ - $has_mysql_path = `echo %PATH%`; - if($has_mysql_path=~/MySQL|MariaDB/i){ - @mysql = split(';', $has_mysql_path); - foreach my $v (@mysql){ - if($v=~/MySQL|MariaDB/i){ - $v =~s/\n//g; - $path = trim($v) . "/mysql"; - last; - } +check_for_world_bootup_database_update(); + +if($db){ + print "[Update] MySQL Path/Location: " . $path . "\n"; + print "[Update] Binary Revision / Local: (" . $binary_database_version . " / " . $local_database_version . ")\n"; + + #::: Bots + #::: Make sure we're running a bots binary to begin with + if(trim($db_version[2]) > 0){ + $bots_local_db_version = get_bots_db_version(); + if($bots_local_db_version > 0){ + print "[Update] (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; } - $console_output .= " (Windows) MySQL is in system path \n"; - $console_output .= " Path = " . $path . "\n"; - $console_output .= "============================================================\n"; } -} -#::: Linux Check -if($OS eq "Linux"){ - $path = `which mysql`; - if ($path eq "") { - $path = `which mariadb`; + #::: If World ran this script, and our version is up to date, continue... + if($binary_database_version <= $local_database_version && $ARGV[0] eq "ran_from_world"){ + print "[Update] Database up to Date: Continuing World Bootup...\n"; + exit; } - $path =~s/\n//g; - - $console_output .= " (Linux) MySQL is in system path \n"; - $console_output .= " Path = " . $path . "\n"; - $console_output .= "============================================================\n"; -} - -#::: Path not found, error and exit -if($path eq ""){ - print "MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; - print "script_exiting...\n"; - exit; -} - -if($ARGV[0] eq "install_peq_db"){ - - $db_name = "peq"; - if($ARGV[1]){ - $db_name = $ARGV[1]; - } - - $db = $db_name; - - #::: Database Routines - print "MariaDB :: Creating Database '" . $db_name . "'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); - - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); -} +} if($ARGV[0] eq "remove_duplicate_rules"){ remove_duplicate_rule_values(); exit; } +if($ARGV[0] eq "map_files_fetch_bulk"){ + map_files_fetch_bulk(); + exit; +} + +if($ARGV[0] eq "loginserver_install_linux"){ + do_linux_login_server_setup(); + exit; +} + if($ARGV[0] eq "installer"){ - print "Running EQEmu Server installer routines...\n"; + print "[Install] Running EQEmu Server installer routines...\n"; + + #::: Make some local server directories... mkdir('logs'); mkdir('updates_staged'); mkdir('shared'); - fetch_latest_windows_binaries(); + + do_install_config_xml(); + read_eqemu_config_xml(); + get_installation_variables(); + + $db_name = "peq"; + if($installation_variables{"mysql_eqemu_db_name"}){ + $db_name = $installation_variables{"mysql_eqemu_db_name"}; + } + + #::: Download assets + if($OS eq "Windows"){ + fetch_latest_windows_binaries(); + get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); + get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); + get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); + } map_files_fetch_bulk(); opcodes_fetch(); plugins_fetch(); quest_files_fetch(); lua_modules_fetch(); - - #::: Binary dll's - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); - - #::: Server scripts fetch_utility_scripts(); #::: Database Routines - print "MariaDB :: Creating Database 'peq'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS peq;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE peq"`; + print "[Database] Creating Database '" . $db_name . "'\n"; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; + + #::: Get Binary DB version if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); - check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - fetch_peq_db_full(); - print "\nFetching Latest Database Updates...\n"; - main_db_management(); - print "\nApplying Latest Database Updates...\n"; - main_db_management(); + $binary_database_version = trim($db_version[1]); - print get_mysql_result("UPDATE `launcher` SET `dynamics` = 30 WHERE `name` = 'zone'"); + #::: Local DB Version + check_db_version_table(); + $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + + #::: Download PEQ latest + fetch_peq_db_full(); + print "[Database] Fetching Latest Database Updates...\n"; + main_db_management(); + print "[Database] Applying Latest Database Updates...\n"; + main_db_management(); if($OS eq "Windows"){ check_windows_firewall_rules(); do_windows_login_server_setup(); } + if($OS eq "Linux"){ + do_linux_login_server_setup(); + + print "[Install] Installation complete!\n"; + } + exit; } @@ -187,204 +158,358 @@ if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } if($ARGV[0] eq "login_server_setup"){ do_windows_login_server_setup(); exit; -} +} -#::: Create db_update working directory if not created -mkdir('db_update'); - -#::: Check if db_version table exists... -if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ - print get_mysql_result("DROP TABLE db_version"); - print "Old db_version table present, dropping...\n\n"; -} - -sub check_db_version_table{ - if(get_mysql_result("SHOW TABLES LIKE 'db_version'") eq "" && $db){ - print get_mysql_result(" - CREATE TABLE db_version ( - version int(11) DEFAULT '0' - ) ENGINE=InnoDB DEFAULT CHARSET=latin1; - INSERT INTO db_version (version) VALUES ('1000');"); - print "Table 'db_version' does not exists.... Creating...\n\n"; +sub check_for_world_bootup_database_update { + if($OS eq "Windows"){ + @db_version = split(': ', `world db_version`); } -} + if($OS eq "Linux"){ + @db_version = split(': ', `./world db_version`); + } -check_db_version_table(); + $binary_database_version = trim($db_version[1]); + $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); -if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } -if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - -$bin_db_ver = trim($db_version[1]); -$local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - -#::: If ran from Linux startup script, supress output -if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_start"){ - print "Database up to date...\n"; - exit; -} -else{ - print $console_output if $db; -} - -if($db){ - print " Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; - - #::: Bots - #::: Make sure we're running a bots binary to begin with - if(trim($db_version[2]) > 0){ - $bots_local_db_version = get_bots_db_version(); - if($bots_local_db_version > 0){ - print " (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; - } - } - - #::: If World ran this script, and our version is up to date, continue... - if($bin_db_ver <= $local_db_ver && $ARGV[0] eq "ran_from_world"){ - print " Database up to Date: Continuing World Bootup...\n"; - print "============================================================\n"; + if($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world"){ + print "[Update] Database up to date...\n"; exit; } + else { + #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup + if($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world"){ + print "[Update] Database not up to date with binaries... Automatically updating...\n"; + print "[Update] Issuing database backup first...\n"; + database_dump_compress(); + print "[Update] Updating database...\n"; + sleep(1); + main_db_management(); + main_db_management(); + print "[Update] Continuing bootup\n"; + exit; + } + + #::: Make sure that we didn't pass any arugments to the script + if(!$ARGV[0]){ + if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } + show_menu_prompt(); + } + } } -if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){ - print "You have missing database updates, type 1 or 2 to backup your database before running them as recommended...\n\n"; - #::: Display Menu - show_menu_prompt(); -} -else{ - #::: Most likely ran standalone - print "\n"; - show_menu_prompt(); +sub check_internet_connection { + if($OS eq "Linux"){ + $count = "c"; + } + if($OS eq "Windows"){ + $count = "n"; + } + + if (`ping 8.8.8.8 -$count 1 -w 500`=~/Reply from|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + elsif (`ping 4.2.2.2 -$count 1 -w 500`=~/Reply from|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + else{ + print "[Update] No connection to the internet, can't check update\n"; + return; + } } -sub do_update_self{ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl", "eqemu_update.pl"); - die "Rerun eqemu_update.pl"; +sub get_perl_version { + #::: Check Perl version + $perl_version = $^V; + $perl_version =~s/v//g; + print "[Update] Perl Version is " . $perl_version . "\n"; + if($perl_version > 5.12){ + no warnings 'uninitialized'; + } + no warnings; +} + +sub do_self_update_check_routine { + #::: Check Version passed from world to update script + get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); + + if(!$has_internet_connection){ + print "[Update] Cannot check update without internet connection...\n"; + return; + } + + if(-e "updates_staged/eqemu_server.pl") { + + my $remote_script_size = -s "updates_staged/eqemu_server.pl"; + my $local_script_size = -s "eqemu_server.pl"; + + if($remote_script_size != $local_script_size){ + print "[Update] Script has been updated, updating...\n"; + + my @files; + my $start_dir = "updates_staged/"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + if($file=~/eqemu_server/i){ + $destination_file = $file; + $destination_file =~s/updates_staged\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + unlink($destination_file); + copy_file($file, $destination_file); + if($OS eq "Linux"){ + system("chmod 755 eqemu_server.pl"); + } + system("perl eqemu_server.pl start_from_world"); + } + } + print "[Install] Done\n"; + } + else { + print "[Update] No script update necessary...\n"; + } + + unlink("updates_staged/eqemu_server.pl"); + } +} + +sub get_installation_variables{ + #::: Fetch installation variables before building the config + if($OS eq "Linux"){ + open (INSTALL_VARS, "../install_variables.txt"); + } + if($OS eq "Windows"){ + open (INSTALL_VARS, "install_variables.txt"); + } + while (){ + chomp; + $o = $_; + @data = split(":", $o); + $installation_variables{trim($data[0])} = trim($data[1]); + } + close (INSTALL_VARS); +} + +sub do_install_config_xml { + get_installation_variables(); + + #::: Fetch XML template + get_remote_file($install_repository_request_url . "eqemu_config.xml", "eqemu_config_template.xml"); + + #::: Open new config file + open (NEW_CONFIG, '>', 'eqemu_config.xml'); + + $in_database_tag = 0; + + #::: Iterate through template and replace variables... + open (FILE_TEMPLATE, "eqemu_config_template.xml"); + while (){ + chomp; + $o = $_; + + #::: Find replace variables + + if($o=~/\<\!--/i){ + next; + } + + if($o=~/database/i && $o=~/\<\//i){ + $in_database_tag = 0; + } + if($o=~/database/i){ + $in_database_tag = 1; + } + + if($o=~/key/i){ + my($replace_key) = $o =~ />(\w+)/i && $in_database_tag){ + my($replace_username) = $o =~ />(\w+)/i && $in_database_tag){ + my($replace_password) = $o =~ />(\w+)/i){ + my($replace_db_name) = $o =~ />(\w+) \&database_dump, - 2 => \&database_dump_compress, - 3 => \&main_db_management, - 4 => \&bots_db_management, - 5 => \&opcodes_fetch, - 6 => \&map_files_fetch, - 7 => \&plugins_fetch, - 8 => \&quest_files_fetch, - 9 => \&lua_modules_fetch, - 10 => \&aa_fetch, - 11 => \&fetch_latest_windows_binaries, - 12 => \&fetch_server_dlls, - 13 => \&do_windows_login_server_setup, - 14 => \&remove_duplicate_rule_values, - 15 => \&fetch_utility_scripts, - 18 => \&fetch_latest_windows_binaries_bots, - 19 => \&do_bots_db_schema_drop, - 20 => \&do_update_self, - 21 => \&database_dump_player_tables, - 0 => \&script_exit, - ); - while (1) { - { - local $| = 1; - if(!$menu_show && ($ARGV[0] eq "ran_from_world" || $ARGV[0] eq "ran_from_start")){ - $menu_show++; - next; - } - print menu_options(), '> '; - $menu_displayed++; - if($menu_displayed > 50){ - print "Safety: Menu looping too many times, exiting...\n"; - exit; - } + $dc = 0; + while (1) { + $input = trim($input); + + $errored_command = 0; + + if($input eq "database"){ + print "\n>>> Database Menu\n\n"; + print " [backup_database] Back up database to backups/ directory\n"; + print " [backup_player_tables] Back up player tables to backups/ directory\n"; + print " [backup_database_compressed] Back up database compressed to backups/ directory\n"; + print " \n"; + print " [check_db_updates] Checks for database updates manually\n"; + print " [check_bot_db_updates] Checks for bot database updates\n"; + print " \n"; + print " [aa_tables] Downloads and installs clean slate AA data from PEQ\n"; + print " [remove_duplicate_rules] Removes duplicate rules from rule_values table\n"; + print " [drop_bots_db_schema] Removes bot database schema\n"; + + print " \n> main - go back to main menu\n"; + print "Enter a command #> "; + $last_menu = trim($input); } - - my $choice = <>; - - $choice =~ s/\A\s+//; - $choice =~ s/\s+\z//; - - if (defined(my $handler = $dispatch{$choice})) { - my $result = $handler->(); - unless (defined $result) { - exit 0; + elsif($input eq "assets"){ + print "\n>>> Server Assets Menu\n\n"; + print " [maps] Download latest maps\n"; + print " [opcodes] Download opcodes (Patches for eq clients)\n"; + print " [quests] Download latest quests\n"; + print " [plugins] Download latest plugins\n"; + print " [lua_modules] Download latest lua_modules\n"; + print " [utility_scripts] Download utility scripts to run and operate the EQEmu Server\n"; + if($OS eq "Windows"){ + print ">>> Windows\n"; + print " [windows_server_download] Updates server code from latest stable\n"; + print " [windows_server_download_bots] Updates server code (bots enabled) from latest\n"; + print " [fetch_dlls] Grabs dll's needed to run windows binaries\n"; + print " [setup_loginserver] Sets up loginserver for Windows\n"; } + print " \n> main - go back to main menu\n"; + print "Enter a command #> "; + $last_menu = trim($input); + } + elsif($input eq "backup_database"){ database_dump(); $dc = 1; } + elsif($input eq "backup_player_tables"){ database_dump_player_tables(); $dc = 1; } + elsif($input eq "backup_database_compressed"){ database_dump_compress(); $dc = 1; } + elsif($input eq "drop_bots_db_schema"){ do_bots_db_schema_drop(); $dc = 1; } + elsif($input eq "aa_tables"){ aa_fetch(); $dc = 1; } + elsif($input eq "remove_duplicate_rules"){ remove_duplicate_rule_values(); $dc = 1; } + elsif($input eq "maps"){ map_files_fetch_bulk(); $dc = 1; } + elsif($input eq "opcodes"){ opcodes_fetch(); $dc = 1; } + elsif($input eq "plugins"){ plugins_fetch(); $dc = 1; } + elsif($input eq "quests"){ quest_files_fetch(); $dc = 1; } + elsif($input eq "lua_modules"){ lua_modules_fetch(); $dc = 1; } + elsif($input eq "windows_server_download"){ fetch_latest_windows_binaries(); $dc = 1; } + elsif($input eq "windows_server_download_bots"){ fetch_latest_windows_binaries_bots(); $dc = 1; } + elsif($input eq "fetch_dlls"){ fetch_server_dlls(); $dc = 1; } + elsif($input eq "utility_scripts"){ fetch_utility_scripts(); $dc = 1; } + elsif($input eq "check_db_updates"){ main_db_management(); $dc = 1; } + elsif($input eq "check_bot_db_updates"){ bots_db_management(); $dc = 1; } + elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; } + elsif($input eq "exit"){ + exit; + } + elsif($input eq "main"){ + print "Returning to main menu...\n"; + print_main_menu(); + $last_menu = trim($input); + } + elsif($input eq "" && $last_menu ne ""){ + $errored_command = 1; + } + elsif($input ne ""){ + print "Invalid command '" . $input . "'\n"; + $errored_command = 1; } else { - if($ARGV[0] ne "ran_from_world"){ - # warn "\n\nInvalid selection\n\n"; - } + print_main_menu(); + } + + #::: Errored command checking + if($errored_command == 1){ + $input = $last_menu; + } + elsif($dc == 1){ + $dc = 0; + $input = ""; + } + else { + $input = <>; } } } -sub menu_options { - if(@total_updates){ - if($bots_db_management == 1){ - $option[3] = "Check and stage pending REQUIRED Database updates"; - $bots_management = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; - } - else{ - $option[3] = "Run pending REQUIRED updates... (" . scalar (@total_updates) . ")"; - if(get_mysql_result("SHOW TABLES LIKE 'bots'") eq ""){ - $bots_management = "Install bots database pre-requisites (Requires bots server binaries)"; - } - else{ - $bots_management = "Check for Bot pending REQUIRED database updates... (Must have bots enabled)"; - } - } - } - else{ - $option[3] = "Check and stage pending REQUIRED Database updates"; - $bots_management = "Check for Bot REQUIRED database updates... (Must have bots enabled)"; - } +sub print_main_menu { + print "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"; + print ">>> EQEmu Server Main Menu >>>>>>>>>>>>\n"; + print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"; + print " [database] Enter database management menu \n"; + print " [assets] Manage server assets \n\n"; + print " exit \n"; + print "\n"; + print "Enter a command #> "; +} -return <; #Read from STDIN @@ -432,7 +553,7 @@ sub database_dump_player_tables { sub database_dump_compress { check_for_database_dump_script(); - print "Performing database backup....\n"; + print "[Database] Performing database backup....\n"; print `perl db_dumper.pl database="$db" loc="backups" compress`; } @@ -442,6 +563,17 @@ sub script_exit{ exit; } +sub check_db_version_table{ + if(get_mysql_result("SHOW TABLES LIKE 'db_version'") eq "" && $db){ + print get_mysql_result(" + CREATE TABLE db_version ( + version int(11) DEFAULT '0' + ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + INSERT INTO db_version (version) VALUES ('1000');"); + print "[Database] Table 'db_version' does not exists.... Creating...\n\n"; + } +} + #::: Returns Tab Delimited MySQL Result from Command Line sub get_mysql_result{ my $run_query = $_[0]; @@ -460,30 +592,40 @@ sub get_mysql_result_from_file{ if($OS eq "Linux"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } } -#::: Gets Remote File based on URL (1st Arg), and saves to destination file (2nd Arg) -#::: Example: get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); +#::: Gets Remote File based on request_url (1st Arg), and saves to destination file (2nd Arg) +#::: Example: get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); sub get_remote_file{ - my $URL = $_[0]; - my $Dest_File = $_[1]; + my $request_url = $_[0]; + my $destination_file = $_[1]; my $content_type = $_[2]; + my $no_retry = $_[3]; + my $silent_download = $_[4]; + + if(!$has_internet_connection){ + print "[Download] Cannot download without internet connection...\n"; + return; + } #::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary - if($Dest_File=~/\//i){ - my @dir_path = split('/', $Dest_File); + + if($destination_file=~/\//i){ + my @directory_path = split('/', $destination_file); $build_path = ""; - $di = 0; - while($dir_path[$di]){ - $build_path .= $dir_path[$di] . "/"; + $directory_index = 0; + while($directory_path[$directory_index] && $directory_path[$directory_index + 1]){ + $build_path .= $directory_path[$directory_index] . "/"; + # print "checking '" . $build_path . "'\n"; #::: If path does not exist, create the directory... - if (!-d $build_path) { + if (!-d $build_path) { + print "[Copy] folder doesn't exist, creating '" . $build_path . "'\n"; mkdir($build_path); } - if(!$dir_path[$di + 2] && $dir_path[$di + 1]){ + if(!$directory_indexr_path[$directory_index + 2] && $directory_indexr_path[$directory_index + 1]){ # print $actual_path . "\n"; $actual_path = $build_path; last; } - $di++; + $directory_index++; } } @@ -492,51 +634,59 @@ sub get_remote_file{ if($content_type == 1){ $break = 0; while($break == 0) { - use LWP::Simple qw(getstore); - if(!getstore($URL, $Dest_File)){ - # print "Error, no connection or failed request...\n\n"; + eval "use LWP::Simple qw(getstore);"; + # use LWP::Simple qw(getstore); + # print "request is " . $request_url . "\n"; + # print "destination file is supposed to be " . $destination_file . "\n"; + if(!getstore($request_url, $destination_file)){ + print "[Download] Error, no connection or failed request...\n\n"; } # sleep(1); #::: Make sure the file exists before continuing... - if(-e $Dest_File) { + if(-e $destination_file) { $break = 1; - print " [URL] :: " . $URL . "\n"; - print " [Saved] :: " . $Dest_File . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; } else { $break = 0; } usleep(500); + + if($no_retry){ + $break = 1; + } } } else{ $break = 0; while($break == 0) { require LWP::UserAgent; - my $ua = LWP::UserAgent->new; + my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; - my $response = $ua->get($URL); + my $response = $ua->get($request_url); if ($response->is_success){ - open (FILE, '> ' . $Dest_File . ''); + open (FILE, '> ' . $destination_file . ''); print FILE $response->decoded_content; close (FILE); } else { - # print "Error, no connection or failed request...\n\n"; + print "[Download] Error, no connection or failed request...\n\n"; } - if(-e $Dest_File) { + if(-e $destination_file) { $break = 1; - print " [URL] :: " . $URL . "\n"; - print " [Saved] :: " . $Dest_File . "\n"; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; } else { $break = 0; } usleep(500); + + if($no_retry){ + $break = 1; + } } } } if($OS eq "Linux"){ #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt - $wget = `wget --no-check-certificate --quiet -O $Dest_File $URL`; - print " o URL: (" . $URL . ")\n"; - print " o Saved: (" . $Dest_File . ") \n"; - if($wget=~/unable to resolve/i){ + $wget = `wget --no-check-certificate --quiet -O $destination_file $request_url`; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; + if($wget=~/unable to resolve/i){ print "Error, no connection or failed request...\n\n"; #die; } @@ -551,6 +701,22 @@ sub trim { return $string; } +sub read_eqemu_config_xml { + my $confile = "eqemu_config.xml"; #default + open(F, "<$confile"); + my $indb = 0; + while() { + s/\r//g; + if(//i) { $indb = 1; } + next unless($indb == 1); + if(/<\/database>/i) { $indb = 0; last; } + if(/(.*)<\/host>/i) { $host = $1; } + elsif(/(.*)<\/username>/i) { $user = $1; } + elsif(/(.*)<\/password>/i) { $pass = $1; } + elsif(/(.*)<\/db>/i) { $db = $1; } + } +} + #::: Fetch Latest PEQ AA's sub aa_fetch{ if(!$db){ @@ -558,48 +724,48 @@ sub aa_fetch{ return; } - print "Pulling down PEQ AA Tables...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); - print "\n\nInstalling AA Tables...\n"; + print "[Install] Pulling down PEQ AA Tables...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); + print "[Install] Installing AA Tables...\n"; print get_mysql_result_from_file("db_update/peq_aa_tables_post_rework.sql"); - print "\nDone...\n\n"; + print "[Install] Done...\n\n"; } #::: Fetch Latest Opcodes sub opcodes_fetch{ - print "Pulling down latest opcodes...\n"; + print "[Update] Pulling down latest opcodes...\n"; %opcodes = ( - 1 => ["opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/opcodes.conf"], - 2 => ["mail_opcodes", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/mail_opcodes.conf"], - 3 => ["Titanium", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_Titanium.conf"], - 4 => ["Secrets of Faydwer", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoF.conf"], - 5 => ["Seeds of Destruction", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_SoD.conf"], - 6 => ["Underfoot", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_UF.conf"], - 7 => ["Rain of Fear", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF.conf"], - 8 => ["Rain of Fear 2", "https://raw.githubusercontent.com/EQEmu/Server/master/utils/patches/patch_RoF2.conf"], + 1 => ["opcodes", $eqemu_repository_request_url . "utils/patches/opcodes.conf"], + 2 => ["mail_opcodes", $eqemu_repository_request_url . "utils/patches/mail_opcodes.conf"], + 3 => ["Titanium", $eqemu_repository_request_url . "utils/patches/patch_Titanium.conf"], + 4 => ["Secrets of Faydwer", $eqemu_repository_request_url . "utils/patches/patch_SoF.conf"], + 5 => ["Seeds of Destruction", $eqemu_repository_request_url . "utils/patches/patch_SoD.conf"], + 6 => ["Underfoot", $eqemu_repository_request_url . "utils/patches/patch_UF.conf"], + 7 => ["Rain of Fear", $eqemu_repository_request_url . "utils/patches/patch_RoF.conf"], + 8 => ["Rain of Fear 2", $eqemu_repository_request_url . "utils/patches/patch_RoF2.conf"], ); $loop = 1; while($opcodes{$loop}[0]){ - #::: Split the URL by the patches folder to get the file name from URL + #::: Split the request_url by the patches folder to get the file name from request_url @real_file = split("patches/", $opcodes{$loop}[1]); $find = 0; while($real_file[$find]){ $file_name = $real_file[$find]; $find++; } - - print "\nDownloading (" . $opcodes{$loop}[0] . ") File: '" . $file_name . "'...\n\n"; + get_remote_file($opcodes{$loop}[1], $file_name); $loop++; } - print "\nDone...\n\n"; + print "[Update] Done...\n"; } -sub remove_duplicate_rule_values{ +sub remove_duplicate_rule_values { $ruleset_id = trim(get_mysql_result("SELECT `ruleset_id` FROM `rule_sets` WHERE `name` = 'default'")); - print "Default Ruleset ID: " . $ruleset_id . "\n"; + print "[Database] Default Ruleset ID: " . $ruleset_id . "\n"; $total_removed = 0; + #::: Store Default values... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` = " . $ruleset_id); my @lines = split("\n", $mysql_result); @@ -607,50 +773,51 @@ sub remove_duplicate_rule_values{ my @values = split("\t", $val); $rule_set_values{$values[1]}[0] = $values[2]; } + #::: Compare default values against other rulesets to check for duplicates... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` != " . $ruleset_id); my @lines = split("\n", $mysql_result); foreach my $val (@lines){ my @values = split("\t", $val); if($values[2] == $rule_set_values{$values[1]}[0]){ - print "DUPLICATE : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . ", removing...\n"; + print "[Database] Removing duplicate : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . "\n"; get_mysql_result("DELETE FROM `rule_values` WHERE `ruleset_id` = " . $values[0] . " AND `rule_name` = '" . $values[1] . "'"); $total_removed++; } } - print "Total duplicate rules removed... " . $total_removed . "\n"; + print "[Database] Total duplicate rules removed... " . $total_removed . "\n"; } -sub copy_file{ +sub copy_file { $l_source_file = $_[0]; - $l_dest_file = $_[1]; - if($l_dest_file=~/\//i){ - my @dir_path = split('/', $l_dest_file); + $l_destination_file = $_[1]; + if($l_destination_file=~/\//i){ + my @directory_path = split('/', $l_destination_file); $build_path = ""; - $di = 0; - while($dir_path[$di]){ - $build_path .= $dir_path[$di] . "/"; + $directory_index = 0; + while($directory_path[$directory_index]){ + $build_path .= $directory_path[$directory_index] . "/"; #::: If path does not exist, create the directory... if (!-d $build_path) { mkdir($build_path); } - if(!$dir_path[$di + 2] && $dir_path[$di + 1]){ + if(!$directory_path[$directory_index + 2] && $directory_path[$directory_index + 1]){ # print $actual_path . "\n"; $actual_path = $build_path; last; } - $di++; + $directory_index++; } } - copy $l_source_file, $l_dest_file; + copy $l_source_file, $l_destination_file; } -sub fetch_latest_windows_binaries{ - print "\n --- Fetching Latest Windows Binaries... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); - print "\n --- Fetched Latest Windows Binaries... --- \n"; - print "\n --- Extracting... --- \n"; +sub fetch_latest_windows_binaries { + print "[Update] Fetching Latest Windows Binaries... \n"; + get_remote_file($install_repository_request_url . "master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); + print "[Update] Fetched Latest Windows Binaries... \n"; + print "[Update] Extracting... --- \n"; unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; @@ -659,21 +826,21 @@ sub fetch_latest_windows_binaries{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/binaries\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/binaries\///g; + print "[Update] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } - print "\n --- Done... --- \n"; + print "[Update] Done\n"; rmtree('updates_staged'); } -sub fetch_latest_windows_binaries_bots{ - print "\n --- Fetching Latest Windows Binaries with Bots... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); - print "\n --- Fetched Latest Windows Binaries with Bots... --- \n"; - print "\n --- Extracting... --- \n"; +sub fetch_latest_windows_binaries_bots { + print "[Update] Fetching Latest Windows Binaries with Bots...\n"; + get_remote_file($install_repository_request_url . "master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); + print "[Update] Fetched Latest Windows Binaries with Bots...\n"; + print "[Update] Extracting...\n"; unzip('updates_staged/master_windows_build_bots.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; @@ -682,20 +849,20 @@ sub fetch_latest_windows_binaries_bots{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/binaries\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/binaries\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } - print "\n --- Done... --- \n"; + print "[Update] Done...\n"; rmtree('updates_staged'); } -sub do_windows_login_server_setup{ - print "\n --- Fetching Loginserver... --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server.zip", "updates_staged/login_server.zip", 1); - print "\n --- Extracting... --- \n"; +sub do_windows_login_server_setup { + print "[Install] Fetching Loginserver... \n"; + get_remote_file($install_repository_request_url . "login_server.zip", "updates_staged/login_server.zip", 1); + print "[Install] Extracting... \n"; unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); my @files; my $start_dir = "updates_staged/login_server"; @@ -704,31 +871,85 @@ sub do_windows_login_server_setup{ $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\/login_server\///g; - print "Installing :: " . $dest_file . "\n"; - copy_file($file, $dest_file); + $destination_file = $file; + $destination_file =~s/updates_staged\/login_server\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); } - print "\n Done... \n"; + print "[Install] Done... \n"; - print "Pulling down Loginserver database tables...\n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/login_server_tables.sql", "db_update/login_server_tables.sql"); - print "\n\nInstalling Loginserver tables...\n"; + print "[Install] Pulling down Loginserver database tables...\n"; + get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); + print "[Install] Installing Loginserver tables...\n"; print get_mysql_result_from_file("db_update/login_server_tables.sql"); - print "\nDone...\n\n"; + print "[Install] Done...\n"; add_login_server_firewall_rules(); rmtree('updates_staged'); rmtree('db_update'); - print "\nPress any key to continue...\n"; + print "[Install] Press any key to continue...\n"; + + <>; #Read from STDIN + +} + +sub do_linux_login_server_setup { + + for my $file (@files) { + $destination_file = $file; + $destination_file =~s/updates_staged\/login_server\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); + } + print "\n Done... \n"; + + print "[Install] Pulling down Loginserver database tables...\n"; + get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); + print "[Install] Installing Loginserver tables...\n"; + print get_mysql_result_from_file("db_update/login_server_tables.sql"); + print "[Install] Done...\n\n"; + + rmtree('updates_staged'); + rmtree('db_update'); + + get_remote_file($install_repository_request_url . "linux/login.ini", "login_template.ini"); + get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes.conf"); + get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes_sod.conf"); + + get_installation_variables(); + my $db_name = $installation_variables{"mysql_eqemu_db_name"}; + my $db_user = $installation_variables{"mysql_eqemu_user"}; + my $db_password = $installation_variables{"mysql_eqemu_password"}; + + #::: Open new config file + open (NEW_CONFIG, '>', 'login.ini'); + + #::: Iterate through template and replace variables... + open (FILE_TEMPLATE, "login_template.ini"); + while (){ + chomp; + $o = $_; + #::: Find replace variables + if($o=~/db/i){ $o = "db = " . $db_name; } + if($o=~/user/i){ $o = "user = " . $db_user; } + if($o=~/password/i){ $o = "password = " . $db_password; } + + print NEW_CONFIG $o . "\n"; + } + + close(FILE_TEMPLATE); + close(NEW_CONFIG); + unlink("login_template.ini"); + + print "[Install] Press any key to continue...\n"; <>; #Read from STDIN } -sub add_login_server_firewall_rules{ +sub add_login_server_firewall_rules { #::: Check Loginserver Firewall install for Windows if($OS eq "Windows"){ $output = `netsh advfirewall firewall show rule name=all`; @@ -750,22 +971,22 @@ sub add_login_server_firewall_rules{ } if($has_loginserver_rules_titanium == 0){ - print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) TCP" dir=in action=allow protocol=TCP localport=5998`; - print "Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) UDP" dir=in action=allow protocol=UDP localport=5998`; } if($has_loginserver_rules_sod == 0){ - print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) TCP" dir=in action=allow protocol=TCP localport=5999`; - print "Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) UDP" dir=in action=allow protocol=UDP localport=5999`; } - print "If firewall rules don't add you must run this script (eqemu_update.pl) as administrator\n"; + print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n"; print "\n"; - print "#::: Instructions \n"; - print "In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; + print "[Install] Instructions \n"; + print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; print " login.eqemulator.net @@ -780,7 +1001,7 @@ sub add_login_server_firewall_rules{ "; - print "\nWhen done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; + print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; } } @@ -794,84 +1015,84 @@ sub check_windows_firewall_rules{ $val=~s/Rule Name://g; if($val=~/EQEmu World/i){ $has_world_rules = 1; - print "Found existing rule :: " . trim($val) . "\n"; + print "[Install] Found existing rule :: " . trim($val) . "\n"; } if($val=~/EQEmu Zone/i){ $has_zone_rules = 1; - print "Found existing rule :: " . trim($val) . "\n"; + print "[Install] Found existing rule :: " . trim($val) . "\n"; } } } if($has_world_rules == 0){ - print "Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; + print "[Install] Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; print `netsh advfirewall firewall add rule name="EQEmu World (9000) TCP" dir=in action=allow protocol=TCP localport=9000`; - print "Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; + print "[Install] Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; print `netsh advfirewall firewall add rule name="EQEmu World (9000) UDP" dir=in action=allow protocol=UDP localport=9000`; } if($has_zone_rules == 0){ - print "Attempting to add EQEmu Zones (7000-7500) TCP \n"; + print "[Install] Attempting to add EQEmu Zones (7000-7500) TCP \n"; print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) TCP" dir=in action=allow protocol=TCP localport=7000-7500`; - print "Attempting to add EQEmu Zones (7000-7500) UDP \n"; + print "[Install] Attempting to add EQEmu Zones (7000-7500) UDP \n"; print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) UDP" dir=in action=allow protocol=UDP localport=7000-7500`; } } sub fetch_server_dlls{ - print "Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/lua51.dll", "lua51.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/zlib1.dll", "zlib1.dll", 1); - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/libmysql.dll", "libmysql.dll", 1); + print "[Download] Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; + get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); + get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); + get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); } sub fetch_peq_db_full{ - print "Downloading latest PEQ Database... Please wait...\n"; + print "[Install] Downloading latest PEQ Database... Please wait...\n"; get_remote_file("http://edit.peqtgc.com/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1); - print "Downloaded latest PEQ Database... Extracting...\n"; + print "[Install] Downloaded latest PEQ Database... Extracting...\n"; unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); - my $start_dir = "updates_staged\\peq_db"; + my $start_dir = "updates_staged/peq_db"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/updates_staged\\peq_db\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/peq_db\///g; if($file=~/peqbeta|player_tables/i){ - print "MariaDB :: Installing :: " . $dest_file . "\n"; + print "[Install] DB :: Installing :: " . $destination_file . "\n"; get_mysql_result_from_file($file); } if($file=~/eqtime/i){ - print "Installing eqtime.cfg\n"; + print "[Install] Installing eqtime.cfg\n"; copy_file($file, "eqtime.cfg"); } } } sub map_files_fetch_bulk{ - print "\n --- Fetching Latest Maps... (This could take a few minutes...) --- \n"; + print "[Install] Fetching Latest Maps... (This could take a few minutes...)\n"; get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1); unzip('maps/maps.zip', 'maps/'); my @files; - my $start_dir = "maps\\EQEmuMaps-master\\maps"; + my $start_dir = "maps/EQEmuMaps-master/maps"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { - $dest_file = $file; - $dest_file =~s/maps\\EQEmuMaps-master\\maps\///g; - print "Installing :: " . $dest_file . "\n"; + $destination_file = $file; + $destination_file =~s/maps\/EQEmuMaps-master\/maps\///g; + print "[Install] Installing :: " . $destination_file . "\n"; copy_file($file, "maps/" . $new_file); } - print "\n --- Fetched Latest Maps... --- \n"; + print "[Install] Fetched Latest Maps\n"; rmtree('maps/EQEmuMaps-master'); unlink('maps/maps.zip'); } sub map_files_fetch{ - print "\n --- Fetching Latest Maps --- \n"; + print "[Install] Fetching Latest Maps --- \n"; get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt"); @@ -894,22 +1115,22 @@ sub map_files_fetch{ my $file_existing = $maps_manifest[$m][0]; my $file_existing_size = (stat $file_existing)[7]; if($file_existing_size != $maps_manifest[$m][1]){ - print "Updating: '" . $maps_manifest[$m][0] . "'\n"; + print "[Install] Updating: '" . $maps_manifest[$m][0] . "'\n"; get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1); $fc++; } } if($fc == 0){ - print "\nNo Map Updates found... \n\n"; + print "[Install] No Map Updates found... \n\n"; } } sub quest_files_fetch{ if (!-e "updates_staged/Quests-Plugins-master/quests/") { - print "\n --- Fetching Latest Quests --- \n"; + print "[Update] Fetching Latest Quests --- \n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest quests...\n"; + print "[Install] Fetched latest quests...\n"; mkdir('updates_staged'); unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -927,30 +1148,30 @@ sub quest_files_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this Quest? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this Quest? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -961,15 +1182,15 @@ sub quest_files_fetch{ rmtree('updates_staged'); if($fc == 0){ - print "\nNo Quest Updates found... \n\n"; + print "[Update] No Quest Updates found... \n\n"; } } -sub lua_modules_fetch{ +sub lua_modules_fetch { if (!-e "updates_staged/Quests-Plugins-master/quests/lua_modules/") { - print "\n --- Fetching Latest LUA Modules --- \n"; + print "[Update] Fetching Latest LUA Modules --- \n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest LUA Modules...\n"; + print "[Update] Fetched latest LUA Modules...\n"; unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -986,29 +1207,29 @@ sub lua_modules_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this LUA Module? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this LUA Module? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -1017,15 +1238,15 @@ sub lua_modules_fetch{ } if($fc == 0){ - print "\nNo LUA Modules Updates found... \n\n"; + print "[Update] No LUA Modules Updates found... \n\n"; } } sub plugins_fetch{ if (!-e "updates_staged/Quests-Plugins-master/plugins/") { - print "\n --- Fetching Latest Plugins --- \n"; + print "[Update] Fetching Latest Plugins\n"; get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "\nFetched latest plugins...\n"; + print "[Update] Fetched latest plugins\n"; unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); } @@ -1042,29 +1263,29 @@ sub plugins_fetch{ for my $file (@files) { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; - $dest_file = $file; - $dest_file =~s/updates_staged\/Quests-Plugins-master\///g; + $destination_file = $file; + $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; - if (!-e $dest_file) { - copy_file($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n"; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; $fc++; } else{ - $diff = do_file_diff($dest_file, $staged_file); - if($diff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $dest_file; - print $diff . "\n"; - print "\nFile Different :: '" . $dest_file . "'\n"; - print "\nDo you wish to update this Plugin? '" . $dest_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + $directory_indexff = do_file_diff($destination_file, $staged_file); + if($directory_indexff ne ""){ + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this Plugin? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; my $input = ; if($input=~/N/i){} else{ #::: Make a backup - copy_file($dest_file, $backup_dest); + copy_file($destination_file, $backup_dest); #::: Copy staged to running - copy($staged_file, $dest_file); - print "Installing :: '" . $dest_file . "'\n\n"; + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; } $fc++; } @@ -1073,7 +1294,7 @@ sub plugins_fetch{ } if($fc == 0){ - print "\nNo Plugin Updates found... \n\n"; + print "[Update] No Plugin Updates found... \n\n"; } } @@ -1082,8 +1303,8 @@ sub do_file_diff{ $file_2 = $_[1]; if($OS eq "Windows"){ eval "use Text::Diff"; - $diff = diff($file_1, $file_2, { STYLE => "Unified" }); - return $diff; + $directory_indexff = diff($file_1, $file_2, { STYLE => "Unified" }); + return $directory_indexff; } if($OS eq "Linux"){ # print 'diff -u "$file_1" "$file_2"' . "\n"; @@ -1091,7 +1312,7 @@ sub do_file_diff{ } } -sub unzip{ +sub unzip { $archive_to_unzip = $_[0]; $dest_folder = $_[1]; @@ -1101,11 +1322,11 @@ sub unzip{ unless ( $zip->read($archive_to_unzip) == AZ_OK ) { die 'read error'; } - print "Extracting...\n"; + print "[Unzip] Extracting...\n"; $zip->extractTree('', $dest_folder); } if($OS eq "Linux"){ - print `unzip -o "$archive_to_unzip" -d "$dest_folder"`; + print `unzip -o -q "$archive_to_unzip" -d "$dest_folder"`; } } @@ -1123,11 +1344,11 @@ sub are_file_sizes_different{ sub do_bots_db_schema_drop{ #"drop_bots.sql" is run before reverting database back to 'normal' - print "Fetching drop_bots.sql...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); + print "[Database] Fetching drop_bots.sql...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); print get_mysql_result_from_file("db_update/drop_bots.sql"); - print "Restoring normality...\n"; + print "[Database] Removing bot database tables...\n"; print get_mysql_result("DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots:%';"); if(get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && $db){ @@ -1153,11 +1374,12 @@ sub do_bots_db_schema_drop{ if(get_mysql_result("SHOW COLUMNS FROM `db_version` LIKE 'bots_version'") ne "" && $db){ print get_mysql_result("UPDATE `db_version` SET `bots_version` = 0;"); } + print "[Database] Done...\n"; } sub modify_db_for_bots{ #Called after the db bots schema (2015_09_30_bots.sql) has been loaded - print "Modifying database for bots...\n"; + print "[Database] Modifying database for bots...\n"; print get_mysql_result("UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298);"); if(get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ @@ -1238,7 +1460,7 @@ sub modify_db_for_bots{ sub convert_existing_bot_data{ if(get_mysql_result("SHOW TABLES LIKE 'bots'") ne "" && $db){ - print "Converting existing bot data...\n"; + print "[Database] Converting existing bot data...\n"; print get_mysql_result("INSERT INTO `bot_data` (`bot_id`, `owner_id`, `spells_id`, `name`, `last_name`, `zone_id`, `gender`, `race`, `class`, `level`, `creation_day`, `last_spawn`, `time_spawned`, `size`, `face`, `hair_color`, `hair_style`, `beard`, `beard_color`, `eye_color_1`, `eye_color_2`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `ac`, `atk`, `hp`, `mana`, `str`, `sta`, `cha`, `dex`, `int`, `agi`, `wis`, `fire`, `cold`, `magic`, `poison`, `disease`, `corruption`) SELECT `BotID`, `BotOwnerCharacterID`, `BotSpellsID`, `Name`, `LastName`, `LastZoneId`, `Gender`, `Race`, `Class`, `BotLevel`, UNIX_TIMESTAMP(`BotCreateDate`), UNIX_TIMESTAMP(`LastSpawnDate`), `TotalPlayTime`, `Size`, `Face`, `LuclinHairColor`, `LuclinHairStyle`, `LuclinBeard`, `LuclinBeardColor`, `LuclinEyeColor`, `LuclinEyeColor2`, `DrakkinHeritage`, `DrakkinTattoo`, `DrakkinDetails`, `AC`, `ATK`, `HP`, `Mana`, `STR`, `STA`, `CHA`, `DEX`, `_INT`, `AGI`, `WIS`, `FR`, `CR`, `MR`, `PR`, `DR`, `Corrup` FROM `bots`;"); print get_mysql_result("INSERT INTO `bot_inspect_messages` (`bot_id`, `inspect_message`) SELECT `BotID`, `BotInspectMessage` FROM `bots`;"); @@ -1335,7 +1557,7 @@ sub get_bots_db_version{ #::: Check if bots_version column exists... if(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db){ print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;"); - print "\nColumn 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; + print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; } $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); return $bots_local_db_version; @@ -1343,15 +1565,15 @@ sub get_bots_db_version{ sub bots_db_management{ #::: Main Binary Database version - $bin_db_ver = trim($db_version[2]); + $binary_database_version = trim($db_version[2]); #::: If we have stale data from main db run if($db_run_stage > 0 && $bots_db_management == 0){ clear_database_runs(); } - if($bin_db_ver == 0){ - print "Your server binaries (world/zone) are not compiled for bots...\n"; + if($binary_database_version == 0){ + print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n"; return; } @@ -1370,7 +1592,7 @@ sub main_db_management{ } #::: Main Binary Database version - $bin_db_ver = trim($db_version[1]); + $binary_database_version = trim($db_version[1]); $bots_db_management = 0; run_database_check(); @@ -1397,22 +1619,22 @@ sub run_database_check{ if(!@total_updates){ #::: Pull down bots database manifest if($bots_db_management == 1){ - print "Retrieving latest bots database manifest...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); + print "[Database] Retrieving latest bots database manifest...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); } #::: Pull down mainstream database manifest else{ - print "Retrieving latest database manifest...\n"; - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); + print "[Database] Retrieving latest database manifest...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); } } #::: Run 2 - Running pending updates... - if(@total_updates){ + if(@total_updates || $db_run_stage == 1){ @total_updates = sort @total_updates; foreach my $val (@total_updates){ $file_name = trim($m_d{$val}[1]); - print "Running Update: " . $val . " - " . $file_name . "\n"; + print "[Database] Running Update: " . $val . " - " . $file_name . "\n"; print get_mysql_result_from_file("db_update/$file_name"); print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val"); @@ -1424,7 +1646,7 @@ sub run_database_check{ } #::: Run 1 - Initial checking of needed updates... else{ - print "Reading manifest...\n\n"; + print "[Database] Reading manifest...\n"; use Data::Dumper; open (FILE, "db_update/db_update_manifest.txt"); while () { @@ -1441,13 +1663,18 @@ sub run_database_check{ @total_updates = (); #::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest... - $revision_check = 1000; - if(get_mysql_result("SHOW TABLES LIKE 'character_data'") ne ""){ - $revision_check = 9000; + if($local_database_version){ + $revision_check = $local_database_version; + } + else { + $revision_check = 1000; + if(get_mysql_result("SHOW TABLES LIKE 'character_data'") ne ""){ + $revision_check = 9000; + } } #::: Iterate through Manifest backwards from binary version down to local version... - for($i = $bin_db_ver; $i > $revision_check; $i--){ + for($i = $binary_database_version ; $i > $revision_check; $i--){ if(!defined($m_d{$i}[0])){ next; } $file_name = trim($m_d{$i}[1]); @@ -1458,23 +1685,23 @@ sub run_database_check{ #::: Match type update if($match_type eq "contains"){ if(trim(get_mysql_result($query_check))=~/$match_text/i){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "missing"){ if(get_mysql_result($query_check)=~/$match_text/i){ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; next; } else{ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } @@ -1483,24 +1710,24 @@ sub run_database_check{ } if($match_type eq "empty"){ if(get_mysql_result($query_check) eq ""){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "not_empty"){ if(get_mysql_result($query_check) ne ""){ - print "Missing DB Update " . $i . " '" . $file_name . "' \n"; + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; fetch_missing_db_update($i, $file_name); push(@total_updates, $i); } else{ - print "DB up to date with: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; } print_match_debug(); print_break(); @@ -1509,14 +1736,14 @@ sub run_database_check{ print "\n"; if(scalar (@total_updates) == 0 && $db_run_stage == 2){ - print "No updates need to be run...\n"; + print "[Database] No updates need to be run...\n"; if($bots_db_management == 1){ - print "Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; - get_mysql_result("UPDATE db_version SET bots_version = $bin_db_ver"); + print "[Database] Setting Database to Bots Binary Version (" . $binary_database_version . ") if not already...\n\n"; + get_mysql_result("UPDATE db_version SET bots_version = $binary_database_version "); } - else{ - print "Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; - get_mysql_result("UPDATE db_version SET version = $bin_db_ver"); + else{ + print "[Database] Setting Database to Binary Version (" . $binary_database_version . ") if not already...\n\n"; + get_mysql_result("UPDATE db_version SET version = $binary_database_version "); } clear_database_runs(); @@ -1528,14 +1755,14 @@ sub fetch_missing_db_update{ $update_file = $_[1]; if($db_update >= 9000){ if($bots_db_management == 1){ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); } else{ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); } } elsif($db_update >= 5000 && $db_update <= 9000){ - get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); + get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); } } @@ -1546,7 +1773,17 @@ sub print_match_debug{ print " Query Check: '" . $query_check . "'\n"; print " Result: '" . trim(get_mysql_result($query_check)) . "'\n"; } + sub print_break{ if(!$debug){ return; } print "\n==============================================\n"; } + +sub generate_random_password { + my $passwordsize = shift; + my @alphanumeric = ('a'..'z', 'A'..'Z', 0..9); + my $randpassword = join '', + map $alphanumeric[rand @alphanumeric], 0..$passwordsize; + + return $randpassword; +} From 031a37baa171918d4282e51d1fd58dda5bdc385d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Aug 2016 01:25:22 -0500 Subject: [PATCH 338/693] Set eqemu_server.pl to check database manifest for only updates that are higher than the local database version - this will prevent false previous match conditions [skip ci] --- utils/scripts/eqemu_server.pl | 224 ++++++++++++++++++---------------- 1 file changed, 117 insertions(+), 107 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index fb8bf6e00..cb94dca0a 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -23,122 +23,40 @@ $eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/ #::: Globals $time_stamp = strftime('%m-%d-%Y', gmtime()); -$db_run_stage = 0; #::: Sets database run stage check -$console_output .= " Operating System is: $Config{osname}\n"; +$db_run_stage = 0; #::: Sets database run stage check if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } $has_internet_connection = check_internet_connection(); +($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); #::: Check for script self update do_self_update_check_routine(); - -print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n"; - -#::: Check Perl version -$perl_version = $^V; -$perl_version =~s/v//g; -print "[Update] Perl Version is " . $perl_version . "\n"; -if($perl_version > 5.12){ - no warnings 'uninitialized'; -} -no warnings; +get_perl_version(); +read_eqemu_config_xml(); +get_mysql_path(); #::: Remove old eqemu_update.pl if(-e "eqemu_update.pl"){ unlink("eqemu_update.pl"); } - -($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); - -read_eqemu_config_xml(); - -if($OS eq "Windows"){ - $has_mysql_path = `echo %PATH%`; - if($has_mysql_path=~/MySQL|MariaDB/i){ - @mysql = split(';', $has_mysql_path); - foreach my $v (@mysql){ - if($v=~/MySQL|MariaDB/i){ - $v =~s/\n//g; - $path = trim($v) . "/mysql"; - last; - } - } - } -} - -#::: Linux Check -if($OS eq "Linux"){ - $path = `which mysql`; - if ($path eq "") { - $path = `which mariadb`; - } - $path =~s/\n//g; -} - -#::: Path not found, error and exit -if($path eq ""){ - print "[Error:eqemu_server.pl] MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; - exit; -} - #::: Create db_update working directory if not created mkdir('db_update'); +print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n"; + #::: Check if db_version table exists... if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ print get_mysql_result("DROP TABLE db_version"); print "[Database] Old db_version table present, dropping...\n\n"; } -sub check_db_version_table{ - if(get_mysql_result("SHOW TABLES LIKE 'db_version'") eq "" && $db){ - print get_mysql_result(" - CREATE TABLE db_version ( - version int(11) DEFAULT '0' - ) ENGINE=InnoDB DEFAULT CHARSET=latin1; - INSERT INTO db_version (version) VALUES ('1000');"); - print "[Database] Table 'db_version' does not exists.... Creating...\n\n"; - } -} - check_db_version_table(); -if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } -if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - -$bin_db_ver = trim($db_version[1]); -$local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - -#::: If ran from Linux startup script, supress output -if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_world"){ - print "[Update] Database up to date...\n"; - exit; -} -else { - - #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup - if($local_db_ver < $bin_db_ver && $ARGV[0] eq "ran_from_world"){ - print "[Update] Database not up to date with binaries... Automatically updating...\n"; - print "[Update] Issuing database backup first...\n"; - database_dump_compress(); - print "[Update] Updating database...\n"; - sleep(1); - main_db_management(); - main_db_management(); - print "[Update] Continuing bootup\n"; - exit; - } - - #::: Make sure that we didn't pass any arugments to the script - if(!$ARGV[0]){ - if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } - show_menu_prompt(); - } -} +check_for_world_bootup_database_update(); if($db){ print "[Update] MySQL Path/Location: " . $path . "\n"; - print "[Update] Binary Revision / Local: (" . $bin_db_ver . " / " . $local_db_ver . ")\n"; + print "[Update] Binary Revision / Local: (" . $binary_database_version . " / " . $local_database_version . ")\n"; #::: Bots #::: Make sure we're running a bots binary to begin with @@ -150,7 +68,7 @@ if($db){ } #::: If World ran this script, and our version is up to date, continue... - if($bin_db_ver <= $local_db_ver && $ARGV[0] eq "ran_from_world"){ + if($binary_database_version <= $local_database_version && $ARGV[0] eq "ran_from_world"){ print "[Update] Database up to Date: Continuing World Bootup...\n"; exit; } @@ -202,8 +120,6 @@ if($ARGV[0] eq "installer"){ lua_modules_fetch(); fetch_utility_scripts(); - - #::: Database Routines print "[Database] Creating Database '" . $db_name . "'\n"; print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; @@ -212,11 +128,11 @@ if($ARGV[0] eq "installer"){ #::: Get Binary DB version if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $bin_db_ver = trim($db_version[1]); + $binary_database_version = trim($db_version[1]); #::: Local DB Version check_db_version_table(); - $local_db_ver = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); #::: Download PEQ latest fetch_peq_db_full(); @@ -244,6 +160,44 @@ if($ARGV[0] eq "login_server_setup"){ exit; } +sub check_for_world_bootup_database_update { + if($OS eq "Windows"){ + @db_version = split(': ', `world db_version`); + } + if($OS eq "Linux"){ + @db_version = split(': ', `./world db_version`); + } + + $binary_database_version = trim($db_version[1]); + $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + + if($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world"){ + print "[Update] Database up to date...\n"; + exit; + } + else { + + #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup + if($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world"){ + print "[Update] Database not up to date with binaries... Automatically updating...\n"; + print "[Update] Issuing database backup first...\n"; + database_dump_compress(); + print "[Update] Updating database...\n"; + sleep(1); + main_db_management(); + main_db_management(); + print "[Update] Continuing bootup\n"; + exit; + } + + #::: Make sure that we didn't pass any arugments to the script + if(!$ARGV[0]){ + if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } + show_menu_prompt(); + } + } +} + sub check_internet_connection { if($OS eq "Linux"){ $count = "c"; @@ -266,6 +220,17 @@ sub check_internet_connection { } } +sub get_perl_version { + #::: Check Perl version + $perl_version = $^V; + $perl_version =~s/v//g; + print "[Update] Perl Version is " . $perl_version . "\n"; + if($perl_version > 5.12){ + no warnings 'uninitialized'; + } + no warnings; +} + sub do_self_update_check_routine { #::: Check Version passed from world to update script get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); @@ -518,6 +483,35 @@ sub print_main_menu { print "Enter a command #> "; } +sub get_mysql_path { + if($OS eq "Windows"){ + $has_mysql_path = `echo %PATH%`; + if($has_mysql_path=~/MySQL|MariaDB/i){ + @mysql = split(';', $has_mysql_path); + foreach my $v (@mysql){ + if($v=~/MySQL|MariaDB/i){ + $v =~s/\n//g; + $path = trim($v) . "/mysql"; + last; + } + } + } + } + if($OS eq "Linux"){ + $path = `which mysql`; + if ($path eq "") { + $path = `which mariadb`; + } + $path =~s/\n//g; + } + + #::: Path not found, error and exit + if($path eq ""){ + print "[Error:eqemu_server.pl] MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; + exit; + } +} + sub check_for_database_dump_script{ if(`perl db_dumper.pl`=~/Need arguments/i){ return; @@ -569,6 +563,17 @@ sub script_exit{ exit; } +sub check_db_version_table{ + if(get_mysql_result("SHOW TABLES LIKE 'db_version'") eq "" && $db){ + print get_mysql_result(" + CREATE TABLE db_version ( + version int(11) DEFAULT '0' + ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + INSERT INTO db_version (version) VALUES ('1000');"); + print "[Database] Table 'db_version' does not exists.... Creating...\n\n"; + } +} + #::: Returns Tab Delimited MySQL Result from Command Line sub get_mysql_result{ my $run_query = $_[0]; @@ -1560,14 +1565,14 @@ sub get_bots_db_version{ sub bots_db_management{ #::: Main Binary Database version - $bin_db_ver = trim($db_version[2]); + $binary_database_version = trim($db_version[2]); #::: If we have stale data from main db run if($db_run_stage > 0 && $bots_db_management == 0){ clear_database_runs(); } - if($bin_db_ver == 0){ + if($binary_database_version == 0){ print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n"; return; } @@ -1587,7 +1592,7 @@ sub main_db_management{ } #::: Main Binary Database version - $bin_db_ver = trim($db_version[1]); + $binary_database_version = trim($db_version[1]); $bots_db_management = 0; run_database_check(); @@ -1658,13 +1663,18 @@ sub run_database_check{ @total_updates = (); #::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest... - $revision_check = 1000; - if(get_mysql_result("SHOW TABLES LIKE 'character_data'") ne ""){ - $revision_check = 9000; + if($local_database_version){ + $revision_check = $local_database_version; + } + else { + $revision_check = 1000; + if(get_mysql_result("SHOW TABLES LIKE 'character_data'") ne ""){ + $revision_check = 9000; + } } #::: Iterate through Manifest backwards from binary version down to local version... - for($i = $bin_db_ver; $i > $revision_check; $i--){ + for($i = $binary_database_version ; $i > $revision_check; $i--){ if(!defined($m_d{$i}[0])){ next; } $file_name = trim($m_d{$i}[1]); @@ -1728,12 +1738,12 @@ sub run_database_check{ if(scalar (@total_updates) == 0 && $db_run_stage == 2){ print "[Database] No updates need to be run...\n"; if($bots_db_management == 1){ - print "[Database] Setting Database to Bots Binary Version (" . $bin_db_ver . ") if not already...\n\n"; - get_mysql_result("UPDATE db_version SET bots_version = $bin_db_ver"); + print "[Database] Setting Database to Bots Binary Version (" . $binary_database_version . ") if not already...\n\n"; + get_mysql_result("UPDATE db_version SET bots_version = $binary_database_version "); } else{ - print "[Database] Setting Database to Binary Version (" . $bin_db_ver . ") if not already...\n\n"; - get_mysql_result("UPDATE db_version SET version = $bin_db_ver"); + print "[Database] Setting Database to Binary Version (" . $binary_database_version . ") if not already...\n\n"; + get_mysql_result("UPDATE db_version SET version = $binary_database_version "); } clear_database_runs(); From 46bb559af1ac963417d2b386caa2f0419172009c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Aug 2016 01:41:09 -0500 Subject: [PATCH 339/693] Updated db_dumper.pl script print output formats [skip ci] --- utils/scripts/db_dumper.pl | 92 +++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/utils/scripts/db_dumper.pl b/utils/scripts/db_dumper.pl index 47f14feef..af734124d 100644 --- a/utils/scripts/db_dumper.pl +++ b/utils/scripts/db_dumper.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl ############################################################ -#::: Script: DB_Dumper.pl +#::: Script: db_dumper.pl #::: Purpose: Utility to easily manage database backups and compress. #::: Export Individual DB Tables... #::: Export specific databases... @@ -24,9 +24,9 @@ if($Config{osname}=~/linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } if(!$ARGV[0]){ - print "\nERROR! Need arguments\n\n"; + print "\nERROR! Need arguments\n"; print "#::: Help :::#\n"; - print "######################################################\n\n"; + print "######################################################\n"; print "Arguments\n"; print " loc=\"C:\\File Location\" - File path location to backup...\n"; print " database=\"dbname\" - Manually specify databasename, default is database in eqemu_config.xml\n"; @@ -34,7 +34,7 @@ if(!$ARGV[0]){ print " compress - Compress Database with 7-ZIP, will fallback to WinRAR depending on what is installed (Must be installed to default program dir)...\n"; print " nolock - Does not lock tables, meant for backuping while the server is running..\n"; print " backup_name=\"name\" - Sets database backup prefix name\n"; - print ' Example: perl DB_Dumper.pl Loc="E:\Backups"' . "\n\n"; + print ' Example: perl DB_Dumper.pl Loc="E:\Backups"' . "\n"; print "######################################################\n"; exit; } @@ -57,7 +57,7 @@ while() { } $Debug = 0; -print "Arguments\n" if $Debug; +print "[db_dumper.pl] Arguments\n" if $Debug; $n = 0; while($ARGV[$n]){ print $n . ': ' . $ARGV[$n] . "\n" if $Debug; @@ -65,22 +65,22 @@ while($ARGV[$n]){ $no_lock = 1; } if($ARGV[$n]=~/compress/i){ - print "Compression SET\n"; + print "[db_dumper.pl] Compression SET\n"; $Compress = 1; } if($ARGV[$n]=~/database=/i){ @DB_NAME = split('=', $ARGV[$n]); - print "Database is " . $DB_NAME[1] . "\n"; + print "[db_dumper.pl] Database is " . $DB_NAME[1] . "\n"; $db = $DB_NAME[1]; } if($ARGV[$n]=~/backup_name=/i){ @data = split('=', $ARGV[$n]); - print "Backup Name is " . $data[1] . "\n"; + print "[db_dumper.pl] Backup Name is " . $data[1] . "\n"; $backup_name = $data[1]; } if($ARGV[$n]=~/loc=/i){ - @B_LOC = split('=', $ARGV[$n]); - print "Backup Directory: " . $B_LOC[1] . "\n"; + @backup_location = split('=', $ARGV[$n]); + print "[db_dumper.pl] Backup Directory: " . $backup_location[1] . "\n"; } if($ARGV[$n]=~/tables=/i){ @Tables = split('=', $ARGV[$n]); @TList = split(',', $Tables[1]); @@ -89,23 +89,23 @@ while($ARGV[$n]){ $t_tables_l .= $tables . "_"; $t_tables_p .= $tables . "\n"; } - print "Backing up tables: \n\n############################\n" . $t_tables_p . "############################\n\n"; + print "[db_dumper.pl] Backing up tables: \n############################\n" . $t_tables_p . "############################\n"; } $n++; } #::: Check for Backup Directory existence, if doesn't exist then create... -if (-d $B_LOC[1]) { - print "Directory currently exists... Adding files to it...\n\n"; +if (-d $backup_location[1]) { + print "[db_dumper.pl] Directory currently exists... Adding files to it...\n"; } -elsif($B_LOC[1] ne ""){ - print "Directory does NOT exist! Creating...\n\n"; - mkdir($B_LOC[1]) or die 'Failed to create folder, maybe created the folder manually at "' . $B_LOC[1]. '" ?'; +elsif($backup_location[1] ne ""){ + print "[db_dumper.pl] Directory does NOT exist! Creating...\n"; + mkdir($backup_location[1]) or die 'Failed to create folder, maybe created the folder manually at "' . $backup_location[1]. '" ?'; } else{ - print "No save location specified... Saving to folder script is running in...\n"; + print "[db_dumper.pl] No save location specified... Saving to folder script is running in...\n"; } -if($B_LOC[1] ne ""){ +if($backup_location[1] ne ""){ if($OS eq "Windows"){ $file_app = "\\"; } if($OS eq "Linux"){ $file_app = "/"; } } @@ -122,13 +122,13 @@ if($t_tables ne ""){ $target_file = '' . $tables_f_l . '_' . $date . ''; } - print "Performing table based backup...\n"; + print "[db_dumper.pl] Performing table based backup...\n"; #::: Backup Database... - print "Backing up Database " . $db . "... \n\n"; + print "[db_dumper.pl] Backing up Database " . $db . "... \n"; if($no_lock == 1){ $added_parameters .= " --skip-lock-tables "; } - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' ' . $t_tables . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; + $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' ' . $t_tables . ' > "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql"'; printcmd($cmd); system($cmd); } @@ -142,73 +142,73 @@ else{ #::: Entire DB Backup } #::: Backup Database... - print "Backing up Database " . $db . "... \n\n"; + print "[db_dumper.pl] Backing up Database " . $db . "... \n"; if($no_lock == 1){ $added_parameters .= " --skip-lock-tables "; } - $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' > "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql"'; + $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' > "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql"'; printcmd($cmd); system($cmd); } #::: Get File Size -$fileloc = '' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql'; +$fileloc = '' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql'; $filesize = -s $fileloc; -if($filesize < 1000){ print "\n" . 'Error occurred... exiting...' . "\n\n"; exit; } -print "Backup DONE... DB Backup File Size '" . $filesize . "' (" . get_filesize_str($fileloc) . ")\n\n"; +if($filesize < 1000){ print "[db_dumper.pl] " . 'Error occurred... exiting...' . "\n"; exit; } +print "[db_dumper.pl] Backup DONE... DB Backup File Size '" . $filesize . "' (" . get_filesize_str($fileloc) . ")\n"; #::: WinRar Get, check compression flag if($Compress == 1){ if($OS eq "Windows"){ if(-d $localdrive . "\\Program Files\\7-Zip"){ - print " ::: You have 7-Zip installed as 64 Bit...\n\n"; + print "[db_dumper.pl] ::: You have 7-Zip installed as 64 Bit...\n"; $S_ZIP = $localdrive . "\\Program Files\\7-Zip"; } elsif(-d $localdrive . "\\Program Files (x86)\\7-Zip"){ - print " ::: You have 7-Zip installed as 32 Bit...\n\n"; + print "[db_dumper.pl] ::: You have 7-Zip installed as 32 Bit...\n"; $S_ZIP = $localdrive . "\\Program Files (x86)\\7-Zip"; } elsif(-d $localdrive . "\\Program Files (x86)\\WinRAR"){ - print " ::: You have WinRAR installed as 32 Bit...\n\n"; + print "[db_dumper.pl] ::: You have WinRAR installed as 32 Bit...\n"; $WinRar = $localdrive . "\\Program Files (x86)\\WinRAR"; } elsif(-d $localdrive . "\\Program Files\\WinRAR"){ - print " ::: You have WinRAR installed as 64 Bit...\n\n"; + print "[db_dumper.pl] ::: You have WinRAR installed as 64 Bit...\n"; $WinRar = $localdrive . "\\Program Files\\WinRAR"; } else{ - print "No WinRAR installed... Will not compress...\n"; + print "[db_dumper.pl] No WinRAR installed... Will not compress...\n"; } if($S_ZIP ne ""){ - print "Compressing Database with 7-ZIP... \n\n"; - $cmd = '"' . $S_ZIP . '\\7z" a -t7z -m0=lzma -mx=9 "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.7z" "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql" '; + print "[db_dumper.pl] Compressing Database with 7-ZIP... \n"; + $cmd = '"' . $S_ZIP . '\\7z" a -t7z -m0=lzma -mx=9 "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.7z" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; printcmd($cmd); system($cmd); - print "\nDeleting RAW .sql Dump... \n\n"; - $cmd = 'del "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql" '; + print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; + $cmd = 'del "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; printcmd($cmd); system($cmd); $final_file = $target_file . ".7z"; } elsif($WinRar ne ""){ - print "Compressing Database with WinRAR... \n"; - $cmd = '"' . $WinRar . '\\rar" a "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.rar" "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql" '; + print "[db_dumper.pl] Compressing Database with WinRAR... \n"; + $cmd = '"' . $WinRar . '\\rar" a "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.rar" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; printcmd($cmd); system($cmd); - print "\nDeleting RAW .sql Dump... \n\n"; - $cmd = 'del "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql" '; + print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; + $cmd = 'del "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; printcmd($cmd); system($cmd); $final_file = $target_file . ".rar"; } } if($OS eq "Linux"){ - print "Compressing Database with Tarball... \n"; - $cmd = 'tar -zcvf "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.tar.gz" "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql" '; + print "[db_dumper.pl] Compressing Database with Tarball... \n"; + $cmd = 'tar -zcvf "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.tar.gz" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; printcmd($cmd); system($cmd); - print "\nDeleting RAW .sql Dump... \n\n"; - $cmd = 'rm "' . $B_LOC[1] . '' . $file_app . '' . $target_file . '.sql" '; + print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; + $cmd = 'rm "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; printcmd($cmd); system($cmd); $final_file = $target_file . ".tar.gz"; @@ -219,7 +219,7 @@ else { } #::: Get Final File Location for display -if($B_LOC[1] ne ""){ $final_loc = $B_LOC[1] . '' . $file_app . ""; } +if($backup_location[1] ne ""){ $final_loc = $backup_location[1] . '' . $file_app . ""; } else{ if($OS eq "Windows"){ $final_loc = `echo %cd%`; @@ -229,10 +229,10 @@ else{ } } -print "Final file located: " . $final_loc . "" . $final_file . "\n\n"; +print "[db_dumper.pl] Final file located: " . $final_loc . "" . $final_file . "\n"; sub printcmd{ - print "--- CMD --- \n" . $_[0] . "\n" . $linesep . "\n\n"; + print "[db_dumper.pl] Command [" . $_[0] . "]\n"; } sub get_filesize_str{ From 29d6817019ac530bf728e5ae7a4e3a7ec6a3573e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Aug 2016 03:19:33 -0500 Subject: [PATCH 340/693] More testing [skip ci] --- utils/scripts/eqemu_server.pl | 75 ++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index cb94dca0a..1bb5405e1 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -30,7 +30,7 @@ $has_internet_connection = check_internet_connection(); ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); #::: Check for script self update -do_self_update_check_routine(); +do_self_update_check_routine() if $check; get_perl_version(); read_eqemu_config_xml(); get_mysql_path(); @@ -42,7 +42,7 @@ if(-e "eqemu_update.pl"){ #::: Create db_update working directory if not created mkdir('db_update'); -print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n"; +print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n" if $ARGV[0] eq "ran_from_world"; #::: Check if db_version table exists... if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ @@ -89,7 +89,64 @@ if($ARGV[0] eq "loginserver_install_linux"){ exit; } +if($ARGV[0] eq "new_server"){ + while(1){ + print "For a new server folder install, we assume Perl and MySQL are configured\n"; + print "This will install a fresh PEQ Database, with all server assets\n"; + print "You will need to supply database credentials to get started...\n"; + + check_for_input("MySQL User: "); + $database_user = trim($input); + + check_for_input("MySQL Password: "); + $database_password = trim($input); + + $check_connection = `mysql -u $database_user -p$database_password -N -B -e "SHOW PROCESSLIST" > mysqlcheck.txt`; + $mysql_pass = 0; + open (MYSQL_CHECK, "mysqlcheck.txt"); + while (){ + chomp; + $o = $_; + if($o=~/Error/i){ $mysql_pass = 0;} + if($o=~/SHOW PROCESSLIST/i){ $mysql_pass = 1; } + } + close (MYSQL_CHECK); + unlink("mysqlcheck.txt"); + + if($mysql_pass == 1){ + print "Success! We have a database connection\n"; + + check_for_input("Specify a database name: "); + $database_name = trim($input); + + #::: Write install vars + open (INSTALL_VARS, '>', 'install_variables.txt'); + print INSTALL_VARS ""; + print INSTALL_VARS "mysql_eqemu_db_name:" . $database_name . "\n"; + print INSTALL_VARS "mysql_eqemu_user:" . $database_user . "\n"; + print INSTALL_VARS "mysql_eqemu_password:" . $database_password . "\n"; + close (INSTALL_VARS); + + do_installer_routines(); + } + else { + print "Authorization failed\n"; + } + } +} + if($ARGV[0] eq "installer"){ + do_installer_routines(); + exit; +} + +if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } +if($ARGV[0] eq "login_server_setup"){ + do_windows_login_server_setup(); + exit; +} + +sub do_installer_routines { print "[Install] Running EQEmu Server installer routines...\n"; #::: Make some local server directories... @@ -150,15 +207,13 @@ if($ARGV[0] eq "installer"){ print "[Install] Installation complete!\n"; } - - exit; } -if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } -if($ARGV[0] eq "login_server_setup"){ - do_windows_login_server_setup(); - exit; -} +sub check_for_input { + print $_[0]; + $input = ; + chomp $input; +} sub check_for_world_bootup_database_update { if($OS eq "Windows"){ @@ -1663,7 +1718,7 @@ sub run_database_check{ @total_updates = (); #::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest... - if($local_database_version){ + if($local_database_version > 9000){ $revision_check = $local_database_version; } else { From dd0d15e134d9a36c2db3ad567acdb92c998632a0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 27 Aug 2016 03:20:22 -0500 Subject: [PATCH 341/693] More testing [skip ci] --- utils/scripts/eqemu_server.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 1bb5405e1..484c5f306 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -30,7 +30,7 @@ $has_internet_connection = check_internet_connection(); ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); #::: Check for script self update -do_self_update_check_routine() if $check; +do_self_update_check_routine(); get_perl_version(); read_eqemu_config_xml(); get_mysql_path(); From ed9b6db3695c66e51b122c5e9f02e91414aaf397 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sat, 27 Aug 2016 17:22:56 -0400 Subject: [PATCH 342/693] Added optional IP-based account exemptions. --- changelog.txt | 6 + common/database.cpp | 12 ++ common/database.h | 2 + common/eqemu_logsys.h | 4 +- common/ruletypes.h | 1 + common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../git/required/2016_08_27_ip_exemptions.sql | 14 +++ world/client.cpp | 2 +- world/clientlist.cpp | 104 +++++++++--------- 10 files changed, 92 insertions(+), 56 deletions(-) create mode 100644 utils/sql/git/required/2016_08_27_ip_exemptions.sql diff --git a/changelog.txt b/changelog.txt index cde46e646..2aa32e8ac 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 08/27/2016 == +Kinglykrab: Added optional IP-based account exemptions. + - To use this system simply set World:EnableIPExemptions to true and create an entry in the ip_exemptions table. + - Example: exemption_ip of IP 192.168.1.4 in ip_exemptions with exemption_amount of 1 will allow only 1 account to login from IP 192.168.1.4. + - Note: If there is no exemption, the amount of accounts logged in from a singular IP will default to World:MaxClientsPerIP + == 08/23/2016 == noudess: Force mobs on a depop @ end pathgrid to still do this on idle zones. This makes them be more random after a zone is idle, rather than always showing diff --git a/common/database.cpp b/common/database.cpp index 6ecbb75dd..a4c862ae0 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2136,3 +2136,15 @@ bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year return results.Success(); } + +int Database::GetIPExemption(std::string account_ip) { + std::string query = StringFormat("SELECT `exemption_amount` FROM `ip_exemptions` WHERE `exemption_ip` = '%s'", account_ip.c_str()); + auto results = QueryDatabase(query); + + if (results.Success() && results.RowCount() > 0) { + auto row = results.begin(); + return atoi(row[0]); + } + + return RuleI(World, MaxClientsPerIP); +} \ No newline at end of file diff --git a/common/database.h b/common/database.h index ed08484b1..547e741e5 100644 --- a/common/database.h +++ b/common/database.h @@ -186,6 +186,8 @@ public: void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus); void SetAgreementFlag(uint32 acctid); + + int GetIPExemption(std::string account_ip); /* Groups */ diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 153d61582..bed33253c 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -83,6 +83,7 @@ namespace Logs { Server_Client_Packet_With_Dump, Client_Server_Packet_With_Dump, Login_Server, + Client_Login, MaxCategoryID /* Don't Remove this*/ }; @@ -131,7 +132,8 @@ namespace Logs { "Packet :: Client -> Server Unhandled", "Packet :: Server -> Client (Dump)", "Packet :: Client -> Server (Dump)", - "Login Server" + "Login Server", + "Client Login" }; } diff --git a/common/ruletypes.h b/common/ruletypes.h index c19ebee45..855afe3e0 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -205,6 +205,7 @@ RULE_INT(World, ExemptMaxClientsStatus, -1) // Exempt accounts from the MaxClien RULE_INT(World, AddMaxClientsPerIP, -1) // Maximum number of clients allowed to connect per IP address if account status is < ExemptMaxClientsStatus. Default value: -1 (feature disabled) RULE_INT(World, AddMaxClientsStatus, -1) // Accounts with status >= this rule will be allowed to use the amount of accounts defined in the AddMaxClientsPerIP. Default value: -1 (feature disabled) RULE_BOOL(World, MaxClientsSetByStatus, false) // If True, IP Limiting will be set to the status on the account as long as the status is > MaxClientsPerIP +RULE_BOOL(World, EnableIPExemptions, false) // If True, ip_exemptions table is used, if there is no entry for the IP it will default to RuleI(World, MaxClientsPerIP) RULE_BOOL(World, ClearTempMerchantlist, true) // Clears temp merchant items when world boots. RULE_BOOL(World, DeleteStaleCorpeBackups, true) // Deletes stale corpse backups older than 2 weeks. RULE_INT(World, AccountSessionLimit, -1) //Max number of characters allowed on at once from a single account (-1 is disabled) diff --git a/common/version.h b/common/version.h index f06a68c05..0fa1f2090 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9098 +#define CURRENT_BINARY_DATABASE_VERSION 9099 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 4030395c3..1f5beec28 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -352,6 +352,7 @@ 9096|2016_03_05_secondary_recall.sql|SHOW COLUMNS FROM `character_bind` LIKE 'slot'|empty| 9097|2016_07_03_npc_class_as_last_name.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'NPC:UseClassAsLastName'|empty| 9098|2016_08_26_object_size_tilt.sql|SHOW COLUMNS FROM `object` LIKE 'size'|empty| +9099|2016_08_27_ip_exemptions.sql|SHOW TABLES LIKE 'ip_exemptions'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2016_08_27_ip_exemptions.sql b/utils/sql/git/required/2016_08_27_ip_exemptions.sql new file mode 100644 index 000000000..9aa8582b0 --- /dev/null +++ b/utils/sql/git/required/2016_08_27_ip_exemptions.sql @@ -0,0 +1,14 @@ +-- IP Exemptions table structure +DROP TABLE IF EXISTS `ip_exemptions`; +CREATE TABLE `ip_exemptions` ( + `exemption_id` int(11) NOT NULL AUTO_INCREMENT, + `exemption_ip` varchar(255) DEFAULT NULL, + `exemption_amount` int(11) DEFAULT NULL, + PRIMARY KEY (`exemption_id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; + +-- Rule Value Entry, Default to false +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES ('1', 'World:EnableIPExemptions', 'true', 'notation'); + +-- Logging Category Entry +INSERT INTO `logsys_categories` (`log_category_id`, `log_category_description`, `log_to_console`, `log_to_file`, `log_to_gmsay`) VALUES ('44', 'Client Login', '1', '1', '1'); \ No newline at end of file diff --git a/world/client.cpp b/world/client.cpp index d2ca3705a..8d036827c 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -722,7 +722,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { return true; } - if (RuleI(World, MaxClientsPerIP) >= 0) { + if (RuleB(World, EnableIPExemptions) || RuleI(World, MaxClientsPerIP) >= 0) { client_list.GetCLEIP(this->GetIP()); //Check current CLE Entry IPs against incoming connection } diff --git a/world/clientlist.cpp b/world/clientlist.cpp index 7c83701f4..fd92051b3 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -29,6 +29,7 @@ #include "../common/classes.h" #include "../common/packet_dump.h" #include "wguild_mgr.h" +#include "../common/misc.h" #include @@ -142,7 +143,6 @@ void ClientList::EnforceSessionLimit(uint32 iLSAccountID) { //Check current CLE Entry IPs against incoming connection void ClientList::GetCLEIP(uint32 iIP) { - ClientListEntry* countCLEIPs = 0; LinkedListIterator iterator(clientlist); @@ -150,64 +150,62 @@ void ClientList::GetCLEIP(uint32 iIP) { iterator.Reset(); while(iterator.MoreElements()) { - - countCLEIPs = iterator.GetData(); - - // If the IP matches, and the connection admin status is below the exempt status, - // or exempt status is less than 0 (no-one is exempt) - if ((countCLEIPs->GetIP() == iIP) && - ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || - (RuleI(World, ExemptMaxClientsStatus) < 0))) { - - // Increment the occurences of this IP address - IPInstances++; - - // If the number of connections exceeds the lower limit - if (IPInstances > (RuleI(World, MaxClientsPerIP))) { - - // If MaxClientsSetByStatus is set to True, override other IP Limit Rules - if (RuleB(World, MaxClientsSetByStatus)) { - - // The IP Limit is set by the status of the account if status > MaxClientsPerIP - if (IPInstances > countCLEIPs->Admin()) { - - if(RuleB(World, IPLimitDisconnectAll)) { + countCLEIPs = iterator.GetData(); + if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0))) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt) + IPInstances++; // Increment the occurences of this IP address + Log.Out(Logs::General, Logs::Client_Login, "Account ID: %i Account Name: %s IP: %s.", countCLEIPs->LSID(), countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); + if (RuleB(World, EnableIPExemptions)) { + Log.Out(Logs::General, Logs::Client_Login, "Account ID: %i Account Name: %s IP: %s IP Instances: %i Max IP Instances: %i", countCLEIPs->LSID(), countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str(), IPInstances, database.GetIPExemption(long2ip(countCLEIPs->GetIP()).c_str())); + if (IPInstances > database.GetIPExemption(long2ip(countCLEIPs->GetIP()).c_str())) { + if(RuleB(World, IPLimitDisconnectAll)) { + Log.Out(Logs::General, Logs::Client_Login, "Disconnect: All accounts on IP %s", long2ip(countCLEIPs->GetIP()).c_str()); + DisconnectByIP(iIP); + return; + } else { + Log.Out(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); + countCLEIPs->SetOnline(CLE_Status_Offline); + iterator.RemoveCurrent(); + continue; + } + } + } else { + if (IPInstances > (RuleI(World, MaxClientsPerIP))) { // If the number of connections exceeds the lower limit + if (RuleB(World, MaxClientsSetByStatus)) { // If MaxClientsSetByStatus is set to True, override other IP Limit Rules + Log.Out(Logs::General, Logs::Client_Login, "Account ID: %i Account Name: %s IP: %s IP Instances: %i Max IP Instances: %i", countCLEIPs->LSID(), countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str(), IPInstances, countCLEIPs->Admin()); + if (IPInstances > countCLEIPs->Admin()) { // The IP Limit is set by the status of the account if status > MaxClientsPerIP + if(RuleB(World, IPLimitDisconnectAll)) { + Log.Out(Logs::General, Logs::Client_Login, "Disconnect: All accounts on IP %s", long2ip(countCLEIPs->GetIP()).c_str()); + DisconnectByIP(iIP); + return; + } else { + Log.Out(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); + countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection + iterator.RemoveCurrent(); + continue; + } + } + } else if ((countCLEIPs->Admin() < RuleI(World, AddMaxClientsStatus)) || (RuleI(World, AddMaxClientsStatus) < 0)) { // Else if the Admin status of the connection is not eligible for the higher limit, or there is no higher limit (AddMaxClientStatus < 0) + if(RuleB(World, IPLimitDisconnectAll)) { + Log.Out(Logs::General, Logs::Client_Login, "Disconnect: All accounts on IP %s", long2ip(countCLEIPs->GetIP()).c_str()); DisconnectByIP(iIP); return; } else { - // Remove the connection - countCLEIPs->SetOnline(CLE_Status_Offline); + Log.Out(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); + countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection + iterator.RemoveCurrent(); + continue; + } + } else if (IPInstances > RuleI(World, AddMaxClientsPerIP)) { // else they are eligible for the higher limit, but if they exceed that + if(RuleB(World, IPLimitDisconnectAll)) { + Log.Out(Logs::General, Logs::Client_Login, "Disconnect: All accounts on IP %s", long2ip(countCLEIPs->GetIP()).c_str()); + DisconnectByIP(iIP); + return; + } else { + Log.Out(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); + countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection iterator.RemoveCurrent(); continue; } - } - } - // Else if the Admin status of the connection is not eligible for the higher limit, - // or there is no higher limit (AddMaxClientStatus<0) - else if ((countCLEIPs->Admin() < (RuleI(World, AddMaxClientsStatus)) || - (RuleI(World, AddMaxClientsStatus) < 0))) { - - if(RuleB(World, IPLimitDisconnectAll)) { - DisconnectByIP(iIP); - return; - } else { - // Remove the connection - countCLEIPs->SetOnline(CLE_Status_Offline); - iterator.RemoveCurrent(); - continue; - } - } - // else they are eligible for the higher limit, but if they exceed that - else if (IPInstances > RuleI(World, AddMaxClientsPerIP)) { - - if(RuleB(World, IPLimitDisconnectAll)) { - DisconnectByIP(iIP); - return; - } else { - // Remove the connection - countCLEIPs->SetOnline(CLE_Status_Offline); - iterator.RemoveCurrent(); - continue; } } } From b7b233d46f7292c7570bb77545b41bd15da986d7 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sat, 27 Aug 2016 21:44:04 -0400 Subject: [PATCH 343/693] World:EnableIPExemptions should be false by default. (Woops.) --- utils/sql/git/required/2016_08_27_ip_exemptions.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/git/required/2016_08_27_ip_exemptions.sql b/utils/sql/git/required/2016_08_27_ip_exemptions.sql index 9aa8582b0..511dcd336 100644 --- a/utils/sql/git/required/2016_08_27_ip_exemptions.sql +++ b/utils/sql/git/required/2016_08_27_ip_exemptions.sql @@ -8,7 +8,7 @@ CREATE TABLE `ip_exemptions` ( ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; -- Rule Value Entry, Default to false -INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES ('1', 'World:EnableIPExemptions', 'true', 'notation'); +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES ('1', 'World:EnableIPExemptions', 'false', 'notation'); -- Logging Category Entry INSERT INTO `logsys_categories` (`log_category_id`, `log_category_description`, `log_to_console`, `log_to_file`, `log_to_gmsay`) VALUES ('44', 'Client Login', '1', '1', '1'); \ No newline at end of file From aaa116d97c2a8b928632148210cb880c2709a143 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 27 Aug 2016 22:24:08 -0400 Subject: [PATCH 344/693] Add support for object display names Ex. Kejek Forge in Stonebrunt Mountains --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + utils/sql/git/required/2016_08_27_object_display_name.sql | 1 + zone/object.cpp | 6 ++++++ zone/object.h | 3 +++ zone/zone.cpp | 3 ++- 6 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 utils/sql/git/required/2016_08_27_object_display_name.sql diff --git a/common/version.h b/common/version.h index 0fa1f2090..0073d5415 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9099 +#define CURRENT_BINARY_DATABASE_VERSION 9100 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 1f5beec28..5674271ae 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -353,6 +353,7 @@ 9097|2016_07_03_npc_class_as_last_name.sql|SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'NPC:UseClassAsLastName'|empty| 9098|2016_08_26_object_size_tilt.sql|SHOW COLUMNS FROM `object` LIKE 'size'|empty| 9099|2016_08_27_ip_exemptions.sql|SHOW TABLES LIKE 'ip_exemptions'|empty| +9100|2016_08_27_object_display_name.sql|SHOW COLUMNS FROM `object` LIKE 'display_name'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2016_08_27_object_display_name.sql b/utils/sql/git/required/2016_08_27_object_display_name.sql new file mode 100644 index 000000000..fbc3e90cd --- /dev/null +++ b/utils/sql/git/required/2016_08_27_object_display_name.sql @@ -0,0 +1 @@ +ALTER TABLE `object` ADD COLUMN `display_name` VARCHAR(64); diff --git a/zone/object.cpp b/zone/object.cpp index a9672ee4f..c00f718b3 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -543,6 +543,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) coa->drop_id = click_object->drop_id; coa->player_id = click_object->player_id; coa->icon = m_icon; + strn0cpy(coa->object_name, m_display_name, 64); //if this is not the main user, send them a close and a message if (user == nullptr || user == sender) { @@ -821,6 +822,11 @@ void Object::SetTiltY(float pos) safe_delete(app2); } +void Object::SetDisplayName(const char *in_name) +{ + strn0cpy(m_display_name, in_name, 64); +} + void Object::Depop() { auto app = new EQApplicationPacket(); diff --git a/zone/object.h b/zone/object.h index 896fc4276..23c152cea 100644 --- a/zone/object.h +++ b/zone/object.h @@ -164,6 +164,8 @@ public: void SetSize(float size); uint16 GetSolidType(); void SetSolidType(uint16 size); + void SetDisplayName(const char *in_name); + const char *GetDisplayName() const { return m_display_name; } const char* GetEntityVariable(const char *id); void SetEntityVariable(const char *id, const char *m_var); @@ -186,6 +188,7 @@ protected: float m_z; float m_heading; bool m_ground_spawn; + char m_display_name[64]; std::map o_EntityVariables; diff --git a/zone/zone.cpp b/zone/zone.cpp index 3dd8e55d8..6aa5c9369 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -162,7 +162,7 @@ bool Zone::LoadZoneObjects() { std::string query = StringFormat("SELECT id, zoneid, xpos, ypos, zpos, heading, " "itemid, charges, objectname, type, icon, unknown08, " "unknown10, unknown20, unknown24, unknown76, size, tilt_x, " - "tilt_y FROM object " + "tilt_y, display_name FROM object " "WHERE zoneid = %i AND (version = %u OR version = -1)", zoneid, instanceversion); auto results = database.QueryDatabase(query); @@ -275,6 +275,7 @@ bool Zone::LoadZoneObjects() { } auto object = new Object(id, type, icon, data, inst); + object->SetDisplayName(row[19]); entity_list.AddObject(object, false); if (type == OT_DROPPEDITEM && itemid != 0) entity_list.RemoveObject(object->GetID()); From 89183cf8b7a7378d4043da9516e2830d3bcdf77a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 27 Aug 2016 22:26:44 -0400 Subject: [PATCH 345/693] clang-format LoadZoneObjects --- zone/zone.cpp | 218 +++++++++++++++++++++++++------------------------- 1 file changed, 108 insertions(+), 110 deletions(-) diff --git a/zone/zone.cpp b/zone/zone.cpp index 6aa5c9369..35b2d52bb 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -157,131 +157,129 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { } //this really loads the objects into entity_list -bool Zone::LoadZoneObjects() { - - std::string query = StringFormat("SELECT id, zoneid, xpos, ypos, zpos, heading, " - "itemid, charges, objectname, type, icon, unknown08, " - "unknown10, unknown20, unknown24, unknown76, size, tilt_x, " - "tilt_y, display_name FROM object " - "WHERE zoneid = %i AND (version = %u OR version = -1)", - zoneid, instanceversion); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - Log.Out(Logs::General, Logs::Error, "Error Loading Objects from DB: %s",results.ErrorMessage().c_str()); +bool Zone::LoadZoneObjects() +{ + std::string query = + StringFormat("SELECT id, zoneid, xpos, ypos, zpos, heading, itemid, charges, objectname, type, icon, " + "unknown08, unknown10, unknown20, unknown24, unknown76, size, tilt_x, tilt_y, display_name " + "FROM object WHERE zoneid = %i AND (version = %u OR version = -1)", + zoneid, instanceversion); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + Log.Out(Logs::General, Logs::Error, "Error Loading Objects from DB: %s", + results.ErrorMessage().c_str()); return false; - } - - Log.Out(Logs::General, Logs::Status, "Loading Objects from DB..."); - for (auto row = results.begin(); row != results.end(); ++row) { - if (atoi(row[9]) == 0) - { - // Type == 0 - Static Object - const char* shortname = database.GetZoneName(atoi(row[1]), false); // zoneid -> zone_shortname - - if (!shortname) - continue; - - Door d; - memset(&d, 0, sizeof(d)); - - strn0cpy(d.zone_name, shortname, sizeof(d.zone_name)); - d.db_id = 1000000000 + atoi(row[0]); // Out of range of normal use for doors.id - d.door_id = -1; // Client doesn't care if these are all the same door_id - d.pos_x = atof(row[2]); // xpos - d.pos_y = atof(row[3]); // ypos - d.pos_z = atof(row[4]); // zpos - d.heading = atof(row[5]); // heading - - strn0cpy(d.door_name, row[8], sizeof(d.door_name)); // objectname - // Strip trailing "_ACTORDEF" if present. Client won't accept it for doors. - int len = strlen(d.door_name); - if ((len > 9) && (memcmp(&d.door_name[len - 9], "_ACTORDEF", 10) == 0)) - d.door_name[len - 9] = '\0'; - - memcpy(d.dest_zone, "NONE", 5); - - if ((d.size = atoi(row[11])) == 0) // unknown08 = optional size percentage - d.size = 100; - - switch (d.opentype = atoi(row[12])) // unknown10 = optional request_nonsolid (0 or 1 or experimental number) - { - case 0: - d.opentype = 31; - break; - case 1: - d.opentype = 9; - break; - } - - d.incline = atoi(row[13]); // unknown20 = optional model incline value - d.client_version_mask = 0xFFFFFFFF; //We should load the mask from the zone. - - auto door = new Doors(&d); - entity_list.AddDoor(door); } - Object_Struct data = {0}; - uint32 id = 0; - uint32 icon = 0; - uint32 type = 0; - uint32 itemid = 0; - uint32 idx = 0; - int16 charges = 0; + Log.Out(Logs::General, Logs::Status, "Loading Objects from DB..."); + for (auto row = results.begin(); row != results.end(); ++row) { + if (atoi(row[9]) == 0) { + // Type == 0 - Static Object + const char *shortname = database.GetZoneName(atoi(row[1]), false); // zoneid -> zone_shortname - id = (uint32)atoi(row[0]); - data.zone_id = atoi(row[1]); - data.x = atof(row[2]); - data.y = atof(row[3]); - data.z = atof(row[4]); - data.heading = atof(row[5]); + if (!shortname) + continue; + + Door d; + memset(&d, 0, sizeof(d)); + + strn0cpy(d.zone_name, shortname, sizeof(d.zone_name)); + d.db_id = 1000000000 + atoi(row[0]); // Out of range of normal use for doors.id + d.door_id = -1; // Client doesn't care if these are all the same door_id + d.pos_x = atof(row[2]); // xpos + d.pos_y = atof(row[3]); // ypos + d.pos_z = atof(row[4]); // zpos + d.heading = atof(row[5]); // heading + + strn0cpy(d.door_name, row[8], sizeof(d.door_name)); // objectname + // Strip trailing "_ACTORDEF" if present. Client won't accept it for doors. + int len = strlen(d.door_name); + if ((len > 9) && (memcmp(&d.door_name[len - 9], "_ACTORDEF", 10) == 0)) + d.door_name[len - 9] = '\0'; + + memcpy(d.dest_zone, "NONE", 5); + + if ((d.size = atoi(row[11])) == 0) // unknown08 = optional size percentage + d.size = 100; + + switch (d.opentype = atoi(row[12])) // unknown10 = optional request_nonsolid (0 or 1 or experimental number) + { + case 0: + d.opentype = 31; + break; + case 1: + d.opentype = 9; + break; + } + + d.incline = atoi(row[13]); // unknown20 = optional model incline value + d.client_version_mask = 0xFFFFFFFF; // We should load the mask from the zone. + + auto door = new Doors(&d); + entity_list.AddDoor(door); + } + + Object_Struct data = {0}; + uint32 id = 0; + uint32 icon = 0; + uint32 type = 0; + uint32 itemid = 0; + uint32 idx = 0; + int16 charges = 0; + + id = (uint32)atoi(row[0]); + data.zone_id = atoi(row[1]); + data.x = atof(row[2]); + data.y = atof(row[3]); + data.z = atof(row[4]); + data.heading = atof(row[5]); itemid = (uint32)atoi(row[6]); - charges = (int16)atoi(row[7]); - strcpy(data.object_name, row[8]); - type = (uint8)atoi(row[9]); - icon = (uint32)atoi(row[10]); + charges = (int16)atoi(row[7]); + strcpy(data.object_name, row[8]); + type = (uint8)atoi(row[9]); + icon = (uint32)atoi(row[10]); data.object_type = type; data.linked_list_addr[0] = 0; - data.linked_list_addr[1] = 0; - - data.solidtype = (uint32)atoi(row[12]); - data.unknown020 = (uint32)atoi(row[13]); - data.unknown024 = (uint32)atoi(row[14]); - data.unknown076 = (uint32)atoi(row[15]); - data.size = atof(row[16]); + data.linked_list_addr[1] = 0; + + data.solidtype = (uint32)atoi(row[12]); + data.unknown020 = (uint32)atoi(row[13]); + data.unknown024 = (uint32)atoi(row[14]); + data.unknown076 = (uint32)atoi(row[15]); + data.size = atof(row[16]); data.tilt_x = atof(row[17]); data.tilt_y = atof(row[18]); - data.unknown084 = 0; + data.unknown084 = 0; - ItemInst* inst = nullptr; - //FatherNitwit: this dosent seem to work... - //tradeskill containers do not have an itemid of 0... at least what I am seeing - if (itemid == 0) { - // Generic tradeskill container - inst = new ItemInst(ItemInstWorldContainer); - } - else { - // Groundspawn object - inst = database.CreateItem(itemid); - } + ItemInst *inst = nullptr; + // FatherNitwit: this dosent seem to work... + // tradeskill containers do not have an itemid of 0... at least what I am seeing + if (itemid == 0) { + // Generic tradeskill container + inst = new ItemInst(ItemInstWorldContainer); + } else { + // Groundspawn object + inst = database.CreateItem(itemid); + } - //Father Nitwit's fix... not perfect... - if(inst == nullptr && type != OT_DROPPEDITEM) { - inst = new ItemInst(ItemInstWorldContainer); - } + // Father Nitwit's fix... not perfect... + if (inst == nullptr && type != OT_DROPPEDITEM) { + inst = new ItemInst(ItemInstWorldContainer); + } - // Load child objects if container + // Load child objects if container if (inst && inst->IsType(EQEmu::item::ItemClassBag)) { - database.LoadWorldContainer(id, inst); - } + database.LoadWorldContainer(id, inst); + } - auto object = new Object(id, type, icon, data, inst); - object->SetDisplayName(row[19]); - entity_list.AddObject(object, false); - if (type == OT_DROPPEDITEM && itemid != 0) - entity_list.RemoveObject(object->GetID()); + auto object = new Object(id, type, icon, data, inst); + object->SetDisplayName(row[19]); + entity_list.AddObject(object, false); + if (type == OT_DROPPEDITEM && itemid != 0) + entity_list.RemoveObject(object->GetID()); - safe_delete(inst); - } + safe_delete(inst); + } return true; } From 364ab42c49d0b7384c6cf160bdddaa2f7338d1b0 Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Sun, 28 Aug 2016 07:00:20 -0500 Subject: [PATCH 346/693] Add rule to ignore MQ2 targeting --- common/ruletypes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/ruletypes.h b/common/ruletypes.h index 855afe3e0..94d669386 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -144,6 +144,7 @@ RULE_BOOL(Character, RestrictSpellScribing, false) // Restricts spell scribing t RULE_BOOL(Character, UseStackablePickPocketing, true) // Allows stackable pickpocketed items to stack instead of only being allowed in empty inventory slots RULE_BOOL(Character, EnableAvoidanceCap, false) RULE_INT(Character, AvoidanceCap, 750) // 750 Is a pretty good value, seen people dodge all attacks beyond 1,000 Avoidance +RULE_BOOL(Character, AllowMQTarget, false) // Disables putting players in the 'hackers' list for targeting beyond the clip plane or attempting to target something untargetable RULE_CATEGORY_END() RULE_CATEGORY(Mercs) From bfb77803d84b2d1632749cc011e972555829706d Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Sun, 28 Aug 2016 07:03:00 -0500 Subject: [PATCH 347/693] Update client_packet.cpp --- zone/client_packet.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 37108697c..cd74af8e8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -13093,6 +13093,11 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) GetTarget()->IsTargeted(1); return; } + else if (RuleB(Character, AllowMQTarget)) + { + + GetTarget()->IsTargeted(1); + + return; + + } else if (IsAssistExempted()) { GetTarget()->IsTargeted(1); From 585e5830f786d80b2915141e2c79aca7ad814fb3 Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Sun, 28 Aug 2016 12:23:59 -0500 Subject: [PATCH 348/693] Update client_packet.cpp --- zone/client_packet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index cd74af8e8..fa253664b 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -13095,9 +13095,9 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) } else if (RuleB(Character, AllowMQTarget)) { - + GetTarget()->IsTargeted(1); - + return; - + } + GetTarget()->IsTargeted(1); + return; + } else if (IsAssistExempted()) { GetTarget()->IsTargeted(1); From ea1ae1a0a4477141e049a51a992e85adc8106ebe Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 29 Aug 2016 13:27:42 -0400 Subject: [PATCH 349/693] Use StopCasting instead of Interrupt on SpellFinished failure Most of these failures already show a message, live doesn't double up on failure message + interrupt message, so lets not There are a few logic error returns, but those really shouldn't happen --- zone/spells.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index e12f8042f..42457c93f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1310,7 +1310,9 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo if( !SpellFinished(spell_id, spell_target, slot, mana_used, inventory_slot, resist_adjust) ) { Log.Out(Logs::Detail, Logs::Spells, "Casting of %d canceled: SpellFinished returned false.", spell_id); - InterruptSpell(); + // most of the cases we return false have a message already or are logic errors that shouldn't happen + // if there are issues I guess we can do something else, but this should work + StopCasting(); return; } From fa337d441efaca9bab229c1ab9f97bfe80f3deee Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 29 Aug 2016 14:08:22 -0400 Subject: [PATCH 350/693] Use StopCasting when we send SPELL_RECAST error --- zone/spells.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 42457c93f..2e99e97a9 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -928,7 +928,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo //should we issue a message or send them a spell gem packet? Message_StringID(13, SPELL_RECAST); Log.Out(Logs::Detail, Logs::Spells, "Casting of %d canceled: spell reuse timer not expired", spell_id); - InterruptSpell(); + StopCasting(); return; } } @@ -942,7 +942,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo if(!CastToClient()->GetPTimers().Expired(&database, (pTimerItemStart + itm->GetItem()->RecastType), false)) { Message_StringID(13, SPELL_RECAST); Log.Out(Logs::Detail, Logs::Spells, "Casting of %d canceled: item spell reuse timer not expired", spell_id); - InterruptSpell(); + StopCasting(); return; } } @@ -1271,7 +1271,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo if(!CastToClient()->GetPTimers().Expired(&database, (pTimerItemStart + recasttype), false)) { Message_StringID(13, SPELL_RECAST); Log.Out(Logs::Detail, Logs::Spells, "Casting of %d canceled: item spell reuse timer not expired", spell_id); - InterruptSpell(); + StopCasting(); return; } else From d8fe5124ffe29c018792b3e5aaac9ffcadc79c59 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 29 Aug 2016 19:23:40 -0400 Subject: [PATCH 351/693] Fix some spell set loading issues --- common/patches/sod.cpp | 4 +++- common/patches/sof.cpp | 15 +++++++++++++++ common/patches/sof_ops.h | 1 + common/patches/sof_structs.h | 5 +++++ common/patches/titanium.cpp | 15 +++++++++++++++ common/patches/titanium_ops.h | 1 + common/patches/titanium_structs.h | 5 +++++ common/patches/uf_structs.h | 7 +++---- 8 files changed, 48 insertions(+), 5 deletions(-) diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index e23c1ca78..c1d573020 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -3246,8 +3246,10 @@ namespace SoD DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); - for (uint32 i = 0; i < MAX_PP_MEMSPELL; ++i) + for (int i = 0; i < structs::MAX_PP_MEMSPELL; ++i) emu->spell[i] = eq->spell[i]; + for (int i = structs::MAX_PP_MEMSPELL; i < MAX_PP_MEMSPELL; ++i) + emu->spell[i] = 0xFFFFFFFF; FINISH_DIRECT_DECODE(); } diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 3ab4a7631..bfad8d296 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2623,6 +2623,21 @@ namespace SoF FINISH_DIRECT_DECODE(); } + DECODE(OP_LoadSpellSet) + { + DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); + SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); + + for (int i = 0; i < structs::MAX_PP_MEMSPELL; ++i) + IN(spell[i]); + for (int i = structs::MAX_PP_MEMSPELL; i < MAX_PP_MEMSPELL; ++i) + emu->spell[i] = 0xFFFFFFFF; + + IN(unknown); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_LootItem) { DECODE_LENGTH_EXACT(structs::LootingItem_Struct); diff --git a/common/patches/sof_ops.h b/common/patches/sof_ops.h index 68ff402f1..180857388 100644 --- a/common/patches/sof_ops.h +++ b/common/patches/sof_ops.h @@ -111,6 +111,7 @@ D(OP_GroupFollow2) D(OP_InspectRequest) D(OP_ItemLinkClick) D(OP_ItemVerifyRequest) +D(OP_LoadSpellSet) D(OP_LootItem) D(OP_MoveItem) D(OP_PetCommands) diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 3c0861f42..0981fd4ee 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -3728,6 +3728,11 @@ struct AnnoyingZoneUnknown_Struct { uint32 value; //always 4 }; +struct LoadSpellSet_Struct { + uint32 spell[MAX_PP_MEMSPELL]; + uint32 unknown; +}; + struct BlockedBuffs_Struct { /*000*/ uint8 unknown000[80]; /*080*/ uint8 unknown081; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 9e93051b1..72b492eeb 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1978,6 +1978,21 @@ namespace Titanium FINISH_DIRECT_DECODE(); } + DECODE(OP_LoadSpellSet) + { + DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); + SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); + + for (int i = 0; i < structs::MAX_PP_MEMSPELL; ++i) + IN(spell[i]); + for (int i = structs::MAX_PP_MEMSPELL; i < MAX_PP_MEMSPELL; ++i) + emu->spell[i] = 0xFFFFFFFF; + + IN(unknown); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_LootItem) { DECODE_LENGTH_EXACT(structs::LootingItem_Struct); diff --git a/common/patches/titanium_ops.h b/common/patches/titanium_ops.h index 5e65dd7c0..9f77a7077 100644 --- a/common/patches/titanium_ops.h +++ b/common/patches/titanium_ops.h @@ -89,6 +89,7 @@ D(OP_InspectAnswer) D(OP_InspectRequest) D(OP_ItemLinkClick) D(OP_LFGuild) +D(OP_LoadSpellSet) D(OP_LootItem) D(OP_MoveItem) D(OP_PetCommands) diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index c6a5e6a49..c4f6d4959 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -3228,6 +3228,11 @@ struct AnnoyingZoneUnknown_Struct { uint32 value; //always 4 }; +struct LoadSpellSet_Struct { + uint32 spell[MAX_PP_MEMSPELL]; + uint32 unknown; +}; + struct ApplyPoison_Struct { uint32 inventorySlot; uint32 success; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 1ba5616dd..8decaa04a 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -847,7 +847,7 @@ struct BindStruct { */ static const uint32 MAX_PP_LANGUAGE = 25; // static const uint32 MAX_PP_SPELLBOOK = 720; // Confirmed 60 pages on Underfoot now -static const uint32 MAX_PP_MEMSPELL = 10; //was 9 now 10 on Underfoot +static const uint32 MAX_PP_MEMSPELL = 12; //was 9 now 10 on Underfoot static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size static const uint32 MAX_PP_AA_ARRAY = 300; //was 299 static const uint32 MAX_GROUP_MEMBERS = 6; @@ -917,7 +917,7 @@ struct PlayerProfile_Struct /*00160*/ uint32 deity; // deity /*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?) /*00168*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis) - 4 Octets Each -/*00208*/ uint8 unknown00208[14]; // Seen 00 00 00 00 00 00 00 00 00 00 00 00 02 01 +/*00208*/ uint8 unknown00208[6]; // Seen 00 00 00 00 00 00 00 00 00 00 00 00 02 01 /*00222*/ uint32 abilitySlotRefresh; /*00226*/ uint8 haircolor; // Player hair color /*00227*/ uint8 beardcolor; // Player beard color @@ -945,7 +945,7 @@ struct PlayerProfile_Struct /*04217*/ uint8 unknown04217[147]; // was [175] /*04364*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880] was [1920] /*07244*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized -/*07284*/ uint8 unknown07284[28]; //#### uint8 unknown04396[32]; in Titanium ####[28] +/*07284*/ uint8 unknown07284[20]; //#### uint8 unknown04396[32]; in Titanium ####[28] /*07312*/ uint32 platinum; // Platinum Pieces on player /*07316*/ uint32 gold; // Gold Pieces on player /*07320*/ uint32 silver; // Silver Pieces on player @@ -3928,7 +3928,6 @@ struct AnnoyingZoneUnknown_Struct { struct LoadSpellSet_Struct { uint8 spell[MAX_PP_MEMSPELL]; // 0 if no action - uint16 unknown2; // is this two more spell gems? uint32 unknown; // there seems to be an extra field in this packet... }; From 159ba9f487d963d8fff649ff28bf99274d16b2df Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 31 Aug 2016 23:02:16 -0400 Subject: [PATCH 352/693] Fix for BotDatabase::SaveEquipmentColor crash --- zone/bot_database.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index db9827a8a..182f4e09f 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1317,8 +1317,8 @@ bool BotDatabase::SaveEquipmentColor(const uint32 bot_id, const int16 slot_id, c " WHERE `bot_id` = '%u'" " %s", rgb, - where_clause.c_str(), - bot_id + bot_id, + where_clause.c_str() ); auto results = QueryDatabase(query); if (!results.Success()) From ec87656d583c100624bf42daaf6e315ce22e3e35 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 1 Sep 2016 01:05:06 -0500 Subject: [PATCH 353/693] Add rule Spells:NPCInnateProcOverride, defaults to true --- common/ruletypes.h | 1 + zone/mob_ai.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 94d669386..f1898a559 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -384,6 +384,7 @@ RULE_BOOL(Spells, AlwaysSendTargetsBuffs, false) // ignore LAA level if true RULE_BOOL(Spells, FlatItemExtraSpellAmt, false) // allow SpellDmg stat to affect all spells, regardless of cast time/cooldown/etc RULE_BOOL(Spells, IgnoreSpellDmgLvlRestriction, false) // ignore the 5 level spread on applying SpellDmg RULE_BOOL(Spells, AllowItemTGB, false) // TGB doesn't work with items on live, custom servers want it though +RULE_BOOL(Spells, NPCInnateProcOverride, true) // NPC innate procs override the target type to single target. RULE_CATEGORY_END() RULE_CATEGORY(Combat) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index eb14865ce..f09df1e7f 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2364,7 +2364,9 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { if (IsValidSpell(attack_proc_spell)) { AddProcToWeapon(attack_proc_spell, true, proc_chance); - innate_proc_spell_id = attack_proc_spell; + + if(RuleB(Spells, NPCInnateProcOverride)) + innate_proc_spell_id = attack_proc_spell; } if (IsValidSpell(range_proc_spell)) From 7c40bcff533240c9c0f62825465af9dc185aa47f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 2 Sep 2016 18:16:09 -0400 Subject: [PATCH 354/693] Fix enrage for NPC classes that can't ripo --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index ed6a26daf..991e251f3 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -373,7 +373,7 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) // riposte -- it may seem crazy, but if the attacker has SPA 173 on them, they are immune to Ripo bool ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance; // Need to check if we have something in MainHand to actually attack with (or fists) - if (hand != EQEmu::legacy::SlotRange && CanThisClassRiposte() && InFront && !ImmuneRipo) { + if (hand != EQEmu::legacy::SlotRange && (CanThisClassRiposte() || IsEnraged()) && InFront && !ImmuneRipo) { if (IsEnraged()) { damage = -3; Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack."); From fb308eaa01f4555d3433b21beed01980ab891c6d Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 3 Sep 2016 17:08:48 -0400 Subject: [PATCH 355/693] Rule-based update to 'Bind Wound' behavior --- changelog.txt | 4 + common/ruletypes.h | 2 + .../2016_09_03_old_bind_wound_rule.sql | 1 + zone/client.cpp | 148 ++++++++++++------ 4 files changed, 111 insertions(+), 44 deletions(-) create mode 100644 utils/sql/git/optional/2016_09_03_old_bind_wound_rule.sql diff --git a/changelog.txt b/changelog.txt index 2aa32e8ac..b2d7c7b05 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/03/2016 == +Uleat: Changed 'Bind Wound' behavior to match the best references that I could find for post-2004 era. + Note: If you wish to retain the old method, source in the optional '2016_09_03_old_bind_wound_rule.sql' script file. + == 08/27/2016 == Kinglykrab: Added optional IP-based account exemptions. - To use this system simply set World:EnableIPExemptions to true and create an entry in the ip_exemptions table. diff --git a/common/ruletypes.h b/common/ruletypes.h index f1898a559..7837834f9 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -145,6 +145,8 @@ RULE_BOOL(Character, UseStackablePickPocketing, true) // Allows stackable pickpo RULE_BOOL(Character, EnableAvoidanceCap, false) RULE_INT(Character, AvoidanceCap, 750) // 750 Is a pretty good value, seen people dodge all attacks beyond 1,000 Avoidance RULE_BOOL(Character, AllowMQTarget, false) // Disables putting players in the 'hackers' list for targeting beyond the clip plane or attempting to target something untargetable +RULE_BOOL(Character, UseOldBindWound, false) // Uses the original bind wound behavior + RULE_CATEGORY_END() RULE_CATEGORY(Mercs) diff --git a/utils/sql/git/optional/2016_09_03_old_bind_wound_rule.sql b/utils/sql/git/optional/2016_09_03_old_bind_wound_rule.sql new file mode 100644 index 000000000..87791d59b --- /dev/null +++ b/utils/sql/git/optional/2016_09_03_old_bind_wound_rule.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Character:UseOldBindWound', 'true', 'Uses the original bind wound behavior'); diff --git a/zone/client.cpp b/zone/client.cpp index 59998bfdb..3a7b60eb5 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2655,60 +2655,120 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail) bind_out->type = 0; CheckIncreaseSkill(EQEmu::skills::SkillBindWound, nullptr, 5); - int maxHPBonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound + - aabonuses.MaxBindWound; + if (RuleB(Character, UseOldBindWound)) { + int maxHPBonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound + + aabonuses.MaxBindWound; - int max_percent = 50 + 10 * maxHPBonus; + int max_percent = 50 + maxHPBonus; - if (GetClass() == MONK && GetSkill(EQEmu::skills::SkillBindWound) > 200) { - max_percent = 70 + 10 * maxHPBonus; - } - - max_percent = mod_bindwound_percent(max_percent, bindmob); - - int max_hp = bindmob->GetMaxHP() * max_percent / 100; - - // send bindmob new hp's - if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() <= (max_hp)-1) { - // 0.120 per skill point, 0.60 per skill level, minimum 3 max 30 - int bindhps = 3; - - if (GetSkill(EQEmu::skills::SkillBindWound) > 200) { - bindhps += GetSkill(EQEmu::skills::SkillBindWound) * 4 / 10; - } - else if (GetSkill(EQEmu::skills::SkillBindWound) >= 10) { - bindhps += GetSkill(EQEmu::skills::SkillBindWound) / 4; + if (GetClass() == MONK && GetSkill(EQEmu::skills::SkillBindWound) > 200) { + max_percent = 70 + maxHPBonus; } - // Implementation of aaMithanielsBinding is a guess (the multiplier) - int bindBonus = spellbonuses.BindWound + itembonuses.BindWound + + max_percent = mod_bindwound_percent(max_percent, bindmob); + + int max_hp = bindmob->GetMaxHP() * max_percent / 100; + + // send bindmob new hp's + if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() <= (max_hp)-1) { + // 0.120 per skill point, 0.60 per skill level, minimum 3 max 30 + int bindhps = 3; + + if (GetSkill(EQEmu::skills::SkillBindWound) > 200) { + bindhps += GetSkill(EQEmu::skills::SkillBindWound) * 4 / 10; + } + else if (GetSkill(EQEmu::skills::SkillBindWound) >= 10) { + bindhps += GetSkill(EQEmu::skills::SkillBindWound) / 4; + } + + // Implementation of aaMithanielsBinding is a guess (the multiplier) + int bindBonus = spellbonuses.BindWound + itembonuses.BindWound + aabonuses.BindWound; - bindhps += bindhps * bindBonus / 100; + bindhps += bindhps * bindBonus / 100; - bindhps = mod_bindwound_hp(bindhps, bindmob); + bindhps = mod_bindwound_hp(bindhps, bindmob); - // if the bind takes them above the max bindable - // cap it at that value. Dont know if live does it this way - // but it makes sense to me. - int chp = bindmob->GetHP() + bindhps; - if (chp > max_hp) - chp = max_hp; + // if the bind takes them above the max bindable + // cap it at that value. Dont know if live does it this way + // but it makes sense to me. + int chp = bindmob->GetHP() + bindhps; + if (chp > max_hp) + chp = max_hp; - bindmob->SetHP(chp); - bindmob->SendHPUpdate(); - } else { - // I dont have the real, live - Message(15, "You cannot bind wounds above %d%% hitpoints.", - max_percent); - if (bindmob != this && bindmob->IsClient()) - bindmob->CastToClient()->Message( - 15, - "You cannot have your wounds bound above %d%% hitpoints.", - max_percent); - // Too many hp message goes here. + bindmob->SetHP(chp); + bindmob->SendHPUpdate(); + } + else { + // I dont have the real, live + Message(15, "You cannot bind wounds above %d%% hitpoints.", + max_percent); + if (bindmob != this && bindmob->IsClient()) + bindmob->CastToClient()->Message( + 15, + "You cannot have your wounds bound above %d%% hitpoints.", + max_percent); + // Too many hp message goes here. + } } - } else { + else { + int percent_base = 50; + if (GetRawSkill(EQEmu::skills::SkillBindWound) > 200) { + if ((GetClass() == MONK) || (GetClass() == BEASTLORD)) + percent_base = 70; + else if ((GetLevel() > 50) && ((GetClass() == WARRIOR) || (GetClass() == ROGUE) || (GetClass() == CLERIC))) + percent_base = 70; + } + + int percent_bonus = 0; + if (percent_base >= 70) + percent_bonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound + aabonuses.MaxBindWound; + + int max_percent = percent_base + percent_bonus; + if (max_percent < 0) + max_percent = 0; + if (max_percent > 100) + max_percent = 100; + + max_percent = mod_bindwound_percent(max_percent, bindmob); + + int max_hp = (bindmob->GetMaxHP() * max_percent) / 100; + if (max_hp > bindmob->GetMaxHP()) + max_hp = bindmob->GetMaxHP(); + + if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() < max_hp) { + int bindhps = 3; // base bind hp + if (percent_base >= 70) + bindhps = (GetSkill(EQEmu::skills::SkillBindWound) * 4) / 10; // 8:5 skill-to-hp ratio + else if (GetSkill(EQEmu::skills::SkillBindWound) >= 12) + bindhps = GetSkill(EQEmu::skills::SkillBindWound) / 4; // 4:1 skill-to-hp ratio + + int bonus_hp_percent = 0; + if (percent_base >= 70) + bonus_hp_percent = spellbonuses.BindWound + itembonuses.BindWound + aabonuses.BindWound; + + bindhps += (bindhps * bonus_hp_percent) / 100; + + if (bindhps < 3) + bindhps = 3; + + bindhps = mod_bindwound_hp(bindhps, bindmob); + + bindhps += bindmob->GetHP(); + if (bindhps > max_hp) + bindhps = max_hp; + + bindmob->SetHP(bindhps); + bindmob->SendHPUpdate(); + } + else { + Message(15, "You cannot bind wounds above %d%% hitpoints", max_percent); + if (bindmob != this && bindmob->IsClient()) + bindmob->CastToClient()->Message(15, "You cannot have your wounds bound above %d%% hitpoints", max_percent); + } + } + } + else { // Send client bind failed if (bindmob != this) bind_out->type = 6; // They moved From 739b1bfaa32b5af433e00208e63727136c0f0d79 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 3 Sep 2016 21:54:59 -0400 Subject: [PATCH 356/693] Fix target buffs showing PC songs --- zone/spells.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 2e99e97a9..c818c8e90 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5458,8 +5458,10 @@ void Mob::SendBuffsToClient(Client *c) EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) { uint32 count = 0; - uint32 buff_count = GetMaxTotalSlots(); - for(unsigned int i = 0; i < buff_count; ++i) + // for self we want all buffs, for target, we want to skip song window buffs + // since NPCs and pets don't have a song window, we still see it for them :P + uint32 buff_count = for_target ? GetMaxBuffSlots() : GetMaxTotalSlots(); + for(int i = 0; i < buff_count; ++i) { if(buffs[i].spellid != SPELL_UNKNOWN) { @@ -5491,7 +5493,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target) buff->type = 0; uint32 index = 0; - for(unsigned int i = 0; i < buff_count; ++i) + for(int i = 0; i < buff_count; ++i) { if(buffs[i].spellid != SPELL_UNKNOWN) { From d0bb3047f03e3471b965917c2d8527bdd1a72b08 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 4 Sep 2016 20:59:39 -0400 Subject: [PATCH 357/693] Let's fix the fear pathing flags right away after SE_ImmuneFleeing This speeds up the response to spells like Call of Challenge Before it would fix the flags the next tick, which makes the spell mostly useless --- zone/bonuses.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 2a8a0c790..1a49aaf66 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -2529,6 +2529,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_ImmuneFleeing: new_bonus->ImmuneToFlee = true; + if (currently_fleeing) // lets update shit now instead of next tick + ProcessFlee(); break; case SE_DelayDeath: From 77974c83d70c349691a0f659010a684645e93c14 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 5 Sep 2016 02:31:28 -0500 Subject: [PATCH 358/693] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 476 ++++++++++++++++++++++++++++------ 1 file changed, 391 insertions(+), 85 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 484c5f306..467912b51 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -24,8 +24,22 @@ $eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/ #::: Globals $time_stamp = strftime('%m-%d-%Y', gmtime()); $db_run_stage = 0; #::: Sets database run stage check -if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } -if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } +if($Config{osname}=~/freebsd|linux/i){ + $OS = "Linux"; + $os_flavor = ""; + if(-e "/etc/debian_version"){ + $os_flavor = "debian"; + } + if(-e "/etc/fedora-release"){ + $os_flavor = "fedora_core"; + } + if(-e "/etc/redhat-release"){ + $os_flavor = "red_hat"; + } +} +if($Config{osname}=~/Win|MS/i){ + $OS = "Windows"; +} $has_internet_connection = check_internet_connection(); ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); @@ -38,9 +52,7 @@ get_mysql_path(); #::: Remove old eqemu_update.pl if(-e "eqemu_update.pl"){ unlink("eqemu_update.pl"); -} -#::: Create db_update working directory if not created -mkdir('db_update'); +} print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n" if $ARGV[0] eq "ran_from_world"; @@ -51,12 +63,11 @@ if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" } check_db_version_table(); - check_for_world_bootup_database_update(); if($db){ print "[Update] MySQL Path/Location: " . $path . "\n"; - print "[Update] Binary Revision / Local: (" . $binary_database_version . " / " . $local_database_version . ")\n"; + print "[Update] Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version . "\n"; #::: Bots #::: Make sure we're running a bots binary to begin with @@ -73,81 +84,318 @@ if($db){ exit; } } - -if($ARGV[0] eq "remove_duplicate_rules"){ - remove_duplicate_rule_values(); - exit; + +sub urlencode { + my ($rv) = @_; + $rv =~ s/([^A-Za-z0-9])/sprintf("%%%2.2X", ord($1))/ge; + return $rv; } +sub urldecode { + my ($rv) = @_; + $rv =~ s/\+/ /g; + $rv =~ s/%(..)/pack("c",hex($1))/ge; + return $rv; +} + +sub analytics_insertion { + $event_name = urlencode($_[0]); + $event_data = urlencode($_[1]); + + #::: Check for internet connection before doing analytics + if(!$has_internet_connection || $can_see_analytics_server == -1){ + return; + } + + #::: Check for analytics server connectivity so that the script doesn't break when its offline + if(!$can_see_analytics_server){ + if($OS eq "Linux"){ + $count = "c"; + } + if($OS eq "Windows"){ + $count = "n"; + } + + if (`ping analytics.akkadius.com -$count 1 -w 500`=~/Reply from|1 received/i) { + $can_see_analytics_server = 1; + } + else { + $can_see_analytics_server = -1; + } + } + + $server_name = ""; + if($long_name){ + $server_name = "&server_name=" . urlencode($long_name); + } + + if(!$extended_os){ + if($OS eq "Linux"){ + $extended_os = `cat /proc/version`; + $extended_os = trim($extended_os); + } + if($OS eq "Windows"){ + my $output = `ver`; + my @os_version = split("\n", $output); + foreach my $val (@os_version){ + if($val=~/Windows/i){ + $extended_os = trim($val); + } + } + } + } + + $url = "http://analytics.akkadius.com/"; + $url .= "?api_key=24a0bde2e5bacd65bcab06a9ac40b62c"; + $url .= "&event=" . $event_name; + $url .= "&event_data=" . $event_data; + $url .= "&OS=" . urlencode($OS); + $url .= "&extended_os=" . urlencode($extended_os); + $url .= $server_name; + + # print "Calling url :: '" . $url . "'\n"; + + if($OS eq "Windows"){ + eval('require LWP::UserAgent;'); + my $ua = LWP::UserAgent->new; + $ua->timeout(1); + $ua->env_proxy; + my $response = $ua->get($url); + } + if($OS eq "Linux"){ + $api_call = `curl -s "$url"`; + } +} + +#::: Command line argument calls +if($ARGV[0]){ + analytics_insertion("cli", trim($ARGV[0])); +} +if($ARGV[0] eq "do_install_config_xml"){ + do_install_config_xml(); + exit; +} +if($ARGV[0] eq "show_install_summary_info"){ + show_install_summary_info(); +} +if($ARGV[0] eq "remove_duplicate_rules"){ + remove_duplicate_rule_values(); + exit; +} if($ARGV[0] eq "map_files_fetch_bulk"){ map_files_fetch_bulk(); exit; } - if($ARGV[0] eq "loginserver_install_linux"){ do_linux_login_server_setup(); exit; } - if($ARGV[0] eq "new_server"){ - while(1){ - print "For a new server folder install, we assume Perl and MySQL are configured\n"; - print "This will install a fresh PEQ Database, with all server assets\n"; - print "You will need to supply database credentials to get started...\n"; - - check_for_input("MySQL User: "); - $database_user = trim($input); + new_server(); + show_install_summary_info(); + exit; +} +if($ARGV[0] eq "installer"){ + analytics_insertion("full_install", "Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); + do_installer_routines(); + show_install_summary_info(); + exit; +} +if($ARGV[0] eq "db_dump_compress"){ + database_dump_compress(); + exit; +} +if($ARGV[0] eq "login_server_setup"){ + do_windows_login_server_setup(); + exit; +} - check_for_input("MySQL Password: "); - $database_password = trim($input); +sub show_install_summary_info { + print "[Install] Installation complete...\n"; + print "[Install] Server Info (Save somewhere if needed):\n"; + + if (-e "install_variables.txt") { + $file_to_open = "install_variables.txt"; + } + elsif(-e "../install_variables.txt"){ + $file_to_open = "../install_variables.txt"; + } + open (INSTALL_VARS, $file_to_open); + while (){ + chomp; + $o = $_; + @data = split(":", $o); + print " - " . $data[0] . "\t" . $data[1] . "\n"; + } + close (INSTALL_VARS); + + if($OS eq "Windows"){ + print "[Install] Windows Utility Scripts:\n"; + print " - t_start_server.bat Starts EQEmu server with 30 dynamic zones, UCS & Queryserv, dynamic zones\n"; + print " - t_start_server_with_loginserver.bat Starts EQEmu server with 30 zones with loginserver\n"; + print " - t_stop_server.bat Stops EQEmu Server (No warning)\n"; + print " - t_database_backup.bat Backs up the Database to backups/ folder - do not run during server is online\n"; + print " - t_server_crash_report.pl Will parse any zone crashes for reporting to developers\n"; + } + if($OS eq "Linux"){ + print "[Install] Linux Utility Scripts:\n"; + print " - server_start.sh Starts EQEmu server (Quiet) with 30 dynamic zones, UCS & Queryserv, dynamic zones\n"; + print " - server_start_dev.sh Starts EQEmu server with 10 dynamic zones, UCS & Queryserv, dynamic zones all verbose\n"; + print " - server_stop.sh Stops EQEmu Server (No warning)\n"; + print " - server_status.sh Prints the status of the EQEmu Server processes\n"; + } + + print "[Configure] eqemu_config.xml Edit to change server settings and name\n"; + + analytics_insertion("install_complete", "null"); +} + +sub new_server { + $file_count = 0; + opendir(DIR, ".") or die $!; + while (my $file = readdir(DIR)) { + next if ($file =~ m/^\./); + $file_count++; + } + closedir(DIR); + + if($file_count > 1 && !-e "install_variables.txt"){ + print "[New Server] ERROR: You must run eqemu_server.pl in an empty directory\n"; + <>; + exit; + } + + if(-e "install_variables.txt"){ + get_installation_variables(); + } + + while(1){ - $check_connection = `mysql -u $database_user -p$database_password -N -B -e "SHOW PROCESSLIST" > mysqlcheck.txt`; - $mysql_pass = 0; - open (MYSQL_CHECK, "mysqlcheck.txt"); - while (){ - chomp; - $o = $_; - if($o=~/Error/i){ $mysql_pass = 0;} - if($o=~/SHOW PROCESSLIST/i){ $mysql_pass = 1; } - } - close (MYSQL_CHECK); - unlink("mysqlcheck.txt"); + $database_name = $installation_variables{"mysql_eqemu_db_name"}; + $database_user = $installation_variables{"mysql_eqemu_user"}; + $database_password = $installation_variables{"mysql_eqemu_password"}; - if($mysql_pass == 1){ - print "Success! We have a database connection\n"; - - check_for_input("Specify a database name: "); - $database_name = trim($input); - - #::: Write install vars - open (INSTALL_VARS, '>', 'install_variables.txt'); - print INSTALL_VARS ""; - print INSTALL_VARS "mysql_eqemu_db_name:" . $database_name . "\n"; - print INSTALL_VARS "mysql_eqemu_user:" . $database_user . "\n"; - print INSTALL_VARS "mysql_eqemu_password:" . $database_password . "\n"; - close (INSTALL_VARS); - - do_installer_routines(); + if($database_name ne ""){ + $mysql_pass = 1; } else { - print "Authorization failed\n"; + + print "\n"; + print "[New Server] For a new server folder install, we assume Perl and MySQL are configured\n"; + print "[New Server] This will install a fresh PEQ Database, with all server assets\n"; + print "[New Server] You will need to supply database credentials to get started...\n\n"; + + check_for_input("MySQL User: "); + $database_user = trim($input); + + check_for_input("MySQL Password: "); + $database_password = trim($input); + + $check_connection = `mysql -u $database_user -p$database_password -N -B -e "SHOW PROCESSLIST" > mysqlcheck.txt`; + $mysql_pass = 0; + open (MYSQL_CHECK, "mysqlcheck.txt"); + while (){ + chomp; + $o = $_; + if($o=~/Error/i){ $mysql_pass = 0;} + if($o=~/SHOW PROCESSLIST/i){ $mysql_pass = 1; } + } + close (MYSQL_CHECK); + unlink("mysqlcheck.txt"); + } + + if($mysql_pass == 1){ + + if(!-e "install_variables.txt"){ + print "[New Server] Success! We have a database connection\n"; + + check_for_input("Specify a NEW database name that PEQ will be installed to: "); + $database_name = trim($input); + + #::: Write install vars + open (INSTALL_VARS, '>', 'install_variables.txt'); + print INSTALL_VARS ""; + print INSTALL_VARS "mysql_eqemu_db_name:" . $database_name . "\n"; + print INSTALL_VARS "mysql_eqemu_user:" . $database_user . "\n"; + print INSTALL_VARS "mysql_eqemu_password:" . $database_password . "\n"; + close (INSTALL_VARS); + } + analytics_insertion("new_server::install", $database_name); + + if($OS eq "Linux"){ + $current_directory = `pwd`; + @directories = split('/', $current_directory); + foreach my $val (@directories){ + if(trim($val) ne ""){ + $last_directory = trim($val); + } + } + my $eqemu_server_directory = "/home/eqemu"; + my $source_dir = $eqemu_server_directory . '/' . $last_directory . '_source'; + + $current_directory = trim($current_directory); + + mkdir($source_dir) if (!-e $source_dir); + + # print 'server_dir: ' . $eqemu_server_directory . "\n"; + # print 'source_dir: ' . $source_dir . "\n"; + # print 'current_dir: \'' . $current_directory . "'\n"; + + chdir($source_dir); + + print `git clone https://github.com/EQEmu/Server.git`; + + mkdir ($source_dir . "/Server/build") if (!-e $source_dir . "/Server/build"); + chdir ($source_dir . "/Server/build"); + + print "Generating CMake build files...\n"; + if($os_flavor eq "fedora_core"){ + print `cmake -DEQEMU_BUILD_LUA=ON -DLUA_INCLUDE_DIR=/usr/include/lua-5.1/ -G "Unix Makefiles" ..`; + } + else { + print `cmake -DEQEMU_BUILD_LUA=ON -G "Unix Makefiles" ..`; + } + print "Building EQEmu Server code. This will take a while."; + + #::: Build + print `make`; + + chdir ($current_directory); + + print `ln -s $source_dir/Server/build/bin/eqlaunch .`; + print `ln -s $source_dir/Server/build/bin/export_client_files .`; + print `ln -s $source_dir/Server/build/bin/import_client_files .`; + print `ln -s $source_dir/Server/build/bin/libcommon.a .`; + print `ln -s $source_dir/Server/build/bin/libluabind.a .`; + print `ln -s $source_dir/Server/build/bin/queryserv .`; + print `ln -s $source_dir/Server/build/bin/shared_memory .`; + print `ln -s $source_dir/Server/build/bin/ucs .`; + print `ln -s $source_dir/Server/build/bin/world .`; + print `ln -s $source_dir/Server/build/bin/zone .`; + + } + + do_installer_routines(); + + if($OS eq "Linux"){ + print `chmod 755 *.sh`; + } + + analytics_insertion("new_server::install_complete", $database_name . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); + + print "[New Server] New server folder install complete\n"; + print "[New Server] Below is your installation info:\n"; + + return; + } + else { + print "[New Server] MySQL authorization failed or no MySQL installed\n"; } } } -if($ARGV[0] eq "installer"){ - do_installer_routines(); - exit; -} - -if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } -if($ARGV[0] eq "login_server_setup"){ - do_windows_login_server_setup(); - exit; -} - sub do_installer_routines { - print "[Install] Running EQEmu Server installer routines...\n"; + print "[Install] EQEmu Server Installer... LOADING... PLEASE WAIT...\n"; #::: Make some local server directories... mkdir('logs'); @@ -170,6 +418,7 @@ sub do_installer_routines { get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); } + map_files_fetch_bulk(); opcodes_fetch(); plugins_fetch(); @@ -204,13 +453,11 @@ sub do_installer_routines { } if($OS eq "Linux"){ do_linux_login_server_setup(); - - print "[Install] Installation complete!\n"; } } sub check_for_input { - print $_[0]; + print "[Input] " . $_[0]; $input = ; chomp $input; } @@ -242,6 +489,8 @@ sub check_for_world_bootup_database_update { main_db_management(); main_db_management(); print "[Update] Continuing bootup\n"; + analytics_insertion("auto database upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); + exit; } @@ -260,7 +509,7 @@ sub check_internet_connection { if($OS eq "Windows"){ $count = "n"; } - + if (`ping 8.8.8.8 -$count 1 -w 500`=~/Reply from|1 received/i) { # print "[Update] We have a connection to the internet, continuing...\n"; return 1; @@ -287,13 +536,15 @@ sub get_perl_version { } sub do_self_update_check_routine { - #::: Check Version passed from world to update script - get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); - + + #::: Check for internet connection before updating if(!$has_internet_connection){ print "[Update] Cannot check update without internet connection...\n"; return; } + + #::: Check for script changes :: eqemu_server.pl + get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); if(-e "updates_staged/eqemu_server.pl") { @@ -383,6 +634,11 @@ sub do_install_config_xml { my($replace_key) = $o =~ />(\w+)/i){ + my($replace_name) = $o =~ /(.*)<\/longname>/; + $append = '(' . generate_random_password(5) . ')'; + $o =~ s/$replace_name/Akkas $OS PEQ Installer $append/g; } if($o=~/\/i && $in_database_tag){ my($replace_username) = $o =~ />(\w+); } - } + } } sub print_main_menu { @@ -532,7 +790,9 @@ sub print_main_menu { print ">>> EQEmu Server Main Menu >>>>>>>>>>>>\n"; print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"; print " [database] Enter database management menu \n"; - print " [assets] Manage server assets \n\n"; + print " [assets] Manage server assets \n"; + print " [new_server] New folder EQEmu/PEQ install - Assumes MySQL/Perl installed \n"; + print "\n"; print " exit \n"; print "\n"; print "Enter a command #> "; @@ -568,13 +828,52 @@ sub get_mysql_path { } sub check_for_database_dump_script{ - if(`perl db_dumper.pl`=~/Need arguments/i){ - return; + #::: Check for internet connection before updating + if(!$has_internet_connection){ + print "[Update] Cannot check update without internet connection...\n"; + return; } - else{ - print "[Database] db_dumper.pl not found... retrieving...\n"; - get_remote_file($eqemu_repository_request_url . "utils/scripts/db_dumper.pl", "db_dumper.pl"); + + #::: Check for script changes :: db_dumper.pl + get_remote_file($eqemu_repository_request_url . "utils/scripts/db_dumper.pl", "updates_staged/db_dumper.pl", 0, 1, 1); + + if(-e "updates_staged/db_dumper.pl") { + + my $remote_script_size = -s "updates_staged/db_dumper.pl"; + my $local_script_size = -s "db_dumper.pl"; + + if($remote_script_size != $local_script_size){ + print "[Update] Script has been updated, updating...\n"; + + my @files; + my $start_dir = "updates_staged/"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + if($file=~/db_dumper/i){ + $destination_file = $file; + $destination_file =~s/updates_staged\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + unlink($destination_file); + copy_file($file, $destination_file); + if($OS eq "Linux"){ + system("chmod 755 db_dumper.pl"); + } + } + } + print "[Install] Done\n"; + } + else { + print "[Update] No script update necessary...\n"; + } + + unlink("updates_staged/db_dumper.pl"); } + + return; + } sub database_dump { @@ -601,7 +900,7 @@ sub database_dump_player_tables { print `perl db_dumper.pl database="$db" loc="backups" tables="$tables" backup_name="player_tables_export" nolock`; print "[Database] Press any key to continue...\n"; - + <>; #Read from STDIN } @@ -762,13 +1061,11 @@ sub read_eqemu_config_xml { my $indb = 0; while() { s/\r//g; - if(//i) { $indb = 1; } - next unless($indb == 1); - if(/<\/database>/i) { $indb = 0; last; } if(/(.*)<\/host>/i) { $host = $1; } elsif(/(.*)<\/username>/i) { $user = $1; } elsif(/(.*)<\/password>/i) { $pass = $1; } elsif(/(.*)<\/db>/i) { $db = $1; } + if(/(.*)<\/longname>/i) { $long_name = $1; } } } @@ -1016,11 +1313,11 @@ sub add_login_server_firewall_rules { $val=~s/Rule Name://g; if($val=~/EQEmu Loginserver/i && $val=~/Titanium/i){ $has_loginserver_rules_titanium = 1; - print "Found existing rule :: " . trim($val) . "\n"; + print "[Install] Found existing rule :: " . trim($val) . "\n"; } if($val=~/EQEmu Loginserver/i && $val=~/SOD/i){ $has_loginserver_rules_sod = 1; - print "Found existing rule :: " . trim($val) . "\n"; + print "[Install] Found existing rule :: " . trim($val) . "\n"; } } } @@ -1619,6 +1916,13 @@ sub get_bots_db_version{ } sub bots_db_management{ + if($OS eq "Windows"){ + @db_version = split(': ', `world db_version`); + } + if($OS eq "Linux"){ + @db_version = split(': ', `./world db_version`); + } + #::: Main Binary Database version $binary_database_version = trim($db_version[2]); @@ -1637,6 +1941,8 @@ sub bots_db_management{ $bots_local_db_version = get_bots_db_version(); + $local_database_version = $bots_local_db_version; + run_database_check(); } @@ -1718,13 +2024,13 @@ sub run_database_check{ @total_updates = (); #::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest... - if($local_database_version > 9000){ + if($local_database_version >= 9000){ $revision_check = $local_database_version; } else { $revision_check = 1000; if(get_mysql_result("SHOW TABLES LIKE 'character_data'") ne ""){ - $revision_check = 9000; + $revision_check = 8999; } } From 2947e3f39f137ec7ddd200716b0eb48d76ffc1c2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 5 Sep 2016 02:33:18 -0500 Subject: [PATCH 359/693] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 467912b51..f128e5248 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -30,10 +30,10 @@ if($Config{osname}=~/freebsd|linux/i){ if(-e "/etc/debian_version"){ $os_flavor = "debian"; } - if(-e "/etc/fedora-release"){ + elsif(-e "/etc/fedora-release"){ $os_flavor = "fedora_core"; } - if(-e "/etc/redhat-release"){ + elsif(-e "/etc/redhat-release"){ $os_flavor = "red_hat"; } } From 0efd0c5f738da34cab983383f7c876f6bf0f691d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 5 Sep 2016 15:26:12 -0500 Subject: [PATCH 360/693] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 168 ++++++++++++++++++++-------------- 1 file changed, 97 insertions(+), 71 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index f128e5248..b5ddb4cc8 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -171,21 +171,9 @@ sub analytics_insertion { if($ARGV[0]){ analytics_insertion("cli", trim($ARGV[0])); } -if($ARGV[0] eq "do_install_config_xml"){ - do_install_config_xml(); - exit; -} if($ARGV[0] eq "show_install_summary_info"){ show_install_summary_info(); } -if($ARGV[0] eq "remove_duplicate_rules"){ - remove_duplicate_rule_values(); - exit; -} -if($ARGV[0] eq "map_files_fetch_bulk"){ - map_files_fetch_bulk(); - exit; -} if($ARGV[0] eq "loginserver_install_linux"){ do_linux_login_server_setup(); exit; @@ -205,10 +193,6 @@ if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } -if($ARGV[0] eq "login_server_setup"){ - do_windows_login_server_setup(); - exit; -} sub show_install_summary_info { print "[Install] Installation complete...\n"; @@ -323,56 +307,7 @@ sub new_server { analytics_insertion("new_server::install", $database_name); if($OS eq "Linux"){ - $current_directory = `pwd`; - @directories = split('/', $current_directory); - foreach my $val (@directories){ - if(trim($val) ne ""){ - $last_directory = trim($val); - } - } - my $eqemu_server_directory = "/home/eqemu"; - my $source_dir = $eqemu_server_directory . '/' . $last_directory . '_source'; - - $current_directory = trim($current_directory); - - mkdir($source_dir) if (!-e $source_dir); - - # print 'server_dir: ' . $eqemu_server_directory . "\n"; - # print 'source_dir: ' . $source_dir . "\n"; - # print 'current_dir: \'' . $current_directory . "'\n"; - - chdir($source_dir); - - print `git clone https://github.com/EQEmu/Server.git`; - - mkdir ($source_dir . "/Server/build") if (!-e $source_dir . "/Server/build"); - chdir ($source_dir . "/Server/build"); - - print "Generating CMake build files...\n"; - if($os_flavor eq "fedora_core"){ - print `cmake -DEQEMU_BUILD_LUA=ON -DLUA_INCLUDE_DIR=/usr/include/lua-5.1/ -G "Unix Makefiles" ..`; - } - else { - print `cmake -DEQEMU_BUILD_LUA=ON -G "Unix Makefiles" ..`; - } - print "Building EQEmu Server code. This will take a while."; - - #::: Build - print `make`; - - chdir ($current_directory); - - print `ln -s $source_dir/Server/build/bin/eqlaunch .`; - print `ln -s $source_dir/Server/build/bin/export_client_files .`; - print `ln -s $source_dir/Server/build/bin/import_client_files .`; - print `ln -s $source_dir/Server/build/bin/libcommon.a .`; - print `ln -s $source_dir/Server/build/bin/libluabind.a .`; - print `ln -s $source_dir/Server/build/bin/queryserv .`; - print `ln -s $source_dir/Server/build/bin/shared_memory .`; - print `ln -s $source_dir/Server/build/bin/ucs .`; - print `ln -s $source_dir/Server/build/bin/world .`; - print `ln -s $source_dir/Server/build/bin/zone .`; - + build_linux_source(); } do_installer_routines(); @@ -394,6 +329,69 @@ sub new_server { } } +sub build_linux_source { + + $build_options = $_[0]; + + $cmake_options = ""; + $source_folder_post_fix = ""; + + if($build_options =~/bots/i){ + $cmake_options .= " -DEQEMU_ENABLE_BOTS=ON"; + $source_folder_post_fix = "_bots"; + } + + $current_directory = `pwd`; + @directories = split('/', $current_directory); + foreach my $val (@directories){ + if(trim($val) ne ""){ + $last_directory = trim($val); + } + } + my $eqemu_server_directory = "/home/eqemu"; + my $source_dir = $eqemu_server_directory . '/' . $last_directory . '_source' . $source_folder_post_fix; + + $current_directory = trim($current_directory); + + mkdir($source_dir) if (!-e $source_dir); + + # print 'server_dir: ' . $eqemu_server_directory . "\n"; + # print 'source_dir: ' . $source_dir . "\n"; + # print 'current_dir: \'' . $current_directory . "'\n"; + + chdir($source_dir); + + print `git clone https://github.com/EQEmu/Server.git`; + + mkdir ($source_dir . "/Server/build") if (!-e $source_dir . "/Server/build"); + chdir ($source_dir . "/Server/build"); + + print "Generating CMake build files...\n"; + if($os_flavor eq "fedora_core"){ + print `cmake $cmake_options -DEQEMU_BUILD_LUA=ON -DLUA_INCLUDE_DIR=/usr/include/lua-5.1/ -G "Unix Makefiles" ..`; + } + else { + print `cmake $cmake_options -DEQEMU_BUILD_LUA=ON -G "Unix Makefiles" ..`; + } + print "Building EQEmu Server code. This will take a while."; + + #::: Build + print `make`; + + chdir ($current_directory); + + print `ln -s -f $source_dir/Server/build/bin/eqlaunch .`; + print `ln -s -f $source_dir/Server/build/bin/export_client_files .`; + print `ln -s -f $source_dir/Server/build/bin/import_client_files .`; + print `ln -s -f $source_dir/Server/build/bin/libcommon.a .`; + print `ln -s -f $source_dir/Server/build/bin/libluabind.a .`; + print `ln -s -f $source_dir/Server/build/bin/queryserv .`; + print `ln -s -f $source_dir/Server/build/bin/shared_memory .`; + print `ln -s -f $source_dir/Server/build/bin/ucs .`; + print `ln -s -f $source_dir/Server/build/bin/world .`; + print `ln -s -f $source_dir/Server/build/bin/zone .`; +} + sub do_installer_routines { print "[Install] EQEmu Server Installer... LOADING... PLEASE WAIT...\n"; @@ -495,7 +493,7 @@ sub check_for_world_bootup_database_update { } #::: Make sure that we didn't pass any arugments to the script - if(!$ARGV[0]){ + else { if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } show_menu_prompt(); } @@ -528,7 +526,7 @@ sub get_perl_version { #::: Check Perl version $perl_version = $^V; $perl_version =~s/v//g; - print "[Update] Perl Version is " . $perl_version . "\n"; + print "[Update] Perl Version is " . $perl_version . "\n" if $debug; if($perl_version > 5.12){ no warnings 'uninitialized'; } @@ -688,18 +686,37 @@ sub fetch_utility_scripts { } } +sub setup_bots { + if($OS eq "Windows"){ + fetch_latest_windows_binaries_bots(); + } + if($OS eq "Linux"){ + build_linux_source("bots"); + } + bots_db_management(); + run_database_check(); + + print "Bots should be setup, run your server and the #bot command should be available in-game\n"; +} + sub show_menu_prompt { $dc = 0; while (1) { - $input = trim($input); + + if($ARGV[0] ne ""){ + $input = trim($ARGV[0]); + } + else { + $input = trim($input); + } $errored_command = 0; if($input eq "database"){ print "\n>>> Database Menu\n\n"; print " [backup_database] Back up database to backups/ directory\n"; - print " [backup_player_tables] Back up player tables to backups/ directory\n"; + print " [backup_player_tables] Back up player tables to backups/ directory\n"; print " [backup_database_compressed] Back up database compressed to backups/ directory\n"; print " \n"; print " [check_db_updates] Checks for database updates manually\n"; @@ -747,10 +764,11 @@ sub show_menu_prompt { elsif($input eq "windows_server_download_bots"){ fetch_latest_windows_binaries_bots(); $dc = 1; } elsif($input eq "fetch_dlls"){ fetch_server_dlls(); $dc = 1; } elsif($input eq "utility_scripts"){ fetch_utility_scripts(); $dc = 1; } - elsif($input eq "check_db_updates"){ main_db_management(); $dc = 1; } + elsif($input eq "check_db_updates"){ main_db_management(); main_db_management(); $dc = 1; } elsif($input eq "check_bot_db_updates"){ bots_db_management(); run_database_check(); $dc = 1; } elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; } elsif($input eq "new_server"){ new_server(); $dc = 1; } + elsif($input eq "setup_bots"){ setup_bots(); $dc = 1; } elsif($input eq "exit"){ exit; } @@ -782,6 +800,13 @@ sub show_menu_prompt { else { $input = <>; } + + #::: If we're processing a CLI command, kill the loop + if($ARGV[0] ne ""){ + $input = ""; + $ARGV[0] = ""; + exit; + } } } @@ -792,6 +817,7 @@ sub print_main_menu { print " [database] Enter database management menu \n"; print " [assets] Manage server assets \n"; print " [new_server] New folder EQEmu/PEQ install - Assumes MySQL/Perl installed \n"; + print " [setup_bots] Enables bots on server - builds code and database requirements \n"; print "\n"; print " exit \n"; print "\n"; From 5b03fba463a5c74c6bde06492728a21fdf675d56 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 6 Sep 2016 20:04:21 -0500 Subject: [PATCH 361/693] Update eqemu_server.pl - Fix windows installs [skip ci] --- utils/scripts/eqemu_server.pl | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index b5ddb4cc8..3d66f9df5 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -168,31 +168,13 @@ sub analytics_insertion { } #::: Command line argument calls -if($ARGV[0]){ - analytics_insertion("cli", trim($ARGV[0])); -} -if($ARGV[0] eq "show_install_summary_info"){ - show_install_summary_info(); -} -if($ARGV[0] eq "loginserver_install_linux"){ - do_linux_login_server_setup(); - exit; -} -if($ARGV[0] eq "new_server"){ - new_server(); - show_install_summary_info(); - exit; -} if($ARGV[0] eq "installer"){ + print "Hi\n"; analytics_insertion("full_install", "Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); - do_installer_routines(); + new_server(); show_install_summary_info(); exit; } -if($ARGV[0] eq "db_dump_compress"){ - database_dump_compress(); - exit; -} sub show_install_summary_info { print "[Install] Installation complete...\n"; @@ -321,6 +303,8 @@ sub new_server { print "[New Server] New server folder install complete\n"; print "[New Server] Below is your installation info:\n"; + show_install_summary_info(); + return; } else { From 5f1141dfb1e99e9874a0c699916b8116ff56b36b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 6 Sep 2016 22:04:38 -0500 Subject: [PATCH 362/693] eqemu_server.pl - Auto update bots database on world bootup if bots enabled [skip ci] --- utils/scripts/eqemu_server.pl | 58 +- utils/scripts/eqemu_update.pl | 1789 --------------------------------- 2 files changed, 27 insertions(+), 1820 deletions(-) delete mode 100644 utils/scripts/eqemu_update.pl diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 3d66f9df5..0cf23b9cb 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -65,26 +65,6 @@ if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" check_db_version_table(); check_for_world_bootup_database_update(); -if($db){ - print "[Update] MySQL Path/Location: " . $path . "\n"; - print "[Update] Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version . "\n"; - - #::: Bots - #::: Make sure we're running a bots binary to begin with - if(trim($db_version[2]) > 0){ - $bots_local_db_version = get_bots_db_version(); - if($bots_local_db_version > 0){ - print "[Update] (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; - } - } - - #::: If World ran this script, and our version is up to date, continue... - if($binary_database_version <= $local_database_version && $ARGV[0] eq "ran_from_world"){ - print "[Update] Database up to Date: Continuing World Bootup...\n"; - exit; - } -} - sub urlencode { my ($rv) = @_; $rv =~ s/([^A-Za-z0-9])/sprintf("%%%2.2X", ord($1))/ge; @@ -167,15 +147,6 @@ sub analytics_insertion { } } -#::: Command line argument calls -if($ARGV[0] eq "installer"){ - print "Hi\n"; - analytics_insertion("full_install", "Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); - new_server(); - show_install_summary_info(); - exit; -} - sub show_install_summary_info { print "[Install] Installation complete...\n"; print "[Install] Server Info (Save somewhere if needed):\n"; @@ -429,6 +400,8 @@ sub do_installer_routines { print "[Database] Applying Latest Database Updates...\n"; main_db_management(); + remove_duplicate_rule_values(); + if($OS eq "Windows"){ check_windows_firewall_rules(); do_windows_login_server_setup(); @@ -455,12 +428,35 @@ sub check_for_world_bootup_database_update { $binary_database_version = trim($db_version[1]); $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + #::: Bots + $bots_binary_version = trim($db_version[2]); + if($bots_binary_version > 0){ + $bots_local_db_version = get_bots_db_version(); + #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup + + if($bots_local_db_version < $bots_binary_version && $ARGV[0] eq "ran_from_world"){ + print "[Update] Bots Database not up to date with binaries... Automatically updating...\n"; + print "[Update] Issuing database backup first...\n"; + database_dump_compress(); + print "[Update] Updating bots database...\n"; + sleep(1); + bots_db_management(); + run_database_check(); + print "[Update] Continuing bootup\n"; + analytics_insertion("auto database bots upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); + + exit; + } + else { + print "[Update] Bots database up to Date: Continuing World Bootup...\n"; + } + } + if($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world"){ print "[Update] Database up to date...\n"; exit; } else { - #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup if($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world"){ print "[Update] Database not up to date with binaries... Automatically updating...\n"; @@ -485,7 +481,7 @@ sub check_for_world_bootup_database_update { } sub check_internet_connection { - if($OS eq "Linux"){ + if($OS eq "Linux"){ $count = "c"; } if($OS eq "Windows"){ diff --git a/utils/scripts/eqemu_update.pl b/utils/scripts/eqemu_update.pl deleted file mode 100644 index cb94dca0a..000000000 --- a/utils/scripts/eqemu_update.pl +++ /dev/null @@ -1,1789 +0,0 @@ -#!/usr/bin/perl - -########################################################### -#::: General EQEmu Server Administration Script -#::: Purpose - Handles: -#::: Automatic database versioning (bots and normal DB) -#::: Updating server assets (binary, opcodes, maps, configuration files) -#::: Original Author: Akkadius -#::: Contributors: Uleat -#::: Purpose: To upgrade databases with ease and maintain versioning -########################################################### - -use Config; -use File::Copy qw(copy); -use POSIX qw(strftime); -use File::Path; -use File::Find; -use Time::HiRes qw(usleep); - -#::: Variables -$install_repository_request_url = "https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/"; -$eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/master/"; - -#::: Globals -$time_stamp = strftime('%m-%d-%Y', gmtime()); -$db_run_stage = 0; #::: Sets database run stage check -if($Config{osname}=~/freebsd|linux/i){ $OS = "Linux"; } -if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } -$has_internet_connection = check_internet_connection(); -($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); - -#::: Check for script self update -do_self_update_check_routine(); -get_perl_version(); -read_eqemu_config_xml(); -get_mysql_path(); - -#::: Remove old eqemu_update.pl -if(-e "eqemu_update.pl"){ - unlink("eqemu_update.pl"); -} -#::: Create db_update working directory if not created -mkdir('db_update'); - -print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n"; - -#::: Check if db_version table exists... -if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ - print get_mysql_result("DROP TABLE db_version"); - print "[Database] Old db_version table present, dropping...\n\n"; -} - -check_db_version_table(); - -check_for_world_bootup_database_update(); - -if($db){ - print "[Update] MySQL Path/Location: " . $path . "\n"; - print "[Update] Binary Revision / Local: (" . $binary_database_version . " / " . $local_database_version . ")\n"; - - #::: Bots - #::: Make sure we're running a bots binary to begin with - if(trim($db_version[2]) > 0){ - $bots_local_db_version = get_bots_db_version(); - if($bots_local_db_version > 0){ - print "[Update] (Bots) Binary Revision / Local: (" . trim($db_version[2]) . " / " . $bots_local_db_version . ")\n"; - } - } - - #::: If World ran this script, and our version is up to date, continue... - if($binary_database_version <= $local_database_version && $ARGV[0] eq "ran_from_world"){ - print "[Update] Database up to Date: Continuing World Bootup...\n"; - exit; - } -} - -if($ARGV[0] eq "remove_duplicate_rules"){ - remove_duplicate_rule_values(); - exit; -} - -if($ARGV[0] eq "map_files_fetch_bulk"){ - map_files_fetch_bulk(); - exit; -} - -if($ARGV[0] eq "loginserver_install_linux"){ - do_linux_login_server_setup(); - exit; -} - -if($ARGV[0] eq "installer"){ - print "[Install] Running EQEmu Server installer routines...\n"; - - #::: Make some local server directories... - mkdir('logs'); - mkdir('updates_staged'); - mkdir('shared'); - - do_install_config_xml(); - read_eqemu_config_xml(); - get_installation_variables(); - - $db_name = "peq"; - if($installation_variables{"mysql_eqemu_db_name"}){ - $db_name = $installation_variables{"mysql_eqemu_db_name"}; - } - - #::: Download assets - if($OS eq "Windows"){ - fetch_latest_windows_binaries(); - get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); - get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); - get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); - } - map_files_fetch_bulk(); - opcodes_fetch(); - plugins_fetch(); - quest_files_fetch(); - lua_modules_fetch(); - fetch_utility_scripts(); - - #::: Database Routines - print "[Database] Creating Database '" . $db_name . "'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; - - #::: Get Binary DB version - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $binary_database_version = trim($db_version[1]); - - #::: Local DB Version - check_db_version_table(); - $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - - #::: Download PEQ latest - fetch_peq_db_full(); - print "[Database] Fetching Latest Database Updates...\n"; - main_db_management(); - print "[Database] Applying Latest Database Updates...\n"; - main_db_management(); - - if($OS eq "Windows"){ - check_windows_firewall_rules(); - do_windows_login_server_setup(); - } - if($OS eq "Linux"){ - do_linux_login_server_setup(); - - print "[Install] Installation complete!\n"; - } - - exit; -} - -if($ARGV[0] eq "db_dump_compress"){ database_dump_compress(); exit; } -if($ARGV[0] eq "login_server_setup"){ - do_windows_login_server_setup(); - exit; -} - -sub check_for_world_bootup_database_update { - if($OS eq "Windows"){ - @db_version = split(': ', `world db_version`); - } - if($OS eq "Linux"){ - @db_version = split(': ', `./world db_version`); - } - - $binary_database_version = trim($db_version[1]); - $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - - if($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world"){ - print "[Update] Database up to date...\n"; - exit; - } - else { - - #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup - if($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world"){ - print "[Update] Database not up to date with binaries... Automatically updating...\n"; - print "[Update] Issuing database backup first...\n"; - database_dump_compress(); - print "[Update] Updating database...\n"; - sleep(1); - main_db_management(); - main_db_management(); - print "[Update] Continuing bootup\n"; - exit; - } - - #::: Make sure that we didn't pass any arugments to the script - if(!$ARGV[0]){ - if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } - show_menu_prompt(); - } - } -} - -sub check_internet_connection { - if($OS eq "Linux"){ - $count = "c"; - } - if($OS eq "Windows"){ - $count = "n"; - } - - if (`ping 8.8.8.8 -$count 1 -w 500`=~/Reply from|1 received/i) { - # print "[Update] We have a connection to the internet, continuing...\n"; - return 1; - } - elsif (`ping 4.2.2.2 -$count 1 -w 500`=~/Reply from|1 received/i) { - # print "[Update] We have a connection to the internet, continuing...\n"; - return 1; - } - else{ - print "[Update] No connection to the internet, can't check update\n"; - return; - } -} - -sub get_perl_version { - #::: Check Perl version - $perl_version = $^V; - $perl_version =~s/v//g; - print "[Update] Perl Version is " . $perl_version . "\n"; - if($perl_version > 5.12){ - no warnings 'uninitialized'; - } - no warnings; -} - -sub do_self_update_check_routine { - #::: Check Version passed from world to update script - get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); - - if(!$has_internet_connection){ - print "[Update] Cannot check update without internet connection...\n"; - return; - } - - if(-e "updates_staged/eqemu_server.pl") { - - my $remote_script_size = -s "updates_staged/eqemu_server.pl"; - my $local_script_size = -s "eqemu_server.pl"; - - if($remote_script_size != $local_script_size){ - print "[Update] Script has been updated, updating...\n"; - - my @files; - my $start_dir = "updates_staged/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - if($file=~/eqemu_server/i){ - $destination_file = $file; - $destination_file =~s/updates_staged\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - unlink($destination_file); - copy_file($file, $destination_file); - if($OS eq "Linux"){ - system("chmod 755 eqemu_server.pl"); - } - system("perl eqemu_server.pl start_from_world"); - } - } - print "[Install] Done\n"; - } - else { - print "[Update] No script update necessary...\n"; - } - - unlink("updates_staged/eqemu_server.pl"); - } -} - -sub get_installation_variables{ - #::: Fetch installation variables before building the config - if($OS eq "Linux"){ - open (INSTALL_VARS, "../install_variables.txt"); - } - if($OS eq "Windows"){ - open (INSTALL_VARS, "install_variables.txt"); - } - while (){ - chomp; - $o = $_; - @data = split(":", $o); - $installation_variables{trim($data[0])} = trim($data[1]); - } - close (INSTALL_VARS); -} - -sub do_install_config_xml { - get_installation_variables(); - - #::: Fetch XML template - get_remote_file($install_repository_request_url . "eqemu_config.xml", "eqemu_config_template.xml"); - - #::: Open new config file - open (NEW_CONFIG, '>', 'eqemu_config.xml'); - - $in_database_tag = 0; - - #::: Iterate through template and replace variables... - open (FILE_TEMPLATE, "eqemu_config_template.xml"); - while (){ - chomp; - $o = $_; - - #::: Find replace variables - - if($o=~/\<\!--/i){ - next; - } - - if($o=~/database/i && $o=~/\<\//i){ - $in_database_tag = 0; - } - if($o=~/database/i){ - $in_database_tag = 1; - } - - if($o=~/key/i){ - my($replace_key) = $o =~ />(\w+)/i && $in_database_tag){ - my($replace_username) = $o =~ />(\w+)/i && $in_database_tag){ - my($replace_password) = $o =~ />(\w+)/i){ - my($replace_db_name) = $o =~ />(\w+)>> Database Menu\n\n"; - print " [backup_database] Back up database to backups/ directory\n"; - print " [backup_player_tables] Back up player tables to backups/ directory\n"; - print " [backup_database_compressed] Back up database compressed to backups/ directory\n"; - print " \n"; - print " [check_db_updates] Checks for database updates manually\n"; - print " [check_bot_db_updates] Checks for bot database updates\n"; - print " \n"; - print " [aa_tables] Downloads and installs clean slate AA data from PEQ\n"; - print " [remove_duplicate_rules] Removes duplicate rules from rule_values table\n"; - print " [drop_bots_db_schema] Removes bot database schema\n"; - - print " \n> main - go back to main menu\n"; - print "Enter a command #> "; - $last_menu = trim($input); - } - elsif($input eq "assets"){ - print "\n>>> Server Assets Menu\n\n"; - print " [maps] Download latest maps\n"; - print " [opcodes] Download opcodes (Patches for eq clients)\n"; - print " [quests] Download latest quests\n"; - print " [plugins] Download latest plugins\n"; - print " [lua_modules] Download latest lua_modules\n"; - print " [utility_scripts] Download utility scripts to run and operate the EQEmu Server\n"; - if($OS eq "Windows"){ - print ">>> Windows\n"; - print " [windows_server_download] Updates server code from latest stable\n"; - print " [windows_server_download_bots] Updates server code (bots enabled) from latest\n"; - print " [fetch_dlls] Grabs dll's needed to run windows binaries\n"; - print " [setup_loginserver] Sets up loginserver for Windows\n"; - } - print " \n> main - go back to main menu\n"; - print "Enter a command #> "; - $last_menu = trim($input); - } - elsif($input eq "backup_database"){ database_dump(); $dc = 1; } - elsif($input eq "backup_player_tables"){ database_dump_player_tables(); $dc = 1; } - elsif($input eq "backup_database_compressed"){ database_dump_compress(); $dc = 1; } - elsif($input eq "drop_bots_db_schema"){ do_bots_db_schema_drop(); $dc = 1; } - elsif($input eq "aa_tables"){ aa_fetch(); $dc = 1; } - elsif($input eq "remove_duplicate_rules"){ remove_duplicate_rule_values(); $dc = 1; } - elsif($input eq "maps"){ map_files_fetch_bulk(); $dc = 1; } - elsif($input eq "opcodes"){ opcodes_fetch(); $dc = 1; } - elsif($input eq "plugins"){ plugins_fetch(); $dc = 1; } - elsif($input eq "quests"){ quest_files_fetch(); $dc = 1; } - elsif($input eq "lua_modules"){ lua_modules_fetch(); $dc = 1; } - elsif($input eq "windows_server_download"){ fetch_latest_windows_binaries(); $dc = 1; } - elsif($input eq "windows_server_download_bots"){ fetch_latest_windows_binaries_bots(); $dc = 1; } - elsif($input eq "fetch_dlls"){ fetch_server_dlls(); $dc = 1; } - elsif($input eq "utility_scripts"){ fetch_utility_scripts(); $dc = 1; } - elsif($input eq "check_db_updates"){ main_db_management(); $dc = 1; } - elsif($input eq "check_bot_db_updates"){ bots_db_management(); $dc = 1; } - elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; } - elsif($input eq "exit"){ - exit; - } - elsif($input eq "main"){ - print "Returning to main menu...\n"; - print_main_menu(); - $last_menu = trim($input); - } - elsif($input eq "" && $last_menu ne ""){ - $errored_command = 1; - } - elsif($input ne ""){ - print "Invalid command '" . $input . "'\n"; - $errored_command = 1; - } - else { - print_main_menu(); - } - - #::: Errored command checking - if($errored_command == 1){ - $input = $last_menu; - } - elsif($dc == 1){ - $dc = 0; - $input = ""; - } - else { - $input = <>; - } - } -} - -sub print_main_menu { - print "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"; - print ">>> EQEmu Server Main Menu >>>>>>>>>>>>\n"; - print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"; - print " [database] Enter database management menu \n"; - print " [assets] Manage server assets \n\n"; - print " exit \n"; - print "\n"; - print "Enter a command #> "; -} - -sub get_mysql_path { - if($OS eq "Windows"){ - $has_mysql_path = `echo %PATH%`; - if($has_mysql_path=~/MySQL|MariaDB/i){ - @mysql = split(';', $has_mysql_path); - foreach my $v (@mysql){ - if($v=~/MySQL|MariaDB/i){ - $v =~s/\n//g; - $path = trim($v) . "/mysql"; - last; - } - } - } - } - if($OS eq "Linux"){ - $path = `which mysql`; - if ($path eq "") { - $path = `which mariadb`; - } - $path =~s/\n//g; - } - - #::: Path not found, error and exit - if($path eq ""){ - print "[Error:eqemu_server.pl] MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; - exit; - } -} - -sub check_for_database_dump_script{ - if(`perl db_dumper.pl`=~/Need arguments/i){ - return; - } - else{ - print "[Database] db_dumper.pl not found... retrieving...\n"; - get_remote_file($eqemu_repository_request_url . "utils/scripts/db_dumper.pl", "db_dumper.pl"); - } -} - -sub database_dump { - check_for_database_dump_script(); - print "[Database] Performing database backup....\n"; - print `perl db_dumper.pl database="$db" loc="backups"`; -} - -sub database_dump_player_tables { - check_for_database_dump_script(); - print "[Database] Performing database backup of player tables....\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/character_table_list.txt", "backups/character_table_list.txt"); - - $tables = ""; - open (FILE, "backups/character_table_list.txt"); - $i = 0; - while (){ - chomp; - $o = $_; - $tables .= $o . ","; - } - $tables = substr($tables, 0, -1); - - print `perl db_dumper.pl database="$db" loc="backups" tables="$tables" backup_name="player_tables_export" nolock`; - - print "[Database] Press any key to continue...\n"; - - <>; #Read from STDIN - -} - -sub database_dump_compress { - check_for_database_dump_script(); - print "[Database] Performing database backup....\n"; - print `perl db_dumper.pl database="$db" loc="backups" compress`; -} - -sub script_exit{ - #::: Cleanup staged folder... - rmtree("updates_staged/"); - exit; -} - -sub check_db_version_table{ - if(get_mysql_result("SHOW TABLES LIKE 'db_version'") eq "" && $db){ - print get_mysql_result(" - CREATE TABLE db_version ( - version int(11) DEFAULT '0' - ) ENGINE=InnoDB DEFAULT CHARSET=latin1; - INSERT INTO db_version (version) VALUES ('1000');"); - print "[Database] Table 'db_version' does not exists.... Creating...\n\n"; - } -} - -#::: Returns Tab Delimited MySQL Result from Command Line -sub get_mysql_result{ - my $run_query = $_[0]; - if(!$db){ return; } - if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`; } - if($OS eq "Linux"){ - $run_query =~s/`//g; - return `$path --user="$user" --host $host --password="$pass" $db -N -B -e "$run_query"`; - } -} - -sub get_mysql_result_from_file{ - my $update_file = $_[0]; - if(!$db){ return; } - if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } - if($OS eq "Linux"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } -} - -#::: Gets Remote File based on request_url (1st Arg), and saves to destination file (2nd Arg) -#::: Example: get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); -sub get_remote_file{ - my $request_url = $_[0]; - my $destination_file = $_[1]; - my $content_type = $_[2]; - my $no_retry = $_[3]; - my $silent_download = $_[4]; - - if(!$has_internet_connection){ - print "[Download] Cannot download without internet connection...\n"; - return; - } - - #::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary - - if($destination_file=~/\//i){ - my @directory_path = split('/', $destination_file); - $build_path = ""; - $directory_index = 0; - while($directory_path[$directory_index] && $directory_path[$directory_index + 1]){ - $build_path .= $directory_path[$directory_index] . "/"; - # print "checking '" . $build_path . "'\n"; - #::: If path does not exist, create the directory... - if (!-d $build_path) { - print "[Copy] folder doesn't exist, creating '" . $build_path . "'\n"; - mkdir($build_path); - } - if(!$directory_indexr_path[$directory_index + 2] && $directory_indexr_path[$directory_index + 1]){ - # print $actual_path . "\n"; - $actual_path = $build_path; - last; - } - $directory_index++; - } - } - - if($OS eq "Windows"){ - #::: For non-text type requests... - if($content_type == 1){ - $break = 0; - while($break == 0) { - eval "use LWP::Simple qw(getstore);"; - # use LWP::Simple qw(getstore); - # print "request is " . $request_url . "\n"; - # print "destination file is supposed to be " . $destination_file . "\n"; - if(!getstore($request_url, $destination_file)){ - print "[Download] Error, no connection or failed request...\n\n"; - } - # sleep(1); - #::: Make sure the file exists before continuing... - if(-e $destination_file) { - $break = 1; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; - } else { $break = 0; } - usleep(500); - - if($no_retry){ - $break = 1; - } - } - } - else{ - $break = 0; - while($break == 0) { - require LWP::UserAgent; - my $ua = LWP::UserAgent->new; - $ua->timeout(10); - $ua->env_proxy; - my $response = $ua->get($request_url); - if ($response->is_success){ - open (FILE, '> ' . $destination_file . ''); - print FILE $response->decoded_content; - close (FILE); - } - else { - print "[Download] Error, no connection or failed request...\n\n"; - } - if(-e $destination_file) { - $break = 1; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; - } else { $break = 0; } - usleep(500); - - if($no_retry){ - $break = 1; - } - } - } - } - if($OS eq "Linux"){ - #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt - $wget = `wget --no-check-certificate --quiet -O $destination_file $request_url`; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; - if($wget=~/unable to resolve/i){ - print "Error, no connection or failed request...\n\n"; - #die; - } - } -} - -#::: Trim Whitespaces -sub trim { - my $string = $_[0]; - $string =~ s/^\s+//; - $string =~ s/\s+$//; - return $string; -} - -sub read_eqemu_config_xml { - my $confile = "eqemu_config.xml"; #default - open(F, "<$confile"); - my $indb = 0; - while() { - s/\r//g; - if(//i) { $indb = 1; } - next unless($indb == 1); - if(/<\/database>/i) { $indb = 0; last; } - if(/(.*)<\/host>/i) { $host = $1; } - elsif(/(.*)<\/username>/i) { $user = $1; } - elsif(/(.*)<\/password>/i) { $pass = $1; } - elsif(/(.*)<\/db>/i) { $db = $1; } - } -} - -#::: Fetch Latest PEQ AA's -sub aa_fetch{ - if(!$db){ - print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n"; - return; - } - - print "[Install] Pulling down PEQ AA Tables...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); - print "[Install] Installing AA Tables...\n"; - print get_mysql_result_from_file("db_update/peq_aa_tables_post_rework.sql"); - print "[Install] Done...\n\n"; -} - -#::: Fetch Latest Opcodes -sub opcodes_fetch{ - print "[Update] Pulling down latest opcodes...\n"; - %opcodes = ( - 1 => ["opcodes", $eqemu_repository_request_url . "utils/patches/opcodes.conf"], - 2 => ["mail_opcodes", $eqemu_repository_request_url . "utils/patches/mail_opcodes.conf"], - 3 => ["Titanium", $eqemu_repository_request_url . "utils/patches/patch_Titanium.conf"], - 4 => ["Secrets of Faydwer", $eqemu_repository_request_url . "utils/patches/patch_SoF.conf"], - 5 => ["Seeds of Destruction", $eqemu_repository_request_url . "utils/patches/patch_SoD.conf"], - 6 => ["Underfoot", $eqemu_repository_request_url . "utils/patches/patch_UF.conf"], - 7 => ["Rain of Fear", $eqemu_repository_request_url . "utils/patches/patch_RoF.conf"], - 8 => ["Rain of Fear 2", $eqemu_repository_request_url . "utils/patches/patch_RoF2.conf"], - ); - $loop = 1; - while($opcodes{$loop}[0]){ - #::: Split the request_url by the patches folder to get the file name from request_url - @real_file = split("patches/", $opcodes{$loop}[1]); - $find = 0; - while($real_file[$find]){ - $file_name = $real_file[$find]; - $find++; - } - - get_remote_file($opcodes{$loop}[1], $file_name); - $loop++; - } - print "[Update] Done...\n"; -} - -sub remove_duplicate_rule_values { - $ruleset_id = trim(get_mysql_result("SELECT `ruleset_id` FROM `rule_sets` WHERE `name` = 'default'")); - print "[Database] Default Ruleset ID: " . $ruleset_id . "\n"; - - $total_removed = 0; - - #::: Store Default values... - $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` = " . $ruleset_id); - my @lines = split("\n", $mysql_result); - foreach my $val (@lines){ - my @values = split("\t", $val); - $rule_set_values{$values[1]}[0] = $values[2]; - } - - #::: Compare default values against other rulesets to check for duplicates... - $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` != " . $ruleset_id); - my @lines = split("\n", $mysql_result); - foreach my $val (@lines){ - my @values = split("\t", $val); - if($values[2] == $rule_set_values{$values[1]}[0]){ - print "[Database] Removing duplicate : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . "\n"; - get_mysql_result("DELETE FROM `rule_values` WHERE `ruleset_id` = " . $values[0] . " AND `rule_name` = '" . $values[1] . "'"); - $total_removed++; - } - } - - print "[Database] Total duplicate rules removed... " . $total_removed . "\n"; -} - -sub copy_file { - $l_source_file = $_[0]; - $l_destination_file = $_[1]; - if($l_destination_file=~/\//i){ - my @directory_path = split('/', $l_destination_file); - $build_path = ""; - $directory_index = 0; - while($directory_path[$directory_index]){ - $build_path .= $directory_path[$directory_index] . "/"; - #::: If path does not exist, create the directory... - if (!-d $build_path) { - mkdir($build_path); - } - if(!$directory_path[$directory_index + 2] && $directory_path[$directory_index + 1]){ - # print $actual_path . "\n"; - $actual_path = $build_path; - last; - } - $directory_index++; - } - } - copy $l_source_file, $l_destination_file; -} - -sub fetch_latest_windows_binaries { - print "[Update] Fetching Latest Windows Binaries... \n"; - get_remote_file($install_repository_request_url . "master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); - print "[Update] Fetched Latest Windows Binaries... \n"; - print "[Update] Extracting... --- \n"; - unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); - my @files; - my $start_dir = "updates_staged/binaries"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/binaries\///g; - print "[Update] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); - } - print "[Update] Done\n"; - - rmtree('updates_staged'); -} - -sub fetch_latest_windows_binaries_bots { - print "[Update] Fetching Latest Windows Binaries with Bots...\n"; - get_remote_file($install_repository_request_url . "master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); - print "[Update] Fetched Latest Windows Binaries with Bots...\n"; - print "[Update] Extracting...\n"; - unzip('updates_staged/master_windows_build_bots.zip', 'updates_staged/binaries/'); - my @files; - my $start_dir = "updates_staged/binaries"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/binaries\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); - } - print "[Update] Done...\n"; - - rmtree('updates_staged'); -} - -sub do_windows_login_server_setup { - print "[Install] Fetching Loginserver... \n"; - get_remote_file($install_repository_request_url . "login_server.zip", "updates_staged/login_server.zip", 1); - print "[Install] Extracting... \n"; - unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); - my @files; - my $start_dir = "updates_staged/login_server"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/login_server\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); - } - print "[Install] Done... \n"; - - print "[Install] Pulling down Loginserver database tables...\n"; - get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); - print "[Install] Installing Loginserver tables...\n"; - print get_mysql_result_from_file("db_update/login_server_tables.sql"); - print "[Install] Done...\n"; - - add_login_server_firewall_rules(); - - rmtree('updates_staged'); - rmtree('db_update'); - - print "[Install] Press any key to continue...\n"; - - <>; #Read from STDIN - -} - -sub do_linux_login_server_setup { - - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/login_server\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); - } - print "\n Done... \n"; - - print "[Install] Pulling down Loginserver database tables...\n"; - get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); - print "[Install] Installing Loginserver tables...\n"; - print get_mysql_result_from_file("db_update/login_server_tables.sql"); - print "[Install] Done...\n\n"; - - rmtree('updates_staged'); - rmtree('db_update'); - - get_remote_file($install_repository_request_url . "linux/login.ini", "login_template.ini"); - get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes.conf"); - get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes_sod.conf"); - - get_installation_variables(); - my $db_name = $installation_variables{"mysql_eqemu_db_name"}; - my $db_user = $installation_variables{"mysql_eqemu_user"}; - my $db_password = $installation_variables{"mysql_eqemu_password"}; - - #::: Open new config file - open (NEW_CONFIG, '>', 'login.ini'); - - #::: Iterate through template and replace variables... - open (FILE_TEMPLATE, "login_template.ini"); - while (){ - chomp; - $o = $_; - #::: Find replace variables - if($o=~/db/i){ $o = "db = " . $db_name; } - if($o=~/user/i){ $o = "user = " . $db_user; } - if($o=~/password/i){ $o = "password = " . $db_password; } - - print NEW_CONFIG $o . "\n"; - } - - close(FILE_TEMPLATE); - close(NEW_CONFIG); - unlink("login_template.ini"); - - print "[Install] Press any key to continue...\n"; - - <>; #Read from STDIN - -} - -sub add_login_server_firewall_rules { - #::: Check Loginserver Firewall install for Windows - if($OS eq "Windows"){ - $output = `netsh advfirewall firewall show rule name=all`; - @output_buffer = split("\n", $output); - $has_loginserver_rules_titanium = 0; - $has_loginserver_rules_sod = 0; - foreach my $val (@output_buffer){ - if($val=~/Rule Name/i){ - $val=~s/Rule Name://g; - if($val=~/EQEmu Loginserver/i && $val=~/Titanium/i){ - $has_loginserver_rules_titanium = 1; - print "Found existing rule :: " . trim($val) . "\n"; - } - if($val=~/EQEmu Loginserver/i && $val=~/SOD/i){ - $has_loginserver_rules_sod = 1; - print "Found existing rule :: " . trim($val) . "\n"; - } - } - } - - if($has_loginserver_rules_titanium == 0){ - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; - print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) TCP" dir=in action=allow protocol=TCP localport=5998`; - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; - print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) UDP" dir=in action=allow protocol=UDP localport=5998`; - } - if($has_loginserver_rules_sod == 0){ - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; - print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) TCP" dir=in action=allow protocol=TCP localport=5999`; - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; - print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) UDP" dir=in action=allow protocol=UDP localport=5999`; - } - - print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n"; - print "\n"; - print "[Install] Instructions \n"; - print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; - print " - - login.eqemulator.net - 5998 - - - - - 127.0.0.1 - 5998 - - - - "; - print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; - } -} - -sub check_windows_firewall_rules{ - $output = `netsh advfirewall firewall show rule name=all`; - @output_buffer = split("\n", $output); - $has_world_rules = 0; - $has_zone_rules = 0; - foreach my $val (@output_buffer){ - if($val=~/Rule Name/i){ - $val=~s/Rule Name://g; - if($val=~/EQEmu World/i){ - $has_world_rules = 1; - print "[Install] Found existing rule :: " . trim($val) . "\n"; - } - if($val=~/EQEmu Zone/i){ - $has_zone_rules = 1; - print "[Install] Found existing rule :: " . trim($val) . "\n"; - } - } - } - - if($has_world_rules == 0){ - print "[Install] Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; - print `netsh advfirewall firewall add rule name="EQEmu World (9000) TCP" dir=in action=allow protocol=TCP localport=9000`; - print "[Install] Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; - print `netsh advfirewall firewall add rule name="EQEmu World (9000) UDP" dir=in action=allow protocol=UDP localport=9000`; - } - if($has_zone_rules == 0){ - print "[Install] Attempting to add EQEmu Zones (7000-7500) TCP \n"; - print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) TCP" dir=in action=allow protocol=TCP localport=7000-7500`; - print "[Install] Attempting to add EQEmu Zones (7000-7500) UDP \n"; - print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) UDP" dir=in action=allow protocol=UDP localport=7000-7500`; - } -} - -sub fetch_server_dlls{ - print "[Download] Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; - get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); - get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); - get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); -} - -sub fetch_peq_db_full{ - print "[Install] Downloading latest PEQ Database... Please wait...\n"; - get_remote_file("http://edit.peqtgc.com/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1); - print "[Install] Downloaded latest PEQ Database... Extracting...\n"; - unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); - my $start_dir = "updates_staged/peq_db"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/peq_db\///g; - if($file=~/peqbeta|player_tables/i){ - print "[Install] DB :: Installing :: " . $destination_file . "\n"; - get_mysql_result_from_file($file); - } - if($file=~/eqtime/i){ - print "[Install] Installing eqtime.cfg\n"; - copy_file($file, "eqtime.cfg"); - } - } -} - -sub map_files_fetch_bulk{ - print "[Install] Fetching Latest Maps... (This could take a few minutes...)\n"; - get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1); - unzip('maps/maps.zip', 'maps/'); - my @files; - my $start_dir = "maps/EQEmuMaps-master/maps"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/maps\/EQEmuMaps-master\/maps\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, "maps/" . $new_file); - } - print "[Install] Fetched Latest Maps\n"; - - rmtree('maps/EQEmuMaps-master'); - unlink('maps/maps.zip'); -} - -sub map_files_fetch{ - print "[Install] Fetching Latest Maps --- \n"; - - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt"); - - #::: Get Data from manifest - open (FILE, "updates_staged/eqemu_maps_manifest.txt"); - $i = 0; - while (){ - chomp; - $o = $_; - @manifest_map_data = split(',', $o); - if($manifest_map_data[0] ne ""){ - $maps_manifest[$i] = [$manifest_map_data[0], $manifest_map_data[1]]; - $i++; - } - } - - #::: Download - $fc = 0; - for($m = 0; $m <= $i; $m++){ - my $file_existing = $maps_manifest[$m][0]; - my $file_existing_size = (stat $file_existing)[7]; - if($file_existing_size != $maps_manifest[$m][1]){ - print "[Install] Updating: '" . $maps_manifest[$m][0] . "'\n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1); - $fc++; - } - } - - if($fc == 0){ - print "[Install] No Map Updates found... \n\n"; - } -} - -sub quest_files_fetch{ - if (!-e "updates_staged/Quests-Plugins-master/quests/") { - print "[Update] Fetching Latest Quests --- \n"; - get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "[Install] Fetched latest quests...\n"; - mkdir('updates_staged'); - unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); - } - - $fc = 0; - use File::Find; - use File::Compare; - - my @files; - my $start_dir = "updates_staged/Quests-Plugins-master/quests/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - if($file=~/\.pl|\.lua|\.ext/i){ - $staged_file = $file; - $destination_file = $file; - $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; - - if (!-e $destination_file) { - copy_file($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n"; - $fc++; - } - else{ - $directory_indexff = do_file_diff($destination_file, $staged_file); - if($directory_indexff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - - print $directory_indexff . "\n"; - print "[Update] File Different :: '" . $destination_file . "'\n"; - print "[Update] Do you wish to update this Quest? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; - my $input = ; - if($input=~/N/i){} - else{ - #::: Make a backup - copy_file($destination_file, $backup_dest); - #::: Copy staged to running - copy($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n\n"; - } - $fc++; - } - } - } - } - - rmtree('updates_staged'); - - if($fc == 0){ - print "[Update] No Quest Updates found... \n\n"; - } -} - -sub lua_modules_fetch { - if (!-e "updates_staged/Quests-Plugins-master/quests/lua_modules/") { - print "[Update] Fetching Latest LUA Modules --- \n"; - get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "[Update] Fetched latest LUA Modules...\n"; - unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); - } - - $fc = 0; - use File::Find; - use File::Compare; - - my @files; - my $start_dir = "updates_staged/Quests-Plugins-master/quests/lua_modules/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - if($file=~/\.pl|\.lua|\.ext/i){ - $staged_file = $file; - $destination_file = $file; - $destination_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; - - if (!-e $destination_file) { - copy_file($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n"; - $fc++; - } - else{ - $directory_indexff = do_file_diff($destination_file, $staged_file); - if($directory_indexff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - print $directory_indexff . "\n"; - print "[Update] File Different :: '" . $destination_file . "'\n"; - print "[Update] Do you wish to update this LUA Module? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; - my $input = ; - if($input=~/N/i){} - else{ - #::: Make a backup - copy_file($destination_file, $backup_dest); - #::: Copy staged to running - copy($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n\n"; - } - $fc++; - } - } - } - } - - if($fc == 0){ - print "[Update] No LUA Modules Updates found... \n\n"; - } -} - -sub plugins_fetch{ - if (!-e "updates_staged/Quests-Plugins-master/plugins/") { - print "[Update] Fetching Latest Plugins\n"; - get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "[Update] Fetched latest plugins\n"; - unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); - } - - $fc = 0; - use File::Find; - use File::Compare; - - my @files; - my $start_dir = "updates_staged/Quests-Plugins-master/plugins/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - if($file=~/\.pl|\.lua|\.ext/i){ - $staged_file = $file; - $destination_file = $file; - $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; - - if (!-e $destination_file) { - copy_file($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n"; - $fc++; - } - else{ - $directory_indexff = do_file_diff($destination_file, $staged_file); - if($directory_indexff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - print $directory_indexff . "\n"; - print "[Update] File Different :: '" . $destination_file . "'\n"; - print "[Update] Do you wish to update this Plugin? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; - my $input = ; - if($input=~/N/i){} - else{ - #::: Make a backup - copy_file($destination_file, $backup_dest); - #::: Copy staged to running - copy($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n\n"; - } - $fc++; - } - } - } - } - - if($fc == 0){ - print "[Update] No Plugin Updates found... \n\n"; - } -} - -sub do_file_diff{ - $file_1 = $_[0]; - $file_2 = $_[1]; - if($OS eq "Windows"){ - eval "use Text::Diff"; - $directory_indexff = diff($file_1, $file_2, { STYLE => "Unified" }); - return $directory_indexff; - } - if($OS eq "Linux"){ - # print 'diff -u "$file_1" "$file_2"' . "\n"; - return `diff -u "$file_1" "$file_2"`; - } -} - -sub unzip { - $archive_to_unzip = $_[0]; - $dest_folder = $_[1]; - - if($OS eq "Windows"){ - eval "use Archive::Zip qw( :ERROR_CODES :CONSTANTS )"; - my $zip = Archive::Zip->new(); - unless ( $zip->read($archive_to_unzip) == AZ_OK ) { - die 'read error'; - } - print "[Unzip] Extracting...\n"; - $zip->extractTree('', $dest_folder); - } - if($OS eq "Linux"){ - print `unzip -o -q "$archive_to_unzip" -d "$dest_folder"`; - } -} - -sub are_file_sizes_different{ - $file_1 = $_[0]; - $file_2 = $_[1]; - my $file_1 = (stat $file_1)[7]; - my $file_2 = (stat $file_2)[7]; - # print $file_1 . " :: " . $file_2 . "\n"; - if($file_1 != $file_2){ - return 1; - } - return; -} - -sub do_bots_db_schema_drop{ - #"drop_bots.sql" is run before reverting database back to 'normal' - print "[Database] Fetching drop_bots.sql...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); - print get_mysql_result_from_file("db_update/drop_bots.sql"); - - print "[Database] Removing bot database tables...\n"; - print get_mysql_result("DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots:%';"); - - if(get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && $db){ - print get_mysql_result("DELETE FROM `commands` WHERE `command` LIKE 'bot';"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && $db){ - print get_mysql_result("DELETE FROM `command_settings` WHERE `command` LIKE 'bot';"); - } - - if(get_mysql_result("SHOW KEYS FROM `group_id` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ - print get_mysql_result("ALTER TABLE `group_id` DROP PRIMARY KEY;"); - } - print get_mysql_result("ALTER TABLE `group_id` ADD PRIMARY KEY (`groupid`, `charid`, `ismerc`);"); - - if(get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ - print get_mysql_result("ALTER TABLE `guild_members` DROP PRIMARY KEY;"); - } - print get_mysql_result("ALTER TABLE `guild_members` ADD PRIMARY KEY (`char_id`);"); - - print get_mysql_result("UPDATE `spawn2` SET `enabled` = 0 WHERE `id` IN (59297,59298);"); - - if(get_mysql_result("SHOW COLUMNS FROM `db_version` LIKE 'bots_version'") ne "" && $db){ - print get_mysql_result("UPDATE `db_version` SET `bots_version` = 0;"); - } - print "[Database] Done...\n"; -} - -sub modify_db_for_bots{ - #Called after the db bots schema (2015_09_30_bots.sql) has been loaded - print "[Database] Modifying database for bots...\n"; - print get_mysql_result("UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298);"); - - if(get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ - print get_mysql_result("ALTER TABLE `guild_members` DROP PRIMARY KEY;"); - } - - if(get_mysql_result("SHOW KEYS FROM `group_id` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ - print get_mysql_result("ALTER TABLE `group_id` DROP PRIMARY KEY;"); - } - print get_mysql_result("ALTER TABLE `group_id` ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`);"); - - if(get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && get_mysql_result("SELECT `command` FROM `command_settings` WHERE `command` LIKE 'bot'") eq "" && $db){ - print get_mysql_result("INSERT INTO `command_settings` VALUES ('bot', '0', '');"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && get_mysql_result("SELECT `command` FROM `commands` WHERE `command` LIKE 'bot'") eq "" && $db){ - print get_mysql_result("INSERT INTO `commands` VALUES ('bot', '0');"); - } - - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotAAExpansion'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:AAExpansion' WHERE `rule_name` LIKE 'Bots:BotAAExpansion';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AAExpansion'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:AAExpansion', '8', 'The expansion through which bots will obtain AAs');"); - } - - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreateBotCount'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:CreationLimit' WHERE `rule_name` LIKE 'Bots:CreateBotCount';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreationLimit'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:CreationLimit', '150', 'Number of bots that each account can create');"); - } - - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotFinishBuffing'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:FinishBuffing' WHERE `rule_name` LIKE 'Bots:BotFinishBuffing';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:FinishBuffing'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:FinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.');"); - } - - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotGroupBuffing'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:GroupBuffing' WHERE `rule_name` LIKE 'Bots:BotGroupBuffing';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:GroupBuffing'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:GroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.');"); - } - - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotManaRegen'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:ManaRegen' WHERE `rule_name` LIKE 'Bots:BotManaRegen';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:ManaRegen'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:ManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.');"); - } - - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotQuest'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpawnLimit' WHERE `rule_name` LIKE 'Bots:BotQuest';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpawnLimit'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpawnLimit', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl');"); - } - - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotSpellQuest'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpells' WHERE `rule_name` LIKE 'Bots:BotSpellQuest';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpells'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpells', 'false', 'Anita Thrall\\\'s (Anita_Thrall.pl) Bot Spell Scriber quests.');"); - } - - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnBotCount'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:SpawnLimit' WHERE `rule_name` LIKE 'Bots:SpawnBotCount';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnLimit'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:SpawnLimit', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid');"); - } - - convert_existing_bot_data(); -} - -sub convert_existing_bot_data{ - if(get_mysql_result("SHOW TABLES LIKE 'bots'") ne "" && $db){ - print "[Database] Converting existing bot data...\n"; - print get_mysql_result("INSERT INTO `bot_data` (`bot_id`, `owner_id`, `spells_id`, `name`, `last_name`, `zone_id`, `gender`, `race`, `class`, `level`, `creation_day`, `last_spawn`, `time_spawned`, `size`, `face`, `hair_color`, `hair_style`, `beard`, `beard_color`, `eye_color_1`, `eye_color_2`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `ac`, `atk`, `hp`, `mana`, `str`, `sta`, `cha`, `dex`, `int`, `agi`, `wis`, `fire`, `cold`, `magic`, `poison`, `disease`, `corruption`) SELECT `BotID`, `BotOwnerCharacterID`, `BotSpellsID`, `Name`, `LastName`, `LastZoneId`, `Gender`, `Race`, `Class`, `BotLevel`, UNIX_TIMESTAMP(`BotCreateDate`), UNIX_TIMESTAMP(`LastSpawnDate`), `TotalPlayTime`, `Size`, `Face`, `LuclinHairColor`, `LuclinHairStyle`, `LuclinBeard`, `LuclinBeardColor`, `LuclinEyeColor`, `LuclinEyeColor2`, `DrakkinHeritage`, `DrakkinTattoo`, `DrakkinDetails`, `AC`, `ATK`, `HP`, `Mana`, `STR`, `STA`, `CHA`, `DEX`, `_INT`, `AGI`, `WIS`, `FR`, `CR`, `MR`, `PR`, `DR`, `Corrup` FROM `bots`;"); - - print get_mysql_result("INSERT INTO `bot_inspect_messages` (`bot_id`, `inspect_message`) SELECT `BotID`, `BotInspectMessage` FROM `bots`;"); - - print get_mysql_result("RENAME TABLE `bots` TO `bots_old`;"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'botstances'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_stances` (`bot_id`, `stance_id`) SELECT bs.`BotID`, bs.`StanceID` FROM `botstances` bs INNER JOIN `bot_data` bd ON bs.`BotID` = bd.`bot_id`;"); - - print get_mysql_result("RENAME TABLE `botstances` TO `botstances_old`;"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'bottimers'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) SELECT bt.`BotID`, bt.`TimerID`, bt.`Value` FROM `bottimers` bt INNER JOIN `bot_data` bd ON bt.`BotID` = bd.`bot_id`;"); - - print get_mysql_result("RENAME TABLE `bottimers` TO `bottimers_old`;"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'botbuffs'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_buffs` (`buffs_index`, `bot_id`, `spell_id`, `caster_level`, `duration_formula`, `tics_remaining`, `poison_counters`, `disease_counters`, `curse_counters`, `corruption_counters`, `numhits`, `melee_rune`, `magic_rune`, `persistent`) SELECT bb.`BotBuffId`, bb.`BotId`, bb.`SpellId`, bb.`CasterLevel`, bb.`DurationFormula`, bb.`TicsRemaining`, bb.`PoisonCounters`, bb.`DiseaseCounters`, bb.`CurseCounters`, bb.`CorruptionCounters`, bb.`HitCount`, bb.`MeleeRune`, bb.`MagicRune`, bb.`Persistent` FROM `botbuffs` bb INNER JOIN `bot_data` bd ON bb.`BotId` = bd.`bot_id`;"); - - if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'dot_rune'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`dot_rune` = bbo.`dot_rune` WHERE bb.`bot_id` = bbo.`BotID`;"); - } - - if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_x'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_x` = bbo.`caston_x` WHERE bb.`bot_id` = bbo.`BotID`;"); - } - - if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_y'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_y` = bbo.`caston_y` WHERE bb.`bot_id` = bbo.`BotID`;"); - } - - if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_z'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_z` = bbo.`caston_z` WHERE bb.`bot_id` = bbo.`BotID`;"); - } - - if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'ExtraDIChance'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`extra_di_chance` = bbo.`ExtraDIChance` WHERE bb.`bot_id` = bbo.`BotID`;"); - } - - print get_mysql_result("RENAME TABLE `botbuffs` TO `botbuffs_old`;"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'botinventory'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_inventories` (`inventories_index`, `bot_id`, `slot_id`, `item_id`, `inst_charges`, `inst_color`, `inst_no_drop`, `augment_1`, `augment_2`, `augment_3`, `augment_4`, `augment_5`) SELECT bi.`BotInventoryID`, bi.`BotID`, bi.`SlotID`, bi.`ItemID`, bi.`charges`, bi.`color`, bi.`instnodrop`, bi.`augslot1`, bi.`augslot2`, bi.`augslot3`, bi.`augslot4`, bi.`augslot5` FROM `botinventory` bi INNER JOIN `bot_data` bd ON bi.`BotID` = bd.`bot_id`;"); - - if(get_mysql_result("SHOW COLUMNS FROM `botinventory` LIKE 'augslot6'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_inventories` bi INNER JOIN `botinventory` bio ON bi.`inventories_index` = bio.`BotInventoryID` SET bi.`augment_6` = bio.`augslot6` WHERE bi.`bot_id` = bio.`BotID`;"); - } - - print get_mysql_result("RENAME TABLE `botinventory` TO `botinventory_old`;"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'botpets'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_pets` (`pets_index`, `pet_id`, `bot_id`, `name`, `mana`, `hp`) SELECT bp.`BotPetsId`, bp.`PetId`, bp.`BotId`, bp.`Name`, bp.`Mana`, bp.`HitPoints` FROM `botpets` bp INNER JOIN `bot_data` bd ON bp.`BotId` = bd.`bot_id`;"); - - print get_mysql_result("RENAME TABLE `botpets` TO `botpets_old`;"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'botpetbuffs'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_pet_buffs` (`pet_buffs_index`, `pets_index`, `spell_id`, `caster_level`, `duration`) SELECT bpb.`BotPetBuffId`, bpb.`BotPetsId`, bpb.`SpellId`, bpb.`CasterLevel`, bpb.`Duration` FROM `botpetbuffs` bpb INNER JOIN `bot_pets` bp ON bpb.`BotPetsId` = bp.`pets_index`;"); - - print get_mysql_result("RENAME TABLE `botpetbuffs` TO `botpetbuffs_old`;"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'botpetinventory'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_pet_inventories` (`pet_inventories_index`, `pets_index`, `item_id`) SELECT bpi.`BotPetInventoryId`, bpi.`BotPetsId`, bpi.`ItemId` FROM `botpetinventory` bpi INNER JOIN `bot_pets` bp ON bpi.`BotPetsId` = bp.`pets_index`;"); - - print get_mysql_result("RENAME TABLE `botpetinventory` TO `botpetinventory_old`;"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'botgroup'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_groups` (`groups_index`, `group_leader_id`, `group_name`) SELECT bg.`BotGroupId`, bg.`BotGroupLeaderBotId`, bg.`BotGroupName` FROM `botgroup` bg INNER JOIN `bot_data` bd ON bg.`BotGroupLeaderBotId` = bd.`bot_id`;"); - - print get_mysql_result("RENAME TABLE `botgroup` TO `botgroup_old`;"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'botgroupmembers'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_group_members` (`group_members_index`, `groups_index`, `bot_id`) SELECT bgm.`BotGroupMemberId`, bgm.`BotGroupId`, bgm.`BotId` FROM `botgroupmembers` bgm INNER JOIN `bot_groups` bg ON bgm.`BotGroupId` = bg.`groups_index` INNER JOIN `bot_data` bd ON bgm.`BotId` = bd.`bot_id`;"); - - print get_mysql_result("RENAME TABLE `botgroupmembers` TO `botgroupmembers_old`;"); - } - - if(get_mysql_result("SHOW TABLES LIKE 'botguildmembers'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_guild_members` (`bot_id`, `guild_id`, `rank`, `tribute_enable`, `total_tribute`, `last_tribute`, `banker`, `public_note`, `alt`) SELECT bgm.`char_id`, bgm.`guild_id`, bgm.`rank`, bgm.`tribute_enable`, bgm.`total_tribute`, bgm.`last_tribute`, bgm.`banker`, bgm.`public_note`, bgm.`alt` FROM `botguildmembers` bgm INNER JOIN `guilds` g ON bgm.`guild_id` = g.`id` INNER JOIN `bot_data` bd ON bgm.`char_id` = bd.`bot_id`;"); - - print get_mysql_result("RENAME TABLE `botguildmembers` TO `botguildmembers_old`;"); - } -} - -sub get_bots_db_version{ - #::: Check if bots_version column exists... - if(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db){ - print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;"); - print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; - } - $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); - return $bots_local_db_version; -} - -sub bots_db_management{ - #::: Main Binary Database version - $binary_database_version = trim($db_version[2]); - - #::: If we have stale data from main db run - if($db_run_stage > 0 && $bots_db_management == 0){ - clear_database_runs(); - } - - if($binary_database_version == 0){ - print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n"; - return; - } - - #::: Set on flag for running bot updates... - $bots_db_management = 1; - - $bots_local_db_version = get_bots_db_version(); - - run_database_check(); -} - -sub main_db_management{ - #::: If we have stale data from bots db run - if($db_run_stage > 0 && $bots_db_management == 1){ - clear_database_runs(); - } - - #::: Main Binary Database version - $binary_database_version = trim($db_version[1]); - - $bots_db_management = 0; - run_database_check(); -} - -sub clear_database_runs{ - # print "DEBUG :: clear_database_runs\n\n"; - #::: Clear manifest data... - %m_d = (); - #::: Clear updates... - @total_updates = (); - #::: Clear stage - $db_run_stage = 0; -} - -#::: Responsible for Database Upgrade Routines -sub run_database_check{ - - if(!$db){ - print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n"; - return; - } - - if(!@total_updates){ - #::: Pull down bots database manifest - if($bots_db_management == 1){ - print "[Database] Retrieving latest bots database manifest...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); - } - #::: Pull down mainstream database manifest - else{ - print "[Database] Retrieving latest database manifest...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); - } - } - - #::: Run 2 - Running pending updates... - if(@total_updates || $db_run_stage == 1){ - @total_updates = sort @total_updates; - foreach my $val (@total_updates){ - $file_name = trim($m_d{$val}[1]); - print "[Database] Running Update: " . $val . " - " . $file_name . "\n"; - print get_mysql_result_from_file("db_update/$file_name"); - print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val"); - - if($bots_db_management == 1 && $val == 9000){ - modify_db_for_bots(); - } - } - $db_run_stage = 2; - } - #::: Run 1 - Initial checking of needed updates... - else{ - print "[Database] Reading manifest...\n"; - use Data::Dumper; - open (FILE, "db_update/db_update_manifest.txt"); - while () { - chomp; - $o = $_; - if($o=~/#/i){ next; } - @manifest = split('\|', $o); - $m_d{$manifest[0]} = [@manifest]; - } - #::: Setting Manifest stage... - $db_run_stage = 1; - } - - @total_updates = (); - - #::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest... - if($local_database_version){ - $revision_check = $local_database_version; - } - else { - $revision_check = 1000; - if(get_mysql_result("SHOW TABLES LIKE 'character_data'") ne ""){ - $revision_check = 9000; - } - } - - #::: Iterate through Manifest backwards from binary version down to local version... - for($i = $binary_database_version ; $i > $revision_check; $i--){ - if(!defined($m_d{$i}[0])){ next; } - - $file_name = trim($m_d{$i}[1]); - $query_check = trim($m_d{$i}[2]); - $match_type = trim($m_d{$i}[3]); - $match_text = trim($m_d{$i}[4]); - - #::: Match type update - if($match_type eq "contains"){ - if(trim(get_mysql_result($query_check))=~/$match_text/i){ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; - fetch_missing_db_update($i, $file_name); - push(@total_updates, $i); - } - else{ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; - } - print_match_debug(); - print_break(); - } - if($match_type eq "missing"){ - if(get_mysql_result($query_check)=~/$match_text/i){ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; - next; - } - else{ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; - fetch_missing_db_update($i, $file_name); - push(@total_updates, $i); - } - print_match_debug(); - print_break(); - } - if($match_type eq "empty"){ - if(get_mysql_result($query_check) eq ""){ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; - fetch_missing_db_update($i, $file_name); - push(@total_updates, $i); - } - else{ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; - } - print_match_debug(); - print_break(); - } - if($match_type eq "not_empty"){ - if(get_mysql_result($query_check) ne ""){ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; - fetch_missing_db_update($i, $file_name); - push(@total_updates, $i); - } - else{ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; - } - print_match_debug(); - print_break(); - } - } - print "\n"; - - if(scalar (@total_updates) == 0 && $db_run_stage == 2){ - print "[Database] No updates need to be run...\n"; - if($bots_db_management == 1){ - print "[Database] Setting Database to Bots Binary Version (" . $binary_database_version . ") if not already...\n\n"; - get_mysql_result("UPDATE db_version SET bots_version = $binary_database_version "); - } - else{ - print "[Database] Setting Database to Binary Version (" . $binary_database_version . ") if not already...\n\n"; - get_mysql_result("UPDATE db_version SET version = $binary_database_version "); - } - - clear_database_runs(); - } -} - -sub fetch_missing_db_update{ - $db_update = $_[0]; - $update_file = $_[1]; - if($db_update >= 9000){ - if($bots_db_management == 1){ - get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); - } - else{ - get_remote_file($eqemu_repository_request_url . "utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); - } - } - elsif($db_update >= 5000 && $db_update <= 9000){ - get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); - } -} - -sub print_match_debug{ - if(!$debug){ return; } - print " Match Type: '" . $match_type . "'\n"; - print " Match Text: '" . $match_text . "'\n"; - print " Query Check: '" . $query_check . "'\n"; - print " Result: '" . trim(get_mysql_result($query_check)) . "'\n"; -} - -sub print_break{ - if(!$debug){ return; } - print "\n==============================================\n"; -} - -sub generate_random_password { - my $passwordsize = shift; - my @alphanumeric = ('a'..'z', 'A'..'Z', 0..9); - my $randpassword = join '', - map $alphanumeric[rand @alphanumeric], 0..$passwordsize; - - return $randpassword; -} From bf283543014cc58dc4067298b77b9f7bf9f50eba Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 6 Sep 2016 22:14:14 -0500 Subject: [PATCH 363/693] Upload Linux installer for Debian/Ubuntu/CentOS/Fedora utils/scripts/linux_installer/install.sh [skip ci] --- utils/scripts/linux_installer/install.sh | 236 +++++++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 utils/scripts/linux_installer/install.sh diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh new file mode 100644 index 000000000..d9cdc0485 --- /dev/null +++ b/utils/scripts/linux_installer/install.sh @@ -0,0 +1,236 @@ +#!/usr/bin/env bash + +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root" 1>&2 + exit 1 +fi + +#::: Determine releases +if [[ -f /etc/debian_version ]]; then + export OS=Debian +elif [[ -f /etc/fedora-release ]]; then + export OS=fedora_core +elif [[ -f /etc/redhat-release ]]; then + export OS=red_hat +else + echo "This script must be run on a Debian or RedHat derivative" + exit 1 +fi + +echo "######################################################### " +echo "#::: EverQuest Emulator Modular Installer " +echo "#::: Installer Author: Akkadius " +echo "#::: Installer Co-Author(s): N0ctrnl " +echo "#::: " +echo "#::: EQEmulator Server Software is developed and maintained " +echo "#::: by the EQEmulator Developement team " +echo "#::: " +echo "#::: Everquest is a registered trademark " +echo "#::: Daybreak Game Company LLC. " +echo "#::: " +echo "#::: EQEmulator is not associated or " +echo "#::: affiliated in any way with Daybreak Game Company LLC. " +echo "######################################################### " +echo "#: " +echo "######################################################### " +echo "#::: To be installed: " +echo "######################################################### " +echo "- Server running folder - Will be installed to the folder you ran this script " +echo "- MariaDB (MySQL) - Database engine " +echo "- Perl 5.X :: Scripting language for quest engines " +echo "- LUA Configured :: Scripting language for quest engines " +echo "- Latest PEQ Database " +echo "- Latest PEQ Quests " +echo "- Latest Plugins repository " +echo "- Maps (Latest V2) formats are loaded " +echo "- New Path files are loaded " +echo "- Optimized server binaries " +echo "######################################################### " + +# Installation variables (Don't need to change, only for advanced users) + +export eqemu_server_directory=/home/eqemu +export apt_options="-y -qq" # Set autoconfirm and silent install + +################################################################ + +read -n1 -r -p "Press any key to continue..." key + +#::: Setting up user environment (eqemu) +echo "First, we need to set your passwords..." +echo "Make sure that you remember these and keep them somewhere" +echo "" +echo "" +groupadd eqemu +useradd -g eqemu -d $eqemu_server_directory eqemu +passwd eqemu + +#::: Make server directory and go to it +mkdir $eqemu_server_directory +cd $eqemu_server_directory + +#::: Setup MySQL root user PW +read -p "Enter MySQL root (Database) password: " eqemu_db_root_password + +#::: Write install variables (later use) +echo "mysql_root:$eqemu_db_root_password" > install_variables.txt + +#::: Setup MySQL server +read -p "Enter Database Name (single word, no special characters, lower case):" eqemu_db_name +read -p "Enter (Database) MySQL EQEmu Server username: " eqemu_db_username +read -p "Enter (Database) MySQL EQEmu Server password: " eqemu_db_password + +#::: Write install variables (later use) +echo "mysql_eqemu_db_name:$eqemu_db_name" >> install_variables.txt +echo "mysql_eqemu_user:$eqemu_db_username" >> install_variables.txt +echo "mysql_eqemu_password:$eqemu_db_password" >> install_variables.txt + +if [[ "$OS" == "Debian" ]]; then + # Install pre-req packages + apt-get $apt_options install bash + apt-get $apt_options install build-essential + apt-get $apt_options install cmake + apt-get $apt_options install cpp + apt-get $apt_options install curl + apt-get $apt_options install debconf-utils + apt-get $apt_options install g++ + apt-get $apt_options install gcc + apt-get $apt_options install git + apt-get $apt_options install git-core + apt-get $apt_options install libio-stringy-perl + apt-get $apt_options install liblua5.1 + apt-get $apt_options install liblua5.1-dev + apt-get $apt_options install libluabind-dev + apt-get $apt_options install libmysql++ + apt-get $apt_options install libperl-dev + apt-get $apt_options install libperl5i-perl + apt-get $apt_options install libwtdbomysql-dev + apt-get $apt_options install lua5.1 + apt-get $apt_options install make + apt-get $apt_options install mariadb-client + apt-get $apt_options install open-vm-tools + apt-get $apt_options install unzip + apt-get $apt_options install uuid-dev + apt-get $apt_options install zlib-bin + apt-get $apt_options install zlibc + + #::: Install FTP for remote FTP access + echo "proftpd-basic shared/proftpd/inetd_or_standalone select standalone" | debconf-set-selections + apt-get -y -q install proftpd + + #::: Install MariaDB Server + export DEBIAN_FRONTEND=noninteractive + debconf-set-selections <<< 'mariadb-server-10.0 mysql-server/root_password password PASS' + debconf-set-selections <<< 'mariadb-server-10.0 mysql-server/root_password_again password PASS' + apt-get install -y mariadb-server + mysql -uroot -pPASS -e "SET PASSWORD = PASSWORD('$eqemu_db_root_password');" + +elif [[ "$OS" == "red_hat" ]]; then + # Do RedHat / CentOS stuff + # Add the MariaDB repository to yum +cat < /etc/yum.repos.d/mariadb.repo +# MariaDB 10.1 CentOS repository list - created 2016-08-20 05:42 UTC +# http://downloads.mariadb.org/mariadb/repositories/ +[mariadb] +name = MariaDB +baseurl = http://yum.mariadb.org/10.1/centos7-amd64 +gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB +enabled=1 +gpgcheck=1 +EOF + # Install prereqs + yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + yum -y install deltarpm + yum -y install open-vm-tools vim cmake boost-* zlib-devel mariadb-server mariadb-client mariadb-devel mariadb-libs mariadb-compat perl-* lua* dos2unix php-mysql proftpd + yum -y groupinstall "Development Tools" "Basic Web Server" "Compatibility Libraries" + +elif [[ "$OS" == "fedora_core" ]]; then + # Do Fedora stuff + dnf -y install open-vm-tools vim cmake boost-devel zlib-devel mariadb-server mariadb-devel mariadb-libs perl perl-DBD-MySQL perl-IO-stringy perl-devel lua-devel lua-sql-mysql dos2unix php-mysql proftpd wget compat-lua-libs compat-lua-devel compat-lua perl-Time-HiRes + dnf -y groupinstall "Development Tools" "Basic Web Server" "C Development Tools and Libraries" +fi + +if [[ "$OS" == "fedora_core" ]] || [[ "$OS" == "red_hat" ]]; then + # Start MariaDB server and set root password + echo "Starting MariaDB server..." + systemctl enable mariadb.service + systemctl start mariadb.service + sleep 5 + /usr/bin/mysqladmin -u root password $eqemu_db_root_password +fi + +#::: Configure game server database user +mysql -uroot -p$eqemu_db_root_password -e "CREATE USER '$eqemu_db_username'@'localhost' IDENTIFIED BY '$eqemu_db_password';" +mysql -uroot -p$eqemu_db_root_password -e "GRANT GRANT OPTION ON *.* TO '$eqemu_db_username'@'localhost';" +mysql -uroot -p$eqemu_db_root_password -e "GRANT ALL ON *.* TO '$eqemu_db_username'@'localhost';" + +#::: Create source and server directories +mkdir $eqemu_server_directory/source +mkdir $eqemu_server_directory/server +mkdir $eqemu_server_directory/server/export +mkdir $eqemu_server_directory/server/logs +mkdir $eqemu_server_directory/server/shared +mkdir $eqemu_server_directory/server/maps + +#::: Pull down needed files for the installer from the Install repo + +cd $eqemu_server_directory/source +git clone https://github.com/EQEmu/Server.git +mkdir $eqemu_server_directory/source/Server/build +cd $eqemu_server_directory/source/Server/build + +echo "Generating CMake build files..." +if [[ "$OS" == "fedora_core" ]]; then + cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -DLUA_INCLUDE_DIR=/usr/include/lua-5.1/ -G "Unix Makefiles" .. +else + cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -G "Unix Makefiles" .. +fi +echo "Building EQEmu Server code. This will take a while." + +#::: Grab loginserver dependencies +cd $eqemu_server_directory/source/Server/dependencies +if [[ "$OS" == "Debian" ]]; then + wget http://eqemu.github.io/downloads/ubuntu_LoginServerCrypto_x64.zip + unzip ubuntu_LoginServerCrypto_x64.zip + rm ubuntu_LoginServerCrypto_x64.zip +elif [[ "$OS" == "fedora_core" ]] || [[ "$OS" == "red_hat" ]]; then + wget http://eqemu.github.io/downloads/fedora12_LoginServerCrypto_x64.zip + unzip fedora12_LoginServerCrypto_x64.zip + rm fedora12_LoginServerCrypto_x64.zip +fi +cd $eqemu_server_directory/source/Server/build + +#::: Build +make + +#::: Back to server directory +cd $eqemu_server_directory/server +wget https://dl.dropboxusercontent.com/u/50023467/dl/eqemu/eqemu_server.pl + +#::: Link build files + +cd $eqemu_server_directory/server + +#::: Map lowercase to uppercase to avoid issues +ln -s maps Maps + +ln -s $eqemu_server_directory/source/Server/build/bin/loginserver +ln -s $eqemu_server_directory/source/Server/build/bin/eqlaunch +ln -s $eqemu_server_directory/source/Server/build/bin/export_client_files +ln -s $eqemu_server_directory/source/Server/build/bin/import_client_files +ln -s $eqemu_server_directory/source/Server/build/bin/libcommon.a +ln -s $eqemu_server_directory/source/Server/build/bin/libluabind.a +ln -s $eqemu_server_directory/source/Server/build/bin/queryserv +ln -s $eqemu_server_directory/source/Server/build/bin/shared_memory +ln -s $eqemu_server_directory/source/Server/build/bin/ucs +ln -s $eqemu_server_directory/source/Server/build/bin/world +ln -s $eqemu_server_directory/source/Server/build/bin/zone + +#::: Notes + +perl $eqemu_server_directory/server/eqemu_server.pl new_server + +#::: Chown files +chown eqemu:eqemu $eqemu_server_directory/ -R +chmod 755 $eqemu_server_directory/server/*.pl +chmod 755 $eqemu_server_directory/server/*.sh From 90dc7a4e387984b45db2b572864818c05cc88f58 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 6 Sep 2016 22:36:50 -0500 Subject: [PATCH 364/693] Fix linux installs [skip ci] --- utils/scripts/eqemu_server.pl | 6 +++--- utils/scripts/linux_installer/install.sh | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 0cf23b9cb..4e98c1fbd 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -196,13 +196,13 @@ sub new_server { } closedir(DIR); - if($file_count > 1 && !-e "install_variables.txt"){ + if($file_count > 1 && (!-e "install_variables.txt" || !-e "../install_variables.txt")){ print "[New Server] ERROR: You must run eqemu_server.pl in an empty directory\n"; <>; exit; } - if(-e "install_variables.txt"){ + if(-e "install_variables.txt" || -e "../install_variables.txt"){ get_installation_variables(); } @@ -2153,4 +2153,4 @@ sub generate_random_password { map $alphanumeric[rand @alphanumeric], 0..$passwordsize; return $randpassword; -} +} \ No newline at end of file diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh index d9cdc0485..5b8fb24aa 100644 --- a/utils/scripts/linux_installer/install.sh +++ b/utils/scripts/linux_installer/install.sh @@ -205,7 +205,7 @@ make #::: Back to server directory cd $eqemu_server_directory/server -wget https://dl.dropboxusercontent.com/u/50023467/dl/eqemu/eqemu_server.pl +wget https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl #::: Link build files From 4246e4f79b9fb4310c3b8e971c792a9872b67ff8 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 6 Sep 2016 22:44:37 -0500 Subject: [PATCH 365/693] Fix linux installs when in new_server routine [skip ci] --- utils/scripts/eqemu_server.pl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 4e98c1fbd..821736fef 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -196,7 +196,7 @@ sub new_server { } closedir(DIR); - if($file_count > 1 && (!-e "install_variables.txt" || !-e "../install_variables.txt")){ + if($file_count > 1 && (!-e "install_variables.txt" && !-e "../install_variables.txt")){ print "[New Server] ERROR: You must run eqemu_server.pl in an empty directory\n"; <>; exit; @@ -243,7 +243,7 @@ sub new_server { if($mysql_pass == 1){ - if(!-e "install_variables.txt"){ + if((!-e "install_variables.txt" && !-e "../install_variables.txt")){ print "[New Server] Success! We have a database connection\n"; check_for_input("Specify a NEW database name that PEQ will be installed to: "); @@ -783,6 +783,7 @@ sub show_menu_prompt { #::: If we're processing a CLI command, kill the loop if($ARGV[0] ne ""){ + analytics_insertion("cli", trim($input)); $input = ""; $ARGV[0] = ""; exit; From 66c0da85e64a50b810698489209048751ed4c120 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 6 Sep 2016 22:51:29 -0500 Subject: [PATCH 366/693] Take out Linux source build from the install.sh file since eqemu_server.pl is flexibly taking care of it --- utils/scripts/linux_installer/install.sh | 56 +++++------------------- 1 file changed, 11 insertions(+), 45 deletions(-) diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh index 5b8fb24aa..5d43230c5 100644 --- a/utils/scripts/linux_installer/install.sh +++ b/utils/scripts/linux_installer/install.sh @@ -172,60 +172,26 @@ mkdir $eqemu_server_directory/server/logs mkdir $eqemu_server_directory/server/shared mkdir $eqemu_server_directory/server/maps -#::: Pull down needed files for the installer from the Install repo - -cd $eqemu_server_directory/source -git clone https://github.com/EQEmu/Server.git -mkdir $eqemu_server_directory/source/Server/build -cd $eqemu_server_directory/source/Server/build - -echo "Generating CMake build files..." -if [[ "$OS" == "fedora_core" ]]; then - cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -DLUA_INCLUDE_DIR=/usr/include/lua-5.1/ -G "Unix Makefiles" .. -else - cmake -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -G "Unix Makefiles" .. -fi -echo "Building EQEmu Server code. This will take a while." - #::: Grab loginserver dependencies -cd $eqemu_server_directory/source/Server/dependencies -if [[ "$OS" == "Debian" ]]; then - wget http://eqemu.github.io/downloads/ubuntu_LoginServerCrypto_x64.zip - unzip ubuntu_LoginServerCrypto_x64.zip - rm ubuntu_LoginServerCrypto_x64.zip -elif [[ "$OS" == "fedora_core" ]] || [[ "$OS" == "red_hat" ]]; then - wget http://eqemu.github.io/downloads/fedora12_LoginServerCrypto_x64.zip - unzip fedora12_LoginServerCrypto_x64.zip - rm fedora12_LoginServerCrypto_x64.zip -fi -cd $eqemu_server_directory/source/Server/build - -#::: Build -make +# cd $eqemu_server_directory/source/Server/dependencies +# if [[ "$OS" == "Debian" ]]; then +# wget http://eqemu.github.io/downloads/ubuntu_LoginServerCrypto_x64.zip +# unzip ubuntu_LoginServerCrypto_x64.zip +# rm ubuntu_LoginServerCrypto_x64.zip +# elif [[ "$OS" == "fedora_core" ]] || [[ "$OS" == "red_hat" ]]; then +# wget http://eqemu.github.io/downloads/fedora12_LoginServerCrypto_x64.zip +# unzip fedora12_LoginServerCrypto_x64.zip +# rm fedora12_LoginServerCrypto_x64.zip +# fi +# cd $eqemu_server_directory/source/Server/build #::: Back to server directory cd $eqemu_server_directory/server wget https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl -#::: Link build files - -cd $eqemu_server_directory/server - #::: Map lowercase to uppercase to avoid issues ln -s maps Maps -ln -s $eqemu_server_directory/source/Server/build/bin/loginserver -ln -s $eqemu_server_directory/source/Server/build/bin/eqlaunch -ln -s $eqemu_server_directory/source/Server/build/bin/export_client_files -ln -s $eqemu_server_directory/source/Server/build/bin/import_client_files -ln -s $eqemu_server_directory/source/Server/build/bin/libcommon.a -ln -s $eqemu_server_directory/source/Server/build/bin/libluabind.a -ln -s $eqemu_server_directory/source/Server/build/bin/queryserv -ln -s $eqemu_server_directory/source/Server/build/bin/shared_memory -ln -s $eqemu_server_directory/source/Server/build/bin/ucs -ln -s $eqemu_server_directory/source/Server/build/bin/world -ln -s $eqemu_server_directory/source/Server/build/bin/zone - #::: Notes perl $eqemu_server_directory/server/eqemu_server.pl new_server From 5679f45f5bae0adc03927e011536c04d6aed1737 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 7 Sep 2016 12:45:14 -0500 Subject: [PATCH 367/693] Update readme [skip ci] --- README.md | 70 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 154703a75..c9180fa96 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,56 @@ -EQEmu -=== +# EQEmulator Core Server +|Travis CI (Linux)|Appveyor (Windows) | +|:---:|:---:| +|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Windows CI](https://ci.appveyor.com/api/projects/status/d0cvokm7u732v8vl/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server/branch/master) | -[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) -[![Windows CI](https://ci.appveyor.com/api/projects/status/d0cvokm7u732v8vl/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server/branch/master) +*** -Overview ---- +**EQEmulator is a custom completely from-scratch open source server implementation for EverQuest built mostly on C++** + * MySQL/MariaDB is used as the database engine (over 200+ tables) + * Perl and LUA are both supported scripting languages for NPC/Player/Quest oriented events + * Open source database (Project EQ) has content up to expansion GoD (included in server installs) + * Game server environments and databases can be heavily customized to create all new experiences + * Hundreds of Quests/events created and maintained by Project EQ -EQEmu is a custom server implementation for EverQuest +## Server Installs +### > Windows +* [Easy Install](http://wiki.eqemulator.org/p?Akkas_PEQ_Server_Installer&frm=Main#from-scratch-installation-instructions-windows) +* [Advanced Setup](http://wiki.eqemulator.org/p?Complete_Windows-based_Server_Setup_Guide) -Dependencies ---- +### > Debian/Ubuntu -For Windows: http://eqemu.github.io +> wget --no-check-certificate https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh -O install.sh && chmod 755 install.sh && ./install.sh -Login Server dependencies for Windows/Linux/OSX: http://eqemu.github.io +### > CentOS/Fedora -For Debian based distros (adjust to your local flavor): +> curl -O https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh install.sh && chmod 755 install.sh && ./install.sh -- libmysqlclient-dev -- libperl-dev -- liblua5.1-0-dev (5.2 should work as well) -- libboost-dev +## Supported Clients -Further instructions on building the source can be found on the -[wiki](http://wiki.eqemulator.org/i?M=Wiki). +|Titanium Edition|Secrets of Faydwer|Seeds of Destruction|Underfoot|Rain of Fear| +|:---:|:---:|:---:|:---:|:---:| +|||||| -Bug reports ---- - -Please use the [issue tracker](https://github.com/EQEmu/Server/issues) provided by GitHub to send us bug +## Bug Reports +* Please use the [issue tracker](https://github.com/EQEmu/Server/issues) provided by GitHub to send us bug reports or feature requests. +* The [EQEmu Forums](http://www.eqemulator.org/forums/) are also a place to submit and get help with bugs. -The [EQEmu Forums](http://www.eqemulator.org/forums/) also have forums to submit -bugs/get help with bugs. +## Contributions -Contributions ---- - -The preferred way to contribute is to fork the repo and submit a pull request on +* The preferred way to contribute is to fork the repo and submit a pull request on GitHub. If you need help with your changes, you can always post on the forums or -try IRC. You can also post unified diffs (`git diff` should do the trick) on the +try Discord. You can also post unified diffs (`git diff` should do the trick) on the [Server Code Submissions](http://www.eqemulator.org/forums/forumdisplay.php?f=669) forum, although pull requests will be much quicker and easier on all parties. -Contact ---- - - **User IRC Channel**: `#eqemu` on `irc.eqemulator.net` - - **Developer IRC Channel**: `#eqemucoders` on `irc.eqemulator.net` +## Contact + - Discord Channel: https://discord.gg/QHsm7CD + - **User Discord Channel**: `#general` + - **Developer Discord Channel**: `#eqemucoders` + +Resources +--- - [EQEmulator Forums](http://www.eqemulator.org/forums) - [EQEmulator Wiki](http://wiki.eqemulator.org/i?M=Wiki) - From 9a3af63f65d142dfcdd0097349f74b56b94202b3 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 7 Sep 2016 15:10:16 -0500 Subject: [PATCH 368/693] Update readme [skip ci] --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c9180fa96..a56251c19 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,9 @@ * Hundreds of Quests/events created and maintained by Project EQ ## Server Installs +||Windows|Linux| +|:---:|:---:|:---:| +|**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)| ### > Windows * [Easy Install](http://wiki.eqemulator.org/p?Akkas_PEQ_Server_Installer&frm=Main#from-scratch-installation-instructions-windows) * [Advanced Setup](http://wiki.eqemulator.org/p?Complete_Windows-based_Server_Setup_Guide) From 64998a398d992c58a78f2e74f340f130b8a796f0 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Thu, 8 Sep 2016 21:59:15 -0400 Subject: [PATCH 369/693] Added GetAAPercent() to Perl and Lua. --- zone/client.h | 1 + zone/lua_client.cpp | 6 ++++++ zone/lua_client.h | 1 + zone/perl_client.cpp | 27 +++++++++++++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/zone/client.h b/zone/client.h index df7c1fce3..da2188fc7 100644 --- a/zone/client.h +++ b/zone/client.h @@ -796,6 +796,7 @@ public: void SendClearAA(); inline uint32 GetMaxAAXP(void) const { return max_AAXP; } inline uint32 GetAAXP() const { return m_pp.expAA; } + inline uint32 GetAAPercent() const { return m_epp.perAA; } int16 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id); void SetAATitle(const char *Title); void SetTitleSuffix(const char *txt); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 6c2345856..403ca82aa 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -185,6 +185,11 @@ uint32 Lua_Client::GetAAExp() { return self->GetAAXP(); } +uint32 Lua_Client::GetAAPercent() { + Lua_Safe_Call_Int(); + return self->GetAAPercent(); +} + uint32 Lua_Client::GetTotalSecondsPlayed() { Lua_Safe_Call_Int(); return self->GetTotalSecondsPlayed(); @@ -1377,6 +1382,7 @@ luabind::scope lua_register_client() { .def("GetWeight", (int(Lua_Client::*)(void))&Lua_Client::GetWeight) .def("GetEXP", (uint32(Lua_Client::*)(void))&Lua_Client::GetEXP) .def("GetAAExp", (uint32(Lua_Client::*)(void))&Lua_Client::GetAAExp) + .def("GetAAPercent", (uint32(Lua_Client::*)(void))&Lua_Client::GetAAPercent) .def("GetTotalSecondsPlayed", (uint32(Lua_Client::*)(void))&Lua_Client::GetTotalSecondsPlayed) .def("UpdateLDoNPoints", (void(Lua_Client::*)(int,uint32))&Lua_Client::UpdateLDoNPoints) .def("SetDeity", (void(Lua_Client::*)(int))&Lua_Client::SetDeity) diff --git a/zone/lua_client.h b/zone/lua_client.h index 36ea2b8a4..a0a5a9083 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -63,6 +63,7 @@ public: int GetWeight(); uint32 GetEXP(); uint32 GetAAExp(); + uint32 GetAAPercent(); uint32 GetTotalSecondsPlayed(); void UpdateLDoNPoints(int points, uint32 theme); void SetDeity(int v); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 76c085714..de334d5d0 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -871,6 +871,32 @@ XS(XS_Client_GetAAExp) XSRETURN(1); } +XS(XS_Client_GetAAPercent); +XS(XS_Client_GetAAPercent) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Client::GetAAPercent(THIS)"); + { + Client* THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetAAPercent(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + XS(XS_Client_GetTotalSecondsPlayed); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_GetTotalSecondsPlayed) { @@ -6465,6 +6491,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "GetWeight"), XS_Client_GetWeight, file, "$"); newXSproto(strcpy(buf, "GetEXP"), XS_Client_GetEXP, file, "$"); newXSproto(strcpy(buf, "GetAAExp"), XS_Client_GetAAExp, file, "$"); + newXSproto(strcpy(buf, "GetAAPercent"), XS_Client_GetAAPercent, file, "$"); newXSproto(strcpy(buf, "GetTotalSecondsPlayed"), XS_Client_GetTotalSecondsPlayed, file, "$"); newXSproto(strcpy(buf, "UpdateLDoNPoints"), XS_Client_UpdateLDoNPoints, file, "$$$"); newXSproto(strcpy(buf, "SetDeity"), XS_Client_SetDeity, file, "$$"); From 4816c1fc9a1a24fa6008faf716f35ad771e73212 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Fri, 9 Sep 2016 23:59:23 -0400 Subject: [PATCH 370/693] Added support for server-wide marquee messages. --- common/servertalk.h | 10 ++++++++++ world/zoneserver.cpp | 1 + zone/embparser_api.cpp | 21 +++++++++++++++++++++ zone/lua_general.cpp | 5 +++++ zone/questmgr.cpp | 14 ++++++++++++++ zone/questmgr.h | 1 + zone/worldserver.cpp | 13 +++++++++++++ 7 files changed, 65 insertions(+) diff --git a/common/servertalk.h b/common/servertalk.h index e476d023d..b0197985f 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -193,6 +193,7 @@ #define ServerOP_QSSendQuery 0x5016 #define ServerOP_CZSignalNPC 0x5017 #define ServerOP_CZSetEntityVariableByNPCTypeID 0x5018 +#define ServerOP_WWMarquee 0x5019 /* Query Serv Generic Packet Flag/Type Enumeration */ enum { QSG_LFGuild = 0 }; @@ -1254,6 +1255,15 @@ struct CZMessagePlayer_Struct { char Message[512]; }; +struct WWMarquee_Struct { + uint32 Type; + uint32 Priority; + uint32 FadeIn; + uint32 FadeOut; + uint32 Duration; + char Message[512]; +}; + struct CZSetEntVarByNPCTypeID_Struct { uint32 npctype_id; char id[256]; diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index abe6e0e18..9a9572f97 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1312,6 +1312,7 @@ bool ZoneServer::Process() { case ServerOP_CZSignalNPC: case ServerOP_CZSetEntityVariableByNPCTypeID: case ServerOP_CZSignalClient: + case ServerOP_WWMarquee: case ServerOP_DepopAllPlayersCorpses: case ServerOP_DepopPlayerCorpse: case ServerOP_ReloadTitles: diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index b9b28f0a6..adaaf3325 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3616,6 +3616,26 @@ XS(XS__crosszonesignalnpcbynpctypeid) XSRETURN_EMPTY; } +XS(XS__worldwidemarquee); +XS(XS__worldwidemarquee) +{ + dXSARGS; + if (items != 6) + Perl_croak(aTHX_ "Usage: worldwidemarquee(type, priority, fadein, fadeout, duration, message)"); + + if (items == 6) { + uint32 type = (uint32)SvIV(ST(0)); + uint32 priority = (uint32)SvIV(ST(1)); + uint32 fadein = (uint32)SvIV(ST(2)); + uint32 fadeout = (uint32)SvIV(ST(3)); + uint32 duration = (uint32)SvIV(ST(4)); + char* message = (char *)SvPV_nolen(ST(5)); + quest_manager.WorldWideMarquee(type, priority, fadein, fadeout, duration, message); + } + + XSRETURN_EMPTY; +} + XS(XS__debug); XS(XS__debug) { @@ -3749,6 +3769,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file); newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file); newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file); + newXS(strcpy(buf, "worldwidemarquee"), XS__worldwidemarquee, file); newXS(strcpy(buf, "debug"), XS__debug, file); newXS(strcpy(buf, "delglobal"), XS__delglobal, file); newXS(strcpy(buf, "depop"), XS__depop, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index d47420fe1..9f413128b 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -892,6 +892,10 @@ void lua_cross_zone_message_player_by_name(uint32 type, const char *player, cons quest_manager.CrossZoneMessagePlayerByName(type, player, message); } +void lua_world_wide_marquee(uint32 type, uint32 priority, uint32 fadein, uint32 fadeout, uint32 duration, const char *message) { + quest_manager.WorldWideMarquee(type, priority, fadein, fadeout, duration, message); +} + luabind::adl::object lua_get_qglobals(lua_State *L, Lua_NPC npc, Lua_Client client) { luabind::adl::object ret = luabind::newtable(L); @@ -1613,6 +1617,7 @@ luabind::scope lua_register_general() { luabind::def("cross_zone_signal_client_by_char_id", &lua_cross_zone_signal_client_by_char_id), luabind::def("cross_zone_signal_client_by_name", &lua_cross_zone_signal_client_by_name), luabind::def("cross_zone_message_player_by_name", &lua_cross_zone_message_player_by_name), + luabind::def("world_wide_marquee", &lua_world_wide_marquee), luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC,Lua_Client))&lua_get_qglobals), luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_Client))&lua_get_qglobals), luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC))&lua_get_qglobals), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 78fc2b206..5803e547c 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -3017,6 +3017,20 @@ void QuestManager::CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, cons safe_delete(pack); } +void QuestManager::WorldWideMarquee(uint32 Type, uint32 Priority, uint32 FadeIn, uint32 FadeOut, uint32 Duration, const char *Message) { + uint32 message_len = strlen(Message) + 1; + auto pack = new ServerPacket(ServerOP_WWMarquee, sizeof(WWMarquee_Struct) + message_len); + WWMarquee_Struct* WWMS = (WWMarquee_Struct*) pack->pBuffer; + WWMS->Type = Type; + WWMS->Priority = Priority; + WWMS->FadeIn = FadeIn; + WWMS->FadeOut = FadeOut; + WWMS->Duration = Duration; + strn0cpy(WWMS->Message, Message, 512); + worldserver.SendPacket(pack); + safe_delete(pack); +} + bool QuestManager::EnableRecipe(uint32 recipe_id) { bool success = false; diff --git a/zone/questmgr.h b/zone/questmgr.h index 612c7815f..10c82c1ee 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -252,6 +252,7 @@ public: void CrossZoneSignalPlayerByName(const char *CharName, uint32 data); void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var); void CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message); + void WorldWideMarquee(uint32 Type, uint32 Priority, uint32 FadeIn, uint32 FadeOut, uint32 Duration, const char *Message); bool EnableRecipe(uint32 recipe_id); bool DisableRecipe(uint32 recipe_id); void ClearNPCTypeCache(int npctype_id); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 0f00ed0c5..60a4e7385 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1838,6 +1838,19 @@ void WorldServer::Process() { } break; } + case ServerOP_WWMarquee: + { + WWMarquee_Struct* WWMS = (WWMarquee_Struct*) pack->pBuffer; + std::list client_list; + entity_list.GetClientList(client_list); + auto iter = client_list.begin(); + std::string Message = WWMS->Message; + while (iter != client_list.end()) { + Client* client = (*iter); + client->SendMarqueeMessage(WWMS->Type, WWMS->Priority, WWMS->FadeIn, WWMS->FadeOut, WWMS->Duration, Message); + iter++; + } + } case ServerOP_ReloadWorld: { ReloadWorld_Struct* RW = (ReloadWorld_Struct*) pack->pBuffer; From 56d355935b99de7039c3c21021d11b9713305b6a Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 10 Sep 2016 14:21:19 -0400 Subject: [PATCH 371/693] Fix task experience by level % to take into account hell level rule. --- zone/exp.cpp | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/zone/exp.cpp b/zone/exp.cpp index 93c689b7c..63989a4e9 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -705,10 +705,33 @@ uint32 Client::GetEXPForLevel(uint16 check_level) return finalxp; } -void Client::AddLevelBasedExp(uint8 exp_percentage, uint8 max_level) { - if (exp_percentage > 100) { exp_percentage = 100; } - if (!max_level || GetLevel() < max_level) { max_level = GetLevel(); } - uint32 newexp = GetEXP() + ((GetEXPForLevel(max_level + 1) - GetEXPForLevel(max_level)) * exp_percentage / 100); +void Client::AddLevelBasedExp(uint8 exp_percentage, uint8 max_level) +{ + uint32 award; + uint32 xp_for_level; + + if (exp_percentage > 100) + { + exp_percentage = 100; + } + + if (!max_level || GetLevel() < max_level) + { + max_level = GetLevel(); + } + + xp_for_level = GetEXPForLevel(max_level + 1) - GetEXPForLevel(max_level); + award = xp_for_level * exp_percentage / 100; + + if(RuleB(Zone, LevelBasedEXPMods)) + { + if(zone->level_exp_mod[GetLevel()].ExpMod) + { + award *= zone->level_exp_mod[GetLevel()].ExpMod; + } + } + + uint32 newexp = GetEXP() + award; SetEXP(newexp, GetAAXP()); } From 0503e85fd3c55e36d0f591e6fd9941740535a905 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 10 Sep 2016 14:26:47 -0400 Subject: [PATCH 372/693] Updated changelog --- changelog.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/changelog.txt b/changelog.txt index b2d7c7b05..1cfdce055 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/10/2016 == +noudess: Task system experience based on a % of a level did not take into +account the hell levels rule. Now it does. + == 09/03/2016 == Uleat: Changed 'Bind Wound' behavior to match the best references that I could find for post-2004 era. Note: If you wish to retain the old method, source in the optional '2016_09_03_old_bind_wound_rule.sql' script file. From f6d721dd72f8e0a1a25f2a4a7ce05e44158993e2 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sun, 11 Sep 2016 19:19:09 -0400 Subject: [PATCH 373/693] #summon will now work when you are in an instance. --- common/database.cpp | 12 ++++++++++++ common/database.h | 2 ++ zone/command.cpp | 1 + zone/worldserver.cpp | 13 ++++++++++++- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/common/database.cpp b/common/database.cpp index a4c862ae0..41220b4d9 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2147,4 +2147,16 @@ int Database::GetIPExemption(std::string account_ip) { } return RuleI(World, MaxClientsPerIP); +} + +int Database::GetInstanceID(uint32 char_id, uint32 zone_id) { + std::string query = StringFormat("SELECT instance_list.id FROM instance_list INNER JOIN instance_list_player ON instance_list.id = instance_list_player.id WHERE instance_list.zone = '%i' AND instance_list_player.charid = '%i'", zone_id, char_id); + auto results = QueryDatabase(query); + + if (results.Success() && results.RowCount() > 0) { + auto row = results.begin(); + return atoi(row[0]);; + } + + return 0; } \ No newline at end of file diff --git a/common/database.h b/common/database.h index 547e741e5..69ad0c576 100644 --- a/common/database.h +++ b/common/database.h @@ -189,6 +189,8 @@ public: int GetIPExemption(std::string account_ip); + int GetInstanceID(uint32 char_id, uint32 zone_id); + /* Groups */ diff --git a/zone/command.cpp b/zone/command.cpp index 4c60ad65b..86f745710 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -1007,6 +1007,7 @@ void command_summon(Client *c, const Seperator *sep) szp->x_pos = c->GetX(); // May need to add a factor of 8 in here.. szp->y_pos = c->GetY(); szp->z_pos = c->GetZ(); + szp->instance_id = zone->GetInstanceID(); worldserver.SendPacket(pack); safe_delete(pack); } diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 60a4e7385..28f3c5ab8 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -543,7 +543,18 @@ void WorldServer::Process() { else { SendEmoteMessage(szp->adminname, 0, 0, "Summoning %s to %s %1.1f, %1.1f, %1.1f", szp->name, szp->zone, szp->x_pos, szp->y_pos, szp->z_pos); } - client->MovePC(database.GetZoneID(szp->zone), szp->instance_id, szp->x_pos, szp->y_pos, szp->z_pos, client->GetHeading(), szp->ignorerestrictions, GMSummon); + if (!szp->instance_id) { + client->MovePC(database.GetZoneID(szp->zone), szp->instance_id, szp->x_pos, szp->y_pos, szp->z_pos, client->GetHeading(), szp->ignorerestrictions, GMSummon); + } else { + if (database.GetInstanceID(client->CharacterID(), database.GetZoneID(szp->zone)) == 0) { + client->AssignToInstance(szp->instance_id); + client->MovePC(database.GetZoneID(szp->zone), szp->instance_id, szp->x_pos, szp->y_pos, szp->z_pos, client->GetHeading(), szp->ignorerestrictions, GMSummon); + } else { + client->RemoveFromInstance(database.GetInstanceID(client->CharacterID(), database.GetZoneID(szp->zone))); + client->AssignToInstance(szp->instance_id); + client->MovePC(database.GetZoneID(szp->zone), szp->instance_id, szp->x_pos, szp->y_pos, szp->z_pos, client->GetHeading(), szp->ignorerestrictions, GMSummon); + } + } } break; } From 745510ea75ddf815f2f6befc6f176de931077679 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 12 Sep 2016 01:31:35 -0500 Subject: [PATCH 374/693] Massive overhaul of the update system and EQEmu Server management utility framework (known as eqemu_update.pl) now known as eqemu_server.pl - eqemu_server.pl is now a general EQEmu Server management utiltiy framework that can be used to extend to many purposes. It's main purpose is to simplify server management - eqemu_server.pl changes: - Menu has been completely changed, instead of a number based (enter number and hit enter) you now type commands within the menu (Ex: 'database') - Handles last mile installation for Windows Servers (See Github Readme) - Handles last mile installation for Linux Servers (See Github Readme) - Ubuntu - Debian - Fedora - CentOS - Now checks for Internet connection before performing web requests - Database: - Regular schema updates now happen automatically, if new binaries present updated database schema changes, script will backup first, auto update database, and continue world bootup - Regular bots database schema changes now happen automatically similarily to the above - Database checks can also be ran manually via the script menu - CLI Arguments - Arguments passed to eqemu_server.pl can execute the same name-based operations that are present in the interactive menu - Example: "perl eqemu_server.pl opcodes" will download opcodes - Example: "perl eqemu_server.pl backup_player_tables" will backup and export player tables - Bots - Bots can now be automatically setup in Linux or Windows via the 'setup_bots' command - Windows will auto download binaries and install, along with installing bots db schema - Linxu will auto compile binaries and install, along with installings bots db schema - Utility scripts - Linux now has the following utility scripts for download, available via menu 'utility_scripts' and via Linux default install: - server_launcher.pl - server_start_dev.sh - server_start.sh - server_status.sh - server_stop.sh - Usage analytics - eqemu_server.pl now collects usage analytics, this is very helpful for our developers - Example: We can see how many installs have been performed: https://github.com/EQEmu/Server#server-installs - This helps us see how often certain utilities are used as well - Console Messages - All script messages have been prefixed with a bracket action Ex: [Update] [Database] [Info] to be more consistent with our log conventions - 'New Server' Utility - Running 'new_server' from the main menu or 'perl eqemu_server.pl new_server' while in a completely new folder with just the script present, will allow a server operator to initiate a full clean PEQ install in that folder. Pulling down all assets and installing a PEQ database with the name the server operator gives the prompts in the script --- changelog.txt | 342 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 208 insertions(+), 134 deletions(-) diff --git a/changelog.txt b/changelog.txt index b2d7c7b05..ce31ffabb 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,79 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/12/2016 == +Akkadius: Massive overhaul of the update system and EQEmu Server management utility framework + (known as eqemu_update.pl) now known as eqemu_server.pl + - eqemu_server.pl is now a general EQEmu Server management utiltiy framework that can be used + to extend to many purposes. It's main purpose is to simplify server management + - eqemu_server.pl changes: + - Menu has been completely changed, instead of a number based (enter number and hit enter) + you now type commands within the menu (Ex: 'database') + - Handles last mile installation for Windows Servers (See Github Readme) + - Handles last mile installation for Linux Servers (See Github Readme) + - Ubuntu + - Debian + - Fedora + - CentOS + - Now checks for Internet connection before performing web requests + - Database: + - Regular schema updates now happen automatically, if new binaries present updated + database schema changes, script will backup first, auto update database, and continue + world bootup + - Regular bots database schema changes now happen automatically similarily to the above + - Database checks can also be ran manually via the script menu + - CLI Arguments + - Arguments passed to eqemu_server.pl can execute the same name-based operations that + are present in the interactive menu + - Example: "perl eqemu_server.pl opcodes" will download opcodes + - Example: "perl eqemu_server.pl backup_player_tables" will backup and export player tables + - Bots + - Bots can now be automatically setup in Linux or Windows via the 'setup_bots' command + - Windows will auto download binaries and install, along with installing bots db schema + - Linxu will auto compile binaries and install, along with installings bots db schema + - Utility scripts + - Linux now has the following utility scripts for download, available via menu 'utility_scripts' + and via Linux default install: + - server_launcher.pl + - server_start_dev.sh + - server_start.sh + - server_status.sh + - server_stop.sh + - Usage analytics + - eqemu_server.pl now collects usage analytics, this is very helpful for our developers + - Example: We can see how many installs have been performed: + https://github.com/EQEmu/Server#server-installs + - This helps us see how often certain utilities are used as well + - Console Messages + - All script messages have been prefixed with a bracket action Ex: [Update] [Database] [Info] + to be more consistent with our log conventions + - 'New Server' Utility + - Running 'new_server' from the main menu or 'perl eqemu_server.pl new_server' while in + a completely new folder with just the script present, will allow a server operator + to initiate a full clean PEQ install in that folder. Pulling down all assets and + installing a PEQ database with the name the server operator gives the prompts in the + script + + +== 09/04/2016 (Changes over past few months) == +Akkadius: Fixed an issue where clients would crash with health marquee's +Akkadius: Fixed issues with NPC's "ghosting" when they path +Akkadius: Overhauled worldserver logging +Akkadius: Pets now don't actually spawn until the player has fully entered the zone (Live-like) +demonstar/KLS: Adjusted some background workings on how spell buff tics are synced with the client +Uleat: Optimizations to map loading and zone times +Uleat/Akkadius: Fixed bandolier exploit where you could equip a 2H and Shield +mackal: Re-worked spell re-use timer logic +mackal: Source optimizations all over, crash fixes +mackal: Fixed some issues with illusions on zoning +mackal: Fixed some client DOT stacking bugs +mackal: Invis will now break on AA spell casts and item cast +mackal: Changed how Loot response code works +mackal: Implemented 3 additional spell gems with (Mnemonic Retention) +mackal: Instant spells now have instrument mods +mackal: Rate limit character saves +mackal: Made it so items no longer do TGB (Live-like) Rule implemented to disable +mackal: Set pet buffs limit to 30 + == 09/03/2016 == Uleat: Changed 'Bind Wound' behavior to match the best references that I could find for post-2004 era. Note: If you wish to retain the old method, source in the optional '2016_09_03_old_bind_wound_rule.sql' script file. @@ -412,10 +486,10 @@ mackal: Reworked the activated avoidace skills (riposte, dodge, etc) based on de Also riposte immunity from the increase riposte chance spell effect. == 7/2/2015 == -KLS/Demonstar55: AA system has been rewritten fixing a ton of bugs and extending functionality while making it easier to create new AA points. -KLS/Demonstar55: New tables are needed and so older data will need to be migrated to the new system. -KLS/Demonstar55: The SQL saves the old aa points spent/avail/character_alt_abilities data if any server ops want to do something different than PEQ did with it. -KLS/Demonstar55: Will try to get a wiki entry written up next week some time explaining the system but it's really not hard to follow the db tables in the meantime. +KLS/mackal: AA system has been rewritten fixing a ton of bugs and extending functionality while making it easier to create new AA points. +KLS/mackal: New tables are needed and so older data will need to be migrated to the new system. +KLS/mackal: The SQL saves the old aa points spent/avail/character_alt_abilities data if any server ops want to do something different than PEQ did with it. +KLS/mackal: Will try to get a wiki entry written up next week some time explaining the system but it's really not hard to follow the db tables in the meantime. == 7/1/2015 == Akkadius: Fix an issue where emote messages would overflow the buffer of 256 by increasing the size and changing some of the initialization @@ -445,7 +519,7 @@ Akkadius: Added DB ver 9082 with update to add npc_types texture columns if tabl Uleat: Added null-term declaration for character names in ENCODE(OP_CharInfo) - where appropriate == 05/20/2015 == -demonstar55: Bard instrument mods should be more consistent with live. Zoning will keep instrument mod for long duration buffs (selo's) +mackal: Bard instrument mods should be more consistent with live. Zoning will keep instrument mod for long duration buffs (selo's) Still need to have procs/doom effects to inherit the instrument mods from their source buff/whatever == 05/18/2015 == @@ -455,7 +529,7 @@ KLS: Changed how fishing locates water to hopefully be a bit more accurate at th Uleat: Added check to EntityList::CheckSpawnQueue() to bypass dereference if returned iterator is npc_list.end() - should fix the debug assertion failure crash == 04/30/2015 == -demonstar55: Implement mob and client melee push +mackal: Implement mob and client melee push You can set Combat:MeleePush to false to turn off or change Combat:MeleePushChance to increase the chance an NPC can be pushed PCs are always pushed, need to do more testing to verify. @@ -509,7 +583,7 @@ Uleat: Fix for RoF+ clients showing active 'Return Home' button when action is n Noudess: Starting erudites that were supposed to start in paineel were landing in erudin on Titanium. Fixed to be paineel. == 02/20/2015 == -demonstar55: Implement claims for RoF/RoF2 (should no longer crash the client!) +mackal: Implement claims for RoF/RoF2 (should no longer crash the client!) - fixed bugs related to claims for the rest of the clients (woo infinite loops) == 02/18/2015 == @@ -528,7 +602,7 @@ Notes: == 02/16/2015 == Trevius: (RoF2) Bazaar Trading (Buying/Selling) is now fully functional. Bazaar (/bazaar) search is not yet functional. -demonstar55: (RoF2) Send the bard focus effects, note custom servers will need to fix their items, server side we still use the old system, but RoF2 wasn't showing anything with not sending focus, so send them +mackal: (RoF2) Send the bard focus effects, note custom servers will need to fix their items, server side we still use the old system, but RoF2 wasn't showing anything with not sending focus, so send them == 02/14/2015 == Trevius: (RoF2) Bazaar is now partially functional. RoF2 clients can start/end trader mode and other clients can purchase from them. No other functionality yet. @@ -578,7 +652,7 @@ Akkadius: Implement Packet logs with dumps See: http://wiki.eqemulator.org/p?Logging_System_Overhaul#packet-logging-levels == 02/01/2015 == -demonstar55: Add quest debugging to lua +mackal: Add quest debugging to lua eq.debug("Test debug level implicit 1") eq.debug("Test debug level explicit 1", 1) eq.debug("Test debug level explicit 2", 2) @@ -771,7 +845,7 @@ Trevius: Finished lining up the RoF2 Player Profile Struct. Zone times are now Trevius: Fixed zoning after death for RoF2. == 12/17/2014 == -demonstar55: Use vectors for route stuff, should be more CPU cache friendly so faster +mackal: Use vectors for route stuff, should be more CPU cache friendly so faster Secrets: EQStream changes as recommended by a community member in private. == 12/15/2014 == @@ -781,7 +855,7 @@ Trevius: Player Corpses now saved attuned settings for Items. Required SQL: utils/sql/git/required/2014_12_15_multiple_table_updates.sql == 12/13/2014 == -demonstar55: Fix guild rank spam on zone (needed to be in OP_PP). +mackal: Fix guild rank spam on zone (needed to be in OP_PP). Trevius: (RoF+) Implemented Armor Ornamentation using Hero's Forge Armor Models. To use, create an ornamentation augment and set the herosforgemodel field in the items table. Trevius: (RoF+) Added command #heromodel (#hm for short) - Usage: #heromodel [hero forge model] [ [slot] ] (example: #heromodel 63) @@ -789,11 +863,11 @@ Be sure to run this or there will be item loss: Required SQL: utils/sql/git/required/2014_12_13_inventory_table_update.sql == 12/12/2014 == -demonstar55: Add special attack 42, Ignore Root Aggro Rules. This allows you to root a mob and have them still use the normal aggro rules (so they will attack the one with most hate, not closest) +mackal: Add special attack 42, Ignore Root Aggro Rules. This allows you to root a mob and have them still use the normal aggro rules (so they will attack the one with most hate, not closest) == 12/09/2014 == Trevius: (RoF+) Implemented Hero's Forge Armor Models for Items. To use, set herosforgemodel field in the item table to a model number such as 63 (for example). -demonstar55: SoF+ swarm pets will no longer be F8able (without a hack!) +mackal: SoF+ swarm pets will no longer be F8able (without a hack!) == 12/08/2014 == Secrets: Added a feature that allows an EQ client to log in directly to World without having to enter the LoginServer, provided the 'password' field is set in WorldServer. @@ -839,10 +913,10 @@ Trevius: Mercenaries now Dismiss, Suspend, Unsuspend, and Die correctly. Trevius: Mercenaries can now zone once again. == 11/17/2014 == -demonstar55: Correct OP_AugmentInfo reply. This fixes RoF display issue with Adventurer's Stone. Still issues with UF/SoF/SoD though. +mackal: Correct OP_AugmentInfo reply. This fixes RoF display issue with Adventurer's Stone. Still issues with UF/SoF/SoD though. == 11/16/2014 == -demonstar55: fix size issue with ControlBoat_Struct and exploit fix in OP_BoardBoat +mackal: fix size issue with ControlBoat_Struct and exploit fix in OP_BoardBoat Akkadius: Implemented Automatic Database update and versioning system Akkadius: Created database revision define, this is located in version.h in common #define CURRENT_BINARY_DATABASE_VERSION 9057 @@ -919,12 +993,12 @@ Optional SQL: utils/sql/git/optional/2014_11_15_SwarmPetTargetLock.sql == 11/14/2014 == Secrets: Identified object size and solidtype as flags. Exported them as functions to Perl. -demonstar55: Don't use the hack for charms that doesn't work on RoF -demonstar55: UF too -demonstar55: Tit -demonstar55: SoF -demonstar55: SoD -demonstar55: 62 (untested) +mackal: Don't use the hack for charms that doesn't work on RoF +mackal: UF too +mackal: Tit +mackal: SoF +mackal: SoD +mackal: 62 (untested) == 11/13/2014 == Kayen: Implemented target type (44) 'Beams' (which projects an AE infront of caster with a specified length and width). @@ -950,7 +1024,7 @@ JJ: Implement new Live-like faction adjustment message using rule Client:UseLive Optional SQL: utils/sql/git/optional/2014_11_09_LiveFactionMessages.sql == 11/06/2014 == -demonstar55: Tracking default sort will now be correct order +mackal: Tracking default sort will now be correct order Trevius: Fixed dynamic merchant list loading. Allows any merchant to be used in any zone. == 11/03/2014 == @@ -974,17 +1048,17 @@ Uleat: Added Client::InterrogateInventory(). Can be invoked by #interrogateinv a Uleat: Fix for stacking items in a world object..added a new command option: #peekinv world - will show world container contents, if one is in use by target. == 10/20/2014 == -demonstar55: Inspect Buffs rank 1 will now show NPC buffs in target window (SoD+) +mackal: Inspect Buffs rank 1 will now show NPC buffs in target window (SoD+) == 10/19/2014 == Uleat: Updated command #peekinv to display item links properly in RoF clients -demonstar55: Group Mentoring in raids -demonstar55: Inspect Buffs (text only version) works in raid groups -demonstar55: Make use of the Inspect Buffs op/packet. 62 SOL until someone finds its op +mackal: Group Mentoring in raids +mackal: Inspect Buffs (text only version) works in raid groups +mackal: Make use of the Inspect Buffs op/packet. 62 SOL until someone finds its op == 10/18/2014== -demonstar55: Implement group mentor, sharing leadership exp (SoF+ only) -demonstar55: Add gaining of group leadership while in raids +mackal: Implement group mentor, sharing leadership exp (SoF+ only) +mackal: Add gaining of group leadership while in raids == 10/16/2014 == Uleat: Fixed the auto-conversion view naming error and renamed the views in the script files. Added a fix sql for databases that auto-converted. @@ -997,7 +1071,7 @@ Notes: I modifed the behavior of both load and drop bots to fail on the first op a few altered tables back to their original state - as of the date in the file. == 10/13/2014 == -demonstar55: Partially implement leadership and raids +mackal: 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) @@ -1006,7 +1080,7 @@ demonstar55: Partially implement leadership and raids Akkadius: Fix for LDON Character Stat load == 10/11/2014 == -demonstar55: Implement Raid MOTD for UF +mackal: Implement Raid MOTD for UF Don't forget 2014_10_11_RaidMOTD.sql! == 10/09/2014 == @@ -1019,7 +1093,7 @@ previously and/or manually changed code, or just have a need for it to re-run, c ** This will only work if you haven't deleted your `character_old` table ** == 10/07/2014 == -demonstar55: Identified tutorial flag in all charcreate packets, reworked logic to correctly set homes binds +mackal: Identified tutorial flag in all charcreate packets, reworked logic to correctly set homes binds == 10/05/2014 == Uleat: Added Server<->Corpse slot translators needed for re-enumeration (inactive until phased in) @@ -1037,13 +1111,13 @@ Uleat: First round of Ti/6.2 translators added - needed for re-enumeration == 10/01/2014 == Kayen: Exported to PERL $client->SendColoredText(color, msg) -demonstar55: Exported SendColoredText to lua +mackal: Exported SendColoredText to lua == 09/30/2014 == Uleat: Implemented click-casting from bag slots for clients that natively support it (RoF) == 09/28/2014 == -demonstar55: Add support for post June 18, 2014 Hundred Hands Effect spells (they changed the formula and stuff) +mackal: Add support for post June 18, 2014 Hundred Hands Effect spells (they changed the formula and stuff) set Spells:Jun182014HundredHandsRevamp to true if you're using a spell file from June 18, 2014+ == 09/27/2014 == @@ -1052,15 +1126,15 @@ Note: identifier is the stat field in spells_new, slot is used for certain effec Example $mob->GetSpellStat(121, "range"); //Returns spell range Example $mob->GetSpellStat(121, "effectid", 1); //Returns the the value of effectid1 This will allow you to pull almost all the data for any spell in quest files. -demonstar55: Move the client's SetAttackTimer to the end of Client::CalcBonuses to keep the haste in sync -demonstar55: Correct haste/slow "stacking" rules -demonstar55: Correct SE_AttackSpeed4 to respect unslowable -demonstar55: Make the haste be between 1-225 like the client (<100 = slow, >100 = haste) to ... -demonstar55: Correct Hundred Hands effect and use formula provided by devs +mackal: Move the client's SetAttackTimer to the end of Client::CalcBonuses to keep the haste in sync +mackal: Correct haste/slow "stacking" rules +mackal: Correct SE_AttackSpeed4 to respect unslowable +mackal: Make the haste be between 1-225 like the client (<100 = slow, >100 = haste) to ... +mackal: Correct Hundred Hands effect and use formula provided by devs == 09/24/2014 == Uleat: Re-ordered server opcodes and handlers to give them some predictability of location (I need this for the inventory re-enumeration.) -demonstar55: Added helper function bool EQEmu::IsTradeskill(uint32 skill) +mackal: Added helper function bool EQEmu::IsTradeskill(uint32 skill) == 09/23/2014 == Kayen: Spell recourse effects will now be applied AFTER the base spells effects have been applied (consistent with live). @@ -1169,46 +1243,46 @@ Akkadius: Player Profile Blob to Database Conversion ORDER BY DATA DESC; == 09/20/2014 == -demonstar55: Fix crash in SendEnterWorld on illegally long names -demonstar55: The client only lets you enter 15 characters for your name (UF at least) -demonstar55: Add rule Spells:SHDProcIDOffByOne for pre-UF spell file, set to true, UF+ set to false +mackal: Fix crash in SendEnterWorld on illegally long names +mackal: The client only lets you enter 15 characters for your name (UF at least) +mackal: Add rule Spells:SHDProcIDOffByOne for pre-UF spell file, set to true, UF+ set to false KLS: #suspend and #ban now have required messages to record the reason for the ban/suspension. == 09/19/2014 == -demonstar55: Added Client::Tell_StringID (used in tell queue messages) -demonstar55: Tell queues (and offline) messages now show correctly -demonstar55: Fix starting with capital check +mackal: Added Client::Tell_StringID (used in tell queue messages) +mackal: Tell queues (and offline) messages now show correctly +mackal: Fix starting with capital check == 09/18/2014== -demonstar55: Implement tell queues +mackal: Implement tell queues Currently set to a limit of 20 by default (World:TellQueueSize) I was unable to hit the limit on live though (100+) The required SQL nukes the old tell queue table, which may or may not be in your DB Optional SQL adds the rule to the DB to allow easy of change Note: this does not play well with multiple sessions with the same name on (crash and relog and have multiple sessions) but normal tells don't play well either == 09/16/2014 == -demonstar55: Implement spell formula 137 (BER AA Desperation) +mackal: Implement spell formula 137 (BER AA Desperation) Uleat (NateDog): Fix for LoadBuffs() crash when a spell with a non-persistent Illusion effect was loaded. -demonstar55: Fix some effect calcs + implement more (derived from the client) +mackal: Fix some effect calcs + implement more (derived from the client) == 09/15/2014 == Kayen: Nimbus effects will now be reapplied after zoning and will be removed when associated buff fades. == 09/13/2014 == -demonstar55: Fix rogues not having Thieves' Cant +mackal: Fix rogues not having Thieves' Cant == 09/09/2014 == -demonstar55: Incrase Mob kick/bash timer by 3 +mackal: Incrase Mob kick/bash timer by 3 see: http://www.eqemulator.org/forums/showthread.php?t=38734 -demonstar55: Fix slow effect on NPC special attack reuse timers +mackal: Fix slow effect on NPC special attack reuse timers see: http://www.eqemulator.org/forums/showthread.php?t=38734 -demonstar55: Slow fixes to bots! -demonstar55: Revamped how NPC attack rate is set +mackal: Slow fixes to bots! +mackal: Revamped how NPC attack rate is set SQL: 2014_09_09_attack_delay.sql -demonstar55: Added attackdelay to #npcedit +mackal: Added attackdelay to #npcedit == 09/08/2014 == -demonstar55: Fix slow calc +mackal: Fix slow calc see: http://www.eqemulator.org/forums/showthread.php?t=38734 == 09/07/2014 == @@ -1219,18 +1293,18 @@ Uleat: Tweaked 'Smart' trading code to return main slots before sub slots in sta == 09/05/2014 == Uleat: Fix for cursor item loss when zoning. (Thanks to the other devs who traced and fixed the 'macro' issue!) -demonstar55: Fix size getting nuked with lua's SendIllusionPacket +mackal: Fix size getting nuked with lua's SendIllusionPacket == 09/03/2014 == Secrets: Identified the routines needed to augment items in RoF. Currently, only Insert and Remove are supported. Swap and Destroy do not work due to missing functions related to the cursor. -demonstar55: Added work around command to show numhits on your buffs (#shownumhits) +mackal: Added work around command to show numhits on your buffs (#shownumhits) Uleat: Fix for timer issue introduced by Zone::ShutDown() fix. == 09/02/2014 == Secrets: Identified OP_GuildPromote for RoF clients. Secrets: Fixed promotion, demotion, transferring a leader and displaying of client ranks in the Rain of Fear client. The rain of fear client, as such, will only have 3 ranks like the other clients, but supports a theoretical 8 ranks later. Secrets/Akkadius: Fixed an issue involving character name lookup in the new DB code. -demonstar55: crash fix checking DivineAura in hate_list.cpp +mackal: crash fix checking DivineAura in hate_list.cpp Secrets: Reverted some code that got in the main branch that shouldn't have gotten there. Uleat: Changed #loc to report the same precision as /loc for Cartesians @@ -1241,7 +1315,7 @@ KLS: Fixed a few quest related inconsistencies. KLS: Added Lua EntityList::ChannelMessage(from, type, msg, language) == 08/30/2014 == -demonstar55: (noudess) Merchants should be more descriptive of why they don't sell to you +mackal: (noudess) Merchants should be more descriptive of why they don't sell to you == 08/26/2014 == Uleat: Implemented 'Smart' Player Trade transfers. Trades are processed by containers, stackables and then all remaining. QueryServ logs have been updated to match these transactions. @@ -1619,7 +1693,7 @@ Optional SQL: utils/sql/git/optional/2014_04_03_SpellProjectileRules.sql Note: The rules in this SQL are for setting the item id for the graphic used by the projectile on different clients. == 04/01/2014 == -demonstar55: Implemented ability for a merchant to open and close shop. +mackal: Implemented ability for a merchant to open and close shop. Lua quest functions: e.self:MerchantOpenShop() and e.self:MerchantCloseShop() GM Commands: #merchant_open_shop (short: #open_shop) and #merchant_close_shop (short: #close_shop) default to status 100, just in case you need to force the merchants status @@ -1685,7 +1759,7 @@ Kayen: Revision to lull/harmony/pacification code to be consistent with live bas which if 'resisted' will cause the caster to gain aggro. == 03/05/2014 == -demonstar55: Corrected rogue's evade to be single target +mackal: Corrected rogue's evade to be single target sorvani: fixed crash issue 119 == 03/04/2014 == @@ -1700,7 +1774,7 @@ Kayen: Revision to root code to be consistent with live based on extensive perso Optional SQL: utils/sql/git/optional/2014_03_04_RootRule.sql == 03/03/2014 == -demonstar55: Implemented deadly strikes and gave rogues higher innate throwing crit chance +mackal: Implemented deadly strikes and gave rogues higher innate throwing crit chance New rules: Combat:RogueCritThrowingChance, Combat:RogueDeadlyStrikeChance, Combat:RogueDeadlyStrikeMod Defaults should give fairly close to live results @@ -1712,7 +1786,7 @@ Kayen: Revision to charm code to be consistent with live based on extensive pers Optional SQL: utils/sql/git/optional/2014_03_02_CharmRules.sql -demonstar55: Melee Crits, HoTs, DoTs messages should now be filtered correctly on all clients. +mackal: Melee Crits, HoTs, DoTs messages should now be filtered correctly on all clients. Clients that also support seeing others DoTs will now see them if they don't filter them note: some newer clients have a 'mine only' option for HoTs but it functions the same as show @@ -1764,7 +1838,7 @@ Sorvani: Renamed the instance_lockout and instance_lockout_player tables to inst Required SQL: utils/sql/git/2014_02_13_Rename_instance_lockout_tables.sql == 02/10/2014 == -demonstar55 (Secrets): Re-wrote the entity list to be a std::map. This should be used for direct entityID lookups and is noticably faster performance-wise. Also should result in less nil pointers potentially. +mackal (Secrets): Re-wrote the entity list to be a std::map. This should be used for direct entityID lookups and is noticably faster performance-wise. Also should result in less nil pointers potentially. Secrets: Fixed a crash issue that could occur on #repop related to quest timers. Kayen: Divine Arbiration and other similar spell effects will now utilize a spell range check. Kayen: Revised how heal amount is calculated to properly incorporate all current focus effects/bonuses. @@ -1795,14 +1869,14 @@ Kayen: Implemented SE_FfLimitUseType (focus limit to numhits type) == 01/20/2014 == cavedude: Live-Like weather system (Thanks to robregen for figuring it out!) -demonstar55: Implemented not_extendable spell flag -demonstar55: Moved Spell Casting Reinforcement to DB -demonstar55: Moved Mez Mastery to DB +mackal: Implemented not_extendable spell flag +mackal: Moved Spell Casting Reinforcement to DB +mackal: Moved Mez Mastery to DB Kayen: Complete revision of the numhits systems to utilize 'numhits type' field in spell file. == 01/18/2014 == sorvani: Implemented for Lua eq.get_characters_in_instance(uint16 instance_id), return a Lua HashTable -demonstar55: NPCs will now cast their charms. +mackal: NPCs will now cast their charms. == 01/13/2014 == Kayen: Numerous minor fixes to spell effects. @@ -1822,19 +1896,19 @@ Kayen: Implemented SE_LimitRace (Limits to spells cast by a certain race) Kayen: Implemented SE_FcMute (silences casting of spells that contain specific spell effects) ie silence only heals == 01/09/2014 == -demonstar55: Add pet size preservation like live (zone, camp, etc) +mackal: Add pet size preservation like live (zone, camp, etc) == 01/07/2014 == -demonstar55: Moved pet can attack check to before it tries to attack, which is more live like. +mackal: Moved pet can attack check to before it tries to attack, which is more live like. == 01/03/2014 == -demonstar55: Crash prevention for emote. +mackal: Crash prevention for emote. == 01/02/2014 == -demonstar55: Stuns from beneficial spells (Harvest) ignore immunity +mackal: Stuns from beneficial spells (Harvest) ignore immunity == 12/26/2013 == -demonstar55: Added classes_required to merchantlist (same bitmask as items) +mackal: Added classes_required to merchantlist (same bitmask as items) == 12/24/2013 == Secrets (Akkadius): Perl $client->SilentMessage("Message"); addition, this is a pre-req for a Perl plugin I've shared with EQEmu. This function essentially mimics a player speaking with an NPC - which is used in popup window responses @@ -1855,14 +1929,14 @@ Kayen: Implemented SE_TriggerOnAmountValue (Trigger spell if HP/Mana/End bellow Kayen: Fix to SE_BlockNextSpellFocus to make it functional again. == 12/15/2013 == -demonstar55: Moved the blocked buff check down so we get spell effects like on live +mackal: Moved the blocked buff check down so we get spell effects like on live Kayen: Implemented SE_ReduceHealing (Reduces amount of healing on target by X amount) Kayen: Implemented SE_CastonFocusEffect (Triggers spell as part of a focus, when that focus effect is used) Kayen: Implemented SE_IncreaseHitDmgTaken (Effect is triggered when X amount of damage is taken) Kayen: More fixes for various spell triggers/procs to now properly use their resist modifier. == 12/14/2013 == -demonstar55: Blocked buffs shouldn't fail, they should just not be applied. +mackal: Blocked buffs shouldn't fail, they should just not be applied. JJ: Changed enable/disable recipe to confirm change made. == 12/13/2013 == @@ -1873,52 +1947,52 @@ Kayen: Fix for various spell triggers/procs to now properly use their resist mod Kayen: Fix to mob->ModSkillDmgTaken(skill_num, value), setting value to -1 will now properly effect all skills. == 12/11/2013 == -demonstar55: Fixed issue with crippling blow from berserker frenzy not actually doing anything -demonstar55: Fix haste caps +mackal: Fixed issue with crippling blow from berserker frenzy not actually doing anything +mackal: Fix haste caps == 12/04/2013 == -demonstar55: Fixed SpellType_Charm case in AICastSpell +mackal: Fixed SpellType_Charm case in AICastSpell == 12/03/2013 == -demonstar55: Added #showspellslist to view a mobs spell list -demonstar55: Fix procing off of unattackable things +mackal: Added #showspellslist to view a mobs spell list +mackal: Fix procing off of unattackable things == 12/02/2013 == JJ: Bandaid fix to CopyCharacter function. == 11/29/2013 == -demonstar55: Stacking issues should be resolved now, probably could be optimized more, but went from 3 loops that do stuff to 3 where only 2 really does stuff and one breaks early in most cases, so slightly better +mackal: Stacking issues should be resolved now, probably could be optimized more, but went from 3 loops that do stuff to 3 where only 2 really does stuff and one breaks early in most cases, so slightly better == 11/23/2013 == Secrets: Fixed an issue related to a zone crash where the count of the abilities in an AA was 0, leading to a size 0 buffer issue. == 11/19/2013 == Secrets: Fixed an issue with two zone crashes reported on PEQ related to the buff restrictions code and AAs. -demonstar55: Partially make use of dot_stacking_exempt (case when it's 1 is implemented, -1 case isn't) +mackal: Partially make use of dot_stacking_exempt (case when it's 1 is implemented, -1 case isn't) == 11/18/2013 == -demonstar55: Added assistradius to npc_types, defaults to aggroradius if set to 0 (old behaviour) +mackal: Added assistradius to npc_types, defaults to aggroradius if set to 0 (old behaviour) == 11/17/2013 == Sorvani: fixed leash and tether special abilities to use the specified range correctly. -demonstar55: Rewrote the Mob::_GetMovementSpeed fix an issue that arose from the change on 11/11 +mackal: Rewrote the Mob::_GetMovementSpeed fix an issue that arose from the change on 11/11 - Added the rule Character:BaseRunSpeedCap (default 158) so people can customize what their runspeed cap is. Hardcapped to 225 so stuff doesn't get too crazy. == 11/16/2013 == Leere: Fixed the drinking message for auto-consume, it will again correctly show up for forced consumption instead. -demonstar55: Added Mob::DoCastingChecks() which will check for various fail conditions while the casting bar is up. This is called after Mob::DoCastSpell() starts the casting and before it returns. +mackal: Added Mob::DoCastingChecks() which will check for various fail conditions while the casting bar is up. This is called after Mob::DoCastSpell() starts the casting and before it returns. == 11/15/2013 == -demonstar55: Fixed Mob::CalcFocusEffect()'s SE_LimitEffect +mackal: Fixed Mob::CalcFocusEffect()'s SE_LimitEffect Leere: Fixed a stacking issue for SE_StackingCommand_Block == 11/13/2013 == -demonstar55: Implemented bard song effect cap. You can set the base cap with the rule Character:BaseInstrumentSoftCap, defaults to 36 or "3.6" as it is sometimes referred to. -demonstar55: Fix Echo of Taelosia and Ayonae's Tutelage to increase the mod cap instead of further improving the instrument mod -demonstar55: Implemented Singing/Instrument Mastery as an AA bonus. +mackal: Implemented bard song effect cap. You can set the base cap with the rule Character:BaseInstrumentSoftCap, defaults to 36 or "3.6" as it is sometimes referred to. +mackal: Fix Echo of Taelosia and Ayonae's Tutelage to increase the mod cap instead of further improving the instrument mod +mackal: Implemented Singing/Instrument Mastery as an AA bonus. == 11/11/2013 == -demonstar55: Changed the way walk speed is calculated to allow mobs to have their walk speed equal a 100% movement reduction +mackal: Changed the way walk speed is calculated to allow mobs to have their walk speed equal a 100% movement reduction == 11/09/2013 == Leere: Fixed Bard mana regen, they now only are affected by items and AA. @@ -1968,50 +2042,50 @@ Uleat: Converted SkillType typedef enumeration to SkillUseTypes enumeration - So Uleat: Prepped the client patch files for larger skill buffer size (not active) == 10/24/2013 == -demonstar55: Fix some memory leaks in Mob::SpellOnTarget +mackal: Fix some memory leaks in Mob::SpellOnTarget == 10/21/2013 == -demonstar55: Changed GetMinLevel return 0 for more cases that EQ uses for some reason ... -demonstar55: Added buff level restrictions, set the Spells:BuffLevelRestrictions to false to have the old behavior. +mackal: Changed GetMinLevel return 0 for more cases that EQ uses for some reason ... +mackal: Added buff level restrictions, set the Spells:BuffLevelRestrictions to false to have the old behavior. == 10/18/2013 == Uleat: Expanded the 'Bag Type' enumeration to include all known values. Also, set in place additional 'Bag Type' to 'Skill Type' conversions. Some of these will need to be verified before activation. Uleat: Cleaned up some unused enumerations to show a move towards standardization. More to come... == 10/12/2013 == -demonstar55: Allow Titanium and lower clients to enter Tutorial zone from character select +mackal: Allow Titanium and lower clients to enter Tutorial zone from character select Bad_Captain: Fixed merc crash issue by updating special_abilities & vwMercNpcTypes (Sorvani). Bad_Captain: Bots- added out of combat bard songs & #bot bardoutofcombat on|off command to turn them on/off. == 10/11/2013 == -JJ: (demonstar55) Allow use of Go Home button when Tutorial still selected in RoF. +JJ: (mackal) Allow use of Go Home button when Tutorial still selected in RoF. == 10/10/2013 == Secrets: Fixed zone shutdown (or #reloadqst) reinitalization of Perl. This should allow for Perl 5.14 and later to work on Windows under the new quest system. -demonstar55: Beneficial single target buffs shouldn't have their mana/timers set if they fail to cast after the Mob::SpellOnTarget call in Mob::SpellFinished +mackal: Beneficial single target buffs shouldn't have their mana/timers set if they fail to cast after the Mob::SpellOnTarget call in Mob::SpellFinished JJ: Revert change to EnterWorldPacket introduced on 22 April 2013 to fix inability to enter Tutorial or Go Home from character select screen. == 10/09/2013 == -demonstar55: Fixed some more instances of the AA timer being eaten +mackal: Fixed some more instances of the AA timer being eaten == 10/08/2013 == -demonstar55: Added IsBuffSpell(spell_id) that will return true if the spell has a duration, so would end up in effects/song/discs etc windows on the client -demonstar55: Replaced instances of using CalcBuffDuration to determine if a spell was a buff with IsBuffSpell -demonstar55: Removed Mob::HasBuffIcon since it was doing what IsBuffSpell does in a more convoluted way with a rather misleading name -demonstar55: Fixed issues that arose from the 10/03/2013 change +mackal: Added IsBuffSpell(spell_id) that will return true if the spell has a duration, so would end up in effects/song/discs etc windows on the client +mackal: Replaced instances of using CalcBuffDuration to determine if a spell was a buff with IsBuffSpell +mackal: Removed Mob::HasBuffIcon since it was doing what IsBuffSpell does in a more convoluted way with a rather misleading name +mackal: Fixed issues that arose from the 10/03/2013 change == 10/05/2013 == Sorvani: fixed issue with stackable items being created with 0 charges cause by fix to SummonItems == 10/03/2013 == -demonstar55: Fix when the random +1 tick is added to nerf extension focus effects to where they should be +mackal: Fix when the random +1 tick is added to nerf extension focus effects to where they should be == 09/30/2013 == Sorvani: Changed SummonItem to only summon an item with max charges when said default value is present and not on zero charges -demonstar55: Fixed issue with #showstats showing your level for a bunch of values +mackal: Fixed issue with #showstats showing your level for a bunch of values == 09/13/2013 == -demonstar55: Add support for /pet hold on and /pet hold off (UF and RoF) +mackal: Add support for /pet hold on and /pet hold off (UF and RoF) == 08/29/2013 == KLS: Removed Common Profiler and Zone Profiler. They're well past outdated status and are just code bloat. @@ -2157,8 +2231,8 @@ KLS: Perl now will (like lua) keep track of the values you return from EVENT_*. KLS: Exported eq.follow(entity_id, [distance]) and eq.stop_follow() to lua. == 07/01/2013 == -demonstar55: Fix Monster Summoning related to giants/cyclops -demonstar55: Prevent Monster Summoning from summoning a portal in bothunder +mackal: Fix Monster Summoning related to giants/cyclops +mackal: Prevent Monster Summoning from summoning a portal in bothunder KLS: Merge of lua branch to master See: http://www.eqemulator.org/forums/showthread.php?t=37008 for more detailed information on what is added. Upgrade notes: @@ -2226,35 +2300,35 @@ JJ: Fixed rare case where heals from buffs could go negative. Derision: Moved entity_list.Clear() prior to destruction of Perl objects in zone shutdown as I was seeing a segfault due to attempts to call EVENT_HATE_LIST as mobs were being destroyed. == 04/09/2013 == -demonstar55: Realized I was an idiot, changed salvage script to be better +mackal: Realized I was an idiot, changed salvage script to be better optional SQL: 2013_04_09_SalvageCleanOld.sql - run if ran old script == 04/08/2013 == -demonstar55: Implemented Salvage AA +mackal: Implemented Salvage AA required SQL: 2013_04_08_Salvage.sql script: generate_salvage.py - will generate the entries for some exceptions for salvage returns. == 04/04/2013 == -demonstar55: Implemented SE_ForageAdditionalItems as a bonus +mackal: Implemented SE_ForageAdditionalItems as a bonus required SQL: 2013_04_04_NaturesBounty.sql == 04/03/2013 == -demonstar55: Overloaded Mob::Say_StringID with the option to provide a message type -demonstar55: Switched rest of the Pet Messages to MT_PetResponse (Leader commands intentionally left the old way) +mackal: Overloaded Mob::Say_StringID with the option to provide a message type +mackal: Switched rest of the Pet Messages to MT_PetResponse (Leader commands intentionally left the old way) == 04/2/2013 == Bad_Captain: Fixed Merc lack of use of heal over time spells (causing excessive healing). Bad_Captain: Fixed pet mitigation/AC issues. == 04/01/2013 == -demonstar55: AA reuse timers now start when you hit the button and are reset upon failure -demonstar55: Instant Cast bard AAs can now be used while singing a song +mackal: AA reuse timers now start when you hit the button and are reset upon failure +mackal: Instant Cast bard AAs can now be used while singing a song == 03/30/2013 == -demonstar55: Fixed most of the pet talking, all use StringIDs now. Pet now informs you when it taunts. +mackal: Fixed most of the pet talking, all use StringIDs now. Pet now informs you when it taunts. == 03/23/2013 == -demonstar55: Fix issues with escape not always working and fixed SE_FadingMemories to have the message since the message isn't part of the spell data. +mackal: Fix issues with escape not always working and fixed SE_FadingMemories to have the message since the message isn't part of the spell data. Escape now uses just the spell and not the AA Actoin Fading Memories now only uses the AA Action to eat mana @@ -2264,7 +2338,7 @@ Bad_Captain: Added checks before dismissing merc to prevent possible bugged merc Bad_Captain: Merged in Secret's merc memory leak fixes. == 03/20/2013 == -demonstar55: Fixed stacking issues with SE_Limit* (ex. Unholy Aura Discipline and Aura of Reverence) +mackal: Fixed stacking issues with SE_Limit* (ex. Unholy Aura Discipline and Aura of Reverence) == 03/18/2013 == Bad_Captain: Fixed zone crash due to merc focus effects & tribute. @@ -2327,7 +2401,7 @@ KLS: Changed how shared memory works: af4t: Add Touch of the Wicked AA redux to SK Improved Harm Touch and Leech Touch. == 02/22/2013 == -demonstar55: Mobs will now be removed from XTargets when they get back to their way point, should be last instance of XTarget mobs not clearing when they are not aggroed anymore +mackal: Mobs will now be removed from XTargets when they get back to their way point, should be last instance of XTarget mobs not clearing when they are not aggroed anymore == 02/19/2013 == Derision: World should no longer crash if the start_zone query fails at character creation. @@ -2336,7 +2410,7 @@ Derision: World should no longer crash if the start_zone query fails at characte Bad_Captain: Moved merc save to merc table, save merc buffs, added cure and rez spells to healer merc. JJ: Chat garbled for drunk characters. Derision: Charmed pets should no longer be targettable with F8. Charmed pets no longer get a surname of Soandso's Pet. -demonstar55: Added potionbelt tool tip +mackal: Added potionbelt tool tip KLS: Added EVENT_DEATH to Player Quests REQUIRED SQL: 2013_02_18_Merc_Rules_and_Tables.sql @@ -2348,8 +2422,8 @@ Derision: Client version is now returned by the stream proxy as a number. Derision: Fixed bug where BecomeTrader packets were only being sent to the Trader, not all other clients in the bazaar. == 02/16/2013 == -demonstar55: Fix AA reuse timer calc -demonstar55: Remove old filters and change all remaining old to new (Also fix Auction filtering out OOC as well due to incorrect define) +mackal: Fix AA reuse timer calc +mackal: Remove old filters and change all remaining old to new (Also fix Auction filtering out OOC as well due to incorrect define) == 02/12/2013 == Kayen: AA fix @@ -2360,7 +2434,7 @@ REQUIRED SQL: utils/sql/svn/2504_required_aa_updates.sql Derision: RoF: Added ENCODE for OP_BeginCast (fixes no sound during spell casting). Corrected OP_DeleteSpell. == 02/10/2013 == -JJ: (demonstar55) Language skill up should use proper function. +JJ: (mackal) Language skill up should use proper function. JJ: SetLanguageSkill now updates client immediately. Both functions do proper limit checks. Added two missing languages. Skill level 0 in a spoken language now shows 'in an unknown tongue'. JJ: Initial implementation of a GarbleMessage function and implemented for languages. Can be shared with drunk speaking. @@ -2396,7 +2470,7 @@ Trevius: RoF: Turning on Trader mode in bazaar now works, but no further trader Akkadius: Fixed an issue where global_npc.pl was not initializing (initially) == 01/31/2013 == -cavedude00: (demonstar55) Rune aggro fix +cavedude00: (mackal) Rune aggro fix cavedude00: (Drajor) Tradeskill skillneeded fix. == 01/30/2013 == @@ -2430,7 +2504,7 @@ Bad_Captain: Mercs - Initial spell casting AI committed. KLS: Added crash logging for Windows builds. Trevius: Mercenaries now despawn when a player camps out or disconnects in any way. Trevius: Players with a Mercenary spawned can now be invited to and join another group with their mercenary. -Sorvani: (Demonstar55): Moved stunproc rule implmentation to catch all cases +Sorvani: (mackal): Moved stunproc rule implmentation to catch all cases OPTIONAL SQL: utils/sql/svn/mercs.sql -- rerun for updated merc stats & merc spell lists @@ -2881,9 +2955,9 @@ references: http://www.eqemulator.org/forums/showthread.php?t=35629 - CSD Bugged Corpse Patch http://www.eqemulator.org/forums/showthread.php?t=35699 - CSD Bandolier Patch -cavedude: (demonstar55) Damage shields by default will no longer count towards EXP gain. (Rule also added to change this behaviour.) -cavedude: (demonstar55) Extended targets should now clear when aggro is lost using skills. -cavedude: (demonstar55) AAs with shorter reuse timers should now reset if the cast failed (interrupted.) +cavedude: (mackal) Damage shields by default will no longer count towards EXP gain. (Rule also added to change this behaviour.) +cavedude: (mackal) Extended targets should now clear when aggro is lost using skills. +cavedude: (mackal) AAs with shorter reuse timers should now reset if the cast failed (interrupted.) KLS: Fixed a cause of raids disbanding on zoning. OPTIONAL SQL: INSERT INTO `rule_values` VALUES (1, 'Combat:EXPFromDmgShield', 'false', 'Determine if damage from a damage shield counts for EXP gain.'); @@ -3260,7 +3334,7 @@ Kayen: Implemented Perl Mob Quest Object GetModVulnerability(resist type) - Retu Optional SQL: utils/sql/svn/2154_optional_rule_spell_procs_resists_falloff.sql ==06/22/2012== -Secrets: (demonstar55) Spells now display to all clients and can be filtered as such. +Secrets: (mackal) Spells now display to all clients and can be filtered as such. Secrets: Damage Shields now go to the proper filter, and do not show the non-melee damage to everyone. ==06/03/2012== @@ -5415,10 +5489,10 @@ WildcardX: *BOTS* Bots can now be invited and disbanded from your group by simpl WildcardX: *BOTS* Tweak to the bots total play time calculation to make it more accurate. KLS: Added #path meshtest simple to do a faster search on errant path nodes. KLS: Modified the accurate hazard code to make automatic path maps with more accurate info that requires less manual editing afterward. -cavedude: (demonstar55) Pets will now be amiable to their owners, indifferent to all else. -cavedude: (demonstar55) Added $client->KeyRingCheck() and $client->KeyRingAdd() to allow Perl to manipulate the keyring. -cavedude: (demonstar55) Casting an invis spell on a player that already has a similar type invis spell will no longer drop the existing buff. -cavedude: (demonstar55) Corrected message string for heal spells. +cavedude: (mackal) Pets will now be amiable to their owners, indifferent to all else. +cavedude: (mackal) Added $client->KeyRingCheck() and $client->KeyRingAdd() to allow Perl to manipulate the keyring. +cavedude: (mackal) Casting an invis spell on a player that already has a similar type invis spell will no longer drop the existing buff. +cavedude: (mackal) Corrected message string for heal spells. cavedude: Added rule to determine at what HP a fleeing NPC will halt due to being snared. ==08/07/2009== @@ -6054,7 +6128,7 @@ KLS: Fixed the /bug structure and updated the table to be more useful. Required SQL: .\utils\sql\svn\503_bugs.sql ==05/11/2009== -demonstar55: Added a function to allow Perl to check augments within items. +mackal: Added a function to allow Perl to check augments within items. cavedude: Increased bind wound skill up speed some. KLS: Fix for potentially dangerous typo in spawn conditions code. KLS: Removed some non-functioning but still taking up database resources database code. @@ -6355,7 +6429,7 @@ cavedude: Removed the USE_RACE_CLASS_XP_MODS define as it was outdated and horri cavedude: Added group XP bonus. The larger the group, the higher the XP gain. cavedude: Added XP bonus for Warrior, Rogue, and Halfling. cavedude: Corrected ZEM for AAs. -cavedude: (Thanks to demonstar55) Pet Affinity will no longer effect charmed pets. +cavedude: (Thanks to mackal) Pet Affinity will no longer effect charmed pets. cavedude: (realityincarnate) Bard songs that require instruments will now require them. Please note: XP gain has pretty much been overhauled. You may need tweak the multiplier rules for your server. @@ -6489,7 +6563,7 @@ AndMetal: Augments are now visible when linking items. Trevius: SoF - Adjusted the new Item Structure to align more fields Trevius: SoF - Added OP_Consume and OP_LootRequest opcodes cavedude00: (AndMetal) AAs now use skill_id instead of index for prereqs. -cavedude00: (demonstar55) Implemented Improved Instrument Mastery, Improved Singing Mastery, and Echo of Taelosia AAs. +cavedude00: (mackal) Implemented Improved Instrument Mastery, Improved Singing Mastery, and Echo of Taelosia AAs. cavedude00: Created Combat:ChanceToHitDivideBy rule and increased default value to 1250. Required and Optional SQL: utils/sql/svn/326_aas.sql KLS: SoF - Fix for item slots in bags. From 8aa942cd27c1625bb395fcad99700cc08e3c810c Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Wed, 14 Sep 2016 16:31:52 -0400 Subject: [PATCH 375/693] Added quest global support for zone_controller. --- common/ruletypes.h | 1 + zone/npc.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/common/ruletypes.h b/common/ruletypes.h index 7837834f9..2731c1a26 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -256,6 +256,7 @@ RULE_INT(Zone, WeatherTimer, 600) // Weather timer when no duration is available RULE_BOOL(Zone, EnableLoggedOffReplenishments, true) RULE_INT(Zone, MinOfflineTimeToReplenishments, 21600) // 21600 seconds is 6 Hours RULE_BOOL(Zone, UseZoneController, true) // Enables the ability to use persistent quest based zone controllers (zone_controller.pl/lua) +RULE_BOOL(Zone, EnableZoneControllerGlobals, false) // Enables the ability to use quest globals with the zone controller NPC RULE_CATEGORY_END() RULE_CATEGORY(Map) diff --git a/zone/npc.cpp b/zone/npc.cpp index 1fc27dc5a..ecc3bf101 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -872,6 +872,10 @@ bool NPC::SpawnZoneController(){ npc_type->merchanttype = 0; npc_type->bodytype = 11; + if (RuleB(Zone, EnableZoneControllerGlobals)) { + npc_type->qglobal = true; + } + npc_type->prim_melee_type = 28; npc_type->sec_melee_type = 28; From b04844aa946d86776512460e4bd4315eed211ddf Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 21 Sep 2016 23:54:51 -0400 Subject: [PATCH 376/693] Fix merge [skip ci] --- changelog.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 3df12a4d2..73be04468 100644 --- a/changelog.txt +++ b/changelog.txt @@ -76,7 +76,6 @@ mackal: Instant spells now have instrument mods mackal: Rate limit character saves mackal: Made it so items no longer do TGB (Live-like) Rule implemented to disable mackal: Set pet buffs limit to 30 ->>>>>>> upstream/master == 09/03/2016 == Uleat: Changed 'Bind Wound' behavior to match the best references that I could find for post-2004 era. From 4cb7d9a3524aae7cafa2fa9a413753c29f89970b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 22 Sep 2016 00:32:01 -0400 Subject: [PATCH 377/693] Remove ability for charmed NPCs from summoning These rules do not appear to be true on live They also don't look to have ever been true? --- zone/mob.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 8aa889719..fb4c14bf2 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2584,14 +2584,12 @@ bool Mob::PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, fl bool Mob::HateSummon() { // check if mob has ability to summon // 97% is the offical % that summoning starts on live, not 94 - // if the mob can summon and is charmed, it can only summon mobs it has LoS to - Mob* mob_owner = nullptr; - if(GetOwnerID()) - mob_owner = entity_list.GetMob(GetOwnerID()); + if (IsCharmed()) + return false; int summon_level = GetSpecialAbility(SPECATK_SUMMON); if(summon_level == 1 || summon_level == 2) { - if(!GetTarget() || (mob_owner && mob_owner->IsClient() && !CheckLosFN(GetTarget()))) { + if(!GetTarget()) { return false; } } else { From 6079b34a2a30e350d5b9c17e239aa30ad36b1b23 Mon Sep 17 00:00:00 2001 From: Xackery Date: Mon, 26 Sep 2016 02:09:39 -0700 Subject: [PATCH 378/693] Added Ruleset AA:ShowExpValues. --- common/ruletypes.h | 1 + zone/exp.cpp | 51 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 2731c1a26..bf35d03e8 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -55,6 +55,7 @@ RULE_REAL(Character, AAExpMultiplier, 0.5) RULE_REAL(Character, GroupExpMultiplier, 0.5) RULE_REAL(Character, RaidExpMultiplier, 0.2) RULE_BOOL(Character, UseXPConScaling, true) +RULE_INT(Character, ShowExpValues, 0) //0 - normal, 1 - Show raw experience values, 2 - Show raw experience values AND percent. RULE_INT(Character, LightBlueModifier, 40) RULE_INT(Character, BlueModifier, 90) RULE_INT(Character, WhiteModifier, 100) diff --git a/zone/exp.cpp b/zone/exp.cpp index 63989a4e9..9d2d33a31 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -350,19 +350,50 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { } if ((set_exp + set_aaxp) > (m_pp.exp+m_pp.expAA)) { - if (isrezzexp) - this->Message_StringID(MT_Experience, REZ_REGAIN); - else{ - if(membercount > 1) - this->Message_StringID(MT_Experience, GAIN_GROUPXP); - else if(IsRaidGrouped()) - Message_StringID(MT_Experience, GAIN_RAIDEXP); - else - this->Message_StringID(MT_Experience, GAIN_XP); + + uint32 exp_gained = set_exp - m_pp.exp; + uint32 aaxp_gained = set_aaxp - m_pp.expAA; + float exp_percent = (float)((float)exp_gained / (float)(GetEXPForLevel(GetLevel() + 1) - GetEXPForLevel(GetLevel())))*(float)100; //EXP needed for level + float aaxp_percent = (float)((float)aaxp_gained / (float)(RuleI(AA, ExpPerPoint)))*(float)100; //AAEXP needed for level + std::string exp_amount_message = ""; + if (RuleI(Character, ShowExpValues) >= 1) { + if (exp_gained > 0 && aaxp_gained > 0) exp_amount_message = StringFormat("%u, %u AA", exp_gained, aaxp_gained); + else if (exp_gained > 0) exp_amount_message = StringFormat("%u", exp_gained); + else exp_amount_message = StringFormat("%u AA", aaxp_gained); + } + + std::string exp_percent_message = ""; + if (RuleI(Character, ShowExpValues) >= 2) { + if (exp_gained > 0 && aaxp_gained > 0) exp_percent_message = StringFormat("(%.3f%%, %.3f%%AA)", exp_percent, aaxp_percent); + else if (exp_gained > 0) exp_percent_message = StringFormat("(%.3f%%)", exp_percent); + else exp_percent_message = StringFormat("(%.3f%%AA)", aaxp_percent); + } + + if (isrezzexp) { + if (RuleI(Character, ShowExpValues) > 0) Message(MT_Experience, "You regain %s experience from resurrection. %s", exp_amount_message.c_str(), exp_percent_message.c_str()); + else Message_StringID(MT_Experience, REZ_REGAIN); + } else { + if (membercount > 1) { + if (RuleI(Character, ShowExpValues) > 0) Message(MT_Experience, "You have gained %s party experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str()); + else Message_StringID(MT_Experience, GAIN_GROUPXP); + } + else if (IsRaidGrouped()) { + if (RuleI(Character, ShowExpValues) > 0) Message(MT_Experience, "You have gained %s raid experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str()); + else Message_StringID(MT_Experience, GAIN_RAIDEXP); + } + else { + if (RuleI(Character, ShowExpValues) > 0) Message(MT_Experience, "You have gained %s experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str()); + else Message_StringID(MT_Experience, GAIN_XP); + } } } else if((set_exp + set_aaxp) < (m_pp.exp+m_pp.expAA)){ //only loss message if you lose exp, no message if you gained/lost nothing. - Message(15, "You have lost experience."); + uint32 exp_lost = m_pp.exp - set_exp; + float exp_percent = (float)((float)exp_lost / (float)(GetEXPForLevel(GetLevel() + 1) - GetEXPForLevel(GetLevel())))*(float)100; + + if (RuleI(Character, ShowExpValues) == 1 && exp_lost > 0) Message(13, "You have lost %i experience.", exp_lost); + else if (RuleI(Character, ShowExpValues) == 2 && exp_lost > 0) Message(13, "You have lost %i experience. (%.3f%%)", exp_lost, exp_percent); + else Message(15, "You have lost experience."); } //check_level represents the level we should be when we have From 19b6a96063ccde0cf62481d85dd48efedebd134b Mon Sep 17 00:00:00 2001 From: Xackery Date: Mon, 26 Sep 2016 02:11:50 -0700 Subject: [PATCH 379/693] Changed lost exp message to all be 15. --- zone/exp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/exp.cpp b/zone/exp.cpp index 9d2d33a31..d6b0b903a 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -391,8 +391,8 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { uint32 exp_lost = m_pp.exp - set_exp; float exp_percent = (float)((float)exp_lost / (float)(GetEXPForLevel(GetLevel() + 1) - GetEXPForLevel(GetLevel())))*(float)100; - if (RuleI(Character, ShowExpValues) == 1 && exp_lost > 0) Message(13, "You have lost %i experience.", exp_lost); - else if (RuleI(Character, ShowExpValues) == 2 && exp_lost > 0) Message(13, "You have lost %i experience. (%.3f%%)", exp_lost, exp_percent); + if (RuleI(Character, ShowExpValues) == 1 && exp_lost > 0) Message(15, "You have lost %i experience.", exp_lost); + else if (RuleI(Character, ShowExpValues) == 2 && exp_lost > 0) Message(15, "You have lost %i experience. (%.3f%%)", exp_lost, exp_percent); else Message(15, "You have lost experience."); } From 4fa8c89e5cc7471402742e47c5d361167948de26 Mon Sep 17 00:00:00 2001 From: Joshua Packard Date: Wed, 28 Sep 2016 19:24:09 -0700 Subject: [PATCH 380/693] Added Best Z Calculation to Ground Spawn Loc --- zone/object.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/zone/object.cpp b/zone/object.cpp index c00f718b3..b28a886f3 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -451,6 +451,21 @@ void Object::RandomSpawn(bool send_packet) { m_data.x = zone->random.Real(m_min_x, m_max_x); m_data.y = zone->random.Real(m_min_y, m_max_y); + + if(m_data.z == BEST_Z_INVALID) { + glm::vec3 me; + me.x = m_data.x; + me.y = m_data.y; + me.z = 0; + glm::vec3 hit; + float best_z = zone->zonemap->FindClosestZ(me, &hit); + if (best_z != BEST_Z_INVALID) { + m_data.z = best_z; + } + } + + Log.Out(Logs::Detail, Logs::Zone_Server, "Object::RandomSpawn(%s): %d (%.2f, %.2f, %.2f)", m_data.object_name, m_inst->GetID(), m_data.x, m_data.y, m_data.z); + respawn_timer.Disable(); if(send_packet) { From 329c9c8d98535b410880389227e8167130fa9930 Mon Sep 17 00:00:00 2001 From: Joshua Packard Date: Wed, 28 Sep 2016 19:26:44 -0700 Subject: [PATCH 381/693] Reordered zone initialization Needed to reorder zone init so that the zonemap is loaded before ground spawns are made, otherwise the best Z won't calculate. --- zone/zone.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/zone/zone.cpp b/zone/zone.cpp index 35b2d52bb..1edf1a268 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -100,9 +100,6 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { worldserver.SetZoneData(0); return false; } - zone->zonemap = Map::LoadMapFile(zone->map_name); - zone->watermap = WaterMap::LoadWaterMapfile(zone->map_name); - zone->pathing = PathManager::LoadPathFile(zone->map_name); std::string tmp; if (database.GetVariable("loglevel", tmp)) { @@ -877,6 +874,23 @@ Zone::~Zone() { //Modified for timezones. bool Zone::Init(bool iStaticZone) { SetStaticZone(iStaticZone); + + //load the zone config file. + if (!LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion(), true)) // try loading the zone name... + LoadZoneCFG(zone->GetFileName(), zone->GetInstanceVersion()); // if that fails, try the file name, then load defaults + + if(RuleManager::Instance()->GetActiveRulesetID() != default_ruleset) + { + std::string r_name = RuleManager::Instance()->GetRulesetName(&database, default_ruleset); + if(r_name.size() > 0) + { + RuleManager::Instance()->LoadRules(&database, r_name.c_str()); + } + } + + zone->zonemap = Map::LoadMapFile(zone->map_name); + zone->watermap = WaterMap::LoadWaterMapfile(zone->map_name); + zone->pathing = PathManager::LoadPathFile(zone->map_name); Log.Out(Logs::General, Logs::Status, "Loading spawn conditions..."); if(!spawn_conditions.LoadSpawnConditions(short_name, instanceid)) { @@ -969,19 +983,6 @@ bool Zone::Init(bool iStaticZone) { petition_list.ClearPetitions(); petition_list.ReadDatabase(); - //load the zone config file. - if (!LoadZoneCFG(zone->GetShortName(), zone->GetInstanceVersion(), true)) // try loading the zone name... - LoadZoneCFG(zone->GetFileName(), zone->GetInstanceVersion()); // if that fails, try the file name, then load defaults - - if(RuleManager::Instance()->GetActiveRulesetID() != default_ruleset) - { - std::string r_name = RuleManager::Instance()->GetRulesetName(&database, default_ruleset); - if(r_name.size() > 0) - { - RuleManager::Instance()->LoadRules(&database, r_name.c_str()); - } - } - Log.Out(Logs::General, Logs::Status, "Loading timezone data..."); zone->zone_time.setEQTimeZone(database.GetZoneTZ(zoneid, GetInstanceVersion())); From 379ef7eed314fc887e47b36859dbc69b1c888024 Mon Sep 17 00:00:00 2001 From: Joshua Packard Date: Thu, 29 Sep 2016 16:49:05 -0700 Subject: [PATCH 382/693] Added optional SQL to apply max z updates --- utils/sql/git/optional/2016_09_29_GroundSpawnsMaxZ.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 utils/sql/git/optional/2016_09_29_GroundSpawnsMaxZ.sql diff --git a/utils/sql/git/optional/2016_09_29_GroundSpawnsMaxZ.sql b/utils/sql/git/optional/2016_09_29_GroundSpawnsMaxZ.sql new file mode 100644 index 000000000..1cc98e246 --- /dev/null +++ b/utils/sql/git/optional/2016_09_29_GroundSpawnsMaxZ.sql @@ -0,0 +1 @@ +UPDATE ground_spawns SET max_z = -99999 WHERE max_x != min_x OR max_y != min_y From 013f7cfd2145ba79f8417d41f0c02f1e54225135 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 3 Oct 2016 01:35:11 -0400 Subject: [PATCH 383/693] Set no_target_hotkey in Mob ctor Fixes UBSan error --- zone/mob.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/mob.cpp b/zone/mob.cpp index fb4c14bf2..1caf69918 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -365,6 +365,7 @@ Mob::Mob(const char* in_name, patrol=0; follow=0; follow_dist = 100; // Default Distance for Follow + no_target_hotkey = false; flee_mode = false; currently_fleeing = false; flee_timer.Start(); From 7b5ea9e99c461b8243e724906e4bb2d352288a1b Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sun, 9 Oct 2016 10:22:55 -0400 Subject: [PATCH 384/693] Fix rogue merchant usage under sneak. --- changelog.txt | 5 +++++ zone/client_process.cpp | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 73be04468..a0339ee08 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/09/2016 == +Noudess: Rogue usage of merchants while utilizing sneak was limited to +temporary items, as the code that checked faction per item sold did not +take into account that rogue was sneaking. Now sneaking rogues can see full +inventory on merchants (well, unless an item requires a + faction value). == 09/12/2016 == Akkadius: Massive overhaul of the update system and EQEmu Server management utility framework (known as eqemu_update.pl) now known as eqemu_server.pl diff --git a/zone/client_process.cpp b/zone/client_process.cpp index e1a769743..9e7b230d7 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -857,7 +857,17 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { continue; int32 fac = merch ? merch->GetPrimaryFaction() : 0; - if (fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required) + int32 cur_fac_level; + if (fac == 0 || sneaking) + { + cur_fac_level = 0; + } + else + { + cur_fac_level = GetModCharacterFactionLevel(fac); + } + + if (cur_fac_level < ml.faction_required) continue; handychance = zone->random.Int(0, merlist.size() + tmp_merlist.size() - 1); From c263c4ef07d6ae1d73791c12fc272efe59e03561 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sun, 9 Oct 2016 11:12:09 -0400 Subject: [PATCH 385/693] 2nd check for faction not needed - had to either check for sneaking again or remove un-needed 2nd check. --- zone/client_packet.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index fa253664b..6fc45fee0 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -12134,11 +12134,6 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) continue; } - int32 fac = tmp->GetPrimaryFaction(); - if (fac != 0 && GetModCharacterFactionLevel(fac) < ml.faction_required) { - continue; - } - if (mp->itemslot == ml.slot){ item_id = ml.item; break; From a5b19d0c0df7dff2b4d648f204aeb7f91da05363 Mon Sep 17 00:00:00 2001 From: Joshua Packard Date: Mon, 10 Oct 2016 09:39:55 -0700 Subject: [PATCH 386/693] Added 0.1 to calculated Z so that objects show better above ground --- zone/object.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/object.cpp b/zone/object.cpp index b28a886f3..ab9637e96 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -460,7 +460,7 @@ void Object::RandomSpawn(bool send_packet) { glm::vec3 hit; float best_z = zone->zonemap->FindClosestZ(me, &hit); if (best_z != BEST_Z_INVALID) { - m_data.z = best_z; + m_data.z = best_z + 0.1f; } } From 343c41bb1824877957f892b50a257077b496fe49 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 13 Oct 2016 23:54:56 -0400 Subject: [PATCH 387/693] Elemental dmg shouldn't allow you to hit bane only --- zone/attack.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 991e251f3..9b83f7994 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -858,7 +858,7 @@ int Mob::GetWeaponDamage(Mob *against, const EQEmu::ItemBase *weapon_item) { } } - if(!eledmg && !banedmg){ + if(!banedmg){ if(!GetSpecialAbility(SPECATK_BANE)) return 0; else @@ -979,7 +979,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate banedmg = against->CheckBaneDamage(weapon_item); if (against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) { - if (!eledmg && !banedmg) { + if (!banedmg) { if (!GetSpecialAbility(SPECATK_BANE)) return 0; else From 1e865a524628175b9152c93df0c71757bf6c95ff Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 13 Oct 2016 23:55:44 -0400 Subject: [PATCH 388/693] Take in elem/bane dmg in BS calc --- zone/special_attacks.cpp | 53 +++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index eb7f5aac1..06d8ba4a9 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -576,33 +576,30 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) int32 primaryweapondamage = 0; int32 backstab_dmg = 0; - if(IsClient()){ - const ItemInst *wpn = nullptr; - wpn = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); - if(wpn) { + if (IsClient()) { + const ItemInst *wpn = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); + if (wpn) { primaryweapondamage = GetWeaponDamage(other, wpn); - backstab_dmg = wpn->GetItem()->BackstabDmg; - for (int i = 0; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) - { - ItemInst *aug = wpn->GetAugment(i); - if(aug) - { - backstab_dmg += aug->GetItem()->BackstabDmg; - } + if (primaryweapondamage) { + backstab_dmg = wpn->GetItemBackstabDamage(true); + backstab_dmg += other->ResistElementalWeaponDmg(wpn); + if (wpn->GetItemBaneDamageBody(true) || wpn->GetItemBaneDamageRace(true)) + backstab_dmg += other->CheckBaneDamage(wpn); } } - } - else{ - primaryweapondamage = (GetLevel()/7)+1; // fallback incase it's a npc without a weapon, 2 dmg at 10, 10 dmg at 65 + } else { + primaryweapondamage = + (GetLevel() / 7) + 1; // fallback incase it's a npc without a weapon, 2 dmg at 10, 10 dmg at 65 backstab_dmg = primaryweapondamage; } - if(primaryweapondamage > 0){ - if(level > 25){ + // ex. bane can make this false + if (primaryweapondamage > 0) { + // this is very wrong but not worth it until we fix the full dmg + if (level > 25) { max_hit = (((((2 * backstab_dmg) * GetDamageTable(EQEmu::skills::SkillBackstab) / 100) * 10 * GetSkill(EQEmu::skills::SkillBackstab) / 355) + ((level - 25) / 3) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); hate = 20 * backstab_dmg * GetSkill(EQEmu::skills::SkillBackstab) / 355; - } - else{ + } else { max_hit = (((((2 * backstab_dmg) * GetDamageTable(EQEmu::skills::SkillBackstab) / 100) * 10 * GetSkill(EQEmu::skills::SkillBackstab) / 355) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); hate = 20 * backstab_dmg * GetSkill(EQEmu::skills::SkillBackstab) / 355; } @@ -610,31 +607,27 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) // determine minimum hits if (level < 51) { min_hit = (level*15/10); - } - else { + } else { // Trumpcard: Replaced switch statement with formula calc. This will give minhit increases all the way to 65. min_hit = (level * ( level*5 - 105)) / 100; } - if (!other->CheckHitChance(this, EQEmu::skills::SkillBackstab, 0)) { + if (!other->CheckHitChance(this, EQEmu::skills::SkillBackstab, 0)) { ndamage = 0; - } - else{ - if(min_damage){ + } else { + if (min_damage) { ndamage = min_hit; - } - else { + } else { if (max_hit < min_hit) max_hit = min_hit; - if(RuleB(Combat, UseIntervalAC)) + if (RuleB(Combat, UseIntervalAC)) ndamage = max_hit; else ndamage = zone->random.Int(min_hit, max_hit); } } - } - else{ + } else { ndamage = -5; } From c90a436db30366b7063331e35e2bc9c5055827d6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 14 Oct 2016 13:52:01 -0400 Subject: [PATCH 389/693] Clang format ConeDirectional --- zone/spells.cpp | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index c818c8e90..52a1e1ab9 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5673,45 +5673,45 @@ void Mob::ConeDirectional(uint16 spell_id, int16 resist_adjust) float angle_start = spells[spell_id].directional_start + (GetHeading() * 360.0f / 256.0f); float angle_end = spells[spell_id].directional_end + (GetHeading() * 360.0f / 256.0f); - while(angle_start > 360.0f) + while (angle_start > 360.0f) angle_start -= 360.0f; - while(angle_end > 360.0f) + while (angle_end > 360.0f) angle_end -= 360.0f; - std::list targets_in_range; - std::list::iterator iter; + std::list targets_in_range; - entity_list.GetTargetsForConeArea(this, spells[spell_id].min_range, spells[spell_id].aoerange, spells[spell_id].aoerange / 2, targets_in_range); - iter = targets_in_range.begin(); + entity_list.GetTargetsForConeArea(this, spells[spell_id].min_range, spells[spell_id].aoerange, + spells[spell_id].aoerange / 2, targets_in_range); + auto iter = targets_in_range.begin(); - while(iter != targets_in_range.end()){ - - if (!(*iter) || (beneficial_targets && ((*iter)->IsNPC() && !(*iter)->IsPetOwnerClient()))){ - ++iter; + while (iter != targets_in_range.end()) { + if (!(*iter) || (beneficial_targets && ((*iter)->IsNPC() && !(*iter)->IsPetOwnerClient()))) { + ++iter; continue; } - float heading_to_target = (CalculateHeadingToTarget((*iter)->GetX(), (*iter)->GetY()) * 360.0f / 256.0f); + float heading_to_target = + (CalculateHeadingToTarget((*iter)->GetX(), (*iter)->GetY()) * 360.0f / 256.0f); - while(heading_to_target < 0.0f) + while (heading_to_target < 0.0f) heading_to_target += 360.0f; - while(heading_to_target > 360.0f) + while (heading_to_target > 360.0f) heading_to_target -= 360.0f; - if(angle_start > angle_end){ - if((heading_to_target >= angle_start && heading_to_target <= 360.0f) || (heading_to_target >= 0.0f && heading_to_target <= angle_end)){ - if(CheckLosFN((*iter)) || spells[spell_id].npc_no_los){ + if (angle_start > angle_end) { + if ((heading_to_target >= angle_start && heading_to_target <= 360.0f) || + (heading_to_target >= 0.0f && heading_to_target <= angle_end)) { + if (CheckLosFN((*iter)) || spells[spell_id].npc_no_los) { (*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this); - SpellOnTarget(spell_id,(*iter), false, true, resist_adjust); + SpellOnTarget(spell_id, (*iter), false, true, resist_adjust); maxtarget_count++; } } - } - else{ - if(heading_to_target >= angle_start && heading_to_target <= angle_end){ - if(CheckLosFN((*iter)) || spells[spell_id].npc_no_los) { + } else { + if (heading_to_target >= angle_start && heading_to_target <= angle_end) { + if (CheckLosFN((*iter)) || spells[spell_id].npc_no_los) { (*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this); SpellOnTarget(spell_id, (*iter), false, true, resist_adjust); maxtarget_count++; From 05ed623056633ea52f5c30eec9f14143e6425819 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 14 Oct 2016 13:55:04 -0400 Subject: [PATCH 390/693] Add NPC NPC faction check to ConeDirectional --- zone/spells.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index 52a1e1ab9..ccae7922b 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5700,6 +5700,19 @@ void Mob::ConeDirectional(uint16 spell_id, int16 resist_adjust) while (heading_to_target > 360.0f) heading_to_target -= 360.0f; + if (IsNPC() && (*iter)->IsNPC()) { + auto fac = (*iter)->GetReverseFactionCon(this); + if (beneficial_targets) { + // only affect mobs we would assist. + if (!(fac <= FACTION_AMIABLE)) + continue; + } else { + // affect mobs that are on our hate list, or which have bad faction with us + if (!(CheckAggro(*iter) || fac == FACTION_THREATENLY || fac == FACTION_SCOWLS)) + continue; + } + } + if (angle_start > angle_end) { if ((heading_to_target >= angle_start && heading_to_target <= 360.0f) || (heading_to_target >= 0.0f && heading_to_target <= angle_end)) { From 46cbd147b567ebc960dd96be12bbd5a6d82d1f3d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 14 Oct 2016 13:58:20 -0400 Subject: [PATCH 391/693] clang format BeamDirectional --- zone/spells.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index ccae7922b..f744541e0 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5619,11 +5619,11 @@ void Mob::BeamDirectional(uint16 spell_id, int16 resist_adjust) if (IsBeneficialSpell(spell_id) && IsClient()) beneficial_targets = true; - std::list targets_in_range; - std::list::iterator iter; + std::list targets_in_range; - entity_list.GetTargetsForConeArea(this, spells[spell_id].min_range, spells[spell_id].range, spells[spell_id].range / 2, targets_in_range); - iter = targets_in_range.begin(); + entity_list.GetTargetsForConeArea(this, spells[spell_id].min_range, spells[spell_id].range, + spells[spell_id].range / 2, targets_in_range); + auto iter = targets_in_range.begin(); float dX = 0; float dY = 0; @@ -5632,24 +5632,22 @@ void Mob::BeamDirectional(uint16 spell_id, int16 resist_adjust) CalcDestFromHeading(GetHeading(), spells[spell_id].range, 5, GetX(), GetY(), dX, dY, dZ); dZ = GetZ(); - //FIND SLOPE: Put it into the form y = mx + b + // FIND SLOPE: Put it into the form y = mx + b float m = (dY - GetY()) / (dX - GetX()); float b = (GetY() * dX - dY * GetX()) / (dX - GetX()); - while(iter != targets_in_range.end()) - { - if (!(*iter) || (beneficial_targets && ((*iter)->IsNPC() && !(*iter)->IsPetOwnerClient())) - || (*iter)->BehindMob(this, (*iter)->GetX(),(*iter)->GetY())){ - ++iter; + while (iter != targets_in_range.end()) { + if (!(*iter) || (beneficial_targets && ((*iter)->IsNPC() && !(*iter)->IsPetOwnerClient())) || + (*iter)->BehindMob(this, (*iter)->GetX(), (*iter)->GetY())) { + ++iter; continue; } //# shortest distance from line to target point float d = std::abs((*iter)->GetY() - m * (*iter)->GetX() - b) / sqrt(m * m + 1); - if (d <= spells[spell_id].aoerange) - { - if(CheckLosFN((*iter)) || spells[spell_id].npc_no_los) { + if (d <= spells[spell_id].aoerange) { + if (CheckLosFN((*iter)) || spells[spell_id].npc_no_los) { (*iter)->CalcSpellPowerDistanceMod(spell_id, 0, this); SpellOnTarget(spell_id, (*iter), false, true, resist_adjust); maxtarget_count++; From e86fca3affc4e5e97cabfdc3f1a5ef85172206ca Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 14 Oct 2016 13:59:45 -0400 Subject: [PATCH 392/693] Add NPC NPC faction check to BeamDirectional --- zone/spells.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index f744541e0..04129b554 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5643,6 +5643,19 @@ void Mob::BeamDirectional(uint16 spell_id, int16 resist_adjust) continue; } + if (IsNPC() && (*iter)->IsNPC()) { + auto fac = (*iter)->GetReverseFactionCon(this); + if (beneficial_targets) { + // only affect mobs we would assist. + if (!(fac <= FACTION_AMIABLE)) + continue; + } else { + // affect mobs that are on our hate list, or which have bad faction with us + if (!(CheckAggro(*iter) || fac == FACTION_THREATENLY || fac == FACTION_SCOWLS)) + continue; + } + } + //# shortest distance from line to target point float d = std::abs((*iter)->GetY() - m * (*iter)->GetX() - b) / sqrt(m * m + 1); From 8496bf16ff201291928ecb33a3067df783d97d58 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 14 Oct 2016 14:37:25 -0500 Subject: [PATCH 393/693] eqemu_server.pl [skip ci] Make the internet connection check more multi-lingual friendly --- utils/scripts/eqemu_server.pl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 821736fef..180dda907 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -488,11 +488,11 @@ sub check_internet_connection { $count = "n"; } - if (`ping 8.8.8.8 -$count 1 -w 500`=~/Reply from|1 received/i) { + if (`ping 8.8.8.8 -$count 1 -w 500`=~/TTL|1 received/i) { # print "[Update] We have a connection to the internet, continuing...\n"; return 1; } - elsif (`ping 4.2.2.2 -$count 1 -w 500`=~/Reply from|1 received/i) { + elsif (`ping 4.2.2.2 -$count 1 -w 500`=~/TTL|1 received/i) { # print "[Update] We have a connection to the internet, continuing...\n"; return 1; } @@ -2154,4 +2154,4 @@ sub generate_random_password { map $alphanumeric[rand @alphanumeric], 0..$passwordsize; return $randpassword; -} \ No newline at end of file +} From 56babc18012982e6097f78d91fbedc691c80f9f6 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 15 Oct 2016 14:54:57 -0500 Subject: [PATCH 394/693] Update client_process.cpp --- zone/client_process.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 9e7b230d7..407343419 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -858,14 +858,12 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { int32 fac = merch ? merch->GetPrimaryFaction() : 0; int32 cur_fac_level; - if (fac == 0 || sneaking) - { + if (fac == 0 || sneaking) { cur_fac_level = 0; - } - else - { + } + else { cur_fac_level = GetModCharacterFactionLevel(fac); - } + } if (cur_fac_level < ml.faction_required) continue; From 16642b7c4c0b2d7f4e8f533043d3894f1721e73f Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 15 Oct 2016 22:14:03 -0400 Subject: [PATCH 395/693] Filename changes to facilitate future updates --- changelog.txt | 3 +++ common/CMakeLists.txt | 26 ++++++------------------- common/extprofile.h | 2 +- common/{item_base.cpp => item_data.cpp} | 2 +- common/{item_base.h => item_data.h} | 0 common/{item.cpp => item_instance.cpp} | 2 +- common/{item.h => item_instance.h} | 2 +- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/patches/sod.cpp | 2 +- common/patches/sof.cpp | 2 +- common/patches/titanium.cpp | 2 +- common/patches/uf.cpp | 2 +- common/say_link.cpp | 4 ++-- common/shareddb.cpp | 2 +- shared_memory/items.cpp | 2 +- world/client.cpp | 2 +- world/worlddb.cpp | 2 +- zone/bonuses.cpp | 2 +- zone/client.h | 4 ++-- zone/npc.cpp | 4 ++-- zone/perl_questitem.cpp | 2 +- zone/spell_effects.cpp | 2 +- zone/spells.cpp | 2 +- zone/zonedb.cpp | 2 +- zone/zonedump.h | 2 +- 26 files changed, 35 insertions(+), 46 deletions(-) rename common/{item_base.cpp => item_data.cpp} (99%) rename common/{item_base.h => item_data.h} (100%) rename common/{item.cpp => item_instance.cpp} (99%) rename common/{item.h => item_instance.h} (99%) diff --git a/changelog.txt b/changelog.txt index 73be04468..c211d6066 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/15/2016 == +Uleat: Changed filenames to facilitate future inventory naming conventions + == 09/12/2016 == Akkadius: Massive overhaul of the update system and EQEmu Server management utility framework (known as eqemu_update.pl) now known as eqemu_server.pl diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 3ed2862ce..2138c5c9e 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -35,9 +35,10 @@ SET(common_sources faction.cpp guild_base.cpp guilds.cpp +# inventory_slot.cpp ipc_mutex.cpp - item.cpp - item_base.cpp + item_data.cpp + item_instance.cpp light_source.cpp md5.cpp memory_buffer.cpp @@ -155,10 +156,11 @@ SET(common_headers global_define.h guild_base.h guilds.h +# inventory_slot.h ipc_mutex.h - item.h - item_base.h + item_data.h item_fieldlist.h + item_instance.h languages.h light_source.h linked_list.h @@ -212,37 +214,29 @@ SET(common_headers zone_numbers.h patches/patches.h patches/sod.h -# patches/sod_itemfields.h patches/sod_limits.h patches/sod_ops.h patches/sod_structs.h patches/sof.h -# patches/sof_itemfields.h patches/sof_limits.h -# patches/sof_opcode_list.h patches/sof_ops.h patches/sof_structs.h patches/ss_declare.h patches/ss_define.h patches/ss_register.h patches/rof.h -# patches/rof_itemfields.h patches/rof_limits.h patches/rof_ops.h patches/rof_structs.h patches/rof2.h -# patches/rof2_itemfields.h patches/rof2_limits.h patches/rof2_ops.h patches/rof2_structs.h patches/titanium.h -# patches/titanium_itemfields_a.h -# patches/titanium_itemfields_b.h patches/titanium_limits.h patches/titanium_ops.h patches/titanium_structs.h patches/uf.h -# patches/uf_itemfields.h patches/uf_limits.h patches/uf_ops.h patches/uf_structs.h @@ -266,37 +260,29 @@ SET(common_headers SOURCE_GROUP(Patches FILES patches/patches.h patches/sod.h -# patches/sod_itemfields.h patches/sod_limits.h patches/sod_ops.h patches/sod_structs.h patches/sof.h -# patches/sof_itemfields.h patches/sof_limits.h -# patches/sof_opcode_list.h patches/sof_ops.h patches/sof_structs.h patches/ss_declare.h patches/ss_define.h patches/ss_register.h patches/rof.h -# patches/rof_itemfields.h patches/rof_limits.h patches/rof_ops.h patches/rof_structs.h patches/rof2.h -# patches/rof2_itemfields.h patches/rof2_limits.h patches/rof2_ops.h patches/rof2_structs.h patches/titanium.h -# patches/titanium_itemfields_a.h -# patches/titanium_itemfields_b.h patches/titanium_limits.h patches/titanium_ops.h patches/titanium_structs.h patches/uf.h -# patches/uf_itemfields.h patches/uf_limits.h patches/uf_ops.h patches/uf_structs.h diff --git a/common/extprofile.h b/common/extprofile.h index e53480631..72cc987b2 100644 --- a/common/extprofile.h +++ b/common/extprofile.h @@ -19,7 +19,7 @@ #define EXTENDED_PROFILE_H #include "eq_packet_structs.h" -#include "item.h" +#include "item_instance.h" #pragma pack(1) diff --git a/common/item_base.cpp b/common/item_data.cpp similarity index 99% rename from common/item_base.cpp rename to common/item_data.cpp index c2cef6918..fd40c2b7f 100644 --- a/common/item_base.cpp +++ b/common/item_data.cpp @@ -17,7 +17,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "item_base.h" +#include "item_data.h" #include "classes.h" #include "races.h" //#include "deity.h" diff --git a/common/item_base.h b/common/item_data.h similarity index 100% rename from common/item_base.h rename to common/item_data.h diff --git a/common/item.cpp b/common/item_instance.cpp similarity index 99% rename from common/item.cpp rename to common/item_instance.cpp index 61e7f926a..c8a75d0a7 100644 --- a/common/item.cpp +++ b/common/item_instance.cpp @@ -18,7 +18,7 @@ #include "classes.h" #include "global_define.h" -#include "item.h" +#include "item_instance.h" #include "races.h" #include "rulesys.h" #include "shareddb.h" diff --git a/common/item.h b/common/item_instance.h similarity index 99% rename from common/item.h rename to common/item_instance.h index f20b41fac..3ea3ba224 100644 --- a/common/item.h +++ b/common/item_instance.h @@ -29,7 +29,7 @@ class ItemParse; // Parses item packets class EvolveInfo; // Stores information about an evolving item family #include "../common/eq_constants.h" -#include "../common/item_base.h" +#include "../common/item_data.h" #include "../common/timer.h" #include "../common/bodytypes.h" #include "../common/deity.h" diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 8ab38905f..dba092bed 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -29,7 +29,7 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" #include "../string_util.h" -#include "../item.h" +#include "../item_instance.h" #include "rof_structs.h" #include "../rulesys.h" diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index aedd7b592..609fdc123 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -29,7 +29,7 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" #include "../string_util.h" -#include "../item.h" +#include "../item_instance.h" #include "rof2_structs.h" #include "../rulesys.h" diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index c1d573020..3b02cbbcb 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -29,7 +29,7 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" #include "../string_util.h" -#include "../item.h" +#include "../item_instance.h" #include "sod_structs.h" #include "../rulesys.h" diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index bfad8d296..0d1afa000 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -29,7 +29,7 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" #include "../string_util.h" -#include "../item.h" +#include "../item_instance.h" #include "sof_structs.h" #include "../rulesys.h" diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 72b492eeb..63feea81f 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -30,7 +30,7 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" #include "../string_util.h" -#include "../item.h" +#include "../item_instance.h" #include "titanium_structs.h" #include diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index ba5bf7622..0436f5af4 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -29,7 +29,7 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" #include "../string_util.h" -#include "../item.h" +#include "../item_instance.h" #include "uf_structs.h" #include "../rulesys.h" diff --git a/common/say_link.cpp b/common/say_link.cpp index 3c9fe7c6e..2a4065403 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -21,8 +21,8 @@ #include "emu_constants.h" #include "string_util.h" -#include "item.h" -#include "item_base.h" +#include "item_instance.h" +#include "item_data.h" #include "../zone/zonedb.h" diff --git a/common/shareddb.cpp b/common/shareddb.cpp index fd89831c0..8e55269e7 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -29,7 +29,7 @@ #include "faction.h" #include "features.h" #include "ipc_mutex.h" -#include "item.h" +#include "item_instance.h" #include "loottable.h" #include "memory_mapped_file.h" #include "mysql.h" diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index e4c938af2..b58382420 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -22,7 +22,7 @@ #include "../common/ipc_mutex.h" #include "../common/memory_mapped_file.h" #include "../common/eqemu_exception.h" -#include "../common/item_base.h" +#include "../common/item_data.h" void LoadItems(SharedDatabase *database, const std::string &prefix) { EQEmu::IPCMutex mutex("items"); diff --git a/world/client.cpp b/world/client.cpp index 8d036827c..ff3c0ce9a 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -25,7 +25,7 @@ #include "../common/eq_packet_structs.h" #include "../common/packet_dump.h" #include "../common/eq_stream_intf.h" -#include "../common/item.h" +#include "../common/item_instance.h" #include "../common/races.h" #include "../common/classes.h" #include "../common/languages.h" diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 8d65f7a78..def22adf4 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -20,7 +20,7 @@ //#include "../common/item.h" #include "../common/string_util.h" #include "../common/eq_packet_structs.h" -#include "../common/item.h" +#include "../common/item_instance.h" #include "../common/rulesys.h" #include #include diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 1a49aaf66..a898e02ec 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -17,7 +17,7 @@ */ #include "../common/classes.h" #include "../common/global_define.h" -#include "../common/item.h" +#include "../common/item_instance.h" #include "../common/rulesys.h" #include "../common/skills.h" #include "../common/spdat.h" diff --git a/zone/client.h b/zone/client.h index da2188fc7..75ce82bf5 100644 --- a/zone/client.h +++ b/zone/client.h @@ -45,9 +45,9 @@ namespace EQEmu #include "../common/extprofile.h" #include "../common/races.h" #include "../common/seperator.h" -#include "../common/item.h" +#include "../common/item_instance.h" #include "../common/guilds.h" -#include "../common/item_base.h" +#include "../common/item_data.h" #include "common.h" #include "merc.h" diff --git a/zone/npc.cpp b/zone/npc.cpp index ecc3bf101..d958ff598 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -26,8 +26,8 @@ #include "../common/string_util.h" #include "../common/emu_versions.h" #include "../common/features.h" -#include "../common/item.h" -#include "../common/item_base.h" +#include "../common/item_instance.h" +#include "../common/item_data.h" #include "../common/linked_list.h" #include "../common/servertalk.h" #include "../common/say_link.h" diff --git a/zone/perl_questitem.cpp b/zone/perl_questitem.cpp index fa186a9b5..053748e97 100644 --- a/zone/perl_questitem.cpp +++ b/zone/perl_questitem.cpp @@ -26,7 +26,7 @@ #undef seed #endif -#include "../common/item.h" +#include "../common/item_instance.h" #ifdef THIS /* this macro seems to leak out on some systems */ #undef THIS diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 8f66345d2..564a9756a 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -20,7 +20,7 @@ #include "../common/bodytypes.h" #include "../common/classes.h" #include "../common/global_define.h" -#include "../common/item.h" +#include "../common/item_instance.h" #include "../common/rulesys.h" #include "../common/skills.h" #include "../common/spdat.h" diff --git a/zone/spells.cpp b/zone/spells.cpp index c818c8e90..a7e37048e 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -70,7 +70,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include "../common/classes.h" #include "../common/global_define.h" #include "../common/eqemu_logsys.h" -#include "../common/item.h" +#include "../common/item_instance.h" #include "../common/rulesys.h" #include "../common/skills.h" #include "../common/spdat.h" diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 7f86f5110..bf9452c4e 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1,7 +1,7 @@ #include "../common/eqemu_logsys.h" #include "../common/extprofile.h" -#include "../common/item.h" +#include "../common/item_instance.h" #include "../common/rulesys.h" #include "../common/string_util.h" diff --git a/zone/zonedump.h b/zone/zonedump.h index 6782881fe..20412ed70 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -28,7 +28,7 @@ spawn2 mediumblob, npcs mediumblob, npc_loot mediumblob, gmspawntype mediumblob, #define ZONEDUMP_H #include "../common/faction.h" #include "../common/eq_packet_structs.h" -#include "../common/item.h" +#include "../common/item_instance.h" #pragma pack(1) From e29ec1675990499439e0eed785d65e5253ba1d41 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 15 Oct 2016 22:23:50 -0400 Subject: [PATCH 396/693] Missed 2 reference changes --- tests/fixed_memory_test.h | 2 +- world/worlddb.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fixed_memory_test.h b/tests/fixed_memory_test.h index 06b529f3c..244394ce5 100644 --- a/tests/fixed_memory_test.h +++ b/tests/fixed_memory_test.h @@ -21,7 +21,7 @@ #include "cppunit/cpptest.h" #include "../common/fixed_memory_hash_set.h" -#include "../common/item.h" +#include "../common/item_instance.h" class FixedMemoryHashTest : public Test::Suite { typedef void(FixedMemoryHashTest::*TestFunction)(void); diff --git a/world/worlddb.cpp b/world/worlddb.cpp index def22adf4..205663ea5 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -17,7 +17,7 @@ */ #include "worlddb.h" -//#include "../common/item.h" +//#include "../common/item_instance.h" #include "../common/string_util.h" #include "../common/eq_packet_structs.h" #include "../common/item_instance.h" From 8b5dd58e96ec38da88ad325485031d2f60c175fa Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 16 Oct 2016 05:10:54 -0400 Subject: [PATCH 397/693] Renamed struct EQEmu::ItemBase to EQEmu::ItemData and class ItemInst to EQEmu::ItemInstance --- changelog.txt | 3 + common/database.cpp | 2 +- common/eq_packet_structs.h | 2 +- common/item_data.cpp | 14 +- common/item_data.h | 46 +-- common/item_instance.cpp | 352 ++++++++++----------- common/item_instance.h | 523 ++++++++++++++++--------------- common/patches/rof.cpp | 12 +- common/patches/rof2.cpp | 12 +- common/patches/rof2_structs.h | 2 +- common/patches/rof_structs.h | 2 +- common/patches/sod.cpp | 12 +- common/patches/sod_structs.h | 2 +- common/patches/sof.cpp | 12 +- common/patches/titanium.cpp | 12 +- common/patches/uf.cpp | 14 +- common/patches/uf_structs.h | 2 +- common/say_link.cpp | 4 +- common/say_link.h | 12 +- common/shareddb.cpp | 74 ++--- common/shareddb.h | 26 +- shared_memory/items.cpp | 2 +- tests/fixed_memory_test.h | 46 +-- world/worlddb.cpp | 4 +- zone/aa.cpp | 2 +- zone/attack.cpp | 44 +-- zone/bonuses.cpp | 40 +-- zone/bot.cpp | 134 ++++---- zone/bot.h | 10 +- zone/bot_command.cpp | 16 +- zone/bot_database.cpp | 4 +- zone/bot_database.h | 8 +- zone/client.cpp | 44 +-- zone/client.h | 60 ++-- zone/client_mods.cpp | 10 +- zone/client_packet.cpp | 136 ++++---- zone/client_process.cpp | 28 +- zone/command.cpp | 26 +- zone/common.h | 8 +- zone/corpse.cpp | 24 +- zone/corpse.h | 8 +- zone/doors.cpp | 2 +- zone/effects.cpp | 2 +- zone/embparser.cpp | 56 ++-- zone/embparser.h | 22 +- zone/embparser_api.cpp | 2 +- zone/embxs.cpp | 2 +- zone/entity.cpp | 6 +- zone/forage.cpp | 14 +- zone/guild_mgr.cpp | 24 +- zone/guild_mgr.h | 2 +- zone/inventory.cpp | 174 +++++----- zone/loottables.cpp | 16 +- zone/lua_client.cpp | 4 +- zone/lua_inventory.cpp | 4 +- zone/lua_item.cpp | 2 +- zone/lua_item.h | 12 +- zone/lua_iteminst.cpp | 4 +- zone/lua_iteminst.h | 20 +- zone/lua_parser.cpp | 10 +- zone/lua_parser.h | 16 +- zone/lua_parser_events.cpp | 34 +- zone/lua_parser_events.h | 20 +- zone/merc.cpp | 16 +- zone/merc.h | 4 +- zone/mob.cpp | 40 +-- zone/mob.h | 38 +-- zone/mod_functions.cpp | 22 +- zone/npc.cpp | 4 +- zone/npc.h | 8 +- zone/object.cpp | 36 +-- zone/object.h | 22 +- zone/perl_client.cpp | 8 +- zone/perl_mob.cpp | 8 +- zone/perl_questitem.cpp | 50 +-- zone/pets.cpp | 4 +- zone/quest_interface.h | 14 +- zone/quest_parser_collection.cpp | 6 +- zone/quest_parser_collection.h | 14 +- zone/questmgr.cpp | 24 +- zone/questmgr.h | 18 +- zone/special_attacks.cpp | 72 ++--- zone/spell_effects.cpp | 38 +-- zone/spells.cpp | 18 +- zone/tasks.cpp | 6 +- zone/tasks.h | 8 +- zone/tradeskills.cpp | 54 ++-- zone/trading.cpp | 112 +++---- zone/tribute.cpp | 4 +- zone/tune.cpp | 8 +- zone/zone.cpp | 8 +- zone/zonedb.cpp | 22 +- zone/zonedb.h | 19 +- 93 files changed, 1492 insertions(+), 1455 deletions(-) diff --git a/changelog.txt b/changelog.txt index f3a6c326b..50640ff55 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/16/2016 == +Uleat: Renamed struct EQEmu::ItemBase to EQEmu::ItemData and class ItemInst to EQEmu::ItemInstance. + == 10/15/2016 == Uleat: Changed filenames to facilitate future inventory naming conventions diff --git a/common/database.cpp b/common/database.cpp index 41220b4d9..93bbe7e0c 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -701,7 +701,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven /* Insert starting inventory... */ std::string invquery; for (int16 i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::BANK_BAGS_END;) { - const ItemInst* newinv = inv->GetItem(i); + const EQEmu::ItemInstance* newinv = inv->GetItem(i); if (newinv) { invquery = StringFormat("INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)", charid, i, newinv->GetItem()->ID, newinv->GetCharges(), newinv->GetColor()); diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index fec5af412..5569c86e0 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -2071,7 +2071,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - EQEmu::ItemBase item; + EQEmu::ItemData item; uint8 iss_unknown001[6]; };*/ diff --git a/common/item_data.cpp b/common/item_data.cpp index fd40c2b7f..3286bf97e 100644 --- a/common/item_data.cpp +++ b/common/item_data.cpp @@ -167,7 +167,7 @@ uint8 EQEmu::item::ConvertAugTypeBitToAugType(uint32 aug_type_bit) } } -bool EQEmu::ItemBase::IsEquipable(uint16 race_id, uint16 class_id) +bool EQEmu::ItemData::IsEquipable(uint16 race_id, uint16 class_id) const { if (!(Races & GetPlayerRaceBit(race_id))) return false; @@ -178,32 +178,32 @@ bool EQEmu::ItemBase::IsEquipable(uint16 race_id, uint16 class_id) return true; } -bool EQEmu::ItemBase::IsClassCommon() +bool EQEmu::ItemData::IsClassCommon() const { return (ItemClass == item::ItemClassCommon); } -bool EQEmu::ItemBase::IsClassBag() +bool EQEmu::ItemData::IsClassBag() const { return (ItemClass == item::ItemClassBag); } -bool EQEmu::ItemBase::IsClassBook() +bool EQEmu::ItemData::IsClassBook() const { return (ItemClass == item::ItemClassBook); } -bool EQEmu::ItemBase::IsType1HWeapon() +bool EQEmu::ItemData::IsType1HWeapon() const { return ((ItemType == item::ItemType1HBlunt) || (ItemType == item::ItemType1HSlash) || (ItemType == item::ItemType1HPiercing)); } -bool EQEmu::ItemBase::IsType2HWeapon() +bool EQEmu::ItemData::IsType2HWeapon() const { return ((ItemType == item::ItemType2HBlunt) || (ItemType == item::ItemType2HSlash) || (ItemType == item::ItemType2HPiercing)); } -bool EQEmu::ItemBase::IsTypeShield() +bool EQEmu::ItemData::IsTypeShield() const { return (ItemType == item::ItemTypeShield); } diff --git a/common/item_data.h b/common/item_data.h index 1ecba6734..ce3eccefa 100644 --- a/common/item_data.h +++ b/common/item_data.h @@ -17,8 +17,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA */ -#ifndef COMMON_ITEM_BASE_H -#define COMMON_ITEM_BASE_H +#ifndef COMMON_ITEM_DATA_H +#define COMMON_ITEM_DATA_H /* @@ -50,17 +50,6 @@ namespace EQEmu { namespace item { - enum ItemAttributeBit : uint32 { - bit_ItemAttributeNone = 0x00000000, - bit_ItemAttributeLore = 0x00000001, - bit_ItemAttributeArtifact = 0x00000002, - bit_ItemAttributeSummoned = 0x00000004, - bit_ItemAttributeMagic = 0x00000008, - bit_ItemAttributeAugment = 0x00000010, - bit_ItemAttributePendingLore = 0x00000020, - bit_ItemAttributeUnknown = 0xFFFFFFFF - }; - enum ItemClass { ItemClassCommon = 0, ItemClassBag, @@ -354,8 +343,8 @@ namespace EQEmu //ProcRate }; - extern uint32 ConvertAugTypeToAugTypeBit(uint8 aug_type); - extern uint8 ConvertAugTypeBitToAugType(uint32 aug_type_bit); + uint32 ConvertAugTypeToAugTypeBit(uint8 aug_type); + uint8 ConvertAugTypeBitToAugType(uint32 aug_type_bit); } /*item*/ @@ -364,10 +353,9 @@ namespace EQEmu const void * inst; }; - struct ItemBase { + struct ItemData { // Non packet based fields uint8 MinStatus; - uint8 ItemDataType; // memset to item::ItemDataBase ('0') during mmf load // Packet based fields uint8 ItemClass; // Item Type: 0=common, 1=container, 2=book @@ -543,23 +531,15 @@ namespace EQEmu char ScrollName[65]; //BardName - bool IsEquipable(uint16 Race, uint16 Class); - bool IsClassCommon(); - bool IsClassBag(); - bool IsClassBook(); - bool IsType1HWeapon(); - bool IsType2HWeapon(); - bool IsTypeShield(); - - bool IsEquipable(uint16 Race, uint16 Class) const { return const_cast(this)->IsEquipable(Race, Class); } - bool IsClassCommon() const { return const_cast(this)->IsClassCommon(); } - bool IsClassBag() const { return const_cast(this)->IsClassBag(); } - bool IsClassBook() const { return const_cast(this)->IsClassBook(); } - bool IsType1HWeapon() const { return const_cast(this)->IsType1HWeapon(); } - bool IsType2HWeapon() const { return const_cast(this)->IsType2HWeapon(); } - bool IsTypeShield() const { return const_cast(this)->IsTypeShield(); } + bool IsEquipable(uint16 Race, uint16 Class) const; + bool IsClassCommon() const; + bool IsClassBag() const; + bool IsClassBook() const; + bool IsType1HWeapon() const; + bool IsType2HWeapon() const; + bool IsTypeShield() const; }; } /*EQEmu*/ -#endif /*COMMON_ITEM_BASE_H*/ +#endif /*COMMON_ITEM_DATA_H*/ diff --git a/common/item_instance.cpp b/common/item_instance.cpp index c8a75d0a7..c8beddd3c 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -30,7 +30,7 @@ #include -std::list dirty_inst; +std::list dirty_inst; int32 NextItemInstSerialNumber = 1; static inline int32 GetNextItemInstSerialNumber() { @@ -66,41 +66,41 @@ ItemInstQueue::~ItemInstQueue() } // Put item onto back of queue -void ItemInstQueue::push(ItemInst* inst) +void ItemInstQueue::push(EQEmu::ItemInstance* inst) { m_list.push_back(inst); } // Put item onto front of queue -void ItemInstQueue::push_front(ItemInst* inst) +void ItemInstQueue::push_front(EQEmu::ItemInstance* inst) { m_list.push_front(inst); } // Remove item from front of queue -ItemInst* ItemInstQueue::pop() +EQEmu::ItemInstance* ItemInstQueue::pop() { if (m_list.empty()) return nullptr; - ItemInst* inst = m_list.front(); + EQEmu::ItemInstance* inst = m_list.front(); m_list.pop_front(); return inst; } // Remove item from back of queue -ItemInst* ItemInstQueue::pop_back() +EQEmu::ItemInstance* ItemInstQueue::pop_back() { if (m_list.empty()) return nullptr; - ItemInst* inst = m_list.back(); + EQEmu::ItemInstance* inst = m_list.back(); m_list.pop_back(); return inst; } // Look at item at front of queue -ItemInst* ItemInstQueue::peek_front() const +EQEmu::ItemInstance* ItemInstQueue::peek_front() const { return (m_list.empty()) ? nullptr : m_list.front(); } @@ -146,16 +146,16 @@ void Inventory::CleanDirty() { dirty_inst.clear(); } -void Inventory::MarkDirty(ItemInst *inst) { +void Inventory::MarkDirty(EQEmu::ItemInstance *inst) { if (inst) { dirty_inst.push_back(inst); } } // Retrieve item at specified slot; returns false if item not found -ItemInst* Inventory::GetItem(int16 slot_id) const +EQEmu::ItemInstance* Inventory::GetItem(int16 slot_id) const { - ItemInst* result = nullptr; + EQEmu::ItemInstance* result = nullptr; // Cursor if (slot_id == EQEmu::legacy::SlotCursor) { @@ -188,35 +188,35 @@ ItemInst* Inventory::GetItem(int16 slot_id) const // Inner bag slots else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { // Trade bag slots - ItemInst* inst = _GetItem(m_trade, Inventory::CalcSlotId(slot_id)); + EQEmu::ItemInstance* inst = _GetItem(m_trade, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { // Shared Bank bag slots - ItemInst* inst = _GetItem(m_shbank, Inventory::CalcSlotId(slot_id)); + EQEmu::ItemInstance* inst = _GetItem(m_shbank, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { // Bank bag slots - ItemInst* inst = _GetItem(m_bank, Inventory::CalcSlotId(slot_id)); + EQEmu::ItemInstance* inst = _GetItem(m_bank, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { // Cursor bag slots - ItemInst* inst = m_cursor.peek_front(); + EQEmu::ItemInstance* inst = m_cursor.peek_front(); if (inst && inst->IsClassBag()) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } } else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { // Personal inventory bag slots - ItemInst* inst = _GetItem(m_inv, Inventory::CalcSlotId(slot_id)); + EQEmu::ItemInstance* inst = _GetItem(m_inv, Inventory::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); } @@ -226,13 +226,13 @@ ItemInst* Inventory::GetItem(int16 slot_id) const } // Retrieve item at specified position within bag -ItemInst* Inventory::GetItem(int16 slot_id, uint8 bagidx) const +EQEmu::ItemInstance* Inventory::GetItem(int16 slot_id, uint8 bagidx) const { return GetItem(Inventory::CalcSlotId(slot_id, bagidx)); } // Put an item snto specified slot -int16 Inventory::PutItem(int16 slot_id, const ItemInst& inst) +int16 Inventory::PutItem(int16 slot_id, const EQEmu::ItemInstance& inst) { // Clean up item already in slot (if exists) DeleteItem(slot_id); @@ -247,13 +247,13 @@ int16 Inventory::PutItem(int16 slot_id, const ItemInst& inst) return _PutItem(slot_id, inst.Clone()); } -int16 Inventory::PushCursor(const ItemInst& inst) +int16 Inventory::PushCursor(const EQEmu::ItemInstance& inst) { m_cursor.push(inst.Clone()); return EQEmu::legacy::SlotCursor; } -ItemInst* Inventory::GetCursorItem() +EQEmu::ItemInstance* Inventory::GetCursorItem() { return m_cursor.peek_front(); } @@ -262,8 +262,8 @@ ItemInst* Inventory::GetCursorItem() bool Inventory::SwapItem(int16 slot_a, int16 slot_b) { // Temp holding areas for a and b - ItemInst* inst_a = GetItem(slot_a); - ItemInst* inst_b = GetItem(slot_b); + EQEmu::ItemInstance* inst_a = GetItem(slot_a); + EQEmu::ItemInstance* inst_b = GetItem(slot_b); if (inst_a) { if (!inst_a->IsSlotAllowed(slot_b)) { return false; } } if (inst_b) { if (!inst_b->IsSlotAllowed(slot_a)) { return false; } } @@ -278,7 +278,7 @@ bool Inventory::SwapItem(int16 slot_a, int16 slot_b) bool Inventory::DeleteItem(int16 slot_id, uint8 quantity) { // Pop item out of inventory map (or queue) - ItemInst* item_to_delete = PopItem(slot_id); + EQEmu::ItemInstance* item_to_delete = PopItem(slot_id); // Determine if object should be fully deleted, or // just a quantity of charges of the item can be deleted @@ -312,12 +312,12 @@ bool Inventory::DeleteItem(int16 slot_id, uint8 quantity) // Checks All items in a bag for No Drop bool Inventory::CheckNoDrop(int16 slot_id) { - ItemInst* inst = GetItem(slot_id); + EQEmu::ItemInstance* inst = GetItem(slot_id); if (!inst) return false; if (!inst->GetItem()->NoDrop) return true; if (inst->GetItem()->ItemClass == 1) { for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { - ItemInst* bagitem = GetItem(Inventory::CalcSlotId(slot_id, i)); + EQEmu::ItemInstance* bagitem = GetItem(Inventory::CalcSlotId(slot_id, i)); if (bagitem && !bagitem->GetItem()->NoDrop) return true; } @@ -327,9 +327,9 @@ bool Inventory::CheckNoDrop(int16 slot_id) { // Remove item from bucket without memory delete // Returns item pointer if full delete was successful -ItemInst* Inventory::PopItem(int16 slot_id) +EQEmu::ItemInstance* Inventory::PopItem(int16 slot_id) { - ItemInst* p = nullptr; + EQEmu::ItemInstance* p = nullptr; if (slot_id == EQEmu::legacy::SlotCursor) { p = m_cursor.pop(); @@ -360,7 +360,7 @@ ItemInst* Inventory::PopItem(int16 slot_id) } else { // Is slot inside bag? - ItemInst* baginst = GetItem(Inventory::CalcSlotId(slot_id)); + EQEmu::ItemInstance* baginst = GetItem(Inventory::CalcSlotId(slot_id)); if (baginst != nullptr && baginst->IsClassBag()) { p = baginst->PopItem(Inventory::CalcBagIdx(slot_id)); } @@ -370,13 +370,13 @@ ItemInst* Inventory::PopItem(int16 slot_id) return p; } -bool Inventory::HasSpaceForItem(const EQEmu::ItemBase *ItemToTry, int16 Quantity) { +bool Inventory::HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity) { if (ItemToTry->Stackable) { for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { - ItemInst* InvItem = GetItem(i); + EQEmu::ItemInstance* InvItem = GetItem(i); if (InvItem && (InvItem->GetItem()->ID == ItemToTry->ID) && (InvItem->GetCharges() < InvItem->GetItem()->StackSize)) { @@ -413,7 +413,7 @@ bool Inventory::HasSpaceForItem(const EQEmu::ItemBase *ItemToTry, int16 Quantity for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { - ItemInst* InvItem = GetItem(i); + EQEmu::ItemInstance* InvItem = GetItem(i); if (!InvItem) { @@ -625,7 +625,7 @@ int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, boo if (!for_bag) { for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { - const ItemInst* inst = GetItem(i); + const EQEmu::ItemInstance* inst = GetItem(i); if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size) { if (inst->GetItem()->BagType == EQEmu::item::BagTypeQuiver && inst->GetItem()->ItemType != EQEmu::item::ItemTypeArrow) @@ -658,7 +658,7 @@ int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, boo } // This is a mix of HasSpaceForItem and FindFreeSlot..due to existing coding behavior, it was better to add a new helper function... -int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { +int16 Inventory::FindFreeSlotForTradeItem(const EQEmu::ItemInstance* inst) { // Do not arbitrarily use this function..it is designed for use with Client::ResetTrade() and Client::FinishTrade(). // If you have a need, use it..but, understand it is not a compatible replacement for Inventory::FindFreeSlot(). // @@ -680,7 +680,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 2: find partial room for stackables if (inst->IsStackable()) { for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const ItemInst* main_inst = m_inv[free_slot]; + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst) continue; @@ -690,14 +690,14 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { } for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const ItemInst* main_inst = m_inv[free_slot]; + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst) continue; if (main_inst->IsClassBag()) { // if item-specific containers already have bad items, we won't fix it here... for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { - const ItemInst* sub_inst = main_inst->GetItem(free_bag_slot); + const EQEmu::ItemInstance* sub_inst = main_inst->GetItem(free_bag_slot); if (!sub_inst) continue; @@ -712,7 +712,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 3a: find room for container-specific items (ItemClassArrow) if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeArrow) { for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const ItemInst* main_inst = m_inv[free_slot]; + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeQuiver) || !main_inst->IsClassBag()) continue; @@ -727,7 +727,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 3b: find room for container-specific items (ItemClassSmallThrowing) if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeSmallThrowing) { for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const ItemInst* main_inst = m_inv[free_slot]; + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeBandolier) || !main_inst->IsClassBag()) continue; @@ -741,14 +741,14 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) { // step 4: just find an empty slot for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const ItemInst* main_inst = m_inv[free_slot]; + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst) return free_slot; } for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const ItemInst* main_inst = m_inv[free_slot]; + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; if (main_inst && main_inst->IsClassBag()) { if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeBandolier) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeQuiver)) @@ -903,7 +903,7 @@ uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) } } -bool Inventory::CanItemFitInContainer(const EQEmu::ItemBase *ItemToTry, const EQEmu::ItemBase *Container) { +bool Inventory::CanItemFitInContainer(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container) { if (!ItemToTry || !Container) return false; @@ -959,7 +959,7 @@ bool Inventory::SupportsContainers(int16 slot_id) return false; } -int Inventory::GetSlotByItemInst(ItemInst *inst) { +int Inventory::GetSlotByItemInst(EQEmu::ItemInstance *inst) { if (!inst) return INVALID_INDEX; @@ -1066,9 +1066,9 @@ void Inventory::dumpSharedBankItems() { dumpItemCollection(m_shbank); } -int Inventory::GetSlotByItemInstCollection(const std::map &collection, ItemInst *inst) { +int Inventory::GetSlotByItemInstCollection(const std::map &collection, EQEmu::ItemInstance *inst) { for (auto iter = collection.begin(); iter != collection.end(); ++iter) { - ItemInst *t_inst = iter->second; + EQEmu::ItemInstance *t_inst = iter->second; if (t_inst == inst) { return iter->first; } @@ -1085,7 +1085,7 @@ int Inventory::GetSlotByItemInstCollection(const std::map &col return -1; } -void Inventory::dumpItemCollection(const std::map &collection) +void Inventory::dumpItemCollection(const std::map &collection) { for (auto it = collection.cbegin(); it != collection.cend(); ++it) { auto inst = it->second; @@ -1099,14 +1099,14 @@ void Inventory::dumpItemCollection(const std::map &collection) } } -void Inventory::dumpBagContents(ItemInst *inst, std::map::const_iterator *it) +void Inventory::dumpBagContents(EQEmu::ItemInstance *inst, std::map::const_iterator *it) { if (!inst || !inst->IsClassBag()) return; // Go through bag, if bag for (auto itb = inst->_cbegin(); itb != inst->_cend(); ++itb) { - ItemInst* baginst = itb->second; + EQEmu::ItemInstance* baginst = itb->second; if (!baginst || !baginst->GetItem()) continue; @@ -1118,7 +1118,7 @@ void Inventory::dumpBagContents(ItemInst *inst, std::map::cons } // Internal Method: Retrieves item within an inventory bucket -ItemInst* Inventory::_GetItem(const std::map& bucket, int16 slot_id) const +EQEmu::ItemInstance* Inventory::_GetItem(const std::map& bucket, int16 slot_id) const { auto it = bucket.find(slot_id); if (it != bucket.end()) { @@ -1131,7 +1131,7 @@ ItemInst* Inventory::_GetItem(const std::map& bucket, int16 sl // Internal Method: "put" item into bucket, without regard for what is currently in bucket // Assumes item has already been allocated -int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst) +int16 Inventory::_PutItem(int16 slot_id, EQEmu::ItemInstance* inst) { // What happens here when we _PutItem(MainCursor)? Bad things..really bad things... // @@ -1178,7 +1178,7 @@ int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst) else { // Slot must be within a bag parentSlot = Inventory::CalcSlotId(slot_id); - ItemInst* baginst = GetItem(parentSlot); // Get parent bag + EQEmu::ItemInstance* baginst = GetItem(parentSlot); // Get parent bag if (baginst && baginst->IsClassBag()) { baginst->_PutItem(Inventory::CalcBagIdx(slot_id), inst); @@ -1195,7 +1195,7 @@ int16 Inventory::_PutItem(int16 slot_id, ItemInst* inst) } // Internal Method: Checks an inventory bucket for a particular item -int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, uint8 quantity) +int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, uint8 quantity) { uint32 quantity_found = 0; @@ -1288,7 +1288,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) } // Internal Method: Checks an inventory bucket for a particular item -int16 Inventory::_HasItemByUse(std::map& bucket, uint8 use, uint8 quantity) +int16 Inventory::_HasItemByUse(std::map& bucket, uint8 use, uint8 quantity) { uint32 quantity_found = 0; @@ -1354,7 +1354,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) return INVALID_INDEX; } -int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 loregroup) +int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 loregroup) { for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { auto inst = iter->second; @@ -1438,12 +1438,12 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) // -// class ItemInst +// class EQEmu::ItemInstance // -ItemInst::ItemInst(const EQEmu::ItemBase* item, int16 charges) { +EQEmu::ItemInstance::ItemInstance(const ItemData* item, int16 charges) { m_use_type = ItemInstNormal; if(item) { - m_item = new EQEmu::ItemBase(*item); + m_item = new ItemData(*item); } else { m_item = nullptr; } @@ -1470,11 +1470,11 @@ ItemInst::ItemInst(const EQEmu::ItemBase* item, int16 charges) { m_recast_timestamp = 0; } -ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) { +EQEmu::ItemInstance::ItemInstance(SharedDatabase *db, uint32 item_id, int16 charges) { m_use_type = ItemInstNormal; m_item = db->GetItem(item_id); if(m_item) { - m_item = new EQEmu::ItemBase(*m_item); + m_item = new ItemData(*m_item); } else { m_item = nullptr; @@ -1503,7 +1503,7 @@ ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) { m_recast_timestamp = 0; } -ItemInst::ItemInst(ItemInstTypes use_type) { +EQEmu::ItemInstance::ItemInstance(ItemInstTypes use_type) { m_use_type = use_type; m_item = nullptr; m_charges = 0; @@ -1524,12 +1524,12 @@ ItemInst::ItemInst(ItemInstTypes use_type) { m_recast_timestamp = 0; } -// Make a copy of an ItemInst object -ItemInst::ItemInst(const ItemInst& copy) +// Make a copy of an EQEmu::ItemInstance object +EQEmu::ItemInstance::ItemInstance(const ItemInstance& copy) { m_use_type=copy.m_use_type; if(copy.m_item) - m_item = new EQEmu::ItemBase(*copy.m_item); + m_item = new ItemData(*copy.m_item); else m_item = nullptr; @@ -1542,8 +1542,8 @@ ItemInst::ItemInst(const ItemInst& copy) m_merchantcount=copy.m_merchantcount; // Copy container contents for (auto it = copy.m_contents.begin(); it != copy.m_contents.end(); ++it) { - ItemInst* inst_old = it->second; - ItemInst* inst_new = nullptr; + ItemInstance* inst_old = it->second; + ItemInstance* inst_new = nullptr; if (inst_old) { inst_new = inst_old->Clone(); @@ -1565,7 +1565,7 @@ ItemInst::ItemInst(const ItemInst& copy) m_evolveLvl = copy.m_evolveLvl; m_activated = copy.m_activated; if (copy.m_scaledItem) - m_scaledItem = new EQEmu::ItemBase(*copy.m_scaledItem); + m_scaledItem = new ItemData(*copy.m_scaledItem); else m_scaledItem = nullptr; @@ -1582,7 +1582,7 @@ ItemInst::ItemInst(const ItemInst& copy) } // Clean up container contents -ItemInst::~ItemInst() +EQEmu::ItemInstance::~ItemInstance() { Clear(); safe_delete(m_item); @@ -1591,7 +1591,7 @@ ItemInst::~ItemInst() } // Query item type -bool ItemInst::IsType(EQEmu::item::ItemClass item_class) const +bool EQEmu::ItemInstance::IsType(EQEmu::item::ItemClass item_class) const { // IsType() does not protect against 'm_item = nullptr' @@ -1605,23 +1605,23 @@ bool ItemInst::IsType(EQEmu::item::ItemClass item_class) const return (m_item->ItemClass == item_class); } -bool ItemInst::IsClassCommon() +bool EQEmu::ItemInstance::IsClassCommon() const { return (m_item && m_item->IsClassCommon()); } -bool ItemInst::IsClassBag() +bool EQEmu::ItemInstance::IsClassBag() const { return (m_item && m_item->IsClassBag()); } -bool ItemInst::IsClassBook() +bool EQEmu::ItemInstance::IsClassBook() const { return (m_item && m_item->IsClassBook()); } // Is item stackable? -bool ItemInst::IsStackable() const +bool EQEmu::ItemInstance::IsStackable() const { if (!m_item) return false; @@ -1629,7 +1629,7 @@ bool ItemInst::IsStackable() const return m_item->Stackable; } -bool ItemInst::IsCharged() const +bool EQEmu::ItemInstance::IsCharged() const { if (!m_item) return false; @@ -1641,7 +1641,7 @@ bool ItemInst::IsCharged() const } // Can item be equipped? -bool ItemInst::IsEquipable(uint16 race, uint16 class_) const +bool EQEmu::ItemInstance::IsEquipable(uint16 race, uint16 class_) const { if (!m_item || (m_item->Slots == 0)) return false; @@ -1650,7 +1650,7 @@ bool ItemInst::IsEquipable(uint16 race, uint16 class_) const } // Can equip at this slot? -bool ItemInst::IsEquipable(int16 slot_id) const +bool EQEmu::ItemInstance::IsEquipable(int16 slot_id) const { if (!m_item) return false; @@ -1668,7 +1668,7 @@ bool ItemInst::IsEquipable(int16 slot_id) const return false; } -bool ItemInst::IsAugmentable() const +bool EQEmu::ItemInstance::IsAugmentable() const { if (!m_item) return false; @@ -1681,7 +1681,7 @@ bool ItemInst::IsAugmentable() const return false; } -bool ItemInst::AvailableWearSlot(uint32 aug_wear_slots) const { +bool EQEmu::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const { // TODO: check to see if incoming 'aug_wear_slots' "switches" bit assignments like above... // (if wrong, would only affect MainAmmo and MainPowerSource augments) if (!m_item || !m_item->IsClassCommon()) @@ -1698,7 +1698,7 @@ bool ItemInst::AvailableWearSlot(uint32 aug_wear_slots) const { return (index < 23) ? true : false; } -int8 ItemInst::AvailableAugmentSlot(int32 augtype) const +int8 EQEmu::ItemInstance::AvailableAugmentSlot(int32 augtype) const { if (!m_item || !m_item->IsClassCommon()) return INVALID_INDEX; @@ -1713,7 +1713,7 @@ int8 ItemInst::AvailableAugmentSlot(int32 augtype) const return (index < EQEmu::legacy::ITEM_COMMON_SIZE) ? index : INVALID_INDEX; } -bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const +bool EQEmu::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const { if (!m_item || !m_item->IsClassCommon()) return false; @@ -1725,7 +1725,7 @@ bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const } // Retrieve item inside container -ItemInst* ItemInst::GetItem(uint8 index) const +EQEmu::ItemInstance* EQEmu::ItemInstance::GetItem(uint8 index) const { auto it = m_contents.find(index); if (it != m_contents.end()) { @@ -1735,16 +1735,16 @@ ItemInst* ItemInst::GetItem(uint8 index) const return nullptr; } -uint32 ItemInst::GetItemID(uint8 slot) const +uint32 EQEmu::ItemInstance::GetItemID(uint8 slot) const { - ItemInst *item = GetItem(slot); + ItemInstance *item = GetItem(slot); if (item) return item->GetID(); return NO_ITEM; } -void ItemInst::PutItem(uint8 index, const ItemInst& inst) +void EQEmu::ItemInstance::PutItem(uint8 index, const ItemInstance& inst) { // Clean up item already in slot (if exists) DeleteItem(index); @@ -1754,19 +1754,19 @@ void ItemInst::PutItem(uint8 index, const ItemInst& inst) } // Remove item inside container -void ItemInst::DeleteItem(uint8 index) +void EQEmu::ItemInstance::DeleteItem(uint8 index) { - ItemInst* inst = PopItem(index); + ItemInstance* inst = PopItem(index); safe_delete(inst); } // Remove item from container without memory delete // Hands over memory ownership to client of this function call -ItemInst* ItemInst::PopItem(uint8 index) +EQEmu::ItemInstance* EQEmu::ItemInstance::PopItem(uint8 index) { auto iter = m_contents.find(index); if (iter != m_contents.end()) { - ItemInst* inst = iter->second; + ItemInstance* inst = iter->second; m_contents.erase(index); return inst; // Return pointer that needs to be deleted (or otherwise managed) } @@ -1775,7 +1775,7 @@ ItemInst* ItemInst::PopItem(uint8 index) } // Remove all items from container -void ItemInst::Clear() +void EQEmu::ItemInstance::Clear() { // Destroy container contents for (auto iter = m_contents.begin(); iter != m_contents.end(); ++iter) { @@ -1785,22 +1785,22 @@ void ItemInst::Clear() } // Remove all items from container -void ItemInst::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent) +void EQEmu::ItemInstance::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent) { // TODO: This needs work... // Destroy container contents - std::map::const_iterator cur, end, del; + std::map::const_iterator cur, end, del; cur = m_contents.begin(); end = m_contents.end(); for (; cur != end;) { - ItemInst* inst = cur->second; + ItemInstance* inst = cur->second; if (inst == nullptr) { cur = m_contents.erase(cur); continue; } - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); if (item == nullptr) { cur = m_contents.erase(cur); continue; @@ -1847,7 +1847,7 @@ void ItemInst::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent) } } -uint8 ItemInst::FirstOpenSlot() const +uint8 EQEmu::ItemInstance::FirstOpenSlot() const { if (!m_item) return INVALID_INDEX; @@ -1861,7 +1861,7 @@ uint8 ItemInst::FirstOpenSlot() const return (i < slots) ? i : INVALID_INDEX; } -uint8 ItemInst::GetTotalItemCount() const +uint8 EQEmu::ItemInstance::GetTotalItemCount() const { if (!m_item) return 0; @@ -1875,7 +1875,7 @@ uint8 ItemInst::GetTotalItemCount() const return item_count; } -bool ItemInst::IsNoneEmptyContainer() +bool EQEmu::ItemInstance::IsNoneEmptyContainer() { if (!m_item || !m_item->IsClassBag()) return false; @@ -1889,7 +1889,7 @@ bool ItemInst::IsNoneEmptyContainer() } // Retrieve augment inside item -ItemInst* ItemInst::GetAugment(uint8 slot) const +EQEmu::ItemInstance* EQEmu::ItemInstance::GetAugment(uint8 slot) const { if (m_item && m_item->IsClassCommon()) return GetItem(slot); @@ -1897,7 +1897,7 @@ ItemInst* ItemInst::GetAugment(uint8 slot) const return nullptr; } -ItemInst* ItemInst::GetOrnamentationAug(int32 ornamentationAugtype) const +EQEmu::ItemInstance* EQEmu::ItemInstance::GetOrnamentationAug(int32 ornamentationAugtype) const { if (!m_item || !m_item->IsClassCommon()) { return nullptr; } if (ornamentationAugtype == 0) { return nullptr; } @@ -1922,7 +1922,7 @@ ItemInst* ItemInst::GetOrnamentationAug(int32 ornamentationAugtype) const return nullptr; } -uint32 ItemInst::GetOrnamentHeroModel(int32 material_slot) const { +uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const { uint32 HeroModel = 0; if (m_ornament_hero_model > 0) { @@ -1935,7 +1935,7 @@ uint32 ItemInst::GetOrnamentHeroModel(int32 material_slot) const { return HeroModel; } -bool ItemInst::UpdateOrnamentationInfo() { +bool EQEmu::ItemInstance::UpdateOrnamentationInfo() { if (!m_item || !m_item->IsClassCommon()) return false; @@ -1944,7 +1944,7 @@ bool ItemInst::UpdateOrnamentationInfo() { int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); if (GetOrnamentationAug(ornamentationAugtype)) { - const EQEmu::ItemBase* ornamentItem; + const ItemData* ornamentItem; ornamentItem = GetOrnamentationAug(ornamentationAugtype)->GetItem(); if (ornamentItem != nullptr) { @@ -1971,7 +1971,7 @@ bool ItemInst::UpdateOrnamentationInfo() { return ornamentSet; } -bool ItemInst::CanTransform(const EQEmu::ItemBase *ItemToTry, const EQEmu::ItemBase *Container, bool AllowAll) { +bool EQEmu::ItemInstance::CanTransform(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container, bool AllowAll) { if (!ItemToTry || !Container) return false; if (ItemToTry->ItemType == EQEmu::item::ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0) @@ -2017,7 +2017,7 @@ bool ItemInst::CanTransform(const EQEmu::ItemBase *ItemToTry, const EQEmu::ItemB return false; } -uint32 ItemInst::GetAugmentItemID(uint8 slot) const +uint32 EQEmu::ItemInstance::GetAugmentItemID(uint8 slot) const { if (!m_item || !m_item->IsClassCommon()) return NO_ITEM; @@ -2026,7 +2026,7 @@ uint32 ItemInst::GetAugmentItemID(uint8 slot) const } // Add an augment to the item -void ItemInst::PutAugment(uint8 slot, const ItemInst& augment) +void EQEmu::ItemInstance::PutAugment(uint8 slot, const ItemInstance& augment) { if (!m_item || !m_item->IsClassCommon()) return; @@ -2034,12 +2034,12 @@ void ItemInst::PutAugment(uint8 slot, const ItemInst& augment) PutItem(slot, augment); } -void ItemInst::PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id) +void EQEmu::ItemInstance::PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id) { if (item_id == NO_ITEM) { return; } if (db == nullptr) { return; /* TODO: add log message for nullptr */ } - const ItemInst* aug = db->CreateItem(item_id); + const ItemInstance* aug = db->CreateItem(item_id); if (aug) { PutAugment(slot, *aug); safe_delete(aug); @@ -2047,7 +2047,7 @@ void ItemInst::PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id) } // Remove augment from item and destroy it -void ItemInst::DeleteAugment(uint8 index) +void EQEmu::ItemInstance::DeleteAugment(uint8 index) { if (!m_item || !m_item->IsClassCommon()) return; @@ -2056,7 +2056,7 @@ void ItemInst::DeleteAugment(uint8 index) } // Remove augment from item and return it -ItemInst* ItemInst::RemoveAugment(uint8 index) +EQEmu::ItemInstance* EQEmu::ItemInstance::RemoveAugment(uint8 index) { if (!m_item || !m_item->IsClassCommon()) return nullptr; @@ -2064,7 +2064,7 @@ ItemInst* ItemInst::RemoveAugment(uint8 index) return PopItem(index); } -bool ItemInst::IsAugmented() +bool EQEmu::ItemInstance::IsAugmented() { if (!m_item || !m_item->IsClassCommon()) return false; @@ -2078,7 +2078,7 @@ bool ItemInst::IsAugmented() } // Has attack/delay? -bool ItemInst::IsWeapon() const +bool EQEmu::ItemInstance::IsWeapon() const { if (!m_item || !m_item->IsClassCommon()) return false; @@ -2089,7 +2089,7 @@ bool ItemInst::IsWeapon() const return ((m_item->Damage != 0) && (m_item->Delay != 0)); } -bool ItemInst::IsAmmo() const +bool EQEmu::ItemInstance::IsAmmo() const { if (!m_item) return false; @@ -2105,7 +2105,7 @@ bool ItemInst::IsAmmo() const } -const EQEmu::ItemBase* ItemInst::GetItem() const +const EQEmu::ItemData* EQEmu::ItemInstance::GetItem() const { if (!m_item) return nullptr; @@ -2116,13 +2116,13 @@ const EQEmu::ItemBase* ItemInst::GetItem() const return m_item; } -const EQEmu::ItemBase* ItemInst::GetUnscaledItem() const +const EQEmu::ItemData* EQEmu::ItemInstance::GetUnscaledItem() const { // No operator calls and defaults to nullptr return m_item; } -std::string ItemInst::GetCustomDataString() const { +std::string EQEmu::ItemInstance::GetCustomDataString() const { std::string ret_val; auto iter = m_custom_data.begin(); while (iter != m_custom_data.end()) { @@ -2141,7 +2141,7 @@ std::string ItemInst::GetCustomDataString() const { return ret_val; } -std::string ItemInst::GetCustomData(std::string identifier) { +std::string EQEmu::ItemInstance::GetCustomData(std::string identifier) { std::map::const_iterator iter = m_custom_data.find(identifier); if (iter != m_custom_data.end()) { return iter->second; @@ -2150,49 +2150,49 @@ std::string ItemInst::GetCustomData(std::string identifier) { return ""; } -void ItemInst::SetCustomData(std::string identifier, std::string value) { +void EQEmu::ItemInstance::SetCustomData(std::string identifier, std::string value) { DeleteCustomData(identifier); m_custom_data[identifier] = value; } -void ItemInst::SetCustomData(std::string identifier, int value) { +void EQEmu::ItemInstance::SetCustomData(std::string identifier, int value) { DeleteCustomData(identifier); std::stringstream ss; ss << value; m_custom_data[identifier] = ss.str(); } -void ItemInst::SetCustomData(std::string identifier, float value) { +void EQEmu::ItemInstance::SetCustomData(std::string identifier, float value) { DeleteCustomData(identifier); std::stringstream ss; ss << value; m_custom_data[identifier] = ss.str(); } -void ItemInst::SetCustomData(std::string identifier, bool value) { +void EQEmu::ItemInstance::SetCustomData(std::string identifier, bool value) { DeleteCustomData(identifier); std::stringstream ss; ss << value; m_custom_data[identifier] = ss.str(); } -void ItemInst::DeleteCustomData(std::string identifier) { +void EQEmu::ItemInstance::DeleteCustomData(std::string identifier) { auto iter = m_custom_data.find(identifier); if (iter != m_custom_data.end()) { m_custom_data.erase(iter); } } -// Clone a type of ItemInst object +// Clone a type of EQEmu::ItemInstance object // c++ doesn't allow a polymorphic copy constructor, // so we have to resort to a polymorphic Clone() -ItemInst* ItemInst::Clone() const +EQEmu::ItemInstance* EQEmu::ItemInstance::Clone() const { // Pseudo-polymorphic copy constructor - return new ItemInst(*this); + return new ItemInstance(*this); } -bool ItemInst::IsSlotAllowed(int16 slot_id) const { +bool EQEmu::ItemInstance::IsSlotAllowed(int16 slot_id) const { // 'SupportsContainers' and 'slot_id > 21' previously saw the reassigned PowerSource slot (9999 to 22) as valid if (!m_item) { return false; } else if (Inventory::SupportsContainers(slot_id)) { return true; } @@ -2202,7 +2202,7 @@ bool ItemInst::IsSlotAllowed(int16 slot_id) const { else { return false; } } -void ItemInst::Initialize(SharedDatabase *db) { +void EQEmu::ItemInstance::Initialize(SharedDatabase *db) { // if there's no actual item, don't do anything if (!m_item) return; @@ -2219,15 +2219,15 @@ void ItemInst::Initialize(SharedDatabase *db) { } } -void ItemInst::ScaleItem() { +void EQEmu::ItemInstance::ScaleItem() { if (!m_item) return; if (m_scaledItem) { - memcpy(m_scaledItem, m_item, sizeof(EQEmu::ItemBase)); + memcpy(m_scaledItem, m_item, sizeof(ItemData)); } else { - m_scaledItem = new EQEmu::ItemBase(*m_item); + m_scaledItem = new ItemData(*m_item); } float Mult = (float)(GetExp()) / 10000; // scaling is determined by exp, with 10,000 being full stats @@ -2303,18 +2303,18 @@ void ItemInst::ScaleItem() { m_scaledItem->CharmFileID = 0; // this stops the client from trying to scale the item itself. } -bool ItemInst::EvolveOnAllKills() const { +bool EQEmu::ItemInstance::EvolveOnAllKills() const { return (m_evolveInfo && m_evolveInfo->AllKills); } -int8 ItemInst::GetMaxEvolveLvl() const { +int8 EQEmu::ItemInstance::GetMaxEvolveLvl() const { if (m_evolveInfo) return m_evolveInfo->MaxLvl; else return 0; } -uint32 ItemInst::GetKillsNeeded(uint8 currentlevel) { +uint32 EQEmu::ItemInstance::GetKillsNeeded(uint8 currentlevel) { uint32 kills = -1; // default to -1 (max uint32 value) because this value is usually divided by, so we don't want to ever return zero. if (m_evolveInfo) if (currentlevel != m_evolveInfo->MaxLvl) @@ -2326,24 +2326,24 @@ uint32 ItemInst::GetKillsNeeded(uint8 currentlevel) { return kills; } -void ItemInst::SetTimer(std::string name, uint32 time) { +void EQEmu::ItemInstance::SetTimer(std::string name, uint32 time) { Timer t(time); t.Start(time, false); m_timers[name] = t; } -void ItemInst::StopTimer(std::string name) { +void EQEmu::ItemInstance::StopTimer(std::string name) { auto iter = m_timers.find(name); if(iter != m_timers.end()) { m_timers.erase(iter); } } -void ItemInst::ClearTimers() { +void EQEmu::ItemInstance::ClearTimers() { m_timers.clear(); } -int ItemInst::GetItemArmorClass(bool augments) const +int EQEmu::ItemInstance::GetItemArmorClass(bool augments) const { int ac = 0; const auto item = GetItem(); @@ -2357,7 +2357,7 @@ int ItemInst::GetItemArmorClass(bool augments) const return ac; } -int ItemInst::GetItemElementalDamage(int &magic, int &fire, int &cold, int &poison, int &disease, int &chromatic, int &prismatic, int &physical, int &corruption, bool augments) const +int EQEmu::ItemInstance::GetItemElementalDamage(int &magic, int &fire, int &cold, int &poison, int &disease, int &chromatic, int &prismatic, int &physical, int &corruption, bool augments) const { const auto item = GetItem(); if (item) { @@ -2399,7 +2399,7 @@ int ItemInst::GetItemElementalDamage(int &magic, int &fire, int &cold, int &pois return magic + fire + cold + poison + disease + chromatic + prismatic + physical + corruption; } -int ItemInst::GetItemElementalFlag(bool augments) const +int EQEmu::ItemInstance::GetItemElementalFlag(bool augments) const { int flag = 0; const auto item = GetItem(); @@ -2420,7 +2420,7 @@ int ItemInst::GetItemElementalFlag(bool augments) const return flag; } -int ItemInst::GetItemElementalDamage(bool augments) const +int EQEmu::ItemInstance::GetItemElementalDamage(bool augments) const { int damage = 0; const auto item = GetItem(); @@ -2441,7 +2441,7 @@ int ItemInst::GetItemElementalDamage(bool augments) const return damage; } -int ItemInst::GetItemRecommendedLevel(bool augments) const +int EQEmu::ItemInstance::GetItemRecommendedLevel(bool augments) const { int level = 0; const auto item = GetItem(); @@ -2463,7 +2463,7 @@ int ItemInst::GetItemRecommendedLevel(bool augments) const return level; } -int ItemInst::GetItemRequiredLevel(bool augments) const +int EQEmu::ItemInstance::GetItemRequiredLevel(bool augments) const { int level = 0; const auto item = GetItem(); @@ -2485,7 +2485,7 @@ int ItemInst::GetItemRequiredLevel(bool augments) const return level; } -int ItemInst::GetItemWeaponDamage(bool augments) const +int EQEmu::ItemInstance::GetItemWeaponDamage(bool augments) const { int damage = 0; const auto item = GetItem(); @@ -2501,7 +2501,7 @@ int ItemInst::GetItemWeaponDamage(bool augments) const return damage; } -int ItemInst::GetItemBackstabDamage(bool augments) const +int EQEmu::ItemInstance::GetItemBackstabDamage(bool augments) const { int damage = 0; const auto item = GetItem(); @@ -2517,7 +2517,7 @@ int ItemInst::GetItemBackstabDamage(bool augments) const return damage; } -int ItemInst::GetItemBaneDamageBody(bool augments) const +int EQEmu::ItemInstance::GetItemBaneDamageBody(bool augments) const { int body = 0; const auto item = GetItem(); @@ -2538,7 +2538,7 @@ int ItemInst::GetItemBaneDamageBody(bool augments) const return body; } -int ItemInst::GetItemBaneDamageRace(bool augments) const +int EQEmu::ItemInstance::GetItemBaneDamageRace(bool augments) const { int race = 0; const auto item = GetItem(); @@ -2559,7 +2559,7 @@ int ItemInst::GetItemBaneDamageRace(bool augments) const return race; } -int ItemInst::GetItemBaneDamageBody(bodyType against, bool augments) const +int EQEmu::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) const { int damage = 0; const auto item = GetItem(); @@ -2576,7 +2576,7 @@ int ItemInst::GetItemBaneDamageBody(bodyType against, bool augments) const return damage; } -int ItemInst::GetItemBaneDamageRace(uint16 against, bool augments) const +int EQEmu::ItemInstance::GetItemBaneDamageRace(uint16 against, bool augments) const { int damage = 0; const auto item = GetItem(); @@ -2593,7 +2593,7 @@ int ItemInst::GetItemBaneDamageRace(uint16 against, bool augments) const return damage; } -int ItemInst::GetItemMagical(bool augments) const +int EQEmu::ItemInstance::GetItemMagical(bool augments) const { const auto item = GetItem(); if (item) { @@ -2609,7 +2609,7 @@ int ItemInst::GetItemMagical(bool augments) const return 0; } -int ItemInst::GetItemHP(bool augments) const +int EQEmu::ItemInstance::GetItemHP(bool augments) const { int hp = 0; const auto item = GetItem(); @@ -2623,7 +2623,7 @@ int ItemInst::GetItemHP(bool augments) const return hp; } -int ItemInst::GetItemMana(bool augments) const +int EQEmu::ItemInstance::GetItemMana(bool augments) const { int mana = 0; const auto item = GetItem(); @@ -2637,7 +2637,7 @@ int ItemInst::GetItemMana(bool augments) const return mana; } -int ItemInst::GetItemEndur(bool augments) const +int EQEmu::ItemInstance::GetItemEndur(bool augments) const { int endur = 0; const auto item = GetItem(); @@ -2651,7 +2651,7 @@ int ItemInst::GetItemEndur(bool augments) const return endur; } -int ItemInst::GetItemAttack(bool augments) const +int EQEmu::ItemInstance::GetItemAttack(bool augments) const { int atk = 0; const auto item = GetItem(); @@ -2665,7 +2665,7 @@ int ItemInst::GetItemAttack(bool augments) const return atk; } -int ItemInst::GetItemStr(bool augments) const +int EQEmu::ItemInstance::GetItemStr(bool augments) const { int str = 0; const auto item = GetItem(); @@ -2679,7 +2679,7 @@ int ItemInst::GetItemStr(bool augments) const return str; } -int ItemInst::GetItemSta(bool augments) const +int EQEmu::ItemInstance::GetItemSta(bool augments) const { int sta = 0; const auto item = GetItem(); @@ -2693,7 +2693,7 @@ int ItemInst::GetItemSta(bool augments) const return sta; } -int ItemInst::GetItemDex(bool augments) const +int EQEmu::ItemInstance::GetItemDex(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2707,7 +2707,7 @@ int ItemInst::GetItemDex(bool augments) const return total; } -int ItemInst::GetItemAgi(bool augments) const +int EQEmu::ItemInstance::GetItemAgi(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2721,7 +2721,7 @@ int ItemInst::GetItemAgi(bool augments) const return total; } -int ItemInst::GetItemInt(bool augments) const +int EQEmu::ItemInstance::GetItemInt(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2735,7 +2735,7 @@ int ItemInst::GetItemInt(bool augments) const return total; } -int ItemInst::GetItemWis(bool augments) const +int EQEmu::ItemInstance::GetItemWis(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2749,7 +2749,7 @@ int ItemInst::GetItemWis(bool augments) const return total; } -int ItemInst::GetItemCha(bool augments) const +int EQEmu::ItemInstance::GetItemCha(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2763,7 +2763,7 @@ int ItemInst::GetItemCha(bool augments) const return total; } -int ItemInst::GetItemMR(bool augments) const +int EQEmu::ItemInstance::GetItemMR(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2777,7 +2777,7 @@ int ItemInst::GetItemMR(bool augments) const return total; } -int ItemInst::GetItemFR(bool augments) const +int EQEmu::ItemInstance::GetItemFR(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2791,7 +2791,7 @@ int ItemInst::GetItemFR(bool augments) const return total; } -int ItemInst::GetItemCR(bool augments) const +int EQEmu::ItemInstance::GetItemCR(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2805,7 +2805,7 @@ int ItemInst::GetItemCR(bool augments) const return total; } -int ItemInst::GetItemPR(bool augments) const +int EQEmu::ItemInstance::GetItemPR(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2819,7 +2819,7 @@ int ItemInst::GetItemPR(bool augments) const return total; } -int ItemInst::GetItemDR(bool augments) const +int EQEmu::ItemInstance::GetItemDR(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2833,7 +2833,7 @@ int ItemInst::GetItemDR(bool augments) const return total; } -int ItemInst::GetItemCorrup(bool augments) const +int EQEmu::ItemInstance::GetItemCorrup(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2847,7 +2847,7 @@ int ItemInst::GetItemCorrup(bool augments) const return total; } -int ItemInst::GetItemHeroicStr(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicStr(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2861,7 +2861,7 @@ int ItemInst::GetItemHeroicStr(bool augments) const return total; } -int ItemInst::GetItemHeroicSta(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicSta(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2875,7 +2875,7 @@ int ItemInst::GetItemHeroicSta(bool augments) const return total; } -int ItemInst::GetItemHeroicDex(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicDex(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2889,7 +2889,7 @@ int ItemInst::GetItemHeroicDex(bool augments) const return total; } -int ItemInst::GetItemHeroicAgi(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicAgi(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2903,7 +2903,7 @@ int ItemInst::GetItemHeroicAgi(bool augments) const return total; } -int ItemInst::GetItemHeroicInt(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicInt(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2917,7 +2917,7 @@ int ItemInst::GetItemHeroicInt(bool augments) const return total; } -int ItemInst::GetItemHeroicWis(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicWis(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2931,7 +2931,7 @@ int ItemInst::GetItemHeroicWis(bool augments) const return total; } -int ItemInst::GetItemHeroicCha(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicCha(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2945,7 +2945,7 @@ int ItemInst::GetItemHeroicCha(bool augments) const return total; } -int ItemInst::GetItemHeroicMR(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicMR(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2959,7 +2959,7 @@ int ItemInst::GetItemHeroicMR(bool augments) const return total; } -int ItemInst::GetItemHeroicFR(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicFR(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2973,7 +2973,7 @@ int ItemInst::GetItemHeroicFR(bool augments) const return total; } -int ItemInst::GetItemHeroicCR(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicCR(bool augments) const { int total = 0; const auto item = GetItem(); @@ -2987,7 +2987,7 @@ int ItemInst::GetItemHeroicCR(bool augments) const return total; } -int ItemInst::GetItemHeroicPR(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicPR(bool augments) const { int total = 0; const auto item = GetItem(); @@ -3001,7 +3001,7 @@ int ItemInst::GetItemHeroicPR(bool augments) const return total; } -int ItemInst::GetItemHeroicDR(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicDR(bool augments) const { int total = 0; const auto item = GetItem(); @@ -3015,7 +3015,7 @@ int ItemInst::GetItemHeroicDR(bool augments) const return total; } -int ItemInst::GetItemHeroicCorrup(bool augments) const +int EQEmu::ItemInstance::GetItemHeroicCorrup(bool augments) const { int total = 0; const auto item = GetItem(); @@ -3029,7 +3029,7 @@ int ItemInst::GetItemHeroicCorrup(bool augments) const return total; } -int ItemInst::GetItemHaste(bool augments) const +int EQEmu::ItemInstance::GetItemHaste(bool augments) const { int total = 0; const auto item = GetItem(); diff --git a/common/item_instance.h b/common/item_instance.h index 3ea3ba224..29523c1b1 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -21,8 +21,8 @@ // These classes could be optimized with database reads/writes by storing // a status flag indicating how object needs to interact with database -#ifndef COMMON_ITEM_H -#define COMMON_ITEM_H +#ifndef COMMON_ITEM_INSTANCE_H +#define COMMON_ITEM_INSTANCE_H class ItemParse; // Parses item packets @@ -51,7 +51,7 @@ namespace ItemField }; }; -// Specifies usage type for item inside ItemInst +// Specifies usage type for item inside EQEmu::ItemInstance enum ItemInstTypes { ItemInstNormal = 0, @@ -76,7 +76,10 @@ enum { invWhereCursor = 0x20 }; -class ItemInst; +namespace EQEmu +{ + class ItemInstance; +} // ######################################## // Class: Queue @@ -89,24 +92,24 @@ public: // Public Methods ///////////////////////// - inline std::list::const_iterator cbegin() { return m_list.cbegin(); } - inline std::list::const_iterator cend() { return m_list.cend(); } + inline std::list::const_iterator cbegin() { return m_list.cbegin(); } + inline std::list::const_iterator cend() { return m_list.cend(); } inline int size() { return static_cast(m_list.size()); } // TODO: change to size_t inline bool empty() { return m_list.empty(); } - void push(ItemInst* inst); - void push_front(ItemInst* inst); - ItemInst* pop(); - ItemInst* pop_back(); - ItemInst* peek_front() const; + void push(EQEmu::ItemInstance* inst); + void push_front(EQEmu::ItemInstance* inst); + EQEmu::ItemInstance* pop(); + EQEmu::ItemInstance* pop_back(); + EQEmu::ItemInstance* peek_front() const; protected: ///////////////////////// // Protected Members ///////////////////////// - std::list m_list; + std::list m_list; }; // ######################################## @@ -114,7 +117,7 @@ protected: // Character inventory class Inventory { - friend class ItemInst; + friend class EQEmu::ItemInstance; public: /////////////////////////////// // Public Methods @@ -138,29 +141,29 @@ public: EQEmu::versions::InventoryVersion InventoryVersion() { return m_inventory_version; } static void CleanDirty(); - static void MarkDirty(ItemInst *inst); + static void MarkDirty(EQEmu::ItemInstance *inst); // Retrieve a writeable item at specified slot - ItemInst* GetItem(int16 slot_id) const; - ItemInst* GetItem(int16 slot_id, uint8 bagidx) const; + EQEmu::ItemInstance* GetItem(int16 slot_id) const; + EQEmu::ItemInstance* GetItem(int16 slot_id, uint8 bagidx) const; - inline std::list::const_iterator cursor_cbegin() { return m_cursor.cbegin(); } - inline std::list::const_iterator cursor_cend() { return m_cursor.cend(); } + inline std::list::const_iterator cursor_cbegin() { return m_cursor.cbegin(); } + inline std::list::const_iterator cursor_cend() { return m_cursor.cend(); } inline int CursorSize() { return m_cursor.size(); } inline bool CursorEmpty() { return m_cursor.empty(); } // Retrieve a read-only item from inventory - inline const ItemInst* operator[](int16 slot_id) const { return GetItem(slot_id); } + inline const EQEmu::ItemInstance* operator[](int16 slot_id) const { return GetItem(slot_id); } // Add item to inventory - int16 PutItem(int16 slot_id, const ItemInst& inst); + int16 PutItem(int16 slot_id, const EQEmu::ItemInstance& inst); // Add item to cursor queue - int16 PushCursor(const ItemInst& inst); + int16 PushCursor(const EQEmu::ItemInstance& inst); // Get cursor item in front of queue - ItemInst* GetCursorItem(); + EQEmu::ItemInstance* GetCursorItem(); // Swap items in inventory bool SwapItem(int16 slot_a, int16 slot_b); @@ -172,10 +175,10 @@ public: bool CheckNoDrop(int16 slot_id); // Remove item from inventory (and take control of memory) - ItemInst* PopItem(int16 slot_id); + EQEmu::ItemInstance* PopItem(int16 slot_id); // Check whether there is space for the specified number of the specified item. - bool HasSpaceForItem(const EQEmu::ItemBase *ItemToTry, int16 Quantity); + bool HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity); // Check whether item exists in inventory // where argument specifies OR'd list of invWhere constants to look @@ -191,7 +194,7 @@ public: // Locate an available inventory slot int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false); - int16 FindFreeSlotForTradeItem(const ItemInst* inst); + int16 FindFreeSlotForTradeItem(const EQEmu::ItemInstance* inst); // Calculate slot_id for an item within a bag static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id @@ -200,7 +203,7 @@ public: static int16 CalcSlotFromMaterial(uint8 material); static uint8 CalcMaterialFromSlot(int16 equipslot); - static bool CanItemFitInContainer(const EQEmu::ItemBase *ItemToTry, const EQEmu::ItemBase *Container); + static bool CanItemFitInContainer(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container); // Test for valid inventory casting slot bool SupportsClickCasting(int16 slot_id); @@ -209,7 +212,7 @@ public: // Test whether a given slot can support a container item static bool SupportsContainers(int16 slot_id); - int GetSlotByItemInst(ItemInst *inst); + int GetSlotByItemInst(EQEmu::ItemInstance *inst); uint8 FindBrightestLightType(); @@ -229,31 +232,31 @@ protected: // Protected Methods /////////////////////////////// - int GetSlotByItemInstCollection(const std::map &collection, ItemInst *inst); - void dumpItemCollection(const std::map &collection); - void dumpBagContents(ItemInst *inst, std::map::const_iterator *it); + int GetSlotByItemInstCollection(const std::map &collection, EQEmu::ItemInstance *inst); + void dumpItemCollection(const std::map &collection); + void dumpBagContents(EQEmu::ItemInstance *inst, std::map::const_iterator *it); // Retrieves item within an inventory bucket - ItemInst* _GetItem(const std::map& bucket, int16 slot_id) const; + EQEmu::ItemInstance* _GetItem(const std::map& bucket, int16 slot_id) const; // Private "put" item into bucket, without regard for what is currently in bucket - int16 _PutItem(int16 slot_id, ItemInst* inst); + int16 _PutItem(int16 slot_id, EQEmu::ItemInstance* inst); // Checks an inventory bucket for a particular item - int16 _HasItem(std::map& bucket, uint32 item_id, uint8 quantity); + int16 _HasItem(std::map& bucket, uint32 item_id, uint8 quantity); int16 _HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity); - int16 _HasItemByUse(std::map& bucket, uint8 use, uint8 quantity); + int16 _HasItemByUse(std::map& bucket, uint8 use, uint8 quantity); int16 _HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity); - int16 _HasItemByLoreGroup(std::map& bucket, uint32 loregroup); + int16 _HasItemByLoreGroup(std::map& bucket, uint32 loregroup); int16 _HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup); // Player inventory - std::map m_worn; // Items worn by character - std::map m_inv; // Items in character personal inventory - std::map m_bank; // Items in character bank - std::map m_shbank; // Items in character shared bank - std::map m_trade; // Items in a trade session + std::map m_worn; // Items worn by character + std::map m_inv; // Items in character personal inventory + std::map m_bank; // Items in character bank + std::map m_shbank; // Items in character shared bank + std::map m_trade; // Items in a trade session ItemInstQueue m_cursor; // Items on cursor: FIFO private: @@ -265,271 +268,269 @@ private: class SharedDatabase; // ######################################## -// Class: ItemInst +// Class: EQEmu::ItemInstance // Base class for an instance of an item // An item instance encapsulates item data + data specific // to an item instance (includes dye, augments, charges, etc) -class ItemInst +namespace EQEmu { -public: - ///////////////////////// - // Methods - ///////////////////////// + class ItemInstance { + public: + ///////////////////////// + // Methods + ///////////////////////// - // Constructors/Destructor - ItemInst(const EQEmu::ItemBase* item = nullptr, int16 charges = 0); + // Constructors/Destructor + ItemInstance(const ItemData* item = nullptr, int16 charges = 0); - ItemInst(SharedDatabase *db, uint32 item_id, int16 charges = 0); + ItemInstance(SharedDatabase *db, uint32 item_id, int16 charges = 0); - ItemInst(ItemInstTypes use_type); + ItemInstance(ItemInstTypes use_type); - ItemInst(const ItemInst& copy); + ItemInstance(const ItemInstance& copy); - ~ItemInst(); + ~ItemInstance(); - // Query item type - bool IsType(EQEmu::item::ItemClass item_class) const; + // Query item type + bool IsType(EQEmu::item::ItemClass item_class) const; - bool IsClassCommon(); - bool IsClassBag(); - bool IsClassBook(); + bool IsClassCommon() const; + bool IsClassBag() const; + bool IsClassBook() const; - bool IsClassCommon() const { return const_cast(this)->IsClassCommon(); } - bool IsClassBag() const { return const_cast(this)->IsClassBag(); } - bool IsClassBook() const { return const_cast(this)->IsClassBook(); } + // Can item be stacked? + bool IsStackable() const; + bool IsCharged() const; - // Can item be stacked? - bool IsStackable() const; - bool IsCharged() const; + // Can item be equipped by/at? + bool IsEquipable(uint16 race, uint16 class_) const; + bool IsEquipable(int16 slot_id) const; - // Can item be equipped by/at? - bool IsEquipable(uint16 race, uint16 class_) const; - bool IsEquipable(int16 slot_id) const; + // + // Augments + // + bool IsAugmentable() const; + bool AvailableWearSlot(uint32 aug_wear_slots) const; + int8 AvailableAugmentSlot(int32 augtype) const; + bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const; + inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : NO_ITEM); } - // - // Augments - // - bool IsAugmentable() const; - bool AvailableWearSlot(uint32 aug_wear_slots) const; - int8 AvailableAugmentSlot(int32 augtype) const; - bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const; - inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : NO_ITEM); } + inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == EQEmu::item::ItemEffectExpendable) || (m_item->ItemType == EQEmu::item::ItemTypePotion)) : false); } - inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == EQEmu::item::ItemEffectExpendable) || (m_item->ItemType == EQEmu::item::ItemTypePotion)) : false); } + // + // Contents + // + ItemInstance* GetItem(uint8 slot) const; + uint32 GetItemID(uint8 slot) const; + inline const ItemInstance* operator[](uint8 slot) const { return GetItem(slot); } + void PutItem(uint8 slot, const ItemInstance& inst); + void PutItem(SharedDatabase *db, uint8 slot, uint32 item_id) { return; } // not defined anywhere... + void DeleteItem(uint8 slot); + ItemInstance* PopItem(uint8 index); + void Clear(); + void ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent); + uint8 FirstOpenSlot() const; + uint8 GetTotalItemCount() const; + bool IsNoneEmptyContainer(); + std::map* GetContents() { return &m_contents; } - // - // Contents - // - ItemInst* GetItem(uint8 slot) const; - uint32 GetItemID(uint8 slot) const; - inline const ItemInst* operator[](uint8 slot) const { return GetItem(slot); } - void PutItem(uint8 slot, const ItemInst& inst); - void PutItem(SharedDatabase *db, uint8 slot, uint32 item_id) { return; } // not defined anywhere... - void DeleteItem(uint8 slot); - ItemInst* PopItem(uint8 index); - void Clear(); - void ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is_norent); - uint8 FirstOpenSlot() const; - uint8 GetTotalItemCount() const; - bool IsNoneEmptyContainer(); - std::map* GetContents() { return &m_contents; } + // + // Augments + // + ItemInstance* GetAugment(uint8 slot) const; + uint32 GetAugmentItemID(uint8 slot) const; + void PutAugment(uint8 slot, const ItemInstance& inst); + void PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id); + void DeleteAugment(uint8 slot); + ItemInstance* RemoveAugment(uint8 index); + bool IsAugmented(); + ItemInstance* GetOrnamentationAug(int32 ornamentationAugtype) const; + bool UpdateOrnamentationInfo(); + static bool CanTransform(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container, bool AllowAll = false); - // - // Augments - // - ItemInst* GetAugment(uint8 slot) const; - uint32 GetAugmentItemID(uint8 slot) const; - void PutAugment(uint8 slot, const ItemInst& inst); - void PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id); - void DeleteAugment(uint8 slot); - ItemInst* RemoveAugment(uint8 index); - bool IsAugmented(); - ItemInst* GetOrnamentationAug(int32 ornamentationAugtype) const; - bool UpdateOrnamentationInfo(); - static bool CanTransform(const EQEmu::ItemBase *ItemToTry, const EQEmu::ItemBase *Container, bool AllowAll = false); - - // Has attack/delay? - bool IsWeapon() const; - bool IsAmmo() const; + // Has attack/delay? + bool IsWeapon() const; + bool IsAmmo() const; - // Accessors - const uint32 GetID() const { return ((m_item) ? m_item->ID : NO_ITEM); } - const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : NO_ITEM); } - const EQEmu::ItemBase* GetItem() const; - const EQEmu::ItemBase* GetUnscaledItem() const; + // Accessors + const uint32 GetID() const { return ((m_item) ? m_item->ID : NO_ITEM); } + const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : NO_ITEM); } + const ItemData* GetItem() const; + const ItemData* GetUnscaledItem() const; - int16 GetCharges() const { return m_charges; } - void SetCharges(int16 charges) { m_charges = charges; } + int16 GetCharges() const { return m_charges; } + void SetCharges(int16 charges) { m_charges = charges; } - uint32 GetPrice() const { return m_price; } - void SetPrice(uint32 price) { m_price = price; } + uint32 GetPrice() const { return m_price; } + void SetPrice(uint32 price) { m_price = price; } - void SetColor(uint32 color) { m_color = color; } - uint32 GetColor() const { return m_color; } + void SetColor(uint32 color) { m_color = color; } + uint32 GetColor() const { return m_color; } - uint32 GetMerchantSlot() const { return m_merchantslot; } - void SetMerchantSlot(uint32 slot) { m_merchantslot = slot; } + uint32 GetMerchantSlot() const { return m_merchantslot; } + void SetMerchantSlot(uint32 slot) { m_merchantslot = slot; } - int32 GetMerchantCount() const { return m_merchantcount; } - void SetMerchantCount(int32 count) { m_merchantcount = count; } + int32 GetMerchantCount() const { return m_merchantcount; } + void SetMerchantCount(int32 count) { m_merchantcount = count; } - int16 GetCurrentSlot() const { return m_currentslot; } - void SetCurrentSlot(int16 curr_slot) { m_currentslot = curr_slot; } + int16 GetCurrentSlot() const { return m_currentslot; } + void SetCurrentSlot(int16 curr_slot) { m_currentslot = curr_slot; } - // Is this item already attuned? - bool IsAttuned() const { return m_attuned; } - void SetAttuned(bool flag) { m_attuned=flag; } + // Is this item already attuned? + bool IsAttuned() const { return m_attuned; } + void SetAttuned(bool flag) { m_attuned = flag; } - std::string GetCustomDataString() const; - std::string GetCustomData(std::string identifier); - void SetCustomData(std::string identifier, std::string value); - void SetCustomData(std::string identifier, int value); - void SetCustomData(std::string identifier, float value); - void SetCustomData(std::string identifier, bool value); - void DeleteCustomData(std::string identifier); + std::string GetCustomDataString() const; + std::string GetCustomData(std::string identifier); + void SetCustomData(std::string identifier, std::string value); + void SetCustomData(std::string identifier, int value); + void SetCustomData(std::string identifier, float value); + void SetCustomData(std::string identifier, bool value); + void DeleteCustomData(std::string identifier); - // Allows treatment of this object as though it were a pointer to m_item - operator bool() const { return (m_item != nullptr); } + // Allows treatment of this object as though it were a pointer to m_item + operator bool() const { return (m_item != nullptr); } - // Compare inner Item_Struct of two ItemInst objects - bool operator==(const ItemInst& right) const { return (this->m_item == right.m_item); } - bool operator!=(const ItemInst& right) const { return (this->m_item != right.m_item); } + // Compare inner Item_Struct of two ItemInstance objects + bool operator==(const ItemInstance& right) const { return (this->m_item == right.m_item); } + bool operator!=(const ItemInstance& right) const { return (this->m_item != right.m_item); } - // Clone current item - ItemInst* Clone() const; + // Clone current item + ItemInstance* Clone() const; - bool IsSlotAllowed(int16 slot_id) const; + bool IsSlotAllowed(int16 slot_id) const; - bool IsScaling() const { return m_scaling; } - bool IsEvolving() const { return (m_evolveLvl >= 1); } - uint32 GetExp() const { return m_exp; } - void SetExp(uint32 exp) { m_exp = exp; } - void AddExp(uint32 exp) { m_exp += exp; } - bool IsActivated() { return m_activated; } - void SetActivated(bool activated) { m_activated = activated; } - int8 GetEvolveLvl() const { return m_evolveLvl; } - void SetScaling(bool v) { m_scaling = v; } - uint32 GetOrnamentationIcon() const { return m_ornamenticon; } - void SetOrnamentIcon(uint32 ornament_icon) { m_ornamenticon = ornament_icon; } - uint32 GetOrnamentationIDFile() const { return m_ornamentidfile; } - void SetOrnamentationIDFile(uint32 ornament_idfile) { m_ornamentidfile = ornament_idfile; } - uint32 GetOrnamentHeroModel(int32 material_slot = -1) const; - void SetOrnamentHeroModel(uint32 ornament_hero_model) { m_ornament_hero_model = ornament_hero_model; } - uint32 GetRecastTimestamp() const { return m_recast_timestamp; } - void SetRecastTimestamp(uint32 in) { m_recast_timestamp = in; } + bool IsScaling() const { return m_scaling; } + bool IsEvolving() const { return (m_evolveLvl >= 1); } + uint32 GetExp() const { return m_exp; } + void SetExp(uint32 exp) { m_exp = exp; } + void AddExp(uint32 exp) { m_exp += exp; } + bool IsActivated() { return m_activated; } + void SetActivated(bool activated) { m_activated = activated; } + int8 GetEvolveLvl() const { return m_evolveLvl; } + void SetScaling(bool v) { m_scaling = v; } + uint32 GetOrnamentationIcon() const { return m_ornamenticon; } + void SetOrnamentIcon(uint32 ornament_icon) { m_ornamenticon = ornament_icon; } + uint32 GetOrnamentationIDFile() const { return m_ornamentidfile; } + void SetOrnamentationIDFile(uint32 ornament_idfile) { m_ornamentidfile = ornament_idfile; } + uint32 GetOrnamentHeroModel(int32 material_slot = -1) const; + void SetOrnamentHeroModel(uint32 ornament_hero_model) { m_ornament_hero_model = ornament_hero_model; } + uint32 GetRecastTimestamp() const { return m_recast_timestamp; } + void SetRecastTimestamp(uint32 in) { m_recast_timestamp = in; } - void Initialize(SharedDatabase *db = nullptr); - void ScaleItem(); - bool EvolveOnAllKills() const; - int8 GetMaxEvolveLvl() const; - uint32 GetKillsNeeded(uint8 currentlevel); + void Initialize(SharedDatabase *db = nullptr); + void ScaleItem(); + bool EvolveOnAllKills() const; + int8 GetMaxEvolveLvl() const; + uint32 GetKillsNeeded(uint8 currentlevel); - std::string Serialize(int16 slot_id) const { EQEmu::InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(EQEmu::InternalSerializedItem_Struct)); return ser; } - void Serialize(EQEmu::OutBuffer& ob, int16 slot_id) const { EQEmu::InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); } - - inline int32 GetSerialNumber() const { return m_SerialNumber; } - inline void SetSerialNumber(int32 id) { m_SerialNumber = id; } + std::string Serialize(int16 slot_id) const { EQEmu::InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(EQEmu::InternalSerializedItem_Struct)); return ser; } + void Serialize(EQEmu::OutBuffer& ob, int16 slot_id) const { EQEmu::InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); } - std::map& GetTimers() { return m_timers; } - void SetTimer(std::string name, uint32 time); - void StopTimer(std::string name); - void ClearTimers(); + inline int32 GetSerialNumber() const { return m_SerialNumber; } + inline void SetSerialNumber(int32 id) { m_SerialNumber = id; } - // Get a total of a stat, including augs - // These functions should be used in place of other code manually totaling - // to centralize where it is done to make future changes easier (ex. whenever powersources come around) - // and to minimize errors. CalcItemBonuses however doesn't use these in interest of performance - // by default these do not recurse into augs - int GetItemArmorClass(bool augments = false) const; - int GetItemElementalDamage(int &magic, int &fire, int &cold, int &poison, int &disease, int &chromatic, int &prismatic, int &physical, int &corruption, bool augments = false) const; - // These two differ in the fact that they're quick checks (they are checked BEFORE the one above - int GetItemElementalFlag(bool augments = false) const; - int GetItemElementalDamage(bool augments = false) const; - int GetItemRecommendedLevel(bool augments = false) const; - int GetItemRequiredLevel(bool augments = false) const; - int GetItemWeaponDamage(bool augments = false) const; - int GetItemBackstabDamage(bool augments = false) const; - // these two are just quick checks - int GetItemBaneDamageBody(bool augments = false) const; - int GetItemBaneDamageRace(bool augments = false) const; - int GetItemBaneDamageBody(bodyType against, bool augments = false) const; - int GetItemBaneDamageRace(uint16 against, bool augments = false) const; - int GetItemMagical(bool augments = false) const; - int GetItemHP(bool augments = false) const; - int GetItemMana(bool augments = false) const; - int GetItemEndur(bool augments = false) const; - int GetItemAttack(bool augments = false) const; - int GetItemStr(bool augments = false) const; - int GetItemSta(bool augments = false) const; - int GetItemDex(bool augments = false) const; - int GetItemAgi(bool augments = false) const; - int GetItemInt(bool augments = false) const; - int GetItemWis(bool augments = false) const; - int GetItemCha(bool augments = false) const; - int GetItemMR(bool augments = false) const; - int GetItemFR(bool augments = false) const; - int GetItemCR(bool augments = false) const; - int GetItemPR(bool augments = false) const; - int GetItemDR(bool augments = false) const; - int GetItemCorrup(bool augments = false) const; - int GetItemHeroicStr(bool augments = false) const; - int GetItemHeroicSta(bool augments = false) const; - int GetItemHeroicDex(bool augments = false) const; - int GetItemHeroicAgi(bool augments = false) const; - int GetItemHeroicInt(bool augments = false) const; - int GetItemHeroicWis(bool augments = false) const; - int GetItemHeroicCha(bool augments = false) const; - int GetItemHeroicMR(bool augments = false) const; - int GetItemHeroicFR(bool augments = false) const; - int GetItemHeroicCR(bool augments = false) const; - int GetItemHeroicPR(bool augments = false) const; - int GetItemHeroicDR(bool augments = false) const; - int GetItemHeroicCorrup(bool augments = false) const; - int GetItemHaste(bool augments = false) const; + std::map& GetTimers() { return m_timers; } + void SetTimer(std::string name, uint32 time); + void StopTimer(std::string name); + void ClearTimers(); -protected: - ////////////////////////// - // Protected Members - ////////////////////////// - std::map::const_iterator _cbegin() { return m_contents.cbegin(); } - std::map::const_iterator _cend() { return m_contents.cend(); } + // Get a total of a stat, including augs + // These functions should be used in place of other code manually totaling + // to centralize where it is done to make future changes easier (ex. whenever powersources come around) + // and to minimize errors. CalcItemBonuses however doesn't use these in interest of performance + // by default these do not recurse into augs + int GetItemArmorClass(bool augments = false) const; + int GetItemElementalDamage(int &magic, int &fire, int &cold, int &poison, int &disease, int &chromatic, int &prismatic, int &physical, int &corruption, bool augments = false) const; + // These two differ in the fact that they're quick checks (they are checked BEFORE the one above + int GetItemElementalFlag(bool augments = false) const; + int GetItemElementalDamage(bool augments = false) const; + int GetItemRecommendedLevel(bool augments = false) const; + int GetItemRequiredLevel(bool augments = false) const; + int GetItemWeaponDamage(bool augments = false) const; + int GetItemBackstabDamage(bool augments = false) const; + // these two are just quick checks + int GetItemBaneDamageBody(bool augments = false) const; + int GetItemBaneDamageRace(bool augments = false) const; + int GetItemBaneDamageBody(bodyType against, bool augments = false) const; + int GetItemBaneDamageRace(uint16 against, bool augments = false) const; + int GetItemMagical(bool augments = false) const; + int GetItemHP(bool augments = false) const; + int GetItemMana(bool augments = false) const; + int GetItemEndur(bool augments = false) const; + int GetItemAttack(bool augments = false) const; + int GetItemStr(bool augments = false) const; + int GetItemSta(bool augments = false) const; + int GetItemDex(bool augments = false) const; + int GetItemAgi(bool augments = false) const; + int GetItemInt(bool augments = false) const; + int GetItemWis(bool augments = false) const; + int GetItemCha(bool augments = false) const; + int GetItemMR(bool augments = false) const; + int GetItemFR(bool augments = false) const; + int GetItemCR(bool augments = false) const; + int GetItemPR(bool augments = false) const; + int GetItemDR(bool augments = false) const; + int GetItemCorrup(bool augments = false) const; + int GetItemHeroicStr(bool augments = false) const; + int GetItemHeroicSta(bool augments = false) const; + int GetItemHeroicDex(bool augments = false) const; + int GetItemHeroicAgi(bool augments = false) const; + int GetItemHeroicInt(bool augments = false) const; + int GetItemHeroicWis(bool augments = false) const; + int GetItemHeroicCha(bool augments = false) const; + int GetItemHeroicMR(bool augments = false) const; + int GetItemHeroicFR(bool augments = false) const; + int GetItemHeroicCR(bool augments = false) const; + int GetItemHeroicPR(bool augments = false) const; + int GetItemHeroicDR(bool augments = false) const; + int GetItemHeroicCorrup(bool augments = false) const; + int GetItemHaste(bool augments = false) const; - friend class Inventory; + protected: + ////////////////////////// + // Protected Members + ////////////////////////// + std::map::const_iterator _cbegin() { return m_contents.cbegin(); } + std::map::const_iterator _cend() { return m_contents.cend(); } + + friend class Inventory; - void _PutItem(uint8 index, ItemInst* inst) { m_contents[index] = inst; } + void _PutItem(uint8 index, ItemInstance* inst) { m_contents[index] = inst; } - ItemInstTypes m_use_type; // Usage type for item - const EQEmu::ItemBase* m_item; // Ptr to item data - int16 m_charges; // # of charges for chargeable items - uint32 m_price; // Bazaar /trader price - uint32 m_color; - uint32 m_merchantslot; - int16 m_currentslot; - bool m_attuned; - int32 m_merchantcount; //number avaliable on the merchant, -1=unlimited - int32 m_SerialNumber; // Unique identifier for this instance of an item. Needed for Bazaar. - uint32 m_exp; - int8 m_evolveLvl; - bool m_activated; - EQEmu::ItemBase* m_scaledItem; - EvolveInfo* m_evolveInfo; - bool m_scaling; - uint32 m_ornamenticon; - uint32 m_ornamentidfile; - uint32 m_ornament_hero_model; - uint32 m_recast_timestamp; + ItemInstTypes m_use_type; // Usage type for item + const ItemData* m_item; // Ptr to item data + int16 m_charges; // # of charges for chargeable items + uint32 m_price; // Bazaar /trader price + uint32 m_color; + uint32 m_merchantslot; + int16 m_currentslot; + bool m_attuned; + int32 m_merchantcount; //number avaliable on the merchant, -1=unlimited + int32 m_SerialNumber; // Unique identifier for this instance of an item. Needed for Bazaar. + uint32 m_exp; + int8 m_evolveLvl; + bool m_activated; + ItemData* m_scaledItem; + EvolveInfo* m_evolveInfo; + bool m_scaling; + uint32 m_ornamenticon; + uint32 m_ornamentidfile; + uint32 m_ornament_hero_model; + uint32 m_recast_timestamp; - // - // Items inside of this item (augs or contents); - std::map m_contents; // Zero-based index: min=0, max=9 - std::map m_custom_data; - std::map m_timers; -}; + // + // Items inside of this item (augs or contents); + std::map m_contents; // Zero-based index: min=0, max=9 + std::map m_custom_data; + std::map m_timers; + }; +} class EvolveInfo { public: - friend class ItemInst; + friend class EQEmu::ItemInstance; //temporary uint16 LvlKills[9]; uint32 FirstItem; @@ -541,4 +542,4 @@ public: ~EvolveInfo(); }; -#endif /*COMMON_ITEM_H*/ +#endif /*COMMON_ITEM_INSTANCE_H*/ diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index dba092bed..a6fcae35c 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -45,7 +45,7 @@ namespace RoF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline structs::InventorySlot_Struct ServerToRoFSlot(uint32 serverSlot); @@ -596,7 +596,7 @@ namespace RoF ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0); if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); @@ -1533,7 +1533,7 @@ namespace RoF ob.write((const char*)__emu_buffer, 4); - SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0); if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; @@ -5209,9 +5209,9 @@ namespace RoF return NextItemInstSerialNumber; } - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id_in, uint8 depth) { - const EQEmu::ItemBase *item = inst->GetUnscaledItem(); + const EQEmu::ItemData *item = inst->GetUnscaledItem(); RoF::structs::ItemSerializationHeader hdr; @@ -5623,7 +5623,7 @@ namespace RoF ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { - ItemInst* sub = inst->GetItem(index); + EQEmu::ItemInstance* sub = inst->GetItem(index); if (!sub) continue; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 609fdc123..47be172a2 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -45,7 +45,7 @@ namespace RoF2 static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth, ItemPacketType packet_type); + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id, uint8 depth, ItemPacketType packet_type); // server to client inventory location converters static inline structs::InventorySlot_Struct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType = ItemPacketInvalid); @@ -671,7 +671,7 @@ namespace RoF2 ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory); + SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory); if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); @@ -1609,7 +1609,7 @@ namespace RoF2 ob.write((const char*)__emu_buffer, 4); - SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType); + SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType); if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; @@ -5499,9 +5499,9 @@ namespace RoF2 return NextItemInstSerialNumber; } - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type) + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type) { - const EQEmu::ItemBase *item = inst->GetUnscaledItem(); + const EQEmu::ItemData *item = inst->GetUnscaledItem(); RoF2::structs::ItemSerializationHeader hdr; @@ -5923,7 +5923,7 @@ namespace RoF2 ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { - ItemInst* sub = inst->GetItem(index); + EQEmu::ItemInstance* sub = inst->GetItem(index); if (!sub) continue; diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index ae4d2c799..12f467a71 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -2423,7 +2423,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - ItemBase item; + ItemData item; uint8 iss_unknown001[6]; };*/ diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 74b47c09e..3b6e01318 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -2450,7 +2450,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - ItemBase item; + ItemData item; uint8 iss_unknown001[6]; };*/ diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 3b02cbbcb..0e1a3fdcd 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -43,7 +43,7 @@ namespace SoD static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToSoDSlot(uint32 ServerSlot); @@ -396,7 +396,7 @@ namespace SoD ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0); if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); @@ -1060,7 +1060,7 @@ namespace SoD ob.write((const char*)__emu_buffer, 4); - SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0); if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; @@ -3553,9 +3553,9 @@ namespace SoD return NextItemInstSerialNumber; } - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id_in, uint8 depth) { - const EQEmu::ItemBase *item = inst->GetUnscaledItem(); + const EQEmu::ItemData *item = inst->GetUnscaledItem(); SoD::structs::ItemSerializationHeader hdr; @@ -3870,7 +3870,7 @@ namespace SoD ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { - ItemInst* sub = inst->GetItem(index); + EQEmu::ItemInstance* sub = inst->GetItem(index); if (!sub) continue; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index bd428c653..d4a4d49a3 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1970,7 +1970,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - ItemBase item; + ItemData item; uint8 iss_unknown001[6]; };*/ diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 0d1afa000..b73e998aa 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -43,7 +43,7 @@ namespace SoF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToSoFSlot(uint32 serverSlot); @@ -378,7 +378,7 @@ namespace SoF ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0); if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); @@ -857,7 +857,7 @@ namespace SoF ob.write((const char*)__emu_buffer, 4); - SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0); if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; @@ -2923,9 +2923,9 @@ namespace SoF return NextItemInstSerialNumber; } - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id_in, uint8 depth) { - const EQEmu::ItemBase *item = inst->GetUnscaledItem(); + const EQEmu::ItemData *item = inst->GetUnscaledItem(); SoF::structs::ItemSerializationHeader hdr; @@ -3238,7 +3238,7 @@ namespace SoF ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { - ItemInst* sub = inst->GetItem(index); + EQEmu::ItemInstance* sub = inst->GetItem(index); if (!sub) continue; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 63feea81f..9b6459afb 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -42,7 +42,7 @@ namespace Titanium static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id_in, uint8 depth); // server to client inventory location converters static inline int16 ServerToTitaniumSlot(uint32 serverSlot); @@ -329,7 +329,7 @@ namespace Titanium EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); for (int r = 0; r < itemcount; r++, eq++) { - SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0); if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); @@ -815,7 +815,7 @@ namespace Titanium ob.write((const char*)__emu_buffer, 4); - SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0); if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; @@ -2216,10 +2216,10 @@ namespace Titanium } // file scope helper methods - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id_in, uint8 depth) { const char* protection = "\\\\\\\\\\"; - const EQEmu::ItemBase* item = inst->GetUnscaledItem(); + const EQEmu::ItemData* item = inst->GetUnscaledItem(); ob << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; @@ -2440,7 +2440,7 @@ namespace Titanium for (int index = SUB_INDEX_BEGIN; index < invbag::ItemBagSize; ++index) { ob << '|'; - ItemInst* sub = inst->GetItem(index); + EQEmu::ItemInstance* sub = inst->GetItem(index); if (!sub) continue; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 0436f5af4..fd45b0c61 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -43,7 +43,7 @@ namespace UF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToUFSlot(uint32 serverSlot); @@ -541,7 +541,7 @@ namespace UF ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + SerializeItem(ob, (const EQEmu::ItemInstance*)eq->inst, eq->slot_id, 0); if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); @@ -1293,7 +1293,7 @@ namespace UF ob.write((const char*)__emu_buffer, 4); - SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + SerializeItem(ob, (const EQEmu::ItemInstance*)int_struct->inst, int_struct->slot_id, 0); if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; @@ -3847,9 +3847,9 @@ namespace UF return NextItemInstSerialNumber; } - void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const EQEmu::ItemInstance *inst, int16 slot_id_in, uint8 depth) { - const EQEmu::ItemBase *item = inst->GetUnscaledItem(); + const EQEmu::ItemData *item = inst->GetUnscaledItem(); UF::structs::ItemSerializationHeader hdr; @@ -3893,7 +3893,7 @@ namespace UF int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); uint16 ornaIcon = 0; if (inst->GetOrnamentationAug(ornamentationAugtype)) { - const EQEmu::ItemBase *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const EQEmu::ItemData *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); ornaIcon = aug_weap->Icon; ob.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); @@ -4225,7 +4225,7 @@ namespace UF ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { - ItemInst* sub = inst->GetItem(index); + EQEmu::ItemInstance* sub = inst->GetItem(index); if (!sub) continue; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 8decaa04a..7ebedbec5 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -2011,7 +2011,7 @@ struct AdventureLeaderboard_Struct /*struct Item_Shop_Struct { uint16 merchantid; uint8 itemtype; - ItemBase item; + ItemData item; uint8 iss_unknown001[6]; };*/ diff --git a/common/say_link.cpp b/common/say_link.cpp index 2a4065403..42c0f46a1 100644 --- a/common/say_link.cpp +++ b/common/say_link.cpp @@ -147,7 +147,7 @@ void EQEmu::SayLinkEngine::generate_body() memset(&m_LinkBodyStruct, 0, sizeof(SayLinkBody_Struct)); - const EQEmu::ItemBase* item_data = nullptr; + const EQEmu::ItemData* item_data = nullptr; switch (m_LinkType) { case saylink::SayLinkBlank: @@ -250,7 +250,7 @@ void EQEmu::SayLinkEngine::generate_text() return; } - const EQEmu::ItemBase* item_data = nullptr; + const EQEmu::ItemData* item_data = nullptr; switch (m_LinkType) { case saylink::SayLinkBlank: diff --git a/common/say_link.h b/common/say_link.h index 0bbac2e36..6bc3e5535 100644 --- a/common/say_link.h +++ b/common/say_link.h @@ -26,11 +26,11 @@ struct ServerLootItem_Struct; -class ItemInst; namespace EQEmu { - struct ItemBase; + struct ItemData; + class ItemInstance; struct SayLinkBody_Struct; namespace saylink { @@ -67,9 +67,9 @@ namespace EQEmu SayLinkEngine(); void SetLinkType(saylink::SayLinkType link_type) { m_LinkType = link_type; } - void SetItemData(const EQEmu::ItemBase* item_data) { m_ItemData = item_data; } + void SetItemData(const EQEmu::ItemData* item_data) { m_ItemData = item_data; } void SetLootData(const ServerLootItem_Struct* loot_data) { m_LootData = loot_data; } - void SetItemInst(const ItemInst* item_inst) { m_ItemInst = item_inst; } + void SetItemInst(const ItemInstance* item_inst) { m_ItemInst = item_inst; } // mainly for saylinks..but, not limited to void SetProxyUnknown1(uint8 proxy_unknown_1) { m_Proxy_unknown_1 = proxy_unknown_1; } @@ -103,9 +103,9 @@ namespace EQEmu void generate_text(); int m_LinkType; - const ItemBase* m_ItemData; + const ItemData* m_ItemData; const ServerLootItem_Struct* m_LootData; - const ItemInst* m_ItemInst; + const ItemInstance* m_ItemInst; uint8 m_Proxy_unknown_1; uint32 m_ProxyItemID; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 8e55269e7..d896fba9c 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -99,7 +99,7 @@ uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) { return EntitledTime; } -bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iterator &start, std::list::const_iterator &end) +bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iterator &start, std::list::const_iterator &end) { // Delete cursor items std::string query = StringFormat("DELETE FROM inventory WHERE charid = %i " @@ -116,7 +116,7 @@ bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iter int i = 8000; for(auto it = start; it != end; ++it, i++) { if (i > 8999) { break; } // shouldn't be anything in the queue that indexes this high - ItemInst *inst = *it; + EQEmu::ItemInstance *inst = *it; int16 use_slot = (i == 8000) ? EQEmu::legacy::SlotCursor : i; if (!SaveInventory(char_id, inst, use_slot)) { return false; @@ -126,7 +126,7 @@ bool SharedDatabase::SaveCursor(uint32 char_id, std::list::const_iter return true; } -bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const ItemInst* inst) +bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const EQEmu::ItemInstance* inst) { // Delete cursor items std::string query = StringFormat("SELECT itemid, charges FROM sharedbank " @@ -159,7 +159,7 @@ bool SharedDatabase::VerifyInventory(uint32 account_id, int16 slot_id, const Ite return true; } -bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 slot_id) { +bool SharedDatabase::SaveInventory(uint32 char_id, const EQEmu::ItemInstance* inst, int16 slot_id) { //never save tribute slots: if (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) @@ -189,13 +189,13 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const ItemInst* inst, int16 s return UpdateInventorySlot(char_id, inst, slot_id); } -bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { +bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQEmu::ItemInstance* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { 0, 0, 0, 0, 0, 0 }; if (inst->IsClassCommon()) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { - ItemInst *auginst = inst->GetItem(i); + EQEmu::ItemInstance *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } } @@ -225,7 +225,7 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { - const ItemInst* baginst = inst->GetItem(idx); + const EQEmu::ItemInstance* baginst = inst->GetItem(idx); SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); } @@ -236,13 +236,13 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const ItemInst* inst, i return true; } -bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id) { +bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const EQEmu::ItemInstance* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { 0, 0, 0, 0, 0, 0 }; if (inst->IsClassCommon()) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { - ItemInst *auginst = inst->GetItem(i); + EQEmu::ItemInstance *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } } @@ -271,7 +271,7 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { - const ItemInst* baginst = inst->GetItem(idx); + const EQEmu::ItemInstance* baginst = inst->GetItem(idx); SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); } } @@ -364,7 +364,7 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) { bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) { - const EQEmu::ItemBase* myitem; + const EQEmu::ItemData* myitem; std::string query = StringFormat("SELECT itemid, item_charges, slot FROM starting_items " "WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND " @@ -385,7 +385,7 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, if(!myitem) continue; - ItemInst* myinst = CreateBaseItem(myitem, charges); + EQEmu::ItemInstance* myinst = CreateBaseItem(myitem, charges); if(slot < 0) slot = inv->FindFreeSlot(0, 0); @@ -436,7 +436,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) aug[4] = (uint32)atoi(row[7]); aug[5] = (uint32)atoi(row[8]); - const EQEmu::ItemBase *item = GetItem(item_id); + const EQEmu::ItemData *item = GetItem(item_id); if (!item) { Log.Out(Logs::General, Logs::Error, @@ -447,7 +447,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) int16 put_slot_id = INVALID_INDEX; - ItemInst *inst = CreateBaseItem(item, charges); + EQEmu::ItemInstance *inst = CreateBaseItem(item, charges); if (inst && item->IsClassCommon()) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { if (aug[i]) @@ -539,7 +539,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) uint32 ornament_idfile = (uint32)atoul(row[13]); uint32 ornament_hero_model = (uint32)atoul(row[14]); - const EQEmu::ItemBase *item = GetItem(item_id); + const EQEmu::ItemData *item = GetItem(item_id); if (!item) { Log.Out(Logs::General, Logs::Error, @@ -550,7 +550,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) int16 put_slot_id = INVALID_INDEX; - ItemInst *inst = CreateBaseItem(item, charges); + EQEmu::ItemInstance *inst = CreateBaseItem(item, charges); if (inst == nullptr) continue; @@ -679,12 +679,12 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) uint32 ornament_idfile = (uint32)atoul(row[13]); uint32 ornament_hero_model = (uint32)atoul(row[14]); - const EQEmu::ItemBase *item = GetItem(item_id); + const EQEmu::ItemData *item = GetItem(item_id); int16 put_slot_id = INVALID_INDEX; if (!item) continue; - ItemInst *inst = CreateBaseItem(item, charges); + EQEmu::ItemInstance *inst = CreateBaseItem(item, charges); if (inst == nullptr) continue; @@ -816,7 +816,7 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { mutex.Lock(); std::string file_name = Config->SharedMemDir + prefix + std::string("items"); items_mmf = std::unique_ptr(new EQEmu::MemoryMappedFile(file_name)); - items_hash = std::unique_ptr>(new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), items_mmf->Size())); + items_hash = std::unique_ptr>(new EQEmu::FixedMemoryHashSet(reinterpret_cast(items_mmf->Get()), items_mmf->Size())); mutex.Unlock(); } catch(std::exception& ex) { Log.Out(Logs::General, Logs::Error, "Error Loading Items: %s", ex.what()); @@ -828,7 +828,7 @@ bool SharedDatabase::LoadItems(const std::string &prefix) { void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id) { - EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); + EQEmu::FixedMemoryHashSet hash(reinterpret_cast(data), size, items, max_item_id); std::string ndbuffer; bool disableNoRent = false; @@ -856,7 +856,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } } - EQEmu::ItemBase item; + EQEmu::ItemData item; const std::string query = "SELECT source," #define F(x) "`"#x"`," @@ -869,7 +869,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } for (auto row = results.begin(); row != results.end(); ++row) { - memset(&item, 0, sizeof(EQEmu::ItemBase)); + memset(&item, 0, sizeof(EQEmu::ItemData)); item.ItemClass = (uint8)atoi(row[ItemField::itemclass]); strcpy(item.Name, row[ItemField::name]); @@ -1086,7 +1086,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ } } -const EQEmu::ItemBase* SharedDatabase::GetItem(uint32 id) { +const EQEmu::ItemData* SharedDatabase::GetItem(uint32 id) { if (id == 0) { return nullptr; @@ -1105,7 +1105,7 @@ const EQEmu::ItemBase* SharedDatabase::GetItem(uint32 id) { return nullptr; } -const EQEmu::ItemBase* SharedDatabase::IterateItems(uint32* id) { +const EQEmu::ItemData* SharedDatabase::IterateItems(uint32* id) { if(!items_hash || !id) { return nullptr; } @@ -1250,18 +1250,18 @@ bool SharedDatabase::LoadNPCFactionLists(const std::string &prefix) { return true; } -// Create appropriate ItemInst class -ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) +// Create appropriate EQEmu::ItemInstance class +EQEmu::ItemInstance* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) { - const EQEmu::ItemBase* item = nullptr; - ItemInst* inst = nullptr; + const EQEmu::ItemData* item = nullptr; + EQEmu::ItemInstance* inst = nullptr; item = GetItem(item_id); if (item) { inst = CreateBaseItem(item, charges); if (inst == nullptr) { - Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItem()"); + Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateItem()"); Log.Out(Logs::General, Logs::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges); return nullptr; } @@ -1279,15 +1279,15 @@ ItemInst* SharedDatabase::CreateItem(uint32 item_id, int16 charges, uint32 aug1, } -// Create appropriate ItemInst class -ItemInst* SharedDatabase::CreateItem(const EQEmu::ItemBase* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) +// Create appropriate EQEmu::ItemInstance class +EQEmu::ItemInstance* SharedDatabase::CreateItem(const EQEmu::ItemData* item, int16 charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6, uint8 attuned) { - ItemInst* inst = nullptr; + EQEmu::ItemInstance* inst = nullptr; if (item) { inst = CreateBaseItem(item, charges); if (inst == nullptr) { - Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateItem()"); + Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateItem()"); Log.Out(Logs::General, Logs::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges); return nullptr; } @@ -1304,8 +1304,8 @@ ItemInst* SharedDatabase::CreateItem(const EQEmu::ItemBase* item, int16 charges, return inst; } -ItemInst* SharedDatabase::CreateBaseItem(const EQEmu::ItemBase* item, int16 charges) { - ItemInst* inst = nullptr; +EQEmu::ItemInstance* SharedDatabase::CreateBaseItem(const EQEmu::ItemData* item, int16 charges) { + EQEmu::ItemInstance* inst = nullptr; if (item) { // if maxcharges is -1 that means it is an unlimited use item. // set it to 1 charge so that it is usable on creation @@ -1315,10 +1315,10 @@ ItemInst* SharedDatabase::CreateBaseItem(const EQEmu::ItemBase* item, int16 char if(charges <= 0 && item->Stackable) charges = 1; - inst = new ItemInst(item, charges); + inst = new EQEmu::ItemInstance(item, charges); if (inst == nullptr) { - Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for ItemInst creation in SharedDatabase::CreateBaseItem()"); + Log.Out(Logs::General, Logs::Error, "Error: valid item data returned a null reference for EQEmu::ItemInstance creation in SharedDatabase::CreateBaseItem()"); Log.Out(Logs::General, Logs::Error, "Item Data = ID: %u, Name: %s, Charges: %i", item->ID, item->Name, charges); return nullptr; } diff --git a/common/shareddb.h b/common/shareddb.h index 68e1821d3..42dfcf4ce 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -34,7 +34,6 @@ class EvolveInfo; class Inventory; -class ItemInst; struct BaseDataStruct; struct InspectMessage_Struct; struct PlayerProfile_Struct; @@ -45,7 +44,8 @@ struct LootDrop_Struct; namespace EQEmu { - struct ItemBase; + struct ItemData; + class ItemInstance; class MemoryMappedFile; } @@ -76,13 +76,13 @@ class SharedDatabase : public Database /* Character Inventory */ - bool SaveCursor(uint32 char_id, std::list::const_iterator &start, std::list::const_iterator &end); - bool SaveInventory(uint32 char_id, const ItemInst* inst, int16 slot_id); + bool SaveCursor(uint32 char_id, std::list::const_iterator &start, std::list::const_iterator &end); + bool SaveInventory(uint32 char_id, const EQEmu::ItemInstance* inst, int16 slot_id); bool DeleteSharedBankSlot(uint32 char_id, int16 slot_id); bool DeleteInventorySlot(uint32 char_id, int16 slot_id); - bool UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id); - bool UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id); - bool VerifyInventory(uint32 account_id, int16 slot_id, const ItemInst* inst); + bool UpdateInventorySlot(uint32 char_id, const EQEmu::ItemInstance* inst, int16 slot_id); + bool UpdateSharedBankSlot(uint32 char_id, const EQEmu::ItemInstance* inst, int16 slot_id); + bool VerifyInventory(uint32 account_id, int16 slot_id, const EQEmu::ItemInstance* inst); bool GetSharedBank(uint32 id, Inventory* inv, bool is_charid); int32 GetSharedPlatinum(uint32 account_id); bool SetSharedPlatinum(uint32 account_id, int32 amount_to_add); @@ -99,9 +99,9 @@ class SharedDatabase : public Database /* Item Methods */ - ItemInst* CreateItem(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); - ItemInst* CreateItem(const EQEmu::ItemBase* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); - ItemInst* CreateBaseItem(const EQEmu::ItemBase* item, int16 charges = 0); + EQEmu::ItemInstance* CreateItem(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); + EQEmu::ItemInstance* CreateItem(const EQEmu::ItemData* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0); + EQEmu::ItemInstance* CreateBaseItem(const EQEmu::ItemData* item, int16 charges = 0); /* Shared Memory crap @@ -111,8 +111,8 @@ class SharedDatabase : public Database void GetItemsCount(int32 &item_count, uint32 &max_id); void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id); bool LoadItems(const std::string &prefix); - const EQEmu::ItemBase* IterateItems(uint32* id); - const EQEmu::ItemBase* GetItem(uint32 id); + const EQEmu::ItemData* IterateItems(uint32* id); + const EQEmu::ItemData* GetItem(uint32 id); const EvolveInfo* GetEvolveInfo(uint32 loregroup); //faction lists @@ -149,7 +149,7 @@ class SharedDatabase : public Database std::unique_ptr skill_caps_mmf; std::unique_ptr items_mmf; - std::unique_ptr> items_hash; + std::unique_ptr> items_hash; std::unique_ptr faction_mmf; std::unique_ptr> faction_hash; std::unique_ptr loot_table_mmf; diff --git a/shared_memory/items.cpp b/shared_memory/items.cpp index b58382420..6923fea3d 100644 --- a/shared_memory/items.cpp +++ b/shared_memory/items.cpp @@ -35,7 +35,7 @@ void LoadItems(SharedDatabase *database, const std::string &prefix) { EQ_EXCEPT("Shared Memory", "Unable to get any items from the database."); } - uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); + uint32 size = static_cast(EQEmu::FixedMemoryHashSet::estimated_size(items, max_item)); auto Config = EQEmuConfig::get(); std::string file_name = Config->SharedMemDir + prefix + std::string("items"); diff --git a/tests/fixed_memory_test.h b/tests/fixed_memory_test.h index 244394ce5..055a85d79 100644 --- a/tests/fixed_memory_test.h +++ b/tests/fixed_memory_test.h @@ -27,7 +27,7 @@ class FixedMemoryHashTest : public Test::Suite { typedef void(FixedMemoryHashTest::*TestFunction)(void); public: FixedMemoryHashTest() { - size_ = EQEmu::FixedMemoryHashSet::estimated_size(72000, 190000); + size_ = EQEmu::FixedMemoryHashSet::estimated_size(72000, 190000); data_ = new uint8[size_]; memset(data_, 0, size_); TEST_ADD(FixedMemoryHashTest::InitTest); @@ -49,7 +49,7 @@ public: private: void InitTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_, 72000, 190000); + EQEmu::FixedMemoryHashSet hash(data_, size_, 72000, 190000); TEST_ASSERT(!hash.exists(1001)); TEST_ASSERT(hash.size() == 0); TEST_ASSERT(hash.max_size() == 72000); @@ -57,7 +57,7 @@ public: } void LoadTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(!hash.exists(1001)); TEST_ASSERT(hash.size() == 0); TEST_ASSERT(hash.max_size() == 72000); @@ -65,8 +65,8 @@ public: } void InsertTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - EQEmu::ItemBase item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::ItemData item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Iron Sword"); item.ID = 1001; @@ -79,20 +79,20 @@ public: } void RetrieveTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 1); TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - EQEmu::ItemBase item = hash[1001]; + EQEmu::ItemData item = hash[1001]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1001); } void OverwriteTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - EQEmu::ItemBase item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::ItemData item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Steel Sword"); item.ID = 1001; @@ -105,20 +105,20 @@ public: } void OverwriteRetrieveTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 1); TEST_ASSERT((hash.max_size() == 72000)); TEST_ASSERT(!hash.empty()); - EQEmu::ItemBase item = hash[1001]; + EQEmu::ItemData item = hash[1001]; TEST_ASSERT(strcmp(item.Name, "Steel Sword") == 0); TEST_ASSERT(item.ID == 1001); } void InsertAgainTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - EQEmu::ItemBase item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::ItemData item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Iron Sword"); item.ID = 1000; @@ -132,14 +132,14 @@ public: } void RetrieveAgainTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.size() == 2); TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - EQEmu::ItemBase item = hash[1000]; + EQEmu::ItemData item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); @@ -149,8 +149,8 @@ public: } void InsertBeginTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - EQEmu::ItemBase item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::ItemData item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Bronze Sword"); item.ID = 0; @@ -165,7 +165,7 @@ public: } void RetrieveBeginTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.exists(0)); @@ -173,7 +173,7 @@ public: TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - EQEmu::ItemBase item = hash[1000]; + EQEmu::ItemData item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); @@ -187,8 +187,8 @@ public: } void InsertEndTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); - EQEmu::ItemBase item; + EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::ItemData item; memset(&item, 0, sizeof(item)); strcpy(item.Name, "Jade Sword"); item.ID = 190000; @@ -204,7 +204,7 @@ public: } void RetrieveEndTest() { - EQEmu::FixedMemoryHashSet hash(data_, size_); + EQEmu::FixedMemoryHashSet hash(data_, size_); TEST_ASSERT(hash.exists(1000)); TEST_ASSERT(hash.exists(1001)); TEST_ASSERT(hash.exists(0)); @@ -213,7 +213,7 @@ public: TEST_ASSERT(hash.max_size() == 72000); TEST_ASSERT(!hash.empty()); - EQEmu::ItemBase item = hash[1000]; + EQEmu::ItemData item = hash[1000]; TEST_ASSERT(strcmp(item.Name, "Iron Sword") == 0); TEST_ASSERT(item.ID == 1000); diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 205663ea5..858a84323 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -245,8 +245,8 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou /* Load Inventory */ // If we ensure that the material data is updated appropriately, we can do away with inventory loads if (GetInventory(accountID, cse->Name, &inv)) { - const EQEmu::ItemBase* item = nullptr; - const ItemInst* inst = nullptr; + const EQEmu::ItemData* item = nullptr; + const EQEmu::ItemInstance* inst = nullptr; int16 invslot = 0; for (uint32 matslot = 0; matslot < EQEmu::textures::TextureCount; matslot++) { diff --git a/zone/aa.cpp b/zone/aa.cpp index 97b444311..b1fadf5e8 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -423,7 +423,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration) uint32 sitem = 0; sitem = CorpseToUse->GetWornItem(x); if(sitem){ - const EQEmu::ItemBase * itm = database.GetItem(sitem); + const EQEmu::ItemData * itm = database.GetItem(sitem); npca->AddLootDrop(itm, &npca->itemlist, 1, 1, 255, true, true); } } diff --git a/zone/attack.cpp b/zone/attack.cpp index 9b83f7994..45de2d6b8 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -51,12 +51,12 @@ extern WorldServer worldserver; extern EntityList entity_list; extern Zone* zone; -bool Mob::AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const ItemInst* weapon) +bool Mob::AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const EQEmu::ItemInstance* weapon) { // Determine animation int type = 0; if (weapon && weapon->IsClassCommon()) { - const EQEmu::ItemBase* item = weapon->GetItem(); + const EQEmu::ItemData* item = weapon->GetItem(); Log.Out(Logs::Detail, Logs::Attack, "Weapon skill : %i", item->ItemType); @@ -786,9 +786,9 @@ int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, //Returns the weapon damage against the input mob //if we cannot hit the mob with the current weapon we will get a value less than or equal to zero //Else we know we can hit. -//GetWeaponDamage(mob*, const ItemBase*) is intended to be used for mobs or any other situation where we do not have a client inventory item -//GetWeaponDamage(mob*, const ItemInst*) is intended to be used for situations where we have a client inventory item -int Mob::GetWeaponDamage(Mob *against, const EQEmu::ItemBase *weapon_item) { +//GetWeaponDamage(mob*, const EQEmu::ItemData*) is intended to be used for mobs or any other situation where we do not have a client inventory item +//GetWeaponDamage(mob*, const EQEmu::ItemInstance*) is intended to be used for situations where we have a client inventory item +int Mob::GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item) { int dmg = 0; int banedmg = 0; @@ -888,7 +888,7 @@ int Mob::GetWeaponDamage(Mob *against, const EQEmu::ItemBase *weapon_item) { return dmg; } -int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate) +int Mob::GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate) { int dmg = 0; int banedmg = 0; @@ -927,7 +927,7 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate } else { bool MagicGloves = false; if (IsClient()) { - const ItemInst *gloves = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotHands); + const EQEmu::ItemInstance *gloves = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotHands); if (gloves) MagicGloves = gloves->GetItemMagical(true); } @@ -1035,7 +1035,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if (GetFeigned()) return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code. - ItemInst* weapon; + EQEmu::ItemInstance* weapon; if (Hand == EQEmu::legacy::SlotSecondary){ // Kaiyodo - Pick weapon from the attacking hand weapon = GetInv().GetItem(EQEmu::legacy::SlotSecondary); OffHandAtk(true); @@ -1114,7 +1114,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemBase*) nullptr); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; @@ -1125,7 +1125,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if (Hand == EQEmu::legacy::SlotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemBase*) nullptr, true); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr, true); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; @@ -1593,7 +1593,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool } //figure out what weapon they are using, if any - const EQEmu::ItemBase* weapon = nullptr; + const EQEmu::ItemData* weapon = nullptr; if (Hand == EQEmu::legacy::SlotPrimary && equipment[EQEmu::legacy::SlotPrimary] > 0) weapon = database.GetItem(equipment[EQEmu::legacy::SlotPrimary]); else if (equipment[EQEmu::legacy::SlotSecondary]) @@ -1645,7 +1645,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool //do attack animation regardless of whether or not we can hit below int16 charges = 0; - ItemInst weapon_inst(weapon, charges); + EQEmu::ItemInstance weapon_inst(weapon, charges); AttackAnimation(skillinuse, Hand, &weapon_inst); //basically "if not immune" then do the attack @@ -2515,7 +2515,7 @@ void Mob::DamageShield(Mob* attacker, bool spell_ds) { } } -uint8 Mob::GetWeaponDamageBonus(const EQEmu::ItemBase *weapon, bool offhand) +uint8 Mob::GetWeaponDamageBonus(const EQEmu::ItemData *weapon, bool offhand) { // dev quote with old and new formulas // https://forums.daybreakgames.com/eq/index.php?threads/test-update-09-17-15.226618/page-5#post-3326194 @@ -3526,7 +3526,7 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) { } } -void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { +void Mob::TryWeaponProc(const EQEmu::ItemInstance* weapon_g, Mob *on, uint16 hand) { if(!on) { SetTarget(nullptr); Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to Mob::TryWeaponProc for evaluation!"); @@ -3544,12 +3544,12 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { } if(!weapon_g) { - TrySpellProc(nullptr, (const EQEmu::ItemBase*)nullptr, on); + TrySpellProc(nullptr, (const EQEmu::ItemData*)nullptr, on); return; } if (!weapon_g->IsClassCommon()) { - TrySpellProc(nullptr, (const EQEmu::ItemBase*)nullptr, on); + TrySpellProc(nullptr, (const EQEmu::ItemData*)nullptr, on); return; } @@ -3562,7 +3562,7 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) { return; } -void Mob::TryWeaponProc(const ItemInst *inst, const EQEmu::ItemBase *weapon, Mob *on, uint16 hand) +void Mob::TryWeaponProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *weapon, Mob *on, uint16 hand) { if (!weapon) @@ -3612,10 +3612,10 @@ void Mob::TryWeaponProc(const ItemInst *inst, const EQEmu::ItemBase *weapon, Mob if (!proced && inst) { for (int r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { - const ItemInst *aug_i = inst->GetAugment(r); + const EQEmu::ItemInstance *aug_i = inst->GetAugment(r); if (!aug_i) // no aug, try next slot! continue; - const EQEmu::ItemBase *aug = aug_i->GetItem(); + const EQEmu::ItemData *aug = aug_i->GetItem(); if (!aug) continue; @@ -3645,7 +3645,7 @@ void Mob::TryWeaponProc(const ItemInst *inst, const EQEmu::ItemBase *weapon, Mob return; } -void Mob::TrySpellProc(const ItemInst *inst, const EQEmu::ItemBase *weapon, Mob *on, uint16 hand) +void Mob::TrySpellProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *weapon, Mob *on, uint16 hand) { float ProcBonus = static_cast(spellbonuses.SpellProcChance + itembonuses.SpellProcChance + aabonuses.SpellProcChance); @@ -4489,10 +4489,10 @@ void Client::SetAttackTimer() else //invalid slot (hands will always hit this) continue; - const EQEmu::ItemBase *ItemToUse = nullptr; + const EQEmu::ItemData *ItemToUse = nullptr; //find our item - ItemInst *ci = GetInv().GetItem(i); + EQEmu::ItemInstance *ci = GetInv().GetItem(i); if (ci) ItemToUse = ci->GetItem(); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index a898e02ec..240643934 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -146,13 +146,13 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { unsigned int i; // Update: MainAmmo should only calc skill mods (TODO: Check for other cases) for (i = EQEmu::legacy::SlotCharm; i <= EQEmu::legacy::SlotAmmo; i++) { - const ItemInst* inst = m_inv[i]; + const EQEmu::ItemInstance* inst = m_inv[i]; if(inst == 0) continue; AddItemBonuses(inst, newbon, false, false, 0, (i == EQEmu::legacy::SlotAmmo)); //These are given special flags due to how often they are checked for various spell effects. - const EQEmu::ItemBase *item = inst->GetItem(); + const EQEmu::ItemData *item = inst->GetItem(); if (i == EQEmu::legacy::SlotSecondary && (item && item->ItemType == EQEmu::item::ItemTypeShield)) SetShieldEquiped(true); else if (i == EQEmu::legacy::SlotPrimary && (item && item->ItemType == EQEmu::item::ItemType2HBlunt)) { @@ -166,14 +166,14 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { //Power Source Slot if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - const ItemInst* inst = m_inv[EQEmu::legacy::SlotPowerSource]; + const EQEmu::ItemInstance* inst = m_inv[EQEmu::legacy::SlotPowerSource]; if(inst) AddItemBonuses(inst, newbon); } //tribute items for (i = 0; i < EQEmu::legacy::TRIBUTE_SIZE; i++) { - const ItemInst* inst = m_inv[EQEmu::legacy::TRIBUTE_BEGIN + i]; + const EQEmu::ItemInstance* inst = m_inv[EQEmu::legacy::TRIBUTE_BEGIN + i]; if(inst == 0) continue; AddItemBonuses(inst, newbon, false, true); @@ -182,7 +182,7 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { //Optional ability to have worn effects calculate as an addititive bonus instead of highest value if (RuleI(Spells, AdditiveBonusWornType) && RuleI(Spells, AdditiveBonusWornType) != EQEmu::item::ItemEffectWorn){ for (i = EQEmu::legacy::SlotCharm; i < EQEmu::legacy::SlotAmmo; i++) { - const ItemInst* inst = m_inv[i]; + const EQEmu::ItemInstance* inst = m_inv[i]; if(inst == 0) continue; AdditiveWornBonuses(inst, newbon); @@ -208,7 +208,7 @@ void Client::ProcessItemCaps() itembonuses.ATK = std::min(itembonuses.ATK, CalcItemATKCap()); } -void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAug, bool isTribute, int rec_override, bool ammo_slot_item) +void Client::AddItemBonuses(const EQEmu::ItemInstance *inst, StatBonuses *newbon, bool isAug, bool isTribute, int rec_override, bool ammo_slot_item) { if (!inst || !inst->IsClassCommon()) { return; @@ -218,7 +218,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu return; } - const EQEmu::ItemBase *item = inst->GetItem(); + const EQEmu::ItemData *item = inst->GetItem(); if (!isTribute && !inst->IsEquipable(GetBaseRace(), GetClass())) { if (item->ItemType != EQEmu::item::ItemTypeFood && item->ItemType != EQEmu::item::ItemTypeDrink) @@ -532,7 +532,7 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAu } } -void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug) { +void Client::AdditiveWornBonuses(const EQEmu::ItemInstance *inst, StatBonuses* newbon, bool isAug) { /* Powerful Non-live like option allows developers to add worn effects on items that @@ -550,7 +550,7 @@ void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool if(inst->GetAugmentType()==0 && isAug == true) return; - const EQEmu::ItemBase *item = inst->GetItem(); + const EQEmu::ItemData *item = inst->GetItem(); if(!inst->IsEquipable(GetBaseRace(),GetClass())) return; @@ -580,9 +580,9 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { { if (food && drink) break; - const ItemInst* inst = GetInv().GetItem(i); + const EQEmu::ItemInstance* inst = GetInv().GetItem(i); if (inst && inst->GetItem() && inst->IsClassCommon()) { - const EQEmu::ItemBase *item = inst->GetItem(); + const EQEmu::ItemData *item = inst->GetItem(); if (item->ItemType == EQEmu::item::ItemTypeFood && !food) food = true; else if (item->ItemType == EQEmu::item::ItemTypeDrink && !drink) @@ -596,9 +596,9 @@ void Client::CalcEdibleBonuses(StatBonuses* newbon) { { if (food && drink) break; - const ItemInst* inst = GetInv().GetItem(i); + const EQEmu::ItemInstance* inst = GetInv().GetItem(i); if (inst && inst->GetItem() && inst->IsClassCommon()) { - const EQEmu::ItemBase *item = inst->GetItem(); + const EQEmu::ItemData *item = inst->GetItem(); if (item->ItemType == EQEmu::item::ItemTypeFood && !food) food = true; else if (item->ItemType == EQEmu::item::ItemTypeDrink && !drink) @@ -3205,7 +3205,7 @@ void NPC::CalcItemBonuses(StatBonuses *newbon) if(newbon){ for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++){ - const EQEmu::ItemBase *cur = database.GetItem(equipment[i]); + const EQEmu::ItemData *cur = database.GetItem(equipment[i]); if(cur){ //basic stats newbon->AC += cur->AC; @@ -3317,7 +3317,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { if (i == EQEmu::legacy::SlotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot continue; - ItemInst* inst = m_inv.GetItem(i); + EQEmu::ItemInstance* inst = m_inv.GetItem(i); if(inst == nullptr) continue; @@ -3325,7 +3325,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) if (i >= EQEmu::legacy::GENERAL_BAGS_BEGIN && i <= EQEmu::legacy::GENERAL_BAGS_END) { - ItemInst* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); + EQEmu::ItemInstance* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; } @@ -3346,7 +3346,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { //iterate all augments for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) { - ItemInst * a_inst = inst->GetAugment(x); + EQEmu::ItemInstance * a_inst = inst->GetAugment(x); if(!a_inst) continue; @@ -3410,7 +3410,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { if (i == EQEmu::legacy::SlotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot continue; - ItemInst* inst = m_inv.GetItem(i); + EQEmu::ItemInstance* inst = m_inv.GetItem(i); if(!inst) continue; @@ -3418,7 +3418,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) if (i >= EQEmu::legacy::GENERAL_BAGS_BEGIN && i <= EQEmu::legacy::GENERAL_BAGS_END) { - ItemInst* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); + EQEmu::ItemInstance* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; } @@ -3449,7 +3449,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { //iterate all augments for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) { - ItemInst *a_inst = inst->GetAugment(x); + EQEmu::ItemInstance *a_inst = inst->GetAugment(x); if(!a_inst) continue; diff --git a/zone/bot.cpp b/zone/bot.cpp index a3dd19b2d..072f99bcd 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -229,13 +229,13 @@ void Bot::SetBotSpellID(uint32 newSpellID) { } uint32 Bot::GetBotArcheryRange() { - const ItemInst *range_inst = GetBotItem(EQEmu::legacy::SlotRange); - const ItemInst *ammo_inst = GetBotItem(EQEmu::legacy::SlotAmmo); + const EQEmu::ItemInstance *range_inst = GetBotItem(EQEmu::legacy::SlotRange); + const EQEmu::ItemInstance *ammo_inst = GetBotItem(EQEmu::legacy::SlotAmmo); if (!range_inst || !ammo_inst) return 0; - const EQEmu::ItemBase *range_item = range_inst->GetItem(); - const EQEmu::ItemBase *ammo_item = ammo_inst->GetItem(); + const EQEmu::ItemData *range_item = range_inst->GetItem(); + const EQEmu::ItemData *ammo_item = ammo_inst->GetItem(); if (!range_item || !ammo_item || range_item->ItemType != EQEmu::item::ItemTypeBow || ammo_item->ItemType != EQEmu::item::ItemTypeArrow) return 0; @@ -1900,13 +1900,13 @@ void Bot::BotRangedAttack(Mob* other) { return; } - ItemInst* rangedItem = GetBotItem(EQEmu::legacy::SlotRange); - const EQEmu::ItemBase* RangeWeapon = 0; + EQEmu::ItemInstance* rangedItem = GetBotItem(EQEmu::legacy::SlotRange); + const EQEmu::ItemData* RangeWeapon = 0; if(rangedItem) RangeWeapon = rangedItem->GetItem(); - ItemInst* ammoItem = GetBotItem(EQEmu::legacy::SlotAmmo); - const EQEmu::ItemBase* Ammo = 0; + EQEmu::ItemInstance* ammoItem = GetBotItem(EQEmu::legacy::SlotAmmo); + const EQEmu::ItemData* Ammo = 0; if(ammoItem) Ammo = ammoItem->GetItem(); @@ -2015,7 +2015,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: int32 min_hit = 1; int32 max_hit = ((2 * weapon_damage * GetDamageTable(skillinuse)) / 100); if(GetLevel() >= 28 && IsWarriorClass()) { - int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::ItemBase*) nullptr); + int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::ItemData*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -2056,8 +2056,8 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: damage = -5; if (skillinuse == EQEmu::skills::SkillBash){ - const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); - const EQEmu::ItemBase* botweapon = 0; + const EQEmu::ItemInstance* inst = GetBotItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemData* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -2116,8 +2116,8 @@ void Bot::ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int3 } if (item_slot >= EQEmu::legacy::EQUIPMENT_BEGIN){ - const ItemInst* inst = GetBotItem(item_slot); - const EQEmu::ItemBase* botweapon = 0; + const EQEmu::ItemInstance* inst = GetBotItem(item_slot); + const EQEmu::ItemData* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -2451,7 +2451,7 @@ void Bot::AI_Process() { if(attack_timer.Check()) { Attack(GetTarget(), EQEmu::legacy::SlotPrimary); TriggerDefensiveProcs(GetTarget(), EQEmu::legacy::SlotPrimary, false); - ItemInst *wpn = GetBotItem(EQEmu::legacy::SlotPrimary); + EQEmu::ItemInstance *wpn = GetBotItem(EQEmu::legacy::SlotPrimary); TryWeaponProc(wpn, GetTarget(), EQEmu::legacy::SlotPrimary); bool tripleSuccess = false; if(BotOwner && GetTarget() && CanThisClassDoubleAttack()) { @@ -2480,7 +2480,7 @@ void Bot::AI_Process() { int32 ExtraAttackChanceBonus = (spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance); if (GetTarget() && ExtraAttackChanceBonus) { - ItemInst *wpn = GetBotItem(EQEmu::legacy::SlotPrimary); + EQEmu::ItemInstance *wpn = GetBotItem(EQEmu::legacy::SlotPrimary); if(wpn) { if (wpn->GetItem()->IsType2HWeapon()) { if(zone->random.Int(0, 100) < ExtraAttackChanceBonus) @@ -2504,8 +2504,8 @@ void Bot::AI_Process() { //now off hand if(GetTarget() && attack_dw_timer.Check() && CanThisClassDualWield()) { - const ItemInst* instweapon = GetBotItem(EQEmu::legacy::SlotSecondary); - const EQEmu::ItemBase* weapon = 0; + const EQEmu::ItemInstance* instweapon = GetBotItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemData* weapon = 0; //can only dual wield without a weapon if you're a monk if(instweapon || (botClass == MONK)) { if(instweapon) @@ -2527,7 +2527,7 @@ void Bot::AI_Process() { float random = zone->random.Real(0, 1); if (random < DualWieldProbability){ // Max 78% of DW Attack(GetTarget(), EQEmu::legacy::SlotSecondary); // Single attack with offhand - ItemInst *wpn = GetBotItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance *wpn = GetBotItem(EQEmu::legacy::SlotSecondary); TryWeaponProc(wpn, GetTarget(), EQEmu::legacy::SlotSecondary); if( CanThisClassDoubleAttack() && CheckBotDoubleAttack()) { if(GetTarget() && GetTarget()->GetHP() > -10) @@ -2952,8 +2952,8 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; ns->spawn.helm = helmtexture; //(GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.equip_chest2 = texture; //0xFF; - const EQEmu::ItemBase* item = 0; - const ItemInst* inst = 0; + const EQEmu::ItemData* item = 0; + const EQEmu::ItemInstance* inst = 0; uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); for (int i = 0; i < EQEmu::textures::TexturePrimary; i++) { @@ -3224,8 +3224,8 @@ void Bot::SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 } // Returns the item id that is in the bot inventory collection for the specified slot. -ItemInst* Bot::GetBotItem(uint32 slotID) { - ItemInst* item = m_inv.GetItem(slotID); +EQEmu::ItemInstance* Bot::GetBotItem(uint32 slotID) { + EQEmu::ItemInstance* item = m_inv.GetItem(slotID); if(item) return item; @@ -3266,7 +3266,7 @@ void Bot::BotRemoveEquipItem(int slot) { } } -void Bot::BotTradeSwapItem(Client* client, int16 lootSlot, const ItemInst* inst, const ItemInst* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap) { +void Bot::BotTradeSwapItem(Client* client, int16 lootSlot, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap) { if(!errorMessage->empty()) return; @@ -3289,7 +3289,7 @@ void Bot::BotTradeSwapItem(Client* client, int16 lootSlot, const ItemInst* inst, } } -void Bot::BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb) +void Bot::BotTradeAddItem(uint32 id, const EQEmu::ItemInstance* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb) { if(addToDb) { if (!botdb.SaveItemBySlot(this, lootSlot, inst)) { @@ -3383,7 +3383,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli bool already_returned = false; Inventory& clientInventory = client->GetInv(); - const ItemInst* inst = clientInventory[i]; + const EQEmu::ItemInstance* inst = clientInventory[i]; if(inst) { items[i] = inst->GetItem()->ID; charges[i] = inst->GetCharges(); @@ -3395,10 +3395,10 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli //EQoffline: will give the items to the bots and change the bot stats if(inst && (GetBotOwner() == client->CastToMob()) && !IsEngaged()) { std::string TempErrorMessage; - const EQEmu::ItemBase* mWeaponItem = inst->GetItem(); + const EQEmu::ItemData* mWeaponItem = inst->GetItem(); bool failedLoreCheck = false; for (int m = AUG_INDEX_BEGIN; m < EQEmu::legacy::ITEM_COMMON_SIZE; ++m) { - ItemInst *itm = inst->GetAugment(m); + EQEmu::ItemInstance *itm = inst->GetAugment(m); if(itm) { if(CheckLoreConflict(itm->GetItem())) { @@ -3415,7 +3415,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli if(!failedLoreCheck && mWeaponItem && inst->IsEquipable(GetBaseRace(), GetClass()) && (GetLevel() >= mWeaponItem->ReqLevel)) { BotCanWear = true; botCanWear[i] = BotCanWear; - ItemInst* swap_item = nullptr; + EQEmu::ItemInstance* swap_item = nullptr; const char* equipped[EQEmu::legacy::EQUIPMENT_SIZE + 1] = { "Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", @@ -3438,7 +3438,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } else { - ItemInst* remove_item = GetBotItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::legacy::SlotSecondary); BotTradeSwapItem(client, EQEmu::legacy::SlotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } @@ -3466,7 +3466,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } if(success) { if (GetBotItem(EQEmu::legacy::SlotPrimary)) { - ItemInst* remove_item = GetBotItem(EQEmu::legacy::SlotPrimary); + EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::legacy::SlotPrimary); if (remove_item->GetItem()->IsType2HWeapon()) { BotTradeSwapItem(client, EQEmu::legacy::SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } @@ -3491,7 +3491,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli swap_item = GetBotItem(j); failedLoreCheck = false; for (int k = AUG_INDEX_BEGIN; k < EQEmu::legacy::ITEM_COMMON_SIZE; ++k) { - ItemInst *itm = swap_item->GetAugment(k); + EQEmu::ItemInstance *itm = swap_item->GetAugment(k); if(itm) { if(client->CheckLoreConflict(itm->GetItem())) { @@ -3510,7 +3510,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli failedLoreCheck = true; } else { - ItemInst* remove_item = GetBotItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::legacy::SlotSecondary); BotTradeSwapItem(client, EQEmu::legacy::SlotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } @@ -3537,7 +3537,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli success = true; } if (success && GetBotItem(EQEmu::legacy::SlotPrimary)) { - ItemInst* remove_item = GetBotItem(EQEmu::legacy::SlotPrimary); + EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::legacy::SlotPrimary); if (remove_item->GetItem()->IsType2HWeapon()) { BotTradeSwapItem(client, EQEmu::legacy::SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } @@ -3574,7 +3574,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } - const EQEmu::ItemBase* item2 = 0; + const EQEmu::ItemData* item2 = 0; for(int y = beginSlotID; y <= endSlotID; ++y) { item2 = database.GetItem(items[y]); if(item2) { @@ -3738,7 +3738,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b } FaceTarget(GetTarget()); - ItemInst* weapon = nullptr; + EQEmu::ItemInstance* weapon = nullptr; if (Hand == EQEmu::legacy::SlotPrimary) { weapon = GetBotItem(EQEmu::legacy::SlotPrimary); OffHandAtk(false); @@ -3813,7 +3813,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemBase*) nullptr); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -3822,7 +3822,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. if (Hand == EQEmu::legacy::SlotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemBase*) nullptr); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -4280,9 +4280,9 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[bottype]) { - const EQEmu::ItemBase* TempItem = 0; - const EQEmu::ItemBase* UsedItem = 0; - const ItemInst* TempInst = 0; + const EQEmu::ItemData* TempItem = 0; + const EQEmu::ItemData* UsedItem = 0; + const EQEmu::ItemInstance* TempInst = 0; uint16 UsedFocusID = 0; int32 Total = 0; int32 focus_max = 0; @@ -4290,7 +4290,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { //item focus for (int x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::EQUIPMENT_END; x++) { TempItem = nullptr; - ItemInst* ins = GetBotItem(x); + EQEmu::ItemInstance* ins = GetBotItem(x); if (!ins) continue; @@ -4314,10 +4314,10 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { } for (int y = AUG_INDEX_BEGIN; y < EQEmu::legacy::ITEM_COMMON_SIZE; ++y) { - ItemInst *aug = nullptr; + EQEmu::ItemInstance *aug = nullptr; aug = ins->GetAugment(y); if(aug) { - const EQEmu::ItemBase* TempItemAug = aug->GetItem(); + const EQEmu::ItemData* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { focus_max = CalcBotFocusEffect(bottype, TempItemAug->Focus.Effect, spell_id, true); @@ -4864,8 +4864,8 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 hate = hate_override; if (skill == EQEmu::skills::SkillBash) { - const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); - const EQEmu::ItemBase* botweapon = 0; + const EQEmu::ItemInstance* inst = GetBotItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemData* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -4929,8 +4929,8 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { bool bIsBehind = false; bool bCanFrontalBS = false; - const ItemInst* inst = GetBotItem(EQEmu::legacy::SlotPrimary); - const EQEmu::ItemBase* botpiercer = nullptr; + const EQEmu::ItemInstance* inst = GetBotItem(EQEmu::legacy::SlotPrimary); + const EQEmu::ItemData* botpiercer = nullptr; if(inst) botpiercer = inst->GetItem(); @@ -4989,12 +4989,12 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { int32 hate = 0; int32 primaryweapondamage = 0; int32 backstab_dmg = 0; - ItemInst* botweaponInst = GetBotItem(EQEmu::legacy::SlotPrimary); + EQEmu::ItemInstance* botweaponInst = GetBotItem(EQEmu::legacy::SlotPrimary); if(botweaponInst) { primaryweapondamage = GetWeaponDamage(other, botweaponInst); backstab_dmg = botweaponInst->GetItem()->BackstabDmg; for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { - ItemInst *aug = botweaponInst->GetAugment(i); + EQEmu::ItemInstance *aug = botweaponInst->GetAugment(i); if(aug) backstab_dmg += aug->GetItem()->BackstabDmg; } @@ -5037,7 +5037,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { } void Bot::RogueAssassinate(Mob* other) { - ItemInst* botweaponInst = GetBotItem(EQEmu::legacy::SlotPrimary); + EQEmu::ItemInstance* botweaponInst = GetBotItem(EQEmu::legacy::SlotPrimary); if(botweaponInst) { if(GetWeaponDamage(other, botweaponInst)) other->Damage(this, 32000, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab); @@ -5366,8 +5366,8 @@ bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) { void Bot::EquipBot(std::string* errorMessage) { GetBotItems(m_inv, errorMessage); - const ItemInst* inst = 0; - const EQEmu::ItemBase* item = 0; + const EQEmu::ItemInstance* inst = 0; + const EQEmu::ItemData* item = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { @@ -5494,7 +5494,7 @@ void Bot::SetAttackTimer() { float haste_mod = (GetHaste() * 0.01f); attack_timer.SetAtTrigger(4000, true); Timer* TimerToUse = nullptr; - const EQEmu::ItemBase* PrimaryWeapon = nullptr; + const EQEmu::ItemData* PrimaryWeapon = nullptr; for (int i = EQEmu::legacy::SlotRange; i <= EQEmu::legacy::SlotSecondary; i++) { if (i == EQEmu::legacy::SlotPrimary) TimerToUse = &attack_timer; @@ -5505,8 +5505,8 @@ void Bot::SetAttackTimer() { else continue; - const EQEmu::ItemBase* ItemToUse = nullptr; - ItemInst* ci = GetBotItem(i); + const EQEmu::ItemData* ItemToUse = nullptr; + EQEmu::ItemInstance* ci = GetBotItem(i); if (ci) ItemToUse = ci->GetItem(); @@ -7180,8 +7180,8 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { insr->TargetID = inspectedBot->GetNPCTypeID(); insr->playerid = inspectedBot->GetID(); - const EQEmu::ItemBase* item = 0; - const ItemInst* inst = 0; + const EQEmu::ItemData* item = 0; + const EQEmu::ItemInstance* inst = 0; // Modded to display power source items (will only show up on SoF+ client inspect windows though.) // I don't think bots are currently coded to use them..but, you'll have to use '#bot inventory list' @@ -7232,10 +7232,10 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { void Bot::CalcItemBonuses(StatBonuses* newbon) { - const EQEmu::ItemBase* itemtmp = 0; + const EQEmu::ItemData* itemtmp = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { - const ItemInst* item = GetBotItem((i == 22 ? 9999 : i)); + const EQEmu::ItemInstance* item = GetBotItem((i == 22 ? 9999 : i)); if(item) { AddItemBonuses(item, newbon); } @@ -7252,7 +7252,7 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) newbon->EnduranceRegen = CalcEnduranceRegenCap(); } -void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute, int rec_override) { +void Bot::AddItemBonuses(const EQEmu::ItemInstance *inst, StatBonuses* newbon, bool isAug, bool isTribute, int rec_override) { if (!inst || !inst->IsClassCommon()) { return; @@ -7263,7 +7263,7 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, return; } - const EQEmu::ItemBase *item = inst->GetItem(); + const EQEmu::ItemData *item = inst->GetItem(); if(!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass())) { @@ -7630,7 +7630,7 @@ void Bot::CalcBotStats(bool showtext) { } } -bool Bot::CheckLoreConflict(const EQEmu::ItemBase* item) { +bool Bot::CheckLoreConflict(const EQEmu::ItemData* item) { if (!item || !(item->LoreFlag)) return false; @@ -8036,7 +8036,7 @@ uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { int Bot::GetRawACNoShield(int &shield_ac) { int ac = itembonuses.AC + spellbonuses.AC; shield_ac = 0; - ItemInst* inst = GetBotItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance* inst = GetBotItem(EQEmu::legacy::SlotSecondary); if(inst) { if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { ac -= inst->GetItem()->AC; @@ -8053,8 +8053,8 @@ int Bot::GetRawACNoShield(int &shield_ac) { } uint32 Bot::CalcCurrentWeight() { - const EQEmu::ItemBase* TempItem = 0; - ItemInst* inst; + const EQEmu::ItemData* TempItem = 0; + EQEmu::ItemInstance* inst; uint32 Total = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { inst = GetBotItem(i); @@ -8435,7 +8435,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) for (uint8 i = 0; i < EQEmu::textures::TexturePrimary; ++i) { uint8 inv_slot = Inventory::CalcSlotFromMaterial(i); - ItemInst* inst = m_inv.GetItem(inv_slot); + EQEmu::ItemInstance* inst = m_inv.GetItem(inv_slot); if (!inst) continue; @@ -8448,7 +8448,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) if (mat_slot == EQEmu::textures::TextureInvalid || mat_slot >= EQEmu::textures::TexturePrimary) return false; - ItemInst* inst = m_inv.GetItem(slot_id); + EQEmu::ItemInstance* inst = m_inv.GetItem(slot_id); if (!inst) return false; diff --git a/zone/bot.h b/zone/bot.h index 3d45475a3..5bafe1caa 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -260,7 +260,7 @@ public: virtual int32 CheckAggroAmount(uint16 spellid); virtual void CalcBonuses(); void CalcItemBonuses(StatBonuses* newbon); - void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0); + void AddItemBonuses(const EQEmu::ItemInstance *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr); virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther); @@ -382,10 +382,10 @@ public: virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0); // Bot Equipment & Inventory Class Methods - void BotTradeSwapItem(Client* client, int16 lootSlot, const ItemInst* inst, const ItemInst* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap = true); - void BotTradeAddItem(uint32 id, const ItemInst* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true); + void BotTradeSwapItem(Client* client, int16 lootSlot, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap = true); + void BotTradeAddItem(uint32 id, const EQEmu::ItemInstance* inst, int16 charges, uint32 equipableSlots, uint16 lootSlot, std::string* errorMessage, bool addToDb = true); void EquipBot(std::string* errorMessage); - bool CheckLoreConflict(const EQEmu::ItemBase* item); + bool CheckLoreConflict(const EQEmu::ItemData* item); virtual void UpdateEquipmentLight() { m_Light.Type[EQEmu::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); } // Static Class Methods @@ -457,7 +457,7 @@ public: uint32 GetBotSpellID() { return npc_spells_id; } Mob* GetBotOwner() { return this->_botOwner; } uint32 GetBotArcheryRange(); - ItemInst* GetBotItem(uint32 slotID); + EQEmu::ItemInstance* GetBotItem(uint32 slotID); virtual bool GetSpawnStatus() { return _spawnStatus; } uint8 GetPetChooserID() { return _petChooserID; } bool IsPetChooser() { return _petChooser; } diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 6b07bbdda..398a0d6b0 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -2402,7 +2402,7 @@ namespace ActionableBots mod_skill_value = base_skill_value; for (int16 index = EQEmu::legacy::EQUIPMENT_BEGIN; index <= EQEmu::legacy::EQUIPMENT_END; ++index) { - const ItemInst* indexed_item = bot_iter->GetBotItem(index); + const EQEmu::ItemInstance* indexed_item = bot_iter->GetBotItem(index); if (indexed_item && indexed_item->GetItem()->SkillModType == skill_type) mod_skill_value += (base_skill_value * (((float)indexed_item->GetItem()->SkillModValue) / 100.0f)); } @@ -7062,8 +7062,8 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) return; } - const ItemInst* inst = nullptr; - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemInstance* inst = nullptr; + const EQEmu::ItemData* item = nullptr; bool is2Hweapon = false; std::string item_link; @@ -7132,8 +7132,8 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) return; } - const EQEmu::ItemBase* itm = nullptr; - const ItemInst* itminst = my_bot->GetBotItem(slotId); + const EQEmu::ItemData* itm = nullptr; + const EQEmu::ItemInstance* itminst = my_bot->GetBotItem(slotId); if (itminst) itm = itminst->GetItem(); @@ -7146,7 +7146,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) if (!itminst) break; - ItemInst *itma = itminst->GetAugment(m); + EQEmu::ItemInstance *itma = itminst->GetAugment(m); if (!itma) continue; if (!c->CheckLoreConflict(itma->GetItem())) @@ -7235,8 +7235,8 @@ void bot_subcommand_inventory_window(Client *c, const Seperator *sep) //linker.SetLinkType(linker.linkItemInst); for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { - const EQEmu::ItemBase* item = nullptr; - const ItemInst* inst = my_bot->CastToBot()->GetBotItem(i == 22 ? EQEmu::legacy::SlotPowerSource : i); + const EQEmu::ItemData* item = nullptr; + const EQEmu::ItemInstance* inst = my_bot->CastToBot()->GetBotItem(i == 22 ? EQEmu::legacy::SlotPowerSource : i); if (inst) item = inst->GetItem(); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 182f4e09f..8e4ddc203 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1064,7 +1064,7 @@ bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) uint32 item_id = atoi(row[1]); uint16 item_charges = (uint16)atoi(row[2]); - ItemInst* item_inst = database.CreateItem( + EQEmu::ItemInstance* item_inst = database.CreateItem( item_id, item_charges, (uint32)atoul(row[9]), @@ -1177,7 +1177,7 @@ bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint return true; } -bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const ItemInst* item_inst) +bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const EQEmu::ItemInstance* item_inst) { if (!bot_inst || !bot_inst->GetBotID() || (slot_id > EQEmu::legacy::EQUIPMENT_END && slot_id != EQEmu::legacy::SlotPowerSource)) return false; diff --git a/zone/bot_database.h b/zone/bot_database.h index 5ade661c2..3eaaf21d9 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -31,10 +31,14 @@ class Bot; -class ItemInst; class Inventory; struct BotsAvailableList; +namespace EQEmu +{ + class ItemInstance; +} + class BotDatabase : public DBcore { @@ -91,7 +95,7 @@ public: bool LoadItemBySlot(Bot* bot_inst); bool LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint32& item_id); - bool SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const ItemInst* item_inst); + bool SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const EQEmu::ItemInstance* item_inst); bool DeleteItemBySlot(const uint32 bot_id, const uint32 slot_id); bool LoadEquipmentColor(const uint32 bot_id, const uint8 material_slot_id, uint32& rgb); diff --git a/zone/client.cpp b/zone/client.cpp index 3a7b60eb5..c0b8078bb 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2017,7 +2017,7 @@ void Client::ReadBook(BookRequest_Struct *book) { out->window = book->window; if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - const ItemInst *inst = m_inv[book->invslot]; + const EQEmu::ItemInstance *inst = m_inv[book->invslot]; if(inst) out->type = inst->GetItem()->Book; else @@ -2549,7 +2549,7 @@ void Client::SetFeigned(bool in_feigned) { feigned=in_feigned; } -void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::ItemBase* item, bool buying) +void Client::LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::ItemData* item, bool buying) { if(!player || !merchant || !item) return; @@ -2796,7 +2796,7 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail) } void Client::SetMaterial(int16 in_slot, uint32 item_id) { - const EQEmu::ItemBase* item = database.GetItem(item_id); + const EQEmu::ItemData* item = database.GetItem(item_id); if (item && item->IsClassCommon()) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); @@ -3839,7 +3839,7 @@ void Client::SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID) { return; } -void Client::SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu::ItemBase* item){ +void Client::SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu::ItemData* item){ auto outapp = new EQApplicationPacket(OP_PickPocket, sizeof(sPickPocket_Struct)); sPickPocket_Struct *pick_out = (sPickPocket_Struct *)outapp->pBuffer; pick_out->coin = amt; @@ -4013,7 +4013,7 @@ bool Client::KeyRingCheck(uint32 item_id) void Client::KeyRingList() { Message(4,"Keys on Keyring:"); - const EQEmu::ItemBase *item = 0; + const EQEmu::ItemData *item = 0; for (auto iter = keyring.begin(); iter != keyring.end(); ++iter) { if ((item = database.GetItem(*iter))!=nullptr) { Message(4,item->Name); @@ -5440,7 +5440,7 @@ bool Client::TryReward(uint32 claim_id) uint32 free_slot = 0xFFFFFFFF; for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; ++i) { - ItemInst *item = GetInv().GetItem(i); + EQEmu::ItemInstance *item = GetInv().GetItem(i); if (!item) { free_slot = i; break; @@ -5486,7 +5486,7 @@ bool Client::TryReward(uint32 claim_id) } auto &ivr = (*iter); - ItemInst *claim = database.CreateItem(ivr.items[0].item_id, ivr.items[0].charges); + EQEmu::ItemInstance *claim = database.CreateItem(ivr.items[0].item_id, ivr.items[0].charges); if (!claim) { Save(); return true; @@ -5496,7 +5496,7 @@ bool Client::TryReward(uint32 claim_id) for (int y = 1; y < 8; y++) if (ivr.items[y].item_id && claim->GetItem()->ItemClass == 1) { - ItemInst *item_temp = database.CreateItem(ivr.items[y].item_id, ivr.items[y].charges); + EQEmu::ItemInstance *item_temp = database.CreateItem(ivr.items[y].item_id, ivr.items[y].charges); if (item_temp) { if (CheckLoreConflict(item_temp->GetItem())) { lore_conflict = true; @@ -5756,8 +5756,8 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { insr->TargetID = requester->GetID(); insr->playerid = requestee->GetID(); - const EQEmu::ItemBase* item = nullptr; - const ItemInst* inst = nullptr; + const EQEmu::ItemData* item = nullptr; + const EQEmu::ItemInstance* inst = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); for(int16 L = 0; L <= 20; L++) { inst = requestee->GetInv().GetItem(L); @@ -5768,7 +5768,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { strcpy(insr->itemnames[L], item->Name); if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - const EQEmu::ItemBase *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const EQEmu::ItemData *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); insr->itemicons[L] = aug_item->Icon; } else if (inst && inst->GetOrnamentationIcon()) @@ -6949,7 +6949,7 @@ void Client::SendAltCurrencies() { uint32 i = 0; auto iter = zone->AlternateCurrencies.begin(); while(iter != zone->AlternateCurrencies.end()) { - const EQEmu::ItemBase* item = database.GetItem((*iter).item_id); + const EQEmu::ItemData* item = database.GetItem((*iter).item_id); altc->entries[i].currency_number = (*iter).id; altc->entries[i].unknown00 = 1; altc->entries[i].currency_number2 = (*iter).id; @@ -7604,7 +7604,7 @@ void Client::DuplicateLoreMessage(uint32 ItemID) return; } - const EQEmu::ItemBase *item = database.GetItem(ItemID); + const EQEmu::ItemData *item = database.GetItem(ItemID); if(!item) return; @@ -8075,7 +8075,7 @@ void Client::TickItemCheck() void Client::TryItemTick(int slot) { int iid = 0; - const ItemInst* inst = m_inv[slot]; + const EQEmu::ItemInstance* inst = m_inv[slot]; if(inst == 0) { return; } iid = inst->GetID(); @@ -8084,7 +8084,7 @@ void Client::TryItemTick(int slot) { if (GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot <= EQEmu::legacy::EQUIPMENT_END)) { - ItemInst* e_inst = (ItemInst*)inst; + EQEmu::ItemInstance* e_inst = (EQEmu::ItemInstance*)inst; parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); } } @@ -8094,7 +8094,7 @@ void Client::TryItemTick(int slot) for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) { - ItemInst * a_inst = inst->GetAugment(x); + EQEmu::ItemInstance * a_inst = inst->GetAugment(x); if(!a_inst) { continue; } iid = a_inst->GetID(); @@ -8103,7 +8103,7 @@ void Client::TryItemTick(int slot) { if( GetLevel() >= zone->tick_items[iid].level && zone->random.Int(0, 100) >= (100 - zone->tick_items[iid].chance) ) { - ItemInst* e_inst = (ItemInst*)a_inst; + EQEmu::ItemInstance* e_inst = (EQEmu::ItemInstance*)a_inst; parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot); } } @@ -8131,7 +8131,7 @@ void Client::ItemTimerCheck() void Client::TryItemTimer(int slot) { - ItemInst* inst = m_inv.GetItem(slot); + EQEmu::ItemInstance* inst = m_inv.GetItem(slot); if(!inst) { return; } @@ -8151,7 +8151,7 @@ void Client::TryItemTimer(int slot) for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) { - ItemInst * a_inst = inst->GetAugment(x); + EQEmu::ItemInstance * a_inst = inst->GetAugment(x); if(!a_inst) { continue; } @@ -8167,7 +8167,7 @@ void Client::TryItemTimer(int slot) } } -void Client::SendItemScale(ItemInst *inst) { +void Client::SendItemScale(EQEmu::ItemInstance *inst) { int slot = m_inv.GetSlotByItemInst(inst); if(slot != -1) { inst->ScaleItem(); @@ -8321,7 +8321,7 @@ void Client::SetConsumption(int32 in_hunger, int32 in_thirst) safe_delete(outapp); } -void Client::Consume(const EQEmu::ItemBase *item, uint8 type, int16 slot, bool auto_consume) +void Client::Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool auto_consume) { if(!item) { return; } @@ -8436,7 +8436,7 @@ void Client::ShowNumHits() int Client::GetQuiverHaste(int delay) { - const ItemInst *pi = nullptr; + const EQEmu::ItemInstance *pi = nullptr; for (int r = EQEmu::legacy::GENERAL_BEGIN; r <= EQEmu::legacy::GENERAL_END; r++) { pi = GetInv().GetItem(r); if (pi && pi->IsClassBag() && pi->GetItem()->BagType == EQEmu::item::BagTypeQuiver && diff --git a/zone/client.h b/zone/client.h index 75ce82bf5..cc5abb88d 100644 --- a/zone/client.h +++ b/zone/client.h @@ -31,7 +31,7 @@ enum WaterRegionType : int; namespace EQEmu { - struct ItemBase; + struct ItemData; } #include "../common/timer.h" @@ -250,7 +250,7 @@ public: void KeyRingList(); virtual bool IsClient() const { return true; } void CompleteConnect(); - bool TryStacking(ItemInst* item, uint8 type = ItemPacketTrade, bool try_worn = true, bool try_cursor = true); + bool TryStacking(EQEmu::ItemInstance* item, uint8 type = ItemPacketTrade, bool try_worn = true, bool try_cursor = true); void SendTraderPacket(Client* trader, uint32 Unknown72 = 51); void SendBuyerPacket(Client* Buyer); GetItems_Struct* GetTraderItems(); @@ -273,7 +273,7 @@ public: void SendTraderItem(uint32 item_id,uint16 quantity); uint16 FindTraderItem(int32 SerialNumber,uint16 Quantity); uint32 FindTraderItemSerialNumber(int32 ItemID); - ItemInst* FindTraderItemBySerialNumber(int32 SerialNumber); + EQEmu::ItemInstance* FindTraderItemBySerialNumber(int32 SerialNumber); void FindAndNukeTraderItem(int32 item_id,uint16 quantity,Client* customer,uint16 traderslot); void NukeTraderItem(uint16 slot, int16 charges, uint16 quantity, Client* customer, uint16 traderslot, int32 uniqueid, int32 itemid = 0); void ReturnTraderReq(const EQApplicationPacket* app,int16 traderitemcharges, uint32 itemid = 0); @@ -294,7 +294,7 @@ public: void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); virtual bool Process(); - void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::ItemBase* item, bool buying); + void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::ItemData* item, bool buying); void SendPacketQueue(bool Block = true); void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone); void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL); @@ -308,7 +308,7 @@ public: void LearnRecipe(uint32 recipeID); bool CanIncreaseTradeskill(EQEmu::skills::SkillType tradeskill); - EQApplicationPacket* ReturnItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType packet_type); + EQApplicationPacket* ReturnItemPacket(int16 slot_id, const EQEmu::ItemInstance* inst, ItemPacketType packet_type); bool GetRevoked() const { return revoked; } void SetRevoked(bool rev) { revoked = rev; } @@ -403,7 +403,7 @@ public: inline uint8 GetLanguageSkill(uint16 n) const { return m_pp.languages[n]; } - void SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu::ItemBase* item = nullptr); + void SendPickPocketResponse(Mob *from, uint32 amt, int type, const EQEmu::ItemData* item = nullptr); inline const char* GetLastName() const { return lastname; } @@ -601,7 +601,7 @@ public: void AssignToInstance(uint16 instance_id); void RemoveFromInstance(uint16 instance_id); void WhoAll(); - bool CheckLoreConflict(const EQEmu::ItemBase* item); + bool CheckLoreConflict(const EQEmu::ItemData* item); void ChangeLastName(const char* in_lastname); void GetGroupAAs(GroupLeadershipAA_Struct *into) const; void GetRaidAAs(RaidLeadershipAA_Struct *into) const; @@ -813,25 +813,25 @@ public: void Undye(); int32 GetItemIDAt(int16 slot_id); int32 GetAugmentIDAt(int16 slot_id, uint8 augslot); - bool PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client_update = false); - bool PushItemOnCursor(const ItemInst& inst, bool client_update = false); + bool PutItemInInventory(int16 slot_id, const EQEmu::ItemInstance& inst, bool client_update = false); + bool PushItemOnCursor(const EQEmu::ItemInstance& inst, bool client_update = false); void SendCursorBuffer(); void DeleteItemInInventory(int16 slot_id, int8 quantity = 0, bool client_update = false, bool update_db = true); bool SwapItem(MoveItem_Struct* move_in); void SwapItemResync(MoveItem_Struct* move_slots); void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false); - void PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data = 0); - bool AutoPutLootInInventory(ItemInst& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0); + void PutLootInInventory(int16 slot_id, const EQEmu::ItemInstance &inst, ServerLootItem_Struct** bag_item_data = 0); + bool AutoPutLootInInventory(EQEmu::ItemInstance& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0); bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = EQEmu::legacy::SlotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); - int GetItemLinkHash(const ItemInst* inst); // move to ItemBase..or make use of the pre-calculated database field + int GetItemLinkHash(const EQEmu::ItemInstance* inst); // move to ItemData..or make use of the pre-calculated database field - void SendItemLink(const ItemInst* inst, bool sendtoall=false); - void SendLootItemInPacket(const ItemInst* inst, int16 slot_id); - void SendItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType packet_type); + void SendItemLink(const EQEmu::ItemInstance* inst, bool sendtoall=false); + void SendLootItemInPacket(const EQEmu::ItemInstance* inst, int16 slot_id); + void SendItemPacket(int16 slot_id, const EQEmu::ItemInstance* inst, ItemPacketType packet_type); bool IsValidSlot(uint32 slot); bool IsBankSlot(uint32 slot); @@ -887,7 +887,7 @@ public: //Calculate vendor price modifier based on CHA: (reverse==selling) float CalcPriceMod(Mob* other = 0, bool reverse = false); void ResetTrade(); - void DropInst(const ItemInst* inst); + void DropInst(const EQEmu::ItemInstance* inst); bool TrainDiscipline(uint32 itemid); void TrainDiscBySpellID(int32 spell_id); int GetDiscSlotBySpellID(int32 spellid); @@ -965,7 +965,7 @@ public: inline void UpdateTasksForItem(ActivityType Type, int ItemID, int Count=1) { if(taskstate) taskstate->UpdateTasksForItem(this, Type, ItemID, Count); } inline void UpdateTasksOnExplore(int ExploreID) { if(taskstate) taskstate->UpdateTasksOnExplore(this, ExploreID); } inline bool UpdateTasksOnSpeakWith(int NPCTypeID) { if(taskstate) return taskstate->UpdateTasksOnSpeakWith(this, NPCTypeID); else return false; } - inline bool UpdateTasksOnDeliver(std::list& Items, int Cash, int NPCTypeID) { if (taskstate) return taskstate->UpdateTasksOnDeliver(this, Items, Cash, NPCTypeID); else return false; } + inline bool UpdateTasksOnDeliver(std::list& Items, int Cash, int NPCTypeID) { if (taskstate) return taskstate->UpdateTasksOnDeliver(this, Items, Cash, NPCTypeID); else return false; } inline void TaskSetSelector(Mob *mob, int TaskSetID) { if(taskmanager) taskmanager->TaskSetSelector(this, taskstate, mob, TaskSetID); } inline void EnableTask(int TaskCount, int *TaskList) { if(taskstate) taskstate->EnableTask(CharacterID(), TaskCount, TaskList); } inline void DisableTask(int TaskCount, int *TaskList) { if(taskstate) taskstate->DisableTask(CharacterID(), TaskCount, TaskList); } @@ -1080,7 +1080,7 @@ public: inline bool GetPendingGuildInvitation() { return PendingGuildInvitation; } void LocateCorpse(); void SendTargetCommand(uint32 EntityID); - bool MoveItemToInventory(ItemInst *BInst, bool UpdateClient = false); + bool MoveItemToInventory(EQEmu::ItemInstance *BInst, bool UpdateClient = false); void HandleRespawnFromHover(uint32 Option); bool IsHoveringForRespawn() { return RespawnFromHoverTimer.Enabled(); } std::list respawn_options; @@ -1173,7 +1173,7 @@ public: void TryItemTick(int slot); void ItemTimerCheck(); void TryItemTimer(int slot); - void SendItemScale(ItemInst *inst); + void SendItemScale(EQEmu::ItemInstance *inst); int32 GetActSTR() { return( std::min(GetMaxSTR(), GetSTR()) ); } int32 GetActSTA() { return( std::min(GetMaxSTA(), GetSTA()) ); } @@ -1186,10 +1186,10 @@ public: void SetAccountFlag(std::string flag, std::string val); std::string GetAccountFlag(std::string flag); float GetDamageMultiplier(EQEmu::skills::SkillType how_long_has_this_been_missing); - void Consume(const EQEmu::ItemBase *item, uint8 type, int16 slot, bool auto_consume); + void Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool auto_consume); void PlayMP3(const char* fname); void ExpeditionSay(const char *str, int ExpID); - int mod_client_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const ItemInst* weapon, Mob* other); + int mod_client_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::ItemInstance* weapon, Mob* other); bool mod_client_message(char* message, uint8 chan_num); bool mod_can_increase_skill(EQEmu::skills::SkillType skillid, Mob* against_who); int16 mod_increase_skill_chance(int16 chance, Mob* against_who); @@ -1201,16 +1201,16 @@ public: int16 mod_pet_power(int16 act_power, uint16 spell_id); float mod_tradeskill_chance(float chance, DBTradeskillRecipe_Struct *spec); float mod_tradeskill_skillup(float chance_stage2); - int32 mod_tribute_item_value(int32 pts, const ItemInst* item); + int32 mod_tribute_item_value(int32 pts, const EQEmu::ItemInstance* item); void mod_client_death_npc(Mob* killerMob); void mod_client_death_duel(Mob* killerMob); void mod_client_death_env(); int32 mod_client_xp(int32 in_exp, NPC *npc); uint32 mod_client_xp_for_level(uint32 xp, uint16 check_level); int mod_client_haste_cap(int cap); - int mod_consume(EQEmu::ItemBase *item, EQEmu::item::ItemType type, int change); - int mod_food_value(const EQEmu::ItemBase *item, int change); - int mod_drink_value(const EQEmu::ItemBase *item, int change); + int mod_consume(EQEmu::ItemData *item, EQEmu::item::ItemType type, int change); + int mod_food_value(const EQEmu::ItemData *item, int change); + int mod_drink_value(const EQEmu::ItemData *item, int change); void SetEngagedRaidTarget(bool value) { EngagedRaidTarget = value; } bool GetEngagedRaidTarget() const { return EngagedRaidTarget; } @@ -1244,8 +1244,8 @@ public: protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); - void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0, bool ammo_slot_item = false); - void AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false); + void AddItemBonuses(const EQEmu::ItemInstance *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0, bool ammo_slot_item = false); + void AdditiveWornBonuses(const EQEmu::ItemInstance *inst, StatBonuses* newbon, bool isAug = false); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); void CalcEdibleBonuses(StatBonuses* newbon); void ProcessItemCaps(); @@ -1286,7 +1286,7 @@ private: void OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 InstanceID, float x, float y, float z); void OPMemorizeSpell(const EQApplicationPacket *app); void OPMoveCoin(const EQApplicationPacket* app); - void MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type); + void MoveItemCharges(EQEmu::ItemInstance &from, int16 to_slot, uint8 type); void OPGMTraining(const EQApplicationPacket *app); void OPGMEndTraining(const EQApplicationPacket *app); void OPGMTrainSkill(const EQApplicationPacket *app); @@ -1561,8 +1561,8 @@ private: bool interrogateinv_flag; // used to minimize log spamming by players - void InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const ItemInst* inst, const ItemInst* parent, bool log, bool silent, bool &error, int depth); - bool InterrogateInventory_error(int16 head, int16 index, const ItemInst* inst, const ItemInst* parent, int depth); + void InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* parent, bool log, bool silent, bool &error, int depth); + bool InterrogateInventory_error(int16 head, int16 index, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* parent, int depth); }; #endif diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index c57fc340f..69f1444f1 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -486,7 +486,7 @@ int32 Client::GetRawItemAC() int32 Total = 0; // this skips MainAmmo..add an '=' conditional if that slot is required (original behavior) for (int16 slot_id = EQEmu::legacy::EQUIPMENT_BEGIN; slot_id < EQEmu::legacy::EQUIPMENT_END; slot_id++) { - const ItemInst* inst = m_inv[slot_id]; + const EQEmu::ItemInstance* inst = m_inv[slot_id]; if (inst && inst->IsClassCommon()) { Total += inst->GetItem()->AC; } @@ -1316,8 +1316,8 @@ int32 Client::CalcManaRegenCap() uint32 Client::CalcCurrentWeight() { - const EQEmu::ItemBase* TempItem = 0; - ItemInst* ins; + const EQEmu::ItemData* TempItem = 0; + EQEmu::ItemInstance* ins; uint32 Total = 0; int x; for (x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::SlotCursor; x++) { // include cursor or not? @@ -1350,7 +1350,7 @@ uint32 Client::CalcCurrentWeight() bagslot += 1; } } - ItemInst* baginst = GetInv().GetItem(bagslot); + EQEmu::ItemInstance* baginst = GetInv().GetItem(bagslot); if (baginst && baginst->GetItem() && baginst->IsClassBag()) { reduction = baginst->GetItem()->BagWR; } @@ -2219,7 +2219,7 @@ int Client::GetRawACNoShield(int &shield_ac) const { int ac = itembonuses.AC + spellbonuses.AC + aabonuses.AC; shield_ac = 0; - const ItemInst *inst = m_inv.GetItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemInstance *inst = m_inv.GetItem(EQEmu::legacy::SlotSecondary); if (inst) { if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { ac -= inst->GetItem()->AC; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 6fc45fee0..a8c96e146 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1690,7 +1690,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /* First item cursor is sent in bulk inventory packet */ if (iter == m_inv.cursor_cbegin()) continue; - const ItemInst *inst = *iter; + const EQEmu::ItemInstance *inst = *iter; SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketLimbo); } } @@ -1883,7 +1883,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) merchantid = tmp->CastToNPC()->MerchantType; - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; bool found = false; std::list merlist = zone->merchanttable[merchantid]; std::list::const_iterator itr; @@ -2026,7 +2026,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) if (item->MaxCharges != 0) charges = item->MaxCharges; - ItemInst *inst = database.CreateItem(item, charges); + EQEmu::ItemInstance *inst = database.CreateItem(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) { PutLootInInventory(EQEmu::legacy::SlotCursor, *inst); @@ -2059,7 +2059,7 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app) merchantid = tmp->CastToNPC()->MerchantType; tmp->CastToNPC()->FaceTarget(this->CastToMob()); - const EQEmu::ItemBase *item = 0; + const EQEmu::ItemData *item = 0; std::list merlist = zone->merchanttable[merchantid]; std::list::const_iterator itr; for (itr = merlist.begin(); itr != merlist.end() && count<255; ++itr){ @@ -2158,8 +2158,8 @@ void Client::Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app) return; } - const EQEmu::ItemBase* item = database.GetItem(itemid); - ItemInst* inst = GetInv().GetItem(ams_in->slot); + const EQEmu::ItemData* item = database.GetItem(itemid); + EQEmu::ItemInstance* inst = GetInv().GetItem(ams_in->slot); if (!item || !inst){ Message(13, "You seemed to have misplaced that item..."); return; @@ -2435,7 +2435,7 @@ void Client::Handle_OP_AltCurrencyMerchantRequest(const EQApplicationPacket *app ss << alt_cur_id << "|1|" << alt_cur_id; uint32 count = 0; uint32 merchant_id = tar->MerchantType; - const EQEmu::ItemBase *item = nullptr; + const EQEmu::ItemData *item = nullptr; std::list merlist = zone->merchanttable[merchant_id]; std::list::const_iterator itr; @@ -2495,7 +2495,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) return; } - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2551,7 +2551,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) if (item->MaxCharges != 0) charges = item->MaxCharges; - ItemInst *inst = database.CreateItem(item, charges); + EQEmu::ItemInstance *inst = database.CreateItem(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) { PutLootInInventory(EQEmu::legacy::SlotCursor, *inst); @@ -2635,7 +2635,7 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) return; } - ItemInst* inst = GetInv().GetItem(sell->slot_id); + EQEmu::ItemInstance* inst = GetInv().GetItem(sell->slot_id); if (!inst) { return; } @@ -2644,7 +2644,7 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) return; } - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2732,12 +2732,12 @@ void Client::Handle_OP_AltCurrencySellSelection(const EQApplicationPacket *app) return; } - ItemInst *inst = m_inv.GetItem(select->slot_id); + EQEmu::ItemInstance *inst = m_inv.GetItem(select->slot_id); if (!inst) { return; } - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; uint32 cost = 0; uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id); uint32 merchant_id = tar->MerchantType; @@ -2816,9 +2816,9 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app) } uint32 ApplyPoisonSuccessResult = 0; ApplyPoison_Struct* ApplyPoisonData = (ApplyPoison_Struct*)app->pBuffer; - const ItemInst* PrimaryWeapon = GetInv().GetItem(EQEmu::legacy::SlotPrimary); - const ItemInst* SecondaryWeapon = GetInv().GetItem(EQEmu::legacy::SlotSecondary); - const ItemInst* PoisonItemInstance = GetInv()[ApplyPoisonData->inventorySlot]; + const EQEmu::ItemInstance* PrimaryWeapon = GetInv().GetItem(EQEmu::legacy::SlotPrimary); + const EQEmu::ItemInstance* SecondaryWeapon = GetInv().GetItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemInstance* PoisonItemInstance = GetInv()[ApplyPoisonData->inventorySlot]; bool IsPoison = PoisonItemInstance && (PoisonItemInstance->GetItem()->ItemType == EQEmu::item::ItemTypePoison); @@ -2912,7 +2912,7 @@ void Client::Handle_OP_AugmentInfo(const EQApplicationPacket *app) } AugmentInfo_Struct* AugInfo = (AugmentInfo_Struct*)app->pBuffer; - const EQEmu::ItemBase * item = database.GetItem(AugInfo->itemid); + const EQEmu::ItemData * item = database.GetItem(AugInfo->itemid); if (item) { strn0cpy(AugInfo->augment_info, item->Name, 64); @@ -2933,12 +2933,12 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) bool deleteItems = false; if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { - ItemInst *itemOneToPush = nullptr, *itemTwoToPush = nullptr; + EQEmu::ItemInstance *itemOneToPush = nullptr, *itemTwoToPush = nullptr; //Log.Out(Logs::DebugLevel::Moderate, Logs::Debug, "cslot: %i aslot: %i cidx: %i aidx: %i act: %i dest: %i", // in_augment->container_slot, in_augment->augment_slot, in_augment->container_index, in_augment->augment_index, in_augment->augment_action, in_augment->dest_inst_id); - ItemInst *tobe_auged = nullptr, *old_aug = nullptr, *new_aug = nullptr, *aug = nullptr, *solvent = nullptr; + EQEmu::ItemInstance *tobe_auged = nullptr, *old_aug = nullptr, *new_aug = nullptr, *aug = nullptr, *solvent = nullptr; Inventory& user_inv = GetInv(); uint16 item_slot = in_augment->container_slot; @@ -3494,13 +3494,13 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app) { BarterItemSearchLinkRequest_Struct* bislr = (BarterItemSearchLinkRequest_Struct*)app->pBuffer; - const EQEmu::ItemBase* item = database.GetItem(bislr->ItemID); + const EQEmu::ItemData* item = database.GetItem(bislr->ItemID); if (!item) Message(13, "Error: This item does not exist!"); else { - ItemInst* inst = database.CreateItem(item); + EQEmu::ItemInstance* inst = database.CreateItem(item); if (inst) { SendItemPacket(0, inst, ItemPacketViewLink); @@ -3527,13 +3527,13 @@ void Client::Handle_OP_Barter(const EQApplicationPacket *app) { BuyerItemSearchLinkRequest_Struct* bislr = (BuyerItemSearchLinkRequest_Struct*)app->pBuffer; - const EQEmu::ItemBase* item = database.GetItem(bislr->ItemID); + const EQEmu::ItemData* item = database.GetItem(bislr->ItemID); if (!item) Message(13, "Error: This item does not exist!"); else { - ItemInst* inst = database.CreateItem(item); + EQEmu::ItemInstance* inst = database.CreateItem(item); if (inst) { SendItemPacket(0, inst, ItemPacketViewLink); @@ -3566,14 +3566,14 @@ void Client::Handle_OP_BazaarInspect(const EQApplicationPacket *app) BazaarInspect_Struct* bis = (BazaarInspect_Struct*)app->pBuffer; - const EQEmu::ItemBase* item = database.GetItem(bis->ItemID); + const EQEmu::ItemData* item = database.GetItem(bis->ItemID); if (!item) { Message(13, "Error: This item does not exist!"); return; } - ItemInst* inst = database.CreateItem(item); + EQEmu::ItemInstance* inst = database.CreateItem(item); if (inst) { SendItemPacket(0, inst, ItemPacketViewLink); @@ -3606,7 +3606,7 @@ void Client::Handle_OP_BazaarSearch(const EQApplicationPacket *app) Client *c = entity_list.GetClientByName(nbis->Name); if (c) { - ItemInst* inst = c->FindTraderItemBySerialNumber(nbis->SerialNumber); + EQEmu::ItemInstance* inst = c->FindTraderItemBySerialNumber(nbis->SerialNumber); if (inst) SendItemPacket(0, inst, ItemPacketViewLink); } @@ -4007,11 +4007,11 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) if (m_inv.SupportsClickCasting(castspell->inventoryslot) || slot == CastingSlot::PotionBelt) // sanity check { // packet field types will be reviewed as packet transistions occur - const ItemInst* inst = m_inv[castspell->inventoryslot]; //slot values are int16, need to check packet on this field + const EQEmu::ItemInstance* inst = m_inv[castspell->inventoryslot]; //slot values are int16, need to check packet on this field //bool cancast = true; if (inst && inst->IsClassCommon()) { - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); if (item->Click.Effect != (uint32)castspell->spell_id) { database.SetMQDetectionFlag(account_name, name, "OP_CastSpell with item, tried to cast a different spell.", zone->GetShortName()); @@ -4025,7 +4025,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) { if (GetLevel() >= item->Click.Level2) { - ItemInst* p_inst = (ItemInst*)inst; + EQEmu::ItemInstance* p_inst = (EQEmu::ItemInstance*)inst; int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot); if (i == 0) { @@ -4045,7 +4045,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) } else { - ItemInst* p_inst = (ItemInst*)inst; + EQEmu::ItemInstance* p_inst = (EQEmu::ItemInstance*)inst; int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot); if (i == 0) { @@ -4857,13 +4857,13 @@ void Client::Handle_OP_Consume(const EQApplicationPacket *app) } } - ItemInst *myitem = GetInv().GetItem(pcs->slot); + EQEmu::ItemInstance *myitem = GetInv().GetItem(pcs->slot); if (myitem == nullptr) { Log.Out(Logs::General, Logs::Error, "Consuming from empty slot %d", pcs->slot); return; } - const EQEmu::ItemBase* eat_item = myitem->GetItem(); + const EQEmu::ItemData* eat_item = myitem->GetItem(); if (pcs->type == 0x01) { Consume(eat_item, EQEmu::item::ItemTypeFood, pcs->slot, (pcs->auto_consumed == 0xffffffff)); } @@ -5146,7 +5146,7 @@ void Client::Handle_OP_DeleteItem(const EQApplicationPacket *app) } DeleteItem_Struct* alc = (DeleteItem_Struct*)app->pBuffer; - const ItemInst *inst = GetInv().GetItem(alc->from_slot); + const EQEmu::ItemInstance *inst = GetInv().GetItem(alc->from_slot); if (inst && inst->GetItem()->ItemType == EQEmu::item::ItemTypeAlcohol) { entity_list.MessageClose_StringID(this, true, 50, 0, DRINKING_MESSAGE, GetName(), inst->GetItem()->Name); CheckIncreaseSkill(EQEmu::skills::SkillAlcoholTolerance, nullptr, 25); @@ -6876,7 +6876,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) if (Slot >= 0) { - ItemInst* inst = GuildBanks->GetItem(GuildID(), GuildBankMainArea, Slot, 1); + EQEmu::ItemInstance* inst = GuildBanks->GetItem(GuildID(), GuildBankMainArea, Slot, 1); if (inst) { @@ -6896,7 +6896,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) { GuildBankViewItem_Struct *gbvis = (GuildBankViewItem_Struct*)app->pBuffer; - ItemInst* inst = GuildBanks->GetItem(GuildID(), gbvis->Area, gbvis->SlotID, 1); + EQEmu::ItemInstance* inst = GuildBanks->GetItem(GuildID(), gbvis->Area, gbvis->SlotID, 1); if (!inst) break; @@ -6919,7 +6919,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) return; } - ItemInst *CursorItemInst = GetInv().GetItem(EQEmu::legacy::SlotCursor); + EQEmu::ItemInstance *CursorItemInst = GetInv().GetItem(EQEmu::legacy::SlotCursor); bool Allowed = true; @@ -6932,7 +6932,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) return; } - const EQEmu::ItemBase* CursorItem = CursorItemInst->GetItem(); + const EQEmu::ItemData* CursorItem = CursorItemInst->GetItem(); if (!CursorItem->NoDrop || CursorItemInst->IsAttuned()) { @@ -6999,7 +6999,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) GuildBankWithdrawItem_Struct *gbwis = (GuildBankWithdrawItem_Struct*)app->pBuffer; - ItemInst* inst = GuildBanks->GetItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity); + EQEmu::ItemInstance* inst = GuildBanks->GetItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity); if (!inst) { @@ -8013,17 +8013,17 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) EQApplicationPacket* outapp = app->Copy(); InspectResponse_Struct* insr = (InspectResponse_Struct*)outapp->pBuffer; Mob* tmp = entity_list.GetMob(insr->TargetID); - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); for (int16 L = EQEmu::legacy::EQUIPMENT_BEGIN; L <= EQEmu::legacy::SlotWaist; L++) { - const ItemInst* inst = GetInv().GetItem(L); + const EQEmu::ItemInstance* inst = GetInv().GetItem(L); item = inst ? inst->GetItem() : nullptr; if (item) { strcpy(insr->itemnames[L], item->Name); if (inst && inst->GetOrnamentationAug(ornamentationAugtype)) { - const EQEmu::ItemBase *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + const EQEmu::ItemData *aug_item = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); insr->itemicons[L] = aug_item->Icon; } else if (inst->GetOrnamentationIcon()) { @@ -8036,7 +8036,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) else { insr->itemicons[L] = 0xFFFFFFFF; } } - const ItemInst* inst = GetInv().GetItem(EQEmu::legacy::SlotAmmo); + const EQEmu::ItemInstance* inst = GetInv().GetItem(EQEmu::legacy::SlotAmmo); item = inst ? inst->GetItem() : nullptr; if (item) { @@ -8123,7 +8123,7 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) // todo: verify ivrs->link_hash based on a rule, in case we don't care about people being able to sniff data // from the item DB - const EQEmu::ItemBase *item = database.GetItem(ivrs->item_id); + const EQEmu::ItemData *item = database.GetItem(ivrs->item_id); if (!item) { if (ivrs->item_id != SAYLINK_ITEM_ID) { Message(13, "Error: The item for the link you have clicked on does not exist!"); @@ -8181,7 +8181,7 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) } } - ItemInst *inst = + EQEmu::ItemInstance *inst = database.CreateItem(item, item->MaxCharges, ivrs->augments[0], ivrs->augments[1], ivrs->augments[2], ivrs->augments[3], ivrs->augments[4], ivrs->augments[5]); if (inst) { @@ -8198,7 +8198,7 @@ void Client::Handle_OP_ItemLinkResponse(const EQApplicationPacket *app) return; } LDONItemViewRequest_Struct* item = (LDONItemViewRequest_Struct*)app->pBuffer; - ItemInst* inst = database.CreateItem(item->item_id); + EQEmu::ItemInstance* inst = database.CreateItem(item->item_id); if (inst) { SendItemPacket(0, inst, ItemPacketViewLink); safe_delete(inst); @@ -8214,7 +8214,7 @@ void Client::Handle_OP_ItemName(const EQApplicationPacket *app) return; } ItemNamePacket_Struct *p = (ItemNamePacket_Struct*)app->pBuffer; - const EQEmu::ItemBase *item = 0; + const EQEmu::ItemData *item = 0; if ((item = database.GetItem(p->item_id)) != nullptr) { auto outapp = new EQApplicationPacket(OP_ItemName, sizeof(ItemNamePacket_Struct)); p = (ItemNamePacket_Struct*)outapp->pBuffer; @@ -8230,7 +8230,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app) VERIFY_PACKET_LENGTH(OP_ItemPreview, app, ItemPreview_Struct); ItemPreview_Struct *ips = (ItemPreview_Struct *)app->pBuffer; - const EQEmu::ItemBase* item = database.GetItem(ips->itemid); + const EQEmu::ItemData* item = database.GetItem(ips->itemid); if (item) { auto outapp = new EQApplicationPacket(OP_ItemPreview, strlen(item->Name) + strlen(item->Lore) + @@ -8441,14 +8441,14 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) return; } - const ItemInst* inst = m_inv[slot_id]; + const EQEmu::ItemInstance* inst = m_inv[slot_id]; if (!inst) { Message(0, "Error: item not found in inventory slot #%i", slot_id); DeleteItemInInventory(slot_id, 0, true); return; } - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); if (!item) { Message(0, "Error: item not found in inventory slot #%i", slot_id); DeleteItemInInventory(slot_id, 0, true); @@ -8484,7 +8484,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) if (m_inv.SupportsClickCasting(slot_id) || ((item->ItemType == EQEmu::item::ItemTypePotion || item->PotionBelt) && m_inv.SupportsPotionBeltCasting(slot_id))) // sanity check { - ItemInst* p_inst = (ItemInst*)inst; + EQEmu::ItemInstance* p_inst = (EQEmu::ItemInstance*)inst; parse->EventItem(EVENT_ITEM_CLICK, this, p_inst, nullptr, "", slot_id); inst = m_inv[slot_id]; @@ -8495,22 +8495,22 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) int r; bool tryaug = false; - ItemInst* clickaug = 0; - EQEmu::ItemBase* augitem = 0; + EQEmu::ItemInstance* clickaug = 0; + EQEmu::ItemData* augitem = 0; for (r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { - const ItemInst* aug_i = inst->GetAugment(r); + const EQEmu::ItemInstance* aug_i = inst->GetAugment(r); if (!aug_i) continue; - const EQEmu::ItemBase* aug = aug_i->GetItem(); + const EQEmu::ItemData* aug = aug_i->GetItem(); if (!aug) continue; if ((aug->Click.Type == EQEmu::item::ItemEffectClick) || (aug->Click.Type == EQEmu::item::ItemEffectExpendable) || (aug->Click.Type == EQEmu::item::ItemEffectEquipClick) || (aug->Click.Type == EQEmu::item::ItemEffectClick2)) { tryaug = true; - clickaug = (ItemInst*)aug_i; - augitem = (EQEmu::ItemBase*)aug; + clickaug = (EQEmu::ItemInstance*)aug_i; + augitem = (EQEmu::ItemData*)aug; spell_id = aug->Click.Effect; break; } @@ -9678,8 +9678,8 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) if (mi->from_slot != mi->to_slot && (mi->from_slot <= EQEmu::legacy::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) { char *detect = nullptr; - const ItemInst *itm_from = GetInv().GetItem(mi->from_slot); - const ItemInst *itm_to = GetInv().GetItem(mi->to_slot); + const EQEmu::ItemInstance *itm_from = GetInv().GetItem(mi->from_slot); + const EQEmu::ItemInstance *itm_to = GetInv().GetItem(mi->to_slot); MakeAnyLenString(&detect, "Player issued a move item from %u(item id %u) to %u(item id %u) while casting %u.", mi->from_slot, itm_from ? itm_from->GetID() : 0, @@ -10545,7 +10545,7 @@ void Client::Handle_OP_PotionBelt(const EQApplicationPacket *app) } if (mptbs->Action == 0) { - const EQEmu::ItemBase *BaseItem = database.GetItem(mptbs->ItemID); + const EQEmu::ItemData *BaseItem = database.GetItem(mptbs->ItemID); if (BaseItem) { m_pp.potionbelt.Items[mptbs->SlotNumber].ID = BaseItem->ID; m_pp.potionbelt.Items[mptbs->SlotNumber].Icon = BaseItem->Icon; @@ -12031,12 +12031,12 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app) Shielding_Struct* shield = (Shielding_Struct*)app->pBuffer; shield_target = entity_list.GetMob(shield->target_id); bool ack = false; - ItemInst* inst = GetInv().GetItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance* inst = GetInv().GetItem(EQEmu::legacy::SlotSecondary); if (!shield_target) return; if (inst) { - const EQEmu::ItemBase* shield = inst->GetItem(); + const EQEmu::ItemData* shield = inst->GetItem(); if (shield && shield->ItemType == EQEmu::item::ItemTypeShield) { for (int x = 0; x < 2; x++) @@ -12139,7 +12139,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) break; } } - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; uint32 prevcharges = 0; if (item_id == 0) { //check to see if its on the temporary table std::list tmp_merlist = zone->tmpmerchanttable[tmp->GetNPCTypeID()]; @@ -12200,7 +12200,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) else charges = item->MaxCharges; - ItemInst* inst = database.CreateItem(item, charges); + EQEmu::ItemInstance* inst = database.CreateItem(item, charges); int SinglePrice = 0; if (RuleB(Merchant, UsePriceMod)) @@ -12321,7 +12321,7 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) qsaudit->items[0].item_id = item->ID; qsaudit->items[0].charges = mpo->quantity; - const ItemInst* audit_inst = m_inv[freeslotid]; + const EQEmu::ItemInstance* audit_inst = m_inv[freeslotid]; if (audit_inst) { qsaudit->items[0].aug_1 = audit_inst->GetAugmentItemID(0); @@ -12387,8 +12387,8 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) uint32 itemid = GetItemIDAt(mp->itemslot); if (itemid == 0) return; - const EQEmu::ItemBase* item = database.GetItem(itemid); - ItemInst* inst = GetInv().GetItem(mp->itemslot); + const EQEmu::ItemData* item = database.GetItem(itemid); + EQEmu::ItemInstance* inst = GetInv().GetItem(mp->itemslot); if (!item || !inst){ Message(13, "You seemed to have misplaced that item.."); return; @@ -12433,7 +12433,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) int freeslot = 0; if (charges > 0 && (freeslot = zone->SaveTempItem(vendor->CastToNPC()->MerchantType, vendor->GetNPCTypeID(), itemid, charges, true)) > 0){ - ItemInst* inst2 = inst->Clone(); + EQEmu::ItemInstance* inst2 = inst->Clone(); while (true) { if (inst2 == nullptr) @@ -13498,7 +13498,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) TradeItemsValid = false; break; } - const EQEmu::ItemBase *Item = database.GetItem(gis->Items[i]); + const EQEmu::ItemData *Item = database.GetItem(gis->Items[i]); if (!Item) { Message(13, "Unexpected error. Unable to start trader mode"); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 407343419..8e2ab8313 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -296,7 +296,7 @@ bool Client::Process() { } if(AutoFireEnabled()){ - ItemInst *ranged = GetInv().GetItem(EQEmu::legacy::SlotRange); + EQEmu::ItemInstance *ranged = GetInv().GetItem(EQEmu::legacy::SlotRange); if(ranged) { if (ranged->GetItem() && ranged->GetItem()->ItemType == EQEmu::item::ItemTypeBow){ @@ -391,7 +391,7 @@ bool Client::Process() { } else if (auto_attack_target->GetHP() > -10) // -10 so we can watch people bleed in PvP { - ItemInst *wpn = GetInv().GetItem(EQEmu::legacy::SlotPrimary); + EQEmu::ItemInstance *wpn = GetInv().GetItem(EQEmu::legacy::SlotPrimary); TryWeaponProc(wpn, auto_attack_target, EQEmu::legacy::SlotPrimary); DoAttackRounds(auto_attack_target, EQEmu::legacy::SlotPrimary); @@ -430,7 +430,7 @@ bool Client::Process() { else if(auto_attack_target->GetHP() > -10) { CheckIncreaseSkill(EQEmu::skills::SkillDualWield, auto_attack_target, -10); if (CheckDualWield()) { - ItemInst *wpn = GetInv().GetItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance *wpn = GetInv().GetItem(EQEmu::legacy::SlotSecondary); TryWeaponProc(wpn, auto_attack_target, EQEmu::legacy::SlotSecondary); DoAttackRounds(auto_attack_target, EQEmu::legacy::SlotSecondary); @@ -738,7 +738,7 @@ void Client::BulkSendInventoryItems() // LINKDEAD TRADE ITEMS // Move trade slot items back into normal inventory..need them there now for the proceeding validity checks for (int16 slot_id = EQEmu::legacy::TRADE_BEGIN; slot_id <= EQEmu::legacy::TRADE_END; slot_id++) { - ItemInst* inst = m_inv.PopItem(slot_id); + EQEmu::ItemInstance* inst = m_inv.PopItem(slot_id); if(inst) { bool is_arrow = (inst->GetItem()->ItemType == EQEmu::item::ItemTypeArrow) ? true : false; int16 free_slot_id = m_inv.FindFreeSlot(inst->IsClassBag(), true, inst->GetItem()->Size, is_arrow); @@ -764,7 +764,7 @@ void Client::BulkSendInventoryItems() // Possessions items for (int16 slot_id = SLOT_BEGIN; slot_id < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; slot_id++) { - const ItemInst* inst = m_inv[slot_id]; + const EQEmu::ItemInstance* inst = m_inv[slot_id]; if (!inst) continue; @@ -778,7 +778,7 @@ void Client::BulkSendInventoryItems() // PowerSource item if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - const ItemInst* inst = m_inv[EQEmu::legacy::SlotPowerSource]; + const EQEmu::ItemInstance* inst = m_inv[EQEmu::legacy::SlotPowerSource]; if (inst) { inst->Serialize(ob, EQEmu::legacy::SlotPowerSource); @@ -791,7 +791,7 @@ void Client::BulkSendInventoryItems() // Bank items for (int16 slot_id = EQEmu::legacy::BANK_BEGIN; slot_id <= EQEmu::legacy::BANK_END; slot_id++) { - const ItemInst* inst = m_inv[slot_id]; + const EQEmu::ItemInstance* inst = m_inv[slot_id]; if (!inst) continue; @@ -805,7 +805,7 @@ void Client::BulkSendInventoryItems() // SharedBank items for (int16 slot_id = EQEmu::legacy::SHARED_BANK_BEGIN; slot_id <= EQEmu::legacy::SHARED_BANK_END; slot_id++) { - const ItemInst* inst = m_inv[slot_id]; + const EQEmu::ItemInstance* inst = m_inv[slot_id]; if (!inst) continue; @@ -825,12 +825,12 @@ void Client::BulkSendInventoryItems() } void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { - const EQEmu::ItemBase* handyitem = nullptr; + const EQEmu::ItemData* handyitem = nullptr; uint32 numItemSlots = 80; //The max number of items passed in the transaction. if (m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater) { // RoF+ can send 200 items numItemSlots = 200; } - const EQEmu::ItemBase *item; + const EQEmu::ItemData *item; std::list merlist = zone->merchanttable[merchant_id]; std::list::const_iterator itr; Mob* merch = entity_list.GetMobByNpcTypeID(npcid); @@ -879,7 +879,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { int charges = 1; if (item->IsClassCommon()) charges = item->MaxCharges; - ItemInst* inst = database.CreateItem(item, charges); + EQEmu::ItemInstance* inst = database.CreateItem(item, charges); if (inst) { if (RuleB(Merchant, UsePriceMod)) { inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(merch, false))); @@ -920,7 +920,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { // charges=ml.charges; //else charges = item->MaxCharges; - ItemInst* inst = database.CreateItem(item, charges); + EQEmu::ItemInstance* inst = database.CreateItem(item, charges); if (inst) { if (RuleB(Merchant, UsePriceMod)) { inst->SetPrice((item->Price * (RuleR(Merchant, SellCostMod)) * item->SellRate * Client::CalcPriceMod(merch, false))); @@ -1095,11 +1095,11 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) switch(memspell->scribing) { case memSpellScribing: { // scribing spell to book - const ItemInst* inst = m_inv[EQEmu::legacy::SlotCursor]; + const EQEmu::ItemInstance* inst = m_inv[EQEmu::legacy::SlotCursor]; if (inst && inst->IsClassCommon()) { - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); if (RuleB(Character, RestrictSpellScribing) && !item->IsEquipable(GetRace(), GetClass())) { Message_StringID(13, CANNOT_USE_ITEM); diff --git a/zone/command.cpp b/zone/command.cpp index 86f745710..1ac321223 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2545,9 +2545,9 @@ void command_peekinv(Client *c, const Seperator *sep) } Client* targetClient = c->GetTarget()->CastToClient(); - const ItemInst* inst_main = nullptr; - const ItemInst* inst_sub = nullptr; - const EQEmu::ItemBase* item_data = nullptr; + const EQEmu::ItemInstance* inst_main = nullptr; + const EQEmu::ItemInstance* inst_sub = nullptr; + const EQEmu::ItemData* item_data = nullptr; std::string item_link; EQEmu::SayLinkEngine linker; linker.SetLinkType(EQEmu::saylink::SayLinkItemInst); @@ -2780,7 +2780,7 @@ void command_interrogateinv(Client *c, const Seperator *sep) } Client* target = nullptr; - std::map instmap; + std::map instmap; bool log = false; bool silent = false; bool error = false; @@ -3146,8 +3146,8 @@ void command_equipitem(Client *c, const Seperator *sep) { uint32 slot_id = atoi(sep->arg[1]); if (sep->IsNumber(1) && ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::legacy::SlotPowerSource))) { - const ItemInst* from_inst = c->GetInv().GetItem(EQEmu::legacy::SlotCursor); - const ItemInst* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack) + const EQEmu::ItemInstance* from_inst = c->GetInv().GetItem(EQEmu::legacy::SlotCursor); + const EQEmu::ItemInstance* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack) bool partialmove = false; int16 movecount; @@ -5519,7 +5519,7 @@ void command_summonitem(Client *c, const Seperator *sep) } int16 item_status = 0; - const EQEmu::ItemBase* item = database.GetItem(itemid); + const EQEmu::ItemData* item = database.GetItem(itemid); if (item) { item_status = static_cast(item->MinStatus); } @@ -5558,7 +5558,7 @@ void command_giveitem(Client *c, const Seperator *sep) Client *t = c->GetTarget()->CastToClient(); uint32 itemid = atoi(sep->arg[1]); int16 item_status = 0; - const EQEmu::ItemBase* item = database.GetItem(itemid); + const EQEmu::ItemData* item = database.GetItem(itemid); if(item) { item_status = static_cast(item->MinStatus); } @@ -5611,7 +5611,7 @@ void command_itemsearch(Client *c, const Seperator *sep) { const char *search_criteria=sep->argplus[1]; - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; std::string item_link; EQEmu::SayLinkEngine linker; linker.SetLinkType(EQEmu::saylink::SayLinkItemData); @@ -7126,7 +7126,7 @@ void command_path(Client *c, const Seperator *sep) void Client::Undye() { for (int cur_slot = EQEmu::textures::TextureBegin; cur_slot <= EQEmu::textures::LastTexture; cur_slot++) { uint8 slot2=SlotConvert(cur_slot); - ItemInst* inst = m_inv.GetItem(slot2); + EQEmu::ItemInstance* inst = m_inv.GetItem(slot2); if(inst != nullptr) { inst->SetColor(inst->GetItem()->Color); @@ -10235,7 +10235,7 @@ void command_zopp(Client *c, const Seperator *sep) uint32 itemid = atoi(sep->arg[3]); int16 charges = sep->argnum == 4 ? atoi(sep->arg[4]) : 1; // defaults to 1 charge if not specified - const EQEmu::ItemBase* FakeItem = database.GetItem(itemid); + const EQEmu::ItemData* FakeItem = database.GetItem(itemid); if (!FakeItem) { c->Message(13, "Error: Item [%u] is not a valid item id.", itemid); @@ -10243,7 +10243,7 @@ void command_zopp(Client *c, const Seperator *sep) } int16 item_status = 0; - const EQEmu::ItemBase* item = database.GetItem(itemid); + const EQEmu::ItemData* item = database.GetItem(itemid); if(item) { item_status = static_cast(item->MinStatus); } @@ -10257,7 +10257,7 @@ void command_zopp(Client *c, const Seperator *sep) c->Message(0, "Processing request..results may cause unpredictable behavior."); } - ItemInst* FakeItemInst = database.CreateItem(FakeItem, charges); + EQEmu::ItemInstance* FakeItemInst = database.CreateItem(FakeItem, charges); c->SendItemPacket(slotid, FakeItemInst, packettype); c->Message(0, "Sending zephyr op packet to client - [%s] %s (%u) with %i %s to slot %i.", packettype == ItemPacketTrade ? "Trade" : "Summon", FakeItem->Name, itemid, charges, diff --git a/zone/common.h b/zone/common.h index 9a5768c56..fd4ea0a89 100644 --- a/zone/common.h +++ b/zone/common.h @@ -568,7 +568,11 @@ struct MercData { uint32 NPCID; }; -class ItemInst; +namespace EQEmu +{ + class ItemInstance; +} + class Mob; // All data associated with a single trade class Trade @@ -606,7 +610,7 @@ public: private: // Send item data for trade item to other person involved in trade - void SendItemData(const ItemInst* inst, int16 dest_slot_id); + void SendItemData(const EQEmu::ItemInstance* inst, int16 dest_slot_id); uint32 with_id; Mob* owner; diff --git a/zone/corpse.cpp b/zone/corpse.cpp index ca32fc528..3690a3b4f 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -268,7 +268,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( int i; PlayerProfile_Struct *pp = &client->GetPP(); - ItemInst *item; + EQEmu::ItemInstance *item; /* Check if Zone has Graveyard First */ if(!zone->HasGraveyard()) { @@ -387,7 +387,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( Save(); } -void Corpse::MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, std::list &removedList) +void Corpse::MoveItemToCorpse(Client *client, EQEmu::ItemInstance *inst, int16 equipSlot, std::list &removedList) { AddItem( inst->GetItem()->ID, @@ -979,8 +979,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a safe_delete(outapp); if(Loot_Request_Type == 5) { int pkitem = GetPlayerKillItem(); - const EQEmu::ItemBase* item = database.GetItem(pkitem); - ItemInst* inst = database.CreateItem(item, item->MaxCharges); + const EQEmu::ItemData* item = database.GetItem(pkitem); + EQEmu::ItemInstance* inst = database.CreateItem(item, item->MaxCharges); if(inst) { if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); @@ -994,7 +994,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a } int i = 0; - const EQEmu::ItemBase* item = 0; + const EQEmu::ItemData* item = 0; ItemList::iterator cur,end; cur = itemlist.begin(); end = itemlist.end(); @@ -1013,7 +1013,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a if(i < corpselootlimit) { item = database.GetItem(item_data->item_id); if(client && item) { - ItemInst* inst = database.CreateItem(item, item_data->charges, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned); + EQEmu::ItemInstance* inst = database.CreateItem(item, item_data->charges, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned); if(inst) { if (item->RecastDelay) inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0); @@ -1110,8 +1110,8 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { being_looted_by = 0xFFFFFFFF; return; } - const EQEmu::ItemBase* item = 0; - ItemInst *inst = 0; + const EQEmu::ItemData* item = 0; + EQEmu::ItemInstance *inst = 0; ServerLootItem_Struct* item_data = nullptr, *bag_item_data[10]; memset(bag_item_data, 0, sizeof(bag_item_data)); @@ -1149,7 +1149,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { if (inst->IsAugmented()) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { - ItemInst *itm = inst->GetAugment(i); + EQEmu::ItemInstance *itm = inst->GetAugment(i); if (itm) { if (client->CheckLoreConflict(itm->GetItem())) { client->Message_StringID(0, LOOT_LORE_ERROR); @@ -1305,7 +1305,7 @@ void Corpse::QueryLoot(Client* to) { else x < corpselootlimit ? sitem->lootslot = x : sitem->lootslot = 0xFFFF; - const EQEmu::ItemBase* item = database.GetItem(sitem->item_id); + const EQEmu::ItemData* item = database.GetItem(sitem->item_id); if (item) to->Message((sitem->lootslot == 0xFFFF), "LootSlot: %i (EquipSlot: %i) Item: %s (%d), Count: %i", static_cast(sitem->lootslot), sitem->equip_slot, item->Name, item->ID, sitem->charges); @@ -1319,7 +1319,7 @@ void Corpse::QueryLoot(Client* to) { } else { sitem->lootslot=y; - const EQEmu::ItemBase* item = database.GetItem(sitem->item_id); + const EQEmu::ItemData* item = database.GetItem(sitem->item_id); if (item) to->Message(0, "LootSlot: %i Item: %s (%d), Count: %i", sitem->lootslot, item->Name, item->ID, sitem->charges); @@ -1414,7 +1414,7 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { } uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { - const EQEmu::ItemBase *item; + const EQEmu::ItemData *item; if (material_slot > EQEmu::textures::LastTexture) { return 0; diff --git a/zone/corpse.h b/zone/corpse.h index 509899827..e43c4c020 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -24,13 +24,17 @@ class Client; class EQApplicationPacket; class Group; -class ItemInst; class NPC; class Raid; struct ExtraAttackOptions; struct NPCType; +namespace EQEmu +{ + class ItemInstance; +} + #define MAX_LOOTERS 72 class Corpse : public Mob { @@ -128,7 +132,7 @@ class Corpse : public Mob { virtual void UpdateEquipmentLight(); protected: - void MoveItemToCorpse(Client *client, ItemInst *inst, int16 equipSlot, std::list &removedList); + void MoveItemToCorpse(Client *client, EQEmu::ItemInstance *inst, int16 equipSlot, std::list &removedList); private: bool is_player_corpse; /* Determines if Player Corpse or not */ diff --git a/zone/doors.cpp b/zone/doors.cpp index 9b1f41370..dd3dbd651 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -188,7 +188,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) uint8 keepoffkeyring = GetNoKeyring(); uint32 haskey = 0; uint32 playerkey = 0; - const ItemInst *lockpicks = sender->GetInv().GetItem(EQEmu::legacy::SlotCursor); + const EQEmu::ItemInstance *lockpicks = sender->GetInv().GetItem(EQEmu::legacy::SlotCursor); haskey = sender->GetInv().HasItem(keyneeded, 1); diff --git a/zone/effects.cpp b/zone/effects.cpp index 5b022f97d..e2d9d4075 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -481,7 +481,7 @@ int32 Client::GetActSpellCasttime(uint16 spell_id, int32 casttime) bool Client::TrainDiscipline(uint32 itemid) { //get the item info - const EQEmu::ItemBase *item = database.GetItem(itemid); + const EQEmu::ItemData *item = database.GetItem(itemid); if(item == nullptr) { Message(13, "Unable to find the tome you turned in!"); Log.Out(Logs::General, Logs::Error, "Unable to find turned in tome id %lu\n", (unsigned long)itemid); diff --git a/zone/embparser.cpp b/zone/embparser.cpp index 43f4c3cdc..bf9bbe5cb 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -157,7 +157,7 @@ void PerlembParser::ReloadQuests() { spell_quest_status_.clear(); } -int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob, +int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, EQEmu::ItemInstance* item_inst, Mob* mob, uint32 extradata, bool global, std::vector *extra_pointers) { if(!perl) @@ -174,9 +174,9 @@ int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * da std::string package_name; GetQuestTypes(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, - event, npcmob, iteminst, mob, global); + event, npcmob, item_inst, mob, global); GetQuestPackageName(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, - package_name, event, objid, data, npcmob, iteminst, global); + package_name, event, objid, data, npcmob, item_inst, global); const char *sub_name = QuestEventSubroutines[event]; if(!perl->SubExists(package_name.c_str(), sub_name)) { @@ -208,14 +208,14 @@ int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * da /* Check for Event export event enable */ if (parse->perl_event_export_settings[event].event_variables){ - ExportEventVariables(package_name, event, objid, data, npcmob, iteminst, mob, extradata, extra_pointers); + ExportEventVariables(package_name, event, objid, data, npcmob, item_inst, mob, extradata, extra_pointers); } if(isPlayerQuest || isGlobalPlayerQuest){ return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, nullptr); } else if(isItemQuest) { - return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, iteminst); + return SendCommands(package_name.c_str(), sub_name, 0, mob, mob, item_inst); } else if(isSpellQuest){ if(mob) { @@ -249,7 +249,7 @@ int PerlembParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::stri return EventCommon(evt, 0, data.c_str(), nullptr, nullptr, client, extra_data, true, extra_pointers); } -int PerlembParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, +int PerlembParser::EventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { // needs pointer validation on 'item' argument return EventCommon(evt, item->GetID(), nullptr, nullptr, item, client, extra_data, false, extra_pointers); @@ -348,7 +348,7 @@ bool PerlembParser::SpellHasQuestSub(uint32 spell_id, QuestEventID evt) { return(perl->SubExists(package_name.str().c_str(), subname)); } -bool PerlembParser::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) { +bool PerlembParser::ItemHasQuestSub(EQEmu::ItemInstance *itm, QuestEventID evt) { std::stringstream package_name; package_name << "qst_item_" << itm->GetID(); @@ -471,7 +471,7 @@ void PerlembParser::LoadGlobalPlayerScript(std::string filename) { global_player_quest_status_ = questLoaded; } -void PerlembParser::LoadItemScript(std::string filename, ItemInst *item) { +void PerlembParser::LoadItemScript(std::string filename, EQEmu::ItemInstance *item) { if (item == nullptr) return; @@ -642,13 +642,13 @@ void PerlembParser::ExportVar(const char *pkgprefix, const char *varname, const } } -int PerlembParser::SendCommands(const char *pkgprefix, const char *event, uint32 npcid, Mob* other, Mob* mob, ItemInst* iteminst) { +int PerlembParser::SendCommands(const char *pkgprefix, const char *event, uint32 npcid, Mob* other, Mob* mob, EQEmu::ItemInstance* item_inst) { if(!perl) return 0; int ret_value = 0; if(mob && mob->IsClient()) - quest_manager.StartQuest(other, mob->CastToClient(), iteminst); + quest_manager.StartQuest(other, mob->CastToClient(), item_inst); else quest_manager.StartQuest(other, nullptr, nullptr); @@ -711,8 +711,8 @@ int PerlembParser::SendCommands(const char *pkgprefix, const char *event, uint32 } //only export QuestItem if it's an item quest - if(iteminst) { - ItemInst* curi = quest_manager.GetQuestItem(); + if(item_inst) { + EQEmu::ItemInstance* curi = quest_manager.GetQuestItem(); snprintf(namebuf, 64, "%s::questitem", pkgprefix); SV *questitem = get_sv(namebuf, true); sv_setref_pv(questitem, "QuestItem", curi); @@ -840,7 +840,7 @@ void PerlembParser::MapFunctions() { } void PerlembParser::GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, - bool &isSpellQuest, QuestEventID event, NPC* npcmob, ItemInst* iteminst, Mob* mob, bool global) + bool &isSpellQuest, QuestEventID event, NPC* npcmob, EQEmu::ItemInstance* item_inst, Mob* mob, bool global) { if(event == EVENT_SPELL_EFFECT_CLIENT || event == EVENT_SPELL_EFFECT_NPC || @@ -854,7 +854,7 @@ void PerlembParser::GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest else { if(!npcmob && mob) { - if(!iteminst) { + if(!item_inst) { if(global) { isGlobalPlayerQuest = true; } else { @@ -869,7 +869,7 @@ void PerlembParser::GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest void PerlembParser::GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, bool &isSpellQuest, std::string &package_name, QuestEventID event, uint32 objid, const char * data, - NPC* npcmob, ItemInst* iteminst, bool global) + NPC* npcmob, EQEmu::ItemInstance* item_inst, bool global) { if(!isPlayerQuest && !isGlobalPlayerQuest && !isItemQuest && !isSpellQuest) { if(global) { @@ -881,8 +881,8 @@ void PerlembParser::GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlaye } } else if(isItemQuest) { - // need a valid ItemInst pointer check here..unsure how to cancel this process - const EQEmu::ItemBase* item = iteminst->GetItem(); + // need a valid EQEmu::ItemInstance pointer check here..unsure how to cancel this process + const EQEmu::ItemData* item = item_inst->GetItem(); package_name = "qst_item_"; package_name += itoa(item->ID); } @@ -1141,7 +1141,7 @@ void PerlembParser::ExportItemVariables(std::string &package_name, Mob *mob) { #undef HASITEM_ISNULLITEM void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID event, uint32 objid, const char * data, - NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, std::vector *extra_pointers) + NPC* npcmob, EQEmu::ItemInstance* item_inst, Mob* mob, uint32 extradata, std::vector *extra_pointers) { switch (event) { case EVENT_SAY: { @@ -1159,7 +1159,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID if(extra_pointers) { size_t sz = extra_pointers->size(); for(size_t i = 0; i < sz; ++i) { - ItemInst *inst = EQEmu::any_cast(extra_pointers->at(i)); + EQEmu::ItemInstance *inst = EQEmu::any_cast(extra_pointers->at(i)); std::string var_name = "item"; var_name += std::to_string(i + 1); @@ -1327,19 +1327,19 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID case EVENT_SCALE_CALC: case EVENT_ITEM_ENTER_ZONE: { - // need a valid ItemInst pointer check here..unsure how to cancel this process + // need a valid EQEmu::ItemInstance pointer check here..unsure how to cancel this process ExportVar(package_name.c_str(), "itemid", objid); - ExportVar(package_name.c_str(), "itemname", iteminst->GetItem()->Name); + ExportVar(package_name.c_str(), "itemname", item_inst->GetItem()->Name); break; } case EVENT_ITEM_CLICK_CAST: case EVENT_ITEM_CLICK: { - // need a valid ItemInst pointer check here..unsure how to cancel this process + // need a valid EQEmu::ItemInstance pointer check here..unsure how to cancel this process ExportVar(package_name.c_str(), "itemid", objid); - ExportVar(package_name.c_str(), "itemname", iteminst->GetItem()->Name); + ExportVar(package_name.c_str(), "itemname", item_inst->GetItem()->Name); ExportVar(package_name.c_str(), "slotid", extradata); - ExportVar(package_name.c_str(), "spell_id", iteminst->GetItem()->Click.Effect); + ExportVar(package_name.c_str(), "spell_id", item_inst->GetItem()->Click.Effect); break; } @@ -1419,10 +1419,10 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID break; } case EVENT_DROP_ITEM: { - ExportVar(package_name.c_str(), "quantity", iteminst->IsStackable() ? iteminst->GetCharges() : 1); - ExportVar(package_name.c_str(), "itemname", iteminst->GetItem()->Name); - ExportVar(package_name.c_str(), "itemid", iteminst->GetItem()->ID); - ExportVar(package_name.c_str(), "spell_id", iteminst->GetItem()->Click.Effect); + ExportVar(package_name.c_str(), "quantity", item_inst->IsStackable() ? item_inst->GetCharges() : 1); + ExportVar(package_name.c_str(), "itemname", item_inst->GetItem()->Name); + ExportVar(package_name.c_str(), "itemid", item_inst->GetItem()->ID); + ExportVar(package_name.c_str(), "spell_id", item_inst->GetItem()->Click.Effect); ExportVar(package_name.c_str(), "slotid", extradata); break; } diff --git a/zone/embparser.h b/zone/embparser.h index 9b33b1ad2..8ae3fa10e 100644 --- a/zone/embparser.h +++ b/zone/embparser.h @@ -27,11 +27,15 @@ #include #include "embperl.h" -class ItemInst; class Mob; class Client; class NPC; +namespace EQEmu +{ + class ItemInstance; +} + typedef enum { questUnloaded, @@ -52,7 +56,7 @@ public: std::vector *extra_pointers); virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers); - virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, + virtual int EventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers); @@ -62,13 +66,13 @@ public: virtual bool PlayerHasQuestSub(QuestEventID evt); virtual bool GlobalPlayerHasQuestSub(QuestEventID evt); virtual bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt); - virtual bool ItemHasQuestSub(ItemInst *itm, QuestEventID evt); + virtual bool ItemHasQuestSub(EQEmu::ItemInstance *itm, QuestEventID evt); virtual void LoadNPCScript(std::string filename, int npc_id); virtual void LoadGlobalNPCScript(std::string filename); virtual void LoadPlayerScript(std::string filename); virtual void LoadGlobalPlayerScript(std::string filename); - virtual void LoadItemScript(std::string filename, ItemInst *item); + virtual void LoadItemScript(std::string filename, EQEmu::ItemInstance *item); virtual void LoadSpellScript(std::string filename, uint32 spell_id); virtual void AddVar(std::string name, std::string val); @@ -86,16 +90,16 @@ private: void ExportVar(const char *pkgprefix, const char *varname, float value); void ExportVarComplex(const char *pkgprefix, const char *varname, const char *value); - int EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob, + int EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, EQEmu::ItemInstance* item_inst, Mob* mob, uint32 extradata, bool global, std::vector *extra_pointers); - int SendCommands(const char *pkgprefix, const char *event, uint32 npcid, Mob* other, Mob* mob, ItemInst *iteminst); + int SendCommands(const char *pkgprefix, const char *event, uint32 npcid, Mob* other, Mob* mob, EQEmu::ItemInstance *item_inst); void MapFunctions(); void GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, - bool &isSpellQuest, QuestEventID event, NPC* npcmob, ItemInst* iteminst, Mob* mob, bool global); + bool &isSpellQuest, QuestEventID event, NPC* npcmob, EQEmu::ItemInstance* item_inst, Mob* mob, bool global); void GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, bool &isSpellQuest, std::string &package_name, QuestEventID event, uint32 objid, const char * data, - NPC* npcmob, ItemInst* iteminst, bool global); + NPC* npcmob, EQEmu::ItemInstance* item_inst, bool global); void ExportCharID(const std::string &package_name, int &char_id, NPC *npcmob, Mob *mob); void ExportQGlobals(bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, bool isSpellQuest, std::string &package_name, NPC *npcmob, Mob *mob, int char_id); @@ -104,7 +108,7 @@ private: void ExportZoneVariables(std::string &package_name); void ExportItemVariables(std::string &package_name, Mob *mob); void ExportEventVariables(std::string &package_name, QuestEventID event, uint32 objid, const char * data, - NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, std::vector *extra_pointers); + NPC* npcmob, EQEmu::ItemInstance* item_inst, Mob* mob, uint32 extradata, std::vector *extra_pointers); std::map npc_quest_status_; PerlQuestStatus global_npc_quest_status_; diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index adaaf3325..c6b07e764 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -110,7 +110,7 @@ XS(XS_QuestItem_new) if (items != 1) Perl_croak(aTHX_ "Usage: QuestItem::new()"); - ItemInst* RETVAL; + EQEmu::ItemInstance* RETVAL; RETVAL = quest_manager.GetQuestItem(); ST(0) = sv_newmortal(); diff --git a/zone/embxs.cpp b/zone/embxs.cpp index 5c8769895..5a4acc36d 100644 --- a/zone/embxs.cpp +++ b/zone/embxs.cpp @@ -33,7 +33,7 @@ const char *getItemName(unsigned itemid) { - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; item = database.GetItem(itemid); if (item) diff --git a/zone/entity.cpp b/zone/entity.cpp index 4eda2e75e..2bbcdef20 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2009,7 +2009,7 @@ void EntityList::QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struc memcpy(outgbius, gbius, sizeof(GuildBankItemUpdate_Struct)); - const EQEmu::ItemBase *Item = database.GetItem(gbius->ItemID); + const EQEmu::ItemData *Item = database.GetItem(gbius->ItemID); auto it = client_list.begin(); while (it != client_list.end()) { @@ -3878,11 +3878,11 @@ void EntityList::GroupMessage(uint32 gid, const char *from, const char *message) uint16 EntityList::CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time) { - const EQEmu::ItemBase *is = database.GetItem(itemid); + const EQEmu::ItemData *is = database.GetItem(itemid); if (!is) return 0; - auto i = new ItemInst(is, is->MaxCharges); + auto i = new EQEmu::ItemInstance(is, is->MaxCharges); if (!i) return 0; diff --git a/zone/forage.cpp b/zone/forage.cpp index 324467025..b1ff0f545 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -153,9 +153,9 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, //we need this function to immediately determine, after we receive OP_Fishing, if we can even try to fish, otherwise we have to wait a while to get the failure bool Client::CanFish() { //make sure we still have a fishing pole on: - const ItemInst* Pole = m_inv[EQEmu::legacy::SlotPrimary]; + const EQEmu::ItemInstance* Pole = m_inv[EQEmu::legacy::SlotPrimary]; int32 bslot = m_inv.HasItemByUse(EQEmu::item::ItemTypeFishingBait, 1, invWhereWorn | invWherePersonal); - const ItemInst* Bait = nullptr; + const EQEmu::ItemInstance* Bait = nullptr; if (bslot != INVALID_INDEX) Bait = m_inv.GetItem(bslot); @@ -253,7 +253,7 @@ void Client::GoFish() //make sure we still have a fishing pole on: int32 bslot = m_inv.HasItemByUse(EQEmu::item::ItemTypeFishingBait, 1, invWhereWorn | invWherePersonal); - const ItemInst* Bait = nullptr; + const EQEmu::ItemInstance* Bait = nullptr; if (bslot != INVALID_INDEX) Bait = m_inv.GetItem(bslot); @@ -304,10 +304,10 @@ void Client::GoFish() food_id = common_fish_ids[index]; } - const EQEmu::ItemBase* food_item = database.GetItem(food_id); + const EQEmu::ItemData* food_item = database.GetItem(food_id); Message_StringID(MT_Skills, FISHING_SUCCESS); - ItemInst* inst = database.CreateItem(food_item, 1); + EQEmu::ItemInstance* inst = database.CreateItem(food_item, 1); if(inst != nullptr) { if(CheckLoreConflict(inst->GetItem())) { @@ -396,7 +396,7 @@ void Client::ForageItem(bool guarantee) { foragedfood = common_food_ids[index]; } - const EQEmu::ItemBase* food_item = database.GetItem(foragedfood); + const EQEmu::ItemData* food_item = database.GetItem(foragedfood); if(!food_item) { Log.Out(Logs::General, Logs::Error, "nullptr returned from database.GetItem in ClientForageItem"); @@ -421,7 +421,7 @@ void Client::ForageItem(bool guarantee) { } Message_StringID(MT_Skills, stringid); - ItemInst* inst = database.CreateItem(food_item, 1); + EQEmu::ItemInstance* inst = database.CreateItem(food_item, 1); if(inst != nullptr) { // check to make sure it isn't a foraged lore item if(CheckLoreConflict(inst->GetItem())) diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index 57f83a981..3dfa6b958 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -694,7 +694,7 @@ void GuildBankManager::SendGuildBank(Client *c) if (c->ClientVersionBit() & EQEmu::versions::bit_RoFAndLater) { auto outapp = new EQApplicationPacket(OP_GuildBankItemList, sizeof(GuildBankItemListEntry_Struct) * 240); for (int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i) { - const EQEmu::ItemBase *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); + const EQEmu::ItemData *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); if (Item) { outapp->WriteUInt8(1); outapp->WriteUInt32(guild_bank->Items.DepositArea[i].Permissions); @@ -718,7 +718,7 @@ void GuildBankManager::SendGuildBank(Client *c) outapp->SetWritePosition(outapp->GetWritePosition() + 20); // newer clients have 40 deposit slots, keep them 0 for now for (int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i) { - const EQEmu::ItemBase *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); + const EQEmu::ItemData *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); if (Item) { outapp->WriteUInt8(1); outapp->WriteUInt32(guild_bank->Items.MainArea[i].Permissions); @@ -749,7 +749,7 @@ void GuildBankManager::SendGuildBank(Client *c) { if(guild_bank->Items.DepositArea[i].ItemID > 0) { - const EQEmu::ItemBase *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); + const EQEmu::ItemData *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); if(!Item) continue; @@ -785,7 +785,7 @@ void GuildBankManager::SendGuildBank(Client *c) { if(guild_bank->Items.MainArea[i].ItemID > 0) { - const EQEmu::ItemBase *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); + const EQEmu::ItemData *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); if(!Item) continue; @@ -916,7 +916,7 @@ bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32 return false; } - const EQEmu::ItemBase *Item = database.GetItem(ItemID); + const EQEmu::ItemData *Item = database.GetItem(ItemID); GuildBankItemUpdate_Struct gbius; @@ -982,7 +982,7 @@ int GuildBankManager::Promote(uint32 guildID, int slotID) (*iter)->Items.DepositArea[slotID].ItemID = 0; - const EQEmu::ItemBase *Item = database.GetItem((*iter)->Items.MainArea[mainSlot].ItemID); + const EQEmu::ItemData *Item = database.GetItem((*iter)->Items.MainArea[mainSlot].ItemID); GuildBankItemUpdate_Struct gbius; @@ -1038,7 +1038,7 @@ void GuildBankManager::SetPermissions(uint32 guildID, uint16 slotID, uint32 perm else (*iter)->Items.MainArea[slotID].WhoFor[0] = '\0'; - const EQEmu::ItemBase *Item = database.GetItem((*iter)->Items.MainArea[slotID].ItemID); + const EQEmu::ItemData *Item = database.GetItem((*iter)->Items.MainArea[slotID].ItemID); GuildBankItemUpdate_Struct gbius; @@ -1062,7 +1062,7 @@ void GuildBankManager::SetPermissions(uint32 guildID, uint16 slotID, uint32 perm entity_list.QueueClientsGuildBankItemUpdate(&gbius, guildID); } -ItemInst* GuildBankManager::GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity) +EQEmu::ItemInstance* GuildBankManager::GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity) { auto Iterator = GetGuildBank(GuildID); @@ -1071,7 +1071,7 @@ ItemInst* GuildBankManager::GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, GuildBankItem* BankArea = nullptr; - ItemInst* inst = nullptr; + EQEmu::ItemInstance* inst = nullptr; if(Area == GuildBankDepositArea) { @@ -1169,7 +1169,7 @@ bool GuildBankManager::DeleteItem(uint32 guildID, uint16 area, uint16 slotID, ui bool deleted = true; - const EQEmu::ItemBase *Item = database.GetItem(BankArea[slotID].ItemID); + const EQEmu::ItemData *Item = database.GetItem(BankArea[slotID].ItemID); if(!Item->Stackable || (quantity >= BankArea[slotID].Quantity)) { std::string query = StringFormat("DELETE FROM `guild_bank` WHERE `guildid` = %i " @@ -1230,7 +1230,7 @@ bool GuildBankManager::MergeStacks(uint32 GuildID, uint16 SlotID) if(BankArea[SlotID].ItemID == 0) return false; - const EQEmu::ItemBase *Item = database.GetItem(BankArea[SlotID].ItemID); + const EQEmu::ItemData *Item = database.GetItem(BankArea[SlotID].ItemID); if(!Item->Stackable) return false; @@ -1328,7 +1328,7 @@ bool GuildBankManager::SplitStack(uint32 GuildID, uint16 SlotID, uint32 Quantity if(BankArea[SlotID].Quantity <= Quantity || Quantity == 0) return false; - const EQEmu::ItemBase *Item = database.GetItem(BankArea[SlotID].ItemID); + const EQEmu::ItemData *Item = database.GetItem(BankArea[SlotID].ItemID); if(!Item->Stackable) return false; diff --git a/zone/guild_mgr.h b/zone/guild_mgr.h index d06473392..abd11fd9f 100644 --- a/zone/guild_mgr.h +++ b/zone/guild_mgr.h @@ -117,7 +117,7 @@ public: bool AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32 QtyOrCharges, const char *Donator, uint8 Permissions, const char *WhoFor); int Promote(uint32 GuildID, int SlotID); void SetPermissions(uint32 GuildID, uint16 SlotID, uint32 Permissions, const char *MemberName); - ItemInst* GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity); + EQEmu::ItemInstance* GetItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity); bool DeleteItem(uint32 GuildID, uint16 Area, uint16 SlotID, uint32 Quantity); bool HasItem(uint32 GuildID, uint32 ItemID); bool IsAreaFull(uint32 GuildID, uint16 Area); diff --git a/zone/inventory.cpp b/zone/inventory.cpp index d03cac310..ae0a82ae3 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -31,7 +31,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { if (itemnum == 0) return 0; uint32 x = 0; - ItemInst *cur = nullptr; + EQEmu::ItemInstance *cur = nullptr; int i; if(where_to_check & invWhereWorn) { @@ -177,7 +177,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } -bool Client::CheckLoreConflict(const EQEmu::ItemBase* item) +bool Client::CheckLoreConflict(const EQEmu::ItemData* item) { if (!item) { return false; } if (!item->LoreFlag) { return false; } @@ -195,7 +195,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // TODO: update calling methods and script apis to handle a failure return - const EQEmu::ItemBase* item = database.GetItem(item_id); + const EQEmu::ItemData* item = database.GetItem(item_id); // make sure the item exists if(item == nullptr) { @@ -247,7 +247,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, bool enforceusable = RuleB(Inventory, EnforceAugmentUsability); for (int iter = AUG_INDEX_BEGIN; iter < EQEmu::legacy::ITEM_COMMON_SIZE; ++iter) { - const EQEmu::ItemBase* augtest = database.GetItem(augments[iter]); + const EQEmu::ItemData* augtest = database.GetItem(augments[iter]); if(augtest == nullptr) { if(augments[iter]) { @@ -528,7 +528,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // in any other situation just use charges as passed - ItemInst* inst = database.CreateItem(item, charges); + EQEmu::ItemInstance* inst = database.CreateItem(item, charges); if(inst == nullptr) { Message(13, "An unknown server error has occurred and your item was not created."); @@ -604,7 +604,7 @@ void Client::DropItem(int16 slot_id) } // Take control of item in client inventory - ItemInst *inst = m_inv.PopItem(slot_id); + EQEmu::ItemInstance *inst = m_inv.PopItem(slot_id); if(inst) { int i = parse->EventItem(EVENT_DROP_ITEM, this, inst, nullptr, "", slot_id); if(i != 0) { @@ -637,7 +637,7 @@ void Client::DropItem(int16 slot_id) } // Drop inst -void Client::DropInst(const ItemInst* inst) +void Client::DropInst(const EQEmu::ItemInstance* inst) { if (!inst) { // Item doesn't exist in inventory! @@ -660,7 +660,7 @@ void Client::DropInst(const ItemInst* inst) // Returns a slot's item ID (returns INVALID_ID if not found) int32 Client::GetItemIDAt(int16 slot_id) { - const ItemInst* inst = m_inv[slot_id]; + const EQEmu::ItemInstance* inst = m_inv[slot_id]; if (inst) return inst->GetItem()->ID; @@ -671,7 +671,7 @@ int32 Client::GetItemIDAt(int16 slot_id) { // Returns an augment's ID that's in an item (returns INVALID_ID if not found) // Pass in the slot ID of the item and which augslot you want to check (0-5) int32 Client::GetAugmentIDAt(int16 slot_id, uint8 augslot) { - const ItemInst* inst = m_inv[slot_id]; + const EQEmu::ItemInstance* inst = m_inv[slot_id]; if (inst && inst->GetAugmentItemID(augslot)) { return inst->GetAugmentItemID(augslot); } @@ -764,7 +764,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd if (m_inv[slot_id]->IsClassBag()) { for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) { - ItemInst* bagitem = m_inv[slot_id]->GetItem(bag_idx); + EQEmu::ItemInstance* bagitem = m_inv[slot_id]->GetItem(bag_idx); if(bagitem) { int16 bagslot_id = Inventory::CalcSlotId(slot_id, bag_idx); @@ -789,7 +789,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd bool isDeleted = m_inv.DeleteItem(slot_id, quantity); - const ItemInst* inst = nullptr; + const EQEmu::ItemInstance* inst = nullptr; if (slot_id == EQEmu::legacy::SlotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); if(update_db) @@ -836,7 +836,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd } } -bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update) +bool Client::PushItemOnCursor(const EQEmu::ItemInstance& inst, bool client_update) { Log.Out(Logs::Detail, Logs::Inventory, "Putting item %s (%d) on the cursor", inst.GetItem()->Name, inst.GetItem()->ID); m_inv.PushCursor(inst); @@ -853,7 +853,7 @@ bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update) // Any items already there will be removed from user's inventory // (Also saves changes back to the database: this may be optimized in the future) // client_update: Sends packet to client -bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client_update) { +bool Client::PutItemInInventory(int16 slot_id, const EQEmu::ItemInstance& inst, bool client_update) { Log.Out(Logs::Detail, Logs::Inventory, "Putting item %s (%d) into slot %d", inst.GetItem()->Name, inst.GetItem()->ID, slot_id); if (slot_id == EQEmu::legacy::SlotCursor) { // don't trust macros before conditional statements... @@ -881,7 +881,7 @@ bool Client::PutItemInInventory(int16 slot_id, const ItemInst& inst, bool client // a lot of wasted checks and calls coded above... } -void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data) +void Client::PutLootInInventory(int16 slot_id, const EQEmu::ItemInstance &inst, ServerLootItem_Struct** bag_item_data) { Log.Out(Logs::Detail, Logs::Inventory, "Putting loot item %s (%d) into slot %d", inst.GetItem()->Name, inst.GetItem()->ID, slot_id); @@ -912,7 +912,7 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI if (bag_item_data[index] == nullptr) continue; - const ItemInst *bagitem = database.CreateItem( + const EQEmu::ItemInstance *bagitem = database.CreateItem( bag_item_data[index]->item_id, bag_item_data[index]->charges, bag_item_data[index]->aug_1, @@ -948,13 +948,13 @@ void Client::PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootI CalcBonuses(); } -bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cursor){ +bool Client::TryStacking(EQEmu::ItemInstance* item, uint8 type, bool try_worn, bool try_cursor){ if(!item || !item->IsStackable() || item->GetCharges()>=item->GetItem()->StackSize) return false; int16 i; uint32 item_id = item->GetItem()->ID; for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { - ItemInst* tmp_inst = m_inv.GetItem(i); + EQEmu::ItemInstance* tmp_inst = m_inv.GetItem(i); if(tmp_inst && tmp_inst->GetItem()->ID == item_id && tmp_inst->GetCharges() < tmp_inst->GetItem()->StackSize){ MoveItemCharges(*item, i, type); CalcBonuses(); @@ -967,7 +967,7 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::legacy::ITEM_CONTAINER_SIZE; j++) { uint16 slotid = Inventory::CalcSlotId(i, j); - ItemInst* tmp_inst = m_inv.GetItem(slotid); + EQEmu::ItemInstance* tmp_inst = m_inv.GetItem(slotid); if(tmp_inst && tmp_inst->GetItem()->ID == item_id && tmp_inst->GetCharges() < tmp_inst->GetItem()->StackSize) { MoveItemCharges(*item, slotid, type); @@ -985,7 +985,7 @@ bool Client::TryStacking(ItemInst* item, uint8 type, bool try_worn, bool try_cur // Locate an available space in inventory to place an item // and then put the item there // The change will be saved to the database -bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_cursor, ServerLootItem_Struct** bag_item_data) +bool Client::AutoPutLootInInventory(EQEmu::ItemInstance& inst, bool try_worn, bool try_cursor, ServerLootItem_Struct** bag_item_data) { // #1: Try to auto equip if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel <= level && (!inst.GetItem()->Attuneable || inst.IsAttuned()) && inst.GetItem()->ItemType != EQEmu::item::ItemTypeAugmentation) { @@ -1048,9 +1048,9 @@ bool Client::AutoPutLootInInventory(ItemInst& inst, bool try_worn, bool try_curs } // helper function for AutoPutLootInInventory -void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type) +void Client::MoveItemCharges(EQEmu::ItemInstance &from, int16 to_slot, uint8 type) { - ItemInst *tmp_inst = m_inv.GetItem(to_slot); + EQEmu::ItemInstance *tmp_inst = m_inv.GetItem(to_slot); if(tmp_inst && tmp_inst->GetCharges() < tmp_inst->GetItem()->StackSize) { // this is how much room is left on the item we're stacking onto @@ -1074,7 +1074,7 @@ void Client::MoveItemCharges(ItemInst &from, int16 to_slot, uint8 type) #if 0 // TODO: needs clean-up to save references -bool MakeItemLink(char* &ret_link, const ItemBase *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint8 evolving, uint8 evolvedlevel) { +bool MakeItemLink(char* &ret_link, const ItemData *item, uint32 aug0, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint8 evolving, uint8 evolvedlevel) { //we're sending back the entire "link", minus the null characters & item name //that way, we can use it for regular links & Task links //note: initiator needs to pass us ret_link @@ -1183,13 +1183,13 @@ bool MakeItemLink(char* &ret_link, const ItemBase *item, uint32 aug0, uint32 aug } #endif -int Client::GetItemLinkHash(const ItemInst* inst) { +int Client::GetItemLinkHash(const EQEmu::ItemInstance* inst) { //pre-Titanium: http://eqitems.13th-floor.org/phpBB2/viewtopic.php?t=70&postdays=0&postorder=asc //Titanium: http://eqitems.13th-floor.org/phpBB2/viewtopic.php?t=145 if (!inst) //have to have an item to make the hash return 0; - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); char* hash_str = 0; /*register */int hash = 0; @@ -1272,7 +1272,7 @@ int Client::GetItemLinkHash(const ItemInst* inst) { } // This appears to still be in use... The core of this should be incorporated into class Client::TextLink -void Client::SendItemLink(const ItemInst* inst, bool send_to_all) +void Client::SendItemLink(const EQEmu::ItemInstance* inst, bool send_to_all) { /* @@ -1283,7 +1283,7 @@ packet with the item number in it, but I cant seem to find it right now if (!inst) return; - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); const char* name2 = &item->Name[0]; auto outapp = new EQApplicationPacket(OP_ItemLinkText, strlen(name2) + 68); char buffer2[135] = {0}; @@ -1312,7 +1312,7 @@ packet with the item number in it, but I cant seem to find it right now safe_delete(outapp); } -void Client::SendLootItemInPacket(const ItemInst* inst, int16 slot_id) +void Client::SendLootItemInPacket(const EQEmu::ItemInstance* inst, int16 slot_id) { SendItemPacket(slot_id,inst, ItemPacketTrade); } @@ -1409,7 +1409,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { Log.Out(Logs::Detail, Logs::Inventory, "Client destroyed item from cursor slot %d", move_in->from_slot); if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit - ItemInst *inst = m_inv.GetItem(EQEmu::legacy::SlotCursor); + EQEmu::ItemInstance *inst = m_inv.GetItem(EQEmu::legacy::SlotCursor); if(inst) { parse->EventItem(EVENT_DESTROY_ITEM, this, inst, nullptr, "", 0); } @@ -1453,8 +1453,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { //Setup uint32 srcitemid = 0; uint32 dstitemid = 0; - ItemInst* src_inst = m_inv.GetItem(src_slot_id); - ItemInst* dst_inst = m_inv.GetItem(dst_slot_id); + EQEmu::ItemInstance* src_inst = m_inv.GetItem(src_slot_id); + EQEmu::ItemInstance* dst_inst = m_inv.GetItem(dst_slot_id); if (src_inst){ Log.Out(Logs::Detail, Logs::Inventory, "Src slot %d has item %s (%d) with %d charges in it.", src_slot_id, src_inst->GetItem()->Name, src_inst->GetItem()->ID, src_inst->GetCharges()); srcitemid = src_inst->GetItem()->ID; @@ -1470,8 +1470,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { dstitemid = dst_inst->GetItem()->ID; } if (Trader && srcitemid>0){ - ItemInst* srcbag; - ItemInst* dstbag; + EQEmu::ItemInstance* srcbag; + EQEmu::ItemInstance* dstbag; uint32 srcbagid =0; uint32 dstbagid = 0; @@ -1517,7 +1517,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } if (src_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::legacy::SHARED_BANK_END && src_inst->IsClassBag()){ for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { - const ItemInst* baginst = src_inst->GetItem(idx); + const EQEmu::ItemInstance* baginst = src_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(src_slot_id, idx), baginst)){ DeleteItemInInventory(Inventory::CalcSlotId(src_slot_id, idx),0,false); } @@ -1532,7 +1532,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } if (dst_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::legacy::SHARED_BANK_END && dst_inst->IsClassBag()){ for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { - const ItemInst* baginst = dst_inst->GetItem(idx); + const EQEmu::ItemInstance* baginst = dst_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(dst_slot_id, idx), baginst)){ DeleteItemInInventory(Inventory::CalcSlotId(dst_slot_id, idx),0,false); } @@ -1550,12 +1550,12 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { auto ndh_inst = m_inv[src_slot_id]; std::string ndh_item_data; if (ndh_inst == nullptr) { - ndh_item_data.append("[nullptr on ItemInst*]"); + ndh_item_data.append("[nullptr on EQEmu::ItemInstance*]"); } else { auto ndh_item = ndh_inst->GetItem(); if (ndh_item == nullptr) { - ndh_item_data.append("[nullptr on ItemBase*]"); + ndh_item_data.append("[nullptr on ItemData*]"); } else { ndh_item_data.append(StringFormat("name=%s", ndh_item->Name)); @@ -1576,7 +1576,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(m_tradeskill_object != nullptr) { if (src_slot_id >= EQEmu::legacy::WORLD_BEGIN && src_slot_id <= EQEmu::legacy::WORLD_END) { // Picking up item from world container - ItemInst* inst = m_tradeskill_object->PopItem(Inventory::CalcBagIdx(src_slot_id)); + EQEmu::ItemInstance* inst = m_tradeskill_object->PopItem(Inventory::CalcBagIdx(src_slot_id)); if (inst) { PutItemInInventory(dst_slot_id, *inst, false); safe_delete(inst); @@ -1589,7 +1589,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { else if (dst_slot_id >= EQEmu::legacy::WORLD_BEGIN && dst_slot_id <= EQEmu::legacy::WORLD_END) { // Putting item into world container, which may swap (or pile onto) with existing item uint8 world_idx = Inventory::CalcBagIdx(dst_slot_id); - ItemInst* world_inst = m_tradeskill_object->PopItem(world_idx); + EQEmu::ItemInstance* world_inst = m_tradeskill_object->PopItem(world_idx); // Case 1: No item in container, unidirectional "Put" if (world_inst == nullptr) { @@ -1597,8 +1597,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { m_inv.DeleteItem(src_slot_id); } else { - const EQEmu::ItemBase* world_item = world_inst->GetItem(); - const EQEmu::ItemBase* src_item = src_inst->GetItem(); + const EQEmu::ItemData* world_item = world_inst->GetItem(); + const EQEmu::ItemData* src_item = src_inst->GetItem(); if (world_item && src_item) { // Case 2: Same item on cursor, stacks, transfer of charges needed if ((world_item->ID == src_item->ID) && src_inst->IsStackable()) { @@ -1629,7 +1629,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { else { // Case 3: Swap the item on user with item in world container // World containers don't follow normal rules for swapping - ItemInst* inv_inst = m_inv.PopItem(src_slot_id); + EQEmu::ItemInstance* inv_inst = m_inv.PopItem(src_slot_id); m_tradeskill_object->PutItem(world_idx, inv_inst); m_inv.PutItem(src_slot_id, *world_inst); safe_delete(inv_inst); @@ -1744,7 +1744,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Split into two src_inst->SetCharges(src_inst->GetCharges() - move_in->number_in_stack); Log.Out(Logs::Detail, Logs::Inventory, "Split stack of %s (%d) from slot %d to %d with stack size %d. Src keeps %d.", src_inst->GetItem()->Name, src_inst->GetItem()->ID, src_slot_id, dst_slot_id, move_in->number_in_stack, src_inst->GetCharges()); - ItemInst* inst = database.CreateItem(src_inst->GetItem(), move_in->number_in_stack); + EQEmu::ItemInstance* inst = database.CreateItem(src_inst->GetItem(), move_in->number_in_stack); m_inv.PutItem(dst_slot_id, *inst); safe_delete(inst); } @@ -1838,8 +1838,8 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { // This prevents the client from crashing when closing any 'phantom' bags - const EQEmu::ItemBase* token_struct = database.GetItem(22292); // 'Copper Coin' - ItemInst* token_inst = database.CreateItem(token_struct, 1); + const EQEmu::ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' + EQEmu::ItemInstance* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); @@ -1863,8 +1863,8 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { if(m_inv[resync_slot]) { - const EQEmu::ItemBase* token_struct = database.GetItem(22292); // 'Copper Coin' - ItemInst* token_inst = database.CreateItem(token_struct, 1); + const EQEmu::ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' + EQEmu::ItemInstance* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade); @@ -1880,8 +1880,8 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { if ((move_slots->to_slot >= EQEmu::legacy::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::legacy::CURSOR_BAG_END) || move_slots->to_slot == EQEmu::legacy::SlotPowerSource) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { - const EQEmu::ItemBase* token_struct = database.GetItem(22292); // 'Copper Coin' - ItemInst* token_inst = database.CreateItem(token_struct, 1); + const EQEmu::ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' + EQEmu::ItemInstance* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); @@ -1905,8 +1905,8 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { if(m_inv[resync_slot]) { - const EQEmu::ItemBase* token_struct = database.GetItem(22292); // 'Copper Coin' - ItemInst* token_inst = database.CreateItem(token_struct, 1); + const EQEmu::ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' + EQEmu::ItemInstance* token_inst = database.CreateItem(token_struct, 1); SendItemPacket(resync_slot, token_inst, ItemPacketTrade); SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade); @@ -1945,7 +1945,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { move_count = 0; - const ItemInst* from_inst = m_inv[postaction_call?to_slot_id:from_slot_id]; + const EQEmu::ItemInstance* from_inst = m_inv[postaction_call?to_slot_id:from_slot_id]; if(from_inst) { qsaudit->items[move_count].from_slot = from_slot_id; @@ -1960,7 +1960,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { if (from_inst->IsType(EQEmu::item::ItemClassBag)) { for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < from_inst->GetItem()->BagSlots; bag_idx++) { - const ItemInst* from_baginst = from_inst->GetItem(bag_idx); + const EQEmu::ItemInstance* from_baginst = from_inst->GetItem(bag_idx); if(from_baginst) { qsaudit->items[move_count].from_slot = Inventory::CalcSlotId(from_slot_id, bag_idx); @@ -1978,7 +1978,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { } if(to_slot_id != from_slot_id) { - const ItemInst* to_inst = m_inv[postaction_call?from_slot_id:to_slot_id]; + const EQEmu::ItemInstance* to_inst = m_inv[postaction_call?from_slot_id:to_slot_id]; if(to_inst) { qsaudit->items[move_count].from_slot = to_slot_id; @@ -1993,7 +1993,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { if (to_inst->IsType(EQEmu::item::ItemClassBag)) { for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < to_inst->GetItem()->BagSlots; bag_idx++) { - const ItemInst* to_baginst = to_inst->GetItem(bag_idx); + const EQEmu::ItemInstance* to_baginst = to_inst->GetItem(bag_idx); if(to_baginst) { qsaudit->items[move_count].from_slot = Inventory::CalcSlotId(to_slot_id, bag_idx); @@ -2027,7 +2027,7 @@ void Client::DyeArmor(EQEmu::TintProfile* dye){ if (slot != INVALID_INDEX){ DeleteItemInInventory(slot,1,true); uint8 slot2=SlotConvert(i); - ItemInst* inst = this->m_inv.GetItem(slot2); + EQEmu::ItemInstance* inst = this->m_inv.GetItem(slot2); if(inst){ uint32 armor_color = ((uint32)dye->Slot[i].Red << 16) | ((uint32)dye->Slot[i].Green << 8) | ((uint32)dye->Slot[i].Blue); inst->SetColor(armor_color); @@ -2057,8 +2057,8 @@ void Client::DyeArmor(EQEmu::TintProfile* dye){ #if 0 bool Client::DecreaseByItemType(uint32 type, uint8 amt) { - const ItemBase* TempItem = 0; - ItemInst* ins; + const ItemData* TempItem = 0; + EQEmu::ItemInstance* ins; int x; for(x=EQEmu::legacy::POSSESSIONS_BEGIN; x <= EQEmu::legacy::POSSESSIONS_END; x++) { @@ -2109,8 +2109,8 @@ bool Client::DecreaseByItemType(uint32 type, uint8 amt) { #endif bool Client::DecreaseByID(uint32 type, uint8 amt) { - const EQEmu::ItemBase* TempItem = nullptr; - ItemInst* ins = nullptr; + const EQEmu::ItemData* TempItem = nullptr; + EQEmu::ItemInstance* ins = nullptr; int x; int num = 0; for(x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::GENERAL_BAGS_END; x++) @@ -2204,7 +2204,7 @@ static uint32 GetDisenchantedBagID(uint8 bag_slots) } } -static bool CopyBagContents(ItemInst* new_bag, const ItemInst* old_bag) +static bool CopyBagContents(EQEmu::ItemInstance* new_bag, const EQEmu::ItemInstance* old_bag) { if (!new_bag || !old_bag) { return false; } if (new_bag->GetItem()->BagSlots < old_bag->GetItem()->BagSlots) { return false; } @@ -2308,7 +2308,7 @@ void Client::DisenchantSummonedBags(bool client_update) if (CopyBagContents(new_inst, inst)) { Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, EQEmu::legacy::SlotCursor); - std::list local; + std::list local; local.push_front(new_inst); m_inv.PopItem(EQEmu::legacy::SlotCursor); safe_delete(inst); @@ -2405,7 +2405,7 @@ void Client::RemoveNoRent(bool client_update) } if (!m_inv.CursorEmpty()) { - std::list local; + std::list local; while (!m_inv.CursorEmpty()) { auto inst = m_inv.PopItem(EQEmu::legacy::SlotCursor); @@ -2516,8 +2516,8 @@ void Client::RemoveDuplicateLore(bool client_update) // Shared Bank and Shared Bank Containers are not checked due to their allowing duplicate lore items if (!m_inv.CursorEmpty()) { - std::list local_1; - std::list local_2; + std::list local_1; + std::list local_2; while (!m_inv.CursorEmpty()) { auto inst = m_inv.PopItem(EQEmu::legacy::SlotCursor); @@ -2591,7 +2591,7 @@ void Client::MoveSlotNotAllowed(bool client_update) uint32 Client::GetEquipment(uint8 material_slot) const { int16 invslot; - const ItemInst *item; + const EQEmu::ItemInstance *item; if(material_slot > EQEmu::textures::LastTexture) { @@ -2617,7 +2617,7 @@ uint32 Client::GetEquipment(uint8 material_slot) const #if 0 int32 Client::GetEquipmentMaterial(uint8 material_slot) { - const ItemBase *item; + const ItemData *item; item = database.GetItem(GetEquipment(material_slot)); if(item != 0) @@ -2634,7 +2634,7 @@ uint32 Client::GetEquipmentColor(uint8 material_slot) const if (material_slot > EQEmu::textures::LastTexture) return 0; - const EQEmu::ItemBase *item = database.GetItem(GetEquipment(material_slot)); + const EQEmu::ItemData *item = database.GetItem(GetEquipment(material_slot)); if(item != nullptr) return ((m_pp.item_tint.Slot[material_slot].UseTint) ? m_pp.item_tint.Slot[material_slot].Color : item->Color); @@ -2642,7 +2642,7 @@ uint32 Client::GetEquipmentColor(uint8 material_slot) const } // Send an item packet (including all subitems of the item) -void Client::SendItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType packet_type) +void Client::SendItemPacket(int16 slot_id, const EQEmu::ItemInstance* inst, ItemPacketType packet_type) { if (!inst) return; @@ -2667,7 +2667,7 @@ void Client::SendItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType FastQueuePacket(&outapp); } -EQApplicationPacket* Client::ReturnItemPacket(int16 slot_id, const ItemInst* inst, ItemPacketType packet_type) +EQApplicationPacket* Client::ReturnItemPacket(int16 slot_id, const EQEmu::ItemInstance* inst, ItemPacketType packet_type) { if (!inst) return nullptr; @@ -2717,8 +2717,8 @@ void Client::CreateBandolier(const EQApplicationPacket *app) Log.Out(Logs::Detail, Logs::Inventory, "Char: %s Creating Bandolier Set %i, Set Name: %s", GetName(), bs->Number, bs->Name); strcpy(m_pp.bandoliers[bs->Number].Name, bs->Name); - const ItemInst* InvItem = nullptr; - const EQEmu::ItemBase *BaseItem = nullptr; + const EQEmu::ItemInstance* InvItem = nullptr; + const EQEmu::ItemData *BaseItem = nullptr; int16 WeaponSlot = 0; database.DeleteCharacterBandolier(this->CharacterID(), bs->Number); @@ -2762,7 +2762,7 @@ void Client::SetBandolier(const EQApplicationPacket *app) Log.Out(Logs::Detail, Logs::Inventory, "Char: %s activating set %i", GetName(), bss->Number); int16 slot = 0; int16 WeaponSlot = 0; - ItemInst *BandolierItems[4]; // Temporary holding area for the weapons we pull out of their inventory + EQEmu::ItemInstance *BandolierItems[4]; // Temporary holding area for the weapons we pull out of their inventory // First we pull the items for this bandolier set out of their inventory, this makes space to put the // currently equipped items back. @@ -2827,7 +2827,7 @@ void Client::SetBandolier(const EQApplicationPacket *app) BandolierItems[BandolierSlot] = 0; if (slot == INVALID_INDEX) { Log.Out(Logs::Detail, Logs::Inventory, "Character does not have required bandolier item for slot %i", WeaponSlot); - ItemInst *InvItem = m_inv.PopItem(WeaponSlot); + EQEmu::ItemInstance *InvItem = m_inv.PopItem(WeaponSlot); if(InvItem) { // If there was an item in that weapon slot, put it in the inventory Log.Out(Logs::Detail, Logs::Inventory, "returning item %s in weapon slot %i to inventory", @@ -2861,7 +2861,7 @@ void Client::SetBandolier(const EQApplicationPacket *app) // if the player has this item in their inventory, and it is not already where it needs to be if(BandolierItems[BandolierSlot]) { // Pull the item that we are going to replace - ItemInst *InvItem = m_inv.PopItem(WeaponSlot); + EQEmu::ItemInstance *InvItem = m_inv.PopItem(WeaponSlot); // Put the item specified in the bandolier where it needs to be m_inv.PutItem(WeaponSlot, *BandolierItems[BandolierSlot]); @@ -2881,7 +2881,7 @@ void Client::SetBandolier(const EQApplicationPacket *app) else { // This bandolier set has no item for this slot, so take whatever is in the weapon slot and // put it in the player's inventory. - ItemInst *InvItem = m_inv.PopItem(WeaponSlot); + EQEmu::ItemInstance *InvItem = m_inv.PopItem(WeaponSlot); if(InvItem) { Log.Out(Logs::Detail, Logs::Inventory, "Bandolier has no item for slot %i, returning item %s to inventory", WeaponSlot, InvItem->GetItem()->Name); // If there was an item in that weapon slot, put it in the inventory @@ -2899,7 +2899,7 @@ void Client::SetBandolier(const EQApplicationPacket *app) CalcBonuses(); } -bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { +bool Client::MoveItemToInventory(EQEmu::ItemInstance *ItemToReturn, bool UpdateClient) { // This is a support function for Client::SetBandolier, however it can be used anywhere it's functionality is required. // @@ -2932,7 +2932,7 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::SlotCursor; i++) { // changed slot max to 30 from 29. client will stack into slot 30 (bags too) before moving. - ItemInst* InvItem = m_inv.GetItem(i); + EQEmu::ItemInstance* InvItem = m_inv.GetItem(i); if(InvItem && (InvItem->GetItem()->ID == ItemID) && (InvItem->GetCharges() < InvItem->GetItem()->StackSize)) { @@ -2991,7 +2991,7 @@ bool Client::MoveItemToInventory(ItemInst *ItemToReturn, bool UpdateClient) { for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::SlotCursor; i++) { // changed slot max to 30 from 29. client will move into slot 30 (bags too) before pushing onto cursor. - ItemInst* InvItem = m_inv.GetItem(i); + EQEmu::ItemInstance* InvItem = m_inv.GetItem(i); if (!InvItem) { // Found available slot in personal inventory @@ -3047,7 +3047,7 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool if (!requester) return false; - std::map instmap; + std::map instmap; // build reference map for (int16 index = SLOT_BEGIN; index < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; ++index) { @@ -3140,7 +3140,7 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool return true; } -void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const ItemInst* inst, const ItemInst* parent, bool log, bool silent, bool &error, int depth) +void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* parent, bool log, bool silent, bool &error, int depth) { if (depth >= 10) { Log.Out(Logs::Detail, Logs::None, "[CLIENT] Client::InterrogateInventory_() - Recursion count has exceeded the maximum allowable (You have a REALLY BIG PROBLEM!!)"); @@ -3153,7 +3153,7 @@ void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 hea } else { if (inst) { - for (int16 sub = SUB_INDEX_BEGIN; (sub < EQEmu::legacy::ITEM_CONTAINER_SIZE) && (!error); ++sub) { // treat any ItemInst as having the max internal slots available + for (int16 sub = SUB_INDEX_BEGIN; (sub < EQEmu::legacy::ITEM_CONTAINER_SIZE) && (!error); ++sub) { // treat any EQEmu::ItemInstance as having the max internal slots available if (inst->GetItem(sub)) InterrogateInventory_(true, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1); } @@ -3193,7 +3193,7 @@ void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 hea return; } -bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* inst, const ItemInst* parent, int depth) +bool Client::InterrogateInventory_error(int16 head, int16 index, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* parent, int depth) { // very basic error checking - can be elaborated upon if more in-depth testing is needed... @@ -3273,7 +3273,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const ItemInst* } void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value) { - ItemInst *inst = GetItem(slot_id); + EQEmu::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); database.SaveInventory(character_id, inst, slot_id); @@ -3281,7 +3281,7 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value) { - ItemInst *inst = GetItem(slot_id); + EQEmu::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); database.SaveInventory(character_id, inst, slot_id); @@ -3289,7 +3289,7 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value) { - ItemInst *inst = GetItem(slot_id); + EQEmu::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); database.SaveInventory(character_id, inst, slot_id); @@ -3297,7 +3297,7 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value) { - ItemInst *inst = GetItem(slot_id); + EQEmu::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); database.SaveInventory(character_id, inst, slot_id); @@ -3305,7 +3305,7 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } std::string Inventory::GetCustomItemData(int16 slot_id, std::string identifier) { - ItemInst *inst = GetItem(slot_id); + EQEmu::ItemInstance *inst = GetItem(slot_id); if(inst) { return inst->GetCustomData(identifier); } diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 910331e27..2a43eda39 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -119,7 +119,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml int charges = lds->Entries[i].multiplier; for(int j = 0; j < charges; ++j) { if(zone->random.Real(0.0, 100.0) <= lds->Entries[i].chance) { - const EQEmu::ItemBase* dbitem = GetItem(lds->Entries[i].item_id); + const EQEmu::ItemData* dbitem = GetItem(lds->Entries[i].item_id); npc->AddLootDrop(dbitem, itemlist, lds->Entries[i].item_charges, lds->Entries[i].minlevel, lds->Entries[i].maxlevel, lds->Entries[i].equip_item > 0 ? true : false, false); } @@ -140,7 +140,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml float roll_t_min = 0.0f; bool active_item_list = false; for(uint32 i = 0; i < lds->NumEntries; ++i) { - const EQEmu::ItemBase* db_item = GetItem(lds->Entries[i].item_id); + const EQEmu::ItemData* db_item = GetItem(lds->Entries[i].item_id); if(db_item) { roll_t += lds->Entries[i].chance; active_item_list = true; @@ -157,7 +157,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml for(int i = 0; i < mindrop; ++i) { float roll = (float)zone->random.Real(0.0, roll_t_min); for(uint32 j = 0; j < lds->NumEntries; ++j) { - const EQEmu::ItemBase* db_item = GetItem(lds->Entries[j].item_id); + const EQEmu::ItemData* db_item = GetItem(lds->Entries[j].item_id); if(db_item) { if(roll < lds->Entries[j].chance) { npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, @@ -187,7 +187,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml for(int i = mindrop; i < droplimit; ++i) { float roll = (float)zone->random.Real(0.0, roll_t); for(uint32 j = 0; j < lds->NumEntries; ++j) { - const EQEmu::ItemBase* db_item = GetItem(lds->Entries[j].item_id); + const EQEmu::ItemData* db_item = GetItem(lds->Entries[j].item_id); if(db_item) { if(roll < lds->Entries[j].chance) { npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, @@ -221,7 +221,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml } //if itemlist is null, just send wear changes -void NPC::AddLootDrop(const EQEmu::ItemBase *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange) { +void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange) { if(item2 == nullptr) return; @@ -258,7 +258,7 @@ void NPC::AddLootDrop(const EQEmu::ItemBase *item2, ItemList* itemlist, int16 ch if (equipit) { uint8 eslot = 0xFF; char newid[20]; - const EQEmu::ItemBase* compitem = nullptr; + const EQEmu::ItemData* compitem = nullptr; bool found = false; // track if we found an empty slot we fit into int32 foundslot = -1; // for multi-slot items @@ -415,14 +415,14 @@ void NPC::AddLootDrop(const EQEmu::ItemBase *item2, ItemList* itemlist, int16 ch SendAppearancePacket(AT_Light, GetActiveLightType()); } -void NPC::AddItem(const EQEmu::ItemBase* item, uint16 charges, bool equipitem) { +void NPC::AddItem(const EQEmu::ItemData* item, uint16 charges, bool equipitem) { //slot isnt needed, its determined from the item. AddLootDrop(item, &itemlist, charges, 1, 255, equipitem, equipitem); } void NPC::AddItem(uint32 itemid, uint16 charges, bool equipitem) { //slot isnt needed, its determined from the item. - const EQEmu::ItemBase * i = database.GetItem(itemid); + const EQEmu::ItemData * i = database.GetItem(itemid); if(i == nullptr) return; AddLootDrop(i, &itemlist, charges, 1, 255, equipitem, equipitem); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 403ca82aa..2e83c5625 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1219,13 +1219,13 @@ Lua_Raid Lua_Client::GetRaid() { bool Lua_Client::PutItemInInventory(int slot_id, Lua_ItemInst inst) { Lua_Safe_Call_Bool(); - ItemInst *rinst = inst; + EQEmu::ItemInstance *rinst = inst; return self->PutItemInInventory(slot_id, *rinst, true); } bool Lua_Client::PushItemOnCursor(Lua_ItemInst inst) { Lua_Safe_Call_Bool(); - ItemInst *rinst = inst; + EQEmu::ItemInstance *rinst = inst; return self->PushItemOnCursor(*rinst, true); } diff --git a/zone/lua_inventory.cpp b/zone/lua_inventory.cpp index 498835926..0866eebc5 100644 --- a/zone/lua_inventory.cpp +++ b/zone/lua_inventory.cpp @@ -20,7 +20,7 @@ Lua_ItemInst Lua_Inventory::GetItem(int slot_id, int bag_slot) { int Lua_Inventory::PutItem(int slot_id, Lua_ItemInst item) { Lua_Safe_Call_Int(); - ItemInst *inst = item; + EQEmu::ItemInstance *inst = item; if(!inst) { return 0; } @@ -30,7 +30,7 @@ int Lua_Inventory::PutItem(int slot_id, Lua_ItemInst item) { int Lua_Inventory::PushCursor(Lua_ItemInst item) { Lua_Safe_Call_Int(); - ItemInst *inst = item; + EQEmu::ItemInstance *inst = item; if(!inst) { return 0; } diff --git a/zone/lua_item.cpp b/zone/lua_item.cpp index d6846abc0..67e7a1bd4 100644 --- a/zone/lua_item.cpp +++ b/zone/lua_item.cpp @@ -7,7 +7,7 @@ #include "lua_item.h" Lua_Item::Lua_Item(uint32 item_id) { - const EQEmu::ItemBase *t = database.GetItem(item_id); + const EQEmu::ItemData *t = database.GetItem(item_id); SetLuaPtrData(t); } diff --git a/zone/lua_item.h b/zone/lua_item.h index 74294f2a5..d5a32c41f 100644 --- a/zone/lua_item.h +++ b/zone/lua_item.h @@ -6,7 +6,7 @@ namespace EQEmu { - struct ItemBase; + struct ItemData; } namespace luabind { @@ -15,17 +15,17 @@ namespace luabind { luabind::scope lua_register_item(); -class Lua_Item : public Lua_Ptr +class Lua_Item : public Lua_Ptr { - typedef const EQEmu::ItemBase NativeType; + typedef const EQEmu::ItemData NativeType; public: Lua_Item(uint32 item_id); Lua_Item() : Lua_Ptr(nullptr) { } - Lua_Item(const EQEmu::ItemBase *d) : Lua_Ptr(d) { } + Lua_Item(const EQEmu::ItemData *d) : Lua_Ptr(d) { } virtual ~Lua_Item() { } - operator const EQEmu::ItemBase*() { - return reinterpret_cast(GetLuaPtrData()); + operator const EQEmu::ItemData*() { + return reinterpret_cast(GetLuaPtrData()); } int GetMinStatus(); diff --git a/zone/lua_iteminst.cpp b/zone/lua_iteminst.cpp index 0b6981358..7844a64bb 100644 --- a/zone/lua_iteminst.cpp +++ b/zone/lua_iteminst.cpp @@ -21,7 +21,7 @@ Lua_ItemInst::Lua_ItemInst(int item_id, int charges) { Lua_ItemInst& Lua_ItemInst::operator=(const Lua_ItemInst& o) { if(o.cloned_) { cloned_ = true; - d_ = new ItemInst(*o.d_); + d_ = new EQEmu::ItemInstance(*o.d_); } else { cloned_ = false; d_ = o.d_; @@ -32,7 +32,7 @@ Lua_ItemInst& Lua_ItemInst::operator=(const Lua_ItemInst& o) { Lua_ItemInst::Lua_ItemInst(const Lua_ItemInst& o) { if(o.cloned_) { cloned_ = true; - d_ = new ItemInst(*o.d_); + d_ = new EQEmu::ItemInstance(*o.d_); } else { cloned_ = false; d_ = o.d_; diff --git a/zone/lua_iteminst.h b/zone/lua_iteminst.h index f12d16983..98943d6dc 100644 --- a/zone/lua_iteminst.h +++ b/zone/lua_iteminst.h @@ -4,30 +4,34 @@ #include "lua_ptr.h" -class ItemInst; class Lua_Item; +namespace EQEmu +{ + class ItemInstance; +} + namespace luabind { struct scope; } luabind::scope lua_register_iteminst(); -class Lua_ItemInst : public Lua_Ptr +class Lua_ItemInst : public Lua_Ptr { - typedef ItemInst NativeType; + typedef EQEmu::ItemInstance NativeType; public: Lua_ItemInst(int item_id); Lua_ItemInst(int item_id, int charges); Lua_ItemInst() : Lua_Ptr(nullptr), cloned_(false) { } - Lua_ItemInst(ItemInst *d) : Lua_Ptr(d), cloned_(false) { } - Lua_ItemInst(ItemInst *d, bool cloned) : Lua_Ptr(d), cloned_(cloned) { } + Lua_ItemInst(EQEmu::ItemInstance *d) : Lua_Ptr(d), cloned_(false) { } + Lua_ItemInst(EQEmu::ItemInstance *d, bool cloned) : Lua_Ptr(d), cloned_(cloned) { } Lua_ItemInst& operator=(const Lua_ItemInst& o); Lua_ItemInst(const Lua_ItemInst& o); - virtual ~Lua_ItemInst() { if(cloned_) { ItemInst *ptr = GetLuaPtrData(); if(ptr) { delete ptr; } } } + virtual ~Lua_ItemInst() { if(cloned_) { EQEmu::ItemInstance *ptr = GetLuaPtrData(); if(ptr) { delete ptr; } } } - operator ItemInst*() { - return reinterpret_cast(GetLuaPtrData()); + operator EQEmu::ItemInstance*() { + return reinterpret_cast(GetLuaPtrData()); } bool IsType(int item_class); diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index ea23df73f..d28c592a4 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -422,7 +422,7 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client * return 0; } -int LuaParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, +int LuaParser::EventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { @@ -442,7 +442,7 @@ int LuaParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob * return _EventItem(package_name, evt, client, item, mob, data, extra_data, extra_pointers); } -int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, Mob *mob, +int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func) { const char *sub_name = LuaEvents[evt]; @@ -706,7 +706,7 @@ bool LuaParser::SpellHasQuestSub(uint32 spell_id, QuestEventID evt) { return HasFunction(subname, package_name); } -bool LuaParser::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) { +bool LuaParser::ItemHasQuestSub(EQEmu::ItemInstance *itm, QuestEventID evt) { if (itm == nullptr) { return false; } @@ -752,7 +752,7 @@ void LuaParser::LoadGlobalPlayerScript(std::string filename) { LoadScript(filename, "global_player"); } -void LuaParser::LoadItemScript(std::string filename, ItemInst *item) { +void LuaParser::LoadItemScript(std::string filename, EQEmu::ItemInstance *item) { if (item == nullptr) return; std::string package_name = "item_"; @@ -1129,7 +1129,7 @@ int LuaParser::DispatchEventPlayer(QuestEventID evt, Client *client, std::string return ret; } -int LuaParser::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, +int LuaParser::DispatchEventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { evt = ConvertLuaEvent(evt); if(evt >= _LargestEventID) { diff --git a/zone/lua_parser.h b/zone/lua_parser.h index 1e4df4740..003c936ce 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -13,10 +13,14 @@ extern const ZoneConfig *Config; struct lua_State; -class ItemInst; class Client; class NPC; +namespace EQEmu +{ + class ItemInstance; +} + #include "lua_parser_events.h" struct lua_registered_event; @@ -39,7 +43,7 @@ public: std::vector *extra_pointers); virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers); - virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, + virtual int EventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers); @@ -51,14 +55,14 @@ public: virtual bool PlayerHasQuestSub(QuestEventID evt); virtual bool GlobalPlayerHasQuestSub(QuestEventID evt); virtual bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt); - virtual bool ItemHasQuestSub(ItemInst *itm, QuestEventID evt); + virtual bool ItemHasQuestSub(EQEmu::ItemInstance *itm, QuestEventID evt); virtual bool EncounterHasQuestSub(std::string encounter_name, QuestEventID evt); virtual void LoadNPCScript(std::string filename, int npc_id); virtual void LoadGlobalNPCScript(std::string filename); virtual void LoadPlayerScript(std::string filename); virtual void LoadGlobalPlayerScript(std::string filename); - virtual void LoadItemScript(std::string filename, ItemInst *item); + virtual void LoadItemScript(std::string filename, EQEmu::ItemInstance *item); virtual void LoadSpellScript(std::string filename, uint32 spell_id); virtual void LoadEncounterScript(std::string filename, std::string encounter_name); @@ -72,7 +76,7 @@ public: std::vector *extra_pointers); virtual int DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers); - virtual int DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, + virtual int DispatchEventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); virtual int DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers); @@ -82,7 +86,7 @@ private: std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); int _EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); - int _EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, + int _EventItem(std::string package_name, QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); int _EventSpell(std::string package_name, QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index 030e43689..f01af5a6d 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -58,7 +58,7 @@ void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob * size_t sz = extra_pointers->size(); for(size_t i = 0; i < sz; ++i) { std::string prefix = "item" + std::to_string(i + 1); - ItemInst *inst = EQEmu::any_cast(extra_pointers->at(i)); + EQEmu::ItemInstance *inst = EQEmu::any_cast(extra_pointers->at(i)); Lua_ItemInst l_inst = inst; luabind::adl::object l_inst_o = luabind::adl::object(L, l_inst); @@ -298,7 +298,7 @@ void handle_player_timer(QuestInterface *parse, lua_State* L, Client* client, st void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { - const EQEmu::ItemBase *item = database.GetItem(extra_data); + const EQEmu::ItemData *item = database.GetItem(extra_data); if(item) { Lua_Item l_item(item); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); @@ -314,7 +314,7 @@ void handle_player_discover_item(QuestInterface *parse, lua_State* L, Client* cl void handle_player_fish_forage_success(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { - Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); + Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); @@ -350,7 +350,7 @@ void handle_player_popup_response(QuestInterface *parse, lua_State* L, Client* c void handle_player_pick_up(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { - Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); + Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); @@ -402,7 +402,7 @@ void handle_player_duel_loss(QuestInterface *parse, lua_State* L, Client* client void handle_player_loot(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { - Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); + Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); @@ -506,19 +506,19 @@ void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std } //Item -void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { lua_pushinteger(L, extra_data); lua_setfield(L, -2, "slot_id"); } -void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { lua_pushstring(L, data.c_str()); lua_setfield(L, -2, "timer"); } -void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { Lua_Mob l_mob(mob); @@ -539,7 +539,7 @@ void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, ItemI } } -void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { if(mob && mob->IsCorpse()) { Lua_Corpse l_corpse(mob->CastToCorpse()); @@ -554,15 +554,15 @@ void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, ItemI } } -void handle_item_equip(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_equip(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { lua_pushinteger(L, extra_data); lua_setfield(L, -2, "slot_id"); } -void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { - Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); + Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "aug"); @@ -571,9 +571,9 @@ void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, It lua_setfield(L, -2, "slot_id"); } -void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { - Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); + Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); @@ -582,9 +582,9 @@ void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* cli lua_setfield(L, -2, "slot_id"); } -void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { - Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); + Lua_ItemInst l_item(EQEmu::any_cast(extra_pointers->at(0))); luabind::adl::object l_item_o = luabind::adl::object(L, l_item); l_item_o.push(L); lua_setfield(L, -2, "item"); @@ -596,7 +596,7 @@ void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* cli lua_setfield(L, -2, "destroyed"); } -void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { } diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index 0a2ab5ad9..42315ed0b 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -4,7 +4,7 @@ typedef void(*NPCArgumentHandler)(QuestInterface*, lua_State*, NPC*, Mob*, std::string, uint32, std::vector*); typedef void(*PlayerArgumentHandler)(QuestInterface*, lua_State*, Client*, std::string, uint32, std::vector*); -typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, ItemInst*, Mob*, std::string, uint32, std::vector*); +typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, EQEmu::ItemInstance*, Mob*, std::string, uint32, std::vector*); typedef void(*SpellArgumentHandler)(QuestInterface*, lua_State*, NPC*, Client*, uint32, uint32, std::vector*); typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, Encounter* encounter, std::string, uint32, std::vector*); @@ -97,23 +97,23 @@ void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std std::vector *extra_pointers); //Item -void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); -void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); -void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); -void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); -void handle_item_equip(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_equip(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); -void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_augment(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); -void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_augment_insert(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); -void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_augment_remove(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); -void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data, +void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); //Spell diff --git a/zone/merc.cpp b/zone/merc.cpp index c787d00c8..c9d177324 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -217,7 +217,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { for (i = 0; i < EQEmu::legacy::SlotAmmo; i++) { if(equipment[i] == 0) continue; - const EQEmu::ItemBase * itm = database.GetItem(equipment[i]); + const EQEmu::ItemData * itm = database.GetItem(equipment[i]); if(itm) AddItemBonuses(itm, newbon); } @@ -225,7 +225,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { //Power Source Slot /*if (GetClientVersion() >= EQClientSoF) { - const ItemInst* inst = m_inv[MainPowerSource]; + const EQEmu::ItemInstance* inst = m_inv[MainPowerSource]; if(inst) AddItemBonuses(inst, newbon); }*/ @@ -243,7 +243,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { SetAttackTimer(); } -void Merc::AddItemBonuses(const EQEmu::ItemBase *item, StatBonuses* newbon) { +void Merc::AddItemBonuses(const EQEmu::ItemData *item, StatBonuses* newbon) { if(GetLevel() < item->ReqLevel) { @@ -1221,7 +1221,7 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { { continue; } - const ItemBase* item = database.GetItem(equipment[i]); + const ItemData* item = database.GetItem(equipment[i]); if(item) { ns->spawn.equipment[i].material = item->Material; @@ -2547,8 +2547,8 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) { //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[type]){ - const EQEmu::ItemBase* TempItem = 0; - const EQEmu::ItemBase* UsedItem = 0; + const EQEmu::ItemData* TempItem = 0; + const EQEmu::ItemData* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -4428,7 +4428,7 @@ void Merc::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ dmg = -5; } else{ @@ -4450,7 +4450,7 @@ void Merc::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ dmg = -5; } else{ diff --git a/zone/merc.h b/zone/merc.h index 00c953288..c78ec22b7 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -14,7 +14,7 @@ struct NewSpawn_Struct; namespace EQEmu { - struct ItemBase; + struct ItemData; } #define MAXMERCS 1 @@ -283,7 +283,7 @@ public: protected: void CalcItemBonuses(StatBonuses* newbon); - void AddItemBonuses(const EQEmu::ItemBase *item, StatBonuses* newbon); + void AddItemBonuses(const EQEmu::ItemData *item, StatBonuses* newbon); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); int16 GetFocusEffect(focusType type, uint16 spell_id); diff --git a/zone/mob.cpp b/zone/mob.cpp index 1caf69918..21409c695 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2374,12 +2374,12 @@ bool Mob::CanThisClassDualWield(void) const { return(GetSkill(EQEmu::skills::SkillDualWield) > 0); } else if (CastToClient()->HasSkill(EQEmu::skills::SkillDualWield)) { - const ItemInst* pinst = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); - const ItemInst* sinst = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemInstance* pinst = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); + const EQEmu::ItemInstance* sinst = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); // 2HS, 2HB, or 2HP if(pinst && pinst->IsWeapon()) { - const EQEmu::ItemBase* item = pinst->GetItem(); + const EQEmu::ItemData* item = pinst->GetItem(); if (item->IsType2HWeapon()) return false; @@ -2749,7 +2749,7 @@ void Mob::SendArmorAppearance(Client *one_client) { if (!IsClient()) { - const EQEmu::ItemBase *item; + const EQEmu::ItemData *item; for (int i = 0; i < 7; ++i) { item = database.GetItem(GetEquipment(i)); @@ -2852,7 +2852,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const { uint32 equipmaterial = 0; int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - const EQEmu::ItemBase *item; + const EQEmu::ItemData *item; item = database.GetItem(GetEquipment(material_slot)); if (item != 0) @@ -2867,7 +2867,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const { return 0; } - const ItemInst* inst = CastToClient()->m_inv[invslot]; + const EQEmu::ItemInstance* inst = CastToClient()->m_inv[invslot]; if (inst) { if (inst->GetOrnamentationAug(ornamentationAugtype)) @@ -2905,7 +2905,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const if (material_slot >= 0 && material_slot < EQEmu::textures::TexturePrimary) { uint32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - const EQEmu::ItemBase *item; + const EQEmu::ItemData *item; item = database.GetItem(GetEquipment(material_slot)); int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); @@ -2913,7 +2913,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const { if (IsClient()) { - const ItemInst* inst = CastToClient()->m_inv[invslot]; + const EQEmu::ItemInstance* inst = CastToClient()->m_inv[invslot]; if (inst) { if (inst->GetOrnamentationAug(ornamentationAugtype)) @@ -2959,7 +2959,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const uint32 Mob::GetEquipmentColor(uint8 material_slot) const { - const EQEmu::ItemBase *item; + const EQEmu::ItemData *item; if (armor_tint.Slot[material_slot].Color) { @@ -2975,7 +2975,7 @@ uint32 Mob::GetEquipmentColor(uint8 material_slot) const uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const { - const EQEmu::ItemBase *item; + const EQEmu::ItemData *item; item = database.GetItem(GetEquipment(material_slot)); if(item != 0) @@ -3187,7 +3187,7 @@ int32 Mob::GetActSpellCasttime(uint16 spell_id, int32 casttime) { return casttime; } -void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on, int level_override) { +void Mob::ExecWeaponProc(const EQEmu::ItemInstance *inst, uint16 spell_id, Mob *on, int level_override) { // Changed proc targets to look up based on the spells goodEffect flag. // This should work for the majority of weapons. if(spell_id == SPELL_UNKNOWN || on->GetSpecialAbility(NO_HARM_FROM_CLIENT)) { @@ -3208,9 +3208,9 @@ void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on, int lev if(inst && IsClient()) { //const cast is dirty but it would require redoing a ton of interfaces at this point - //It should be safe as we don't have any truly const ItemInst floating around anywhere. + //It should be safe as we don't have any truly const EQEmu::ItemInstance floating around anywhere. //So we'll live with it for now - int i = parse->EventItem(EVENT_WEAPON_PROC, CastToClient(), const_cast(inst), on, "", spell_id); + int i = parse->EventItem(EVENT_WEAPON_PROC, CastToClient(), const_cast(inst), on, "", spell_id); if(i != 0) { return; } @@ -3888,11 +3888,11 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) int32 Mob::GetItemStat(uint32 itemid, const char *identifier) { - const ItemInst* inst = database.CreateItem(itemid); + const EQEmu::ItemInstance* inst = database.CreateItem(itemid); if (!inst) return 0; - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); if (!item) return 0; @@ -5623,7 +5623,7 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot) bool Mob::CanClassEquipItem(uint32 item_id) { - const EQEmu::ItemBase* itm = nullptr; + const EQEmu::ItemData* itm = nullptr; itm = database.GetItem(item_id); if (!itm) @@ -5692,9 +5692,9 @@ int32 Mob::GetMeleeMitigation() { } /* this is the mob being attacked. - * Pass in the weapon's ItemInst + * Pass in the weapon's EQEmu::ItemInstance */ -int Mob::ResistElementalWeaponDmg(const ItemInst *item) +int Mob::ResistElementalWeaponDmg(const EQEmu::ItemInstance *item) { if (!item) return 0; @@ -5844,9 +5844,9 @@ int Mob::ResistElementalWeaponDmg(const ItemInst *item) } /* this is the mob being attacked. - * Pass in the weapon's ItemInst + * Pass in the weapon's EQEmu::ItemInstance */ -int Mob::CheckBaneDamage(const ItemInst *item) +int Mob::CheckBaneDamage(const EQEmu::ItemInstance *item) { if (!item) return 0; diff --git a/zone/mob.h b/zone/mob.h index c09da4e0b..120e1f116 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -43,7 +43,6 @@ class EGNode; class Client; class EQApplicationPacket; class Group; -class ItemInst; class NPC; class Raid; struct NewSpawn_Struct; @@ -51,7 +50,8 @@ struct PlayerPositionUpdateServer_Struct; namespace EQEmu { - struct ItemBase; + struct ItemData; + class ItemInstance; } class Mob : public Entity { @@ -215,7 +215,7 @@ public: inline bool SeeImprovedHide() const { return see_improved_hide; } bool IsInvisible(Mob* other = 0) const; void SetInvisible(uint8 state); - bool AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const ItemInst* weapon); + bool AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const EQEmu::ItemInstance* weapon); //Song bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1); @@ -242,8 +242,8 @@ public: int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false, int level_override = -1); int ResistPhysical(int level_diff, uint8 caster_level); - int ResistElementalWeaponDmg(const ItemInst *item); - int CheckBaneDamage(const ItemInst *item); + int ResistElementalWeaponDmg(const EQEmu::ItemInstance *item); + int CheckBaneDamage(const EQEmu::ItemInstance *item); uint16 GetSpecializeSkillValue(uint16 spell_id) const; void SendSpellBarDisable(); void SendSpellBarEnable(uint16 spellid); @@ -774,7 +774,7 @@ public: virtual int GetHaste(); int32 GetMeleeMitigation(); - uint8 GetWeaponDamageBonus(const EQEmu::ItemBase* weapon, bool offhand = false); + uint8 GetWeaponDamageBonus(const EQEmu::ItemData* weapon, bool offhand = false); uint16 GetDamageTable(EQEmu::skills::SkillType skillinuse); virtual int GetHandToHandDamage(void); @@ -799,10 +799,10 @@ public: int32 ReduceAllDamage(int32 damage); virtual void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool CheckHitChance = false, bool CanAvoid = true); - virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon = nullptr, const EQEmu::ItemBase* AmmoItem = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, int AmmoSlot = 0, float speed = 4.0f); + virtual void DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon = nullptr, const EQEmu::ItemData* AmmoItem = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, int AmmoSlot = 0, float speed = 4.0f); virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0); - virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon = nullptr, const ItemInst* Ammo = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, uint32 ammo_id = 0, const EQEmu::ItemBase *AmmoItem = nullptr, int AmmoSlot = 0, float speed = 4.0f); - bool TryProjectileAttack(Mob* other, const EQEmu::ItemBase *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed); + virtual void DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon = nullptr, const EQEmu::ItemInstance* Ammo = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, uint32 ammo_id = 0, const EQEmu::ItemData *AmmoItem = nullptr, int AmmoSlot = 0, float speed = 4.0f); + bool TryProjectileAttack(Mob* other, const EQEmu::ItemData *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const EQEmu::ItemInstance* RangeWeapon, const EQEmu::ItemInstance* Ammo, int AmmoSlot, float speed); void ProjectileAttack(); inline bool HasProjectileAttack() const { return ActiveProjectileATK; } inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; } @@ -921,7 +921,7 @@ public: // HP Event inline int GetNextHPEvent() const { return nexthpevent; } void SetNextHPEvent( int hpevent ); - void SendItemAnimation(Mob *to, const EQEmu::ItemBase *item, EQEmu::skills::SkillType skillInUse, float velocity = 4.0); + void SendItemAnimation(Mob *to, const EQEmu::ItemData *item, EQEmu::skills::SkillType skillInUse, float velocity = 4.0); inline int& GetNextIncHPEvent() { return nextinchpevent; } void SetNextIncHPEvent( int inchpevent ); @@ -985,9 +985,9 @@ public: int32 mod_frenzy_damage(int32 dmg); int32 mod_monk_special_damage(int32 ndamage, EQEmu::skills::SkillType skill_type); int32 mod_backstab_damage(int32 ndamage); - int mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon); - uint32 mod_archery_bonus_damage(uint32 MaxDmg, const ItemInst* RangeWeapon); - int32 mod_archery_damage(int32 TotalDmg, bool hasbonus, const ItemInst* RangeWeapon); + int mod_archery_bonus_chance(int bonuschance, const EQEmu::ItemInstance* RangeWeapon); + uint32 mod_archery_bonus_damage(uint32 MaxDmg, const EQEmu::ItemInstance* RangeWeapon); + int32 mod_archery_damage(int32 TotalDmg, bool hasbonus, const EQEmu::ItemInstance* RangeWeapon); uint16 mod_throwing_damage(uint16 MaxDmg); int32 mod_cast_time(int32 cast_time); int mod_buff_duration(int res, Mob* caster, Mob* target, uint16 spell_id); @@ -1159,18 +1159,18 @@ protected: bool PassLimitToSkill(uint16 spell_id, uint16 skill); bool PassLimitClass(uint32 Classes_, uint16 Class_); void TryDefensiveProc(Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); - void TryWeaponProc(const ItemInst* inst, const EQEmu::ItemBase* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); - void TrySpellProc(const ItemInst* inst, const EQEmu::ItemBase* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); - void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); - void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on, int level_override = -1); + void TryWeaponProc(const EQEmu::ItemInstance* inst, const EQEmu::ItemData* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); + void TrySpellProc(const EQEmu::ItemInstance* inst, const EQEmu::ItemData* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); + void TryWeaponProc(const EQEmu::ItemInstance* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); + void ExecWeaponProc(const EQEmu::ItemInstance* weapon, uint16 spell_id, Mob *on, int level_override = -1); virtual float GetProcChances(float ProcBonus, uint16 hand = EQEmu::legacy::SlotPrimary); virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = EQEmu::legacy::SlotPrimary, Mob *on = nullptr); virtual float GetSpecialProcChances(uint16 hand); virtual float GetAssassinateProcChances(uint16 ReuseTime); virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm? uint16 GetWeaponSpeedbyHand(uint16 hand); - int GetWeaponDamage(Mob *against, const EQEmu::ItemBase *weapon_item); - int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr); + int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item); + int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr); int GetKickDamage(); int GetBashDamage(); virtual void ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int32 &mindmg); diff --git a/zone/mod_functions.cpp b/zone/mod_functions.cpp index 601041361..ca9a5e107 100644 --- a/zone/mod_functions.cpp +++ b/zone/mod_functions.cpp @@ -5,11 +5,15 @@ #include "worldserver.h" #include "zone.h" -class ItemInst; class Spawn2; struct Consider_Struct; struct DBTradeskillRecipe_Struct; +namespace EQEmu +{ + class ItemInstance; +} + extern EntityList entity_list; extern Zone* zone; @@ -25,7 +29,7 @@ void Zone::mod_repop() { return; } void NPC::mod_prespawn(Spawn2 *sp) { return; } //Base damage from NPC::Attack -int NPC::mod_npc_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::ItemBase* weapon, Mob* other) { return(damage); } +int NPC::mod_npc_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::ItemData* weapon, Mob* other) { return(damage); } //Mob c has been given credit for a kill. This is called after the regular EVENT_KILLED_MERIT event. void NPC::mod_npc_killed_merit(Mob* c) { return; } @@ -34,7 +38,7 @@ void NPC::mod_npc_killed_merit(Mob* c) { return; } void NPC::mod_npc_killed(Mob* oos) { return; } //Base damage from Client::Attack - can cover myriad skill types -int Client::mod_client_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const ItemInst* weapon, Mob* other) { return(damage); } +int Client::mod_client_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::ItemInstance* weapon, Mob* other) { return(damage); } //message is char[4096], don't screw it up. Return true for normal behavior, false to return immediately. // Channels: @@ -87,7 +91,7 @@ float Client::mod_tradeskill_chance(float chance, DBTradeskillRecipe_Struct *spe float Client::mod_tradeskill_skillup(float chance_stage2) { return(chance_stage2); } //Tribute value override -int32 Client::mod_tribute_item_value(int32 pts, const ItemInst* item) { return(pts); } +int32 Client::mod_tribute_item_value(int32 pts, const EQEmu::ItemInstance* item) { return(pts); } //Death reporting void Client::mod_client_death_npc(Mob* killerMob) { return; } @@ -103,8 +107,8 @@ int32 Client::mod_client_xp(int32 in_xp, NPC *npc) { return(in_xp); } uint32 Client::mod_client_xp_for_level(uint32 xp, uint16 check_level) { return(xp); } //Food and drink values as computed by consume requests. Return < 0 to abort the request. -int Client::mod_food_value(const EQEmu::ItemBase *item, int change) { return(change); } -int Client::mod_drink_value(const EQEmu::ItemBase *item, int change) { return(change); } +int Client::mod_food_value(const EQEmu::ItemData *item, int change) { return(change); } +int Client::mod_drink_value(const EQEmu::ItemData *item, int change) { return(change); } //effect_vallue - Spell effect value as calculated by default formulas. You will want to ignore effects that don't lend themselves to scaling - pet ID's, gate coords, etc. int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster, uint16 caster_id) { return(effect_value); } @@ -148,13 +152,13 @@ int32 Mob::mod_monk_special_damage(int32 ndamage, EQEmu::skills::SkillType skill int32 Mob::mod_backstab_damage(int32 ndamage) { return(ndamage); } //Chance for 50+ archery bonus damage if Combat:UseArcheryBonusRoll is true. Base is Combat:ArcheryBonusChance -int Mob::mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon) { return(bonuschance); } +int Mob::mod_archery_bonus_chance(int bonuschance, const EQEmu::ItemInstance* RangeWeapon) { return(bonuschance); } //Archery bonus damage -uint32 Mob::mod_archery_bonus_damage(uint32 MaxDmg, const ItemInst* RangeWeapon) { return(MaxDmg); } +uint32 Mob::mod_archery_bonus_damage(uint32 MaxDmg, const EQEmu::ItemInstance* RangeWeapon) { return(MaxDmg); } //Final archery damage including bonus if it was applied. -int32 Mob::mod_archery_damage(int32 TotalDmg, bool hasbonus, const ItemInst* RangeWeapon) { return(TotalDmg); } +int32 Mob::mod_archery_damage(int32 TotalDmg, bool hasbonus, const EQEmu::ItemInstance* RangeWeapon) { return(TotalDmg); } //Thrown weapon damage after all other calcs uint16 Mob::mod_throwing_damage(uint16 MaxDmg) { return(MaxDmg); } diff --git a/zone/npc.cpp b/zone/npc.cpp index d958ff598..78c4604ea 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -525,7 +525,7 @@ void NPC::QueryLoot(Client* to) int x = 0; for (auto cur = itemlist.begin(); cur != itemlist.end(); ++cur, ++x) { - const EQEmu::ItemBase* item = database.GetItem((*cur)->item_id); + const EQEmu::ItemData* item = database.GetItem((*cur)->item_id); if (item == nullptr) { Log.Out(Logs::General, Logs::Error, "Database error, invalid item"); continue; @@ -1462,7 +1462,7 @@ void NPC::PickPocket(Client* thief) // still needs to have FindFreeSlot vs PutItemInInventory issue worked out while (steal_item) { - std::vector> loot_selection; // + std::vector> loot_selection; // for (auto item_iter : itemlist) { if (!item_iter || !item_iter->item_id) continue; diff --git a/zone/npc.h b/zone/npc.h index d3e7928a2..0230b550f 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -93,7 +93,7 @@ class Spawn2; namespace EQEmu { - struct ItemBase; + struct ItemData; } class NPC : public Mob @@ -178,7 +178,7 @@ public: virtual void SpellProcess(); virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); - void AddItem(const EQEmu::ItemBase* item, uint16 charges, bool equipitem = true); + void AddItem(const EQEmu::ItemData* item, uint16 charges, bool equipitem = true); void AddItem(uint32 itemid, uint16 charges, bool equipitem = true); void AddLootTable(); void AddLootTable(uint32 ldid); @@ -270,7 +270,7 @@ public: bool IsTaunting() const { return taunting; } void PickPocket(Client* thief); void StartSwarmTimer(uint32 duration) { swarm_timer.Start(duration); } - void AddLootDrop(const EQEmu::ItemBase*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); + void AddLootDrop(const EQEmu::ItemData*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); virtual void DoClassAttacks(Mob *target); void CheckSignal(); inline bool IsNotTargetableWithHotkey() const { return no_target_hotkey; } @@ -403,7 +403,7 @@ public: void SetMerchantProbability(uint8 amt) { probability = amt; } uint8 GetMerchantProbability() { return probability; } void mod_prespawn(Spawn2 *sp); - int mod_npc_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::ItemBase* weapon, Mob* other); + int mod_npc_damage(int damage, EQEmu::skills::SkillType skillinuse, int hand, const EQEmu::ItemData* weapon, Mob* other); void mod_npc_killed_merit(Mob* c); void mod_npc_killed(Mob* oos); void AISpellsList(Client *c); diff --git a/zone/object.cpp b/zone/object.cpp index ab9637e96..a2bb912bc 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -37,7 +37,7 @@ extern Zone* zone; extern EntityList entity_list; // Loading object from database -Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst) +Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const EQEmu::ItemInstance* inst) : respawn_timer(0), decay_timer(300000) { @@ -69,7 +69,7 @@ Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, } //creating a re-ocurring ground spawn. -Object::Object(const ItemInst* inst, char* name,float max_x,float min_x,float max_y,float min_y,float z,float heading,uint32 respawntimer) +Object::Object(const EQEmu::ItemInstance* inst, char* name,float max_x,float min_x,float max_y,float min_y,float z,float heading,uint32 respawntimer) : respawn_timer(respawntimer), decay_timer(300000) { @@ -102,7 +102,7 @@ Object::Object(const ItemInst* inst, char* name,float max_x,float min_x,float ma } // Loading object from client dropping item on ground -Object::Object(Client* client, const ItemInst* inst) +Object::Object(Client* client, const EQEmu::ItemInstance* inst) : respawn_timer(0), decay_timer(300000) { user = nullptr; @@ -141,7 +141,7 @@ Object::Object(Client* client, const ItemInst* inst) // Set object name if (inst) { - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); if (item && item->IDFile) { if (strlen(item->IDFile) == 0) { strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); @@ -164,7 +164,7 @@ Object::Object(Client* client, const ItemInst* inst) } } -Object::Object(const ItemInst *inst, float x, float y, float z, float heading, uint32 decay_time) +Object::Object(const EQEmu::ItemInstance *inst, float x, float y, float z, float heading, uint32 decay_time) : respawn_timer(0), decay_timer(decay_time) { user = nullptr; @@ -197,7 +197,7 @@ Object::Object(const ItemInst *inst, float x, float y, float z, float heading, u // Set object name if (inst) { - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); if (item && item->IDFile) { if (strlen(item->IDFile) == 0) { strcpy(m_data.object_name, DEFAULT_OBJECT_NAME); @@ -225,8 +225,8 @@ Object::Object(const char *model, float x, float y, float z, float heading, uint { user = nullptr; last_user = nullptr; - ItemInst* inst = nullptr; - inst = new ItemInst(ItemInstWorldContainer); + EQEmu::ItemInstance* inst = nullptr; + inst = new EQEmu::ItemInstance(ItemInstWorldContainer); // Initialize members m_id = 0; @@ -326,7 +326,7 @@ void Object::Delete(bool reset_state) } } -const ItemInst* Object::GetItem(uint8 index) { +const EQEmu::ItemInstance* Object::GetItem(uint8 index) { if (index < EQEmu::legacy::TYPE_WORLD_SIZE) { return m_inst->GetItem(index); } @@ -335,7 +335,7 @@ const ItemInst* Object::GetItem(uint8 index) { } // Add item to object (only logical for world tradeskill containers -void Object::PutItem(uint8 index, const ItemInst* inst) +void Object::PutItem(uint8 index, const EQEmu::ItemInstance* inst) { if (index > 9) { Log.Out(Logs::General, Logs::Error, "Object::PutItem: Invalid index specified (%i)", index); @@ -362,12 +362,12 @@ void Object::Close() { last_user = user; // put any remaining items from the world container back into the player's inventory to avoid item loss // if they close the container without removing all items - ItemInst* container = this->m_inst; + EQEmu::ItemInstance* container = this->m_inst; if(container != nullptr) { for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { - ItemInst* inst = container->PopItem(i); + EQEmu::ItemInstance* inst = container->PopItem(i); if(inst != nullptr) { user->MoveItemToInventory(inst, true); @@ -392,9 +392,9 @@ void Object::DeleteItem(uint8 index) } // Pop item out of container -ItemInst* Object::PopItem(uint8 index) +EQEmu::ItemInstance* Object::PopItem(uint8 index) { - ItemInst* inst = nullptr; + EQEmu::ItemInstance* inst = nullptr; if (m_inst && m_inst->IsType(EQEmu::item::ItemClassBag)) { inst = m_inst->PopItem(index); @@ -603,7 +603,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) sender->QueuePacket(outapp); safe_delete(outapp); for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { - const ItemInst* inst = m_inst->GetItem(i); + const EQEmu::ItemInstance* inst = m_inst->GetItem(i); if (inst) { //sender->GetInv().PutItem(i+4000,inst); sender->SendItemPacket(i, inst, ItemPacketWorldContainer); @@ -616,7 +616,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) } // Add new Zone Object (theoretically only called for items dropped to ground) -uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst) +uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& object, const EQEmu::ItemInstance* inst) { uint32 database_id = 0; uint32 item_id = 0; @@ -654,7 +654,7 @@ uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& ob } // Update information about existing object in database -void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst) +void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const EQEmu::ItemInstance* inst) { uint32 item_id = 0; int16 charges = 0; @@ -945,7 +945,7 @@ uint32 Object::GetItemID() return 0; } - const EQEmu::ItemBase* item = this->m_inst->GetItem(); + const EQEmu::ItemData* item = this->m_inst->GetItem(); if (item == 0) { diff --git a/zone/object.h b/zone/object.h index 23c152cea..1afe574ea 100644 --- a/zone/object.h +++ b/zone/object.h @@ -29,7 +29,11 @@ class Client; class EQApplicationPacket; -class ItemInst; + +namespace EQEmu +{ + class ItemInstance; +} /* item icon numbers (showeq) @@ -89,11 +93,11 @@ class Object: public Entity { public: // Loading object from database - Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& data, const ItemInst* inst); - Object(const ItemInst* inst, char* name,float max_x,float min_x,float max_y,float min_y,float z,float heading,uint32 respawntimer); + Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& data, const EQEmu::ItemInstance* inst); + Object(const EQEmu::ItemInstance* inst, char* name,float max_x,float min_x,float max_y,float min_y,float z,float heading,uint32 respawntimer); // Loading object from client dropping item on ground - Object(Client* client, const ItemInst* inst); - Object(const ItemInst *inst, float x, float y, float z, float heading, uint32 decay_time = 300000); + Object(Client* client, const EQEmu::ItemInstance* inst); + Object(const EQEmu::ItemInstance *inst, float x, float y, float z, float heading, uint32 decay_time = 300000); Object(const char *model, float x, float y, float z, float heading, uint8 type, uint32 decay_time = 0); // Destructor @@ -120,10 +124,10 @@ public: void StartDecay() {decay_timer.Start();} // Container functions - const ItemInst* GetItem(uint8 index); - void PutItem(uint8 index, const ItemInst* inst); + const EQEmu::ItemInstance* GetItem(uint8 index); + void PutItem(uint8 index, const EQEmu::ItemInstance* inst); void DeleteItem(uint8 index); // Item inside container - ItemInst* PopItem(uint8 index); // Pop item out of container + EQEmu::ItemInstance* PopItem(uint8 index); // Pop item out of container // Override base class implementations virtual bool IsObject() const { return true; } @@ -176,7 +180,7 @@ protected: void RandomSpawn(bool send_packet = false); //spawn this ground spawn at a random place Object_Struct m_data; // Packet data - ItemInst* m_inst; // Item representing object + EQEmu::ItemInstance* m_inst; // Item representing object bool m_inuse; // Currently in use by a client? uint32 m_id; // Database key, different than drop_id uint32 m_type; // Object Type, ie, forge, oven, dropped item, etc (ref: ContainerUseTypes) diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index de334d5d0..65ff5a4e0 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -4324,7 +4324,7 @@ XS(XS_Client_GetItemAt) Perl_croak(aTHX_ "Usage: Client::GetItemAt(THIS, slot)"); { Client * THIS; - ItemInst * RETVAL; + EQEmu::ItemInstance * RETVAL; uint32 slot = (int32)SvIV(ST(1)); if (sv_derived_from(ST(0), "Client")) { @@ -4351,7 +4351,7 @@ XS(XS_Client_GetAugmentAt) Perl_croak(aTHX_ "Usage: Client::GetAugmentAt(THIS, slot, aug_slot)"); { Client * THIS; - ItemInst * RETVAL; + EQEmu::ItemInstance * RETVAL; uint32 slot = (int32)SvIV(ST(1)); uint32 aug_slot = (int32)SvIV(ST(1)); @@ -4364,7 +4364,7 @@ XS(XS_Client_GetAugmentAt) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - ItemInst * inst = THIS->GetInv().GetItem(slot); + EQEmu::ItemInstance * inst = THIS->GetInv().GetItem(slot); if(inst) { RETVAL = inst->GetAugment(aug_slot); @@ -5627,7 +5627,7 @@ XS(XS_Client_GetItemInInventory) { Client * THIS; int16 slot_id = (int16)SvIV(ST(1)); - ItemInst *RETVAL = nullptr; + EQEmu::ItemInstance *RETVAL = nullptr; if (sv_derived_from(ST(0), "Client")) { IV tmp = SvIV((SV*)SvRV(ST(0))); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index f171d8d79..9af0fa43f 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -8092,8 +8092,8 @@ XS(XS_Mob_DoArcheryAttackDmg) { Mob * THIS; Mob* target; - ItemInst* RangeWeapon = nullptr; - ItemInst* Ammo = nullptr; + EQEmu::ItemInstance* RangeWeapon = nullptr; + EQEmu::ItemInstance* Ammo = nullptr; uint16 weapon_damage = (uint16)SvIV(ST(4)); int16 chance_mod = (int16)SvIV(ST(5)); int16 focus = (int16)SvIV(ST(6)); @@ -8130,8 +8130,8 @@ XS(XS_Mob_DoThrowingAttackDmg) { Mob * THIS; Mob* target; - ItemInst* RangeWeapon = nullptr; - EQEmu::ItemBase* item = nullptr; + EQEmu::ItemInstance* RangeWeapon = nullptr; + EQEmu::ItemData* item = nullptr; uint16 weapon_damage = (uint16)SvIV(ST(4)); int16 chance_mod = (int16)SvIV(ST(5)); int16 focus = (int16)SvIV(ST(6)); diff --git a/zone/perl_questitem.cpp b/zone/perl_questitem.cpp index 053748e97..742a00814 100644 --- a/zone/perl_questitem.cpp +++ b/zone/perl_questitem.cpp @@ -38,16 +38,16 @@ XS(XS_QuestItem_GetName) { if (items != 1) Perl_croak(aTHX_ "Usage: QuestItem::GetName(THIS)"); { - ItemInst * THIS; + EQEmu::ItemInstance * THIS; Const_char * RETVAL; dXSTARG; if (sv_derived_from(ST(0), "QuestItem")) { IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(ItemInst *,tmp); + THIS = INT2PTR(EQEmu::ItemInstance *,tmp); } else - Perl_croak(aTHX_ "THIS is not of type ItemInst"); + Perl_croak(aTHX_ "THIS is not of type EQEmu::ItemInstance"); if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); @@ -64,15 +64,15 @@ XS(XS_QuestItem_SetScale) if (items != 2) Perl_croak(aTHX_ "Usage: QuestItem::SetScale(THIS, scale factor)"); { - ItemInst * THIS; + EQEmu::ItemInstance * THIS; float Mult; if (sv_derived_from(ST(0), "QuestItem")) { IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(ItemInst *,tmp); + THIS = INT2PTR(EQEmu::ItemInstance *,tmp); } else - Perl_croak(aTHX_ "THIS is not of type ItemInst"); + Perl_croak(aTHX_ "THIS is not of type EQEmu::ItemInstance"); if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); @@ -92,16 +92,16 @@ XS(XS_QuestItem_ItemSay) if (items != 2 && items != 3) Perl_croak(aTHX_ "Usage: QuestItem::ItemSay(THIS, text [, language])"); { - ItemInst* THIS; + EQEmu::ItemInstance* THIS; Const_char* text; int lang = 0; if (sv_derived_from(ST(0), "QuestItem")) { IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(ItemInst *,tmp); + THIS = INT2PTR(EQEmu::ItemInstance *,tmp); } else - Perl_croak(aTHX_ "THIS is not of type ItemInst"); + Perl_croak(aTHX_ "THIS is not of type EQEmu::ItemInstance"); if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); @@ -121,16 +121,16 @@ XS(XS_QuestItem_IsType) if (items != 2) Perl_croak(aTHX_ "Usage: QuestItem::IsType(THIS, type)"); { - ItemInst* THIS; + EQEmu::ItemInstance* THIS; bool RETVAL; uint32 type = (int32)SvIV(ST(1)); if (sv_derived_from(ST(0), "QuestItem")) { IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(ItemInst *,tmp); + THIS = INT2PTR(EQEmu::ItemInstance *,tmp); } else - Perl_croak(aTHX_ "THIS is not of type ItemInst"); + Perl_croak(aTHX_ "THIS is not of type EQEmu::ItemInstance"); if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); @@ -148,15 +148,15 @@ XS(XS_QuestItem_IsAttuned) if (items != 1) Perl_croak(aTHX_ "Usage: QuestItem::IsAttuned(THIS)"); { - ItemInst* THIS; + EQEmu::ItemInstance* THIS; bool RETVAL; if (sv_derived_from(ST(0), "QuestItem")) { IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(ItemInst *,tmp); + THIS = INT2PTR(EQEmu::ItemInstance *,tmp); } else - Perl_croak(aTHX_ "THIS is not of type ItemInst"); + Perl_croak(aTHX_ "THIS is not of type EQEmu::ItemInstance"); if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); @@ -174,16 +174,16 @@ XS(XS_QuestItem_GetCharges) if (items != 1) Perl_croak(aTHX_ "Usage: QuestItem::GetCharges(THIS)"); { - ItemInst* THIS; + EQEmu::ItemInstance* THIS; int16 RETVAL; dXSTARG; if (sv_derived_from(ST(0), "QuestItem")) { IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(ItemInst *,tmp); + THIS = INT2PTR(EQEmu::ItemInstance *,tmp); } else - Perl_croak(aTHX_ "THIS is not of type ItemInst"); + Perl_croak(aTHX_ "THIS is not of type EQEmu::ItemInstance"); if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); @@ -200,16 +200,16 @@ XS(XS_QuestItem_GetAugment) if (items != 2) Perl_croak(aTHX_ "Usage: QuestItem::GetAugment(THIS, augment_id)"); { - ItemInst* THIS; + EQEmu::ItemInstance* THIS; int16 slot_id = (int16)SvIV(ST(1)); - ItemInst* RETVAL; + EQEmu::ItemInstance* RETVAL; if (sv_derived_from(ST(0), "QuestItem")) { IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(ItemInst *,tmp); + THIS = INT2PTR(EQEmu::ItemInstance *,tmp); } else - Perl_croak(aTHX_ "THIS is not of type ItemInst"); + Perl_croak(aTHX_ "THIS is not of type EQEmu::ItemInstance"); if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); @@ -227,16 +227,16 @@ XS(XS_QuestItem_GetID) if (items != 1) Perl_croak(aTHX_ "Usage: QuestItem::GetID(THIS)"); { - ItemInst* THIS; + EQEmu::ItemInstance* THIS; uint32 RETVAL; dXSTARG; if (sv_derived_from(ST(0), "QuestItem")) { IV tmp = SvIV((SV*)SvRV(ST(0))); - THIS = INT2PTR(ItemInst *,tmp); + THIS = INT2PTR(EQEmu::ItemInstance *,tmp); } else - Perl_croak(aTHX_ "THIS is not of type ItemInst"); + Perl_croak(aTHX_ "THIS is not of type EQEmu::ItemInstance"); if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); diff --git a/zone/pets.cpp b/zone/pets.cpp index e527d80ce..a50dcbed4 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -420,7 +420,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, // like the special back items some focused pets may receive. uint32 petinv[EQEmu::legacy::EQUIPMENT_SIZE]; memset(petinv, 0, sizeof(petinv)); - const EQEmu::ItemBase *item = 0; + const EQEmu::ItemData *item = 0; if (database.GetBasePetItems(record.equipmentset, petinv)) { for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++) @@ -665,7 +665,7 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { if(items[i] == 0) continue; - const EQEmu::ItemBase* item2 = database.GetItem(items[i]); + const EQEmu::ItemData* item2 = database.GetItem(items[i]); if (item2 && item2->NoDrop != 0) { //dont bother saving item charges for now, NPCs never use them //and nobody should be able to get them off the corpse..? diff --git a/zone/quest_interface.h b/zone/quest_interface.h index c1cf3dc73..36ca9458f 100644 --- a/zone/quest_interface.h +++ b/zone/quest_interface.h @@ -23,10 +23,14 @@ #include "../common/any.h" #include "event_codes.h" -class ItemInst; class Client; class NPC; +namespace EQEmu +{ + class ItemInstance; +} + class QuestInterface { public: virtual int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, @@ -37,7 +41,7 @@ public: std::vector *extra_pointers) { return 0; } virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers) { return 0; } - virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, + virtual int EventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { return 0; } virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers) { return 0; } @@ -49,14 +53,14 @@ public: virtual bool PlayerHasQuestSub(QuestEventID evt) { return false; } virtual bool GlobalPlayerHasQuestSub(QuestEventID evt) { return false; } virtual bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt) { return false; } - virtual bool ItemHasQuestSub(ItemInst *itm, QuestEventID evt) { return false; } + virtual bool ItemHasQuestSub(EQEmu::ItemInstance *itm, QuestEventID evt) { return false; } virtual bool EncounterHasQuestSub(std::string encounter_name, QuestEventID evt) { return false; } virtual void LoadNPCScript(std::string filename, int npc_id) { } virtual void LoadGlobalNPCScript(std::string filename) { } virtual void LoadPlayerScript(std::string filename) { } virtual void LoadGlobalPlayerScript(std::string filename) { } - virtual void LoadItemScript(std::string filename, ItemInst *item) { } + virtual void LoadItemScript(std::string filename, EQEmu::ItemInstance *item) { } virtual void LoadSpellScript(std::string filename, uint32 spell_id) { } virtual void LoadEncounterScript(std::string filename, std::string encounter_name) { } @@ -64,7 +68,7 @@ public: std::vector *extra_pointers) { return 0; } virtual int DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers) { return 0; } - virtual int DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, + virtual int DispatchEventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { return 0; } virtual int DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers) { return 0; } diff --git a/zone/quest_parser_collection.cpp b/zone/quest_parser_collection.cpp index 290b71ab9..2c2086d8c 100644 --- a/zone/quest_parser_collection.cpp +++ b/zone/quest_parser_collection.cpp @@ -200,7 +200,7 @@ bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID evt) return false; } -bool QuestParserCollection::ItemHasQuestSub(ItemInst *itm, QuestEventID evt) { +bool QuestParserCollection::ItemHasQuestSub(EQEmu::ItemInstance *itm, QuestEventID evt) { if (itm == nullptr) return false; @@ -352,7 +352,7 @@ int QuestParserCollection::EventPlayerGlobal(QuestEventID evt, Client *client, s return 0; } -int QuestParserCollection::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, +int QuestParserCollection::EventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { // needs pointer validation check on 'item' argument @@ -1013,7 +1013,7 @@ int QuestParserCollection::DispatchEventPlayer(QuestEventID evt, Client *client, return ret; } -int QuestParserCollection::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, +int QuestParserCollection::DispatchEventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { int ret = 0; auto iter = _load_precedence.begin(); diff --git a/zone/quest_parser_collection.h b/zone/quest_parser_collection.h index c17e2ccda..196cfffc2 100644 --- a/zone/quest_parser_collection.h +++ b/zone/quest_parser_collection.h @@ -44,11 +44,15 @@ extern const ZoneConfig *Config; class Client; -class ItemInst; class Mob; class NPC; class QuestInterface; -namespace EQEmu { class Any; } + +namespace EQEmu +{ + class Any; + class ItemInstance; +} class QuestParserCollection { public: @@ -65,13 +69,13 @@ public: bool HasQuestSub(uint32 npcid, QuestEventID evt); bool PlayerHasQuestSub(QuestEventID evt); bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt); - bool ItemHasQuestSub(ItemInst *itm, QuestEventID evt); + bool ItemHasQuestSub(EQEmu::ItemInstance *itm, QuestEventID evt); int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers = nullptr); int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers = nullptr); - int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, + int EventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers = nullptr); int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers = nullptr); @@ -124,7 +128,7 @@ private: std::vector *extra_pointers); int DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data, std::vector *extra_pointers); - int DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data, + int DispatchEventItem(QuestEventID evt, Client *client, EQEmu::ItemInstance *item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers); int DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 5803e547c..1df7492c2 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -54,7 +54,7 @@ QuestManager quest_manager; #define QuestManagerCurrentQuestVars() \ Mob *owner = nullptr; \ Client *initiator = nullptr; \ - ItemInst* questitem = nullptr; \ + EQEmu::ItemInstance* questitem = nullptr; \ bool depop_npc = false; \ std::string encounter; \ do { \ @@ -116,7 +116,7 @@ void QuestManager::Process() { } } -void QuestManager::StartQuest(Mob *_owner, Client *_initiator, ItemInst* _questitem, std::string encounter) { +void QuestManager::StartQuest(Mob *_owner, Client *_initiator, EQEmu::ItemInstance* _questitem, std::string encounter) { running_quest run; run.owner = _owner; run.initiator = _initiator; @@ -450,7 +450,7 @@ void QuestManager::settimerMS(const char *timer_name, int milliseconds) { QTimerList.push_back(QuestTimer(milliseconds, owner, timer_name)); } -void QuestManager::settimerMS(const char *timer_name, int milliseconds, ItemInst *inst) { +void QuestManager::settimerMS(const char *timer_name, int milliseconds, EQEmu::ItemInstance *inst) { if (inst) { inst->SetTimer(timer_name, milliseconds); } @@ -493,7 +493,7 @@ void QuestManager::stoptimer(const char *timer_name) { } } -void QuestManager::stoptimer(const char *timer_name, ItemInst *inst) { +void QuestManager::stoptimer(const char *timer_name, EQEmu::ItemInstance *inst) { if (inst) { inst->StopTimer(timer_name); } @@ -531,7 +531,7 @@ void QuestManager::stopalltimers() { } } -void QuestManager::stopalltimers(ItemInst *inst) { +void QuestManager::stopalltimers(EQEmu::ItemInstance *inst) { if (inst) { inst->ClearTimers(); } @@ -814,7 +814,7 @@ void QuestManager::traindisc(int discipline_tome_item_id) { } bool QuestManager::isdisctome(int item_id) { - const EQEmu::ItemBase *item = database.GetItem(item_id); + const EQEmu::ItemData *item = database.GetItem(item_id); if(item == nullptr) { return(false); } @@ -1305,7 +1305,7 @@ void QuestManager::settime(uint8 new_hour, uint8 new_min, bool update_world /*= void QuestManager::itemlink(int item_id) { QuestManagerCurrentQuestVars(); if (initiator) { - const EQEmu::ItemBase* item = database.GetItem(item_id); + const EQEmu::ItemData* item = database.GetItem(item_id); if (item == nullptr) return; @@ -2408,7 +2408,7 @@ int QuestManager::collectitems_processSlot(int16 slot_id, uint32 item_id, bool remove) { QuestManagerCurrentQuestVars(); - ItemInst *item = nullptr; + EQEmu::ItemInstance *item = nullptr; int quantity = 0; item = initiator->GetInv().GetItem(slot_id); @@ -2497,7 +2497,7 @@ void QuestManager::MerchantSetItem(uint32 NPCid, uint32 itemid, uint32 quantity) if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != MERCHANT)) return; // don't do anything if NPCid isn't a merchant - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; item = database.GetItem(itemid); if (!item) return; // if the item id doesn't correspond to a real item, do nothing @@ -2510,7 +2510,7 @@ uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) { if (merchant == 0 || !merchant->IsNPC() || (merchant->GetClass() != MERCHANT)) return 0; // if it isn't a merchant, it doesn't have any items - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; item = database.GetItem(itemid); if (!item) return 0; // if it isn't a valid item, the merchant doesn't have any @@ -2533,7 +2533,7 @@ uint32 QuestManager::MerchantCountItem(uint32 NPCid, uint32 itemid) { // Item Link for use in Variables - "my $example_link = quest::varlink(item_id);" const char* QuestManager::varlink(char* perltext, int item_id) { QuestManagerCurrentQuestVars(); - const EQEmu::ItemBase* item = database.GetItem(item_id); + const EQEmu::ItemData* item = database.GetItem(item_id); if (!item) return "INVALID ITEM ID IN VARLINK"; @@ -3087,7 +3087,7 @@ Mob *QuestManager::GetOwner() const { return nullptr; } -ItemInst *QuestManager::GetQuestItem() const { +EQEmu::ItemInstance *QuestManager::GetQuestItem() const { if(!quests_running_.empty()) { running_quest e = quests_running_.top(); return e.questitem; diff --git a/zone/questmgr.h b/zone/questmgr.h index 10c82c1ee..1bef4e1ee 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -25,15 +25,19 @@ #include class Client; -class ItemInst; class Mob; class NPC; +namespace EQEmu +{ + class ItemInstance; +} + class QuestManager { struct running_quest { Mob *owner; Client *initiator; - ItemInst* questitem; + EQEmu::ItemInstance* questitem; bool depop_npc; std::string encounter; }; @@ -41,7 +45,7 @@ public: QuestManager(); virtual ~QuestManager(); - void StartQuest(Mob *_owner, Client *_initiator = nullptr, ItemInst* _questitem = nullptr, std::string encounter = ""); + void StartQuest(Mob *_owner, Client *_initiator = nullptr, EQEmu::ItemInstance* _questitem = nullptr, std::string encounter = ""); void EndQuest(); bool QuestsRunning() { return !quests_running_.empty(); } @@ -70,13 +74,13 @@ public: void Zone(const char *zone_name); void settimer(const char *timer_name, int seconds); void settimerMS(const char *timer_name, int milliseconds); - void settimerMS(const char *timer_name, int milliseconds, ItemInst *inst); + void settimerMS(const char *timer_name, int milliseconds, EQEmu::ItemInstance *inst); void settimerMS(const char *timer_name, int milliseconds, Mob *mob); void stoptimer(const char *timer_name); - void stoptimer(const char *timer_name, ItemInst *inst); + void stoptimer(const char *timer_name, EQEmu::ItemInstance *inst); void stoptimer(const char *timer_name, Mob *mob); void stopalltimers(); - void stopalltimers(ItemInst *inst); + void stopalltimers(EQEmu::ItemInstance *inst); void stopalltimers(Mob *mob); void emote(const char *str); void shout(const char *str); @@ -261,7 +265,7 @@ public: Client *GetInitiator() const; NPC *GetNPC() const; Mob *GetOwner() const; - ItemInst *GetQuestItem() const; + EQEmu::ItemInstance *GetQuestItem() const; std::string GetEncounter() const; inline bool ProximitySayInUse() { return HaveProximitySays; } diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 06d8ba4a9..be0c04abb 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -83,7 +83,7 @@ void Mob::ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int3 } if (item_slot >= 0){ - const ItemInst* itm = nullptr; + const EQEmu::ItemInstance* itm = nullptr; itm = CastToClient()->GetInv().GetItem(item_slot); if(itm) dmg += itm->GetItem()->AC * (RuleI(Combat, SpecialAttackACBonus))/100; @@ -111,14 +111,14 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 if (skill == EQEmu::skills::SkillBash){ if(IsClient()){ - ItemInst *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); if(item) { if (item->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { hate += item->GetItem()->AC; } - const EQEmu::ItemBase *itm = item->GetItem(); + const EQEmu::ItemData *itm = item->GetItem(); auto fbash = GetFuriousBash(itm->Focus.Effect); hate = hate * (100 + fbash) / 100; if (fbash) @@ -463,7 +463,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) } } else{ - if (GetWeaponDamage(other, (const EQEmu::ItemBase*)nullptr) <= 0){ + if (GetWeaponDamage(other, (const EQEmu::ItemData*)nullptr) <= 0){ ndamage = -5; } } @@ -498,7 +498,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { //make sure we have a proper weapon if we are a client. if(IsClient()) { - const ItemInst *wpn = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); + const EQEmu::ItemInstance *wpn = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); if (!wpn || (wpn->GetItem()->ItemType != EQEmu::item::ItemType1HPiercing)){ Message_StringID(13, BACKSTAB_WEAPON); return; @@ -577,7 +577,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) int32 backstab_dmg = 0; if (IsClient()) { - const ItemInst *wpn = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); + const EQEmu::ItemInstance *wpn = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); if (wpn) { primaryweapondamage = GetWeaponDamage(other, wpn); if (primaryweapondamage) { @@ -650,7 +650,7 @@ void Mob::RogueAssassinate(Mob* other) { //can you dodge, parry, etc.. an assassinate?? //if so, use DoSpecialAttackDamage(other, BACKSTAB, 32000); instead - if (GetWeaponDamage(other, IsClient() ? CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary) : (const ItemInst*)nullptr) > 0){ + if (GetWeaponDamage(other, IsClient() ? CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary) : (const EQEmu::ItemInstance*)nullptr) > 0){ other->Damage(this, 32000, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab); }else{ other->Damage(this, -5, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab); @@ -670,11 +670,11 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { //Message(0, "Error: Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime()); return; } - const ItemInst* RangeWeapon = m_inv[EQEmu::legacy::SlotRange]; + const EQEmu::ItemInstance* RangeWeapon = m_inv[EQEmu::legacy::SlotRange]; //locate ammo int ammo_slot = EQEmu::legacy::SlotAmmo; - const ItemInst* Ammo = m_inv[EQEmu::legacy::SlotAmmo]; + const EQEmu::ItemInstance* Ammo = m_inv[EQEmu::legacy::SlotAmmo]; if (!RangeWeapon || !RangeWeapon->IsClassCommon()) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(EQEmu::legacy::SlotRange), EQEmu::legacy::SlotRange); @@ -687,8 +687,8 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { return; } - const EQEmu::ItemBase* RangeItem = RangeWeapon->GetItem(); - const EQEmu::ItemBase* AmmoItem = Ammo->GetItem(); + const EQEmu::ItemData* RangeItem = RangeWeapon->GetItem(); + const EQEmu::ItemData* AmmoItem = Ammo->GetItem(); if (RangeItem->ItemType != EQEmu::item::ItemTypeBow) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item is not a bow. type %d.", RangeItem->ItemType); @@ -709,17 +709,17 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { int r; bool found = false; for (r = EQEmu::legacy::GENERAL_BEGIN; r <= EQEmu::legacy::GENERAL_END; r++) { - const ItemInst *pi = m_inv[r]; + const EQEmu::ItemInstance *pi = m_inv[r]; if (pi == nullptr || !pi->IsClassBag()) continue; - const EQEmu::ItemBase* bagitem = pi->GetItem(); + const EQEmu::ItemData* bagitem = pi->GetItem(); if (!bagitem || bagitem->BagType != EQEmu::item::BagTypeQuiver) continue; //we found a quiver, look for the ammo in it int i; for (i = 0; i < bagitem->BagSlots; i++) { - ItemInst* baginst = pi->GetItem(i); + EQEmu::ItemInstance* baginst = pi->GetItem(i); if(!baginst) continue; //empty if(baginst->GetID() == Ammo->GetID()) { @@ -790,8 +790,8 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { CommonBreakInvisibleFromCombat(); } -void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, - uint32 range_id, uint32 ammo_id, const EQEmu::ItemBase *AmmoItem, int AmmoSlot, float speed) { +void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon, const EQEmu::ItemInstance* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, + uint32 range_id, uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed) { if ((other == nullptr || ((IsClient() && CastToClient()->dead) || @@ -804,9 +804,9 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite return; } - const ItemInst* _RangeWeapon = nullptr; - const ItemInst* _Ammo = nullptr; - const EQEmu::ItemBase* ammo_lost = nullptr; + const EQEmu::ItemInstance* _RangeWeapon = nullptr; + const EQEmu::ItemInstance* _Ammo = nullptr; + const EQEmu::ItemData* ammo_lost = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -1002,7 +1002,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite } } -bool Mob::TryProjectileAttack(Mob* other, const EQEmu::ItemBase *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const ItemInst* RangeWeapon, const ItemInst* Ammo, int AmmoSlot, float speed){ +bool Mob::TryProjectileAttack(Mob* other, const EQEmu::ItemData *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const EQEmu::ItemInstance* RangeWeapon, const EQEmu::ItemInstance* Ammo, int AmmoSlot, float speed){ if (!other) return false; @@ -1306,7 +1306,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha //try proc on hits and misses if(other && !other->HasDied()) - TrySpellProc(nullptr, (const EQEmu::ItemBase*)nullptr, other, EQEmu::legacy::SlotRange); + TrySpellProc(nullptr, (const EQEmu::ItemData*)nullptr, other, EQEmu::legacy::SlotRange); if (HasSkillProcs() && other && !other->HasDied()) TrySkillProc(other, skillInUse, 0, false, EQEmu::legacy::SlotRange); @@ -1352,7 +1352,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 } int ammo_slot = EQEmu::legacy::SlotRange; - const ItemInst* RangeWeapon = m_inv[EQEmu::legacy::SlotRange]; + const EQEmu::ItemInstance* RangeWeapon = m_inv[EQEmu::legacy::SlotRange]; if (!RangeWeapon || !RangeWeapon->IsClassCommon()) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(EQEmu::legacy::SlotRange), EQEmu::legacy::SlotRange); @@ -1360,7 +1360,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 return; } - const EQEmu::ItemBase* item = RangeWeapon->GetItem(); + const EQEmu::ItemData* item = RangeWeapon->GetItem(); if (item->ItemType != EQEmu::item::ItemTypeLargeThrowing && item->ItemType != EQEmu::item::ItemTypeSmallThrowing) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item %d is not a throwing weapon. type %d.", item->ItemType); Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(EQEmu::legacy::SlotRange)); @@ -1371,7 +1371,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 if(RangeWeapon->GetCharges() == 1) { //first check ammo - const ItemInst* AmmoItem = m_inv[EQEmu::legacy::SlotAmmo]; + const EQEmu::ItemInstance* AmmoItem = m_inv[EQEmu::legacy::SlotAmmo]; if(AmmoItem != nullptr && AmmoItem->GetID() == RangeWeapon->GetID()) { //more in the ammo slot, use it RangeWeapon = AmmoItem; @@ -1421,7 +1421,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 CommonBreakInvisibleFromCombat(); } -void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQEmu::ItemBase* AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed) +void Mob::DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon, const EQEmu::ItemData* AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed) { if ((other == nullptr || ((IsClient() && CastToClient()->dead) || @@ -1434,8 +1434,8 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQE return; } - const ItemInst* _RangeWeapon = nullptr; - const EQEmu::ItemBase* ammo_lost = nullptr; + const EQEmu::ItemInstance* _RangeWeapon = nullptr; + const EQEmu::ItemData* ammo_lost = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -1559,7 +1559,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const EQE } } -void Mob::SendItemAnimation(Mob *to, const EQEmu::ItemBase *item, EQEmu::skills::SkillType skillInUse, float velocity) { +void Mob::SendItemAnimation(Mob *to, const EQEmu::ItemData *item, EQEmu::skills::SkillType skillInUse, float velocity) { auto outapp = new EQApplicationPacket(OP_SomeItemPacketMaybe, sizeof(Arrow_Struct)); Arrow_Struct *as = (Arrow_Struct *) outapp->pBuffer; as->type = 1; @@ -1609,7 +1609,7 @@ void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, f if (!to) return; - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; uint8 item_type = 0; if(!item_id) { @@ -1750,7 +1750,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ dmg = -5; } else{ @@ -1771,7 +1771,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ dmg = -5; } else{ @@ -1824,7 +1824,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animKick); int32 dmg = 0; - if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ dmg = -5; } else{ @@ -1849,7 +1849,7 @@ void NPC::DoClassAttacks(Mob *target) { DoAnim(animTailRake); int32 dmg = 0; - if (GetWeaponDamage(target, (const EQEmu::ItemBase*)nullptr) <= 0){ + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ dmg = -5; } else{ @@ -2361,7 +2361,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: int32 max_hit = (2 * weapon_damage*GetDamageTable(skillinuse)) / 100; if(GetLevel() >= 28 && IsWarriorClass() ) { - int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::ItemBase*) nullptr); + int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::ItemData*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; hate += ucDamageBonus; @@ -2369,12 +2369,12 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: if (skillinuse == EQEmu::skills::SkillBash){ if(IsClient()){ - ItemInst *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); if(item){ if (item->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { hate += item->GetItem()->AC; } - const EQEmu::ItemBase *itm = item->GetItem(); + const EQEmu::ItemData *itm = item->GetItem(); hate = hate * (100 + GetFuriousBash(itm->Focus.Effect)) / 100; } } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 564a9756a..161604ea9 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -48,7 +48,7 @@ extern WorldServer worldserver; bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_override) { int caster_level, buffslot, effect, effect_value, i; - ItemInst *SummonedItem=nullptr; + EQEmu::ItemInstance *SummonedItem=nullptr; #ifdef SPELL_EFFECT_SPAM #define _EDLEN 200 char effect_desc[_EDLEN]; @@ -61,7 +61,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove bool c_override = false; if (caster && caster->IsClient() && GetCastedSpellInvSlot() > 0) { - const ItemInst *inst = caster->CastToClient()->GetInv().GetItem(GetCastedSpellInvSlot()); + const EQEmu::ItemInstance *inst = caster->CastToClient()->GetInv().GetItem(GetCastedSpellInvSlot()); if (inst) { if (inst->GetItem()->Click.Level > 0) { caster_level = inst->GetItem()->Click.Level; @@ -622,7 +622,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Flesh To Bone"); #endif if(IsClient()){ - ItemInst* transI = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotCursor); + EQEmu::ItemInstance* transI = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotCursor); if (transI && transI->IsClassCommon() && transI->IsStackable()){ uint32 fcharges = transI->GetCharges(); //Does it sound like meat... maybe should check if it looks like meat too... @@ -1148,7 +1148,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_SummonItem: { - const EQEmu::ItemBase *item = database.GetItem(spell.base[i]); + const EQEmu::ItemData *item = database.GetItem(spell.base[i]); #ifdef SPELL_EFFECT_SPAM const char *itemname = item ? item->Name : "*Unknown Item*"; snprintf(effect_desc, _EDLEN, "Summon Item: %s (id %d)", itemname, spell.base[i]); @@ -1184,7 +1184,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } case SE_SummonItemIntoBag: { - const EQEmu::ItemBase *item = database.GetItem(spell.base[i]); + const EQEmu::ItemData *item = database.GetItem(spell.base[i]); #ifdef SPELL_EFFECT_SPAM const char *itemname = item ? item->Name : "*Unknown Item*"; snprintf(effect_desc, _EDLEN, "Summon Item In Bag: %s (id %d)", itemname, spell.base[i]); @@ -1213,7 +1213,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (charges < 1) charges = 1; - ItemInst *SubItem = database.CreateItem(spell.base[i], charges); + EQEmu::ItemInstance *SubItem = database.CreateItem(spell.base[i], charges); if (SubItem != nullptr) { SummonedItem->PutItem(slot, *SubItem); safe_delete(SubItem); @@ -5172,7 +5172,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { //item focus if (itembonuses.FocusEffects[type]){ - const EQEmu::ItemBase* TempItem = 0; + const EQEmu::ItemData* TempItem = 0; for (int x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::EQUIPMENT_END; x++) { @@ -5180,7 +5180,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { continue; TempItem = nullptr; - ItemInst* ins = GetInv().GetItem(x); + EQEmu::ItemInstance* ins = GetInv().GetItem(x); if (!ins) continue; TempItem = ins->GetItem(); @@ -5199,11 +5199,11 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; - ItemInst *aug = nullptr; + EQEmu::ItemInstance *aug = nullptr; aug = ins->GetAugment(y); if(aug) { - const EQEmu::ItemBase* TempItemAug = aug->GetItem(); + const EQEmu::ItemData* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && IsValidSpell(TempItemAug->Focus.Effect)) { proc_spellid = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id); if (IsValidSpell(proc_spellid)){ @@ -5301,8 +5301,8 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[type]){ - const EQEmu::ItemBase* TempItem = 0; - const EQEmu::ItemBase* UsedItem = 0; + const EQEmu::ItemData* TempItem = 0; + const EQEmu::ItemData* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -5312,7 +5312,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) for (int x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::EQUIPMENT_END; x++) { TempItem = nullptr; - ItemInst* ins = GetInv().GetItem(x); + EQEmu::ItemInstance* ins = GetInv().GetItem(x); if (!ins) continue; TempItem = ins->GetItem(); @@ -5345,11 +5345,11 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) for (int y = AUG_INDEX_BEGIN; y < EQEmu::legacy::ITEM_COMMON_SIZE; ++y) { - ItemInst *aug = nullptr; + EQEmu::ItemInstance *aug = nullptr; aug = ins->GetAugment(y); if(aug) { - const EQEmu::ItemBase* TempItemAug = aug->GetItem(); + const EQEmu::ItemData* TempItemAug = aug->GetItem(); if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { if(rand_effectiveness) { focus_max = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id, true); @@ -5384,7 +5384,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) for (int x = EQEmu::legacy::TRIBUTE_BEGIN; x <= EQEmu::legacy::TRIBUTE_END; ++x) { TempItem = nullptr; - ItemInst* ins = GetInv().GetItem(x); + EQEmu::ItemInstance* ins = GetInv().GetItem(x); if (!ins) continue; TempItem = ins->GetItem(); @@ -5573,8 +5573,8 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { if (RuleB(Spells, NPC_UseFocusFromItems) && itembonuses.FocusEffects[type]){ - const EQEmu::ItemBase* TempItem = 0; - const EQEmu::ItemBase* UsedItem = 0; + const EQEmu::ItemData* TempItem = 0; + const EQEmu::ItemData* UsedItem = 0; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -5582,7 +5582,7 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { //item focus for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++){ - const EQEmu::ItemBase *cur = database.GetItem(equipment[i]); + const EQEmu::ItemData *cur = database.GetItem(equipment[i]); if(!cur) continue; diff --git a/zone/spells.cpp b/zone/spells.cpp index 6c27ab610..e00fc05c2 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -256,7 +256,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, //Added to prevent MQ2 exploitation of equipping normally-unequippable/clickable items with effects and clicking them for benefits. if(item_slot && IsClient() && (slot == CastingSlot::Item || slot == CastingSlot::PotionBelt)) { - ItemInst *itm = CastToClient()->GetInv().GetItem(item_slot); + EQEmu::ItemInstance *itm = CastToClient()->GetInv().GetItem(item_slot); int bitmask = 1; bitmask = bitmask << (CastToClient()->GetClass() - 1); if( itm && itm->GetItem()->Classes != 65535 ) { @@ -936,7 +936,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo if(IsClient() && (slot == CastingSlot::Item || slot == CastingSlot::PotionBelt)) { IsFromItem = true; - ItemInst *itm = CastToClient()->GetInv().GetItem(inventory_slot); + EQEmu::ItemInstance *itm = CastToClient()->GetInv().GetItem(inventory_slot); if(itm && itm->GetItem()->RecastDelay > 0) { if(!CastToClient()->GetPTimers().Expired(&database, (pTimerItemStart + itm->GetItem()->RecastType), false)) { @@ -1174,7 +1174,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo missingreags=true; } - const EQEmu::ItemBase *item = database.GetItem(component); + const EQEmu::ItemData *item = database.GetItem(component); if(item) { c->Message_StringID(13, MISSING_SPELL_COMP_ITEM, item->Name); Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Canceled. Missing required reagent %s (%d)", spell_id, item->Name, component); @@ -1235,8 +1235,8 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo && inventory_slot != 0xFFFFFFFF) // 10 is an item { bool fromaug = false; - const ItemInst* inst = CastToClient()->GetInv()[inventory_slot]; - EQEmu::ItemBase* augitem = 0; + const EQEmu::ItemInstance* inst = CastToClient()->GetInv()[inventory_slot]; + EQEmu::ItemData* augitem = 0; uint32 recastdelay = 0; uint32 recasttype = 0; @@ -1245,11 +1245,11 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo break; for (int r = AUG_INDEX_BEGIN; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { - const ItemInst* aug_i = inst->GetAugment(r); + const EQEmu::ItemInstance* aug_i = inst->GetAugment(r); if (!aug_i) continue; - const EQEmu::ItemBase* aug = aug_i->GetItem(); + const EQEmu::ItemData* aug = aug_i->GetItem(); if (!aug) continue; @@ -1285,7 +1285,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo if (inst && inst->IsClassCommon() && (inst->GetItem()->Click.Effect == spell_id) && inst->GetCharges() || fromaug) { - //const ItemBase* item = inst->GetItem(); + //const ItemData* item = inst->GetItem(); int16 charges = inst->GetItem()->MaxCharges; if(fromaug) { charges = -1; } //Don't destroy the parent item @@ -2385,7 +2385,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui if(IsClient() && (slot == CastingSlot::Item || slot == CastingSlot::PotionBelt)) { - ItemInst *itm = CastToClient()->GetInv().GetItem(inventory_slot); + EQEmu::ItemInstance *itm = CastToClient()->GetInv().GetItem(inventory_slot); if(itm && itm->GetItem()->RecastDelay > 0){ auto recast_type = itm->GetItem()->RecastType; CastToClient()->GetPTimers().Start((pTimerItemStart + recast_type), itm->GetItem()->RecastDelay); diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 40e7d8b67..dff042388 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1708,7 +1708,7 @@ void ClientTaskState::UpdateTasksOnExplore(Client *c, int ExploreID) { return; } -bool ClientTaskState::UpdateTasksOnDeliver(Client *c, std::list& Items, int Cash, int NPCTypeID) { +bool ClientTaskState::UpdateTasksOnDeliver(Client *c, std::list& Items, int Cash, int NPCTypeID) { bool Ret = false; @@ -1900,7 +1900,7 @@ void ClientTaskState::RewardTask(Client *c, TaskInformation *Task) { if(!Task || !c) return; - const EQEmu::ItemBase* Item; + const EQEmu::ItemData* Item; std::vector RewardList; switch(Task->RewardMethod) { @@ -2791,7 +2791,7 @@ void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, int SequenceN } if(ItemID) { - const EQEmu::ItemBase* reward_item = database.GetItem(ItemID); + const EQEmu::ItemData* reward_item = database.GetItem(ItemID); EQEmu::SayLinkEngine linker; linker.SetLinkType(EQEmu::saylink::SayLinkItemData); diff --git a/zone/tasks.h b/zone/tasks.h index 9b5543b3d..5a6944639 100644 --- a/zone/tasks.h +++ b/zone/tasks.h @@ -45,7 +45,11 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) class Client; class Mob; -class ItemInst; + +namespace EQEmu +{ + class ItemInstance; +} struct TaskGoalList_Struct { int ListID; @@ -187,7 +191,7 @@ public: void UpdateTasksForItem(Client *c, ActivityType Type, int ItemID, int Count=1); void UpdateTasksOnExplore(Client *c, int ExploreID); bool UpdateTasksOnSpeakWith(Client *c, int NPCTypeID); - bool UpdateTasksOnDeliver(Client *c, std::list& Items, int Cash, int NPCTypeID); + bool UpdateTasksOnDeliver(Client *c, std::list& Items, int Cash, int NPCTypeID); void UpdateTasksOnTouch(Client *c, int ZoneID); void ProcessTaskProximities(Client *c, float X, float Y, float Z); bool TaskOutOfTime(int Index); diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 6deb51778..38bb5a231 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -46,7 +46,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme return; } - ItemInst* container = nullptr; + EQEmu::ItemInstance* container = nullptr; if (worldo) { @@ -56,12 +56,12 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme { // Check to see if they have an inventory container type 53 that is used for this. Inventory& user_inv = user->GetInv(); - ItemInst* inst = nullptr; + EQEmu::ItemInstance* inst = nullptr; inst = user_inv.GetItem(in_augment->container_slot); if (inst) { - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); if (item && inst->IsType(EQEmu::item::ItemClassBag) && item->BagType == 53) { // We have found an appropriate inventory augmentation sealer @@ -71,7 +71,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme uint8 itemsFound = 0; for (uint8 i = SLOT_BEGIN; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) { - const ItemInst* inst = container->GetItem(i); + const EQEmu::ItemInstance* inst = container->GetItem(i); if (inst) { itemsFound++; @@ -94,7 +94,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme return; } - ItemInst *tobe_auged = nullptr, *auged_with = nullptr; + EQEmu::ItemInstance *tobe_auged = nullptr, *auged_with = nullptr; int8 slot=-1; // Verify 2 items in the augmentation device @@ -135,7 +135,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme bool deleteItems = false; - ItemInst *itemOneToPush = nullptr, *itemTwoToPush = nullptr; + EQEmu::ItemInstance *itemOneToPush = nullptr, *itemTwoToPush = nullptr; // Adding augment if (in_augment->augment_slot == -1) @@ -145,7 +145,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme { tobe_auged->PutAugment(slot, *auged_with); - ItemInst *aug = tobe_auged->GetAugment(slot); + EQEmu::ItemInstance *aug = tobe_auged->GetAugment(slot); if(aug) { std::vector args; args.push_back(aug); @@ -165,7 +165,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme } else { - ItemInst *old_aug = nullptr; + EQEmu::ItemInstance *old_aug = nullptr; bool isSolvent = auged_with->GetItem()->ItemType == EQEmu::item::ItemTypeAugmentationSolvent; if (!isSolvent && auged_with->GetItem()->ItemType != EQEmu::item::ItemTypeAugmentationDistiller) { @@ -175,7 +175,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme return; } - ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_slot); + EQEmu::ItemInstance *aug = tobe_auged->GetAugment(in_augment->augment_slot); if (aug) { if (!isSolvent && auged_with->GetItem()->ID != aug->GetItem()->AugDistiller) { @@ -224,7 +224,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme // Delete items in our inventory container... for (uint8 i = SLOT_BEGIN; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) { - const ItemInst* inst = container->GetItem(i); + const EQEmu::ItemInstance* inst = container->GetItem(i); if (inst) { user->DeleteItemInInventory(Inventory::CalcSlotId(in_augment->container_slot,i),0,true); @@ -258,8 +258,8 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob Inventory& user_inv = user->GetInv(); PlayerProfile_Struct& user_pp = user->GetPP(); - ItemInst* container = nullptr; - ItemInst* inst = nullptr; + EQEmu::ItemInstance* container = nullptr; + EQEmu::ItemInstance* inst = nullptr; uint8 c_type = 0xE8; uint32 some_id = 0; bool worldcontainer=false; @@ -276,7 +276,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob else { inst = user_inv.GetItem(in_combine->container_slot); if (inst) { - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); if (item && inst->IsType(EQEmu::item::ItemClassBag)) { c_type = item->BagType; some_id = item->ID; @@ -291,10 +291,10 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob container = inst; if (container->GetItem() && container->GetItem()->BagType == EQEmu::item::BagTypeTransformationmold) { - const ItemInst* inst = container->GetItem(0); + const EQEmu::ItemInstance* inst = container->GetItem(0); bool AllowAll = RuleB(Inventory, AllowAnyWeaponTransformation); - if (inst && ItemInst::CanTransform(inst->GetItem(), container->GetItem(), AllowAll)) { - const EQEmu::ItemBase* new_weapon = inst->GetItem(); + if (inst && EQEmu::ItemInstance::CanTransform(inst->GetItem(), container->GetItem(), AllowAll)) { + const EQEmu::ItemData* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::legacy::SlotCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2)); @@ -312,9 +312,9 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob } if (container->GetItem() && container->GetItem()->BagType == EQEmu::item::BagTypeDetransformationmold) { - const ItemInst* inst = container->GetItem(0); + const EQEmu::ItemInstance* inst = container->GetItem(0); if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIcon()) { - const EQEmu::ItemBase* new_weapon = inst->GetItem(); + const EQEmu::ItemData* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::legacy::SlotCursor, 0, 0); @@ -402,7 +402,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob database.DeleteWorldContainer(worldo->m_id, zone->GetZoneID()); } else{ for (uint8 i = SLOT_BEGIN; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) { - const ItemInst* inst = container->GetItem(i); + const EQEmu::ItemInstance* inst = container->GetItem(i); if (inst) { user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot,i),0,true); } @@ -537,7 +537,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac user->Message_StringID(MT_Skills, TRADESKILL_MISSING_COMPONENTS); for (auto it = MissingItems.begin(); it != MissingItems.end(); ++it) { - const EQEmu::ItemBase* item = database.GetItem(*it); + const EQEmu::ItemData* item = database.GetItem(*it); if(item) user->Message_StringID(MT_Skills, TRADESKILL_MISSING_ITEM, item->Name); @@ -566,7 +566,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac return; } - const ItemInst* inst = user_inv.GetItem(slot); + const EQEmu::ItemInstance* inst = user_inv.GetItem(slot); if (inst && !inst->IsStackable()) user->DeleteItemInInventory(slot, 0, true); @@ -962,7 +962,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { aa_chance = spellbonuses.ReduceTradeskillFail[spec->tradeskill] + itembonuses.ReduceTradeskillFail[spec->tradeskill] + aabonuses.ReduceTradeskillFail[spec->tradeskill]; - const EQEmu::ItemBase* item = nullptr; + const EQEmu::ItemData* item = nullptr; chance = mod_tradeskill_chance(chance, spec); @@ -1090,7 +1090,7 @@ void Client::CheckIncreaseTradeskill(int16 bonusstat, int16 stat_modifier, float Log.Out(Logs::Detail, Logs::Tradeskills, "...Stage2 chance was: %f percent. 0 percent means stage1 failed", chance_stage2); } -bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint32 some_id, +bool ZoneDatabase::GetTradeRecipe(const EQEmu::ItemInstance* container, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec) { if (container == nullptr) @@ -1109,11 +1109,11 @@ bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint3 uint32 count = 0; uint32 sum = 0; for (uint8 i = 0; i < 10; i++) { // TODO: need to determine if this is bound to world/item container size - const ItemInst* inst = container->GetItem(i); + const EQEmu::ItemInstance* inst = container->GetItem(i); if (!inst) continue; - const EQEmu::ItemBase* item = GetItem(inst->GetItem()->ID); + const EQEmu::ItemData* item = GetItem(inst->GetItem()->ID); if (!item) continue; @@ -1238,11 +1238,11 @@ bool ZoneDatabase::GetTradeRecipe(const ItemInst* container, uint8 c_type, uint3 int ccnt = 0; for (int x = SLOT_BEGIN; x < EQEmu::legacy::TYPE_WORLD_SIZE; x++) { - const ItemInst* inst = container->GetItem(x); + const EQEmu::ItemInstance* inst = container->GetItem(x); if(!inst) continue; - const EQEmu::ItemBase* item = GetItem(inst->GetItem()->ID); + const EQEmu::ItemData* item = GetItem(inst->GetItem()->ID); if (!item) continue; diff --git a/zone/trading.cpp b/zone/trading.cpp index aab8ac8ac..cfca3a2e6 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -98,14 +98,14 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) { // Item always goes into trade bucket from cursor Client* client = owner->CastToClient(); - ItemInst* inst = client->GetInv().GetItem(EQEmu::legacy::SlotCursor); + EQEmu::ItemInstance* inst = client->GetInv().GetItem(EQEmu::legacy::SlotCursor); if (!inst) { client->Message(13, "Error: Could not find item on your cursor!"); return; } - ItemInst* inst2 = client->GetInv().GetItem(trade_slot_id); + EQEmu::ItemInstance* inst2 = client->GetInv().GetItem(trade_slot_id); // it looks like the original code attempted to allow stacking... // (it just didn't handle partial stack move actions) @@ -158,7 +158,7 @@ Mob* Trade::With() } // Private Method: Send item data for trade item to other person involved in trade -void Trade::SendItemData(const ItemInst* inst, int16 dest_slot_id) +void Trade::SendItemData(const EQEmu::ItemInstance* inst, int16 dest_slot_id) { if (inst == nullptr) return; @@ -175,7 +175,7 @@ void Trade::SendItemData(const ItemInst* inst, int16 dest_slot_id) if (inst->GetItem()->ItemClass == 1) { for (uint16 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { uint16 bagslot_id = Inventory::CalcSlotId(dest_slot_id, i); - const ItemInst* bagitem = trader->GetInv().GetItem(bagslot_id); + const EQEmu::ItemInstance* bagitem = trader->GetInv().GetItem(bagslot_id); if (bagitem) { with->SendItemPacket(bagslot_id - EQEmu::legacy::TRADE_BEGIN, bagitem, ItemPacketTradeView); } @@ -252,7 +252,7 @@ void Trade::LogTrade() strcat(logtext, "items {"); for (uint16 i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_END; i++) { - const ItemInst* inst = trader->GetInv().GetItem(i); + const EQEmu::ItemInstance* inst = trader->GetInv().GetItem(i); if (!comma) comma = true; @@ -304,7 +304,7 @@ void Trade::DumpTrade() Client* trader = owner->CastToClient(); for (uint16 i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_END; i++) { - const ItemInst* inst = trader->GetInv().GetItem(i); + const EQEmu::ItemInstance* inst = trader->GetInv().GetItem(i); if (inst) { Log.Out(Logs::Detail, Logs::Trading, "Item %i (Charges=%i, Slot=%i, IsBag=%s)", @@ -333,7 +333,7 @@ void Client::ResetTrade() { // step 1: process bags for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { - const ItemInst* inst = m_inv[trade_slot]; + const EQEmu::ItemInstance* inst = m_inv[trade_slot]; if (inst && inst->IsClassBag()) { int16 free_slot = m_inv.FindFreeSlotForTradeItem(inst); @@ -352,7 +352,7 @@ void Client::ResetTrade() { // step 2a: process stackables for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { - ItemInst* inst = GetInv().GetItem(trade_slot); + EQEmu::ItemInstance* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { while (true) { @@ -362,7 +362,7 @@ void Client::ResetTrade() { if ((free_slot == EQEmu::legacy::SlotCursor) || (free_slot == INVALID_INDEX)) break; - ItemInst* partial_inst = GetInv().GetItem(free_slot); + EQEmu::ItemInstance* partial_inst = GetInv().GetItem(free_slot); if (!partial_inst) break; @@ -399,14 +399,14 @@ void Client::ResetTrade() { // step 2b: adjust trade stack bias // (if any partial stacks exist before the final stack, FindFreeSlotForTradeItem() will return that slot in step 3 and an overwrite will occur) for (int16 trade_slot = EQEmu::legacy::TRADE_END; trade_slot >= EQEmu::legacy::TRADE_BEGIN; --trade_slot) { - ItemInst* inst = GetInv().GetItem(trade_slot); + EQEmu::ItemInstance* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { for (int16 bias_slot = EQEmu::legacy::TRADE_BEGIN; bias_slot <= EQEmu::legacy::TRADE_END; ++bias_slot) { if (bias_slot >= trade_slot) break; - ItemInst* bias_inst = GetInv().GetItem(bias_slot); + EQEmu::ItemInstance* bias_inst = GetInv().GetItem(bias_slot); if (!bias_inst || (bias_inst->GetID() != inst->GetID()) || (bias_inst->GetCharges() >= bias_inst->GetItem()->StackSize)) continue; @@ -433,7 +433,7 @@ void Client::ResetTrade() { // step 3: process everything else for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { - const ItemInst* inst = m_inv[trade_slot]; + const EQEmu::ItemInstance* inst = m_inv[trade_slot]; if (inst) { int16 free_slot = m_inv.FindFreeSlotForTradeItem(inst); @@ -488,7 +488,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // step 1: process bags for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { - const ItemInst* inst = m_inv[trade_slot]; + const EQEmu::ItemInstance* inst = m_inv[trade_slot]; if (inst && inst->IsClassBag()) { Log.Out(Logs::Detail, Logs::Trading, "Giving container %s (%d) in slot %d to %s", inst->GetItem()->Name, inst->GetItem()->ID, trade_slot, other->GetName()); @@ -524,7 +524,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { for (uint8 sub_slot = SUB_INDEX_BEGIN; (sub_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items - const ItemInst* bag_inst = inst->GetItem(sub_slot); + const EQEmu::ItemInstance* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { detail = new QSTradeItems_Struct; @@ -572,7 +572,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // step 2a: process stackables for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { - ItemInst* inst = GetInv().GetItem(trade_slot); + EQEmu::ItemInstance* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { while (true) { @@ -582,7 +582,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if ((partial_slot == EQEmu::legacy::SlotCursor) || (partial_slot == INVALID_INDEX)) break; - ItemInst* partial_inst = other->GetInv().GetItem(partial_slot); + EQEmu::ItemInstance* partial_inst = other->GetInv().GetItem(partial_slot); if (!partial_inst) break; @@ -654,14 +654,14 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // step 2b: adjust trade stack bias // (if any partial stacks exist before the final stack, FindFreeSlotForTradeItem() will return that slot in step 3 and an overwrite will occur) for (int16 trade_slot = EQEmu::legacy::TRADE_END; trade_slot >= EQEmu::legacy::TRADE_BEGIN; --trade_slot) { - ItemInst* inst = GetInv().GetItem(trade_slot); + EQEmu::ItemInstance* inst = GetInv().GetItem(trade_slot); if (inst && inst->IsStackable()) { for (int16 bias_slot = EQEmu::legacy::TRADE_BEGIN; bias_slot <= EQEmu::legacy::TRADE_END; ++bias_slot) { if (bias_slot >= trade_slot) break; - ItemInst* bias_inst = GetInv().GetItem(bias_slot); + EQEmu::ItemInstance* bias_inst = GetInv().GetItem(bias_slot); if (!bias_inst || (bias_inst->GetID() != inst->GetID()) || (bias_inst->GetCharges() >= bias_inst->GetItem()->StackSize)) continue; @@ -707,7 +707,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // step 3: process everything else for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_END; ++trade_slot) { - const ItemInst* inst = m_inv[trade_slot]; + const EQEmu::ItemInstance* inst = m_inv[trade_slot]; if (inst) { Log.Out(Logs::Detail, Logs::Trading, "Giving item %s (%d) in slot %d to %s", inst->GetItem()->Name, inst->GetItem()->ID, trade_slot, other->GetName()); @@ -744,7 +744,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // 'step 3' should never really see containers..but, just in case... //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { for (uint8 sub_slot = SUB_INDEX_BEGIN; (sub_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items - const ItemInst* bag_inst = inst->GetItem(sub_slot); + const EQEmu::ItemInstance* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { detail = new QSTradeItems_Struct; @@ -821,7 +821,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if(qs_log) { // This can be incorporated below when revisions are made for (int16 trade_slot = EQEmu::legacy::TRADE_BEGIN; trade_slot <= EQEmu::legacy::TRADE_NPC_END; ++trade_slot) { - const ItemInst* trade_inst = m_inv[trade_slot]; + const EQEmu::ItemInstance* trade_inst = m_inv[trade_slot]; if(trade_inst) { auto detail = new QSHandinItems_Struct; @@ -842,7 +842,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if (trade_inst->IsClassBag()) { for (uint8 sub_slot = SUB_INDEX_BEGIN; sub_slot < trade_inst->GetItem()->BagSlots; ++sub_slot) { - const ItemInst* trade_baginst = trade_inst->GetItem(sub_slot); + const EQEmu::ItemInstance* trade_baginst = trade_inst->GetItem(sub_slot); if(trade_baginst) { detail = new QSHandinItems_Struct; @@ -874,27 +874,27 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st } std::vector item_list; - std::list items; + std::list items; for (int i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_NPC_END; ++i) { - ItemInst *inst = m_inv.GetItem(i); + EQEmu::ItemInstance *inst = m_inv.GetItem(i); if(inst) { items.push_back(inst); item_list.push_back(inst); } else { - item_list.push_back((ItemInst*)nullptr); + item_list.push_back((EQEmu::ItemInstance*)nullptr); continue; } - const EQEmu::ItemBase* item = inst->GetItem(); + const EQEmu::ItemData* item = inst->GetItem(); if(item && quest_npc == false) { // if it was not a NO DROP or Attuned item (or if a GM is trading), let the NPC have it if(GetGM() || (item->NoDrop != 0 && inst->IsAttuned() == false)) { // pets need to look inside bags and try to equip items found there if (item->IsClassBag() && item->BagSlots > 0) { for (int16 bslot = SUB_INDEX_BEGIN; bslot < item->BagSlots; bslot++) { - const ItemInst* baginst = inst->GetItem(bslot); + const EQEmu::ItemInstance* baginst = inst->GetItem(bslot); if (baginst) { - const EQEmu::ItemBase* bagitem = baginst->GetItem(); + const EQEmu::ItemData* bagitem = baginst->GetItem(); if (bagitem && (GetGM() || (bagitem->NoDrop != 0 && baginst->IsAttuned() == false))) { tradingWith->CastToNPC()->AddLootDrop(bagitem, &tradingWith->CastToNPC()->itemlist, baginst->GetCharges(), 1, 127, true, true); @@ -947,7 +947,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st tradingWith->FaceTarget(this); } - ItemInst *insts[4] = { 0 }; + EQEmu::ItemInstance *insts[4] = { 0 }; for (int i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_NPC_END; ++i) { insts[i - EQEmu::legacy::TRADE_BEGIN] = m_inv.PopItem(i); database.SaveInventory(CharacterID(), nullptr, i); @@ -969,7 +969,7 @@ bool Client::CheckTradeLoreConflict(Client* other) return true; // Move each trade slot into free inventory slot for (int16 i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_END; i++){ - const ItemInst* inst = m_inv[i]; + const EQEmu::ItemInstance* inst = m_inv[i]; if (inst && inst->GetItem()) { if (other->CheckLoreConflict(inst->GetItem())) @@ -978,7 +978,7 @@ bool Client::CheckTradeLoreConflict(Client* other) } for (int16 i = EQEmu::legacy::TRADE_BAGS_BEGIN; i <= EQEmu::legacy::TRADE_BAGS_END; i++){ - const ItemInst* inst = m_inv[i]; + const EQEmu::ItemInstance* inst = m_inv[i]; if (inst && inst->GetItem()) { if (other->CheckLoreConflict(inst->GetItem())) @@ -1158,14 +1158,14 @@ void Client::SendTraderItem(uint32 ItemID, uint16 Quantity) { std::string Packet; int16 FreeSlotID=0; - const EQEmu::ItemBase* item = database.GetItem(ItemID); + const EQEmu::ItemData* item = database.GetItem(ItemID); if(!item){ Log.Out(Logs::Detail, Logs::Trading, "Bogus item deleted in Client::SendTraderItem!\n"); return; } - ItemInst* inst = database.CreateItem(item, Quantity); + EQEmu::ItemInstance* inst = database.CreateItem(item, Quantity); if (inst) { @@ -1183,7 +1183,7 @@ void Client::SendTraderItem(uint32 ItemID, uint16 Quantity) { void Client::SendSingleTraderItem(uint32 CharID, int SerialNumber) { - ItemInst* inst= database.LoadSingleTraderItem(CharID, SerialNumber); + EQEmu::ItemInstance* inst= database.LoadSingleTraderItem(CharID, SerialNumber); if(inst) { SendItemPacket(30, inst, ItemPacketMerchant); // MainCursor? safe_delete(inst); @@ -1192,7 +1192,7 @@ void Client::SendSingleTraderItem(uint32 CharID, int SerialNumber) { } void Client::BulkSendTraderInventory(uint32 char_id) { - const EQEmu::ItemBase *item; + const EQEmu::ItemData *item; TraderCharges_Struct* TraderItems = database.LoadTraderItemWithCharges(char_id); @@ -1204,7 +1204,7 @@ void Client::BulkSendTraderInventory(uint32 char_id) { item=database.GetItem(TraderItems->ItemID[i]); if (item && (item->NoDrop!=0)) { - ItemInst* inst = database.CreateItem(item); + EQEmu::ItemInstance* inst = database.CreateItem(item); if (inst) { inst->SetSerialNumber(TraderItems->SerialNumber[i]); if(TraderItems->Charges[i] > 0) @@ -1230,7 +1230,7 @@ void Client::BulkSendTraderInventory(uint32 char_id) { uint32 Client::FindTraderItemSerialNumber(int32 ItemID) { - ItemInst* item = nullptr; + EQEmu::ItemInstance* item = nullptr; uint16 SlotID = 0; for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++){ item = this->GetInv().GetItem(i); @@ -1251,9 +1251,9 @@ uint32 Client::FindTraderItemSerialNumber(int32 ItemID) { return 0; } -ItemInst* Client::FindTraderItemBySerialNumber(int32 SerialNumber){ +EQEmu::ItemInstance* Client::FindTraderItemBySerialNumber(int32 SerialNumber){ - ItemInst* item = nullptr; + EQEmu::ItemInstance* item = nullptr; uint16 SlotID = 0; for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++){ item = this->GetInv().GetItem(i); @@ -1277,7 +1277,7 @@ ItemInst* Client::FindTraderItemBySerialNumber(int32 SerialNumber){ GetItems_Struct* Client::GetTraderItems(){ - const ItemInst* item = nullptr; + const EQEmu::ItemInstance* item = nullptr; uint16 SlotID = 0; auto gis = new GetItems_Struct; @@ -1308,7 +1308,7 @@ GetItems_Struct* Client::GetTraderItems(){ uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){ - const ItemInst* item= nullptr; + const EQEmu::ItemInstance* item= nullptr; uint16 SlotID = 0; for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { item = this->GetInv().GetItem(i); @@ -1370,7 +1370,7 @@ void Client::NukeTraderItem(uint16 Slot,int16 Charges,uint16 Quantity,Client* Cu } // This updates the trader. Removes it from his trading bags. // - const ItemInst* Inst = m_inv[Slot]; + const EQEmu::ItemInstance* Inst = m_inv[Slot]; database.SaveInventory(CharacterID(), Inst, Slot); @@ -1412,7 +1412,7 @@ void Client::TraderUpdate(uint16 SlotID,uint32 TraderID){ void Client::FindAndNukeTraderItem(int32 SerialNumber, uint16 Quantity, Client* Customer, uint16 TraderSlot){ - const ItemInst* item= nullptr; + const EQEmu::ItemInstance* item= nullptr; bool Stackable = false; int16 Charges=0; @@ -1564,7 +1564,7 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic outtbs->ItemID = tbs->ItemID; - const ItemInst* BuyItem = nullptr; + const EQEmu::ItemInstance* BuyItem = nullptr; uint32 ItemID = 0; if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) @@ -2027,11 +2027,11 @@ static void UpdateTraderCustomerItemsAdded(uint32 CustomerID, TraderCharges_Stru if(!Customer) return; - const EQEmu::ItemBase *item = database.GetItem(ItemID); + const EQEmu::ItemData *item = database.GetItem(ItemID); if(!item) return; - ItemInst* inst = database.CreateItem(item); + EQEmu::ItemInstance* inst = database.CreateItem(item); if(!inst) return; @@ -2071,7 +2071,7 @@ static void UpdateTraderCustomerPriceChanged(uint32 CustomerID, TraderCharges_St if(!Customer) return; - const EQEmu::ItemBase *item = database.GetItem(ItemID); + const EQEmu::ItemData *item = database.GetItem(ItemID); if(!item) return; @@ -2112,7 +2112,7 @@ static void UpdateTraderCustomerPriceChanged(uint32 CustomerID, TraderCharges_St Log.Out(Logs::Detail, Logs::Trading, "Sending price updates to customer %s", Customer->GetName()); - ItemInst* inst = database.CreateItem(item); + EQEmu::ItemInstance* inst = database.CreateItem(item); if(!inst) return; @@ -2230,7 +2230,7 @@ void Client::HandleTraderPriceUpdate(const EQApplicationPacket *app) { } - const EQEmu::ItemBase *item = 0; + const EQEmu::ItemData *item = 0; if(IDOfItemToAdd) item = database.GetItem(IDOfItemToAdd); @@ -2396,7 +2396,7 @@ void Client::SendBuyerResults(char* searchString, uint32 searchID) { char *buf = (char *)outapp->pBuffer; - const EQEmu::ItemBase* item = database.GetItem(itemID); + const EQEmu::ItemData* item = database.GetItem(itemID); if(!item) { safe_delete(outapp); @@ -2492,7 +2492,7 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) { char *Buf = (char *)outapp->pBuffer; - const EQEmu::ItemBase* item = database.GetItem(ItemID); + const EQEmu::ItemData* item = database.GetItem(ItemID); if(!item) { safe_delete(outapp); @@ -2536,7 +2536,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { /*uint32 BuyerID2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused /*uint32 Unknown3 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused - const EQEmu::ItemBase *item = database.GetItem(ItemID); + const EQEmu::ItemData *item = database.GetItem(ItemID); if(!item || !Quantity || !Price || !QtyBuyerWants) return; @@ -2602,7 +2602,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { return; } - ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot); + EQEmu::ItemInstance* ItemToTransfer = m_inv.PopItem(SellerSlot); if(!ItemToTransfer || !Buyer->MoveItemToInventory(ItemToTransfer, true)) { Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); @@ -2648,7 +2648,7 @@ void Client::SellToBuyer(const EQApplicationPacket *app) { return; } - ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot); + EQEmu::ItemInstance* ItemToTransfer = m_inv.PopItem(SellerSlot); if(!ItemToTransfer) { Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); @@ -2927,7 +2927,7 @@ void Client::UpdateBuyLine(const EQApplicationPacket *app) { /*uint32 UnknownZ =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused uint32 ItemCount = VARSTRUCT_DECODE_TYPE(uint32, Buf); - const EQEmu::ItemBase *item = database.GetItem(ItemID); + const EQEmu::ItemData *item = database.GetItem(ItemID); if(!item) return; @@ -2991,7 +2991,7 @@ void Client::BuyerItemSearch(const EQApplicationPacket *app) { BuyerItemSearchResults_Struct* bisr = (BuyerItemSearchResults_Struct*)outapp->pBuffer; - const EQEmu::ItemBase* item = 0; + const EQEmu::ItemData* item = 0; int Count=0; diff --git a/zone/tribute.cpp b/zone/tribute.cpp index d40dfa6f2..537473e72 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -161,7 +161,7 @@ void Client::DoTributeUpdate() { uint32 item_id = tier.tribute_item_id; //summon the item for them - const ItemInst* inst = database.CreateItem(item_id, 1); + const EQEmu::ItemInstance* inst = database.CreateItem(item_id, 1); if(inst == nullptr) continue; @@ -239,7 +239,7 @@ void Client::SendTributeDetails(uint32 client_id, uint32 tribute_id) { //returns the number of points received from the tribute int32 Client::TributeItem(uint32 slot, uint32 quantity) { - const ItemInst*inst = m_inv[slot]; + const EQEmu::ItemInstance*inst = m_inv[slot]; if(inst == nullptr) return(0); diff --git a/zone/tune.cpp b/zone/tune.cpp index ea93a43f3..f8655d66a 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -587,7 +587,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) if (!other) return 0; - ItemInst* weapon; + EQEmu::ItemInstance* weapon; weapon = GetInv().GetItem(EQEmu::legacy::SlotPrimary); if(weapon != nullptr) { @@ -630,7 +630,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { - ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemBase*) nullptr); + ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); min_hit += (int) ucDamageBonus; max_hit += (int) ucDamageBonus; @@ -661,7 +661,7 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch EQEmu::skills::SkillType skillinuse = EQEmu::skills::SkillHandtoHand; if (attacker->IsClient()) {//Will check first equiped weapon for skill. Ie. remove wepaons to assess bow. - ItemInst* weapon; + EQEmu::ItemInstance* weapon; weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); if(weapon && weapon->IsWeapon()){ @@ -741,7 +741,7 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ EQEmu::skills::SkillType skillinuse = EQEmu::skills::SkillHandtoHand; if (attacker->IsClient()) {//Will check first equiped weapon for skill. Ie. remove wepaons to assess bow. - ItemInst* weapon; + EQEmu::ItemInstance* weapon; weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); if(weapon && weapon->IsWeapon()){ diff --git a/zone/zone.cpp b/zone/zone.cpp index 1edf1a268..9391b47bb 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -248,12 +248,12 @@ bool Zone::LoadZoneObjects() data.tilt_y = atof(row[18]); data.unknown084 = 0; - ItemInst *inst = nullptr; + EQEmu::ItemInstance *inst = nullptr; // FatherNitwit: this dosent seem to work... // tradeskill containers do not have an itemid of 0... at least what I am seeing if (itemid == 0) { // Generic tradeskill container - inst = new ItemInst(ItemInstWorldContainer); + inst = new EQEmu::ItemInstance(ItemInstWorldContainer); } else { // Groundspawn object inst = database.CreateItem(itemid); @@ -261,7 +261,7 @@ bool Zone::LoadZoneObjects() // Father Nitwit's fix... not perfect... if (inst == nullptr && type != OT_DROPPEDITEM) { - inst = new ItemInst(ItemInstWorldContainer); + inst = new EQEmu::ItemInstance(ItemInstWorldContainer); } // Load child objects if container @@ -294,7 +294,7 @@ bool Zone::LoadGroundSpawns() { uint32 gsnumber=0; for(gsindex=0;gsindex<50;gsindex++){ if(groundspawn.spawn[gsindex].item>0 && groundspawn.spawn[gsindex].itemGetItem()->IsClassCommon()) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) if (aug[i]) @@ -509,7 +509,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, ItemInst* container) } // Save child objects for a world container (i.e., forge, bag dropped to ground, etc) -void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const ItemInst* container) +void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const EQEmu::ItemInstance* container) { // Since state is not saved for each world container action, we'll just delete // all and save from scratch .. we may come back later to optimize @@ -522,7 +522,7 @@ void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const It // Save all 10 items, if they exist for (uint8 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; index++) { - ItemInst* inst = container->GetItem(index); + EQEmu::ItemInstance* inst = container->GetItem(index); if (!inst) continue; @@ -531,7 +531,7 @@ void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const It if (inst->IsType(EQEmu::item::ItemClassCommon)) { for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { - ItemInst *auginst=inst->GetAugment(i); + EQEmu::ItemInstance *auginst=inst->GetAugment(i); augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } } @@ -611,7 +611,7 @@ TraderCharges_Struct* ZoneDatabase::LoadTraderItemWithCharges(uint32 char_id) return loadti; } -ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { +EQEmu::ItemInstance* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { std::string query = StringFormat("SELECT * FROM trader WHERE char_id = %i AND serialnumber = %i " "ORDER BY slot_id LIMIT 80", CharID, SerialNumber); auto results = QueryDatabase(query); @@ -629,7 +629,7 @@ ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { int Charges = atoi(row[3]); int Cost = atoi(row[4]); - const EQEmu::ItemBase *item = database.GetItem(ItemID); + const EQEmu::ItemData *item = database.GetItem(ItemID); if(!item) { Log.Out(Logs::Detail, Logs::Trading, "Unable to create item\n"); @@ -640,7 +640,7 @@ ItemInst* ZoneDatabase::LoadSingleTraderItem(uint32 CharID, int SerialNumber) { if (item->NoDrop == 0) return nullptr; - ItemInst* inst = database.CreateItem(item); + EQEmu::ItemInstance* inst = database.CreateItem(item); if(!inst) { Log.Out(Logs::Detail, Logs::Trading, "Unable to create item instance\n"); fflush(stdout); @@ -684,7 +684,7 @@ void ZoneDatabase::UpdateTraderItemPrice(int CharID, uint32 ItemID, uint32 Charg Log.Out(Logs::Detail, Logs::Trading, "ZoneDatabase::UpdateTraderPrice(%i, %i, %i, %i)", CharID, ItemID, Charges, NewPrice); - const EQEmu::ItemBase *item = database.GetItem(ItemID); + const EQEmu::ItemData *item = database.GetItem(ItemID); if(!item) return; @@ -1197,7 +1197,7 @@ bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Str i = atoi(row[r]); /* Bandolier ID */ r++; si = atoi(row[r]); /* Bandolier Slot */ r++; - const EQEmu::ItemBase* item_data = database.GetItem(atoi(row[r])); + const EQEmu::ItemData* item_data = database.GetItem(atoi(row[r])); if (item_data) { pp->bandoliers[i].Items[si].ID = item_data->ID; r++; pp->bandoliers[i].Items[si].Icon = atoi(row[r]); r++; // Must use db value in case an Ornamentation is assigned @@ -1249,7 +1249,7 @@ bool ZoneDatabase::LoadCharacterPotions(uint32 character_id, PlayerProfile_Struc for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); - const EQEmu::ItemBase *item_data = database.GetItem(atoi(row[1])); + const EQEmu::ItemData *item_data = database.GetItem(atoi(row[1])); if (!item_data) continue; pp->potionbelt.Items[i].ID = item_data->ID; diff --git a/zone/zonedb.h b/zone/zonedb.h index 689f9a82f..1c96ee298 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -16,7 +16,6 @@ class NPC; class Petition; class Spawn2; class SpawnGroupList; -class ItemInst; struct CharacterEventLog_Struct; struct Door; struct ExtendedProfile_Struct; @@ -24,6 +23,12 @@ struct NPCType; struct PlayerCorpse_Struct; struct ZonePoint; struct npcDecayTimes_Struct; + +namespace EQEmu +{ + class ItemInstance; +} + template class LinkedList; //#include "doors.h" @@ -224,11 +229,11 @@ public: virtual ~ZoneDatabase(); /* Objects and World Containers */ - void LoadWorldContainer(uint32 parentid, ItemInst* container); - void SaveWorldContainer(uint32 zone_id, uint32 parent_id, const ItemInst* container); + void LoadWorldContainer(uint32 parentid, EQEmu::ItemInstance* container); + void SaveWorldContainer(uint32 zone_id, uint32 parent_id, const EQEmu::ItemInstance* container); void DeleteWorldContainer(uint32 parent_id,uint32 zone_id); - uint32 AddObject(uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst); - void UpdateObject(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst); + uint32 AddObject(uint32 type, uint32 icon, const Object_Struct& object, const EQEmu::ItemInstance* inst); + void UpdateObject(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const EQEmu::ItemInstance* inst); void DeleteObject(uint32 id); Ground_Spawns* LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs); @@ -239,7 +244,7 @@ public: void DeleteTraderItem(uint32 char_id); void DeleteTraderItem(uint32 char_id,uint16 slot_id); - ItemInst* LoadSingleTraderItem(uint32 char_id, int uniqueid); + EQEmu::ItemInstance* LoadSingleTraderItem(uint32 char_id, int uniqueid); Trader_Struct* LoadTraderItem(uint32 char_id); TraderCharges_Struct* LoadTraderItemWithCharges(uint32 char_id); @@ -427,7 +432,7 @@ public: void DeleteMerchantTemp(uint32 npcid, uint32 slot); /* Tradeskills */ - bool GetTradeRecipe(const ItemInst* container, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec); + bool GetTradeRecipe(const EQEmu::ItemInstance* container, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec); bool GetTradeRecipe(uint32 recipe_id, uint8 c_type, uint32 some_id, uint32 char_id, DBTradeskillRecipe_Struct *spec); uint32 GetZoneForage(uint32 ZoneID, uint8 skill); /* for foraging */ uint32 GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, uint8 &npc_chance); From bfd07b101082545bf253ee3c424e036c05077695 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 16 Oct 2016 21:36:39 -0400 Subject: [PATCH 398/693] Added class EQEmu::InventorySlot --- changelog.txt | 3 +- common/CMakeLists.txt | 4 +- common/database.cpp | 2 +- common/database_conversions.cpp | 8 +- common/emu_constants.h | 80 ++++++ common/emu_legacy.h | 103 ++------ common/eq_constants.h | 8 - common/eq_limits.cpp | 40 +-- common/eq_limits.h | 2 +- common/eq_packet_structs.h | 10 +- common/extprofile.h | 2 +- common/inventory_slot.cpp | 397 ++++++++++++++++++++++++++++++ common/inventory_slot.h | 133 ++++++++++ common/item_data.h | 6 +- common/item_instance.cpp | 306 +++++++++++------------ common/item_instance.h | 6 +- common/patches/rof.cpp | 105 ++++---- common/patches/rof2.cpp | 102 ++++---- common/patches/rof2_structs.h | 4 +- common/patches/rof_structs.h | 2 +- common/patches/sod.cpp | 30 +-- common/patches/sod_structs.h | 6 +- common/patches/sof.cpp | 26 +- common/patches/sof_structs.h | 6 +- common/patches/titanium.cpp | 14 +- common/patches/titanium_structs.h | 4 +- common/patches/uf.cpp | 30 +-- common/patches/uf_structs.h | 6 +- common/shareddb.cpp | 34 +-- common/textures.cpp | 79 ------ common/textures.h | 181 +++++++------- world/worlddb.cpp | 16 +- zone/attack.cpp | 106 ++++---- zone/beacon.h | 2 +- zone/bonuses.cpp | 34 +-- zone/bot.cpp | 230 ++++++++--------- zone/bot.h | 4 +- zone/bot_command.cpp | 72 +++--- zone/bot_database.cpp | 22 +- zone/client.cpp | 94 +++---- zone/client.h | 6 +- zone/client_mods.cpp | 16 +- zone/client_packet.cpp | 52 ++-- zone/client_process.cpp | 26 +- zone/command.cpp | 38 +-- zone/corpse.cpp | 42 ++-- zone/corpse.h | 2 +- zone/doors.cpp | 2 +- zone/encounter.h | 2 +- zone/entity.h | 2 +- zone/forage.cpp | 12 +- zone/inventory.cpp | 228 ++++++++--------- zone/loottables.cpp | 38 +-- zone/lua_general.cpp | 100 ++++---- zone/merc.cpp | 32 +-- zone/merc.h | 2 +- zone/mob.cpp | 14 +- zone/mob.h | 18 +- zone/mob_ai.cpp | 8 +- zone/npc.cpp | 26 +- zone/npc.h | 2 +- zone/object.cpp | 10 +- zone/special_attacks.cpp | 118 ++++----- zone/spell_effects.cpp | 20 +- zone/spells.cpp | 4 +- zone/tradeskills.cpp | 12 +- zone/trading.cpp | 32 +-- zone/tune.cpp | 42 ++-- zone/zonedb.cpp | 18 +- 69 files changed, 1852 insertions(+), 1391 deletions(-) create mode 100644 common/inventory_slot.cpp create mode 100644 common/inventory_slot.h diff --git a/changelog.txt b/changelog.txt index 50640ff55..5dfeca1d1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 10/16/2016 == -Uleat: Renamed struct EQEmu::ItemBase to EQEmu::ItemData and class ItemInst to EQEmu::ItemInstance. +Uleat: Renamed struct EQEmu::ItemBase to EQEmu::ItemData and class ItemInst to EQEmu::ItemInstance +Uleat: Added class EQEmu::InventorySlot. Re-attached pertinent inventory token references to EQDictionary == 10/15/2016 == Uleat: Changed filenames to facilitate future inventory naming conventions diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 2138c5c9e..fbfc9305e 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -35,7 +35,7 @@ SET(common_sources faction.cpp guild_base.cpp guilds.cpp -# inventory_slot.cpp + inventory_slot.cpp ipc_mutex.cpp item_data.cpp item_instance.cpp @@ -156,7 +156,7 @@ SET(common_headers global_define.h guild_base.h guilds.h -# inventory_slot.h + inventory_slot.h ipc_mutex.h item_data.h item_fieldlist.h diff --git a/common/database.cpp b/common/database.cpp index 93bbe7e0c..743bec9f2 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -709,7 +709,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven auto results = QueryDatabase(invquery); } - if (i == EQEmu::legacy::SlotCursor) { + if (i == EQEmu::inventory::slotCursor) { i = EQEmu::legacy::GENERAL_BAGS_BEGIN; continue; } diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index c282acc94..d5cdbdb25 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -186,7 +186,7 @@ namespace Convert { /*002*/ uint32 HP; /*006*/ uint32 Mana; /*010*/ Convert::SpellBuff_Struct Buffs[BUFF_COUNT]; - /*510*/ uint32 Items[EQEmu::textures::TextureCount]; + /*510*/ uint32 Items[EQEmu::textures::materialCount]; /*546*/ char Name[64]; /*610*/ }; @@ -227,9 +227,9 @@ namespace Convert { /*0304*/ uint8 ability_time_minutes; /*0305*/ uint8 ability_time_hours; //place holder /*0306*/ uint8 unknown0306[6]; // @bp Spacer/Flag? - /*0312*/ uint32 item_material[EQEmu::textures::TextureCount]; // Item texture/material of worn/held items + /*0312*/ uint32 item_material[EQEmu::textures::materialCount]; // Item texture/material of worn/held items /*0348*/ uint8 unknown0348[44]; - /*0392*/ Convert::Color_Struct item_tint[EQEmu::textures::TextureCount]; + /*0392*/ Convert::Color_Struct item_tint[EQEmu::textures::materialCount]; /*0428*/ Convert::AA_Array aa_array[MAX_PP_AA_ARRAY]; /*2348*/ float unknown2384; //seen ~128, ~47 /*2352*/ char servername[32]; // length probably not right @@ -1403,7 +1403,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){ if (rquery != ""){ results = QueryDatabase(rquery); } /* Run Material Color Convert */ first_entry = 0; rquery = ""; - for (i = 0; i < EQEmu::textures::TextureCount; i++){ + for (i = EQEmu::textures::textureBegin; i < EQEmu::textures::materialCount; i++){ if (pp->item_tint[i].color > 0){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); diff --git a/common/emu_constants.h b/common/emu_constants.h index bf8189acc..9e44976a8 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -35,6 +35,79 @@ namespace EQEmu //using namespace RoF2::invbag; //using namespace RoF2::invaug; + enum : int16 { typeInvalid = -1, slotInvalid = -1, containerInvalid = -1, socketInvalid = -1 }; // temporary + enum : int16 { typeBegin = 0, slotBegin = 0, containerBegin = 0, socketBegin = 0 }; // temporary + + enum PossessionsSlots : int16 { // temporary + slotCharm = 0, + slotEar1, + slotHead, + slotFace, + slotEar2, + slotNeck, // 5 + slotShoulders, + slotArms, + slotBack, + slotWrist1, + slotWrist2, // 10 + slotRange, + slotHands, + slotPrimary, + slotSecondary, + slotFinger1, // 15 + slotFinger2, + slotChest, + slotLegs, + slotFeet, + slotWaist, // 20 + slotPowerSource = 9999, + slotAmmo = 21, + slotGeneral1, + slotGeneral2, + slotGeneral3, + slotGeneral4, // 25 + slotGeneral5, + slotGeneral6, + slotGeneral7, + slotGeneral8, + slotCursor, // 30 + slotCount + }; + + enum InventoryTypes : int16 { // temporary + typePossessions = 0, + typeBank, + typeSharedBank, + typeTrade, + typeWorld, + typeLimbo, // 5 + typeTribute, + typeTrophyTribute, + typeGuildTribute, + typeMerchant, + typeDeleted, // 10 + typeCorpse, + typeBazaar, + typeInspect, + typeRealEstate, + typeViewMODPC, // 15 + typeViewMODBank, + typeViewMODSharedBank, + typeViewMODLimbo, + typeAltStorage, + typeArchived, // 20 + typeMail, + typeGuildTrophyTribute, + typeKrono, + typeOther, + typeCount + }; + + static int16 SlotCount(int16 type_index) { return 0; } // temporary + + const int16 ContainerCount = 10; // temporary + const int16 SocketCount = 6; // temporary + } /*inventory*/ namespace constants { @@ -44,6 +117,7 @@ namespace EQEmu const size_t SayLinkBodySize = RoF2::constants::SayLinkBodySize; } /*constants*/ + enum class CastingSlot : uint32 { Gem1 = 0, Gem2 = 1, @@ -68,3 +142,9 @@ namespace EQEmu } /*EQEmu*/ #endif /*COMMON_EMU_CONSTANTS_H*/ + +/* hack list to prevent circular references + + eq_limits.h:EQEmu::inventory::LookupEntry::InventoryTypeSize[n]; + +*/ diff --git a/common/emu_legacy.h b/common/emu_legacy.h index 98829eae4..b70d7143c 100644 --- a/common/emu_legacy.h +++ b/common/emu_legacy.h @@ -61,8 +61,6 @@ namespace EQEmu SLOT_GENERAL_6 = 27, SLOT_GENERAL_7 = 28, SLOT_GENERAL_8 = 29, - //SLOT_GENERAL_9 = not supported - //SLOT_GENERAL_10 = not supported SLOT_CURSOR = 30, SLOT_CURSOR_END = (int16)0xFFFE, // I hope no one is using this... SLOT_TRADESKILL = 1000, @@ -96,75 +94,8 @@ namespace EQEmu SLOT_WORLD_END = 4009 }; - enum InventoryTypes : int16 { - TypePossessions = 0, - TypeBank, - TypeSharedBank, - TypeTrade, - TypeWorld, - TypeLimbo, // 5 - TypeTribute, - TypeTrophyTribute, - TypeGuildTribute, - TypeMerchant, - TypeDeleted, // 10 - TypeCorpse, - TypeBazaar, - TypeInspect, - TypeRealEstate, - TypeViewMODPC, // 15 - TypeViewMODBank, - TypeViewMODSharedBank, - TypeViewMODLimbo, - TypeAltStorage, - TypeArchived, // 20 - TypeMail, - TypeGuildTrophyTribute, - TypeKrono, - TypeOther, - TypeCount - }; - - enum PossessionsSlots : int16 { - SlotCharm = 0, - SlotEar1, - SlotHead, - SlotFace, - SlotEar2, - SlotNeck, // 5 - SlotShoulders, - SlotArms, - SlotBack, - SlotWrist1, - SlotWrist2, // 10 - SlotRange, - SlotHands, - SlotPrimary, - SlotSecondary, - SlotFinger1, // 15 - SlotFinger2, - SlotChest, - SlotLegs, - SlotFeet, - SlotWaist, // 20 - SlotPowerSource = 9999, // temp - SlotAmmo = 21, // temp - SlotGeneral1, - SlotGeneral2, - SlotGeneral3, - SlotGeneral4, // 25 - SlotGeneral5, - SlotGeneral6, - SlotGeneral7, - SlotGeneral8, - //SlotGeneral9, - //SlotGeneral10, - SlotCursor, // 30 - SlotCount - }; - // these are currently hard-coded for existing inventory system..do not use in place of special client version handlers until ready - static const uint16 TYPE_POSSESSIONS_SIZE = SlotCount; + static const uint16 TYPE_POSSESSIONS_SIZE = 31; static const uint16 TYPE_BANK_SIZE = 24; static const uint16 TYPE_SHARED_BANK_SIZE = 2; static const uint16 TYPE_TRADE_SIZE = 8; @@ -175,14 +106,14 @@ namespace EQEmu static const uint16 TYPE_GUILD_TRIBUTE_SIZE = 0; static const uint16 TYPE_MERCHANT_SIZE = 0; static const uint16 TYPE_DELETED_SIZE = 0; - static const uint16 TYPE_CORPSE_SIZE = SlotCount; // no bitmask use..limits to size of client corpse window (see EQLimits::InventoryMapSize(MapCorpse, = slot_count) + return false; + + if (_container_index < inventory::containerInvalid || _container_index >= inventory::ContainerCount) + return false; + + if (_socket_index < inventory::socketInvalid || _socket_index >= inventory::SocketCount) + return false; + + return true; +} + +bool EQEmu::InventorySlot::IsDeleteSlot() const +{ + if (_typeless) + return (_slot_index == inventory::slotInvalid && _container_index == inventory::containerInvalid && _socket_index == inventory::socketInvalid); + else + return (_type_index == inventory::typeInvalid && _slot_index == inventory::slotInvalid && _container_index == inventory::containerInvalid && _socket_index == inventory::socketInvalid); +} + +bool EQEmu::InventorySlot::IsEquipmentIndex(int16 slot_index) +{ + /*if (slot_index < inventory::EquipmentBegin || slot_index > inventory::EquipmentEnd) + return false;*/ + if ((slot_index < legacy::EQUIPMENT_BEGIN || slot_index > legacy::EQUIPMENT_END) && slot_index != legacy::SLOT_POWER_SOURCE) + return false; + + return true; +} + +bool EQEmu::InventorySlot::IsGeneralIndex(int16 slot_index) +{ + /*if (slot_index < inventory::GeneralBegin || slot_index > inventory::GeneralEnd) + return false;*/ + if (slot_index < legacy::GENERAL_BEGIN || slot_index > legacy::GENERAL_END) + return false; + + return true; +} + +bool EQEmu::InventorySlot::IsCursorIndex(int16 slot_index) +{ + /*if (slot_index != inventory::slotCursor) + return false;*/ + if (slot_index != legacy::SLOT_CURSOR) + return false; + + return true; +} + +bool EQEmu::InventorySlot::IsWeaponIndex(int16 slot_index) +{ + /*if ((slot_index != inventory::slotRange) && (slot_index != inventory::slotPrimary) && (slot_index != inventory::slotSecondary)) + return false;*/ + if ((slot_index != legacy::SLOT_RANGE) && (slot_index != legacy::SLOT_PRIMARY) && (slot_index != legacy::SLOT_SECONDARY)) + return false; + + return true; +} + +bool EQEmu::InventorySlot::IsTextureIndex(int16 slot_index) +{ + switch (slot_index) { + case inventory::slotHead: + case inventory::slotChest: + case inventory::slotArms: + case inventory::slotWrist1: + case inventory::slotHands: + case inventory::slotLegs: + case inventory::slotFeet: + case inventory::slotPrimary: + case inventory::slotSecondary: + return true; + default: + return false; + } +} + +bool EQEmu::InventorySlot::IsTintableIndex(int16 slot_index) +{ + switch (slot_index) { + case inventory::slotHead: + case inventory::slotChest: + case inventory::slotArms: + case inventory::slotWrist1: + case inventory::slotHands: + case inventory::slotLegs: + case inventory::slotFeet: + return true; + default: + return false; + } +} + +bool EQEmu::InventorySlot::IsEquipmentSlot() const +{ + if (!_typeless && (_type_index != inventory::typePossessions)) + return false; + + if ((_container_index != inventory::containerInvalid) || (_socket_index != inventory::socketInvalid)) + return false; + + return IsEquipmentIndex(_slot_index); +} + +bool EQEmu::InventorySlot::IsGeneralSlot() const +{ + if (!_typeless && (_type_index != inventory::typePossessions)) + return false; + + if ((_container_index != inventory::containerInvalid) || (_socket_index != inventory::socketInvalid)) + return false; + + return IsGeneralIndex(_socket_index); +} + +bool EQEmu::InventorySlot::IsCursorSlot() const +{ + if (!_typeless && (_type_index != inventory::typePossessions)) + return false; + + if ((_container_index != inventory::containerInvalid) || (_socket_index != inventory::socketInvalid)) + return false; + + return IsCursorIndex(_slot_index); +} + +bool EQEmu::InventorySlot::IsWeaponSlot() const +{ + if (!_typeless && (_type_index != inventory::typePossessions)) + return false; + + if ((_container_index != inventory::containerInvalid) || (_socket_index != inventory::socketInvalid)) + return false; + + return IsWeaponIndex(_slot_index); +} + +bool EQEmu::InventorySlot::IsTextureSlot() const +{ + if (!_typeless && (_type_index != inventory::typePossessions)) + return false; + + if ((_container_index != inventory::containerInvalid) || (_socket_index != inventory::socketInvalid)) + return false; + + return IsTextureIndex(_slot_index); +} + +bool EQEmu::InventorySlot::IsTintableSlot() const +{ + if (!_typeless && (_type_index != inventory::typePossessions)) + return false; + + if ((_container_index != inventory::containerInvalid) || (_socket_index != inventory::socketInvalid)) + return false; + + return IsTintableIndex(_slot_index); +} + +bool EQEmu::InventorySlot::IsSlot() const +{ + if (!_typeless && (_type_index == inventory::typeInvalid)) + return false; + if (_slot_index == inventory::slotInvalid) + return false; + if (_container_index != inventory::containerInvalid) + return false; + if (_socket_index != inventory::socketInvalid) + return false; + + return true; +} + +bool EQEmu::InventorySlot::IsSlotSocket() const +{ + if (!_typeless && (_type_index == inventory::typeInvalid)) + return false; + if (_slot_index == inventory::slotInvalid) + return false; + if (_container_index != inventory::containerInvalid) + return false; + if (_socket_index == inventory::socketInvalid) + return false; + + return true; +} + +bool EQEmu::InventorySlot::IsContainer() const +{ + if (!_typeless && (_type_index == inventory::typeInvalid)) + return false; + if (_slot_index == inventory::slotInvalid) + return false; + if (_container_index == inventory::containerInvalid) + return false; + if (_socket_index != inventory::socketInvalid) + return false; + + return true; +} + +bool EQEmu::InventorySlot::IsContainerSocket() const +{ + if (!_typeless && (_type_index == inventory::typeInvalid)) + return false; + if (_slot_index == inventory::slotInvalid) + return false; + if (_container_index == inventory::containerInvalid) + return false; + if (_socket_index == inventory::socketInvalid) + return false; + + return true; +} + +EQEmu::InventorySlot EQEmu::InventorySlot::ToTopOwner() const +{ + return InventorySlot(_type_index, _slot_index); +} + +EQEmu::InventorySlot EQEmu::InventorySlot::ToOwner() const +{ + if (IsSlot() || IsSlotSocket() || IsContainer()) + return InventorySlot(_type_index, _slot_index); + + if (IsContainerSocket()) + return InventorySlot(_type_index, _slot_index, _container_index); + + return InventorySlot(); +} + +const std::string EQEmu::InventorySlot::ToString() const +{ + return StringFormat("(%i%s, %i, %i, %i)", _type_index, (_typeless ? " [typeless]" : ""), _slot_index, _container_index, _socket_index); +} + +const std::string EQEmu::InventorySlot::ToName() const +{ + return StringFormat("InventorySlot - _type_index: %i%s, _slot_index: %i, _container_index: %i, _socket_index: %i", _type_index, (_typeless ? " [typeless]" : ""), _slot_index, _container_index, _socket_index); +} + +void EQEmu::InventorySlot::SetInvalidSlot() +{ + _type_index = inventory::typeInvalid; + _slot_index = inventory::slotInvalid; + _container_index = inventory::containerInvalid; + _socket_index = inventory::socketInvalid; +} + +//bool EQEmu::InventorySlot::IsBonusIndex(int16 slot_index) +//{ +// if ((slot_index >= inventory::EquipmentBegin) && (slot_index <= inventory::EquipmentEnd) && (slot_index != inventory::slotAmmo)) +// return true; +// +// return false; +//} + +//bool EQEmu::InventorySlot::IsBonusSlot() const +//{ +// if ((_type_index != inventory::typePossessions) || (_container_index != inventory::containerInvalid) || (_socket_index != inventory::socketInvalid)) +// return false; +// +// return IsBonusIndex(_slot_index); +//} + +bool inventory_slot_typeless_lessthan(const EQEmu::InventorySlot& lhs, const EQEmu::InventorySlot& rhs) +{ + if (lhs.SlotIndex() < rhs.SlotIndex()) + return true; + + if ((lhs.SlotIndex() == rhs.SlotIndex()) && (lhs.ContainerIndex() < rhs.ContainerIndex())) + return true; + + if ((lhs.SlotIndex() == rhs.SlotIndex()) && (lhs.ContainerIndex() == rhs.ContainerIndex()) && (lhs.SocketIndex() < rhs.SocketIndex())) + return true; + + return false; +} + +bool EQEmu::InventorySlot::operator<(const InventorySlot& rhs) const +{ + if (Typeless() || rhs.Typeless()) + return inventory_slot_typeless_lessthan(*this, rhs); + + if (TypeIndex() < rhs.TypeIndex()) + return true; + + if ((TypeIndex() == rhs.TypeIndex()) && (SlotIndex() < rhs.SlotIndex())) + return true; + + if ((TypeIndex() == rhs.TypeIndex()) && (SlotIndex() == rhs.SlotIndex()) && (ContainerIndex() < rhs.ContainerIndex())) + return true; + + if ((TypeIndex() == rhs.TypeIndex()) && (SlotIndex() == rhs.SlotIndex()) && (ContainerIndex() == rhs.ContainerIndex()) && (SocketIndex() < rhs.SocketIndex())) + return true; + + return false; +} + +bool EQEmu::operator==(const InventorySlot& lhs, const InventorySlot& rhs) +{ + if (lhs.Typeless() || rhs.Typeless()) + return ((lhs.SlotIndex() == rhs.SlotIndex()) && (lhs.ContainerIndex() == rhs.ContainerIndex()) && (lhs.SocketIndex() == rhs.SocketIndex())); + + return ((lhs.TypeIndex() == rhs.TypeIndex()) && (lhs.SlotIndex() == rhs.SlotIndex()) && (lhs.ContainerIndex() == rhs.ContainerIndex()) && (lhs.SocketIndex() == rhs.SocketIndex())); +} diff --git a/common/inventory_slot.h b/common/inventory_slot.h new file mode 100644 index 000000000..695282e34 --- /dev/null +++ b/common/inventory_slot.h @@ -0,0 +1,133 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef COMMON_INVENTORY_SLOT +#define COMMON_INVENTORY_SLOT + +#include "emu_constants.h" + + +namespace EQEmu +{ + class InventorySlot; + + namespace inventory { + int8 ConvertEquipmentIndexToTextureIndex(int16 slot_index); + int8 ConvertEquipmentSlotToTextureIndex(const InventorySlot& inventory_slot); + int16 ConvertTextureIndexToEquipmentIndex(int8 texture_index); + } + + class InventorySlot { + public: + InventorySlot() : _type_index(inventory::typeInvalid), _slot_index(inventory::slotInvalid), _container_index(inventory::containerInvalid), _socket_index(inventory::socketInvalid), _typeless(false) { } + InventorySlot(int16 type_index) : _type_index(type_index), _slot_index(inventory::slotInvalid), _container_index(inventory::containerInvalid), _socket_index(inventory::socketInvalid), _typeless(false) { } + InventorySlot(int16 type_index, int16 parent_index) : _type_index(type_index), _slot_index(parent_index), _container_index(inventory::containerInvalid), _socket_index(inventory::socketInvalid), _typeless(false) { } + InventorySlot(int16 type_index, int16 parent_index, int16 bag_index) : _type_index(type_index), _slot_index(parent_index), _container_index(bag_index), _socket_index(inventory::socketInvalid), _typeless(false) { } + InventorySlot(int16 type_index, int16 parent_index, int16 bag_index, int16 aug_index) : _type_index(type_index), _slot_index(parent_index), _container_index(bag_index), _socket_index(aug_index), _typeless(false) { } + InventorySlot(const InventorySlot& r) : _type_index(r._type_index), _slot_index(r._slot_index), _container_index(r._container_index), _socket_index(r._socket_index), _typeless(r._typeless) { } + InventorySlot(int16 type_index, const InventorySlot& r) : _type_index(type_index), _slot_index(r._slot_index), _container_index(r._container_index), _socket_index(r._socket_index), _typeless(false) { } + + inline int16 TypeIndex() const { return _type_index; } + inline int16 SlotIndex() const { return _slot_index; } + inline int16 ContainerIndex() const { return _container_index; } + inline int16 SocketIndex() const { return _socket_index; } + + bool Typeless() const { return _typeless; } + + bool IsValidSlot() const; + bool IsDeleteSlot() const; + + static bool IsEquipmentIndex(int16 slot_index); + static bool IsGeneralIndex(int16 slot_index); + static bool IsCursorIndex(int16 slot_index); + static bool IsWeaponIndex(int16 slot_index); + static bool IsTextureIndex(int16 slot_index); + static bool IsTintableIndex(int16 slot_index); + + bool IsEquipmentSlot() const; + bool IsGeneralSlot() const; + bool IsCursorSlot() const; + bool IsWeaponSlot() const; + bool IsTextureSlot() const; + bool IsTintableSlot() const; + + bool IsSlot() const; + bool IsSlotSocket() const; + bool IsContainer() const; + bool IsContainerSocket() const; + + InventorySlot ToTopOwner() const; + InventorySlot ToOwner() const; + + const std::string ToString() const; + const std::string ToName() const; + + bool IsTypeIndex(int16 type_index) const { return (_type_index == type_index); } + bool IsSlotIndex(int16 slot_index) const { return (_slot_index == slot_index); } + bool IsContainerIndex(int16 container_index) const { return (_container_index == container_index); } + bool IsSocketIndex(int16 socket_index) const { return (_socket_index == socket_index); } + + void SetType(int16 type_index) { _type_index = type_index; } + void SetSlot(int16 slot_index) { _slot_index = slot_index; } + void SetContainer(int16 container_index) { _container_index = container_index; } + void SetSocket(int16 socket_index) { _socket_index = socket_index; } + + void SetInvalidSlot(); + + void SetTypeInvalid() { _type_index = inventory::typeInvalid; } + void SetSlotInvalid() { _slot_index = inventory::slotInvalid; } + void SetContainerInvalid() { _container_index = inventory::containerInvalid; } + void SetSocketInvalid() { _socket_index = inventory::socketInvalid; } + + void SetTypeBegin() { _type_index = inventory::typeBegin; } + void SetSlotBegin() { _slot_index = inventory::slotBegin; } + void SetContainerBegin() { _container_index = inventory::containerBegin; } + void SetSocketBegin() { _socket_index = inventory::socketBegin; } + + void IncrementType() { ++_type_index; } + void IncrementSlot() { ++_slot_index; } + void IncrementContainer() { ++_container_index; } + void IncrementSocket() { ++_socket_index; } + + void SetTypeless() { _typeless = true; } + void ClearTypeless() { _typeless = false; } + + // these two methods should really check for all bonus-valid slots..currently checks for equipment only (rework needed) + //static bool IsBonusIndex(int16 slot_index); + //bool IsBonusSlot() const; + + bool operator<(const InventorySlot& rhs) const; + + private: + int16 _type_index; + //int16 _unknown2; // not implemented + int16 _slot_index; + int16 _container_index; + int16 _socket_index; + //int16 _unknown1; // not implemented + + bool _typeless; + }; + + bool operator==(const InventorySlot& lhs, const InventorySlot& rhs); + bool operator!=(const InventorySlot& lhs, const InventorySlot& rhs) { return (!(lhs == rhs)); } + +} /*EQEmu*/ + +#endif /*COMMON_INVENTORY_SLOT*/ diff --git a/common/item_data.h b/common/item_data.h index ce3eccefa..14aa368c2 100644 --- a/common/item_data.h +++ b/common/item_data.h @@ -464,9 +464,9 @@ namespace EQEmu int32 FactionAmt4; // Faction Amt 4 char CharmFile[32]; // ? uint32 AugType; - uint8 AugSlotType[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Type - uint8 AugSlotVisible[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Visible - uint8 AugSlotUnk2[EQEmu::legacy::ITEM_COMMON_SIZE]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related + uint8 AugSlotType[inventory::SocketCount]; // RoF: Augment Slot 1-6 Type + uint8 AugSlotVisible[inventory::SocketCount]; // RoF: Augment Slot 1-6 Visible + uint8 AugSlotUnk2[inventory::SocketCount]; // RoF: Augment Slot 1-6 Unknown Most likely Powersource related uint32 LDoNTheme; uint32 LDoNPrice; uint32 LDoNSold; diff --git a/common/item_instance.cpp b/common/item_instance.cpp index c8beddd3c..fbe2af543 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -158,7 +158,7 @@ EQEmu::ItemInstance* Inventory::GetItem(int16 slot_id) const EQEmu::ItemInstance* result = nullptr; // Cursor - if (slot_id == EQEmu::legacy::SlotCursor) { + if (slot_id == EQEmu::inventory::slotCursor) { // Cursor slot result = m_cursor.peek_front(); } @@ -180,7 +180,7 @@ EQEmu::ItemInstance* Inventory::GetItem(int16 slot_id) const result = _GetItem(m_inv, slot_id); } else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || - (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) || (slot_id == EQEmu::legacy::SlotPowerSource)) { + (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { // Equippable slots (on body) result = _GetItem(m_worn, slot_id); } @@ -250,7 +250,7 @@ int16 Inventory::PutItem(int16 slot_id, const EQEmu::ItemInstance& inst) int16 Inventory::PushCursor(const EQEmu::ItemInstance& inst) { m_cursor.push(inst.Clone()); - return EQEmu::legacy::SlotCursor; + return EQEmu::inventory::slotCursor; } EQEmu::ItemInstance* Inventory::GetCursorItem() @@ -316,7 +316,7 @@ bool Inventory::CheckNoDrop(int16 slot_id) { if (!inst) return false; if (!inst->GetItem()->NoDrop) return true; if (inst->GetItem()->ItemClass == 1) { - for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { + for (uint8 i = EQEmu::inventory::containerBegin; i < EQEmu::inventory::ContainerCount; i++) { EQEmu::ItemInstance* bagitem = GetItem(Inventory::CalcSlotId(slot_id, i)); if (bagitem && !bagitem->GetItem()->NoDrop) return true; @@ -331,10 +331,10 @@ EQEmu::ItemInstance* Inventory::PopItem(int16 slot_id) { EQEmu::ItemInstance* p = nullptr; - if (slot_id == EQEmu::legacy::SlotCursor) { + if (slot_id == EQEmu::inventory::slotCursor) { p = m_cursor.pop(); } - else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::legacy::SlotPowerSource)) { + else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { p = m_worn[slot_id]; m_worn.erase(slot_id); } @@ -390,9 +390,9 @@ bool Inventory::HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity } if (InvItem && InvItem->IsClassBag()) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); + int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); uint8 BagSize = InvItem->GetItem()->BagSlots; - for (uint8 BagSlot = SUB_INDEX_BEGIN; BagSlot < BagSize; BagSlot++) { + for (uint8 BagSlot = EQEmu::inventory::containerBegin; BagSlot < BagSize; BagSlot++) { InvItem = GetItem(BaseSlotID + BagSlot); @@ -434,11 +434,11 @@ bool Inventory::HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity } else if (InvItem->IsClassBag() && CanItemFitInContainer(ItemToTry, InvItem->GetItem())) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); + int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); uint8 BagSize = InvItem->GetItem()->BagSlots; - for (uint8 BagSlot = SUB_INDEX_BEGIN; BagSlotGetItem()->BagSlots; uint8 j; - for (j = SUB_INDEX_BEGIN; jIsClassBag()) { // if item-specific containers already have bad items, we won't fix it here... - for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { const EQEmu::ItemInstance* sub_inst = main_inst->GetItem(free_bag_slot); if (!sub_inst) @@ -717,7 +717,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const EQEmu::ItemInstance* inst) { if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeQuiver) || !main_inst->IsClassBag()) continue; - for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -732,7 +732,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const EQEmu::ItemInstance* inst) { if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeBandolier) || !main_inst->IsClassBag()) continue; - for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -754,7 +754,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const EQEmu::ItemInstance* inst) { if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeBandolier) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeQuiver)) continue; - for (uint8 free_bag_slot = SUB_INDEX_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++free_bag_slot) { + for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return Inventory::CalcSlotId(free_slot, free_bag_slot); } @@ -762,7 +762,7 @@ int16 Inventory::FindFreeSlotForTradeItem(const EQEmu::ItemInstance* inst) { } //return INVALID_INDEX; // everything else pushes to the cursor - return EQEmu::legacy::SlotCursor; + return EQEmu::inventory::slotCursor; } // Opposite of below: Get parent bag slot_id from a slot inside of bag @@ -775,19 +775,19 @@ int16 Inventory::CalcSlotId(int16 slot_id) { //else if (slot_id >= 3100 && slot_id <= 3179) should be {3031..3110}..where did this range come from!!? (verified db save range) if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { - parent_slot_id = EQEmu::legacy::GENERAL_BEGIN + (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) / EQEmu::legacy::ITEM_CONTAINER_SIZE; + parent_slot_id = EQEmu::legacy::GENERAL_BEGIN + (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; } else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { - parent_slot_id = EQEmu::legacy::SlotCursor; + parent_slot_id = EQEmu::inventory::slotCursor; } else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { - parent_slot_id = EQEmu::legacy::BANK_BEGIN + (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) / EQEmu::legacy::ITEM_CONTAINER_SIZE; + parent_slot_id = EQEmu::legacy::BANK_BEGIN + (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; } else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { - parent_slot_id = EQEmu::legacy::SHARED_BANK_BEGIN + (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) / EQEmu::legacy::ITEM_CONTAINER_SIZE; + parent_slot_id = EQEmu::legacy::SHARED_BANK_BEGIN + (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; } else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { - parent_slot_id = EQEmu::legacy::TRADE_BEGIN + (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) / EQEmu::legacy::ITEM_CONTAINER_SIZE; + parent_slot_id = EQEmu::legacy::TRADE_BEGIN + (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; } return parent_slot_id; @@ -800,20 +800,20 @@ int16 Inventory::CalcSlotId(int16 bagslot_id, uint8 bagidx) { int16 slot_id = INVALID_INDEX; - if (bagslot_id == EQEmu::legacy::SlotCursor || bagslot_id == 8000) { + if (bagslot_id == EQEmu::inventory::slotCursor || bagslot_id == 8000) { slot_id = EQEmu::legacy::CURSOR_BAG_BEGIN + bagidx; } else if (bagslot_id >= EQEmu::legacy::GENERAL_BEGIN && bagslot_id <= EQEmu::legacy::GENERAL_END) { - slot_id = EQEmu::legacy::GENERAL_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::GENERAL_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE + bagidx; + slot_id = EQEmu::legacy::GENERAL_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::GENERAL_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; } else if (bagslot_id >= EQEmu::legacy::BANK_BEGIN && bagslot_id <= EQEmu::legacy::BANK_END) { - slot_id = EQEmu::legacy::BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE + bagidx; + slot_id = EQEmu::legacy::BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::BANK_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; } else if (bagslot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && bagslot_id <= EQEmu::legacy::SHARED_BANK_END) { - slot_id = EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE + bagidx; + slot_id = EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; } else if (bagslot_id >= EQEmu::legacy::TRADE_BEGIN && bagslot_id <= EQEmu::legacy::TRADE_END) { - slot_id = EQEmu::legacy::TRADE_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::TRADE_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE + bagidx; + slot_id = EQEmu::legacy::TRADE_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::TRADE_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; } return slot_id; @@ -827,19 +827,19 @@ uint8 Inventory::CalcBagIdx(int16 slot_id) { // index = (slot_id - EmuConstants::BANK_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { - index = (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) % EQEmu::legacy::ITEM_CONTAINER_SIZE; + index = (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; } else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { index = (slot_id - EQEmu::legacy::CURSOR_BAG_BEGIN); // % EQEmu::legacy::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots } else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { - index = (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) % EQEmu::legacy::ITEM_CONTAINER_SIZE; + index = (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; } else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { - index = (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) % EQEmu::legacy::ITEM_CONTAINER_SIZE; + index = (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; } else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { - index = (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) % EQEmu::legacy::ITEM_CONTAINER_SIZE; + index = (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; } else if (slot_id >= EQEmu::legacy::WORLD_BEGIN && slot_id <= EQEmu::legacy::WORLD_END) { index = (slot_id - EQEmu::legacy::WORLD_BEGIN); // % EQEmu::legacy::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots @@ -852,24 +852,24 @@ int16 Inventory::CalcSlotFromMaterial(uint8 material) { switch (material) { - case EQEmu::textures::TextureHead: - return EQEmu::legacy::SlotHead; - case EQEmu::textures::TextureChest: - return EQEmu::legacy::SlotChest; - case EQEmu::textures::TextureArms: - return EQEmu::legacy::SlotArms; - case EQEmu::textures::TextureWrist: - return EQEmu::legacy::SlotWrist1; // there's 2 bracers, only one bracer material - case EQEmu::textures::TextureHands: - return EQEmu::legacy::SlotHands; - case EQEmu::textures::TextureLegs: - return EQEmu::legacy::SlotLegs; - case EQEmu::textures::TextureFeet: - return EQEmu::legacy::SlotFeet; - case EQEmu::textures::TexturePrimary: - return EQEmu::legacy::SlotPrimary; - case EQEmu::textures::TextureSecondary: - return EQEmu::legacy::SlotSecondary; + case EQEmu::textures::armorHead: + return EQEmu::inventory::slotHead; + case EQEmu::textures::armorChest: + return EQEmu::inventory::slotChest; + case EQEmu::textures::armorArms: + return EQEmu::inventory::slotArms; + case EQEmu::textures::armorWrist: + return EQEmu::inventory::slotWrist1; // there's 2 bracers, only one bracer material + case EQEmu::textures::armorHands: + return EQEmu::inventory::slotHands; + case EQEmu::textures::armorLegs: + return EQEmu::inventory::slotLegs; + case EQEmu::textures::armorFeet: + return EQEmu::inventory::slotFeet; + case EQEmu::textures::weaponPrimary: + return EQEmu::inventory::slotPrimary; + case EQEmu::textures::weaponSecondary: + return EQEmu::inventory::slotSecondary; default: return INVALID_INDEX; } @@ -879,27 +879,27 @@ uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) { switch (equipslot) { - case EQEmu::legacy::SlotHead: - return EQEmu::textures::TextureHead; - case EQEmu::legacy::SlotChest: - return EQEmu::textures::TextureChest; - case EQEmu::legacy::SlotArms: - return EQEmu::textures::TextureArms; - case EQEmu::legacy::SlotWrist1: + case EQEmu::inventory::slotHead: + return EQEmu::textures::armorHead; + case EQEmu::inventory::slotChest: + return EQEmu::textures::armorChest; + case EQEmu::inventory::slotArms: + return EQEmu::textures::armorArms; + case EQEmu::inventory::slotWrist1: //case SLOT_BRACER02: // non-live behavior - return EQEmu::textures::TextureWrist; - case EQEmu::legacy::SlotHands: - return EQEmu::textures::TextureHands; - case EQEmu::legacy::SlotLegs: - return EQEmu::textures::TextureLegs; - case EQEmu::legacy::SlotFeet: - return EQEmu::textures::TextureFeet; - case EQEmu::legacy::SlotPrimary: - return EQEmu::textures::TexturePrimary; - case EQEmu::legacy::SlotSecondary: - return EQEmu::textures::TextureSecondary; + return EQEmu::textures::armorWrist; + case EQEmu::inventory::slotHands: + return EQEmu::textures::armorHands; + case EQEmu::inventory::slotLegs: + return EQEmu::textures::armorLegs; + case EQEmu::inventory::slotFeet: + return EQEmu::textures::armorFeet; + case EQEmu::inventory::slotPrimary: + return EQEmu::textures::weaponPrimary; + case EQEmu::inventory::slotSecondary: + return EQEmu::textures::weaponSecondary; default: - return EQEmu::textures::TextureInvalid; + return EQEmu::textures::materialInvalid; } } @@ -923,7 +923,7 @@ bool Inventory::CanItemFitInContainer(const EQEmu::ItemData *ItemToTry, const EQ bool Inventory::SupportsClickCasting(int16 slot_id) { // there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range - if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::legacy::SlotPowerSource) + if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::inventory::slotPowerSource) { return true; } @@ -938,7 +938,7 @@ bool Inventory::SupportsClickCasting(int16 slot_id) bool Inventory::SupportsPotionBeltCasting(int16 slot_id) { - if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::legacy::SlotPowerSource || (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END)) + if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::inventory::slotPowerSource || (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END)) return true; return false; @@ -947,7 +947,7 @@ bool Inventory::SupportsPotionBeltCasting(int16 slot_id) // Test whether a given slot can support a container item bool Inventory::SupportsContainers(int16 slot_id) { - if ((slot_id == EQEmu::legacy::SlotCursor) || + if ((slot_id == EQEmu::inventory::slotCursor) || (slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END) || (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) || (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) || @@ -989,7 +989,7 @@ int Inventory::GetSlotByItemInst(EQEmu::ItemInstance *inst) { } if (m_cursor.peek_front() == inst) { - return EQEmu::legacy::SlotCursor; + return EQEmu::inventory::slotCursor; } return INVALID_INDEX; @@ -1000,8 +1000,8 @@ uint8 Inventory::FindBrightestLightType() uint8 brightest_light_type = 0; for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { - if ((iter->first < EQEmu::legacy::EQUIPMENT_BEGIN || iter->first > EQEmu::legacy::EQUIPMENT_END) && iter->first != EQEmu::legacy::SlotPowerSource) { continue; } - if (iter->first == EQEmu::legacy::SlotAmmo) { continue; } + if ((iter->first < EQEmu::legacy::EQUIPMENT_BEGIN || iter->first > EQEmu::legacy::EQUIPMENT_END) && iter->first != EQEmu::inventory::slotPowerSource) { continue; } + if (iter->first == EQEmu::inventory::slotAmmo) { continue; } auto inst = iter->second; if (inst == nullptr) { continue; } @@ -1145,13 +1145,13 @@ int16 Inventory::_PutItem(int16 slot_id, EQEmu::ItemInstance* inst) int16 result = INVALID_INDEX; int16 parentSlot = INVALID_INDEX; - if (slot_id == EQEmu::legacy::SlotCursor) { + if (slot_id == EQEmu::inventory::slotCursor) { // Replace current item on cursor, if exists m_cursor.pop(); // no memory delete, clients of this function know what they are doing m_cursor.push_front(inst); result = slot_id; } - else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::legacy::SlotPowerSource)) { + else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { m_worn[slot_id] = inst; result = slot_id; } @@ -1209,7 +1209,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 return iter->first; } - for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) return EQEmu::legacy::SLOT_AUGMENT; } @@ -1226,7 +1226,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 return Inventory::CalcSlotId(iter->first, bag_iter->first); } - for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) return EQEmu::legacy::SLOT_AUGMENT; } @@ -1254,10 +1254,10 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) if (inst->GetID() == item_id) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); if (quantity_found >= quantity) - return EQEmu::legacy::SlotCursor; + return EQEmu::inventory::slotCursor; } - for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) return EQEmu::legacy::SLOT_AUGMENT; } @@ -1271,10 +1271,10 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) if (bag_inst->GetID() == item_id) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(EQEmu::legacy::SlotCursor, bag_iter->first); + return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); } - for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) return EQEmu::legacy::SLOT_AUGMENT; } @@ -1331,7 +1331,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) if (inst->IsClassCommon() && inst->GetItem()->ItemType == use) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); if (quantity_found >= quantity) - return EQEmu::legacy::SlotCursor; + return EQEmu::inventory::slotCursor; } if (!inst->IsClassBag()) { continue; } @@ -1343,7 +1343,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) if (bag_inst->IsClassCommon() && bag_inst->GetItem()->ItemType == use) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(EQEmu::legacy::SlotCursor, bag_iter->first); + return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); } } @@ -1363,7 +1363,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& buck if (inst->GetItem()->LoreGroup == loregroup) return iter->first; - for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { auto aug_inst = inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1380,7 +1380,7 @@ int16 Inventory::_HasItemByLoreGroup(std::map& buck if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) return Inventory::CalcSlotId(iter->first, bag_iter->first); - for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { auto aug_inst = bag_inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1401,9 +1401,9 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (inst == nullptr) { continue; } if (inst->GetItem()->LoreGroup == loregroup) - return EQEmu::legacy::SlotCursor; + return EQEmu::inventory::slotCursor; - for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { auto aug_inst = inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1418,9 +1418,9 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (bag_inst == nullptr) { continue; } if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) - return Inventory::CalcSlotId(EQEmu::legacy::SlotCursor, bag_iter->first); + return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); - for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { auto aug_inst = bag_inst->GetAugment(index); if (aug_inst == nullptr) { continue; } @@ -1657,7 +1657,7 @@ bool EQEmu::ItemInstance::IsEquipable(int16 slot_id) const // another "shouldn't do" fix..will be fixed in future updates (requires code and database work) int16 use_slot = INVALID_INDEX; - if (slot_id == EQEmu::legacy::SlotPowerSource) { use_slot = EQEmu::legacy::SlotGeneral1; } + if (slot_id == EQEmu::inventory::slotPowerSource) { use_slot = EQEmu::inventory::slotGeneral1; } if ((uint16)slot_id <= EQEmu::legacy::EQUIPMENT_END) { use_slot = slot_id; } if (use_slot != INVALID_INDEX) { @@ -1673,8 +1673,8 @@ bool EQEmu::ItemInstance::IsAugmentable() const if (!m_item) return false; - for (int index = 0; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { - if (m_item->AugSlotType[index] != NO_ITEM) + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + if (m_item->AugSlotType[index] != 0) return true; } @@ -1688,7 +1688,7 @@ bool EQEmu::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const { return false; int index = EQEmu::legacy::EQUIPMENT_BEGIN; - for (; index <= EQEmu::legacy::SlotGeneral1; ++index) { // MainGeneral1 should be EQEmu::legacy::EQUIPMENT_END + for (; index <= EQEmu::inventory::slotGeneral1; ++index) { // MainGeneral1 should be EQEmu::legacy::EQUIPMENT_END if (m_item->Slots & (1 << index)) { if (aug_wear_slots & (1 << index)) break; @@ -1703,14 +1703,14 @@ int8 EQEmu::ItemInstance::AvailableAugmentSlot(int32 augtype) const if (!m_item || !m_item->IsClassCommon()) return INVALID_INDEX; - int index = AUG_INDEX_BEGIN; - for (; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { + int index = EQEmu::inventory::socketBegin; + for (; index < EQEmu::inventory::SocketCount; ++index) { if (GetItem(index)) { continue; } if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype))) break; } - return (index < EQEmu::legacy::ITEM_COMMON_SIZE) ? index : INVALID_INDEX; + return (index < EQEmu::inventory::SocketCount) ? index : INVALID_INDEX; } bool EQEmu::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const @@ -1741,7 +1741,7 @@ uint32 EQEmu::ItemInstance::GetItemID(uint8 slot) const if (item) return item->GetID(); - return NO_ITEM; + return 0; } void EQEmu::ItemInstance::PutItem(uint8 index, const ItemInstance& inst) @@ -1853,7 +1853,7 @@ uint8 EQEmu::ItemInstance::FirstOpenSlot() const return INVALID_INDEX; uint8 slots = m_item->BagSlots, i; - for (i = SUB_INDEX_BEGIN; i < slots; i++) { + for (i = EQEmu::inventory::containerBegin; i < slots; i++) { if (!GetItem(i)) break; } @@ -1870,7 +1870,7 @@ uint8 EQEmu::ItemInstance::GetTotalItemCount() const if (m_item && !m_item->IsClassBag()) { return item_count; } - for (int index = SUB_INDEX_BEGIN; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } } + for (int index = EQEmu::inventory::containerBegin; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } } return item_count; } @@ -1880,7 +1880,7 @@ bool EQEmu::ItemInstance::IsNoneEmptyContainer() if (!m_item || !m_item->IsClassBag()) return false; - for (int index = SUB_INDEX_BEGIN; index < m_item->BagSlots; ++index) { + for (int index = EQEmu::inventory::containerBegin; index < m_item->BagSlots; ++index) { if (GetItem(index)) return true; } @@ -1902,7 +1902,7 @@ EQEmu::ItemInstance* EQEmu::ItemInstance::GetOrnamentationAug(int32 ornamentatio if (!m_item || !m_item->IsClassCommon()) { return nullptr; } if (ornamentationAugtype == 0) { return nullptr; } - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype) { @@ -2020,7 +2020,7 @@ bool EQEmu::ItemInstance::CanTransform(const EQEmu::ItemData *ItemToTry, const E uint32 EQEmu::ItemInstance::GetAugmentItemID(uint8 slot) const { if (!m_item || !m_item->IsClassCommon()) - return NO_ITEM; + return 0; return GetItemID(slot); } @@ -2036,7 +2036,7 @@ void EQEmu::ItemInstance::PutAugment(uint8 slot, const ItemInstance& augment) void EQEmu::ItemInstance::PutAugment(SharedDatabase *db, uint8 slot, uint32 item_id) { - if (item_id == NO_ITEM) { return; } + if (item_id == 0) { return; } if (db == nullptr) { return; /* TODO: add log message for nullptr */ } const ItemInstance* aug = db->CreateItem(item_id); @@ -2069,7 +2069,7 @@ bool EQEmu::ItemInstance::IsAugmented() if (!m_item || !m_item->IsClassCommon()) return false; - for (int index = AUG_INDEX_BEGIN; index < EQEmu::legacy::ITEM_COMMON_SIZE; ++index) { + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { if (GetAugmentItemID(index)) return true; } @@ -2197,8 +2197,8 @@ bool EQEmu::ItemInstance::IsSlotAllowed(int16 slot_id) const { if (!m_item) { return false; } else if (Inventory::SupportsContainers(slot_id)) { return true; } else if (m_item->Slots & (1 << slot_id)) { return true; } - else if (slot_id == EQEmu::legacy::SlotPowerSource && (m_item->Slots & (1 << 22))) { return true; } // got lazy... - else if (slot_id != EQEmu::legacy::SlotPowerSource && slot_id > EQEmu::legacy::EQUIPMENT_END) { return true; } + else if (slot_id == EQEmu::inventory::slotPowerSource && (m_item->Slots & (1 << 22))) { return true; } // got lazy... + else if (slot_id != EQEmu::inventory::slotPowerSource && slot_id > EQEmu::legacy::EQUIPMENT_END) { return true; } else { return false; } } @@ -2350,7 +2350,7 @@ int EQEmu::ItemInstance::GetItemArmorClass(bool augments) const if (item) { ac = item->AC; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) ac += GetAugment(i)->GetItemArmorClass(); } @@ -2392,7 +2392,7 @@ int EQEmu::ItemInstance::GetItemElementalDamage(int &magic, int &fire, int &cold } if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) GetAugment(i)->GetItemElementalDamage(magic, fire, cold, poison, disease, chromatic, prismatic, physical, corruption); } @@ -2409,7 +2409,7 @@ int EQEmu::ItemInstance::GetItemElementalFlag(bool augments) const return flag; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) { if (GetAugment(i)) flag = GetAugment(i)->GetItemElementalFlag(); if (flag) @@ -2430,7 +2430,7 @@ int EQEmu::ItemInstance::GetItemElementalDamage(bool augments) const return damage; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) { if (GetAugment(i)) damage = GetAugment(i)->GetItemElementalDamage(); if (damage) @@ -2449,7 +2449,7 @@ int EQEmu::ItemInstance::GetItemRecommendedLevel(bool augments) const level = item->RecLevel; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) { int temp = 0; if (GetAugment(i)) { temp = GetAugment(i)->GetItemRecommendedLevel(); @@ -2471,7 +2471,7 @@ int EQEmu::ItemInstance::GetItemRequiredLevel(bool augments) const level = item->ReqLevel; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) { int temp = 0; if (GetAugment(i)) { temp = GetAugment(i)->GetItemRequiredLevel(); @@ -2493,7 +2493,7 @@ int EQEmu::ItemInstance::GetItemWeaponDamage(bool augments) const damage = item->Damage; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemWeaponDamage(); } @@ -2509,7 +2509,7 @@ int EQEmu::ItemInstance::GetItemBackstabDamage(bool augments) const damage = item->BackstabDmg; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBackstabDamage(); } @@ -2527,7 +2527,7 @@ int EQEmu::ItemInstance::GetItemBaneDamageBody(bool augments) const return body; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) { body = GetAugment(i)->GetItemBaneDamageBody(); if (body) @@ -2548,7 +2548,7 @@ int EQEmu::ItemInstance::GetItemBaneDamageRace(bool augments) const return race; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) { race = GetAugment(i)->GetItemBaneDamageRace(); if (race) @@ -2568,7 +2568,7 @@ int EQEmu::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) damage += item->BaneDmgAmt; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBaneDamageBody(against); } @@ -2585,7 +2585,7 @@ int EQEmu::ItemInstance::GetItemBaneDamageRace(uint16 against, bool augments) co damage += item->BaneDmgRaceAmt; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBaneDamageRace(against); } @@ -2601,7 +2601,7 @@ int EQEmu::ItemInstance::GetItemMagical(bool augments) const return 1; if (augments) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i) && GetAugment(i)->GetItemMagical()) return 1; } @@ -2616,7 +2616,7 @@ int EQEmu::ItemInstance::GetItemHP(bool augments) const if (item) { hp = item->HP; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) hp += GetAugment(i)->GetItemHP(); } @@ -2630,7 +2630,7 @@ int EQEmu::ItemInstance::GetItemMana(bool augments) const if (item) { mana = item->Mana; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) mana += GetAugment(i)->GetItemMana(); } @@ -2644,7 +2644,7 @@ int EQEmu::ItemInstance::GetItemEndur(bool augments) const if (item) { endur = item->Endur; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) endur += GetAugment(i)->GetItemEndur(); } @@ -2658,7 +2658,7 @@ int EQEmu::ItemInstance::GetItemAttack(bool augments) const if (item) { atk = item->Attack; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) atk += GetAugment(i)->GetItemAttack(); } @@ -2672,7 +2672,7 @@ int EQEmu::ItemInstance::GetItemStr(bool augments) const if (item) { str = item->AStr; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) str += GetAugment(i)->GetItemStr(); } @@ -2686,7 +2686,7 @@ int EQEmu::ItemInstance::GetItemSta(bool augments) const if (item) { sta = item->ASta; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) sta += GetAugment(i)->GetItemSta(); } @@ -2700,7 +2700,7 @@ int EQEmu::ItemInstance::GetItemDex(bool augments) const if (item) { total = item->ADex; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemDex(); } @@ -2714,7 +2714,7 @@ int EQEmu::ItemInstance::GetItemAgi(bool augments) const if (item) { total = item->AAgi; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemAgi(); } @@ -2728,7 +2728,7 @@ int EQEmu::ItemInstance::GetItemInt(bool augments) const if (item) { total = item->AInt; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemInt(); } @@ -2742,7 +2742,7 @@ int EQEmu::ItemInstance::GetItemWis(bool augments) const if (item) { total = item->AWis; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemWis(); } @@ -2756,7 +2756,7 @@ int EQEmu::ItemInstance::GetItemCha(bool augments) const if (item) { total = item->ACha; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCha(); } @@ -2770,7 +2770,7 @@ int EQEmu::ItemInstance::GetItemMR(bool augments) const if (item) { total = item->MR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemMR(); } @@ -2784,7 +2784,7 @@ int EQEmu::ItemInstance::GetItemFR(bool augments) const if (item) { total = item->FR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemFR(); } @@ -2798,7 +2798,7 @@ int EQEmu::ItemInstance::GetItemCR(bool augments) const if (item) { total = item->CR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCR(); } @@ -2812,7 +2812,7 @@ int EQEmu::ItemInstance::GetItemPR(bool augments) const if (item) { total = item->PR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemPR(); } @@ -2826,7 +2826,7 @@ int EQEmu::ItemInstance::GetItemDR(bool augments) const if (item) { total = item->DR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemDR(); } @@ -2840,7 +2840,7 @@ int EQEmu::ItemInstance::GetItemCorrup(bool augments) const if (item) { total = item->SVCorruption; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCorrup(); } @@ -2854,7 +2854,7 @@ int EQEmu::ItemInstance::GetItemHeroicStr(bool augments) const if (item) { total = item->HeroicStr; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicStr(); } @@ -2868,7 +2868,7 @@ int EQEmu::ItemInstance::GetItemHeroicSta(bool augments) const if (item) { total = item->HeroicSta; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicSta(); } @@ -2882,7 +2882,7 @@ int EQEmu::ItemInstance::GetItemHeroicDex(bool augments) const if (item) { total = item->HeroicDex; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicDex(); } @@ -2896,7 +2896,7 @@ int EQEmu::ItemInstance::GetItemHeroicAgi(bool augments) const if (item) { total = item->HeroicAgi; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicAgi(); } @@ -2910,7 +2910,7 @@ int EQEmu::ItemInstance::GetItemHeroicInt(bool augments) const if (item) { total = item->HeroicInt; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicInt(); } @@ -2924,7 +2924,7 @@ int EQEmu::ItemInstance::GetItemHeroicWis(bool augments) const if (item) { total = item->HeroicWis; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicWis(); } @@ -2938,7 +2938,7 @@ int EQEmu::ItemInstance::GetItemHeroicCha(bool augments) const if (item) { total = item->HeroicCha; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCha(); } @@ -2952,7 +2952,7 @@ int EQEmu::ItemInstance::GetItemHeroicMR(bool augments) const if (item) { total = item->HeroicMR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicMR(); } @@ -2966,7 +2966,7 @@ int EQEmu::ItemInstance::GetItemHeroicFR(bool augments) const if (item) { total = item->HeroicFR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicFR(); } @@ -2980,7 +2980,7 @@ int EQEmu::ItemInstance::GetItemHeroicCR(bool augments) const if (item) { total = item->HeroicCR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCR(); } @@ -2994,7 +2994,7 @@ int EQEmu::ItemInstance::GetItemHeroicPR(bool augments) const if (item) { total = item->HeroicPR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicPR(); } @@ -3008,7 +3008,7 @@ int EQEmu::ItemInstance::GetItemHeroicDR(bool augments) const if (item) { total = item->HeroicDR; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicDR(); } @@ -3022,7 +3022,7 @@ int EQEmu::ItemInstance::GetItemHeroicCorrup(bool augments) const if (item) { total = item->HeroicSVCorrup; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCorrup(); } @@ -3036,7 +3036,7 @@ int EQEmu::ItemInstance::GetItemHaste(bool augments) const if (item) { total = item->Haste; if (augments) - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) if (GetAugment(i)) { int temp = GetAugment(i)->GetItemHaste(); if (temp > total) diff --git a/common/item_instance.h b/common/item_instance.h index 29523c1b1..7fbf03cd9 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -313,7 +313,7 @@ namespace EQEmu bool AvailableWearSlot(uint32 aug_wear_slots) const; int8 AvailableAugmentSlot(int32 augtype) const; bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const; - inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : NO_ITEM); } + inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); } inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == EQEmu::item::ItemEffectExpendable) || (m_item->ItemType == EQEmu::item::ItemTypePotion)) : false); } @@ -353,8 +353,8 @@ namespace EQEmu bool IsAmmo() const; // Accessors - const uint32 GetID() const { return ((m_item) ? m_item->ID : NO_ITEM); } - const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : NO_ITEM); } + const uint32 GetID() const { return ((m_item) ? m_item->ID : 0); } + const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : 0); } const ItemData* GetItem() const; const ItemData* GetUnscaledItem() const; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index a6fcae35c..d3b4456b7 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2079,7 +2079,7 @@ namespace RoF outapp->WriteUInt32(22); // Equipment count - for (int r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) + for (int r = EQEmu::textures::textureBegin; r < EQEmu::textures::materialCount; r++) { outapp->WriteUInt32(emu->item_material.Slot[r].Material); outapp->WriteUInt32(0); @@ -2099,9 +2099,9 @@ namespace RoF outapp->WriteUInt32(0); } - outapp->WriteUInt32(EQEmu::textures::TextureCount); // Equipment2 count + outapp->WriteUInt32(EQEmu::textures::materialCount); // Equipment2 count - for (int r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) + for (int r = EQEmu::textures::textureBegin; r < EQEmu::textures::materialCount; r++) { outapp->WriteUInt32(0); outapp->WriteUInt32(0); @@ -2110,7 +2110,7 @@ namespace RoF outapp->WriteUInt32(0); } - outapp->WriteUInt32(EQEmu::textures::TextureCount); // Tint Count + outapp->WriteUInt32(EQEmu::textures::materialCount); // Tint Count for (int r = 0; r < 7; r++) { @@ -2120,7 +2120,7 @@ namespace RoF outapp->WriteUInt32(0); outapp->WriteUInt32(0); - outapp->WriteUInt32(EQEmu::textures::TextureCount); // Tint2 Count + outapp->WriteUInt32(EQEmu::textures::materialCount); // Tint2 Count for (int r = 0; r < 7; r++) { @@ -3059,12 +3059,12 @@ namespace RoF eq_cse->Gender = emu_cse->Gender; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::textures::materialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; - eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; - eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HeroForgeModel; - eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Material2; + eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteModel; + eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HeroicModel; + eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Unknown2; eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } @@ -4096,7 +4096,7 @@ namespace RoF if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { - for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; ++k) + for (k = EQEmu::textures::textureBegin; k < EQEmu::textures::materialCount; ++k) { { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); @@ -4105,15 +4105,15 @@ namespace RoF structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; - for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { + for (k = EQEmu::textures::textureBegin; k < EQEmu::textures::materialCount; k++) { Equipment[k].Material = emu->equipment.Slot[k].Material; Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; - Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; - Equipment[k].HeroForgeModel = emu->equipment.Slot[k].HeroForgeModel; - Equipment[k].Material2 = emu->equipment.Slot[k].Material2; + Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteModel; + Equipment[k].HeroForgeModel = emu->equipment.Slot[k].HeroicModel; + Equipment[k].Material2 = emu->equipment.Slot[k].Unknown2; } - Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); + Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::materialCount); } else { @@ -4829,10 +4829,9 @@ namespace RoF IN(item_id); int r; - for (r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { + for (r = EQEmu::inventory::socketBegin; r < EQEmu::inventory::SocketCount; r++) { IN(augments[r]); } - // Max Augs is now 6, but no code to support that many yet IN(link_hash); IN(icon); @@ -5622,18 +5621,18 @@ namespace RoF ob.write((const char*)&subitem_count, sizeof(uint32)); - for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { + for (uint32 index = EQEmu::inventory::containerBegin; index < EQEmu::inventory::ContainerCount; ++index) { EQEmu::ItemInstance* sub = inst->GetItem(index); if (!sub) continue; int SubSlotNumber = INVALID_INDEX; if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) - SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1); + SubSlotNumber = (((slot_id_in + 3) * EQEmu::inventory::ContainerCount) + index + 1); else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) - SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::inventory::ContainerCount) + EQEmu::legacy::BANK_BAGS_BEGIN + index); else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) - SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::inventory::ContainerCount) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); else SubSlotNumber = slot_id_in; @@ -5659,17 +5658,17 @@ namespace RoF uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == EQEmu::legacy::SlotPowerSource) { // Main Inventory and Cursor + if (serverSlot < 56 || serverSlot == EQEmu::inventory::slotPowerSource) { // Main Inventory and Cursor RoFSlot.Type = invtype::InvTypePossessions; RoFSlot.Slot = serverSlot; - if (serverSlot == EQEmu::legacy::SlotPowerSource) + if (serverSlot == EQEmu::inventory::slotPowerSource) RoFSlot.Slot = invslot::PossessionsPowerSource; - else if (serverSlot >= EQEmu::legacy::SlotCursor) // Cursor and Extended Corpse Inventory + else if (serverSlot >= EQEmu::inventory::slotCursor) // Cursor and Extended Corpse Inventory RoFSlot.Slot += 3; - else if (serverSlot >= EQEmu::legacy::SlotAmmo) // (> 20) + else if (serverSlot >= EQEmu::inventory::slotAmmo) // (> 20) RoFSlot.Slot += 1; } @@ -5681,8 +5680,8 @@ namespace RoF else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) { // (> 250 && < 341) RoFSlot.Type = invtype::InvTypePossessions; TempSlot = serverSlot - 1; - RoFSlot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 2; - RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::legacy::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::inventory::ContainerCount) - 2; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::inventory::ContainerCount); if (RoFSlot.Slot >= invslot::PossessionsGeneral9) // (> 30) RoFSlot.Slot = invslot::PossessionsCursor; @@ -5699,8 +5698,8 @@ namespace RoF RoFSlot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoFSlot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::inventory::ContainerCount) - 3; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::inventory::ContainerCount); } } @@ -5710,8 +5709,8 @@ namespace RoF RoFSlot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoFSlot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::inventory::ContainerCount) - 3; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::inventory::ContainerCount); } } @@ -5721,8 +5720,8 @@ namespace RoF RoFSlot.Slot = TempSlot; if (TempSlot > 30) { - RoFSlot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::inventory::ContainerCount) - 3; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 3) * EQEmu::inventory::ContainerCount); } /* @@ -5760,16 +5759,16 @@ namespace RoF uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == EQEmu::legacy::SlotPowerSource) { // (< 52) + if (serverSlot < 56 || serverSlot == EQEmu::inventory::slotPowerSource) { // (< 52) RoFSlot.Slot = serverSlot; - if (serverSlot == EQEmu::legacy::SlotPowerSource) + if (serverSlot == EQEmu::inventory::slotPowerSource) RoFSlot.Slot = invslot::PossessionsPowerSource; - else if (serverSlot >= EQEmu::legacy::SlotCursor) // Cursor and Extended Corpse Inventory + else if (serverSlot >= EQEmu::inventory::slotCursor) // Cursor and Extended Corpse Inventory RoFSlot.Slot += 3; - else if (serverSlot >= EQEmu::legacy::SlotAmmo) // Ammo and Personl Inventory + else if (serverSlot >= EQEmu::inventory::slotAmmo) // Ammo and Personl Inventory RoFSlot.Slot += 1; /*else if (ServerSlot >= MainCursor) { // Cursor @@ -5782,8 +5781,8 @@ namespace RoF else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) { TempSlot = serverSlot - 1; - RoFSlot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 2; - RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::legacy::ITEM_CONTAINER_SIZE); + RoFSlot.Slot = int(TempSlot / EQEmu::inventory::ContainerCount) - 2; + RoFSlot.SubIndex = TempSlot - ((RoFSlot.Slot + 2) * EQEmu::inventory::ContainerCount); } Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoFSlot.Slot, RoFSlot.SubIndex, RoFSlot.AugIndex, RoFSlot.Unknown01); @@ -5803,7 +5802,7 @@ namespace RoF if (rofSlot.Type == invtype::InvTypePossessions && rofSlot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 51) if (rofSlot.Slot == invslot::PossessionsPowerSource) - TempSlot = EQEmu::legacy::SlotPowerSource; + TempSlot = EQEmu::inventory::slotPowerSource; else if (rofSlot.Slot >= invslot::PossessionsCursor) // Cursor and Extended Corpse Inventory TempSlot = rofSlot.Slot - 3; @@ -5825,8 +5824,8 @@ namespace RoF else // Worn Slots TempSlot = rofSlot.Slot; - if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; + if (rofSlot.SubIndex >= EQEmu::inventory::containerBegin) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::inventory::ContainerCount) + rofSlot.SubIndex + 1; ServerSlot = TempSlot; } @@ -5834,8 +5833,8 @@ namespace RoF else if (rofSlot.Type == invtype::InvTypeBank) { TempSlot = EQEmu::legacy::BANK_BEGIN; - if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rofSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; + if (rofSlot.SubIndex >= EQEmu::inventory::containerBegin) + TempSlot += ((rofSlot.Slot + 3) * EQEmu::inventory::ContainerCount) + rofSlot.SubIndex + 1; else TempSlot += rofSlot.Slot; @@ -5846,8 +5845,8 @@ namespace RoF else if (rofSlot.Type == invtype::InvTypeSharedBank) { TempSlot = EQEmu::legacy::SHARED_BANK_BEGIN; - if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rofSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; + if (rofSlot.SubIndex >= EQEmu::inventory::containerBegin) + TempSlot += ((rofSlot.Slot + 3) * EQEmu::inventory::ContainerCount) + rofSlot.SubIndex + 1; else TempSlot += rofSlot.Slot; @@ -5858,10 +5857,10 @@ namespace RoF else if (rofSlot.Type == invtype::InvTypeTrade) { TempSlot = EQEmu::legacy::TRADE_BEGIN; - if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rofSlot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; + if (rofSlot.SubIndex >= EQEmu::inventory::containerBegin) + TempSlot += ((rofSlot.Slot + 3) * EQEmu::inventory::ContainerCount) + rofSlot.SubIndex + 1; // OLD CODE: - //TempSlot += 100 + (RoFSlot.MainSlot * EQEmu::legacy::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot; + //TempSlot += 100 + (RoFSlot.MainSlot * EQEmu::inventory::ContainerCount) + RoFSlot.SubSlot; else TempSlot += rofSlot.Slot; @@ -5872,7 +5871,7 @@ namespace RoF else if (rofSlot.Type == invtype::InvTypeWorld) { TempSlot = EQEmu::legacy::WORLD_BEGIN; - if (rofSlot.Slot >= SUB_INDEX_BEGIN) + if (rofSlot.Slot >= EQEmu::inventory::containerBegin) TempSlot += rofSlot.Slot; ServerSlot = TempSlot; @@ -5903,7 +5902,7 @@ namespace RoF if (rofSlot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 33) if (rofSlot.Slot == invslot::PossessionsPowerSource) - TempSlot = EQEmu::legacy::SlotPowerSource; + TempSlot = EQEmu::inventory::slotPowerSource; else if (rofSlot.Slot >= invslot::PossessionsCursor) // Cursor and Extended Corpse Inventory TempSlot = rofSlot.Slot - 3; @@ -5920,8 +5919,8 @@ namespace RoF else TempSlot = rofSlot.Slot; - if (rofSlot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rofSlot.SubIndex + 1; + if (rofSlot.SubIndex >= EQEmu::inventory::containerBegin) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::inventory::ContainerCount) + rofSlot.SubIndex + 1; ServerSlot = TempSlot; } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 47be172a2..676f4c89f 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2164,7 +2164,7 @@ namespace RoF2 outapp->WriteUInt32(22); // Equipment count - for (int r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) + for (int r = EQEmu::textures::textureBegin; r < EQEmu::textures::materialCount; r++) { outapp->WriteUInt32(emu->item_material.Slot[r].Material); outapp->WriteUInt32(0); @@ -2184,9 +2184,9 @@ namespace RoF2 outapp->WriteUInt32(0); } - outapp->WriteUInt32(EQEmu::textures::TextureCount); // Equipment2 count + outapp->WriteUInt32(EQEmu::textures::materialCount); // Equipment2 count - for (int r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) + for (int r = EQEmu::textures::textureBegin; r < EQEmu::textures::materialCount; r++) { outapp->WriteUInt32(0); outapp->WriteUInt32(0); @@ -2195,7 +2195,7 @@ namespace RoF2 outapp->WriteUInt32(0); } - outapp->WriteUInt32(EQEmu::textures::TextureCount); // Tint Count + outapp->WriteUInt32(EQEmu::textures::materialCount); // Tint Count for (int r = 0; r < 7; r++) { @@ -2205,7 +2205,7 @@ namespace RoF2 outapp->WriteUInt32(0); outapp->WriteUInt32(0); - outapp->WriteUInt32(EQEmu::textures::TextureCount); // Tint2 Count + outapp->WriteUInt32(EQEmu::textures::materialCount); // Tint2 Count for (int r = 0; r < 7; r++) { @@ -3154,12 +3154,12 @@ namespace RoF2 eq_cse->Gender = emu_cse->Gender; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { + for (int equip_index = 0; equip_index < EQEmu::textures::materialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; - eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; - eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HeroForgeModel; - eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Material2; + eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteModel; + eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HeroicModel; + eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Unknown2; eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } @@ -4321,7 +4321,7 @@ namespace RoF2 if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { - for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; ++k) + for (k = EQEmu::textures::textureBegin; k < EQEmu::textures::materialCount; ++k) { { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); @@ -4330,15 +4330,15 @@ namespace RoF2 structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; - for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { + for (k = EQEmu::textures::textureBegin; k < EQEmu::textures::materialCount; k++) { Equipment[k].Material = emu->equipment.Slot[k].Material; Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; - Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; - Equipment[k].HeroForgeModel = emu->equipment.Slot[k].HeroForgeModel; - Equipment[k].Material2 = emu->equipment.Slot[k].Material2; + Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteModel; + Equipment[k].HeroForgeModel = emu->equipment.Slot[k].HeroicModel; + Equipment[k].Material2 = emu->equipment.Slot[k].Unknown2; } - Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); + Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::materialCount); } else { @@ -5066,7 +5066,7 @@ namespace RoF2 IN(item_id); int r; - for (r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { + for (r = EQEmu::inventory::socketBegin; r < EQEmu::inventory::SocketCount; r++) { IN(augments[r]); } IN(link_hash); @@ -5922,18 +5922,18 @@ namespace RoF2 ob.write((const char*)&subitem_count, sizeof(uint32)); - for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { + for (uint32 index = EQEmu::inventory::containerBegin; index < EQEmu::inventory::ContainerCount; ++index) { EQEmu::ItemInstance* sub = inst->GetItem(index); if (!sub) continue; int SubSlotNumber = INVALID_INDEX; if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) - SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1); + SubSlotNumber = (((slot_id_in + 3) * EQEmu::inventory::ContainerCount) + index + 1); else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) - SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::inventory::ContainerCount) + EQEmu::legacy::BANK_BAGS_BEGIN + index); else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) - SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::inventory::ContainerCount) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); else SubSlotNumber = slot_id_in; @@ -5959,7 +5959,7 @@ namespace RoF2 uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == EQEmu::legacy::SlotPowerSource) { // Main Inventory and Cursor + if (serverSlot < 56 || serverSlot == EQEmu::inventory::slotPowerSource) { // Main Inventory and Cursor if (PacketType == ItemPacketLoot) { RoF2Slot.Type = invtype::InvTypeCorpse; @@ -5971,13 +5971,13 @@ namespace RoF2 RoF2Slot.Slot = serverSlot; } - if (serverSlot == EQEmu::legacy::SlotPowerSource) + if (serverSlot == EQEmu::inventory::slotPowerSource) RoF2Slot.Slot = invslot::PossessionsPowerSource; - else if (serverSlot >= EQEmu::legacy::SlotCursor && PacketType != ItemPacketLoot) // Cursor and Extended Corpse Inventory + else if (serverSlot >= EQEmu::inventory::slotCursor && PacketType != ItemPacketLoot) // Cursor and Extended Corpse Inventory RoF2Slot.Slot += 3; - else if (serverSlot >= EQEmu::legacy::SlotAmmo) // (> 20) + else if (serverSlot >= EQEmu::inventory::slotAmmo) // (> 20) RoF2Slot.Slot += 1; } @@ -5989,8 +5989,8 @@ namespace RoF2 else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) { // (> 250 && < 341) RoF2Slot.Type = invtype::InvTypePossessions; TempSlot = serverSlot - 1; - RoF2Slot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 2; - RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::legacy::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::inventory::ContainerCount) - 2; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::inventory::ContainerCount); if (RoF2Slot.Slot >= invslot::PossessionsGeneral9) // (> 30) RoF2Slot.Slot = invslot::PossessionsCursor; @@ -6007,8 +6007,8 @@ namespace RoF2 RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoF2Slot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::inventory::ContainerCount) - 3; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::inventory::ContainerCount); } } @@ -6018,8 +6018,8 @@ namespace RoF2 RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { // (> 30) - RoF2Slot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::inventory::ContainerCount) - 3; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::inventory::ContainerCount); } } @@ -6029,8 +6029,8 @@ namespace RoF2 RoF2Slot.Slot = TempSlot; if (TempSlot > 30) { - RoF2Slot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 3; - RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::inventory::ContainerCount) - 3; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 3) * EQEmu::inventory::ContainerCount); } /* @@ -6068,16 +6068,16 @@ namespace RoF2 uint32 TempSlot = 0; - if (serverSlot < 56 || serverSlot == EQEmu::legacy::SlotPowerSource) { // (< 52) + if (serverSlot < 56 || serverSlot == EQEmu::inventory::slotPowerSource) { // (< 52) RoF2Slot.Slot = serverSlot; - if (serverSlot == EQEmu::legacy::SlotPowerSource) + if (serverSlot == EQEmu::inventory::slotPowerSource) RoF2Slot.Slot = invslot::PossessionsPowerSource; - else if (serverSlot >= EQEmu::legacy::SlotCursor) // Cursor and Extended Corpse Inventory + else if (serverSlot >= EQEmu::inventory::slotCursor) // Cursor and Extended Corpse Inventory RoF2Slot.Slot += 3; - else if (serverSlot >= EQEmu::legacy::SlotAmmo) // Ammo and Personl Inventory + else if (serverSlot >= EQEmu::inventory::slotAmmo) // Ammo and Personl Inventory RoF2Slot.Slot += 1; /*else if (ServerSlot >= MainCursor) { // Cursor @@ -6090,8 +6090,8 @@ namespace RoF2 else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) { TempSlot = serverSlot - 1; - RoF2Slot.Slot = int(TempSlot / EQEmu::legacy::ITEM_CONTAINER_SIZE) - 2; - RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::legacy::ITEM_CONTAINER_SIZE); + RoF2Slot.Slot = int(TempSlot / EQEmu::inventory::ContainerCount) - 2; + RoF2Slot.SubIndex = TempSlot - ((RoF2Slot.Slot + 2) * EQEmu::inventory::ContainerCount); } Log.Out(Logs::General, Logs::Netcode, "[ERROR] Convert Server Slot %i to RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i", serverSlot, RoF2Slot.Slot, RoF2Slot.SubIndex, RoF2Slot.AugIndex, RoF2Slot.Unknown01); @@ -6111,7 +6111,7 @@ namespace RoF2 if (rof2Slot.Type == invtype::InvTypePossessions && rof2Slot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 51) if (rof2Slot.Slot == invslot::PossessionsPowerSource) - TempSlot = EQEmu::legacy::SlotPowerSource; + TempSlot = EQEmu::inventory::slotPowerSource; else if (rof2Slot.Slot >= invslot::PossessionsCursor) // Cursor and Extended Corpse Inventory TempSlot = rof2Slot.Slot - 3; @@ -6133,8 +6133,8 @@ namespace RoF2 else // Worn Slots TempSlot = rof2Slot.Slot; - if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; + if (rof2Slot.SubIndex >= EQEmu::inventory::containerBegin) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::inventory::ContainerCount) + rof2Slot.SubIndex + 1; ServerSlot = TempSlot; } @@ -6142,8 +6142,8 @@ namespace RoF2 else if (rof2Slot.Type == invtype::InvTypeBank) { TempSlot = EQEmu::legacy::BANK_BEGIN; - if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rof2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; + if (rof2Slot.SubIndex >= EQEmu::inventory::containerBegin) + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::inventory::ContainerCount) + rof2Slot.SubIndex + 1; else TempSlot += rof2Slot.Slot; @@ -6154,8 +6154,8 @@ namespace RoF2 else if (rof2Slot.Type == invtype::InvTypeSharedBank) { TempSlot = EQEmu::legacy::SHARED_BANK_BEGIN; - if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rof2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; + if (rof2Slot.SubIndex >= EQEmu::inventory::containerBegin) + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::inventory::ContainerCount) + rof2Slot.SubIndex + 1; else TempSlot += rof2Slot.Slot; @@ -6166,8 +6166,8 @@ namespace RoF2 else if (rof2Slot.Type == invtype::InvTypeTrade) { TempSlot = EQEmu::legacy::TRADE_BEGIN; - if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) - TempSlot += ((rof2Slot.Slot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; + if (rof2Slot.SubIndex >= EQEmu::inventory::containerBegin) + TempSlot += ((rof2Slot.Slot + 3) * EQEmu::inventory::ContainerCount) + rof2Slot.SubIndex + 1; // OLD CODE: //TempSlot += 100 + (RoF2Slot.MainSlot * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot; @@ -6180,7 +6180,7 @@ namespace RoF2 else if (rof2Slot.Type == invtype::InvTypeWorld) { TempSlot = EQEmu::legacy::WORLD_BEGIN; - if (rof2Slot.Slot >= SUB_INDEX_BEGIN) + if (rof2Slot.Slot >= EQEmu::inventory::containerBegin) TempSlot += rof2Slot.Slot; ServerSlot = TempSlot; @@ -6215,7 +6215,7 @@ namespace RoF2 if (rof2Slot.Slot < 57) { // Worn/Personal Inventory and Cursor (< 33) if (rof2Slot.Slot == invslot::PossessionsPowerSource) - TempSlot = EQEmu::legacy::SlotPowerSource; + TempSlot = EQEmu::inventory::slotPowerSource; else if (rof2Slot.Slot >= invslot::PossessionsCursor) // Cursor and Extended Corpse Inventory TempSlot = rof2Slot.Slot - 3; @@ -6232,8 +6232,8 @@ namespace RoF2 else TempSlot = rof2Slot.Slot; - if (rof2Slot.SubIndex >= SUB_INDEX_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + rof2Slot.SubIndex + 1; + if (rof2Slot.SubIndex >= EQEmu::inventory::containerBegin) // Bag Slots + TempSlot = ((TempSlot + 3) * EQEmu::inventory::ContainerCount) + rof2Slot.SubIndex + 1; ServerSlot = TempSlot; } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 12f467a71..850df8ddf 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -190,7 +190,7 @@ struct TintProfile Tint_Struct Primary; Tint_Struct Secondary; }; - Tint_Struct Slot[EQEmu::textures::TextureCount]; + Tint_Struct Slot[EQEmu::textures::materialCount]; }; }; @@ -1082,7 +1082,7 @@ union /*00184*/ Texture_Struct equipment[22]; // Total Slots }; /*00624*/ uint32 equip2_count; // Seen 9 -/*00628*/ Texture_Struct equipment2[EQEmu::textures::TextureCount]; // Appears to be Visible slots, but all 0s +/*00628*/ Texture_Struct equipment2[EQEmu::textures::materialCount]; // Appears to be Visible slots, but all 0s /*00808*/ uint32 tint_count; // Seen 9 /*00812*/ TintProfile item_tint; // RR GG BB 00 /*00848*/ uint32 tint_count2; // Seen 9 diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 3b6e01318..879afc1d4 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -190,7 +190,7 @@ struct TintProfile Tint_Struct Primary; Tint_Struct Secondary; }; - Tint_Struct Slot[EQEmu::textures::TextureCount]; + Tint_Struct Slot[EQEmu::textures::materialCount]; }; }; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 0e1a3fdcd..330f7ee20 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1558,7 +1558,7 @@ namespace SoD OUT(hairstyle); OUT(beard); // OUT(unknown00178[10]); - for (r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { + for (r = EQEmu::textures::textureBegin; r < EQEmu::textures::materialCount; r++) { eq->equipment.Slot[r].Material = emu->item_material.Slot[r].Material; eq->equipment.Slot[r].Unknown1 = 0; eq->equipment.Slot[r].EliteMaterial = 0; @@ -1998,10 +1998,10 @@ namespace SoD eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { + for (int equip_index = EQEmu::textures::textureBegin; equip_index < EQEmu::textures::materialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; - eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; + eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteModel; eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } @@ -2568,7 +2568,7 @@ namespace SoD float SpawnSize = emu->size; if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) { - PacketSize -= (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); + PacketSize -= (sizeof(structs::Texture_Struct) * EQEmu::textures::materialCount); if (emu->size == 0) { @@ -2765,7 +2765,7 @@ namespace SoD if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { - for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; ++k) + for (k = EQEmu::textures::textureBegin; k < EQEmu::textures::materialCount; ++k) { { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); @@ -2792,13 +2792,13 @@ namespace SoD { structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; - for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { + for (k = EQEmu::textures::textureBegin; k < EQEmu::textures::materialCount; k++) { Equipment[k].Material = emu->equipment.Slot[k].Material; Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; - Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; + Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteModel; } - Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); + Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::materialCount); } if (strlen(emu->title)) { @@ -3869,18 +3869,18 @@ namespace SoD ob.write((const char*)&subitem_count, sizeof(uint32)); - for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { + for (uint32 index = EQEmu::inventory::containerBegin; index < EQEmu::inventory::ContainerCount; ++index) { EQEmu::ItemInstance* sub = inst->GetItem(index); if (!sub) continue; int SubSlotNumber = INVALID_INDEX; if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) - SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1); + SubSlotNumber = (((slot_id_in + 3) * EQEmu::inventory::ContainerCount) + index + 1); else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) - SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::inventory::ContainerCount) + EQEmu::legacy::BANK_BAGS_BEGIN + index); else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) - SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::inventory::ContainerCount) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); else SubSlotNumber = slot_id_in; @@ -3898,7 +3898,7 @@ namespace SoD { uint32 SoDSlot = 0; - if (serverSlot >= EQEmu::legacy::SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (serverSlot >= EQEmu::inventory::slotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots SoDSlot = serverSlot + 1; else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) SoDSlot = serverSlot + 11; @@ -3906,7 +3906,7 @@ namespace SoD SoDSlot = serverSlot + 1; else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) SoDSlot = serverSlot + 1; - else if (serverSlot == EQEmu::legacy::SlotPowerSource) + else if (serverSlot == EQEmu::inventory::slotPowerSource) SoDSlot = invslot::PossessionsPowerSource; else SoDSlot = serverSlot; @@ -3932,7 +3932,7 @@ namespace SoD else if (sodSlot >= invbag::SharedBankBagsBegin && sodSlot <= invbag::SharedBankBagsEnd) ServerSlot = sodSlot - 1; else if (sodSlot == invslot::PossessionsPowerSource) - ServerSlot = EQEmu::legacy::SlotPowerSource; + ServerSlot = EQEmu::inventory::slotPowerSource; else ServerSlot = sodSlot; return ServerSlot; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index d4a4d49a3..cd76218e0 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -149,7 +149,7 @@ struct TintProfile Tint_Struct Primary; Tint_Struct Secondary; }; - Tint_Struct Slot[EQEmu::textures::TextureCount]; + Tint_Struct Slot[EQEmu::textures::materialCount]; }; }; @@ -178,7 +178,7 @@ struct TextureProfile Texture_Struct Primary; Texture_Struct Secondary; }; - Texture_Struct Slot[EQEmu::textures::TextureCount]; + Texture_Struct Slot[EQEmu::textures::materialCount]; }; TextureProfile(); @@ -195,7 +195,7 @@ struct CharacterSelectEntry_Struct /*0000*/ uint8 Beard; // /*0001*/ uint8 HairColor; // /*0000*/ uint8 Face; // -/*0000*/ CharSelectEquip Equip[EQEmu::textures::TextureCount]; +/*0000*/ CharSelectEquip Equip[EQEmu::textures::materialCount]; /*0000*/ uint32 PrimaryIDFile; // /*0000*/ uint32 SecondaryIDFile; // /*0000*/ uint8 Unknown15; // 0xff diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index b73e998aa..59e0edb5f 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1230,7 +1230,7 @@ namespace SoF OUT(hairstyle); OUT(beard); // OUT(unknown00178[10]); - for (r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { + for (r = EQEmu::textures::textureBegin; r < EQEmu::textures::materialCount; r++) { eq->equipment.Slot[r].Material = emu->item_material.Slot[r].Material; eq->equipment.Slot[r].Unknown1 = 0; eq->equipment.Slot[r].EliteMaterial = 0; @@ -1670,10 +1670,10 @@ namespace SoF eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { + for (int equip_index = EQEmu::textures::textureBegin; equip_index < EQEmu::textures::materialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; - eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; + eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteModel; eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } @@ -2101,10 +2101,10 @@ namespace SoF eq->deity = emu->deity; eq->drakkin_heritage = emu->drakkin_heritage; eq->gender = emu->gender; - for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { + for (k = EQEmu::textures::textureBegin; k < EQEmu::textures::materialCount; k++) { eq->equipment.Slot[k].Material = emu->equipment.Slot[k].Material; eq->equipment.Slot[k].Unknown1 = emu->equipment.Slot[k].Unknown1; - eq->equipment.Slot[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; + eq->equipment.Slot[k].EliteMaterial = emu->equipment.Slot[k].EliteModel; eq->equipment_tint.Slot[k].Color = emu->equipment_tint.Slot[k].Color; } eq->StandState = emu->StandState; @@ -2167,7 +2167,7 @@ namespace SoF strcpy(eq->name, emu->name); eq->petOwnerId = emu->petOwnerId; eq->pvp = 0; // 0 = non-pvp colored name, 1 = red pvp name - for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { + for (k = EQEmu::textures::textureBegin; k < EQEmu::textures::materialCount; k++) { eq->equipment_tint.Slot[k].Color = emu->equipment_tint.Slot[k].Color; } eq->anon = emu->anon; @@ -3237,18 +3237,18 @@ namespace SoF ob.write((const char*)&subitem_count, sizeof(uint32)); - for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { + for (uint32 index = EQEmu::inventory::containerBegin; index < EQEmu::inventory::ContainerCount; ++index) { EQEmu::ItemInstance* sub = inst->GetItem(index); if (!sub) continue; int SubSlotNumber = INVALID_INDEX; if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) - SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1); + SubSlotNumber = (((slot_id_in + 3) * EQEmu::inventory::ContainerCount) + index + 1); else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) - SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::inventory::ContainerCount) + EQEmu::legacy::BANK_BAGS_BEGIN + index); else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) - SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::inventory::ContainerCount) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); else SubSlotNumber = slot_id_in; @@ -3266,7 +3266,7 @@ namespace SoF { uint32 SoFSlot = 0; - if (serverSlot >= EQEmu::legacy::SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (serverSlot >= EQEmu::inventory::slotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots SoFSlot = serverSlot + 1; else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) SoFSlot = serverSlot + 11; @@ -3274,7 +3274,7 @@ namespace SoF SoFSlot = serverSlot + 1; else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) SoFSlot = serverSlot + 1; - else if (serverSlot == EQEmu::legacy::SlotPowerSource) + else if (serverSlot == EQEmu::inventory::slotPowerSource) SoFSlot = invslot::PossessionsPowerSource; else SoFSlot = serverSlot; @@ -3301,7 +3301,7 @@ namespace SoF else if (sofSlot >= invbag::SharedBankBagsBegin && sofSlot <= invbag::SharedBankBagsEnd) ServerSlot = sofSlot - 1; else if (sofSlot == invslot::PossessionsPowerSource) - ServerSlot = EQEmu::legacy::SlotPowerSource; + ServerSlot = EQEmu::inventory::slotPowerSource; else ServerSlot = sofSlot; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 0981fd4ee..9be93d49f 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -149,7 +149,7 @@ struct TintProfile Tint_Struct Primary; Tint_Struct Secondary; }; - Tint_Struct Slot[EQEmu::textures::TextureCount]; + Tint_Struct Slot[EQEmu::textures::materialCount]; }; }; @@ -178,7 +178,7 @@ struct TextureProfile Texture_Struct Primary; Texture_Struct Secondary; }; - Texture_Struct Slot[EQEmu::textures::TextureCount]; + Texture_Struct Slot[EQEmu::textures::materialCount]; }; TextureProfile(); @@ -195,7 +195,7 @@ struct CharacterSelectEntry_Struct /*0000*/ uint8 Beard; // /*0001*/ uint8 HairColor; // /*0000*/ uint8 Face; // -/*0000*/ CharSelectEquip Equip[EQEmu::textures::TextureCount]; +/*0000*/ CharSelectEquip Equip[EQEmu::textures::materialCount]; /*0000*/ uint32 PrimaryIDFile; // /*0000*/ uint32 SecondaryIDFile; // /*0000*/ uint8 Unknown15; // 0xff diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 9b6459afb..286d09d1b 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -981,7 +981,7 @@ namespace Titanium OUT(hairstyle); OUT(beard); // OUT(unknown00178[10]); - for (r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { + for (r = EQEmu::textures::textureBegin; r < EQEmu::textures::materialCount; r++) { OUT(item_material.Slot[r].Material); OUT(item_tint.Slot[r].Color); } @@ -1301,14 +1301,14 @@ namespace Titanium if (eq->Race[char_index] > 473) eq->Race[char_index] = 1; - for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { + for (int index = 0; index < EQEmu::textures::materialCount; ++index) { eq->CS_Colors[char_index].Slot[index].Color = emu_cse->Equip[index].Color; } eq->BeardColor[char_index] = emu_cse->BeardColor; eq->HairStyle[char_index] = emu_cse->HairStyle; - for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { + for (int index = 0; index < EQEmu::textures::materialCount; ++index) { eq->Equip[char_index].Slot[index].Material = emu_cse->Equip[index].Material; } @@ -1338,14 +1338,14 @@ namespace Titanium for (; char_index < 10; ++char_index) { eq->Race[char_index] = 0; - for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { + for (int index = 0; index < EQEmu::textures::materialCount; ++index) { eq->CS_Colors[char_index].Slot[index].Color = 0; } eq->BeardColor[char_index] = 0; eq->HairStyle[char_index] = 0; - for (int index = 0; index < EQEmu::textures::TextureCount; ++index) { + for (int index = 0; index < EQEmu::textures::materialCount; ++index) { eq->Equip[char_index].Slot[index].Material = 0; } @@ -1677,7 +1677,7 @@ namespace Titanium eq->petOwnerId = emu->petOwnerId; eq->guildrank = emu->guildrank; // eq->unknown0194[3] = emu->unknown0194[3]; - for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { + for (k = EQEmu::textures::textureBegin; k < EQEmu::textures::materialCount; k++) { eq->equipment.Slot[k].Material = emu->equipment.Slot[k].Material; eq->equipment_tint.Slot[k].Color = emu->equipment_tint.Slot[k].Color; } @@ -2437,7 +2437,7 @@ namespace Titanium ob << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data // Sub data - for (int index = SUB_INDEX_BEGIN; index < invbag::ItemBagSize; ++index) { + for (int index = EQEmu::inventory::containerBegin; index < invbag::ItemBagSize; ++index) { ob << '|'; EQEmu::ItemInstance* sub = inst->GetItem(index); diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index c4f6d4959..91921da2e 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -144,7 +144,7 @@ struct TintProfile { Tint_Struct Primary; Tint_Struct Secondary; }; - Tint_Struct Slot[EQEmu::textures::TextureCount]; + Tint_Struct Slot[EQEmu::textures::materialCount]; }; }; @@ -167,7 +167,7 @@ struct TextureProfile Texture_Struct Primary; Texture_Struct Secondary; }; - Texture_Struct Slot[EQEmu::textures::TextureCount]; + Texture_Struct Slot[EQEmu::textures::materialCount]; }; TextureProfile(); diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index fd45b0c61..92be237b1 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1817,7 +1817,7 @@ namespace UF OUT(hairstyle); OUT(beard); // OUT(unknown00178[10]); - for (r = EQEmu::textures::TextureBegin; r < EQEmu::textures::TextureCount; r++) { + for (r = EQEmu::textures::textureBegin; r < EQEmu::textures::materialCount; r++) { eq->equipment.Slot[r].Material = emu->item_material.Slot[r].Material; eq->equipment.Slot[r].Unknown1 = 0; eq->equipment.Slot[r].EliteMaterial = 0; @@ -2301,10 +2301,10 @@ namespace UF eq_cse->HairColor = emu_cse->HairColor; eq_cse->Face = emu_cse->Face; - for (int equip_index = 0; equip_index < EQEmu::textures::TextureCount; equip_index++) { + for (int equip_index = EQEmu::textures::textureBegin; equip_index < EQEmu::textures::materialCount; equip_index++) { eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; - eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteMaterial; + eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteModel; eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } @@ -2869,7 +2869,7 @@ namespace UF float SpawnSize = emu->size; if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) { - PacketSize -= (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); + PacketSize -= (sizeof(structs::Texture_Struct) * EQEmu::textures::materialCount); if (emu->size == 0) { @@ -3068,7 +3068,7 @@ namespace UF if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { - for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; ++k) + for (k = EQEmu::textures::textureBegin; k < EQEmu::textures::materialCount; ++k) { { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment_tint.Slot[k].Color); @@ -3104,17 +3104,17 @@ namespace UF { structs::Texture_Struct *Equipment = (structs::Texture_Struct *)Buffer; - for (k = EQEmu::textures::TextureBegin; k < EQEmu::textures::TextureCount; k++) { + for (k = EQEmu::textures::textureBegin; k < EQEmu::textures::materialCount; k++) { if (emu->equipment.Slot[k].Material > 99999) { Equipment[k].Material = 63; } else { Equipment[k].Material = emu->equipment.Slot[k].Material; } Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; - Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteMaterial; + Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteModel; } - Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::TextureCount); + Buffer += (sizeof(structs::Texture_Struct) * EQEmu::textures::materialCount); } if (strlen(emu->title)) { @@ -4224,18 +4224,18 @@ namespace UF ob.write((const char*)&subitem_count, sizeof(uint32)); - for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { + for (uint32 index = EQEmu::inventory::containerBegin; index < EQEmu::inventory::ContainerCount; ++index) { EQEmu::ItemInstance* sub = inst->GetItem(index); if (!sub) continue; int SubSlotNumber = INVALID_INDEX; if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) - SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1); + SubSlotNumber = (((slot_id_in + 3) * EQEmu::inventory::ContainerCount) + index + 1); else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END) - SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::inventory::ContainerCount) + EQEmu::legacy::BANK_BAGS_BEGIN + index); else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END) - SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); + SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::inventory::ContainerCount) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index); else SubSlotNumber = slot_id_in; @@ -4253,7 +4253,7 @@ namespace UF { uint32 UnderfootSlot = 0; - if (serverSlot >= EQEmu::legacy::SlotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + if (serverSlot >= EQEmu::inventory::slotAmmo && serverSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots UnderfootSlot = serverSlot + 1; else if (serverSlot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && serverSlot <= EQEmu::legacy::CURSOR_BAG_END) UnderfootSlot = serverSlot + 11; @@ -4261,7 +4261,7 @@ namespace UF UnderfootSlot = serverSlot + 1; else if (serverSlot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && serverSlot <= EQEmu::legacy::SHARED_BANK_BAGS_END) UnderfootSlot = serverSlot + 1; - else if (serverSlot == EQEmu::legacy::SlotPowerSource) + else if (serverSlot == EQEmu::inventory::slotPowerSource) UnderfootSlot = invslot::PossessionsPowerSource; else UnderfootSlot = serverSlot; @@ -4288,7 +4288,7 @@ namespace UF else if (ufSlot >= invbag::SharedBankBagsBegin && ufSlot <= invbag::SharedBankBagsEnd) ServerSlot = ufSlot - 1; else if (ufSlot == invslot::PossessionsPowerSource) - ServerSlot = EQEmu::legacy::SlotPowerSource; + ServerSlot = EQEmu::inventory::slotPowerSource; else ServerSlot = ufSlot; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 7ebedbec5..ec279e56c 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -149,7 +149,7 @@ struct TintProfile Tint_Struct Primary; Tint_Struct Secondary; }; - Tint_Struct Slot[EQEmu::textures::TextureCount]; + Tint_Struct Slot[EQEmu::textures::materialCount]; }; }; @@ -178,7 +178,7 @@ struct TextureProfile Texture_Struct Primary; Texture_Struct Secondary; }; - Texture_Struct Slot[EQEmu::textures::TextureCount]; + Texture_Struct Slot[EQEmu::textures::materialCount]; }; TextureProfile(); @@ -195,7 +195,7 @@ struct CharacterSelectEntry_Struct /*0000*/ uint8 Beard; // /*0001*/ uint8 HairColor; // /*0000*/ uint8 Face; // -/*0000*/ CharSelectEquip Equip[EQEmu::textures::TextureCount]; +/*0000*/ CharSelectEquip Equip[EQEmu::textures::materialCount]; /*0000*/ uint32 PrimaryIDFile; // /*0000*/ uint32 SecondaryIDFile; // /*0000*/ uint8 Unknown15; // 0xff diff --git a/common/shareddb.cpp b/common/shareddb.cpp index d896fba9c..e748a2d56 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -105,7 +105,7 @@ bool SharedDatabase::SaveCursor(uint32 char_id, std::list: std::string query = StringFormat("DELETE FROM inventory WHERE charid = %i " "AND ((slotid >= 8000 AND slotid <= 8999) " "OR slotid = %i OR (slotid >= %i AND slotid <= %i) )", - char_id, EQEmu::legacy::SlotCursor, + char_id, EQEmu::inventory::slotCursor, EQEmu::legacy::CURSOR_BAG_BEGIN, EQEmu::legacy::CURSOR_BAG_END); auto results = QueryDatabase(query); if (!results.Success()) { @@ -117,7 +117,7 @@ bool SharedDatabase::SaveCursor(uint32 char_id, std::list: for(auto it = start; it != end; ++it, i++) { if (i > 8999) { break; } // shouldn't be anything in the queue that indexes this high EQEmu::ItemInstance *inst = *it; - int16 use_slot = (i == 8000) ? EQEmu::legacy::SlotCursor : i; + int16 use_slot = (i == 8000) ? EQEmu::inventory::slotCursor : i; if (!SaveInventory(char_id, inst, use_slot)) { return false; } @@ -192,9 +192,9 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const EQEmu::ItemInstance* in bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQEmu::ItemInstance* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer - uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { 0, 0, 0, 0, 0, 0 }; + uint32 augslot[EQEmu::inventory::SocketCount] = { 0, 0, 0, 0, 0, 0 }; if (inst->IsClassCommon()) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { EQEmu::ItemInstance *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } @@ -224,7 +224,7 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQEmu::ItemInstan if (inst->IsClassBag() && Inventory::SupportsContainers(slot_id)) // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) - for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { + for (uint8 idx = EQEmu::inventory::containerBegin; idx < inst->GetItem()->BagSlots && idx < EQEmu::inventory::ContainerCount; idx++) { const EQEmu::ItemInstance* baginst = inst->GetItem(idx); SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); } @@ -239,9 +239,9 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQEmu::ItemInstan bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const EQEmu::ItemInstance* inst, int16 slot_id) { // need to check 'inst' argument for valid pointer - uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { 0, 0, 0, 0, 0, 0 }; + uint32 augslot[EQEmu::inventory::SocketCount] = { 0, 0, 0, 0, 0, 0 }; if (inst->IsClassCommon()) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { EQEmu::ItemInstance *auginst = inst->GetItem(i); augslot[i] = (auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } @@ -270,7 +270,7 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const EQEmu::ItemInsta if (inst->IsClassBag() && Inventory::SupportsContainers(slot_id)) { // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) - for (uint8 idx = SUB_INDEX_BEGIN; idx < inst->GetItem()->BagSlots && idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { + for (uint8 idx = EQEmu::inventory::containerBegin; idx < inst->GetItem()->BagSlots && idx < EQEmu::inventory::ContainerCount; idx++) { const EQEmu::ItemInstance* baginst = inst->GetItem(idx); SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); } @@ -296,7 +296,7 @@ bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id) { if (!Inventory::SupportsContainers(slot_id)) return true; - int16 base_slot_id = Inventory::CalcSlotId(slot_id, SUB_INDEX_BEGIN); + int16 base_slot_id = Inventory::CalcSlotId(slot_id, EQEmu::inventory::containerBegin); query = StringFormat("DELETE FROM inventory WHERE charid = %i AND slotid >= %i AND slotid < %i", char_id, base_slot_id, (base_slot_id+10)); results = QueryDatabase(query); @@ -322,7 +322,7 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) { if (!Inventory::SupportsContainers(slot_id)) return true; - int16 base_slot_id = Inventory::CalcSlotId(slot_id, SUB_INDEX_BEGIN); + int16 base_slot_id = Inventory::CalcSlotId(slot_id, EQEmu::inventory::containerBegin); query = StringFormat("DELETE FROM sharedbank WHERE acctid = %i " "AND slotid >= %i AND slotid < %i", account_id, base_slot_id, (base_slot_id+10)); @@ -428,7 +428,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) uint32 item_id = (uint32)atoi(row[1]); int8 charges = (int8)atoi(row[2]); - uint32 aug[EQEmu::legacy::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::inventory::SocketCount]; aug[0] = (uint32)atoi(row[3]); aug[1] = (uint32)atoi(row[4]); aug[2] = (uint32)atoi(row[5]); @@ -449,7 +449,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) EQEmu::ItemInstance *inst = CreateBaseItem(item, charges); if (inst && item->IsClassCommon()) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } @@ -524,7 +524,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) uint16 charges = atoi(row[2]); uint32 color = atoul(row[3]); - uint32 aug[EQEmu::legacy::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::inventory::SocketCount]; aug[0] = (uint32)atoul(row[4]); aug[1] = (uint32)atoul(row[5]); @@ -587,7 +587,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) if (instnodrop || (((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || - slot_id == EQEmu::legacy::SlotPowerSource) && + slot_id == EQEmu::inventory::slotPowerSource) && inst->GetItem()->Attuneable)) inst->SetAttuned(true); @@ -609,7 +609,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) } if (item->IsClassCommon()) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } @@ -666,7 +666,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) int8 charges = atoi(row[2]); uint32 color = atoul(row[3]); - uint32 aug[EQEmu::legacy::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::inventory::SocketCount]; aug[0] = (uint32)atoi(row[4]); aug[1] = (uint32)atoi(row[5]); aug[2] = (uint32)atoi(row[6]); @@ -727,7 +727,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) inst->SetCharges(charges); if (item->IsClassCommon()) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { if (aug[i]) inst->PutAugment(this, i, aug[i]); } diff --git a/common/textures.cpp b/common/textures.cpp index 7993ec384..262b4786c 100644 --- a/common/textures.cpp +++ b/common/textures.cpp @@ -18,82 +18,3 @@ */ #include "textures.h" -//#include "inventory_slot.h" - -#include // temp - - -//int EQEmu::textures::ConvertEquipmentSlotToTextureSlot(int equipment_slot) -//{ -// switch (equipment_slot) { -// case inventory::PossessionsHead: -// return textures::TextureHead; -// case inventory::PossessionsChest: -// return textures::TextureChest; -// case inventory::PossessionsArms: -// return textures::TextureArms; -// case inventory::PossessionsWrist1: -// return textures::TextureWrist; -// case inventory::PossessionsHands: -// return textures::TextureHands; -// case inventory::PossessionsLegs: -// return textures::TextureLegs; -// case inventory::PossessionsFeet: -// return textures::TextureFeet; -// case inventory::PossessionsPrimary: -// return textures::TexturePrimary; -// case inventory::PossessionsSecondary: -// return textures::TextureSecondary; -// default: -// return textures::TextureInvalid; -// } -//} - -//int EQEmu::textures::ConvertEquipmentSlotToTextureSlot(const InventorySlot &equipment_slot) -//{ -// if (equipment_slot.Type() != inventory::InvTypePossessions || equipment_slot.Bag() != inventory::InvBagInvalid || equipment_slot.Aug() != inventory::InvAugInvalid) -// return textures::TextureInvalid; -// -// return ConvertEquipmentSlotToTextureSlot(equipment_slot.Slot()); -//} - -//EQEmu::InventorySlot EQEmu::textures::ConvertTextureSlotToEquipmentSlot(int texture_slot) -//{ -// switch (texture_slot) { -// case textures::TextureHead: -// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsHead); -// case textures::TextureChest: -// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsChest); -// case textures::TextureArms: -// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsArms); -// case textures::TextureWrist: -// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsWrist1); -// case textures::TextureHands: -// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsHands); -// case textures::TextureLegs: -// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsLegs); -// case textures::TextureFeet: -// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsFeet); -// case textures::TexturePrimary: -// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsPrimary); -// case textures::TextureSecondary: -// return EQEmu::InventorySlot(inventory::InvTypePossessions, inventory::PossessionsSecondary); -// default: -// return EQEmu::InventorySlot(); -// } -//} - -EQEmu::TextureProfile::TextureProfile() -{ - memset(&Slot, 0, (sizeof(Texture_Struct) * textures::TextureCount)); -} - -EQEmu::TextureShortProfile::TextureShortProfile() -{ - memset(&Slot, 0, (sizeof(uint32) * textures::TextureCount)); -} - -EQEmu::TintProfile::TintProfile() -{ - memset(&Slot, 0, (sizeof(uint32) * textures::TextureCount)); -} diff --git a/common/textures.h b/common/textures.h index a6333a03f..bbf5f71c9 100644 --- a/common/textures.h +++ b/common/textures.h @@ -25,116 +25,129 @@ namespace EQEmu { - //class InventorySlot; - namespace textures { - //enum : int { TextureInvalid = -1, TextureBegin }; - enum : uint8 { TextureInvalid = 255, TextureBegin = 0 }; + enum : int8 { textureInvalid = -1, textureBegin }; - //enum TextureSlot : int { - enum TextureSlot : uint8 { - TextureHead = TextureBegin, - TextureChest, - TextureArms, - TextureWrist, - TextureHands, - TextureLegs, - TextureFeet, - TexturePrimary, - TextureSecondary, - TextureCount + enum TextureSlot : int8 { + armorHead = textureBegin, + armorChest, + armorArms, + armorWrist, + armorHands, + armorLegs, + armorFeet, + weaponPrimary, + weaponSecondary, + materialCount, + materialInvalid = textureInvalid }; - const int LastTexture = TextureSecondary; - const int LastTintableTexture = TextureFeet; + enum TintSlot : int8 { + tintHead = textureBegin, + tintChest, + tintArms, + tintWrist, + tintHands, + tintLegs, + tintFeet, + tintCount, + tintInvalid = textureInvalid + }; - //extern int ConvertEquipmentSlotToTextureSlot(int equipment_slot); - //extern int ConvertEquipmentSlotToTextureSlot(const InventorySlot &equipment_slot); - //extern InventorySlot ConvertTextureSlotToEquipmentSlot(int texture_slot); + const int8 LastTexture = weaponSecondary; + const int8 LastTintableTexture = tintFeet; + + struct Texture_Struct { + union { + struct { + struct { + struct { + uint32 _material; + } _1_field; + + uint32 _unknown1; + uint32 _elite_model; + } _3_fields; + + uint32 _heroic_model; + uint32 _unknown2; + } _5_fields; + + uint32 Material; + uint32 Unknown1; + uint32 EliteModel; + uint32 HeroicModel; + uint32 Unknown2; // same as material? + }; + }; + + struct TextureMaterial_Struct { + uint32 Material; + }; + + struct Tint_Struct { + union { + struct { + uint8 Blue; + uint8 Green; + uint8 Red; + uint8 UseTint; // if there's a tint, this is FF + }; + uint32 Color; + }; + }; } /*textures*/ - struct Texture_Struct { - uint32 Material; - uint32 Unknown1; - uint32 EliteMaterial; - uint32 HeroForgeModel; - uint32 Material2; // Same as material? - }; - struct TextureProfile { union { struct { - Texture_Struct Head; - Texture_Struct Chest; - Texture_Struct Arms; - Texture_Struct Wrist; - Texture_Struct Hands; - Texture_Struct Legs; - Texture_Struct Feet; - Texture_Struct Primary; - Texture_Struct Secondary; + textures::Texture_Struct Head; + textures::Texture_Struct Chest; + textures::Texture_Struct Arms; + textures::Texture_Struct Wrist; + textures::Texture_Struct Hands; + textures::Texture_Struct Legs; + textures::Texture_Struct Feet; + textures::Texture_Struct Primary; + textures::Texture_Struct Secondary; }; - Texture_Struct Slot[textures::TextureCount]; + textures::Texture_Struct Slot[textures::materialCount]; }; - - TextureProfile(); }; - struct TextureShort_Struct { - uint32 Material; - }; - - struct TextureShortProfile { + struct TextureMaterialProfile { union { struct { - TextureShort_Struct Head; - TextureShort_Struct Chest; - TextureShort_Struct Arms; - TextureShort_Struct Wrist; - TextureShort_Struct Hands; - TextureShort_Struct Legs; - TextureShort_Struct Feet; - TextureShort_Struct Primary; - TextureShort_Struct Secondary; + textures::TextureMaterial_Struct Head; + textures::TextureMaterial_Struct Chest; + textures::TextureMaterial_Struct Arms; + textures::TextureMaterial_Struct Wrist; + textures::TextureMaterial_Struct Hands; + textures::TextureMaterial_Struct Legs; + textures::TextureMaterial_Struct Feet; + textures::TextureMaterial_Struct Primary; + textures::TextureMaterial_Struct Secondary; }; - TextureShort_Struct Slot[textures::TextureCount]; + textures::TextureMaterial_Struct Slot[textures::materialCount]; }; - - TextureShortProfile(); - }; - - struct Tint_Struct { - union { - struct { - uint8 Blue; - uint8 Green; - uint8 Red; - uint8 UseTint; // if there's a tint this is FF - }; - uint32 Color; - }; - - //Tint_Struct(); }; struct TintProfile { union { struct { - Tint_Struct Head; - Tint_Struct Chest; - Tint_Struct Arms; - Tint_Struct Wrist; - Tint_Struct Hands; - Tint_Struct Legs; - Tint_Struct Feet; - Tint_Struct Primary; - Tint_Struct Secondary; + textures::Tint_Struct Head; + textures::Tint_Struct Chest; + textures::Tint_Struct Arms; + textures::Tint_Struct Wrist; + textures::Tint_Struct Hands; + textures::Tint_Struct Legs; + textures::Tint_Struct Feet; + textures::Tint_Struct Primary; + textures::Tint_Struct Secondary; }; - Tint_Struct Slot[textures::TextureCount]; + textures::Tint_Struct Slot[textures::materialCount]; // materialCount is correct..but, {[weaponPrimary],[weaponSecondary]} are not tintable... }; - - TintProfile(); }; } /*EQEmu*/ diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 858a84323..0fa814417 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -117,12 +117,12 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou cse->Gender = (uint8)atoi(row[2]); cse->Face = (uint8)atoi(row[15]); - for (uint32 matslot = 0; matslot < EQEmu::textures::TextureCount; matslot++) { // Processed below + for (uint32 matslot = 0; matslot < EQEmu::textures::materialCount; matslot++) { // Processed below cse->Equip[matslot].Material = 0; cse->Equip[matslot].Unknown1 = 0; - cse->Equip[matslot].EliteMaterial = 0; - cse->Equip[matslot].HeroForgeModel = 0; - cse->Equip[matslot].Material2 = 0; + cse->Equip[matslot].EliteModel = 0; + cse->Equip[matslot].HeroicModel = 0; + cse->Equip[matslot].Unknown2 = 0; cse->Equip[matslot].Color = 0; } @@ -249,7 +249,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou const EQEmu::ItemInstance* inst = nullptr; int16 invslot = 0; - for (uint32 matslot = 0; matslot < EQEmu::textures::TextureCount; matslot++) { + for (uint32 matslot = EQEmu::textures::textureBegin; matslot < EQEmu::textures::materialCount; matslot++) { invslot = Inventory::CalcSlotFromMaterial(matslot); if (invslot == INVALID_INDEX) { continue; } inst = inv.GetItem(invslot); @@ -270,7 +270,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou cse->Equip[matslot].Material = idfile; } } - if (matslot == EQEmu::textures::TexturePrimary) { + if (matslot == EQEmu::textures::weaponPrimary) { cse->PrimaryIDFile = idfile; } else { @@ -288,8 +288,8 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou // Armor Materials/Models cse->Equip[matslot].Material = item->Material; - cse->Equip[matslot].EliteMaterial = item->EliteMaterial; - cse->Equip[matslot].HeroForgeModel = inst->GetOrnamentHeroModel(matslot); + cse->Equip[matslot].EliteModel = item->EliteMaterial; + cse->Equip[matslot].HeroicModel = inst->GetOrnamentHeroModel(matslot); cse->Equip[matslot].Color = color; } } diff --git a/zone/attack.cpp b/zone/attack.cpp index 45de2d6b8..475aee7b3 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -132,7 +132,7 @@ bool Mob::AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const } // If we're attacking with the secondary hand, play the dual wield anim - if (Hand == EQEmu::legacy::SlotSecondary) // DW anim + if (Hand == EQEmu::inventory::slotSecondary) // DW anim type = animDualWield; DoAnim(type); @@ -373,7 +373,7 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) // riposte -- it may seem crazy, but if the attacker has SPA 173 on them, they are immune to Ripo bool ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance; // Need to check if we have something in MainHand to actually attack with (or fists) - if (hand != EQEmu::legacy::SlotRange && (CanThisClassRiposte() || IsEnraged()) && InFront && !ImmuneRipo) { + if (hand != EQEmu::inventory::slotRange && (CanThisClassRiposte() || IsEnraged()) && InFront && !ImmuneRipo) { if (IsEnraged()) { damage = -3; Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack."); @@ -395,7 +395,7 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) chance -= chance * counter; } // AA Slippery Attacks - if (hand == EQEmu::legacy::SlotSecondary) { + if (hand == EQEmu::inventory::slotSecondary) { int slip = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail; chance += chance * slip / 100; } @@ -440,7 +440,7 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) } // parry - if (CanThisClassParry() && InFront && hand != EQEmu::legacy::SlotRange) { + if (CanThisClassParry() && InFront && hand != EQEmu::inventory::slotRange) { if (IsClient()) CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillParry, other, -10); // check auto discs ... I guess aa/items too :P @@ -927,7 +927,7 @@ int Mob::GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, u } else { bool MagicGloves = false; if (IsClient()) { - const EQEmu::ItemInstance *gloves = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotHands); + const EQEmu::ItemInstance *gloves = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotHands); if (gloves) MagicGloves = gloves->GetItemMagical(true); } @@ -1036,12 +1036,12 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code. EQEmu::ItemInstance* weapon; - if (Hand == EQEmu::legacy::SlotSecondary){ // Kaiyodo - Pick weapon from the attacking hand - weapon = GetInv().GetItem(EQEmu::legacy::SlotSecondary); + if (Hand == EQEmu::inventory::slotSecondary){ // Kaiyodo - Pick weapon from the attacking hand + weapon = GetInv().GetItem(EQEmu::inventory::slotSecondary); OffHandAtk(true); } else{ - weapon = GetInv().GetItem(EQEmu::legacy::SlotPrimary); + weapon = GetInv().GetItem(EQEmu::inventory::slotPrimary); OffHandAtk(false); } @@ -1109,7 +1109,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b int ucDamageBonus = 0; - if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) + if (Hand == EQEmu::inventory::slotPrimary && GetLevel() >= 28 && IsWarriorClass()) { // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. @@ -1122,7 +1122,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b } #endif //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. - if (Hand == EQEmu::legacy::SlotSecondary) { + if (Hand == EQEmu::inventory::slotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr, true); @@ -1583,28 +1583,28 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool FaceTarget(GetTarget()); EQEmu::skills::SkillType skillinuse = EQEmu::skills::SkillHandtoHand; - if (Hand == EQEmu::legacy::SlotPrimary) { + if (Hand == EQEmu::inventory::slotPrimary) { skillinuse = static_cast(GetPrimSkill()); OffHandAtk(false); } - if (Hand == EQEmu::legacy::SlotSecondary) { + if (Hand == EQEmu::inventory::slotSecondary) { skillinuse = static_cast(GetSecSkill()); OffHandAtk(true); } //figure out what weapon they are using, if any const EQEmu::ItemData* weapon = nullptr; - if (Hand == EQEmu::legacy::SlotPrimary && equipment[EQEmu::legacy::SlotPrimary] > 0) - weapon = database.GetItem(equipment[EQEmu::legacy::SlotPrimary]); - else if (equipment[EQEmu::legacy::SlotSecondary]) - weapon = database.GetItem(equipment[EQEmu::legacy::SlotSecondary]); + if (Hand == EQEmu::inventory::slotPrimary && equipment[EQEmu::inventory::slotPrimary] > 0) + weapon = database.GetItem(equipment[EQEmu::inventory::slotPrimary]); + else if (equipment[EQEmu::inventory::slotSecondary]) + weapon = database.GetItem(equipment[EQEmu::inventory::slotSecondary]); //We dont factor much from the weapon into the attack. //Just the skill type so it doesn't look silly using punching animations and stuff while wielding weapons if(weapon) { Log.Out(Logs::Detail, Logs::Combat, "Attacking with weapon: %s (%d) (too bad im not using it for much)", weapon->Name, weapon->ID); - if (Hand == EQEmu::legacy::SlotSecondary && weapon->ItemType == EQEmu::item::ItemTypeShield){ + if (Hand == EQEmu::inventory::slotSecondary && weapon->ItemType == EQEmu::item::ItemTypeShield){ Log.Out(Logs::Detail, Logs::Combat, "Attack with shield canceled."); return false; } @@ -3501,7 +3501,7 @@ void Mob::TryDefensiveProc(Mob *on, uint16 hand) { float ProcChance, ProcBonus; on->GetDefensiveProcChances(ProcBonus, ProcChance, hand , this); - if (hand != EQEmu::legacy::SlotPrimary) + if (hand != EQEmu::inventory::slotPrimary) ProcChance /= 2; int level_penalty = 0; @@ -3574,7 +3574,7 @@ void Mob::TryWeaponProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData * ProcBonus += static_cast(itembonuses.ProcChance) / 10.0f; // Combat Effects float ProcChance = GetProcChances(ProcBonus, hand); - if (hand != EQEmu::legacy::SlotPrimary) //Is Archery intened to proc at 50% rate? + if (hand != EQEmu::inventory::slotPrimary) //Is Archery intened to proc at 50% rate? ProcChance /= 2; // Try innate proc on weapon @@ -3611,7 +3611,7 @@ void Mob::TryWeaponProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData * proced = false; if (!proced && inst) { - for (int r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { + for (int r = EQEmu::inventory::socketBegin; r < EQEmu::inventory::SocketCount; r++) { const EQEmu::ItemInstance *aug_i = inst->GetAugment(r); if (!aug_i) // no aug, try next slot! continue; @@ -3652,11 +3652,11 @@ void Mob::TrySpellProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *w float ProcChance = 0.0f; ProcChance = GetProcChances(ProcBonus, hand); - if (hand != EQEmu::legacy::SlotPrimary) //Is Archery intened to proc at 50% rate? + if (hand != EQEmu::inventory::slotPrimary) //Is Archery intened to proc at 50% rate? ProcChance /= 2; bool rangedattk = false; - if (weapon && hand == EQEmu::legacy::SlotRange) { + if (weapon && hand == EQEmu::inventory::slotRange) { if (weapon->ItemType == EQEmu::item::ItemTypeArrow || weapon->ItemType == EQEmu::item::ItemTypeLargeThrowing || weapon->ItemType == EQEmu::item::ItemTypeSmallThrowing || @@ -3665,11 +3665,11 @@ void Mob::TrySpellProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *w } } - if (!weapon && hand == EQEmu::legacy::SlotRange && GetSpecialAbility(SPECATK_RANGED_ATK)) + if (!weapon && hand == EQEmu::inventory::slotRange && GetSpecialAbility(SPECATK_RANGED_ATK)) rangedattk = true; for (uint32 i = 0; i < MAX_PROCS; i++) { - if (IsPet() && hand != EQEmu::legacy::SlotPrimary) //Pets can only proc spell procs from their primay hand (ie; beastlord pets) + if (IsPet() && hand != EQEmu::inventory::slotPrimary) //Pets can only proc spell procs from their primay hand (ie; beastlord pets) continue; // If pets ever can proc from off hand, this will need to change // Not ranged @@ -3732,7 +3732,7 @@ void Mob::TrySpellProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *w } } - if (HasSkillProcs() && hand != EQEmu::legacy::SlotRange){ //We check ranged skill procs within the attack functions. + if (HasSkillProcs() && hand != EQEmu::inventory::slotRange){ //We check ranged skill procs within the attack functions. uint16 skillinuse = 28; if (weapon) skillinuse = GetSkillByItemType(weapon->ItemType); @@ -3980,7 +3980,7 @@ void Mob::DoRiposte(Mob *defender) if (!defender) return; - defender->Attack(this, EQEmu::legacy::SlotPrimary, true); + defender->Attack(this, EQEmu::inventory::slotPrimary, true); if (HasDied()) return; @@ -3991,7 +3991,7 @@ void Mob::DoRiposte(Mob *defender) if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) { Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposted from SE_DoubleRiposte (%d percent chance)", DoubleRipChance); - defender->Attack(this, EQEmu::legacy::SlotPrimary, true); + defender->Attack(this, EQEmu::inventory::slotPrimary, true); if (HasDied()) return; } @@ -4004,7 +4004,7 @@ void Mob::DoRiposte(Mob *defender) Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposted from SE_GiveDoubleRiposte base1 == 0 (%d percent chance)", DoubleRipChance); - defender->Attack(this, EQEmu::legacy::SlotPrimary, true); + defender->Attack(this, EQEmu::inventory::slotPrimary, true); if (HasDied()) return; } @@ -4288,7 +4288,7 @@ float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) { if (!ReuseTime && hand) { weapon_speed = GetWeaponSpeedbyHand(hand); ProcChance = static_cast(weapon_speed) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f); - if (hand != EQEmu::legacy::SlotPrimary) + if (hand != EQEmu::inventory::slotPrimary) ProcChance /= 2; } @@ -4478,13 +4478,13 @@ void Client::SetAttackTimer() Timer *TimerToUse = nullptr; - for (int i = EQEmu::legacy::SlotRange; i <= EQEmu::legacy::SlotSecondary; i++) { + for (int i = EQEmu::inventory::slotRange; i <= EQEmu::inventory::slotSecondary; i++) { //pick a timer - if (i == EQEmu::legacy::SlotPrimary) + if (i == EQEmu::inventory::slotPrimary) TimerToUse = &attack_timer; - else if (i == EQEmu::legacy::SlotRange) + else if (i == EQEmu::inventory::slotRange) TimerToUse = &ranged_timer; - else if (i == EQEmu::legacy::SlotSecondary) + else if (i == EQEmu::inventory::slotSecondary) TimerToUse = &attack_dw_timer; else //invalid slot (hands will always hit this) continue; @@ -4497,7 +4497,7 @@ void Client::SetAttackTimer() ItemToUse = ci->GetItem(); //special offhand stuff - if (i == EQEmu::legacy::SlotSecondary) { + if (i == EQEmu::inventory::slotSecondary) { //if we cant dual wield, skip it if (!CanThisClassDualWield() || HasTwoHanderEquipped()) { attack_dw_timer.Disable(); @@ -4571,19 +4571,19 @@ void NPC::SetAttackTimer() else speed = static_cast(((attack_delay / haste_mod) + ((hhe / 100.0f) * attack_delay)) * 100); - for (int i = EQEmu::legacy::SlotRange; i <= EQEmu::legacy::SlotSecondary; i++) { + for (int i = EQEmu::inventory::slotRange; i <= EQEmu::inventory::slotSecondary; i++) { //pick a timer - if (i == EQEmu::legacy::SlotPrimary) + if (i == EQEmu::inventory::slotPrimary) TimerToUse = &attack_timer; - else if (i == EQEmu::legacy::SlotRange) + else if (i == EQEmu::inventory::slotRange) TimerToUse = &ranged_timer; - else if (i == EQEmu::legacy::SlotSecondary) + else if (i == EQEmu::inventory::slotSecondary) TimerToUse = &attack_dw_timer; else //invalid slot (hands will always hit this) continue; //special offhand stuff - if (i == EQEmu::legacy::SlotSecondary) { + if (i == EQEmu::inventory::slotSecondary) { // SPECATK_QUAD is uncheesable if(!CanThisClassDualWield() || (HasTwoHanderEquipped() && !GetSpecialAbility(SPECATK_QUAD))) { attack_dw_timer.Disable(); @@ -4605,7 +4605,7 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) bool candouble = CanThisClassDoubleAttack(); // extra off hand non-sense, can only double with skill of 150 or above // or you have any amount of GiveDoubleAttack - if (candouble && hand == EQEmu::legacy::SlotSecondary) + if (candouble && hand == EQEmu::inventory::slotSecondary) candouble = GetSkill(EQEmu::skills::SkillDoubleAttack) > 149 || (aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack) > 0; if (candouble) { @@ -4613,7 +4613,7 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) if (CheckDoubleAttack()) { Attack(target, hand, false, false, IsFromSpell); // you can only triple from the main hand - if (hand == EQEmu::legacy::SlotPrimary && CanThisClassTripleAttack()) { + if (hand == EQEmu::inventory::slotPrimary && CanThisClassTripleAttack()) { CheckIncreaseSkill(EQEmu::skills::SkillTripleAttack, target, -10); if (CheckTripleAttack()) Attack(target, hand, false, false, IsFromSpell); @@ -4621,7 +4621,7 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) } } - if (hand == EQEmu::legacy::SlotPrimary) { + if (hand == EQEmu::inventory::slotPrimary) { // According to http://www.monkly-business.net/forums/showpost.php?p=312095&postcount=168 a dev told them flurry isn't dependant on triple attack // the parses kind of back that up and all of my parses seemed to be 4 or 5 attacks in the round which would work out to be // doubles or triples with 2 from flurries or triple with 1 or 2 flurries ... Going with the "dev quote" I guess like we've always had it @@ -4674,9 +4674,9 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec if (RuleB(Combat, UseLiveCombatRounds)) { // A "quad" on live really is just a successful dual wield where both double attack // The mobs that could triple lost the ability to when the triple attack skill was added in - Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); if (CanThisClassDoubleAttack() && CheckDoubleAttack()){ - Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ int chance = spellbonuses.PC_Pet_Flurry + itembonuses.PC_Pet_Flurry + aabonuses.PC_Pet_Flurry; @@ -4690,14 +4690,14 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec if (IsNPC()) { int16 n_atk = CastToNPC()->GetNumberOfAttacks(); if (n_atk <= 1) { - Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); } else { for (int i = 0; i < n_atk; ++i) { - Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); } } } else { - Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); } // we use this random value in three comparisons with different @@ -4708,15 +4708,15 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec // check double attack, this is NOT the same rules that clients use... && RandRoll < (GetLevel() + NPCDualAttackModifier)) { - Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); // lets see if we can do a triple attack with the main hand // pets are excluded from triple and quads... if ((GetSpecialAbility(SPECATK_TRIPLE) || GetSpecialAbility(SPECATK_QUAD)) && !IsPet() && RandRoll < (GetLevel() + NPCTripleAttackModifier)) { - Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); // now lets check the quad attack if (GetSpecialAbility(SPECATK_QUAD) && RandRoll < (GetLevel() + NPCQuadAttackModifier)) { - Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); } } } @@ -4730,11 +4730,11 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int speci // For now, SPECATK_QUAD means innate DW when Combat:UseLiveCombatRounds is true if ((GetSpecialAbility(SPECATK_INNATE_DW) || (RuleB(Combat, UseLiveCombatRounds) && GetSpecialAbility(SPECATK_QUAD))) || - GetEquipment(EQEmu::textures::TextureSecondary) != 0) { + GetEquipment(EQEmu::textures::weaponSecondary) != 0) { if (CheckDualWield()) { - Attack(target, EQEmu::legacy::SlotSecondary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotSecondary, false, false, false, opts, special); if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()){ - Attack(target, EQEmu::legacy::SlotSecondary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotSecondary, false, false, false, opts, special); if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ int chance = spellbonuses.PC_Pet_Flurry + itembonuses.PC_Pet_Flurry + aabonuses.PC_Pet_Flurry; diff --git a/zone/beacon.h b/zone/beacon.h index 398c9680e..cd66269bb 100644 --- a/zone/beacon.h +++ b/zone/beacon.h @@ -36,7 +36,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; } virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } - virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 240643934..4ff4fbabe 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -145,28 +145,28 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { unsigned int i; // Update: MainAmmo should only calc skill mods (TODO: Check for other cases) - for (i = EQEmu::legacy::SlotCharm; i <= EQEmu::legacy::SlotAmmo; i++) { + for (i = EQEmu::inventory::slotCharm; i <= EQEmu::inventory::slotAmmo; i++) { const EQEmu::ItemInstance* inst = m_inv[i]; if(inst == 0) continue; - AddItemBonuses(inst, newbon, false, false, 0, (i == EQEmu::legacy::SlotAmmo)); + AddItemBonuses(inst, newbon, false, false, 0, (i == EQEmu::inventory::slotAmmo)); //These are given special flags due to how often they are checked for various spell effects. const EQEmu::ItemData *item = inst->GetItem(); - if (i == EQEmu::legacy::SlotSecondary && (item && item->ItemType == EQEmu::item::ItemTypeShield)) + if (i == EQEmu::inventory::slotSecondary && (item && item->ItemType == EQEmu::item::ItemTypeShield)) SetShieldEquiped(true); - else if (i == EQEmu::legacy::SlotPrimary && (item && item->ItemType == EQEmu::item::ItemType2HBlunt)) { + else if (i == EQEmu::inventory::slotPrimary && (item && item->ItemType == EQEmu::item::ItemType2HBlunt)) { SetTwoHandBluntEquiped(true); SetTwoHanderEquipped(true); } - else if (i == EQEmu::legacy::SlotPrimary && (item && (item->ItemType == EQEmu::item::ItemType2HSlash || item->ItemType == EQEmu::item::ItemType2HPiercing))) + else if (i == EQEmu::inventory::slotPrimary && (item && (item->ItemType == EQEmu::item::ItemType2HSlash || item->ItemType == EQEmu::item::ItemType2HPiercing))) SetTwoHanderEquipped(true); } //Power Source Slot if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - const EQEmu::ItemInstance* inst = m_inv[EQEmu::legacy::SlotPowerSource]; + const EQEmu::ItemInstance* inst = m_inv[EQEmu::inventory::slotPowerSource]; if(inst) AddItemBonuses(inst, newbon); } @@ -181,7 +181,7 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { //Optional ability to have worn effects calculate as an addititive bonus instead of highest value if (RuleI(Spells, AdditiveBonusWornType) && RuleI(Spells, AdditiveBonusWornType) != EQEmu::item::ItemEffectWorn){ - for (i = EQEmu::legacy::SlotCharm; i < EQEmu::legacy::SlotAmmo; i++) { + for (i = EQEmu::inventory::slotCharm; i < EQEmu::inventory::slotAmmo; i++) { const EQEmu::ItemInstance* inst = m_inv[i]; if(inst == 0) continue; @@ -527,7 +527,7 @@ void Client::AddItemBonuses(const EQEmu::ItemInstance *inst, StatBonuses *newbon } if (!isAug) { - for (int i = 0; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) AddItemBonuses(inst->GetAugment(i), newbon, true, false, rec_level, ammo_slot_item); } } @@ -565,7 +565,7 @@ void Client::AdditiveWornBonuses(const EQEmu::ItemInstance *inst, StatBonuses* n if (!isAug) { int i; - for (i = 0; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { + for (i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { AdditiveWornBonuses(inst->GetAugment(i),newbon,true); } } @@ -3299,7 +3299,7 @@ void Client::CalcItemScale() { //Power Source Slot if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - if (CalcItemScale(EQEmu::legacy::SlotPowerSource, EQEmu::legacy::SlotPowerSource)) + if (CalcItemScale(EQEmu::inventory::slotPowerSource, EQEmu::inventory::slotPowerSource)) changed = true; } @@ -3314,7 +3314,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { bool changed = false; uint32 i; for (i = slot_x; i <= slot_y; i++) { - if (i == EQEmu::legacy::SlotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot + if (i == EQEmu::inventory::slotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot continue; EQEmu::ItemInstance* inst = m_inv.GetItem(i); @@ -3344,7 +3344,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { } //iterate all augments - for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) + for (int x = EQEmu::inventory::socketBegin; x < EQEmu::inventory::SocketCount; ++x) { EQEmu::ItemInstance * a_inst = inst->GetAugment(x); if(!a_inst) @@ -3393,7 +3393,7 @@ void Client::DoItemEnterZone() { //Power Source Slot if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - if (DoItemEnterZone(EQEmu::legacy::SlotPowerSource, EQEmu::legacy::SlotPowerSource)) + if (DoItemEnterZone(EQEmu::inventory::slotPowerSource, EQEmu::inventory::slotPowerSource)) changed = true; } @@ -3407,7 +3407,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { // behavior change: 'slot_y' is now [RANGE]_END and not [RANGE]_END + 1 bool changed = false; for(uint32 i = slot_x; i <= slot_y; i++) { - if (i == EQEmu::legacy::SlotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot + if (i == EQEmu::inventory::slotAmmo) // moved here from calling procedure to facilitate future range changes where MainAmmo may not be the last slot continue; EQEmu::ItemInstance* inst = m_inv.GetItem(i); @@ -3429,7 +3429,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { uint16 oldexp = inst->GetExp(); parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, inst, nullptr, "", 0); - if (i <= EQEmu::legacy::SlotAmmo || i == EQEmu::legacy::SlotPowerSource) { + if (i <= EQEmu::inventory::slotAmmo || i == EQEmu::inventory::slotPowerSource) { parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); } @@ -3439,7 +3439,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { update_slot = true; } } else { - if (i <= EQEmu::legacy::SlotAmmo || i == EQEmu::legacy::SlotPowerSource) { + if (i <= EQEmu::inventory::slotAmmo || i == EQEmu::inventory::slotPowerSource) { parse->EventItem(EVENT_EQUIP_ITEM, this, inst, nullptr, "", i); } @@ -3447,7 +3447,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { } //iterate all augments - for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) + for (int x = EQEmu::inventory::socketBegin; x < EQEmu::inventory::SocketCount; ++x) { EQEmu::ItemInstance *a_inst = inst->GetAugment(x); if(!a_inst) diff --git a/zone/bot.cpp b/zone/bot.cpp index 072f99bcd..03ba04dfd 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -229,8 +229,8 @@ void Bot::SetBotSpellID(uint32 newSpellID) { } uint32 Bot::GetBotArcheryRange() { - const EQEmu::ItemInstance *range_inst = GetBotItem(EQEmu::legacy::SlotRange); - const EQEmu::ItemInstance *ammo_inst = GetBotItem(EQEmu::legacy::SlotAmmo); + const EQEmu::ItemInstance *range_inst = GetBotItem(EQEmu::inventory::slotRange); + const EQEmu::ItemInstance *ammo_inst = GetBotItem(EQEmu::inventory::slotAmmo); if (!range_inst || !ammo_inst) return 0; @@ -246,15 +246,15 @@ uint32 Bot::GetBotArcheryRange() { void Bot::ChangeBotArcherWeapons(bool isArcher) { if((GetClass()==WARRIOR) || (GetClass()==PALADIN) || (GetClass()==RANGER) || (GetClass()==SHADOWKNIGHT) || (GetClass()==ROGUE)) { if(!isArcher) { - BotAddEquipItem(EQEmu::legacy::SlotPrimary, GetBotItemBySlot(EQEmu::legacy::SlotPrimary)); - BotAddEquipItem(EQEmu::legacy::SlotSecondary, GetBotItemBySlot(EQEmu::legacy::SlotSecondary)); + BotAddEquipItem(EQEmu::inventory::slotPrimary, GetBotItemBySlot(EQEmu::inventory::slotPrimary)); + BotAddEquipItem(EQEmu::inventory::slotSecondary, GetBotItemBySlot(EQEmu::inventory::slotSecondary)); SetAttackTimer(); BotGroupSay(this, "My blade is ready"); } else { - BotRemoveEquipItem(EQEmu::legacy::SlotPrimary); - BotRemoveEquipItem(EQEmu::legacy::SlotSecondary); - BotAddEquipItem(EQEmu::legacy::SlotAmmo, GetBotItemBySlot(EQEmu::legacy::SlotAmmo)); - BotAddEquipItem(EQEmu::legacy::SlotSecondary, GetBotItemBySlot(EQEmu::legacy::SlotRange)); + BotRemoveEquipItem(EQEmu::inventory::slotPrimary); + BotRemoveEquipItem(EQEmu::inventory::slotSecondary); + BotAddEquipItem(EQEmu::inventory::slotAmmo, GetBotItemBySlot(EQEmu::inventory::slotAmmo)); + BotAddEquipItem(EQEmu::inventory::slotSecondary, GetBotItemBySlot(EQEmu::inventory::slotRange)); SetAttackTimer(); BotGroupSay(this, "My bow is true and ready"); } @@ -1175,11 +1175,11 @@ void Bot::GenerateArmorClass() { uint16 Bot::GetPrimarySkillValue() { EQEmu::skills::SkillType skill = EQEmu::skills::HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill - bool equiped = m_inv.GetItem(EQEmu::legacy::SlotPrimary); + bool equiped = m_inv.GetItem(EQEmu::inventory::slotPrimary); if(!equiped) skill = EQEmu::skills::SkillHandtoHand; else { - uint8 type = m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType; //is this the best way to do this? + uint8 type = m_inv.GetItem(EQEmu::inventory::slotPrimary)->GetItem()->ItemType; //is this the best way to do this? switch(type) { case EQEmu::item::ItemType1HSlash: skill = EQEmu::skills::Skill1HSlashing; @@ -1900,12 +1900,12 @@ void Bot::BotRangedAttack(Mob* other) { return; } - EQEmu::ItemInstance* rangedItem = GetBotItem(EQEmu::legacy::SlotRange); + EQEmu::ItemInstance* rangedItem = GetBotItem(EQEmu::inventory::slotRange); const EQEmu::ItemData* RangeWeapon = 0; if(rangedItem) RangeWeapon = rangedItem->GetItem(); - EQEmu::ItemInstance* ammoItem = GetBotItem(EQEmu::legacy::SlotAmmo); + EQEmu::ItemInstance* ammoItem = GetBotItem(EQEmu::inventory::slotAmmo); const EQEmu::ItemData* Ammo = 0; if(ammoItem) Ammo = ammoItem->GetItem(); @@ -2002,7 +2002,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: int damage = 0; uint32 hate = 0; - int Hand = EQEmu::legacy::SlotPrimary; + int Hand = EQEmu::inventory::slotPrimary; if (hate == 0 && weapon_damage > 1) hate = weapon_damage; @@ -2031,7 +2031,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: else damage = zone->random.Int(min_hit, max_hit); - if (other->AvoidDamage(this, damage, CanRiposte ? EQEmu::legacy::SlotRange : EQEmu::legacy::SlotPrimary)) { // MainRange excludes ripo, primary doesn't have any extra behavior + if (other->AvoidDamage(this, damage, CanRiposte ? EQEmu::inventory::slotRange : EQEmu::inventory::slotPrimary)) { // MainRange excludes ripo, primary doesn't have any extra behavior if (damage == -3) { DoRiposte(other); if (HasDied()) @@ -2056,7 +2056,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: damage = -5; if (skillinuse == EQEmu::skills::SkillBash){ - const EQEmu::ItemInstance* inst = GetBotItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemInstance* inst = GetBotItem(EQEmu::inventory::slotSecondary); const EQEmu::ItemData* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -2103,15 +2103,15 @@ void Bot::ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int3 case EQEmu::skills::SkillFlyingKick: case EQEmu::skills::SkillRoundKick: case EQEmu::skills::SkillKick: - item_slot = EQEmu::legacy::SlotFeet; + item_slot = EQEmu::inventory::slotFeet; break; case EQEmu::skills::SkillBash: - item_slot = EQEmu::legacy::SlotSecondary; + item_slot = EQEmu::inventory::slotSecondary; break; case EQEmu::skills::SkillDragonPunch: case EQEmu::skills::SkillEagleStrike: case EQEmu::skills::SkillTigerClaw: - item_slot = EQEmu::legacy::SlotHands; + item_slot = EQEmu::inventory::slotHands; break; } @@ -2449,23 +2449,23 @@ void Bot::AI_Process() { // First, special attack per class (kick, backstab etc..) DoClassAttacks(GetTarget()); if(attack_timer.Check()) { - Attack(GetTarget(), EQEmu::legacy::SlotPrimary); - TriggerDefensiveProcs(GetTarget(), EQEmu::legacy::SlotPrimary, false); - EQEmu::ItemInstance *wpn = GetBotItem(EQEmu::legacy::SlotPrimary); - TryWeaponProc(wpn, GetTarget(), EQEmu::legacy::SlotPrimary); + Attack(GetTarget(), EQEmu::inventory::slotPrimary); + TriggerDefensiveProcs(GetTarget(), EQEmu::inventory::slotPrimary, false); + EQEmu::ItemInstance *wpn = GetBotItem(EQEmu::inventory::slotPrimary); + TryWeaponProc(wpn, GetTarget(), EQEmu::inventory::slotPrimary); bool tripleSuccess = false; if(BotOwner && GetTarget() && CanThisClassDoubleAttack()) { if(BotOwner && CheckBotDoubleAttack()) - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, true); if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_TRIPLE) && CheckBotDoubleAttack(true)) { tripleSuccess = true; - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, true); } //quad attack, does this belong here?? if(BotOwner && GetTarget() && GetSpecialAbility(SPECATK_QUAD) && CheckBotDoubleAttack(true)) - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, true); } //Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack). @@ -2473,18 +2473,18 @@ void Bot::AI_Process() { if (GetTarget() && flurrychance) { if(zone->random.Int(0, 100) < flurrychance) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, false); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, false); } } int32 ExtraAttackChanceBonus = (spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance); if (GetTarget() && ExtraAttackChanceBonus) { - EQEmu::ItemInstance *wpn = GetBotItem(EQEmu::legacy::SlotPrimary); + EQEmu::ItemInstance *wpn = GetBotItem(EQEmu::inventory::slotPrimary); if(wpn) { if (wpn->GetItem()->IsType2HWeapon()) { if(zone->random.Int(0, 100) < ExtraAttackChanceBonus) - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, false); } } } @@ -2504,7 +2504,7 @@ void Bot::AI_Process() { //now off hand if(GetTarget() && attack_dw_timer.Check() && CanThisClassDualWield()) { - const EQEmu::ItemInstance* instweapon = GetBotItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemInstance* instweapon = GetBotItem(EQEmu::inventory::slotSecondary); const EQEmu::ItemData* weapon = 0; //can only dual wield without a weapon if you're a monk if(instweapon || (botClass == MONK)) { @@ -2526,12 +2526,12 @@ void Bot::AI_Process() { DualWieldProbability += (DualWieldProbability * float(DWBonus) / 100.0f); float random = zone->random.Real(0, 1); if (random < DualWieldProbability){ // Max 78% of DW - Attack(GetTarget(), EQEmu::legacy::SlotSecondary); // Single attack with offhand - EQEmu::ItemInstance *wpn = GetBotItem(EQEmu::legacy::SlotSecondary); - TryWeaponProc(wpn, GetTarget(), EQEmu::legacy::SlotSecondary); + Attack(GetTarget(), EQEmu::inventory::slotSecondary); // Single attack with offhand + EQEmu::ItemInstance *wpn = GetBotItem(EQEmu::inventory::slotSecondary); + TryWeaponProc(wpn, GetTarget(), EQEmu::inventory::slotSecondary); if( CanThisClassDoubleAttack() && CheckBotDoubleAttack()) { if(GetTarget() && GetTarget()->GetHP() > -10) - Attack(GetTarget(), EQEmu::legacy::SlotSecondary); // Single attack with offhand + Attack(GetTarget(), EQEmu::inventory::slotSecondary); // Single attack with offhand } } } @@ -2702,12 +2702,12 @@ void Bot::PetAIProcess() { if(!botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY()) && botPet->GetTarget()->IsEnraged()) return; - if (botPet->Attack(GetTarget(), EQEmu::legacy::SlotPrimary)) // try the main hand + if (botPet->Attack(GetTarget(), EQEmu::inventory::slotPrimary)) // try the main hand if (botPet->GetTarget()) { // We're a pet so we re able to dual attack int32 RandRoll = zone->random.Int(0, 99); if (botPet->CanThisClassDoubleAttack() && (RandRoll < (botPet->GetLevel() + NPCDualAttackModifier))) { - if (botPet->Attack(botPet->GetTarget(), EQEmu::legacy::SlotPrimary)) {} + if (botPet->Attack(botPet->GetTarget(), EQEmu::inventory::slotPrimary)) {} } } @@ -2745,11 +2745,11 @@ void Bot::PetAIProcess() { float DualWieldProbability = ((botPet->GetSkill(EQEmu::skills::SkillDualWield) + botPet->GetLevel()) / 400.0f); DualWieldProbability -= zone->random.Real(0, 1); if(DualWieldProbability < 0) { - botPet->Attack(botPet->GetTarget(), EQEmu::legacy::SlotSecondary); + botPet->Attack(botPet->GetTarget(), EQEmu::inventory::slotSecondary); if (botPet->CanThisClassDoubleAttack()) { int32 RandRoll = zone->random.Int(0, 99); if (RandRoll < (botPet->GetLevel() + 20)) - botPet->Attack(botPet->GetTarget(), EQEmu::legacy::SlotSecondary); + botPet->Attack(botPet->GetTarget(), EQEmu::inventory::slotSecondary); } } } @@ -2956,14 +2956,14 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { const EQEmu::ItemInstance* inst = 0; uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); - for (int i = 0; i < EQEmu::textures::TexturePrimary; i++) { + for (int i = EQEmu::textures::textureBegin; i < EQEmu::textures::weaponPrimary; i++) { inst = GetBotItem(i); if (inst) { item = inst->GetItem(); if (item != 0) { ns->spawn.equipment.Slot[i].Material = item->Material; - ns->spawn.equipment.Slot[i].EliteMaterial = item->EliteMaterial; - ns->spawn.equipment.Slot[i].HeroForgeModel = item->HerosForgeModel; + ns->spawn.equipment.Slot[i].EliteModel = item->EliteMaterial; + ns->spawn.equipment.Slot[i].HeroicModel = item->HerosForgeModel; if (armor_tint.Slot[i].Color) ns->spawn.equipment_tint.Slot[i].Color = armor_tint.Slot[i].Color; else @@ -2975,25 +2975,25 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { } } - inst = GetBotItem(EQEmu::legacy::SlotPrimary); + inst = GetBotItem(EQEmu::inventory::slotPrimary); if(inst) { item = inst->GetItem(); if(item) { if(strlen(item->IDFile) > 2) ns->spawn.equipment.Primary.Material = atoi(&item->IDFile[2]); - ns->spawn.equipment_tint.Primary.Color = GetEquipmentColor(EQEmu::textures::TexturePrimary); + ns->spawn.equipment_tint.Primary.Color = GetEquipmentColor(EQEmu::textures::weaponPrimary); } } - inst = GetBotItem(EQEmu::legacy::SlotSecondary); + inst = GetBotItem(EQEmu::inventory::slotSecondary); if(inst) { item = inst->GetItem(); if(item) { if(strlen(item->IDFile) > 2) ns->spawn.equipment.Secondary.Material = atoi(&item->IDFile[2]); - ns->spawn.equipment_tint.Secondary.Color = GetEquipmentColor(EQEmu::textures::TextureSecondary); + ns->spawn.equipment_tint.Secondary.Color = GetEquipmentColor(EQEmu::textures::weaponSecondary); } } } @@ -3237,7 +3237,7 @@ void Bot::BotAddEquipItem(int slot, uint32 id) { if(slot > 0 && id > 0) { uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); - if (materialFromSlot != EQEmu::textures::TextureInvalid) { + if (materialFromSlot != EQEmu::textures::materialInvalid) { equipment[slot] = id; // npc has more than just material slots. Valid material should mean valid inventory index SendWearChange(materialFromSlot); } @@ -3253,11 +3253,11 @@ void Bot::BotRemoveEquipItem(int slot) { if(slot > 0) { uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); - if (materialFromSlot != EQEmu::textures::TextureInvalid) { + if (materialFromSlot != EQEmu::textures::materialInvalid) { equipment[slot] = 0; // npc has more than just material slots. Valid material should mean valid inventory index SendWearChange(materialFromSlot); - if (materialFromSlot == EQEmu::textures::TextureChest) - SendWearChange(EQEmu::textures::TextureArms); + if (materialFromSlot == EQEmu::textures::armorChest) + SendWearChange(EQEmu::textures::armorArms); } UpdateEquipmentLight(); @@ -3360,7 +3360,7 @@ void Bot::FinishTrade(Client* client, BotTradeType tradeType) { else if(tradeType == BotTradeClientNoDropNoTrade) { // Items being traded are found on the Client's cursor slot, slot id 30. This item can be either a single item or it can be a bag. // If it is a bag, then we have to search for items in slots 331 thru 340 - PerformTradeWithClient(EQEmu::legacy::SlotCursor, EQEmu::legacy::SlotCursor, client); + PerformTradeWithClient(EQEmu::inventory::slotCursor, EQEmu::inventory::slotCursor, client); // TODO: Add logic here to test if the item in SLOT_CURSOR is a container type, if it is then we need to call the following: // PerformTradeWithClient(331, 340, client); @@ -3389,7 +3389,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli charges[i] = inst->GetCharges(); } - if (i == EQEmu::legacy::SlotCursor) + if (i == EQEmu::inventory::slotCursor) UpdateClient = true; //EQoffline: will give the items to the bots and change the bot stats @@ -3397,7 +3397,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli std::string TempErrorMessage; const EQEmu::ItemData* mWeaponItem = inst->GetItem(); bool failedLoreCheck = false; - for (int m = AUG_INDEX_BEGIN; m < EQEmu::legacy::ITEM_COMMON_SIZE; ++m) { + for (int m = EQEmu::inventory::socketBegin; m < EQEmu::inventory::SocketCount; ++m) { EQEmu::ItemInstance *itm = inst->GetAugment(m); if(itm) { @@ -3429,17 +3429,17 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli how_many_slots++; if(!GetBotItem(j)) { - if (j == EQEmu::legacy::SlotPrimary) { + if (j == EQEmu::inventory::slotPrimary) { if (mWeaponItem->IsType2HWeapon()) { - if (GetBotItem(EQEmu::legacy::SlotSecondary)) { + if (GetBotItem(EQEmu::inventory::slotSecondary)) { if (mWeaponItem && mWeaponItem->IsType2HWeapon()) { - if (client->CheckLoreConflict(GetBotItem(EQEmu::legacy::SlotSecondary)->GetItem())) { + if (client->CheckLoreConflict(GetBotItem(EQEmu::inventory::slotSecondary)->GetItem())) { failedLoreCheck = true; } } else { - EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::legacy::SlotSecondary); - BotTradeSwapItem(client, EQEmu::legacy::SlotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::inventory::slotSecondary); + BotTradeSwapItem(client, EQEmu::inventory::slotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } } @@ -3449,7 +3449,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } break; } - else if (j == EQEmu::legacy::SlotSecondary) { + else if (j == EQEmu::inventory::slotSecondary) { if(inst->IsWeapon()) { if(CanThisClassDualWield()) { BotTradeAddItem(mWeaponItem->ID, inst, inst->GetCharges(), mWeaponItem->Slots, j, &TempErrorMessage); @@ -3465,10 +3465,10 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli success = true; } if(success) { - if (GetBotItem(EQEmu::legacy::SlotPrimary)) { - EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::legacy::SlotPrimary); + if (GetBotItem(EQEmu::inventory::slotPrimary)) { + EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::inventory::slotPrimary); if (remove_item->GetItem()->IsType2HWeapon()) { - BotTradeSwapItem(client, EQEmu::legacy::SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + BotTradeSwapItem(client, EQEmu::inventory::slotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } break; @@ -3490,7 +3490,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli swap_item = GetBotItem(j); failedLoreCheck = false; - for (int k = AUG_INDEX_BEGIN; k < EQEmu::legacy::ITEM_COMMON_SIZE; ++k) { + for (int k = EQEmu::inventory::socketBegin; k < EQEmu::inventory::SocketCount; ++k) { EQEmu::ItemInstance *itm = swap_item->GetAugment(k); if(itm) { @@ -3503,28 +3503,28 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli failedLoreCheck = true; } if(!failedLoreCheck) { - if (j == EQEmu::legacy::SlotPrimary) { + if (j == EQEmu::inventory::slotPrimary) { if (mWeaponItem->IsType2HWeapon()) { - if (GetBotItem(EQEmu::legacy::SlotSecondary)) { - if (client->CheckLoreConflict(GetBotItem(EQEmu::legacy::SlotSecondary)->GetItem())) { + if (GetBotItem(EQEmu::inventory::slotSecondary)) { + if (client->CheckLoreConflict(GetBotItem(EQEmu::inventory::slotSecondary)->GetItem())) { failedLoreCheck = true; } else { - EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::legacy::SlotSecondary); - BotTradeSwapItem(client, EQEmu::legacy::SlotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::inventory::slotSecondary); + BotTradeSwapItem(client, EQEmu::inventory::slotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } } if(!failedLoreCheck) { - BotTradeSwapItem(client, EQEmu::legacy::SlotPrimary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); + BotTradeSwapItem(client, EQEmu::inventory::slotPrimary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); success = true; } break; } - else if (j == EQEmu::legacy::SlotSecondary) { + else if (j == EQEmu::inventory::slotSecondary) { if(inst->IsWeapon()) { if(CanThisClassDualWield()) { - BotTradeSwapItem(client, EQEmu::legacy::SlotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); + BotTradeSwapItem(client, EQEmu::inventory::slotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); success = true; } else { @@ -3533,13 +3533,13 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } else { - BotTradeSwapItem(client, EQEmu::legacy::SlotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); + BotTradeSwapItem(client, EQEmu::inventory::slotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); success = true; } - if (success && GetBotItem(EQEmu::legacy::SlotPrimary)) { - EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::legacy::SlotPrimary); + if (success && GetBotItem(EQEmu::inventory::slotPrimary)) { + EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::inventory::slotPrimary); if (remove_item->GetItem()->IsType2HWeapon()) { - BotTradeSwapItem(client, EQEmu::legacy::SlotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); + BotTradeSwapItem(client, EQEmu::inventory::slotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); } } break; @@ -3739,13 +3739,13 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b FaceTarget(GetTarget()); EQEmu::ItemInstance* weapon = nullptr; - if (Hand == EQEmu::legacy::SlotPrimary) { - weapon = GetBotItem(EQEmu::legacy::SlotPrimary); + if (Hand == EQEmu::inventory::slotPrimary) { + weapon = GetBotItem(EQEmu::inventory::slotPrimary); OffHandAtk(false); } - if (Hand == EQEmu::legacy::SlotSecondary) { - weapon = GetBotItem(EQEmu::legacy::SlotSecondary); + if (Hand == EQEmu::inventory::slotSecondary) { + weapon = GetBotItem(EQEmu::inventory::slotSecondary); OffHandAtk(true); } @@ -3810,7 +3810,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b // This is not recommended for normal usage, as the damage bonus represents a non-trivial component of the DPS output // of weapons wielded by higher-level melee characters (especially for two-handed weapons). int ucDamageBonus = 0; - if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) { + if (Hand == EQEmu::inventory::slotPrimary && GetLevel() >= 28 && IsWarriorClass()) { // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); @@ -3820,7 +3820,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b } #endif //Live AA - Sinister Strikes *Adds weapon damage bonus to offhand weapon. - if (Hand == EQEmu::legacy::SlotSecondary) { + if (Hand == EQEmu::inventory::slotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); min_hit += (int) ucDamageBonus; @@ -4313,7 +4313,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { } } - for (int y = AUG_INDEX_BEGIN; y < EQEmu::legacy::ITEM_COMMON_SIZE; ++y) { + for (int y = EQEmu::inventory::socketBegin; y < EQEmu::inventory::SocketCount; ++y) { EQEmu::ItemInstance *aug = nullptr; aug = ins->GetAugment(y); if(aug) { @@ -4749,13 +4749,13 @@ float Bot::GetProcChances(float ProcBonus, uint16 hand) { float ProcChance = 0.0f; uint32 weapon_speed = 0; switch (hand) { - case EQEmu::legacy::SlotPrimary: + case EQEmu::inventory::slotPrimary: weapon_speed = attack_timer.GetDuration(); break; - case EQEmu::legacy::SlotSecondary: + case EQEmu::inventory::slotSecondary: weapon_speed = attack_dw_timer.GetDuration(); break; - case EQEmu::legacy::SlotRange: + case EQEmu::inventory::slotRange: weapon_speed = ranged_timer.GetDuration(); break; } @@ -4781,7 +4781,7 @@ int Bot::GetHandToHandDamage(void) { // everyone uses this in the revamp! int skill = GetSkill(EQEmu::skills::SkillHandtoHand); int epic = 0; - if (CastToNPC()->GetEquipment(EQEmu::textures::TextureHands) == 10652 && GetLevel() > 46) + if (CastToNPC()->GetEquipment(EQEmu::textures::armorHands) == 10652 && GetLevel() > 46) epic = 280; if (epic > skill) skill = epic; @@ -4803,7 +4803,7 @@ int Bot::GetHandToHandDamage(void) { 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, // 31-40 10, 11, 11, 11, 11, 11, 11, 12, 12}; // 41-49 if (GetClass() == MONK) { - if (CastToNPC()->GetEquipment(EQEmu::textures::TextureHands) == 10652 && GetLevel() > 50) + if (CastToNPC()->GetEquipment(EQEmu::textures::armorHands) == 10652 && GetLevel() > 50) return 9; if (level > 62) return 15; @@ -4842,11 +4842,11 @@ void Bot::DoRiposte(Mob* defender) { if (!defender) return; - defender->Attack(this, EQEmu::legacy::SlotPrimary, true); + defender->Attack(this, EQEmu::inventory::slotPrimary, true); int32 DoubleRipChance = (defender->GetAABonuses().GiveDoubleRiposte[0] + defender->GetSpellBonuses().GiveDoubleRiposte[0] + defender->GetItemBonuses().GiveDoubleRiposte[0]); if(DoubleRipChance && (DoubleRipChance >= zone->random.Int(0, 100))) { Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposte (%d percent chance)", DoubleRipChance); - defender->Attack(this, EQEmu::legacy::SlotPrimary, true); + defender->Attack(this, EQEmu::inventory::slotPrimary, true); } DoubleRipChance = defender->GetAABonuses().GiveDoubleRiposte[1]; @@ -4864,7 +4864,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 hate = hate_override; if (skill == EQEmu::skills::SkillBash) { - const EQEmu::ItemInstance* inst = GetBotItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemInstance* inst = GetBotItem(EQEmu::inventory::slotSecondary); const EQEmu::ItemData* botweapon = 0; if(inst) botweapon = inst->GetItem(); @@ -4878,14 +4878,14 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 } min_damage += (min_damage * GetMeleeMinDamageMod_SE(skill) / 100); - int hand = EQEmu::legacy::SlotPrimary; + int hand = EQEmu::inventory::slotPrimary; if (skill == EQEmu::skills::SkillThrowing || skill == EQEmu::skills::SkillArchery) - hand = EQEmu::legacy::SlotRange; + hand = EQEmu::inventory::slotRange; if (who->AvoidDamage(this, max_damage, hand)) { if (max_damage == -3) DoRiposte(who); } else { - if (HitChance || who->CheckHitChance(this, skill, EQEmu::legacy::SlotPrimary)) { + if (HitChance || who->CheckHitChance(this, skill, EQEmu::inventory::slotPrimary)) { who->MeleeMitigation(this, max_damage, min_damage); ApplyMeleeDamageBonus(skill, max_damage); max_damage += who->GetFcDamageAmtIncoming(this, 0, true, skill); @@ -4929,7 +4929,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { bool bIsBehind = false; bool bCanFrontalBS = false; - const EQEmu::ItemInstance* inst = GetBotItem(EQEmu::legacy::SlotPrimary); + const EQEmu::ItemInstance* inst = GetBotItem(EQEmu::inventory::slotPrimary); const EQEmu::ItemData* botpiercer = nullptr; if(inst) botpiercer = inst->GetItem(); @@ -4979,7 +4979,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { } } else - Attack(other, EQEmu::legacy::SlotPrimary); + Attack(other, EQEmu::inventory::slotPrimary); } void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { @@ -4989,11 +4989,11 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { int32 hate = 0; int32 primaryweapondamage = 0; int32 backstab_dmg = 0; - EQEmu::ItemInstance* botweaponInst = GetBotItem(EQEmu::legacy::SlotPrimary); + EQEmu::ItemInstance* botweaponInst = GetBotItem(EQEmu::inventory::slotPrimary); if(botweaponInst) { primaryweapondamage = GetWeaponDamage(other, botweaponInst); backstab_dmg = botweaponInst->GetItem()->BackstabDmg; - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; ++i) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) { EQEmu::ItemInstance *aug = botweaponInst->GetAugment(i); if(aug) backstab_dmg += aug->GetItem()->BackstabDmg; @@ -5037,7 +5037,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { } void Bot::RogueAssassinate(Mob* other) { - EQEmu::ItemInstance* botweaponInst = GetBotItem(EQEmu::legacy::SlotPrimary); + EQEmu::ItemInstance* botweaponInst = GetBotItem(EQEmu::inventory::slotPrimary); if(botweaponInst) { if(GetWeaponDamage(other, botweaponInst)) other->Damage(this, 32000, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab); @@ -5103,7 +5103,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { case WARRIOR: if(level >= RuleI(Combat, NPCBashKickLevel)){ bool canBash = false; - if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQEmu::legacy::SlotSecondary) && m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType == EQEmu::item::ItemTypeShield) || (m_inv.GetItem(EQEmu::legacy::SlotPrimary) && m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->IsType2HWeapon() && GetAA(aa2HandBash) >= 1)) + if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQEmu::inventory::slotSecondary) && m_inv.GetItem(EQEmu::inventory::slotSecondary)->GetItem()->ItemType == EQEmu::item::ItemTypeShield) || (m_inv.GetItem(EQEmu::inventory::slotPrimary) && m_inv.GetItem(EQEmu::inventory::slotPrimary)->GetItem()->IsType2HWeapon() && GetAA(aa2HandBash) >= 1)) canBash = true; if(!canBash || zone->random.Int(0, 100) > 25) @@ -5122,7 +5122,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { case SHADOWKNIGHT: case PALADIN: if(level >= RuleI(Combat, NPCBashKickLevel)){ - if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQEmu::legacy::SlotSecondary) && m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType == EQEmu::item::ItemTypeShield) || (m_inv.GetItem(EQEmu::legacy::SlotPrimary) && m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->IsType2HWeapon() && GetAA(aa2HandBash) >= 1)) + if ((GetRace() == OGRE || GetRace() == TROLL || GetRace() == BARBARIAN) || (m_inv.GetItem(EQEmu::inventory::slotSecondary) && m_inv.GetItem(EQEmu::inventory::slotSecondary)->GetItem()->ItemType == EQEmu::item::ItemTypeShield) || (m_inv.GetItem(EQEmu::inventory::slotPrimary) && m_inv.GetItem(EQEmu::inventory::slotPrimary)->GetItem()->IsType2HWeapon() && GetAA(aa2HandBash) >= 1)) skill_to_use = EQEmu::skills::SkillBash; } break; @@ -5151,7 +5151,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if (skill_to_use == EQEmu::skills::SkillBash) { if (target != this) { DoAnim(animTailRake); - if (GetWeaponDamage(target, GetBotItem(EQEmu::legacy::SlotSecondary)) <= 0 && GetWeaponDamage(target, GetBotItem(EQEmu::legacy::SlotShoulders)) <= 0) + if (GetWeaponDamage(target, GetBotItem(EQEmu::inventory::slotSecondary)) <= 0 && GetWeaponDamage(target, GetBotItem(EQEmu::inventory::slotShoulders)) <= 0) dmg = -5; else { if (!target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) @@ -5201,7 +5201,7 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if (skill_to_use == EQEmu::skills::SkillKick) { if(target != this) { DoAnim(animKick); - if (GetWeaponDamage(target, GetBotItem(EQEmu::legacy::SlotFeet)) <= 0) + if (GetWeaponDamage(target, GetBotItem(EQEmu::inventory::slotFeet)) <= 0) dmg = -5; else { if (!target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) @@ -5495,12 +5495,12 @@ void Bot::SetAttackTimer() { attack_timer.SetAtTrigger(4000, true); Timer* TimerToUse = nullptr; const EQEmu::ItemData* PrimaryWeapon = nullptr; - for (int i = EQEmu::legacy::SlotRange; i <= EQEmu::legacy::SlotSecondary; i++) { - if (i == EQEmu::legacy::SlotPrimary) + for (int i = EQEmu::inventory::slotRange; i <= EQEmu::inventory::slotSecondary; i++) { + if (i == EQEmu::inventory::slotPrimary) TimerToUse = &attack_timer; - else if (i == EQEmu::legacy::SlotRange) + else if (i == EQEmu::inventory::slotRange) TimerToUse = &ranged_timer; - else if (i == EQEmu::legacy::SlotSecondary) + else if (i == EQEmu::inventory::slotSecondary) TimerToUse = &attack_dw_timer; else continue; @@ -5510,7 +5510,7 @@ void Bot::SetAttackTimer() { if (ci) ItemToUse = ci->GetItem(); - if (i == EQEmu::legacy::SlotSecondary) { + if (i == EQEmu::inventory::slotSecondary) { if (PrimaryWeapon != nullptr) { if (PrimaryWeapon->IsClassCommon() && PrimaryWeapon->IsType2HWeapon()) { attack_dw_timer.Disable(); @@ -5541,7 +5541,7 @@ void Bot::SetAttackTimer() { speed = (RuleB(Spells, Jun182014HundredHandsRevamp) ? static_cast(((delay / haste_mod) + ((hhe / 1000.0f) * (delay / haste_mod))) * 100) : static_cast(((delay / haste_mod) + ((hhe / 100.0f) * delay)) * 100)); TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true); - if (i == EQEmu::legacy::SlotPrimary) + if (i == EQEmu::inventory::slotPrimary) PrimaryWeapon = ItemToUse; } } @@ -7186,7 +7186,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { // Modded to display power source items (will only show up on SoF+ client inspect windows though.) // I don't think bots are currently coded to use them..but, you'll have to use '#bot inventory list' // to see them on a Titanium client when/if they are activated. - for (int16 L = EQEmu::legacy::EQUIPMENT_BEGIN; L <= EQEmu::legacy::SlotWaist; L++) { + for (int16 L = EQEmu::legacy::EQUIPMENT_BEGIN; L <= EQEmu::inventory::slotWaist; L++) { inst = inspectedBot->GetBotItem(L); if(inst) { @@ -7200,7 +7200,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { } } - inst = inspectedBot->GetBotItem(EQEmu::legacy::SlotPowerSource); + inst = inspectedBot->GetBotItem(EQEmu::inventory::slotPowerSource); if(inst) { item = inst->GetItem(); @@ -7212,7 +7212,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { insr->itemicons[SoF::invslot::PossessionsPowerSource] = 0xFFFFFFFF; } - inst = inspectedBot->GetBotItem(EQEmu::legacy::SlotAmmo); + inst = inspectedBot->GetBotItem(EQEmu::inventory::slotAmmo); if(inst) { item = inst->GetItem(); @@ -7547,7 +7547,7 @@ void Bot::AddItemBonuses(const EQEmu::ItemInstance *inst, StatBonuses* newbon, b if (!isAug) { - for (int i = 0; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) AddItemBonuses(inst->GetAugment(i),newbon,true, false, rec_level); } @@ -8036,12 +8036,12 @@ uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { int Bot::GetRawACNoShield(int &shield_ac) { int ac = itembonuses.AC + spellbonuses.AC; shield_ac = 0; - EQEmu::ItemInstance* inst = GetBotItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance* inst = GetBotItem(EQEmu::inventory::slotSecondary); if(inst) { if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; - for (uint8 i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { + for (uint8 i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { if(inst->GetAugment(i)) { ac -= inst->GetAugment(i)->GetItem()->AC; shield_ac += inst->GetAugment(i)->GetItem()->AC; @@ -8433,7 +8433,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) if (slot_id != INVALID_INDEX) return false; - for (uint8 i = 0; i < EQEmu::textures::TexturePrimary; ++i) { + for (uint8 i = EQEmu::textures::textureBegin; i < EQEmu::textures::weaponPrimary; ++i) { uint8 inv_slot = Inventory::CalcSlotFromMaterial(i); EQEmu::ItemInstance* inst = m_inv.GetItem(inv_slot); if (!inst) @@ -8445,7 +8445,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) } else { uint8 mat_slot = Inventory::CalcMaterialFromSlot(slot_id); - if (mat_slot == EQEmu::textures::TextureInvalid || mat_slot >= EQEmu::textures::TexturePrimary) + if (mat_slot == EQEmu::textures::materialInvalid || mat_slot >= EQEmu::textures::weaponPrimary) return false; EQEmu::ItemInstance* inst = m_inv.GetItem(slot_id); diff --git a/zone/bot.h b/zone/bot.h index 5bafe1caa..96ca86eec 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -77,7 +77,7 @@ static const std::string bot_stance_name[BOT_STANCE_COUNT] = { static const char* GetBotStanceName(int stance_id) { return bot_stance_name[VALIDBOTSTANCE(stance_id)].c_str(); } -#define VALIDBOTEQUIPSLOT(x) ((x >= EQEmu::legacy::EQUIPMENT_BEGIN && x <= EQEmu::legacy::EQUIPMENT_END) ? (x) : ((x == EQEmu::legacy::SlotPowerSource) ? (22) : (23))) +#define VALIDBOTEQUIPSLOT(x) ((x >= EQEmu::legacy::EQUIPMENT_BEGIN && x <= EQEmu::legacy::EQUIPMENT_END) ? (x) : ((x == EQEmu::inventory::slotPowerSource) ? (22) : (23))) static std::string bot_equip_slot_name[EQEmu::legacy::EQUIPMENT_SIZE + 2] = { @@ -207,7 +207,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 398a0d6b0..57dd2d418 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -4358,7 +4358,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) // TODO: Trouble-shoot model update issue const std::string msg_matslot = StringFormat("mat_slot: %c(All), %i(Head), %i(Chest), %i(Arms), %i(Wrists), %i(Hands), %i(Legs), %i(Feet)", - '*', EQEmu::textures::TextureHead, EQEmu::textures::TextureChest, EQEmu::textures::TextureArms, EQEmu::textures::TextureWrist, EQEmu::textures::TextureHands, EQEmu::textures::TextureLegs, EQEmu::textures::TextureFeet); + '*', EQEmu::textures::armorHead, EQEmu::textures::armorChest, EQEmu::textures::armorArms, EQEmu::textures::armorWrist, EQEmu::textures::armorHands, EQEmu::textures::armorLegs, EQEmu::textures::armorFeet); if (helper_command_alias_fail(c, "bot_subcommand_bot_dye_armor", sep->arg[0], "botdyearmor")) return; @@ -4369,7 +4369,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) } const int ab_mask = ActionableBots::ABM_NoFilter; - uint8 material_slot = EQEmu::textures::TextureInvalid; + uint8 material_slot = EQEmu::textures::materialInvalid; int16 slot_id = INVALID_INDEX; bool dye_all = (sep->arg[1][0] == '*'); @@ -4377,7 +4377,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) material_slot = atoi(sep->arg[1]); slot_id = Inventory::CalcSlotFromMaterial(material_slot); - if (!sep->IsNumber(1) || slot_id == INVALID_INDEX || material_slot > EQEmu::textures::TextureFeet) { + if (!sep->IsNumber(1) || slot_id == INVALID_INDEX || material_slot > EQEmu::textures::LastTintableTexture) { c->Message(m_fail, "Valid [mat_slot]s for this command are:"); c->Message(m_fail, msg_matslot.c_str()); return; @@ -7072,23 +7072,23 @@ void bot_subcommand_inventory_list(Client *c, const Seperator *sep) uint32 inventory_count = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { - if ((i == EQEmu::legacy::SlotSecondary) && is2Hweapon) + if ((i == EQEmu::inventory::slotSecondary) && is2Hweapon) continue; - inst = my_bot->CastToBot()->GetBotItem(i == 22 ? EQEmu::legacy::SlotPowerSource : i); + inst = my_bot->CastToBot()->GetBotItem(i == 22 ? EQEmu::inventory::slotPowerSource : i); if (!inst || !inst->GetItem()) { - c->Message(m_message, "I need something for my %s (slot %i)", GetBotEquipSlotName(i), (i == 22 ? EQEmu::legacy::SlotPowerSource : i)); + c->Message(m_message, "I need something for my %s (slot %i)", GetBotEquipSlotName(i), (i == 22 ? EQEmu::inventory::slotPowerSource : i)); continue; } item = inst->GetItem(); - if ((i == EQEmu::legacy::SlotPrimary) && item->IsType2HWeapon()) { + if ((i == EQEmu::inventory::slotPrimary) && item->IsType2HWeapon()) { is2Hweapon = true; } linker.SetItemInst(inst); item_link = linker.GenerateLink(); - c->Message(m_message, "Using %s in my %s (slot %i)", item_link.c_str(), GetBotEquipSlotName(i), (i == 22 ? EQEmu::legacy::SlotPowerSource : i)); + c->Message(m_message, "Using %s in my %s (slot %i)", item_link.c_str(), GetBotEquipSlotName(i), (i == 22 ? EQEmu::inventory::slotPowerSource : i)); ++inventory_count; } @@ -7127,7 +7127,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) } int slotId = atoi(sep->arg[1]); - if (!sep->IsNumber(1) || ((slotId > EQEmu::legacy::EQUIPMENT_END || slotId < EQEmu::legacy::EQUIPMENT_BEGIN) && slotId != EQEmu::legacy::SlotPowerSource)) { + if (!sep->IsNumber(1) || ((slotId > EQEmu::legacy::EQUIPMENT_END || slotId < EQEmu::legacy::EQUIPMENT_BEGIN) && slotId != EQEmu::inventory::slotPowerSource)) { c->Message(m_fail, "Valid slots are 0-21 or 9999"); return; } @@ -7142,7 +7142,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) return; } - for (int m = AUG_INDEX_BEGIN; m < EQEmu::legacy::ITEM_COMMON_SIZE; ++m) { + for (int m = EQEmu::inventory::socketBegin; m < EQEmu::inventory::SocketCount; ++m) { if (!itminst) break; @@ -7159,7 +7159,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) std::string error_message; if (itm) { c->PushItemOnCursor(*itminst, true); - if ((slotId == EQEmu::legacy::SlotRange) || (slotId == EQEmu::legacy::SlotAmmo) || (slotId == EQEmu::legacy::SlotPrimary) || (slotId == EQEmu::legacy::SlotSecondary)) + if ((slotId == EQEmu::inventory::slotRange) || (slotId == EQEmu::inventory::slotAmmo) || (slotId == EQEmu::inventory::slotPrimary) || (slotId == EQEmu::inventory::slotSecondary)) my_bot->SetBotArcher(false); my_bot->RemoveBotItemBySlot(slotId, &error_message); @@ -7173,31 +7173,31 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) } switch (slotId) { - case EQEmu::legacy::SlotCharm: - case EQEmu::legacy::SlotEar1: - case EQEmu::legacy::SlotHead: - case EQEmu::legacy::SlotFace: - case EQEmu::legacy::SlotEar2: - case EQEmu::legacy::SlotNeck: - case EQEmu::legacy::SlotBack: - case EQEmu::legacy::SlotWrist1: - case EQEmu::legacy::SlotWrist2: - case EQEmu::legacy::SlotRange: - case EQEmu::legacy::SlotPrimary: - case EQEmu::legacy::SlotSecondary: - case EQEmu::legacy::SlotFinger1: - case EQEmu::legacy::SlotFinger2: - case EQEmu::legacy::SlotChest: - case EQEmu::legacy::SlotWaist: - case EQEmu::legacy::SlotPowerSource: - case EQEmu::legacy::SlotAmmo: + case EQEmu::inventory::slotCharm: + case EQEmu::inventory::slotEar1: + case EQEmu::inventory::slotHead: + case EQEmu::inventory::slotFace: + case EQEmu::inventory::slotEar2: + case EQEmu::inventory::slotNeck: + case EQEmu::inventory::slotBack: + case EQEmu::inventory::slotWrist1: + case EQEmu::inventory::slotWrist2: + case EQEmu::inventory::slotRange: + case EQEmu::inventory::slotPrimary: + case EQEmu::inventory::slotSecondary: + case EQEmu::inventory::slotFinger1: + case EQEmu::inventory::slotFinger2: + case EQEmu::inventory::slotChest: + case EQEmu::inventory::slotWaist: + case EQEmu::inventory::slotPowerSource: + case EQEmu::inventory::slotAmmo: c->Message(m_message, "My %s is %s unequipped", GetBotEquipSlotName(slotId), ((itm) ? ("now") : ("already"))); break; - case EQEmu::legacy::SlotShoulders: - case EQEmu::legacy::SlotArms: - case EQEmu::legacy::SlotHands: - case EQEmu::legacy::SlotLegs: - case EQEmu::legacy::SlotFeet: + case EQEmu::inventory::slotShoulders: + case EQEmu::inventory::slotArms: + case EQEmu::inventory::slotHands: + case EQEmu::inventory::slotLegs: + case EQEmu::inventory::slotFeet: c->Message(m_message, "My %s are %s unequipped", GetBotEquipSlotName(slotId), ((itm) ? ("now") : ("already"))); break; default: @@ -7236,12 +7236,12 @@ void bot_subcommand_inventory_window(Client *c, const Seperator *sep) for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { const EQEmu::ItemData* item = nullptr; - const EQEmu::ItemInstance* inst = my_bot->CastToBot()->GetBotItem(i == 22 ? EQEmu::legacy::SlotPowerSource : i); + const EQEmu::ItemInstance* inst = my_bot->CastToBot()->GetBotItem(i == 22 ? EQEmu::inventory::slotPowerSource : i); if (inst) item = inst->GetItem(); window_text.append(""); - window_text.append(GetBotEquipSlotName(i == 22 ? EQEmu::legacy::SlotPowerSource : i)); + window_text.append(GetBotEquipSlotName(i == 22 ? EQEmu::inventory::slotPowerSource : i)); window_text.append(": "); if (item) { //window_text.append(""); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 8e4ddc203..259df1d63 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1058,7 +1058,7 @@ bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) for (auto row = results.begin(); row != results.end(); ++row) { int16 slot_id = atoi(row[0]); - if ((slot_id < EQEmu::legacy::EQUIPMENT_BEGIN || slot_id > EQEmu::legacy::EQUIPMENT_END) && slot_id != EQEmu::legacy::SlotPowerSource) + if ((slot_id < EQEmu::legacy::EQUIPMENT_BEGIN || slot_id > EQEmu::legacy::EQUIPMENT_END) && slot_id != EQEmu::inventory::slotPowerSource) continue; uint32 item_id = atoi(row[1]); @@ -1093,7 +1093,7 @@ bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) if (item_inst->GetItem()->Attuneable) { if (atoi(row[4])) item_inst->SetAttuned(true); - else if (((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::legacy::EQUIPMENT_END) || slot_id == EQEmu::legacy::SlotPowerSource)) + else if (((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::legacy::EQUIPMENT_END) || slot_id == EQEmu::inventory::slotPowerSource)) item_inst->SetAttuned(true); } @@ -1161,7 +1161,7 @@ bool BotDatabase::LoadItemBySlot(Bot* bot_inst) bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint32& item_id) { - if (!bot_id || (slot_id > EQEmu::legacy::EQUIPMENT_END && slot_id != EQEmu::legacy::SlotPowerSource)) + if (!bot_id || (slot_id > EQEmu::legacy::EQUIPMENT_END && slot_id != EQEmu::inventory::slotPowerSource)) return false; query = StringFormat("SELECT `item_id` FROM `bot_inventories` WHERE `bot_id` = '%i' AND `slot_id` = '%i' LIMIT 1", bot_id, slot_id); @@ -1179,7 +1179,7 @@ bool BotDatabase::LoadItemBySlot(const uint32 bot_id, const uint32 slot_id, uint bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const EQEmu::ItemInstance* item_inst) { - if (!bot_inst || !bot_inst->GetBotID() || (slot_id > EQEmu::legacy::EQUIPMENT_END && slot_id != EQEmu::legacy::SlotPowerSource)) + if (!bot_inst || !bot_inst->GetBotID() || (slot_id > EQEmu::legacy::EQUIPMENT_END && slot_id != EQEmu::inventory::slotPowerSource)) return false; if (!DeleteItemBySlot(bot_inst->GetBotID(), slot_id)) @@ -1188,8 +1188,8 @@ bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const EQEm if (!item_inst || !item_inst->GetID()) return true; - uint32 augment_id[] = { 0, 0, 0, 0, 0, 0 }; - for (int augment_iter = 0; augment_iter < EQEmu::legacy::ITEM_COMMON_SIZE; ++augment_iter) + uint32 augment_id[EQEmu::inventory::SocketCount] = { 0, 0, 0, 0, 0, 0 }; + for (int augment_iter = EQEmu::inventory::socketBegin; augment_iter < EQEmu::inventory::SocketCount; ++augment_iter) augment_id[augment_iter] = item_inst->GetAugmentItemID(augment_iter); uint16 item_charges = 0; @@ -1263,7 +1263,7 @@ bool BotDatabase::SaveItemBySlot(Bot* bot_inst, const uint32 slot_id, const EQEm bool BotDatabase::DeleteItemBySlot(const uint32 bot_id, const uint32 slot_id) { - if (!bot_id || (slot_id > EQEmu::legacy::EQUIPMENT_END && slot_id != EQEmu::legacy::SlotPowerSource)) + if (!bot_id || (slot_id > EQEmu::legacy::EQUIPMENT_END && slot_id != EQEmu::inventory::slotPowerSource)) return false; query = StringFormat("DELETE FROM `bot_inventories` WHERE `bot_id` = '%u' AND `slot_id` = '%u'", bot_id, slot_id); @@ -1302,12 +1302,12 @@ bool BotDatabase::SaveEquipmentColor(const uint32 bot_id, const int16 slot_id, c return false; bool all_flag = (slot_id == -2); - if ((slot_id < EQEmu::legacy::EQUIPMENT_BEGIN || slot_id > EQEmu::legacy::EQUIPMENT_END) && slot_id != EQEmu::legacy::SlotPowerSource && !all_flag) + if ((slot_id < EQEmu::legacy::EQUIPMENT_BEGIN || slot_id > EQEmu::legacy::EQUIPMENT_END) && slot_id != EQEmu::inventory::slotPowerSource && !all_flag) return false; std::string where_clause; if (all_flag) - where_clause = StringFormat(" AND `slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u')", EQEmu::legacy::SlotHead, EQEmu::legacy::SlotArms, EQEmu::legacy::SlotWrist1, EQEmu::legacy::SlotHands, EQEmu::legacy::SlotChest, EQEmu::legacy::SlotLegs, EQEmu::legacy::SlotFeet); + where_clause = StringFormat(" AND `slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u')", EQEmu::inventory::slotHead, EQEmu::inventory::slotArms, EQEmu::inventory::slotWrist1, EQEmu::inventory::slotHands, EQEmu::inventory::slotChest, EQEmu::inventory::slotLegs, EQEmu::inventory::slotFeet); else where_clause = StringFormat(" AND `slot_id` = '%u'", slot_id); @@ -1752,7 +1752,7 @@ bool BotDatabase::SaveAllArmorColorBySlot(const uint32 owner_id, const int16 slo " AND bi.`slot_id` = '%i'", owner_id, rgb_value, - EQEmu::legacy::SlotHead, EQEmu::legacy::SlotChest, EQEmu::legacy::SlotArms, EQEmu::legacy::SlotWrist1, EQEmu::legacy::SlotWrist2, EQEmu::legacy::SlotHands, EQEmu::legacy::SlotLegs, EQEmu::legacy::SlotFeet, + EQEmu::inventory::slotHead, EQEmu::inventory::slotChest, EQEmu::inventory::slotArms, EQEmu::inventory::slotWrist1, EQEmu::inventory::slotWrist2, EQEmu::inventory::slotHands, EQEmu::inventory::slotLegs, EQEmu::inventory::slotFeet, slot_id ); auto results = QueryDatabase(query); @@ -1776,7 +1776,7 @@ bool BotDatabase::SaveAllArmorColors(const uint32 owner_id, const uint32 rgb_val " AND bi.`slot_id` IN ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", owner_id, rgb_value, - EQEmu::legacy::SlotHead, EQEmu::legacy::SlotChest, EQEmu::legacy::SlotArms, EQEmu::legacy::SlotWrist1, EQEmu::legacy::SlotWrist2, EQEmu::legacy::SlotHands, EQEmu::legacy::SlotLegs, EQEmu::legacy::SlotFeet + EQEmu::inventory::slotHead, EQEmu::inventory::slotChest, EQEmu::inventory::slotArms, EQEmu::inventory::slotWrist1, EQEmu::inventory::slotWrist2, EQEmu::inventory::slotHands, EQEmu::inventory::slotLegs, EQEmu::inventory::slotFeet ); auto results = QueryDatabase(query); if (!results.Success()) diff --git a/zone/client.cpp b/zone/client.cpp index c0b8078bb..09f843616 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2800,7 +2800,7 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) { if (item && item->IsClassCommon()) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); - if (matslot != EQEmu::textures::TextureInvalid) + if (matslot != EQEmu::textures::materialInvalid) { m_pp.item_material.Slot[matslot].Material = GetEquipmentMaterial(matslot); } @@ -3132,17 +3132,17 @@ void Client::Tell_StringID(uint32 string_id, const char *who, const char *messag } void Client::SetTint(int16 in_slot, uint32 color) { - EQEmu::Tint_Struct new_color; + EQEmu::textures::Tint_Struct new_color; new_color.Color = color; SetTint(in_slot, new_color); database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color); } // Still need to reconcile bracer01 versus bracer02 -void Client::SetTint(int16 in_slot, EQEmu::Tint_Struct& color) { +void Client::SetTint(int16 in_slot, EQEmu::textures::Tint_Struct& color) { uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); - if (matslot != EQEmu::textures::TextureInvalid) + if (matslot != EQEmu::textures::materialInvalid) { m_pp.item_tint.Slot[matslot].Color = color.Color; database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.Color); @@ -3219,28 +3219,28 @@ void Client::LinkDead() uint8 Client::SlotConvert(uint8 slot,bool bracer){ uint8 slot2 = 0; // why are we returning MainCharm instead of INVALID_INDEX? (must be a pre-charm segment...) if(bracer) - return EQEmu::legacy::SlotWrist2; + return EQEmu::inventory::slotWrist2; switch(slot) { - case EQEmu::textures::TextureHead: - slot2 = EQEmu::legacy::SlotHead; + case EQEmu::textures::armorHead: + slot2 = EQEmu::inventory::slotHead; break; - case EQEmu::textures::TextureChest: - slot2 = EQEmu::legacy::SlotChest; + case EQEmu::textures::armorChest: + slot2 = EQEmu::inventory::slotChest; break; - case EQEmu::textures::TextureArms: - slot2 = EQEmu::legacy::SlotArms; + case EQEmu::textures::armorArms: + slot2 = EQEmu::inventory::slotArms; break; - case EQEmu::textures::TextureWrist: - slot2 = EQEmu::legacy::SlotWrist1; + case EQEmu::textures::armorWrist: + slot2 = EQEmu::inventory::slotWrist1; break; - case EQEmu::textures::TextureHands: - slot2 = EQEmu::legacy::SlotHands; + case EQEmu::textures::armorHands: + slot2 = EQEmu::inventory::slotHands; break; - case EQEmu::textures::TextureLegs: - slot2 = EQEmu::legacy::SlotLegs; + case EQEmu::textures::armorLegs: + slot2 = EQEmu::inventory::slotLegs; break; - case EQEmu::textures::TextureFeet: - slot2 = EQEmu::legacy::SlotFeet; + case EQEmu::textures::armorFeet: + slot2 = EQEmu::inventory::slotFeet; break; } return slot2; @@ -3249,26 +3249,26 @@ uint8 Client::SlotConvert(uint8 slot,bool bracer){ uint8 Client::SlotConvert2(uint8 slot){ uint8 slot2 = 0; // same as above... switch(slot){ - case EQEmu::legacy::SlotHead: - slot2 = EQEmu::textures::TextureHead; + case EQEmu::inventory::slotHead: + slot2 = EQEmu::textures::armorHead; break; - case EQEmu::legacy::SlotChest: - slot2 = EQEmu::textures::TextureChest; + case EQEmu::inventory::slotChest: + slot2 = EQEmu::textures::armorChest; break; - case EQEmu::legacy::SlotArms: - slot2 = EQEmu::textures::TextureArms; + case EQEmu::inventory::slotArms: + slot2 = EQEmu::textures::armorArms; break; - case EQEmu::legacy::SlotWrist1: - slot2 = EQEmu::textures::TextureWrist; + case EQEmu::inventory::slotWrist1: + slot2 = EQEmu::textures::armorWrist; break; - case EQEmu::legacy::SlotHands: - slot2 = EQEmu::textures::TextureHands; + case EQEmu::inventory::slotHands: + slot2 = EQEmu::textures::armorHands; break; - case EQEmu::legacy::SlotLegs: - slot2 = EQEmu::textures::TextureLegs; + case EQEmu::inventory::slotLegs: + slot2 = EQEmu::textures::armorLegs; break; - case EQEmu::legacy::SlotFeet: - slot2 = EQEmu::textures::TextureFeet; + case EQEmu::inventory::slotFeet: + slot2 = EQEmu::textures::armorFeet; break; } return slot2; @@ -4268,14 +4268,14 @@ bool Client::GroupFollow(Client* inviter) { uint16 Client::GetPrimarySkillValue() { EQEmu::skills::SkillType skill = EQEmu::skills::HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill - bool equiped = m_inv.GetItem(EQEmu::legacy::SlotPrimary); + bool equiped = m_inv.GetItem(EQEmu::inventory::slotPrimary); if (!equiped) skill = EQEmu::skills::SkillHandtoHand; else { - uint8 type = m_inv.GetItem(EQEmu::legacy::SlotPrimary)->GetItem()->ItemType; //is this the best way to do this? + uint8 type = m_inv.GetItem(EQEmu::inventory::slotPrimary)->GetItem()->ItemType; //is this the best way to do this? switch (type) { case EQEmu::item::ItemType1HSlash: // 1H Slashing @@ -5785,7 +5785,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { } } - inst = requestee->GetInv().GetItem(EQEmu::legacy::SlotPowerSource); + inst = requestee->GetInv().GetItem(EQEmu::inventory::slotPowerSource); if(inst) { item = inst->GetItem(); @@ -5799,7 +5799,7 @@ void Client::ProcessInspectRequest(Client* requestee, Client* requester) { insr->itemicons[SoF::invslot::PossessionsPowerSource] = 0xFFFFFFFF; } - inst = requestee->GetInv().GetItem(EQEmu::legacy::SlotAmmo); + inst = requestee->GetInv().GetItem(EQEmu::inventory::slotAmmo); if(inst) { item = inst->GetItem(); @@ -6341,8 +6341,8 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid made_npc->Corrup = GetCorrup(); made_npc->PhR = GetPhR(); // looks - made_npc->texture = GetEquipmentMaterial(EQEmu::textures::TextureChest); - made_npc->helmtexture = GetEquipmentMaterial(EQEmu::textures::TextureHead); + made_npc->texture = GetEquipmentMaterial(EQEmu::textures::armorChest); + made_npc->helmtexture = GetEquipmentMaterial(EQEmu::textures::armorHead); made_npc->haircolor = GetHairColor(); made_npc->beardcolor = GetBeardColor(); made_npc->eyecolor1 = GetEyeColor1(); @@ -6353,9 +6353,9 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid made_npc->drakkin_heritage = GetDrakkinHeritage(); made_npc->drakkin_tattoo = GetDrakkinTattoo(); made_npc->drakkin_details = GetDrakkinDetails(); - made_npc->d_melee_texture1 = GetEquipmentMaterial(EQEmu::textures::TexturePrimary); - made_npc->d_melee_texture2 = GetEquipmentMaterial(EQEmu::textures::TextureSecondary); - for (int i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTexture; i++) { + made_npc->d_melee_texture1 = GetEquipmentMaterial(EQEmu::textures::weaponPrimary); + made_npc->d_melee_texture2 = GetEquipmentMaterial(EQEmu::textures::weaponSecondary); + for (int i = EQEmu::textures::textureBegin; i <= EQEmu::textures::LastTexture; i++) { made_npc->armor_tint.Slot[i].Color = GetEquipmentColor(i); } made_npc->loottable_id = 0; @@ -8061,7 +8061,7 @@ void Client::TickItemCheck() TryItemTick(i); } //Scan main inventory + cursor - for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::SlotCursor; i++) + for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::inventory::slotCursor; i++) { TryItemTick(i); } @@ -8092,7 +8092,7 @@ void Client::TryItemTick(int slot) //Only look at augs in main inventory if (slot > EQEmu::legacy::EQUIPMENT_END) { return; } - for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) + for (int x = EQEmu::inventory::socketBegin; x < EQEmu::inventory::SocketCount; ++x) { EQEmu::ItemInstance * a_inst = inst->GetAugment(x); if(!a_inst) { continue; } @@ -8118,7 +8118,7 @@ void Client::ItemTimerCheck() TryItemTimer(i); } - for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::SlotCursor; i++) + for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::inventory::slotCursor; i++) { TryItemTimer(i); } @@ -8149,7 +8149,7 @@ void Client::TryItemTimer(int slot) return; } - for (int x = AUG_INDEX_BEGIN; x < EQEmu::legacy::ITEM_COMMON_SIZE; ++x) + for (int x = EQEmu::inventory::socketBegin; x < EQEmu::inventory::SocketCount; ++x) { EQEmu::ItemInstance * a_inst = inst->GetAugment(x); if(!a_inst) { @@ -8482,7 +8482,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold, AddMoneyToPP(copper, silver, gold, platinum, false); if (itemid > 0) - SummonItem(itemid, 0, 0, 0, 0, 0, 0, false, EQEmu::legacy::SlotPowerSource); + SummonItem(itemid, 0, 0, 0, 0, 0, 0, false, EQEmu::inventory::slotPowerSource); if (faction) { diff --git a/zone/client.h b/zone/client.h index cc5abb88d..bfe9f96cd 100644 --- a/zone/client.h +++ b/zone/client.h @@ -222,7 +222,7 @@ public: //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } @@ -808,7 +808,7 @@ public: uint32 NukeItem(uint32 itemnum, uint8 where_to_check = (invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor)); void SetTint(int16 slot_id, uint32 color); - void SetTint(int16 slot_id, EQEmu::Tint_Struct& color); + void SetTint(int16 slot_id, EQEmu::textures::Tint_Struct& color); void SetMaterial(int16 slot_id, uint32 item_id); void Undye(); int32 GetItemIDAt(int16 slot_id); @@ -822,7 +822,7 @@ public: void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false); void PutLootInInventory(int16 slot_id, const EQEmu::ItemInstance &inst, ServerLootItem_Struct** bag_item_data = 0); bool AutoPutLootInInventory(EQEmu::ItemInstance& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0); - bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = EQEmu::legacy::SlotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); + bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = EQEmu::inventory::slotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); void DropItem(int16 slot_id); diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 69f1444f1..f2205aabd 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1074,9 +1074,9 @@ int32 Client::CalcAC() } // Shield AC bonus for HeroicSTR if (itembonuses.HeroicSTR) { - bool equiped = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary); + bool equiped = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary); if (equiped) { - uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType; + uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary)->GetItem()->ItemType; if (shield == EQEmu::item::ItemTypeShield) { displayed += itembonuses.HeroicSTR / 2; } @@ -1103,9 +1103,9 @@ int32 Client::GetACMit() } // Shield AC bonus for HeroicSTR if (itembonuses.HeroicSTR) { - bool equiped = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary); + bool equiped = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary); if (equiped) { - uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::legacy::SlotSecondary)->GetItem()->ItemType; + uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary)->GetItem()->ItemType; if (shield == EQEmu::item::ItemTypeShield) { mitigation += itembonuses.HeroicSTR / 2; } @@ -1320,7 +1320,7 @@ uint32 Client::CalcCurrentWeight() EQEmu::ItemInstance* ins; uint32 Total = 0; int x; - for (x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::SlotCursor; x++) { // include cursor or not? + for (x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::inventory::slotCursor; x++) { // include cursor or not? TempItem = 0; ins = GetInv().GetItem(x); if (ins) { @@ -1343,7 +1343,7 @@ uint32 Client::CalcCurrentWeight() if (TmpWeight > 0) { // this code indicates that weight redux bags can only be in the first general inventory slot to be effective... // is this correct? or can we scan for the highest weight redux and use that? (need client verifications) - int bagslot = EQEmu::legacy::SlotGeneral1; + int bagslot = EQEmu::inventory::slotGeneral1; int reduction = 0; for (int m = EQEmu::legacy::GENERAL_BAGS_BEGIN + 10; m <= EQEmu::legacy::GENERAL_BAGS_END; m += 10) { // include cursor bags or not? if (x >= m) { @@ -2219,12 +2219,12 @@ int Client::GetRawACNoShield(int &shield_ac) const { int ac = itembonuses.AC + spellbonuses.AC + aabonuses.AC; shield_ac = 0; - const EQEmu::ItemInstance *inst = m_inv.GetItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemInstance *inst = m_inv.GetItem(EQEmu::inventory::slotSecondary); if (inst) { if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { ac -= inst->GetItem()->AC; shield_ac = inst->GetItem()->AC; - for (uint8 i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { + for (uint8 i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { if (inst->GetAugment(i)) { ac -= inst->GetAugment(i)->GetItem()->AC; shield_ac += inst->GetAugment(i)->GetItem()->AC; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a8c96e146..a537c1db2 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1334,7 +1334,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) } /* Set item material tint */ - for (int i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTexture; i++) + for (int i = EQEmu::textures::textureBegin; i <= EQEmu::textures::LastTexture; i++) { if (m_pp.item_tint.Slot[i].UseTint == 1 || m_pp.item_tint.Slot[i].UseTint == 255) { @@ -1691,7 +1691,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (iter == m_inv.cursor_cbegin()) continue; const EQEmu::ItemInstance *inst = *iter; - SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketLimbo); + SendItemPacket(EQEmu::inventory::slotCursor, inst, ItemPacketLimbo); } } @@ -2029,7 +2029,7 @@ void Client::Handle_OP_AdventureMerchantPurchase(const EQApplicationPacket *app) EQEmu::ItemInstance *inst = database.CreateItem(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) { - PutLootInInventory(EQEmu::legacy::SlotCursor, *inst); + PutLootInInventory(EQEmu::inventory::slotCursor, *inst); } Save(1); } @@ -2554,7 +2554,7 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) EQEmu::ItemInstance *inst = database.CreateItem(item, charges); if (!AutoPutLootInInventory(*inst, true, true)) { - PutLootInInventory(EQEmu::legacy::SlotCursor, *inst); + PutLootInInventory(EQEmu::inventory::slotCursor, *inst); } Save(1); @@ -2604,7 +2604,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) SetAlternateCurrencyValue(reclaim->currency_id, 0); } else { - SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, EQEmu::legacy::SlotCursor); + SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, 0, false, EQEmu::inventory::slotCursor); AddAlternateCurrencyValue(reclaim->currency_id, -((int32)reclaim->count)); } /* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */ @@ -2816,8 +2816,8 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app) } uint32 ApplyPoisonSuccessResult = 0; ApplyPoison_Struct* ApplyPoisonData = (ApplyPoison_Struct*)app->pBuffer; - const EQEmu::ItemInstance* PrimaryWeapon = GetInv().GetItem(EQEmu::legacy::SlotPrimary); - const EQEmu::ItemInstance* SecondaryWeapon = GetInv().GetItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemInstance* PrimaryWeapon = GetInv().GetItem(EQEmu::inventory::slotPrimary); + const EQEmu::ItemInstance* SecondaryWeapon = GetInv().GetItem(EQEmu::inventory::slotSecondary); const EQEmu::ItemInstance* PoisonItemInstance = GetInv()[ApplyPoisonData->inventorySlot]; bool IsPoison = PoisonItemInstance && (PoisonItemInstance->GetItem()->ItemType == EQEmu::item::ItemTypePoison); @@ -2999,7 +2999,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) { case 0: // Adding an augment case 2: // Swapping augment - new_aug = user_inv.GetItem(EQEmu::legacy::SlotCursor); + new_aug = user_inv.GetItem(EQEmu::inventory::slotCursor); if (!new_aug) // Shouldn't get the OP code without the augment on the user's cursor, but maybe it's h4x. { @@ -3057,7 +3057,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (itemOneToPush) { DeleteItemInInventory(item_slot, 0, true); - DeleteItemInInventory(EQEmu::legacy::SlotCursor, new_aug->IsStackable() ? 1 : 0, true); + DeleteItemInInventory(EQEmu::inventory::slotCursor, new_aug->IsStackable() ? 1 : 0, true); if (solvent) { @@ -3068,7 +3068,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (itemTwoToPush) { // This is a swap. Return the old aug to the player's cursor. - if (!PutItemInInventory(EQEmu::legacy::SlotCursor, *itemTwoToPush, true)) + if (!PutItemInInventory(EQEmu::inventory::slotCursor, *itemTwoToPush, true)) { Log.Out(Logs::General, Logs::Error, "Problem returning old augment to player's cursor after augmentation swap."); Message(15, "Error: Failed to retrieve old augment after augmentation swap!"); @@ -3081,7 +3081,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != EQEmu::textures::TextureInvalid) + if (mat != EQEmu::textures::materialInvalid) { SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. } @@ -3146,13 +3146,13 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != EQEmu::textures::TextureInvalid) + if (mat != EQEmu::textures::materialInvalid) { SendWearChange(mat); // Visible item augged while equipped. Send WC in case ornamentation changed. } // Drop the removed augment on the player's cursor - if (!PutItemInInventory(EQEmu::legacy::SlotCursor, *itemTwoToPush, true)) + if (!PutItemInInventory(EQEmu::inventory::slotCursor, *itemTwoToPush, true)) { Log.Out(Logs::General, Logs::Error, "Problem returning augment to player's cursor after safe removal."); Message(15, "Error: Failed to return augment after removal from item!"); @@ -3201,7 +3201,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) CalcBonuses(); - if (mat != EQEmu::textures::TextureInvalid) + if (mat != EQEmu::textures::materialInvalid) { SendWearChange(mat); } @@ -4070,7 +4070,7 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) } else { - Message(0, "Error: castspell->inventoryslot >= %i (0x%04x)", EQEmu::legacy::SlotCursor, castspell->inventoryslot); + Message(0, "Error: castspell->inventoryslot >= %i (0x%04x)", EQEmu::inventory::slotCursor, castspell->inventoryslot); InterruptSpell(castspell->spell_id); } } @@ -4993,7 +4993,7 @@ void Client::Handle_OP_CrashDump(const EQApplicationPacket *app) void Client::Handle_OP_CreateObject(const EQApplicationPacket *app) { - DropItem(EQEmu::legacy::SlotCursor); + DropItem(EQEmu::inventory::slotCursor); return; } @@ -6919,7 +6919,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) return; } - EQEmu::ItemInstance *CursorItemInst = GetInv().GetItem(EQEmu::legacy::SlotCursor); + EQEmu::ItemInstance *CursorItemInst = GetInv().GetItem(EQEmu::inventory::slotCursor); bool Allowed = true; @@ -6967,7 +6967,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) { GuildBankDepositAck(false, sentAction); - DeleteItemInInventory(EQEmu::legacy::SlotCursor, 0, false); + DeleteItemInInventory(EQEmu::inventory::slotCursor, 0, false); } break; @@ -6988,7 +6988,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) case GuildBankWithdraw: { - if (GetInv()[EQEmu::legacy::SlotCursor]) + if (GetInv()[EQEmu::inventory::slotCursor]) { Message_StringID(13, GUILD_BANK_EMPTY_HANDS); @@ -7034,7 +7034,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) { PushItemOnCursor(*inst); - SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketLimbo); + SendItemPacket(EQEmu::inventory::slotCursor, inst, ItemPacketLimbo); GuildBanks->DeleteItem(GuildID(), gbwis->Area, gbwis->SlotID, gbwis->Quantity); } @@ -8016,7 +8016,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) const EQEmu::ItemData* item = nullptr; int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - for (int16 L = EQEmu::legacy::EQUIPMENT_BEGIN; L <= EQEmu::legacy::SlotWaist; L++) { + for (int16 L = EQEmu::legacy::EQUIPMENT_BEGIN; L <= EQEmu::inventory::slotWaist; L++) { const EQEmu::ItemInstance* inst = GetInv().GetItem(L); item = inst ? inst->GetItem() : nullptr; @@ -8036,7 +8036,7 @@ void Client::Handle_OP_InspectAnswer(const EQApplicationPacket *app) else { insr->itemicons[L] = 0xFFFFFFFF; } } - const EQEmu::ItemInstance* inst = GetInv().GetItem(EQEmu::legacy::SlotAmmo); + const EQEmu::ItemInstance* inst = GetInv().GetItem(EQEmu::inventory::slotAmmo); item = inst ? inst->GetItem() : nullptr; if (item) { @@ -8498,7 +8498,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) EQEmu::ItemInstance* clickaug = 0; EQEmu::ItemData* augitem = 0; - for (r = 0; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { + for (r = EQEmu::inventory::socketBegin; r < EQEmu::inventory::SocketCount; r++) { const EQEmu::ItemInstance* aug_i = inst->GetAugment(r); if (!aug_i) continue; @@ -12031,7 +12031,7 @@ void Client::Handle_OP_Shielding(const EQApplicationPacket *app) Shielding_Struct* shield = (Shielding_Struct*)app->pBuffer; shield_target = entity_list.GetMob(shield->target_id); bool ack = false; - EQEmu::ItemInstance* inst = GetInv().GetItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance* inst = GetInv().GetItem(EQEmu::inventory::slotSecondary); if (!shield_target) return; if (inst) @@ -12243,8 +12243,8 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app) // shouldn't we be reimbursing if these two fail? //make sure we are not completely full... - if (freeslotid == EQEmu::legacy::SlotCursor) { - if (m_inv.GetItem(EQEmu::legacy::SlotCursor) != nullptr) { + if (freeslotid == EQEmu::inventory::slotCursor) { + if (m_inv.GetItem(EQEmu::inventory::slotCursor) != nullptr) { Message(13, "You do not have room for any more items."); safe_delete(outapp); safe_delete(inst); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 8e2ab8313..55843e724 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -296,7 +296,7 @@ bool Client::Process() { } if(AutoFireEnabled()){ - EQEmu::ItemInstance *ranged = GetInv().GetItem(EQEmu::legacy::SlotRange); + EQEmu::ItemInstance *ranged = GetInv().GetItem(EQEmu::inventory::slotRange); if(ranged) { if (ranged->GetItem() && ranged->GetItem()->ItemType == EQEmu::item::ItemTypeBow){ @@ -391,10 +391,10 @@ bool Client::Process() { } else if (auto_attack_target->GetHP() > -10) // -10 so we can watch people bleed in PvP { - EQEmu::ItemInstance *wpn = GetInv().GetItem(EQEmu::legacy::SlotPrimary); - TryWeaponProc(wpn, auto_attack_target, EQEmu::legacy::SlotPrimary); + EQEmu::ItemInstance *wpn = GetInv().GetItem(EQEmu::inventory::slotPrimary); + TryWeaponProc(wpn, auto_attack_target, EQEmu::inventory::slotPrimary); - DoAttackRounds(auto_attack_target, EQEmu::legacy::SlotPrimary); + DoAttackRounds(auto_attack_target, EQEmu::inventory::slotPrimary); if (CheckAATimer(aaTimerRampage)) entity_list.AEAttack(this, 30); } @@ -430,10 +430,10 @@ bool Client::Process() { else if(auto_attack_target->GetHP() > -10) { CheckIncreaseSkill(EQEmu::skills::SkillDualWield, auto_attack_target, -10); if (CheckDualWield()) { - EQEmu::ItemInstance *wpn = GetInv().GetItem(EQEmu::legacy::SlotSecondary); - TryWeaponProc(wpn, auto_attack_target, EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance *wpn = GetInv().GetItem(EQEmu::inventory::slotSecondary); + TryWeaponProc(wpn, auto_attack_target, EQEmu::inventory::slotSecondary); - DoAttackRounds(auto_attack_target, EQEmu::legacy::SlotSecondary); + DoAttackRounds(auto_attack_target, EQEmu::inventory::slotSecondary); } } } @@ -763,7 +763,7 @@ void Client::BulkSendInventoryItems() EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); // Possessions items - for (int16 slot_id = SLOT_BEGIN; slot_id < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; slot_id++) { + for (int16 slot_id = EQEmu::inventory::slotBegin; slot_id < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; slot_id++) { const EQEmu::ItemInstance* inst = m_inv[slot_id]; if (!inst) continue; @@ -778,12 +778,12 @@ void Client::BulkSendInventoryItems() // PowerSource item if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - const EQEmu::ItemInstance* inst = m_inv[EQEmu::legacy::SlotPowerSource]; + const EQEmu::ItemInstance* inst = m_inv[EQEmu::inventory::slotPowerSource]; if (inst) { - inst->Serialize(ob, EQEmu::legacy::SlotPowerSource); + inst->Serialize(ob, EQEmu::inventory::slotPowerSource); if (ob.tellp() == last_pos) - Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", EQEmu::legacy::SlotPowerSource); + Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", EQEmu::inventory::slotPowerSource); last_pos = ob.tellp(); } @@ -1095,7 +1095,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) switch(memspell->scribing) { case memSpellScribing: { // scribing spell to book - const EQEmu::ItemInstance* inst = m_inv[EQEmu::legacy::SlotCursor]; + const EQEmu::ItemInstance* inst = m_inv[EQEmu::inventory::slotCursor]; if (inst && inst->IsClassCommon()) { @@ -1109,7 +1109,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app) if(item && item->Scroll.Effect == (int32)(memspell->spell_id)) { ScribeSpell(memspell->spell_id, memspell->slot); - DeleteItemInInventory(EQEmu::legacy::SlotCursor, 1, true); + DeleteItemInInventory(EQEmu::inventory::slotCursor, 1, true); } else Message(0,"Scribing spell: inst exists but item does not or spell ids do not match."); diff --git a/zone/command.cpp b/zone/command.cpp index 1ac321223..487e25286 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2417,14 +2417,14 @@ void command_texture(Client *c, const Seperator *sep) // Player Races Wear Armor, so Wearchange is sent instead int i; if (!c->GetTarget()) - for (i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTintableTexture; i++) + for (i = EQEmu::textures::textureBegin; i <= EQEmu::textures::LastTintableTexture; i++) { c->SendTextureWC(i, texture); } else if ((c->GetTarget()->GetRace() > 0 && c->GetTarget()->GetRace() <= 12) || c->GetTarget()->GetRace() == 128 || c->GetTarget()->GetRace() == 130 || c->GetTarget()->GetRace() == 330 || c->GetTarget()->GetRace() == 522) { - for (i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTintableTexture; i++) + for (i = EQEmu::textures::textureBegin; i <= EQEmu::textures::LastTintableTexture; i++) { c->GetTarget()->SendTextureWC(i, texture); } @@ -2567,14 +2567,14 @@ void command_peekinv(Client *c, const Seperator *sep) } if ((scopeWhere & peekWorn) && (targetClient->ClientVersion() >= EQEmu::versions::ClientVersion::SoF)) { - inst_main = targetClient->GetInv().GetItem(EQEmu::legacy::SlotPowerSource); + inst_main = targetClient->GetInv().GetItem(EQEmu::inventory::slotPowerSource); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); item_link = linker.GenerateLink(); c->Message((item_data == nullptr), "WornSlot: %i, Item: %i (%s), Charges: %i", - EQEmu::legacy::SlotPowerSource, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); + EQEmu::inventory::slotPowerSource, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); } // inv @@ -2588,7 +2588,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "InvSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = EQEmu::inventory::containerBegin; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2608,7 +2608,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message(1, "CursorSlot: %i, Item: %i (%s), Charges: %i", - EQEmu::legacy::SlotCursor, 0, item_link.c_str(), 0); + EQEmu::inventory::slotCursor, 0, item_link.c_str(), 0); } else { int cursorDepth = 0; @@ -2620,9 +2620,9 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), "CursorSlot: %i, Depth: %i, Item: %i (%s), Charges: %i", - EQEmu::legacy::SlotCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); + EQEmu::inventory::slotCursor, cursorDepth, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; (cursorDepth == 0) && inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = EQEmu::inventory::containerBegin; (cursorDepth == 0) && inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2630,7 +2630,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(EQEmu::legacy::SlotCursor, indexSub), EQEmu::legacy::SlotCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + Inventory::CalcSlotId(EQEmu::inventory::slotCursor, indexSub), EQEmu::inventory::slotCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } } @@ -2659,7 +2659,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "BankSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = EQEmu::inventory::containerBegin; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2681,7 +2681,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "SharedBankSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = EQEmu::inventory::containerBegin; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2704,7 +2704,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "TradeSlot: %i, Item: %i (%s), Charges: %i", indexMain, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = EQEmu::inventory::containerBegin; inst_main && inst_main->IsClassBag() && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -2726,7 +2726,7 @@ void command_peekinv(Client *c, const Seperator *sep) else { c->Message(0, "[WorldObject DBID: %i (entityid: %i)]", objectTradeskill->GetDBID(), objectTradeskill->GetID()); - for (int16 indexMain = SLOT_BEGIN; indexMain < EQEmu::legacy::TYPE_WORLD_SIZE; ++indexMain) { + for (int16 indexMain = EQEmu::inventory::slotBegin; indexMain < EQEmu::legacy::TYPE_WORLD_SIZE; ++indexMain) { inst_main = objectTradeskill->GetItem(indexMain); item_data = (inst_main == nullptr) ? nullptr : inst_main->GetItem(); linker.SetItemInst(inst_main); @@ -2736,7 +2736,7 @@ void command_peekinv(Client *c, const Seperator *sep) c->Message((item_data == nullptr), "WorldSlot: %i, Item: %i (%s), Charges: %i", (EQEmu::legacy::WORLD_BEGIN + indexMain), ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_main == nullptr) ? 0 : inst_main->GetCharges())); - for (uint8 indexSub = SUB_INDEX_BEGIN; inst_main && inst_main->IsType(EQEmu::item::ItemClassBag) && (indexSub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++indexSub) { + for (uint8 indexSub = EQEmu::inventory::containerBegin; inst_main && inst_main->IsType(EQEmu::item::ItemClassBag) && (indexSub < EQEmu::inventory::ContainerCount); ++indexSub) { inst_sub = inst_main->GetItem(indexSub); item_data = (inst_sub == nullptr) ? nullptr : inst_sub->GetItem(); linker.SetItemInst(inst_sub); @@ -3145,8 +3145,8 @@ void command_listpetition(Client *c, const Seperator *sep) void command_equipitem(Client *c, const Seperator *sep) { uint32 slot_id = atoi(sep->arg[1]); - if (sep->IsNumber(1) && ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::legacy::SlotPowerSource))) { - const EQEmu::ItemInstance* from_inst = c->GetInv().GetItem(EQEmu::legacy::SlotCursor); + if (sep->IsNumber(1) && ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN) && (slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::inventory::slotPowerSource))) { + const EQEmu::ItemInstance* from_inst = c->GetInv().GetItem(EQEmu::inventory::slotCursor); const EQEmu::ItemInstance* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack) bool partialmove = false; int16 movecount; @@ -3154,7 +3154,7 @@ void command_equipitem(Client *c, const Seperator *sep) if (from_inst && from_inst->IsClassCommon()) { auto outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer; - mi->from_slot = EQEmu::legacy::SlotCursor; + mi->from_slot = EQEmu::inventory::slotCursor; mi->to_slot = slot_id; // mi->number_in_stack = from_inst->GetCharges(); // replaced with con check for stacking @@ -4339,7 +4339,7 @@ void command_goto(Client *c, const Seperator *sep) void command_iteminfo(Client *c, const Seperator *sep) { - auto inst = c->GetInv()[EQEmu::legacy::SlotCursor]; + auto inst = c->GetInv()[EQEmu::inventory::slotCursor]; if (!inst) { c->Message(13, "Error: You need an item on your cursor for this command"); return; @@ -7124,7 +7124,7 @@ void command_path(Client *c, const Seperator *sep) } void Client::Undye() { - for (int cur_slot = EQEmu::textures::TextureBegin; cur_slot <= EQEmu::textures::LastTexture; cur_slot++) { + for (int cur_slot = EQEmu::textures::textureBegin; cur_slot <= EQEmu::textures::LastTexture; cur_slot++) { uint8 slot2=SlotConvert(cur_slot); EQEmu::ItemInstance* inst = m_inv.GetItem(slot2); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 3690a3b4f..57a85aff9 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -323,12 +323,12 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( // to go into the regular slots on the player, out of bags std::list removed_list; - for (i = SLOT_BEGIN; i < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; ++i) { - if (i == EQEmu::legacy::SlotAmmo && client->ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { - item = client->GetInv().GetItem(EQEmu::legacy::SlotPowerSource); + for (i = EQEmu::inventory::slotBegin; i < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; ++i) { + if (i == EQEmu::inventory::slotAmmo && client->ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { + item = client->GetInv().GetItem(EQEmu::inventory::slotPowerSource); if (item != nullptr) { if (!client->IsBecomeNPC() || (client->IsBecomeNPC() && !item->GetItem()->NoRent)) - MoveItemToCorpse(client, item, EQEmu::legacy::SlotPowerSource, removed_list); + MoveItemToCorpse(client, item, EQEmu::inventory::slotPowerSource, removed_list); } } @@ -405,9 +405,9 @@ void Corpse::MoveItemToCorpse(Client *client, EQEmu::ItemInstance *inst, int16 e while (true) { if (!inst->IsClassBag()) { break; } - if (equipSlot < EQEmu::legacy::GENERAL_BEGIN || equipSlot > EQEmu::legacy::SlotCursor) { break; } + if (equipSlot < EQEmu::legacy::GENERAL_BEGIN || equipSlot > EQEmu::inventory::slotCursor) { break; } - for (auto sub_index = SUB_INDEX_BEGIN; sub_index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++sub_index) { + for (int16 sub_index = EQEmu::inventory::containerBegin; sub_index < EQEmu::inventory::ContainerCount; ++sub_index) { int16 real_bag_slot = Inventory::CalcSlotId(equipSlot, sub_index); auto bag_inst = client->GetInv().GetItem(real_bag_slot); if (bag_inst == nullptr) { continue; } @@ -685,7 +685,7 @@ ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** } if (sitem && bag_item_data && Inventory::SupportsContainers(sitem->equip_slot)) { - int16 bagstart = Inventory::CalcSlotId(sitem->equip_slot, SUB_INDEX_BEGIN); + int16 bagstart = Inventory::CalcSlotId(sitem->equip_slot, EQEmu::inventory::containerBegin); cur = itemlist.begin(); end = itemlist.end(); @@ -740,7 +740,7 @@ void Corpse::RemoveItem(ServerLootItem_Struct* item_data) itemlist.erase(iter); uint8 material = Inventory::CalcMaterialFromSlot(sitem->equip_slot); // autos to unsigned char - if (material != EQEmu::textures::TextureInvalid) + if (material != EQEmu::textures::materialInvalid) SendWearChange(material); UpdateEquipmentLight(); @@ -999,7 +999,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()))->InventoryTypeSize[EQEmu::legacy::TypeCorpse]; + int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()))->InventoryTypeSize[EQEmu::inventory::typeCorpse]; for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; @@ -1008,7 +1008,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a // Dont display the item if it's in a bag // Added cursor queue slots to corpse item visibility list. Nothing else should be making it to corpse. - if (!IsPlayerCorpse() || item_data->equip_slot <= EQEmu::legacy::SlotCursor || item_data->equip_slot == EQEmu::legacy::SlotPowerSource || Loot_Request_Type >= 3 || + if (!IsPlayerCorpse() || item_data->equip_slot <= EQEmu::inventory::slotCursor || item_data->equip_slot == EQEmu::inventory::slotPowerSource || Loot_Request_Type >= 3 || (item_data->equip_slot >= 8000 && item_data->equip_slot <= 8999)) { if(i < corpselootlimit) { item = database.GetItem(item_data->item_id); @@ -1148,7 +1148,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } if (inst->IsAugmented()) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { EQEmu::ItemInstance *itm = inst->GetAugment(i); if (itm) { if (client->CheckLoreConflict(itm->GetItem())) { @@ -1190,10 +1190,10 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { /* First add it to the looter - this will do the bag contents too */ if (lootitem->auto_loot) { if (!client->AutoPutLootInInventory(*inst, true, true, bag_item_data)) - client->PutLootInInventory(EQEmu::legacy::SlotCursor, *inst, bag_item_data); + client->PutLootInInventory(EQEmu::inventory::slotCursor, *inst, bag_item_data); } else { - client->PutLootInInventory(EQEmu::legacy::SlotCursor, *inst, bag_item_data); + client->PutLootInInventory(EQEmu::inventory::slotCursor, *inst, bag_item_data); } /* Update any tasks that have an activity to loot this item */ @@ -1210,7 +1210,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { /* Remove Bag Contents */ if (item->IsClassBag() && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) { - for (int i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { + for (int i = EQEmu::inventory::containerBegin; i < EQEmu::inventory::ContainerCount; i++) { if (bag_item_data[i]) { /* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */ database.DeleteItemOffCharacterCorpse(this->corpse_db_id, bag_item_data[i]->equip_slot, bag_item_data[i]->item_id); @@ -1294,7 +1294,7 @@ void Corpse::QueryLoot(Client* to) { cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()))->InventoryTypeSize[EQEmu::legacy::TypeCorpse]; + int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()))->InventoryTypeSize[EQEmu::inventory::typeCorpse]; for(; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; @@ -1403,12 +1403,12 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { int16 invslot; if (material_slot > EQEmu::textures::LastTexture) { - return NO_ITEM; + return 0; } invslot = Inventory::CalcSlotFromMaterial(material_slot); - if(invslot == INVALID_INDEX) // GetWornItem() should be returning a NO_ITEM for any invalid index... - return NO_ITEM; + if(invslot == INVALID_INDEX) // GetWornItem() should be returning a 0 for any invalid index... + return 0; return GetWornItem(invslot); } @@ -1421,7 +1421,7 @@ uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { } item = database.GetItem(GetEquipment(material_slot)); - if(item != NO_ITEM) { + if(item != 0) { return (item_tint.Slot[material_slot].UseTint ? item_tint.Slot[material_slot].Color : item->Color); } @@ -1434,8 +1434,8 @@ void Corpse::UpdateEquipmentLight() m_Light.Level[EQEmu::lightsource::LightEquipment] = 0; for (auto iter = itemlist.begin(); iter != itemlist.end(); ++iter) { - if (((*iter)->equip_slot < EQEmu::legacy::EQUIPMENT_BEGIN || (*iter)->equip_slot > EQEmu::legacy::EQUIPMENT_END) && (*iter)->equip_slot != EQEmu::legacy::SlotPowerSource) { continue; } - if ((*iter)->equip_slot == EQEmu::legacy::SlotAmmo) { continue; } + if (((*iter)->equip_slot < EQEmu::legacy::EQUIPMENT_BEGIN || (*iter)->equip_slot > EQEmu::legacy::EQUIPMENT_END) && (*iter)->equip_slot != EQEmu::inventory::slotPowerSource) { continue; } + if ((*iter)->equip_slot == EQEmu::inventory::slotAmmo) { continue; } auto item = database.GetItem((*iter)->item_id); if (item == nullptr) { continue; } diff --git a/zone/corpse.h b/zone/corpse.h index e43c4c020..e83235c1e 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -53,7 +53,7 @@ class Corpse : public Mob { /* Corpse: General */ virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; } virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } - virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } + virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } diff --git a/zone/doors.cpp b/zone/doors.cpp index dd3dbd651..45953fc89 100644 --- a/zone/doors.cpp +++ b/zone/doors.cpp @@ -188,7 +188,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) uint8 keepoffkeyring = GetNoKeyring(); uint32 haskey = 0; uint32 playerkey = 0; - const EQEmu::ItemInstance *lockpicks = sender->GetInv().GetItem(EQEmu::legacy::SlotCursor); + const EQEmu::ItemInstance *lockpicks = sender->GetInv().GetItem(EQEmu::inventory::slotCursor); haskey = sender->GetInv().HasItem(keyneeded, 1); diff --git a/zone/encounter.h b/zone/encounter.h index ed8faec34..8b672fdd4 100644 --- a/zone/encounter.h +++ b/zone/encounter.h @@ -36,7 +36,7 @@ public: //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; } virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } - virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } diff --git a/zone/entity.h b/zone/entity.h index 8abb34ca2..d2141d1b9 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -352,7 +352,7 @@ public: void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app); void QueueManaged(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, bool ackreq = true); - void AEAttack(Mob *attacker, float dist, int Hand = EQEmu::legacy::SlotPrimary, int count = 0, bool IsFromSpell = false); + void AEAttack(Mob *attacker, float dist, int Hand = EQEmu::inventory::slotPrimary, int count = 0, bool IsFromSpell = false); void AETaunt(Client *caster, float range=0, int32 bonus_hate=0); void AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true, int16 resist_adjust = 0); void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true); diff --git a/zone/forage.cpp b/zone/forage.cpp index b1ff0f545..aec4d6b73 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -153,7 +153,7 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id, //we need this function to immediately determine, after we receive OP_Fishing, if we can even try to fish, otherwise we have to wait a while to get the failure bool Client::CanFish() { //make sure we still have a fishing pole on: - const EQEmu::ItemInstance* Pole = m_inv[EQEmu::legacy::SlotPrimary]; + const EQEmu::ItemInstance* Pole = m_inv[EQEmu::inventory::slotPrimary]; int32 bslot = m_inv.HasItemByUse(EQEmu::item::ItemTypeFishingBait, 1, invWhereWorn | invWherePersonal); const EQEmu::ItemInstance* Bait = nullptr; if (bslot != INVALID_INDEX) @@ -317,12 +317,12 @@ void Client::GoFish() else { PushItemOnCursor(*inst); - SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketLimbo); + SendItemPacket(EQEmu::inventory::slotCursor, inst, ItemPacketLimbo); if(RuleB(TaskSystem, EnableTaskSystem)) UpdateTasksForItem(ActivityFish, food_id); safe_delete(inst); - inst = m_inv.GetItem(EQEmu::legacy::SlotCursor); + inst = m_inv.GetItem(EQEmu::inventory::slotCursor); } if(inst) { @@ -354,7 +354,7 @@ void Client::GoFish() //and then swap out items in primary slot... too lazy to fix right now if (zone->random.Int(0, 49) == 1) { Message_StringID(MT_Skills, FISHING_POLE_BROKE); //Your fishing pole broke! - DeleteItemInInventory(EQEmu::legacy::SlotPrimary, 0, true); + DeleteItemInInventory(EQEmu::inventory::slotPrimary, 0, true); } if (CheckIncreaseSkill(EQEmu::skills::SkillFishing, nullptr, 5)) @@ -431,12 +431,12 @@ void Client::ForageItem(bool guarantee) { } else { PushItemOnCursor(*inst); - SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketLimbo); + SendItemPacket(EQEmu::inventory::slotCursor, inst, ItemPacketLimbo); if(RuleB(TaskSystem, EnableTaskSystem)) UpdateTasksForItem(ActivityForage, foragedfood); safe_delete(inst); - inst = m_inv.GetItem(EQEmu::legacy::SlotCursor); + inst = m_inv.GetItem(EQEmu::inventory::slotCursor); } if(inst) { diff --git a/zone/inventory.cpp b/zone/inventory.cpp index ae0a82ae3..c89879610 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -48,8 +48,8 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } } - if (GetItemIDAt(EQEmu::legacy::SlotPowerSource) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(EQEmu::legacy::SlotPowerSource) != INVALID_ID)) { - cur = m_inv.GetItem(EQEmu::legacy::SlotPowerSource); + if (GetItemIDAt(EQEmu::inventory::slotPowerSource) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(EQEmu::inventory::slotPowerSource) != INVALID_ID)) { + cur = m_inv.GetItem(EQEmu::inventory::slotPowerSource); if(cur && cur->GetItem()->Stackable) { x += cur->GetCharges(); } else { @@ -57,22 +57,22 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { } if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) - DeleteItemInInventory(EQEmu::legacy::SlotPowerSource, 0, true); + DeleteItemInInventory(EQEmu::inventory::slotPowerSource, 0, true); else - DeleteItemInInventory(EQEmu::legacy::SlotPowerSource, 0, false); // Prevents Titanium crash + DeleteItemInInventory(EQEmu::inventory::slotPowerSource, 0, false); // Prevents Titanium crash } } if(where_to_check & invWhereCursor) { - if (GetItemIDAt(EQEmu::legacy::SlotCursor) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(EQEmu::legacy::SlotCursor) != INVALID_ID)) { - cur = m_inv.GetItem(EQEmu::legacy::SlotCursor); + if (GetItemIDAt(EQEmu::inventory::slotCursor) == itemnum || (itemnum == 0xFFFE && GetItemIDAt(EQEmu::inventory::slotCursor) != INVALID_ID)) { + cur = m_inv.GetItem(EQEmu::inventory::slotCursor); if(cur && cur->GetItem()->Stackable) { x += cur->GetCharges(); } else { x++; } - DeleteItemInInventory(EQEmu::legacy::SlotCursor, 0, true); + DeleteItemInInventory(EQEmu::inventory::slotCursor, 0, true); } for (i = EQEmu::legacy::CURSOR_BAG_BEGIN; i <= EQEmu::legacy::CURSOR_BAG_END; i++) { @@ -236,7 +236,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, } */ - uint32 augments[EQEmu::legacy::ITEM_COMMON_SIZE] = { aug1, aug2, aug3, aug4, aug5, aug6 }; + uint32 augments[EQEmu::inventory::SocketCount] = { aug1, aug2, aug3, aug4, aug5, aug6 }; uint32 classes = item->Classes; uint32 races = item->Races; @@ -246,7 +246,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, bool enforcerestr = RuleB(Inventory, EnforceAugmentRestriction); bool enforceusable = RuleB(Inventory, EnforceAugmentUsability); - for (int iter = AUG_INDEX_BEGIN; iter < EQEmu::legacy::ITEM_COMMON_SIZE; ++iter) { + for (int iter = EQEmu::inventory::socketBegin; iter < EQEmu::inventory::SocketCount; ++iter) { const EQEmu::ItemData* augtest = database.GetItem(augments[iter]); if(augtest == nullptr) { @@ -540,7 +540,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, } // add any validated augments - for (int iter = AUG_INDEX_BEGIN; iter < EQEmu::legacy::ITEM_COMMON_SIZE; ++iter) { + for (int iter = EQEmu::inventory::socketBegin; iter < EQEmu::inventory::SocketCount; ++iter) { if(augments[iter]) inst->PutAugment(&database, iter, augments[iter]); } @@ -554,22 +554,22 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, inst->SetOrnamentHeroModel(ornament_hero_model); // check to see if item is usable in requested slot - if (enforceusable && (((to_slot >= EQEmu::legacy::SlotCharm) && (to_slot <= EQEmu::legacy::SlotAmmo)) || (to_slot == EQEmu::legacy::SlotPowerSource))) { - uint32 slottest = (to_slot == EQEmu::legacy::SlotPowerSource) ? 22 : to_slot; // can't change '22' just yet... + if (enforceusable && (((to_slot >= EQEmu::inventory::slotCharm) && (to_slot <= EQEmu::inventory::slotAmmo)) || (to_slot == EQEmu::inventory::slotPowerSource))) { + uint32 slottest = (to_slot == EQEmu::inventory::slotPowerSource) ? 22 : to_slot; // can't change '22' just yet... if(!(slots & ((uint32)1 << slottest))) { Message(0, "This item is not equipable at slot %u - moving to cursor.", to_slot); Log.Out(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to equip an item unusable in slot %u - moved to cursor.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", GetName(), account_name, to_slot, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); - to_slot = EQEmu::legacy::SlotCursor; + to_slot = EQEmu::inventory::slotCursor; } } // put item into inventory - if (to_slot == EQEmu::legacy::SlotCursor) { + if (to_slot == EQEmu::inventory::slotCursor) { PushItemOnCursor(*inst); - SendItemPacket(EQEmu::legacy::SlotCursor, inst, ItemPacketLimbo); + SendItemPacket(EQEmu::inventory::slotCursor, inst, ItemPacketLimbo); } else { PutItemInInventory(to_slot, *inst, true); @@ -617,7 +617,7 @@ void Client::DropItem(int16 slot_id) } // Save client inventory change to database - if (slot_id == EQEmu::legacy::SlotCursor) { + if (slot_id == EQEmu::inventory::slotCursor) { SendCursorBuffer(); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(CharacterID(), s, e); @@ -706,11 +706,11 @@ void Client::SendCursorBuffer() GetName(), test_item->Name, test_item->ID); Message_StringID(MT_LootMessages, 290); parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); - DeleteItemInInventory(EQEmu::legacy::SlotCursor); + DeleteItemInInventory(EQEmu::inventory::slotCursor); SendCursorBuffer(); } else { - SendItemPacket(EQEmu::legacy::SlotCursor, test_inst, ItemPacketLimbo); + SendItemPacket(EQEmu::inventory::slotCursor, test_inst, ItemPacketLimbo); } } @@ -763,7 +763,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd qsaudit->items[parent_offset].aug_5 = m_inv[slot_id]->GetAugmentItemID(5); if (m_inv[slot_id]->IsClassBag()) { - for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) { + for (uint8 bag_idx = EQEmu::inventory::containerBegin; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) { EQEmu::ItemInstance* bagitem = m_inv[slot_id]->GetItem(bag_idx); if(bagitem) { @@ -790,7 +790,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd bool isDeleted = m_inv.DeleteItem(slot_id, quantity); const EQEmu::ItemInstance* inst = nullptr; - if (slot_id == EQEmu::legacy::SlotCursor) { + if (slot_id == EQEmu::inventory::slotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); if(update_db) database.SaveCursor(character_id, s, e); @@ -842,7 +842,7 @@ bool Client::PushItemOnCursor(const EQEmu::ItemInstance& inst, bool client_updat m_inv.PushCursor(inst); if (client_update) { - SendItemPacket(EQEmu::legacy::SlotCursor, &inst, ItemPacketLimbo); + SendItemPacket(EQEmu::inventory::slotCursor, &inst, ItemPacketLimbo); } auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); @@ -856,7 +856,7 @@ bool Client::PushItemOnCursor(const EQEmu::ItemInstance& inst, bool client_updat bool Client::PutItemInInventory(int16 slot_id, const EQEmu::ItemInstance& inst, bool client_update) { Log.Out(Logs::Detail, Logs::Inventory, "Putting item %s (%d) into slot %d", inst.GetItem()->Name, inst.GetItem()->ID, slot_id); - if (slot_id == EQEmu::legacy::SlotCursor) { // don't trust macros before conditional statements... + if (slot_id == EQEmu::inventory::slotCursor) { // don't trust macros before conditional statements... return PushItemOnCursor(inst, client_update); } else { @@ -865,11 +865,11 @@ bool Client::PutItemInInventory(int16 slot_id, const EQEmu::ItemInstance& inst, if (client_update) { - SendItemPacket(slot_id, &inst, ((slot_id == EQEmu::legacy::SlotCursor) ? ItemPacketLimbo : ItemPacketTrade)); + SendItemPacket(slot_id, &inst, ((slot_id == EQEmu::inventory::slotCursor) ? ItemPacketLimbo : ItemPacketTrade)); //SendWearChange(Inventory::CalcMaterialFromSlot(slot_id)); } - if (slot_id == EQEmu::legacy::SlotCursor) { + if (slot_id == EQEmu::inventory::slotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); return database.SaveCursor(this->CharacterID(), s, e); } @@ -887,7 +887,7 @@ void Client::PutLootInInventory(int16 slot_id, const EQEmu::ItemInstance &inst, bool cursor_empty = m_inv.CursorEmpty(); - if (slot_id == EQEmu::legacy::SlotCursor) { + if (slot_id == EQEmu::inventory::slotCursor) { m_inv.PushCursor(inst); auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(this->CharacterID(), s, e); @@ -898,7 +898,7 @@ void Client::PutLootInInventory(int16 slot_id, const EQEmu::ItemInstance &inst, } // Subordinate items in cursor buffer must be sent via ItemPacketSummonItem or we just overwrite the visible cursor and desync the client - if (slot_id == EQEmu::legacy::SlotCursor && !cursor_empty) { + if (slot_id == EQEmu::inventory::slotCursor && !cursor_empty) { // RoF+ currently has a specialized cursor handler if (ClientVersion() < EQEmu::versions::ClientVersion::RoF) SendItemPacket(slot_id, &inst, ItemPacketLimbo); @@ -908,7 +908,7 @@ void Client::PutLootInInventory(int16 slot_id, const EQEmu::ItemInstance &inst, } if (bag_item_data) { - for (int index = 0; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { + for (int index = 0; index < EQEmu::inventory::ContainerCount; ++index) { if (bag_item_data[index] == nullptr) continue; @@ -926,12 +926,12 @@ void Client::PutLootInInventory(int16 slot_id, const EQEmu::ItemInstance &inst, // Dump bag contents to cursor in the event that owning bag is not the first cursor item // (This assumes that the data passed is correctly associated..no safety checks are implemented) - if (slot_id == EQEmu::legacy::SlotCursor && !cursor_empty) { + if (slot_id == EQEmu::inventory::slotCursor && !cursor_empty) { Log.Out(Logs::Detail, Logs::Inventory, "Putting bag loot item %s (%d) into slot %d (non-empty cursor override)", - inst.GetItem()->Name, inst.GetItem()->ID, EQEmu::legacy::SlotCursor); + inst.GetItem()->Name, inst.GetItem()->ID, EQEmu::inventory::slotCursor); - PutLootInInventory(EQEmu::legacy::SlotCursor, *bagitem); + PutLootInInventory(EQEmu::inventory::slotCursor, *bagitem); } else { auto bag_slot = Inventory::CalcSlotId(slot_id, index); @@ -965,7 +965,7 @@ bool Client::TryStacking(EQEmu::ItemInstance* item, uint8 type, bool try_worn, b } } for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { - for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::legacy::ITEM_CONTAINER_SIZE; j++) { + for (uint8 j = EQEmu::inventory::containerBegin; j < EQEmu::inventory::ContainerCount; j++) { uint16 slotid = Inventory::CalcSlotId(i, j); EQEmu::ItemInstance* tmp_inst = m_inv.GetItem(slotid); @@ -990,28 +990,28 @@ bool Client::AutoPutLootInInventory(EQEmu::ItemInstance& inst, bool try_worn, bo // #1: Try to auto equip if (try_worn && inst.IsEquipable(GetBaseRace(), GetClass()) && inst.GetItem()->ReqLevel <= level && (!inst.GetItem()->Attuneable || inst.IsAttuned()) && inst.GetItem()->ItemType != EQEmu::item::ItemTypeAugmentation) { // too messy as-is... - for (int16 i = EQEmu::legacy::EQUIPMENT_BEGIN; i < EQEmu::legacy::SlotPowerSource; i++) { // originally (i < 22) + for (int16 i = EQEmu::legacy::EQUIPMENT_BEGIN; i < EQEmu::inventory::slotPowerSource; i++) { // originally (i < 22) if (i == EQEmu::legacy::GENERAL_BEGIN) { // added power source check for SoF+ clients if (this->ClientVersion() >= EQEmu::versions::ClientVersion::SoF) - i = EQEmu::legacy::SlotPowerSource; + i = EQEmu::inventory::slotPowerSource; else break; } if (!m_inv[i]) { - if (i == EQEmu::legacy::SlotPrimary && inst.IsWeapon()) { // If item is primary slot weapon + if (i == EQEmu::inventory::slotPrimary && inst.IsWeapon()) { // If item is primary slot weapon if (inst.GetItem()->IsType2HWeapon()) { // and uses 2hs \ 2hb \ 2hp - if (m_inv[EQEmu::legacy::SlotSecondary]) { // and if secondary slot is not empty + if (m_inv[EQEmu::inventory::slotSecondary]) { // and if secondary slot is not empty continue; // Can't auto-equip } } } - if (i == EQEmu::legacy::SlotSecondary && m_inv[EQEmu::legacy::SlotPrimary]) { // check to see if primary slot is a two hander - if (m_inv[EQEmu::legacy::SlotPrimary]->GetItem()->IsType2HWeapon()) + if (i == EQEmu::inventory::slotSecondary && m_inv[EQEmu::inventory::slotPrimary]) { // check to see if primary slot is a two hander + if (m_inv[EQEmu::inventory::slotPrimary]->GetItem()->IsType2HWeapon()) continue; } - if (i == EQEmu::legacy::SlotSecondary && inst.IsWeapon() && !CanThisClassDualWield()) { + if (i == EQEmu::inventory::slotSecondary && inst.IsWeapon() && !CanThisClassDualWield()) { continue; } @@ -1019,7 +1019,7 @@ bool Client::AutoPutLootInInventory(EQEmu::ItemInstance& inst, bool try_worn, bo //send worn to everyone... PutLootInInventory(i, inst); uint8 worn_slot_material = Inventory::CalcMaterialFromSlot(i); - if (worn_slot_material != EQEmu::textures::TextureInvalid) { + if (worn_slot_material != EQEmu::textures::materialInvalid) { SendWearChange(worn_slot_material); } @@ -1062,7 +1062,7 @@ void Client::MoveItemCharges(EQEmu::ItemInstance &from, int16 to_slot, uint8 typ tmp_inst->SetCharges(tmp_inst->GetCharges() + charges_to_move); from.SetCharges(from.GetCharges() - charges_to_move); SendLootItemInPacket(tmp_inst, to_slot); - if (to_slot == EQEmu::legacy::SlotCursor) { + if (to_slot == EQEmu::inventory::slotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(this->CharacterID(), s, e); } @@ -1319,7 +1319,7 @@ void Client::SendLootItemInPacket(const EQEmu::ItemInstance* inst, int16 slot_id bool Client::IsValidSlot(uint32 slot) { if ((slot == (uint32)INVALID_INDEX) || - (slot >= SLOT_BEGIN && slot < EQEmu::legacy::TYPE_POSSESSIONS_SIZE) || + (slot >= EQEmu::inventory::slotBegin && slot < EQEmu::legacy::TYPE_POSSESSIONS_SIZE) || (slot >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot <= EQEmu::legacy::CURSOR_BAG_END) || (slot >= EQEmu::legacy::TRIBUTE_BEGIN && slot <= EQEmu::legacy::TRIBUTE_END) || (slot >= EQEmu::legacy::BANK_BEGIN && slot <= EQEmu::legacy::BANK_END) || @@ -1328,7 +1328,7 @@ bool Client::IsValidSlot(uint32 slot) { (slot >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot <= EQEmu::legacy::SHARED_BANK_BAGS_END) || (slot >= EQEmu::legacy::TRADE_BEGIN && slot <= EQEmu::legacy::TRADE_END) || (slot >= EQEmu::legacy::WORLD_BEGIN && slot <= EQEmu::legacy::WORLD_END) || - (slot == EQEmu::legacy::SlotPowerSource) + (slot == EQEmu::inventory::slotPowerSource) ) { return true; } @@ -1378,8 +1378,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { return true; } // Can't do RoF+ - if (move_in->to_slot == EQEmu::legacy::SlotCursor) { - auto test_inst = m_inv.GetItem(EQEmu::legacy::SlotCursor); + if (move_in->to_slot == EQEmu::inventory::slotCursor) { + auto test_inst = m_inv.GetItem(EQEmu::inventory::slotCursor); if (test_inst == nullptr) { return true; } auto test_item = test_inst->GetItem(); if (test_item == nullptr) { return true; } @@ -1398,18 +1398,18 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { GetName(), test_item->Name, test_item->ID); Message_StringID(MT_LootMessages, 290); parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); - DeleteItemInInventory(EQEmu::legacy::SlotCursor, 0, true); + DeleteItemInInventory(EQEmu::inventory::slotCursor, 0, true); } } return true; } if (move_in->to_slot == (uint32)INVALID_INDEX) { - if (move_in->from_slot == (uint32)EQEmu::legacy::SlotCursor) { + if (move_in->from_slot == (uint32)EQEmu::inventory::slotCursor) { Log.Out(Logs::Detail, Logs::Inventory, "Client destroyed item from cursor slot %d", move_in->from_slot); if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit - EQEmu::ItemInstance *inst = m_inv.GetItem(EQEmu::legacy::SlotCursor); + EQEmu::ItemInstance *inst = m_inv.GetItem(EQEmu::inventory::slotCursor); if(inst) { parse->EventItem(EVENT_DESTROY_ITEM, this, inst, nullptr, "", 0); } @@ -1426,9 +1426,9 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return true; // Item deletion } } - if (auto_attack && (move_in->from_slot == EQEmu::legacy::SlotPrimary || move_in->from_slot == EQEmu::legacy::SlotSecondary || move_in->from_slot == EQEmu::legacy::SlotRange)) + if (auto_attack && (move_in->from_slot == EQEmu::inventory::slotPrimary || move_in->from_slot == EQEmu::inventory::slotSecondary || move_in->from_slot == EQEmu::inventory::slotRange)) SetAttackTimer(); - else if (auto_attack && (move_in->to_slot == EQEmu::legacy::SlotPrimary || move_in->to_slot == EQEmu::legacy::SlotSecondary || move_in->to_slot == EQEmu::legacy::SlotRange)) + else if (auto_attack && (move_in->to_slot == EQEmu::inventory::slotPrimary || move_in->to_slot == EQEmu::inventory::slotSecondary || move_in->to_slot == EQEmu::inventory::slotRange)) SetAttackTimer(); // Step 1: Variables int16 src_slot_id = (int16)move_in->from_slot; @@ -1516,7 +1516,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return(false); } if (src_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::legacy::SHARED_BANK_END && src_inst->IsClassBag()){ - for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { + for (uint8 idx = EQEmu::inventory::containerBegin; idx < EQEmu::inventory::ContainerCount; idx++) { const EQEmu::ItemInstance* baginst = src_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(src_slot_id, idx), baginst)){ DeleteItemInInventory(Inventory::CalcSlotId(src_slot_id, idx),0,false); @@ -1531,7 +1531,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return(false); } if (dst_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::legacy::SHARED_BANK_END && dst_inst->IsClassBag()){ - for (uint8 idx = SUB_INDEX_BEGIN; idx < EQEmu::legacy::ITEM_CONTAINER_SIZE; idx++) { + for (uint8 idx = EQEmu::inventory::containerBegin; idx < EQEmu::inventory::ContainerCount; idx++) { const EQEmu::ItemInstance* baginst = dst_inst->GetItem(idx); if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(dst_slot_id, idx), baginst)){ DeleteItemInInventory(Inventory::CalcSlotId(dst_slot_id, idx),0,false); @@ -1638,7 +1638,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } safe_delete(world_inst); - if (src_slot_id == EQEmu::legacy::SlotCursor) + if (src_slot_id == EQEmu::inventory::slotCursor) { if (dstitemid == 0) { @@ -1660,14 +1660,14 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { // Step 4: Check for entity trade if (dst_slot_id >= EQEmu::legacy::TRADE_BEGIN && dst_slot_id <= EQEmu::legacy::TRADE_END) { - if (src_slot_id != EQEmu::legacy::SlotCursor) { + if (src_slot_id != EQEmu::inventory::slotCursor) { Kick(); return false; } if (with) { Log.Out(Logs::Detail, Logs::Inventory, "Trade item move from slot %d to slot %d (trade with %s)", src_slot_id, dst_slot_id, with->GetName()); // Fill Trade list with items from cursor - if (!m_inv[EQEmu::legacy::SlotCursor]) { + if (!m_inv[EQEmu::inventory::slotCursor]) { Message(13, "Error: Cursor item not located on server!"); return false; } @@ -1687,7 +1687,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(RuleB(QueryServ, PlayerLogMoves)) { QSSwapItemAuditor(move_in); } // QS Audit SummonItem(src_inst->GetID(), src_inst->GetCharges()); - DeleteItemInInventory(EQEmu::legacy::SlotCursor); + DeleteItemInInventory(EQEmu::inventory::slotCursor); return true; } @@ -1752,12 +1752,12 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } else { // Not dealing with charges - just do direct swap - if (src_inst && (dst_slot_id <= EQEmu::legacy::EQUIPMENT_END || dst_slot_id == EQEmu::legacy::SlotPowerSource) && dst_slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN) { + if (src_inst && (dst_slot_id <= EQEmu::legacy::EQUIPMENT_END || dst_slot_id == EQEmu::inventory::slotPowerSource) && dst_slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN) { if (src_inst->GetItem()->Attuneable) { src_inst->SetAttuned(true); } if (src_inst->IsAugmented()) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { if (src_inst->GetAugment(i)) { if (src_inst->GetAugment(i)->GetItem()->Attuneable) { src_inst->GetAugment(i)->SetAttuned(true); @@ -1770,7 +1770,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(!m_inv.SwapItem(src_slot_id, dst_slot_id)) { return false; } Log.Out(Logs::Detail, Logs::Inventory, "Moving entire item from slot %d to slot %d", src_slot_id, dst_slot_id); - if (src_slot_id <= EQEmu::legacy::EQUIPMENT_END || src_slot_id == EQEmu::legacy::SlotPowerSource) { + if (src_slot_id <= EQEmu::legacy::EQUIPMENT_END || src_slot_id == EQEmu::inventory::slotPowerSource) { if(src_inst) { parse->EventItem(EVENT_UNEQUIP_ITEM, this, src_inst, nullptr, "", src_slot_id); } @@ -1780,7 +1780,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } } - if (dst_slot_id <= EQEmu::legacy::EQUIPMENT_END || dst_slot_id == EQEmu::legacy::SlotPowerSource) { + if (dst_slot_id <= EQEmu::legacy::EQUIPMENT_END || dst_slot_id == EQEmu::inventory::slotPowerSource) { if(dst_inst) { parse->EventItem(EVENT_UNEQUIP_ITEM, this, dst_inst, nullptr, "", dst_slot_id); } @@ -1792,12 +1792,12 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } int matslot = SlotConvert2(dst_slot_id); - if (dst_slot_id <= EQEmu::legacy::EQUIPMENT_END && matslot != EQEmu::textures::TextureHead) { // think this is to allow the client to update with /showhelm + if (dst_slot_id <= EQEmu::legacy::EQUIPMENT_END && matslot != EQEmu::textures::armorHead) { // think this is to allow the client to update with /showhelm SendWearChange(matslot); } // Step 7: Save change to the database - if (src_slot_id == EQEmu::legacy::SlotCursor) { + if (src_slot_id == EQEmu::inventory::slotCursor) { // If not swapping another item to cursor and stacking items were depleted if (dstitemid == 0 || all_to_stack == true) { @@ -1810,7 +1810,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { database.SaveInventory(character_id, m_inv.GetItem(src_slot_id), src_slot_id); } - if (dst_slot_id == EQEmu::legacy::SlotCursor) { + if (dst_slot_id == EQEmu::inventory::slotCursor) { auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); database.SaveCursor(character_id, s, e); } @@ -1834,7 +1834,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { Log.Out(Logs::Detail, Logs::Inventory, "Inventory desyncronization. (charname: %s, source: %i, destination: %i)", GetName(), move_slots->from_slot, move_slots->to_slot); Message(15, "Inventory Desyncronization detected: Resending slot data..."); - if ((move_slots->from_slot >= EQEmu::legacy::EQUIPMENT_BEGIN && move_slots->from_slot <= EQEmu::legacy::CURSOR_BAG_END) || move_slots->from_slot == EQEmu::legacy::SlotPowerSource) { + if ((move_slots->from_slot >= EQEmu::legacy::EQUIPMENT_BEGIN && move_slots->from_slot <= EQEmu::legacy::CURSOR_BAG_END) || move_slots->from_slot == EQEmu::inventory::slotPowerSource) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { // This prevents the client from crashing when closing any 'phantom' bags @@ -1877,7 +1877,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); } } - if ((move_slots->to_slot >= EQEmu::legacy::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::legacy::CURSOR_BAG_END) || move_slots->to_slot == EQEmu::legacy::SlotPowerSource) { + if ((move_slots->to_slot >= EQEmu::legacy::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::legacy::CURSOR_BAG_END) || move_slots->to_slot == EQEmu::inventory::slotPowerSource) { int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { const EQEmu::ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' @@ -1959,7 +1959,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { qsaudit->items[move_count++].aug_5 = from_inst->GetAugmentItemID(5); if (from_inst->IsType(EQEmu::item::ItemClassBag)) { - for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < from_inst->GetItem()->BagSlots; bag_idx++) { + for (uint8 bag_idx = EQEmu::inventory::containerBegin; bag_idx < from_inst->GetItem()->BagSlots; bag_idx++) { const EQEmu::ItemInstance* from_baginst = from_inst->GetItem(bag_idx); if(from_baginst) { @@ -1992,7 +1992,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { qsaudit->items[move_count++].aug_5 = to_inst->GetAugmentItemID(5); if (to_inst->IsType(EQEmu::item::ItemClassBag)) { - for (uint8 bag_idx = SUB_INDEX_BEGIN; bag_idx < to_inst->GetItem()->BagSlots; bag_idx++) { + for (uint8 bag_idx = EQEmu::inventory::containerBegin; bag_idx < to_inst->GetItem()->BagSlots; bag_idx++) { const EQEmu::ItemInstance* to_baginst = to_inst->GetItem(bag_idx); if(to_baginst) { @@ -2021,7 +2021,7 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { void Client::DyeArmor(EQEmu::TintProfile* dye){ int16 slot=0; - for (int i = EQEmu::textures::TextureBegin; i <= EQEmu::textures::LastTintableTexture; i++) { + for (int i = EQEmu::textures::textureBegin; i <= EQEmu::textures::LastTintableTexture; i++) { if ((m_pp.item_tint.Slot[i].Color & 0x00FFFFFF) != (dye->Slot[i].Color & 0x00FFFFFF)) { slot = m_inv.HasItem(32557, 1, invWherePersonal); if (slot != INVALID_INDEX){ @@ -2115,7 +2115,7 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) { int num = 0; for(x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::GENERAL_BAGS_END; x++) { - if (x == EQEmu::legacy::SlotCursor + 1) + if (x == EQEmu::inventory::slotCursor + 1) x = EQEmu::legacy::GENERAL_BAGS_BEGIN; TempItem = nullptr; ins = GetInv().GetItem(x); @@ -2132,7 +2132,7 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) { return false; for(x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::GENERAL_BAGS_END; x++) // should this be CURSOR_BAG_END? { - if (x == EQEmu::legacy::SlotCursor + 1) + if (x == EQEmu::inventory::slotCursor + 1) x = EQEmu::legacy::GENERAL_BAGS_BEGIN; TempItem = nullptr; ins = GetInv().GetItem(x); @@ -2293,7 +2293,7 @@ void Client::DisenchantSummonedBags(bool client_update) } while (!m_inv.CursorEmpty()) { - auto inst = m_inv[EQEmu::legacy::SlotCursor]; + auto inst = m_inv[EQEmu::inventory::slotCursor]; if (!inst) { break; } if (!IsSummonedBagID(inst->GetItem()->ID)) { break; } if (!inst->GetItem()->IsClassBag()) { break; } @@ -2307,14 +2307,14 @@ void Client::DisenchantSummonedBags(bool client_update) if (!new_inst) { break; } if (CopyBagContents(new_inst, inst)) { - Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, EQEmu::legacy::SlotCursor); + Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, EQEmu::inventory::slotCursor); std::list local; local.push_front(new_inst); - m_inv.PopItem(EQEmu::legacy::SlotCursor); + m_inv.PopItem(EQEmu::inventory::slotCursor); safe_delete(inst); while (!m_inv.CursorEmpty()) { - auto limbo_inst = m_inv.PopItem(EQEmu::legacy::SlotCursor); + auto limbo_inst = m_inv.PopItem(EQEmu::inventory::slotCursor); if (limbo_inst == nullptr) { continue; } local.push_back(limbo_inst); } @@ -2356,11 +2356,11 @@ void Client::RemoveNoRent(bool client_update) } } - if (m_inv[EQEmu::legacy::SlotPowerSource]) { - auto inst = m_inv[EQEmu::legacy::SlotPowerSource]; + if (m_inv[EQEmu::inventory::slotPowerSource]) { + auto inst = m_inv[EQEmu::inventory::slotPowerSource]; if (inst && !inst->GetItem()->NoRent) { - Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, EQEmu::legacy::SlotPowerSource); - DeleteItemInInventory(EQEmu::legacy::SlotPowerSource, 0, (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) ? client_update : false); // Ti slot non-existent + Log.Out(Logs::Detail, Logs::Inventory, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, EQEmu::inventory::slotPowerSource); + DeleteItemInInventory(EQEmu::inventory::slotPowerSource, 0, (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) ? client_update : false); // Ti slot non-existent } } @@ -2408,7 +2408,7 @@ void Client::RemoveNoRent(bool client_update) std::list local; while (!m_inv.CursorEmpty()) { - auto inst = m_inv.PopItem(EQEmu::legacy::SlotCursor); + auto inst = m_inv.PopItem(EQEmu::inventory::slotCursor); if (inst == nullptr) { continue; } local.push_back(inst); } @@ -2460,15 +2460,15 @@ void Client::RemoveDuplicateLore(bool client_update) safe_delete(inst); } - if (m_inv[EQEmu::legacy::SlotPowerSource]) { - auto inst = m_inv.PopItem(EQEmu::legacy::SlotPowerSource); + if (m_inv[EQEmu::inventory::slotPowerSource]) { + auto inst = m_inv.PopItem(EQEmu::inventory::slotPowerSource); if (inst) { if (CheckLoreConflict(inst->GetItem())) { - Log.Out(Logs::Detail, Logs::Inventory, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, EQEmu::legacy::SlotPowerSource); - database.SaveInventory(character_id, nullptr, EQEmu::legacy::SlotPowerSource); + Log.Out(Logs::Detail, Logs::Inventory, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, EQEmu::inventory::slotPowerSource); + database.SaveInventory(character_id, nullptr, EQEmu::inventory::slotPowerSource); } else { - m_inv.PutItem(EQEmu::legacy::SlotPowerSource, *inst); + m_inv.PutItem(EQEmu::inventory::slotPowerSource, *inst); } safe_delete(inst); } @@ -2520,7 +2520,7 @@ void Client::RemoveDuplicateLore(bool client_update) std::list local_2; while (!m_inv.CursorEmpty()) { - auto inst = m_inv.PopItem(EQEmu::legacy::SlotCursor); + auto inst = m_inv.PopItem(EQEmu::inventory::slotCursor); if (inst == nullptr) { continue; } local_1.push_back(inst); } @@ -2573,13 +2573,13 @@ void Client::MoveSlotNotAllowed(bool client_update) } } - if (m_inv[EQEmu::legacy::SlotPowerSource] && !m_inv[EQEmu::legacy::SlotPowerSource]->IsSlotAllowed(EQEmu::legacy::SlotPowerSource)) { - auto inst = m_inv.PopItem(EQEmu::legacy::SlotPowerSource); + if (m_inv[EQEmu::inventory::slotPowerSource] && !m_inv[EQEmu::inventory::slotPowerSource]->IsSlotAllowed(EQEmu::inventory::slotPowerSource)) { + auto inst = m_inv.PopItem(EQEmu::inventory::slotPowerSource); bool is_arrow = (inst->GetItem()->ItemType == EQEmu::item::ItemTypeArrow) ? true : false; int16 free_slot_id = m_inv.FindFreeSlot(inst->IsClassBag(), true, inst->GetItem()->Size, is_arrow); - Log.Out(Logs::Detail, Logs::Inventory, "Slot Assignment Error: Moving %s from slot %i to %i", inst->GetItem()->Name, EQEmu::legacy::SlotPowerSource, free_slot_id); + Log.Out(Logs::Detail, Logs::Inventory, "Slot Assignment Error: Moving %s from slot %i to %i", inst->GetItem()->Name, EQEmu::inventory::slotPowerSource, free_slot_id); PutItemInInventory(free_slot_id, *inst, (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) ? client_update : false); - database.SaveInventory(character_id, nullptr, EQEmu::legacy::SlotPowerSource); + database.SaveInventory(character_id, nullptr, EQEmu::inventory::slotPowerSource); safe_delete(inst); } @@ -2697,13 +2697,13 @@ static int16 BandolierSlotToWeaponSlot(int BandolierSlot) switch (BandolierSlot) { case bandolierPrimary: - return EQEmu::legacy::SlotPrimary; + return EQEmu::inventory::slotPrimary; case bandolierSecondary: - return EQEmu::legacy::SlotSecondary; + return EQEmu::inventory::slotSecondary; case bandolierRange: - return EQEmu::legacy::SlotRange; + return EQEmu::inventory::slotRange; default: - return EQEmu::legacy::SlotAmmo; + return EQEmu::inventory::slotAmmo; } } @@ -2778,12 +2778,12 @@ void Client::SetBandolier(const EQApplicationPacket *app) // removed 'invWhereCursor' argument from above and implemented slots 30, 331-340 checks here if (slot == INVALID_INDEX) { - if (m_inv.GetItem(EQEmu::legacy::SlotCursor)) { - if (m_inv.GetItem(EQEmu::legacy::SlotCursor)->GetItem()->ID == m_pp.bandoliers[bss->Number].Items[BandolierSlot].ID && - m_inv.GetItem(EQEmu::legacy::SlotCursor)->GetCharges() >= 1) { // '> 0' the same, but this matches Inventory::_HasItem conditional check - slot = EQEmu::legacy::SlotCursor; + if (m_inv.GetItem(EQEmu::inventory::slotCursor)) { + if (m_inv.GetItem(EQEmu::inventory::slotCursor)->GetItem()->ID == m_pp.bandoliers[bss->Number].Items[BandolierSlot].ID && + m_inv.GetItem(EQEmu::inventory::slotCursor)->GetCharges() >= 1) { // '> 0' the same, but this matches Inventory::_HasItem conditional check + slot = EQEmu::inventory::slotCursor; } - else if (m_inv.GetItem(EQEmu::legacy::SlotCursor)->GetItem()->ItemClass == 1) { + else if (m_inv.GetItem(EQEmu::inventory::slotCursor)->GetItem()->ItemClass == 1) { for(int16 CursorBagSlot = EQEmu::legacy::CURSOR_BAG_BEGIN; CursorBagSlot <= EQEmu::legacy::CURSOR_BAG_END; CursorBagSlot++) { if (m_inv.GetItem(CursorBagSlot)) { if (m_inv.GetItem(CursorBagSlot)->GetItem()->ID == m_pp.bandoliers[bss->Number].Items[BandolierSlot].ID && @@ -2930,7 +2930,7 @@ bool Client::MoveItemToInventory(EQEmu::ItemInstance *ItemToReturn, bool UpdateC // if(ItemToReturn->IsStackable()) { - for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::SlotCursor; i++) { // changed slot max to 30 from 29. client will stack into slot 30 (bags too) before moving. + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::inventory::slotCursor; i++) { // changed slot max to 30 from 29. client will stack into slot 30 (bags too) before moving. EQEmu::ItemInstance* InvItem = m_inv.GetItem(i); @@ -2956,12 +2956,12 @@ bool Client::MoveItemToInventory(EQEmu::ItemInstance *ItemToReturn, bool UpdateC // if (InvItem && InvItem->IsClassBag()) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); + int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); uint8 BagSize=InvItem->GetItem()->BagSlots; uint8 BagSlot; - for (BagSlot = SUB_INDEX_BEGIN; BagSlot < BagSize; BagSlot++) { + for (BagSlot = EQEmu::inventory::containerBegin; BagSlot < BagSize; BagSlot++) { InvItem = m_inv.GetItem(BaseSlotID + BagSlot); if (InvItem && (InvItem->GetItem()->ID == ItemID) && (InvItem->GetCharges() < InvItem->GetItem()->StackSize)) { @@ -2989,7 +2989,7 @@ bool Client::MoveItemToInventory(EQEmu::ItemInstance *ItemToReturn, bool UpdateC // We have tried stacking items, now just try and find an empty slot. - for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::SlotCursor; i++) { // changed slot max to 30 from 29. client will move into slot 30 (bags too) before pushing onto cursor. + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::inventory::slotCursor; i++) { // changed slot max to 30 from 29. client will move into slot 30 (bags too) before pushing onto cursor. EQEmu::ItemInstance* InvItem = m_inv.GetItem(i); @@ -3008,11 +3008,11 @@ bool Client::MoveItemToInventory(EQEmu::ItemInstance *ItemToReturn, bool UpdateC } if (InvItem->IsClassBag() && Inventory::CanItemFitInContainer(ItemToReturn->GetItem(), InvItem->GetItem())) { - int16 BaseSlotID = Inventory::CalcSlotId(i, SUB_INDEX_BEGIN); + int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); uint8 BagSize=InvItem->GetItem()->BagSlots; - for (uint8 BagSlot = SUB_INDEX_BEGIN; BagSlot < BagSize; BagSlot++) { + for (uint8 BagSlot = EQEmu::inventory::containerBegin; BagSlot < BagSize; BagSlot++) { InvItem = m_inv.GetItem(BaseSlotID + BagSlot); @@ -3050,7 +3050,7 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool std::map instmap; // build reference map - for (int16 index = SLOT_BEGIN; index < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; ++index) { + for (int16 index = EQEmu::inventory::slotBegin; index < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; ++index) { auto inst = m_inv[index]; if (inst == nullptr) { continue; } instmap[index] = inst; @@ -3078,7 +3078,7 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool auto tsobject = GetTradeskillObject(); if (tsobject != nullptr) { - for (int16 index = SLOT_BEGIN; index < EQEmu::legacy::TYPE_WORLD_SIZE; ++index) { + for (int16 index = EQEmu::inventory::slotBegin; index < EQEmu::legacy::TYPE_WORLD_SIZE; ++index) { auto inst = tsobject->GetItem(index); if (inst == nullptr) { continue; } instmap[EQEmu::legacy::WORLD_BEGIN + index] = inst; @@ -3094,8 +3094,8 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool instmap[8000 + limbo] = *cursor_itr; } - if (m_inv[EQEmu::legacy::SlotPowerSource]) - instmap[EQEmu::legacy::SlotPowerSource] = m_inv[EQEmu::legacy::SlotPowerSource]; + if (m_inv[EQEmu::inventory::slotPowerSource]) + instmap[EQEmu::inventory::slotPowerSource] = m_inv[EQEmu::inventory::slotPowerSource]; // call InterrogateInventory_ for error check for (auto instmap_itr = instmap.begin(); (instmap_itr != instmap.end()) && (!error); ++instmap_itr) { @@ -3153,7 +3153,7 @@ void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 hea } else { if (inst) { - for (int16 sub = SUB_INDEX_BEGIN; (sub < EQEmu::legacy::ITEM_CONTAINER_SIZE) && (!error); ++sub) { // treat any EQEmu::ItemInstance as having the max internal slots available + for (int16 sub = EQEmu::inventory::containerBegin; (sub < EQEmu::inventory::ContainerCount) && (!error); ++sub) { // treat any EQEmu::ItemInstance as having the max internal slots available if (inst->GetItem(sub)) InterrogateInventory_(true, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1); } @@ -3183,7 +3183,7 @@ void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 hea } if (inst) { - for (int16 sub = SUB_INDEX_BEGIN; (sub < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++sub) { + for (int16 sub = EQEmu::inventory::containerBegin; (sub < EQEmu::inventory::ContainerCount); ++sub) { if (inst->GetItem(sub)) InterrogateInventory_(false, requester, head, sub, inst->GetItem(sub), inst, log, silent, error, depth + 1); } @@ -3202,7 +3202,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const EQEmu::It (head >= EQEmu::legacy::TRIBUTE_BEGIN && head <= EQEmu::legacy::TRIBUTE_END) || (head >= EQEmu::legacy::WORLD_BEGIN && head <= EQEmu::legacy::WORLD_END) || (head >= 8000 && head <= 8101) || - (head == EQEmu::legacy::SlotPowerSource)) { + (head == EQEmu::inventory::slotPowerSource)) { switch (depth) { case 0: // requirement: inst is extant @@ -3214,7 +3214,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const EQEmu::It return true; if (!parent->IsType(EQEmu::item::ItemClassCommon)) return true; - if (index >= EQEmu::legacy::ITEM_COMMON_SIZE) + if (index >= EQEmu::inventory::SocketCount) return true; break; default: // requirement: none (something bad happened...) @@ -3223,7 +3223,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const EQEmu::It } else if ( (head >= EQEmu::legacy::GENERAL_BEGIN && head <= EQEmu::legacy::GENERAL_END) || - (head == EQEmu::legacy::SlotCursor) || + (head == EQEmu::inventory::slotCursor) || (head >= EQEmu::legacy::BANK_BEGIN && head <= EQEmu::legacy::BANK_END) || (head >= EQEmu::legacy::SHARED_BANK_BEGIN && head <= EQEmu::legacy::SHARED_BANK_END) || (head >= EQEmu::legacy::TRADE_BEGIN && head <= EQEmu::legacy::TRADE_END)) { @@ -3243,7 +3243,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const EQEmu::It if (parent->IsClassCommon()) { if (!(inst->GetItem()->AugType > 0)) return true; - if (index >= EQEmu::legacy::ITEM_COMMON_SIZE) + if (index >= EQEmu::inventory::SocketCount) return true; } break; @@ -3257,7 +3257,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const EQEmu::It if (parent->IsClassCommon()) { if (!(inst->GetItem()->AugType > 0)) return true; - if (index >= EQEmu::legacy::ITEM_COMMON_SIZE) + if (index >= EQEmu::inventory::SocketCount) return true; } break; diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 2a43eda39..4dae50960 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -313,7 +313,7 @@ void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 ch // @merth: IDFile size has been increased, this needs to change uint16 emat; if(item2->Material <= 0 - || item2->Slots & (1 << EQEmu::legacy::SlotPrimary | 1 << EQEmu::legacy::SlotSecondary)) { + || item2->Slots & (1 << EQEmu::inventory::slotPrimary | 1 << EQEmu::inventory::slotSecondary)) { memset(newid, 0, sizeof(newid)); for(int i=0;i<7;i++){ if (!isalpha(item2->IDFile[i])){ @@ -327,47 +327,47 @@ void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 ch emat = item2->Material; } - if (foundslot == EQEmu::legacy::SlotPrimary) { + if (foundslot == EQEmu::inventory::slotPrimary) { if (item2->Proc.Effect != 0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); - eslot = EQEmu::textures::TexturePrimary; + eslot = EQEmu::textures::weaponPrimary; if (item2->Damage > 0) SendAddPlayerState(PlayerState::PrimaryWeaponEquipped); if (item2->IsType2HWeapon()) SetTwoHanderEquipped(true); } - else if (foundslot == EQEmu::legacy::SlotSecondary + else if (foundslot == EQEmu::inventory::slotSecondary && (GetOwner() != nullptr || (CanThisClassDualWield() && zone->random.Roll(NPC_DW_CHANCE)) || (item2->Damage==0)) && (item2->IsType1HWeapon() || item2->ItemType == EQEmu::item::ItemTypeShield)) { if (item2->Proc.Effect!=0) CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); - eslot = EQEmu::textures::TextureSecondary; + eslot = EQEmu::textures::weaponSecondary; if (item2->Damage > 0) SendAddPlayerState(PlayerState::SecondaryWeaponEquipped); } - else if (foundslot == EQEmu::legacy::SlotHead) { - eslot = EQEmu::textures::TextureHead; + else if (foundslot == EQEmu::inventory::slotHead) { + eslot = EQEmu::textures::armorHead; } - else if (foundslot == EQEmu::legacy::SlotChest) { - eslot = EQEmu::textures::TextureChest; + else if (foundslot == EQEmu::inventory::slotChest) { + eslot = EQEmu::textures::armorChest; } - else if (foundslot == EQEmu::legacy::SlotArms) { - eslot = EQEmu::textures::TextureArms; + else if (foundslot == EQEmu::inventory::slotArms) { + eslot = EQEmu::textures::armorArms; } - else if (foundslot == EQEmu::legacy::SlotWrist1 || foundslot == EQEmu::legacy::SlotWrist2) { - eslot = EQEmu::textures::TextureWrist; + else if (foundslot == EQEmu::inventory::slotWrist1 || foundslot == EQEmu::inventory::slotWrist2) { + eslot = EQEmu::textures::armorWrist; } - else if (foundslot == EQEmu::legacy::SlotHands) { - eslot = EQEmu::textures::TextureHands; + else if (foundslot == EQEmu::inventory::slotHands) { + eslot = EQEmu::textures::armorHands; } - else if (foundslot == EQEmu::legacy::SlotLegs) { - eslot = EQEmu::textures::TextureLegs; + else if (foundslot == EQEmu::inventory::slotLegs) { + eslot = EQEmu::textures::armorLegs; } - else if (foundslot == EQEmu::legacy::SlotFeet) { - eslot = EQEmu::textures::TextureFeet; + else if (foundslot == EQEmu::inventory::slotFeet) { + eslot = EQEmu::textures::armorFeet; } /* diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 9f413128b..e71153d8e 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1762,43 +1762,43 @@ luabind::scope lua_register_slot() { return luabind::class_("Slot") .enum_("constants") [ - luabind::value("Charm", static_cast(EQEmu::legacy::SlotCharm)), - luabind::value("Ear1", static_cast(EQEmu::legacy::SlotEar1)), - luabind::value("Head", static_cast(EQEmu::legacy::SlotHead)), - luabind::value("Face", static_cast(EQEmu::legacy::SlotFace)), - luabind::value("Ear2", static_cast(EQEmu::legacy::SlotEar2)), - luabind::value("Neck", static_cast(EQEmu::legacy::SlotNeck)), - luabind::value("Shoulder", static_cast(EQEmu::legacy::SlotShoulders)), // deprecated - luabind::value("Shoulders", static_cast(EQEmu::legacy::SlotShoulders)), - luabind::value("Arms", static_cast(EQEmu::legacy::SlotArms)), - luabind::value("Back", static_cast(EQEmu::legacy::SlotBack)), - luabind::value("Bracer1", static_cast(EQEmu::legacy::SlotWrist1)), // deprecated - luabind::value("Wrist1", static_cast(EQEmu::legacy::SlotWrist1)), - luabind::value("Bracer2", static_cast(EQEmu::legacy::SlotWrist2)), // deprecated - luabind::value("Wrist2", static_cast(EQEmu::legacy::SlotWrist2)), - luabind::value("Range", static_cast(EQEmu::legacy::SlotRange)), - luabind::value("Hands", static_cast(EQEmu::legacy::SlotHands)), - luabind::value("Primary", static_cast(EQEmu::legacy::SlotPrimary)), - luabind::value("Secondary", static_cast(EQEmu::legacy::SlotSecondary)), - luabind::value("Ring1", static_cast(EQEmu::legacy::SlotFinger1)), // deprecated - luabind::value("Finger1", static_cast(EQEmu::legacy::SlotFinger1)), - luabind::value("Ring2", static_cast(EQEmu::legacy::SlotFinger2)), // deprecated - luabind::value("Finger2", static_cast(EQEmu::legacy::SlotFinger2)), - luabind::value("Chest", static_cast(EQEmu::legacy::SlotChest)), - luabind::value("Legs", static_cast(EQEmu::legacy::SlotLegs)), - luabind::value("Feet", static_cast(EQEmu::legacy::SlotFeet)), - luabind::value("Waist", static_cast(EQEmu::legacy::SlotWaist)), - luabind::value("PowerSource", static_cast(EQEmu::legacy::SlotPowerSource)), - luabind::value("Ammo", static_cast(EQEmu::legacy::SlotAmmo)), - luabind::value("General1", static_cast(EQEmu::legacy::SlotGeneral1)), - luabind::value("General2", static_cast(EQEmu::legacy::SlotGeneral2)), - luabind::value("General3", static_cast(EQEmu::legacy::SlotGeneral3)), - luabind::value("General4", static_cast(EQEmu::legacy::SlotGeneral4)), - luabind::value("General5", static_cast(EQEmu::legacy::SlotGeneral5)), - luabind::value("General6", static_cast(EQEmu::legacy::SlotGeneral6)), - luabind::value("General7", static_cast(EQEmu::legacy::SlotGeneral7)), - luabind::value("General8", static_cast(EQEmu::legacy::SlotGeneral8)), - luabind::value("Cursor", static_cast(EQEmu::legacy::SlotCursor)), + luabind::value("Charm", static_cast(EQEmu::inventory::slotCharm)), + luabind::value("Ear1", static_cast(EQEmu::inventory::slotEar1)), + luabind::value("Head", static_cast(EQEmu::inventory::slotHead)), + luabind::value("Face", static_cast(EQEmu::inventory::slotFace)), + luabind::value("Ear2", static_cast(EQEmu::inventory::slotEar2)), + luabind::value("Neck", static_cast(EQEmu::inventory::slotNeck)), + luabind::value("Shoulder", static_cast(EQEmu::inventory::slotShoulders)), // deprecated + luabind::value("Shoulders", static_cast(EQEmu::inventory::slotShoulders)), + luabind::value("Arms", static_cast(EQEmu::inventory::slotArms)), + luabind::value("Back", static_cast(EQEmu::inventory::slotBack)), + luabind::value("Bracer1", static_cast(EQEmu::inventory::slotWrist1)), // deprecated + luabind::value("Wrist1", static_cast(EQEmu::inventory::slotWrist1)), + luabind::value("Bracer2", static_cast(EQEmu::inventory::slotWrist2)), // deprecated + luabind::value("Wrist2", static_cast(EQEmu::inventory::slotWrist2)), + luabind::value("Range", static_cast(EQEmu::inventory::slotRange)), + luabind::value("Hands", static_cast(EQEmu::inventory::slotHands)), + luabind::value("Primary", static_cast(EQEmu::inventory::slotPrimary)), + luabind::value("Secondary", static_cast(EQEmu::inventory::slotSecondary)), + luabind::value("Ring1", static_cast(EQEmu::inventory::slotFinger1)), // deprecated + luabind::value("Finger1", static_cast(EQEmu::inventory::slotFinger1)), + luabind::value("Ring2", static_cast(EQEmu::inventory::slotFinger2)), // deprecated + luabind::value("Finger2", static_cast(EQEmu::inventory::slotFinger2)), + luabind::value("Chest", static_cast(EQEmu::inventory::slotChest)), + luabind::value("Legs", static_cast(EQEmu::inventory::slotLegs)), + luabind::value("Feet", static_cast(EQEmu::inventory::slotFeet)), + luabind::value("Waist", static_cast(EQEmu::inventory::slotWaist)), + luabind::value("PowerSource", static_cast(EQEmu::inventory::slotPowerSource)), + luabind::value("Ammo", static_cast(EQEmu::inventory::slotAmmo)), + luabind::value("General1", static_cast(EQEmu::inventory::slotGeneral1)), + luabind::value("General2", static_cast(EQEmu::inventory::slotGeneral2)), + luabind::value("General3", static_cast(EQEmu::inventory::slotGeneral3)), + luabind::value("General4", static_cast(EQEmu::inventory::slotGeneral4)), + luabind::value("General5", static_cast(EQEmu::inventory::slotGeneral5)), + luabind::value("General6", static_cast(EQEmu::inventory::slotGeneral6)), + luabind::value("General7", static_cast(EQEmu::inventory::slotGeneral7)), + luabind::value("General8", static_cast(EQEmu::inventory::slotGeneral8)), + luabind::value("Cursor", static_cast(EQEmu::inventory::slotCursor)), luabind::value("PersonalBegin", static_cast(EQEmu::legacy::GENERAL_BEGIN)), // deprecated luabind::value("GeneralBegin", static_cast(EQEmu::legacy::GENERAL_BEGIN)), luabind::value("PersonalEnd", static_cast(EQEmu::legacy::GENERAL_END)), // deprecated @@ -1814,19 +1814,19 @@ luabind::scope lua_register_material() { return luabind::class_("Material") .enum_("constants") [ - luabind::value("Head", static_cast(EQEmu::textures::TextureHead)), - luabind::value("Chest", static_cast(EQEmu::textures::TextureChest)), - luabind::value("Arms", static_cast(EQEmu::textures::TextureArms)), - luabind::value("Bracer", static_cast(EQEmu::textures::TextureWrist)), // deprecated - luabind::value("Wrist", static_cast(EQEmu::textures::TextureWrist)), - luabind::value("Hands", static_cast(EQEmu::textures::TextureHands)), - luabind::value("Legs", static_cast(EQEmu::textures::TextureLegs)), - luabind::value("Feet", static_cast(EQEmu::textures::TextureFeet)), - luabind::value("Primary", static_cast(EQEmu::textures::TexturePrimary)), - luabind::value("Secondary", static_cast(EQEmu::textures::TextureSecondary)), - luabind::value("Max", static_cast(EQEmu::textures::TextureCount)), // deprecated - luabind::value("Count", static_cast(EQEmu::textures::TextureCount)), - luabind::value("Invalid", static_cast(EQEmu::textures::TextureInvalid)) + luabind::value("Head", static_cast(EQEmu::textures::armorHead)), + luabind::value("Chest", static_cast(EQEmu::textures::armorChest)), + luabind::value("Arms", static_cast(EQEmu::textures::armorArms)), + luabind::value("Bracer", static_cast(EQEmu::textures::armorWrist)), // deprecated + luabind::value("Wrist", static_cast(EQEmu::textures::armorWrist)), + luabind::value("Hands", static_cast(EQEmu::textures::armorHands)), + luabind::value("Legs", static_cast(EQEmu::textures::armorLegs)), + luabind::value("Feet", static_cast(EQEmu::textures::armorFeet)), + luabind::value("Primary", static_cast(EQEmu::textures::weaponPrimary)), + luabind::value("Secondary", static_cast(EQEmu::textures::weaponSecondary)), + luabind::value("Max", static_cast(EQEmu::textures::materialCount)), // deprecated + luabind::value("Count", static_cast(EQEmu::textures::materialCount)), + luabind::value("Invalid", static_cast(EQEmu::textures::materialInvalid)) ]; } diff --git a/zone/merc.cpp b/zone/merc.cpp index c9d177324..c45d0c268 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -214,7 +214,7 @@ void Merc::CalcItemBonuses(StatBonuses* newbon) { unsigned int i; //should not include 21 (SLOT_AMMO) - for (i = 0; i < EQEmu::legacy::SlotAmmo; i++) { + for (i = 0; i < EQEmu::inventory::slotAmmo; i++) { if(equipment[i] == 0) continue; const EQEmu::ItemData * itm = database.GetItem(equipment[i]); @@ -1559,24 +1559,24 @@ void Merc::AI_Process() { //try main hand first if(attack_timer.Check()) { - Attack(GetTarget(), EQEmu::legacy::SlotPrimary); + Attack(GetTarget(), EQEmu::inventory::slotPrimary); bool tripleSuccess = false; if(GetOwner() && GetTarget() && CanThisClassDoubleAttack()) { if(GetOwner()) { - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, true); } if(GetOwner() && GetTarget() && GetSpecialAbility(SPECATK_TRIPLE)) { tripleSuccess = true; - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, true); } //quad attack, does this belong here?? if(GetOwner() && GetTarget() && GetSpecialAbility(SPECATK_QUAD)) { - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, true); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, true); } } @@ -1588,8 +1588,8 @@ void Merc::AI_Process() { if(zone->random.Roll(flurrychance)) { Message_StringID(MT_NPCFlurry, YOU_FLURRY); - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, false); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, false); } } @@ -1598,7 +1598,7 @@ void Merc::AI_Process() { if (GetTarget() && ExtraAttackChanceBonus) { if(zone->random.Roll(ExtraAttackChanceBonus)) { - Attack(GetTarget(), EQEmu::legacy::SlotPrimary, false); + Attack(GetTarget(), EQEmu::inventory::slotPrimary, false); } } } @@ -1634,11 +1634,11 @@ void Merc::AI_Process() { // Max 78% of DW if (zone->random.Roll(DualWieldProbability)) { - Attack(GetTarget(), EQEmu::legacy::SlotSecondary); // Single attack with offhand + Attack(GetTarget(), EQEmu::inventory::slotSecondary); // Single attack with offhand if(CanThisClassDoubleAttack()) { if(GetTarget() && GetTarget()->GetHP() > -10) - Attack(GetTarget(), EQEmu::legacy::SlotSecondary); // Single attack with offhand + Attack(GetTarget(), EQEmu::inventory::slotSecondary); // Single attack with offhand } } } @@ -5045,13 +5045,13 @@ void Merc::ScaleStats(int scalepercent, bool setmax) { void Merc::UpdateMercAppearance() { // Copied from Bot Code: - uint32 itemID = NO_ITEM; - uint8 materialFromSlot = EQEmu::textures::TextureInvalid; + uint32 itemID = 0; + uint8 materialFromSlot = EQEmu::textures::materialInvalid; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { itemID = equipment[i]; - if(itemID != NO_ITEM) { + if(itemID != 0) { materialFromSlot = Inventory::CalcMaterialFromSlot(i); - if (materialFromSlot != EQEmu::textures::TextureInvalid) + if (materialFromSlot != EQEmu::textures::materialInvalid) this->SendWearChange(materialFromSlot); } } @@ -5065,8 +5065,8 @@ void Merc::UpdateEquipmentLight() m_Light.Type[EQEmu::lightsource::LightEquipment] = 0; m_Light.Level[EQEmu::lightsource::LightEquipment] = 0; - for (int index = SLOT_BEGIN; index < EQEmu::legacy::EQUIPMENT_SIZE; ++index) { - if (index == EQEmu::legacy::SlotAmmo) { continue; } + for (int index = EQEmu::inventory::slotBegin; index < EQEmu::legacy::EQUIPMENT_SIZE; ++index) { + if (index == EQEmu::inventory::slotAmmo) { continue; } auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } diff --git a/zone/merc.h b/zone/merc.h index c78ec22b7..ad219a2ec 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -66,7 +66,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return (GetGroup() ? true : false); } diff --git a/zone/mob.cpp b/zone/mob.cpp index 21409c695..dcb9792f2 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -278,7 +278,7 @@ Mob::Mob(const char* in_name, RangedProcs[j].level_override = -1; } - for (i = 0; i < EQEmu::textures::TextureCount; i++) + for (i = EQEmu::textures::textureBegin; i < EQEmu::textures::materialCount; i++) { armor_tint.Slot[i].Color = in_armor_tint.Slot[i].Color; } @@ -1158,8 +1158,8 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) if (Mob::IsPlayerRace(race) || i > 6) { ns->spawn.equipment.Slot[i].Material = GetEquipmentMaterial(i); - ns->spawn.equipment.Slot[i].EliteMaterial = IsEliteMaterialItem(i); - ns->spawn.equipment.Slot[i].HeroForgeModel = GetHerosForgeModel(i); + ns->spawn.equipment.Slot[i].EliteModel = IsEliteMaterialItem(i); + ns->spawn.equipment.Slot[i].HeroicModel = GetHerosForgeModel(i); ns->spawn.equipment_tint.Slot[i].Color = GetEquipmentColor(i); } } @@ -2374,8 +2374,8 @@ bool Mob::CanThisClassDualWield(void) const { return(GetSkill(EQEmu::skills::SkillDualWield) > 0); } else if (CastToClient()->HasSkill(EQEmu::skills::SkillDualWield)) { - const EQEmu::ItemInstance* pinst = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); - const EQEmu::ItemInstance* sinst = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); + const EQEmu::ItemInstance* pinst = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); + const EQEmu::ItemInstance* sinst = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); // 2HS, 2HB, or 2HP if(pinst && pinst->IsWeapon()) { @@ -2858,7 +2858,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const if (item != 0) { // For primary and secondary we need the model, not the material - if (material_slot == EQEmu::textures::TexturePrimary || material_slot == EQEmu::textures::TextureSecondary) + if (material_slot == EQEmu::textures::weaponPrimary || material_slot == EQEmu::textures::weaponSecondary) { if (this->IsClient()) { @@ -2902,7 +2902,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const int32 Mob::GetHerosForgeModel(uint8 material_slot) const { uint32 HeroModel = 0; - if (material_slot >= 0 && material_slot < EQEmu::textures::TexturePrimary) + if (material_slot >= 0 && material_slot < EQEmu::textures::weaponPrimary) { uint32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); const EQEmu::ItemData *item; diff --git a/zone/mob.h b/zone/mob.h index 120e1f116..94a251394 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -154,7 +154,7 @@ public: virtual void ThrowingAttack(Mob* other) { } uint16 GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg); // 13 = Primary (default), 14 = secondary - virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) = 0; int MonkSpecialAttack(Mob* other, uint8 skill_used); virtual void TryBackstab(Mob *other,int ReuseTime = 10); @@ -390,7 +390,7 @@ public: inline uint8 GetDrakkinHeritage() const { return drakkin_heritage; } inline uint8 GetDrakkinTattoo() const { return drakkin_tattoo; } inline uint8 GetDrakkinDetails() const { return drakkin_details; } - inline uint32 GetArmorTint(uint8 i) const { return armor_tint.Slot[(i < EQEmu::textures::TextureCount) ? i : 0].Color; } + inline uint32 GetArmorTint(uint8 i) const { return armor_tint.Slot[(i < EQEmu::textures::materialCount) ? i : 0].Color; } inline uint8 GetClass() const { return class_; } inline uint8 GetLevel() const { return level; } inline uint8 GetOrigLevel() const { return orig_level; } @@ -577,7 +577,7 @@ public: bool lookForAftArc = true); //Procs - void TriggerDefensiveProcs(Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary, bool FromSkillProc = false, int damage = 0); + void TriggerDefensiveProcs(Mob *on, uint16 hand = EQEmu::inventory::slotPrimary, bool FromSkillProc = false, int damage = 0); bool AddRangedProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); bool RemoveRangedProc(uint16 spell_id, bool bAll = false); bool HasRangedProcs() const; @@ -1158,13 +1158,13 @@ protected: void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false); // hand = SlotCharm? bool PassLimitToSkill(uint16 spell_id, uint16 skill); bool PassLimitClass(uint32 Classes_, uint16 Class_); - void TryDefensiveProc(Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); - void TryWeaponProc(const EQEmu::ItemInstance* inst, const EQEmu::ItemData* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); - void TrySpellProc(const EQEmu::ItemInstance* inst, const EQEmu::ItemData* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); - void TryWeaponProc(const EQEmu::ItemInstance* weapon, Mob *on, uint16 hand = EQEmu::legacy::SlotPrimary); + void TryDefensiveProc(Mob *on, uint16 hand = EQEmu::inventory::slotPrimary); + void TryWeaponProc(const EQEmu::ItemInstance* inst, const EQEmu::ItemData* weapon, Mob *on, uint16 hand = EQEmu::inventory::slotPrimary); + void TrySpellProc(const EQEmu::ItemInstance* inst, const EQEmu::ItemData* weapon, Mob *on, uint16 hand = EQEmu::inventory::slotPrimary); + void TryWeaponProc(const EQEmu::ItemInstance* weapon, Mob *on, uint16 hand = EQEmu::inventory::slotPrimary); void ExecWeaponProc(const EQEmu::ItemInstance* weapon, uint16 spell_id, Mob *on, int level_override = -1); - virtual float GetProcChances(float ProcBonus, uint16 hand = EQEmu::legacy::SlotPrimary); - virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = EQEmu::legacy::SlotPrimary, Mob *on = nullptr); + virtual float GetProcChances(float ProcBonus, uint16 hand = EQEmu::inventory::slotPrimary); + virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = EQEmu::inventory::slotPrimary, Mob *on = nullptr); virtual float GetSpecialProcChances(uint16 hand); virtual float GetAssassinateProcChances(uint16 ReuseTime); virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm? diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index f09df1e7f..836cd086f 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -847,7 +847,7 @@ void Client::AI_Process() if (GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) { if (attack_timer.Check()) { // Should charmed clients not be procing? - DoAttackRounds(GetTarget(), EQEmu::legacy::SlotPrimary); + DoAttackRounds(GetTarget(), EQEmu::inventory::slotPrimary); } } @@ -855,7 +855,7 @@ void Client::AI_Process() if (attack_dw_timer.Check()) { if (CheckDualWield()) { // Should charmed clients not be procing? - DoAttackRounds(GetTarget(), EQEmu::legacy::SlotSecondary); + DoAttackRounds(GetTarget(), EQEmu::inventory::slotSecondary); } } } @@ -1106,7 +1106,7 @@ void Mob::AI_Process() { //try main hand first if(attack_timer.Check()) { DoMainHandAttackRounds(target); - TriggerDefensiveProcs(target, EQEmu::legacy::SlotPrimary, false); + TriggerDefensiveProcs(target, EQEmu::inventory::slotPrimary, false); bool specialed = false; // NPCs can only do one of these a round if (GetSpecialAbility(SPECATK_FLURRY)) { @@ -1952,7 +1952,7 @@ bool Mob::Flurry(ExtraAttackOptions *opts) int num_attacks = GetSpecialAbilityParam(SPECATK_FLURRY, 1); num_attacks = num_attacks > 0 ? num_attacks : RuleI(Combat, MaxFlurryHits); for (int i = 0; i < num_attacks; i++) - Attack(target, EQEmu::legacy::SlotPrimary, false, false, false, opts); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts); } return true; } diff --git a/zone/npc.cpp b/zone/npc.cpp index 78c4604ea..166cd33fc 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -490,7 +490,7 @@ void NPC::CheckMinMaxLevel(Mob *them) if(themlevel < (*cur)->min_level || themlevel > (*cur)->max_level) { material = Inventory::CalcMaterialFromSlot((*cur)->equip_slot); - if (material != EQEmu::textures::TextureInvalid) + if (material != EQEmu::textures::materialInvalid) SendWearChange(material); cur = itemlist.erase(cur); @@ -750,8 +750,8 @@ void NPC::UpdateEquipmentLight() m_Light.Type[EQEmu::lightsource::LightEquipment] = 0; m_Light.Level[EQEmu::lightsource::LightEquipment] = 0; - for (int index = SLOT_BEGIN; index < EQEmu::legacy::EQUIPMENT_SIZE; ++index) { - if (index == EQEmu::legacy::SlotAmmo) { continue; } + for (int index = EQEmu::inventory::slotBegin; index < EQEmu::legacy::EQUIPMENT_SIZE; ++index) { + if (index == EQEmu::inventory::slotAmmo) { continue; } auto item = database.GetItem(equipment[index]); if (item == nullptr) { continue; } @@ -1378,7 +1378,7 @@ uint32 ZoneDatabase::NPCSpawnDB(uint8 command, const char* zone, uint32 zone_ver int32 NPC::GetEquipmentMaterial(uint8 material_slot) const { - if (material_slot >= EQEmu::textures::TextureCount) + if (material_slot >= EQEmu::textures::materialCount) return 0; int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); @@ -1389,23 +1389,23 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const { switch(material_slot) { - case EQEmu::textures::TextureHead: + case EQEmu::textures::armorHead: return helmtexture; - case EQEmu::textures::TextureChest: + case EQEmu::textures::armorChest: return texture; - case EQEmu::textures::TextureArms: + case EQEmu::textures::armorArms: return armtexture; - case EQEmu::textures::TextureWrist: + case EQEmu::textures::armorWrist: return bracertexture; - case EQEmu::textures::TextureHands: + case EQEmu::textures::armorHands: return handtexture; - case EQEmu::textures::TextureLegs: + case EQEmu::textures::armorLegs: return legtexture; - case EQEmu::textures::TextureFeet: + case EQEmu::textures::armorFeet: return feettexture; - case EQEmu::textures::TexturePrimary: + case EQEmu::textures::weaponPrimary: return d_melee_texture1; - case EQEmu::textures::TextureSecondary: + case EQEmu::textures::weaponSecondary: return d_melee_texture2; default: //they have nothing in the slot, and its not a special slot... they get nothing. diff --git a/zone/npc.h b/zone/npc.h index 0230b550f..ba9e93843 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -110,7 +110,7 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); - virtual bool Attack(Mob* other, int Hand = EQEmu::legacy::SlotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, + virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } diff --git a/zone/object.cpp b/zone/object.cpp index a2bb912bc..15c14a77c 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -365,7 +365,7 @@ void Object::Close() { EQEmu::ItemInstance* container = this->m_inst; if(container != nullptr) { - for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) + for (uint8 i = EQEmu::inventory::containerBegin; i < EQEmu::inventory::ContainerCount; i++) { EQEmu::ItemInstance* inst = container->PopItem(i); if(inst != nullptr) @@ -521,11 +521,11 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) // Transfer item to client - sender->PutItemInInventory(EQEmu::legacy::SlotCursor, *m_inst, false); - sender->SendItemPacket(EQEmu::legacy::SlotCursor, m_inst, ItemPacketTrade); + sender->PutItemInInventory(EQEmu::inventory::slotCursor, *m_inst, false); + sender->SendItemPacket(EQEmu::inventory::slotCursor, m_inst, ItemPacketTrade); if(cursordelete) // delete the item if it's a duplicate lore. We have to do this because the client expects the item packet - sender->DeleteItemInInventory(EQEmu::legacy::SlotCursor); + sender->DeleteItemInInventory(EQEmu::inventory::slotCursor); if(!m_ground_spawn) safe_delete(m_inst); @@ -602,7 +602,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) auto outapp = new EQApplicationPacket(OP_ClientReady, 0); sender->QueuePacket(outapp); safe_delete(outapp); - for (uint8 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { + for (uint8 i = EQEmu::inventory::containerBegin; i < EQEmu::inventory::ContainerCount; i++) { const EQEmu::ItemInstance* inst = m_inst->GetItem(i); if (inst) { //sender->GetInv().PutItem(i+4000,inst); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index be0c04abb..d582975e9 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -68,15 +68,15 @@ void Mob::ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int3 case EQEmu::skills::SkillFlyingKick: case EQEmu::skills::SkillRoundKick: case EQEmu::skills::SkillKick: - item_slot = EQEmu::legacy::SlotFeet; + item_slot = EQEmu::inventory::slotFeet; break; case EQEmu::skills::SkillBash: - item_slot = EQEmu::legacy::SlotSecondary; + item_slot = EQEmu::inventory::slotSecondary; break; case EQEmu::skills::SkillDragonPunch: case EQEmu::skills::SkillEagleStrike: case EQEmu::skills::SkillTigerClaw: - item_slot = EQEmu::legacy::SlotHands; + item_slot = EQEmu::inventory::slotHands; break; default: break; @@ -111,7 +111,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 if (skill == EQEmu::skills::SkillBash){ if(IsClient()){ - EQEmu::ItemInstance *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance *item = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); if(item) { if (item->GetItem()->ItemType == EQEmu::item::ItemTypeShield) @@ -129,14 +129,14 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 min_damage += min_damage * GetMeleeMinDamageMod_SE(skill) / 100; - int hand = EQEmu::legacy::SlotPrimary; // Avoid checks hand for throwing/archery exclusion, primary should work for most + int hand = EQEmu::inventory::slotPrimary; // Avoid checks hand for throwing/archery exclusion, primary should work for most if (skill == EQEmu::skills::SkillThrowing || skill == EQEmu::skills::SkillArchery) - hand = EQEmu::legacy::SlotRange; + hand = EQEmu::inventory::slotRange; if (who->AvoidDamage(this, max_damage, hand)) { if (max_damage == -3) DoRiposte(who); } else { - if (!CheckHitChance || (CheckHitChance && who->CheckHitChance(this, skill, EQEmu::legacy::SlotPrimary))) { + if (!CheckHitChance || (CheckHitChance && who->CheckHitChance(this, skill, EQEmu::inventory::slotPrimary))) { who->MeleeMitigation(this, max_damage, min_damage); CommonOutgoingHitSuccess(who, max_damage, skill); } else { @@ -194,7 +194,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { //These two are not subject to the combat ability timer, as they //allready do their checking in conjunction with the attack timer //throwing weapons - if (ca_atk->m_atk == EQEmu::legacy::SlotRange) { + if (ca_atk->m_atk == EQEmu::inventory::slotRange) { if (ca_atk->m_skill == EQEmu::skills::SkillThrowing) { SetAttackTimer(); ThrowingAttack(GetTarget()); @@ -244,8 +244,8 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { DoAnim(animTailRake); int32 ht = 0; - if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::legacy::SlotSecondary)) <= 0 && - GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::legacy::SlotShoulders)) <= 0){ + if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotSecondary)) <= 0 && + GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotShoulders)) <= 0){ dmg = -5; } else{ @@ -321,7 +321,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { DoAnim(animKick); int32 ht = 0; - if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::legacy::SlotFeet)) <= 0){ + if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0){ dmg = -5; } else{ @@ -404,7 +404,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) int32 min_dmg = 1; int reuse = 0; EQEmu::skills::SkillType skill_type; //to avoid casting... even though it "would work" - uint8 itemslot = EQEmu::legacy::SlotFeet; + uint8 itemslot = EQEmu::inventory::slotFeet; switch(unchecked_type) { case EQEmu::skills::SkillFlyingKick: @@ -418,7 +418,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) case EQEmu::skills::SkillDragonPunch: skill_type = EQEmu::skills::SkillDragonPunch; max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, DragonPunchBonus) / 100) + 26; - itemslot = EQEmu::legacy::SlotHands; + itemslot = EQEmu::inventory::slotHands; ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animTailRake); reuse = TailRakeReuseTime; @@ -426,7 +426,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) case EQEmu::skills::SkillEagleStrike: skill_type = EQEmu::skills::SkillEagleStrike; max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, EagleStrikeBonus) / 100) + 19; - itemslot = EQEmu::legacy::SlotHands; + itemslot = EQEmu::inventory::slotHands; ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animEagleStrike); reuse = EagleStrikeReuseTime; @@ -434,7 +434,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) case EQEmu::skills::SkillTigerClaw: skill_type = EQEmu::skills::SkillTigerClaw; max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, TigerClawBonus) / 100) + 12; - itemslot = EQEmu::legacy::SlotHands; + itemslot = EQEmu::inventory::slotHands; ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animTigerClaw); reuse = TigerClawReuseTime; @@ -498,7 +498,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { //make sure we have a proper weapon if we are a client. if(IsClient()) { - const EQEmu::ItemInstance *wpn = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); + const EQEmu::ItemInstance *wpn = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); if (!wpn || (wpn->GetItem()->ItemType != EQEmu::item::ItemType1HPiercing)){ Message_StringID(13, BACKSTAB_WEAPON); return; @@ -559,7 +559,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillBackstab, other, 10); } else { //We do a single regular attack if we attack from the front without chaotic stab - Attack(other, EQEmu::legacy::SlotPrimary); + Attack(other, EQEmu::inventory::slotPrimary); } } @@ -577,7 +577,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) int32 backstab_dmg = 0; if (IsClient()) { - const EQEmu::ItemInstance *wpn = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); + const EQEmu::ItemInstance *wpn = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); if (wpn) { primaryweapondamage = GetWeaponDamage(other, wpn); if (primaryweapondamage) { @@ -650,7 +650,7 @@ void Mob::RogueAssassinate(Mob* other) { //can you dodge, parry, etc.. an assassinate?? //if so, use DoSpecialAttackDamage(other, BACKSTAB, 32000); instead - if (GetWeaponDamage(other, IsClient() ? CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary) : (const EQEmu::ItemInstance*)nullptr) > 0){ + if (GetWeaponDamage(other, IsClient() ? CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary) : (const EQEmu::ItemInstance*)nullptr) > 0){ other->Damage(this, 32000, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab); }else{ other->Damage(this, -5, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab); @@ -670,20 +670,20 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { //Message(0, "Error: Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime()); return; } - const EQEmu::ItemInstance* RangeWeapon = m_inv[EQEmu::legacy::SlotRange]; + const EQEmu::ItemInstance* RangeWeapon = m_inv[EQEmu::inventory::slotRange]; //locate ammo - int ammo_slot = EQEmu::legacy::SlotAmmo; - const EQEmu::ItemInstance* Ammo = m_inv[EQEmu::legacy::SlotAmmo]; + int ammo_slot = EQEmu::inventory::slotAmmo; + const EQEmu::ItemInstance* Ammo = m_inv[EQEmu::inventory::slotAmmo]; if (!RangeWeapon || !RangeWeapon->IsClassCommon()) { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(EQEmu::legacy::SlotRange), EQEmu::legacy::SlotRange); - Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have no bow!", GetItemIDAt(EQEmu::legacy::SlotRange)); + Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(EQEmu::inventory::slotRange), EQEmu::inventory::slotRange); + Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have no bow!", GetItemIDAt(EQEmu::inventory::slotRange)); return; } if (!Ammo || !Ammo->IsClassCommon()) { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ammo item (%d) in slot %d", GetItemIDAt(EQEmu::legacy::SlotAmmo), EQEmu::legacy::SlotAmmo); - Message(0, "Error: Ammo: GetItem(%i)==0, you have no ammo!", GetItemIDAt(EQEmu::legacy::SlotAmmo)); + Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ammo item (%d) in slot %d", GetItemIDAt(EQEmu::inventory::slotAmmo), EQEmu::inventory::slotAmmo); + Message(0, "Error: Ammo: GetItem(%i)==0, you have no ammo!", GetItemIDAt(EQEmu::inventory::slotAmmo)); return; } @@ -838,7 +838,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon if (IsClient()){ - _RangeWeapon = CastToClient()->m_inv[EQEmu::legacy::SlotRange]; + _RangeWeapon = CastToClient()->m_inv[EQEmu::inventory::slotRange]; if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id) RangeWeapon = _RangeWeapon; @@ -854,7 +854,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon else if (AmmoItem) SendItemAnimation(other, AmmoItem, EQEmu::skills::SkillArchery); - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillArchery, EQEmu::legacy::SlotPrimary, chance_mod))) { + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillArchery, EQEmu::inventory::slotPrimary, chance_mod))) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ @@ -952,7 +952,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon } if (!HeadShot) - other->AvoidDamage(this, TotalDmg, EQEmu::legacy::SlotRange); + other->AvoidDamage(this, TotalDmg, EQEmu::inventory::slotRange); other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0){ @@ -976,7 +976,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon if (ReuseTime) TrySkillProc(other, EQEmu::skills::SkillArchery, ReuseTime); else - TrySkillProc(other, EQEmu::skills::SkillArchery, 0, true, EQEmu::legacy::SlotRange); + TrySkillProc(other, EQEmu::skills::SkillArchery, 0, true, EQEmu::inventory::slotRange); } } @@ -985,20 +985,20 @@ void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon //Weapon Proc if(RangeWeapon && other && !other->HasDied()) - TryWeaponProc(RangeWeapon, other, EQEmu::legacy::SlotRange); + TryWeaponProc(RangeWeapon, other, EQEmu::inventory::slotRange); //Ammo Proc if (ammo_lost) - TryWeaponProc(nullptr, ammo_lost, other, EQEmu::legacy::SlotRange); + TryWeaponProc(nullptr, ammo_lost, other, EQEmu::inventory::slotRange); else if(Ammo && other && !other->HasDied()) - TryWeaponProc(Ammo, other, EQEmu::legacy::SlotRange); + TryWeaponProc(Ammo, other, EQEmu::inventory::slotRange); //Skill Proc if (HasSkillProcs() && other && !other->HasDied()){ if (ReuseTime) TrySkillProc(other, EQEmu::skills::SkillArchery, ReuseTime); else - TrySkillProc(other, EQEmu::skills::SkillArchery, 0, false, EQEmu::legacy::SlotRange); + TrySkillProc(other, EQEmu::skills::SkillArchery, 0, false, EQEmu::inventory::slotRange); } } @@ -1264,7 +1264,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha if (!chance_mod) chance_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2); - if (!other->CheckHitChance(this, skillInUse, EQEmu::legacy::SlotRange, chance_mod)) + if (!other->CheckHitChance(this, skillInUse, EQEmu::inventory::slotRange, chance_mod)) { other->Damage(this, 0, SPELL_UNKNOWN, skillInUse); } @@ -1285,7 +1285,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha TotalDmg += TotalDmg * damage_mod / 100; - other->AvoidDamage(this, TotalDmg, EQEmu::legacy::SlotRange); + other->AvoidDamage(this, TotalDmg, EQEmu::inventory::slotRange); other->MeleeMitigation(this, TotalDmg, MinDmg); if (TotalDmg > 0) @@ -1301,15 +1301,15 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillInUse); if (TotalDmg > 0 && HasSkillProcSuccess() && !other->HasDied()) - TrySkillProc(other, skillInUse, 0, true, EQEmu::legacy::SlotRange); + TrySkillProc(other, skillInUse, 0, true, EQEmu::inventory::slotRange); } //try proc on hits and misses if(other && !other->HasDied()) - TrySpellProc(nullptr, (const EQEmu::ItemData*)nullptr, other, EQEmu::legacy::SlotRange); + TrySpellProc(nullptr, (const EQEmu::ItemData*)nullptr, other, EQEmu::inventory::slotRange); if (HasSkillProcs() && other && !other->HasDied()) - TrySkillProc(other, skillInUse, 0, false, EQEmu::legacy::SlotRange); + TrySkillProc(other, skillInUse, 0, false, EQEmu::inventory::slotRange); } uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) { @@ -1351,19 +1351,19 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 return; } - int ammo_slot = EQEmu::legacy::SlotRange; - const EQEmu::ItemInstance* RangeWeapon = m_inv[EQEmu::legacy::SlotRange]; + int ammo_slot = EQEmu::inventory::slotRange; + const EQEmu::ItemInstance* RangeWeapon = m_inv[EQEmu::inventory::slotRange]; if (!RangeWeapon || !RangeWeapon->IsClassCommon()) { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(EQEmu::legacy::SlotRange), EQEmu::legacy::SlotRange); - Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(EQEmu::legacy::SlotRange)); + Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Missing or invalid ranged weapon (%d) in slot %d", GetItemIDAt(EQEmu::inventory::slotRange), EQEmu::inventory::slotRange); + Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing to throw!", GetItemIDAt(EQEmu::inventory::slotRange)); return; } const EQEmu::ItemData* item = RangeWeapon->GetItem(); if (item->ItemType != EQEmu::item::ItemTypeLargeThrowing && item->ItemType != EQEmu::item::ItemTypeSmallThrowing) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack canceled. Ranged item %d is not a throwing weapon. type %d.", item->ItemType); - Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(EQEmu::legacy::SlotRange)); + Message(0, "Error: Rangeweapon: GetItem(%i)==0, you have nothing useful to throw!", GetItemIDAt(EQEmu::inventory::slotRange)); return; } @@ -1371,11 +1371,11 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 if(RangeWeapon->GetCharges() == 1) { //first check ammo - const EQEmu::ItemInstance* AmmoItem = m_inv[EQEmu::legacy::SlotAmmo]; + const EQEmu::ItemInstance* AmmoItem = m_inv[EQEmu::inventory::slotAmmo]; if(AmmoItem != nullptr && AmmoItem->GetID() == RangeWeapon->GetID()) { //more in the ammo slot, use it RangeWeapon = AmmoItem; - ammo_slot = EQEmu::legacy::SlotAmmo; + ammo_slot = EQEmu::inventory::slotAmmo; Log.Out(Logs::Detail, Logs::Combat, "Using ammo from ammo slot, stack at slot %d. %d in stack.", ammo_slot, RangeWeapon->GetCharges()); } else { //look through our inventory for more @@ -1472,7 +1472,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon else if (AmmoItem) SendItemAnimation(other, AmmoItem, EQEmu::skills::SkillThrowing); - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillThrowing, EQEmu::legacy::SlotPrimary, chance_mod))){ + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillThrowing, EQEmu::inventory::slotPrimary, chance_mod))){ Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot, speed); @@ -1519,7 +1519,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon Log.Out(Logs::Detail, Logs::Combat, "Item DMG %d. Max Damage %d. Hit for damage %d", WDmg, MaxDmg, TotalDmg); if (!Assassinate_Dmg) - other->AvoidDamage(this, TotalDmg, EQEmu::legacy::SlotRange); + other->AvoidDamage(this, TotalDmg, EQEmu::inventory::slotRange); other->MeleeMitigation(this, TotalDmg, minDmg); if(TotalDmg > 0) @@ -1538,7 +1538,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon if (ReuseTime) TrySkillProc(other, EQEmu::skills::SkillThrowing, ReuseTime); else - TrySkillProc(other, EQEmu::skills::SkillThrowing, 0, true, EQEmu::legacy::SlotRange); + TrySkillProc(other, EQEmu::skills::SkillThrowing, 0, true, EQEmu::inventory::slotRange); } } @@ -1547,15 +1547,15 @@ void Mob::DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon //Throwing item Proc if (ammo_lost) - TryWeaponProc(nullptr, ammo_lost, other, EQEmu::legacy::SlotRange); + TryWeaponProc(nullptr, ammo_lost, other, EQEmu::inventory::slotRange); else if(RangeWeapon && other && !other->HasDied()) - TryWeaponProc(RangeWeapon, other, EQEmu::legacy::SlotRange); + TryWeaponProc(RangeWeapon, other, EQEmu::inventory::slotRange); if (HasSkillProcs() && other && !other->HasDied()){ if (ReuseTime) TrySkillProc(other, EQEmu::skills::SkillThrowing, ReuseTime); else - TrySkillProc(other, EQEmu::skills::SkillThrowing, 0, false, EQEmu::legacy::SlotRange); + TrySkillProc(other, EQEmu::skills::SkillThrowing, 0, false, EQEmu::inventory::slotRange); } } @@ -1955,7 +1955,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if (ca_target!=this) { DoAnim(animTailRake); - if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::legacy::SlotSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::legacy::SlotShoulders)) <= 0){ + if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotShoulders)) <= 0){ dmg = -5; } else{ @@ -2019,7 +2019,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if(ca_target!=this){ DoAnim(animKick); - if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::legacy::SlotFeet)) <= 0){ + if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0){ dmg = -5; } else{ @@ -2231,7 +2231,7 @@ uint32 Mob::TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse) { HeadShot_Level = itembonuses.HSLevel; if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){ - float ProcChance = GetSpecialProcChances(EQEmu::legacy::SlotRange); + float ProcChance = GetSpecialProcChances(EQEmu::inventory::slotRange); if(zone->random.Roll(ProcChance)) return HeadShot_Dmg; } @@ -2294,7 +2294,7 @@ uint32 Mob::TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, u float ProcChance = 0.0f; if (skillInUse == EQEmu::skills::SkillThrowing) - ProcChance = GetSpecialProcChances(EQEmu::legacy::SlotRange); + ProcChance = GetSpecialProcChances(EQEmu::inventory::slotRange); else ProcChance = GetAssassinateProcChances(ReuseTime); @@ -2345,7 +2345,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: int damage = 0; uint32 hate = 0; - int Hand = EQEmu::legacy::SlotPrimary; + int Hand = EQEmu::inventory::slotPrimary; if (hate == 0 && weapon_damage > 1) hate = weapon_damage; if(weapon_damage > 0){ @@ -2369,7 +2369,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: if (skillinuse == EQEmu::skills::SkillBash){ if(IsClient()){ - EQEmu::ItemInstance *item = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); + EQEmu::ItemInstance *item = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); if(item){ if (item->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { hate += item->GetItem()->AC; @@ -2391,7 +2391,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: else damage = zone->random.Int(min_hit, max_hit); - if (other->AvoidDamage(this, damage, CanRiposte ? EQEmu::legacy::SlotRange : EQEmu::legacy::SlotPrimary)) { // SlotRange excludes ripo, primary doesn't have any extra behavior + if (other->AvoidDamage(this, damage, CanRiposte ? EQEmu::inventory::slotRange : EQEmu::inventory::slotPrimary)) { // SlotRange excludes ripo, primary doesn't have any extra behavior if (damage == -3) { DoRiposte(other); if (HasDied()) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 161604ea9..841457bdc 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -622,7 +622,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Flesh To Bone"); #endif if(IsClient()){ - EQEmu::ItemInstance* transI = CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotCursor); + EQEmu::ItemInstance* transI = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotCursor); if (transI && transI->IsClassCommon() && transI->IsStackable()){ uint32 fcharges = transI->GetCharges(); //Does it sound like meat... maybe should check if it looks like meat too... @@ -632,7 +632,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove strstr(transI->GetItem()->Name, "Flesh") || strstr(transI->GetItem()->Name, "parts") || strstr(transI->GetItem()->Name, "Parts")){ - CastToClient()->DeleteItemInInventory(EQEmu::legacy::SlotCursor, fcharges, true); + CastToClient()->DeleteItemInInventory(EQEmu::inventory::slotCursor, fcharges, true); CastToClient()->SummonItem(13073, fcharges); } else{ @@ -1173,7 +1173,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (SummonedItem) { c->PushItemOnCursor(*SummonedItem); - c->SendItemPacket(EQEmu::legacy::SlotCursor, SummonedItem, ItemPacketLimbo); + c->SendItemPacket(EQEmu::inventory::slotCursor, SummonedItem, ItemPacketLimbo); safe_delete(SummonedItem); } SummonedItem = database.CreateItem(spell.base[i], charges); @@ -1445,7 +1445,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } } - for (int x = EQEmu::textures::TextureBegin; x <= EQEmu::textures::LastTintableTexture; x++) + for (int x = EQEmu::textures::textureBegin; x <= EQEmu::textures::LastTintableTexture; x++) SendWearChange(x); if (caster == this && spell.id != 287 && spell.id != 601 && @@ -1471,7 +1471,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove ); caster->SendAppearancePacket(AT_Size, static_cast(caster->GetTarget()->GetSize())); - for (int x = EQEmu::textures::TextureBegin; x <= EQEmu::textures::LastTintableTexture; x++) + for (int x = EQEmu::textures::textureBegin; x <= EQEmu::textures::LastTintableTexture; x++) caster->SendWearChange(x); } } @@ -2239,7 +2239,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove snprintf(effect_desc, _EDLEN, "Rampage"); #endif if(caster) - entity_list.AEAttack(caster, 30, EQEmu::legacy::SlotPrimary, 0, true); // on live wars dont get a duration ramp, its a one shot deal + entity_list.AEAttack(caster, 30, EQEmu::inventory::slotPrimary, 0, true); // on live wars dont get a duration ramp, its a one shot deal break; } @@ -3037,7 +3037,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (SummonedItem) { Client *c=CastToClient(); c->PushItemOnCursor(*SummonedItem); - c->SendItemPacket(EQEmu::legacy::SlotCursor, SummonedItem, ItemPacketLimbo); + c->SendItemPacket(EQEmu::inventory::slotCursor, SummonedItem, ItemPacketLimbo); safe_delete(SummonedItem); } @@ -3855,7 +3855,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) else{ SendAppearancePacket(AT_Size, 6); } - for (int x = EQEmu::textures::TextureBegin; x <= EQEmu::textures::LastTintableTexture; x++){ + for (int x = EQEmu::textures::textureBegin; x <= EQEmu::textures::LastTintableTexture; x++){ SendWearChange(x); } break; @@ -5194,7 +5194,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { } } - for (int y = AUG_INDEX_BEGIN; y < EQEmu::legacy::ITEM_COMMON_SIZE; ++y) + for (int y = EQEmu::inventory::socketBegin; y < EQEmu::inventory::SocketCount; ++y) { if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) continue; @@ -5343,7 +5343,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) } } - for (int y = AUG_INDEX_BEGIN; y < EQEmu::legacy::ITEM_COMMON_SIZE; ++y) + for (int y = EQEmu::inventory::socketBegin; y < EQEmu::inventory::SocketCount; ++y) { EQEmu::ItemInstance *aug = nullptr; aug = ins->GetAugment(y); diff --git a/zone/spells.cpp b/zone/spells.cpp index e00fc05c2..649fa99c9 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -293,7 +293,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, return(false); } } - if (itm && (itm->GetItem()->Click.Type == EQEmu::item::ItemEffectEquipClick) && !(item_slot <= EQEmu::legacy::SlotAmmo || item_slot == EQEmu::legacy::SlotPowerSource)){ + if (itm && (itm->GetItem()->Click.Type == EQEmu::item::ItemEffectEquipClick) && !(item_slot <= EQEmu::inventory::slotAmmo || item_slot == EQEmu::inventory::slotPowerSource)){ if (CastToClient()->ClientVersion() < EQEmu::versions::ClientVersion::SoF) { // They are attempting to cast a must equip clicky without having it equipped Log.Out(Logs::General, Logs::Error, "HACKER: %s (account: %s) attempted to click an equip-only effect on item %s (id: %d) without equiping it!", CastToClient()->GetCleanName(), CastToClient()->AccountName(), itm->GetItem()->Name, itm->GetItem()->ID); @@ -1244,7 +1244,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo if (inst == nullptr) break; - for (int r = AUG_INDEX_BEGIN; r < EQEmu::legacy::ITEM_COMMON_SIZE; r++) { + for (int r = EQEmu::inventory::socketBegin; r < EQEmu::inventory::SocketCount; r++) { const EQEmu::ItemInstance* aug_i = inst->GetAugment(r); if (!aug_i) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 38bb5a231..8db24d81e 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -69,7 +69,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme // Verify that no more than two items are in container to guarantee no inadvertant wipes. uint8 itemsFound = 0; - for (uint8 i = SLOT_BEGIN; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) + for (uint8 i = EQEmu::inventory::slotBegin; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) { const EQEmu::ItemInstance* inst = container->GetItem(i); if (inst) @@ -222,7 +222,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme else { // Delete items in our inventory container... - for (uint8 i = SLOT_BEGIN; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) + for (uint8 i = EQEmu::inventory::slotBegin; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) { const EQEmu::ItemInstance* inst = container->GetItem(i); if (inst) @@ -297,7 +297,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob const EQEmu::ItemData* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); - user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::legacy::SlotCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2)); + user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::inventory::slotCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2)); user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name); if (RuleB(Inventory, DeleteTransformationMold)) user->DeleteItemInInventory(in_combine->container_slot, 0, true); @@ -317,7 +317,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob const EQEmu::ItemData* new_weapon = inst->GetItem(); user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); - user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::legacy::SlotCursor, 0, 0); + user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::inventory::slotCursor, 0, 0); user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name); } else if (inst) { @@ -401,7 +401,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob safe_delete(outapp); database.DeleteWorldContainer(worldo->m_id, zone->GetZoneID()); } else{ - for (uint8 i = SLOT_BEGIN; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) { + for (uint8 i = EQEmu::inventory::slotBegin; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) { const EQEmu::ItemInstance* inst = container->GetItem(i); if (inst) { user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot,i),0,true); @@ -1237,7 +1237,7 @@ bool ZoneDatabase::GetTradeRecipe(const EQEmu::ItemInstance* container, uint8 c_ for (auto row = results.begin(); row != results.end(); ++row) { int ccnt = 0; - for (int x = SLOT_BEGIN; x < EQEmu::legacy::TYPE_WORLD_SIZE; x++) { + for (int x = EQEmu::inventory::slotBegin; x < EQEmu::legacy::TYPE_WORLD_SIZE; x++) { const EQEmu::ItemInstance* inst = container->GetItem(x); if(!inst) continue; diff --git a/zone/trading.cpp b/zone/trading.cpp index cfca3a2e6..9d9738ffc 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -98,7 +98,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) { // Item always goes into trade bucket from cursor Client* client = owner->CastToClient(); - EQEmu::ItemInstance* inst = client->GetInv().GetItem(EQEmu::legacy::SlotCursor); + EQEmu::ItemInstance* inst = client->GetInv().GetItem(EQEmu::inventory::slotCursor); if (!inst) { client->Message(13, "Error: Could not find item on your cursor!"); @@ -131,7 +131,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) { if (_stack_size > 0) inst->SetCharges(_stack_size); else - client->DeleteItemInInventory(EQEmu::legacy::SlotCursor); + client->DeleteItemInInventory(EQEmu::inventory::slotCursor); SendItemData(inst2, trade_slot_id); } @@ -146,7 +146,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) { Log.Out(Logs::Detail, Logs::Trading, "%s added item '%s' to trade slot %i", owner->GetName(), inst->GetItem()->Name, trade_slot_id); client->PutItemInInventory(trade_slot_id, *inst); - client->DeleteItemInInventory(EQEmu::legacy::SlotCursor); + client->DeleteItemInInventory(EQEmu::inventory::slotCursor); } } @@ -173,7 +173,7 @@ void Trade::SendItemData(const EQEmu::ItemInstance* inst, int16 dest_slot_id) if (with && with->IsClient()) { with->SendItemPacket(dest_slot_id - EQEmu::legacy::TRADE_BEGIN, inst, ItemPacketTradeView); if (inst->GetItem()->ItemClass == 1) { - for (uint16 i = SUB_INDEX_BEGIN; i < EQEmu::legacy::ITEM_CONTAINER_SIZE; i++) { + for (uint16 i = EQEmu::inventory::containerBegin; i < EQEmu::inventory::ContainerCount; i++) { uint16 bagslot_id = Inventory::CalcSlotId(dest_slot_id, i); const EQEmu::ItemInstance* bagitem = trader->GetInv().GetItem(bagslot_id); if (bagitem) { @@ -267,7 +267,7 @@ void Trade::LogTrade() strcat(logtext, item_num); if (inst->IsClassBag()) { - for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::legacy::ITEM_CONTAINER_SIZE; j++) { + for (uint8 j = EQEmu::inventory::containerBegin; j < EQEmu::inventory::ContainerCount; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { strcat(logtext, ","); @@ -312,7 +312,7 @@ void Trade::DumpTrade() i, ((inst->IsClassBag()) ? "True" : "False")); if (inst->IsClassBag()) { - for (uint8 j = SUB_INDEX_BEGIN; j < EQEmu::legacy::ITEM_CONTAINER_SIZE; j++) { + for (uint8 j = EQEmu::inventory::containerBegin; j < EQEmu::inventory::ContainerCount; j++) { inst = trader->GetInv().GetItem(i, j); if (inst) { Log.Out(Logs::Detail, Logs::Trading, "\tBagItem %i (Charges=%i, Slot=%i)", @@ -359,7 +359,7 @@ void Client::ResetTrade() { // there's no built-in safety check against an infinite loop..but, it should break on one of the conditional checks int16 free_slot = m_inv.FindFreeSlotForTradeItem(inst); - if ((free_slot == EQEmu::legacy::SlotCursor) || (free_slot == INVALID_INDEX)) + if ((free_slot == EQEmu::inventory::slotCursor) || (free_slot == INVALID_INDEX)) break; EQEmu::ItemInstance* partial_inst = GetInv().GetItem(free_slot); @@ -523,7 +523,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st qs_audit->char1_count += detail->charges; //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { - for (uint8 sub_slot = SUB_INDEX_BEGIN; (sub_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items + for (uint8 sub_slot = EQEmu::inventory::containerBegin; (sub_slot < EQEmu::inventory::ContainerCount); ++sub_slot) { // this is to catch ALL items const EQEmu::ItemInstance* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { @@ -579,7 +579,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // there's no built-in safety check against an infinite loop..but, it should break on one of the conditional checks int16 partial_slot = other->GetInv().FindFreeSlotForTradeItem(inst); - if ((partial_slot == EQEmu::legacy::SlotCursor) || (partial_slot == INVALID_INDEX)) + if ((partial_slot == EQEmu::inventory::slotCursor) || (partial_slot == INVALID_INDEX)) break; EQEmu::ItemInstance* partial_inst = other->GetInv().GetItem(partial_slot); @@ -743,7 +743,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st // 'step 3' should never really see containers..but, just in case... //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { - for (uint8 sub_slot = SUB_INDEX_BEGIN; (sub_slot < EQEmu::legacy::ITEM_CONTAINER_SIZE); ++sub_slot) { // this is to catch ALL items + for (uint8 sub_slot = EQEmu::inventory::containerBegin; (sub_slot < EQEmu::inventory::ContainerCount); ++sub_slot) { // this is to catch ALL items const EQEmu::ItemInstance* bag_inst = inst->GetItem(sub_slot); if (bag_inst) { @@ -841,7 +841,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st qs_audit->char_count += detail->charges; if (trade_inst->IsClassBag()) { - for (uint8 sub_slot = SUB_INDEX_BEGIN; sub_slot < trade_inst->GetItem()->BagSlots; ++sub_slot) { + for (uint8 sub_slot = EQEmu::inventory::containerBegin; sub_slot < trade_inst->GetItem()->BagSlots; ++sub_slot) { const EQEmu::ItemInstance* trade_baginst = trade_inst->GetItem(sub_slot); if(trade_baginst) { @@ -891,7 +891,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st if(GetGM() || (item->NoDrop != 0 && inst->IsAttuned() == false)) { // pets need to look inside bags and try to equip items found there if (item->IsClassBag() && item->BagSlots > 0) { - for (int16 bslot = SUB_INDEX_BEGIN; bslot < item->BagSlots; bslot++) { + for (int16 bslot = EQEmu::inventory::containerBegin; bslot < item->BagSlots; bslot++) { const EQEmu::ItemInstance* baginst = inst->GetItem(bslot); if (baginst) { const EQEmu::ItemData* bagitem = baginst->GetItem(); @@ -1235,7 +1235,7 @@ uint32 Client::FindTraderItemSerialNumber(int32 ItemID) { for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++){ item = this->GetInv().GetItem(i); if (item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; x++) { + for (int x = EQEmu::inventory::containerBegin; x < EQEmu::inventory::ContainerCount; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1258,7 +1258,7 @@ EQEmu::ItemInstance* Client::FindTraderItemBySerialNumber(int32 SerialNumber){ for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++){ item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; x++) { + for (int x = EQEmu::inventory::containerBegin; x < EQEmu::inventory::ContainerCount; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1289,7 +1289,7 @@ GetItems_Struct* Client::GetTraderItems(){ for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; x++) { + for (int x = EQEmu::inventory::containerBegin; x < EQEmu::inventory::ContainerCount; x++) { SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1313,7 +1313,7 @@ uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){ for (int i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel - for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; x++){ + for (int x = EQEmu::inventory::containerBegin; x < EQEmu::inventory::ContainerCount; x++){ SlotID = Inventory::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); diff --git a/zone/tune.cpp b/zone/tune.cpp index f8655d66a..6595ad4d0 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -582,13 +582,13 @@ int32 Client::Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 mi int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) { - int Hand = EQEmu::legacy::SlotPrimary; + int Hand = EQEmu::inventory::slotPrimary; if (!other) return 0; EQEmu::ItemInstance* weapon; - weapon = GetInv().GetItem(EQEmu::legacy::SlotPrimary); + weapon = GetInv().GetItem(EQEmu::inventory::slotPrimary); if(weapon != nullptr) { if (!weapon->IsWeapon()) { @@ -628,7 +628,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) int ucDamageBonus = 0; - if (Hand == EQEmu::legacy::SlotPrimary && GetLevel() >= 28 && IsWarriorClass()) + if (Hand == EQEmu::inventory::slotPrimary && GetLevel() >= 28 && IsWarriorClass()) { ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); @@ -662,24 +662,24 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch if (attacker->IsClient()) {//Will check first equiped weapon for skill. Ie. remove wepaons to assess bow. EQEmu::ItemInstance* weapon; - weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); if(weapon && weapon->IsWeapon()){ - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotPrimary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotPrimary, weapon); } else { - weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotSecondary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotSecondary, weapon); else { - weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotRange); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotRange); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotRange, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotRange, weapon); } } } - tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, 0, 0, avoid_override); + tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::inventory::slotPrimary, 0, 0, 0, avoid_override); Message(0, "#Tune - Begin Parse [Interval %i Max Loop Iterations %i]", interval, max_loop); @@ -691,7 +691,7 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch for (int j=0; j < max_loop; j++) { - tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, false, 0, avoid_override, add_acc); + tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::inventory::slotPrimary, 0, false, 0, avoid_override, add_acc); if (Msg >= 3) Message(15, "#Tune - Processing... [%i] [ACCURACY %i] Hit Chance %.2f ",j,add_acc,tmp_hit_chance); @@ -706,7 +706,7 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch if (end){ - Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, Msg, 0, avoid_override);//Display Stat Report + Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::inventory::slotPrimary, 0, Msg, 0, avoid_override);//Display Stat Report Message(0, " "); @@ -742,24 +742,24 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ if (attacker->IsClient()) {//Will check first equiped weapon for skill. Ie. remove wepaons to assess bow. EQEmu::ItemInstance* weapon; - weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotPrimary); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); if(weapon && weapon->IsWeapon()){ - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotPrimary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotPrimary, weapon); } else { - weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotSecondary); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotSecondary, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotSecondary, weapon); else { - weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::legacy::SlotRange); + weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotRange); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::legacy::SlotRange, weapon); + attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotRange, weapon); } } } - tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, 0, acc_override, 0); + tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::inventory::slotPrimary, 0, 0, acc_override, 0); Message(0, "#Tune - Begin Parse [Interval %i Max Loop Iterations %i]", interval, max_loop); Message(0, "#Tune - Processing... Find Avoidance for hit chance on defender of (%.0f) pct from attacker. [Current Hit Chance %.2f]", hit_chance, tmp_hit_chance); @@ -769,7 +769,7 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ for (int j=0; j < max_loop; j++) { - tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, 0, acc_override, 0, 0, add_avoid); + tmp_hit_chance = Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::inventory::slotPrimary, 0, 0, acc_override, 0, 0, add_avoid); if (Msg >= 3) Message(0, "#Tune - Processing... [%i] [AVOIDANCE %i] Hit Chance %.2f ",j,add_avoid,tmp_hit_chance); @@ -784,7 +784,7 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ if (end){ - Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::legacy::SlotPrimary, 0, Msg, acc_override, 0);//Display Stat Report + Tune_CheckHitChance(defender, attacker, skillinuse, EQEmu::inventory::slotPrimary, 0, Msg, acc_override, 0);//Display Stat Report Message(0, " "); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 98c5e6c92..8bf2e4d31 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -487,7 +487,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, EQEmu::ItemInstance* cont uint8 index = (uint8)atoi(row[0]); uint32 item_id = (uint32)atoi(row[1]); int8 charges = (int8)atoi(row[2]); - uint32 aug[EQEmu::legacy::ITEM_COMMON_SIZE]; + uint32 aug[EQEmu::inventory::SocketCount]; aug[0] = (uint32)atoi(row[3]); aug[1] = (uint32)atoi(row[4]); aug[2] = (uint32)atoi(row[5]); @@ -497,7 +497,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parentid, EQEmu::ItemInstance* cont EQEmu::ItemInstance* inst = database.CreateItem(item_id, charges); if (inst && inst->GetItem()->IsClassCommon()) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) if (aug[i]) inst->PutAugment(&database, i, aug[i]); // Put item inside world container @@ -520,17 +520,17 @@ void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const EQ DeleteWorldContainer(parent_id,zone_id); // Save all 10 items, if they exist - for (uint8 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; index++) { + for (uint8 index = EQEmu::inventory::containerBegin; index < EQEmu::inventory::ContainerCount; index++) { EQEmu::ItemInstance* inst = container->GetItem(index); if (!inst) continue; uint32 item_id = inst->GetItem()->ID; - uint32 augslot[EQEmu::legacy::ITEM_COMMON_SIZE] = { NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM, NO_ITEM }; + uint32 augslot[EQEmu::inventory::SocketCount] = { 0, 0, 0, 0, 0, 0 }; if (inst->IsType(EQEmu::item::ItemClassCommon)) { - for (int i = AUG_INDEX_BEGIN; i < EQEmu::legacy::ITEM_COMMON_SIZE; i++) { + for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) { EQEmu::ItemInstance *auginst=inst->GetAugment(i); augslot[i]=(auginst && auginst->GetItem()) ? auginst->GetItem()->ID : 0; } @@ -2092,7 +2092,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load else { auto armorTint_row = armortint_results.begin(); - for (int index = EQEmu::textures::TextureBegin; index <= EQEmu::textures::LastTexture; index++) { + for (int index = EQEmu::textures::textureBegin; index <= EQEmu::textures::LastTexture; index++) { temp_npctype_data->armor_tint.Slot[index].Color = atoi(armorTint_row[index * 3]) << 16; temp_npctype_data->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 1]) << 8; temp_npctype_data->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 2]); @@ -2102,7 +2102,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load } // Try loading npc_types tint fields if armor tint is 0 or query failed to get results if (armor_tint_id == 0) { - for (int index = EQEmu::textures::TextureChest; index < EQEmu::textures::TextureCount; index++) { + for (int index = EQEmu::textures::armorChest; index < EQEmu::textures::materialCount; index++) { temp_npctype_data->armor_tint.Slot[index].Color = temp_npctype_data->armor_tint.Slot[0].Color; // odd way to 'zero-out' the array... } } @@ -2307,7 +2307,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client tmpNPCType->armor_tint.Slot[0].Color |= (tmpNPCType->armor_tint.Slot[0].Color) ? (0xFF << 24) : 0; if (armor_tint_id == 0) - for (int index = EQEmu::textures::TextureChest; index <= EQEmu::textures::LastTexture; index++) + for (int index = EQEmu::textures::armorChest; index <= EQEmu::textures::LastTexture; index++) tmpNPCType->armor_tint.Slot[index].Color = tmpNPCType->armor_tint.Slot[0].Color; else if (tmpNPCType->armor_tint.Slot[0].Color == 0) { std::string armorTint_query = StringFormat("SELECT red1h, grn1h, blu1h, " @@ -2327,7 +2327,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client else { auto armorTint_row = results.begin(); - for (int index = EQEmu::textures::TextureBegin; index <= EQEmu::textures::LastTexture; index++) { + for (int index = EQEmu::textures::textureBegin; index <= EQEmu::textures::LastTexture; index++) { tmpNPCType->armor_tint.Slot[index].Color = atoi(armorTint_row[index * 3]) << 16; tmpNPCType->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 1]) << 8; tmpNPCType->armor_tint.Slot[index].Color |= atoi(armorTint_row[index * 3 + 2]); From 7071b271831f5ecb757fb133131b689190a6c6ec Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 16 Oct 2016 21:59:35 -0400 Subject: [PATCH 399/693] Fix for travis-ci build failure --- common/item_instance.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/item_instance.h b/common/item_instance.h index 7fbf03cd9..df28d72b4 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -491,11 +491,10 @@ namespace EQEmu ////////////////////////// // Protected Members ////////////////////////// - std::map::const_iterator _cbegin() { return m_contents.cbegin(); } - std::map::const_iterator _cend() { return m_contents.cend(); } - friend class Inventory; + std::map::const_iterator _cbegin() { return m_contents.cbegin(); } + std::map::const_iterator _cend() { return m_contents.cend(); } void _PutItem(uint8 index, ItemInstance* inst) { m_contents[index] = inst; } From 9f01d14c64c688e7f8cec638b9a2c62f4dc5c460 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 16 Oct 2016 23:18:12 -0400 Subject: [PATCH 400/693] Real fix for travis-ci build failure (thanks demonstar55!) --- common/item_instance.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/item_instance.h b/common/item_instance.h index df28d72b4..a1793dee2 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -491,7 +491,7 @@ namespace EQEmu ////////////////////////// // Protected Members ////////////////////////// - friend class Inventory; + friend class ::Inventory; std::map::const_iterator _cbegin() { return m_contents.cbegin(); } std::map::const_iterator _cend() { return m_contents.cend(); } From 3438247904baff7a95ba51775d81c438543c9937 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 17 Oct 2016 01:03:40 -0400 Subject: [PATCH 401/693] Moved namespace ItemField from item_instance.h to shareddb.cpp --- changelog.txt | 3 +++ common/item_instance.h | 12 ------------ common/shareddb.cpp | 11 +++++++++++ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/changelog.txt b/changelog.txt index 5dfeca1d1..0d4412bbd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 10/17/2016 == +Uleat: Moved namespace ItemField from item_instance.h to shareddb.cpp - the only place it is used + == 10/16/2016 == Uleat: Renamed struct EQEmu::ItemBase to EQEmu::ItemData and class ItemInst to EQEmu::ItemInstance Uleat: Added class EQEmu::InventorySlot. Re-attached pertinent inventory token references to EQDictionary diff --git a/common/item_instance.h b/common/item_instance.h index a1793dee2..b83baa13f 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -39,18 +39,6 @@ class EvolveInfo; // Stores information about an evolving item family #include -namespace ItemField -{ - enum - { - source = 0, -#define F(x) x, -#include "item_fieldlist.h" -#undef F - updated - }; -}; - // Specifies usage type for item inside EQEmu::ItemInstance enum ItemInstTypes { diff --git a/common/shareddb.cpp b/common/shareddb.cpp index e748a2d56..35369c758 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -38,6 +38,17 @@ #include "string_util.h" #include "eqemu_config.h" +namespace ItemField +{ + enum { + source = 0, +#define F(x) x, +#include "item_fieldlist.h" +#undef F + updated + }; +} + SharedDatabase::SharedDatabase() : Database() { From 195bc03645e4eff575f1e2de81c477429d0926ba Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 17 Oct 2016 00:56:17 -0500 Subject: [PATCH 402/693] Update eqemu_server.pl [skip ci] - Make eqemu_config.xml parsing more strict to look inside the database section --- utils/scripts/eqemu_server.pl | 49 ++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 180dda907..4fd6bb796 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -1063,17 +1063,46 @@ sub trim { } sub read_eqemu_config_xml { - my $confile = "eqemu_config.xml"; #default - open(F, "<$confile"); - my $indb = 0; - while() { - s/\r//g; - if(/(.*)<\/host>/i) { $host = $1; } - elsif(/(.*)<\/username>/i) { $user = $1; } - elsif(/(.*)<\/password>/i) { $pass = $1; } - elsif(/(.*)<\/db>/i) { $db = $1; } - if(/(.*)<\/longname>/i) { $long_name = $1; } + open (CONFIG, "eqemu_config.xml"); + while (){ + chomp; + $o = $_; + + if($o=~/\<\!--/i){ + next; + } + + if($o=~/database/i && $o=~/\<\//i){ + $in_database_tag = 0; + } + if($o=~/\/i){ + print "IN DATABASE TAG\n" if $debug; + $in_database_tag = 1; + } + if($o=~/\/i){ + ($long_name) = $o =~ /(.*)<\/longname>/; + print "Long Name: " . $long_name . "\n" if $debug; + } + if($in_database_tag == 1){ + if($o=~/\/i && $in_database_tag){ + ($user) = $o =~ />(\w+)/i && $in_database_tag){ + ($pass) = $o =~ />(\w+)/i){ + ($db) = $o =~ />(\w+)/i){ + ($host) = $o =~ />(\w+) Date: Mon, 17 Oct 2016 02:41:09 -0400 Subject: [PATCH 403/693] Separated class Inventory from item_instance files into inventory_profile files --- changelog.txt | 1 + common/CMakeLists.txt | 2 + common/extprofile.h | 2 +- common/inventory_profile.cpp | 1419 ++++++++++++++++++++++++++++++++++ common/inventory_profile.h | 228 ++++++ common/item_instance.cpp | 1400 +-------------------------------- common/item_instance.h | 203 +---- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/shareddb.cpp | 2 +- world/client.cpp | 2 +- world/worlddb.cpp | 3 +- zone/client.h | 4 +- zone/zonedump.h | 2 +- 14 files changed, 1668 insertions(+), 1604 deletions(-) create mode 100644 common/inventory_profile.cpp create mode 100644 common/inventory_profile.h diff --git a/changelog.txt b/changelog.txt index 0d4412bbd..5806a984f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 10/17/2016 == Uleat: Moved namespace ItemField from item_instance.h to shareddb.cpp - the only place it is used +Uleat: Separated class Inventory from item_instance files into inventory_profile files == 10/16/2016 == Uleat: Renamed struct EQEmu::ItemBase to EQEmu::ItemData and class ItemInst to EQEmu::ItemInstance diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index fbfc9305e..cecb47d12 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -35,6 +35,7 @@ SET(common_sources faction.cpp guild_base.cpp guilds.cpp + inventory_profile.cpp inventory_slot.cpp ipc_mutex.cpp item_data.cpp @@ -156,6 +157,7 @@ SET(common_headers global_define.h guild_base.h guilds.h + inventory_profile.h inventory_slot.h ipc_mutex.h item_data.h diff --git a/common/extprofile.h b/common/extprofile.h index e2dae7579..bdb746068 100644 --- a/common/extprofile.h +++ b/common/extprofile.h @@ -19,7 +19,7 @@ #define EXTENDED_PROFILE_H #include "eq_packet_structs.h" -#include "item_instance.h" +#include "inventory_profile.h" #pragma pack(1) diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp new file mode 100644 index 000000000..9e4c4fc94 --- /dev/null +++ b/common/inventory_profile.cpp @@ -0,0 +1,1419 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "inventory_profile.h" +#include "textures.h" +#include "eqemu_logsys.h" +//#include "classes.h" +//#include "global_define.h" +//#include "item_instance.h" +//#include "races.h" +//#include "rulesys.h" +//#include "shareddb.h" +#include "string_util.h" + +#include "../common/light_source.h" + +//#include + +#include + +std::list dirty_inst; + + +// +// class ItemInstQueue +// +ItemInstQueue::~ItemInstQueue() +{ + for (auto iter = m_list.begin(); iter != m_list.end(); ++iter) { + safe_delete(*iter); + } + m_list.clear(); +} + +// Put item onto back of queue +void ItemInstQueue::push(EQEmu::ItemInstance* inst) +{ + m_list.push_back(inst); +} + +// Put item onto front of queue +void ItemInstQueue::push_front(EQEmu::ItemInstance* inst) +{ + m_list.push_front(inst); +} + +// Remove item from front of queue +EQEmu::ItemInstance* ItemInstQueue::pop() +{ + if (m_list.empty()) + return nullptr; + + EQEmu::ItemInstance* inst = m_list.front(); + m_list.pop_front(); + return inst; +} + +// Remove item from back of queue +EQEmu::ItemInstance* ItemInstQueue::pop_back() +{ + if (m_list.empty()) + return nullptr; + + EQEmu::ItemInstance* inst = m_list.back(); + m_list.pop_back(); + return inst; +} + +// Look at item at front of queue +EQEmu::ItemInstance* ItemInstQueue::peek_front() const +{ + return (m_list.empty()) ? nullptr : m_list.front(); +} + + +// +// class Inventory +// +Inventory::~Inventory() +{ + for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { + safe_delete(iter->second); + } + m_worn.clear(); + + for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) { + safe_delete(iter->second); + } + m_inv.clear(); + + for (auto iter = m_bank.begin(); iter != m_bank.end(); ++iter) { + safe_delete(iter->second); + } + m_bank.clear(); + + for (auto iter = m_shbank.begin(); iter != m_shbank.end(); ++iter) { + safe_delete(iter->second); + } + m_shbank.clear(); + + for (auto iter = m_trade.begin(); iter != m_trade.end(); ++iter) { + safe_delete(iter->second); + } + m_trade.clear(); +} + +void Inventory::CleanDirty() { + auto iter = dirty_inst.begin(); + while (iter != dirty_inst.end()) { + delete (*iter); + ++iter; + } + dirty_inst.clear(); +} + +void Inventory::MarkDirty(EQEmu::ItemInstance *inst) { + if (inst) { + dirty_inst.push_back(inst); + } +} + +// Retrieve item at specified slot; returns false if item not found +EQEmu::ItemInstance* Inventory::GetItem(int16 slot_id) const +{ + EQEmu::ItemInstance* result = nullptr; + + // Cursor + if (slot_id == EQEmu::inventory::slotCursor) { + // Cursor slot + result = m_cursor.peek_front(); + } + + // Non bag slots + else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { + result = _GetItem(m_trade, slot_id); + } + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { + // Shared Bank slots + result = _GetItem(m_shbank, slot_id); + } + else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { + // Bank slots + result = _GetItem(m_bank, slot_id); + } + else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { + // Personal inventory slots + result = _GetItem(m_inv, slot_id); + } + else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || + (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { + // Equippable slots (on body) + result = _GetItem(m_worn, slot_id); + } + + // Inner bag slots + else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { + // Trade bag slots + EQEmu::ItemInstance* inst = _GetItem(m_trade, Inventory::CalcSlotId(slot_id)); + if (inst && inst->IsClassBag()) { + result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + } + } + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { + // Shared Bank bag slots + EQEmu::ItemInstance* inst = _GetItem(m_shbank, Inventory::CalcSlotId(slot_id)); + if (inst && inst->IsClassBag()) { + result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + } + } + else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { + // Bank bag slots + EQEmu::ItemInstance* inst = _GetItem(m_bank, Inventory::CalcSlotId(slot_id)); + if (inst && inst->IsClassBag()) { + result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + } + } + else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { + // Cursor bag slots + EQEmu::ItemInstance* inst = m_cursor.peek_front(); + if (inst && inst->IsClassBag()) { + result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + } + } + else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { + // Personal inventory bag slots + EQEmu::ItemInstance* inst = _GetItem(m_inv, Inventory::CalcSlotId(slot_id)); + if (inst && inst->IsClassBag()) { + result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + } + } + + return result; +} + +// Retrieve item at specified position within bag +EQEmu::ItemInstance* Inventory::GetItem(int16 slot_id, uint8 bagidx) const +{ + return GetItem(Inventory::CalcSlotId(slot_id, bagidx)); +} + +// Put an item snto specified slot +int16 Inventory::PutItem(int16 slot_id, const EQEmu::ItemInstance& inst) +{ + // Clean up item already in slot (if exists) + DeleteItem(slot_id); + + if (!inst) { + // User is effectively deleting the item + // in the slot, why hold a null ptr in map<>? + return slot_id; + } + + // Delegate to internal method + return _PutItem(slot_id, inst.Clone()); +} + +int16 Inventory::PushCursor(const EQEmu::ItemInstance& inst) +{ + m_cursor.push(inst.Clone()); + return EQEmu::inventory::slotCursor; +} + +EQEmu::ItemInstance* Inventory::GetCursorItem() +{ + return m_cursor.peek_front(); +} + +// Swap items in inventory +bool Inventory::SwapItem(int16 slot_a, int16 slot_b) +{ + // Temp holding areas for a and b + EQEmu::ItemInstance* inst_a = GetItem(slot_a); + EQEmu::ItemInstance* inst_b = GetItem(slot_b); + + if (inst_a) { if (!inst_a->IsSlotAllowed(slot_b)) { return false; } } + if (inst_b) { if (!inst_b->IsSlotAllowed(slot_a)) { return false; } } + + _PutItem(slot_a, inst_b); // Copy b->a + _PutItem(slot_b, inst_a); // Copy a->b + + return true; +} + +// Remove item from inventory (with memory delete) +bool Inventory::DeleteItem(int16 slot_id, uint8 quantity) +{ + // Pop item out of inventory map (or queue) + EQEmu::ItemInstance* item_to_delete = PopItem(slot_id); + + // Determine if object should be fully deleted, or + // just a quantity of charges of the item can be deleted + if (item_to_delete && (quantity > 0)) { + + item_to_delete->SetCharges(item_to_delete->GetCharges() - quantity); + + // If there are no charges left on the item, + if (item_to_delete->GetCharges() <= 0) { + // If the item is stackable (e.g arrows), or + // the item is not stackable, and is not a charged item, or is expendable, delete it + if (item_to_delete->IsStackable() || + (!item_to_delete->IsStackable() && + ((item_to_delete->GetItem()->MaxCharges == 0) || item_to_delete->IsExpendable())) + ) { + // Item can now be destroyed + Inventory::MarkDirty(item_to_delete); + return true; + } + } + + // Charges still exist, or it is a charged item that is not expendable. Put back into inventory + _PutItem(slot_id, item_to_delete); + return false; + } + + Inventory::MarkDirty(item_to_delete); + return true; + +} + +// Checks All items in a bag for No Drop +bool Inventory::CheckNoDrop(int16 slot_id) { + EQEmu::ItemInstance* inst = GetItem(slot_id); + if (!inst) return false; + if (!inst->GetItem()->NoDrop) return true; + if (inst->GetItem()->ItemClass == 1) { + for (uint8 i = EQEmu::inventory::containerBegin; i < EQEmu::inventory::ContainerCount; i++) { + EQEmu::ItemInstance* bagitem = GetItem(Inventory::CalcSlotId(slot_id, i)); + if (bagitem && !bagitem->GetItem()->NoDrop) + return true; + } + } + return false; +} + +// Remove item from bucket without memory delete +// Returns item pointer if full delete was successful +EQEmu::ItemInstance* Inventory::PopItem(int16 slot_id) +{ + EQEmu::ItemInstance* p = nullptr; + + if (slot_id == EQEmu::inventory::slotCursor) { + p = m_cursor.pop(); + } + else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { + p = m_worn[slot_id]; + m_worn.erase(slot_id); + } + else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { + p = m_inv[slot_id]; + m_inv.erase(slot_id); + } + else if (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) { + p = m_worn[slot_id]; + m_worn.erase(slot_id); + } + else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { + p = m_bank[slot_id]; + m_bank.erase(slot_id); + } + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { + p = m_shbank[slot_id]; + m_shbank.erase(slot_id); + } + else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { + p = m_trade[slot_id]; + m_trade.erase(slot_id); + } + else { + // Is slot inside bag? + EQEmu::ItemInstance* baginst = GetItem(Inventory::CalcSlotId(slot_id)); + if (baginst != nullptr && baginst->IsClassBag()) { + p = baginst->PopItem(Inventory::CalcBagIdx(slot_id)); + } + } + + // Return pointer that needs to be deleted (or otherwise managed) + return p; +} + +bool Inventory::HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity) { + + if (ItemToTry->Stackable) { + + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { + + EQEmu::ItemInstance* InvItem = GetItem(i); + + if (InvItem && (InvItem->GetItem()->ID == ItemToTry->ID) && (InvItem->GetCharges() < InvItem->GetItem()->StackSize)) { + + int ChargeSlotsLeft = InvItem->GetItem()->StackSize - InvItem->GetCharges(); + + if (Quantity <= ChargeSlotsLeft) + return true; + + Quantity -= ChargeSlotsLeft; + + } + if (InvItem && InvItem->IsClassBag()) { + + int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); + uint8 BagSize = InvItem->GetItem()->BagSlots; + for (uint8 BagSlot = EQEmu::inventory::containerBegin; BagSlot < BagSize; BagSlot++) { + + InvItem = GetItem(BaseSlotID + BagSlot); + + if (InvItem && (InvItem->GetItem()->ID == ItemToTry->ID) && + (InvItem->GetCharges() < InvItem->GetItem()->StackSize)) { + + int ChargeSlotsLeft = InvItem->GetItem()->StackSize - InvItem->GetCharges(); + + if (Quantity <= ChargeSlotsLeft) + return true; + + Quantity -= ChargeSlotsLeft; + } + } + } + } + } + + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { + + EQEmu::ItemInstance* InvItem = GetItem(i); + + if (!InvItem) { + + if (!ItemToTry->Stackable) { + + if (Quantity == 1) + return true; + else + Quantity--; + } + else { + if (Quantity <= ItemToTry->StackSize) + return true; + else + Quantity -= ItemToTry->StackSize; + } + + } + else if (InvItem->IsClassBag() && CanItemFitInContainer(ItemToTry, InvItem->GetItem())) { + + int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); + + uint8 BagSize = InvItem->GetItem()->BagSlots; + + for (uint8 BagSlot = EQEmu::inventory::containerBegin; BagSlotStackable) { + + if (Quantity == 1) + return true; + else + Quantity--; + } + else { + if (Quantity <= ItemToTry->StackSize) + return true; + else + Quantity -= ItemToTry->StackSize; + } + } + } + } + } + + return false; + +} + +// Checks that user has at least 'quantity' number of items in a given inventory slot +// Returns first slot it was found in, or SLOT_INVALID if not found + +//This function has a flaw in that it only returns the last stack that it looked at +//when quantity is greater than 1 and not all of quantity can be found in 1 stack. +int16 Inventory::HasItem(uint32 item_id, uint8 quantity, uint8 where) +{ + int16 slot_id = INVALID_INDEX; + + //Altered by Father Nitwit to support a specification of + //where to search, with a default value to maintain compatibility + + // Check each inventory bucket + if (where & invWhereWorn) { + slot_id = _HasItem(m_worn, item_id, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWherePersonal) { + slot_id = _HasItem(m_inv, item_id, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWhereBank) { + slot_id = _HasItem(m_bank, item_id, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWhereSharedBank) { + slot_id = _HasItem(m_shbank, item_id, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWhereTrading) { + slot_id = _HasItem(m_trade, item_id, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + // Behavioral change - Limbo is no longer checked due to improper handling of return value + if (where & invWhereCursor) { + // Check cursor queue + slot_id = _HasItem(m_cursor, item_id, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + return slot_id; +} + +//this function has the same quantity flaw mentioned above in HasItem() +int16 Inventory::HasItemByUse(uint8 use, uint8 quantity, uint8 where) +{ + int16 slot_id = INVALID_INDEX; + + // Check each inventory bucket + if (where & invWhereWorn) { + slot_id = _HasItemByUse(m_worn, use, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWherePersonal) { + slot_id = _HasItemByUse(m_inv, use, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWhereBank) { + slot_id = _HasItemByUse(m_bank, use, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWhereSharedBank) { + slot_id = _HasItemByUse(m_shbank, use, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWhereTrading) { + slot_id = _HasItemByUse(m_trade, use, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + // Behavioral change - Limbo is no longer checked due to improper handling of return value + if (where & invWhereCursor) { + // Check cursor queue + slot_id = _HasItemByUse(m_cursor, use, quantity); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + return slot_id; +} + +int16 Inventory::HasItemByLoreGroup(uint32 loregroup, uint8 where) +{ + int16 slot_id = INVALID_INDEX; + + // Check each inventory bucket + if (where & invWhereWorn) { + slot_id = _HasItemByLoreGroup(m_worn, loregroup); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWherePersonal) { + slot_id = _HasItemByLoreGroup(m_inv, loregroup); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWhereBank) { + slot_id = _HasItemByLoreGroup(m_bank, loregroup); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWhereSharedBank) { + slot_id = _HasItemByLoreGroup(m_shbank, loregroup); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + if (where & invWhereTrading) { + slot_id = _HasItemByLoreGroup(m_trade, loregroup); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + // Behavioral change - Limbo is no longer checked due to improper handling of return value + if (where & invWhereCursor) { + // Check cursor queue + slot_id = _HasItemByLoreGroup(m_cursor, loregroup); + if (slot_id != INVALID_INDEX) + return slot_id; + } + + return slot_id; +} + +// Locate an available inventory slot +// Returns slot_id when there's one available, else SLOT_INVALID +int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow) +{ + // Check basic inventory + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { + if (!GetItem(i)) + // Found available slot in personal inventory + return i; + } + + if (!for_bag) { + for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { + const EQEmu::ItemInstance* inst = GetItem(i); + if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size) + { + if (inst->GetItem()->BagType == EQEmu::item::BagTypeQuiver && inst->GetItem()->ItemType != EQEmu::item::ItemTypeArrow) + { + continue; + } + + int16 base_slot_id = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); + + uint8 slots = inst->GetItem()->BagSlots; + uint8 j; + for (j = EQEmu::inventory::containerBegin; jGetID()) + return INVALID_INDEX; + + // step 1: find room for bags (caller should really ask for slots for bags first to avoid sending them to cursor..and bag item loss) + if (inst->IsClassBag()) { + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { + if (!m_inv[free_slot]) + return free_slot; + } + + return EQEmu::inventory::slotCursor; // return cursor since bags do not stack and will not fit inside other bags..yet...) + } + + // step 2: find partial room for stackables + if (inst->IsStackable()) { + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + + if (!main_inst) + continue; + + if ((main_inst->GetID() == inst->GetID()) && (main_inst->GetCharges() < main_inst->GetItem()->StackSize)) + return free_slot; + } + + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + + if (!main_inst) + continue; + + if (main_inst->IsClassBag()) { // if item-specific containers already have bad items, we won't fix it here... + for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { + const EQEmu::ItemInstance* sub_inst = main_inst->GetItem(free_bag_slot); + + if (!sub_inst) + continue; + + if ((sub_inst->GetID() == inst->GetID()) && (sub_inst->GetCharges() < sub_inst->GetItem()->StackSize)) + return Inventory::CalcSlotId(free_slot, free_bag_slot); + } + } + } + } + + // step 3a: find room for container-specific items (ItemClassArrow) + if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeArrow) { + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + + if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeQuiver) || !main_inst->IsClassBag()) + continue; + + for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { + if (!main_inst->GetItem(free_bag_slot)) + return Inventory::CalcSlotId(free_slot, free_bag_slot); + } + } + } + + // step 3b: find room for container-specific items (ItemClassSmallThrowing) + if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeSmallThrowing) { + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + + if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeBandolier) || !main_inst->IsClassBag()) + continue; + + for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { + if (!main_inst->GetItem(free_bag_slot)) + return Inventory::CalcSlotId(free_slot, free_bag_slot); + } + } + } + + // step 4: just find an empty slot + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + + if (!main_inst) + return free_slot; + } + + for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { + const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + + if (main_inst && main_inst->IsClassBag()) { + if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeBandolier) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeQuiver)) + continue; + + for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { + if (!main_inst->GetItem(free_bag_slot)) + return Inventory::CalcSlotId(free_slot, free_bag_slot); + } + } + } + + //return INVALID_INDEX; // everything else pushes to the cursor + return EQEmu::inventory::slotCursor; +} + +// Opposite of below: Get parent bag slot_id from a slot inside of bag +int16 Inventory::CalcSlotId(int16 slot_id) { + int16 parent_slot_id = INVALID_INDEX; + + // this is not a bag range... using this risks over-writing existing items + //else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) + // parent_slot_id = EmuConstants::BANK_BEGIN + (slot_id - EmuConstants::BANK_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; + //else if (slot_id >= 3100 && slot_id <= 3179) should be {3031..3110}..where did this range come from!!? (verified db save range) + + if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { + parent_slot_id = EQEmu::legacy::GENERAL_BEGIN + (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; + } + else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { + parent_slot_id = EQEmu::inventory::slotCursor; + } + else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { + parent_slot_id = EQEmu::legacy::BANK_BEGIN + (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; + } + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { + parent_slot_id = EQEmu::legacy::SHARED_BANK_BEGIN + (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; + } + else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { + parent_slot_id = EQEmu::legacy::TRADE_BEGIN + (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; + } + + return parent_slot_id; +} + +// Calculate slot_id for an item within a bag +int16 Inventory::CalcSlotId(int16 bagslot_id, uint8 bagidx) { + if (!Inventory::SupportsContainers(bagslot_id)) + return INVALID_INDEX; + + int16 slot_id = INVALID_INDEX; + + if (bagslot_id == EQEmu::inventory::slotCursor || bagslot_id == 8000) { + slot_id = EQEmu::legacy::CURSOR_BAG_BEGIN + bagidx; + } + else if (bagslot_id >= EQEmu::legacy::GENERAL_BEGIN && bagslot_id <= EQEmu::legacy::GENERAL_END) { + slot_id = EQEmu::legacy::GENERAL_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::GENERAL_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; + } + else if (bagslot_id >= EQEmu::legacy::BANK_BEGIN && bagslot_id <= EQEmu::legacy::BANK_END) { + slot_id = EQEmu::legacy::BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::BANK_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; + } + else if (bagslot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && bagslot_id <= EQEmu::legacy::SHARED_BANK_END) { + slot_id = EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; + } + else if (bagslot_id >= EQEmu::legacy::TRADE_BEGIN && bagslot_id <= EQEmu::legacy::TRADE_END) { + slot_id = EQEmu::legacy::TRADE_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::TRADE_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; + } + + return slot_id; +} + +uint8 Inventory::CalcBagIdx(int16 slot_id) { + uint8 index = 0; + + // this is not a bag range... using this risks over-writing existing items + //else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) + // index = (slot_id - EmuConstants::BANK_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; + + if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { + index = (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; + } + else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { + index = (slot_id - EQEmu::legacy::CURSOR_BAG_BEGIN); // % EQEmu::legacy::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots + } + else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { + index = (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; + } + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { + index = (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; + } + else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { + index = (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; + } + else if (slot_id >= EQEmu::legacy::WORLD_BEGIN && slot_id <= EQEmu::legacy::WORLD_END) { + index = (slot_id - EQEmu::legacy::WORLD_BEGIN); // % EQEmu::legacy::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots + } + + return index; +} + +int16 Inventory::CalcSlotFromMaterial(uint8 material) +{ + switch (material) + { + case EQEmu::textures::armorHead: + return EQEmu::inventory::slotHead; + case EQEmu::textures::armorChest: + return EQEmu::inventory::slotChest; + case EQEmu::textures::armorArms: + return EQEmu::inventory::slotArms; + case EQEmu::textures::armorWrist: + return EQEmu::inventory::slotWrist1; // there's 2 bracers, only one bracer material + case EQEmu::textures::armorHands: + return EQEmu::inventory::slotHands; + case EQEmu::textures::armorLegs: + return EQEmu::inventory::slotLegs; + case EQEmu::textures::armorFeet: + return EQEmu::inventory::slotFeet; + case EQEmu::textures::weaponPrimary: + return EQEmu::inventory::slotPrimary; + case EQEmu::textures::weaponSecondary: + return EQEmu::inventory::slotSecondary; + default: + return INVALID_INDEX; + } +} + +uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) +{ + switch (equipslot) + { + case EQEmu::inventory::slotHead: + return EQEmu::textures::armorHead; + case EQEmu::inventory::slotChest: + return EQEmu::textures::armorChest; + case EQEmu::inventory::slotArms: + return EQEmu::textures::armorArms; + case EQEmu::inventory::slotWrist1: + //case SLOT_BRACER02: // non-live behavior + return EQEmu::textures::armorWrist; + case EQEmu::inventory::slotHands: + return EQEmu::textures::armorHands; + case EQEmu::inventory::slotLegs: + return EQEmu::textures::armorLegs; + case EQEmu::inventory::slotFeet: + return EQEmu::textures::armorFeet; + case EQEmu::inventory::slotPrimary: + return EQEmu::textures::weaponPrimary; + case EQEmu::inventory::slotSecondary: + return EQEmu::textures::weaponSecondary; + default: + return EQEmu::textures::materialInvalid; + } +} + +bool Inventory::CanItemFitInContainer(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container) { + + if (!ItemToTry || !Container) + return false; + + if (ItemToTry->Size > Container->BagSize) + return false; + + if ((Container->BagType == EQEmu::item::BagTypeQuiver) && (ItemToTry->ItemType != EQEmu::item::ItemTypeArrow)) + return false; + + if ((Container->BagType == EQEmu::item::BagTypeBandolier) && (ItemToTry->ItemType != EQEmu::item::ItemTypeSmallThrowing)) + return false; + + return true; +} + +bool Inventory::SupportsClickCasting(int16 slot_id) +{ + // there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range + if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::inventory::slotPowerSource) + { + return true; + } + else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) + { + if (EQEmu::inventory::Lookup(m_inventory_version)->AllowClickCastFromBag) + return true; + } + + return false; +} + +bool Inventory::SupportsPotionBeltCasting(int16 slot_id) +{ + if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::inventory::slotPowerSource || (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END)) + return true; + + return false; +} + +// Test whether a given slot can support a container item +bool Inventory::SupportsContainers(int16 slot_id) +{ + if ((slot_id == EQEmu::inventory::slotCursor) || + (slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END) || + (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) || + (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) || + (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) + ) { + return true; + } + + return false; +} + +int Inventory::GetSlotByItemInst(EQEmu::ItemInstance *inst) { + if (!inst) + return INVALID_INDEX; + + int i = GetSlotByItemInstCollection(m_worn, inst); + if (i != INVALID_INDEX) { + return i; + } + + i = GetSlotByItemInstCollection(m_inv, inst); + if (i != INVALID_INDEX) { + return i; + } + + i = GetSlotByItemInstCollection(m_bank, inst); + if (i != INVALID_INDEX) { + return i; + } + + i = GetSlotByItemInstCollection(m_shbank, inst); + if (i != INVALID_INDEX) { + return i; + } + + i = GetSlotByItemInstCollection(m_trade, inst); + if (i != INVALID_INDEX) { + return i; + } + + if (m_cursor.peek_front() == inst) { + return EQEmu::inventory::slotCursor; + } + + return INVALID_INDEX; +} + +uint8 Inventory::FindBrightestLightType() +{ + uint8 brightest_light_type = 0; + + for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { + if ((iter->first < EQEmu::legacy::EQUIPMENT_BEGIN || iter->first > EQEmu::legacy::EQUIPMENT_END) && iter->first != EQEmu::inventory::slotPowerSource) { continue; } + if (iter->first == EQEmu::inventory::slotAmmo) { continue; } + + auto inst = iter->second; + if (inst == nullptr) { continue; } + auto item = inst->GetItem(); + if (item == nullptr) { continue; } + + if (EQEmu::lightsource::IsLevelGreater(item->Light, brightest_light_type)) + brightest_light_type = item->Light; + } + + uint8 general_light_type = 0; + for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) { + if (iter->first < EQEmu::legacy::GENERAL_BEGIN || iter->first > EQEmu::legacy::GENERAL_END) { continue; } + + auto inst = iter->second; + if (inst == nullptr) { continue; } + auto item = inst->GetItem(); + if (item == nullptr) { continue; } + + if (!item->IsClassCommon()) { continue; } + if (item->Light < 9 || item->Light > 13) { continue; } + + if (EQEmu::lightsource::TypeToLevel(item->Light)) + general_light_type = item->Light; + } + + if (EQEmu::lightsource::IsLevelGreater(general_light_type, brightest_light_type)) + brightest_light_type = general_light_type; + + return brightest_light_type; +} + +void Inventory::dumpEntireInventory() { + + dumpWornItems(); + dumpInventory(); + dumpBankItems(); + dumpSharedBankItems(); + + std::cout << std::endl; +} + +void Inventory::dumpWornItems() { + std::cout << "Worn items:" << std::endl; + dumpItemCollection(m_worn); +} + +void Inventory::dumpInventory() { + std::cout << "Inventory items:" << std::endl; + dumpItemCollection(m_inv); +} + +void Inventory::dumpBankItems() { + + std::cout << "Bank items:" << std::endl; + dumpItemCollection(m_bank); +} + +void Inventory::dumpSharedBankItems() { + + std::cout << "Shared Bank items:" << std::endl; + dumpItemCollection(m_shbank); +} + +int Inventory::GetSlotByItemInstCollection(const std::map &collection, EQEmu::ItemInstance *inst) { + for (auto iter = collection.begin(); iter != collection.end(); ++iter) { + EQEmu::ItemInstance *t_inst = iter->second; + if (t_inst == inst) { + return iter->first; + } + + if (t_inst && !t_inst->IsClassBag()) { + for (auto b_iter = t_inst->_cbegin(); b_iter != t_inst->_cend(); ++b_iter) { + if (b_iter->second == inst) { + return Inventory::CalcSlotId(iter->first, b_iter->first); + } + } + } + } + + return -1; +} + +void Inventory::dumpItemCollection(const std::map &collection) +{ + for (auto it = collection.cbegin(); it != collection.cend(); ++it) { + auto inst = it->second; + if (!inst || !inst->GetItem()) + continue; + + std::string slot = StringFormat("Slot %d: %s (%d)", it->first, it->second->GetItem()->Name, (inst->GetCharges() <= 0) ? 1 : inst->GetCharges()); + std::cout << slot << std::endl; + + dumpBagContents(inst, &it); + } +} + +void Inventory::dumpBagContents(EQEmu::ItemInstance *inst, std::map::const_iterator *it) +{ + if (!inst || !inst->IsClassBag()) + return; + + // Go through bag, if bag + for (auto itb = inst->_cbegin(); itb != inst->_cend(); ++itb) { + EQEmu::ItemInstance* baginst = itb->second; + if (!baginst || !baginst->GetItem()) + continue; + + std::string subSlot = StringFormat(" Slot %d: %s (%d)", Inventory::CalcSlotId((*it)->first, itb->first), + baginst->GetItem()->Name, (baginst->GetCharges() <= 0) ? 1 : baginst->GetCharges()); + std::cout << subSlot << std::endl; + } + +} + +// Internal Method: Retrieves item within an inventory bucket +EQEmu::ItemInstance* Inventory::_GetItem(const std::map& bucket, int16 slot_id) const +{ + auto it = bucket.find(slot_id); + if (it != bucket.end()) { + return it->second; + } + + // Not found! + return nullptr; +} + +// Internal Method: "put" item into bucket, without regard for what is currently in bucket +// Assumes item has already been allocated +int16 Inventory::_PutItem(int16 slot_id, EQEmu::ItemInstance* inst) +{ + // What happens here when we _PutItem(MainCursor)? Bad things..really bad things... + // + // If putting a nullptr into slot, we need to remove slot without memory delete + if (inst == nullptr) { + //Why do we not delete the poped item here???? + PopItem(slot_id); + return slot_id; + } + + int16 result = INVALID_INDEX; + int16 parentSlot = INVALID_INDEX; + + if (slot_id == EQEmu::inventory::slotCursor) { + // Replace current item on cursor, if exists + m_cursor.pop(); // no memory delete, clients of this function know what they are doing + m_cursor.push_front(inst); + result = slot_id; + } + else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { + m_worn[slot_id] = inst; + result = slot_id; + } + else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { + m_inv[slot_id] = inst; + result = slot_id; + } + else if (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) { + m_worn[slot_id] = inst; + result = slot_id; + } + else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { + m_bank[slot_id] = inst; + result = slot_id; + } + else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { + m_shbank[slot_id] = inst; + result = slot_id; + } + else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { + m_trade[slot_id] = inst; + result = slot_id; + } + else { + // Slot must be within a bag + parentSlot = Inventory::CalcSlotId(slot_id); + EQEmu::ItemInstance* baginst = GetItem(parentSlot); // Get parent bag + if (baginst && baginst->IsClassBag()) + { + baginst->_PutItem(Inventory::CalcBagIdx(slot_id), inst); + result = slot_id; + } + } + + if (result == INVALID_INDEX) { + Log.Out(Logs::General, Logs::Error, "Inventory::_PutItem: Invalid slot_id specified (%i) with parent slot id (%i)", slot_id, parentSlot); + Inventory::MarkDirty(inst); // Slot not found, clean up + } + + return result; +} + +// Internal Method: Checks an inventory bucket for a particular item +int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, uint8 quantity) +{ + uint32 quantity_found = 0; + + for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { + auto inst = iter->second; + if (inst == nullptr) { continue; } + + if (inst->GetID() == item_id) { + quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); + if (quantity_found >= quantity) + return iter->first; + } + + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) + return EQEmu::legacy::SLOT_AUGMENT; + } + + if (!inst->IsClassBag()) { continue; } + + for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { + auto bag_inst = bag_iter->second; + if (bag_inst == nullptr) { continue; } + + if (bag_inst->GetID() == item_id) { + quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); + if (quantity_found >= quantity) + return Inventory::CalcSlotId(iter->first, bag_iter->first); + } + + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) + return EQEmu::legacy::SLOT_AUGMENT; + } + } + } + + return INVALID_INDEX; +} + +// Internal Method: Checks an inventory queue type bucket for a particular item +int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) +{ + // The downfall of this (these) queue procedure is that callers presume that when an item is + // found, it is presented as being available on the cursor. In cases of a parity check, this + // is sufficient. However, in cases where referential criteria is considered, this can lead + // to unintended results. Funtionality should be observed when referencing the return value + // of this query + + uint32 quantity_found = 0; + + for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { + auto inst = *iter; + if (inst == nullptr) { continue; } + + if (inst->GetID() == item_id) { + quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); + if (quantity_found >= quantity) + return EQEmu::inventory::slotCursor; + } + + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) + return EQEmu::legacy::SLOT_AUGMENT; + } + + if (!inst->IsClassBag()) { continue; } + + for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { + auto bag_inst = bag_iter->second; + if (bag_inst == nullptr) { continue; } + + if (bag_inst->GetID() == item_id) { + quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); + if (quantity_found >= quantity) + return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); + } + + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) + return EQEmu::legacy::SLOT_AUGMENT; + } + } + + // We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo) + break; + } + + return INVALID_INDEX; +} + +// Internal Method: Checks an inventory bucket for a particular item +int16 Inventory::_HasItemByUse(std::map& bucket, uint8 use, uint8 quantity) +{ + uint32 quantity_found = 0; + + for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { + auto inst = iter->second; + if (inst == nullptr) { continue; } + + if (inst->IsClassCommon() && inst->GetItem()->ItemType == use) { + quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); + if (quantity_found >= quantity) + return iter->first; + } + + if (!inst->IsClassBag()) { continue; } + + for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { + auto bag_inst = bag_iter->second; + if (bag_inst == nullptr) { continue; } + + if (bag_inst->IsClassCommon() && bag_inst->GetItem()->ItemType == use) { + quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); + if (quantity_found >= quantity) + return Inventory::CalcSlotId(iter->first, bag_iter->first); + } + } + } + + return INVALID_INDEX; +} + +// Internal Method: Checks an inventory queue type bucket for a particular item +int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) +{ + uint32 quantity_found = 0; + + for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { + auto inst = *iter; + if (inst == nullptr) { continue; } + + if (inst->IsClassCommon() && inst->GetItem()->ItemType == use) { + quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); + if (quantity_found >= quantity) + return EQEmu::inventory::slotCursor; + } + + if (!inst->IsClassBag()) { continue; } + + for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { + auto bag_inst = bag_iter->second; + if (bag_inst == nullptr) { continue; } + + if (bag_inst->IsClassCommon() && bag_inst->GetItem()->ItemType == use) { + quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); + if (quantity_found >= quantity) + return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); + } + } + + // We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo) + break; + } + + return INVALID_INDEX; +} + +int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 loregroup) +{ + for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { + auto inst = iter->second; + if (inst == nullptr) { continue; } + + if (inst->GetItem()->LoreGroup == loregroup) + return iter->first; + + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + auto aug_inst = inst->GetAugment(index); + if (aug_inst == nullptr) { continue; } + + if (aug_inst->GetItem()->LoreGroup == loregroup) + return EQEmu::legacy::SLOT_AUGMENT; + } + + if (!inst->IsClassBag()) { continue; } + + for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { + auto bag_inst = bag_iter->second; + if (bag_inst == nullptr) { continue; } + + if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) + return Inventory::CalcSlotId(iter->first, bag_iter->first); + + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + auto aug_inst = bag_inst->GetAugment(index); + if (aug_inst == nullptr) { continue; } + + if (aug_inst->GetItem()->LoreGroup == loregroup) + return EQEmu::legacy::SLOT_AUGMENT; + } + } + } + + return INVALID_INDEX; +} + +// Internal Method: Checks an inventory queue type bucket for a particular item +int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) +{ + for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { + auto inst = *iter; + if (inst == nullptr) { continue; } + + if (inst->GetItem()->LoreGroup == loregroup) + return EQEmu::inventory::slotCursor; + + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + auto aug_inst = inst->GetAugment(index); + if (aug_inst == nullptr) { continue; } + + if (aug_inst->GetItem()->LoreGroup == loregroup) + return EQEmu::legacy::SLOT_AUGMENT; + } + + if (!inst->IsClassBag()) { continue; } + + for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { + auto bag_inst = bag_iter->second; + if (bag_inst == nullptr) { continue; } + + if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) + return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); + + for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + auto aug_inst = bag_inst->GetAugment(index); + if (aug_inst == nullptr) { continue; } + + if (aug_inst->GetItem()->LoreGroup == loregroup) + return EQEmu::legacy::SLOT_AUGMENT; + } + } + + // We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo) + break; + } + + return INVALID_INDEX; +} diff --git a/common/inventory_profile.h b/common/inventory_profile.h new file mode 100644 index 000000000..3903f9812 --- /dev/null +++ b/common/inventory_profile.h @@ -0,0 +1,228 @@ +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY except by those people which sell it, which + are required to give you total support for your newly bought product; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA +*/ + +// @merth notes: +// These classes could be optimized with database reads/writes by storing +// a status flag indicating how object needs to interact with database + +#ifndef COMMON_INVENTORY_PROFILE_H +#define COMMON_INVENTORY_PROFILE_H + + +#include "item_instance.h" + +#include + + +//FatherNitwit: location bits for searching specific +//places with HasItem() and HasItemByUse() +enum { + invWhereWorn = 0x01, + invWherePersonal = 0x02, //in the character's inventory + invWhereBank = 0x04, + invWhereSharedBank = 0x08, + invWhereTrading = 0x10, + invWhereCursor = 0x20 +}; + +// ######################################## +// Class: Queue +// Queue that allows a read-only iterator +class ItemInstQueue +{ +public: + ~ItemInstQueue(); + ///////////////////////// + // Public Methods + ///////////////////////// + + inline std::list::const_iterator cbegin() { return m_list.cbegin(); } + inline std::list::const_iterator cend() { return m_list.cend(); } + + inline int size() { return static_cast(m_list.size()); } // TODO: change to size_t + inline bool empty() { return m_list.empty(); } + + void push(EQEmu::ItemInstance* inst); + void push_front(EQEmu::ItemInstance* inst); + EQEmu::ItemInstance* pop(); + EQEmu::ItemInstance* pop_back(); + EQEmu::ItemInstance* peek_front() const; + +protected: + ///////////////////////// + // Protected Members + ///////////////////////// + + std::list m_list; +}; + +// ######################################## +// Class: Inventory +// Character inventory +class Inventory +{ + friend class EQEmu::ItemInstance; +public: + /////////////////////////////// + // Public Methods + /////////////////////////////// + + Inventory() { m_inventory_version = EQEmu::versions::InventoryVersion::Unknown; m_inventory_version_set = false; } + ~Inventory(); + + // inv2 creep + bool SetInventoryVersion(EQEmu::versions::InventoryVersion inventory_version) { + if (!m_inventory_version_set) { + m_inventory_version = EQEmu::versions::ValidateInventoryVersion(inventory_version); + return (m_inventory_version_set = true); + } + else { + return false; + } + } + bool SetInventoryVersion(EQEmu::versions::ClientVersion client_version) { return SetInventoryVersion(EQEmu::versions::ConvertClientVersionToInventoryVersion(client_version)); } + + EQEmu::versions::InventoryVersion InventoryVersion() { return m_inventory_version; } + + static void CleanDirty(); + static void MarkDirty(EQEmu::ItemInstance *inst); + + // Retrieve a writeable item at specified slot + EQEmu::ItemInstance* GetItem(int16 slot_id) const; + EQEmu::ItemInstance* GetItem(int16 slot_id, uint8 bagidx) const; + + inline std::list::const_iterator cursor_cbegin() { return m_cursor.cbegin(); } + inline std::list::const_iterator cursor_cend() { return m_cursor.cend(); } + + inline int CursorSize() { return m_cursor.size(); } + inline bool CursorEmpty() { return m_cursor.empty(); } + + // Retrieve a read-only item from inventory + inline const EQEmu::ItemInstance* operator[](int16 slot_id) const { return GetItem(slot_id); } + + // Add item to inventory + int16 PutItem(int16 slot_id, const EQEmu::ItemInstance& inst); + + // Add item to cursor queue + int16 PushCursor(const EQEmu::ItemInstance& inst); + + // Get cursor item in front of queue + EQEmu::ItemInstance* GetCursorItem(); + + // Swap items in inventory + bool SwapItem(int16 slot_a, int16 slot_b); + + // Remove item from inventory + bool DeleteItem(int16 slot_id, uint8 quantity=0); + + // Checks All items in a bag for No Drop + bool CheckNoDrop(int16 slot_id); + + // Remove item from inventory (and take control of memory) + EQEmu::ItemInstance* PopItem(int16 slot_id); + + // Check whether there is space for the specified number of the specified item. + bool HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity); + + // Check whether item exists in inventory + // where argument specifies OR'd list of invWhere constants to look + int16 HasItem(uint32 item_id, uint8 quantity = 0, uint8 where = 0xFF); + + // Check whether item exists in inventory + // where argument specifies OR'd list of invWhere constants to look + int16 HasItemByUse(uint8 use, uint8 quantity=0, uint8 where=0xFF); + + // Check whether item exists in inventory + // where argument specifies OR'd list of invWhere constants to look + int16 HasItemByLoreGroup(uint32 loregroup, uint8 where=0xFF); + + // Locate an available inventory slot + int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false); + int16 FindFreeSlotForTradeItem(const EQEmu::ItemInstance* inst); + + // Calculate slot_id for an item within a bag + static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id + static int16 CalcSlotId(int16 bagslot_id, uint8 bagidx); // Calc slot_id for item inside bag + static uint8 CalcBagIdx(int16 slot_id); // Calc bagidx for slot_id + static int16 CalcSlotFromMaterial(uint8 material); + static uint8 CalcMaterialFromSlot(int16 equipslot); + + static bool CanItemFitInContainer(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container); + + // Test for valid inventory casting slot + bool SupportsClickCasting(int16 slot_id); + bool SupportsPotionBeltCasting(int16 slot_id); + + // Test whether a given slot can support a container item + static bool SupportsContainers(int16 slot_id); + + int GetSlotByItemInst(EQEmu::ItemInstance *inst); + + uint8 FindBrightestLightType(); + + void dumpEntireInventory(); + void dumpWornItems(); + void dumpInventory(); + void dumpBankItems(); + void dumpSharedBankItems(); + + void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value); + void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value); + void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value); + void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value); + std::string GetCustomItemData(int16 slot_id, std::string identifier); +protected: + /////////////////////////////// + // Protected Methods + /////////////////////////////// + + int GetSlotByItemInstCollection(const std::map &collection, EQEmu::ItemInstance *inst); + void dumpItemCollection(const std::map &collection); + void dumpBagContents(EQEmu::ItemInstance *inst, std::map::const_iterator *it); + + // Retrieves item within an inventory bucket + EQEmu::ItemInstance* _GetItem(const std::map& bucket, int16 slot_id) const; + + // Private "put" item into bucket, without regard for what is currently in bucket + int16 _PutItem(int16 slot_id, EQEmu::ItemInstance* inst); + + // Checks an inventory bucket for a particular item + int16 _HasItem(std::map& bucket, uint32 item_id, uint8 quantity); + int16 _HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity); + int16 _HasItemByUse(std::map& bucket, uint8 use, uint8 quantity); + int16 _HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity); + int16 _HasItemByLoreGroup(std::map& bucket, uint32 loregroup); + int16 _HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup); + + + // Player inventory + std::map m_worn; // Items worn by character + std::map m_inv; // Items in character personal inventory + std::map m_bank; // Items in character bank + std::map m_shbank; // Items in character shared bank + std::map m_trade; // Items in a trade session + ItemInstQueue m_cursor; // Items on cursor: FIFO + +private: + // Active inventory version + EQEmu::versions::InventoryVersion m_inventory_version; + bool m_inventory_version_set; +}; + +#endif /*COMMON_INVENTORY_PROFILE_H*/ diff --git a/common/item_instance.cpp b/common/item_instance.cpp index fbe2af543..de01c0893 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -16,21 +16,21 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "classes.h" -#include "global_define.h" -#include "item_instance.h" -#include "races.h" +#include "inventory_profile.h" +//#include "classes.h" +//#include "global_define.h" +//#include "item_instance.h" +//#include "races.h" #include "rulesys.h" #include "shareddb.h" #include "string_util.h" -#include "../common/light_source.h" +//#include "../common/light_source.h" -#include +//#include -#include +//#include -std::list dirty_inst; int32 NextItemInstSerialNumber = 1; static inline int32 GetNextItemInstSerialNumber() { @@ -53,1390 +53,6 @@ static inline int32 GetNextItemInstSerialNumber() { return NextItemInstSerialNumber; } - -// -// class ItemInstQueue -// -ItemInstQueue::~ItemInstQueue() -{ - for (auto iter = m_list.begin(); iter != m_list.end(); ++iter) { - safe_delete(*iter); - } - m_list.clear(); -} - -// Put item onto back of queue -void ItemInstQueue::push(EQEmu::ItemInstance* inst) -{ - m_list.push_back(inst); -} - -// Put item onto front of queue -void ItemInstQueue::push_front(EQEmu::ItemInstance* inst) -{ - m_list.push_front(inst); -} - -// Remove item from front of queue -EQEmu::ItemInstance* ItemInstQueue::pop() -{ - if (m_list.empty()) - return nullptr; - - EQEmu::ItemInstance* inst = m_list.front(); - m_list.pop_front(); - return inst; -} - -// Remove item from back of queue -EQEmu::ItemInstance* ItemInstQueue::pop_back() -{ - if (m_list.empty()) - return nullptr; - - EQEmu::ItemInstance* inst = m_list.back(); - m_list.pop_back(); - return inst; -} - -// Look at item at front of queue -EQEmu::ItemInstance* ItemInstQueue::peek_front() const -{ - return (m_list.empty()) ? nullptr : m_list.front(); -} - - -// -// class Inventory -// -Inventory::~Inventory() -{ - for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { - safe_delete(iter->second); - } - m_worn.clear(); - - for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) { - safe_delete(iter->second); - } - m_inv.clear(); - - for (auto iter = m_bank.begin(); iter != m_bank.end(); ++iter) { - safe_delete(iter->second); - } - m_bank.clear(); - - for (auto iter = m_shbank.begin(); iter != m_shbank.end(); ++iter) { - safe_delete(iter->second); - } - m_shbank.clear(); - - for (auto iter = m_trade.begin(); iter != m_trade.end(); ++iter) { - safe_delete(iter->second); - } - m_trade.clear(); -} - -void Inventory::CleanDirty() { - auto iter = dirty_inst.begin(); - while (iter != dirty_inst.end()) { - delete (*iter); - ++iter; - } - dirty_inst.clear(); -} - -void Inventory::MarkDirty(EQEmu::ItemInstance *inst) { - if (inst) { - dirty_inst.push_back(inst); - } -} - -// Retrieve item at specified slot; returns false if item not found -EQEmu::ItemInstance* Inventory::GetItem(int16 slot_id) const -{ - EQEmu::ItemInstance* result = nullptr; - - // Cursor - if (slot_id == EQEmu::inventory::slotCursor) { - // Cursor slot - result = m_cursor.peek_front(); - } - - // Non bag slots - else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { - result = _GetItem(m_trade, slot_id); - } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { - // Shared Bank slots - result = _GetItem(m_shbank, slot_id); - } - else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { - // Bank slots - result = _GetItem(m_bank, slot_id); - } - else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { - // Personal inventory slots - result = _GetItem(m_inv, slot_id); - } - else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || - (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { - // Equippable slots (on body) - result = _GetItem(m_worn, slot_id); - } - - // Inner bag slots - else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { - // Trade bag slots - EQEmu::ItemInstance* inst = _GetItem(m_trade, Inventory::CalcSlotId(slot_id)); - if (inst && inst->IsClassBag()) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); - } - } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { - // Shared Bank bag slots - EQEmu::ItemInstance* inst = _GetItem(m_shbank, Inventory::CalcSlotId(slot_id)); - if (inst && inst->IsClassBag()) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); - } - } - else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { - // Bank bag slots - EQEmu::ItemInstance* inst = _GetItem(m_bank, Inventory::CalcSlotId(slot_id)); - if (inst && inst->IsClassBag()) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); - } - } - else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { - // Cursor bag slots - EQEmu::ItemInstance* inst = m_cursor.peek_front(); - if (inst && inst->IsClassBag()) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); - } - } - else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { - // Personal inventory bag slots - EQEmu::ItemInstance* inst = _GetItem(m_inv, Inventory::CalcSlotId(slot_id)); - if (inst && inst->IsClassBag()) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); - } - } - - return result; -} - -// Retrieve item at specified position within bag -EQEmu::ItemInstance* Inventory::GetItem(int16 slot_id, uint8 bagidx) const -{ - return GetItem(Inventory::CalcSlotId(slot_id, bagidx)); -} - -// Put an item snto specified slot -int16 Inventory::PutItem(int16 slot_id, const EQEmu::ItemInstance& inst) -{ - // Clean up item already in slot (if exists) - DeleteItem(slot_id); - - if (!inst) { - // User is effectively deleting the item - // in the slot, why hold a null ptr in map<>? - return slot_id; - } - - // Delegate to internal method - return _PutItem(slot_id, inst.Clone()); -} - -int16 Inventory::PushCursor(const EQEmu::ItemInstance& inst) -{ - m_cursor.push(inst.Clone()); - return EQEmu::inventory::slotCursor; -} - -EQEmu::ItemInstance* Inventory::GetCursorItem() -{ - return m_cursor.peek_front(); -} - -// Swap items in inventory -bool Inventory::SwapItem(int16 slot_a, int16 slot_b) -{ - // Temp holding areas for a and b - EQEmu::ItemInstance* inst_a = GetItem(slot_a); - EQEmu::ItemInstance* inst_b = GetItem(slot_b); - - if (inst_a) { if (!inst_a->IsSlotAllowed(slot_b)) { return false; } } - if (inst_b) { if (!inst_b->IsSlotAllowed(slot_a)) { return false; } } - - _PutItem(slot_a, inst_b); // Copy b->a - _PutItem(slot_b, inst_a); // Copy a->b - - return true; -} - -// Remove item from inventory (with memory delete) -bool Inventory::DeleteItem(int16 slot_id, uint8 quantity) -{ - // Pop item out of inventory map (or queue) - EQEmu::ItemInstance* item_to_delete = PopItem(slot_id); - - // Determine if object should be fully deleted, or - // just a quantity of charges of the item can be deleted - if (item_to_delete && (quantity > 0)) { - - item_to_delete->SetCharges(item_to_delete->GetCharges() - quantity); - - // If there are no charges left on the item, - if (item_to_delete->GetCharges() <= 0) { - // If the item is stackable (e.g arrows), or - // the item is not stackable, and is not a charged item, or is expendable, delete it - if (item_to_delete->IsStackable() || - (!item_to_delete->IsStackable() && - ((item_to_delete->GetItem()->MaxCharges == 0) || item_to_delete->IsExpendable())) - ) { - // Item can now be destroyed - Inventory::MarkDirty(item_to_delete); - return true; - } - } - - // Charges still exist, or it is a charged item that is not expendable. Put back into inventory - _PutItem(slot_id, item_to_delete); - return false; - } - - Inventory::MarkDirty(item_to_delete); - return true; - -} - -// Checks All items in a bag for No Drop -bool Inventory::CheckNoDrop(int16 slot_id) { - EQEmu::ItemInstance* inst = GetItem(slot_id); - if (!inst) return false; - if (!inst->GetItem()->NoDrop) return true; - if (inst->GetItem()->ItemClass == 1) { - for (uint8 i = EQEmu::inventory::containerBegin; i < EQEmu::inventory::ContainerCount; i++) { - EQEmu::ItemInstance* bagitem = GetItem(Inventory::CalcSlotId(slot_id, i)); - if (bagitem && !bagitem->GetItem()->NoDrop) - return true; - } - } - return false; -} - -// Remove item from bucket without memory delete -// Returns item pointer if full delete was successful -EQEmu::ItemInstance* Inventory::PopItem(int16 slot_id) -{ - EQEmu::ItemInstance* p = nullptr; - - if (slot_id == EQEmu::inventory::slotCursor) { - p = m_cursor.pop(); - } - else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { - p = m_worn[slot_id]; - m_worn.erase(slot_id); - } - else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { - p = m_inv[slot_id]; - m_inv.erase(slot_id); - } - else if (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) { - p = m_worn[slot_id]; - m_worn.erase(slot_id); - } - else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { - p = m_bank[slot_id]; - m_bank.erase(slot_id); - } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { - p = m_shbank[slot_id]; - m_shbank.erase(slot_id); - } - else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { - p = m_trade[slot_id]; - m_trade.erase(slot_id); - } - else { - // Is slot inside bag? - EQEmu::ItemInstance* baginst = GetItem(Inventory::CalcSlotId(slot_id)); - if (baginst != nullptr && baginst->IsClassBag()) { - p = baginst->PopItem(Inventory::CalcBagIdx(slot_id)); - } - } - - // Return pointer that needs to be deleted (or otherwise managed) - return p; -} - -bool Inventory::HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity) { - - if (ItemToTry->Stackable) { - - for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { - - EQEmu::ItemInstance* InvItem = GetItem(i); - - if (InvItem && (InvItem->GetItem()->ID == ItemToTry->ID) && (InvItem->GetCharges() < InvItem->GetItem()->StackSize)) { - - int ChargeSlotsLeft = InvItem->GetItem()->StackSize - InvItem->GetCharges(); - - if (Quantity <= ChargeSlotsLeft) - return true; - - Quantity -= ChargeSlotsLeft; - - } - if (InvItem && InvItem->IsClassBag()) { - - int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); - uint8 BagSize = InvItem->GetItem()->BagSlots; - for (uint8 BagSlot = EQEmu::inventory::containerBegin; BagSlot < BagSize; BagSlot++) { - - InvItem = GetItem(BaseSlotID + BagSlot); - - if (InvItem && (InvItem->GetItem()->ID == ItemToTry->ID) && - (InvItem->GetCharges() < InvItem->GetItem()->StackSize)) { - - int ChargeSlotsLeft = InvItem->GetItem()->StackSize - InvItem->GetCharges(); - - if (Quantity <= ChargeSlotsLeft) - return true; - - Quantity -= ChargeSlotsLeft; - } - } - } - } - } - - for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { - - EQEmu::ItemInstance* InvItem = GetItem(i); - - if (!InvItem) { - - if (!ItemToTry->Stackable) { - - if (Quantity == 1) - return true; - else - Quantity--; - } - else { - if (Quantity <= ItemToTry->StackSize) - return true; - else - Quantity -= ItemToTry->StackSize; - } - - } - else if (InvItem->IsClassBag() && CanItemFitInContainer(ItemToTry, InvItem->GetItem())) { - - int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); - - uint8 BagSize = InvItem->GetItem()->BagSlots; - - for (uint8 BagSlot = EQEmu::inventory::containerBegin; BagSlotStackable) { - - if (Quantity == 1) - return true; - else - Quantity--; - } - else { - if (Quantity <= ItemToTry->StackSize) - return true; - else - Quantity -= ItemToTry->StackSize; - } - } - } - } - } - - return false; - -} - -// Checks that user has at least 'quantity' number of items in a given inventory slot -// Returns first slot it was found in, or SLOT_INVALID if not found - -//This function has a flaw in that it only returns the last stack that it looked at -//when quantity is greater than 1 and not all of quantity can be found in 1 stack. -int16 Inventory::HasItem(uint32 item_id, uint8 quantity, uint8 where) -{ - int16 slot_id = INVALID_INDEX; - - //Altered by Father Nitwit to support a specification of - //where to search, with a default value to maintain compatibility - - // Check each inventory bucket - if (where & invWhereWorn) { - slot_id = _HasItem(m_worn, item_id, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWherePersonal) { - slot_id = _HasItem(m_inv, item_id, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWhereBank) { - slot_id = _HasItem(m_bank, item_id, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWhereSharedBank) { - slot_id = _HasItem(m_shbank, item_id, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWhereTrading) { - slot_id = _HasItem(m_trade, item_id, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - // Behavioral change - Limbo is no longer checked due to improper handling of return value - if (where & invWhereCursor) { - // Check cursor queue - slot_id = _HasItem(m_cursor, item_id, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - return slot_id; -} - -//this function has the same quantity flaw mentioned above in HasItem() -int16 Inventory::HasItemByUse(uint8 use, uint8 quantity, uint8 where) -{ - int16 slot_id = INVALID_INDEX; - - // Check each inventory bucket - if (where & invWhereWorn) { - slot_id = _HasItemByUse(m_worn, use, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWherePersonal) { - slot_id = _HasItemByUse(m_inv, use, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWhereBank) { - slot_id = _HasItemByUse(m_bank, use, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWhereSharedBank) { - slot_id = _HasItemByUse(m_shbank, use, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWhereTrading) { - slot_id = _HasItemByUse(m_trade, use, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - // Behavioral change - Limbo is no longer checked due to improper handling of return value - if (where & invWhereCursor) { - // Check cursor queue - slot_id = _HasItemByUse(m_cursor, use, quantity); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - return slot_id; -} - -int16 Inventory::HasItemByLoreGroup(uint32 loregroup, uint8 where) -{ - int16 slot_id = INVALID_INDEX; - - // Check each inventory bucket - if (where & invWhereWorn) { - slot_id = _HasItemByLoreGroup(m_worn, loregroup); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWherePersonal) { - slot_id = _HasItemByLoreGroup(m_inv, loregroup); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWhereBank) { - slot_id = _HasItemByLoreGroup(m_bank, loregroup); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWhereSharedBank) { - slot_id = _HasItemByLoreGroup(m_shbank, loregroup); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - if (where & invWhereTrading) { - slot_id = _HasItemByLoreGroup(m_trade, loregroup); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - // Behavioral change - Limbo is no longer checked due to improper handling of return value - if (where & invWhereCursor) { - // Check cursor queue - slot_id = _HasItemByLoreGroup(m_cursor, loregroup); - if (slot_id != INVALID_INDEX) - return slot_id; - } - - return slot_id; -} - -// Locate an available inventory slot -// Returns slot_id when there's one available, else SLOT_INVALID -int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, bool is_arrow) -{ - // Check basic inventory - for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { - if (!GetItem(i)) - // Found available slot in personal inventory - return i; - } - - if (!for_bag) { - for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { - const EQEmu::ItemInstance* inst = GetItem(i); - if (inst && inst->IsClassBag() && inst->GetItem()->BagSize >= min_size) - { - if (inst->GetItem()->BagType == EQEmu::item::BagTypeQuiver && inst->GetItem()->ItemType != EQEmu::item::ItemTypeArrow) - { - continue; - } - - int16 base_slot_id = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); - - uint8 slots = inst->GetItem()->BagSlots; - uint8 j; - for (j = EQEmu::inventory::containerBegin; jGetID()) - return INVALID_INDEX; - - // step 1: find room for bags (caller should really ask for slots for bags first to avoid sending them to cursor..and bag item loss) - if (inst->IsClassBag()) { - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - if (!m_inv[free_slot]) - return free_slot; - } - - return EQEmu::inventory::slotCursor; // return cursor since bags do not stack and will not fit inside other bags..yet...) - } - - // step 2: find partial room for stackables - if (inst->IsStackable()) { - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; - - if (!main_inst) - continue; - - if ((main_inst->GetID() == inst->GetID()) && (main_inst->GetCharges() < main_inst->GetItem()->StackSize)) - return free_slot; - } - - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; - - if (!main_inst) - continue; - - if (main_inst->IsClassBag()) { // if item-specific containers already have bad items, we won't fix it here... - for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { - const EQEmu::ItemInstance* sub_inst = main_inst->GetItem(free_bag_slot); - - if (!sub_inst) - continue; - - if ((sub_inst->GetID() == inst->GetID()) && (sub_inst->GetCharges() < sub_inst->GetItem()->StackSize)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); - } - } - } - } - - // step 3a: find room for container-specific items (ItemClassArrow) - if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeArrow) { - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; - - if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeQuiver) || !main_inst->IsClassBag()) - continue; - - for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { - if (!main_inst->GetItem(free_bag_slot)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); - } - } - } - - // step 3b: find room for container-specific items (ItemClassSmallThrowing) - if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeSmallThrowing) { - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; - - if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeBandolier) || !main_inst->IsClassBag()) - continue; - - for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { - if (!main_inst->GetItem(free_bag_slot)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); - } - } - } - - // step 4: just find an empty slot - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; - - if (!main_inst) - return free_slot; - } - - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; - - if (main_inst && main_inst->IsClassBag()) { - if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeBandolier) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeQuiver)) - continue; - - for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { - if (!main_inst->GetItem(free_bag_slot)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); - } - } - } - - //return INVALID_INDEX; // everything else pushes to the cursor - return EQEmu::inventory::slotCursor; -} - -// Opposite of below: Get parent bag slot_id from a slot inside of bag -int16 Inventory::CalcSlotId(int16 slot_id) { - int16 parent_slot_id = INVALID_INDEX; - - // this is not a bag range... using this risks over-writing existing items - //else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) - // parent_slot_id = EmuConstants::BANK_BEGIN + (slot_id - EmuConstants::BANK_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; - //else if (slot_id >= 3100 && slot_id <= 3179) should be {3031..3110}..where did this range come from!!? (verified db save range) - - if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { - parent_slot_id = EQEmu::legacy::GENERAL_BEGIN + (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; - } - else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { - parent_slot_id = EQEmu::inventory::slotCursor; - } - else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { - parent_slot_id = EQEmu::legacy::BANK_BEGIN + (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; - } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { - parent_slot_id = EQEmu::legacy::SHARED_BANK_BEGIN + (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; - } - else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { - parent_slot_id = EQEmu::legacy::TRADE_BEGIN + (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; - } - - return parent_slot_id; -} - -// Calculate slot_id for an item within a bag -int16 Inventory::CalcSlotId(int16 bagslot_id, uint8 bagidx) { - if (!Inventory::SupportsContainers(bagslot_id)) - return INVALID_INDEX; - - int16 slot_id = INVALID_INDEX; - - if (bagslot_id == EQEmu::inventory::slotCursor || bagslot_id == 8000) { - slot_id = EQEmu::legacy::CURSOR_BAG_BEGIN + bagidx; - } - else if (bagslot_id >= EQEmu::legacy::GENERAL_BEGIN && bagslot_id <= EQEmu::legacy::GENERAL_END) { - slot_id = EQEmu::legacy::GENERAL_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::GENERAL_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; - } - else if (bagslot_id >= EQEmu::legacy::BANK_BEGIN && bagslot_id <= EQEmu::legacy::BANK_END) { - slot_id = EQEmu::legacy::BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::BANK_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; - } - else if (bagslot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && bagslot_id <= EQEmu::legacy::SHARED_BANK_END) { - slot_id = EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; - } - else if (bagslot_id >= EQEmu::legacy::TRADE_BEGIN && bagslot_id <= EQEmu::legacy::TRADE_END) { - slot_id = EQEmu::legacy::TRADE_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::TRADE_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; - } - - return slot_id; -} - -uint8 Inventory::CalcBagIdx(int16 slot_id) { - uint8 index = 0; - - // this is not a bag range... using this risks over-writing existing items - //else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) - // index = (slot_id - EmuConstants::BANK_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; - - if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { - index = (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; - } - else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { - index = (slot_id - EQEmu::legacy::CURSOR_BAG_BEGIN); // % EQEmu::legacy::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots - } - else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { - index = (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; - } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { - index = (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; - } - else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { - index = (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; - } - else if (slot_id >= EQEmu::legacy::WORLD_BEGIN && slot_id <= EQEmu::legacy::WORLD_END) { - index = (slot_id - EQEmu::legacy::WORLD_BEGIN); // % EQEmu::legacy::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots - } - - return index; -} - -int16 Inventory::CalcSlotFromMaterial(uint8 material) -{ - switch (material) - { - case EQEmu::textures::armorHead: - return EQEmu::inventory::slotHead; - case EQEmu::textures::armorChest: - return EQEmu::inventory::slotChest; - case EQEmu::textures::armorArms: - return EQEmu::inventory::slotArms; - case EQEmu::textures::armorWrist: - return EQEmu::inventory::slotWrist1; // there's 2 bracers, only one bracer material - case EQEmu::textures::armorHands: - return EQEmu::inventory::slotHands; - case EQEmu::textures::armorLegs: - return EQEmu::inventory::slotLegs; - case EQEmu::textures::armorFeet: - return EQEmu::inventory::slotFeet; - case EQEmu::textures::weaponPrimary: - return EQEmu::inventory::slotPrimary; - case EQEmu::textures::weaponSecondary: - return EQEmu::inventory::slotSecondary; - default: - return INVALID_INDEX; - } -} - -uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) -{ - switch (equipslot) - { - case EQEmu::inventory::slotHead: - return EQEmu::textures::armorHead; - case EQEmu::inventory::slotChest: - return EQEmu::textures::armorChest; - case EQEmu::inventory::slotArms: - return EQEmu::textures::armorArms; - case EQEmu::inventory::slotWrist1: - //case SLOT_BRACER02: // non-live behavior - return EQEmu::textures::armorWrist; - case EQEmu::inventory::slotHands: - return EQEmu::textures::armorHands; - case EQEmu::inventory::slotLegs: - return EQEmu::textures::armorLegs; - case EQEmu::inventory::slotFeet: - return EQEmu::textures::armorFeet; - case EQEmu::inventory::slotPrimary: - return EQEmu::textures::weaponPrimary; - case EQEmu::inventory::slotSecondary: - return EQEmu::textures::weaponSecondary; - default: - return EQEmu::textures::materialInvalid; - } -} - -bool Inventory::CanItemFitInContainer(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container) { - - if (!ItemToTry || !Container) - return false; - - if (ItemToTry->Size > Container->BagSize) - return false; - - if ((Container->BagType == EQEmu::item::BagTypeQuiver) && (ItemToTry->ItemType != EQEmu::item::ItemTypeArrow)) - return false; - - if ((Container->BagType == EQEmu::item::BagTypeBandolier) && (ItemToTry->ItemType != EQEmu::item::ItemTypeSmallThrowing)) - return false; - - return true; -} - -bool Inventory::SupportsClickCasting(int16 slot_id) -{ - // there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range - if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::inventory::slotPowerSource) - { - return true; - } - else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) - { - if (EQEmu::inventory::Lookup(m_inventory_version)->AllowClickCastFromBag) - return true; - } - - return false; -} - -bool Inventory::SupportsPotionBeltCasting(int16 slot_id) -{ - if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::inventory::slotPowerSource || (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END)) - return true; - - return false; -} - -// Test whether a given slot can support a container item -bool Inventory::SupportsContainers(int16 slot_id) -{ - if ((slot_id == EQEmu::inventory::slotCursor) || - (slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END) || - (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) || - (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) || - (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) - ) { - return true; - } - - return false; -} - -int Inventory::GetSlotByItemInst(EQEmu::ItemInstance *inst) { - if (!inst) - return INVALID_INDEX; - - int i = GetSlotByItemInstCollection(m_worn, inst); - if (i != INVALID_INDEX) { - return i; - } - - i = GetSlotByItemInstCollection(m_inv, inst); - if (i != INVALID_INDEX) { - return i; - } - - i = GetSlotByItemInstCollection(m_bank, inst); - if (i != INVALID_INDEX) { - return i; - } - - i = GetSlotByItemInstCollection(m_shbank, inst); - if (i != INVALID_INDEX) { - return i; - } - - i = GetSlotByItemInstCollection(m_trade, inst); - if (i != INVALID_INDEX) { - return i; - } - - if (m_cursor.peek_front() == inst) { - return EQEmu::inventory::slotCursor; - } - - return INVALID_INDEX; -} - -uint8 Inventory::FindBrightestLightType() -{ - uint8 brightest_light_type = 0; - - for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { - if ((iter->first < EQEmu::legacy::EQUIPMENT_BEGIN || iter->first > EQEmu::legacy::EQUIPMENT_END) && iter->first != EQEmu::inventory::slotPowerSource) { continue; } - if (iter->first == EQEmu::inventory::slotAmmo) { continue; } - - auto inst = iter->second; - if (inst == nullptr) { continue; } - auto item = inst->GetItem(); - if (item == nullptr) { continue; } - - if (EQEmu::lightsource::IsLevelGreater(item->Light, brightest_light_type)) - brightest_light_type = item->Light; - } - - uint8 general_light_type = 0; - for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) { - if (iter->first < EQEmu::legacy::GENERAL_BEGIN || iter->first > EQEmu::legacy::GENERAL_END) { continue; } - - auto inst = iter->second; - if (inst == nullptr) { continue; } - auto item = inst->GetItem(); - if (item == nullptr) { continue; } - - if (!item->IsClassCommon()) { continue; } - if (item->Light < 9 || item->Light > 13) { continue; } - - if (EQEmu::lightsource::TypeToLevel(item->Light)) - general_light_type = item->Light; - } - - if (EQEmu::lightsource::IsLevelGreater(general_light_type, brightest_light_type)) - brightest_light_type = general_light_type; - - return brightest_light_type; -} - -void Inventory::dumpEntireInventory() { - - dumpWornItems(); - dumpInventory(); - dumpBankItems(); - dumpSharedBankItems(); - - std::cout << std::endl; -} - -void Inventory::dumpWornItems() { - std::cout << "Worn items:" << std::endl; - dumpItemCollection(m_worn); -} - -void Inventory::dumpInventory() { - std::cout << "Inventory items:" << std::endl; - dumpItemCollection(m_inv); -} - -void Inventory::dumpBankItems() { - - std::cout << "Bank items:" << std::endl; - dumpItemCollection(m_bank); -} - -void Inventory::dumpSharedBankItems() { - - std::cout << "Shared Bank items:" << std::endl; - dumpItemCollection(m_shbank); -} - -int Inventory::GetSlotByItemInstCollection(const std::map &collection, EQEmu::ItemInstance *inst) { - for (auto iter = collection.begin(); iter != collection.end(); ++iter) { - EQEmu::ItemInstance *t_inst = iter->second; - if (t_inst == inst) { - return iter->first; - } - - if (t_inst && !t_inst->IsClassBag()) { - for (auto b_iter = t_inst->_cbegin(); b_iter != t_inst->_cend(); ++b_iter) { - if (b_iter->second == inst) { - return Inventory::CalcSlotId(iter->first, b_iter->first); - } - } - } - } - - return -1; -} - -void Inventory::dumpItemCollection(const std::map &collection) -{ - for (auto it = collection.cbegin(); it != collection.cend(); ++it) { - auto inst = it->second; - if (!inst || !inst->GetItem()) - continue; - - std::string slot = StringFormat("Slot %d: %s (%d)", it->first, it->second->GetItem()->Name, (inst->GetCharges() <= 0) ? 1 : inst->GetCharges()); - std::cout << slot << std::endl; - - dumpBagContents(inst, &it); - } -} - -void Inventory::dumpBagContents(EQEmu::ItemInstance *inst, std::map::const_iterator *it) -{ - if (!inst || !inst->IsClassBag()) - return; - - // Go through bag, if bag - for (auto itb = inst->_cbegin(); itb != inst->_cend(); ++itb) { - EQEmu::ItemInstance* baginst = itb->second; - if (!baginst || !baginst->GetItem()) - continue; - - std::string subSlot = StringFormat(" Slot %d: %s (%d)", Inventory::CalcSlotId((*it)->first, itb->first), - baginst->GetItem()->Name, (baginst->GetCharges() <= 0) ? 1 : baginst->GetCharges()); - std::cout << subSlot << std::endl; - } - -} - -// Internal Method: Retrieves item within an inventory bucket -EQEmu::ItemInstance* Inventory::_GetItem(const std::map& bucket, int16 slot_id) const -{ - auto it = bucket.find(slot_id); - if (it != bucket.end()) { - return it->second; - } - - // Not found! - return nullptr; -} - -// Internal Method: "put" item into bucket, without regard for what is currently in bucket -// Assumes item has already been allocated -int16 Inventory::_PutItem(int16 slot_id, EQEmu::ItemInstance* inst) -{ - // What happens here when we _PutItem(MainCursor)? Bad things..really bad things... - // - // If putting a nullptr into slot, we need to remove slot without memory delete - if (inst == nullptr) { - //Why do we not delete the poped item here???? - PopItem(slot_id); - return slot_id; - } - - int16 result = INVALID_INDEX; - int16 parentSlot = INVALID_INDEX; - - if (slot_id == EQEmu::inventory::slotCursor) { - // Replace current item on cursor, if exists - m_cursor.pop(); // no memory delete, clients of this function know what they are doing - m_cursor.push_front(inst); - result = slot_id; - } - else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { - m_worn[slot_id] = inst; - result = slot_id; - } - else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { - m_inv[slot_id] = inst; - result = slot_id; - } - else if (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) { - m_worn[slot_id] = inst; - result = slot_id; - } - else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { - m_bank[slot_id] = inst; - result = slot_id; - } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { - m_shbank[slot_id] = inst; - result = slot_id; - } - else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { - m_trade[slot_id] = inst; - result = slot_id; - } - else { - // Slot must be within a bag - parentSlot = Inventory::CalcSlotId(slot_id); - EQEmu::ItemInstance* baginst = GetItem(parentSlot); // Get parent bag - if (baginst && baginst->IsClassBag()) - { - baginst->_PutItem(Inventory::CalcBagIdx(slot_id), inst); - result = slot_id; - } - } - - if (result == INVALID_INDEX) { - Log.Out(Logs::General, Logs::Error, "Inventory::_PutItem: Invalid slot_id specified (%i) with parent slot id (%i)", slot_id, parentSlot); - Inventory::MarkDirty(inst); // Slot not found, clean up - } - - return result; -} - -// Internal Method: Checks an inventory bucket for a particular item -int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, uint8 quantity) -{ - uint32 quantity_found = 0; - - for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { - auto inst = iter->second; - if (inst == nullptr) { continue; } - - if (inst->GetID() == item_id) { - quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); - if (quantity_found >= quantity) - return iter->first; - } - - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { - if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::legacy::SLOT_AUGMENT; - } - - if (!inst->IsClassBag()) { continue; } - - for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } - - if (bag_inst->GetID() == item_id) { - quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); - if (quantity_found >= quantity) - return Inventory::CalcSlotId(iter->first, bag_iter->first); - } - - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { - if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::legacy::SLOT_AUGMENT; - } - } - } - - return INVALID_INDEX; -} - -// Internal Method: Checks an inventory queue type bucket for a particular item -int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) -{ - // The downfall of this (these) queue procedure is that callers presume that when an item is - // found, it is presented as being available on the cursor. In cases of a parity check, this - // is sufficient. However, in cases where referential criteria is considered, this can lead - // to unintended results. Funtionality should be observed when referencing the return value - // of this query - - uint32 quantity_found = 0; - - for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { - auto inst = *iter; - if (inst == nullptr) { continue; } - - if (inst->GetID() == item_id) { - quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); - if (quantity_found >= quantity) - return EQEmu::inventory::slotCursor; - } - - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { - if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::legacy::SLOT_AUGMENT; - } - - if (!inst->IsClassBag()) { continue; } - - for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } - - if (bag_inst->GetID() == item_id) { - quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); - if (quantity_found >= quantity) - return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); - } - - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { - if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::legacy::SLOT_AUGMENT; - } - } - - // We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo) - break; - } - - return INVALID_INDEX; -} - -// Internal Method: Checks an inventory bucket for a particular item -int16 Inventory::_HasItemByUse(std::map& bucket, uint8 use, uint8 quantity) -{ - uint32 quantity_found = 0; - - for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { - auto inst = iter->second; - if (inst == nullptr) { continue; } - - if (inst->IsClassCommon() && inst->GetItem()->ItemType == use) { - quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); - if (quantity_found >= quantity) - return iter->first; - } - - if (!inst->IsClassBag()) { continue; } - - for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } - - if (bag_inst->IsClassCommon() && bag_inst->GetItem()->ItemType == use) { - quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); - if (quantity_found >= quantity) - return Inventory::CalcSlotId(iter->first, bag_iter->first); - } - } - } - - return INVALID_INDEX; -} - -// Internal Method: Checks an inventory queue type bucket for a particular item -int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) -{ - uint32 quantity_found = 0; - - for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { - auto inst = *iter; - if (inst == nullptr) { continue; } - - if (inst->IsClassCommon() && inst->GetItem()->ItemType == use) { - quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); - if (quantity_found >= quantity) - return EQEmu::inventory::slotCursor; - } - - if (!inst->IsClassBag()) { continue; } - - for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } - - if (bag_inst->IsClassCommon() && bag_inst->GetItem()->ItemType == use) { - quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); - if (quantity_found >= quantity) - return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); - } - } - - // We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo) - break; - } - - return INVALID_INDEX; -} - -int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 loregroup) -{ - for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { - auto inst = iter->second; - if (inst == nullptr) { continue; } - - if (inst->GetItem()->LoreGroup == loregroup) - return iter->first; - - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { - auto aug_inst = inst->GetAugment(index); - if (aug_inst == nullptr) { continue; } - - if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::legacy::SLOT_AUGMENT; - } - - if (!inst->IsClassBag()) { continue; } - - for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } - - if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) - return Inventory::CalcSlotId(iter->first, bag_iter->first); - - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { - auto aug_inst = bag_inst->GetAugment(index); - if (aug_inst == nullptr) { continue; } - - if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::legacy::SLOT_AUGMENT; - } - } - } - - return INVALID_INDEX; -} - -// Internal Method: Checks an inventory queue type bucket for a particular item -int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) -{ - for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { - auto inst = *iter; - if (inst == nullptr) { continue; } - - if (inst->GetItem()->LoreGroup == loregroup) - return EQEmu::inventory::slotCursor; - - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { - auto aug_inst = inst->GetAugment(index); - if (aug_inst == nullptr) { continue; } - - if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::legacy::SLOT_AUGMENT; - } - - if (!inst->IsClassBag()) { continue; } - - for (auto bag_iter = inst->_cbegin(); bag_iter != inst->_cend(); ++bag_iter) { - auto bag_inst = bag_iter->second; - if (bag_inst == nullptr) { continue; } - - if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) - return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); - - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { - auto aug_inst = bag_inst->GetAugment(index); - if (aug_inst == nullptr) { continue; } - - if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::legacy::SLOT_AUGMENT; - } - } - - // We only check the visible cursor due to lack of queue processing ability (client allows duplicate in limbo) - break; - } - - return INVALID_INDEX; -} - - // // class EQEmu::ItemInstance // diff --git a/common/item_instance.h b/common/item_instance.h index b83baa13f..2a4afdca1 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -35,7 +35,6 @@ class EvolveInfo; // Stores information about an evolving item family #include "../common/deity.h" #include "../common/memory_buffer.h" -#include #include @@ -52,208 +51,8 @@ typedef enum { byFlagNotSet //apply action if the flag is NOT set } byFlagSetting; - -//FatherNitwit: location bits for searching specific -//places with HasItem() and HasItemByUse() -enum { - invWhereWorn = 0x01, - invWherePersonal = 0x02, //in the character's inventory - invWhereBank = 0x04, - invWhereSharedBank = 0x08, - invWhereTrading = 0x10, - invWhereCursor = 0x20 -}; - -namespace EQEmu -{ - class ItemInstance; -} - -// ######################################## -// Class: Queue -// Queue that allows a read-only iterator -class ItemInstQueue -{ -public: - ~ItemInstQueue(); - ///////////////////////// - // Public Methods - ///////////////////////// - - inline std::list::const_iterator cbegin() { return m_list.cbegin(); } - inline std::list::const_iterator cend() { return m_list.cend(); } - - inline int size() { return static_cast(m_list.size()); } // TODO: change to size_t - inline bool empty() { return m_list.empty(); } - - void push(EQEmu::ItemInstance* inst); - void push_front(EQEmu::ItemInstance* inst); - EQEmu::ItemInstance* pop(); - EQEmu::ItemInstance* pop_back(); - EQEmu::ItemInstance* peek_front() const; - -protected: - ///////////////////////// - // Protected Members - ///////////////////////// - - std::list m_list; -}; - -// ######################################## -// Class: Inventory -// Character inventory -class Inventory -{ - friend class EQEmu::ItemInstance; -public: - /////////////////////////////// - // Public Methods - /////////////////////////////// - - Inventory() { m_inventory_version = EQEmu::versions::InventoryVersion::Unknown; m_inventory_version_set = false; } - ~Inventory(); - - // inv2 creep - bool SetInventoryVersion(EQEmu::versions::InventoryVersion inventory_version) { - if (!m_inventory_version_set) { - m_inventory_version = EQEmu::versions::ValidateInventoryVersion(inventory_version); - return (m_inventory_version_set = true); - } - else { - return false; - } - } - bool SetInventoryVersion(EQEmu::versions::ClientVersion client_version) { return SetInventoryVersion(EQEmu::versions::ConvertClientVersionToInventoryVersion(client_version)); } - - EQEmu::versions::InventoryVersion InventoryVersion() { return m_inventory_version; } - - static void CleanDirty(); - static void MarkDirty(EQEmu::ItemInstance *inst); - - // Retrieve a writeable item at specified slot - EQEmu::ItemInstance* GetItem(int16 slot_id) const; - EQEmu::ItemInstance* GetItem(int16 slot_id, uint8 bagidx) const; - - inline std::list::const_iterator cursor_cbegin() { return m_cursor.cbegin(); } - inline std::list::const_iterator cursor_cend() { return m_cursor.cend(); } - - inline int CursorSize() { return m_cursor.size(); } - inline bool CursorEmpty() { return m_cursor.empty(); } - - // Retrieve a read-only item from inventory - inline const EQEmu::ItemInstance* operator[](int16 slot_id) const { return GetItem(slot_id); } - - // Add item to inventory - int16 PutItem(int16 slot_id, const EQEmu::ItemInstance& inst); - - // Add item to cursor queue - int16 PushCursor(const EQEmu::ItemInstance& inst); - - // Get cursor item in front of queue - EQEmu::ItemInstance* GetCursorItem(); - - // Swap items in inventory - bool SwapItem(int16 slot_a, int16 slot_b); - - // Remove item from inventory - bool DeleteItem(int16 slot_id, uint8 quantity=0); - - // Checks All items in a bag for No Drop - bool CheckNoDrop(int16 slot_id); - - // Remove item from inventory (and take control of memory) - EQEmu::ItemInstance* PopItem(int16 slot_id); - - // Check whether there is space for the specified number of the specified item. - bool HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity); - - // Check whether item exists in inventory - // where argument specifies OR'd list of invWhere constants to look - int16 HasItem(uint32 item_id, uint8 quantity = 0, uint8 where = 0xFF); - - // Check whether item exists in inventory - // where argument specifies OR'd list of invWhere constants to look - int16 HasItemByUse(uint8 use, uint8 quantity=0, uint8 where=0xFF); - - // Check whether item exists in inventory - // where argument specifies OR'd list of invWhere constants to look - int16 HasItemByLoreGroup(uint32 loregroup, uint8 where=0xFF); - - // Locate an available inventory slot - int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false); - int16 FindFreeSlotForTradeItem(const EQEmu::ItemInstance* inst); - - // Calculate slot_id for an item within a bag - static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id - static int16 CalcSlotId(int16 bagslot_id, uint8 bagidx); // Calc slot_id for item inside bag - static uint8 CalcBagIdx(int16 slot_id); // Calc bagidx for slot_id - static int16 CalcSlotFromMaterial(uint8 material); - static uint8 CalcMaterialFromSlot(int16 equipslot); - - static bool CanItemFitInContainer(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container); - - // Test for valid inventory casting slot - bool SupportsClickCasting(int16 slot_id); - bool SupportsPotionBeltCasting(int16 slot_id); - - // Test whether a given slot can support a container item - static bool SupportsContainers(int16 slot_id); - - int GetSlotByItemInst(EQEmu::ItemInstance *inst); - - uint8 FindBrightestLightType(); - - void dumpEntireInventory(); - void dumpWornItems(); - void dumpInventory(); - void dumpBankItems(); - void dumpSharedBankItems(); - - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value); - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value); - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value); - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value); - std::string GetCustomItemData(int16 slot_id, std::string identifier); -protected: - /////////////////////////////// - // Protected Methods - /////////////////////////////// - - int GetSlotByItemInstCollection(const std::map &collection, EQEmu::ItemInstance *inst); - void dumpItemCollection(const std::map &collection); - void dumpBagContents(EQEmu::ItemInstance *inst, std::map::const_iterator *it); - - // Retrieves item within an inventory bucket - EQEmu::ItemInstance* _GetItem(const std::map& bucket, int16 slot_id) const; - - // Private "put" item into bucket, without regard for what is currently in bucket - int16 _PutItem(int16 slot_id, EQEmu::ItemInstance* inst); - - // Checks an inventory bucket for a particular item - int16 _HasItem(std::map& bucket, uint32 item_id, uint8 quantity); - int16 _HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity); - int16 _HasItemByUse(std::map& bucket, uint8 use, uint8 quantity); - int16 _HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity); - int16 _HasItemByLoreGroup(std::map& bucket, uint32 loregroup); - int16 _HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup); - - - // Player inventory - std::map m_worn; // Items worn by character - std::map m_inv; // Items in character personal inventory - std::map m_bank; // Items in character bank - std::map m_shbank; // Items in character shared bank - std::map m_trade; // Items in a trade session - ItemInstQueue m_cursor; // Items on cursor: FIFO - -private: - // Active inventory version - EQEmu::versions::InventoryVersion m_inventory_version; - bool m_inventory_version_set; -}; - class SharedDatabase; +class Inventory; // ######################################## // Class: EQEmu::ItemInstance diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index d3b4456b7..cc1744a31 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -29,7 +29,7 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" #include "../string_util.h" -#include "../item_instance.h" +#include "../inventory_profile.h" #include "rof_structs.h" #include "../rulesys.h" diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 676f4c89f..aadd0a90b 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -29,7 +29,7 @@ #include "../eq_packet_structs.h" #include "../misc_functions.h" #include "../string_util.h" -#include "../item_instance.h" +#include "../inventory_profile.h" #include "rof2_structs.h" #include "../rulesys.h" diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 35369c758..8cd62f164 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -29,7 +29,7 @@ #include "faction.h" #include "features.h" #include "ipc_mutex.h" -#include "item_instance.h" +#include "inventory_profile.h" #include "loottable.h" #include "memory_mapped_file.h" #include "mysql.h" diff --git a/world/client.cpp b/world/client.cpp index ff3c0ce9a..5614d6317 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -25,7 +25,7 @@ #include "../common/eq_packet_structs.h" #include "../common/packet_dump.h" #include "../common/eq_stream_intf.h" -#include "../common/item_instance.h" +#include "../common/inventory_profile.h" #include "../common/races.h" #include "../common/classes.h" #include "../common/languages.h" diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 0fa814417..65476190e 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -17,10 +17,9 @@ */ #include "worlddb.h" -//#include "../common/item_instance.h" #include "../common/string_util.h" #include "../common/eq_packet_structs.h" -#include "../common/item_instance.h" +#include "../common/inventory_profile.h" #include "../common/rulesys.h" #include #include diff --git a/zone/client.h b/zone/client.h index bfe9f96cd..82ee442d2 100644 --- a/zone/client.h +++ b/zone/client.h @@ -45,9 +45,9 @@ namespace EQEmu #include "../common/extprofile.h" #include "../common/races.h" #include "../common/seperator.h" -#include "../common/item_instance.h" +#include "../common/inventory_profile.h" #include "../common/guilds.h" -#include "../common/item_data.h" +//#include "../common/item_data.h" #include "common.h" #include "merc.h" diff --git a/zone/zonedump.h b/zone/zonedump.h index 20412ed70..80888d31e 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -28,7 +28,7 @@ spawn2 mediumblob, npcs mediumblob, npc_loot mediumblob, gmspawntype mediumblob, #define ZONEDUMP_H #include "../common/faction.h" #include "../common/eq_packet_structs.h" -#include "../common/item_instance.h" +#include "../common/inventory_profile.h" #pragma pack(1) From 04f4fd652bdbc05766bf1eb390aaa23dcb81a7ff Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 17 Oct 2016 04:59:00 -0400 Subject: [PATCH 404/693] Renamed class Inventory to EQEmu::InventoryProfile --- changelog.txt | 1 + common/database.cpp | 2 +- common/database.h | 8 +- common/inventory_profile.cpp | 526 +++++++++++++++++------------------ common/inventory_profile.h | 231 +++++++-------- common/item_instance.cpp | 138 ++++----- common/item_instance.h | 17 +- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/shareddb.cpp | 28 +- common/shareddb.h | 12 +- world/client.cpp | 2 +- world/worlddb.cpp | 4 +- zone/bonuses.cpp | 4 +- zone/bot.cpp | 14 +- zone/bot.h | 4 +- zone/bot_command.cpp | 2 +- zone/bot_database.cpp | 4 +- zone/bot_database.h | 4 +- zone/client.cpp | 4 +- zone/client.h | 6 +- zone/client_packet.cpp | 4 +- zone/command.cpp | 10 +- zone/corpse.cpp | 10 +- zone/inventory.cpp | 56 ++-- zone/lua_inventory.h | 16 +- zone/merc.cpp | 2 +- zone/merc.h | 2 +- zone/mob.cpp | 6 +- zone/npc.cpp | 4 +- zone/tradeskills.cpp | 14 +- zone/trading.cpp | 18 +- zone/zone.cpp | 2 +- 33 files changed, 586 insertions(+), 573 deletions(-) diff --git a/changelog.txt b/changelog.txt index 5806a984f..1ac1ec731 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 10/17/2016 == Uleat: Moved namespace ItemField from item_instance.h to shareddb.cpp - the only place it is used Uleat: Separated class Inventory from item_instance files into inventory_profile files +Uleat: Renamed class Inventory to EQEmu::InventoryProfile == 10/16/2016 == Uleat: Renamed struct EQEmu::ItemBase to EQEmu::ItemData and class ItemInst to EQEmu::ItemInstance diff --git a/common/database.cpp b/common/database.cpp index 743bec9f2..66ac8495b 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -672,7 +672,7 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe } /* This only for new Character creation storing */ -bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv) { +bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, EQEmu::InventoryProfile* inv) { uint32 charid = 0; char zone[50]; float x, y, z; diff --git a/common/database.h b/common/database.h index 69ad0c576..6f3fd0642 100644 --- a/common/database.h +++ b/common/database.h @@ -37,10 +37,14 @@ //atoi is not uint32 or uint32 safe!!!! #define atoul(str) strtoul(str, nullptr, 10) -class Inventory; class MySQLRequestResult; class Client; +namespace EQEmu +{ + class InventoryProfile; +} + struct EventLogDetails_Struct { uint32 id; char accountname[64]; @@ -109,7 +113,7 @@ public: bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); bool SetHackerFlag(const char* accountname, const char* charactername, const char* hacked); bool SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone); - bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv); + bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, EQEmu::InventoryProfile* inv); bool UpdateName(const char* oldname, const char* newname); /* General Information Queries */ diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index 9e4c4fc94..c952392b1 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -89,9 +89,9 @@ EQEmu::ItemInstance* ItemInstQueue::peek_front() const // -// class Inventory +// class EQEmu::InventoryProfile // -Inventory::~Inventory() +EQEmu::InventoryProfile::~InventoryProfile() { for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { safe_delete(iter->second); @@ -119,7 +119,7 @@ Inventory::~Inventory() m_trade.clear(); } -void Inventory::CleanDirty() { +void EQEmu::InventoryProfile::CleanDirty() { auto iter = dirty_inst.begin(); while (iter != dirty_inst.end()) { delete (*iter); @@ -128,79 +128,79 @@ void Inventory::CleanDirty() { dirty_inst.clear(); } -void Inventory::MarkDirty(EQEmu::ItemInstance *inst) { +void EQEmu::InventoryProfile::MarkDirty(ItemInstance *inst) { if (inst) { dirty_inst.push_back(inst); } } // Retrieve item at specified slot; returns false if item not found -EQEmu::ItemInstance* Inventory::GetItem(int16 slot_id) const +EQEmu::ItemInstance* EQEmu::InventoryProfile::GetItem(int16 slot_id) const { - EQEmu::ItemInstance* result = nullptr; + ItemInstance* result = nullptr; // Cursor - if (slot_id == EQEmu::inventory::slotCursor) { + if (slot_id == inventory::slotCursor) { // Cursor slot result = m_cursor.peek_front(); } // Non bag slots - else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { + else if (slot_id >= legacy::TRADE_BEGIN && slot_id <= legacy::TRADE_END) { result = _GetItem(m_trade, slot_id); } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { + else if (slot_id >= legacy::SHARED_BANK_BEGIN && slot_id <= legacy::SHARED_BANK_END) { // Shared Bank slots result = _GetItem(m_shbank, slot_id); } - else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { + else if (slot_id >= legacy::BANK_BEGIN && slot_id <= legacy::BANK_END) { // Bank slots result = _GetItem(m_bank, slot_id); } - else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { + else if ((slot_id >= legacy::GENERAL_BEGIN && slot_id <= legacy::GENERAL_END)) { // Personal inventory slots result = _GetItem(m_inv, slot_id); } - else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || - (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { + else if ((slot_id >= legacy::EQUIPMENT_BEGIN && slot_id <= legacy::EQUIPMENT_END) || + (slot_id >= legacy::TRIBUTE_BEGIN && slot_id <= legacy::TRIBUTE_END) || (slot_id == inventory::slotPowerSource)) { // Equippable slots (on body) result = _GetItem(m_worn, slot_id); } // Inner bag slots - else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { + else if (slot_id >= legacy::TRADE_BAGS_BEGIN && slot_id <= legacy::TRADE_BAGS_END) { // Trade bag slots - EQEmu::ItemInstance* inst = _GetItem(m_trade, Inventory::CalcSlotId(slot_id)); + ItemInstance* inst = _GetItem(m_trade, InventoryProfile::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + result = inst->GetItem(InventoryProfile::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { + else if (slot_id >= legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= legacy::SHARED_BANK_BAGS_END) { // Shared Bank bag slots - EQEmu::ItemInstance* inst = _GetItem(m_shbank, Inventory::CalcSlotId(slot_id)); + ItemInstance* inst = _GetItem(m_shbank, InventoryProfile::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + result = inst->GetItem(InventoryProfile::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { + else if (slot_id >= legacy::BANK_BAGS_BEGIN && slot_id <= legacy::BANK_BAGS_END) { // Bank bag slots - EQEmu::ItemInstance* inst = _GetItem(m_bank, Inventory::CalcSlotId(slot_id)); + ItemInstance* inst = _GetItem(m_bank, InventoryProfile::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + result = inst->GetItem(InventoryProfile::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { + else if (slot_id >= legacy::CURSOR_BAG_BEGIN && slot_id <= legacy::CURSOR_BAG_END) { // Cursor bag slots - EQEmu::ItemInstance* inst = m_cursor.peek_front(); + ItemInstance* inst = m_cursor.peek_front(); if (inst && inst->IsClassBag()) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + result = inst->GetItem(InventoryProfile::CalcBagIdx(slot_id)); } } - else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { + else if (slot_id >= legacy::GENERAL_BAGS_BEGIN && slot_id <= legacy::GENERAL_BAGS_END) { // Personal inventory bag slots - EQEmu::ItemInstance* inst = _GetItem(m_inv, Inventory::CalcSlotId(slot_id)); + ItemInstance* inst = _GetItem(m_inv, InventoryProfile::CalcSlotId(slot_id)); if (inst && inst->IsClassBag()) { - result = inst->GetItem(Inventory::CalcBagIdx(slot_id)); + result = inst->GetItem(InventoryProfile::CalcBagIdx(slot_id)); } } @@ -208,13 +208,13 @@ EQEmu::ItemInstance* Inventory::GetItem(int16 slot_id) const } // Retrieve item at specified position within bag -EQEmu::ItemInstance* Inventory::GetItem(int16 slot_id, uint8 bagidx) const +EQEmu::ItemInstance* EQEmu::InventoryProfile::GetItem(int16 slot_id, uint8 bagidx) const { - return GetItem(Inventory::CalcSlotId(slot_id, bagidx)); + return GetItem(InventoryProfile::CalcSlotId(slot_id, bagidx)); } // Put an item snto specified slot -int16 Inventory::PutItem(int16 slot_id, const EQEmu::ItemInstance& inst) +int16 EQEmu::InventoryProfile::PutItem(int16 slot_id, const ItemInstance& inst) { // Clean up item already in slot (if exists) DeleteItem(slot_id); @@ -229,23 +229,23 @@ int16 Inventory::PutItem(int16 slot_id, const EQEmu::ItemInstance& inst) return _PutItem(slot_id, inst.Clone()); } -int16 Inventory::PushCursor(const EQEmu::ItemInstance& inst) +int16 EQEmu::InventoryProfile::PushCursor(const ItemInstance& inst) { m_cursor.push(inst.Clone()); - return EQEmu::inventory::slotCursor; + return inventory::slotCursor; } -EQEmu::ItemInstance* Inventory::GetCursorItem() +EQEmu::ItemInstance* EQEmu::InventoryProfile::GetCursorItem() { return m_cursor.peek_front(); } // Swap items in inventory -bool Inventory::SwapItem(int16 slot_a, int16 slot_b) +bool EQEmu::InventoryProfile::SwapItem(int16 slot_a, int16 slot_b) { // Temp holding areas for a and b - EQEmu::ItemInstance* inst_a = GetItem(slot_a); - EQEmu::ItemInstance* inst_b = GetItem(slot_b); + ItemInstance* inst_a = GetItem(slot_a); + ItemInstance* inst_b = GetItem(slot_b); if (inst_a) { if (!inst_a->IsSlotAllowed(slot_b)) { return false; } } if (inst_b) { if (!inst_b->IsSlotAllowed(slot_a)) { return false; } } @@ -257,10 +257,10 @@ bool Inventory::SwapItem(int16 slot_a, int16 slot_b) } // Remove item from inventory (with memory delete) -bool Inventory::DeleteItem(int16 slot_id, uint8 quantity) +bool EQEmu::InventoryProfile::DeleteItem(int16 slot_id, uint8 quantity) { // Pop item out of inventory map (or queue) - EQEmu::ItemInstance* item_to_delete = PopItem(slot_id); + ItemInstance* item_to_delete = PopItem(slot_id); // Determine if object should be fully deleted, or // just a quantity of charges of the item can be deleted @@ -277,7 +277,7 @@ bool Inventory::DeleteItem(int16 slot_id, uint8 quantity) ((item_to_delete->GetItem()->MaxCharges == 0) || item_to_delete->IsExpendable())) ) { // Item can now be destroyed - Inventory::MarkDirty(item_to_delete); + InventoryProfile::MarkDirty(item_to_delete); return true; } } @@ -287,19 +287,19 @@ bool Inventory::DeleteItem(int16 slot_id, uint8 quantity) return false; } - Inventory::MarkDirty(item_to_delete); + InventoryProfile::MarkDirty(item_to_delete); return true; } // Checks All items in a bag for No Drop -bool Inventory::CheckNoDrop(int16 slot_id) { - EQEmu::ItemInstance* inst = GetItem(slot_id); +bool EQEmu::InventoryProfile::CheckNoDrop(int16 slot_id) { + ItemInstance* inst = GetItem(slot_id); if (!inst) return false; if (!inst->GetItem()->NoDrop) return true; if (inst->GetItem()->ItemClass == 1) { - for (uint8 i = EQEmu::inventory::containerBegin; i < EQEmu::inventory::ContainerCount; i++) { - EQEmu::ItemInstance* bagitem = GetItem(Inventory::CalcSlotId(slot_id, i)); + for (uint8 i = inventory::containerBegin; i < inventory::ContainerCount; i++) { + ItemInstance* bagitem = GetItem(InventoryProfile::CalcSlotId(slot_id, i)); if (bagitem && !bagitem->GetItem()->NoDrop) return true; } @@ -309,42 +309,42 @@ bool Inventory::CheckNoDrop(int16 slot_id) { // Remove item from bucket without memory delete // Returns item pointer if full delete was successful -EQEmu::ItemInstance* Inventory::PopItem(int16 slot_id) +EQEmu::ItemInstance* EQEmu::InventoryProfile::PopItem(int16 slot_id) { - EQEmu::ItemInstance* p = nullptr; + ItemInstance* p = nullptr; - if (slot_id == EQEmu::inventory::slotCursor) { + if (slot_id == inventory::slotCursor) { p = m_cursor.pop(); } - else if ((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { + else if ((slot_id >= legacy::EQUIPMENT_BEGIN && slot_id <= legacy::EQUIPMENT_END) || (slot_id == inventory::slotPowerSource)) { p = m_worn[slot_id]; m_worn.erase(slot_id); } - else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { + else if ((slot_id >= legacy::GENERAL_BEGIN && slot_id <= legacy::GENERAL_END)) { p = m_inv[slot_id]; m_inv.erase(slot_id); } - else if (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) { + else if (slot_id >= legacy::TRIBUTE_BEGIN && slot_id <= legacy::TRIBUTE_END) { p = m_worn[slot_id]; m_worn.erase(slot_id); } - else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { + else if (slot_id >= legacy::BANK_BEGIN && slot_id <= legacy::BANK_END) { p = m_bank[slot_id]; m_bank.erase(slot_id); } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { + else if (slot_id >= legacy::SHARED_BANK_BEGIN && slot_id <= legacy::SHARED_BANK_END) { p = m_shbank[slot_id]; m_shbank.erase(slot_id); } - else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { + else if (slot_id >= legacy::TRADE_BEGIN && slot_id <= legacy::TRADE_END) { p = m_trade[slot_id]; m_trade.erase(slot_id); } else { // Is slot inside bag? - EQEmu::ItemInstance* baginst = GetItem(Inventory::CalcSlotId(slot_id)); + ItemInstance* baginst = GetItem(InventoryProfile::CalcSlotId(slot_id)); if (baginst != nullptr && baginst->IsClassBag()) { - p = baginst->PopItem(Inventory::CalcBagIdx(slot_id)); + p = baginst->PopItem(InventoryProfile::CalcBagIdx(slot_id)); } } @@ -352,13 +352,13 @@ EQEmu::ItemInstance* Inventory::PopItem(int16 slot_id) return p; } -bool Inventory::HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity) { +bool EQEmu::InventoryProfile::HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity) { if (ItemToTry->Stackable) { - for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { + for (int16 i = legacy::GENERAL_BEGIN; i <= legacy::GENERAL_END; i++) { - EQEmu::ItemInstance* InvItem = GetItem(i); + ItemInstance* InvItem = GetItem(i); if (InvItem && (InvItem->GetItem()->ID == ItemToTry->ID) && (InvItem->GetCharges() < InvItem->GetItem()->StackSize)) { @@ -372,9 +372,9 @@ bool Inventory::HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity } if (InvItem && InvItem->IsClassBag()) { - int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); + int16 BaseSlotID = InventoryProfile::CalcSlotId(i, inventory::containerBegin); uint8 BagSize = InvItem->GetItem()->BagSlots; - for (uint8 BagSlot = EQEmu::inventory::containerBegin; BagSlot < BagSize; BagSlot++) { + for (uint8 BagSlot = inventory::containerBegin; BagSlot < BagSize; BagSlot++) { InvItem = GetItem(BaseSlotID + BagSlot); @@ -393,9 +393,9 @@ bool Inventory::HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity } } - for (int16 i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { + for (int16 i = legacy::GENERAL_BEGIN; i <= legacy::GENERAL_END; i++) { - EQEmu::ItemInstance* InvItem = GetItem(i); + ItemInstance* InvItem = GetItem(i); if (!InvItem) { @@ -416,11 +416,11 @@ bool Inventory::HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity } else if (InvItem->IsClassBag() && CanItemFitInContainer(ItemToTry, InvItem->GetItem())) { - int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); + int16 BaseSlotID = InventoryProfile::CalcSlotId(i, inventory::containerBegin); uint8 BagSize = InvItem->GetItem()->BagSlots; - for (uint8 BagSlot = EQEmu::inventory::containerBegin; BagSlotIsClassBag() && inst->GetItem()->BagSize >= min_size) { - if (inst->GetItem()->BagType == EQEmu::item::BagTypeQuiver && inst->GetItem()->ItemType != EQEmu::item::ItemTypeArrow) + if (inst->GetItem()->BagType == item::BagTypeQuiver && inst->GetItem()->ItemType != item::ItemTypeArrow) { continue; } - int16 base_slot_id = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); + int16 base_slot_id = InventoryProfile::CalcSlotId(i, inventory::containerBegin); uint8 slots = inst->GetItem()->BagSlots; uint8 j; - for (j = EQEmu::inventory::containerBegin; jIsClassBag()) { - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { + for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { if (!m_inv[free_slot]) return free_slot; } - return EQEmu::inventory::slotCursor; // return cursor since bags do not stack and will not fit inside other bags..yet...) + return inventory::slotCursor; // return cursor since bags do not stack and will not fit inside other bags..yet...) } // step 2: find partial room for stackables if (inst->IsStackable()) { - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + const ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst) continue; @@ -671,84 +671,84 @@ int16 Inventory::FindFreeSlotForTradeItem(const EQEmu::ItemInstance* inst) { return free_slot; } - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + const ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst) continue; if (main_inst->IsClassBag()) { // if item-specific containers already have bad items, we won't fix it here... - for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { - const EQEmu::ItemInstance* sub_inst = main_inst->GetItem(free_bag_slot); + for (uint8 free_bag_slot = inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { + const ItemInstance* sub_inst = main_inst->GetItem(free_bag_slot); if (!sub_inst) continue; if ((sub_inst->GetID() == inst->GetID()) && (sub_inst->GetCharges() < sub_inst->GetItem()->StackSize)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); + return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); } } } } // step 3a: find room for container-specific items (ItemClassArrow) - if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeArrow) { - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + if (inst->GetItem()->ItemType == item::ItemTypeArrow) { + for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + const ItemInstance* main_inst = m_inv[free_slot]; - if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeQuiver) || !main_inst->IsClassBag()) + if (!main_inst || (main_inst->GetItem()->BagType != item::BagTypeQuiver) || !main_inst->IsClassBag()) continue; - for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { + for (uint8 free_bag_slot = inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); + return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); } } } // step 3b: find room for container-specific items (ItemClassSmallThrowing) - if (inst->GetItem()->ItemType == EQEmu::item::ItemTypeSmallThrowing) { - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + if (inst->GetItem()->ItemType == item::ItemTypeSmallThrowing) { + for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + const ItemInstance* main_inst = m_inv[free_slot]; - if (!main_inst || (main_inst->GetItem()->BagType != EQEmu::item::BagTypeBandolier) || !main_inst->IsClassBag()) + if (!main_inst || (main_inst->GetItem()->BagType != item::BagTypeBandolier) || !main_inst->IsClassBag()) continue; - for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { + for (uint8 free_bag_slot = inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); + return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); } } } // step 4: just find an empty slot - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + const ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst) return free_slot; } - for (int16 free_slot = EQEmu::legacy::GENERAL_BEGIN; free_slot <= EQEmu::legacy::GENERAL_END; ++free_slot) { - const EQEmu::ItemInstance* main_inst = m_inv[free_slot]; + for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + const ItemInstance* main_inst = m_inv[free_slot]; if (main_inst && main_inst->IsClassBag()) { - if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeBandolier) || (main_inst->GetItem()->BagType == EQEmu::item::BagTypeQuiver)) + if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == item::BagTypeBandolier) || (main_inst->GetItem()->BagType == item::BagTypeQuiver)) continue; - for (uint8 free_bag_slot = EQEmu::inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EQEmu::inventory::ContainerCount); ++free_bag_slot) { + for (uint8 free_bag_slot = inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) - return Inventory::CalcSlotId(free_slot, free_bag_slot); + return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); } } } //return INVALID_INDEX; // everything else pushes to the cursor - return EQEmu::inventory::slotCursor; + return inventory::slotCursor; } // Opposite of below: Get parent bag slot_id from a slot inside of bag -int16 Inventory::CalcSlotId(int16 slot_id) { +int16 EQEmu::InventoryProfile::CalcSlotId(int16 slot_id) { int16 parent_slot_id = INVALID_INDEX; // this is not a bag range... using this risks over-writing existing items @@ -756,136 +756,136 @@ int16 Inventory::CalcSlotId(int16 slot_id) { // parent_slot_id = EmuConstants::BANK_BEGIN + (slot_id - EmuConstants::BANK_BEGIN) / EmuConstants::ITEM_CONTAINER_SIZE; //else if (slot_id >= 3100 && slot_id <= 3179) should be {3031..3110}..where did this range come from!!? (verified db save range) - if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { - parent_slot_id = EQEmu::legacy::GENERAL_BEGIN + (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; + if (slot_id >= legacy::GENERAL_BAGS_BEGIN && slot_id <= legacy::GENERAL_BAGS_END) { + parent_slot_id = legacy::GENERAL_BEGIN + (slot_id - legacy::GENERAL_BAGS_BEGIN) / inventory::ContainerCount; } - else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { - parent_slot_id = EQEmu::inventory::slotCursor; + else if (slot_id >= legacy::CURSOR_BAG_BEGIN && slot_id <= legacy::CURSOR_BAG_END) { + parent_slot_id = inventory::slotCursor; } - else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { - parent_slot_id = EQEmu::legacy::BANK_BEGIN + (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; + else if (slot_id >= legacy::BANK_BAGS_BEGIN && slot_id <= legacy::BANK_BAGS_END) { + parent_slot_id = legacy::BANK_BEGIN + (slot_id - legacy::BANK_BAGS_BEGIN) / inventory::ContainerCount; } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { - parent_slot_id = EQEmu::legacy::SHARED_BANK_BEGIN + (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; + else if (slot_id >= legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= legacy::SHARED_BANK_BAGS_END) { + parent_slot_id = legacy::SHARED_BANK_BEGIN + (slot_id - legacy::SHARED_BANK_BAGS_BEGIN) / inventory::ContainerCount; } - else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { - parent_slot_id = EQEmu::legacy::TRADE_BEGIN + (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) / EQEmu::inventory::ContainerCount; + else if (slot_id >= legacy::TRADE_BAGS_BEGIN && slot_id <= legacy::TRADE_BAGS_END) { + parent_slot_id = legacy::TRADE_BEGIN + (slot_id - legacy::TRADE_BAGS_BEGIN) / inventory::ContainerCount; } return parent_slot_id; } // Calculate slot_id for an item within a bag -int16 Inventory::CalcSlotId(int16 bagslot_id, uint8 bagidx) { - if (!Inventory::SupportsContainers(bagslot_id)) +int16 EQEmu::InventoryProfile::CalcSlotId(int16 bagslot_id, uint8 bagidx) { + if (!InventoryProfile::SupportsContainers(bagslot_id)) return INVALID_INDEX; int16 slot_id = INVALID_INDEX; - if (bagslot_id == EQEmu::inventory::slotCursor || bagslot_id == 8000) { - slot_id = EQEmu::legacy::CURSOR_BAG_BEGIN + bagidx; + if (bagslot_id == inventory::slotCursor || bagslot_id == 8000) { + slot_id = legacy::CURSOR_BAG_BEGIN + bagidx; } - else if (bagslot_id >= EQEmu::legacy::GENERAL_BEGIN && bagslot_id <= EQEmu::legacy::GENERAL_END) { - slot_id = EQEmu::legacy::GENERAL_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::GENERAL_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; + else if (bagslot_id >= legacy::GENERAL_BEGIN && bagslot_id <= legacy::GENERAL_END) { + slot_id = legacy::GENERAL_BAGS_BEGIN + (bagslot_id - legacy::GENERAL_BEGIN) * inventory::ContainerCount + bagidx; } - else if (bagslot_id >= EQEmu::legacy::BANK_BEGIN && bagslot_id <= EQEmu::legacy::BANK_END) { - slot_id = EQEmu::legacy::BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::BANK_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; + else if (bagslot_id >= legacy::BANK_BEGIN && bagslot_id <= legacy::BANK_END) { + slot_id = legacy::BANK_BAGS_BEGIN + (bagslot_id - legacy::BANK_BEGIN) * inventory::ContainerCount + bagidx; } - else if (bagslot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && bagslot_id <= EQEmu::legacy::SHARED_BANK_END) { - slot_id = EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; + else if (bagslot_id >= legacy::SHARED_BANK_BEGIN && bagslot_id <= legacy::SHARED_BANK_END) { + slot_id = legacy::SHARED_BANK_BAGS_BEGIN + (bagslot_id - legacy::SHARED_BANK_BEGIN) * inventory::ContainerCount + bagidx; } - else if (bagslot_id >= EQEmu::legacy::TRADE_BEGIN && bagslot_id <= EQEmu::legacy::TRADE_END) { - slot_id = EQEmu::legacy::TRADE_BAGS_BEGIN + (bagslot_id - EQEmu::legacy::TRADE_BEGIN) * EQEmu::inventory::ContainerCount + bagidx; + else if (bagslot_id >= legacy::TRADE_BEGIN && bagslot_id <= legacy::TRADE_END) { + slot_id = legacy::TRADE_BAGS_BEGIN + (bagslot_id - legacy::TRADE_BEGIN) * inventory::ContainerCount + bagidx; } return slot_id; } -uint8 Inventory::CalcBagIdx(int16 slot_id) { +uint8 EQEmu::InventoryProfile::CalcBagIdx(int16 slot_id) { uint8 index = 0; // this is not a bag range... using this risks over-writing existing items //else if (slot_id >= EmuConstants::BANK_BEGIN && slot_id <= EmuConstants::BANK_END) // index = (slot_id - EmuConstants::BANK_BEGIN) % EmuConstants::ITEM_CONTAINER_SIZE; - if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) { - index = (slot_id - EQEmu::legacy::GENERAL_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; + if (slot_id >= legacy::GENERAL_BAGS_BEGIN && slot_id <= legacy::GENERAL_BAGS_END) { + index = (slot_id - legacy::GENERAL_BAGS_BEGIN) % inventory::ContainerCount; } - else if (slot_id >= EQEmu::legacy::CURSOR_BAG_BEGIN && slot_id <= EQEmu::legacy::CURSOR_BAG_END) { - index = (slot_id - EQEmu::legacy::CURSOR_BAG_BEGIN); // % EQEmu::legacy::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots + else if (slot_id >= legacy::CURSOR_BAG_BEGIN && slot_id <= legacy::CURSOR_BAG_END) { + index = (slot_id - legacy::CURSOR_BAG_BEGIN); // % inventory::ContainerCount; - not needed since range is 10 slots } - else if (slot_id >= EQEmu::legacy::BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::BANK_BAGS_END) { - index = (slot_id - EQEmu::legacy::BANK_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; + else if (slot_id >= legacy::BANK_BAGS_BEGIN && slot_id <= legacy::BANK_BAGS_END) { + index = (slot_id - legacy::BANK_BAGS_BEGIN) % inventory::ContainerCount; } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_BAGS_END) { - index = (slot_id - EQEmu::legacy::SHARED_BANK_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; + else if (slot_id >= legacy::SHARED_BANK_BAGS_BEGIN && slot_id <= legacy::SHARED_BANK_BAGS_END) { + index = (slot_id - legacy::SHARED_BANK_BAGS_BEGIN) % inventory::ContainerCount; } - else if (slot_id >= EQEmu::legacy::TRADE_BAGS_BEGIN && slot_id <= EQEmu::legacy::TRADE_BAGS_END) { - index = (slot_id - EQEmu::legacy::TRADE_BAGS_BEGIN) % EQEmu::inventory::ContainerCount; + else if (slot_id >= legacy::TRADE_BAGS_BEGIN && slot_id <= legacy::TRADE_BAGS_END) { + index = (slot_id - legacy::TRADE_BAGS_BEGIN) % inventory::ContainerCount; } - else if (slot_id >= EQEmu::legacy::WORLD_BEGIN && slot_id <= EQEmu::legacy::WORLD_END) { - index = (slot_id - EQEmu::legacy::WORLD_BEGIN); // % EQEmu::legacy::ITEM_CONTAINER_SIZE; - not needed since range is 10 slots + else if (slot_id >= legacy::WORLD_BEGIN && slot_id <= legacy::WORLD_END) { + index = (slot_id - legacy::WORLD_BEGIN); // % inventory::ContainerCount; - not needed since range is 10 slots } return index; } -int16 Inventory::CalcSlotFromMaterial(uint8 material) +int16 EQEmu::InventoryProfile::CalcSlotFromMaterial(uint8 material) { switch (material) { - case EQEmu::textures::armorHead: - return EQEmu::inventory::slotHead; - case EQEmu::textures::armorChest: - return EQEmu::inventory::slotChest; - case EQEmu::textures::armorArms: - return EQEmu::inventory::slotArms; - case EQEmu::textures::armorWrist: - return EQEmu::inventory::slotWrist1; // there's 2 bracers, only one bracer material - case EQEmu::textures::armorHands: - return EQEmu::inventory::slotHands; - case EQEmu::textures::armorLegs: - return EQEmu::inventory::slotLegs; - case EQEmu::textures::armorFeet: - return EQEmu::inventory::slotFeet; - case EQEmu::textures::weaponPrimary: - return EQEmu::inventory::slotPrimary; - case EQEmu::textures::weaponSecondary: - return EQEmu::inventory::slotSecondary; + case textures::armorHead: + return inventory::slotHead; + case textures::armorChest: + return inventory::slotChest; + case textures::armorArms: + return inventory::slotArms; + case textures::armorWrist: + return inventory::slotWrist1; // there's 2 bracers, only one bracer material + case textures::armorHands: + return inventory::slotHands; + case textures::armorLegs: + return inventory::slotLegs; + case textures::armorFeet: + return inventory::slotFeet; + case textures::weaponPrimary: + return inventory::slotPrimary; + case textures::weaponSecondary: + return inventory::slotSecondary; default: return INVALID_INDEX; } } -uint8 Inventory::CalcMaterialFromSlot(int16 equipslot) +uint8 EQEmu::InventoryProfile::CalcMaterialFromSlot(int16 equipslot) { switch (equipslot) { - case EQEmu::inventory::slotHead: - return EQEmu::textures::armorHead; - case EQEmu::inventory::slotChest: - return EQEmu::textures::armorChest; - case EQEmu::inventory::slotArms: - return EQEmu::textures::armorArms; - case EQEmu::inventory::slotWrist1: + case inventory::slotHead: + return textures::armorHead; + case inventory::slotChest: + return textures::armorChest; + case inventory::slotArms: + return textures::armorArms; + case inventory::slotWrist1: //case SLOT_BRACER02: // non-live behavior - return EQEmu::textures::armorWrist; - case EQEmu::inventory::slotHands: - return EQEmu::textures::armorHands; - case EQEmu::inventory::slotLegs: - return EQEmu::textures::armorLegs; - case EQEmu::inventory::slotFeet: - return EQEmu::textures::armorFeet; - case EQEmu::inventory::slotPrimary: - return EQEmu::textures::weaponPrimary; - case EQEmu::inventory::slotSecondary: - return EQEmu::textures::weaponSecondary; + return textures::armorWrist; + case inventory::slotHands: + return textures::armorHands; + case inventory::slotLegs: + return textures::armorLegs; + case inventory::slotFeet: + return textures::armorFeet; + case inventory::slotPrimary: + return textures::weaponPrimary; + case inventory::slotSecondary: + return textures::weaponSecondary; default: - return EQEmu::textures::materialInvalid; + return textures::materialInvalid; } } -bool Inventory::CanItemFitInContainer(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container) { +bool EQEmu::InventoryProfile::CanItemFitInContainer(const ItemData *ItemToTry, const ItemData *Container) { if (!ItemToTry || !Container) return false; @@ -893,47 +893,47 @@ bool Inventory::CanItemFitInContainer(const EQEmu::ItemData *ItemToTry, const EQ if (ItemToTry->Size > Container->BagSize) return false; - if ((Container->BagType == EQEmu::item::BagTypeQuiver) && (ItemToTry->ItemType != EQEmu::item::ItemTypeArrow)) + if ((Container->BagType == item::BagTypeQuiver) && (ItemToTry->ItemType != item::ItemTypeArrow)) return false; - if ((Container->BagType == EQEmu::item::BagTypeBandolier) && (ItemToTry->ItemType != EQEmu::item::ItemTypeSmallThrowing)) + if ((Container->BagType == item::BagTypeBandolier) && (ItemToTry->ItemType != item::ItemTypeSmallThrowing)) return false; return true; } -bool Inventory::SupportsClickCasting(int16 slot_id) +bool EQEmu::InventoryProfile::SupportsClickCasting(int16 slot_id) { // there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range - if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::inventory::slotPowerSource) + if ((uint16)slot_id <= legacy::GENERAL_END || slot_id == inventory::slotPowerSource) { return true; } - else if (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END) + else if (slot_id >= legacy::GENERAL_BAGS_BEGIN && slot_id <= legacy::GENERAL_BAGS_END) { - if (EQEmu::inventory::Lookup(m_inventory_version)->AllowClickCastFromBag) + if (inventory::Lookup(m_inventory_version)->AllowClickCastFromBag) return true; } return false; } -bool Inventory::SupportsPotionBeltCasting(int16 slot_id) +bool EQEmu::InventoryProfile::SupportsPotionBeltCasting(int16 slot_id) { - if ((uint16)slot_id <= EQEmu::legacy::GENERAL_END || slot_id == EQEmu::inventory::slotPowerSource || (slot_id >= EQEmu::legacy::GENERAL_BAGS_BEGIN && slot_id <= EQEmu::legacy::GENERAL_BAGS_END)) + if ((uint16)slot_id <= legacy::GENERAL_END || slot_id == inventory::slotPowerSource || (slot_id >= legacy::GENERAL_BAGS_BEGIN && slot_id <= legacy::GENERAL_BAGS_END)) return true; return false; } // Test whether a given slot can support a container item -bool Inventory::SupportsContainers(int16 slot_id) +bool EQEmu::InventoryProfile::SupportsContainers(int16 slot_id) { - if ((slot_id == EQEmu::inventory::slotCursor) || - (slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END) || - (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) || - (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) || - (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) + if ((slot_id == inventory::slotCursor) || + (slot_id >= legacy::GENERAL_BEGIN && slot_id <= legacy::GENERAL_END) || + (slot_id >= legacy::BANK_BEGIN && slot_id <= legacy::BANK_END) || + (slot_id >= legacy::SHARED_BANK_BEGIN && slot_id <= legacy::SHARED_BANK_END) || + (slot_id >= legacy::TRADE_BEGIN && slot_id <= legacy::TRADE_END) ) { return true; } @@ -941,7 +941,7 @@ bool Inventory::SupportsContainers(int16 slot_id) return false; } -int Inventory::GetSlotByItemInst(EQEmu::ItemInstance *inst) { +int EQEmu::InventoryProfile::GetSlotByItemInst(ItemInstance *inst) { if (!inst) return INVALID_INDEX; @@ -971,32 +971,32 @@ int Inventory::GetSlotByItemInst(EQEmu::ItemInstance *inst) { } if (m_cursor.peek_front() == inst) { - return EQEmu::inventory::slotCursor; + return inventory::slotCursor; } return INVALID_INDEX; } -uint8 Inventory::FindBrightestLightType() +uint8 EQEmu::InventoryProfile::FindBrightestLightType() { uint8 brightest_light_type = 0; for (auto iter = m_worn.begin(); iter != m_worn.end(); ++iter) { - if ((iter->first < EQEmu::legacy::EQUIPMENT_BEGIN || iter->first > EQEmu::legacy::EQUIPMENT_END) && iter->first != EQEmu::inventory::slotPowerSource) { continue; } - if (iter->first == EQEmu::inventory::slotAmmo) { continue; } + if ((iter->first < legacy::EQUIPMENT_BEGIN || iter->first > legacy::EQUIPMENT_END) && iter->first != inventory::slotPowerSource) { continue; } + if (iter->first == inventory::slotAmmo) { continue; } auto inst = iter->second; if (inst == nullptr) { continue; } auto item = inst->GetItem(); if (item == nullptr) { continue; } - if (EQEmu::lightsource::IsLevelGreater(item->Light, brightest_light_type)) + if (lightsource::IsLevelGreater(item->Light, brightest_light_type)) brightest_light_type = item->Light; } uint8 general_light_type = 0; for (auto iter = m_inv.begin(); iter != m_inv.end(); ++iter) { - if (iter->first < EQEmu::legacy::GENERAL_BEGIN || iter->first > EQEmu::legacy::GENERAL_END) { continue; } + if (iter->first < legacy::GENERAL_BEGIN || iter->first > legacy::GENERAL_END) { continue; } auto inst = iter->second; if (inst == nullptr) { continue; } @@ -1006,17 +1006,17 @@ uint8 Inventory::FindBrightestLightType() if (!item->IsClassCommon()) { continue; } if (item->Light < 9 || item->Light > 13) { continue; } - if (EQEmu::lightsource::TypeToLevel(item->Light)) + if (lightsource::TypeToLevel(item->Light)) general_light_type = item->Light; } - if (EQEmu::lightsource::IsLevelGreater(general_light_type, brightest_light_type)) + if (lightsource::IsLevelGreater(general_light_type, brightest_light_type)) brightest_light_type = general_light_type; return brightest_light_type; } -void Inventory::dumpEntireInventory() { +void EQEmu::InventoryProfile::dumpEntireInventory() { dumpWornItems(); dumpInventory(); @@ -1026,31 +1026,31 @@ void Inventory::dumpEntireInventory() { std::cout << std::endl; } -void Inventory::dumpWornItems() { +void EQEmu::InventoryProfile::dumpWornItems() { std::cout << "Worn items:" << std::endl; dumpItemCollection(m_worn); } -void Inventory::dumpInventory() { +void EQEmu::InventoryProfile::dumpInventory() { std::cout << "Inventory items:" << std::endl; dumpItemCollection(m_inv); } -void Inventory::dumpBankItems() { +void EQEmu::InventoryProfile::dumpBankItems() { std::cout << "Bank items:" << std::endl; dumpItemCollection(m_bank); } -void Inventory::dumpSharedBankItems() { +void EQEmu::InventoryProfile::dumpSharedBankItems() { std::cout << "Shared Bank items:" << std::endl; dumpItemCollection(m_shbank); } -int Inventory::GetSlotByItemInstCollection(const std::map &collection, EQEmu::ItemInstance *inst) { +int EQEmu::InventoryProfile::GetSlotByItemInstCollection(const std::map &collection, ItemInstance *inst) { for (auto iter = collection.begin(); iter != collection.end(); ++iter) { - EQEmu::ItemInstance *t_inst = iter->second; + ItemInstance *t_inst = iter->second; if (t_inst == inst) { return iter->first; } @@ -1058,7 +1058,7 @@ int Inventory::GetSlotByItemInstCollection(const std::mapIsClassBag()) { for (auto b_iter = t_inst->_cbegin(); b_iter != t_inst->_cend(); ++b_iter) { if (b_iter->second == inst) { - return Inventory::CalcSlotId(iter->first, b_iter->first); + return InventoryProfile::CalcSlotId(iter->first, b_iter->first); } } } @@ -1067,7 +1067,7 @@ int Inventory::GetSlotByItemInstCollection(const std::map &collection) +void EQEmu::InventoryProfile::dumpItemCollection(const std::map &collection) { for (auto it = collection.cbegin(); it != collection.cend(); ++it) { auto inst = it->second; @@ -1081,18 +1081,18 @@ void Inventory::dumpItemCollection(const std::map & } } -void Inventory::dumpBagContents(EQEmu::ItemInstance *inst, std::map::const_iterator *it) +void EQEmu::InventoryProfile::dumpBagContents(ItemInstance *inst, std::map::const_iterator *it) { if (!inst || !inst->IsClassBag()) return; // Go through bag, if bag for (auto itb = inst->_cbegin(); itb != inst->_cend(); ++itb) { - EQEmu::ItemInstance* baginst = itb->second; + ItemInstance* baginst = itb->second; if (!baginst || !baginst->GetItem()) continue; - std::string subSlot = StringFormat(" Slot %d: %s (%d)", Inventory::CalcSlotId((*it)->first, itb->first), + std::string subSlot = StringFormat(" Slot %d: %s (%d)", InventoryProfile::CalcSlotId((*it)->first, itb->first), baginst->GetItem()->Name, (baginst->GetCharges() <= 0) ? 1 : baginst->GetCharges()); std::cout << subSlot << std::endl; } @@ -1100,7 +1100,7 @@ void Inventory::dumpBagContents(EQEmu::ItemInstance *inst, std::map& bucket, int16 slot_id) const +EQEmu::ItemInstance* EQEmu::InventoryProfile::_GetItem(const std::map& bucket, int16 slot_id) const { auto it = bucket.find(slot_id); if (it != bucket.end()) { @@ -1113,7 +1113,7 @@ EQEmu::ItemInstance* Inventory::_GetItem(const std::map= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || (slot_id == EQEmu::inventory::slotPowerSource)) { + else if ((slot_id >= legacy::EQUIPMENT_BEGIN && slot_id <= legacy::EQUIPMENT_END) || (slot_id == inventory::slotPowerSource)) { m_worn[slot_id] = inst; result = slot_id; } - else if ((slot_id >= EQEmu::legacy::GENERAL_BEGIN && slot_id <= EQEmu::legacy::GENERAL_END)) { + else if ((slot_id >= legacy::GENERAL_BEGIN && slot_id <= legacy::GENERAL_END)) { m_inv[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::legacy::TRIBUTE_BEGIN && slot_id <= EQEmu::legacy::TRIBUTE_END) { + else if (slot_id >= legacy::TRIBUTE_BEGIN && slot_id <= legacy::TRIBUTE_END) { m_worn[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::legacy::BANK_BEGIN && slot_id <= EQEmu::legacy::BANK_END) { + else if (slot_id >= legacy::BANK_BEGIN && slot_id <= legacy::BANK_END) { m_bank[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id <= EQEmu::legacy::SHARED_BANK_END) { + else if (slot_id >= legacy::SHARED_BANK_BEGIN && slot_id <= legacy::SHARED_BANK_END) { m_shbank[slot_id] = inst; result = slot_id; } - else if (slot_id >= EQEmu::legacy::TRADE_BEGIN && slot_id <= EQEmu::legacy::TRADE_END) { + else if (slot_id >= legacy::TRADE_BEGIN && slot_id <= legacy::TRADE_END) { m_trade[slot_id] = inst; result = slot_id; } else { // Slot must be within a bag - parentSlot = Inventory::CalcSlotId(slot_id); - EQEmu::ItemInstance* baginst = GetItem(parentSlot); // Get parent bag + parentSlot = InventoryProfile::CalcSlotId(slot_id); + ItemInstance* baginst = GetItem(parentSlot); // Get parent bag if (baginst && baginst->IsClassBag()) { - baginst->_PutItem(Inventory::CalcBagIdx(slot_id), inst); + baginst->_PutItem(InventoryProfile::CalcBagIdx(slot_id), inst); result = slot_id; } } if (result == INVALID_INDEX) { - Log.Out(Logs::General, Logs::Error, "Inventory::_PutItem: Invalid slot_id specified (%i) with parent slot id (%i)", slot_id, parentSlot); - Inventory::MarkDirty(inst); // Slot not found, clean up + Log.Out(Logs::General, Logs::Error, "InventoryProfile::_PutItem: Invalid slot_id specified (%i) with parent slot id (%i)", slot_id, parentSlot); + InventoryProfile::MarkDirty(inst); // Slot not found, clean up } return result; } // Internal Method: Checks an inventory bucket for a particular item -int16 Inventory::_HasItem(std::map& bucket, uint32 item_id, uint8 quantity) +int16 EQEmu::InventoryProfile::_HasItem(std::map& bucket, uint32 item_id, uint8 quantity) { uint32 quantity_found = 0; @@ -1191,9 +1191,9 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 return iter->first; } - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + for (int index = inventory::socketBegin; index < inventory::SocketCount; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::legacy::SLOT_AUGMENT; + return legacy::SLOT_AUGMENT; } if (!inst->IsClassBag()) { continue; } @@ -1205,12 +1205,12 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 if (bag_inst->GetID() == item_id) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(iter->first, bag_iter->first); + return InventoryProfile::CalcSlotId(iter->first, bag_iter->first); } - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + for (int index = inventory::socketBegin; index < inventory::SocketCount; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::legacy::SLOT_AUGMENT; + return legacy::SLOT_AUGMENT; } } } @@ -1219,7 +1219,7 @@ int16 Inventory::_HasItem(std::map& bucket, uint32 } // Internal Method: Checks an inventory queue type bucket for a particular item -int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) +int16 EQEmu::InventoryProfile::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) { // The downfall of this (these) queue procedure is that callers presume that when an item is // found, it is presented as being available on the cursor. In cases of a parity check, this @@ -1236,12 +1236,12 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) if (inst->GetID() == item_id) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); if (quantity_found >= quantity) - return EQEmu::inventory::slotCursor; + return inventory::slotCursor; } - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + for (int index = inventory::socketBegin; index < inventory::SocketCount; ++index) { if (inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::legacy::SLOT_AUGMENT; + return legacy::SLOT_AUGMENT; } if (!inst->IsClassBag()) { continue; } @@ -1253,12 +1253,12 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) if (bag_inst->GetID() == item_id) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); + return InventoryProfile::CalcSlotId(inventory::slotCursor, bag_iter->first); } - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + for (int index = inventory::socketBegin; index < inventory::SocketCount; ++index) { if (bag_inst->GetAugmentItemID(index) == item_id && quantity <= 1) - return EQEmu::legacy::SLOT_AUGMENT; + return legacy::SLOT_AUGMENT; } } @@ -1270,7 +1270,7 @@ int16 Inventory::_HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity) } // Internal Method: Checks an inventory bucket for a particular item -int16 Inventory::_HasItemByUse(std::map& bucket, uint8 use, uint8 quantity) +int16 EQEmu::InventoryProfile::_HasItemByUse(std::map& bucket, uint8 use, uint8 quantity) { uint32 quantity_found = 0; @@ -1293,7 +1293,7 @@ int16 Inventory::_HasItemByUse(std::map& bucket, ui if (bag_inst->IsClassCommon() && bag_inst->GetItem()->ItemType == use) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(iter->first, bag_iter->first); + return InventoryProfile::CalcSlotId(iter->first, bag_iter->first); } } } @@ -1302,7 +1302,7 @@ int16 Inventory::_HasItemByUse(std::map& bucket, ui } // Internal Method: Checks an inventory queue type bucket for a particular item -int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) +int16 EQEmu::InventoryProfile::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) { uint32 quantity_found = 0; @@ -1313,7 +1313,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) if (inst->IsClassCommon() && inst->GetItem()->ItemType == use) { quantity_found += (inst->GetCharges() <= 0) ? 1 : inst->GetCharges(); if (quantity_found >= quantity) - return EQEmu::inventory::slotCursor; + return inventory::slotCursor; } if (!inst->IsClassBag()) { continue; } @@ -1325,7 +1325,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) if (bag_inst->IsClassCommon() && bag_inst->GetItem()->ItemType == use) { quantity_found += (bag_inst->GetCharges() <= 0) ? 1 : bag_inst->GetCharges(); if (quantity_found >= quantity) - return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); + return InventoryProfile::CalcSlotId(inventory::slotCursor, bag_iter->first); } } @@ -1336,7 +1336,7 @@ int16 Inventory::_HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity) return INVALID_INDEX; } -int16 Inventory::_HasItemByLoreGroup(std::map& bucket, uint32 loregroup) +int16 EQEmu::InventoryProfile::_HasItemByLoreGroup(std::map& bucket, uint32 loregroup) { for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) { auto inst = iter->second; @@ -1345,12 +1345,12 @@ int16 Inventory::_HasItemByLoreGroup(std::map& buck if (inst->GetItem()->LoreGroup == loregroup) return iter->first; - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + for (int index = inventory::socketBegin; index < inventory::SocketCount; ++index) { auto aug_inst = inst->GetAugment(index); if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::legacy::SLOT_AUGMENT; + return legacy::SLOT_AUGMENT; } if (!inst->IsClassBag()) { continue; } @@ -1360,14 +1360,14 @@ int16 Inventory::_HasItemByLoreGroup(std::map& buck if (bag_inst == nullptr) { continue; } if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) - return Inventory::CalcSlotId(iter->first, bag_iter->first); + return InventoryProfile::CalcSlotId(iter->first, bag_iter->first); - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + for (int index = inventory::socketBegin; index < inventory::SocketCount; ++index) { auto aug_inst = bag_inst->GetAugment(index); if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::legacy::SLOT_AUGMENT; + return legacy::SLOT_AUGMENT; } } } @@ -1376,21 +1376,21 @@ int16 Inventory::_HasItemByLoreGroup(std::map& buck } // Internal Method: Checks an inventory queue type bucket for a particular item -int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) +int16 EQEmu::InventoryProfile::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) { for (auto iter = iqueue.cbegin(); iter != iqueue.cend(); ++iter) { auto inst = *iter; if (inst == nullptr) { continue; } if (inst->GetItem()->LoreGroup == loregroup) - return EQEmu::inventory::slotCursor; + return inventory::slotCursor; - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + for (int index = inventory::socketBegin; index < inventory::SocketCount; ++index) { auto aug_inst = inst->GetAugment(index); if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::legacy::SLOT_AUGMENT; + return legacy::SLOT_AUGMENT; } if (!inst->IsClassBag()) { continue; } @@ -1400,14 +1400,14 @@ int16 Inventory::_HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup) if (bag_inst == nullptr) { continue; } if (bag_inst->IsClassCommon() && bag_inst->GetItem()->LoreGroup == loregroup) - return Inventory::CalcSlotId(EQEmu::inventory::slotCursor, bag_iter->first); + return InventoryProfile::CalcSlotId(inventory::slotCursor, bag_iter->first); - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + for (int index = inventory::socketBegin; index < inventory::SocketCount; ++index) { auto aug_inst = bag_inst->GetAugment(index); if (aug_inst == nullptr) { continue; } if (aug_inst->GetItem()->LoreGroup == loregroup) - return EQEmu::legacy::SLOT_AUGMENT; + return legacy::SLOT_AUGMENT; } } diff --git a/common/inventory_profile.h b/common/inventory_profile.h index 3903f9812..0f90fdea2 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -73,156 +73,159 @@ protected: }; // ######################################## -// Class: Inventory +// Class: EQEmu::InventoryProfile // Character inventory -class Inventory +namespace EQEmu { - friend class EQEmu::ItemInstance; -public: - /////////////////////////////// - // Public Methods - /////////////////////////////// - - Inventory() { m_inventory_version = EQEmu::versions::InventoryVersion::Unknown; m_inventory_version_set = false; } - ~Inventory(); + class InventoryProfile + { + friend class ItemInstance; + public: + /////////////////////////////// + // Public Methods + /////////////////////////////// - // inv2 creep - bool SetInventoryVersion(EQEmu::versions::InventoryVersion inventory_version) { - if (!m_inventory_version_set) { - m_inventory_version = EQEmu::versions::ValidateInventoryVersion(inventory_version); - return (m_inventory_version_set = true); + InventoryProfile() { m_inventory_version = versions::InventoryVersion::Unknown; m_inventory_version_set = false; } + ~InventoryProfile(); + + // inv2 creep + bool SetInventoryVersion(versions::InventoryVersion inventory_version) { + if (!m_inventory_version_set) { + m_inventory_version = versions::ValidateInventoryVersion(inventory_version); + return (m_inventory_version_set = true); + } + else { + return false; + } } - else { - return false; - } - } - bool SetInventoryVersion(EQEmu::versions::ClientVersion client_version) { return SetInventoryVersion(EQEmu::versions::ConvertClientVersionToInventoryVersion(client_version)); } + bool SetInventoryVersion(versions::ClientVersion client_version) { return SetInventoryVersion(versions::ConvertClientVersionToInventoryVersion(client_version)); } - EQEmu::versions::InventoryVersion InventoryVersion() { return m_inventory_version; } + versions::InventoryVersion InventoryVersion() { return m_inventory_version; } - static void CleanDirty(); - static void MarkDirty(EQEmu::ItemInstance *inst); + static void CleanDirty(); + static void MarkDirty(ItemInstance *inst); - // Retrieve a writeable item at specified slot - EQEmu::ItemInstance* GetItem(int16 slot_id) const; - EQEmu::ItemInstance* GetItem(int16 slot_id, uint8 bagidx) const; + // Retrieve a writeable item at specified slot + ItemInstance* GetItem(int16 slot_id) const; + ItemInstance* GetItem(int16 slot_id, uint8 bagidx) const; - inline std::list::const_iterator cursor_cbegin() { return m_cursor.cbegin(); } - inline std::list::const_iterator cursor_cend() { return m_cursor.cend(); } + inline std::list::const_iterator cursor_cbegin() { return m_cursor.cbegin(); } + inline std::list::const_iterator cursor_cend() { return m_cursor.cend(); } - inline int CursorSize() { return m_cursor.size(); } - inline bool CursorEmpty() { return m_cursor.empty(); } + inline int CursorSize() { return m_cursor.size(); } + inline bool CursorEmpty() { return m_cursor.empty(); } - // Retrieve a read-only item from inventory - inline const EQEmu::ItemInstance* operator[](int16 slot_id) const { return GetItem(slot_id); } + // Retrieve a read-only item from inventory + inline const ItemInstance* operator[](int16 slot_id) const { return GetItem(slot_id); } - // Add item to inventory - int16 PutItem(int16 slot_id, const EQEmu::ItemInstance& inst); + // Add item to inventory + int16 PutItem(int16 slot_id, const ItemInstance& inst); - // Add item to cursor queue - int16 PushCursor(const EQEmu::ItemInstance& inst); + // Add item to cursor queue + int16 PushCursor(const ItemInstance& inst); - // Get cursor item in front of queue - EQEmu::ItemInstance* GetCursorItem(); + // Get cursor item in front of queue + ItemInstance* GetCursorItem(); - // Swap items in inventory - bool SwapItem(int16 slot_a, int16 slot_b); + // Swap items in inventory + bool SwapItem(int16 slot_a, int16 slot_b); - // Remove item from inventory - bool DeleteItem(int16 slot_id, uint8 quantity=0); + // Remove item from inventory + bool DeleteItem(int16 slot_id, uint8 quantity = 0); - // Checks All items in a bag for No Drop - bool CheckNoDrop(int16 slot_id); + // Checks All items in a bag for No Drop + bool CheckNoDrop(int16 slot_id); - // Remove item from inventory (and take control of memory) - EQEmu::ItemInstance* PopItem(int16 slot_id); + // Remove item from inventory (and take control of memory) + ItemInstance* PopItem(int16 slot_id); - // Check whether there is space for the specified number of the specified item. - bool HasSpaceForItem(const EQEmu::ItemData *ItemToTry, int16 Quantity); + // Check whether there is space for the specified number of the specified item. + bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity); - // Check whether item exists in inventory - // where argument specifies OR'd list of invWhere constants to look - int16 HasItem(uint32 item_id, uint8 quantity = 0, uint8 where = 0xFF); + // Check whether item exists in inventory + // where argument specifies OR'd list of invWhere constants to look + int16 HasItem(uint32 item_id, uint8 quantity = 0, uint8 where = 0xFF); - // Check whether item exists in inventory - // where argument specifies OR'd list of invWhere constants to look - int16 HasItemByUse(uint8 use, uint8 quantity=0, uint8 where=0xFF); + // Check whether item exists in inventory + // where argument specifies OR'd list of invWhere constants to look + int16 HasItemByUse(uint8 use, uint8 quantity = 0, uint8 where = 0xFF); - // Check whether item exists in inventory - // where argument specifies OR'd list of invWhere constants to look - int16 HasItemByLoreGroup(uint32 loregroup, uint8 where=0xFF); + // Check whether item exists in inventory + // where argument specifies OR'd list of invWhere constants to look + int16 HasItemByLoreGroup(uint32 loregroup, uint8 where = 0xFF); - // Locate an available inventory slot - int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false); - int16 FindFreeSlotForTradeItem(const EQEmu::ItemInstance* inst); + // Locate an available inventory slot + int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false); + int16 FindFreeSlotForTradeItem(const ItemInstance* inst); - // Calculate slot_id for an item within a bag - static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id - static int16 CalcSlotId(int16 bagslot_id, uint8 bagidx); // Calc slot_id for item inside bag - static uint8 CalcBagIdx(int16 slot_id); // Calc bagidx for slot_id - static int16 CalcSlotFromMaterial(uint8 material); - static uint8 CalcMaterialFromSlot(int16 equipslot); + // Calculate slot_id for an item within a bag + static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id + static int16 CalcSlotId(int16 bagslot_id, uint8 bagidx); // Calc slot_id for item inside bag + static uint8 CalcBagIdx(int16 slot_id); // Calc bagidx for slot_id + static int16 CalcSlotFromMaterial(uint8 material); + static uint8 CalcMaterialFromSlot(int16 equipslot); - static bool CanItemFitInContainer(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container); + static bool CanItemFitInContainer(const ItemData *ItemToTry, const ItemData *Container); - // Test for valid inventory casting slot - bool SupportsClickCasting(int16 slot_id); - bool SupportsPotionBeltCasting(int16 slot_id); + // Test for valid inventory casting slot + bool SupportsClickCasting(int16 slot_id); + bool SupportsPotionBeltCasting(int16 slot_id); - // Test whether a given slot can support a container item - static bool SupportsContainers(int16 slot_id); + // Test whether a given slot can support a container item + static bool SupportsContainers(int16 slot_id); - int GetSlotByItemInst(EQEmu::ItemInstance *inst); + int GetSlotByItemInst(ItemInstance *inst); - uint8 FindBrightestLightType(); + uint8 FindBrightestLightType(); - void dumpEntireInventory(); - void dumpWornItems(); - void dumpInventory(); - void dumpBankItems(); - void dumpSharedBankItems(); + void dumpEntireInventory(); + void dumpWornItems(); + void dumpInventory(); + void dumpBankItems(); + void dumpSharedBankItems(); - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value); - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value); - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value); - void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value); - std::string GetCustomItemData(int16 slot_id, std::string identifier); -protected: - /////////////////////////////// - // Protected Methods - /////////////////////////////// + void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value); + void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value); + void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value); + void SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value); + std::string GetCustomItemData(int16 slot_id, std::string identifier); + protected: + /////////////////////////////// + // Protected Methods + /////////////////////////////// - int GetSlotByItemInstCollection(const std::map &collection, EQEmu::ItemInstance *inst); - void dumpItemCollection(const std::map &collection); - void dumpBagContents(EQEmu::ItemInstance *inst, std::map::const_iterator *it); + int GetSlotByItemInstCollection(const std::map &collection, ItemInstance *inst); + void dumpItemCollection(const std::map &collection); + void dumpBagContents(ItemInstance *inst, std::map::const_iterator *it); - // Retrieves item within an inventory bucket - EQEmu::ItemInstance* _GetItem(const std::map& bucket, int16 slot_id) const; + // Retrieves item within an inventory bucket + ItemInstance* _GetItem(const std::map& bucket, int16 slot_id) const; - // Private "put" item into bucket, without regard for what is currently in bucket - int16 _PutItem(int16 slot_id, EQEmu::ItemInstance* inst); + // Private "put" item into bucket, without regard for what is currently in bucket + int16 _PutItem(int16 slot_id, ItemInstance* inst); - // Checks an inventory bucket for a particular item - int16 _HasItem(std::map& bucket, uint32 item_id, uint8 quantity); - int16 _HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity); - int16 _HasItemByUse(std::map& bucket, uint8 use, uint8 quantity); - int16 _HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity); - int16 _HasItemByLoreGroup(std::map& bucket, uint32 loregroup); - int16 _HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup); + // Checks an inventory bucket for a particular item + int16 _HasItem(std::map& bucket, uint32 item_id, uint8 quantity); + int16 _HasItem(ItemInstQueue& iqueue, uint32 item_id, uint8 quantity); + int16 _HasItemByUse(std::map& bucket, uint8 use, uint8 quantity); + int16 _HasItemByUse(ItemInstQueue& iqueue, uint8 use, uint8 quantity); + int16 _HasItemByLoreGroup(std::map& bucket, uint32 loregroup); + int16 _HasItemByLoreGroup(ItemInstQueue& iqueue, uint32 loregroup); - // Player inventory - std::map m_worn; // Items worn by character - std::map m_inv; // Items in character personal inventory - std::map m_bank; // Items in character bank - std::map m_shbank; // Items in character shared bank - std::map m_trade; // Items in a trade session - ItemInstQueue m_cursor; // Items on cursor: FIFO + // Player inventory + std::map m_worn; // Items worn by character + std::map m_inv; // Items in character personal inventory + std::map m_bank; // Items in character bank + std::map m_shbank; // Items in character shared bank + std::map m_trade; // Items in a trade session + ::ItemInstQueue m_cursor; // Items on cursor: FIFO -private: - // Active inventory version - EQEmu::versions::InventoryVersion m_inventory_version; - bool m_inventory_version_set; -}; + private: + // Active inventory version + versions::InventoryVersion m_inventory_version; + bool m_inventory_version_set; + }; +} #endif /*COMMON_INVENTORY_PROFILE_H*/ diff --git a/common/item_instance.cpp b/common/item_instance.cpp index de01c0893..61b9d3243 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -207,12 +207,12 @@ EQEmu::ItemInstance::~ItemInstance() } // Query item type -bool EQEmu::ItemInstance::IsType(EQEmu::item::ItemClass item_class) const +bool EQEmu::ItemInstance::IsType(item::ItemClass item_class) const { // IsType() does not protect against 'm_item = nullptr' // Check usage type - if ((m_use_type == ItemInstWorldContainer) && (item_class == EQEmu::item::ItemClassBag)) + if ((m_use_type == ItemInstWorldContainer) && (item_class == item::ItemClassBag)) return true; if (!m_item) @@ -273,8 +273,8 @@ bool EQEmu::ItemInstance::IsEquipable(int16 slot_id) const // another "shouldn't do" fix..will be fixed in future updates (requires code and database work) int16 use_slot = INVALID_INDEX; - if (slot_id == EQEmu::inventory::slotPowerSource) { use_slot = EQEmu::inventory::slotGeneral1; } - if ((uint16)slot_id <= EQEmu::legacy::EQUIPMENT_END) { use_slot = slot_id; } + if (slot_id == inventory::slotPowerSource) { use_slot = inventory::slotGeneral1; } + if ((uint16)slot_id <= legacy::EQUIPMENT_END) { use_slot = slot_id; } if (use_slot != INVALID_INDEX) { if (m_item->Slots & (1 << use_slot)) @@ -289,7 +289,7 @@ bool EQEmu::ItemInstance::IsAugmentable() const if (!m_item) return false; - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + for (int index = inventory::socketBegin; index < inventory::SocketCount; ++index) { if (m_item->AugSlotType[index] != 0) return true; } @@ -303,8 +303,8 @@ bool EQEmu::ItemInstance::AvailableWearSlot(uint32 aug_wear_slots) const { if (!m_item || !m_item->IsClassCommon()) return false; - int index = EQEmu::legacy::EQUIPMENT_BEGIN; - for (; index <= EQEmu::inventory::slotGeneral1; ++index) { // MainGeneral1 should be EQEmu::legacy::EQUIPMENT_END + int index = legacy::EQUIPMENT_BEGIN; + for (; index <= inventory::slotGeneral1; ++index) { // MainGeneral1 should be legacy::EQUIPMENT_END if (m_item->Slots & (1 << index)) { if (aug_wear_slots & (1 << index)) break; @@ -319,14 +319,14 @@ int8 EQEmu::ItemInstance::AvailableAugmentSlot(int32 augtype) const if (!m_item || !m_item->IsClassCommon()) return INVALID_INDEX; - int index = EQEmu::inventory::socketBegin; - for (; index < EQEmu::inventory::SocketCount; ++index) { + int index = inventory::socketBegin; + for (; index < inventory::SocketCount; ++index) { if (GetItem(index)) { continue; } if (augtype == -1 || (m_item->AugSlotType[index] && ((1 << (m_item->AugSlotType[index] - 1)) & augtype))) break; } - return (index < EQEmu::inventory::SocketCount) ? index : INVALID_INDEX; + return (index < inventory::SocketCount) ? index : INVALID_INDEX; } bool EQEmu::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const @@ -416,7 +416,7 @@ void EQEmu::ItemInstance::ClearByFlags(byFlagSetting is_nodrop, byFlagSetting is continue; } - const EQEmu::ItemData* item = inst->GetItem(); + const ItemData* item = inst->GetItem(); if (item == nullptr) { cur = m_contents.erase(cur); continue; @@ -469,7 +469,7 @@ uint8 EQEmu::ItemInstance::FirstOpenSlot() const return INVALID_INDEX; uint8 slots = m_item->BagSlots, i; - for (i = EQEmu::inventory::containerBegin; i < slots; i++) { + for (i = inventory::containerBegin; i < slots; i++) { if (!GetItem(i)) break; } @@ -486,7 +486,7 @@ uint8 EQEmu::ItemInstance::GetTotalItemCount() const if (m_item && !m_item->IsClassBag()) { return item_count; } - for (int index = EQEmu::inventory::containerBegin; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } } + for (int index = inventory::containerBegin; index < m_item->BagSlots; ++index) { if (GetItem(index)) { ++item_count; } } return item_count; } @@ -496,7 +496,7 @@ bool EQEmu::ItemInstance::IsNoneEmptyContainer() if (!m_item || !m_item->IsClassBag()) return false; - for (int index = EQEmu::inventory::containerBegin; index < m_item->BagSlots; ++index) { + for (int index = inventory::containerBegin; index < m_item->BagSlots; ++index) { if (GetItem(index)) return true; } @@ -518,7 +518,7 @@ EQEmu::ItemInstance* EQEmu::ItemInstance::GetOrnamentationAug(int32 ornamentatio if (!m_item || !m_item->IsClassCommon()) { return nullptr; } if (ornamentationAugtype == 0) { return nullptr; } - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; i++) + for (int i = inventory::socketBegin; i < inventory::SocketCount; i++) { if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype) { @@ -587,10 +587,10 @@ bool EQEmu::ItemInstance::UpdateOrnamentationInfo() { return ornamentSet; } -bool EQEmu::ItemInstance::CanTransform(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container, bool AllowAll) { +bool EQEmu::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll) { if (!ItemToTry || !Container) return false; - if (ItemToTry->ItemType == EQEmu::item::ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0) + if (ItemToTry->ItemType == item::ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0) return false; if (AllowAll && strncasecmp(Container->CharmFile, "ITEMTRANSFIGSHIELD", 18) && strncasecmp(Container->CharmFile, "ITEMTransfigBow", 15)) { @@ -685,7 +685,7 @@ bool EQEmu::ItemInstance::IsAugmented() if (!m_item || !m_item->IsClassCommon()) return false; - for (int index = EQEmu::inventory::socketBegin; index < EQEmu::inventory::SocketCount; ++index) { + for (int index = inventory::socketBegin; index < inventory::SocketCount; ++index) { if (GetAugmentItemID(index)) return true; } @@ -699,7 +699,7 @@ bool EQEmu::ItemInstance::IsWeapon() const if (!m_item || !m_item->IsClassCommon()) return false; - if (m_item->ItemType == EQEmu::item::ItemTypeArrow && m_item->Damage != 0) + if (m_item->ItemType == item::ItemTypeArrow && m_item->Damage != 0) return true; else return ((m_item->Damage != 0) && (m_item->Delay != 0)); @@ -710,9 +710,9 @@ bool EQEmu::ItemInstance::IsAmmo() const if (!m_item) return false; - if ((m_item->ItemType == EQEmu::item::ItemTypeArrow) || - (m_item->ItemType == EQEmu::item::ItemTypeLargeThrowing) || - (m_item->ItemType == EQEmu::item::ItemTypeSmallThrowing) + if ((m_item->ItemType == item::ItemTypeArrow) || + (m_item->ItemType == item::ItemTypeLargeThrowing) || + (m_item->ItemType == item::ItemTypeSmallThrowing) ) { return true; } @@ -811,10 +811,10 @@ EQEmu::ItemInstance* EQEmu::ItemInstance::Clone() const bool EQEmu::ItemInstance::IsSlotAllowed(int16 slot_id) const { // 'SupportsContainers' and 'slot_id > 21' previously saw the reassigned PowerSource slot (9999 to 22) as valid if (!m_item) { return false; } - else if (Inventory::SupportsContainers(slot_id)) { return true; } + else if (InventoryProfile::SupportsContainers(slot_id)) { return true; } else if (m_item->Slots & (1 << slot_id)) { return true; } - else if (slot_id == EQEmu::inventory::slotPowerSource && (m_item->Slots & (1 << 22))) { return true; } // got lazy... - else if (slot_id != EQEmu::inventory::slotPowerSource && slot_id > EQEmu::legacy::EQUIPMENT_END) { return true; } + else if (slot_id == inventory::slotPowerSource && (m_item->Slots & (1 << 22))) { return true; } // got lazy... + else if (slot_id != inventory::slotPowerSource && slot_id > legacy::EQUIPMENT_END) { return true; } else { return false; } } @@ -966,7 +966,7 @@ int EQEmu::ItemInstance::GetItemArmorClass(bool augments) const if (item) { ac = item->AC; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) ac += GetAugment(i)->GetItemArmorClass(); } @@ -1008,7 +1008,7 @@ int EQEmu::ItemInstance::GetItemElementalDamage(int &magic, int &fire, int &cold } if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) GetAugment(i)->GetItemElementalDamage(magic, fire, cold, poison, disease, chromatic, prismatic, physical, corruption); } @@ -1025,7 +1025,7 @@ int EQEmu::ItemInstance::GetItemElementalFlag(bool augments) const return flag; if (augments) { - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) { + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) { if (GetAugment(i)) flag = GetAugment(i)->GetItemElementalFlag(); if (flag) @@ -1046,7 +1046,7 @@ int EQEmu::ItemInstance::GetItemElementalDamage(bool augments) const return damage; if (augments) { - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) { + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) { if (GetAugment(i)) damage = GetAugment(i)->GetItemElementalDamage(); if (damage) @@ -1065,7 +1065,7 @@ int EQEmu::ItemInstance::GetItemRecommendedLevel(bool augments) const level = item->RecLevel; if (augments) { - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) { + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) { int temp = 0; if (GetAugment(i)) { temp = GetAugment(i)->GetItemRecommendedLevel(); @@ -1087,7 +1087,7 @@ int EQEmu::ItemInstance::GetItemRequiredLevel(bool augments) const level = item->ReqLevel; if (augments) { - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) { + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) { int temp = 0; if (GetAugment(i)) { temp = GetAugment(i)->GetItemRequiredLevel(); @@ -1109,7 +1109,7 @@ int EQEmu::ItemInstance::GetItemWeaponDamage(bool augments) const damage = item->Damage; if (augments) { - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemWeaponDamage(); } @@ -1125,7 +1125,7 @@ int EQEmu::ItemInstance::GetItemBackstabDamage(bool augments) const damage = item->BackstabDmg; if (augments) { - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBackstabDamage(); } @@ -1143,7 +1143,7 @@ int EQEmu::ItemInstance::GetItemBaneDamageBody(bool augments) const return body; if (augments) { - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) { body = GetAugment(i)->GetItemBaneDamageBody(); if (body) @@ -1164,7 +1164,7 @@ int EQEmu::ItemInstance::GetItemBaneDamageRace(bool augments) const return race; if (augments) { - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) { race = GetAugment(i)->GetItemBaneDamageRace(); if (race) @@ -1184,7 +1184,7 @@ int EQEmu::ItemInstance::GetItemBaneDamageBody(bodyType against, bool augments) damage += item->BaneDmgAmt; if (augments) { - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBaneDamageBody(against); } @@ -1201,7 +1201,7 @@ int EQEmu::ItemInstance::GetItemBaneDamageRace(uint16 against, bool augments) co damage += item->BaneDmgRaceAmt; if (augments) { - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) damage += GetAugment(i)->GetItemBaneDamageRace(against); } @@ -1217,7 +1217,7 @@ int EQEmu::ItemInstance::GetItemMagical(bool augments) const return 1; if (augments) { - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i) && GetAugment(i)->GetItemMagical()) return 1; } @@ -1232,7 +1232,7 @@ int EQEmu::ItemInstance::GetItemHP(bool augments) const if (item) { hp = item->HP; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) hp += GetAugment(i)->GetItemHP(); } @@ -1246,7 +1246,7 @@ int EQEmu::ItemInstance::GetItemMana(bool augments) const if (item) { mana = item->Mana; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) mana += GetAugment(i)->GetItemMana(); } @@ -1260,7 +1260,7 @@ int EQEmu::ItemInstance::GetItemEndur(bool augments) const if (item) { endur = item->Endur; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) endur += GetAugment(i)->GetItemEndur(); } @@ -1274,7 +1274,7 @@ int EQEmu::ItemInstance::GetItemAttack(bool augments) const if (item) { atk = item->Attack; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) atk += GetAugment(i)->GetItemAttack(); } @@ -1288,7 +1288,7 @@ int EQEmu::ItemInstance::GetItemStr(bool augments) const if (item) { str = item->AStr; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) str += GetAugment(i)->GetItemStr(); } @@ -1302,7 +1302,7 @@ int EQEmu::ItemInstance::GetItemSta(bool augments) const if (item) { sta = item->ASta; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) sta += GetAugment(i)->GetItemSta(); } @@ -1316,7 +1316,7 @@ int EQEmu::ItemInstance::GetItemDex(bool augments) const if (item) { total = item->ADex; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemDex(); } @@ -1330,7 +1330,7 @@ int EQEmu::ItemInstance::GetItemAgi(bool augments) const if (item) { total = item->AAgi; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemAgi(); } @@ -1344,7 +1344,7 @@ int EQEmu::ItemInstance::GetItemInt(bool augments) const if (item) { total = item->AInt; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemInt(); } @@ -1358,7 +1358,7 @@ int EQEmu::ItemInstance::GetItemWis(bool augments) const if (item) { total = item->AWis; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemWis(); } @@ -1372,7 +1372,7 @@ int EQEmu::ItemInstance::GetItemCha(bool augments) const if (item) { total = item->ACha; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCha(); } @@ -1386,7 +1386,7 @@ int EQEmu::ItemInstance::GetItemMR(bool augments) const if (item) { total = item->MR; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemMR(); } @@ -1400,7 +1400,7 @@ int EQEmu::ItemInstance::GetItemFR(bool augments) const if (item) { total = item->FR; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemFR(); } @@ -1414,7 +1414,7 @@ int EQEmu::ItemInstance::GetItemCR(bool augments) const if (item) { total = item->CR; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCR(); } @@ -1428,7 +1428,7 @@ int EQEmu::ItemInstance::GetItemPR(bool augments) const if (item) { total = item->PR; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemPR(); } @@ -1442,7 +1442,7 @@ int EQEmu::ItemInstance::GetItemDR(bool augments) const if (item) { total = item->DR; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemDR(); } @@ -1456,7 +1456,7 @@ int EQEmu::ItemInstance::GetItemCorrup(bool augments) const if (item) { total = item->SVCorruption; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemCorrup(); } @@ -1470,7 +1470,7 @@ int EQEmu::ItemInstance::GetItemHeroicStr(bool augments) const if (item) { total = item->HeroicStr; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicStr(); } @@ -1484,7 +1484,7 @@ int EQEmu::ItemInstance::GetItemHeroicSta(bool augments) const if (item) { total = item->HeroicSta; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicSta(); } @@ -1498,7 +1498,7 @@ int EQEmu::ItemInstance::GetItemHeroicDex(bool augments) const if (item) { total = item->HeroicDex; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicDex(); } @@ -1512,7 +1512,7 @@ int EQEmu::ItemInstance::GetItemHeroicAgi(bool augments) const if (item) { total = item->HeroicAgi; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicAgi(); } @@ -1526,7 +1526,7 @@ int EQEmu::ItemInstance::GetItemHeroicInt(bool augments) const if (item) { total = item->HeroicInt; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicInt(); } @@ -1540,7 +1540,7 @@ int EQEmu::ItemInstance::GetItemHeroicWis(bool augments) const if (item) { total = item->HeroicWis; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicWis(); } @@ -1554,7 +1554,7 @@ int EQEmu::ItemInstance::GetItemHeroicCha(bool augments) const if (item) { total = item->HeroicCha; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCha(); } @@ -1568,7 +1568,7 @@ int EQEmu::ItemInstance::GetItemHeroicMR(bool augments) const if (item) { total = item->HeroicMR; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicMR(); } @@ -1582,7 +1582,7 @@ int EQEmu::ItemInstance::GetItemHeroicFR(bool augments) const if (item) { total = item->HeroicFR; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicFR(); } @@ -1596,7 +1596,7 @@ int EQEmu::ItemInstance::GetItemHeroicCR(bool augments) const if (item) { total = item->HeroicCR; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCR(); } @@ -1610,7 +1610,7 @@ int EQEmu::ItemInstance::GetItemHeroicPR(bool augments) const if (item) { total = item->HeroicPR; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicPR(); } @@ -1624,7 +1624,7 @@ int EQEmu::ItemInstance::GetItemHeroicDR(bool augments) const if (item) { total = item->HeroicDR; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicDR(); } @@ -1638,7 +1638,7 @@ int EQEmu::ItemInstance::GetItemHeroicCorrup(bool augments) const if (item) { total = item->HeroicSVCorrup; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) total += GetAugment(i)->GetItemHeroicCorrup(); } @@ -1652,7 +1652,7 @@ int EQEmu::ItemInstance::GetItemHaste(bool augments) const if (item) { total = item->Haste; if (augments) - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) + for (int i = inventory::socketBegin; i < inventory::SocketCount; ++i) if (GetAugment(i)) { int temp = GetAugment(i)->GetItemHaste(); if (temp > total) diff --git a/common/item_instance.h b/common/item_instance.h index 2a4afdca1..90dd1403f 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -52,7 +52,6 @@ typedef enum { } byFlagSetting; class SharedDatabase; -class Inventory; // ######################################## // Class: EQEmu::ItemInstance @@ -61,6 +60,8 @@ class Inventory; // to an item instance (includes dye, augments, charges, etc) namespace EQEmu { + class InventoryProfile; + class ItemInstance { public: ///////////////////////// @@ -79,7 +80,7 @@ namespace EQEmu ~ItemInstance(); // Query item type - bool IsType(EQEmu::item::ItemClass item_class) const; + bool IsType(item::ItemClass item_class) const; bool IsClassCommon() const; bool IsClassBag() const; @@ -102,7 +103,7 @@ namespace EQEmu bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const; inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); } - inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == EQEmu::item::ItemEffectExpendable) || (m_item->ItemType == EQEmu::item::ItemTypePotion)) : false); } + inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == item::ItemEffectExpendable) || (m_item->ItemType == item::ItemTypePotion)) : false); } // // Contents @@ -133,7 +134,7 @@ namespace EQEmu bool IsAugmented(); ItemInstance* GetOrnamentationAug(int32 ornamentationAugtype) const; bool UpdateOrnamentationInfo(); - static bool CanTransform(const EQEmu::ItemData *ItemToTry, const EQEmu::ItemData *Container, bool AllowAll = false); + static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false); // Has attack/delay? bool IsWeapon() const; @@ -211,8 +212,8 @@ namespace EQEmu int8 GetMaxEvolveLvl() const; uint32 GetKillsNeeded(uint8 currentlevel); - std::string Serialize(int16 slot_id) const { EQEmu::InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(EQEmu::InternalSerializedItem_Struct)); return ser; } - void Serialize(EQEmu::OutBuffer& ob, int16 slot_id) const { EQEmu::InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); } + std::string Serialize(int16 slot_id) const { InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(InternalSerializedItem_Struct)); return ser; } + void Serialize(OutBuffer& ob, int16 slot_id) const { InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); } inline int32 GetSerialNumber() const { return m_SerialNumber; } inline void SetSerialNumber(int32 id) { m_SerialNumber = id; } @@ -278,7 +279,7 @@ namespace EQEmu ////////////////////////// // Protected Members ////////////////////////// - friend class ::Inventory; + friend class InventoryProfile; std::map::const_iterator _cbegin() { return m_contents.cbegin(); } std::map::const_iterator _cend() { return m_contents.cend(); } @@ -299,7 +300,7 @@ namespace EQEmu int8 m_evolveLvl; bool m_activated; ItemData* m_scaledItem; - EvolveInfo* m_evolveInfo; + ::EvolveInfo* m_evolveInfo; bool m_scaling; uint32 m_ornamenticon; uint32 m_ornamentidfile; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index cc1744a31..6d13bb338 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -5264,7 +5264,7 @@ namespace RoF if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { ornaIcon = inst->GetOrnamentationIcon(); - heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in)); + heroModel = inst->GetOrnamentHeroModel(EQEmu::InventoryProfile::CalcMaterialFromSlot(slot_id_in)); char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index aadd0a90b..14fcdc2e6 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -5555,7 +5555,7 @@ namespace RoF2 if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { ornaIcon = inst->GetOrnamentationIcon(); - heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in)); + heroModel = inst->GetOrnamentHeroModel(EQEmu::InventoryProfile::CalcMaterialFromSlot(slot_id_in)); char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 8cd62f164..fd55b3766 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -184,7 +184,7 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const EQEmu::ItemInstance* in else { // Needed to clear out bag slots that 'REPLACE' in UpdateSharedBankSlot does not overwrite..otherwise, duplication occurs // (This requires that parent then child items be sent..which should be how they are currently passed) - if (Inventory::SupportsContainers(slot_id)) + if (EQEmu::InventoryProfile::SupportsContainers(slot_id)) DeleteSharedBankSlot(char_id, slot_id); return UpdateSharedBankSlot(char_id, inst, slot_id); } @@ -195,7 +195,7 @@ bool SharedDatabase::SaveInventory(uint32 char_id, const EQEmu::ItemInstance* in // Needed to clear out bag slots that 'REPLACE' in UpdateInventorySlot does not overwrite..otherwise, duplication occurs // (This requires that parent then child items be sent..which should be how they are currently passed) - if (Inventory::SupportsContainers(slot_id)) + if (EQEmu::InventoryProfile::SupportsContainers(slot_id)) DeleteInventorySlot(char_id, slot_id); return UpdateInventorySlot(char_id, inst, slot_id); } @@ -232,12 +232,12 @@ bool SharedDatabase::UpdateInventorySlot(uint32 char_id, const EQEmu::ItemInstan auto results = QueryDatabase(query); // Save bag contents, if slot supports bag contents - if (inst->IsClassBag() && Inventory::SupportsContainers(slot_id)) + if (inst->IsClassBag() && EQEmu::InventoryProfile::SupportsContainers(slot_id)) // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) for (uint8 idx = EQEmu::inventory::containerBegin; idx < inst->GetItem()->BagSlots && idx < EQEmu::inventory::ContainerCount; idx++) { const EQEmu::ItemInstance* baginst = inst->GetItem(idx); - SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); + SaveInventory(char_id, baginst, EQEmu::InventoryProfile::CalcSlotId(slot_id, idx)); } if (!results.Success()) { @@ -278,12 +278,12 @@ bool SharedDatabase::UpdateSharedBankSlot(uint32 char_id, const EQEmu::ItemInsta auto results = QueryDatabase(query); // Save bag contents, if slot supports bag contents - if (inst->IsClassBag() && Inventory::SupportsContainers(slot_id)) { + if (inst->IsClassBag() && EQEmu::InventoryProfile::SupportsContainers(slot_id)) { // Limiting to bag slot count will get rid of 'hidden' duplicated items and 'Invalid Slot ID' // messages through attrition (and the modded code in SaveInventory) for (uint8 idx = EQEmu::inventory::containerBegin; idx < inst->GetItem()->BagSlots && idx < EQEmu::inventory::ContainerCount; idx++) { const EQEmu::ItemInstance* baginst = inst->GetItem(idx); - SaveInventory(char_id, baginst, Inventory::CalcSlotId(slot_id, idx)); + SaveInventory(char_id, baginst, EQEmu::InventoryProfile::CalcSlotId(slot_id, idx)); } } @@ -304,10 +304,10 @@ bool SharedDatabase::DeleteInventorySlot(uint32 char_id, int16 slot_id) { } // Delete bag slots, if need be - if (!Inventory::SupportsContainers(slot_id)) + if (!EQEmu::InventoryProfile::SupportsContainers(slot_id)) return true; - int16 base_slot_id = Inventory::CalcSlotId(slot_id, EQEmu::inventory::containerBegin); + int16 base_slot_id = EQEmu::InventoryProfile::CalcSlotId(slot_id, EQEmu::inventory::containerBegin); query = StringFormat("DELETE FROM inventory WHERE charid = %i AND slotid >= %i AND slotid < %i", char_id, base_slot_id, (base_slot_id+10)); results = QueryDatabase(query); @@ -330,10 +330,10 @@ bool SharedDatabase::DeleteSharedBankSlot(uint32 char_id, int16 slot_id) { } // Delete bag slots, if need be - if (!Inventory::SupportsContainers(slot_id)) + if (!EQEmu::InventoryProfile::SupportsContainers(slot_id)) return true; - int16 base_slot_id = Inventory::CalcSlotId(slot_id, EQEmu::inventory::containerBegin); + int16 base_slot_id = EQEmu::InventoryProfile::CalcSlotId(slot_id, EQEmu::inventory::containerBegin); query = StringFormat("DELETE FROM sharedbank WHERE acctid = %i " "AND slotid >= %i AND slotid < %i", account_id, base_slot_id, (base_slot_id+10)); @@ -373,7 +373,7 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) { return true; } -bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) { +bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, EQEmu::InventoryProfile* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) { const EQEmu::ItemData* myitem; @@ -410,7 +410,7 @@ bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, // Retrieve shared bank inventory based on either account or character -bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) +bool SharedDatabase::GetSharedBank(uint32 id, EQEmu::InventoryProfile *inv, bool is_charid) { std::string query; @@ -511,7 +511,7 @@ bool SharedDatabase::GetSharedBank(uint32 id, Inventory *inv, bool is_charid) } // Overloaded: Retrieve character inventory based on character id -bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) +bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::InventoryProfile *inv) { // Retrieve character inventory std::string query = @@ -653,7 +653,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, Inventory *inv) } // Overloaded: Retrieve character inventory based on account_id and character name -bool SharedDatabase::GetInventory(uint32 account_id, char *name, Inventory *inv) +bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQEmu::InventoryProfile *inv) { // Retrieve character inventory std::string query = diff --git a/common/shareddb.h b/common/shareddb.h index 42dfcf4ce..b58d1f138 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -33,7 +33,6 @@ #include class EvolveInfo; -class Inventory; struct BaseDataStruct; struct InspectMessage_Struct; struct PlayerProfile_Struct; @@ -46,6 +45,7 @@ namespace EQEmu { struct ItemData; class ItemInstance; + class InventoryProfile; class MemoryMappedFile; } @@ -74,7 +74,7 @@ class SharedDatabase : public Database uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID); /* - Character Inventory + Character InventoryProfile */ bool SaveCursor(uint32 char_id, std::list::const_iterator &start, std::list::const_iterator &end); bool SaveInventory(uint32 char_id, const EQEmu::ItemInstance* inst, int16 slot_id); @@ -83,15 +83,15 @@ class SharedDatabase : public Database bool UpdateInventorySlot(uint32 char_id, const EQEmu::ItemInstance* inst, int16 slot_id); bool UpdateSharedBankSlot(uint32 char_id, const EQEmu::ItemInstance* inst, int16 slot_id); bool VerifyInventory(uint32 account_id, int16 slot_id, const EQEmu::ItemInstance* inst); - bool GetSharedBank(uint32 id, Inventory* inv, bool is_charid); + bool GetSharedBank(uint32 id, EQEmu::InventoryProfile* inv, bool is_charid); int32 GetSharedPlatinum(uint32 account_id); bool SetSharedPlatinum(uint32 account_id, int32 amount_to_add); - bool GetInventory(uint32 char_id, Inventory* inv); - bool GetInventory(uint32 account_id, char* name, Inventory* inv); + bool GetInventory(uint32 char_id, EQEmu::InventoryProfile* inv); + bool GetInventory(uint32 account_id, char* name, EQEmu::InventoryProfile* inv); std::map GetItemRecastTimestamps(uint32 char_id); uint32 GetItemRecastTimestamp(uint32 char_id, uint32 recast_type); void ClearOldRecastTimestamps(uint32 char_id); - bool SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin); + bool SetStartingItems(PlayerProfile_Struct* pp, EQEmu::InventoryProfile* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin); std::string GetBook(const char *txtfile); diff --git a/world/client.cpp b/world/client.cpp index 5614d6317..29abc5b9d 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1399,7 +1399,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) { PlayerProfile_Struct pp; ExtendedProfile_Struct ext; - Inventory inv; + EQEmu::InventoryProfile inv; time_t bday = time(nullptr); char startzone[50]={0}; uint32 i; diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 65476190e..5cac4b648 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -96,7 +96,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou for (auto row = results.begin(); row != results.end(); ++row) { CharacterSelectEntry_Struct *cse = (CharacterSelectEntry_Struct *)buff_ptr; PlayerProfile_Struct pp; - Inventory inv; + EQEmu::InventoryProfile inv; uint32 character_id = (uint32)atoi(row[0]); uint8 has_home = 0; uint8 has_bind = 0; @@ -249,7 +249,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou int16 invslot = 0; for (uint32 matslot = EQEmu::textures::textureBegin; matslot < EQEmu::textures::materialCount; matslot++) { - invslot = Inventory::CalcSlotFromMaterial(matslot); + invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(matslot); if (invslot == INVALID_INDEX) { continue; } inst = inv.GetItem(invslot); if (inst == nullptr) { continue; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 4ff4fbabe..760ca52dc 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -3325,7 +3325,7 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) if (i >= EQEmu::legacy::GENERAL_BAGS_BEGIN && i <= EQEmu::legacy::GENERAL_BAGS_END) { - EQEmu::ItemInstance* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); + EQEmu::ItemInstance* parent_item = m_inv.GetItem(EQEmu::InventoryProfile::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; } @@ -3418,7 +3418,7 @@ bool Client::DoItemEnterZone(uint32 slot_x, uint32 slot_y) { // TEST CODE: test for bazaar trader crashing with charm items if (Trader) if (i >= EQEmu::legacy::GENERAL_BAGS_BEGIN && i <= EQEmu::legacy::GENERAL_BAGS_END) { - EQEmu::ItemInstance* parent_item = m_inv.GetItem(Inventory::CalcSlotId(i)); + EQEmu::ItemInstance* parent_item = m_inv.GetItem(EQEmu::InventoryProfile::CalcSlotId(i)); if (parent_item && parent_item->GetItem()->ID == 17899) // trader satchel continue; } diff --git a/zone/bot.cpp b/zone/bot.cpp index 03ba04dfd..1629580bf 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2875,7 +2875,7 @@ void Bot::Spawn(Client* botCharacterOwner) { for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { itemID = GetBotItemBySlot(i); if(itemID != 0) { - materialFromSlot = Inventory::CalcMaterialFromSlot(i); + materialFromSlot = EQEmu::InventoryProfile::CalcMaterialFromSlot(i); if(materialFromSlot != 0xFF) this->SendWearChange(materialFromSlot); } @@ -2897,7 +2897,7 @@ void Bot::RemoveBotItemBySlot(uint32 slotID, std::string *errorMessage) } // Retrieves all the inventory records from the database for this bot. -void Bot::GetBotItems(Inventory &inv, std::string* errorMessage) +void Bot::GetBotItems(EQEmu::InventoryProfile &inv, std::string* errorMessage) { if(!GetBotID()) return; @@ -3235,7 +3235,7 @@ EQEmu::ItemInstance* Bot::GetBotItem(uint32 slotID) { // Adds the specified item it bot to the NPC equipment array and to the bot inventory collection. void Bot::BotAddEquipItem(int slot, uint32 id) { if(slot > 0 && id > 0) { - uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); + uint8 materialFromSlot = EQEmu::InventoryProfile::CalcMaterialFromSlot(slot); if (materialFromSlot != EQEmu::textures::materialInvalid) { equipment[slot] = id; // npc has more than just material slots. Valid material should mean valid inventory index @@ -3251,7 +3251,7 @@ void Bot::BotAddEquipItem(int slot, uint32 id) { // Erases the specified item from bot the NPC equipment array and from the bot inventory collection. void Bot::BotRemoveEquipItem(int slot) { if(slot > 0) { - uint8 materialFromSlot = Inventory::CalcMaterialFromSlot(slot); + uint8 materialFromSlot = EQEmu::InventoryProfile::CalcMaterialFromSlot(slot); if (materialFromSlot != EQEmu::textures::materialInvalid) { equipment[slot] = 0; // npc has more than just material slots. Valid material should mean valid inventory index @@ -3382,7 +3382,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli bool UpdateClient = false; bool already_returned = false; - Inventory& clientInventory = client->GetInv(); + EQEmu::InventoryProfile& clientInventory = client->GetInv(); const EQEmu::ItemInstance* inst = clientInventory[i]; if(inst) { items[i] = inst->GetItem()->ID; @@ -8434,7 +8434,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) return false; for (uint8 i = EQEmu::textures::textureBegin; i < EQEmu::textures::weaponPrimary; ++i) { - uint8 inv_slot = Inventory::CalcSlotFromMaterial(i); + uint8 inv_slot = EQEmu::InventoryProfile::CalcSlotFromMaterial(i); EQEmu::ItemInstance* inst = m_inv.GetItem(inv_slot); if (!inst) continue; @@ -8444,7 +8444,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag) } } else { - uint8 mat_slot = Inventory::CalcMaterialFromSlot(slot_id); + uint8 mat_slot = EQEmu::InventoryProfile::CalcMaterialFromSlot(slot_id); if (mat_slot == EQEmu::textures::materialInvalid || mat_slot >= EQEmu::textures::weaponPrimary) return false; diff --git a/zone/bot.h b/zone/bot.h index 96ca86eec..736a464ab 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -647,7 +647,7 @@ private: bool _petChooser; uint8 _petChooserID; bool berserk; - Inventory m_inv; + EQEmu::InventoryProfile m_inv; double _lastTotalPlayTime; time_t _startTotalPlayTime; Mob* _previousTarget; @@ -711,7 +711,7 @@ private: void SetBotID(uint32 botID); // Private "Inventory" Methods - void GetBotItems(Inventory &inv, std::string* errorMessage); + void GetBotItems(EQEmu::InventoryProfile &inv, std::string* errorMessage); void BotAddEquipItem(int slot, uint32 id); uint32 GetBotItemBySlot(uint32 slotID); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 57dd2d418..72ac6cae4 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -4375,7 +4375,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep) bool dye_all = (sep->arg[1][0] == '*'); if (!dye_all) { material_slot = atoi(sep->arg[1]); - slot_id = Inventory::CalcSlotFromMaterial(material_slot); + slot_id = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot); if (!sep->IsNumber(1) || slot_id == INVALID_INDEX || material_slot > EQEmu::textures::LastTintableTexture) { c->Message(m_fail, "Valid [mat_slot]s for this command are:"); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 259df1d63..04ce5b281 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -1023,7 +1023,7 @@ bool BotDatabase::QueryInventoryCount(const uint32 bot_id, uint32& item_count) return true; } -bool BotDatabase::LoadItems(const uint32 bot_id, Inventory& inventory_inst) +bool BotDatabase::LoadItems(const uint32 bot_id, EQEmu::InventoryProfile& inventory_inst) { if (!bot_id) return false; @@ -1279,7 +1279,7 @@ bool BotDatabase::LoadEquipmentColor(const uint32 bot_id, const uint8 material_s if (!bot_id) return false; - int16 slot_id = Inventory::CalcSlotFromMaterial(material_slot_id); + int16 slot_id = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot_id); if (slot_id == INVALID_INDEX) return false; diff --git a/zone/bot_database.h b/zone/bot_database.h index 3eaaf21d9..b7245306f 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -31,12 +31,12 @@ class Bot; -class Inventory; struct BotsAvailableList; namespace EQEmu { class ItemInstance; + class InventoryProfile; } @@ -89,7 +89,7 @@ public: /* Bot inventory functions */ bool QueryInventoryCount(const uint32 bot_id, uint32& item_count); - bool LoadItems(const uint32 bot_id, Inventory &inventory_inst); + bool LoadItems(const uint32 bot_id, EQEmu::InventoryProfile &inventory_inst); bool SaveItems(Bot* bot_inst); bool DeleteItems(const uint32 bot_id); diff --git a/zone/client.cpp b/zone/client.cpp index 09f843616..3f914d1ae 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2799,7 +2799,7 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) { const EQEmu::ItemData* item = database.GetItem(item_id); if (item && item->IsClassCommon()) { - uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); + uint8 matslot = EQEmu::InventoryProfile::CalcMaterialFromSlot(in_slot); if (matslot != EQEmu::textures::materialInvalid) { m_pp.item_material.Slot[matslot].Material = GetEquipmentMaterial(matslot); @@ -3141,7 +3141,7 @@ void Client::SetTint(int16 in_slot, uint32 color) { // Still need to reconcile bracer01 versus bracer02 void Client::SetTint(int16 in_slot, EQEmu::textures::Tint_Struct& color) { - uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot); + uint8 matslot = EQEmu::InventoryProfile::CalcMaterialFromSlot(in_slot); if (matslot != EQEmu::textures::materialInvalid) { m_pp.item_tint.Slot[matslot].Color = color.Color; diff --git a/zone/client.h b/zone/client.h index 82ee442d2..c7973de18 100644 --- a/zone/client.h +++ b/zone/client.h @@ -340,8 +340,8 @@ public: inline uint8 GetAnon() const { return m_pp.anon; } inline PlayerProfile_Struct& GetPP() { return m_pp; } inline ExtendedProfile_Struct& GetEPP() { return m_epp; } - inline Inventory& GetInv() { return m_inv; } - inline const Inventory& GetInv() const { return m_inv; } + inline EQEmu::InventoryProfile& GetInv() { return m_inv; } + inline const EQEmu::InventoryProfile& GetInv() const { return m_inv; } inline PetInfo* GetPetInfo(uint16 pet) { return (pet==1)?&m_suspendedminion:&m_petinfo; } inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; } inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; } @@ -1395,7 +1395,7 @@ private: PlayerProfile_Struct m_pp; ExtendedProfile_Struct m_epp; - Inventory m_inv; + EQEmu::InventoryProfile m_inv; Object* m_tradeskill_object; PetInfo m_petinfo; // current pet data, used while loading from and saving to DB PetInfo m_suspendedminion; // pet data for our suspended minion. diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a537c1db2..0b6221c2a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2939,11 +2939,11 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) // in_augment->container_slot, in_augment->augment_slot, in_augment->container_index, in_augment->augment_index, in_augment->augment_action, in_augment->dest_inst_id); EQEmu::ItemInstance *tobe_auged = nullptr, *old_aug = nullptr, *new_aug = nullptr, *aug = nullptr, *solvent = nullptr; - Inventory& user_inv = GetInv(); + EQEmu::InventoryProfile& user_inv = GetInv(); uint16 item_slot = in_augment->container_slot; uint16 solvent_slot = in_augment->augment_slot; - uint8 mat = Inventory::CalcMaterialFromSlot(item_slot); // for when player is augging a piece of equipment while they're wearing it + uint8 mat = EQEmu::InventoryProfile::CalcMaterialFromSlot(item_slot); // for when player is augging a piece of equipment while they're wearing it if (item_slot == INVALID_INDEX || solvent_slot == INVALID_INDEX) { diff --git a/zone/command.cpp b/zone/command.cpp index 487e25286..d75dec901 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2596,7 +2596,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " InvBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } @@ -2630,7 +2630,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " CursorBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(EQEmu::inventory::slotCursor, indexSub), EQEmu::inventory::slotCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + EQEmu::InventoryProfile::CalcSlotId(EQEmu::inventory::slotCursor, indexSub), EQEmu::inventory::slotCursor, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } } @@ -2667,7 +2667,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " BankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } @@ -2689,7 +2689,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " SharedBankBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } @@ -2712,7 +2712,7 @@ void command_peekinv(Client *c, const Seperator *sep) item_link = linker.GenerateLink(); c->Message((item_data == nullptr), " TradeBagSlot: %i (Slot #%i, Bag #%i), Item: %i (%s), Charges: %i", - Inventory::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); + EQEmu::InventoryProfile::CalcSlotId(indexMain, indexSub), indexMain, indexSub, ((item_data == nullptr) ? 0 : item_data->ID), item_link.c_str(), ((inst_sub == nullptr) ? 0 : inst_sub->GetCharges())); } } diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 57a85aff9..3b9c15214 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -408,7 +408,7 @@ void Corpse::MoveItemToCorpse(Client *client, EQEmu::ItemInstance *inst, int16 e if (equipSlot < EQEmu::legacy::GENERAL_BEGIN || equipSlot > EQEmu::inventory::slotCursor) { break; } for (int16 sub_index = EQEmu::inventory::containerBegin; sub_index < EQEmu::inventory::ContainerCount; ++sub_index) { - int16 real_bag_slot = Inventory::CalcSlotId(equipSlot, sub_index); + int16 real_bag_slot = EQEmu::InventoryProfile::CalcSlotId(equipSlot, sub_index); auto bag_inst = client->GetInv().GetItem(real_bag_slot); if (bag_inst == nullptr) { continue; } @@ -684,8 +684,8 @@ ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** } } - if (sitem && bag_item_data && Inventory::SupportsContainers(sitem->equip_slot)) { - int16 bagstart = Inventory::CalcSlotId(sitem->equip_slot, EQEmu::inventory::containerBegin); + if (sitem && bag_item_data && EQEmu::InventoryProfile::SupportsContainers(sitem->equip_slot)) { + int16 bagstart = EQEmu::InventoryProfile::CalcSlotId(sitem->equip_slot, EQEmu::inventory::containerBegin); cur = itemlist.begin(); end = itemlist.end(); @@ -739,7 +739,7 @@ void Corpse::RemoveItem(ServerLootItem_Struct* item_data) is_corpse_changed = true; itemlist.erase(iter); - uint8 material = Inventory::CalcMaterialFromSlot(sitem->equip_slot); // autos to unsigned char + uint8 material = EQEmu::InventoryProfile::CalcMaterialFromSlot(sitem->equip_slot); // autos to unsigned char if (material != EQEmu::textures::materialInvalid) SendWearChange(material); @@ -1406,7 +1406,7 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { return 0; } - invslot = Inventory::CalcSlotFromMaterial(material_slot); + invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot); if(invslot == INVALID_INDEX) // GetWornItem() should be returning a 0 for any invalid index... return 0; diff --git a/zone/inventory.cpp b/zone/inventory.cpp index c89879610..c5d7de0fe 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -767,7 +767,7 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd EQEmu::ItemInstance* bagitem = m_inv[slot_id]->GetItem(bag_idx); if(bagitem) { - int16 bagslot_id = Inventory::CalcSlotId(slot_id, bag_idx); + int16 bagslot_id = EQEmu::InventoryProfile::CalcSlotId(slot_id, bag_idx); qsaudit->items[++parent_offset].char_slot = bagslot_id; qsaudit->items[parent_offset].item_id = bagitem->GetID(); @@ -866,7 +866,7 @@ bool Client::PutItemInInventory(int16 slot_id, const EQEmu::ItemInstance& inst, if (client_update) { SendItemPacket(slot_id, &inst, ((slot_id == EQEmu::inventory::slotCursor) ? ItemPacketLimbo : ItemPacketTrade)); - //SendWearChange(Inventory::CalcMaterialFromSlot(slot_id)); + //SendWearChange(EQEmu::InventoryProfile::CalcMaterialFromSlot(slot_id)); } if (slot_id == EQEmu::inventory::slotCursor) { @@ -934,7 +934,7 @@ void Client::PutLootInInventory(int16 slot_id, const EQEmu::ItemInstance &inst, PutLootInInventory(EQEmu::inventory::slotCursor, *bagitem); } else { - auto bag_slot = Inventory::CalcSlotId(slot_id, index); + auto bag_slot = EQEmu::InventoryProfile::CalcSlotId(slot_id, index); Log.Out(Logs::Detail, Logs::Inventory, "Putting bag loot item %s (%d) into slot %d (bag slot %d)", @@ -966,7 +966,7 @@ bool Client::TryStacking(EQEmu::ItemInstance* item, uint8 type, bool try_worn, b } for (i = EQEmu::legacy::GENERAL_BEGIN; i <= EQEmu::legacy::GENERAL_END; i++) { for (uint8 j = EQEmu::inventory::containerBegin; j < EQEmu::inventory::ContainerCount; j++) { - uint16 slotid = Inventory::CalcSlotId(i, j); + uint16 slotid = EQEmu::InventoryProfile::CalcSlotId(i, j); EQEmu::ItemInstance* tmp_inst = m_inv.GetItem(slotid); if(tmp_inst && tmp_inst->GetItem()->ID == item_id && tmp_inst->GetCharges() < tmp_inst->GetItem()->StackSize) { @@ -1018,7 +1018,7 @@ bool Client::AutoPutLootInInventory(EQEmu::ItemInstance& inst, bool try_worn, bo if (inst.IsEquipable(i)) { // Equippable at this slot? //send worn to everyone... PutLootInInventory(i, inst); - uint8 worn_slot_material = Inventory::CalcMaterialFromSlot(i); + uint8 worn_slot_material = EQEmu::InventoryProfile::CalcMaterialFromSlot(i); if (worn_slot_material != EQEmu::textures::materialInvalid) { SendWearChange(worn_slot_material); } @@ -1518,8 +1518,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (src_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && src_slot_id <= EQEmu::legacy::SHARED_BANK_END && src_inst->IsClassBag()){ for (uint8 idx = EQEmu::inventory::containerBegin; idx < EQEmu::inventory::ContainerCount; idx++) { const EQEmu::ItemInstance* baginst = src_inst->GetItem(idx); - if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(src_slot_id, idx), baginst)){ - DeleteItemInInventory(Inventory::CalcSlotId(src_slot_id, idx),0,false); + if (baginst && !database.VerifyInventory(account_id, EQEmu::InventoryProfile::CalcSlotId(src_slot_id, idx), baginst)){ + DeleteItemInInventory(EQEmu::InventoryProfile::CalcSlotId(src_slot_id, idx), 0, false); } } } @@ -1533,8 +1533,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if (dst_slot_id >= EQEmu::legacy::SHARED_BANK_BEGIN && dst_slot_id <= EQEmu::legacy::SHARED_BANK_END && dst_inst->IsClassBag()){ for (uint8 idx = EQEmu::inventory::containerBegin; idx < EQEmu::inventory::ContainerCount; idx++) { const EQEmu::ItemInstance* baginst = dst_inst->GetItem(idx); - if(baginst && !database.VerifyInventory(account_id, Inventory::CalcSlotId(dst_slot_id, idx), baginst)){ - DeleteItemInInventory(Inventory::CalcSlotId(dst_slot_id, idx),0,false); + if (baginst && !database.VerifyInventory(account_id, EQEmu::InventoryProfile::CalcSlotId(dst_slot_id, idx), baginst)){ + DeleteItemInInventory(EQEmu::InventoryProfile::CalcSlotId(dst_slot_id, idx), 0, false); } } } @@ -1576,7 +1576,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { if(m_tradeskill_object != nullptr) { if (src_slot_id >= EQEmu::legacy::WORLD_BEGIN && src_slot_id <= EQEmu::legacy::WORLD_END) { // Picking up item from world container - EQEmu::ItemInstance* inst = m_tradeskill_object->PopItem(Inventory::CalcBagIdx(src_slot_id)); + EQEmu::ItemInstance* inst = m_tradeskill_object->PopItem(EQEmu::InventoryProfile::CalcBagIdx(src_slot_id)); if (inst) { PutItemInInventory(dst_slot_id, *inst, false); safe_delete(inst); @@ -1588,7 +1588,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { } else if (dst_slot_id >= EQEmu::legacy::WORLD_BEGIN && dst_slot_id <= EQEmu::legacy::WORLD_END) { // Putting item into world container, which may swap (or pile onto) with existing item - uint8 world_idx = Inventory::CalcBagIdx(dst_slot_id); + uint8 world_idx = EQEmu::InventoryProfile::CalcBagIdx(dst_slot_id); EQEmu::ItemInstance* world_inst = m_tradeskill_object->PopItem(world_idx); // Case 1: No item in container, unidirectional "Put" @@ -1835,7 +1835,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { Message(15, "Inventory Desyncronization detected: Resending slot data..."); if ((move_slots->from_slot >= EQEmu::legacy::EQUIPMENT_BEGIN && move_slots->from_slot <= EQEmu::legacy::CURSOR_BAG_END) || move_slots->from_slot == EQEmu::inventory::slotPowerSource) { - int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); + int16 resync_slot = (EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { // This prevents the client from crashing when closing any 'phantom' bags const EQEmu::ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' @@ -1860,7 +1860,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); } } else { - int16 resync_slot = (Inventory::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : Inventory::CalcSlotId(move_slots->from_slot); + int16 resync_slot = (EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { if(m_inv[resync_slot]) { const EQEmu::ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' @@ -1878,7 +1878,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { } if ((move_slots->to_slot >= EQEmu::legacy::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::legacy::CURSOR_BAG_END) || move_slots->to_slot == EQEmu::inventory::slotPowerSource) { - int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); + int16 resync_slot = (EQEmu::InventoryProfile::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : EQEmu::InventoryProfile::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { const EQEmu::ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' EQEmu::ItemInstance* token_inst = database.CreateItem(token_struct, 1); @@ -1902,7 +1902,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { else { Message(13, "Could not resyncronize destination slot %i.", move_slots->to_slot); } } else { - int16 resync_slot = (Inventory::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : Inventory::CalcSlotId(move_slots->to_slot); + int16 resync_slot = (EQEmu::InventoryProfile::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : EQEmu::InventoryProfile::CalcSlotId(move_slots->to_slot); if (IsValidSlot(resync_slot) && resync_slot != INVALID_INDEX) { if(m_inv[resync_slot]) { const EQEmu::ItemData* token_struct = database.GetItem(22292); // 'Copper Coin' @@ -1963,8 +1963,8 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { const EQEmu::ItemInstance* from_baginst = from_inst->GetItem(bag_idx); if(from_baginst) { - qsaudit->items[move_count].from_slot = Inventory::CalcSlotId(from_slot_id, bag_idx); - qsaudit->items[move_count].to_slot = Inventory::CalcSlotId(to_slot_id, bag_idx); + qsaudit->items[move_count].from_slot = EQEmu::InventoryProfile::CalcSlotId(from_slot_id, bag_idx); + qsaudit->items[move_count].to_slot = EQEmu::InventoryProfile::CalcSlotId(to_slot_id, bag_idx); qsaudit->items[move_count].item_id = from_baginst->GetID(); qsaudit->items[move_count].charges = from_baginst->GetCharges(); qsaudit->items[move_count].aug_1 = from_baginst->GetAugmentItemID(1); @@ -1996,8 +1996,8 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { const EQEmu::ItemInstance* to_baginst = to_inst->GetItem(bag_idx); if(to_baginst) { - qsaudit->items[move_count].from_slot = Inventory::CalcSlotId(to_slot_id, bag_idx); - qsaudit->items[move_count].to_slot = Inventory::CalcSlotId(from_slot_id, bag_idx); + qsaudit->items[move_count].from_slot = EQEmu::InventoryProfile::CalcSlotId(to_slot_id, bag_idx); + qsaudit->items[move_count].to_slot = EQEmu::InventoryProfile::CalcSlotId(from_slot_id, bag_idx); qsaudit->items[move_count].item_id = to_baginst->GetID(); qsaudit->items[move_count].charges = to_baginst->GetCharges(); qsaudit->items[move_count].aug_1 = to_baginst->GetAugmentItemID(1); @@ -2598,7 +2598,7 @@ uint32 Client::GetEquipment(uint8 material_slot) const return 0; } - invslot = Inventory::CalcSlotFromMaterial(material_slot); + invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot); if (invslot == INVALID_INDEX) { return 0; @@ -2956,7 +2956,7 @@ bool Client::MoveItemToInventory(EQEmu::ItemInstance *ItemToReturn, bool UpdateC // if (InvItem && InvItem->IsClassBag()) { - int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); + int16 BaseSlotID = EQEmu::InventoryProfile::CalcSlotId(i, EQEmu::inventory::containerBegin); uint8 BagSize=InvItem->GetItem()->BagSlots; @@ -3006,9 +3006,9 @@ bool Client::MoveItemToInventory(EQEmu::ItemInstance *ItemToReturn, bool UpdateC return true; } - if (InvItem->IsClassBag() && Inventory::CanItemFitInContainer(ItemToReturn->GetItem(), InvItem->GetItem())) { + if (InvItem->IsClassBag() && EQEmu::InventoryProfile::CanItemFitInContainer(ItemToReturn->GetItem(), InvItem->GetItem())) { - int16 BaseSlotID = Inventory::CalcSlotId(i, EQEmu::inventory::containerBegin); + int16 BaseSlotID = EQEmu::InventoryProfile::CalcSlotId(i, EQEmu::inventory::containerBegin); uint8 BagSize=InvItem->GetItem()->BagSlots; @@ -3272,7 +3272,7 @@ bool Client::InterrogateInventory_error(int16 head, int16 index, const EQEmu::It return false; } -void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value) { +void EQEmu::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, std::string value) { EQEmu::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3280,7 +3280,7 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } } -void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value) { +void EQEmu::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, int value) { EQEmu::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3288,7 +3288,7 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } } -void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value) { +void EQEmu::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, float value) { EQEmu::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3296,7 +3296,7 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } } -void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value) { +void EQEmu::InventoryProfile::SetCustomItemData(uint32 character_id, int16 slot_id, std::string identifier, bool value) { EQEmu::ItemInstance *inst = GetItem(slot_id); if(inst) { inst->SetCustomData(identifier, value); @@ -3304,7 +3304,7 @@ void Inventory::SetCustomItemData(uint32 character_id, int16 slot_id, std::strin } } -std::string Inventory::GetCustomItemData(int16 slot_id, std::string identifier) { +std::string EQEmu::InventoryProfile::GetCustomItemData(int16 slot_id, std::string identifier) { EQEmu::ItemInstance *inst = GetItem(slot_id); if(inst) { return inst->GetCustomData(identifier); diff --git a/zone/lua_inventory.h b/zone/lua_inventory.h index ca49a55e6..baaa5d10f 100644 --- a/zone/lua_inventory.h +++ b/zone/lua_inventory.h @@ -4,26 +4,30 @@ #include "lua_ptr.h" -class Inventory; class Lua_ItemInst; class Lua_Item; +namespace EQEmu +{ + class InventoryProfile; +} + namespace luabind { struct scope; } luabind::scope lua_register_inventory(); -class Lua_Inventory : public Lua_Ptr +class Lua_Inventory : public Lua_Ptr { - typedef Inventory NativeType; + typedef EQEmu::InventoryProfile NativeType; public: Lua_Inventory() : Lua_Ptr(nullptr) { } - Lua_Inventory(Inventory *d) : Lua_Ptr(d) { } + Lua_Inventory(EQEmu::InventoryProfile *d) : Lua_Ptr(d) { } virtual ~Lua_Inventory() { } - operator Inventory*() { - return reinterpret_cast(GetLuaPtrData()); + operator EQEmu::InventoryProfile*() { + return reinterpret_cast(GetLuaPtrData()); } Lua_ItemInst GetItem(int slot_id); diff --git a/zone/merc.cpp b/zone/merc.cpp index c45d0c268..6dc00836b 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -5050,7 +5050,7 @@ void Merc::UpdateMercAppearance() { for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { itemID = equipment[i]; if(itemID != 0) { - materialFromSlot = Inventory::CalcMaterialFromSlot(i); + materialFromSlot = EQEmu::InventoryProfile::CalcMaterialFromSlot(i); if (materialFromSlot != EQEmu::textures::materialInvalid) this->SendWearChange(materialFromSlot); } diff --git a/zone/merc.h b/zone/merc.h index ad219a2ec..b563775b0 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -386,7 +386,7 @@ private: uint8 _OwnerClientVersion; uint32 _currentStance; - Inventory m_inv; + EQEmu::InventoryProfile m_inv; int32 max_end; int32 cur_end; bool _medding; diff --git a/zone/mob.cpp b/zone/mob.cpp index dcb9792f2..368d34e1f 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2728,7 +2728,7 @@ uint32 NPC::GetEquipment(uint8 material_slot) const { if(material_slot > 8) return 0; - int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + int16 invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot); if (invslot == INVALID_INDEX) return 0; return equipment[invslot]; @@ -2862,7 +2862,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const { if (this->IsClient()) { - int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + int16 invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot); if (invslot == INVALID_INDEX) { return 0; @@ -2907,7 +2907,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const uint32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); const EQEmu::ItemData *item; item = database.GetItem(GetEquipment(material_slot)); - int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + int16 invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot); if (item != 0 && invslot != INVALID_INDEX) { diff --git a/zone/npc.cpp b/zone/npc.cpp index 166cd33fc..f6e080a26 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -489,7 +489,7 @@ void NPC::CheckMinMaxLevel(Mob *them) if(themlevel < (*cur)->min_level || themlevel > (*cur)->max_level) { - material = Inventory::CalcMaterialFromSlot((*cur)->equip_slot); + material = EQEmu::InventoryProfile::CalcMaterialFromSlot((*cur)->equip_slot); if (material != EQEmu::textures::materialInvalid) SendWearChange(material); @@ -1381,7 +1381,7 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const if (material_slot >= EQEmu::textures::materialCount) return 0; - int16 invslot = Inventory::CalcSlotFromMaterial(material_slot); + int16 invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot); if (invslot == INVALID_INDEX) return 0; diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 8db24d81e..4c8dfdeaf 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -55,7 +55,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme else { // Check to see if they have an inventory container type 53 that is used for this. - Inventory& user_inv = user->GetInv(); + EQEmu::InventoryProfile& user_inv = user->GetInv(); EQEmu::ItemInstance* inst = nullptr; inst = user_inv.GetItem(in_augment->container_slot); @@ -227,7 +227,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme const EQEmu::ItemInstance* inst = container->GetItem(i); if (inst) { - user->DeleteItemInInventory(Inventory::CalcSlotId(in_augment->container_slot,i),0,true); + user->DeleteItemInInventory(EQEmu::InventoryProfile::CalcSlotId(in_augment->container_slot, i), 0, true); } } // Explicitly mark container as cleared. @@ -256,7 +256,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob return; } - Inventory& user_inv = user->GetInv(); + EQEmu::InventoryProfile& user_inv = user->GetInv(); PlayerProfile_Struct& user_pp = user->GetPP(); EQEmu::ItemInstance* container = nullptr; EQEmu::ItemInstance* inst = nullptr; @@ -295,7 +295,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob bool AllowAll = RuleB(Inventory, AllowAnyWeaponTransformation); if (inst && EQEmu::ItemInstance::CanTransform(inst->GetItem(), container->GetItem(), AllowAll)) { const EQEmu::ItemData* new_weapon = inst->GetItem(); - user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); + user->DeleteItemInInventory(EQEmu::InventoryProfile::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::inventory::slotCursor, container->GetItem()->Icon, atoi(container->GetItem()->IDFile + 2)); user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name); @@ -315,7 +315,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob const EQEmu::ItemInstance* inst = container->GetItem(0); if (inst && inst->GetOrnamentationIcon() && inst->GetOrnamentationIcon()) { const EQEmu::ItemData* new_weapon = inst->GetItem(); - user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot, 0), 0, true); + user->DeleteItemInInventory(EQEmu::InventoryProfile::CalcSlotId(in_combine->container_slot, 0), 0, true); container->Clear(); user->SummonItem(new_weapon->ID, inst->GetCharges(), inst->GetAugmentItemID(0), inst->GetAugmentItemID(1), inst->GetAugmentItemID(2), inst->GetAugmentItemID(3), inst->GetAugmentItemID(4), inst->GetAugmentItemID(5), inst->IsAttuned(), EQEmu::inventory::slotCursor, 0, 0); user->Message_StringID(4, TRANSFORM_COMPLETE, inst->GetItem()->Name); @@ -404,7 +404,7 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob for (uint8 i = EQEmu::inventory::slotBegin; i < EQEmu::legacy::TYPE_WORLD_SIZE; i++) { const EQEmu::ItemInstance* inst = container->GetItem(i); if (inst) { - user->DeleteItemInInventory(Inventory::CalcSlotId(in_combine->container_slot,i),0,true); + user->DeleteItemInInventory(EQEmu::InventoryProfile::CalcSlotId(in_combine->container_slot, i), 0, true); } } container->Clear(); @@ -501,7 +501,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac memset(counts, 0, sizeof(counts)); //search for all the items in their inventory - Inventory& user_inv = user->GetInv(); + EQEmu::InventoryProfile& user_inv = user->GetInv(); uint8 count = 0; uint8 needcount = 0; diff --git a/zone/trading.cpp b/zone/trading.cpp index 9d9738ffc..e150ceb12 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -174,7 +174,7 @@ void Trade::SendItemData(const EQEmu::ItemInstance* inst, int16 dest_slot_id) with->SendItemPacket(dest_slot_id - EQEmu::legacy::TRADE_BEGIN, inst, ItemPacketTradeView); if (inst->GetItem()->ItemClass == 1) { for (uint16 i = EQEmu::inventory::containerBegin; i < EQEmu::inventory::ContainerCount; i++) { - uint16 bagslot_id = Inventory::CalcSlotId(dest_slot_id, i); + uint16 bagslot_id = EQEmu::InventoryProfile::CalcSlotId(dest_slot_id, i); const EQEmu::ItemInstance* bagitem = trader->GetInv().GetItem(bagslot_id); if (bagitem) { with->SendItemPacket(bagslot_id - EQEmu::legacy::TRADE_BEGIN, bagitem, ItemPacketTradeView); @@ -317,7 +317,7 @@ void Trade::DumpTrade() if (inst) { Log.Out(Logs::Detail, Logs::Trading, "\tBagItem %i (Charges=%i, Slot=%i)", inst->GetItem()->ID, inst->GetCharges(), - Inventory::CalcSlotId(i, j)); + EQEmu::InventoryProfile::CalcSlotId(i, j)); } } } @@ -530,9 +530,9 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st detail = new QSTradeItems_Struct; detail->from_id = this->character_id; - detail->from_slot = Inventory::CalcSlotId(trade_slot, sub_slot); + detail->from_slot = EQEmu::InventoryProfile::CalcSlotId(trade_slot, sub_slot); detail->to_id = other->CharacterID(); - detail->to_slot = Inventory::CalcSlotId(free_slot, sub_slot); + detail->to_slot = EQEmu::InventoryProfile::CalcSlotId(free_slot, sub_slot); detail->item_id = bag_inst->GetID(); detail->charges = (!bag_inst->IsStackable() ? 1 : bag_inst->GetCharges()); detail->aug_1 = bag_inst->GetAugmentItemID(1); @@ -849,7 +849,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st strcpy(detail->action_type, "HANDIN"); - detail->char_slot = Inventory::CalcSlotId(trade_slot, sub_slot); + detail->char_slot = EQEmu::InventoryProfile::CalcSlotId(trade_slot, sub_slot); detail->item_id = trade_baginst->GetID(); detail->charges = (!trade_inst->IsStackable() ? 1 : trade_inst->GetCharges()); detail->aug_1 = trade_baginst->GetAugmentItemID(1); @@ -1237,7 +1237,7 @@ uint32 Client::FindTraderItemSerialNumber(int32 ItemID) { if (item && item->GetItem()->ID == 17899){ //Traders Satchel for (int x = EQEmu::inventory::containerBegin; x < EQEmu::inventory::ContainerCount; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? - SlotID = Inventory::CalcSlotId(i, x); + SlotID = EQEmu::InventoryProfile::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); if (item) { if (item->GetID() == ItemID) @@ -1260,7 +1260,7 @@ EQEmu::ItemInstance* Client::FindTraderItemBySerialNumber(int32 SerialNumber){ if(item && item->GetItem()->ID == 17899){ //Traders Satchel for (int x = EQEmu::inventory::containerBegin; x < EQEmu::inventory::ContainerCount; x++) { // we already have the parent bag and a contents iterator..why not just iterate the bag!?? - SlotID = Inventory::CalcSlotId(i, x); + SlotID = EQEmu::InventoryProfile::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); if(item) { if(item->GetSerialNumber() == SerialNumber) @@ -1290,7 +1290,7 @@ GetItems_Struct* Client::GetTraderItems(){ item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel for (int x = EQEmu::inventory::containerBegin; x < EQEmu::inventory::ContainerCount; x++) { - SlotID = Inventory::CalcSlotId(i, x); + SlotID = EQEmu::InventoryProfile::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); @@ -1314,7 +1314,7 @@ uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){ item = this->GetInv().GetItem(i); if(item && item->GetItem()->ID == 17899){ //Traders Satchel for (int x = EQEmu::inventory::containerBegin; x < EQEmu::inventory::ContainerCount; x++){ - SlotID = Inventory::CalcSlotId(i, x); + SlotID = EQEmu::InventoryProfile::CalcSlotId(i, x); item = this->GetInv().GetItem(SlotID); diff --git a/zone/zone.cpp b/zone/zone.cpp index 9391b47bb..ab0a9b6e4 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1167,7 +1167,7 @@ bool Zone::Process() { if(spawn2_timer.Check()) { LinkedListIterator iterator(spawn2_list); - Inventory::CleanDirty(); + EQEmu::InventoryProfile::CleanDirty(); iterator.Reset(); while (iterator.MoreElements()) { From 101002d635dbf3ba52ff6951f635be506e797b1d Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 17 Oct 2016 06:32:51 -0400 Subject: [PATCH 405/693] Renamed enum class InventoryVersion to MobVersion --- changelog.txt | 1 + common/emu_versions.cpp | 226 ++++----- common/emu_versions.h | 56 ++- common/eq_limits.cpp | 912 ++++++++++++++++++++++++++++------- common/eq_limits.h | 4 +- common/inventory_profile.cpp | 2 +- common/inventory_profile.h | 21 +- zone/client_mods.cpp | 2 +- zone/corpse.cpp | 4 +- 9 files changed, 886 insertions(+), 342 deletions(-) diff --git a/changelog.txt b/changelog.txt index 1ac1ec731..4b2d029d5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,6 +4,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) Uleat: Moved namespace ItemField from item_instance.h to shareddb.cpp - the only place it is used Uleat: Separated class Inventory from item_instance files into inventory_profile files Uleat: Renamed class Inventory to EQEmu::InventoryProfile +Uleat: Renamed enum class InventoryVersion to MobVersion == 10/16/2016 == Uleat: Renamed struct EQEmu::ItemBase to EQEmu::ItemData and class ItemInst to EQEmu::ItemInstance diff --git a/common/emu_versions.cpp b/common/emu_versions.cpp index 92766e407..ee4970638 100644 --- a/common/emu_versions.cpp +++ b/common/emu_versions.cpp @@ -127,244 +127,244 @@ uint32 EQEmu::versions::ConvertClientVersionToExpansion(ClientVersion client_ver } } -bool EQEmu::versions::IsValidInventoryVersion(InventoryVersion inventory_version) +bool EQEmu::versions::IsValidMobVersion(MobVersion mob_version) { - if (inventory_version <= InventoryVersion::Unknown || inventory_version > LastInventoryVersion) + if (mob_version <= MobVersion::Unknown || mob_version > LastMobVersion) return false; return true; } -bool EQEmu::versions::IsValidPCInventoryVersion(InventoryVersion inventory_version) +bool EQEmu::versions::IsValidPCMobVersion(MobVersion mob_version) { - if (inventory_version <= InventoryVersion::Unknown || inventory_version > LastPCInventoryVersion) + if (mob_version <= MobVersion::Unknown || mob_version > LastPCMobVersion) return false; return true; } -bool EQEmu::versions::IsValidNonPCInventoryVersion(InventoryVersion inventory_version) +bool EQEmu::versions::IsValidNonPCMobVersion(MobVersion mob_version) { - if (inventory_version <= LastPCInventoryVersion || inventory_version > LastNonPCInventoryVersion) + if (mob_version <= LastPCMobVersion || mob_version > LastNonPCMobVersion) return false; return true; } -bool EQEmu::versions::IsValidOfflinePCInventoryVersion(InventoryVersion inventory_version) +bool EQEmu::versions::IsValidOfflinePCMobVersion(MobVersion mob_version) { - if (inventory_version <= LastNonPCInventoryVersion || inventory_version > LastOfflinePCInventoryVersion) + if (mob_version <= LastNonPCMobVersion || mob_version > LastOfflinePCMobVersion) return false; return true; } -EQEmu::versions::InventoryVersion EQEmu::versions::ValidateInventoryVersion(InventoryVersion inventory_version) +EQEmu::versions::MobVersion EQEmu::versions::ValidateMobVersion(MobVersion mob_version) { - if (inventory_version <= InventoryVersion::Unknown || inventory_version > LastInventoryVersion) - return InventoryVersion::Unknown; + if (mob_version <= MobVersion::Unknown || mob_version > LastMobVersion) + return MobVersion::Unknown; - return inventory_version; + return mob_version; } -EQEmu::versions::InventoryVersion EQEmu::versions::ValidatePCInventoryVersion(InventoryVersion inventory_version) +EQEmu::versions::MobVersion EQEmu::versions::ValidatePCMobVersion(MobVersion mob_version) { - if (inventory_version <= InventoryVersion::Unknown || inventory_version > LastPCInventoryVersion) - return InventoryVersion::Unknown; + if (mob_version <= MobVersion::Unknown || mob_version > LastPCMobVersion) + return MobVersion::Unknown; - return inventory_version; + return mob_version; } -EQEmu::versions::InventoryVersion EQEmu::versions::ValidateNonPCInventoryVersion(InventoryVersion inventory_version) +EQEmu::versions::MobVersion EQEmu::versions::ValidateNonPCMobVersion(MobVersion mob_version) { - if (inventory_version <= LastPCInventoryVersion || inventory_version > LastNonPCInventoryVersion) - return InventoryVersion::Unknown; + if (mob_version <= LastPCMobVersion || mob_version > LastNonPCMobVersion) + return MobVersion::Unknown; - return inventory_version; + return mob_version; } -EQEmu::versions::InventoryVersion EQEmu::versions::ValidateOfflinePCInventoryVersion(InventoryVersion inventory_version) +EQEmu::versions::MobVersion EQEmu::versions::ValidateOfflinePCMobVersion(MobVersion mob_version) { - if (inventory_version <= LastNonPCInventoryVersion || inventory_version > LastOfflinePCInventoryVersion) - return InventoryVersion::Unknown; + if (mob_version <= LastNonPCMobVersion || mob_version > LastOfflinePCMobVersion) + return MobVersion::Unknown; - return inventory_version; + return mob_version; } -const char* EQEmu::versions::InventoryVersionName(InventoryVersion inventory_version) +const char* EQEmu::versions::MobVersionName(MobVersion mob_version) { - switch (inventory_version) { - case InventoryVersion::Unknown: + switch (mob_version) { + case MobVersion::Unknown: return "Unknown Version"; - case InventoryVersion::Client62: + case MobVersion::Client62: return "Client 6.2"; - case InventoryVersion::Titanium: + case MobVersion::Titanium: return "Titanium"; - case InventoryVersion::SoF: + case MobVersion::SoF: return "SoF"; - case InventoryVersion::SoD: + case MobVersion::SoD: return "SoD"; - case InventoryVersion::UF: + case MobVersion::UF: return "UF"; - case InventoryVersion::RoF: + case MobVersion::RoF: return "RoF"; - case InventoryVersion::RoF2: + case MobVersion::RoF2: return "RoF2"; - case InventoryVersion::NPC: + case MobVersion::NPC: return "NPC"; - case InventoryVersion::NPCMerchant: + case MobVersion::NPCMerchant: return "NPC Merchant"; - case InventoryVersion::Merc: + case MobVersion::Merc: return "Merc"; - case InventoryVersion::Bot: + case MobVersion::Bot: return "Bot"; - case InventoryVersion::ClientPet: + case MobVersion::ClientPet: return "Client Pet"; - case InventoryVersion::NPCPet: + case MobVersion::NPCPet: return "NPC Pet"; - case InventoryVersion::MercPet: + case MobVersion::MercPet: return "Merc Pet"; - case InventoryVersion::BotPet: + case MobVersion::BotPet: return "Bot Pet"; - case InventoryVersion::OfflineTitanium: + case MobVersion::OfflineTitanium: return "Offline Titanium"; - case InventoryVersion::OfflineSoF: + case MobVersion::OfflineSoF: return "Offline SoF"; - case InventoryVersion::OfflineSoD: + case MobVersion::OfflineSoD: return "Offline SoD"; - case InventoryVersion::OfflineUF: + case MobVersion::OfflineUF: return "Offline UF"; - case InventoryVersion::OfflineRoF: + case MobVersion::OfflineRoF: return "Offline RoF"; - case InventoryVersion::OfflineRoF2: + case MobVersion::OfflineRoF2: return "Offline RoF2"; default: return "Invalid Version"; }; } -EQEmu::versions::ClientVersion EQEmu::versions::ConvertInventoryVersionToClientVersion(InventoryVersion inventory_version) +EQEmu::versions::ClientVersion EQEmu::versions::ConvertMobVersionToClientVersion(MobVersion mob_version) { - switch (inventory_version) { - case InventoryVersion::Unknown: - case InventoryVersion::Client62: + switch (mob_version) { + case MobVersion::Unknown: + case MobVersion::Client62: return ClientVersion::Unknown; - case InventoryVersion::Titanium: + case MobVersion::Titanium: return ClientVersion::Titanium; - case InventoryVersion::SoF: + case MobVersion::SoF: return ClientVersion::SoF; - case InventoryVersion::SoD: + case MobVersion::SoD: return ClientVersion::SoD; - case InventoryVersion::UF: + case MobVersion::UF: return ClientVersion::UF; - case InventoryVersion::RoF: + case MobVersion::RoF: return ClientVersion::RoF; - case InventoryVersion::RoF2: + case MobVersion::RoF2: return ClientVersion::RoF2; default: return ClientVersion::Unknown; } } -EQEmu::versions::InventoryVersion EQEmu::versions::ConvertClientVersionToInventoryVersion(ClientVersion client_version) +EQEmu::versions::MobVersion EQEmu::versions::ConvertClientVersionToMobVersion(ClientVersion client_version) { switch (client_version) { case ClientVersion::Unknown: case ClientVersion::Client62: - return InventoryVersion::Unknown; + return MobVersion::Unknown; case ClientVersion::Titanium: - return InventoryVersion::Titanium; + return MobVersion::Titanium; case ClientVersion::SoF: - return InventoryVersion::SoF; + return MobVersion::SoF; case ClientVersion::SoD: - return InventoryVersion::SoD; + return MobVersion::SoD; case ClientVersion::UF: - return InventoryVersion::UF; + return MobVersion::UF; case ClientVersion::RoF: - return InventoryVersion::RoF; + return MobVersion::RoF; case ClientVersion::RoF2: - return InventoryVersion::RoF2; + return MobVersion::RoF2; default: - return InventoryVersion::Unknown; + return MobVersion::Unknown; } } -EQEmu::versions::InventoryVersion EQEmu::versions::ConvertPCInventoryVersionToOfflinePCInventoryVersion(InventoryVersion inventory_version) +EQEmu::versions::MobVersion EQEmu::versions::ConvertPCMobVersionToOfflinePCMobVersion(MobVersion mob_version) { - switch (inventory_version) { - case InventoryVersion::Titanium: - return InventoryVersion::OfflineTitanium; - case InventoryVersion::SoF: - return InventoryVersion::OfflineSoF; - case InventoryVersion::SoD: - return InventoryVersion::OfflineSoD; - case InventoryVersion::UF: - return InventoryVersion::OfflineUF; - case InventoryVersion::RoF: - return InventoryVersion::OfflineRoF; - case InventoryVersion::RoF2: - return InventoryVersion::OfflineRoF2; + switch (mob_version) { + case MobVersion::Titanium: + return MobVersion::OfflineTitanium; + case MobVersion::SoF: + return MobVersion::OfflineSoF; + case MobVersion::SoD: + return MobVersion::OfflineSoD; + case MobVersion::UF: + return MobVersion::OfflineUF; + case MobVersion::RoF: + return MobVersion::OfflineRoF; + case MobVersion::RoF2: + return MobVersion::OfflineRoF2; default: - return InventoryVersion::Unknown; + return MobVersion::Unknown; } } -EQEmu::versions::InventoryVersion EQEmu::versions::ConvertOfflinePCInventoryVersionToPCInventoryVersion(InventoryVersion inventory_version) +EQEmu::versions::MobVersion EQEmu::versions::ConvertOfflinePCMobVersionToPCMobVersion(MobVersion mob_version) { - switch (inventory_version) { - case InventoryVersion::OfflineTitanium: - return InventoryVersion::Titanium; - case InventoryVersion::OfflineSoF: - return InventoryVersion::SoF; - case InventoryVersion::OfflineSoD: - return InventoryVersion::SoD; - case InventoryVersion::OfflineUF: - return InventoryVersion::UF; - case InventoryVersion::OfflineRoF: - return InventoryVersion::RoF; - case InventoryVersion::OfflineRoF2: - return InventoryVersion::RoF2; + switch (mob_version) { + case MobVersion::OfflineTitanium: + return MobVersion::Titanium; + case MobVersion::OfflineSoF: + return MobVersion::SoF; + case MobVersion::OfflineSoD: + return MobVersion::SoD; + case MobVersion::OfflineUF: + return MobVersion::UF; + case MobVersion::OfflineRoF: + return MobVersion::RoF; + case MobVersion::OfflineRoF2: + return MobVersion::RoF2; default: - return InventoryVersion::Unknown; + return MobVersion::Unknown; } } -EQEmu::versions::ClientVersion EQEmu::versions::ConvertOfflinePCInventoryVersionToClientVersion(InventoryVersion inventory_version) +EQEmu::versions::ClientVersion EQEmu::versions::ConvertOfflinePCMobVersionToClientVersion(MobVersion mob_version) { - switch (inventory_version) { - case InventoryVersion::OfflineTitanium: + switch (mob_version) { + case MobVersion::OfflineTitanium: return ClientVersion::Titanium; - case InventoryVersion::OfflineSoF: + case MobVersion::OfflineSoF: return ClientVersion::SoF; - case InventoryVersion::OfflineSoD: + case MobVersion::OfflineSoD: return ClientVersion::SoD; - case InventoryVersion::OfflineUF: + case MobVersion::OfflineUF: return ClientVersion::UF; - case InventoryVersion::OfflineRoF: + case MobVersion::OfflineRoF: return ClientVersion::RoF; - case InventoryVersion::OfflineRoF2: + case MobVersion::OfflineRoF2: return ClientVersion::RoF2; default: return ClientVersion::Unknown; } } -EQEmu::versions::InventoryVersion EQEmu::versions::ConvertClientVersionToOfflinePCInventoryVersion(ClientVersion client_version) +EQEmu::versions::MobVersion EQEmu::versions::ConvertClientVersionToOfflinePCMobVersion(ClientVersion client_version) { switch (client_version) { case ClientVersion::Titanium: - return InventoryVersion::OfflineTitanium; + return MobVersion::OfflineTitanium; case ClientVersion::SoF: - return InventoryVersion::OfflineSoF; + return MobVersion::OfflineSoF; case ClientVersion::SoD: - return InventoryVersion::OfflineSoD; + return MobVersion::OfflineSoD; case ClientVersion::UF: - return InventoryVersion::OfflineUF; + return MobVersion::OfflineUF; case ClientVersion::RoF: - return InventoryVersion::OfflineRoF; + return MobVersion::OfflineRoF; case ClientVersion::RoF2: - return InventoryVersion::OfflineRoF2; + return MobVersion::OfflineRoF2; default: - return InventoryVersion::Unknown; + return MobVersion::Unknown; } } diff --git a/common/emu_versions.h b/common/emu_versions.h index 8a806e8fc..9d9e1f580 100644 --- a/common/emu_versions.h +++ b/common/emu_versions.h @@ -64,17 +64,15 @@ namespace EQEmu const ClientVersion LastClientVersion = ClientVersion::RoF2; const size_t ClientVersionCount = (static_cast(LastClientVersion) + 1); - extern bool IsValidClientVersion(ClientVersion client_version); - extern ClientVersion ValidateClientVersion(ClientVersion client_version); - extern const char* ClientVersionName(ClientVersion client_version); - extern uint32 ConvertClientVersionToClientVersionBit(ClientVersion client_version); - extern ClientVersion ConvertClientVersionBitToClientVersion(uint32 client_version_bit); - extern uint32 ConvertClientVersionToExpansion(ClientVersion client_version); + bool IsValidClientVersion(ClientVersion client_version); + ClientVersion ValidateClientVersion(ClientVersion client_version); + const char* ClientVersionName(ClientVersion client_version); + uint32 ConvertClientVersionToClientVersionBit(ClientVersion client_version); + ClientVersion ConvertClientVersionBitToClientVersion(uint32 client_version_bit); + uint32 ConvertClientVersionToExpansion(ClientVersion client_version); - } /*versions*/ - namespace versions { - enum class InventoryVersion { + enum class MobVersion { Unknown = 0, Client62, Titanium, @@ -99,29 +97,29 @@ namespace EQEmu OfflineRoF2 }; - const InventoryVersion LastInventoryVersion = InventoryVersion::OfflineRoF2; - const InventoryVersion LastPCInventoryVersion = InventoryVersion::RoF2; - const InventoryVersion LastNonPCInventoryVersion = InventoryVersion::BotPet; - const InventoryVersion LastOfflinePCInventoryVersion = InventoryVersion::OfflineRoF2; - const size_t InventoryVersionCount = (static_cast(LastInventoryVersion) + 1); + const MobVersion LastMobVersion = MobVersion::OfflineRoF2; + const MobVersion LastPCMobVersion = MobVersion::RoF2; + const MobVersion LastNonPCMobVersion = MobVersion::BotPet; + const MobVersion LastOfflinePCMobVersion = MobVersion::OfflineRoF2; + const size_t MobVersionCount = (static_cast(LastMobVersion) + 1); - extern bool IsValidInventoryVersion(InventoryVersion inventory_version); - extern bool IsValidPCInventoryVersion(InventoryVersion inventory_version); - extern bool IsValidNonPCInventoryVersion(InventoryVersion inventory_version); - extern bool IsValidOfflinePCInventoryVersion(InventoryVersion inventory_version); + bool IsValidMobVersion(MobVersion mob_version); + bool IsValidPCMobVersion(MobVersion mob_version); + bool IsValidNonPCMobVersion(MobVersion mob_version); + bool IsValidOfflinePCMobVersion(MobVersion mob_version); - extern InventoryVersion ValidateInventoryVersion(InventoryVersion inventory_version); - extern InventoryVersion ValidatePCInventoryVersion(InventoryVersion inventory_version); - extern InventoryVersion ValidateNonPCInventoryVersion(InventoryVersion inventory_version); - extern InventoryVersion ValidateOfflinePCInventoryVersion(InventoryVersion inventory_version); + MobVersion ValidateMobVersion(MobVersion mob_version); + MobVersion ValidatePCMobVersion(MobVersion mob_version); + MobVersion ValidateNonPCMobVersion(MobVersion mob_version); + MobVersion ValidateOfflinePCMobVersion(MobVersion mob_version); - extern const char* InventoryVersionName(InventoryVersion inventory_version); - extern ClientVersion ConvertInventoryVersionToClientVersion(InventoryVersion inventory_version); - extern InventoryVersion ConvertClientVersionToInventoryVersion(ClientVersion client_version); - extern InventoryVersion ConvertPCInventoryVersionToOfflinePCInventoryVersion(InventoryVersion inventory_version); - extern InventoryVersion ConvertOfflinePCInventoryVersionToPCInventoryVersion(InventoryVersion inventory_version); - extern ClientVersion ConvertOfflinePCInventoryVersionToClientVersion(InventoryVersion inventory_version); - extern InventoryVersion ConvertClientVersionToOfflinePCInventoryVersion(ClientVersion client_version); + const char* MobVersionName(MobVersion mob_version); + ClientVersion ConvertMobVersionToClientVersion(MobVersion mob_version); + MobVersion ConvertClientVersionToMobVersion(ClientVersion client_version); + MobVersion ConvertPCMobVersionToOfflinePCMobVersion(MobVersion mob_version); + MobVersion ConvertOfflinePCMobVersionToPCMobVersion(MobVersion mob_version); + ClientVersion ConvertOfflinePCMobVersionToClientVersion(MobVersion mob_version); + MobVersion ConvertClientVersionToOfflinePCMobVersion(ClientVersion client_version); } /*versions*/ diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 9f960557c..1c0140811 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -23,28 +23,28 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versions::ClientVersionCount] = { - { // Unknown + { ClientUnknown::Null }, - { // Client62 + { Client62::Null }, - { // Titanium + { Titanium::constants::CharacterCreationLimit }, - { // SoF + { SoF::constants::CharacterCreationLimit }, - { // SoD + { SoD::constants::CharacterCreationLimit }, - { // UF + { UF::constants::CharacterCreationLimit }, - { // RoF + { RoF::constants::CharacterCreationLimit }, - { // RoF2 + { RoF2::constants::CharacterCreationLimit } }; @@ -54,258 +54,804 @@ const EQEmu::constants::LookupEntry* EQEmu::constants::Lookup(versions::ClientVe return &constants_lookup_entries[static_cast(versions::ValidateClientVersion(client_version))]; } -static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versions::InventoryVersionCount] = +static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versions::MobVersionCount] = { - { // Unknown - ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, - ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, - ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, - ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, - ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, + { + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, - ClientUnknown::Null, ClientUnknown::Null, ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, - ClientUnknown::False, ClientUnknown::False, ClientUnknown::False, ClientUnknown::False + ClientUnknown::False, + ClientUnknown::False, + ClientUnknown::False, + ClientUnknown::False }, - { // Client62 - Client62::Null, Client62::Null, Client62::Null, Client62::Null, Client62::Null, - Client62::Null, Client62::Null, Client62::Null, Client62::Null, Client62::Null, - Client62::Null, Client62::Null, Client62::Null, Client62::Null, Client62::Null, - Client62::Null, Client62::Null, Client62::Null, Client62::Null, Client62::Null, - Client62::Null, Client62::Null, Client62::Null, Client62::Null, Client62::Null, + { + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, - Client62::Null, Client62::Null, Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, - Client62::False, Client62::False, Client62::False, Client62::False + Client62::False, + Client62::False, + Client62::False, + Client62::False }, - { // Titanium - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*Titanium::invtype::InvTypePossessionsSize,*/ Titanium::invtype::InvTypeBankSize, Titanium::invtype::InvTypeSharedBankSize, Titanium::invtype::InvTypeTradeSize, Titanium::invtype::InvTypeWorldSize, - Titanium::invtype::InvTypeLimboSize, Titanium::invtype::InvTypeTributeSize, Titanium::Null, Titanium::Null, /*Titanium::invtype::InvTypeGuildTributeSize,*/ Titanium::invtype::InvTypeMerchantSize, - Titanium::Null, Titanium::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*Titanium::invtype::InvTypeBazaarSize,*/ Titanium::invtype::InvTypeInspectSize, Titanium::Null, - Titanium::invtype::InvTypeViewMODPCSize, Titanium::invtype::InvTypeViewMODBankSize, Titanium::invtype::InvTypeViewMODSharedBankSize, Titanium::invtype::InvTypeViewMODLimboSize, Titanium::invtype::InvTypeAltStorageSize, - Titanium::invtype::InvTypeArchivedSize, Titanium::Null, Titanium::Null, Titanium::Null, Titanium::invtype::InvTypeOtherSize, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*Titanium::invtype::InvTypePossessionsSize,*/ + Titanium::invtype::InvTypeBankSize, + Titanium::invtype::InvTypeSharedBankSize, + Titanium::invtype::InvTypeTradeSize, + Titanium::invtype::InvTypeWorldSize, + Titanium::invtype::InvTypeLimboSize, + Titanium::invtype::InvTypeTributeSize, + Titanium::Null, + Titanium::Null, /*Titanium::invtype::InvTypeGuildTributeSize,*/ + Titanium::invtype::InvTypeMerchantSize, + Titanium::Null, + Titanium::invtype::InvTypeCorpseSize, + EQEmu::legacy::TYPE_BAZAAR_SIZE, /*Titanium::invtype::InvTypeBazaarSize,*/ + Titanium::invtype::InvTypeInspectSize, + Titanium::Null, + Titanium::invtype::InvTypeViewMODPCSize, + Titanium::invtype::InvTypeViewMODBankSize, + Titanium::invtype::InvTypeViewMODSharedBankSize, + Titanium::invtype::InvTypeViewMODLimboSize, + Titanium::invtype::InvTypeAltStorageSize, + Titanium::invtype::InvTypeArchivedSize, + Titanium::Null, + Titanium::Null, + Titanium::Null, + Titanium::invtype::InvTypeOtherSize, - Titanium::Null, /*0x000000027FDFFFFF,*/ EQEmu::inventory::ContainerCount, /*Titanium::invbag::ItemBagSize,*/ EQEmu::inventory::SocketCount, /*Titanium::invaug::ItemAugSize,*/ + Titanium::Null, /*0x000000027FDFFFFF,*/ + EQEmu::inventory::ContainerCount, /*Titanium::invbag::ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*Titanium::invaug::ItemAugSize,*/ - Titanium::inventory::AllowEmptyBagInBag, Titanium::inventory::AllowClickCastFromBag, Titanium::inventory::ConcatenateInvTypeLimbo, Titanium::inventory::AllowOverLevelEquipment + Titanium::inventory::AllowEmptyBagInBag, + Titanium::inventory::AllowClickCastFromBag, + Titanium::inventory::ConcatenateInvTypeLimbo, + Titanium::inventory::AllowOverLevelEquipment }, - { // SoF - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*SoF::invtype::InvTypePossessionsSize,*/ SoF::invtype::InvTypeBankSize, SoF::invtype::InvTypeSharedBankSize, SoF::invtype::InvTypeTradeSize, SoF::invtype::InvTypeWorldSize, - SoF::invtype::InvTypeLimboSize, SoF::invtype::InvTypeTributeSize, SoF::Null, SoF::Null, /*SoF::invtype::InvTypeGuildTributeSize,*/ SoF::invtype::InvTypeMerchantSize, - SoF::Null, SoF::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*SoF::invtype::InvTypeBazaarSize,*/ SoF::invtype::InvTypeInspectSize, SoF::Null, - SoF::invtype::InvTypeViewMODPCSize, SoF::invtype::InvTypeViewMODBankSize, SoF::invtype::InvTypeViewMODSharedBankSize, SoF::invtype::InvTypeViewMODLimboSize, SoF::invtype::InvTypeAltStorageSize, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*SoF::invtype::InvTypePossessionsSize,*/ + SoF::invtype::InvTypeBankSize, + SoF::invtype::InvTypeSharedBankSize, + SoF::invtype::InvTypeTradeSize, + SoF::invtype::InvTypeWorldSize, + SoF::invtype::InvTypeLimboSize, + SoF::invtype::InvTypeTributeSize, + SoF::Null, + SoF::Null, /*SoF::invtype::InvTypeGuildTributeSize,*/ + SoF::invtype::InvTypeMerchantSize, + SoF::Null, + SoF::invtype::InvTypeCorpseSize, + EQEmu::legacy::TYPE_BAZAAR_SIZE, /*SoF::invtype::InvTypeBazaarSize,*/ + SoF::invtype::InvTypeInspectSize, + SoF::Null, + SoF::invtype::InvTypeViewMODPCSize, + SoF::invtype::InvTypeViewMODBankSize, + SoF::invtype::InvTypeViewMODSharedBankSize, + SoF::invtype::InvTypeViewMODLimboSize, + SoF::invtype::InvTypeAltStorageSize, SoF::invtype::InvTypeArchivedSize, SoF::Null, SoF::Null, SoF::Null, SoF::invtype::InvTypeOtherSize, - SoF::Null, /*0x000000027FFFFFFF,*/ EQEmu::inventory::ContainerCount, /*SoF::invbag::ItemBagSize,*/ EQEmu::inventory::SocketCount, /*SoF::invaug::ItemAugSize,*/ + SoF::Null, /*0x000000027FFFFFFF,*/ + EQEmu::inventory::ContainerCount, /*SoF::invbag::ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*SoF::invaug::ItemAugSize,*/ - SoF::inventory::AllowEmptyBagInBag, SoF::inventory::AllowClickCastFromBag, SoF::inventory::ConcatenateInvTypeLimbo, SoF::inventory::AllowOverLevelEquipment + SoF::inventory::AllowEmptyBagInBag, + SoF::inventory::AllowClickCastFromBag, + SoF::inventory::ConcatenateInvTypeLimbo, + SoF::inventory::AllowOverLevelEquipment }, - { // SoD - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*SoD::invtype::InvTypePossessionsSize,*/ SoD::invtype::InvTypeBankSize, SoD::invtype::InvTypeSharedBankSize, SoD::invtype::InvTypeTradeSize, SoD::invtype::InvTypeWorldSize, - SoD::invtype::InvTypeLimboSize, SoD::invtype::InvTypeTributeSize, SoD::Null, SoD::Null, /*SoD::invtype::InvTypeGuildTributeSize,*/ SoD::invtype::InvTypeMerchantSize, - SoD::Null, SoD::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*SoD::invtype::InvTypeBazaarSize,*/ SoD::invtype::InvTypeInspectSize, SoD::Null, - SoD::invtype::InvTypeViewMODPCSize, SoD::invtype::InvTypeViewMODBankSize, SoD::invtype::InvTypeViewMODSharedBankSize, SoD::invtype::InvTypeViewMODLimboSize, SoD::invtype::InvTypeAltStorageSize, - SoD::invtype::InvTypeArchivedSize, SoD::Null, SoD::Null, SoD::Null, SoD::invtype::InvTypeOtherSize, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*SoD::invtype::InvTypePossessionsSize,*/ + SoD::invtype::InvTypeBankSize, + SoD::invtype::InvTypeSharedBankSize, + SoD::invtype::InvTypeTradeSize, + SoD::invtype::InvTypeWorldSize, + SoD::invtype::InvTypeLimboSize, + SoD::invtype::InvTypeTributeSize, + SoD::Null, + SoD::Null, /*SoD::invtype::InvTypeGuildTributeSize,*/ + SoD::invtype::InvTypeMerchantSize, + SoD::Null, + SoD::invtype::InvTypeCorpseSize, + EQEmu::legacy::TYPE_BAZAAR_SIZE, /*SoD::invtype::InvTypeBazaarSize,*/ + SoD::invtype::InvTypeInspectSize, + SoD::Null, + SoD::invtype::InvTypeViewMODPCSize, + SoD::invtype::InvTypeViewMODBankSize, + SoD::invtype::InvTypeViewMODSharedBankSize, + SoD::invtype::InvTypeViewMODLimboSize, + SoD::invtype::InvTypeAltStorageSize, + SoD::invtype::InvTypeArchivedSize, + SoD::Null, + SoD::Null, + SoD::Null, + SoD::invtype::InvTypeOtherSize, - SoD::Null, /*0x000000027FFFFFFF,*/ EQEmu::inventory::ContainerCount, /*SoD::invbag::ItemBagSize,*/ EQEmu::inventory::SocketCount, /*SoD::invaug::ItemAugSize,*/ + SoD::Null, /*0x000000027FFFFFFF,*/ + EQEmu::inventory::ContainerCount, /*SoD::invbag::ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*SoD::invaug::ItemAugSize,*/ - SoD::inventory::AllowEmptyBagInBag, SoD::inventory::AllowClickCastFromBag, SoD::inventory::ConcatenateInvTypeLimbo, SoD::inventory::AllowOverLevelEquipment + SoD::inventory::AllowEmptyBagInBag, + SoD::inventory::AllowClickCastFromBag, + SoD::inventory::ConcatenateInvTypeLimbo, + SoD::inventory::AllowOverLevelEquipment }, - { // UF - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*UF::invtype::InvTypePossessionsSize,*/ UF::invtype::InvTypeBankSize, UF::invtype::InvTypeSharedBankSize, UF::invtype::InvTypeTradeSize, UF::invtype::InvTypeWorldSize, - UF::invtype::InvTypeLimboSize, UF::invtype::InvTypeTributeSize, UF::Null, UF::Null, /*UF::invtype::InvTypeGuildTributeSize,*/ UF::invtype::InvTypeMerchantSize, - UF::Null, UF::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*UF::invtype::InvTypeBazaarSize,*/ UF::invtype::InvTypeInspectSize, UF::Null, - UF::invtype::InvTypeViewMODPCSize, UF::invtype::InvTypeViewMODBankSize, UF::invtype::InvTypeViewMODSharedBankSize, UF::invtype::InvTypeViewMODLimboSize, UF::invtype::InvTypeAltStorageSize, - UF::invtype::InvTypeArchivedSize, UF::Null, UF::Null, UF::Null, UF::invtype::InvTypeOtherSize, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*UF::invtype::InvTypePossessionsSize,*/ + UF::invtype::InvTypeBankSize, + UF::invtype::InvTypeSharedBankSize, + UF::invtype::InvTypeTradeSize, + UF::invtype::InvTypeWorldSize, + UF::invtype::InvTypeLimboSize, + UF::invtype::InvTypeTributeSize, + UF::Null, + UF::Null, /*UF::invtype::InvTypeGuildTributeSize,*/ + UF::invtype::InvTypeMerchantSize, + UF::Null, + UF::invtype::InvTypeCorpseSize, + EQEmu::legacy::TYPE_BAZAAR_SIZE, /*UF::invtype::InvTypeBazaarSize,*/ + UF::invtype::InvTypeInspectSize, + UF::Null, + UF::invtype::InvTypeViewMODPCSize, + UF::invtype::InvTypeViewMODBankSize, + UF::invtype::InvTypeViewMODSharedBankSize, + UF::invtype::InvTypeViewMODLimboSize, + UF::invtype::InvTypeAltStorageSize, + UF::invtype::InvTypeArchivedSize, + UF::Null, + UF::Null, + UF::Null, + UF::invtype::InvTypeOtherSize, - UF::Null, /*0x000000027FFFFFFF,*/ EQEmu::inventory::ContainerCount, /*UF::invbag::ItemBagSize,*/ EQEmu::inventory::SocketCount, /*UF::invaug::ItemAugSize,*/ + UF::Null, /*0x000000027FFFFFFF,*/ + EQEmu::inventory::ContainerCount, /*UF::invbag::ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*UF::invaug::ItemAugSize,*/ - UF::inventory::AllowEmptyBagInBag, UF::inventory::AllowClickCastFromBag, UF::inventory::ConcatenateInvTypeLimbo, UF::inventory::AllowOverLevelEquipment + UF::inventory::AllowEmptyBagInBag, + UF::inventory::AllowClickCastFromBag, + UF::inventory::ConcatenateInvTypeLimbo, + UF::inventory::AllowOverLevelEquipment }, - { // RoF - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*RoF::invtype::InvTypePossessionsSize,*/ RoF::invtype::InvTypeBankSize, RoF::invtype::InvTypeSharedBankSize, RoF::invtype::InvTypeTradeSize, RoF::invtype::InvTypeWorldSize, - RoF::invtype::InvTypeLimboSize, RoF::invtype::InvTypeTributeSize, RoF::Null, /*RoF::invtype::InvTypeTrophyTributeSize,*/ RoF::Null, /*RoF::invtype::InvTypeGuildTributeSize,*/ RoF::invtype::InvTypeMerchantSize, - RoF::Null, /*RoF::invtype::InvTypeDeletedSize,*/ RoF::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*RoF::invtype::InvTypeBazaarSize,*/ RoF::invtype::InvTypeInspectSize, RoF::Null, /*RoF::invtype::InvTypeRealEstateSize,*/ - RoF::invtype::InvTypeViewMODPCSize, RoF::invtype::InvTypeViewMODBankSize, RoF::invtype::InvTypeViewMODSharedBankSize, RoF::invtype::InvTypeViewMODLimboSize, RoF::invtype::InvTypeAltStorageSize, - RoF::invtype::InvTypeArchivedSize, RoF::invtype::InvTypeMailSize, RoF::invtype::InvTypeGuildTrophyTributeSize, RoF::Null, RoF::invtype::InvTypeOtherSize, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*RoF::invtype::InvTypePossessionsSize,*/ + RoF::invtype::InvTypeBankSize, + RoF::invtype::InvTypeSharedBankSize, + RoF::invtype::InvTypeTradeSize, + RoF::invtype::InvTypeWorldSize, + RoF::invtype::InvTypeLimboSize, + RoF::invtype::InvTypeTributeSize, + RoF::Null, /*RoF::invtype::InvTypeTrophyTributeSize,*/ + RoF::Null, /*RoF::invtype::InvTypeGuildTributeSize,*/ + RoF::invtype::InvTypeMerchantSize, + RoF::Null, /*RoF::invtype::InvTypeDeletedSize,*/ + RoF::invtype::InvTypeCorpseSize, + EQEmu::legacy::TYPE_BAZAAR_SIZE, /*RoF::invtype::InvTypeBazaarSize,*/ + RoF::invtype::InvTypeInspectSize, + RoF::Null, /*RoF::invtype::InvTypeRealEstateSize,*/ + RoF::invtype::InvTypeViewMODPCSize, + RoF::invtype::InvTypeViewMODBankSize, + RoF::invtype::InvTypeViewMODSharedBankSize, + RoF::invtype::InvTypeViewMODLimboSize, + RoF::invtype::InvTypeAltStorageSize, + RoF::invtype::InvTypeArchivedSize, + RoF::invtype::InvTypeMailSize, + RoF::invtype::InvTypeGuildTrophyTributeSize, + RoF::Null, + RoF::invtype::InvTypeOtherSize, - RoF::Null, /*0x00000003FFFFFFFF,*/ EQEmu::inventory::ContainerCount, /*RoF::invbag::ItemBagSize,*/ EQEmu::inventory::SocketCount, /*RoF::invaug::ItemAugSize,*/ + RoF::Null, /*0x00000003FFFFFFFF,*/ + EQEmu::inventory::ContainerCount, /*RoF::invbag::ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*RoF::invaug::ItemAugSize,*/ - RoF::False, /*RoF::inventory::AllowEmptyBagInBag,*/ RoF::inventory::AllowClickCastFromBag, RoF::inventory::ConcatenateInvTypeLimbo, RoF::inventory::AllowOverLevelEquipment + RoF::False, /*RoF::inventory::AllowEmptyBagInBag,*/ + RoF::inventory::AllowClickCastFromBag, + RoF::inventory::ConcatenateInvTypeLimbo, + RoF::inventory::AllowOverLevelEquipment }, - { // RoF2 - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*RoF2::invtype::InvTypePossessionsSize,*/ RoF2::invtype::InvTypeBankSize, RoF2::invtype::InvTypeSharedBankSize, RoF2::invtype::InvTypeTradeSize, RoF2::invtype::InvTypeWorldSize, - RoF2::invtype::InvTypeLimboSize, RoF2::invtype::InvTypeTributeSize, RoF2::Null, /*RoF2::invtype::InvTypeTrophyTributeSize,*/ RoF2::Null, /*RoF2::invtype::InvTypeGuildTributeSize,*/ RoF2::invtype::InvTypeMerchantSize, - RoF2::Null, /*RoF2::invtype::InvTypeDeletedSize,*/ RoF2::invtype::InvTypeCorpseSize, EQEmu::legacy::TYPE_BAZAAR_SIZE, /*RoF2::invtype::InvTypeBazaarSize,*/ RoF2::invtype::InvTypeInspectSize, RoF2::Null, /*RoF2::invtype::InvTypeRealEstateSize*/ - RoF2::invtype::InvTypeViewMODPCSize, RoF2::invtype::InvTypeViewMODBankSize, RoF2::invtype::InvTypeViewMODSharedBankSize, RoF2::invtype::InvTypeViewMODLimboSize, RoF2::invtype::InvTypeAltStorageSize, - RoF2::invtype::InvTypeArchivedSize, RoF2::invtype::InvTypeMailSize, RoF2::invtype::InvTypeGuildTrophyTributeSize, RoF2::invtype::InvTypeKronoSize, RoF2::invtype::InvTypeOtherSize, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*RoF2::invtype::InvTypePossessionsSize,*/ + RoF2::invtype::InvTypeBankSize, + RoF2::invtype::InvTypeSharedBankSize, + RoF2::invtype::InvTypeTradeSize, + RoF2::invtype::InvTypeWorldSize, + RoF2::invtype::InvTypeLimboSize, + RoF2::invtype::InvTypeTributeSize, + RoF2::Null, /*RoF2::invtype::InvTypeTrophyTributeSize,*/ + RoF2::Null, /*RoF2::invtype::InvTypeGuildTributeSize,*/ + RoF2::invtype::InvTypeMerchantSize, + RoF2::Null, /*RoF2::invtype::InvTypeDeletedSize,*/ + RoF2::invtype::InvTypeCorpseSize, + EQEmu::legacy::TYPE_BAZAAR_SIZE, /*RoF2::invtype::InvTypeBazaarSize,*/ + RoF2::invtype::InvTypeInspectSize, + RoF2::Null, /*RoF2::invtype::InvTypeRealEstateSize*/ + RoF2::invtype::InvTypeViewMODPCSize, + RoF2::invtype::InvTypeViewMODBankSize, + RoF2::invtype::InvTypeViewMODSharedBankSize, + RoF2::invtype::InvTypeViewMODLimboSize, + RoF2::invtype::InvTypeAltStorageSize, + RoF2::invtype::InvTypeArchivedSize, + RoF2::invtype::InvTypeMailSize, + RoF2::invtype::InvTypeGuildTrophyTributeSize, + RoF2::invtype::InvTypeKronoSize, + RoF2::invtype::InvTypeOtherSize, - RoF2::Null, /*0x00000003FFFFFFFF,*/ EQEmu::inventory::ContainerCount, /*RoF2::invbag::ItemBagSize,*/ EQEmu::inventory::SocketCount, /*RoF2::invaug::ItemAugSize,*/ + RoF2::Null, /*0x00000003FFFFFFFF,*/ + EQEmu::inventory::ContainerCount, /*RoF2::invbag::ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*RoF2::invaug::ItemAugSize,*/ - RoF2::False, /*RoF2::inventory::AllowEmptyBagInBag,*/ RoF2::inventory::AllowClickCastFromBag, RoF2::inventory::ConcatenateInvTypeLimbo, RoF2::inventory::AllowOverLevelEquipment + RoF2::False, /*RoF2::inventory::AllowEmptyBagInBag,*/ + RoF2::inventory::AllowClickCastFromBag, + RoF2::inventory::ConcatenateInvTypeLimbo, + RoF2::inventory::AllowOverLevelEquipment }, - { // NPC - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::InvTypeTradeSize, EntityLimits::NPC::Null, - EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, - EntityLimits::NPC::Null, EntityLimits::NPC::Null, /*InvTypeCorpseSize,*/ EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, - EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, - EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, EntityLimits::NPC::Null, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::InvTypeTradeSize, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, /*InvTypeCorpseSize,*/ + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, + EntityLimits::NPC::Null, - EntityLimits::NPC::Null, EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ EQEmu::inventory::SocketCount, /*ItemAugSize,*/ + EntityLimits::NPC::Null, + EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*ItemAugSize,*/ - EntityLimits::NPC::False, EntityLimits::NPC::False, EntityLimits::NPC::False, EntityLimits::NPC::False + EntityLimits::NPC::False, + EntityLimits::NPC::False, + EntityLimits::NPC::False, + EntityLimits::NPC::False }, - { // NPCMerchant - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::InvTypeTradeSize, EntityLimits::NPCMerchant::Null, - EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, - EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, /*InvTypeCorpseSize,*/ EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, - EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, - EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, EntityLimits::NPCMerchant::Null, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::InvTypeTradeSize, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, /*InvTypeCorpseSize,*/ + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, + EntityLimits::NPCMerchant::Null, - EntityLimits::NPCMerchant::Null, EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ EQEmu::inventory::SocketCount, /*ItemAugSize,*/ + EntityLimits::NPCMerchant::Null, + EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*ItemAugSize,*/ - EntityLimits::NPCMerchant::False, EntityLimits::NPCMerchant::False, EntityLimits::NPCMerchant::False, EntityLimits::NPCMerchant::False + EntityLimits::NPCMerchant::False, + EntityLimits::NPCMerchant::False, + EntityLimits::NPCMerchant::False, + EntityLimits::NPCMerchant::False }, - { // Merc - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::InvTypeTradeSize, EntityLimits::Merc::Null, - EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, - EntityLimits::Merc::Null, EntityLimits::Merc::Null, /*InvTypeCorpseSize,*/ EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, - EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, - EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, EntityLimits::Merc::Null, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::InvTypeTradeSize, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, /*InvTypeCorpseSize,*/ + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, + EntityLimits::Merc::Null, - EntityLimits::Merc::Null, EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ EQEmu::inventory::SocketCount, /*ItemAugSize,*/ + EntityLimits::Merc::Null, + EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*ItemAugSize,*/ - EntityLimits::Merc::False, EntityLimits::Merc::False, EntityLimits::Merc::False, EntityLimits::Merc::False + EntityLimits::Merc::False, + EntityLimits::Merc::False, + EntityLimits::Merc::False, + EntityLimits::Merc::False }, - { // Bot - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::InvTypeTradeSize, EntityLimits::Bot::Null, - EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, - EntityLimits::Bot::Null, EntityLimits::Bot::Null, /*InvTypeCorpseSize,*/ EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, - EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, - EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, EntityLimits::Bot::Null, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::InvTypeTradeSize, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, /*InvTypeCorpseSize,*/ + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, + EntityLimits::Bot::Null, - EntityLimits::Bot::Null, EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ EQEmu::inventory::SocketCount, /*ItemAugSize,*/ + EntityLimits::Bot::Null, + EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*ItemAugSize,*/ - EntityLimits::Bot::False, EntityLimits::Bot::False, EntityLimits::Bot::False, EntityLimits::Bot::False + EntityLimits::Bot::False, + EntityLimits::Bot::False, + EntityLimits::Bot::False, + EntityLimits::Bot::False }, - { // ClientPet - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::InvTypeTradeSize, EntityLimits::ClientPet::Null, - EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, - EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, /*InvTypeCorpseSize,*/ EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, - EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, - EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, EntityLimits::ClientPet::Null, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::InvTypeTradeSize, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, /*InvTypeCorpseSize,*/ + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, + EntityLimits::ClientPet::Null, - EntityLimits::ClientPet::Null, EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ EQEmu::inventory::SocketCount, /*ItemAugSize,*/ + EntityLimits::ClientPet::Null, + EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*ItemAugSize,*/ - EntityLimits::ClientPet::False, EntityLimits::ClientPet::False, EntityLimits::ClientPet::False, EntityLimits::ClientPet::False + EntityLimits::ClientPet::False, + EntityLimits::ClientPet::False, + EntityLimits::ClientPet::False, + EntityLimits::ClientPet::False }, - { // NPCPet - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::InvTypeTradeSize, EntityLimits::NPCPet::Null, - EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, - EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, /*InvTypeCorpseSize,*/ EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, - EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, - EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, EntityLimits::NPCPet::Null, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::InvTypeTradeSize, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, /*InvTypeCorpseSize,*/ + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, + EntityLimits::NPCPet::Null, - EntityLimits::NPCPet::Null, EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ EQEmu::inventory::SocketCount, /*ItemAugSize,*/ + EntityLimits::NPCPet::Null, + EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*ItemAugSize,*/ - EntityLimits::NPCPet::False, EntityLimits::NPCPet::False, EntityLimits::NPCPet::False, EntityLimits::NPCPet::False + EntityLimits::NPCPet::False, + EntityLimits::NPCPet::False, + EntityLimits::NPCPet::False, + EntityLimits::NPCPet::False }, - { // MercPet - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::InvTypeTradeSize, EntityLimits::MercPet::Null, - EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, - EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, /*InvTypeCorpseSize,*/ EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, - EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, - EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, EntityLimits::MercPet::Null, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::InvTypeTradeSize, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, /*InvTypeCorpseSize,*/ + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, + EntityLimits::MercPet::Null, - EntityLimits::MercPet::Null, EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ EQEmu::inventory::SocketCount, /*ItemAugSize,*/ + EntityLimits::MercPet::Null, + EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*ItemAugSize,*/ - EntityLimits::MercPet::False, EntityLimits::MercPet::False, EntityLimits::MercPet::False, EntityLimits::MercPet::False + EntityLimits::MercPet::False, + EntityLimits::MercPet::False, + EntityLimits::MercPet::False, + EntityLimits::MercPet::False }, - { // BotPet - EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::InvTypeTradeSize, EntityLimits::BotPet::Null, - EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, - EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, /*InvTypeCorpseSize,*/ EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, - EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, - EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, EntityLimits::BotPet::Null, + { + EQEmu::legacy::TYPE_POSSESSIONS_SIZE, /*InvTypePossessionsSize,*/ + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::InvTypeTradeSize, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, /*InvTypeCorpseSize,*/ + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, + EntityLimits::BotPet::Null, - EntityLimits::BotPet::Null, EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ EQEmu::inventory::SocketCount, /*ItemAugSize,*/ + EntityLimits::BotPet::Null, + EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ + EQEmu::inventory::SocketCount, /*ItemAugSize,*/ - EntityLimits::BotPet::False, EntityLimits::BotPet::False, EntityLimits::BotPet::False, EntityLimits::BotPet::False + EntityLimits::BotPet::False, + EntityLimits::BotPet::False, + EntityLimits::BotPet::False, + EntityLimits::BotPet::False }, { // OfflineTitanium - Titanium::Null, Titanium::Null, Titanium::Null, Titanium::invtype::InvTypeTradeSize, Titanium::Null, - Titanium::Null, Titanium::Null, Titanium::Null, Titanium::Null, Titanium::invtype::InvTypeMerchantSize, - Titanium::Null, Titanium::Null, Titanium::Null, /*Titanium::invtype::InvTypeBazaarSize,*/ Titanium::invtype::InvTypeInspectSize, Titanium::Null, - Titanium::invtype::InvTypeViewMODPCSize, Titanium::invtype::InvTypeViewMODBankSize, Titanium::invtype::InvTypeViewMODSharedBankSize, Titanium::invtype::InvTypeViewMODLimboSize, Titanium::Null, - Titanium::Null, Titanium::Null, Titanium::Null, Titanium::Null, Titanium::Null, + Titanium::Null, + Titanium::Null, + Titanium::Null, + Titanium::invtype::InvTypeTradeSize, + Titanium::Null, + Titanium::Null, + Titanium::Null, + Titanium::Null, + Titanium::Null, + Titanium::invtype::InvTypeMerchantSize, + Titanium::Null, + Titanium::Null, + Titanium::Null, /*Titanium::invtype::InvTypeBazaarSize,*/ + Titanium::invtype::InvTypeInspectSize, + Titanium::Null, + Titanium::invtype::InvTypeViewMODPCSize, + Titanium::invtype::InvTypeViewMODBankSize, + Titanium::invtype::InvTypeViewMODSharedBankSize, + Titanium::invtype::InvTypeViewMODLimboSize, + Titanium::Null, + Titanium::Null, + Titanium::Null, + Titanium::Null, + Titanium::Null, + Titanium::Null, - Titanium::Null, EQEmu::inventory::ContainerCount, /*Titanium::Null,*/ Titanium::Null, + Titanium::Null, + EQEmu::inventory::ContainerCount, /*Titanium::Null,*/ + Titanium::Null, - Titanium::False, Titanium::False, Titanium::False, Titanium::False + Titanium::False, + Titanium::False, + Titanium::False, + Titanium::False }, { // OfflineSoF - SoF::Null, SoF::Null, SoF::Null, SoF::invtype::InvTypeTradeSize, SoF::Null, - SoF::Null, SoF::Null, SoF::Null, SoF::Null, SoF::invtype::InvTypeMerchantSize, - SoF::Null, SoF::Null, SoF::Null, /*SoF::invtype::InvTypeBazaarSize,*/ SoF::invtype::InvTypeInspectSize, SoF::Null, - SoF::invtype::InvTypeViewMODPCSize, SoF::invtype::InvTypeViewMODBankSize, SoF::invtype::InvTypeViewMODSharedBankSize, SoF::invtype::InvTypeViewMODLimboSize, SoF::Null, - SoF::Null, SoF::Null, SoF::Null, SoF::Null, SoF::Null, + SoF::Null, + SoF::Null, + SoF::Null, + SoF::invtype::InvTypeTradeSize, + SoF::Null, + SoF::Null, + SoF::Null, + SoF::Null, + SoF::Null, + SoF::invtype::InvTypeMerchantSize, + SoF::Null, + SoF::Null, + SoF::Null, /*SoF::invtype::InvTypeBazaarSize,*/ + SoF::invtype::InvTypeInspectSize, + SoF::Null, + SoF::invtype::InvTypeViewMODPCSize, + SoF::invtype::InvTypeViewMODBankSize, + SoF::invtype::InvTypeViewMODSharedBankSize, + SoF::invtype::InvTypeViewMODLimboSize, + SoF::Null, + SoF::Null, + SoF::Null, + SoF::Null, + SoF::Null, + SoF::Null, - SoF::Null, EQEmu::inventory::ContainerCount, /*SoF::Null,*/ SoF::Null, + SoF::Null, + EQEmu::inventory::ContainerCount, /*SoF::Null,*/ + SoF::Null, - SoF::False, SoF::False, SoF::False, SoF::False + SoF::False, + SoF::False, + SoF::False, + SoF::False }, { // OfflineSoD - SoD::Null, SoD::Null, SoD::Null, SoD::invtype::InvTypeTradeSize, SoD::Null, - SoD::Null, SoD::Null, SoD::Null, SoD::Null, SoD::invtype::InvTypeMerchantSize, - SoD::Null, SoD::Null, SoD::Null, /*SoD::invtype::InvTypeBazaarSize,*/ SoD::invtype::InvTypeInspectSize, SoD::Null, - SoD::invtype::InvTypeViewMODPCSize, SoD::invtype::InvTypeViewMODBankSize, SoD::invtype::InvTypeViewMODSharedBankSize, SoD::invtype::InvTypeViewMODLimboSize, SoD::Null, - SoD::Null, SoD::Null, SoD::Null, SoD::Null, SoD::Null, + SoD::Null, + SoD::Null, + SoD::Null, + SoD::invtype::InvTypeTradeSize, + SoD::Null, + SoD::Null, + SoD::Null, + SoD::Null, + SoD::Null, + SoD::invtype::InvTypeMerchantSize, + SoD::Null, + SoD::Null, + SoD::Null, /*SoD::invtype::InvTypeBazaarSize,*/ + SoD::invtype::InvTypeInspectSize, + SoD::Null, + SoD::invtype::InvTypeViewMODPCSize, + SoD::invtype::InvTypeViewMODBankSize, + SoD::invtype::InvTypeViewMODSharedBankSize, + SoD::invtype::InvTypeViewMODLimboSize, + SoD::Null, + SoD::Null, + SoD::Null, + SoD::Null, + SoD::Null, + SoD::Null, - SoD::Null, EQEmu::inventory::ContainerCount, /*SoD::Null,*/ SoD::Null, + SoD::Null, + EQEmu::inventory::ContainerCount, /*SoD::Null,*/ + SoD::Null, - SoD::False, SoD::False, SoD::False, SoD::False + SoD::False, + SoD::False, + SoD::False, + SoD::False }, { // OfflineUF - UF::Null, UF::Null, UF::Null, UF::invtype::InvTypeTradeSize, UF::Null, - UF::Null, UF::Null, UF::Null, UF::Null, UF::invtype::InvTypeMerchantSize, - UF::Null, UF::Null, UF::Null, /*UF::invtype::InvTypeBazaarSize,*/ UF::invtype::InvTypeInspectSize, UF::Null, - UF::invtype::InvTypeViewMODPCSize, UF::invtype::InvTypeViewMODBankSize, UF::invtype::InvTypeViewMODSharedBankSize, UF::invtype::InvTypeViewMODLimboSize, UF::Null, - UF::Null, UF::Null, UF::Null, UF::Null, UF::Null, + UF::Null, + UF::Null, + UF::Null, + UF::invtype::InvTypeTradeSize, + UF::Null, + UF::Null, + UF::Null, + UF::Null, + UF::Null, + UF::invtype::InvTypeMerchantSize, + UF::Null, + UF::Null, + UF::Null, /*UF::invtype::InvTypeBazaarSize,*/ + UF::invtype::InvTypeInspectSize, + UF::Null, + UF::invtype::InvTypeViewMODPCSize, + UF::invtype::InvTypeViewMODBankSize, + UF::invtype::InvTypeViewMODSharedBankSize, + UF::invtype::InvTypeViewMODLimboSize, + UF::Null, + UF::Null, + UF::Null, + UF::Null, + UF::Null, + UF::Null, - UF::Null, EQEmu::inventory::ContainerCount, /*UF::Null,*/ UF::Null, + UF::Null, + EQEmu::inventory::ContainerCount, /*UF::Null,*/ + UF::Null, - UF::False, UF::False, UF::False, UF::False + UF::False, + UF::False, + UF::False, + UF::False }, { // OfflineRoF - RoF::Null, RoF::Null, RoF::Null, RoF::invtype::InvTypeTradeSize, RoF::Null, - RoF::Null, RoF::Null, RoF::Null, RoF::Null, RoF::invtype::InvTypeMerchantSize, - RoF::Null, RoF::Null, RoF::Null, /*RoF::invtype::InvTypeBazaarSize,*/ RoF::invtype::InvTypeInspectSize, RoF::Null, - RoF::invtype::InvTypeViewMODPCSize, RoF::invtype::InvTypeViewMODBankSize, RoF::invtype::InvTypeViewMODSharedBankSize, RoF::invtype::InvTypeViewMODLimboSize, RoF::Null, - RoF::Null, RoF::Null, RoF::Null, RoF::Null, RoF::Null, + RoF::Null, + RoF::Null, + RoF::Null, + RoF::invtype::InvTypeTradeSize, + RoF::Null, + RoF::Null, + RoF::Null, + RoF::Null, + RoF::Null, + RoF::invtype::InvTypeMerchantSize, + RoF::Null, + RoF::Null, + RoF::Null, /*RoF::invtype::InvTypeBazaarSize,*/ + RoF::invtype::InvTypeInspectSize, + RoF::Null, + RoF::invtype::InvTypeViewMODPCSize, + RoF::invtype::InvTypeViewMODBankSize, + RoF::invtype::InvTypeViewMODSharedBankSize, + RoF::invtype::InvTypeViewMODLimboSize, + RoF::Null, + RoF::Null, + RoF::Null, + RoF::Null, + RoF::Null, + RoF::Null, - RoF::Null, EQEmu::inventory::ContainerCount, /*RoF::Null,*/ RoF::Null, + RoF::Null, + EQEmu::inventory::ContainerCount, /*RoF::Null,*/ + RoF::Null, - RoF::False, RoF::False, RoF::False, RoF::False + RoF::False, + RoF::False, + RoF::False, + RoF::False }, { // OfflineRoF2 - RoF2::Null, RoF2::Null, RoF2::Null, RoF2::invtype::InvTypeTradeSize, RoF2::Null, - RoF2::Null, RoF2::Null, RoF2::Null, RoF2::Null, RoF2::invtype::InvTypeMerchantSize, - RoF2::Null, RoF2::Null, RoF2::Null, /*RoF2::invtype::InvTypeBazaarSize,*/ RoF2::invtype::InvTypeInspectSize, RoF2::Null, - RoF2::invtype::InvTypeViewMODPCSize, RoF2::invtype::InvTypeViewMODBankSize, RoF2::invtype::InvTypeViewMODSharedBankSize, RoF2::invtype::InvTypeViewMODLimboSize, RoF2::Null, - RoF2::Null, RoF2::Null, RoF2::Null, RoF2::Null, RoF2::Null, + RoF2::Null, + RoF2::Null, + RoF2::Null, + RoF2::invtype::InvTypeTradeSize, + RoF2::Null, + RoF2::Null, + RoF2::Null, + RoF2::Null, + RoF2::Null, + RoF2::invtype::InvTypeMerchantSize, + RoF2::Null, + RoF2::Null, + RoF2::Null, /*RoF2::invtype::InvTypeBazaarSize,*/ + RoF2::invtype::InvTypeInspectSize, + RoF2::Null, + RoF2::invtype::InvTypeViewMODPCSize, + RoF2::invtype::InvTypeViewMODBankSize, + RoF2::invtype::InvTypeViewMODSharedBankSize, + RoF2::invtype::InvTypeViewMODLimboSize, + RoF2::Null, + RoF2::Null, + RoF2::Null, + RoF2::Null, + RoF2::Null, + RoF2::Null, - RoF2::Null, EQEmu::inventory::ContainerCount, /*RoF2::Null,*/ RoF2::Null, + RoF2::Null, + EQEmu::inventory::ContainerCount, /*RoF2::Null,*/ + RoF2::Null, - RoF2::False, RoF2::False, RoF2::False, RoF2::False + RoF2::False, + RoF2::False, + RoF2::False, + RoF2::False } }; -const EQEmu::inventory::LookupEntry* EQEmu::inventory::Lookup(versions::InventoryVersion inventory_version) +const EQEmu::inventory::LookupEntry* EQEmu::inventory::Lookup(versions::MobVersion mob_version) { - return &inventory_lookup_entries[static_cast(versions::ValidateInventoryVersion(inventory_version))]; + return &inventory_lookup_entries[static_cast(versions::ValidateMobVersion(mob_version))]; } -static const EQEmu::behavior::LookupEntry behavior_lookup_entries[EQEmu::versions::InventoryVersionCount] = +static const EQEmu::behavior::LookupEntry behavior_lookup_entries[EQEmu::versions::MobVersionCount] = { { // Unknown ClientUnknown::True @@ -375,7 +921,7 @@ static const EQEmu::behavior::LookupEntry behavior_lookup_entries[EQEmu::version } }; -const EQEmu::behavior::LookupEntry* EQEmu::behavior::Lookup(versions::InventoryVersion inventory_version) +const EQEmu::behavior::LookupEntry* EQEmu::behavior::Lookup(versions::MobVersion mob_version) { - return &behavior_lookup_entries[static_cast(versions::ValidateInventoryVersion(inventory_version))]; + return &behavior_lookup_entries[static_cast(versions::ValidateMobVersion(mob_version))]; } diff --git a/common/eq_limits.h b/common/eq_limits.h index da1df17db..72d710998 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -59,7 +59,7 @@ namespace EQEmu bool AllowOverLevelEquipment; }; - const LookupEntry* Lookup(versions::InventoryVersion inventory_version); + const LookupEntry* Lookup(versions::MobVersion mob_version); } /*inventory*/ @@ -69,7 +69,7 @@ namespace EQEmu bool CoinHasWeight; }; - const LookupEntry* Lookup(versions::InventoryVersion inventory_version); + const LookupEntry* Lookup(versions::MobVersion mob_version); } /*behavior*/ diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index c952392b1..03b1df4e0 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -911,7 +911,7 @@ bool EQEmu::InventoryProfile::SupportsClickCasting(int16 slot_id) } else if (slot_id >= legacy::GENERAL_BAGS_BEGIN && slot_id <= legacy::GENERAL_BAGS_END) { - if (inventory::Lookup(m_inventory_version)->AllowClickCastFromBag) + if (inventory::Lookup(m_mob_version)->AllowClickCastFromBag) return true; } diff --git a/common/inventory_profile.h b/common/inventory_profile.h index 0f90fdea2..336bb47d8 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -85,22 +85,21 @@ namespace EQEmu // Public Methods /////////////////////////////// - InventoryProfile() { m_inventory_version = versions::InventoryVersion::Unknown; m_inventory_version_set = false; } + InventoryProfile() { m_mob_version = versions::MobVersion::Unknown; m_mob_version_set = false; } ~InventoryProfile(); - // inv2 creep - bool SetInventoryVersion(versions::InventoryVersion inventory_version) { - if (!m_inventory_version_set) { - m_inventory_version = versions::ValidateInventoryVersion(inventory_version); - return (m_inventory_version_set = true); + bool SetInventoryVersion(versions::MobVersion inventory_version) { + if (!m_mob_version_set) { + m_mob_version = versions::ValidateMobVersion(inventory_version); + return (m_mob_version_set = true); } else { return false; } } - bool SetInventoryVersion(versions::ClientVersion client_version) { return SetInventoryVersion(versions::ConvertClientVersionToInventoryVersion(client_version)); } + bool SetInventoryVersion(versions::ClientVersion client_version) { return SetInventoryVersion(versions::ConvertClientVersionToMobVersion(client_version)); } - versions::InventoryVersion InventoryVersion() { return m_inventory_version; } + versions::MobVersion InventoryVersion() { return m_mob_version; } static void CleanDirty(); static void MarkDirty(ItemInstance *inst); @@ -222,9 +221,9 @@ namespace EQEmu ::ItemInstQueue m_cursor; // Items on cursor: FIFO private: - // Active inventory version - versions::InventoryVersion m_inventory_version; - bool m_inventory_version_set; + // Active mob version + versions::MobVersion m_mob_version; + bool m_mob_version_set; }; } diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index f2205aabd..d9914fb26 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1369,7 +1369,7 @@ uint32 Client::CalcCurrentWeight() This is the ONLY instance I have seen where the client is hard coded to particular Item IDs to set a certain property for an item. It is very odd. */ // SoD+ client has no weight for coin - if (EQEmu::behavior::Lookup(EQEmu::versions::ConvertClientVersionToInventoryVersion(ClientVersion()))->CoinHasWeight) { + if (EQEmu::behavior::Lookup(EQEmu::versions::ConvertClientVersionToMobVersion(ClientVersion()))->CoinHasWeight) { Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4; } float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat; diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 3b9c15214..34a2191b2 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -999,7 +999,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToInventoryVersion(client->ClientVersion()))->InventoryTypeSize[EQEmu::inventory::typeCorpse]; + int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToMobVersion(client->ClientVersion()))->InventoryTypeSize[EQEmu::inventory::typeCorpse]; for(; cur != end; ++cur) { ServerLootItem_Struct* item_data = *cur; @@ -1294,7 +1294,7 @@ void Corpse::QueryLoot(Client* to) { cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToInventoryVersion(to->ClientVersion()))->InventoryTypeSize[EQEmu::inventory::typeCorpse]; + int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToMobVersion(to->ClientVersion()))->InventoryTypeSize[EQEmu::inventory::typeCorpse]; for(; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; From ec548874cc0d98971daa42a2924a24f9ea83908b Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 17 Oct 2016 11:06:16 -0400 Subject: [PATCH 406/693] Another windows laxity... --- common/item_instance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/item_instance.cpp b/common/item_instance.cpp index 61b9d3243..ab109bb41 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -27,7 +27,7 @@ //#include "../common/light_source.h" -//#include +#include //#include From d62ceaefcc1f9fb929027b1747d8021c94b57a8f Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Mon, 17 Oct 2016 18:57:35 -0500 Subject: [PATCH 407/693] Rule to grant HoTT ability on character create --- common/database.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/common/database.cpp b/common/database.cpp index 66ac8495b..423bbac58 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -638,6 +638,13 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 4 ); results = QueryDatabase(query); + /* HoTT Ability */ + if(RuleB(Character, GrantHoTTOnCreate)) + { + query = StringFormat("INSERT INTO `character_leadership_abilities` (id, slot, rank) VALUES (%u, %i, %i)", character_id, 14, 1); + results = QueryDatabase(query); + } + /* Save Skills */ int firstquery = 0; for (int i = 0; i < MAX_PP_SKILL; i++){ @@ -2159,4 +2166,4 @@ int Database::GetInstanceID(uint32 char_id, uint32 zone_id) { } return 0; -} \ No newline at end of file +} From d1f7448b25bda0c3340404c58e2a70eef7fd766d Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Mon, 17 Oct 2016 18:58:52 -0500 Subject: [PATCH 408/693] Rule for HoTT grant. Defaults to false --- common/ruletypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index bf35d03e8..3b3816201 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -147,7 +147,7 @@ RULE_BOOL(Character, EnableAvoidanceCap, false) RULE_INT(Character, AvoidanceCap, 750) // 750 Is a pretty good value, seen people dodge all attacks beyond 1,000 Avoidance RULE_BOOL(Character, AllowMQTarget, false) // Disables putting players in the 'hackers' list for targeting beyond the clip plane or attempting to target something untargetable RULE_BOOL(Character, UseOldBindWound, false) // Uses the original bind wound behavior - +RULE_BOOL(Character, GrantHoTTOnCreate, false) // Grant Health of Target's Target leadership AA on character creation RULE_CATEGORY_END() RULE_CATEGORY(Mercs) From e3e20a947bed9a199830e093b66d58d945074946 Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Mon, 17 Oct 2016 19:00:08 -0500 Subject: [PATCH 409/693] Create 2016_10_17_GrantHoTTOnCharacterCreate.sql --- utils/sql/git/optional/2016_10_17_GrantHoTTOnCharacterCreate.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 utils/sql/git/optional/2016_10_17_GrantHoTTOnCharacterCreate.sql diff --git a/utils/sql/git/optional/2016_10_17_GrantHoTTOnCharacterCreate.sql b/utils/sql/git/optional/2016_10_17_GrantHoTTOnCharacterCreate.sql new file mode 100644 index 000000000..eeb73c293 --- /dev/null +++ b/utils/sql/git/optional/2016_10_17_GrantHoTTOnCharacterCreate.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Character:GrantHoTTOnCreate', 'false', 'Grant Health of Target\'s Target leadership AA on character creation'); From 16fa32e65bf7dcecc4a90cbc449a9195f4cb8039 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 18 Oct 2016 14:16:53 -0500 Subject: [PATCH 410/693] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 4fd6bb796..c39ddd37e 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -939,18 +939,18 @@ sub check_db_version_table{ sub get_mysql_result{ my $run_query = $_[0]; if(!$db){ return; } - if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`; } + if($OS eq "Windows"){ return `"$path" --host "$host" --user "$user" --password="$pass" $db -N -B -e "$run_query"`; } if($OS eq "Linux"){ $run_query =~s/`//g; - return `$path --user="$user" --host $host --password="$pass" $db -N -B -e "$run_query"`; + return `$path --user="$user" --host "$host" --password="$pass" $db -N -B -e "$run_query"`; } } sub get_mysql_result_from_file{ my $update_file = $_[0]; if(!$db){ return; } - if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } - if($OS eq "Linux"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } + if($OS eq "Windows"){ return `"$path" --host "$host" --user "$user" --password="$pass" --force $db < $update_file`; } + if($OS eq "Linux"){ return `"$path" --host "$host" --user "$user" --password="$pass" --force $db < $update_file`; } } #::: Gets Remote File based on request_url (1st Arg), and saves to destination file (2nd Arg) From 6e0cba566fedac2f8ccb425cb77cb6d681d30792 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 18 Oct 2016 17:09:07 -0400 Subject: [PATCH 411/693] Added 'sow' argument to bot_command_movement_speed --- zone/bot_command.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 72ac6cae4..17182451f 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -3397,15 +3397,18 @@ void bot_command_movement_speed(Client *c, const Seperator *sep) if (helper_spell_list_fail(c, local_list, BCEnum::SpT_MovementSpeed) || helper_command_alias_fail(c, "bot_command_movement_speed", sep->arg[0], "movementspeed")) return; if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(m_usage, "usage: () %s ([group])", sep->arg[0]); + c->Message(m_usage, "usage: () %s ([group | sow])", sep->arg[0]); helper_send_usage_required_bots(c, BCEnum::SpT_MovementSpeed); return; } bool group = false; - std::string group_arg = sep->arg[1]; - if (!group_arg.compare("group")) + bool sow = false; + std::string arg1 = sep->arg[1]; + if (!arg1.compare("group")) group = true; + else if (!arg1.compare("sow")) + sow = true; ActionableTarget::Types actionable_targets; Bot* my_bot = nullptr; @@ -3417,7 +3420,9 @@ void bot_command_movement_speed(Client *c, const Seperator *sep) auto local_entry = list_iter->SafeCastToMovementSpeed(); if (helper_spell_check_fail(local_entry)) continue; - if (local_entry->group != group) + if (!sow && (local_entry->group != group)) + continue; + if (sow && (local_entry->spell_id != 278)) // '278' = single-target "Spirit of Wolf" continue; auto target_mob = actionable_targets.Select(c, local_entry->target_type, FRIENDLY); From fe968f83a33695e7cfbb365daa4f5facbe54e2cf Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 18 Oct 2016 16:21:21 -0500 Subject: [PATCH 412/693] Update eqemu_server.pl [skip ci] - undo previous quote commit --- utils/scripts/eqemu_server.pl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index c39ddd37e..4fd6bb796 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -939,18 +939,18 @@ sub check_db_version_table{ sub get_mysql_result{ my $run_query = $_[0]; if(!$db){ return; } - if($OS eq "Windows"){ return `"$path" --host "$host" --user "$user" --password="$pass" $db -N -B -e "$run_query"`; } + if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`; } if($OS eq "Linux"){ $run_query =~s/`//g; - return `$path --user="$user" --host "$host" --password="$pass" $db -N -B -e "$run_query"`; + return `$path --user="$user" --host $host --password="$pass" $db -N -B -e "$run_query"`; } } sub get_mysql_result_from_file{ my $update_file = $_[0]; if(!$db){ return; } - if($OS eq "Windows"){ return `"$path" --host "$host" --user "$user" --password="$pass" --force $db < $update_file`; } - if($OS eq "Linux"){ return `"$path" --host "$host" --user "$user" --password="$pass" --force $db < $update_file`; } + if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } + if($OS eq "Linux"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } } #::: Gets Remote File based on request_url (1st Arg), and saves to destination file (2nd Arg) From 97999a63b7a0bdecaabab534e1cb4e37d31e960e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 18 Oct 2016 16:49:47 -0500 Subject: [PATCH 413/693] Update eqemu_server.pl [skip ci] - Fix eqemu_config.xml tag parsing scenarios --- utils/scripts/eqemu_server.pl | 80 ++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 4fd6bb796..b27aac310 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -1063,46 +1063,50 @@ sub trim { } sub read_eqemu_config_xml { - open (CONFIG, "eqemu_config.xml"); - while (){ - chomp; - $o = $_; + open (CONFIG, "eqemu_config.xml"); + while (){ + chomp; + $o = $_; - if($o=~/\<\!--/i){ - next; - } + if($o=~/\<\!--/i){ + next; + } + + if($o=~/database/i && $o=~/\<\//i){ + $in_database_tag = 0; + } + if($o=~//i){ + print "IN DATABASE TAG\n" if $debug; + $in_database_tag = 1; + } + if($o=~//i){ + ($long_name) = $o =~ /(.*)<\/longname>/; + print "Long Name: '" . $long_name . "'\n" if $debug; + } + if($in_database_tag == 1){ + @left = split (">", $o); + @right = split("<", $left[1]); + $tag_data = trim($right[0]); - if($o=~/database/i && $o=~/\<\//i){ - $in_database_tag = 0; - } - if($o=~/\/i){ - print "IN DATABASE TAG\n" if $debug; - $in_database_tag = 1; - } - if($o=~/\/i){ - ($long_name) = $o =~ /(.*)<\/longname>/; - print "Long Name: " . $long_name . "\n" if $debug; - } - if($in_database_tag == 1){ - if($o=~/\/i && $in_database_tag){ - ($user) = $o =~ />(\w+)/i && $in_database_tag){ - ($pass) = $o =~ />(\w+)/i){ - ($db) = $o =~ />(\w+)/i){ - ($host) = $o =~ />(\w+)/i && $in_database_tag){ + $user = $tag_data; + print "Database User: '" . $user . "'\n" if $debug; + } + if($o=~//i && $in_database_tag){ + $pass = $tag_data; + print "Database Pass: '" . $pass . "'\n" if $debug; + } + if($o=~//i){ + $db = $tag_data; + print "Database Name: '" . $db . "'\n" if $debug; + } + if($o=~//i){ + $host = $tag_data; + print "Database Host: '" . $host . "'\n" if $debug; + } + } + } + close(CONFIG); } #::: Fetch Latest PEQ AA's From 409bad8108473b290d0d203b945a7afaf45fe9f6 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 18 Oct 2016 16:52:51 -0500 Subject: [PATCH 414/693] Update eqemu_server.pl [skip ci] - not sure why formatting is getting thrown off --- utils/scripts/eqemu_server.pl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index b27aac310..dd0448ddc 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -1076,21 +1076,21 @@ sub read_eqemu_config_xml { $in_database_tag = 0; } if($o=~//i){ - print "IN DATABASE TAG\n" if $debug; - $in_database_tag = 1; + print "IN DATABASE TAG\n" if $debug; + $in_database_tag = 1; } if($o=~//i){ - ($long_name) = $o =~ /(.*)<\/longname>/; - print "Long Name: '" . $long_name . "'\n" if $debug; + ($long_name) = $o =~ /(.*)<\/longname>/; + print "Long Name: '" . $long_name . "'\n" if $debug; } if($in_database_tag == 1){ - @left = split (">", $o); - @right = split("<", $left[1]); - $tag_data = trim($right[0]); + @left = split (">", $o); + @right = split("<", $left[1]); + $tag_data = trim($right[0]); if($o=~//i && $in_database_tag){ - $user = $tag_data; - print "Database User: '" . $user . "'\n" if $debug; + $user = $tag_data; + print "Database User: '" . $user . "'\n" if $debug; } if($o=~//i && $in_database_tag){ $pass = $tag_data; @@ -1101,8 +1101,8 @@ sub read_eqemu_config_xml { print "Database Name: '" . $db . "'\n" if $debug; } if($o=~//i){ - $host = $tag_data; - print "Database Host: '" . $host . "'\n" if $debug; + $host = $tag_data; + print "Database Host: '" . $host . "'\n" if $debug; } } } From 752821f22bd20736cdb31e52d0ae0567e490b01a Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 20 Oct 2016 16:36:46 -0400 Subject: [PATCH 415/693] Added proximity data report to npcstats command --- zone/command.cpp | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index d75dec901..718feedcc 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -1471,16 +1471,29 @@ void command_npcstats(Client *c, const Seperator *sep) else if (!c->GetTarget()->IsNPC()) c->Message(0, "ERROR: Target is not a NPC!"); else { + auto target_npc = c->GetTarget()->CastToNPC(); c->Message(0, "NPC Stats:"); - c->Message(0, "Name: %s NpcID: %u", c->GetTarget()->GetName(), c->GetTarget()->GetNPCTypeID()); - c->Message(0, "Race: %i Level: %i Class: %i Material: %i", c->GetTarget()->GetRace(), c->GetTarget()->GetLevel(), c->GetTarget()->GetClass(), c->GetTarget()->GetTexture()); - c->Message(0, "Current HP: %i Max HP: %i", c->GetTarget()->GetHP(), c->GetTarget()->GetMaxHP()); - //c->Message(0, "Weapon Item Number: %s", c->GetTarget()->GetWeapNo()); - c->Message(0, "Gender: %i Size: %f Bodytype: %d", c->GetTarget()->GetGender(), c->GetTarget()->GetSize(), c->GetTarget()->GetBodyType()); - c->Message(0, "Runspeed: %.3f Walkspeed: %.3f", static_cast(0.025f * c->GetTarget()->GetRunspeed()), static_cast(0.025f * c->GetTarget()->GetWalkspeed())); - c->Message(0, "Spawn Group: %i Grid: %i", c->GetTarget()->CastToNPC()->GetSp2(), c->GetTarget()->CastToNPC()->GetGrid()); - c->Message(0, "EmoteID: %i", c->GetTarget()->CastToNPC()->GetEmoteID()); - c->GetTarget()->CastToNPC()->QueryLoot(c); + c->Message(0, "Name: %s NpcID: %u", target_npc->GetName(), target_npc->GetNPCTypeID()); + c->Message(0, "Race: %i Level: %i Class: %i Material: %i", target_npc->GetRace(), target_npc->GetLevel(), target_npc->GetClass(), target_npc->GetTexture()); + c->Message(0, "Current HP: %i Max HP: %i", target_npc->GetHP(), target_npc->GetMaxHP()); + //c->Message(0, "Weapon Item Number: %s", target_npc->GetWeapNo()); + c->Message(0, "Gender: %i Size: %f Bodytype: %d", target_npc->GetGender(), target_npc->GetSize(), target_npc->GetBodyType()); + c->Message(0, "Runspeed: %.3f Walkspeed: %.3f", static_cast(0.025f * target_npc->GetRunspeed()), static_cast(0.025f * target_npc->GetWalkspeed())); + c->Message(0, "Spawn Group: %i Grid: %i", target_npc->GetSp2(), target_npc->GetGrid()); + if (target_npc->proximity) { + c->Message(0, "Proximity: Enabled"); + c->Message(0, "Cur_X: %1.3f, Cur_Y: %1.3f, Cur_Z: %1.3f", target_npc->GetX(), target_npc->GetY(), target_npc->GetZ()); + c->Message(0, "Min_X: %1.3f(%1.3f), Max_X: %1.3f(%1.3f), X_Range: %1.3f", target_npc->proximity->min_x, (target_npc->proximity->min_x - target_npc->GetX()), target_npc->proximity->max_x, (target_npc->proximity->max_x - target_npc->GetX()), (target_npc->proximity->max_x - target_npc->proximity->min_x)); + c->Message(0, "Min_Y: %1.3f(%1.3f), Max_Y: %1.3f(%1.3f), Y_Range: %1.3f", target_npc->proximity->min_y, (target_npc->proximity->min_y - target_npc->GetY()), target_npc->proximity->max_y, (target_npc->proximity->max_y - target_npc->GetY()), (target_npc->proximity->max_y - target_npc->proximity->min_y)); + c->Message(0, "Min_Z: %1.3f(%1.3f), Max_Z: %1.3f(%1.3f), Z_Range: %1.3f", target_npc->proximity->min_z, (target_npc->proximity->min_z - target_npc->GetZ()), target_npc->proximity->max_z, (target_npc->proximity->max_z - target_npc->GetZ()), (target_npc->proximity->max_z - target_npc->proximity->min_z)); + c->Message(0, "Say: %s", (target_npc->proximity->say ? "Enabled" : "Disabled")); + } + else { + c->Message(0, "Proximity: Disabled"); + } + c->Message(0, ""); + c->Message(0, "EmoteID: %i", target_npc->GetEmoteID()); + target_npc->QueryLoot(c); } } From 6abed18eb9508f702e916c6d0880df71cdb7e1c2 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Thu, 20 Oct 2016 21:10:07 -0400 Subject: [PATCH 416/693] Added augment support for NPC AddItem() and quest::addloot in Perl/Lua. This will allow you to add items to NPCs with scripts that already have augments in them. --- zone/loottables.cpp | 18 +++++++++--------- zone/lua_npc.cpp | 36 ++++++++++++++++++++++++++++++++++++ zone/lua_npc.h | 6 ++++++ zone/npc.h | 4 ++-- zone/perl_npc.cpp | 26 ++++++++++++++++++++++---- zone/questmgr.cpp | 4 ++-- zone/questmgr.h | 2 +- 7 files changed, 78 insertions(+), 18 deletions(-) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 4dae50960..03f1590b1 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -221,7 +221,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml } //if itemlist is null, just send wear changes -void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange) { +void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6) { if(item2 == nullptr) return; @@ -245,12 +245,12 @@ void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 ch item->item_id = item2->ID; item->charges = charges; - item->aug_1 = 0; - item->aug_2 = 0; - item->aug_3 = 0; - item->aug_4 = 0; - item->aug_5 = 0; - item->aug_6 = 0; + item->aug_1 = aug1; + item->aug_2 = aug2; + item->aug_3 = aug3; + item->aug_4 = aug4; + item->aug_5 = aug5; + item->aug_6 = aug6; item->attuned = 0; item->min_level = minlevel; item->max_level = maxlevel; @@ -420,12 +420,12 @@ void NPC::AddItem(const EQEmu::ItemData* item, uint16 charges, bool equipitem) { AddLootDrop(item, &itemlist, charges, 1, 255, equipitem, equipitem); } -void NPC::AddItem(uint32 itemid, uint16 charges, bool equipitem) { +void NPC::AddItem(uint32 itemid, uint16 charges, bool equipitem, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5, uint32 aug6) { //slot isnt needed, its determined from the item. const EQEmu::ItemData * i = database.GetItem(itemid); if(i == nullptr) return; - AddLootDrop(i, &itemlist, charges, 1, 255, equipitem, equipitem); + AddLootDrop(i, &itemlist, charges, 1, 255, equipitem, equipitem, aug1, aug2, aug3, aug4, aug5, aug6); } void NPC::AddLootTable() { diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index 6d6c69a62..9ed705496 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -27,6 +27,36 @@ void Lua_NPC::AddItem(int item_id, int charges, bool equip) { self->AddItem(item_id, charges, equip); } +void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1) { + Lua_Safe_Call_Void(); + self->AddItem(item_id, charges, equip, aug1); +} + +void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1, int aug2) { + Lua_Safe_Call_Void(); + self->AddItem(item_id, charges, equip, aug1, aug2); +} + +void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3) { + Lua_Safe_Call_Void(); + self->AddItem(item_id, charges, equip, aug1, aug2, aug3); +} + +void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4) { + Lua_Safe_Call_Void(); + self->AddItem(item_id, charges, equip, aug1, aug2, aug3, aug4); +} + +void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4, int aug5) { + Lua_Safe_Call_Void(); + self->AddItem(item_id, charges, equip, aug1, aug2, aug3, aug4, aug5); +} + +void Lua_NPC::AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4, int aug5, int aug6) { + Lua_Safe_Call_Void(); + self->AddItem(item_id, charges, equip, aug1, aug2, aug3, aug4, aug5, aug6); +} + void Lua_NPC::AddLootTable() { Lua_Safe_Call_Void(); self->AddLootTable(); @@ -475,6 +505,12 @@ luabind::scope lua_register_npc() { .def("CheckNPCFactionAlly", (int(Lua_NPC::*)(int))&Lua_NPC::CheckNPCFactionAlly) .def("AddItem", (void(Lua_NPC::*)(int,int))&Lua_NPC::AddItem) .def("AddItem", (void(Lua_NPC::*)(int,int,bool))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int,int))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int,int,int))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int,int,int,int))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int,int,int,int,int))&Lua_NPC::AddItem) + .def("AddItem", (void(Lua_NPC::*)(int,int,bool,int,int,int,int,int,int))&Lua_NPC::AddItem) .def("AddLootTable", (void(Lua_NPC::*)(void))&Lua_NPC::AddLootTable) .def("AddLootTable", (void(Lua_NPC::*)(int))&Lua_NPC::AddLootTable) .def("RemoveItem", (void(Lua_NPC::*)(int))&Lua_NPC::RemoveItem) diff --git a/zone/lua_npc.h b/zone/lua_npc.h index f5bb4719d..e355c3e4d 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -31,6 +31,12 @@ public: int CheckNPCFactionAlly(int faction); void AddItem(int item_id, int charges); void AddItem(int item_id, int charges, bool equip); + void AddItem(int item_id, int charges, bool equip, int aug1); + void AddItem(int item_id, int charges, bool equip, int aug1, int aug2); + void AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3); + void AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4); + void AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4, int aug5); + void AddItem(int item_id, int charges, bool equip, int aug1, int aug2, int aug3, int aug4, int aug5, int aug6); void AddLootTable(); void AddLootTable(int id); void RemoveItem(int item_id); diff --git a/zone/npc.h b/zone/npc.h index ba9e93843..4b81d45a6 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -179,7 +179,7 @@ public: virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); void AddItem(const EQEmu::ItemData* item, uint16 charges, bool equipitem = true); - void AddItem(uint32 itemid, uint16 charges, bool equipitem = true); + void AddItem(uint32 itemid, uint16 charges, bool equipitem = true, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0); void AddLootTable(); void AddLootTable(uint32 ldid); void DescribeAggro(Client *towho, Mob *mob, bool verbose); @@ -270,7 +270,7 @@ public: bool IsTaunting() const { return taunting; } void PickPocket(Client* thief); void StartSwarmTimer(uint32 duration) { swarm_timer.Start(duration); } - void AddLootDrop(const EQEmu::ItemData*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false); + void AddLootDrop(const EQEmu::ItemData*dbitem, ItemList* itemlistconst, int16 charges, uint8 minlevel, uint8 maxlevel, bool equipit, bool wearchange = false, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0); virtual void DoClassAttacks(Mob *target); void CheckSignal(); inline bool IsNotTargetableWithHotkey() const { return no_target_hotkey; } diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index 0c9cec797..64e71d82f 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -98,13 +98,19 @@ XS(XS_NPC_AddItem); /* prototype to pass -Wmissing-prototypes */ XS(XS_NPC_AddItem) { dXSARGS; - if (items < 2 || items > 4) - Perl_croak(aTHX_ "Usage: NPC::AddItem(THIS, itemid, charges = 0, equipitem = true)"); + if (items < 2 || items > 10) + Perl_croak(aTHX_ "Usage: NPC::AddItem(THIS, itemid, charges = 0, equipitem = true, aug1 = 0, aug2 = 0, aug3 = 0, aug4 = 0, aug5 = 0, aug6 = 0)"); { NPC * THIS; uint32 itemid = (uint32)SvUV(ST(1)); uint16 charges = 0; bool equipitem = true; + uint32 aug1 = 0; + uint32 aug2 = 0; + uint32 aug3 = 0; + uint32 aug4 = 0; + uint32 aug5 = 0; + uint32 aug6 = 0; if (sv_derived_from(ST(0), "NPC")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -119,8 +125,20 @@ XS(XS_NPC_AddItem) charges = (uint16)SvUV(ST(2)); if (items > 3) equipitem = (bool)SvTRUE(ST(3)); + if (items > 4) + aug1 = (uint32)SvUV(ST(4)); + if (items > 5) + aug2 = (uint32)SvUV(ST(5)); + if (items > 6) + aug3 = (uint32)SvUV(ST(6)); + if (items > 7) + aug4 = (uint32)SvUV(ST(7)); + if (items > 8) + aug5 = (uint32)SvUV(ST(8)); + if (items > 9) + aug6 = (uint32)SvUV(ST(9)); - THIS->AddItem(itemid, charges, equipitem); + THIS->AddItem(itemid, charges, equipitem, aug1, aug2, aug3, aug4, aug5, aug6); } XSRETURN_EMPTY; } @@ -2577,7 +2595,7 @@ XS(boot_NPC) newXSproto(strcpy(buf, "SignalNPC"), XS_NPC_SignalNPC, file, "$$"); newXSproto(strcpy(buf, "CheckNPCFactionAlly"), XS_NPC_CheckNPCFactionAlly, file, "$$"); - newXSproto(strcpy(buf, "AddItem"), XS_NPC_AddItem, file, "$$;$$"); + newXSproto(strcpy(buf, "AddItem"), XS_NPC_AddItem, file, "$$;$$$$$$$$"); newXSproto(strcpy(buf, "AddLootTable"), XS_NPC_AddLootTable, file, "$"); newXSproto(strcpy(buf, "RemoveItem"), XS_NPC_RemoveItem, file, "$$;$$"); newXSproto(strcpy(buf, "ClearItemList"), XS_NPC_ClearItemList, file, "$"); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 1df7492c2..4668a1bbc 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -375,11 +375,11 @@ void QuestManager::selfcast(int spell_id) { initiator->SpellFinished(spell_id, initiator, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } -void QuestManager::addloot(int item_id, int charges, bool equipitem) { +void QuestManager::addloot(int item_id, int charges, bool equipitem, int aug1, int aug2, int aug3, int aug4, int aug5, int aug6) { QuestManagerCurrentQuestVars(); if(item_id != 0){ if(owner->IsNPC()) - owner->CastToNPC()->AddItem(item_id, charges, equipitem); + owner->CastToNPC()->AddItem(item_id, charges, equipitem, aug1, aug2, aug3, aug4, aug5, aug6); } } diff --git a/zone/questmgr.h b/zone/questmgr.h index 1bef4e1ee..a878de71e 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -70,7 +70,7 @@ public: void incstat(int stat, int value); void castspell(int spell_id, int target_id); void selfcast(int spell_id); - void addloot(int item_id, int charges = 0, bool equipitem = true); + void addloot(int item_id, int charges = 0, bool equipitem = true, int aug1 = 0, int aug2 = 0, int aug3 = 0, int aug4 = 0, int aug5 = 0, int aug6 = 0); void Zone(const char *zone_name); void settimer(const char *timer_name, int seconds); void settimerMS(const char *timer_name, int milliseconds); From 95064947b6832b353d754240447dc8c2d0744aee Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 21 Oct 2016 20:48:18 -0400 Subject: [PATCH 417/693] Hack to fix long recast bard songs --- zone/spells.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 649fa99c9..4c01e1340 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -985,17 +985,23 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo if(GetClass() == BARD) // bard's can move when casting any spell... { if (IsBardSong(spell_id)) { - if(spells[spell_id].buffduration == 0xFFFF || spells[spell_id].recast_time != 0) { - Log.Out(Logs::Detail, Logs::Spells, "Bard song %d not applying bard logic because duration or recast is wrong: dur=%d, recast=%d", spells[spell_id].buffduration, spells[spell_id].recast_time); + if(spells[spell_id].buffduration == 0xFFFF) { + Log.Out(Logs::Detail, Logs::Spells, "Bard song %d not applying bard logic because duration. dur=%d, recast=%d", spells[spell_id].buffduration); } else { - bardsong = spell_id; - bardsong_slot = slot; - //NOTE: theres a lot more target types than this to think about... - if (spell_target == nullptr || (spells[spell_id].targettype != ST_Target && spells[spell_id].targettype != ST_AETarget)) - bardsong_target_id = GetID(); - else - bardsong_target_id = spell_target->GetID(); - bardsong_timer.Start(6000); + // So long recast bard songs need special bard logic, although the effects don't repulse like other songs + // This is basically a hack to get that effect + // You can hold down the long recast spells, but you only get the effects once + // TODO fuck bards. + if (spells[spell_id].recast_time == 0) { + bardsong = spell_id; + bardsong_slot = slot; + //NOTE: theres a lot more target types than this to think about... + if (spell_target == nullptr || (spells[spell_id].targettype != ST_Target && spells[spell_id].targettype != ST_AETarget)) + bardsong_target_id = GetID(); + else + bardsong_target_id = spell_target->GetID(); + bardsong_timer.Start(6000); + } Log.Out(Logs::Detail, Logs::Spells, "Bard song %d started: slot %d, target id %d", bardsong, bardsong_slot, bardsong_target_id); bard_song_mode = true; } From db7f0cc9776dd15d83019bf7f9e73595b5226361 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 23 Oct 2016 15:28:20 -0400 Subject: [PATCH 418/693] Fix for model glitches resulting from a recent patch --- common/patches/rof.cpp | 4 ++-- common/patches/rof2.cpp | 4 ++-- common/textures.h | 26 +++++--------------------- world/worlddb.cpp | 4 ++-- zone/bot.cpp | 2 +- zone/mob.cpp | 2 +- 6 files changed, 13 insertions(+), 29 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 6d13bb338..5793e6392 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3063,7 +3063,7 @@ namespace RoF eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteModel; - eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HeroicModel; + eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HerosForgeModel; eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Unknown2; eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } @@ -4109,7 +4109,7 @@ namespace RoF Equipment[k].Material = emu->equipment.Slot[k].Material; Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteModel; - Equipment[k].HeroForgeModel = emu->equipment.Slot[k].HeroicModel; + Equipment[k].HeroForgeModel = emu->equipment.Slot[k].HerosForgeModel; Equipment[k].Material2 = emu->equipment.Slot[k].Unknown2; } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 14fcdc2e6..c19203d8a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3158,7 +3158,7 @@ namespace RoF2 eq_cse->Equip[equip_index].Material = emu_cse->Equip[equip_index].Material; eq_cse->Equip[equip_index].Unknown1 = emu_cse->Equip[equip_index].Unknown1; eq_cse->Equip[equip_index].EliteMaterial = emu_cse->Equip[equip_index].EliteModel; - eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HeroicModel; + eq_cse->Equip[equip_index].HeroForgeModel = emu_cse->Equip[equip_index].HerosForgeModel; eq_cse->Equip[equip_index].Material2 = emu_cse->Equip[equip_index].Unknown2; eq_cse->Equip[equip_index].Color = emu_cse->Equip[equip_index].Color; } @@ -4334,7 +4334,7 @@ namespace RoF2 Equipment[k].Material = emu->equipment.Slot[k].Material; Equipment[k].Unknown1 = emu->equipment.Slot[k].Unknown1; Equipment[k].EliteMaterial = emu->equipment.Slot[k].EliteModel; - Equipment[k].HeroForgeModel = emu->equipment.Slot[k].HeroicModel; + Equipment[k].HeroForgeModel = emu->equipment.Slot[k].HerosForgeModel; Equipment[k].Material2 = emu->equipment.Slot[k].Unknown2; } diff --git a/common/textures.h b/common/textures.h index bbf5f71c9..a39f4c007 100644 --- a/common/textures.h +++ b/common/textures.h @@ -58,27 +58,11 @@ namespace EQEmu const int8 LastTintableTexture = tintFeet; struct Texture_Struct { - union { - struct { - struct { - struct { - uint32 _material; - } _1_field; - - uint32 _unknown1; - uint32 _elite_model; - } _3_fields; - - uint32 _heroic_model; - uint32 _unknown2; - } _5_fields; - - uint32 Material; - uint32 Unknown1; - uint32 EliteModel; - uint32 HeroicModel; - uint32 Unknown2; // same as material? - }; + uint32 Material; + uint32 Unknown1; + uint32 EliteModel; + uint32 HerosForgeModel; + uint32 Unknown2; // same as material? }; struct TextureMaterial_Struct { diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 5cac4b648..2955daf50 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -120,7 +120,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou cse->Equip[matslot].Material = 0; cse->Equip[matslot].Unknown1 = 0; cse->Equip[matslot].EliteModel = 0; - cse->Equip[matslot].HeroicModel = 0; + cse->Equip[matslot].HerosForgeModel = 0; cse->Equip[matslot].Unknown2 = 0; cse->Equip[matslot].Color = 0; } @@ -288,7 +288,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou // Armor Materials/Models cse->Equip[matslot].Material = item->Material; cse->Equip[matslot].EliteModel = item->EliteMaterial; - cse->Equip[matslot].HeroicModel = inst->GetOrnamentHeroModel(matslot); + cse->Equip[matslot].HerosForgeModel = inst->GetOrnamentHeroModel(matslot); cse->Equip[matslot].Color = color; } } diff --git a/zone/bot.cpp b/zone/bot.cpp index 1629580bf..133932df7 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2963,7 +2963,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { if (item != 0) { ns->spawn.equipment.Slot[i].Material = item->Material; ns->spawn.equipment.Slot[i].EliteModel = item->EliteMaterial; - ns->spawn.equipment.Slot[i].HeroicModel = item->HerosForgeModel; + ns->spawn.equipment.Slot[i].HerosForgeModel = item->HerosForgeModel; if (armor_tint.Slot[i].Color) ns->spawn.equipment_tint.Slot[i].Color = armor_tint.Slot[i].Color; else diff --git a/zone/mob.cpp b/zone/mob.cpp index 368d34e1f..fbc82e63f 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1159,7 +1159,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.equipment.Slot[i].Material = GetEquipmentMaterial(i); ns->spawn.equipment.Slot[i].EliteModel = IsEliteMaterialItem(i); - ns->spawn.equipment.Slot[i].HeroicModel = GetHerosForgeModel(i); + ns->spawn.equipment.Slot[i].HerosForgeModel = GetHerosForgeModel(i); ns->spawn.equipment_tint.Slot[i].Color = GetEquipmentColor(i); } } From aabf7b9b5a34efdbb4ba151feb3a119c2c290cad Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 23 Oct 2016 20:51:07 -0400 Subject: [PATCH 419/693] Switched NPC::QueryLoot() from ItemData model to ServerLootItem model (allows saylinks with augments) --- zone/npc.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index f6e080a26..b2b3ff48c 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -525,19 +525,22 @@ void NPC::QueryLoot(Client* to) int x = 0; for (auto cur = itemlist.begin(); cur != itemlist.end(); ++cur, ++x) { - const EQEmu::ItemData* item = database.GetItem((*cur)->item_id); - if (item == nullptr) { - Log.Out(Logs::General, Logs::Error, "Database error, invalid item"); + if (!(*cur)) { + Log.Out(Logs::General, Logs::Error, "NPC::QueryLoot() - ItemList error, null item"); + continue; + } + if (!(*cur)->item_id || !database.GetItem((*cur)->item_id)) { + Log.Out(Logs::General, Logs::Error, "NPC::QueryLoot() - Database error, invalid item"); continue; } EQEmu::SayLinkEngine linker; - linker.SetLinkType(EQEmu::saylink::SayLinkItemData); - linker.SetItemData(item); + linker.SetLinkType(EQEmu::saylink::SayLinkLootItem); + linker.SetLootData(*cur); auto item_link = linker.GenerateLink(); - to->Message(0, "%s, ID: %u, Level: (min: %u, max: %u)", item_link.c_str(), item->ID, (*cur)->min_level, (*cur)->max_level); + to->Message(0, "%s, ID: %u, Level: (min: %u, max: %u)", item_link.c_str(), (*cur)->item_id, (*cur)->min_level, (*cur)->max_level); } to->Message(0, "%i items on %s.", x, GetName()); From a6f5571750b1c39d5e9a6798a9599934d023e85d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 24 Oct 2016 13:29:07 -0400 Subject: [PATCH 420/693] Fix infinite loops --- zone/spells.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 4c01e1340..95e4fed06 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5653,12 +5653,16 @@ void Mob::BeamDirectional(uint16 spell_id, int16 resist_adjust) auto fac = (*iter)->GetReverseFactionCon(this); if (beneficial_targets) { // only affect mobs we would assist. - if (!(fac <= FACTION_AMIABLE)) + if (!(fac <= FACTION_AMIABLE)) { + ++iter; continue; + } } else { // affect mobs that are on our hate list, or which have bad faction with us - if (!(CheckAggro(*iter) || fac == FACTION_THREATENLY || fac == FACTION_SCOWLS)) + if (!(CheckAggro(*iter) || fac == FACTION_THREATENLY || fac == FACTION_SCOWLS)) { + ++iter; continue; + } } } @@ -5721,12 +5725,16 @@ void Mob::ConeDirectional(uint16 spell_id, int16 resist_adjust) auto fac = (*iter)->GetReverseFactionCon(this); if (beneficial_targets) { // only affect mobs we would assist. - if (!(fac <= FACTION_AMIABLE)) + if (!(fac <= FACTION_AMIABLE)) { + ++iter; continue; + } } else { // affect mobs that are on our hate list, or which have bad faction with us - if (!(CheckAggro(*iter) || fac == FACTION_THREATENLY || fac == FACTION_SCOWLS)) + if (!(CheckAggro(*iter) || fac == FACTION_THREATENLY || fac == FACTION_SCOWLS)) { + ++iter; continue; + } } } From 60406ebcc1579b08d6f6ea08fc0718b5f5ca909c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 25 Oct 2016 02:52:31 -0500 Subject: [PATCH 421/693] Test build notification --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a56251c19..e1753680b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # EQEmulator Core Server |Travis CI (Linux)|Appveyor (Windows) | -|:---:|:---:| +|:---:|:---:| |[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Windows CI](https://ci.appveyor.com/api/projects/status/d0cvokm7u732v8vl/branch/master?svg=true)](https://ci.appveyor.com/project/KimLS/server/branch/master) | *** From b9fefc95e82b4ae1d507c4dd75beb995cda6c331 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 25 Oct 2016 23:19:20 -0400 Subject: [PATCH 422/693] Enforce 4 sec Sneak Attack rule fixes #569 Spells flagged with SNEAK_ATTACK requires you to be hidden for about 4 seconds before you can cast them --- zone/aa.cpp | 5 +++++ zone/client_packet.cpp | 1 + zone/effects.cpp | 28 +++++++++++++++++----------- zone/mob.cpp | 3 ++- zone/mob.h | 1 + zone/spells.cpp | 5 ----- 6 files changed, 26 insertions(+), 17 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index b1fadf5e8..f175ba9ba 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1181,6 +1181,11 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { if (!IsCastWhileInvis(rank->spell)) CommonBreakInvisible(); + + if (spells[rank->spell].sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) { + Message_StringID(13, SNEAK_RESTRICT); + return; + } // Bards can cast instant cast AAs while they are casting another song if(spells[rank->spell].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 0b6221c2a..e05cc4f8c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -7911,6 +7911,7 @@ void Client::Handle_OP_Hide(const EQApplicationPacket *app) } else hidden = true; + tmHidden = Timer::GetCurrentTime(); } if (GetClass() == ROGUE){ auto outapp = new EQApplicationPacket(OP_SimpleMessage, sizeof(SimpleMessage_Struct)); diff --git a/zone/effects.cpp b/zone/effects.cpp index e2d9d4075..53cead938 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -630,17 +630,6 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { if(r == MAX_PP_DISCIPLINES) return(false); //not found. - //Check the disc timer - pTimerType DiscTimer = pTimerDisciplineReuseStart + spells[spell_id].EndurTimerIndex; - if(!p_timers.Expired(&database, DiscTimer)) { - /*char val1[20]={0};*/ //unused - /*char val2[20]={0};*/ //unused - uint32 remain = p_timers.GetRemainingTime(DiscTimer); - //Message_StringID(0, DISCIPLINE_CANUSEIN, ConvertArray((remain)/60,val1), ConvertArray(remain%60,val2)); - Message(0, "You can use this discipline in %d minutes %d seconds.", ((remain)/60), (remain%60)); - return(false); - } - //make sure we can use it.. if(!IsValidSpell(spell_id)) { Message(13, "This tome contains invalid knowledge."); @@ -667,6 +656,23 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { return(false); } + // sneak attack discs require you to be hidden for 4 seconds before use + if (spell.sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) { + Message_StringID(13, SNEAK_RESTRICT); + return false; + } + + //Check the disc timer + pTimerType DiscTimer = pTimerDisciplineReuseStart + spell.EndurTimerIndex; + if(!p_timers.Expired(&database, DiscTimer)) { + /*char val1[20]={0};*/ //unused + /*char val2[20]={0};*/ //unused + uint32 remain = p_timers.GetRemainingTime(DiscTimer); + //Message_StringID(0, DISCIPLINE_CANUSEIN, ConvertArray((remain)/60,val1), ConvertArray(remain%60,val2)); + Message(0, "You can use this discipline in %d minutes %d seconds.", ((remain)/60), (remain%60)); + return(false); + } + if(spell.recast_time > 0) { uint32 reduced_recast = spell.recast_time / 1000; diff --git a/zone/mob.cpp b/zone/mob.cpp index fbc82e63f..a39dcfa99 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -108,7 +108,8 @@ Mob::Mob(const char* in_name, m_TargetLocation(glm::vec3()), m_TargetV(glm::vec3()), flee_timer(FLEE_CHECK_TIMER), - m_Position(position) + m_Position(position), + tmHidden(-1) { targeted = 0; tar_ndx=0; diff --git a/zone/mob.h b/zone/mob.h index 94a251394..9d874c33b 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -762,6 +762,7 @@ public: inline const bodyType GetOrigBodyType() const { return orig_bodytype; } void SetBodyType(bodyType new_body, bool overwrite_orig); + uint32 tmHidden; // timestamp of hide, only valid while hidden == true uint8 invisible, see_invis; bool invulnerable, invisible_undead, invisible_animals, sneaking, hidden, improved_hidden; bool see_invis_undead, see_hide, see_improved_hide; diff --git a/zone/spells.cpp b/zone/spells.cpp index 95e4fed06..6b875c96f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3392,11 +3392,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r if(spelltar->IsClient() && spelltar->CastToClient()->IsHoveringForRespawn()) return false; - if (spells[spell_id].sneak && IsClient() && !CastToClient()->sneaking){ - Message_StringID(13, SNEAK_RESTRICT); - return false;//Fail Safe, this can cause a zone crash certain situations if you try to apply sneak effects when not sneaking. - } - if(IsDetrimentalSpell(spell_id) && !IsAttackAllowed(spelltar) && !IsResurrectionEffects(spell_id)) { if(!IsClient() || !CastToClient()->GetGM()) { Message_StringID(MT_SpellFailure, SPELL_NO_HOLD); From cbb7090615cc65817e4aefd4aca7e5510b00c8ca Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 28 Oct 2016 20:45:05 -0400 Subject: [PATCH 423/693] Fix SNEAK_RESTRICT Message Type --- zone/aa.cpp | 2 +- zone/effects.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index f175ba9ba..0f0617393 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1183,7 +1183,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { CommonBreakInvisible(); if (spells[rank->spell].sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) { - Message_StringID(13, SNEAK_RESTRICT); + Message_StringID(MT_SpellFailure, SNEAK_RESTRICT); return; } // Bards can cast instant cast AAs while they are casting another song diff --git a/zone/effects.cpp b/zone/effects.cpp index 53cead938..3e3f7a4bc 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -658,7 +658,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { // sneak attack discs require you to be hidden for 4 seconds before use if (spell.sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) { - Message_StringID(13, SNEAK_RESTRICT); + Message_StringID(MT_SpellFailure, SNEAK_RESTRICT); return false; } From a15df2ec2c70d3a353eea3ca67f501003fc2e2f9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 30 Oct 2016 22:41:24 -0400 Subject: [PATCH 424/693] Switch Master Wu to modern live implementation Classic Master Wu still exists setting Combat:ClassicMasterWu to true --- common/ruletypes.h | 1 + zone/special_attacks.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index bf35d03e8..febe13e33 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -491,6 +491,7 @@ RULE_BOOL(Combat, UseLiveCombatRounds, true) // turn this false if you don't wan RULE_INT(Combat, NPCAssistCap, 5) // Maxiumium number of NPCs that will assist another NPC at once RULE_INT(Combat, NPCAssistCapTimer, 6000) // Time in milliseconds a NPC will take to clear assist aggro cap space RULE_BOOL(Combat, UseRevampHandToHand, false) // use h2h revamped dmg/delays I believe this was implemented during SoF +RULE_BOOL(Combat, ClassicMasterWu, false) // classic master wu uses a random special, modern doesn't RULE_CATEGORY_END() RULE_CATEGORY(NPC) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index d582975e9..2f43d51c9 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -349,7 +349,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; if (wuchance) { if (wuchance >= 100 || zone->random.Roll(wuchance)) { - int MonkSPA[5] = { EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, EQEmu::skills::SkillRoundKick }; + const int MonkSPA[5] = { EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, EQEmu::skills::SkillRoundKick }; int extra = 1; // always 1/4 of the double attack chance, 25% at rank 5 (100/4) if (zone->random.Roll(wuchance / 4)) @@ -358,8 +358,9 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { std::string msg = StringFormat("The spirit of Master Wu fills you! You gain %d additional attack(s).", extra); // live uses 400 here -- not sure if it's the best for all clients though SendColoredText(400, msg); + auto classic = RuleB(Combat, ClassicMasterWu); while (extra) { - MonkSpecialAttack(GetTarget(), MonkSPA[zone->random.Int(0, 4)]); + MonkSpecialAttack(GetTarget(), classic ? MonkSPA[zone->random.Int(0, 4)] : ca_atk->m_skill); extra--; } } From a29177de9ef4ddc82e960f3530a2fa3c19b8f3b7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 30 Oct 2016 22:51:50 -0400 Subject: [PATCH 425/693] Fix zone/embparser.h header guard --- zone/embparser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/embparser.h b/zone/embparser.h index 8ae3fa10e..1e4c9c391 100644 --- a/zone/embparser.h +++ b/zone/embparser.h @@ -17,7 +17,7 @@ */ #ifndef EQEMU_EMBPARSER_H -#define EQMEU_EMBPARSER_H +#define EQEMU_EMBPARSER_H #ifdef EMBPERL #include "quest_parser_collection.h" From 7f4ce3faf508974904fbd5e292462cd0c2ffcf48 Mon Sep 17 00:00:00 2001 From: zerosum0x0 Date: Sun, 30 Oct 2016 22:04:10 -0600 Subject: [PATCH 426/693] fix potential plat creation exploit --- zone/client_process.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 55843e724..4a6e0403c 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -3,7 +3,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. + the Free Software Foundation; version 2 of the License.f This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY except by those people which sell it, which @@ -1194,6 +1194,12 @@ void Client::OPMoveCoin(const EQApplicationPacket* app) int32 *from_bucket = 0, *to_bucket = 0; Mob* trader = trade->With(); + // if amount < 0, client is sending a malicious packet + if (mc->amount < 0) + { + return; + } + // could just do a range, but this is clearer and explicit if ( From 66f253553aad7b7f9dba478318f9d84d15912a44 Mon Sep 17 00:00:00 2001 From: zerosum0x0 Date: Sun, 30 Oct 2016 22:12:46 -0600 Subject: [PATCH 427/693] Added an f like a dummy --- zone/client_process.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 4a6e0403c..632f953d7 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -3,7 +3,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License.f + the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY except by those people which sell it, which From cbe53951f8b1ad03097ec6849901db89c34c2b5e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 2 Nov 2016 13:36:04 -0400 Subject: [PATCH 428/693] Add missing ITEMTransfig1HB --- common/item_instance.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/common/item_instance.cpp b/common/item_instance.cpp index ab109bb41..268440dc8 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -613,6 +613,7 @@ bool EQEmu::ItemInstance::CanTransform(const ItemData *ItemToTry, const ItemData types["itemtransfig2hp"] = 35; types["itemtransfig2hs"] = 1; types["itemtransfigblunt"] = 3; + types["itemtransfig1hb"] = 3; types["itemtransfigbow"] = 5; types["itemtransfighth"] = 45; types["itemtransfigshield"] = 8; From b1f97712f1feb4f8b73a74342148bf833cba9496 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 3 Nov 2016 14:31:09 -0400 Subject: [PATCH 429/693] Quick fix for bulk XTarget updates This needs to be investigated more, but a 0 here for a valid mob is bad. --- zone/client.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 3f914d1ae..891591780 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7272,7 +7272,8 @@ void Client::SendXTargetUpdates() for (int i = 0; i < GetMaxXTargets(); ++i) { if (XTargets[i].dirty) { outapp->WriteUInt32(i); - outapp->WriteUInt8(0); // no idea what this is + // MQ2 checks this for valid mobs, so 0 is bad here at least ... + outapp->WriteUInt8(XTargets[i].ID ? 1 : 0); outapp->WriteUInt32(XTargets[i].ID); outapp->WriteString(XTargets[i].Name); count++; From 06e2f76c05df895cce895d0046c0e9d2b3eac1ca Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 5 Nov 2016 14:08:00 -0400 Subject: [PATCH 430/693] Implement SE_SummonToCorpse --- common/spdat.h | 2 +- zone/spell_effects.cpp | 1 + zone/worldserver.cpp | 8 +++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index 2734f6078..edb750f2a 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -485,7 +485,7 @@ typedef enum { #define SE_ManaAbsorbPercentDamage 329 // implemented #define SE_CriticalDamageMob 330 // implemented #define SE_Salvage 331 // implemented - chance to recover items that would be destroyed in failed tradeskill combine -//#define SE_SummonToCorpse 332 // *not implemented AA - Call of the Wild (Druid/Shaman Res spell with no exp) +#define SE_SummonToCorpse 332 // *not implemented AA - Call of the Wild (Druid/Shaman Res spell with no exp) #define SE_CastOnRuneFadeEffect 333 // implemented #define SE_BardAEDot 334 // implemented #define SE_BlockNextSpellFocus 335 // implemented - base1 chance to block next spell ie Puratus (8494) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 841457bdc..a2a66f9ae 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1650,6 +1650,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } + case SE_SummonToCorpse: case SE_Revive: { #ifdef SPELL_EFFECT_SPAM diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 28f3c5ab8..84d4cb399 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -722,10 +722,12 @@ void WorldServer::Process() { Log.Out(Logs::Detail, Logs::Spells, "OP_RezzComplete received in zone %s for corpse %s", zone->GetShortName(), srs->rez.corpse_name); - Log.Out(Logs::Detail, Logs::Spells, "Found corpse. Marking corpse as rezzed."); + Log.Out(Logs::Detail, Logs::Spells, "Found corpse. Marking corpse as rezzed if needed."); // I don't know why Rezzed is not set to true in CompleteRezz(). - corpse->IsRezzed(true); - corpse->CompleteResurrection(); + if (!IsEffectInSpell(srs->rez.spellid, SE_SummonToCorpse)) { + corpse->IsRezzed(true); + corpse->CompleteResurrection(); + } } } From 4af996e359ecceb786e0729f80ad53835d0f88c2 Mon Sep 17 00:00:00 2001 From: Athrogate Date: Wed, 9 Nov 2016 04:28:57 -0800 Subject: [PATCH 431/693] Adding GetLowestLevel() --- zone/lua_group.cpp | 5 +++++ zone/lua_group.h | 1 + 2 files changed, 6 insertions(+) diff --git a/zone/lua_group.cpp b/zone/lua_group.cpp index 23c12cae6..ee85c6e64 100644 --- a/zone/lua_group.cpp +++ b/zone/lua_group.cpp @@ -82,6 +82,11 @@ int Lua_Group::GetHighestLevel() { return self->GetHighestLevel(); } +int Lua_Group::GetLowestLevel() { + Lua_Safe_Call_Int(); + return self->GetLowestLevel(); +} + void Lua_Group::TeleportGroup(Lua_Mob sender, uint32 zone_id, uint32 instance_id, float x, float y, float z, float h) { Lua_Safe_Call_Void(); self->TeleportGroup(sender, zone_id, instance_id, x, y, z, h); diff --git a/zone/lua_group.h b/zone/lua_group.h index 399abbe2b..3d4020bbc 100644 --- a/zone/lua_group.h +++ b/zone/lua_group.h @@ -40,6 +40,7 @@ public: bool IsLeader(Lua_Mob leader); int GroupCount(); int GetHighestLevel(); + int GetLowestLevel(); void TeleportGroup(Lua_Mob sender, uint32 zone_id, uint32 instance_id, float x, float y, float z, float h); int GetID(); Lua_Mob GetMember(int index); From 72e7465e1602103ad6f8409de65356e522a71036 Mon Sep 17 00:00:00 2001 From: Athrogate Date: Wed, 9 Nov 2016 04:41:09 -0800 Subject: [PATCH 432/693] Lua GetLowestLevel() --- zone/lua_group.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/lua_group.cpp b/zone/lua_group.cpp index ee85c6e64..fc0ce7bb5 100644 --- a/zone/lua_group.cpp +++ b/zone/lua_group.cpp @@ -126,6 +126,7 @@ luabind::scope lua_register_group() { .def("IsLeader", (bool(Lua_Group::*)(Lua_Mob))&Lua_Group::IsLeader) .def("GroupCount", (int(Lua_Group::*)(void))&Lua_Group::GroupCount) .def("GetHighestLevel", (int(Lua_Group::*)(void))&Lua_Group::GetHighestLevel) + .def("GetLowestLevel", (int(Lua_Group::*)(void))&Lua_Group::GetLowestLevel) .def("TeleportGroup", (void(Lua_Group::*)(Lua_Mob,uint32,uint32,float,float,float,float))&Lua_Group::TeleportGroup) .def("GetID", (int(Lua_Group::*)(void))&Lua_Group::GetID) .def("GetMember", (Lua_Mob(Lua_Group::*)(int))&Lua_Group::GetMember); From b3842ba72a50df28dc2a7ad7d8420d19583faf3e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 9 Nov 2016 12:14:24 -0500 Subject: [PATCH 433/693] Fix indent --- zone/lua_group.cpp | 4 ++-- zone/lua_group.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/lua_group.cpp b/zone/lua_group.cpp index fc0ce7bb5..f297d72f1 100644 --- a/zone/lua_group.cpp +++ b/zone/lua_group.cpp @@ -83,8 +83,8 @@ int Lua_Group::GetHighestLevel() { } int Lua_Group::GetLowestLevel() { - Lua_Safe_Call_Int(); - return self->GetLowestLevel(); + Lua_Safe_Call_Int(); + return self->GetLowestLevel(); } void Lua_Group::TeleportGroup(Lua_Mob sender, uint32 zone_id, uint32 instance_id, float x, float y, float z, float h) { diff --git a/zone/lua_group.h b/zone/lua_group.h index 3d4020bbc..e1aa2a11d 100644 --- a/zone/lua_group.h +++ b/zone/lua_group.h @@ -40,7 +40,7 @@ public: bool IsLeader(Lua_Mob leader); int GroupCount(); int GetHighestLevel(); - int GetLowestLevel(); + int GetLowestLevel(); void TeleportGroup(Lua_Mob sender, uint32 zone_id, uint32 instance_id, float x, float y, float z, float h); int GetID(); Lua_Mob GetMember(int index); From e7e379c71b39f991b467aab26ee6f1da4e6db6e8 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 10 Nov 2016 11:28:06 -0600 Subject: [PATCH 434/693] Fix map loading logic so that case sensitive checks are made in the following order: maps, Maps, and if neither of those two exist, then value would take precedence. - Added some log messages for what version of map is being loaded versus MMF --- zone/map.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/zone/map.cpp b/zone/map.cpp index 29a386331..9a5ab8e10 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -268,8 +268,23 @@ bool Map::CheckLoS(glm::vec3 myloc, glm::vec3 oloc) const { return !imp->rm->raycast((const RmReal*)&myloc, (const RmReal*)&oloc, nullptr, nullptr, nullptr); } +inline bool file_exists(const std::string& name) { + std::ifstream f(name.c_str()); + return f.good(); +} + Map *Map::LoadMapFile(std::string file) { - std::string filename = Config->MapDir; + + std::string filename = ""; + if (file_exists("maps")) { + filename = "maps"; + } + else if (file_exists("Maps")) { + filename = "Maps"; + } + else { + filename = Config->MapDir; + } std::transform(file.begin(), file.end(), file.begin(), ::tolower); filename += file; filename += ".map"; @@ -287,7 +302,7 @@ Map *Map::LoadMapFile(std::string file) { bool Map::Load(std::string filename, bool force_mmf_overwrite) { if (LoadMMF(filename, force_mmf_overwrite)) { - Log.Out(Logs::General, Logs::Zone_Server, "Zone map mmf found - using it in lieu of '%s'", filename.c_str()); + Log.Out(Logs::General, Logs::Zone_Server, "Loaded .MMF Map File in place of '%s'", filename.c_str()); return true; } #else @@ -304,6 +319,7 @@ bool Map::Load(std::string filename) } if(version == 0x01000000) { + Log.Out(Logs::General, Logs::Zone_Server, "Loaded V1 Map File :: '%s'", filename.c_str()); bool v = LoadV1(f); fclose(f); @@ -314,6 +330,7 @@ bool Map::Load(std::string filename) return v; } else if(version == 0x02000000) { + Log.Out(Logs::General, Logs::Zone_Server, "Loaded V2 Map File :: '%s'", filename.c_str()); bool v = LoadV2(f); fclose(f); From 34ffb5b90827cf907c90e4a84b0c158a3f9ff847 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 10 Nov 2016 12:00:44 -0600 Subject: [PATCH 435/693] Create shared_memory directory from the config file if it doesn't exist on launch of shared_memory.exe --- common/emu_legacy.h | 1 + shared_memory/main.cpp | 38 ++++++++++++++++++++++++++++++++++++++ zone/map.cpp | 6 +++--- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/common/emu_legacy.h b/common/emu_legacy.h index b70d7143c..a624be883 100644 --- a/common/emu_legacy.h +++ b/common/emu_legacy.h @@ -176,6 +176,7 @@ namespace EQEmu static const size_t TEXT_LINK_BODY_LENGTH = 56; } + } #endif /* COMMON_EMU_LEGACY_H */ diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 79824251f..8f9ad4255 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -36,6 +36,39 @@ EQEmuLogSys Log; +#ifdef _WINDOWS +#include +#else +#include +#include +#endif + +inline bool MakeDirectory(const std::string &directory_name) +{ +#ifdef _WINDOWS + struct _stat st; + if (_stat(directory_name.c_str(), &st) == 0) { + return false; + } + else { + _mkdir(directory_name.c_str()); + return true; + } + +#else + struct stat st; + if (stat(directory_name.c_str(), &st) == 0) { + return false; + } + else { + mkdir(directory_name.c_str(), 0755); + return true; + } + +#endif + return false; +} + int main(int argc, char **argv) { RegisterExecutablePlatform(ExePlatformSharedMemory); Log.LoadLogSettingsDefaults(); @@ -62,6 +95,11 @@ int main(int argc, char **argv) { database.LoadLogSettings(Log.log_settings); Log.StartFileLogs(); + std::string shared_mem_directory = Config->SharedMemDir; + if (MakeDirectory(shared_mem_directory)) { + Log.Out(Logs::General, Logs::Status, "Shared Memory folder doesn't exist, so we created it... '%s'", shared_mem_directory.c_str()); + } + database.LoadVariables(); /* If we're running shared memory and hotfix has no custom name, we probably want to start from scratch... */ diff --git a/zone/map.cpp b/zone/map.cpp index 9a5ab8e10..b4daca584 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -302,7 +302,7 @@ Map *Map::LoadMapFile(std::string file) { bool Map::Load(std::string filename, bool force_mmf_overwrite) { if (LoadMMF(filename, force_mmf_overwrite)) { - Log.Out(Logs::General, Logs::Zone_Server, "Loaded .MMF Map File in place of '%s'", filename.c_str()); + Log.Out(Logs::General, Logs::Status, "Loaded .MMF Map File in place of '%s'", filename.c_str()); return true; } #else @@ -319,7 +319,7 @@ bool Map::Load(std::string filename) } if(version == 0x01000000) { - Log.Out(Logs::General, Logs::Zone_Server, "Loaded V1 Map File :: '%s'", filename.c_str()); + Log.Out(Logs::General, Logs::Status, "Loaded V1 Map File :: '%s'", filename.c_str()); bool v = LoadV1(f); fclose(f); @@ -330,7 +330,7 @@ bool Map::Load(std::string filename) return v; } else if(version == 0x02000000) { - Log.Out(Logs::General, Logs::Zone_Server, "Loaded V2 Map File :: '%s'", filename.c_str()); + Log.Out(Logs::General, Logs::Status, "Loaded V2 Map File :: '%s'", filename.c_str()); bool v = LoadV2(f); fclose(f); From cb1d0a0bef7d9afca83524e6a9351b74dc669010 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Thu, 10 Nov 2016 15:42:20 -0500 Subject: [PATCH 436/693] Fixed #npcspawn update. --- zone/npc.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index b2b3ff48c..d1255f8aa 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1213,12 +1213,13 @@ uint32 ZoneDatabase::AddNewNPCSpawnGroupCommand(const char *zone, uint32 zone_ve uint32 ZoneDatabase::UpdateNPCTypeAppearance(Client *client, NPC *spawn) { std::string query = - StringFormat("UPDATE npc_types SET name = \"%s\", level = %i, race = %i, class = %i, " - "hp = %i, gender = %i, texture = %i, helmtexture = %i, size = %i, " - "loottable_id = %i, merchant_id = %i, face = %i, WHERE id = %i", + StringFormat("UPDATE npc_types SET name = '%s', level = '%i', race = '%i', class = '%i', " + "hp = '%i', gender = '%i', texture = '%i', helmtexture = '%i', size = '%i', " + "loottable_id = '%i', merchant_id = '%i', face = '%i' " + "WHERE id = '%i'", spawn->GetName(), spawn->GetLevel(), spawn->GetRace(), spawn->GetClass(), spawn->GetMaxHP(), spawn->GetGender(), spawn->GetTexture(), spawn->GetHelmTexture(), spawn->GetSize(), - spawn->GetLoottableID(), spawn->MerchantType, spawn->GetNPCTypeID()); + spawn->GetLoottableID(), spawn->MerchantType, spawn->GetLuclinFace(), spawn->GetNPCTypeID()); auto results = QueryDatabase(query); return results.Success() == true ? 1 : 0; } From 3447c86562f3c17381f03ff758bf1736dc3400c9 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 11 Nov 2016 18:59:47 -0500 Subject: [PATCH 437/693] Fix for windows compile (stat-use related) --- shared_memory/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 8f9ad4255..d80c22156 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -40,8 +40,8 @@ EQEmuLogSys Log; #include #else #include -#include #endif +#include inline bool MakeDirectory(const std::string &directory_name) { From e8d80a436e6d70dcea536027c5b494942b8a47a9 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 11 Nov 2016 22:31:54 -0600 Subject: [PATCH 438/693] Add map debugging [skip ci] --- zone/map.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/map.cpp b/zone/map.cpp index b4daca584..691e751b2 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -289,6 +289,8 @@ Map *Map::LoadMapFile(std::string file) { filename += file; filename += ".map"; + Log.Out(Logs::General, Logs::Status, "Attempting to load Map File :: '%s'", filename.c_str()); + auto m = new Map(); if (m->Load(filename)) { return m; From 04c8fe7d2cb851f2de56c6aeef2bbcaca2762ddb Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 11 Nov 2016 22:39:08 -0600 Subject: [PATCH 439/693] Fix map loading paths for both platforms --- zone/map.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/map.cpp b/zone/map.cpp index 691e751b2..ceef7894a 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -286,6 +286,7 @@ Map *Map::LoadMapFile(std::string file) { filename = Config->MapDir; } std::transform(file.begin(), file.end(), file.begin(), ::tolower); + filename += "/"; filename += file; filename += ".map"; From 3dec02881a2b272292639cf26757d63c182cd09b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 15 Nov 2016 01:37:58 -0500 Subject: [PATCH 440/693] Revamp Buff slots Server side we now have 63 total buff slots for clients They match RoF/RoF2 and are mapped as 42 long, 20 short, 1 disc The player is limited to what their clients supports, so Tit players can have 25 buffs and 12 songs, while other can have more When you log in, we only load up to the max your client supports, the rest of the buffs are thrown away Also changed is the default Max Buff slots for NPCs, they now match Tit (60) If you are thinking about raising that, here are what some other clients support Tit - SoF 60, SoD - UF 85, RoF - RoF2 97 (although UI only has 85 slots, you can edit it if you want more) Also SoD+ the pet limits match the NPC limits. This will increase memory usage a bit, but I don't see a solution to that Plus I think most people want this. --- common/emu_constants.h | 8 ++++ common/eq_limits.cpp | 68 +++++++++++++++++++++++++++++--- common/eq_limits.h | 7 ++++ common/patches/rof.cpp | 60 +++++++++++++++++----------- common/patches/rof2.cpp | 67 +++++++++++++++++-------------- common/patches/rof2_limits.h | 8 ++++ common/patches/rof_limits.h | 8 ++++ common/patches/sod.cpp | 35 ++++++++++++++-- common/patches/sod_limits.h | 8 ++++ common/patches/sof.cpp | 33 +++++++++++++++- common/patches/sof_limits.h | 8 ++++ common/patches/titanium.cpp | 33 +++++++++++++++- common/patches/titanium_limits.h | 8 ++++ common/patches/uf.cpp | 55 ++++++++++++++++---------- common/patches/uf_limits.h | 40 +++++++++++-------- common/ruletypes.h | 10 ++--- zone/client.h | 8 ++-- zone/spells.cpp | 4 +- zone/zonedb.cpp | 3 +- 19 files changed, 358 insertions(+), 113 deletions(-) diff --git a/common/emu_constants.h b/common/emu_constants.h index 9e44976a8..e156fe98a 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -116,6 +116,14 @@ namespace EQEmu const size_t SayLinkBodySize = RoF2::constants::SayLinkBodySize; + const int LongBuffs = RoF2::constants::LongBuffs; + const int ShortBuffs = RoF2::constants::ShortBuffs; + const int DiscBuffs = RoF2::constants::DiscBuffs; + const int TotalBuffs = RoF2::constants::TotalBuffs; + const int NPCBuffs = RoF2::constants::NPCBuffs; + const int PetBuffs = RoF2::constants::PetBuffs; + const int MercBuffs = RoF2::constants::MercBuffs; + } /*constants*/ enum class CastingSlot : uint32 { diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 1c0140811..ce94c4359 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -24,28 +24,84 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versions::ClientVersionCount] = { { + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, + ClientUnknown::Null, ClientUnknown::Null }, { + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, + Client62::Null, Client62::Null }, { - Titanium::constants::CharacterCreationLimit + Titanium::constants::CharacterCreationLimit, + Titanium::constants::LongBuffs, + Titanium::constants::ShortBuffs, + Titanium::constants::DiscBuffs, + Titanium::constants::TotalBuffs, + Titanium::constants::NPCBuffs, + Titanium::constants::PetBuffs, + Titanium::constants::MercBuffs }, { - SoF::constants::CharacterCreationLimit + SoF::constants::CharacterCreationLimit, + SoF::constants::LongBuffs, + SoF::constants::ShortBuffs, + SoF::constants::DiscBuffs, + SoF::constants::TotalBuffs, + SoF::constants::NPCBuffs, + SoF::constants::PetBuffs, + SoF::constants::MercBuffs }, { - SoD::constants::CharacterCreationLimit + SoD::constants::CharacterCreationLimit, + SoD::constants::LongBuffs, + SoD::constants::ShortBuffs, + SoD::constants::DiscBuffs, + SoD::constants::TotalBuffs, + SoD::constants::NPCBuffs, + SoD::constants::PetBuffs, + SoD::constants::MercBuffs }, { - UF::constants::CharacterCreationLimit + UF::constants::CharacterCreationLimit, + UF::constants::LongBuffs, + UF::constants::ShortBuffs, + UF::constants::DiscBuffs, + UF::constants::TotalBuffs, + UF::constants::NPCBuffs, + UF::constants::PetBuffs, + UF::constants::MercBuffs }, { - RoF::constants::CharacterCreationLimit + RoF::constants::CharacterCreationLimit, + RoF::constants::LongBuffs, + RoF::constants::ShortBuffs, + RoF::constants::DiscBuffs, + RoF::constants::TotalBuffs, + RoF::constants::NPCBuffs, + RoF::constants::PetBuffs, + RoF::constants::MercBuffs }, { - RoF2::constants::CharacterCreationLimit + RoF2::constants::CharacterCreationLimit, + RoF2::constants::LongBuffs, + RoF2::constants::ShortBuffs, + RoF2::constants::DiscBuffs, + RoF2::constants::TotalBuffs, + RoF2::constants::NPCBuffs, + RoF2::constants::PetBuffs, + RoF2::constants::MercBuffs } }; diff --git a/common/eq_limits.h b/common/eq_limits.h index 72d710998..252d23053 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -38,6 +38,13 @@ namespace EQEmu class LookupEntry { public: size_t CharacterCreationLimit; + int LongBuffs; + int ShortBuffs; + int DiscBuffs; + int TotalBuffs; + int NPCBuffs; + int PetBuffs; + int MercBuffs; }; const LookupEntry* Lookup(versions::ClientVersion client_version); diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 5793e6392..980a4f4ed 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -66,6 +66,9 @@ namespace RoF static inline CastingSlot ServerToRoFCastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot RoFToServerCastingSlot(CastingSlot slot); + static inline int ServerToRoFBuffSlot(int index); + static inline int RoFToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -423,15 +426,8 @@ namespace RoF OUT(buff.y); OUT(buff.x); OUT(buff.z); - uint16 buffslot = emu->slotid; - // Not sure if this is needs amending for RoF yet. - if (buffslot >= 25) - { - buffslot += 17; - } - // TODO: implement slot_data stuff - eq->slotid = buffslot; + eq->slotid = ServerToRoFBuffSlot(emu->slotid); if (emu->bufffade == 1) eq->bufffade = 1; @@ -447,10 +443,10 @@ namespace RoF outapp->WriteUInt32(0); // tic timer outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ? outapp->WriteUInt16(1); // 1 buff in this packet - outapp->WriteUInt32(buffslot); + outapp->WriteUInt32(eq->slotid); outapp->WriteUInt32(0xffffffff); // SpellID (0xffff to remove) outapp->WriteUInt32(0); // Duration - outapp->WriteUInt32(0); // ? + outapp->WriteUInt32(0); // numhits outapp->WriteUInt8(0); // Caster name outapp->WriteUInt8(0); // Type } @@ -474,17 +470,9 @@ namespace RoF __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) + for (int i = 0; i < emu->count; ++i) { - uint16 buffslot = emu->entries[i].buff_slot; - if (emu->type == 0) { // only correct for self packets - if (emu->entries[i].buff_slot >= 25) - buffslot += 17; - if (buffslot == 54) - buffslot = 62; - } - - __packet->WriteUInt32(buffslot); + __packet->WriteUInt32(emu->type == 0 ? ServerToRoFBuffSlot(emu->entries[i].buff_slot) : emu->entries[i].buff_slot); __packet->WriteUInt32(emu->entries[i].spell_id); __packet->WriteUInt32(emu->entries[i].tics_remaining); __packet->WriteUInt32(emu->entries[i].num_hits); // Unknown @@ -4312,7 +4300,7 @@ namespace RoF IN(buff.unknown003); IN(buff.spellid); IN(buff.duration); - IN(slotid); + emu->slotid = RoFToServerBuffSlot(eq->slotid); IN(bufffade); FINISH_DIRECT_DECODE(); @@ -4325,7 +4313,7 @@ namespace RoF DECODE_LENGTH_EXACT(structs::BuffRemoveRequest_Struct); SETUP_DIRECT_DECODE(BuffRemoveRequest_Struct, structs::BuffRemoveRequest_Struct); - emu->SlotID = (eq->SlotID < 42) ? eq->SlotID : (eq->SlotID - 17); + emu->SlotID = RoFToServerBuffSlot(eq->SlotID); IN(EntityID); @@ -6084,4 +6072,32 @@ namespace RoF return EQEmu::CastingSlot::Discipline; } } + + // these should be optimized out for RoF since they should all boil down to return index :P + // but lets leave it here for future proofing + static inline int ServerToRoFBuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int RoFToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*RoF*/ diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index c19203d8a..d14008e93 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -66,6 +66,9 @@ namespace RoF2 static inline CastingSlot ServerToRoF2CastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot RoF2ToServerCastingSlot(CastingSlot slot); + static inline int ServerToRoF2BuffSlot(int index); + static inline int RoF2ToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -492,18 +495,7 @@ namespace RoF2 OUT(buff.y); OUT(buff.x); OUT(buff.z); - uint16 buffslot = emu->slotid; - // Not sure if this is needs amending for RoF2 yet. - if (buffslot >= 25) - { - buffslot += 17; - } - // TODO: We should really just deal with these "server side" - // so we can have clients not limited to other clients. - // This fixes discs, songs were changed to 20 - if (buffslot == 54) - buffslot = 62; - eq->slotid = buffslot; + eq->slotid = ServerToRoF2BuffSlot(emu->slotid); // TODO: implement slot_data stuff if (emu->bufffade == 1) eq->bufffade = 1; @@ -519,10 +511,10 @@ namespace RoF2 outapp->WriteUInt32(0); // tic timer outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ? outapp->WriteUInt16(1); // 1 buff in this packet - outapp->WriteUInt32(buffslot); + outapp->WriteUInt32(eq->slotid); outapp->WriteUInt32(0xffffffff); // SpellID (0xffff to remove) outapp->WriteUInt32(0); // Duration - outapp->WriteUInt32(0); // ? + outapp->WriteUInt32(0); // numhits outapp->WriteUInt8(0); // Caster name outapp->WriteUInt8(0); // Type } @@ -546,20 +538,9 @@ namespace RoF2 __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) + for (int i = 0; i < emu->count; ++i) { - uint16 buffslot = emu->entries[i].buff_slot; - if (emu->type == 0) { // only correct for self packets - if (emu->entries[i].buff_slot >= 25) - buffslot += 17; - // TODO: We should really just deal with these "server side" - // so we can have clients not limited to other clients. - // This fixes discs, songs were changed to 20 - if (buffslot == 54) - buffslot = 62; - } - - __packet->WriteUInt32(buffslot); + __packet->WriteUInt32(emu->type == 0 ? ServerToRoF2BuffSlot(emu->entries[i].buff_slot) : emu->entries[i].buff_slot); __packet->WriteUInt32(emu->entries[i].spell_id); __packet->WriteUInt32(emu->entries[i].tics_remaining); __packet->WriteUInt32(emu->entries[i].num_hits); // Unknown @@ -4550,7 +4531,7 @@ namespace RoF2 IN(buff.unknown003); IN(buff.spellid); IN(buff.duration); - IN(slotid); + emu->slotid = RoF2ToServerBuffSlot(eq->slotid); IN(bufffade); FINISH_DIRECT_DECODE(); @@ -4563,7 +4544,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::BuffRemoveRequest_Struct); SETUP_DIRECT_DECODE(BuffRemoveRequest_Struct, structs::BuffRemoveRequest_Struct); - emu->SlotID = (eq->SlotID < 42) ? eq->SlotID : (eq->SlotID - 17); + emu->SlotID = RoF2ToServerBuffSlot(eq->SlotID); IN(EntityID); @@ -6388,4 +6369,32 @@ namespace RoF2 return EQEmu::CastingSlot::Discipline; } } + + // these should be optimized out for RoF2 since they should all boil down to return index :P + // but lets leave it here for future proofing + static inline int ServerToRoF2BuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int RoF2ToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*RoF2*/ diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index fb2f997ca..6f4e649ff 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -277,6 +277,14 @@ namespace RoF2 const size_t SayLinkBodySize = 56; + const int LongBuffs = 42; + const int ShortBuffs = 20; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 97; + const int PetBuffs = NPCBuffs; + const int MercBuffs = LongBuffs; + } /*constants*/ namespace behavior { diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index ed0b9a6d0..952d14b20 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -268,6 +268,14 @@ namespace RoF const size_t SayLinkBodySize = 55; + const int LongBuffs = 42; + const int ShortBuffs = 20; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 97; + const int PetBuffs = NPCBuffs; + const int MercBuffs = LongBuffs; + } /*constants*/ namespace behavior { diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 330f7ee20..a3872e9c9 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -62,6 +62,9 @@ namespace SoD static inline CastingSlot ServerToSoDCastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot SoDToServerCastingSlot(CastingSlot slot); + static inline int ServerToSoDBuffSlot(int index); + static inline int SoDToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -315,7 +318,7 @@ namespace SoD OUT(buff.duration); OUT(buff.counters); OUT(buff.player_id); - OUT(slotid); + eq->slotid = ServerToSoDBuffSlot(emu->slotid); OUT(bufffade); FINISH_ENCODE(); @@ -2921,8 +2924,8 @@ namespace SoD IN(buff.bard_modifier); IN(buff.spellid); IN(buff.duration); - IN(buff.counters) - IN(slotid); + IN(buff.counters); + emu->slotid = SoDToServerBuffSlot(eq->slotid); IN(bufffade); FINISH_DIRECT_DECODE(); @@ -4088,4 +4091,30 @@ namespace SoD return EQEmu::CastingSlot::Discipline; } } + + static inline int ServerToSoDBuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int SoDToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*SoD*/ diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index fa2c29317..8f8031a3d 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -295,6 +295,14 @@ namespace SoD const size_t SayLinkBodySize = 50; + const int LongBuffs = 25; + const int ShortBuffs = 15; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 85; + const int PetBuffs = NPCBuffs; + const int MercBuffs = LongBuffs; + } /*constants*/ namespace behavior { diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 59e0edb5f..9009979ef 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -62,6 +62,9 @@ namespace SoF static inline CastingSlot ServerToSoFCastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot SoFToServerCastingSlot(CastingSlot slot, uint32 itemlocation); + static inline int ServerToSoFBuffSlot(int index); + static inline int SoFToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -297,7 +300,7 @@ namespace SoF OUT(buff.duration); OUT(buff.counters); OUT(buff.player_id); - OUT(slotid); + eq->slotid = ServerToSoFBuffSlot(emu->slotid); OUT(bufffade); FINISH_ENCODE(); @@ -2375,7 +2378,7 @@ namespace SoF IN(buff.duration); IN(buff.counters); IN(buff.player_id); - IN(slotid); + emu->slotid = SoFToServerBuffSlot(eq->slotid); IN(bufffade); FINISH_DIRECT_DECODE(); @@ -3461,4 +3464,30 @@ namespace SoF return EQEmu::CastingSlot::Discipline; } } + + static inline int ServerToSoFBuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int SoFToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*SoF*/ diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 575df39ba..d34197a90 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -295,6 +295,14 @@ namespace SoF const size_t SayLinkBodySize = 50; + const int LongBuffs = 25; + const int ShortBuffs = 15; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 60; + const int PetBuffs = 30; + const int MercBuffs = 0; + } /*constants*/ namespace behavior { diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 286d09d1b..1c7033186 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -61,6 +61,9 @@ namespace Titanium static inline CastingSlot ServerToTitaniumCastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot TitaniumToServerCastingSlot(CastingSlot slot, uint32 itemlocation); + static inline int ServerToTitaniumBuffSlot(int index); + static inline int TitaniumToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { auto Config = EQEmuConfig::get(); @@ -270,7 +273,7 @@ namespace Titanium OUT(buff.duration); OUT(buff.counters); OUT(buff.player_id); - OUT(slotid); + eq->slotid = ServerToTitaniumBuffSlot(emu->slotid); OUT(bufffade); FINISH_ENCODE(); @@ -1779,7 +1782,7 @@ namespace Titanium IN(buff.duration); IN(buff.counters); IN(buff.player_id); - IN(slotid); + emu->slotid = TitaniumToServerBuffSlot(eq->slotid); IN(bufffade); FINISH_DIRECT_DECODE(); @@ -2632,4 +2635,30 @@ namespace Titanium return EQEmu::CastingSlot::Discipline; } } + + static inline int ServerToTitaniumBuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int TitaniumToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*Titanium*/ diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index e631f8492..3266ade6f 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -294,6 +294,14 @@ namespace Titanium const size_t SayLinkBodySize = 45; + const int LongBuffs = 25; + const int ShortBuffs = 12; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 60; + const int PetBuffs = 30; + const int MercBuffs = 0; + } /*constants*/ namespace behavior { diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 92be237b1..061444bea 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -62,6 +62,9 @@ namespace UF static inline CastingSlot ServerToUFCastingSlot(EQEmu::CastingSlot slot); static inline EQEmu::CastingSlot UFToServerCastingSlot(CastingSlot slot); + static inline int ServerToUFBuffSlot(int index); + static inline int UFToServerBuffSlot(int index); + void Register(EQStreamIdentifier &into) { //create our opcode manager if we havent already @@ -377,17 +380,8 @@ namespace UF OUT(buff.spellid); OUT(buff.duration); OUT(buff.num_hits); - uint16 buffslot = emu->slotid; - if (buffslot >= 25 && buffslot < 37) - { - buffslot += 5; - } - else if (buffslot >= 37) - { - buffslot += 14; - } // TODO: implement slot_data stuff - eq->slotid = buffslot; + eq->slotid = ServerToUFBuffSlot(emu->slotid); OUT(bufffade); // Live (October 2011) sends a 2 rather than 0 when a buff is created, but it doesn't seem to matter. FINISH_ENCODE(); @@ -407,17 +401,9 @@ namespace UF __packet->WriteUInt8(emu->all_buffs); // 1 = all buffs, 0 = 1 buff __packet->WriteUInt16(emu->count); - for (uint16 i = 0; i < emu->count; ++i) + for (int i = 0; i < emu->count; ++i) { - uint16 buffslot = emu->entries[i].buff_slot; - if (emu->type == 0) { // only correct for self packets - if (emu->entries[i].buff_slot >= 25 && emu->entries[i].buff_slot < 37) - buffslot += 5; - else if (emu->entries[i].buff_slot >= 37) - buffslot += 14; - } - - __packet->WriteUInt32(buffslot); + __packet->WriteUInt32(emu->type == 0 ? ServerToUFBuffSlot(emu->entries[i].buff_slot) : emu->entries[i].buff_slot); __packet->WriteUInt32(emu->entries[i].spell_id); __packet->WriteUInt32(emu->entries[i].tics_remaining); __packet->WriteUInt32(emu->entries[i].num_hits); @@ -3236,6 +3222,7 @@ namespace UF IN(buff.unknown003); IN(buff.spellid); IN(buff.duration); + emu->slotid = UFToServerBuffSlot(eq->slotid); IN(slotid); IN(bufffade); @@ -3249,7 +3236,7 @@ namespace UF DECODE_LENGTH_EXACT(structs::BuffRemoveRequest_Struct); SETUP_DIRECT_DECODE(BuffRemoveRequest_Struct, structs::BuffRemoveRequest_Struct); - emu->SlotID = (eq->SlotID < 30) ? eq->SlotID : (eq->SlotID - 5); + emu->SlotID = UFToServerBuffSlot(eq->SlotID); IN(EntityID); @@ -4453,4 +4440,30 @@ namespace UF return EQEmu::CastingSlot::Discipline; } } + + static inline int ServerToUFBuffSlot(int index) + { + // we're a disc + if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) + return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + + constants::LongBuffs + constants::ShortBuffs; + // we're a song + if (index >= EQEmu::constants::LongBuffs) + return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } + + static inline int UFToServerBuffSlot(int index) + { + // we're a disc + if (index >= constants::LongBuffs + constants::ShortBuffs) + return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + + EQEmu::constants::ShortBuffs; + // we're a song + if (index >= constants::LongBuffs) + return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + // we're a normal buff + return index; // as long as we guard against bad slots server side, we should be fine + } } /*UF*/ diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index 2e799ac0c..719fcc394 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -64,7 +64,7 @@ namespace UF InvTypeOther, InvTypeCount }; - + } /*invtype*/ namespace invslot { @@ -115,21 +115,21 @@ namespace UF const int GeneralBegin = PossessionsGeneral1; const int GeneralEnd = PossessionsGeneral8; const int GeneralCount = (GeneralEnd - GeneralBegin + 1); - + } /*invslot*/ namespace invbag { inline EQEmu::versions::ClientVersion GetInvBagRef() { return EQEmu::versions::ClientVersion::UF; } enum : int { InvBagInvalid = -1, InvBagBegin }; - + } /*invbag*/ namespace invaug { inline EQEmu::versions::ClientVersion GetInvAugRef() { return EQEmu::versions::ClientVersion::UF; } enum : int { InvAugInvalid = -1, InvAugBegin }; - + } /*invaug*/ namespace item { @@ -148,27 +148,27 @@ namespace UF ItemPacketCharmUpdate = 110, ItemPacket11 = 111 }; - + } /*item*/ namespace profile { inline EQEmu::versions::ClientVersion GetProfileRef() { return EQEmu::versions::ClientVersion::UF; } - + } /*profile*/ namespace constants { inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::UF; } - + } /*constants*/ namespace behavior { inline EQEmu::versions::ClientVersion GetBehaviorRef() { return EQEmu::versions::ClientVersion::UF; } - + } /*behavior*/ namespace skills { inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::UF; } - + } /*skills*/ @@ -208,7 +208,7 @@ namespace UF extern const char* GetInvTypeName(int inv_type); extern bool IsInvTypePersistent(int inv_type); - + } /*invtype*/ namespace invslot { @@ -237,7 +237,7 @@ namespace UF extern const char* GetInvPossessionsSlotName(int inv_slot); extern const char* GetInvCorpseSlotName(int inv_slot); extern const char* GetInvSlotName(int inv_type, int inv_slot); - + } /*invslot*/ namespace invbag { @@ -264,7 +264,7 @@ namespace UF const int TradeBagsEnd = (TradeBagsBegin + TradeBagsSize) - 1; extern const char* GetInvBagIndexName(int bag_index); - + } /*invbag*/ namespace invaug { @@ -288,24 +288,32 @@ namespace UF const size_t PotionBeltSize = 5; const size_t SkillArraySize = 100; - + } /*profile*/ namespace constants { const size_t CharacterCreationLimit = 12; const size_t SayLinkBodySize = 50; - + + const int LongBuffs = 30; + const int ShortBuffs = 20; + const int DiscBuffs = 1; + const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; + const int NPCBuffs = 85; + const int PetBuffs = NPCBuffs; + const int MercBuffs = LongBuffs; + } /*constants*/ namespace behavior { const bool CoinHasWeight = false; - + } /*behavior*/ namespace skills { const size_t LastUsableSkill = EQEmu::skills::SkillTripleAttack; - + } /*skills*/ }; /*UF*/ diff --git a/common/ruletypes.h b/common/ruletypes.h index 0f424072d..9a18ff063 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -333,11 +333,11 @@ RULE_INT(Spells, SacrificeMinLevel, 46) //first level Sacrifice will work on RULE_INT(Spells, SacrificeMaxLevel, 69) //last level Sacrifice will work on RULE_INT(Spells, SacrificeItemID, 9963) //Item ID of the item Sacrifice will return (defaults to an EE) RULE_BOOL(Spells, EnableSpellGlobals, false) // If Enabled, spells check the spell_globals table and compare character data from the quest globals before allowing that spell to scribe with scribespells -RULE_INT(Spells, MaxBuffSlotsNPC, 25) -RULE_INT(Spells, MaxSongSlotsNPC, 10) -RULE_INT(Spells, MaxDiscSlotsNPC, 1) -RULE_INT(Spells, MaxTotalSlotsNPC, 36) -RULE_INT(Spells, MaxTotalSlotsPET, 30) // do not set this higher than 25 until the player profile is removed from the blob +RULE_INT(Spells, MaxBuffSlotsNPC, 60) // default to Tit's limit +RULE_INT(Spells, MaxSongSlotsNPC, 0) // NPCs don't have songs ... +RULE_INT(Spells, MaxDiscSlotsNPC, 0) // NPCs don't have discs ... +RULE_INT(Spells, MaxTotalSlotsNPC, 60) // default to Tit's limit +RULE_INT(Spells, MaxTotalSlotsPET, 30) // default to Tit's limit RULE_BOOL (Spells, EnableBlockedBuffs, true) RULE_INT(Spells, ReflectType, 1) //0 = disabled, 1 = single target player spells only, 2 = all player spells, 3 = all single target spells, 4 = all spells RULE_INT(Spells, VirusSpreadDistance, 30) // The distance a viral spell will jump to its next victim diff --git a/zone/client.h b/zone/client.h index c7973de18..5b2c0a939 100644 --- a/zone/client.h +++ b/zone/client.h @@ -509,10 +509,10 @@ public: virtual int GetCurrentBuffSlots() const; virtual int GetCurrentSongSlots() const; virtual int GetCurrentDiscSlots() const { return 1; } - virtual int GetMaxBuffSlots() const { return 25; } - virtual int GetMaxSongSlots() const { return 12; } - virtual int GetMaxDiscSlots() const { return 1; } - virtual int GetMaxTotalSlots() const { return 38; } + virtual int GetMaxBuffSlots() const { return EQEmu::constants::LongBuffs; } + virtual int GetMaxSongSlots() const { return EQEmu::constants::ShortBuffs; } + virtual int GetMaxDiscSlots() const { return EQEmu::constants::DiscBuffs; } + virtual int GetMaxTotalSlots() const { return EQEmu::constants::TotalBuffs; } virtual uint32 GetFirstBuffSlot(bool disc, bool song); virtual uint32 GetLastBuffSlot(bool disc, bool song); virtual void InitializeBuffSlots(); diff --git a/zone/spells.cpp b/zone/spells.cpp index 6b875c96f..3b232f9cd 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5534,12 +5534,12 @@ int Client::GetCurrentBuffSlots() const numbuffs++; if (GetLevel() > 74) numbuffs++; - return EQEmu::ClampUpper(numbuffs, GetMaxBuffSlots()); + return EQEmu::ClampUpper(numbuffs, EQEmu::constants::Lookup(m_ClientVersion)->LongBuffs); } int Client::GetCurrentSongSlots() const { - return 12; // AAs dont affect this + return EQEmu::constants::Lookup(m_ClientVersion)->ShortBuffs; // AAs dont affect this } void Client::InitializeBuffSlots() diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 8bf2e4d31..c4fcfc55f 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3122,7 +3122,8 @@ void ZoneDatabase::LoadBuffs(Client *client) buffs[slot_id].instrument_mod = instrument_mod; } - max_slots = client->GetMaxBuffSlots(); + // We load up to the most our client supports + max_slots = EQEmu::constants::Lookup(client->ClientVersion())->LongBuffs; for (int index = 0; index < max_slots; ++index) { if (!IsValidSpell(buffs[index].spellid)) continue; From 5a08e0ffd975d2ed27d28c282cb2f22c73f7ec62 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 16 Nov 2016 02:36:20 -0500 Subject: [PATCH 441/693] Adjust Rogue Evade drop Live seems to be inconsistent with how much hate is dropped, but I parsed ~69% drop on the highest and ~39% for the lowest. So round to 70 and 40. It was also fairly obvious there was a min hate it could drop you to, which parsed out to ~100 hate. --- zone/aggro.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index d50c1d43e..9533fbbff 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -1343,8 +1343,8 @@ bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) { void Mob::RogueEvade(Mob *other) { - int amount = other->GetHateAmount(this) - (GetLevel() * 13); - other->SetHateAmountOnEnt(this, std::max(1, amount)); + int amount = other->GetHateAmount(this) * zone->random.Int(40, 70) / 100; + other->SetHateAmountOnEnt(this, std::max(100, amount)); return; } From bbd2796ea44ad36ca3233a1fe56026b8a8cac920 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 18 Nov 2016 13:55:04 -0500 Subject: [PATCH 442/693] Add ParticlePoint enum for OP_LevelAppearance --- common/eq_packet_structs.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 5e83a467f..1d25e4d66 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -3517,6 +3517,20 @@ struct RecipeAutoCombine_Struct { // f5 ff ff ff in 'you dont have all the stuff' reply }; +// this is the "value#a" data +enum EParticlePoint { + eDefault, + eChest, + eHead, + eLeftHand, + eRigthHand, + eLeftFoot, + eRightFood, + eLeftEye, + eRightEye, + eMouth +}; + struct LevelAppearance_Struct { //Sends a little graphic on level up uint32 spawn_id; uint32 parm1; From a1216751616af4ae90ebf5335951b0ad3f094275 Mon Sep 17 00:00:00 2001 From: Athrogate Date: Mon, 28 Nov 2016 13:50:24 -0800 Subject: [PATCH 443/693] Add GetAppearance() to lua. --- zone/lua_mob.cpp | 6 ++++++ zone/lua_mob.h | 1 + 2 files changed, 7 insertions(+) diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index f5b8c8382..d13ff4a52 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1806,6 +1806,11 @@ void Lua_Mob::ProcessSpecialAbilities(std::string str) { self->ProcessSpecialAbilities(str); } +uint32 Lua_Mob::GetAppearance() { + Lua_Safe_Call_Int(); + return self->GetAppearance(); +} + void Lua_Mob::SetAppearance(int app) { Lua_Safe_Call_Void(); self->SetAppearance(static_cast(app)); @@ -2291,6 +2296,7 @@ luabind::scope lua_register_mob() { .def("SetSpecialAbilityParam", (void(Lua_Mob::*)(int,int,int))&Lua_Mob::SetSpecialAbilityParam) .def("ClearSpecialAbilities", (void(Lua_Mob::*)(void))&Lua_Mob::ClearSpecialAbilities) .def("ProcessSpecialAbilities", (void(Lua_Mob::*)(std::string))&Lua_Mob::ProcessSpecialAbilities) + .def("GetAppearance", (uint32(Lua_Mob::*)(void))&Lua_Mob::GetAppearance) .def("SetAppearance", (void(Lua_Mob::*)(int))&Lua_Mob::SetAppearance) .def("SetAppearance", (void(Lua_Mob::*)(int,bool))&Lua_Mob::SetAppearance) .def("SetDestructibleObject", (void(Lua_Mob::*)(bool))&Lua_Mob::SetDestructibleObject) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 48d1f3e14..4fd1f0c69 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -348,6 +348,7 @@ public: void ClearSpecialAbilities(); void ProcessSpecialAbilities(std::string str); void SetAppearance(int app); + uint32 GetAppearance(); void SetAppearance(int app, bool ignore_self); void SetDestructibleObject(bool set); bool IsImmuneToSpell(int spell_id, Lua_Mob caster); From b5e324af83e8c4e7a8b17f6412140aafe113619b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 28 Nov 2016 16:46:38 -0600 Subject: [PATCH 444/693] eqemu_server.pl windows_server_latest - Now pulls down latest unstable binaries built from AppVeyor (x86) [skip ci] --- utils/scripts/eqemu_server.pl | 38 +++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index dd0448ddc..16c592187 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -43,8 +43,12 @@ if($Config{osname}=~/Win|MS/i){ $has_internet_connection = check_internet_connection(); ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); +if(-e "eqemu_server_skip_update.txt"){ + $skip_self_update_check = 1; +} + #::: Check for script self update -do_self_update_check_routine(); +do_self_update_check_routine() if !$skip_self_update_check; get_perl_version(); read_eqemu_config_xml(); get_mysql_path(); @@ -558,6 +562,7 @@ sub do_self_update_check_routine { } unlink("updates_staged/eqemu_server.pl"); + unlink("updates_staged"); } } @@ -720,13 +725,14 @@ sub show_menu_prompt { print " [utility_scripts] Download utility scripts to run and operate the EQEmu Server\n"; if($OS eq "Windows"){ print ">>> Windows\n"; - print " [windows_server_download] Updates server code from latest stable\n"; - print " [windows_server_download_bots] Updates server code (bots enabled) from latest\n"; + print " [windows_server_download] Updates server via latest 'stable' code\n"; + print " [windows_server_latest] Updates server via latest commit 'unstable'\n"; + print " [windows_server_download_bots] Updates server (bots) from latest 'stable'\n"; print " [fetch_dlls] Grabs dll's needed to run windows binaries\n"; print " [setup_loginserver] Sets up loginserver for Windows\n"; } print " \n> main - go back to main menu\n"; - print "Enter a command #> "; + print "Enter a command #> "; $last_menu = trim($input); } elsif($input eq "backup_database"){ database_dump(); $dc = 1; } @@ -741,6 +747,7 @@ sub show_menu_prompt { elsif($input eq "quests"){ quest_files_fetch(); $dc = 1; } elsif($input eq "lua_modules"){ lua_modules_fetch(); $dc = 1; } elsif($input eq "windows_server_download"){ fetch_latest_windows_binaries(); $dc = 1; } + elsif($input eq "windows_server_latest"){ fetch_latest_windows_appveyor(); $dc = 1; } elsif($input eq "windows_server_download_bots"){ fetch_latest_windows_binaries_bots(); $dc = 1; } elsif($input eq "fetch_dlls"){ fetch_server_dlls(); $dc = 1; } elsif($input eq "utility_scripts"){ fetch_utility_scripts(); $dc = 1; } @@ -1205,6 +1212,29 @@ sub copy_file { copy $l_source_file, $l_destination_file; } +sub fetch_latest_windows_appveyor { + print "[Update] Fetching Latest Windows Binaries (unstable) from Appveyor... \n"; + get_remote_file("https://ci.appveyor.com/api/projects/KimLS/server/artifacts/build_x86.zip", "updates_staged/master_windows_build.zip", 1); + print "[Update] Fetched Latest Windows Binaries (unstable) from Appveyor... \n"; + print "[Update] Extracting... --- \n"; + unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); + my @files; + my $start_dir = "updates_staged/binaries"; + find( + sub { push @files, $File::Find::name unless -d; }, + $start_dir + ); + for my $file (@files) { + $destination_file = $file; + $destination_file =~s/updates_staged\/binaries\///g; + print "[Update] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); + } + print "[Update] Done\n"; + + rmtree('updates_staged'); +} + sub fetch_latest_windows_binaries { print "[Update] Fetching Latest Windows Binaries... \n"; get_remote_file($install_repository_request_url . "master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); From 286bfa7af64be6469b95ab807fb42b40ef67340a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 30 Nov 2016 20:53:39 -0500 Subject: [PATCH 445/693] Implement the PC/NPC only flag --- common/shareddb.cpp | 1 + common/spdat.h | 2 +- zone/effects.cpp | 5 +++++ zone/entity.cpp | 10 +++++++++- zone/entity.h | 2 +- zone/spells.cpp | 15 +++++++++++++-- 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index fd55b3766..fc628ea6f 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1700,6 +1700,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { sp[tempid].pvpresistcalc=atoi(row[178]); sp[tempid].pvpresistcap=atoi(row[179]); sp[tempid].spell_category=atoi(row[180]); + sp[tempid].pcnpc_only_flag=atoi(row[183]); sp[tempid].cast_not_standing = atoi(row[184]) != 0; sp[tempid].can_mgb=atoi(row[185]); sp[tempid].dispel_flag = atoi(row[186]); diff --git a/common/spdat.h b/common/spdat.h index edb750f2a..ab00451e0 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -735,7 +735,7 @@ struct SPDat_Spell_Struct /* 180 */ int spell_category; // -- GLOBAL_GROUP /* 181 */ //int pvp_duration; // buffdurationformula for PvP -- PVP_DURATION /* 182 */ //int pvp_duration_cap; // buffduration for PvP -- PVP_DURATION_CAP -/* 183 */ //int pcnpc_only_flag; // valid values are 0, 1 = PCs (and mercs), and 2 = NPCs (and not mercs) -- PCNPC_ONLY_FLAG +/* 183 */ int pcnpc_only_flag; // valid values are 0, 1 = PCs (and mercs), and 2 = NPCs (and not mercs) -- PCNPC_ONLY_FLAG /* 184 */ bool cast_not_standing; // this is checked in the client's EQ_Spell::IsCastWhileInvisSpell, this also blocks SE_InterruptCasting from affecting this spell -- CAST_NOT_STANDING /* 185 */ bool can_mgb; // 0=no, -1 or 1 = yes -- CAN_MGB /* 186 */ int dispel_flag; // -- NO_DISPELL diff --git a/zone/effects.cpp b/zone/effects.cpp index 3e3f7a4bc..0cec65877 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -778,6 +778,11 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ continue; if (spells[spell_id].targettype == ST_AreaNPCOnly && !curmob->IsNPC()) continue; + // check PC/NPC only flag 1 = PCs, 2 = NPCs + if (spells[spell_id].pcnpc_only_flag == 1 && !curmob->IsClient() && !curmob->IsMerc()) + continue; + if (spells[spell_id].pcnpc_only_flag == 2 && (curmob->IsClient() || curmob->IsMerc())) + continue; if (spells[spell_id].targettype == ST_Ring) { dist_targ = DistanceSquared(static_cast(curmob->GetPosition()), caster->GetTargetRingLocation()); diff --git a/zone/entity.cpp b/zone/entity.cpp index 2bbcdef20..2ff83980e 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -4655,7 +4655,7 @@ Mob *EntityList::GetClosestMobByBodyType(Mob *sender, bodyType BodyType) return ClosestMob; } -void EntityList::GetTargetsForConeArea(Mob *start, float min_radius, float radius, float height, std::list &m_list) +void EntityList::GetTargetsForConeArea(Mob *start, float min_radius, float radius, float height, int pcnpc, std::list &m_list) { auto it = mob_list.begin(); while (it != mob_list.end()) { @@ -4664,6 +4664,14 @@ void EntityList::GetTargetsForConeArea(Mob *start, float min_radius, float radiu ++it; continue; } + // check PC/NPC only flag 1 = PCs, 2 = NPCs + if (pcnpc == 1 && !ptr->IsClient() && !ptr->IsMerc()) { + ++it; + continue; + } else if (pcnpc == 2 && (ptr->IsClient() || ptr->IsMerc())) { + ++it; + continue; + } float x_diff = ptr->GetX() - start->GetX(); float y_diff = ptr->GetY() - start->GetY(); float z_diff = ptr->GetZ() - start->GetZ(); diff --git a/zone/entity.h b/zone/entity.h index d2141d1b9..9a532cdb1 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -451,7 +451,7 @@ public: void GetObjectList(std::list &o_list); void GetDoorsList(std::list &d_list); void GetSpawnList(std::list &d_list); - void GetTargetsForConeArea(Mob *start, float min_radius, float radius, float height, std::list &m_list); + void GetTargetsForConeArea(Mob *start, float min_radius, float radius, float height, int pcnpc, std::list &m_list); void DepopAll(int NPCTypeID, bool StartSpawnTimer = true); diff --git a/zone/spells.cpp b/zone/spells.cpp index 3b232f9cd..814f01be6 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3405,6 +3405,17 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r if(!IsValidSpell(spell_id)) return false; + // these target types skip pcnpc only check (according to dev quotes) + // other AE spells this is redundant, oh well + // 1 = PCs, 2 = NPCs + if (spells[spell_id].pcnpc_only_flag && spells[spell_id].targettype != ST_AETargetHateList && + spells[spell_id].targettype != ST_HateList) { + if (spells[spell_id].pcnpc_only_flag == 1 && !spelltar->IsClient() && !spelltar->IsMerc()) + return false; + else if (spells[spell_id].pcnpc_only_flag == 2 && (spelltar->IsClient() || spelltar->IsMerc())) + return false; + } + uint16 caster_level = level_override > 0 ? level_override : GetCasterLevel(spell_id); Log.Out(Logs::Detail, Logs::Spells, "Casting spell %d on %s with effective caster level %d", spell_id, spelltar->GetName(), caster_level); @@ -5623,7 +5634,7 @@ void Mob::BeamDirectional(uint16 spell_id, int16 resist_adjust) std::list targets_in_range; entity_list.GetTargetsForConeArea(this, spells[spell_id].min_range, spells[spell_id].range, - spells[spell_id].range / 2, targets_in_range); + spells[spell_id].range / 2, spells[spell_id].pcnpc_only_flag, targets_in_range); auto iter = targets_in_range.begin(); float dX = 0; @@ -5698,7 +5709,7 @@ void Mob::ConeDirectional(uint16 spell_id, int16 resist_adjust) std::list targets_in_range; entity_list.GetTargetsForConeArea(this, spells[spell_id].min_range, spells[spell_id].aoerange, - spells[spell_id].aoerange / 2, targets_in_range); + spells[spell_id].aoerange / 2, spells[spell_id].pcnpc_only_flag, targets_in_range); auto iter = targets_in_range.begin(); while (iter != targets_in_range.end()) { From ffbc913b9d8c6334bcd1ac7cc6969418e0ae0b58 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 1 Dec 2016 13:35:19 -0500 Subject: [PATCH 446/693] Rename some spell fields --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + utils/sql/git/required/2016_12_01_pcnpc_only.sql | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2016_12_01_pcnpc_only.sql diff --git a/common/version.h b/common/version.h index 0073d5415..93dfba189 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9100 +#define CURRENT_BINARY_DATABASE_VERSION 9101 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 5674271ae..aa72310ce 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -354,6 +354,7 @@ 9098|2016_08_26_object_size_tilt.sql|SHOW COLUMNS FROM `object` LIKE 'size'|empty| 9099|2016_08_27_ip_exemptions.sql|SHOW TABLES LIKE 'ip_exemptions'|empty| 9100|2016_08_27_object_display_name.sql|SHOW COLUMNS FROM `object` LIKE 'display_name'|empty| +9101|2016_12_01_pcnpc_only.sql|SHOW COLUMNS FROM `spells_new` LIKE 'pcnpc_only_flag'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2016_12_01_pcnpc_only.sql b/utils/sql/git/required/2016_12_01_pcnpc_only.sql new file mode 100644 index 000000000..836730e57 --- /dev/null +++ b/utils/sql/git/required/2016_12_01_pcnpc_only.sql @@ -0,0 +1,2 @@ +ALTER TABLE `spells_new` CHANGE `field183` `pcnpc_only_flag` INT(11) DEFAULT 0; +ALTER TABLE `spells_new` CHANGE `field184` `cast_not_standing` INT(11) DEFAULT 0; From de92c277e0715ecee54bb3c2f04ec9c72684ae41 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 1 Dec 2016 19:41:12 -0600 Subject: [PATCH 447/693] Update eqemu_server.pl to use new AppVeyor build link Adjust pet zoning to occur before zone spawns are sent in bulk --- zone/client.cpp | 1 + zone/client_packet.cpp | 39 ++++++++++++++++++--------------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 891591780..ddf10d9d5 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -424,6 +424,7 @@ Client::~Client() { void Client::SendZoneInPackets() { + ////////////////////////////////////////////////////// // Spawn Appearance Packet auto outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e05cc4f8c..7a2715197 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -493,6 +493,7 @@ int Client::HandlePacket(const EQApplicationPacket *app) // Finish client connecting state void Client::CompleteConnect() { + UpdateWho(); client_state = CLIENT_CONNECTED; SendAllPackets(); @@ -502,27 +503,6 @@ void Client::CompleteConnect() SetDuelTarget(0); SetDueling(false); - database.LoadPetInfo(this); - /* - This was moved before the spawn packets are sent - in hopes that it adds more consistency... - Remake pet - */ - if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) { - MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, m_petinfo.Name, m_petinfo.size); - if (GetPet() && GetPet()->IsNPC()) { - NPC *pet = GetPet()->CastToNPC(); - pet->SetPetState(m_petinfo.Buffs, m_petinfo.Items); - pet->CalcBonuses(); - pet->SetHP(m_petinfo.HP); - pet->SetMana(m_petinfo.Mana); - } - m_petinfo.SpellID = 0; - } - /* Moved here so it's after where we load the pet data. */ - if (!GetAA(aaPersistentMinion)) - memset(&m_suspendedminion, 0, sizeof(PetInfo)); - EnteringMessages(this); LoadZoneFlags(); @@ -1649,6 +1629,23 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (m_pp.RestTimer) rest_timer.Start(m_pp.RestTimer * 1000); + /* Load Pet */ + database.LoadPetInfo(this); + if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) { + MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower, m_petinfo.Name, m_petinfo.size); + if (GetPet() && GetPet()->IsNPC()) { + NPC *pet = GetPet()->CastToNPC(); + pet->SetPetState(m_petinfo.Buffs, m_petinfo.Items); + pet->CalcBonuses(); + pet->SetHP(m_petinfo.HP); + pet->SetMana(m_petinfo.Mana); + } + m_petinfo.SpellID = 0; + } + /* Moved here so it's after where we load the pet data. */ + if (!GetAA(aaPersistentMinion)) + memset(&m_suspendedminion, 0, sizeof(PetInfo)); + /* Server Zone Entry Packet */ outapp = new EQApplicationPacket(OP_ZoneEntry, sizeof(ServerZoneEntry_Struct)); ServerZoneEntry_Struct* sze = (ServerZoneEntry_Struct*)outapp->pBuffer; From 3e504916197a3a9cc68f94da4b941ef36fe398d6 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 1 Dec 2016 19:46:43 -0600 Subject: [PATCH 448/693] Update eqemu_server.pl to use new AppVeyor build link [skip ci] --- utils/scripts/eqemu_server.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 16c592187..abc4c74aa 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -1214,7 +1214,7 @@ sub copy_file { sub fetch_latest_windows_appveyor { print "[Update] Fetching Latest Windows Binaries (unstable) from Appveyor... \n"; - get_remote_file("https://ci.appveyor.com/api/projects/KimLS/server/artifacts/build_x86.zip", "updates_staged/master_windows_build.zip", 1); + get_remote_file("https://ci.appveyor.com/api/projects/KimLS/server/artifacts/build_x86_pdb.zip", "updates_staged/master_windows_build.zip", 1); print "[Update] Fetched Latest Windows Binaries (unstable) from Appveyor... \n"; print "[Update] Extracting... --- \n"; unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); From 0d9af27a03514d4283731f3511c340cdd33ea139 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 1 Dec 2016 22:34:43 -0500 Subject: [PATCH 449/693] Exploit abatement for item duplication involving augments --- changelog.txt | 3 +++ zone/client_packet.cpp | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/changelog.txt b/changelog.txt index 4b2d029d5..a1a4e264c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 21/01/2016 == +Uleat: Disabled RoF+ clients from augmentation items not in their possessions slots (0-29, 9999, 251-330) to abate an exploit in the current code + == 10/17/2016 == Uleat: Moved namespace ItemField from item_instance.h to shareddb.cpp - the only place it is used Uleat: Separated class Inventory from item_instance files into inventory_profile files diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e05cc4f8c..a28327196 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2933,6 +2933,19 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) bool deleteItems = false; if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { + if ((in_augment->container_slot < 0 || in_augment->container_slot >= EQEmu::legacy::SLOT_CURSOR) && + in_augment->container_slot != EQEmu::legacy::SLOT_POWER_SOURCE && + (in_augment->container_slot < EQEmu::legacy::SLOT_PERSONAL_BAGS_BEGIN || in_augment->container_slot > EQEmu::legacy::SLOT_PERSONAL_BAGS_END)) + { + Message(13, "The server does not allow augmentation actions from this slot."); + auto cursor_item = m_inv[EQEmu::legacy::SLOT_CURSOR]; + auto augmented_item = m_inv[in_augment->container_slot]; + SendItemPacket(EQEmu::legacy::SLOT_CURSOR, cursor_item, ItemPacketCharInventory); + // this may crash clients on certain slots + SendItemPacket(in_augment->container_slot, augmented_item, ItemPacketCharInventory); + return; + } + EQEmu::ItemInstance *itemOneToPush = nullptr, *itemTwoToPush = nullptr; //Log.Out(Logs::DebugLevel::Moderate, Logs::Debug, "cslot: %i aslot: %i cidx: %i aidx: %i act: %i dest: %i", From bb8fc17189f54f8dd5006c2cb0d60eb49c428e77 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 1 Dec 2016 22:57:13 -0500 Subject: [PATCH 450/693] Quick fix for PP buff issue This may break buffs zoning, but I don't have time to look at --- zone/client_packet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 749a4ed11..0d4294132 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1460,7 +1460,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) database.LoadBuffs(this); uint32 max_slots = GetMaxBuffSlots(); - for (int i = 0; i < max_slots; i++) { + for (int i = 0; i < BUFF_COUNT; i++) { if (buffs[i].spellid != SPELL_UNKNOWN) { m_pp.buffs[i].spellid = buffs[i].spellid; m_pp.buffs[i].bard_modifier = buffs[i].instrument_mod; From a4c9fa6a653e4b9ec46e187333e05608407fd73d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 1 Dec 2016 22:42:22 -0600 Subject: [PATCH 451/693] eqemu_server.pl windws_server_latest - now grabs both pdb's and regular binaries [skip ci] --- utils/scripts/eqemu_server.pl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index abc4c74aa..e0960847e 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -1214,10 +1214,12 @@ sub copy_file { sub fetch_latest_windows_appveyor { print "[Update] Fetching Latest Windows Binaries (unstable) from Appveyor... \n"; - get_remote_file("https://ci.appveyor.com/api/projects/KimLS/server/artifacts/build_x86_pdb.zip", "updates_staged/master_windows_build.zip", 1); + get_remote_file("https://ci.appveyor.com/api/projects/KimLS/server/artifacts/build_x86_pdb.zip", "updates_staged/master_windows_build_pdb.zip", 1); + get_remote_file("https://ci.appveyor.com/api/projects/KimLS/server/artifacts/build_x86.zip", "updates_staged/master_windows_build.zip", 1); print "[Update] Fetched Latest Windows Binaries (unstable) from Appveyor... \n"; print "[Update] Extracting... --- \n"; unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); + unzip('updates_staged/master_windows_build_pdb.zip', 'updates_staged/binaries/'); my @files; my $start_dir = "updates_staged/binaries"; find( From 0ab0c5c1179ade639e39d8da863d091d34f6ca9e Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 3 Dec 2016 18:17:10 -0500 Subject: [PATCH 452/693] Added trade hack detection code --- changelog.txt | 9 +++++++-- common/item_instance.cpp | 26 ++++++++++++++++++++++++++ common/item_instance.h | 2 ++ zone/client.h | 1 + zone/client_packet.cpp | 21 ++++++++++++++++++++- zone/string_ids.h | 1 + zone/trading.cpp | 40 +++++++++++++++++++++++++++------------- 7 files changed, 84 insertions(+), 16 deletions(-) diff --git a/changelog.txt b/changelog.txt index a1a4e264c..33bf2de1a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,7 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- -== 21/01/2016 == -Uleat: Disabled RoF+ clients from augmentation items not in their possessions slots (0-29, 9999, 251-330) to abate an exploit in the current code +== 12/03/2016 == +Uleat: Added hack detection to trade code + - If illegal items are found in trade slots when the 'trade' button is clicked, the trade is cancelled and a message is sent to the offending player + - Future revisions will, at a minimum, log the player as a hacker once the quirks have been worked out + +== 12/01/2016 == +Uleat: Disabled RoF+ clients from augmenting items not in their possessions slots (0-29, 9999, 251-330) to abate an exploit in the current code == 10/17/2016 == Uleat: Moved namespace ItemField from item_instance.h to shareddb.cpp - the only place it is used diff --git a/common/item_instance.cpp b/common/item_instance.cpp index 268440dc8..d8d23064e 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -819,6 +819,32 @@ bool EQEmu::ItemInstance::IsSlotAllowed(int16 slot_id) const { else { return false; } } +bool EQEmu::ItemInstance::IsDroppable(bool recurse) const +{ + if (!m_item) + return false; + /*if (m_ornamentidfile) // not implemented + return false;*/ + if (m_attuned) + return false; + /*if (m_item->FVNoDrop != 0) // not implemented + return false;*/ + if (m_item->NoDrop == 0) + return false; + + if (recurse) { + for (auto iter : m_contents) { + if (!iter.second) + continue; + + if (!iter.second->IsDroppable(recurse)) + return false; + } + } + + return true; +} + void EQEmu::ItemInstance::Initialize(SharedDatabase *db) { // if there's no actual item, don't do anything if (!m_item) diff --git a/common/item_instance.h b/common/item_instance.h index 90dd1403f..6566fd77e 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -188,6 +188,8 @@ namespace EQEmu bool IsSlotAllowed(int16 slot_id) const; + bool IsDroppable(bool recurse = true) const; + bool IsScaling() const { return m_scaling; } bool IsEvolving() const { return (m_evolveLvl >= 1); } uint32 GetExp() const { return m_exp; } diff --git a/zone/client.h b/zone/client.h index 5b2c0a939..8bb996bdf 100644 --- a/zone/client.h +++ b/zone/client.h @@ -855,6 +855,7 @@ public: void SetConsumption(int32 in_hunger, int32 in_thirst); bool CheckTradeLoreConflict(Client* other); + bool CheckTradeNonDroppable(); void LinkDead(); void Insight(uint32 t_id); bool CheckDoubleAttack(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 0d4294132..0ba79d15f 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -13287,7 +13287,6 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) other->trade->state = TradeCompleting; trade->state = TradeCompleting; - // should we do this for NoDrop items as well? if (CheckTradeLoreConflict(other) || other->CheckTradeLoreConflict(this)) { Message_StringID(13, TRADE_CANCEL_LORE); other->Message_StringID(13, TRADE_CANCEL_LORE); @@ -13296,6 +13295,26 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app) other->trade->Reset(); trade->Reset(); } + else if (CheckTradeNonDroppable()) { + Message_StringID(13, TRADE_HAS_BEEN_CANCELLED); + other->Message_StringID(13, TRADE_HAS_BEEN_CANCELLED); + this->FinishTrade(this); + other->FinishTrade(other); + other->trade->Reset(); + trade->Reset(); + Message(15, "Hacking activity detected in trade transaction."); + // TODO: query (this) as a hacker + } + else if (other->CheckTradeNonDroppable()) { + Message_StringID(13, TRADE_HAS_BEEN_CANCELLED); + other->Message_StringID(13, TRADE_HAS_BEEN_CANCELLED); + this->FinishTrade(this); + other->FinishTrade(other); + other->trade->Reset(); + trade->Reset(); + other->Message(15, "Hacking activity detected in trade transaction."); + // TODO: query (other) as a hacker + } else { // Audit trade to database for both trade streams other->trade->LogTrade(); diff --git a/zone/string_ids.h b/zone/string_ids.h index e1fb4de7c..b9eba66df 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -255,6 +255,7 @@ #define MEMBER_OF_YOUR_GUILD 1429 #define OFFICER_OF_YOUR_GUILD 1430 #define LEADER_OF_YOUR_GUILD 1431 +#define TRADE_HAS_BEEN_CANCELLED 1449 #define RECEIVED_PLATINUM 1452 //You receive %1 Platinum from %2. #define RECEIVED_GOLD 1453 //You receive %1 Gold from %2. #define RECEIVED_SILVER 1454 //You receive %1 Silver from %2. diff --git a/zone/trading.cpp b/zone/trading.cpp index e150ceb12..85ed824b2 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -967,23 +967,37 @@ bool Client::CheckTradeLoreConflict(Client* other) { if (!other) return true; - // Move each trade slot into free inventory slot - for (int16 i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_END; i++){ - const EQEmu::ItemInstance* inst = m_inv[i]; - if (inst && inst->GetItem()) { - if (other->CheckLoreConflict(inst->GetItem())) - return true; - } + for (int16 index = EQEmu::legacy::TRADE_BEGIN; index <= EQEmu::legacy::TRADE_END; ++index) { + const EQEmu::ItemInstance* inst = m_inv[index]; + if (!inst || !inst->GetItem()) + continue; + + if (other->CheckLoreConflict(inst->GetItem())) + return true; } - for (int16 i = EQEmu::legacy::TRADE_BAGS_BEGIN; i <= EQEmu::legacy::TRADE_BAGS_END; i++){ - const EQEmu::ItemInstance* inst = m_inv[i]; + for (int16 index = EQEmu::legacy::TRADE_BAGS_BEGIN; index <= EQEmu::legacy::TRADE_BAGS_END; ++index) { + const EQEmu::ItemInstance* inst = m_inv[index]; + if (!inst || !inst->GetItem()) + continue; - if (inst && inst->GetItem()) { - if (other->CheckLoreConflict(inst->GetItem())) - return true; - } + if (other->CheckLoreConflict(inst->GetItem())) + return true; + } + + return false; +} + +bool Client::CheckTradeNonDroppable() +{ + for (int16 index = EQEmu::legacy::TRADE_BEGIN; index <= EQEmu::legacy::TRADE_END; ++index){ + const EQEmu::ItemInstance* inst = m_inv[index]; + if (!inst) + continue; + + if (!inst->IsDroppable()) + return true; } return false; From baf9336617e329a2d7922675b625413b1752b32e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 6 Dec 2016 14:12:11 -0500 Subject: [PATCH 453/693] Fix RoF+ OP_InterruptCast --- common/patches/rof.cpp | 11 ----------- common/patches/rof2.cpp | 11 ----------- common/patches/rof2_ops.h | 1 - common/patches/rof_ops.h | 1 - 4 files changed, 24 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 980a4f4ed..2916046be 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -1492,17 +1492,6 @@ namespace RoF FINISH_ENCODE(); } - ENCODE(OP_InterruptCast) - { - ENCODE_LENGTH_EXACT(InterruptCast_Struct); - SETUP_DIRECT_ENCODE(InterruptCast_Struct, structs::InterruptCast_Struct); - - OUT(spawnid); - OUT(messageid); - - FINISH_ENCODE(); - } - ENCODE(OP_ItemLinkResponse) { ENCODE_FORWARD(OP_ItemPacket); } ENCODE(OP_ItemPacket) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index d14008e93..d56791bef 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1560,17 +1560,6 @@ namespace RoF2 FINISH_ENCODE(); } - ENCODE(OP_InterruptCast) - { - ENCODE_LENGTH_EXACT(InterruptCast_Struct); - SETUP_DIRECT_ENCODE(InterruptCast_Struct, structs::InterruptCast_Struct); - - OUT(spawnid); - OUT(messageid); - - FINISH_ENCODE(); - } - ENCODE(OP_ItemLinkResponse) { ENCODE_FORWARD(OP_ItemPacket); } ENCODE(OP_ItemPacket) diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index 1ca7063f4..2cd81aaee 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -85,7 +85,6 @@ E(OP_HPUpdate) E(OP_Illusion) E(OP_InspectBuffs) E(OP_InspectRequest) -E(OP_InterruptCast) E(OP_ItemLinkResponse) E(OP_ItemPacket) E(OP_ItemVerifyReply) diff --git a/common/patches/rof_ops.h b/common/patches/rof_ops.h index 45221cfc5..9030a480b 100644 --- a/common/patches/rof_ops.h +++ b/common/patches/rof_ops.h @@ -70,7 +70,6 @@ E(OP_HPUpdate) E(OP_Illusion) E(OP_InspectBuffs) E(OP_InspectRequest) -E(OP_InterruptCast) E(OP_ItemLinkResponse) E(OP_ItemPacket) E(OP_ItemVerifyReply) From 95efc3a66c2c5937867e077905d2a5c66a8b1559 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Thu, 8 Dec 2016 16:06:32 -0500 Subject: [PATCH 454/693] Undo changes --- zone/attack.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/zone/attack.cpp b/zone/attack.cpp index 475aee7b3..3b69380f0 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1217,8 +1217,14 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b CommonBreakInvisibleFromCombat(); + // Defensive procs from opponent happen here. + // We, the attacker check for them and make them happen. + // Added 2nd check for spell based defensive procs on opponent. if(GetTarget()) + { TriggerDefensiveProcs(other, Hand, true, damage); + TriggerDefensiveProcs(other, Hand, false); + } if (damage > 0) return true; @@ -1783,8 +1789,14 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool TrySkillProc(other, skillinuse, 0, true, Hand); } + // Defensive procs from opponent happen here. + // We, the attacker check for them and make them happen. + // Added 2nd check for spell based defensive procs on opponent. if(GetHP() > 0 && !other->HasDied()) + { TriggerDefensiveProcs(other, Hand, true, damage); + TriggerDefensiveProcs(other, Hand, false); + } if (damage > 0) return true; From 246f770e8f80865a2d93b6ccd4b34d6069e93300 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sun, 27 Nov 2016 16:43:43 -0500 Subject: [PATCH 455/693] Fix fishing messages so when actual fish are caught, name is in message. --- zone/forage.cpp | 14 +++++++++++++- zone/string_ids.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/zone/forage.cpp b/zone/forage.cpp index aec4d6b73..8331560fd 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -221,6 +221,8 @@ bool Client::CanFish() { void Client::GoFish() { + bool junk=false; + //TODO: generate a message if we're already fishing /*if (!fishing_timer.Check()) { //this isn't the right check, may need to add something to the Client class like 'bool is_fishing' Message_StringID(0, ALREADY_FISHING); //You are already fishing! @@ -302,11 +304,21 @@ void Client::GoFish() if(food_id == 0) { int index = zone->random.Int(0, MAX_COMMON_FISH_IDS-1); food_id = common_fish_ids[index]; + if (food_id != 13019) { + junk=true; // Alters the message to "caught something..." + } + } const EQEmu::ItemData* food_item = database.GetItem(food_id); - Message_StringID(MT_Skills, FISHING_SUCCESS); + if (junk == true) { + Message_StringID(MT_Skills, FISHING_SUCCESS); + } + else { + Message_StringID(MT_Skills, FISHING_SUCCESS_FISH_NAME, food_item->Name); + } + EQEmu::ItemInstance* inst = database.CreateItem(food_item, 1); if(inst != nullptr) { if(CheckLoreConflict(inst->GetItem())) diff --git a/zone/string_ids.h b/zone/string_ids.h index b9eba66df..67dd808ab 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -46,6 +46,7 @@ #define FISHING_FAILED 168 //You didn't catch anything. #define FISHING_POLE_BROKE 169 //Your fishing pole broke! #define FISHING_SUCCESS 170 //You caught, something... +#define FISHING_SUCCESS_FISH_NAME 421 //You caught %1! #define FISHING_SPILL_BEER 171 //You spill your beer while bringing in your line. #define FISHING_LOST_BAIT 172 //You lost your bait! #define SPELL_FIZZLE 173 //Your spell fizzles! From f5a0b994dc422b46c9e19e0802fd74d1ec11caa7 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sun, 27 Nov 2016 17:02:19 -0500 Subject: [PATCH 456/693] Make message based on item type. Learned that non fish items can come from both tables. --- zone/forage.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/zone/forage.cpp b/zone/forage.cpp index 8331560fd..92fde80b5 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -221,8 +221,6 @@ bool Client::CanFish() { void Client::GoFish() { - bool junk=false; - //TODO: generate a message if we're already fishing /*if (!fishing_timer.Check()) { //this isn't the right check, may need to add something to the Client class like 'bool is_fishing' Message_StringID(0, ALREADY_FISHING); //You are already fishing! @@ -304,15 +302,13 @@ void Client::GoFish() if(food_id == 0) { int index = zone->random.Int(0, MAX_COMMON_FISH_IDS-1); food_id = common_fish_ids[index]; - if (food_id != 13019) { - junk=true; // Alters the message to "caught something..." } } const EQEmu::ItemData* food_item = database.GetItem(food_id); - if (junk == true) { + if (food_item->ItemType != ItemTypeFood) { // non-fish oddity Message_StringID(MT_Skills, FISHING_SUCCESS); } else { From d99df2540d11c33bd01822e15e70a2f8e08d13a3 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sun, 27 Nov 2016 17:17:26 -0500 Subject: [PATCH 457/693] Fix typo --- zone/forage.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zone/forage.cpp b/zone/forage.cpp index 92fde80b5..7bb87bf6c 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -303,12 +303,10 @@ void Client::GoFish() int index = zone->random.Int(0, MAX_COMMON_FISH_IDS-1); food_id = common_fish_ids[index]; } - - } const EQEmu::ItemData* food_item = database.GetItem(food_id); - if (food_item->ItemType != ItemTypeFood) { // non-fish oddity + if (food_item->ItemType != EQEmu::item::ItemTypeFood) { Message_StringID(MT_Skills, FISHING_SUCCESS); } else { From 6cbb4bcf478f2e10c22c1e4b1606783503ab81f7 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Thu, 8 Dec 2016 16:15:58 -0500 Subject: [PATCH 458/693] Remove defensive proc changes --- zone/attack.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 3b69380f0..3359f4eed 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1223,7 +1223,6 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if(GetTarget()) { TriggerDefensiveProcs(other, Hand, true, damage); - TriggerDefensiveProcs(other, Hand, false); } if (damage > 0) @@ -1795,7 +1794,6 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool if(GetHP() > 0 && !other->HasDied()) { TriggerDefensiveProcs(other, Hand, true, damage); - TriggerDefensiveProcs(other, Hand, false); } if (damage > 0) From d0e6bb6e072a19ce5d71a27604700ad2d913afd1 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Thu, 8 Dec 2016 16:17:10 -0500 Subject: [PATCH 459/693] more undos --- zone/attack.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 3359f4eed..475aee7b3 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1217,13 +1217,8 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b CommonBreakInvisibleFromCombat(); - // Defensive procs from opponent happen here. - // We, the attacker check for them and make them happen. - // Added 2nd check for spell based defensive procs on opponent. if(GetTarget()) - { TriggerDefensiveProcs(other, Hand, true, damage); - } if (damage > 0) return true; @@ -1788,13 +1783,8 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool TrySkillProc(other, skillinuse, 0, true, Hand); } - // Defensive procs from opponent happen here. - // We, the attacker check for them and make them happen. - // Added 2nd check for spell based defensive procs on opponent. if(GetHP() > 0 && !other->HasDied()) - { TriggerDefensiveProcs(other, Hand, true, damage); - } if (damage > 0) return true; From 538ff873ee73a447786af834e75837343b7e2a87 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Thu, 8 Dec 2016 16:19:17 -0500 Subject: [PATCH 460/693] Fix alignment --- zone/forage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/forage.cpp b/zone/forage.cpp index 7bb87bf6c..cce6d9694 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -302,7 +302,7 @@ void Client::GoFish() if(food_id == 0) { int index = zone->random.Int(0, MAX_COMMON_FISH_IDS-1); food_id = common_fish_ids[index]; - } + } const EQEmu::ItemData* food_item = database.GetItem(food_id); From 26985496d1177d69c0141029ac017644f87aa033 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 8 Dec 2016 22:36:47 -0500 Subject: [PATCH 461/693] Fix Shield Specialist related SPAs --- common/spdat.h | 4 ++-- zone/attack.cpp | 10 +++++----- zone/bonuses.cpp | 28 +++++----------------------- zone/common.h | 3 +-- zone/mob.cpp | 3 --- zone/spell_effects.cpp | 2 +- 6 files changed, 14 insertions(+), 36 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index ab00451e0..6ca588f04 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -502,7 +502,7 @@ typedef enum { #define SE_HeadShotLevel 346 // implemented[AA] - HeadShot max level to kill #define SE_DoubleRangedAttack 347 // implemented - chance at an additional archery attack (consumes arrow) #define SE_LimitManaMin 348 // implemented -#define SE_ShieldEquipHateMod 349 // implemented[AA] Increase melee hate when wearing a shield. +#define SE_ShieldEquipDmgMod 349 // implemented[AA] Increase melee base damage (indirectly increasing hate) when wearing a shield. #define SE_ManaBurn 350 // implemented - Drains mana for damage/heal at a defined ratio up to a defined maximum amount of mana. //#define SE_PersistentEffect 351 // *not implemented. creates a trap/totem that casts a spell (spell id + base1?) when anything comes near it. can probably make a beacon for this //#define SE_IncreaseTrapCount 352 // *not implemented - looks to be some type of invulnerability? Test ITC (8755) @@ -519,7 +519,7 @@ typedef enum { #define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank. #define SE_TripleAttackChance 364 // implemented #define SE_ProcOnSpellKillShot 365 // implemented - chance to trigger a spell on kill when the kill is caused by a specific spell with this effect in it (10470 Venin) -#define SE_ShieldEquipDmgMod 366 // implemented[AA] Damage modifier to melee if shield equiped. (base1 = dmg mod , base2 = ?) ie Shield Specialist AA +#define SE_GroupShielding 366 // *not implemented[AA] This gives you /shieldgroup #define SE_SetBodyType 367 // implemented - set body type of base1 so it can be affected by spells that are limited to that type (Plant, Animal, Undead, etc) //#define SE_FactionMod 368 // *not implemented - increases faction with base1 (faction id, live won't match up w/ ours) by base2 #define SE_CorruptionCounter 369 // implemented diff --git a/zone/attack.cpp b/zone/attack.cpp index 475aee7b3..40de941dc 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1072,6 +1072,11 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b //if weapon damage > 0 then we know we can hit the target with this weapon //otherwise we cannot and we set the damage to -5 later on if(weapon_damage > 0){ + auto shield_inc = spellbonuses.ShieldEquipDmgMod + itembonuses.ShieldEquipDmgMod + aabonuses.ShieldEquipDmgMod; + if (shield_inc > 0 && HasShieldEquiped() && Hand == EQEmu::inventory::slotPrimary) { + weapon_damage = weapon_damage * (100 + shield_inc) / 100; + hate = hate * (100 + shield_inc) / 100; + } //Berserker Berserk damage bonus if(IsBerserk() && GetClass() == BERSERKER){ @@ -2291,11 +2296,6 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b // Spell Casting Subtlety etc int hatemod = 100 + other->spellbonuses.hatemod + other->itembonuses.hatemod + other->aabonuses.hatemod; - int32 shieldhatemod = other->spellbonuses.ShieldEquipHateMod + other->itembonuses.ShieldEquipHateMod + other->aabonuses.ShieldEquipHateMod; - - if (shieldhatemod && other->HasShieldEquiped()) - hatemod += shieldhatemod; - if(hatemod < 1) hatemod = 1; hate = ((hate * (hatemod))/100); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 760ca52dc..beae3995d 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -940,12 +940,8 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) case SE_ShieldBlock: newbon->ShieldBlock += base1; break; - case SE_ShieldEquipHateMod: - newbon->ShieldEquipHateMod += base1; - break; case SE_ShieldEquipDmgMod: - newbon->ShieldEquipDmgMod[0] += base1; - newbon->ShieldEquipDmgMod[1] += base2; + newbon->ShieldEquipDmgMod += base1; break; case SE_SecondaryDmgInc: newbon->SecondaryDmgInc = true; @@ -2655,13 +2651,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne new_bonus->ShieldBlock += effect_value; break; - case SE_ShieldEquipHateMod: - new_bonus->ShieldEquipHateMod += effect_value; - break; - case SE_ShieldEquipDmgMod: - new_bonus->ShieldEquipDmgMod[0] += effect_value; - new_bonus->ShieldEquipDmgMod[1] += base2; + new_bonus->ShieldEquipDmgMod += effect_value; break; case SE_BlockBehind: @@ -4555,19 +4546,10 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) itembonuses.DoubleRangedAttack = effect_value; break; - case SE_ShieldEquipHateMod: - spellbonuses.ShieldEquipHateMod = effect_value; - aabonuses.ShieldEquipHateMod = effect_value; - itembonuses.ShieldEquipHateMod = effect_value; - break; - case SE_ShieldEquipDmgMod: - spellbonuses.ShieldEquipDmgMod[0] = effect_value; - spellbonuses.ShieldEquipDmgMod[1] = effect_value; - aabonuses.ShieldEquipDmgMod[0] = effect_value; - aabonuses.ShieldEquipDmgMod[1] = effect_value; - itembonuses.ShieldEquipDmgMod[0] = effect_value; - itembonuses.ShieldEquipDmgMod[1] = effect_value; + spellbonuses.ShieldEquipDmgMod = effect_value; + aabonuses.ShieldEquipDmgMod = effect_value; + itembonuses.ShieldEquipDmgMod = effect_value; break; case SE_TriggerMeleeThreshold: diff --git a/zone/common.h b/zone/common.h index fd4ea0a89..e621c336b 100644 --- a/zone/common.h +++ b/zone/common.h @@ -457,8 +457,7 @@ struct StatBonuses { int32 ItemATKCap; // Raise item attack cap int32 FinishingBlow[2]; // Chance to do a finishing blow for specified damage amount. uint32 FinishingBlowLvl[2]; // Sets max level an NPC can be affected by FB. (base1 = lv, base2= ???) - int32 ShieldEquipHateMod; // Hate mod when shield equiped. - int32 ShieldEquipDmgMod[2]; // Damage mod when shield equiped. 0 = damage modifier 1 = Unknown + int32 ShieldEquipDmgMod; // Increases weapon's base damage by base1 % when shield is equipped (indirectly increasing hate) bool TriggerOnValueAmount; // Triggers off various different conditions, bool to check if client has effect. int8 StunBashChance; // chance to stun with bash. int8 IncreaseChanceMemwipe; // increases chance to memory wipe diff --git a/zone/mob.cpp b/zone/mob.cpp index a39dcfa99..c47788ee5 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4668,9 +4668,6 @@ int16 Mob::GetMeleeDamageMod_SE(uint16 skill) dmg_mod += itembonuses.DamageModifier2[EQEmu::skills::HIGHEST_SKILL + 1] + spellbonuses.DamageModifier2[EQEmu::skills::HIGHEST_SKILL + 1] + aabonuses.DamageModifier2[EQEmu::skills::HIGHEST_SKILL + 1] + itembonuses.DamageModifier2[skill] + spellbonuses.DamageModifier2[skill] + aabonuses.DamageModifier2[skill]; - if (HasShieldEquiped() && !IsOffHandAtk()) - dmg_mod += itembonuses.ShieldEquipDmgMod[0] + spellbonuses.ShieldEquipDmgMod[0] + aabonuses.ShieldEquipDmgMod[0]; - if(dmg_mod < -100) dmg_mod = -100; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index a2a66f9ae..43833328c 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2982,8 +2982,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_FcHealAmtIncoming: case SE_LimitManaMax: case SE_DoubleRangedAttack: - case SE_ShieldEquipHateMod: case SE_ShieldEquipDmgMod: + case SE_GroupShielding: case SE_TriggerOnReqTarget: case SE_LimitRace: case SE_FcLimitUse: From fddb6f67abcc6fb6424e3a3b5fdf9a570bc8f5a6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 9 Dec 2016 13:29:46 -0500 Subject: [PATCH 462/693] Update IsPartialCapableSpell based on Torven's findings --- common/spdat.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/common/spdat.cpp b/common/spdat.cpp index f22a82000..fd4e3c5ea 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -409,8 +409,19 @@ bool IsPartialCapableSpell(uint16 spell_id) if (spells[spell_id].no_partial_resist) return false; - if (IsPureNukeSpell(spell_id)) - return true; + // spell uses 600 (partial) scale if first effect is damage, else it uses 200 scale. + // this includes DoTs. no_partial_resist excludes spells like necro snares + for (int o = 0; o < EFFECT_COUNT; o++) { + auto tid = spells[spell_id].effectid[o]; + + if (IsBlankSpellEffect(spell_id, o)) + continue; + + if ((tid == SE_CurrentHPOnce || tid == SE_CurrentHP) && spells[spell_id].base[o] < 0) + return true; + + return false; + } return false; } From 491cabfe8b170546784687a4fd86bdfc6ed24e5f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 9 Dec 2016 13:36:09 -0500 Subject: [PATCH 463/693] Fix SE_Destroy breaking respawns --- zone/spell_effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 43833328c..a2841ee8e 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2038,7 +2038,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #endif if(IsNPC()) { if(GetLevel() <= 52) - CastToNPC()->Depop(); + CastToNPC()->Depop(true); else Message(13, "Your target is too high level to be affected by this spell."); } From 6311d82095a596d3b4a331dda354c950a6eb6203 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Fri, 9 Dec 2016 18:59:44 -0500 Subject: [PATCH 464/693] Add check for mob spell based defensive procs (as per DB entry) for attacking clients. Got coaching and testing from demonstar55. --- zone/client_process.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 632f953d7..bb2db4777 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -393,6 +393,7 @@ bool Client::Process() { { EQEmu::ItemInstance *wpn = GetInv().GetItem(EQEmu::inventory::slotPrimary); TryWeaponProc(wpn, auto_attack_target, EQEmu::inventory::slotPrimary); + TriggerDefensiveProcs(auto_attack_target, EQEmu::inventory::slotPrimary, false); DoAttackRounds(auto_attack_target, EQEmu::inventory::slotPrimary); if (CheckAATimer(aaTimerRampage)) From 69941571842a663405b73ea2a4d8f5203848d8d1 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 9 Dec 2016 20:12:08 -0500 Subject: [PATCH 465/693] Added optional bots rule 'CasterStopMeleeLevel' --- common/ruletypes.h | 3 ++- .../git/bots/optional/2014_03_31_BotLevelsWithOwnerRule.sql | 4 ---- .../optional/2014_03_31_bots_bot_levels_with_owner_rule.sql | 1 + .../optional/2016_12_09_bots_caster_stop_melee_level_rule.sql | 2 ++ zone/bot.cpp | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 utils/sql/git/bots/optional/2014_03_31_BotLevelsWithOwnerRule.sql create mode 100644 utils/sql/git/bots/optional/2014_03_31_bots_bot_levels_with_owner_rule.sql create mode 100644 utils/sql/git/bots/optional/2016_12_09_bots_caster_stop_melee_level_rule.sql diff --git a/common/ruletypes.h b/common/ruletypes.h index 9a18ff063..dc1a31c1f 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -556,12 +556,13 @@ RULE_REAL(Bots, ManaRegen, 2.0) // Adjust mana regen for bots, 1 is fast and hig RULE_BOOL(Bots, PreferNoManaCommandSpells, true) // Give sorting priority to newer no-mana spells (i.e., 'Bind Affinity') RULE_BOOL(Bots, QuestableSpawnLimit, false) // Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl RULE_BOOL(Bots, QuestableSpells, false) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests. -RULE_INT(Bots, SpawnLimit, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid +RULE_INT(Bots, SpawnLimit, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group pseudo-raid (bots are not raidable at this time) RULE_BOOL(Bots, BotGroupXP, false) // Determines whether client gets xp for bots outside their group. RULE_BOOL(Bots, BotBardUseOutOfCombatSongs, true) // Determines whether bard bots use additional out of combat songs (optional script) RULE_BOOL(Bots, BotLevelsWithOwner, false) // Auto-updates spawned bots as owner levels/de-levels (false is original behavior) RULE_BOOL(Bots, BotCharacterLevelEnabled, false) // Enables required level to spawn bots RULE_INT(Bots, BotCharacterLevel, 0) // 0 as default (if level > this value you can spawn bots if BotCharacterLevelEnabled is true) +RULE_INT(Bots, CasterStopMeleeLevel, 13) // Level at which caster bots stop melee attacks RULE_CATEGORY_END() #endif diff --git a/utils/sql/git/bots/optional/2014_03_31_BotLevelsWithOwnerRule.sql b/utils/sql/git/bots/optional/2014_03_31_BotLevelsWithOwnerRule.sql deleted file mode 100644 index 4700d9abf..000000000 --- a/utils/sql/git/bots/optional/2014_03_31_BotLevelsWithOwnerRule.sql +++ /dev/null @@ -1,4 +0,0 @@ -INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Bots:BotLevelsWithOwner', 'true', 'Auto-updates bots with ding.'); -INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (2, 'Bots:BotLevelsWithOwner', 'true', 'Auto-updates bots with ding.'); -INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (4, 'Bots:BotLevelsWithOwner', 'true', 'Auto-updates bots with ding.'); -INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (10, 'Bots:BotLevelsWithOwner', 'true', 'Auto-updates bots with ding.'); diff --git a/utils/sql/git/bots/optional/2014_03_31_bots_bot_levels_with_owner_rule.sql b/utils/sql/git/bots/optional/2014_03_31_bots_bot_levels_with_owner_rule.sql new file mode 100644 index 000000000..73a3c5b4c --- /dev/null +++ b/utils/sql/git/bots/optional/2014_03_31_bots_bot_levels_with_owner_rule.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Bots:BotLevelsWithOwner', 'true', 'Auto-updates bots with ding.'); diff --git a/utils/sql/git/bots/optional/2016_12_09_bots_caster_stop_melee_level_rule.sql b/utils/sql/git/bots/optional/2016_12_09_bots_caster_stop_melee_level_rule.sql new file mode 100644 index 000000000..1e50c659e --- /dev/null +++ b/utils/sql/git/bots/optional/2016_12_09_bots_caster_stop_melee_level_rule.sql @@ -0,0 +1,2 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Bots:CasterStopMeleeLevel', '13', 'Level at which caster bots stop melee attacks'); + diff --git a/zone/bot.cpp b/zone/bot.cpp index 133932df7..056a55289 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2391,7 +2391,7 @@ void Bot::AI_Process() { } } atCombatRange = true; - } else if(IsBotCaster() && GetLevel() > 12) { + } else if(IsBotCaster() && GetLevel() >= RuleI(Bots, CasterStopMeleeLevel)) { if(IsBotCasterCombatRange(GetTarget())) atCombatRange = true; } @@ -2440,7 +2440,7 @@ void Bot::AI_Process() { if(GetTarget()->GetHPRatio() <= 99.0f) BotRangedAttack(GetTarget()); } - else if(!IsBotArcher() && (!(IsBotCaster() && GetLevel() > 12)) && GetTarget() && !IsStunned() && !IsMezzed() && (GetAppearance() != eaDead)) { + else if(!IsBotArcher() && (!(IsBotCaster() && GetLevel() >= RuleI(Bots, CasterStopMeleeLevel))) && GetTarget() && !IsStunned() && !IsMezzed() && (GetAppearance() != eaDead)) { // we can't fight if we don't have a target, are stun/mezzed or dead.. // Stop attacking if the target is enraged if((IsEngaged() && !BehindMob(GetTarget(), GetX(), GetY()) && GetTarget()->IsEnraged()) || GetBotStance() == BotStancePassive) From 3cc7d0db6345821190901aeecc64c7768e39257a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 14 Dec 2016 22:06:05 -0500 Subject: [PATCH 466/693] Fix fizzle message being the wrong color --- zone/spells.cpp | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 814f01be6..409a07f47 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -230,23 +230,6 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, } } - // check for fizzle - // note that CheckFizzle itself doesn't let NPCs fizzle, - // but this code allows for it. - if(slot < CastingSlot::MaxGems && !CheckFizzle(spell_id)) - { - int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE; - InterruptSpell(fizzle_msg, 0x121, spell_id); - - uint32 use_mana = ((spells[spell_id].mana) / 4); - Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: fizzled. %d mana has been consumed", use_mana); - - // fizzle 1/4 the mana away - SetMana(GetMana() - use_mana); - TryTriggerOnValueAmount(false, true); - return(false); - } - if (HasActiveSong() && IsBardSong(spell_id)) { Log.Out(Logs::Detail, Logs::Spells, "Casting a new song while singing a song. Killing old song %d.", bardsong); //Note: this does NOT tell the client @@ -366,6 +349,28 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, } casting_spell_aa_id = aa_id; + // check for fizzle + // note that CheckFizzle itself doesn't let NPCs fizzle, + // but this code allows for it. + if (slot < CastingSlot::MaxGems && !CheckFizzle(spell_id)) { + int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE; + + uint32 use_mana = ((spells[spell_id].mana) / 4); + Log.Out(Logs::Detail, Logs::Spells, "Spell casting canceled: fizzled. %d mana has been consumed", use_mana); + + // fizzle 1/4 the mana away + Mob::SetMana(GetMana() - use_mana); // We send StopCasting which will update mana + StopCasting(); + + Message_StringID(MT_SpellFailure, fizzle_msg); + entity_list.FilteredMessageClose_StringID( + this, true, 200, MT_SpellFailure, IsClient() ? FilterPCSpells : FilterNPCSpells, + fizzle_msg == MISS_NOTE ? MISSED_NOTE_OTHER : SPELL_FIZZLE_OTHER, GetName()); + + TryTriggerOnValueAmount(false, true); + return(false); + } + SaveSpellLoc(); Log.Out(Logs::Detail, Logs::Spells, "Casting %d Started at (%.3f,%.3f,%.3f)", spell_id, m_SpellLocation.x, m_SpellLocation.y, m_SpellLocation.z); From d305d6727932ce969f3e4e9cf389b5c0af0876f7 Mon Sep 17 00:00:00 2001 From: SCMcLaughlin Date: Thu, 15 Dec 2016 14:47:58 -0800 Subject: [PATCH 467/693] Fix potential infinite loop in loginserver's config file reader --- loginserver/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loginserver/config.cpp b/loginserver/config.cpp index ee17bdbed..ecffb00f7 100644 --- a/loginserver/config.cpp +++ b/loginserver/config.cpp @@ -144,7 +144,7 @@ void Config::Parse(const char *file_name) */ void Config::Tokenize(FILE *input, std::list &tokens) { - char c = fgetc(input); + int c = fgetc(input); std::string lexeme; while(c != EOF) From c1fbfc0f44160a494393d2f21efdfab9d167bb36 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 15 Dec 2016 18:31:08 -0500 Subject: [PATCH 468/693] Add support for kicking epic loot locks Returning non-0 (no return in a lua/perl function = return 0 so this is best) will prevent the client from looting the item I still need to figure out how to make it so we don't have to kick the player from the corpse, but maybe that's just a difference on live --- zone/corpse.cpp | 10 +++++++++- zone/string_ids.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 34a2191b2..6a26f33ab 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1170,7 +1170,15 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { std::vector args; args.push_back(inst); args.push_back(this); - parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args); + if (parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args) != 0) { + lootitem->auto_loot = 0xFFFFFFFF; + client->Message_StringID(CC_Red, LOOT_NOT_ALLOWED, inst->GetItem()->Name); + client->QueuePacket(app); + SendEndLootErrorPacket(client); // shouldn't need this, but it will work for now + being_looted_by = 0; + delete inst; + return; + } parse->EventItem(EVENT_LOOT, client, inst, this, buf, 0); if (!IsPlayerCorpse() && RuleB(Character, EnableDiscoveredItems)) { diff --git a/zone/string_ids.h b/zone/string_ids.h index 67dd808ab..f03d8f44d 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -279,6 +279,7 @@ #define TRADESKILL_MISSING_COMPONENTS 3456 //Sorry, but you don't have everything you need for this recipe in your general inventory. #define TRADESKILL_LEARN_RECIPE 3457 //You have learned the recipe %1! #define EXPEDITION_MIN_REMAIN 3551 //You only have %1 minutes remaining before this expedition comes to an end. +#define LOOT_NOT_ALLOWED 3562 //You are not allowed to loot the item: %1. #define NO_CAST_ON_PET 4045 //You cannot cast this spell on your pet. #define REWIND_WAIT 4059 //You must wait a bit longer before using the rewind command again. #define CORPSEDRAG_LIMIT 4061 //You are already dragging as much as you can! From 343c23cc6c0868a22c2d5c77247c6d87dff8011a Mon Sep 17 00:00:00 2001 From: SCMcLaughlin Date: Thu, 15 Dec 2016 20:58:53 -0800 Subject: [PATCH 469/693] Additional LS config parser fixes: * use auto * fix some questionable uses of string.append() that were broken by the use of int/auto --- loginserver/config.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/loginserver/config.cpp b/loginserver/config.cpp index ecffb00f7..5582e9754 100644 --- a/loginserver/config.cpp +++ b/loginserver/config.cpp @@ -144,7 +144,7 @@ void Config::Parse(const char *file_name) */ void Config::Tokenize(FILE *input, std::list &tokens) { - int c = fgetc(input); + auto c = fgetc(input); std::string lexeme; while(c != EOF) @@ -162,7 +162,7 @@ void Config::Tokenize(FILE *input, std::list &tokens) if(isalnum(c)) { - lexeme.append((const char *)&c, 1); + lexeme += c; c = fgetc(input); continue; } @@ -193,14 +193,14 @@ void Config::Tokenize(FILE *input, std::list &tokens) lexeme.clear(); } - lexeme.append((const char *)&c, 1); + lexeme += c; tokens.push_back(lexeme); lexeme.clear(); break; } default: { - lexeme.append((const char *)&c, 1); + lexeme += c; } } From 8f5ba05e75a64848e13d0957559b258a09d1292f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 16 Dec 2016 16:02:42 -0500 Subject: [PATCH 470/693] Minor Corpse::LootItem refactoring --- zone/corpse.cpp | 22 ++++++++++------------ zone/corpse.h | 3 ++- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 6a26f33ab..e83631252 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -36,7 +36,6 @@ Child of the Mob class. #include "../common/string_util.h" #include "../common/say_link.h" -#include "client.h" #include "corpse.h" #include "entity.h" #include "groups.h" @@ -1070,9 +1069,8 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { if (!loot_cooldown_timer.Check()) { SendEndLootErrorPacket(client); //unlock corpse for others - if (this->being_looted_by = client->GetID()) { - being_looted_by = 0xFFFFFFFF; - } + if (IsBeingLootedBy(client)) + ResetLooter(); return; } @@ -1081,15 +1079,14 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { client->Message(13, "You may not loot an item while you have an item on your cursor."); SendEndLootErrorPacket(client); /* Unlock corpse for others */ - if (this->being_looted_by = client->GetID()) { - being_looted_by = 0xFFFFFFFF; - } + if (IsBeingLootedBy(client)) + ResetLooter(); return; } LootingItem_Struct* lootitem = (LootingItem_Struct*)app->pBuffer; - if (this->being_looted_by != client->GetID()) { + if (!IsBeingLootedBy(client)) { client->Message(13, "Error: Corpse::LootItem: BeingLootedBy != client"); SendEndLootErrorPacket(client); return; @@ -1107,9 +1104,10 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && GetPlayerKillItem() == 0){ client->Message(13, "Error: You cannot loot any more items from this corpse."); SendEndLootErrorPacket(client); - being_looted_by = 0xFFFFFFFF; + ResetLooter(); return; } + const EQEmu::ItemData* item = 0; EQEmu::ItemInstance *inst = 0; ServerLootItem_Struct* item_data = nullptr, *bag_item_data[10]; @@ -1142,7 +1140,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { if (client->CheckLoreConflict(item)) { client->Message_StringID(0, LOOT_LORE_ERROR); SendEndLootErrorPacket(client); - being_looted_by = 0; + ResetLooter(); delete inst; return; } @@ -1154,7 +1152,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { if (client->CheckLoreConflict(itm->GetItem())) { client->Message_StringID(0, LOOT_LORE_ERROR); SendEndLootErrorPacket(client); - being_looted_by = 0; + ResetLooter(); delete inst; return; } @@ -1175,7 +1173,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { client->Message_StringID(CC_Red, LOOT_NOT_ALLOWED, inst->GetItem()->Name); client->QueuePacket(app); SendEndLootErrorPacket(client); // shouldn't need this, but it will work for now - being_looted_by = 0; + ResetLooter(); delete inst; return; } diff --git a/zone/corpse.h b/zone/corpse.h index e83235c1e..49b1cba39 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -20,8 +20,8 @@ #define CORPSE_H #include "mob.h" +#include "client.h" -class Client; class EQApplicationPacket; class Group; class NPC; @@ -118,6 +118,7 @@ class Corpse : public Mob { inline bool IsLocked() { return is_locked; } inline void ResetLooter() { being_looted_by = 0xFFFFFFFF; } inline bool IsBeingLooted() { return (being_looted_by != 0xFFFFFFFF); } + inline bool IsBeingLootedBy(Client *c) { return being_looted_by == c->GetID(); } /* Mob */ void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); From 019586abbd0b42ecc09ccc77bbe3a566a7dd603a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 16 Dec 2016 16:03:44 -0500 Subject: [PATCH 471/693] Clang-format Corpse::LootItem --- zone/corpse.cpp | 98 ++++++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/zone/corpse.cpp b/zone/corpse.cpp index e83631252..216bf2299 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1062,13 +1062,14 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a SendLootReqErrorPacket(client, LootResponse::LootAll); } -void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { +void Corpse::LootItem(Client *client, const EQApplicationPacket *app) +{ /* This gets sent no matter what as a sort of ACK */ client->QueuePacket(app); if (!loot_cooldown_timer.Check()) { SendEndLootErrorPacket(client); - //unlock corpse for others + // unlock corpse for others if (IsBeingLootedBy(client)) ResetLooter(); return; @@ -1084,14 +1085,15 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { return; } - LootingItem_Struct* lootitem = (LootingItem_Struct*)app->pBuffer; + LootingItem_Struct *lootitem = (LootingItem_Struct *)app->pBuffer; if (!IsBeingLootedBy(client)) { client->Message(13, "Error: Corpse::LootItem: BeingLootedBy != client"); SendEndLootErrorPacket(client); return; } - if (IsPlayerCorpse() && !CanPlayerLoot(client->CharacterID()) && !become_npc && (char_id != client->CharacterID() && client->Admin() < 150)) { + if (IsPlayerCorpse() && !CanPlayerLoot(client->CharacterID()) && !become_npc && + (char_id != client->CharacterID() && client->Admin() < 150)) { client->Message(13, "Error: This is a player corpse and you dont own it."); SendEndLootErrorPacket(client); return; @@ -1101,37 +1103,39 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { client->Message(13, "Error: Corpse locked by GM."); return; } - if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && GetPlayerKillItem() == 0){ + if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && + GetPlayerKillItem() == 0) { client->Message(13, "Error: You cannot loot any more items from this corpse."); SendEndLootErrorPacket(client); ResetLooter(); return; } - const EQEmu::ItemData* item = 0; + const EQEmu::ItemData *item = 0; EQEmu::ItemInstance *inst = 0; - ServerLootItem_Struct* item_data = nullptr, *bag_item_data[10]; + ServerLootItem_Struct *item_data = nullptr, *bag_item_data[10]; memset(bag_item_data, 0, sizeof(bag_item_data)); - if (GetPlayerKillItem() > 1){ + if (GetPlayerKillItem() > 1) { item = database.GetItem(GetPlayerKillItem()); - } - else if (GetPlayerKillItem() == -1 || GetPlayerKillItem() == 1){ - item_data = GetItem(lootitem->slot_id - EQEmu::legacy::CORPSE_BEGIN); //dont allow them to loot entire bags of items as pvp reward - } - else{ + } else if (GetPlayerKillItem() == -1 || GetPlayerKillItem() == 1) { + item_data = + GetItem(lootitem->slot_id - + EQEmu::legacy::CORPSE_BEGIN); // dont allow them to loot entire bags of items as pvp reward + } else { item_data = GetItem(lootitem->slot_id - EQEmu::legacy::CORPSE_BEGIN, bag_item_data); } - if (GetPlayerKillItem()<=1 && item_data != 0) { + if (GetPlayerKillItem() <= 1 && item_data != 0) { item = database.GetItem(item_data->item_id); } if (item != 0) { - if (item_data){ - inst = database.CreateItem(item, item_data ? item_data->charges : 0, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned); - } - else { + if (item_data) { + inst = database.CreateItem(item, item_data ? item_data->charges : 0, item_data->aug_1, + item_data->aug_2, item_data->aug_3, item_data->aug_4, + item_data->aug_5, item_data->aug_6, item_data->attuned); + } else { inst = database.CreateItem(item); } } @@ -1163,7 +1167,8 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { char buf[88]; char q_corpse_name[64]; strcpy(q_corpse_name, corpse_name); - snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(q_corpse_name)); + snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(), + EntityList::RemoveNumbers(q_corpse_name)); buf[87] = '\0'; std::vector args; args.push_back(inst); @@ -1185,7 +1190,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { } if (zone->adv_data) { - ServerZoneAdventureDataReply_Struct *ad = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; + ServerZoneAdventureDataReply_Struct *ad = (ServerZoneAdventureDataReply_Struct *)zone->adv_data; if (ad->type == Adventure_Collect && !IsPlayerCorpse()) { if (ad->data_id == inst->GetItem()->ID) { zone->DoAdventureCountIncrease(); @@ -1197,8 +1202,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { if (lootitem->auto_loot) { if (!client->AutoPutLootInInventory(*inst, true, true, bag_item_data)) client->PutLootInInventory(EQEmu::inventory::slotCursor, *inst, bag_item_data); - } - else { + } else { client->PutLootInInventory(EQEmu::inventory::slotCursor, *inst, bag_item_data); } @@ -1207,9 +1211,11 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { client->UpdateTasksForItem(ActivityLoot, item->ID); /* Remove it from Corpse */ - if (item_data){ - /* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */ - database.DeleteItemOffCharacterCorpse(this->corpse_db_id, item_data->equip_slot, item_data->item_id); + if (item_data) { + /* Delete needs to be before RemoveItem because its deletes the pointer for + * item_data/bag_item_data */ + database.DeleteItemOffCharacterCorpse(this->corpse_db_id, item_data->equip_slot, + item_data->item_id); /* Delete Item Instance */ RemoveItem(item_data->lootslot); } @@ -1218,8 +1224,11 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { if (item->IsClassBag() && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) { for (int i = EQEmu::inventory::containerBegin; i < EQEmu::inventory::ContainerCount; i++) { if (bag_item_data[i]) { - /* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */ - database.DeleteItemOffCharacterCorpse(this->corpse_db_id, bag_item_data[i]->equip_slot, bag_item_data[i]->item_id); + /* Delete needs to be before RemoveItem because its deletes the pointer for + * item_data/bag_item_data */ + database.DeleteItemOffCharacterCorpse(this->corpse_db_id, + bag_item_data[i]->equip_slot, + bag_item_data[i]->item_id); /* Delete Item Instance */ RemoveItem(bag_item_data[i]); } @@ -1230,38 +1239,37 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { SetPlayerKillItemID(0); } - /* Send message with item link to groups and such */ - EQEmu::SayLinkEngine linker; - linker.SetLinkType(EQEmu::saylink::SayLinkItemInst); - linker.SetItemInst(inst); + /* Send message with item link to groups and such */ + EQEmu::SayLinkEngine linker; + linker.SetLinkType(EQEmu::saylink::SayLinkItemInst); + linker.SetItemInst(inst); - auto item_link = linker.GenerateLink(); + auto item_link = linker.GenerateLink(); - client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, item_link.c_str()); + client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, item_link.c_str()); - if (!IsPlayerCorpse()) { + if (!IsPlayerCorpse()) { Group *g = client->GetGroup(); - if(g != nullptr) { - g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str()); - } - else { + if (g != nullptr) { + g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, + client->GetName(), item_link.c_str()); + } else { Raid *r = client->GetRaid(); - if(r != nullptr) { - r->RaidMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str()); + if (r != nullptr) { + r->RaidMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, + client->GetName(), item_link.c_str()); } } } - } - else { + } else { SendEndLootErrorPacket(client); safe_delete(inst); return; } - if (IsPlayerCorpse()){ + if (IsPlayerCorpse()) { client->SendItemLink(inst); - } - else{ + } else { client->SendItemLink(inst, true); } From e680a0f70429d4e355c4ab029b0ba1987634818f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 16 Dec 2016 16:09:31 -0500 Subject: [PATCH 472/693] Change LottingItem_Struct::auto_loot to signed --- common/eq_packet_structs.h | 2 +- common/patches/rof_structs.h | 2 +- common/patches/sod_structs.h | 2 +- common/patches/sof_structs.h | 2 +- common/patches/titanium_structs.h | 2 +- common/patches/uf_structs.h | 2 +- zone/corpse.cpp | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 1d25e4d66..ffbcead70 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1643,7 +1643,7 @@ struct LootingItem_Struct { /*002*/ uint32 looter; /*004*/ uint16 slot_id; /*006*/ uint8 unknown3[2]; -/*008*/ uint32 auto_loot; +/*008*/ int32 auto_loot; }; struct GuildManageStatus_Struct{ diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 879afc1d4..32c7c0d28 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -2021,7 +2021,7 @@ struct LootingItem_Struct { /*004*/ uint32 looter; /*008*/ uint16 slot_id; /*010*/ uint16 unknown10; -/*012*/ uint32 auto_loot; +/*012*/ int32 auto_loot; /*016*/ uint32 unknown16; /*020*/ }; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index cd76218e0..fdcb03658 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1666,7 +1666,7 @@ struct LootingItem_Struct { /*000*/ uint32 lootee; /*004*/ uint32 looter; /*008*/ uint32 slot_id; -/*012*/ uint32 auto_loot; +/*012*/ int32 auto_loot; /*016*/ uint32 unknown16; /*020*/ }; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 9be93d49f..00fcd4ecf 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1648,7 +1648,7 @@ struct LootingItem_Struct { /*002*/ uint32 looter; /*004*/ uint16 slot_id; /*006*/ uint8 unknown3[2]; -/*008*/ uint32 auto_loot; +/*008*/ int32 auto_loot; }; struct GuildManageStatus_Struct{ diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 91921da2e..69988dd7c 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -1420,7 +1420,7 @@ struct LootingItem_Struct { /*002*/ uint32 looter; /*004*/ uint16 slot_id; /*006*/ uint8 unknown3[2]; -/*008*/ uint32 auto_loot; +/*008*/ int32 auto_loot; }; struct GuildManageStatus_Struct{ diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index ec279e56c..560a9378d 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1707,7 +1707,7 @@ struct LootingItem_Struct { /*000*/ uint32 lootee; /*004*/ uint32 looter; /*008*/ uint32 slot_id; -/*012*/ uint32 auto_loot; +/*012*/ int32 auto_loot; /*016*/ uint32 unknown16; /*020*/ }; diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 216bf2299..8219577de 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1174,7 +1174,7 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) args.push_back(inst); args.push_back(this); if (parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args) != 0) { - lootitem->auto_loot = 0xFFFFFFFF; + lootitem->auto_loot = -1; client->Message_StringID(CC_Red, LOOT_NOT_ALLOWED, inst->GetItem()->Name); client->QueuePacket(app); SendEndLootErrorPacket(client); // shouldn't need this, but it will work for now @@ -1199,7 +1199,7 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) } /* First add it to the looter - this will do the bag contents too */ - if (lootitem->auto_loot) { + if (lootitem->auto_loot > 0) { if (!client->AutoPutLootInInventory(*inst, true, true, bag_item_data)) client->PutLootInInventory(EQEmu::inventory::slotCursor, *inst, bag_item_data); } else { From f53b95d141689aab8150ddb968325097a7a8118f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 16 Dec 2016 17:11:44 -0500 Subject: [PATCH 473/693] Rework look acking a bit We should no longer kick from corpse if the quest says to not loot an item Need to investigate autoloot behavior with respect to everything still So other cases will still kick you from the corpse (lore conflict etc) --- zone/corpse.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 8219577de..24c4b8220 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1064,10 +1064,10 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a void Corpse::LootItem(Client *client, const EQApplicationPacket *app) { - /* This gets sent no matter what as a sort of ACK */ - client->QueuePacket(app); + auto lootitem = (LootingItem_Struct *)app->pBuffer; if (!loot_cooldown_timer.Check()) { + client->QueuePacket(app); SendEndLootErrorPacket(client); // unlock corpse for others if (IsBeingLootedBy(client)) @@ -1078,6 +1078,7 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) /* To prevent item loss for a player using 'Loot All' who doesn't have inventory space for all their items. */ if (RuleB(Character, CheckCursorEmptyWhenLooting) && !client->GetInv().CursorEmpty()) { client->Message(13, "You may not loot an item while you have an item on your cursor."); + client->QueuePacket(app); SendEndLootErrorPacket(client); /* Unlock corpse for others */ if (IsBeingLootedBy(client)) @@ -1085,27 +1086,32 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) return; } - LootingItem_Struct *lootitem = (LootingItem_Struct *)app->pBuffer; - if (!IsBeingLootedBy(client)) { client->Message(13, "Error: Corpse::LootItem: BeingLootedBy != client"); + client->QueuePacket(app); SendEndLootErrorPacket(client); return; } + if (IsPlayerCorpse() && !CanPlayerLoot(client->CharacterID()) && !become_npc && (char_id != client->CharacterID() && client->Admin() < 150)) { client->Message(13, "Error: This is a player corpse and you dont own it."); + client->QueuePacket(app); SendEndLootErrorPacket(client); return; } + if (is_locked && client->Admin() < 100) { + client->QueuePacket(app); SendLootReqErrorPacket(client, LootResponse::SomeoneElse); client->Message(13, "Error: Corpse locked by GM."); return; } + if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && GetPlayerKillItem() == 0) { client->Message(13, "Error: You cannot loot any more items from this corpse."); + client->QueuePacket(app); SendEndLootErrorPacket(client); ResetLooter(); return; @@ -1143,6 +1149,7 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) if (client && inst) { if (client->CheckLoreConflict(item)) { client->Message_StringID(0, LOOT_LORE_ERROR); + client->QueuePacket(app); SendEndLootErrorPacket(client); ResetLooter(); delete inst; @@ -1155,6 +1162,7 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) if (itm) { if (client->CheckLoreConflict(itm->GetItem())) { client->Message_StringID(0, LOOT_LORE_ERROR); + client->QueuePacket(app); SendEndLootErrorPacket(client); ResetLooter(); delete inst; @@ -1177,13 +1185,15 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) lootitem->auto_loot = -1; client->Message_StringID(CC_Red, LOOT_NOT_ALLOWED, inst->GetItem()->Name); client->QueuePacket(app); - SendEndLootErrorPacket(client); // shouldn't need this, but it will work for now - ResetLooter(); delete inst; return; } + // do we want this to have a fail option too? parse->EventItem(EVENT_LOOT, client, inst, this, buf, 0); + // safe to ACK now + client->QueuePacket(app); + if (!IsPlayerCorpse() && RuleB(Character, EnableDiscoveredItems)) { if (client && !client->GetGM() && !client->IsDiscovered(inst->GetItem()->ID)) client->DiscoverItem(inst->GetItem()->ID); From 06279b18a3e5fde8ebc198742e6e94eb53609338 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 18 Dec 2016 05:36:30 -0600 Subject: [PATCH 474/693] Fix Hero Forge model not showing up at character select --- common/shareddb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index fc628ea6f..5205c97da 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -594,7 +594,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::InventoryProfile *inv) inst->SetOrnamentIcon(ornament_icon); inst->SetOrnamentationIDFile(ornament_idfile); - inst->SetOrnamentHeroModel(ornament_hero_model); + inst->SetOrnamentHeroModel(item->HerosForgeModel); if (instnodrop || (((slot_id >= EQEmu::legacy::EQUIPMENT_BEGIN && slot_id <= EQEmu::legacy::EQUIPMENT_END) || @@ -730,7 +730,7 @@ bool SharedDatabase::GetInventory(uint32 account_id, char *name, EQEmu::Inventor inst->SetOrnamentIcon(ornament_icon); inst->SetOrnamentationIDFile(ornament_idfile); - inst->SetOrnamentHeroModel(ornament_hero_model); + inst->SetOrnamentHeroModel(item->HerosForgeModel); if (color > 0) inst->SetColor(color); From 648078d76c50be0f5e1b99e0cbad3b2cfcef6348 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 18 Dec 2016 20:20:27 -0500 Subject: [PATCH 475/693] More NoDrop-related hack abatement --- common/inventory_profile.cpp | 17 ++++++----------- common/inventory_profile.h | 2 +- zone/client.h | 2 +- zone/inventory.cpp | 4 ++-- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index 03b1df4e0..ae17a2a17 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -293,18 +293,13 @@ bool EQEmu::InventoryProfile::DeleteItem(int16 slot_id, uint8 quantity) } // Checks All items in a bag for No Drop -bool EQEmu::InventoryProfile::CheckNoDrop(int16 slot_id) { +bool EQEmu::InventoryProfile::CheckNoDrop(int16 slot_id, bool recurse) +{ ItemInstance* inst = GetItem(slot_id); - if (!inst) return false; - if (!inst->GetItem()->NoDrop) return true; - if (inst->GetItem()->ItemClass == 1) { - for (uint8 i = inventory::containerBegin; i < inventory::ContainerCount; i++) { - ItemInstance* bagitem = GetItem(InventoryProfile::CalcSlotId(slot_id, i)); - if (bagitem && !bagitem->GetItem()->NoDrop) - return true; - } - } - return false; + if (!inst) + return false; + + return (!inst->IsDroppable(recurse)); } // Remove item from bucket without memory delete diff --git a/common/inventory_profile.h b/common/inventory_profile.h index 336bb47d8..b9ae1db8c 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -133,7 +133,7 @@ namespace EQEmu bool DeleteItem(int16 slot_id, uint8 quantity = 0); // Checks All items in a bag for No Drop - bool CheckNoDrop(int16 slot_id); + bool CheckNoDrop(int16 slot_id, bool recurse = true); // Remove item from inventory (and take control of memory) ItemInstance* PopItem(int16 slot_id); diff --git a/zone/client.h b/zone/client.h index 8bb996bdf..803540ffb 100644 --- a/zone/client.h +++ b/zone/client.h @@ -825,7 +825,7 @@ public: bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = EQEmu::inventory::slotCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); void SetStats(uint8 type,int16 set_val); void IncStats(uint8 type,int16 increase_val); - void DropItem(int16 slot_id); + void DropItem(int16 slot_id, bool recurse = true); int GetItemLinkHash(const EQEmu::ItemInstance* inst); // move to ItemData..or make use of the pre-calculated database field diff --git a/zone/inventory.cpp b/zone/inventory.cpp index c5d7de0fe..d86de7fd8 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -594,9 +594,9 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, } // Drop item from inventory to ground (generally only dropped from SLOT_CURSOR) -void Client::DropItem(int16 slot_id) +void Client::DropItem(int16 slot_id, bool recurse) { - if(GetInv().CheckNoDrop(slot_id) && RuleI(World, FVNoDropFlag) == 0 || + if(GetInv().CheckNoDrop(slot_id, recurse) && RuleI(World, FVNoDropFlag) == 0 || RuleI(Character, MinStatusForNoDropExemptions) < Admin() && RuleI(World, FVNoDropFlag) == 2) { database.SetHackerFlag(this->AccountName(), this->GetCleanName(), "Tried to drop an item on the ground that was nodrop!"); GetInv().DeleteItem(slot_id); From 908a7061cfcddc39379da1db37459435533ca497 Mon Sep 17 00:00:00 2001 From: Drajor Date: Mon, 19 Dec 2016 21:00:55 +1000 Subject: [PATCH 476/693] Hero forge ID in OP_WearChange originating from a client is now set to the correct value prior to being broadcast to other clients. --- zone/client_packet.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 0ba79d15f..1de41d6b3 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -14049,6 +14049,10 @@ void Client::Handle_OP_WearChange(const EQApplicationPacket *app) if (wc->spawn_id != GetID()) return; + // Hero Forge ID needs to be fixed here as RoF2 appears to send an incorrect value. + if (wc->hero_forge_model != 0 && wc->wear_slot_id >= 0 && wc->wear_slot_id < EQEmu::textures::weaponPrimary) + wc->hero_forge_model = GetHerosForgeModel(wc->wear_slot_id); + // we could maybe ignore this and just send our own from moveitem entity_list.QueueClients(this, app, true); return; From 18693998b9762ccf0c01627b0bd82fa5840362fd Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 19 Dec 2016 20:58:38 -0500 Subject: [PATCH 477/693] Added logging code to DropItem() --- zone/client_packet.cpp | 3 +++ zone/inventory.cpp | 58 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 1de41d6b3..56936147d 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5003,6 +5003,9 @@ void Client::Handle_OP_CrashDump(const EQApplicationPacket *app) void Client::Handle_OP_CreateObject(const EQApplicationPacket *app) { + if (Log.log_settings[Logs::Inventory].is_category_enabled) + Log.Out(Logs::Detail, Logs::Inventory, "Handle_OP_CreateObject() [psize: %u] %s", app->size, DumpPacketToString(app).c_str()); + DropItem(EQEmu::inventory::slotCursor); return; } diff --git a/zone/inventory.cpp b/zone/inventory.cpp index d86de7fd8..416a97e28 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -596,8 +596,35 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2, // Drop item from inventory to ground (generally only dropped from SLOT_CURSOR) void Client::DropItem(int16 slot_id, bool recurse) { + Log.Out(Logs::General, Logs::Inventory, "'%s' (char_id: %u) Attempting to drop item from slot %i on the ground", + GetCleanName(), CharacterID(), slot_id); + if(GetInv().CheckNoDrop(slot_id, recurse) && RuleI(World, FVNoDropFlag) == 0 || - RuleI(Character, MinStatusForNoDropExemptions) < Admin() && RuleI(World, FVNoDropFlag) == 2) { + RuleI(Character, MinStatusForNoDropExemptions) < Admin() && RuleI(World, FVNoDropFlag) == 2) + { + auto invalid_drop = m_inv.GetItem(slot_id); + if (!invalid_drop) { + Log.Out(Logs::General, Logs::Inventory, "Error in InventoryProfile::CheckNoDrop() - returned 'true' for empty slot"); + } + else { + if (Log.log_settings[Logs::Inventory].is_category_enabled) { + Log.Out(Logs::General, Logs::Inventory, "DropItem() Hack detected - full item parse:"); + Log.Out(Logs::General, Logs::Inventory, "depth: 0, Item: '%s' (id: %u), IsDroppable: %s", + (invalid_drop->GetItem() ? invalid_drop->GetItem()->Name : "null data"), invalid_drop->GetID(), invalid_drop->IsDroppable(false)); + + for (auto iter1 : *invalid_drop->GetContents()) { // depth 1 + Log.Out(Logs::General, Logs::Inventory, "-depth: 1, Item: '%s' (id: %u), IsDroppable: %s", + (iter1.second->GetItem() ? iter1.second->GetItem()->Name : "null data"), iter1.second->GetID(), iter1.second->IsDroppable(false)); + + for (auto iter2 : *iter1.second->GetContents()) { // depth 2 + Log.Out(Logs::General, Logs::Inventory, "--depth: 2, Item: '%s' (id: %u), IsDroppable: %s", + (iter2.second->GetItem() ? iter2.second->GetItem()->Name : "null data"), iter2.second->GetID(), iter2.second->IsDroppable(false)); + } + } + } + } + invalid_drop = nullptr; + database.SetHackerFlag(this->AccountName(), this->GetCleanName(), "Tried to drop an item on the ground that was nodrop!"); GetInv().DeleteItem(slot_id); return; @@ -606,12 +633,39 @@ void Client::DropItem(int16 slot_id, bool recurse) // Take control of item in client inventory EQEmu::ItemInstance *inst = m_inv.PopItem(slot_id); if(inst) { + if (Log.log_settings[Logs::Inventory].is_category_enabled) { + Log.Out(Logs::General, Logs::Inventory, "DropItem() Processing - full item parse:"); + Log.Out(Logs::General, Logs::Inventory, "depth: 0, Item: '%s' (id: %u), IsDroppable: %s", + (inst->GetItem() ? inst->GetItem()->Name : "null data"), inst->GetID(), inst->IsDroppable(false)); + + if (!inst->IsDroppable(false)) + Log.Out(Logs::General, Logs::Error, "Non-droppable item being processed for drop by '%s'", GetCleanName()); + + for (auto iter1 : *inst->GetContents()) { // depth 1 + Log.Out(Logs::General, Logs::Inventory, "-depth: 1, Item: '%s' (id: %u), IsDroppable: %s", + (iter1.second->GetItem() ? iter1.second->GetItem()->Name : "null data"), iter1.second->GetID(), iter1.second->IsDroppable(false)); + + if (!iter1.second->IsDroppable(false)) + Log.Out(Logs::General, Logs::Error, "Non-droppable item being processed for drop by '%s'", GetCleanName()); + + for (auto iter2 : *iter1.second->GetContents()) { // depth 2 + Log.Out(Logs::General, Logs::Inventory, "--depth: 2, Item: '%s' (id: %u), IsDroppable: %s", + (iter2.second->GetItem() ? iter2.second->GetItem()->Name : "null data"), iter2.second->GetID(), iter2.second->IsDroppable(false)); + + if (!iter2.second->IsDroppable(false)) + Log.Out(Logs::General, Logs::Error, "Non-droppable item being processed for drop by '%s'", GetCleanName()); + } + } + } + int i = parse->EventItem(EVENT_DROP_ITEM, this, inst, nullptr, "", slot_id); if(i != 0) { + Log.Out(Logs::General, Logs::Inventory, "Item drop handled by [EVENT_DROP_ITEM]"); safe_delete(inst); } } else { // Item doesn't exist in inventory! + Log.Out(Logs::General, Logs::Inventory, "DropItem() - No item found in slot %i", slot_id); Message(13, "Error: Item not found in slot %i", slot_id); return; } @@ -633,6 +687,8 @@ void Client::DropItem(int16 slot_id, bool recurse) entity_list.AddObject(object, true); object->StartDecay(); + Log.Out(Logs::General, Logs::Inventory, "Item drop handled ut assolet"); + safe_delete(inst); } From a13e32498a639aa93a6541fbb7da69b0147a7faa Mon Sep 17 00:00:00 2001 From: Drajor Date: Wed, 21 Dec 2016 13:03:19 +1000 Subject: [PATCH 478/693] Hero Forge robes are now visible at character select. Items using a robe HF ID need use the actual ID in the DB i.e. 11607-12107. WearChange command modified to allow both shorthand HF IDs and explicit IDs. --- common/item_instance.cpp | 20 ++++++++++---------- zone/command.cpp | 17 ++++------------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/common/item_instance.cpp b/common/item_instance.cpp index d8d23064e..ffec614b4 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -539,16 +539,16 @@ EQEmu::ItemInstance* EQEmu::ItemInstance::GetOrnamentationAug(int32 ornamentatio } uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const { - uint32 HeroModel = 0; - if (m_ornament_hero_model > 0) - { - HeroModel = m_ornament_hero_model; - if (material_slot >= 0) - { - HeroModel = (m_ornament_hero_model * 100) + material_slot; - } - } - return HeroModel; + // Not a Hero Forge item. + if (m_ornament_hero_model == 0) + return 0; + + // Item is using an explicit Hero Forge ID + if (m_ornament_hero_model >= 1000) + return m_ornament_hero_model; + + // Item is using a shorthand ID + return (m_ornament_hero_model * 100) + material_slot; } bool EQEmu::ItemInstance::UpdateOrnamentationInfo() { diff --git a/zone/command.cpp b/zone/command.cpp index 718feedcc..307b4e949 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -745,24 +745,15 @@ void command_wc(Client *c, const Seperator *sep) uint32 hero_forge_model = 0; uint32 wearslot = atoi(sep->arg[1]); + // Hero Forge if (sep->argnum > 2) { hero_forge_model = atoi(sep->arg[3]); - if (hero_forge_model > 0) - { - // Conversion to simplify the command arguments - // Hero's Forge model is actually model * 1000 + texture * 100 + wearslot - hero_forge_model *= 1000; - hero_forge_model += (atoi(sep->arg[2]) * 100); - hero_forge_model += wearslot; - // For Hero's Forge, slot 7 is actually for Robes, but it still needs to use slot 1 in the packet - if (wearslot == 7) - { - wearslot = 1; - } + if (hero_forge_model != 0 && hero_forge_model < 1000) { + // Shorthand Hero Forge ID. Otherwise use the value the user entered. + hero_forge_model = (hero_forge_model * 100) + wearslot; } - } /* // Leaving here to add color option to the #wc command eventually From 55e78cd8e9ffbcaab3cb28713a34a5860a5d478d Mon Sep 17 00:00:00 2001 From: Drajor Date: Wed, 21 Dec 2016 13:28:05 +1000 Subject: [PATCH 479/693] Fix for error in previous change. ItemInstance::GetOrnamentHeroModel will return zero again when parameter material_slot is the default -1. --- common/item_instance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/item_instance.cpp b/common/item_instance.cpp index ffec614b4..a2860f3e5 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -540,7 +540,7 @@ EQEmu::ItemInstance* EQEmu::ItemInstance::GetOrnamentationAug(int32 ornamentatio uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const { // Not a Hero Forge item. - if (m_ornament_hero_model == 0) + if (m_ornament_hero_model == 0 || material_slot < 0) return 0; // Item is using an explicit Hero Forge ID From 630ea0d3c63c7f8ecd79610efd56b1eb68db126e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 21 Dec 2016 13:45:18 -0500 Subject: [PATCH 480/693] Fix RoF2 OP_GMHideMe --- utils/patches/patch_RoF2.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 19ef8d842..20111e850 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -150,7 +150,7 @@ OP_GMZoneRequest=0x62ac OP_GMZoneRequest2=0x7e1a OP_GMGoto=0x7d8e OP_GMSearchCorpse=0x357c -OP_GMHideMe=0x79c5 +OP_GMHideMe=0x2fab OP_GMDelCorpse=0x607e OP_GMApproval=0x6db5 OP_GMToggle=0x2097 From 6a2be94282d0a2174c92b74732a2e5d8031dee7c Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Wed, 21 Dec 2016 14:38:24 -0500 Subject: [PATCH 481/693] Alliance spell line for chanters was not working. --- zone/spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 814f01be6..a44a2ef5d 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3631,7 +3631,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r } - if(!IsBeneficialAllowed(spelltar) || + if((!IsAllianceSpellLine(spell_id) && !IsBeneficialAllowed(spelltar)) || (IsGroupOnlySpell(spell_id) && !( (pBasicGroup && ((pBasicGroup == pBasicGroupTarget) || (pBasicGroup == pBasicGroupTargetPet))) || //Basic Group From 1d19bd11d0efc4d7e8a5d1a082bb2e12cb887560 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 25 Dec 2016 21:06:02 -0500 Subject: [PATCH 482/693] Add Random::Roll0 This has the same interval ((0,N]) that the client function does The devs have referenced this in a few posts talking about mechanics. --- common/random.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/common/random.h b/common/random.h index 44be53e98..0c877bfea 100644 --- a/common/random.h +++ b/common/random.h @@ -65,6 +65,15 @@ namespace EQEmu { return Real(0.0, 1.0) <= required; } + // same range as client's roll0 + // This is their main high level RNG function + int Roll0(int max) + { + if (max - 1 > 0) + return Int(0, max - 1); + return 0; + } + // std::shuffle requires a RNG engine passed to it, so lets provide a wrapper to use our engine template void Shuffle(RandomAccessIterator first, RandomAccessIterator last) From f5827174ee7758293e60258f4b27337df6f59601 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 25 Dec 2016 21:11:10 -0500 Subject: [PATCH 483/693] Make CheckHitChance much more live like This should be fairly close to live-like. Based on client decompiling, Torven's write up and parses and more parses. It will probably break your server. --- zone/attack.cpp | 256 +++++++++++++++++---------------------- zone/bot.cpp | 6 +- zone/mob.h | 4 +- zone/special_attacks.cpp | 10 +- zone/zonedump.h | 4 +- 5 files changed, 124 insertions(+), 156 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 40de941dc..47b7bcb66 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -139,175 +139,141 @@ bool Mob::AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const return true; } +int Mob::compute_tohit(EQEmu::skills::SkillType skillinuse) +{ + int tohit = GetSkill(EQEmu::skills::SkillOffense) + 7; + tohit += GetSkill(skillinuse); + if (IsNPC()) + tohit += CastToNPC()->GetAccuracyRating(); + if (IsClient()) { + double reduction = CastToClient()->m_pp.intoxication / 2.0; + if (reduction > 20.0) { + reduction = std::min((110 - reduction) / 100.0, 1.0); + tohit = reduction * static_cast(tohit); + } else if (IsBerserk()) { + tohit += (GetLevel() * 2) / 5; + } + } + return std::max(tohit, 1); +} + +// based on dev quotes +// the AGI bonus has actually drastically changed from classic +int Mob::compute_defense() +{ + int defense = GetSkill(EQEmu::skills::SkillDefense) * 400 / 225; + defense += (8000 * (GetAGI() - 40)) / 36000; + if (IsClient()) + defense += CastToClient()->GetHeroicAGI() / 10; + + defense += itembonuses.AvoidMeleeChance; // item mod2 + if (IsNPC()) + defense += CastToNPC()->GetAvoidanceRating(); + + if (IsClient()) { + double reduction = CastToClient()->m_pp.intoxication / 2.0; + if (reduction > 20.0) { + reduction = std::min((110 - reduction) / 100.0, 1.0); + defense = reduction * static_cast(defense); + } + } + + return std::max(1, defense); +} + // called when a mob is attacked, does the checks to see if it's a hit // and does other mitigation checks. 'this' is the mob being attacked. -bool Mob::CheckHitChance(Mob* other, EQEmu::skills::SkillType skillinuse, int Hand, int16 chance_mod) +bool Mob::CheckHitChance(Mob* other, EQEmu::skills::SkillType skillinuse, int chance_mod) { -/*/ - //Reworked a lot of this code to achieve better balance at higher levels. - //The old code basically meant that any in high level (50+) combat, - //both parties always had 95% chance to hit the other one. -/*/ - - Mob *attacker=other; - Mob *defender=this; - float chancetohit = RuleR(Combat, BaseHitChance); - - if(attacker->IsNPC() && !attacker->IsPet()) - chancetohit += RuleR(Combat, NPCBonusHitChance); - + Mob *attacker = other; + Mob *defender = this; Log.Out(Logs::Detail, Logs::Attack, "CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName()); - bool pvpmode = false; - if(IsClient() && other->IsClient()) - pvpmode = true; - - if (chance_mod >= 10000) + // calculate defender's avoidance + auto avoidance = defender->compute_defense() + 10; // add 10 in case the NPC's stats are fucked + auto evasion_bonus = defender->spellbonuses.AvoidMeleeChanceEffect; // we check this first since it has a special case + if (evasion_bonus <= -100) return true; - - float avoidanceBonus = 0; - float hitBonus = 0; - - //////////////////////////////////////////////////////// - // To hit calcs go here - //////////////////////////////////////////////////////// - - uint8 attacker_level = attacker->GetLevel() ? attacker->GetLevel() : 1; - uint8 defender_level = defender->GetLevel() ? defender->GetLevel() : 1; - - //Calculate the level difference - - Log.Out(Logs::Detail, Logs::Attack, "Chance to hit before level diff calc %.2f", chancetohit); - - double level_difference = attacker_level - defender_level; - double range = defender->GetLevel(); - range = ((range / 4) + 3); - - if(level_difference < 0) - { - if(level_difference >= -range) - { - chancetohit += (level_difference / range) * RuleR(Combat,HitFalloffMinor); //5 - } - else if (level_difference >= -(range+3.0)) - { - chancetohit -= RuleR(Combat,HitFalloffMinor); - chancetohit += ((level_difference+range) / (3.0)) * RuleR(Combat,HitFalloffModerate); //7 - } - else - { - chancetohit -= (RuleR(Combat,HitFalloffMinor) + RuleR(Combat,HitFalloffModerate)); - chancetohit += ((level_difference+range+3.0)/12.0) * RuleR(Combat,HitFalloffMajor); //50 - } - } - else - { - chancetohit += (RuleR(Combat,HitBonusPerLevel) * level_difference); - } - - Log.Out(Logs::Detail, Logs::Attack, "Chance to hit after level diff calc %.2f", chancetohit); - - chancetohit -= ((float)defender->GetAGI() * RuleR(Combat, AgiHitFactor)); - - Log.Out(Logs::Detail, Logs::Attack, "Chance to hit after Agility calc %.2f", chancetohit); - - if(attacker->IsClient()) - { - chancetohit -= (RuleR(Combat,WeaponSkillFalloff) * (attacker->CastToClient()->MaxSkill(skillinuse) - attacker->GetSkill(skillinuse))); - Log.Out(Logs::Detail, Logs::Attack, "Chance to hit after agil calc %.2f", "Chance to hit after weapon falloff calc (attack) %.2f", chancetohit); - } - - if(defender->IsClient()) - { - chancetohit += (RuleR(Combat, WeaponSkillFalloff) * (defender->CastToClient()->MaxSkill(EQEmu::skills::SkillDefense) - defender->GetSkill(EQEmu::skills::SkillDefense))); - Log.Out(Logs::Detail, Logs::Attack, "Chance to hit after weapon falloff calc (defense) %.2f", chancetohit); - } - - //I dont think this is 100% correct, but at least it does something... - if(attacker->spellbonuses.MeleeSkillCheckSkill == skillinuse || attacker->spellbonuses.MeleeSkillCheckSkill == 255) { - chancetohit += attacker->spellbonuses.MeleeSkillCheck; - Log.Out(Logs::Detail, Logs::Attack, "Applied spell melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit); - } - if(attacker->itembonuses.MeleeSkillCheckSkill == skillinuse || attacker->itembonuses.MeleeSkillCheckSkill == 255) { - chancetohit += attacker->itembonuses.MeleeSkillCheck; - Log.Out(Logs::Detail, Logs::Attack, "Applied item melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit); - } - - //Avoidance Bonuses on defender decreases baseline hit chance by percent. - avoidanceBonus = defender->spellbonuses.AvoidMeleeChanceEffect + - defender->itembonuses.AvoidMeleeChanceEffect + - defender->aabonuses.AvoidMeleeChanceEffect + - (defender->itembonuses.AvoidMeleeChance / 10.0f); //Item Mod 'Avoidence' + if (evasion_bonus >= 10000) // some sort of auto avoid disc + return false; + // 172 Evasion aka SE_AvoidMeleeChance + evasion_bonus += defender->itembonuses.AvoidMeleeChanceEffect + defender->aabonuses.AvoidMeleeChanceEffect; // item bonus here isn't mod2 avoidance Mob *owner = nullptr; if (defender->IsPet()) owner = defender->GetOwner(); - else if ((defender->IsNPC() && defender->CastToNPC()->GetSwarmOwner())) + else if (defender->IsNPC() && defender->CastToNPC()->GetSwarmOwner()) owner = entity_list.GetMobID(defender->CastToNPC()->GetSwarmOwner()); - if (owner) - avoidanceBonus += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance; + if (owner) // 215 Pet Avoidance % aka SE_PetAvoidance + evasion_bonus += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance; - if(defender->IsNPC()) - avoidanceBonus += (defender->CastToNPC()->GetAvoidanceRating() / 10.0f); //Modifier from database + // Evasion is a percentage bonus according to AA descriptions + if (evasion_bonus) + avoidance = (avoidance * (100 + evasion_bonus)) / 100; - //Hit Chance Bonuses on attacker increases baseline hit chance by percent. - hitBonus += attacker->itembonuses.HitChanceEffect[skillinuse] + - attacker->spellbonuses.HitChanceEffect[skillinuse]+ - attacker->aabonuses.HitChanceEffect[skillinuse]+ - attacker->itembonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + - attacker->spellbonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + - attacker->aabonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1]; + if (chance_mod >= 10000) // override for stuff like SE_SkillAttack + return true; - //Accuracy = Spell Effect , HitChance = 'Accuracy' from Item Effect - //Only AA derived accuracy can be skill limited. ie (Precision of the Pathfinder, Dead Aim) - hitBonus += (attacker->itembonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + - attacker->spellbonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + + // calculate attacker's accuracy + auto accuracy = attacker->compute_tohit(skillinuse) + 10; // add 10 in case the NPC's stats are fucked + if (chance_mod > 0) // multiplier + accuracy *= chance_mod; + + // Torven parsed an apparent constant of 1.2 somewhere in here * 6 / 5 looks eqmathy to me! + accuracy = accuracy * 6 / 5; + + // unsure on the stacking order of these effects, rather hard to parse + // item mod2 accuracy isn't applied to range? Theory crafting and parses back it up I guess + // mod2 accuracy -- flat bonus + if (skillinuse != EQEmu::skills::SkillArchery && skillinuse != EQEmu::skills::SkillThrowing) + accuracy += attacker->itembonuses.HitChance; + + // 216 Melee Accuracy Amt aka SE_Accuracy -- flat bonus + accuracy += attacker->itembonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + attacker->aabonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->spellbonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->itembonuses.Accuracy[skillinuse] + attacker->aabonuses.Accuracy[skillinuse] + - attacker->itembonuses.HitChance) / 15.0f; //Item Mod 'Accuracy' + attacker->spellbonuses.Accuracy[skillinuse]; - hitBonus += chance_mod; //Modifier applied from casted/disc skill attacks. + // auto hit discs (and looks like there are some autohit AAs) + if (attacker->spellbonuses.HitChanceEffect[skillinuse] >= 10000 || attacker->aabonuses.HitChanceEffect[skillinuse] >= 10000) + return true; - if(attacker->IsNPC()) - hitBonus += (attacker->CastToNPC()->GetAccuracyRating() / 10.0f); //Modifier from database + if (attacker->spellbonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] >= 10000) + return true; - if (skillinuse == EQEmu::skills::SkillArchery) - hitBonus -= hitBonus*RuleR(Combat, ArcheryHitPenalty); + // 184 Accuracy % aka SE_HitChance -- percentage increase + auto hit_bonus = attacker->itembonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->aabonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->spellbonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + + attacker->itembonuses.HitChanceEffect[skillinuse] + + attacker->aabonuses.HitChanceEffect[skillinuse] + + attacker->spellbonuses.HitChanceEffect[skillinuse]; - //Calculate final chance to hit - chancetohit += ((chancetohit * (hitBonus - avoidanceBonus)) / 100.0f); - Log.Out(Logs::Detail, Logs::Attack, "Chance to hit %.2f after accuracy calc %.2f and avoidance calc %.2f", chancetohit, hitBonus, avoidanceBonus); + accuracy = (accuracy * (100 + hit_bonus)) / 100; - chancetohit = mod_hit_chance(chancetohit, skillinuse, attacker); + // TODO: April 2003 added an archery/throwing PVP accuracy penalty while moving, should be in here some where, + // but PVP is less important so I haven't tried parsing it at all - // Chance to hit; Max 95%, Min 5% DEFAULTS - if(chancetohit > 1000 || chancetohit < -1000) { - //if chance to hit is crazy high, that means a discipline is in use, and let it stay there - } - else if(chancetohit > RuleR(Combat,MaxChancetoHit)) { - chancetohit = RuleR(Combat,MaxChancetoHit); - } - else if(chancetohit < RuleR(Combat,MinChancetoHit)) { - chancetohit = RuleR(Combat,MinChancetoHit); - } + // There is also 110 Ranger Archery Accuracy % which should probably be in here some where, but it's not in any spells/aas + // Name implies it's a percentage increase, if one wishes to implement, do it like the hit_bonus above but limited to ranger archery - //I dont know the best way to handle a garunteed hit discipline being used - //agains a garunteed riposte (for example) discipline... for now, garunteed hit wins + // There is also 183 UNUSED - Skill Increase Chance which devs say isn't used at all in code, but some spells reference it + // I do not recommend implementing this once since there are spells that use it which would make this not live-like with default spell files + // so now we roll! + // relevant dev quote: + // Then your chance to simply avoid the attack is checked (defender's avoidance roll beat the attacker's accuracy roll.) + int tohit_roll = zone->random.Roll0(accuracy); + int avoid_roll = zone->random.Roll0(avoidance); + Log.Out(Logs::Detail, Logs::Attack, "CheckHitChance accuracy(%d => %d) avoidance(%d => %d)", accuracy, tohit_roll, avoidance, avoid_roll); - Log.Out(Logs::Detail, Logs::Attack, "3 FINAL calculated chance to hit is: %5.2f", chancetohit); - - - // - // Did we hit? - // - - float tohit_roll = zone->random.Real(0, 100); - - Log.Out(Logs::Detail, Logs::Attack, "Final hit chance: %.2f%%. Hit roll %.2f", chancetohit, tohit_roll); - - return(tohit_roll <= chancetohit); + // tie breaker? Don't want to be biased any one way + if (tohit_roll == avoid_roll) + return zone->random.Roll(50); + return tohit_roll > avoid_roll; } bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) @@ -1182,7 +1148,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b } Log.Out(Logs::Detail, Logs::Combat, "Avoided damage with code %d", damage); } else { - if (other->CheckHitChance(this, skillinuse, Hand, hit_chance_bonus)) { + if (other->CheckHitChance(this, skillinuse, hit_chance_bonus)) { other->MeleeMitigation(this, damage, min_hit, opts); if (damage > 0) CommonOutgoingHitSuccess(other, damage, skillinuse,opts); @@ -1742,7 +1708,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool if (!bRiposte && damage == -3) DoRiposte(other); } else { - if (other->CheckHitChance(this, skillinuse, Hand, hit_chance_bonus)) { + if (other->CheckHitChance(this, skillinuse, hit_chance_bonus)) { other->MeleeMitigation(this, damage, min_dmg+eleBane, opts); CommonOutgoingHitSuccess(other, damage, skillinuse, opts); } else { diff --git a/zone/bot.cpp b/zone/bot.cpp index 056a55289..7b0739b47 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2038,7 +2038,7 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: return; } } else { - if (other->CheckHitChance(this, skillinuse, Hand, chance_mod)) { + if (other->CheckHitChance(this, skillinuse, chance_mod)) { other->MeleeMitigation(this, damage, min_hit); if (damage > 0) { damage += damage*focus/100; @@ -3865,7 +3865,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b } } } else { - if (other->CheckHitChance(this, skillinuse, Hand)) { + if (other->CheckHitChance(this, skillinuse)) { other->MeleeMitigation(this, damage, min_hit, opts); ApplyMeleeDamageBonus(skillinuse, damage); damage += ((itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse)); @@ -4885,7 +4885,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 if (max_damage == -3) DoRiposte(who); } else { - if (HitChance || who->CheckHitChance(this, skill, EQEmu::inventory::slotPrimary)) { + if (HitChance || who->CheckHitChance(this, skill)) { who->MeleeMitigation(this, max_damage, min_damage); ApplyMeleeDamageBonus(skill, max_damage); max_damage += who->GetFcDamageAmtIncoming(this, 0, true, skill); diff --git a/zone/mob.h b/zone/mob.h index 9d874c33b..a581ea819 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -159,7 +159,9 @@ public: int MonkSpecialAttack(Mob* other, uint8 skill_used); virtual void TryBackstab(Mob *other,int ReuseTime = 10); bool AvoidDamage(Mob* attacker, int32 &damage, int hand); - virtual bool CheckHitChance(Mob* attacker, EQEmu::skills::SkillType skillinuse, int Hand, int16 chance_mod = 0); + int compute_tohit(EQEmu::skills::SkillType skillinuse); + int compute_defense(); + virtual bool CheckHitChance(Mob* attacker, EQEmu::skills::SkillType skillinuse, int chance_mod = 0); virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts = nullptr); void TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage); virtual bool TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 2f43d51c9..86eb01921 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -136,7 +136,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 if (max_damage == -3) DoRiposte(who); } else { - if (!CheckHitChance || (CheckHitChance && who->CheckHitChance(this, skill, EQEmu::inventory::slotPrimary))) { + if (!CheckHitChance || (CheckHitChance && who->CheckHitChance(this, skill))) { who->MeleeMitigation(this, max_damage, min_damage); CommonOutgoingHitSuccess(who, max_damage, skill); } else { @@ -855,7 +855,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon else if (AmmoItem) SendItemAnimation(other, AmmoItem, EQEmu::skills::SkillArchery); - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillArchery, EQEmu::inventory::slotPrimary, chance_mod))) { + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillArchery, chance_mod))) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ @@ -1265,7 +1265,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha if (!chance_mod) chance_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2); - if (!other->CheckHitChance(this, skillInUse, EQEmu::inventory::slotRange, chance_mod)) + if (!other->CheckHitChance(this, skillInUse, chance_mod)) { other->Damage(this, 0, SPELL_UNKNOWN, skillInUse); } @@ -1473,7 +1473,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon else if (AmmoItem) SendItemAnimation(other, AmmoItem, EQEmu::skills::SkillThrowing); - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillThrowing, EQEmu::inventory::slotPrimary, chance_mod))){ + if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillThrowing, chance_mod))){ Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); if (LaunchProjectile){ TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot, speed); @@ -2399,7 +2399,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: return; } } else { - if (other->CheckHitChance(this, skillinuse, Hand, chance_mod)) { + if (other->CheckHitChance(this, skillinuse, chance_mod)) { other->MeleeMitigation(this, damage, min_hit); CommonOutgoingHitSuccess(other, damage, skillinuse); } else { diff --git a/zone/zonedump.h b/zone/zonedump.h index 80888d31e..c6121fd48 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -111,8 +111,8 @@ struct NPCType uint8 mount_color; //only used by horse class float attack_speed; //%+- on attack delay of the mob. uint8 attack_delay; //delay between attacks in 10ths of a second - int accuracy_rating; //10 = 1% accuracy - int avoidance_rating; //10 = 1% avoidance + int accuracy_rating; // flat bonus before mods + int avoidance_rating; // flat bonus before mods bool findable; //can be found with find command bool trackable; int16 slow_mitigation; From 80ff535215fb92ccf542e48d5e24f52691717816 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Tue, 10 Jan 2017 20:15:03 -0500 Subject: [PATCH 484/693] Added code so that books/scrolls read that are in a language other than common get language skill applied. Added code to support ReadBook slots above and beyond main inventory slots by decoding additional bag slot field. --- .../git/required/2017_01_10_book_languages.sql | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 utils/sql/git/required/2017_01_10_book_languages.sql diff --git a/utils/sql/git/required/2017_01_10_book_languages.sql b/utils/sql/git/required/2017_01_10_book_languages.sql new file mode 100644 index 000000000..508cdc156 --- /dev/null +++ b/utils/sql/git/required/2017_01_10_book_languages.sql @@ -0,0 +1,15 @@ +alter table books add language int default 0; + +drop table reading_is_fundamental; + +create table reading_is_fundamental +( +filename varchar(32), +language int +); + +insert into reading_is_fundamental (select items.filename, items.booktype from items where items.filename != "" group by filename); + +update books set books.language = (select language from reading_is_fundamental r where r.filename = books.name); + +drop table reading_is_fundamental; From df86e644f445ef579bfdfa152ae98c4bc18e69d3 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Tue, 10 Jan 2017 20:18:16 -0500 Subject: [PATCH 485/693] Now the actual code changes - lol --- common/eq_packet_structs.h | 1 + common/patches/rof2.cpp | 1 + common/patches/rof2_structs.h | 3 ++- common/shareddb.cpp | 5 ++-- common/shareddb.h | 2 +- utils/sql/db_update_manifest.txt | 1 + zone/client.cpp | 40 +++++++++++++++++++++++++++----- 7 files changed, 43 insertions(+), 10 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 1d25e4d66..a3e26a9a4 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -2495,6 +2495,7 @@ struct BookRequest_Struct { uint8 window; // where to display the text (0xFF means new window) uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly others. uint32 invslot; // Only used in Sof and later clients; + int16 subslot; // The subslot inside of a bag if it is inside one. char txtfile[20]; }; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index d56791bef..8f8d41281 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -5154,6 +5154,7 @@ namespace RoF2 IN(type); IN(invslot); + IN(subslot); emu->window = (uint8)eq->window; strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 850df8ddf..1ed1b9916 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -2826,7 +2826,8 @@ struct BookText_Struct { struct BookRequest_Struct { /*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window). /*0004*/ uint16 invslot; // Is the slot, but the RoF2 conversion causes it to fail. Turned to 0 since it isnt required anyway. -/*0008*/ uint32 unknown006; // Seen FFFFFFFF +/*0006*/ int16 subslot; // Inventory sub-slot (0-x) +/*0008*/ uint16 unknown006; // Seen FFFF /*0010*/ uint16 unknown008; // seen 0000 /*0012*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others /*0016*/ uint32 unknown0012; diff --git a/common/shareddb.cpp b/common/shareddb.cpp index fc628ea6f..a4d0e6235 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1136,13 +1136,13 @@ const EQEmu::ItemData* SharedDatabase::IterateItems(uint32* id) { return nullptr; } -std::string SharedDatabase::GetBook(const char *txtfile) +std::string SharedDatabase::GetBook(const char *txtfile, int16 *language) { char txtfile2[20]; std::string txtout; strcpy(txtfile2, txtfile); - std::string query = StringFormat("SELECT txtfile FROM books WHERE name = '%s'", txtfile2); + std::string query = StringFormat("SELECT txtfile, language FROM books WHERE name = '%s'", txtfile2); auto results = QueryDatabase(query); if (!results.Success()) { txtout.assign(" ",1); @@ -1157,6 +1157,7 @@ std::string SharedDatabase::GetBook(const char *txtfile) auto row = results.begin(); txtout.assign(row[0],strlen(row[0])); + *language = static_cast(atoi(row[1])); return txtout; } diff --git a/common/shareddb.h b/common/shareddb.h index b58d1f138..d3d8020a1 100644 --- a/common/shareddb.h +++ b/common/shareddb.h @@ -94,7 +94,7 @@ class SharedDatabase : public Database bool SetStartingItems(PlayerProfile_Struct* pp, EQEmu::InventoryProfile* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin); - std::string GetBook(const char *txtfile); + std::string GetBook(const char *txtfile, int16 *language); /* Item Methods diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index aa72310ce..816a35a7c 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -355,6 +355,7 @@ 9099|2016_08_27_ip_exemptions.sql|SHOW TABLES LIKE 'ip_exemptions'|empty| 9100|2016_08_27_object_display_name.sql|SHOW COLUMNS FROM `object` LIKE 'display_name'|empty| 9101|2016_12_01_pcnpc_only.sql|SHOW COLUMNS FROM `spells_new` LIKE 'pcnpc_only_flag'|empty| +9102|2017_01_10_book_languages.sql|SHOW COLUMNS FROM `books` LIKE 'language'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/zone/client.cpp b/zone/client.cpp index ddf10d9d5..6b6de32c1 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -33,6 +33,7 @@ extern volatile bool RunLoops; #include "../common/eqemu_logsys.h" #include "../common/features.h" +#include "../common/emu_legacy.h" #include "../common/spdat.h" #include "../common/guilds.h" #include "../common/rulesys.h" @@ -1998,6 +1999,7 @@ void Client::SetGM(bool toggle) { } void Client::ReadBook(BookRequest_Struct *book) { + int16 book_language=0; char *txtfile = book->txtfile; if(txtfile[0] == '0' && txtfile[1] == '\0') { @@ -2005,7 +2007,7 @@ void Client::ReadBook(BookRequest_Struct *book) { return; } - std::string booktxt2 = database.GetBook(txtfile); + std::string booktxt2 = database.GetBook(txtfile, &book_language); int length = booktxt2.length(); if (booktxt2[0] != '\0') { @@ -2016,21 +2018,47 @@ void Client::ReadBook(BookRequest_Struct *book) { BookText_Struct *out = (BookText_Struct *) outapp->pBuffer; out->window = book->window; - if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) - { - const EQEmu::ItemInstance *inst = m_inv[book->invslot]; + + + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { + // Find out what slot the book was read from. + // SoF+ need to look up book type for the output message. + int16 read_from_slot; + + if (book->subslot >= 0) { + uint16 offset; + offset = (book->invslot-23) * 10; // How many packs to skip. + read_from_slot = 251 + offset + book->subslot; + } + else { + read_from_slot = book->invslot -1; + } + + const EQEmu::ItemInstance *inst = 0; + + if (read_from_slot <= EQEmu::legacy::SLOT_PERSONAL_BAGS_END) + { + inst = m_inv[read_from_slot]; + } + if(inst) out->type = inst->GetItem()->Book; else out->type = book->type; } - else - { + else { out->type = book->type; } out->invslot = book->invslot; + memcpy(out->booktext, booktxt2.c_str(), length); + if (book_language > 0 && book_language < MAX_PP_LANGUAGE) { + if (m_pp.languages[book_language] < 100) { + GarbleMessage(out->booktext, (100 - m_pp.languages[book_language])); + } + } + QueuePacket(outapp); safe_delete(outapp); } From af4a432745bdbd893349d30a1e3c6517cf82d492 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Tue, 10 Jan 2017 20:33:01 -0500 Subject: [PATCH 486/693] Missed version.h in original commit --- common/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/version.h b/common/version.h index 93dfba189..2d5f1d75f 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9101 +#define CURRENT_BINARY_DATABASE_VERSION 9102 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 #else From 0a4ccb11aa7cb4cf430bc5a1e94564c5f13b4167 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 12 Jan 2017 17:55:08 -0500 Subject: [PATCH 487/693] Update travis-ci to use newer VM --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 74e5701ae..8083c7772 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: cpp compiler: gcc +dist: trusty sudo: false addons: apt: @@ -21,4 +22,4 @@ notifications: email: false irc: channels: "irc.eqemulator.net#eqemucoders" -os: linux \ No newline at end of file +os: linux From 50a67c76e7eb63d6009785b76e40f8b4be0d7aab Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 12 Jan 2017 18:06:13 -0500 Subject: [PATCH 488/693] Try newer GCC versions? --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8083c7772..392c509ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,11 @@ dist: trusty sudo: false addons: apt: + sources: + - ubuntu-toolchain-r-test packages: + - gcc-5 + - g++-5 - libmysqlclient-dev - libperl-dev - libboost-dev From da08a622f153326b52161daab1a7e7bfcefa212a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 12 Jan 2017 18:10:45 -0500 Subject: [PATCH 489/693] Gotta update env vars too I guess --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 392c509ca..7d6688b99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ addons: - libboost-dev - liblua5.1-0-dev - zlib1g-dev +env: COMPILER=g++-5 script: - cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON - make -j8 From 6cef5c6beb99514bc774f038687b06c7ae856416 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 12 Jan 2017 18:19:04 -0500 Subject: [PATCH 490/693] Gotta set them actually --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7d6688b99..40ea4f915 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,8 @@ addons: - libboost-dev - liblua5.1-0-dev - zlib1g-dev -env: COMPILER=g++-5 script: - - cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON + - CC=gcc-5 CXX=g++-5 cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON - make -j8 - ./bin/tests branches: From e3f15de1f869cdfb9eaf7c7ff3d6597acbe0a506 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 12 Jan 2017 18:25:06 -0500 Subject: [PATCH 491/693] Revert "Gotta set them actually" This reverts commit 6cef5c6beb99514bc774f038687b06c7ae856416. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 40ea4f915..7d6688b99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,9 @@ addons: - libboost-dev - liblua5.1-0-dev - zlib1g-dev +env: COMPILER=g++-5 script: - - CC=gcc-5 CXX=g++-5 cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON + - cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON - make -j8 - ./bin/tests branches: From ffdc933ce01d320487aee24655f0b3107bdf82c7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 12 Jan 2017 18:25:16 -0500 Subject: [PATCH 492/693] Revert "Gotta update env vars too I guess" This reverts commit da08a622f153326b52161daab1a7e7bfcefa212a. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7d6688b99..392c509ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,6 @@ addons: - libboost-dev - liblua5.1-0-dev - zlib1g-dev -env: COMPILER=g++-5 script: - cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON - make -j8 From a4fda2a951591779a7c8eb5a71c733ecaf12a843 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 12 Jan 2017 18:25:25 -0500 Subject: [PATCH 493/693] Revert "Try newer GCC versions?" This reverts commit 50a67c76e7eb63d6009785b76e40f8b4be0d7aab. --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 392c509ca..8083c7772 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,11 +4,7 @@ dist: trusty sudo: false addons: apt: - sources: - - ubuntu-toolchain-r-test packages: - - gcc-5 - - g++-5 - libmysqlclient-dev - libperl-dev - libboost-dev From 891fa0411c437b3fa3f3e1404d4c293e4ee68ea8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 12 Jan 2017 18:25:32 -0500 Subject: [PATCH 494/693] Revert "Update travis-ci to use newer VM" This reverts commit 0a4ccb11aa7cb4cf430bc5a1e94564c5f13b4167. --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8083c7772..74e5701ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: cpp compiler: gcc -dist: trusty sudo: false addons: apt: @@ -22,4 +21,4 @@ notifications: email: false irc: channels: "irc.eqemulator.net#eqemucoders" -os: linux +os: linux \ No newline at end of file From 9e824876ba5dac262b121c0e60d022bb2ecc45bd Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 15 Jan 2017 00:03:02 -0500 Subject: [PATCH 495/693] Combat Revamp - MAJOR BREAKING CHANGE This commit makes combat much more live like. This is based on a lot of parses done by TAKP and myself. There are numerous things based on dev quotes and hints. Pretty much all combat has changed, spell effects correct, stacking correct, etc. This is the fist stage of the revamp, I will be trying to remove some code duplication and make things generally cleaner. Server ops will have to rebalance their NPCs. AC actually means something now. Rough recommendations? Level 50 "classic" trash should be no more than 115. Classic raid mobs should be more 200+ etc Other "classic" NPCs should be a lot lower as well. PoP trash probably shouldn't exceed 120 AC PoP raids should be higher Devs have said the vast majority of NPCs didn't exceed 600 AC until very recently. The exceptions were mostly raid encounters. There really isn't a good "default" for every server, so this will be up to the devs to find where they want their server stats to be. --- common/skills.cpp | 24 + common/skills.h | 1 + zone/attack.cpp | 1437 ++++++++++++++++++++++++-------------- zone/beacon.h | 4 +- zone/bonuses.cpp | 8 +- zone/bot.cpp | 451 ++++-------- zone/bot.h | 10 +- zone/client.cpp | 6 +- zone/client.h | 11 +- zone/client_mods.cpp | 105 --- zone/common.h | 6 + zone/corpse.h | 4 +- zone/encounter.h | 4 +- zone/hate_list.cpp | 2 +- zone/merc.cpp | 21 +- zone/merc.h | 5 +- zone/mob.cpp | 6 +- zone/mob.h | 76 +- zone/mob_ai.cpp | 31 +- zone/npc.cpp | 23 +- zone/npc.h | 10 +- zone/special_attacks.cpp | 777 ++++++++------------- zone/tune.cpp | 8 +- zone/zonedb.cpp | 2 +- zone/zonedump.h | 2 +- 25 files changed, 1520 insertions(+), 1514 deletions(-) diff --git a/common/skills.cpp b/common/skills.cpp index a23d77a7b..6cb063e2e 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -124,6 +124,30 @@ bool EQEmu::skills::IsCastingSkill(SkillType skill) } } +int32 EQEmu::skills::GetBaseDamage(SkillType skill) +{ + switch (skill) { + case SkillBash: + return 2; + case SkillDragonPunch: + return 12; + case SkillEagleStrike: + return 7; + case SkillFlyingKick: + return 25; + case SkillKick: + return 3; + case SkillRoundKick: + return 5; + case SkillTigerClaw: + return 4; + case SkillFrenzy: + return 10; + default: + return 0; + } +} + const std::map& EQEmu::skills::GetSkillTypeMap() { /* VS2013 code diff --git a/common/skills.h b/common/skills.h index 19a996729..572b8c59f 100644 --- a/common/skills.h +++ b/common/skills.h @@ -166,6 +166,7 @@ namespace EQEmu float GetSkillMeleePushForce(SkillType skill); bool IsBardInstrumentSkill(SkillType skill); bool IsCastingSkill(SkillType skill); + int32 GetBaseDamage(SkillType skill); extern const std::map& GetSkillTypeMap(); diff --git a/zone/attack.cpp b/zone/attack.cpp index 47b7bcb66..219ee231e 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -189,6 +189,9 @@ bool Mob::CheckHitChance(Mob* other, EQEmu::skills::SkillType skillinuse, int ch Mob *defender = this; Log.Out(Logs::Detail, Logs::Attack, "CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName()); + if (defender->IsClient() && defender->CastToClient()->IsSitting()) + return true; + // calculate defender's avoidance auto avoidance = defender->compute_defense() + 10; // add 10 in case the NPC's stats are fucked auto evasion_bonus = defender->spellbonuses.AvoidMeleeChanceEffect; // we check this first since it has a special case @@ -276,7 +279,7 @@ bool Mob::CheckHitChance(Mob* other, EQEmu::skills::SkillType skillinuse, int ch return tohit_roll > avoid_roll; } -bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) +bool Mob::AvoidDamage(Mob *other, int &damage, int hand) { /* called when a mob is attacked, does the checks to see if it's a hit * and does other mitigation checks. 'this' is the mob being attacked. @@ -479,274 +482,403 @@ bool Mob::AvoidDamage(Mob *other, int32 &damage, int hand) return false; } -void Mob::MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts) +int Mob::GetACSoftcap() { - if (damage <= 0) + // from test server Resources/ACMitigation.txt + static int war_softcaps[] = { + 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, + 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, + 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, + 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, + 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520 + }; + + static int clrbrdmnk_softcaps[] = { + 274, 276, 278, 278, 280, 282, 284, 286, 288, 290, 292, 292, 294, 296, 298, 300, 302, 304, 306, 308, 308, + 310, 312, 314, 316, 318, 320, 322, 322, 324, 326, 328, 330, 332, 334, 336, 336, 338, 340, 342, 344, 346, + 348, 350, 352, 352, 354, 356, 358, 360, 362, 364, 366, 366, 368, 370, 372, 374, 376, 378, 380, 380, 382, + 384, 386, 388, 390, 392, 394, 396, 396, 398, 400, 402, 404, 406, 408, 410, 410, 412, 414, 416, 418, 420, + 422, 424, 424, 426, 428, 430, 432, 434, 436, 438, 440, 440, 442, 444, 446, 448, 450, 452, 454, 454, 456 + }; + + static int palshd_softcaps[] = { + 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 336, + 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, + 380, 382, 384, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, + 420, 422, 424, 426, 428, 430, 432, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, + 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498 + }; + + static int rng_softcaps[] = { + 286, 288, 290, 292, 294, 296, 298, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 322, + 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, + 364, 366, 368, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 390, 392, 394, 396, 398, 400, + 402, 404, 406, 408, 410, 412, 414, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 436, 438, + 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478 + }; + + static int dru_softcaps[] = { + 254, 256, 258, 260, 262, 264, 264, 266, 268, 270, 272, 272, 274, 276, 278, 280, 282, 282, 284, 286, 288, + 290, 290, 292, 294, 296, 298, 300, 300, 302, 304, 306, 308, 308, 310, 312, 314, 316, 318, 318, 320, 322, + 324, 326, 328, 328, 330, 332, 334, 336, 336, 338, 340, 342, 344, 346, 346, 348, 350, 352, 354, 354, 356, + 358, 360, 362, 364, 364, 366, 368, 370, 372, 372, 374, 376, 378, 380, 382, 382, 384, 386, 388, 390, 390, + 392, 394, 396, 398, 400, 400, 402, 404, 406, 408, 410, 410, 412, 414, 416, 418, 418, 420, 422, 424, 426 + }; + + static int rogshmbstber_softcaps[] = { + 264, 266, 268, 270, 272, 272, 274, 276, 278, 280, 282, 282, 284, 286, 288, 290, 292, 294, 294, 296, 298, + 300, 302, 304, 306, 306, 308, 310, 312, 314, 316, 316, 318, 320, 322, 324, 326, 328, 328, 330, 332, 334, + 336, 338, 340, 340, 342, 344, 346, 348, 350, 350, 352, 354, 356, 358, 360, 362, 362, 364, 366, 368, 370, + 372, 374, 374, 376, 378, 380, 382, 384, 384, 386, 388, 390, 392, 394, 396, 396, 398, 400, 402, 404, 406, + 408, 408, 410, 412, 414, 416, 418, 418, 420, 422, 424, 426, 428, 430, 430, 432, 434, 436, 438, 440, 442 + }; + + static int necwizmagenc_softcaps[] = { + 248, 250, 252, 254, 256, 256, 258, 260, 262, 264, 264, 266, 268, 270, 272, 272, 274, 276, 278, 280, 280, + 282, 284, 286, 288, 288, 290, 292, 294, 296, 296, 298, 300, 302, 304, 304, 306, 308, 310, 312, 312, 314, + 316, 318, 320, 320, 322, 324, 326, 328, 328, 330, 332, 334, 336, 336, 338, 340, 342, 344, 344, 346, 348, + 350, 352, 352, 354, 356, 358, 360, 360, 362, 364, 366, 368, 368, 370, 372, 374, 376, 376, 378, 380, 382, + 384, 384, 386, 388, 390, 392, 392, 394, 396, 398, 400, 400, 402, 404, 406, 408, 408, 410, 412, 414, 416 + }; + + int level = std::min(105, static_cast(GetLevel())) - 1; + + switch (GetClass()) { + case WARRIOR: + return war_softcaps[level]; + case CLERIC: + case BARD: + case MONK: + return clrbrdmnk_softcaps[level]; + case PALADIN: + case SHADOWKNIGHT: + return palshd_softcaps[level]; + case RANGER: + return rng_softcaps[level]; + case DRUID: + return dru_softcaps[level]; + case ROGUE: + case SHAMAN: + case BEASTLORD: + case BERSERKER: + return rogshmbstber_softcaps[level]; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return necwizmagenc_softcaps[level]; + default: + return 350; + } +} + +double Mob::GetSoftcapReturns() +{ + // These are based on the dev post, they seem to be correct for every level + // AKA no more hard caps + switch (GetClass()) { + case WARRIOR: + return 0.35; + case CLERIC: + case BARD: + case MONK: + return 0.3; + case PALADIN: + case SHADOWKNIGHT: + return 0.33; + case RANGER: + return 0.315; + case DRUID: + return 0.265; + case ROGUE: + case SHAMAN: + case BEASTLORD: + case BERSERKER: + return 0.28; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return 0.25; + default: + return 0.3; + } +} + +int Mob::GetClassRaceACBonus() +{ + int ac_bonus = 0; + auto level = GetLevel(); + if (GetClass() == MONK) { + int hardcap = 30; + int softcap = 14; + if (level > 99) { + hardcap = 58; + softcap = 35; + } else if (level > 94) { + hardcap = 57; + softcap = 34; + } else if (level > 89) { + hardcap = 56; + softcap = 33; + } else if (level > 84) { + hardcap = 55; + softcap = 32; + } else if (level > 79) { + hardcap = 54; + softcap = 31; + } else if (level > 74) { + hardcap = 53; + softcap = 30; + } else if (level > 69) { + hardcap = 53; + softcap = 28; + } else if (level > 64) { + hardcap = 53; + softcap = 26; + } else if (level > 63) { + hardcap = 50; + softcap = 24; + } else if (level > 61) { + hardcap = 47; + softcap = 24; + } else if (level > 59) { + hardcap = 45; + softcap = 24; + } else if (level > 54) { + hardcap = 40; + softcap = 20; + } else if (level > 50) { + hardcap = 38; + softcap = 18; + } else if (level > 44) { + hardcap = 36; + softcap = 17; + } else if (level > 29) { + hardcap = 34; + softcap = 16; + } else if (level > 14) { + hardcap = 32; + softcap = 15; + } + int weight = IsClient() ? CastToClient()->CalcCurrentWeight() : 0; + if (weight < hardcap - 1) { + int temp = level + 5; + if (weight > softcap) { + double redux = (weight - softcap) * 6.66667; + redux = (100.0 - std::min(100.0, redux)) * 0.01; + temp = std::max(0, static_cast(temp * redux)); + } + ac_bonus = (4 * temp) / 3; + } else if (weight > hardcap + 1) { + int temp = level + 5; + double multiplier = std::min(1.0, (weight - (hardcap - 10.0)) / 100.0); + temp = (4 * temp) / 3; + ac_bonus -= static_cast(temp * multiplier); + } + } + + if (GetClass() == ROGUE) { + int level_scaler = level - 26; + if (GetAGI() < 80) + ac_bonus = level_scaler / 4; + else if (GetAGI() < 85) + ac_bonus = (level_scaler * 2) / 4; + else if (GetAGI() < 90) + ac_bonus = (level_scaler * 3) / 4; + else if (GetAGI() < 100) + ac_bonus = (level_scaler * 4) / 4; + else if (GetAGI() >= 100) + ac_bonus = (level_scaler * 5) / 4; + if (ac_bonus > 12) + ac_bonus = 12; + } + + if (GetClass() == BEASTLORD) { + int level_scaler = level - 6; + if (GetAGI() < 80) + ac_bonus = level_scaler / 5; + else if (GetAGI() < 85) + ac_bonus = (level_scaler * 2) / 5; + else if (GetAGI() < 90) + ac_bonus = (level_scaler * 3) / 5; + else if (GetAGI() < 100) + ac_bonus = (level_scaler * 4) / 5; + else if (GetAGI() >= 100) + ac_bonus = (level_scaler * 5) / 5; + if (ac_bonus > 16) + ac_bonus = 16; + } + + if (GetRace() == IKSAR) + ac_bonus += EQEmu::Clamp(static_cast(level), 10, 35); + + return ac_bonus; +} + +int Mob::ACSum() +{ + int ac = 0; // this should be base AC whenever shrouds come around + ac += itembonuses.AC; // items + food + tribute + int shield_ac = 0; + if (HasShieldEquiped() && IsClient()) { + auto client = CastToClient(); + auto inst = client->GetInv().GetItem(EQEmu::inventory::slotSecondary); + if (inst) { + if (inst->GetItemRecommendedLevel(true) <= GetLevel()) + shield_ac = inst->GetItemArmorClass(true); + else + shield_ac = client->CalcRecommendedLevelBonus(GetLevel(), inst->GetItemRecommendedLevel(true), inst->GetItemArmorClass(true)); + } + shield_ac += client->GetHeroicSTR() / 10; + } + // EQ math + ac = (ac * 4) / 3; + // anti-twink + if (GetLevel() < 50) + ac = std::min(ac, 25 + 6 * GetLevel()); + ac = std::max(0, ac + GetClassRaceACBonus()); + if (IsNPC()) { + // This is the developer tweaked number + // for the VAST amount of NPCs in EQ this number didn't exceed 600 until recently (PoWar) + // According to the guild hall Combat Dummies, a level 50 classic EQ mob it should be ~115 + // For a 60 PoP mob ~120, 70 OoW ~120 + ac += GetAC(); + Mob *owner = nullptr; + if (IsPet()) + owner = GetOwner(); + else if (CastToNPC()->GetSwarmOwner()) + owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); + if (owner) + ac += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance; + } + auto spell_aa_ac = aabonuses.AC + spellbonuses.AC; + if (EQEmu::ValueWithin(static_cast(GetClass()), NECROMANCER, ENCHANTER)) + ac += GetSkill(EQEmu::skills::SkillDefense) / 2 + spell_aa_ac / 3; + else + ac += GetSkill(EQEmu::skills::SkillDefense) / 3 + spell_aa_ac / 4; + + if (GetAGI() > 70) + ac += GetAGI() / 20; + if (ac < 0) + ac = 0; + + if (IsClient() +#ifdef BOTS + || IsBot() +#endif + ) { + auto softcap = GetACSoftcap(); + auto returns = GetSoftcapReturns(); + int total_aclimitmod = aabonuses.CombatStability + itembonuses.CombatStability + spellbonuses.CombatStability; + if (total_aclimitmod) + softcap = (softcap * (100 + total_aclimitmod)) / 100; + softcap += shield_ac; + if (ac > softcap) { + auto over_cap = ac - softcap; + ac = softcap + (over_cap * returns); + } + Log.Out(Logs::Detail, Logs::Combat, "ACSum ac %d softcap %d returns %f", ac, softcap, returns); + } else { + Log.Out(Logs::Detail, Logs::Combat, "ACSum ac %d", ac); + } + return ac; +} + +int Mob::offense(EQEmu::skills::SkillType skill) +{ + int offense = GetSkill(skill); + int stat_bonus = 0; + if (skill == EQEmu::skills::SkillArchery || skill == EQEmu::skills::SkillThrowing) + stat_bonus = GetDEX(); + else + stat_bonus = GetSTR(); + if (stat_bonus >= 75) + offense += (2 * stat_bonus - 150) / 3; + offense += GetATK(); + return offense; +} + +// this assumes "this" is the defender +// this returns between 0.1 to 2.0 +double Mob::RollD20(double offense, double mitigation) +{ + if (IsClient() && CastToClient()->IsSitting()) + return 2.0; + + // this works pretty good. From Torven's implementation for TAKP + mitigation -= (mitigation - offense) / 2.0; + double diff = offense - mitigation; + double mean = 0; + double mult1, mult2; + + if (offense > 30.0) { + mult1 = offense / 200.0 + 25.75; + if (mitigation / offense < 0.35) + mult1 = mult1 + 1.0; + else if (mitigation / offense > 0.65) + mult1 = mult1 - 1.0; + mult2 = offense / 140 + 18.5; + } else { + mult1 = 11.5 + offense / 2.0; + mult2 = 14.0 + offense / 6.0; + } + + // changing the mean shifts the bell curve + // this was mostly determined by trial and error to find what fit best + if (offense > mitigation) + mean = diff / offense * mult1; + else if (mitigation > offense) + mean = diff / mitigation * mult2; + + double stddev = 8.8; // standard deviation adjusts the height of the bell + // again, trial and error to find what fit best + double theta = 2 * M_PI * zone->random.Real(0.0, 1.0); + double rho = std::sqrt(-2 * std::log(1 - zone->random.Real(0.0, 1.0))); + double d = mean + stddev * rho * std::cos(theta); + + // this combined with the stddev will produce ~15% DI1 and ~15% DI20 when mitigation == offens + d = EQEmu::Clamp(d, -9.5, 9.5); + d += 11.0; + int roll = static_cast(d); + + // the client has an array called damage_factor that is set to this value, so probably what they do + return roll * 0.1; +} + +void Mob::MeleeMitigation(Mob *attacker, int &damage, int base_damage, int offense, EQEmu::skills::SkillType skill, ExtraAttackOptions *opts) +{ + if (damage < 0 || base_damage == 0) return; Mob* defender = this; - float aa_mit = (aabonuses.CombatStability + itembonuses.CombatStability + - spellbonuses.CombatStability) / 100.0f; + auto mitigation = defender->GetMitigationAC(); + if (IsClient() && attacker->IsClient()) + mitigation = mitigation * 80 / 100; // 2004 PvP changes - if (RuleB(Combat, UseIntervalAC)) { - float softcap = (GetSkill(EQEmu::skills::SkillDefense) + GetLevel()) * - RuleR(Combat, SoftcapFactor) * (1.0 + aa_mit); - float mitigation_rating = 0.0; - float attack_rating = 0.0; - int shield_ac = 0; - int armor = 0; - float weight = 0.0; - - float monkweight = RuleI(Combat, MonkACBonusWeight); - monkweight = mod_monk_weight(monkweight, attacker); - - if (IsClient()) { - armor = CastToClient()->GetRawACNoShield(shield_ac); - weight = (CastToClient()->CalcCurrentWeight() / 10.0); - } else if (IsNPC()) { - armor = CastToNPC()->GetRawAC(); - int PetACBonus = 0; - - if (!IsPet()) - armor = (armor / RuleR(Combat, NPCACFactor)); - - Mob *owner = nullptr; - if (IsPet()) - owner = GetOwner(); - else if ((CastToNPC()->GetSwarmOwner())) - owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); - - if (owner) - PetACBonus = owner->aabonuses.PetMeleeMitigation + owner->itembonuses.PetMeleeMitigation + owner->spellbonuses.PetMeleeMitigation; - - armor += spellbonuses.AC + itembonuses.AC + PetACBonus + 1; - } - - if (opts) { - armor *= (1.0f - opts->armor_pen_percent); - armor -= opts->armor_pen_flat; - } - - if (RuleB(Combat, OldACSoftcapRules)) { - if (GetClass() == WIZARD || GetClass() == MAGICIAN || - GetClass() == NECROMANCER || GetClass() == ENCHANTER) - softcap = RuleI(Combat, ClothACSoftcap); - else if (GetClass() == MONK && weight <= monkweight) - softcap = RuleI(Combat, MonkACSoftcap); - else if(GetClass() == DRUID || GetClass() == BEASTLORD || GetClass() == MONK) - softcap = RuleI(Combat, LeatherACSoftcap); - else if(GetClass() == SHAMAN || GetClass() == ROGUE || - GetClass() == BERSERKER || GetClass() == RANGER) - softcap = RuleI(Combat, ChainACSoftcap); - else - softcap = RuleI(Combat, PlateACSoftcap); - } - - softcap += shield_ac; - armor += shield_ac; - if (RuleB(Combat, OldACSoftcapRules)) - softcap += (softcap * (aa_mit * RuleR(Combat, AAMitigationACFactor))); - if (armor > softcap) { - int softcap_armor = armor - softcap; - if (RuleB(Combat, OldACSoftcapRules)) { - if (GetClass() == WARRIOR) - softcap_armor = softcap_armor * RuleR(Combat, WarriorACSoftcapReturn); - else if (GetClass() == SHADOWKNIGHT || GetClass() == PALADIN || - (GetClass() == MONK && weight <= monkweight)) - softcap_armor = softcap_armor * RuleR(Combat, KnightACSoftcapReturn); - else if (GetClass() == CLERIC || GetClass() == BARD || - GetClass() == BERSERKER || GetClass() == ROGUE || - GetClass() == SHAMAN || GetClass() == MONK) - softcap_armor = softcap_armor * RuleR(Combat, LowPlateChainACSoftcapReturn); - else if (GetClass() == RANGER || GetClass() == BEASTLORD) - softcap_armor = softcap_armor * RuleR(Combat, LowChainLeatherACSoftcapReturn); - else if (GetClass() == WIZARD || GetClass() == MAGICIAN || - GetClass() == NECROMANCER || GetClass() == ENCHANTER || - GetClass() == DRUID) - softcap_armor = softcap_armor * RuleR(Combat, CasterACSoftcapReturn); - else - softcap_armor = softcap_armor * RuleR(Combat, MiscACSoftcapReturn); - } else { - if (GetClass() == WARRIOR) - softcap_armor *= RuleR(Combat, WarACSoftcapReturn); - else if (GetClass() == PALADIN || GetClass() == SHADOWKNIGHT) - softcap_armor *= RuleR(Combat, PalShdACSoftcapReturn); - else if (GetClass() == CLERIC || GetClass() == RANGER || - GetClass() == MONK || GetClass() == BARD) - softcap_armor *= RuleR(Combat, ClrRngMnkBrdACSoftcapReturn); - else if (GetClass() == DRUID || GetClass() == NECROMANCER || - GetClass() == WIZARD || GetClass() == ENCHANTER || - GetClass() == MAGICIAN) - softcap_armor *= RuleR(Combat, DruNecWizEncMagACSoftcapReturn); - else if (GetClass() == ROGUE || GetClass() == SHAMAN || - GetClass() == BEASTLORD || GetClass() == BERSERKER) - softcap_armor *= RuleR(Combat, RogShmBstBerACSoftcapReturn); - else - softcap_armor *= RuleR(Combat, MiscACSoftcapReturn); - } - armor = softcap + softcap_armor; - } - - if (GetClass() == WIZARD || GetClass() == MAGICIAN || - GetClass() == NECROMANCER || GetClass() == ENCHANTER) - mitigation_rating = ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 4.0) + armor + 1; - else - mitigation_rating = ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 3.0) + (armor * 1.333333) + 1; - mitigation_rating *= 0.847; - - mitigation_rating = mod_mitigation_rating(mitigation_rating, attacker); - - if (attacker->IsClient()) - attack_rating = (attacker->CastToClient()->CalcATK() + ((attacker->GetSTR() - 66) * 0.9) + (attacker->GetSkill(EQEmu::skills::SkillOffense)*1.345)); - else - attack_rating = (attacker->GetATK() + (attacker->GetSkill(EQEmu::skills::SkillOffense)*1.345) + ((attacker->GetSTR() - 66) * 0.9)); - - attack_rating = attacker->mod_attack_rating(attack_rating, this); - - damage = GetMeleeMitDmg(attacker, damage, minhit, mitigation_rating, attack_rating); - } else { - //////////////////////////////////////////////////////// - // Scorpious2k: Include AC in the calculation - // use serverop variables to set values - int32 myac = GetAC(); - if(opts) { - myac *= (1.0f - opts->armor_pen_percent); - myac -= opts->armor_pen_flat; - } - - if (damage > 0 && myac > 0) { - int acfail=1000; - std::string tmp; - - if (database.GetVariable("ACfail", tmp)) { - acfail = (int) (atof(tmp.c_str()) * 100); - if (acfail>100) acfail=100; - } - - if (acfail<=0 || zone->random.Int(0, 100)>acfail) { - float acreduction=1; - int acrandom=300; - if (database.GetVariable("ACreduction", tmp)) - { - acreduction=atof(tmp.c_str()); - if (acreduction>100) acreduction=100; - } - - if (database.GetVariable("ACrandom", tmp)) - { - acrandom = (int) ((atof(tmp.c_str())+1) * 100); - if (acrandom>10100) acrandom=10100; - } - - if (acreduction>0) { - damage -= (int32) (GetAC() * acreduction/100.0f); - } - if (acrandom>0) { - damage -= (myac * zone->random.Int(0, acrandom) / 10000); - } - if (damage<1) damage=1; - Log.Out(Logs::Detail, Logs::Combat, "AC Damage Reduction: fail chance %d%%. Failed. Reduction %.3f%%, random %d. Resulting damage %d.", acfail, acreduction, acrandom, damage); - } else { - Log.Out(Logs::Detail, Logs::Combat, "AC Damage Reduction: fail chance %d%%. Did not fail.", acfail); - } - } - - damage -= (aa_mit * damage); - - if(damage != 0 && damage < minhit) - damage = minhit; - //reduce the damage from shielding item and aa based on the min dmg - //spells offer pure mitigation - damage -= (minhit * defender->itembonuses.MeleeMitigation / 100); - damage -= (damage * (defender->spellbonuses.MeleeMitigationEffect + defender->itembonuses.MeleeMitigationEffect + defender->aabonuses.MeleeMitigationEffect) / 100); + if (opts) { + mitigation *= (1.0f - opts->armor_pen_percent); + mitigation -= opts->armor_pen_flat; } + auto roll = RollD20(offense, mitigation); + + // 168 Defensive -- TODO: I think this is suppose to happen after damage table + // It happening after damage table also means it acts more like negative 185, which might explain + // why the spell has a negative value :P + auto meleemitspell = spellbonuses.MeleeMitigationEffect + itembonuses.MeleeMitigationEffect + aabonuses.MeleeMitigationEffect; + if (GetClass() == WARRIOR && IsClient()) + meleemitspell += 5; + + // +0.5 for rounding + damage = static_cast(roll * static_cast(base_damage) + 0.5); + + if (meleemitspell) + damage = (damage * (100 - meleemitspell)) / 100; + if (damage < 0) damage = 0; -} - -// This is called when the Mob is the one being hit -int32 Mob::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, - float mit_rating, float atk_rating) -{ - float d = 10.0; - float mit_roll = zone->random.Real(0, mit_rating); - float atk_roll = zone->random.Real(0, atk_rating); - - if (atk_roll > mit_roll) { - float a_diff = atk_roll - mit_roll; - float thac0 = atk_rating * RuleR(Combat, ACthac0Factor); - float thac0cap = attacker->GetLevel() * 9 + 20; - if (thac0 > thac0cap) - thac0 = thac0cap; - - d -= 10.0 * (a_diff / thac0); - } else if (mit_roll > atk_roll) { - float m_diff = mit_roll - atk_roll; - float thac20 = mit_rating * RuleR(Combat, ACthac20Factor); - float thac20cap = GetLevel() * 9 + 20; - if (thac20 > thac20cap) - thac20 = thac20cap; - - d += 10.0 * (m_diff / thac20); - } - - if (d < 0.0) - d = 0.0; - else if (d > 20.0) - d = 20.0; - - float interval = (damage - minhit) / 20.0; - damage -= ((int)d * interval); - - damage -= (minhit * itembonuses.MeleeMitigation / 100); - damage -= (damage * (spellbonuses.MeleeMitigationEffect + itembonuses.MeleeMitigationEffect + aabonuses.MeleeMitigationEffect) / 100); - return damage; -} - -// This is called when the Client is the one being hit -int32 Client::GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, - float mit_rating, float atk_rating) -{ - if (!attacker->IsNPC() || RuleB(Combat, UseOldDamageIntervalRules)) - return Mob::GetMeleeMitDmg(attacker, damage, minhit, mit_rating, atk_rating); - int d = 10; - // floats for the rounding issues - float dmg_interval = (damage - minhit) / 19.0; - float dmg_bonus = minhit - dmg_interval; - float spellMeleeMit = (spellbonuses.MeleeMitigationEffect + itembonuses.MeleeMitigationEffect + aabonuses.MeleeMitigationEffect) / 100.0; - if (GetClass() == WARRIOR) - spellMeleeMit += 0.05; - dmg_bonus -= dmg_bonus * (itembonuses.MeleeMitigation / 100.0); - dmg_interval -= dmg_interval * spellMeleeMit; - - float mit_roll = zone->random.Real(0, mit_rating); - float atk_roll = zone->random.Real(0, atk_rating); - - if (atk_roll > mit_roll) { - float a_diff = atk_roll - mit_roll; - float thac0 = atk_rating * RuleR(Combat, ACthac0Factor); - float thac0cap = attacker->GetLevel() * 9 + 20; - if (thac0 > thac0cap) - thac0 = thac0cap; - - d += 10 * (a_diff / thac0); - } else if (mit_roll > atk_roll) { - float m_diff = mit_roll - atk_roll; - float thac20 = mit_rating * RuleR(Combat, ACthac20Factor); - float thac20cap = GetLevel() * 9 + 20; - if (thac20 > thac20cap) - thac20 = thac20cap; - - d -= 10 * (m_diff / thac20); - } - - if (d < 1) - d = 1; - else if (d > 20) - d = 20; - - return static_cast((dmg_bonus + dmg_interval * d)); + Log.Out(Logs::Detail, Logs::Attack, "mitigation %d vs offense %d. base %d defensive SPA %d rolled %f damage %d", mitigation, offense, base_damage, meleemitspell, roll, damage); } //Returns the weapon damage against the input mob @@ -964,10 +1096,113 @@ int Mob::GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, u return std::max(0, dmg); } +int Client::DoDamageCaps(int base_damage) +{ + // this is based on a client function that caps melee base_damage + auto level = GetLevel(); + int cap = 0; + if (level >= 125) { + cap = 7 * level; + } else if (level >= 110) { + cap = 6 * level; + } else if (level >= 90) { + cap = 5 * level; + } else if (level >= 70) { + cap = 4 * level; + } else if (level >= 40) { + switch (GetClass()) { + case CLERIC: + case DRUID: + case SHAMAN: + cap = 80; + break; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + cap = 40; + break; + default: + cap = 200; + break; + } + } else if (level >= 30) { + switch (GetClass()) { + case CLERIC: + case DRUID: + case SHAMAN: + cap = 26; + break; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + cap = 18; + break; + default: + cap = 60; + break; + } + } else if (level >= 20) { + switch (GetClass()) { + case CLERIC: + case DRUID: + case SHAMAN: + cap = 20; + break; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + cap = 12; + break; + default: + cap = 30; + break; + } + } else if (level >= 10) { + switch (GetClass()) { + case CLERIC: + case DRUID: + case SHAMAN: + cap = 12; + break; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + cap = 10; + break; + default: + cap = 14; + break; + } + } else { + switch (GetClass()) { + case CLERIC: + case DRUID: + case SHAMAN: + cap = 9; + break; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + cap = 6; + break; + default: + cap = 10; // this is where the 20 damage cap comes from + break; + } + } + + return std::min(cap, base_damage); +} + //note: throughout this method, setting `damage` to a negative is a way to //stop the attack calculations // IsFromSpell added to allow spell effects to use Attack. (Mainly for the Rampage AA right now.) -bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) +bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { if (!other) { SetTarget(nullptr); @@ -1027,7 +1262,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b AttackAnimation(skillinuse, Hand, weapon); Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse); - /// Now figure out damage + // Now figure out damage int damage = 0; uint8 mylevel = GetLevel() ? GetLevel() : 1; uint32 hate = 0; @@ -1038,30 +1273,18 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b //if weapon damage > 0 then we know we can hit the target with this weapon //otherwise we cannot and we set the damage to -5 later on if(weapon_damage > 0){ + // if we revamp this function be more general, we will have to make sure this isn't + // executed for anything BUT normal melee damage weapons from auto attack + if (Hand == EQEmu::inventory::slotPrimary || Hand == EQEmu::inventory::slotSecondary) + weapon_damage = DoDamageCaps(weapon_damage); auto shield_inc = spellbonuses.ShieldEquipDmgMod + itembonuses.ShieldEquipDmgMod + aabonuses.ShieldEquipDmgMod; if (shield_inc > 0 && HasShieldEquiped() && Hand == EQEmu::inventory::slotPrimary) { weapon_damage = weapon_damage * (100 + shield_inc) / 100; hate = hate * (100 + shield_inc) / 100; } - //Berserker Berserk damage bonus - if(IsBerserk() && GetClass() == BERSERKER){ - int bonus = 3 + GetLevel()/10; //unverified - weapon_damage = weapon_damage * (100+bonus) / 100; - Log.Out(Logs::Detail, Logs::Combat, "Berserker damage bonus increases DMG to %d", weapon_damage); - } - - //try a finishing blow.. if successful end the attack - if(TryFinishingBlow(other, skillinuse)) - return (true); - - int min_hit = 1; - int max_hit = (2*weapon_damage*GetDamageTable(skillinuse)) / 100; - - if(GetLevel() < 10 && max_hit > RuleI(Combat, HitCapPre10)) - max_hit = (RuleI(Combat, HitCapPre10)); - else if(GetLevel() < 20 && max_hit > RuleI(Combat, HitCapPre20)) - max_hit = (RuleI(Combat, HitCapPre20)); + int base_damage = weapon_damage; + int min_damage = 0; // damage bonus CheckIncreaseSkill(skillinuse, other, -15); CheckIncreaseSkill(EQEmu::skills::SkillOffense, other, -15); @@ -1087,8 +1310,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); - min_hit += (int) ucDamageBonus; - max_hit += (int) ucDamageBonus; + min_damage = ucDamageBonus; hate += ucDamageBonus; } #endif @@ -1098,33 +1320,25 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr, true); - min_hit += (int) ucDamageBonus; - max_hit += (int) ucDamageBonus; + min_damage = ucDamageBonus; hate += ucDamageBonus; } } // this effect is actually a min cap that happens after the final damage is calculated - min_hit += min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100; + int min_cap = base_damage * GetMeleeMinDamageMod_SE(skillinuse) / 100; - if(max_hit < min_hit) - max_hit = min_hit; + // damage = mod_client_damage(damage, skillinuse, Hand, weapon, other); - if(RuleB(Combat, UseIntervalAC)) - damage = max_hit; - else - damage = zone->random.Int(min_hit, max_hit); - - damage = mod_client_damage(damage, skillinuse, Hand, weapon, other); - - Log.Out(Logs::Detail, Logs::Combat, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)", - damage, min_hit, max_hit, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel); + Log.Out(Logs::Detail, Logs::Combat, "Damage calculated to %d (bonus %d, base %d, str %d, skill %d, DMG %d, lv %d)", + damage, min_damage, base_damage, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel); int hit_chance_bonus = 0; + auto offense = this->offense(skillinuse); // we need this a few times if(opts) { - damage *= opts->damage_percent; - damage += opts->damage_flat; + base_damage *= opts->damage_percent; + base_damage += opts->damage_flat; hate *= opts->hate_percent; hate += opts->hate_flat; hit_chance_bonus += opts->hit_chance; @@ -1149,9 +1363,11 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b Log.Out(Logs::Detail, Logs::Combat, "Avoided damage with code %d", damage); } else { if (other->CheckHitChance(this, skillinuse, hit_chance_bonus)) { - other->MeleeMitigation(this, damage, min_hit, opts); - if (damage > 0) - CommonOutgoingHitSuccess(other, damage, skillinuse,opts); + other->MeleeMitigation(this, damage, base_damage, offense, skillinuse, opts); + if (damage > 0) { + ApplyDamageTable(damage, offense); + CommonOutgoingHitSuccess(other, damage, min_damage, min_cap, skillinuse, opts); + } Log.Out(Logs::Detail, Logs::Combat, "Final damage after all reductions: %d", damage); } else { Log.Out(Logs::Detail, Logs::Combat, "Attack missed. Damage set to 0."); @@ -1177,7 +1393,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, true, -1, false, special); + other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, true, -1, false, m_specialattacks); if (IsDead()) return false; @@ -1205,7 +1421,7 @@ void Mob::Heal() SendHPUpdate(); } -void Client::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) +void Client::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, eSpecialAttacks special) { if(dead || IsCorpse()) return; @@ -1522,7 +1738,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk return true; } -bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) +bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { int damage = 0; @@ -1620,12 +1836,12 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool AttackAnimation(skillinuse, Hand, &weapon_inst); //basically "if not immune" then do the attack - if((weapon_damage) > 0) { + if(weapon_damage > 0) { //ele and bane dmg too //NPCs add this differently than PCs //if NPCs can't inheriently hit the target we don't add bane/magic dmg which isn't exactly the same as PCs - uint32 eleBane = 0; + int eleBane = 0; if(weapon){ if(weapon->BaneDmgBody == other->GetBodyType()){ eleBane += weapon->BaneDmgAmt; @@ -1652,71 +1868,36 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool otherlevel = otherlevel ? otherlevel : 1; mylevel = mylevel ? mylevel : 1; - //instead of calcing damage in floats lets just go straight to ints - if(RuleB(Combat, UseIntervalAC)) - damage = (max_dmg+eleBane); - else - damage = zone->random.Int((min_dmg+eleBane),(max_dmg+eleBane)); + //damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other); - //check if we're hitting above our max or below it. - if((min_dmg+eleBane) != 0 && damage < (min_dmg+eleBane)) { - Log.Out(Logs::Detail, Logs::Combat, "Damage (%d) is below min (%d). Setting to min.", damage, (min_dmg+eleBane)); - damage = (min_dmg+eleBane); - } - if((max_dmg+eleBane) != 0 && damage > (max_dmg+eleBane)) { - Log.Out(Logs::Detail, Logs::Combat, "Damage (%d) is above max (%d). Setting to max.", damage, (max_dmg+eleBane)); - damage = (max_dmg+eleBane); + int lbase_damage = this->base_damage + eleBane; + int lmin_damage = this->min_damage; + int32 hate = lbase_damage + lmin_damage; + + int min_cap = lbase_damage * GetMeleeMinDamageMod_SE(skillinuse) / 100; + + int hit_chance_bonus = 0; + + if(opts) { + lbase_damage *= opts->damage_percent; + lbase_damage += opts->damage_flat; + hate *= opts->hate_percent; + hate += opts->hate_flat; + hit_chance_bonus += opts->hit_chance; } - damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other); - - int32 hate = damage; - if(IsPet()) - { - hate = hate * 100 / GetDamageTable(skillinuse); - } - - if(other->IsClient() && other->CastToClient()->IsSitting()) { - Log.Out(Logs::Detail, Logs::Combat, "Client %s is sitting. Hitting for max damage (%d).", other->GetName(), (max_dmg+eleBane)); - damage = (max_dmg+eleBane); - damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse, opts) / 100) + GetSkillDmgAmt(skillinuse); - - if(opts) { - damage *= opts->damage_percent; - damage += opts->damage_flat; - hate *= opts->hate_percent; - hate += opts->hate_flat; - } - - Log.Out(Logs::Detail, Logs::Combat, "Generating hate %d towards %s", hate, GetName()); - // now add done damage to the hate list - other->AddToHateList(this, hate); - + if (other->AvoidDamage(this, damage, Hand)) { + if (!bRiposte && damage == -3) + DoRiposte(other); } else { - - int hit_chance_bonus = 0; - - if(opts) { - damage *= opts->damage_percent; - damage += opts->damage_flat; - hate *= opts->hate_percent; - hate += opts->hate_flat; - hit_chance_bonus += opts->hit_chance; - } - - if (other->AvoidDamage(this, damage, Hand)) { - if (!bRiposte && damage == -3) - DoRiposte(other); + if (other->CheckHitChance(this, skillinuse, hit_chance_bonus)) { + other->MeleeMitigation(this, damage, lbase_damage, this->offense(skillinuse), skillinuse, opts); + CommonOutgoingHitSuccess(other, damage, lmin_damage, min_cap, skillinuse, opts); } else { - if (other->CheckHitChance(this, skillinuse, hit_chance_bonus)) { - other->MeleeMitigation(this, damage, min_dmg+eleBane, opts); - CommonOutgoingHitSuccess(other, damage, skillinuse, opts); - } else { - damage = 0; - } + damage = 0; } - other->AddToHateList(this, hate); } + other->AddToHateList(this, hate); Log.Out(Logs::Detail, Logs::Combat, "Final damage against %s: %d", other->GetName(), damage); @@ -1729,7 +1910,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool damage = -5; if(GetHP() > 0 && !other->HasDied()) { - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, true, -1, false, special); // Not avoidable client already had thier chance to Avoid + other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, true, -1, false, m_specialattacks); // Not avoidable client already had thier chance to Avoid } else return false; @@ -1764,7 +1945,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool return false; } -void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { +void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, eSpecialAttacks special) { if(spell_id==0) spell_id = SPELL_UNKNOWN; @@ -2988,7 +3169,7 @@ bool Mob::CheckDoubleAttack() return zone->random.Int(1, 500) <= chance; } -void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, const EQEmu::skills::SkillType skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special) { +void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const EQEmu::skills::SkillType skill_used, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks special) { // This method is called with skill_used=ABJURE for Damage Shield damage. bool FromDamageShield = (skill_used == EQEmu::skills::SkillAbjuration); bool ignore_invul = false; @@ -3226,7 +3407,12 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons a->type = SkillDamageTypes[skill_used]; // was 0x1c a->damage = damage; a->spellid = spell_id; - a->special = special; + if (special == eSpecialAttacks::AERampage) + a->special = 1; + else if (special == eSpecialAttacks::Rampage) + a->special = 2; + else + a->special = 0; a->meleepush_xy = attacker ? attacker->GetHeading() * 2.0f : 0.0f; if (RuleB(Combat, MeleePush) && damage > 0 && !IsRooted() && (IsClient() || zone->random.Roll(RuleI(Combat, MeleePushChance)))) { @@ -3709,21 +3895,22 @@ void Mob::TrySpellProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *w return; } -void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage) +void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int &damage) { - if(damage < 1) + if (damage < 1) return; - //Allows pets to perform critical hits. - //Each rank adds an additional 1% chance for any melee hit (primary, secondary, kick, bash, etc) to critical, - //dealing up to 63% more damage. http://www.magecompendium.com/aa-short-library.html + // Allows pets to perform critical hits. + // Each rank adds an additional 1% chance for any melee hit (primary, secondary, kick, bash, etc) to critical, + // dealing up to 63% more damage. http://www.magecompendium.com/aa-short-library.html + // appears to be 70% damage, unsure if changed or just bad info before Mob *owner = nullptr; - float critChance = 0.0f; + int critChance = 0; critChance += RuleI(Combat, MeleeBaseCritChance); - uint32 critMod = 163; + int critMod = 170; - if (damage < 1) //We can't critical hit if we don't hit. + if (damage < 1) // We can't critical hit if we don't hit. return; if (IsPet()) @@ -3736,91 +3923,87 @@ void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage) if (!owner) return; - int32 CritPetChance = owner->aabonuses.PetCriticalHit + owner->itembonuses.PetCriticalHit + owner->spellbonuses.PetCriticalHit; - int32 CritChanceBonus = GetCriticalChanceBonus(skill); + int CritPetChance = + owner->aabonuses.PetCriticalHit + owner->itembonuses.PetCriticalHit + owner->spellbonuses.PetCriticalHit; if (CritPetChance || critChance) { - //For pets use PetCriticalHit for base chance, pets do not innately critical with without it - //even if buffed with a CritChanceBonus effects. + // For pets use PetCriticalHit for base chance, pets do not innately critical with without it critChance += CritPetChance; - critChance += critChance*CritChanceBonus/100.0f; } - if(critChance > 0){ - - critChance /= 100; - - if(zone->random.Roll(critChance)) - { - critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100 + if (critChance > 0) { + if (zone->random.Roll(critChance)) { + critMod += GetCritDmgMob(skill); + damage += 5; damage = (damage * critMod) / 100; - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, CRITICAL_HIT, - GetCleanName(), itoa(damage)); + entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, FilterMeleeCrits, + CRITICAL_HIT, GetCleanName(), itoa(damage)); } } } -void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts) +void Mob::TryCriticalHit(Mob *defender, uint16 skill, int &damage, int min_damage, ExtraAttackOptions *opts) { - if(damage < 1 || !defender) + if (damage < 1 || !defender) return; // decided to branch this into it's own function since it's going to be duplicating a lot of the // code in here, but could lead to some confusion otherwise if ((IsPet() && GetOwner()->IsClient()) || (IsNPC() && CastToNPC()->GetSwarmOwner())) { - TryPetCriticalHit(defender,skill,damage); + TryPetCriticalHit(defender, skill, damage); return; } #ifdef BOTS if (this->IsPet() && this->GetOwner() && this->GetOwner()->IsBot()) { - this->TryPetCriticalHit(defender,skill,damage); + this->TryPetCriticalHit(defender, skill, damage); return; } -#endif //BOTS +#endif // BOTS float critChance = 0.0f; bool IsBerskerSPA = false; - //1: Try Slay Undead - if (defender->GetBodyType() == BT_Undead || - defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire) { + // 1: Try Slay Undead + if (defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead || + defender->GetBodyType() == BT_Vampire) { int32 SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0]; if (SlayRateBonus) { float slayChance = static_cast(SlayRateBonus) / 10000.0f; if (zone->random.Roll(slayChance)) { - int32 SlayDmgBonus = aabonuses.SlayUndead[1] + itembonuses.SlayUndead[1] + spellbonuses.SlayUndead[1]; - damage = (damage * SlayDmgBonus * 2.25) / 100; + int32 SlayDmgBonus = + aabonuses.SlayUndead[1] + itembonuses.SlayUndead[1] + spellbonuses.SlayUndead[1]; + damage += 5; + damage = (damage * SlayDmgBonus) / 100; if (GetGender() == 1) // female - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, FEMALE_SLAYUNDEAD, - GetCleanName(), itoa(damage)); + entity_list.FilteredMessageClose_StringID( + this, false, 200, MT_CritMelee, FilterMeleeCrits, FEMALE_SLAYUNDEAD, + GetCleanName(), itoa(damage + min_damage)); else // males and neuter I guess - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, MALE_SLAYUNDEAD, - GetCleanName(), itoa(damage)); + entity_list.FilteredMessageClose_StringID( + this, false, 200, MT_CritMelee, FilterMeleeCrits, MALE_SLAYUNDEAD, + GetCleanName(), itoa(damage + min_damage)); return; } } } - //2: Try Melee Critical + // 2: Try Melee Critical - //Base critical rate for all classes is dervived from DEX stat, this rate is then augmented - //by item,spell and AA bonuses allowing you a chance to critical hit. If the following rules - //are defined you will have an innate chance to hit at Level 1 regardless of bonuses. - //Warning: Do not define these rules if you want live like critical hits. + // Base critical rate for all classes is dervived from DEX stat, this rate is then augmented + // by item,spell and AA bonuses allowing you a chance to critical hit. If the following rules + // are defined you will have an innate chance to hit at Level 1 regardless of bonuses. + // Warning: Do not define these rules if you want live like critical hits. critChance += RuleI(Combat, MeleeBaseCritChance); if (IsClient()) { - critChance += RuleI(Combat, ClientBaseCritChance); + critChance += RuleI(Combat, ClientBaseCritChance); if (spellbonuses.BerserkSPA || itembonuses.BerserkSPA || aabonuses.BerserkSPA) - IsBerskerSPA = true; + IsBerskerSPA = true; - if (((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) || IsBerskerSPA) { + if (((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) || IsBerskerSPA) { if (IsBerserk() || IsBerskerSPA) critChance += RuleI(Combat, BerserkBaseCritChance); else @@ -3833,7 +4016,8 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack if (skill == EQEmu::skills::SkillArchery && GetClass() == RANGER && GetSkill(EQEmu::skills::SkillArchery) >= 65) critChance += 6; - if (skill == EQEmu::skills::SkillThrowing && GetClass() == ROGUE && GetSkill(EQEmu::skills::SkillThrowing) >= 65) { + if (skill == EQEmu::skills::SkillThrowing && GetClass() == ROGUE && + GetSkill(EQEmu::skills::SkillThrowing) >= 65) { critChance += RuleI(Combat, RogueCritThrowingChance); deadlyChance = RuleI(Combat, RogueDeadlyStrikeChance); deadlyMod = RuleI(Combat, RogueDeadlyStrikeMod); @@ -3843,44 +4027,45 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack if (CritChanceBonus || critChance) { - //Get Base CritChance from Dex. (200 = ~1.6%, 255 = ~2.0%, 355 = ~2.20%) Fall off rate > 255 - //http://giline.versus.jp/shiden/su.htm , http://giline.versus.jp/shiden/damage_e.htm + // Get Base CritChance from Dex. (200 = ~1.6%, 255 = ~2.0%, 355 = ~2.20%) Fall off rate > 255 + // http://giline.versus.jp/shiden/su.htm , http://giline.versus.jp/shiden/damage_e.htm if (GetDEX() <= 255) critChance += (float(GetDEX()) / 125.0f); else if (GetDEX() > 255) - critChance += (float(GetDEX()-255)/ 500.0f) + 2.0f; - critChance += critChance*(float)CritChanceBonus /100.0f; + critChance += (float(GetDEX() - 255) / 500.0f) + 2.0f; + critChance += critChance * (float)CritChanceBonus / 100.0f; } - if(opts) { + if (opts) { critChance *= opts->crit_percent; critChance += opts->crit_flat; } - if(critChance > 0) { + if (critChance > 0) { critChance /= 100; - if(zone->random.Roll(critChance)) - { - uint32 critMod = 200; + if (zone->random.Roll(critChance)) { + if (TryFinishingBlow(defender, static_cast(skill), damage)) + return; + int critMod = 170; bool crip_success = false; int32 CripplingBlowChance = GetCrippBlowChance(); - //Crippling Blow Chance: The percent value of the effect is applied - //to the your Chance to Critical. (ie You have 10% chance to critical and you - //have a 200% Chance to Critical Blow effect, therefore you have a 20% Chance to Critical Blow. + // Crippling Blow Chance: The percent value of the effect is applied + // to the your Chance to Critical. (ie You have 10% chance to critical and you + // have a 200% Chance to Critical Blow effect, therefore you have a 20% Chance to Critical Blow. if (CripplingBlowChance || (IsBerserk() || IsBerskerSPA)) { if (!IsBerserk() && !IsBerskerSPA) - critChance *= float(CripplingBlowChance)/100.0f; + critChance *= float(CripplingBlowChance) / 100.0f; - if ((IsBerserk() || IsBerskerSPA) || zone->random.Roll(critChance)) { - critMod = 400; + if ((IsBerserk() || IsBerskerSPA) || zone->random.Roll(critChance)) crip_success = true; - } } - critMod += GetCritDmgMob(skill) * 2; // To account for base crit mod being 200 not 100 + critMod += GetCritDmgMob(skill); + damage += 5; + int ogdmg = damage; damage = damage * critMod / 100; bool deadlySuccess = false; @@ -3892,33 +4077,37 @@ void Mob::TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttack } if (crip_success) { - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, CRIPPLING_BLOW, - GetCleanName(), itoa(damage)); + damage += ogdmg * 119 / 100; // the damage_e page says it's a ~1.192 increase of dmg before mod + entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, + FilterMeleeCrits, CRIPPLING_BLOW, + GetCleanName(), itoa(damage + min_damage)); // Crippling blows also have a chance to stun - //Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a staggers message. - if (defender->GetLevel() <= 55 && !defender->GetSpecialAbility(IMMUNE_STUN)){ + // Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a + // staggers message. + if (defender->GetLevel() <= 55 && !defender->GetSpecialAbility(IMMUNE_STUN)) { defender->Emote("staggers."); defender->Stun(0); } } else if (deadlySuccess) { - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, DEADLY_STRIKE, - GetCleanName(), itoa(damage)); + entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, + FilterMeleeCrits, DEADLY_STRIKE, + GetCleanName(), itoa(damage + min_damage)); } else { - entity_list.FilteredMessageClose_StringID(this, false, 200, - MT_CritMelee, FilterMeleeCrits, CRITICAL_HIT, - GetCleanName(), itoa(damage)); + entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, + FilterMeleeCrits, CRITICAL_HIT, + GetCleanName(), itoa(damage + min_damage)); } } } } -bool Mob::TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse) +bool Mob::TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse, int &damage) { - if (defender && !defender->IsClient() && defender->GetHPRatio() < 10){ + // base2 of FinishingBlowLvl is the HP limit (cur / max) * 1000, 10% is listed as 100 + if (defender && !defender->IsClient() && defender->GetHPRatio() < 10) { - uint32 FB_Dmg = aabonuses.FinishingBlow[1] + spellbonuses.FinishingBlow[1] + itembonuses.FinishingBlow[1]; + uint32 FB_Dmg = + aabonuses.FinishingBlow[1] + spellbonuses.FinishingBlow[1] + itembonuses.FinishingBlow[1]; uint32 FB_Level = 0; FB_Level = aabonuses.FinishingBlowLvl[0]; @@ -3927,12 +4116,14 @@ bool Mob::TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse) else if (FB_Level < itembonuses.FinishingBlowLvl[0]) FB_Level = itembonuses.FinishingBlowLvl[0]; - //Proc Chance value of 500 = 5% - uint32 ProcChance = (aabonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0])/10; + // Proc Chance value of 500 = 5% + uint32 ProcChance = + (aabonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0]) / 10; - if(FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && (ProcChance >= zone->random.Int(0, 1000))){ + if (FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && + (ProcChance >= zone->random.Int(0, 1000))) { entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); - DoSpecialAttackDamage(defender, skillinuse, FB_Dmg, 1, -1, 10, false, false); + damage = FB_Dmg; return true; } } @@ -3991,21 +4182,10 @@ void Mob::DoRiposte(Mob *defender) } } -void Mob::ApplyMeleeDamageBonus(uint16 skill, int32 &damage,ExtraAttackOptions *opts){ - - if(!RuleB(Combat, UseIntervalAC)){ - if(IsNPC()){ //across the board NPC damage bonuses. - //only account for STR here, assume their base STR was factored into their DB damages - int dmgbonusmod = 0; - dmgbonusmod += (100*(itembonuses.STR + spellbonuses.STR))/3; - dmgbonusmod += (100*(spellbonuses.ATK + itembonuses.ATK))/5; - Log.Out(Logs::Detail, Logs::Combat, "Damage bonus: %d percent from ATK and STR bonuses.", (dmgbonusmod/100)); - damage += (damage*dmgbonusmod/10000); - } - } - +void Mob::ApplyMeleeDamageBonus(uint16 skill, int &damage, ExtraAttackOptions *opts) +{ int dmgbonusmod = 0; - + dmgbonusmod += GetMeleeDamageMod_SE(skill); if (opts) dmgbonusmod += opts->melee_damage_bonus_flat; @@ -4025,48 +4205,168 @@ bool Mob::HasDied() { return Result; } -uint16 Mob::GetDamageTable(EQEmu::skills::SkillType skillinuse) +const DamageTable &Mob::GetDamageTable() const { - if(GetLevel() <= 51) - { - uint32 ret_table = 0; - int str_over_75 = 0; - if(GetSTR() > 75) - str_over_75 = GetSTR() - 75; - if(str_over_75 > 255) - ret_table = (GetSkill(skillinuse)+255)/2; - else - ret_table = (GetSkill(skillinuse)+str_over_75)/2; + static const DamageTable dmg_table[] = { + {210, 49, 105}, // 1-50 + {245, 35, 80}, // 51 + {245, 35, 80}, // 52 + {245, 35, 80}, // 53 + {245, 35, 80}, // 54 + {245, 35, 80}, // 55 + {265, 28, 70}, // 56 + {265, 28, 70}, // 57 + {265, 28, 70}, // 58 + {265, 28, 70}, // 59 + {285, 23, 65}, // 60 + {285, 23, 65}, // 61 + {285, 23, 65}, // 62 + {290, 21, 60}, // 63 + {290, 21, 60}, // 64 + {295, 19, 55}, // 65 + {295, 19, 55}, // 66 + {300, 19, 55}, // 67 + {300, 19, 55}, // 68 + {300, 19, 55}, // 69 + {305, 19, 55}, // 70 + {305, 19, 55}, // 71 + {310, 17, 50}, // 72 + {310, 17, 50}, // 73 + {310, 17, 50}, // 74 + {315, 17, 50}, // 75 + {315, 17, 50}, // 76 + {325, 17, 45}, // 77 + {325, 17, 45}, // 78 + {325, 17, 45}, // 79 + {335, 17, 45}, // 80 + {335, 17, 45}, // 81 + {345, 17, 45}, // 82 + {345, 17, 45}, // 83 + {345, 17, 45}, // 84 + {355, 17, 45}, // 85 + {355, 17, 45}, // 86 + {365, 17, 45}, // 87 + {365, 17, 45}, // 88 + {365, 17, 45}, // 89 + {375, 17, 45}, // 90 + {375, 17, 45}, // 91 + {380, 17, 45}, // 92 + {380, 17, 45}, // 93 + {380, 17, 45}, // 94 + {385, 17, 45}, // 95 + {385, 17, 45}, // 96 + {390, 17, 45}, // 97 + {390, 17, 45}, // 98 + {390, 17, 45}, // 99 + {395, 17, 45}, // 100 + {395, 17, 45}, // 101 + {400, 17, 45}, // 102 + {400, 17, 45}, // 103 + {400, 17, 45}, // 104 + {405, 17, 45} // 105 + }; - if(ret_table < 100) - return 100; + static const DamageTable mnk_table[] = { + {220, 45, 100}, // 1-50 + {245, 35, 80}, // 51 + {245, 35, 80}, // 52 + {245, 35, 80}, // 53 + {245, 35, 80}, // 54 + {245, 35, 80}, // 55 + {285, 23, 65}, // 56 + {285, 23, 65}, // 57 + {285, 23, 65}, // 58 + {285, 23, 65}, // 59 + {290, 21, 60}, // 60 + {290, 21, 60}, // 61 + {290, 21, 60}, // 62 + {295, 19, 55}, // 63 + {295, 19, 55}, // 64 + {300, 17, 50}, // 65 + {300, 17, 50}, // 66 + {310, 17, 50}, // 67 + {310, 17, 50}, // 68 + {310, 17, 50}, // 69 + {320, 17, 50}, // 70 + {320, 17, 50}, // 71 + {325, 15, 45}, // 72 + {325, 15, 45}, // 73 + {325, 15, 45}, // 74 + {330, 15, 45}, // 75 + {330, 15, 45}, // 76 + {335, 15, 40}, // 77 + {335, 15, 40}, // 78 + {335, 15, 40}, // 79 + {345, 15, 40}, // 80 + {345, 15, 40}, // 81 + {355, 15, 40}, // 82 + {355, 15, 40}, // 83 + {355, 15, 40}, // 84 + {365, 15, 40}, // 85 + {365, 15, 40}, // 86 + {375, 15, 40}, // 87 + {375, 15, 40}, // 88 + {375, 15, 40}, // 89 + {385, 15, 40}, // 90 + {385, 15, 40}, // 91 + {390, 15, 40}, // 92 + {390, 15, 40}, // 93 + {390, 15, 40}, // 94 + {395, 15, 40}, // 95 + {395, 15, 40}, // 96 + {400, 15, 40}, // 97 + {400, 15, 40}, // 98 + {400, 15, 40}, // 99 + {405, 15, 40}, // 100 + {405, 15, 40}, // 101 + {410, 15, 40}, // 102 + {410, 15, 40}, // 103 + {410, 15, 40}, // 104 + {415, 15, 40}, // 105 + }; - return ret_table; - } - else if(GetLevel() >= 90) - { - if(GetClass() == MONK) - return 379; - else - return 345; - } - else - { - uint32 dmg_table[] = { - 275, 275, 275, 275, 275, - 280, 280, 280, 280, 285, - 285, 285, 290, 290, 295, - 295, 300, 300, 300, 305, - 305, 305, 310, 310, 315, - 315, 320, 320, 320, 325, - 325, 325, 330, 330, 335, - 335, 340, 340, 340, - }; - if(GetClass() == MONK) - return (dmg_table[GetLevel()-51]*(100+RuleI(Combat,MonkDamageTableBonus))/100); - else - return dmg_table[GetLevel()-51]; - } + bool monk = GetClass() == MONK; + bool melee = IsWarriorClass(); + // tables caped at 105 for now -- future proofed for a while at least :P + int level = std::min(static_cast(GetLevel()), 105); + + if (!melee || (!monk && level < 51)) + return dmg_table[0]; + + if (monk && level < 51) + return mnk_table[0]; + + auto &which = monk ? mnk_table : dmg_table; + return which[level - 50]; +} + +void Mob::ApplyDamageTable(int &damage, int offense) +{ + // someone may want to add this to custom servers, can remove this if that's the case + if (!IsClient() +#ifdef BOTS + && !IsBot() +#endif + ) + return; + // this was parsed, but we do see the min of 10 and the normal minus factor is 105, so makes sense + if (offense < 115) + return; + + auto &damage_table = GetDamageTable(); + + if (zone->random.Roll(damage_table.chance)) + return; + + int basebonus = offense - damage_table.minusfactor; + basebonus = std::max(10, basebonus / 2); + int extrapercent = zone->random.Roll0(basebonus); + int percent = std::min(100 + extrapercent, damage_table.max_extra); + damage = (damage * percent) / 100; + + if (IsWarriorClass() && GetLevel() > 54) + damage++; + Log.Out(Logs::Detail, Logs::Attack, "Damage table applied %d (max %d)", percent, damage_table.max_extra); } void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, uint16 hand, bool IsDefensive) @@ -4368,14 +4668,108 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type) return damage; } -void Mob::CommonOutgoingHitSuccess(Mob* defender, int32 &damage, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts) +// min_damage is the damage bonus, we need to pass it along for a bit +// min_mod is the min hit cap, which needs to be calculated before we call this, but applied here +void Mob::CommonOutgoingHitSuccess(Mob* defender, int &damage, int min_damage, int min_mod, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts) { if (!defender) return; + // BER weren't parsing the halving + if (skillInUse == EQEmu::skills::SkillArchery || + (skillInUse == EQEmu::skills::SkillThrowing && GetClass() != BERSERKER)) + damage /= 2; + + if (damage < 1) + damage = 1; + + if (skillInUse == EQEmu::skills::SkillArchery) { + int bonus = aabonuses.ArcheryDamageModifier + itembonuses.ArcheryDamageModifier + spellbonuses.ArcheryDamageModifier; + damage += damage * bonus / 100; + int headshot = TryHeadShot(defender, skillInUse); + if (headshot > 0) + damage = headshot; + } + + // this parses after damage table + if (skillInUse == EQEmu::skills::SkillArchery && GetClass() == RANGER && GetLevel() > 50) { + if (defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) { + damage *= 2; + Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE); + } + } + + int extra_mincap = 0; + if (skillInUse == EQEmu::skills::SkillBackstab) { + extra_mincap = GetLevel() < 7 ? 7 : GetLevel(); + if (GetLevel() >= 60) + extra_mincap = GetLevel() * 2; + else if (GetLevel() > 50) + extra_mincap = GetLevel() * 3 / 2; + if (IsSpecialAttack(eSpecialAttacks::ChaoticStab)) { + damage = extra_mincap; + } else { + int ass = TryAssassinate(defender, skillInUse, 10000); // reusetime shouldn't have an effect .... + if (ass > 0) + damage = ass; + } + } else if (skillInUse == EQEmu::skills::SkillFrenzy && GetClass() == BERSERKER && GetLevel() > 50) { + extra_mincap = 4 * GetLevel() / 5; + } + + // this has some weird ordering + // Seems the crit message is generated before some of them :P + + // worn item +skill dmg, SPA 220, 418. Live has a normalized version that should be here too + min_damage += GetSkillDmgAmt(skillInUse); + + // shielding mod2 + if (defender->itembonuses.MeleeMitigation) + min_damage -= min_damage * defender->itembonuses.MeleeMitigation / 100; + ApplyMeleeDamageBonus(skillInUse, damage, opts); - damage += (damage * defender->GetSkillDmgTaken(skillInUse, opts) / 100) + (GetSkillDmgAmt(skillInUse) + defender->GetFcDamageAmtIncoming(this, 0, true, skillInUse)); - TryCriticalHit(defender, skillInUse, damage,opts); + min_mod = std::max(min_mod, extra_mincap); + if (min_mod && damage < min_mod) // SPA 186 + damage = min_mod; + + TryCriticalHit(defender, skillInUse, damage, min_damage, opts); + + damage += min_damage; + if (IsClient()) { + int extra = 0; + switch (skillInUse) { + case EQEmu::skills::SkillThrowing: + case EQEmu::skills::SkillArchery: + extra = CastToClient()->GetHeroicDEX() / 10; + break; + default: + extra = CastToClient()->GetHeroicSTR() / 10; + break; + } + damage += extra; + } + + // this appears where they do special attack dmg mods + int spec_mod = 0; + if (IsSpecialAttack(eSpecialAttacks::Rampage)) { + int mod = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2); + if (mod > 0) + spec_mod = mod; + if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) { + int spell = spellbonuses.PC_Pet_Rampage[1] + itembonuses.PC_Pet_Rampage[1] + aabonuses.PC_Pet_Rampage[1]; + if (spell > spec_mod) + spec_mod = spell; + } + } else if (IsSpecialAttack(eSpecialAttacks::AERampage)) { + int mod = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2); + if (mod > 0) + spec_mod = mod; + } + if (spec_mod > 0) + damage = (damage * spec_mod) / 100; + + damage += (damage * defender->GetSkillDmgTaken(skillInUse, opts) / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, skillInUse)); + CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); } @@ -4533,9 +4927,9 @@ void NPC::SetAttackTimer() // Mob's delay set to 20, weapon set to 21, delay 20 int speed = 0; if (RuleB(Spells, Jun182014HundredHandsRevamp)) - speed = static_cast(((attack_delay / haste_mod) + ((hhe / 1000.0f) * (attack_delay / haste_mod))) * 100); + speed = static_cast((attack_delay / haste_mod) + ((hhe / 1000.0f) * (attack_delay / haste_mod))); else - speed = static_cast(((attack_delay / haste_mod) + ((hhe / 100.0f) * attack_delay)) * 100); + speed = static_cast((attack_delay / haste_mod) + ((hhe / 100.0f) * attack_delay)); for (int i = EQEmu::inventory::slotRange; i <= EQEmu::inventory::slotSecondary; i++) { //pick a timer @@ -4632,7 +5026,7 @@ bool Client::CheckDualWield() return zone->random.Int(1, 375) <= chance; } -void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int special) +void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts) { if (!target) return; @@ -4640,10 +5034,9 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec if (RuleB(Combat, UseLiveCombatRounds)) { // A "quad" on live really is just a successful dual wield where both double attack // The mobs that could triple lost the ability to when the triple attack skill was added in - Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts); if (CanThisClassDoubleAttack() && CheckDoubleAttack()){ - Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); - + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts); if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ int chance = spellbonuses.PC_Pet_Flurry + itembonuses.PC_Pet_Flurry + aabonuses.PC_Pet_Flurry; if (chance && zone->random.Roll(chance)) @@ -4656,14 +5049,14 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec if (IsNPC()) { int16 n_atk = CastToNPC()->GetNumberOfAttacks(); if (n_atk <= 1) { - Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts); } else { for (int i = 0; i < n_atk; ++i) { - Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts); } } } else { - Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts); } // we use this random value in three comparisons with different @@ -4674,21 +5067,21 @@ void Mob::DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int spec // check double attack, this is NOT the same rules that clients use... && RandRoll < (GetLevel() + NPCDualAttackModifier)) { - Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts); // lets see if we can do a triple attack with the main hand // pets are excluded from triple and quads... if ((GetSpecialAbility(SPECATK_TRIPLE) || GetSpecialAbility(SPECATK_QUAD)) && !IsPet() && RandRoll < (GetLevel() + NPCTripleAttackModifier)) { - Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts); // now lets check the quad attack if (GetSpecialAbility(SPECATK_QUAD) && RandRoll < (GetLevel() + NPCQuadAttackModifier)) { - Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotPrimary, false, false, false, opts); } } } } -void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int special) +void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts) { if (!target) return; @@ -4698,9 +5091,9 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts, int speci (RuleB(Combat, UseLiveCombatRounds) && GetSpecialAbility(SPECATK_QUAD))) || GetEquipment(EQEmu::textures::weaponSecondary) != 0) { if (CheckDualWield()) { - Attack(target, EQEmu::inventory::slotSecondary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotSecondary, false, false, false, opts); if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()){ - Attack(target, EQEmu::inventory::slotSecondary, false, false, false, opts, special); + Attack(target, EQEmu::inventory::slotSecondary, false, false, false, opts); if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ int chance = spellbonuses.PC_Pet_Flurry + itembonuses.PC_Pet_Flurry + aabonuses.PC_Pet_Flurry; diff --git a/zone/beacon.h b/zone/beacon.h index cd66269bb..b79ed318c 100644 --- a/zone/beacon.h +++ b/zone/beacon.h @@ -35,9 +35,9 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; } - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) { return; } virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } + ExtraAttackOptions *opts = nullptr) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index beae3995d..3acf6cb1d 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -46,6 +46,7 @@ void Mob::CalcBonuses() CalcMaxHP(); CalcMaxMana(); SetAttackTimer(); + CalcAC(); rooted = FindType(SE_Root); } @@ -669,6 +670,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } switch (effect) { + case SE_ACv2: + case SE_ArmorClass: + newbon->AC += base1; + break; // Note: AA effects that use accuracy are skill limited, while spell effect is not. case SE_Accuracy: // Bad data or unsupported new skill @@ -1527,9 +1532,6 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) } } - // THIS IS WRONG, leaving for now - //this prolly suffer from roundoff error slightly... - newbon->AC = newbon->AC * 10 / 34; //ratio determined impirically from client. if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. } diff --git a/zone/bot.cpp b/zone/bot.cpp index 7b0739b47..ac6a6ddd7 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1992,110 +1992,6 @@ bool Bot::CheckBotDoubleAttack(bool tripleAttack) { return false; } -void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime) { - if (!CanDoSpecialAttack(other)) - return; - - //For spells using skill value 98 (feral swipe ect) server sets this to 67 automatically. - if (skillinuse == EQEmu::skills::SkillBegging) - skillinuse = EQEmu::skills::SkillOffense; - - int damage = 0; - uint32 hate = 0; - int Hand = EQEmu::inventory::slotPrimary; - if (hate == 0 && weapon_damage > 1) - hate = weapon_damage; - - if(weapon_damage > 0) { - if(GetClass() == BERSERKER) { - int bonus = (3 + GetLevel( )/ 10); - weapon_damage = (weapon_damage * (100 + bonus) / 100); - } - - int32 min_hit = 1; - int32 max_hit = ((2 * weapon_damage * GetDamageTable(skillinuse)) / 100); - if(GetLevel() >= 28 && IsWarriorClass()) { - int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::ItemData*) nullptr); - min_hit += (int) ucDamageBonus; - max_hit += (int) ucDamageBonus; - hate += ucDamageBonus; - } - - ApplySpecialAttackMod(skillinuse, max_hit, min_hit); - min_hit += (min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100); - if(max_hit < min_hit) - max_hit = min_hit; - - if(RuleB(Combat, UseIntervalAC)) - damage = max_hit; - else - damage = zone->random.Int(min_hit, max_hit); - - if (other->AvoidDamage(this, damage, CanRiposte ? EQEmu::inventory::slotRange : EQEmu::inventory::slotPrimary)) { // MainRange excludes ripo, primary doesn't have any extra behavior - if (damage == -3) { - DoRiposte(other); - if (HasDied()) - return; - } - } else { - if (other->CheckHitChance(this, skillinuse, chance_mod)) { - other->MeleeMitigation(this, damage, min_hit); - if (damage > 0) { - damage += damage*focus/100; - ApplyMeleeDamageBonus(skillinuse, damage); - damage += other->GetFcDamageAmtIncoming(this, 0, true, skillinuse); - damage += ((itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse)); - TryCriticalHit(other, skillinuse, damage, nullptr); - } - } else { - damage = 0; - } - } - } - else - damage = -5; - - if (skillinuse == EQEmu::skills::SkillBash){ - const EQEmu::ItemInstance* inst = GetBotItem(EQEmu::inventory::slotSecondary); - const EQEmu::ItemData* botweapon = 0; - if(inst) - botweapon = inst->GetItem(); - - if(botweapon) { - if (botweapon->ItemType == EQEmu::item::ItemTypeShield) - hate += botweapon->AC; - - hate = (hate * (100 + GetFuriousBash(botweapon->Focus.Effect)) / 100); - } - } - - other->AddToHateList(this, hate); - - bool CanSkillProc = true; - if (skillinuse == EQEmu::skills::SkillOffense){ //Hack to allow damage to display. - skillinuse = EQEmu::skills::SkillTigerClaw; //'strike' your opponent - Arbitrary choice for message. - CanSkillProc = false; //Disable skill procs - } - - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); - if (HasDied()) - return; - - if (damage > 0) - CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); - - if ((skillinuse == EQEmu::skills::SkillDragonPunch) && GetAA(aaDragonPunch) && zone->random.Int(0, 99) < 25){ - SpellFinished(904, other, EQEmu::CastingSlot::Item, 0, -1, spells[904].ResistDiff); - other->Stun(100); - } - - if (CanSkillProc && HasSkillProcs()) - TrySkillProc(other, skillinuse, ReuseTime); - - if (CanSkillProc && (damage > 0) && HasSkillProcSuccess()) - TrySkillProc(other, skillinuse, ReuseTime, true); -} - void Bot::ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int32 &mindmg) { int item_slot = -1; //1: Apply bonus from AC (BOOT/SHIELD/HANDS) est. 40AC=6dmg @@ -3664,7 +3560,7 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, EQEmu::skills::Sk return true; } -void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) { +void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, eSpecialAttacks special) { if(spell_id == 0) spell_id = SPELL_UNKNOWN; @@ -3710,7 +3606,7 @@ void Bot::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic); } -bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) { +bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { if (!other) { SetTarget(nullptr); Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to Bot::Attack for evaluation!"); @@ -3778,25 +3674,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b //if weapon damage > 0 then we know we can hit the target with this weapon //otherwise we cannot and we set the damage to -5 later on if(weapon_damage > 0) { - //Berserker Berserk damage bonus - if(berserk && (GetClass() == BERSERKER)){ - int bonus = (3 + GetLevel() / 10); //unverified - weapon_damage = (weapon_damage * (100 + bonus) / 100); - Log.Out(Logs::Detail, Logs::Combat, "Berserker damage bonus increases DMG to %d", weapon_damage); - } - - //try a finishing blow.. if successful end the attack - if(TryFinishingBlow(other, skillinuse)) - return true; - - //damage formula needs some work - int min_hit = 1; - int max_hit = ((2 * weapon_damage * GetDamageTable(skillinuse)) / 100); - - if(GetLevel() < 10 && max_hit > RuleI(Combat, HitCapPre10)) - max_hit = (RuleI(Combat, HitCapPre10)); - else if(GetLevel() < 20 && max_hit > RuleI(Combat, HitCapPre20)) - max_hit = (RuleI(Combat, HitCapPre20)); + int min_damage = 0; // *************************************************************** // *** Calculate the damage bonus, if applicable, for this hit *** @@ -3814,8 +3692,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); - min_hit += (int) ucDamageBonus; - max_hit += (int) ucDamageBonus; + min_damage = ucDamageBonus; hate += ucDamageBonus; } #endif @@ -3823,28 +3700,21 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if (Hand == EQEmu::inventory::slotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); - min_hit += (int) ucDamageBonus; - max_hit += (int) ucDamageBonus; + min_damage = ucDamageBonus; hate += ucDamageBonus; } } - min_hit = (min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100); + int min_cap = (base_damage * GetMeleeMinDamageMod_SE(skillinuse) / 100); - if(max_hit < min_hit) - max_hit = min_hit; + Log.Out(Logs::Detail, Logs::Combat, "Damage calculated to %d (bonus %d, base %d, str %d, skill %d, DMG %d, lv %d)", + damage, min_damage, base_damage, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel); - if(RuleB(Combat, UseIntervalAC)) - damage = max_hit; - else - damage = zone->random.Int(min_hit, max_hit); - - Log.Out(Logs::Detail, Logs::Combat, "Damage calculated to %d (min %d, max %d, str %d, skill %d, DMG %d, lv %d)", - damage, min_hit, max_hit, GetSTR(), GetSkill(skillinuse), weapon_damage, GetLevel()); + auto offense = this->offense(skillinuse); if(opts) { - damage *= opts->damage_percent; - damage += opts->damage_flat; + base_damage *= opts->damage_percent; + base_damage += opts->damage_flat; hate *= opts->hate_percent; hate += opts->hate_flat; } @@ -3866,10 +3736,11 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b } } else { if (other->CheckHitChance(this, skillinuse)) { - other->MeleeMitigation(this, damage, min_hit, opts); - ApplyMeleeDamageBonus(skillinuse, damage); - damage += ((itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse)); - TryCriticalHit(other, skillinuse, damage, opts); + other->MeleeMitigation(this, damage, base_damage, offense, skillinuse, opts); + if (damage > 0) { + ApplyDamageTable(damage, offense); + CommonOutgoingHitSuccess(other, damage, min_damage, min_cap, skillinuse, opts); + } } else { damage = 0; } @@ -3896,39 +3767,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if (damage > 0) CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); - //break invis when you attack - if(invisible) { - Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility due to melee attack."); - BuffFadeByEffect(SE_Invisibility); - BuffFadeByEffect(SE_Invisibility2); - invisible = false; - } - - if(invisible_undead) { - Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. undead due to melee attack."); - BuffFadeByEffect(SE_InvisVsUndead); - BuffFadeByEffect(SE_InvisVsUndead2); - invisible_undead = false; - } - - if(invisible_animals){ - Log.Out(Logs::Detail, Logs::Combat, "Removing invisibility vs. animals due to melee attack."); - BuffFadeByEffect(SE_InvisVsAnimals); - invisible_animals = false; - } - - if(hidden || improved_hidden){ - hidden = false; - improved_hidden = false; - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SpawnAppearance, sizeof(SpawnAppearance_Struct)); - SpawnAppearance_Struct* sa_out = (SpawnAppearance_Struct*)outapp->pBuffer; - sa_out->spawn_id = GetID(); - sa_out->type = 0x03; - sa_out->parameter = 0; - entity_list.QueueClients(this, outapp, true); - safe_delete(outapp); - } - + CommonBreakInvisibleFromCombat(); if (spellbonuses.NegateIfCombat) BuffFadeByEffect(SE_NegateIfCombat); @@ -4816,21 +4655,24 @@ int Bot::GetHandToHandDamage(void) { return 2; } -bool Bot::TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse) { +bool Bot::TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse, int &damage) +{ if (!defender) return false; if (aabonuses.FinishingBlow[1] && !defender->IsClient() && defender->GetHPRatio() < 10) { - uint32 chance = (aabonuses.FinishingBlow[0] / 10); - uint32 damage = aabonuses.FinishingBlow[1]; - uint16 levelreq = aabonuses.FinishingBlowLvl[0]; - if(defender->GetLevel() <= levelreq && (chance >= zone->random.Int(0, 1000))){ - Log.Out(Logs::Detail, Logs::Combat, "Landed a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); + int chance = (aabonuses.FinishingBlow[0] / 10); + int fb_damage = aabonuses.FinishingBlow[1]; + int levelreq = aabonuses.FinishingBlowLvl[0]; + if (defender->GetLevel() <= levelreq && (chance >= zone->random.Int(0, 1000))) { + Log.Out(Logs::Detail, Logs::Combat, "Landed a finishing blow: levelreq at %d, other level %d", + levelreq, defender->GetLevel()); entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); - defender->Damage(this, damage, SPELL_UNKNOWN, skillinuse); + damage = fb_damage; return true; } else { - Log.Out(Logs::Detail, Logs::Combat, "FAILED a finishing blow: levelreq at %d, other level %d", levelreq , defender->GetLevel()); + Log.Out(Logs::Detail, Logs::Combat, "FAILED a finishing blow: levelreq at %d, other level %d", + levelreq, defender->GetLevel()); return false; } } @@ -4858,6 +4700,92 @@ void Bot::DoRiposte(Mob* defender) { } } +int Bot::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target) +{ + int base = EQEmu::skills::GetBaseDamage(skill); + auto skill_level = GetSkill(skill); + switch (skill) { + case EQEmu::skills::SkillDragonPunch: + case EQEmu::skills::SkillEagleStrike: + case EQEmu::skills::SkillTigerClaw: + if (skill_level >= 25) + base++; + if (skill_level >= 75) + base++; + if (skill_level >= 125) + base++; + if (skill_level >= 175) + base++; + return base; + case EQEmu::skills::SkillFrenzy: + if (GetBotItem(EQEmu::inventory::slotSecondary)) { + if (GetLevel() > 15) + base += GetLevel() - 15; + if (base > 23) + base = 23; + if (GetLevel() > 50) + base += 2; + if (GetLevel() > 54) + base++; + if (GetLevel() > 59) + base++; + } + return base; + case EQEmu::skills::SkillFlyingKick: { + float skill_bonus = skill_level / 9.0f; + float ac_bonus = 0.0f; + auto inst = GetBotItem(EQEmu::inventory::slotFeet); + if (inst) + ac_bonus = inst->GetItemArmorClass(true) / 25.0f; + if (ac_bonus > skill_bonus) + ac_bonus = skill_bonus; + return static_cast(ac_bonus + skill_bonus); + } + case EQEmu::skills::SkillKick: { + float skill_bonus = skill_level / 10.0f; + float ac_bonus = 0.0f; + auto inst = GetBotItem(EQEmu::inventory::slotFeet); + if (inst) + ac_bonus = inst->GetItemArmorClass(true) / 25.0f; + if (ac_bonus > skill_bonus) + ac_bonus = skill_bonus; + return static_cast(ac_bonus + skill_bonus); + } + case EQEmu::skills::SkillBash: { + float skill_bonus = skill_level / 10.0f; + float ac_bonus = 0.0f; + const EQEmu::ItemInstance *inst = nullptr; + if (HasShieldEquiped()) + inst = GetBotItem(EQEmu::inventory::slotSecondary); + else if (HasTwoHanderEquipped()) + inst = GetBotItem(EQEmu::inventory::slotPrimary); + if (inst) + ac_bonus = inst->GetItemArmorClass(true) / 25.0f; + if (ac_bonus > skill_bonus) + ac_bonus = skill_bonus; + return static_cast(ac_bonus + skill_bonus); + } + case EQEmu::skills::SkillBackstab: { + float skill_bonus = static_cast(skill_level) * 0.02f; + auto inst = GetBotItem(EQEmu::inventory::slotPrimary); + if (inst && inst->GetItem() && inst->GetItem()->ItemType == EQEmu::item::ItemType1HPiercing) { + base = inst->GetItemBackstabDamage(true); + if (!inst->GetItemBackstabDamage()) + base += inst->GetItemWeaponDamage(true); + if (target) { + if (inst->GetItemElementalFlag(true) && inst->GetItemElementalDamage(true)) + base += target->ResistElementalWeaponDmg(inst); + if (inst->GetItemBaneDamageBody(true) || inst->GetItemBaneDamageRace(true)) + base += target->CheckBaneDamage(inst); + } + } + return static_cast(static_cast(base) * (skill_bonus + 2.0f)); + } + default: + return 0; + } +} + void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool HitChance) { int32 hate = max_damage; if(hate_override > -1) @@ -4877,33 +4805,36 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 } } - min_damage += (min_damage * GetMeleeMinDamageMod_SE(skill) / 100); + int min_cap = max_damage * GetMeleeMinDamageMod_SE(skill) / 100; int hand = EQEmu::inventory::slotPrimary; + int damage = 0; + auto offense = this->offense(skill); if (skill == EQEmu::skills::SkillThrowing || skill == EQEmu::skills::SkillArchery) hand = EQEmu::inventory::slotRange; - if (who->AvoidDamage(this, max_damage, hand)) { - if (max_damage == -3) + if (who->AvoidDamage(this, damage, hand)) { + if (damage == -3) DoRiposte(who); } else { if (HitChance || who->CheckHitChance(this, skill)) { - who->MeleeMitigation(this, max_damage, min_damage); - ApplyMeleeDamageBonus(skill, max_damage); - max_damage += who->GetFcDamageAmtIncoming(this, 0, true, skill); - max_damage += ((itembonuses.HeroicSTR / 10) + (max_damage * who->GetSkillDmgTaken(skill) / 100) + GetSkillDmgAmt(skill)); - TryCriticalHit(who, skill, max_damage); + if (max_damage > 0) + who->MeleeMitigation(this, damage, max_damage, offense, skill); + if (damage > 0) { + ApplyDamageTable(damage, offense); + CommonOutgoingHitSuccess(who, damage, min_damage, min_cap, skill); + } } else { - max_damage = 0; + damage = 0; } } who->AddToHateList(this, hate); - who->Damage(this, max_damage, SPELL_UNKNOWN, skill, false); + who->Damage(this, damage, SPELL_UNKNOWN, skill, false); if(!GetTarget() || HasDied()) return; - if (max_damage > 0) + if (damage > 0) CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); //[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill @@ -4919,7 +4850,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 if (HasSkillProcs()) TrySkillProc(who, skill, (ReuseTime * 1000)); - if (max_damage > 0 && HasSkillProcSuccess()) + if (damage > 0 && HasSkillProcSuccess()) TrySkillProc(who, skill, (ReuseTime * 1000), true); } @@ -4967,72 +4898,33 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) { } } } else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) { + m_specialattacks = eSpecialAttacks::ChaoticStab; RogueBackstab(other, true); - if (level > 54) { - float DoubleAttackProbability = ((GetSkill(EQEmu::skills::SkillDoubleAttack) + GetLevel()) / 500.0f); - if(zone->random.Real(0, 1) < DoubleAttackProbability) - if(other->GetHP() > 0) - RogueBackstab(other,true, ReuseTime); - - if (tripleChance && other->GetHP() > 0 && tripleChance > zone->random.Int(0, 100)) - RogueBackstab(other,false,ReuseTime); - } + m_specialattacks = eSpecialAttacks::None; } else Attack(other, EQEmu::inventory::slotPrimary); } -void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { - int32 ndamage = 0; - int32 max_hit = 0; - int32 min_hit = 0; - int32 hate = 0; - int32 primaryweapondamage = 0; - int32 backstab_dmg = 0; - EQEmu::ItemInstance* botweaponInst = GetBotItem(EQEmu::inventory::slotPrimary); - if(botweaponInst) { - primaryweapondamage = GetWeaponDamage(other, botweaponInst); - backstab_dmg = botweaponInst->GetItem()->BackstabDmg; - for (int i = EQEmu::inventory::socketBegin; i < EQEmu::inventory::SocketCount; ++i) { - EQEmu::ItemInstance *aug = botweaponInst->GetAugment(i); - if(aug) - backstab_dmg += aug->GetItem()->BackstabDmg; - } - } else { - primaryweapondamage = ((GetLevel() / 7) + 1); - backstab_dmg = primaryweapondamage; +void Bot::RogueBackstab(Mob *other, bool min_damage, int ReuseTime) +{ + if (!other) + return; + + EQEmu::ItemInstance *botweaponInst = GetBotItem(EQEmu::inventory::slotPrimary); + if (botweaponInst) { + if (!GetWeaponDamage(other, botweaponInst)) + return; + } else if (!GetWeaponDamage(other, (const EQEmu::ItemData *)nullptr)) { + return; } - if(primaryweapondamage > 0) { - if(level > 25) { - max_hit = (((((2 * backstab_dmg) * GetDamageTable(EQEmu::skills::SkillBackstab) / 100) * 10 * GetSkill(EQEmu::skills::SkillBackstab) / 355) + ((level - 25) / 3) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); - hate = (20 * backstab_dmg * GetSkill(EQEmu::skills::SkillBackstab) / 355); - } else { - max_hit = (((((2 * backstab_dmg) * GetDamageTable(EQEmu::skills::SkillBackstab) / 100) * 10 * GetSkill(EQEmu::skills::SkillBackstab) / 355) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); - hate = (20 * backstab_dmg * GetSkill(EQEmu::skills::SkillBackstab) / 355); - } + uint32 hate = 0; - if (level < 51) - min_hit = (level * 15 / 10); - else - min_hit = ((level * ( level * 5 - 105)) / 100); + int base_damage = GetBaseSkillDamage(EQEmu::skills::SkillBackstab, other); + hate = base_damage; - if (!other->CheckHitChance(this, EQEmu::skills::SkillBackstab, 0)) - ndamage = 0; - else { - if (min_damage) { - ndamage = min_hit; - } else { - if (max_hit < min_hit) - max_hit = min_hit; - - ndamage = (RuleB(Combat, UseIntervalAC) ? max_hit : zone->random.Int(min_hit, max_hit)); - } - } - } else - ndamage = -5; - - DoSpecialAttackDamage(other, EQEmu::skills::SkillBackstab, ndamage, min_hit, hate, ReuseTime); + DoSpecialAttackDamage(other, EQEmu::skills::SkillBackstab, base_damage, 0, hate, ReuseTime); DoAnim(anim1HPiercing); } @@ -5157,41 +5049,25 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if (!target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) dmg = 0; else { - if(RuleB(Combat, UseIntervalAC)) - dmg = GetBashDamage(); - else - dmg = zone->random.Int(1, GetBashDamage()); + dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); } } reuse = (BashReuseTime * 1000); - DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, 0, -1, reuse); did_attack = true; } } if (skill_to_use == EQEmu::skills::SkillFrenzy) { int AtkRounds = 3; - int skillmod = 0; - if (MaxSkill(EQEmu::skills::SkillFrenzy) > 0) - skillmod = (100 * GetSkill(EQEmu::skills::SkillFrenzy) / MaxSkill(EQEmu::skills::SkillFrenzy)); - - int32 max_dmg = (26 + ((((GetLevel() - 6) * 2) * skillmod) / 100)) * ((100 + RuleI(Combat, FrenzyBonus)) / 100); - int32 min_dmg = 0; + int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy); DoAnim(anim2HSlashing); - if (GetLevel() < 51) - min_dmg = 1; - else - min_dmg = (GetLevel() * 8 / 10); - - if (min_dmg > max_dmg) - max_dmg = min_dmg; - reuse = (FrenzyReuseTime * 1000); did_attack = true; while(AtkRounds > 0) { if (GetTarget() && (AtkRounds == 1 || zone->random.Int(0, 100) < 75)) { - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, min_dmg, max_dmg, reuse, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, 0, max_dmg, reuse, true); } AtkRounds--; @@ -5207,14 +5083,11 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if (!target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) dmg = 0; else { - if(RuleB(Combat, UseIntervalAC)) - dmg = GetKickDamage(); - else - dmg = zone->random.Int(1, GetKickDamage()); + dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); } } reuse = (KickReuseTime * 1000); - DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, 0, -1, reuse); did_attack = true; } } @@ -5249,26 +5122,6 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { classattack_timer.Start(reuse / HasteModifier); } -bool Bot::TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse) { - bool Result = false; - if (defender && (defender->GetBodyType() == BT_Humanoid) && (skillInUse == EQEmu::skills::SkillArchery) && (GetClass() == RANGER) && (GetLevel() >= 62)) { - int defenderLevel = defender->GetLevel(); - int rangerLevel = GetLevel(); - if(GetAA(aaHeadshot) && ((defenderLevel - 46) <= GetAA(aaHeadshot) * 2)) { - float AttackerChance = 0.20f + ((float)(rangerLevel - 51) * 0.005f); - float DefenderChance = (float)zone->random.Real(0.00f, 1.00f); - if(AttackerChance > DefenderChance) { - Log.Out(Logs::Detail, Logs::Combat, "Landed a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance); - entity_list.MessageClose(this, false, 200, MT_CritMelee, "%s has scored a leathal HEADSHOT!", GetName()); - defender->Damage(this, (defender->GetMaxHP()+50), SPELL_UNKNOWN, skillInUse); - Result = true; - } else - Log.Out(Logs::Detail, Logs::Combat, "FAILED a headshot: Attacker chance was %f and Defender chance was %f.", AttackerChance, DefenderChance); - } - } - return Result; -} - int32 Bot::CheckAggroAmount(uint16 spellid) { int32 AggroAmount = Mob::CheckAggroAmount(spellid, nullptr); int32 focusAggro = GetBotFocusEffect(BotfocusSpellHateMod, spellid); diff --git a/zone/bot.h b/zone/bot.h index 736a464ab..15a1b0938 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -206,9 +206,9 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None); virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr, int special = 0); + ExtraAttackOptions *opts = nullptr); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } virtual Raid* GetRaid() { return entity_list.GetRaidByMob(this); } @@ -239,7 +239,7 @@ public: uint16 BotGetSpellPriority(int spellslot) { return AIspells[spellslot].priority; } virtual float GetProcChances(float ProcBonus, uint16 hand); virtual int GetHandToHandDamage(void); - virtual bool TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse); + virtual bool TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse, int &damage); virtual void DoRiposte(Mob* defender); inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQEmu::skills::SkillOffense)) * 9 / 10); } inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } @@ -248,13 +248,12 @@ public: uint16 GetPrimarySkillValue(); uint16 MaxSkill(EQEmu::skills::SkillType skillid, uint16 class_, uint16 level) const; inline uint16 MaxSkill(EQEmu::skills::SkillType skillid) const { return MaxSkill(skillid, GetClass(), GetLevel()); } + virtual int GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target = nullptr); virtual void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance = false); virtual void TryBackstab(Mob *other,int ReuseTime = 10); virtual void RogueBackstab(Mob* other, bool min_damage = false, int ReuseTime = 10); virtual void RogueAssassinate(Mob* other); virtual void DoClassAttacks(Mob *target, bool IsRiposte=false); - virtual bool TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse); - virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0); virtual void ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int32 &mindmg); bool CanDoSpecialAttack(Mob *other); virtual int32 CheckAggroAmount(uint16 spellid); @@ -503,7 +502,6 @@ public: bool GetAltOutOfCombatBehavior() { return _altoutofcombatbehavior;} bool GetShowHelm() { return _showhelm; } - inline virtual int32 GetAC() const { return AC; } inline virtual int32 GetSTR() const { return STR; } inline virtual int32 GetSTA() const { return STA; } inline virtual int32 GetDEX() const { return DEX; } diff --git a/zone/client.cpp b/zone/client.cpp index ddf10d9d5..a066b9b12 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -6871,8 +6871,8 @@ void Client::SendStatsWindow(Client* client, bool use_window) /* DS */ indP << "DS: " << (itembonuses.DamageShield + spellbonuses.DamageShield*-1) << " (Spell: " << (spellbonuses.DamageShield*-1) << " + Item: " << itembonuses.DamageShield << " / " << RuleI(Character, ItemDamageShieldCap) << ")
" << /* Atk */ indP << "ATK: " << GetTotalATK() << "
" << /* Atk2 */ indP << "- Base: " << GetATKRating() << " | Item: " << itembonuses.ATK << " (" << RuleI(Character, ItemATKCap) << ")~Used: " << (itembonuses.ATK * 1.342) << " | Spell: " << spellbonuses.ATK << "
" << - /* AC */ indP << "AC: " << CalcAC() << "
" << - /* AC2 */ indP << "- Mit: " << GetACMit() << " | Avoid: " << GetACAvoid() << " | Spell: " << spellbonuses.AC << " | Shield: " << shield_ac << "
" << + /* AC */ indP << "AC: " << -1 << "
" << + /* AC2 */ indP << "- Mit: " << -1 << " | Avoid: " << -1 << " | Spell: " << spellbonuses.AC << " | Shield: " << shield_ac << "
" << /* Haste */ indP << "Haste: " << GetHaste() << "
" << /* Haste2 */ indP << " - Item: " << itembonuses.haste << " + Spell: " << (spellbonuses.haste + spellbonuses.hastetype2) << " (Cap: " << RuleI(Character, HasteCap) << ") | Over: " << (spellbonuses.hastetype3 + ExtraHaste) << "
" << /* RunSpeed*/ indP << "Runspeed: " << GetRunspeed() << "
" << @@ -6910,7 +6910,7 @@ void Client::SendStatsWindow(Client* client, bool use_window) client->Message(15, "~~~~~ %s %s ~~~~~", GetCleanName(), GetLastName()); client->Message(0, " Level: %i Class: %i Race: %i DS: %i/%i Size: %1.1f Weight: %.1f/%d ", GetLevel(), GetClass(), GetRace(), GetDS(), RuleI(Character, ItemDamageShieldCap), GetSize(), (float)CalcCurrentWeight() / 10.0f, GetSTR()); client->Message(0, " HP: %i/%i HP Regen: %i/%i",GetHP(), GetMaxHP(), CalcHPRegen(), CalcHPRegenCap()); - client->Message(0, " AC: %i ( Mit.: %i + Avoid.: %i + Spell: %i ) | Shield AC: %i", CalcAC(), GetACMit(), GetACAvoid(), spellbonuses.AC, shield_ac); + client->Message(0, " AC: %i ( Mit.: %i + Avoid.: %i + Spell: %i ) | Shield AC: %i", -1, -1, -1, spellbonuses.AC, shield_ac); if(CalcMaxMana() > 0) client->Message(0, " Mana: %i/%i Mana Regen: %i/%i", GetMana(), GetMaxMana(), CalcManaRegen(), CalcManaRegenCap()); client->Message(0, " End.: %i/%i End. Regen: %i/%i",GetEndurance(), GetMaxEndurance(), CalcEnduranceRegen(), CalcEnduranceRegenCap()); diff --git a/zone/client.h b/zone/client.h index 803540ffb..687ff04d6 100644 --- a/zone/client.h +++ b/zone/client.h @@ -221,18 +221,18 @@ public: //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None); virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr, int special = 0); + ExtraAttackOptions *opts = nullptr); virtual bool HasRaid() { return (GetRaid() ? true : false); } virtual bool HasGroup() { return (GetGroup() ? true : false); } virtual Raid* GetRaid() { return entity_list.GetRaidByClient(this); } virtual Group* GetGroup() { return entity_list.GetGroupByClient(this); } virtual inline bool IsBerserk() { return berserk; } - virtual int32 GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating); virtual void SetAttackTimer(); int GetQuiverHaste(int delay); void DoAttackRounds(Mob *target, int hand, bool IsFromSpell = false); + int DoDamageCaps(int base_damage); void AI_Init(); void AI_Start(uint32 iMoveDelay = 0); @@ -418,8 +418,6 @@ public: virtual void CalcBonuses(); //these are all precalculated now - inline virtual int32 GetAC() const { return AC; } - inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQEmu::skills::SkillOffense)) * 9 / 10); } inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } inline virtual int GetHaste() const { return Haste; } int GetRawACNoShield(int &shield_ac) const; @@ -1301,9 +1299,6 @@ private: void HandleTraderPriceUpdate(const EQApplicationPacket *app); - int32 CalcAC(); - int32 GetACMit(); - int32 GetACAvoid(); int32 CalcATK(); int32 CalcItemATKCap(); int32 CalcHaste(); diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index d9914fb26..3d3a1d529 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1025,111 +1025,6 @@ int32 Client::acmod() return 0; }; -// This is a testing formula for AC, the value this returns should be the same value as the one the client shows... -// ac1 and ac2 are probably the damage migitation and damage avoidance numbers, not sure which is which. -// I forgot to include the iksar defense bonus and i cant find my notes now... -// AC from spells are not included (cant even cast spells yet..) -int32 Client::CalcAC() -{ - // new formula - int avoidance = (acmod() + ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) * 16) / 9); - if (avoidance < 0) { - avoidance = 0; - } - - if (RuleB(Character, EnableAvoidanceCap)) { - if (avoidance > RuleI(Character, AvoidanceCap)) { - avoidance = RuleI(Character, AvoidanceCap); - } - } - - int mitigation = 0; - if (m_pp.class_ == WIZARD || m_pp.class_ == MAGICIAN || m_pp.class_ == NECROMANCER || m_pp.class_ == ENCHANTER) { - //something is wrong with this, naked casters have the wrong natural AC -// mitigation = (spellbonuses.AC/3) + (GetSkill(DEFENSE)/2) + (itembonuses.AC+1); - mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 4 + (itembonuses.AC + 1); - //this might be off by 4.. - mitigation -= 4; - } - else { -// mitigation = (spellbonuses.AC/4) + (GetSkill(DEFENSE)/3) + ((itembonuses.AC*4)/3); - mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 3 + ((itembonuses.AC * 4) / 3); - if (m_pp.class_ == MONK) { - mitigation += GetLevel() * 13 / 10; //the 13/10 might be wrong, but it is close... - } - } - int displayed = 0; - displayed += ((avoidance + mitigation) * 1000) / 847; //natural AC - //Iksar AC, untested - if (GetRace() == IKSAR) { - displayed += 12; - int iksarlevel = GetLevel(); - iksarlevel -= 10; - if (iksarlevel > 25) { - iksarlevel = 25; - } - if (iksarlevel > 0) { - displayed += iksarlevel * 12 / 10; - } - } - // Shield AC bonus for HeroicSTR - if (itembonuses.HeroicSTR) { - bool equiped = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary); - if (equiped) { - uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary)->GetItem()->ItemType; - if (shield == EQEmu::item::ItemTypeShield) { - displayed += itembonuses.HeroicSTR / 2; - } - } - } - //spell AC bonuses are added directly to natural total - displayed += spellbonuses.AC; - AC = displayed; - return (AC); -} - -int32 Client::GetACMit() -{ - int mitigation = 0; - if (m_pp.class_ == WIZARD || m_pp.class_ == MAGICIAN || m_pp.class_ == NECROMANCER || m_pp.class_ == ENCHANTER) { - mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 4 + (itembonuses.AC + 1); - mitigation -= 4; - } - else { - mitigation = (GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) / 3 + ((itembonuses.AC * 4) / 3); - if (m_pp.class_ == MONK) { - mitigation += GetLevel() * 13 / 10; //the 13/10 might be wrong, but it is close... - } - } - // Shield AC bonus for HeroicSTR - if (itembonuses.HeroicSTR) { - bool equiped = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary); - if (equiped) { - uint8 shield = CastToClient()->m_inv.GetItem(EQEmu::inventory::slotSecondary)->GetItem()->ItemType; - if (shield == EQEmu::item::ItemTypeShield) { - mitigation += itembonuses.HeroicSTR / 2; - } - } - } - return (mitigation * 1000 / 847); -} - -int32 Client::GetACAvoid() -{ - int32 avoidance = (acmod() + ((GetSkill(EQEmu::skills::SkillDefense) + itembonuses.HeroicAGI / 10) * 16) / 9); - if (avoidance < 0) { - avoidance = 0; - } - - if (RuleB(Character, EnableAvoidanceCap)) { - if ((avoidance * 1000 / 847) > RuleI(Character, AvoidanceCap)) { - return RuleI(Character, AvoidanceCap); - } - } - - return (avoidance * 1000 / 847); -} - int32 Client::CalcMaxMana() { switch (GetCasterClass()) { diff --git a/zone/common.h b/zone/common.h index e621c336b..5a6782148 100644 --- a/zone/common.h +++ b/zone/common.h @@ -638,5 +638,11 @@ struct ExtraAttackOptions { }; +struct DamageTable { + int32 max_extra; // max extra damage + int32 chance; // chance not to apply? + int32 minusfactor; // difficulty of rolling +}; + #endif diff --git a/zone/corpse.h b/zone/corpse.h index 49b1cba39..e601f2aa3 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -52,8 +52,8 @@ class Corpse : public Mob { /* Corpse: General */ virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; } - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } - virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) { return false; } + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) { return; } + virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = true, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) { return false; } virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } diff --git a/zone/encounter.h b/zone/encounter.h index 8b672fdd4..e0d8dbcb0 100644 --- a/zone/encounter.h +++ b/zone/encounter.h @@ -35,9 +35,9 @@ public: //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { return true; } - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) { return; } + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) { return; } virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, - ExtraAttackOptions *opts = nullptr, int special = 0) { + ExtraAttackOptions *opts = nullptr) { return false; } virtual bool HasRaid() { return false; } diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index b98ca6923..34519b69f 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -553,7 +553,7 @@ int HateList::AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOption auto mob = entity_list.GetMobID(id); if (mob) { ++hit_count; - caster->ProcessAttackRounds(mob, opts, 1); + caster->ProcessAttackRounds(mob, opts); } } diff --git a/zone/merc.cpp b/zone/merc.cpp index 6dc00836b..6021f05d5 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -4432,13 +4432,8 @@ void Merc::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) { - if(RuleB(Combat, UseIntervalAC)) - dmg = GetKickDamage(); - else - dmg = zone->random.Int(1, GetKickDamage()); - - } + if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) + dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick, GetTarget()); } reuse = KickReuseTime * 1000; @@ -4454,12 +4449,8 @@ void Merc::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) { - if(RuleB(Combat, UseIntervalAC)) - dmg = GetBashDamage(); - else - dmg = zone->random.Int(1, GetBashDamage()); - } + if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) + dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash, GetTarget()); } reuse = BashReuseTime * 1000; @@ -4474,7 +4465,7 @@ void Merc::DoClassAttacks(Mob *target) { classattack_timer.Start(reuse / HasteModifier); } -bool Merc::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, int special) +bool Merc::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { if (!other) { SetTarget(nullptr); @@ -4485,7 +4476,7 @@ bool Merc::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, boo return NPC::Attack(other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts); } -void Merc::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, int special) +void Merc::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable, int8 buffslot, bool iBuffTic, eSpecialAttacks special) { if(IsDead() || IsCorpse()) return; diff --git a/zone/merc.h b/zone/merc.h index b563775b0..7bd4c2b9b 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -65,9 +65,9 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None); virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, - bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return (GetGroup() ? true : false); } virtual Raid* GetRaid() { return 0; } @@ -197,7 +197,6 @@ public: virtual void CalcBonuses(); int32 GetEndurance() const {return cur_end;} //This gets our current endurance inline uint8 GetEndurancePercent() { return (uint8)((float)cur_end / (float)max_end * 100.0f); } - inline virtual int32 GetAC() const { return AC; } inline virtual int32 GetATK() const { return ATK; } inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } int32 GetRawACNoShield(int &shield_ac) const; diff --git a/zone/mob.cpp b/zone/mob.cpp index c47788ee5..c5b61f546 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -109,7 +109,9 @@ Mob::Mob(const char* in_name, m_TargetV(glm::vec3()), flee_timer(FLEE_CHECK_TIMER), m_Position(position), - tmHidden(-1) + tmHidden(-1), + mitigation_ac(0), + m_specialattacks(eSpecialAttacks::None) { targeted = 0; tar_ndx=0; @@ -4643,7 +4645,7 @@ void Mob::SetRaidGrouped(bool v) } } -int16 Mob::GetCriticalChanceBonus(uint16 skill) +int Mob::GetCriticalChanceBonus(uint16 skill) { int critical_chance = 0; diff --git a/zone/mob.h b/zone/mob.h index a581ea819..802eede5c 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -54,6 +54,13 @@ namespace EQEmu class ItemInstance; } +enum class eSpecialAttacks : int { + None, + Rampage, + AERampage, + ChaoticStab +}; + class Mob : public Entity { public: enum CLIENT_CONN_STATUS { CLIENT_CONNECTING, CLIENT_CONNECTED, CLIENT_LINKDEAD, @@ -152,45 +159,51 @@ public: float HeadingAngleToMob(Mob *other); // to keep consistent with client generated messages virtual void RangedAttack(Mob* other) { } virtual void ThrowingAttack(Mob* other) { } - uint16 GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg); // 13 = Primary (default), 14 = secondary virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, - bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0) = 0; + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) = 0; int MonkSpecialAttack(Mob* other, uint8 skill_used); virtual void TryBackstab(Mob *other,int ReuseTime = 10); - bool AvoidDamage(Mob* attacker, int32 &damage, int hand); + bool AvoidDamage(Mob* attacker, int &damage, int hand); int compute_tohit(EQEmu::skills::SkillType skillinuse); int compute_defense(); - virtual bool CheckHitChance(Mob* attacker, EQEmu::skills::SkillType skillinuse, int chance_mod = 0); - virtual void TryCriticalHit(Mob *defender, uint16 skill, int32 &damage, ExtraAttackOptions *opts = nullptr); - void TryPetCriticalHit(Mob *defender, uint16 skill, int32 &damage); - virtual bool TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse); - uint32 TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse); - uint32 TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, uint16 ReuseTime); + bool CheckHitChance(Mob* attacker, EQEmu::skills::SkillType skillinuse, int chance_mod = 0); + virtual void TryCriticalHit(Mob *defender, uint16 skill, int &damage, int min_damage, ExtraAttackOptions *opts = nullptr); + void TryPetCriticalHit(Mob *defender, uint16 skill, int &damage); + virtual bool TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse, int &damage); + int TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse); + int TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, uint16 ReuseTime); virtual void DoRiposte(Mob* defender); - void ApplyMeleeDamageBonus(uint16 skill, int32 &damage,ExtraAttackOptions *opts = nullptr); - virtual void MeleeMitigation(Mob *attacker, int32 &damage, int32 minhit, ExtraAttackOptions *opts = nullptr); - virtual int32 GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating); + void ApplyMeleeDamageBonus(uint16 skill, int &damage,ExtraAttackOptions *opts = nullptr); + int ACSum(); + int offense(EQEmu::skills::SkillType skill); + void CalcAC() { mitigation_ac = ACSum(); } + int GetACSoftcap(); + double GetSoftcapReturns(); + int GetClassRaceACBonus(); + inline int GetMitigationAC() { return mitigation_ac; } + void MeleeMitigation(Mob *attacker, int &damage, int base_damage, int offense, EQEmu::skills::SkillType, ExtraAttackOptions *opts = nullptr); + double RollD20(double offense, double mitigation); // CALL THIS FROM THE DEFENDER bool CombatRange(Mob* other); virtual inline bool IsBerserk() { return false; } // only clients void RogueEvade(Mob *other); - void CommonOutgoingHitSuccess(Mob* defender, int32 &damage, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts = nullptr); + void CommonOutgoingHitSuccess(Mob* defender, int &damage, int min_damage, int min_mod, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts = nullptr); void BreakInvisibleSpells(); virtual void CancelSneakHide(); void CommonBreakInvisible(); void CommonBreakInvisibleFromCombat(); bool HasDied(); virtual bool CheckDualWield(); - void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0); - void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0); + void DoMainHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); + void DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr); virtual bool CheckDoubleAttack(); // inline process for places where we need to do them outside of the AI_Process - void ProcessAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr, int special = 0) + void ProcessAttackRounds(Mob *target, ExtraAttackOptions *opts = nullptr) { if (target) { - DoMainHandAttackRounds(target, opts, special); + DoMainHandAttackRounds(target, opts); if (CanThisClassDualWield()) - DoOffHandAttackRounds(target, opts, special); + DoOffHandAttackRounds(target, opts); } return; } @@ -367,7 +380,7 @@ public: bool AffectedBySpellExcludingSlot(int slot, int effect); virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) = 0; virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, - bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0) = 0; + bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) = 0; inline virtual void SetHP(int32 hp) { if (hp >= max_hp) cur_hp = max_hp; else cur_hp = hp;} bool ChangeHP(Mob* other, int32 amount, uint16 spell_id = 0, int8 buffslot = -1, bool iBuffTic = false); inline void SetOOCRegen(int32 newoocregen) {oocregen = newoocregen;} @@ -406,7 +419,7 @@ public: virtual void SetTarget(Mob* mob); virtual inline float GetHPRatio() const { return max_hp == 0 ? 0 : ((float)cur_hp/max_hp*100); } virtual inline int GetIntHPRatio() const { return max_hp == 0 ? 0 : static_cast(cur_hp * 100 / max_hp); } - inline virtual int32 GetAC() const { return AC + itembonuses.AC + spellbonuses.AC; } + inline int32 GetAC() const { return AC; } inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK; } inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } inline virtual int32 GetSTR() const { return STR + itembonuses.STR + spellbonuses.STR; } @@ -673,7 +686,7 @@ public: int16 GetMeleeMinDamageMod_SE(uint16 skill); int16 GetCrippBlowChance(); int16 GetSkillReuseTime(uint16 skill); - int16 GetCriticalChanceBonus(uint16 skill); + int GetCriticalChanceBonus(uint16 skill); int16 GetSkillDmgAmt(uint16 skill); bool TryReflectSpell(uint32 spell_id); bool CanBlockSpell() const { return(spellbonuses.BlockNextSpell); } @@ -778,7 +791,8 @@ public: int32 GetMeleeMitigation(); uint8 GetWeaponDamageBonus(const EQEmu::ItemData* weapon, bool offhand = false); - uint16 GetDamageTable(EQEmu::skills::SkillType skillinuse); + const DamageTable &GetDamageTable() const; + void ApplyDamageTable(int &damage, int offense); virtual int GetHandToHandDamage(void); bool CanThisClassDoubleAttack(void) const; @@ -801,9 +815,9 @@ public: int32 AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker); int32 ReduceAllDamage(int32 damage); - virtual void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool CheckHitChance = false, bool CanAvoid = true); + void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int base_damage, int min_damage = 0, int32 hate_override = -1, int ReuseTime = 10, bool CheckHitChance = false, bool CanAvoid = true); virtual void DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon = nullptr, const EQEmu::ItemData* AmmoItem = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, int AmmoSlot = 0, float speed = 4.0f); - virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0); + void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0); virtual void DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon = nullptr, const EQEmu::ItemInstance* Ammo = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, uint32 ammo_id = 0, const EQEmu::ItemData *AmmoItem = nullptr, int AmmoSlot = 0, float speed = 4.0f); bool TryProjectileAttack(Mob* other, const EQEmu::ItemData *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const EQEmu::ItemInstance* RangeWeapon, const EQEmu::ItemInstance* Ammo, int AmmoSlot, float speed); void ProjectileAttack(); @@ -816,6 +830,7 @@ public: bool AddRampage(Mob*); void ClearRampage(); void AreaRampage(ExtraAttackOptions *opts); + inline bool IsSpecialAttack(eSpecialAttacks in) { return m_specialattacks == in; } void StartEnrage(); void ProcessEnrage(); @@ -1042,7 +1057,7 @@ public: #endif protected: - void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const EQEmu::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, int special = 0); + void CommonDamage(Mob* other, int &damage, const uint16 spell_id, const EQEmu::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None); static uint16 GetProcID(uint16 spell_id, uint8 effect_index); float _GetMovementSpeed(int mod) const; int _GetWalkSpeed() const; @@ -1079,6 +1094,7 @@ protected: bool multitexture; int AC; + int mitigation_ac; // cached Mob::ACSum int32 ATK; int32 STR; int32 STA; @@ -1150,6 +1166,7 @@ protected: int base_walkspeed; int base_fearspeed; int current_speed; + eSpecialAttacks m_specialattacks; uint32 pLastChange; bool held; @@ -1174,9 +1191,10 @@ protected: uint16 GetWeaponSpeedbyHand(uint16 hand); int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item); int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr); - int GetKickDamage(); - int GetBashDamage(); - virtual void ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int32 &mindmg); +#ifdef BOTS + virtual +#endif + int GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target = nullptr); virtual int16 GetFocusEffect(focusType type, uint16 spell_id) { return 0; } void CalculateNewFearpoint(); float FindGroundZ(float new_x, float new_y, float z_offset=0.0); @@ -1211,7 +1229,7 @@ protected: Timer attack_dw_timer; Timer ranged_timer; float attack_speed; //% increase/decrease in attack speed (not haste) - int8 attack_delay; //delay between attacks in 10ths of seconds + int attack_delay; //delay between attacks in 10ths of seconds int16 slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%) Timer tic_timer; Timer mana_timer; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 836cd086f..d2340581d 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1160,11 +1160,8 @@ void Mob::AI_Process() { if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ if (spellbonuses.PC_Pet_Rampage[0] || itembonuses.PC_Pet_Rampage[0] || aabonuses.PC_Pet_Rampage[0]){ int chance = spellbonuses.PC_Pet_Rampage[0] + itembonuses.PC_Pet_Rampage[0] + aabonuses.PC_Pet_Rampage[0]; - int dmg_mod = spellbonuses.PC_Pet_Rampage[1] + itembonuses.PC_Pet_Rampage[1] + aabonuses.PC_Pet_Rampage[1]; if(zone->random.Roll(chance)) { - ExtraAttackOptions opts; - opts.damage_percent = dmg_mod / 100.0f; - Rampage(&opts); + Rampage(nullptr); } } } @@ -1175,12 +1172,7 @@ void Mob::AI_Process() { rampage_chance = rampage_chance > 0 ? rampage_chance : 20; if(zone->random.Roll(rampage_chance)) { ExtraAttackOptions opts; - int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 2); - if(cur > 0) { - opts.damage_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 3); + int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 3); if(cur > 0) { opts.damage_flat = cur; } @@ -1215,12 +1207,7 @@ void Mob::AI_Process() { rampage_chance = rampage_chance > 0 ? rampage_chance : 20; if(zone->random.Roll(rampage_chance)) { ExtraAttackOptions opts; - int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 2); - if(cur > 0) { - opts.damage_percent = cur / 100.0f; - } - - cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 3); + int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 3); if(cur > 0) { opts.damage_flat = cur; } @@ -1992,6 +1979,8 @@ bool Mob::Rampage(ExtraAttackOptions *opts) rampage_targets = RuleI(Combat, DefaultRampageTargets); if (rampage_targets > RuleI(Combat, MaxRampageTargets)) rampage_targets = RuleI(Combat, MaxRampageTargets); + + m_specialattacks = eSpecialAttacks::Rampage; for (int i = 0; i < RampageArray.size(); i++) { if (index_hit >= rampage_targets) break; @@ -2001,14 +1990,16 @@ bool Mob::Rampage(ExtraAttackOptions *opts) if (m_target == GetTarget()) continue; if (CombatRange(m_target)) { - ProcessAttackRounds(m_target, opts, 2); + ProcessAttackRounds(m_target, opts); index_hit++; } } } if (RuleB(Combat, RampageHitsTarget) && index_hit < rampage_targets) - ProcessAttackRounds(GetTarget(), opts, 2); + ProcessAttackRounds(GetTarget(), opts); + + m_specialattacks = eSpecialAttacks::None; return true; } @@ -2024,10 +2015,12 @@ void Mob::AreaRampage(ExtraAttackOptions *opts) int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1); rampage_targets = rampage_targets > 0 ? rampage_targets : -1; + m_specialattacks = eSpecialAttacks::AERampage; index_hit = hate_list.AreaRampage(this, GetTarget(), rampage_targets, opts); if(index_hit == 0) - ProcessAttackRounds(GetTarget(), opts, 1); + ProcessAttackRounds(GetTarget(), opts); + m_specialattacks = eSpecialAttacks::None; } uint32 Mob::GetLevelCon(uint8 mylevel, uint8 iOtherLevel) { diff --git a/zone/npc.cpp b/zone/npc.cpp index d1255f8aa..ebff4786a 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -201,6 +201,9 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if CalcNPCDamage(); } + base_damage = round((max_dmg - min_dmg) / 1.9); + min_damage = min_dmg - round(base_damage / 10.0); + accuracy_rating = d->accuracy_rating; avoidance_rating = d->avoidance_rating; ATK = d->ATK; @@ -1054,7 +1057,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* npc_type->WIS = 150; npc_type->CHA = 150; - npc_type->attack_delay = 30; + npc_type->attack_delay = 3000; npc_type->prim_melee_type = 28; npc_type->sec_melee_type = 28; @@ -1984,13 +1987,25 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) else if(id == "special_attacks") { NPCSpecialAttacks(val.c_str(), 0, 1); return; } else if(id == "special_abilities") { ProcessSpecialAbilities(val.c_str()); return; } else if(id == "attack_speed") { attack_speed = (float)atof(val.c_str()); CalcBonuses(); return; } - else if(id == "attack_delay") { attack_delay = atoi(val.c_str()); CalcBonuses(); return; } + else if(id == "attack_delay") { /* TODO: fix DB */attack_delay = atoi(val.c_str()) * 100; CalcBonuses(); return; } else if(id == "atk") { ATK = atoi(val.c_str()); return; } else if(id == "accuracy") { accuracy_rating = atoi(val.c_str()); return; } else if(id == "avoidance") { avoidance_rating = atoi(val.c_str()); return; } else if(id == "trackable") { trackable = atoi(val.c_str()); return; } - else if(id == "min_hit") { min_dmg = atoi(val.c_str()); return; } - else if(id == "max_hit") { max_dmg = atoi(val.c_str()); return; } + else if(id == "min_hit") { + min_dmg = atoi(val.c_str()); + // TODO: fix DB + base_damage = round((max_dmg - min_dmg) / 1.9); + min_damage = min_dmg - round(base_damage / 10.0); + return; + } + else if(id == "max_hit") { + max_dmg = atoi(val.c_str()); + // TODO: fix DB + base_damage = round((max_dmg - min_dmg) / 1.9); + min_damage = min_dmg - round(base_damage / 10.0); + return; + } else if(id == "attack_count") { attack_count = atoi(val.c_str()); return; } else if(id == "see_invis") { see_invis = atoi(val.c_str()); return; } else if(id == "see_invis_undead") { see_invis_undead = atoi(val.c_str()); return; } diff --git a/zone/npc.h b/zone/npc.h index 4b81d45a6..543725c28 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -109,9 +109,9 @@ public: //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); - virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, int special = 0); + virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None); virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, - bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr, int special = 0); + bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr); virtual bool HasRaid() { return false; } virtual bool HasGroup() { return false; } virtual Raid* GetRaid() { return 0; } @@ -259,9 +259,11 @@ public: uint32 GetMaxDMG() const {return max_dmg;} uint32 GetMinDMG() const {return min_dmg;} + int GetBaseDamage() const { return base_damage; } + int GetMinDamage() const { return min_damage; } float GetSlowMitigation() const { return slow_mitigation; } float GetAttackSpeed() const {return attack_speed;} - uint8 GetAttackDelay() const {return attack_delay;} + int GetAttackDelay() const {return attack_delay;} bool IsAnimal() const { return(bodytype == BT_Animal); } uint16 GetPetSpellID() const {return pet_spell_id;} void SetPetSpellID(uint16 amt) {pet_spell_id = amt;} @@ -463,6 +465,8 @@ protected: uint32 max_dmg; uint32 min_dmg; + int base_damage; + int min_damage; int32 accuracy_rating; int32 avoidance_rating; int16 attack_count; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 86eb01921..03e4a7d90 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -26,96 +26,138 @@ #include - -int Mob::GetKickDamage() { - int multiple=(GetLevel()*100/5); - multiple += 100; - int32 dmg = (((GetSkill(EQEmu::skills::SkillKick) + GetSTR() + GetLevel()) * 100 / 9000) * multiple) + 600; //Set a base of 6 damage, 1 seemed too low at the sub level 30 level. - if(GetClass() == WARRIOR || GetClass() == WARRIORGM ||GetClass() == BERSERKER || GetClass() == BERSERKERGM) { - dmg*=12/10;//small increase for warriors +int Mob::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target) +{ + int base = EQEmu::skills::GetBaseDamage(skill); + auto skill_level = GetSkill(skill); + switch (skill) { + case EQEmu::skills::SkillDragonPunch: + case EQEmu::skills::SkillEagleStrike: + case EQEmu::skills::SkillTigerClaw: + if (skill_level >= 25) + base++; + if (skill_level >= 75) + base++; + if (skill_level >= 125) + base++; + if (skill_level >= 175) + base++; + return base; + case EQEmu::skills::SkillFrenzy: + if (IsClient() && CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary)) { + if (GetLevel() > 15) + base += GetLevel() - 15; + if (base > 23) + base = 23; + if (GetLevel() > 50) + base += 2; + if (GetLevel() > 54) + base++; + if (GetLevel() > 59) + base++; + } + return base; + case EQEmu::skills::SkillFlyingKick: { + float skill_bonus = skill_level / 9.0f; + float ac_bonus = 0.0f; + if (IsClient()) { + auto inst = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotFeet); + if (inst) + ac_bonus = inst->GetItemArmorClass(true) / 25.0f; + } + if (ac_bonus > skill_bonus) + ac_bonus = skill_bonus; + return static_cast(ac_bonus + skill_bonus); } - dmg /= 100; - - int32 mindmg = 1; - ApplySpecialAttackMod(EQEmu::skills::SkillKick, dmg, mindmg); - - dmg = mod_kick_damage(dmg); - - return(dmg); -} - -int Mob::GetBashDamage() { - int multiple=(GetLevel()*100/5); - multiple += 100; - - //this is complete shite - int32 dmg = ((((GetSkill(EQEmu::skills::SkillBash) + GetSTR()) * 100 + GetLevel() * 100 / 2) / 10000) * multiple) + 600; //Set a base of 6 damage, 1 seemed too low at the sub level 30 level. - dmg /= 100; - - int32 mindmg = 1; - ApplySpecialAttackMod(EQEmu::skills::SkillBash, dmg, mindmg); - - dmg = mod_bash_damage(dmg); - - return(dmg); -} - -void Mob::ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int32 &mindmg) { - int item_slot = -1; - //1: Apply bonus from AC (BOOT/SHIELD/HANDS) est. 40AC=6dmg - if (IsClient()){ - switch (skill) { - case EQEmu::skills::SkillFlyingKick: - case EQEmu::skills::SkillRoundKick: - case EQEmu::skills::SkillKick: - item_slot = EQEmu::inventory::slotFeet; - break; - case EQEmu::skills::SkillBash: - item_slot = EQEmu::inventory::slotSecondary; - break; - case EQEmu::skills::SkillDragonPunch: - case EQEmu::skills::SkillEagleStrike: - case EQEmu::skills::SkillTigerClaw: - item_slot = EQEmu::inventory::slotHands; - break; - default: - break; + case EQEmu::skills::SkillKick: { + // there is some base *= 4 case in here? + float skill_bonus = skill_level / 10.0f; + float ac_bonus = 0.0f; + if (IsClient()) { + auto inst = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotFeet); + if (inst) + ac_bonus = inst->GetItemArmorClass(true) / 25.0f; } - - if (item_slot >= 0){ - const EQEmu::ItemInstance* itm = nullptr; - itm = CastToClient()->GetInv().GetItem(item_slot); - if(itm) - dmg += itm->GetItem()->AC * (RuleI(Combat, SpecialAttackACBonus))/100; + if (ac_bonus > skill_bonus) + ac_bonus = skill_bonus; + return static_cast(ac_bonus + skill_bonus); + } + case EQEmu::skills::SkillBash: { + float skill_bonus = skill_level / 10.0f; + float ac_bonus = 0.0f; + const EQEmu::ItemInstance *inst = nullptr; + if (IsClient()) { + if (HasShieldEquiped()) + inst = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); + else if (HasTwoHanderEquipped()) + inst = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); } + if (inst) + ac_bonus = inst->GetItemArmorClass(true) / 25.0f; + if (ac_bonus > skill_bonus) + ac_bonus = skill_bonus; + return static_cast(ac_bonus + skill_bonus); + } + case EQEmu::skills::SkillBackstab: { + float skill_bonus = static_cast(skill_level) * 0.02f; + base = 3; // There seems to be a base 3 for NPCs or some how BS w/o weapon? + // until we get a better inv system for NPCs they get nerfed! + if (IsClient()) { + auto *inst = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); + if (inst && inst->GetItem() && inst->GetItem()->ItemType == EQEmu::item::ItemType1HPiercing) { + base = inst->GetItemBackstabDamage(true); + if (!inst->GetItemBackstabDamage()) + base += inst->GetItemWeaponDamage(true); + if (target) { + if (inst->GetItemElementalFlag(true) && inst->GetItemElementalDamage(true)) + base += target->ResistElementalWeaponDmg(inst); + if (inst->GetItemBaneDamageBody(true) || inst->GetItemBaneDamageRace(true)) + base += target->CheckBaneDamage(inst); + } + } + } else if (IsNPC()) { + auto *npc = CastToNPC(); + base = std::max(base, npc->GetBaseDamage()); + // parses show relatively low BS mods from lots of NPCs, so either their BS skill is super low + // or their mod is divided again, this is probably not the right mod, but it's better + skill_bonus /= 3.0f; + } + // ahh lets make sure everything is casted right :P ugly but w/e + return static_cast(static_cast(base) * (skill_bonus + 2.0f)); + } + default: + return 0; } } -void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 max_damage, int32 min_damage, int32 hate_override, int ReuseTime, - bool CheckHitChance, bool CanAvoid) { - //this really should go through the same code as normal melee damage to - //pick up all the special behavior there +void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, + int32 hate_override, int ReuseTime, bool CheckHitChance, bool CanAvoid) +{ + // this really should go through the same code as normal melee damage to + // pick up all the special behavior there - if ((who == nullptr || ((IsClient() && CastToClient()->dead) || (who->IsClient() && who->CastToClient()->dead)) || HasDied() || (!IsAttackAllowed(who)))) + if ((who == nullptr || + ((IsClient() && CastToClient()->dead) || (who->IsClient() && who->CastToClient()->dead)) || HasDied() || + (!IsAttackAllowed(who)))) return; - - if(who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE)) - max_damage = -5; + + int damage = 0; + + if (who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE)) + damage = -5; if (who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE) && skill != EQEmu::skills::SkillBackstab) - max_damage = -5; + damage = -5; - uint32 hate = max_damage; - if(hate_override > -1) + uint32 hate = base_damage; + if (hate_override > -1) hate = hate_override; - if (skill == EQEmu::skills::SkillBash){ - if(IsClient()){ + if (skill == EQEmu::skills::SkillBash) { + if (IsClient()) { EQEmu::ItemInstance *item = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); - if(item) - { - if (item->GetItem()->ItemType == EQEmu::item::ItemTypeShield) - { + if (item) { + if (item->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { hate += item->GetItem()->AC; } const EQEmu::ItemData *itm = item->GetItem(); @@ -127,46 +169,54 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 } } - min_damage += min_damage * GetMeleeMinDamageMod_SE(skill) / 100; + int min_cap = base_damage * GetMeleeMinDamageMod_SE(skill) / 100; - int hand = EQEmu::inventory::slotPrimary; // Avoid checks hand for throwing/archery exclusion, primary should work for most + auto offense = this->offense(skill); + + int hand = EQEmu::inventory::slotPrimary; // Avoid checks hand for throwing/archery exclusion, primary should + // work for most if (skill == EQEmu::skills::SkillThrowing || skill == EQEmu::skills::SkillArchery) hand = EQEmu::inventory::slotRange; - if (who->AvoidDamage(this, max_damage, hand)) { - if (max_damage == -3) + if (who->AvoidDamage(this, damage, hand)) { + if (damage == -3) DoRiposte(who); } else { - if (!CheckHitChance || (CheckHitChance && who->CheckHitChance(this, skill))) { - who->MeleeMitigation(this, max_damage, min_damage); - CommonOutgoingHitSuccess(who, max_damage, skill); + if (!CheckHitChance || who->CheckHitChance(this, skill)) { + if (base_damage > 0) // we do this weird, so we have to check it first :( + who->MeleeMitigation(this, damage, base_damage, offense, skill); + if (damage > 0) { + ApplyDamageTable(damage, offense); + CommonOutgoingHitSuccess(who, damage, min_damage, min_cap, skill); + } } else { - max_damage = 0; + damage = 0; } } who->AddToHateList(this, hate, 0, false); - if (max_damage > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == skill && + if (damage > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == skill && IsValidSpell(aabonuses.SkillAttackProc[2])) { float chance = aabonuses.SkillAttackProc[0] / 1000.0f; if (zone->random.Roll(chance)) SpellFinished(aabonuses.SkillAttackProc[2], who, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } - who->Damage(this, max_damage, SPELL_UNKNOWN, skill, false); + who->Damage(this, damage, SPELL_UNKNOWN, skill, false); - //Make sure 'this' has not killed the target and 'this' is not dead (Damage shield ect). - if(!GetTarget())return; - if (HasDied()) return; + // Make sure 'this' has not killed the target and 'this' is not dead (Damage shield ect). + if (!GetTarget()) + return; + if (HasDied()) + return; if (HasSkillProcs()) - TrySkillProc(who, skill, ReuseTime*1000); - - if (max_damage > 0 && HasSkillProcSuccess()) - TrySkillProc(who, skill, ReuseTime*1000, true); + TrySkillProc(who, skill, ReuseTime * 1000); + if (damage > 0 && HasSkillProcSuccess()) + TrySkillProc(who, skill, ReuseTime * 1000, true); } - +// We should probably refactor this to take the struct not the packet void Client::OPCombatAbility(const EQApplicationPacket *app) { if(!GetTarget()) return; @@ -251,20 +301,16 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { else{ if (!GetTarget()->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) { dmg = 0; - ht = GetBashDamage(); + ht = GetBaseSkillDamage(EQEmu::skills::SkillBash, GetTarget()); } else{ - if(RuleB(Combat, UseIntervalAC)) - ht = dmg = GetBashDamage(); - else - ht = dmg = zone->random.Int(1, GetBashDamage()); - + ht = dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash, GetTarget()); } } ReuseTime = BashReuseTime-1-skill_reduction; ReuseTime = (ReuseTime*HasteMod)/100; - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillBash, dmg, 1, ht, ReuseTime); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillBash, dmg, 0, ht, ReuseTime); if(ReuseTime > 0) { p_timers.Start(timer, ReuseTime); @@ -276,28 +322,18 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { if ((ca_atk->m_atk == 100) && (ca_atk->m_skill == EQEmu::skills::SkillFrenzy)){ CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10); int AtkRounds = 3; - int skillmod = 100 * GetSkill(EQEmu::skills::SkillFrenzy) / MaxSkill(EQEmu::skills::SkillFrenzy); - int32 max_dmg = (26 + ((((GetLevel()-6) * 2)*skillmod)/100)) * ((100+RuleI(Combat, FrenzyBonus))/100); - int32 min_dmg = 0; + int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy, GetTarget()); DoAnim(anim2HSlashing); max_dmg = mod_frenzy_damage(max_dmg); - if (GetLevel() < 51) - min_dmg = 1; - else - min_dmg = GetLevel()*8/10; - - if (min_dmg > max_dmg) - max_dmg = min_dmg; - ReuseTime = FrenzyReuseTime-1-skill_reduction; ReuseTime = (ReuseTime*HasteMod)/100; //Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit. while(AtkRounds > 0) { if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, min_dmg, max_dmg, ReuseTime, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, 0, max_dmg, ReuseTime, true); } AtkRounds--; } @@ -327,18 +363,15 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { else{ if (!GetTarget()->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) { dmg = 0; - ht = GetKickDamage(); + ht = GetBaseSkillDamage(EQEmu::skills::SkillKick, GetTarget()); } else{ - if(RuleB(Combat, UseIntervalAC)) - ht = dmg = GetKickDamage(); - else - ht = dmg = zone->random.Int(1, GetKickDamage()); + ht = dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick, GetTarget()); } } ReuseTime = KickReuseTime-1-skill_reduction; - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillKick, dmg, 1, ht, ReuseTime); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillKick, dmg, 0, ht, ReuseTime); } break; @@ -395,99 +428,91 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { } //returns the reuse time in sec for the special attack used. -int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type) +int Mob::MonkSpecialAttack(Mob *other, uint8 unchecked_type) { - if(!other) + if (!other) return 0; int32 ndamage = 0; int32 max_dmg = 0; - int32 min_dmg = 1; + int32 min_dmg = 0; int reuse = 0; - EQEmu::skills::SkillType skill_type; //to avoid casting... even though it "would work" + EQEmu::skills::SkillType skill_type; // to avoid casting... even though it "would work" uint8 itemslot = EQEmu::inventory::slotFeet; + if (IsNPC()) { + auto *npc = CastToNPC(); + min_dmg = npc->GetMinDamage(); + } - switch(unchecked_type) { + switch (unchecked_type) { case EQEmu::skills::SkillFlyingKick: skill_type = EQEmu::skills::SkillFlyingKick; - max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, FlyingKickBonus) / 100) + 35; - min_dmg = ((level*8)/10); - ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); + max_dmg = GetBaseSkillDamage(skill_type); + min_dmg = 0; // revamped FK formula is missing the min mod? DoAnim(animFlyingKick); reuse = FlyingKickReuseTime; break; case EQEmu::skills::SkillDragonPunch: skill_type = EQEmu::skills::SkillDragonPunch; - max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, DragonPunchBonus) / 100) + 26; + max_dmg = GetBaseSkillDamage(skill_type); itemslot = EQEmu::inventory::slotHands; - ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animTailRake); reuse = TailRakeReuseTime; break; case EQEmu::skills::SkillEagleStrike: skill_type = EQEmu::skills::SkillEagleStrike; - max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, EagleStrikeBonus) / 100) + 19; + max_dmg = GetBaseSkillDamage(skill_type); itemslot = EQEmu::inventory::slotHands; - ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animEagleStrike); reuse = EagleStrikeReuseTime; break; case EQEmu::skills::SkillTigerClaw: skill_type = EQEmu::skills::SkillTigerClaw; - max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, TigerClawBonus) / 100) + 12; + max_dmg = GetBaseSkillDamage(skill_type); itemslot = EQEmu::inventory::slotHands; - ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); DoAnim(animTigerClaw); reuse = TigerClawReuseTime; break; case EQEmu::skills::SkillRoundKick: skill_type = EQEmu::skills::SkillRoundKick; - max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, RoundKickBonus) / 100) + 10; - ApplySpecialAttackMod(skill_type, max_dmg, min_dmg); + max_dmg = GetBaseSkillDamage(skill_type); DoAnim(animRoundKick); reuse = RoundKickReuseTime; break; case EQEmu::skills::SkillKick: skill_type = EQEmu::skills::SkillKick; - max_dmg = GetKickDamage(); + max_dmg = GetBaseSkillDamage(skill_type); DoAnim(animKick); reuse = KickReuseTime; break; default: Log.Out(Logs::Detail, Logs::Attack, "Invalid special attack type %d attempted", unchecked_type); - return(1000); /* nice long delay for them, the caller depends on this! */ + return (1000); /* nice long delay for them, the caller depends on this! */ } - if(IsClient()){ - if(GetWeaponDamage(other, CastToClient()->GetInv().GetItem(itemslot)) <= 0){ + if (IsClient()) { + if (GetWeaponDamage(other, CastToClient()->GetInv().GetItem(itemslot)) <= 0) { ndamage = -5; } - } - else{ - if (GetWeaponDamage(other, (const EQEmu::ItemData*)nullptr) <= 0){ + } else { + if (GetWeaponDamage(other, (const EQEmu::ItemData *)nullptr) <= 0) { ndamage = -5; } } int32 ht = 0; - if(ndamage == 0){ - if(other->CheckHitChance(this, skill_type, 0)){ - if(RuleB(Combat, UseIntervalAC)) - ht = ndamage = max_dmg; - else - ht = ndamage = zone->random.Int(min_dmg, max_dmg); - } - else{ - ht = max_dmg; - } + if (ndamage == 0) { + ht = max_dmg; + if (other->CheckHitChance(this, skill_type, 0)) + ndamage = max_dmg; } - //This can potentially stack with changes to kick damage + // This can potentially stack with changes to kick damage ht = ndamage = mod_monk_special_damage(ndamage, skill_type); DoSpecialAttackDamage(other, skill_type, ndamage, min_dmg, ht, reuse); - return(reuse); + return (reuse); } void Mob::TryBackstab(Mob *other, int ReuseTime) { @@ -542,22 +567,15 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { } //Live AA - Chaotic Backstab else if(aabonuses.FrontalBackstabMinDmg || itembonuses.FrontalBackstabMinDmg || spellbonuses.FrontalBackstabMinDmg) { + m_specialattacks = eSpecialAttacks::ChaoticStab; //we can stab from any angle, we do min damage though. + // chaotic backstab can't double etc Seized can, but that's because it's a chance to do normal BS + // Live actually added SPA 473 which grants chance to double here when they revamped chaotic/seized RogueBackstab(other, true, ReuseTime); - if (level > 54) { - - // Check for double attack with main hand assuming maxed DA Skill (MS) - if(IsClient() && CastToClient()->CheckDoubleAttack()) - if(other->GetHP() > 0) - RogueBackstab(other,true, ReuseTime); - - if (tripleChance && other->GetHP() > 0 && zone->random.Roll(tripleChance)) - RogueBackstab(other,false,ReuseTime); - } - if(IsClient()) CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillBackstab, other, 10); + m_specialattacks = eSpecialAttacks::None; } else { //We do a single regular attack if we attack from the front without chaotic stab Attack(other, EQEmu::inventory::slotPrimary); @@ -570,79 +588,21 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) if (!other) return; - int32 ndamage = 0; - int32 max_hit = 0; - int32 min_hit = 0; uint32 hate = 0; - int32 primaryweapondamage = 0; - int32 backstab_dmg = 0; + // make sure we can hit (bane, magical, etc) if (IsClient()) { const EQEmu::ItemInstance *wpn = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); - if (wpn) { - primaryweapondamage = GetWeaponDamage(other, wpn); - if (primaryweapondamage) { - backstab_dmg = wpn->GetItemBackstabDamage(true); - backstab_dmg += other->ResistElementalWeaponDmg(wpn); - if (wpn->GetItemBaneDamageBody(true) || wpn->GetItemBaneDamageRace(true)) - backstab_dmg += other->CheckBaneDamage(wpn); - } - } - } else { - primaryweapondamage = - (GetLevel() / 7) + 1; // fallback incase it's a npc without a weapon, 2 dmg at 10, 10 dmg at 65 - backstab_dmg = primaryweapondamage; + if (!GetWeaponDamage(other, wpn)) + return; + } else if (!GetWeaponDamage(other, (const EQEmu::ItemData*)nullptr)){ + return; } - // ex. bane can make this false - if (primaryweapondamage > 0) { - // this is very wrong but not worth it until we fix the full dmg - if (level > 25) { - max_hit = (((((2 * backstab_dmg) * GetDamageTable(EQEmu::skills::SkillBackstab) / 100) * 10 * GetSkill(EQEmu::skills::SkillBackstab) / 355) + ((level - 25) / 3) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); - hate = 20 * backstab_dmg * GetSkill(EQEmu::skills::SkillBackstab) / 355; - } else { - max_hit = (((((2 * backstab_dmg) * GetDamageTable(EQEmu::skills::SkillBackstab) / 100) * 10 * GetSkill(EQEmu::skills::SkillBackstab) / 355) + 1) * ((100 + RuleI(Combat, BackstabBonus)) / 100)); - hate = 20 * backstab_dmg * GetSkill(EQEmu::skills::SkillBackstab) / 355; - } + int base_damage = GetBaseSkillDamage(EQEmu::skills::SkillBackstab, other); + hate = base_damage; - // determine minimum hits - if (level < 51) { - min_hit = (level*15/10); - } else { - // Trumpcard: Replaced switch statement with formula calc. This will give minhit increases all the way to 65. - min_hit = (level * ( level*5 - 105)) / 100; - } - - if (!other->CheckHitChance(this, EQEmu::skills::SkillBackstab, 0)) { - ndamage = 0; - } else { - if (min_damage) { - ndamage = min_hit; - } else { - if (max_hit < min_hit) - max_hit = min_hit; - - if (RuleB(Combat, UseIntervalAC)) - ndamage = max_hit; - else - ndamage = zone->random.Int(min_hit, max_hit); - } - } - } else { - ndamage = -5; - } - - ndamage = mod_backstab_damage(ndamage); - - uint32 Assassinate_Dmg = 0; - Assassinate_Dmg = TryAssassinate(other, EQEmu::skills::SkillBackstab, ReuseTime); - - if (Assassinate_Dmg) { - ndamage = Assassinate_Dmg; - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); - } - - DoSpecialAttackDamage(other, EQEmu::skills::SkillBackstab, ndamage, min_hit, hate, ReuseTime, false, false); + DoSpecialAttackDamage(other, EQEmu::skills::SkillBackstab, base_damage, 0, hate, ReuseTime, true, false); DoAnim(anim1HPiercing); } @@ -867,11 +827,6 @@ void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon } else { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack hit %s.", other->GetName()); - bool HeadShot = false; - uint32 HeadShot_Dmg = TryHeadShot(other, EQEmu::skills::SkillArchery); - if (HeadShot_Dmg) - HeadShot = true; - uint32 hate = 0; int32 TotalDmg = 0; int16 WDmg = 0; @@ -888,85 +843,42 @@ void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon return; } + // unsure when this should happen if (focus) //From FcBaseEffects - WDmg += WDmg*focus/100; + WDmg += WDmg * focus / 100; if((WDmg > 0) || (ADmg > 0)) { if(WDmg < 0) WDmg = 0; if(ADmg < 0) ADmg = 0; - uint32 MaxDmg = (RuleR(Combat, ArcheryBaseDamageBonus)*(WDmg + ADmg)*GetDamageTable(EQEmu::skills::SkillArchery)) / 100; + uint32 MaxDmg = WDmg + ADmg; hate = ((WDmg+ADmg)); - if (HeadShot) - MaxDmg = HeadShot_Dmg; - - uint16 bonusArcheryDamageModifier = aabonuses.ArcheryDamageModifier + itembonuses.ArcheryDamageModifier + spellbonuses.ArcheryDamageModifier; - - MaxDmg += MaxDmg*bonusArcheryDamageModifier / 100; - if (RuleB(Combat, ProjectileDmgOnImpact)) Log.Out(Logs::Detail, Logs::Combat, "Bow and Arrow DMG %d, Max Damage %d.", WDmg, MaxDmg); else Log.Out(Logs::Detail, Logs::Combat, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg); - bool dobonus = false; - if(GetClass() == RANGER && GetLevel() > 50){ - int bonuschance = RuleI(Combat, ArcheryBonusChance); - bonuschance = mod_archery_bonus_chance(bonuschance, RangeWeapon); - - if( !RuleB(Combat, UseArcheryBonusRoll) || zone->random.Roll(bonuschance)){ - if(RuleB(Combat, ArcheryBonusRequiresStationary)){ - if(other->IsNPC() && !other->IsMoving() && !other->IsRooted()) - dobonus = true; - } - else - dobonus = true; - } - - if(dobonus){ - MaxDmg *= 2; - hate *= 2; - MaxDmg = mod_archery_bonus_damage(MaxDmg, RangeWeapon); - - Log.Out(Logs::Detail, Logs::Combat, "Ranger. Double damage success roll, doubling damage to %d", MaxDmg); - Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE); - } - } - if (MaxDmg == 0) MaxDmg = 1; - if(RuleB(Combat, UseIntervalAC)) - TotalDmg = MaxDmg; - else - TotalDmg = zone->random.Int(1, MaxDmg); + int min_cap = MaxDmg * GetMeleeMinDamageMod_SE(EQEmu::skills::SkillArchery) / 100; + auto offense = this->offense(EQEmu::skills::SkillArchery); - int minDmg = 1; - if(GetLevel() > 25){ - //twice, for ammo and weapon - TotalDmg += (2*((GetLevel()-25)/3)); - minDmg += (2*((GetLevel()-25)/3)); - minDmg += minDmg * GetMeleeMinDamageMod_SE(EQEmu::skills::SkillArchery) / 100; - hate += (2*((GetLevel()-25)/3)); - } + other->AvoidDamage(this, TotalDmg, EQEmu::inventory::slotRange); - if (!HeadShot) - other->AvoidDamage(this, TotalDmg, EQEmu::inventory::slotRange); - - other->MeleeMitigation(this, TotalDmg, minDmg); + other->MeleeMitigation(this, TotalDmg, MaxDmg, offense, EQEmu::skills::SkillArchery); if(TotalDmg > 0){ - CommonOutgoingHitSuccess(other, TotalDmg, EQEmu::skills::SkillArchery); - TotalDmg = mod_archery_damage(TotalDmg, dobonus, RangeWeapon); + if (IsClient()) + ApplyDamageTable(TotalDmg, offense); + CommonOutgoingHitSuccess(other, TotalDmg, 0, min_cap, EQEmu::skills::SkillArchery); + //TotalDmg = mod_archery_damage(TotalDmg, dobonus, RangeWeapon); } } else TotalDmg = -5; - if (HeadShot) - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FATAL_BOW_SHOT, GetName()); - if (IsClient() && !CastToClient()->GetFeigned()) other->AddToHateList(this, hate, 0, false); @@ -1227,8 +1139,8 @@ void NPC::RangedAttack(Mob* other) } } -void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile) { - +void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile) +{ if ((other == nullptr || (other->HasDied())) || HasDied() || @@ -1271,15 +1183,9 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha } else { - int32 TotalDmg = 0; - int32 MaxDmg = max_dmg * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types - int32 MinDmg = min_dmg * RuleR(Combat, ArcheryNPCMultiplier); - - if(RuleB(Combat, UseIntervalAC)) - TotalDmg = MaxDmg; - else - TotalDmg = zone->random.Int(MinDmg, MaxDmg); - + int TotalDmg = 0; + int MaxDmg = GetBaseDamage() * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types + int MinDmg = GetMinDamage() * RuleR(Combat, ArcheryNPCMultiplier); if (!damage_mod) damage_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3);//Damage modifier @@ -1287,10 +1193,10 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha TotalDmg += TotalDmg * damage_mod / 100; other->AvoidDamage(this, TotalDmg, EQEmu::inventory::slotRange); - other->MeleeMitigation(this, TotalDmg, MinDmg); + other->MeleeMitigation(this, TotalDmg, MaxDmg, offense(skillInUse), skillInUse); if (TotalDmg > 0) - CommonOutgoingHitSuccess(other, TotalDmg, skillInUse); + CommonOutgoingHitSuccess(other, TotalDmg, MinDmg, 0, skillInUse); else if (TotalDmg < -4) TotalDmg = -5; @@ -1313,32 +1219,6 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha TrySkillProc(other, skillInUse, 0, false, EQEmu::inventory::slotRange); } -uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) { - uint16 MaxDmg = (((2 * wDmg) * GetDamageTable(EQEmu::skills::SkillThrowing)) / 100); - - if (MaxDmg == 0) - MaxDmg = 1; - - if(RuleB(Combat, UseIntervalAC)) - TotalDmg = MaxDmg; - else - TotalDmg = zone->random.Int(1, MaxDmg); - - minDmg = 1; - if(GetLevel() > 25){ - TotalDmg += ((GetLevel()-25)/3); - minDmg += ((GetLevel()-25)/3); - minDmg += minDmg * GetMeleeMinDamageMod_SE(EQEmu::skills::SkillThrowing) / 100; - } - - if(MaxDmg < minDmg) - MaxDmg = minDmg; - - MaxDmg = mod_throwing_damage(MaxDmg); - - return MaxDmg; -} - void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 //conditions to use an attack checked before we are called if (!other) @@ -1422,21 +1302,18 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 CommonBreakInvisibleFromCombat(); } -void Mob::DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon, const EQEmu::ItemData* AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed) +void Mob::DoThrowingAttackDmg(Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemData *AmmoItem, + uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, uint32 range_id, + int AmmoSlot, float speed) { if ((other == nullptr || - ((IsClient() && CastToClient()->dead) || - (other->IsClient() && other->CastToClient()->dead)) || - HasDied() || - (!IsAttackAllowed(other)) || - (other->GetInvul() || - other->GetSpecialAbility(IMMUNE_MELEE)))) - { + ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) || + HasDied() || (!IsAttackAllowed(other)) || (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)))) { return; } - const EQEmu::ItemInstance* _RangeWeapon = nullptr; - const EQEmu::ItemData* ammo_lost = nullptr; + const EQEmu::ItemInstance *_RangeWeapon = nullptr; + const EQEmu::ItemData *ammo_lost = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -1447,95 +1324,97 @@ void Mob::DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon bool ProjectileImpact = false; bool ProjectileMiss = false; - if (RuleB(Combat, ProjectileDmgOnImpact)){ + if (RuleB(Combat, ProjectileDmgOnImpact)) { if (AmmoItem) LaunchProjectile = true; - else{ - if (!RangeWeapon && range_id){ + else { + if (!RangeWeapon && range_id) { ProjectileImpact = true; if (weapon_damage == 0) - ProjectileMiss = true; //This indicates that MISS was originally calculated. + ProjectileMiss = true; // This indicates that MISS was originally calculated. - if (IsClient()){ + if (IsClient()) { _RangeWeapon = CastToClient()->m_inv[AmmoSlot]; - if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID != range_id) + if (_RangeWeapon && _RangeWeapon->GetItem() && + _RangeWeapon->GetItem()->ID != range_id) RangeWeapon = _RangeWeapon; else ammo_lost = database.GetItem(range_id); } } } - } - else if (AmmoItem) + } else if (AmmoItem) SendItemAnimation(other, AmmoItem, EQEmu::skills::SkillThrowing); - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillThrowing, chance_mod))){ + if (ProjectileMiss || + (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillThrowing, chance_mod))) { Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); - if (LaunchProjectile){ - TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillThrowing, 0, RangeWeapon, nullptr, AmmoSlot, speed); + if (LaunchProjectile) { + TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillThrowing, 0, RangeWeapon, nullptr, + AmmoSlot, speed); return; - } - else + } else other->Damage(this, 0, SPELL_UNKNOWN, EQEmu::skills::SkillThrowing); } else { Log.Out(Logs::Detail, Logs::Combat, "Throwing attack hit %s.", other->GetName()); int16 WDmg = 0; - if (!weapon_damage){ + if (!weapon_damage) { if (IsClient() && RangeWeapon) WDmg = GetWeaponDamage(other, RangeWeapon); else if (AmmoItem) WDmg = GetWeaponDamage(other, AmmoItem); - if (LaunchProjectile){ - TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillThrowing, WDmg, RangeWeapon, nullptr, AmmoSlot, speed); + if (LaunchProjectile) { + TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillThrowing, WDmg, RangeWeapon, + nullptr, AmmoSlot, speed); return; } - } - else + } else WDmg = weapon_damage; - if (focus) //From FcBaseEffects - WDmg += WDmg*focus/100; + if (focus) // From FcBaseEffects + WDmg += WDmg * focus / 100; int32 TotalDmg = 0; uint32 Assassinate_Dmg = 0; if (GetClass() == ROGUE && (BehindMob(other, GetX(), GetY()))) - Assassinate_Dmg = TryAssassinate(other, EQEmu::skills::SkillThrowing, ranged_timer.GetDuration()); - - if(WDmg > 0){ - int minDmg = 1; - uint16 MaxDmg = GetThrownDamage(WDmg, TotalDmg, minDmg); + Assassinate_Dmg = + TryAssassinate(other, EQEmu::skills::SkillThrowing, ranged_timer.GetDuration()); + if (WDmg > 0) { + int min_cap = WDmg * GetMeleeMinDamageMod_SE(EQEmu::skills::SkillThrowing) / 100; + auto offense = this->offense(EQEmu::skills::SkillThrowing); if (Assassinate_Dmg) { TotalDmg = Assassinate_Dmg; - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); } - Log.Out(Logs::Detail, Logs::Combat, "Item DMG %d. Max Damage %d. Hit for damage %d", WDmg, MaxDmg, TotalDmg); + Log.Out(Logs::Detail, Logs::Combat, "Item DMG %d. Hit for damage %d", WDmg, TotalDmg); if (!Assassinate_Dmg) other->AvoidDamage(this, TotalDmg, EQEmu::inventory::slotRange); - other->MeleeMitigation(this, TotalDmg, minDmg); - if(TotalDmg > 0) - CommonOutgoingHitSuccess(other, TotalDmg, EQEmu::skills::SkillThrowing); + other->MeleeMitigation(this, TotalDmg, WDmg, offense, EQEmu::skills::SkillThrowing); + if (TotalDmg > 0) + if (IsClient()) + ApplyDamageTable(TotalDmg, offense); + CommonOutgoingHitSuccess(other, TotalDmg, 0, min_cap, EQEmu::skills::SkillThrowing); } else TotalDmg = -5; if (IsClient() && !CastToClient()->GetFeigned()) - other->AddToHateList(this, 2*WDmg, 0, false); + other->AddToHateList(this, 2 * WDmg, 0, false); other->Damage(this, TotalDmg, SPELL_UNKNOWN, EQEmu::skills::SkillThrowing); - if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()){ + if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()) { if (ReuseTime) TrySkillProc(other, EQEmu::skills::SkillThrowing, ReuseTime); else @@ -1546,13 +1425,13 @@ void Mob::DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon if (LaunchProjectile) return; - //Throwing item Proc + // Throwing item Proc if (ammo_lost) TryWeaponProc(nullptr, ammo_lost, other, EQEmu::inventory::slotRange); - else if(RangeWeapon && other && !other->HasDied()) + else if (RangeWeapon && other && !other->HasDied()) TryWeaponProc(RangeWeapon, other, EQEmu::inventory::slotRange); - if (HasSkillProcs() && other && !other->HasDied()){ + if (HasSkillProcs() && other && !other->HasDied()) { if (ReuseTime) TrySkillProc(other, EQEmu::skills::SkillThrowing, ReuseTime); else @@ -1755,17 +1634,12 @@ void NPC::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) { - if(RuleB(Combat, UseIntervalAC)) - dmg = GetKickDamage(); - else - dmg = zone->random.Int(1, GetKickDamage()); - - } + if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) + dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); } reuse = (KickReuseTime + 3) * 1000; - DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, GetMinDamage(), -1, reuse); did_attack = true; } else { @@ -1776,16 +1650,12 @@ void NPC::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) { - if(RuleB(Combat, UseIntervalAC)) - dmg = GetBashDamage(); - else - dmg = zone->random.Int(1, GetBashDamage()); - } + if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) + dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); } reuse = (BashReuseTime + 3) * 1000; - DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, GetMinDamage(), -1, reuse); did_attack = true; } } @@ -1793,28 +1663,16 @@ void NPC::DoClassAttacks(Mob *target) { } case BERSERKER: case BERSERKERGM:{ int AtkRounds = 3; - int32 max_dmg = 26 + ((GetLevel()-6) * 2); - int32 min_dmg = 0; + int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy); DoAnim(anim2HSlashing); - if (GetLevel() < 51) - min_dmg = 1; - else - min_dmg = GetLevel()*8/10; - - if (min_dmg > max_dmg) - max_dmg = min_dmg; - - reuse = FrenzyReuseTime * 1000; - while(AtkRounds > 0) { if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, min_dmg, -1, reuse, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, GetMinDamage(), -1, reuse, true); } AtkRounds--; } - did_attack = true; break; } @@ -1829,16 +1687,12 @@ void NPC::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) { - if(RuleB(Combat, UseIntervalAC)) - dmg = GetKickDamage(); - else - dmg = zone->random.Int(1, GetKickDamage()); - } + if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) + dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); } reuse = (KickReuseTime + 3) * 1000; - DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, GetMinDamage(), -1, reuse); did_attack = true; } break; @@ -1854,16 +1708,12 @@ void NPC::DoClassAttacks(Mob *target) { dmg = -5; } else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) { - if(RuleB(Combat, UseIntervalAC)) - dmg = GetBashDamage(); - else - dmg = zone->random.Int(1, GetBashDamage()); - } + if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) + dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); } reuse = (BashReuseTime + 3) * 1000; - DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, 1, -1, reuse); + DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, GetMinDamage(), -1, reuse); did_attack = true; } break; @@ -1873,6 +1723,7 @@ void NPC::DoClassAttacks(Mob *target) { classattack_timer.Start(reuse / HasteModifier); } +// this should be refactored to generate an OP_CombatAbility struct and call OPCombatAbility void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) { if(!ca_target) @@ -1964,17 +1815,13 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) dmg = 0; } else{ - if(RuleB(Combat, UseIntervalAC)) - dmg = GetBashDamage(); - else - dmg = zone->random.Int(1, GetBashDamage()); - + dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash, ca_target); } } ReuseTime = (BashReuseTime - 1) / HasteMod; - DoSpecialAttackDamage(ca_target, EQEmu::skills::SkillBash, dmg, 1, -1, ReuseTime); + DoSpecialAttackDamage(ca_target, EQEmu::skills::SkillBash, dmg, 0, -1, ReuseTime); if(ReuseTime > 0 && !IsRiposte) { p_timers.Start(pTimerCombatAbility, ReuseTime); @@ -1986,26 +1833,16 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if (skill_to_use == EQEmu::skills::SkillFrenzy){ CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10); int AtkRounds = 3; - int skillmod = 100 * GetSkill(EQEmu::skills::SkillFrenzy) / MaxSkill(EQEmu::skills::SkillFrenzy); - int32 max_dmg = (26 + ((((GetLevel()-6) * 2)*skillmod)/100)) * ((100+RuleI(Combat, FrenzyBonus))/100); - int32 min_dmg = 0; + int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash, GetTarget()); DoAnim(anim2HSlashing); - if (GetLevel() < 51) - min_dmg = 1; - else - min_dmg = GetLevel()*8/10; - - if (min_dmg > max_dmg) - max_dmg = min_dmg; - ReuseTime = (FrenzyReuseTime - 1) / HasteMod; //Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit. while(AtkRounds > 0) { if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, min_dmg, max_dmg, ReuseTime, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, 0, max_dmg, ReuseTime, true); } AtkRounds--; } @@ -2028,16 +1865,13 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) dmg = 0; } else{ - if(RuleB(Combat, UseIntervalAC)) - dmg = GetKickDamage(); - else - dmg = zone->random.Int(1, GetKickDamage()); + dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick, ca_target); } } ReuseTime = KickReuseTime-1; - DoSpecialAttackDamage(ca_target, EQEmu::skills::SkillKick, dmg, 1, -1, ReuseTime); + DoSpecialAttackDamage(ca_target, EQEmu::skills::SkillKick, dmg, 0, -1, ReuseTime); } } @@ -2218,7 +2052,7 @@ void Mob::InstillDoubt(Mob *who) { } } -uint32 Mob::TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse) { +int Mob::TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse) { //Only works on YOUR target. if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() && (skillInUse == EQEmu::skills::SkillArchery) && (GetTarget() == defender)) { @@ -2233,8 +2067,10 @@ uint32 Mob::TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse) { if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){ float ProcChance = GetSpecialProcChances(EQEmu::inventory::slotRange); - if(zone->random.Roll(ProcChance)) + if(zone->random.Roll(ProcChance)) { + entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FATAL_BOW_SHOT, GetName()); return HeadShot_Dmg; + } } } @@ -2269,9 +2105,9 @@ float Mob::GetSpecialProcChances(uint16 hand) return ProcChance; } -uint32 Mob::TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, uint16 ReuseTime) { +int Mob::TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, uint16 ReuseTime) { - if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() && + if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() && GetLevel() >= 60 && (skillInUse == EQEmu::skills::SkillBackstab || skillInUse == EQEmu::skills::SkillThrowing)) { uint32 Assassinate_Dmg = aabonuses.Assassinate[1] + spellbonuses.Assassinate[1] + itembonuses.Assassinate[1]; @@ -2283,13 +2119,9 @@ uint32 Mob::TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, u else if (Assassinate_Level < itembonuses.AssassinateLevel) Assassinate_Level = itembonuses.AssassinateLevel; - if (GetLevel() >= 60){ //Innate Assassinate Ability if client as no bonuses. - if (!Assassinate_Level) - Assassinate_Level = 45; - - if (!Assassinate_Dmg) - Assassinate_Dmg = 32000; - } + // revamped AAs require AA line I believe? + if (!Assassinate_Level) + return 0; if(Assassinate_Dmg && Assassinate_Level && (defender->GetLevel() <= Assassinate_Level)){ float ProcChance = 0.0f; @@ -2299,8 +2131,11 @@ uint32 Mob::TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, u else ProcChance = GetAssassinateProcChances(ReuseTime); - if(zone->random.Roll(ProcChance)) + if(zone->random.Roll(ProcChance)) { + entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, + GetName()); return Assassinate_Dmg; + } } } @@ -2340,34 +2175,20 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: /* For spells using skill value 98 (feral swipe ect) server sets this to 67 automatically. Kayen: This is unlikely to be completely accurate but use OFFENSE skill value for these effects. + TODO: We need to stop moving skill 98, it's suppose to just be a dummy skill AFAIK + Spells using offense should use the skill of your primary, if you can use it, otherwise h2h */ if (skillinuse == EQEmu::skills::SkillBegging) skillinuse = EQEmu::skills::SkillOffense; int damage = 0; uint32 hate = 0; - int Hand = EQEmu::inventory::slotPrimary; if (hate == 0 && weapon_damage > 1) hate = weapon_damage; if(weapon_damage > 0){ if (focus) //From FcBaseEffects weapon_damage += weapon_damage*focus/100; - if(GetClass() == BERSERKER){ - int bonus = 3 + GetLevel()/10; - weapon_damage = weapon_damage * (100+bonus) / 100; - } - - int32 min_hit = 1; - int32 max_hit = (2 * weapon_damage*GetDamageTable(skillinuse)) / 100; - - if(GetLevel() >= 28 && IsWarriorClass() ) { - int ucDamageBonus = GetWeaponDamageBonus((const EQEmu::ItemData*) nullptr); - min_hit += (int) ucDamageBonus; - max_hit += (int) ucDamageBonus; - hate += ucDamageBonus; - } - if (skillinuse == EQEmu::skills::SkillBash){ if(IsClient()){ EQEmu::ItemInstance *item = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); @@ -2381,16 +2202,11 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: } } - ApplySpecialAttackMod(skillinuse, max_hit, min_hit); - min_hit += min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100; - - if(max_hit < min_hit) - max_hit = min_hit; - - if(RuleB(Combat, UseIntervalAC)) - damage = max_hit; - else - damage = zone->random.Int(min_hit, max_hit); + int min_cap = weapon_damage * GetMeleeMinDamageMod_SE(skillinuse) / 100; + auto offense = this->offense(skillinuse); + int min_damage = 0; + if (IsNPC()) + min_damage = CastToNPC()->GetMinDamage(); if (other->AvoidDamage(this, damage, CanRiposte ? EQEmu::inventory::slotRange : EQEmu::inventory::slotPrimary)) { // SlotRange excludes ripo, primary doesn't have any extra behavior if (damage == -3) { @@ -2400,8 +2216,9 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: } } else { if (other->CheckHitChance(this, skillinuse, chance_mod)) { - other->MeleeMitigation(this, damage, min_hit); - CommonOutgoingHitSuccess(other, damage, skillinuse); + other->MeleeMitigation(this, damage, weapon_damage, offense, skillinuse); + ApplyDamageTable(damage, offense); + CommonOutgoingHitSuccess(other, damage, min_damage, min_cap, skillinuse); } else { damage = 0; } diff --git a/zone/tune.cpp b/zone/tune.cpp index 6595ad4d0..bbb56217e 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -486,7 +486,7 @@ int32 Mob::Tune_MeleeMitigation(Mob* GM, Mob *attacker, int32 damage, int32 minh } - damage = GetMeleeMitDmg(attacker, damage, minhit, mitigation_rating, attack_rating); + //damage = GetMeleeMitDmg(attacker, damage, minhit, mitigation_rating, attack_rating); } if (damage < 0) @@ -539,7 +539,7 @@ int32 Client::Tune_GetMeleeMitDmg(Mob* GM, Mob *attacker, int32 damage, int32 mi float mit_rating, float atk_rating) { if (!attacker->IsNPC() || RuleB(Combat, UseOldDamageIntervalRules)) - return Mob::GetMeleeMitDmg(attacker, damage, minhit, mit_rating, atk_rating); + return 0; //Mob::GetMeleeMitDmg(attacker, damage, minhit, mit_rating, atk_rating); int d = 10; // floats for the rounding issues float dmg_interval = (damage - minhit) / 19.0; @@ -613,7 +613,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) } int min_hit = 1; - int max_hit = (2*weapon_damage*GetDamageTable(skillinuse)) / 100; + int max_hit = 2;//(2*weapon_damage*GetDamageTable(skillinuse)) / 100; if(GetLevel() < 10 && max_hit > RuleI(Combat, HitCapPre10)) max_hit = (RuleI(Combat, HitCapPre10)); @@ -1086,4 +1086,4 @@ float Mob::Tune_CheckHitChance(Mob* defender, Mob* attacker, EQEmu::skills::Skil } return(chancetohit); -} \ No newline at end of file +} diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index c4fcfc55f..ec56b8df8 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2133,7 +2133,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load temp_npctype_data->healscale = atoi(row[87]); temp_npctype_data->no_target_hotkey = atoi(row[88]) == 1 ? true: false; temp_npctype_data->raid_target = atoi(row[89]) == 0 ? false: true; - temp_npctype_data->attack_delay = atoi(row[90]); + temp_npctype_data->attack_delay = atoi(row[90]) * 100; // TODO: fix DB temp_npctype_data->light = (atoi(row[91]) & 0x0F); temp_npctype_data->armtexture = atoi(row[92]); diff --git a/zone/zonedump.h b/zone/zonedump.h index c6121fd48..ef8da2243 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -110,7 +110,7 @@ struct NPCType uint8 spawn_limit; //only this many may be in zone at a time (0=no limit) uint8 mount_color; //only used by horse class float attack_speed; //%+- on attack delay of the mob. - uint8 attack_delay; //delay between attacks in 10ths of a second + int attack_delay; //delay between attacks in ms int accuracy_rating; // flat bonus before mods int avoidance_rating; // flat bonus before mods bool findable; //can be found with find command From 7e49a21b3bc6100bc6d0df1e2d6d274cdc97e1bb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 15 Jan 2017 13:54:10 -0500 Subject: [PATCH 496/693] Change NPC skill AC bonus Basically, live doesn't have an NPC's skill at the max for their class like we do. So for now, we'll just set their SkillDefense bonus to value / 5 --- zone/attack.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 219ee231e..122bc7da5 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -735,7 +735,7 @@ int Mob::ACSum() // EQ math ac = (ac * 4) / 3; // anti-twink - if (GetLevel() < 50) + if (IsClient() && GetLevel() < 50) ac = std::min(ac, 25 + 6 * GetLevel()); ac = std::max(0, ac + GetClassRaceACBonus()); if (IsNPC()) { @@ -751,12 +751,19 @@ int Mob::ACSum() owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); if (owner) ac += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance; + auto spell_aa_ac = aabonuses.AC + spellbonuses.AC; + ac += GetSkill(EQEmu::skills::SkillDefense) / 5; + if (EQEmu::ValueWithin(static_cast(GetClass()), NECROMANCER, ENCHANTER)) + ac += spell_aa_ac / 3; + else + ac += spell_aa_ac / 4; + } else { // TODO: so we can't set NPC skills ... so the skill bonus ends up being HUGE so lets nerf them a bit + auto spell_aa_ac = aabonuses.AC + spellbonuses.AC; + if (EQEmu::ValueWithin(static_cast(GetClass()), NECROMANCER, ENCHANTER)) + ac += GetSkill(EQEmu::skills::SkillDefense) / 2 + spell_aa_ac / 3; + else + ac += GetSkill(EQEmu::skills::SkillDefense) / 3 + spell_aa_ac / 4; } - auto spell_aa_ac = aabonuses.AC + spellbonuses.AC; - if (EQEmu::ValueWithin(static_cast(GetClass()), NECROMANCER, ENCHANTER)) - ac += GetSkill(EQEmu::skills::SkillDefense) / 2 + spell_aa_ac / 3; - else - ac += GetSkill(EQEmu::skills::SkillDefense) / 3 + spell_aa_ac / 4; if (GetAGI() > 70) ac += GetAGI() / 20; From c030e1ce8d54ddce83508af94a38a93165cede30 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 15 Jan 2017 15:39:12 -0500 Subject: [PATCH 497/693] Add rule Combat:LevelToStopDamageCaps Setting this to 1 will effectively disable damage caps Setting this to 20 will give similar results to old incorrect default rules --- common/ruletypes.h | 1 + zone/attack.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/common/ruletypes.h b/common/ruletypes.h index dc1a31c1f..2b0b71899 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -492,6 +492,7 @@ RULE_INT(Combat, NPCAssistCap, 5) // Maxiumium number of NPCs that will assist a RULE_INT(Combat, NPCAssistCapTimer, 6000) // Time in milliseconds a NPC will take to clear assist aggro cap space RULE_BOOL(Combat, UseRevampHandToHand, false) // use h2h revamped dmg/delays I believe this was implemented during SoF RULE_BOOL(Combat, ClassicMasterWu, false) // classic master wu uses a random special, modern doesn't +RULE_INT(Combat, LevelToStopDamageCaps, 0) // 1 will effectively disable them, 20 should give basically same results as old incorrect system RULE_CATEGORY_END() RULE_CATEGORY(NPC) diff --git a/zone/attack.cpp b/zone/attack.cpp index 122bc7da5..a1dfbc176 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1107,6 +1107,9 @@ int Client::DoDamageCaps(int base_damage) { // this is based on a client function that caps melee base_damage auto level = GetLevel(); + auto stop_level = RuleI(Combat, LevelToStopDamageCaps); + if (stop_level && stop_level <= level) + return base_damage; int cap = 0; if (level >= 125) { cap = 7 * level; From e03a90b05dfa5eaa6c66f7de4f20fa41959e5cee Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 15 Jan 2017 16:08:22 -0500 Subject: [PATCH 498/693] Refactor CheckHitChance Pulled the accuracy/avoidance spell bonuses into their own functions so we can show the total values in #showstats --- zone/attack.cpp | 157 +++++++++++++++++++++++++++--------------------- zone/mob.h | 2 + 2 files changed, 89 insertions(+), 70 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index a1dfbc176..cdc3bab06 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -157,6 +157,62 @@ int Mob::compute_tohit(EQEmu::skills::SkillType skillinuse) return std::max(tohit, 1); } +// return -1 in cases that always hit +int Mob::GetTotalToHit(EQEmu::skills::SkillType skill, int chance_mod) +{ + if (chance_mod >= 10000) // override for stuff like SE_SkillAttack + return -1; + + // calculate attacker's accuracy + auto accuracy = compute_tohit(skill) + 10; // add 10 in case the NPC's stats are fucked + if (chance_mod > 0) // multiplier + accuracy *= chance_mod; + + // Torven parsed an apparent constant of 1.2 somewhere in here * 6 / 5 looks eqmathy to me! + accuracy = accuracy * 6 / 5; + + // unsure on the stacking order of these effects, rather hard to parse + // item mod2 accuracy isn't applied to range? Theory crafting and parses back it up I guess + // mod2 accuracy -- flat bonus + if (skill != EQEmu::skills::SkillArchery && skill != EQEmu::skills::SkillThrowing) + accuracy += itembonuses.HitChance; + + // 216 Melee Accuracy Amt aka SE_Accuracy -- flat bonus + accuracy += itembonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + + aabonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + + spellbonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + + itembonuses.Accuracy[skill] + + aabonuses.Accuracy[skill] + + spellbonuses.Accuracy[skill]; + + // auto hit discs (and looks like there are some autohit AAs) + if (spellbonuses.HitChanceEffect[skill] >= 10000 || aabonuses.HitChanceEffect[skill] >= 10000) + return -1; + + if (spellbonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] >= 10000) + return -1; + + // 184 Accuracy % aka SE_HitChance -- percentage increase + auto hit_bonus = itembonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + + aabonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + + spellbonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + + itembonuses.HitChanceEffect[skill] + + aabonuses.HitChanceEffect[skill] + + spellbonuses.HitChanceEffect[skill]; + + accuracy = (accuracy * (100 + hit_bonus)) / 100; + + // TODO: April 2003 added an archery/throwing PVP accuracy penalty while moving, should be in here some where, + // but PVP is less important so I haven't tried parsing it at all + + // There is also 110 Ranger Archery Accuracy % which should probably be in here some where, but it's not in any spells/aas + // Name implies it's a percentage increase, if one wishes to implement, do it like the hit_bonus above but limited to ranger archery + + // There is also 183 UNUSED - Skill Increase Chance which devs say isn't used at all in code, but some spells reference it + // I do not recommend implementing this once since there are spells that use it which would make this not live-like with default spell files + return accuracy; +} + // based on dev quotes // the AGI bonus has actually drastically changed from classic int Mob::compute_defense() @@ -181,6 +237,33 @@ int Mob::compute_defense() return std::max(1, defense); } +// return -1 in cases that always miss +int Mob::GetTotalDefense() +{ + auto avoidance = compute_defense() + 10; // add 10 in case the NPC's stats are fucked + auto evasion_bonus = spellbonuses.AvoidMeleeChanceEffect; // we check this first since it has a special case + if (evasion_bonus >= 10000) + return -1; + // + // 172 Evasion aka SE_AvoidMeleeChance + evasion_bonus += itembonuses.AvoidMeleeChanceEffect + aabonuses.AvoidMeleeChanceEffect; // item bonus here isn't mod2 avoidance + + Mob *owner = nullptr; + if (IsPet()) + owner = GetOwner(); + else if (IsNPC() && CastToNPC()->GetSwarmOwner()) + owner = entity_list.GetMobID(CastToNPC()->GetSwarmOwner()); + + if (owner) // 215 Pet Avoidance % aka SE_PetAvoidance + evasion_bonus += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance; + + // Evasion is a percentage bonus according to AA descriptions + if (evasion_bonus) + avoidance = (avoidance * (100 + evasion_bonus)) / 100; + + return avoidance; +} + // called when a mob is attacked, does the checks to see if it's a hit // and does other mitigation checks. 'this' is the mob being attacked. bool Mob::CheckHitChance(Mob* other, EQEmu::skills::SkillType skillinuse, int chance_mod) @@ -192,80 +275,14 @@ bool Mob::CheckHitChance(Mob* other, EQEmu::skills::SkillType skillinuse, int ch if (defender->IsClient() && defender->CastToClient()->IsSitting()) return true; - // calculate defender's avoidance - auto avoidance = defender->compute_defense() + 10; // add 10 in case the NPC's stats are fucked - auto evasion_bonus = defender->spellbonuses.AvoidMeleeChanceEffect; // we check this first since it has a special case - if (evasion_bonus <= -100) - return true; - if (evasion_bonus >= 10000) // some sort of auto avoid disc + auto avoidance = defender->GetTotalDefense(); + if (avoidance == -1) // some sort of auto avoid disc return false; - // 172 Evasion aka SE_AvoidMeleeChance - evasion_bonus += defender->itembonuses.AvoidMeleeChanceEffect + defender->aabonuses.AvoidMeleeChanceEffect; // item bonus here isn't mod2 avoidance - Mob *owner = nullptr; - if (defender->IsPet()) - owner = defender->GetOwner(); - else if (defender->IsNPC() && defender->CastToNPC()->GetSwarmOwner()) - owner = entity_list.GetMobID(defender->CastToNPC()->GetSwarmOwner()); - - if (owner) // 215 Pet Avoidance % aka SE_PetAvoidance - evasion_bonus += owner->aabonuses.PetAvoidance + owner->spellbonuses.PetAvoidance + owner->itembonuses.PetAvoidance; - - // Evasion is a percentage bonus according to AA descriptions - if (evasion_bonus) - avoidance = (avoidance * (100 + evasion_bonus)) / 100; - - if (chance_mod >= 10000) // override for stuff like SE_SkillAttack + auto accuracy = attacker->GetTotalToHit(skillinuse, chance_mod); + if (accuracy == -1) return true; - // calculate attacker's accuracy - auto accuracy = attacker->compute_tohit(skillinuse) + 10; // add 10 in case the NPC's stats are fucked - if (chance_mod > 0) // multiplier - accuracy *= chance_mod; - - // Torven parsed an apparent constant of 1.2 somewhere in here * 6 / 5 looks eqmathy to me! - accuracy = accuracy * 6 / 5; - - // unsure on the stacking order of these effects, rather hard to parse - // item mod2 accuracy isn't applied to range? Theory crafting and parses back it up I guess - // mod2 accuracy -- flat bonus - if (skillinuse != EQEmu::skills::SkillArchery && skillinuse != EQEmu::skills::SkillThrowing) - accuracy += attacker->itembonuses.HitChance; - - // 216 Melee Accuracy Amt aka SE_Accuracy -- flat bonus - accuracy += attacker->itembonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + - attacker->aabonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + - attacker->spellbonuses.Accuracy[EQEmu::skills::HIGHEST_SKILL + 1] + - attacker->itembonuses.Accuracy[skillinuse] + - attacker->aabonuses.Accuracy[skillinuse] + - attacker->spellbonuses.Accuracy[skillinuse]; - - // auto hit discs (and looks like there are some autohit AAs) - if (attacker->spellbonuses.HitChanceEffect[skillinuse] >= 10000 || attacker->aabonuses.HitChanceEffect[skillinuse] >= 10000) - return true; - - if (attacker->spellbonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] >= 10000) - return true; - - // 184 Accuracy % aka SE_HitChance -- percentage increase - auto hit_bonus = attacker->itembonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + - attacker->aabonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + - attacker->spellbonuses.HitChanceEffect[EQEmu::skills::HIGHEST_SKILL + 1] + - attacker->itembonuses.HitChanceEffect[skillinuse] + - attacker->aabonuses.HitChanceEffect[skillinuse] + - attacker->spellbonuses.HitChanceEffect[skillinuse]; - - accuracy = (accuracy * (100 + hit_bonus)) / 100; - - // TODO: April 2003 added an archery/throwing PVP accuracy penalty while moving, should be in here some where, - // but PVP is less important so I haven't tried parsing it at all - - // There is also 110 Ranger Archery Accuracy % which should probably be in here some where, but it's not in any spells/aas - // Name implies it's a percentage increase, if one wishes to implement, do it like the hit_bonus above but limited to ranger archery - - // There is also 183 UNUSED - Skill Increase Chance which devs say isn't used at all in code, but some spells reference it - // I do not recommend implementing this once since there are spells that use it which would make this not live-like with default spell files - // so now we roll! // relevant dev quote: // Then your chance to simply avoid the attack is checked (defender's avoidance roll beat the attacker's accuracy roll.) diff --git a/zone/mob.h b/zone/mob.h index 802eede5c..6e390d7d6 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -166,7 +166,9 @@ public: virtual void TryBackstab(Mob *other,int ReuseTime = 10); bool AvoidDamage(Mob* attacker, int &damage, int hand); int compute_tohit(EQEmu::skills::SkillType skillinuse); + int GetTotalToHit(EQEmu::skills::SkillType skill, int chance_mod); // compute_tohit + spell bonuses int compute_defense(); + int GetTotalDefense(); // compute_defense + spell bonuses bool CheckHitChance(Mob* attacker, EQEmu::skills::SkillType skillinuse, int chance_mod = 0); virtual void TryCriticalHit(Mob *defender, uint16 skill, int &damage, int min_damage, ExtraAttackOptions *opts = nullptr); void TryPetCriticalHit(Mob *defender, uint16 skill, int &damage); From 8c6fefa33e784ae5495246d997aaeb0afa0294a4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 15 Jan 2017 16:32:15 -0500 Subject: [PATCH 499/693] Update #showstats --- zone/client.cpp | 42 +++++++++++++++++++++++++++++++++++++----- zone/mob.cpp | 3 +++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index a066b9b12..5b849ba58 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -6863,16 +6863,46 @@ void Client::SendStatsWindow(Client* client, bool use_window) indP + "Wind: " + itoa(GetWindMod()) + "
"; } + EQEmu::skills::SkillType skill = EQEmu::skills::SkillHandtoHand; + auto *inst = GetInv().GetItem(EQEmu::inventory::slotPrimary); + if (inst && inst->IsClassCommon()) { + switch (inst->GetItem()->ItemType) { + case EQEmu::item::ItemType1HSlash: + skill = EQEmu::skills::Skill1HSlashing; + break; + case EQEmu::item::ItemType2HSlash: + skill = EQEmu::skills::Skill2HSlashing; + break; + case EQEmu::item::ItemType1HPiercing: + skill = EQEmu::skills::Skill1HPiercing; + break; + case EQEmu::item::ItemType1HBlunt: + skill = EQEmu::skills::Skill1HBlunt; + break; + case EQEmu::item::ItemType2HBlunt: + skill = EQEmu::skills::Skill2HBlunt; + break; + case EQEmu::item::ItemType2HPiercing: + if (ClientVersion() < EQEmu::versions::ClientVersion::RoF2) + skill = EQEmu::skills::Skill1HPiercing; + else + skill = EQEmu::skills::Skill2HPiercing; + break; + default: + break; + } + } + std::ostringstream final_string; final_string << /* C/L/R */ indP << "Class: " << class_Name << indS << "Level: " << static_cast(GetLevel()) << indS << "Race: " << race_Name << "
" << /* Runes */ indP << "Rune: " << rune_number << indL << indS << "Spell Rune: " << magic_rune_number << "
" << /* HP/M/E */ HME_row << /* DS */ indP << "DS: " << (itembonuses.DamageShield + spellbonuses.DamageShield*-1) << " (Spell: " << (spellbonuses.DamageShield*-1) << " + Item: " << itembonuses.DamageShield << " / " << RuleI(Character, ItemDamageShieldCap) << ")
" << - /* Atk */ indP << "ATK: " << GetTotalATK() << "
" << - /* Atk2 */ indP << "- Base: " << GetATKRating() << " | Item: " << itembonuses.ATK << " (" << RuleI(Character, ItemATKCap) << ")~Used: " << (itembonuses.ATK * 1.342) << " | Spell: " << spellbonuses.ATK << "
" << - /* AC */ indP << "AC: " << -1 << "
" << - /* AC2 */ indP << "- Mit: " << -1 << " | Avoid: " << -1 << " | Spell: " << spellbonuses.AC << " | Shield: " << shield_ac << "
" << + /* Atk */ indP << "tohit: " << compute_tohit(skill) << " / " << GetTotalToHit(skill, 0) << "
" << + /* Atk2 */ indP << "- Offense: " << offense(skill) << " | Item: " << itembonuses.ATK << " (" << RuleI(Character, ItemATKCap) << ")~Used: " << (itembonuses.ATK * 1.342) << " | Spell: " << spellbonuses.ATK << "
" << + /* AC */ indP << "mitigation AC: " << GetMitigationAC() << "
" << + /* AC2 */ indP << "- defense: " << compute_defense() << " / " << GetTotalDefense() << " | Spell: " << spellbonuses.AC << " | Shield: " << shield_ac << "
" << /* Haste */ indP << "Haste: " << GetHaste() << "
" << /* Haste2 */ indP << " - Item: " << itembonuses.haste << " + Spell: " << (spellbonuses.haste + spellbonuses.hastetype2) << " (Cap: " << RuleI(Character, HasteCap) << ") | Over: " << (spellbonuses.hastetype3 + ExtraHaste) << "
" << /* RunSpeed*/ indP << "Runspeed: " << GetRunspeed() << "
" << @@ -6910,7 +6940,9 @@ void Client::SendStatsWindow(Client* client, bool use_window) client->Message(15, "~~~~~ %s %s ~~~~~", GetCleanName(), GetLastName()); client->Message(0, " Level: %i Class: %i Race: %i DS: %i/%i Size: %1.1f Weight: %.1f/%d ", GetLevel(), GetClass(), GetRace(), GetDS(), RuleI(Character, ItemDamageShieldCap), GetSize(), (float)CalcCurrentWeight() / 10.0f, GetSTR()); client->Message(0, " HP: %i/%i HP Regen: %i/%i",GetHP(), GetMaxHP(), CalcHPRegen(), CalcHPRegenCap()); - client->Message(0, " AC: %i ( Mit.: %i + Avoid.: %i + Spell: %i ) | Shield AC: %i", -1, -1, -1, spellbonuses.AC, shield_ac); + client->Message(0, " compute_tohit: %i TotalToHit: %i", compute_tohit(skill), GetTotalToHit(skill, 0)); + client->Message(0, " compute_defense: %i TotalDefense: %i", compute_defense(), GetTotalDefense()); + client->Message(0, " offense: %i mitigation ac: %i", offense(skill), GetMitigationAC()); if(CalcMaxMana() > 0) client->Message(0, " Mana: %i/%i Mana Regen: %i/%i", GetMana(), GetMaxMana(), CalcManaRegen(), CalcManaRegenCap()); client->Message(0, " End.: %i/%i End. Regen: %i/%i",GetEndurance(), GetMaxEndurance(), CalcEnduranceRegen(), CalcEnduranceRegenCap()); diff --git a/zone/mob.cpp b/zone/mob.cpp index c5b61f546..d8b10874e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1493,6 +1493,9 @@ void Mob::ShowStats(Client* client) spawngroupid = n->respawn2->SpawnGroupID(); client->Message(0, " NPCID: %u SpawnGroupID: %u Grid: %i LootTable: %u FactionID: %i SpellsID: %u ", GetNPCTypeID(),spawngroupid, n->GetGrid(), n->GetLoottableID(), n->GetNPCFactionID(), n->GetNPCSpellsID()); client->Message(0, " Accuracy: %i MerchantID: %i EmoteID: %i Runspeed: %.3f Walkspeed: %.3f", n->GetAccuracyRating(), n->MerchantType, n->GetEmoteID(), static_cast(0.025f * n->GetRunspeed()), static_cast(0.025f * n->GetWalkspeed())); + client->Message(0, " compute_tohit: %i TotalToHit: %i", n->compute_tohit(EQEmu::skills::SkillHandtoHand), n->GetTotalToHit(EQEmu::skills::SkillHandtoHand, 0)); + client->Message(0, " compute_defense: %i TotalDefense: %i", n->compute_defense(), n->GetTotalDefense()); + client->Message(0, " offense: %i mitigation ac: %i", n->offense(EQEmu::skills::SkillHandtoHand), n->GetMitigationAC()); n->QueryLoot(client); } if (IsAIControlled()) { From b92d6c57a1403b5e61e1f7a04fa256835bde8c51 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 15 Jan 2017 22:19:32 -0500 Subject: [PATCH 500/693] Rework OPCombatAbiltiy a bit This is done to help remove some code duplication in the future --- zone/client.h | 2 +- zone/client_packet.cpp | 3 +- zone/special_attacks.cpp | 222 ++++++++++++++++++--------------------- 3 files changed, 106 insertions(+), 121 deletions(-) diff --git a/zone/client.h b/zone/client.h index 687ff04d6..69fdddffa 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1290,7 +1290,7 @@ private: void OPGMEndTraining(const EQApplicationPacket *app); void OPGMTrainSkill(const EQApplicationPacket *app); void OPGMSummon(const EQApplicationPacket *app); - void OPCombatAbility(const EQApplicationPacket *app); + void OPCombatAbility(const CombatAbility_Struct *ca_atk); // Bandolier Methods void CreateBandolier(const EQApplicationPacket *app); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 56936147d..f2e78adf7 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4622,7 +4622,8 @@ void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app) std::cout << "Wrong size on OP_CombatAbility. Got: " << app->size << ", Expected: " << sizeof(CombatAbility_Struct) << std::endl; return; } - OPCombatAbility(app); + auto ca_atk = (CombatAbility_Struct *)app->pBuffer; + OPCombatAbility(ca_atk); return; } diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 03e4a7d90..a9fcf82b1 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -217,14 +217,14 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 } // We should probably refactor this to take the struct not the packet -void Client::OPCombatAbility(const EQApplicationPacket *app) { - if(!GetTarget()) +void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) +{ + if (!GetTarget()) return; - //make sure were actually able to use such an attack. - if(spellend_timer.Enabled() || IsFeared() || IsStunned() || IsMezzed() || DivineAura() || dead) + // make sure were actually able to use such an attack. + if (spellend_timer.Enabled() || IsFeared() || IsStunned() || IsMezzed() || DivineAura() || dead) return; - CombatAbility_Struct* ca_atk = (CombatAbility_Struct*) app->pBuffer; pTimerType timer = pTimerCombatAbility; // RoF2+ Tiger Claw is unlinked from other monk skills, if they ever do that for other classes there will need // to be more checks here @@ -235,15 +235,15 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { if (!MaxSkill(static_cast(ca_atk->m_skill))) return; - if(GetTarget()->GetID() != ca_atk->m_target) - return; //invalid packet. + if (GetTarget()->GetID() != ca_atk->m_target) + return; // invalid packet. - if(!IsAttackAllowed(GetTarget())) + if (!IsAttackAllowed(GetTarget())) return; - //These two are not subject to the combat ability timer, as they - //allready do their checking in conjunction with the attack timer - //throwing weapons + // These two are not subject to the combat ability timer, as they + // allready do their checking in conjunction with the attack timer + // throwing weapons if (ca_atk->m_atk == EQEmu::inventory::slotRange) { if (ca_atk->m_skill == EQEmu::skills::SkillThrowing) { SetAttackTimer(); @@ -252,7 +252,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { ThrowingAttack(GetTarget(), true); return; } - //ranged attack (archery) + // ranged attack (archery) if (ca_atk->m_skill == EQEmu::skills::SkillArchery) { SetAttackTimer(); RangedAttack(GetTarget()); @@ -260,15 +260,15 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { RangedAttack(GetTarget(), true); return; } - //could we return here? Im not sure is m_atk 11 is used for real specials + // could we return here? Im not sure is m_atk 11 is used for real specials } - //check range for all these abilities, they are all close combat stuff - if(!CombatRange(GetTarget())) + // check range for all these abilities, they are all close combat stuff + if (!CombatRange(GetTarget())) return; - if(!p_timers.Expired(&database, timer, false)) { - Message(13,"Ability recovery time not yet met."); + if (!p_timers.Expired(&database, timer, false)) { + Message(13, "Ability recovery time not yet met."); return; } @@ -276,18 +276,18 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { int ClientHaste = GetHaste(); int HasteMod = 0; - if(ClientHaste >= 0){ - HasteMod = (10000/(100+ClientHaste)); //+100% haste = 2x as many attacks - } - else{ - HasteMod = (100-ClientHaste); //-100% haste = 1/2 as many attacks - } + if (ClientHaste >= 0) + HasteMod = (10000 / (100 + ClientHaste)); //+100% haste = 2x as many attacks + else + HasteMod = (100 - ClientHaste); //-100% haste = 1/2 as many attacks + int32 dmg = 0; int32 skill_reduction = this->GetSkillReuseTime(ca_atk->m_skill); // not sure what the '100' indicates..if ->m_atk is not used as 'slot' reference, then change SlotRange above back to '11' - if ((ca_atk->m_atk == 100) && (ca_atk->m_skill == EQEmu::skills::SkillBash)) { // SLAM - Bash without a shield equipped + if (ca_atk->m_atk == 100 && + ca_atk->m_skill == EQEmu::skills::SkillBash) { // SLAM - Bash without a shield equipped if (GetTarget() != this) { CheckIncreaseSkill(EQEmu::skills::SkillBash, GetTarget(), 10); @@ -295,31 +295,21 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { int32 ht = 0; if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotSecondary)) <= 0 && - GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotShoulders)) <= 0){ + GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotShoulders)) <= 0) dmg = -5; - } - else{ - if (!GetTarget()->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) { - dmg = 0; - ht = GetBaseSkillDamage(EQEmu::skills::SkillBash, GetTarget()); - } - else{ - ht = dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash, GetTarget()); - } - } + else + ht = dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash, GetTarget()); - ReuseTime = BashReuseTime-1-skill_reduction; - ReuseTime = (ReuseTime*HasteMod)/100; - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillBash, dmg, 0, ht, ReuseTime); - if(ReuseTime > 0) - { + ReuseTime = BashReuseTime - 1 - skill_reduction; + ReuseTime = (ReuseTime * HasteMod) / 100; + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillBash, dmg, 0, ht, ReuseTime, true); + if (ReuseTime > 0) p_timers.Start(timer, ReuseTime); - } } return; } - if ((ca_atk->m_atk == 100) && (ca_atk->m_skill == EQEmu::skills::SkillFrenzy)){ + if (ca_atk->m_atk == 100 && ca_atk->m_skill == EQEmu::skills::SkillFrenzy) { CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10); int AtkRounds = 3; int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy, GetTarget()); @@ -327,102 +317,96 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) { max_dmg = mod_frenzy_damage(max_dmg); - ReuseTime = FrenzyReuseTime-1-skill_reduction; - ReuseTime = (ReuseTime*HasteMod)/100; + ReuseTime = FrenzyReuseTime - 1 - skill_reduction; + ReuseTime = (ReuseTime * HasteMod) / 100; - //Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit. - while(AtkRounds > 0) { + // Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit. + while (AtkRounds > 0) { if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, 0, max_dmg, ReuseTime, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, 0, max_dmg, + ReuseTime, true); } AtkRounds--; } - if(ReuseTime > 0) { + if (ReuseTime > 0) p_timers.Start(timer, ReuseTime); - } return; } - switch(GetClass()){ - case BERSERKER: - case WARRIOR: - case RANGER: - case BEASTLORD: - if (ca_atk->m_atk != 100 || ca_atk->m_skill != EQEmu::skills::SkillKick) { - break; - } - if (GetTarget() != this) { - CheckIncreaseSkill(EQEmu::skills::SkillKick, GetTarget(), 10); - DoAnim(animKick); - - int32 ht = 0; - if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0){ - dmg = -5; - } - else{ - if (!GetTarget()->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) { - dmg = 0; - ht = GetBaseSkillDamage(EQEmu::skills::SkillKick, GetTarget()); - } - else{ - ht = dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick, GetTarget()); - } - } - - ReuseTime = KickReuseTime-1-skill_reduction; - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillKick, dmg, 0, ht, ReuseTime); - - } + switch (GetClass()) { + case BERSERKER: + case WARRIOR: + case RANGER: + case BEASTLORD: + if (ca_atk->m_atk != 100 || ca_atk->m_skill != EQEmu::skills::SkillKick) break; - case MONK: { - ReuseTime = MonkSpecialAttack(GetTarget(), ca_atk->m_skill) - 1 - skill_reduction; + if (GetTarget() != this) { + CheckIncreaseSkill(EQEmu::skills::SkillKick, GetTarget(), 10); + DoAnim(animKick); - //Live AA - Technique of Master Wu - int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; - if (wuchance) { - if (wuchance >= 100 || zone->random.Roll(wuchance)) { - const int MonkSPA[5] = { EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, EQEmu::skills::SkillRoundKick }; - int extra = 1; - // always 1/4 of the double attack chance, 25% at rank 5 (100/4) - if (zone->random.Roll(wuchance / 4)) - extra++; - // They didn't add a string ID for this. - std::string msg = StringFormat("The spirit of Master Wu fills you! You gain %d additional attack(s).", extra); - // live uses 400 here -- not sure if it's the best for all clients though - SendColoredText(400, msg); - auto classic = RuleB(Combat, ClassicMasterWu); - while (extra) { - MonkSpecialAttack(GetTarget(), classic ? MonkSPA[zone->random.Int(0, 4)] : ca_atk->m_skill); - extra--; - } - } - } + int32 ht = 0; + if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0) + dmg = -5; + else + ht = dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick, GetTarget()); - if(ReuseTime < 100) { - //hackish... but we return a huge reuse time if this is an - // invalid skill, otherwise, we can safely assume it is a - // valid monk skill and just cast it to a SkillType - CheckIncreaseSkill((EQEmu::skills::SkillType) ca_atk->m_skill, GetTarget(), 10); - } - break; + ReuseTime = KickReuseTime - 1 - skill_reduction; + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillKick, dmg, 0, ht, ReuseTime, true); } - case ROGUE: { - if (ca_atk->m_atk != 100 || ca_atk->m_skill != EQEmu::skills::SkillBackstab) { - break; + break; + case MONK: { + ReuseTime = MonkSpecialAttack(GetTarget(), ca_atk->m_skill) - 1 - skill_reduction; + + // Live AA - Technique of Master Wu + int wuchance = + itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; + if (wuchance) { + if (wuchance >= 100 || zone->random.Roll(wuchance)) { + const int MonkSPA[5] = {EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, + EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, + EQEmu::skills::SkillRoundKick}; + int extra = 1; + // always 1/4 of the double attack chance, 25% at rank 5 (100/4) + if (zone->random.Roll(wuchance / 4)) + extra++; + // They didn't add a string ID for this. + std::string msg = StringFormat( + "The spirit of Master Wu fills you! You gain %d additional attack(s).", extra); + // live uses 400 here -- not sure if it's the best for all clients though + SendColoredText(400, msg); + auto classic = RuleB(Combat, ClassicMasterWu); + while (extra) { + MonkSpecialAttack(GetTarget(), + classic ? MonkSPA[zone->random.Int(0, 4)] : ca_atk->m_skill); + extra--; + } } - ReuseTime = BackstabReuseTime-1 - skill_reduction; - TryBackstab(GetTarget(), ReuseTime); - break; } - default: - //they have no abilities... wtf? make em wait a bit - ReuseTime = 9 - skill_reduction; + + if (ReuseTime < 100) { + // hackish... but we return a huge reuse time if this is an + // invalid skill, otherwise, we can safely assume it is a + // valid monk skill and just cast it to a SkillType + CheckIncreaseSkill((EQEmu::skills::SkillType)ca_atk->m_skill, GetTarget(), 10); + } + break; + } + case ROGUE: { + if (ca_atk->m_atk != 100 || ca_atk->m_skill != EQEmu::skills::SkillBackstab) break; + ReuseTime = BackstabReuseTime-1 - skill_reduction; + TryBackstab(GetTarget(), ReuseTime); + break; + } + default: + //they have no abilities... wtf? make em wait a bit + ReuseTime = 9 - skill_reduction; + break; } - ReuseTime = (ReuseTime*HasteMod)/100; - if(ReuseTime > 0){ + ReuseTime = (ReuseTime * HasteMod) / 100; + if (ReuseTime > 0) { p_timers.Start(timer, ReuseTime); } } From 0d84a73e9f8acfa81eaaee7c08cabc89197ef051 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 15 Jan 2017 22:54:50 -0500 Subject: [PATCH 501/693] Clean up MonkSpecialAttack too --- zone/special_attacks.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index a9fcf82b1..929c272d9 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -476,27 +476,24 @@ int Mob::MonkSpecialAttack(Mob *other, uint8 unchecked_type) if (IsClient()) { if (GetWeaponDamage(other, CastToClient()->GetInv().GetItem(itemslot)) <= 0) { - ndamage = -5; + max_dmg = -5; } } else { if (GetWeaponDamage(other, (const EQEmu::ItemData *)nullptr) <= 0) { - ndamage = -5; + max_dmg = -5; } } int32 ht = 0; - if (ndamage == 0) { + if (max_dmg > 0) ht = max_dmg; - if (other->CheckHitChance(this, skill_type, 0)) - ndamage = max_dmg; - } // This can potentially stack with changes to kick damage ht = ndamage = mod_monk_special_damage(ndamage, skill_type); - DoSpecialAttackDamage(other, skill_type, ndamage, min_dmg, ht, reuse); + DoSpecialAttackDamage(other, skill_type, max_dmg, min_dmg, ht, reuse, true); - return (reuse); + return reuse; } void Mob::TryBackstab(Mob *other, int ReuseTime) { From fb820f4fecfee050a1ba3986e61f3a2044e55c4e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 16 Jan 2017 16:58:32 -0500 Subject: [PATCH 502/693] Add Creamo's SQL to rebalance NPCs --- .../2017_01_16_NPCCombatRebalance.sql | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 utils/sql/git/optional/2017_01_16_NPCCombatRebalance.sql diff --git a/utils/sql/git/optional/2017_01_16_NPCCombatRebalance.sql b/utils/sql/git/optional/2017_01_16_NPCCombatRebalance.sql new file mode 100644 index 000000000..43bd3e9bb --- /dev/null +++ b/utils/sql/git/optional/2017_01_16_NPCCombatRebalance.sql @@ -0,0 +1,25 @@ +update npc_types set attack_speed=0, atk=ceil(1.7*level), accuracy=ceil(1.7*level) where (name like 'Swarm%' or name like '%skel%' or name like 'BLpet%' or name like 'Sum%') +and id >510 and id <860; +update npc_types set attack_speed=0, atk=ceil(0.5*level), accuracy=ceil(0.5*level) where name like 'SumFire%'; +update npc_types set attack_speed=0, atk=ceil(1.8*level), accuracy=ceil(1.8*level) where name like 'SumAir%'; +update npc_types set attack_speed=0, atk=ceil(1.8*level), accuracy=ceil(1.8*level) where name like 'SumEarth%'; +update npc_types set attack_speed=0, atk=ceil(2.4*level), accuracy=ceil(2.4*level),gender=2,size=3 where name like 'BestialAid%'; +update npc_types set attack_speed=0, atk=ceil(2.4*level), accuracy=ceil(2.4*level),gender=2,size=3 where name like 'RagingServant%'; + + +update npc_types n +set ac= +ceil(case +when level < 3 then level*2+2 +when level < 15 and level >=3 then level*3 +when id >= 200000 and id < 224000 then 200*.5+level +else level * 4.1 end +* (case when raid_target=1 then 1.4 else 1 end) + (case when raid_target=1 then level*1.4 else 0 end)) ++ 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5) +,str=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5) +,sta=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5) +,agi=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5) +,_int=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5) +,dex=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5) +,wis=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5) +,cha=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5); \ No newline at end of file From 698a814fc3953ef0cb11f1578ce26741a8f48d6c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 16 Jan 2017 17:02:34 -0500 Subject: [PATCH 503/693] Add KLS' combat sim This will show you the distribution of hits for a given offense and mitigation DI 1 is the min hit and DI 20 is the max hit --- utils/combat-sim/app.js | 138 ++++++++++++++++++++++++++++++++++++ utils/combat-sim/index.html | 30 ++++++++ utils/combat-sim/style.css | 3 + 3 files changed, 171 insertions(+) create mode 100644 utils/combat-sim/app.js create mode 100644 utils/combat-sim/index.html create mode 100644 utils/combat-sim/style.css diff --git a/utils/combat-sim/app.js b/utils/combat-sim/app.js new file mode 100644 index 000000000..691a41c96 --- /dev/null +++ b/utils/combat-sim/app.js @@ -0,0 +1,138 @@ +var app = angular.module('app', ['nvd3']); + +app.controller('MainCtrl', function($scope, $interval) { + $scope.options = { + chart: { + type: 'discreteBarChart', + height: 450, + margin: { + top: 20, + right: 20, + bottom: 50, + left: 55 + }, + x: function(d) { + return d.label; + }, + y: function(d) { + return d.value + (1e-10); + }, + showValues: true, + valueFormat: function(d) { + return d3.format(',.2r')(d); + }, + duration: 500, + xAxis: { + axisLabel: 'D1-D20' + }, + yAxis: { + axisLabel: 'Count' + } + } + }; + + $scope.offense = 100; + $scope.defense = 100; + + $scope.data = [{ + key: "Cumulative Return", + values: [] + }]; + + for (var i = 0; i < 20; ++i) { + var value = { + "label": i + 1, + "value": 0 + }; + $scope.data[0].values.push(value); + } + + function addRoll(interval) { + $scope.data[0].values[interval - 1].value += 1; + } + + var stop; + $scope.clearData = function() { + console.log('Clearing data'); + for (var i = 0; i < 20; ++i) { + $scope.data[0].values[i].value = 0; + } + }; + + $scope.start = function() { + if (angular.isDefined(stop)) + return; + + stop = $interval(doCombatRound, 100); + }; + + $scope.stop = function() { + if (angular.isDefined(stop)) { + $interval.cancel(stop); + stop = undefined; + } + }; + + $scope.$on('$destroy', function() { + $scope.stop(); + }); + + function getRandomInt(min, max) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min)) + min; + } + + function getRandom(min, max) { + return Math.random() * (max - min) + min; + } + + function addChance(bucket, chance, value) { + for (var i = 0; i < chance; ++i) { + bucket.push(value); + } + } + + function doCombatRound() { + var offense = $scope.offense; + var defense = $scope.defense; + defense = defense - ((defense - offense) / 2.0); + var diff = offense - defense; + var mean = 0.0; + var mult1 = 0.0; + var mult2 = 0.0; + + if (offense > 30.0) { + mult1 = offense / 200.0 + 25.75; + if ((defense / offense) < 0.35) { + mult1 = mult1 + 1.0; + } else if ((defense / offense) > 0.65) { + mult1 = mult1 - 1.0; + } + mult2 = offense / 140 + 18.5; + } else { + mult1 = 11.5 + offense / 2.0; + mult2 = 14.0 + offense / 6.0; + } + + if (offense > defense) { + mean = diff / offense * mult1; + } else if (defense > offense) { + mean = diff / defense * mult2; + } + + var stddev = 8.8; + var theta = 2 * Math.PI * getRandom(0.0, 1.0); + var rho = Math.sqrt(-2 * Math.log(1 - getRandom(0.0, 1.0))); + var d = mean + stddev * rho * Math.cos(theta); + + if (d < -9.5) { + d = -9.5; + } else if (d > 9.5) { + d = 9.5; + } + d = d + 11; + addRoll(parseInt(d)); + }; +}); + diff --git a/utils/combat-sim/index.html b/utils/combat-sim/index.html new file mode 100644 index 000000000..783177051 --- /dev/null +++ b/utils/combat-sim/index.html @@ -0,0 +1,30 @@ + + + + + Combat Visualization + + + + + + + + + + + + + + + +
+ + +
+
+ + +
+ + diff --git a/utils/combat-sim/style.css b/utils/combat-sim/style.css new file mode 100644 index 000000000..c427aa7f4 --- /dev/null +++ b/utils/combat-sim/style.css @@ -0,0 +1,3 @@ +.input-row { + padding: 8px; +} \ No newline at end of file From 18e6e5e5e28f0f482b4db1e7916bb16406409197 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 16 Jan 2017 17:05:57 -0500 Subject: [PATCH 504/693] Rename Defense to Mitigation on sim (since that's what it is) --- utils/combat-sim/app.js | 18 +++++++++--------- utils/combat-sim/index.html | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/utils/combat-sim/app.js b/utils/combat-sim/app.js index 691a41c96..ce5a7ac69 100644 --- a/utils/combat-sim/app.js +++ b/utils/combat-sim/app.js @@ -32,7 +32,7 @@ app.controller('MainCtrl', function($scope, $interval) { }; $scope.offense = 100; - $scope.defense = 100; + $scope.mitigation = 100; $scope.data = [{ key: "Cumulative Return", @@ -95,18 +95,18 @@ app.controller('MainCtrl', function($scope, $interval) { function doCombatRound() { var offense = $scope.offense; - var defense = $scope.defense; - defense = defense - ((defense - offense) / 2.0); - var diff = offense - defense; + var mitigation = $scope.mitigation; + mitigation = mitigation - ((mitigation - offense) / 2.0); + var diff = offense - mitigation; var mean = 0.0; var mult1 = 0.0; var mult2 = 0.0; if (offense > 30.0) { mult1 = offense / 200.0 + 25.75; - if ((defense / offense) < 0.35) { + if ((mitigation / offense) < 0.35) { mult1 = mult1 + 1.0; - } else if ((defense / offense) > 0.65) { + } else if ((mitigation / offense) > 0.65) { mult1 = mult1 - 1.0; } mult2 = offense / 140 + 18.5; @@ -115,10 +115,10 @@ app.controller('MainCtrl', function($scope, $interval) { mult2 = 14.0 + offense / 6.0; } - if (offense > defense) { + if (offense > mitigation) { mean = diff / offense * mult1; - } else if (defense > offense) { - mean = diff / defense * mult2; + } else if (mitigation > offense) { + mean = diff / mitigation * mult2; } var stddev = 8.8; diff --git a/utils/combat-sim/index.html b/utils/combat-sim/index.html index 783177051..00d21e722 100644 --- a/utils/combat-sim/index.html +++ b/utils/combat-sim/index.html @@ -23,8 +23,8 @@
- - + +
From f3e09abf22ab3f1ffe1034af7dfaafef6704f683 Mon Sep 17 00:00:00 2001 From: huffin Date: Mon, 16 Jan 2017 19:33:33 -0600 Subject: [PATCH 505/693] Update 2017_01_16_NPCCombatRebalance.sql --- .../sql/git/optional/2017_01_16_NPCCombatRebalance.sql | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/sql/git/optional/2017_01_16_NPCCombatRebalance.sql b/utils/sql/git/optional/2017_01_16_NPCCombatRebalance.sql index 43bd3e9bb..d49b9def9 100644 --- a/utils/sql/git/optional/2017_01_16_NPCCombatRebalance.sql +++ b/utils/sql/git/optional/2017_01_16_NPCCombatRebalance.sql @@ -1,10 +1,10 @@ update npc_types set attack_speed=0, atk=ceil(1.7*level), accuracy=ceil(1.7*level) where (name like 'Swarm%' or name like '%skel%' or name like 'BLpet%' or name like 'Sum%') and id >510 and id <860; update npc_types set attack_speed=0, atk=ceil(0.5*level), accuracy=ceil(0.5*level) where name like 'SumFire%'; -update npc_types set attack_speed=0, atk=ceil(1.8*level), accuracy=ceil(1.8*level) where name like 'SumAir%'; -update npc_types set attack_speed=0, atk=ceil(1.8*level), accuracy=ceil(1.8*level) where name like 'SumEarth%'; -update npc_types set attack_speed=0, atk=ceil(2.4*level), accuracy=ceil(2.4*level),gender=2,size=3 where name like 'BestialAid%'; -update npc_types set attack_speed=0, atk=ceil(2.4*level), accuracy=ceil(2.4*level),gender=2,size=3 where name like 'RagingServant%'; +update npc_types set attack_speed=0, atk=ceil(1.775*level), accuracy=ceil(1.775*level) where name like 'SumAir%'; +update npc_types set attack_speed=0, atk=ceil(1.775*level), accuracy=ceil(1.775*level) where name like 'SumEarth%'; +update npc_types set attack_speed=0, atk=ceil(2.26*level), accuracy=ceil(2.26*level),gender=2,size=3 where name like 'BestialAid%'; +update npc_types set attack_speed=0, atk=ceil(2.26*level), accuracy=ceil(2.26*level),gender=2,size=3 where name like 'RagingServant%'; update npc_types n @@ -22,4 +22,4 @@ else level * 4.1 end ,_int=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5) ,dex=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5) ,wis=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5) -,cha=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5); \ No newline at end of file +,cha=ceil((level * 4.1)*.75) + case when raid_target=1 then level else 0 end + 4*ifnull((select min(expansion)from zone where zoneidnumber=floor(n.id/1000)),5); From 8f21b01b7eaf7006adf417e3fcc7c8d20bc7d76b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 17 Jan 2017 02:52:16 -0500 Subject: [PATCH 506/693] Tweak to accuracy based on newer clients --- zone/attack.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index cdc3bab06..48b58964c 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -169,7 +169,8 @@ int Mob::GetTotalToHit(EQEmu::skills::SkillType skill, int chance_mod) accuracy *= chance_mod; // Torven parsed an apparent constant of 1.2 somewhere in here * 6 / 5 looks eqmathy to me! - accuracy = accuracy * 6 / 5; + // new test clients have 121 / 100 + accuracy = (accuracy * 121) / 100; // unsure on the stacking order of these effects, rather hard to parse // item mod2 accuracy isn't applied to range? Theory crafting and parses back it up I guess From f614c35f6e45d079c31a23b6b584ea3b684147d1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 17 Jan 2017 23:30:50 -0500 Subject: [PATCH 507/693] Combat Revamp -- BREAKING CHANGES -- see changelog Changelog updated for combat revamp --- changelog.txt | 53 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/changelog.txt b/changelog.txt index 33bf2de1a..6a76e3b55 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,18 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/17/2017 == +Mackal: Combat Revamp + - This change brings melee combat into line with how combat is done on live. + - This correctly applies the PC damage tables and corrects stacking order of many spells + - Given the scope of what had to be rewritten, it was not feasible to preserve the old combat system. + This means you will likely have to rebalance your server, which sucks, but this is very + accurate so shouldn't require any more changes, at least none that would cause you to have + to rebalance your server again. + - For rebalancing, I would recommend running the optional SQL and tweaking from there. + - To help with rebalancing there is a simulator included at utils/combat-sim. + - You can enter the mitigation or offense values you would like to balance around (#showstats will show you them) + a 1 on the sim is min damage 20 is max. + - Quick recommendations for best ways to improve PC DPS, give them some worn (or AA) SE_DamageModifier and/or SE_MinDamageModifier == 12/03/2016 == Uleat: Added hack detection to trade code - If illegal items are found in trade slots when the 'trade' button is clicked, the trade is cancelled and a message is sent to the offending player @@ -28,7 +41,7 @@ take into account that rogue was sneaking. Now sneaking rogues can see full inventory on merchants (well, unless an item requires a + faction value). == 09/12/2016 == -Akkadius: Massive overhaul of the update system and EQEmu Server management utility framework +Akkadius: Massive overhaul of the update system and EQEmu Server management utility framework (known as eqemu_update.pl) now known as eqemu_server.pl - eqemu_server.pl is now a general EQEmu Server management utiltiy framework that can be used to extend to many purposes. It's main purpose is to simplify server management @@ -49,7 +62,7 @@ Akkadius: Massive overhaul of the update system and EQEmu Server management util - Regular bots database schema changes now happen automatically similarily to the above - Database checks can also be ran manually via the script menu - CLI Arguments - - Arguments passed to eqemu_server.pl can execute the same name-based operations that + - Arguments passed to eqemu_server.pl can execute the same name-based operations that are present in the interactive menu - Example: "perl eqemu_server.pl opcodes" will download opcodes - Example: "perl eqemu_server.pl backup_player_tables" will backup and export player tables @@ -64,7 +77,7 @@ Akkadius: Massive overhaul of the update system and EQEmu Server management util - server_start_dev.sh - server_start.sh - server_status.sh - - server_stop.sh + - server_stop.sh - Usage analytics - eqemu_server.pl now collects usage analytics, this is very helpful for our developers - Example: We can see how many installs have been performed: @@ -76,10 +89,10 @@ Akkadius: Massive overhaul of the update system and EQEmu Server management util - 'New Server' Utility - Running 'new_server' from the main menu or 'perl eqemu_server.pl new_server' while in a completely new folder with just the script present, will allow a server operator - to initiate a full clean PEQ install in that folder. Pulling down all assets and - installing a PEQ database with the name the server operator gives the prompts in the + to initiate a full clean PEQ install in that folder. Pulling down all assets and + installing a PEQ database with the name the server operator gives the prompts in the script - + == 09/10/2016 == noudess: Task system experience based on a % of a level did not take into account the hell levels rule. Now it does. @@ -133,7 +146,7 @@ Kinglykrab: Implemented optional avoidance cap rules. - Rule Names: - Character:EnableAvoidanceCap (default is false) - Character:AvoidanceCap (default is 750, beyond 1,000 seems to make characters dodge all attacks) - + == 08/02/2016 == Uleat: Changed 'SendZoneSpawnsBulk' behavior to use near/far criteria (live-like) when sending packets. - Zone-to-Zone client loading will see a small decrease in time (less than 10~15%) @@ -171,7 +184,7 @@ mackal: Fix up the SpellBuff struct Uleat: Important fix for mob pathing - This should fix failed pathing issues (and high cpu usage for zone.exe) for mobs in affect zones - Changed variable 'gridno' type from int16 to int32 to reflect actual return value of fetch (values do exceed 32767 aka int16.max) - - Precision loss from int32 to int16 conversion was causing grid id to be changed to quest controlled movement in cases where (gridno & 0x8000 == true) + - Precision loss from int32 to int16 conversion was causing grid id to be changed to quest controlled movement in cases where (gridno & 0x8000 == true) == 06/28/2016 == Noudess: Resurrection effects now block certain buffs like on live. @@ -240,7 +253,7 @@ Uleat: Moved database query code out of bot.cpp and into the new BotDatabase cla == 03/25/2016 == Uleat: Fix for heal rotation 'Stack Overflow' error -Kayen: Defensive procs will now only proc once per attack round (instead of every attack chance). +Kayen: Defensive procs will now only proc once per attack round (instead of every attack chance). Live like modifier added that decreases defensive proc chance if you are higher level then your attacker. == 03/24/2016 == @@ -283,7 +296,7 @@ Kinglykrab: Modified #flag so you can refresh your target's account status (GM s - Just target the person whose flag you want to refresh and type #flag. Uleat: Added itemlink functionality to the #summonitem command. Current use is limited to extracting the item id from the link. - Invoking by item link '#summonitem Arrow' produces the same result as by item id '#summonitem 8005' - + == 01/12/2016 == Athrogate: Adding ClearCompassMark() to Lua. - Lua didn't have ClearCompassMark(). Perl already had this. @@ -313,7 +326,7 @@ Kinglykrab: Added GetInstanceTimer() to Perl and Lua. - Note: If you do not provide an instance id in the method it defaults to instance id 0 and returns 0 for time remaining. - Added UpdateZoneHeader(type, value) to Perl and Lua. - Note: UpdateZoneHeader allows you to manipulate fog color, fog density, and many other zone header settings on the fly in Perl and Lua. - + == 12/21/2015 == Natedog: Updated item table fields and added a few missing fields for evolving items -DO NOT implement Heirloom items till the inventory code is fixed to allow placing NO DROP @@ -322,7 +335,7 @@ Natedog: Updated item table fields and added a few missing fields for evolving i 100% 2HSlashing (Max 50) - can only increase 2hslash by 50 MAX! (item field located though) Kinglykrab: Added GetMeleeMitigation() for NPCs and Clients in Perl and Lua. - This allows you to check total item, spell, and AA melee mitigation contribution. - + == 12/19/2015 == Kinglykrab: Added many methods to Perl and Lua, list below: - SeeInvisible() @@ -344,7 +357,7 @@ Kinglykrab: Added many methods to Perl and Lua, list below: - HasPet() - IsSilenced() - IsAmnesiad() - + == 12/16/2015 == Noudess: Repaired issue with Bind Wounds on someone else. Message was not coming out on client (hold still) and a bind wounds on someone already binding their wounds would interrupt their bind and make them stand. Also removed some duplicate messaging. @@ -353,7 +366,7 @@ Kinglykrab: Added IsBlind() and IsFeared() functionality to Perl and Lua. - Note: Both methods are Mob methods and may be used on NPCs or PCs. Natedog: Added Discipline functions, UpdateInstanceTimer function, and UnmemSpellBySpellID to lua and perl -Examples: http://wiki.eqemulator.org/i?M=Pastebin&Paste=BJ0ygmNM - + == 12/07/2015 == Uleat: Command aliases are no longer handled through the command_add() function. - To add a command alias, edit the database table `command_settings` - here, you will find three columns: `command`, `access` and `aliases` @@ -366,7 +379,7 @@ Uleat: Command aliases are no longer handled through the command_add() function. - If you need need more name space for aliases, simply edit the `command_settings` table and increase the size of the `aliases` column - The old `commands` table has been renamed to `commands_old` for reference - All of the current 'standard' commands have been added to the new `command_settings` table - + - YOU WILL NEED TO VERIFY/IMPORT OLD ACCESS VALUES AS THIS CHANGE REVERTS ALL COMMAND ACCESS VALUES TO THEIR PEQDB DEFAULTS == 11/30/2015 == @@ -388,7 +401,7 @@ Akkadius: Performance boost (exponential) - Adjusted default idle cast check tim - Database version 9089 will take care of this update automatically only if you used the default values - The CPU cost of NPC's checking the entire entity list to cast beneficial spells (Heals/Buffs) becomes extremely high when higher NPC count zones exist (Based off of process profiling) - Distance checks for every single NPC to every single other NPC who are casting beneficial spells occur every .5 - 2 seconds unless npc_spells dictates other values, which most of the time it does not - - Zones that once fluctuated from 1-8% CPU with no activity (Idle but players present) now idle at .5% based on my testings due + - Zones that once fluctuated from 1-8% CPU with no activity (Idle but players present) now idle at .5% based on my testings due to this change in conjunction with the past few performance commits, these are zones that have 600-800 NPC's in them - These values normally are overidden by the spells table (npc_spells), fields (idle_no_sp_recast_min, idle_no_sp_recast_max) @@ -396,7 +409,7 @@ Akkadius: Performance boost (exponential) - Adjusted default idle cast check tim Akkadius: Made many performance optimizing oriented code changes in the source - Added Rate limit the rate in which signals are processed for NPC's (.5 seconds instead of .01 seconds) Akkadius: Added Perl Export Settings which should heavily reduce the Perl footprint - - Normally when any sub EVENT_ gets triggered, all kinds of variables have to get exported every single time an event is triggered and + - Normally when any sub EVENT_ gets triggered, all kinds of variables have to get exported every single time an event is triggered and this can make Perl very slow when events are triggered constantly - The two most taxing variable exports are the item variables ($itemcount{} $hasitem{} $oncursor{}) and qglobals ($qglobals{}) - qglobals can pose to be an issue quickly when global qglobals build up, it is highly recommend to use the GetGlobal() and SetGlobal() @@ -424,7 +437,7 @@ Akkadius: Added Perl Export Settings which should heavily reduce the Perl footpr | 4 | EVENT_ATTACK | 0 | 1 | 1 | 0 | 1 | | 5 | EVENT_COMBAT | 1 | 1 | 1 | 0 | 1 | +----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+ - + - If a change is made to this table while the server is live and running, you can hot reload all zone process settings via: #reloadperlexportsettings - For those who wonder what "exports" are, they are reference to variables that are made available at runtime of the sub event, such as: @@ -433,7 +446,7 @@ Akkadius: Added Perl Export Settings which should heavily reduce the Perl footpr (export_zone) : $zoneid, $instanceid, $zoneln etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1083 (export_mob) : $x, $y, $z, $h, $hpratio etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1032 (export_event) : (event specific) IE: EVENT_SAY ($text) https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1141 - + == 10/16/2015 == Uleat: Added command '#bot clearfollowdistance [ | spawned | all ]' to coincide with the activation of the load/save feature for follow_distance @@ -465,7 +478,7 @@ rules: commands: '#invsnapshot' - Takes a snapshot of target client's inventory (feature active or inactive) '#clearinvsnapshots [use rule]' - Clears snapshot entries based on bool argument ([true] - honors the 'InvSnapshotHistoryD' rule, [false] - erases all) - + == 08/02/2015 == Shendare: VS2013 query StringFormat glitches when "%f" is passed for the int GetRunSpeed(). Shendare: In CreateNewNPCCommand(), the npc_type_id and spawngroupid are created in the database, but never set in the spawn class, so later it can't delete them with #npcspawn remove or #npcspawn delete. From 9aba99388837049bd6a34ffea019003a6de3913c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 17 Jan 2017 23:34:52 -0500 Subject: [PATCH 508/693] Add optional rule SQL for combat update [skip ci] --- utils/sql/git/optional/2017_01_17_LevelStopDamageCaps.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 utils/sql/git/optional/2017_01_17_LevelStopDamageCaps.sql diff --git a/utils/sql/git/optional/2017_01_17_LevelStopDamageCaps.sql b/utils/sql/git/optional/2017_01_17_LevelStopDamageCaps.sql new file mode 100644 index 000000000..f6e1cf35a --- /dev/null +++ b/utils/sql/git/optional/2017_01_17_LevelStopDamageCaps.sql @@ -0,0 +1,2 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Combat:LevelToStopDamageCaps', '0', '1 will effectively disable them, 20 should give basically same results as old incorrect system.'); + From 2c6e11b4642c147aaa54a9ce6444344ddb2ab8a0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 19 Jan 2017 23:17:14 -0500 Subject: [PATCH 509/693] Have modify NPC stat AC/AGI recache AC --- zone/npc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index ebff4786a..c327db11f 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1959,10 +1959,10 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) id[i] = std::tolower(id[i]); } - if(id == "ac") { AC = atoi(val.c_str()); return; } + if(id == "ac") { AC = atoi(val.c_str()); CalcAC(); return; } else if(id == "str") { STR = atoi(val.c_str()); return; } else if(id == "sta") { STA = atoi(val.c_str()); return; } - else if(id == "agi") { AGI = atoi(val.c_str()); return; } + else if(id == "agi") { AGI = atoi(val.c_str()); CalcAC(); return; } else if(id == "dex") { DEX = atoi(val.c_str()); return; } else if(id == "wis") { WIS = atoi(val.c_str()); CalcMaxMana(); return; } else if(id == "int" || id == "_int") { INT = atoi(val.c_str()); CalcMaxMana(); return; } From 905e3acab3ea3e97b2641315d376ee4e175aaa58 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 20 Jan 2017 23:27:19 -0500 Subject: [PATCH 510/693] Fix bots? --- zone/bot.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index ac6a6ddd7..a592ab94f 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3705,16 +3705,16 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b } } - int min_cap = (base_damage * GetMeleeMinDamageMod_SE(skillinuse) / 100); + int min_cap = (weapon_damage * GetMeleeMinDamageMod_SE(skillinuse) / 100); Log.Out(Logs::Detail, Logs::Combat, "Damage calculated to %d (bonus %d, base %d, str %d, skill %d, DMG %d, lv %d)", - damage, min_damage, base_damage, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel); + damage, min_damage, weapon_damage, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel); auto offense = this->offense(skillinuse); if(opts) { - base_damage *= opts->damage_percent; - base_damage += opts->damage_flat; + weapon_damage *= opts->damage_percent; + weapon_damage += opts->damage_flat; hate *= opts->hate_percent; hate += opts->hate_flat; } @@ -3736,7 +3736,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b } } else { if (other->CheckHitChance(this, skillinuse)) { - other->MeleeMitigation(this, damage, base_damage, offense, skillinuse, opts); + other->MeleeMitigation(this, damage, weapon_damage, offense, skillinuse, opts); if (damage > 0) { ApplyDamageTable(damage, offense); CommonOutgoingHitSuccess(other, damage, min_damage, min_cap, skillinuse, opts); From 7033d9d91988b2e3e0a6dd15388c05b49e23d1eb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 21 Jan 2017 01:47:06 -0500 Subject: [PATCH 511/693] memleak fix --- zone/object.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zone/object.cpp b/zone/object.cpp index 15c14a77c..3097ceba1 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -225,8 +225,7 @@ Object::Object(const char *model, float x, float y, float z, float heading, uint { user = nullptr; last_user = nullptr; - EQEmu::ItemInstance* inst = nullptr; - inst = new EQEmu::ItemInstance(ItemInstWorldContainer); + EQEmu::ItemInstance* inst = new EQEmu::ItemInstance(ItemInstWorldContainer); // Initialize members m_id = 0; @@ -257,6 +256,8 @@ Object::Object(const char *model, float x, float y, float z, float heading, uint strcpy(m_data.object_name, model); else strcpy(m_data.object_name, "IT64_ACTORDEF"); //default object name if model isn't specified for some unknown reason + + safe_delete(inst); } Object::~Object() From ae81ab8a124baae1faa1138ae3bc7bba0d20dffa Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 21 Jan 2017 21:38:32 -0500 Subject: [PATCH 512/693] Fix for obscure crash related to bots and GetNeedsCured() --- zone/bot.cpp | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index a592ab94f..86e56fc9a 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -8008,29 +8008,11 @@ bool Bot::GetNeedsCured(Mob *tar) { bool needCured = false; if(tar) { if(tar->FindType(SE_PoisonCounter) || tar->FindType(SE_DiseaseCounter) || tar->FindType(SE_CurseCounter) || tar->FindType(SE_CorruptionCounter)) { - uint32 buff_count = GetMaxTotalSlots(); + uint32 buff_count = tar->GetMaxTotalSlots(); int buffsWithCounters = 0; needCured = true; for (unsigned int j = 0; j < buff_count; j++) { - // this should prevent crashes until the cause can be found - if (!tar->GetBuffs()) { - std::string mob_type = "Unknown"; - if (tar->IsClient()) - mob_type = "Client"; - else if (tar->IsBot()) - mob_type = "Bot"; - else if (tar->IsMerc()) - mob_type = "Merc"; - else if (tar->IsPet()) - mob_type = "Pet"; - else if (tar->IsNPC()) - mob_type = "NPC"; - - Log.Out(Logs::General, Logs::Error, "Bot::GetNeedsCured() processed mob type '%s' with a null buffs pointer (mob: '%s')", mob_type.c_str(), tar->GetName()); - - continue; - } - else if(tar->GetBuffs()[j].spellid != SPELL_UNKNOWN) { + if(tar->GetBuffs()[j].spellid != SPELL_UNKNOWN) { if(CalculateCounters(tar->GetBuffs()[j].spellid) > 0) { buffsWithCounters++; if(buffsWithCounters == 1 && (tar->GetBuffs()[j].ticsremaining < 2 || (int32)((tar->GetBuffs()[j].ticsremaining * 6) / tar->GetBuffs()[j].counters) < 2)) { From 31de6a63ccf2309d37cd14e70fcbb6dc2b69fbd5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 25 Jan 2017 21:08:59 -0500 Subject: [PATCH 513/693] Fix bot frenzy --- zone/bot.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 86e56fc9a..bc9166b63 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -4718,7 +4718,7 @@ int Bot::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target) base++; return base; case EQEmu::skills::SkillFrenzy: - if (GetBotItem(EQEmu::inventory::slotSecondary)) { + if (GetBotItem(EQEmu::inventory::slotPrimary)) { if (GetLevel() > 15) base += GetLevel() - 15; if (base > 23) From 3d54a4edcb8c23e1b5b393a77881ec2062bba16e Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 26 Jan 2017 14:37:51 -0500 Subject: [PATCH 514/693] Eliminated Rogue Bot twirling combat behavior. --- changelog.txt | 3 +++ zone/bot.cpp | 36 +++++++++++++++++++----------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/changelog.txt b/changelog.txt index 6a76e3b55..7a9a0fa65 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/26/2017 == +Uleat: Change rogue bot behavior to eliminate twirling combat. They will only get behind the mob if they are not the mob's target or if the mob is feared or fleeing. This may lower rogue bot dps a small fraction..but, is more in-line with realistic game mechanics. + == 01/17/2017 == Mackal: Combat Revamp - This change brings melee combat into line with how combat is done on live. diff --git a/zone/bot.cpp b/zone/bot.cpp index bc9166b63..e751f4865 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2305,24 +2305,26 @@ void Bot::AI_Process() { } if(AI_movement_timer->Check()) { - if(!IsMoving() && GetClass() == ROGUE && !BehindMob(GetTarget(), GetX(), GetY())) { - // Move the rogue to behind the mob - float newX = 0; - float newY = 0; - float newZ = 0; - if(PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) { - CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); - return; + if (!IsMoving()) { + if (GetClass() == ROGUE && (GetTarget() != this || GetTarget()->IsFeared()) && !BehindMob(GetTarget(), GetX(), GetY())) { + // Move the rogue to behind the mob + float newX = 0; + float newY = 0; + float newZ = 0; + if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) { + CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); + return; + } } - } - else if(!IsMoving() && GetClass() != ROGUE && (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) < GetTarget()->GetSize())) { - // If we are not a rogue trying to backstab, let's try to adjust our melee range so we don't appear to be bunched up - float newX = 0; - float newY = 0; - float newZ = 0; - if(PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) { - CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); - return; + else if (GetClass() != ROGUE && (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) < GetTarget()->GetSize())) { + // If we are not a rogue trying to backstab, let's try to adjust our melee range so we don't appear to be bunched up + float newX = 0; + float newY = 0; + float newZ = 0; + if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) { + CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); + return; + } } } From 36300d6df1d0f94acac029a19c00ddc16c7695d0 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 26 Jan 2017 17:29:39 -0500 Subject: [PATCH 515/693] Removed SE_NegateIfCombat movement spells from bot commands (i.e., Scale of Wolf) --- zone/bot_command.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 17182451f..fa15dc7d2 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -436,6 +436,8 @@ public: case 10: if (spells[spell_id].effectdescnum != 65) break; + if (IsEffectInSpell(spell_id, SE_NegateIfCombat)) + break; entry_prototype = new STMovementSpeedEntry(); entry_prototype->SafeCastToMovementSpeed()->group = BCSpells::IsGroupType(target_type); break; From cdf0d5deb0ca6b690557037c16b0cf0aa27e209a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 26 Jan 2017 18:04:59 -0500 Subject: [PATCH 516/693] Fix crash --- zone/mob.cpp | 2 ++ zone/mob.h | 3 ++- zone/spells.cpp | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index d8b10874e..bcaa43ccc 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -286,6 +286,8 @@ Mob::Mob(const char* in_name, armor_tint.Slot[i].Color = in_armor_tint.Slot[i].Color; } + std::fill(std::begin(m_spellHitsLeft), std::end(m_spellHitsLeft), 0); + m_Delta = glm::vec4(); animation = 0; diff --git a/zone/mob.h b/zone/mob.h index 6e390d7d6..0dfa162c1 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1414,7 +1414,8 @@ protected: glm::vec3 m_TargetRing; - uint32 m_spellHitsLeft[38]; // Used to track which spells will have their numhits incremented when spell finishes casting, 38 Buffslots + // we might want to do this differently, we gotta do max NPC buffs ... which is 97 + uint32 m_spellHitsLeft[EQEmu::constants::TotalBuffs]; // Used to track which spells will have their numhits incremented when spell finishes casting int flymode; bool m_targetable; int QGVarDuration(const char *fmt); diff --git a/zone/spells.cpp b/zone/spells.cpp index 9fcfc56d2..f37f2fc53 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5565,6 +5565,7 @@ void Client::InitializeBuffSlots() for(int x = 0; x < max_slots; ++x) { buffs[x].spellid = SPELL_UNKNOWN; + buffs[x].UpdateClient = false; } current_buff_count = 0; } @@ -5581,6 +5582,7 @@ void NPC::InitializeBuffSlots() for(int x = 0; x < max_slots; ++x) { buffs[x].spellid = SPELL_UNKNOWN; + buffs[x].UpdateClient = false; } current_buff_count = 0; } From 104a0998ceef2cf18a4afafb6075e3cc82ce925e Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 27 Jan 2017 21:28:25 -0500 Subject: [PATCH 517/693] Added rogue evade to bot combat (nothing is every really fixed until you do it a second time and add a timer...) --- zone/bot.cpp | 41 +++++++++++++++++++++++++++++++++-------- zone/bot.h | 2 ++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index e751f4865..7edbbbebb 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -176,6 +176,9 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to for (int i = 0; i < MaxTimer; i++) timers[i] = 0; + if (GetClass() == ROGUE) + evade_timer.Start(); + GenerateBaseStats(); if (!botdb.LoadTimers(this) && bot_owner) @@ -2306,14 +2309,36 @@ void Bot::AI_Process() { if(AI_movement_timer->Check()) { if (!IsMoving()) { - if (GetClass() == ROGUE && (GetTarget() != this || GetTarget()->IsFeared()) && !BehindMob(GetTarget(), GetX(), GetY())) { - // Move the rogue to behind the mob - float newX = 0; - float newY = 0; - float newZ = 0; - if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) { - CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); - return; + if (GetClass() == ROGUE) { + if ((GetTarget()->GetTarget() == this) && !GetTarget()->IsFeared() && !GetTarget()->IsStunned()) { + if (evade_timer.Check(false)) { + // Hate redux actions + uint32 timer_duration = (HideReuseTime * 1000); + evade_timer.Start(timer_duration); + + Bot::BotGroupSay(this, "Attempting to evade %s", GetTarget()->GetCleanName()); + if (zone->random.Int(0, 260) < (int)GetSkill(EQEmu::skills::SkillHide)) + RogueEvade(GetTarget()); + + return; + } + //else if (GetTarget()->IsRooted()) { + // Should move rogue backwards, out of combat range + //} + + // Could add a bot accessor like.. + // bool NeedsHateRedux() { return (GetClass() == Rogue && evade_timer.check(false)); } - or something like this + // ..then add hate redux spells to caster combat repertoires + } + else if (!BehindMob(GetTarget(), GetX(), GetY())) { + // Move the rogue to behind the mob + float newX = 0; + float newY = 0; + float newZ = 0; + if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) { + CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); + return; + } } } else if (GetClass() != ROGUE && (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) < GetTarget()->GetSize())) { diff --git a/zone/bot.h b/zone/bot.h index 15a1b0938..177efeffb 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -670,6 +670,8 @@ private: glm::vec3 m_PreSummonLocation; uint8 _spellCastingChances[MaxStances][MaxSpellTypes]; + Timer evade_timer; + std::shared_ptr m_member_of_heal_rotation; std::map botAAs; From 05cb9d56c283f829bc17fcdb9b33f0e5bac5db6d Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 27 Jan 2017 23:17:25 -0500 Subject: [PATCH 518/693] Modded 2017_01_10_book_languages.sql to eliminate error message --- utils/sql/git/required/2017_01_10_book_languages.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/git/required/2017_01_10_book_languages.sql b/utils/sql/git/required/2017_01_10_book_languages.sql index 508cdc156..aa767cd03 100644 --- a/utils/sql/git/required/2017_01_10_book_languages.sql +++ b/utils/sql/git/required/2017_01_10_book_languages.sql @@ -1,6 +1,6 @@ alter table books add language int default 0; -drop table reading_is_fundamental; +drop table if exists reading_is_fundamental; create table reading_is_fundamental ( From e300f82c28ca748660572e2dac172c4f4832d44d Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 28 Jan 2017 16:07:58 -0500 Subject: [PATCH 519/693] Added "rooted mob" conditional to rogue bot hate redux methods --- zone/bot.cpp | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 7edbbbebb..42ca396af 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2311,9 +2311,12 @@ void Bot::AI_Process() { if (!IsMoving()) { if (GetClass() == ROGUE) { if ((GetTarget()->GetTarget() == this) && !GetTarget()->IsFeared() && !GetTarget()->IsStunned()) { + // Hate redux actions if (evade_timer.Check(false)) { - // Hate redux actions - uint32 timer_duration = (HideReuseTime * 1000); + // Attempt to evade + int timer_duration = (HideReuseTime - GetSkillReuseTime(EQEmu::skills::SkillHide)) * 1000; + if (timer_duration < 0) + timer_duration = 0; evade_timer.Start(timer_duration); Bot::BotGroupSay(this, "Attempting to evade %s", GetTarget()->GetCleanName()); @@ -2322,9 +2325,23 @@ void Bot::AI_Process() { return; } - //else if (GetTarget()->IsRooted()) { - // Should move rogue backwards, out of combat range - //} + else if (GetTarget()->IsRooted()) { + // Move rogue back from rooted mob - out of combat range, if necessary + float melee_distance = GetMaxMeleeRangeToTarget(GetTarget()); + float current_distance = DistanceSquared(static_cast(m_Position), static_cast(GetTarget()->GetPosition())); + + if (current_distance <= melee_distance) { + float newX = 0; + float newY = 0; + float newZ = 0; + FaceTarget(GetTarget()); + if (PlotPositionAroundTarget(this, newX, newY, newZ)) { + Bot::BotGroupSay(this, "Backing off of %s", GetTarget()->GetCleanName()); + CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); + return; + } + } + } // Could add a bot accessor like.. // bool NeedsHateRedux() { return (GetClass() == Rogue && evade_timer.check(false)); } - or something like this From 37e87e8cef23994a7b2f9d444b68f8cfcb672d38 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 28 Jan 2017 19:38:44 -0500 Subject: [PATCH 520/693] Rework combat to make use of a struct to fix some bugs --- common/ruletypes.h | 11 +- utils/combat-sim/app.js | 53 +-- zone/attack.cpp | 664 +++++++++++++-------------- zone/bonuses.cpp | 47 +- zone/bot.cpp | 151 +++--- zone/bot.h | 2 +- zone/common.h | 23 +- zone/lua_mob.cpp | 7 - zone/lua_mob.h | 1 - zone/merc.cpp | 22 +- zone/mob.h | 27 +- zone/special_attacks.cpp | 970 ++++++++++++++++++--------------------- 12 files changed, 893 insertions(+), 1085 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 2b0b71899..21c4949ea 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -392,15 +392,12 @@ RULE_BOOL(Spells, NPCInnateProcOverride, true) // NPC innate procs override the RULE_CATEGORY_END() RULE_CATEGORY(Combat) -RULE_INT(Combat, MeleeBaseCritChance, 0) //The base crit chance for non warriors, NOTE: This will apply to NPCs as well -RULE_INT(Combat, WarBerBaseCritChance, 3) //The base crit chance for warriors and berserkers, only applies to clients -RULE_INT(Combat, BerserkBaseCritChance, 6) //The bonus base crit chance you get when you're berserk +RULE_INT(Combat, PetBaseCritChance, 0) // Pet Base crit chance RULE_INT(Combat, NPCBashKickLevel, 6) //The level that npcs can KICK/BASH RULE_INT(Combat, NPCBashKickStunChance, 15) //Percent chance that a bash/kick will stun -RULE_INT(Combat, RogueCritThrowingChance, 25) //Rogue throwing crit bonus -RULE_INT(Combat, RogueDeadlyStrikeChance, 80) //Rogue chance throwing from behind crit becomes a deadly strike -RULE_INT(Combat, RogueDeadlyStrikeMod, 2) //Deadly strike modifier to crit damage -RULE_INT(Combat, ClientBaseCritChance, 0) //The base crit chance for all clients, this will stack with warrior's/zerker's crit chance. +RULE_INT(Combat, MeleeCritDifficulty, 8900) // lower is easier +RULE_INT(Combat, ArcheryCritDifficulty, 3400) // lower is easier +RULE_INT(Combat, ThrowingCritDifficulty, 1100) // lower is easier RULE_BOOL(Combat, UseIntervalAC, true) RULE_INT(Combat, PetAttackMagicLevel, 30) RULE_BOOL(Combat, EnableFearPathing, true) diff --git a/utils/combat-sim/app.js b/utils/combat-sim/app.js index ce5a7ac69..1bd00364e 100644 --- a/utils/combat-sim/app.js +++ b/utils/combat-sim/app.js @@ -77,6 +77,8 @@ app.controller('MainCtrl', function($scope, $interval) { $scope.stop(); }); + var damage_mods = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; + function getRandomInt(min, max) { min = Math.ceil(min); max = Math.floor(max); @@ -94,45 +96,20 @@ app.controller('MainCtrl', function($scope, $interval) { } function doCombatRound() { - var offense = $scope.offense; - var mitigation = $scope.mitigation; - mitigation = mitigation - ((mitigation - offense) / 2.0); - var diff = offense - mitigation; - var mean = 0.0; - var mult1 = 0.0; - var mult2 = 0.0; - - if (offense > 30.0) { - mult1 = offense / 200.0 + 25.75; - if ((mitigation / offense) < 0.35) { - mult1 = mult1 + 1.0; - } else if ((mitigation / offense) > 0.65) { - mult1 = mult1 - 1.0; - } - mult2 = offense / 140 + 18.5; - } else { - mult1 = 11.5 + offense / 2.0; - mult2 = 14.0 + offense / 6.0; + var offense = getRandomInt(0, $scope.offense + 5); + var mitigation = getRandomInt(0, $scope.mitigation + 5); + var avg = parseInt(($scope.offense + $scope.mitigation + 10) / 2); + var index = parseInt((offense - mitigation) + (avg / 2)); + if (index < 0) { + index = 0; } - - if (offense > mitigation) { - mean = diff / offense * mult1; - } else if (mitigation > offense) { - mean = diff / mitigation * mult2; - } - - var stddev = 8.8; - var theta = 2 * Math.PI * getRandom(0.0, 1.0); - var rho = Math.sqrt(-2 * Math.log(1 - getRandom(0.0, 1.0))); - var d = mean + stddev * rho * Math.cos(theta); - - if (d < -9.5) { - d = -9.5; - } else if (d > 9.5) { - d = 9.5; - } - d = d + 11; - addRoll(parseInt(d)); + index = parseInt((index * 20) / avg); + if (index >= 20) + index = 19; + if (index < 0) + index = 0; + var roll = damage_mods[index]; + addRoll(roll); }; }); diff --git a/zone/attack.cpp b/zone/attack.cpp index 48b58964c..c05be46cb 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -267,7 +267,7 @@ int Mob::GetTotalDefense() // called when a mob is attacked, does the checks to see if it's a hit // and does other mitigation checks. 'this' is the mob being attacked. -bool Mob::CheckHitChance(Mob* other, EQEmu::skills::SkillType skillinuse, int chance_mod) +bool Mob::CheckHitChance(Mob* other, DamageHitInfo &hit) { Mob *attacker = other; Mob *defender = this; @@ -280,7 +280,7 @@ bool Mob::CheckHitChance(Mob* other, EQEmu::skills::SkillType skillinuse, int ch if (avoidance == -1) // some sort of auto avoid disc return false; - auto accuracy = attacker->GetTotalToHit(skillinuse, chance_mod); + auto accuracy = hit.tohit; if (accuracy == -1) return true; @@ -297,7 +297,7 @@ bool Mob::CheckHitChance(Mob* other, EQEmu::skills::SkillType skillinuse, int ch return tohit_roll > avoid_roll; } -bool Mob::AvoidDamage(Mob *other, int &damage, int hand) +bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) { /* called when a mob is attacked, does the checks to see if it's a hit * and does other mitigation checks. 'this' is the mob being attacked. @@ -360,9 +360,9 @@ bool Mob::AvoidDamage(Mob *other, int &damage, int hand) // riposte -- it may seem crazy, but if the attacker has SPA 173 on them, they are immune to Ripo bool ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance; // Need to check if we have something in MainHand to actually attack with (or fists) - if (hand != EQEmu::inventory::slotRange && (CanThisClassRiposte() || IsEnraged()) && InFront && !ImmuneRipo) { + if (hit.hand != EQEmu::inventory::slotRange && (CanThisClassRiposte() || IsEnraged()) && InFront && !ImmuneRipo) { if (IsEnraged()) { - damage = -3; + hit.damage_done = DMG_RIPOSTED; Log.Out(Logs::Detail, Logs::Combat, "I am enraged, riposting frontal attack."); return true; } @@ -370,7 +370,7 @@ bool Mob::AvoidDamage(Mob *other, int &damage, int hand) CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillRiposte, other, -10); // check auto discs ... I guess aa/items too :P if (spellbonuses.RiposteChance == 10000 || aabonuses.RiposteChance == 10000 || itembonuses.RiposteChance == 10000) { - damage = -3; + hit.damage_done = DMG_RIPOSTED; return true; } int chance = GetSkill(EQEmu::skills::SkillRiposte) + 100; @@ -382,12 +382,12 @@ bool Mob::AvoidDamage(Mob *other, int &damage, int hand) chance -= chance * counter; } // AA Slippery Attacks - if (hand == EQEmu::inventory::slotSecondary) { + if (hit.hand == EQEmu::inventory::slotSecondary) { int slip = aabonuses.OffhandRiposteFail + itembonuses.OffhandRiposteFail + spellbonuses.OffhandRiposteFail; chance += chance * slip / 100; } if (chance > 0 && zone->random.Roll(chance)) { // could be <0 from offhand stuff - damage = -3; + hit.damage_done = DMG_RIPOSTED; return true; } } @@ -409,7 +409,7 @@ bool Mob::AvoidDamage(Mob *other, int &damage, int hand) // check auto discs ... I guess aa/items too :P if (spellbonuses.IncreaseBlockChance == 10000 || aabonuses.IncreaseBlockChance == 10000 || itembonuses.IncreaseBlockChance == 10000) { - damage = -1; + hit.damage_done = DMG_BLOCKED; return true; } int chance = GetSkill(EQEmu::skills::SkillBlock) + 100; @@ -421,18 +421,18 @@ bool Mob::AvoidDamage(Mob *other, int &damage, int hand) chance -= chance * counter; } if (zone->random.Roll(chance)) { - damage = -1; + hit.damage_done = DMG_BLOCKED; return true; } } // parry - if (CanThisClassParry() && InFront && hand != EQEmu::inventory::slotRange) { + if (CanThisClassParry() && InFront && hit.hand != EQEmu::inventory::slotRange) { if (IsClient()) CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillParry, other, -10); // check auto discs ... I guess aa/items too :P if (spellbonuses.ParryChance == 10000 || aabonuses.ParryChance == 10000 || itembonuses.ParryChance == 10000) { - damage = -2; + hit.damage_done = DMG_PARRIED; return true; } int chance = GetSkill(EQEmu::skills::SkillParry) + 100; @@ -444,7 +444,7 @@ bool Mob::AvoidDamage(Mob *other, int &damage, int hand) chance -= chance * counter; } if (zone->random.Roll(chance)) { - damage = -2; + hit.damage_done = DMG_PARRIED; return true; } } @@ -455,7 +455,7 @@ bool Mob::AvoidDamage(Mob *other, int &damage, int hand) CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillDodge, other, -10); // check auto discs ... I guess aa/items too :P if (spellbonuses.DodgeChance == 10000 || aabonuses.DodgeChance == 10000 || itembonuses.DodgeChance == 10000) { - damage = -4; + hit.damage_done = DMG_DODGED; return true; } int chance = GetSkill(EQEmu::skills::SkillDodge) + 100; @@ -467,7 +467,7 @@ bool Mob::AvoidDamage(Mob *other, int &damage, int hand) chance -= chance * counter; } if (zone->random.Roll(chance)) { - damage = -4; + hit.damage_done = DMG_DODGED; return true; } } @@ -480,7 +480,7 @@ bool Mob::AvoidDamage(Mob *other, int &damage, int hand) chance -= chance * counter; } if (zone->random.Roll(chance)) { - damage = -1; + hit.damage_done = DMG_BLOCKED; return true; } } @@ -492,7 +492,7 @@ bool Mob::AvoidDamage(Mob *other, int &damage, int hand) chance -= chance * counter; } if (zone->random.Roll(chance)) { - damage = -1; + hit.damage_done = DMG_BLOCKED; return true; } } @@ -826,54 +826,32 @@ int Mob::offense(EQEmu::skills::SkillType skill) // this assumes "this" is the defender // this returns between 0.1 to 2.0 -double Mob::RollD20(double offense, double mitigation) +double Mob::RollD20(int offense, int mitigation) { + static double mods[] = { + 0.1, 0.2, 0.3, 0.4, 0.5, + 0.6, 0.7, 0.8, 0.9, 1.0, + 1.1, 1.2, 1.3, 1.4, 1.5, + 1.6, 1.7, 1.8, 1.9, 2.0 + }; + if (IsClient() && CastToClient()->IsSitting()) - return 2.0; + return mods[19]; - // this works pretty good. From Torven's implementation for TAKP - mitigation -= (mitigation - offense) / 2.0; - double diff = offense - mitigation; - double mean = 0; - double mult1, mult2; + auto atk_roll = zone->random.Roll0(offense + 5); + auto def_roll = zone->random.Roll0(mitigation + 5); - if (offense > 30.0) { - mult1 = offense / 200.0 + 25.75; - if (mitigation / offense < 0.35) - mult1 = mult1 + 1.0; - else if (mitigation / offense > 0.65) - mult1 = mult1 - 1.0; - mult2 = offense / 140 + 18.5; - } else { - mult1 = 11.5 + offense / 2.0; - mult2 = 14.0 + offense / 6.0; - } + int avg = (offense + mitigation + 10) / 2; + int index = std::max(0, (atk_roll - def_roll) + (avg / 2)); - // changing the mean shifts the bell curve - // this was mostly determined by trial and error to find what fit best - if (offense > mitigation) - mean = diff / offense * mult1; - else if (mitigation > offense) - mean = diff / mitigation * mult2; + index = EQEmu::Clamp((index * 20) / avg, 0, 19); - double stddev = 8.8; // standard deviation adjusts the height of the bell - // again, trial and error to find what fit best - double theta = 2 * M_PI * zone->random.Real(0.0, 1.0); - double rho = std::sqrt(-2 * std::log(1 - zone->random.Real(0.0, 1.0))); - double d = mean + stddev * rho * std::cos(theta); - - // this combined with the stddev will produce ~15% DI1 and ~15% DI20 when mitigation == offens - d = EQEmu::Clamp(d, -9.5, 9.5); - d += 11.0; - int roll = static_cast(d); - - // the client has an array called damage_factor that is set to this value, so probably what they do - return roll * 0.1; + return mods[index]; } -void Mob::MeleeMitigation(Mob *attacker, int &damage, int base_damage, int offense, EQEmu::skills::SkillType skill, ExtraAttackOptions *opts) +void Mob::MeleeMitigation(Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts) { - if (damage < 0 || base_damage == 0) + if (hit.damage_done < 0 || hit.base_damage == 0) return; Mob* defender = this; @@ -886,24 +864,14 @@ void Mob::MeleeMitigation(Mob *attacker, int &damage, int base_damage, int offen mitigation -= opts->armor_pen_flat; } - auto roll = RollD20(offense, mitigation); - - // 168 Defensive -- TODO: I think this is suppose to happen after damage table - // It happening after damage table also means it acts more like negative 185, which might explain - // why the spell has a negative value :P - auto meleemitspell = spellbonuses.MeleeMitigationEffect + itembonuses.MeleeMitigationEffect + aabonuses.MeleeMitigationEffect; - if (GetClass() == WARRIOR && IsClient()) - meleemitspell += 5; + auto roll = RollD20(hit.offense, mitigation); // +0.5 for rounding - damage = static_cast(roll * static_cast(base_damage) + 0.5); + hit.damage_done = static_cast(roll * static_cast(hit.base_damage) + 0.5); - if (meleemitspell) - damage = (damage * (100 - meleemitspell)) / 100; - - if (damage < 0) - damage = 0; - Log.Out(Logs::Detail, Logs::Attack, "mitigation %d vs offense %d. base %d defensive SPA %d rolled %f damage %d", mitigation, offense, base_damage, meleemitspell, roll, damage); + if (hit.damage_done < 0) + hit.damage_done = 0; + Log.Out(Logs::Detail, Logs::Attack, "mitigation %d vs offense %d. base %d rolled %f damage %d", mitigation, hit.offense, hit.base_damage, roll, hit.damage_done); } //Returns the weapon damage against the input mob @@ -1227,6 +1195,44 @@ int Client::DoDamageCaps(int base_damage) return std::min(cap, base_damage); } +void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts) +{ + if (!other) + return; + Log.Out(Logs::Detail, Logs::Combat, "%s::DoAttack vs %s base %d min %d offense %d tohit %d skill %d", GetName(), + other->GetName(), hit.base_damage, hit.min_damage, hit.offense, hit.tohit, hit.skill); + // check to see if we hit.. + if (other->AvoidDamage(this, hit)) { + int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; + if (strike_through && zone->random.Roll(strike_through)) { + Message_StringID(MT_StrikeThrough, + STRIKETHROUGH_STRING); // You strike through your opponents defenses! + hit.damage_done = 0; // set to zero, we will check this to continue + } + // I'm pretty sure you can riposte a riposte + if (hit.damage_done == DMG_RIPOSTED) { + DoRiposte(other); + //if (IsDead()) + return; + } + Log.Out(Logs::Detail, Logs::Combat, "Avoided/strikethrough damage with code %d", hit.damage_done); + } + + if (hit.damage_done == 0) { + if (other->CheckHitChance(this, hit)) { + other->MeleeMitigation(this, hit, opts); + if (hit.damage_done > 0) { + ApplyDamageTable(hit); + CommonOutgoingHitSuccess(other, hit, opts); + } + Log.Out(Logs::Detail, Logs::Combat, "Final damage after all reductions: %d", hit.damage_done); + } else { + Log.Out(Logs::Detail, Logs::Combat, "Attack missed. Damage set to 0."); + hit.damage_done = 0; + } + } +} + //note: throughout this method, setting `damage` to a negative is a way to //stop the attack calculations // IsFromSpell added to allow spell effects to use Attack. (Mainly for the Rampage AA right now.) @@ -1284,37 +1290,34 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b Log.Out(Logs::Detail, Logs::Combat, "Attacking without a weapon."); } + DamageHitInfo my_hit; // calculate attack_skill and skillinuse depending on hand and weapon // also send Packet to near clients - EQEmu::skills::SkillType skillinuse; - AttackAnimation(skillinuse, Hand, weapon); - Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse); + AttackAnimation(my_hit.skill, Hand, weapon); + Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, my_hit.skill); // Now figure out damage - int damage = 0; + my_hit.damage_done = 0; uint8 mylevel = GetLevel() ? GetLevel() : 1; uint32 hate = 0; if (weapon) hate = weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt; - int weapon_damage = GetWeaponDamage(other, weapon, &hate); - if (hate == 0 && weapon_damage > 1) hate = weapon_damage; + my_hit.base_damage = GetWeaponDamage(other, weapon, &hate); + if (hate == 0 && my_hit.base_damage > 1) hate = my_hit.base_damage; //if weapon damage > 0 then we know we can hit the target with this weapon //otherwise we cannot and we set the damage to -5 later on - if(weapon_damage > 0){ + if (my_hit.base_damage > 0) { // if we revamp this function be more general, we will have to make sure this isn't // executed for anything BUT normal melee damage weapons from auto attack if (Hand == EQEmu::inventory::slotPrimary || Hand == EQEmu::inventory::slotSecondary) - weapon_damage = DoDamageCaps(weapon_damage); + my_hit.base_damage = DoDamageCaps(my_hit.base_damage); auto shield_inc = spellbonuses.ShieldEquipDmgMod + itembonuses.ShieldEquipDmgMod + aabonuses.ShieldEquipDmgMod; if (shield_inc > 0 && HasShieldEquiped() && Hand == EQEmu::inventory::slotPrimary) { - weapon_damage = weapon_damage * (100 + shield_inc) / 100; + my_hit.base_damage = my_hit.base_damage * (100 + shield_inc) / 100; hate = hate * (100 + shield_inc) / 100; } - int base_damage = weapon_damage; - int min_damage = 0; // damage bonus - - CheckIncreaseSkill(skillinuse, other, -15); + CheckIncreaseSkill(my_hit.skill, other, -15); CheckIncreaseSkill(EQEmu::skills::SkillOffense, other, -15); // *************************************************************** @@ -1338,7 +1341,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); - min_damage = ucDamageBonus; + my_hit.min_damage = ucDamageBonus; hate += ucDamageBonus; } #endif @@ -1348,62 +1351,32 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr, true); - min_damage = ucDamageBonus; + my_hit.min_damage = ucDamageBonus; hate += ucDamageBonus; } } - // this effect is actually a min cap that happens after the final damage is calculated - int min_cap = base_damage * GetMeleeMinDamageMod_SE(skillinuse) / 100; - // damage = mod_client_damage(damage, skillinuse, Hand, weapon, other); - Log.Out(Logs::Detail, Logs::Combat, "Damage calculated to %d (bonus %d, base %d, str %d, skill %d, DMG %d, lv %d)", - damage, min_damage, base_damage, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel); + Log.Out(Logs::Detail, Logs::Combat, "Damage calculated: base %d min damage %d skill %d", my_hit.base_damage, my_hit.min_damage, my_hit.skill); int hit_chance_bonus = 0; - auto offense = this->offense(skillinuse); // we need this a few times + my_hit.offense = offense(my_hit.skill); // we need this a few times + my_hit.hand = Hand; if(opts) { - base_damage *= opts->damage_percent; - base_damage += opts->damage_flat; + my_hit.base_damage *= opts->damage_percent; + my_hit.base_damage += opts->damage_flat; hate *= opts->hate_percent; hate += opts->hate_flat; hit_chance_bonus += opts->hit_chance; } - //check to see if we hit.. - if (other->AvoidDamage(this, damage, Hand)) { - if (!bRiposte && !IsStrikethrough) { - int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; - if(strike_through && zone->random.Roll(strike_through)) { - Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses! - Attack(other, Hand, false, true); // Strikethrough only gives another attempted hit - return false; - } - // I'm pretty sure you can riposte a riposte - if (damage == -3 && !bRiposte) { - DoRiposte(other); - if (IsDead()) - return false; - } - } - Log.Out(Logs::Detail, Logs::Combat, "Avoided damage with code %d", damage); - } else { - if (other->CheckHitChance(this, skillinuse, hit_chance_bonus)) { - other->MeleeMitigation(this, damage, base_damage, offense, skillinuse, opts); - if (damage > 0) { - ApplyDamageTable(damage, offense); - CommonOutgoingHitSuccess(other, damage, min_damage, min_cap, skillinuse, opts); - } - Log.Out(Logs::Detail, Logs::Combat, "Final damage after all reductions: %d", damage); - } else { - Log.Out(Logs::Detail, Logs::Combat, "Attack missed. Damage set to 0."); - damage = 0; - } - } + my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus); + + DoAttack(other, my_hit, opts); } else { - damage = -5; + my_hit.damage_done = DMG_INVULNERABLE; } // Hate Generation is on a per swing basis, regardless of a hit, miss, or block, its always the same. @@ -1414,28 +1387,28 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b /////////////////////////////////////////////////////////// ////// Send Attack Damage /////////////////////////////////////////////////////////// - if (damage > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == skillinuse && + if (my_hit.damage_done > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == my_hit.skill && IsValidSpell(aabonuses.SkillAttackProc[2])) { float chance = aabonuses.SkillAttackProc[0] / 1000.0f; if (zone->random.Roll(chance)) SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, true, -1, false, m_specialattacks); + other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill, true, -1, false, m_specialattacks); if (IsDead()) return false; - MeleeLifeTap(damage); + MeleeLifeTap(my_hit.damage_done); - if (damage > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0) - TrySkillProc(other, skillinuse, 0, true, Hand); + if (my_hit.damage_done > 0 && HasSkillProcSuccess() && other && other->GetHP() > 0) + TrySkillProc(other, my_hit.skill, 0, true, Hand); CommonBreakInvisibleFromCombat(); if(GetTarget()) - TriggerDefensiveProcs(other, Hand, true, damage); + TriggerDefensiveProcs(other, Hand, true, my_hit.damage_done); - if (damage > 0) + if (my_hit.damage_done > 0) return true; else @@ -1768,8 +1741,6 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { - int damage = 0; - if (!other) { SetTarget(nullptr); Log.Out(Logs::General, Logs::Error, "A null Mob object was passed to NPC::Attack() for evaluation!"); @@ -1797,13 +1768,16 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool FaceTarget(GetTarget()); - EQEmu::skills::SkillType skillinuse = EQEmu::skills::SkillHandtoHand; + DamageHitInfo my_hit; + my_hit.skill = EQEmu::skills::SkillHandtoHand; + my_hit.hand = Hand; + my_hit.damage_done = 0; if (Hand == EQEmu::inventory::slotPrimary) { - skillinuse = static_cast(GetPrimSkill()); + my_hit.skill = static_cast(GetPrimSkill()); OffHandAtk(false); } if (Hand == EQEmu::inventory::slotSecondary) { - skillinuse = static_cast(GetSecSkill()); + my_hit.skill = static_cast(GetSecSkill()); OffHandAtk(true); } @@ -1826,32 +1800,32 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool switch(weapon->ItemType) { case EQEmu::item::ItemType1HSlash: - skillinuse = EQEmu::skills::Skill1HSlashing; + my_hit.skill = EQEmu::skills::Skill1HSlashing; break; case EQEmu::item::ItemType2HSlash: - skillinuse = EQEmu::skills::Skill2HSlashing; + my_hit.skill = EQEmu::skills::Skill2HSlashing; break; case EQEmu::item::ItemType1HPiercing: - skillinuse = EQEmu::skills::Skill1HPiercing; + my_hit.skill = EQEmu::skills::Skill1HPiercing; break; case EQEmu::item::ItemType2HPiercing: - skillinuse = EQEmu::skills::Skill2HPiercing; + my_hit.skill = EQEmu::skills::Skill2HPiercing; break; case EQEmu::item::ItemType1HBlunt: - skillinuse = EQEmu::skills::Skill1HBlunt; + my_hit.skill = EQEmu::skills::Skill1HBlunt; break; case EQEmu::item::ItemType2HBlunt: - skillinuse = EQEmu::skills::Skill2HBlunt; + my_hit.skill = EQEmu::skills::Skill2HBlunt; break; case EQEmu::item::ItemTypeBow: - skillinuse = EQEmu::skills::SkillArchery; + my_hit.skill = EQEmu::skills::SkillArchery; break; case EQEmu::item::ItemTypeLargeThrowing: case EQEmu::item::ItemTypeSmallThrowing: - skillinuse = EQEmu::skills::SkillThrowing; + my_hit.skill = EQEmu::skills::SkillThrowing; break; default: - skillinuse = EQEmu::skills::SkillHandtoHand; + my_hit.skill = EQEmu::skills::SkillHandtoHand; break; } } @@ -1861,7 +1835,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool //do attack animation regardless of whether or not we can hit below int16 charges = 0; EQEmu::ItemInstance weapon_inst(weapon, charges); - AttackAnimation(skillinuse, Hand, &weapon_inst); + AttackAnimation(my_hit.skill, Hand, &weapon_inst); //basically "if not immune" then do the attack if(weapon_damage > 0) { @@ -1898,54 +1872,48 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool //damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other); - int lbase_damage = this->base_damage + eleBane; - int lmin_damage = this->min_damage; - int32 hate = lbase_damage + lmin_damage; - - int min_cap = lbase_damage * GetMeleeMinDamageMod_SE(skillinuse) / 100; + my_hit.base_damage = GetBaseDamage() + eleBane; + my_hit.min_damage = GetMinDamage(); + int32 hate = my_hit.base_damage + my_hit.min_damage; int hit_chance_bonus = 0; - if(opts) { - lbase_damage *= opts->damage_percent; - lbase_damage += opts->damage_flat; + if (opts) { + my_hit.base_damage *= opts->damage_percent; + my_hit.base_damage += opts->damage_flat; hate *= opts->hate_percent; hate += opts->hate_flat; hit_chance_bonus += opts->hit_chance; } - if (other->AvoidDamage(this, damage, Hand)) { - if (!bRiposte && damage == -3) - DoRiposte(other); - } else { - if (other->CheckHitChance(this, skillinuse, hit_chance_bonus)) { - other->MeleeMitigation(this, damage, lbase_damage, this->offense(skillinuse), skillinuse, opts); - CommonOutgoingHitSuccess(other, damage, lmin_damage, min_cap, skillinuse, opts); - } else { - damage = 0; - } - } + my_hit.offense = offense(my_hit.skill); + my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus); + + DoAttack(other, my_hit, opts); + other->AddToHateList(this, hate); - Log.Out(Logs::Detail, Logs::Combat, "Final damage against %s: %d", other->GetName(), damage); + Log.Out(Logs::Detail, Logs::Combat, "Final damage against %s: %d", other->GetName(), my_hit.damage_done); if(other->IsClient() && IsPet() && GetOwner()->IsClient()) { //pets do half damage to clients in pvp - damage=damage/2; + my_hit.damage_done /= 2; + if (my_hit.damage_done < 1) + my_hit.damage_done = 1; } + } else { + my_hit.damage_done = DMG_INVULNERABLE; } - else - damage = -5; if(GetHP() > 0 && !other->HasDied()) { - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse, true, -1, false, m_specialattacks); // Not avoidable client already had thier chance to Avoid + other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill, true, -1, false, m_specialattacks); // Not avoidable client already had thier chance to Avoid } else return false; if (HasDied()) //killed by damage shield ect return false; - MeleeLifeTap(damage); + MeleeLifeTap(my_hit.damage_done); CommonBreakInvisibleFromCombat(); @@ -1959,14 +1927,14 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool if (!other->HasDied()) TrySpellProc(nullptr, weapon, other, Hand); - if (damage > 0 && HasSkillProcSuccess() && !other->HasDied()) - TrySkillProc(other, skillinuse, 0, true, Hand); + if (my_hit.damage_done > 0 && HasSkillProcSuccess() && !other->HasDied()) + TrySkillProc(other, my_hit.skill, 0, true, Hand); } if(GetHP() > 0 && !other->HasDied()) - TriggerDefensiveProcs(other, Hand, true, damage); + TriggerDefensiveProcs(other, Hand, true, my_hit.damage_done); - if (damage > 0) + if (my_hit.damage_done > 0) return true; else @@ -2874,7 +2842,7 @@ int32 Mob::ReduceDamage(int32 damage) if (spellbonuses.NegateAttacks[2] && (damage > spellbonuses.NegateAttacks[2])) damage -= spellbonuses.NegateAttacks[2]; else - return -6; + return DMG_RUNE; } } @@ -2935,13 +2903,13 @@ int32 Mob::ReduceDamage(int32 damage) } if(damage < 1) - return -6; + return DMG_RUNE; if (spellbonuses.MeleeRune[0] && spellbonuses.MeleeRune[1] >= 0) damage = RuneAbsorb(damage, SE_Rune); if(damage < 1) - return -6; + return DMG_RUNE; return(damage); } @@ -3166,11 +3134,11 @@ bool Client::CheckTripleAttack() if (chance < 1) return false; - int per_inc = aabonuses.TripleAttackChance + spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance; - if (per_inc) - chance += chance * per_inc / 100; + int inc = aabonuses.TripleAttackChance + spellbonuses.TripleAttackChance + itembonuses.TripleAttackChance; + chance = static_cast(chance * (1 + inc / 100.0f)); + chance = (chance * 100) / (chance + 800); - return zone->random.Int(1, 1000) <= chance; + return zone->random.Int(1, 100) <= chance; } bool Client::CheckDoubleRangedAttack() { @@ -3923,9 +3891,9 @@ void Mob::TrySpellProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *w return; } -void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int &damage) +void Mob::TryPetCriticalHit(Mob *defender, DamageHitInfo &hit) { - if (damage < 1) + if (hit.damage_done < 1) return; // Allows pets to perform critical hits. @@ -3935,12 +3903,9 @@ void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int &damage) Mob *owner = nullptr; int critChance = 0; - critChance += RuleI(Combat, MeleeBaseCritChance); + critChance += RuleI(Combat, PetBaseCritChance); // 0 by default int critMod = 170; - if (damage < 1) // We can't critical hit if we don't hit. - return; - if (IsPet()) owner = GetOwner(); else if ((IsNPC() && CastToNPC()->GetSwarmOwner())) @@ -3954,182 +3919,170 @@ void Mob::TryPetCriticalHit(Mob *defender, uint16 skill, int &damage) int CritPetChance = owner->aabonuses.PetCriticalHit + owner->itembonuses.PetCriticalHit + owner->spellbonuses.PetCriticalHit; - if (CritPetChance || critChance) { - + if (CritPetChance || critChance) // For pets use PetCriticalHit for base chance, pets do not innately critical with without it critChance += CritPetChance; - } if (critChance > 0) { if (zone->random.Roll(critChance)) { - critMod += GetCritDmgMob(skill); - damage += 5; - damage = (damage * critMod) / 100; + critMod += GetCritDmgMob(hit.skill); + hit.damage_done += 5; + hit.damage_done = (hit.damage_done * critMod) / 100; entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, FilterMeleeCrits, - CRITICAL_HIT, GetCleanName(), itoa(damage)); + CRITICAL_HIT, GetCleanName(), itoa(hit.damage_done + hit.min_damage)); } } } -void Mob::TryCriticalHit(Mob *defender, uint16 skill, int &damage, int min_damage, ExtraAttackOptions *opts) +void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts) { - if (damage < 1 || !defender) + if (hit.damage_done < 1 || !defender) return; // decided to branch this into it's own function since it's going to be duplicating a lot of the // code in here, but could lead to some confusion otherwise if ((IsPet() && GetOwner()->IsClient()) || (IsNPC() && CastToNPC()->GetSwarmOwner())) { - TryPetCriticalHit(defender, skill, damage); + TryPetCriticalHit(defender, hit); return; } #ifdef BOTS if (this->IsPet() && this->GetOwner() && this->GetOwner()->IsBot()) { - this->TryPetCriticalHit(defender, skill, damage); + this->TryPetCriticalHit(defender, hit); return; } #endif // BOTS - float critChance = 0.0f; - bool IsBerskerSPA = false; - // 1: Try Slay Undead if (defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire) { - int32 SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0]; + int SlayRateBonus = aabonuses.SlayUndead[0] + itembonuses.SlayUndead[0] + spellbonuses.SlayUndead[0]; if (SlayRateBonus) { float slayChance = static_cast(SlayRateBonus) / 10000.0f; if (zone->random.Roll(slayChance)) { - int32 SlayDmgBonus = - aabonuses.SlayUndead[1] + itembonuses.SlayUndead[1] + spellbonuses.SlayUndead[1]; - damage += 5; - damage = (damage * SlayDmgBonus) / 100; + int SlayDmgBonus = std::max( + {aabonuses.SlayUndead[1], itembonuses.SlayUndead[1], spellbonuses.SlayUndead[1]}); + hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5; + hit.damage_done = (hit.damage_done * SlayDmgBonus) / 100; if (GetGender() == 1) // female entity_list.FilteredMessageClose_StringID( this, false, 200, MT_CritMelee, FilterMeleeCrits, FEMALE_SLAYUNDEAD, - GetCleanName(), itoa(damage + min_damage)); + GetCleanName(), itoa(hit.damage_done + hit.min_damage)); else // males and neuter I guess entity_list.FilteredMessageClose_StringID( this, false, 200, MT_CritMelee, FilterMeleeCrits, MALE_SLAYUNDEAD, - GetCleanName(), itoa(damage + min_damage)); + GetCleanName(), itoa(hit.damage_done + hit.min_damage)); return; } } } // 2: Try Melee Critical + // a lot of good info: http://giline.versus.jp/shiden/damage_e.htm, http://giline.versus.jp/shiden/su.htm - // Base critical rate for all classes is dervived from DEX stat, this rate is then augmented - // by item,spell and AA bonuses allowing you a chance to critical hit. If the following rules - // are defined you will have an innate chance to hit at Level 1 regardless of bonuses. - // Warning: Do not define these rules if you want live like critical hits. - critChance += RuleI(Combat, MeleeBaseCritChance); - + // We either require an innate crit chance or some SPA 169 to crit + bool innate_crit = false; + int crit_chance = GetCriticalChanceBonus(hit.skill); if (IsClient()) { - critChance += RuleI(Combat, ClientBaseCritChance); - - if (spellbonuses.BerserkSPA || itembonuses.BerserkSPA || aabonuses.BerserkSPA) - IsBerskerSPA = true; - - if (((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) || IsBerskerSPA) { - if (IsBerserk() || IsBerskerSPA) - critChance += RuleI(Combat, BerserkBaseCritChance); - else - critChance += RuleI(Combat, WarBerBaseCritChance); - } + if ((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) + innate_crit = true; + else if (GetClass() == RANGER && GetLevel() >= 12 && hit.skill == EQEmu::skills::SkillArchery) + innate_crit = true; + else if (GetClass() == ROGUE && GetLevel() >= 12 && hit.skill == EQEmu::skills::SkillThrowing) + innate_crit = true; } - int deadlyChance = 0; - int deadlyMod = 0; - if (skill == EQEmu::skills::SkillArchery && GetClass() == RANGER && GetSkill(EQEmu::skills::SkillArchery) >= 65) - critChance += 6; + // we have a chance to crit! + if (innate_crit || crit_chance) { + int difficulty = 0; + if (hit.skill == EQEmu::skills::SkillArchery) + difficulty = RuleI(Combat, ArcheryCritDifficulty); + else if (hit.skill == EQEmu::skills::SkillThrowing) + difficulty = RuleI(Combat, ThrowingCritDifficulty); + else + difficulty = RuleI(Combat, MeleeCritDifficulty); + int roll = zone->random.Int(1, difficulty); - if (skill == EQEmu::skills::SkillThrowing && GetClass() == ROGUE && - GetSkill(EQEmu::skills::SkillThrowing) >= 65) { - critChance += RuleI(Combat, RogueCritThrowingChance); - deadlyChance = RuleI(Combat, RogueDeadlyStrikeChance); - deadlyMod = RuleI(Combat, RogueDeadlyStrikeMod); - } + int dex_bonus = GetDEX(); + if (dex_bonus > 255) + dex_bonus = 255 + ((dex_bonus - 255) / 5); + dex_bonus += 45; // chances did not match live without a small boost - int CritChanceBonus = GetCriticalChanceBonus(skill); + // so if we have an innate crit we have a better chance, except for ber throwing + if (!innate_crit || (GetClass() == BERSERKER && hit.skill == EQEmu::skills::SkillThrowing)) + dex_bonus = dex_bonus * 3 / 5; - if (CritChanceBonus || critChance) { + if (crit_chance) + dex_bonus += dex_bonus * crit_chance / 100; - // Get Base CritChance from Dex. (200 = ~1.6%, 255 = ~2.0%, 355 = ~2.20%) Fall off rate > 255 - // http://giline.versus.jp/shiden/su.htm , http://giline.versus.jp/shiden/damage_e.htm - if (GetDEX() <= 255) - critChance += (float(GetDEX()) / 125.0f); - else if (GetDEX() > 255) - critChance += (float(GetDEX() - 255) / 500.0f) + 2.0f; - critChance += critChance * (float)CritChanceBonus / 100.0f; - } - - if (opts) { - critChance *= opts->crit_percent; - critChance += opts->crit_flat; - } - - if (critChance > 0) { - - critChance /= 100; - - if (zone->random.Roll(critChance)) { - if (TryFinishingBlow(defender, static_cast(skill), damage)) + // check if we crited + if (roll < dex_bonus) { + // step 1: check for finishing blow + if (TryFinishingBlow(defender, hit.damage_done)) return; - int critMod = 170; - bool crip_success = false; - int32 CripplingBlowChance = GetCrippBlowChance(); - // Crippling Blow Chance: The percent value of the effect is applied - // to the your Chance to Critical. (ie You have 10% chance to critical and you - // have a 200% Chance to Critical Blow effect, therefore you have a 20% Chance to Critical Blow. - if (CripplingBlowChance || (IsBerserk() || IsBerskerSPA)) { - if (!IsBerserk() && !IsBerskerSPA) - critChance *= float(CripplingBlowChance) / 100.0f; + // step 2: calculate damage + hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5; + int og_damage = hit.damage_done; + int crit_mod = 170 + GetCritDmgMob(hit.skill); + hit.damage_done = hit.damage_done * crit_mod / 100; + Log.Out(Logs::Detail, Logs::Combat, + "Crit success roll %d dex chance %d og dmg %d crit_mod %d new dmg %d", roll, dex_bonus, + og_damage, crit_mod, hit.damage_done); - if ((IsBerserk() || IsBerskerSPA) || zone->random.Roll(critChance)) - crip_success = true; - } - - critMod += GetCritDmgMob(skill); - damage += 5; - int ogdmg = damage; - damage = damage * critMod / 100; - - bool deadlySuccess = false; - if (deadlyChance && zone->random.Roll(static_cast(deadlyChance) / 100.0f)) { + // step 3: check deadly strike + if (GetClass() == ROGUE && hit.skill == EQEmu::skills::SkillThrowing) { if (BehindMob(defender, GetX(), GetY())) { - damage *= deadlyMod; - deadlySuccess = true; + int chance = GetLevel() * 12; + if (zone->random.Int(1, 1000) < chance) { + // step 3a: check assassinate + int assdmg = TryAssassinate(defender, hit.skill); // I don't think this is right + if (assdmg) { + hit.damage_done = assdmg; + return; + } + hit.damage_done = hit.damage_done * 200 / 100; + entity_list.FilteredMessageClose_StringID( + this, false, 200, MT_CritMelee, FilterMeleeCrits, DEADLY_STRIKE, + GetCleanName(), itoa(hit.damage_done + hit.min_damage)); + return; + } } } - if (crip_success) { - damage += ogdmg * 119 / 100; // the damage_e page says it's a ~1.192 increase of dmg before mod - entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, - FilterMeleeCrits, CRIPPLING_BLOW, - GetCleanName(), itoa(damage + min_damage)); + // step 4: check crips + // this SPA was reused on live ... + bool berserk = spellbonuses.BerserkSPA || itembonuses.BerserkSPA || aabonuses.BerserkSPA; + if (!berserk) { + if (zone->random.Roll(GetCrippBlowChance())) { + berserk = true; + } // TODO: Holyforge is suppose to have an innate extra undead chance? 1/5 which matches the SPA crip though ... + } + + if (IsBerserk() || berserk) { + hit.damage_done += og_damage * 119 / 100; + Log.Out(Logs::Detail, Logs::Combat, "Crip damage %d", hit.damage_done); + entity_list.FilteredMessageClose_StringID( + this, false, 200, MT_CritMelee, FilterMeleeCrits, CRIPPLING_BLOW, GetCleanName(), + itoa(hit.damage_done + hit.min_damage)); // Crippling blows also have a chance to stun // Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a // staggers message. if (defender->GetLevel() <= 55 && !defender->GetSpecialAbility(IMMUNE_STUN)) { defender->Emote("staggers."); - defender->Stun(0); + defender->Stun(2000); } - } else if (deadlySuccess) { - entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, - FilterMeleeCrits, DEADLY_STRIKE, - GetCleanName(), itoa(damage + min_damage)); - } else { - entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, - FilterMeleeCrits, CRITICAL_HIT, - GetCleanName(), itoa(damage + min_damage)); + return; } + // okay, critted but didn't do anything else, just normal message now + entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, FilterMeleeCrits, + CRITICAL_HIT, GetCleanName(), + itoa(hit.damage_done + hit.min_damage)); } } } -bool Mob::TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse, int &damage) +bool Mob::TryFinishingBlow(Mob *defender, int &damage) { // base2 of FinishingBlowLvl is the HP limit (cur / max) * 1000, 10% is listed as 100 if (defender && !defender->IsClient() && defender->GetHPRatio() < 10) { @@ -4144,12 +4097,12 @@ bool Mob::TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse, i else if (FB_Level < itembonuses.FinishingBlowLvl[0]) FB_Level = itembonuses.FinishingBlowLvl[0]; - // Proc Chance value of 500 = 5% - uint32 ProcChance = - (aabonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0]) / 10; + // modern AA description says rank 1 (500) is 50% chance + int ProcChance = + aabonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0] + spellbonuses.FinishingBlow[0]; if (FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && - (ProcChance >= zone->random.Int(0, 1000))) { + (ProcChance >= zone->random.Int(1, 1000))) { entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); damage = FB_Dmg; return true; @@ -4205,12 +4158,12 @@ void Mob::DoRiposte(Mob *defender) if (defender->GetClass() == MONK) defender->MonkSpecialAttack(this, defender->aabonuses.GiveDoubleRiposte[2]); - else if (defender->IsClient() && defender->CastToClient()->HasSkill((EQEmu::skills::SkillType)defender->aabonuses.GiveDoubleRiposte[2])) + else if (defender->IsClient()) // so yeah, even if you don't have the skill you can still do the attack :P (and we don't crash anymore) defender->CastToClient()->DoClassAttacks(this, defender->aabonuses.GiveDoubleRiposte[2], true); } } -void Mob::ApplyMeleeDamageBonus(uint16 skill, int &damage, ExtraAttackOptions *opts) +void Mob::ApplyMeleeDamageMods(uint16 skill, int &damage, Mob *defender, ExtraAttackOptions *opts) { int dmgbonusmod = 0; @@ -4218,6 +4171,13 @@ void Mob::ApplyMeleeDamageBonus(uint16 skill, int &damage, ExtraAttackOptions *o if (opts) dmgbonusmod += opts->melee_damage_bonus_flat; + if (defender) { + if (defender->IsClient() && defender->GetClass() == WARRIOR) + dmgbonusmod -= 5; + // 168 defensive + dmgbonusmod += (defender->spellbonuses.MeleeMitigationEffect + itembonuses.MeleeMitigationEffect + aabonuses.MeleeMitigationEffect); + } + damage += damage * dmgbonusmod / 100; } @@ -4368,7 +4328,7 @@ const DamageTable &Mob::GetDamageTable() const return which[level - 50]; } -void Mob::ApplyDamageTable(int &damage, int offense) +void Mob::ApplyDamageTable(DamageHitInfo &hit) { // someone may want to add this to custom servers, can remove this if that's the case if (!IsClient() @@ -4378,7 +4338,7 @@ void Mob::ApplyDamageTable(int &damage, int offense) ) return; // this was parsed, but we do see the min of 10 and the normal minus factor is 105, so makes sense - if (offense < 115) + if (hit.offense < 115) return; auto &damage_table = GetDamageTable(); @@ -4386,14 +4346,14 @@ void Mob::ApplyDamageTable(int &damage, int offense) if (zone->random.Roll(damage_table.chance)) return; - int basebonus = offense - damage_table.minusfactor; + int basebonus = hit.offense - damage_table.minusfactor; basebonus = std::max(10, basebonus / 2); int extrapercent = zone->random.Roll0(basebonus); int percent = std::min(100 + extrapercent, damage_table.max_extra); - damage = (damage * percent) / 100; + hit.damage_done = (hit.damage_done * percent) / 100; if (IsWarriorClass() && GetLevel() > 54) - damage++; + hit.damage_done++; Log.Out(Logs::Detail, Logs::Attack, "Damage table applied %d (max %d)", percent, damage_table.max_extra); } @@ -4696,52 +4656,49 @@ int32 Mob::RuneAbsorb(int32 damage, uint16 type) return damage; } -// min_damage is the damage bonus, we need to pass it along for a bit -// min_mod is the min hit cap, which needs to be calculated before we call this, but applied here -void Mob::CommonOutgoingHitSuccess(Mob* defender, int &damage, int min_damage, int min_mod, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts) +void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttackOptions *opts) { if (!defender) return; // BER weren't parsing the halving - if (skillInUse == EQEmu::skills::SkillArchery || - (skillInUse == EQEmu::skills::SkillThrowing && GetClass() != BERSERKER)) - damage /= 2; + if (hit.skill == EQEmu::skills::SkillArchery || + (hit.skill == EQEmu::skills::SkillThrowing && GetClass() != BERSERKER)) + hit.damage_done /= 2; - if (damage < 1) - damage = 1; + if (hit.damage_done < 1) + hit.damage_done = 1; - if (skillInUse == EQEmu::skills::SkillArchery) { + if (hit.skill == EQEmu::skills::SkillArchery) { int bonus = aabonuses.ArcheryDamageModifier + itembonuses.ArcheryDamageModifier + spellbonuses.ArcheryDamageModifier; - damage += damage * bonus / 100; - int headshot = TryHeadShot(defender, skillInUse); - if (headshot > 0) - damage = headshot; - } - - // this parses after damage table - if (skillInUse == EQEmu::skills::SkillArchery && GetClass() == RANGER && GetLevel() > 50) { - if (defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) { - damage *= 2; - Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE); + hit.damage_done += hit.damage_done * bonus / 100; + int headshot = TryHeadShot(defender, hit.skill); + if (headshot > 0) { + hit.damage_done = headshot; + } else if (GetClass() == RANGER && GetLevel() > 50) { // no double dmg on headshot + if (defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) { + hit.damage_done *= 2; + Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE); + } } } int extra_mincap = 0; - if (skillInUse == EQEmu::skills::SkillBackstab) { + int min_mod = hit.base_damage * GetMeleeMinDamageMod_SE(hit.skill) / 100; + if (hit.skill == EQEmu::skills::SkillBackstab) { extra_mincap = GetLevel() < 7 ? 7 : GetLevel(); if (GetLevel() >= 60) extra_mincap = GetLevel() * 2; else if (GetLevel() > 50) extra_mincap = GetLevel() * 3 / 2; if (IsSpecialAttack(eSpecialAttacks::ChaoticStab)) { - damage = extra_mincap; + hit.damage_done = extra_mincap; } else { - int ass = TryAssassinate(defender, skillInUse, 10000); // reusetime shouldn't have an effect .... + int ass = TryAssassinate(defender, hit.skill); if (ass > 0) - damage = ass; + hit.damage_done = ass; } - } else if (skillInUse == EQEmu::skills::SkillFrenzy && GetClass() == BERSERKER && GetLevel() > 50) { + } else if (hit.skill == EQEmu::skills::SkillFrenzy && GetClass() == BERSERKER && GetLevel() > 50) { extra_mincap = 4 * GetLevel() / 5; } @@ -4749,23 +4706,23 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, int &damage, int min_damage, i // Seems the crit message is generated before some of them :P // worn item +skill dmg, SPA 220, 418. Live has a normalized version that should be here too - min_damage += GetSkillDmgAmt(skillInUse); + hit.min_damage += GetSkillDmgAmt(hit.skill); // shielding mod2 if (defender->itembonuses.MeleeMitigation) - min_damage -= min_damage * defender->itembonuses.MeleeMitigation / 100; + hit.min_damage -= hit.min_damage * defender->itembonuses.MeleeMitigation / 100; - ApplyMeleeDamageBonus(skillInUse, damage, opts); + ApplyMeleeDamageMods(hit.skill, hit.damage_done, defender, opts); min_mod = std::max(min_mod, extra_mincap); - if (min_mod && damage < min_mod) // SPA 186 - damage = min_mod; + if (min_mod && hit.damage_done < min_mod) // SPA 186 + hit.damage_done = min_mod; - TryCriticalHit(defender, skillInUse, damage, min_damage, opts); + TryCriticalHit(defender, hit, opts); - damage += min_damage; + hit.damage_done += hit.min_damage; if (IsClient()) { int extra = 0; - switch (skillInUse) { + switch (hit.skill) { case EQEmu::skills::SkillThrowing: case EQEmu::skills::SkillArchery: extra = CastToClient()->GetHeroicDEX() / 10; @@ -4774,7 +4731,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, int &damage, int min_damage, i extra = CastToClient()->GetHeroicSTR() / 10; break; } - damage += extra; + hit.damage_done += extra; } // this appears where they do special attack dmg mods @@ -4794,9 +4751,9 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, int &damage, int min_damage, i spec_mod = mod; } if (spec_mod > 0) - damage = (damage * spec_mod) / 100; + hit.damage_done = (hit.damage_done * spec_mod) / 100; - damage += (damage * defender->GetSkillDmgTaken(skillInUse, opts) / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, skillInUse)); + hit.damage_done += (hit.damage_done * defender->GetSkillDmgTaken(hit.skill, opts) / 100) + (defender->GetFcDamageAmtIncoming(this, 0, true, hit.skill)); CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); } @@ -5003,23 +4960,22 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell) // you can only triple from the main hand if (hand == EQEmu::inventory::slotPrimary && CanThisClassTripleAttack()) { CheckIncreaseSkill(EQEmu::skills::SkillTripleAttack, target, -10); - if (CheckTripleAttack()) + if (CheckTripleAttack()) { Attack(target, hand, false, false, IsFromSpell); + auto flurrychance = aabonuses.FlurryChance + spellbonuses.FlurryChance + + itembonuses.FlurryChance; + if (flurrychance && zone->random.Roll(flurrychance)) { + Attack(target, hand, false, false, IsFromSpell); + if (zone->random.Roll(flurrychance)) + Attack(target, hand, false, false, IsFromSpell); + Message_StringID(MT_NPCFlurry, YOU_FLURRY); + } + } } } } if (hand == EQEmu::inventory::slotPrimary) { - // According to http://www.monkly-business.net/forums/showpost.php?p=312095&postcount=168 a dev told them flurry isn't dependant on triple attack - // the parses kind of back that up and all of my parses seemed to be 4 or 5 attacks in the round which would work out to be - // doubles or triples with 2 from flurries or triple with 1 or 2 flurries ... Going with the "dev quote" I guess like we've always had it - auto flurrychance = aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance; - if (flurrychance && zone->random.Roll(flurrychance)) { - Attack(target, hand, false, false, IsFromSpell); - Attack(target, hand, false, false, IsFromSpell); - Message_StringID(MT_NPCFlurry, YOU_FLURRY); - } - // I haven't parsed where this guy happens, but it's not part of the normal chain above so this is fine auto extraattackchance = aabonuses.ExtraAttackChance + spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance; if (extraattackchance && HasTwoHanderEquipped() && zone->random.Roll(extraattackchance)) Attack(target, hand, false, false, IsFromSpell); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 3acf6cb1d..1f94fb63b 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1313,8 +1313,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } case SE_HeadShotLevel: { - if (newbon->HSLevel < base1) - newbon->HSLevel = base1; + if (newbon->HSLevel[0] < base1) + newbon->HSLevel[0] = base1; + newbon->HSLevel[1] = base2; break; } @@ -1327,8 +1328,10 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } case SE_AssassinateLevel: { - if (newbon->AssassinateLevel < base1) - newbon->AssassinateLevel = base1; + if (newbon->AssassinateLevel[0] < base1) { + newbon->AssassinateLevel[0] = base1; + newbon->AssassinateLevel[1] = base2; + } break; } @@ -1386,7 +1389,7 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) } case SE_MeleeMitigation: - newbon->MeleeMitigationEffect -= base1; + newbon->MeleeMitigationEffect += base1; break; case SE_ATK: @@ -1929,8 +1932,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne break; case SE_MeleeMitigation: - //for some reason... this value is negative for increased mitigation - new_bonus->MeleeMitigationEffect -= effect_value; + // This value is negative because it counteracts another SPA :P + new_bonus->MeleeMitigationEffect += effect_value; break; case SE_CriticalHitChance: @@ -3026,8 +3029,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_HeadShotLevel: { - if(new_bonus->HSLevel < effect_value) - new_bonus->HSLevel = effect_value; + if(new_bonus->HSLevel[0] < effect_value) { + new_bonus->HSLevel[0] = effect_value; + new_bonus->HSLevel[1] = base2; + } break; } @@ -3042,8 +3047,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne case SE_AssassinateLevel: { - if(new_bonus->AssassinateLevel < effect_value) - new_bonus->AssassinateLevel = effect_value; + if(new_bonus->AssassinateLevel[0] < effect_value) { + new_bonus->AssassinateLevel[0] = effect_value; + new_bonus->AssassinateLevel[1] = base2; + } break; } @@ -4649,9 +4656,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) break; case SE_HeadShotLevel: - spellbonuses.HSLevel = effect_value; - aabonuses.HSLevel = effect_value; - itembonuses.HSLevel = effect_value; + spellbonuses.HSLevel[0] = effect_value; + aabonuses.HSLevel[0] = effect_value; + itembonuses.HSLevel[0] = effect_value; + spellbonuses.HSLevel[1] = effect_value; + aabonuses.HSLevel[1] = effect_value; + itembonuses.HSLevel[1] = effect_value; break; case SE_Assassinate: @@ -4664,9 +4674,12 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) break; case SE_AssassinateLevel: - spellbonuses.AssassinateLevel = effect_value; - aabonuses.AssassinateLevel = effect_value; - itembonuses.AssassinateLevel = effect_value; + spellbonuses.AssassinateLevel[0] = effect_value; + aabonuses.AssassinateLevel[0] = effect_value; + itembonuses.AssassinateLevel[0] = effect_value; + spellbonuses.AssassinateLevel[1] = effect_value; + aabonuses.AssassinateLevel[1] = effect_value; + itembonuses.AssassinateLevel[1] = effect_value; break; case SE_FinishingBlow: diff --git a/zone/bot.cpp b/zone/bot.cpp index 42ca396af..237c1144b 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3701,24 +3701,24 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b // calculate attack_skill and skillinuse depending on hand and weapon // also send Packet to near clients - EQEmu::skills::SkillType skillinuse; - AttackAnimation(skillinuse, Hand, weapon); - Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, skillinuse); + DamageHitInfo my_hit; + AttackAnimation(my_hit.skill, Hand, weapon); + Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, my_hit.skill); /// Now figure out damage - int damage = 0; + my_hit.damage_done =0; uint8 mylevel = GetLevel() ? GetLevel() : 1; uint32 hate = 0; if (weapon) hate = (weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt); - int weapon_damage = GetWeaponDamage(other, weapon, &hate); - if (hate == 0 && weapon_damage > 1) - hate = weapon_damage; + my_hit.base_damage = GetWeaponDamage(other, weapon, &hate); + if (hate == 0 && my_hit.base_damage > 1) + hate = my_hit.base_damage; //if weapon damage > 0 then we know we can hit the target with this weapon //otherwise we cannot and we set the damage to -5 later on - if(weapon_damage > 0) { - int min_damage = 0; + if (my_hit.base_damage > 0) { + my_hit.min_damage = 0; // *************************************************************** // *** Calculate the damage bonus, if applicable, for this hit *** @@ -3736,7 +3736,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b // Damage bonuses apply only to hits from the main hand (Hand == MainPrimary) by characters level 28 and above // who belong to a melee class. If we're here, then all of these conditions apply. ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); - min_damage = ucDamageBonus; + my_hit.min_damage = ucDamageBonus; hate += ucDamageBonus; } #endif @@ -3744,55 +3744,29 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b if (Hand == EQEmu::inventory::slotSecondary) { if (aabonuses.SecondaryDmgInc || itembonuses.SecondaryDmgInc || spellbonuses.SecondaryDmgInc){ ucDamageBonus = GetWeaponDamageBonus(weapon ? weapon->GetItem() : (const EQEmu::ItemData*) nullptr); - min_damage = ucDamageBonus; + my_hit.min_damage = ucDamageBonus; hate += ucDamageBonus; } } - int min_cap = (weapon_damage * GetMeleeMinDamageMod_SE(skillinuse) / 100); + Log.Out(Logs::Detail, Logs::Combat, "Damage calculated: base %d min damage %d skill %d", my_hit.base_damage, my_hit.min_damage, my_hit.skill); - Log.Out(Logs::Detail, Logs::Combat, "Damage calculated to %d (bonus %d, base %d, str %d, skill %d, DMG %d, lv %d)", - damage, min_damage, weapon_damage, GetSTR(), GetSkill(skillinuse), weapon_damage, mylevel); + my_hit.offense = offense(my_hit.skill); + my_hit.hand = Hand; - auto offense = this->offense(skillinuse); - - if(opts) { - weapon_damage *= opts->damage_percent; - weapon_damage += opts->damage_flat; + if (opts) { + my_hit.base_damage *= opts->damage_percent; + my_hit.base_damage += opts->damage_flat; hate *= opts->hate_percent; hate += opts->hate_flat; } - //check to see if we hit.. - if (other->AvoidDamage(this, damage, Hand)) { - if (!FromRiposte && !IsStrikethrough) { - int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; - if(strike_through && zone->random.Roll(strike_through)) { - Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses! - Attack(other, Hand, false, true); // Strikethrough only gives another attempted hit - return false; - } - if (damage == -3 && !FromRiposte) { - DoRiposte(other); - if (HasDied()) - return false; - } - } - } else { - if (other->CheckHitChance(this, skillinuse)) { - other->MeleeMitigation(this, damage, weapon_damage, offense, skillinuse, opts); - if (damage > 0) { - ApplyDamageTable(damage, offense); - CommonOutgoingHitSuccess(other, damage, min_damage, min_cap, skillinuse, opts); - } - } else { - damage = 0; - } - } - Log.Out(Logs::Detail, Logs::Combat, "Final damage after all reductions: %d", damage); + DoAttack(other, my_hit, opts); + + Log.Out(Logs::Detail, Logs::Combat, "Final damage after all reductions: %d", my_hit.damage_done); + } else { + my_hit.damage_done = DMG_INVULNERABLE; } - else - damage = -5; // Hate Generation is on a per swing basis, regardless of a hit, miss, or block, its always the same. // If we are this far, this means we are atleast making a swing. @@ -3801,14 +3775,14 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b /////////////////////////////////////////////////////////// ////// Send Attack Damage /////////////////////////////////////////////////////////// - other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); + other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill); if (GetHP() < 0) return false; - MeleeLifeTap(damage); + MeleeLifeTap(my_hit.damage_done); - if (damage > 0) + if (my_hit.damage_done > 0) CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); CommonBreakInvisibleFromCombat(); @@ -3816,9 +3790,9 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b BuffFadeByEffect(SE_NegateIfCombat); if(GetTarget()) - TriggerDefensiveProcs(other, Hand, true, damage); + TriggerDefensiveProcs(other, Hand, true, my_hit.damage_done); - if (damage > 0) + if (my_hit.damage_done > 0) return true; else return false; @@ -4699,16 +4673,16 @@ int Bot::GetHandToHandDamage(void) { return 2; } -bool Bot::TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse, int &damage) +bool Bot::TryFinishingBlow(Mob *defender, int &damage) { if (!defender) return false; if (aabonuses.FinishingBlow[1] && !defender->IsClient() && defender->GetHPRatio() < 10) { - int chance = (aabonuses.FinishingBlow[0] / 10); + int chance = aabonuses.FinishingBlow[0]; int fb_damage = aabonuses.FinishingBlow[1]; int levelreq = aabonuses.FinishingBlowLvl[0]; - if (defender->GetLevel() <= levelreq && (chance >= zone->random.Int(0, 1000))) { + if (defender->GetLevel() <= levelreq && (chance >= zone->random.Int(1, 1000))) { Log.Out(Logs::Detail, Logs::Combat, "Landed a finishing blow: levelreq at %d, other level %d", levelreq, defender->GetLevel()); entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); @@ -4849,36 +4823,29 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 } } - int min_cap = max_damage * GetMeleeMinDamageMod_SE(skill) / 100; - int hand = EQEmu::inventory::slotPrimary; - int damage = 0; - auto offense = this->offense(skill); + DamageHitInfo my_hit; + my_hit.base_damage = max_damage; + my_hit.min_damage = min_damage; + my_hit.damage_done = 0; + + my_hit.skill = skill; + my_hit.offense = offense(my_hit.skill); + my_hit.tohit = GetTotalToHit(my_hit.skill, 0); + my_hit.hand = EQEmu::inventory::slotPrimary; + if (skill == EQEmu::skills::SkillThrowing || skill == EQEmu::skills::SkillArchery) - hand = EQEmu::inventory::slotRange; - if (who->AvoidDamage(this, damage, hand)) { - if (damage == -3) - DoRiposte(who); - } else { - if (HitChance || who->CheckHitChance(this, skill)) { - if (max_damage > 0) - who->MeleeMitigation(this, damage, max_damage, offense, skill); - if (damage > 0) { - ApplyDamageTable(damage, offense); - CommonOutgoingHitSuccess(who, damage, min_damage, min_cap, skill); - } - } else { - damage = 0; - } - } + my_hit.hand = EQEmu::inventory::slotRange; + + DoAttack(who, my_hit); who->AddToHateList(this, hate); - who->Damage(this, damage, SPELL_UNKNOWN, skill, false); + who->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, skill, false); if(!GetTarget() || HasDied()) return; - if (damage > 0) + if (my_hit.damage_done > 0) CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); //[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill @@ -4894,7 +4861,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 if (HasSkillProcs()) TrySkillProc(who, skill, (ReuseTime * 1000)); - if (damage > 0 && HasSkillProcSuccess()) + if (my_hit.damage_done > 0 && HasSkillProcSuccess()) TrySkillProc(who, skill, (ReuseTime * 1000), true); } @@ -5030,7 +4997,6 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { return; float HasteModifier = (GetHaste() * 0.01f); - int32 dmg = 0; uint16 skill_to_use = -1; int level = GetLevel(); int reuse = (TauntReuseTime * 1000); @@ -5084,18 +5050,14 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if(skill_to_use == -1) return; + int dmg = GetBaseSkillDamage(static_cast(skill_to_use), GetTarget()); + if (skill_to_use == EQEmu::skills::SkillBash) { if (target != this) { DoAnim(animTailRake); if (GetWeaponDamage(target, GetBotItem(EQEmu::inventory::slotSecondary)) <= 0 && GetWeaponDamage(target, GetBotItem(EQEmu::inventory::slotShoulders)) <= 0) - dmg = -5; - else { - if (!target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) - dmg = 0; - else { - dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); - } - } + dmg = DMG_INVULNERABLE; + reuse = (BashReuseTime * 1000); DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, 0, -1, reuse); did_attack = true; @@ -5104,14 +5066,13 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if (skill_to_use == EQEmu::skills::SkillFrenzy) { int AtkRounds = 3; - int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy); DoAnim(anim2HSlashing); reuse = (FrenzyReuseTime * 1000); did_attack = true; while(AtkRounds > 0) { if (GetTarget() && (AtkRounds == 1 || zone->random.Int(0, 100) < 75)) { - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, 0, max_dmg, reuse, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, dmg, 0, dmg, reuse, true); } AtkRounds--; @@ -5122,14 +5083,8 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { if(target != this) { DoAnim(animKick); if (GetWeaponDamage(target, GetBotItem(EQEmu::inventory::slotFeet)) <= 0) - dmg = -5; - else { - if (!target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) - dmg = 0; - else { - dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); - } - } + dmg = DMG_INVULNERABLE; + reuse = (KickReuseTime * 1000); DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, 0, -1, reuse); did_attack = true; diff --git a/zone/bot.h b/zone/bot.h index 177efeffb..5431df341 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -239,7 +239,7 @@ public: uint16 BotGetSpellPriority(int spellslot) { return AIspells[spellslot].priority; } virtual float GetProcChances(float ProcBonus, uint16 hand); virtual int GetHandToHandDamage(void); - virtual bool TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse, int &damage); + virtual bool TryFinishingBlow(Mob *defender, int &damage); virtual void DoRiposte(Mob* defender); inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK + ((GetSTR() + GetSkill(EQEmu::skills::SkillOffense)) * 9 / 10); } inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; } diff --git a/zone/common.h b/zone/common.h index 5a6782148..2ed076b6f 100644 --- a/zone/common.h +++ b/zone/common.h @@ -35,6 +35,13 @@ #define CON_YELLOW 15 #define CON_RED 13 +#define DMG_BLOCKED -1 +#define DMG_PARRIED -2 +#define DMG_RIPOSTED -3 +#define DMG_DODGED -4 +#define DMG_INVULNERABLE -5 +#define DMG_RUNE -6 + //Spell specialization parameters, not sure of a better place for them #define SPECIALIZE_FIZZLE 11 //% fizzle chance reduce at 200 specialized #define SPECIALIZE_MANA_REDUCE 12 //% mana cost reduction at 200 specialized @@ -464,9 +471,9 @@ struct StatBonuses { int8 CriticalMend; // chance critical monk mend int32 ImprovedReclaimEnergy; // Modifies amount of mana returned from reclaim energy uint32 HeadShot[2]; // Headshot AA (Massive dmg vs humaniod w/ archery) 0= ? 1= Dmg - uint8 HSLevel; // Max Level Headshot will be effective at. + uint8 HSLevel[2]; // Max Level Headshot will be effective at. and chance mod uint32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg - uint8 AssassinateLevel; // Max Level Assassinate will be effective at. + uint8 AssassinateLevel[2]; // Max Level Assassinate will be effective at. int32 PetMeleeMitigation; // Add AC to owner's pet. bool IllusionPersistence; // Causes illusions not to fade. uint16 extra_xtargets; // extra xtarget entries @@ -644,5 +651,17 @@ struct DamageTable { int32 minusfactor; // difficulty of rolling }; +struct DamageHitInfo { + //uint16 attacker; // id + //uint16 defender; // id + int base_damage; + int min_damage; + int damage_done; + int offense; + int tohit; + int hand; + EQEmu::skills::SkillType skill; +}; + #endif diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index d13ff4a52..add24d861 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1270,12 +1270,6 @@ void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, in self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage, hate_override, reuse_time); } -void Lua_Mob::DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override, int reuse_time, - bool hit_chance) { - Lua_Safe_Call_Void(); - self->DoSpecialAttackDamage(other, static_cast(skill), max_damage, min_damage, hate_override, reuse_time, hit_chance); -} - void Lua_Mob::DoThrowingAttackDmg(Lua_Mob other) { Lua_Safe_Call_Void(); self->DoThrowingAttackDmg(other); @@ -2218,7 +2212,6 @@ luabind::scope lua_register_mob() { .def("DoSpecialAttackDamage", (void(Lua_Mob::*)(Lua_Mob,int,int,int))&Lua_Mob::DoSpecialAttackDamage) .def("DoSpecialAttackDamage", (void(Lua_Mob::*)(Lua_Mob,int,int,int,int))&Lua_Mob::DoSpecialAttackDamage) .def("DoSpecialAttackDamage", (void(Lua_Mob::*)(Lua_Mob,int,int,int,int,int))&Lua_Mob::DoSpecialAttackDamage) - .def("DoSpecialAttackDamage", (void(Lua_Mob::*)(Lua_Mob,int,int,int,int,int,bool))&Lua_Mob::DoSpecialAttackDamage) .def("DoThrowingAttackDmg", (void(Lua_Mob::*)(Lua_Mob))&Lua_Mob::DoThrowingAttackDmg) .def("DoThrowingAttackDmg", (void(Lua_Mob::*)(Lua_Mob,Lua_ItemInst))&Lua_Mob::DoThrowingAttackDmg) .def("DoThrowingAttackDmg", (void(Lua_Mob::*)(Lua_Mob,Lua_ItemInst,Lua_Item))&Lua_Mob::DoThrowingAttackDmg) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 4fd1f0c69..37bde994a 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -267,7 +267,6 @@ public: void DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage); void DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override); void DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override, int reuse_time); - void DoSpecialAttackDamage(Lua_Mob other, int skill, int max_damage, int min_damage, int hate_override, int reuse_time, bool hit_chance); void DoThrowingAttackDmg(Lua_Mob other); void DoThrowingAttackDmg(Lua_Mob other, Lua_ItemInst range_weapon); void DoThrowingAttackDmg(Lua_Mob other, Lua_ItemInst range_weapon, Lua_Item item); diff --git a/zone/merc.cpp b/zone/merc.cpp index 6021f05d5..be8f75e60 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -4426,15 +4426,10 @@ void Merc::DoClassAttacks(Mob *target) { if(zone->random.Int(0, 100) > 25) //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference. { DoAnim(animKick); - int32 dmg = 0; + int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); - if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ - dmg = -5; - } - else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) - dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick, GetTarget()); - } + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) + dmg = DMG_INVULNERABLE; reuse = KickReuseTime * 1000; DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, 1, -1, reuse); @@ -4443,15 +4438,10 @@ void Merc::DoClassAttacks(Mob *target) { else { DoAnim(animTailRake); - int32 dmg = 0; + int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); - if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ - dmg = -5; - } - else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) - dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash, GetTarget()); - } + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) + dmg = DMG_INVULNERABLE; reuse = BashReuseTime * 1000; DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, 1, -1, reuse); diff --git a/zone/mob.h b/zone/mob.h index 0dfa162c1..d6fd610cd 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -162,21 +162,22 @@ public: // 13 = Primary (default), 14 = secondary virtual bool Attack(Mob* other, int Hand = EQEmu::inventory::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) = 0; + void DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr); int MonkSpecialAttack(Mob* other, uint8 skill_used); virtual void TryBackstab(Mob *other,int ReuseTime = 10); - bool AvoidDamage(Mob* attacker, int &damage, int hand); + bool AvoidDamage(Mob *attacker, DamageHitInfo &hit); int compute_tohit(EQEmu::skills::SkillType skillinuse); int GetTotalToHit(EQEmu::skills::SkillType skill, int chance_mod); // compute_tohit + spell bonuses int compute_defense(); int GetTotalDefense(); // compute_defense + spell bonuses - bool CheckHitChance(Mob* attacker, EQEmu::skills::SkillType skillinuse, int chance_mod = 0); - virtual void TryCriticalHit(Mob *defender, uint16 skill, int &damage, int min_damage, ExtraAttackOptions *opts = nullptr); - void TryPetCriticalHit(Mob *defender, uint16 skill, int &damage); - virtual bool TryFinishingBlow(Mob *defender, EQEmu::skills::SkillType skillinuse, int &damage); + bool CheckHitChance(Mob* attacker, DamageHitInfo &hit); + void TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr); + void TryPetCriticalHit(Mob *defender, DamageHitInfo &hit); + virtual bool TryFinishingBlow(Mob *defender, int &damage); int TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse); - int TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, uint16 ReuseTime); + int TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse); virtual void DoRiposte(Mob* defender); - void ApplyMeleeDamageBonus(uint16 skill, int &damage,ExtraAttackOptions *opts = nullptr); + void ApplyMeleeDamageMods(uint16 skill, int &damage, Mob * defender = nullptr, ExtraAttackOptions *opts = nullptr); int ACSum(); int offense(EQEmu::skills::SkillType skill); void CalcAC() { mitigation_ac = ACSum(); } @@ -184,12 +185,12 @@ public: double GetSoftcapReturns(); int GetClassRaceACBonus(); inline int GetMitigationAC() { return mitigation_ac; } - void MeleeMitigation(Mob *attacker, int &damage, int base_damage, int offense, EQEmu::skills::SkillType, ExtraAttackOptions *opts = nullptr); - double RollD20(double offense, double mitigation); // CALL THIS FROM THE DEFENDER + void MeleeMitigation(Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr); + double RollD20(int offense, int mitigation); // CALL THIS FROM THE DEFENDER bool CombatRange(Mob* other); virtual inline bool IsBerserk() { return false; } // only clients void RogueEvade(Mob *other); - void CommonOutgoingHitSuccess(Mob* defender, int &damage, int min_damage, int min_mod, EQEmu::skills::SkillType skillInUse, ExtraAttackOptions *opts = nullptr); + void CommonOutgoingHitSuccess(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts = nullptr); void BreakInvisibleSpells(); virtual void CancelSneakHide(); void CommonBreakInvisible(); @@ -794,7 +795,7 @@ public: uint8 GetWeaponDamageBonus(const EQEmu::ItemData* weapon, bool offhand = false); const DamageTable &GetDamageTable() const; - void ApplyDamageTable(int &damage, int offense); + void ApplyDamageTable(DamageHitInfo &hit); virtual int GetHandToHandDamage(void); bool CanThisClassDoubleAttack(void) const; @@ -817,7 +818,7 @@ public: int32 AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTic, Mob* attacker); int32 ReduceAllDamage(int32 damage); - void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int base_damage, int min_damage = 0, int32 hate_override = -1, int ReuseTime = 10, bool CheckHitChance = false, bool CanAvoid = true); + void DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int base_damage, int min_damage = 0, int32 hate_override = -1, int ReuseTime = 10); virtual void DoThrowingAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon = nullptr, const EQEmu::ItemData* AmmoItem = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, int AmmoSlot = 0, float speed = 4.0f); void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod = 0, int16 focus = 0, bool CanRiposte = false, int ReuseTime = 0); virtual void DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon = nullptr, const EQEmu::ItemInstance* Ammo = nullptr, uint16 weapon_damage = 0, int16 chance_mod = 0, int16 focus = 0, int ReuseTime = 0, uint32 range_id = 0, uint32 ammo_id = 0, const EQEmu::ItemData *AmmoItem = nullptr, int AmmoSlot = 0, float speed = 4.0f); @@ -1187,8 +1188,6 @@ protected: void ExecWeaponProc(const EQEmu::ItemInstance* weapon, uint16 spell_id, Mob *on, int level_override = -1); virtual float GetProcChances(float ProcBonus, uint16 hand = EQEmu::inventory::slotPrimary); virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = EQEmu::inventory::slotPrimary, Mob *on = nullptr); - virtual float GetSpecialProcChances(uint16 hand); - virtual float GetAssassinateProcChances(uint16 ReuseTime); virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm? uint16 GetWeaponSpeedbyHand(uint16 hand); int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 929c272d9..7f6ec112d 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -131,7 +131,7 @@ int Mob::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target) } void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, - int32 hate_override, int ReuseTime, bool CheckHitChance, bool CanAvoid) + int32 hate_override, int ReuseTime) { // this really should go through the same code as normal melee damage to // pick up all the special behavior there @@ -141,15 +141,22 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 (!IsAttackAllowed(who)))) return; - int damage = 0; + DamageHitInfo my_hit; + my_hit.damage_done = 0; + my_hit.base_damage = base_damage; + my_hit.min_damage = min_damage; + my_hit.skill = skill; + + if (my_hit.base_damage == 0) + my_hit.base_damage = GetBaseSkillDamage(my_hit.skill); if (who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE)) - damage = -5; + my_hit.damage_done = DMG_INVULNERABLE; if (who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE) && skill != EQEmu::skills::SkillBackstab) - damage = -5; + my_hit.damage_done = DMG_INVULNERABLE; - uint32 hate = base_damage; + uint32 hate = my_hit.base_damage; if (hate_override > -1) hate = hate_override; @@ -169,39 +176,26 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 } } - int min_cap = base_damage * GetMeleeMinDamageMod_SE(skill) / 100; + my_hit.offense = offense(my_hit.skill); + my_hit.tohit = GetTotalToHit(my_hit.skill, 0); - auto offense = this->offense(skill); - - int hand = EQEmu::inventory::slotPrimary; // Avoid checks hand for throwing/archery exclusion, primary should + my_hit.hand = EQEmu::inventory::slotPrimary; // Avoid checks hand for throwing/archery exclusion, primary should // work for most if (skill == EQEmu::skills::SkillThrowing || skill == EQEmu::skills::SkillArchery) - hand = EQEmu::inventory::slotRange; - if (who->AvoidDamage(this, damage, hand)) { - if (damage == -3) - DoRiposte(who); - } else { - if (!CheckHitChance || who->CheckHitChance(this, skill)) { - if (base_damage > 0) // we do this weird, so we have to check it first :( - who->MeleeMitigation(this, damage, base_damage, offense, skill); - if (damage > 0) { - ApplyDamageTable(damage, offense); - CommonOutgoingHitSuccess(who, damage, min_damage, min_cap, skill); - } - } else { - damage = 0; - } - } + my_hit.hand = EQEmu::inventory::slotRange; + + DoAttack(who, my_hit); who->AddToHateList(this, hate, 0, false); - if (damage > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == skill && + if (my_hit.damage_done > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == skill && IsValidSpell(aabonuses.SkillAttackProc[2])) { float chance = aabonuses.SkillAttackProc[0] / 1000.0f; if (zone->random.Roll(chance)) SpellFinished(aabonuses.SkillAttackProc[2], who, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } - who->Damage(this, damage, SPELL_UNKNOWN, skill, false); + + who->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, skill, false); // Make sure 'this' has not killed the target and 'this' is not dead (Damage shield ect). if (!GetTarget()) @@ -212,7 +206,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 if (HasSkillProcs()) TrySkillProc(who, skill, ReuseTime * 1000); - if (damage > 0 && HasSkillProcSuccess()) + if (my_hit.damage_done > 0 && HasSkillProcSuccess()) TrySkillProc(who, skill, ReuseTime * 1000, true); } @@ -302,7 +296,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) ReuseTime = BashReuseTime - 1 - skill_reduction; ReuseTime = (ReuseTime * HasteMod) / 100; - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillBash, dmg, 0, ht, ReuseTime, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillBash, dmg, 0, ht, ReuseTime); if (ReuseTime > 0) p_timers.Start(timer, ReuseTime); } @@ -311,21 +305,26 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) if (ca_atk->m_atk == 100 && ca_atk->m_skill == EQEmu::skills::SkillFrenzy) { CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10); - int AtkRounds = 3; + int AtkRounds = 1; int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy, GetTarget()); DoAnim(anim2HSlashing); max_dmg = mod_frenzy_damage(max_dmg); + if (GetClass() == BERSERKER) { + int chance = GetLevel() * 2 + GetSkill(EQEmu::skills::SkillFrenzy); + if (zone->random.Roll0(450) < chance) + AtkRounds++; + if (zone->random.Roll0(450) < chance) + AtkRounds++; + } + ReuseTime = FrenzyReuseTime - 1 - skill_reduction; ReuseTime = (ReuseTime * HasteMod) / 100; - // Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit. while (AtkRounds > 0) { - if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, 0, max_dmg, - ReuseTime, true); - } + if (GetTarget()) + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, 0, max_dmg, ReuseTime); AtkRounds--; } @@ -352,7 +351,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) ht = dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick, GetTarget()); ReuseTime = KickReuseTime - 1 - skill_reduction; - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillKick, dmg, 0, ht, ReuseTime, true); + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillKick, dmg, 0, ht, ReuseTime); } break; case MONK: { @@ -362,25 +361,28 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; if (wuchance) { - if (wuchance >= 100 || zone->random.Roll(wuchance)) { - const int MonkSPA[5] = {EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, - EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, - EQEmu::skills::SkillRoundKick}; - int extra = 1; - // always 1/4 of the double attack chance, 25% at rank 5 (100/4) - if (zone->random.Roll(wuchance / 4)) + const int MonkSPA[5] = {EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, + EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, + EQEmu::skills::SkillRoundKick}; + int extra = 0; + // always 1/4 of the double attack chance, 25% at rank 5 (100/4) + while (wuchance > 0) { + if (zone->random.Roll(wuchance)) extra++; - // They didn't add a string ID for this. - std::string msg = StringFormat( - "The spirit of Master Wu fills you! You gain %d additional attack(s).", extra); - // live uses 400 here -- not sure if it's the best for all clients though - SendColoredText(400, msg); - auto classic = RuleB(Combat, ClassicMasterWu); - while (extra) { - MonkSpecialAttack(GetTarget(), - classic ? MonkSPA[zone->random.Int(0, 4)] : ca_atk->m_skill); - extra--; - } + else + break; + wuchance /= 4; + } + // They didn't add a string ID for this. + std::string msg = StringFormat( + "The spirit of Master Wu fills you! You gain %d additional attack(s).", extra); + // live uses 400 here -- not sure if it's the best for all clients though + SendColoredText(400, msg); + auto classic = RuleB(Combat, ClassicMasterWu); + while (extra) { + MonkSpecialAttack(GetTarget(), + classic ? MonkSPA[zone->random.Int(0, 4)] : ca_atk->m_skill); + extra--; } } @@ -476,11 +478,11 @@ int Mob::MonkSpecialAttack(Mob *other, uint8 unchecked_type) if (IsClient()) { if (GetWeaponDamage(other, CastToClient()->GetInv().GetItem(itemslot)) <= 0) { - max_dmg = -5; + max_dmg = DMG_INVULNERABLE; } } else { if (GetWeaponDamage(other, (const EQEmu::ItemData *)nullptr) <= 0) { - max_dmg = -5; + max_dmg = DMG_INVULNERABLE; } } @@ -491,7 +493,7 @@ int Mob::MonkSpecialAttack(Mob *other, uint8 unchecked_type) // This can potentially stack with changes to kick damage ht = ndamage = mod_monk_special_damage(ndamage, skill_type); - DoSpecialAttackDamage(other, skill_type, max_dmg, min_dmg, ht, reuse, true); + DoSpecialAttackDamage(other, skill_type, max_dmg, min_dmg, ht, reuse); return reuse; } @@ -532,6 +534,7 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { RogueBackstab(other,false,ReuseTime); if (level > 54) { + // TODO: 55-59 doesn't appear to match just checking double attack, 60+ does though if(IsClient() && CastToClient()->CheckDoubleAttack()) { if(other->GetHP() > 0) @@ -583,7 +586,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) int base_damage = GetBaseSkillDamage(EQEmu::skills::SkillBackstab, other); hate = base_damage; - DoSpecialAttackDamage(other, EQEmu::skills::SkillBackstab, base_damage, 0, hate, ReuseTime, true, false); + DoSpecialAttackDamage(other, EQEmu::skills::SkillBackstab, base_damage, 0, hate, ReuseTime); DoAnim(anim1HPiercing); } @@ -732,23 +735,20 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { CommonBreakInvisibleFromCombat(); } -void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon, const EQEmu::ItemInstance* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, - uint32 range_id, uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed) { +void Mob::DoArcheryAttackDmg(Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemInstance *Ammo, + uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, uint32 range_id, + uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed) +{ if ((other == nullptr || - ((IsClient() && CastToClient()->dead) || - (other->IsClient() && other->CastToClient()->dead)) || - HasDied() || - (!IsAttackAllowed(other)) || - (other->GetInvul() || - other->GetSpecialAbility(IMMUNE_MELEE)))) - { + ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) || + HasDied() || (!IsAttackAllowed(other)) || (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)))) { return; } - const EQEmu::ItemInstance* _RangeWeapon = nullptr; - const EQEmu::ItemInstance* _Ammo = nullptr; - const EQEmu::ItemData* ammo_lost = nullptr; + const EQEmu::ItemInstance *_RangeWeapon = nullptr; + const EQEmu::ItemInstance *_Ammo = nullptr; + const EQEmu::ItemData *ammo_lost = nullptr; /* If LaunchProjectile is false this function will do archery damage on target, @@ -756,32 +756,24 @@ void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon this function is then run again to do the damage portion */ bool LaunchProjectile = false; - bool ProjectileImpact = false; - bool ProjectileMiss = false; - if (RuleB(Combat, ProjectileDmgOnImpact)){ - - if (AmmoItem) + if (RuleB(Combat, ProjectileDmgOnImpact)) { + if (AmmoItem) { // won't be null when we are firing the arrow LaunchProjectile = true; - else{ + } else { /* Item sync check on projectile landing. Weapon damage is already calculated so this only affects procs! Ammo proc check will use database to find proc if you used up your last ammo. - If you change range item mid projectile flight, you loose your chance to proc from bow (Deal with it!). + If you change range item mid projectile flight, you loose your chance to proc from bow (Deal + with it!). */ - if (!RangeWeapon && !Ammo && range_id && ammo_id){ - - ProjectileImpact = true; - - if (weapon_damage == 0) - ProjectileMiss = true; //This indicates that MISS was originally calculated. - - if (IsClient()){ - + if (!RangeWeapon && !Ammo && range_id && ammo_id) { + if (IsClient()) { _RangeWeapon = CastToClient()->m_inv[EQEmu::inventory::slotRange]; - if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID == range_id) + if (_RangeWeapon && _RangeWeapon->GetItem() && + _RangeWeapon->GetItem()->ID == range_id) RangeWeapon = _RangeWeapon; _Ammo = CastToClient()->m_inv[AmmoSlot]; @@ -792,103 +784,96 @@ void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon } } } - } - else if (AmmoItem) + } else if (AmmoItem) { SendItemAnimation(other, AmmoItem, EQEmu::skills::SkillArchery); - - if (ProjectileMiss || (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillArchery, chance_mod))) { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); - - if (LaunchProjectile){ - TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillArchery, 0, RangeWeapon, Ammo, AmmoSlot, speed); - return; - } - else - other->Damage(this, 0, SPELL_UNKNOWN, EQEmu::skills::SkillArchery); - } else { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack hit %s.", other->GetName()); - - uint32 hate = 0; - int32 TotalDmg = 0; - int16 WDmg = 0; - int16 ADmg = 0; - if (!weapon_damage){ - WDmg = GetWeaponDamage(other, RangeWeapon); - ADmg = GetWeaponDamage(other, Ammo); - } - else - WDmg = weapon_damage; - - if (LaunchProjectile){//1: Shoot the Projectile once we calculate weapon damage. - TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillArchery, (WDmg + ADmg), RangeWeapon, Ammo, AmmoSlot, speed); - return; - } - - // unsure when this should happen - if (focus) //From FcBaseEffects - WDmg += WDmg * focus / 100; - - if((WDmg > 0) || (ADmg > 0)) { - if(WDmg < 0) - WDmg = 0; - if(ADmg < 0) - ADmg = 0; - uint32 MaxDmg = WDmg + ADmg; - hate = ((WDmg+ADmg)); - - if (RuleB(Combat, ProjectileDmgOnImpact)) - Log.Out(Logs::Detail, Logs::Combat, "Bow and Arrow DMG %d, Max Damage %d.", WDmg, MaxDmg); - else - Log.Out(Logs::Detail, Logs::Combat, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg); - - if (MaxDmg == 0) - MaxDmg = 1; - - int min_cap = MaxDmg * GetMeleeMinDamageMod_SE(EQEmu::skills::SkillArchery) / 100; - auto offense = this->offense(EQEmu::skills::SkillArchery); - - other->AvoidDamage(this, TotalDmg, EQEmu::inventory::slotRange); - - other->MeleeMitigation(this, TotalDmg, MaxDmg, offense, EQEmu::skills::SkillArchery); - if(TotalDmg > 0){ - if (IsClient()) - ApplyDamageTable(TotalDmg, offense); - CommonOutgoingHitSuccess(other, TotalDmg, 0, min_cap, EQEmu::skills::SkillArchery); - //TotalDmg = mod_archery_damage(TotalDmg, dobonus, RangeWeapon); - } - } - else - TotalDmg = -5; - - if (IsClient() && !CastToClient()->GetFeigned()) - other->AddToHateList(this, hate, 0, false); - - other->Damage(this, TotalDmg, SPELL_UNKNOWN, EQEmu::skills::SkillArchery); - - //Skill Proc Success - if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()){ - if (ReuseTime) - TrySkillProc(other, EQEmu::skills::SkillArchery, ReuseTime); - else - TrySkillProc(other, EQEmu::skills::SkillArchery, 0, true, EQEmu::inventory::slotRange); - } } + Log.Out(Logs::Detail, Logs::Combat, "Ranged attack hit %s.", other->GetName()); + + uint32 hate = 0; + int TotalDmg = 0; + int WDmg = 0; + int ADmg = 0; + if (!weapon_damage) { + WDmg = GetWeaponDamage(other, RangeWeapon); + ADmg = GetWeaponDamage(other, Ammo); + } else { + WDmg = weapon_damage; + } + + if (LaunchProjectile) { // 1: Shoot the Projectile once we calculate weapon damage. + TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillArchery, (WDmg + ADmg), RangeWeapon, + Ammo, AmmoSlot, speed); + return; + } + + // unsure when this should happen + if (focus) // From FcBaseEffects + WDmg += WDmg * focus / 100; + + if (WDmg > 0 || ADmg > 0) { + if (WDmg < 0) + WDmg = 0; + if (ADmg < 0) + ADmg = 0; + int MaxDmg = WDmg + ADmg; + hate = ((WDmg + ADmg)); + + if (RuleB(Combat, ProjectileDmgOnImpact)) + Log.Out(Logs::Detail, Logs::Combat, "Bow and Arrow DMG %d, Max Damage %d.", WDmg, + MaxDmg); + else + Log.Out(Logs::Detail, Logs::Combat, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, + ADmg, MaxDmg); + + if (MaxDmg == 0) + MaxDmg = 1; + + DamageHitInfo my_hit; + my_hit.base_damage = MaxDmg; + my_hit.min_damage = 0; + my_hit.damage_done = 0; + + my_hit.skill = EQEmu::skills::SkillArchery; + my_hit.offense = offense(my_hit.skill); + my_hit.tohit = GetTotalToHit(my_hit.skill, chance_mod); + my_hit.hand = EQEmu::inventory::slotRange; + + DoAttack(other, my_hit); + TotalDmg = my_hit.damage_done; + } else { + TotalDmg = DMG_INVULNERABLE; + } + + if (IsClient() && !CastToClient()->GetFeigned()) + other->AddToHateList(this, hate, 0, false); + + other->Damage(this, TotalDmg, SPELL_UNKNOWN, EQEmu::skills::SkillArchery); + + // Skill Proc Success + if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()) { + if (ReuseTime) + TrySkillProc(other, EQEmu::skills::SkillArchery, ReuseTime); + else + TrySkillProc(other, EQEmu::skills::SkillArchery, 0, true, EQEmu::inventory::slotRange); + } + // end of old fuck + if (LaunchProjectile) - return;//Shouldn't reach this point durring initial launch phase, but just in case. + return; // Shouldn't reach this point durring initial launch phase, but just in case. - //Weapon Proc - if(RangeWeapon && other && !other->HasDied()) + // Weapon Proc + if (RangeWeapon && other && !other->HasDied()) TryWeaponProc(RangeWeapon, other, EQEmu::inventory::slotRange); - //Ammo Proc + // Ammo Proc if (ammo_lost) TryWeaponProc(nullptr, ammo_lost, other, EQEmu::inventory::slotRange); - else if(Ammo && other && !other->HasDied()) + else if (Ammo && other && !other->HasDied()) TryWeaponProc(Ammo, other, EQEmu::inventory::slotRange); - //Skill Proc - if (HasSkillProcs() && other && !other->HasDied()){ + // Skill Proc + if (HasSkillProcs() && other && !other->HasDied()) { if (ReuseTime) TrySkillProc(other, EQEmu::skills::SkillArchery, ReuseTime); else @@ -896,16 +881,18 @@ void Mob::DoArcheryAttackDmg(Mob* other, const EQEmu::ItemInstance* RangeWeapon } } -bool Mob::TryProjectileAttack(Mob* other, const EQEmu::ItemData *item, EQEmu::skills::SkillType skillInUse, uint16 weapon_dmg, const EQEmu::ItemInstance* RangeWeapon, const EQEmu::ItemInstance* Ammo, int AmmoSlot, float speed){ - +bool Mob::TryProjectileAttack(Mob *other, const EQEmu::ItemData *item, EQEmu::skills::SkillType skillInUse, + uint16 weapon_dmg, const EQEmu::ItemInstance *RangeWeapon, + const EQEmu::ItemInstance *Ammo, int AmmoSlot, float speed) +{ if (!other) return false; int slot = -1; - //Make sure there is an avialable slot. + // Make sure there is an avialable slot. for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { - if (ProjectileAtk[i].target_id == 0){ + if (ProjectileAtk[i].target_id == 0) { slot = i; break; } @@ -917,10 +904,11 @@ bool Mob::TryProjectileAttack(Mob* other, const EQEmu::ItemData *item, EQEmu::sk float speed_mod = speed * 0.45f; float distance = other->CalculateDistance(GetX(), GetY(), GetZ()); - float hit = 60.0f + (distance / speed_mod); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) + float hit = + 60.0f + (distance / speed_mod); // Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) ProjectileAtk[slot].increment = 1; - ProjectileAtk[slot].hit_increment = static_cast(hit); //This projected hit time if target does NOT MOVE + ProjectileAtk[slot].hit_increment = static_cast(hit); // This projected hit time if target does NOT MOVE ProjectileAtk[slot].target_id = other->GetID(); ProjectileAtk[slot].wpn_dmg = weapon_dmg; ProjectileAtk[slot].origin_x = GetX(); @@ -939,64 +927,74 @@ bool Mob::TryProjectileAttack(Mob* other, const EQEmu::ItemData *item, EQEmu::sk SetProjectileAttack(true); - if(item) + if (item) SendItemAnimation(other, item, skillInUse, speed); - //else if (IsNPC()) - //ProjectileAnimation(other, 0,false,speed,0,0,0,CastToNPC()->GetAmmoIDfile(),skillInUse); + // else if (IsNPC()) + // ProjectileAnimation(other, 0,false,speed,0,0,0,CastToNPC()->GetAmmoIDfile(),skillInUse); return true; } - void Mob::ProjectileAttack() { if (!HasProjectileAttack()) - return;; + return; + ; - Mob* target = nullptr; + Mob *target = nullptr; bool disable = true; for (int i = 0; i < MAX_SPELL_PROJECTILE; i++) { - - if (ProjectileAtk[i].increment == 0){ + if (ProjectileAtk[i].increment == 0) continue; - } disable = false; - Mob* target = entity_list.GetMobID(ProjectileAtk[i].target_id); + Mob *target = entity_list.GetMobID(ProjectileAtk[i].target_id); - if (target && target->IsMoving()){ //Only recalculate hit increment if target moving - //Due to frequency that we need to check increment the targets position variables may not be updated even if moving. Do a simple check before calculating distance. - if (ProjectileAtk[i].tlast_x != target->GetX() || ProjectileAtk[i].tlast_y != target->GetY()){ + if (target && target->IsMoving()) { // Only recalculate hit increment if target moving + // Due to frequency that we need to check increment the targets position variables may not be + // updated even if moving. Do a simple check before calculating distance. + if (ProjectileAtk[i].tlast_x != target->GetX() || ProjectileAtk[i].tlast_y != target->GetY()) { ProjectileAtk[i].tlast_x = target->GetX(); ProjectileAtk[i].tlast_y = target->GetY(); - float distance = target->CalculateDistance(ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z); - float hit = 60.0f + (distance / ProjectileAtk[i].speed_mod); //Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4) + float distance = target->CalculateDistance( + ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z); + float hit = 60.0f + (distance / ProjectileAtk[i].speed_mod); // Calcuation: 60 = + // Animation Lag, 1.8 = + // Speed modifier for speed + // of (4) ProjectileAtk[i].hit_increment = static_cast(hit); } } - if (ProjectileAtk[i].hit_increment <= ProjectileAtk[i].increment){ - - if (target){ - - if (IsNPC()){ - if (ProjectileAtk[i].skill == EQEmu::skills::SkillConjuration){ + // We hit I guess? + if (ProjectileAtk[i].hit_increment <= ProjectileAtk[i].increment) { + if (target) { + if (IsNPC()) { + if (ProjectileAtk[i].skill == EQEmu::skills::SkillConjuration) { if (IsValidSpell(ProjectileAtk[i].wpn_dmg)) - SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true); + SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, + spells[ProjectileAtk[i].wpn_dmg].ResistDiff, + true); + } else { + CastToNPC()->DoRangedAttackDmg( + target, false, ProjectileAtk[i].wpn_dmg, 0, + static_cast(ProjectileAtk[i].skill)); } - else - CastToNPC()->DoRangedAttackDmg(target, false, ProjectileAtk[i].wpn_dmg, 0, static_cast(ProjectileAtk[i].skill)); - } - - else - { + } else { if (ProjectileAtk[i].skill == EQEmu::skills::SkillArchery) - DoArcheryAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0,ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_id, nullptr, ProjectileAtk[i].ammo_slot); + DoArcheryAttackDmg(target, nullptr, nullptr, ProjectileAtk[i].wpn_dmg, + 0, 0, 0, ProjectileAtk[i].ranged_id, + ProjectileAtk[i].ammo_id, nullptr, + ProjectileAtk[i].ammo_slot); else if (ProjectileAtk[i].skill == EQEmu::skills::SkillThrowing) - DoThrowingAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0, ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_slot); - else if (ProjectileAtk[i].skill == EQEmu::skills::SkillConjuration && IsValidSpell(ProjectileAtk[i].wpn_dmg)) - SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true); + DoThrowingAttackDmg(target, nullptr, nullptr, ProjectileAtk[i].wpn_dmg, + 0, 0, 0, ProjectileAtk[i].ranged_id, + ProjectileAtk[i].ammo_slot); + else if (ProjectileAtk[i].skill == EQEmu::skills::SkillConjuration && + IsValidSpell(ProjectileAtk[i].wpn_dmg)) + SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, + spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true); } } @@ -1013,9 +1011,7 @@ void Mob::ProjectileAttack() ProjectileAtk[i].ammo_slot = 0; ProjectileAtk[i].skill = 0; ProjectileAtk[i].speed_mod = 0.0f; - } - - else { + } else { ProjectileAtk[i].increment++; } } @@ -1158,39 +1154,38 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha if (!chance_mod) chance_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2); - if (!other->CheckHitChance(this, skillInUse, chance_mod)) - { - other->Damage(this, 0, SPELL_UNKNOWN, skillInUse); + int TotalDmg = 0; + int MaxDmg = GetBaseDamage() * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types + int MinDmg = GetMinDamage() * RuleR(Combat, ArcheryNPCMultiplier); + + if (!damage_mod) + damage_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3);//Damage modifier + + DamageHitInfo my_hit; + my_hit.base_damage = MaxDmg; + my_hit.min_damage = MinDmg; + my_hit.damage_done = 0; + + my_hit.skill = skill; + my_hit.offense = offense(my_hit.skill); + my_hit.tohit = GetTotalToHit(my_hit.skill, chance_mod); + my_hit.hand = EQEmu::inventory::slotRange; + + DoAttack(other, my_hit); + + TotalDmg = my_hit.damage_done; + + if (TotalDmg > 0) { + TotalDmg += TotalDmg * damage_mod / 100; + other->AddToHateList(this, TotalDmg, 0, false); + } else { + other->AddToHateList(this, 0, 0, false); } - else - { - int TotalDmg = 0; - int MaxDmg = GetBaseDamage() * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types - int MinDmg = GetMinDamage() * RuleR(Combat, ArcheryNPCMultiplier); - if (!damage_mod) - damage_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3);//Damage modifier + other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillInUse); - TotalDmg += TotalDmg * damage_mod / 100; - - other->AvoidDamage(this, TotalDmg, EQEmu::inventory::slotRange); - other->MeleeMitigation(this, TotalDmg, MaxDmg, offense(skillInUse), skillInUse); - - if (TotalDmg > 0) - CommonOutgoingHitSuccess(other, TotalDmg, MinDmg, 0, skillInUse); - else if (TotalDmg < -4) - TotalDmg = -5; - - if (TotalDmg > 0) - other->AddToHateList(this, TotalDmg, 0, false); - else - other->AddToHateList(this, 0, 0, false); - - other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillInUse); - - if (TotalDmg > 0 && HasSkillProcSuccess() && !other->HasDied()) - TrySkillProc(other, skillInUse, 0, true, EQEmu::inventory::slotRange); - } + if (TotalDmg > 0 && HasSkillProcSuccess() && !other->HasDied()) + TrySkillProc(other, skillInUse, 0, true, EQEmu::inventory::slotRange); //try proc on hits and misses if(other && !other->HasDied()) @@ -1302,23 +1297,13 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQEmu::ItemInstance *RangeWeapon this function is then run again to do the damage portion */ bool LaunchProjectile = false; - bool ProjectileImpact = false; - bool ProjectileMiss = false; if (RuleB(Combat, ProjectileDmgOnImpact)) { - - if (AmmoItem) + if (AmmoItem) { LaunchProjectile = true; - else { + } else { if (!RangeWeapon && range_id) { - - ProjectileImpact = true; - - if (weapon_damage == 0) - ProjectileMiss = true; // This indicates that MISS was originally calculated. - if (IsClient()) { - _RangeWeapon = CastToClient()->m_inv[AmmoSlot]; if (_RangeWeapon && _RangeWeapon->GetItem() && _RangeWeapon->GetItem()->ID != range_id) @@ -1328,81 +1313,66 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQEmu::ItemInstance *RangeWeapon } } } - } else if (AmmoItem) + } else if (AmmoItem) { SendItemAnimation(other, AmmoItem, EQEmu::skills::SkillThrowing); - - if (ProjectileMiss || - (!ProjectileImpact && !other->CheckHitChance(this, EQEmu::skills::SkillThrowing, chance_mod))) { - Log.Out(Logs::Detail, Logs::Combat, "Ranged attack missed %s.", other->GetName()); - if (LaunchProjectile) { - TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillThrowing, 0, RangeWeapon, nullptr, - AmmoSlot, speed); - return; - } else - other->Damage(this, 0, SPELL_UNKNOWN, EQEmu::skills::SkillThrowing); - } else { - Log.Out(Logs::Detail, Logs::Combat, "Throwing attack hit %s.", other->GetName()); - - int16 WDmg = 0; - - if (!weapon_damage) { - if (IsClient() && RangeWeapon) - WDmg = GetWeaponDamage(other, RangeWeapon); - else if (AmmoItem) - WDmg = GetWeaponDamage(other, AmmoItem); - - if (LaunchProjectile) { - TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillThrowing, WDmg, RangeWeapon, - nullptr, AmmoSlot, speed); - return; - } - } else - WDmg = weapon_damage; - - if (focus) // From FcBaseEffects - WDmg += WDmg * focus / 100; - - int32 TotalDmg = 0; - - uint32 Assassinate_Dmg = 0; - if (GetClass() == ROGUE && (BehindMob(other, GetX(), GetY()))) - Assassinate_Dmg = - TryAssassinate(other, EQEmu::skills::SkillThrowing, ranged_timer.GetDuration()); - - if (WDmg > 0) { - int min_cap = WDmg * GetMeleeMinDamageMod_SE(EQEmu::skills::SkillThrowing) / 100; - auto offense = this->offense(EQEmu::skills::SkillThrowing); - if (Assassinate_Dmg) { - TotalDmg = Assassinate_Dmg; - } - - Log.Out(Logs::Detail, Logs::Combat, "Item DMG %d. Hit for damage %d", WDmg, TotalDmg); - if (!Assassinate_Dmg) - other->AvoidDamage(this, TotalDmg, EQEmu::inventory::slotRange); - - other->MeleeMitigation(this, TotalDmg, WDmg, offense, EQEmu::skills::SkillThrowing); - if (TotalDmg > 0) - if (IsClient()) - ApplyDamageTable(TotalDmg, offense); - CommonOutgoingHitSuccess(other, TotalDmg, 0, min_cap, EQEmu::skills::SkillThrowing); - } - - else - TotalDmg = -5; - - if (IsClient() && !CastToClient()->GetFeigned()) - other->AddToHateList(this, 2 * WDmg, 0, false); - - other->Damage(this, TotalDmg, SPELL_UNKNOWN, EQEmu::skills::SkillThrowing); - - if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()) { - if (ReuseTime) - TrySkillProc(other, EQEmu::skills::SkillThrowing, ReuseTime); - else - TrySkillProc(other, EQEmu::skills::SkillThrowing, 0, true, EQEmu::inventory::slotRange); - } } + Log.Out(Logs::Detail, Logs::Combat, "Throwing attack hit %s.", other->GetName()); + + int WDmg = 0; + + if (!weapon_damage) { + if (IsClient() && RangeWeapon) + WDmg = GetWeaponDamage(other, RangeWeapon); + else if (AmmoItem) + WDmg = GetWeaponDamage(other, AmmoItem); + + if (LaunchProjectile) { + TryProjectileAttack(other, AmmoItem, EQEmu::skills::SkillThrowing, WDmg, RangeWeapon, + nullptr, AmmoSlot, speed); + return; + } + } else { + WDmg = weapon_damage; + } + + if (focus) // From FcBaseEffects + WDmg += WDmg * focus / 100; + + int TotalDmg = 0; + + if (WDmg > 0) { + DamageHitInfo my_hit; + my_hit.base_damage = WDmg; + my_hit.min_damage = 0; + my_hit.damage_done = 0; + + my_hit.skill = EQEmu::skills::SkillThrowing; + my_hit.offense = offense(my_hit.skill); + my_hit.tohit = GetTotalToHit(my_hit.skill, chance_mod); + my_hit.hand = EQEmu::inventory::slotRange; + + DoAttack(other, my_hit); + TotalDmg = my_hit.damage_done; + + Log.Out(Logs::Detail, Logs::Combat, "Item DMG %d. Hit for damage %d", WDmg, TotalDmg); + } else { + TotalDmg = DMG_INVULNERABLE; + } + + if (IsClient() && !CastToClient()->GetFeigned()) + other->AddToHateList(this, WDmg, 0, false); + + other->Damage(this, TotalDmg, SPELL_UNKNOWN, EQEmu::skills::SkillThrowing); + + if (TotalDmg > 0 && HasSkillProcSuccess() && other && !other->HasDied()) { + if (ReuseTime) + TrySkillProc(other, EQEmu::skills::SkillThrowing, ReuseTime); + else + TrySkillProc(other, EQEmu::skills::SkillThrowing, 0, true, EQEmu::inventory::slotRange); + } + // end old shit + if (LaunchProjectile) return; @@ -1609,15 +1579,10 @@ void NPC::DoClassAttacks(Mob *target) { if(level >= RuleI(Combat, NPCBashKickLevel)){ if(zone->random.Roll(75)) { //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference. DoAnim(animKick); - int32 dmg = 0; + int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); - if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ - dmg = -5; - } - else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) - dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); - } + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) + dmg = DMG_INVULNERABLE; reuse = (KickReuseTime + 3) * 1000; DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, GetMinDamage(), -1, reuse); @@ -1625,15 +1590,10 @@ void NPC::DoClassAttacks(Mob *target) { } else { DoAnim(animTailRake); - int32 dmg = 0; + int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); - if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ - dmg = -5; - } - else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) - dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); - } + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) + dmg = DMG_INVULNERABLE; reuse = (BashReuseTime + 3) * 1000; DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, GetMinDamage(), -1, reuse); @@ -1643,14 +1603,21 @@ void NPC::DoClassAttacks(Mob *target) { break; } case BERSERKER: case BERSERKERGM:{ - int AtkRounds = 3; + int AtkRounds = 1; int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy); DoAnim(anim2HSlashing); - while(AtkRounds > 0) { - if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, GetMinDamage(), -1, reuse, true); - } + if (GetClass() == BERSERKER) { + int chance = GetLevel() * 2 + GetSkill(EQEmu::skills::SkillFrenzy); + if (zone->random.Roll0(450) < chance) + AtkRounds++; + if (zone->random.Roll0(450) < chance) + AtkRounds++; + } + + while (AtkRounds > 0) { + if (GetTarget()) + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, GetMinDamage(), -1, reuse); AtkRounds--; } @@ -1662,15 +1629,10 @@ void NPC::DoClassAttacks(Mob *target) { //kick if(level >= RuleI(Combat, NPCBashKickLevel)){ DoAnim(animKick); - int32 dmg = 0; + int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); - if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ - dmg = -5; - } - else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) - dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick); - } + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) + dmg = DMG_INVULNERABLE; reuse = (KickReuseTime + 3) * 1000; DoSpecialAttackDamage(target, EQEmu::skills::SkillKick, dmg, GetMinDamage(), -1, reuse); @@ -1683,15 +1645,10 @@ void NPC::DoClassAttacks(Mob *target) { case PALADIN: case PALADINGM:{ if(level >= RuleI(Combat, NPCBashKickLevel)){ DoAnim(animTailRake); - int32 dmg = 0; + int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); - if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0){ - dmg = -5; - } - else{ - if (target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) - dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash); - } + if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0) + dmg = DMG_INVULNERABLE; reuse = (BashReuseTime + 3) * 1000; DoSpecialAttackDamage(target, EQEmu::skills::SkillBash, dmg, GetMinDamage(), -1, reuse); @@ -1728,8 +1685,6 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) int ReuseTime = 0; float HasteMod = GetHaste() * 0.01f; - int32 dmg = 0; - uint16 skill_to_use = -1; if (skill == -1){ @@ -1784,21 +1739,14 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if(skill_to_use == -1) return; + int dmg = GetBaseSkillDamage(static_cast(skill_to_use), GetTarget()); + if (skill_to_use == EQEmu::skills::SkillBash) { if (ca_target!=this) { DoAnim(animTailRake); - if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotShoulders)) <= 0){ - dmg = -5; - } - else{ - if (!ca_target->CheckHitChance(this, EQEmu::skills::SkillBash, 0)) { - dmg = 0; - } - else{ - dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash, ca_target); - } - } + if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotShoulders)) <= 0) + dmg = DMG_INVULNERABLE; ReuseTime = (BashReuseTime - 1) / HasteMod; @@ -1811,20 +1759,25 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) return; } - if (skill_to_use == EQEmu::skills::SkillFrenzy){ + if (skill_to_use == EQEmu::skills::SkillFrenzy) { CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10); - int AtkRounds = 3; - int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash, GetTarget()); + int AtkRounds = 1; DoAnim(anim2HSlashing); ReuseTime = (FrenzyReuseTime - 1) / HasteMod; - //Live parses show around 55% Triple 35% Double 10% Single, you will always get first hit. - while(AtkRounds > 0) { + // bards can do riposte frenzy for some reason + if (!IsRiposte && GetClass() == BERSERKER) { + int chance = GetLevel() * 2 + GetSkill(EQEmu::skills::SkillFrenzy); + if (zone->random.Roll0(450) < chance) + AtkRounds++; + if (zone->random.Roll0(450) < chance) + AtkRounds++; + } - if (GetTarget() && (AtkRounds == 1 || zone->random.Roll(75))) { - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, max_dmg, 0, max_dmg, ReuseTime, true); - } + while(AtkRounds > 0) { + if (GetTarget()) + DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, dmg, 0, dmg, ReuseTime); AtkRounds--; } @@ -1838,17 +1791,8 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) if(ca_target!=this){ DoAnim(animKick); - if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0){ - dmg = -5; - } - else{ - if (!ca_target->CheckHitChance(this, EQEmu::skills::SkillKick, 0)) { - dmg = 0; - } - else{ - dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick, ca_target); - } - } + if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0) + dmg = DMG_INVULNERABLE; ReuseTime = KickReuseTime-1; @@ -1866,19 +1810,28 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) //Live AA - Technique of Master Wu int wuchance = itembonuses.DoubleSpecialAttack + spellbonuses.DoubleSpecialAttack + aabonuses.DoubleSpecialAttack; if (wuchance) { - if (wuchance >= 100 || zone->random.Roll(wuchance)) { - int MonkSPA[5] = { EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, EQEmu::skills::SkillRoundKick }; - int extra = 1; - if (zone->random.Roll(wuchance / 4)) + const int MonkSPA[5] = {EQEmu::skills::SkillFlyingKick, EQEmu::skills::SkillDragonPunch, + EQEmu::skills::SkillEagleStrike, EQEmu::skills::SkillTigerClaw, + EQEmu::skills::SkillRoundKick}; + int extra = 0; + // always 1/4 of the double attack chance, 25% at rank 5 (100/4) + while (wuchance > 0) { + if (zone->random.Roll(wuchance)) extra++; - // They didn't add a string ID for this. - std::string msg = StringFormat("The spirit of Master Wu fills you! You gain %d additional attack(s).", extra); - // live uses 400 here -- not sure if it's the best for all clients though - SendColoredText(400, msg); - while (extra) { - MonkSpecialAttack(ca_target, MonkSPA[zone->random.Int(0, 4)]); - extra--; - } + else + break; + wuchance /= 4; + } + // They didn't add a string ID for this. + std::string msg = StringFormat( + "The spirit of Master Wu fills you! You gain %d additional attack(s).", extra); + // live uses 400 here -- not sure if it's the best for all clients though + SendColoredText(400, msg); + auto classic = RuleB(Combat, ClassicMasterWu); + while (extra) { + MonkSpecialAttack(GetTarget(), + classic ? MonkSPA[zone->random.Int(0, 4)] : skill_to_use); + extra--; } } } @@ -2033,23 +1986,28 @@ void Mob::InstillDoubt(Mob *who) { } } -int Mob::TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse) { - //Only works on YOUR target. - if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() - && (skillInUse == EQEmu::skills::SkillArchery) && (GetTarget() == defender)) { - +int Mob::TryHeadShot(Mob *defender, EQEmu::skills::SkillType skillInUse) +{ + // Only works on YOUR target. + if (defender && defender->GetBodyType() == BT_Humanoid && !defender->IsClient() && + skillInUse == EQEmu::skills::SkillArchery && GetTarget() == defender) { uint32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1]; - uint8 HeadShot_Level = 0; //Get Highest Headshot Level - HeadShot_Level = aabonuses.HSLevel; - if (HeadShot_Level < spellbonuses.HSLevel) - HeadShot_Level = spellbonuses.HSLevel; - else if (HeadShot_Level < itembonuses.HSLevel) - HeadShot_Level = itembonuses.HSLevel; + uint8 HeadShot_Level = 0; // Get Highest Headshot Level + HeadShot_Level = std::max({aabonuses.HSLevel[0], spellbonuses.HSLevel[0], itembonuses.HSLevel[0]}); - if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){ - float ProcChance = GetSpecialProcChances(EQEmu::inventory::slotRange); - if(zone->random.Roll(ProcChance)) { - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FATAL_BOW_SHOT, GetName()); + if (HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)) { + int chance = GetDEX(); + chance = 100 * chance / (chance + 3500); + if (IsClient()) + chance += CastToClient()->GetHeroicDEX() / 25; + chance *= 10; + int norm = aabonuses.HSLevel[1]; + if (norm > 0) + chance = chance * norm / 100; + chance += aabonuses.HeadShot[0] + spellbonuses.HeadShot[0] + itembonuses.HeadShot[0]; + if (zone->random.Int(1, 1000) <= chance) { + entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FATAL_BOW_SHOT, + GetName()); return HeadShot_Dmg; } } @@ -2058,61 +2016,41 @@ int Mob::TryHeadShot(Mob* defender, EQEmu::skills::SkillType skillInUse) { return 0; } -float Mob::GetSpecialProcChances(uint16 hand) +int Mob::TryAssassinate(Mob *defender, EQEmu::skills::SkillType skillInUse) { - int mydex = GetDEX(); + if (defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() && GetLevel() >= 60 && + (skillInUse == EQEmu::skills::SkillBackstab || skillInUse == EQEmu::skills::SkillThrowing)) { + int chance = GetDEX(); + if (skillInUse == EQEmu::skills::SkillBackstab) { + chance = 100 * chance / (chance + 3500); + if (IsClient()) + chance += CastToClient()->GetHeroicDEX(); + chance *= 10; + int norm = aabonuses.AssassinateLevel[1]; + if (norm > 0) + chance = chance * norm / 100; + } else if (skillInUse == EQEmu::skills::SkillThrowing) { + if (chance > 255) + chance = 260; + else + chance += 5; + } - if (mydex > 255) - mydex = 255; + chance += aabonuses.Assassinate[0] + spellbonuses.Assassinate[0] + itembonuses.Assassinate[0]; - uint16 weapon_speed; - float ProcChance = 0.0f; - float ProcBonus = 0.0f; + uint32 Assassinate_Dmg = + aabonuses.Assassinate[1] + spellbonuses.Assassinate[1] + itembonuses.Assassinate[1]; - weapon_speed = GetWeaponSpeedbyHand(hand); - - if (RuleB(Combat, AdjustSpecialProcPerMinute)) { - ProcChance = (static_cast(weapon_speed) * - RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f); - ProcBonus += static_cast(mydex/35) + static_cast(itembonuses.HeroicDEX / 25); - ProcChance += ProcChance * ProcBonus / 100.0f; - } else { - /*PRE 2014 CHANGE Dev Quote - "Elidroth SOE:Proc chance is a function of your base hardcapped Dexterity / 35 + Heroic Dexterity / 25.” - Kayen: Most reports suggest a ~ 6% chance to Headshot which consistent with above.*/ - - ProcChance = (static_cast(mydex/35) + static_cast(itembonuses.HeroicDEX / 25))/100.0f; - } - - return ProcChance; -} - -int Mob::TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, uint16 ReuseTime) { - - if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient() && GetLevel() >= 60 && - (skillInUse == EQEmu::skills::SkillBackstab || skillInUse == EQEmu::skills::SkillThrowing)) { - - uint32 Assassinate_Dmg = aabonuses.Assassinate[1] + spellbonuses.Assassinate[1] + itembonuses.Assassinate[1]; - - uint8 Assassinate_Level = 0; //Get Highest Headshot Level - Assassinate_Level = aabonuses.AssassinateLevel; - if (Assassinate_Level < spellbonuses.AssassinateLevel) - Assassinate_Level = spellbonuses.AssassinateLevel; - else if (Assassinate_Level < itembonuses.AssassinateLevel) - Assassinate_Level = itembonuses.AssassinateLevel; + uint8 Assassinate_Level = 0; // Get Highest Headshot Level + Assassinate_Level = std::max( + {aabonuses.AssassinateLevel[0], spellbonuses.AssassinateLevel[0], itembonuses.AssassinateLevel[0]}); // revamped AAs require AA line I believe? if (!Assassinate_Level) return 0; - if(Assassinate_Dmg && Assassinate_Level && (defender->GetLevel() <= Assassinate_Level)){ - float ProcChance = 0.0f; - - if (skillInUse == EQEmu::skills::SkillThrowing) - ProcChance = GetSpecialProcChances(EQEmu::inventory::slotRange); - else - ProcChance = GetAssassinateProcChances(ReuseTime); - - if(zone->random.Roll(ProcChance)) { + if (Assassinate_Dmg && Assassinate_Level && (defender->GetLevel() <= Assassinate_Level)) { + if (zone->random.Int(1, 1000) <= chance) { entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); return Assassinate_Dmg; @@ -2123,32 +2061,8 @@ int Mob::TryAssassinate(Mob* defender, EQEmu::skills::SkillType skillInUse, uint return 0; } -float Mob::GetAssassinateProcChances(uint16 ReuseTime) -{ - int mydex = GetDEX(); - - if (mydex > 255) - mydex = 255; - - float ProcChance = 0.0f; - float ProcBonus = 0.0f; - - if (RuleB(Combat, AdjustSpecialProcPerMinute)) { - ProcChance = (static_cast(ReuseTime*1000) * - RuleR(Combat, AvgSpecialProcsPerMinute) / 60000.0f); - ProcBonus += (10 + (static_cast(mydex/10) + static_cast(itembonuses.HeroicDEX /10)))/100.0f; - ProcChance += ProcChance * ProcBonus / 100.0f; - - } else { - /* Kayen: Unable to find data on old proc rate of assassinate, no idea if our formula is real or made up. */ - ProcChance = (10 + (static_cast(mydex/10) + static_cast(itembonuses.HeroicDEX /10)))/100.0f; - - } - - return ProcChance; -} - -void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime) +void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, + int16 focus, bool CanRiposte, int ReuseTime) { if (!CanDoSpecialAttack(other)) return; @@ -2164,17 +2078,19 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: int damage = 0; uint32 hate = 0; - if (hate == 0 && weapon_damage > 1) hate = weapon_damage; + if (hate == 0 && weapon_damage > 1) + hate = weapon_damage; - if(weapon_damage > 0){ - if (focus) //From FcBaseEffects - weapon_damage += weapon_damage*focus/100; + if (weapon_damage > 0) { + if (focus) // From FcBaseEffects + weapon_damage += weapon_damage * focus / 100; - if (skillinuse == EQEmu::skills::SkillBash){ - if(IsClient()){ - EQEmu::ItemInstance *item = CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); - if(item){ - if (item->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { + if (skillinuse == EQEmu::skills::SkillBash) { + if (IsClient()) { + EQEmu::ItemInstance *item = + CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); + if (item) { + if (item->GetItem()->ItemType == EQEmu::item::ItemTypeShield) { hate += item->GetItem()->AC; } const EQEmu::ItemData *itm = item->GetItem(); @@ -2183,37 +2099,30 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: } } - int min_cap = weapon_damage * GetMeleeMinDamageMod_SE(skillinuse) / 100; - auto offense = this->offense(skillinuse); - int min_damage = 0; + DamageHitInfo my_hit; + my_hit.base_damage = weapon_damage; + my_hit.min_damage = 0; + my_hit.damage_done = 0; + + my_hit.skill = skillinuse; + my_hit.offense = offense(my_hit.skill); + my_hit.tohit = GetTotalToHit(my_hit.skill, chance_mod); + // slot range exclude ripe etc ... + my_hit.hand = CanRiposte ? EQEmu::inventory::slotRange : EQEmu::inventory::slotPrimary; + if (IsNPC()) - min_damage = CastToNPC()->GetMinDamage(); - - if (other->AvoidDamage(this, damage, CanRiposte ? EQEmu::inventory::slotRange : EQEmu::inventory::slotPrimary)) { // SlotRange excludes ripo, primary doesn't have any extra behavior - if (damage == -3) { - DoRiposte(other); - if (HasDied()) - return; - } - } else { - if (other->CheckHitChance(this, skillinuse, chance_mod)) { - other->MeleeMitigation(this, damage, weapon_damage, offense, skillinuse); - ApplyDamageTable(damage, offense); - CommonOutgoingHitSuccess(other, damage, min_damage, min_cap, skillinuse); - } else { - damage = 0; - } - } + my_hit.min_damage = CastToNPC()->GetMinDamage(); + DoAttack(other, my_hit); + damage = my_hit.damage_done; + } else { + damage = DMG_INVULNERABLE; } - else - damage = -5; - bool CanSkillProc = true; - if (skillinuse == EQEmu::skills::SkillOffense){ //Hack to allow damage to display. + if (skillinuse == EQEmu::skills::SkillOffense) { // Hack to allow damage to display. skillinuse = EQEmu::skills::SkillTigerClaw; //'strike' your opponent - Arbitrary choice for message. - CanSkillProc = false; //Disable skill procs + CanSkillProc = false; // Disable skill procs } other->AddToHateList(this, hate, 0, false); @@ -2224,6 +2133,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, EQEmu::skills: SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } + other->Damage(this, damage, SPELL_UNKNOWN, skillinuse); if (HasDied()) From c17ac67296e1744363d5660126e2658a03bfeab0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 28 Jan 2017 22:43:07 -0500 Subject: [PATCH 521/693] Tweak #showstats so bots don't skip stuff --- zone/mob.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index bcaa43ccc..63f1d82ab 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1495,14 +1495,15 @@ void Mob::ShowStats(Client* client) spawngroupid = n->respawn2->SpawnGroupID(); client->Message(0, " NPCID: %u SpawnGroupID: %u Grid: %i LootTable: %u FactionID: %i SpellsID: %u ", GetNPCTypeID(),spawngroupid, n->GetGrid(), n->GetLoottableID(), n->GetNPCFactionID(), n->GetNPCSpellsID()); client->Message(0, " Accuracy: %i MerchantID: %i EmoteID: %i Runspeed: %.3f Walkspeed: %.3f", n->GetAccuracyRating(), n->MerchantType, n->GetEmoteID(), static_cast(0.025f * n->GetRunspeed()), static_cast(0.025f * n->GetWalkspeed())); - client->Message(0, " compute_tohit: %i TotalToHit: %i", n->compute_tohit(EQEmu::skills::SkillHandtoHand), n->GetTotalToHit(EQEmu::skills::SkillHandtoHand, 0)); - client->Message(0, " compute_defense: %i TotalDefense: %i", n->compute_defense(), n->GetTotalDefense()); - client->Message(0, " offense: %i mitigation ac: %i", n->offense(EQEmu::skills::SkillHandtoHand), n->GetMitigationAC()); n->QueryLoot(client); } if (IsAIControlled()) { client->Message(0, " AggroRange: %1.0f AssistRange: %1.0f", GetAggroRange(), GetAssistRange()); } + + client->Message(0, " compute_tohit: %i TotalToHit: %i", n->compute_tohit(EQEmu::skills::SkillHandtoHand), n->GetTotalToHit(EQEmu::skills::SkillHandtoHand, 0)); + client->Message(0, " compute_defense: %i TotalDefense: %i", n->compute_defense(), n->GetTotalDefense()); + client->Message(0, " offense: %i mitigation ac: %i", n->offense(EQEmu::skills::SkillHandtoHand), n->GetMitigationAC()); } } From 2db6464d1423fc396dd27fa4f096d772e9ff3325 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 28 Jan 2017 22:46:02 -0500 Subject: [PATCH 522/693] Fix last commit --- zone/mob.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 63f1d82ab..41add6490 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1501,9 +1501,9 @@ void Mob::ShowStats(Client* client) client->Message(0, " AggroRange: %1.0f AssistRange: %1.0f", GetAggroRange(), GetAssistRange()); } - client->Message(0, " compute_tohit: %i TotalToHit: %i", n->compute_tohit(EQEmu::skills::SkillHandtoHand), n->GetTotalToHit(EQEmu::skills::SkillHandtoHand, 0)); - client->Message(0, " compute_defense: %i TotalDefense: %i", n->compute_defense(), n->GetTotalDefense()); - client->Message(0, " offense: %i mitigation ac: %i", n->offense(EQEmu::skills::SkillHandtoHand), n->GetMitigationAC()); + client->Message(0, " compute_tohit: %i TotalToHit: %i", compute_tohit(EQEmu::skills::SkillHandtoHand), GetTotalToHit(EQEmu::skills::SkillHandtoHand, 0)); + client->Message(0, " compute_defense: %i TotalDefense: %i", compute_defense(), GetTotalDefense()); + client->Message(0, " offense: %i mitigation ac: %i", offense(EQEmu::skills::SkillHandtoHand), GetMitigationAC()); } } From 5d61cf5bcf15eaf3d05ad8f23bab416a70feeb25 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 28 Jan 2017 23:21:12 -0500 Subject: [PATCH 523/693] Bots are dumb --- zone/bot.cpp | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 237c1144b..0ce204d06 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -82,7 +82,6 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm // Do this once and only in this constructor GenerateAppearance(); GenerateBaseStats(); - GenerateArmorClass(); // Calculate HitPoints Last As It Uses Base Stats cur_hp = GenerateBaseHitPoints(); cur_mana = GenerateBaseManaPoints(); @@ -1140,42 +1139,6 @@ int32 Bot::acmod() { return 0; } -void Bot::GenerateArmorClass() { - /// new formula - int avoidance = 0; - avoidance = (acmod() + ((GetSkill(EQEmu::skills::SkillDefense) * 16) / 9)); - if(avoidance < 0) - avoidance = 0; - - int mitigation = 0; - if(GetClass() == WIZARD || GetClass() == MAGICIAN || GetClass() == NECROMANCER || GetClass() == ENCHANTER) { - mitigation = (GetSkill(EQEmu::skills::SkillDefense) / 4 + (itembonuses.AC + 1)); - mitigation -= 4; - } else { - mitigation = (GetSkill(EQEmu::skills::SkillDefense) / 3 + ((itembonuses.AC * 4) / 3)); - if(GetClass() == MONK) - mitigation += (GetLevel() * 13 / 10); //the 13/10 might be wrong, but it is close... - } - int displayed = 0; - displayed += (((avoidance + mitigation) * 1000) / 847); //natural AC - - //Iksar AC, untested - if(GetRace() == IKSAR) { - displayed += 12; - int iksarlevel = GetLevel(); - iksarlevel -= 10; - if(iksarlevel > 25) - iksarlevel = 25; - - if(iksarlevel > 0) - displayed += (iksarlevel * 12 / 10); - } - - //spell AC bonuses are added directly to natural total - displayed += spellbonuses.AC; - this->AC = displayed; -} - uint16 Bot::GetPrimarySkillValue() { EQEmu::skills::SkillType skill = EQEmu::skills::HIGHEST_SKILL; //because nullptr == 0, which is 1H Slashing, & we want it to return 0 from GetSkill bool equiped = m_inv.GetItem(EQEmu::inventory::slotPrimary); @@ -6157,7 +6120,7 @@ void Bot::CalcBonuses() { CalcPR(); CalcCR(); CalcCorrup(); - GenerateArmorClass(); + CalcAC(); CalcMaxHP(); CalcMaxMana(); CalcMaxEndurance(); From 984a009fbb1af0c64d4c28294e65389db9d85e8b Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 29 Jan 2017 04:35:03 -0500 Subject: [PATCH 524/693] Temp fix for bot armor color issue - may break armor dying (not tested) --- zone/mob.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/zone/mob.cpp b/zone/mob.cpp index 41add6490..4f8b51ee9 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2780,7 +2780,22 @@ void Mob::SendWearChange(uint8 material_slot, Client *one_client) wc->material = GetEquipmentMaterial(material_slot); wc->elite_material = IsEliteMaterialItem(material_slot); wc->hero_forge_model = GetHerosForgeModel(material_slot); + +#ifdef BOTS + if (IsBot()) { + auto item_inst = CastToBot()->GetBotItem(EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot)); + if (item_inst) + wc->color.Color = item_inst->GetColor(); + else + wc->color.Color = 0; + } + else { + wc->color.Color = GetEquipmentColor(material_slot); + } +#else wc->color.Color = GetEquipmentColor(material_slot); +#endif + wc->wear_slot_id = material_slot; if (!one_client) From dc308e2ecb2e5fa92368ca34bf9fc2cdbc77d7f6 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 30 Jan 2017 03:08:00 -0500 Subject: [PATCH 525/693] Fix for null columns in `books`.`language` crash --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + utils/sql/git/required/2017_01_10_book_languages.sql | 2 +- utils/sql/git/required/2017_01_30_book_languages_fix.sql | 4 ++++ 4 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 utils/sql/git/required/2017_01_30_book_languages_fix.sql diff --git a/common/version.h b/common/version.h index 2d5f1d75f..f7f2ad05d 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9102 +#define CURRENT_BINARY_DATABASE_VERSION 9103 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 816a35a7c..2c27d858d 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -356,6 +356,7 @@ 9100|2016_08_27_object_display_name.sql|SHOW COLUMNS FROM `object` LIKE 'display_name'|empty| 9101|2016_12_01_pcnpc_only.sql|SHOW COLUMNS FROM `spells_new` LIKE 'pcnpc_only_flag'|empty| 9102|2017_01_10_book_languages.sql|SHOW COLUMNS FROM `books` LIKE 'language'|empty| +9103|2017_01_30_book_languages_fix.sql|SELECT `language` from `books` WHERE `language` IS NULL|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2017_01_10_book_languages.sql b/utils/sql/git/required/2017_01_10_book_languages.sql index aa767cd03..1f51325a9 100644 --- a/utils/sql/git/required/2017_01_10_book_languages.sql +++ b/utils/sql/git/required/2017_01_10_book_languages.sql @@ -1,4 +1,4 @@ -alter table books add language int default 0; +alter table books add language int not null default 0; drop table if exists reading_is_fundamental; diff --git a/utils/sql/git/required/2017_01_30_book_languages_fix.sql b/utils/sql/git/required/2017_01_30_book_languages_fix.sql new file mode 100644 index 000000000..3d913b19c --- /dev/null +++ b/utils/sql/git/required/2017_01_30_book_languages_fix.sql @@ -0,0 +1,4 @@ +UPDATE `books` SET `language` = '0' WHERE `language` IS NULL; + +ALTER TABLE `books` MODIFY COLUMN `language` INT NOT NULL DEFAULT '0'; + From da9792160dc07e84d6dedca65b8db4f5f6a1c865 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 30 Jan 2017 17:38:17 -0500 Subject: [PATCH 526/693] Added Mob::HasTargetReflection() --- zone/bot.cpp | 4 ++-- zone/mob.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 0ce204d06..174c4568e 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2273,7 +2273,7 @@ void Bot::AI_Process() { if(AI_movement_timer->Check()) { if (!IsMoving()) { if (GetClass() == ROGUE) { - if ((GetTarget()->GetTarget() == this) && !GetTarget()->IsFeared() && !GetTarget()->IsStunned()) { + if (HasTargetReflection() && !GetTarget()->IsFeared() && !GetTarget()->IsStunned()) { // Hate redux actions if (evade_timer.Check(false)) { // Attempt to evade @@ -2299,7 +2299,7 @@ void Bot::AI_Process() { float newZ = 0; FaceTarget(GetTarget()); if (PlotPositionAroundTarget(this, newX, newY, newZ)) { - Bot::BotGroupSay(this, "Backing off of %s", GetTarget()->GetCleanName()); + Emote("steps back from %s", GetTarget()->GetCleanName()); CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); return; } diff --git a/zone/mob.h b/zone/mob.h index d6fd610cd..dfa0cb16f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -420,6 +420,7 @@ public: strn0cpy(name, GetName(), 64); return; }; inline Mob* GetTarget() const { return target; } virtual void SetTarget(Mob* mob); + inline bool HasTargetReflection() const { return (target && target->target == this); } virtual inline float GetHPRatio() const { return max_hp == 0 ? 0 : ((float)cur_hp/max_hp*100); } virtual inline int GetIntHPRatio() const { return max_hp == 0 ? 0 : static_cast(cur_hp * 100 / max_hp); } inline int32 GetAC() const { return AC; } From d8519bc270ad932047679fa1c2c86870ff29a176 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 31 Jan 2017 17:25:05 -0500 Subject: [PATCH 527/693] Weapons allow NPCs to facestab --- zone/loottables.cpp | 4 +++- zone/mob.cpp | 1 + zone/mob.h | 3 +++ zone/special_attacks.cpp | 4 ++-- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 03f1590b1..7f8e371bd 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -332,8 +332,10 @@ void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 ch CastToMob()->AddProcToWeapon(item2->Proc.Effect, true); eslot = EQEmu::textures::weaponPrimary; - if (item2->Damage > 0) + if (item2->Damage > 0) { SendAddPlayerState(PlayerState::PrimaryWeaponEquipped); + SetFacestab(true); + } if (item2->IsType2HWeapon()) SetTwoHanderEquipped(true); } diff --git a/zone/mob.cpp b/zone/mob.cpp index 4f8b51ee9..506c8b44e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -213,6 +213,7 @@ Mob::Mob(const char* in_name, has_shieldequiped = false; has_twohandbluntequiped = false; has_twohanderequipped = false; + can_facestab = false; has_numhits = false; has_MGB = false; has_ProjectIllusion = false; diff --git a/zone/mob.h b/zone/mob.h index dfa0cb16f..52ad3937b 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -373,6 +373,8 @@ public: inline void SetTwoHandBluntEquiped(bool val) { has_twohandbluntequiped = val; } bool HasTwoHanderEquipped() { return has_twohanderequipped; } void SetTwoHanderEquipped(bool val) { has_twohanderequipped = val; } + bool CanFacestab() { return can_facestab; } + void SetFacestab(bool val) { can_facestab = val; } virtual uint16 GetSkill(EQEmu::skills::SkillType skill_num) const { return 0; } virtual uint32 GetEquipment(uint8 material_slot) const { return(0); } virtual int32 GetEquipmentMaterial(uint8 material_slot) const; @@ -1298,6 +1300,7 @@ protected: bool has_shieldequiped; bool has_twohandbluntequiped; bool has_twohanderequipped; + bool can_facestab; bool has_numhits; bool has_MGB; bool has_ProjectIllusion; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 7f6ec112d..81c888915 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -528,8 +528,8 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) { bCanFrontalBS = true; } - if (bIsBehind || bCanFrontalBS){ // Player is behind other OR can do Frontal Backstab - if (bCanFrontalBS) + if (bIsBehind || bCanFrontalBS || (IsNPC() && CanFacestab())) { // Player is behind other OR can do Frontal Backstab + if (bCanFrontalBS && IsClient()) // I don't think there is any message ... CastToClient()->Message(0,"Your fierce attack is executed with such grace, your target did not see it coming!"); RogueBackstab(other,false,ReuseTime); From b0ad9524bc80c4de68828bca82d17cc43eb40f4b Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 31 Jan 2017 20:17:54 -0500 Subject: [PATCH 528/693] Bot movement behavior change..still in-work --- changelog.txt | 3 ++ zone/bot.cpp | 119 +++++++++++++++++++++++++++++++++++++------------- zone/bot.h | 1 + zone/mob.h | 2 +- 4 files changed, 93 insertions(+), 32 deletions(-) diff --git a/changelog.txt b/changelog.txt index 7a9a0fa65..390c45cd9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 01/31/2017 == +Uleat: Modifed bot movement behavior in an attempt to 'normalize' it. This is a hack fix and will be revisited at some point. (Probably just need a follow function rather than use movement, when the leader of the follow chain is moving.) + == 01/26/2017 == Uleat: Change rogue bot behavior to eliminate twirling combat. They will only get behind the mob if they are not the mob's target or if the mob is feared or fleeing. This may lower rogue bot dps a small fraction..but, is more in-line with realistic game mechanics. diff --git a/zone/bot.cpp b/zone/bot.cpp index 174c4568e..3759335a4 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2305,10 +2305,6 @@ void Bot::AI_Process() { } } } - - // Could add a bot accessor like.. - // bool NeedsHateRedux() { return (GetClass() == Rogue && evade_timer.check(false)); } - or something like this - // ..then add hate redux spells to caster combat repertoires } else if (!BehindMob(GetTarget(), GetX(), GetY())) { // Move the rogue to behind the mob @@ -2472,42 +2468,67 @@ void Bot::AI_Process() { BotMeditate(true); } } else { - SetTarget(0); + SetTarget(nullptr); if (m_PlayerState & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); - if(!IsMoving() && AI_think_timer->Check() && !spellend_timer.Enabled()) { - if(GetBotStance() != BotStancePassive) { - if(!AI_IdleCastCheck() && !IsCasting()) - BotMeditate(true); - } - else - BotMeditate(true); - } + Mob* follow = entity_list.GetMob(GetFollowID()); + if (!follow) + return; - if(AI_movement_timer->Check()) { - if(GetFollowID()) { - Mob* follow = entity_list.GetMob(GetFollowID()); - if(follow) { - float dist = DistanceSquared(m_Position, follow->GetPosition()); - int speed = follow->GetRunspeed(); - if(dist < GetFollowDistance() + 1000) - speed = follow->GetWalkspeed(); + float cur_dist = DistanceSquared(m_Position, follow->GetPosition()); - if(dist > GetFollowDistance()) { - CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); - if(rest_timer.Enabled()) - rest_timer.Disable(); - return; - } else { - if(moved) { - moved = false; - SetCurrentSpeed(0); - } + if (!IsMoving() && cur_dist <= GetFollowDistance()) { + if (AI_think_timer->Check()) { + if (!spellend_timer.Enabled()) { + if (GetBotStance() != BotStancePassive) { + if (!AI_IdleCastCheck() && !IsCasting() && GetClass() != BARD) + BotMeditate(true); + } + else { + if (GetClass() != BARD) + BotMeditate(true); } } } } + else if(AI_movement_timer->Check()) { + int speed = GetRunspeed(); + if (cur_dist < GetFollowDistance() + 1000) { + speed = GetWalkspeed(); + } + else if (cur_dist >= GetFollowDistance() + 8000) { + auto leader = follow; + while (leader->GetFollowID()) { + leader = entity_list.GetMob(leader->GetFollowID()); + if (!leader || leader == this) + break; + } + if (leader && leader != this && leader->GetRunspeed() > speed) + speed = leader->GetRunspeed(); + speed = (float)speed * 1.8f; // special bot sprint mod + } + + // this needs work.. + // could probably eliminate the sprint mod with the correct logic + if (cur_dist > GetFollowDistance()) { + CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); + if (rest_timer.Enabled()) + rest_timer.Disable(); + return; + } + else { + if (moved) { + moved = false; + SetCurrentSpeed(0); + } + } + } + else if (IsMoving()) { + if (GetBotStance() != BotStancePassive && GetClass() == BARD && !spellend_timer.Enabled() && AI_think_timer->Check()) { + AI_IdleCastCheck(); + } + } } } @@ -7989,6 +8010,42 @@ bool Bot::GetNeedsCured(Mob *tar) { return needCured; } +bool Bot::GetNeedsHateRedux(Mob *tar) { + // This really should be a scalar function based in class Mob that returns 'this' state..but, is inline with current Bot coding... + // TODO: Good starting point..but, can be refined.. + // TODO: Still awaiting bot spell rework.. + if (!tar || !tar->HasTargetReflection()) + return false; + + if (tar->IsClient()) { + switch (tar->GetClass()) { + // TODO: figure out affectable classes.. + // Might need flag to allow player to determine redux req... + default: + return false; + } + } + else if (tar->IsBot()) { + switch (tar->GetClass()) { + case ROGUE: + if (tar->CastToBot()->evade_timer.Check(false)) + return false; + case CLERIC: + case DRUID: + case SHAMAN: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + default: + return false; + } + } + + return false; +} + bool Bot::HasOrMayGetAggro() { bool mayGetAggro = false; if(GetTarget() && GetTarget()->GetHateTop()) { diff --git a/zone/bot.h b/zone/bot.h index 5431df341..bda693094 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -293,6 +293,7 @@ public: bool UseDiscipline(uint32 spell_id, uint32 target); uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets); bool GetNeedsCured(Mob *tar); + bool GetNeedsHateRedux(Mob *tar); bool HasOrMayGetAggro(); void SetDefaultBotStance(); void CalcChanceToCast(); diff --git a/zone/mob.h b/zone/mob.h index 52ad3937b..fe76f949d 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -422,7 +422,7 @@ public: strn0cpy(name, GetName(), 64); return; }; inline Mob* GetTarget() const { return target; } virtual void SetTarget(Mob* mob); - inline bool HasTargetReflection() const { return (target && target->target == this); } + inline bool HasTargetReflection() const { return (target && target != this && target->target == this); } virtual inline float GetHPRatio() const { return max_hp == 0 ? 0 : ((float)cur_hp/max_hp*100); } virtual inline int GetIntHPRatio() const { return max_hp == 0 ? 0 : static_cast(cur_hp * 100 / max_hp); } inline int32 GetAC() const { return AC; } From 1999982e6a43a526c6cff15873debe6ad1ab6e1e Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 2 Feb 2017 19:10:10 -0500 Subject: [PATCH 529/693] Fix for bot load buffs instrument mod. More tweaks to bot movement hack --- zone/bot.cpp | 29 ++++++++++++++++------------- zone/bot_database.cpp | 4 +++- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 3759335a4..d5f6ff814 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2299,7 +2299,6 @@ void Bot::AI_Process() { float newZ = 0; FaceTarget(GetTarget()); if (PlotPositionAroundTarget(this, newX, newY, newZ)) { - Emote("steps back from %s", GetTarget()->GetCleanName()); CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); return; } @@ -2493,24 +2492,28 @@ void Bot::AI_Process() { } } else if(AI_movement_timer->Check()) { + // something is wrong with bot movement spell bonuses - based on logging.. + // ..this code won't need to be so complex once fixed... int speed = GetRunspeed(); - if (cur_dist < GetFollowDistance() + 1000) { + if (cur_dist < GetFollowDistance() + 2000) { speed = GetWalkspeed(); } - else if (cur_dist >= GetFollowDistance() + 8000) { - auto leader = follow; - while (leader->GetFollowID()) { - leader = entity_list.GetMob(leader->GetFollowID()); - if (!leader || leader == this) - break; + else if (cur_dist >= GetFollowDistance() + 10000) { // 100 + if (cur_dist >= 22500) { // 150 + auto leader = follow; + while (leader->GetFollowID()) { + leader = entity_list.GetMob(leader->GetFollowID()); + if (!leader || leader == this) + break; + if (leader->GetRunspeed() > speed) + speed = leader->GetRunspeed(); + if (leader->IsClient()) + break; + } } - if (leader && leader != this && leader->GetRunspeed() > speed) - speed = leader->GetRunspeed(); - speed = (float)speed * 1.8f; // special bot sprint mod + speed = (float)speed * (1.0f + ((float)speed * 0.03125f)); // 1/32 - special bot sprint mod } - // this needs work.. - // could probably eliminate the sprint mod with the correct logic if (cur_dist > GetFollowDistance()) { CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); if (rest_timer.Enabled()) diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 04ce5b281..0f7553ada 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -617,7 +617,8 @@ bool BotDatabase::LoadBuffs(Bot* bot_inst) " `caston_x`," " `caston_y`," " `caston_z`," - " `extra_di_chance`" + " `extra_di_chance`," + " `instrument_mod`" " FROM `bot_buffs`" " WHERE `bot_id` = '%u'", bot_inst->GetBotID() @@ -657,6 +658,7 @@ bool BotDatabase::LoadBuffs(Bot* bot_inst) bot_buffs[buff_count].caston_y = atoi(row[14]); bot_buffs[buff_count].caston_z = atoi(row[15]); bot_buffs[buff_count].ExtraDIChance = atoi(row[16]); + bot_buffs[buff_count].instrument_mod = atoi(row[17]); bot_buffs[buff_count].casterid = 0; ++buff_count; } From b1f14e1e2954b61d3c3b79ac93c6753cf74179ba Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 4 Feb 2017 05:55:10 -0500 Subject: [PATCH 530/693] Added dev script for function to retrieve effect id labels for spells from queries [skip ci] --- utils/scripts/spell_effect_token_function.sql | 494 ++++++++++++++++++ 1 file changed, 494 insertions(+) create mode 100644 utils/scripts/spell_effect_token_function.sql diff --git a/utils/scripts/spell_effect_token_function.sql b/utils/scripts/spell_effect_token_function.sql new file mode 100644 index 000000000..ee5f9afc8 --- /dev/null +++ b/utils/scripts/spell_effect_token_function.sql @@ -0,0 +1,494 @@ +DELIMITER $$ + +DROP FUNCTION IF EXISTS `GetSpellEffectToken`; + +-- This function converts a numeric spell effect id to a string label based on server code designations +-- +-- example: +-- SELECT `id`, `name`, GetSpellEffectToken(`effectid1`), GetSpellEffectToken(`effectid2`) FROM `spells_new` WHERE `id` IN ('1011', '1602'); +CREATE FUNCTION `GetSpellEffectToken` (`effect_id` INT(11)) RETURNS VARCHAR(64) +BEGIN + DECLARE `token` VARCHAR(64) DEFAULT ''; + + CASE `effect_id` + WHEN '0' THEN SET `token` = 'SE_CurrentHP'; + WHEN '1' THEN SET `token` = 'SE_ArmorClass'; + WHEN '2' THEN SET `token` = 'SE_ATK'; + WHEN '3' THEN SET `token` = 'SE_MovementSpeed'; + WHEN '4' THEN SET `token` = 'SE_STR'; + WHEN '5' THEN SET `token` = 'SE_DEX'; + WHEN '6' THEN SET `token` = 'SE_AGI'; + WHEN '7' THEN SET `token` = 'SE_STA'; + WHEN '8' THEN SET `token` = 'SE_INT'; + WHEN '9' THEN SET `token` = 'SE_WIS'; + WHEN '10' THEN SET `token` = 'SE_CHA'; + WHEN '11' THEN SET `token` = 'SE_AttackSpeed'; + WHEN '12' THEN SET `token` = 'SE_Invisibility'; + WHEN '13' THEN SET `token` = 'SE_SeeInvis'; + WHEN '14' THEN SET `token` = 'SE_WaterBreathing'; + WHEN '15' THEN SET `token` = 'SE_CurrentMana'; + WHEN '16' THEN SET `token` = 'SE_NPCFrenzy'; + WHEN '17' THEN SET `token` = 'SE_NPCAwareness'; + WHEN '18' THEN SET `token` = 'SE_Lull'; + WHEN '19' THEN SET `token` = 'SE_AddFaction'; + WHEN '20' THEN SET `token` = 'SE_Blind'; + WHEN '21' THEN SET `token` = 'SE_Stun'; + WHEN '22' THEN SET `token` = 'SE_Charm'; + WHEN '23' THEN SET `token` = 'SE_Fear'; + WHEN '24' THEN SET `token` = 'SE_Stamina'; + WHEN '25' THEN SET `token` = 'SE_BindAffinity'; + WHEN '26' THEN SET `token` = 'SE_Gate'; + WHEN '27' THEN SET `token` = 'SE_CancelMagic'; + WHEN '28' THEN SET `token` = 'SE_InvisVsUndead'; + WHEN '29' THEN SET `token` = 'SE_InvisVsAnimals'; + WHEN '30' THEN SET `token` = 'SE_ChangeFrenzyRad'; + WHEN '31' THEN SET `token` = 'SE_Mez'; + WHEN '32' THEN SET `token` = 'SE_SummonItem'; + WHEN '33' THEN SET `token` = 'SE_SummonPet'; + WHEN '34' THEN SET `token` = 'SE_Confuse'; + WHEN '35' THEN SET `token` = 'SE_DiseaseCounter'; + WHEN '36' THEN SET `token` = 'SE_PoisonCounter'; + WHEN '37' THEN SET `token` = 'SE_DetectHostile'; + WHEN '38' THEN SET `token` = 'SE_DetectMagic'; + WHEN '39' THEN SET `token` = 'SE_DetectPoison'; + WHEN '40' THEN SET `token` = 'SE_DivineAura'; + WHEN '41' THEN SET `token` = 'SE_Destroy'; + WHEN '42' THEN SET `token` = 'SE_ShadowStep'; + WHEN '43' THEN SET `token` = 'SE_Berserk'; + WHEN '44' THEN SET `token` = 'SE_Lycanthropy'; + WHEN '45' THEN SET `token` = 'SE_Vampirism'; + WHEN '46' THEN SET `token` = 'SE_ResistFire'; + WHEN '47' THEN SET `token` = 'SE_ResistCold'; + WHEN '48' THEN SET `token` = 'SE_ResistPoison'; + WHEN '49' THEN SET `token` = 'SE_ResistDisease'; + WHEN '50' THEN SET `token` = 'SE_ResistMagic'; + WHEN '51' THEN SET `token` = 'SE_DetectTraps'; + WHEN '52' THEN SET `token` = 'SE_SenseDead'; + WHEN '53' THEN SET `token` = 'SE_SenseSummoned'; + WHEN '54' THEN SET `token` = 'SE_SenseAnimals'; + WHEN '55' THEN SET `token` = 'SE_Rune'; + WHEN '56' THEN SET `token` = 'SE_TrueNorth'; + WHEN '57' THEN SET `token` = 'SE_Levitate'; + WHEN '58' THEN SET `token` = 'SE_Illusion'; + WHEN '59' THEN SET `token` = 'SE_DamageShield'; + WHEN '60' THEN SET `token` = 'SE_TransferItem'; + WHEN '61' THEN SET `token` = 'SE_Identify'; + WHEN '62' THEN SET `token` = 'SE_ItemID'; + WHEN '63' THEN SET `token` = 'SE_WipeHateList'; + WHEN '64' THEN SET `token` = 'SE_SpinTarget'; + WHEN '65' THEN SET `token` = 'SE_InfraVision'; + WHEN '66' THEN SET `token` = 'SE_UltraVision'; + WHEN '67' THEN SET `token` = 'SE_EyeOfZomm'; + WHEN '68' THEN SET `token` = 'SE_ReclaimPet'; + WHEN '69' THEN SET `token` = 'SE_TotalHP'; + WHEN '70' THEN SET `token` = 'SE_CorpseBomb'; + WHEN '71' THEN SET `token` = 'SE_NecPet'; + WHEN '72' THEN SET `token` = 'SE_PreserveCorpse'; + WHEN '73' THEN SET `token` = 'SE_BindSight'; + WHEN '74' THEN SET `token` = 'SE_FeignDeath'; + WHEN '75' THEN SET `token` = 'SE_VoiceGraft'; + WHEN '76' THEN SET `token` = 'SE_Sentinel'; + WHEN '77' THEN SET `token` = 'SE_LocateCorpse'; + WHEN '78' THEN SET `token` = 'SE_AbsorbMagicAtt'; + WHEN '79' THEN SET `token` = 'SE_CurrentHPOnce'; + WHEN '80' THEN SET `token` = 'SE_EnchantLight'; + WHEN '81' THEN SET `token` = 'SE_Revive'; + WHEN '82' THEN SET `token` = 'SE_SummonPC'; + WHEN '83' THEN SET `token` = 'SE_Teleport'; + WHEN '84' THEN SET `token` = 'SE_TossUp'; + WHEN '85' THEN SET `token` = 'SE_WeaponProc'; + WHEN '86' THEN SET `token` = 'SE_Harmony'; + WHEN '87' THEN SET `token` = 'SE_MagnifyVision'; + WHEN '88' THEN SET `token` = 'SE_Succor'; + WHEN '89' THEN SET `token` = 'SE_ModelSize'; + WHEN '90' THEN SET `token` = 'SE_Cloak'; + WHEN '91' THEN SET `token` = 'SE_SummonCorpse'; + WHEN '92' THEN SET `token` = 'SE_InstantHate'; + WHEN '93' THEN SET `token` = 'SE_StopRain'; + WHEN '94' THEN SET `token` = 'SE_NegateIfCombat'; + WHEN '95' THEN SET `token` = 'SE_Sacrifice'; + WHEN '96' THEN SET `token` = 'SE_Silence'; + WHEN '97' THEN SET `token` = 'SE_ManaPool'; + WHEN '98' THEN SET `token` = 'SE_AttackSpeed2'; + WHEN '99' THEN SET `token` = 'SE_Root'; + WHEN '100' THEN SET `token` = 'SE_HealOverTime'; + WHEN '101' THEN SET `token` = 'SE_CompleteHeal'; + WHEN '102' THEN SET `token` = 'SE_Fearless'; + WHEN '103' THEN SET `token` = 'SE_CallPet'; + WHEN '104' THEN SET `token` = 'SE_Translocate'; + WHEN '105' THEN SET `token` = 'SE_AntiGate'; + WHEN '106' THEN SET `token` = 'SE_SummonBSTPet'; + WHEN '107' THEN SET `token` = 'SE_AlterNPCLevel'; + WHEN '108' THEN SET `token` = 'SE_Familiar'; + WHEN '109' THEN SET `token` = 'SE_SummonItemIntoBag'; + WHEN '110' THEN SET `token` = 'SE_IncreaseArchery'; + WHEN '111' THEN SET `token` = 'SE_ResistAll'; + WHEN '112' THEN SET `token` = 'SE_CastingLevel'; + WHEN '113' THEN SET `token` = 'SE_SummonHorse'; + WHEN '114' THEN SET `token` = 'SE_ChangeAggro'; + WHEN '115' THEN SET `token` = 'SE_Hunger'; + WHEN '116' THEN SET `token` = 'SE_CurseCounter'; + WHEN '117' THEN SET `token` = 'SE_MagicWeapon'; + WHEN '118' THEN SET `token` = 'SE_Amplification'; + WHEN '119' THEN SET `token` = 'SE_AttackSpeed3'; + WHEN '120' THEN SET `token` = 'SE_HealRate'; + WHEN '121' THEN SET `token` = 'SE_ReverseDS'; + WHEN '122' THEN SET `token` = 'SE_ReduceSkill'; + WHEN '123' THEN SET `token` = 'SE_Screech'; + WHEN '124' THEN SET `token` = 'SE_ImprovedDamage'; + WHEN '125' THEN SET `token` = 'SE_ImprovedHeal'; + WHEN '126' THEN SET `token` = 'SE_SpellResistReduction'; + WHEN '127' THEN SET `token` = 'SE_IncreaseSpellHaste'; + WHEN '128' THEN SET `token` = 'SE_IncreaseSpellDuration'; + WHEN '129' THEN SET `token` = 'SE_IncreaseRange'; + WHEN '130' THEN SET `token` = 'SE_SpellHateMod'; + WHEN '131' THEN SET `token` = 'SE_ReduceReagentCost'; + WHEN '132' THEN SET `token` = 'SE_ReduceManaCost'; + WHEN '133' THEN SET `token` = 'SE_FcStunTimeMod'; + WHEN '134' THEN SET `token` = 'SE_LimitMaxLevel'; + WHEN '135' THEN SET `token` = 'SE_LimitResist'; + WHEN '136' THEN SET `token` = 'SE_LimitTarget'; + WHEN '137' THEN SET `token` = 'SE_LimitEffect'; + WHEN '138' THEN SET `token` = 'SE_LimitSpellType'; + WHEN '139' THEN SET `token` = 'SE_LimitSpell'; + WHEN '140' THEN SET `token` = 'SE_LimitMinDur'; + WHEN '141' THEN SET `token` = 'SE_LimitInstant'; + WHEN '142' THEN SET `token` = 'SE_LimitMinLevel'; + WHEN '143' THEN SET `token` = 'SE_LimitCastTimeMin'; + WHEN '144' THEN SET `token` = 'SE_LimitCastTimeMax'; + WHEN '145' THEN SET `token` = 'SE_Teleport2'; + WHEN '146' THEN SET `token` = 'SE_ElectricityResist'; + WHEN '147' THEN SET `token` = 'SE_PercentalHeal'; + WHEN '148' THEN SET `token` = 'SE_StackingCommand_Block'; + WHEN '149' THEN SET `token` = 'SE_StackingCommand_Overwrite'; + WHEN '150' THEN SET `token` = 'SE_DeathSave'; + WHEN '151' THEN SET `token` = 'SE_SuspendPet'; + WHEN '152' THEN SET `token` = 'SE_TemporaryPets'; + WHEN '153' THEN SET `token` = 'SE_BalanceHP'; + WHEN '154' THEN SET `token` = 'SE_DispelDetrimental'; + WHEN '155' THEN SET `token` = 'SE_SpellCritDmgIncrease'; + WHEN '156' THEN SET `token` = 'SE_IllusionCopy'; + WHEN '157' THEN SET `token` = 'SE_SpellDamageShield'; + WHEN '158' THEN SET `token` = 'SE_Reflect'; + WHEN '159' THEN SET `token` = 'SE_AllStats'; + WHEN '160' THEN SET `token` = 'SE_MakeDrunk'; + WHEN '161' THEN SET `token` = 'SE_MitigateSpellDamage'; + WHEN '162' THEN SET `token` = 'SE_MitigateMeleeDamage'; + WHEN '163' THEN SET `token` = 'SE_NegateAttacks'; + WHEN '164' THEN SET `token` = 'SE_AppraiseLDonChest'; + WHEN '165' THEN SET `token` = 'SE_DisarmLDoNTrap'; + WHEN '166' THEN SET `token` = 'SE_UnlockLDoNChest'; + WHEN '167' THEN SET `token` = 'SE_PetPowerIncrease'; + WHEN '168' THEN SET `token` = 'SE_MeleeMitigation'; + WHEN '169' THEN SET `token` = 'SE_CriticalHitChance'; + WHEN '170' THEN SET `token` = 'SE_SpellCritChance'; + WHEN '171' THEN SET `token` = 'SE_CrippBlowChance'; + WHEN '172' THEN SET `token` = 'SE_AvoidMeleeChance'; + WHEN '173' THEN SET `token` = 'SE_RiposteChance'; + WHEN '174' THEN SET `token` = 'SE_DodgeChance'; + WHEN '175' THEN SET `token` = 'SE_ParryChance'; + WHEN '176' THEN SET `token` = 'SE_DualWieldChance'; + WHEN '177' THEN SET `token` = 'SE_DoubleAttackChance'; + WHEN '178' THEN SET `token` = 'SE_MeleeLifetap'; + WHEN '179' THEN SET `token` = 'SE_AllInstrumentMod'; + WHEN '180' THEN SET `token` = 'SE_ResistSpellChance'; + WHEN '181' THEN SET `token` = 'SE_ResistFearChance'; + WHEN '182' THEN SET `token` = 'SE_HundredHands'; + WHEN '183' THEN SET `token` = 'SE_MeleeSkillCheck'; + WHEN '184' THEN SET `token` = 'SE_HitChance'; + WHEN '185' THEN SET `token` = 'SE_DamageModifier'; + WHEN '186' THEN SET `token` = 'SE_MinDamageModifier'; + WHEN '187' THEN SET `token` = 'SE_BalanceMana'; + WHEN '188' THEN SET `token` = 'SE_IncreaseBlockChance'; + WHEN '189' THEN SET `token` = 'SE_CurrentEndurance'; + WHEN '190' THEN SET `token` = 'SE_EndurancePool'; + WHEN '191' THEN SET `token` = 'SE_Amnesia'; + WHEN '192' THEN SET `token` = 'SE_Hate'; + WHEN '193' THEN SET `token` = 'SE_SkillAttack'; + WHEN '194' THEN SET `token` = 'SE_FadingMemories'; + WHEN '195' THEN SET `token` = 'SE_StunResist'; + WHEN '196' THEN SET `token` = 'SE_StrikeThrough'; + WHEN '197' THEN SET `token` = 'SE_SkillDamageTaken'; + WHEN '198' THEN SET `token` = 'SE_CurrentEnduranceOnce'; + WHEN '199' THEN SET `token` = 'SE_Taunt'; + WHEN '200' THEN SET `token` = 'SE_ProcChance'; + WHEN '201' THEN SET `token` = 'SE_RangedProc'; + WHEN '202' THEN SET `token` = 'SE_IllusionOther'; + WHEN '203' THEN SET `token` = 'SE_MassGroupBuff'; + WHEN '204' THEN SET `token` = 'SE_GroupFearImmunity'; + WHEN '205' THEN SET `token` = 'SE_Rampage'; + WHEN '206' THEN SET `token` = 'SE_AETaunt'; + WHEN '207' THEN SET `token` = 'SE_FleshToBone'; + WHEN '208' THEN SET `token` = 'SE_PurgePoison'; + WHEN '209' THEN SET `token` = 'SE_DispelBeneficial'; + WHEN '210' THEN SET `token` = 'SE_PetShield'; + WHEN '211' THEN SET `token` = 'SE_AEMelee'; + WHEN '212' THEN SET `token` = 'SE_FrenziedDevastation'; + WHEN '213' THEN SET `token` = 'SE_PetMaxHP'; + WHEN '214' THEN SET `token` = 'SE_MaxHPChange'; + WHEN '215' THEN SET `token` = 'SE_PetAvoidance'; + WHEN '216' THEN SET `token` = 'SE_Accuracy'; + WHEN '217' THEN SET `token` = 'SE_HeadShot'; + WHEN '218' THEN SET `token` = 'SE_PetCriticalHit'; + WHEN '219' THEN SET `token` = 'SE_SlayUndead'; + WHEN '220' THEN SET `token` = 'SE_SkillDamageAmount'; + WHEN '221' THEN SET `token` = 'SE_Packrat'; + WHEN '222' THEN SET `token` = 'SE_BlockBehind'; + WHEN '223' THEN SET `token` = 'SE_DoubleRiposte'; + WHEN '224' THEN SET `token` = 'SE_GiveDoubleRiposte'; + WHEN '225' THEN SET `token` = 'SE_GiveDoubleAttack'; + WHEN '226' THEN SET `token` = 'SE_TwoHandBash'; + WHEN '227' THEN SET `token` = 'SE_ReduceSkillTimer'; + WHEN '228' THEN SET `token` = 'SE_ReduceFallDamage'; + WHEN '229' THEN SET `token` = 'SE_PersistantCasting'; + WHEN '230' THEN SET `token` = 'SE_ExtendedShielding'; + WHEN '231' THEN SET `token` = 'SE_StunBashChance'; + WHEN '232' THEN SET `token` = 'SE_DivineSave'; + WHEN '233' THEN SET `token` = 'SE_Metabolism'; + WHEN '234' THEN SET `token` = 'SE_ReduceApplyPoisonTime'; + WHEN '235' THEN SET `token` = 'SE_ChannelChanceSpells'; + WHEN '236' THEN SET `token` = 'SE_FreePet'; + WHEN '237' THEN SET `token` = 'SE_GivePetGroupTarget'; + WHEN '238' THEN SET `token` = 'SE_IllusionPersistence'; + WHEN '239' THEN SET `token` = 'SE_FeignedCastOnChance'; + WHEN '240' THEN SET `token` = 'SE_StringUnbreakable'; + WHEN '241' THEN SET `token` = 'SE_ImprovedReclaimEnergy'; + WHEN '242' THEN SET `token` = 'SE_IncreaseChanceMemwipe'; + WHEN '243' THEN SET `token` = 'SE_CharmBreakChance'; + WHEN '244' THEN SET `token` = 'SE_RootBreakChance'; + WHEN '245' THEN SET `token` = 'SE_TrapCircumvention'; + WHEN '246' THEN SET `token` = 'SE_SetBreathLevel'; + WHEN '247' THEN SET `token` = 'SE_RaiseSkillCap'; + WHEN '248' THEN SET `token` = 'SE_SecondaryForte'; + WHEN '249' THEN SET `token` = 'SE_SecondaryDmgInc'; + WHEN '250' THEN SET `token` = 'SE_SpellProcChance'; + WHEN '251' THEN SET `token` = 'SE_ConsumeProjectile'; + WHEN '252' THEN SET `token` = 'SE_FrontalBackstabChance'; + WHEN '253' THEN SET `token` = 'SE_FrontalBackstabMinDmg'; + WHEN '254' THEN SET `token` = 'SE_Blank'; + WHEN '255' THEN SET `token` = 'SE_ShieldDuration'; + WHEN '256' THEN SET `token` = 'SE_ShroudofStealth'; + WHEN '257' THEN SET `token` = 'SE_PetDiscipline'; + WHEN '258' THEN SET `token` = 'SE_TripleBackstab'; + WHEN '259' THEN SET `token` = 'SE_CombatStability'; + WHEN '260' THEN SET `token` = 'SE_AddSingingMod'; + WHEN '261' THEN SET `token` = 'SE_SongModCap'; + WHEN '262' THEN SET `token` = 'SE_RaiseStatCap'; + WHEN '263' THEN SET `token` = 'SE_TradeSkillMastery'; + WHEN '264' THEN SET `token` = 'SE_HastenedAASkill'; + WHEN '265' THEN SET `token` = 'SE_MasteryofPast'; + WHEN '266' THEN SET `token` = 'SE_ExtraAttackChance'; + WHEN '267' THEN SET `token` = 'SE_PetDiscipline2'; + WHEN '268' THEN SET `token` = 'SE_ReduceTradeskillFail'; + WHEN '269' THEN SET `token` = 'SE_MaxBindWound'; + WHEN '270' THEN SET `token` = 'SE_BardSongRange'; + WHEN '271' THEN SET `token` = 'SE_BaseMovementSpeed'; + WHEN '272' THEN SET `token` = 'SE_CastingLevel2'; + WHEN '273' THEN SET `token` = 'SE_CriticalDoTChance'; + WHEN '274' THEN SET `token` = 'SE_CriticalHealChance'; + WHEN '275' THEN SET `token` = 'SE_CriticalMend'; + WHEN '276' THEN SET `token` = 'SE_Ambidexterity'; + WHEN '277' THEN SET `token` = 'SE_UnfailingDivinity'; + WHEN '278' THEN SET `token` = 'SE_FinishingBlow'; + WHEN '279' THEN SET `token` = 'SE_Flurry'; + WHEN '280' THEN SET `token` = 'SE_PetFlurry'; + WHEN '281' THEN SET `token` = 'SE_FeignedMinion'; + WHEN '282' THEN SET `token` = 'SE_ImprovedBindWound'; + WHEN '283' THEN SET `token` = 'SE_DoubleSpecialAttack'; + WHEN '284' THEN SET `token` = 'SE_LoHSetHeal'; + WHEN '285' THEN SET `token` = 'SE_NimbleEvasion'; + WHEN '286' THEN SET `token` = 'SE_FcDamageAmt'; + WHEN '287' THEN SET `token` = 'SE_SpellDurationIncByTic'; + WHEN '288' THEN SET `token` = 'SE_SkillAttackProc'; + WHEN '289' THEN SET `token` = 'SE_CastOnFadeEffect'; + WHEN '290' THEN SET `token` = 'SE_IncreaseRunSpeedCap'; + WHEN '291' THEN SET `token` = 'SE_Purify'; + WHEN '292' THEN SET `token` = 'SE_StrikeThrough2'; + WHEN '293' THEN SET `token` = 'SE_FrontalStunResist'; + WHEN '294' THEN SET `token` = 'SE_CriticalSpellChance'; + WHEN '295' THEN SET `token` = 'SE_ReduceTimerSpecial'; + WHEN '296' THEN SET `token` = 'SE_FcSpellVulnerability'; + WHEN '297' THEN SET `token` = 'SE_FcDamageAmtIncoming'; + WHEN '298' THEN SET `token` = 'SE_ChangeHeight'; + WHEN '299' THEN SET `token` = 'SE_WakeTheDead'; + WHEN '300' THEN SET `token` = 'SE_Doppelganger'; + WHEN '301' THEN SET `token` = 'SE_ArcheryDamageModifier'; + WHEN '302' THEN SET `token` = 'SE_FcDamagePctCrit'; + WHEN '303' THEN SET `token` = 'SE_FcDamageAmtCrit'; + WHEN '304' THEN SET `token` = 'SE_OffhandRiposteFail'; + WHEN '305' THEN SET `token` = 'SE_MitigateDamageShield'; + WHEN '306' THEN SET `token` = 'SE_ArmyOfTheDead'; + WHEN '307' THEN SET `token` = 'SE_Appraisal'; + WHEN '308' THEN SET `token` = 'SE_SuspendMinion'; + WHEN '309' THEN SET `token` = 'SE_GateCastersBindpoint'; + WHEN '310' THEN SET `token` = 'SE_ReduceReuseTimer'; + WHEN '311' THEN SET `token` = 'SE_LimitCombatSkills'; + WHEN '312' THEN SET `token` = 'SE_Sanctuary'; + WHEN '313' THEN SET `token` = 'SE_ForageAdditionalItems'; + WHEN '314' THEN SET `token` = 'SE_Invisibility2'; + WHEN '315' THEN SET `token` = 'SE_InvisVsUndead2'; + WHEN '316' THEN SET `token` = 'SE_ImprovedInvisAnimals'; + WHEN '317' THEN SET `token` = 'SE_ItemHPRegenCapIncrease'; + WHEN '318' THEN SET `token` = 'SE_ItemManaRegenCapIncrease'; + WHEN '319' THEN SET `token` = 'SE_CriticalHealOverTime'; + WHEN '320' THEN SET `token` = 'SE_ShieldBlock'; + WHEN '321' THEN SET `token` = 'SE_ReduceHate'; + WHEN '322' THEN SET `token` = 'SE_GateToHomeCity'; + WHEN '323' THEN SET `token` = 'SE_DefensiveProc'; + WHEN '324' THEN SET `token` = 'SE_HPToMana'; + WHEN '325' THEN SET `token` = 'SE_NoBreakAESneak'; + WHEN '326' THEN SET `token` = 'SE_SpellSlotIncrease'; + WHEN '327' THEN SET `token` = 'SE_MysticalAttune'; + WHEN '328' THEN SET `token` = 'SE_DelayDeath'; + WHEN '329' THEN SET `token` = 'SE_ManaAbsorbPercentDamage'; + WHEN '330' THEN SET `token` = 'SE_CriticalDamageMob'; + WHEN '331' THEN SET `token` = 'SE_Salvage'; + WHEN '332' THEN SET `token` = 'SE_SummonToCorpse'; + WHEN '333' THEN SET `token` = 'SE_CastOnRuneFadeEffect'; + WHEN '334' THEN SET `token` = 'SE_BardAEDot'; + WHEN '335' THEN SET `token` = 'SE_BlockNextSpellFocus'; + WHEN '336' THEN SET `token` = 'SE_IllusionaryTarget'; + WHEN '337' THEN SET `token` = 'SE_PercentXPIncrease'; + WHEN '338' THEN SET `token` = 'SE_SummonAndResAllCorpses'; + WHEN '339' THEN SET `token` = 'SE_TriggerOnCast'; + WHEN '340' THEN SET `token` = 'SE_SpellTrigger'; + WHEN '341' THEN SET `token` = 'SE_ItemAttackCapIncrease'; + WHEN '342' THEN SET `token` = 'SE_ImmuneFleeing'; + WHEN '343' THEN SET `token` = 'SE_InterruptCasting'; + WHEN '344' THEN SET `token` = 'SE_ChannelChanceItems'; + WHEN '345' THEN SET `token` = 'SE_AssassinateLevel'; + WHEN '346' THEN SET `token` = 'SE_HeadShotLevel'; + WHEN '347' THEN SET `token` = 'SE_DoubleRangedAttack'; + WHEN '348' THEN SET `token` = 'SE_LimitManaMin'; + WHEN '349' THEN SET `token` = 'SE_ShieldEquipDmgMod'; + WHEN '350' THEN SET `token` = 'SE_ManaBurn'; + WHEN '351' THEN SET `token` = 'SE_PersistentEffect'; + WHEN '352' THEN SET `token` = 'SE_IncreaseTrapCount'; + WHEN '353' THEN SET `token` = 'SE_AdditionalAura'; + WHEN '354' THEN SET `token` = 'SE_DeactivateAllTraps'; + WHEN '355' THEN SET `token` = 'SE_LearnTrap'; + WHEN '356' THEN SET `token` = 'SE_ChangeTriggerType'; + WHEN '357' THEN SET `token` = 'SE_FcMute'; + WHEN '358' THEN SET `token` = 'SE_CurrentManaOnce'; + WHEN '359' THEN SET `token` = 'SE_PassiveSenseTrap'; + WHEN '360' THEN SET `token` = 'SE_ProcOnKillShot'; + WHEN '361' THEN SET `token` = 'SE_SpellOnDeath'; + WHEN '362' THEN SET `token` = 'SE_PotionBeltSlots'; + WHEN '363' THEN SET `token` = 'SE_BandolierSlots'; + WHEN '364' THEN SET `token` = 'SE_TripleAttackChance'; + WHEN '365' THEN SET `token` = 'SE_ProcOnSpellKillShot'; + WHEN '366' THEN SET `token` = 'SE_GroupShielding'; + WHEN '367' THEN SET `token` = 'SE_SetBodyType'; + WHEN '368' THEN SET `token` = 'SE_FactionMod'; + WHEN '369' THEN SET `token` = 'SE_CorruptionCounter'; + WHEN '370' THEN SET `token` = 'SE_ResistCorruption'; + WHEN '371' THEN SET `token` = 'SE_AttackSpeed4'; + WHEN '372' THEN SET `token` = 'SE_ForageSkill'; + WHEN '373' THEN SET `token` = 'SE_CastOnFadeEffectAlways'; + WHEN '374' THEN SET `token` = 'SE_ApplyEffect'; + WHEN '375' THEN SET `token` = 'SE_DotCritDmgIncrease'; + WHEN '376' THEN SET `token` = 'SE_Fling'; + WHEN '377' THEN SET `token` = 'SE_CastOnFadeEffectNPC'; + WHEN '378' THEN SET `token` = 'SE_SpellEffectResistChance'; + WHEN '379' THEN SET `token` = 'SE_ShadowStepDirectional'; + WHEN '380' THEN SET `token` = 'SE_Knockdown'; + WHEN '381' THEN SET `token` = 'SE_KnockTowardCaster'; + WHEN '382' THEN SET `token` = 'SE_NegateSpellEffect'; + WHEN '383' THEN SET `token` = 'SE_SympatheticProc'; + WHEN '384' THEN SET `token` = 'SE_Leap'; + WHEN '385' THEN SET `token` = 'SE_LimitSpellGroup'; + WHEN '386' THEN SET `token` = 'SE_CastOnCurer'; + WHEN '387' THEN SET `token` = 'SE_CastOnCure'; + WHEN '388' THEN SET `token` = 'SE_SummonCorpseZone'; + WHEN '389' THEN SET `token` = 'SE_FcTimerRefresh'; + WHEN '390' THEN SET `token` = 'SE_FcTimerLockout'; + WHEN '391' THEN SET `token` = 'SE_LimitManaMax'; + WHEN '392' THEN SET `token` = 'SE_FcHealAmt'; + WHEN '393' THEN SET `token` = 'SE_FcHealPctIncoming'; + WHEN '394' THEN SET `token` = 'SE_FcHealAmtIncoming'; + WHEN '395' THEN SET `token` = 'SE_FcHealPctCritIncoming'; + WHEN '396' THEN SET `token` = 'SE_FcHealAmtCrit'; + WHEN '397' THEN SET `token` = 'SE_PetMeleeMitigation'; + WHEN '398' THEN SET `token` = 'SE_SwarmPetDuration'; + WHEN '399' THEN SET `token` = 'SE_FcTwincast'; + WHEN '400' THEN SET `token` = 'SE_HealGroupFromMana'; + WHEN '401' THEN SET `token` = 'SE_ManaDrainWithDmg'; + WHEN '402' THEN SET `token` = 'SE_EndDrainWithDmg'; + WHEN '403' THEN SET `token` = 'SE_LimitSpellClass'; + WHEN '404' THEN SET `token` = 'SE_LimitSpellSubclass'; + WHEN '405' THEN SET `token` = 'SE_TwoHandBluntBlock'; + WHEN '406' THEN SET `token` = 'SE_CastonNumHitFade'; + WHEN '407' THEN SET `token` = 'SE_CastonFocusEffect'; + WHEN '408' THEN SET `token` = 'SE_LimitHPPercent'; + WHEN '409' THEN SET `token` = 'SE_LimitManaPercent'; + WHEN '410' THEN SET `token` = 'SE_LimitEndPercent'; + WHEN '411' THEN SET `token` = 'SE_LimitClass'; + WHEN '412' THEN SET `token` = 'SE_LimitRace'; + WHEN '413' THEN SET `token` = 'SE_FcBaseEffects'; + WHEN '414' THEN SET `token` = 'SE_LimitCastingSkill'; + WHEN '415' THEN SET `token` = 'SE_FFItemClass'; + WHEN '416' THEN SET `token` = 'SE_ACv2'; + WHEN '417' THEN SET `token` = 'SE_ManaRegen_v2'; + WHEN '418' THEN SET `token` = 'SE_SkillDamageAmount2'; + WHEN '419' THEN SET `token` = 'SE_AddMeleeProc'; + WHEN '420' THEN SET `token` = 'SE_FcLimitUse'; + WHEN '421' THEN SET `token` = 'SE_FcIncreaseNumHits'; + WHEN '422' THEN SET `token` = 'SE_LimitUseMin'; + WHEN '423' THEN SET `token` = 'SE_LimitUseType'; + WHEN '424' THEN SET `token` = 'SE_GravityEffect'; + WHEN '425' THEN SET `token` = 'SE_Display'; + WHEN '426' THEN SET `token` = 'SE_IncreaseExtTargetWindow'; + WHEN '427' THEN SET `token` = 'SE_SkillProc'; + WHEN '428' THEN SET `token` = 'SE_LimitToSkill'; + WHEN '429' THEN SET `token` = 'SE_SkillProcSuccess'; + WHEN '430' THEN SET `token` = 'SE_PostEffect'; + WHEN '431' THEN SET `token` = 'SE_PostEffectData'; + WHEN '432' THEN SET `token` = 'SE_ExpandMaxActiveTrophyBen'; + WHEN '433' THEN SET `token` = 'SE_CriticalDotDecay'; + WHEN '434' THEN SET `token` = 'SE_CriticalHealDecay'; + WHEN '435' THEN SET `token` = 'SE_CriticalRegenDecay'; + WHEN '436' THEN SET `token` = 'SE_BeneficialCountDownHold'; + WHEN '437' THEN SET `token` = 'SE_TeleporttoAnchor'; + WHEN '438' THEN SET `token` = 'SE_TranslocatetoAnchor'; + WHEN '439' THEN SET `token` = 'SE_Assassinate'; + WHEN '440' THEN SET `token` = 'SE_FinishingBlowLvl'; + WHEN '441' THEN SET `token` = 'SE_DistanceRemoval'; + WHEN '442' THEN SET `token` = 'SE_TriggerOnReqTarget'; + WHEN '443' THEN SET `token` = 'SE_TriggerOnReqCaster'; + WHEN '444' THEN SET `token` = 'SE_ImprovedTaunt'; + WHEN '445' THEN SET `token` = 'SE_AddMercSlot'; + WHEN '446' THEN SET `token` = 'SE_AStacker'; + WHEN '447' THEN SET `token` = 'SE_BStacker'; + WHEN '448' THEN SET `token` = 'SE_CStacker'; + WHEN '449' THEN SET `token` = 'SE_DStacker'; + WHEN '450' THEN SET `token` = 'SE_MitigateDotDamage'; + WHEN '451' THEN SET `token` = 'SE_MeleeThresholdGuard'; + WHEN '452' THEN SET `token` = 'SE_SpellThresholdGuard'; + WHEN '453' THEN SET `token` = 'SE_TriggerMeleeThreshold'; + WHEN '454' THEN SET `token` = 'SE_TriggerSpellThreshold'; + WHEN '455' THEN SET `token` = 'SE_AddHatePct'; + WHEN '456' THEN SET `token` = 'SE_AddHateOverTimePct'; + WHEN '457' THEN SET `token` = 'SE_ResourceTap'; + WHEN '458' THEN SET `token` = 'SE_FactionModPct'; + WHEN '459' THEN SET `token` = 'SE_DamageModifier2'; + WHEN '460' THEN SET `token` = 'SE_Ff_Override_NotFocusable'; + WHEN '461' THEN SET `token` = 'SE_ImprovedDamage2'; + WHEN '462' THEN SET `token` = 'SE_FcDamageAmt2'; + WHEN '463' THEN SET `token` = 'SE_Shield_Target'; + WHEN '464' THEN SET `token` = 'SE_PC_Pet_Rampage'; + WHEN '465' THEN SET `token` = 'SE_PC_Pet_AE_Rampage'; + WHEN '466' THEN SET `token` = 'SE_PC_Pet_Flurry_Chance'; + WHEN '467' THEN SET `token` = 'SE_DS_Mitigation_Amount'; + WHEN '468' THEN SET `token` = 'SE_DS_Mitigation_Percentage'; + WHEN '469' THEN SET `token` = 'SE_Chance_Best_in_Spell_Grp'; + WHEN '470' THEN SET `token` = 'SE_Trigger_Best_in_Spell_Grp'; + WHEN '471' THEN SET `token` = 'SE_Double_Melee_Round'; + ELSE SET `token` = 'unk'; + END CASE; + + SET `token` = CONCAT(`token`, '(', `effect_id`, ')'); + + RETURN `token`; +END$$ + +DELIMITER ; \ No newline at end of file From a6a056ad0d3ddaa17fde0788babad7f908ff34b9 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 4 Feb 2017 19:52:21 -0500 Subject: [PATCH 531/693] Added rest of public spell effect list. Changed unimplemented effects to "NI_"##token format [skip ci] --- utils/scripts/spell_effect_token_function.sql | 137 +++++++++++------- 1 file changed, 81 insertions(+), 56 deletions(-) diff --git a/utils/scripts/spell_effect_token_function.sql b/utils/scripts/spell_effect_token_function.sql index ee5f9afc8..38cba8ed0 100644 --- a/utils/scripts/spell_effect_token_function.sql +++ b/utils/scripts/spell_effect_token_function.sql @@ -27,8 +27,8 @@ BEGIN WHEN '13' THEN SET `token` = 'SE_SeeInvis'; WHEN '14' THEN SET `token` = 'SE_WaterBreathing'; WHEN '15' THEN SET `token` = 'SE_CurrentMana'; - WHEN '16' THEN SET `token` = 'SE_NPCFrenzy'; - WHEN '17' THEN SET `token` = 'SE_NPCAwareness'; + WHEN '16' THEN SET `token` = 'NI_NPCFrenzy'; + WHEN '17' THEN SET `token` = 'NI_NPCAwareness'; WHEN '18' THEN SET `token` = 'SE_Lull'; WHEN '19' THEN SET `token` = 'SE_AddFaction'; WHEN '20' THEN SET `token` = 'SE_Blind'; @@ -45,12 +45,12 @@ BEGIN WHEN '31' THEN SET `token` = 'SE_Mez'; WHEN '32' THEN SET `token` = 'SE_SummonItem'; WHEN '33' THEN SET `token` = 'SE_SummonPet'; - WHEN '34' THEN SET `token` = 'SE_Confuse'; + WHEN '34' THEN SET `token` = 'NI_Confuse'; WHEN '35' THEN SET `token` = 'SE_DiseaseCounter'; WHEN '36' THEN SET `token` = 'SE_PoisonCounter'; - WHEN '37' THEN SET `token` = 'SE_DetectHostile'; - WHEN '38' THEN SET `token` = 'SE_DetectMagic'; - WHEN '39' THEN SET `token` = 'SE_DetectPoison'; + WHEN '37' THEN SET `token` = 'NI_DetectHostile'; + WHEN '38' THEN SET `token` = 'NI_DetectMagic'; + WHEN '39' THEN SET `token` = 'NI_DetectPoison'; WHEN '40' THEN SET `token` = 'SE_DivineAura'; WHEN '41' THEN SET `token` = 'SE_Destroy'; WHEN '42' THEN SET `token` = 'SE_ShadowStep'; @@ -62,7 +62,7 @@ BEGIN WHEN '48' THEN SET `token` = 'SE_ResistPoison'; WHEN '49' THEN SET `token` = 'SE_ResistDisease'; WHEN '50' THEN SET `token` = 'SE_ResistMagic'; - WHEN '51' THEN SET `token` = 'SE_DetectTraps'; + WHEN '51' THEN SET `token` = 'NI_DetectTraps'; WHEN '52' THEN SET `token` = 'SE_SenseDead'; WHEN '53' THEN SET `token` = 'SE_SenseSummoned'; WHEN '54' THEN SET `token` = 'SE_SenseAnimals'; @@ -71,9 +71,9 @@ BEGIN WHEN '57' THEN SET `token` = 'SE_Levitate'; WHEN '58' THEN SET `token` = 'SE_Illusion'; WHEN '59' THEN SET `token` = 'SE_DamageShield'; - WHEN '60' THEN SET `token` = 'SE_TransferItem'; + WHEN '60' THEN SET `token` = 'NI_TransferItem'; WHEN '61' THEN SET `token` = 'SE_Identify'; - WHEN '62' THEN SET `token` = 'SE_ItemID'; + WHEN '62' THEN SET `token` = 'NI_ItemID'; WHEN '63' THEN SET `token` = 'SE_WipeHateList'; WHEN '64' THEN SET `token` = 'SE_SpinTarget'; WHEN '65' THEN SET `token` = 'SE_InfraVision'; @@ -81,9 +81,9 @@ BEGIN WHEN '67' THEN SET `token` = 'SE_EyeOfZomm'; WHEN '68' THEN SET `token` = 'SE_ReclaimPet'; WHEN '69' THEN SET `token` = 'SE_TotalHP'; - WHEN '70' THEN SET `token` = 'SE_CorpseBomb'; + WHEN '70' THEN SET `token` = 'NI_CorpseBomb'; WHEN '71' THEN SET `token` = 'SE_NecPet'; - WHEN '72' THEN SET `token` = 'SE_PreserveCorpse'; + WHEN '72' THEN SET `token` = 'NI_PreserveCorpse'; WHEN '73' THEN SET `token` = 'SE_BindSight'; WHEN '74' THEN SET `token` = 'SE_FeignDeath'; WHEN '75' THEN SET `token` = 'SE_VoiceGraft'; @@ -91,7 +91,7 @@ BEGIN WHEN '77' THEN SET `token` = 'SE_LocateCorpse'; WHEN '78' THEN SET `token` = 'SE_AbsorbMagicAtt'; WHEN '79' THEN SET `token` = 'SE_CurrentHPOnce'; - WHEN '80' THEN SET `token` = 'SE_EnchantLight'; + WHEN '80' THEN SET `token` = 'NI_EnchantLight'; WHEN '81' THEN SET `token` = 'SE_Revive'; WHEN '82' THEN SET `token` = 'SE_SummonPC'; WHEN '83' THEN SET `token` = 'SE_Teleport'; @@ -101,7 +101,7 @@ BEGIN WHEN '87' THEN SET `token` = 'SE_MagnifyVision'; WHEN '88' THEN SET `token` = 'SE_Succor'; WHEN '89' THEN SET `token` = 'SE_ModelSize'; - WHEN '90' THEN SET `token` = 'SE_Cloak'; + WHEN '90' THEN SET `token` = 'NI_Cloak'; WHEN '91' THEN SET `token` = 'SE_SummonCorpse'; WHEN '92' THEN SET `token` = 'SE_InstantHate'; WHEN '93' THEN SET `token` = 'SE_StopRain'; @@ -121,7 +121,7 @@ BEGIN WHEN '107' THEN SET `token` = 'SE_AlterNPCLevel'; WHEN '108' THEN SET `token` = 'SE_Familiar'; WHEN '109' THEN SET `token` = 'SE_SummonItemIntoBag'; - WHEN '110' THEN SET `token` = 'SE_IncreaseArchery'; + WHEN '110' THEN SET `token` = 'NI_IncreaseArchery'; WHEN '111' THEN SET `token` = 'SE_ResistAll'; WHEN '112' THEN SET `token` = 'SE_CastingLevel'; WHEN '113' THEN SET `token` = 'SE_SummonHorse'; @@ -133,7 +133,7 @@ BEGIN WHEN '119' THEN SET `token` = 'SE_AttackSpeed3'; WHEN '120' THEN SET `token` = 'SE_HealRate'; WHEN '121' THEN SET `token` = 'SE_ReverseDS'; - WHEN '122' THEN SET `token` = 'SE_ReduceSkill'; + WHEN '122' THEN SET `token` = 'NI_ReduceSkill'; WHEN '123' THEN SET `token` = 'SE_Screech'; WHEN '124' THEN SET `token` = 'SE_ImprovedDamage'; WHEN '125' THEN SET `token` = 'SE_ImprovedHeal'; @@ -157,7 +157,7 @@ BEGIN WHEN '143' THEN SET `token` = 'SE_LimitCastTimeMin'; WHEN '144' THEN SET `token` = 'SE_LimitCastTimeMax'; WHEN '145' THEN SET `token` = 'SE_Teleport2'; - WHEN '146' THEN SET `token` = 'SE_ElectricityResist'; + WHEN '146' THEN SET `token` = 'NI_ElectricityResist'; WHEN '147' THEN SET `token` = 'SE_PercentalHeal'; WHEN '148' THEN SET `token` = 'SE_StackingCommand_Block'; WHEN '149' THEN SET `token` = 'SE_StackingCommand_Overwrite'; @@ -171,7 +171,7 @@ BEGIN WHEN '157' THEN SET `token` = 'SE_SpellDamageShield'; WHEN '158' THEN SET `token` = 'SE_Reflect'; WHEN '159' THEN SET `token` = 'SE_AllStats'; - WHEN '160' THEN SET `token` = 'SE_MakeDrunk'; + WHEN '160' THEN SET `token` = 'NI_MakeDrunk'; WHEN '161' THEN SET `token` = 'SE_MitigateSpellDamage'; WHEN '162' THEN SET `token` = 'SE_MitigateMeleeDamage'; WHEN '163' THEN SET `token` = 'SE_NegateAttacks'; @@ -219,9 +219,9 @@ BEGIN WHEN '205' THEN SET `token` = 'SE_Rampage'; WHEN '206' THEN SET `token` = 'SE_AETaunt'; WHEN '207' THEN SET `token` = 'SE_FleshToBone'; - WHEN '208' THEN SET `token` = 'SE_PurgePoison'; + WHEN '208' THEN SET `token` = 'NI_PurgePoison'; WHEN '209' THEN SET `token` = 'SE_DispelBeneficial'; - WHEN '210' THEN SET `token` = 'SE_PetShield'; + WHEN '210' THEN SET `token` = 'NI_PetShield'; WHEN '211' THEN SET `token` = 'SE_AEMelee'; WHEN '212' THEN SET `token` = 'SE_FrenziedDevastation'; WHEN '213' THEN SET `token` = 'SE_PetMaxHP'; @@ -247,11 +247,11 @@ BEGIN WHEN '233' THEN SET `token` = 'SE_Metabolism'; WHEN '234' THEN SET `token` = 'SE_ReduceApplyPoisonTime'; WHEN '235' THEN SET `token` = 'SE_ChannelChanceSpells'; - WHEN '236' THEN SET `token` = 'SE_FreePet'; + WHEN '236' THEN SET `token` = 'NI_FreePet'; WHEN '237' THEN SET `token` = 'SE_GivePetGroupTarget'; WHEN '238' THEN SET `token` = 'SE_IllusionPersistence'; WHEN '239' THEN SET `token` = 'SE_FeignedCastOnChance'; - WHEN '240' THEN SET `token` = 'SE_StringUnbreakable'; + WHEN '240' THEN SET `token` = 'NI_StringUnbreakable'; WHEN '241' THEN SET `token` = 'SE_ImprovedReclaimEnergy'; WHEN '242' THEN SET `token` = 'SE_IncreaseChanceMemwipe'; WHEN '243' THEN SET `token` = 'SE_CharmBreakChance'; @@ -295,7 +295,7 @@ BEGIN WHEN '281' THEN SET `token` = 'SE_FeignedMinion'; WHEN '282' THEN SET `token` = 'SE_ImprovedBindWound'; WHEN '283' THEN SET `token` = 'SE_DoubleSpecialAttack'; - WHEN '284' THEN SET `token` = 'SE_LoHSetHeal'; + WHEN '284' THEN SET `token` = 'NI_LoHSetHeal'; WHEN '285' THEN SET `token` = 'SE_NimbleEvasion'; WHEN '286' THEN SET `token` = 'SE_FcDamageAmt'; WHEN '287' THEN SET `token` = 'SE_SpellDurationIncByTic'; @@ -306,7 +306,7 @@ BEGIN WHEN '292' THEN SET `token` = 'SE_StrikeThrough2'; WHEN '293' THEN SET `token` = 'SE_FrontalStunResist'; WHEN '294' THEN SET `token` = 'SE_CriticalSpellChance'; - WHEN '295' THEN SET `token` = 'SE_ReduceTimerSpecial'; + WHEN '295' THEN SET `token` = 'NI_ReduceTimerSpecial'; WHEN '296' THEN SET `token` = 'SE_FcSpellVulnerability'; WHEN '297' THEN SET `token` = 'SE_FcDamageAmtIncoming'; WHEN '298' THEN SET `token` = 'SE_ChangeHeight'; @@ -317,8 +317,8 @@ BEGIN WHEN '303' THEN SET `token` = 'SE_FcDamageAmtCrit'; WHEN '304' THEN SET `token` = 'SE_OffhandRiposteFail'; WHEN '305' THEN SET `token` = 'SE_MitigateDamageShield'; - WHEN '306' THEN SET `token` = 'SE_ArmyOfTheDead'; - WHEN '307' THEN SET `token` = 'SE_Appraisal'; + WHEN '306' THEN SET `token` = 'NI_ArmyOfTheDead'; + WHEN '307' THEN SET `token` = 'NI_Appraisal'; WHEN '308' THEN SET `token` = 'SE_SuspendMinion'; WHEN '309' THEN SET `token` = 'SE_GateCastersBindpoint'; WHEN '310' THEN SET `token` = 'SE_ReduceReuseTimer'; @@ -327,7 +327,7 @@ BEGIN WHEN '313' THEN SET `token` = 'SE_ForageAdditionalItems'; WHEN '314' THEN SET `token` = 'SE_Invisibility2'; WHEN '315' THEN SET `token` = 'SE_InvisVsUndead2'; - WHEN '316' THEN SET `token` = 'SE_ImprovedInvisAnimals'; + WHEN '316' THEN SET `token` = 'NI_ImprovedInvisAnimals'; WHEN '317' THEN SET `token` = 'SE_ItemHPRegenCapIncrease'; WHEN '318' THEN SET `token` = 'SE_ItemManaRegenCapIncrease'; WHEN '319' THEN SET `token` = 'SE_CriticalHealOverTime'; @@ -347,7 +347,7 @@ BEGIN WHEN '333' THEN SET `token` = 'SE_CastOnRuneFadeEffect'; WHEN '334' THEN SET `token` = 'SE_BardAEDot'; WHEN '335' THEN SET `token` = 'SE_BlockNextSpellFocus'; - WHEN '336' THEN SET `token` = 'SE_IllusionaryTarget'; + WHEN '336' THEN SET `token` = 'NI_IllusionaryTarget'; WHEN '337' THEN SET `token` = 'SE_PercentXPIncrease'; WHEN '338' THEN SET `token` = 'SE_SummonAndResAllCorpses'; WHEN '339' THEN SET `token` = 'SE_TriggerOnCast'; @@ -362,15 +362,15 @@ BEGIN WHEN '348' THEN SET `token` = 'SE_LimitManaMin'; WHEN '349' THEN SET `token` = 'SE_ShieldEquipDmgMod'; WHEN '350' THEN SET `token` = 'SE_ManaBurn'; - WHEN '351' THEN SET `token` = 'SE_PersistentEffect'; - WHEN '352' THEN SET `token` = 'SE_IncreaseTrapCount'; - WHEN '353' THEN SET `token` = 'SE_AdditionalAura'; - WHEN '354' THEN SET `token` = 'SE_DeactivateAllTraps'; - WHEN '355' THEN SET `token` = 'SE_LearnTrap'; - WHEN '356' THEN SET `token` = 'SE_ChangeTriggerType'; + WHEN '351' THEN SET `token` = 'NI_PersistentEffect'; + WHEN '352' THEN SET `token` = 'NI_IncreaseTrapCount'; + WHEN '353' THEN SET `token` = 'NI_AdditionalAura'; + WHEN '354' THEN SET `token` = 'NI_DeactivateAllTraps'; + WHEN '355' THEN SET `token` = 'NI_LearnTrap'; + WHEN '356' THEN SET `token` = 'NI_ChangeTriggerType'; WHEN '357' THEN SET `token` = 'SE_FcMute'; WHEN '358' THEN SET `token` = 'SE_CurrentManaOnce'; - WHEN '359' THEN SET `token` = 'SE_PassiveSenseTrap'; + WHEN '359' THEN SET `token` = 'NI_PassiveSenseTrap'; WHEN '360' THEN SET `token` = 'SE_ProcOnKillShot'; WHEN '361' THEN SET `token` = 'SE_SpellOnDeath'; WHEN '362' THEN SET `token` = 'SE_PotionBeltSlots'; @@ -379,7 +379,7 @@ BEGIN WHEN '365' THEN SET `token` = 'SE_ProcOnSpellKillShot'; WHEN '366' THEN SET `token` = 'SE_GroupShielding'; WHEN '367' THEN SET `token` = 'SE_SetBodyType'; - WHEN '368' THEN SET `token` = 'SE_FactionMod'; + WHEN '368' THEN SET `token` = 'NI_FactionMod'; WHEN '369' THEN SET `token` = 'SE_CorruptionCounter'; WHEN '370' THEN SET `token` = 'SE_ResistCorruption'; WHEN '371' THEN SET `token` = 'SE_AttackSpeed4'; @@ -387,21 +387,21 @@ BEGIN WHEN '373' THEN SET `token` = 'SE_CastOnFadeEffectAlways'; WHEN '374' THEN SET `token` = 'SE_ApplyEffect'; WHEN '375' THEN SET `token` = 'SE_DotCritDmgIncrease'; - WHEN '376' THEN SET `token` = 'SE_Fling'; + WHEN '376' THEN SET `token` = 'NI_Fling'; WHEN '377' THEN SET `token` = 'SE_CastOnFadeEffectNPC'; WHEN '378' THEN SET `token` = 'SE_SpellEffectResistChance'; WHEN '379' THEN SET `token` = 'SE_ShadowStepDirectional'; WHEN '380' THEN SET `token` = 'SE_Knockdown'; - WHEN '381' THEN SET `token` = 'SE_KnockTowardCaster'; + WHEN '381' THEN SET `token` = 'NI_KnockTowardCaster'; WHEN '382' THEN SET `token` = 'SE_NegateSpellEffect'; WHEN '383' THEN SET `token` = 'SE_SympatheticProc'; WHEN '384' THEN SET `token` = 'SE_Leap'; WHEN '385' THEN SET `token` = 'SE_LimitSpellGroup'; WHEN '386' THEN SET `token` = 'SE_CastOnCurer'; WHEN '387' THEN SET `token` = 'SE_CastOnCure'; - WHEN '388' THEN SET `token` = 'SE_SummonCorpseZone'; + WHEN '388' THEN SET `token` = 'NI_SummonCorpseZone'; WHEN '389' THEN SET `token` = 'SE_FcTimerRefresh'; - WHEN '390' THEN SET `token` = 'SE_FcTimerLockout'; + WHEN '390' THEN SET `token` = 'NI_FcTimerLockout'; WHEN '391' THEN SET `token` = 'SE_LimitManaMax'; WHEN '392' THEN SET `token` = 'SE_FcHealAmt'; WHEN '393' THEN SET `token` = 'SE_FcHealPctIncoming'; @@ -426,7 +426,7 @@ BEGIN WHEN '412' THEN SET `token` = 'SE_LimitRace'; WHEN '413' THEN SET `token` = 'SE_FcBaseEffects'; WHEN '414' THEN SET `token` = 'SE_LimitCastingSkill'; - WHEN '415' THEN SET `token` = 'SE_FFItemClass'; + WHEN '415' THEN SET `token` = 'NI_FFItemClass'; WHEN '416' THEN SET `token` = 'SE_ACv2'; WHEN '417' THEN SET `token` = 'SE_ManaRegen_v2'; WHEN '418' THEN SET `token` = 'SE_SkillDamageAmount2'; @@ -436,27 +436,27 @@ BEGIN WHEN '422' THEN SET `token` = 'SE_LimitUseMin'; WHEN '423' THEN SET `token` = 'SE_LimitUseType'; WHEN '424' THEN SET `token` = 'SE_GravityEffect'; - WHEN '425' THEN SET `token` = 'SE_Display'; + WHEN '425' THEN SET `token` = 'NI_Display'; WHEN '426' THEN SET `token` = 'SE_IncreaseExtTargetWindow'; WHEN '427' THEN SET `token` = 'SE_SkillProc'; WHEN '428' THEN SET `token` = 'SE_LimitToSkill'; WHEN '429' THEN SET `token` = 'SE_SkillProcSuccess'; - WHEN '430' THEN SET `token` = 'SE_PostEffect'; - WHEN '431' THEN SET `token` = 'SE_PostEffectData'; - WHEN '432' THEN SET `token` = 'SE_ExpandMaxActiveTrophyBen'; + WHEN '430' THEN SET `token` = 'NI_PostEffect'; + WHEN '431' THEN SET `token` = 'NI_PostEffectData'; + WHEN '432' THEN SET `token` = 'NI_ExpandMaxActiveTrophyBen'; WHEN '433' THEN SET `token` = 'SE_CriticalDotDecay'; WHEN '434' THEN SET `token` = 'SE_CriticalHealDecay'; WHEN '435' THEN SET `token` = 'SE_CriticalRegenDecay'; - WHEN '436' THEN SET `token` = 'SE_BeneficialCountDownHold'; - WHEN '437' THEN SET `token` = 'SE_TeleporttoAnchor'; - WHEN '438' THEN SET `token` = 'SE_TranslocatetoAnchor'; + WHEN '436' THEN SET `token` = 'NI_BeneficialCountDownHold'; + WHEN '437' THEN SET `token` = 'NI_TeleporttoAnchor'; + WHEN '438' THEN SET `token` = 'NI_TranslocatetoAnchor'; WHEN '439' THEN SET `token` = 'SE_Assassinate'; WHEN '440' THEN SET `token` = 'SE_FinishingBlowLvl'; WHEN '441' THEN SET `token` = 'SE_DistanceRemoval'; WHEN '442' THEN SET `token` = 'SE_TriggerOnReqTarget'; WHEN '443' THEN SET `token` = 'SE_TriggerOnReqCaster'; WHEN '444' THEN SET `token` = 'SE_ImprovedTaunt'; - WHEN '445' THEN SET `token` = 'SE_AddMercSlot'; + WHEN '445' THEN SET `token` = 'NI_AddMercSlot'; WHEN '446' THEN SET `token` = 'SE_AStacker'; WHEN '447' THEN SET `token` = 'SE_BStacker'; WHEN '448' THEN SET `token` = 'SE_CStacker'; @@ -471,18 +471,43 @@ BEGIN WHEN '457' THEN SET `token` = 'SE_ResourceTap'; WHEN '458' THEN SET `token` = 'SE_FactionModPct'; WHEN '459' THEN SET `token` = 'SE_DamageModifier2'; - WHEN '460' THEN SET `token` = 'SE_Ff_Override_NotFocusable'; + WHEN '460' THEN SET `token` = 'NI_Ff_Override_NotFocusable'; WHEN '461' THEN SET `token` = 'SE_ImprovedDamage2'; WHEN '462' THEN SET `token` = 'SE_FcDamageAmt2'; - WHEN '463' THEN SET `token` = 'SE_Shield_Target'; + WHEN '463' THEN SET `token` = 'NI_Shield_Target'; WHEN '464' THEN SET `token` = 'SE_PC_Pet_Rampage'; - WHEN '465' THEN SET `token` = 'SE_PC_Pet_AE_Rampage'; + WHEN '465' THEN SET `token` = 'NI_PC_Pet_AE_Rampage'; WHEN '466' THEN SET `token` = 'SE_PC_Pet_Flurry_Chance'; - WHEN '467' THEN SET `token` = 'SE_DS_Mitigation_Amount'; - WHEN '468' THEN SET `token` = 'SE_DS_Mitigation_Percentage'; - WHEN '469' THEN SET `token` = 'SE_Chance_Best_in_Spell_Grp'; - WHEN '470' THEN SET `token` = 'SE_Trigger_Best_in_Spell_Grp'; - WHEN '471' THEN SET `token` = 'SE_Double_Melee_Round'; + WHEN '467' THEN SET `token` = 'NI_DS_Mitigation_Amount'; + WHEN '468' THEN SET `token` = 'NI_DS_Mitigation_Percentage'; + WHEN '469' THEN SET `token` = 'NI_Chance_Best_in_Spell_Grp'; + WHEN '470' THEN SET `token` = 'NI_Trigger_Best_in_Spell_Grp'; + WHEN '471' THEN SET `token` = 'NI_Double_Melee_Round'; +-- these are not defined + WHEN '472' THEN SET `token` = 'NI_Buy_AA_Rank'; + WHEN '473' THEN SET `token` = 'NI_Double_Backstab_From_Front'; + WHEN '474' THEN SET `token` = 'NI_Pet_Crit_Melee_Damage_Pct'; + WHEN '475' THEN SET `token` = 'NI_Trigger_Spell_Non_Item'; + WHEN '476' THEN SET `token` = 'NI_Weapon_Stance'; + WHEN '477' THEN SET `token` = 'NI_Hatelist_To_Top_Index'; + WHEN '478' THEN SET `token` = 'NI_Hatelist_To_Tail_Index'; + WHEN '479' THEN SET `token` = 'NI_Ff_Value_Min'; + WHEN '480' THEN SET `token` = 'NI_Ff_Value_Max'; + WHEN '481' THEN SET `token` = 'NI_Fc_Cast_Spell_On_Land'; + WHEN '482' THEN SET `token` = 'NI_Skill_Base_Damage_Mod'; + WHEN '483' THEN SET `token` = 'NI_Fc_Spell_Damage_Pct_IncomingPC'; + WHEN '484' THEN SET `token` = 'NI_Fc_Spell_Damage_Amt_IncomingPC'; + WHEN '485' THEN SET `token` = 'NI_Ff_CasterClass'; + WHEN '486' THEN SET `token` = 'NI_Ff_Same_Caster'; + WHEN '487' THEN SET `token` = 'NI_Extend_Tradeskill_Cap'; + WHEN '488' THEN SET `token` = 'NI_Defender_Melee_Force_Pct'; + WHEN '489' THEN SET `token` = 'NI_Worn_Endurance_Regen_Cap'; + WHEN '490' THEN SET `token` = 'NI_Ff_ReuseTimeMin'; + WHEN '491' THEN SET `token` = 'NI_Ff_ReuseTimeMax'; + WHEN '492' THEN SET `token` = 'NI_Ff_Endurance_Min'; + WHEN '493' THEN SET `token` = 'NI_Ff_Endurance_Max'; + WHEN '494' THEN SET `token` = 'NI_Pet_Add_Atk'; + WHEN '495' THEN SET `token` = 'NI_Ff_DurationMax'; ELSE SET `token` = 'unk'; END CASE; From df1d499da6673bd49d00eb6c120708168bb6d1e4 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 5 Feb 2017 02:20:40 -0500 Subject: [PATCH 532/693] Imported RoF2 race names --- common/races.cpp | 1359 ++++++++++++++++++++++++++++++++++++++++++++-- common/races.h | 735 +++++++++++++++++++++++++ 2 files changed, 2051 insertions(+), 43 deletions(-) diff --git a/common/races.cpp b/common/races.cpp index 7fd88911b..9d5fbdda0 100644 --- a/common/races.cpp +++ b/common/races.cpp @@ -21,53 +21,1326 @@ const char* GetRaceIDName(uint16 race_id) { switch (race_id) { - case HUMAN: - return "Human"; - case BARBARIAN: + // Old Race Labels + //case HUMAN: + // return "Human"; + //case BARBARIAN: + // return "Barbarian"; + //case ERUDITE: + // return "Erudite"; + //case WOOD_ELF: + // return "Wood Elf"; + //case HIGH_ELF: + // return "High Elf"; + //case DARK_ELF: + // return "Dark Elf"; + //case HALF_ELF: + // return "Half Elf"; + //case DWARF: + // return "Dwarf"; + //case TROLL: + // return "Troll"; + //case OGRE: + // return "Ogre"; + //case HALFLING: + // return "Halfling"; + //case GNOME: + // return "Gnome"; + //case IKSAR: + // return "Iksar"; + //case WEREWOLF: + // return "Werewolf"; + //case SKELETON: + // return "Skeleton"; + //case ELEMENTAL: + // return "Elemental"; + //case EYE_OF_ZOMM: + // return "Eye of Zomm"; + //case WOLF_ELEMENTAL: + // return "Wolf Elemental"; + //case IKSAR_SKELETON: + // return "Iksar Skeleton"; + //case VAHSHIR: + // return "Vah Shir"; + //case FROGLOK: + //case FROGLOK2: // "Piranha"? (low-byte issue..) + // return "Froglok"; + //case DRAKKIN: + // return "Drakkin"; + + // RoF2 Race Labels + case RT_ABHORRENT: + return "Abhorrent"; + case RT_AIR_ELEMENTAL: + case RT_AIR_ELEMENTAL_2: + return "Air Elemental"; + case RT_AIR_MEPHIT: + return "Air Mephit"; + case RT_AKHEVA: + case RT_AKHEVA_2: + return "Akheva"; + case RT_ALARAN: + return "Alaran"; + case RT_ALARAN_GHOST: + return "Alaran Ghost"; + case RT_ALARAN_SENTRY_STONE: + return "Alaran Sentry Stone"; + case RT_ALLIGATOR: + case RT_ALLIGATOR_2: + return "Alligator"; + case RT_AMYGDALAN: + case RT_AMYGDALAN_2: + return "Amygdalan"; + case RT_ANEUK: + return "Aneuk"; + case RT_ANIMATED_ARMOR: + return "Animated Armor"; + case RT_ANIMATED_HAND: + return "Animated Hand"; + case RT_ANIMATED_STATUE: + case RT_ANIMATED_STATUE_2: + return "Animated Statue"; + case RT_APEXUS: + return "Apexus"; + case RT_ARACHNID: + return "Arachnid"; + case RT_ARCANIST_OF_HATE: + return "Arcanist of Hate"; + case RT_ARMADILLO: + return "Armadillo"; + case RT_ARMOR_RACK: + return "Armor Rack"; + case RT_AVIAK: + case RT_AVIAK_2: + return "Aviak"; + case RT_AVIAK_PULL_ALONG: + return "Aviak Pull Along"; + case RT_AYONAE_RO: + return "Ayonae Ro"; + case RT_BANNER: + case RT_BANNER_2: + case RT_BANNER_3: + case RT_BANNER_4: + case RT_BANNER_5: + case RT_BANNER_6: + case RT_BANNER_7: + return "Banner"; + case RT_BANNER_10TH_ANNIVERSARY: + return "10th Anniversary Banner"; + case RT_BANSHEE: + case RT_BANSHEE_2: + case RT_BANSHEE_3: + return "Banshee"; + case RT_BARBARIAN: + case RT_BARBARIAN_2: return "Barbarian"; - case ERUDITE: - return "Erudite"; - case WOOD_ELF: - return "Wood Elf"; - case HIGH_ELF: - return "High Elf"; - case DARK_ELF: + case RT_BARREL: + return "Barrel"; + case RT_BARREL_BARGE_SHIP: + return "Barrel Barge Ship"; + case RT_BASILISK: + return "Basilisk"; + case RT_BAT: + case RT_BAT_2: + case RT_BAT_3: + return "Bat"; + case RT_BAZU: + return "Bazu"; + case RT_BEAR: + case RT_BEAR_2: + case RT_BEAR_3: + return "Bear"; + case RT_BEAR_MOUNT: + return "Bear Mount"; + case RT_BEAR_TRAP: + return "Bear Trap"; + case RT_BEETLE: + case RT_BEETLE_2: + case RT_BEETLE_3: + return "Beetle"; + case RT_BEGGAR: + return "Beggar"; + case RT_BELLIKOS: + return "Bellikos"; + case RT_BERTOXXULOUS: + case RT_BERTOXXULOUS_2: + return "Bertoxxulous"; + case RT_BIXIE: + case RT_BIXIE_2: + return "Bixie"; + case RT_BLIMP_SHIP: + return "Blimp Ship"; + case RT_BLIND_DREAMER: + return "Blind Dreamer"; + case RT_BLOOD_RAVEN: + return "Blood Raven"; + case RT_BOAT: + case RT_BOAT_2: + return "Boat"; + case RT_BOLVIRK: + return "Bolvirk"; + case RT_BONE_GOLEM: + case RT_BONE_GOLEM_2: + return "Bone Golem"; + case RT_BONES: + return "Bones"; + case RT_BOOK_DERVISH: + return "Book Dervish"; + case RT_BOT_PORTAL: + return "BoT Portal"; + case RT_BOULDER: + return "Boulder"; + case RT_BOX: + return "Box"; + case RT_BRAXI: + return "Braxi"; + case RT_BRAXI_MOUNT: + return "Braxi Mount"; + case RT_BRELL: + return "Brell"; + case RT_BRELLS_FIRST_CREATION: + return "Brell's First Creation"; + case RT_BRISTLEBANE: + return "Bristlebane"; + case RT_BROKEN_CLOCKWORK: + return "Broken Clockwork"; + case RT_BRONTOTHERIUM: + return "Brontotherium"; + case RT_BROWNIE: + case RT_BROWNIE_2: + return "Brownie"; + case RT_BUBONIAN: + return "Bubonian"; + case RT_BUBONIAN_UNDERLING: + return "Bubonian Underling"; + case RT_BURYNAI: + case RT_BURYNAI_2: + return "Burynai"; + case RT_CAKE_10TH_ANNIVERSARY: + return "10th Anniversary Cake"; + case RT_CAMPFIRE: + return "Campfire"; + case RT_CARRIER_HAND: + return "Carrier Hand"; + case RT_CAT: + return "Cat"; + case RT_CAZIC_THULE: + case RT_CAZIC_THULE_2: + return "Cazic Thule"; + case RT_CENTAUR: + case RT_CENTAUR_2: + return "Centaur"; + case RT_CHEST: + case RT_CHEST_2: + case RT_CHEST_3: + return "Chest"; + case RT_CHIMERA: + case RT_CHIMERA_2: + return "Chimera"; + case RT_CHOKIDAI: + return "Chokidai"; + case RT_CLAM: + return "Clam"; + case RT_CLIKNAR_MOUNT: + return "Cliknar Mount"; + case RT_CLIKNAR_QUEEN: + return "Cliknar Queen"; + case RT_CLIKNAR_SOLDIER: + return "Cliknar Soldier"; + case RT_CLIKNAR_WORKER: + return "Cliknar Worker"; + case RT_CLOCKWORK_BEETLE: + return "Clockwork Beetle"; + case RT_CLOCKWORK_BOAR: + return "Clockwork Boar"; + case RT_CLOCKWORK_BOMB: + return "Clockwork Bomb"; + case RT_CLOCKWORK_BRAIN: + return "Clockwork Brain"; + case RT_CLOCKWORK_GNOME: + return "Clockwork Gnome"; + case RT_CLOCKWORK_GOLEM: + return "Clockwork Golem"; + case RT_CLOCKWORK_GUARDIAN: + return "Clockwork Guardian"; + case RT_COCKATRICE: + return "Cockatrice"; + case RT_COFFIN: + case RT_COFFIN_2: + return "Coffin"; + case RT_COIN_PURSE: + return "Coin Purse"; + case RT_COLDAIN: + case RT_COLDAIN_2: + case RT_COLDAIN_3: + return "Coldain"; + case RT_CORAL: + return "Coral"; + case RT_CORATHUS: + return "Corathus"; + case RT_CRAB: + return "Crab"; + case RT_CRAGBEAST: + return "Cragbeast"; + case RT_CRAGSLITHER: + return "Cragslither"; + case RT_CROCODILE: + return "Crocodile"; + case RT_CRYSTAL: + return "Crystal"; + case RT_CRYSTAL_SHARD: + return "Crystal Shard"; + case RT_CRYSTAL_SPHERE: + return "Crystal Sphere"; + case RT_CRYSTAL_SPIDER: + return "Crystal Spider"; + case RT_CRYSTALSKIN_AMBULOID: + return "Crystalskin Ambuloid"; + case RT_CRYSTALSKIN_SESSILOID: + return "Crystalskin Sessiloid"; + case RT_DAISY_MAN: + return "Daisy Man"; + case RT_DARK_ELF: + case RT_DARK_ELF_2: return "Dark Elf"; - case HALF_ELF: - return "Half Elf"; - case DWARF: - return "Dwarf"; - case TROLL: - return "Troll"; - case OGRE: - return "Ogre"; - case HALFLING: - return "Halfling"; - case GNOME: - return "Gnome"; - case IKSAR: - return "Iksar"; - case WEREWOLF: - return "Werewolf"; - case SKELETON: - return "Skeleton"; - case ELEMENTAL: - return "Elemental"; - case EYE_OF_ZOMM: - return "Eye of Zomm"; - case WOLF_ELEMENTAL: - return "Wolf Elemental"; - case IKSAR_SKELETON: - return "Iksar Skeleton"; - case VAHSHIR: - return "Vah Shir"; - case FROGLOK: - case FROGLOK2: - return "Froglok"; - case DRAKKIN: + case RT_DARK_LORD: + return "Dark Lord"; + case RT_DEMI_LICH: + return "Demi Lich"; + case RT_DEMON_VULTURE: + return "Demon Vulture"; + case RT_DERVISH: + case RT_DERVISH_2: + case RT_DERVISH_3: + case RT_DERVISH_4: + return "Dervish"; + case RT_DERVISH_VER_5: + return "Dervish(Ver. 5)"; + case RT_DERVISH_VER_6: + return "Dervish(Ver. 6)"; + case RT_DEVOURER: + return "Devourer"; + case RT_DIRE_WOLF: + return "Dire Wolf"; + case RT_DISCORD_SHIP: + return "Discord Ship"; + case RT_DISCORDLING: + return "Discordling"; + case RT_DISEASED_FIEND: + return "Diseased Fiend"; + case RT_DJINN: + return "Djinn"; + case RT_DRACHNID: + case RT_DRACHNID_2: + return "Drachnid"; + case RT_DRACHNID_COCOON: + return "Drachnid Cocoon"; + case RT_DRACOLICH: + return "Dracolich"; + case RT_DRAGLOCK: + return "Draglock"; + case RT_DRAGON: + case RT_DRAGON_2: + case RT_DRAGON_3: + case RT_DRAGON_4: + case RT_DRAGON_5: + case RT_DRAGON_6: + case RT_DRAGON_7: + case RT_DRAGON_8: + case RT_DRAGON_9: + case RT_DRAGON_10: + case RT_DRAGON_11: + case RT_DRAGON_12: + case RT_DRAGON_13: + case RT_DRAGON_14: + case RT_DRAGON_15: + case RT_DRAGON_16: + return "Dragon"; + case RT_DRAGON_BONES: + return "Dragon Bones"; + case RT_DRAGON_EGG: + return "Dragon Egg"; + case RT_DRAGON_STATUE: + return "Dragon Statue"; + case RT_DRAGORN: + return "Dragorn"; + case RT_DRAGORN_BOX: + return "Dragorn Box"; + case RT_DRAKE: + case RT_DRAKE_2: + case RT_DRAKE_3: + return "Drake"; + case RT_DRAKKIN: return "Drakkin"; + case RT_DRIXIE: + return "Drixie"; + case RT_DROGMORE: + return "Drogmore"; + case RT_DROLVARG: + return "Drolvarg"; + case RT_DRYAD: + return "Dryad"; + case RT_DWARF: + case RT_DWARF_2: + return "Dwarf"; + case RT_DYNAMITE_KEG: + return "Dynamite Keg"; + case RT_DYNLETH: + return "Dyn'Leth"; + case RT_EARTH_ELEMENTAL: + case RT_EARTH_ELEMENTAL_2: + return "Earth Elemental"; + case RT_EARTH_MEPHIT: + return "Earth Mephit"; + case RT_EEL: + return "Eel"; + case RT_EFREETI: + case RT_EFREETI_2: + return "Efreeti"; + case RT_ELDDAR: + return "Elddar"; + case RT_ELEMENTAL: + return "Elemental"; + case RT_ELK_HEAD: + return "Elk Head"; + case RT_ELVEN_BOAT: + return "Elven Boat"; + case RT_ELVEN_GHOST: + return "Elven Ghost"; + case RT_ENCHANTED_ARMOR: + return "Enchanted Armor"; + case RT_EROLLISI: + return "Erollisi"; + case RT_ERUDITE: + case RT_ERUDITE_2: + case RT_ERUDITE_3: + return "Erudite"; + case RT_EVAN_TEST: + return "Evan Test"; + case RT_EVIL_EYE: + case RT_EVIL_EYE_2: + case RT_EVIL_EYE_3: + return "Evil Eye"; + case RT_EXOSKELETON: + return "Exoskeleton"; + case RT_EXPLOSIVE_CART: + return "Explosive Cart"; + case RT_EYE: + return "Eye"; + case RT_FAIRY: + case RT_FAIRY_2: + return "Fairy"; + case RT_FALLEN_KNIGHT: + return "Fallen Knight"; + case RT_FAUN: + return "Faun"; + case RT_FAY_DRAKE: + return "Fay Drake"; + case RT_FENNIN_RO: + return "Fennin Ro"; + case RT_FERAN: + return "Feran"; + case RT_FERAN_MOUNT: + return "Feran Mount"; + case RT_FIEND: + return "Fiend"; + case RT_FIRE_ELEMENTAL: + case RT_FIRE_ELEMENTAL_2: + return "Fire Elemental"; + case RT_FIRE_MEPHIT: + return "Fire Mephit"; + case RT_FISH: + case RT_FISH_2: + return "Fish"; + case RT_FLAG: + return "Flag"; + case RT_FLOATING_ISLAND: + return "Floating Island"; + case RT_FLOATING_SKULL: + return "Floating Skull"; + case RT_FLOATING_TOWER: + return "Floating Tower"; + case RT_FLY: + return "Fly"; + case RT_FLYING_CARPET: + return "Flying Carpet"; + case RT_FOREST_GIANT: + return "Forest Giant"; + case RT_FROG: + case RT_FROG_2: + return "Frog"; + case RT_FROGLOK: + case RT_FROGLOK_2: + case RT_FROGLOK_3: + return "Froglok"; + case RT_FROGLOK_GHOST: + return "Froglok Ghost"; + case RT_FROGLOK_SKELETON: + return "Froglok Skeleton"; + case RT_FUNGAL_FIEND: + return "Fungal Fiend"; + case RT_FUNGUS_PATCH: + return "Fungus Patch"; + case RT_FUNGUSMAN: + return "Fungusman"; + case RT_GALORIAN: + return "Galorian"; + case RT_GARGOYLE: + case RT_GARGOYLE_2: + return "Gargoyle"; + case RT_GASBAG: + return "Gasbag"; + case RT_GELATINOUS_CUBE: + case RT_GELATINOUS_CUBE_2: + return "Gelatinous Cube"; + case RT_GELIDRAN: + return "Gelidran"; + case RT_GENARI: + return "Genari"; + case RT_GEONID: + return "Geonid"; + case RT_GHOST: + case RT_GHOST_2: + case RT_GHOST_3: + case RT_GHOST_4: + return "Ghost"; + case RT_GHOST_SHIP: + case RT_GHOST_SHIP_2: + return "Ghost Ship"; + case RT_GHOUL: + case RT_GHOUL_2: + return "Ghoul"; + case RT_GIANT: + case RT_GIANT_2: + case RT_GIANT_3: + case RT_GIANT_4: + case RT_GIANT_5: + case RT_GIANT_6: + case RT_GIANT_7: + case RT_GIANT_8: + case RT_GIANT_9: + case RT_GIANT_10: + case RT_GIANT_11: + case RT_GIANT_12: + case RT_GIANT_13: + return "Giant"; + case RT_GIANT_CLOCKWORK: + return "Giant Clockwork"; + case RT_GIANT_RALLOSIAN_MATS: + return "Giant(Rallosian mats)"; + case RT_GIANT_SHADE: + return "Giant Shade"; + case RT_GIGYN: + return "Gigyn"; + case RT_GINGERBREAD_MAN: + return "Gingerbread Man"; + case RT_GIRPLAN: + return "Girplan"; + case RT_GNOLL: + case RT_GNOLL_2: + case RT_GNOLL_3: + return "Gnoll"; + case RT_GNOME: + return "Gnome"; + case RT_GNOMEWORK: + return "Gnomework"; + case RT_GNOMISH_BALLOON: + return "Gnomish Balloon"; + case RT_GNOMISH_BOAT: + return "Gnomish Boat"; + case RT_GNOMISH_HOVERING_TRANSPORT: + return "Gnomish Hovering Transport"; + case RT_GNOMISH_ROCKET_PACK: + return "Gnomish Rocket Pack"; + case RT_GOBLIN: + case RT_GOBLIN_2: + case RT_GOBLIN_3: + case RT_GOBLIN_4: + case RT_GOBLIN_5: + return "Goblin"; + case RT_GOD_LUCLIN_VER_2: + return "God - Luclin(Ver. 2)"; + case RT_GOD_LUCLIN_VER_3: + return "God - Luclin(Ver. 3)"; + case RT_GOD_LUCLIN_VER_4: + return "God - Luclin(Ver. 4)"; + case RT_GOD_OF_DISCORD: + return "God of Discord"; + case RT_GOLEM: + case RT_GOLEM_2: + return "Golem"; + case RT_GOO: + case RT_GOO_2: + case RT_GOO_3: + case RT_GOO_4: + return "Goo"; + case RT_GORAL: + return "Goral"; + case RT_GORAL_MOUNT: + return "Goral Mount"; + case RT_GORGON: + return "Gorgon"; + case RT_GORILLA: + case RT_GORILLA_2: + return "Gorilla"; + case RT_GRANDFATHER_CLOCK: + return "Grandfather Clock"; + case RT_GREKEN_YOUNG: + return "Greken - Young"; + case RT_GREKEN_YOUNG_ADULT: + return "Greken - Young Adult"; + case RT_GRENDLAEN: + return "Grendlaen"; + case RT_GRIEG_VENEFICUS: + return "Grieg Veneficus"; + case RT_GRIFFIN: + case RT_GRIFFIN_2: + return "Griffin"; + case RT_GRIMLING: + return "Grimling"; + case RT_GROUND_SHAKER: + return "Ground Shaker"; + case RT_GUARD: + case RT_GUARD_2: + case RT_GUARD_3: + case RT_GUARD_4: + return "Guard"; + case RT_GUARD_OF_JUSTICE: + return "Guard of Justice"; + case RT_GUARDIAN_CPU: + return "Guardian CPU"; + case RT_HADAL: + return "Hadal"; + case RT_HAG: + return "Hag"; + case RT_HALF_ELF: + return "Half Elf"; + case RT_HALFLING: + case RT_HALFLING_2: + return "Halfling"; + case RT_HARPY: + case RT_HARPY_2: + return "Harpy"; + case RT_HIGH_ELF: + return "High Elf"; + case RT_HIPPOGRIFF: + return "Hippogriff"; + case RT_HOLGRESH: + case RT_HOLGRESH_2: + return "Holgresh"; + case RT_HONEY_POT: + return "Honey Pot"; + case RT_HORSE: + case RT_HORSE_2: + case RT_HORSE_3: + return "Horse"; + case RT_HOVERING_PLATFORM: + return "Hovering Platform"; + case RT_HRAQUIS: + return "Hraquis"; + case RT_HUMAN: + case RT_HUMAN_2: + case RT_HUMAN_3: + case RT_HUMAN_4: + return "Human"; + case RT_HUMAN_GHOST: + return "Human Ghost"; + case RT_HUVUL: + return "Huvul"; + case RT_HYDRA_CRYSTAL: + return "Hydra Crystal"; + case RT_HYDRA_MOUNT: + return "Hydra Mount"; + case RT_HYDRA_NPC: + return "Hydra NPC"; + case RT_HYNID: + return "Hynid"; + case RT_ICE_SPECTRE: + return "Ice Spectre"; + case RT_IKAAV: + return "Ikaav"; + case RT_IKSAR: + case RT_IKSAR_2: + return "Iksar"; + case RT_IKSAR_GHOST: + return "Iksar Ghost"; + case RT_IKSAR_GOLEM: + return "Iksar Golem"; + case RT_IKSAR_SKELETON: + return "Iksar Skeleton"; + case RT_IKSAR_SPIRIT: + return "Iksar Spirit"; + case RT_IMP: + return "Imp"; + case RT_INNORUUK: + return "Innoruuk"; + case RT_INSECT: + return "Insect"; + case RT_INTERACTIVE_OBJECT: + return "Interactive Object"; + case RT_INVISIBLE_MAN: + case RT_INVISIBLE_MAN_2: + case RT_INVISIBLE_MAN_3: + return "Invisible Man"; + case RT_INVISIBLE_MAN_OF_ZOMM: + return "Invisible Man of Zomm"; + case RT_IXT: + return "Ixt"; + case RT_JOKESTER: + return "Jokester"; + case RT_JUM_JUM_BUCKET: + return "Jum Jum Bucket"; + case RT_JUNK_BEAST: + return "Junk Beast"; + case RT_KANGON: + return "Kangon"; + case RT_KANGON_MOUNT: + return "Kangon Mount"; + case RT_KARANA: + return "Karana"; + case RT_KEDGE: + case RT_KEDGE_2: + return "Kedge"; + case RT_KERRAN: + case RT_KERRAN_2: + return "Kerran"; + case RT_KIRIN: + case RT_KIRIN_2: + return "Kirin"; + case RT_KNIGHT_OF_HATE: + return "Knight of Hate"; + case RT_KNIGHT_OF_PESTILENCE: + return "Knight of Pestilence"; + case RT_KOBOLD: + case RT_KOBOLD_2: + return "Kobold"; + case RT_KRAKEN: + return "Kraken"; + case RT_KYV: + return "Kyv"; + case RT_LAUNCH: + return "Launch"; + case RT_LAVA_ROCK: + return "Lava Rock"; + case RT_LAVA_SPIDER: + return "Lava Spider"; + case RT_LAVA_SPIDER_QUEEN: + return "Lava Spider Queen"; + case RT_LEECH: + return "Leech"; + case RT_LEPERTOLOTH: + return "Lepertoloth"; + case RT_LIGHTCRAWLER: + return "Lightcrawler"; + case RT_LIGHTNING_WARRIOR: + return "Lightning Warrior"; + case RT_LION: + return "Lion"; + case RT_LIZARD_MAN: + return "Lizard Man"; + case RT_LUCLIN: + return "Luclin"; + case RT_LUGGALD: + case RT_LUGGALD_2: + return "Luggald"; + case RT_LUGGALDS: + return "Luggalds"; + case RT_MALARIAN: + return "Malarian"; + case RT_MAMMOTH: + case RT_MAMMOTH_2: + return "Mammoth"; + case RT_MAN_EATING_PLANT: + return "Man - Eating Plant"; + case RT_MANSION: + return "Mansion"; + case RT_MANTICORE: + return "Manticore"; + case RT_MANTRAP: + return "Mantrap"; + case RT_MARIONETTE: + return "Marionette"; + case RT_MASTRUQ: + return "Mastruq"; + case RT_MATA_MURAM: + return "Mata Muram"; + case RT_MEDIUM_PLANT: + return "Medium Plant"; + case RT_MEPHIT: + return "Mephit"; + case RT_MERCHANT_SHIP: + return "Merchant Ship"; + case RT_MERMAID: + return "Mermaid"; + case RT_MIMIC: + return "Mimic"; + case RT_MINI_POM: + return "Mini POM"; + case RT_MINOTAUR: + case RT_MINOTAUR_2: + case RT_MINOTAUR_3: + case RT_MINOTAUR_4: + return "Minotaur"; + case RT_MITHANIEL_MARR: + return "Mithaniel Marr"; + case RT_MORELL_THULE: + return "Morell Thule"; + case RT_MOSQUITO: + return "Mosquito"; + case RT_MOUTH_OF_INSANITY: + return "Mouth of Insanity"; + case RT_MUDDITE: + return "Muddite"; + case RT_MUMMY: + return "Mummy"; + case RT_MURAMITE_ARMOR_PILE: + return "Muramite Armor Pile"; + case RT_MURKGLIDER: + return "Murkglider"; + case RT_MURKGLIDER_EGG_SAC: + return "Murkglider Egg Sac"; + case RT_MUTNA: + return "Mutna"; + case RT_NEKHON: + return "Nekhon"; + case RT_NETHERBIAN: + return "Netherbian"; + case RT_NIGHTMARE: + return "Nightmare"; + case RT_NIGHTMARE_GARGOYLE: + return "Nightmare Gargoyle"; + case RT_NIGHTMARE_GOBLIN: + return "Nightmare Goblin"; + case RT_NIGHTMARE_MEPHIT: + return "Nightmare Mephit"; + case RT_NIGHTMARE_UNICORN: + case RT_NIGHTMARE_UNICORN_2: + return "Nightmare / Unicorn"; + case RT_NIGHTMARE_WRAITH: + return "Nightmare Wraith"; + case RT_NIHIL: + return "Nihil"; + case RT_NILBORIEN: + return "Nilborien"; + case RT_NOC: + return "Noc"; + case RT_NYMPH: + return "Nymph"; + case RT_OGRE: + case RT_OGRE_2: + return "Ogre"; + case RT_OGRE_NPC_MALE: + return "Ogre NPC - Male"; + case RT_ORB: + return "Orb"; + case RT_ORC: + case RT_ORC_2: + return "Orc"; + case RT_OTHMIR: + return "Othmir"; + case RT_OWLBEAR: + return "Owlbear"; + case RT_PARASITIC_SCAVENGER: + return "Parasitic Scavenger"; + case RT_PEGASUS: + case RT_PEGASUS_2: + case RT_PEGASUS_3: + return "Pegasus"; + case RT_PHOENIX: + return "Phoenix"; + case RT_PIRANHA: + return "Piranha"; + case RT_PIRATE: + case RT_PIRATE_2: + case RT_PIRATE_3: + case RT_PIRATE_4: + case RT_PIRATE_5: + case RT_PIRATE_6: + case RT_PIRATE_7: + case RT_PIRATE_8: + return "Pirate"; + case RT_PIRATE_SHIP: + return "Pirate Ship"; + case RT_PIXIE: + return "Pixie"; + case RT_POISON_FROG: + return "Poison Frog"; + case RT_PORTAL: + return "Portal"; + case RT_POWDER_KEG: + return "Powder Keg"; + case RT_PRESSURE_PLATE: + return "Pressure Plate"; + case RT_PUFFER_SPORE: + return "Puffer Spore"; + case RT_PUMA: + case RT_PUMA_2: + case RT_PUMA_3: + return "Puma"; + case RT_PUSLING: + return "Pusling"; + case RT_PYRILEN: + return "Pyrilen"; + case RT_RA_TUK: + return "Ra`tuk"; + case RT_RABBIT: + return "Rabbit"; + case RT_RALLOS_ZEK: + case RT_RALLOS_ZEK_2: + return "Rallos Zek"; + case RT_RALLOS_ZEK_MINION: + return "Rallos Zek Minion"; + case RT_RAPTOR: + case RT_RAPTOR_2: + return "Raptor"; + case RT_RAPTOR_MOUNT: + return "Raptor Mount"; + case RT_RAT: + case RT_RAT_2: + return "Rat"; + case RT_RAT_MOUNT: + return "Rat Mount"; + case RT_RATMAN: + case RT_RATMAN_2: + return "Ratman"; + case RT_REANIMATED_HAND: + return "Reanimated Hand"; + case RT_RECUSO: + return "Recuso"; + case RT_REGENERATION_POOL: + return "Regeneration Pool"; + case RT_RELIC_CASE: + return "Relic case "; + case RT_RHINO_BEETLE: + return "Rhino Beetle"; + case RT_RHINOCEROS: + return "Rhinoceros"; + case RT_ROBOCOPTER_OF_ZOMM: + return "Robocopter of Zomm"; + case RT_ROCK_PILE: + return "Rock Pile"; + case RT_ROCKHOPPER: + return "Rockhopper"; + case RT_RONNIE_TEST: + return "Ronnie Test"; + case RT_ROOT_TENTACLE: + return "Root Tentacle"; + case RT_ROT_DOG_MOUNT: + return "Rot Dog Mount"; + case RT_ROTDOG: + return "Rotdog"; + case RT_ROTOCOPTER: + return "Rotocopter"; + case RT_ROWBOAT: + return "Rowboat"; + case RT_ROYAL_GUARD: + return "Royal Guard"; + case RT_RUJARKIAN_ORC: + case RT_RUJARKIAN_ORC_2: + return "Rujarkian Orc"; + case RT_RUNED_ORB: + return "Runed Orb"; + case RT_RUNIC_SYMBOL: + return "Runic Symbol"; + case RT_SABER_TOOTHED_CAT: + return "Saber - toothed Cat"; + case RT_SALTPETTER_BOMB: + return "Saltpetter Bomb"; + case RT_SAND_ELF: + return "Sand Elf"; + case RT_SANDMAN: + return "Sandman"; + case RT_SARNAK: + case RT_SARNAK_2: + return "Sarnak"; + case RT_SARNAK_GOLEM: + return "Sarnak Golem"; + case RT_SARNAK_SPIRIT: + return "Sarnak Spirit"; + case RT_SARYRN: + return "Saryrn"; + case RT_SATYR: + return "Satyr"; + case RT_SCALED_WOLF: + return "Scaled Wolf"; + case RT_SCARECROW: + case RT_SCARECROW_2: + return "Scarecrow"; + case RT_SCARLET_CHEETAH: + return "Scarlet Cheetah"; + case RT_SCLERA_MOUNT: + return "Sclera Mount"; + case RT_SCORPION: + case RT_SCORPION_2: + case RT_SCORPION_3: + return "Scorpion"; + case RT_SCRYKIN: + return "Scrykin"; + case RT_SEA_TURTLE: + return "Sea Turtle"; + case RT_SEAHORSE: + return "Seahorse"; + case RT_SELYRAH: + return "Selyrah"; + case RT_SELYRAH_MOUNT: + return "Selyrah Mount"; + case RT_SERU: + return "Seru"; + case RT_SERVANT_OF_SHADOW: + return "Servant of Shadow"; + case RT_SESSILOID_MOUNT: + return "Sessiloid Mount"; + case RT_SHADE: + case RT_SHADE_2: + case RT_SHADE_3: + return "Shade"; + case RT_SHADEL: + return "Shadel"; + case RT_SHAMBLING_MOUND: + return "Shambling Mound"; + case RT_SHARK: + return "Shark"; + case RT_SHIKNAR: + return "Shik'Nar"; + case RT_SHILISKIN: + return "Shiliskin"; + case RT_SHIP: + return "Ship"; + case RT_SHIP_IN_A_BOTTLE: + return "Ship in a Bottle"; + case RT_SHISSAR: + case RT_SHISSAR_2: + return "Shissar"; + case RT_SHRIEKER: + return "Shrieker"; + case RT_SIREN: + case RT_SIREN_2: + return "Siren"; + case RT_SKELETAL_HORSE: + return "Skeletal Horse"; + case RT_SKELETON: + case RT_SKELETON_2: + case RT_SKELETON_3: + return "Skeleton"; + case RT_SKUNK: + return "Skunk"; + case RT_SKYSTRIDER: + return "Skystrider"; + case RT_SMALL_PLANT: + return "Small Plant"; + case RT_SNAKE: + case RT_SNAKE_2: + return "Snake"; + case RT_SNAKE_ELEMENTAL: + return "Snake Elemental"; + case RT_SNOW_DERVISH: + return "Snow Dervish"; + case RT_SNOW_RABBIT: + return "Snow Rabbit"; + case RT_SOKOKAR: + return "Sokokar"; + case RT_SOKOKAR_MOUNT: + return "Sokokar Mount"; + case RT_SOKOKAR_W_SADDLE: + return "Sokokar(w saddle)"; + case RT_SOLUSEK_RO: + case RT_SOLUSEK_RO_2: + return "Solusek Ro"; + case RT_SOLUSEK_RO_GUARD: + return "Solusek Ro Guard"; + case RT_SONIC_WOLF: + return "Sonic Wolf"; + case RT_SOUL_DEVOURER: + return "Soul Devourer"; + case RT_SPECTRE: + case RT_SPECTRE_2: + return "Spectre"; + case RT_SPELL_PARTICLE_1: + return "Spell Particle 1"; + case RT_SPHINX: + case RT_SPHINX_2: + return "Sphinx"; + case RT_SPIDER: + case RT_SPIDER_2: + return "Spider"; + case RT_SPIDER_EGG_SACK: + return "Spider Egg Sack"; + case RT_SPIDER_MOUNT: + return "Spider Mount"; + case RT_SPIDER_QUEEN: + return "Spider Queen"; + case RT_SPIKE_TRAP: + return "Spike Trap"; + case RT_SPIRIT_WOLF: + return "Spirit Wolf"; + case RT_SPORALI: + return "Sporali"; + case RT_STONE_JUG: + return "Stone Jug"; + case RT_STONE_PYLON: + return "Stone Pylon"; + case RT_STONE_RING: + return "Stone Ring"; + case RT_STONE_WORKER: + case RT_STONE_WORKER_2: + return "Stone Worker"; + case RT_STONEGRABBER: + return "Stonegrabber"; + case RT_STONEMITE: + return "Stonemite"; + case RT_STORMRIDER: + return "Stormrider"; + case RT_SUCCUBUS: + return "Succubus"; + case RT_SUCCULENT: + return "Succulent"; + case RT_SULLON_ZEK: + return "Sullon Zek"; + case RT_SUN_REVENANT: + return "Sun Revenant"; + case RT_SUNFLOWER: + return "Sunflower"; + case RT_SWINETOR: + return "Swinetor"; + case RT_SWORDFISH: + return "Swordfish"; + case RT_SYNARCANA: + return "Synarcana"; + case RT_TABLE: + return "Table"; + case RT_TADPOLE: + return "Tadpole"; + case RT_TAELOSIAN: + return "Taelosian"; + case RT_TALL_PLANT: + return "Tall Plant"; + case RT_TALLON_ZEK: + return "Tallon Zek"; + case RT_TANETH: + return "Taneth"; + case RT_TAREW_MARR: + return "Tarew Marr"; + case RT_TEGI: + return "Tegi"; + case RT_TELEPORT_MAN: + return "Teleport Man"; + case RT_TELEPORTATION_STAND: + return "Teleportation Stand"; + case RT_TELMIRA: + return "Telmira"; + case RT_TENTACLE_TERROR: + case RT_TENTACLE_TERROR_2: + return "Tentacle Terror"; + case RT_TERRIS_THULE: + return "Terris Thule"; + case RT_TEST_OBJECT: + return "Test Object"; + case RT_THE_RATHE: + return "The Rathe"; + case RT_THE_TRIBUNAL: + return "The Tribunal"; + case RT_THOUGHT_HORROR: + return "Thought Horror"; + case RT_TIGER: + return "Tiger"; + case RT_TIN_SOLDIER: + return "Tin Soldier"; + case RT_TOOLBOX: + return "Toolbox"; + case RT_TOPIARY_LION: + return "Topiary Lion"; + case RT_TOPIARY_LION_MOUNT: + return "Topiary Lion Mount"; + case RT_TORMENTOR: + return "Tormentor"; + case RT_TOTEM: + case RT_TOTEM_2: + return "Totem"; + case RT_TRAKANON: + return "Trakanon"; + case RT_TRANQUILION: + return "Tranquilion"; + case RT_TREANT: + case RT_TREANT_2: + case RT_TREANT_3: + return "Treant"; + case RT_TRIBUNAL: + return "Tribunal"; + case RT_TRIUMVIRATE: + return "Triumvirate"; + case RT_TROLL: + case RT_TROLL_2: + case RT_TROLL_3: + case RT_TROLL_4: + case RT_TROLL_5: + return "Troll"; + case RT_TROLL_ZOMBIE: + return "Troll Zombie"; + case RT_TRUSIK: + return "Trusik"; + case RT_TSETSIAN: + return "Tsetsian"; + case RT_TUMBLEWEED: + return "Tumbleweed"; + case RT_TUNARE: + return "Tunare"; + case RT_TUREPTA: + return "Turepta"; + case RT_UKUN: + return "Ukun"; + case RT_ULTHORK: + return "Ulthork"; + case RT_UNDEAD_CHOKIDAI: + return "Undead Chokidai"; + case RT_UNDEAD_FOOTMAN: + return "Undead Footman"; + case RT_UNDEAD_FROGLOK: + return "Undead Froglok"; + case RT_UNDEAD_IKSAR: + return "Undead Iksar"; + case RT_UNDEAD_KNIGHT: + return "Undead Knight"; + case RT_UNDEAD_SARNAK: + return "Undead Sarnak"; + case RT_UNDEAD_VEKSAR: + return "Undead Veksar"; + case RT_UNDERBULK: + return "Underbulk"; + case RT_UNICORN: + return "Unicorn"; + case RT_UNKNOWN_RACE: + case RT_UNKNOWN_RACE_2: + case RT_UNKNOWN_RACE_3: + case RT_UNKNOWN_RACE_4: + case RT_UNKNOWN_RACE_5: + case RT_UNKNOWN_RACE_6: + case RT_UNKNOWN_RACE_7: + return "UNKNOWN RACE"; + case RT_VAH_SHIR: + case RT_VAH_SHIR_2: + return "Vah Shir"; + case RT_VAH_SHIR_SKELETON: + return "Vah Shir Skeleton"; + case RT_VALLON_ZEK: + return "Vallon Zek"; + case RT_VALORIAN: + case RT_VALORIAN_2: + return "Valorian"; + case RT_VAMPIRE: + case RT_VAMPIRE_2: + case RT_VAMPIRE_3: + case RT_VAMPIRE_4: + case RT_VAMPIRE_5: + case RT_VAMPIRE_6: + case RT_VAMPIRE_7: + case RT_VAMPIRE_8: + return "Vampire"; + case RT_VASE: + return "Vase"; + case RT_VEGEROG: + return "Vegerog"; + case RT_VEKSAR: + case RT_VEKSAR_2: + case RT_VEKSAR_3: + return "Veksar"; + case RT_VENRIL_SATHIR: + return "Venril Sathir"; + case RT_VINE_MAW: + return "Vine Maw"; + case RT_WAGON: + return "Wagon"; + case RT_WALRUS: + return "Walrus"; + case RT_WAR_BOAR: + case RT_WAR_BOAR_2: + return "War Boar"; + case RT_WAR_WRAITH: + return "War Wraith"; + case RT_WASP: + return "Wasp"; + case RT_WATER_ELEMENTAL: + case RT_WATER_ELEMENTAL_2: + return "Water Elemental"; + case RT_WATER_MEPHIT: + return "Water Mephit"; + case RT_WATER_SPOUT: + return "Water Spout"; + case RT_WEAPON_RACK: + case RT_WEAPON_RACK_2: + return "Weapon Rack"; + case RT_WEB: + return "Web"; + case RT_WEDDING_ALTAR: + return "Wedding Altar"; + case RT_WEDDING_ARBOR: + return "Wedding Arbor"; + case RT_WEDDING_FLOWERS: + return "Wedding Flowers"; + case RT_WEREORC: + return "Wereorc"; + case RT_WEREWOLF: + case RT_WEREWOLF_2: + case RT_WEREWOLF_3: + return "Werewolf"; + case RT_WETFANG_MINNOW: + return "Wetfang Minnow"; + case RT_WHIRLIGIG: + return "Whirligig"; + case RT_WICKER_BASKET: + return "Wicker Basket"; + case RT_WILL_O_WISP: + return "Will - O - Wisp"; + case RT_WINE_CASK: + case RT_WINE_CASK_2: + return "Wine Cask"; + case RT_WITHERAN: + case RT_WITHERAN_2: + return "Witheran"; + case RT_WOLF: + case RT_WOLF_2: + case RT_WOLF_3: + return "Wolf"; + case RT_WOOD_ELF: + return "Wood Elf"; + case RT_WORG: + case RT_WORG_2: + return "Worg"; + case RT_WORM: + return "Worm"; + case RT_WRETCH: + return "Wretch"; + case RT_WRULON: + case RT_WRULON_2: + return "Wrulon"; + case RT_WURM: + case RT_WURM_2: + return "Wurm"; + case RT_WURM_MOUNT: + return "Wurm Mount"; + case RT_WYVERN: + case RT_WYVERN_2: + return "Wyvern"; + case RT_XALGOZ: + return "Xalgoz"; + case RT_XARIC_THE_UNSPOKEN: + return "Xaric the Unspoken"; + case RT_XEGONY: + return "Xegony"; + case RT_YAKKAR: + return "Yakkar"; + case RT_YETI: + return "Yeti"; + case RT_ZEBUXORUK: + return "Zebuxoruk"; + case RT_ZEBUXORUKS_CAGE: + return "Zebuxoruk's Cage"; + case RT_ZELNIAK: + return "Zelniak"; + case RT_ZOMBIE: + case RT_ZOMBIE_2: + return "Zombie"; default: - return "Unknown"; + return "UNKNOWN RACE"; } } diff --git a/common/races.h b/common/races.h index d34d9b754..04fdbbd32 100644 --- a/common/races.h +++ b/common/races.h @@ -113,6 +113,741 @@ #define PLAYER_RACE_ALL_MASK 65535 +#define RT_ABHORRENT 193 +#define RT_AIR_ELEMENTAL 210 +#define RT_AIR_ELEMENTAL_2 475 +#define RT_AIR_MEPHIT 291 +#define RT_AKHEVA 230 +#define RT_AKHEVA_2 722 +#define RT_ALARAN 695 +#define RT_ALARAN_GHOST 708 +#define RT_ALARAN_SENTRY_STONE 703 +#define RT_ALLIGATOR 91 +#define RT_ALLIGATOR_2 479 +#define RT_AMYGDALAN 99 +#define RT_AMYGDALAN_2 663 +#define RT_ANEUK 395 +#define RT_ANIMATED_ARMOR 323 +#define RT_ANIMATED_HAND 166 +#define RT_ANIMATED_STATUE 442 +#define RT_ANIMATED_STATUE_2 448 +#define RT_APEXUS 637 +#define RT_ARACHNID 326 +#define RT_ARCANIST_OF_HATE 352 +#define RT_ARMADILLO 87 +#define RT_ARMOR_RACK 535 +#define RT_AVIAK 13 +#define RT_AVIAK_2 558 +#define RT_AVIAK_PULL_ALONG 711 +#define RT_AYONAE_RO 498 +#define RT_BANNER 500 +#define RT_BANNER_2 553 +#define RT_BANNER_3 554 +#define RT_BANNER_4 555 +#define RT_BANNER_5 556 +#define RT_BANNER_6 557 +#define RT_BANNER_7 586 +#define RT_BANNER_10TH_ANNIVERSARY 628 +#define RT_BANSHEE 250 +#define RT_BANSHEE_2 487 +#define RT_BANSHEE_3 488 +#define RT_BARBARIAN 2 +#define RT_BARBARIAN_2 90 +#define RT_BARREL 377 +#define RT_BARREL_BARGE_SHIP 546 +#define RT_BASILISK 436 +#define RT_BAT 34 +#define RT_BAT_2 260 +#define RT_BAT_3 416 +#define RT_BAZU 409 +#define RT_BEAR 43 +#define RT_BEAR_2 305 +#define RT_BEAR_3 480 +#define RT_BEAR_MOUNT 655 +#define RT_BEAR_TRAP 503 +#define RT_BEETLE 22 +#define RT_BEETLE_2 559 +#define RT_BEETLE_3 716 +#define RT_BEGGAR 55 +#define RT_BELLIKOS 638 +#define RT_BERTOXXULOUS 152 +#define RT_BERTOXXULOUS_2 255 +#define RT_BIXIE 79 +#define RT_BIXIE_2 520 +#define RT_BLIMP_SHIP 693 +#define RT_BLIND_DREAMER 669 +#define RT_BLOOD_RAVEN 279 +#define RT_BOAT 141 +#define RT_BOAT_2 533 +#define RT_BOLVIRK 486 +#define RT_BONE_GOLEM 362 +#define RT_BONE_GOLEM_2 491 +#define RT_BONES 383 +#define RT_BOOK_DERVISH 660 +#define RT_BOT_PORTAL 329 +#define RT_BOULDER 585 +#define RT_BOX 376 +#define RT_BRAXI 688 +#define RT_BRAXI_MOUNT 676 +#define RT_BRELL 640 +#define RT_BRELLS_FIRST_CREATION 639 +#define RT_BRISTLEBANE 153 +#define RT_BROKEN_CLOCKWORK 274 +#define RT_BRONTOTHERIUM 169 +#define RT_BROWNIE 15 +#define RT_BROWNIE_2 568 +#define RT_BUBONIAN 268 +#define RT_BUBONIAN_UNDERLING 269 +#define RT_BURYNAI 144 +#define RT_BURYNAI_2 602 +#define RT_CAKE_10TH_ANNIVERSARY 629 +#define RT_CAMPFIRE 567 +#define RT_CARRIER_HAND 721 +#define RT_CAT 713 +#define RT_CAZIC_THULE 95 +#define RT_CAZIC_THULE_2 670 +#define RT_CENTAUR 16 +#define RT_CENTAUR_2 521 +#define RT_CHEST 378 +#define RT_CHEST_2 589 +#define RT_CHEST_3 590 +#define RT_CHIMERA 412 +#define RT_CHIMERA_2 582 +#define RT_CHOKIDAI 356 +#define RT_CLAM 115 +#define RT_CLIKNAR_MOUNT 652 +#define RT_CLIKNAR_QUEEN 642 +#define RT_CLIKNAR_SOLDIER 643 +#define RT_CLIKNAR_WORKER 644 +#define RT_CLOCKWORK_BEETLE 276 +#define RT_CLOCKWORK_BOAR 472 +#define RT_CLOCKWORK_BOMB 504 +#define RT_CLOCKWORK_BRAIN 249 +#define RT_CLOCKWORK_GNOME 88 +#define RT_CLOCKWORK_GOLEM 248 +#define RT_CLOCKWORK_GUARDIAN 572 +#define RT_COCKATRICE 96 +#define RT_COFFIN 382 +#define RT_COFFIN_2 592 +#define RT_COIN_PURSE 427 +#define RT_COLDAIN 183 +#define RT_COLDAIN_2 645 +#define RT_COLDAIN_3 646 +#define RT_CORAL 460 +#define RT_CORATHUS 459 +#define RT_CRAB 302 +#define RT_CRAGBEAST 390 +#define RT_CRAGSLITHER 597 +#define RT_CROCODILE 259 +#define RT_CRYSTAL 591 +#define RT_CRYSTAL_SHARD 425 +#define RT_CRYSTAL_SPHERE 616 +#define RT_CRYSTAL_SPIDER 327 +#define RT_CRYSTALSKIN_AMBULOID 641 +#define RT_CRYSTALSKIN_SESSILOID 647 +#define RT_DAISY_MAN 97 +#define RT_DARK_ELF 6 +#define RT_DARK_ELF_2 77 +#define RT_DARK_LORD 466 +#define RT_DEMI_LICH 45 +#define RT_DEMON_VULTURE 620 +#define RT_DERVISH 100 +#define RT_DERVISH_2 372 +#define RT_DERVISH_3 431 +#define RT_DERVISH_4 704 +#define RT_DERVISH_VER_5 726 +#define RT_DERVISH_VER_6 727 +#define RT_DEVOURER 159 +#define RT_DIRE_WOLF 171 +#define RT_DISCORD_SHIP 404 +#define RT_DISCORDLING 418 +#define RT_DISEASED_FIEND 253 +#define RT_DJINN 126 +#define RT_DRACHNID 57 +#define RT_DRACHNID_2 461 +#define RT_DRACHNID_COCOON 462 +#define RT_DRACOLICH 604 +#define RT_DRAGLOCK 132 +#define RT_DRAGON 49 +#define RT_DRAGON_2 122 +#define RT_DRAGON_3 165 +#define RT_DRAGON_4 184 +#define RT_DRAGON_5 192 +#define RT_DRAGON_6 195 +#define RT_DRAGON_7 196 +#define RT_DRAGON_8 198 +#define RT_DRAGON_9 304 +#define RT_DRAGON_10 435 +#define RT_DRAGON_11 437 +#define RT_DRAGON_12 438 +#define RT_DRAGON_13 452 +#define RT_DRAGON_14 530 +#define RT_DRAGON_15 531 +#define RT_DRAGON_16 569 +#define RT_DRAGON_BONES 423 +#define RT_DRAGON_EGG 445 +#define RT_DRAGON_STATUE 446 +#define RT_DRAGORN 413 +#define RT_DRAGORN_BOX 421 +#define RT_DRAKE 89 +#define RT_DRAKE_2 430 +#define RT_DRAKE_3 432 +#define RT_DRAKKIN 522 +#define RT_DRIXIE 113 +#define RT_DROGMORE 348 +#define RT_DROLVARG 133 +#define RT_DRYAD 243 +#define RT_DWARF 8 +#define RT_DWARF_2 94 +#define RT_DYNAMITE_KEG 505 +#define RT_DYNLETH 532 +#define RT_EARTH_ELEMENTAL 209 +#define RT_EARTH_ELEMENTAL_2 476 +#define RT_EARTH_MEPHIT 292 +#define RT_EEL 35 +#define RT_EFREETI 101 +#define RT_EFREETI_2 320 +#define RT_ELDDAR 489 +#define RT_ELEMENTAL 75 +#define RT_ELK_HEAD 714 +#define RT_ELVEN_BOAT 544 +#define RT_ELVEN_GHOST 587 +#define RT_ENCHANTED_ARMOR 175 +#define RT_EROLLISI 150 +#define RT_ERUDITE 3 +#define RT_ERUDITE_2 78 +#define RT_ERUDITE_3 678 +#define RT_EVAN_TEST 204 +#define RT_EVIL_EYE 21 +#define RT_EVIL_EYE_2 375 +#define RT_EVIL_EYE_3 469 +#define RT_EXOSKELETON 570 +#define RT_EXPLOSIVE_CART 692 +#define RT_EYE 108 +#define RT_FAIRY 25 +#define RT_FAIRY_2 473 +#define RT_FALLEN_KNIGHT 719 +#define RT_FAUN 182 +#define RT_FAY_DRAKE 154 +#define RT_FENNIN_RO 284 +#define RT_FERAN 410 +#define RT_FERAN_MOUNT 623 +#define RT_FIEND 300 +#define RT_FIRE_ELEMENTAL 212 +#define RT_FIRE_ELEMENTAL_2 477 +#define RT_FIRE_MEPHIT 293 +#define RT_FISH 24 +#define RT_FISH_2 148 +#define RT_FLAG 501 +#define RT_FLOATING_ISLAND 596 +#define RT_FLOATING_SKULL 512 +#define RT_FLOATING_TOWER 691 +#define RT_FLY 245 +#define RT_FLYING_CARPET 720 +#define RT_FOREST_GIANT 490 +#define RT_FROG 343 +#define RT_FROG_2 603 +#define RT_FROGLOK 26 +#define RT_FROGLOK_2 27 +#define RT_FROGLOK_3 330 +#define RT_FROGLOK_GHOST 371 +#define RT_FROGLOK_SKELETON 349 +#define RT_FUNGAL_FIEND 218 +#define RT_FUNGUS_PATCH 463 +#define RT_FUNGUSMAN 28 +#define RT_GALORIAN 228 +#define RT_GARGOYLE 29 +#define RT_GARGOYLE_2 464 +#define RT_GASBAG 30 +#define RT_GELATINOUS_CUBE 31 +#define RT_GELATINOUS_CUBE_2 712 +#define RT_GELIDRAN 417 +#define RT_GENARI 648 +#define RT_GEONID 178 +#define RT_GHOST 32 +#define RT_GHOST_2 117 +#define RT_GHOST_3 118 +#define RT_GHOST_4 334 +#define RT_GHOST_SHIP 114 +#define RT_GHOST_SHIP_2 552 +#define RT_GHOUL 33 +#define RT_GHOUL_2 571 +#define RT_GIANT 18 +#define RT_GIANT_2 140 +#define RT_GIANT_3 188 +#define RT_GIANT_4 189 +#define RT_GIANT_5 306 +#define RT_GIANT_6 307 +#define RT_GIANT_7 308 +#define RT_GIANT_8 309 +#define RT_GIANT_9 310 +#define RT_GIANT_10 311 +#define RT_GIANT_11 312 +#define RT_GIANT_12 453 +#define RT_GIANT_13 523 +#define RT_GIANT_CLOCKWORK 275 +#define RT_GIANT_RALLOSIAN_MATS 626 +#define RT_GIANT_SHADE 526 +#define RT_GIGYN 649 +#define RT_GINGERBREAD_MAN 666 +#define RT_GIRPLAN 419 +#define RT_GNOLL 39 +#define RT_GNOLL_2 524 +#define RT_GNOLL_3 617 +#define RT_GNOME 12 +#define RT_GNOMEWORK 457 +#define RT_GNOMISH_BALLOON 683 +#define RT_GNOMISH_BOAT 545 +#define RT_GNOMISH_HOVERING_TRANSPORT 685 +#define RT_GNOMISH_ROCKET_PACK 684 +#define RT_GOBLIN 40 +#define RT_GOBLIN_2 59 +#define RT_GOBLIN_3 137 +#define RT_GOBLIN_4 369 +#define RT_GOBLIN_5 433 +#define RT_GOD_LUCLIN_VER_2 728 +#define RT_GOD_LUCLIN_VER_3 729 +#define RT_GOD_LUCLIN_VER_4 731 +#define RT_GOD_OF_DISCORD 622 +#define RT_GOLEM 17 +#define RT_GOLEM_2 374 +#define RT_GOO 145 +#define RT_GOO_2 547 +#define RT_GOO_3 548 +#define RT_GOO_4 549 +#define RT_GORAL 687 +#define RT_GORAL_MOUNT 673 +#define RT_GORGON 121 +#define RT_GORILLA 41 +#define RT_GORILLA_2 560 +#define RT_GRANDFATHER_CLOCK 665 +#define RT_GREKEN_YOUNG 651 +#define RT_GREKEN_YOUNG_ADULT 650 +#define RT_GRENDLAEN 701 +#define RT_GRIEG_VENEFICUS 231 +#define RT_GRIFFIN 47 +#define RT_GRIFFIN_2 525 +#define RT_GRIMLING 202 +#define RT_GROUND_SHAKER 233 +#define RT_GUARD 44 +#define RT_GUARD_2 106 +#define RT_GUARD_3 112 +#define RT_GUARD_4 239 +#define RT_GUARD_OF_JUSTICE 251 +#define RT_GUARDIAN_CPU 593 +#define RT_HADAL 698 +#define RT_HAG 185 +#define RT_HALF_ELF 7 +#define RT_HALFLING 11 +#define RT_HALFLING_2 81 +#define RT_HARPY 111 +#define RT_HARPY_2 527 +#define RT_HIGH_ELF 5 +#define RT_HIPPOGRIFF 186 +#define RT_HOLGRESH 168 +#define RT_HOLGRESH_2 715 +#define RT_HONEY_POT 536 +#define RT_HORSE 216 +#define RT_HORSE_2 492 +#define RT_HORSE_3 518 +#define RT_HOVERING_PLATFORM 699 +#define RT_HRAQUIS 261 +#define RT_HUMAN 1 +#define RT_HUMAN_2 67 +#define RT_HUMAN_3 71 +#define RT_HUMAN_4 566 +#define RT_HUMAN_GHOST 588 +#define RT_HUVUL 400 +#define RT_HYDRA_CRYSTAL 615 +#define RT_HYDRA_MOUNT 631 +#define RT_HYDRA_NPC 632 +#define RT_HYNID 388 +#define RT_ICE_SPECTRE 174 +#define RT_IKAAV 394 +#define RT_IKSAR 128 +#define RT_IKSAR_2 139 +#define RT_IKSAR_GHOST 605 +#define RT_IKSAR_GOLEM 160 +#define RT_IKSAR_SKELETON 606 +#define RT_IKSAR_SPIRIT 147 +#define RT_IMP 46 +#define RT_INNORUUK 123 +#define RT_INSECT 370 +#define RT_INTERACTIVE_OBJECT 2250 +#define RT_INVISIBLE_MAN 127 +#define RT_INVISIBLE_MAN_2 681 +#define RT_INVISIBLE_MAN_3 690 +#define RT_INVISIBLE_MAN_OF_ZOMM 600 +#define RT_IXT 393 +#define RT_JOKESTER 384 +#define RT_JUM_JUM_BUCKET 537 +#define RT_JUNK_BEAST 273 +#define RT_KANGON 689 +#define RT_KANGON_MOUNT 677 +#define RT_KARANA 278 +#define RT_KEDGE 103 +#define RT_KEDGE_2 561 +#define RT_KERRAN 23 +#define RT_KERRAN_2 562 +#define RT_KIRIN 434 +#define RT_KIRIN_2 583 +#define RT_KNIGHT_OF_HATE 351 +#define RT_KNIGHT_OF_PESTILENCE 266 +#define RT_KOBOLD 48 +#define RT_KOBOLD_2 455 +#define RT_KRAKEN 315 +#define RT_KYV 396 +#define RT_LAUNCH 73 +#define RT_LAVA_ROCK 447 +#define RT_LAVA_SPIDER 450 +#define RT_LAVA_SPIDER_QUEEN 451 +#define RT_LEECH 104 +#define RT_LEPERTOLOTH 267 +#define RT_LIGHTCRAWLER 223 +#define RT_LIGHTNING_WARRIOR 407 +#define RT_LION 50 +#define RT_LIZARD_MAN 51 +#define RT_LUCLIN 724 +#define RT_LUGGALD 345 +#define RT_LUGGALD_2 346 +#define RT_LUGGALDS 347 +#define RT_MALARIAN 265 +#define RT_MAMMOTH 107 +#define RT_MAMMOTH_2 528 +#define RT_MAN_EATING_PLANT 162 +#define RT_MANSION 595 +#define RT_MANTICORE 172 +#define RT_MANTRAP 573 +#define RT_MARIONETTE 659 +#define RT_MASTRUQ 402 +#define RT_MATA_MURAM 406 +#define RT_MEDIUM_PLANT 541 +#define RT_MEPHIT 607 +#define RT_MERCHANT_SHIP 550 +#define RT_MERMAID 110 +#define RT_MIMIC 52 +#define RT_MINI_POM 252 +#define RT_MINOTAUR 53 +#define RT_MINOTAUR_2 420 +#define RT_MINOTAUR_3 470 +#define RT_MINOTAUR_4 574 +#define RT_MITHANIEL_MARR 296 +#define RT_MORELL_THULE 658 +#define RT_MOSQUITO 134 +#define RT_MOUTH_OF_INSANITY 281 +#define RT_MUDDITE 608 +#define RT_MUMMY 368 +#define RT_MURAMITE_ARMOR_PILE 424 +#define RT_MURKGLIDER 414 +#define RT_MURKGLIDER_EGG_SAC 429 +#define RT_MUTNA 401 +#define RT_NEKHON 614 +#define RT_NETHERBIAN 229 +#define RT_NIGHTMARE 287 +#define RT_NIGHTMARE_GARGOYLE 280 +#define RT_NIGHTMARE_GOBLIN 277 +#define RT_NIGHTMARE_MEPHIT 294 +#define RT_NIGHTMARE_UNICORN 517 +#define RT_NIGHTMARE_UNICORN_2 519 +#define RT_NIGHTMARE_WRAITH 264 +#define RT_NIHIL 385 +#define RT_NILBORIEN 317 +#define RT_NOC 397 +#define RT_NYMPH 242 +#define RT_OGRE 10 +#define RT_OGRE_2 93 +#define RT_OGRE_NPC_MALE 624 +#define RT_ORB 730 +#define RT_ORC 54 +#define RT_ORC_2 458 +#define RT_OTHMIR 190 +#define RT_OWLBEAR 206 +#define RT_PARASITIC_SCAVENGER 700 +#define RT_PEGASUS 125 +#define RT_PEGASUS_2 493 +#define RT_PEGASUS_3 732 +#define RT_PHOENIX 303 +#define RT_PIRANHA 74 +#define RT_PIRATE 335 +#define RT_PIRATE_2 336 +#define RT_PIRATE_3 337 +#define RT_PIRATE_4 338 +#define RT_PIRATE_5 339 +#define RT_PIRATE_6 340 +#define RT_PIRATE_7 341 +#define RT_PIRATE_8 342 +#define RT_PIRATE_SHIP 551 +#define RT_PIXIE 56 +#define RT_POISON_FROG 316 +#define RT_PORTAL 426 +#define RT_POWDER_KEG 636 +#define RT_PRESSURE_PLATE 506 +#define RT_PUFFER_SPORE 507 +#define RT_PUMA 76 +#define RT_PUMA_2 439 +#define RT_PUMA_3 584 +#define RT_PUSLING 270 +#define RT_PYRILEN 411 +#define RT_RA_TUK 398 +#define RT_RABBIT 668 +#define RT_RALLOS_ZEK 66 +#define RT_RALLOS_ZEK_2 288 +#define RT_RALLOS_ZEK_MINION 325 +#define RT_RAPTOR 163 +#define RT_RAPTOR_2 609 +#define RT_RAPTOR_MOUNT 680 +#define RT_RAT 36 +#define RT_RAT_2 415 +#define RT_RAT_MOUNT 656 +#define RT_RATMAN 156 +#define RT_RATMAN_2 718 +#define RT_REANIMATED_HAND 80 +#define RT_RECUSO 237 +#define RT_REGENERATION_POOL 705 +#define RT_RELIC_CASE 707 +#define RT_RHINO_BEETLE 207 +#define RT_RHINOCEROS 135 +#define RT_ROBOCOPTER_OF_ZOMM 601 +#define RT_ROCK_PILE 428 +#define RT_ROCKHOPPER 200 +#define RT_RONNIE_TEST 197 +#define RT_ROOT_TENTACLE 509 +#define RT_ROT_DOG_MOUNT 672 +#define RT_ROTDOG 662 +#define RT_ROTOCOPTER 577 +#define RT_ROWBOAT 502 +#define RT_ROYAL_GUARD 667 +#define RT_RUJARKIAN_ORC 361 +#define RT_RUJARKIAN_ORC_2 366 +#define RT_RUNED_ORB 422 +#define RT_RUNIC_SYMBOL 510 +#define RT_SABER_TOOTHED_CAT 119 +#define RT_SALTPETTER_BOMB 511 +#define RT_SAND_ELF 364 +#define RT_SANDMAN 664 +#define RT_SARNAK 131 +#define RT_SARNAK_2 610 +#define RT_SARNAK_GOLEM 164 +#define RT_SARNAK_SPIRIT 146 +#define RT_SARYRN 283 +#define RT_SATYR 529 +#define RT_SCALED_WOLF 481 +#define RT_SCARECROW 82 +#define RT_SCARECROW_2 575 +#define RT_SCARLET_CHEETAH 221 +#define RT_SCLERA_MOUNT 675 +#define RT_SCORPION 129 +#define RT_SCORPION_2 149 +#define RT_SCORPION_3 611 +#define RT_SCRYKIN 495 +#define RT_SEA_TURTLE 194 +#define RT_SEAHORSE 116 +#define RT_SELYRAH 686 +#define RT_SELYRAH_MOUNT 674 +#define RT_SERU 236 +#define RT_SERVANT_OF_SHADOW 723 +#define RT_SESSILOID_MOUNT 657 +#define RT_SHADE 224 +#define RT_SHADE_2 373 +#define RT_SHADE_3 576 +#define RT_SHADEL 205 +#define RT_SHAMBLING_MOUND 494 +#define RT_SHARK 61 +#define RT_SHIKNAR 199 +#define RT_SHILISKIN 467 +#define RT_SHIP 72 +#define RT_SHIP_IN_A_BOTTLE 702 +#define RT_SHISSAR 217 +#define RT_SHISSAR_2 563 +#define RT_SHRIEKER 227 +#define RT_SIREN 187 +#define RT_SIREN_2 564 +#define RT_SKELETAL_HORSE 282 +#define RT_SKELETON 60 +#define RT_SKELETON_2 367 +#define RT_SKELETON_3 484 +#define RT_SKUNK 83 +#define RT_SKYSTRIDER 709 +#define RT_SMALL_PLANT 540 +#define RT_SNAKE 37 +#define RT_SNAKE_2 468 +#define RT_SNAKE_ELEMENTAL 84 +#define RT_SNOW_DERVISH 170 +#define RT_SNOW_RABBIT 176 +#define RT_SOKOKAR 618 +#define RT_SOKOKAR_MOUNT 625 +#define RT_SOKOKAR_W_SADDLE 627 +#define RT_SOLUSEK_RO 58 +#define RT_SOLUSEK_RO_2 247 +#define RT_SOLUSEK_RO_GUARD 254 +#define RT_SONIC_WOLF 232 +#define RT_SOUL_DEVOURER 286 +#define RT_SPECTRE 85 +#define RT_SPECTRE_2 485 +#define RT_SPELL_PARTICLE_1 599 +#define RT_SPHINX 86 +#define RT_SPHINX_2 565 +#define RT_SPIDER 38 +#define RT_SPIDER_2 440 +#define RT_SPIDER_EGG_SACK 449 +#define RT_SPIDER_MOUNT 654 +#define RT_SPIDER_QUEEN 441 +#define RT_SPIKE_TRAP 513 +#define RT_SPIRIT_WOLF 483 +#define RT_SPORALI 456 +#define RT_STONE_JUG 539 +#define RT_STONE_PYLON 619 +#define RT_STONE_RING 508 +#define RT_STONE_WORKER 387 +#define RT_STONE_WORKER_2 405 +#define RT_STONEGRABBER 220 +#define RT_STONEMITE 391 +#define RT_STORMRIDER 272 +#define RT_SUCCUBUS 408 +#define RT_SUCCULENT 167 +#define RT_SULLON_ZEK 499 +#define RT_SUN_REVENANT 226 +#define RT_SUNFLOWER 225 +#define RT_SWINETOR 696 +#define RT_SWORDFISH 105 +#define RT_SYNARCANA 363 +#define RT_TABLE 380 +#define RT_TADPOLE 102 +#define RT_TAELOSIAN 403 +#define RT_TALL_PLANT 542 +#define RT_TALLON_ZEK 290 +#define RT_TANETH 399 +#define RT_TAREW_MARR 246 +#define RT_TEGI 215 +#define RT_TELEPORT_MAN 240 +#define RT_TELEPORTATION_STAND 706 +#define RT_TELMIRA 653 +#define RT_TENTACLE_TERROR 68 +#define RT_TENTACLE_TERROR_2 578 +#define RT_TERRIS_THULE 257 +#define RT_TEST_OBJECT 301 +#define RT_THE_RATHE 298 +#define RT_THE_TRIBUNAL 256 +#define RT_THOUGHT_HORROR 214 +#define RT_TIGER 63 +#define RT_TIN_SOLDIER 263 +#define RT_TOOLBOX 538 +#define RT_TOPIARY_LION 661 +#define RT_TOPIARY_LION_MOUNT 671 +#define RT_TORMENTOR 285 +#define RT_TOTEM 173 +#define RT_TOTEM_2 514 +#define RT_TRAKANON 19 +#define RT_TRANQUILION 262 +#define RT_TREANT 64 +#define RT_TREANT_2 244 +#define RT_TREANT_3 496 +#define RT_TRIBUNAL 151 +#define RT_TRIUMVIRATE 697 +#define RT_TROLL 9 +#define RT_TROLL_2 92 +#define RT_TROLL_3 331 +#define RT_TROLL_4 332 +#define RT_TROLL_5 333 +#define RT_TROLL_ZOMBIE 344 +#define RT_TRUSIK 386 +#define RT_TSETSIAN 612 +#define RT_TUMBLEWEED 694 +#define RT_TUNARE 62 +#define RT_TUREPTA 389 +#define RT_UKUN 392 +#define RT_ULTHORK 191 +#define RT_UNDEAD_CHOKIDAI 357 +#define RT_UNDEAD_FOOTMAN 324 +#define RT_UNDEAD_FROGLOK 350 +#define RT_UNDEAD_IKSAR 161 +#define RT_UNDEAD_KNIGHT 297 +#define RT_UNDEAD_SARNAK 155 +#define RT_UNDEAD_VEKSAR 358 +#define RT_UNDERBULK 201 +#define RT_UNICORN 124 +#define RT_UNKNOWN_RACE 0 +#define RT_UNKNOWN_RACE_2 142 +#define RT_UNKNOWN_RACE_3 143 +#define RT_UNKNOWN_RACE_4 179 +#define RT_UNKNOWN_RACE_5 180 +#define RT_UNKNOWN_RACE_6 443 +#define RT_UNKNOWN_RACE_7 444 +#define RT_VAH_SHIR 130 +#define RT_VAH_SHIR_2 238 +#define RT_VAH_SHIR_SKELETON 234 +#define RT_VALLON_ZEK 289 +#define RT_VALORIAN 318 +#define RT_VALORIAN_2 322 +#define RT_VAMPIRE 65 +#define RT_VAMPIRE_2 98 +#define RT_VAMPIRE_3 208 +#define RT_VAMPIRE_4 219 +#define RT_VAMPIRE_5 359 +#define RT_VAMPIRE_6 360 +#define RT_VAMPIRE_7 365 +#define RT_VAMPIRE_8 497 +#define RT_VASE 379 +#define RT_VEGEROG 258 +#define RT_VEKSAR 353 +#define RT_VEKSAR_2 354 +#define RT_VEKSAR_3 355 +#define RT_VENRIL_SATHIR 20 +#define RT_VINE_MAW 717 +#define RT_WAGON 621 +#define RT_WALRUS 177 +#define RT_WAR_BOAR 319 +#define RT_WAR_BOAR_2 321 +#define RT_WAR_WRAITH 313 +#define RT_WASP 109 +#define RT_WATER_ELEMENTAL 211 +#define RT_WATER_ELEMENTAL_2 478 +#define RT_WATER_MEPHIT 271 +#define RT_WATER_SPOUT 710 +#define RT_WEAPON_RACK 381 +#define RT_WEAPON_RACK_2 534 +#define RT_WEB 515 +#define RT_WEDDING_ALTAR 635 +#define RT_WEDDING_ARBOR 634 +#define RT_WEDDING_FLOWERS 633 +#define RT_WEREORC 579 +#define RT_WEREWOLF 14 +#define RT_WEREWOLF_2 241 +#define RT_WEREWOLF_3 454 +#define RT_WETFANG_MINNOW 213 +#define RT_WHIRLIGIG 682 +#define RT_WICKER_BASKET 516 +#define RT_WILL_O_WISP 69 +#define RT_WINE_CASK 543 +#define RT_WINE_CASK_2 630 +#define RT_WITHERAN 465 +#define RT_WITHERAN_2 474 +#define RT_WOLF 42 +#define RT_WOLF_2 120 +#define RT_WOLF_3 482 +#define RT_WOOD_ELF 4 +#define RT_WORG 580 +#define RT_WORG_2 594 +#define RT_WORM 203 +#define RT_WRETCH 235 +#define RT_WRULON 314 +#define RT_WRULON_2 598 +#define RT_WURM 158 +#define RT_WURM_2 613 +#define RT_WURM_MOUNT 679 +#define RT_WYVERN 157 +#define RT_WYVERN_2 581 +#define RT_XALGOZ 136 +#define RT_XARIC_THE_UNSPOKEN 725 +#define RT_XEGONY 299 +#define RT_YAKKAR 181 +#define RT_YETI 138 +#define RT_ZEBUXORUK 295 +#define RT_ZEBUXORUKS_CAGE 328 +#define RT_ZELNIAK 222 +#define RT_ZOMBIE 70 +#define RT_ZOMBIE_2 471 + const char* GetRaceIDName(uint16 race_id); const char* GetPlayerRaceName(uint32 player_race_value); From 68680ac9d819ebe3647fcf4eb5d3fc53ecfc1816 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 5 Feb 2017 02:37:01 -0500 Subject: [PATCH 533/693] Created sub-d for database tools --- .../scripts/{ => database_tools}/spell_effect_token_function.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename utils/scripts/{ => database_tools}/spell_effect_token_function.sql (100%) diff --git a/utils/scripts/spell_effect_token_function.sql b/utils/scripts/database_tools/spell_effect_token_function.sql similarity index 100% rename from utils/scripts/spell_effect_token_function.sql rename to utils/scripts/database_tools/spell_effect_token_function.sql From 1d1382cb12b21533e5da663ee4843b812d051a7b Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 5 Feb 2017 04:32:32 -0500 Subject: [PATCH 534/693] * Added dev script for function to retrieve race id labels from queries [skip ci] --- .../database_tools/race_token_function.sql | 756 ++++++++++++++++++ .../spell_effect_token_function.sql | 2 +- 2 files changed, 757 insertions(+), 1 deletion(-) create mode 100644 utils/scripts/database_tools/race_token_function.sql diff --git a/utils/scripts/database_tools/race_token_function.sql b/utils/scripts/database_tools/race_token_function.sql new file mode 100644 index 000000000..f31fd1177 --- /dev/null +++ b/utils/scripts/database_tools/race_token_function.sql @@ -0,0 +1,756 @@ +DELIMITER $$ + +DROP FUNCTION IF EXISTS `GetRaceToken`; + +-- This function converts a numeric race id to a string label based on server code designations +-- +-- example: +-- SELECT `id`, `name`, GetRaceToken(`race`) FROM `npc_types` WHERE `id` IN ('644', '105153', '261131'); +CREATE FUNCTION `GetRaceToken` (`race_id` INT(11)) RETURNS VARCHAR(64) +BEGIN + DECLARE `token` VARCHAR(64) DEFAULT ''; + + CASE `race_id` + WHEN '0' THEN SET `token` = 'UNKNOWN RACE'; + WHEN '1' THEN SET `token` = 'Human'; + WHEN '2' THEN SET `token` = 'Barbarian'; + WHEN '3' THEN SET `token` = 'Erudite'; + WHEN '4' THEN SET `token` = 'Wood Elf'; + WHEN '5' THEN SET `token` = 'High Elf'; + WHEN '6' THEN SET `token` = 'Dark Elf'; + WHEN '7' THEN SET `token` = 'Half Elf'; + WHEN '8' THEN SET `token` = 'Dwarf'; + WHEN '9' THEN SET `token` = 'Troll'; + WHEN '10' THEN SET `token` = 'Ogre'; + WHEN '11' THEN SET `token` = 'Halfling'; + WHEN '12' THEN SET `token` = 'Gnome'; + WHEN '13' THEN SET `token` = 'Aviak'; + WHEN '14' THEN SET `token` = 'Werewolf'; + WHEN '15' THEN SET `token` = 'Brownie'; + WHEN '16' THEN SET `token` = 'Centaur'; + WHEN '17' THEN SET `token` = 'Golem'; + WHEN '18' THEN SET `token` = 'Giant'; + WHEN '19' THEN SET `token` = 'Trakanon'; + WHEN '20' THEN SET `token` = 'Venril Sathir'; + WHEN '21' THEN SET `token` = 'Evil Eye'; + WHEN '22' THEN SET `token` = 'Beetle'; + WHEN '23' THEN SET `token` = 'Kerran'; + WHEN '24' THEN SET `token` = 'Fish'; + WHEN '25' THEN SET `token` = 'Fairy'; + WHEN '26' THEN SET `token` = 'Froglok'; + WHEN '27' THEN SET `token` = 'Froglok'; + WHEN '28' THEN SET `token` = 'Fungusman'; + WHEN '29' THEN SET `token` = 'Gargoyle'; + WHEN '30' THEN SET `token` = 'Gasbag'; + WHEN '31' THEN SET `token` = 'Gelatinous Cube'; + WHEN '32' THEN SET `token` = 'Ghost'; + WHEN '33' THEN SET `token` = 'Ghoul'; + WHEN '34' THEN SET `token` = 'Bat'; + WHEN '35' THEN SET `token` = 'Eel'; + WHEN '36' THEN SET `token` = 'Rat'; + WHEN '37' THEN SET `token` = 'Snake'; + WHEN '38' THEN SET `token` = 'Spider'; + WHEN '39' THEN SET `token` = 'Gnoll'; + WHEN '40' THEN SET `token` = 'Goblin'; + WHEN '41' THEN SET `token` = 'Gorilla'; + WHEN '42' THEN SET `token` = 'Wolf'; + WHEN '43' THEN SET `token` = 'Bear'; + WHEN '44' THEN SET `token` = 'Guard'; + WHEN '45' THEN SET `token` = 'Demi Lich'; + WHEN '46' THEN SET `token` = 'Imp'; + WHEN '47' THEN SET `token` = 'Griffin'; + WHEN '48' THEN SET `token` = 'Kobold'; + WHEN '49' THEN SET `token` = 'Dragon'; + WHEN '50' THEN SET `token` = 'Lion'; + WHEN '51' THEN SET `token` = 'Lizard Man'; + WHEN '52' THEN SET `token` = 'Mimic'; + WHEN '53' THEN SET `token` = 'Minotaur'; + WHEN '54' THEN SET `token` = 'Orc'; + WHEN '55' THEN SET `token` = 'Beggar'; + WHEN '56' THEN SET `token` = 'Pixie'; + WHEN '57' THEN SET `token` = 'Drachnid'; + WHEN '58' THEN SET `token` = 'Solusek Ro'; + WHEN '59' THEN SET `token` = 'Goblin'; + WHEN '60' THEN SET `token` = 'Skeleton'; + WHEN '61' THEN SET `token` = 'Shark'; + WHEN '62' THEN SET `token` = 'Tunare'; + WHEN '63' THEN SET `token` = 'Tiger'; + WHEN '64' THEN SET `token` = 'Treant'; + WHEN '65' THEN SET `token` = 'Vampire'; + WHEN '66' THEN SET `token` = 'Rallos Zek'; + WHEN '67' THEN SET `token` = 'Human'; + WHEN '68' THEN SET `token` = 'Tentacle Terror'; + WHEN '69' THEN SET `token` = 'Will-O-Wisp'; + WHEN '70' THEN SET `token` = 'Zombie'; + WHEN '71' THEN SET `token` = 'Human'; + WHEN '72' THEN SET `token` = 'Ship'; + WHEN '73' THEN SET `token` = 'Launch'; + WHEN '74' THEN SET `token` = 'Piranha'; + WHEN '75' THEN SET `token` = 'Elemental'; + WHEN '76' THEN SET `token` = 'Puma'; + WHEN '77' THEN SET `token` = 'Dark Elf'; + WHEN '78' THEN SET `token` = 'Erudite'; + WHEN '79' THEN SET `token` = 'Bixie'; + WHEN '80' THEN SET `token` = 'Reanimated Hand'; + WHEN '81' THEN SET `token` = 'Halfling'; + WHEN '82' THEN SET `token` = 'Scarecrow'; + WHEN '83' THEN SET `token` = 'Skunk'; + WHEN '84' THEN SET `token` = 'Snake Elemental'; + WHEN '85' THEN SET `token` = 'Spectre'; + WHEN '86' THEN SET `token` = 'Sphinx'; + WHEN '87' THEN SET `token` = 'Armadillo'; + WHEN '88' THEN SET `token` = 'Clockwork Gnome'; + WHEN '89' THEN SET `token` = 'Drake'; + WHEN '90' THEN SET `token` = 'Barbarian'; + WHEN '91' THEN SET `token` = 'Alligator'; + WHEN '92' THEN SET `token` = 'Troll'; + WHEN '93' THEN SET `token` = 'Ogre'; + WHEN '94' THEN SET `token` = 'Dwarf'; + WHEN '95' THEN SET `token` = 'Cazic Thule'; + WHEN '96' THEN SET `token` = 'Cockatrice'; + WHEN '97' THEN SET `token` = 'Daisy Man'; + WHEN '98' THEN SET `token` = 'Vampire'; + WHEN '99' THEN SET `token` = 'Amygdalan'; + WHEN '100' THEN SET `token` = 'Dervish'; + WHEN '101' THEN SET `token` = 'Efreeti'; + WHEN '102' THEN SET `token` = 'Tadpole'; + WHEN '103' THEN SET `token` = 'Kedge'; + WHEN '104' THEN SET `token` = 'Leech'; + WHEN '105' THEN SET `token` = 'Swordfish'; + WHEN '106' THEN SET `token` = 'Guard'; + WHEN '107' THEN SET `token` = 'Mammoth'; + WHEN '108' THEN SET `token` = 'Eye'; + WHEN '109' THEN SET `token` = 'Wasp'; + WHEN '110' THEN SET `token` = 'Mermaid'; + WHEN '111' THEN SET `token` = 'Harpy'; + WHEN '112' THEN SET `token` = 'Guard'; + WHEN '113' THEN SET `token` = 'Drixie'; + WHEN '114' THEN SET `token` = 'Ghost Ship'; + WHEN '115' THEN SET `token` = 'Clam'; + WHEN '116' THEN SET `token` = 'Seahorse'; + WHEN '117' THEN SET `token` = 'Ghost'; + WHEN '118' THEN SET `token` = 'Ghost'; + WHEN '119' THEN SET `token` = 'Saber-toothed Cat'; + WHEN '120' THEN SET `token` = 'Wolf'; + WHEN '121' THEN SET `token` = 'Gorgon'; + WHEN '122' THEN SET `token` = 'Dragon'; + WHEN '123' THEN SET `token` = 'Innoruuk'; + WHEN '124' THEN SET `token` = 'Unicorn'; + WHEN '125' THEN SET `token` = 'Pegasus'; + WHEN '126' THEN SET `token` = 'Djinn'; + WHEN '127' THEN SET `token` = 'Invisible Man'; + WHEN '128' THEN SET `token` = 'Iksar'; + WHEN '129' THEN SET `token` = 'Scorpion'; + WHEN '130' THEN SET `token` = 'Vah Shir'; + WHEN '131' THEN SET `token` = 'Sarnak'; + WHEN '132' THEN SET `token` = 'Draglock'; + WHEN '133' THEN SET `token` = 'Drolvarg'; + WHEN '134' THEN SET `token` = 'Mosquito'; + WHEN '135' THEN SET `token` = 'Rhinoceros'; + WHEN '136' THEN SET `token` = 'Xalgoz'; + WHEN '137' THEN SET `token` = 'Goblin'; + WHEN '138' THEN SET `token` = 'Yeti'; + WHEN '139' THEN SET `token` = 'Iksar'; + WHEN '140' THEN SET `token` = 'Giant'; + WHEN '141' THEN SET `token` = 'Boat'; + WHEN '142' THEN SET `token` = 'UNKNOWN RACE'; + WHEN '143' THEN SET `token` = 'UNKNOWN RACE'; + WHEN '144' THEN SET `token` = 'Burynai'; + WHEN '145' THEN SET `token` = 'Goo'; + WHEN '146' THEN SET `token` = 'Sarnak Spirit'; + WHEN '147' THEN SET `token` = 'Iksar Spirit'; + WHEN '148' THEN SET `token` = 'Fish'; + WHEN '149' THEN SET `token` = 'Scorpion'; + WHEN '150' THEN SET `token` = 'Erollisi'; + WHEN '151' THEN SET `token` = 'Tribunal'; + WHEN '152' THEN SET `token` = 'Bertoxxulous'; + WHEN '153' THEN SET `token` = 'Bristlebane'; + WHEN '154' THEN SET `token` = 'Fay Drake'; + WHEN '155' THEN SET `token` = 'Undead Sarnak'; + WHEN '156' THEN SET `token` = 'Ratman'; + WHEN '157' THEN SET `token` = 'Wyvern'; + WHEN '158' THEN SET `token` = 'Wurm'; + WHEN '159' THEN SET `token` = 'Devourer'; + WHEN '160' THEN SET `token` = 'Iksar Golem'; + WHEN '161' THEN SET `token` = 'Undead Iksar'; + WHEN '162' THEN SET `token` = 'Man-Eating Plant'; + WHEN '163' THEN SET `token` = 'Raptor'; + WHEN '164' THEN SET `token` = 'Sarnak Golem'; + WHEN '165' THEN SET `token` = 'Dragon'; + WHEN '166' THEN SET `token` = 'Animated Hand'; + WHEN '167' THEN SET `token` = 'Succulent'; + WHEN '168' THEN SET `token` = 'Holgresh'; + WHEN '169' THEN SET `token` = 'Brontotherium'; + WHEN '170' THEN SET `token` = 'Snow Dervish'; + WHEN '171' THEN SET `token` = 'Dire Wolf'; + WHEN '172' THEN SET `token` = 'Manticore'; + WHEN '173' THEN SET `token` = 'Totem'; + WHEN '174' THEN SET `token` = 'Ice Spectre'; + WHEN '175' THEN SET `token` = 'Enchanted Armor'; + WHEN '176' THEN SET `token` = 'Snow Rabbit'; + WHEN '177' THEN SET `token` = 'Walrus'; + WHEN '178' THEN SET `token` = 'Geonid'; + WHEN '179' THEN SET `token` = 'UNKNOWN RACE'; + WHEN '180' THEN SET `token` = 'UNKNOWN RACE'; + WHEN '181' THEN SET `token` = 'Yakkar'; + WHEN '182' THEN SET `token` = 'Faun'; + WHEN '183' THEN SET `token` = 'Coldain'; + WHEN '184' THEN SET `token` = 'Dragon'; + WHEN '185' THEN SET `token` = 'Hag'; + WHEN '186' THEN SET `token` = 'Hippogriff'; + WHEN '187' THEN SET `token` = 'Siren'; + WHEN '188' THEN SET `token` = 'Giant'; + WHEN '189' THEN SET `token` = 'Giant'; + WHEN '190' THEN SET `token` = 'Othmir'; + WHEN '191' THEN SET `token` = 'Ulthork'; + WHEN '192' THEN SET `token` = 'Dragon'; + WHEN '193' THEN SET `token` = 'Abhorrent'; + WHEN '194' THEN SET `token` = 'Sea Turtle'; + WHEN '195' THEN SET `token` = 'Dragon'; + WHEN '196' THEN SET `token` = 'Dragon'; + WHEN '197' THEN SET `token` = 'Ronnie Test'; + WHEN '198' THEN SET `token` = 'Dragon'; + WHEN '199' THEN SET `token` = 'Shik\'Nar'; + WHEN '200' THEN SET `token` = 'Rockhopper'; + WHEN '201' THEN SET `token` = 'Underbulk'; + WHEN '202' THEN SET `token` = 'Grimling'; + WHEN '203' THEN SET `token` = 'Worm'; + WHEN '204' THEN SET `token` = 'Evan Test'; + WHEN '205' THEN SET `token` = 'Shadel'; + WHEN '206' THEN SET `token` = 'Owlbear'; + WHEN '207' THEN SET `token` = 'Rhino Beetle'; + WHEN '208' THEN SET `token` = 'Vampire'; + WHEN '209' THEN SET `token` = 'Earth Elemental'; + WHEN '210' THEN SET `token` = 'Air Elemental'; + WHEN '211' THEN SET `token` = 'Water Elemental'; + WHEN '212' THEN SET `token` = 'Fire Elemental'; + WHEN '213' THEN SET `token` = 'Wetfang Minnow'; + WHEN '214' THEN SET `token` = 'Thought Horror'; + WHEN '215' THEN SET `token` = 'Tegi'; + WHEN '216' THEN SET `token` = 'Horse'; + WHEN '217' THEN SET `token` = 'Shissar'; + WHEN '218' THEN SET `token` = 'Fungal Fiend'; + WHEN '219' THEN SET `token` = 'Vampire'; + WHEN '220' THEN SET `token` = 'Stonegrabber'; + WHEN '221' THEN SET `token` = 'Scarlet Cheetah'; + WHEN '222' THEN SET `token` = 'Zelniak'; + WHEN '223' THEN SET `token` = 'Lightcrawler'; + WHEN '224' THEN SET `token` = 'Shade'; + WHEN '225' THEN SET `token` = 'Sunflower'; + WHEN '226' THEN SET `token` = 'Sun Revenant'; + WHEN '227' THEN SET `token` = 'Shrieker'; + WHEN '228' THEN SET `token` = 'Galorian'; + WHEN '229' THEN SET `token` = 'Netherbian'; + WHEN '230' THEN SET `token` = 'Akheva'; + WHEN '231' THEN SET `token` = 'Grieg Veneficus'; + WHEN '232' THEN SET `token` = 'Sonic Wolf'; + WHEN '233' THEN SET `token` = 'Ground Shaker'; + WHEN '234' THEN SET `token` = 'Vah Shir Skeleton'; + WHEN '235' THEN SET `token` = 'Wretch'; + WHEN '236' THEN SET `token` = 'Seru'; + WHEN '237' THEN SET `token` = 'Recuso'; + WHEN '238' THEN SET `token` = 'Vah Shir'; + WHEN '239' THEN SET `token` = 'Guard'; + WHEN '240' THEN SET `token` = 'Teleport Man'; + WHEN '241' THEN SET `token` = 'Werewolf'; + WHEN '242' THEN SET `token` = 'Nymph'; + WHEN '243' THEN SET `token` = 'Dryad'; + WHEN '244' THEN SET `token` = 'Treant'; + WHEN '245' THEN SET `token` = 'Fly'; + WHEN '246' THEN SET `token` = 'Tarew Marr'; + WHEN '247' THEN SET `token` = 'Solusek Ro'; + WHEN '248' THEN SET `token` = 'Clockwork Golem'; + WHEN '249' THEN SET `token` = 'Clockwork Brain'; + WHEN '250' THEN SET `token` = 'Banshee'; + WHEN '251' THEN SET `token` = 'Guard of Justice'; + WHEN '252' THEN SET `token` = 'Mini POM'; + WHEN '253' THEN SET `token` = 'Diseased Fiend'; + WHEN '254' THEN SET `token` = 'Solusek Ro Guard'; + WHEN '255' THEN SET `token` = 'Bertoxxulous'; + WHEN '256' THEN SET `token` = 'The Tribunal'; + WHEN '257' THEN SET `token` = 'Terris Thule'; + WHEN '258' THEN SET `token` = 'Vegerog'; + WHEN '259' THEN SET `token` = 'Crocodile'; + WHEN '260' THEN SET `token` = 'Bat'; + WHEN '261' THEN SET `token` = 'Hraquis'; + WHEN '262' THEN SET `token` = 'Tranquilion'; + WHEN '263' THEN SET `token` = 'Tin Soldier'; + WHEN '264' THEN SET `token` = 'Nightmare Wraith'; + WHEN '265' THEN SET `token` = 'Malarian'; + WHEN '266' THEN SET `token` = 'Knight of Pestilence'; + WHEN '267' THEN SET `token` = 'Lepertoloth'; + WHEN '268' THEN SET `token` = 'Bubonian'; + WHEN '269' THEN SET `token` = 'Bubonian Underling'; + WHEN '270' THEN SET `token` = 'Pusling'; + WHEN '271' THEN SET `token` = 'Water Mephit'; + WHEN '272' THEN SET `token` = 'Stormrider'; + WHEN '273' THEN SET `token` = 'Junk Beast'; + WHEN '274' THEN SET `token` = 'Broken Clockwork'; + WHEN '275' THEN SET `token` = 'Giant Clockwork'; + WHEN '276' THEN SET `token` = 'Clockwork Beetle'; + WHEN '277' THEN SET `token` = 'Nightmare Goblin'; + WHEN '278' THEN SET `token` = 'Karana'; + WHEN '279' THEN SET `token` = 'Blood Raven'; + WHEN '280' THEN SET `token` = 'Nightmare Gargoyle'; + WHEN '281' THEN SET `token` = 'Mouth of Insanity'; + WHEN '282' THEN SET `token` = 'Skeletal Horse'; + WHEN '283' THEN SET `token` = 'Saryrn'; + WHEN '284' THEN SET `token` = 'Fennin Ro'; + WHEN '285' THEN SET `token` = 'Tormentor'; + WHEN '286' THEN SET `token` = 'Soul Devourer'; + WHEN '287' THEN SET `token` = 'Nightmare'; + WHEN '288' THEN SET `token` = 'Rallos Zek'; + WHEN '289' THEN SET `token` = 'Vallon Zek'; + WHEN '290' THEN SET `token` = 'Tallon Zek'; + WHEN '291' THEN SET `token` = 'Air Mephit'; + WHEN '292' THEN SET `token` = 'Earth Mephit'; + WHEN '293' THEN SET `token` = 'Fire Mephit'; + WHEN '294' THEN SET `token` = 'Nightmare Mephit'; + WHEN '295' THEN SET `token` = 'Zebuxoruk'; + WHEN '296' THEN SET `token` = 'Mithaniel Marr'; + WHEN '297' THEN SET `token` = 'Undead Knight'; + WHEN '298' THEN SET `token` = 'The Rathe'; + WHEN '299' THEN SET `token` = 'Xegony'; + WHEN '300' THEN SET `token` = 'Fiend'; + WHEN '301' THEN SET `token` = 'Test Object'; + WHEN '302' THEN SET `token` = 'Crab'; + WHEN '303' THEN SET `token` = 'Phoenix'; + WHEN '304' THEN SET `token` = 'Dragon'; + WHEN '305' THEN SET `token` = 'Bear'; + WHEN '306' THEN SET `token` = 'Giant'; + WHEN '307' THEN SET `token` = 'Giant'; + WHEN '308' THEN SET `token` = 'Giant'; + WHEN '309' THEN SET `token` = 'Giant'; + WHEN '310' THEN SET `token` = 'Giant'; + WHEN '311' THEN SET `token` = 'Giant'; + WHEN '312' THEN SET `token` = 'Giant'; + WHEN '313' THEN SET `token` = 'War Wraith'; + WHEN '314' THEN SET `token` = 'Wrulon'; + WHEN '315' THEN SET `token` = 'Kraken'; + WHEN '316' THEN SET `token` = 'Poison Frog'; + WHEN '317' THEN SET `token` = 'Nilborien'; + WHEN '318' THEN SET `token` = 'Valorian'; + WHEN '319' THEN SET `token` = 'War Boar'; + WHEN '320' THEN SET `token` = 'Efreeti'; + WHEN '321' THEN SET `token` = 'War Boar'; + WHEN '322' THEN SET `token` = 'Valorian'; + WHEN '323' THEN SET `token` = 'Animated Armor'; + WHEN '324' THEN SET `token` = 'Undead Footman'; + WHEN '325' THEN SET `token` = 'Rallos Zek Minion'; + WHEN '326' THEN SET `token` = 'Arachnid'; + WHEN '327' THEN SET `token` = 'Crystal Spider'; + WHEN '328' THEN SET `token` = 'Zebuxoruk\'s Cage'; + WHEN '329' THEN SET `token` = 'BoT Portal'; + WHEN '330' THEN SET `token` = 'Froglok'; + WHEN '331' THEN SET `token` = 'Troll'; + WHEN '332' THEN SET `token` = 'Troll'; + WHEN '333' THEN SET `token` = 'Troll'; + WHEN '334' THEN SET `token` = 'Ghost'; + WHEN '335' THEN SET `token` = 'Pirate'; + WHEN '336' THEN SET `token` = 'Pirate'; + WHEN '337' THEN SET `token` = 'Pirate'; + WHEN '338' THEN SET `token` = 'Pirate'; + WHEN '339' THEN SET `token` = 'Pirate'; + WHEN '340' THEN SET `token` = 'Pirate'; + WHEN '341' THEN SET `token` = 'Pirate'; + WHEN '342' THEN SET `token` = 'Pirate'; + WHEN '343' THEN SET `token` = 'Frog'; + WHEN '344' THEN SET `token` = 'Troll Zombie'; + WHEN '345' THEN SET `token` = 'Luggald'; + WHEN '346' THEN SET `token` = 'Luggald'; + WHEN '347' THEN SET `token` = 'Luggalds'; + WHEN '348' THEN SET `token` = 'Drogmore'; + WHEN '349' THEN SET `token` = 'Froglok Skeleton'; + WHEN '350' THEN SET `token` = 'Undead Froglok'; + WHEN '351' THEN SET `token` = 'Knight of Hate'; + WHEN '352' THEN SET `token` = 'Arcanist of Hate'; + WHEN '353' THEN SET `token` = 'Veksar'; + WHEN '354' THEN SET `token` = 'Veksar'; + WHEN '355' THEN SET `token` = 'Veksar'; + WHEN '356' THEN SET `token` = 'Chokidai'; + WHEN '357' THEN SET `token` = 'Undead Chokidai'; + WHEN '358' THEN SET `token` = 'Undead Veksar'; + WHEN '359' THEN SET `token` = 'Vampire'; + WHEN '360' THEN SET `token` = 'Vampire'; + WHEN '361' THEN SET `token` = 'Rujarkian Orc'; + WHEN '362' THEN SET `token` = 'Bone Golem'; + WHEN '363' THEN SET `token` = 'Synarcana'; + WHEN '364' THEN SET `token` = 'Sand Elf'; + WHEN '365' THEN SET `token` = 'Vampire'; + WHEN '366' THEN SET `token` = 'Rujarkian Orc'; + WHEN '367' THEN SET `token` = 'Skeleton'; + WHEN '368' THEN SET `token` = 'Mummy'; + WHEN '369' THEN SET `token` = 'Goblin'; + WHEN '370' THEN SET `token` = 'Insect'; + WHEN '371' THEN SET `token` = 'Froglok Ghost'; + WHEN '372' THEN SET `token` = 'Dervish'; + WHEN '373' THEN SET `token` = 'Shade'; + WHEN '374' THEN SET `token` = 'Golem'; + WHEN '375' THEN SET `token` = 'Evil Eye'; + WHEN '376' THEN SET `token` = 'Box'; + WHEN '377' THEN SET `token` = 'Barrel'; + WHEN '378' THEN SET `token` = 'Chest'; + WHEN '379' THEN SET `token` = 'Vase'; + WHEN '380' THEN SET `token` = 'Table'; + WHEN '381' THEN SET `token` = 'Weapon Rack'; + WHEN '382' THEN SET `token` = 'Coffin'; + WHEN '383' THEN SET `token` = 'Bones'; + WHEN '384' THEN SET `token` = 'Jokester'; + WHEN '385' THEN SET `token` = 'Nihil'; + WHEN '386' THEN SET `token` = 'Trusik'; + WHEN '387' THEN SET `token` = 'Stone Worker'; + WHEN '388' THEN SET `token` = 'Hynid'; + WHEN '389' THEN SET `token` = 'Turepta'; + WHEN '390' THEN SET `token` = 'Cragbeast'; + WHEN '391' THEN SET `token` = 'Stonemite'; + WHEN '392' THEN SET `token` = 'Ukun'; + WHEN '393' THEN SET `token` = 'Ixt'; + WHEN '394' THEN SET `token` = 'Ikaav'; + WHEN '395' THEN SET `token` = 'Aneuk'; + WHEN '396' THEN SET `token` = 'Kyv'; + WHEN '397' THEN SET `token` = 'Noc'; + WHEN '398' THEN SET `token` = 'Ra`tuk'; + WHEN '399' THEN SET `token` = 'Taneth'; + WHEN '400' THEN SET `token` = 'Huvul'; + WHEN '401' THEN SET `token` = 'Mutna'; + WHEN '402' THEN SET `token` = 'Mastruq'; + WHEN '403' THEN SET `token` = 'Taelosian'; + WHEN '404' THEN SET `token` = 'Discord Ship'; + WHEN '405' THEN SET `token` = 'Stone Worker'; + WHEN '406' THEN SET `token` = 'Mata Muram'; + WHEN '407' THEN SET `token` = 'Lightning Warrior'; + WHEN '408' THEN SET `token` = 'Succubus'; + WHEN '409' THEN SET `token` = 'Bazu'; + WHEN '410' THEN SET `token` = 'Feran'; + WHEN '411' THEN SET `token` = 'Pyrilen'; + WHEN '412' THEN SET `token` = 'Chimera'; + WHEN '413' THEN SET `token` = 'Dragorn'; + WHEN '414' THEN SET `token` = 'Murkglider'; + WHEN '415' THEN SET `token` = 'Rat'; + WHEN '416' THEN SET `token` = 'Bat'; + WHEN '417' THEN SET `token` = 'Gelidran'; + WHEN '418' THEN SET `token` = 'Discordling'; + WHEN '419' THEN SET `token` = 'Girplan'; + WHEN '420' THEN SET `token` = 'Minotaur'; + WHEN '421' THEN SET `token` = 'Dragorn Box'; + WHEN '422' THEN SET `token` = 'Runed Orb'; + WHEN '423' THEN SET `token` = 'Dragon Bones'; + WHEN '424' THEN SET `token` = 'Muramite Armor Pile'; + WHEN '425' THEN SET `token` = 'Crystal Shard'; + WHEN '426' THEN SET `token` = 'Portal'; + WHEN '427' THEN SET `token` = 'Coin Purse'; + WHEN '428' THEN SET `token` = 'Rock Pile'; + WHEN '429' THEN SET `token` = 'Murkglider Egg Sac'; + WHEN '430' THEN SET `token` = 'Drake'; + WHEN '431' THEN SET `token` = 'Dervish'; + WHEN '432' THEN SET `token` = 'Drake'; + WHEN '433' THEN SET `token` = 'Goblin'; + WHEN '434' THEN SET `token` = 'Kirin'; + WHEN '435' THEN SET `token` = 'Dragon'; + WHEN '436' THEN SET `token` = 'Basilisk'; + WHEN '437' THEN SET `token` = 'Dragon'; + WHEN '438' THEN SET `token` = 'Dragon'; + WHEN '439' THEN SET `token` = 'Puma'; + WHEN '440' THEN SET `token` = 'Spider'; + WHEN '441' THEN SET `token` = 'Spider Queen'; + WHEN '442' THEN SET `token` = 'Animated Statue'; + WHEN '443' THEN SET `token` = 'UNKNOWN RACE'; + WHEN '444' THEN SET `token` = 'UNKNOWN RACE'; + WHEN '445' THEN SET `token` = 'Dragon Egg'; + WHEN '446' THEN SET `token` = 'Dragon Statue'; + WHEN '447' THEN SET `token` = 'Lava Rock'; + WHEN '448' THEN SET `token` = 'Animated Statue'; + WHEN '449' THEN SET `token` = 'Spider Egg Sack'; + WHEN '450' THEN SET `token` = 'Lava Spider'; + WHEN '451' THEN SET `token` = 'Lava Spider Queen'; + WHEN '452' THEN SET `token` = 'Dragon'; + WHEN '453' THEN SET `token` = 'Giant'; + WHEN '454' THEN SET `token` = 'Werewolf'; + WHEN '455' THEN SET `token` = 'Kobold'; + WHEN '456' THEN SET `token` = 'Sporali'; + WHEN '457' THEN SET `token` = 'Gnomework'; + WHEN '458' THEN SET `token` = 'Orc'; + WHEN '459' THEN SET `token` = 'Corathus'; + WHEN '460' THEN SET `token` = 'Coral'; + WHEN '461' THEN SET `token` = 'Drachnid'; + WHEN '462' THEN SET `token` = 'Drachnid Cocoon'; + WHEN '463' THEN SET `token` = 'Fungus Patch'; + WHEN '464' THEN SET `token` = 'Gargoyle'; + WHEN '465' THEN SET `token` = 'Witheran'; + WHEN '466' THEN SET `token` = 'Dark Lord'; + WHEN '467' THEN SET `token` = 'Shiliskin'; + WHEN '468' THEN SET `token` = 'Snake'; + WHEN '469' THEN SET `token` = 'Evil Eye'; + WHEN '470' THEN SET `token` = 'Minotaur'; + WHEN '471' THEN SET `token` = 'Zombie'; + WHEN '472' THEN SET `token` = 'Clockwork Boar'; + WHEN '473' THEN SET `token` = 'Fairy'; + WHEN '474' THEN SET `token` = 'Witheran'; + WHEN '475' THEN SET `token` = 'Air Elemental'; + WHEN '476' THEN SET `token` = 'Earth Elemental'; + WHEN '477' THEN SET `token` = 'Fire Elemental'; + WHEN '478' THEN SET `token` = 'Water Elemental'; + WHEN '479' THEN SET `token` = 'Alligator'; + WHEN '480' THEN SET `token` = 'Bear'; + WHEN '481' THEN SET `token` = 'Scaled Wolf'; + WHEN '482' THEN SET `token` = 'Wolf'; + WHEN '483' THEN SET `token` = 'Spirit Wolf'; + WHEN '484' THEN SET `token` = 'Skeleton'; + WHEN '485' THEN SET `token` = 'Spectre'; + WHEN '486' THEN SET `token` = 'Bolvirk'; + WHEN '487' THEN SET `token` = 'Banshee'; + WHEN '488' THEN SET `token` = 'Banshee'; + WHEN '489' THEN SET `token` = 'Elddar'; + WHEN '490' THEN SET `token` = 'Forest Giant'; + WHEN '491' THEN SET `token` = 'Bone Golem'; + WHEN '492' THEN SET `token` = 'Horse'; + WHEN '493' THEN SET `token` = 'Pegasus'; + WHEN '494' THEN SET `token` = 'Shambling Mound'; + WHEN '495' THEN SET `token` = 'Scrykin'; + WHEN '496' THEN SET `token` = 'Treant'; + WHEN '497' THEN SET `token` = 'Vampire'; + WHEN '498' THEN SET `token` = 'Ayonae Ro'; + WHEN '499' THEN SET `token` = 'Sullon Zek'; + WHEN '500' THEN SET `token` = 'Banner'; + WHEN '501' THEN SET `token` = 'Flag'; + WHEN '502' THEN SET `token` = 'Rowboat'; + WHEN '503' THEN SET `token` = 'Bear Trap'; + WHEN '504' THEN SET `token` = 'Clockwork Bomb'; + WHEN '505' THEN SET `token` = 'Dynamite Keg'; + WHEN '506' THEN SET `token` = 'Pressure Plate'; + WHEN '507' THEN SET `token` = 'Puffer Spore'; + WHEN '508' THEN SET `token` = 'Stone Ring'; + WHEN '509' THEN SET `token` = 'Root Tentacle'; + WHEN '510' THEN SET `token` = 'Runic Symbol'; + WHEN '511' THEN SET `token` = 'Saltpetter Bomb'; + WHEN '512' THEN SET `token` = 'Floating Skull'; + WHEN '513' THEN SET `token` = 'Spike Trap'; + WHEN '514' THEN SET `token` = 'Totem'; + WHEN '515' THEN SET `token` = 'Web'; + WHEN '516' THEN SET `token` = 'Wicker Basket'; + WHEN '517' THEN SET `token` = 'Nightmare/Unicorn'; + WHEN '518' THEN SET `token` = 'Horse'; + WHEN '519' THEN SET `token` = 'Nightmare/Unicorn'; + WHEN '520' THEN SET `token` = 'Bixie'; + WHEN '521' THEN SET `token` = 'Centaur'; + WHEN '522' THEN SET `token` = 'Drakkin'; + WHEN '523' THEN SET `token` = 'Giant'; + WHEN '524' THEN SET `token` = 'Gnoll'; + WHEN '525' THEN SET `token` = 'Griffin'; + WHEN '526' THEN SET `token` = 'Giant Shade'; + WHEN '527' THEN SET `token` = 'Harpy'; + WHEN '528' THEN SET `token` = 'Mammoth'; + WHEN '529' THEN SET `token` = 'Satyr'; + WHEN '530' THEN SET `token` = 'Dragon'; + WHEN '531' THEN SET `token` = 'Dragon'; + WHEN '532' THEN SET `token` = 'Dyn\'Leth'; + WHEN '533' THEN SET `token` = 'Boat'; + WHEN '534' THEN SET `token` = 'Weapon Rack'; + WHEN '535' THEN SET `token` = 'Armor Rack'; + WHEN '536' THEN SET `token` = 'Honey Pot'; + WHEN '537' THEN SET `token` = 'Jum Jum Bucket'; + WHEN '538' THEN SET `token` = 'Toolbox'; + WHEN '539' THEN SET `token` = 'Stone Jug'; + WHEN '540' THEN SET `token` = 'Small Plant'; + WHEN '541' THEN SET `token` = 'Medium Plant'; + WHEN '542' THEN SET `token` = 'Tall Plant'; + WHEN '543' THEN SET `token` = 'Wine Cask'; + WHEN '544' THEN SET `token` = 'Elven Boat'; + WHEN '545' THEN SET `token` = 'Gnomish Boat'; + WHEN '546' THEN SET `token` = 'Barrel Barge Ship'; + WHEN '547' THEN SET `token` = 'Goo'; + WHEN '548' THEN SET `token` = 'Goo'; + WHEN '549' THEN SET `token` = 'Goo'; + WHEN '550' THEN SET `token` = 'Merchant Ship'; + WHEN '551' THEN SET `token` = 'Pirate Ship'; + WHEN '552' THEN SET `token` = 'Ghost Ship'; + WHEN '553' THEN SET `token` = 'Banner'; + WHEN '554' THEN SET `token` = 'Banner'; + WHEN '555' THEN SET `token` = 'Banner'; + WHEN '556' THEN SET `token` = 'Banner'; + WHEN '557' THEN SET `token` = 'Banner'; + WHEN '558' THEN SET `token` = 'Aviak'; + WHEN '559' THEN SET `token` = 'Beetle'; + WHEN '560' THEN SET `token` = 'Gorilla'; + WHEN '561' THEN SET `token` = 'Kedge'; + WHEN '562' THEN SET `token` = 'Kerran'; + WHEN '563' THEN SET `token` = 'Shissar'; + WHEN '564' THEN SET `token` = 'Siren'; + WHEN '565' THEN SET `token` = 'Sphinx'; + WHEN '566' THEN SET `token` = 'Human'; + WHEN '567' THEN SET `token` = 'Campfire'; + WHEN '568' THEN SET `token` = 'Brownie'; + WHEN '569' THEN SET `token` = 'Dragon'; + WHEN '570' THEN SET `token` = 'Exoskeleton'; + WHEN '571' THEN SET `token` = 'Ghoul'; + WHEN '572' THEN SET `token` = 'Clockwork Guardian'; + WHEN '573' THEN SET `token` = 'Mantrap'; + WHEN '574' THEN SET `token` = 'Minotaur'; + WHEN '575' THEN SET `token` = 'Scarecrow'; + WHEN '576' THEN SET `token` = 'Shade'; + WHEN '577' THEN SET `token` = 'Rotocopter'; + WHEN '578' THEN SET `token` = 'Tentacle Terror'; + WHEN '579' THEN SET `token` = 'Wereorc'; + WHEN '580' THEN SET `token` = 'Worg'; + WHEN '581' THEN SET `token` = 'Wyvern'; + WHEN '582' THEN SET `token` = 'Chimera'; + WHEN '583' THEN SET `token` = 'Kirin'; + WHEN '584' THEN SET `token` = 'Puma'; + WHEN '585' THEN SET `token` = 'Boulder'; + WHEN '586' THEN SET `token` = 'Banner'; + WHEN '587' THEN SET `token` = 'Elven Ghost'; + WHEN '588' THEN SET `token` = 'Human Ghost'; + WHEN '589' THEN SET `token` = 'Chest'; + WHEN '590' THEN SET `token` = 'Chest'; + WHEN '591' THEN SET `token` = 'Crystal'; + WHEN '592' THEN SET `token` = 'Coffin'; + WHEN '593' THEN SET `token` = 'Guardian CPU'; + WHEN '594' THEN SET `token` = 'Worg'; + WHEN '595' THEN SET `token` = 'Mansion'; + WHEN '596' THEN SET `token` = 'Floating Island'; + WHEN '597' THEN SET `token` = 'Cragslither'; + WHEN '598' THEN SET `token` = 'Wrulon'; + WHEN '599' THEN SET `token` = 'Spell Particle 1'; + WHEN '600' THEN SET `token` = 'Invisible Man of Zomm'; + WHEN '601' THEN SET `token` = 'Robocopter of Zomm'; + WHEN '602' THEN SET `token` = 'Burynai'; + WHEN '603' THEN SET `token` = 'Frog'; + WHEN '604' THEN SET `token` = 'Dracolich'; + WHEN '605' THEN SET `token` = 'Iksar Ghost'; + WHEN '606' THEN SET `token` = 'Iksar Skeleton'; + WHEN '607' THEN SET `token` = 'Mephit'; + WHEN '608' THEN SET `token` = 'Muddite'; + WHEN '609' THEN SET `token` = 'Raptor'; + WHEN '610' THEN SET `token` = 'Sarnak'; + WHEN '611' THEN SET `token` = 'Scorpion'; + WHEN '612' THEN SET `token` = 'T THEN SET sian'; + WHEN '613' THEN SET `token` = 'Wurm'; + WHEN '614' THEN SET `token` = 'Nekhon'; + WHEN '615' THEN SET `token` = 'Hydra Crystal'; + WHEN '616' THEN SET `token` = 'Crystal Sphere'; + WHEN '617' THEN SET `token` = 'Gnoll'; + WHEN '618' THEN SET `token` = 'Sokokar'; + WHEN '619' THEN SET `token` = 'Stone Pylon'; + WHEN '620' THEN SET `token` = 'Demon Vulture'; + WHEN '621' THEN SET `token` = 'Wagon'; + WHEN '622' THEN SET `token` = 'God of Discord'; + WHEN '623' THEN SET `token` = 'Feran Mount'; + WHEN '624' THEN SET `token` = 'Ogre NPC - Male'; + WHEN '625' THEN SET `token` = 'Sokokar Mount'; + WHEN '626' THEN SET `token` = 'Giant (Rallosian mats)'; + WHEN '627' THEN SET `token` = 'Sokokar (w saddle)'; + WHEN '628' THEN SET `token` = '10th Anniversary Banner'; + WHEN '629' THEN SET `token` = '10th Anniversary Cake'; + WHEN '630' THEN SET `token` = 'Wine Cask'; + WHEN '631' THEN SET `token` = 'Hydra Mount'; + WHEN '632' THEN SET `token` = 'Hydra NPC'; + WHEN '633' THEN SET `token` = 'Wedding Flowers'; + WHEN '634' THEN SET `token` = 'Wedding Arbor'; + WHEN '635' THEN SET `token` = 'Wedding Altar'; + WHEN '636' THEN SET `token` = 'Powder Keg'; + WHEN '637' THEN SET `token` = 'Apexus'; + WHEN '638' THEN SET `token` = 'Bellikos'; + WHEN '639' THEN SET `token` = 'Brell\'s First Creation'; + WHEN '640' THEN SET `token` = 'Brell'; + WHEN '641' THEN SET `token` = 'Crystalskin Ambuloid'; + WHEN '642' THEN SET `token` = 'Cliknar Queen'; + WHEN '643' THEN SET `token` = 'Cliknar Soldier'; + WHEN '644' THEN SET `token` = 'Cliknar Worker'; + WHEN '645' THEN SET `token` = 'Coldain'; + WHEN '646' THEN SET `token` = 'Coldain'; + WHEN '647' THEN SET `token` = 'Crystalskin Sessiloid'; + WHEN '648' THEN SET `token` = 'Genari'; + WHEN '649' THEN SET `token` = 'Gigyn'; + WHEN '650' THEN SET `token` = 'Greken - Young Adult'; + WHEN '651' THEN SET `token` = 'Greken - Young'; + WHEN '652' THEN SET `token` = 'Cliknar Mount'; + WHEN '653' THEN SET `token` = 'Telmira'; + WHEN '654' THEN SET `token` = 'Spider Mount'; + WHEN '655' THEN SET `token` = 'Bear Mount'; + WHEN '656' THEN SET `token` = 'Rat Mount'; + WHEN '657' THEN SET `token` = 'Sessiloid Mount'; + WHEN '658' THEN SET `token` = 'Morell Thule'; + WHEN '659' THEN SET `token` = 'Marionette'; + WHEN '660' THEN SET `token` = 'Book Dervish'; + WHEN '661' THEN SET `token` = 'Topiary Lion'; + WHEN '662' THEN SET `token` = 'Rotdog'; + WHEN '663' THEN SET `token` = 'Amygdalan'; + WHEN '664' THEN SET `token` = 'Sandman'; + WHEN '665' THEN SET `token` = 'Grandfather Clock'; + WHEN '666' THEN SET `token` = 'Gingerbread Man'; + WHEN '667' THEN SET `token` = 'Royal Guard'; + WHEN '668' THEN SET `token` = 'Rabbit'; + WHEN '669' THEN SET `token` = 'Blind Dreamer'; + WHEN '670' THEN SET `token` = 'Cazic Thule'; + WHEN '671' THEN SET `token` = 'Topiary Lion Mount'; + WHEN '672' THEN SET `token` = 'Rot Dog Mount'; + WHEN '673' THEN SET `token` = 'Goral Mount'; + WHEN '674' THEN SET `token` = 'Selyrah Mount'; + WHEN '675' THEN SET `token` = 'Sclera Mount'; + WHEN '676' THEN SET `token` = 'Braxi Mount'; + WHEN '677' THEN SET `token` = 'Kangon Mount'; + WHEN '678' THEN SET `token` = 'Erudite'; + WHEN '679' THEN SET `token` = 'Wurm Mount'; + WHEN '680' THEN SET `token` = 'Raptor Mount'; + WHEN '681' THEN SET `token` = 'Invisible Man'; + WHEN '682' THEN SET `token` = 'Whirligig'; + WHEN '683' THEN SET `token` = 'Gnomish Balloon'; + WHEN '684' THEN SET `token` = 'Gnomish Rocket Pack'; + WHEN '685' THEN SET `token` = 'Gnomish Hovering Transport'; + WHEN '686' THEN SET `token` = 'Selyrah'; + WHEN '687' THEN SET `token` = 'Goral'; + WHEN '688' THEN SET `token` = 'Braxi'; + WHEN '689' THEN SET `token` = 'Kangon'; + WHEN '690' THEN SET `token` = 'Invisible Man'; + WHEN '691' THEN SET `token` = 'Floating Tower'; + WHEN '692' THEN SET `token` = 'Explosive Cart'; + WHEN '693' THEN SET `token` = 'Blimp Ship'; + WHEN '694' THEN SET `token` = 'Tumbleweed'; + WHEN '695' THEN SET `token` = 'Alaran'; + WHEN '696' THEN SET `token` = 'Swinetor'; + WHEN '697' THEN SET `token` = 'Triumvirate'; + WHEN '698' THEN SET `token` = 'Hadal'; + WHEN '699' THEN SET `token` = 'Hovering Platform'; + WHEN '700' THEN SET `token` = 'Parasitic Scavenger'; + WHEN '701' THEN SET `token` = 'Grendlaen'; + WHEN '702' THEN SET `token` = 'Ship in a Bottle'; + WHEN '703' THEN SET `token` = 'Alaran Sentry Stone'; + WHEN '704' THEN SET `token` = 'Dervish'; + WHEN '705' THEN SET `token` = 'Regeneration Pool'; + WHEN '706' THEN SET `token` = 'Teleportation Stand'; + WHEN '707' THEN SET `token` = 'Relic Case'; + WHEN '708' THEN SET `token` = 'Alaran Ghost'; + WHEN '709' THEN SET `token` = 'Skystrider'; + WHEN '710' THEN SET `token` = 'Water Spout'; + WHEN '711' THEN SET `token` = 'Aviak Pull Along'; + WHEN '712' THEN SET `token` = 'Gelatinous Cube'; + WHEN '713' THEN SET `token` = 'Cat'; + WHEN '714' THEN SET `token` = 'Elk Head'; + WHEN '715' THEN SET `token` = 'Holgresh'; + WHEN '716' THEN SET `token` = 'Beetle'; + WHEN '717' THEN SET `token` = 'Vine Maw'; + WHEN '718' THEN SET `token` = 'Ratman'; + WHEN '719' THEN SET `token` = 'Fallen Knight'; + WHEN '720' THEN SET `token` = 'Flying Carpet'; + WHEN '721' THEN SET `token` = 'Carrier Hand'; + WHEN '722' THEN SET `token` = 'Akheva'; + WHEN '723' THEN SET `token` = 'Servant of Shadow'; + WHEN '724' THEN SET `token` = 'Luclin'; + WHEN '725' THEN SET `token` = 'Xaric the Unspoken'; + WHEN '726' THEN SET `token` = 'Dervish (Ver. 5)'; + WHEN '727' THEN SET `token` = 'Dervish (Ver. 6)'; + WHEN '728' THEN SET `token` = 'God - Luclin (Ver. 2)'; + WHEN '729' THEN SET `token` = 'God - Luclin (Ver. 3)'; + WHEN '730' THEN SET `token` = 'Orb'; + WHEN '731' THEN SET `token` = 'God - Luclin (Ver. 4)'; + WHEN '732' THEN SET `token` = 'Pegasus'; + WHEN '2250' THEN SET `token` = 'Interactive Object'; + ELSE SET `token` = 'unk'; + END CASE; + + SET `token` = CONCAT(`token`, '(', `race_id`, ')'); + + RETURN `token`; +END$$ + +DELIMITER ; diff --git a/utils/scripts/database_tools/spell_effect_token_function.sql b/utils/scripts/database_tools/spell_effect_token_function.sql index 38cba8ed0..24efc9cc8 100644 --- a/utils/scripts/database_tools/spell_effect_token_function.sql +++ b/utils/scripts/database_tools/spell_effect_token_function.sql @@ -516,4 +516,4 @@ BEGIN RETURN `token`; END$$ -DELIMITER ; \ No newline at end of file +DELIMITER ; From f8f783fa462ae2d1c2350bcd076252b9e5d81ea1 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 5 Feb 2017 05:01:51 -0500 Subject: [PATCH 535/693] Added dev script for function to retrieve spell target type labels for spells from queries [skip ci] --- .../spell_target_type_token_function.sql | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 utils/scripts/database_tools/spell_target_type_token_function.sql diff --git a/utils/scripts/database_tools/spell_target_type_token_function.sql b/utils/scripts/database_tools/spell_target_type_token_function.sql new file mode 100644 index 000000000..6d891ba5f --- /dev/null +++ b/utils/scripts/database_tools/spell_target_type_token_function.sql @@ -0,0 +1,59 @@ +DELIMITER $$ + +DROP FUNCTION IF EXISTS `GetSpellTargetTypeToken`; + +-- This function converts a numeric spell target type to a string label based on server code designations +-- Note: `cast_restriction` look-up is not implemented at this time +-- +-- example: +-- SELECT `id`, `name`, GetSpellTargetTypeToken(`targettype`, `CastRestriction`) FROM `spells_new` WHERE `id` IN ('6836', '10763', '30057'); +CREATE FUNCTION `GetSpellTargetTypeToken` (`target_type` INT(11), `cast_restriction` INT(11)) RETURNS VARCHAR(64) +BEGIN + DECLARE `token` VARCHAR(64) DEFAULT ''; + + CASE `target_type` + WHEN '1' THEN SET `token` = 'ST_TargetOptional'; + WHEN '2' THEN SET `token` = 'ST_AEClientV1'; + WHEN '3' THEN SET `token` = 'ST_GroupTeleport'; + WHEN '4' THEN SET `token` = 'ST_AECaster'; + WHEN '5' THEN SET `token` = 'ST_Target'; + WHEN '6' THEN SET `token` = 'ST_Self'; + WHEN '8' THEN SET `token` = 'ST_AETarget'; + WHEN '9' THEN SET `token` = 'ST_Animal'; + WHEN '10' THEN SET `token` = 'ST_Undead'; + WHEN '11' THEN SET `token` = 'ST_Summoned'; + WHEN '13' THEN SET `token` = 'ST_Tap'; + WHEN '14' THEN SET `token` = 'ST_Pet'; + WHEN '15' THEN SET `token` = 'ST_Corpse'; + WHEN '16' THEN SET `token` = 'ST_Plant'; + WHEN '17' THEN SET `token` = 'ST_Giant'; + WHEN '18' THEN SET `token` = 'ST_Dragon'; + WHEN '20' THEN SET `token` = 'ST_TargetAETap'; + WHEN '24' THEN SET `token` = 'ST_UndeadAE'; + WHEN '25' THEN SET `token` = 'ST_SummonedAE'; + WHEN '32' THEN SET `token` = 'ST_AETargetHateList'; + WHEN '33' THEN SET `token` = 'ST_HateList'; + WHEN '34' THEN SET `token` = 'ST_LDoNChest_Cursed'; + WHEN '35' THEN SET `token` = 'ST_Muramite'; + WHEN '36' THEN SET `token` = 'ST_AreaClientOnly'; + WHEN '37' THEN SET `token` = 'ST_AreaNPCOnly'; + WHEN '38' THEN SET `token` = 'ST_SummonedPet'; + WHEN '39' THEN SET `token` = 'ST_GroupNoPets'; + WHEN '40' THEN SET `token` = 'ST_AEBard'; + WHEN '41' THEN SET `token` = 'ST_Group'; + WHEN '42' THEN SET `token` = 'ST_Directional'; + WHEN '43' THEN SET `token` = 'ST_GroupClientAndPet'; + WHEN '44' THEN SET `token` = 'ST_Beam'; + WHEN '45' THEN SET `token` = 'ST_Ring'; + WHEN '46' THEN SET `token` = 'ST_TargetsTarget'; + WHEN '47' THEN SET `token` = 'ST_PetMaster'; + WHEN '50' THEN SET `token` = 'ST_TargetAENoPlayersPets'; + ELSE SET `token` = 'unk'; + END CASE; + + SET `token` = CONCAT(`token`, '(', `target_type`, ')', '->(', `cast_restriction`, ')'); + + RETURN `token`; +END$$ + +DELIMITER ; From 409dc3ad35fa712556d813b2f63dfa320626dfd3 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 5 Feb 2017 07:56:37 -0500 Subject: [PATCH 536/693] Added dev script for function to retrieve body type labels from queries [skip ci] --- .../body_type_token_function.sql | 57 +++++++++++++++++++ .../spell_effect_token_function.sql | 2 +- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 utils/scripts/database_tools/body_type_token_function.sql diff --git a/utils/scripts/database_tools/body_type_token_function.sql b/utils/scripts/database_tools/body_type_token_function.sql new file mode 100644 index 000000000..2482e0b4a --- /dev/null +++ b/utils/scripts/database_tools/body_type_token_function.sql @@ -0,0 +1,57 @@ +DELIMITER $$ + +DROP FUNCTION IF EXISTS `GetBodyTypeToken`; + +-- This function converts a numeric body type to a string label based on server code designations +-- Note: A preceeding '*' indicates a non-client verified token +-- +-- example: +-- SELECT `id`, `name`, GetBodyTypeToken(`bodytype`) FROM `npc_types` WHERE `id` IN ('116539', '154086', '164042'); +CREATE FUNCTION `GetBodyTypeToken` (`body_type` INT(11)) RETURNS VARCHAR(64) +BEGIN + DECLARE `token` VARCHAR(64) DEFAULT ''; + + CASE `body_type` + WHEN '1' THEN SET `token` = 'BT_Humanoid'; + WHEN '2' THEN SET `token` = 'BT_Lycanthrope'; + WHEN '3' THEN SET `token` = 'BT_Undead'; + WHEN '4' THEN SET `token` = 'BT_Giant'; + WHEN '5' THEN SET `token` = 'BT_Construct'; + WHEN '6' THEN SET `token` = 'BT_Extraplanar'; + WHEN '7' THEN SET `token` = 'BT_Magical'; + WHEN '8' THEN SET `token` = '*BT_SummonedUndead'; + WHEN '9' THEN SET `token` = '*BT_RaidGiant'; + WHEN '11' THEN SET `token` = '*BT_NoTarget'; + WHEN '12' THEN SET `token` = 'BT_Vampyre'; + WHEN '13' THEN SET `token` = 'BT_Atenha_Ra'; + WHEN '14' THEN SET `token` = 'BT_Greater_Akheva'; + WHEN '15' THEN SET `token` = 'BT_Khati_Sha'; + WHEN '16' THEN SET `token` = '*BT_Seru'; + WHEN '18' THEN SET `token` = 'BT_Draz_Nurakk'; + WHEN '19' THEN SET `token` = 'BT_Zek'; + WHEN '20' THEN SET `token` = 'BT_Luggald'; + WHEN '21' THEN SET `token` = 'BT_Animal'; + WHEN '22' THEN SET `token` = 'BT_Insect'; + WHEN '23' THEN SET `token` = 'BT_Monster'; + WHEN '24' THEN SET `token` = 'BT_Elemental/*BT_Summoned'; + WHEN '25' THEN SET `token` = 'BT_Plant'; + WHEN '26' THEN SET `token` = 'BT_Dragon'; + WHEN '27' THEN SET `token` = '*BT_Summoned2'; + WHEN '28' THEN SET `token` = 'BT_Summoned_Creature/*BT_Summoned3'; + WHEN '30' THEN SET `token` = '*BT_VeliousDragon'; + WHEN '32' THEN SET `token` = '*BT_Dragon3'; + WHEN '33' THEN SET `token` = '*BT_Boxes'; + WHEN '34' THEN SET `token` = 'BT_Muramite'; + WHEN '60' THEN SET `token` = '*BT_NoTarget2'; + WHEN '63' THEN SET `token` = '*BT_SwarmPet'; + WHEN '66' THEN SET `token` = '*BT_InvisMan'; + WHEN '67' THEN SET `token` = '*BT_Special'; + ELSE SET `token` = 'BT_UNKNOWN_BODYTYPE'; + END CASE; + + SET `token` = CONCAT(`token`, '(', `body_type`, ')'); + + RETURN `token`; +END$$ + +DELIMITER ; diff --git a/utils/scripts/database_tools/spell_effect_token_function.sql b/utils/scripts/database_tools/spell_effect_token_function.sql index 24efc9cc8..5208914dd 100644 --- a/utils/scripts/database_tools/spell_effect_token_function.sql +++ b/utils/scripts/database_tools/spell_effect_token_function.sql @@ -5,7 +5,7 @@ DROP FUNCTION IF EXISTS `GetSpellEffectToken`; -- This function converts a numeric spell effect id to a string label based on server code designations -- -- example: --- SELECT `id`, `name`, GetSpellEffectToken(`effectid1`), GetSpellEffectToken(`effectid2`) FROM `spells_new` WHERE `id` IN ('1011', '1602'); +-- SELECT `id`, `name`, GetSpellEffectToken(`effectid1`), GetSpellEffectToken(`effectid2`) FROM `spells_new` WHERE `id` IN ('1011', '1602', '11091'); CREATE FUNCTION `GetSpellEffectToken` (`effect_id` INT(11)) RETURNS VARCHAR(64) BEGIN DECLARE `token` VARCHAR(64) DEFAULT ''; From 592f9a9cb915e11307befdbeab8d744b829f7822 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 5 Feb 2017 13:44:04 -0500 Subject: [PATCH 537/693] Add rule to allow non-PC pet NPCs to crit NPCs can't crit at all ever on live --- common/ruletypes.h | 1 + zone/attack.cpp | 17 +++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 21c4949ea..5323fda49 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -398,6 +398,7 @@ RULE_INT(Combat, NPCBashKickStunChance, 15) //Percent chance that a bash/kick wi RULE_INT(Combat, MeleeCritDifficulty, 8900) // lower is easier RULE_INT(Combat, ArcheryCritDifficulty, 3400) // lower is easier RULE_INT(Combat, ThrowingCritDifficulty, 1100) // lower is easier +RULE_BOOL(Combat, NPCCanCrit, false) // true allows non PC pet NPCs to crit RULE_BOOL(Combat, UseIntervalAC, true) RULE_INT(Combat, PetAttackMagicLevel, 30) RULE_BOOL(Combat, EnableFearPathing, true) diff --git a/zone/attack.cpp b/zone/attack.cpp index c05be46cb..1ebf2a352 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3953,6 +3953,9 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * } #endif // BOTS + if (IsNPC() && !RuleB(Combat, NPCCanCrit)) + return; + // 1: Try Slay Undead if (defender->GetBodyType() == BT_Undead || defender->GetBodyType() == BT_SummonedUndead || defender->GetBodyType() == BT_Vampire) { @@ -3983,14 +3986,12 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * // We either require an innate crit chance or some SPA 169 to crit bool innate_crit = false; int crit_chance = GetCriticalChanceBonus(hit.skill); - if (IsClient()) { - if ((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) - innate_crit = true; - else if (GetClass() == RANGER && GetLevel() >= 12 && hit.skill == EQEmu::skills::SkillArchery) - innate_crit = true; - else if (GetClass() == ROGUE && GetLevel() >= 12 && hit.skill == EQEmu::skills::SkillThrowing) - innate_crit = true; - } + if ((GetClass() == WARRIOR || GetClass() == BERSERKER) && GetLevel() >= 12) + innate_crit = true; + else if (GetClass() == RANGER && GetLevel() >= 12 && hit.skill == EQEmu::skills::SkillArchery) + innate_crit = true; + else if (GetClass() == ROGUE && GetLevel() >= 12 && hit.skill == EQEmu::skills::SkillThrowing) + innate_crit = true; // we have a chance to crit! if (innate_crit || crit_chance) { From a13694c859874a696ed885f9b390463b6b6389c8 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 5 Feb 2017 22:11:02 -0500 Subject: [PATCH 538/693] Implemented cast restrictions in GetSpellTargetTypeToken() [skip ci] --- .../spell_target_type_token_function.sql | 147 +++++++++++++++++- 1 file changed, 144 insertions(+), 3 deletions(-) diff --git a/utils/scripts/database_tools/spell_target_type_token_function.sql b/utils/scripts/database_tools/spell_target_type_token_function.sql index 6d891ba5f..1b76714fa 100644 --- a/utils/scripts/database_tools/spell_target_type_token_function.sql +++ b/utils/scripts/database_tools/spell_target_type_token_function.sql @@ -3,13 +3,14 @@ DELIMITER $$ DROP FUNCTION IF EXISTS `GetSpellTargetTypeToken`; -- This function converts a numeric spell target type to a string label based on server code designations --- Note: `cast_restriction` look-up is not implemented at this time +-- Note: `cast_restriction` data taken from MacroQuest2 definitions -- -- example: --- SELECT `id`, `name`, GetSpellTargetTypeToken(`targettype`, `CastRestriction`) FROM `spells_new` WHERE `id` IN ('6836', '10763', '30057'); +-- SELECT `id`, `name`, GetSpellTargetTypeToken(`targettype`, `CastRestriction`) FROM `spells_new` WHERE `id` IN ('6836', '10763', '25039'); CREATE FUNCTION `GetSpellTargetTypeToken` (`target_type` INT(11), `cast_restriction` INT(11)) RETURNS VARCHAR(64) BEGIN DECLARE `token` VARCHAR(64) DEFAULT ''; + DECLARE `token2` VARCHAR(64) DEFAULT ''; CASE `target_type` WHEN '1' THEN SET `token` = 'ST_TargetOptional'; @@ -51,7 +52,147 @@ BEGIN ELSE SET `token` = 'unk'; END CASE; - SET `token` = CONCAT(`token`, '(', `target_type`, ')', '->(', `cast_restriction`, ')'); + SET `token` = CONCAT(`token`, '(', `target_type`, ')'); + + CASE `cast_restriction` + WHEN '0' THEN SET `token2` = 'None'; + -- WHEN '1' THEN SET `token2` = '---'; + WHEN '100' THEN SET `token2` = 'Only works on Animal or Humanoid'; + WHEN '101' THEN SET `token2` = 'Only works on Dragon'; + WHEN '102' THEN SET `token2` = 'Only works on Animal or Insect'; + WHEN '104' THEN SET `token2` = 'Only works on Animal'; + WHEN '105' THEN SET `token2` = 'Only works on Plant'; + WHEN '106' THEN SET `token2` = 'Only works on Giant'; + WHEN '108' THEN SET `token2` = 'Doesn\'t work on Animals or Humanoids'; + WHEN '109' THEN SET `token2` = 'Only works on Bixie'; + WHEN '110' THEN SET `token2` = 'Only works on Harpy'; + WHEN '111' THEN SET `token2` = 'Only works on Gnoll'; + WHEN '112' THEN SET `token2` = 'Only works on Sporali'; + WHEN '113' THEN SET `token2` = 'Only works on Kobold'; + WHEN '114' THEN SET `token2` = 'Only works on Shade'; + WHEN '115' THEN SET `token2` = 'Only works on Drakkin'; + WHEN '117' THEN SET `token2` = 'Only works on Animals or Plants'; + WHEN '118' THEN SET `token2` = 'Only works on Summoned'; + WHEN '119' THEN SET `token2` = 'Only works on Fire_Pet'; + WHEN '120' THEN SET `token2` = 'Only works on Undead'; + WHEN '121' THEN SET `token2` = 'Only works on Living'; + WHEN '122' THEN SET `token2` = 'Only works on Fairy'; + WHEN '123' THEN SET `token2` = 'Only works on Humanoid'; + WHEN '124' THEN SET `token2` = 'Undead HP Less Than 10%'; + WHEN '125' THEN SET `token2` = 'Clockwork HP Less Than 45%'; + WHEN '126' THEN SET `token2` = 'Wisp HP Less Than 10%'; + -- WHEN '127' THEN SET `token2` = '---'; + -- WHEN '128' THEN SET `token2` = '---'; + -- WHEN '129' THEN SET `token2` = '---'; + -- WHEN '130' THEN SET `token2` = '---'; + -- WHEN '150' THEN SET `token2` = '---'; + WHEN '190' THEN SET `token2` = 'Doesn\'t work on Raid Bosses'; + WHEN '191' THEN SET `token2` = 'Only works on Raid Bosses'; + WHEN '201' THEN SET `token2` = 'HP Above 75%'; + WHEN '203' THEN SET `token2` = 'HP Less Than 20%'; + WHEN '204' THEN SET `token2` = 'HP Less Than 50%'; + WHEN '216' THEN SET `token2` = 'Not In Combat'; + WHEN '221' THEN SET `token2` = 'At Least 1 Pet On Hatelist'; + WHEN '222' THEN SET `token2` = 'At Least 2 Pets On Hatelist'; + WHEN '223' THEN SET `token2` = 'At Least 3 Pets On Hatelist'; + WHEN '224' THEN SET `token2` = 'At Least 4 Pets On Hatelist'; + WHEN '225' THEN SET `token2` = 'At Least 5 Pets On Hatelist'; + WHEN '226' THEN SET `token2` = 'At Least 6 Pets On Hatelist'; + WHEN '227' THEN SET `token2` = 'At Least 7 Pets On Hatelist'; + WHEN '228' THEN SET `token2` = 'At Least 8 Pets On Hatelist'; + WHEN '229' THEN SET `token2` = 'At Least 9 Pets On Hatelist'; + WHEN '230' THEN SET `token2` = 'At Least 10 Pets On Hatelist'; + WHEN '231' THEN SET `token2` = 'At Least 11 Pets On Hatelist'; + WHEN '232' THEN SET `token2` = 'At Least 12 Pets On Hatelist'; + WHEN '233' THEN SET `token2` = 'At Least 13 Pets On Hatelist'; + WHEN '234' THEN SET `token2` = 'At Least 14 Pets On Hatelist'; + WHEN '235' THEN SET `token2` = 'At Least 15 Pets On Hatelist'; + WHEN '236' THEN SET `token2` = 'At Least 16 Pets On Hatelist'; + WHEN '237' THEN SET `token2` = 'At Least 17 Pets On Hatelist'; + WHEN '238' THEN SET `token2` = 'At Least 18 Pets On Hatelist'; + WHEN '239' THEN SET `token2` = 'At Least 19 Pets On Hatelist'; + WHEN '240' THEN SET `token2` = 'At Least 20 Pets On Hatelist'; + WHEN '250' THEN SET `token2` = 'HP Less Than 35%'; + WHEN '304' THEN SET `token2` = 'Chain Plate Classes'; + WHEN '399' THEN SET `token2` = 'HP Between 15 and 25%'; + WHEN '400' THEN SET `token2` = 'HP Between 1 and 25%'; + WHEN '401' THEN SET `token2` = 'HP Between 25 and 35%'; + WHEN '402' THEN SET `token2` = 'HP Between 35 and 45%'; + WHEN '403' THEN SET `token2` = 'HP Between 45 and 55%'; + WHEN '404' THEN SET `token2` = 'HP Between 55 and 65%'; + -- WHEN '410' THEN SET `token2` = '---'; + -- WHEN '411' THEN SET `token2` = '---'; + WHEN '412' THEN SET `token2` = 'HP Above 99%'; + WHEN '501' THEN SET `token2` = 'HP Below 5%'; + WHEN '502' THEN SET `token2` = 'HP Below 10%'; + WHEN '503' THEN SET `token2` = 'HP Below 15%'; + WHEN '504' THEN SET `token2` = 'HP Below 20%'; + WHEN '505' THEN SET `token2` = 'HP Below 25%'; + WHEN '506' THEN SET `token2` = 'HP Below 30%'; + WHEN '507' THEN SET `token2` = 'HP Below 35%'; + WHEN '508' THEN SET `token2` = 'HP Below 40%'; + WHEN '509' THEN SET `token2` = 'HP Below 45%'; + WHEN '510' THEN SET `token2` = 'HP Below 50%'; + WHEN '511' THEN SET `token2` = 'HP Below 55%'; + WHEN '512' THEN SET `token2` = 'HP Below 60%'; + WHEN '513' THEN SET `token2` = 'HP Below 65%'; + WHEN '514' THEN SET `token2` = 'HP Below 70%'; + WHEN '515' THEN SET `token2` = 'HP Below 75%'; + WHEN '516' THEN SET `token2` = 'HP Below 80%'; + WHEN '517' THEN SET `token2` = 'HP Below 85%'; + WHEN '518' THEN SET `token2` = 'HP Below 90%'; + WHEN '519' THEN SET `token2` = 'HP Below 95%'; + WHEN '521' THEN SET `token2` = 'Mana Below X%'; + WHEN '522' THEN SET `token2` = 'End Below 40%'; + WHEN '523' THEN SET `token2` = 'Mana Below 40%'; + -- WHEN '601' THEN SET `token2` = '---'; + WHEN '603' THEN SET `token2` = 'Only works on Undead2'; + WHEN '608' THEN SET `token2` = 'Only works on Undead3'; + WHEN '624' THEN SET `token2` = 'Only works on Summoned2'; + -- WHEN '626' THEN SET `token2` = '---'; + -- WHEN '700' THEN SET `token2` = '---'; + WHEN '701' THEN SET `token2` = 'Doesn\'t work on Pets'; + -- WHEN '800' THEN SET `token2` = '---'; + -- WHEN '812' THEN SET `token2` = '---'; + -- WHEN '814' THEN SET `token2` = '---'; + -- WHEN '815' THEN SET `token2` = '---'; + -- WHEN '816' THEN SET `token2` = '---'; + -- WHEN '817' THEN SET `token2` = '---'; + WHEN '818' THEN SET `token2` = 'Only works on Undead4'; + WHEN '819' THEN SET `token2` = 'Doesn\'t work on Undead4'; + -- WHEN '820' THEN SET `token2` = '---'; + -- WHEN '821' THEN SET `token2` = '---'; + -- WHEN '822' THEN SET `token2` = '---'; + WHEN '825' THEN SET `token2` = 'End Below 21%'; + WHEN '826' THEN SET `token2` = 'End Below 25%'; + WHEN '827' THEN SET `token2` = 'End Below 29%'; + WHEN '836' THEN SET `token2` = 'Only works on Regular Servers'; + WHEN '837' THEN SET `token2` = 'Doesn\'t work on Progression Servers'; + WHEN '842' THEN SET `token2` = 'Only works on Humanoid Level 84 Max'; + WHEN '843' THEN SET `token2` = 'Only works on Humanoid Level 86 Max'; + WHEN '844' THEN SET `token2` = 'Only works on Humanoid Level 88 Max'; + -- WHEN '845' THEN SET `token2` = '---'; + -- WHEN '846' THEN SET `token2` = '---'; + -- WHEN '847' THEN SET `token2` = '---'; + -- WHEN '860' THEN SET `token2` = '---'; + -- WHEN '861' THEN SET `token2` = '---'; + -- WHEN '862' THEN SET `token2` = '---'; + -- WHEN '863' THEN SET `token2` = '---'; + -- WHEN '864' THEN SET `token2` = '---'; + -- WHEN '865' THEN SET `token2` = '---'; + WHEN '1000' THEN SET `token2` = 'Between Level 1 and 75'; + WHEN '1001' THEN SET `token2` = 'Between Level 76 and 85'; + WHEN '1002' THEN SET `token2` = 'Between Level 86 and 95'; + WHEN '1003' THEN SET `token2` = 'Between Level 96 and 100'; + WHEN '1004' THEN SET `token2` = 'HP Less Than 80%'; + WHEN '38311' THEN SET `token2` = 'Mana Below 20%'; + WHEN '38312' THEN SET `token2` = 'Mana Below 10%'; + ELSE SET `token2` = 'unk'; + END CASE; + + SET `token2` = CONCAT(`token2`, '(', `cast_restriction`, ')'); + + SET `token` = CONCAT(`token`, ':', `token2`); RETURN `token`; END$$ From ef8b4754ea2fc65a37e46b5360a35419180b3588 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 6 Feb 2017 00:11:08 -0500 Subject: [PATCH 539/693] Fix min damage issue --- zone/attack.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/attack.cpp b/zone/attack.cpp index 1ebf2a352..801242d45 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1298,6 +1298,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b // Now figure out damage my_hit.damage_done = 0; + my_hit.min_damage = 0; uint8 mylevel = GetLevel() ? GetLevel() : 1; uint32 hate = 0; if (weapon) hate = weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt; From 5dbbc5f21cefc0ec8400f7d887151db520498e41 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 6 Feb 2017 07:14:50 -0500 Subject: [PATCH 540/693] Added some additional SpellAffectIndex declarations to the enumeration (no reference.) Added dev script for function to retrieve spell affect index id labels for spells from queries --- common/spdat.h | 55 ++++++++++++-- .../spell_affect_index_token_function.sql | 71 +++++++++++++++++++ .../spell_target_type_token_function.sql | 33 +-------- 3 files changed, 124 insertions(+), 35 deletions(-) create mode 100644 utils/scripts/database_tools/spell_affect_index_token_function.sql diff --git a/common/spdat.h b/common/spdat.h index 6ca588f04..e8ec2574e 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -67,11 +67,58 @@ const int SpellTypes_Beneficial = SpellType_Heal|SpellType_Buff|SpellType_Escape #define SpellType_Any 0xFFFF +// These don't appear to be consistent either through us or soe.. +// Use for generalization rather than validation enum SpellAffectIndex { - SAI_Calm = 12, // Lull and Alliance Spells - SAI_Dispell_Sight = 14, // Dispells and Spells like Bind Sight - SAI_Memory_Blur = 27, - SAI_Calm_Song = 43 // Lull and Alliance Songs + SAI_Summon_Mount_Unclass = -1, + SAI_Direct_Damage = 0, + SAI_Heal_Cure = 1, + SAI_AC_Buff = 2, + SAI_AE_Damage = 3, + SAI_Summon = 4, // Summoned Pets and Items + SAI_Sight = 5, + SAI_Mana_Regen_Resist_Song = 6, + SAI_Stat_Buff = 7, + SAI_Vanish = 9, // Invisibility and Gate/Port + SAI_Appearance = 10, // Illusion and Size + SAI_Enchanter_Pet = 11, + SAI_Calm = 12, // Lull and Alliance Spells + SAI_Fear = 13, + SAI_Dispell_Sight = 14, // Dispells and Spells like Bind Sight + SAI_Stun = 15, + SAI_Haste_Runspeed = 16, // Haste and SoW + SAI_Combat_Slow = 17, + SAI_Damage_Shield = 18, + SAI_Cannibalize_Weapon_Proc = 19, + SAI_Weaken = 20, + SAI_Banish = 21, + SAI_Blind_Poison = 22, + SAI_Cold_DD = 23, + SAI_Poison_Disease_DD = 24, + SAI_Fire_DD = 25, + SAI_Memory_Blur = 27, + SAI_Gravity_Fling = 28, + SAI_Suffocate = 29, + SAI_Lifetap_Over_Time = 30, + SAI_Fire_AE = 31, + SAI_Cold_AE = 33, + SAI_Poison_Disease_AE = 34, + SAI_Teleport = 40, + SAI_Direct_Damage_Song = 41, + SAI_Combat_Buff_Song = 42, + SAI_Calm_Song = 43, // Lull and Alliance Songs + SAI_Firework = 45, + SAI_Firework_AE = 46, + SAI_Weather_Rocket = 47, + SAI_Convert_Vitals = 50, + SAI_NPC_Special_60 = 60, + SAI_NPC_Special_61 = 61, + SAI_NPC_Special_62 = 62, + SAI_NPC_Special_63 = 63, + SAI_NPC_Special_70 = 70, + SAI_NPC_Special_71 = 71, + SAI_NPC_Special_80 = 80, + SAI_Trap_Lock = 88 }; enum RESISTTYPE { diff --git a/utils/scripts/database_tools/spell_affect_index_token_function.sql b/utils/scripts/database_tools/spell_affect_index_token_function.sql new file mode 100644 index 000000000..0aa6926c8 --- /dev/null +++ b/utils/scripts/database_tools/spell_affect_index_token_function.sql @@ -0,0 +1,71 @@ +DELIMITER $$ + +DROP FUNCTION IF EXISTS `GetSpellAffectIndexToken`; + +-- This function converts a numeric spell affect index id to a string label based on server code designations +-- +-- example: +-- SELECT `id`, `name`, GetSpellAffectIndexToken(`SpellAffectIndex`) FROM `spells_new` WHERE `id` IN ('73', '2253', '2319'); +CREATE FUNCTION `GetSpellAffectIndexToken` (`affect_index_id` INT(11)) RETURNS VARCHAR(64) +BEGIN + DECLARE `token` VARCHAR(64) DEFAULT ''; + + CASE `affect_index_id` + WHEN '-1' THEN SET `token` = 'SAI_Summon_Mount_Unclass'; + WHEN '0' THEN SET `token` = 'SAI_Direct_Damage'; + WHEN '1' THEN SET `token` = 'SAI_Heal_Cure'; + WHEN '2' THEN SET `token` = 'SAI_AC_Buff'; + WHEN '3' THEN SET `token` = 'SAI_AE_Damage'; + WHEN '4' THEN SET `token` = 'SAI_Summon'; + WHEN '5' THEN SET `token` = 'SAI_Sight'; + WHEN '6' THEN SET `token` = 'SAI_Mana_Regen_Resist_Song'; + WHEN '7' THEN SET `token` = 'SAI_Stat_Buff'; + WHEN '9' THEN SET `token` = 'SAI_Vanish'; + WHEN '10' THEN SET `token` = 'SAI_Appearance'; + WHEN '11' THEN SET `token` = 'SAI_Enchanter_Pet'; + WHEN '12' THEN SET `token` = 'SAI_Calm'; + WHEN '13' THEN SET `token` = 'SAI_Fear'; + WHEN '14' THEN SET `token` = 'SAI_Dispell_Sight'; + WHEN '15' THEN SET `token` = 'SAI_Stun'; + WHEN '16' THEN SET `token` = 'SAI_Haste_Runspeed'; + WHEN '17' THEN SET `token` = 'SAI_Combat_Slow'; + WHEN '18' THEN SET `token` = 'SAI_Damage_Shield'; + WHEN '19' THEN SET `token` = 'SAI_Cannibalize_Weapon_Proc'; + WHEN '20' THEN SET `token` = 'SAI_Weaken'; + WHEN '21' THEN SET `token` = 'SAI_Banish'; + WHEN '22' THEN SET `token` = 'SAI_Blind_Poison'; + WHEN '23' THEN SET `token` = 'SAI_Cold_DD'; + WHEN '24' THEN SET `token` = 'SAI_Poison_Disease_DD'; + WHEN '25' THEN SET `token` = 'SAI_Fire_DD'; + WHEN '27' THEN SET `token` = 'SAI_Memory_Blur'; + WHEN '28' THEN SET `token` = 'SAI_Gravity_Fling'; + WHEN '29' THEN SET `token` = 'SAI_Suffocate'; + WHEN '30' THEN SET `token` = 'SAI_Lifetap_Over_Time'; + WHEN '31' THEN SET `token` = 'SAI_Fire_AE'; + WHEN '33' THEN SET `token` = 'SAI_Cold_AE'; + WHEN '34' THEN SET `token` = 'SAI_Poison_Disease_AE'; + WHEN '40' THEN SET `token` = 'SAI_Teleport'; + WHEN '41' THEN SET `token` = 'SAI_Direct_Damage_Song'; + WHEN '42' THEN SET `token` = 'SAI_Combat_Buff_Song'; + WHEN '43' THEN SET `token` = 'SAI_Calm_Song'; + WHEN '45' THEN SET `token` = 'SAI_Firework'; + WHEN '46' THEN SET `token` = 'SAI_Firework_AE'; + WHEN '47' THEN SET `token` = 'SAI_Weather_Rocket'; + WHEN '50' THEN SET `token` = 'SAI_Convert_Vitals'; + WHEN '60' THEN SET `token` = 'SAI_NPC_Special_60'; + WHEN '61' THEN SET `token` = 'SAI_NPC_Special_61'; + WHEN '62' THEN SET `token` = 'SAI_NPC_Special_62'; + WHEN '63' THEN SET `token` = 'SAI_NPC_Special_63'; + WHEN '70' THEN SET `token` = 'SAI_NPC_Special_70'; + WHEN '71' THEN SET `token` = 'SAI_NPC_Special_71'; + WHEN '80' THEN SET `token` = 'SAI_NPC_Special_80'; + WHEN '88' THEN SET `token` = 'SAI_Lock_Trap'; + ELSE SET `token` = 'unk'; + END CASE; + + SET `token` = CONCAT(`token`, '(', `affect_index_id`, ')'); + + RETURN `token`; +END$$ + +DELIMITER ; diff --git a/utils/scripts/database_tools/spell_target_type_token_function.sql b/utils/scripts/database_tools/spell_target_type_token_function.sql index 1b76714fa..76d726bce 100644 --- a/utils/scripts/database_tools/spell_target_type_token_function.sql +++ b/utils/scripts/database_tools/spell_target_type_token_function.sql @@ -7,9 +7,9 @@ DROP FUNCTION IF EXISTS `GetSpellTargetTypeToken`; -- -- example: -- SELECT `id`, `name`, GetSpellTargetTypeToken(`targettype`, `CastRestriction`) FROM `spells_new` WHERE `id` IN ('6836', '10763', '25039'); -CREATE FUNCTION `GetSpellTargetTypeToken` (`target_type` INT(11), `cast_restriction` INT(11)) RETURNS VARCHAR(64) +CREATE FUNCTION `GetSpellTargetTypeToken` (`target_type` INT(11), `cast_restriction` INT(11)) RETURNS VARCHAR(128) BEGIN - DECLARE `token` VARCHAR(64) DEFAULT ''; + DECLARE `token` VARCHAR(128) DEFAULT ''; DECLARE `token2` VARCHAR(64) DEFAULT ''; CASE `target_type` @@ -56,7 +56,6 @@ BEGIN CASE `cast_restriction` WHEN '0' THEN SET `token2` = 'None'; - -- WHEN '1' THEN SET `token2` = '---'; WHEN '100' THEN SET `token2` = 'Only works on Animal or Humanoid'; WHEN '101' THEN SET `token2` = 'Only works on Dragon'; WHEN '102' THEN SET `token2` = 'Only works on Animal or Insect'; @@ -81,11 +80,6 @@ BEGIN WHEN '124' THEN SET `token2` = 'Undead HP Less Than 10%'; WHEN '125' THEN SET `token2` = 'Clockwork HP Less Than 45%'; WHEN '126' THEN SET `token2` = 'Wisp HP Less Than 10%'; - -- WHEN '127' THEN SET `token2` = '---'; - -- WHEN '128' THEN SET `token2` = '---'; - -- WHEN '129' THEN SET `token2` = '---'; - -- WHEN '130' THEN SET `token2` = '---'; - -- WHEN '150' THEN SET `token2` = '---'; WHEN '190' THEN SET `token2` = 'Doesn\'t work on Raid Bosses'; WHEN '191' THEN SET `token2` = 'Only works on Raid Bosses'; WHEN '201' THEN SET `token2` = 'HP Above 75%'; @@ -120,8 +114,6 @@ BEGIN WHEN '402' THEN SET `token2` = 'HP Between 35 and 45%'; WHEN '403' THEN SET `token2` = 'HP Between 45 and 55%'; WHEN '404' THEN SET `token2` = 'HP Between 55 and 65%'; - -- WHEN '410' THEN SET `token2` = '---'; - -- WHEN '411' THEN SET `token2` = '---'; WHEN '412' THEN SET `token2` = 'HP Above 99%'; WHEN '501' THEN SET `token2` = 'HP Below 5%'; WHEN '502' THEN SET `token2` = 'HP Below 10%'; @@ -145,24 +137,12 @@ BEGIN WHEN '521' THEN SET `token2` = 'Mana Below X%'; WHEN '522' THEN SET `token2` = 'End Below 40%'; WHEN '523' THEN SET `token2` = 'Mana Below 40%'; - -- WHEN '601' THEN SET `token2` = '---'; WHEN '603' THEN SET `token2` = 'Only works on Undead2'; WHEN '608' THEN SET `token2` = 'Only works on Undead3'; WHEN '624' THEN SET `token2` = 'Only works on Summoned2'; - -- WHEN '626' THEN SET `token2` = '---'; - -- WHEN '700' THEN SET `token2` = '---'; WHEN '701' THEN SET `token2` = 'Doesn\'t work on Pets'; - -- WHEN '800' THEN SET `token2` = '---'; - -- WHEN '812' THEN SET `token2` = '---'; - -- WHEN '814' THEN SET `token2` = '---'; - -- WHEN '815' THEN SET `token2` = '---'; - -- WHEN '816' THEN SET `token2` = '---'; - -- WHEN '817' THEN SET `token2` = '---'; WHEN '818' THEN SET `token2` = 'Only works on Undead4'; WHEN '819' THEN SET `token2` = 'Doesn\'t work on Undead4'; - -- WHEN '820' THEN SET `token2` = '---'; - -- WHEN '821' THEN SET `token2` = '---'; - -- WHEN '822' THEN SET `token2` = '---'; WHEN '825' THEN SET `token2` = 'End Below 21%'; WHEN '826' THEN SET `token2` = 'End Below 25%'; WHEN '827' THEN SET `token2` = 'End Below 29%'; @@ -171,15 +151,6 @@ BEGIN WHEN '842' THEN SET `token2` = 'Only works on Humanoid Level 84 Max'; WHEN '843' THEN SET `token2` = 'Only works on Humanoid Level 86 Max'; WHEN '844' THEN SET `token2` = 'Only works on Humanoid Level 88 Max'; - -- WHEN '845' THEN SET `token2` = '---'; - -- WHEN '846' THEN SET `token2` = '---'; - -- WHEN '847' THEN SET `token2` = '---'; - -- WHEN '860' THEN SET `token2` = '---'; - -- WHEN '861' THEN SET `token2` = '---'; - -- WHEN '862' THEN SET `token2` = '---'; - -- WHEN '863' THEN SET `token2` = '---'; - -- WHEN '864' THEN SET `token2` = '---'; - -- WHEN '865' THEN SET `token2` = '---'; WHEN '1000' THEN SET `token2` = 'Between Level 1 and 75'; WHEN '1001' THEN SET `token2` = 'Between Level 76 and 85'; WHEN '1002' THEN SET `token2` = 'Between Level 86 and 95'; From 3d1bb6bd088d57943d3b38778d3ab591145d4c32 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 6 Feb 2017 17:48:44 -0500 Subject: [PATCH 541/693] Updated SpellAffectIndex enumeration remarks [skip ci] --- common/spdat.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index e8ec2574e..3344489df 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -67,8 +67,9 @@ const int SpellTypes_Beneficial = SpellType_Heal|SpellType_Buff|SpellType_Escape #define SpellType_Any 0xFFFF -// These don't appear to be consistent either through us or soe.. -// Use for generalization rather than validation +// These should not be used to determine spell category.. +// They are a graphical affects (effects?) index only +// TODO: import sai list enum SpellAffectIndex { SAI_Summon_Mount_Unclass = -1, SAI_Direct_Damage = 0, From cd11d7d1af94cfae8f3f76af2f5dea26285c8640 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 7 Feb 2017 21:52:17 -0500 Subject: [PATCH 542/693] Added dev script for function to retrieve spell category labels for spells from queries [skip ci] --- .../spell_category_token_function.sql | 206 ++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 utils/scripts/database_tools/spell_category_token_function.sql diff --git a/utils/scripts/database_tools/spell_category_token_function.sql b/utils/scripts/database_tools/spell_category_token_function.sql new file mode 100644 index 000000000..9a0949eec --- /dev/null +++ b/utils/scripts/database_tools/spell_category_token_function.sql @@ -0,0 +1,206 @@ +DELIMITER $$ + +DROP FUNCTION IF EXISTS `GetSpellCategoryToken`; + +-- This function converts numeric spell category ids to a string label based on server code designations +-- +-- example: +-- SELECT `id`, `name`, GetSpellCategoryToken(`spell_category`) FROM `spells_new` WHERE `id` IN ('39', '129', '3468'); +CREATE FUNCTION `GetSpellCategoryToken` (`spell_category` INT(11)) RETURNS VARCHAR(256) +BEGIN + DECLARE `token` VARCHAR(256) DEFAULT ''; + + CASE `spell_category` + WHEN '-99' THEN SET `token` = 'neg99#'; + WHEN '-1' THEN SET `token` = 'neg1#'; + WHEN '0' THEN SET `token` = CONCAT('#', `spell_category`); + WHEN '1' THEN SET `token` = 'DD'; + WHEN '2' THEN SET `token` = 'DD_Undead'; + WHEN '3' THEN SET `token` = 'DD_Summoned'; + WHEN '4' THEN SET `token` = 'Lifetap_to_Self'; + WHEN '5' THEN SET `token` = 'DoT_Plant'; + WHEN '6' THEN SET `token` = 'DD_Body_Type'; + WHEN '7' THEN SET `token` = 'DoT'; + WHEN '8' THEN SET `token` = 'Divine_DoT'; + WHEN '9' THEN SET `token` = 'Lifetap_to_Self_2'; + WHEN '10' THEN SET `token` = 'AoE_DD'; + WHEN '11' THEN SET `token` = 'AoE_DD_Earth'; + WHEN '12' THEN SET `token` = 'AoE_DD_Nature'; + WHEN '13' THEN SET `token` = 'Bolt_Fire_Cold'; + WHEN '14' THEN SET `token` = 'Stun_Damage'; + WHEN '15' THEN SET `token` = 'Target_Stun'; + WHEN '16' THEN SET `token` = 'Group_Stun'; + WHEN '17' THEN SET `token` = 'Leech_to_Group'; + WHEN '18' THEN SET `token` = 'Siphon_Strength'; + WHEN '19' THEN SET `token` = 'Weapon_Proc'; + WHEN '20' THEN SET `token` = 'Target_Heal'; + WHEN '21' THEN SET `token` = 'Target_HoT'; + WHEN '22' THEN SET `token` = 'Group_Heal_Cure'; + WHEN '23' THEN SET `token` = 'Group_HoT'; + WHEN '24' THEN SET `token` = 'Target_Health_Regen'; + WHEN '25' THEN SET `token` = 'Group_Health_Regen'; + WHEN '26' THEN SET `token` = 'Pet_Heal'; + WHEN '27' THEN SET `token` = 'Resurrection'; + WHEN '28' THEN SET `token` = 'Dark_Empathy'; + WHEN '29' THEN SET `token` = 'Cure_Poison'; + WHEN '30' THEN SET `token` = 'Resolution'; + WHEN '32' THEN SET `token` = 'Blur'; + WHEN '34' THEN SET `token` = 'Hate_Buff'; + WHEN '35' THEN SET `token` = 'Attack_Speed_Buff'; + WHEN '36' THEN SET `token` = 'Pet_Combat_Buff'; + WHEN '37' THEN SET `token` = 'Attack_Speed_Buff_Song'; + WHEN '38' THEN SET `token` = 'Attack_Speed_Debuff'; + WHEN '39' THEN SET `token` = 'Attack_Speed_Debuff_2'; + WHEN '40' THEN SET `token` = 'Cannibalize'; + WHEN '41' THEN SET `token` = 'Target_Movement_Speed'; + WHEN '42' THEN SET `token` = 'Group_Movement_Speed'; + WHEN '43' THEN SET `token` = 'Wolf_Form'; + WHEN '44' THEN SET `token` = 'Elemental_Pet_Movement_Speed'; + WHEN '45' THEN SET `token` = 'Illusion'; + WHEN '46' THEN SET `token` = 'Dark_Pact'; + WHEN '47' THEN SET `token` = 'Form_of_the_Bear'; + WHEN '48' THEN SET `token` = 'Treeform'; + WHEN '49' THEN SET `token` = 'Dead_Man_Floating'; + WHEN '50' THEN SET `token` = 'Root'; + WHEN '51' THEN SET `token` = 'Summon_Pet'; + WHEN '52' THEN SET `token` = 'Summon_Corpse'; + WHEN '53' THEN SET `token` = 'Sense'; + WHEN '54' THEN SET `token` = 'Divine_Aura'; + WHEN '55' THEN SET `token` = 'Evacuate'; + WHEN '56' THEN SET `token` = 'Gate'; + WHEN '58' THEN SET `token` = 'Teleport_Bind'; + WHEN '59' THEN SET `token` = 'Shadow_Step'; + WHEN '60' THEN SET `token` = 'Enchant_Material'; + WHEN '61' THEN SET `token` = 'Summon_Common_Item'; + WHEN '62' THEN SET `token` = 'Fear'; + WHEN '63' THEN SET `token` = 'Fear_Animal'; + WHEN '64' THEN SET `token` = 'Fear_Undead'; + WHEN '65' THEN SET `token` = 'Damage_Shield'; + WHEN '66' THEN SET `token` = 'Resist_Buff_Song'; + WHEN '67' THEN SET `token` = CONCAT('#', `spell_category`); + WHEN '68' THEN SET `token` = 'Damage_Shield_2'; + WHEN '69' THEN SET `token` = 'Resist_Redux'; + WHEN '70' THEN SET `token` = 'Resist_Buff'; + WHEN '71' THEN SET `token` = 'Warder'; + WHEN '72' THEN SET `token` = 'Familiar'; + WHEN '73' THEN SET `token` = 'Strength_Buff'; + WHEN '74' THEN SET `token` = 'Dexterity_Buff'; + WHEN '75' THEN SET `token` = 'Agility_Buff'; + WHEN '76' THEN SET `token` = 'Stamina_Buff'; + WHEN '77' THEN SET `token` = 'Intelligence_Wisdom_Buff'; + WHEN '78' THEN SET `token` = 'Charisma_Buff'; + WHEN '79' THEN SET `token` = 'Weaken'; + WHEN '80' THEN SET `token` = 'Invisibility_v_Undead'; + WHEN '81' THEN SET `token` = 'Invisibility_v_Animals'; + WHEN '82' THEN SET `token` = 'Invisibility'; + WHEN '83' THEN SET `token` = 'Damage_Absorbtion'; + WHEN '84' THEN SET `token` = 'Fizzle_Redux'; + WHEN '85' THEN SET `token` = 'Clarity'; + WHEN '86' THEN SET `token` = 'Gift_of_Magic'; + WHEN '87' THEN SET `token` = 'Mana_Drain'; + WHEN '88' THEN SET `token` = 'Mana_Subversion'; + WHEN '89' THEN SET `token` = 'Harvest_Mana'; + WHEN '90' THEN SET `token` = 'Hate_Redux'; + WHEN '91' THEN SET `token` = 'Increase_Aim'; + WHEN '92' THEN SET `token` = 'Combat_Buff'; + WHEN '93' THEN SET `token` = 'Bind_Sight'; + WHEN '94' THEN SET `token` = 'Enduring_Breath'; + WHEN '95' THEN SET `token` = 'Alliance'; + WHEN '96' THEN SET `token` = 'Charm'; + WHEN '97' THEN SET `token` = 'Strip_Enchantment'; + WHEN '98' THEN SET `token` = 'Lull'; + WHEN '99' THEN SET `token` = 'Mesmerize'; + WHEN '100' THEN SET `token` = 'Casting_Enhancement'; + WHEN '101' THEN SET `token` = 'Snare_Hamstring'; + WHEN '102' THEN SET `token` = 'Shackle'; + WHEN '105' THEN SET `token` = 'Feign_Death'; + WHEN '106' THEN SET `token` = 'Identify'; + WHEN '107' THEN SET `token` = 'Reclaim_Energy'; + WHEN '108' THEN SET `token` = 'Locate_Corpse'; + WHEN '109' THEN SET `token` = 'Call_of_the_Hero'; + WHEN '110' THEN SET `token` = 'Mana_Shield'; + WHEN '112' THEN SET `token` = 'Blind'; + WHEN '113' THEN SET `token` = 'Gravity_is_for_Suckers'; -- 'Levitation' + WHEN '114' THEN SET `token` = 'Bard_Nerf'; + WHEN '115' THEN SET `token` = 'Divine_Intervention'; + WHEN '116' THEN SET `token` = 'Memory_Blur'; + WHEN '118' THEN SET `token` = 'Size_Change'; + WHEN '119' THEN SET `token` = 'Hate_Buff_2'; + WHEN '120' THEN SET `token` = CONCAT('#', `spell_category`); + WHEN '121' THEN SET `token` = CONCAT('#', `spell_category`); + WHEN '122' THEN SET `token` = CONCAT('#', `spell_category`); + WHEN '125' THEN SET `token` = 'DD_Fire'; + WHEN '126' THEN SET `token` = 'DD_Cold'; + WHEN '127' THEN SET `token` = 'Bolt_Poison'; + WHEN '128' THEN SET `token` = 'Bolt_Disease'; + WHEN '129' THEN SET `token` = 'DoT_Fire'; + WHEN '130' THEN SET `token` = 'DoT_Cold'; + WHEN '131' THEN SET `token` = 'DoT_Poison'; + WHEN '132' THEN SET `token` = 'DoT_Disease'; + WHEN '133' THEN SET `token` = 'Destroy_Lock'; + WHEN '134' THEN SET `token` = 'Sense_Trap'; + WHEN '135' THEN SET `token` = 'Disarm_Trap'; + WHEN '136' THEN SET `token` = 'Destroy_Cursed_Lock'; + WHEN '137' THEN SET `token` = 'Sense_Cursed_Trap'; + WHEN '138' THEN SET `token` = 'Disarm_Cursed_Trap'; + WHEN '140' THEN SET `token` = 'Banish_Undead'; + WHEN '141' THEN SET `token` = 'Banish'; + WHEN '142' THEN SET `token` = 'AoE_DD_Fire_Column'; + WHEN '143' THEN SET `token` = 'AoE_DD_Cold_Column'; + WHEN '146' THEN SET `token` = 'AoE_DD_Fire'; + WHEN '147' THEN SET `token` = 'AoE_DD_Cold'; + WHEN '150' THEN SET `token` = 'AoE_DoT_Fire'; + WHEN '151' THEN SET `token` = 'AoE_DoT_Cold'; + WHEN '152' THEN SET `token` = 'AoE_DoT_Poison'; + WHEN '154' THEN SET `token` = 'AoE_Fear_Song'; + WHEN '155' THEN SET `token` = 'Target_Heal_2'; + WHEN '156' THEN SET `token` = 'Mana_to_HP'; + WHEN '157' THEN SET `token` = 'Symbiosis'; + WHEN '159' THEN SET `token` = 'Cure_Corruption'; + WHEN '160' THEN SET `token` = 'Remove_Curse'; + WHEN '161' THEN SET `token` = 'Cure'; + WHEN '162' THEN SET `token` = 'Cure_Blindness'; + WHEN '163' THEN SET `token` = 'Divine_Cure'; + WHEN '164' THEN SET `token` = CONCAT('#', `spell_category`); + WHEN '165' THEN SET `token` = 'Magic_Combat_Buff'; + WHEN '166' THEN SET `token` = 'Nature_HP_Attack_Buff'; + WHEN '167' THEN SET `token` = 'Divine_HP_Buff'; + WHEN '168' THEN SET `token` = 'Divine_HP_AC_Buff'; + WHEN '169' THEN SET `token` = CONCAT('#', `spell_category`); + WHEN '170' THEN SET `token` = 'Spell_Rune'; + WHEN '171' THEN SET `token` = 'Pet_Rune'; + WHEN '172' THEN SET `token` = 'Spell_Reflection'; + WHEN '173' THEN SET `token` = 'Damage_Shield_3'; + WHEN '174' THEN SET `token` = 'Vital_Regen'; + WHEN '175' THEN SET `token` = 'Aggro_Redux'; + WHEN '200' THEN SET `token` = 'Cantrips'; + WHEN '201' THEN SET `token` = CONCAT('#', `spell_category`); + WHEN '202' THEN SET `token` = 'Combat_Buff_Song'; + WHEN '203' THEN SET `token` = 'Summon_Swarm'; + WHEN '204' THEN SET `token` = 'Summon_Air_Elemental'; + WHEN '205' THEN SET `token` = 'Summon_Water_Elemental'; + WHEN '206' THEN SET `token` = 'Summon_Fire_Elemental'; + WHEN '207' THEN SET `token` = 'Summon_Earth_Elemental'; + WHEN '208' THEN SET `token` = 'Monster_Summoning'; + WHEN '209' THEN SET `token` = 'Teleport_Antonica'; + WHEN '210' THEN SET `token` = 'Teleport_Odus'; + WHEN '211' THEN SET `token` = 'Teleport_Faydwer'; + WHEN '212' THEN SET `token` = 'Teleport_Combine'; + WHEN '213' THEN SET `token` = 'Teleport_Velious'; + WHEN '214' THEN SET `token` = 'Teleport_Luclin'; + WHEN '215' THEN SET `token` = 'Teleport_Planes'; + WHEN '216' THEN SET `token` = 'Teleport_Gates'; + WHEN '217' THEN SET `token` = 'Summon_Weapon'; + WHEN '218' THEN SET `token` = 'Summon_Jewelry'; + WHEN '219' THEN SET `token` = 'Summon_Sustenance'; + WHEN '220' THEN SET `token` = 'Summon_Armor'; + WHEN '999' THEN SET `token` = CONCAT('#', `spell_category`); + ELSE SET `token` = 'unk'; + END CASE; + + SET `token` = CONCAT(`token`, '(', `spell_category`, ')'); + + RETURN `token`; +END$$ + +DELIMITER ; From d1abe4a332d30283dde306b7495da6a7867f2bad Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 7 Feb 2017 21:52:46 -0500 Subject: [PATCH 543/693] Added dev script for function to retrieve spell type description labels for spells from queries [skip ci] --- .../spell_type_description_token_function.sql | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 utils/scripts/database_tools/spell_type_description_token_function.sql diff --git a/utils/scripts/database_tools/spell_type_description_token_function.sql b/utils/scripts/database_tools/spell_type_description_token_function.sql new file mode 100644 index 000000000..ea7875916 --- /dev/null +++ b/utils/scripts/database_tools/spell_type_description_token_function.sql @@ -0,0 +1,185 @@ +DELIMITER $$ + +DROP FUNCTION IF EXISTS `GetSpellTypeDescriptionToken`; + +-- This function converts numeric spell type description ids to a string label based on server code designations +-- +-- example: +-- SELECT `id`, `name`, GetSpellTypeDescriptionToken(`typedescnum`) FROM `spells_new` WHERE `id` IN ('16', '42', '23214'); +CREATE FUNCTION `GetSpellTypeDescriptionToken` (`type_description_id` INT(11)) RETURNS VARCHAR(256) +BEGIN + DECLARE `token` VARCHAR(256) DEFAULT ''; + + CASE `type_description_id` + WHEN '1' THEN SET `token` = 'Aegolism'; + WHEN '2' THEN SET `token` = 'Agility'; + WHEN '3' THEN SET `token` = 'Alliance'; + WHEN '4' THEN SET `token` = 'Animal'; + WHEN '5' THEN SET `token` = 'Antonica'; + WHEN '6' THEN SET `token` = 'Armor_Class'; + WHEN '7' THEN SET `token` = 'Attack'; + WHEN '8' THEN SET `token` = 'Bane'; + WHEN '9' THEN SET `token` = 'Blind'; + WHEN '10' THEN SET `token` = 'Block'; + WHEN '11' THEN SET `token` = 'Calm'; + WHEN '12' THEN SET `token` = 'Charisma'; + WHEN '13' THEN SET `token` = 'Charm'; + WHEN '14' THEN SET `token` = 'Cold'; + WHEN '15' THEN SET `token` = 'Combat_Abilities'; + WHEN '16' THEN SET `token` = 'Combat_Innates'; + WHEN '17' THEN SET `token` = 'Conversions'; + WHEN '18' THEN SET `token` = 'Create_Item'; + WHEN '19' THEN SET `token` = 'Cure'; + WHEN '20' THEN SET `token` = 'Damage_Over_Time'; + WHEN '21' THEN SET `token` = 'Damage_Shield'; + WHEN '22' THEN SET `token` = 'Defensive'; + WHEN '23' THEN SET `token` = 'Destroy'; + WHEN '24' THEN SET `token` = 'Dexterity'; + WHEN '25' THEN SET `token` = 'Direct_Damage'; + WHEN '26' THEN SET `token` = 'Disarm_Traps'; + WHEN '27' THEN SET `token` = 'Disciplines'; + WHEN '28' THEN SET `token` = 'Discord'; + WHEN '29' THEN SET `token` = 'Disease'; + WHEN '30' THEN SET `token` = 'Disempowering'; + WHEN '31' THEN SET `token` = 'Dispel'; + WHEN '32' THEN SET `token` = 'Duration_Heals'; + WHEN '33' THEN SET `token` = 'Duration_Tap'; + WHEN '34' THEN SET `token` = 'Enchant_Metal'; + WHEN '35' THEN SET `token` = 'Enthrall'; + WHEN '36' THEN SET `token` = 'Faydwer'; + WHEN '37' THEN SET `token` = 'Fear'; + WHEN '38' THEN SET `token` = 'Fire'; + WHEN '39' THEN SET `token` = 'Fizzle_Rate'; + WHEN '40' THEN SET `token` = 'Fumble'; + WHEN '41' THEN SET `token` = 'Haste'; + WHEN '42' THEN SET `token` = 'Heals'; + WHEN '43' THEN SET `token` = 'Health'; + WHEN '44' THEN SET `token` = 'Health_Mana'; + WHEN '45' THEN SET `token` = 'HP_Buffs'; + WHEN '46' THEN SET `token` = 'HP_type_one'; + WHEN '47' THEN SET `token` = 'HP_type_two'; + WHEN '48' THEN SET `token` = 'Illusion_Other'; + WHEN '49' THEN SET `token` = 'Illusion_Player'; + WHEN '50' THEN SET `token` = 'Imbue_Gem'; + WHEN '51' THEN SET `token` = 'Invisibility'; + WHEN '52' THEN SET `token` = 'Invulnerability'; + WHEN '53' THEN SET `token` = 'Jolt'; + WHEN '54' THEN SET `token` = 'Kunark'; + WHEN '55' THEN SET `token` = 'Levitate'; + WHEN '56' THEN SET `token` = 'Life_Flow'; + WHEN '57' THEN SET `token` = 'Luclin'; + WHEN '58' THEN SET `token` = 'Magic'; + WHEN '59' THEN SET `token` = 'Mana'; + WHEN '60' THEN SET `token` = 'Mana_Drain'; + WHEN '61' THEN SET `token` = 'Mana_Flow'; + WHEN '62' THEN SET `token` = 'Melee_Guard'; + WHEN '63' THEN SET `token` = 'Memory_Blur'; + WHEN '64' THEN SET `token` = 'Misc'; + WHEN '65' THEN SET `token` = 'Movement'; + WHEN '66' THEN SET `token` = 'Objects'; + WHEN '67' THEN SET `token` = 'Odus'; + WHEN '68' THEN SET `token` = 'Offensive'; + WHEN '69' THEN SET `token` = 'Pet'; + WHEN '70' THEN SET `token` = 'Pet_Haste'; + WHEN '71' THEN SET `token` = 'Pet_Misc_Buffs'; + WHEN '72' THEN SET `token` = 'Physical'; + WHEN '73' THEN SET `token` = 'Picklock'; + WHEN '74' THEN SET `token` = 'Plant'; + WHEN '75' THEN SET `token` = 'Poison'; + WHEN '76' THEN SET `token` = 'Power_Tap'; + WHEN '77' THEN SET `token` = 'Quick_Heal'; + WHEN '78' THEN SET `token` = 'Reflection'; + WHEN '79' THEN SET `token` = 'Regen'; + WHEN '80' THEN SET `token` = 'Resist_Buff'; + WHEN '81' THEN SET `token` = 'Resist_Debuffs'; + WHEN '82' THEN SET `token` = 'Resurrection'; + WHEN '83' THEN SET `token` = 'Root'; + WHEN '84' THEN SET `token` = 'Rune'; + WHEN '85' THEN SET `token` = 'Sense_Trap'; + WHEN '86' THEN SET `token` = 'Shadowstep'; + WHEN '87' THEN SET `token` = 'Shielding'; + WHEN '88' THEN SET `token` = 'Slow'; + WHEN '89' THEN SET `token` = 'Snare'; + WHEN '90' THEN SET `token` = 'Special'; + WHEN '91' THEN SET `token` = 'Spell_Focus'; + WHEN '92' THEN SET `token` = 'Spell_Guard'; + WHEN '93' THEN SET `token` = 'Spellshield'; + WHEN '94' THEN SET `token` = 'Stamina'; + WHEN '95' THEN SET `token` = 'Statistic_Buffs'; + WHEN '96' THEN SET `token` = 'Strength'; + WHEN '97' THEN SET `token` = 'Stun'; + WHEN '98' THEN SET `token` = 'Sum_Air'; + WHEN '99' THEN SET `token` = 'Sum_Animation'; + WHEN '100' THEN SET `token` = 'Sum_Earth'; + WHEN '101' THEN SET `token` = 'Sum_Familiar'; + WHEN '102' THEN SET `token` = 'Sum_Fire'; + WHEN '103' THEN SET `token` = 'Sum_Undead'; + WHEN '104' THEN SET `token` = 'Sum_Warder'; + WHEN '105' THEN SET `token` = 'Sum_Water'; + WHEN '106' THEN SET `token` = 'Summon_Armor'; + WHEN '107' THEN SET `token` = 'Summon_Focus'; + WHEN '108' THEN SET `token` = 'Summon_Food_Water'; + WHEN '109' THEN SET `token` = 'Summon_Utility'; + WHEN '110' THEN SET `token` = 'Summon_Weapon'; + WHEN '111' THEN SET `token` = 'Summoned'; + WHEN '112' THEN SET `token` = 'Symbol'; + WHEN '113' THEN SET `token` = 'Taelosia'; + WHEN '114' THEN SET `token` = 'Taps'; + WHEN '115' THEN SET `token` = 'Techniques'; + WHEN '116' THEN SET `token` = 'The_Planes'; + WHEN '117' THEN SET `token` = 'Timer_1'; + WHEN '118' THEN SET `token` = 'Timer_2'; + WHEN '119' THEN SET `token` = 'Timer_3'; + WHEN '120' THEN SET `token` = 'Timer_4'; + WHEN '121' THEN SET `token` = 'Timer_5'; + WHEN '122' THEN SET `token` = 'Timer_6'; + WHEN '123' THEN SET `token` = 'Transport'; + WHEN '124' THEN SET `token` = 'Undead'; + WHEN '125' THEN SET `token` = 'Utility_Beneficial'; + WHEN '126' THEN SET `token` = 'Utility_Detrimental'; + WHEN '127' THEN SET `token` = 'Velious'; + WHEN '128' THEN SET `token` = 'Visages'; + WHEN '129' THEN SET `token` = 'Vision'; + WHEN '130' THEN SET `token` = 'Wisdom_Intelligence'; + WHEN '131' THEN SET `token` = 'Traps'; + WHEN '132' THEN SET `token` = 'Auras'; + WHEN '133' THEN SET `token` = 'Endurance'; + WHEN '134' THEN SET `token` = 'Serpent\'s_Spine'; + WHEN '135' THEN SET `token` = 'Corruption'; + WHEN '136' THEN SET `token` = 'Learning'; + WHEN '137' THEN SET `token` = 'Chromatic'; + WHEN '138' THEN SET `token` = 'Prismatic'; + WHEN '139' THEN SET `token` = 'Sum_Swarm'; + WHEN '140' THEN SET `token` = 'Delayed'; + WHEN '141' THEN SET `token` = 'Temporary'; + WHEN '142' THEN SET `token` = 'Twincast'; + WHEN '143' THEN SET `token` = 'Sum_Bodyguard'; + WHEN '144' THEN SET `token` = 'Humanoid'; + WHEN '145' THEN SET `token` = 'Haste_Spell_Focus'; + WHEN '146' THEN SET `token` = 'Timer_7'; + WHEN '147' THEN SET `token` = 'Timer_8'; + WHEN '148' THEN SET `token` = 'Timer_9'; + WHEN '149' THEN SET `token` = 'Timer_10'; + WHEN '150' THEN SET `token` = 'Timer_11'; + WHEN '151' THEN SET `token` = 'Timer_12'; + WHEN '152' THEN SET `token` = 'Hatred'; + WHEN '153' THEN SET `token` = 'Fast'; + WHEN '154' THEN SET `token` = 'Illusion_Special'; + WHEN '155' THEN SET `token` = 'Timer_13'; + WHEN '156' THEN SET `token` = 'Timer_14'; + WHEN '157' THEN SET `token` = 'Timer_15'; + WHEN '158' THEN SET `token` = 'Timer_16'; + WHEN '159' THEN SET `token` = 'Timer_17'; + WHEN '160' THEN SET `token` = 'Timer_18'; + WHEN '161' THEN SET `token` = 'Timer_19'; + WHEN '162' THEN SET `token` = 'Timer_20'; + WHEN '163' THEN SET `token` = 'Alaris'; + ELSE SET `token` = 'unk'; + END CASE; + + SET `token` = CONCAT(`token`, '(', `type_description_id`, ')'); + + RETURN `token`; +END$$ + +DELIMITER ; From 57d75572b22eb3ced95cdc81e7b48984bd9de5a4 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 8 Feb 2017 17:28:54 -0600 Subject: [PATCH 544/693] Heavily reduce idle cpu footprint with many zone processes loaded simultaneously and not active --- zone/net.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/zone/net.cpp b/zone/net.cpp index 25d6f65df..2f67c85d3 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -546,7 +546,13 @@ int main(int argc, char** argv) { #endif #endif } //end extra profiler block - Sleep(ZoneTimerResolution); + if (is_zone_loaded) { + Sleep(ZoneTimerResolution); + } + else { + Sleep(1000); + } + } entity_list.Clear(); From a81212e1b4721cbbb369b4512b891caf0c0a8b55 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 8 Feb 2017 18:00:38 -0600 Subject: [PATCH 545/693] Allow admin telnet connections from localhost without requiring credentials to world --- world/console.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/world/console.cpp b/world/console.cpp index a933ad56f..5f1598654 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -224,9 +224,27 @@ bool Console::Process() { } //if we have not gotten the special markers after this timer, send login prompt if(prompt_timer.Check()) { + struct in_addr in; + in.s_addr = GetIP(); + + std::string connecting_ip = inet_ntoa(in); + + SendMessage(2, StringFormat("Establishing connection from IP: %s Port: %d", inet_ntoa(in), GetPort()).c_str()); + + if (connecting_ip.find("127.0.0.1") != std::string::npos) { + SendMessage(2, StringFormat("Connecting established from local host, auto assuming admin").c_str()); + state = CONSOLE_STATE_CONNECTED; + tcpc->SetEcho(false); + admin = 255; + SendPrompt(); + } + else { + if (tcpc->GetMode() == EmuTCPConnection::modeConsole) + tcpc->Send((const uchar*) "Username: ", strlen("Username: ")); + } + prompt_timer.Disable(); - if(tcpc->GetMode() == EmuTCPConnection::modeConsole) - tcpc->Send((const uchar*) "Username: ", strlen("Username: ")); + } if (timeout_timer.Check()) { From 9e49b2ae0fbedd341921e2544c85bd3b620a446a Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Wed, 8 Feb 2017 19:01:50 -0600 Subject: [PATCH 546/693] Update for Ubuntu 16.04 This should be fully working with Ubuntu 16.04 Server. --- utils/scripts/linux_installer/install.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh index 5d43230c5..97cfa582e 100644 --- a/utils/scripts/linux_installer/install.sh +++ b/utils/scripts/linux_installer/install.sh @@ -87,6 +87,7 @@ echo "mysql_eqemu_password:$eqemu_db_password" >> install_variables.txt if [[ "$OS" == "Debian" ]]; then # Install pre-req packages + apt-get -y update apt-get $apt_options install bash apt-get $apt_options install build-essential apt-get $apt_options install cmake @@ -105,6 +106,8 @@ if [[ "$OS" == "Debian" ]]; then apt-get $apt_options install libperl-dev apt-get $apt_options install libperl5i-perl apt-get $apt_options install libwtdbomysql-dev + apt-get $apt_options install libmysqlclient-dev + apt-get $apt_options install minizip apt-get $apt_options install lua5.1 apt-get $apt_options install make apt-get $apt_options install mariadb-client From c83bc038f30e51a1f1ab98ade4aac95e5a9b3d64 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 9 Feb 2017 01:32:26 -0600 Subject: [PATCH 547/693] Fix issue with installer pulling down the wrong opcodes for SOD+ clients on Linux Loginserver --- utils/scripts/eqemu_server.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index e0960847e..b81520a3c 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -1340,7 +1340,7 @@ sub do_linux_login_server_setup { get_remote_file($install_repository_request_url . "linux/login.ini", "login_template.ini"); get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes.conf"); - get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes_sod.conf"); + get_remote_file($install_repository_request_url . "linux/login_opcodes_sod.conf", "login_opcodes_sod.conf"); get_installation_variables(); my $db_name = $installation_variables{"mysql_eqemu_db_name"}; From 38651258fcf9025e45c5aeda9a6cb2f75681d295 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 9 Feb 2017 17:57:55 -0500 Subject: [PATCH 549/693] Updated npc spell types to 32-bit mask --- common/spdat.h | 47 ++++++++++--------- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + ...7_02_09_npc_spells_entries_type_update.sql | 1 + zone/bot.cpp | 2 +- zone/bot.h | 10 ++-- zone/botspellsai.cpp | 8 ++-- zone/entity.h | 4 +- zone/merc.cpp | 8 ++-- zone/merc.h | 10 ++-- zone/mob_ai.cpp | 4 +- zone/npc.h | 4 +- 12 files changed, 54 insertions(+), 47 deletions(-) create mode 100644 utils/sql/git/required/2017_02_09_npc_spells_entries_type_update.sql diff --git a/common/spdat.h b/common/spdat.h index 3344489df..4168b283c 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -43,29 +43,34 @@ const int Z_AGGRO=10; -const int MobAISpellRange=100; // max range of buffs -const int SpellType_Nuke=1; -const int SpellType_Heal=2; -const int SpellType_Root=4; -const int SpellType_Buff=8; -const int SpellType_Escape=16; -const int SpellType_Pet=32; -const int SpellType_Lifetap=64; -const int SpellType_Snare=128; -const int SpellType_DOT=256; -const int SpellType_Dispel=512; -const int SpellType_InCombatBuff=1024; -const int SpellType_Mez=2048; -const int SpellType_Charm=4096; -const int SpellType_Slow = 8192; -const int SpellType_Debuff = 16384; -const int SpellType_Cure = 32768; -const int SpellType_Resurrect = 65536; +const uint32 MobAISpellRange=100; // max range of buffs -const int SpellTypes_Detrimental = SpellType_Nuke|SpellType_Root|SpellType_Lifetap|SpellType_Snare|SpellType_DOT|SpellType_Dispel|SpellType_Mez|SpellType_Charm|SpellType_Debuff|SpellType_Slow; -const int SpellTypes_Beneficial = SpellType_Heal|SpellType_Buff|SpellType_Escape|SpellType_Pet|SpellType_InCombatBuff|SpellType_Cure; +enum SpellTypes : uint32 +{ + SpellType_Nuke = (1 << 0), + SpellType_Heal = (1 << 1), + SpellType_Root = (1 << 2), + SpellType_Buff = (1 << 3), + SpellType_Escape = (1 << 4), + SpellType_Pet = (1 << 5), + SpellType_Lifetap = (1 << 6), + SpellType_Snare = (1 << 7), + SpellType_DOT = (1 << 8), + SpellType_Dispel = (1 << 9), + SpellType_InCombatBuff = (1 << 10), + SpellType_Mez = (1 << 11), + SpellType_Charm = (1 << 12), + SpellType_Slow = (1 << 13), + SpellType_Debuff = (1 << 14), + SpellType_Cure = (1 << 15), + SpellType_Resurrect = (1 << 16), + + SpellTypes_Detrimental = (SpellType_Nuke | SpellType_Root | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Charm | SpellType_Debuff | SpellType_Slow), + SpellTypes_Beneficial = (SpellType_Heal | SpellType_Buff | SpellType_Escape | SpellType_Pet | SpellType_InCombatBuff | SpellType_Cure), + + SpellType_Any = 0xFFFFFFFF +}; -#define SpellType_Any 0xFFFF // These should not be used to determine spell category.. // They are a graphical affects (effects?) index only diff --git a/common/version.h b/common/version.h index f7f2ad05d..7afe02279 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9103 +#define CURRENT_BINARY_DATABASE_VERSION 9104 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 2c27d858d..98dc22fc1 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -357,6 +357,7 @@ 9101|2016_12_01_pcnpc_only.sql|SHOW COLUMNS FROM `spells_new` LIKE 'pcnpc_only_flag'|empty| 9102|2017_01_10_book_languages.sql|SHOW COLUMNS FROM `books` LIKE 'language'|empty| 9103|2017_01_30_book_languages_fix.sql|SELECT `language` from `books` WHERE `language` IS NULL|not_empty| +9104|2017_02_09_npc_spells_entries_type_update.sql|SHOW COLUMNS IN `npc_spells_entries` LIKE `type`|contains|smallint(5) unsigned # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2017_02_09_npc_spells_entries_type_update.sql b/utils/sql/git/required/2017_02_09_npc_spells_entries_type_update.sql new file mode 100644 index 000000000..faa46e86e --- /dev/null +++ b/utils/sql/git/required/2017_02_09_npc_spells_entries_type_update.sql @@ -0,0 +1 @@ +ALTER TABLE `npc_spells_entries` MODIFY COLUMN `type` INT(10) UNSIGNED NOT NULL DEFAULT '0'; diff --git a/zone/bot.cpp b/zone/bot.cpp index d5f6ff814..56d8fd5d1 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -7495,7 +7495,7 @@ bool Bot::GroupHasClass(Group* group, uint8 classId) { return result; } -bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint16 iSpellTypes) { +bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint32 iSpellTypes) { if((iSpellTypes&SpellTypes_Detrimental) != 0) { Log.Out(Logs::General, Logs::Error, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!"); return false; diff --git a/zone/bot.h b/zone/bot.h index bda693094..dda1c5f0e 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -235,7 +235,7 @@ public: virtual void Depop(); void CalcBotStats(bool showtext = true); uint16 BotGetSpells(int spellslot) { return AIspells[spellslot].spellid; } - uint16 BotGetSpellType(int spellslot) { return AIspells[spellslot].type; } + uint32 BotGetSpellType(int spellslot) { return AIspells[spellslot].type; } uint16 BotGetSpellPriority(int spellslot) { return AIspells[spellslot].priority; } virtual float GetProcChances(float ProcBonus, uint16 hand); virtual int GetHandToHandDamage(void); @@ -350,7 +350,7 @@ public: void DoEnduranceUpkeep(); //does the endurance upkeep // AI Methods - virtual bool AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes); + virtual bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes); virtual bool AI_EngagedCastCheck(); virtual bool AI_PursueCastCheck(); virtual bool AI_IdleCastCheck(); @@ -416,8 +416,8 @@ public: static uint32 GetDisciplineRemainingTime(Bot *caster, int timer_index); static std::list GetBotSpellsForSpellEffect(Bot* botCaster, int spellEffect); static std::list GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, int spellEffect, SpellTargetType targetType); - static std::list GetBotSpellsBySpellType(Bot* botCaster, uint16 spellType); - static BotSpell GetFirstBotSpellBySpellType(Bot* botCaster, uint16 spellType); + static std::list GetBotSpellsBySpellType(Bot* botCaster, uint32 spellType); + static BotSpell GetFirstBotSpellBySpellType(Bot* botCaster, uint32 spellType); static BotSpell GetBestBotSpellForFastHeal(Bot* botCaster); static BotSpell GetBestBotSpellForHealOverTime(Bot* botCaster); static BotSpell GetBestBotSpellForPercentageHeal(Bot* botCaster); @@ -467,7 +467,7 @@ public: bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; } BotRoleType GetBotRole() { return _botRole; } BotStanceType GetBotStance() { return _botStance; } - uint8 GetChanceToCastBySpellType(uint16 spellType); + uint8 GetChanceToCastBySpellType(uint32 spellType); bool IsGroupPrimaryHealer(); bool IsGroupPrimarySlower(); bool IsBotCaster() { return IsCasterClass(GetClass()); } diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index a35760535..c36e928bb 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -29,7 +29,7 @@ #define BotAI_DEBUG_Spells -1 #endif -bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { +bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { if (!tar) { return false; @@ -1417,7 +1417,7 @@ std::list Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, return result; } -std::list Bot::GetBotSpellsBySpellType(Bot* botCaster, uint16 spellType) { +std::list Bot::GetBotSpellsBySpellType(Bot* botCaster, uint32 spellType) { std::list result; if(botCaster && botCaster->AI_HasSpells()) { @@ -1444,7 +1444,7 @@ std::list Bot::GetBotSpellsBySpellType(Bot* botCaster, uint16 spellTyp return result; } -BotSpell Bot::GetFirstBotSpellBySpellType(Bot* botCaster, uint16 spellType) { +BotSpell Bot::GetFirstBotSpellBySpellType(Bot* botCaster, uint32 spellType) { BotSpell result; result.SpellId = 0; @@ -3324,7 +3324,7 @@ void Bot::CalcChanceToCast() { _spellCastingChances[botStance][SpellType_CureIndex] = castChance; } -uint8 Bot::GetChanceToCastBySpellType(uint16 spellType) { +uint8 Bot::GetChanceToCastBySpellType(uint32 spellType) { int index = 0; int botStance = (int)GetBotStance(); uint8 chance = 0; diff --git a/zone/entity.h b/zone/entity.h index 9a532cdb1..1ea9a4c03 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -413,7 +413,7 @@ public: Mob* AICheckCloseAggro(Mob* sender, float iAggroRange, float iAssistRange); int GetHatedCount(Mob *attacker, Mob *exclude); void AIYellForHelp(Mob* sender, Mob* attacker); - bool AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint16 iSpellTypes); + bool AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes); bool Merc_AICheckCloseBeneficialSpells(Merc* caster, uint8 iChance, float iRange, uint32 iSpellTypes); Mob* GetTargetForMez(Mob* caster); uint32 CheckNPCsClose(Mob *center); @@ -502,7 +502,7 @@ private: Bot* GetBotByBotName(std::string botName); std::list GetBotsByBotOwnerCharacterID(uint32 botOwnerCharacterID); - bool Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint16 iSpellTypes); // TODO: Evaluate this closesly in hopes to eliminate + bool Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint32 iSpellTypes); // TODO: Evaluate this closesly in hopes to eliminate void ShowSpawnWindow(Client* client, int Distance, bool NamedOnly); // TODO: Implement ShowSpawnWindow in the bot class but it needs entity list stuff private: std::list bot_list; diff --git a/zone/merc.cpp b/zone/merc.cpp index be8f75e60..3e3dfae93 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1985,7 +1985,7 @@ bool Merc::AIDoSpellCast(uint16 spellid, Mob* tar, int32 mana_cost, uint32* oDon return result; } -bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) { +bool Merc::AICastSpell(int8 iChance, uint32 iSpellTypes) { if(!AI_HasSpells()) return false; @@ -2746,7 +2746,7 @@ int32 Merc::GetActSpellCasttime(uint16 spell_id, int32 casttime) return casttime; } -int8 Merc::GetChanceToCastBySpellType(int16 spellType) { +int8 Merc::GetChanceToCastBySpellType(uint32 spellType) { int mercStance = (int)GetStance(); int8 mercClass = GetClass(); int8 chance = 0; @@ -2888,7 +2888,7 @@ bool Merc::CheckStance(int16 stance) { return false; } -std::list Merc::GetMercSpellsBySpellType(Merc* caster, int spellType) { +std::list Merc::GetMercSpellsBySpellType(Merc* caster, uint32 spellType) { std::list result; if(caster && caster->AI_HasSpells()) { @@ -2918,7 +2918,7 @@ std::list Merc::GetMercSpellsBySpellType(Merc* caster, int spellType) return result; } -MercSpell Merc::GetFirstMercSpellBySpellType(Merc* caster, int spellType) { +MercSpell Merc::GetFirstMercSpellBySpellType(Merc* caster, uint32 spellType) { MercSpell result; result.spellid = 0; diff --git a/zone/merc.h b/zone/merc.h index 7bd4c2b9b..e3eb6c029 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -78,8 +78,8 @@ public: virtual void AI_Stop(); virtual void AI_Process(); - //virtual bool AICastSpell(Mob* tar, int8 iChance, int16 iSpellTypes); - virtual bool AICastSpell(int8 iChance, int32 iSpellTypes); + //virtual bool AICastSpell(Mob* tar, int8 iChance, uint32 iSpellTypes); + virtual bool AICastSpell(int8 iChance, uint32 iSpellTypes); virtual bool AIDoSpellCast(uint16 spellid, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); virtual bool AI_EngagedCastCheck(); //virtual bool AI_PursueCastCheck(); @@ -97,7 +97,7 @@ public: // Merc Spell Casting Methods virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime); virtual int32 GetActSpellCost(uint16 spell_id, int32 cost); - int8 GetChanceToCastBySpellType(int16 spellType); + int8 GetChanceToCastBySpellType(uint32 spellType); void SetSpellRecastTimer(uint16 timer_id, uint16 spellid, uint32 recast_delay); void SetDisciplineRecastTimer(uint16 timer_id, uint16 spellid, uint32 recast_delay); void SetSpellTimeCanCast(uint16 spellid, uint32 recast_delay); @@ -108,8 +108,8 @@ public: static int32 GetDisciplineRemainingTime(Merc *caster, uint16 timer_id); static std::list GetMercSpellsForSpellEffect(Merc* caster, int spellEffect); static std::list GetMercSpellsForSpellEffectAndTargetType(Merc* caster, int spellEffect, SpellTargetType targetType); - static std::list GetMercSpellsBySpellType(Merc* caster, int spellType); - static MercSpell GetFirstMercSpellBySpellType(Merc* caster, int spellType); + static std::list GetMercSpellsBySpellType(Merc* caster, uint32 spellType); + static MercSpell GetFirstMercSpellBySpellType(Merc* caster, uint32 spellType); static MercSpell GetFirstMercSpellForSingleTargetHeal(Merc* caster); static MercSpell GetMercSpellBySpellID(Merc* caster, uint16 spellid); static MercSpell GetBestMercSpellForVeryFastHeal(Merc* caster); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index d2340581d..5034925d9 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -47,7 +47,7 @@ extern Zone *zone; #endif //NOTE: do NOT pass in beneficial and detrimental spell types into the same call here! -bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes) { +bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { if (!tar) return false; @@ -344,7 +344,7 @@ bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain return CastSpell(AIspells[i].spellid, tar->GetID(), EQEmu::CastingSlot::Gem2, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust)); } -bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint16 iSpellTypes) { +bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes) { if((iSpellTypes&SpellTypes_Detrimental) != 0) { //according to live, you can buff and heal through walls... //now with PCs, this only applies if you can TARGET the target, but diff --git a/zone/npc.h b/zone/npc.h index 543725c28..2db110d98 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -54,7 +54,7 @@ typedef struct { } NPCProximity; struct AISpells_Struct { - uint16 type; // 0 = never, must be one (and only one) of the defined values + uint32 type; // 0 = never, must be one (and only one) of the defined values uint16 spellid; // <= 0 = no spell int16 manacost; // -1 = use spdat, -2 = no cast time uint32 time_cancast; // when we can cast this spell next @@ -453,7 +453,7 @@ protected: uint32* pDontCastBefore_casting_spell; std::vector AIspells; bool HasAISpell; - virtual bool AICastSpell(Mob* tar, uint8 iChance, uint16 iSpellTypes); + virtual bool AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes); virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); AISpellsVar_Struct AISpellVar; int16 GetFocusEffect(focusType type, uint16 spell_id); From ed717add299c0a4d07e4183fc6bcd35cf71c2491 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 11 Feb 2017 18:33:58 -0500 Subject: [PATCH 550/693] Added a few more SpellType enumerations (uncoded) --- common/spdat.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/spdat.h b/common/spdat.h index 4168b283c..ba275f933 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -64,9 +64,12 @@ enum SpellTypes : uint32 SpellType_Debuff = (1 << 14), SpellType_Cure = (1 << 15), SpellType_Resurrect = (1 << 16), + SpellType_HateRedux = (1 << 17), + SpellType_InCombatBuffSong = (1 << 18), + SpellType_OutOfCombatBuffSong = (1 << 19), SpellTypes_Detrimental = (SpellType_Nuke | SpellType_Root | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Charm | SpellType_Debuff | SpellType_Slow), - SpellTypes_Beneficial = (SpellType_Heal | SpellType_Buff | SpellType_Escape | SpellType_Pet | SpellType_InCombatBuff | SpellType_Cure), + SpellTypes_Beneficial = (SpellType_Heal | SpellType_Buff | SpellType_Escape | SpellType_Pet | SpellType_InCombatBuff | SpellType_Cure | SpellType_HateRedux | SpellType_InCombatBuffSong | SpellType_OutOfCombatBuffSong), SpellType_Any = 0xFFFFFFFF }; From 955514c20ffdf75878995febe291164bd474945f Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 12 Feb 2017 23:16:38 -0600 Subject: [PATCH 551/693] eqemu_server.pl Linux make routine compile with the amount of cores available [skip ci] --- utils/scripts/eqemu_server.pl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index b81520a3c..0fcfa9161 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -334,8 +334,9 @@ sub build_linux_source { } print "Building EQEmu Server code. This will take a while."; - #::: Build - print `make`; + #::: Build + $processor_cores = `cat /proc/cpuinfo | grep -c ^processor /proc/cpuinfo`; + print `make -j$processor_cores`; chdir ($current_directory); From 0f32f780a9d9dab0ec54808be224b1e795db077b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 12 Feb 2017 23:31:25 -0600 Subject: [PATCH 552/693] Revert previous change to keep installation memory safe and independent [skip ci] --- utils/scripts/eqemu_server.pl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 0fcfa9161..e9ba02099 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -335,8 +335,7 @@ sub build_linux_source { print "Building EQEmu Server code. This will take a while."; #::: Build - $processor_cores = `cat /proc/cpuinfo | grep -c ^processor /proc/cpuinfo`; - print `make -j$processor_cores`; + print `make`; chdir ($current_directory); From 92d4468326026549c487a6cc84a4601773307ee1 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 13 Feb 2017 01:26:19 -0600 Subject: [PATCH 553/693] Put a category enabled filter on default switch case so we're not chewing up extra cpu cycles --- loginserver/client.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/loginserver/client.cpp b/loginserver/client.cpp index 9a6a81593..6f64b5899 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -99,9 +99,11 @@ bool Client::Process() } default: { - char dump[64]; - app->build_header_dump(dump); - Log.Out(Logs::General, Logs::Error, "Recieved unhandled application packet from the client: %s.", dump); + if (Log.log_settings[Logs::Client_Server_Packet_Unhandled].is_category_enabled == 1) { + char dump[64]; + app->build_header_dump(dump); + Log.Out(Logs::General, Logs::Error, "Recieved unhandled application packet from the client: %s.", dump); + } } } From fe215646592331b1a95b20b0d8e2dff5397609f3 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 13 Feb 2017 01:38:23 -0600 Subject: [PATCH 554/693] Apply KLS' tweaks to Log.Out (CPU saves) https://github.com/EQEmu/Server/commit/1d055b5364a4183a327683dfa13cf33954874616 --- common/eqemu_logsys.cpp | 57 ++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index 4c0ee1c9f..78a26c5dc 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -123,26 +123,21 @@ void EQEmuLogSys::LoadLogSettingsDefaults() std::string EQEmuLogSys::FormatOutMessageString(uint16 log_category, const std::string &in_message) { - std::string category_string; - if (log_category > 0 && Logs::LogCategoryName[log_category]) - category_string = StringFormat("[%s] ", Logs::LogCategoryName[log_category]); - return StringFormat("%s%s", category_string.c_str(), in_message.c_str()); + std::string ret; + ret.push_back('['); + ret.append(Logs::LogCategoryName[log_category]); + ret.push_back(']'); + ret.push_back(' '); + ret.append(in_message); + return ret; } void EQEmuLogSys::ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message) { - /* Check if category enabled for process */ - if (log_settings[log_category].log_to_gmsay == 0) - return; - /* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash */ if (log_category == Logs::LogCategory::Netcode) return; - /* Make sure the message inbound is at a debug level we're set at */ - if (log_settings[log_category].log_to_gmsay < debug_level) - return; - /* Check to see if the process that actually ran this is zone */ if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) on_log_gmsay_hook(log_category, message); @@ -160,14 +155,6 @@ void EQEmuLogSys::ProcessLogWrite(uint16 debug_level, uint16 log_category, const crash_log.close(); } - /* Check if category enabled for process */ - if (log_settings[log_category].log_to_file == 0) - return; - - /* Make sure the message inbound is at a debug level we're set at */ - if (log_settings[log_category].log_to_file < debug_level) - return; - char time_stamp[80]; EQEmuLogSys::SetCurrentTimeStamp(time_stamp); @@ -246,13 +233,6 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) { void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message) { - /* Check if category enabled for process */ - if (log_settings[log_category].log_to_console == 0) - return; - - /* Make sure the message inbound is at a debug level we're set at */ - if (log_settings[log_category].log_to_console < debug_level) - return; #ifdef _WINDOWS HANDLE console_handle; @@ -273,12 +253,25 @@ void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...) { - const bool log_to_console = log_settings[log_category].log_to_console > 0; - const bool log_to_file = log_settings[log_category].log_to_file > 0; - const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0; - const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay; - if (nothing_to_log) return; + bool log_to_console = true; + if (log_settings[log_category].log_to_console < debug_level) { + log_to_console = false; + } + + bool log_to_file = true; + if (log_settings[log_category].log_to_file < debug_level) { + log_to_file = false; + } + + bool log_to_gmsay = true; + if (log_settings[log_category].log_to_gmsay < debug_level) { + log_to_gmsay = false; + } + + const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay; + if (nothing_to_log) + return; va_list args; va_start(args, message); From ef165224731eeac848e6a5181d017b31ed228734 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 13 Feb 2017 02:16:40 -0600 Subject: [PATCH 555/693] Implement Rule Zone:GlobalLootMultiplier (Default 1) - Sets Global Loot drop multiplier for database based drops, useful for double, triple loot etc. --- common/ruletypes.h | 1 + zone/loottables.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 5323fda49..f972034f0 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -258,6 +258,7 @@ RULE_BOOL(Zone, EnableLoggedOffReplenishments, true) RULE_INT(Zone, MinOfflineTimeToReplenishments, 21600) // 21600 seconds is 6 Hours RULE_BOOL(Zone, UseZoneController, true) // Enables the ability to use persistent quest based zone controllers (zone_controller.pl/lua) RULE_BOOL(Zone, EnableZoneControllerGlobals, false) // Enables the ability to use quest globals with the zone controller NPC +RULE_INT(Zone, GlobalLootMultiplier, 1) // Sets Global Loot drop multiplier for database based drops, useful for double, triple loot etc. RULE_CATEGORY_END() RULE_CATEGORY(Map) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 7f8e371bd..3297dec60 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -80,10 +80,11 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite *copper = cash; } + uint32 global_loot_multiplier = RuleI(Zone, GlobalLootMultiplier); // Do items for (uint32 i=0; iNumEntries; i++) { - for (uint32 k = 1; k <= lts->Entries[i].multiplier; k++) { + for (uint32 k = 1; k <= (lts->Entries[i].multiplier * global_loot_multiplier); k++) { uint8 droplimit = lts->Entries[i].droplimit; uint8 mindrop = lts->Entries[i].mindrop; From 5b8ad902ce367cf70d9ebc68eb9cf6c9ce46e718 Mon Sep 17 00:00:00 2001 From: JJ Date: Mon, 13 Feb 2017 16:00:39 -0500 Subject: [PATCH 556/693] Add character_tasks to the list when deleting a character. --- common/database.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/common/database.cpp b/common/database.cpp index 423bbac58..b06540cbd 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -307,6 +307,7 @@ bool Database::DeleteCharacter(char *name) { query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", charid); QueryDatabase(query); query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", charid); QueryDatabase(query); query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_tasks` WHERE `charid` = '%d'", charid); QueryDatabase(query); query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", charid); QueryDatabase(query); query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", charid); QueryDatabase(query); query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", charid); QueryDatabase(query); From d043c38f71eef1436a8fc11b85e09b5a1480f7f4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 14 Feb 2017 16:39:31 -0500 Subject: [PATCH 557/693] Make it so enraged NPCs can't be riposted This should prevent infinite loops --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 801242d45..826ae713b 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -358,7 +358,7 @@ bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) } // riposte -- it may seem crazy, but if the attacker has SPA 173 on them, they are immune to Ripo - bool ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance; + bool ImmuneRipo = attacker->aabonuses.RiposteChance || attacker->spellbonuses.RiposteChance || attacker->itembonuses.RiposteChance || attacker->IsEnraged(); // Need to check if we have something in MainHand to actually attack with (or fists) if (hit.hand != EQEmu::inventory::slotRange && (CanThisClassRiposte() || IsEnraged()) && InFront && !ImmuneRipo) { if (IsEnraged()) { From d62a449f9cf44505a149a6dff2c096ba816e789a Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 15 Feb 2017 07:03:43 -0500 Subject: [PATCH 558/693] Missed an npc spells type (or two..) --- zone/mob_ai.cpp | 4 ++-- zone/npc.h | 2 +- zone/zonedb.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 5034925d9..896709fc8 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2496,7 +2496,7 @@ bool IsSpellInList(DBnpcspells_Struct* spell_list, int16 iSpellID) { } // adds a spell to the list, taking into account priority and resorting list as needed. -void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint16 iType, +void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint32 iType, int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust) { @@ -2646,7 +2646,7 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { { int spell_id = atoi(row[0]); npc_spells_cache[iDBSpellsID]->entries[entryIndex].spellid = spell_id; - npc_spells_cache[iDBSpellsID]->entries[entryIndex].type = atoi(row[1]); + npc_spells_cache[iDBSpellsID]->entries[entryIndex].type = atoul(row[1]); npc_spells_cache[iDBSpellsID]->entries[entryIndex].minlevel = atoi(row[2]); npc_spells_cache[iDBSpellsID]->entries[entryIndex].maxlevel = atoi(row[3]); npc_spells_cache[iDBSpellsID]->entries[entryIndex].manacost = atoi(row[4]); diff --git a/zone/npc.h b/zone/npc.h index 2db110d98..5dcc7eac9 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -377,7 +377,7 @@ public: void NPCSlotTexture(uint8 slot, uint16 texture); // Sets new material values for slots uint32 GetAdventureTemplate() const { return adventure_template_id; } - void AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint16 iType, int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust); + void AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint32 iType, int16 iManaCost, int32 iRecastDelay, int16 iResistAdjust); void AddSpellEffectToNPCList(uint16 iSpellEffectID, int32 base, int32 limit, int32 max); void RemoveSpellFromNPCList(int16 spell_id); Timer *GetRefaceTimer() const { return reface_timer; } diff --git a/zone/zonedb.h b/zone/zonedb.h index 1c96ee298..46ce825e4 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -45,7 +45,7 @@ struct wplist { #pragma pack(1) struct DBnpcspells_entries_Struct { int16 spellid; - uint16 type; + uint32 type; uint8 minlevel; uint8 maxlevel; int16 manacost; From e3c8b7525924b82310851b0b6e441c52a0bc0420 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 15 Feb 2017 07:42:17 -0500 Subject: [PATCH 559/693] Moved bot spell entries out of npc spell entries (easier to manage bot changes by committing to non-bot manifest) --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../2017_02_15_bot_spells_entries.sql | 31 +++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2017_02_15_bot_spells_entries.sql diff --git a/common/version.h b/common/version.h index 7afe02279..88f986807 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9104 +#define CURRENT_BINARY_DATABASE_VERSION 9105 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 98dc22fc1..c21f60f4b 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -358,6 +358,7 @@ 9102|2017_01_10_book_languages.sql|SHOW COLUMNS FROM `books` LIKE 'language'|empty| 9103|2017_01_30_book_languages_fix.sql|SELECT `language` from `books` WHERE `language` IS NULL|not_empty| 9104|2017_02_09_npc_spells_entries_type_update.sql|SHOW COLUMNS IN `npc_spells_entries` LIKE `type`|contains|smallint(5) unsigned +9105|2017_02_15_bot_spells_entries.sql|SELECT `id` FROM `npc_spells_entries` WHERE `npc_spells_id` >= 701 AND `npc_spells_id` <= 712|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2017_02_15_bot_spells_entries.sql b/utils/sql/git/required/2017_02_15_bot_spells_entries.sql new file mode 100644 index 000000000..7f3a73d98 --- /dev/null +++ b/utils/sql/git/required/2017_02_15_bot_spells_entries.sql @@ -0,0 +1,31 @@ +-- Delete any existing `bots_spells_entries` table +DROP TABLE IF EXISTS `bots_spells_entries`; + +-- Create new bot spells entries table (new table does not have spells_id_spellid constraint) +CREATE TABLE `bot_spells_entries` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_spells_id` INT(11) NOT NULL DEFAULT '0', + `spellid` SMALLINT(5) NOT NULL DEFAULT '0', + `type` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `minlevel` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `maxlevel` TINYINT(3) UNSIGNED NOT NULL DEFAULT '255', + `manacost` SMALLINT(5) NOT NULL DEFAULT '-1', + `recast_delay` INT(11) NOT NULL DEFAULT '-1', + `priority` SMALLINT(5) NOT NULL DEFAULT '0', + `resist_adjust` INT(11) NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1 +; + +-- Copy bots spells into new table +INSERT INTO `bot_spells_entries` (`npc_spells_id`, `spellid`, `type`, `minlevel`, `maxlevel`, `manacost`, `recast_delay`, `priority`, `resist_adjust`) +SELECT `npc_spells_id`, `spellid`, `type`, `minlevel`, `maxlevel`, `manacost`, `recast_delay`, `priority`, `resist_adjust` +FROM `npc_spells_entries` WHERE `npc_spells_id` >= '701' AND `npc_spells_id` <= '712'; + +-- Delete bot spells from old table +DELETE FROM `npc_spells_entries` WHERE `npc_spells_id` >= '701' AND `npc_spells_id` <= '712'; + +-- Admins can remove this new table if they are 100% certain they will never use bots From 8177f7d9bb0a55738900d0be9854deea6945668d Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 15 Feb 2017 19:04:36 -0500 Subject: [PATCH 560/693] Activation of `bot_spells_entries` table --- common/version.h | 2 +- .../sql/git/bots/bots_db_update_manifest.txt | 1 + .../2017_02_15_bots_bot_spells_entries.sql | 29 +++++++++++++++++++ zone/mob_ai.cpp | 7 ++++- 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 utils/sql/git/bots/required/2017_02_15_bots_bot_spells_entries.sql diff --git a/common/version.h b/common/version.h index 88f986807..bda89dd8c 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9105 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9008 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9009 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 3122545a0..d63c142c8 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -7,6 +7,7 @@ 9006|2016_04_12_bots_inventory_window.sql|SELECT `bot_command` FROM `bot_command_settings` WHERE `bot_command` LIKE 'inventorywindow'|empty| 9007|2016_06_23_bots_camel_case_name_rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AllowCamelCaseNames'|empty| 9008|2016_06_28_bots_inventory_charges_update.sql|SELECT * FROM `information_schema`.`COLUMNS` isc WHERE isc.`TABLE_SCHEMA` = DATABASE() AND isc.`TABLE_NAME` = 'bot_inventories' AND isc.`COLUMN_NAME` = 'inst_charges' AND isc.`DATA_TYPE` = 'tinyint'|not_empty| +9009|2017_02_15_bots_bot_spells_entries.sql|SELECT `id` FROM `npc_spells_entries` WHERE `npc_spells_id` >= 701 AND `npc_spells_id` <= 712|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2017_02_15_bots_bot_spells_entries.sql b/utils/sql/git/bots/required/2017_02_15_bots_bot_spells_entries.sql new file mode 100644 index 000000000..c7d5087e6 --- /dev/null +++ b/utils/sql/git/bots/required/2017_02_15_bots_bot_spells_entries.sql @@ -0,0 +1,29 @@ +-- Delete any existing `bots_spells_entries` table +DROP TABLE IF EXISTS `bots_spells_entries`; + +-- Create new bot spells entries table (new table does not have spells_id_spellid constraint) +CREATE TABLE `bot_spells_entries` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `npc_spells_id` INT(11) NOT NULL DEFAULT '0', + `spellid` SMALLINT(5) NOT NULL DEFAULT '0', + `type` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `minlevel` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `maxlevel` TINYINT(3) UNSIGNED NOT NULL DEFAULT '255', + `manacost` SMALLINT(5) NOT NULL DEFAULT '-1', + `recast_delay` INT(11) NOT NULL DEFAULT '-1', + `priority` SMALLINT(5) NOT NULL DEFAULT '0', + `resist_adjust` INT(11) NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +AUTO_INCREMENT=1 +; + +-- Copy bots spells into new table +INSERT INTO `bot_spells_entries` (`npc_spells_id`, `spellid`, `type`, `minlevel`, `maxlevel`, `manacost`, `recast_delay`, `priority`, `resist_adjust`) +SELECT `npc_spells_id`, `spellid`, `type`, `minlevel`, `maxlevel`, `manacost`, `recast_delay`, `priority`, `resist_adjust` +FROM `npc_spells_entries` WHERE `npc_spells_id` >= '701' AND `npc_spells_id` <= '712'; + +-- Delete bot spells from old table +DELETE FROM `npc_spells_entries` WHERE `npc_spells_id` >= '701' AND `npc_spells_id` <= '712'; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 896709fc8..294247d59 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2608,8 +2608,13 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { query = StringFormat("SELECT spellid, type, minlevel, maxlevel, " "manacost, recast_delay, priority, resist_adjust " +#ifdef BOTS + "FROM %s " + "WHERE npc_spells_id=%d ORDER BY minlevel", (iDBSpellsID >= 701 && iDBSpellsID <= 712 ? "bot_spells_entries" : "npc_spells_entries"), iDBSpellsID); +#else "FROM npc_spells_entries " - "WHERE npc_spells_id=%d ORDER BY minlevel", iDBSpellsID); + "WHERE npc_spells_id=%d ORDER BY minlevel", iDBSpellsID); +#endif results = QueryDatabase(query); if (!results.Success()) From 9f4604ec3ebf8df4c1c1059a6a5865c576d77324 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 17 Feb 2017 21:04:48 -0500 Subject: [PATCH 561/693] Rework how XTarget auto haters work This should cause the auto haters to be shared with other toons who might be interested (group/raid) like live. There maybe some bugs since there is a lot of complex interactions here. --- zone/CMakeLists.txt | 2 + zone/attack.cpp | 6 +- zone/client.cpp | 194 +++++++++++++++++++++++++++---------- zone/client.h | 11 +++ zone/client_packet.cpp | 24 +++-- zone/client_process.cpp | 6 ++ zone/entity.cpp | 10 +- zone/groups.cpp | 38 +++++++- zone/groups.h | 8 +- zone/raids.cpp | 36 ++++++- zone/raids.h | 6 ++ zone/worldserver.cpp | 5 + zone/xtargetautohaters.cpp | 112 +++++++++++++++++++++ zone/xtargetautohaters.h | 48 +++++++++ 14 files changed, 435 insertions(+), 71 deletions(-) create mode 100644 zone/xtargetautohaters.cpp create mode 100644 zone/xtargetautohaters.h diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 532cc86cd..7bc96c3db 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -122,6 +122,7 @@ SET(zone_sources water_map_v2.cpp waypoints.cpp worldserver.cpp + xtargetautohaters.cpp zone.cpp zone_config.cpp zonedb.cpp @@ -215,6 +216,7 @@ SET(zone_headers water_map_v1.h water_map_v2.h worldserver.h + xtargetautohaters.h zone.h zone_config.h zonedb.h diff --git a/zone/attack.cpp b/zone/attack.cpp index 826ae713b..b7cd49384 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2432,9 +2432,9 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b Mob* mypet = this->GetPet(); Mob* myowner = this->GetOwner(); Mob* targetmob = this->GetTarget(); + bool on_hatelist = CheckAggro(other); if(other){ - bool on_hatelist = CheckAggro(other); AddRampage(other); if (on_hatelist) { // odd reason, if you're not on the hate list, subtlety etc don't apply! // Spell Casting Subtlety etc @@ -2510,7 +2510,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b hate_list.AddEntToHateList(other, hate, damage, bFrenzy, !iBuffTic); - if(other->IsClient()) + if(other->IsClient() && !on_hatelist) other->CastToClient()->AddAutoXTarget(this); #ifdef BOTS @@ -2549,7 +2549,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b if(!owner->GetSpecialAbility(IMMUNE_AGGRO)) { hate_list.AddEntToHateList(owner, 0, 0, false, !iBuffTic); - if(owner->IsClient()) + if(owner->IsClient() && !CheckAggro(owner)) owner->CastToClient()->AddAutoXTarget(this); } } diff --git a/zone/client.cpp b/zone/client.cpp index 1a5c02f1e..a3239eeb1 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -310,6 +310,8 @@ Client::Client(EQStreamInterface* ieqs) } MaxXTargets = 5; XTargetAutoAddHaters = true; + m_autohatermgr.SetOwner(this, nullptr, nullptr); + m_activeautohatermgr = &m_autohatermgr; LoadAccountFlags(); initial_respawn_selection = 0; @@ -4159,6 +4161,18 @@ bool Client::GroupFollow(Client* inviter) { } if (raid->RaidCount() < MAX_RAID_MEMBERS) { + // okay, so we now have a single client (this) joining a group in a raid + // And they're not already in the raid (which is above and doesn't need xtarget shit) + if (!GetXTargetAutoMgr()->empty()) { + raid->GetXTargetAutoMgr()->merge(*GetXTargetAutoMgr()); + GetXTargetAutoMgr()->clear(); + RemoveAutoXTargets(); + } + + SetXTargetAutoMgr(GetXTargetAutoMgr()); + if (!GetXTargetAutoMgr()->empty()) + SetDirtyAutoHaters(); + if (raid->GroupCount(groupToUse) < 6) { raid->SendRaidCreate(this); @@ -4234,7 +4248,9 @@ bool Client::GroupFollow(Client* inviter) { inviter->SendGroupLeaderChangePacket(inviter->GetName()); inviter->SendGroupJoinAcknowledge(); } - + group->GetXTargetAutoMgr()->merge(*inviter->GetXTargetAutoMgr()); + inviter->GetXTargetAutoMgr()->clear(); + inviter->SetXTargetAutoMgr(group->GetXTargetAutoMgr()); } if (!group) @@ -7171,12 +7187,12 @@ void Client::UpdateClientXTarget(Client *c) } } +// IT IS NOT SAFE TO CALL THIS IF IT'S NOT INITIAL AGGRO void Client::AddAutoXTarget(Mob *m, bool send) { - if(!XTargettingAvailable() || !XTargetAutoAddHaters) - return; + m_activeautohatermgr->increment_count(m); - if(IsXTarget(m)) + if (!XTargettingAvailable() || !XTargetAutoAddHaters || IsXTarget(m)) return; for(int i = 0; i < GetMaxXTargets(); ++i) @@ -7195,60 +7211,15 @@ void Client::AddAutoXTarget(Mob *m, bool send) void Client::RemoveXTarget(Mob *m, bool OnlyAutoSlots) { - if (!XTargettingAvailable()) - return; - - bool HadFreeAutoSlotsBefore = false; - - int FreedAutoSlots = 0; - - if (m->GetID() == 0) - return; - + m_activeautohatermgr->decrement_count(m); + // now we may need to clean up our CurrentTargetNPC entries for (int i = 0; i < GetMaxXTargets(); ++i) { - if (OnlyAutoSlots && XTargets[i].Type != Auto) - continue; - - if (XTargets[i].ID == m->GetID()) { - if (XTargets[i].Type == CurrentTargetNPC) - XTargets[i].Type = Auto; - - if (XTargets[i].Type == Auto) - ++FreedAutoSlots; - + if (XTargets[i].Type == CurrentTargetNPC && XTargets[i].ID == m->GetID()) { + XTargets[i].Type = Auto; XTargets[i].ID = 0; XTargets[i].dirty = true; - } else { - if (XTargets[i].Type == Auto && XTargets[i].ID == 0) - HadFreeAutoSlotsBefore = true; } } - - // move shit up! If the removed NPC was in a CurrentTargetNPC slot it becomes Auto - // and we need to potentially fill it - std::queue empty_slots; - for (int i = 0; i < GetMaxXTargets(); ++i) { - if (XTargets[i].Type != Auto) - continue; - - if (XTargets[i].ID == 0) { - empty_slots.push(i); - continue; - } - - if (XTargets[i].ID != 0 && !empty_slots.empty()) { - int temp = empty_slots.front(); - std::swap(XTargets[i], XTargets[temp]); - XTargets[i].dirty = XTargets[temp].dirty = true; - empty_slots.pop(); - empty_slots.push(i); - } - } - // If there are more mobs aggro on us than we had auto-hate slots, add one of those haters into the slot(s) we - // just freed up. - if (!HadFreeAutoSlotsBefore && FreedAutoSlots) - entity_list.RefreshAutoXTargets(this); - SendXTargetUpdates(); } void Client::UpdateXTargetType(XTargetType Type, Mob *m, const char *Name) @@ -7405,6 +7376,123 @@ void Client::ShowXTargets(Client *c) for(int i = 0; i < GetMaxXTargets(); ++i) c->Message(0, "Xtarget Slot: %i, Type: %2i, ID: %4i, Name: %s", i, XTargets[i].Type, XTargets[i].ID, XTargets[i].Name); + auto &list = GetXTargetAutoMgr()->get_list(); + // yeah, I kept having to do something for debugging to tell if managers were the same object or not :P + // so lets use the address as an "ID" + c->Message(0, "XTargetAutoMgr ID %p size %d", GetXTargetAutoMgr(), list.size()); + int count = 0; + for (auto &e : list) { + c->Message(0, "spawn id %d count %d", e.spawn_id, e.count); + count++; + if (count == 20) { // lets not spam too many ... + c->Message(0, " ... "); + break; + } + } +} + +void Client::ProcessXTargetAutoHaters() +{ + if (!XTargettingAvailable()) + return; + + // move shit up! If the removed NPC was in a CurrentTargetNPC slot it becomes Auto + // and we need to potentially fill it + std::queue empty_slots; + for (int i = 0; i < GetMaxXTargets(); ++i) { + if (XTargets[i].Type != Auto) + continue; + + if (XTargets[i].ID != 0 && !GetXTargetAutoMgr()->contains_mob(XTargets[i].ID)) { + XTargets[i].ID = 0; + XTargets[i].dirty = true; + } + + if (XTargets[i].ID == 0) { + empty_slots.push(i); + continue; + } + + if (XTargets[i].ID != 0 && !empty_slots.empty()) { + int temp = empty_slots.front(); + std::swap(XTargets[i], XTargets[temp]); + XTargets[i].dirty = XTargets[temp].dirty = true; + empty_slots.pop(); + empty_slots.push(i); + } + } + // okay, now we need to check if we have any empty slots and if we have aggro + // We make the assumption that if we shuffled the NPCs up that they're still on the aggro + // list in the same order. We could probably do this better and try to calc if + // there are new NPCs for our empty slots on the manager, but ahhh fuck it. + if (!empty_slots.empty() && !GetXTargetAutoMgr()->empty() && XTargetAutoAddHaters) { + auto &haters = GetXTargetAutoMgr()->get_list(); + for (auto &e : haters) { + auto *mob = entity_list.GetMob(e.spawn_id); + if (!IsXTarget(mob)) { + auto slot = empty_slots.front(); + empty_slots.pop(); + XTargets[slot].dirty = true; + XTargets[slot].ID = mob->GetID(); + strn0cpy(XTargets[slot].Name, mob->GetCleanName(), 64); + } + if (empty_slots.empty()) + break; + } + } + m_dirtyautohaters = false; + SendXTargetUpdates(); +} + +// This function is called when a client is added to a group +// Group leader joining isn't handled by this function +void Client::JoinGroupXTargets(Group *g) +{ + if (!g) + return; + + if (!GetXTargetAutoMgr()->empty()) { + g->GetXTargetAutoMgr()->merge(*GetXTargetAutoMgr()); + GetXTargetAutoMgr()->clear(); + RemoveAutoXTargets(); + } + + SetXTargetAutoMgr(g->GetXTargetAutoMgr()); + + if (!GetXTargetAutoMgr()->empty()) + SetDirtyAutoHaters(); +} + +// This function is called when a client leaves a group +void Client::LeaveGroupXTargets(Group *g) +{ + if (!g) + return; + + SetXTargetAutoMgr(nullptr); // this will set it back to our manager + RemoveAutoXTargets(); + entity_list.RefreshAutoXTargets(this); // this will probably break the temporal ordering, but whatever + // We now have a rebuilt, valid auto hater manager, so we need to demerge from the groups + if (!GetXTargetAutoMgr()->empty()) { + GetXTargetAutoMgr()->demerge(*g->GetXTargetAutoMgr()); // this will remove entries where we only had aggro + SetDirtyAutoHaters(); + } +} + +// This function is called when a client leaves a group +void Client::LeaveRaidXTargets(Raid *r) +{ + if (!r) + return; + + SetXTargetAutoMgr(nullptr); // this will set it back to our manager + RemoveAutoXTargets(); + entity_list.RefreshAutoXTargets(this); // this will probably break the temporal ordering, but whatever + // We now have a rebuilt, valid auto hater manager, so we need to demerge from the groups + if (!GetXTargetAutoMgr()->empty()) { + GetXTargetAutoMgr()->demerge(*r->GetXTargetAutoMgr()); // this will remove entries where we only had aggro + SetDirtyAutoHaters(); + } } void Client::SetMaxXTargets(uint8 NewMax) diff --git a/zone/client.h b/zone/client.h index 69fdddffa..ae6c2ef30 100644 --- a/zone/client.h +++ b/zone/client.h @@ -48,6 +48,7 @@ namespace EQEmu #include "../common/inventory_profile.h" #include "../common/guilds.h" //#include "../common/item_data.h" +#include "xtargetautohaters.h" #include "common.h" #include "merc.h" @@ -1122,6 +1123,13 @@ public: void RemoveGroupXTargets(); void RemoveAutoXTargets(); void ShowXTargets(Client *c); + inline XTargetAutoHaters *GetXTargetAutoMgr() { return m_activeautohatermgr; } // will be either raid or group or self + inline void SetXTargetAutoMgr(XTargetAutoHaters *in) { if (in) m_activeautohatermgr = in; else m_activeautohatermgr = &m_autohatermgr; } + inline void SetDirtyAutoHaters() { m_dirtyautohaters = true; } + void ProcessXTargetAutoHaters(); // fixes up our auto haters + void JoinGroupXTargets(Group *g); + void LeaveGroupXTargets(Group *g); + void LeaveRaidXTargets(Raid *r); bool GroupFollow(Client* inviter); inline bool GetRunMode() const { return runmode; } @@ -1546,8 +1554,11 @@ private: uint8 MaxXTargets; bool XTargetAutoAddHaters; + bool m_dirtyautohaters; struct XTarget_Struct XTargets[XTARGET_HARDCAP]; + XTargetAutoHaters m_autohatermgr; + XTargetAutoHaters *m_activeautohatermgr; Timer ItemTickTimer; Timer ItemQuestTimer; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f2e78adf7..721421b9e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -575,6 +575,11 @@ void Client::CompleteConnect() } } raid->SendGroupLeadershipAA(this, grpID); // this may get sent an extra time ... + + SetXTargetAutoMgr(raid->GetXTargetAutoMgr()); + if (!GetXTargetAutoMgr()->empty()) + SetDirtyAutoHaters(); + if (raid->IsLocked()) raid->SendRaidLockTo(this); } @@ -1548,8 +1553,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) // we purchased a new one while out-of-zone. if (group->IsLeader(this)) group->SendLeadershipAAUpdate(); - } + JoinGroupXTargets(group); group->UpdatePlayer(this); LFG = false; } @@ -10806,7 +10811,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) } } } - g->DisbandGroup(); + g->JoinRaidXTarget(r); + g->DisbandGroup(true); r->GroupUpdate(freeGroup); } else{ @@ -10871,7 +10877,8 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) } } } - ig->DisbandGroup(); + ig->JoinRaidXTarget(r, true); + ig->DisbandGroup(true); r->GroupUpdate(groupFree); groupFree = r->GetFreeGroup(); } @@ -10924,10 +10931,11 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) } } } - g->DisbandGroup(); + g->JoinRaidXTarget(r); + g->DisbandGroup(true); r->GroupUpdate(groupFree); } - else + else // target does not have a group { if (ig){ r = new Raid(i); @@ -10981,14 +10989,15 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app) r->SendRaidCreate(this); r->SendMakeLeaderPacketTo(r->leadername, this); r->SendBulkRaid(this); + ig->JoinRaidXTarget(r, true); r->AddMember(this); - ig->DisbandGroup(); + ig->DisbandGroup(true); r->GroupUpdate(0); if (r->IsLocked()) { r->SendRaidLockTo(this); } } - else{ + else{ // neither has a group r = new Raid(i); entity_list.AddRaid(r); r->SetRaidDetails(); @@ -14087,6 +14096,7 @@ void Client::Handle_OP_XTargetAutoAddHaters(const EQApplicationPacket *app) } XTargetAutoAddHaters = app->ReadUInt8(0); + SetDirtyAutoHaters(); } void Client::Handle_OP_XTargetOpen(const EQApplicationPacket *app) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index bb2db4777..b97f7b22e 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -681,6 +681,12 @@ bool Client::Process() { Message(0, "Your enemies have forgotten you!"); } + if (client_state == CLIENT_CONNECTED) { + if (m_dirtyautohaters) + ProcessXTargetAutoHaters(); + // aggro meter stuff should live here + } + return ret; } diff --git a/zone/entity.cpp b/zone/entity.cpp index 2ff83980e..9f23f63a4 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1404,15 +1404,15 @@ void EntityList::RemoveFromTargets(Mob *mob, bool RemoveFromXTargets) if (!m) continue; - m->RemoveFromHateList(mob); - if (RemoveFromXTargets) { - if (m->IsClient()) + if (m->IsClient() && mob->CheckAggro(m)) m->CastToClient()->RemoveXTarget(mob, false); // FadingMemories calls this function passing the client. - else if (mob->IsClient()) + else if (mob->IsClient() && m->CheckAggro(mob)) mob->CastToClient()->RemoveXTarget(m, false); } + + m->RemoveFromHateList(mob); } } @@ -2557,6 +2557,8 @@ void EntityList::RemoveFromHateLists(Mob *mob, bool settoone) it->second->RemoveFromHateList(mob); else it->second->SetHateAmountOnEnt(mob, 1); + if (mob->IsClient()) + mob->CastToClient()->RemoveXTarget(it->second, false); // gotta do book keeping } ++it; } diff --git a/zone/groups.cpp b/zone/groups.cpp index 2162e735e..24d31e74c 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -64,6 +64,8 @@ Group::Group(uint32 gid) MarkedNPCs[i] = 0; NPCMarkerID = 0; + + m_autohatermgr.SetOwner(nullptr, this, nullptr); } //creating a new group @@ -94,6 +96,7 @@ Group::Group(Mob* leader) MarkedNPCs[i] = 0; NPCMarkerID = 0; + m_autohatermgr.SetOwner(nullptr, this, nullptr); } Group::~Group() @@ -346,6 +349,9 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte database.SetGroupID(NewMemberName, GetID(), CharacterID, ismerc); } + if (newmember && newmember->IsClient()) + newmember->CastToClient()->JoinGroupXTargets(this); + safe_delete(outapp); return true; @@ -718,8 +724,10 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) if (oldmember->GetName() == mentoree_name) ClearGroupMentor(); - if(oldmember->IsClient()) + if(oldmember->IsClient()) { SendMarkedNPCsToMember(oldmember->CastToClient(), true); + oldmember->CastToClient()->LeaveGroupXTargets(this); + } if(GroupCount() < 3) { @@ -872,7 +880,7 @@ uint32 Group::GetTotalGroupDamage(Mob* other) { return total; } -void Group::DisbandGroup() { +void Group::DisbandGroup(bool joinraid) { auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate_Struct)); GroupUpdate_Struct* gu = (GroupUpdate_Struct*) outapp->pBuffer; @@ -899,6 +907,8 @@ void Group::DisbandGroup() { database.SetGroupID(members[i]->GetCleanName(), 0, members[i]->CastToClient()->CharacterID(), false); members[i]->CastToClient()->QueuePacket(outapp); SendMarkedNPCsToMember(members[i]->CastToClient(), true); + if (!joinraid) + members[i]->CastToClient()->LeaveGroupXTargets(this); } if (members[i]->IsMerc()) @@ -2292,6 +2302,30 @@ void Group::UpdateXTargetMarkedNPC(uint32 Number, Mob *m) } +void Group::SetDirtyAutoHaters() +{ + for (int i = 0; i < MAX_GROUP_MEMBERS; ++i) + if (members[i] && members[i]->IsClient()) + members[i]->CastToClient()->SetDirtyAutoHaters(); +} + +void Group::JoinRaidXTarget(Raid *raid, bool first) +{ + if (!GetXTargetAutoMgr()->empty()) + raid->GetXTargetAutoMgr()->merge(*GetXTargetAutoMgr()); + + for (int i = 0; i < MAX_GROUP_MEMBERS; ++i) { + if (members[i] && members[i]->IsClient()) { + auto *client = members[i]->CastToClient(); + if (!first) + client->RemoveAutoXTargets(); + client->SetXTargetAutoMgr(raid->GetXTargetAutoMgr()); + if (!client->GetXTargetAutoMgr()->empty()) + client->SetDirtyAutoHaters(); + } + } +} + void Group::SetMainTank(const char *NewMainTankName) { MainTankName = NewMainTankName; diff --git a/zone/groups.h b/zone/groups.h index 3da2aae54..6de364d93 100644 --- a/zone/groups.h +++ b/zone/groups.h @@ -22,6 +22,7 @@ #include "../common/types.h" #include "mob.h" +#include "xtargetautohaters.h" class Client; class EQApplicationPacket; @@ -58,7 +59,7 @@ public: void SendWorldGroup(uint32 zone_id,Mob* zoningmember); bool DelMemberOOZ(const char *Name); bool DelMember(Mob* oldmember,bool ignoresender = false); - void DisbandGroup(); + void DisbandGroup(bool joinraid = false); void GetMemberList(std::list& member_list, bool clear_list = true); void GetClientList(std::list& client_list, bool clear_list = true); #ifdef BOTS @@ -140,6 +141,9 @@ public: void ChangeLeader(Mob* newleader); const char *GetClientNameByIndex(uint8 index); void UpdateXTargetMarkedNPC(uint32 Number, Mob *m); + void SetDirtyAutoHaters(); + inline XTargetAutoHaters *GetXTargetAutoMgr() { return &m_autohatermgr; } + void JoinRaidXTarget(Raid *raid, bool first = false); void SetGroupMentor(int percent, char *name); void ClearGroupMentor(); @@ -168,6 +172,8 @@ private: std::string mentoree_name; Client *mentoree; int mentor_percent; + + XTargetAutoHaters m_autohatermgr; }; #endif diff --git a/zone/raids.cpp b/zone/raids.cpp index ff9e84578..46dd4424e 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -43,6 +43,8 @@ Raid::Raid(uint32 raidID) memset(leadername, 0, 64); locked = false; LootType = 4; + + m_autohatermgr.SetOwner(nullptr, nullptr, this); } Raid::Raid(Client* nLeader) @@ -60,6 +62,8 @@ Raid::Raid(Client* nLeader) strn0cpy(leadername, nLeader->GetName(), 64); locked = false; LootType = 4; + + m_autohatermgr.SetOwner(nullptr, nullptr, this); } Raid::~Raid() @@ -121,6 +125,26 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo c->SetRaidGrouped(true); SendRaidMOTD(c); + // xtarget shit .......... + if (group == RAID_GROUPLESS) { + if (rleader) { + GetXTargetAutoMgr()->merge(*c->GetXTargetAutoMgr()); + c->GetXTargetAutoMgr()->clear(); + c->SetXTargetAutoMgr(GetXTargetAutoMgr()); + } else { + if (!c->GetXTargetAutoMgr()->empty()) { + GetXTargetAutoMgr()->merge(*c->GetXTargetAutoMgr()); + c->GetXTargetAutoMgr()->clear(); + c->RemoveAutoXTargets(); + } + + c->SetXTargetAutoMgr(GetXTargetAutoMgr()); + + if (!c->GetXTargetAutoMgr()->empty()) + c->SetDirtyAutoHaters(); + } + } + auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); @@ -143,8 +167,10 @@ void Raid::RemoveMember(const char *characterName) LearnMembers(); VerifyRaid(); - if(client) + if(client) { client->SetRaidGrouped(false); + client->LeaveRaidXTargets(this); + } auto pack = new ServerPacket(ServerOP_RaidRemove, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; @@ -1672,3 +1698,11 @@ void Raid::CheckGroupMentor(uint32 group_id, Client *c) group_mentor[group_id].mentoree = c; } +void Raid::SetDirtyAutoHaters() +{ + for (int i = 0; i < MAX_RAID_MEMBERS; ++i) + if (members[i].member) + members[i].member->SetDirtyAutoHaters(); + +} + diff --git a/zone/raids.h b/zone/raids.h index ca5d0ff9b..9e681153c 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -20,6 +20,7 @@ #include "../common/types.h" #include "groups.h" +#include "xtargetautohaters.h" class Client; class EQApplicationPacket; @@ -230,6 +231,9 @@ public: inline int GetMentorPercent(uint32 group_id) { return group_mentor[group_id].mentor_percent; } inline Client *GetMentoree(uint32 group_id) { return group_mentor[group_id].mentoree; } + void SetDirtyAutoHaters(); + inline XTargetAutoHaters *GetXTargetAutoMgr() { return &m_autohatermgr; } + RaidMember members[MAX_RAID_MEMBERS]; char leadername[64]; protected: @@ -244,6 +248,8 @@ protected: GroupLeadershipAA_Struct group_aa[MAX_RAID_GROUPS]; GroupMentor group_mentor[MAX_RAID_GROUPS]; + + XTargetAutoHaters m_autohatermgr; }; diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 84d4cb399..3251250ce 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -897,6 +897,9 @@ void WorldServer::Process() { Inviter->CastToClient()->SendGroupLeaderChangePacket(Inviter->GetName()); Inviter->CastToClient()->SendGroupJoinAcknowledge(); } + group->GetXTargetAutoMgr()->merge(*Inviter->CastToClient()->GetXTargetAutoMgr()); + Inviter->CastToClient()->GetXTargetAutoMgr()->clear(); + Inviter->CastToClient()->SetXTargetAutoMgr(group->GetXTargetAutoMgr()); } if(!group) @@ -1011,6 +1014,7 @@ void WorldServer::Process() { group->SetGroupMentor(mentor_percent, mentoree_name); } + client->JoinGroupXTargets(group); } else if (client->GetMerc()) { @@ -1109,6 +1113,7 @@ void WorldServer::Process() { r->SendRaidRemoveAll(rga->playername); Client *rem = entity_list.GetClientByName(rga->playername); if(rem){ + rem->LeaveRaidXTargets(r); r->SendRaidDisband(rem); } r->LearnMembers(); diff --git a/zone/xtargetautohaters.cpp b/zone/xtargetautohaters.cpp new file mode 100644 index 000000000..ab010d9db --- /dev/null +++ b/zone/xtargetautohaters.cpp @@ -0,0 +1,112 @@ +#include "xtargetautohaters.h" +#include "mob.h" +#include "client.h" +#include "raids.h" +#include "groups.h" + +#include + +void XTargetAutoHaters::increment_count(Mob *in) +{ + assert(in != nullptr); + auto it = std::find_if(m_haters.begin(), m_haters.end(), + [&in](const HatersCount &c) { return c.spawn_id == in->GetID(); }); + + // we are on the list, we just need to increment the count + if (it != m_haters.end()) { + it->count++; + return; + } + // We are not on the list + HatersCount c; + c.spawn_id = in->GetID(); + c.count = 1; + + m_haters.push_back(c); + // trigger event on owner + if (m_client) + m_client->SetDirtyAutoHaters(); + else if (m_group) + m_group->SetDirtyAutoHaters(); + else if (m_raid) + m_raid->SetDirtyAutoHaters(); +} + +void XTargetAutoHaters::decrement_count(Mob *in) +{ + assert(in != nullptr); + auto it = std::find_if(m_haters.begin(), m_haters.end(), + [&in](const HatersCount &c) { return c.spawn_id == in->GetID(); }); + + // we are not on the list ... shouldn't happen + if (it == m_haters.end()) + return; + it->count--; + if (it->count == 0) { + m_haters.erase(it); + if (m_client) + m_client->SetDirtyAutoHaters(); + else if (m_group) + m_group->SetDirtyAutoHaters(); + else if (m_raid) + m_raid->SetDirtyAutoHaters(); + } +} + +void XTargetAutoHaters::merge(XTargetAutoHaters &other) +{ + bool trigger = false; + for (auto &e : other.m_haters) { + auto it = std::find_if(m_haters.begin(), m_haters.end(), + [&e](const HatersCount &c) { return e.spawn_id == c.spawn_id; }); + if (it != m_haters.end()) { + it->count += e.count; + continue; + } + m_haters.push_back(e); + trigger = true; + } + + if (trigger) { + if (m_client) + m_client->SetDirtyAutoHaters(); + else if (m_group) + m_group->SetDirtyAutoHaters(); + else if (m_raid) + m_raid->SetDirtyAutoHaters(); + } +} + +// demerge this from other. other belongs to group/raid you just left +void XTargetAutoHaters::demerge(XTargetAutoHaters &other) +{ + bool trigger = false; + for (auto &e : m_haters) { + auto it = std::find_if(other.m_haters.begin(), other.m_haters.end(), + [&e](const HatersCount &c) { return e.spawn_id == c.spawn_id; }); + if (it != other.m_haters.end()) { + it->count -= e.count; + if (it->count == 0) { + trigger = true; + other.m_haters.erase(it); + } + } + } + + if (trigger) { + if (other.m_client) + other.m_client->SetDirtyAutoHaters(); + else if (other.m_group) + other.m_group->SetDirtyAutoHaters(); + else if (other.m_raid) + other.m_raid->SetDirtyAutoHaters(); + } +} + +bool XTargetAutoHaters::contains_mob(int spawn_id) +{ + auto it = std::find_if(m_haters.begin(), m_haters.end(), + [spawn_id](const HatersCount &c) { return c.spawn_id == spawn_id; }); + return it != m_haters.end(); +} + diff --git a/zone/xtargetautohaters.h b/zone/xtargetautohaters.h new file mode 100644 index 000000000..fd8ee4f21 --- /dev/null +++ b/zone/xtargetautohaters.h @@ -0,0 +1,48 @@ +#ifndef XTARGETAUTOHATERS_H +#define XTARGETAUTOHATERS_H + +#include + +class Mob; +class Client; +class Group; +class Raid; + +class XTargetAutoHaters { +struct HatersCount { + int spawn_id; + int count; +}; +public: + XTargetAutoHaters() : m_client(nullptr), m_group(nullptr), m_raid(nullptr) {} + XTargetAutoHaters(Client *co, Group *go, Raid *ro) : m_client(co), m_group(go), m_raid(ro) {} + ~XTargetAutoHaters() {} + + void merge(XTargetAutoHaters &other); + void demerge(XTargetAutoHaters &other); + void increment_count(Mob *in); + void decrement_count(Mob *in); + + bool contains_mob(int spawn_id); + + inline const std::vector &get_list() { return m_haters; } + inline void SetOwner(Client *c, Group *g, Raid *r) {m_client = c; m_group = g; m_raid = r; } + inline void clear() { m_haters.clear(); } + inline bool empty() { return m_haters.empty(); } + +private: + /* This will contain all of the mobs that are possible to fill in an autohater + * slot. This keeps track of ALL MOBS for a client or group or raid + * This list needs to be merged when you join group/raid/etc + */ + std::vector m_haters; + + // So this is the object that owns us ... only 1 shouldn't be null + Client *m_client; + Group *m_group; + Raid *m_raid; +}; + + +#endif /* !XTARGETAUTOHATERS_H */ + From 08c2f73e379066d4a2486c223282ba6daf72e6cb Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Feb 2017 22:27:34 -0500 Subject: [PATCH 562/693] Implement aggro meter for RoF2 (RoF wasn't tested) I didn't test RoF, so it's disabled for now (change AggroMeterAvaliable if you want to test) Group member meters probably buggy ... but do later The "lock target" feature isn't working currently either --- common/emu_oplist.h | 3 + common/ruletypes.h | 1 + utils/patches/patch_RoF.conf | 3 + utils/patches/patch_RoF2.conf | 3 + zone/CMakeLists.txt | 2 + zone/aggromanager.cpp | 11 +++ zone/aggromanager.h | 80 +++++++++++++++++ zone/client.cpp | 165 ++++++++++++++++++++++++++++++++++ zone/client.h | 9 ++ zone/client_packet.cpp | 12 +++ zone/client_packet.h | 1 + zone/client_process.cpp | 3 +- zone/hate_list.cpp | 30 ++++++- zone/hate_list.h | 8 +- zone/mob.h | 2 + 15 files changed, 328 insertions(+), 5 deletions(-) create mode 100644 zone/aggromanager.cpp create mode 100644 zone/aggromanager.h diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 6b7c58841..cf6f4ca28 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -25,6 +25,9 @@ N(OP_AdventureRequest), N(OP_AdventureStatsReply), N(OP_AdventureStatsRequest), N(OP_AdventureUpdate), +N(OP_AggroMeterLockTarget), +N(OP_AggroMeterTargetInfo), +N(OP_AggroMeterUpdate), N(OP_AltCurrency), N(OP_AltCurrencyMerchantReply), N(OP_AltCurrencyMerchantRequest), diff --git a/common/ruletypes.h b/common/ruletypes.h index f972034f0..a0bf01496 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -114,6 +114,7 @@ RULE_BOOL(Character, CheckCursorEmptyWhenLooting, true) // If true, a player can RULE_BOOL(Character, MaintainIntoxicationAcrossZones, true) // If true, alcohol effects are maintained across zoning and logging out/in. RULE_BOOL(Character, EnableDiscoveredItems, true) // If enabled, it enables EVENT_DISCOVER_ITEM and also saves character names and timestamps for the first time an item is discovered. RULE_BOOL(Character, EnableXTargetting, true) // Enable Extended Targetting Window, for users with UF and later clients. +RULE_BOOL(Character, EnableAggroMeter, true) // Enable Aggro Meter, for users with RoF and later clients. RULE_BOOL(Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap RULE_INT(Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update RULE_INT(Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well. diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index aefcd8dbc..ad54b6341 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -359,6 +359,9 @@ OP_OpenContainer=0x654f OP_Marquee=0x288a OP_Fling=0x6b8e OP_CancelSneakHide=0x265f +OP_AggroMeterLockTarget=0x70b7 +OP_AggroMeterTargetInfo=0x18fe +OP_AggroMeterUpdate=0x75aa OP_DzQuit=0x5fc8 OP_DzListTimers=0x67b9 diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 20111e850..9f588d18f 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -360,6 +360,9 @@ OP_ItemRecastDelay=0x15a9 OP_ResetAA=0x1669 OP_Fling=0x6f80 OP_CancelSneakHide=0x0927 +OP_AggroMeterLockTarget=0x1643 +OP_AggroMeterTargetInfo=0x16bc +OP_AggroMeterUpdate=0x1781 # Expeditions OP_DzAddPlayer=0x4701 diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 7bc96c3db..deadd079e 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -4,6 +4,7 @@ SET(zone_sources aa.cpp aa_ability.cpp aggro.cpp + aggromanager.cpp attack.cpp beacon.cpp bonuses.cpp @@ -132,6 +133,7 @@ SET(zone_sources SET(zone_headers aa.h aa_ability.h + aggromanager.h basic_functions.h beacon.h bot.h diff --git a/zone/aggromanager.cpp b/zone/aggromanager.cpp new file mode 100644 index 000000000..8dd532c74 --- /dev/null +++ b/zone/aggromanager.cpp @@ -0,0 +1,11 @@ +#include "aggromanager.h" + +AggroMeter::AggroMeter() : lock_id(0), target_id(0), secondary_id(0), lock_changed(false) +{ + for (int i = 0; i < AT_Max; ++i) { + data[i].type = i; + data[i].pct = 0; + } +} + + diff --git a/zone/aggromanager.h b/zone/aggromanager.h new file mode 100644 index 000000000..b140b07d7 --- /dev/null +++ b/zone/aggromanager.h @@ -0,0 +1,80 @@ +#ifndef AGGROMANAGER_H +#define AGGROMANAGER_H + +#include "../common/types.h" +#include +#include + +class AggroMeter +{ +public: + enum AggroTypes { + AT_Player, + AT_Secondary, + AT_Group1, + AT_Group2, + AT_Group3, + AT_Group4, + AT_Group5, + AT_XTarget1, + AT_XTarget2, + AT_XTarget3, + AT_XTarget4, + AT_XTarget5, + AT_XTarget6, + AT_XTarget7, + AT_XTarget8, + AT_XTarget9, + AT_XTarget10, + AT_XTarget11, + AT_XTarget12, + AT_XTarget13, + AT_XTarget14, + AT_XTarget15, + AT_XTarget16, + AT_XTarget17, + AT_XTarget18, + AT_XTarget19, + AT_XTarget20, + AT_Max + }; + +private: + struct AggroData { + int16 type; + int16 pct; + }; + + AggroData data[AT_Max]; + int lock_id; // we set this + int target_id; // current target or if PC targeted, their Target + // so secondary depends on if we have aggro or not + // When we are the current target, this will be the 2nd person on list + // When we are not tanking, this will be the current tank + int secondary_id; + + // so we need some easy way to detect the client changing but still delaying the packet + bool lock_changed; +public: + AggroMeter(); + ~AggroMeter() {} + + inline void set_lock_id(int in) { lock_id = in; lock_changed = true; } + inline bool update_lock() { bool ret = lock_changed; lock_changed = false; return ret; } + inline void set_target_id(int in) { target_id = in; } + inline void set_secondary_id(int in) { secondary_id = in; } + // returns true when changed + inline bool set_pct(AggroTypes t, int pct) { assert(t >= AT_Player && t < AT_Max); if (data[t].pct == pct) return false; data[t].pct = pct; return true; } + + inline int get_lock_id() const { return lock_id; } + inline int get_target_id() const { return target_id; } + inline int get_secondary_id() const { return secondary_id; } + inline int get_pct(AggroTypes t) const { assert(t >= AT_Player && t < AT_Max); return data[t].pct; } + // the ID of the spawn for player entry depends on lock_id + inline int get_player_aggro_id() const { return lock_id ? lock_id : target_id; } + // fuck it, lets just use a buffer the size of the largest to work with + const inline size_t max_packet_size() const { return sizeof(uint8) + sizeof(uint32) + sizeof(uint8) + (sizeof(uint8) + sizeof(uint16)) * AT_Max; } +}; + + +#endif /* !AGGROMANAGER_H */ diff --git a/zone/client.cpp b/zone/client.cpp index a3239eeb1..9e02195c0 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -154,6 +154,7 @@ Client::Client(EQStreamInterface* ieqs) afk_toggle_timer(250), helm_toggle_timer(250), light_update_timer(600), + aggro_meter_timer(1000), m_Proximity(FLT_MAX, FLT_MAX, FLT_MAX), //arbitrary large number m_ZoneSummonLocation(-2.0f,-2.0f,-2.0f), m_AutoAttackPosition(0.0f, 0.0f, 0.0f, 0.0f), @@ -8771,3 +8772,167 @@ void Client::CheckRegionTypeChanges() else if (GetPVP()) SetPVP(false, false); } + +void Client::ProcessAggroMeter() +{ + if (!AggroMeterAvailable()) + return; + + // we need to decide if we need to send OP_AggroMeterTargetInfo now + // This packet sends the current lock target ID and the current target ID + // target ID will be either our target or our target of target when we're targeting a PC + bool send_targetinfo = false; + auto cur_tar = GetTarget(); + + // probably should have PVP rules ... + if (cur_tar && cur_tar != this) { + if (cur_tar->IsNPC() && !cur_tar->IsPetOwnerClient() && cur_tar->GetID() != m_aggrometer.get_target_id()) { + m_aggrometer.set_target_id(cur_tar->GetID()); + send_targetinfo = true; + } else if ((cur_tar->IsPetOwnerClient() || cur_tar->IsClient()) && cur_tar->GetTarget() && cur_tar->GetTarget()->GetID() != m_aggrometer.get_target_id()) { + m_aggrometer.set_target_id(cur_tar->GetTarget()->GetID()); + send_targetinfo = true; + } + } else if (m_aggrometer.get_target_id()) { + m_aggrometer.set_target_id(0); + send_targetinfo = true; + } + + if (m_aggrometer.update_lock()) + send_targetinfo = true; + + if (send_targetinfo) { + auto app = new EQApplicationPacket(OP_AggroMeterTargetInfo, sizeof(uint32) * 2); + app->WriteUInt32(m_aggrometer.get_lock_id()); + app->WriteUInt32(m_aggrometer.get_target_id()); + FastQueuePacket(&app); + } + + // we could just calculate how big the packet would need to be ... but it's easier this way :P should be 87 bytes + auto app = new EQApplicationPacket(OP_AggroMeterUpdate, m_aggrometer.max_packet_size()); + + cur_tar = entity_list.GetMob(m_aggrometer.get_target_id()); + + // first we must check the secondary + // TODO: lock target should affect secondary as well + bool send = false; + Mob *secondary = nullptr; + bool has_aggro = false; + if (cur_tar) { + if (cur_tar->GetTarget() == this) {// we got aggro + secondary = cur_tar->GetSecondaryHate(this); + has_aggro = true; + } else { + secondary = cur_tar->GetTarget(); + } + } + + if (secondary && secondary->GetID() != m_aggrometer.get_secondary_id()) { + m_aggrometer.set_secondary_id(secondary->GetID()); + app->WriteUInt8(1); + app->WriteUInt32(m_aggrometer.get_secondary_id()); + send = true; + } else if (!secondary && m_aggrometer.get_secondary_id()) { + m_aggrometer.set_secondary_id(0); + app->WriteUInt8(1); + app->WriteUInt32(0); + send = true; + } else { // might not need to send in this case + app->WriteUInt8(0); + } + + auto count_offset = app->GetWritePosition(); + app->WriteUInt8(0); + + int count = 0; + auto add_entry = [&app, &count, this](AggroMeter::AggroTypes i) { + count++; + app->WriteUInt8(i); + app->WriteUInt16(m_aggrometer.get_pct(i)); + }; + // TODO: Player entry should either be lock or yourself, ignoring lock for now + // player, secondary, and group depend on your target/lock + if (cur_tar) { + if (m_aggrometer.set_pct(AggroMeter::AT_Player, cur_tar->GetHateRatio(cur_tar->GetTarget(), this))) + add_entry(AggroMeter::AT_Player); + + if (m_aggrometer.set_pct(AggroMeter::AT_Secondary, has_aggro ? cur_tar->GetHateRatio(this, secondary) : secondary ? 100 : 0)) + add_entry(AggroMeter::AT_Secondary); + + // fuuuuuuuuuuuuuuuuuuuuuuuucckkkkkkkkkkkkkkk raids + if (IsRaidGrouped()) { + auto raid = GetRaid(); + if (raid) { + auto gid = raid->GetGroup(this); + if (gid < 12) { + int at_id = AggroMeter::AT_Group1; + for (int i = 0; i < MAX_RAID_MEMBERS; ++i) { + if (raid->members[i].member && raid->members[i].member != this && raid->members[i].GroupNumber == gid) { + if (m_aggrometer.set_pct(static_cast(at_id), cur_tar->GetHateRatio(cur_tar->GetTarget(), raid->members[i].member))) + add_entry(static_cast(at_id)); + at_id++; + if (at_id > AggroMeter::AT_Group5) + break; + } + } + } + } + } else if (IsGrouped()) { + auto group = GetGroup(); + if (group) { + int at_id = AggroMeter::AT_Group1; + for (int i = 0; i < MAX_GROUP_MEMBERS; ++i) { + if (group->members[i] && group->members[i] != this) { + if (m_aggrometer.set_pct(static_cast(at_id), cur_tar->GetHateRatio(cur_tar->GetTarget(), group->members[i]))) + add_entry(static_cast(at_id)); + at_id++; + } + } + } + } + } else { // we might need to clear out some data now + if (m_aggrometer.set_pct(AggroMeter::AT_Player, 0)) + add_entry(AggroMeter::AT_Player); + if (m_aggrometer.set_pct(AggroMeter::AT_Secondary, 0)) + add_entry(AggroMeter::AT_Secondary); + if (m_aggrometer.set_pct(AggroMeter::AT_Group1, 0)) + add_entry(AggroMeter::AT_Group1); + if (m_aggrometer.set_pct(AggroMeter::AT_Group2, 0)) + add_entry(AggroMeter::AT_Group2); + if (m_aggrometer.set_pct(AggroMeter::AT_Group3, 0)) + add_entry(AggroMeter::AT_Group3); + if (m_aggrometer.set_pct(AggroMeter::AT_Group4, 0)) + add_entry(AggroMeter::AT_Group5); + if (m_aggrometer.set_pct(AggroMeter::AT_Group5, 0)) + add_entry(AggroMeter::AT_Group5); + } + + // now to go over our xtargets + // if the entry is an NPC it's our hate relative to the NPCs current tank + // if it's a PC, it's their hate relative to our current target + for (int i = 0; i < GetMaxXTargets(); ++i) { + if (XTargets[i].ID) { + auto mob = entity_list.GetMob(XTargets[i].ID); + if (mob) { + int ratio = 0; + if (mob->IsNPC()) + ratio = mob->GetHateRatio(mob->GetTarget(), this); + else if (cur_tar) + ratio = cur_tar->GetHateRatio(cur_tar->GetTarget(), mob); + if (m_aggrometer.set_pct(static_cast(AggroMeter::AT_XTarget1 + i), ratio)) + add_entry(static_cast(AggroMeter::AT_XTarget1 + i)); + } + } + } + + if (send || count) { + app->size = app->GetWritePosition(); // this should be safe, although not recommended + // but this way we can have a smaller buffer created for the packet dispatched to the client w/o resizing this one + app->SetWritePosition(count_offset); + app->WriteUInt8(count); + FastQueuePacket(&app); + } else { + safe_delete(app); + } +} + diff --git a/zone/client.h b/zone/client.h index ae6c2ef30..6dc4d6e38 100644 --- a/zone/client.h +++ b/zone/client.h @@ -49,6 +49,7 @@ namespace EQEmu #include "../common/guilds.h" //#include "../common/item_data.h" #include "xtargetautohaters.h" +#include "aggromanager.h" #include "common.h" #include "merc.h" @@ -1133,6 +1134,11 @@ public: bool GroupFollow(Client* inviter); inline bool GetRunMode() const { return runmode; } + inline bool AggroMeterAvailable() const { return ((m_ClientVersionBit & EQEmu::versions::bit_RoF2AndLater)) && RuleB(Character, EnableAggroMeter); } // RoF untested + inline void SetAggroMeterLock(int in) { m_aggrometer.set_lock_id(in); } + + void ProcessAggroMeter(); // builds packet and sends + void InitializeMercInfo(); bool CheckCanSpawnMerc(uint32 template_id); bool CheckCanHireMerc(Mob* merchant, uint32 template_id); @@ -1470,6 +1476,7 @@ private: Timer afk_toggle_timer; Timer helm_toggle_timer; Timer light_update_timer; + Timer aggro_meter_timer; glm::vec3 m_Proximity; @@ -1560,6 +1567,8 @@ private: XTargetAutoHaters m_autohatermgr; XTargetAutoHaters *m_activeautohatermgr; + AggroMeter m_aggrometer; + Timer ItemTickTimer; Timer ItemQuestTimer; std::map accountflags; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 721421b9e..535e5e98e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -120,6 +120,7 @@ void MapOpcodes() ConnectedOpcodes[OP_AdventureMerchantSell] = &Client::Handle_OP_AdventureMerchantSell; ConnectedOpcodes[OP_AdventureRequest] = &Client::Handle_OP_AdventureRequest; ConnectedOpcodes[OP_AdventureStatsRequest] = &Client::Handle_OP_AdventureStatsRequest; + ConnectedOpcodes[OP_AggroMeterLockTarget] = &Client::Handle_OP_AggroMeterLockTarget; ConnectedOpcodes[OP_AltCurrencyMerchantRequest] = &Client::Handle_OP_AltCurrencyMerchantRequest; ConnectedOpcodes[OP_AltCurrencyPurchase] = &Client::Handle_OP_AltCurrencyPurchase; ConnectedOpcodes[OP_AltCurrencyReclaim] = &Client::Handle_OP_AltCurrencyReclaim; @@ -2400,6 +2401,17 @@ void Client::Handle_OP_AdventureStatsRequest(const EQApplicationPacket *app) FastQueuePacket(&outapp); } +void Client::Handle_OP_AggroMeterLockTarget(const EQApplicationPacket *app) +{ + if (app->size < sizeof(uint32)) { + Log.Out(Logs::General, Logs::Error, "Handle_OP_AggroMeterLockTarget had a packet that was too small."); + return; + } + + SetAggroMeterLock(app->ReadUInt32(0)); + ProcessAggroMeter(); +} + void Client::Handle_OP_AltCurrencyMerchantRequest(const EQApplicationPacket *app) { VERIFY_PACKET_LENGTH(OP_AltCurrencyMerchantRequest, app, uint32); diff --git a/zone/client_packet.h b/zone/client_packet.h index 2635724dd..76a26e04e 100644 --- a/zone/client_packet.h +++ b/zone/client_packet.h @@ -32,6 +32,7 @@ void Handle_OP_AdventureMerchantSell(const EQApplicationPacket *app); void Handle_OP_AdventureRequest(const EQApplicationPacket *app); void Handle_OP_AdventureStatsRequest(const EQApplicationPacket *app); + void Handle_OP_AggroMeterLockTarget(const EQApplicationPacket *app); void Handle_OP_AltCurrencyMerchantRequest(const EQApplicationPacket *app); void Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app); void Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index b97f7b22e..2bfa8a055 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -684,7 +684,8 @@ bool Client::Process() { if (client_state == CLIENT_CONNECTED) { if (m_dirtyautohaters) ProcessXTargetAutoHaters(); - // aggro meter stuff should live here + if (aggro_meter_timer.Check()) + ProcessAggroMeter(); } return ret; diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 34519b69f..225ff39ff 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "raids.h" #include "../common/rulesys.h" +#include "../common/data_verification.h" #include "hate_list.h" #include "quest_parser_collection.h" @@ -277,7 +278,24 @@ int HateList::GetSummonedPetCountOnHateList(Mob *hater) { return pet_count; } -Mob *HateList::GetEntWithMostHateOnList(Mob *center) +int HateList::GetHateRatio(Mob *top, Mob *other) +{ + auto other_entry = Find(other); + + if (!other_entry || other_entry->stored_hate_amount < 1) + return 0; + + auto top_entry = Find(top); + + if (!top_entry || top_entry->stored_hate_amount < 1) + return 999; // shouldn't happen if you call it right :P + + return EQEmu::Clamp(static_cast((other_entry->stored_hate_amount * 100) / top_entry->stored_hate_amount), 1, 999); +} + +// skip is used to ignore a certain mob on the list +// Currently used for getting 2nd on list for aggro meter +Mob *HateList::GetEntWithMostHateOnList(Mob *center, Mob *skip) { // hack fix for zone shutdown crashes on some servers if (!zone->IsLoaded()) @@ -310,6 +328,11 @@ Mob *HateList::GetEntWithMostHateOnList(Mob *center) continue; } + if (cur->entity_on_hatelist == skip) { + ++iterator; + continue; + } + auto hateEntryPosition = glm::vec3(cur->entity_on_hatelist->GetX(), cur->entity_on_hatelist->GetY(), cur->entity_on_hatelist->GetZ()); if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { if (!zone->watermap->InLiquid(hateEntryPosition)) { @@ -436,6 +459,11 @@ Mob *HateList::GetEntWithMostHateOnList(Mob *center) while (iterator != list.end()) { struct_HateList *cur = (*iterator); + if (cur->entity_on_hatelist == skip) { + ++iterator; + continue; + } + if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { if(!zone->watermap->InLiquid(glm::vec3(cur->entity_on_hatelist->GetPosition()))) { skipped_count++; diff --git a/zone/hate_list.h b/zone/hate_list.h index dda8cb21d..f0e2b7618 100644 --- a/zone/hate_list.h +++ b/zone/hate_list.h @@ -41,9 +41,9 @@ public: Mob *GetClosestEntOnHateList(Mob *hater); Mob *GetDamageTopOnHateList(Mob *hater); - Mob *GetEntWithMostHateOnList(Mob *center); + Mob *GetEntWithMostHateOnList(Mob *center, Mob *skip = nullptr); Mob *GetRandomEntOnHateList(); - Mob* GetEntWithMostHateOnList(); + Mob *GetEntWithMostHateOnList(); bool IsEntOnHateList(Mob *mob); bool IsHateListEmpty(); @@ -51,6 +51,7 @@ public: int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts); int GetSummonedPetCountOnHateList(Mob *hater); + int GetHateRatio(Mob *top, Mob *other); int32 GetEntHateAmount(Mob *ent, bool in_damage = false); @@ -73,4 +74,5 @@ private: Mob *hate_owner; }; -#endif \ No newline at end of file +#endif + diff --git a/zone/mob.h b/zone/mob.h index fe76f949d..42672f046 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -539,7 +539,9 @@ public: void DoubleAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate ? in_hate * 2 : 1)); } uint32 GetHateAmount(Mob* tmob, bool is_dam = false) { return hate_list.GetEntHateAmount(tmob,is_dam);} uint32 GetDamageAmount(Mob* tmob) { return hate_list.GetEntHateAmount(tmob, true);} + int GetHateRatio(Mob *first, Mob *with) { return hate_list.GetHateRatio(first, with); } Mob* GetHateTop() { return hate_list.GetEntWithMostHateOnList(this);} + Mob* GetSecondaryHate(Mob *skip) { return hate_list.GetEntWithMostHateOnList(this, skip); } Mob* GetHateDamageTop(Mob* other) { return hate_list.GetDamageTopOnHateList(other);} Mob* GetHateRandom() { return hate_list.GetRandomEntOnHateList();} Mob* GetHateMost() { return hate_list.GetEntWithMostHateOnList();} From f0f5c41c305668862dca717c04fb2392bec79d35 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 19 Feb 2017 21:12:18 -0600 Subject: [PATCH 563/693] Fixed an issue where clients would sell x1000 stacks of items where the price overflows data sizes, the code will now make sure not to sell too many items that go over this data size --- zone/client_packet.cpp | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 535e5e98e..67e085d0d 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -12440,14 +12440,33 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) return; } - int cost_quantity = mp->quantity; + uint32 cost_quantity = mp->quantity; if (inst->IsCharged()) - int cost_quantity = 1; + uint32 cost_quantity = 1; + + uint32 i; + + if (RuleB(Merchant, UsePriceMod)) { + for (i = 0; i < cost_quantity; i++) { + price = (uint32)((item->Price * i)*(RuleR(Merchant, BuyCostMod))*Client::CalcPriceMod(vendor, true) + 0.5); // need to round up, because client does it automatically when displaying price + if (price > 4000000000) { + cost_quantity = i; + mp->quantity = i; + break; + } + } + } + else { + for (i = 0; i < cost_quantity; i++) { + price = (uint32)((item->Price * i)*(RuleR(Merchant, BuyCostMod)) + 0.5); // need to round up, because client does it automatically when displaying price + if (price > 4000000000) { + cost_quantity = i; + mp->quantity = i; + break; + } + } + } - if (RuleB(Merchant, UsePriceMod)) - price = (int)((item->Price*cost_quantity)*(RuleR(Merchant, BuyCostMod))*Client::CalcPriceMod(vendor, true) + 0.5); // need to round up, because client does it automatically when displaying price - else - price = (int)((item->Price*cost_quantity)*(RuleR(Merchant, BuyCostMod)) + 0.5); AddMoneyToPP(price, false); if (inst->IsStackable() || inst->IsCharged()) From 46b19e8e6f41045b6411c274f59078a502565cc1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 20 Feb 2017 18:41:17 -0500 Subject: [PATCH 564/693] Disable the aggro meter timer if it's not enabled --- zone/client.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 9e02195c0..5f3d3ac81 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8775,8 +8775,10 @@ void Client::CheckRegionTypeChanges() void Client::ProcessAggroMeter() { - if (!AggroMeterAvailable()) + if (!AggroMeterAvailable()) { + aggro_meter_timer.Disable(); return; + } // we need to decide if we need to send OP_AggroMeterTargetInfo now // This packet sends the current lock target ID and the current target ID From d9633dfee47dfa4970d1b76894a0268432cd9749 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 20 Feb 2017 21:41:15 -0500 Subject: [PATCH 565/693] Bard bot song twisting update --- changelog.txt | 3 + common/spdat.h | 4 +- common/version.h | 2 +- .../sql/git/bots/bots_db_update_manifest.txt | 1 + .../2017_02_20_bots_bard_spell_update.sql | 153 + zone/bot.cpp | 24 +- zone/bot.h | 15 +- zone/bot_command.cpp | 1 - zone/bot_structs.h | 4 + zone/botspellsai.cpp | 4458 ++++++++++++----- zone/groups.cpp | 25 +- 11 files changed, 3482 insertions(+), 1208 deletions(-) create mode 100644 utils/sql/git/bots/required/2017_02_20_bots_bard_spell_update.sql diff --git a/changelog.txt b/changelog.txt index 390c45cd9..23700766c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 02/20/2017 == +Uleat: Reworked bard bot spell twisting and updated their spell (song) list + == 01/31/2017 == Uleat: Modifed bot movement behavior in an attempt to 'normalize' it. This is a hack fix and will be revisited at some point. (Probably just need a follow function rather than use movement, when the leader of the follow chain is moving.) diff --git a/common/spdat.h b/common/spdat.h index ba275f933..d4ccd9456 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -65,8 +65,8 @@ enum SpellTypes : uint32 SpellType_Cure = (1 << 15), SpellType_Resurrect = (1 << 16), SpellType_HateRedux = (1 << 17), - SpellType_InCombatBuffSong = (1 << 18), - SpellType_OutOfCombatBuffSong = (1 << 19), + SpellType_InCombatBuffSong = (1 << 18), // bard in-combat group/ae buffs + SpellType_OutOfCombatBuffSong = (1 << 19), // bard out-of-combat group/ae buffs SpellTypes_Detrimental = (SpellType_Nuke | SpellType_Root | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Charm | SpellType_Debuff | SpellType_Slow), SpellTypes_Beneficial = (SpellType_Heal | SpellType_Buff | SpellType_Escape | SpellType_Pet | SpellType_InCombatBuff | SpellType_Cure | SpellType_HateRedux | SpellType_InCombatBuffSong | SpellType_OutOfCombatBuffSong), diff --git a/common/version.h b/common/version.h index bda89dd8c..40e50a0ac 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9105 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9009 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9010 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index d63c142c8..44e68f037 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -8,6 +8,7 @@ 9007|2016_06_23_bots_camel_case_name_rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AllowCamelCaseNames'|empty| 9008|2016_06_28_bots_inventory_charges_update.sql|SELECT * FROM `information_schema`.`COLUMNS` isc WHERE isc.`TABLE_SCHEMA` = DATABASE() AND isc.`TABLE_NAME` = 'bot_inventories' AND isc.`COLUMN_NAME` = 'inst_charges' AND isc.`DATA_TYPE` = 'tinyint'|not_empty| 9009|2017_02_15_bots_bot_spells_entries.sql|SELECT `id` FROM `npc_spells_entries` WHERE `npc_spells_id` >= 701 AND `npc_spells_id` <= 712|not_empty| +9010|2017_02_20_bots_bard_spell_update.sql|SELECT * FROM `bot_spells_entries` WHERE (`type` & 0xFFFF0000) = 0xFFFF0000|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2017_02_20_bots_bard_spell_update.sql b/utils/sql/git/bots/required/2017_02_20_bots_bard_spell_update.sql new file mode 100644 index 000000000..b0161209a --- /dev/null +++ b/utils/sql/git/bots/required/2017_02_20_bots_bard_spell_update.sql @@ -0,0 +1,153 @@ +DELETE FROM `bot_spells_entries` WHERE `npc_spells_id` = '711'; + +INSERT INTO `bot_spells_entries`(`npc_spells_id`,`spellid`,`type`,`minlevel`,`maxlevel`,`manacost`,`recast_delay`,`priority`,`resist_adjust`) VALUES + +-- versioning entry +('711', '0', '4294901760', '0', '0', '-1', '-1', '0', NULL), -- 0xFFFF0000 + +-- nuke +('711', '704', '1', '12', '54', '-1', '-1', '1', NULL), +('711', '1747', '1', '55', '127', '-1', '-1', '1', NULL), + +-- escape +('711', '1749', '16', '60', '127', '-1', '-1', '1', NULL), + +-- dot +('711', '743', '256', '38', '64', '-1', '-1', '1', NULL), +('711', '3367', '256', '65', '69', '-1', '-1', '1', NULL), +('711', '5385', '256', '70', '79', '-1', '-1', '1', NULL), +('711', '14074', '256', '80', '84', '-1', '-1', '1', NULL), +('711', '18059', '256', '85', '89', '-1', '-1', '1', NULL), +('711', '26084', '256', '90', '94', '-1', '-1', '1', NULL), +('711', '29182', '256', '95', '127', '-1', '-1', '1', NULL), +('711', '3566', '256', '50', '62', '-1', '-1', '2', NULL), +('711', '3370', '256', '63', '67', '-1', '-1', '2', NULL), +('711', '5378', '256', '68', '77', '-1', '-1', '2', NULL), +('711', '14071', '256', '78', '82', '-1', '-1', '2', NULL), +('711', '18056', '256', '83', '87', '-1', '-1', '2', NULL), +('711', '26033', '256', '88', '92', '-1', '-1', '2', NULL), +('711', '29128', '256', '93', '127', '-1', '-1', '2', NULL), +('711', '744', '256', '46', '62', '-1', '-1', '3', NULL), +('711', '3373', '256', '63', '66', '-1', '-1', '3', NULL), +('711', '5379', '256', '67', '76', '-1', '-1', '3', NULL), +('711', '14068', '256', '77', '81', '-1', '-1', '3', NULL), +('711', '18053', '256', '82', '86', '-1', '-1', '3', NULL), +('711', '26003', '256', '87', '91', '-1', '-1', '3', NULL), +('711', '29101', '256', '92', '127', '-1', '-1', '3', NULL), +('711', '3567', '256', '42', '60', '-1', '-1', '4', NULL), +('711', '3363', '256', '61', '65', '-1', '-1', '4', NULL), +('711', '5371', '256', '66', '75', '-1', '-1', '4', NULL), +('711', '14065', '256', '76', '80', '-1', '-1', '4', NULL), +('711', '18050', '256', '81', '85', '-1', '-1', '4', NULL), +('711', '25976', '256', '86', '90', '-1', '-1', '4', NULL), +('711', '29077', '256', '91', '127', '-1', '-1', '4', NULL), +('711', '707', '256', '30', '59', '-1', '-1', '5', NULL), +('711', '4210', '256', '60', '127', '-1', '-1', '5', NULL), + +-- slow +('711', '738', '8192', '23', '50', '-1', '-1', '1', NULL), +('711', '1751', '8192', '51', '59', '-1', '-1', '1', NULL), +('711', '1748', '8192', '60', '63', '-1', '-1', '1', NULL), +('711', '3066', '8192', '64', '127', '-1', '-1', '1', NULL), +('711', '738', '8192', '51', '63', '-1', '-1', '2', NULL), +('711', '1751', '8192', '64', '127', '-1', '-1', '2', NULL), +('711', '738', '8192', '64', '127', '-1', '-1', '3', NULL), + +-- cure +('711', '3682', '32768', '45', '85', '-1', '-1', '1', NULL), +('711', '25958', '32768', '86', '90', '-1', '-1', '1', NULL), +('711', '29059', '32768', '91', '127', '-1', '-1', '1', NULL), +('711', '3681', '32768', '52', '127', '-1', '-1', '2', NULL), +('711', '10448', '32768', '74', '78', '-1', '-1', '3', NULL), +('711', '14029', '32768', '79', '83', '-1', '-1', '3', NULL), +('711', '18023', '32768', '84', '127', '-1', '-1', '3', NULL), + +-- hate redux +('711', '1754', '131072', '53', '127', '-1', '-1', '1', NULL), +('711', '10436', '131072', '73', '127', '-1', '-1', '2', NULL), + +-- in-combat buff songs +('711', '2606', '262144', '52', '59', '-1', '-1', '1', NULL), +('711', '2610', '262144', '60', '127', '-1', '-1', '1', NULL), +('711', '700', '262144', '1', '9', '-1', '-1', '2', NULL), +('711', '701', '262144', '10', '35', '-1', '-1', '2', NULL), +('711', '740', '262144', '36', '41', '-1', '-1', '2', NULL), +('711', '702', '262144', '42', '49', '-1', '-1', '2', NULL), +('711', '747', '262144', '50', '61', '-1', '-1', '2', NULL), +('711', '3374', '262144', '62', '64', '-1', '-1', '2', NULL), +('711', '4871', '262144', '65', '67', '-1', '-1', '2', NULL), +('711', '5376', '262144', '68', '78', '-1', '-1', '2', NULL), +('711', '14080', '262144', '79', '83', '-1', '-1', '2', NULL), +('711', '18065', '262144', '84', '88', '-1', '-1', '2', NULL), +('711', '26042', '262144', '89', '93', '-1', '-1', '2', NULL), +('711', '29143', '262144', '94', '127', '-1', '-1', '2', NULL), +('711', '7', '262144', '6', '19', '-1', '-1', '2', NULL), +('711', '1287', '262144', '20', '31', '-1', '-1', '3', NULL), +('711', '723', '262144', '32', '33', '-1', '-1', '3', NULL), +('711', '1448', '262144', '34', '54', '-1', '-1', '3', NULL), +('711', '1759', '262144', '55', '61', '-1', '-1', '3', NULL), +('711', '3651', '262144', '62', '66', '-1', '-1', '3', NULL), +('711', '5377', '262144', '67', '70', '-1', '-1', '3', NULL), +('711', '10421', '262144', '71', '75', '-1', '-1', '3', NULL), +('711', '14008', '262144', '76', '80', '-1', '-1', '3', NULL), +('711', '18008', '262144', '81', '87', '-1', '-1', '3', NULL), +('711', '26015', '262144', '88', '92', '-1', '-1', '3', NULL), +('711', '29107', '262144', '93', '127', '-1', '-1', '3', NULL), +('711', '734', '262144', '7', '8', '-1', '-1', '4', NULL), +('711', '710', '262144', '9', '12', '-1', '-1', '4', NULL), +('711', '711', '262144', '13', '16', '-1', '-1', '4', NULL), +('711', '709', '262144', '17', '40', '-1', '-1', '4', NULL), +('711', '714', '262144', '41', '46', '-1', '-1', '4', NULL), +('711', '748', '262144', '47', '57', '-1', '-1', '4', NULL), +('711', '1763', '262144', '58', '72', '-1', '-1', '4', NULL), +('711', '11881', '262144', '73', '77', '-1', '-1', '4', NULL), +('711', '14056', '262144', '78', '82', '-1', '-1', '4', NULL), +('711', '18041', '262144', '83', '87', '-1', '-1', '4', NULL), +('711', '26027', '262144', '88', '92', '-1', '-1', '4', NULL), +('711', '29122', '262144', '93', '127', '-1', '-1', '4', NULL), +('711', '734', '262144', '9', '24', '-1', '-1', '5', NULL), +('711', '712', '262144', '25', '28', '-1', '-1', '5', NULL), +('711', '715', '262144', '29', '32', '-1', '-1', '5', NULL), +('711', '713', '262144', '33', '36', '-1', '-1', '5', NULL), +('711', '716', '262144', '37', '44', '-1', '-1', '5', NULL), +('711', '4083', '262144', '45', '52', '-1', '-1', '5', NULL), +('711', '4084', '262144', '53', '63', '-1', '-1', '5', NULL), +('711', '3362', '262144', '64', '64', '-1', '-1', '5', NULL), +('711', '4872', '262144', '65', '68', '-1', '-1', '5', NULL), +('711', '5382', '262144', '69', '75', '-1', '-1', '5', NULL), +('711', '14062', '262144', '76', '80', '-1', '-1', '5', NULL), +('711', '18047', '262144', '81', '85', '-1', '-1', '5', NULL), +('711', '25961', '262144', '86', '90', '-1', '-1', '5', NULL), +('711', '29062', '262144', '91', '127', '-1', '-1', '5', NULL), +('711', '734', '262144', '25', '43', '-1', '-1', '6', NULL), +('711', '4085', '262144', '44', '51', '-1', '-1', '6', NULL), +('711', '4086', '262144', '52', '62', '-1', '-1', '6', NULL), +('711', '4087', '262144', '63', '68', '-1', '-1', '6', NULL), +('711', '5374', '262144', '69', '71', '-1', '-1', '6', NULL), +('711', '10439', '262144', '72', '76', '-1', '-1', '6', NULL), +('711', '14020', '262144', '77', '81', '-1', '-1', '6', NULL), +('711', '18014', '262144', '82', '86', '-1', '-1', '6', NULL), +('711', '25991', '262144', '87', '127', '-1', '-1', '6', NULL), +('711', '734', '262144', '30', '82', '-1', '-1', '7', NULL), +('711', '18020', '262144', '83', '127', '-1', '-1', '7', NULL), +('711', '734', '262144', '83', '127', '-1', '-1', '8', NULL), +('711', '2603', '262144', '30', '127', '-1', '-1', '9', NULL), + +-- out-of-combat buff songs +('711', '7', '524288', '6', '19', '-1', '-1', '1', NULL), +('711', '1287', '524288', '20', '31', '-1', '-1', '1', NULL), +('711', '723', '524288', '32', '33', '-1', '-1', '1', NULL), +('711', '1448', '524288', '34', '54', '-1', '-1', '1', NULL), +('711', '1759', '524288', '55', '61', '-1', '-1', '1', NULL), +('711', '3651', '524288', '62', '66', '-1', '-1', '1', NULL), +('711', '5377', '524288', '67', '70', '-1', '-1', '1', NULL), +('711', '10421', '524288', '71', '75', '-1', '-1', '1', NULL), +('711', '14008', '524288', '76', '80', '-1', '-1', '1', NULL), +('711', '18008', '524288', '81', '87', '-1', '-1', '1', NULL), +('711', '26015', '524288', '88', '92', '-1', '-1', '1', NULL), +('711', '29107', '524288', '93', '127', '-1', '-1', '1', NULL), +('711', '717', '524288', '5', '29', '-1', '-1','2', NULL), +('711', '2603', '524288', '30', '127', '-1', '-1','2', NULL), +('711', '717', '524288', '30', '48', '-1', '-1','3', NULL), +('711', '2605', '524288', '49', '127', '-1', '-1','3', NULL), +('711', '2602', '524288', '15', '127', '-1', '-1','4', NULL); diff --git a/zone/bot.cpp b/zone/bot.cpp index 56d8fd5d1..240530237 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -76,7 +76,6 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm SetAltOutOfCombatBehavior(GetClass() == BARD); // will need to be updated if more classes make use of this flag SetShowHelm(true); SetPauseAI(false); - CalcChanceToCast(); rest_timer.Disable(); SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE); // Do this once and only in this constructor @@ -151,7 +150,6 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SetTaunting((GetClass() == WARRIOR || GetClass() == PALADIN || GetClass() == SHADOWKNIGHT) && (GetBotStance() == BotStanceAggressive)); SetPauseAI(false); - CalcChanceToCast(); rest_timer.Disable(); SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE); strcpy(this->name, this->GetCleanName()); @@ -7639,6 +7637,24 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } } + + if (iSpellTypes == SpellType_HateRedux) { + if (!caster->IsEngaged()) + return false; + + if (caster->HasGroup()) { + Group *g = caster->GetGroup(); + if (g) { + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (g->members[i] && caster->GetNeedsHateRedux(g->members[i])) { + if (caster->AICastSpell(g->members[i], caster->GetChanceToCastBySpellType(SpellType_HateRedux), SpellType_HateRedux)) + return true; + } + } + } + } + } + return false; } @@ -8017,7 +8033,7 @@ bool Bot::GetNeedsHateRedux(Mob *tar) { // This really should be a scalar function based in class Mob that returns 'this' state..but, is inline with current Bot coding... // TODO: Good starting point..but, can be refined.. // TODO: Still awaiting bot spell rework.. - if (!tar || !tar->HasTargetReflection()) + if (!tar || !tar->IsEngaged() || !tar->HasTargetReflection() || !tar->GetTarget()->IsNPC()) return false; if (tar->IsClient()) { @@ -8031,7 +8047,7 @@ bool Bot::GetNeedsHateRedux(Mob *tar) { else if (tar->IsBot()) { switch (tar->GetClass()) { case ROGUE: - if (tar->CastToBot()->evade_timer.Check(false)) + if (tar->CanFacestab() || tar->CastToBot()->evade_timer.Check(false)) return false; case CLERIC: case DRUID: diff --git a/zone/bot.h b/zone/bot.h index dda1c5f0e..97bf9fc1f 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -47,8 +47,6 @@ const int MaxSpellTimer = 15; const int MaxDisciplineTimer = 10; const int DisciplineReuseStart = MaxSpellTimer + 1; const int MaxTimer = MaxSpellTimer + MaxDisciplineTimer; -const int MaxStances = 7; -const int MaxSpellTypes = 16; enum BotStanceType { BotStancePassive, @@ -58,7 +56,8 @@ enum BotStanceType { BotStanceAggressive, BotStanceBurn, BotStanceBurnAE, - BotStanceUnknown + BotStanceUnknown, + MaxStances = BotStanceUnknown }; #define BOT_STANCE_COUNT 8 @@ -125,7 +124,12 @@ enum SpellTypeIndex { SpellType_CharmIndex, SpellType_SlowIndex, SpellType_DebuffIndex, - SpellType_CureIndex + SpellType_CureIndex, + SpellType_ResurrectIndex, + SpellType_HateReduxIndex, + SpellType_InCombatBuffSongIndex, + SpellType_OutOfCombatBuffSongIndex, + MaxSpellTypes }; class Bot : public NPC { @@ -296,7 +300,6 @@ public: bool GetNeedsHateRedux(Mob *tar); bool HasOrMayGetAggro(); void SetDefaultBotStance(); - void CalcChanceToCast(); inline virtual int32 GetMaxStat(); inline virtual int32 GetMaxResist(); @@ -417,6 +420,7 @@ public: static std::list GetBotSpellsForSpellEffect(Bot* botCaster, int spellEffect); static std::list GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, int spellEffect, SpellTargetType targetType); static std::list GetBotSpellsBySpellType(Bot* botCaster, uint32 spellType); + static std::list GetPrioritizedBotSpellsBySpellType(Bot* botCaster, uint32 spellType); static BotSpell GetFirstBotSpellBySpellType(Bot* botCaster, uint32 spellType); static BotSpell GetBestBotSpellForFastHeal(Bot* botCaster); static BotSpell GetBestBotSpellForHealOverTime(Bot* botCaster); @@ -669,7 +673,6 @@ private: uint32 timers[MaxTimer]; bool _hasBeenSummoned; glm::vec3 m_PreSummonLocation; - uint8 _spellCastingChances[MaxStances][MaxSpellTypes]; Timer evade_timer; diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index fa15dc7d2..ef995ce69 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -5117,7 +5117,6 @@ void bot_subcommand_bot_stance(Client *c, const Seperator *sep) if (!current_flag) { bot_iter->SetBotStance(bst); - bot_iter->CalcChanceToCast(); bot_iter->Save(); } diff --git a/zone/bot_structs.h b/zone/bot_structs.h index 996fbff41..a774bad70 100644 --- a/zone/bot_structs.h +++ b/zone/bot_structs.h @@ -56,6 +56,10 @@ struct BotSpell { int16 ManaCost; }; +struct BotSpell_wPriority : public BotSpell { + uint8 Priority; +}; + struct BotAA { uint32 aa_id; uint8 req_level; diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index c36e928bb..74870fed3 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -96,14 +96,8 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { castedSpell = AIDoSpellCast(botSpell.SpellIndex, addMob, botSpell.ManaCost); - if(castedSpell) { - char* gmsg = 0; - - MakeAnyLenString(&gmsg, "Attempting to mez %s.", addMob->GetCleanName()); - - if(gmsg) - BotGroupSay(this, gmsg); - } + if(castedSpell) + BotGroupSay(this, "Attempting to mez %s.", addMob->GetCleanName()); } break; } @@ -248,7 +242,6 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontHealMeBeforeTime); if(castedSpell) { - char* gmsg = 0; /*if(TempDontHealMeBeforeTime != tar->DontHealMeBefore()) tar->SetDontHealMeBefore(TempDontHealMeBeforeTime); @@ -270,7 +263,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { Group *g = this->GetGroup(); if(g) { - MakeAnyLenString(&gmsg, "Casting %s.", spells[botSpell.SpellId].name); + BotGroupSay(this, "Casting %s.", spells[botSpell.SpellId].name); for( int i = 0; imembers[i] && !g->members[i]->qglobal) { @@ -282,14 +275,11 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { } else { if(tar != this) //we don't need spam of bots healing themselves - MakeAnyLenString(&gmsg, "Casting %s on %s", spells[botSpell.SpellId].name, tar->GetCleanName()); + BotGroupSay(this, "Casting %s on %s", spells[botSpell.SpellId].name, tar->GetCleanName()); tar->SetDontHealMeBefore(Timer::GetCurrentTime() + 2000); } } - - if(gmsg) - BotGroupSay(this, gmsg); } } } @@ -748,35 +738,69 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { checked_los = true; } - std::list dotList = GetBotSpellsBySpellType(this, SpellType_DOT); + if (GetClass() == BARD) { + std::list dotList = GetPrioritizedBotSpellsBySpellType(this, SpellType_DOT); - const int maxDotSelect = 5; - int dotSelectCounter = 0; + const int maxDotSelect = 5; + int dotSelectCounter = 0; - for(std::list::iterator itr = dotList.begin(); itr != dotList.end(); ++itr) { - BotSpell selectedBotSpell = *itr; + for (std::list::iterator itr = dotList.begin(); itr != dotList.end(); ++itr) { + BotSpell selectedBotSpell = *itr; - if(selectedBotSpell.SpellId == 0) - continue; - - if(CheckSpellRecastTimers(this, itr->SpellIndex)) - { - - if(!(!tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0)) + if (selectedBotSpell.SpellId == 0) continue; - uint32 TempDontDotMeBefore = tar->DontDotMeBefore(); + if (CheckSpellRecastTimers(this, itr->SpellIndex)) + { - castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontDotMeBefore); + if (!(!tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0)) + continue; - if(TempDontDotMeBefore != tar->DontDotMeBefore()) - tar->SetDontDotMeBefore(TempDontDotMeBefore); + uint32 TempDontDotMeBefore = tar->DontDotMeBefore(); + + castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontDotMeBefore); + + if (TempDontDotMeBefore != tar->DontDotMeBefore()) + tar->SetDontDotMeBefore(TempDontDotMeBefore); + } + + dotSelectCounter++; + + if ((dotSelectCounter == maxDotSelect) || castedSpell) + break; } + } + else { + std::list dotList = GetBotSpellsBySpellType(this, SpellType_DOT); - dotSelectCounter++; + const int maxDotSelect = 5; + int dotSelectCounter = 0; - if((dotSelectCounter == maxDotSelect) || castedSpell) - break; + for (std::list::iterator itr = dotList.begin(); itr != dotList.end(); ++itr) { + BotSpell selectedBotSpell = *itr; + + if (selectedBotSpell.SpellId == 0) + continue; + + if (CheckSpellRecastTimers(this, itr->SpellIndex)) + { + + if (!(!tar->IsImmuneToSpell(selectedBotSpell.SpellId, this) && tar->CanBuffStack(selectedBotSpell.SpellId, botLevel, true) >= 0)) + continue; + + uint32 TempDontDotMeBefore = tar->DontDotMeBefore(); + + castedSpell = AIDoSpellCast(selectedBotSpell.SpellIndex, tar, selectedBotSpell.ManaCost, &TempDontDotMeBefore); + + if (TempDontDotMeBefore != tar->DontDotMeBefore()) + tar->SetDontDotMeBefore(TempDontDotMeBefore); + } + + dotSelectCounter++; + + if ((dotSelectCounter == maxDotSelect) || castedSpell) + break; + } } } break; @@ -792,6 +816,28 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { } switch (botClass) { + case BARD: { + // probably needs attackable check + std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_Slow); + for (auto iter : botSongList) { + if (!iter.SpellId) + continue; + if (!CheckSpellRecastTimers(this, iter.SpellIndex)) + continue; + if (spells[iter.SpellId].zonetype != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zonetype != zone->GetZoneType()) // is this bit or index? + continue; + if (spells[iter.SpellId].targettype != ST_Target) + continue; + if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) + continue; + + castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); + if (castedSpell) + break; + } + + break; + } case ENCHANTER: { botSpell = GetBestBotSpellForMagicBasedSlow(this); break; @@ -814,14 +860,8 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost); - if(castedSpell) { - char* gmsg = 0; - - MakeAnyLenString(&gmsg, "Attempting to slow %s.", tar->GetCleanName()); - - if(gmsg) - BotGroupSay(this, gmsg); - } + if(castedSpell && GetClass() != BARD) + BotGroupSay(this, "Attempting to slow %s.", tar->GetCleanName()); } break; } @@ -889,6 +929,100 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { } break; } + case SpellType_Resurrect: + break; + case SpellType_HateRedux: { + // assumed group member at this point + if (GetClass() == BARD) { + std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_HateRedux); + for (auto iter : botSongList) { + if (!iter.SpellId) + continue; + if (!CheckSpellRecastTimers(this, iter.SpellIndex)) + continue; + if (spells[iter.SpellId].zonetype != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zonetype != zone->GetZoneType()) // is this bit or index? + continue; + if (spells[iter.SpellId].targettype != ST_Target) + continue; + if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) + continue; + + castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); + if (castedSpell) { + BotGroupSay(this, "Attempting to reduce hate on %s.", tar->GetCleanName()); + break; + } + } + } + + break; + } + case SpellType_InCombatBuffSong: { + if (GetClass() != BARD || tar != this) // In-Combat songs can be cast Out-of-Combat in preparation for battle + break; + + std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_InCombatBuffSong); + for (auto iter : botSongList) { + if (!iter.SpellId) + continue; + if (!CheckSpellRecastTimers(this, iter.SpellIndex)) + continue; + if (spells[iter.SpellId].zonetype != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zonetype != zone->GetZoneType()) // is this bit or index? + continue; + switch (spells[iter.SpellId].targettype) { + case ST_AEBard: + case ST_AECaster: + case ST_GroupTeleport: + case ST_Group: + case ST_Self: + break; + default: + continue; + } + if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) + continue; + + castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); + if (castedSpell) + break; + } + + break; + } + case SpellType_OutOfCombatBuffSong: { + if (GetClass() != BARD || tar != this || IsEngaged()) // Out-of-Combat songs can not be cast in combat + break; + + std::list botSongList = GetPrioritizedBotSpellsBySpellType(this, SpellType_OutOfCombatBuffSong); + for (auto iter : botSongList) { + if (!iter.SpellId) + continue; + if (!CheckSpellRecastTimers(this, iter.SpellIndex)) + continue; + if (spells[iter.SpellId].zonetype != -1 && zone->GetZoneType() != -1 && spells[iter.SpellId].zonetype != zone->GetZoneType()) // is this bit or index? + continue; + switch (spells[iter.SpellId].targettype) { + case ST_AEBard: + case ST_AECaster: + case ST_GroupTeleport: + case ST_Group: + case ST_Self: + break; + default: + continue; + } + if (tar->CanBuffStack(iter.SpellId, botLevel, true) < 0) + continue; + + castedSpell = AIDoSpellCast(iter.SpellIndex, tar, iter.ManaCost); + if (castedSpell) + break; + } + + break; + } + default: + break; } return castedSpell; @@ -945,22 +1079,18 @@ bool Bot::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain extraMana = false; } else { //handle spell recast and recast timers - if(GetClass() == BARD && IsGroupSpell(AIspells[i].spellid)) { - // Bard Clarity songs (spellids: 723 & 1287) are recast_time = 0 and buffduration = 0. - // This translates to an insta-recast in the above check and is essentially locking all idle bard songs - // between levels 20 & 33 to one of the clarity songs. + //if(GetClass() == BARD && IsGroupSpell(AIspells[i].spellid)) { + // // Bard buff songs have been moved to their own npc spell type.. + // // Buff stacking is now checked as opposed to manipulating the timer to avoid rapid casting + + // //AIspells[i].time_cancast = (spells[AIspells[i].spellid].recast_time > (spells[AIspells[i].spellid].buffduration * 6000)) ? Timer::GetCurrentTime() + spells[AIspells[i].spellid].recast_time : Timer::GetCurrentTime() + spells[AIspells[i].spellid].buffduration * 6000; + // //spellend_timer.Start(spells[AIspells[i].spellid].cast_time); + //} + //else + // AIspells[i].time_cancast = Timer::GetCurrentTime() + spells[AIspells[i].spellid].recast_time; + + AIspells[i].time_cancast = Timer::GetCurrentTime() + spells[AIspells[i].spellid].recast_time; - // Hard-coded fix of '0/0' bard songs..watch for issues in other song lines - if(spells[AIspells[i].spellid].recast_time == 0 && spells[AIspells[i].spellid].buffduration == 0 && spells[AIspells[i].spellid].goodEffect > 0) { - AIspells[i].time_cancast = Timer::GetCurrentTime() + (3 * 6000); // pseudo 'buffduration' of 3 (value matches others in bard 'heal' song line) - } - else { - AIspells[i].time_cancast = (spells[AIspells[i].spellid].recast_time > (spells[AIspells[i].spellid].buffduration * 6000)) ? Timer::GetCurrentTime() + spells[AIspells[i].spellid].recast_time : Timer::GetCurrentTime() + spells[AIspells[i].spellid].buffduration * 6000; - } - //spellend_timer.Start(spells[AIspells[i].spellid].cast_time); - } - else - AIspells[i].time_cancast = Timer::GetCurrentTime() + spells[AIspells[i].spellid].recast_time; if(spells[AIspells[i].spellid].EndurTimerIndex > 0) { SetSpellRecastTimer(spells[AIspells[i].spellid].EndurTimerIndex, spells[AIspells[i].spellid].recast_time); } @@ -1049,13 +1179,27 @@ bool Bot::AI_IdleCastCheck() { } else if(botClass == BARD) { // bard bots - if(!AICastSpell(this, 100, SpellType_Cure)) { - if(!AICastSpell(this, 100, SpellType_Heal)) { - if((!RuleB(Bots, BotBardUseOutOfCombatSongs) || !GetAltOutOfCombatBehavior()) || !AICastSpell(this, 100, SpellType_Buff)) { // skips if rule is false - if(!AICastSpell(this, 100, SpellType_InCombatBuff)) { // this tries to keep some combat buffs on the group until engaged code can pick up the buffing - // - } - } + bool battle_prep = false; + Mob* prep_against = nullptr; + + if (HasGroup() && GetGroup()->GetLeader() && GetGroup()->GetLeader()->IsClient()) + prep_against = GetGroup()->GetLeader(); + else if (GetOwner() && GetOwner()->IsClient()) + prep_against = GetOwner(); + + if (prep_against && prep_against->GetTarget() && prep_against->GetTarget()->IsNPC() && !prep_against->GetTarget()->IsPet()) + battle_prep = true; + + if (battle_prep) { + if (!AICastSpell(this, 100, SpellType_InCombatBuffSong)) { + // + } + } + else { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { + if (!AICastSpell(this, 100, SpellType_OutOfCombatBuffSong)) { + // + } } } @@ -1063,7 +1207,7 @@ bool Bot::AI_IdleCastCheck() { } if(!AIautocastspell_timer->Enabled()) - AIautocastspell_timer->Start(RandomTimer(1000, 5000), false); + AIautocastspell_timer->Start(RandomTimer(500, 2000), false); // avg human response is much less than 5 seconds..even for non-combat situations... } return result; @@ -1256,13 +1400,15 @@ bool Bot::AI_EngagedCastCheck() { } } else if(botClass == BARD) { - if(!AICastSpell(this, GetChanceToCastBySpellType(SpellType_InCombatBuff), SpellType_InCombatBuff)) { - if(!AICastSpell(this, GetChanceToCastBySpellType(SpellType_Heal), SpellType_Heal)) { - if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Dispel), SpellType_Dispel)) {// Bards will use their dispel songs - if(!AICastSpell(GetTarget(), mayGetAggro?0:GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) {// Bards will use their nuke songs - if(!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {// Bards will use their escape songs - // - failedToCast = true; + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, GetChanceToCastBySpellType(SpellType_HateRedux), BotAISpellRange, SpellType_HateRedux)) { + if (!AICastSpell(this, GetChanceToCastBySpellType(SpellType_InCombatBuffSong), SpellType_InCombatBuffSong)) { + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Slow), SpellType_Slow)) { + if (!AICastSpell(GetTarget(), mayGetAggro ? 0 : GetChanceToCastBySpellType(SpellType_DOT), SpellType_DOT)) {// Bards will use their dot songs + if (!AICastSpell(GetTarget(), mayGetAggro ? 0 : GetChanceToCastBySpellType(SpellType_Nuke), SpellType_Nuke)) {// Bards will use their nuke songs + if (!AICastSpell(GetTarget(), GetChanceToCastBySpellType(SpellType_Escape), SpellType_Escape)) {// Bards will use their escape songs + // + failedToCast = true; + } } } } @@ -1271,7 +1417,7 @@ bool Bot::AI_EngagedCastCheck() { } if(!AIautocastspell_timer->Enabled()) { - AIautocastspell_timer->Start(RandomTimer(100, 250), false); + AIautocastspell_timer->Start(RandomTimer(150, 300), false); } if(!failedToCast) @@ -1349,14 +1495,8 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) { castedSpell = AIDoSpellCast(botSpell.SpellIndex, tar, botSpell.ManaCost, &TempDontHealMeBeforeTime); - if(castedSpell) { - char* gmsg = 0; - - MakeAnyLenString(&gmsg, "Casting %s on %s, please stay in range!", spells[botSpell.SpellId].name, tar->GetCleanName()); - - if(gmsg) - Say(gmsg); - } + if(castedSpell) + Say("Casting %s on %s, please stay in range!", spells[botSpell.SpellId].name, tar->GetCleanName()); return castedSpell; } @@ -1444,6 +1584,37 @@ std::list Bot::GetBotSpellsBySpellType(Bot* botCaster, uint32 spellTyp return result; } +std::list Bot::GetPrioritizedBotSpellsBySpellType(Bot* botCaster, uint32 spellType) { + std::list result; + + if (botCaster && botCaster->AI_HasSpells()) { + std::vector botSpellList = botCaster->GetBotSpells(); + + for (int i = botSpellList.size() - 1; i >= 0; i--) { + if (botSpellList[i].spellid <= 0 || botSpellList[i].spellid >= SPDAT_RECORDS) { + // this is both to quit early to save cpu and to avoid casting bad spells + // Bad info from database can trigger this incorrectly, but that should be fixed in DB, not here + continue; + } + + if (botSpellList[i].type & spellType) { + BotSpell_wPriority botSpell; + botSpell.SpellId = botSpellList[i].spellid; + botSpell.SpellIndex = i; + botSpell.ManaCost = botSpellList[i].manacost; + botSpell.Priority = botSpellList[i].priority; + + result.push_back(botSpell); + } + } + + if (result.size() > 1) + result.sort([](BotSpell_wPriority& l, BotSpell_wPriority& r) { return l.Priority < r.Priority; }); + } + + return result; +} + BotSpell Bot::GetFirstBotSpellBySpellType(Bot* botCaster, uint32 spellType) { BotSpell result; @@ -1738,9 +1909,9 @@ BotSpell Bot::GetBestBotSpellForMagicBasedSlow(Bot* botCaster) { if(botCaster) { std::list botSpellList = GetBotSpellsForSpellEffect(botCaster, SE_AttackSpeed); - for(std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { + for (std::list::iterator botSpellListItr = botSpellList.begin(); botSpellListItr != botSpellList.end(); ++botSpellListItr) { // Assuming all the spells have been loaded into this list by level and in descending order - if(IsSlowSpell(botSpellListItr->SpellId) && spells[botSpellListItr->SpellId].resisttype == RESIST_MAGIC && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { + if (IsSlowSpell(botSpellListItr->SpellId) && spells[botSpellListItr->SpellId].resisttype == RESIST_MAGIC && CheckSpellRecastTimers(botCaster, botSpellListItr->SpellIndex)) { result.SpellId = botSpellListItr->SpellId; result.SpellIndex = botSpellListItr->SpellIndex; result.ManaCost = botSpellListItr->ManaCost; @@ -2139,7 +2310,7 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) { } BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) { - BotSpell result; + BotSpell_wPriority result; bool spellSelected = false; result.SpellId = 0; @@ -2156,7 +2327,7 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) { bool isCorrupted = tar->FindType(SE_CorruptionCounter); if(botCaster && botCaster->AI_HasSpells()) { - std::list cureList = GetBotSpellsBySpellType(botCaster, SpellType_Cure); + std::list cureList = GetPrioritizedBotSpellsBySpellType(botCaster, SpellType_Cure); if(tar->HasGroup()) { Group *g = tar->GetGroup(); @@ -2173,7 +2344,7 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) { //Check for group cure first if(countNeedsCured > 2) { - for(std::list::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) { + for (std::list::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) { BotSpell selectedBotSpell = *itr; if(IsGroupSpell(itr->SpellId) && CheckSpellRecastTimers(botCaster, itr->SpellIndex)) { @@ -2210,7 +2381,7 @@ BotSpell Bot::GetBestBotSpellForCure(Bot* botCaster, Mob *tar) { //no group cure for target- try to find single target spell if(!spellSelected) { - for(std::list::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) { + for(std::list::iterator itr = cureList.begin(); itr != cureList.end(); ++itr) { BotSpell selectedBotSpell = *itr; if(CheckSpellRecastTimers(botCaster, itr->SpellIndex)) { @@ -2312,1099 +2483,3040 @@ bool Bot::CheckDisciplineRecastTimers(Bot *caster, int timer_index) { return false; } -void Bot::CalcChanceToCast() { - uint8 castChance = 0; - - for(int i=0; i < MaxStances; i++) { - for(int j=0; j < MaxSpellTypes; j++) { - _spellCastingChances[i][j] = 0; +uint8 Bot::GetChanceToCastBySpellType(uint32 spellType) +{ + enum : uint8 { nHS = 0, pH, pS, pHS, cntHS}; // negative Healer/Slower, positive Healer, postive Slower, positive Healer/Slower + + static const uint8 spell_casting_chances[MaxSpellTypes][PLAYER_CLASS_COUNT][MaxStances][cntHS] = { +// SpellType_NukeIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 15, 25, 15 }, // Balanced { nHS, pH, pS, pHS } + { 15, 0, 15, 0 }, // Efficient { nHS, pH, pS, pHS } + { 25, 15, 25, 15 }, // Reactive { nHS, pH, pS, pHS } + { 50, 15, 50, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 25, 50, 25 }, // Burn { nHS, pH, pS, pHS } + { 50, 25, 50, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 15, 25, 15 }, // Balanced { nHS, pH, pS, pHS } + { 15, 0, 15, 0 }, // Efficient { nHS, pH, pS, pHS } + { 25, 15, 25, 15 }, // Reactive { nHS, pH, pS, pHS } + { 50, 15, 50, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 25, 50, 25 }, // Burn { nHS, pH, pS, pHS } + { 50, 25, 50, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } + { 5, 5, 5, 5 }, // Efficient { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Burn { nHS, pH, pS, pHS } + { 50, 50, 50, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } + { 5, 5, 5, 5 }, // Efficient { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Burn { nHS, pH, pS, pHS } + { 50, 50, 50, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 15, 25, 15 }, // Balanced { nHS, pH, pS, pHS } + { 15, 0, 15, 0 }, // Efficient { nHS, pH, pS, pHS } + { 25, 15, 25, 15 }, // Reactive { nHS, pH, pS, pHS } + { 50, 15, 50, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 25, 50, 25 }, // Burn { nHS, pH, pS, pHS } + { 50, 25, 50, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } + { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 10, 5, 0 }, // Balanced { nHS, pH, pS, pHS } + { 10, 5, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 15, 10, 5, 0 }, // Reactive { nHS, pH, pS, pHS } + { 25, 15, 15, 5 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 25, 25, 15 }, // Burn { nHS, pH, pS, pHS } + { 50, 25, 25, 15 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } + { 5, 5, 5, 5 }, // Efficient { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Burn { nHS, pH, pS, pHS } + { 50, 50, 50, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Reactive { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Aggressive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } + { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Reactive { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Aggressive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } + { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 15, 15 }, // Balanced { nHS, pH, pS, pHS } + { 15, 15, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 15, 15 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 50, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 50, 50, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 10, 5, 0 }, // Balanced { nHS, pH, pS, pHS } + { 10, 5, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 15, 10, 5, 0 }, // Reactive { nHS, pH, pS, pHS } + { 25, 15, 15, 5 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 25, 25, 15 }, // Burn { nHS, pH, pS, pHS } + { 50, 25, 25, 15 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_HealIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Efficient { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Burn { nHS, pH, pS, pHS } + { 50, 50, 50, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 100, 25, 100 }, // Balanced { nHS, pH, pS, pHS } + { 15, 75, 15, 75 }, // Efficient { nHS, pH, pS, pHS } + { 25, 100, 25, 100 }, // Reactive { nHS, pH, pS, pHS } + { 15, 75, 15, 75 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 50, 0, 50 }, // Burn { nHS, pH, pS, pHS } + { 0, 50, 0, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 100, 25, 100 }, // Balanced { nHS, pH, pS, pHS } + { 15, 75, 15, 75 }, // Efficient { nHS, pH, pS, pHS } + { 25, 100, 25, 100 }, // Reactive { nHS, pH, pS, pHS } + { 15, 75, 15, 75 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 50, 0, 50 }, // Burn { nHS, pH, pS, pHS } + { 0, 50, 0, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } + { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 100, 25, 100 }, // Balanced { nHS, pH, pS, pHS } + { 15, 100, 15, 100 }, // Efficient { nHS, pH, pS, pHS } + { 25, 100, 25, 100 }, // Reactive { nHS, pH, pS, pHS } + { 25, 75, 25, 75 }, // Aggressive { nHS, pH, pS, pHS } + { 10, 50, 10, 50 }, // Burn { nHS, pH, pS, pHS } + { 10, 50, 10, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 100, 25, 100 }, // Balanced { nHS, pH, pS, pHS } + { 15, 100, 15, 100 }, // Efficient { nHS, pH, pS, pHS } + { 25, 100, 25, 100 }, // Reactive { nHS, pH, pS, pHS } + { 25, 75, 25, 75 }, // Aggressive { nHS, pH, pS, pHS } + { 10, 50, 10, 50 }, // Burn { nHS, pH, pS, pHS } + { 10, 50, 10, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 100, 25, 100 }, // Balanced { nHS, pH, pS, pHS } + { 15, 75, 15, 75 }, // Efficient { nHS, pH, pS, pHS } + { 25, 100, 25, 100 }, // Reactive { nHS, pH, pS, pHS } + { 15, 75, 15, 75 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 50, 0, 50 }, // Burn { nHS, pH, pS, pHS } + { 0, 50, 0, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_RootIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_BuffIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_EscapeIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } + { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Efficient { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } + { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } + { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } + { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } + { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Efficient { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } + { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Efficient { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_PetIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Burn { nHS, pH, pS, pHS } + { 10, 10, 10, 10 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Burn { nHS, pH, pS, pHS } + { 10, 10, 10, 10 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Burn { nHS, pH, pS, pHS } + { 10, 10, 10, 10 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Burn { nHS, pH, pS, pHS } + { 10, 10, 10, 10 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_LifetapIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } + { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } + { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_SnareIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_DOTIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 15, 10, 10 }, // Balanced { nHS, pH, pS, pHS } + { 10, 10, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 15, 15, 10, 10 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 50, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 50, 50, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 15, 10, 10 }, // Balanced { nHS, pH, pS, pHS } + { 10, 10, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 15, 15, 10, 10 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 50, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 50, 50, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 15, 50, 15 }, // Balanced { nHS, pH, pS, pHS } + { 25, 10, 25, 10 }, // Efficient { nHS, pH, pS, pHS } + { 50, 15, 50, 15 }, // Reactive { nHS, pH, pS, pHS } + { 50, 25, 50, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 25, 50, 25 }, // Burn { nHS, pH, pS, pHS } + { 50, 25, 50, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 25, 25, 15, 15 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 100, 100, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 100, 100, 50, 50 }, // Burn { nHS, pH, pS, pHS } + { 100, 100, 50, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 15, 15, 0 }, // Balanced { nHS, pH, pS, pHS } + { 15, 10, 10, 0 }, // Efficient { nHS, pH, pS, pHS } + { 25, 15, 15, 0 }, // Reactive { nHS, pH, pS, pHS } + { 50, 25, 50, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 25, 50, 15 }, // Burn { nHS, pH, pS, pHS } + { 50, 25, 50, 15 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Burn { nHS, pH, pS, pHS } + { 75, 75, 75, 75 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 15, 15 }, // Balanced { nHS, pH, pS, pHS } + { 25, 25, 10, 10 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 15, 15 }, // Reactive { nHS, pH, pS, pHS } + { 15, 15, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 15, 15, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 15, 15, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 15, 10, 10 }, // Balanced { nHS, pH, pS, pHS } + { 10, 10, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 15, 15, 10, 10 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 50, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 50, 50, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_DispelIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_InCombatBuffIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } + { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Burn { nHS, pH, pS, pHS } + { 50, 50, 50, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 75, 50, 75 }, // Balanced { nHS, pH, pS, pHS } + { 25, 50, 25, 50 }, // Efficient { nHS, pH, pS, pHS } + { 50, 75, 50, 75 }, // Reactive { nHS, pH, pS, pHS } + { 75, 100, 75, 100 }, // Aggressive { nHS, pH, pS, pHS } + { 75, 100, 75, 100 }, // Burn { nHS, pH, pS, pHS } + { 75, 100, 75, 100 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_MezIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_CharmIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_SlowIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 15, 15, 100, 100 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 50, 50 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 50, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 25, 25, 100, 100 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 15, 15, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 15, 15, 50, 50 }, // Burn { nHS, pH, pS, pHS } + { 15, 15, 50, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 50, 50, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 25, 25, 100, 100 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 15, 15, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 15, 15, 50, 50 }, // Burn { nHS, pH, pS, pHS } + { 15, 15, 50, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 15, 15, 100, 100 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 50, 50 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 50, 50 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_DebuffIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Efficient { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } + { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } + { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } + { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_CureIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Balanced { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Efficient { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Aggressive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } + { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_ResurrectIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_HateReduxIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_InCombatBuffSongIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Efficient { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Reactive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Aggressive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } + { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } + }, +// SpellType_OutOfCombatBuffSongIndex + { + {// WarriorIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ClericIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// PaladinIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RangerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShadowknightIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// DruidIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MonkIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Balanced { nHS, pH, pS, pHS } + { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } + { 75, 75, 75, 75 }, // Reactive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Aggressive { nHS, pH, pS, pHS } + { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } + { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } + }, + {// RogueIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// ShamanIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// NecromancerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// WizardIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// MagicianIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// EnchanterIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BeastlordIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + }, + {// BerserkerIndex + { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } + { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } + { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } + } } - } - - BotStanceType botStance = GetBotStance(); - uint8 botClass = GetClass(); - bool isPrimaryHealer = false; - bool isPrimarySlower = false; - - if(HasGroup()) { - isPrimaryHealer = IsGroupPrimaryHealer(); - isPrimarySlower = IsGroupPrimarySlower(); - } - - //Nuke - switch(botClass) - { - case WIZARD: - case MAGICIAN: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - case BotStanceAggressive: - castChance = 75; - break; - case BotStanceEfficient: - castChance = 50; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 100; - break; - default: - castChance = 0; - break; - } - break; - case DRUID: - case CLERIC: - case PALADIN: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimaryHealer?15:25; - break; - case BotStanceEfficient: - castChance = isPrimaryHealer?0:15; - break; - case BotStanceAggressive: - castChance = isPrimaryHealer?15:50; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimaryHealer?25:50; - break; - default: - castChance = 0; - break; - } - break; - case ENCHANTER: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimarySlower?15:25; - break; - case BotStanceEfficient: - castChance = isPrimarySlower?0:15; - break; - case BotStanceAggressive: - castChance = isPrimarySlower?15:50; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimarySlower?25:50; - break; - default: - castChance = 0; - break; - } - break; - case BEASTLORD: - case SHAMAN: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimarySlower?isPrimaryHealer?0:5:isPrimaryHealer?10:15; - break; - case BotStanceEfficient: - castChance = isPrimarySlower?isPrimaryHealer?0:0:isPrimaryHealer?5:10; - break; - case BotStanceAggressive: - castChance = isPrimarySlower?isPrimaryHealer?5:15:isPrimaryHealer?15:25; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimarySlower?isPrimaryHealer?15:25:isPrimaryHealer?25:50; - break; - default: - castChance = 0; - break; - } - break; - case NECROMANCER: - case RANGER: - case SHADOWKNIGHT: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - case BotStanceAggressive: - castChance = 15; - break; - case BotStanceEfficient: - castChance = 5; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 50; - break; - default: - castChance = 0; - break; - } - break; - case BARD: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - case BotStanceAggressive: - castChance = 50; - break; - case BotStanceEfficient: - castChance = 25; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 100; - break; - default: - castChance = 0; - break; - } - break; - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_NukeIndex] = castChance; - - //Heal - switch(botClass) - { - case CLERIC: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceEfficient: - case BotStanceReactive: - castChance = 100; - break; - case BotStanceAggressive: - castChance = 75; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 50; - break; - default: - castChance = 0; - break; - } - break; - case DRUID: - case SHAMAN: - switch(botStance) - { - case BotStanceEfficient: - castChance = isPrimaryHealer?100:15; - break; - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimaryHealer?100:25; - break; - case BotStanceAggressive: - castChance = isPrimaryHealer?75:15; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimaryHealer?50:10; - break; - default: - castChance = 0; - break; - } - break; - case NECROMANCER: - case MAGICIAN: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 100; - break; - case BotStanceEfficient: - case BotStanceAggressive: - castChance = 50; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 25; - break; - default: - castChance = 0; - break; - } - break; - case SHADOWKNIGHT: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 50; - break; - case BotStanceEfficient: - case BotStanceAggressive: - castChance = 25; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 15; - break; - default: - castChance = 0; - break; - } - break; - case BEASTLORD: - case PALADIN: - case RANGER: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimaryHealer?100:25; - break; - case BotStanceEfficient: - case BotStanceAggressive: - castChance = isPrimaryHealer?75:15; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimaryHealer?50:0; - break; - default: - castChance = 0; - break; - } - break; - case BARD: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 100; - break; - case BotStanceEfficient: - case BotStanceAggressive: - castChance = 50; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 25; - break; - default: - castChance = 0; - break; - } - break; - case ENCHANTER: - case WIZARD: - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_HealIndex] = castChance; - - //Root - castChance = 0; - _spellCastingChances[botStance][SpellType_RootIndex] = castChance; - - //Buff - switch(botClass) - { - case BARD: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 100; - break; - case BotStanceEfficient: - case BotStanceAggressive: - castChance = 50; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 25; - break; - default: - castChance = 0; - break; - } - break; - case CLERIC: - case DRUID: - case SHAMAN: - case NECROMANCER: - case MAGICIAN: - case SHADOWKNIGHT: - case BEASTLORD: - case PALADIN: - case RANGER: - case ENCHANTER: - case WIZARD: - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_BuffIndex] = castChance; - - //Escape - switch(botClass) - { - case ENCHANTER: - case WIZARD: - case RANGER: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - case BotStanceEfficient: - castChance = 100; - break; - case BotStanceAggressive: - castChance = 50; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 25; - break; - default: - castChance = 0; - break; - } - break; - case CLERIC: - case DRUID: - case SHAMAN: - case NECROMANCER: - case MAGICIAN: - case BARD: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - case BotStanceEfficient: - castChance = 50; - break; - case BotStanceAggressive: - castChance = 25; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 15; - break; - default: - castChance = 0; - break; - } - break; - case SHADOWKNIGHT: - case PALADIN: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 25; - break; - case BotStanceEfficient: - castChance = 15; - break; - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - break; - case BEASTLORD: - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_EscapeIndex] = castChance; - - //Pet - switch(botClass) - { - case MAGICIAN: - case NECROMANCER: - case BEASTLORD: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 100; - break; - case BotStanceEfficient: - case BotStanceAggressive: - castChance = 50; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 25; - break; - default: - castChance = 0; - break; - } - break; - case DRUID: - case SHAMAN: - case ENCHANTER: - case SHADOWKNIGHT: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 25; - break; - case BotStanceEfficient: - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 10; - break; - default: - castChance = 0; - break; - } - break; - case BARD: - case WIZARD: - case CLERIC: - case RANGER: - case PALADIN: - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_PetIndex] = castChance; - - //Lifetap - switch(botClass) - { - case NECROMANCER: - case SHADOWKNIGHT: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - case BotStanceEfficient: - case BotStanceAggressive: - castChance = 50; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 100; - break; - default: - castChance = 0; - break; - } - break; - case MAGICIAN: - case BEASTLORD: - case DRUID: - case SHAMAN: - case ENCHANTER: - case BARD: - case WIZARD: - case CLERIC: - case RANGER: - case PALADIN: - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_LifetapIndex] = castChance; - - //Snare - castChance = 0; - _spellCastingChances[botStance][SpellType_SnareIndex] = castChance; - - //DOT - switch(botClass) - { - case NECROMANCER: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - case BotStanceAggressive: - castChance = 50; - break; - case BotStanceEfficient: - castChance = 25; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 75; - break; - default: - castChance = 0; - break; - } - break; - case DRUID: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimaryHealer?15:50; - break; - case BotStanceEfficient: - castChance = isPrimaryHealer?10:25; - break; - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimaryHealer?25:50; - break; - default: - castChance = 0; - break; - } - break; - case ENCHANTER: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimarySlower?15:50; - break; - case BotStanceEfficient: - castChance = isPrimarySlower?10:25; - break; - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimarySlower?25:15; - break; - default: - castChance = 0; - break; - } - break; - case SHAMAN: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimarySlower?isPrimaryHealer?0:15:isPrimaryHealer?15:25; - break; - case BotStanceEfficient: - castChance = isPrimarySlower?isPrimaryHealer?0:10:isPrimaryHealer?10:15; - break; - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimarySlower?isPrimaryHealer?15:50:isPrimaryHealer?25:50; - break; - default: - castChance = 0; - break; - } - break; - case BEASTLORD: - case RANGER: - case SHADOWKNIGHT: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimarySlower?10:15; - break; - case BotStanceEfficient: - castChance = isPrimarySlower?0:10; - break; - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimarySlower?25:50; - break; - default: - castChance = 0; - break; - } - break; - case BARD: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimarySlower?25:50; - break; - case BotStanceEfficient: - castChance = isPrimarySlower?15:25; - break; - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimarySlower?50:100; - break; - default: - castChance = 0; - break; - } - break; - case MAGICIAN: - case PALADIN: - case CLERIC: - case WIZARD: - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_DOTIndex] = castChance; - - //Dispel - switch(botClass) - { - case BARD: - case ENCHANTER: - case WIZARD: - case MAGICIAN: - case CLERIC: - case DRUID: - case SHAMAN: - case NECROMANCER: - case RANGER: - case SHADOWKNIGHT: - case PALADIN: - case BEASTLORD: - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_DispelIndex] = castChance; - - //InCombatBuff - switch(botClass) - { - case CLERIC: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 15; - break; - case BotStanceEfficient: - castChance = 0; - break; - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 25; - break; - default: - castChance = 0; - break; - } - break; - case PALADIN: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 25; - break; - case BotStanceEfficient: - castChance = 0; - break; - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 50; - break; - default: - castChance = 0; - break; - } - break; - case SHAMAN: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimaryHealer?75:50; - break; - case BotStanceEfficient: - castChance = isPrimaryHealer?50:25; - break; - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimaryHealer?100:75; - break; - default: - castChance = 0; - break; - } - break; - case BARD: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 100; - break; - case BotStanceEfficient: - case BotStanceAggressive: - castChance = 50; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 25; - break; - default: - castChance = 0; - break; - } - break; - case BEASTLORD: - case MAGICIAN: - case DRUID: - case ENCHANTER: - case WIZARD: - case NECROMANCER: - case SHADOWKNIGHT: - case RANGER: - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_InCombatBuffIndex] = castChance; - - //Mez - switch(botClass) - { - case ENCHANTER: - case BARD: - castChance = 100; - break; - case WIZARD: - case CLERIC: - case DRUID: - case SHAMAN: - case NECROMANCER: - case MAGICIAN: - case RANGER: - case SHADOWKNIGHT: - case PALADIN: - case BEASTLORD: - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_MezIndex] = castChance; - - //Charm - castChance = 0; - _spellCastingChances[botStance][SpellType_CharmIndex] = castChance; - - //Slow - switch(botClass) - { - case ENCHANTER: - case SHAMAN: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimarySlower?100:50; - break; - case BotStanceEfficient: - castChance = isPrimarySlower?100:25; - break; - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimarySlower?50:15; - break; - default: - castChance = 0; - break; - } - break; - case BARD: - case BEASTLORD: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = isPrimarySlower?100:25; - break; - case BotStanceEfficient: - castChance = isPrimarySlower?100:15; - break; - case BotStanceAggressive: - case BotStanceBurn: - case BotStanceBurnAE: - castChance = isPrimarySlower?50:0; - break; - default: - castChance = 0; - break; - } - break; - case MAGICIAN: - case DRUID: - case PALADIN: - case CLERIC: - case WIZARD: - case NECROMANCER: - case SHADOWKNIGHT: - case RANGER: - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_SlowIndex] = castChance; - - //Debuff - switch(botClass) - { - case ENCHANTER: - case SHAMAN: - case MAGICIAN: - case DRUID: - case NECROMANCER: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 25; - break; - case BotStanceEfficient: - case BotStanceAggressive: - castChance = 15; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - break; - case BEASTLORD: - case RANGER: - case SHADOWKNIGHT: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceReactive: - castChance = 15; - break; - case BotStanceEfficient: - case BotStanceAggressive: - castChance = 10; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - break; - case BARD: - switch(botStance) - { - case BotStanceBalanced: - case BotStanceEfficient: - castChance = 25; - break; - case BotStanceReactive: - case BotStanceAggressive: - castChance = 50; - break; - case BotStanceBurn: - case BotStanceBurnAE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - break; - case CLERIC: - case PALADIN: - case WIZARD: - case WARRIOR: - case BERSERKER: - case MONK: - case ROGUE: - castChance = 0; - break; - default: - castChance = 0; - break; - } - _spellCastingChances[botStance][SpellType_DebuffIndex] = castChance; - - //Cure - castChance = 0; - _spellCastingChances[botStance][SpellType_CureIndex] = castChance; -} - -uint8 Bot::GetChanceToCastBySpellType(uint32 spellType) { - int index = 0; - int botStance = (int)GetBotStance(); - uint8 chance = 0; - - if(GetBotStance() >= MaxStances) - return 0; - + }; + + uint8 spell_type_index = MaxSpellTypes; switch (spellType) { - case SpellType_Nuke: { - index = SpellType_NukeIndex; - break; - } - case SpellType_Heal: { - index = SpellType_HealIndex; - break; - } - case SpellType_Root: { - index = SpellType_RootIndex; - break; - } - case SpellType_Buff: { - index = SpellType_BuffIndex; - break; - } - case SpellType_Escape: { - index = SpellType_EscapeIndex; - break; - } - case SpellType_Pet: { - index = SpellType_PetIndex; - break; - } - case SpellType_Lifetap: { - index = SpellType_LifetapIndex; - break; - } - case SpellType_Snare: { - index = SpellType_SnareIndex; - break; - } - case SpellType_DOT: { - index = SpellType_DOTIndex; - break; - } - case SpellType_Dispel: { - index = SpellType_DispelIndex; - break; - } - case SpellType_InCombatBuff: { - index = SpellType_InCombatBuffIndex; - break; - } - case SpellType_Mez: { - index = SpellType_MezIndex; - break; - } - case SpellType_Charm: { - index = SpellType_CharmIndex; - break; - } - case SpellType_Slow: { - index = SpellType_SlowIndex; - break; - } - case SpellType_Debuff: { - index = SpellType_DebuffIndex; - break; - } - case SpellType_Cure: { - index = SpellType_CureIndex; - break; - } + case SpellType_Nuke: + spell_type_index = SpellType_NukeIndex; + break; + case SpellType_Heal: + spell_type_index = SpellType_HealIndex; + break; + case SpellType_Root: + spell_type_index = SpellType_RootIndex; + break; + case SpellType_Buff: + spell_type_index = SpellType_BuffIndex; + break; + case SpellType_Escape: + spell_type_index = SpellType_EscapeIndex; + break; + case SpellType_Pet: + spell_type_index = SpellType_PetIndex; + break; + case SpellType_Lifetap: + spell_type_index = SpellType_LifetapIndex; + break; + case SpellType_Snare: + spell_type_index = SpellType_SnareIndex; + break; + case SpellType_DOT: + spell_type_index = SpellType_DOTIndex; + break; + case SpellType_Dispel: + spell_type_index = SpellType_DispelIndex; + break; + case SpellType_InCombatBuff: + spell_type_index = SpellType_InCombatBuffIndex; + break; + case SpellType_Mez: + spell_type_index = SpellType_MezIndex; + break; + case SpellType_Charm: + spell_type_index = SpellType_CharmIndex; + break; + case SpellType_Slow: + spell_type_index = SpellType_SlowIndex; + break; + case SpellType_Debuff: + spell_type_index = SpellType_DebuffIndex; + break; + case SpellType_Cure: + spell_type_index = SpellType_CureIndex; + break; + case SpellType_Resurrect: + spell_type_index = SpellType_ResurrectIndex; + break; + case SpellType_HateRedux: + spell_type_index = SpellType_HateReduxIndex; + break; + case SpellType_InCombatBuffSong: + spell_type_index = SpellType_InCombatBuffSongIndex; + break; + case SpellType_OutOfCombatBuffSong: + spell_type_index = SpellType_OutOfCombatBuffSongIndex; + break; + default: + spell_type_index = MaxSpellTypes; + break; } - - if(index >= MaxSpellTypes) + if (spell_type_index >= MaxSpellTypes) return 0; - chance = _spellCastingChances[botStance][index]; + uint8 class_index = GetClass(); + if (class_index > BERSERKER || class_index < WARRIOR) + return 0; + --class_index; - return chance; + uint8 stance_index = (uint8)GetBotStance(); + if (stance_index >= MaxStances) + return 0; + + uint8 type_index = nHS; + if (HasGroup()) { + if (IsGroupPrimaryHealer()) + type_index |= pH; + if (IsGroupPrimarySlower()) + type_index |= pS; + } + + return spell_casting_chances[spell_type_index][class_index][stance_index][type_index]; } #endif diff --git a/zone/groups.cpp b/zone/groups.cpp index 2162e735e..37f1f9da1 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -333,13 +333,6 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte database.SetGroupID(NewMemberName, GetID(), owner->CharacterID(), true); } } -#ifdef BOTS - for (i = 0;i < MAX_GROUP_MEMBERS; i++) { - if (members[i] != nullptr && members[i]->IsBot()) { - members[i]->CastToBot()->CalcChanceToCast(); - } - } -#endif //BOTS } else { @@ -496,16 +489,11 @@ void Group::MemberZoned(Mob* removemob) { SetLeader(nullptr); for (i = 0; i < MAX_GROUP_MEMBERS; i++) { - if (members[i] == removemob) { - members[i] = nullptr; - //should NOT clear the name, it is used for world communication. - break; - } -#ifdef BOTS - if (members[i] != nullptr && members[i]->IsBot()) { - members[i]->CastToBot()->CalcChanceToCast(); + if (members[i] == removemob) { + members[i] = nullptr; + //should NOT clear the name, it is used for world communication. + break; } -#endif //BOTS } if(removemob->IsClient() && HasRole(removemob, RoleAssist)) @@ -661,11 +649,6 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) if(members[i]->IsClient()) members[i]->CastToClient()->QueuePacket(outapp); } -#ifdef BOTS - if (members[i] != nullptr && members[i]->IsBot()) { - members[i]->CastToBot()->CalcChanceToCast(); - } -#endif //BOTS } if (!ignoresender) From f851b1a3b4d92af68d247a6071d30da3a30ac832 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 20 Feb 2017 21:47:47 -0500 Subject: [PATCH 566/693] Added combat-prep song buffing note [skip ci] --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 23700766c..b2e74a626 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 02/20/2017 == Uleat: Reworked bard bot spell twisting and updated their spell (song) list +Uleat: Added ability to shift to pre-combat song buffing by selecting a non-pet npc target, eliminating the need to mix all bard buff songs together == 01/31/2017 == Uleat: Modifed bot movement behavior in an attempt to 'normalize' it. This is a hack fix and will be revisited at some point. (Probably just need a follow function rather than use movement, when the leader of the follow chain is moving.) From 8f67df1f4feaf0bdf329ab11d242dde9054ac2c5 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 20 Feb 2017 22:50:43 -0500 Subject: [PATCH 567/693] Oops! (Won't affect any changes up to this point) [skip ci] --- utils/sql/git/bots/bots_db_update_manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 44e68f037..8418dd83b 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -8,7 +8,7 @@ 9007|2016_06_23_bots_camel_case_name_rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AllowCamelCaseNames'|empty| 9008|2016_06_28_bots_inventory_charges_update.sql|SELECT * FROM `information_schema`.`COLUMNS` isc WHERE isc.`TABLE_SCHEMA` = DATABASE() AND isc.`TABLE_NAME` = 'bot_inventories' AND isc.`COLUMN_NAME` = 'inst_charges' AND isc.`DATA_TYPE` = 'tinyint'|not_empty| 9009|2017_02_15_bots_bot_spells_entries.sql|SELECT `id` FROM `npc_spells_entries` WHERE `npc_spells_id` >= 701 AND `npc_spells_id` <= 712|not_empty| -9010|2017_02_20_bots_bard_spell_update.sql|SELECT * FROM `bot_spells_entries` WHERE (`type` & 0xFFFF0000) = 0xFFFF0000|empty| +9010|2017_02_20_bots_bard_spell_update.sql|SELECT * FROM `bot_spells_entries` WHERE `npc_spells_id` = 711 AND (`type` & 0xFFFF0000) = 0xFFFF0000|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From a8846395349a31d5ee29c7fc98daf2f3c86081fa Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 21 Feb 2017 03:55:21 -0600 Subject: [PATCH 568/693] Reduce the initial telnet console prompt timer --- changelog.txt | 3 +++ world/console.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 390c45cd9..84b7dc67b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 2/19/2017 == +Akkadius: Added a fix for limiting the amount of items sold in a stack when the resulting return coin is higher than the supporting struct for returning coin + == 01/31/2017 == Uleat: Modifed bot movement behavior in an attempt to 'normalize' it. This is a hack fix and will be revisited at some point. (Probably just need a follow function rather than use movement, when the leader of the follow chain is moving.) diff --git a/world/console.cpp b/world/console.cpp index 5f1598654..b8a0b419a 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -68,7 +68,7 @@ void CatchSignal(int sig_num); Console::Console(EmuTCPConnection* itcpc) : WorldTCPConnection(), timeout_timer(RuleI(Console, SessionTimeOut)), - prompt_timer(1000) + prompt_timer(1) { tcpc = itcpc; tcpc->SetEcho(true); From 056725b9bd60e400aeb168a2ec8d71dcfc48ec1b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 21 Feb 2017 13:38:00 -0500 Subject: [PATCH 569/693] Make timer for aggro meter not a magic number you can edit AGGRO_METER_UPDATE_MS in common/features.h if you want to see if a different number would work better --- common/features.h | 3 +++ zone/client.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/common/features.h b/common/features.h index 27390e745..4140014d8 100644 --- a/common/features.h +++ b/common/features.h @@ -235,6 +235,9 @@ enum { //some random constants #define ZONE_CONTROLLER_NPC_ID 10 +// Timer to update aggrometer +#define AGGRO_METER_UPDATE_MS 1000 + //Some hard coded statuses from commands and other places: enum { minStatusToBeGM = 40, diff --git a/zone/client.cpp b/zone/client.cpp index 5f3d3ac81..842563d88 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -154,7 +154,7 @@ Client::Client(EQStreamInterface* ieqs) afk_toggle_timer(250), helm_toggle_timer(250), light_update_timer(600), - aggro_meter_timer(1000), + aggro_meter_timer(AGGRO_METER_UPDATE_MS), m_Proximity(FLT_MAX, FLT_MAX, FLT_MAX), //arbitrary large number m_ZoneSummonLocation(-2.0f,-2.0f,-2.0f), m_AutoAttackPosition(0.0f, 0.0f, 0.0f, 0.0f), From 7db82a3b142dd29cde1598230e207bc3f7bcd3ab Mon Sep 17 00:00:00 2001 From: Drajor Date: Wed, 22 Feb 2017 06:26:49 +1000 Subject: [PATCH 570/693] Fixes issue with calculating the value of items being sold. The loop was starting at 0 instead of 1. --- zone/client_packet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 67e085d0d..1c5e4ebfd 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -12447,7 +12447,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) uint32 i; if (RuleB(Merchant, UsePriceMod)) { - for (i = 0; i < cost_quantity; i++) { + for (i = 1; i <= cost_quantity; i++) { price = (uint32)((item->Price * i)*(RuleR(Merchant, BuyCostMod))*Client::CalcPriceMod(vendor, true) + 0.5); // need to round up, because client does it automatically when displaying price if (price > 4000000000) { cost_quantity = i; @@ -12457,7 +12457,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) } } else { - for (i = 0; i < cost_quantity; i++) { + for (i = 1; i <= cost_quantity; i++) { price = (uint32)((item->Price * i)*(RuleR(Merchant, BuyCostMod)) + 0.5); // need to round up, because client does it automatically when displaying price if (price > 4000000000) { cost_quantity = i; From 9a157fa02870f671d02a4e3e392a95e4b0a04a4f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 21 Feb 2017 17:54:25 -0500 Subject: [PATCH 571/693] Turn aggro meter off by default until more tested Reports of it being too spammy and causing DCs --- common/ruletypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index a0bf01496..20430735a 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -114,7 +114,7 @@ RULE_BOOL(Character, CheckCursorEmptyWhenLooting, true) // If true, a player can RULE_BOOL(Character, MaintainIntoxicationAcrossZones, true) // If true, alcohol effects are maintained across zoning and logging out/in. RULE_BOOL(Character, EnableDiscoveredItems, true) // If enabled, it enables EVENT_DISCOVER_ITEM and also saves character names and timestamps for the first time an item is discovered. RULE_BOOL(Character, EnableXTargetting, true) // Enable Extended Targetting Window, for users with UF and later clients. -RULE_BOOL(Character, EnableAggroMeter, true) // Enable Aggro Meter, for users with RoF and later clients. +RULE_BOOL(Character, EnableAggroMeter, false) // Enable Aggro Meter, for users with RoF and later clients. RULE_BOOL(Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap RULE_INT(Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update RULE_INT(Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well. From b423ad0d80189fd168861c529de0c2c05f1f0413 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 21 Feb 2017 18:02:58 -0500 Subject: [PATCH 572/693] Crash fix --- zone/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 842563d88..40a919d2b 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7430,7 +7430,7 @@ void Client::ProcessXTargetAutoHaters() auto &haters = GetXTargetAutoMgr()->get_list(); for (auto &e : haters) { auto *mob = entity_list.GetMob(e.spawn_id); - if (!IsXTarget(mob)) { + if (mob && !IsXTarget(mob)) { auto slot = empty_slots.front(); empty_slots.pop(); XTargets[slot].dirty = true; From 9adfe5b9ff3f50afe27b294e000067adfbb1ba7e Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 21 Feb 2017 20:40:04 -0500 Subject: [PATCH 573/693] Fix for bot wizard repeating familiar casting when pet is dead and buff is active --- zone/bot.cpp | 19 ++++++++++++++++--- zone/botspellsai.cpp | 31 ++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 240530237..5da128aa6 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1634,6 +1634,19 @@ bool Bot::LoadPet() auto bot_owner = GetBotOwner(); if (!bot_owner) return false; + + if (GetClass() == WIZARD) { + auto buffs_max = GetMaxBuffSlots(); + auto my_buffs = GetBuffs(); + if (buffs_max && my_buffs) { + for (int index = 0; index < buffs_max; ++index) { + if (IsEffectInSpell(my_buffs[index].spellid, SE_Familiar)) { + MakePet(my_buffs[index].spellid, spells[my_buffs[index].spellid].teleport_zone); + return true; + } + } + } + } std::string error_message; @@ -1649,7 +1662,7 @@ bool Bot::LoadPet() if (!botdb.LoadPetSpellID(GetBotID(), saved_pet_spell_id)) { bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetSpellID(), GetCleanName()); } - if (!saved_pet_spell_id || saved_pet_spell_id > SPDAT_RECORDS) { + if (!IsValidSpell(saved_pet_spell_id)) { bot_owner->Message(13, "Invalid spell id for %s's pet", GetCleanName()); DeletePet(); return false; @@ -1693,11 +1706,11 @@ bool Bot::LoadPet() bool Bot::SavePet() { - if (!GetPet() /*|| dead*/) + if (!GetPet() || GetPet()->IsFamiliar() /*|| dead*/) return true; NPC *pet_inst = GetPet()->CastToNPC(); - if (pet_inst->IsFamiliar() || !pet_inst->GetPetSpellID() || pet_inst->GetPetSpellID() > SPDAT_RECORDS) + if (!pet_inst->GetPetSpellID() || !IsValidSpell(pet_inst->GetPetSpellID())) return false; auto bot_owner = GetBotOwner(); diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 74870fed3..f3b4ec83a 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -557,10 +557,35 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { case SpellType_Pet: { //keep mobs from recasting pets when they have them. if (!IsPet() && !GetPetID() && !IsBotCharmer()) { - if(botClass == MAGICIAN) - botSpell = GetBestBotMagicianPetSpell(this); - else + if (botClass == WIZARD) { + auto buffs_max = GetMaxBuffSlots(); + auto my_buffs = GetBuffs(); + int familiar_buff_slot = -1; + if (buffs_max && my_buffs) { + for (int index = 0; index < buffs_max; ++index) { + if (IsEffectInSpell(my_buffs[index].spellid, SE_Familiar)) { + MakePet(my_buffs[index].spellid, spells[my_buffs[index].spellid].teleport_zone); + familiar_buff_slot = index; + break; + } + } + } + if (GetPetID()) + break; + + if (familiar_buff_slot >= 0) { + BuffFadeBySlot(familiar_buff_slot); + break; + } + botSpell = GetFirstBotSpellBySpellType(this, SpellType_Pet); + } + else if (botClass == MAGICIAN) { + botSpell = GetBestBotMagicianPetSpell(this); + } + else { + botSpell = GetFirstBotSpellBySpellType(this, SpellType_Pet); + } if(botSpell.SpellId == 0) break; From e0988369349c5984f1e6ca16942dea91630b4cbd Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 22 Feb 2017 22:49:23 -0600 Subject: [PATCH 574/693] Upload table lists that PEQ uses in daily database dump --- utils/sql/data_tables.txt | 5 ++ utils/sql/system_tables.txt | 100 ++++++++++++++++++++++++++++++++++++ utils/sql/user_tables.txt | 93 +++++++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 utils/sql/data_tables.txt create mode 100644 utils/sql/system_tables.txt create mode 100644 utils/sql/user_tables.txt diff --git a/utils/sql/data_tables.txt b/utils/sql/data_tables.txt new file mode 100644 index 000000000..76938a8d2 --- /dev/null +++ b/utils/sql/data_tables.txt @@ -0,0 +1,5 @@ +command_settings +launcher +rule_sets +rule_values +variables \ No newline at end of file diff --git a/utils/sql/system_tables.txt b/utils/sql/system_tables.txt new file mode 100644 index 000000000..ba1489b65 --- /dev/null +++ b/utils/sql/system_tables.txt @@ -0,0 +1,100 @@ +aa_ability +aa_actions +aa_effects +aa_required_level_cost +aa_ranks +aa_rank_effects +aa_rank_prereqs +activities +adventure_template +adventure_template_entry +adventure_template_entry_flavor +altadv_vars +alternate_currency +base_data +blocked_spells +books +char_create_combinations +char_create_point_allocations +class_skill +damageshieldtypes +doors +faction_list +faction_list_mod +fear_hints +fishing +forage +goallists +graveyard +grid +grid_entries +ground_spawns +horses +instance_list +items +ldon_trap_templates +ldon_trap_entries +level_exp_mods +lootdrop +lootdrop_entries +loottable +loottable_entries +merc_armorinfo +merc_weaponinfo +merc_stats +merc_merchant_entries +merc_merchant_template_entries +merc_merchant_templates +merc_stance_entries +merc_templates +merc_npc_types +merc_name_types +merc_subtypes +merc_types +merc_spell_list_entries +merc_spell_lists +merc_buffs +mercs +merc_inventory +merchantlist +npc_emotes +npc_faction +npc_faction_entries +npc_spells +npc_spells_entries +npc_spells_effects +npc_spells_effects_entries +npc_types +npc_types_metadata +npc_types_tint +object +pets +pets_equipmentset +pets_equipmentset_entries +proximities +races +saylink +skill_caps +spawn2 +spawn_conditions +spawn_condition_values +spawn_events +spawnentry +spawngroup +spells_new +start_zones +starting_items +tasks +tasksets +titles +tradeskill_recipe +tradeskill_recipe_entries +traps +tribute_levels +tributes +veteran_reward_templates +zone +zone_points +zone_server +zone_state_dump +zoneserver_auth \ No newline at end of file diff --git a/utils/sql/user_tables.txt b/utils/sql/user_tables.txt new file mode 100644 index 000000000..a2fa028e7 --- /dev/null +++ b/utils/sql/user_tables.txt @@ -0,0 +1,93 @@ +aa_timers +account +account_flags +account_ip +account_rewards +adventure_details +adventure_members +adventure_stats +Banned_IPs +bugs +buyer +char_recipe_list +character_data +character_currency +character_alternate_abilities +character_bind +character_corpses +character_corpse_items +character_languages +character_lookup +character_skills +character_spells +character_memmed_spells +character_disciplines +character_material +character_tribute +character_bandolier +character_potionbelt +character_inspect_messages +character_leadership_abilities +character_activities +character_alt_currency +character_backup +character_buffs +character_enabledtasks +character_pet_buffs +character_pet_info +character_pet_inventory +character_tasks +chatchannels +completed_tasks +discovered_items +eventlog +faction_values +friends +gm_ips +group_id +group_leaders +guilds +guild_bank +guild_ranks +guild_relations +guild_members +hackers +instance_list_player +inventory +item_tick +keyring +launcher_zones +lfguild +mail +merchantlist_temp +name_filter +object_contents +petitions +player_titlesets +qs_player_move_record +qs_player_move_record_entries +qs_player_npc_kill_record +qs_player_npc_kill_record_entries +qs_player_speech +qs_player_trade_record +qs_player_trade_record_entries +qs_merchant_transaction_record +qs_merchant_transaction_record_entries +qs_player_delete_record +qs_player_delete_record_entries +qs_player_handin_record +qs_player_handin_record_entries +qs_player_aa_rate_hourly +qs_player_events +quest_globals +raid_details +raid_leaders +raid_members +reports +respawn_times +sharedbank +spell_globals +timers +trader +trader_audit +zone_flags \ No newline at end of file From 602381ebecd8ee9602195db1e5f503459488aa5b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 23 Feb 2017 12:27:44 -0500 Subject: [PATCH 575/693] copy paste fail --- zone/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 40a919d2b..2d7806821 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8904,7 +8904,7 @@ void Client::ProcessAggroMeter() if (m_aggrometer.set_pct(AggroMeter::AT_Group3, 0)) add_entry(AggroMeter::AT_Group3); if (m_aggrometer.set_pct(AggroMeter::AT_Group4, 0)) - add_entry(AggroMeter::AT_Group5); + add_entry(AggroMeter::AT_Group4); if (m_aggrometer.set_pct(AggroMeter::AT_Group5, 0)) add_entry(AggroMeter::AT_Group5); } From 4e8a03f7b4130ea81430eead1b2dadee2e7ea4a7 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 23 Feb 2017 19:16:36 -0500 Subject: [PATCH 576/693] Migrated bot spell casting chance data to the database --- changelog.txt | 15 + common/version.h | 2 +- .../sql/git/bots/bots_db_update_manifest.txt | 1 + .../2017_02_23_bots_spell_casting_chances.sql | 11257 ++++++++++++++++ zone/bot.h | 3 + zone/bot_database.cpp | 57 + zone/bot_database.h | 2 + zone/botspellsai.cpp | 2947 +--- zone/net.cpp | 4 + 9 files changed, 11341 insertions(+), 2947 deletions(-) create mode 100644 utils/sql/git/bots/required/2017_02_23_bots_spell_casting_chances.sql diff --git a/changelog.txt b/changelog.txt index 865c82173..53d48a83d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,20 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 02/23/2017 == +Uleat: Moved bot spell casting chance values into database - this will allow admins to tailor their bots without having to rebuild server code + - Each entry uses a 4-dimensional identifier: [spell type index][class index][stance index][conditional index] + - [spell type index] is not the SpellType_## bit value..use SpellType_##Index instead + - [class index] values of 0-15 are valid and determined by subtracting 1 from the actual class value + - [stance index] is a direct correlation (0-6) + - the [conditional index] is currently predicated on 2 compounded boolean states: + - not primary healer/not primary slower: 0 + - primary healer/not primary slower: 1 + - not primary healer/ primary slower: 2 + - primary healer/primary slower: 3 + - Valid `value` entries are 0-100..though, the field accepts up to 255... Anything above 100 is clamped to 100 upon loading, however + - Not all conditions are currently coded and changing a field may not produce any results + - The 'default' database values will be changed and tweaked as bot spell code modifications occur + == 02/20/2017 == Uleat: Reworked bard bot spell twisting and updated their spell (song) list Uleat: Added ability to shift to pre-combat song buffing by selecting a non-pet npc target, eliminating the need to mix all bard buff songs together diff --git a/common/version.h b/common/version.h index 40e50a0ac..b2261505f 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9105 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9010 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9011 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 8418dd83b..810d767cc 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -9,6 +9,7 @@ 9008|2016_06_28_bots_inventory_charges_update.sql|SELECT * FROM `information_schema`.`COLUMNS` isc WHERE isc.`TABLE_SCHEMA` = DATABASE() AND isc.`TABLE_NAME` = 'bot_inventories' AND isc.`COLUMN_NAME` = 'inst_charges' AND isc.`DATA_TYPE` = 'tinyint'|not_empty| 9009|2017_02_15_bots_bot_spells_entries.sql|SELECT `id` FROM `npc_spells_entries` WHERE `npc_spells_id` >= 701 AND `npc_spells_id` <= 712|not_empty| 9010|2017_02_20_bots_bard_spell_update.sql|SELECT * FROM `bot_spells_entries` WHERE `npc_spells_id` = 711 AND (`type` & 0xFFFF0000) = 0xFFFF0000|empty| +9011|2017_02_23_bots_spell_casting_chances.sql|SHOW TABLES LIKE 'bot_spell_casting_chances'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2017_02_23_bots_spell_casting_chances.sql b/utils/sql/git/bots/required/2017_02_23_bots_spell_casting_chances.sql new file mode 100644 index 000000000..951824e13 --- /dev/null +++ b/utils/sql/git/bots/required/2017_02_23_bots_spell_casting_chances.sql @@ -0,0 +1,11257 @@ +DROP TABLE IF EXISTS `bot_spell_casting_chances`; + +CREATE TABLE `bot_spell_casting_chances` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `spell_type_index` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `class_index` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `stance_index` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `conditional_index` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + INDEX `Index 2` (`spell_type_index`, `class_index`, `stance_index`, `conditional_index`) +) +ENGINE=InnoDB +; + +-- Initial migration entries based on coded values + +INSERT INTO `bot_spell_casting_chances`(`spell_type_index`, `class_index`, `stance_index`, `conditional_index`, `value`) VALUES +-- SpellType_NukeIndex + +('0', '0', '0', '0', '0'), +('0', '0', '0', '1', '0'), +('0', '0', '0', '2', '0'), +('0', '0', '0', '3', '0'), + +('0', '0', '1', '0', '0'), +('0', '0', '1', '1', '0'), +('0', '0', '1', '2', '0'), +('0', '0', '1', '3', '0'), + +('0', '0', '2', '0', '0'), +('0', '0', '2', '1', '0'), +('0', '0', '2', '2', '0'), +('0', '0', '2', '3', '0'), + +('0', '0', '3', '0', '0'), +('0', '0', '3', '1', '0'), +('0', '0', '3', '2', '0'), +('0', '0', '3', '3', '0'), + +('0', '0', '4', '0', '0'), +('0', '0', '4', '1', '0'), +('0', '0', '4', '2', '0'), +('0', '0', '4', '3', '0'), + +('0', '0', '5', '0', '0'), +('0', '0', '5', '1', '0'), +('0', '0', '5', '2', '0'), +('0', '0', '5', '3', '0'), + +('0', '0', '6', '0', '0'), +('0', '0', '6', '1', '0'), +('0', '0', '6', '2', '0'), +('0', '0', '6', '3', '0'), + +('0', '1', '0', '0', '0'), +('0', '1', '0', '1', '0'), +('0', '1', '0', '2', '0'), +('0', '1', '0', '3', '0'), + +('0', '1', '1', '0', '25'), +('0', '1', '1', '1', '15'), +('0', '1', '1', '2', '25'), +('0', '1', '1', '3', '15'), + +('0', '1', '2', '0', '15'), +('0', '1', '2', '1', '0'), +('0', '1', '2', '2', '15'), +('0', '1', '2', '3', '0'), + +('0', '1', '3', '0', '25'), +('0', '1', '3', '1', '15'), +('0', '1', '3', '2', '25'), +('0', '1', '3', '3', '15'), + +('0', '1', '4', '0', '50'), +('0', '1', '4', '1', '15'), +('0', '1', '4', '2', '50'), +('0', '1', '4', '3', '15'), + +('0', '1', '5', '0', '50'), +('0', '1', '5', '1', '25'), +('0', '1', '5', '2', '50'), +('0', '1', '5', '3', '25'), + +('0', '1', '6', '0', '50'), +('0', '1', '6', '1', '25'), +('0', '1', '6', '2', '50'), +('0', '1', '6', '3', '25'), + +('0', '2', '0', '0', '0'), +('0', '2', '0', '1', '0'), +('0', '2', '0', '2', '0'), +('0', '2', '0', '3', '0'), + +('0', '2', '1', '0', '25'), +('0', '2', '1', '1', '15'), +('0', '2', '1', '2', '25'), +('0', '2', '1', '3', '15'), + +('0', '2', '2', '0', '15'), +('0', '2', '2', '1', '0'), +('0', '2', '2', '2', '15'), +('0', '2', '2', '3', '0'), + +('0', '2', '3', '0', '25'), +('0', '2', '3', '1', '15'), +('0', '2', '3', '2', '25'), +('0', '2', '3', '3', '15'), + +('0', '2', '4', '0', '50'), +('0', '2', '4', '1', '15'), +('0', '2', '4', '2', '50'), +('0', '2', '4', '3', '15'), + +('0', '2', '5', '0', '50'), +('0', '2', '5', '1', '25'), +('0', '2', '5', '2', '50'), +('0', '2', '5', '3', '25'), + +('0', '2', '6', '0', '50'), +('0', '2', '6', '1', '25'), +('0', '2', '6', '2', '50'), +('0', '2', '6', '3', '25'), + +('0', '3', '0', '0', '0'), +('0', '3', '0', '1', '0'), +('0', '3', '0', '2', '0'), +('0', '3', '0', '3', '0'), + +('0', '3', '1', '0', '15'), +('0', '3', '1', '1', '15'), +('0', '3', '1', '2', '15'), +('0', '3', '1', '3', '15'), + +('0', '3', '2', '0', '5'), +('0', '3', '2', '1', '5'), +('0', '3', '2', '2', '5'), +('0', '3', '2', '3', '5'), + +('0', '3', '3', '0', '15'), +('0', '3', '3', '1', '15'), +('0', '3', '3', '2', '15'), +('0', '3', '3', '3', '15'), + +('0', '3', '4', '0', '15'), +('0', '3', '4', '1', '15'), +('0', '3', '4', '2', '15'), +('0', '3', '4', '3', '15'), + +('0', '3', '5', '0', '50'), +('0', '3', '5', '1', '50'), +('0', '3', '5', '2', '50'), +('0', '3', '5', '3', '50'), + +('0', '3', '6', '0', '50'), +('0', '3', '6', '1', '50'), +('0', '3', '6', '2', '50'), +('0', '3', '6', '3', '50'), + +('0', '4', '0', '0', '0'), +('0', '4', '0', '1', '0'), +('0', '4', '0', '2', '0'), +('0', '4', '0', '3', '0'), + +('0', '4', '1', '0', '15'), +('0', '4', '1', '1', '15'), +('0', '4', '1', '2', '15'), +('0', '4', '1', '3', '15'), + +('0', '4', '2', '0', '5'), +('0', '4', '2', '1', '5'), +('0', '4', '2', '2', '5'), +('0', '4', '2', '3', '5'), + +('0', '4', '3', '0', '15'), +('0', '4', '3', '1', '15'), +('0', '4', '3', '2', '15'), +('0', '4', '3', '3', '15'), + +('0', '4', '4', '0', '15'), +('0', '4', '4', '1', '15'), +('0', '4', '4', '2', '15'), +('0', '4', '4', '3', '15'), + +('0', '4', '5', '0', '50'), +('0', '4', '5', '1', '50'), +('0', '4', '5', '2', '50'), +('0', '4', '5', '3', '50'), + +('0', '4', '6', '0', '50'), +('0', '4', '6', '1', '50'), +('0', '4', '6', '2', '50'), +('0', '4', '6', '3', '50'), + +('0', '5', '0', '0', '0'), +('0', '5', '0', '1', '0'), +('0', '5', '0', '2', '0'), +('0', '5', '0', '3', '0'), + +('0', '5', '1', '0', '25'), +('0', '5', '1', '1', '15'), +('0', '5', '1', '2', '25'), +('0', '5', '1', '3', '15'), + +('0', '5', '2', '0', '15'), +('0', '5', '2', '1', '0'), +('0', '5', '2', '2', '15'), +('0', '5', '2', '3', '0'), + +('0', '5', '3', '0', '25'), +('0', '5', '3', '1', '15'), +('0', '5', '3', '2', '25'), +('0', '5', '3', '3', '15'), + +('0', '5', '4', '0', '50'), +('0', '5', '4', '1', '15'), +('0', '5', '4', '2', '50'), +('0', '5', '4', '3', '15'), + +('0', '5', '5', '0', '50'), +('0', '5', '5', '1', '25'), +('0', '5', '5', '2', '50'), +('0', '5', '5', '3', '25'), + +('0', '5', '6', '0', '50'), +('0', '5', '6', '1', '25'), +('0', '5', '6', '2', '50'), +('0', '5', '6', '3', '25'), + +('0', '6', '0', '0', '0'), +('0', '6', '0', '1', '0'), +('0', '6', '0', '2', '0'), +('0', '6', '0', '3', '0'), + +('0', '6', '1', '0', '0'), +('0', '6', '1', '1', '0'), +('0', '6', '1', '2', '0'), +('0', '6', '1', '3', '0'), + +('0', '6', '2', '0', '0'), +('0', '6', '2', '1', '0'), +('0', '6', '2', '2', '0'), +('0', '6', '2', '3', '0'), + +('0', '6', '3', '0', '0'), +('0', '6', '3', '1', '0'), +('0', '6', '3', '2', '0'), +('0', '6', '3', '3', '0'), + +('0', '6', '4', '0', '0'), +('0', '6', '4', '1', '0'), +('0', '6', '4', '2', '0'), +('0', '6', '4', '3', '0'), + +('0', '6', '5', '0', '0'), +('0', '6', '5', '1', '0'), +('0', '6', '5', '2', '0'), +('0', '6', '5', '3', '0'), + +('0', '6', '6', '0', '0'), +('0', '6', '6', '1', '0'), +('0', '6', '6', '2', '0'), +('0', '6', '6', '3', '0'), + +('0', '7', '0', '0', '0'), +('0', '7', '0', '1', '0'), +('0', '7', '0', '2', '0'), +('0', '7', '0', '3', '0'), + +('0', '7', '1', '0', '50'), +('0', '7', '1', '1', '50'), +('0', '7', '1', '2', '50'), +('0', '7', '1', '3', '50'), + +('0', '7', '2', '0', '25'), +('0', '7', '2', '1', '25'), +('0', '7', '2', '2', '25'), +('0', '7', '2', '3', '25'), + +('0', '7', '3', '0', '50'), +('0', '7', '3', '1', '50'), +('0', '7', '3', '2', '50'), +('0', '7', '3', '3', '50'), + +('0', '7', '4', '0', '50'), +('0', '7', '4', '1', '50'), +('0', '7', '4', '2', '50'), +('0', '7', '4', '3', '50'), + +('0', '7', '5', '0', '100'), +('0', '7', '5', '1', '100'), +('0', '7', '5', '2', '100'), +('0', '7', '5', '3', '100'), + +('0', '7', '6', '0', '100'), +('0', '7', '6', '1', '100'), +('0', '7', '6', '2', '100'), +('0', '7', '6', '3', '100'), + +('0', '8', '0', '0', '0'), +('0', '8', '0', '1', '0'), +('0', '8', '0', '2', '0'), +('0', '8', '0', '3', '0'), + +('0', '8', '1', '0', '0'), +('0', '8', '1', '1', '0'), +('0', '8', '1', '2', '0'), +('0', '8', '1', '3', '0'), + +('0', '8', '2', '0', '0'), +('0', '8', '2', '1', '0'), +('0', '8', '2', '2', '0'), +('0', '8', '2', '3', '0'), + +('0', '8', '3', '0', '0'), +('0', '8', '3', '1', '0'), +('0', '8', '3', '2', '0'), +('0', '8', '3', '3', '0'), + +('0', '8', '4', '0', '0'), +('0', '8', '4', '1', '0'), +('0', '8', '4', '2', '0'), +('0', '8', '4', '3', '0'), + +('0', '8', '5', '0', '0'), +('0', '8', '5', '1', '0'), +('0', '8', '5', '2', '0'), +('0', '8', '5', '3', '0'), + +('0', '8', '6', '0', '0'), +('0', '8', '6', '1', '0'), +('0', '8', '6', '2', '0'), +('0', '8', '6', '3', '0'), + +('0', '9', '0', '0', '0'), +('0', '9', '0', '1', '0'), +('0', '9', '0', '2', '0'), +('0', '9', '0', '3', '0'), + +('0', '9', '1', '0', '15'), +('0', '9', '1', '1', '10'), +('0', '9', '1', '2', '5'), +('0', '9', '1', '3', '0'), + +('0', '9', '2', '0', '10'), +('0', '9', '2', '1', '5'), +('0', '9', '2', '2', '0'), +('0', '9', '2', '3', '0'), + +('0', '9', '3', '0', '15'), +('0', '9', '3', '1', '10'), +('0', '9', '3', '2', '5'), +('0', '9', '3', '3', '0'), + +('0', '9', '4', '0', '25'), +('0', '9', '4', '1', '15'), +('0', '9', '4', '2', '15'), +('0', '9', '4', '3', '5'), + +('0', '9', '5', '0', '50'), +('0', '9', '5', '1', '25'), +('0', '9', '5', '2', '25'), +('0', '9', '5', '3', '15'), + +('0', '9', '6', '0', '50'), +('0', '9', '6', '1', '25'), +('0', '9', '6', '2', '25'), +('0', '9', '6', '3', '15'), + +('0', '10', '0', '0', '0'), +('0', '10', '0', '1', '0'), +('0', '10', '0', '2', '0'), +('0', '10', '0', '3', '0'), + +('0', '10', '1', '0', '15'), +('0', '10', '1', '1', '15'), +('0', '10', '1', '2', '15'), +('0', '10', '1', '3', '15'), + +('0', '10', '2', '0', '5'), +('0', '10', '2', '1', '5'), +('0', '10', '2', '2', '5'), +('0', '10', '2', '3', '5'), + +('0', '10', '3', '0', '15'), +('0', '10', '3', '1', '15'), +('0', '10', '3', '2', '15'), +('0', '10', '3', '3', '15'), + +('0', '10', '4', '0', '15'), +('0', '10', '4', '1', '15'), +('0', '10', '4', '2', '15'), +('0', '10', '4', '3', '15'), + +('0', '10', '5', '0', '50'), +('0', '10', '5', '1', '50'), +('0', '10', '5', '2', '50'), +('0', '10', '5', '3', '50'), + +('0', '10', '6', '0', '50'), +('0', '10', '6', '1', '50'), +('0', '10', '6', '2', '50'), +('0', '10', '6', '3', '50'), + +('0', '11', '0', '0', '0'), +('0', '11', '0', '1', '0'), +('0', '11', '0', '2', '0'), +('0', '11', '0', '3', '0'), + +('0', '11', '1', '0', '75'), +('0', '11', '1', '1', '75'), +('0', '11', '1', '2', '75'), +('0', '11', '1', '3', '75'), + +('0', '11', '2', '0', '50'), +('0', '11', '2', '1', '50'), +('0', '11', '2', '2', '50'), +('0', '11', '2', '3', '50'), + +('0', '11', '3', '0', '75'), +('0', '11', '3', '1', '75'), +('0', '11', '3', '2', '75'), +('0', '11', '3', '3', '75'), + +('0', '11', '4', '0', '75'), +('0', '11', '4', '1', '75'), +('0', '11', '4', '2', '75'), +('0', '11', '4', '3', '75'), + +('0', '11', '5', '0', '100'), +('0', '11', '5', '1', '100'), +('0', '11', '5', '2', '100'), +('0', '11', '5', '3', '100'), + +('0', '11', '6', '0', '100'), +('0', '11', '6', '1', '100'), +('0', '11', '6', '2', '100'), +('0', '11', '6', '3', '100'), + +('0', '12', '0', '0', '0'), +('0', '12', '0', '1', '0'), +('0', '12', '0', '2', '0'), +('0', '12', '0', '3', '0'), + +('0', '12', '1', '0', '75'), +('0', '12', '1', '1', '75'), +('0', '12', '1', '2', '75'), +('0', '12', '1', '3', '75'), + +('0', '12', '2', '0', '50'), +('0', '12', '2', '1', '50'), +('0', '12', '2', '2', '50'), +('0', '12', '2', '3', '50'), + +('0', '12', '3', '0', '75'), +('0', '12', '3', '1', '75'), +('0', '12', '3', '2', '75'), +('0', '12', '3', '3', '75'), + +('0', '12', '4', '0', '75'), +('0', '12', '4', '1', '75'), +('0', '12', '4', '2', '75'), +('0', '12', '4', '3', '75'), + +('0', '12', '5', '0', '100'), +('0', '12', '5', '1', '100'), +('0', '12', '5', '2', '100'), +('0', '12', '5', '3', '100'), + +('0', '12', '6', '0', '100'), +('0', '12', '6', '1', '100'), +('0', '12', '6', '2', '100'), +('0', '12', '6', '3', '100'), + +('0', '13', '0', '0', '0'), +('0', '13', '0', '1', '0'), +('0', '13', '0', '2', '0'), +('0', '13', '0', '3', '0'), + +('0', '13', '1', '0', '25'), +('0', '13', '1', '1', '25'), +('0', '13', '1', '2', '15'), +('0', '13', '1', '3', '15'), + +('0', '13', '2', '0', '15'), +('0', '13', '2', '1', '15'), +('0', '13', '2', '2', '0'), +('0', '13', '2', '3', '0'), + +('0', '13', '3', '0', '25'), +('0', '13', '3', '1', '25'), +('0', '13', '3', '2', '15'), +('0', '13', '3', '3', '15'), + +('0', '13', '4', '0', '50'), +('0', '13', '4', '1', '50'), +('0', '13', '4', '2', '15'), +('0', '13', '4', '3', '15'), + +('0', '13', '5', '0', '50'), +('0', '13', '5', '1', '50'), +('0', '13', '5', '2', '25'), +('0', '13', '5', '3', '25'), + +('0', '13', '6', '0', '50'), +('0', '13', '6', '1', '50'), +('0', '13', '6', '2', '25'), +('0', '13', '6', '3', '25'), + +('0', '14', '0', '0', '0'), +('0', '14', '0', '1', '0'), +('0', '14', '0', '2', '0'), +('0', '14', '0', '3', '0'), + +('0', '14', '1', '0', '15'), +('0', '14', '1', '1', '10'), +('0', '14', '1', '2', '5'), +('0', '14', '1', '3', '0'), + +('0', '14', '2', '0', '10'), +('0', '14', '2', '1', '5'), +('0', '14', '2', '2', '0'), +('0', '14', '2', '3', '0'), + +('0', '14', '3', '0', '15'), +('0', '14', '3', '1', '10'), +('0', '14', '3', '2', '5'), +('0', '14', '3', '3', '0'), + +('0', '14', '4', '0', '25'), +('0', '14', '4', '1', '15'), +('0', '14', '4', '2', '15'), +('0', '14', '4', '3', '5'), + +('0', '14', '5', '0', '50'), +('0', '14', '5', '1', '25'), +('0', '14', '5', '2', '25'), +('0', '14', '5', '3', '15'), + +('0', '14', '6', '0', '50'), +('0', '14', '6', '1', '25'), +('0', '14', '6', '2', '25'), +('0', '14', '6', '3', '15'), + +('0', '15', '0', '0', '0'), +('0', '15', '0', '1', '0'), +('0', '15', '0', '2', '0'), +('0', '15', '0', '3', '0'), + +('0', '15', '1', '0', '0'), +('0', '15', '1', '1', '0'), +('0', '15', '1', '2', '0'), +('0', '15', '1', '3', '0'), + +('0', '15', '2', '0', '0'), +('0', '15', '2', '1', '0'), +('0', '15', '2', '2', '0'), +('0', '15', '2', '3', '0'), + +('0', '15', '3', '0', '0'), +('0', '15', '3', '1', '0'), +('0', '15', '3', '2', '0'), +('0', '15', '3', '3', '0'), + +('0', '15', '4', '0', '0'), +('0', '15', '4', '1', '0'), +('0', '15', '4', '2', '0'), +('0', '15', '4', '3', '0'), + +('0', '15', '5', '0', '0'), +('0', '15', '5', '1', '0'), +('0', '15', '5', '2', '0'), +('0', '15', '5', '3', '0'), + +('0', '15', '6', '0', '0'), +('0', '15', '6', '1', '0'), +('0', '15', '6', '2', '0'), +('0', '15', '6', '3', '0'), + +-- SpellType_HealIndex + +('1', '0', '0', '0', '0'), +('1', '0', '0', '1', '0'), +('1', '0', '0', '2', '0'), +('1', '0', '0', '3', '0'), + +('1', '0', '1', '0', '0'), +('1', '0', '1', '1', '0'), +('1', '0', '1', '2', '0'), +('1', '0', '1', '3', '0'), + +('1', '0', '2', '0', '0'), +('1', '0', '2', '1', '0'), +('1', '0', '2', '2', '0'), +('1', '0', '2', '3', '0'), + +('1', '0', '3', '0', '0'), +('1', '0', '3', '1', '0'), +('1', '0', '3', '2', '0'), +('1', '0', '3', '3', '0'), + +('1', '0', '4', '0', '0'), +('1', '0', '4', '1', '0'), +('1', '0', '4', '2', '0'), +('1', '0', '4', '3', '0'), + +('1', '0', '5', '0', '0'), +('1', '0', '5', '1', '0'), +('1', '0', '5', '2', '0'), +('1', '0', '5', '3', '0'), + +('1', '0', '6', '0', '0'), +('1', '0', '6', '1', '0'), +('1', '0', '6', '2', '0'), +('1', '0', '6', '3', '0'), + +('1', '1', '0', '0', '0'), +('1', '1', '0', '1', '0'), +('1', '1', '0', '2', '0'), +('1', '1', '0', '3', '0'), + +('1', '1', '1', '0', '100'), +('1', '1', '1', '1', '100'), +('1', '1', '1', '2', '100'), +('1', '1', '1', '3', '100'), + +('1', '1', '2', '0', '100'), +('1', '1', '2', '1', '100'), +('1', '1', '2', '2', '100'), +('1', '1', '2', '3', '100'), + +('1', '1', '3', '0', '100'), +('1', '1', '3', '1', '100'), +('1', '1', '3', '2', '100'), +('1', '1', '3', '3', '100'), + +('1', '1', '4', '0', '75'), +('1', '1', '4', '1', '75'), +('1', '1', '4', '2', '75'), +('1', '1', '4', '3', '75'), + +('1', '1', '5', '0', '50'), +('1', '1', '5', '1', '50'), +('1', '1', '5', '2', '50'), +('1', '1', '5', '3', '50'), + +('1', '1', '6', '0', '50'), +('1', '1', '6', '1', '50'), +('1', '1', '6', '2', '50'), +('1', '1', '6', '3', '50'), + +('1', '2', '0', '0', '0'), +('1', '2', '0', '1', '0'), +('1', '2', '0', '2', '0'), +('1', '2', '0', '3', '0'), + +('1', '2', '1', '0', '25'), +('1', '2', '1', '1', '100'), +('1', '2', '1', '2', '25'), +('1', '2', '1', '3', '100'), + +('1', '2', '2', '0', '15'), +('1', '2', '2', '1', '75'), +('1', '2', '2', '2', '15'), +('1', '2', '2', '3', '75'), + +('1', '2', '3', '0', '25'), +('1', '2', '3', '1', '100'), +('1', '2', '3', '2', '25'), +('1', '2', '3', '3', '100'), + +('1', '2', '4', '0', '15'), +('1', '2', '4', '1', '75'), +('1', '2', '4', '2', '15'), +('1', '2', '4', '3', '75'), + +('1', '2', '5', '0', '0'), +('1', '2', '5', '1', '50'), +('1', '2', '5', '2', '0'), +('1', '2', '5', '3', '50'), + +('1', '2', '6', '0', '0'), +('1', '2', '6', '1', '50'), +('1', '2', '6', '2', '0'), +('1', '2', '6', '3', '50'), + +('1', '3', '0', '0', '0'), +('1', '3', '0', '1', '0'), +('1', '3', '0', '2', '0'), +('1', '3', '0', '3', '0'), + +('1', '3', '1', '0', '25'), +('1', '3', '1', '1', '100'), +('1', '3', '1', '2', '25'), +('1', '3', '1', '3', '100'), + +('1', '3', '2', '0', '15'), +('1', '3', '2', '1', '75'), +('1', '3', '2', '2', '15'), +('1', '3', '2', '3', '75'), + +('1', '3', '3', '0', '25'), +('1', '3', '3', '1', '100'), +('1', '3', '3', '2', '25'), +('1', '3', '3', '3', '100'), + +('1', '3', '4', '0', '15'), +('1', '3', '4', '1', '75'), +('1', '3', '4', '2', '15'), +('1', '3', '4', '3', '75'), + +('1', '3', '5', '0', '0'), +('1', '3', '5', '1', '50'), +('1', '3', '5', '2', '0'), +('1', '3', '5', '3', '50'), + +('1', '3', '6', '0', '0'), +('1', '3', '6', '1', '50'), +('1', '3', '6', '2', '0'), +('1', '3', '6', '3', '50'), + +('1', '4', '0', '0', '0'), +('1', '4', '0', '1', '0'), +('1', '4', '0', '2', '0'), +('1', '4', '0', '3', '0'), + +('1', '4', '1', '0', '50'), +('1', '4', '1', '1', '50'), +('1', '4', '1', '2', '50'), +('1', '4', '1', '3', '50'), + +('1', '4', '2', '0', '25'), +('1', '4', '2', '1', '25'), +('1', '4', '2', '2', '25'), +('1', '4', '2', '3', '25'), + +('1', '4', '3', '0', '50'), +('1', '4', '3', '1', '50'), +('1', '4', '3', '2', '50'), +('1', '4', '3', '3', '50'), + +('1', '4', '4', '0', '25'), +('1', '4', '4', '1', '25'), +('1', '4', '4', '2', '25'), +('1', '4', '4', '3', '25'), + +('1', '4', '5', '0', '15'), +('1', '4', '5', '1', '15'), +('1', '4', '5', '2', '15'), +('1', '4', '5', '3', '15'), + +('1', '4', '6', '0', '15'), +('1', '4', '6', '1', '15'), +('1', '4', '6', '2', '15'), +('1', '4', '6', '3', '15'), + +('1', '5', '0', '0', '0'), +('1', '5', '0', '1', '0'), +('1', '5', '0', '2', '0'), +('1', '5', '0', '3', '0'), + +('1', '5', '1', '0', '25'), +('1', '5', '1', '1', '100'), +('1', '5', '1', '2', '25'), +('1', '5', '1', '3', '100'), + +('1', '5', '2', '0', '15'), +('1', '5', '2', '1', '100'), +('1', '5', '2', '2', '15'), +('1', '5', '2', '3', '100'), + +('1', '5', '3', '0', '25'), +('1', '5', '3', '1', '100'), +('1', '5', '3', '2', '25'), +('1', '5', '3', '3', '100'), + +('1', '5', '4', '0', '25'), +('1', '5', '4', '1', '75'), +('1', '5', '4', '2', '25'), +('1', '5', '4', '3', '75'), + +('1', '5', '5', '0', '10'), +('1', '5', '5', '1', '50'), +('1', '5', '5', '2', '10'), +('1', '5', '5', '3', '50'), + +('1', '5', '6', '0', '10'), +('1', '5', '6', '1', '50'), +('1', '5', '6', '2', '10'), +('1', '5', '6', '3', '50'), + +('1', '6', '0', '0', '0'), +('1', '6', '0', '1', '0'), +('1', '6', '0', '2', '0'), +('1', '6', '0', '3', '0'), + +('1', '6', '1', '0', '0'), +('1', '6', '1', '1', '0'), +('1', '6', '1', '2', '0'), +('1', '6', '1', '3', '0'), + +('1', '6', '2', '0', '0'), +('1', '6', '2', '1', '0'), +('1', '6', '2', '2', '0'), +('1', '6', '2', '3', '0'), + +('1', '6', '3', '0', '0'), +('1', '6', '3', '1', '0'), +('1', '6', '3', '2', '0'), +('1', '6', '3', '3', '0'), + +('1', '6', '4', '0', '0'), +('1', '6', '4', '1', '0'), +('1', '6', '4', '2', '0'), +('1', '6', '4', '3', '0'), + +('1', '6', '5', '0', '0'), +('1', '6', '5', '1', '0'), +('1', '6', '5', '2', '0'), +('1', '6', '5', '3', '0'), + +('1', '6', '6', '0', '0'), +('1', '6', '6', '1', '0'), +('1', '6', '6', '2', '0'), +('1', '6', '6', '3', '0'), + +('1', '7', '0', '0', '0'), +('1', '7', '0', '1', '0'), +('1', '7', '0', '2', '0'), +('1', '7', '0', '3', '0'), + +('1', '7', '1', '0', '0'), +('1', '7', '1', '1', '0'), +('1', '7', '1', '2', '0'), +('1', '7', '1', '3', '0'), + +('1', '7', '2', '0', '0'), +('1', '7', '2', '1', '0'), +('1', '7', '2', '2', '0'), +('1', '7', '2', '3', '0'), + +('1', '7', '3', '0', '0'), +('1', '7', '3', '1', '0'), +('1', '7', '3', '2', '0'), +('1', '7', '3', '3', '0'), + +('1', '7', '4', '0', '0'), +('1', '7', '4', '1', '0'), +('1', '7', '4', '2', '0'), +('1', '7', '4', '3', '0'), + +('1', '7', '5', '0', '0'), +('1', '7', '5', '1', '0'), +('1', '7', '5', '2', '0'), +('1', '7', '5', '3', '0'), + +('1', '7', '6', '0', '0'), +('1', '7', '6', '1', '0'), +('1', '7', '6', '2', '0'), +('1', '7', '6', '3', '0'), + +('1', '8', '0', '0', '0'), +('1', '8', '0', '1', '0'), +('1', '8', '0', '2', '0'), +('1', '8', '0', '3', '0'), + +('1', '8', '1', '0', '0'), +('1', '8', '1', '1', '0'), +('1', '8', '1', '2', '0'), +('1', '8', '1', '3', '0'), + +('1', '8', '2', '0', '0'), +('1', '8', '2', '1', '0'), +('1', '8', '2', '2', '0'), +('1', '8', '2', '3', '0'), + +('1', '8', '3', '0', '0'), +('1', '8', '3', '1', '0'), +('1', '8', '3', '2', '0'), +('1', '8', '3', '3', '0'), + +('1', '8', '4', '0', '0'), +('1', '8', '4', '1', '0'), +('1', '8', '4', '2', '0'), +('1', '8', '4', '3', '0'), + +('1', '8', '5', '0', '0'), +('1', '8', '5', '1', '0'), +('1', '8', '5', '2', '0'), +('1', '8', '5', '3', '0'), + +('1', '8', '6', '0', '0'), +('1', '8', '6', '1', '0'), +('1', '8', '6', '2', '0'), +('1', '8', '6', '3', '0'), + +('1', '9', '0', '0', '0'), +('1', '9', '0', '1', '0'), +('1', '9', '0', '2', '0'), +('1', '9', '0', '3', '0'), + +('1', '9', '1', '0', '25'), +('1', '9', '1', '1', '100'), +('1', '9', '1', '2', '25'), +('1', '9', '1', '3', '100'), + +('1', '9', '2', '0', '15'), +('1', '9', '2', '1', '100'), +('1', '9', '2', '2', '15'), +('1', '9', '2', '3', '100'), + +('1', '9', '3', '0', '25'), +('1', '9', '3', '1', '100'), +('1', '9', '3', '2', '25'), +('1', '9', '3', '3', '100'), + +('1', '9', '4', '0', '25'), +('1', '9', '4', '1', '75'), +('1', '9', '4', '2', '25'), +('1', '9', '4', '3', '75'), + +('1', '9', '5', '0', '10'), +('1', '9', '5', '1', '50'), +('1', '9', '5', '2', '10'), +('1', '9', '5', '3', '50'), + +('1', '9', '6', '0', '10'), +('1', '9', '6', '1', '50'), +('1', '9', '6', '2', '10'), +('1', '9', '6', '3', '50'), + +('1', '10', '0', '0', '0'), +('1', '10', '0', '1', '0'), +('1', '10', '0', '2', '0'), +('1', '10', '0', '3', '0'), + +('1', '10', '1', '0', '100'), +('1', '10', '1', '1', '100'), +('1', '10', '1', '2', '100'), +('1', '10', '1', '3', '100'), + +('1', '10', '2', '0', '50'), +('1', '10', '2', '1', '50'), +('1', '10', '2', '2', '50'), +('1', '10', '2', '3', '50'), + +('1', '10', '3', '0', '100'), +('1', '10', '3', '1', '100'), +('1', '10', '3', '2', '100'), +('1', '10', '3', '3', '100'), + +('1', '10', '4', '0', '50'), +('1', '10', '4', '1', '50'), +('1', '10', '4', '2', '50'), +('1', '10', '4', '3', '50'), + +('1', '10', '5', '0', '25'), +('1', '10', '5', '1', '25'), +('1', '10', '5', '2', '25'), +('1', '10', '5', '3', '25'), + +('1', '10', '6', '0', '25'), +('1', '10', '6', '1', '25'), +('1', '10', '6', '2', '25'), +('1', '10', '6', '3', '25'), + +('1', '11', '0', '0', '0'), +('1', '11', '0', '1', '0'), +('1', '11', '0', '2', '0'), +('1', '11', '0', '3', '0'), + +('1', '11', '1', '0', '0'), +('1', '11', '1', '1', '0'), +('1', '11', '1', '2', '0'), +('1', '11', '1', '3', '0'), + +('1', '11', '2', '0', '0'), +('1', '11', '2', '1', '0'), +('1', '11', '2', '2', '0'), +('1', '11', '2', '3', '0'), + +('1', '11', '3', '0', '0'), +('1', '11', '3', '1', '0'), +('1', '11', '3', '2', '0'), +('1', '11', '3', '3', '0'), + +('1', '11', '4', '0', '0'), +('1', '11', '4', '1', '0'), +('1', '11', '4', '2', '0'), +('1', '11', '4', '3', '0'), + +('1', '11', '5', '0', '0'), +('1', '11', '5', '1', '0'), +('1', '11', '5', '2', '0'), +('1', '11', '5', '3', '0'), + +('1', '11', '6', '0', '0'), +('1', '11', '6', '1', '0'), +('1', '11', '6', '2', '0'), +('1', '11', '6', '3', '0'), + +('1', '12', '0', '0', '0'), +('1', '12', '0', '1', '0'), +('1', '12', '0', '2', '0'), +('1', '12', '0', '3', '0'), + +('1', '12', '1', '0', '100'), +('1', '12', '1', '1', '100'), +('1', '12', '1', '2', '100'), +('1', '12', '1', '3', '100'), + +('1', '12', '2', '0', '50'), +('1', '12', '2', '1', '50'), +('1', '12', '2', '2', '50'), +('1', '12', '2', '3', '50'), + +('1', '12', '3', '0', '100'), +('1', '12', '3', '1', '100'), +('1', '12', '3', '2', '100'), +('1', '12', '3', '3', '100'), + +('1', '12', '4', '0', '50'), +('1', '12', '4', '1', '50'), +('1', '12', '4', '2', '50'), +('1', '12', '4', '3', '50'), + +('1', '12', '5', '0', '25'), +('1', '12', '5', '1', '25'), +('1', '12', '5', '2', '25'), +('1', '12', '5', '3', '25'), + +('1', '12', '6', '0', '25'), +('1', '12', '6', '1', '25'), +('1', '12', '6', '2', '25'), +('1', '12', '6', '3', '25'), + +('1', '13', '0', '0', '0'), +('1', '13', '0', '1', '0'), +('1', '13', '0', '2', '0'), +('1', '13', '0', '3', '0'), + +('1', '13', '1', '0', '0'), +('1', '13', '1', '1', '0'), +('1', '13', '1', '2', '0'), +('1', '13', '1', '3', '0'), + +('1', '13', '2', '0', '0'), +('1', '13', '2', '1', '0'), +('1', '13', '2', '2', '0'), +('1', '13', '2', '3', '0'), + +('1', '13', '3', '0', '0'), +('1', '13', '3', '1', '0'), +('1', '13', '3', '2', '0'), +('1', '13', '3', '3', '0'), + +('1', '13', '4', '0', '0'), +('1', '13', '4', '1', '0'), +('1', '13', '4', '2', '0'), +('1', '13', '4', '3', '0'), + +('1', '13', '5', '0', '0'), +('1', '13', '5', '1', '0'), +('1', '13', '5', '2', '0'), +('1', '13', '5', '3', '0'), + +('1', '13', '6', '0', '0'), +('1', '13', '6', '1', '0'), +('1', '13', '6', '2', '0'), +('1', '13', '6', '3', '0'), + +('1', '14', '0', '0', '0'), +('1', '14', '0', '1', '0'), +('1', '14', '0', '2', '0'), +('1', '14', '0', '3', '0'), + +('1', '14', '1', '0', '25'), +('1', '14', '1', '1', '100'), +('1', '14', '1', '2', '25'), +('1', '14', '1', '3', '100'), + +('1', '14', '2', '0', '15'), +('1', '14', '2', '1', '75'), +('1', '14', '2', '2', '15'), +('1', '14', '2', '3', '75'), + +('1', '14', '3', '0', '25'), +('1', '14', '3', '1', '100'), +('1', '14', '3', '2', '25'), +('1', '14', '3', '3', '100'), + +('1', '14', '4', '0', '15'), +('1', '14', '4', '1', '75'), +('1', '14', '4', '2', '15'), +('1', '14', '4', '3', '75'), + +('1', '14', '5', '0', '0'), +('1', '14', '5', '1', '50'), +('1', '14', '5', '2', '0'), +('1', '14', '5', '3', '50'), + +('1', '14', '6', '0', '0'), +('1', '14', '6', '1', '50'), +('1', '14', '6', '2', '0'), +('1', '14', '6', '3', '50'), + +('1', '15', '0', '0', '0'), +('1', '15', '0', '1', '0'), +('1', '15', '0', '2', '0'), +('1', '15', '0', '3', '0'), + +('1', '15', '1', '0', '0'), +('1', '15', '1', '1', '0'), +('1', '15', '1', '2', '0'), +('1', '15', '1', '3', '0'), + +('1', '15', '2', '0', '0'), +('1', '15', '2', '1', '0'), +('1', '15', '2', '2', '0'), +('1', '15', '2', '3', '0'), + +('1', '15', '3', '0', '0'), +('1', '15', '3', '1', '0'), +('1', '15', '3', '2', '0'), +('1', '15', '3', '3', '0'), + +('1', '15', '4', '0', '0'), +('1', '15', '4', '1', '0'), +('1', '15', '4', '2', '0'), +('1', '15', '4', '3', '0'), + +('1', '15', '5', '0', '0'), +('1', '15', '5', '1', '0'), +('1', '15', '5', '2', '0'), +('1', '15', '5', '3', '0'), + +('1', '15', '6', '0', '0'), +('1', '15', '6', '1', '0'), +('1', '15', '6', '2', '0'), +('1', '15', '6', '3', '0'), + +-- SpellType_RootIndex + +('2', '0', '0', '0', '0'), +('2', '0', '0', '1', '0'), +('2', '0', '0', '2', '0'), +('2', '0', '0', '3', '0'), + +('2', '0', '1', '0', '0'), +('2', '0', '1', '1', '0'), +('2', '0', '1', '2', '0'), +('2', '0', '1', '3', '0'), + +('2', '0', '2', '0', '0'), +('2', '0', '2', '1', '0'), +('2', '0', '2', '2', '0'), +('2', '0', '2', '3', '0'), + +('2', '0', '3', '0', '0'), +('2', '0', '3', '1', '0'), +('2', '0', '3', '2', '0'), +('2', '0', '3', '3', '0'), + +('2', '0', '4', '0', '0'), +('2', '0', '4', '1', '0'), +('2', '0', '4', '2', '0'), +('2', '0', '4', '3', '0'), + +('2', '0', '5', '0', '0'), +('2', '0', '5', '1', '0'), +('2', '0', '5', '2', '0'), +('2', '0', '5', '3', '0'), + +('2', '0', '6', '0', '0'), +('2', '0', '6', '1', '0'), +('2', '0', '6', '2', '0'), +('2', '0', '6', '3', '0'), + +('2', '1', '0', '0', '0'), +('2', '1', '0', '1', '0'), +('2', '1', '0', '2', '0'), +('2', '1', '0', '3', '0'), + +('2', '1', '1', '0', '0'), +('2', '1', '1', '1', '0'), +('2', '1', '1', '2', '0'), +('2', '1', '1', '3', '0'), + +('2', '1', '2', '0', '0'), +('2', '1', '2', '1', '0'), +('2', '1', '2', '2', '0'), +('2', '1', '2', '3', '0'), + +('2', '1', '3', '0', '0'), +('2', '1', '3', '1', '0'), +('2', '1', '3', '2', '0'), +('2', '1', '3', '3', '0'), + +('2', '1', '4', '0', '0'), +('2', '1', '4', '1', '0'), +('2', '1', '4', '2', '0'), +('2', '1', '4', '3', '0'), + +('2', '1', '5', '0', '0'), +('2', '1', '5', '1', '0'), +('2', '1', '5', '2', '0'), +('2', '1', '5', '3', '0'), + +('2', '1', '6', '0', '0'), +('2', '1', '6', '1', '0'), +('2', '1', '6', '2', '0'), +('2', '1', '6', '3', '0'), + +('2', '2', '0', '0', '0'), +('2', '2', '0', '1', '0'), +('2', '2', '0', '2', '0'), +('2', '2', '0', '3', '0'), + +('2', '2', '1', '0', '0'), +('2', '2', '1', '1', '0'), +('2', '2', '1', '2', '0'), +('2', '2', '1', '3', '0'), + +('2', '2', '2', '0', '0'), +('2', '2', '2', '1', '0'), +('2', '2', '2', '2', '0'), +('2', '2', '2', '3', '0'), + +('2', '2', '3', '0', '0'), +('2', '2', '3', '1', '0'), +('2', '2', '3', '2', '0'), +('2', '2', '3', '3', '0'), + +('2', '2', '4', '0', '0'), +('2', '2', '4', '1', '0'), +('2', '2', '4', '2', '0'), +('2', '2', '4', '3', '0'), + +('2', '2', '5', '0', '0'), +('2', '2', '5', '1', '0'), +('2', '2', '5', '2', '0'), +('2', '2', '5', '3', '0'), + +('2', '2', '6', '0', '0'), +('2', '2', '6', '1', '0'), +('2', '2', '6', '2', '0'), +('2', '2', '6', '3', '0'), + +('2', '3', '0', '0', '0'), +('2', '3', '0', '1', '0'), +('2', '3', '0', '2', '0'), +('2', '3', '0', '3', '0'), + +('2', '3', '1', '0', '0'), +('2', '3', '1', '1', '0'), +('2', '3', '1', '2', '0'), +('2', '3', '1', '3', '0'), + +('2', '3', '2', '0', '0'), +('2', '3', '2', '1', '0'), +('2', '3', '2', '2', '0'), +('2', '3', '2', '3', '0'), + +('2', '3', '3', '0', '0'), +('2', '3', '3', '1', '0'), +('2', '3', '3', '2', '0'), +('2', '3', '3', '3', '0'), + +('2', '3', '4', '0', '0'), +('2', '3', '4', '1', '0'), +('2', '3', '4', '2', '0'), +('2', '3', '4', '3', '0'), + +('2', '3', '5', '0', '0'), +('2', '3', '5', '1', '0'), +('2', '3', '5', '2', '0'), +('2', '3', '5', '3', '0'), + +('2', '3', '6', '0', '0'), +('2', '3', '6', '1', '0'), +('2', '3', '6', '2', '0'), +('2', '3', '6', '3', '0'), + +('2', '4', '0', '0', '0'), +('2', '4', '0', '1', '0'), +('2', '4', '0', '2', '0'), +('2', '4', '0', '3', '0'), + +('2', '4', '1', '0', '0'), +('2', '4', '1', '1', '0'), +('2', '4', '1', '2', '0'), +('2', '4', '1', '3', '0'), + +('2', '4', '2', '0', '0'), +('2', '4', '2', '1', '0'), +('2', '4', '2', '2', '0'), +('2', '4', '2', '3', '0'), + +('2', '4', '3', '0', '0'), +('2', '4', '3', '1', '0'), +('2', '4', '3', '2', '0'), +('2', '4', '3', '3', '0'), + +('2', '4', '4', '0', '0'), +('2', '4', '4', '1', '0'), +('2', '4', '4', '2', '0'), +('2', '4', '4', '3', '0'), + +('2', '4', '5', '0', '0'), +('2', '4', '5', '1', '0'), +('2', '4', '5', '2', '0'), +('2', '4', '5', '3', '0'), + +('2', '4', '6', '0', '0'), +('2', '4', '6', '1', '0'), +('2', '4', '6', '2', '0'), +('2', '4', '6', '3', '0'), + +('2', '5', '0', '0', '0'), +('2', '5', '0', '1', '0'), +('2', '5', '0', '2', '0'), +('2', '5', '0', '3', '0'), + +('2', '5', '1', '0', '0'), +('2', '5', '1', '1', '0'), +('2', '5', '1', '2', '0'), +('2', '5', '1', '3', '0'), + +('2', '5', '2', '0', '0'), +('2', '5', '2', '1', '0'), +('2', '5', '2', '2', '0'), +('2', '5', '2', '3', '0'), + +('2', '5', '3', '0', '0'), +('2', '5', '3', '1', '0'), +('2', '5', '3', '2', '0'), +('2', '5', '3', '3', '0'), + +('2', '5', '4', '0', '0'), +('2', '5', '4', '1', '0'), +('2', '5', '4', '2', '0'), +('2', '5', '4', '3', '0'), + +('2', '5', '5', '0', '0'), +('2', '5', '5', '1', '0'), +('2', '5', '5', '2', '0'), +('2', '5', '5', '3', '0'), + +('2', '5', '6', '0', '0'), +('2', '5', '6', '1', '0'), +('2', '5', '6', '2', '0'), +('2', '5', '6', '3', '0'), + +('2', '6', '0', '0', '0'), +('2', '6', '0', '1', '0'), +('2', '6', '0', '2', '0'), +('2', '6', '0', '3', '0'), + +('2', '6', '1', '0', '0'), +('2', '6', '1', '1', '0'), +('2', '6', '1', '2', '0'), +('2', '6', '1', '3', '0'), + +('2', '6', '2', '0', '0'), +('2', '6', '2', '1', '0'), +('2', '6', '2', '2', '0'), +('2', '6', '2', '3', '0'), + +('2', '6', '3', '0', '0'), +('2', '6', '3', '1', '0'), +('2', '6', '3', '2', '0'), +('2', '6', '3', '3', '0'), + +('2', '6', '4', '0', '0'), +('2', '6', '4', '1', '0'), +('2', '6', '4', '2', '0'), +('2', '6', '4', '3', '0'), + +('2', '6', '5', '0', '0'), +('2', '6', '5', '1', '0'), +('2', '6', '5', '2', '0'), +('2', '6', '5', '3', '0'), + +('2', '6', '6', '0', '0'), +('2', '6', '6', '1', '0'), +('2', '6', '6', '2', '0'), +('2', '6', '6', '3', '0'), + +('2', '7', '0', '0', '0'), +('2', '7', '0', '1', '0'), +('2', '7', '0', '2', '0'), +('2', '7', '0', '3', '0'), + +('2', '7', '1', '0', '0'), +('2', '7', '1', '1', '0'), +('2', '7', '1', '2', '0'), +('2', '7', '1', '3', '0'), + +('2', '7', '2', '0', '0'), +('2', '7', '2', '1', '0'), +('2', '7', '2', '2', '0'), +('2', '7', '2', '3', '0'), + +('2', '7', '3', '0', '0'), +('2', '7', '3', '1', '0'), +('2', '7', '3', '2', '0'), +('2', '7', '3', '3', '0'), + +('2', '7', '4', '0', '0'), +('2', '7', '4', '1', '0'), +('2', '7', '4', '2', '0'), +('2', '7', '4', '3', '0'), + +('2', '7', '5', '0', '0'), +('2', '7', '5', '1', '0'), +('2', '7', '5', '2', '0'), +('2', '7', '5', '3', '0'), + +('2', '7', '6', '0', '0'), +('2', '7', '6', '1', '0'), +('2', '7', '6', '2', '0'), +('2', '7', '6', '3', '0'), + +('2', '8', '0', '0', '0'), +('2', '8', '0', '1', '0'), +('2', '8', '0', '2', '0'), +('2', '8', '0', '3', '0'), + +('2', '8', '1', '0', '0'), +('2', '8', '1', '1', '0'), +('2', '8', '1', '2', '0'), +('2', '8', '1', '3', '0'), + +('2', '8', '2', '0', '0'), +('2', '8', '2', '1', '0'), +('2', '8', '2', '2', '0'), +('2', '8', '2', '3', '0'), + +('2', '8', '3', '0', '0'), +('2', '8', '3', '1', '0'), +('2', '8', '3', '2', '0'), +('2', '8', '3', '3', '0'), + +('2', '8', '4', '0', '0'), +('2', '8', '4', '1', '0'), +('2', '8', '4', '2', '0'), +('2', '8', '4', '3', '0'), + +('2', '8', '5', '0', '0'), +('2', '8', '5', '1', '0'), +('2', '8', '5', '2', '0'), +('2', '8', '5', '3', '0'), + +('2', '8', '6', '0', '0'), +('2', '8', '6', '1', '0'), +('2', '8', '6', '2', '0'), +('2', '8', '6', '3', '0'), + +('2', '9', '0', '0', '0'), +('2', '9', '0', '1', '0'), +('2', '9', '0', '2', '0'), +('2', '9', '0', '3', '0'), + +('2', '9', '1', '0', '0'), +('2', '9', '1', '1', '0'), +('2', '9', '1', '2', '0'), +('2', '9', '1', '3', '0'), + +('2', '9', '2', '0', '0'), +('2', '9', '2', '1', '0'), +('2', '9', '2', '2', '0'), +('2', '9', '2', '3', '0'), + +('2', '9', '3', '0', '0'), +('2', '9', '3', '1', '0'), +('2', '9', '3', '2', '0'), +('2', '9', '3', '3', '0'), + +('2', '9', '4', '0', '0'), +('2', '9', '4', '1', '0'), +('2', '9', '4', '2', '0'), +('2', '9', '4', '3', '0'), + +('2', '9', '5', '0', '0'), +('2', '9', '5', '1', '0'), +('2', '9', '5', '2', '0'), +('2', '9', '5', '3', '0'), + +('2', '9', '6', '0', '0'), +('2', '9', '6', '1', '0'), +('2', '9', '6', '2', '0'), +('2', '9', '6', '3', '0'), + +('2', '10', '0', '0', '0'), +('2', '10', '0', '1', '0'), +('2', '10', '0', '2', '0'), +('2', '10', '0', '3', '0'), + +('2', '10', '1', '0', '0'), +('2', '10', '1', '1', '0'), +('2', '10', '1', '2', '0'), +('2', '10', '1', '3', '0'), + +('2', '10', '2', '0', '0'), +('2', '10', '2', '1', '0'), +('2', '10', '2', '2', '0'), +('2', '10', '2', '3', '0'), + +('2', '10', '3', '0', '0'), +('2', '10', '3', '1', '0'), +('2', '10', '3', '2', '0'), +('2', '10', '3', '3', '0'), + +('2', '10', '4', '0', '0'), +('2', '10', '4', '1', '0'), +('2', '10', '4', '2', '0'), +('2', '10', '4', '3', '0'), + +('2', '10', '5', '0', '0'), +('2', '10', '5', '1', '0'), +('2', '10', '5', '2', '0'), +('2', '10', '5', '3', '0'), + +('2', '10', '6', '0', '0'), +('2', '10', '6', '1', '0'), +('2', '10', '6', '2', '0'), +('2', '10', '6', '3', '0'), + +('2', '11', '0', '0', '0'), +('2', '11', '0', '1', '0'), +('2', '11', '0', '2', '0'), +('2', '11', '0', '3', '0'), + +('2', '11', '1', '0', '0'), +('2', '11', '1', '1', '0'), +('2', '11', '1', '2', '0'), +('2', '11', '1', '3', '0'), + +('2', '11', '2', '0', '0'), +('2', '11', '2', '1', '0'), +('2', '11', '2', '2', '0'), +('2', '11', '2', '3', '0'), + +('2', '11', '3', '0', '0'), +('2', '11', '3', '1', '0'), +('2', '11', '3', '2', '0'), +('2', '11', '3', '3', '0'), + +('2', '11', '4', '0', '0'), +('2', '11', '4', '1', '0'), +('2', '11', '4', '2', '0'), +('2', '11', '4', '3', '0'), + +('2', '11', '5', '0', '0'), +('2', '11', '5', '1', '0'), +('2', '11', '5', '2', '0'), +('2', '11', '5', '3', '0'), + +('2', '11', '6', '0', '0'), +('2', '11', '6', '1', '0'), +('2', '11', '6', '2', '0'), +('2', '11', '6', '3', '0'), + +('2', '12', '0', '0', '0'), +('2', '12', '0', '1', '0'), +('2', '12', '0', '2', '0'), +('2', '12', '0', '3', '0'), + +('2', '12', '1', '0', '0'), +('2', '12', '1', '1', '0'), +('2', '12', '1', '2', '0'), +('2', '12', '1', '3', '0'), + +('2', '12', '2', '0', '0'), +('2', '12', '2', '1', '0'), +('2', '12', '2', '2', '0'), +('2', '12', '2', '3', '0'), + +('2', '12', '3', '0', '0'), +('2', '12', '3', '1', '0'), +('2', '12', '3', '2', '0'), +('2', '12', '3', '3', '0'), + +('2', '12', '4', '0', '0'), +('2', '12', '4', '1', '0'), +('2', '12', '4', '2', '0'), +('2', '12', '4', '3', '0'), + +('2', '12', '5', '0', '0'), +('2', '12', '5', '1', '0'), +('2', '12', '5', '2', '0'), +('2', '12', '5', '3', '0'), + +('2', '12', '6', '0', '0'), +('2', '12', '6', '1', '0'), +('2', '12', '6', '2', '0'), +('2', '12', '6', '3', '0'), + +('2', '13', '0', '0', '0'), +('2', '13', '0', '1', '0'), +('2', '13', '0', '2', '0'), +('2', '13', '0', '3', '0'), + +('2', '13', '1', '0', '0'), +('2', '13', '1', '1', '0'), +('2', '13', '1', '2', '0'), +('2', '13', '1', '3', '0'), + +('2', '13', '2', '0', '0'), +('2', '13', '2', '1', '0'), +('2', '13', '2', '2', '0'), +('2', '13', '2', '3', '0'), + +('2', '13', '3', '0', '0'), +('2', '13', '3', '1', '0'), +('2', '13', '3', '2', '0'), +('2', '13', '3', '3', '0'), + +('2', '13', '4', '0', '0'), +('2', '13', '4', '1', '0'), +('2', '13', '4', '2', '0'), +('2', '13', '4', '3', '0'), + +('2', '13', '5', '0', '0'), +('2', '13', '5', '1', '0'), +('2', '13', '5', '2', '0'), +('2', '13', '5', '3', '0'), + +('2', '13', '6', '0', '0'), +('2', '13', '6', '1', '0'), +('2', '13', '6', '2', '0'), +('2', '13', '6', '3', '0'), + +('2', '14', '0', '0', '0'), +('2', '14', '0', '1', '0'), +('2', '14', '0', '2', '0'), +('2', '14', '0', '3', '0'), + +('2', '14', '1', '0', '0'), +('2', '14', '1', '1', '0'), +('2', '14', '1', '2', '0'), +('2', '14', '1', '3', '0'), + +('2', '14', '2', '0', '0'), +('2', '14', '2', '1', '0'), +('2', '14', '2', '2', '0'), +('2', '14', '2', '3', '0'), + +('2', '14', '3', '0', '0'), +('2', '14', '3', '1', '0'), +('2', '14', '3', '2', '0'), +('2', '14', '3', '3', '0'), + +('2', '14', '4', '0', '0'), +('2', '14', '4', '1', '0'), +('2', '14', '4', '2', '0'), +('2', '14', '4', '3', '0'), + +('2', '14', '5', '0', '0'), +('2', '14', '5', '1', '0'), +('2', '14', '5', '2', '0'), +('2', '14', '5', '3', '0'), + +('2', '14', '6', '0', '0'), +('2', '14', '6', '1', '0'), +('2', '14', '6', '2', '0'), +('2', '14', '6', '3', '0'), + +('2', '15', '0', '0', '0'), +('2', '15', '0', '1', '0'), +('2', '15', '0', '2', '0'), +('2', '15', '0', '3', '0'), + +('2', '15', '1', '0', '0'), +('2', '15', '1', '1', '0'), +('2', '15', '1', '2', '0'), +('2', '15', '1', '3', '0'), + +('2', '15', '2', '0', '0'), +('2', '15', '2', '1', '0'), +('2', '15', '2', '2', '0'), +('2', '15', '2', '3', '0'), + +('2', '15', '3', '0', '0'), +('2', '15', '3', '1', '0'), +('2', '15', '3', '2', '0'), +('2', '15', '3', '3', '0'), + +('2', '15', '4', '0', '0'), +('2', '15', '4', '1', '0'), +('2', '15', '4', '2', '0'), +('2', '15', '4', '3', '0'), + +('2', '15', '5', '0', '0'), +('2', '15', '5', '1', '0'), +('2', '15', '5', '2', '0'), +('2', '15', '5', '3', '0'), + +('2', '15', '6', '0', '0'), +('2', '15', '6', '1', '0'), +('2', '15', '6', '2', '0'), +('2', '15', '6', '3', '0'), + +-- SpellType_BuffIndex + +('3', '0', '0', '0', '0'), +('3', '0', '0', '1', '0'), +('3', '0', '0', '2', '0'), +('3', '0', '0', '3', '0'), + +('3', '0', '1', '0', '0'), +('3', '0', '1', '1', '0'), +('3', '0', '1', '2', '0'), +('3', '0', '1', '3', '0'), + +('3', '0', '2', '0', '0'), +('3', '0', '2', '1', '0'), +('3', '0', '2', '2', '0'), +('3', '0', '2', '3', '0'), + +('3', '0', '3', '0', '0'), +('3', '0', '3', '1', '0'), +('3', '0', '3', '2', '0'), +('3', '0', '3', '3', '0'), + +('3', '0', '4', '0', '0'), +('3', '0', '4', '1', '0'), +('3', '0', '4', '2', '0'), +('3', '0', '4', '3', '0'), + +('3', '0', '5', '0', '0'), +('3', '0', '5', '1', '0'), +('3', '0', '5', '2', '0'), +('3', '0', '5', '3', '0'), + +('3', '0', '6', '0', '0'), +('3', '0', '6', '1', '0'), +('3', '0', '6', '2', '0'), +('3', '0', '6', '3', '0'), + +('3', '1', '0', '0', '0'), +('3', '1', '0', '1', '0'), +('3', '1', '0', '2', '0'), +('3', '1', '0', '3', '0'), + +('3', '1', '1', '0', '0'), +('3', '1', '1', '1', '0'), +('3', '1', '1', '2', '0'), +('3', '1', '1', '3', '0'), + +('3', '1', '2', '0', '0'), +('3', '1', '2', '1', '0'), +('3', '1', '2', '2', '0'), +('3', '1', '2', '3', '0'), + +('3', '1', '3', '0', '0'), +('3', '1', '3', '1', '0'), +('3', '1', '3', '2', '0'), +('3', '1', '3', '3', '0'), + +('3', '1', '4', '0', '0'), +('3', '1', '4', '1', '0'), +('3', '1', '4', '2', '0'), +('3', '1', '4', '3', '0'), + +('3', '1', '5', '0', '0'), +('3', '1', '5', '1', '0'), +('3', '1', '5', '2', '0'), +('3', '1', '5', '3', '0'), + +('3', '1', '6', '0', '0'), +('3', '1', '6', '1', '0'), +('3', '1', '6', '2', '0'), +('3', '1', '6', '3', '0'), + +('3', '2', '0', '0', '0'), +('3', '2', '0', '1', '0'), +('3', '2', '0', '2', '0'), +('3', '2', '0', '3', '0'), + +('3', '2', '1', '0', '0'), +('3', '2', '1', '1', '0'), +('3', '2', '1', '2', '0'), +('3', '2', '1', '3', '0'), + +('3', '2', '2', '0', '0'), +('3', '2', '2', '1', '0'), +('3', '2', '2', '2', '0'), +('3', '2', '2', '3', '0'), + +('3', '2', '3', '0', '0'), +('3', '2', '3', '1', '0'), +('3', '2', '3', '2', '0'), +('3', '2', '3', '3', '0'), + +('3', '2', '4', '0', '0'), +('3', '2', '4', '1', '0'), +('3', '2', '4', '2', '0'), +('3', '2', '4', '3', '0'), + +('3', '2', '5', '0', '0'), +('3', '2', '5', '1', '0'), +('3', '2', '5', '2', '0'), +('3', '2', '5', '3', '0'), + +('3', '2', '6', '0', '0'), +('3', '2', '6', '1', '0'), +('3', '2', '6', '2', '0'), +('3', '2', '6', '3', '0'), + +('3', '3', '0', '0', '0'), +('3', '3', '0', '1', '0'), +('3', '3', '0', '2', '0'), +('3', '3', '0', '3', '0'), + +('3', '3', '1', '0', '0'), +('3', '3', '1', '1', '0'), +('3', '3', '1', '2', '0'), +('3', '3', '1', '3', '0'), + +('3', '3', '2', '0', '0'), +('3', '3', '2', '1', '0'), +('3', '3', '2', '2', '0'), +('3', '3', '2', '3', '0'), + +('3', '3', '3', '0', '0'), +('3', '3', '3', '1', '0'), +('3', '3', '3', '2', '0'), +('3', '3', '3', '3', '0'), + +('3', '3', '4', '0', '0'), +('3', '3', '4', '1', '0'), +('3', '3', '4', '2', '0'), +('3', '3', '4', '3', '0'), + +('3', '3', '5', '0', '0'), +('3', '3', '5', '1', '0'), +('3', '3', '5', '2', '0'), +('3', '3', '5', '3', '0'), + +('3', '3', '6', '0', '0'), +('3', '3', '6', '1', '0'), +('3', '3', '6', '2', '0'), +('3', '3', '6', '3', '0'), + +('3', '4', '0', '0', '0'), +('3', '4', '0', '1', '0'), +('3', '4', '0', '2', '0'), +('3', '4', '0', '3', '0'), + +('3', '4', '1', '0', '0'), +('3', '4', '1', '1', '0'), +('3', '4', '1', '2', '0'), +('3', '4', '1', '3', '0'), + +('3', '4', '2', '0', '0'), +('3', '4', '2', '1', '0'), +('3', '4', '2', '2', '0'), +('3', '4', '2', '3', '0'), + +('3', '4', '3', '0', '0'), +('3', '4', '3', '1', '0'), +('3', '4', '3', '2', '0'), +('3', '4', '3', '3', '0'), + +('3', '4', '4', '0', '0'), +('3', '4', '4', '1', '0'), +('3', '4', '4', '2', '0'), +('3', '4', '4', '3', '0'), + +('3', '4', '5', '0', '0'), +('3', '4', '5', '1', '0'), +('3', '4', '5', '2', '0'), +('3', '4', '5', '3', '0'), + +('3', '4', '6', '0', '0'), +('3', '4', '6', '1', '0'), +('3', '4', '6', '2', '0'), +('3', '4', '6', '3', '0'), + +('3', '5', '0', '0', '0'), +('3', '5', '0', '1', '0'), +('3', '5', '0', '2', '0'), +('3', '5', '0', '3', '0'), + +('3', '5', '1', '0', '0'), +('3', '5', '1', '1', '0'), +('3', '5', '1', '2', '0'), +('3', '5', '1', '3', '0'), + +('3', '5', '2', '0', '0'), +('3', '5', '2', '1', '0'), +('3', '5', '2', '2', '0'), +('3', '5', '2', '3', '0'), + +('3', '5', '3', '0', '0'), +('3', '5', '3', '1', '0'), +('3', '5', '3', '2', '0'), +('3', '5', '3', '3', '0'), + +('3', '5', '4', '0', '0'), +('3', '5', '4', '1', '0'), +('3', '5', '4', '2', '0'), +('3', '5', '4', '3', '0'), + +('3', '5', '5', '0', '0'), +('3', '5', '5', '1', '0'), +('3', '5', '5', '2', '0'), +('3', '5', '5', '3', '0'), + +('3', '5', '6', '0', '0'), +('3', '5', '6', '1', '0'), +('3', '5', '6', '2', '0'), +('3', '5', '6', '3', '0'), + +('3', '6', '0', '0', '0'), +('3', '6', '0', '1', '0'), +('3', '6', '0', '2', '0'), +('3', '6', '0', '3', '0'), + +('3', '6', '1', '0', '0'), +('3', '6', '1', '1', '0'), +('3', '6', '1', '2', '0'), +('3', '6', '1', '3', '0'), + +('3', '6', '2', '0', '0'), +('3', '6', '2', '1', '0'), +('3', '6', '2', '2', '0'), +('3', '6', '2', '3', '0'), + +('3', '6', '3', '0', '0'), +('3', '6', '3', '1', '0'), +('3', '6', '3', '2', '0'), +('3', '6', '3', '3', '0'), + +('3', '6', '4', '0', '0'), +('3', '6', '4', '1', '0'), +('3', '6', '4', '2', '0'), +('3', '6', '4', '3', '0'), + +('3', '6', '5', '0', '0'), +('3', '6', '5', '1', '0'), +('3', '6', '5', '2', '0'), +('3', '6', '5', '3', '0'), + +('3', '6', '6', '0', '0'), +('3', '6', '6', '1', '0'), +('3', '6', '6', '2', '0'), +('3', '6', '6', '3', '0'), + +('3', '7', '0', '0', '0'), +('3', '7', '0', '1', '0'), +('3', '7', '0', '2', '0'), +('3', '7', '0', '3', '0'), + +('3', '7', '1', '0', '0'), +('3', '7', '1', '1', '0'), +('3', '7', '1', '2', '0'), +('3', '7', '1', '3', '0'), + +('3', '7', '2', '0', '0'), +('3', '7', '2', '1', '0'), +('3', '7', '2', '2', '0'), +('3', '7', '2', '3', '0'), + +('3', '7', '3', '0', '0'), +('3', '7', '3', '1', '0'), +('3', '7', '3', '2', '0'), +('3', '7', '3', '3', '0'), + +('3', '7', '4', '0', '0'), +('3', '7', '4', '1', '0'), +('3', '7', '4', '2', '0'), +('3', '7', '4', '3', '0'), + +('3', '7', '5', '0', '0'), +('3', '7', '5', '1', '0'), +('3', '7', '5', '2', '0'), +('3', '7', '5', '3', '0'), + +('3', '7', '6', '0', '0'), +('3', '7', '6', '1', '0'), +('3', '7', '6', '2', '0'), +('3', '7', '6', '3', '0'), + +('3', '8', '0', '0', '0'), +('3', '8', '0', '1', '0'), +('3', '8', '0', '2', '0'), +('3', '8', '0', '3', '0'), + +('3', '8', '1', '0', '0'), +('3', '8', '1', '1', '0'), +('3', '8', '1', '2', '0'), +('3', '8', '1', '3', '0'), + +('3', '8', '2', '0', '0'), +('3', '8', '2', '1', '0'), +('3', '8', '2', '2', '0'), +('3', '8', '2', '3', '0'), + +('3', '8', '3', '0', '0'), +('3', '8', '3', '1', '0'), +('3', '8', '3', '2', '0'), +('3', '8', '3', '3', '0'), + +('3', '8', '4', '0', '0'), +('3', '8', '4', '1', '0'), +('3', '8', '4', '2', '0'), +('3', '8', '4', '3', '0'), + +('3', '8', '5', '0', '0'), +('3', '8', '5', '1', '0'), +('3', '8', '5', '2', '0'), +('3', '8', '5', '3', '0'), + +('3', '8', '6', '0', '0'), +('3', '8', '6', '1', '0'), +('3', '8', '6', '2', '0'), +('3', '8', '6', '3', '0'), + +('3', '9', '0', '0', '0'), +('3', '9', '0', '1', '0'), +('3', '9', '0', '2', '0'), +('3', '9', '0', '3', '0'), + +('3', '9', '1', '0', '0'), +('3', '9', '1', '1', '0'), +('3', '9', '1', '2', '0'), +('3', '9', '1', '3', '0'), + +('3', '9', '2', '0', '0'), +('3', '9', '2', '1', '0'), +('3', '9', '2', '2', '0'), +('3', '9', '2', '3', '0'), + +('3', '9', '3', '0', '0'), +('3', '9', '3', '1', '0'), +('3', '9', '3', '2', '0'), +('3', '9', '3', '3', '0'), + +('3', '9', '4', '0', '0'), +('3', '9', '4', '1', '0'), +('3', '9', '4', '2', '0'), +('3', '9', '4', '3', '0'), + +('3', '9', '5', '0', '0'), +('3', '9', '5', '1', '0'), +('3', '9', '5', '2', '0'), +('3', '9', '5', '3', '0'), + +('3', '9', '6', '0', '0'), +('3', '9', '6', '1', '0'), +('3', '9', '6', '2', '0'), +('3', '9', '6', '3', '0'), + +('3', '10', '0', '0', '0'), +('3', '10', '0', '1', '0'), +('3', '10', '0', '2', '0'), +('3', '10', '0', '3', '0'), + +('3', '10', '1', '0', '0'), +('3', '10', '1', '1', '0'), +('3', '10', '1', '2', '0'), +('3', '10', '1', '3', '0'), + +('3', '10', '2', '0', '0'), +('3', '10', '2', '1', '0'), +('3', '10', '2', '2', '0'), +('3', '10', '2', '3', '0'), + +('3', '10', '3', '0', '0'), +('3', '10', '3', '1', '0'), +('3', '10', '3', '2', '0'), +('3', '10', '3', '3', '0'), + +('3', '10', '4', '0', '0'), +('3', '10', '4', '1', '0'), +('3', '10', '4', '2', '0'), +('3', '10', '4', '3', '0'), + +('3', '10', '5', '0', '0'), +('3', '10', '5', '1', '0'), +('3', '10', '5', '2', '0'), +('3', '10', '5', '3', '0'), + +('3', '10', '6', '0', '0'), +('3', '10', '6', '1', '0'), +('3', '10', '6', '2', '0'), +('3', '10', '6', '3', '0'), + +('3', '11', '0', '0', '0'), +('3', '11', '0', '1', '0'), +('3', '11', '0', '2', '0'), +('3', '11', '0', '3', '0'), + +('3', '11', '1', '0', '0'), +('3', '11', '1', '1', '0'), +('3', '11', '1', '2', '0'), +('3', '11', '1', '3', '0'), + +('3', '11', '2', '0', '0'), +('3', '11', '2', '1', '0'), +('3', '11', '2', '2', '0'), +('3', '11', '2', '3', '0'), + +('3', '11', '3', '0', '0'), +('3', '11', '3', '1', '0'), +('3', '11', '3', '2', '0'), +('3', '11', '3', '3', '0'), + +('3', '11', '4', '0', '0'), +('3', '11', '4', '1', '0'), +('3', '11', '4', '2', '0'), +('3', '11', '4', '3', '0'), + +('3', '11', '5', '0', '0'), +('3', '11', '5', '1', '0'), +('3', '11', '5', '2', '0'), +('3', '11', '5', '3', '0'), + +('3', '11', '6', '0', '0'), +('3', '11', '6', '1', '0'), +('3', '11', '6', '2', '0'), +('3', '11', '6', '3', '0'), + +('3', '12', '0', '0', '0'), +('3', '12', '0', '1', '0'), +('3', '12', '0', '2', '0'), +('3', '12', '0', '3', '0'), + +('3', '12', '1', '0', '0'), +('3', '12', '1', '1', '0'), +('3', '12', '1', '2', '0'), +('3', '12', '1', '3', '0'), + +('3', '12', '2', '0', '0'), +('3', '12', '2', '1', '0'), +('3', '12', '2', '2', '0'), +('3', '12', '2', '3', '0'), + +('3', '12', '3', '0', '0'), +('3', '12', '3', '1', '0'), +('3', '12', '3', '2', '0'), +('3', '12', '3', '3', '0'), + +('3', '12', '4', '0', '0'), +('3', '12', '4', '1', '0'), +('3', '12', '4', '2', '0'), +('3', '12', '4', '3', '0'), + +('3', '12', '5', '0', '0'), +('3', '12', '5', '1', '0'), +('3', '12', '5', '2', '0'), +('3', '12', '5', '3', '0'), + +('3', '12', '6', '0', '0'), +('3', '12', '6', '1', '0'), +('3', '12', '6', '2', '0'), +('3', '12', '6', '3', '0'), + +('3', '13', '0', '0', '0'), +('3', '13', '0', '1', '0'), +('3', '13', '0', '2', '0'), +('3', '13', '0', '3', '0'), + +('3', '13', '1', '0', '0'), +('3', '13', '1', '1', '0'), +('3', '13', '1', '2', '0'), +('3', '13', '1', '3', '0'), + +('3', '13', '2', '0', '0'), +('3', '13', '2', '1', '0'), +('3', '13', '2', '2', '0'), +('3', '13', '2', '3', '0'), + +('3', '13', '3', '0', '0'), +('3', '13', '3', '1', '0'), +('3', '13', '3', '2', '0'), +('3', '13', '3', '3', '0'), + +('3', '13', '4', '0', '0'), +('3', '13', '4', '1', '0'), +('3', '13', '4', '2', '0'), +('3', '13', '4', '3', '0'), + +('3', '13', '5', '0', '0'), +('3', '13', '5', '1', '0'), +('3', '13', '5', '2', '0'), +('3', '13', '5', '3', '0'), + +('3', '13', '6', '0', '0'), +('3', '13', '6', '1', '0'), +('3', '13', '6', '2', '0'), +('3', '13', '6', '3', '0'), + +('3', '14', '0', '0', '0'), +('3', '14', '0', '1', '0'), +('3', '14', '0', '2', '0'), +('3', '14', '0', '3', '0'), + +('3', '14', '1', '0', '0'), +('3', '14', '1', '1', '0'), +('3', '14', '1', '2', '0'), +('3', '14', '1', '3', '0'), + +('3', '14', '2', '0', '0'), +('3', '14', '2', '1', '0'), +('3', '14', '2', '2', '0'), +('3', '14', '2', '3', '0'), + +('3', '14', '3', '0', '0'), +('3', '14', '3', '1', '0'), +('3', '14', '3', '2', '0'), +('3', '14', '3', '3', '0'), + +('3', '14', '4', '0', '0'), +('3', '14', '4', '1', '0'), +('3', '14', '4', '2', '0'), +('3', '14', '4', '3', '0'), + +('3', '14', '5', '0', '0'), +('3', '14', '5', '1', '0'), +('3', '14', '5', '2', '0'), +('3', '14', '5', '3', '0'), + +('3', '14', '6', '0', '0'), +('3', '14', '6', '1', '0'), +('3', '14', '6', '2', '0'), +('3', '14', '6', '3', '0'), + +('3', '15', '0', '0', '0'), +('3', '15', '0', '1', '0'), +('3', '15', '0', '2', '0'), +('3', '15', '0', '3', '0'), + +('3', '15', '1', '0', '0'), +('3', '15', '1', '1', '0'), +('3', '15', '1', '2', '0'), +('3', '15', '1', '3', '0'), + +('3', '15', '2', '0', '0'), +('3', '15', '2', '1', '0'), +('3', '15', '2', '2', '0'), +('3', '15', '2', '3', '0'), + +('3', '15', '3', '0', '0'), +('3', '15', '3', '1', '0'), +('3', '15', '3', '2', '0'), +('3', '15', '3', '3', '0'), + +('3', '15', '4', '0', '0'), +('3', '15', '4', '1', '0'), +('3', '15', '4', '2', '0'), +('3', '15', '4', '3', '0'), + +('3', '15', '5', '0', '0'), +('3', '15', '5', '1', '0'), +('3', '15', '5', '2', '0'), +('3', '15', '5', '3', '0'), + +('3', '15', '6', '0', '0'), +('3', '15', '6', '1', '0'), +('3', '15', '6', '2', '0'), +('3', '15', '6', '3', '0'), + +-- SpellType_EscapeIndex + +('4', '0', '0', '0', '0'), +('4', '0', '0', '1', '0'), +('4', '0', '0', '2', '0'), +('4', '0', '0', '3', '0'), + +('4', '0', '1', '0', '0'), +('4', '0', '1', '1', '0'), +('4', '0', '1', '2', '0'), +('4', '0', '1', '3', '0'), + +('4', '0', '2', '0', '0'), +('4', '0', '2', '1', '0'), +('4', '0', '2', '2', '0'), +('4', '0', '2', '3', '0'), + +('4', '0', '3', '0', '0'), +('4', '0', '3', '1', '0'), +('4', '0', '3', '2', '0'), +('4', '0', '3', '3', '0'), + +('4', '0', '4', '0', '0'), +('4', '0', '4', '1', '0'), +('4', '0', '4', '2', '0'), +('4', '0', '4', '3', '0'), + +('4', '0', '5', '0', '0'), +('4', '0', '5', '1', '0'), +('4', '0', '5', '2', '0'), +('4', '0', '5', '3', '0'), + +('4', '0', '6', '0', '0'), +('4', '0', '6', '1', '0'), +('4', '0', '6', '2', '0'), +('4', '0', '6', '3', '0'), + +('4', '1', '0', '0', '0'), +('4', '1', '0', '1', '0'), +('4', '1', '0', '2', '0'), +('4', '1', '0', '3', '0'), + +('4', '1', '1', '0', '50'), +('4', '1', '1', '1', '50'), +('4', '1', '1', '2', '50'), +('4', '1', '1', '3', '50'), + +('4', '1', '2', '0', '50'), +('4', '1', '2', '1', '50'), +('4', '1', '2', '2', '50'), +('4', '1', '2', '3', '50'), + +('4', '1', '3', '0', '50'), +('4', '1', '3', '1', '50'), +('4', '1', '3', '2', '50'), +('4', '1', '3', '3', '50'), + +('4', '1', '4', '0', '25'), +('4', '1', '4', '1', '25'), +('4', '1', '4', '2', '25'), +('4', '1', '4', '3', '25'), + +('4', '1', '5', '0', '15'), +('4', '1', '5', '1', '15'), +('4', '1', '5', '2', '15'), +('4', '1', '5', '3', '15'), + +('4', '1', '6', '0', '15'), +('4', '1', '6', '1', '15'), +('4', '1', '6', '2', '15'), +('4', '1', '6', '3', '15'), + +('4', '2', '0', '0', '0'), +('4', '2', '0', '1', '0'), +('4', '2', '0', '2', '0'), +('4', '2', '0', '3', '0'), + +('4', '2', '1', '0', '25'), +('4', '2', '1', '1', '25'), +('4', '2', '1', '2', '25'), +('4', '2', '1', '3', '25'), + +('4', '2', '2', '0', '15'), +('4', '2', '2', '1', '15'), +('4', '2', '2', '2', '15'), +('4', '2', '2', '3', '15'), + +('4', '2', '3', '0', '25'), +('4', '2', '3', '1', '25'), +('4', '2', '3', '2', '25'), +('4', '2', '3', '3', '25'), + +('4', '2', '4', '0', '0'), +('4', '2', '4', '1', '0'), +('4', '2', '4', '2', '0'), +('4', '2', '4', '3', '0'), + +('4', '2', '5', '0', '0'), +('4', '2', '5', '1', '0'), +('4', '2', '5', '2', '0'), +('4', '2', '5', '3', '0'), + +('4', '2', '6', '0', '0'), +('4', '2', '6', '1', '0'), +('4', '2', '6', '2', '0'), +('4', '2', '6', '3', '0'), + +('4', '3', '0', '0', '0'), +('4', '3', '0', '1', '0'), +('4', '3', '0', '2', '0'), +('4', '3', '0', '3', '0'), + +('4', '3', '1', '0', '100'), +('4', '3', '1', '1', '100'), +('4', '3', '1', '2', '100'), +('4', '3', '1', '3', '100'), + +('4', '3', '2', '0', '100'), +('4', '3', '2', '1', '100'), +('4', '3', '2', '2', '100'), +('4', '3', '2', '3', '100'), + +('4', '3', '3', '0', '100'), +('4', '3', '3', '1', '100'), +('4', '3', '3', '2', '100'), +('4', '3', '3', '3', '100'), + +('4', '3', '4', '0', '50'), +('4', '3', '4', '1', '50'), +('4', '3', '4', '2', '50'), +('4', '3', '4', '3', '50'), + +('4', '3', '5', '0', '25'), +('4', '3', '5', '1', '25'), +('4', '3', '5', '2', '25'), +('4', '3', '5', '3', '25'), + +('4', '3', '6', '0', '25'), +('4', '3', '6', '1', '25'), +('4', '3', '6', '2', '25'), +('4', '3', '6', '3', '25'), + +('4', '4', '0', '0', '0'), +('4', '4', '0', '1', '0'), +('4', '4', '0', '2', '0'), +('4', '4', '0', '3', '0'), + +('4', '4', '1', '0', '25'), +('4', '4', '1', '1', '25'), +('4', '4', '1', '2', '25'), +('4', '4', '1', '3', '25'), + +('4', '4', '2', '0', '15'), +('4', '4', '2', '1', '15'), +('4', '4', '2', '2', '15'), +('4', '4', '2', '3', '15'), + +('4', '4', '3', '0', '25'), +('4', '4', '3', '1', '25'), +('4', '4', '3', '2', '25'), +('4', '4', '3', '3', '25'), + +('4', '4', '4', '0', '0'), +('4', '4', '4', '1', '0'), +('4', '4', '4', '2', '0'), +('4', '4', '4', '3', '0'), + +('4', '4', '5', '0', '0'), +('4', '4', '5', '1', '0'), +('4', '4', '5', '2', '0'), +('4', '4', '5', '3', '0'), + +('4', '4', '6', '0', '0'), +('4', '4', '6', '1', '0'), +('4', '4', '6', '2', '0'), +('4', '4', '6', '3', '0'), + +('4', '5', '0', '0', '0'), +('4', '5', '0', '1', '0'), +('4', '5', '0', '2', '0'), +('4', '5', '0', '3', '0'), + +('4', '5', '1', '0', '50'), +('4', '5', '1', '1', '50'), +('4', '5', '1', '2', '50'), +('4', '5', '1', '3', '50'), + +('4', '5', '2', '0', '50'), +('4', '5', '2', '1', '50'), +('4', '5', '2', '2', '50'), +('4', '5', '2', '3', '50'), + +('4', '5', '3', '0', '50'), +('4', '5', '3', '1', '50'), +('4', '5', '3', '2', '50'), +('4', '5', '3', '3', '50'), + +('4', '5', '4', '0', '25'), +('4', '5', '4', '1', '25'), +('4', '5', '4', '2', '25'), +('4', '5', '4', '3', '25'), + +('4', '5', '5', '0', '15'), +('4', '5', '5', '1', '15'), +('4', '5', '5', '2', '15'), +('4', '5', '5', '3', '15'), + +('4', '5', '6', '0', '15'), +('4', '5', '6', '1', '15'), +('4', '5', '6', '2', '15'), +('4', '5', '6', '3', '15'), + +('4', '6', '0', '0', '0'), +('4', '6', '0', '1', '0'), +('4', '6', '0', '2', '0'), +('4', '6', '0', '3', '0'), + +('4', '6', '1', '0', '0'), +('4', '6', '1', '1', '0'), +('4', '6', '1', '2', '0'), +('4', '6', '1', '3', '0'), + +('4', '6', '2', '0', '0'), +('4', '6', '2', '1', '0'), +('4', '6', '2', '2', '0'), +('4', '6', '2', '3', '0'), + +('4', '6', '3', '0', '0'), +('4', '6', '3', '1', '0'), +('4', '6', '3', '2', '0'), +('4', '6', '3', '3', '0'), + +('4', '6', '4', '0', '0'), +('4', '6', '4', '1', '0'), +('4', '6', '4', '2', '0'), +('4', '6', '4', '3', '0'), + +('4', '6', '5', '0', '0'), +('4', '6', '5', '1', '0'), +('4', '6', '5', '2', '0'), +('4', '6', '5', '3', '0'), + +('4', '6', '6', '0', '0'), +('4', '6', '6', '1', '0'), +('4', '6', '6', '2', '0'), +('4', '6', '6', '3', '0'), + +('4', '7', '0', '0', '0'), +('4', '7', '0', '1', '0'), +('4', '7', '0', '2', '0'), +('4', '7', '0', '3', '0'), + +('4', '7', '1', '0', '50'), +('4', '7', '1', '1', '50'), +('4', '7', '1', '2', '50'), +('4', '7', '1', '3', '50'), + +('4', '7', '2', '0', '50'), +('4', '7', '2', '1', '50'), +('4', '7', '2', '2', '50'), +('4', '7', '2', '3', '50'), + +('4', '7', '3', '0', '50'), +('4', '7', '3', '1', '50'), +('4', '7', '3', '2', '50'), +('4', '7', '3', '3', '50'), + +('4', '7', '4', '0', '25'), +('4', '7', '4', '1', '25'), +('4', '7', '4', '2', '25'), +('4', '7', '4', '3', '25'), + +('4', '7', '5', '0', '15'), +('4', '7', '5', '1', '15'), +('4', '7', '5', '2', '15'), +('4', '7', '5', '3', '15'), + +('4', '7', '6', '0', '15'), +('4', '7', '6', '1', '15'), +('4', '7', '6', '2', '15'), +('4', '7', '6', '3', '15'), + +('4', '8', '0', '0', '0'), +('4', '8', '0', '1', '0'), +('4', '8', '0', '2', '0'), +('4', '8', '0', '3', '0'), + +('4', '8', '1', '0', '0'), +('4', '8', '1', '1', '0'), +('4', '8', '1', '2', '0'), +('4', '8', '1', '3', '0'), + +('4', '8', '2', '0', '0'), +('4', '8', '2', '1', '0'), +('4', '8', '2', '2', '0'), +('4', '8', '2', '3', '0'), + +('4', '8', '3', '0', '0'), +('4', '8', '3', '1', '0'), +('4', '8', '3', '2', '0'), +('4', '8', '3', '3', '0'), + +('4', '8', '4', '0', '0'), +('4', '8', '4', '1', '0'), +('4', '8', '4', '2', '0'), +('4', '8', '4', '3', '0'), + +('4', '8', '5', '0', '0'), +('4', '8', '5', '1', '0'), +('4', '8', '5', '2', '0'), +('4', '8', '5', '3', '0'), + +('4', '8', '6', '0', '0'), +('4', '8', '6', '1', '0'), +('4', '8', '6', '2', '0'), +('4', '8', '6', '3', '0'), + +('4', '9', '0', '0', '0'), +('4', '9', '0', '1', '0'), +('4', '9', '0', '2', '0'), +('4', '9', '0', '3', '0'), + +('4', '9', '1', '0', '50'), +('4', '9', '1', '1', '50'), +('4', '9', '1', '2', '50'), +('4', '9', '1', '3', '50'), + +('4', '9', '2', '0', '50'), +('4', '9', '2', '1', '50'), +('4', '9', '2', '2', '50'), +('4', '9', '2', '3', '50'), + +('4', '9', '3', '0', '50'), +('4', '9', '3', '1', '50'), +('4', '9', '3', '2', '50'), +('4', '9', '3', '3', '50'), + +('4', '9', '4', '0', '25'), +('4', '9', '4', '1', '25'), +('4', '9', '4', '2', '25'), +('4', '9', '4', '3', '25'), + +('4', '9', '5', '0', '15'), +('4', '9', '5', '1', '15'), +('4', '9', '5', '2', '15'), +('4', '9', '5', '3', '15'), + +('4', '9', '6', '0', '15'), +('4', '9', '6', '1', '15'), +('4', '9', '6', '2', '15'), +('4', '9', '6', '3', '15'), + +('4', '10', '0', '0', '0'), +('4', '10', '0', '1', '0'), +('4', '10', '0', '2', '0'), +('4', '10', '0', '3', '0'), + +('4', '10', '1', '0', '50'), +('4', '10', '1', '1', '50'), +('4', '10', '1', '2', '50'), +('4', '10', '1', '3', '50'), + +('4', '10', '2', '0', '50'), +('4', '10', '2', '1', '50'), +('4', '10', '2', '2', '50'), +('4', '10', '2', '3', '50'), + +('4', '10', '3', '0', '50'), +('4', '10', '3', '1', '50'), +('4', '10', '3', '2', '50'), +('4', '10', '3', '3', '50'), + +('4', '10', '4', '0', '25'), +('4', '10', '4', '1', '25'), +('4', '10', '4', '2', '25'), +('4', '10', '4', '3', '25'), + +('4', '10', '5', '0', '15'), +('4', '10', '5', '1', '15'), +('4', '10', '5', '2', '15'), +('4', '10', '5', '3', '15'), + +('4', '10', '6', '0', '15'), +('4', '10', '6', '1', '15'), +('4', '10', '6', '2', '15'), +('4', '10', '6', '3', '15'), + +('4', '11', '0', '0', '0'), +('4', '11', '0', '1', '0'), +('4', '11', '0', '2', '0'), +('4', '11', '0', '3', '0'), + +('4', '11', '1', '0', '100'), +('4', '11', '1', '1', '100'), +('4', '11', '1', '2', '100'), +('4', '11', '1', '3', '100'), + +('4', '11', '2', '0', '100'), +('4', '11', '2', '1', '100'), +('4', '11', '2', '2', '100'), +('4', '11', '2', '3', '100'), + +('4', '11', '3', '0', '100'), +('4', '11', '3', '1', '100'), +('4', '11', '3', '2', '100'), +('4', '11', '3', '3', '100'), + +('4', '11', '4', '0', '50'), +('4', '11', '4', '1', '50'), +('4', '11', '4', '2', '50'), +('4', '11', '4', '3', '50'), + +('4', '11', '5', '0', '25'), +('4', '11', '5', '1', '25'), +('4', '11', '5', '2', '25'), +('4', '11', '5', '3', '25'), + +('4', '11', '6', '0', '25'), +('4', '11', '6', '1', '25'), +('4', '11', '6', '2', '25'), +('4', '11', '6', '3', '25'), + +('4', '12', '0', '0', '0'), +('4', '12', '0', '1', '0'), +('4', '12', '0', '2', '0'), +('4', '12', '0', '3', '0'), + +('4', '12', '1', '0', '50'), +('4', '12', '1', '1', '50'), +('4', '12', '1', '2', '50'), +('4', '12', '1', '3', '50'), + +('4', '12', '2', '0', '50'), +('4', '12', '2', '1', '50'), +('4', '12', '2', '2', '50'), +('4', '12', '2', '3', '50'), + +('4', '12', '3', '0', '50'), +('4', '12', '3', '1', '50'), +('4', '12', '3', '2', '50'), +('4', '12', '3', '3', '50'), + +('4', '12', '4', '0', '25'), +('4', '12', '4', '1', '25'), +('4', '12', '4', '2', '25'), +('4', '12', '4', '3', '25'), + +('4', '12', '5', '0', '15'), +('4', '12', '5', '1', '15'), +('4', '12', '5', '2', '15'), +('4', '12', '5', '3', '15'), + +('4', '12', '6', '0', '15'), +('4', '12', '6', '1', '15'), +('4', '12', '6', '2', '15'), +('4', '12', '6', '3', '15'), + +('4', '13', '0', '0', '0'), +('4', '13', '0', '1', '0'), +('4', '13', '0', '2', '0'), +('4', '13', '0', '3', '0'), + +('4', '13', '1', '0', '100'), +('4', '13', '1', '1', '100'), +('4', '13', '1', '2', '100'), +('4', '13', '1', '3', '100'), + +('4', '13', '2', '0', '100'), +('4', '13', '2', '1', '100'), +('4', '13', '2', '2', '100'), +('4', '13', '2', '3', '100'), + +('4', '13', '3', '0', '100'), +('4', '13', '3', '1', '100'), +('4', '13', '3', '2', '100'), +('4', '13', '3', '3', '100'), + +('4', '13', '4', '0', '50'), +('4', '13', '4', '1', '50'), +('4', '13', '4', '2', '50'), +('4', '13', '4', '3', '50'), + +('4', '13', '5', '0', '25'), +('4', '13', '5', '1', '25'), +('4', '13', '5', '2', '25'), +('4', '13', '5', '3', '25'), + +('4', '13', '6', '0', '25'), +('4', '13', '6', '1', '25'), +('4', '13', '6', '2', '25'), +('4', '13', '6', '3', '25'), + +('4', '14', '0', '0', '0'), +('4', '14', '0', '1', '0'), +('4', '14', '0', '2', '0'), +('4', '14', '0', '3', '0'), + +('4', '14', '1', '0', '0'), +('4', '14', '1', '1', '0'), +('4', '14', '1', '2', '0'), +('4', '14', '1', '3', '0'), + +('4', '14', '2', '0', '0'), +('4', '14', '2', '1', '0'), +('4', '14', '2', '2', '0'), +('4', '14', '2', '3', '0'), + +('4', '14', '3', '0', '0'), +('4', '14', '3', '1', '0'), +('4', '14', '3', '2', '0'), +('4', '14', '3', '3', '0'), + +('4', '14', '4', '0', '0'), +('4', '14', '4', '1', '0'), +('4', '14', '4', '2', '0'), +('4', '14', '4', '3', '0'), + +('4', '14', '5', '0', '0'), +('4', '14', '5', '1', '0'), +('4', '14', '5', '2', '0'), +('4', '14', '5', '3', '0'), + +('4', '14', '6', '0', '0'), +('4', '14', '6', '1', '0'), +('4', '14', '6', '2', '0'), +('4', '14', '6', '3', '0'), + +('4', '15', '0', '0', '0'), +('4', '15', '0', '1', '0'), +('4', '15', '0', '2', '0'), +('4', '15', '0', '3', '0'), + +('4', '15', '1', '0', '0'), +('4', '15', '1', '1', '0'), +('4', '15', '1', '2', '0'), +('4', '15', '1', '3', '0'), + +('4', '15', '2', '0', '0'), +('4', '15', '2', '1', '0'), +('4', '15', '2', '2', '0'), +('4', '15', '2', '3', '0'), + +('4', '15', '3', '0', '0'), +('4', '15', '3', '1', '0'), +('4', '15', '3', '2', '0'), +('4', '15', '3', '3', '0'), + +('4', '15', '4', '0', '0'), +('4', '15', '4', '1', '0'), +('4', '15', '4', '2', '0'), +('4', '15', '4', '3', '0'), + +('4', '15', '5', '0', '0'), +('4', '15', '5', '1', '0'), +('4', '15', '5', '2', '0'), +('4', '15', '5', '3', '0'), + +('4', '15', '6', '0', '0'), +('4', '15', '6', '1', '0'), +('4', '15', '6', '2', '0'), +('4', '15', '6', '3', '0'), + +-- SpellType_PetIndex + +('5', '0', '0', '0', '0'), +('5', '0', '0', '1', '0'), +('5', '0', '0', '2', '0'), +('5', '0', '0', '3', '0'), + +('5', '0', '1', '0', '0'), +('5', '0', '1', '1', '0'), +('5', '0', '1', '2', '0'), +('5', '0', '1', '3', '0'), + +('5', '0', '2', '0', '0'), +('5', '0', '2', '1', '0'), +('5', '0', '2', '2', '0'), +('5', '0', '2', '3', '0'), + +('5', '0', '3', '0', '0'), +('5', '0', '3', '1', '0'), +('5', '0', '3', '2', '0'), +('5', '0', '3', '3', '0'), + +('5', '0', '4', '0', '0'), +('5', '0', '4', '1', '0'), +('5', '0', '4', '2', '0'), +('5', '0', '4', '3', '0'), + +('5', '0', '5', '0', '0'), +('5', '0', '5', '1', '0'), +('5', '0', '5', '2', '0'), +('5', '0', '5', '3', '0'), + +('5', '0', '6', '0', '0'), +('5', '0', '6', '1', '0'), +('5', '0', '6', '2', '0'), +('5', '0', '6', '3', '0'), + +('5', '1', '0', '0', '0'), +('5', '1', '0', '1', '0'), +('5', '1', '0', '2', '0'), +('5', '1', '0', '3', '0'), + +('5', '1', '1', '0', '0'), +('5', '1', '1', '1', '0'), +('5', '1', '1', '2', '0'), +('5', '1', '1', '3', '0'), + +('5', '1', '2', '0', '0'), +('5', '1', '2', '1', '0'), +('5', '1', '2', '2', '0'), +('5', '1', '2', '3', '0'), + +('5', '1', '3', '0', '0'), +('5', '1', '3', '1', '0'), +('5', '1', '3', '2', '0'), +('5', '1', '3', '3', '0'), + +('5', '1', '4', '0', '0'), +('5', '1', '4', '1', '0'), +('5', '1', '4', '2', '0'), +('5', '1', '4', '3', '0'), + +('5', '1', '5', '0', '0'), +('5', '1', '5', '1', '0'), +('5', '1', '5', '2', '0'), +('5', '1', '5', '3', '0'), + +('5', '1', '6', '0', '0'), +('5', '1', '6', '1', '0'), +('5', '1', '6', '2', '0'), +('5', '1', '6', '3', '0'), + +('5', '2', '0', '0', '0'), +('5', '2', '0', '1', '0'), +('5', '2', '0', '2', '0'), +('5', '2', '0', '3', '0'), + +('5', '2', '1', '0', '0'), +('5', '2', '1', '1', '0'), +('5', '2', '1', '2', '0'), +('5', '2', '1', '3', '0'), + +('5', '2', '2', '0', '0'), +('5', '2', '2', '1', '0'), +('5', '2', '2', '2', '0'), +('5', '2', '2', '3', '0'), + +('5', '2', '3', '0', '0'), +('5', '2', '3', '1', '0'), +('5', '2', '3', '2', '0'), +('5', '2', '3', '3', '0'), + +('5', '2', '4', '0', '0'), +('5', '2', '4', '1', '0'), +('5', '2', '4', '2', '0'), +('5', '2', '4', '3', '0'), + +('5', '2', '5', '0', '0'), +('5', '2', '5', '1', '0'), +('5', '2', '5', '2', '0'), +('5', '2', '5', '3', '0'), + +('5', '2', '6', '0', '0'), +('5', '2', '6', '1', '0'), +('5', '2', '6', '2', '0'), +('5', '2', '6', '3', '0'), + +('5', '3', '0', '0', '0'), +('5', '3', '0', '1', '0'), +('5', '3', '0', '2', '0'), +('5', '3', '0', '3', '0'), + +('5', '3', '1', '0', '0'), +('5', '3', '1', '1', '0'), +('5', '3', '1', '2', '0'), +('5', '3', '1', '3', '0'), + +('5', '3', '2', '0', '0'), +('5', '3', '2', '1', '0'), +('5', '3', '2', '2', '0'), +('5', '3', '2', '3', '0'), + +('5', '3', '3', '0', '0'), +('5', '3', '3', '1', '0'), +('5', '3', '3', '2', '0'), +('5', '3', '3', '3', '0'), + +('5', '3', '4', '0', '0'), +('5', '3', '4', '1', '0'), +('5', '3', '4', '2', '0'), +('5', '3', '4', '3', '0'), + +('5', '3', '5', '0', '0'), +('5', '3', '5', '1', '0'), +('5', '3', '5', '2', '0'), +('5', '3', '5', '3', '0'), + +('5', '3', '6', '0', '0'), +('5', '3', '6', '1', '0'), +('5', '3', '6', '2', '0'), +('5', '3', '6', '3', '0'), + +('5', '4', '0', '0', '0'), +('5', '4', '0', '1', '0'), +('5', '4', '0', '2', '0'), +('5', '4', '0', '3', '0'), + +('5', '4', '1', '0', '25'), +('5', '4', '1', '1', '25'), +('5', '4', '1', '2', '25'), +('5', '4', '1', '3', '25'), + +('5', '4', '2', '0', '10'), +('5', '4', '2', '1', '10'), +('5', '4', '2', '2', '10'), +('5', '4', '2', '3', '10'), + +('5', '4', '3', '0', '25'), +('5', '4', '3', '1', '25'), +('5', '4', '3', '2', '25'), +('5', '4', '3', '3', '25'), + +('5', '4', '4', '0', '10'), +('5', '4', '4', '1', '10'), +('5', '4', '4', '2', '10'), +('5', '4', '4', '3', '10'), + +('5', '4', '5', '0', '10'), +('5', '4', '5', '1', '10'), +('5', '4', '5', '2', '10'), +('5', '4', '5', '3', '10'), + +('5', '4', '6', '0', '10'), +('5', '4', '6', '1', '10'), +('5', '4', '6', '2', '10'), +('5', '4', '6', '3', '10'), + +('5', '5', '0', '0', '0'), +('5', '5', '0', '1', '0'), +('5', '5', '0', '2', '0'), +('5', '5', '0', '3', '0'), + +('5', '5', '1', '0', '25'), +('5', '5', '1', '1', '25'), +('5', '5', '1', '2', '25'), +('5', '5', '1', '3', '25'), + +('5', '5', '2', '0', '10'), +('5', '5', '2', '1', '10'), +('5', '5', '2', '2', '10'), +('5', '5', '2', '3', '10'), + +('5', '5', '3', '0', '25'), +('5', '5', '3', '1', '25'), +('5', '5', '3', '2', '25'), +('5', '5', '3', '3', '25'), + +('5', '5', '4', '0', '10'), +('5', '5', '4', '1', '10'), +('5', '5', '4', '2', '10'), +('5', '5', '4', '3', '10'), + +('5', '5', '5', '0', '10'), +('5', '5', '5', '1', '10'), +('5', '5', '5', '2', '10'), +('5', '5', '5', '3', '10'), + +('5', '5', '6', '0', '10'), +('5', '5', '6', '1', '10'), +('5', '5', '6', '2', '10'), +('5', '5', '6', '3', '10'), + +('5', '6', '0', '0', '0'), +('5', '6', '0', '1', '0'), +('5', '6', '0', '2', '0'), +('5', '6', '0', '3', '0'), + +('5', '6', '1', '0', '0'), +('5', '6', '1', '1', '0'), +('5', '6', '1', '2', '0'), +('5', '6', '1', '3', '0'), + +('5', '6', '2', '0', '0'), +('5', '6', '2', '1', '0'), +('5', '6', '2', '2', '0'), +('5', '6', '2', '3', '0'), + +('5', '6', '3', '0', '0'), +('5', '6', '3', '1', '0'), +('5', '6', '3', '2', '0'), +('5', '6', '3', '3', '0'), + +('5', '6', '4', '0', '0'), +('5', '6', '4', '1', '0'), +('5', '6', '4', '2', '0'), +('5', '6', '4', '3', '0'), + +('5', '6', '5', '0', '0'), +('5', '6', '5', '1', '0'), +('5', '6', '5', '2', '0'), +('5', '6', '5', '3', '0'), + +('5', '6', '6', '0', '0'), +('5', '6', '6', '1', '0'), +('5', '6', '6', '2', '0'), +('5', '6', '6', '3', '0'), + +('5', '7', '0', '0', '0'), +('5', '7', '0', '1', '0'), +('5', '7', '0', '2', '0'), +('5', '7', '0', '3', '0'), + +('5', '7', '1', '0', '0'), +('5', '7', '1', '1', '0'), +('5', '7', '1', '2', '0'), +('5', '7', '1', '3', '0'), + +('5', '7', '2', '0', '0'), +('5', '7', '2', '1', '0'), +('5', '7', '2', '2', '0'), +('5', '7', '2', '3', '0'), + +('5', '7', '3', '0', '0'), +('5', '7', '3', '1', '0'), +('5', '7', '3', '2', '0'), +('5', '7', '3', '3', '0'), + +('5', '7', '4', '0', '0'), +('5', '7', '4', '1', '0'), +('5', '7', '4', '2', '0'), +('5', '7', '4', '3', '0'), + +('5', '7', '5', '0', '0'), +('5', '7', '5', '1', '0'), +('5', '7', '5', '2', '0'), +('5', '7', '5', '3', '0'), + +('5', '7', '6', '0', '0'), +('5', '7', '6', '1', '0'), +('5', '7', '6', '2', '0'), +('5', '7', '6', '3', '0'), + +('5', '8', '0', '0', '0'), +('5', '8', '0', '1', '0'), +('5', '8', '0', '2', '0'), +('5', '8', '0', '3', '0'), + +('5', '8', '1', '0', '0'), +('5', '8', '1', '1', '0'), +('5', '8', '1', '2', '0'), +('5', '8', '1', '3', '0'), + +('5', '8', '2', '0', '0'), +('5', '8', '2', '1', '0'), +('5', '8', '2', '2', '0'), +('5', '8', '2', '3', '0'), + +('5', '8', '3', '0', '0'), +('5', '8', '3', '1', '0'), +('5', '8', '3', '2', '0'), +('5', '8', '3', '3', '0'), + +('5', '8', '4', '0', '0'), +('5', '8', '4', '1', '0'), +('5', '8', '4', '2', '0'), +('5', '8', '4', '3', '0'), + +('5', '8', '5', '0', '0'), +('5', '8', '5', '1', '0'), +('5', '8', '5', '2', '0'), +('5', '8', '5', '3', '0'), + +('5', '8', '6', '0', '0'), +('5', '8', '6', '1', '0'), +('5', '8', '6', '2', '0'), +('5', '8', '6', '3', '0'), + +('5', '9', '0', '0', '0'), +('5', '9', '0', '1', '0'), +('5', '9', '0', '2', '0'), +('5', '9', '0', '3', '0'), + +('5', '9', '1', '0', '25'), +('5', '9', '1', '1', '25'), +('5', '9', '1', '2', '25'), +('5', '9', '1', '3', '25'), + +('5', '9', '2', '0', '10'), +('5', '9', '2', '1', '10'), +('5', '9', '2', '2', '10'), +('5', '9', '2', '3', '10'), + +('5', '9', '3', '0', '25'), +('5', '9', '3', '1', '25'), +('5', '9', '3', '2', '25'), +('5', '9', '3', '3', '25'), + +('5', '9', '4', '0', '10'), +('5', '9', '4', '1', '10'), +('5', '9', '4', '2', '10'), +('5', '9', '4', '3', '10'), + +('5', '9', '5', '0', '10'), +('5', '9', '5', '1', '10'), +('5', '9', '5', '2', '10'), +('5', '9', '5', '3', '10'), + +('5', '9', '6', '0', '10'), +('5', '9', '6', '1', '10'), +('5', '9', '6', '2', '10'), +('5', '9', '6', '3', '10'), + +('5', '10', '0', '0', '0'), +('5', '10', '0', '1', '0'), +('5', '10', '0', '2', '0'), +('5', '10', '0', '3', '0'), + +('5', '10', '1', '0', '100'), +('5', '10', '1', '1', '100'), +('5', '10', '1', '2', '100'), +('5', '10', '1', '3', '100'), + +('5', '10', '2', '0', '50'), +('5', '10', '2', '1', '50'), +('5', '10', '2', '2', '50'), +('5', '10', '2', '3', '50'), + +('5', '10', '3', '0', '100'), +('5', '10', '3', '1', '100'), +('5', '10', '3', '2', '100'), +('5', '10', '3', '3', '100'), + +('5', '10', '4', '0', '50'), +('5', '10', '4', '1', '50'), +('5', '10', '4', '2', '50'), +('5', '10', '4', '3', '50'), + +('5', '10', '5', '0', '25'), +('5', '10', '5', '1', '25'), +('5', '10', '5', '2', '25'), +('5', '10', '5', '3', '25'), + +('5', '10', '6', '0', '25'), +('5', '10', '6', '1', '25'), +('5', '10', '6', '2', '25'), +('5', '10', '6', '3', '25'), + +('5', '11', '0', '0', '0'), +('5', '11', '0', '1', '0'), +('5', '11', '0', '2', '0'), +('5', '11', '0', '3', '0'), + +('5', '11', '1', '0', '0'), +('5', '11', '1', '1', '0'), +('5', '11', '1', '2', '0'), +('5', '11', '1', '3', '0'), + +('5', '11', '2', '0', '0'), +('5', '11', '2', '1', '0'), +('5', '11', '2', '2', '0'), +('5', '11', '2', '3', '0'), + +('5', '11', '3', '0', '0'), +('5', '11', '3', '1', '0'), +('5', '11', '3', '2', '0'), +('5', '11', '3', '3', '0'), + +('5', '11', '4', '0', '0'), +('5', '11', '4', '1', '0'), +('5', '11', '4', '2', '0'), +('5', '11', '4', '3', '0'), + +('5', '11', '5', '0', '0'), +('5', '11', '5', '1', '0'), +('5', '11', '5', '2', '0'), +('5', '11', '5', '3', '0'), + +('5', '11', '6', '0', '0'), +('5', '11', '6', '1', '0'), +('5', '11', '6', '2', '0'), +('5', '11', '6', '3', '0'), + +('5', '12', '0', '0', '0'), +('5', '12', '0', '1', '0'), +('5', '12', '0', '2', '0'), +('5', '12', '0', '3', '0'), + +('5', '12', '1', '0', '100'), +('5', '12', '1', '1', '100'), +('5', '12', '1', '2', '100'), +('5', '12', '1', '3', '100'), + +('5', '12', '2', '0', '50'), +('5', '12', '2', '1', '50'), +('5', '12', '2', '2', '50'), +('5', '12', '2', '3', '50'), + +('5', '12', '3', '0', '100'), +('5', '12', '3', '1', '100'), +('5', '12', '3', '2', '100'), +('5', '12', '3', '3', '100'), + +('5', '12', '4', '0', '50'), +('5', '12', '4', '1', '50'), +('5', '12', '4', '2', '50'), +('5', '12', '4', '3', '50'), + +('5', '12', '5', '0', '25'), +('5', '12', '5', '1', '25'), +('5', '12', '5', '2', '25'), +('5', '12', '5', '3', '25'), + +('5', '12', '6', '0', '25'), +('5', '12', '6', '1', '25'), +('5', '12', '6', '2', '25'), +('5', '12', '6', '3', '25'), + +('5', '13', '0', '0', '0'), +('5', '13', '0', '1', '0'), +('5', '13', '0', '2', '0'), +('5', '13', '0', '3', '0'), + +('5', '13', '1', '0', '25'), +('5', '13', '1', '1', '25'), +('5', '13', '1', '2', '25'), +('5', '13', '1', '3', '25'), + +('5', '13', '2', '0', '10'), +('5', '13', '2', '1', '10'), +('5', '13', '2', '2', '10'), +('5', '13', '2', '3', '10'), + +('5', '13', '3', '0', '25'), +('5', '13', '3', '1', '25'), +('5', '13', '3', '2', '25'), +('5', '13', '3', '3', '25'), + +('5', '13', '4', '0', '10'), +('5', '13', '4', '1', '10'), +('5', '13', '4', '2', '10'), +('5', '13', '4', '3', '10'), + +('5', '13', '5', '0', '10'), +('5', '13', '5', '1', '10'), +('5', '13', '5', '2', '10'), +('5', '13', '5', '3', '10'), + +('5', '13', '6', '0', '10'), +('5', '13', '6', '1', '10'), +('5', '13', '6', '2', '10'), +('5', '13', '6', '3', '10'), + +('5', '14', '0', '0', '0'), +('5', '14', '0', '1', '0'), +('5', '14', '0', '2', '0'), +('5', '14', '0', '3', '0'), + +('5', '14', '1', '0', '100'), +('5', '14', '1', '1', '100'), +('5', '14', '1', '2', '100'), +('5', '14', '1', '3', '100'), + +('5', '14', '2', '0', '50'), +('5', '14', '2', '1', '50'), +('5', '14', '2', '2', '50'), +('5', '14', '2', '3', '50'), + +('5', '14', '3', '0', '100'), +('5', '14', '3', '1', '100'), +('5', '14', '3', '2', '100'), +('5', '14', '3', '3', '100'), + +('5', '14', '4', '0', '50'), +('5', '14', '4', '1', '50'), +('5', '14', '4', '2', '50'), +('5', '14', '4', '3', '50'), + +('5', '14', '5', '0', '25'), +('5', '14', '5', '1', '25'), +('5', '14', '5', '2', '25'), +('5', '14', '5', '3', '25'), + +('5', '14', '6', '0', '25'), +('5', '14', '6', '1', '25'), +('5', '14', '6', '2', '25'), +('5', '14', '6', '3', '25'), + +('5', '15', '0', '0', '0'), +('5', '15', '0', '1', '0'), +('5', '15', '0', '2', '0'), +('5', '15', '0', '3', '0'), + +('5', '15', '1', '0', '0'), +('5', '15', '1', '1', '0'), +('5', '15', '1', '2', '0'), +('5', '15', '1', '3', '0'), + +('5', '15', '2', '0', '0'), +('5', '15', '2', '1', '0'), +('5', '15', '2', '2', '0'), +('5', '15', '2', '3', '0'), + +('5', '15', '3', '0', '0'), +('5', '15', '3', '1', '0'), +('5', '15', '3', '2', '0'), +('5', '15', '3', '3', '0'), + +('5', '15', '4', '0', '0'), +('5', '15', '4', '1', '0'), +('5', '15', '4', '2', '0'), +('5', '15', '4', '3', '0'), + +('5', '15', '5', '0', '0'), +('5', '15', '5', '1', '0'), +('5', '15', '5', '2', '0'), +('5', '15', '5', '3', '0'), + +('5', '15', '6', '0', '0'), +('5', '15', '6', '1', '0'), +('5', '15', '6', '2', '0'), +('5', '15', '6', '3', '0'), + +-- SpellType_LifetapIndex + +('6', '0', '0', '0', '0'), +('6', '0', '0', '1', '0'), +('6', '0', '0', '2', '0'), +('6', '0', '0', '3', '0'), + +('6', '0', '1', '0', '0'), +('6', '0', '1', '1', '0'), +('6', '0', '1', '2', '0'), +('6', '0', '1', '3', '0'), + +('6', '0', '2', '0', '0'), +('6', '0', '2', '1', '0'), +('6', '0', '2', '2', '0'), +('6', '0', '2', '3', '0'), + +('6', '0', '3', '0', '0'), +('6', '0', '3', '1', '0'), +('6', '0', '3', '2', '0'), +('6', '0', '3', '3', '0'), + +('6', '0', '4', '0', '0'), +('6', '0', '4', '1', '0'), +('6', '0', '4', '2', '0'), +('6', '0', '4', '3', '0'), + +('6', '0', '5', '0', '0'), +('6', '0', '5', '1', '0'), +('6', '0', '5', '2', '0'), +('6', '0', '5', '3', '0'), + +('6', '0', '6', '0', '0'), +('6', '0', '6', '1', '0'), +('6', '0', '6', '2', '0'), +('6', '0', '6', '3', '0'), + +('6', '1', '0', '0', '0'), +('6', '1', '0', '1', '0'), +('6', '1', '0', '2', '0'), +('6', '1', '0', '3', '0'), + +('6', '1', '1', '0', '0'), +('6', '1', '1', '1', '0'), +('6', '1', '1', '2', '0'), +('6', '1', '1', '3', '0'), + +('6', '1', '2', '0', '0'), +('6', '1', '2', '1', '0'), +('6', '1', '2', '2', '0'), +('6', '1', '2', '3', '0'), + +('6', '1', '3', '0', '0'), +('6', '1', '3', '1', '0'), +('6', '1', '3', '2', '0'), +('6', '1', '3', '3', '0'), + +('6', '1', '4', '0', '0'), +('6', '1', '4', '1', '0'), +('6', '1', '4', '2', '0'), +('6', '1', '4', '3', '0'), + +('6', '1', '5', '0', '0'), +('6', '1', '5', '1', '0'), +('6', '1', '5', '2', '0'), +('6', '1', '5', '3', '0'), + +('6', '1', '6', '0', '0'), +('6', '1', '6', '1', '0'), +('6', '1', '6', '2', '0'), +('6', '1', '6', '3', '0'), + +('6', '2', '0', '0', '0'), +('6', '2', '0', '1', '0'), +('6', '2', '0', '2', '0'), +('6', '2', '0', '3', '0'), + +('6', '2', '1', '0', '0'), +('6', '2', '1', '1', '0'), +('6', '2', '1', '2', '0'), +('6', '2', '1', '3', '0'), + +('6', '2', '2', '0', '0'), +('6', '2', '2', '1', '0'), +('6', '2', '2', '2', '0'), +('6', '2', '2', '3', '0'), + +('6', '2', '3', '0', '0'), +('6', '2', '3', '1', '0'), +('6', '2', '3', '2', '0'), +('6', '2', '3', '3', '0'), + +('6', '2', '4', '0', '0'), +('6', '2', '4', '1', '0'), +('6', '2', '4', '2', '0'), +('6', '2', '4', '3', '0'), + +('6', '2', '5', '0', '0'), +('6', '2', '5', '1', '0'), +('6', '2', '5', '2', '0'), +('6', '2', '5', '3', '0'), + +('6', '2', '6', '0', '0'), +('6', '2', '6', '1', '0'), +('6', '2', '6', '2', '0'), +('6', '2', '6', '3', '0'), + +('6', '3', '0', '0', '0'), +('6', '3', '0', '1', '0'), +('6', '3', '0', '2', '0'), +('6', '3', '0', '3', '0'), + +('6', '3', '1', '0', '0'), +('6', '3', '1', '1', '0'), +('6', '3', '1', '2', '0'), +('6', '3', '1', '3', '0'), + +('6', '3', '2', '0', '0'), +('6', '3', '2', '1', '0'), +('6', '3', '2', '2', '0'), +('6', '3', '2', '3', '0'), + +('6', '3', '3', '0', '0'), +('6', '3', '3', '1', '0'), +('6', '3', '3', '2', '0'), +('6', '3', '3', '3', '0'), + +('6', '3', '4', '0', '0'), +('6', '3', '4', '1', '0'), +('6', '3', '4', '2', '0'), +('6', '3', '4', '3', '0'), + +('6', '3', '5', '0', '0'), +('6', '3', '5', '1', '0'), +('6', '3', '5', '2', '0'), +('6', '3', '5', '3', '0'), + +('6', '3', '6', '0', '0'), +('6', '3', '6', '1', '0'), +('6', '3', '6', '2', '0'), +('6', '3', '6', '3', '0'), + +('6', '4', '0', '0', '0'), +('6', '4', '0', '1', '0'), +('6', '4', '0', '2', '0'), +('6', '4', '0', '3', '0'), + +('6', '4', '1', '0', '50'), +('6', '4', '1', '1', '50'), +('6', '4', '1', '2', '50'), +('6', '4', '1', '3', '50'), + +('6', '4', '2', '0', '50'), +('6', '4', '2', '1', '50'), +('6', '4', '2', '2', '50'), +('6', '4', '2', '3', '50'), + +('6', '4', '3', '0', '50'), +('6', '4', '3', '1', '50'), +('6', '4', '3', '2', '50'), +('6', '4', '3', '3', '50'), + +('6', '4', '4', '0', '50'), +('6', '4', '4', '1', '50'), +('6', '4', '4', '2', '50'), +('6', '4', '4', '3', '50'), + +('6', '4', '5', '0', '100'), +('6', '4', '5', '1', '100'), +('6', '4', '5', '2', '100'), +('6', '4', '5', '3', '100'), + +('6', '4', '6', '0', '100'), +('6', '4', '6', '1', '100'), +('6', '4', '6', '2', '100'), +('6', '4', '6', '3', '100'), + +('6', '5', '0', '0', '0'), +('6', '5', '0', '1', '0'), +('6', '5', '0', '2', '0'), +('6', '5', '0', '3', '0'), + +('6', '5', '1', '0', '0'), +('6', '5', '1', '1', '0'), +('6', '5', '1', '2', '0'), +('6', '5', '1', '3', '0'), + +('6', '5', '2', '0', '0'), +('6', '5', '2', '1', '0'), +('6', '5', '2', '2', '0'), +('6', '5', '2', '3', '0'), + +('6', '5', '3', '0', '0'), +('6', '5', '3', '1', '0'), +('6', '5', '3', '2', '0'), +('6', '5', '3', '3', '0'), + +('6', '5', '4', '0', '0'), +('6', '5', '4', '1', '0'), +('6', '5', '4', '2', '0'), +('6', '5', '4', '3', '0'), + +('6', '5', '5', '0', '0'), +('6', '5', '5', '1', '0'), +('6', '5', '5', '2', '0'), +('6', '5', '5', '3', '0'), + +('6', '5', '6', '0', '0'), +('6', '5', '6', '1', '0'), +('6', '5', '6', '2', '0'), +('6', '5', '6', '3', '0'), + +('6', '6', '0', '0', '0'), +('6', '6', '0', '1', '0'), +('6', '6', '0', '2', '0'), +('6', '6', '0', '3', '0'), + +('6', '6', '1', '0', '0'), +('6', '6', '1', '1', '0'), +('6', '6', '1', '2', '0'), +('6', '6', '1', '3', '0'), + +('6', '6', '2', '0', '0'), +('6', '6', '2', '1', '0'), +('6', '6', '2', '2', '0'), +('6', '6', '2', '3', '0'), + +('6', '6', '3', '0', '0'), +('6', '6', '3', '1', '0'), +('6', '6', '3', '2', '0'), +('6', '6', '3', '3', '0'), + +('6', '6', '4', '0', '0'), +('6', '6', '4', '1', '0'), +('6', '6', '4', '2', '0'), +('6', '6', '4', '3', '0'), + +('6', '6', '5', '0', '0'), +('6', '6', '5', '1', '0'), +('6', '6', '5', '2', '0'), +('6', '6', '5', '3', '0'), + +('6', '6', '6', '0', '0'), +('6', '6', '6', '1', '0'), +('6', '6', '6', '2', '0'), +('6', '6', '6', '3', '0'), + +('6', '7', '0', '0', '0'), +('6', '7', '0', '1', '0'), +('6', '7', '0', '2', '0'), +('6', '7', '0', '3', '0'), + +('6', '7', '1', '0', '0'), +('6', '7', '1', '1', '0'), +('6', '7', '1', '2', '0'), +('6', '7', '1', '3', '0'), + +('6', '7', '2', '0', '0'), +('6', '7', '2', '1', '0'), +('6', '7', '2', '2', '0'), +('6', '7', '2', '3', '0'), + +('6', '7', '3', '0', '0'), +('6', '7', '3', '1', '0'), +('6', '7', '3', '2', '0'), +('6', '7', '3', '3', '0'), + +('6', '7', '4', '0', '0'), +('6', '7', '4', '1', '0'), +('6', '7', '4', '2', '0'), +('6', '7', '4', '3', '0'), + +('6', '7', '5', '0', '0'), +('6', '7', '5', '1', '0'), +('6', '7', '5', '2', '0'), +('6', '7', '5', '3', '0'), + +('6', '7', '6', '0', '0'), +('6', '7', '6', '1', '0'), +('6', '7', '6', '2', '0'), +('6', '7', '6', '3', '0'), + +('6', '8', '0', '0', '0'), +('6', '8', '0', '1', '0'), +('6', '8', '0', '2', '0'), +('6', '8', '0', '3', '0'), + +('6', '8', '1', '0', '0'), +('6', '8', '1', '1', '0'), +('6', '8', '1', '2', '0'), +('6', '8', '1', '3', '0'), + +('6', '8', '2', '0', '0'), +('6', '8', '2', '1', '0'), +('6', '8', '2', '2', '0'), +('6', '8', '2', '3', '0'), + +('6', '8', '3', '0', '0'), +('6', '8', '3', '1', '0'), +('6', '8', '3', '2', '0'), +('6', '8', '3', '3', '0'), + +('6', '8', '4', '0', '0'), +('6', '8', '4', '1', '0'), +('6', '8', '4', '2', '0'), +('6', '8', '4', '3', '0'), + +('6', '8', '5', '0', '0'), +('6', '8', '5', '1', '0'), +('6', '8', '5', '2', '0'), +('6', '8', '5', '3', '0'), + +('6', '8', '6', '0', '0'), +('6', '8', '6', '1', '0'), +('6', '8', '6', '2', '0'), +('6', '8', '6', '3', '0'), + +('6', '9', '0', '0', '0'), +('6', '9', '0', '1', '0'), +('6', '9', '0', '2', '0'), +('6', '9', '0', '3', '0'), + +('6', '9', '1', '0', '0'), +('6', '9', '1', '1', '0'), +('6', '9', '1', '2', '0'), +('6', '9', '1', '3', '0'), + +('6', '9', '2', '0', '0'), +('6', '9', '2', '1', '0'), +('6', '9', '2', '2', '0'), +('6', '9', '2', '3', '0'), + +('6', '9', '3', '0', '0'), +('6', '9', '3', '1', '0'), +('6', '9', '3', '2', '0'), +('6', '9', '3', '3', '0'), + +('6', '9', '4', '0', '0'), +('6', '9', '4', '1', '0'), +('6', '9', '4', '2', '0'), +('6', '9', '4', '3', '0'), + +('6', '9', '5', '0', '0'), +('6', '9', '5', '1', '0'), +('6', '9', '5', '2', '0'), +('6', '9', '5', '3', '0'), + +('6', '9', '6', '0', '0'), +('6', '9', '6', '1', '0'), +('6', '9', '6', '2', '0'), +('6', '9', '6', '3', '0'), + +('6', '10', '0', '0', '0'), +('6', '10', '0', '1', '0'), +('6', '10', '0', '2', '0'), +('6', '10', '0', '3', '0'), + +('6', '10', '1', '0', '50'), +('6', '10', '1', '1', '50'), +('6', '10', '1', '2', '50'), +('6', '10', '1', '3', '50'), + +('6', '10', '2', '0', '50'), +('6', '10', '2', '1', '50'), +('6', '10', '2', '2', '50'), +('6', '10', '2', '3', '50'), + +('6', '10', '3', '0', '50'), +('6', '10', '3', '1', '50'), +('6', '10', '3', '2', '50'), +('6', '10', '3', '3', '50'), + +('6', '10', '4', '0', '50'), +('6', '10', '4', '1', '50'), +('6', '10', '4', '2', '50'), +('6', '10', '4', '3', '50'), + +('6', '10', '5', '0', '100'), +('6', '10', '5', '1', '100'), +('6', '10', '5', '2', '100'), +('6', '10', '5', '3', '100'), + +('6', '10', '6', '0', '100'), +('6', '10', '6', '1', '100'), +('6', '10', '6', '2', '100'), +('6', '10', '6', '3', '100'), + +('6', '11', '0', '0', '0'), +('6', '11', '0', '1', '0'), +('6', '11', '0', '2', '0'), +('6', '11', '0', '3', '0'), + +('6', '11', '1', '0', '0'), +('6', '11', '1', '1', '0'), +('6', '11', '1', '2', '0'), +('6', '11', '1', '3', '0'), + +('6', '11', '2', '0', '0'), +('6', '11', '2', '1', '0'), +('6', '11', '2', '2', '0'), +('6', '11', '2', '3', '0'), + +('6', '11', '3', '0', '0'), +('6', '11', '3', '1', '0'), +('6', '11', '3', '2', '0'), +('6', '11', '3', '3', '0'), + +('6', '11', '4', '0', '0'), +('6', '11', '4', '1', '0'), +('6', '11', '4', '2', '0'), +('6', '11', '4', '3', '0'), + +('6', '11', '5', '0', '0'), +('6', '11', '5', '1', '0'), +('6', '11', '5', '2', '0'), +('6', '11', '5', '3', '0'), + +('6', '11', '6', '0', '0'), +('6', '11', '6', '1', '0'), +('6', '11', '6', '2', '0'), +('6', '11', '6', '3', '0'), + +('6', '12', '0', '0', '0'), +('6', '12', '0', '1', '0'), +('6', '12', '0', '2', '0'), +('6', '12', '0', '3', '0'), + +('6', '12', '1', '0', '0'), +('6', '12', '1', '1', '0'), +('6', '12', '1', '2', '0'), +('6', '12', '1', '3', '0'), + +('6', '12', '2', '0', '0'), +('6', '12', '2', '1', '0'), +('6', '12', '2', '2', '0'), +('6', '12', '2', '3', '0'), + +('6', '12', '3', '0', '0'), +('6', '12', '3', '1', '0'), +('6', '12', '3', '2', '0'), +('6', '12', '3', '3', '0'), + +('6', '12', '4', '0', '0'), +('6', '12', '4', '1', '0'), +('6', '12', '4', '2', '0'), +('6', '12', '4', '3', '0'), + +('6', '12', '5', '0', '0'), +('6', '12', '5', '1', '0'), +('6', '12', '5', '2', '0'), +('6', '12', '5', '3', '0'), + +('6', '12', '6', '0', '0'), +('6', '12', '6', '1', '0'), +('6', '12', '6', '2', '0'), +('6', '12', '6', '3', '0'), + +('6', '13', '0', '0', '0'), +('6', '13', '0', '1', '0'), +('6', '13', '0', '2', '0'), +('6', '13', '0', '3', '0'), + +('6', '13', '1', '0', '0'), +('6', '13', '1', '1', '0'), +('6', '13', '1', '2', '0'), +('6', '13', '1', '3', '0'), + +('6', '13', '2', '0', '0'), +('6', '13', '2', '1', '0'), +('6', '13', '2', '2', '0'), +('6', '13', '2', '3', '0'), + +('6', '13', '3', '0', '0'), +('6', '13', '3', '1', '0'), +('6', '13', '3', '2', '0'), +('6', '13', '3', '3', '0'), + +('6', '13', '4', '0', '0'), +('6', '13', '4', '1', '0'), +('6', '13', '4', '2', '0'), +('6', '13', '4', '3', '0'), + +('6', '13', '5', '0', '0'), +('6', '13', '5', '1', '0'), +('6', '13', '5', '2', '0'), +('6', '13', '5', '3', '0'), + +('6', '13', '6', '0', '0'), +('6', '13', '6', '1', '0'), +('6', '13', '6', '2', '0'), +('6', '13', '6', '3', '0'), + +('6', '14', '0', '0', '0'), +('6', '14', '0', '1', '0'), +('6', '14', '0', '2', '0'), +('6', '14', '0', '3', '0'), + +('6', '14', '1', '0', '0'), +('6', '14', '1', '1', '0'), +('6', '14', '1', '2', '0'), +('6', '14', '1', '3', '0'), + +('6', '14', '2', '0', '0'), +('6', '14', '2', '1', '0'), +('6', '14', '2', '2', '0'), +('6', '14', '2', '3', '0'), + +('6', '14', '3', '0', '0'), +('6', '14', '3', '1', '0'), +('6', '14', '3', '2', '0'), +('6', '14', '3', '3', '0'), + +('6', '14', '4', '0', '0'), +('6', '14', '4', '1', '0'), +('6', '14', '4', '2', '0'), +('6', '14', '4', '3', '0'), + +('6', '14', '5', '0', '0'), +('6', '14', '5', '1', '0'), +('6', '14', '5', '2', '0'), +('6', '14', '5', '3', '0'), + +('6', '14', '6', '0', '0'), +('6', '14', '6', '1', '0'), +('6', '14', '6', '2', '0'), +('6', '14', '6', '3', '0'), + +('6', '15', '0', '0', '0'), +('6', '15', '0', '1', '0'), +('6', '15', '0', '2', '0'), +('6', '15', '0', '3', '0'), + +('6', '15', '1', '0', '0'), +('6', '15', '1', '1', '0'), +('6', '15', '1', '2', '0'), +('6', '15', '1', '3', '0'), + +('6', '15', '2', '0', '0'), +('6', '15', '2', '1', '0'), +('6', '15', '2', '2', '0'), +('6', '15', '2', '3', '0'), + +('6', '15', '3', '0', '0'), +('6', '15', '3', '1', '0'), +('6', '15', '3', '2', '0'), +('6', '15', '3', '3', '0'), + +('6', '15', '4', '0', '0'), +('6', '15', '4', '1', '0'), +('6', '15', '4', '2', '0'), +('6', '15', '4', '3', '0'), + +('6', '15', '5', '0', '0'), +('6', '15', '5', '1', '0'), +('6', '15', '5', '2', '0'), +('6', '15', '5', '3', '0'), + +('6', '15', '6', '0', '0'), +('6', '15', '6', '1', '0'), +('6', '15', '6', '2', '0'), +('6', '15', '6', '3', '0'), + +-- SpellType_SnareIndex + +('7', '0', '0', '0', '0'), +('7', '0', '0', '1', '0'), +('7', '0', '0', '2', '0'), +('7', '0', '0', '3', '0'), + +('7', '0', '1', '0', '0'), +('7', '0', '1', '1', '0'), +('7', '0', '1', '2', '0'), +('7', '0', '1', '3', '0'), + +('7', '0', '2', '0', '0'), +('7', '0', '2', '1', '0'), +('7', '0', '2', '2', '0'), +('7', '0', '2', '3', '0'), + +('7', '0', '3', '0', '0'), +('7', '0', '3', '1', '0'), +('7', '0', '3', '2', '0'), +('7', '0', '3', '3', '0'), + +('7', '0', '4', '0', '0'), +('7', '0', '4', '1', '0'), +('7', '0', '4', '2', '0'), +('7', '0', '4', '3', '0'), + +('7', '0', '5', '0', '0'), +('7', '0', '5', '1', '0'), +('7', '0', '5', '2', '0'), +('7', '0', '5', '3', '0'), + +('7', '0', '6', '0', '0'), +('7', '0', '6', '1', '0'), +('7', '0', '6', '2', '0'), +('7', '0', '6', '3', '0'), + +('7', '1', '0', '0', '0'), +('7', '1', '0', '1', '0'), +('7', '1', '0', '2', '0'), +('7', '1', '0', '3', '0'), + +('7', '1', '1', '0', '0'), +('7', '1', '1', '1', '0'), +('7', '1', '1', '2', '0'), +('7', '1', '1', '3', '0'), + +('7', '1', '2', '0', '0'), +('7', '1', '2', '1', '0'), +('7', '1', '2', '2', '0'), +('7', '1', '2', '3', '0'), + +('7', '1', '3', '0', '0'), +('7', '1', '3', '1', '0'), +('7', '1', '3', '2', '0'), +('7', '1', '3', '3', '0'), + +('7', '1', '4', '0', '0'), +('7', '1', '4', '1', '0'), +('7', '1', '4', '2', '0'), +('7', '1', '4', '3', '0'), + +('7', '1', '5', '0', '0'), +('7', '1', '5', '1', '0'), +('7', '1', '5', '2', '0'), +('7', '1', '5', '3', '0'), + +('7', '1', '6', '0', '0'), +('7', '1', '6', '1', '0'), +('7', '1', '6', '2', '0'), +('7', '1', '6', '3', '0'), + +('7', '2', '0', '0', '0'), +('7', '2', '0', '1', '0'), +('7', '2', '0', '2', '0'), +('7', '2', '0', '3', '0'), + +('7', '2', '1', '0', '0'), +('7', '2', '1', '1', '0'), +('7', '2', '1', '2', '0'), +('7', '2', '1', '3', '0'), + +('7', '2', '2', '0', '0'), +('7', '2', '2', '1', '0'), +('7', '2', '2', '2', '0'), +('7', '2', '2', '3', '0'), + +('7', '2', '3', '0', '0'), +('7', '2', '3', '1', '0'), +('7', '2', '3', '2', '0'), +('7', '2', '3', '3', '0'), + +('7', '2', '4', '0', '0'), +('7', '2', '4', '1', '0'), +('7', '2', '4', '2', '0'), +('7', '2', '4', '3', '0'), + +('7', '2', '5', '0', '0'), +('7', '2', '5', '1', '0'), +('7', '2', '5', '2', '0'), +('7', '2', '5', '3', '0'), + +('7', '2', '6', '0', '0'), +('7', '2', '6', '1', '0'), +('7', '2', '6', '2', '0'), +('7', '2', '6', '3', '0'), + +('7', '3', '0', '0', '0'), +('7', '3', '0', '1', '0'), +('7', '3', '0', '2', '0'), +('7', '3', '0', '3', '0'), + +('7', '3', '1', '0', '0'), +('7', '3', '1', '1', '0'), +('7', '3', '1', '2', '0'), +('7', '3', '1', '3', '0'), + +('7', '3', '2', '0', '0'), +('7', '3', '2', '1', '0'), +('7', '3', '2', '2', '0'), +('7', '3', '2', '3', '0'), + +('7', '3', '3', '0', '0'), +('7', '3', '3', '1', '0'), +('7', '3', '3', '2', '0'), +('7', '3', '3', '3', '0'), + +('7', '3', '4', '0', '0'), +('7', '3', '4', '1', '0'), +('7', '3', '4', '2', '0'), +('7', '3', '4', '3', '0'), + +('7', '3', '5', '0', '0'), +('7', '3', '5', '1', '0'), +('7', '3', '5', '2', '0'), +('7', '3', '5', '3', '0'), + +('7', '3', '6', '0', '0'), +('7', '3', '6', '1', '0'), +('7', '3', '6', '2', '0'), +('7', '3', '6', '3', '0'), + +('7', '4', '0', '0', '0'), +('7', '4', '0', '1', '0'), +('7', '4', '0', '2', '0'), +('7', '4', '0', '3', '0'), + +('7', '4', '1', '0', '0'), +('7', '4', '1', '1', '0'), +('7', '4', '1', '2', '0'), +('7', '4', '1', '3', '0'), + +('7', '4', '2', '0', '0'), +('7', '4', '2', '1', '0'), +('7', '4', '2', '2', '0'), +('7', '4', '2', '3', '0'), + +('7', '4', '3', '0', '0'), +('7', '4', '3', '1', '0'), +('7', '4', '3', '2', '0'), +('7', '4', '3', '3', '0'), + +('7', '4', '4', '0', '0'), +('7', '4', '4', '1', '0'), +('7', '4', '4', '2', '0'), +('7', '4', '4', '3', '0'), + +('7', '4', '5', '0', '0'), +('7', '4', '5', '1', '0'), +('7', '4', '5', '2', '0'), +('7', '4', '5', '3', '0'), + +('7', '4', '6', '0', '0'), +('7', '4', '6', '1', '0'), +('7', '4', '6', '2', '0'), +('7', '4', '6', '3', '0'), + +('7', '5', '0', '0', '0'), +('7', '5', '0', '1', '0'), +('7', '5', '0', '2', '0'), +('7', '5', '0', '3', '0'), + +('7', '5', '1', '0', '0'), +('7', '5', '1', '1', '0'), +('7', '5', '1', '2', '0'), +('7', '5', '1', '3', '0'), + +('7', '5', '2', '0', '0'), +('7', '5', '2', '1', '0'), +('7', '5', '2', '2', '0'), +('7', '5', '2', '3', '0'), + +('7', '5', '3', '0', '0'), +('7', '5', '3', '1', '0'), +('7', '5', '3', '2', '0'), +('7', '5', '3', '3', '0'), + +('7', '5', '4', '0', '0'), +('7', '5', '4', '1', '0'), +('7', '5', '4', '2', '0'), +('7', '5', '4', '3', '0'), + +('7', '5', '5', '0', '0'), +('7', '5', '5', '1', '0'), +('7', '5', '5', '2', '0'), +('7', '5', '5', '3', '0'), + +('7', '5', '6', '0', '0'), +('7', '5', '6', '1', '0'), +('7', '5', '6', '2', '0'), +('7', '5', '6', '3', '0'), + +('7', '6', '0', '0', '0'), +('7', '6', '0', '1', '0'), +('7', '6', '0', '2', '0'), +('7', '6', '0', '3', '0'), + +('7', '6', '1', '0', '0'), +('7', '6', '1', '1', '0'), +('7', '6', '1', '2', '0'), +('7', '6', '1', '3', '0'), + +('7', '6', '2', '0', '0'), +('7', '6', '2', '1', '0'), +('7', '6', '2', '2', '0'), +('7', '6', '2', '3', '0'), + +('7', '6', '3', '0', '0'), +('7', '6', '3', '1', '0'), +('7', '6', '3', '2', '0'), +('7', '6', '3', '3', '0'), + +('7', '6', '4', '0', '0'), +('7', '6', '4', '1', '0'), +('7', '6', '4', '2', '0'), +('7', '6', '4', '3', '0'), + +('7', '6', '5', '0', '0'), +('7', '6', '5', '1', '0'), +('7', '6', '5', '2', '0'), +('7', '6', '5', '3', '0'), + +('7', '6', '6', '0', '0'), +('7', '6', '6', '1', '0'), +('7', '6', '6', '2', '0'), +('7', '6', '6', '3', '0'), + +('7', '7', '0', '0', '0'), +('7', '7', '0', '1', '0'), +('7', '7', '0', '2', '0'), +('7', '7', '0', '3', '0'), + +('7', '7', '1', '0', '0'), +('7', '7', '1', '1', '0'), +('7', '7', '1', '2', '0'), +('7', '7', '1', '3', '0'), + +('7', '7', '2', '0', '0'), +('7', '7', '2', '1', '0'), +('7', '7', '2', '2', '0'), +('7', '7', '2', '3', '0'), + +('7', '7', '3', '0', '0'), +('7', '7', '3', '1', '0'), +('7', '7', '3', '2', '0'), +('7', '7', '3', '3', '0'), + +('7', '7', '4', '0', '0'), +('7', '7', '4', '1', '0'), +('7', '7', '4', '2', '0'), +('7', '7', '4', '3', '0'), + +('7', '7', '5', '0', '0'), +('7', '7', '5', '1', '0'), +('7', '7', '5', '2', '0'), +('7', '7', '5', '3', '0'), + +('7', '7', '6', '0', '0'), +('7', '7', '6', '1', '0'), +('7', '7', '6', '2', '0'), +('7', '7', '6', '3', '0'), + +('7', '8', '0', '0', '0'), +('7', '8', '0', '1', '0'), +('7', '8', '0', '2', '0'), +('7', '8', '0', '3', '0'), + +('7', '8', '1', '0', '0'), +('7', '8', '1', '1', '0'), +('7', '8', '1', '2', '0'), +('7', '8', '1', '3', '0'), + +('7', '8', '2', '0', '0'), +('7', '8', '2', '1', '0'), +('7', '8', '2', '2', '0'), +('7', '8', '2', '3', '0'), + +('7', '8', '3', '0', '0'), +('7', '8', '3', '1', '0'), +('7', '8', '3', '2', '0'), +('7', '8', '3', '3', '0'), + +('7', '8', '4', '0', '0'), +('7', '8', '4', '1', '0'), +('7', '8', '4', '2', '0'), +('7', '8', '4', '3', '0'), + +('7', '8', '5', '0', '0'), +('7', '8', '5', '1', '0'), +('7', '8', '5', '2', '0'), +('7', '8', '5', '3', '0'), + +('7', '8', '6', '0', '0'), +('7', '8', '6', '1', '0'), +('7', '8', '6', '2', '0'), +('7', '8', '6', '3', '0'), + +('7', '9', '0', '0', '0'), +('7', '9', '0', '1', '0'), +('7', '9', '0', '2', '0'), +('7', '9', '0', '3', '0'), + +('7', '9', '1', '0', '0'), +('7', '9', '1', '1', '0'), +('7', '9', '1', '2', '0'), +('7', '9', '1', '3', '0'), + +('7', '9', '2', '0', '0'), +('7', '9', '2', '1', '0'), +('7', '9', '2', '2', '0'), +('7', '9', '2', '3', '0'), + +('7', '9', '3', '0', '0'), +('7', '9', '3', '1', '0'), +('7', '9', '3', '2', '0'), +('7', '9', '3', '3', '0'), + +('7', '9', '4', '0', '0'), +('7', '9', '4', '1', '0'), +('7', '9', '4', '2', '0'), +('7', '9', '4', '3', '0'), + +('7', '9', '5', '0', '0'), +('7', '9', '5', '1', '0'), +('7', '9', '5', '2', '0'), +('7', '9', '5', '3', '0'), + +('7', '9', '6', '0', '0'), +('7', '9', '6', '1', '0'), +('7', '9', '6', '2', '0'), +('7', '9', '6', '3', '0'), + +('7', '10', '0', '0', '0'), +('7', '10', '0', '1', '0'), +('7', '10', '0', '2', '0'), +('7', '10', '0', '3', '0'), + +('7', '10', '1', '0', '0'), +('7', '10', '1', '1', '0'), +('7', '10', '1', '2', '0'), +('7', '10', '1', '3', '0'), + +('7', '10', '2', '0', '0'), +('7', '10', '2', '1', '0'), +('7', '10', '2', '2', '0'), +('7', '10', '2', '3', '0'), + +('7', '10', '3', '0', '0'), +('7', '10', '3', '1', '0'), +('7', '10', '3', '2', '0'), +('7', '10', '3', '3', '0'), + +('7', '10', '4', '0', '0'), +('7', '10', '4', '1', '0'), +('7', '10', '4', '2', '0'), +('7', '10', '4', '3', '0'), + +('7', '10', '5', '0', '0'), +('7', '10', '5', '1', '0'), +('7', '10', '5', '2', '0'), +('7', '10', '5', '3', '0'), + +('7', '10', '6', '0', '0'), +('7', '10', '6', '1', '0'), +('7', '10', '6', '2', '0'), +('7', '10', '6', '3', '0'), + +('7', '11', '0', '0', '0'), +('7', '11', '0', '1', '0'), +('7', '11', '0', '2', '0'), +('7', '11', '0', '3', '0'), + +('7', '11', '1', '0', '0'), +('7', '11', '1', '1', '0'), +('7', '11', '1', '2', '0'), +('7', '11', '1', '3', '0'), + +('7', '11', '2', '0', '0'), +('7', '11', '2', '1', '0'), +('7', '11', '2', '2', '0'), +('7', '11', '2', '3', '0'), + +('7', '11', '3', '0', '0'), +('7', '11', '3', '1', '0'), +('7', '11', '3', '2', '0'), +('7', '11', '3', '3', '0'), + +('7', '11', '4', '0', '0'), +('7', '11', '4', '1', '0'), +('7', '11', '4', '2', '0'), +('7', '11', '4', '3', '0'), + +('7', '11', '5', '0', '0'), +('7', '11', '5', '1', '0'), +('7', '11', '5', '2', '0'), +('7', '11', '5', '3', '0'), + +('7', '11', '6', '0', '0'), +('7', '11', '6', '1', '0'), +('7', '11', '6', '2', '0'), +('7', '11', '6', '3', '0'), + +('7', '12', '0', '0', '0'), +('7', '12', '0', '1', '0'), +('7', '12', '0', '2', '0'), +('7', '12', '0', '3', '0'), + +('7', '12', '1', '0', '0'), +('7', '12', '1', '1', '0'), +('7', '12', '1', '2', '0'), +('7', '12', '1', '3', '0'), + +('7', '12', '2', '0', '0'), +('7', '12', '2', '1', '0'), +('7', '12', '2', '2', '0'), +('7', '12', '2', '3', '0'), + +('7', '12', '3', '0', '0'), +('7', '12', '3', '1', '0'), +('7', '12', '3', '2', '0'), +('7', '12', '3', '3', '0'), + +('7', '12', '4', '0', '0'), +('7', '12', '4', '1', '0'), +('7', '12', '4', '2', '0'), +('7', '12', '4', '3', '0'), + +('7', '12', '5', '0', '0'), +('7', '12', '5', '1', '0'), +('7', '12', '5', '2', '0'), +('7', '12', '5', '3', '0'), + +('7', '12', '6', '0', '0'), +('7', '12', '6', '1', '0'), +('7', '12', '6', '2', '0'), +('7', '12', '6', '3', '0'), + +('7', '13', '0', '0', '0'), +('7', '13', '0', '1', '0'), +('7', '13', '0', '2', '0'), +('7', '13', '0', '3', '0'), + +('7', '13', '1', '0', '0'), +('7', '13', '1', '1', '0'), +('7', '13', '1', '2', '0'), +('7', '13', '1', '3', '0'), + +('7', '13', '2', '0', '0'), +('7', '13', '2', '1', '0'), +('7', '13', '2', '2', '0'), +('7', '13', '2', '3', '0'), + +('7', '13', '3', '0', '0'), +('7', '13', '3', '1', '0'), +('7', '13', '3', '2', '0'), +('7', '13', '3', '3', '0'), + +('7', '13', '4', '0', '0'), +('7', '13', '4', '1', '0'), +('7', '13', '4', '2', '0'), +('7', '13', '4', '3', '0'), + +('7', '13', '5', '0', '0'), +('7', '13', '5', '1', '0'), +('7', '13', '5', '2', '0'), +('7', '13', '5', '3', '0'), + +('7', '13', '6', '0', '0'), +('7', '13', '6', '1', '0'), +('7', '13', '6', '2', '0'), +('7', '13', '6', '3', '0'), + +('7', '14', '0', '0', '0'), +('7', '14', '0', '1', '0'), +('7', '14', '0', '2', '0'), +('7', '14', '0', '3', '0'), + +('7', '14', '1', '0', '0'), +('7', '14', '1', '1', '0'), +('7', '14', '1', '2', '0'), +('7', '14', '1', '3', '0'), + +('7', '14', '2', '0', '0'), +('7', '14', '2', '1', '0'), +('7', '14', '2', '2', '0'), +('7', '14', '2', '3', '0'), + +('7', '14', '3', '0', '0'), +('7', '14', '3', '1', '0'), +('7', '14', '3', '2', '0'), +('7', '14', '3', '3', '0'), + +('7', '14', '4', '0', '0'), +('7', '14', '4', '1', '0'), +('7', '14', '4', '2', '0'), +('7', '14', '4', '3', '0'), + +('7', '14', '5', '0', '0'), +('7', '14', '5', '1', '0'), +('7', '14', '5', '2', '0'), +('7', '14', '5', '3', '0'), + +('7', '14', '6', '0', '0'), +('7', '14', '6', '1', '0'), +('7', '14', '6', '2', '0'), +('7', '14', '6', '3', '0'), + +('7', '15', '0', '0', '0'), +('7', '15', '0', '1', '0'), +('7', '15', '0', '2', '0'), +('7', '15', '0', '3', '0'), + +('7', '15', '1', '0', '0'), +('7', '15', '1', '1', '0'), +('7', '15', '1', '2', '0'), +('7', '15', '1', '3', '0'), + +('7', '15', '2', '0', '0'), +('7', '15', '2', '1', '0'), +('7', '15', '2', '2', '0'), +('7', '15', '2', '3', '0'), + +('7', '15', '3', '0', '0'), +('7', '15', '3', '1', '0'), +('7', '15', '3', '2', '0'), +('7', '15', '3', '3', '0'), + +('7', '15', '4', '0', '0'), +('7', '15', '4', '1', '0'), +('7', '15', '4', '2', '0'), +('7', '15', '4', '3', '0'), + +('7', '15', '5', '0', '0'), +('7', '15', '5', '1', '0'), +('7', '15', '5', '2', '0'), +('7', '15', '5', '3', '0'), + +('7', '15', '6', '0', '0'), +('7', '15', '6', '1', '0'), +('7', '15', '6', '2', '0'), +('7', '15', '6', '3', '0'), + +-- SpellType_DOTIndex + +('8', '0', '0', '0', '0'), +('8', '0', '0', '1', '0'), +('8', '0', '0', '2', '0'), +('8', '0', '0', '3', '0'), + +('8', '0', '1', '0', '0'), +('8', '0', '1', '1', '0'), +('8', '0', '1', '2', '0'), +('8', '0', '1', '3', '0'), + +('8', '0', '2', '0', '0'), +('8', '0', '2', '1', '0'), +('8', '0', '2', '2', '0'), +('8', '0', '2', '3', '0'), + +('8', '0', '3', '0', '0'), +('8', '0', '3', '1', '0'), +('8', '0', '3', '2', '0'), +('8', '0', '3', '3', '0'), + +('8', '0', '4', '0', '0'), +('8', '0', '4', '1', '0'), +('8', '0', '4', '2', '0'), +('8', '0', '4', '3', '0'), + +('8', '0', '5', '0', '0'), +('8', '0', '5', '1', '0'), +('8', '0', '5', '2', '0'), +('8', '0', '5', '3', '0'), + +('8', '0', '6', '0', '0'), +('8', '0', '6', '1', '0'), +('8', '0', '6', '2', '0'), +('8', '0', '6', '3', '0'), + +('8', '1', '0', '0', '0'), +('8', '1', '0', '1', '0'), +('8', '1', '0', '2', '0'), +('8', '1', '0', '3', '0'), + +('8', '1', '1', '0', '0'), +('8', '1', '1', '1', '0'), +('8', '1', '1', '2', '0'), +('8', '1', '1', '3', '0'), + +('8', '1', '2', '0', '0'), +('8', '1', '2', '1', '0'), +('8', '1', '2', '2', '0'), +('8', '1', '2', '3', '0'), + +('8', '1', '3', '0', '0'), +('8', '1', '3', '1', '0'), +('8', '1', '3', '2', '0'), +('8', '1', '3', '3', '0'), + +('8', '1', '4', '0', '0'), +('8', '1', '4', '1', '0'), +('8', '1', '4', '2', '0'), +('8', '1', '4', '3', '0'), + +('8', '1', '5', '0', '0'), +('8', '1', '5', '1', '0'), +('8', '1', '5', '2', '0'), +('8', '1', '5', '3', '0'), + +('8', '1', '6', '0', '0'), +('8', '1', '6', '1', '0'), +('8', '1', '6', '2', '0'), +('8', '1', '6', '3', '0'), + +('8', '2', '0', '0', '0'), +('8', '2', '0', '1', '0'), +('8', '2', '0', '2', '0'), +('8', '2', '0', '3', '0'), + +('8', '2', '1', '0', '0'), +('8', '2', '1', '1', '0'), +('8', '2', '1', '2', '0'), +('8', '2', '1', '3', '0'), + +('8', '2', '2', '0', '0'), +('8', '2', '2', '1', '0'), +('8', '2', '2', '2', '0'), +('8', '2', '2', '3', '0'), + +('8', '2', '3', '0', '0'), +('8', '2', '3', '1', '0'), +('8', '2', '3', '2', '0'), +('8', '2', '3', '3', '0'), + +('8', '2', '4', '0', '0'), +('8', '2', '4', '1', '0'), +('8', '2', '4', '2', '0'), +('8', '2', '4', '3', '0'), + +('8', '2', '5', '0', '0'), +('8', '2', '5', '1', '0'), +('8', '2', '5', '2', '0'), +('8', '2', '5', '3', '0'), + +('8', '2', '6', '0', '0'), +('8', '2', '6', '1', '0'), +('8', '2', '6', '2', '0'), +('8', '2', '6', '3', '0'), + +('8', '3', '0', '0', '0'), +('8', '3', '0', '1', '0'), +('8', '3', '0', '2', '0'), +('8', '3', '0', '3', '0'), + +('8', '3', '1', '0', '15'), +('8', '3', '1', '1', '15'), +('8', '3', '1', '2', '10'), +('8', '3', '1', '3', '10'), + +('8', '3', '2', '0', '10'), +('8', '3', '2', '1', '10'), +('8', '3', '2', '2', '0'), +('8', '3', '2', '3', '0'), + +('8', '3', '3', '0', '15'), +('8', '3', '3', '1', '15'), +('8', '3', '3', '2', '10'), +('8', '3', '3', '3', '10'), + +('8', '3', '4', '0', '50'), +('8', '3', '4', '1', '50'), +('8', '3', '4', '2', '25'), +('8', '3', '4', '3', '25'), + +('8', '3', '5', '0', '50'), +('8', '3', '5', '1', '50'), +('8', '3', '5', '2', '25'), +('8', '3', '5', '3', '25'), + +('8', '3', '6', '0', '50'), +('8', '3', '6', '1', '50'), +('8', '3', '6', '2', '25'), +('8', '3', '6', '3', '25'), + +('8', '4', '0', '0', '0'), +('8', '4', '0', '1', '0'), +('8', '4', '0', '2', '0'), +('8', '4', '0', '3', '0'), + +('8', '4', '1', '0', '15'), +('8', '4', '1', '1', '15'), +('8', '4', '1', '2', '10'), +('8', '4', '1', '3', '10'), + +('8', '4', '2', '0', '10'), +('8', '4', '2', '1', '10'), +('8', '4', '2', '2', '0'), +('8', '4', '2', '3', '0'), + +('8', '4', '3', '0', '15'), +('8', '4', '3', '1', '15'), +('8', '4', '3', '2', '10'), +('8', '4', '3', '3', '10'), + +('8', '4', '4', '0', '50'), +('8', '4', '4', '1', '50'), +('8', '4', '4', '2', '25'), +('8', '4', '4', '3', '25'), + +('8', '4', '5', '0', '50'), +('8', '4', '5', '1', '50'), +('8', '4', '5', '2', '25'), +('8', '4', '5', '3', '25'), + +('8', '4', '6', '0', '50'), +('8', '4', '6', '1', '50'), +('8', '4', '6', '2', '25'), +('8', '4', '6', '3', '25'), + +('8', '5', '0', '0', '0'), +('8', '5', '0', '1', '0'), +('8', '5', '0', '2', '0'), +('8', '5', '0', '3', '0'), + +('8', '5', '1', '0', '50'), +('8', '5', '1', '1', '15'), +('8', '5', '1', '2', '50'), +('8', '5', '1', '3', '15'), + +('8', '5', '2', '0', '25'), +('8', '5', '2', '1', '10'), +('8', '5', '2', '2', '25'), +('8', '5', '2', '3', '10'), + +('8', '5', '3', '0', '50'), +('8', '5', '3', '1', '15'), +('8', '5', '3', '2', '50'), +('8', '5', '3', '3', '15'), + +('8', '5', '4', '0', '50'), +('8', '5', '4', '1', '25'), +('8', '5', '4', '2', '50'), +('8', '5', '4', '3', '25'), + +('8', '5', '5', '0', '50'), +('8', '5', '5', '1', '25'), +('8', '5', '5', '2', '50'), +('8', '5', '5', '3', '25'), + +('8', '5', '6', '0', '50'), +('8', '5', '6', '1', '25'), +('8', '5', '6', '2', '50'), +('8', '5', '6', '3', '25'), + +('8', '6', '0', '0', '0'), +('8', '6', '0', '1', '0'), +('8', '6', '0', '2', '0'), +('8', '6', '0', '3', '0'), + +('8', '6', '1', '0', '0'), +('8', '6', '1', '1', '0'), +('8', '6', '1', '2', '0'), +('8', '6', '1', '3', '0'), + +('8', '6', '2', '0', '0'), +('8', '6', '2', '1', '0'), +('8', '6', '2', '2', '0'), +('8', '6', '2', '3', '0'), + +('8', '6', '3', '0', '0'), +('8', '6', '3', '1', '0'), +('8', '6', '3', '2', '0'), +('8', '6', '3', '3', '0'), + +('8', '6', '4', '0', '0'), +('8', '6', '4', '1', '0'), +('8', '6', '4', '2', '0'), +('8', '6', '4', '3', '0'), + +('8', '6', '5', '0', '0'), +('8', '6', '5', '1', '0'), +('8', '6', '5', '2', '0'), +('8', '6', '5', '3', '0'), + +('8', '6', '6', '0', '0'), +('8', '6', '6', '1', '0'), +('8', '6', '6', '2', '0'), +('8', '6', '6', '3', '0'), + +('8', '7', '0', '0', '0'), +('8', '7', '0', '1', '0'), +('8', '7', '0', '2', '0'), +('8', '7', '0', '3', '0'), + +('8', '7', '1', '0', '50'), +('8', '7', '1', '1', '50'), +('8', '7', '1', '2', '25'), +('8', '7', '1', '3', '25'), + +('8', '7', '2', '0', '25'), +('8', '7', '2', '1', '25'), +('8', '7', '2', '2', '15'), +('8', '7', '2', '3', '15'), + +('8', '7', '3', '0', '50'), +('8', '7', '3', '1', '50'), +('8', '7', '3', '2', '25'), +('8', '7', '3', '3', '25'), + +('8', '7', '4', '0', '100'), +('8', '7', '4', '1', '100'), +('8', '7', '4', '2', '50'), +('8', '7', '4', '3', '50'), + +('8', '7', '5', '0', '100'), +('8', '7', '5', '1', '100'), +('8', '7', '5', '2', '50'), +('8', '7', '5', '3', '50'), + +('8', '7', '6', '0', '100'), +('8', '7', '6', '1', '100'), +('8', '7', '6', '2', '50'), +('8', '7', '6', '3', '50'), + +('8', '8', '0', '0', '0'), +('8', '8', '0', '1', '0'), +('8', '8', '0', '2', '0'), +('8', '8', '0', '3', '0'), + +('8', '8', '1', '0', '0'), +('8', '8', '1', '1', '0'), +('8', '8', '1', '2', '0'), +('8', '8', '1', '3', '0'), + +('8', '8', '2', '0', '0'), +('8', '8', '2', '1', '0'), +('8', '8', '2', '2', '0'), +('8', '8', '2', '3', '0'), + +('8', '8', '3', '0', '0'), +('8', '8', '3', '1', '0'), +('8', '8', '3', '2', '0'), +('8', '8', '3', '3', '0'), + +('8', '8', '4', '0', '0'), +('8', '8', '4', '1', '0'), +('8', '8', '4', '2', '0'), +('8', '8', '4', '3', '0'), + +('8', '8', '5', '0', '0'), +('8', '8', '5', '1', '0'), +('8', '8', '5', '2', '0'), +('8', '8', '5', '3', '0'), + +('8', '8', '6', '0', '0'), +('8', '8', '6', '1', '0'), +('8', '8', '6', '2', '0'), +('8', '8', '6', '3', '0'), + +('8', '9', '0', '0', '0'), +('8', '9', '0', '1', '0'), +('8', '9', '0', '2', '0'), +('8', '9', '0', '3', '0'), + +('8', '9', '1', '0', '25'), +('8', '9', '1', '1', '15'), +('8', '9', '1', '2', '15'), +('8', '9', '1', '3', '0'), + +('8', '9', '2', '0', '15'), +('8', '9', '2', '1', '10'), +('8', '9', '2', '2', '10'), +('8', '9', '2', '3', '0'), + +('8', '9', '3', '0', '25'), +('8', '9', '3', '1', '15'), +('8', '9', '3', '2', '15'), +('8', '9', '3', '3', '0'), + +('8', '9', '4', '0', '50'), +('8', '9', '4', '1', '25'), +('8', '9', '4', '2', '50'), +('8', '9', '4', '3', '15'), + +('8', '9', '5', '0', '50'), +('8', '9', '5', '1', '25'), +('8', '9', '5', '2', '50'), +('8', '9', '5', '3', '15'), + +('8', '9', '6', '0', '50'), +('8', '9', '6', '1', '25'), +('8', '9', '6', '2', '50'), +('8', '9', '6', '3', '15'), + +('8', '10', '0', '0', '0'), +('8', '10', '0', '1', '0'), +('8', '10', '0', '2', '0'), +('8', '10', '0', '3', '0'), + +('8', '10', '1', '0', '50'), +('8', '10', '1', '1', '50'), +('8', '10', '1', '2', '50'), +('8', '10', '1', '3', '50'), + +('8', '10', '2', '0', '25'), +('8', '10', '2', '1', '25'), +('8', '10', '2', '2', '25'), +('8', '10', '2', '3', '25'), + +('8', '10', '3', '0', '50'), +('8', '10', '3', '1', '50'), +('8', '10', '3', '2', '50'), +('8', '10', '3', '3', '50'), + +('8', '10', '4', '0', '50'), +('8', '10', '4', '1', '50'), +('8', '10', '4', '2', '50'), +('8', '10', '4', '3', '50'), + +('8', '10', '5', '0', '75'), +('8', '10', '5', '1', '75'), +('8', '10', '5', '2', '75'), +('8', '10', '5', '3', '75'), + +('8', '10', '6', '0', '75'), +('8', '10', '6', '1', '75'), +('8', '10', '6', '2', '75'), +('8', '10', '6', '3', '75'), + +('8', '11', '0', '0', '0'), +('8', '11', '0', '1', '0'), +('8', '11', '0', '2', '0'), +('8', '11', '0', '3', '0'), + +('8', '11', '1', '0', '0'), +('8', '11', '1', '1', '0'), +('8', '11', '1', '2', '0'), +('8', '11', '1', '3', '0'), + +('8', '11', '2', '0', '0'), +('8', '11', '2', '1', '0'), +('8', '11', '2', '2', '0'), +('8', '11', '2', '3', '0'), + +('8', '11', '3', '0', '0'), +('8', '11', '3', '1', '0'), +('8', '11', '3', '2', '0'), +('8', '11', '3', '3', '0'), + +('8', '11', '4', '0', '0'), +('8', '11', '4', '1', '0'), +('8', '11', '4', '2', '0'), +('8', '11', '4', '3', '0'), + +('8', '11', '5', '0', '0'), +('8', '11', '5', '1', '0'), +('8', '11', '5', '2', '0'), +('8', '11', '5', '3', '0'), + +('8', '11', '6', '0', '0'), +('8', '11', '6', '1', '0'), +('8', '11', '6', '2', '0'), +('8', '11', '6', '3', '0'), + +('8', '12', '0', '0', '0'), +('8', '12', '0', '1', '0'), +('8', '12', '0', '2', '0'), +('8', '12', '0', '3', '0'), + +('8', '12', '1', '0', '0'), +('8', '12', '1', '1', '0'), +('8', '12', '1', '2', '0'), +('8', '12', '1', '3', '0'), + +('8', '12', '2', '0', '0'), +('8', '12', '2', '1', '0'), +('8', '12', '2', '2', '0'), +('8', '12', '2', '3', '0'), + +('8', '12', '3', '0', '0'), +('8', '12', '3', '1', '0'), +('8', '12', '3', '2', '0'), +('8', '12', '3', '3', '0'), + +('8', '12', '4', '0', '0'), +('8', '12', '4', '1', '0'), +('8', '12', '4', '2', '0'), +('8', '12', '4', '3', '0'), + +('8', '12', '5', '0', '0'), +('8', '12', '5', '1', '0'), +('8', '12', '5', '2', '0'), +('8', '12', '5', '3', '0'), + +('8', '12', '6', '0', '0'), +('8', '12', '6', '1', '0'), +('8', '12', '6', '2', '0'), +('8', '12', '6', '3', '0'), + +('8', '13', '0', '0', '0'), +('8', '13', '0', '1', '0'), +('8', '13', '0', '2', '0'), +('8', '13', '0', '3', '0'), + +('8', '13', '1', '0', '50'), +('8', '13', '1', '1', '50'), +('8', '13', '1', '2', '15'), +('8', '13', '1', '3', '15'), + +('8', '13', '2', '0', '25'), +('8', '13', '2', '1', '25'), +('8', '13', '2', '2', '10'), +('8', '13', '2', '3', '10'), + +('8', '13', '3', '0', '50'), +('8', '13', '3', '1', '50'), +('8', '13', '3', '2', '15'), +('8', '13', '3', '3', '15'), + +('8', '13', '4', '0', '15'), +('8', '13', '4', '1', '15'), +('8', '13', '4', '2', '25'), +('8', '13', '4', '3', '25'), + +('8', '13', '5', '0', '15'), +('8', '13', '5', '1', '15'), +('8', '13', '5', '2', '25'), +('8', '13', '5', '3', '25'), + +('8', '13', '6', '0', '15'), +('8', '13', '6', '1', '15'), +('8', '13', '6', '2', '25'), +('8', '13', '6', '3', '25'), + +('8', '14', '0', '0', '0'), +('8', '14', '0', '1', '0'), +('8', '14', '0', '2', '0'), +('8', '14', '0', '3', '0'), + +('8', '14', '1', '0', '15'), +('8', '14', '1', '1', '15'), +('8', '14', '1', '2', '10'), +('8', '14', '1', '3', '10'), + +('8', '14', '2', '0', '10'), +('8', '14', '2', '1', '10'), +('8', '14', '2', '2', '0'), +('8', '14', '2', '3', '0'), + +('8', '14', '3', '0', '15'), +('8', '14', '3', '1', '15'), +('8', '14', '3', '2', '10'), +('8', '14', '3', '3', '10'), + +('8', '14', '4', '0', '50'), +('8', '14', '4', '1', '50'), +('8', '14', '4', '2', '25'), +('8', '14', '4', '3', '25'), + +('8', '14', '5', '0', '50'), +('8', '14', '5', '1', '50'), +('8', '14', '5', '2', '25'), +('8', '14', '5', '3', '25'), + +('8', '14', '6', '0', '50'), +('8', '14', '6', '1', '50'), +('8', '14', '6', '2', '25'), +('8', '14', '6', '3', '25'), + +('8', '15', '0', '0', '0'), +('8', '15', '0', '1', '0'), +('8', '15', '0', '2', '0'), +('8', '15', '0', '3', '0'), + +('8', '15', '1', '0', '0'), +('8', '15', '1', '1', '0'), +('8', '15', '1', '2', '0'), +('8', '15', '1', '3', '0'), + +('8', '15', '2', '0', '0'), +('8', '15', '2', '1', '0'), +('8', '15', '2', '2', '0'), +('8', '15', '2', '3', '0'), + +('8', '15', '3', '0', '0'), +('8', '15', '3', '1', '0'), +('8', '15', '3', '2', '0'), +('8', '15', '3', '3', '0'), + +('8', '15', '4', '0', '0'), +('8', '15', '4', '1', '0'), +('8', '15', '4', '2', '0'), +('8', '15', '4', '3', '0'), + +('8', '15', '5', '0', '0'), +('8', '15', '5', '1', '0'), +('8', '15', '5', '2', '0'), +('8', '15', '5', '3', '0'), + +('8', '15', '6', '0', '0'), +('8', '15', '6', '1', '0'), +('8', '15', '6', '2', '0'), +('8', '15', '6', '3', '0'), + +-- SpellType_DispelIndex + +('9', '0', '0', '0', '0'), +('9', '0', '0', '1', '0'), +('9', '0', '0', '2', '0'), +('9', '0', '0', '3', '0'), + +('9', '0', '1', '0', '0'), +('9', '0', '1', '1', '0'), +('9', '0', '1', '2', '0'), +('9', '0', '1', '3', '0'), + +('9', '0', '2', '0', '0'), +('9', '0', '2', '1', '0'), +('9', '0', '2', '2', '0'), +('9', '0', '2', '3', '0'), + +('9', '0', '3', '0', '0'), +('9', '0', '3', '1', '0'), +('9', '0', '3', '2', '0'), +('9', '0', '3', '3', '0'), + +('9', '0', '4', '0', '0'), +('9', '0', '4', '1', '0'), +('9', '0', '4', '2', '0'), +('9', '0', '4', '3', '0'), + +('9', '0', '5', '0', '0'), +('9', '0', '5', '1', '0'), +('9', '0', '5', '2', '0'), +('9', '0', '5', '3', '0'), + +('9', '0', '6', '0', '0'), +('9', '0', '6', '1', '0'), +('9', '0', '6', '2', '0'), +('9', '0', '6', '3', '0'), + +('9', '1', '0', '0', '0'), +('9', '1', '0', '1', '0'), +('9', '1', '0', '2', '0'), +('9', '1', '0', '3', '0'), + +('9', '1', '1', '0', '0'), +('9', '1', '1', '1', '0'), +('9', '1', '1', '2', '0'), +('9', '1', '1', '3', '0'), + +('9', '1', '2', '0', '0'), +('9', '1', '2', '1', '0'), +('9', '1', '2', '2', '0'), +('9', '1', '2', '3', '0'), + +('9', '1', '3', '0', '0'), +('9', '1', '3', '1', '0'), +('9', '1', '3', '2', '0'), +('9', '1', '3', '3', '0'), + +('9', '1', '4', '0', '0'), +('9', '1', '4', '1', '0'), +('9', '1', '4', '2', '0'), +('9', '1', '4', '3', '0'), + +('9', '1', '5', '0', '0'), +('9', '1', '5', '1', '0'), +('9', '1', '5', '2', '0'), +('9', '1', '5', '3', '0'), + +('9', '1', '6', '0', '0'), +('9', '1', '6', '1', '0'), +('9', '1', '6', '2', '0'), +('9', '1', '6', '3', '0'), + +('9', '2', '0', '0', '0'), +('9', '2', '0', '1', '0'), +('9', '2', '0', '2', '0'), +('9', '2', '0', '3', '0'), + +('9', '2', '1', '0', '0'), +('9', '2', '1', '1', '0'), +('9', '2', '1', '2', '0'), +('9', '2', '1', '3', '0'), + +('9', '2', '2', '0', '0'), +('9', '2', '2', '1', '0'), +('9', '2', '2', '2', '0'), +('9', '2', '2', '3', '0'), + +('9', '2', '3', '0', '0'), +('9', '2', '3', '1', '0'), +('9', '2', '3', '2', '0'), +('9', '2', '3', '3', '0'), + +('9', '2', '4', '0', '0'), +('9', '2', '4', '1', '0'), +('9', '2', '4', '2', '0'), +('9', '2', '4', '3', '0'), + +('9', '2', '5', '0', '0'), +('9', '2', '5', '1', '0'), +('9', '2', '5', '2', '0'), +('9', '2', '5', '3', '0'), + +('9', '2', '6', '0', '0'), +('9', '2', '6', '1', '0'), +('9', '2', '6', '2', '0'), +('9', '2', '6', '3', '0'), + +('9', '3', '0', '0', '0'), +('9', '3', '0', '1', '0'), +('9', '3', '0', '2', '0'), +('9', '3', '0', '3', '0'), + +('9', '3', '1', '0', '0'), +('9', '3', '1', '1', '0'), +('9', '3', '1', '2', '0'), +('9', '3', '1', '3', '0'), + +('9', '3', '2', '0', '0'), +('9', '3', '2', '1', '0'), +('9', '3', '2', '2', '0'), +('9', '3', '2', '3', '0'), + +('9', '3', '3', '0', '0'), +('9', '3', '3', '1', '0'), +('9', '3', '3', '2', '0'), +('9', '3', '3', '3', '0'), + +('9', '3', '4', '0', '0'), +('9', '3', '4', '1', '0'), +('9', '3', '4', '2', '0'), +('9', '3', '4', '3', '0'), + +('9', '3', '5', '0', '0'), +('9', '3', '5', '1', '0'), +('9', '3', '5', '2', '0'), +('9', '3', '5', '3', '0'), + +('9', '3', '6', '0', '0'), +('9', '3', '6', '1', '0'), +('9', '3', '6', '2', '0'), +('9', '3', '6', '3', '0'), + +('9', '4', '0', '0', '0'), +('9', '4', '0', '1', '0'), +('9', '4', '0', '2', '0'), +('9', '4', '0', '3', '0'), + +('9', '4', '1', '0', '0'), +('9', '4', '1', '1', '0'), +('9', '4', '1', '2', '0'), +('9', '4', '1', '3', '0'), + +('9', '4', '2', '0', '0'), +('9', '4', '2', '1', '0'), +('9', '4', '2', '2', '0'), +('9', '4', '2', '3', '0'), + +('9', '4', '3', '0', '0'), +('9', '4', '3', '1', '0'), +('9', '4', '3', '2', '0'), +('9', '4', '3', '3', '0'), + +('9', '4', '4', '0', '0'), +('9', '4', '4', '1', '0'), +('9', '4', '4', '2', '0'), +('9', '4', '4', '3', '0'), + +('9', '4', '5', '0', '0'), +('9', '4', '5', '1', '0'), +('9', '4', '5', '2', '0'), +('9', '4', '5', '3', '0'), + +('9', '4', '6', '0', '0'), +('9', '4', '6', '1', '0'), +('9', '4', '6', '2', '0'), +('9', '4', '6', '3', '0'), + +('9', '5', '0', '0', '0'), +('9', '5', '0', '1', '0'), +('9', '5', '0', '2', '0'), +('9', '5', '0', '3', '0'), + +('9', '5', '1', '0', '0'), +('9', '5', '1', '1', '0'), +('9', '5', '1', '2', '0'), +('9', '5', '1', '3', '0'), + +('9', '5', '2', '0', '0'), +('9', '5', '2', '1', '0'), +('9', '5', '2', '2', '0'), +('9', '5', '2', '3', '0'), + +('9', '5', '3', '0', '0'), +('9', '5', '3', '1', '0'), +('9', '5', '3', '2', '0'), +('9', '5', '3', '3', '0'), + +('9', '5', '4', '0', '0'), +('9', '5', '4', '1', '0'), +('9', '5', '4', '2', '0'), +('9', '5', '4', '3', '0'), + +('9', '5', '5', '0', '0'), +('9', '5', '5', '1', '0'), +('9', '5', '5', '2', '0'), +('9', '5', '5', '3', '0'), + +('9', '5', '6', '0', '0'), +('9', '5', '6', '1', '0'), +('9', '5', '6', '2', '0'), +('9', '5', '6', '3', '0'), + +('9', '6', '0', '0', '0'), +('9', '6', '0', '1', '0'), +('9', '6', '0', '2', '0'), +('9', '6', '0', '3', '0'), + +('9', '6', '1', '0', '0'), +('9', '6', '1', '1', '0'), +('9', '6', '1', '2', '0'), +('9', '6', '1', '3', '0'), + +('9', '6', '2', '0', '0'), +('9', '6', '2', '1', '0'), +('9', '6', '2', '2', '0'), +('9', '6', '2', '3', '0'), + +('9', '6', '3', '0', '0'), +('9', '6', '3', '1', '0'), +('9', '6', '3', '2', '0'), +('9', '6', '3', '3', '0'), + +('9', '6', '4', '0', '0'), +('9', '6', '4', '1', '0'), +('9', '6', '4', '2', '0'), +('9', '6', '4', '3', '0'), + +('9', '6', '5', '0', '0'), +('9', '6', '5', '1', '0'), +('9', '6', '5', '2', '0'), +('9', '6', '5', '3', '0'), + +('9', '6', '6', '0', '0'), +('9', '6', '6', '1', '0'), +('9', '6', '6', '2', '0'), +('9', '6', '6', '3', '0'), + +('9', '7', '0', '0', '0'), +('9', '7', '0', '1', '0'), +('9', '7', '0', '2', '0'), +('9', '7', '0', '3', '0'), + +('9', '7', '1', '0', '0'), +('9', '7', '1', '1', '0'), +('9', '7', '1', '2', '0'), +('9', '7', '1', '3', '0'), + +('9', '7', '2', '0', '0'), +('9', '7', '2', '1', '0'), +('9', '7', '2', '2', '0'), +('9', '7', '2', '3', '0'), + +('9', '7', '3', '0', '0'), +('9', '7', '3', '1', '0'), +('9', '7', '3', '2', '0'), +('9', '7', '3', '3', '0'), + +('9', '7', '4', '0', '0'), +('9', '7', '4', '1', '0'), +('9', '7', '4', '2', '0'), +('9', '7', '4', '3', '0'), + +('9', '7', '5', '0', '0'), +('9', '7', '5', '1', '0'), +('9', '7', '5', '2', '0'), +('9', '7', '5', '3', '0'), + +('9', '7', '6', '0', '0'), +('9', '7', '6', '1', '0'), +('9', '7', '6', '2', '0'), +('9', '7', '6', '3', '0'), + +('9', '8', '0', '0', '0'), +('9', '8', '0', '1', '0'), +('9', '8', '0', '2', '0'), +('9', '8', '0', '3', '0'), + +('9', '8', '1', '0', '0'), +('9', '8', '1', '1', '0'), +('9', '8', '1', '2', '0'), +('9', '8', '1', '3', '0'), + +('9', '8', '2', '0', '0'), +('9', '8', '2', '1', '0'), +('9', '8', '2', '2', '0'), +('9', '8', '2', '3', '0'), + +('9', '8', '3', '0', '0'), +('9', '8', '3', '1', '0'), +('9', '8', '3', '2', '0'), +('9', '8', '3', '3', '0'), + +('9', '8', '4', '0', '0'), +('9', '8', '4', '1', '0'), +('9', '8', '4', '2', '0'), +('9', '8', '4', '3', '0'), + +('9', '8', '5', '0', '0'), +('9', '8', '5', '1', '0'), +('9', '8', '5', '2', '0'), +('9', '8', '5', '3', '0'), + +('9', '8', '6', '0', '0'), +('9', '8', '6', '1', '0'), +('9', '8', '6', '2', '0'), +('9', '8', '6', '3', '0'), + +('9', '9', '0', '0', '0'), +('9', '9', '0', '1', '0'), +('9', '9', '0', '2', '0'), +('9', '9', '0', '3', '0'), + +('9', '9', '1', '0', '0'), +('9', '9', '1', '1', '0'), +('9', '9', '1', '2', '0'), +('9', '9', '1', '3', '0'), + +('9', '9', '2', '0', '0'), +('9', '9', '2', '1', '0'), +('9', '9', '2', '2', '0'), +('9', '9', '2', '3', '0'), + +('9', '9', '3', '0', '0'), +('9', '9', '3', '1', '0'), +('9', '9', '3', '2', '0'), +('9', '9', '3', '3', '0'), + +('9', '9', '4', '0', '0'), +('9', '9', '4', '1', '0'), +('9', '9', '4', '2', '0'), +('9', '9', '4', '3', '0'), + +('9', '9', '5', '0', '0'), +('9', '9', '5', '1', '0'), +('9', '9', '5', '2', '0'), +('9', '9', '5', '3', '0'), + +('9', '9', '6', '0', '0'), +('9', '9', '6', '1', '0'), +('9', '9', '6', '2', '0'), +('9', '9', '6', '3', '0'), + +('9', '10', '0', '0', '0'), +('9', '10', '0', '1', '0'), +('9', '10', '0', '2', '0'), +('9', '10', '0', '3', '0'), + +('9', '10', '1', '0', '0'), +('9', '10', '1', '1', '0'), +('9', '10', '1', '2', '0'), +('9', '10', '1', '3', '0'), + +('9', '10', '2', '0', '0'), +('9', '10', '2', '1', '0'), +('9', '10', '2', '2', '0'), +('9', '10', '2', '3', '0'), + +('9', '10', '3', '0', '0'), +('9', '10', '3', '1', '0'), +('9', '10', '3', '2', '0'), +('9', '10', '3', '3', '0'), + +('9', '10', '4', '0', '0'), +('9', '10', '4', '1', '0'), +('9', '10', '4', '2', '0'), +('9', '10', '4', '3', '0'), + +('9', '10', '5', '0', '0'), +('9', '10', '5', '1', '0'), +('9', '10', '5', '2', '0'), +('9', '10', '5', '3', '0'), + +('9', '10', '6', '0', '0'), +('9', '10', '6', '1', '0'), +('9', '10', '6', '2', '0'), +('9', '10', '6', '3', '0'), + +('9', '11', '0', '0', '0'), +('9', '11', '0', '1', '0'), +('9', '11', '0', '2', '0'), +('9', '11', '0', '3', '0'), + +('9', '11', '1', '0', '0'), +('9', '11', '1', '1', '0'), +('9', '11', '1', '2', '0'), +('9', '11', '1', '3', '0'), + +('9', '11', '2', '0', '0'), +('9', '11', '2', '1', '0'), +('9', '11', '2', '2', '0'), +('9', '11', '2', '3', '0'), + +('9', '11', '3', '0', '0'), +('9', '11', '3', '1', '0'), +('9', '11', '3', '2', '0'), +('9', '11', '3', '3', '0'), + +('9', '11', '4', '0', '0'), +('9', '11', '4', '1', '0'), +('9', '11', '4', '2', '0'), +('9', '11', '4', '3', '0'), + +('9', '11', '5', '0', '0'), +('9', '11', '5', '1', '0'), +('9', '11', '5', '2', '0'), +('9', '11', '5', '3', '0'), + +('9', '11', '6', '0', '0'), +('9', '11', '6', '1', '0'), +('9', '11', '6', '2', '0'), +('9', '11', '6', '3', '0'), + +('9', '12', '0', '0', '0'), +('9', '12', '0', '1', '0'), +('9', '12', '0', '2', '0'), +('9', '12', '0', '3', '0'), + +('9', '12', '1', '0', '0'), +('9', '12', '1', '1', '0'), +('9', '12', '1', '2', '0'), +('9', '12', '1', '3', '0'), + +('9', '12', '2', '0', '0'), +('9', '12', '2', '1', '0'), +('9', '12', '2', '2', '0'), +('9', '12', '2', '3', '0'), + +('9', '12', '3', '0', '0'), +('9', '12', '3', '1', '0'), +('9', '12', '3', '2', '0'), +('9', '12', '3', '3', '0'), + +('9', '12', '4', '0', '0'), +('9', '12', '4', '1', '0'), +('9', '12', '4', '2', '0'), +('9', '12', '4', '3', '0'), + +('9', '12', '5', '0', '0'), +('9', '12', '5', '1', '0'), +('9', '12', '5', '2', '0'), +('9', '12', '5', '3', '0'), + +('9', '12', '6', '0', '0'), +('9', '12', '6', '1', '0'), +('9', '12', '6', '2', '0'), +('9', '12', '6', '3', '0'), + +('9', '13', '0', '0', '0'), +('9', '13', '0', '1', '0'), +('9', '13', '0', '2', '0'), +('9', '13', '0', '3', '0'), + +('9', '13', '1', '0', '0'), +('9', '13', '1', '1', '0'), +('9', '13', '1', '2', '0'), +('9', '13', '1', '3', '0'), + +('9', '13', '2', '0', '0'), +('9', '13', '2', '1', '0'), +('9', '13', '2', '2', '0'), +('9', '13', '2', '3', '0'), + +('9', '13', '3', '0', '0'), +('9', '13', '3', '1', '0'), +('9', '13', '3', '2', '0'), +('9', '13', '3', '3', '0'), + +('9', '13', '4', '0', '0'), +('9', '13', '4', '1', '0'), +('9', '13', '4', '2', '0'), +('9', '13', '4', '3', '0'), + +('9', '13', '5', '0', '0'), +('9', '13', '5', '1', '0'), +('9', '13', '5', '2', '0'), +('9', '13', '5', '3', '0'), + +('9', '13', '6', '0', '0'), +('9', '13', '6', '1', '0'), +('9', '13', '6', '2', '0'), +('9', '13', '6', '3', '0'), + +('9', '14', '0', '0', '0'), +('9', '14', '0', '1', '0'), +('9', '14', '0', '2', '0'), +('9', '14', '0', '3', '0'), + +('9', '14', '1', '0', '0'), +('9', '14', '1', '1', '0'), +('9', '14', '1', '2', '0'), +('9', '14', '1', '3', '0'), + +('9', '14', '2', '0', '0'), +('9', '14', '2', '1', '0'), +('9', '14', '2', '2', '0'), +('9', '14', '2', '3', '0'), + +('9', '14', '3', '0', '0'), +('9', '14', '3', '1', '0'), +('9', '14', '3', '2', '0'), +('9', '14', '3', '3', '0'), + +('9', '14', '4', '0', '0'), +('9', '14', '4', '1', '0'), +('9', '14', '4', '2', '0'), +('9', '14', '4', '3', '0'), + +('9', '14', '5', '0', '0'), +('9', '14', '5', '1', '0'), +('9', '14', '5', '2', '0'), +('9', '14', '5', '3', '0'), + +('9', '14', '6', '0', '0'), +('9', '14', '6', '1', '0'), +('9', '14', '6', '2', '0'), +('9', '14', '6', '3', '0'), + +('9', '15', '0', '0', '0'), +('9', '15', '0', '1', '0'), +('9', '15', '0', '2', '0'), +('9', '15', '0', '3', '0'), + +('9', '15', '1', '0', '0'), +('9', '15', '1', '1', '0'), +('9', '15', '1', '2', '0'), +('9', '15', '1', '3', '0'), + +('9', '15', '2', '0', '0'), +('9', '15', '2', '1', '0'), +('9', '15', '2', '2', '0'), +('9', '15', '2', '3', '0'), + +('9', '15', '3', '0', '0'), +('9', '15', '3', '1', '0'), +('9', '15', '3', '2', '0'), +('9', '15', '3', '3', '0'), + +('9', '15', '4', '0', '0'), +('9', '15', '4', '1', '0'), +('9', '15', '4', '2', '0'), +('9', '15', '4', '3', '0'), + +('9', '15', '5', '0', '0'), +('9', '15', '5', '1', '0'), +('9', '15', '5', '2', '0'), +('9', '15', '5', '3', '0'), + +('9', '15', '6', '0', '0'), +('9', '15', '6', '1', '0'), +('9', '15', '6', '2', '0'), +('9', '15', '6', '3', '0'), + +-- SpellType_InCombatBuffIndex + +('10', '0', '0', '0', '0'), +('10', '0', '0', '1', '0'), +('10', '0', '0', '2', '0'), +('10', '0', '0', '3', '0'), + +('10', '0', '1', '0', '0'), +('10', '0', '1', '1', '0'), +('10', '0', '1', '2', '0'), +('10', '0', '1', '3', '0'), + +('10', '0', '2', '0', '0'), +('10', '0', '2', '1', '0'), +('10', '0', '2', '2', '0'), +('10', '0', '2', '3', '0'), + +('10', '0', '3', '0', '0'), +('10', '0', '3', '1', '0'), +('10', '0', '3', '2', '0'), +('10', '0', '3', '3', '0'), + +('10', '0', '4', '0', '0'), +('10', '0', '4', '1', '0'), +('10', '0', '4', '2', '0'), +('10', '0', '4', '3', '0'), + +('10', '0', '5', '0', '0'), +('10', '0', '5', '1', '0'), +('10', '0', '5', '2', '0'), +('10', '0', '5', '3', '0'), + +('10', '0', '6', '0', '0'), +('10', '0', '6', '1', '0'), +('10', '0', '6', '2', '0'), +('10', '0', '6', '3', '0'), + +('10', '1', '0', '0', '0'), +('10', '1', '0', '1', '0'), +('10', '1', '0', '2', '0'), +('10', '1', '0', '3', '0'), + +('10', '1', '1', '0', '15'), +('10', '1', '1', '1', '15'), +('10', '1', '1', '2', '15'), +('10', '1', '1', '3', '15'), + +('10', '1', '2', '0', '0'), +('10', '1', '2', '1', '0'), +('10', '1', '2', '2', '0'), +('10', '1', '2', '3', '0'), + +('10', '1', '3', '0', '15'), +('10', '1', '3', '1', '15'), +('10', '1', '3', '2', '15'), +('10', '1', '3', '3', '15'), + +('10', '1', '4', '0', '25'), +('10', '1', '4', '1', '25'), +('10', '1', '4', '2', '25'), +('10', '1', '4', '3', '25'), + +('10', '1', '5', '0', '25'), +('10', '1', '5', '1', '25'), +('10', '1', '5', '2', '25'), +('10', '1', '5', '3', '25'), + +('10', '1', '6', '0', '25'), +('10', '1', '6', '1', '25'), +('10', '1', '6', '2', '25'), +('10', '1', '6', '3', '25'), + +('10', '2', '0', '0', '0'), +('10', '2', '0', '1', '0'), +('10', '2', '0', '2', '0'), +('10', '2', '0', '3', '0'), + +('10', '2', '1', '0', '25'), +('10', '2', '1', '1', '25'), +('10', '2', '1', '2', '25'), +('10', '2', '1', '3', '25'), + +('10', '2', '2', '0', '0'), +('10', '2', '2', '1', '0'), +('10', '2', '2', '2', '0'), +('10', '2', '2', '3', '0'), + +('10', '2', '3', '0', '25'), +('10', '2', '3', '1', '25'), +('10', '2', '3', '2', '25'), +('10', '2', '3', '3', '25'), + +('10', '2', '4', '0', '50'), +('10', '2', '4', '1', '50'), +('10', '2', '4', '2', '50'), +('10', '2', '4', '3', '50'), + +('10', '2', '5', '0', '50'), +('10', '2', '5', '1', '50'), +('10', '2', '5', '2', '50'), +('10', '2', '5', '3', '50'), + +('10', '2', '6', '0', '50'), +('10', '2', '6', '1', '50'), +('10', '2', '6', '2', '50'), +('10', '2', '6', '3', '50'), + +('10', '3', '0', '0', '0'), +('10', '3', '0', '1', '0'), +('10', '3', '0', '2', '0'), +('10', '3', '0', '3', '0'), + +('10', '3', '1', '0', '0'), +('10', '3', '1', '1', '0'), +('10', '3', '1', '2', '0'), +('10', '3', '1', '3', '0'), + +('10', '3', '2', '0', '0'), +('10', '3', '2', '1', '0'), +('10', '3', '2', '2', '0'), +('10', '3', '2', '3', '0'), + +('10', '3', '3', '0', '0'), +('10', '3', '3', '1', '0'), +('10', '3', '3', '2', '0'), +('10', '3', '3', '3', '0'), + +('10', '3', '4', '0', '0'), +('10', '3', '4', '1', '0'), +('10', '3', '4', '2', '0'), +('10', '3', '4', '3', '0'), + +('10', '3', '5', '0', '0'), +('10', '3', '5', '1', '0'), +('10', '3', '5', '2', '0'), +('10', '3', '5', '3', '0'), + +('10', '3', '6', '0', '0'), +('10', '3', '6', '1', '0'), +('10', '3', '6', '2', '0'), +('10', '3', '6', '3', '0'), + +('10', '4', '0', '0', '0'), +('10', '4', '0', '1', '0'), +('10', '4', '0', '2', '0'), +('10', '4', '0', '3', '0'), + +('10', '4', '1', '0', '0'), +('10', '4', '1', '1', '0'), +('10', '4', '1', '2', '0'), +('10', '4', '1', '3', '0'), + +('10', '4', '2', '0', '0'), +('10', '4', '2', '1', '0'), +('10', '4', '2', '2', '0'), +('10', '4', '2', '3', '0'), + +('10', '4', '3', '0', '0'), +('10', '4', '3', '1', '0'), +('10', '4', '3', '2', '0'), +('10', '4', '3', '3', '0'), + +('10', '4', '4', '0', '0'), +('10', '4', '4', '1', '0'), +('10', '4', '4', '2', '0'), +('10', '4', '4', '3', '0'), + +('10', '4', '5', '0', '0'), +('10', '4', '5', '1', '0'), +('10', '4', '5', '2', '0'), +('10', '4', '5', '3', '0'), + +('10', '4', '6', '0', '0'), +('10', '4', '6', '1', '0'), +('10', '4', '6', '2', '0'), +('10', '4', '6', '3', '0'), + +('10', '5', '0', '0', '0'), +('10', '5', '0', '1', '0'), +('10', '5', '0', '2', '0'), +('10', '5', '0', '3', '0'), + +('10', '5', '1', '0', '0'), +('10', '5', '1', '1', '0'), +('10', '5', '1', '2', '0'), +('10', '5', '1', '3', '0'), + +('10', '5', '2', '0', '0'), +('10', '5', '2', '1', '0'), +('10', '5', '2', '2', '0'), +('10', '5', '2', '3', '0'), + +('10', '5', '3', '0', '0'), +('10', '5', '3', '1', '0'), +('10', '5', '3', '2', '0'), +('10', '5', '3', '3', '0'), + +('10', '5', '4', '0', '0'), +('10', '5', '4', '1', '0'), +('10', '5', '4', '2', '0'), +('10', '5', '4', '3', '0'), + +('10', '5', '5', '0', '0'), +('10', '5', '5', '1', '0'), +('10', '5', '5', '2', '0'), +('10', '5', '5', '3', '0'), + +('10', '5', '6', '0', '0'), +('10', '5', '6', '1', '0'), +('10', '5', '6', '2', '0'), +('10', '5', '6', '3', '0'), + +('10', '6', '0', '0', '0'), +('10', '6', '0', '1', '0'), +('10', '6', '0', '2', '0'), +('10', '6', '0', '3', '0'), + +('10', '6', '1', '0', '0'), +('10', '6', '1', '1', '0'), +('10', '6', '1', '2', '0'), +('10', '6', '1', '3', '0'), + +('10', '6', '2', '0', '0'), +('10', '6', '2', '1', '0'), +('10', '6', '2', '2', '0'), +('10', '6', '2', '3', '0'), + +('10', '6', '3', '0', '0'), +('10', '6', '3', '1', '0'), +('10', '6', '3', '2', '0'), +('10', '6', '3', '3', '0'), + +('10', '6', '4', '0', '0'), +('10', '6', '4', '1', '0'), +('10', '6', '4', '2', '0'), +('10', '6', '4', '3', '0'), + +('10', '6', '5', '0', '0'), +('10', '6', '5', '1', '0'), +('10', '6', '5', '2', '0'), +('10', '6', '5', '3', '0'), + +('10', '6', '6', '0', '0'), +('10', '6', '6', '1', '0'), +('10', '6', '6', '2', '0'), +('10', '6', '6', '3', '0'), + +('10', '7', '0', '0', '0'), +('10', '7', '0', '1', '0'), +('10', '7', '0', '2', '0'), +('10', '7', '0', '3', '0'), + +('10', '7', '1', '0', '0'), +('10', '7', '1', '1', '0'), +('10', '7', '1', '2', '0'), +('10', '7', '1', '3', '0'), + +('10', '7', '2', '0', '0'), +('10', '7', '2', '1', '0'), +('10', '7', '2', '2', '0'), +('10', '7', '2', '3', '0'), + +('10', '7', '3', '0', '0'), +('10', '7', '3', '1', '0'), +('10', '7', '3', '2', '0'), +('10', '7', '3', '3', '0'), + +('10', '7', '4', '0', '0'), +('10', '7', '4', '1', '0'), +('10', '7', '4', '2', '0'), +('10', '7', '4', '3', '0'), + +('10', '7', '5', '0', '0'), +('10', '7', '5', '1', '0'), +('10', '7', '5', '2', '0'), +('10', '7', '5', '3', '0'), + +('10', '7', '6', '0', '0'), +('10', '7', '6', '1', '0'), +('10', '7', '6', '2', '0'), +('10', '7', '6', '3', '0'), + +('10', '8', '0', '0', '0'), +('10', '8', '0', '1', '0'), +('10', '8', '0', '2', '0'), +('10', '8', '0', '3', '0'), + +('10', '8', '1', '0', '0'), +('10', '8', '1', '1', '0'), +('10', '8', '1', '2', '0'), +('10', '8', '1', '3', '0'), + +('10', '8', '2', '0', '0'), +('10', '8', '2', '1', '0'), +('10', '8', '2', '2', '0'), +('10', '8', '2', '3', '0'), + +('10', '8', '3', '0', '0'), +('10', '8', '3', '1', '0'), +('10', '8', '3', '2', '0'), +('10', '8', '3', '3', '0'), + +('10', '8', '4', '0', '0'), +('10', '8', '4', '1', '0'), +('10', '8', '4', '2', '0'), +('10', '8', '4', '3', '0'), + +('10', '8', '5', '0', '0'), +('10', '8', '5', '1', '0'), +('10', '8', '5', '2', '0'), +('10', '8', '5', '3', '0'), + +('10', '8', '6', '0', '0'), +('10', '8', '6', '1', '0'), +('10', '8', '6', '2', '0'), +('10', '8', '6', '3', '0'), + +('10', '9', '0', '0', '0'), +('10', '9', '0', '1', '0'), +('10', '9', '0', '2', '0'), +('10', '9', '0', '3', '0'), + +('10', '9', '1', '0', '50'), +('10', '9', '1', '1', '75'), +('10', '9', '1', '2', '50'), +('10', '9', '1', '3', '75'), + +('10', '9', '2', '0', '25'), +('10', '9', '2', '1', '50'), +('10', '9', '2', '2', '25'), +('10', '9', '2', '3', '50'), + +('10', '9', '3', '0', '50'), +('10', '9', '3', '1', '75'), +('10', '9', '3', '2', '50'), +('10', '9', '3', '3', '75'), + +('10', '9', '4', '0', '75'), +('10', '9', '4', '1', '100'), +('10', '9', '4', '2', '75'), +('10', '9', '4', '3', '100'), + +('10', '9', '5', '0', '75'), +('10', '9', '5', '1', '100'), +('10', '9', '5', '2', '75'), +('10', '9', '5', '3', '100'), + +('10', '9', '6', '0', '75'), +('10', '9', '6', '1', '100'), +('10', '9', '6', '2', '75'), +('10', '9', '6', '3', '100'), + +('10', '10', '0', '0', '0'), +('10', '10', '0', '1', '0'), +('10', '10', '0', '2', '0'), +('10', '10', '0', '3', '0'), + +('10', '10', '1', '0', '0'), +('10', '10', '1', '1', '0'), +('10', '10', '1', '2', '0'), +('10', '10', '1', '3', '0'), + +('10', '10', '2', '0', '0'), +('10', '10', '2', '1', '0'), +('10', '10', '2', '2', '0'), +('10', '10', '2', '3', '0'), + +('10', '10', '3', '0', '0'), +('10', '10', '3', '1', '0'), +('10', '10', '3', '2', '0'), +('10', '10', '3', '3', '0'), + +('10', '10', '4', '0', '0'), +('10', '10', '4', '1', '0'), +('10', '10', '4', '2', '0'), +('10', '10', '4', '3', '0'), + +('10', '10', '5', '0', '0'), +('10', '10', '5', '1', '0'), +('10', '10', '5', '2', '0'), +('10', '10', '5', '3', '0'), + +('10', '10', '6', '0', '0'), +('10', '10', '6', '1', '0'), +('10', '10', '6', '2', '0'), +('10', '10', '6', '3', '0'), + +('10', '11', '0', '0', '0'), +('10', '11', '0', '1', '0'), +('10', '11', '0', '2', '0'), +('10', '11', '0', '3', '0'), + +('10', '11', '1', '0', '0'), +('10', '11', '1', '1', '0'), +('10', '11', '1', '2', '0'), +('10', '11', '1', '3', '0'), + +('10', '11', '2', '0', '0'), +('10', '11', '2', '1', '0'), +('10', '11', '2', '2', '0'), +('10', '11', '2', '3', '0'), + +('10', '11', '3', '0', '0'), +('10', '11', '3', '1', '0'), +('10', '11', '3', '2', '0'), +('10', '11', '3', '3', '0'), + +('10', '11', '4', '0', '0'), +('10', '11', '4', '1', '0'), +('10', '11', '4', '2', '0'), +('10', '11', '4', '3', '0'), + +('10', '11', '5', '0', '0'), +('10', '11', '5', '1', '0'), +('10', '11', '5', '2', '0'), +('10', '11', '5', '3', '0'), + +('10', '11', '6', '0', '0'), +('10', '11', '6', '1', '0'), +('10', '11', '6', '2', '0'), +('10', '11', '6', '3', '0'), + +('10', '12', '0', '0', '0'), +('10', '12', '0', '1', '0'), +('10', '12', '0', '2', '0'), +('10', '12', '0', '3', '0'), + +('10', '12', '1', '0', '0'), +('10', '12', '1', '1', '0'), +('10', '12', '1', '2', '0'), +('10', '12', '1', '3', '0'), + +('10', '12', '2', '0', '0'), +('10', '12', '2', '1', '0'), +('10', '12', '2', '2', '0'), +('10', '12', '2', '3', '0'), + +('10', '12', '3', '0', '0'), +('10', '12', '3', '1', '0'), +('10', '12', '3', '2', '0'), +('10', '12', '3', '3', '0'), + +('10', '12', '4', '0', '0'), +('10', '12', '4', '1', '0'), +('10', '12', '4', '2', '0'), +('10', '12', '4', '3', '0'), + +('10', '12', '5', '0', '0'), +('10', '12', '5', '1', '0'), +('10', '12', '5', '2', '0'), +('10', '12', '5', '3', '0'), + +('10', '12', '6', '0', '0'), +('10', '12', '6', '1', '0'), +('10', '12', '6', '2', '0'), +('10', '12', '6', '3', '0'), + +('10', '13', '0', '0', '0'), +('10', '13', '0', '1', '0'), +('10', '13', '0', '2', '0'), +('10', '13', '0', '3', '0'), + +('10', '13', '1', '0', '0'), +('10', '13', '1', '1', '0'), +('10', '13', '1', '2', '0'), +('10', '13', '1', '3', '0'), + +('10', '13', '2', '0', '0'), +('10', '13', '2', '1', '0'), +('10', '13', '2', '2', '0'), +('10', '13', '2', '3', '0'), + +('10', '13', '3', '0', '0'), +('10', '13', '3', '1', '0'), +('10', '13', '3', '2', '0'), +('10', '13', '3', '3', '0'), + +('10', '13', '4', '0', '0'), +('10', '13', '4', '1', '0'), +('10', '13', '4', '2', '0'), +('10', '13', '4', '3', '0'), + +('10', '13', '5', '0', '0'), +('10', '13', '5', '1', '0'), +('10', '13', '5', '2', '0'), +('10', '13', '5', '3', '0'), + +('10', '13', '6', '0', '0'), +('10', '13', '6', '1', '0'), +('10', '13', '6', '2', '0'), +('10', '13', '6', '3', '0'), + +('10', '14', '0', '0', '0'), +('10', '14', '0', '1', '0'), +('10', '14', '0', '2', '0'), +('10', '14', '0', '3', '0'), + +('10', '14', '1', '0', '0'), +('10', '14', '1', '1', '0'), +('10', '14', '1', '2', '0'), +('10', '14', '1', '3', '0'), + +('10', '14', '2', '0', '0'), +('10', '14', '2', '1', '0'), +('10', '14', '2', '2', '0'), +('10', '14', '2', '3', '0'), + +('10', '14', '3', '0', '0'), +('10', '14', '3', '1', '0'), +('10', '14', '3', '2', '0'), +('10', '14', '3', '3', '0'), + +('10', '14', '4', '0', '0'), +('10', '14', '4', '1', '0'), +('10', '14', '4', '2', '0'), +('10', '14', '4', '3', '0'), + +('10', '14', '5', '0', '0'), +('10', '14', '5', '1', '0'), +('10', '14', '5', '2', '0'), +('10', '14', '5', '3', '0'), + +('10', '14', '6', '0', '0'), +('10', '14', '6', '1', '0'), +('10', '14', '6', '2', '0'), +('10', '14', '6', '3', '0'), + +('10', '15', '0', '0', '0'), +('10', '15', '0', '1', '0'), +('10', '15', '0', '2', '0'), +('10', '15', '0', '3', '0'), + +('10', '15', '1', '0', '0'), +('10', '15', '1', '1', '0'), +('10', '15', '1', '2', '0'), +('10', '15', '1', '3', '0'), + +('10', '15', '2', '0', '0'), +('10', '15', '2', '1', '0'), +('10', '15', '2', '2', '0'), +('10', '15', '2', '3', '0'), + +('10', '15', '3', '0', '0'), +('10', '15', '3', '1', '0'), +('10', '15', '3', '2', '0'), +('10', '15', '3', '3', '0'), + +('10', '15', '4', '0', '0'), +('10', '15', '4', '1', '0'), +('10', '15', '4', '2', '0'), +('10', '15', '4', '3', '0'), + +('10', '15', '5', '0', '0'), +('10', '15', '5', '1', '0'), +('10', '15', '5', '2', '0'), +('10', '15', '5', '3', '0'), + +('10', '15', '6', '0', '0'), +('10', '15', '6', '1', '0'), +('10', '15', '6', '2', '0'), +('10', '15', '6', '3', '0'), + +-- SpellType_MezIndex + +('11', '0', '0', '0', '0'), +('11', '0', '0', '1', '0'), +('11', '0', '0', '2', '0'), +('11', '0', '0', '3', '0'), + +('11', '0', '1', '0', '0'), +('11', '0', '1', '1', '0'), +('11', '0', '1', '2', '0'), +('11', '0', '1', '3', '0'), + +('11', '0', '2', '0', '0'), +('11', '0', '2', '1', '0'), +('11', '0', '2', '2', '0'), +('11', '0', '2', '3', '0'), + +('11', '0', '3', '0', '0'), +('11', '0', '3', '1', '0'), +('11', '0', '3', '2', '0'), +('11', '0', '3', '3', '0'), + +('11', '0', '4', '0', '0'), +('11', '0', '4', '1', '0'), +('11', '0', '4', '2', '0'), +('11', '0', '4', '3', '0'), + +('11', '0', '5', '0', '0'), +('11', '0', '5', '1', '0'), +('11', '0', '5', '2', '0'), +('11', '0', '5', '3', '0'), + +('11', '0', '6', '0', '0'), +('11', '0', '6', '1', '0'), +('11', '0', '6', '2', '0'), +('11', '0', '6', '3', '0'), + +('11', '1', '0', '0', '0'), +('11', '1', '0', '1', '0'), +('11', '1', '0', '2', '0'), +('11', '1', '0', '3', '0'), + +('11', '1', '1', '0', '0'), +('11', '1', '1', '1', '0'), +('11', '1', '1', '2', '0'), +('11', '1', '1', '3', '0'), + +('11', '1', '2', '0', '0'), +('11', '1', '2', '1', '0'), +('11', '1', '2', '2', '0'), +('11', '1', '2', '3', '0'), + +('11', '1', '3', '0', '0'), +('11', '1', '3', '1', '0'), +('11', '1', '3', '2', '0'), +('11', '1', '3', '3', '0'), + +('11', '1', '4', '0', '0'), +('11', '1', '4', '1', '0'), +('11', '1', '4', '2', '0'), +('11', '1', '4', '3', '0'), + +('11', '1', '5', '0', '0'), +('11', '1', '5', '1', '0'), +('11', '1', '5', '2', '0'), +('11', '1', '5', '3', '0'), + +('11', '1', '6', '0', '0'), +('11', '1', '6', '1', '0'), +('11', '1', '6', '2', '0'), +('11', '1', '6', '3', '0'), + +('11', '2', '0', '0', '0'), +('11', '2', '0', '1', '0'), +('11', '2', '0', '2', '0'), +('11', '2', '0', '3', '0'), + +('11', '2', '1', '0', '0'), +('11', '2', '1', '1', '0'), +('11', '2', '1', '2', '0'), +('11', '2', '1', '3', '0'), + +('11', '2', '2', '0', '0'), +('11', '2', '2', '1', '0'), +('11', '2', '2', '2', '0'), +('11', '2', '2', '3', '0'), + +('11', '2', '3', '0', '0'), +('11', '2', '3', '1', '0'), +('11', '2', '3', '2', '0'), +('11', '2', '3', '3', '0'), + +('11', '2', '4', '0', '0'), +('11', '2', '4', '1', '0'), +('11', '2', '4', '2', '0'), +('11', '2', '4', '3', '0'), + +('11', '2', '5', '0', '0'), +('11', '2', '5', '1', '0'), +('11', '2', '5', '2', '0'), +('11', '2', '5', '3', '0'), + +('11', '2', '6', '0', '0'), +('11', '2', '6', '1', '0'), +('11', '2', '6', '2', '0'), +('11', '2', '6', '3', '0'), + +('11', '3', '0', '0', '0'), +('11', '3', '0', '1', '0'), +('11', '3', '0', '2', '0'), +('11', '3', '0', '3', '0'), + +('11', '3', '1', '0', '0'), +('11', '3', '1', '1', '0'), +('11', '3', '1', '2', '0'), +('11', '3', '1', '3', '0'), + +('11', '3', '2', '0', '0'), +('11', '3', '2', '1', '0'), +('11', '3', '2', '2', '0'), +('11', '3', '2', '3', '0'), + +('11', '3', '3', '0', '0'), +('11', '3', '3', '1', '0'), +('11', '3', '3', '2', '0'), +('11', '3', '3', '3', '0'), + +('11', '3', '4', '0', '0'), +('11', '3', '4', '1', '0'), +('11', '3', '4', '2', '0'), +('11', '3', '4', '3', '0'), + +('11', '3', '5', '0', '0'), +('11', '3', '5', '1', '0'), +('11', '3', '5', '2', '0'), +('11', '3', '5', '3', '0'), + +('11', '3', '6', '0', '0'), +('11', '3', '6', '1', '0'), +('11', '3', '6', '2', '0'), +('11', '3', '6', '3', '0'), + +('11', '4', '0', '0', '0'), +('11', '4', '0', '1', '0'), +('11', '4', '0', '2', '0'), +('11', '4', '0', '3', '0'), + +('11', '4', '1', '0', '0'), +('11', '4', '1', '1', '0'), +('11', '4', '1', '2', '0'), +('11', '4', '1', '3', '0'), + +('11', '4', '2', '0', '0'), +('11', '4', '2', '1', '0'), +('11', '4', '2', '2', '0'), +('11', '4', '2', '3', '0'), + +('11', '4', '3', '0', '0'), +('11', '4', '3', '1', '0'), +('11', '4', '3', '2', '0'), +('11', '4', '3', '3', '0'), + +('11', '4', '4', '0', '0'), +('11', '4', '4', '1', '0'), +('11', '4', '4', '2', '0'), +('11', '4', '4', '3', '0'), + +('11', '4', '5', '0', '0'), +('11', '4', '5', '1', '0'), +('11', '4', '5', '2', '0'), +('11', '4', '5', '3', '0'), + +('11', '4', '6', '0', '0'), +('11', '4', '6', '1', '0'), +('11', '4', '6', '2', '0'), +('11', '4', '6', '3', '0'), + +('11', '5', '0', '0', '0'), +('11', '5', '0', '1', '0'), +('11', '5', '0', '2', '0'), +('11', '5', '0', '3', '0'), + +('11', '5', '1', '0', '0'), +('11', '5', '1', '1', '0'), +('11', '5', '1', '2', '0'), +('11', '5', '1', '3', '0'), + +('11', '5', '2', '0', '0'), +('11', '5', '2', '1', '0'), +('11', '5', '2', '2', '0'), +('11', '5', '2', '3', '0'), + +('11', '5', '3', '0', '0'), +('11', '5', '3', '1', '0'), +('11', '5', '3', '2', '0'), +('11', '5', '3', '3', '0'), + +('11', '5', '4', '0', '0'), +('11', '5', '4', '1', '0'), +('11', '5', '4', '2', '0'), +('11', '5', '4', '3', '0'), + +('11', '5', '5', '0', '0'), +('11', '5', '5', '1', '0'), +('11', '5', '5', '2', '0'), +('11', '5', '5', '3', '0'), + +('11', '5', '6', '0', '0'), +('11', '5', '6', '1', '0'), +('11', '5', '6', '2', '0'), +('11', '5', '6', '3', '0'), + +('11', '6', '0', '0', '0'), +('11', '6', '0', '1', '0'), +('11', '6', '0', '2', '0'), +('11', '6', '0', '3', '0'), + +('11', '6', '1', '0', '0'), +('11', '6', '1', '1', '0'), +('11', '6', '1', '2', '0'), +('11', '6', '1', '3', '0'), + +('11', '6', '2', '0', '0'), +('11', '6', '2', '1', '0'), +('11', '6', '2', '2', '0'), +('11', '6', '2', '3', '0'), + +('11', '6', '3', '0', '0'), +('11', '6', '3', '1', '0'), +('11', '6', '3', '2', '0'), +('11', '6', '3', '3', '0'), + +('11', '6', '4', '0', '0'), +('11', '6', '4', '1', '0'), +('11', '6', '4', '2', '0'), +('11', '6', '4', '3', '0'), + +('11', '6', '5', '0', '0'), +('11', '6', '5', '1', '0'), +('11', '6', '5', '2', '0'), +('11', '6', '5', '3', '0'), + +('11', '6', '6', '0', '0'), +('11', '6', '6', '1', '0'), +('11', '6', '6', '2', '0'), +('11', '6', '6', '3', '0'), + +('11', '7', '0', '0', '0'), +('11', '7', '0', '1', '0'), +('11', '7', '0', '2', '0'), +('11', '7', '0', '3', '0'), + +('11', '7', '1', '0', '0'), +('11', '7', '1', '1', '0'), +('11', '7', '1', '2', '0'), +('11', '7', '1', '3', '0'), + +('11', '7', '2', '0', '0'), +('11', '7', '2', '1', '0'), +('11', '7', '2', '2', '0'), +('11', '7', '2', '3', '0'), + +('11', '7', '3', '0', '0'), +('11', '7', '3', '1', '0'), +('11', '7', '3', '2', '0'), +('11', '7', '3', '3', '0'), + +('11', '7', '4', '0', '0'), +('11', '7', '4', '1', '0'), +('11', '7', '4', '2', '0'), +('11', '7', '4', '3', '0'), + +('11', '7', '5', '0', '0'), +('11', '7', '5', '1', '0'), +('11', '7', '5', '2', '0'), +('11', '7', '5', '3', '0'), + +('11', '7', '6', '0', '0'), +('11', '7', '6', '1', '0'), +('11', '7', '6', '2', '0'), +('11', '7', '6', '3', '0'), + +('11', '8', '0', '0', '0'), +('11', '8', '0', '1', '0'), +('11', '8', '0', '2', '0'), +('11', '8', '0', '3', '0'), + +('11', '8', '1', '0', '0'), +('11', '8', '1', '1', '0'), +('11', '8', '1', '2', '0'), +('11', '8', '1', '3', '0'), + +('11', '8', '2', '0', '0'), +('11', '8', '2', '1', '0'), +('11', '8', '2', '2', '0'), +('11', '8', '2', '3', '0'), + +('11', '8', '3', '0', '0'), +('11', '8', '3', '1', '0'), +('11', '8', '3', '2', '0'), +('11', '8', '3', '3', '0'), + +('11', '8', '4', '0', '0'), +('11', '8', '4', '1', '0'), +('11', '8', '4', '2', '0'), +('11', '8', '4', '3', '0'), + +('11', '8', '5', '0', '0'), +('11', '8', '5', '1', '0'), +('11', '8', '5', '2', '0'), +('11', '8', '5', '3', '0'), + +('11', '8', '6', '0', '0'), +('11', '8', '6', '1', '0'), +('11', '8', '6', '2', '0'), +('11', '8', '6', '3', '0'), + +('11', '9', '0', '0', '0'), +('11', '9', '0', '1', '0'), +('11', '9', '0', '2', '0'), +('11', '9', '0', '3', '0'), + +('11', '9', '1', '0', '0'), +('11', '9', '1', '1', '0'), +('11', '9', '1', '2', '0'), +('11', '9', '1', '3', '0'), + +('11', '9', '2', '0', '0'), +('11', '9', '2', '1', '0'), +('11', '9', '2', '2', '0'), +('11', '9', '2', '3', '0'), + +('11', '9', '3', '0', '0'), +('11', '9', '3', '1', '0'), +('11', '9', '3', '2', '0'), +('11', '9', '3', '3', '0'), + +('11', '9', '4', '0', '0'), +('11', '9', '4', '1', '0'), +('11', '9', '4', '2', '0'), +('11', '9', '4', '3', '0'), + +('11', '9', '5', '0', '0'), +('11', '9', '5', '1', '0'), +('11', '9', '5', '2', '0'), +('11', '9', '5', '3', '0'), + +('11', '9', '6', '0', '0'), +('11', '9', '6', '1', '0'), +('11', '9', '6', '2', '0'), +('11', '9', '6', '3', '0'), + +('11', '10', '0', '0', '0'), +('11', '10', '0', '1', '0'), +('11', '10', '0', '2', '0'), +('11', '10', '0', '3', '0'), + +('11', '10', '1', '0', '0'), +('11', '10', '1', '1', '0'), +('11', '10', '1', '2', '0'), +('11', '10', '1', '3', '0'), + +('11', '10', '2', '0', '0'), +('11', '10', '2', '1', '0'), +('11', '10', '2', '2', '0'), +('11', '10', '2', '3', '0'), + +('11', '10', '3', '0', '0'), +('11', '10', '3', '1', '0'), +('11', '10', '3', '2', '0'), +('11', '10', '3', '3', '0'), + +('11', '10', '4', '0', '0'), +('11', '10', '4', '1', '0'), +('11', '10', '4', '2', '0'), +('11', '10', '4', '3', '0'), + +('11', '10', '5', '0', '0'), +('11', '10', '5', '1', '0'), +('11', '10', '5', '2', '0'), +('11', '10', '5', '3', '0'), + +('11', '10', '6', '0', '0'), +('11', '10', '6', '1', '0'), +('11', '10', '6', '2', '0'), +('11', '10', '6', '3', '0'), + +('11', '11', '0', '0', '0'), +('11', '11', '0', '1', '0'), +('11', '11', '0', '2', '0'), +('11', '11', '0', '3', '0'), + +('11', '11', '1', '0', '0'), +('11', '11', '1', '1', '0'), +('11', '11', '1', '2', '0'), +('11', '11', '1', '3', '0'), + +('11', '11', '2', '0', '0'), +('11', '11', '2', '1', '0'), +('11', '11', '2', '2', '0'), +('11', '11', '2', '3', '0'), + +('11', '11', '3', '0', '0'), +('11', '11', '3', '1', '0'), +('11', '11', '3', '2', '0'), +('11', '11', '3', '3', '0'), + +('11', '11', '4', '0', '0'), +('11', '11', '4', '1', '0'), +('11', '11', '4', '2', '0'), +('11', '11', '4', '3', '0'), + +('11', '11', '5', '0', '0'), +('11', '11', '5', '1', '0'), +('11', '11', '5', '2', '0'), +('11', '11', '5', '3', '0'), + +('11', '11', '6', '0', '0'), +('11', '11', '6', '1', '0'), +('11', '11', '6', '2', '0'), +('11', '11', '6', '3', '0'), + +('11', '12', '0', '0', '0'), +('11', '12', '0', '1', '0'), +('11', '12', '0', '2', '0'), +('11', '12', '0', '3', '0'), + +('11', '12', '1', '0', '0'), +('11', '12', '1', '1', '0'), +('11', '12', '1', '2', '0'), +('11', '12', '1', '3', '0'), + +('11', '12', '2', '0', '0'), +('11', '12', '2', '1', '0'), +('11', '12', '2', '2', '0'), +('11', '12', '2', '3', '0'), + +('11', '12', '3', '0', '0'), +('11', '12', '3', '1', '0'), +('11', '12', '3', '2', '0'), +('11', '12', '3', '3', '0'), + +('11', '12', '4', '0', '0'), +('11', '12', '4', '1', '0'), +('11', '12', '4', '2', '0'), +('11', '12', '4', '3', '0'), + +('11', '12', '5', '0', '0'), +('11', '12', '5', '1', '0'), +('11', '12', '5', '2', '0'), +('11', '12', '5', '3', '0'), + +('11', '12', '6', '0', '0'), +('11', '12', '6', '1', '0'), +('11', '12', '6', '2', '0'), +('11', '12', '6', '3', '0'), + +('11', '13', '0', '0', '0'), +('11', '13', '0', '1', '0'), +('11', '13', '0', '2', '0'), +('11', '13', '0', '3', '0'), + +('11', '13', '1', '0', '0'), +('11', '13', '1', '1', '0'), +('11', '13', '1', '2', '0'), +('11', '13', '1', '3', '0'), + +('11', '13', '2', '0', '0'), +('11', '13', '2', '1', '0'), +('11', '13', '2', '2', '0'), +('11', '13', '2', '3', '0'), + +('11', '13', '3', '0', '0'), +('11', '13', '3', '1', '0'), +('11', '13', '3', '2', '0'), +('11', '13', '3', '3', '0'), + +('11', '13', '4', '0', '0'), +('11', '13', '4', '1', '0'), +('11', '13', '4', '2', '0'), +('11', '13', '4', '3', '0'), + +('11', '13', '5', '0', '0'), +('11', '13', '5', '1', '0'), +('11', '13', '5', '2', '0'), +('11', '13', '5', '3', '0'), + +('11', '13', '6', '0', '0'), +('11', '13', '6', '1', '0'), +('11', '13', '6', '2', '0'), +('11', '13', '6', '3', '0'), + +('11', '14', '0', '0', '0'), +('11', '14', '0', '1', '0'), +('11', '14', '0', '2', '0'), +('11', '14', '0', '3', '0'), + +('11', '14', '1', '0', '0'), +('11', '14', '1', '1', '0'), +('11', '14', '1', '2', '0'), +('11', '14', '1', '3', '0'), + +('11', '14', '2', '0', '0'), +('11', '14', '2', '1', '0'), +('11', '14', '2', '2', '0'), +('11', '14', '2', '3', '0'), + +('11', '14', '3', '0', '0'), +('11', '14', '3', '1', '0'), +('11', '14', '3', '2', '0'), +('11', '14', '3', '3', '0'), + +('11', '14', '4', '0', '0'), +('11', '14', '4', '1', '0'), +('11', '14', '4', '2', '0'), +('11', '14', '4', '3', '0'), + +('11', '14', '5', '0', '0'), +('11', '14', '5', '1', '0'), +('11', '14', '5', '2', '0'), +('11', '14', '5', '3', '0'), + +('11', '14', '6', '0', '0'), +('11', '14', '6', '1', '0'), +('11', '14', '6', '2', '0'), +('11', '14', '6', '3', '0'), + +('11', '15', '0', '0', '0'), +('11', '15', '0', '1', '0'), +('11', '15', '0', '2', '0'), +('11', '15', '0', '3', '0'), + +('11', '15', '1', '0', '0'), +('11', '15', '1', '1', '0'), +('11', '15', '1', '2', '0'), +('11', '15', '1', '3', '0'), + +('11', '15', '2', '0', '0'), +('11', '15', '2', '1', '0'), +('11', '15', '2', '2', '0'), +('11', '15', '2', '3', '0'), + +('11', '15', '3', '0', '0'), +('11', '15', '3', '1', '0'), +('11', '15', '3', '2', '0'), +('11', '15', '3', '3', '0'), + +('11', '15', '4', '0', '0'), +('11', '15', '4', '1', '0'), +('11', '15', '4', '2', '0'), +('11', '15', '4', '3', '0'), + +('11', '15', '5', '0', '0'), +('11', '15', '5', '1', '0'), +('11', '15', '5', '2', '0'), +('11', '15', '5', '3', '0'), + +('11', '15', '6', '0', '0'), +('11', '15', '6', '1', '0'), +('11', '15', '6', '2', '0'), +('11', '15', '6', '3', '0'), + +-- SpellType_CharmIndex + +('12', '0', '0', '0', '0'), +('12', '0', '0', '1', '0'), +('12', '0', '0', '2', '0'), +('12', '0', '0', '3', '0'), + +('12', '0', '1', '0', '0'), +('12', '0', '1', '1', '0'), +('12', '0', '1', '2', '0'), +('12', '0', '1', '3', '0'), + +('12', '0', '2', '0', '0'), +('12', '0', '2', '1', '0'), +('12', '0', '2', '2', '0'), +('12', '0', '2', '3', '0'), + +('12', '0', '3', '0', '0'), +('12', '0', '3', '1', '0'), +('12', '0', '3', '2', '0'), +('12', '0', '3', '3', '0'), + +('12', '0', '4', '0', '0'), +('12', '0', '4', '1', '0'), +('12', '0', '4', '2', '0'), +('12', '0', '4', '3', '0'), + +('12', '0', '5', '0', '0'), +('12', '0', '5', '1', '0'), +('12', '0', '5', '2', '0'), +('12', '0', '5', '3', '0'), + +('12', '0', '6', '0', '0'), +('12', '0', '6', '1', '0'), +('12', '0', '6', '2', '0'), +('12', '0', '6', '3', '0'), + +('12', '1', '0', '0', '0'), +('12', '1', '0', '1', '0'), +('12', '1', '0', '2', '0'), +('12', '1', '0', '3', '0'), + +('12', '1', '1', '0', '0'), +('12', '1', '1', '1', '0'), +('12', '1', '1', '2', '0'), +('12', '1', '1', '3', '0'), + +('12', '1', '2', '0', '0'), +('12', '1', '2', '1', '0'), +('12', '1', '2', '2', '0'), +('12', '1', '2', '3', '0'), + +('12', '1', '3', '0', '0'), +('12', '1', '3', '1', '0'), +('12', '1', '3', '2', '0'), +('12', '1', '3', '3', '0'), + +('12', '1', '4', '0', '0'), +('12', '1', '4', '1', '0'), +('12', '1', '4', '2', '0'), +('12', '1', '4', '3', '0'), + +('12', '1', '5', '0', '0'), +('12', '1', '5', '1', '0'), +('12', '1', '5', '2', '0'), +('12', '1', '5', '3', '0'), + +('12', '1', '6', '0', '0'), +('12', '1', '6', '1', '0'), +('12', '1', '6', '2', '0'), +('12', '1', '6', '3', '0'), + +('12', '2', '0', '0', '0'), +('12', '2', '0', '1', '0'), +('12', '2', '0', '2', '0'), +('12', '2', '0', '3', '0'), + +('12', '2', '1', '0', '0'), +('12', '2', '1', '1', '0'), +('12', '2', '1', '2', '0'), +('12', '2', '1', '3', '0'), + +('12', '2', '2', '0', '0'), +('12', '2', '2', '1', '0'), +('12', '2', '2', '2', '0'), +('12', '2', '2', '3', '0'), + +('12', '2', '3', '0', '0'), +('12', '2', '3', '1', '0'), +('12', '2', '3', '2', '0'), +('12', '2', '3', '3', '0'), + +('12', '2', '4', '0', '0'), +('12', '2', '4', '1', '0'), +('12', '2', '4', '2', '0'), +('12', '2', '4', '3', '0'), + +('12', '2', '5', '0', '0'), +('12', '2', '5', '1', '0'), +('12', '2', '5', '2', '0'), +('12', '2', '5', '3', '0'), + +('12', '2', '6', '0', '0'), +('12', '2', '6', '1', '0'), +('12', '2', '6', '2', '0'), +('12', '2', '6', '3', '0'), + +('12', '3', '0', '0', '0'), +('12', '3', '0', '1', '0'), +('12', '3', '0', '2', '0'), +('12', '3', '0', '3', '0'), + +('12', '3', '1', '0', '0'), +('12', '3', '1', '1', '0'), +('12', '3', '1', '2', '0'), +('12', '3', '1', '3', '0'), + +('12', '3', '2', '0', '0'), +('12', '3', '2', '1', '0'), +('12', '3', '2', '2', '0'), +('12', '3', '2', '3', '0'), + +('12', '3', '3', '0', '0'), +('12', '3', '3', '1', '0'), +('12', '3', '3', '2', '0'), +('12', '3', '3', '3', '0'), + +('12', '3', '4', '0', '0'), +('12', '3', '4', '1', '0'), +('12', '3', '4', '2', '0'), +('12', '3', '4', '3', '0'), + +('12', '3', '5', '0', '0'), +('12', '3', '5', '1', '0'), +('12', '3', '5', '2', '0'), +('12', '3', '5', '3', '0'), + +('12', '3', '6', '0', '0'), +('12', '3', '6', '1', '0'), +('12', '3', '6', '2', '0'), +('12', '3', '6', '3', '0'), + +('12', '4', '0', '0', '0'), +('12', '4', '0', '1', '0'), +('12', '4', '0', '2', '0'), +('12', '4', '0', '3', '0'), + +('12', '4', '1', '0', '0'), +('12', '4', '1', '1', '0'), +('12', '4', '1', '2', '0'), +('12', '4', '1', '3', '0'), + +('12', '4', '2', '0', '0'), +('12', '4', '2', '1', '0'), +('12', '4', '2', '2', '0'), +('12', '4', '2', '3', '0'), + +('12', '4', '3', '0', '0'), +('12', '4', '3', '1', '0'), +('12', '4', '3', '2', '0'), +('12', '4', '3', '3', '0'), + +('12', '4', '4', '0', '0'), +('12', '4', '4', '1', '0'), +('12', '4', '4', '2', '0'), +('12', '4', '4', '3', '0'), + +('12', '4', '5', '0', '0'), +('12', '4', '5', '1', '0'), +('12', '4', '5', '2', '0'), +('12', '4', '5', '3', '0'), + +('12', '4', '6', '0', '0'), +('12', '4', '6', '1', '0'), +('12', '4', '6', '2', '0'), +('12', '4', '6', '3', '0'), + +('12', '5', '0', '0', '0'), +('12', '5', '0', '1', '0'), +('12', '5', '0', '2', '0'), +('12', '5', '0', '3', '0'), + +('12', '5', '1', '0', '0'), +('12', '5', '1', '1', '0'), +('12', '5', '1', '2', '0'), +('12', '5', '1', '3', '0'), + +('12', '5', '2', '0', '0'), +('12', '5', '2', '1', '0'), +('12', '5', '2', '2', '0'), +('12', '5', '2', '3', '0'), + +('12', '5', '3', '0', '0'), +('12', '5', '3', '1', '0'), +('12', '5', '3', '2', '0'), +('12', '5', '3', '3', '0'), + +('12', '5', '4', '0', '0'), +('12', '5', '4', '1', '0'), +('12', '5', '4', '2', '0'), +('12', '5', '4', '3', '0'), + +('12', '5', '5', '0', '0'), +('12', '5', '5', '1', '0'), +('12', '5', '5', '2', '0'), +('12', '5', '5', '3', '0'), + +('12', '5', '6', '0', '0'), +('12', '5', '6', '1', '0'), +('12', '5', '6', '2', '0'), +('12', '5', '6', '3', '0'), + +('12', '6', '0', '0', '0'), +('12', '6', '0', '1', '0'), +('12', '6', '0', '2', '0'), +('12', '6', '0', '3', '0'), + +('12', '6', '1', '0', '0'), +('12', '6', '1', '1', '0'), +('12', '6', '1', '2', '0'), +('12', '6', '1', '3', '0'), + +('12', '6', '2', '0', '0'), +('12', '6', '2', '1', '0'), +('12', '6', '2', '2', '0'), +('12', '6', '2', '3', '0'), + +('12', '6', '3', '0', '0'), +('12', '6', '3', '1', '0'), +('12', '6', '3', '2', '0'), +('12', '6', '3', '3', '0'), + +('12', '6', '4', '0', '0'), +('12', '6', '4', '1', '0'), +('12', '6', '4', '2', '0'), +('12', '6', '4', '3', '0'), + +('12', '6', '5', '0', '0'), +('12', '6', '5', '1', '0'), +('12', '6', '5', '2', '0'), +('12', '6', '5', '3', '0'), + +('12', '6', '6', '0', '0'), +('12', '6', '6', '1', '0'), +('12', '6', '6', '2', '0'), +('12', '6', '6', '3', '0'), + +('12', '7', '0', '0', '0'), +('12', '7', '0', '1', '0'), +('12', '7', '0', '2', '0'), +('12', '7', '0', '3', '0'), + +('12', '7', '1', '0', '0'), +('12', '7', '1', '1', '0'), +('12', '7', '1', '2', '0'), +('12', '7', '1', '3', '0'), + +('12', '7', '2', '0', '0'), +('12', '7', '2', '1', '0'), +('12', '7', '2', '2', '0'), +('12', '7', '2', '3', '0'), + +('12', '7', '3', '0', '0'), +('12', '7', '3', '1', '0'), +('12', '7', '3', '2', '0'), +('12', '7', '3', '3', '0'), + +('12', '7', '4', '0', '0'), +('12', '7', '4', '1', '0'), +('12', '7', '4', '2', '0'), +('12', '7', '4', '3', '0'), + +('12', '7', '5', '0', '0'), +('12', '7', '5', '1', '0'), +('12', '7', '5', '2', '0'), +('12', '7', '5', '3', '0'), + +('12', '7', '6', '0', '0'), +('12', '7', '6', '1', '0'), +('12', '7', '6', '2', '0'), +('12', '7', '6', '3', '0'), + +('12', '8', '0', '0', '0'), +('12', '8', '0', '1', '0'), +('12', '8', '0', '2', '0'), +('12', '8', '0', '3', '0'), + +('12', '8', '1', '0', '0'), +('12', '8', '1', '1', '0'), +('12', '8', '1', '2', '0'), +('12', '8', '1', '3', '0'), + +('12', '8', '2', '0', '0'), +('12', '8', '2', '1', '0'), +('12', '8', '2', '2', '0'), +('12', '8', '2', '3', '0'), + +('12', '8', '3', '0', '0'), +('12', '8', '3', '1', '0'), +('12', '8', '3', '2', '0'), +('12', '8', '3', '3', '0'), + +('12', '8', '4', '0', '0'), +('12', '8', '4', '1', '0'), +('12', '8', '4', '2', '0'), +('12', '8', '4', '3', '0'), + +('12', '8', '5', '0', '0'), +('12', '8', '5', '1', '0'), +('12', '8', '5', '2', '0'), +('12', '8', '5', '3', '0'), + +('12', '8', '6', '0', '0'), +('12', '8', '6', '1', '0'), +('12', '8', '6', '2', '0'), +('12', '8', '6', '3', '0'), + +('12', '9', '0', '0', '0'), +('12', '9', '0', '1', '0'), +('12', '9', '0', '2', '0'), +('12', '9', '0', '3', '0'), + +('12', '9', '1', '0', '0'), +('12', '9', '1', '1', '0'), +('12', '9', '1', '2', '0'), +('12', '9', '1', '3', '0'), + +('12', '9', '2', '0', '0'), +('12', '9', '2', '1', '0'), +('12', '9', '2', '2', '0'), +('12', '9', '2', '3', '0'), + +('12', '9', '3', '0', '0'), +('12', '9', '3', '1', '0'), +('12', '9', '3', '2', '0'), +('12', '9', '3', '3', '0'), + +('12', '9', '4', '0', '0'), +('12', '9', '4', '1', '0'), +('12', '9', '4', '2', '0'), +('12', '9', '4', '3', '0'), + +('12', '9', '5', '0', '0'), +('12', '9', '5', '1', '0'), +('12', '9', '5', '2', '0'), +('12', '9', '5', '3', '0'), + +('12', '9', '6', '0', '0'), +('12', '9', '6', '1', '0'), +('12', '9', '6', '2', '0'), +('12', '9', '6', '3', '0'), + +('12', '10', '0', '0', '0'), +('12', '10', '0', '1', '0'), +('12', '10', '0', '2', '0'), +('12', '10', '0', '3', '0'), + +('12', '10', '1', '0', '0'), +('12', '10', '1', '1', '0'), +('12', '10', '1', '2', '0'), +('12', '10', '1', '3', '0'), + +('12', '10', '2', '0', '0'), +('12', '10', '2', '1', '0'), +('12', '10', '2', '2', '0'), +('12', '10', '2', '3', '0'), + +('12', '10', '3', '0', '0'), +('12', '10', '3', '1', '0'), +('12', '10', '3', '2', '0'), +('12', '10', '3', '3', '0'), + +('12', '10', '4', '0', '0'), +('12', '10', '4', '1', '0'), +('12', '10', '4', '2', '0'), +('12', '10', '4', '3', '0'), + +('12', '10', '5', '0', '0'), +('12', '10', '5', '1', '0'), +('12', '10', '5', '2', '0'), +('12', '10', '5', '3', '0'), + +('12', '10', '6', '0', '0'), +('12', '10', '6', '1', '0'), +('12', '10', '6', '2', '0'), +('12', '10', '6', '3', '0'), + +('12', '11', '0', '0', '0'), +('12', '11', '0', '1', '0'), +('12', '11', '0', '2', '0'), +('12', '11', '0', '3', '0'), + +('12', '11', '1', '0', '0'), +('12', '11', '1', '1', '0'), +('12', '11', '1', '2', '0'), +('12', '11', '1', '3', '0'), + +('12', '11', '2', '0', '0'), +('12', '11', '2', '1', '0'), +('12', '11', '2', '2', '0'), +('12', '11', '2', '3', '0'), + +('12', '11', '3', '0', '0'), +('12', '11', '3', '1', '0'), +('12', '11', '3', '2', '0'), +('12', '11', '3', '3', '0'), + +('12', '11', '4', '0', '0'), +('12', '11', '4', '1', '0'), +('12', '11', '4', '2', '0'), +('12', '11', '4', '3', '0'), + +('12', '11', '5', '0', '0'), +('12', '11', '5', '1', '0'), +('12', '11', '5', '2', '0'), +('12', '11', '5', '3', '0'), + +('12', '11', '6', '0', '0'), +('12', '11', '6', '1', '0'), +('12', '11', '6', '2', '0'), +('12', '11', '6', '3', '0'), + +('12', '12', '0', '0', '0'), +('12', '12', '0', '1', '0'), +('12', '12', '0', '2', '0'), +('12', '12', '0', '3', '0'), + +('12', '12', '1', '0', '0'), +('12', '12', '1', '1', '0'), +('12', '12', '1', '2', '0'), +('12', '12', '1', '3', '0'), + +('12', '12', '2', '0', '0'), +('12', '12', '2', '1', '0'), +('12', '12', '2', '2', '0'), +('12', '12', '2', '3', '0'), + +('12', '12', '3', '0', '0'), +('12', '12', '3', '1', '0'), +('12', '12', '3', '2', '0'), +('12', '12', '3', '3', '0'), + +('12', '12', '4', '0', '0'), +('12', '12', '4', '1', '0'), +('12', '12', '4', '2', '0'), +('12', '12', '4', '3', '0'), + +('12', '12', '5', '0', '0'), +('12', '12', '5', '1', '0'), +('12', '12', '5', '2', '0'), +('12', '12', '5', '3', '0'), + +('12', '12', '6', '0', '0'), +('12', '12', '6', '1', '0'), +('12', '12', '6', '2', '0'), +('12', '12', '6', '3', '0'), + +('12', '13', '0', '0', '0'), +('12', '13', '0', '1', '0'), +('12', '13', '0', '2', '0'), +('12', '13', '0', '3', '0'), + +('12', '13', '1', '0', '0'), +('12', '13', '1', '1', '0'), +('12', '13', '1', '2', '0'), +('12', '13', '1', '3', '0'), + +('12', '13', '2', '0', '0'), +('12', '13', '2', '1', '0'), +('12', '13', '2', '2', '0'), +('12', '13', '2', '3', '0'), + +('12', '13', '3', '0', '0'), +('12', '13', '3', '1', '0'), +('12', '13', '3', '2', '0'), +('12', '13', '3', '3', '0'), + +('12', '13', '4', '0', '0'), +('12', '13', '4', '1', '0'), +('12', '13', '4', '2', '0'), +('12', '13', '4', '3', '0'), + +('12', '13', '5', '0', '0'), +('12', '13', '5', '1', '0'), +('12', '13', '5', '2', '0'), +('12', '13', '5', '3', '0'), + +('12', '13', '6', '0', '0'), +('12', '13', '6', '1', '0'), +('12', '13', '6', '2', '0'), +('12', '13', '6', '3', '0'), + +('12', '14', '0', '0', '0'), +('12', '14', '0', '1', '0'), +('12', '14', '0', '2', '0'), +('12', '14', '0', '3', '0'), + +('12', '14', '1', '0', '0'), +('12', '14', '1', '1', '0'), +('12', '14', '1', '2', '0'), +('12', '14', '1', '3', '0'), + +('12', '14', '2', '0', '0'), +('12', '14', '2', '1', '0'), +('12', '14', '2', '2', '0'), +('12', '14', '2', '3', '0'), + +('12', '14', '3', '0', '0'), +('12', '14', '3', '1', '0'), +('12', '14', '3', '2', '0'), +('12', '14', '3', '3', '0'), + +('12', '14', '4', '0', '0'), +('12', '14', '4', '1', '0'), +('12', '14', '4', '2', '0'), +('12', '14', '4', '3', '0'), + +('12', '14', '5', '0', '0'), +('12', '14', '5', '1', '0'), +('12', '14', '5', '2', '0'), +('12', '14', '5', '3', '0'), + +('12', '14', '6', '0', '0'), +('12', '14', '6', '1', '0'), +('12', '14', '6', '2', '0'), +('12', '14', '6', '3', '0'), + +('12', '15', '0', '0', '0'), +('12', '15', '0', '1', '0'), +('12', '15', '0', '2', '0'), +('12', '15', '0', '3', '0'), + +('12', '15', '1', '0', '0'), +('12', '15', '1', '1', '0'), +('12', '15', '1', '2', '0'), +('12', '15', '1', '3', '0'), + +('12', '15', '2', '0', '0'), +('12', '15', '2', '1', '0'), +('12', '15', '2', '2', '0'), +('12', '15', '2', '3', '0'), + +('12', '15', '3', '0', '0'), +('12', '15', '3', '1', '0'), +('12', '15', '3', '2', '0'), +('12', '15', '3', '3', '0'), + +('12', '15', '4', '0', '0'), +('12', '15', '4', '1', '0'), +('12', '15', '4', '2', '0'), +('12', '15', '4', '3', '0'), + +('12', '15', '5', '0', '0'), +('12', '15', '5', '1', '0'), +('12', '15', '5', '2', '0'), +('12', '15', '5', '3', '0'), + +('12', '15', '6', '0', '0'), +('12', '15', '6', '1', '0'), +('12', '15', '6', '2', '0'), +('12', '15', '6', '3', '0'), + +-- SpellType_SlowIndex + +('13', '0', '0', '0', '0'), +('13', '0', '0', '1', '0'), +('13', '0', '0', '2', '0'), +('13', '0', '0', '3', '0'), + +('13', '0', '1', '0', '0'), +('13', '0', '1', '1', '0'), +('13', '0', '1', '2', '0'), +('13', '0', '1', '3', '0'), + +('13', '0', '2', '0', '0'), +('13', '0', '2', '1', '0'), +('13', '0', '2', '2', '0'), +('13', '0', '2', '3', '0'), + +('13', '0', '3', '0', '0'), +('13', '0', '3', '1', '0'), +('13', '0', '3', '2', '0'), +('13', '0', '3', '3', '0'), + +('13', '0', '4', '0', '0'), +('13', '0', '4', '1', '0'), +('13', '0', '4', '2', '0'), +('13', '0', '4', '3', '0'), + +('13', '0', '5', '0', '0'), +('13', '0', '5', '1', '0'), +('13', '0', '5', '2', '0'), +('13', '0', '5', '3', '0'), + +('13', '0', '6', '0', '0'), +('13', '0', '6', '1', '0'), +('13', '0', '6', '2', '0'), +('13', '0', '6', '3', '0'), + +('13', '1', '0', '0', '0'), +('13', '1', '0', '1', '0'), +('13', '1', '0', '2', '0'), +('13', '1', '0', '3', '0'), + +('13', '1', '1', '0', '0'), +('13', '1', '1', '1', '0'), +('13', '1', '1', '2', '0'), +('13', '1', '1', '3', '0'), + +('13', '1', '2', '0', '0'), +('13', '1', '2', '1', '0'), +('13', '1', '2', '2', '0'), +('13', '1', '2', '3', '0'), + +('13', '1', '3', '0', '0'), +('13', '1', '3', '1', '0'), +('13', '1', '3', '2', '0'), +('13', '1', '3', '3', '0'), + +('13', '1', '4', '0', '0'), +('13', '1', '4', '1', '0'), +('13', '1', '4', '2', '0'), +('13', '1', '4', '3', '0'), + +('13', '1', '5', '0', '0'), +('13', '1', '5', '1', '0'), +('13', '1', '5', '2', '0'), +('13', '1', '5', '3', '0'), + +('13', '1', '6', '0', '0'), +('13', '1', '6', '1', '0'), +('13', '1', '6', '2', '0'), +('13', '1', '6', '3', '0'), + +('13', '2', '0', '0', '0'), +('13', '2', '0', '1', '0'), +('13', '2', '0', '2', '0'), +('13', '2', '0', '3', '0'), + +('13', '2', '1', '0', '0'), +('13', '2', '1', '1', '0'), +('13', '2', '1', '2', '0'), +('13', '2', '1', '3', '0'), + +('13', '2', '2', '0', '0'), +('13', '2', '2', '1', '0'), +('13', '2', '2', '2', '0'), +('13', '2', '2', '3', '0'), + +('13', '2', '3', '0', '0'), +('13', '2', '3', '1', '0'), +('13', '2', '3', '2', '0'), +('13', '2', '3', '3', '0'), + +('13', '2', '4', '0', '0'), +('13', '2', '4', '1', '0'), +('13', '2', '4', '2', '0'), +('13', '2', '4', '3', '0'), + +('13', '2', '5', '0', '0'), +('13', '2', '5', '1', '0'), +('13', '2', '5', '2', '0'), +('13', '2', '5', '3', '0'), + +('13', '2', '6', '0', '0'), +('13', '2', '6', '1', '0'), +('13', '2', '6', '2', '0'), +('13', '2', '6', '3', '0'), + +('13', '3', '0', '0', '0'), +('13', '3', '0', '1', '0'), +('13', '3', '0', '2', '0'), +('13', '3', '0', '3', '0'), + +('13', '3', '1', '0', '0'), +('13', '3', '1', '1', '0'), +('13', '3', '1', '2', '0'), +('13', '3', '1', '3', '0'), + +('13', '3', '2', '0', '0'), +('13', '3', '2', '1', '0'), +('13', '3', '2', '2', '0'), +('13', '3', '2', '3', '0'), + +('13', '3', '3', '0', '0'), +('13', '3', '3', '1', '0'), +('13', '3', '3', '2', '0'), +('13', '3', '3', '3', '0'), + +('13', '3', '4', '0', '0'), +('13', '3', '4', '1', '0'), +('13', '3', '4', '2', '0'), +('13', '3', '4', '3', '0'), + +('13', '3', '5', '0', '0'), +('13', '3', '5', '1', '0'), +('13', '3', '5', '2', '0'), +('13', '3', '5', '3', '0'), + +('13', '3', '6', '0', '0'), +('13', '3', '6', '1', '0'), +('13', '3', '6', '2', '0'), +('13', '3', '6', '3', '0'), + +('13', '4', '0', '0', '0'), +('13', '4', '0', '1', '0'), +('13', '4', '0', '2', '0'), +('13', '4', '0', '3', '0'), + +('13', '4', '1', '0', '0'), +('13', '4', '1', '1', '0'), +('13', '4', '1', '2', '0'), +('13', '4', '1', '3', '0'), + +('13', '4', '2', '0', '0'), +('13', '4', '2', '1', '0'), +('13', '4', '2', '2', '0'), +('13', '4', '2', '3', '0'), + +('13', '4', '3', '0', '0'), +('13', '4', '3', '1', '0'), +('13', '4', '3', '2', '0'), +('13', '4', '3', '3', '0'), + +('13', '4', '4', '0', '0'), +('13', '4', '4', '1', '0'), +('13', '4', '4', '2', '0'), +('13', '4', '4', '3', '0'), + +('13', '4', '5', '0', '0'), +('13', '4', '5', '1', '0'), +('13', '4', '5', '2', '0'), +('13', '4', '5', '3', '0'), + +('13', '4', '6', '0', '0'), +('13', '4', '6', '1', '0'), +('13', '4', '6', '2', '0'), +('13', '4', '6', '3', '0'), + +('13', '5', '0', '0', '0'), +('13', '5', '0', '1', '0'), +('13', '5', '0', '2', '0'), +('13', '5', '0', '3', '0'), + +('13', '5', '1', '0', '0'), +('13', '5', '1', '1', '0'), +('13', '5', '1', '2', '0'), +('13', '5', '1', '3', '0'), + +('13', '5', '2', '0', '0'), +('13', '5', '2', '1', '0'), +('13', '5', '2', '2', '0'), +('13', '5', '2', '3', '0'), + +('13', '5', '3', '0', '0'), +('13', '5', '3', '1', '0'), +('13', '5', '3', '2', '0'), +('13', '5', '3', '3', '0'), + +('13', '5', '4', '0', '0'), +('13', '5', '4', '1', '0'), +('13', '5', '4', '2', '0'), +('13', '5', '4', '3', '0'), + +('13', '5', '5', '0', '0'), +('13', '5', '5', '1', '0'), +('13', '5', '5', '2', '0'), +('13', '5', '5', '3', '0'), + +('13', '5', '6', '0', '0'), +('13', '5', '6', '1', '0'), +('13', '5', '6', '2', '0'), +('13', '5', '6', '3', '0'), + +('13', '6', '0', '0', '0'), +('13', '6', '0', '1', '0'), +('13', '6', '0', '2', '0'), +('13', '6', '0', '3', '0'), + +('13', '6', '1', '0', '0'), +('13', '6', '1', '1', '0'), +('13', '6', '1', '2', '0'), +('13', '6', '1', '3', '0'), + +('13', '6', '2', '0', '0'), +('13', '6', '2', '1', '0'), +('13', '6', '2', '2', '0'), +('13', '6', '2', '3', '0'), + +('13', '6', '3', '0', '0'), +('13', '6', '3', '1', '0'), +('13', '6', '3', '2', '0'), +('13', '6', '3', '3', '0'), + +('13', '6', '4', '0', '0'), +('13', '6', '4', '1', '0'), +('13', '6', '4', '2', '0'), +('13', '6', '4', '3', '0'), + +('13', '6', '5', '0', '0'), +('13', '6', '5', '1', '0'), +('13', '6', '5', '2', '0'), +('13', '6', '5', '3', '0'), + +('13', '6', '6', '0', '0'), +('13', '6', '6', '1', '0'), +('13', '6', '6', '2', '0'), +('13', '6', '6', '3', '0'), + +('13', '7', '0', '0', '0'), +('13', '7', '0', '1', '0'), +('13', '7', '0', '2', '0'), +('13', '7', '0', '3', '0'), + +('13', '7', '1', '0', '25'), +('13', '7', '1', '1', '25'), +('13', '7', '1', '2', '100'), +('13', '7', '1', '3', '100'), + +('13', '7', '2', '0', '15'), +('13', '7', '2', '1', '15'), +('13', '7', '2', '2', '100'), +('13', '7', '2', '3', '100'), + +('13', '7', '3', '0', '25'), +('13', '7', '3', '1', '25'), +('13', '7', '3', '2', '100'), +('13', '7', '3', '3', '100'), + +('13', '7', '4', '0', '0'), +('13', '7', '4', '1', '0'), +('13', '7', '4', '2', '50'), +('13', '7', '4', '3', '50'), + +('13', '7', '5', '0', '0'), +('13', '7', '5', '1', '0'), +('13', '7', '5', '2', '50'), +('13', '7', '5', '3', '50'), + +('13', '7', '6', '0', '0'), +('13', '7', '6', '1', '0'), +('13', '7', '6', '2', '50'), +('13', '7', '6', '3', '50'), + +('13', '8', '0', '0', '0'), +('13', '8', '0', '1', '0'), +('13', '8', '0', '2', '0'), +('13', '8', '0', '3', '0'), + +('13', '8', '1', '0', '0'), +('13', '8', '1', '1', '0'), +('13', '8', '1', '2', '0'), +('13', '8', '1', '3', '0'), + +('13', '8', '2', '0', '0'), +('13', '8', '2', '1', '0'), +('13', '8', '2', '2', '0'), +('13', '8', '2', '3', '0'), + +('13', '8', '3', '0', '0'), +('13', '8', '3', '1', '0'), +('13', '8', '3', '2', '0'), +('13', '8', '3', '3', '0'), + +('13', '8', '4', '0', '0'), +('13', '8', '4', '1', '0'), +('13', '8', '4', '2', '0'), +('13', '8', '4', '3', '0'), + +('13', '8', '5', '0', '0'), +('13', '8', '5', '1', '0'), +('13', '8', '5', '2', '0'), +('13', '8', '5', '3', '0'), + +('13', '8', '6', '0', '0'), +('13', '8', '6', '1', '0'), +('13', '8', '6', '2', '0'), +('13', '8', '6', '3', '0'), + +('13', '9', '0', '0', '0'), +('13', '9', '0', '1', '0'), +('13', '9', '0', '2', '0'), +('13', '9', '0', '3', '0'), + +('13', '9', '1', '0', '50'), +('13', '9', '1', '1', '50'), +('13', '9', '1', '2', '100'), +('13', '9', '1', '3', '100'), + +('13', '9', '2', '0', '25'), +('13', '9', '2', '1', '25'), +('13', '9', '2', '2', '100'), +('13', '9', '2', '3', '100'), + +('13', '9', '3', '0', '50'), +('13', '9', '3', '1', '50'), +('13', '9', '3', '2', '100'), +('13', '9', '3', '3', '100'), + +('13', '9', '4', '0', '15'), +('13', '9', '4', '1', '15'), +('13', '9', '4', '2', '50'), +('13', '9', '4', '3', '50'), + +('13', '9', '5', '0', '15'), +('13', '9', '5', '1', '15'), +('13', '9', '5', '2', '50'), +('13', '9', '5', '3', '50'), + +('13', '9', '6', '0', '15'), +('13', '9', '6', '1', '15'), +('13', '9', '6', '2', '50'), +('13', '9', '6', '3', '50'), + +('13', '10', '0', '0', '0'), +('13', '10', '0', '1', '0'), +('13', '10', '0', '2', '0'), +('13', '10', '0', '3', '0'), + +('13', '10', '1', '0', '0'), +('13', '10', '1', '1', '0'), +('13', '10', '1', '2', '0'), +('13', '10', '1', '3', '0'), + +('13', '10', '2', '0', '0'), +('13', '10', '2', '1', '0'), +('13', '10', '2', '2', '0'), +('13', '10', '2', '3', '0'), + +('13', '10', '3', '0', '0'), +('13', '10', '3', '1', '0'), +('13', '10', '3', '2', '0'), +('13', '10', '3', '3', '0'), + +('13', '10', '4', '0', '0'), +('13', '10', '4', '1', '0'), +('13', '10', '4', '2', '0'), +('13', '10', '4', '3', '0'), + +('13', '10', '5', '0', '0'), +('13', '10', '5', '1', '0'), +('13', '10', '5', '2', '0'), +('13', '10', '5', '3', '0'), + +('13', '10', '6', '0', '0'), +('13', '10', '6', '1', '0'), +('13', '10', '6', '2', '0'), +('13', '10', '6', '3', '0'), + +('13', '11', '0', '0', '0'), +('13', '11', '0', '1', '0'), +('13', '11', '0', '2', '0'), +('13', '11', '0', '3', '0'), + +('13', '11', '1', '0', '0'), +('13', '11', '1', '1', '0'), +('13', '11', '1', '2', '0'), +('13', '11', '1', '3', '0'), + +('13', '11', '2', '0', '0'), +('13', '11', '2', '1', '0'), +('13', '11', '2', '2', '0'), +('13', '11', '2', '3', '0'), + +('13', '11', '3', '0', '0'), +('13', '11', '3', '1', '0'), +('13', '11', '3', '2', '0'), +('13', '11', '3', '3', '0'), + +('13', '11', '4', '0', '0'), +('13', '11', '4', '1', '0'), +('13', '11', '4', '2', '0'), +('13', '11', '4', '3', '0'), + +('13', '11', '5', '0', '0'), +('13', '11', '5', '1', '0'), +('13', '11', '5', '2', '0'), +('13', '11', '5', '3', '0'), + +('13', '11', '6', '0', '0'), +('13', '11', '6', '1', '0'), +('13', '11', '6', '2', '0'), +('13', '11', '6', '3', '0'), + +('13', '12', '0', '0', '0'), +('13', '12', '0', '1', '0'), +('13', '12', '0', '2', '0'), +('13', '12', '0', '3', '0'), + +('13', '12', '1', '0', '0'), +('13', '12', '1', '1', '0'), +('13', '12', '1', '2', '0'), +('13', '12', '1', '3', '0'), + +('13', '12', '2', '0', '0'), +('13', '12', '2', '1', '0'), +('13', '12', '2', '2', '0'), +('13', '12', '2', '3', '0'), + +('13', '12', '3', '0', '0'), +('13', '12', '3', '1', '0'), +('13', '12', '3', '2', '0'), +('13', '12', '3', '3', '0'), + +('13', '12', '4', '0', '0'), +('13', '12', '4', '1', '0'), +('13', '12', '4', '2', '0'), +('13', '12', '4', '3', '0'), + +('13', '12', '5', '0', '0'), +('13', '12', '5', '1', '0'), +('13', '12', '5', '2', '0'), +('13', '12', '5', '3', '0'), + +('13', '12', '6', '0', '0'), +('13', '12', '6', '1', '0'), +('13', '12', '6', '2', '0'), +('13', '12', '6', '3', '0'), + +('13', '13', '0', '0', '0'), +('13', '13', '0', '1', '0'), +('13', '13', '0', '2', '0'), +('13', '13', '0', '3', '0'), + +('13', '13', '1', '0', '50'), +('13', '13', '1', '1', '50'), +('13', '13', '1', '2', '100'), +('13', '13', '1', '3', '100'), + +('13', '13', '2', '0', '25'), +('13', '13', '2', '1', '25'), +('13', '13', '2', '2', '100'), +('13', '13', '2', '3', '100'), + +('13', '13', '3', '0', '50'), +('13', '13', '3', '1', '50'), +('13', '13', '3', '2', '100'), +('13', '13', '3', '3', '100'), + +('13', '13', '4', '0', '15'), +('13', '13', '4', '1', '15'), +('13', '13', '4', '2', '50'), +('13', '13', '4', '3', '50'), + +('13', '13', '5', '0', '15'), +('13', '13', '5', '1', '15'), +('13', '13', '5', '2', '50'), +('13', '13', '5', '3', '50'), + +('13', '13', '6', '0', '15'), +('13', '13', '6', '1', '15'), +('13', '13', '6', '2', '50'), +('13', '13', '6', '3', '50'), + +('13', '14', '0', '0', '0'), +('13', '14', '0', '1', '0'), +('13', '14', '0', '2', '0'), +('13', '14', '0', '3', '0'), + +('13', '14', '1', '0', '25'), +('13', '14', '1', '1', '25'), +('13', '14', '1', '2', '100'), +('13', '14', '1', '3', '100'), + +('13', '14', '2', '0', '15'), +('13', '14', '2', '1', '15'), +('13', '14', '2', '2', '100'), +('13', '14', '2', '3', '100'), + +('13', '14', '3', '0', '25'), +('13', '14', '3', '1', '25'), +('13', '14', '3', '2', '100'), +('13', '14', '3', '3', '100'), + +('13', '14', '4', '0', '0'), +('13', '14', '4', '1', '0'), +('13', '14', '4', '2', '50'), +('13', '14', '4', '3', '50'), + +('13', '14', '5', '0', '0'), +('13', '14', '5', '1', '0'), +('13', '14', '5', '2', '50'), +('13', '14', '5', '3', '50'), + +('13', '14', '6', '0', '0'), +('13', '14', '6', '1', '0'), +('13', '14', '6', '2', '50'), +('13', '14', '6', '3', '50'), + +('13', '15', '0', '0', '0'), +('13', '15', '0', '1', '0'), +('13', '15', '0', '2', '0'), +('13', '15', '0', '3', '0'), + +('13', '15', '1', '0', '0'), +('13', '15', '1', '1', '0'), +('13', '15', '1', '2', '0'), +('13', '15', '1', '3', '0'), + +('13', '15', '2', '0', '0'), +('13', '15', '2', '1', '0'), +('13', '15', '2', '2', '0'), +('13', '15', '2', '3', '0'), + +('13', '15', '3', '0', '0'), +('13', '15', '3', '1', '0'), +('13', '15', '3', '2', '0'), +('13', '15', '3', '3', '0'), + +('13', '15', '4', '0', '0'), +('13', '15', '4', '1', '0'), +('13', '15', '4', '2', '0'), +('13', '15', '4', '3', '0'), + +('13', '15', '5', '0', '0'), +('13', '15', '5', '1', '0'), +('13', '15', '5', '2', '0'), +('13', '15', '5', '3', '0'), + +('13', '15', '6', '0', '0'), +('13', '15', '6', '1', '0'), +('13', '15', '6', '2', '0'), +('13', '15', '6', '3', '0'), + +-- SpellType_DebuffIndex + +('14', '0', '0', '0', '0'), +('14', '0', '0', '1', '0'), +('14', '0', '0', '2', '0'), +('14', '0', '0', '3', '0'), + +('14', '0', '1', '0', '0'), +('14', '0', '1', '1', '0'), +('14', '0', '1', '2', '0'), +('14', '0', '1', '3', '0'), + +('14', '0', '2', '0', '0'), +('14', '0', '2', '1', '0'), +('14', '0', '2', '2', '0'), +('14', '0', '2', '3', '0'), + +('14', '0', '3', '0', '0'), +('14', '0', '3', '1', '0'), +('14', '0', '3', '2', '0'), +('14', '0', '3', '3', '0'), + +('14', '0', '4', '0', '0'), +('14', '0', '4', '1', '0'), +('14', '0', '4', '2', '0'), +('14', '0', '4', '3', '0'), + +('14', '0', '5', '0', '0'), +('14', '0', '5', '1', '0'), +('14', '0', '5', '2', '0'), +('14', '0', '5', '3', '0'), + +('14', '0', '6', '0', '0'), +('14', '0', '6', '1', '0'), +('14', '0', '6', '2', '0'), +('14', '0', '6', '3', '0'), + +('14', '1', '0', '0', '0'), +('14', '1', '0', '1', '0'), +('14', '1', '0', '2', '0'), +('14', '1', '0', '3', '0'), + +('14', '1', '1', '0', '0'), +('14', '1', '1', '1', '0'), +('14', '1', '1', '2', '0'), +('14', '1', '1', '3', '0'), + +('14', '1', '2', '0', '0'), +('14', '1', '2', '1', '0'), +('14', '1', '2', '2', '0'), +('14', '1', '2', '3', '0'), + +('14', '1', '3', '0', '0'), +('14', '1', '3', '1', '0'), +('14', '1', '3', '2', '0'), +('14', '1', '3', '3', '0'), + +('14', '1', '4', '0', '0'), +('14', '1', '4', '1', '0'), +('14', '1', '4', '2', '0'), +('14', '1', '4', '3', '0'), + +('14', '1', '5', '0', '0'), +('14', '1', '5', '1', '0'), +('14', '1', '5', '2', '0'), +('14', '1', '5', '3', '0'), + +('14', '1', '6', '0', '0'), +('14', '1', '6', '1', '0'), +('14', '1', '6', '2', '0'), +('14', '1', '6', '3', '0'), + +('14', '2', '0', '0', '0'), +('14', '2', '0', '1', '0'), +('14', '2', '0', '2', '0'), +('14', '2', '0', '3', '0'), + +('14', '2', '1', '0', '0'), +('14', '2', '1', '1', '0'), +('14', '2', '1', '2', '0'), +('14', '2', '1', '3', '0'), + +('14', '2', '2', '0', '0'), +('14', '2', '2', '1', '0'), +('14', '2', '2', '2', '0'), +('14', '2', '2', '3', '0'), + +('14', '2', '3', '0', '0'), +('14', '2', '3', '1', '0'), +('14', '2', '3', '2', '0'), +('14', '2', '3', '3', '0'), + +('14', '2', '4', '0', '0'), +('14', '2', '4', '1', '0'), +('14', '2', '4', '2', '0'), +('14', '2', '4', '3', '0'), + +('14', '2', '5', '0', '0'), +('14', '2', '5', '1', '0'), +('14', '2', '5', '2', '0'), +('14', '2', '5', '3', '0'), + +('14', '2', '6', '0', '0'), +('14', '2', '6', '1', '0'), +('14', '2', '6', '2', '0'), +('14', '2', '6', '3', '0'), + +('14', '3', '0', '0', '0'), +('14', '3', '0', '1', '0'), +('14', '3', '0', '2', '0'), +('14', '3', '0', '3', '0'), + +('14', '3', '1', '0', '15'), +('14', '3', '1', '1', '15'), +('14', '3', '1', '2', '15'), +('14', '3', '1', '3', '15'), + +('14', '3', '2', '0', '10'), +('14', '3', '2', '1', '10'), +('14', '3', '2', '2', '10'), +('14', '3', '2', '3', '10'), + +('14', '3', '3', '0', '15'), +('14', '3', '3', '1', '15'), +('14', '3', '3', '2', '15'), +('14', '3', '3', '3', '15'), + +('14', '3', '4', '0', '10'), +('14', '3', '4', '1', '10'), +('14', '3', '4', '2', '10'), +('14', '3', '4', '3', '10'), + +('14', '3', '5', '0', '0'), +('14', '3', '5', '1', '0'), +('14', '3', '5', '2', '0'), +('14', '3', '5', '3', '0'), + +('14', '3', '6', '0', '0'), +('14', '3', '6', '1', '0'), +('14', '3', '6', '2', '0'), +('14', '3', '6', '3', '0'), + +('14', '4', '0', '0', '0'), +('14', '4', '0', '1', '0'), +('14', '4', '0', '2', '0'), +('14', '4', '0', '3', '0'), + +('14', '4', '1', '0', '15'), +('14', '4', '1', '1', '15'), +('14', '4', '1', '2', '15'), +('14', '4', '1', '3', '15'), + +('14', '4', '2', '0', '10'), +('14', '4', '2', '1', '10'), +('14', '4', '2', '2', '10'), +('14', '4', '2', '3', '10'), + +('14', '4', '3', '0', '15'), +('14', '4', '3', '1', '15'), +('14', '4', '3', '2', '15'), +('14', '4', '3', '3', '15'), + +('14', '4', '4', '0', '10'), +('14', '4', '4', '1', '10'), +('14', '4', '4', '2', '10'), +('14', '4', '4', '3', '10'), + +('14', '4', '5', '0', '0'), +('14', '4', '5', '1', '0'), +('14', '4', '5', '2', '0'), +('14', '4', '5', '3', '0'), + +('14', '4', '6', '0', '0'), +('14', '4', '6', '1', '0'), +('14', '4', '6', '2', '0'), +('14', '4', '6', '3', '0'), + +('14', '5', '0', '0', '0'), +('14', '5', '0', '1', '0'), +('14', '5', '0', '2', '0'), +('14', '5', '0', '3', '0'), + +('14', '5', '1', '0', '25'), +('14', '5', '1', '1', '25'), +('14', '5', '1', '2', '25'), +('14', '5', '1', '3', '25'), + +('14', '5', '2', '0', '15'), +('14', '5', '2', '1', '15'), +('14', '5', '2', '2', '15'), +('14', '5', '2', '3', '15'), + +('14', '5', '3', '0', '25'), +('14', '5', '3', '1', '25'), +('14', '5', '3', '2', '25'), +('14', '5', '3', '3', '25'), + +('14', '5', '4', '0', '15'), +('14', '5', '4', '1', '15'), +('14', '5', '4', '2', '15'), +('14', '5', '4', '3', '15'), + +('14', '5', '5', '0', '0'), +('14', '5', '5', '1', '0'), +('14', '5', '5', '2', '0'), +('14', '5', '5', '3', '0'), + +('14', '5', '6', '0', '0'), +('14', '5', '6', '1', '0'), +('14', '5', '6', '2', '0'), +('14', '5', '6', '3', '0'), + +('14', '6', '0', '0', '0'), +('14', '6', '0', '1', '0'), +('14', '6', '0', '2', '0'), +('14', '6', '0', '3', '0'), + +('14', '6', '1', '0', '0'), +('14', '6', '1', '1', '0'), +('14', '6', '1', '2', '0'), +('14', '6', '1', '3', '0'), + +('14', '6', '2', '0', '0'), +('14', '6', '2', '1', '0'), +('14', '6', '2', '2', '0'), +('14', '6', '2', '3', '0'), + +('14', '6', '3', '0', '0'), +('14', '6', '3', '1', '0'), +('14', '6', '3', '2', '0'), +('14', '6', '3', '3', '0'), + +('14', '6', '4', '0', '0'), +('14', '6', '4', '1', '0'), +('14', '6', '4', '2', '0'), +('14', '6', '4', '3', '0'), + +('14', '6', '5', '0', '0'), +('14', '6', '5', '1', '0'), +('14', '6', '5', '2', '0'), +('14', '6', '5', '3', '0'), + +('14', '6', '6', '0', '0'), +('14', '6', '6', '1', '0'), +('14', '6', '6', '2', '0'), +('14', '6', '6', '3', '0'), + +('14', '7', '0', '0', '0'), +('14', '7', '0', '1', '0'), +('14', '7', '0', '2', '0'), +('14', '7', '0', '3', '0'), + +('14', '7', '1', '0', '25'), +('14', '7', '1', '1', '25'), +('14', '7', '1', '2', '25'), +('14', '7', '1', '3', '25'), + +('14', '7', '2', '0', '25'), +('14', '7', '2', '1', '25'), +('14', '7', '2', '2', '25'), +('14', '7', '2', '3', '25'), + +('14', '7', '3', '0', '50'), +('14', '7', '3', '1', '50'), +('14', '7', '3', '2', '50'), +('14', '7', '3', '3', '50'), + +('14', '7', '4', '0', '50'), +('14', '7', '4', '1', '50'), +('14', '7', '4', '2', '50'), +('14', '7', '4', '3', '50'), + +('14', '7', '5', '0', '0'), +('14', '7', '5', '1', '0'), +('14', '7', '5', '2', '0'), +('14', '7', '5', '3', '0'), + +('14', '7', '6', '0', '0'), +('14', '7', '6', '1', '0'), +('14', '7', '6', '2', '0'), +('14', '7', '6', '3', '0'), + +('14', '8', '0', '0', '0'), +('14', '8', '0', '1', '0'), +('14', '8', '0', '2', '0'), +('14', '8', '0', '3', '0'), + +('14', '8', '1', '0', '0'), +('14', '8', '1', '1', '0'), +('14', '8', '1', '2', '0'), +('14', '8', '1', '3', '0'), + +('14', '8', '2', '0', '0'), +('14', '8', '2', '1', '0'), +('14', '8', '2', '2', '0'), +('14', '8', '2', '3', '0'), + +('14', '8', '3', '0', '0'), +('14', '8', '3', '1', '0'), +('14', '8', '3', '2', '0'), +('14', '8', '3', '3', '0'), + +('14', '8', '4', '0', '0'), +('14', '8', '4', '1', '0'), +('14', '8', '4', '2', '0'), +('14', '8', '4', '3', '0'), + +('14', '8', '5', '0', '0'), +('14', '8', '5', '1', '0'), +('14', '8', '5', '2', '0'), +('14', '8', '5', '3', '0'), + +('14', '8', '6', '0', '0'), +('14', '8', '6', '1', '0'), +('14', '8', '6', '2', '0'), +('14', '8', '6', '3', '0'), + +('14', '9', '0', '0', '0'), +('14', '9', '0', '1', '0'), +('14', '9', '0', '2', '0'), +('14', '9', '0', '3', '0'), + +('14', '9', '1', '0', '25'), +('14', '9', '1', '1', '25'), +('14', '9', '1', '2', '25'), +('14', '9', '1', '3', '25'), + +('14', '9', '2', '0', '15'), +('14', '9', '2', '1', '15'), +('14', '9', '2', '2', '15'), +('14', '9', '2', '3', '15'), + +('14', '9', '3', '0', '25'), +('14', '9', '3', '1', '25'), +('14', '9', '3', '2', '25'), +('14', '9', '3', '3', '25'), + +('14', '9', '4', '0', '15'), +('14', '9', '4', '1', '15'), +('14', '9', '4', '2', '15'), +('14', '9', '4', '3', '15'), + +('14', '9', '5', '0', '0'), +('14', '9', '5', '1', '0'), +('14', '9', '5', '2', '0'), +('14', '9', '5', '3', '0'), + +('14', '9', '6', '0', '0'), +('14', '9', '6', '1', '0'), +('14', '9', '6', '2', '0'), +('14', '9', '6', '3', '0'), + +('14', '10', '0', '0', '0'), +('14', '10', '0', '1', '0'), +('14', '10', '0', '2', '0'), +('14', '10', '0', '3', '0'), + +('14', '10', '1', '0', '25'), +('14', '10', '1', '1', '25'), +('14', '10', '1', '2', '25'), +('14', '10', '1', '3', '25'), + +('14', '10', '2', '0', '15'), +('14', '10', '2', '1', '15'), +('14', '10', '2', '2', '15'), +('14', '10', '2', '3', '15'), + +('14', '10', '3', '0', '25'), +('14', '10', '3', '1', '25'), +('14', '10', '3', '2', '25'), +('14', '10', '3', '3', '25'), + +('14', '10', '4', '0', '15'), +('14', '10', '4', '1', '15'), +('14', '10', '4', '2', '15'), +('14', '10', '4', '3', '15'), + +('14', '10', '5', '0', '0'), +('14', '10', '5', '1', '0'), +('14', '10', '5', '2', '0'), +('14', '10', '5', '3', '0'), + +('14', '10', '6', '0', '0'), +('14', '10', '6', '1', '0'), +('14', '10', '6', '2', '0'), +('14', '10', '6', '3', '0'), + +('14', '11', '0', '0', '0'), +('14', '11', '0', '1', '0'), +('14', '11', '0', '2', '0'), +('14', '11', '0', '3', '0'), + +('14', '11', '1', '0', '0'), +('14', '11', '1', '1', '0'), +('14', '11', '1', '2', '0'), +('14', '11', '1', '3', '0'), + +('14', '11', '2', '0', '0'), +('14', '11', '2', '1', '0'), +('14', '11', '2', '2', '0'), +('14', '11', '2', '3', '0'), + +('14', '11', '3', '0', '0'), +('14', '11', '3', '1', '0'), +('14', '11', '3', '2', '0'), +('14', '11', '3', '3', '0'), + +('14', '11', '4', '0', '0'), +('14', '11', '4', '1', '0'), +('14', '11', '4', '2', '0'), +('14', '11', '4', '3', '0'), + +('14', '11', '5', '0', '0'), +('14', '11', '5', '1', '0'), +('14', '11', '5', '2', '0'), +('14', '11', '5', '3', '0'), + +('14', '11', '6', '0', '0'), +('14', '11', '6', '1', '0'), +('14', '11', '6', '2', '0'), +('14', '11', '6', '3', '0'), + +('14', '12', '0', '0', '0'), +('14', '12', '0', '1', '0'), +('14', '12', '0', '2', '0'), +('14', '12', '0', '3', '0'), + +('14', '12', '1', '0', '25'), +('14', '12', '1', '1', '25'), +('14', '12', '1', '2', '25'), +('14', '12', '1', '3', '25'), + +('14', '12', '2', '0', '15'), +('14', '12', '2', '1', '15'), +('14', '12', '2', '2', '15'), +('14', '12', '2', '3', '15'), + +('14', '12', '3', '0', '25'), +('14', '12', '3', '1', '25'), +('14', '12', '3', '2', '25'), +('14', '12', '3', '3', '25'), + +('14', '12', '4', '0', '15'), +('14', '12', '4', '1', '15'), +('14', '12', '4', '2', '15'), +('14', '12', '4', '3', '15'), + +('14', '12', '5', '0', '0'), +('14', '12', '5', '1', '0'), +('14', '12', '5', '2', '0'), +('14', '12', '5', '3', '0'), + +('14', '12', '6', '0', '0'), +('14', '12', '6', '1', '0'), +('14', '12', '6', '2', '0'), +('14', '12', '6', '3', '0'), + +('14', '13', '0', '0', '0'), +('14', '13', '0', '1', '0'), +('14', '13', '0', '2', '0'), +('14', '13', '0', '3', '0'), + +('14', '13', '1', '0', '25'), +('14', '13', '1', '1', '25'), +('14', '13', '1', '2', '25'), +('14', '13', '1', '3', '25'), + +('14', '13', '2', '0', '15'), +('14', '13', '2', '1', '15'), +('14', '13', '2', '2', '15'), +('14', '13', '2', '3', '15'), + +('14', '13', '3', '0', '25'), +('14', '13', '3', '1', '25'), +('14', '13', '3', '2', '25'), +('14', '13', '3', '3', '25'), + +('14', '13', '4', '0', '15'), +('14', '13', '4', '1', '15'), +('14', '13', '4', '2', '15'), +('14', '13', '4', '3', '15'), + +('14', '13', '5', '0', '0'), +('14', '13', '5', '1', '0'), +('14', '13', '5', '2', '0'), +('14', '13', '5', '3', '0'), + +('14', '13', '6', '0', '0'), +('14', '13', '6', '1', '0'), +('14', '13', '6', '2', '0'), +('14', '13', '6', '3', '0'), + +('14', '14', '0', '0', '0'), +('14', '14', '0', '1', '0'), +('14', '14', '0', '2', '0'), +('14', '14', '0', '3', '0'), + +('14', '14', '1', '0', '15'), +('14', '14', '1', '1', '15'), +('14', '14', '1', '2', '15'), +('14', '14', '1', '3', '15'), + +('14', '14', '2', '0', '10'), +('14', '14', '2', '1', '10'), +('14', '14', '2', '2', '10'), +('14', '14', '2', '3', '10'), + +('14', '14', '3', '0', '15'), +('14', '14', '3', '1', '15'), +('14', '14', '3', '2', '15'), +('14', '14', '3', '3', '15'), + +('14', '14', '4', '0', '10'), +('14', '14', '4', '1', '10'), +('14', '14', '4', '2', '10'), +('14', '14', '4', '3', '10'), + +('14', '14', '5', '0', '0'), +('14', '14', '5', '1', '0'), +('14', '14', '5', '2', '0'), +('14', '14', '5', '3', '0'), + +('14', '14', '6', '0', '0'), +('14', '14', '6', '1', '0'), +('14', '14', '6', '2', '0'), +('14', '14', '6', '3', '0'), + +('14', '15', '0', '0', '0'), +('14', '15', '0', '1', '0'), +('14', '15', '0', '2', '0'), +('14', '15', '0', '3', '0'), + +('14', '15', '1', '0', '0'), +('14', '15', '1', '1', '0'), +('14', '15', '1', '2', '0'), +('14', '15', '1', '3', '0'), + +('14', '15', '2', '0', '0'), +('14', '15', '2', '1', '0'), +('14', '15', '2', '2', '0'), +('14', '15', '2', '3', '0'), + +('14', '15', '3', '0', '0'), +('14', '15', '3', '1', '0'), +('14', '15', '3', '2', '0'), +('14', '15', '3', '3', '0'), + +('14', '15', '4', '0', '0'), +('14', '15', '4', '1', '0'), +('14', '15', '4', '2', '0'), +('14', '15', '4', '3', '0'), + +('14', '15', '5', '0', '0'), +('14', '15', '5', '1', '0'), +('14', '15', '5', '2', '0'), +('14', '15', '5', '3', '0'), + +('14', '15', '6', '0', '0'), +('14', '15', '6', '1', '0'), +('14', '15', '6', '2', '0'), +('14', '15', '6', '3', '0'), + +-- SpellType_CureIndex + +('15', '0', '0', '0', '0'), +('15', '0', '0', '1', '0'), +('15', '0', '0', '2', '0'), +('15', '0', '0', '3', '0'), + +('15', '0', '1', '0', '0'), +('15', '0', '1', '1', '0'), +('15', '0', '1', '2', '0'), +('15', '0', '1', '3', '0'), + +('15', '0', '2', '0', '0'), +('15', '0', '2', '1', '0'), +('15', '0', '2', '2', '0'), +('15', '0', '2', '3', '0'), + +('15', '0', '3', '0', '0'), +('15', '0', '3', '1', '0'), +('15', '0', '3', '2', '0'), +('15', '0', '3', '3', '0'), + +('15', '0', '4', '0', '0'), +('15', '0', '4', '1', '0'), +('15', '0', '4', '2', '0'), +('15', '0', '4', '3', '0'), + +('15', '0', '5', '0', '0'), +('15', '0', '5', '1', '0'), +('15', '0', '5', '2', '0'), +('15', '0', '5', '3', '0'), + +('15', '0', '6', '0', '0'), +('15', '0', '6', '1', '0'), +('15', '0', '6', '2', '0'), +('15', '0', '6', '3', '0'), + +('15', '1', '0', '0', '0'), +('15', '1', '0', '1', '0'), +('15', '1', '0', '2', '0'), +('15', '1', '0', '3', '0'), + +('15', '1', '1', '0', '0'), +('15', '1', '1', '1', '0'), +('15', '1', '1', '2', '0'), +('15', '1', '1', '3', '0'), + +('15', '1', '2', '0', '0'), +('15', '1', '2', '1', '0'), +('15', '1', '2', '2', '0'), +('15', '1', '2', '3', '0'), + +('15', '1', '3', '0', '0'), +('15', '1', '3', '1', '0'), +('15', '1', '3', '2', '0'), +('15', '1', '3', '3', '0'), + +('15', '1', '4', '0', '0'), +('15', '1', '4', '1', '0'), +('15', '1', '4', '2', '0'), +('15', '1', '4', '3', '0'), + +('15', '1', '5', '0', '0'), +('15', '1', '5', '1', '0'), +('15', '1', '5', '2', '0'), +('15', '1', '5', '3', '0'), + +('15', '1', '6', '0', '0'), +('15', '1', '6', '1', '0'), +('15', '1', '6', '2', '0'), +('15', '1', '6', '3', '0'), + +('15', '2', '0', '0', '0'), +('15', '2', '0', '1', '0'), +('15', '2', '0', '2', '0'), +('15', '2', '0', '3', '0'), + +('15', '2', '1', '0', '0'), +('15', '2', '1', '1', '0'), +('15', '2', '1', '2', '0'), +('15', '2', '1', '3', '0'), + +('15', '2', '2', '0', '0'), +('15', '2', '2', '1', '0'), +('15', '2', '2', '2', '0'), +('15', '2', '2', '3', '0'), + +('15', '2', '3', '0', '0'), +('15', '2', '3', '1', '0'), +('15', '2', '3', '2', '0'), +('15', '2', '3', '3', '0'), + +('15', '2', '4', '0', '0'), +('15', '2', '4', '1', '0'), +('15', '2', '4', '2', '0'), +('15', '2', '4', '3', '0'), + +('15', '2', '5', '0', '0'), +('15', '2', '5', '1', '0'), +('15', '2', '5', '2', '0'), +('15', '2', '5', '3', '0'), + +('15', '2', '6', '0', '0'), +('15', '2', '6', '1', '0'), +('15', '2', '6', '2', '0'), +('15', '2', '6', '3', '0'), + +('15', '3', '0', '0', '0'), +('15', '3', '0', '1', '0'), +('15', '3', '0', '2', '0'), +('15', '3', '0', '3', '0'), + +('15', '3', '1', '0', '0'), +('15', '3', '1', '1', '0'), +('15', '3', '1', '2', '0'), +('15', '3', '1', '3', '0'), + +('15', '3', '2', '0', '0'), +('15', '3', '2', '1', '0'), +('15', '3', '2', '2', '0'), +('15', '3', '2', '3', '0'), + +('15', '3', '3', '0', '0'), +('15', '3', '3', '1', '0'), +('15', '3', '3', '2', '0'), +('15', '3', '3', '3', '0'), + +('15', '3', '4', '0', '0'), +('15', '3', '4', '1', '0'), +('15', '3', '4', '2', '0'), +('15', '3', '4', '3', '0'), + +('15', '3', '5', '0', '0'), +('15', '3', '5', '1', '0'), +('15', '3', '5', '2', '0'), +('15', '3', '5', '3', '0'), + +('15', '3', '6', '0', '0'), +('15', '3', '6', '1', '0'), +('15', '3', '6', '2', '0'), +('15', '3', '6', '3', '0'), + +('15', '4', '0', '0', '0'), +('15', '4', '0', '1', '0'), +('15', '4', '0', '2', '0'), +('15', '4', '0', '3', '0'), + +('15', '4', '1', '0', '0'), +('15', '4', '1', '1', '0'), +('15', '4', '1', '2', '0'), +('15', '4', '1', '3', '0'), + +('15', '4', '2', '0', '0'), +('15', '4', '2', '1', '0'), +('15', '4', '2', '2', '0'), +('15', '4', '2', '3', '0'), + +('15', '4', '3', '0', '0'), +('15', '4', '3', '1', '0'), +('15', '4', '3', '2', '0'), +('15', '4', '3', '3', '0'), + +('15', '4', '4', '0', '0'), +('15', '4', '4', '1', '0'), +('15', '4', '4', '2', '0'), +('15', '4', '4', '3', '0'), + +('15', '4', '5', '0', '0'), +('15', '4', '5', '1', '0'), +('15', '4', '5', '2', '0'), +('15', '4', '5', '3', '0'), + +('15', '4', '6', '0', '0'), +('15', '4', '6', '1', '0'), +('15', '4', '6', '2', '0'), +('15', '4', '6', '3', '0'), + +('15', '5', '0', '0', '0'), +('15', '5', '0', '1', '0'), +('15', '5', '0', '2', '0'), +('15', '5', '0', '3', '0'), + +('15', '5', '1', '0', '0'), +('15', '5', '1', '1', '0'), +('15', '5', '1', '2', '0'), +('15', '5', '1', '3', '0'), + +('15', '5', '2', '0', '0'), +('15', '5', '2', '1', '0'), +('15', '5', '2', '2', '0'), +('15', '5', '2', '3', '0'), + +('15', '5', '3', '0', '0'), +('15', '5', '3', '1', '0'), +('15', '5', '3', '2', '0'), +('15', '5', '3', '3', '0'), + +('15', '5', '4', '0', '0'), +('15', '5', '4', '1', '0'), +('15', '5', '4', '2', '0'), +('15', '5', '4', '3', '0'), + +('15', '5', '5', '0', '0'), +('15', '5', '5', '1', '0'), +('15', '5', '5', '2', '0'), +('15', '5', '5', '3', '0'), + +('15', '5', '6', '0', '0'), +('15', '5', '6', '1', '0'), +('15', '5', '6', '2', '0'), +('15', '5', '6', '3', '0'), + +('15', '6', '0', '0', '0'), +('15', '6', '0', '1', '0'), +('15', '6', '0', '2', '0'), +('15', '6', '0', '3', '0'), + +('15', '6', '1', '0', '0'), +('15', '6', '1', '1', '0'), +('15', '6', '1', '2', '0'), +('15', '6', '1', '3', '0'), + +('15', '6', '2', '0', '0'), +('15', '6', '2', '1', '0'), +('15', '6', '2', '2', '0'), +('15', '6', '2', '3', '0'), + +('15', '6', '3', '0', '0'), +('15', '6', '3', '1', '0'), +('15', '6', '3', '2', '0'), +('15', '6', '3', '3', '0'), + +('15', '6', '4', '0', '0'), +('15', '6', '4', '1', '0'), +('15', '6', '4', '2', '0'), +('15', '6', '4', '3', '0'), + +('15', '6', '5', '0', '0'), +('15', '6', '5', '1', '0'), +('15', '6', '5', '2', '0'), +('15', '6', '5', '3', '0'), + +('15', '6', '6', '0', '0'), +('15', '6', '6', '1', '0'), +('15', '6', '6', '2', '0'), +('15', '6', '6', '3', '0'), + +('15', '7', '0', '0', '0'), +('15', '7', '0', '1', '0'), +('15', '7', '0', '2', '0'), +('15', '7', '0', '3', '0'), + +('15', '7', '1', '0', '75'), +('15', '7', '1', '1', '75'), +('15', '7', '1', '2', '75'), +('15', '7', '1', '3', '75'), + +('15', '7', '2', '0', '75'), +('15', '7', '2', '1', '75'), +('15', '7', '2', '2', '75'), +('15', '7', '2', '3', '75'), + +('15', '7', '3', '0', '100'), +('15', '7', '3', '1', '100'), +('15', '7', '3', '2', '100'), +('15', '7', '3', '3', '100'), + +('15', '7', '4', '0', '100'), +('15', '7', '4', '1', '100'), +('15', '7', '4', '2', '100'), +('15', '7', '4', '3', '100'), + +('15', '7', '5', '0', '100'), +('15', '7', '5', '1', '100'), +('15', '7', '5', '2', '100'), +('15', '7', '5', '3', '100'), + +('15', '7', '6', '0', '100'), +('15', '7', '6', '1', '100'), +('15', '7', '6', '2', '100'), +('15', '7', '6', '3', '100'), + +('15', '8', '0', '0', '0'), +('15', '8', '0', '1', '0'), +('15', '8', '0', '2', '0'), +('15', '8', '0', '3', '0'), + +('15', '8', '1', '0', '0'), +('15', '8', '1', '1', '0'), +('15', '8', '1', '2', '0'), +('15', '8', '1', '3', '0'), + +('15', '8', '2', '0', '0'), +('15', '8', '2', '1', '0'), +('15', '8', '2', '2', '0'), +('15', '8', '2', '3', '0'), + +('15', '8', '3', '0', '0'), +('15', '8', '3', '1', '0'), +('15', '8', '3', '2', '0'), +('15', '8', '3', '3', '0'), + +('15', '8', '4', '0', '0'), +('15', '8', '4', '1', '0'), +('15', '8', '4', '2', '0'), +('15', '8', '4', '3', '0'), + +('15', '8', '5', '0', '0'), +('15', '8', '5', '1', '0'), +('15', '8', '5', '2', '0'), +('15', '8', '5', '3', '0'), + +('15', '8', '6', '0', '0'), +('15', '8', '6', '1', '0'), +('15', '8', '6', '2', '0'), +('15', '8', '6', '3', '0'), + +('15', '9', '0', '0', '0'), +('15', '9', '0', '1', '0'), +('15', '9', '0', '2', '0'), +('15', '9', '0', '3', '0'), + +('15', '9', '1', '0', '0'), +('15', '9', '1', '1', '0'), +('15', '9', '1', '2', '0'), +('15', '9', '1', '3', '0'), + +('15', '9', '2', '0', '0'), +('15', '9', '2', '1', '0'), +('15', '9', '2', '2', '0'), +('15', '9', '2', '3', '0'), + +('15', '9', '3', '0', '0'), +('15', '9', '3', '1', '0'), +('15', '9', '3', '2', '0'), +('15', '9', '3', '3', '0'), + +('15', '9', '4', '0', '0'), +('15', '9', '4', '1', '0'), +('15', '9', '4', '2', '0'), +('15', '9', '4', '3', '0'), + +('15', '9', '5', '0', '0'), +('15', '9', '5', '1', '0'), +('15', '9', '5', '2', '0'), +('15', '9', '5', '3', '0'), + +('15', '9', '6', '0', '0'), +('15', '9', '6', '1', '0'), +('15', '9', '6', '2', '0'), +('15', '9', '6', '3', '0'), + +('15', '10', '0', '0', '0'), +('15', '10', '0', '1', '0'), +('15', '10', '0', '2', '0'), +('15', '10', '0', '3', '0'), + +('15', '10', '1', '0', '0'), +('15', '10', '1', '1', '0'), +('15', '10', '1', '2', '0'), +('15', '10', '1', '3', '0'), + +('15', '10', '2', '0', '0'), +('15', '10', '2', '1', '0'), +('15', '10', '2', '2', '0'), +('15', '10', '2', '3', '0'), + +('15', '10', '3', '0', '0'), +('15', '10', '3', '1', '0'), +('15', '10', '3', '2', '0'), +('15', '10', '3', '3', '0'), + +('15', '10', '4', '0', '0'), +('15', '10', '4', '1', '0'), +('15', '10', '4', '2', '0'), +('15', '10', '4', '3', '0'), + +('15', '10', '5', '0', '0'), +('15', '10', '5', '1', '0'), +('15', '10', '5', '2', '0'), +('15', '10', '5', '3', '0'), + +('15', '10', '6', '0', '0'), +('15', '10', '6', '1', '0'), +('15', '10', '6', '2', '0'), +('15', '10', '6', '3', '0'), + +('15', '11', '0', '0', '0'), +('15', '11', '0', '1', '0'), +('15', '11', '0', '2', '0'), +('15', '11', '0', '3', '0'), + +('15', '11', '1', '0', '0'), +('15', '11', '1', '1', '0'), +('15', '11', '1', '2', '0'), +('15', '11', '1', '3', '0'), + +('15', '11', '2', '0', '0'), +('15', '11', '2', '1', '0'), +('15', '11', '2', '2', '0'), +('15', '11', '2', '3', '0'), + +('15', '11', '3', '0', '0'), +('15', '11', '3', '1', '0'), +('15', '11', '3', '2', '0'), +('15', '11', '3', '3', '0'), + +('15', '11', '4', '0', '0'), +('15', '11', '4', '1', '0'), +('15', '11', '4', '2', '0'), +('15', '11', '4', '3', '0'), + +('15', '11', '5', '0', '0'), +('15', '11', '5', '1', '0'), +('15', '11', '5', '2', '0'), +('15', '11', '5', '3', '0'), + +('15', '11', '6', '0', '0'), +('15', '11', '6', '1', '0'), +('15', '11', '6', '2', '0'), +('15', '11', '6', '3', '0'), + +('15', '12', '0', '0', '0'), +('15', '12', '0', '1', '0'), +('15', '12', '0', '2', '0'), +('15', '12', '0', '3', '0'), + +('15', '12', '1', '0', '0'), +('15', '12', '1', '1', '0'), +('15', '12', '1', '2', '0'), +('15', '12', '1', '3', '0'), + +('15', '12', '2', '0', '0'), +('15', '12', '2', '1', '0'), +('15', '12', '2', '2', '0'), +('15', '12', '2', '3', '0'), + +('15', '12', '3', '0', '0'), +('15', '12', '3', '1', '0'), +('15', '12', '3', '2', '0'), +('15', '12', '3', '3', '0'), + +('15', '12', '4', '0', '0'), +('15', '12', '4', '1', '0'), +('15', '12', '4', '2', '0'), +('15', '12', '4', '3', '0'), + +('15', '12', '5', '0', '0'), +('15', '12', '5', '1', '0'), +('15', '12', '5', '2', '0'), +('15', '12', '5', '3', '0'), + +('15', '12', '6', '0', '0'), +('15', '12', '6', '1', '0'), +('15', '12', '6', '2', '0'), +('15', '12', '6', '3', '0'), + +('15', '13', '0', '0', '0'), +('15', '13', '0', '1', '0'), +('15', '13', '0', '2', '0'), +('15', '13', '0', '3', '0'), + +('15', '13', '1', '0', '0'), +('15', '13', '1', '1', '0'), +('15', '13', '1', '2', '0'), +('15', '13', '1', '3', '0'), + +('15', '13', '2', '0', '0'), +('15', '13', '2', '1', '0'), +('15', '13', '2', '2', '0'), +('15', '13', '2', '3', '0'), + +('15', '13', '3', '0', '0'), +('15', '13', '3', '1', '0'), +('15', '13', '3', '2', '0'), +('15', '13', '3', '3', '0'), + +('15', '13', '4', '0', '0'), +('15', '13', '4', '1', '0'), +('15', '13', '4', '2', '0'), +('15', '13', '4', '3', '0'), + +('15', '13', '5', '0', '0'), +('15', '13', '5', '1', '0'), +('15', '13', '5', '2', '0'), +('15', '13', '5', '3', '0'), + +('15', '13', '6', '0', '0'), +('15', '13', '6', '1', '0'), +('15', '13', '6', '2', '0'), +('15', '13', '6', '3', '0'), + +('15', '14', '0', '0', '0'), +('15', '14', '0', '1', '0'), +('15', '14', '0', '2', '0'), +('15', '14', '0', '3', '0'), + +('15', '14', '1', '0', '0'), +('15', '14', '1', '1', '0'), +('15', '14', '1', '2', '0'), +('15', '14', '1', '3', '0'), + +('15', '14', '2', '0', '0'), +('15', '14', '2', '1', '0'), +('15', '14', '2', '2', '0'), +('15', '14', '2', '3', '0'), + +('15', '14', '3', '0', '0'), +('15', '14', '3', '1', '0'), +('15', '14', '3', '2', '0'), +('15', '14', '3', '3', '0'), + +('15', '14', '4', '0', '0'), +('15', '14', '4', '1', '0'), +('15', '14', '4', '2', '0'), +('15', '14', '4', '3', '0'), + +('15', '14', '5', '0', '0'), +('15', '14', '5', '1', '0'), +('15', '14', '5', '2', '0'), +('15', '14', '5', '3', '0'), + +('15', '14', '6', '0', '0'), +('15', '14', '6', '1', '0'), +('15', '14', '6', '2', '0'), +('15', '14', '6', '3', '0'), + +('15', '15', '0', '0', '0'), +('15', '15', '0', '1', '0'), +('15', '15', '0', '2', '0'), +('15', '15', '0', '3', '0'), + +('15', '15', '1', '0', '0'), +('15', '15', '1', '1', '0'), +('15', '15', '1', '2', '0'), +('15', '15', '1', '3', '0'), + +('15', '15', '2', '0', '0'), +('15', '15', '2', '1', '0'), +('15', '15', '2', '2', '0'), +('15', '15', '2', '3', '0'), + +('15', '15', '3', '0', '0'), +('15', '15', '3', '1', '0'), +('15', '15', '3', '2', '0'), +('15', '15', '3', '3', '0'), + +('15', '15', '4', '0', '0'), +('15', '15', '4', '1', '0'), +('15', '15', '4', '2', '0'), +('15', '15', '4', '3', '0'), + +('15', '15', '5', '0', '0'), +('15', '15', '5', '1', '0'), +('15', '15', '5', '2', '0'), +('15', '15', '5', '3', '0'), + +('15', '15', '6', '0', '0'), +('15', '15', '6', '1', '0'), +('15', '15', '6', '2', '0'), +('15', '15', '6', '3', '0'), + +-- SpellType_ResurrectIndex + +('16', '0', '0', '0', '0'), +('16', '0', '0', '1', '0'), +('16', '0', '0', '2', '0'), +('16', '0', '0', '3', '0'), + +('16', '0', '1', '0', '0'), +('16', '0', '1', '1', '0'), +('16', '0', '1', '2', '0'), +('16', '0', '1', '3', '0'), + +('16', '0', '2', '0', '0'), +('16', '0', '2', '1', '0'), +('16', '0', '2', '2', '0'), +('16', '0', '2', '3', '0'), + +('16', '0', '3', '0', '0'), +('16', '0', '3', '1', '0'), +('16', '0', '3', '2', '0'), +('16', '0', '3', '3', '0'), + +('16', '0', '4', '0', '0'), +('16', '0', '4', '1', '0'), +('16', '0', '4', '2', '0'), +('16', '0', '4', '3', '0'), + +('16', '0', '5', '0', '0'), +('16', '0', '5', '1', '0'), +('16', '0', '5', '2', '0'), +('16', '0', '5', '3', '0'), + +('16', '0', '6', '0', '0'), +('16', '0', '6', '1', '0'), +('16', '0', '6', '2', '0'), +('16', '0', '6', '3', '0'), + +('16', '1', '0', '0', '0'), +('16', '1', '0', '1', '0'), +('16', '1', '0', '2', '0'), +('16', '1', '0', '3', '0'), + +('16', '1', '1', '0', '0'), +('16', '1', '1', '1', '0'), +('16', '1', '1', '2', '0'), +('16', '1', '1', '3', '0'), + +('16', '1', '2', '0', '0'), +('16', '1', '2', '1', '0'), +('16', '1', '2', '2', '0'), +('16', '1', '2', '3', '0'), + +('16', '1', '3', '0', '0'), +('16', '1', '3', '1', '0'), +('16', '1', '3', '2', '0'), +('16', '1', '3', '3', '0'), + +('16', '1', '4', '0', '0'), +('16', '1', '4', '1', '0'), +('16', '1', '4', '2', '0'), +('16', '1', '4', '3', '0'), + +('16', '1', '5', '0', '0'), +('16', '1', '5', '1', '0'), +('16', '1', '5', '2', '0'), +('16', '1', '5', '3', '0'), + +('16', '1', '6', '0', '0'), +('16', '1', '6', '1', '0'), +('16', '1', '6', '2', '0'), +('16', '1', '6', '3', '0'), + +('16', '2', '0', '0', '0'), +('16', '2', '0', '1', '0'), +('16', '2', '0', '2', '0'), +('16', '2', '0', '3', '0'), + +('16', '2', '1', '0', '0'), +('16', '2', '1', '1', '0'), +('16', '2', '1', '2', '0'), +('16', '2', '1', '3', '0'), + +('16', '2', '2', '0', '0'), +('16', '2', '2', '1', '0'), +('16', '2', '2', '2', '0'), +('16', '2', '2', '3', '0'), + +('16', '2', '3', '0', '0'), +('16', '2', '3', '1', '0'), +('16', '2', '3', '2', '0'), +('16', '2', '3', '3', '0'), + +('16', '2', '4', '0', '0'), +('16', '2', '4', '1', '0'), +('16', '2', '4', '2', '0'), +('16', '2', '4', '3', '0'), + +('16', '2', '5', '0', '0'), +('16', '2', '5', '1', '0'), +('16', '2', '5', '2', '0'), +('16', '2', '5', '3', '0'), + +('16', '2', '6', '0', '0'), +('16', '2', '6', '1', '0'), +('16', '2', '6', '2', '0'), +('16', '2', '6', '3', '0'), + +('16', '3', '0', '0', '0'), +('16', '3', '0', '1', '0'), +('16', '3', '0', '2', '0'), +('16', '3', '0', '3', '0'), + +('16', '3', '1', '0', '0'), +('16', '3', '1', '1', '0'), +('16', '3', '1', '2', '0'), +('16', '3', '1', '3', '0'), + +('16', '3', '2', '0', '0'), +('16', '3', '2', '1', '0'), +('16', '3', '2', '2', '0'), +('16', '3', '2', '3', '0'), + +('16', '3', '3', '0', '0'), +('16', '3', '3', '1', '0'), +('16', '3', '3', '2', '0'), +('16', '3', '3', '3', '0'), + +('16', '3', '4', '0', '0'), +('16', '3', '4', '1', '0'), +('16', '3', '4', '2', '0'), +('16', '3', '4', '3', '0'), + +('16', '3', '5', '0', '0'), +('16', '3', '5', '1', '0'), +('16', '3', '5', '2', '0'), +('16', '3', '5', '3', '0'), + +('16', '3', '6', '0', '0'), +('16', '3', '6', '1', '0'), +('16', '3', '6', '2', '0'), +('16', '3', '6', '3', '0'), + +('16', '4', '0', '0', '0'), +('16', '4', '0', '1', '0'), +('16', '4', '0', '2', '0'), +('16', '4', '0', '3', '0'), + +('16', '4', '1', '0', '0'), +('16', '4', '1', '1', '0'), +('16', '4', '1', '2', '0'), +('16', '4', '1', '3', '0'), + +('16', '4', '2', '0', '0'), +('16', '4', '2', '1', '0'), +('16', '4', '2', '2', '0'), +('16', '4', '2', '3', '0'), + +('16', '4', '3', '0', '0'), +('16', '4', '3', '1', '0'), +('16', '4', '3', '2', '0'), +('16', '4', '3', '3', '0'), + +('16', '4', '4', '0', '0'), +('16', '4', '4', '1', '0'), +('16', '4', '4', '2', '0'), +('16', '4', '4', '3', '0'), + +('16', '4', '5', '0', '0'), +('16', '4', '5', '1', '0'), +('16', '4', '5', '2', '0'), +('16', '4', '5', '3', '0'), + +('16', '4', '6', '0', '0'), +('16', '4', '6', '1', '0'), +('16', '4', '6', '2', '0'), +('16', '4', '6', '3', '0'), + +('16', '5', '0', '0', '0'), +('16', '5', '0', '1', '0'), +('16', '5', '0', '2', '0'), +('16', '5', '0', '3', '0'), + +('16', '5', '1', '0', '0'), +('16', '5', '1', '1', '0'), +('16', '5', '1', '2', '0'), +('16', '5', '1', '3', '0'), + +('16', '5', '2', '0', '0'), +('16', '5', '2', '1', '0'), +('16', '5', '2', '2', '0'), +('16', '5', '2', '3', '0'), + +('16', '5', '3', '0', '0'), +('16', '5', '3', '1', '0'), +('16', '5', '3', '2', '0'), +('16', '5', '3', '3', '0'), + +('16', '5', '4', '0', '0'), +('16', '5', '4', '1', '0'), +('16', '5', '4', '2', '0'), +('16', '5', '4', '3', '0'), + +('16', '5', '5', '0', '0'), +('16', '5', '5', '1', '0'), +('16', '5', '5', '2', '0'), +('16', '5', '5', '3', '0'), + +('16', '5', '6', '0', '0'), +('16', '5', '6', '1', '0'), +('16', '5', '6', '2', '0'), +('16', '5', '6', '3', '0'), + +('16', '6', '0', '0', '0'), +('16', '6', '0', '1', '0'), +('16', '6', '0', '2', '0'), +('16', '6', '0', '3', '0'), + +('16', '6', '1', '0', '0'), +('16', '6', '1', '1', '0'), +('16', '6', '1', '2', '0'), +('16', '6', '1', '3', '0'), + +('16', '6', '2', '0', '0'), +('16', '6', '2', '1', '0'), +('16', '6', '2', '2', '0'), +('16', '6', '2', '3', '0'), + +('16', '6', '3', '0', '0'), +('16', '6', '3', '1', '0'), +('16', '6', '3', '2', '0'), +('16', '6', '3', '3', '0'), + +('16', '6', '4', '0', '0'), +('16', '6', '4', '1', '0'), +('16', '6', '4', '2', '0'), +('16', '6', '4', '3', '0'), + +('16', '6', '5', '0', '0'), +('16', '6', '5', '1', '0'), +('16', '6', '5', '2', '0'), +('16', '6', '5', '3', '0'), + +('16', '6', '6', '0', '0'), +('16', '6', '6', '1', '0'), +('16', '6', '6', '2', '0'), +('16', '6', '6', '3', '0'), + +('16', '7', '0', '0', '0'), +('16', '7', '0', '1', '0'), +('16', '7', '0', '2', '0'), +('16', '7', '0', '3', '0'), + +('16', '7', '1', '0', '0'), +('16', '7', '1', '1', '0'), +('16', '7', '1', '2', '0'), +('16', '7', '1', '3', '0'), + +('16', '7', '2', '0', '0'), +('16', '7', '2', '1', '0'), +('16', '7', '2', '2', '0'), +('16', '7', '2', '3', '0'), + +('16', '7', '3', '0', '0'), +('16', '7', '3', '1', '0'), +('16', '7', '3', '2', '0'), +('16', '7', '3', '3', '0'), + +('16', '7', '4', '0', '0'), +('16', '7', '4', '1', '0'), +('16', '7', '4', '2', '0'), +('16', '7', '4', '3', '0'), + +('16', '7', '5', '0', '0'), +('16', '7', '5', '1', '0'), +('16', '7', '5', '2', '0'), +('16', '7', '5', '3', '0'), + +('16', '7', '6', '0', '0'), +('16', '7', '6', '1', '0'), +('16', '7', '6', '2', '0'), +('16', '7', '6', '3', '0'), + +('16', '8', '0', '0', '0'), +('16', '8', '0', '1', '0'), +('16', '8', '0', '2', '0'), +('16', '8', '0', '3', '0'), + +('16', '8', '1', '0', '0'), +('16', '8', '1', '1', '0'), +('16', '8', '1', '2', '0'), +('16', '8', '1', '3', '0'), + +('16', '8', '2', '0', '0'), +('16', '8', '2', '1', '0'), +('16', '8', '2', '2', '0'), +('16', '8', '2', '3', '0'), + +('16', '8', '3', '0', '0'), +('16', '8', '3', '1', '0'), +('16', '8', '3', '2', '0'), +('16', '8', '3', '3', '0'), + +('16', '8', '4', '0', '0'), +('16', '8', '4', '1', '0'), +('16', '8', '4', '2', '0'), +('16', '8', '4', '3', '0'), + +('16', '8', '5', '0', '0'), +('16', '8', '5', '1', '0'), +('16', '8', '5', '2', '0'), +('16', '8', '5', '3', '0'), + +('16', '8', '6', '0', '0'), +('16', '8', '6', '1', '0'), +('16', '8', '6', '2', '0'), +('16', '8', '6', '3', '0'), + +('16', '9', '0', '0', '0'), +('16', '9', '0', '1', '0'), +('16', '9', '0', '2', '0'), +('16', '9', '0', '3', '0'), + +('16', '9', '1', '0', '0'), +('16', '9', '1', '1', '0'), +('16', '9', '1', '2', '0'), +('16', '9', '1', '3', '0'), + +('16', '9', '2', '0', '0'), +('16', '9', '2', '1', '0'), +('16', '9', '2', '2', '0'), +('16', '9', '2', '3', '0'), + +('16', '9', '3', '0', '0'), +('16', '9', '3', '1', '0'), +('16', '9', '3', '2', '0'), +('16', '9', '3', '3', '0'), + +('16', '9', '4', '0', '0'), +('16', '9', '4', '1', '0'), +('16', '9', '4', '2', '0'), +('16', '9', '4', '3', '0'), + +('16', '9', '5', '0', '0'), +('16', '9', '5', '1', '0'), +('16', '9', '5', '2', '0'), +('16', '9', '5', '3', '0'), + +('16', '9', '6', '0', '0'), +('16', '9', '6', '1', '0'), +('16', '9', '6', '2', '0'), +('16', '9', '6', '3', '0'), + +('16', '10', '0', '0', '0'), +('16', '10', '0', '1', '0'), +('16', '10', '0', '2', '0'), +('16', '10', '0', '3', '0'), + +('16', '10', '1', '0', '0'), +('16', '10', '1', '1', '0'), +('16', '10', '1', '2', '0'), +('16', '10', '1', '3', '0'), + +('16', '10', '2', '0', '0'), +('16', '10', '2', '1', '0'), +('16', '10', '2', '2', '0'), +('16', '10', '2', '3', '0'), + +('16', '10', '3', '0', '0'), +('16', '10', '3', '1', '0'), +('16', '10', '3', '2', '0'), +('16', '10', '3', '3', '0'), + +('16', '10', '4', '0', '0'), +('16', '10', '4', '1', '0'), +('16', '10', '4', '2', '0'), +('16', '10', '4', '3', '0'), + +('16', '10', '5', '0', '0'), +('16', '10', '5', '1', '0'), +('16', '10', '5', '2', '0'), +('16', '10', '5', '3', '0'), + +('16', '10', '6', '0', '0'), +('16', '10', '6', '1', '0'), +('16', '10', '6', '2', '0'), +('16', '10', '6', '3', '0'), + +('16', '11', '0', '0', '0'), +('16', '11', '0', '1', '0'), +('16', '11', '0', '2', '0'), +('16', '11', '0', '3', '0'), + +('16', '11', '1', '0', '0'), +('16', '11', '1', '1', '0'), +('16', '11', '1', '2', '0'), +('16', '11', '1', '3', '0'), + +('16', '11', '2', '0', '0'), +('16', '11', '2', '1', '0'), +('16', '11', '2', '2', '0'), +('16', '11', '2', '3', '0'), + +('16', '11', '3', '0', '0'), +('16', '11', '3', '1', '0'), +('16', '11', '3', '2', '0'), +('16', '11', '3', '3', '0'), + +('16', '11', '4', '0', '0'), +('16', '11', '4', '1', '0'), +('16', '11', '4', '2', '0'), +('16', '11', '4', '3', '0'), + +('16', '11', '5', '0', '0'), +('16', '11', '5', '1', '0'), +('16', '11', '5', '2', '0'), +('16', '11', '5', '3', '0'), + +('16', '11', '6', '0', '0'), +('16', '11', '6', '1', '0'), +('16', '11', '6', '2', '0'), +('16', '11', '6', '3', '0'), + +('16', '12', '0', '0', '0'), +('16', '12', '0', '1', '0'), +('16', '12', '0', '2', '0'), +('16', '12', '0', '3', '0'), + +('16', '12', '1', '0', '0'), +('16', '12', '1', '1', '0'), +('16', '12', '1', '2', '0'), +('16', '12', '1', '3', '0'), + +('16', '12', '2', '0', '0'), +('16', '12', '2', '1', '0'), +('16', '12', '2', '2', '0'), +('16', '12', '2', '3', '0'), + +('16', '12', '3', '0', '0'), +('16', '12', '3', '1', '0'), +('16', '12', '3', '2', '0'), +('16', '12', '3', '3', '0'), + +('16', '12', '4', '0', '0'), +('16', '12', '4', '1', '0'), +('16', '12', '4', '2', '0'), +('16', '12', '4', '3', '0'), + +('16', '12', '5', '0', '0'), +('16', '12', '5', '1', '0'), +('16', '12', '5', '2', '0'), +('16', '12', '5', '3', '0'), + +('16', '12', '6', '0', '0'), +('16', '12', '6', '1', '0'), +('16', '12', '6', '2', '0'), +('16', '12', '6', '3', '0'), + +('16', '13', '0', '0', '0'), +('16', '13', '0', '1', '0'), +('16', '13', '0', '2', '0'), +('16', '13', '0', '3', '0'), + +('16', '13', '1', '0', '0'), +('16', '13', '1', '1', '0'), +('16', '13', '1', '2', '0'), +('16', '13', '1', '3', '0'), + +('16', '13', '2', '0', '0'), +('16', '13', '2', '1', '0'), +('16', '13', '2', '2', '0'), +('16', '13', '2', '3', '0'), + +('16', '13', '3', '0', '0'), +('16', '13', '3', '1', '0'), +('16', '13', '3', '2', '0'), +('16', '13', '3', '3', '0'), + +('16', '13', '4', '0', '0'), +('16', '13', '4', '1', '0'), +('16', '13', '4', '2', '0'), +('16', '13', '4', '3', '0'), + +('16', '13', '5', '0', '0'), +('16', '13', '5', '1', '0'), +('16', '13', '5', '2', '0'), +('16', '13', '5', '3', '0'), + +('16', '13', '6', '0', '0'), +('16', '13', '6', '1', '0'), +('16', '13', '6', '2', '0'), +('16', '13', '6', '3', '0'), + +('16', '14', '0', '0', '0'), +('16', '14', '0', '1', '0'), +('16', '14', '0', '2', '0'), +('16', '14', '0', '3', '0'), + +('16', '14', '1', '0', '0'), +('16', '14', '1', '1', '0'), +('16', '14', '1', '2', '0'), +('16', '14', '1', '3', '0'), + +('16', '14', '2', '0', '0'), +('16', '14', '2', '1', '0'), +('16', '14', '2', '2', '0'), +('16', '14', '2', '3', '0'), + +('16', '14', '3', '0', '0'), +('16', '14', '3', '1', '0'), +('16', '14', '3', '2', '0'), +('16', '14', '3', '3', '0'), + +('16', '14', '4', '0', '0'), +('16', '14', '4', '1', '0'), +('16', '14', '4', '2', '0'), +('16', '14', '4', '3', '0'), + +('16', '14', '5', '0', '0'), +('16', '14', '5', '1', '0'), +('16', '14', '5', '2', '0'), +('16', '14', '5', '3', '0'), + +('16', '14', '6', '0', '0'), +('16', '14', '6', '1', '0'), +('16', '14', '6', '2', '0'), +('16', '14', '6', '3', '0'), + +('16', '15', '0', '0', '0'), +('16', '15', '0', '1', '0'), +('16', '15', '0', '2', '0'), +('16', '15', '0', '3', '0'), + +('16', '15', '1', '0', '0'), +('16', '15', '1', '1', '0'), +('16', '15', '1', '2', '0'), +('16', '15', '1', '3', '0'), + +('16', '15', '2', '0', '0'), +('16', '15', '2', '1', '0'), +('16', '15', '2', '2', '0'), +('16', '15', '2', '3', '0'), + +('16', '15', '3', '0', '0'), +('16', '15', '3', '1', '0'), +('16', '15', '3', '2', '0'), +('16', '15', '3', '3', '0'), + +('16', '15', '4', '0', '0'), +('16', '15', '4', '1', '0'), +('16', '15', '4', '2', '0'), +('16', '15', '4', '3', '0'), + +('16', '15', '5', '0', '0'), +('16', '15', '5', '1', '0'), +('16', '15', '5', '2', '0'), +('16', '15', '5', '3', '0'), + +('16', '15', '6', '0', '0'), +('16', '15', '6', '1', '0'), +('16', '15', '6', '2', '0'), +('16', '15', '6', '3', '0'), + +-- SpellType_HateReduxIndex + +('17', '0', '0', '0', '0'), +('17', '0', '0', '1', '0'), +('17', '0', '0', '2', '0'), +('17', '0', '0', '3', '0'), + +('17', '0', '1', '0', '0'), +('17', '0', '1', '1', '0'), +('17', '0', '1', '2', '0'), +('17', '0', '1', '3', '0'), + +('17', '0', '2', '0', '0'), +('17', '0', '2', '1', '0'), +('17', '0', '2', '2', '0'), +('17', '0', '2', '3', '0'), + +('17', '0', '3', '0', '0'), +('17', '0', '3', '1', '0'), +('17', '0', '3', '2', '0'), +('17', '0', '3', '3', '0'), + +('17', '0', '4', '0', '0'), +('17', '0', '4', '1', '0'), +('17', '0', '4', '2', '0'), +('17', '0', '4', '3', '0'), + +('17', '0', '5', '0', '0'), +('17', '0', '5', '1', '0'), +('17', '0', '5', '2', '0'), +('17', '0', '5', '3', '0'), + +('17', '0', '6', '0', '0'), +('17', '0', '6', '1', '0'), +('17', '0', '6', '2', '0'), +('17', '0', '6', '3', '0'), + +('17', '1', '0', '0', '0'), +('17', '1', '0', '1', '0'), +('17', '1', '0', '2', '0'), +('17', '1', '0', '3', '0'), + +('17', '1', '1', '0', '0'), +('17', '1', '1', '1', '0'), +('17', '1', '1', '2', '0'), +('17', '1', '1', '3', '0'), + +('17', '1', '2', '0', '0'), +('17', '1', '2', '1', '0'), +('17', '1', '2', '2', '0'), +('17', '1', '2', '3', '0'), + +('17', '1', '3', '0', '0'), +('17', '1', '3', '1', '0'), +('17', '1', '3', '2', '0'), +('17', '1', '3', '3', '0'), + +('17', '1', '4', '0', '0'), +('17', '1', '4', '1', '0'), +('17', '1', '4', '2', '0'), +('17', '1', '4', '3', '0'), + +('17', '1', '5', '0', '0'), +('17', '1', '5', '1', '0'), +('17', '1', '5', '2', '0'), +('17', '1', '5', '3', '0'), + +('17', '1', '6', '0', '0'), +('17', '1', '6', '1', '0'), +('17', '1', '6', '2', '0'), +('17', '1', '6', '3', '0'), + +('17', '2', '0', '0', '0'), +('17', '2', '0', '1', '0'), +('17', '2', '0', '2', '0'), +('17', '2', '0', '3', '0'), + +('17', '2', '1', '0', '0'), +('17', '2', '1', '1', '0'), +('17', '2', '1', '2', '0'), +('17', '2', '1', '3', '0'), + +('17', '2', '2', '0', '0'), +('17', '2', '2', '1', '0'), +('17', '2', '2', '2', '0'), +('17', '2', '2', '3', '0'), + +('17', '2', '3', '0', '0'), +('17', '2', '3', '1', '0'), +('17', '2', '3', '2', '0'), +('17', '2', '3', '3', '0'), + +('17', '2', '4', '0', '0'), +('17', '2', '4', '1', '0'), +('17', '2', '4', '2', '0'), +('17', '2', '4', '3', '0'), + +('17', '2', '5', '0', '0'), +('17', '2', '5', '1', '0'), +('17', '2', '5', '2', '0'), +('17', '2', '5', '3', '0'), + +('17', '2', '6', '0', '0'), +('17', '2', '6', '1', '0'), +('17', '2', '6', '2', '0'), +('17', '2', '6', '3', '0'), + +('17', '3', '0', '0', '0'), +('17', '3', '0', '1', '0'), +('17', '3', '0', '2', '0'), +('17', '3', '0', '3', '0'), + +('17', '3', '1', '0', '0'), +('17', '3', '1', '1', '0'), +('17', '3', '1', '2', '0'), +('17', '3', '1', '3', '0'), + +('17', '3', '2', '0', '0'), +('17', '3', '2', '1', '0'), +('17', '3', '2', '2', '0'), +('17', '3', '2', '3', '0'), + +('17', '3', '3', '0', '0'), +('17', '3', '3', '1', '0'), +('17', '3', '3', '2', '0'), +('17', '3', '3', '3', '0'), + +('17', '3', '4', '0', '0'), +('17', '3', '4', '1', '0'), +('17', '3', '4', '2', '0'), +('17', '3', '4', '3', '0'), + +('17', '3', '5', '0', '0'), +('17', '3', '5', '1', '0'), +('17', '3', '5', '2', '0'), +('17', '3', '5', '3', '0'), + +('17', '3', '6', '0', '0'), +('17', '3', '6', '1', '0'), +('17', '3', '6', '2', '0'), +('17', '3', '6', '3', '0'), + +('17', '4', '0', '0', '0'), +('17', '4', '0', '1', '0'), +('17', '4', '0', '2', '0'), +('17', '4', '0', '3', '0'), + +('17', '4', '1', '0', '0'), +('17', '4', '1', '1', '0'), +('17', '4', '1', '2', '0'), +('17', '4', '1', '3', '0'), + +('17', '4', '2', '0', '0'), +('17', '4', '2', '1', '0'), +('17', '4', '2', '2', '0'), +('17', '4', '2', '3', '0'), + +('17', '4', '3', '0', '0'), +('17', '4', '3', '1', '0'), +('17', '4', '3', '2', '0'), +('17', '4', '3', '3', '0'), + +('17', '4', '4', '0', '0'), +('17', '4', '4', '1', '0'), +('17', '4', '4', '2', '0'), +('17', '4', '4', '3', '0'), + +('17', '4', '5', '0', '0'), +('17', '4', '5', '1', '0'), +('17', '4', '5', '2', '0'), +('17', '4', '5', '3', '0'), + +('17', '4', '6', '0', '0'), +('17', '4', '6', '1', '0'), +('17', '4', '6', '2', '0'), +('17', '4', '6', '3', '0'), + +('17', '5', '0', '0', '0'), +('17', '5', '0', '1', '0'), +('17', '5', '0', '2', '0'), +('17', '5', '0', '3', '0'), + +('17', '5', '1', '0', '0'), +('17', '5', '1', '1', '0'), +('17', '5', '1', '2', '0'), +('17', '5', '1', '3', '0'), + +('17', '5', '2', '0', '0'), +('17', '5', '2', '1', '0'), +('17', '5', '2', '2', '0'), +('17', '5', '2', '3', '0'), + +('17', '5', '3', '0', '0'), +('17', '5', '3', '1', '0'), +('17', '5', '3', '2', '0'), +('17', '5', '3', '3', '0'), + +('17', '5', '4', '0', '0'), +('17', '5', '4', '1', '0'), +('17', '5', '4', '2', '0'), +('17', '5', '4', '3', '0'), + +('17', '5', '5', '0', '0'), +('17', '5', '5', '1', '0'), +('17', '5', '5', '2', '0'), +('17', '5', '5', '3', '0'), + +('17', '5', '6', '0', '0'), +('17', '5', '6', '1', '0'), +('17', '5', '6', '2', '0'), +('17', '5', '6', '3', '0'), + +('17', '6', '0', '0', '0'), +('17', '6', '0', '1', '0'), +('17', '6', '0', '2', '0'), +('17', '6', '0', '3', '0'), + +('17', '6', '1', '0', '0'), +('17', '6', '1', '1', '0'), +('17', '6', '1', '2', '0'), +('17', '6', '1', '3', '0'), + +('17', '6', '2', '0', '0'), +('17', '6', '2', '1', '0'), +('17', '6', '2', '2', '0'), +('17', '6', '2', '3', '0'), + +('17', '6', '3', '0', '0'), +('17', '6', '3', '1', '0'), +('17', '6', '3', '2', '0'), +('17', '6', '3', '3', '0'), + +('17', '6', '4', '0', '0'), +('17', '6', '4', '1', '0'), +('17', '6', '4', '2', '0'), +('17', '6', '4', '3', '0'), + +('17', '6', '5', '0', '0'), +('17', '6', '5', '1', '0'), +('17', '6', '5', '2', '0'), +('17', '6', '5', '3', '0'), + +('17', '6', '6', '0', '0'), +('17', '6', '6', '1', '0'), +('17', '6', '6', '2', '0'), +('17', '6', '6', '3', '0'), + +('17', '7', '0', '0', '0'), +('17', '7', '0', '1', '0'), +('17', '7', '0', '2', '0'), +('17', '7', '0', '3', '0'), + +('17', '7', '1', '0', '0'), +('17', '7', '1', '1', '0'), +('17', '7', '1', '2', '0'), +('17', '7', '1', '3', '0'), + +('17', '7', '2', '0', '0'), +('17', '7', '2', '1', '0'), +('17', '7', '2', '2', '0'), +('17', '7', '2', '3', '0'), + +('17', '7', '3', '0', '0'), +('17', '7', '3', '1', '0'), +('17', '7', '3', '2', '0'), +('17', '7', '3', '3', '0'), + +('17', '7', '4', '0', '0'), +('17', '7', '4', '1', '0'), +('17', '7', '4', '2', '0'), +('17', '7', '4', '3', '0'), + +('17', '7', '5', '0', '0'), +('17', '7', '5', '1', '0'), +('17', '7', '5', '2', '0'), +('17', '7', '5', '3', '0'), + +('17', '7', '6', '0', '0'), +('17', '7', '6', '1', '0'), +('17', '7', '6', '2', '0'), +('17', '7', '6', '3', '0'), + +('17', '8', '0', '0', '0'), +('17', '8', '0', '1', '0'), +('17', '8', '0', '2', '0'), +('17', '8', '0', '3', '0'), + +('17', '8', '1', '0', '0'), +('17', '8', '1', '1', '0'), +('17', '8', '1', '2', '0'), +('17', '8', '1', '3', '0'), + +('17', '8', '2', '0', '0'), +('17', '8', '2', '1', '0'), +('17', '8', '2', '2', '0'), +('17', '8', '2', '3', '0'), + +('17', '8', '3', '0', '0'), +('17', '8', '3', '1', '0'), +('17', '8', '3', '2', '0'), +('17', '8', '3', '3', '0'), + +('17', '8', '4', '0', '0'), +('17', '8', '4', '1', '0'), +('17', '8', '4', '2', '0'), +('17', '8', '4', '3', '0'), + +('17', '8', '5', '0', '0'), +('17', '8', '5', '1', '0'), +('17', '8', '5', '2', '0'), +('17', '8', '5', '3', '0'), + +('17', '8', '6', '0', '0'), +('17', '8', '6', '1', '0'), +('17', '8', '6', '2', '0'), +('17', '8', '6', '3', '0'), + +('17', '9', '0', '0', '0'), +('17', '9', '0', '1', '0'), +('17', '9', '0', '2', '0'), +('17', '9', '0', '3', '0'), + +('17', '9', '1', '0', '0'), +('17', '9', '1', '1', '0'), +('17', '9', '1', '2', '0'), +('17', '9', '1', '3', '0'), + +('17', '9', '2', '0', '0'), +('17', '9', '2', '1', '0'), +('17', '9', '2', '2', '0'), +('17', '9', '2', '3', '0'), + +('17', '9', '3', '0', '0'), +('17', '9', '3', '1', '0'), +('17', '9', '3', '2', '0'), +('17', '9', '3', '3', '0'), + +('17', '9', '4', '0', '0'), +('17', '9', '4', '1', '0'), +('17', '9', '4', '2', '0'), +('17', '9', '4', '3', '0'), + +('17', '9', '5', '0', '0'), +('17', '9', '5', '1', '0'), +('17', '9', '5', '2', '0'), +('17', '9', '5', '3', '0'), + +('17', '9', '6', '0', '0'), +('17', '9', '6', '1', '0'), +('17', '9', '6', '2', '0'), +('17', '9', '6', '3', '0'), + +('17', '10', '0', '0', '0'), +('17', '10', '0', '1', '0'), +('17', '10', '0', '2', '0'), +('17', '10', '0', '3', '0'), + +('17', '10', '1', '0', '0'), +('17', '10', '1', '1', '0'), +('17', '10', '1', '2', '0'), +('17', '10', '1', '3', '0'), + +('17', '10', '2', '0', '0'), +('17', '10', '2', '1', '0'), +('17', '10', '2', '2', '0'), +('17', '10', '2', '3', '0'), + +('17', '10', '3', '0', '0'), +('17', '10', '3', '1', '0'), +('17', '10', '3', '2', '0'), +('17', '10', '3', '3', '0'), + +('17', '10', '4', '0', '0'), +('17', '10', '4', '1', '0'), +('17', '10', '4', '2', '0'), +('17', '10', '4', '3', '0'), + +('17', '10', '5', '0', '0'), +('17', '10', '5', '1', '0'), +('17', '10', '5', '2', '0'), +('17', '10', '5', '3', '0'), + +('17', '10', '6', '0', '0'), +('17', '10', '6', '1', '0'), +('17', '10', '6', '2', '0'), +('17', '10', '6', '3', '0'), + +('17', '11', '0', '0', '0'), +('17', '11', '0', '1', '0'), +('17', '11', '0', '2', '0'), +('17', '11', '0', '3', '0'), + +('17', '11', '1', '0', '0'), +('17', '11', '1', '1', '0'), +('17', '11', '1', '2', '0'), +('17', '11', '1', '3', '0'), + +('17', '11', '2', '0', '0'), +('17', '11', '2', '1', '0'), +('17', '11', '2', '2', '0'), +('17', '11', '2', '3', '0'), + +('17', '11', '3', '0', '0'), +('17', '11', '3', '1', '0'), +('17', '11', '3', '2', '0'), +('17', '11', '3', '3', '0'), + +('17', '11', '4', '0', '0'), +('17', '11', '4', '1', '0'), +('17', '11', '4', '2', '0'), +('17', '11', '4', '3', '0'), + +('17', '11', '5', '0', '0'), +('17', '11', '5', '1', '0'), +('17', '11', '5', '2', '0'), +('17', '11', '5', '3', '0'), + +('17', '11', '6', '0', '0'), +('17', '11', '6', '1', '0'), +('17', '11', '6', '2', '0'), +('17', '11', '6', '3', '0'), + +('17', '12', '0', '0', '0'), +('17', '12', '0', '1', '0'), +('17', '12', '0', '2', '0'), +('17', '12', '0', '3', '0'), + +('17', '12', '1', '0', '0'), +('17', '12', '1', '1', '0'), +('17', '12', '1', '2', '0'), +('17', '12', '1', '3', '0'), + +('17', '12', '2', '0', '0'), +('17', '12', '2', '1', '0'), +('17', '12', '2', '2', '0'), +('17', '12', '2', '3', '0'), + +('17', '12', '3', '0', '0'), +('17', '12', '3', '1', '0'), +('17', '12', '3', '2', '0'), +('17', '12', '3', '3', '0'), + +('17', '12', '4', '0', '0'), +('17', '12', '4', '1', '0'), +('17', '12', '4', '2', '0'), +('17', '12', '4', '3', '0'), + +('17', '12', '5', '0', '0'), +('17', '12', '5', '1', '0'), +('17', '12', '5', '2', '0'), +('17', '12', '5', '3', '0'), + +('17', '12', '6', '0', '0'), +('17', '12', '6', '1', '0'), +('17', '12', '6', '2', '0'), +('17', '12', '6', '3', '0'), + +('17', '13', '0', '0', '0'), +('17', '13', '0', '1', '0'), +('17', '13', '0', '2', '0'), +('17', '13', '0', '3', '0'), + +('17', '13', '1', '0', '0'), +('17', '13', '1', '1', '0'), +('17', '13', '1', '2', '0'), +('17', '13', '1', '3', '0'), + +('17', '13', '2', '0', '0'), +('17', '13', '2', '1', '0'), +('17', '13', '2', '2', '0'), +('17', '13', '2', '3', '0'), + +('17', '13', '3', '0', '0'), +('17', '13', '3', '1', '0'), +('17', '13', '3', '2', '0'), +('17', '13', '3', '3', '0'), + +('17', '13', '4', '0', '0'), +('17', '13', '4', '1', '0'), +('17', '13', '4', '2', '0'), +('17', '13', '4', '3', '0'), + +('17', '13', '5', '0', '0'), +('17', '13', '5', '1', '0'), +('17', '13', '5', '2', '0'), +('17', '13', '5', '3', '0'), + +('17', '13', '6', '0', '0'), +('17', '13', '6', '1', '0'), +('17', '13', '6', '2', '0'), +('17', '13', '6', '3', '0'), + +('17', '14', '0', '0', '0'), +('17', '14', '0', '1', '0'), +('17', '14', '0', '2', '0'), +('17', '14', '0', '3', '0'), + +('17', '14', '1', '0', '0'), +('17', '14', '1', '1', '0'), +('17', '14', '1', '2', '0'), +('17', '14', '1', '3', '0'), + +('17', '14', '2', '0', '0'), +('17', '14', '2', '1', '0'), +('17', '14', '2', '2', '0'), +('17', '14', '2', '3', '0'), + +('17', '14', '3', '0', '0'), +('17', '14', '3', '1', '0'), +('17', '14', '3', '2', '0'), +('17', '14', '3', '3', '0'), + +('17', '14', '4', '0', '0'), +('17', '14', '4', '1', '0'), +('17', '14', '4', '2', '0'), +('17', '14', '4', '3', '0'), + +('17', '14', '5', '0', '0'), +('17', '14', '5', '1', '0'), +('17', '14', '5', '2', '0'), +('17', '14', '5', '3', '0'), + +('17', '14', '6', '0', '0'), +('17', '14', '6', '1', '0'), +('17', '14', '6', '2', '0'), +('17', '14', '6', '3', '0'), + +('17', '15', '0', '0', '0'), +('17', '15', '0', '1', '0'), +('17', '15', '0', '2', '0'), +('17', '15', '0', '3', '0'), + +('17', '15', '1', '0', '0'), +('17', '15', '1', '1', '0'), +('17', '15', '1', '2', '0'), +('17', '15', '1', '3', '0'), + +('17', '15', '2', '0', '0'), +('17', '15', '2', '1', '0'), +('17', '15', '2', '2', '0'), +('17', '15', '2', '3', '0'), + +('17', '15', '3', '0', '0'), +('17', '15', '3', '1', '0'), +('17', '15', '3', '2', '0'), +('17', '15', '3', '3', '0'), + +('17', '15', '4', '0', '0'), +('17', '15', '4', '1', '0'), +('17', '15', '4', '2', '0'), +('17', '15', '4', '3', '0'), + +('17', '15', '5', '0', '0'), +('17', '15', '5', '1', '0'), +('17', '15', '5', '2', '0'), +('17', '15', '5', '3', '0'), + +('17', '15', '6', '0', '0'), +('17', '15', '6', '1', '0'), +('17', '15', '6', '2', '0'), +('17', '15', '6', '3', '0'), + +-- SpellType_InCombatBuffSongIndex + +('18', '0', '0', '0', '0'), +('18', '0', '0', '1', '0'), +('18', '0', '0', '2', '0'), +('18', '0', '0', '3', '0'), + +('18', '0', '1', '0', '0'), +('18', '0', '1', '1', '0'), +('18', '0', '1', '2', '0'), +('18', '0', '1', '3', '0'), + +('18', '0', '2', '0', '0'), +('18', '0', '2', '1', '0'), +('18', '0', '2', '2', '0'), +('18', '0', '2', '3', '0'), + +('18', '0', '3', '0', '0'), +('18', '0', '3', '1', '0'), +('18', '0', '3', '2', '0'), +('18', '0', '3', '3', '0'), + +('18', '0', '4', '0', '0'), +('18', '0', '4', '1', '0'), +('18', '0', '4', '2', '0'), +('18', '0', '4', '3', '0'), + +('18', '0', '5', '0', '0'), +('18', '0', '5', '1', '0'), +('18', '0', '5', '2', '0'), +('18', '0', '5', '3', '0'), + +('18', '0', '6', '0', '0'), +('18', '0', '6', '1', '0'), +('18', '0', '6', '2', '0'), +('18', '0', '6', '3', '0'), + +('18', '1', '0', '0', '0'), +('18', '1', '0', '1', '0'), +('18', '1', '0', '2', '0'), +('18', '1', '0', '3', '0'), + +('18', '1', '1', '0', '0'), +('18', '1', '1', '1', '0'), +('18', '1', '1', '2', '0'), +('18', '1', '1', '3', '0'), + +('18', '1', '2', '0', '0'), +('18', '1', '2', '1', '0'), +('18', '1', '2', '2', '0'), +('18', '1', '2', '3', '0'), + +('18', '1', '3', '0', '0'), +('18', '1', '3', '1', '0'), +('18', '1', '3', '2', '0'), +('18', '1', '3', '3', '0'), + +('18', '1', '4', '0', '0'), +('18', '1', '4', '1', '0'), +('18', '1', '4', '2', '0'), +('18', '1', '4', '3', '0'), + +('18', '1', '5', '0', '0'), +('18', '1', '5', '1', '0'), +('18', '1', '5', '2', '0'), +('18', '1', '5', '3', '0'), + +('18', '1', '6', '0', '0'), +('18', '1', '6', '1', '0'), +('18', '1', '6', '2', '0'), +('18', '1', '6', '3', '0'), + +('18', '2', '0', '0', '0'), +('18', '2', '0', '1', '0'), +('18', '2', '0', '2', '0'), +('18', '2', '0', '3', '0'), + +('18', '2', '1', '0', '0'), +('18', '2', '1', '1', '0'), +('18', '2', '1', '2', '0'), +('18', '2', '1', '3', '0'), + +('18', '2', '2', '0', '0'), +('18', '2', '2', '1', '0'), +('18', '2', '2', '2', '0'), +('18', '2', '2', '3', '0'), + +('18', '2', '3', '0', '0'), +('18', '2', '3', '1', '0'), +('18', '2', '3', '2', '0'), +('18', '2', '3', '3', '0'), + +('18', '2', '4', '0', '0'), +('18', '2', '4', '1', '0'), +('18', '2', '4', '2', '0'), +('18', '2', '4', '3', '0'), + +('18', '2', '5', '0', '0'), +('18', '2', '5', '1', '0'), +('18', '2', '5', '2', '0'), +('18', '2', '5', '3', '0'), + +('18', '2', '6', '0', '0'), +('18', '2', '6', '1', '0'), +('18', '2', '6', '2', '0'), +('18', '2', '6', '3', '0'), + +('18', '3', '0', '0', '0'), +('18', '3', '0', '1', '0'), +('18', '3', '0', '2', '0'), +('18', '3', '0', '3', '0'), + +('18', '3', '1', '0', '0'), +('18', '3', '1', '1', '0'), +('18', '3', '1', '2', '0'), +('18', '3', '1', '3', '0'), + +('18', '3', '2', '0', '0'), +('18', '3', '2', '1', '0'), +('18', '3', '2', '2', '0'), +('18', '3', '2', '3', '0'), + +('18', '3', '3', '0', '0'), +('18', '3', '3', '1', '0'), +('18', '3', '3', '2', '0'), +('18', '3', '3', '3', '0'), + +('18', '3', '4', '0', '0'), +('18', '3', '4', '1', '0'), +('18', '3', '4', '2', '0'), +('18', '3', '4', '3', '0'), + +('18', '3', '5', '0', '0'), +('18', '3', '5', '1', '0'), +('18', '3', '5', '2', '0'), +('18', '3', '5', '3', '0'), + +('18', '3', '6', '0', '0'), +('18', '3', '6', '1', '0'), +('18', '3', '6', '2', '0'), +('18', '3', '6', '3', '0'), + +('18', '4', '0', '0', '0'), +('18', '4', '0', '1', '0'), +('18', '4', '0', '2', '0'), +('18', '4', '0', '3', '0'), + +('18', '4', '1', '0', '0'), +('18', '4', '1', '1', '0'), +('18', '4', '1', '2', '0'), +('18', '4', '1', '3', '0'), + +('18', '4', '2', '0', '0'), +('18', '4', '2', '1', '0'), +('18', '4', '2', '2', '0'), +('18', '4', '2', '3', '0'), + +('18', '4', '3', '0', '0'), +('18', '4', '3', '1', '0'), +('18', '4', '3', '2', '0'), +('18', '4', '3', '3', '0'), + +('18', '4', '4', '0', '0'), +('18', '4', '4', '1', '0'), +('18', '4', '4', '2', '0'), +('18', '4', '4', '3', '0'), + +('18', '4', '5', '0', '0'), +('18', '4', '5', '1', '0'), +('18', '4', '5', '2', '0'), +('18', '4', '5', '3', '0'), + +('18', '4', '6', '0', '0'), +('18', '4', '6', '1', '0'), +('18', '4', '6', '2', '0'), +('18', '4', '6', '3', '0'), + +('18', '5', '0', '0', '0'), +('18', '5', '0', '1', '0'), +('18', '5', '0', '2', '0'), +('18', '5', '0', '3', '0'), + +('18', '5', '1', '0', '0'), +('18', '5', '1', '1', '0'), +('18', '5', '1', '2', '0'), +('18', '5', '1', '3', '0'), + +('18', '5', '2', '0', '0'), +('18', '5', '2', '1', '0'), +('18', '5', '2', '2', '0'), +('18', '5', '2', '3', '0'), + +('18', '5', '3', '0', '0'), +('18', '5', '3', '1', '0'), +('18', '5', '3', '2', '0'), +('18', '5', '3', '3', '0'), + +('18', '5', '4', '0', '0'), +('18', '5', '4', '1', '0'), +('18', '5', '4', '2', '0'), +('18', '5', '4', '3', '0'), + +('18', '5', '5', '0', '0'), +('18', '5', '5', '1', '0'), +('18', '5', '5', '2', '0'), +('18', '5', '5', '3', '0'), + +('18', '5', '6', '0', '0'), +('18', '5', '6', '1', '0'), +('18', '5', '6', '2', '0'), +('18', '5', '6', '3', '0'), + +('18', '6', '0', '0', '0'), +('18', '6', '0', '1', '0'), +('18', '6', '0', '2', '0'), +('18', '6', '0', '3', '0'), + +('18', '6', '1', '0', '0'), +('18', '6', '1', '1', '0'), +('18', '6', '1', '2', '0'), +('18', '6', '1', '3', '0'), + +('18', '6', '2', '0', '0'), +('18', '6', '2', '1', '0'), +('18', '6', '2', '2', '0'), +('18', '6', '2', '3', '0'), + +('18', '6', '3', '0', '0'), +('18', '6', '3', '1', '0'), +('18', '6', '3', '2', '0'), +('18', '6', '3', '3', '0'), + +('18', '6', '4', '0', '0'), +('18', '6', '4', '1', '0'), +('18', '6', '4', '2', '0'), +('18', '6', '4', '3', '0'), + +('18', '6', '5', '0', '0'), +('18', '6', '5', '1', '0'), +('18', '6', '5', '2', '0'), +('18', '6', '5', '3', '0'), + +('18', '6', '6', '0', '0'), +('18', '6', '6', '1', '0'), +('18', '6', '6', '2', '0'), +('18', '6', '6', '3', '0'), + +('18', '7', '0', '0', '0'), +('18', '7', '0', '1', '0'), +('18', '7', '0', '2', '0'), +('18', '7', '0', '3', '0'), + +('18', '7', '1', '0', '100'), +('18', '7', '1', '1', '100'), +('18', '7', '1', '2', '100'), +('18', '7', '1', '3', '100'), + +('18', '7', '2', '0', '75'), +('18', '7', '2', '1', '75'), +('18', '7', '2', '2', '75'), +('18', '7', '2', '3', '75'), + +('18', '7', '3', '0', '75'), +('18', '7', '3', '1', '75'), +('18', '7', '3', '2', '75'), +('18', '7', '3', '3', '75'), + +('18', '7', '4', '0', '100'), +('18', '7', '4', '1', '100'), +('18', '7', '4', '2', '100'), +('18', '7', '4', '3', '100'), + +('18', '7', '5', '0', '100'), +('18', '7', '5', '1', '100'), +('18', '7', '5', '2', '100'), +('18', '7', '5', '3', '100'), + +('18', '7', '6', '0', '100'), +('18', '7', '6', '1', '100'), +('18', '7', '6', '2', '100'), +('18', '7', '6', '3', '100'), + +('18', '8', '0', '0', '0'), +('18', '8', '0', '1', '0'), +('18', '8', '0', '2', '0'), +('18', '8', '0', '3', '0'), + +('18', '8', '1', '0', '0'), +('18', '8', '1', '1', '0'), +('18', '8', '1', '2', '0'), +('18', '8', '1', '3', '0'), + +('18', '8', '2', '0', '0'), +('18', '8', '2', '1', '0'), +('18', '8', '2', '2', '0'), +('18', '8', '2', '3', '0'), + +('18', '8', '3', '0', '0'), +('18', '8', '3', '1', '0'), +('18', '8', '3', '2', '0'), +('18', '8', '3', '3', '0'), + +('18', '8', '4', '0', '0'), +('18', '8', '4', '1', '0'), +('18', '8', '4', '2', '0'), +('18', '8', '4', '3', '0'), + +('18', '8', '5', '0', '0'), +('18', '8', '5', '1', '0'), +('18', '8', '5', '2', '0'), +('18', '8', '5', '3', '0'), + +('18', '8', '6', '0', '0'), +('18', '8', '6', '1', '0'), +('18', '8', '6', '2', '0'), +('18', '8', '6', '3', '0'), + +('18', '9', '0', '0', '0'), +('18', '9', '0', '1', '0'), +('18', '9', '0', '2', '0'), +('18', '9', '0', '3', '0'), + +('18', '9', '1', '0', '0'), +('18', '9', '1', '1', '0'), +('18', '9', '1', '2', '0'), +('18', '9', '1', '3', '0'), + +('18', '9', '2', '0', '0'), +('18', '9', '2', '1', '0'), +('18', '9', '2', '2', '0'), +('18', '9', '2', '3', '0'), + +('18', '9', '3', '0', '0'), +('18', '9', '3', '1', '0'), +('18', '9', '3', '2', '0'), +('18', '9', '3', '3', '0'), + +('18', '9', '4', '0', '0'), +('18', '9', '4', '1', '0'), +('18', '9', '4', '2', '0'), +('18', '9', '4', '3', '0'), + +('18', '9', '5', '0', '0'), +('18', '9', '5', '1', '0'), +('18', '9', '5', '2', '0'), +('18', '9', '5', '3', '0'), + +('18', '9', '6', '0', '0'), +('18', '9', '6', '1', '0'), +('18', '9', '6', '2', '0'), +('18', '9', '6', '3', '0'), + +('18', '10', '0', '0', '0'), +('18', '10', '0', '1', '0'), +('18', '10', '0', '2', '0'), +('18', '10', '0', '3', '0'), + +('18', '10', '1', '0', '0'), +('18', '10', '1', '1', '0'), +('18', '10', '1', '2', '0'), +('18', '10', '1', '3', '0'), + +('18', '10', '2', '0', '0'), +('18', '10', '2', '1', '0'), +('18', '10', '2', '2', '0'), +('18', '10', '2', '3', '0'), + +('18', '10', '3', '0', '0'), +('18', '10', '3', '1', '0'), +('18', '10', '3', '2', '0'), +('18', '10', '3', '3', '0'), + +('18', '10', '4', '0', '0'), +('18', '10', '4', '1', '0'), +('18', '10', '4', '2', '0'), +('18', '10', '4', '3', '0'), + +('18', '10', '5', '0', '0'), +('18', '10', '5', '1', '0'), +('18', '10', '5', '2', '0'), +('18', '10', '5', '3', '0'), + +('18', '10', '6', '0', '0'), +('18', '10', '6', '1', '0'), +('18', '10', '6', '2', '0'), +('18', '10', '6', '3', '0'), + +('18', '11', '0', '0', '0'), +('18', '11', '0', '1', '0'), +('18', '11', '0', '2', '0'), +('18', '11', '0', '3', '0'), + +('18', '11', '1', '0', '0'), +('18', '11', '1', '1', '0'), +('18', '11', '1', '2', '0'), +('18', '11', '1', '3', '0'), + +('18', '11', '2', '0', '0'), +('18', '11', '2', '1', '0'), +('18', '11', '2', '2', '0'), +('18', '11', '2', '3', '0'), + +('18', '11', '3', '0', '0'), +('18', '11', '3', '1', '0'), +('18', '11', '3', '2', '0'), +('18', '11', '3', '3', '0'), + +('18', '11', '4', '0', '0'), +('18', '11', '4', '1', '0'), +('18', '11', '4', '2', '0'), +('18', '11', '4', '3', '0'), + +('18', '11', '5', '0', '0'), +('18', '11', '5', '1', '0'), +('18', '11', '5', '2', '0'), +('18', '11', '5', '3', '0'), + +('18', '11', '6', '0', '0'), +('18', '11', '6', '1', '0'), +('18', '11', '6', '2', '0'), +('18', '11', '6', '3', '0'), + +('18', '12', '0', '0', '0'), +('18', '12', '0', '1', '0'), +('18', '12', '0', '2', '0'), +('18', '12', '0', '3', '0'), + +('18', '12', '1', '0', '0'), +('18', '12', '1', '1', '0'), +('18', '12', '1', '2', '0'), +('18', '12', '1', '3', '0'), + +('18', '12', '2', '0', '0'), +('18', '12', '2', '1', '0'), +('18', '12', '2', '2', '0'), +('18', '12', '2', '3', '0'), + +('18', '12', '3', '0', '0'), +('18', '12', '3', '1', '0'), +('18', '12', '3', '2', '0'), +('18', '12', '3', '3', '0'), + +('18', '12', '4', '0', '0'), +('18', '12', '4', '1', '0'), +('18', '12', '4', '2', '0'), +('18', '12', '4', '3', '0'), + +('18', '12', '5', '0', '0'), +('18', '12', '5', '1', '0'), +('18', '12', '5', '2', '0'), +('18', '12', '5', '3', '0'), + +('18', '12', '6', '0', '0'), +('18', '12', '6', '1', '0'), +('18', '12', '6', '2', '0'), +('18', '12', '6', '3', '0'), + +('18', '13', '0', '0', '0'), +('18', '13', '0', '1', '0'), +('18', '13', '0', '2', '0'), +('18', '13', '0', '3', '0'), + +('18', '13', '1', '0', '0'), +('18', '13', '1', '1', '0'), +('18', '13', '1', '2', '0'), +('18', '13', '1', '3', '0'), + +('18', '13', '2', '0', '0'), +('18', '13', '2', '1', '0'), +('18', '13', '2', '2', '0'), +('18', '13', '2', '3', '0'), + +('18', '13', '3', '0', '0'), +('18', '13', '3', '1', '0'), +('18', '13', '3', '2', '0'), +('18', '13', '3', '3', '0'), + +('18', '13', '4', '0', '0'), +('18', '13', '4', '1', '0'), +('18', '13', '4', '2', '0'), +('18', '13', '4', '3', '0'), + +('18', '13', '5', '0', '0'), +('18', '13', '5', '1', '0'), +('18', '13', '5', '2', '0'), +('18', '13', '5', '3', '0'), + +('18', '13', '6', '0', '0'), +('18', '13', '6', '1', '0'), +('18', '13', '6', '2', '0'), +('18', '13', '6', '3', '0'), + +('18', '14', '0', '0', '0'), +('18', '14', '0', '1', '0'), +('18', '14', '0', '2', '0'), +('18', '14', '0', '3', '0'), + +('18', '14', '1', '0', '0'), +('18', '14', '1', '1', '0'), +('18', '14', '1', '2', '0'), +('18', '14', '1', '3', '0'), + +('18', '14', '2', '0', '0'), +('18', '14', '2', '1', '0'), +('18', '14', '2', '2', '0'), +('18', '14', '2', '3', '0'), + +('18', '14', '3', '0', '0'), +('18', '14', '3', '1', '0'), +('18', '14', '3', '2', '0'), +('18', '14', '3', '3', '0'), + +('18', '14', '4', '0', '0'), +('18', '14', '4', '1', '0'), +('18', '14', '4', '2', '0'), +('18', '14', '4', '3', '0'), + +('18', '14', '5', '0', '0'), +('18', '14', '5', '1', '0'), +('18', '14', '5', '2', '0'), +('18', '14', '5', '3', '0'), + +('18', '14', '6', '0', '0'), +('18', '14', '6', '1', '0'), +('18', '14', '6', '2', '0'), +('18', '14', '6', '3', '0'), + +('18', '15', '0', '0', '0'), +('18', '15', '0', '1', '0'), +('18', '15', '0', '2', '0'), +('18', '15', '0', '3', '0'), + +('18', '15', '1', '0', '0'), +('18', '15', '1', '1', '0'), +('18', '15', '1', '2', '0'), +('18', '15', '1', '3', '0'), + +('18', '15', '2', '0', '0'), +('18', '15', '2', '1', '0'), +('18', '15', '2', '2', '0'), +('18', '15', '2', '3', '0'), + +('18', '15', '3', '0', '0'), +('18', '15', '3', '1', '0'), +('18', '15', '3', '2', '0'), +('18', '15', '3', '3', '0'), + +('18', '15', '4', '0', '0'), +('18', '15', '4', '1', '0'), +('18', '15', '4', '2', '0'), +('18', '15', '4', '3', '0'), + +('18', '15', '5', '0', '0'), +('18', '15', '5', '1', '0'), +('18', '15', '5', '2', '0'), +('18', '15', '5', '3', '0'), + +('18', '15', '6', '0', '0'), +('18', '15', '6', '1', '0'), +('18', '15', '6', '2', '0'), +('18', '15', '6', '3', '0'), + +-- SpellType_OutOfCombatBuffSongIndex + +('19', '0', '0', '0', '0'), +('19', '0', '0', '1', '0'), +('19', '0', '0', '2', '0'), +('19', '0', '0', '3', '0'), + +('19', '0', '1', '0', '0'), +('19', '0', '1', '1', '0'), +('19', '0', '1', '2', '0'), +('19', '0', '1', '3', '0'), + +('19', '0', '2', '0', '0'), +('19', '0', '2', '1', '0'), +('19', '0', '2', '2', '0'), +('19', '0', '2', '3', '0'), + +('19', '0', '3', '0', '0'), +('19', '0', '3', '1', '0'), +('19', '0', '3', '2', '0'), +('19', '0', '3', '3', '0'), + +('19', '0', '4', '0', '0'), +('19', '0', '4', '1', '0'), +('19', '0', '4', '2', '0'), +('19', '0', '4', '3', '0'), + +('19', '0', '5', '0', '0'), +('19', '0', '5', '1', '0'), +('19', '0', '5', '2', '0'), +('19', '0', '5', '3', '0'), + +('19', '0', '6', '0', '0'), +('19', '0', '6', '1', '0'), +('19', '0', '6', '2', '0'), +('19', '0', '6', '3', '0'), + +('19', '1', '0', '0', '0'), +('19', '1', '0', '1', '0'), +('19', '1', '0', '2', '0'), +('19', '1', '0', '3', '0'), + +('19', '1', '1', '0', '0'), +('19', '1', '1', '1', '0'), +('19', '1', '1', '2', '0'), +('19', '1', '1', '3', '0'), + +('19', '1', '2', '0', '0'), +('19', '1', '2', '1', '0'), +('19', '1', '2', '2', '0'), +('19', '1', '2', '3', '0'), + +('19', '1', '3', '0', '0'), +('19', '1', '3', '1', '0'), +('19', '1', '3', '2', '0'), +('19', '1', '3', '3', '0'), + +('19', '1', '4', '0', '0'), +('19', '1', '4', '1', '0'), +('19', '1', '4', '2', '0'), +('19', '1', '4', '3', '0'), + +('19', '1', '5', '0', '0'), +('19', '1', '5', '1', '0'), +('19', '1', '5', '2', '0'), +('19', '1', '5', '3', '0'), + +('19', '1', '6', '0', '0'), +('19', '1', '6', '1', '0'), +('19', '1', '6', '2', '0'), +('19', '1', '6', '3', '0'), + +('19', '2', '0', '0', '0'), +('19', '2', '0', '1', '0'), +('19', '2', '0', '2', '0'), +('19', '2', '0', '3', '0'), + +('19', '2', '1', '0', '0'), +('19', '2', '1', '1', '0'), +('19', '2', '1', '2', '0'), +('19', '2', '1', '3', '0'), + +('19', '2', '2', '0', '0'), +('19', '2', '2', '1', '0'), +('19', '2', '2', '2', '0'), +('19', '2', '2', '3', '0'), + +('19', '2', '3', '0', '0'), +('19', '2', '3', '1', '0'), +('19', '2', '3', '2', '0'), +('19', '2', '3', '3', '0'), + +('19', '2', '4', '0', '0'), +('19', '2', '4', '1', '0'), +('19', '2', '4', '2', '0'), +('19', '2', '4', '3', '0'), + +('19', '2', '5', '0', '0'), +('19', '2', '5', '1', '0'), +('19', '2', '5', '2', '0'), +('19', '2', '5', '3', '0'), + +('19', '2', '6', '0', '0'), +('19', '2', '6', '1', '0'), +('19', '2', '6', '2', '0'), +('19', '2', '6', '3', '0'), + +('19', '3', '0', '0', '0'), +('19', '3', '0', '1', '0'), +('19', '3', '0', '2', '0'), +('19', '3', '0', '3', '0'), + +('19', '3', '1', '0', '0'), +('19', '3', '1', '1', '0'), +('19', '3', '1', '2', '0'), +('19', '3', '1', '3', '0'), + +('19', '3', '2', '0', '0'), +('19', '3', '2', '1', '0'), +('19', '3', '2', '2', '0'), +('19', '3', '2', '3', '0'), + +('19', '3', '3', '0', '0'), +('19', '3', '3', '1', '0'), +('19', '3', '3', '2', '0'), +('19', '3', '3', '3', '0'), + +('19', '3', '4', '0', '0'), +('19', '3', '4', '1', '0'), +('19', '3', '4', '2', '0'), +('19', '3', '4', '3', '0'), + +('19', '3', '5', '0', '0'), +('19', '3', '5', '1', '0'), +('19', '3', '5', '2', '0'), +('19', '3', '5', '3', '0'), + +('19', '3', '6', '0', '0'), +('19', '3', '6', '1', '0'), +('19', '3', '6', '2', '0'), +('19', '3', '6', '3', '0'), + +('19', '4', '0', '0', '0'), +('19', '4', '0', '1', '0'), +('19', '4', '0', '2', '0'), +('19', '4', '0', '3', '0'), + +('19', '4', '1', '0', '0'), +('19', '4', '1', '1', '0'), +('19', '4', '1', '2', '0'), +('19', '4', '1', '3', '0'), + +('19', '4', '2', '0', '0'), +('19', '4', '2', '1', '0'), +('19', '4', '2', '2', '0'), +('19', '4', '2', '3', '0'), + +('19', '4', '3', '0', '0'), +('19', '4', '3', '1', '0'), +('19', '4', '3', '2', '0'), +('19', '4', '3', '3', '0'), + +('19', '4', '4', '0', '0'), +('19', '4', '4', '1', '0'), +('19', '4', '4', '2', '0'), +('19', '4', '4', '3', '0'), + +('19', '4', '5', '0', '0'), +('19', '4', '5', '1', '0'), +('19', '4', '5', '2', '0'), +('19', '4', '5', '3', '0'), + +('19', '4', '6', '0', '0'), +('19', '4', '6', '1', '0'), +('19', '4', '6', '2', '0'), +('19', '4', '6', '3', '0'), + +('19', '5', '0', '0', '0'), +('19', '5', '0', '1', '0'), +('19', '5', '0', '2', '0'), +('19', '5', '0', '3', '0'), + +('19', '5', '1', '0', '0'), +('19', '5', '1', '1', '0'), +('19', '5', '1', '2', '0'), +('19', '5', '1', '3', '0'), + +('19', '5', '2', '0', '0'), +('19', '5', '2', '1', '0'), +('19', '5', '2', '2', '0'), +('19', '5', '2', '3', '0'), + +('19', '5', '3', '0', '0'), +('19', '5', '3', '1', '0'), +('19', '5', '3', '2', '0'), +('19', '5', '3', '3', '0'), + +('19', '5', '4', '0', '0'), +('19', '5', '4', '1', '0'), +('19', '5', '4', '2', '0'), +('19', '5', '4', '3', '0'), + +('19', '5', '5', '0', '0'), +('19', '5', '5', '1', '0'), +('19', '5', '5', '2', '0'), +('19', '5', '5', '3', '0'), + +('19', '5', '6', '0', '0'), +('19', '5', '6', '1', '0'), +('19', '5', '6', '2', '0'), +('19', '5', '6', '3', '0'), + +('19', '6', '0', '0', '0'), +('19', '6', '0', '1', '0'), +('19', '6', '0', '2', '0'), +('19', '6', '0', '3', '0'), + +('19', '6', '1', '0', '0'), +('19', '6', '1', '1', '0'), +('19', '6', '1', '2', '0'), +('19', '6', '1', '3', '0'), + +('19', '6', '2', '0', '0'), +('19', '6', '2', '1', '0'), +('19', '6', '2', '2', '0'), +('19', '6', '2', '3', '0'), + +('19', '6', '3', '0', '0'), +('19', '6', '3', '1', '0'), +('19', '6', '3', '2', '0'), +('19', '6', '3', '3', '0'), + +('19', '6', '4', '0', '0'), +('19', '6', '4', '1', '0'), +('19', '6', '4', '2', '0'), +('19', '6', '4', '3', '0'), + +('19', '6', '5', '0', '0'), +('19', '6', '5', '1', '0'), +('19', '6', '5', '2', '0'), +('19', '6', '5', '3', '0'), + +('19', '6', '6', '0', '0'), +('19', '6', '6', '1', '0'), +('19', '6', '6', '2', '0'), +('19', '6', '6', '3', '0'), + +('19', '7', '0', '0', '0'), +('19', '7', '0', '1', '0'), +('19', '7', '0', '2', '0'), +('19', '7', '0', '3', '0'), + +('19', '7', '1', '0', '75'), +('19', '7', '1', '1', '75'), +('19', '7', '1', '2', '75'), +('19', '7', '1', '3', '75'), + +('19', '7', '2', '0', '50'), +('19', '7', '2', '1', '50'), +('19', '7', '2', '2', '50'), +('19', '7', '2', '3', '50'), + +('19', '7', '3', '0', '75'), +('19', '7', '3', '1', '75'), +('19', '7', '3', '2', '75'), +('19', '7', '3', '3', '75'), + +('19', '7', '4', '0', '100'), +('19', '7', '4', '1', '100'), +('19', '7', '4', '2', '100'), +('19', '7', '4', '3', '100'), + +('19', '7', '5', '0', '100'), +('19', '7', '5', '1', '100'), +('19', '7', '5', '2', '100'), +('19', '7', '5', '3', '100'), + +('19', '7', '6', '0', '100'), +('19', '7', '6', '1', '100'), +('19', '7', '6', '2', '100'), +('19', '7', '6', '3', '100'), + +('19', '8', '0', '0', '0'), +('19', '8', '0', '1', '0'), +('19', '8', '0', '2', '0'), +('19', '8', '0', '3', '0'), + +('19', '8', '1', '0', '0'), +('19', '8', '1', '1', '0'), +('19', '8', '1', '2', '0'), +('19', '8', '1', '3', '0'), + +('19', '8', '2', '0', '0'), +('19', '8', '2', '1', '0'), +('19', '8', '2', '2', '0'), +('19', '8', '2', '3', '0'), + +('19', '8', '3', '0', '0'), +('19', '8', '3', '1', '0'), +('19', '8', '3', '2', '0'), +('19', '8', '3', '3', '0'), + +('19', '8', '4', '0', '0'), +('19', '8', '4', '1', '0'), +('19', '8', '4', '2', '0'), +('19', '8', '4', '3', '0'), + +('19', '8', '5', '0', '0'), +('19', '8', '5', '1', '0'), +('19', '8', '5', '2', '0'), +('19', '8', '5', '3', '0'), + +('19', '8', '6', '0', '0'), +('19', '8', '6', '1', '0'), +('19', '8', '6', '2', '0'), +('19', '8', '6', '3', '0'), + +('19', '9', '0', '0', '0'), +('19', '9', '0', '1', '0'), +('19', '9', '0', '2', '0'), +('19', '9', '0', '3', '0'), + +('19', '9', '1', '0', '0'), +('19', '9', '1', '1', '0'), +('19', '9', '1', '2', '0'), +('19', '9', '1', '3', '0'), + +('19', '9', '2', '0', '0'), +('19', '9', '2', '1', '0'), +('19', '9', '2', '2', '0'), +('19', '9', '2', '3', '0'), + +('19', '9', '3', '0', '0'), +('19', '9', '3', '1', '0'), +('19', '9', '3', '2', '0'), +('19', '9', '3', '3', '0'), + +('19', '9', '4', '0', '0'), +('19', '9', '4', '1', '0'), +('19', '9', '4', '2', '0'), +('19', '9', '4', '3', '0'), + +('19', '9', '5', '0', '0'), +('19', '9', '5', '1', '0'), +('19', '9', '5', '2', '0'), +('19', '9', '5', '3', '0'), + +('19', '9', '6', '0', '0'), +('19', '9', '6', '1', '0'), +('19', '9', '6', '2', '0'), +('19', '9', '6', '3', '0'), + +('19', '10', '0', '0', '0'), +('19', '10', '0', '1', '0'), +('19', '10', '0', '2', '0'), +('19', '10', '0', '3', '0'), + +('19', '10', '1', '0', '0'), +('19', '10', '1', '1', '0'), +('19', '10', '1', '2', '0'), +('19', '10', '1', '3', '0'), + +('19', '10', '2', '0', '0'), +('19', '10', '2', '1', '0'), +('19', '10', '2', '2', '0'), +('19', '10', '2', '3', '0'), + +('19', '10', '3', '0', '0'), +('19', '10', '3', '1', '0'), +('19', '10', '3', '2', '0'), +('19', '10', '3', '3', '0'), + +('19', '10', '4', '0', '0'), +('19', '10', '4', '1', '0'), +('19', '10', '4', '2', '0'), +('19', '10', '4', '3', '0'), + +('19', '10', '5', '0', '0'), +('19', '10', '5', '1', '0'), +('19', '10', '5', '2', '0'), +('19', '10', '5', '3', '0'), + +('19', '10', '6', '0', '0'), +('19', '10', '6', '1', '0'), +('19', '10', '6', '2', '0'), +('19', '10', '6', '3', '0'), + +('19', '11', '0', '0', '0'), +('19', '11', '0', '1', '0'), +('19', '11', '0', '2', '0'), +('19', '11', '0', '3', '0'), + +('19', '11', '1', '0', '0'), +('19', '11', '1', '1', '0'), +('19', '11', '1', '2', '0'), +('19', '11', '1', '3', '0'), + +('19', '11', '2', '0', '0'), +('19', '11', '2', '1', '0'), +('19', '11', '2', '2', '0'), +('19', '11', '2', '3', '0'), + +('19', '11', '3', '0', '0'), +('19', '11', '3', '1', '0'), +('19', '11', '3', '2', '0'), +('19', '11', '3', '3', '0'), + +('19', '11', '4', '0', '0'), +('19', '11', '4', '1', '0'), +('19', '11', '4', '2', '0'), +('19', '11', '4', '3', '0'), + +('19', '11', '5', '0', '0'), +('19', '11', '5', '1', '0'), +('19', '11', '5', '2', '0'), +('19', '11', '5', '3', '0'), + +('19', '11', '6', '0', '0'), +('19', '11', '6', '1', '0'), +('19', '11', '6', '2', '0'), +('19', '11', '6', '3', '0'), + +('19', '12', '0', '0', '0'), +('19', '12', '0', '1', '0'), +('19', '12', '0', '2', '0'), +('19', '12', '0', '3', '0'), + +('19', '12', '1', '0', '0'), +('19', '12', '1', '1', '0'), +('19', '12', '1', '2', '0'), +('19', '12', '1', '3', '0'), + +('19', '12', '2', '0', '0'), +('19', '12', '2', '1', '0'), +('19', '12', '2', '2', '0'), +('19', '12', '2', '3', '0'), + +('19', '12', '3', '0', '0'), +('19', '12', '3', '1', '0'), +('19', '12', '3', '2', '0'), +('19', '12', '3', '3', '0'), + +('19', '12', '4', '0', '0'), +('19', '12', '4', '1', '0'), +('19', '12', '4', '2', '0'), +('19', '12', '4', '3', '0'), + +('19', '12', '5', '0', '0'), +('19', '12', '5', '1', '0'), +('19', '12', '5', '2', '0'), +('19', '12', '5', '3', '0'), + +('19', '12', '6', '0', '0'), +('19', '12', '6', '1', '0'), +('19', '12', '6', '2', '0'), +('19', '12', '6', '3', '0'), + +('19', '13', '0', '0', '0'), +('19', '13', '0', '1', '0'), +('19', '13', '0', '2', '0'), +('19', '13', '0', '3', '0'), + +('19', '13', '1', '0', '0'), +('19', '13', '1', '1', '0'), +('19', '13', '1', '2', '0'), +('19', '13', '1', '3', '0'), + +('19', '13', '2', '0', '0'), +('19', '13', '2', '1', '0'), +('19', '13', '2', '2', '0'), +('19', '13', '2', '3', '0'), + +('19', '13', '3', '0', '0'), +('19', '13', '3', '1', '0'), +('19', '13', '3', '2', '0'), +('19', '13', '3', '3', '0'), + +('19', '13', '4', '0', '0'), +('19', '13', '4', '1', '0'), +('19', '13', '4', '2', '0'), +('19', '13', '4', '3', '0'), + +('19', '13', '5', '0', '0'), +('19', '13', '5', '1', '0'), +('19', '13', '5', '2', '0'), +('19', '13', '5', '3', '0'), + +('19', '13', '6', '0', '0'), +('19', '13', '6', '1', '0'), +('19', '13', '6', '2', '0'), +('19', '13', '6', '3', '0'), + +('19', '14', '0', '0', '0'), +('19', '14', '0', '1', '0'), +('19', '14', '0', '2', '0'), +('19', '14', '0', '3', '0'), + +('19', '14', '1', '0', '0'), +('19', '14', '1', '1', '0'), +('19', '14', '1', '2', '0'), +('19', '14', '1', '3', '0'), + +('19', '14', '2', '0', '0'), +('19', '14', '2', '1', '0'), +('19', '14', '2', '2', '0'), +('19', '14', '2', '3', '0'), + +('19', '14', '3', '0', '0'), +('19', '14', '3', '1', '0'), +('19', '14', '3', '2', '0'), +('19', '14', '3', '3', '0'), + +('19', '14', '4', '0', '0'), +('19', '14', '4', '1', '0'), +('19', '14', '4', '2', '0'), +('19', '14', '4', '3', '0'), + +('19', '14', '5', '0', '0'), +('19', '14', '5', '1', '0'), +('19', '14', '5', '2', '0'), +('19', '14', '5', '3', '0'), + +('19', '14', '6', '0', '0'), +('19', '14', '6', '1', '0'), +('19', '14', '6', '2', '0'), +('19', '14', '6', '3', '0'), + +('19', '15', '0', '0', '0'), +('19', '15', '0', '1', '0'), +('19', '15', '0', '2', '0'), +('19', '15', '0', '3', '0'), + +('19', '15', '1', '0', '0'), +('19', '15', '1', '1', '0'), +('19', '15', '1', '2', '0'), +('19', '15', '1', '3', '0'), + +('19', '15', '2', '0', '0'), +('19', '15', '2', '1', '0'), +('19', '15', '2', '2', '0'), +('19', '15', '2', '3', '0'), + +('19', '15', '3', '0', '0'), +('19', '15', '3', '1', '0'), +('19', '15', '3', '2', '0'), +('19', '15', '3', '3', '0'), + +('19', '15', '4', '0', '0'), +('19', '15', '4', '1', '0'), +('19', '15', '4', '2', '0'), +('19', '15', '4', '3', '0'), + +('19', '15', '5', '0', '0'), +('19', '15', '5', '1', '0'), +('19', '15', '5', '2', '0'), +('19', '15', '5', '3', '0'), + +('19', '15', '6', '0', '0'), +('19', '15', '6', '1', '0'), +('19', '15', '6', '2', '0'), +('19', '15', '6', '3', '0'); diff --git a/zone/bot.h b/zone/bot.h index 97bf9fc1f..17855ad38 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -132,6 +132,9 @@ enum SpellTypeIndex { MaxSpellTypes }; +enum BotCastingChanceConditional : uint8 { nHS = 0, pH, pS, pHS, cntHS }; // negative Healer/Slower, positive Healer, postive Slower, positive Healer/Slower + + class Bot : public NPC { friend class Mob; public: diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 0f7553ada..cd2d33b3a 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -82,6 +82,50 @@ bool BotDatabase::LoadBotCommandSettings(std::map= MaxSpellTypes) + continue; + uint8 class_index = atoi(row[1]); + if (class_index >= PLAYER_CLASS_COUNT) + continue; + uint8 stance_index = atoi(row[2]); + if (stance_index >= MaxStances) + continue; + uint8 conditional_index = atoi(row[3]); + if (conditional_index >= cntHS) + continue; + uint8 value = atoi(row[4]); + if (value > 100) + value = 100; + spell_casting_chances[spell_type_index][class_index][stance_index][conditional_index] = value; + } + + return true; +} + /* Bot functions */ bool BotDatabase::QueryNameAvailablity(const std::string& bot_name, bool& available_flag) @@ -2711,6 +2755,19 @@ bool BotDatabase::DeleteAllHealRotations(const uint32 owner_id) /* Bot miscellaneous functions */ +uint8 BotDatabase::GetSpellCastingChance(uint8 spell_type_index, uint8 class_index, uint8 stance_index, uint8 conditional_index) +{ + if (spell_type_index >= MaxSpellTypes) + return 0; + if (class_index >= PLAYER_CLASS_COUNT) + return 0; + if (stance_index >= MaxStances) + return 0; + if (conditional_index >= cntHS) + return 0; + + return spell_casting_chances[spell_type_index][class_index][stance_index][conditional_index]; +} /* fail::Bot functions */ diff --git a/zone/bot_database.h b/zone/bot_database.h index b7245306f..a4986b6c2 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -50,6 +50,7 @@ public: bool Connect(const char* host, const char* user, const char* passwd, const char* database, uint32 port); bool LoadBotCommandSettings(std::map>> &bot_command_settings); + bool LoadBotSpellCastingChances(); /* Bot functions */ @@ -183,6 +184,7 @@ public: bool DeleteAllHealRotations(const uint32 owner_id); /* Bot miscellaneous functions */ + uint8 GetSpellCastingChance(uint8 spell_type_index, uint8 class_index, uint8 stance_index, uint8 conditional_index); class fail { diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index f3b4ec83a..783b735b7 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -2510,2951 +2510,6 @@ bool Bot::CheckDisciplineRecastTimers(Bot *caster, int timer_index) { uint8 Bot::GetChanceToCastBySpellType(uint32 spellType) { - enum : uint8 { nHS = 0, pH, pS, pHS, cntHS}; // negative Healer/Slower, positive Healer, postive Slower, positive Healer/Slower - - static const uint8 spell_casting_chances[MaxSpellTypes][PLAYER_CLASS_COUNT][MaxStances][cntHS] = { -// SpellType_NukeIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 15, 25, 15 }, // Balanced { nHS, pH, pS, pHS } - { 15, 0, 15, 0 }, // Efficient { nHS, pH, pS, pHS } - { 25, 15, 25, 15 }, // Reactive { nHS, pH, pS, pHS } - { 50, 15, 50, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 25, 50, 25 }, // Burn { nHS, pH, pS, pHS } - { 50, 25, 50, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 15, 25, 15 }, // Balanced { nHS, pH, pS, pHS } - { 15, 0, 15, 0 }, // Efficient { nHS, pH, pS, pHS } - { 25, 15, 25, 15 }, // Reactive { nHS, pH, pS, pHS } - { 50, 15, 50, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 25, 50, 25 }, // Burn { nHS, pH, pS, pHS } - { 50, 25, 50, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } - { 5, 5, 5, 5 }, // Efficient { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Burn { nHS, pH, pS, pHS } - { 50, 50, 50, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } - { 5, 5, 5, 5 }, // Efficient { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Burn { nHS, pH, pS, pHS } - { 50, 50, 50, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 15, 25, 15 }, // Balanced { nHS, pH, pS, pHS } - { 15, 0, 15, 0 }, // Efficient { nHS, pH, pS, pHS } - { 25, 15, 25, 15 }, // Reactive { nHS, pH, pS, pHS } - { 50, 15, 50, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 25, 50, 25 }, // Burn { nHS, pH, pS, pHS } - { 50, 25, 50, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } - { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 10, 5, 0 }, // Balanced { nHS, pH, pS, pHS } - { 10, 5, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 15, 10, 5, 0 }, // Reactive { nHS, pH, pS, pHS } - { 25, 15, 15, 5 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 25, 25, 15 }, // Burn { nHS, pH, pS, pHS } - { 50, 25, 25, 15 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } - { 5, 5, 5, 5 }, // Efficient { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Burn { nHS, pH, pS, pHS } - { 50, 50, 50, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Reactive { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Aggressive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } - { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Reactive { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Aggressive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } - { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 15, 15 }, // Balanced { nHS, pH, pS, pHS } - { 15, 15, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 15, 15 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 50, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 50, 50, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 10, 5, 0 }, // Balanced { nHS, pH, pS, pHS } - { 10, 5, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 15, 10, 5, 0 }, // Reactive { nHS, pH, pS, pHS } - { 25, 15, 15, 5 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 25, 25, 15 }, // Burn { nHS, pH, pS, pHS } - { 50, 25, 25, 15 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_HealIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Efficient { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Burn { nHS, pH, pS, pHS } - { 50, 50, 50, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 100, 25, 100 }, // Balanced { nHS, pH, pS, pHS } - { 15, 75, 15, 75 }, // Efficient { nHS, pH, pS, pHS } - { 25, 100, 25, 100 }, // Reactive { nHS, pH, pS, pHS } - { 15, 75, 15, 75 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 50, 0, 50 }, // Burn { nHS, pH, pS, pHS } - { 0, 50, 0, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 100, 25, 100 }, // Balanced { nHS, pH, pS, pHS } - { 15, 75, 15, 75 }, // Efficient { nHS, pH, pS, pHS } - { 25, 100, 25, 100 }, // Reactive { nHS, pH, pS, pHS } - { 15, 75, 15, 75 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 50, 0, 50 }, // Burn { nHS, pH, pS, pHS } - { 0, 50, 0, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } - { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 100, 25, 100 }, // Balanced { nHS, pH, pS, pHS } - { 15, 100, 15, 100 }, // Efficient { nHS, pH, pS, pHS } - { 25, 100, 25, 100 }, // Reactive { nHS, pH, pS, pHS } - { 25, 75, 25, 75 }, // Aggressive { nHS, pH, pS, pHS } - { 10, 50, 10, 50 }, // Burn { nHS, pH, pS, pHS } - { 10, 50, 10, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 100, 25, 100 }, // Balanced { nHS, pH, pS, pHS } - { 15, 100, 15, 100 }, // Efficient { nHS, pH, pS, pHS } - { 25, 100, 25, 100 }, // Reactive { nHS, pH, pS, pHS } - { 25, 75, 25, 75 }, // Aggressive { nHS, pH, pS, pHS } - { 10, 50, 10, 50 }, // Burn { nHS, pH, pS, pHS } - { 10, 50, 10, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 100, 25, 100 }, // Balanced { nHS, pH, pS, pHS } - { 15, 75, 15, 75 }, // Efficient { nHS, pH, pS, pHS } - { 25, 100, 25, 100 }, // Reactive { nHS, pH, pS, pHS } - { 15, 75, 15, 75 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 50, 0, 50 }, // Burn { nHS, pH, pS, pHS } - { 0, 50, 0, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_RootIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_BuffIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_EscapeIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } - { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Efficient { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } - { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } - { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } - { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } - { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Efficient { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Burn { nHS, pH, pS, pHS } - { 15, 15, 15, 15 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Efficient { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_PetIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Burn { nHS, pH, pS, pHS } - { 10, 10, 10, 10 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Burn { nHS, pH, pS, pHS } - { 10, 10, 10, 10 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Burn { nHS, pH, pS, pHS } - { 10, 10, 10, 10 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Burn { nHS, pH, pS, pHS } - { 10, 10, 10, 10 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_LifetapIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } - { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } - { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_SnareIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_DOTIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 15, 10, 10 }, // Balanced { nHS, pH, pS, pHS } - { 10, 10, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 15, 15, 10, 10 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 50, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 50, 50, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 15, 10, 10 }, // Balanced { nHS, pH, pS, pHS } - { 10, 10, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 15, 15, 10, 10 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 50, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 50, 50, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 15, 50, 15 }, // Balanced { nHS, pH, pS, pHS } - { 25, 10, 25, 10 }, // Efficient { nHS, pH, pS, pHS } - { 50, 15, 50, 15 }, // Reactive { nHS, pH, pS, pHS } - { 50, 25, 50, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 25, 50, 25 }, // Burn { nHS, pH, pS, pHS } - { 50, 25, 50, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 25, 25, 15, 15 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 100, 100, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 100, 100, 50, 50 }, // Burn { nHS, pH, pS, pHS } - { 100, 100, 50, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 15, 15, 0 }, // Balanced { nHS, pH, pS, pHS } - { 15, 10, 10, 0 }, // Efficient { nHS, pH, pS, pHS } - { 25, 15, 15, 0 }, // Reactive { nHS, pH, pS, pHS } - { 50, 25, 50, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 25, 50, 15 }, // Burn { nHS, pH, pS, pHS } - { 50, 25, 50, 15 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Balanced { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Burn { nHS, pH, pS, pHS } - { 75, 75, 75, 75 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 15, 15 }, // Balanced { nHS, pH, pS, pHS } - { 25, 25, 10, 10 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 15, 15 }, // Reactive { nHS, pH, pS, pHS } - { 15, 15, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 15, 15, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 15, 15, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 15, 10, 10 }, // Balanced { nHS, pH, pS, pHS } - { 10, 10, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 15, 15, 10, 10 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 50, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 50, 50, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_DispelIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_InCombatBuffIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Aggressive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Burn { nHS, pH, pS, pHS } - { 25, 25, 25, 25 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Burn { nHS, pH, pS, pHS } - { 50, 50, 50, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 75, 50, 75 }, // Balanced { nHS, pH, pS, pHS } - { 25, 50, 25, 50 }, // Efficient { nHS, pH, pS, pHS } - { 50, 75, 50, 75 }, // Reactive { nHS, pH, pS, pHS } - { 75, 100, 75, 100 }, // Aggressive { nHS, pH, pS, pHS } - { 75, 100, 75, 100 }, // Burn { nHS, pH, pS, pHS } - { 75, 100, 75, 100 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_MezIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_CharmIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_SlowIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 15, 15, 100, 100 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 50, 50 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 50, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 25, 25, 100, 100 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 15, 15, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 15, 15, 50, 50 }, // Burn { nHS, pH, pS, pHS } - { 15, 15, 50, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 50, 50, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 25, 25, 100, 100 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 15, 15, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 15, 15, 50, 50 }, // Burn { nHS, pH, pS, pHS } - { 15, 15, 50, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 15, 15, 100, 100 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 50, 50 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 50, 50 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_DebuffIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Efficient { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Reactive { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Balanced { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Efficient { nHS, pH, pS, pHS } - { 25, 25, 25, 25 }, // Reactive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Balanced { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Efficient { nHS, pH, pS, pHS } - { 15, 15, 15, 15 }, // Reactive { nHS, pH, pS, pHS } - { 10, 10, 10, 10 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_CureIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Balanced { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Efficient { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Reactive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Aggressive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } - { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_ResurrectIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_HateReduxIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_InCombatBuffSongIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Balanced { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Efficient { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Reactive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Aggressive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } - { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - }, -// SpellType_OutOfCombatBuffSongIndex - { - {// WarriorIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ClericIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// PaladinIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RangerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShadowknightIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// DruidIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MonkIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Balanced { nHS, pH, pS, pHS } - { 50, 50, 50, 50 }, // Efficient { nHS, pH, pS, pHS } - { 75, 75, 75, 75 }, // Reactive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Aggressive { nHS, pH, pS, pHS } - { 100, 100, 100, 100 }, // Burn { nHS, pH, pS, pHS } - { 100, 100, 100, 100 } // BurnAE { nHS, pH, pS, pHS } - }, - {// RogueIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// ShamanIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// NecromancerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// WizardIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// MagicianIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// EnchanterIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BeastlordIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - }, - {// BerserkerIndex - { 0, 0, 0, 0 }, // Passive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Balanced { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Efficient { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Reactive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Aggressive { nHS, pH, pS, pHS } - { 0, 0, 0, 0 }, // Burn { nHS, pH, pS, pHS } - { 0, 0, 0, 0 } // BurnAE { nHS, pH, pS, pHS } - } - } - }; - uint8 spell_type_index = MaxSpellTypes; switch (spellType) { case SpellType_Nuke: @@ -5541,7 +2596,7 @@ uint8 Bot::GetChanceToCastBySpellType(uint32 spellType) type_index |= pS; } - return spell_casting_chances[spell_type_index][class_index][stance_index][type_index]; + return botdb.GetSpellCastingChance(spell_type_index, class_index, stance_index, type_index); } #endif diff --git a/zone/net.cpp b/zone/net.cpp index 2f67c85d3..935dace7d 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -369,6 +369,10 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::Error, "Bot command loading FAILED"); else Log.Out(Logs::General, Logs::Zone_Server, "%d bot commands loaded", botretval); + + Log.Out(Logs::General, Logs::Zone_Server, "Loading bot spell casting chances"); + if (!botdb.LoadBotSpellCastingChances()) + Log.Out(Logs::General, Logs::Error, "Bot spell casting chances loading FAILED"); #endif if(RuleB(TaskSystem, EnableTaskSystem)) { From 7621bf47c8a6cd6f92e9719c63086ff1672e96a3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 24 Feb 2017 01:12:46 -0500 Subject: [PATCH 577/693] Quick fix to resolve some serious group issues Group leader swapping didn't work and left the client in a bad state This just disbands the group if the leader leaves Also prevents a group leader from disbanding other groups ... Which also lead to bad states Group leader swapping not working is better than these issues :P --- zone/client_packet.cpp | 18 +++++++++++------- zone/groups.cpp | 10 ++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 1c5e4ebfd..5411dbf7a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6506,6 +6506,16 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) if (!group) //We must recheck this here.. incase the final bot disbanded the party..otherwise we crash return; #endif + Mob* memberToDisband = GetTarget(); + + if (!memberToDisband) + memberToDisband = entity_list.GetMob(gd->name2); + + if (memberToDisband) { + auto group2 = memberToDisband->GetGroup(); + if (group2 != group) // they're not in our group! + memberToDisband = this; + } if (group->GroupCount() < 3) { @@ -6527,7 +6537,7 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) GetMerc()->Suspend(); } } - else if (group->IsLeader(this) && GetTarget() == this) + else if (group->IsLeader(this) && (GetTarget() == this || memberToDisband == this)) { LeaveGroup(); if (GetMerc() && !GetMerc()->IsSuspended()) @@ -6537,12 +6547,6 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) } else { - Mob* memberToDisband = nullptr; - memberToDisband = GetTarget(); - - if (!memberToDisband) - memberToDisband = entity_list.GetMob(gd->name2); - if (memberToDisband) { if (group->IsLeader(this)) diff --git a/zone/groups.cpp b/zone/groups.cpp index 94a2b0032..e9b2ec93c 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -581,6 +581,16 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) return false; } + // TODO: fix this shit + // okay, so there is code below that tries to handle this. It does not. + // So instead of figuring it out now, lets just disband the group so the client doesn't + // sit there with a broken group and there isn't any group leader shuffling going on + // since the code below doesn't work. + if (oldmember == GetLeader()) { + DisbandGroup(); + return true; + } + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { if (members[i] == oldmember) From 3383f65ff7d47427c3da645bb353dd8d870bcfb2 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 24 Feb 2017 04:48:33 -0500 Subject: [PATCH 578/693] Updated bot casting roles to not refresh with every spell cast (oversight in recent casting chances commit) --- zone/bot.cpp | 159 ++++++++++++++++++++++++++++--------------- zone/bot.h | 16 ++++- zone/bot_structs.h | 5 ++ zone/botspellsai.cpp | 6 +- zone/groups.cpp | 20 ++++++ 5 files changed, 147 insertions(+), 59 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 5da128aa6..cb5f89ed2 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -176,6 +176,9 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to if (GetClass() == ROGUE) evade_timer.Start(); + m_CastingRoles.GroupHealer = false; + m_CastingRoles.GroupSlower = false; + GenerateBaseStats(); if (!botdb.LoadTimers(this) && bot_owner) @@ -6835,66 +6838,116 @@ bool Bot::IsBotCasterCombatRange(Mob *target) { return result; } -bool Bot::IsGroupPrimaryHealer() { - bool result = false; - uint8 botclass = GetClass(); - if(HasGroup()) { - Group *g = GetGroup(); - switch(botclass) { - case CLERIC: { - result = true; - break; - } - case DRUID: { - result = GroupHasClericClass(g) ? false : true; - break; - } - case SHAMAN: { - result = (GroupHasClericClass(g) || GroupHasDruidClass(g)) ? false : true; - break; - } - case PALADIN: - case RANGER: - case BEASTLORD: { - result = GroupHasPriestClass(g) ? false : true; - break; - } - default: { - result = false; - break; - } +void Bot::UpdateGroupCastingRoles(const Group* group, bool disband) +{ + if (!group) + return; + + for (auto iter : group->members) { + if (!iter) + continue; + + if (iter->IsBot()) { + iter->CastToBot()->SetGroupHealer(false); + iter->CastToBot()->SetGroupSlower(false); } } - return result; -} + if (disband) + return; -bool Bot::IsGroupPrimarySlower() { - bool result = false; - uint8 botclass = GetClass(); - if(HasGroup()) { - Group *g = GetGroup(); - switch(botclass) { - case SHAMAN: { - result = true; - break; - } - case ENCHANTER: { - result = GroupHasShamanClass(g) ? false : true; - break; - } - case BEASTLORD: { - result = (GroupHasShamanClass(g) || GroupHasEnchanterClass(g)) ? false : true; - break; - } - default: { - result = false; - break; - } + Mob* healer = nullptr; + Mob* slower = nullptr; + + for (auto iter : group->members) { + if (!iter) + continue; + + switch (iter->GetClass()) { + case CLERIC: + if (!healer) + healer = iter; + else + switch (healer->GetClass()) { + case CLERIC: + break; + default: + healer = iter; + } + + break; + case DRUID: + if (!healer) + healer = iter; + else + switch (healer->GetClass()) { + case CLERIC: + case DRUID: + break; + default: + healer = iter; + } + break; + case SHAMAN: + if (!healer) + healer = iter; + else + switch (healer->GetClass()) { + case CLERIC: + case DRUID: + case SHAMAN: + break; + default: + healer = iter; + } + break; + case PALADIN: + case RANGER: + case BEASTLORD: + if (!healer) + healer = iter; + break; + default: + break; + } + + switch (iter->GetClass()) { + case SHAMAN: + if (!slower) + slower = iter; + else + switch (slower->GetClass()) { + case SHAMAN: + break; + default: + slower = iter; + } + break; + case ENCHANTER: + if (!slower) + slower = iter; + else + switch (slower->GetClass()) { + case SHAMAN: + case ENCHANTER: + break; + default: + slower = iter; + } + break; + case BEASTLORD: + if (!slower) + slower = iter; + break; + default: + break; } } - return result; + if (healer && healer->IsBot()) + healer->CastToBot()->SetGroupHealer(); + if (slower && slower->IsBot()) + slower->CastToBot()->SetGroupSlower(); } bool Bot::CanHeal() { diff --git a/zone/bot.h b/zone/bot.h index 17855ad38..dd22f1498 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -132,7 +132,8 @@ enum SpellTypeIndex { MaxSpellTypes }; -enum BotCastingChanceConditional : uint8 { nHS = 0, pH, pS, pHS, cntHS }; // negative Healer/Slower, positive Healer, postive Slower, positive Healer/Slower +// negative Healer/Slower, positive Healer, postive Slower, positive Healer/Slower +enum BotCastingChanceConditional : uint8 { nHS = 0, pH, pS, pHS, cntHS = 4 }; class Bot : public NPC { @@ -475,8 +476,11 @@ public: BotRoleType GetBotRole() { return _botRole; } BotStanceType GetBotStance() { return _botStance; } uint8 GetChanceToCastBySpellType(uint32 spellType); - bool IsGroupPrimaryHealer(); - bool IsGroupPrimarySlower(); + + bool IsGroupHealer() { return m_CastingRoles.GroupHealer; } + bool IsGroupSlower() { return m_CastingRoles.GroupSlower; } + static void UpdateGroupCastingRoles(const Group* group, bool disband = false); + bool IsBotCaster() { return IsCasterClass(GetClass()); } bool IsBotINTCaster() { return IsINTCasterClass(GetClass()); } bool IsBotWISCaster() { return IsWISCasterClass(GetClass()); } @@ -640,6 +644,10 @@ protected: virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); virtual float GetMaxMeleeRangeToTarget(Mob* target); + BotCastingRoles& GetCastingRoles() { return m_CastingRoles; } + void SetGroupHealer(bool flag = true) { m_CastingRoles.GroupHealer = flag; } + void SetGroupSlower(bool flag = true) { m_CastingRoles.GroupSlower = flag; } + private: // Class Members uint32 _botID; @@ -679,6 +687,8 @@ private: Timer evade_timer; + BotCastingRoles m_CastingRoles; + std::shared_ptr m_member_of_heal_rotation; std::map botAAs; diff --git a/zone/bot_structs.h b/zone/bot_structs.h index a774bad70..8200c9933 100644 --- a/zone/bot_structs.h +++ b/zone/bot_structs.h @@ -60,6 +60,11 @@ struct BotSpell_wPriority : public BotSpell { uint8 Priority; }; +struct BotCastingRoles { + bool GroupHealer; + bool GroupSlower; +}; + struct BotAA { uint32 aa_id; uint8 req_level; diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 783b735b7..51546eb2a 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -108,7 +108,7 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { bool isPrimaryHealer = false; if(HasGroup()) { - isPrimaryHealer = IsGroupPrimaryHealer(); + isPrimaryHealer = IsGroupHealer(); } if(hpr < 95 || (tar->IsClient() && (hpr < 95)) || (botClass == BARD)) { @@ -2590,9 +2590,9 @@ uint8 Bot::GetChanceToCastBySpellType(uint32 spellType) uint8 type_index = nHS; if (HasGroup()) { - if (IsGroupPrimaryHealer()) + if (IsGroupHealer()) type_index |= pH; - if (IsGroupPrimarySlower()) + if (IsGroupSlower()) type_index |= pS; } diff --git a/zone/groups.cpp b/zone/groups.cpp index 94a2b0032..6eff2cee6 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -347,6 +347,10 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte safe_delete(outapp); +#ifdef BOTS + Bot::UpdateGroupCastingRoles(this); +#endif + return true; } @@ -481,6 +485,10 @@ bool Group::UpdatePlayer(Mob* update){ if (update->IsClient() && !mentoree && mentoree_name.length() && !mentoree_name.compare(update->GetName())) mentoree = update->CastToClient(); +#ifdef BOTS + Bot::UpdateGroupCastingRoles(this); +#endif + return updateSuccess; } @@ -513,6 +521,10 @@ void Group::MemberZoned(Mob* removemob) { if (removemob->IsClient() && removemob == mentoree) mentoree = nullptr; + +#ifdef BOTS + Bot::UpdateGroupCastingRoles(this); +#endif } void Group::SendGroupJoinOOZ(Mob* NewMember) { @@ -721,6 +733,10 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) ClearAllNPCMarks(); } +#ifdef BOTS + Bot::UpdateGroupCastingRoles(this); +#endif + return true; } @@ -864,6 +880,10 @@ uint32 Group::GetTotalGroupDamage(Mob* other) { } void Group::DisbandGroup(bool joinraid) { +#ifdef BOTS + Bot::UpdateGroupCastingRoles(this, true); +#endif + auto outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupUpdate_Struct)); GroupUpdate_Struct* gu = (GroupUpdate_Struct*) outapp->pBuffer; From 171474f1d24a98bedb323c5e78536144aeb65185 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 24 Feb 2017 10:02:50 -0500 Subject: [PATCH 579/693] Fix for bot combat line-of-sight issue (let me know if this causes zone training again) --- zone/bot.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index cb5f89ed2..98d622742 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2217,7 +2217,7 @@ void Bot::AI_Process() { // Let's check if we have a los with our target. // If we don't, our hate_list is wiped. // Else, it was causing the bot to aggro behind wall etc... causing massive trains. - if(!CheckLosFN(GetTarget()) || GetTarget()->IsMezzed() || !IsAttackAllowed(GetTarget())) { + if(GetTarget()->IsMezzed() || !IsAttackAllowed(GetTarget())) { WipeHateList(); if(IsMoving()) { SetHeading(0); @@ -2228,6 +2228,16 @@ void Bot::AI_Process() { } return; } + else if (!CheckLosFN(GetTarget())) { + if (!IsRooted()) { + Mob* follow = entity_list.GetMob(GetFollowID()); + if (follow) + CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetRunspeed()); + return; + } + + return; + } if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) SendAddPlayerState(PlayerState::Aggressive); From 0968ce0d60fb22feb5257ed5c498576c9917055e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 24 Feb 2017 15:28:22 -0500 Subject: [PATCH 580/693] Add petnaming type 5 (`s ward) --- zone/pets.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zone/pets.cpp b/zone/pets.cpp index a50dcbed4..b9ccafe38 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -304,6 +304,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, // 2 - `s Warder // 3 - Random name if client, `s pet for others // 4 - Keep DB name + // 5 - `s ward if (petname != nullptr) { @@ -325,6 +326,10 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, // Keep the DB name } else if (record.petnaming == 3 && IsClient()) { strcpy(npc_type->name, GetRandPetName()); + } else if (record.petnaming == 5 && IsClient()) { + strcpy(npc_type->name, this->GetName()); + npc_type->name[24] = '\0'; + strcat(npc_type->name, "`s_ward"); } else { strcpy(npc_type->name, this->GetCleanName()); npc_type->name[25] = '\0'; From 31907382c86ff226cf4038b614a293a7fea3bb66 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 25 Feb 2017 02:21:48 -0500 Subject: [PATCH 581/693] Lets not aggro zonign clients --- zone/aggro.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 9533fbbff..cc537662a 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -253,7 +253,7 @@ bool Mob::CheckWillAggro(Mob *mob) { //sometimes if a client has some lag while zoning into a dangerous place while either invis or a GM //they will aggro mobs even though it's supposed to be impossible, to lets make sure we've finished connecting if (mob->IsClient()) { - if (!mob->CastToClient()->ClientFinishedLoading() || mob->CastToClient()->IsHoveringForRespawn()) + if (!mob->CastToClient()->ClientFinishedLoading() || mob->CastToClient()->IsHoveringForRespawn() || mob->CastToClient()->zoning) return false; } From 14a5ff399aa0adc07952aef8a80159c829a913a2 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 25 Feb 2017 02:37:57 -0500 Subject: [PATCH 582/693] clear xtarget manager on death --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index b7cd49384..dc50f23db 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1563,7 +1563,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk } } - entity_list.RemoveFromTargets(this); + entity_list.RemoveFromTargets(this, true); hate_list.RemoveEntFromHateList(this); RemoveAutoXTargets(); From 7a6d5d46f4cc4d4939afe5332a33be6c62191920 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 25 Feb 2017 03:48:02 -0500 Subject: [PATCH 583/693] Added node pathing to the bot movement dilemma... --- changelog.txt | 7 ++ common/ruletypes.h | 1 + .../2017_02_25_bots_use_pathing_rule.sql | 1 + zone/bot.cpp | 92 +++++++++++++------ zone/bot.h | 5 +- zone/bot_command.cpp | 6 +- zone/bot_database.cpp | 10 +- 7 files changed, 90 insertions(+), 32 deletions(-) create mode 100644 utils/sql/git/bots/optional/2017_02_25_bots_use_pathing_rule.sql diff --git a/changelog.txt b/changelog.txt index 53d48a83d..e42a60de8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 02/25/2017 == +Uleat: Implemented rule-based node pathing for bots + - This currently applies to out-of-combat following movement and blocked los in-combat movement + - The default is set to 'true' (use node pathing) + - If you want to disable node pathing, apply the optional sql '2017_02_25_bots_use_pathing_rule.sql' file located in the utils/sql/git/bots/optional sub-directory. This will apply a 'false' rule..but, it can be changed as desired + - This helps with bot movement..but, there are still issues... + == 02/23/2017 == Uleat: Moved bot spell casting chance values into database - this will allow admins to tailor their bots without having to rebuild server code - Each entry uses a 4-dimensional identifier: [spell type index][class index][stance index][conditional index] diff --git a/common/ruletypes.h b/common/ruletypes.h index 20430735a..b5c0b0b99 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -558,6 +558,7 @@ RULE_BOOL(Bots, PreferNoManaCommandSpells, true) // Give sorting priority to new RULE_BOOL(Bots, QuestableSpawnLimit, false) // Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl RULE_BOOL(Bots, QuestableSpells, false) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests. RULE_INT(Bots, SpawnLimit, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group pseudo-raid (bots are not raidable at this time) +RULE_BOOL(Bots, UsePathing, true) // Bots will use node pathing when moving RULE_BOOL(Bots, BotGroupXP, false) // Determines whether client gets xp for bots outside their group. RULE_BOOL(Bots, BotBardUseOutOfCombatSongs, true) // Determines whether bard bots use additional out of combat songs (optional script) RULE_BOOL(Bots, BotLevelsWithOwner, false) // Auto-updates spawned bots as owner levels/de-levels (false is original behavior) diff --git a/utils/sql/git/bots/optional/2017_02_25_bots_use_pathing_rule.sql b/utils/sql/git/bots/optional/2017_02_25_bots_use_pathing_rule.sql new file mode 100644 index 000000000..bf367d435 --- /dev/null +++ b/utils/sql/git/bots/optional/2017_02_25_bots_use_pathing_rule.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Bots:UsePathing', 'false', 'Bots will use node pathing when moving'); diff --git a/zone/bot.cpp b/zone/bot.cpp index 98d622742..2ae8f169c 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -77,7 +77,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm SetShowHelm(true); SetPauseAI(false); rest_timer.Disable(); - SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE); + SetFollowDistance(BOT_FOLLOW_DISTANCE_DEFAULT); // Do this once and only in this constructor GenerateAppearance(); GenerateBaseStats(); @@ -151,7 +151,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SetPauseAI(false); rest_timer.Disable(); - SetFollowDistance(BOT_DEFAULT_FOLLOW_DISTANCE); + SetFollowDistance(BOT_FOLLOW_DISTANCE_DEFAULT); strcpy(this->name, this->GetCleanName()); memset(&_botInspectMessage, 0, sizeof(InspectMessage_Struct)); @@ -2065,6 +2065,8 @@ float Bot::GetMaxMeleeRangeToTarget(Mob* target) { // AI Processing for the Bot object void Bot::AI_Process() { + // TODO: Need to add root checks to all movement code + if (!IsAIControlled()) return; if (GetPauseAI()) @@ -2229,13 +2231,23 @@ void Bot::AI_Process() { return; } else if (!CheckLosFN(GetTarget())) { - if (!IsRooted()) { + if (RuleB(Bots, UsePathing) && zone->pathing) { + bool WaypointChanged, NodeReached; + + glm::vec3 Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), + GetRunspeed(), WaypointChanged, NodeReached); + + if (WaypointChanged) + tar_ndx = 20; + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); + } + else { Mob* follow = entity_list.GetMob(GetFollowID()); if (follow) CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetRunspeed()); - return; } - + return; } @@ -2516,33 +2528,52 @@ void Bot::AI_Process() { } } else if(AI_movement_timer->Check()) { - // something is wrong with bot movement spell bonuses - based on logging.. - // ..this code won't need to be so complex once fixed... - int speed = GetRunspeed(); - if (cur_dist < GetFollowDistance() + 2000) { - speed = GetWalkspeed(); - } - else if (cur_dist >= GetFollowDistance() + 10000) { // 100 - if (cur_dist >= 22500) { // 150 - auto leader = follow; - while (leader->GetFollowID()) { - leader = entity_list.GetMob(leader->GetFollowID()); - if (!leader || leader == this) - break; - if (leader->GetRunspeed() > speed) - speed = leader->GetRunspeed(); - if (leader->IsClient()) - break; + // Something is still wrong with bot following... + // Shows up really bad over long distances when movement bonuses are involved + if (cur_dist > GetFollowDistance()) { + if (RuleB(Bots, UsePathing) && zone->pathing) { + if (cur_dist <= GetFollowDistance() + BOT_FOLLOW_DISTANCE_WALK) { + bool WaypointChanged, NodeReached; + + glm::vec3 Goal = UpdatePath(follow->GetX(), follow->GetY(), follow->GetZ(), + GetWalkspeed(), WaypointChanged, NodeReached); + + if (WaypointChanged) + tar_ndx = 20; + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetWalkspeed()); + } + else { + int speed = GetRunspeed(); + if (cur_dist > GetFollowDistance() + BOT_FOLLOW_DISTANCE_CRITICAL) + speed = ((float)speed * 1.25f); // sprint mod (1/4 boost) + + bool WaypointChanged, NodeReached; + + glm::vec3 Goal = UpdatePath(follow->GetX(), follow->GetY(), follow->GetZ(), + speed, WaypointChanged, NodeReached); + + if (WaypointChanged) + tar_ndx = 20; + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed); } } - speed = (float)speed * (1.0f + ((float)speed * 0.03125f)); // 1/32 - special bot sprint mod - } + else { + if (cur_dist <= GetFollowDistance() + BOT_FOLLOW_DISTANCE_WALK) { + CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetWalkspeed()); + } + else { + int speed = GetRunspeed(); + if (cur_dist > GetFollowDistance() + BOT_FOLLOW_DISTANCE_CRITICAL) + speed = ((float)speed * 1.25f); // sprint mod (1/4 boost) - if (cur_dist > GetFollowDistance()) { - CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); + CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); + } + } + if (rest_timer.Enabled()) rest_timer.Disable(); - return; } else { if (moved) { @@ -2550,9 +2581,14 @@ void Bot::AI_Process() { SetCurrentSpeed(0); } } + + if (GetClass() == BARD && GetBotStance() != BotStancePassive && !spellend_timer.Enabled() && AI_think_timer->Check()) + AI_IdleCastCheck(); + + return; } else if (IsMoving()) { - if (GetBotStance() != BotStancePassive && GetClass() == BARD && !spellend_timer.Enabled() && AI_think_timer->Check()) { + if (GetClass() == BARD && GetBotStance() != BotStancePassive && !spellend_timer.Enabled() && AI_think_timer->Check()) { AI_IdleCastCheck(); } } diff --git a/zone/bot.h b/zone/bot.h index dd22f1498..095ef6720 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -38,7 +38,10 @@ #include -#define BOT_DEFAULT_FOLLOW_DISTANCE 184 +#define BOT_FOLLOW_DISTANCE_DEFAULT 184 // as DSq value (~13.565 units) +#define BOT_FOLLOW_DISTANCE_DEFAULT_MAX 2500 // as DSq value (50 units) +#define BOT_FOLLOW_DISTANCE_WALK 625 // as DSq value (25 units) +#define BOT_FOLLOW_DISTANCE_CRITICAL 22500 // as DSq value (150 units) extern WorldServer worldserver; diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index ef995ce69..5e15b0f08 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -4550,7 +4550,7 @@ void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep) } const int ab_mask = ActionableBots::ABM_NoFilter; - uint32 bfd = BOT_DEFAULT_FOLLOW_DISTANCE; + uint32 bfd = BOT_FOLLOW_DISTANCE_DEFAULT; bool set_flag = false; int ab_arg = 2; @@ -4561,6 +4561,10 @@ void bot_subcommand_bot_follow_distance(Client *c, const Seperator *sep) } bfd = atoi(sep->arg[2]); + if (bfd < 1) + bfd = 1; + if (bfd > BOT_FOLLOW_DISTANCE_DEFAULT_MAX) + bfd = BOT_FOLLOW_DISTANCE_DEFAULT_MAX; set_flag = true; ab_arg = 3; } diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index cd2d33b3a..3ccc9726e 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -378,7 +378,13 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot) loaded_bot = new Bot(bot_id, atoi(row[0]), atoi(row[1]), atof(row[14]), atoi(row[6]), tempNPCStruct); if (loaded_bot) { loaded_bot->SetShowHelm((atoi(row[43]) > 0 ? true : false)); - loaded_bot->SetFollowDistance(atoi(row[44])); + uint32 bfd = atoi(row[44]); + if (bfd < 1) + bfd = 1; + if (bfd > BOT_FOLLOW_DISTANCE_DEFAULT_MAX) + bfd = BOT_FOLLOW_DISTANCE_DEFAULT_MAX; + loaded_bot->SetFollowDistance(bfd); + } return true; @@ -515,7 +521,7 @@ bool BotDatabase::SaveNewBot(Bot* bot_inst, uint32& bot_id) bot_inst->GetPR(), bot_inst->GetDR(), bot_inst->GetCorrup(), - BOT_DEFAULT_FOLLOW_DISTANCE + BOT_FOLLOW_DISTANCE_DEFAULT ); auto results = QueryDatabase(query); if (!results.Success()) From c61c27522165af2b1b4e0f42b5900589a73950de Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 25 Feb 2017 09:02:20 -0500 Subject: [PATCH 584/693] Added position update packet in out-of-combat movement code when movement occurs (rule-based; default: false) - appears to help with rubber-banding effect --- changelog.txt | 7 +++++- common/ruletypes.h | 1 + ...5_bots_update_position_with_timer_rule.sql | 1 + zone/bot.cpp | 23 +++++++++++++------ zone/bot.h | 2 +- 5 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 utils/sql/git/bots/optional/2017_02_25_bots_update_position_with_timer_rule.sql diff --git a/changelog.txt b/changelog.txt index e42a60de8..45236d039 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,9 +3,14 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 02/25/2017 == Uleat: Implemented rule-based node pathing for bots - This currently applies to out-of-combat following movement and blocked los in-combat movement - - The default is set to 'true' (use node pathing) + - The default is set to 'true' (use node pathing)..so, consider disabling it if cpu use is too high - If you want to disable node pathing, apply the optional sql '2017_02_25_bots_use_pathing_rule.sql' file located in the utils/sql/git/bots/optional sub-directory. This will apply a 'false' rule..but, it can be changed as desired - This helps with bot movement..but, there are still issues... +Uleat: Implemented rule-based position update packet with movement timer check for bots + - This currently only applies to out-of-combat movement + - The default is set to 'false' (original behavior) to help save bandwidth (each bot will send an update packet every 1/10th of a second when enabled) + - If you want to enable the position update packet, apply the optional sql '2017_02_25_bots_update_position_with_timer_rule.sql' file located in the utils/sql/git/bots/optional sub-directory. This will apply a 'true' rule..but, it can be changed as desired + - This appears to help with/eliminate rubber banding == 02/23/2017 == Uleat: Moved bot spell casting chance values into database - this will allow admins to tailor their bots without having to rebuild server code diff --git a/common/ruletypes.h b/common/ruletypes.h index b5c0b0b99..3599a718e 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -558,6 +558,7 @@ RULE_BOOL(Bots, PreferNoManaCommandSpells, true) // Give sorting priority to new RULE_BOOL(Bots, QuestableSpawnLimit, false) // Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl RULE_BOOL(Bots, QuestableSpells, false) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests. RULE_INT(Bots, SpawnLimit, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group pseudo-raid (bots are not raidable at this time) +RULE_BOOL(Bots, UpdatePositionWithTimer, false) // Sends a position update with every positive movement timer check RULE_BOOL(Bots, UsePathing, true) // Bots will use node pathing when moving RULE_BOOL(Bots, BotGroupXP, false) // Determines whether client gets xp for bots outside their group. RULE_BOOL(Bots, BotBardUseOutOfCombatSongs, true) // Determines whether bard bots use additional out of combat songs (optional script) diff --git a/utils/sql/git/bots/optional/2017_02_25_bots_update_position_with_timer_rule.sql b/utils/sql/git/bots/optional/2017_02_25_bots_update_position_with_timer_rule.sql new file mode 100644 index 000000000..5a15cb6fd --- /dev/null +++ b/utils/sql/git/bots/optional/2017_02_25_bots_update_position_with_timer_rule.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Bots:UpdatePositionWithTimer', 'true', 'Sends a position update with every positive movement timer check'); diff --git a/zone/bot.cpp b/zone/bot.cpp index 2ae8f169c..d33864346 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2364,6 +2364,7 @@ void Bot::AI_Process() { } } + // TODO: Test RuleB(Bots, UpdatePositionWithTimer) if(IsMoving()) SendPosUpdate(); else @@ -2528,11 +2529,12 @@ void Bot::AI_Process() { } } else if(AI_movement_timer->Check()) { - // Something is still wrong with bot following... + // Something is still wrong with bot the follow code... // Shows up really bad over long distances when movement bonuses are involved + // The flip-side is that too much speed adversely affects node pathing... if (cur_dist > GetFollowDistance()) { if (RuleB(Bots, UsePathing) && zone->pathing) { - if (cur_dist <= GetFollowDistance() + BOT_FOLLOW_DISTANCE_WALK) { + if (cur_dist <= BOT_FOLLOW_DISTANCE_WALK) { bool WaypointChanged, NodeReached; glm::vec3 Goal = UpdatePath(follow->GetX(), follow->GetY(), follow->GetZ(), @@ -2545,8 +2547,8 @@ void Bot::AI_Process() { } else { int speed = GetRunspeed(); - if (cur_dist > GetFollowDistance() + BOT_FOLLOW_DISTANCE_CRITICAL) - speed = ((float)speed * 1.25f); // sprint mod (1/4 boost) + if (cur_dist > BOT_FOLLOW_DISTANCE_CRITICAL) + speed = ((float)speed * 1.333f); // sprint mod (1/3 boost) bool WaypointChanged, NodeReached; @@ -2560,13 +2562,13 @@ void Bot::AI_Process() { } } else { - if (cur_dist <= GetFollowDistance() + BOT_FOLLOW_DISTANCE_WALK) { + if (cur_dist <= BOT_FOLLOW_DISTANCE_WALK) { CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetWalkspeed()); } else { int speed = GetRunspeed(); - if (cur_dist > GetFollowDistance() + BOT_FOLLOW_DISTANCE_CRITICAL) - speed = ((float)speed * 1.25f); // sprint mod (1/4 boost) + if (cur_dist > BOT_FOLLOW_DISTANCE_CRITICAL) + speed = ((float)speed * 1.333f); // sprint mod (1/3 boost) CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); } @@ -2574,6 +2576,13 @@ void Bot::AI_Process() { if (rest_timer.Enabled()) rest_timer.Disable(); + + if (RuleB(Bots, UpdatePositionWithTimer)) { // this helps with rubber-banding effect + if (IsMoving()) + SendPosUpdate(); + //else + // SendPosition(); // enabled - no discernable difference..disabled - saves on no movement packets + } } else { if (moved) { diff --git a/zone/bot.h b/zone/bot.h index 095ef6720..9608d60f3 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -40,7 +40,7 @@ #define BOT_FOLLOW_DISTANCE_DEFAULT 184 // as DSq value (~13.565 units) #define BOT_FOLLOW_DISTANCE_DEFAULT_MAX 2500 // as DSq value (50 units) -#define BOT_FOLLOW_DISTANCE_WALK 625 // as DSq value (25 units) +#define BOT_FOLLOW_DISTANCE_WALK 400 // as DSq value (20 units) #define BOT_FOLLOW_DISTANCE_CRITICAL 22500 // as DSq value (150 units) extern WorldServer worldserver; From 3fd40e9449368033aef5787d405433fd2bcedd1e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 25 Feb 2017 14:36:17 -0500 Subject: [PATCH 585/693] Make ST_AreaNPCOnly skip faction check The motivation for this is there a bunch of auras that use this target type that all would require setting up faction for these NPCs so they would hate everything. Also allows Ward of Destruction to work. --- zone/effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 0cec65877..400bae1fa 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -795,7 +795,7 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ continue; if (dist_targ < min_range2) //make sure they are in range continue; - if (isnpc && curmob->IsNPC()) { //check npc->npc casting + if (isnpc && curmob->IsNPC() && spells[spell_id].targettype != ST_AreaNPCOnly) { //check npc->npc casting FACTION_VALUE f = curmob->GetReverseFactionCon(caster); if (bad) { //affect mobs that are on our hate list, or From 9ae585dd81a24b1562003dc839f6f100f337edfb Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 26 Feb 2017 05:47:10 -0500 Subject: [PATCH 586/693] Moved bot npc spells entries to the 3000 + class id range --- changelog.txt | 3 +++ common/version.h | 4 ++-- utils/sql/db_update_manifest.txt | 1 + .../sql/git/bots/bots_db_update_manifest.txt | 1 + ..._02_26_bots_npc_spells_update_for_bots.sql | 19 +++++++++++++++++++ .../2017_02_26_npc_spells_update_for_bots.sql | 19 +++++++++++++++++++ 6 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 utils/sql/git/bots/required/2017_02_26_bots_npc_spells_update_for_bots.sql create mode 100644 utils/sql/git/required/2017_02_26_npc_spells_update_for_bots.sql diff --git a/changelog.txt b/changelog.txt index 45236d039..2b01b0150 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 02/26/2017 == +Uleat: Moved bot `npc_spells` entries from '701-712' to 3000 + .. also, added melee types for future expansion + == 02/25/2017 == Uleat: Implemented rule-based node pathing for bots - This currently applies to out-of-combat following movement and blocked los in-combat movement diff --git a/common/version.h b/common/version.h index b2261505f..7c6ccfe7a 100644 --- a/common/version.h +++ b/common/version.h @@ -30,9 +30,9 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9105 +#define CURRENT_BINARY_DATABASE_VERSION 9106 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9011 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9012 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index c21f60f4b..c21d00951 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -359,6 +359,7 @@ 9103|2017_01_30_book_languages_fix.sql|SELECT `language` from `books` WHERE `language` IS NULL|not_empty| 9104|2017_02_09_npc_spells_entries_type_update.sql|SHOW COLUMNS IN `npc_spells_entries` LIKE `type`|contains|smallint(5) unsigned 9105|2017_02_15_bot_spells_entries.sql|SELECT `id` FROM `npc_spells_entries` WHERE `npc_spells_id` >= 701 AND `npc_spells_id` <= 712|not_empty| +9106|2017_02_26_npc_spells_update_for_bots.sql|SELECT * FROM `npc_spells` WHERE `id` = '701' AND `name` = 'Cleric Bot'|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 810d767cc..47b2aa6cd 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -10,6 +10,7 @@ 9009|2017_02_15_bots_bot_spells_entries.sql|SELECT `id` FROM `npc_spells_entries` WHERE `npc_spells_id` >= 701 AND `npc_spells_id` <= 712|not_empty| 9010|2017_02_20_bots_bard_spell_update.sql|SELECT * FROM `bot_spells_entries` WHERE `npc_spells_id` = 711 AND (`type` & 0xFFFF0000) = 0xFFFF0000|empty| 9011|2017_02_23_bots_spell_casting_chances.sql|SHOW TABLES LIKE 'bot_spell_casting_chances'|empty| +9012|2017_02_26_bots_npc_spells_update_for_bots.sql|SELECT * FROM `npc_spells` WHERE `id` = '701' AND `name` = 'Cleric Bot'|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2017_02_26_bots_npc_spells_update_for_bots.sql b/utils/sql/git/bots/required/2017_02_26_bots_npc_spells_update_for_bots.sql new file mode 100644 index 000000000..7632a7e1a --- /dev/null +++ b/utils/sql/git/bots/required/2017_02_26_bots_npc_spells_update_for_bots.sql @@ -0,0 +1,19 @@ +-- Re-ordered entries according to actual class values and added melee types (for future expansion) +DELETE FROM `npc_spells` WHERE `id` >= '701' AND `id` <= '712'; + +INSERT INTO `npc_spells` VALUES (3001, 'Warrior Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3002, 'Cleric Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3003, 'Paladin Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3004, 'Ranger Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3005, 'Shadowknight Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3006, 'Druid Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3007, 'Monk Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3008, 'Bard Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3009, 'Rogue Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3010, 'Shaman Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3011, 'Necromancer Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3012, 'Wizard Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3013, 'Magician Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3014, 'Enchanter Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3015, 'Beastlord Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3016, 'Berserker Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); diff --git a/utils/sql/git/required/2017_02_26_npc_spells_update_for_bots.sql b/utils/sql/git/required/2017_02_26_npc_spells_update_for_bots.sql new file mode 100644 index 000000000..7632a7e1a --- /dev/null +++ b/utils/sql/git/required/2017_02_26_npc_spells_update_for_bots.sql @@ -0,0 +1,19 @@ +-- Re-ordered entries according to actual class values and added melee types (for future expansion) +DELETE FROM `npc_spells` WHERE `id` >= '701' AND `id` <= '712'; + +INSERT INTO `npc_spells` VALUES (3001, 'Warrior Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3002, 'Cleric Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3003, 'Paladin Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3004, 'Ranger Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3005, 'Shadowknight Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3006, 'Druid Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3007, 'Monk Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3008, 'Bard Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3009, 'Rogue Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3010, 'Shaman Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3011, 'Necromancer Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3012, 'Wizard Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3013, 'Magician Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3014, 'Enchanter Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3015, 'Beastlord Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); +INSERT INTO `npc_spells` VALUES (3016, 'Berserker Bot', 0, -1, 3, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); From a49e3d64714fd5abd9777f62ec018759b59f7cd4 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 26 Feb 2017 06:26:59 -0500 Subject: [PATCH 587/693] Update for saved bot data to use new spells id values --- common/version.h | 2 +- .../sql/git/bots/bots_db_update_manifest.txt | 1 + ...6_bots_spells_id_update_for_saved_bots.sql | 17 +++ zone/bot.cpp | 102 ++++++++++-------- 4 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 utils/sql/git/bots/required/2017_02_26_bots_spells_id_update_for_saved_bots.sql diff --git a/common/version.h b/common/version.h index 7c6ccfe7a..8d82afc35 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9106 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9012 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9013 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index 47b2aa6cd..b0e334229 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -11,6 +11,7 @@ 9010|2017_02_20_bots_bard_spell_update.sql|SELECT * FROM `bot_spells_entries` WHERE `npc_spells_id` = 711 AND (`type` & 0xFFFF0000) = 0xFFFF0000|empty| 9011|2017_02_23_bots_spell_casting_chances.sql|SHOW TABLES LIKE 'bot_spell_casting_chances'|empty| 9012|2017_02_26_bots_npc_spells_update_for_bots.sql|SELECT * FROM `npc_spells` WHERE `id` = '701' AND `name` = 'Cleric Bot'|not_empty| +9013|2017_02_26_bots_spells_id_update_for_saved_bots.sql|SELECT * FROM `bot_data` WHERE `spells_id` >= '701' AND `spells_id` <= '712'|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2017_02_26_bots_spells_id_update_for_saved_bots.sql b/utils/sql/git/bots/required/2017_02_26_bots_spells_id_update_for_saved_bots.sql new file mode 100644 index 000000000..78ca8cb98 --- /dev/null +++ b/utils/sql/git/bots/required/2017_02_26_bots_spells_id_update_for_saved_bots.sql @@ -0,0 +1,17 @@ +-- Update spells_id to new values +UPDATE `bot_data` SET `spells_id` = '3001' WHERE `class` = '1'; +UPDATE `bot_data` SET `spells_id` = '3002' WHERE `class` = '2'; +UPDATE `bot_data` SET `spells_id` = '3003' WHERE `class` = '3'; +UPDATE `bot_data` SET `spells_id` = '3004' WHERE `class` = '4'; +UPDATE `bot_data` SET `spells_id` = '3005' WHERE `class` = '5'; +UPDATE `bot_data` SET `spells_id` = '3006' WHERE `class` = '6'; +UPDATE `bot_data` SET `spells_id` = '3007' WHERE `class` = '7'; +UPDATE `bot_data` SET `spells_id` = '3008' WHERE `class` = '8'; +UPDATE `bot_data` SET `spells_id` = '3009' WHERE `class` = '9'; +UPDATE `bot_data` SET `spells_id` = '3010' WHERE `class` = '10'; +UPDATE `bot_data` SET `spells_id` = '3011' WHERE `class` = '11'; +UPDATE `bot_data` SET `spells_id` = '3012' WHERE `class` = '12'; +UPDATE `bot_data` SET `spells_id` = '3013' WHERE `class` = '13'; +UPDATE `bot_data` SET `spells_id` = '3014' WHERE `class` = '14'; +UPDATE `bot_data` SET `spells_id` = '3015' WHERE `class` = '15'; +UPDATE `bot_data` SET `spells_id` = '3016' WHERE `class` = '16'; diff --git a/zone/bot.cpp b/zone/bot.cpp index d33864346..1156aec31 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -404,8 +404,10 @@ NPCType Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string b return Result; } -void Bot::GenerateBaseStats() { +void Bot::GenerateBaseStats() +{ int BotSpellID = 0; + // base stats uint32 Strength = _baseSTR; uint32 Stamina = _baseSTA; @@ -421,24 +423,26 @@ void Bot::GenerateBaseStats() { int32 PoisonResist = _basePR; int32 ColdResist = _baseCR; int32 CorruptionResist = _baseCorrup; + switch(this->GetClass()) { - case 1: // Warrior (why not just use 'case WARRIOR:'?) + case WARRIOR: + BotSpellID = 3001; Strength += 10; Stamina += 20; Agility += 10; Dexterity += 10; Attack += 12; break; - case 2: // Cleric - BotSpellID = 701; + case CLERIC: + BotSpellID = 3002; Strength += 5; Stamina += 5; Agility += 10; Wisdom += 30; Attack += 8; break; - case 3: // Paladin - BotSpellID = 708; + case PALADIN: + BotSpellID = 3003; Strength += 15; Stamina += 5; Wisdom += 15; @@ -446,84 +450,86 @@ void Bot::GenerateBaseStats() { Dexterity += 5; Attack += 17; break; - case 4: // Ranger - BotSpellID = 710; + case RANGER: + BotSpellID = 3004; Strength += 15; Stamina += 10; Agility += 10; Wisdom += 15; Attack += 17; break; - case 5: // Shadowknight - BotSpellID = 709; + case SHADOWKNIGHT: + BotSpellID = 3004; Strength += 10; Stamina += 15; Intelligence += 20; Charisma += 5; Attack += 17; break; - case 6: // Druid - BotSpellID = 707; + case DRUID: + BotSpellID = 3006; Stamina += 15; Wisdom += 35; Attack += 5; break; - case 7: // Monk + case MONK: + BotSpellID = 3007; Strength += 5; Stamina += 15; Agility += 15; Dexterity += 15; Attack += 17; break; - case 8: // Bard - BotSpellID = 711; + case BARD: + BotSpellID = 3008; Strength += 15; Dexterity += 10; Charisma += 15; Intelligence += 10; Attack += 17; break; - case 9: // Rogue + case ROGUE: + BotSpellID = 3009; Strength += 10; Stamina += 20; Agility += 10; Dexterity += 10; Attack += 12; break; - case 10: // Shaman - BotSpellID = 706; + case SHAMAN: + BotSpellID = 3010; Stamina += 10; Wisdom += 30; Charisma += 10; Attack += 28; break; - case 11: // Necromancer - BotSpellID = 703; + case NECROMANCER: + BotSpellID = 3011; Dexterity += 10; Agility += 10; Intelligence += 30; Attack += 5; break; - case 12: // Wizard - BotSpellID = 702; + case WIZARD: + BotSpellID = 3012; Stamina += 20; Intelligence += 30; Attack += 5; break; - case 13: // Magician - BotSpellID = 704; + case MAGICIAN: + BotSpellID = 3013; Stamina += 20; Intelligence += 30; Attack += 5; break; - case 14: // Enchanter - BotSpellID = 705; + case ENCHANTER: + BotSpellID = 3014; Intelligence += 25; Charisma += 25; Attack += 5; break; - case 15: // Beastlord - BotSpellID = 712; + case BEASTLORD: + BotSpellID = 3015; Stamina += 10; Agility += 10; Dexterity += 5; @@ -531,21 +537,24 @@ void Bot::GenerateBaseStats() { Charisma += 5; Attack += 31; break; - case 16: // Berserker + case BERSERKER: + BotSpellID = 3016; Strength += 10; Stamina += 15; Dexterity += 15; Agility += 10; Attack += 25; break; + default: + break; } float BotSize = GetSize(); switch(this->GetRace()) { - case 1: // Humans have no race bonus + case HUMAN: // Humans have no race bonus break; - case 2: // Barbarian + case BARBARIAN: Strength += 28; Stamina += 20; Agility += 7; @@ -556,7 +565,7 @@ void Bot::GenerateBaseStats() { BotSize = 7.0; ColdResist += 10; break; - case 3: // Erudite + case ERUDITE: Strength -= 15; Stamina -= 5; Agility -= 5; @@ -567,7 +576,7 @@ void Bot::GenerateBaseStats() { MagicResist += 5; DiseaseResist -= 5; break; - case 4: // Wood Elf + case WOOD_ELF: Strength -= 10; Stamina -= 10; Agility += 20; @@ -575,7 +584,7 @@ void Bot::GenerateBaseStats() { Wisdom += 5; BotSize = 5.0; break; - case 5: // High Elf + case HIGH_ELF: Strength -= 20; Stamina -= 10; Agility += 10; @@ -584,7 +593,7 @@ void Bot::GenerateBaseStats() { Intelligence += 12; Charisma += 5; break; - case 6: // Dark Elf + case DARK_ELF: Strength -= 15; Stamina -= 10; Agility += 15; @@ -593,7 +602,7 @@ void Bot::GenerateBaseStats() { Charisma -= 15; BotSize = 5.0; break; - case 7: // Half Elf + case HALF_ELF: Strength -= 5; Stamina -= 5; Agility += 15; @@ -601,7 +610,7 @@ void Bot::GenerateBaseStats() { Wisdom -= 15; BotSize = 5.5; break; - case 8: // Dwarf + case DWARF: Strength += 15; Stamina += 15; Agility -= 5; @@ -613,7 +622,7 @@ void Bot::GenerateBaseStats() { MagicResist -= 5; PoisonResist += 5; break; - case 9: // Troll + case TROLL: Strength += 33; Stamina += 34; Agility += 8; @@ -623,7 +632,7 @@ void Bot::GenerateBaseStats() { BotSize = 8.0; FireResist -= 20; break; - case 10: // Ogre + case OGRE: Strength += 55; Stamina += 77; Agility -= 5; @@ -633,7 +642,7 @@ void Bot::GenerateBaseStats() { Charisma -= 38; BotSize = 9.0; break; - case 11: // Halfling + case HALFLING: Strength -= 5; Agility += 20; Dexterity += 15; @@ -644,7 +653,7 @@ void Bot::GenerateBaseStats() { PoisonResist += 5; DiseaseResist += 5; break; - case 12: // Gnome + case GNOME: Strength -= 15; Stamina -= 5; Agility += 10; @@ -654,7 +663,7 @@ void Bot::GenerateBaseStats() { Charisma -= 15; BotSize = 3.0; break; - case 128: // Iksar + case IKSAR: Strength -= 5; Stamina -= 5; Agility += 15; @@ -664,7 +673,7 @@ void Bot::GenerateBaseStats() { MagicResist -= 5; FireResist -= 5; break; - case 130: // Vah Shir + case VAHSHIR: Strength += 15; Agility += 15; Dexterity -= 5; @@ -675,7 +684,7 @@ void Bot::GenerateBaseStats() { MagicResist -= 5; FireResist -= 5; break; - case 330: // Froglok + case FROGLOK: Strength -= 5; Stamina += 5; Agility += 25; @@ -685,7 +694,7 @@ void Bot::GenerateBaseStats() { MagicResist -= 5; FireResist -= 5; break; - case 522: // Drakkin + case DRAKKIN: Strength -= 5; Stamina += 5; Agility += 10; @@ -698,7 +707,10 @@ void Bot::GenerateBaseStats() { FireResist += 2; ColdResist += 2; break; + default: + break; } + this->STR = Strength; this->STA = Stamina; this->DEX = Dexterity; From ec9af74dc90d3fe6f28b69d897e0923bae860e40 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 26 Feb 2017 07:00:24 -0500 Subject: [PATCH 588/693] Update bot spells entries for new npc spells id values --- common/version.h | 2 +- utils/sql/git/bots/bots_db_update_manifest.txt | 1 + ...bots_spells_id_update_for_bot_spells_entries.sql | 13 +++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/bots/required/2017_02_26_bots_spells_id_update_for_bot_spells_entries.sql diff --git a/common/version.h b/common/version.h index 8d82afc35..f6ed08da5 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9106 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9013 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9014 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index b0e334229..d404568ef 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -12,6 +12,7 @@ 9011|2017_02_23_bots_spell_casting_chances.sql|SHOW TABLES LIKE 'bot_spell_casting_chances'|empty| 9012|2017_02_26_bots_npc_spells_update_for_bots.sql|SELECT * FROM `npc_spells` WHERE `id` = '701' AND `name` = 'Cleric Bot'|not_empty| 9013|2017_02_26_bots_spells_id_update_for_saved_bots.sql|SELECT * FROM `bot_data` WHERE `spells_id` >= '701' AND `spells_id` <= '712'|not_empty| +9014|2017_02_26_bots_spells_id_update_for_bot_spells_entries.sql|SELECT * FROM `bot_spells_entries` WHERE `npc_spells_id` >= '701' AND `npc_spells_id` <= '712'|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2017_02_26_bots_spells_id_update_for_bot_spells_entries.sql b/utils/sql/git/bots/required/2017_02_26_bots_spells_id_update_for_bot_spells_entries.sql new file mode 100644 index 000000000..d8b23b8e7 --- /dev/null +++ b/utils/sql/git/bots/required/2017_02_26_bots_spells_id_update_for_bot_spells_entries.sql @@ -0,0 +1,13 @@ +-- Update npc_spells_id to new values +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3002' WHERE `npc_spells_id` = '701'; +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3012' WHERE `npc_spells_id` = '702'; +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3011' WHERE `npc_spells_id` = '703'; +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3013' WHERE `npc_spells_id` = '704'; +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3014' WHERE `npc_spells_id` = '705'; +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3010' WHERE `npc_spells_id` = '706'; +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3006' WHERE `npc_spells_id` = '707'; +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3003' WHERE `npc_spells_id` = '708'; +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3005' WHERE `npc_spells_id` = '709'; +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3004' WHERE `npc_spells_id` = '710'; +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3008' WHERE `npc_spells_id` = '711'; +UPDATE `bot_spells_entries` SET `npc_spells_id` = '3015' WHERE `npc_spells_id` = '712'; From 303f056075da03e641cfc32faeb4fc85ab55b495 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 26 Feb 2017 07:02:20 -0500 Subject: [PATCH 589/693] Forgot loader... --- zone/mob_ai.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 294247d59..dbbae074f 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2610,7 +2610,7 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { "manacost, recast_delay, priority, resist_adjust " #ifdef BOTS "FROM %s " - "WHERE npc_spells_id=%d ORDER BY minlevel", (iDBSpellsID >= 701 && iDBSpellsID <= 712 ? "bot_spells_entries" : "npc_spells_entries"), iDBSpellsID); + "WHERE npc_spells_id=%d ORDER BY minlevel", (iDBSpellsID >= 3001 && iDBSpellsID <= 3016 ? "bot_spells_entries" : "npc_spells_entries"), iDBSpellsID); #else "FROM npc_spells_entries " "WHERE npc_spells_id=%d ORDER BY minlevel", iDBSpellsID); From 91ae6a66136e13d5dde26e8a28d0e2dad169a948 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 26 Feb 2017 19:13:47 -0500 Subject: [PATCH 590/693] Secondary aggro meter fix --- zone/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 2d7806821..d638f1d1f 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8825,7 +8825,7 @@ void Client::ProcessAggroMeter() secondary = cur_tar->GetSecondaryHate(this); has_aggro = true; } else { - secondary = cur_tar->GetTarget(); + secondary = cur_tar->CheckAggro(cur_tar->GetTarget()) ? cur_tar->GetTarget() : nullptr; // make sure they are targeting for aggro reasons } } From b1be6678845304950bdfdee002b5de83c7e45f44 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 26 Feb 2017 22:13:41 -0500 Subject: [PATCH 591/693] Update bot spell casting chances table and implemented 'pre-combat' mode for all bots (only bard is actively coded atm) --- changelog.txt | 35 + common/spdat.h | 4 +- common/version.h | 2 +- .../sql/git/bots/bots_db_update_manifest.txt | 1 + ...2_26_bots_spell_casting_chances_update.sql | 2922 +++++++++++++++++ zone/bot.cpp | 55 + zone/bot.h | 55 +- zone/bot_database.cpp | 52 +- zone/bot_structs.h | 6 + zone/botspellsai.cpp | 133 +- zone/mob_ai.cpp | 1 + 11 files changed, 3214 insertions(+), 52 deletions(-) create mode 100644 utils/sql/git/bots/required/2017_02_26_bots_spell_casting_chances_update.sql diff --git a/changelog.txt b/changelog.txt index 2b01b0150..d76bb0608 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,40 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 02/26/2017 == Uleat: Moved bot `npc_spells` entries from '701-712' to 3000 + .. also, added melee types for future expansion +Uleat: Moved bot spell casting chance values into database - this will allow admins to tailor their bots without having to rebuild server code + - Each entry uses a 3-dimensional identifier: [spell type index][class id][stance index] + - [spell type index] is not the SpellType_## bit value..use SpellType_##Index instead + - [class id] values of 1-16 are valid and hold a direct correlation to server-coded player class values + - [stance index] is a direct correlation (0-6) + - the 'conditional fields' are currently predicated on 4 compounded boolean states: + - `pH_value` represents bit '0' + - `pS_value` represents bit '1' + - `pN_value` represents bit '2' + - `pD_value` represents bit '3' + - all other conditional fields are masked based on these 4 predicates + - the full conditional field enumeration is as follows: + - `nHSND_value` - negative Healer/Slower/Nuker/Doter + - `pH_value` - positive Healer + - `pS_value` - positive Slower + - `pHS_value` - positive Healer/Slower + - `pN_value` - positive Nuker + - `pHN_value` - positive Healer/Nuker + - `pSN_value` - positive Slower/Nuker + - `pHSN_value` - positive Healer/Slower/Nuker + - `pD_value` - positive Doter + - `pHD_value` - positive Healer/Doter + - `pSD_value` - positive Slower/Doter + - `pHSD_value` - positive Healer/Slower/Doter + - `pND_value` - positive Nuker/Doter + - `pHND_value` - positive Healer/Nuker/Doter + - `pSND_value` - positive Slower/Nuker/Doter + - `pHSND_value` - positive Healer/Slower/Nuker/Doter + - Single- and mixed-bits fields should be filled-in based on the boolean 'AND' concept + - (i.e., if 'healer' then `pH_value`=x; if 'slower' then `pS_value`=y; if 'healer' AND 'slower' then `pHS_value`=z; ) + - most cases can allow the same value across all fields..but, there are some that shouldn't and this format allows for their discrimination + - Valid `##_value` entries are 0-100..though, the field accepts up to 255... Anything above 100 is clamped to 100 upon loading, however... + - Not all conditions are currently coded and changing a field may not produce any results + - The 'default' database values will be changed and tweaked as bot spell code modifications occur == 02/25/2017 == Uleat: Implemented rule-based node pathing for bots @@ -16,6 +50,7 @@ Uleat: Implemented rule-based position update packet with movement timer check f - This appears to help with/eliminate rubber banding == 02/23/2017 == +** THIS NOTE HAS BEEN SUPERCEDED ON 02/26/2017 ** Uleat: Moved bot spell casting chance values into database - this will allow admins to tailor their bots without having to rebuild server code - Each entry uses a 4-dimensional identifier: [spell type index][class index][stance index][conditional index] - [spell type index] is not the SpellType_## bit value..use SpellType_##Index instead diff --git a/common/spdat.h b/common/spdat.h index d4ccd9456..913ee5a4b 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -67,9 +67,11 @@ enum SpellTypes : uint32 SpellType_HateRedux = (1 << 17), SpellType_InCombatBuffSong = (1 << 18), // bard in-combat group/ae buffs SpellType_OutOfCombatBuffSong = (1 << 19), // bard out-of-combat group/ae buffs + SpellType_PreCombatBuff = (1 << 20), + SpellType_PreCombatBuffSong = (1 << 21), SpellTypes_Detrimental = (SpellType_Nuke | SpellType_Root | SpellType_Lifetap | SpellType_Snare | SpellType_DOT | SpellType_Dispel | SpellType_Mez | SpellType_Charm | SpellType_Debuff | SpellType_Slow), - SpellTypes_Beneficial = (SpellType_Heal | SpellType_Buff | SpellType_Escape | SpellType_Pet | SpellType_InCombatBuff | SpellType_Cure | SpellType_HateRedux | SpellType_InCombatBuffSong | SpellType_OutOfCombatBuffSong), + SpellTypes_Beneficial = (SpellType_Heal | SpellType_Buff | SpellType_Escape | SpellType_Pet | SpellType_InCombatBuff | SpellType_Cure | SpellType_HateRedux | SpellType_InCombatBuffSong | SpellType_OutOfCombatBuffSong | SpellType_PreCombatBuff | SpellType_PreCombatBuffSong), SpellType_Any = 0xFFFFFFFF }; diff --git a/common/version.h b/common/version.h index f6ed08da5..1eb98558f 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9106 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9014 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9015 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index d404568ef..c9a8999e1 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -13,6 +13,7 @@ 9012|2017_02_26_bots_npc_spells_update_for_bots.sql|SELECT * FROM `npc_spells` WHERE `id` = '701' AND `name` = 'Cleric Bot'|not_empty| 9013|2017_02_26_bots_spells_id_update_for_saved_bots.sql|SELECT * FROM `bot_data` WHERE `spells_id` >= '701' AND `spells_id` <= '712'|not_empty| 9014|2017_02_26_bots_spells_id_update_for_bot_spells_entries.sql|SELECT * FROM `bot_spells_entries` WHERE `npc_spells_id` >= '701' AND `npc_spells_id` <= '712'|not_empty| +9015|2017_02_26_bots_spell_casting_chances_update.sql|SHOW COLUMNS FROM `bot_spell_casting_chances` LIKE 'value'|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/bots/required/2017_02_26_bots_spell_casting_chances_update.sql b/utils/sql/git/bots/required/2017_02_26_bots_spell_casting_chances_update.sql new file mode 100644 index 000000000..318f68d5b --- /dev/null +++ b/utils/sql/git/bots/required/2017_02_26_bots_spell_casting_chances_update.sql @@ -0,0 +1,2922 @@ +DROP TABLE IF EXISTS `bot_spell_casting_chances`; + +CREATE TABLE `bot_spell_casting_chances` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `spell_type_index` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `class_id` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `stance_index` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `nHSND_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pH_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pS_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pHS_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pN_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pHN_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pSN_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pHSN_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pD_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pHD_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pSD_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pHSD_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pND_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pHND_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pSND_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + `pHSND_value` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + INDEX `spelltype_class_stance` (`spell_type_index`, `class_id`, `stance_index`) +) +ENGINE=InnoDB +; + +-- Updated table schema + +-- This contents of this file are auto-generated – Do not make adjustments within this file. + + +-- Sheet Enumeration Validation +-- SpellType_NukeIndex = 0 : SpellType_NukeIndex +-- SpellType_HealIndex = 1 : SpellType_HealIndex +-- SpellType_RootIndex = 2 : SpellType_RootIndex +-- SpellType_BuffIndex = 3 : SpellType_BuffIndex +-- SpellType_EscapeIndex = 4 : SpellType_EscapeIndex +-- SpellType_PetIndex = 5 : SpellType_PetIndex +-- SpellType_LifetapIndex = 6 : SpellType_LifetapIndex +-- SpellType_SnareIndex = 7 : SpellType_SnareIndex +-- SpellType_DOTIndex, = 8 : SpellType_DOTIndex +-- SpellType_DispelIndex = 9 : SpellType_DispelIndex +-- SpellType_InCombatBuffIndex = 10 : SpellType_InCombatBuffIndex +-- SpellType_MezIndex = 11 : SpellType_MezIndex +-- SpellType_CharmIndex = 12 : SpellType_CharmIndex +-- SpellType_SlowIndex = 13 : SpellType_SlowIndex +-- SpellType_DebuffIndex = 14 : SpellType_DebuffIndex +-- SpellType_CureIndex = 15 : SpellType_CureIndex +-- SpellType_ResurrectIndex = 16 : SpellType_ResurrectIndex +-- SpellType_HateReduxIndex = 17 : SpellType_HateReduxIndex +-- SpellType_InCombatBuffSongIndex = 18 : SpellType_InCombatBuffSongIndex +-- SpellType_OutOfCombatBuffSongIndex = 19 : SpellType_OutOfCombatBuffSongIndex +-- SpellType_PreCombatBuffIndex = 20 : SpellType_PreCombatBuffIndex +-- SpellType_PreCombatBuffSongIndex = 21 : SpellType_PreCombatBuffSongIndex + + +INSERT INTO `bot_spell_casting_chances` (`spell_type_index`, `class_id`, `stance_index`, `nHSND_value`, `pH_value`, `pS_value`, `pHS_value`, `pN_value`, `pHN_value`, `pSN_value`, `pHSN_value`, `pD_value`, `pHD_value`, `pSD_value`, `pHSD_value`, `pND_value`, `pHND_value`, `pSND_value`, `pHSND_value`) VALUES +-- Versioning +('255', '255', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_NukeIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '2', '1', '25', '15', '25', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '2', '2', '15', '0', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '2', '3', '25', '15', '25', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '2', '4', '50', '15', '50', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '2', '5', '50', '25', '50', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '2', '6', '50', '25', '50', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '3', '1', '25', '15', '25', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '3', '2', '15', '0', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '3', '3', '25', '15', '25', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '3', '4', '50', '15', '50', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '3', '5', '50', '25', '50', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '3', '6', '50', '25', '50', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '4', '1', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '4', '2', '5', '5', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '4', '3', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '4', '4', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '4', '5', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '4', '6', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '5', '1', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '5', '2', '5', '5', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '5', '3', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '5', '4', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '5', '5', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '5', '6', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '6', '1', '25', '15', '25', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '6', '2', '15', '0', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '6', '3', '25', '15', '25', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '6', '4', '50', '15', '50', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '6', '5', '50', '25', '50', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '6', '6', '50', '25', '50', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '8', '1', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '8', '2', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '8', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '8', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '8', '5', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '8', '6', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '10', '1', '15', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '10', '2', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '10', '3', '15', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '10', '4', '25', '15', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '10', '5', '50', '25', '25', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '10', '6', '50', '25', '25', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '11', '1', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '11', '2', '5', '5', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '11', '3', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '11', '4', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '11', '5', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '11', '6', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '12', '1', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '12', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '12', '3', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '12', '4', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '12', '5', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '12', '6', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '13', '1', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '13', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '13', '3', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '13', '4', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '13', '5', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '13', '6', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '14', '1', '25', '25', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '14', '2', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '14', '3', '25', '25', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '14', '4', '50', '50', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '14', '5', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '14', '6', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '15', '1', '15', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '15', '2', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '15', '3', '15', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '15', '4', '25', '15', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '15', '5', '50', '25', '25', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '15', '6', '50', '25', '25', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('0', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('0', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_HealIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '2', '1', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '2', '2', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '2', '3', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '2', '4', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '2', '5', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '2', '6', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '3', '1', '25', '100', '25', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '3', '2', '15', '75', '15', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '3', '3', '25', '100', '25', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '3', '4', '15', '75', '15', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '3', '5', '0', '50', '0', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '3', '6', '0', '50', '0', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '4', '1', '25', '100', '25', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '4', '2', '15', '75', '15', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '4', '3', '25', '100', '25', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '4', '4', '15', '75', '15', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '4', '5', '0', '50', '0', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '4', '6', '0', '50', '0', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '5', '1', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '5', '2', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '5', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '5', '4', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '5', '5', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '5', '6', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '6', '1', '25', '100', '25', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '6', '2', '15', '100', '15', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '6', '3', '25', '100', '25', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '6', '4', '25', '75', '25', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '6', '5', '10', '50', '10', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '6', '6', '10', '50', '10', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '10', '1', '25', '100', '25', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '10', '2', '15', '100', '15', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '10', '3', '25', '100', '25', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '10', '4', '25', '75', '25', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '10', '5', '10', '50', '10', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '10', '6', '10', '50', '10', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '11', '1', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '11', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '11', '3', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '11', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '11', '5', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '11', '6', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '13', '1', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '13', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '13', '3', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '13', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '13', '5', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '13', '6', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '15', '1', '25', '100', '25', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '15', '2', '15', '75', '15', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '15', '3', '25', '100', '25', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '15', '4', '15', '75', '15', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '15', '5', '0', '50', '0', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '15', '6', '0', '50', '0', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('1', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('1', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_RootIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('2', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('2', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_BuffIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('3', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('3', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_EscapeIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '2', '1', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '2', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '2', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '2', '4', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '2', '5', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '2', '6', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '3', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '3', '2', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '3', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '4', '1', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '4', '2', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '4', '3', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '4', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '4', '5', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '4', '6', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '5', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '5', '2', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '5', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '6', '1', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '6', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '6', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '6', '4', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '6', '5', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '6', '6', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '8', '1', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '8', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '8', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '8', '4', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '8', '5', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '8', '6', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '10', '1', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '10', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '10', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '10', '4', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '10', '5', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '10', '6', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '11', '1', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '11', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '11', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '11', '4', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '11', '5', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '11', '6', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '12', '1', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '12', '2', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '12', '3', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '12', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '12', '5', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '12', '6', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '13', '1', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '13', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '13', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '13', '4', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '13', '5', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '13', '6', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '14', '1', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '14', '2', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '14', '3', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '14', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '14', '5', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '14', '6', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('4', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('4', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_PetIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '5', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '5', '2', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '5', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '5', '4', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '5', '5', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '5', '6', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '6', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '6', '2', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '6', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '6', '4', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '6', '5', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '6', '6', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '10', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '10', '2', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '10', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '10', '4', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '10', '5', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '10', '6', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '11', '1', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '11', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '11', '3', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '11', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '11', '5', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '11', '6', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '13', '1', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '13', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '13', '3', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '13', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '13', '5', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '13', '6', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '14', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '14', '2', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '14', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '14', '4', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '14', '5', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '14', '6', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '15', '1', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '15', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '15', '3', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '15', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '15', '5', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '15', '6', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('5', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('5', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_LifetapIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '5', '1', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '5', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '5', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '5', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '5', '5', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '5', '6', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '11', '1', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '11', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '11', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '11', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '11', '5', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '11', '6', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('6', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('6', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_SnareIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('7', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('7', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_DOTIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '4', '1', '15', '15', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '4', '2', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '4', '3', '15', '15', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '4', '4', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '4', '5', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '4', '6', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '5', '1', '15', '15', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '5', '2', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '5', '3', '15', '15', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '5', '4', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '5', '5', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '5', '6', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '6', '1', '50', '15', '50', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '6', '2', '25', '10', '25', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '6', '3', '50', '15', '50', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '6', '4', '50', '25', '50', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '6', '5', '50', '25', '50', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '6', '6', '50', '25', '50', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '8', '1', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '8', '2', '25', '25', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '8', '3', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '8', '4', '100', '100', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '8', '5', '100', '100', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '8', '6', '100', '100', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '10', '1', '25', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '10', '2', '15', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '10', '3', '25', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '10', '4', '50', '25', '50', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '10', '5', '50', '25', '50', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '10', '6', '50', '25', '50', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '11', '1', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '11', '2', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '11', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '11', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '11', '5', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '11', '6', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '14', '1', '50', '50', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '14', '2', '25', '25', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '14', '3', '50', '50', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '14', '4', '15', '15', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '14', '5', '15', '15', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '14', '6', '15', '15', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '15', '1', '15', '15', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '15', '2', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '15', '3', '15', '15', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '15', '4', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '15', '5', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '15', '6', '50', '50', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('8', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('8', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_DispelIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('9', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('9', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_InCombatBuffIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '2', '1', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '2', '3', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '2', '4', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '2', '5', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '2', '6', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '3', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '3', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '3', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '3', '5', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '3', '6', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '10', '1', '50', '75', '50', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '10', '2', '25', '50', '25', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '10', '3', '50', '75', '50', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '10', '4', '75', '100', '75', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '10', '5', '75', '100', '75', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '10', '6', '75', '100', '75', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('10', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('10', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_MezIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('11', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('11', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_CharmIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('12', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('12', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_SlowIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '8', '1', '25', '25', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '8', '2', '15', '15', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '8', '3', '25', '25', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '8', '4', '0', '0', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '8', '5', '0', '0', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '8', '6', '0', '0', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '10', '1', '50', '50', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '10', '2', '25', '25', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '10', '3', '50', '50', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '10', '4', '15', '15', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '10', '5', '15', '15', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '10', '6', '15', '15', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '14', '1', '50', '50', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '14', '2', '25', '25', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '14', '3', '50', '50', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '14', '4', '15', '15', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '14', '5', '15', '15', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '14', '6', '15', '15', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '15', '1', '25', '25', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '15', '2', '15', '15', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '15', '3', '25', '25', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '15', '4', '0', '0', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '15', '5', '0', '0', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '15', '6', '0', '0', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('13', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('13', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_DebuffIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '4', '1', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '4', '2', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '4', '3', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '4', '4', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '5', '1', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '5', '2', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '5', '3', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '5', '4', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '6', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '6', '2', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '6', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '6', '4', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '8', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '8', '2', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '8', '3', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '8', '4', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '10', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '10', '2', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '10', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '10', '4', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '11', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '11', '2', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '11', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '11', '4', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '13', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '13', '2', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '13', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '13', '4', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '14', '1', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '14', '2', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '14', '3', '25', '25', '25', '25', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '14', '4', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '15', '1', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '15', '2', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '15', '3', '15', '15', '15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '15', '4', '10', '10', '10', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('14', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('14', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_CureIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '8', '1', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '8', '2', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '8', '3', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '8', '4', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '8', '5', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '8', '6', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('15', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('15', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_ResurrectIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('16', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('16', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_HateReduxIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '8', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '8', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '8', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '8', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '8', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '8', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('17', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('17', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_InCombatBuffSongIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '8', '1', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '8', '2', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '8', '3', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '8', '4', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '8', '5', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '8', '6', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('18', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('18', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_OutOfCombatBuffSongIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '8', '1', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '8', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '8', '3', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '8', '4', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '8', '5', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '8', '6', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('19', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('19', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_PreCombatBuffIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '8', '1', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '8', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '8', '3', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '8', '4', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '8', '5', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '8', '6', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('20', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('20', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), + +-- SpellType_PreCombatBuffSongIndex +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '1', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '1', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '1', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '1', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '1', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '2', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '2', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '2', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '2', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '2', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '2', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '3', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '3', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '3', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '3', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '3', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '3', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '4', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '4', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '4', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '4', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '4', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '4', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '5', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '5', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '5', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '5', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '5', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '5', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '6', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '6', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '6', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '6', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '6', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '6', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '7', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '7', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '7', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '7', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '7', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '7', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '7', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '8', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '8', '1', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '8', '2', '50', '50', '50', '50', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '8', '3', '75', '75', '75', '75', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '8', '4', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '8', '5', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '8', '6', '100', '100', '100', '100', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '9', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '9', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '9', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '9', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '9', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '9', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '9', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '10', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '10', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '10', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '10', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '10', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '10', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '10', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '11', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '11', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '11', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '11', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '11', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '11', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '11', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '12', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '12', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '12', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '12', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '12', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '12', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '12', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '13', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '13', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '13', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '13', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '13', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '13', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '13', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '14', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '14', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '14', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '14', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '14', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '14', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '14', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '15', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '15', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '15', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '15', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '15', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '15', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '15', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +-- nHSND pH pS pHS pN pHN pSN pHSN pD pHD pSD pHSD pND pHND pSND pHSND +('21', '16', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '16', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '16', '2', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '16', '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '16', '4', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '16', '5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'), +('21', '16', '6', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'); diff --git a/zone/bot.cpp b/zone/bot.cpp index 1156aec31..fc26d6ccb 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -178,6 +178,8 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to m_CastingRoles.GroupHealer = false; m_CastingRoles.GroupSlower = false; + m_CastingRoles.GroupNuker = false; + m_CastingRoles.GroupDoter = false; GenerateBaseStats(); @@ -424,6 +426,7 @@ void Bot::GenerateBaseStats() int32 ColdResist = _baseCR; int32 CorruptionResist = _baseCorrup; + // pulling fixed values from an auto-increment field is dangerous... switch(this->GetClass()) { case WARRIOR: BotSpellID = 3001; @@ -6917,6 +6920,8 @@ void Bot::UpdateGroupCastingRoles(const Group* group, bool disband) if (iter->IsBot()) { iter->CastToBot()->SetGroupHealer(false); iter->CastToBot()->SetGroupSlower(false); + iter->CastToBot()->SetGroupNuker(false); + iter->CastToBot()->SetGroupDoter(false); } } @@ -6925,11 +6930,14 @@ void Bot::UpdateGroupCastingRoles(const Group* group, bool disband) Mob* healer = nullptr; Mob* slower = nullptr; + Mob* nuker = nullptr; + Mob* doter = nullptr; for (auto iter : group->members) { if (!iter) continue; + // GroupHealer switch (iter->GetClass()) { case CLERIC: if (!healer) @@ -6978,6 +6986,7 @@ void Bot::UpdateGroupCastingRoles(const Group* group, bool disband) break; } + // GroupSlower switch (iter->GetClass()) { case SHAMAN: if (!slower) @@ -7009,14 +7018,43 @@ void Bot::UpdateGroupCastingRoles(const Group* group, bool disband) default: break; } + + // GroupNuker + switch (iter->GetClass()) { + // wizard + // magician + // necromancer + // enchanter + // druid + // cleric + // shaman + // shadowknight + // paladin + // ranger + // beastlord + default: + break; + } + + // GroupDoter + switch (iter->GetClass()) { + default: + break; + } } if (healer && healer->IsBot()) healer->CastToBot()->SetGroupHealer(); if (slower && slower->IsBot()) slower->CastToBot()->SetGroupSlower(); + if (nuker && nuker->IsBot()) + nuker->CastToBot()->SetGroupNuker(); + if (doter && doter->IsBot()) + doter->CastToBot()->SetGroupDoter(); } +//void Bot::UpdateRaidCastingRoles(const Raid* raid, bool disband = false) { } + bool Bot::CanHeal() { bool result = false; @@ -7788,6 +7826,23 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl } } + if (iSpellTypes == SpellType_PreCombatBuff) { + if (botCasterClass == BARD || caster->IsEngaged()) + return false; + + if (caster->HasGroup()) { + Group *g = caster->GetGroup(); + if (g) { + for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (g->members[i]) { + if (caster->AICastSpell(g->members[i], iChance, SpellType_PreCombatBuff) || caster->AICastSpell(g->members[i]->GetPet(), iChance, SpellType_PreCombatBuff)) + return true; + } + } + } + } + } + return false; } diff --git a/zone/bot.h b/zone/bot.h index 9608d60f3..d124a6fc2 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -132,11 +132,48 @@ enum SpellTypeIndex { SpellType_HateReduxIndex, SpellType_InCombatBuffSongIndex, SpellType_OutOfCombatBuffSongIndex, + SpellType_PreCombatBuffIndex, + SpellType_PreCombatBuffSongIndex, MaxSpellTypes }; -// negative Healer/Slower, positive Healer, postive Slower, positive Healer/Slower -enum BotCastingChanceConditional : uint8 { nHS = 0, pH, pS, pHS, cntHS = 4 }; +// nHSND negative Healer/Slower/Nuker/Doter +// pH positive Healer +// pS positive Slower +// pHS positive Healer/Slower +// pN positive Nuker +// pHN positive Healer/Nuker +// pSN positive Slower/Nuker +// pHSN positive Healer/Slower/Nuker +// pD positive Doter +// pHD positive Healer/Doter +// pSD positive Slower/Doter +// pHSD positive Healer/Slower/Doter +// pND positive Nuker/Doter +// pHND positive Healer/Nuker/Doter +// pSND positive Slower/Nuker/Doter +// pHSND positive Healer/Slower/Nuker/Doter +// cntHSND count Healer/Slower/Nuker/Doter +enum BotCastingChanceConditional : uint8 +{ + nHSND = 0, + pH, + pS, + pHS, + pN, + pHN, + pSN, + pHSN, + pD, + pHD, + pSD, + pHSD, + pND, + pHND, + pSND, + pHSND, + cntHSND = 16 +}; class Bot : public NPC { @@ -482,8 +519,16 @@ public: bool IsGroupHealer() { return m_CastingRoles.GroupHealer; } bool IsGroupSlower() { return m_CastingRoles.GroupSlower; } + bool IsGroupNuker() { return m_CastingRoles.GroupNuker; } + bool IsGroupDoter() { return m_CastingRoles.GroupDoter; } static void UpdateGroupCastingRoles(const Group* group, bool disband = false); + //bool IsRaidHealer() { return m_CastingRoles.RaidHealer; } + //bool IsRaidSlower() { return m_CastingRoles.RaidSlower; } + //bool IsRaidNuker() { return m_CastingRoles.RaidNuker; } + //bool IsRaidDoter() { return m_CastingRoles.RaidDoter; } + //static void UpdateRaidCastingRoles(const Raid* raid, bool disband = false); + bool IsBotCaster() { return IsCasterClass(GetClass()); } bool IsBotINTCaster() { return IsINTCasterClass(GetClass()); } bool IsBotWISCaster() { return IsWISCasterClass(GetClass()); } @@ -650,6 +695,12 @@ protected: BotCastingRoles& GetCastingRoles() { return m_CastingRoles; } void SetGroupHealer(bool flag = true) { m_CastingRoles.GroupHealer = flag; } void SetGroupSlower(bool flag = true) { m_CastingRoles.GroupSlower = flag; } + void SetGroupNuker(bool flag = true) { m_CastingRoles.GroupNuker = flag; } + void SetGroupDoter(bool flag = true) { m_CastingRoles.GroupDoter = flag; } + //void SetRaidHealer(bool flag = true) { m_CastingRoles.RaidHealer = flag; } + //void SetRaidSlower(bool flag = true) { m_CastingRoles.RaidSlower = flag; } + //void SetRaidNuker(bool flag = true) { m_CastingRoles.RaidNuker = flag; } + //void SetRaidDoter(bool flag = true) { m_CastingRoles.RaidDoter = flag; } private: // Class Members diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 3ccc9726e..b45ef6a3b 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -82,7 +82,7 @@ bool BotDatabase::LoadBotCommandSettings(std::map= MaxSpellTypes) continue; uint8 class_index = atoi(row[1]); - if (class_index >= PLAYER_CLASS_COUNT) + if (class_index < WARRIOR || class_index > BERSERKER) continue; + --class_index; uint8 stance_index = atoi(row[2]); if (stance_index >= MaxStances) continue; - uint8 conditional_index = atoi(row[3]); - if (conditional_index >= cntHS) - continue; - uint8 value = atoi(row[4]); - if (value > 100) - value = 100; - spell_casting_chances[spell_type_index][class_index][stance_index][conditional_index] = value; + + for (uint8 conditional_index = nHSND; conditional_index < cntHSND; ++conditional_index) { + uint8 value = atoi(row[3 + conditional_index]); + if (!value) + continue; + if (value > 100) + value = 100; + + spell_casting_chances[spell_type_index][class_index][stance_index][conditional_index] = value; + } } return true; @@ -2761,7 +2777,7 @@ bool BotDatabase::DeleteAllHealRotations(const uint32 owner_id) /* Bot miscellaneous functions */ -uint8 BotDatabase::GetSpellCastingChance(uint8 spell_type_index, uint8 class_index, uint8 stance_index, uint8 conditional_index) +uint8 BotDatabase::GetSpellCastingChance(uint8 spell_type_index, uint8 class_index, uint8 stance_index, uint8 conditional_index) // class_index is 0-based { if (spell_type_index >= MaxSpellTypes) return 0; @@ -2769,7 +2785,7 @@ uint8 BotDatabase::GetSpellCastingChance(uint8 spell_type_index, uint8 class_ind return 0; if (stance_index >= MaxStances) return 0; - if (conditional_index >= cntHS) + if (conditional_index >= cntHSND) return 0; return spell_casting_chances[spell_type_index][class_index][stance_index][conditional_index]; diff --git a/zone/bot_structs.h b/zone/bot_structs.h index 8200c9933..d54c0c042 100644 --- a/zone/bot_structs.h +++ b/zone/bot_structs.h @@ -63,6 +63,12 @@ struct BotSpell_wPriority : public BotSpell { struct BotCastingRoles { bool GroupHealer; bool GroupSlower; + bool GroupNuker; + bool GroupDoter; + //bool RaidHealer; + //bool RaidSlower; + //bool RaidNuker; + //bool RaidDoter; }; struct BotAA { diff --git a/zone/botspellsai.cpp b/zone/botspellsai.cpp index 51546eb2a..9967d2368 100644 --- a/zone/botspellsai.cpp +++ b/zone/botspellsai.cpp @@ -1046,6 +1046,12 @@ bool Bot::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { break; } + case SpellType_PreCombatBuff: { + break; + } + case SpellType_PreCombatBuffSong: { + break; + } default: break; } @@ -1163,16 +1169,28 @@ bool Bot::AI_IdleCastCheck() { #endif AIautocastspell_timer->Disable(); //prevent the timer from going off AGAIN while we are casting. - //Ok, IdleCastCheck depends of class. - // Healers WITHOUT pets will check if a heal is needed before buffing. - uint8 botClass = GetClass(); + bool pre_combat = false; + Mob* test_against = nullptr; - if(botClass == CLERIC || botClass == PALADIN || botClass == RANGER) { - if(!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { + if (HasGroup() && GetGroup()->GetLeader() && GetGroup()->GetLeader()->IsClient()) + test_against = GetGroup()->GetLeader(); + else if (GetOwner() && GetOwner()->IsClient()) + test_against = GetOwner(); + + if (test_against && test_against->GetTarget() && test_against->GetTarget()->IsNPC() && !test_against->GetTarget()->IsPet()) + pre_combat = true; + + //Ok, IdleCastCheck depends of class. + switch (GetClass()) { + // Healers WITHOUT pets will check if a heal is needed before buffing. + case CLERIC: + case PALADIN: + case RANGER: { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { if (!AICastSpell(this, 100, SpellType_Heal)) { - if(!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) { if (!AICastSpell(this, 100, SpellType_Buff)) { - if(!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { // } } @@ -1181,16 +1199,23 @@ bool Bot::AI_IdleCastCheck() { } result = true; + break; } // Pets class will first cast their pet, then buffs - else if(botClass == DRUID || botClass == MAGICIAN || botClass == SHADOWKNIGHT || botClass == SHAMAN || botClass == NECROMANCER || botClass == ENCHANTER || botClass == BEASTLORD || botClass == WIZARD) { - if(!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { + case DRUID: + case MAGICIAN: + case SHADOWKNIGHT: + case SHAMAN: + case NECROMANCER: + case ENCHANTER: + case BEASTLORD: { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { if (!AICastSpell(this, 100, SpellType_Pet)) { if (!AICastSpell(this, 100, SpellType_Heal)) { - if(!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) { if (!AICastSpell(this, 100, SpellType_Buff)) { if (!AICastSpell(GetPet(), 100, SpellType_Heal)) { - if(!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { // } } @@ -1201,23 +1226,57 @@ bool Bot::AI_IdleCastCheck() { } result = true; + break; } - else if(botClass == BARD) { - // bard bots - bool battle_prep = false; - Mob* prep_against = nullptr; - - if (HasGroup() && GetGroup()->GetLeader() && GetGroup()->GetLeader()->IsClient()) - prep_against = GetGroup()->GetLeader(); - else if (GetOwner() && GetOwner()->IsClient()) - prep_against = GetOwner(); - - if (prep_against && prep_against->GetTarget() && prep_against->GetTarget()->IsNPC() && !prep_against->GetTarget()->IsPet()) - battle_prep = true; - - if (battle_prep) { - if (!AICastSpell(this, 100, SpellType_InCombatBuffSong)) { - // + case WIZARD: { // This can eventually be move into the BEASTLORD case handler once pre-combat is fully implemented + if (pre_combat) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { + if (!AICastSpell(this, 100, SpellType_Pet)) { + if (!AICastSpell(this, 100, SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) { + if (!AICastSpell(this, 100, SpellType_Buff)) { + if (!AICastSpell(GetPet(), 100, SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_PreCombatBuff)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { + // + } + } + } + } + } + } + } + } + } + else { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { + if (!AICastSpell(this, 100, SpellType_Pet)) { + if (!AICastSpell(this, 100, SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Heal)) { + if (!AICastSpell(this, 100, SpellType_Buff)) { + if (!AICastSpell(GetPet(), 100, SpellType_Heal)) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Buff)) { + // + } + } + } + } + } + } + } + } + + result = true; + break; + } + case BARD: { + if (pre_combat) { + if (!entity_list.Bot_AICheckCloseBeneficialSpells(this, 100, BotAISpellRange, SpellType_Cure)) { + if (!AICastSpell(this, 100, SpellType_PreCombatBuffSong)) { + if (!AICastSpell(this, 100, SpellType_InCombatBuffSong)) { + // + } + } } } else { @@ -1229,6 +1288,10 @@ bool Bot::AI_IdleCastCheck() { } result = true; + break; + } + default: + break; } if(!AIautocastspell_timer->Enabled()) @@ -2572,6 +2635,12 @@ uint8 Bot::GetChanceToCastBySpellType(uint32 spellType) case SpellType_OutOfCombatBuffSong: spell_type_index = SpellType_OutOfCombatBuffSongIndex; break; + case SpellType_PreCombatBuff: + spell_type_index = SpellType_PreCombatBuffIndex; + break; + case SpellType_PreCombatBuffSong: + spell_type_index = SpellType_PreCombatBuffSongIndex; + break; default: spell_type_index = MaxSpellTypes; break; @@ -2588,12 +2657,16 @@ uint8 Bot::GetChanceToCastBySpellType(uint32 spellType) if (stance_index >= MaxStances) return 0; - uint8 type_index = nHS; + uint8 type_index = nHSND; if (HasGroup()) { - if (IsGroupHealer()) + if (IsGroupHealer()/* || IsRaidHealer()*/) type_index |= pH; - if (IsGroupSlower()) + if (IsGroupSlower()/* || IsRaidSlower()*/) type_index |= pS; + if (IsGroupNuker()/* || IsRaidNuker()*/) + type_index |= pN; + if (IsGroupDoter()/* || IsRaidDoter()*/) + type_index |= pD; } return botdb.GetSpellCastingChance(spell_type_index, class_index, stance_index, type_index); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index dbbae074f..f6e6fa019 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2606,6 +2606,7 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) { uint32 tmpidle_no_sp_recast_max = atoi(row[18]); uint8 tmpidle_b_chance = atoi(row[19]); + // pulling fixed values from an auto-increment field is dangerous... query = StringFormat("SELECT spellid, type, minlevel, maxlevel, " "manacost, recast_delay, priority, resist_adjust " #ifdef BOTS From 666513c4ab2d91117a0450f3e7208731d778db93 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 27 Feb 2017 15:21:50 -0500 Subject: [PATCH 592/693] Better comment SendGroupCreatePacket --- zone/client.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index d638f1d1f..0228b12f4 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -5913,20 +5913,20 @@ void Client::SendGroupCreatePacket() char *Buffer = (char *)outapp->pBuffer; // Header - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // Null Leader name + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // group ID probably + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); // count of members in packet + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // Null Leader name, shouldn't be null besides this case - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Member 0 - VARSTRUCT_ENCODE_STRING(Buffer, GetName()); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, GetLevel()); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint16, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Member 0, index + VARSTRUCT_ENCODE_STRING(Buffer, GetName()); // group member name + VARSTRUCT_ENCODE_TYPE(uint16, Buffer, 0); // merc flag + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // owner name (if merc) + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, GetLevel()); // level + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // group tank flag + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // group assist flag + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // group puller flag + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // offline flag + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // timestamp FastQueuePacket(&outapp); } From bf239f969198a1f16e14d6dd58a2109f6abb4c00 Mon Sep 17 00:00:00 2001 From: Uleat Date: Mon, 27 Feb 2017 21:32:07 -0500 Subject: [PATCH 593/693] A 'hack' and a 'fix' (bot movement changes) --- zone/bot.cpp | 120 +++++++++++++++------------------------------ zone/bot.h | 6 +-- zone/mob.cpp | 19 ++++++- zone/waypoints.cpp | 4 ++ 4 files changed, 65 insertions(+), 84 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index fc26d6ccb..eaba1aeea 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2164,7 +2164,7 @@ void Bot::AI_Process() { } else if(!IsRooted()) { if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) { Log.Out(Logs::Detail, Logs::AI, "Returning to location prior to being summoned."); - CalculateNewPosition2(m_PreSummonLocation.x, m_PreSummonLocation.y, m_PreSummonLocation.z, GetRunspeed()); + CalculateNewPosition2(m_PreSummonLocation.x, m_PreSummonLocation.y, m_PreSummonLocation.z, GetBotRunspeed()); SetHeading(CalculateHeadingToTarget(m_PreSummonLocation.x, m_PreSummonLocation.y)); return; } @@ -2239,7 +2239,7 @@ void Bot::AI_Process() { if(IsMoving()) { SetHeading(0); SetRunAnimSpeed(0); - SetCurrentSpeed(GetRunspeed()); + SetCurrentSpeed(GetBotRunspeed()); if(moved) SetCurrentSpeed(0); } @@ -2250,17 +2250,17 @@ void Bot::AI_Process() { bool WaypointChanged, NodeReached; glm::vec3 Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), - GetRunspeed(), WaypointChanged, NodeReached); + GetBotRunspeed(), WaypointChanged, NodeReached); if (WaypointChanged) tar_ndx = 20; - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetBotRunspeed()); } else { Mob* follow = entity_list.GetMob(GetFollowID()); if (follow) - CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetRunspeed()); + CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetBotRunspeed()); } return; @@ -2350,7 +2350,7 @@ void Bot::AI_Process() { float newZ = 0; FaceTarget(GetTarget()); if (PlotPositionAroundTarget(this, newX, newY, newZ)) { - CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); + CalculateNewPosition2(newX, newY, newZ, GetBotRunspeed()); return; } } @@ -2362,7 +2362,7 @@ void Bot::AI_Process() { float newY = 0; float newZ = 0; if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) { - CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); + CalculateNewPosition2(newX, newY, newZ, GetBotRunspeed()); return; } } @@ -2373,7 +2373,7 @@ void Bot::AI_Process() { float newY = 0; float newZ = 0; if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) { - CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); + CalculateNewPosition2(newX, newY, newZ, GetBotRunspeed()); return; } } @@ -2498,7 +2498,7 @@ void Bot::AI_Process() { if (AI_movement_timer->Check()) { if(!IsRooted()) { Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName()); - CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed()); + CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetBotRunspeed()); return; } @@ -2518,7 +2518,8 @@ void Bot::AI_Process() { else if(GetArchetype() == ARCHETYPE_CASTER) BotMeditate(true); } - } else { + } + else { SetTarget(nullptr); if (m_PlayerState & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); @@ -2527,77 +2528,44 @@ void Bot::AI_Process() { if (!follow) return; - float cur_dist = DistanceSquared(m_Position, follow->GetPosition()); - - if (!IsMoving() && cur_dist <= GetFollowDistance()) { - if (AI_think_timer->Check()) { - if (!spellend_timer.Enabled()) { - if (GetBotStance() != BotStancePassive) { - if (!AI_IdleCastCheck() && !IsCasting() && GetClass() != BARD) - BotMeditate(true); - } - else { - if (GetClass() != BARD) - BotMeditate(true); - } - } + if (!IsMoving() && AI_think_timer->Check() && !spellend_timer.Enabled()) { + if (GetBotStance() != BotStancePassive) { + if (!AI_IdleCastCheck() && !IsCasting() && GetClass() != BARD) + BotMeditate(true); + } + else { + if (GetClass() != BARD) + BotMeditate(true); } } - else if(AI_movement_timer->Check()) { - // Something is still wrong with bot the follow code... - // Shows up really bad over long distances when movement bonuses are involved - // The flip-side is that too much speed adversely affects node pathing... - if (cur_dist > GetFollowDistance()) { + + if (AI_movement_timer->Check()) { + float dist = DistanceSquared(m_Position, follow->GetPosition()); + int speed = GetBotRunspeed(); + + if (dist < GetFollowDistance() + BOT_FOLLOW_DISTANCE_WALK) + speed = GetBotWalkspeed(); + + SetRunAnimSpeed(0); + + if (dist > GetFollowDistance()) { if (RuleB(Bots, UsePathing) && zone->pathing) { - if (cur_dist <= BOT_FOLLOW_DISTANCE_WALK) { - bool WaypointChanged, NodeReached; + bool WaypointChanged, NodeReached; - glm::vec3 Goal = UpdatePath(follow->GetX(), follow->GetY(), follow->GetZ(), - GetWalkspeed(), WaypointChanged, NodeReached); + glm::vec3 Goal = UpdatePath(follow->GetX(), follow->GetY(), follow->GetZ(), + speed, WaypointChanged, NodeReached); - if (WaypointChanged) - tar_ndx = 20; + if (WaypointChanged) + tar_ndx = 20; - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetWalkspeed()); - } - else { - int speed = GetRunspeed(); - if (cur_dist > BOT_FOLLOW_DISTANCE_CRITICAL) - speed = ((float)speed * 1.333f); // sprint mod (1/3 boost) - - bool WaypointChanged, NodeReached; - - glm::vec3 Goal = UpdatePath(follow->GetX(), follow->GetY(), follow->GetZ(), - speed, WaypointChanged, NodeReached); - - if (WaypointChanged) - tar_ndx = 20; - - CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed); - } + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed); } else { - if (cur_dist <= BOT_FOLLOW_DISTANCE_WALK) { - CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetWalkspeed()); - } - else { - int speed = GetRunspeed(); - if (cur_dist > BOT_FOLLOW_DISTANCE_CRITICAL) - speed = ((float)speed * 1.333f); // sprint mod (1/3 boost) - - CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); - } + CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); } - + if (rest_timer.Enabled()) rest_timer.Disable(); - - if (RuleB(Bots, UpdatePositionWithTimer)) { // this helps with rubber-banding effect - if (IsMoving()) - SendPosUpdate(); - //else - // SendPosition(); // enabled - no discernable difference..disabled - saves on no movement packets - } } else { if (moved) { @@ -2605,13 +2573,9 @@ void Bot::AI_Process() { SetCurrentSpeed(0); } } - - if (GetClass() == BARD && GetBotStance() != BotStancePassive && !spellend_timer.Enabled() && AI_think_timer->Check()) - AI_IdleCastCheck(); - - return; } - else if (IsMoving()) { + + if (IsMoving()) { if (GetClass() == BARD && GetBotStance() != BotStancePassive && !spellend_timer.Enabled() && AI_think_timer->Check()) { AI_IdleCastCheck(); } @@ -7074,10 +7038,6 @@ bool Bot::CanHeal() { return result; } -bool Bot::CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ) { - return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ); -} - Bot* Bot::GetBotByBotClientOwnerAndBotName(Client* c, std::string botName) { Bot* Result = 0; if(c) { diff --git a/zone/bot.h b/zone/bot.h index d124a6fc2..7bfbf87d0 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -40,8 +40,7 @@ #define BOT_FOLLOW_DISTANCE_DEFAULT 184 // as DSq value (~13.565 units) #define BOT_FOLLOW_DISTANCE_DEFAULT_MAX 2500 // as DSq value (50 units) -#define BOT_FOLLOW_DISTANCE_WALK 400 // as DSq value (20 units) -#define BOT_FOLLOW_DISTANCE_CRITICAL 22500 // as DSq value (150 units) +#define BOT_FOLLOW_DISTANCE_WALK 1000 // as DSq value (~31.623 units) extern WorldServer worldserver; @@ -336,8 +335,9 @@ public: void Stand(); bool IsSitting(); bool IsStanding(); + int GetBotWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.786f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143 + int GetBotRunspeed() const { return (int)((float)_GetRunSpeed() * 1.786f); } bool IsBotCasterCombatRange(Mob *target); - bool CalculateNewPosition2(float x, float y, float z, float speed, bool checkZ = true) ; bool UseDiscipline(uint32 spell_id, uint32 target); uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets); bool GetNeedsCured(Mob *tar); diff --git a/zone/mob.cpp b/zone/mob.cpp index 506c8b44e..119f32031 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -613,7 +613,11 @@ int Mob::_GetWalkSpeed() const { return(0); //runspeed cap. +#ifdef BOTS + if (IsClient() || IsBot()) +#else if(IsClient()) +#endif { if(speed_mod > runspeedcap) speed_mod = runspeedcap; @@ -672,7 +676,11 @@ int Mob::_GetRunSpeed() const { if (!has_horse && movemod != 0) { +#ifdef BOTS + if (IsClient() || IsBot()) +#else if (IsClient()) +#endif { speed_mod += (speed_mod * movemod / 100); } else { @@ -701,7 +709,11 @@ int Mob::_GetRunSpeed() const { return(0); } //runspeed cap. +#ifdef BOTS + if (IsClient() || IsBot()) +#else if(IsClient()) +#endif { if(speed_mod > runspeedcap) speed_mod = runspeedcap; @@ -1458,10 +1470,15 @@ void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) { spu->padding0006 =7; spu->padding0014 =0x7f; spu->padding0018 =0x5df27; +#ifdef BOTS + if (this->IsClient() || this->IsBot()) +#else if(this->IsClient()) +#endif spu->animation = animation; else - spu->animation = pRunAnimSpeed;//animation; + spu->animation = pRunAnimSpeed;//animation; + spu->delta_heading = NewFloatToEQ13(m_Delta.w); } diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index f6c55a5eb..5f9e32cab 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -574,7 +574,11 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo m_TargetV.z = z - nz; SetCurrentSpeed((int8)speed); pRunAnimSpeed = speed; +#ifdef BOTS + if(IsClient() || IsBot()) +#else if(IsClient()) +#endif { animation = speed / 2; } From a8a1c3f8090fe1ee7baa99a3eceff0d25aad0f9c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 28 Feb 2017 02:21:29 -0500 Subject: [PATCH 594/693] Better comment some group shit --- common/eq_packet_structs.h | 1 + common/patches/rof2.cpp | 40 +++++++++++++++++------------------ common/patches/rof2_structs.h | 7 ++++-- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 7b44bd45c..3730e1d14 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -2243,6 +2243,7 @@ struct GroupFollow_Struct { // SoF Follow Struct /*0132*/ }; +// this is generic struct struct GroupLeaderChange_Struct { /*000*/ char Unknown000[64]; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 8f8d41281..cf84f040b 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1182,17 +1182,17 @@ namespace RoF2 // Leader // - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_STRING(Buffer, gu2->yourname); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // index + VARSTRUCT_ENCODE_STRING(Buffer, gu2->yourname); // name + VARSTRUCT_ENCODE_TYPE(uint16, Buffer, 0); // owner name of merc //VARSTRUCT_ENCODE_STRING(Buffer, ""); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x46); // Observed 0x41 and 0x46 here - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint16, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x46); // level + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // group tank flag + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // group assist flag + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // group puller flag + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // offline + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // timestamp int MemberNumber = 1; @@ -1201,17 +1201,17 @@ namespace RoF2 if (gu2->membername[i][0] == '\0') continue; - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, MemberNumber++); - VARSTRUCT_ENCODE_STRING(Buffer, gu2->membername[i]); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, MemberNumber++); // index + VARSTRUCT_ENCODE_STRING(Buffer, gu2->membername[i]); // name + VARSTRUCT_ENCODE_TYPE(uint16, Buffer, 0); // merc flag //VARSTRUCT_ENCODE_STRING(Buffer, ""); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x41); // Observed 0x41 and 0x46 here - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Low byte is Main Assist Flag - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint16, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // owner name fo merc + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x41); // level + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // group tank flag + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // group assist flag + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // group puller flag + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // offline + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // timestamp } //Log.Hex(Logs::Netcode, outapp->pBuffer, outapp->size); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 1ed1b9916..13befdad9 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -2566,9 +2566,12 @@ struct GroupJoin_Struct_Live { // New for Live }; struct GroupJoin_Struct { -/*000*/ char unknown000[64]; +/*000*/ char owner_name[64]; // merc /*064*/ char membername[64]; -/*128*/ uint8 unknown128[20]; // Leadership AA ? +/*128*/ uint8 merc; +/*129*/ uint8 padding129[3]; +/*132*/ uint32 level; +/*136*/ uint8 unknown136[12]; // group ID most likely in here judging from like captures (unused by client) /*148*/ }; From 52d79f89a98115eaa7236268da2c736f1d1cb715 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 28 Feb 2017 08:49:25 -0500 Subject: [PATCH 595/693] Bots should now /con correctly after a successful ^update --- zone/bot_command.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 5e15b0f08..d15b3f972 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -5399,6 +5399,7 @@ void bot_subcommand_bot_update(Client *c, const Seperator *sep) bot_iter->SetPetChooser(false); bot_iter->CalcBotStats((sbl.size() == 1)); + bot_iter->SendAppearancePacket(AT_WhoLevel, bot_iter->GetLevel(), true, true); ++bot_count; } From a7cbe2f60eab05f2516b44df8eda501c1c52cfac Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 28 Feb 2017 09:44:24 -0500 Subject: [PATCH 596/693] Fix for npc corpse looting not updating appearance of looted items --- zone/loottables.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 3297dec60..4fd9c893c 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -255,6 +255,7 @@ void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 ch item->attuned = 0; item->min_level = minlevel; item->max_level = maxlevel; + item->equip_slot = EQEmu::inventory::slotInvalid; if (equipit) { uint8 eslot = 0xFF; @@ -399,8 +400,8 @@ void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 ch } if (found) { CalcBonuses(); // This is less than ideal for bulk adding of items + item->equip_slot = foundslot; } - item->equip_slot = item2->Slots; } if(itemlist != nullptr) From 05ca4669a91693a5006d0d5f942829939cd38e95 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 28 Feb 2017 10:39:26 -0500 Subject: [PATCH 597/693] Fix for aberrant bot animations when using ^summon (i.e., swimming in air) --- changelog.txt | 9 +++++++++ zone/bot_command.cpp | 1 + 2 files changed, 10 insertions(+) diff --git a/changelog.txt b/changelog.txt index d76bb0608..208cb0585 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,14 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 02/27/2017 == +Uleat: Notes on bot movement speed changes: + - Clients (players) appear to be on a different speed scale than other entities (NPCs, etc...) + - The server does not calculate deltas/velocities for moving players..those come the client itself + - GetBotWalkspeed() and GetBotRunspeed() are specific to bot movement calculations + - The class Mob equivilents are not scalared so that a 'client-oriented' value can still be attained + - The value of ~1.786f is derived from the ratio of 1.25f/0.7f (npc speed/client speed) + - Modifying the two speeds like this is a rough guess-timate..but, appears to at least bring the incongruous behavior to acceptable levels + == 02/26/2017 == Uleat: Moved bot `npc_spells` entries from '701-712' to 3000 + .. also, added melee types for future expansion Uleat: Moved bot spell casting chance values into database - this will allow admins to tailor their bots without having to rebuild server code diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index d15b3f972..9a9c6a8e7 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -5151,6 +5151,7 @@ void bot_subcommand_bot_summon(Client *c, const Seperator *sep) bot_iter->WipeHateList(); bot_iter->SetTarget(bot_iter->GetBotOwner()); bot_iter->Warp(glm::vec3(c->GetPosition())); + bot_iter->DoAnim(0); if (!bot_iter->HasPet()) continue; From 12d7f242b4aa5af980cc29966c6c27a74130c8e2 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 1 Mar 2017 16:11:17 -0500 Subject: [PATCH 598/693] Tweaked bot caster combat range code a little (they shouldn't pile up unless there are los issues...) --- zone/bot.cpp | 54 ++++++++++++++++++++++++++++++++-------------------- zone/bot.h | 2 +- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index eaba1aeea..172ac3d5d 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2156,7 +2156,7 @@ void Bot::AI_Process() { if(GetHasBeenSummoned()) { if(IsBotCaster() || IsBotArcher()) { if (AI_movement_timer->Check()) { - if(!GetTarget() || (IsBotCaster() && !IsBotCasterCombatRange(GetTarget())) || (IsBotArcher() && IsArcheryRange(GetTarget())) || (DistanceSquaredNoZ(static_cast(m_Position), m_PreSummonLocation) < 10)) { + if(!GetTarget() || (IsBotCaster() && !IsBotCasterAtCombatRange(GetTarget())) || (IsBotArcher() && IsArcheryRange(GetTarget())) || (DistanceSquaredNoZ(static_cast(m_Position), m_PreSummonLocation) < 10)) { if(GetTarget()) FaceTarget(GetTarget()); @@ -2293,23 +2293,24 @@ void Bot::AI_Process() { ChangeBotArcherWeapons(IsBotArcher()); } - if(IsBotArcher() && atArcheryRange) { - if(IsMoving()) { + if (IsBotArcher() && atArcheryRange) { + if (IsMoving()) { SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); SetRunAnimSpeed(0); SetCurrentSpeed(0); - if(moved) { + if (moved) { moved = false; SetCurrentSpeed(0); } } atCombatRange = true; - } else if(IsBotCaster() && GetLevel() >= RuleI(Bots, CasterStopMeleeLevel)) { - if(IsBotCasterCombatRange(GetTarget())) - atCombatRange = true; } - else if(DistanceSquared(m_Position, GetTarget()->GetPosition()) <= meleeDistance) + else if (GetLevel() >= RuleI(Bots, CasterStopMeleeLevel) && IsBotCasterAtCombatRange(GetTarget())) { atCombatRange = true; + } + else if (DistanceSquared(m_Position, GetTarget()->GetPosition()) <= meleeDistance) { + atCombatRange = true; + } if(atCombatRange) { if(IsMoving()) { @@ -6856,20 +6857,31 @@ bool Bot::IsArcheryRange(Mob *target) { return result; } -bool Bot::IsBotCasterCombatRange(Mob *target) { - bool result = false; - if(target) { - float range = BotAISpellRange; - range *= range; - range *= .5; - float targetDistance = DistanceSquaredNoZ(m_Position, target->GetPosition()); - if(targetDistance > range) - result = false; - else - result = true; - } +bool Bot::IsBotCasterAtCombatRange(Mob *target) +{ + static const float local[PLAYER_CLASS_COUNT] = { + 0.0f, // WARRIOR + 1156.0f, // CLERIC as DSq value (34 units) + 0.0f, 0.0f, 0.0f, // PALADIN, RANGER, SHADOWKNIGHT + 1764.0f, // DRUID as DSq value (42 units) + 0.0f, 0.0f, 0.0f, // MONK, BARD, ROGUE + 1444.0f, // SHAMAN as DSq value (38 units) + 2916.0f, // NECROMANCER as DSq value (54 units) + 2304.0f, // WIZARD as DSq value (48 units) + 2704.0f, // MAGICIAN as DSq value (52 units) + 2500.0f, // ENCHANTER as DSq value (50 units) + 0.0f, 0.0f // BEASTLORD, BERSERKER + }; - return result; + if (!target) + return false; + if (GetClass() < WARRIOR || GetClass() > BERSERKER) + return false; + + float targetDistance = DistanceSquaredNoZ(m_Position, target->GetPosition()); + if (targetDistance < local[GetClass() - 1]) + return true; + return false; } void Bot::UpdateGroupCastingRoles(const Group* group, bool disband) diff --git a/zone/bot.h b/zone/bot.h index 7bfbf87d0..88ff654df 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -337,7 +337,7 @@ public: bool IsStanding(); int GetBotWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.786f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143 int GetBotRunspeed() const { return (int)((float)_GetRunSpeed() * 1.786f); } - bool IsBotCasterCombatRange(Mob *target); + bool IsBotCasterAtCombatRange(Mob *target); bool UseDiscipline(uint32 spell_id, uint32 target); uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets); bool GetNeedsCured(Mob *tar); From 5213e4c7d41b2973604787c35f95c85cc495bd3e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 1 Mar 2017 15:19:56 -0600 Subject: [PATCH 599/693] Remove table that doesn't exist anymore (PEQ Dumps) [skip ci] --- utils/sql/user_tables.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/sql/user_tables.txt b/utils/sql/user_tables.txt index a2fa028e7..9e35ac5e2 100644 --- a/utils/sql/user_tables.txt +++ b/utils/sql/user_tables.txt @@ -30,7 +30,6 @@ character_inspect_messages character_leadership_abilities character_activities character_alt_currency -character_backup character_buffs character_enabledtasks character_pet_buffs From 15af28720abda0316c7c3723d3bb464e0ef2b4d4 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 1 Mar 2017 19:16:02 -0500 Subject: [PATCH 600/693] Bad logic..not used anyways --- zone/bot.cpp | 15 --------------- zone/bot.h | 10 ++++------ 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 172ac3d5d..0fc7418e0 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -7621,21 +7621,6 @@ bool Bot::CheckLoreConflict(const EQEmu::ItemData* item) { return (m_inv.HasItemByLoreGroup(item->LoreGroup, invWhereWorn) != INVALID_INDEX); } -bool Bot::GroupHasClass(Group* group, uint8 classId) { - bool result = false; - - if(group) { - for(int counter = 0; counter < MAX_GROUP_MEMBERS; counter++) { - if(group->members[counter] && group->members[counter]->GetClass() & classId) { - result = true; - break; - } - } - } - - return result; -} - bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, float iRange, uint32 iSpellTypes) { if((iSpellTypes&SpellTypes_Detrimental) != 0) { Log.Out(Logs::General, Logs::Error, "Error: detrimental spells requested from AICheckCloseBeneficialSpells!!"); diff --git a/zone/bot.h b/zone/bot.h index 88ff654df..dea5dd8e8 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -461,10 +461,12 @@ public: static int32 GetDisciplineRecastTimer(Bot *caster, int timer_index); static bool CheckDisciplineRecastTimers(Bot *caster, int timer_index); static uint32 GetDisciplineRemainingTime(Bot *caster, int timer_index); + static std::list GetBotSpellsForSpellEffect(Bot* botCaster, int spellEffect); static std::list GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, int spellEffect, SpellTargetType targetType); static std::list GetBotSpellsBySpellType(Bot* botCaster, uint32 spellType); static std::list GetPrioritizedBotSpellsBySpellType(Bot* botCaster, uint32 spellType); + static BotSpell GetFirstBotSpellBySpellType(Bot* botCaster, uint32 spellType); static BotSpell GetBestBotSpellForFastHeal(Bot* botCaster); static BotSpell GetBestBotSpellForHealOverTime(Bot* botCaster); @@ -476,6 +478,7 @@ public: static BotSpell GetBestBotSpellForGroupHeal(Bot* botCaster); static BotSpell GetBestBotSpellForMagicBasedSlow(Bot* botCaster); static BotSpell GetBestBotSpellForDiseaseBasedSlow(Bot* botCaster); + static Mob* GetFirstIncomingMobToMez(Bot* botCaster, BotSpell botSpell); static BotSpell GetBestBotSpellForMez(Bot* botCaster); static BotSpell GetBestBotMagicianPetSpell(Bot* botCaster); @@ -486,17 +489,12 @@ public: static BotSpell GetDebuffBotSpell(Bot* botCaster, Mob* target); static BotSpell GetBestBotSpellForCure(Bot* botCaster, Mob* target); static BotSpell GetBestBotSpellForResistDebuff(Bot* botCaster, Mob* target); + static NPCType CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender); // Static Bot Group Methods static bool AddBotToGroup(Bot* bot, Group* group); static bool RemoveBotFromGroup(Bot* bot, Group* group); - static bool GroupHasClass(Group* group, uint8 classId); - static bool GroupHasClericClass(Group* group) { return GroupHasClass(group, CLERIC); } - static bool GroupHasDruidClass(Group* group) { return GroupHasClass(group, DRUID); } - static bool GroupHasShamanClass(Group* group) { return GroupHasClass(group, SHAMAN); } - static bool GroupHasEnchanterClass(Group* group) { return GroupHasClass(group, ENCHANTER); } - static bool GroupHasPriestClass(Group* group) { return GroupHasClass(group, CLERIC | DRUID | SHAMAN); } static void BotGroupSay(Mob *speaker, const char *msg, ...); // "GET" Class Methods From 7d13475bac68b873e36133f3190d21df10686f02 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 2 Mar 2017 14:31:48 -0500 Subject: [PATCH 601/693] Fix ClearAggro xtarget issue --- zone/entity.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index 9f23f63a4..2bc1b99ed 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2980,10 +2980,16 @@ void EntityList::Evade(Mob *who) //removes "targ" from all hate lists, including feigned, in the zone void EntityList::ClearAggro(Mob* targ) { + Client *c = nullptr; + if (targ->IsClient()) + c = targ->CastToClient(); auto it = npc_list.begin(); while (it != npc_list.end()) { - if (it->second->CheckAggro(targ)) + if (it->second->CheckAggro(targ)) { + if (c) + c->RemoveXTarget(it->second, false); it->second->RemoveFromHateList(targ); + } it->second->RemoveFromFeignMemory(targ->CastToClient()); //just in case we feigned ++it; } From 2690d8fed8a054b801e530f698c4262795900f78 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 3 Mar 2017 17:51:02 -0500 Subject: [PATCH 602/693] Added inspect buff cases for bots (ZombieSoul) --- zone/client_packet.cpp | 22 ++++++++++++++++++---- zone/spell_effects.cpp | 8 ++++++-- zone/spells.cpp | 8 ++++++-- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 5411dbf7a..d7d8bdd0e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -3895,10 +3895,19 @@ void Client::Handle_OP_BuffRemoveRequest(const EQApplicationPacket *app) Mob *m = nullptr; - if (brrs->EntityID == GetID()) + if (brrs->EntityID == GetID()) { m = this; - else if (brrs->EntityID == GetPetID()) + } + else if (brrs->EntityID == GetPetID()) { m = GetPet(); + } +#ifdef BOTS + else { + Mob* bot_test = entity_list.GetMob(brrs->EntityID); + if (bot_test && bot_test->IsBot() && bot_test->GetOwner() == this) + m = bot_test; + } +#endif if (!m) return; @@ -13042,9 +13051,14 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app) } } if (GetGM() || RuleB(Spells, AlwaysSendTargetsBuffs) || nt == this || inspect_buffs || (nt->IsClient() && !nt->CastToClient()->GetPVP()) || - (nt->IsPet() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP()) || - (nt->IsMerc() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP())) + (nt->IsPet() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP()) || +#ifdef BOTS + (nt->IsBot() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP()) || // TODO: bot pets +#endif + (nt->IsMerc() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP())) + { nt->SendBuffsToClient(this); + } } else { diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index a2841ee8e..132e6bcdb 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -4155,8 +4155,12 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) if(IsPet() && GetOwner() && GetOwner()->IsClient()) { SendPetBuffsToClient(); } - if((IsClient() && !CastToClient()->GetPVP()) || (IsPet() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP()) || - (IsMerc() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP())) + if((IsClient() && !CastToClient()->GetPVP()) || + (IsPet() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP()) || +#ifdef BOTS + (IsBot() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP()) || +#endif + (IsMerc() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP())) { EQApplicationPacket *outapp = MakeBuffsPacket(); diff --git a/zone/spells.cpp b/zone/spells.cpp index f37f2fc53..0961b3404 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3290,8 +3290,12 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid if (IsPet() && GetOwner() && GetOwner()->IsClient()) SendPetBuffsToClient(); - if((IsClient() && !CastToClient()->GetPVP()) || (IsPet() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP()) || - (IsMerc() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP())) + if((IsClient() && !CastToClient()->GetPVP()) || + (IsPet() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP()) || +#ifdef BOTS + (IsBot() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP()) || +#endif + (IsMerc() && GetOwner() && GetOwner()->IsClient() && !GetOwner()->CastToClient()->GetPVP())) { EQApplicationPacket *outapp = MakeBuffsPacket(); From d559e9da1045c9fe69217a94361167862a229dcb Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 4 Mar 2017 14:50:32 -0500 Subject: [PATCH 603/693] Fix for bot auto-combat damage (please post any abnormalities) --- zone/attack.cpp | 7 +++++-- zone/bot.cpp | 29 +++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index dc50f23db..c89f217bd 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1301,9 +1301,12 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b my_hit.min_damage = 0; uint8 mylevel = GetLevel() ? GetLevel() : 1; uint32 hate = 0; - if (weapon) hate = weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt; + if (weapon) + hate = (weapon->GetItem()->Damage + weapon->GetItem()->ElemDmgAmt); + my_hit.base_damage = GetWeaponDamage(other, weapon, &hate); - if (hate == 0 && my_hit.base_damage > 1) hate = my_hit.base_damage; + if (hate == 0 && my_hit.base_damage > 1) + hate = my_hit.base_damage; //if weapon damage > 0 then we know we can hit the target with this weapon //otherwise we cannot and we set the damage to -5 later on diff --git a/zone/bot.cpp b/zone/bot.cpp index 0fc7418e0..06a25af78 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3693,11 +3693,22 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b return false; } - if(!GetTarget() || GetTarget() != other) - SetTarget(other); + if ((GetHP() <= 0) || (GetAppearance() == eaDead)) { + SetTarget(nullptr); + Log.Out(Logs::Detail, Logs::Combat, "Attempted to attack %s while unconscious or, otherwise, appearing dead", other->GetCleanName()); + return false; + } - Log.Out(Logs::Detail, Logs::Combat, "Attacking %s with hand %d %s", other?other->GetCleanName():"(nullptr)", Hand, FromRiposte?"(this is a riposte)":""); - if ((IsCasting() && (GetClass() != BARD) && !IsFromSpell) || other == nullptr || (GetHP() < 0) || (GetAppearance() == eaDead) || (!IsAttackAllowed(other))) { + //if(!GetTarget() || GetTarget() != other) // NPC::Attack() doesn't do this + // SetTarget(other); + + // apparently, we always want our target to be 'other'..why not just set it? + SetTarget(other); + // takes more to compare a call result, load for a call, load a compare to address and compare, and finally + // push a value to an address than to just load for a call and push a value to an address. + + Log.Out(Logs::Detail, Logs::Combat, "Attacking %s with hand %d %s", other->GetCleanName(), Hand, (FromRiposte ? "(this is a riposte)" : "")); + if ((IsCasting() && (GetClass() != BARD) && !IsFromSpell) || (!IsAttackAllowed(other))) { if(this->GetOwnerID()) entity_list.MessageClose(this, 1, 200, 10, "%s says, '%s is not a legal target master.'", this->GetCleanName(), this->GetTarget()->GetCleanName()); @@ -3740,8 +3751,10 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b DamageHitInfo my_hit; AttackAnimation(my_hit.skill, Hand, weapon); Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, my_hit.skill); - /// Now figure out damage - my_hit.damage_done =0; + + // Now figure out damage + my_hit.damage_done = 0; + my_hit.min_damage = 0; uint8 mylevel = GetLevel() ? GetLevel() : 1; uint32 hate = 0; if (weapon) @@ -3787,6 +3800,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b Log.Out(Logs::Detail, Logs::Combat, "Damage calculated: base %d min damage %d skill %d", my_hit.base_damage, my_hit.min_damage, my_hit.skill); + int hit_chance_bonus = 0; my_hit.offense = offense(my_hit.skill); my_hit.hand = Hand; @@ -3795,8 +3809,11 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b my_hit.base_damage += opts->damage_flat; hate *= opts->hate_percent; hate += opts->hate_flat; + hit_chance_bonus += opts->hit_chance; } + my_hit.tohit = GetTotalToHit(my_hit.skill, hit_chance_bonus); + DoAttack(other, my_hit, opts); Log.Out(Logs::Detail, Logs::Combat, "Final damage after all reductions: %d", my_hit.damage_done); From becd7b5c2492bc8d9667fb9e665fa9a36abb9cba Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 5 Mar 2017 05:12:54 -0500 Subject: [PATCH 604/693] This probably resolves a long-term bug with bots who are conscientious objectors to fighting... (Had a rash of reports concerning this -- obscure attack timer bug within inherited NPC class ctor) --- zone/bot.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 06a25af78..6a3e774b0 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -5444,7 +5444,7 @@ void Bot::SetAttackTimer() { } speed = (RuleB(Spells, Jun182014HundredHandsRevamp) ? static_cast(((delay / haste_mod) + ((hhe / 1000.0f) * (delay / haste_mod))) * 100) : static_cast(((delay / haste_mod) + ((hhe / 100.0f) * delay)) * 100)); - TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true); + TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true, true); if (i == EQEmu::inventory::slotPrimary) PrimaryWeapon = ItemToUse; From f26b7a4adc83ff6bd390948ac0593b05a54cefec Mon Sep 17 00:00:00 2001 From: Drajor Date: Wed, 8 Mar 2017 06:22:17 +1000 Subject: [PATCH 605/693] Hacky fix for quantity wrapping when stacked items are sold that have a quantity greater than 255. A better solution will need to implemented long term --- zone/client_packet.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index d7d8bdd0e..d4404247e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -12567,8 +12567,25 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) // Now remove the item from the player, this happens regardless of outcome if (!inst->IsStackable()) this->DeleteItemInInventory(mp->itemslot, 0, false); - else - this->DeleteItemInInventory(mp->itemslot, mp->quantity, false); + else { + // HACK: DeleteItemInInventory uses int8 for quantity type. There is no consistent use of types in code in this path so for now iteratively delete from inventory. + if (mp->quantity > 255) { + uint32 temp = mp->quantity; + while (temp > 255 && temp != 0) { + // Delete chunks of 255 + this->DeleteItemInInventory(mp->itemslot, 255, false); + temp -= 255; + } + if (temp != 0) { + // Delete remaining + this->DeleteItemInInventory(mp->itemslot, temp, false); + } + } + else { + this->DeleteItemInInventory(mp->itemslot, mp->quantity, false); + } + } + //This forces the price to show up correctly for charged items. if (inst->IsCharged()) From 09bbfbcc314157e3897a44c9b303bf37d43d7e05 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 8 Mar 2017 08:12:04 -0500 Subject: [PATCH 606/693] Complete rework of the bot trading system (see changelog.txt) --- changelog.txt | 15 + common/inventory_profile.cpp | 31 +- common/inventory_profile.h | 2 +- zone/bot.cpp | 614 ++++++++++++++++++++++------------- zone/bot.h | 2 +- 5 files changed, 416 insertions(+), 248 deletions(-) diff --git a/changelog.txt b/changelog.txt index 208cb0585..76fc0740e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,20 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/08/2017 == +Uleat: Complete rework of the bot trading system + - Equipment slot priority can now be tailored..though, a recompile will be required + - All item validations and slot assignments for trades and returns are now performed before any actual item movements occur + - Failed trade/returned items will now go straight into the client's inventory, just like a normal trade transaction + - A 'green' message appears at the end of each successful trade informing the trader of 'accepted' and 'returned' item counts + - Bots respond to the trader directly now instead of using BotGroupSay() + - Bots will still only allow trades from their owner (currently, too high a risk of exploit and/or malicious activity) + - Partial stack movements (i.e., ammo refills) have been scoped..but, not implemented + - I have not been able to reproduce any 'illegal' weapon combinations with this code + - NOTE: The report of item duplication with bot return items appears to be an inventory desync condition + - I experienced this condition both before and after the rework with RoF+ clients (UF- appears ok) + - The bug lies within the actual client inventory system and not with bot trades + - Please post any issues with this change as they arise + == 02/27/2017 == Uleat: Notes on bot movement speed changes: - Clients (players) appear to be on a different speed scale than other entities (NPCs, etc...) diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index ae17a2a17..7c97be706 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -635,18 +635,23 @@ int16 EQEmu::InventoryProfile::FindFreeSlot(bool for_bag, bool try_cursor, uint8 } // This is a mix of HasSpaceForItem and FindFreeSlot..due to existing coding behavior, it was better to add a new helper function... -int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst) { +int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start, int16 bag_start) { // Do not arbitrarily use this function..it is designed for use with Client::ResetTrade() and Client::FinishTrade(). - // If you have a need, use it..but, understand it is not a compatible replacement for InventoryProfile::FindFreeSlot(). + // If you have a need, use it..but, understand it is not a suitable replacement for InventoryProfile::FindFreeSlot(). // // I'll probably implement a bitmask in the new inventory system to avoid having to adjust stack bias + if ((general_start < legacy::GENERAL_BEGIN) || (general_start > legacy::GENERAL_END)) + return INVALID_INDEX; + if ((bag_start < inventory::containerBegin) || (bag_start >= inventory::ContainerCount)) + return INVALID_INDEX; + if (!inst || !inst->GetID()) return INVALID_INDEX; // step 1: find room for bags (caller should really ask for slots for bags first to avoid sending them to cursor..and bag item loss) if (inst->IsClassBag()) { - for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + for (int16 free_slot = general_start; free_slot <= legacy::GENERAL_END; ++free_slot) { if (!m_inv[free_slot]) return free_slot; } @@ -656,7 +661,7 @@ int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst // step 2: find partial room for stackables if (inst->IsStackable()) { - for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + for (int16 free_slot = general_start; free_slot <= legacy::GENERAL_END; ++free_slot) { const ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst) @@ -666,14 +671,14 @@ int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst return free_slot; } - for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + for (int16 free_slot = general_start; free_slot <= legacy::GENERAL_END; ++free_slot) { const ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst) continue; if (main_inst->IsClassBag()) { // if item-specific containers already have bad items, we won't fix it here... - for (uint8 free_bag_slot = inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { + for (uint8 free_bag_slot = bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { const ItemInstance* sub_inst = main_inst->GetItem(free_bag_slot); if (!sub_inst) @@ -688,13 +693,13 @@ int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst // step 3a: find room for container-specific items (ItemClassArrow) if (inst->GetItem()->ItemType == item::ItemTypeArrow) { - for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + for (int16 free_slot = general_start; free_slot <= legacy::GENERAL_END; ++free_slot) { const ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst || (main_inst->GetItem()->BagType != item::BagTypeQuiver) || !main_inst->IsClassBag()) continue; - for (uint8 free_bag_slot = inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { + for (uint8 free_bag_slot = bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); } @@ -703,13 +708,13 @@ int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst // step 3b: find room for container-specific items (ItemClassSmallThrowing) if (inst->GetItem()->ItemType == item::ItemTypeSmallThrowing) { - for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + for (int16 free_slot = general_start; free_slot <= legacy::GENERAL_END; ++free_slot) { const ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst || (main_inst->GetItem()->BagType != item::BagTypeBandolier) || !main_inst->IsClassBag()) continue; - for (uint8 free_bag_slot = inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { + for (uint8 free_bag_slot = bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); } @@ -717,21 +722,21 @@ int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst } // step 4: just find an empty slot - for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + for (int16 free_slot = general_start; free_slot <= legacy::GENERAL_END; ++free_slot) { const ItemInstance* main_inst = m_inv[free_slot]; if (!main_inst) return free_slot; } - for (int16 free_slot = legacy::GENERAL_BEGIN; free_slot <= legacy::GENERAL_END; ++free_slot) { + for (int16 free_slot = general_start; free_slot <= legacy::GENERAL_END; ++free_slot) { const ItemInstance* main_inst = m_inv[free_slot]; if (main_inst && main_inst->IsClassBag()) { if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == item::BagTypeBandolier) || (main_inst->GetItem()->BagType == item::BagTypeQuiver)) continue; - for (uint8 free_bag_slot = inventory::containerBegin; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { + for (uint8 free_bag_slot = bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); } diff --git a/common/inventory_profile.h b/common/inventory_profile.h index b9ae1db8c..7bb659cff 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -155,7 +155,7 @@ namespace EQEmu // Locate an available inventory slot int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false); - int16 FindFreeSlotForTradeItem(const ItemInstance* inst); + int16 FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start = legacy::GENERAL_BEGIN, int16 bag_start = inventory::containerBegin); // Calculate slot_id for an item within a bag static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id diff --git a/zone/bot.cpp b/zone/bot.cpp index 6a3e774b0..32796b88b 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3225,21 +3225,20 @@ void Bot::BotAddEquipItem(int slot, uint32 id) { } // Erases the specified item from bot the NPC equipment array and from the bot inventory collection. -void Bot::BotRemoveEquipItem(int slot) { - if(slot > 0) { - uint8 materialFromSlot = EQEmu::InventoryProfile::CalcMaterialFromSlot(slot); +void Bot::BotRemoveEquipItem(int16 slot) +{ + uint8 material_slot = EQEmu::InventoryProfile::CalcMaterialFromSlot(slot); - if (materialFromSlot != EQEmu::textures::materialInvalid) { - equipment[slot] = 0; // npc has more than just material slots. Valid material should mean valid inventory index - SendWearChange(materialFromSlot); - if (materialFromSlot == EQEmu::textures::armorChest) - SendWearChange(EQEmu::textures::armorArms); - } - - UpdateEquipmentLight(); - if (UpdateActiveLight()) - SendAppearancePacket(AT_Light, GetActiveLightType()); + if (material_slot != EQEmu::textures::materialInvalid) { + equipment[slot] = 0; // npc has more than just material slots. Valid material should mean valid inventory index + SendWearChange(material_slot); + if (material_slot == EQEmu::textures::armorChest) + SendWearChange(EQEmu::textures::armorArms); } + + UpdateEquipmentLight(); + if (UpdateActiveLight()) + SendAppearancePacket(AT_Light, GetActiveLightType()); } void Bot::BotTradeSwapItem(Client* client, int16 lootSlot, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap) { @@ -3326,243 +3325,392 @@ bool Bot::AddBotToGroup(Bot* bot, Group* group) { } // Completes a trade with a client bot owner -void Bot::FinishTrade(Client* client, BotTradeType tradeType) { - if(client && !client->GetTradeskillObject() && (client->trade->state != Trading)) { - if(tradeType == BotTradeClientNormal) { - // Items being traded are found in the normal trade window used to trade between a Client and a Client or NPC - // Items in this mode are found in slot ids 3000 thru 3003 - thought bots used the full 8-slot window..? - PerformTradeWithClient(EQEmu::legacy::TRADE_BEGIN, EQEmu::legacy::TRADE_END, client); // {3000..3007} - } - else if(tradeType == BotTradeClientNoDropNoTrade) { - // Items being traded are found on the Client's cursor slot, slot id 30. This item can be either a single item or it can be a bag. - // If it is a bag, then we have to search for items in slots 331 thru 340 - PerformTradeWithClient(EQEmu::inventory::slotCursor, EQEmu::inventory::slotCursor, client); +void Bot::FinishTrade(Client* client, BotTradeType tradeType) +{ + if (!client || (GetOwner() != client) || client->GetTradeskillObject() || client->trade->state == Trading) { + if (client) + client->ResetTrade(); + return; + } - // TODO: Add logic here to test if the item in SLOT_CURSOR is a container type, if it is then we need to call the following: - // PerformTradeWithClient(331, 340, client); - } + // these notes are not correct or obselete + if (tradeType == BotTradeClientNormal) { + // Items being traded are found in the normal trade window used to trade between a Client and a Client or NPC + // Items in this mode are found in slot ids 3000 thru 3003 - thought bots used the full 8-slot window..? + PerformTradeWithClient(EQEmu::legacy::TRADE_BEGIN, EQEmu::legacy::TRADE_END, client); // {3000..3007} + } + else if (tradeType == BotTradeClientNoDropNoTrade) { + // Items being traded are found on the Client's cursor slot, slot id 30. This item can be either a single item or it can be a bag. + // If it is a bag, then we have to search for items in slots 331 thru 340 + PerformTradeWithClient(EQEmu::inventory::slotCursor, EQEmu::inventory::slotCursor, client); + + // TODO: Add logic here to test if the item in SLOT_CURSOR is a container type, if it is then we need to call the following: + // PerformTradeWithClient(331, 340, client); } } // Perfoms the actual trade action with a client bot owner -void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client) { - if(client) { - // TODO: Figure out what the actual max slot id is - const int MAX_SLOT_ID = EQEmu::legacy::TRADE_BAGS_END; // was the old incorrect 3179.. - uint32 items[MAX_SLOT_ID] = {0}; - uint8 charges[MAX_SLOT_ID] = {0}; - bool botCanWear[MAX_SLOT_ID] = {0}; +void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client) +{ + using namespace EQEmu; - for(int16 i = beginSlotID; i <= endSlotID; ++i) { - bool BotCanWear = false; - bool UpdateClient = false; - bool already_returned = false; + struct ClientTrade { + const ItemInstance* tradeItemInstance; + int16 fromClientSlot; + int16 toBotSlot; + int adjustStackSize; + + ClientTrade(const ItemInstance* item, int16 from) : tradeItemInstance(item), fromClientSlot(from), toBotSlot(legacy::SLOT_INVALID), adjustStackSize(0) { } + }; - EQEmu::InventoryProfile& clientInventory = client->GetInv(); - const EQEmu::ItemInstance* inst = clientInventory[i]; - if(inst) { - items[i] = inst->GetItem()->ID; - charges[i] = inst->GetCharges(); - } + struct ClientReturn { + const ItemInstance* returnItemInstance; + int16 fromBotSlot; + int16 toClientSlot; + int adjustStackSize; + + ClientReturn(const ItemInstance* item, int16 from) : returnItemInstance(item), fromBotSlot(from), toClientSlot(legacy::SLOT_INVALID), adjustStackSize(0) { } + }; - if (i == EQEmu::inventory::slotCursor) - UpdateClient = true; + static const int16 proxyPowerSource = 22; - //EQoffline: will give the items to the bots and change the bot stats - if(inst && (GetBotOwner() == client->CastToMob()) && !IsEngaged()) { - std::string TempErrorMessage; - const EQEmu::ItemData* mWeaponItem = inst->GetItem(); - bool failedLoreCheck = false; - for (int m = EQEmu::inventory::socketBegin; m < EQEmu::inventory::SocketCount; ++m) { - EQEmu::ItemInstance *itm = inst->GetAugment(m); - if(itm) - { - if(CheckLoreConflict(itm->GetItem())) { - failedLoreCheck = true; - } - } - } - if(CheckLoreConflict(mWeaponItem)) { - failedLoreCheck = true; - } - if(failedLoreCheck) { - Message_StringID(0, DUP_LORE); - } - if(!failedLoreCheck && mWeaponItem && inst->IsEquipable(GetBaseRace(), GetClass()) && (GetLevel() >= mWeaponItem->ReqLevel)) { - BotCanWear = true; - botCanWear[i] = BotCanWear; - EQEmu::ItemInstance* swap_item = nullptr; + static const int16 bot_equip_order[(legacy::EQUIPMENT_SIZE + 1)] = { + inventory::slotCharm, inventory::slotEar1, inventory::slotHead, inventory::slotFace, + inventory::slotEar2, inventory::slotNeck, inventory::slotShoulders, inventory::slotArms, + inventory::slotBack, inventory::slotWrist1, inventory::slotWrist2, inventory::slotRange, + inventory::slotHands, inventory::slotPrimary, inventory::slotSecondary, inventory::slotFinger1, + inventory::slotFinger2, inventory::slotChest, inventory::slotLegs, inventory::slotFeet, + inventory::slotWaist, inventory::slotAmmo, proxyPowerSource // inventory::slotPowerSource + }; - const char* equipped[EQEmu::legacy::EQUIPMENT_SIZE + 1] = { "Charm", "Left Ear", "Head", "Face", "Right Ear", "Neck", "Shoulders", "Arms", "Back", - "Left Wrist", "Right Wrist", "Range", "Hands", "Primary Hand", "Secondary Hand", - "Left Finger", "Right Finger", "Chest", "Legs", "Feet", "Waist", "Ammo", "Powersource" }; - bool success = false; - int how_many_slots = 0; - for (int j = EQEmu::legacy::EQUIPMENT_BEGIN; j <= (EQEmu::legacy::EQUIPMENT_END + 1); ++j) { - if((mWeaponItem->Slots & (1 << j))) { - if (j == 22) - j = 9999; + enum { stageStackable = 0, stageEmpty, stageReplaceable }; + + if (!client) { + Emote("NO CLIENT"); + return; + } - how_many_slots++; - if(!GetBotItem(j)) { - if (j == EQEmu::inventory::slotPrimary) { - if (mWeaponItem->IsType2HWeapon()) { - if (GetBotItem(EQEmu::inventory::slotSecondary)) { - if (mWeaponItem && mWeaponItem->IsType2HWeapon()) { - if (client->CheckLoreConflict(GetBotItem(EQEmu::inventory::slotSecondary)->GetItem())) { - failedLoreCheck = true; - } - } - else { - EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::inventory::slotSecondary); - BotTradeSwapItem(client, EQEmu::inventory::slotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); - } - } - } - if(!failedLoreCheck) { - BotTradeAddItem(mWeaponItem->ID, inst, inst->GetCharges(), mWeaponItem->Slots, j, &TempErrorMessage); - success = true; - } - break; - } - else if (j == EQEmu::inventory::slotSecondary) { - if(inst->IsWeapon()) { - if(CanThisClassDualWield()) { - BotTradeAddItem(mWeaponItem->ID, inst, inst->GetCharges(), mWeaponItem->Slots, j, &TempErrorMessage); - success = true; - } - else { - BotGroupSay(this, "I can't Dual Wield yet."); - --how_many_slots; - } - } - else { - BotTradeAddItem(mWeaponItem->ID, inst, inst->GetCharges(), mWeaponItem->Slots, j, &TempErrorMessage); - success = true; - } - if(success) { - if (GetBotItem(EQEmu::inventory::slotPrimary)) { - EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::inventory::slotPrimary); - if (remove_item->GetItem()->IsType2HWeapon()) { - BotTradeSwapItem(client, EQEmu::inventory::slotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); - } - } - break; - } - } - else { - BotTradeAddItem(mWeaponItem->ID, inst, inst->GetCharges(), mWeaponItem->Slots, j, &TempErrorMessage); - success = true; - break; - } - } - } - } - if(!success) { - for (int j = EQEmu::legacy::EQUIPMENT_BEGIN; j <= (EQEmu::legacy::EQUIPMENT_END + 1); ++j) { - if((mWeaponItem->Slots & (1 << j))) { - if (j == 22) - j = 9999; + if (client != GetOwner()) { + client->Message(CC_Red, "You are not the owner of this bot - Trade Canceled."); + client->ResetTrade(); + return; + } + if ((beginSlotID != legacy::TRADE_BEGIN) && (beginSlotID != inventory::slotCursor)) { + client->Message(CC_Red, "Trade request processing from illegal 'begin' slot - Trade Canceled."); + client->ResetTrade(); + return; + } + if ((endSlotID != legacy::TRADE_END) && (endSlotID != inventory::slotCursor)) { + client->Message(CC_Red, "Trade request processing from illegal 'end' slot - Trade Canceled."); + client->ResetTrade(); + return; + } + if (((beginSlotID == inventory::slotCursor) && (endSlotID != inventory::slotCursor)) || ((beginSlotID != inventory::slotCursor) && (endSlotID == inventory::slotCursor))) { + client->Message(CC_Red, "Trade request processing illegal slot range - Trade Canceled."); + client->ResetTrade(); + return; + } + if (endSlotID < beginSlotID) { + client->Message(CC_Red, "Trade request processing in reverse slot order - Trade Canceled."); + client->ResetTrade(); + return; + } + if (client->IsEngaged() || IsEngaged()) { + client->Message(CC_Yellow, "You may not perform a trade while engaged - Trade Canceled!"); + client->ResetTrade(); + return; + } - swap_item = GetBotItem(j); - failedLoreCheck = false; - for (int k = EQEmu::inventory::socketBegin; k < EQEmu::inventory::SocketCount; ++k) { - EQEmu::ItemInstance *itm = swap_item->GetAugment(k); - if(itm) - { - if(client->CheckLoreConflict(itm->GetItem())) { - failedLoreCheck = true; - } - } - } - if(client->CheckLoreConflict(swap_item->GetItem())) { - failedLoreCheck = true; - } - if(!failedLoreCheck) { - if (j == EQEmu::inventory::slotPrimary) { - if (mWeaponItem->IsType2HWeapon()) { - if (GetBotItem(EQEmu::inventory::slotSecondary)) { - if (client->CheckLoreConflict(GetBotItem(EQEmu::inventory::slotSecondary)->GetItem())) { - failedLoreCheck = true; - } - else { - EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::inventory::slotSecondary); - BotTradeSwapItem(client, EQEmu::inventory::slotSecondary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); - } - } - } - if(!failedLoreCheck) { - BotTradeSwapItem(client, EQEmu::inventory::slotPrimary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); - success = true; - } - break; - } - else if (j == EQEmu::inventory::slotSecondary) { - if(inst->IsWeapon()) { - if(CanThisClassDualWield()) { - BotTradeSwapItem(client, EQEmu::inventory::slotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); - success = true; - } - else { - botCanWear[i] = false; - BotGroupSay(this, "I can't Dual Wield yet."); - } - } - else { - BotTradeSwapItem(client, EQEmu::inventory::slotSecondary, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); - success = true; - } - if (success && GetBotItem(EQEmu::inventory::slotPrimary)) { - EQEmu::ItemInstance* remove_item = GetBotItem(EQEmu::inventory::slotPrimary); - if (remove_item->GetItem()->IsType2HWeapon()) { - BotTradeSwapItem(client, EQEmu::inventory::slotPrimary, 0, remove_item, remove_item->GetItem()->Slots, &TempErrorMessage, false); - } - } - break; - } - else { - BotTradeSwapItem(client, j, inst, swap_item, mWeaponItem->Slots, &TempErrorMessage); - success = true; - break; - } - } - else { - botCanWear[i] = false; - Message_StringID(0, PICK_LORE); - break; - } - } - } - } - if(success) { - if(how_many_slots > 1) { - Message(300, "If you want this item in a different slot, use #bot inventory remove to clear the spot."); - } - CalcBotStats(); - } - } - } - if(inst) { - client->DeleteItemInInventory(i, 0, UpdateClient); - if(!botCanWear[i]) { - client->PushItemOnCursor(*inst, true); - } - } + std::list client_trade; + std::list client_return; + + // pre-checks for incoming illegal transfers + for (int16 trade_index = beginSlotID; trade_index <= endSlotID; ++trade_index) { + auto trade_instance = client->GetInv()[trade_index]; + if (!trade_instance) + continue; + + if (!trade_instance->GetItem()) { + // TODO: add logging + client->Message(CC_Red, "A server error was encountered while processing client slot %i - Trade Canceled.", trade_index); + client->ResetTrade(); + return; + } + if ((trade_index != inventory::slotCursor) && !trade_instance->IsDroppable()) { + // TODO: add logging + client->Message(CC_Red, "Trade hack detected - Trade Canceled."); + client->ResetTrade(); + return; + } + if (CheckLoreConflict(trade_instance->GetItem())) { + client->Message(CC_Yellow, "This bot already has lore equipment matching the item '%s' - Trade Canceled!", trade_instance->GetItem()->Name); + client->ResetTrade(); + return; } - const EQEmu::ItemData* item2 = 0; - for(int y = beginSlotID; y <= endSlotID; ++y) { - item2 = database.GetItem(items[y]); - if(item2) { - if(botCanWear[y]) { - BotGroupSay(this, "Thank you for the %s, %s!", item2->Name, client->GetName()); - } - else { - BotGroupSay(this, "I can't use this %s!", item2->Name); - } + if (!trade_instance->IsType(item::ItemClassCommon)) { + client_return.push_back(ClientReturn(trade_instance, trade_index)); + continue; + } + if (!trade_instance->IsEquipable(GetBaseRace(), GetClass()) || (GetLevel() < trade_instance->GetItem()->ReqLevel)) { + client_return.push_back(ClientReturn(trade_instance, trade_index)); + continue; + } + + client_trade.push_back(ClientTrade(trade_instance, trade_index)); + } + + // check for incoming lore hacks + for (auto& trade_iterator : client_trade) { + if (!trade_iterator.tradeItemInstance->GetItem()->LoreFlag) + continue; + + for (const auto& check_iterator : client_trade) { + if (check_iterator.fromClientSlot == trade_iterator.fromClientSlot) + continue; + if (!check_iterator.tradeItemInstance->GetItem()->LoreFlag) + continue; + + if ((trade_iterator.tradeItemInstance->GetItem()->LoreGroup == -1) && (check_iterator.tradeItemInstance->GetItem()->ID == trade_iterator.tradeItemInstance->GetItem()->ID)) { + // TODO: add logging + client->Message(CC_Red, "Trade hack detected - Trade Canceled."); + client->ResetTrade(); + return; + } + if ((trade_iterator.tradeItemInstance->GetItem()->LoreGroup > 0) && (check_iterator.tradeItemInstance->GetItem()->LoreGroup == trade_iterator.tradeItemInstance->GetItem()->LoreGroup)) { + // TODO: add logging + client->Message(CC_Red, "Trade hack detected - Trade Canceled."); + client->ResetTrade(); + return; } } } + + // find equipment slots + const bool can_dual_wield = CanThisClassDualWield(); + bool melee_2h_weapon = false; + bool melee_secondary = false; + + //for (unsigned stage_loop = stageStackable; stage_loop <= stageReplaceable; ++stage_loop) { // awaiting implementation + for (unsigned stage_loop = stageEmpty; stage_loop <= stageReplaceable; ++stage_loop) { + for (auto& trade_iterator : client_trade) { + if (trade_iterator.toBotSlot != legacy::SLOT_INVALID) + continue; + + auto trade_instance = trade_iterator.tradeItemInstance; + /*if ((stage_loop == stageStackable) && !trade_instance->IsStackable()) + continue;*/ + + for (auto index : bot_equip_order) { + if (!(trade_instance->GetItem()->Slots & (1 << index))) + continue; + + //if (stage_loop == stageStackable) { + // // TODO: implement + // continue; + //} + + if (stage_loop != stageReplaceable) { + if ((index == proxyPowerSource) && m_inv[inventory::slotPowerSource]) + continue; + else if (m_inv[index]) + continue; + } + + bool slot_taken = false; + for (const auto& check_iterator : client_trade) { + if (check_iterator.fromClientSlot == trade_iterator.fromClientSlot) + continue; + + if (check_iterator.toBotSlot == index) { + slot_taken = true; + break; + } + } + if (slot_taken) + continue; + + if (index == inventory::slotPrimary) { + if (trade_instance->GetItem()->IsType2HWeapon()) { + if (!melee_secondary) { + melee_2h_weapon = true; + + if (m_inv[inventory::slotSecondary]) + client_return.push_back(ClientReturn(m_inv[inventory::slotSecondary], inventory::slotSecondary)); + } + else { + continue; + } + } + } + if (index == inventory::slotSecondary) { + if (!melee_2h_weapon) { + if ((can_dual_wield && trade_instance->GetItem()->IsType1HWeapon()) || trade_instance->GetItem()->IsTypeShield() || !trade_instance->IsWeapon()) + melee_secondary = true; + else + continue; + } + else { + continue; + } + } + + if (index == proxyPowerSource) { + trade_iterator.toBotSlot = inventory::slotPowerSource; + + if (m_inv[inventory::slotPowerSource]) + client_return.push_back(ClientReturn(m_inv[inventory::slotPowerSource], inventory::slotPowerSource)); + } + else { + trade_iterator.toBotSlot = index; + + if (m_inv[index]) + client_return.push_back(ClientReturn(m_inv[index], index)); + } + + break; + } + } + } + + // move unassignable items from trade list to return list + for (std::list::iterator trade_iterator = client_trade.begin(); trade_iterator != client_trade.end();) { + if (trade_iterator->toBotSlot == legacy::SLOT_INVALID) { + client_return.push_back(ClientReturn(trade_iterator->tradeItemInstance, trade_iterator->fromClientSlot)); + trade_iterator = client_trade.erase(trade_iterator); + continue; + } + ++trade_iterator; + } + + // out-going return checks for client + for (auto& return_iterator : client_return) { + auto return_instance = return_iterator.returnItemInstance; + if (!return_instance) + continue; + + if (!return_instance->GetItem()) { + // TODO: add logging + client->Message(CC_Red, "A server error was encountered while processing bot slot %i - Trade Canceled.", return_iterator.fromBotSlot); + client->ResetTrade(); + return; + } + if (client->CheckLoreConflict(return_instance->GetItem())) { + client->Message(CC_Yellow, "You already have lore equipment matching the item '%s' - Trade Canceled!", return_instance->GetItem()->Name); + client->ResetTrade(); + return; + } + + if (return_iterator.fromBotSlot == inventory::slotCursor) { + return_iterator.toClientSlot = inventory::slotCursor; + } + else { + int16 client_search_general = legacy::GENERAL_BEGIN; + int16 client_search_bag = inventory::containerBegin; + + bool run_search = true; + while (run_search) { + int16 client_test_slot = client->GetInv().FindFreeSlotForTradeItem(return_instance, client_search_general, client_search_bag); + if (client_test_slot == legacy::SLOT_INVALID) { + run_search = false; + continue; + } + + bool slot_taken = false; + for (const auto& check_iterator : client_return) { + if (check_iterator.fromBotSlot == return_iterator.fromBotSlot) + continue; + + if ((check_iterator.toClientSlot == client_test_slot) && (client_test_slot != inventory::slotCursor)) { + slot_taken = true; + break; + } + } + if (slot_taken) { + client_search_general = InventoryProfile::CalcSlotId(client_test_slot); + client_search_bag = InventoryProfile::CalcBagIdx(client_test_slot); + + ++client_search_bag; + if (client_search_bag >= inventory::ContainerCount) { + client_search_bag = inventory::containerBegin; + // incrementing this past legacy::GENERAL_END triggers the (client_test_slot == legacy::SLOT_INVALID) at the beginning of the search loop + // ideally, this will never occur because we always start fresh with each loop iteration and should receive SLOT_CURSOR as a return value + ++client_search_general; + } + continue; + } + + return_iterator.toClientSlot = client_test_slot; + run_search = false; + } + } + + if (return_iterator.toClientSlot == legacy::SLOT_INVALID) { + client->Message(CC_Yellow, "You do not have room to complete this trade - Trade Canceled!"); + client->ResetTrade(); + return; + } + } + + // perform actual trades + // returns first since clients have trade slots and bots do not + for (auto& return_iterator : client_return) { + // TODO: code for stackables + + if (return_iterator.fromBotSlot == inventory::slotCursor) { // failed trade return + // no movement action required + } + else if ((return_iterator.fromBotSlot >= legacy::TRADE_BEGIN) && (return_iterator.fromBotSlot <= legacy::TRADE_END)) { // failed trade returns + client->PutItemInInventory(return_iterator.toClientSlot, *return_iterator.returnItemInstance); + client->SendItemPacket(return_iterator.toClientSlot, return_iterator.returnItemInstance, ItemPacketTrade); + client->DeleteItemInInventory(return_iterator.fromBotSlot); + } + else { // successful trade returns + auto return_instance = m_inv.PopItem(return_iterator.fromBotSlot); + if (*return_instance != *return_iterator.returnItemInstance) { + // TODO: add logging + } + + if (!botdb.DeleteItemBySlot(GetBotID(), return_iterator.fromBotSlot)) + client->Message(CC_Red, "%s (slot: %i, name: '%s')", BotDatabase::fail::DeleteItemBySlot(), return_iterator.fromBotSlot, (return_instance ? return_instance->GetItem()->Name : "nullptr")); + + BotRemoveEquipItem(return_iterator.fromBotSlot); + client->PutItemInInventory(return_iterator.toClientSlot, *return_instance, true); + InventoryProfile::MarkDirty(return_instance); + } + return_iterator.returnItemInstance = nullptr; + } + + // trades can now go in as empty slot inserts + for (auto& trade_iterator : client_trade) { + // TODO: code for stackables + + if (!botdb.SaveItemBySlot(this, trade_iterator.toBotSlot, trade_iterator.tradeItemInstance)) + client->Message(CC_Red, "%s (slot: %i, name: '%s')", BotDatabase::fail::SaveItemBySlot(), trade_iterator.toBotSlot, (trade_iterator.tradeItemInstance ? trade_iterator.tradeItemInstance->GetItem()->Name : "nullptr")); + + m_inv.PutItem(trade_iterator.toBotSlot, *trade_iterator.tradeItemInstance); + this->BotAddEquipItem(trade_iterator.toBotSlot, (trade_iterator.tradeItemInstance ? trade_iterator.tradeItemInstance->GetID() : 0)); + client->DeleteItemInInventory(trade_iterator.fromClientSlot, 0, true); + trade_iterator.tradeItemInstance = nullptr; + } + + // trade announcements + for (const auto& return_iterator : client_return) { // item pointers should be nulled by this point + if (((return_iterator.fromBotSlot < legacy::TRADE_BEGIN) || (return_iterator.fromBotSlot > legacy::TRADE_END)) && (return_iterator.fromBotSlot != inventory::slotCursor)) + continue; + + if (client->GetInv()[return_iterator.toClientSlot]) + client->Message(MT_Tell, "%s tells you, \"%s, I can't use this '%s.'\"", GetCleanName(), client->GetName(), client->GetInv()[return_iterator.toClientSlot]->GetItem()->Name); + } + for (const auto& trade_iterator : client_trade) { // item pointers should be nulled by this point + if (m_inv[trade_iterator.toBotSlot]) + client->Message(MT_Tell, "%s tells you, \"Thank you for the '%s,' %s!\"", GetCleanName(), m_inv[trade_iterator.toBotSlot]->GetItem()->Name, client->GetName()); + } + + size_t accepted_count = client_trade.size(); + size_t returned_count = client_return.size(); + + client->Message(CC_Lime, "Trade with '%s' resulted in %i accepted item%s, %i returned item%s.", GetCleanName(), accepted_count, ((accepted_count == 1) ? "" : "s"), returned_count, ((returned_count == 1) ? "" : "s")); } bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { diff --git a/zone/bot.h b/zone/bot.h index dea5dd8e8..ca5a7e9ad 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -655,7 +655,7 @@ public: // Publicized private functions static NPCType FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack); - void BotRemoveEquipItem(int slot); + void BotRemoveEquipItem(int16 slot); void RemoveBotItemBySlot(uint32 slotID, std::string* errorMessage); uint32 GetTotalPlayTime(); From 999650d368c68507827595a11c0b45fade9d76d0 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 9 Mar 2017 01:55:01 -0500 Subject: [PATCH 607/693] Fixed a few glitches related to bot trading and other affected code --- changelog.txt | 7 ++++ common/inventory_profile.cpp | 16 +++++---- common/inventory_profile.h | 2 +- zone/bot.cpp | 63 +++++++++++++++++++++--------------- 4 files changed, 55 insertions(+), 33 deletions(-) diff --git a/changelog.txt b/changelog.txt index 76fc0740e..85ac6c97a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/09/2017 == +Uleat: Fixed a few glitches related to bot trading and other affected code + - Added a temporary fail clause for partial stack transfers to prevent client item overwrites + - Return messages no longer repeat the top cursor item when multiple items are pushed there + - Test slot for client returns is now handled appropriately for parent and bag searches + - FindFreeSlotForTradeItem() now begins at the correct bag index on subsequent parent iterations + == 03/08/2017 == Uleat: Complete rework of the bot trading system - Equipment slot priority can now be tailored..though, a recompile will be required diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index 7c97be706..480f4e98f 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -635,7 +635,7 @@ int16 EQEmu::InventoryProfile::FindFreeSlot(bool for_bag, bool try_cursor, uint8 } // This is a mix of HasSpaceForItem and FindFreeSlot..due to existing coding behavior, it was better to add a new helper function... -int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start, int16 bag_start) { +int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start, uint8 bag_start) { // Do not arbitrarily use this function..it is designed for use with Client::ResetTrade() and Client::FinishTrade(). // If you have a need, use it..but, understand it is not a suitable replacement for InventoryProfile::FindFreeSlot(). // @@ -643,7 +643,7 @@ int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst if ((general_start < legacy::GENERAL_BEGIN) || (general_start > legacy::GENERAL_END)) return INVALID_INDEX; - if ((bag_start < inventory::containerBegin) || (bag_start >= inventory::ContainerCount)) + if (bag_start >= inventory::ContainerCount) return INVALID_INDEX; if (!inst || !inst->GetID()) @@ -678,7 +678,8 @@ int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst continue; if (main_inst->IsClassBag()) { // if item-specific containers already have bad items, we won't fix it here... - for (uint8 free_bag_slot = bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { + uint8 _bag_start = (free_slot > general_start) ? inventory::containerBegin : bag_start; + for (uint8 free_bag_slot = _bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { const ItemInstance* sub_inst = main_inst->GetItem(free_bag_slot); if (!sub_inst) @@ -699,7 +700,8 @@ int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst if (!main_inst || (main_inst->GetItem()->BagType != item::BagTypeQuiver) || !main_inst->IsClassBag()) continue; - for (uint8 free_bag_slot = bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { + uint8 _bag_start = (free_slot > general_start) ? inventory::containerBegin : bag_start; + for (uint8 free_bag_slot = _bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); } @@ -714,7 +716,8 @@ int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst if (!main_inst || (main_inst->GetItem()->BagType != item::BagTypeBandolier) || !main_inst->IsClassBag()) continue; - for (uint8 free_bag_slot = bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { + uint8 _bag_start = (free_slot > general_start) ? inventory::containerBegin : bag_start; + for (uint8 free_bag_slot = _bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); } @@ -736,7 +739,8 @@ int16 EQEmu::InventoryProfile::FindFreeSlotForTradeItem(const ItemInstance* inst if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == item::BagTypeBandolier) || (main_inst->GetItem()->BagType == item::BagTypeQuiver)) continue; - for (uint8 free_bag_slot = bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { + uint8 _bag_start = (free_slot > general_start) ? inventory::containerBegin : bag_start; + for (uint8 free_bag_slot = _bag_start; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < inventory::ContainerCount); ++free_bag_slot) { if (!main_inst->GetItem(free_bag_slot)) return InventoryProfile::CalcSlotId(free_slot, free_bag_slot); } diff --git a/common/inventory_profile.h b/common/inventory_profile.h index 7bb659cff..d8cf6cf7f 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -155,7 +155,7 @@ namespace EQEmu // Locate an available inventory slot int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false); - int16 FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start = legacy::GENERAL_BEGIN, int16 bag_start = inventory::containerBegin); + int16 FindFreeSlotForTradeItem(const ItemInstance* inst, int16 general_start = legacy::GENERAL_BEGIN, uint8 bag_start = inventory::containerBegin); // Calculate slot_id for an item within a bag static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id diff --git a/zone/bot.cpp b/zone/bot.cpp index 32796b88b..361a188c1 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3359,8 +3359,9 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli int16 fromClientSlot; int16 toBotSlot; int adjustStackSize; + std::string acceptedItemName; - ClientTrade(const ItemInstance* item, int16 from) : tradeItemInstance(item), fromClientSlot(from), toBotSlot(legacy::SLOT_INVALID), adjustStackSize(0) { } + ClientTrade(const ItemInstance* item, int16 from, const char* name = "") : tradeItemInstance(item), fromClientSlot(from), toBotSlot(legacy::SLOT_INVALID), adjustStackSize(0), acceptedItemName(name) { } }; struct ClientReturn { @@ -3368,8 +3369,9 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli int16 fromBotSlot; int16 toClientSlot; int adjustStackSize; + std::string failedItemName; - ClientReturn(const ItemInstance* item, int16 from) : returnItemInstance(item), fromBotSlot(from), toClientSlot(legacy::SLOT_INVALID), adjustStackSize(0) { } + ClientReturn(const ItemInstance* item, int16 from, const char* name = "") : returnItemInstance(item), fromBotSlot(from), toClientSlot(legacy::SLOT_INVALID), adjustStackSize(0), failedItemName(name) { } }; static const int16 proxyPowerSource = 22; @@ -3442,6 +3444,11 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli client->ResetTrade(); return; } + if (trade_instance->IsStackable() && (trade_instance->GetCharges() < trade_instance->GetItem()->StackSize)) { // temp until partial stacks are implemented + client->Message(CC_Yellow, "'%s' is only a partially stacked item - Trade Canceled!", trade_instance->GetItem()->Name); + client->ResetTrade(); + return; + } if (CheckLoreConflict(trade_instance->GetItem())) { client->Message(CC_Yellow, "This bot already has lore equipment matching the item '%s' - Trade Canceled!", trade_instance->GetItem()->Name); client->ResetTrade(); @@ -3449,15 +3456,15 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } if (!trade_instance->IsType(item::ItemClassCommon)) { - client_return.push_back(ClientReturn(trade_instance, trade_index)); + client_return.push_back(ClientReturn(trade_instance, trade_index, trade_instance->GetItem()->Name)); continue; } - if (!trade_instance->IsEquipable(GetBaseRace(), GetClass()) || (GetLevel() < trade_instance->GetItem()->ReqLevel)) { - client_return.push_back(ClientReturn(trade_instance, trade_index)); + if (!trade_instance->IsEquipable(GetBaseRace(), GetClass()) || (GetLevel() < trade_instance->GetItem()->ReqLevel)) { // deity checks will be handled within IsEquipable() + client_return.push_back(ClientReturn(trade_instance, trade_index, trade_instance->GetItem()->Name)); continue; } - client_trade.push_back(ClientTrade(trade_instance, trade_index)); + client_trade.push_back(ClientTrade(trade_instance, trade_index, trade_instance->GetItem()->Name)); } // check for incoming lore hacks @@ -3576,7 +3583,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli // move unassignable items from trade list to return list for (std::list::iterator trade_iterator = client_trade.begin(); trade_iterator != client_trade.end();) { if (trade_iterator->toBotSlot == legacy::SLOT_INVALID) { - client_return.push_back(ClientReturn(trade_iterator->tradeItemInstance, trade_iterator->fromClientSlot)); + client_return.push_back(ClientReturn(trade_iterator->tradeItemInstance, trade_iterator->fromClientSlot, trade_iterator->tradeItemInstance->GetItem()->Name)); trade_iterator = client_trade.erase(trade_iterator); continue; } @@ -3606,7 +3613,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } else { int16 client_search_general = legacy::GENERAL_BEGIN; - int16 client_search_bag = inventory::containerBegin; + uint8 client_search_bag = inventory::containerBegin; bool run_search = true; while (run_search) { @@ -3627,16 +3634,23 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } } if (slot_taken) { - client_search_general = InventoryProfile::CalcSlotId(client_test_slot); - client_search_bag = InventoryProfile::CalcBagIdx(client_test_slot); - - ++client_search_bag; - if (client_search_bag >= inventory::ContainerCount) { - client_search_bag = inventory::containerBegin; - // incrementing this past legacy::GENERAL_END triggers the (client_test_slot == legacy::SLOT_INVALID) at the beginning of the search loop - // ideally, this will never occur because we always start fresh with each loop iteration and should receive SLOT_CURSOR as a return value + if ((client_test_slot >= legacy::GENERAL_BEGIN) && (client_test_slot <= legacy::GENERAL_END)) { ++client_search_general; + client_search_bag = inventory::containerBegin; } + else { + client_search_general = InventoryProfile::CalcSlotId(client_test_slot); + client_search_bag = InventoryProfile::CalcBagIdx(client_test_slot); + + ++client_search_bag; + if (client_search_bag >= inventory::ContainerCount) { + // incrementing this past legacy::GENERAL_END triggers the (client_test_slot == legacy::SLOT_INVALID) at the beginning of the search loop + // ideally, this will never occur because we always start fresh with each loop iteration and should receive SLOT_CURSOR as a return value + ++client_search_general; + client_search_bag = inventory::containerBegin; + } + } + continue; } @@ -3694,17 +3708,14 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli trade_iterator.tradeItemInstance = nullptr; } - // trade announcements - for (const auto& return_iterator : client_return) { // item pointers should be nulled by this point - if (((return_iterator.fromBotSlot < legacy::TRADE_BEGIN) || (return_iterator.fromBotSlot > legacy::TRADE_END)) && (return_iterator.fromBotSlot != inventory::slotCursor)) - continue; - - if (client->GetInv()[return_iterator.toClientSlot]) - client->Message(MT_Tell, "%s tells you, \"%s, I can't use this '%s.'\"", GetCleanName(), client->GetName(), client->GetInv()[return_iterator.toClientSlot]->GetItem()->Name); + // trade messages + for (const auto& return_iterator : client_return) { + if (return_iterator.failedItemName.size()) + client->Message(MT_Tell, "%s tells you, \"%s, I can't use this '%s.'\"", GetCleanName(), client->GetName(), return_iterator.failedItemName.c_str()); } - for (const auto& trade_iterator : client_trade) { // item pointers should be nulled by this point - if (m_inv[trade_iterator.toBotSlot]) - client->Message(MT_Tell, "%s tells you, \"Thank you for the '%s,' %s!\"", GetCleanName(), m_inv[trade_iterator.toBotSlot]->GetItem()->Name, client->GetName()); + for (const auto& trade_iterator : client_trade) { + if (trade_iterator.acceptedItemName.size()) + client->Message(MT_Tell, "%s tells you, \"Thank you for the '%s,' %s!\"", GetCleanName(), trade_iterator.acceptedItemName.c_str(), client->GetName()); } size_t accepted_count = client_trade.size(); From 37d22e17a348c0f1b192dd38c39c855f84e0690f Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 9 Mar 2017 02:46:09 -0500 Subject: [PATCH 608/693] First step of implementing inventory v2.0 --- changelog.txt | 1 + common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../sql/git/required/2017_03_09_inventory_version.sql | 11 +++++++++++ 4 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2017_03_09_inventory_version.sql diff --git a/changelog.txt b/changelog.txt index 85ac6c97a..073827861 100644 --- a/changelog.txt +++ b/changelog.txt @@ -6,6 +6,7 @@ Uleat: Fixed a few glitches related to bot trading and other affected code - Return messages no longer repeat the top cursor item when multiple items are pushed there - Test slot for client returns is now handled appropriately for parent and bag searches - FindFreeSlotForTradeItem() now begins at the correct bag index on subsequent parent iterations +Uleat: First step of implementing inventory v2.0 == 03/08/2017 == Uleat: Complete rework of the bot trading system diff --git a/common/version.h b/common/version.h index 1eb98558f..60d594dea 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9106 +#define CURRENT_BINARY_DATABASE_VERSION 9107 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9015 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index c21d00951..428fd52c8 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -360,6 +360,7 @@ 9104|2017_02_09_npc_spells_entries_type_update.sql|SHOW COLUMNS IN `npc_spells_entries` LIKE `type`|contains|smallint(5) unsigned 9105|2017_02_15_bot_spells_entries.sql|SELECT `id` FROM `npc_spells_entries` WHERE `npc_spells_id` >= 701 AND `npc_spells_id` <= 712|not_empty| 9106|2017_02_26_npc_spells_update_for_bots.sql|SELECT * FROM `npc_spells` WHERE `id` = '701' AND `name` = 'Cleric Bot'|not_empty| +9107|2017_03_09_inventory_version.sql|SHOW TABLES LIKE 'inventory_version'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2017_03_09_inventory_version.sql b/utils/sql/git/required/2017_03_09_inventory_version.sql new file mode 100644 index 000000000..37ef38548 --- /dev/null +++ b/utils/sql/git/required/2017_03_09_inventory_version.sql @@ -0,0 +1,11 @@ +DROP TABLE IF EXISTS `inventory_version`; + +CREATE TABLE `inventory_version` ( + `version` INT(11) UNSIGNED NOT NULL DEFAULT '0', + `step` INT(11) UNSIGNED NOT NULL DEFAULT '0' +) +COLLATE='latin1_swedish_ci' +ENGINE=MyISAM +; + +INSERT INTO `inventory_version` VALUES (2, 0); From df5d58f43da4e2aeb9ca215796fd7bd82ad60b6d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 10 Mar 2017 13:00:22 -0500 Subject: [PATCH 609/693] Temp pets shouldn't spawn when they're targeting a corpse --- zone/aa.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zone/aa.cpp b/zone/aa.cpp index 0f0617393..3c6f11f6e 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -42,6 +42,10 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u //Dook- swarms and wards + // do nothing if it's a corpse + if (targ != nullptr && targ->IsCorpse()) + return; + PetRecord record; if(!database.GetPetEntry(spells[spell_id].teleport_zone, &record)) { From 3d229e1da1c99f0fb6d4a23cec5cca38b63ec0f0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 10 Mar 2017 18:15:08 -0500 Subject: [PATCH 610/693] Aggro Meter on by default now (seemed fine on PEQ) --- common/ruletypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 3599a718e..1b2688f53 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -114,7 +114,7 @@ RULE_BOOL(Character, CheckCursorEmptyWhenLooting, true) // If true, a player can RULE_BOOL(Character, MaintainIntoxicationAcrossZones, true) // If true, alcohol effects are maintained across zoning and logging out/in. RULE_BOOL(Character, EnableDiscoveredItems, true) // If enabled, it enables EVENT_DISCOVER_ITEM and also saves character names and timestamps for the first time an item is discovered. RULE_BOOL(Character, EnableXTargetting, true) // Enable Extended Targetting Window, for users with UF and later clients. -RULE_BOOL(Character, EnableAggroMeter, false) // Enable Aggro Meter, for users with RoF and later clients. +RULE_BOOL(Character, EnableAggroMeter, true) // Enable Aggro Meter, for users with RoF and later clients. RULE_BOOL(Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap RULE_INT(Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update RULE_INT(Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well. From bf3d9b2d02ca203fda51e696b8749c4d911765bb Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 10 Mar 2017 18:41:04 -0500 Subject: [PATCH 611/693] Couple of critical fixes for bot trade code --- common/item_data.cpp | 2 +- zone/bot.cpp | 26 +++++++++++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/common/item_data.cpp b/common/item_data.cpp index 3286bf97e..e23f962d2 100644 --- a/common/item_data.cpp +++ b/common/item_data.cpp @@ -195,7 +195,7 @@ bool EQEmu::ItemData::IsClassBook() const bool EQEmu::ItemData::IsType1HWeapon() const { - return ((ItemType == item::ItemType1HBlunt) || (ItemType == item::ItemType1HSlash) || (ItemType == item::ItemType1HPiercing)); + return ((ItemType == item::ItemType1HBlunt) || (ItemType == item::ItemType1HSlash) || (ItemType == item::ItemType1HPiercing) || (ItemType == item::ItemTypeMartial)); } bool EQEmu::ItemData::IsType2HWeapon() const diff --git a/zone/bot.cpp b/zone/bot.cpp index 361a188c1..df5c3ce08 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3494,7 +3494,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } // find equipment slots - const bool can_dual_wield = CanThisClassDualWield(); + const bool can_dual_wield = (GetSkill(EQEmu::skills::SkillDualWield) > 0); bool melee_2h_weapon = false; bool melee_secondary = false; @@ -3542,8 +3542,9 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli if (!melee_secondary) { melee_2h_weapon = true; - if (m_inv[inventory::slotSecondary]) - client_return.push_back(ClientReturn(m_inv[inventory::slotSecondary], inventory::slotSecondary)); + auto equipped_secondary_weapon = m_inv[inventory::slotSecondary]; + if (equipped_secondary_weapon) + client_return.push_back(ClientReturn(equipped_secondary_weapon, inventory::slotSecondary)); } else { continue; @@ -3552,10 +3553,16 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } if (index == inventory::slotSecondary) { if (!melee_2h_weapon) { - if ((can_dual_wield && trade_instance->GetItem()->IsType1HWeapon()) || trade_instance->GetItem()->IsTypeShield() || !trade_instance->IsWeapon()) + if ((can_dual_wield && trade_instance->GetItem()->IsType1HWeapon()) || trade_instance->GetItem()->IsTypeShield() || !trade_instance->IsWeapon()) { melee_secondary = true; - else + + auto equipped_primary_weapon = m_inv[inventory::slotPrimary]; + if (equipped_primary_weapon && equipped_primary_weapon->GetItem()->IsType2HWeapon()) + client_return.push_back(ClientReturn(equipped_primary_weapon, inventory::slotPrimary)); + } + else { continue; + } } else { continue; @@ -3681,15 +3688,16 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli } else { // successful trade returns auto return_instance = m_inv.PopItem(return_iterator.fromBotSlot); - if (*return_instance != *return_iterator.returnItemInstance) { - // TODO: add logging - } + //if (*return_instance != *return_iterator.returnItemInstance) { + // // TODO: add logging + //} if (!botdb.DeleteItemBySlot(GetBotID(), return_iterator.fromBotSlot)) client->Message(CC_Red, "%s (slot: %i, name: '%s')", BotDatabase::fail::DeleteItemBySlot(), return_iterator.fromBotSlot, (return_instance ? return_instance->GetItem()->Name : "nullptr")); BotRemoveEquipItem(return_iterator.fromBotSlot); - client->PutItemInInventory(return_iterator.toClientSlot, *return_instance, true); + if (return_instance) + client->PutItemInInventory(return_iterator.toClientSlot, *return_instance, true); InventoryProfile::MarkDirty(return_instance); } return_iterator.returnItemInstance = nullptr; From 262bcf5c2903046a5bc80d23629e58b770978f12 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 10 Mar 2017 19:16:43 -0500 Subject: [PATCH 612/693] Fix merc attack delay --- zone/zonedb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index ec56b8df8..a36042610 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2261,7 +2261,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client tmpNPCType->gender = atoi(row[7]); tmpNPCType->texture = atoi(row[8]); tmpNPCType->helmtexture = atoi(row[9]); - tmpNPCType->attack_delay = atoi(row[10]); + tmpNPCType->attack_delay = atoi(row[10]) * 100; // TODO: fix DB tmpNPCType->STR = atoi(row[11]); tmpNPCType->STA = atoi(row[12]); tmpNPCType->DEX = atoi(row[13]); From 3555791e1fa10635dea79bf97ff0886c4b23d848 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 11 Mar 2017 13:35:30 -0500 Subject: [PATCH 613/693] Multi-line remark statements wreck havoc on visual studio's parser (expensive) --- zone/bot.cpp | 74 ++++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index df5c3ce08..bdb8cd627 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1724,7 +1724,7 @@ bool Bot::LoadPet() bool Bot::SavePet() { - if (!GetPet() || GetPet()->IsFamiliar() /*|| dead*/) + if (!GetPet() || GetPet()->IsFamiliar()) // dead? return true; NPC *pet_inst = GetPet()->CastToNPC(); @@ -3505,8 +3505,8 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli continue; auto trade_instance = trade_iterator.tradeItemInstance; - /*if ((stage_loop == stageStackable) && !trade_instance->IsStackable()) - continue;*/ + //if ((stage_loop == stageStackable) && !trade_instance->IsStackable()) + // continue; for (auto index : bot_equip_order) { if (!(trade_instance->GetItem()->Slots & (1 << index))) @@ -3849,7 +3849,8 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, EQEmu::skills::SkillT } } -void Bot::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/) { +//void Bot::AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false) +void Bot::AddToHateList(Mob* other, uint32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) { Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic); } @@ -4261,24 +4262,23 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 value = base1; break; } - /* - case SE_SympatheticProc: - { - if(type == focusSympatheticProc) - { - float ProcChance, ProcBonus; - int16 ProcRateMod = base1; //Baseline is 100 for most Sympathetic foci - int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time); - GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod); + //case SE_SympatheticProc: + //{ + // if(type == focusSympatheticProc) + // { + // float ProcChance, ProcBonus; + // int16 ProcRateMod = base1; //Baseline is 100 for most Sympathetic foci + // int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time); + // GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod); - if(zone->random.Real(0, 1) <= ProcChance) - value = focus_id; + // if(zone->random.Real(0, 1) <= ProcChance) + // value = focus_id; - else - value = 0; - } - break; - }*/ + // else + // value = 0; + // } + // break; + //} case SE_FcDamageAmt: { if(type == focusFcDamageAmt) value = base1; @@ -5069,14 +5069,14 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 CheckNumHitsRemaining(NumHit::OutgoingHitSuccess); //[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill -/* if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){ - int kb_chance = 25; - kb_chance += (kb_chance * (100 - aabonuses.SpecialAttackKBProc[0]) / 100); + //if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){ + // int kb_chance = 25; + // kb_chance += (kb_chance * (100 - aabonuses.SpecialAttackKBProc[0]) / 100); - if (zone->random.Int(0, 99) < kb_chance) - SpellFinished(904, who, 10, 0, -1, spells[904].ResistDiff); - //who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC. - }*/ + // if (zone->random.Int(0, 99) < kb_chance) + // SpellFinished(904, who, 10, 0, -1, spells[904].ResistDiff); + // //who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC. + //} if (HasSkillProcs()) TrySkillProc(who, skill, (ReuseTime * 1000)); @@ -7648,7 +7648,7 @@ void Bot::AddItemBonuses(const EQEmu::ItemInstance *inst, StatBonuses* newbon, b switch(item->BardType) { - case 51: /* All (e.g. Singing Short Sword) */ + case EQEmu::item::ItemTypeAllInstrumentTypes: // (e.g. Singing Short Sword) { if(item->BardValue > newbon->singingMod) newbon->singingMod = item->BardValue; @@ -7662,31 +7662,31 @@ void Bot::AddItemBonuses(const EQEmu::ItemInstance *inst, StatBonuses* newbon, b newbon->windMod = item->BardValue; break; } - case 50: /* Singing */ + case EQEmu::item::ItemTypeSinging: { if(item->BardValue > newbon->singingMod) newbon->singingMod = item->BardValue; break; } - case 23: /* Wind */ + case EQEmu::item::ItemTypeWindInstrument: { if(item->BardValue > newbon->windMod) newbon->windMod = item->BardValue; break; } - case 24: /* stringed */ + case EQEmu::item::ItemTypeStringedInstrument: { if(item->BardValue > newbon->stringedMod) newbon->stringedMod = item->BardValue; break; } - case 25: /* brass */ + case EQEmu::item::ItemTypeBrassInstrument: { if(item->BardValue > newbon->brassMod) newbon->brassMod = item->BardValue; break; } - case 26: /* Percussion */ + case EQEmu::item::ItemTypePercussionInstrument: { if(item->BardValue > newbon->percussionMod) newbon->percussionMod = item->BardValue; @@ -7768,10 +7768,10 @@ void Bot::CalcBotStats(bool showtext) { GetSkill(EQEmu::skills::SkillBrassInstruments), GetSkill(EQEmu::skills::SkillPercussionInstruments), GetSkill(EQEmu::skills::SkillSinging), GetSkill(EQEmu::skills::SkillStringedInstruments), GetSkill(EQEmu::skills::SkillWindInstruments)); } - /*if(this->Save()) - this->GetBotOwner()->CastToClient()->Message(0, "%s saved.", this->GetCleanName()); - else - this->GetBotOwner()->CastToClient()->Message(13, "%s save failed!", this->GetCleanName());*/ + //if(this->Save()) + // this->GetBotOwner()->CastToClient()->Message(0, "%s saved.", this->GetCleanName()); + //else + // this->GetBotOwner()->CastToClient()->Message(13, "%s save failed!", this->GetCleanName()); CalcBonuses(); From 04ce4f66ed3c5f4066a0d17b49363e38d16f3cf0 Mon Sep 17 00:00:00 2001 From: E Spause Date: Sun, 12 Mar 2017 03:41:21 -0400 Subject: [PATCH 614/693] Added an optional rule value that forces startzones to be the same as the bind zone and enabled bind xyz once again. --- common/ruletypes.h | 1 + world/client.cpp | 14 ++++++++------ world/worlddb.cpp | 5 ++++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 1b2688f53..1e280bbcc 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -226,6 +226,7 @@ RULE_BOOL (World, IsGMPetitionWindowEnabled, false) RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items. RULE_BOOL (World, IPLimitDisconnectAll, false) RULE_INT (World, TellQueueSize, 20) +RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone ALWAYS be the same location as your bind? RULE_CATEGORY_END() RULE_CATEGORY(Zone) diff --git a/world/client.cpp b/world/client.cpp index 29abc5b9d..45d65e494 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1552,12 +1552,14 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) database.GetSafePoints(pp.zone_id, 0, &pp.x, &pp.y, &pp.z); } - /* Will either be the same as home or tutorial */ - pp.binds[0].zoneId = pp.zone_id; - pp.binds[0].x = pp.x; - pp.binds[0].y = pp.y; - pp.binds[0].z = pp.z; - pp.binds[0].heading = pp.heading; + /* Will either be the same as home or tutorial if enabled. */ + if(RuleB(World, StartZoneSameAsBindOnCreation)) { + pp.binds[0].zoneId = pp.zone_id; + pp.binds[0].x = pp.x; + pp.binds[0].y = pp.y; + pp.binds[0].z = pp.z; + pp.binds[0].heading = pp.heading; + } Log.Out(Logs::Detail, Logs::World_Server,"Current location: %s (%d) %0.2f, %0.2f, %0.2f, %0.2f", database.GetZoneName(pp.zone_id), pp.zone_id, pp.x, pp.y, pp.z, pp.heading); diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 2955daf50..cd6733770 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -353,7 +353,7 @@ bool WorldDatabase::GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_pp->x = in_pp->y = in_pp->z = in_pp->heading = in_pp->zone_id = 0; in_pp->binds[0].x = in_pp->binds[0].y = in_pp->binds[0].z = in_pp->binds[0].zoneId = in_pp->binds[0].instance_id = 0; // see if we have an entry for start_zone. We can support both titanium & SOF+ by having two entries per class/race/deity combo with different zone_ids - std::string query = StringFormat("SELECT x, y, z, heading, start_zone, bind_id FROM start_zones WHERE zone_id = %i " + std::string query = StringFormat("SELECT x, y, z, heading, start_zone, bind_id, bind_x, bind_y, bind_z FROM start_zones WHERE zone_id = %i " "AND player_class = %i AND player_deity = %i AND player_race = %i", in_cc->start_zone, in_cc->class_, in_cc->deity, in_cc->race); auto results = QueryDatabase(query); @@ -376,6 +376,9 @@ bool WorldDatabase::GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_pp->heading = atof(row[3]); in_pp->zone_id = atoi(row[4]); in_pp->binds[0].zoneId = atoi(row[5]); + in_pp->binds[0].x = atof(row[6]); + in_pp->binds[0].y = atof(row[7]); + in_pp->binds[0].z = atof(row[8]); } if(in_pp->x == 0 && in_pp->y == 0 && in_pp->z == 0) From 17b5cc1fa527f0941ef58eb4e917b5480bb7a77f Mon Sep 17 00:00:00 2001 From: E Spause Date: Sun, 12 Mar 2017 03:47:26 -0400 Subject: [PATCH 615/693] Remove error message that has honestly bothered me since the dawn of time. Appears most often when doing loot all. EQLive does not have it. --- zone/corpse.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 24c4b8220..a1cc8c69d 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1087,7 +1087,6 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) } if (!IsBeingLootedBy(client)) { - client->Message(13, "Error: Corpse::LootItem: BeingLootedBy != client"); client->QueuePacket(app); SendEndLootErrorPacket(client); return; From fe70834a6ba4b9e5b00e636834679b97d8308c72 Mon Sep 17 00:00:00 2001 From: E Spause Date: Sun, 12 Mar 2017 03:49:07 -0400 Subject: [PATCH 616/693] Enabled a skill check bypass for OGRE, TROLL, and BARBARIAN races so the "Slam" skill works once more. --- zone/special_attacks.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 81c888915..7f0193426 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -225,8 +225,22 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) if (ClientVersion() >= EQEmu::versions::ClientVersion::RoF2 && ca_atk->m_skill == EQEmu::skills::SkillTigerClaw) timer = pTimerCombatAbility2; + + + if (ca_atk->m_skill == EQEmu::skills::SkillBash) {// SLAM - Bash without a shield equipped + + switch (GetRace()) + { + case OGRE: + case TROLL: + case BARBARIAN: + default: + break; + } + + } + /* Check to see if actually have skill */ - if (!MaxSkill(static_cast(ca_atk->m_skill))) return; if (GetTarget()->GetID() != ca_atk->m_target) From 4fad93824b329bbf500b7f2f3e2fdc38b49455ca Mon Sep 17 00:00:00 2001 From: E Spause Date: Sun, 12 Mar 2017 03:49:41 -0400 Subject: [PATCH 617/693] Formatting fixes. --- zone/special_attacks.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 7f0193426..40836c67c 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -226,21 +226,22 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk) timer = pTimerCombatAbility2; + bool CanBypassSkillCheck = false; - if (ca_atk->m_skill == EQEmu::skills::SkillBash) {// SLAM - Bash without a shield equipped - + if (ca_atk->m_skill == EQEmu::skills::SkillBash) { // SLAM - Bash without a shield equipped switch (GetRace()) { case OGRE: case TROLL: case BARBARIAN: + CanBypassSkillCheck = true; default: break; } - } /* Check to see if actually have skill */ + if (!MaxSkill(static_cast(ca_atk->m_skill)) && !CanBypassSkillCheck) return; if (GetTarget()->GetID() != ca_atk->m_target) From 8cd6416754a389f52eb09cd50b589de9656007f5 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 12 Mar 2017 14:20:22 -0400 Subject: [PATCH 618/693] Added ItemData::CheckLoreConflict() --- common/item_data.cpp | 18 ++++++++++++++++++ common/item_data.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/common/item_data.cpp b/common/item_data.cpp index e23f962d2..c0e70d72a 100644 --- a/common/item_data.cpp +++ b/common/item_data.cpp @@ -207,3 +207,21 @@ bool EQEmu::ItemData::IsTypeShield() const { return (ItemType == item::ItemTypeShield); } + +bool EQEmu::ItemData::CheckLoreConflict(const ItemData* l_item, const ItemData* r_item) +{ + if (!l_item || !r_item) + return false; + + if (!l_item->LoreGroup || !r_item->LoreGroup) + return false; + + if (l_item->LoreGroup == r_item->LoreGroup) { + if ((l_item->LoreGroup == -1) && (l_item->ID != r_item->ID)) + return false; + + return true; + } + + return false; +} diff --git a/common/item_data.h b/common/item_data.h index 14aa368c2..e5d1a24f2 100644 --- a/common/item_data.h +++ b/common/item_data.h @@ -538,6 +538,9 @@ namespace EQEmu bool IsType1HWeapon() const; bool IsType2HWeapon() const; bool IsTypeShield() const; + + static bool CheckLoreConflict(const ItemData* l_item, const ItemData* r_item); + bool CheckLoreConflict(const ItemData* item) const { return CheckLoreConflict(this, item); } }; } /*EQEmu*/ From 14d09485eb1fda95982eba7ebf48207729b394a2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 12 Mar 2017 14:38:14 -0500 Subject: [PATCH 619/693] Implement new rule based ranges for various range based packet operations (performance) - the defaults are set in the code and can be tweaked by sourcing utils/sql/git/optional/rule_values_range_update.sql - Thanks to mackal for gathering live ranges, thanks to takp for initial numbers - We would send 200 for combat updates and the client will only display <= range 54 anyways, these should help a lot in spammy combat RULE_CATEGORY( Range ) RULE_INT ( Range, Say, 135 ) RULE_INT ( Range, Emote, 135 ) RULE_INT ( Range, BeginCast, 200) RULE_INT ( Range, Anims, 135) RULE_INT ( Range, DamageMessages, 50) RULE_INT ( Range, SpellMessages, 75) RULE_INT ( Range, SongMessages, 75) RULE_CATEGORY_END() --- common/ruletypes.h | 10 ++++++++++ .../git/optional/rule_values_range_update.sql | 7 +++++++ zone/attack.cpp | 10 +++++----- zone/client.cpp | 6 +++--- zone/client_packet.cpp | 6 +++--- zone/mob.cpp | 2 +- zone/spells.cpp | 17 +++++++++-------- zone/zoning.cpp | 2 +- 8 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 utils/sql/git/optional/rule_values_range_update.sql diff --git a/common/ruletypes.h b/common/ruletypes.h index 1b2688f53..fbb6f17bd 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -543,6 +543,16 @@ RULE_BOOL(TaskSystem, KeepOneRecordPerCompletedTask, true) RULE_BOOL(TaskSystem, EnableTaskProximity, true) RULE_CATEGORY_END() +RULE_CATEGORY(Range) +RULE_INT(Range, Say, 135) +RULE_INT(Range, Emote, 135) +RULE_INT(Range, BeginCast, 200) +RULE_INT(Range, Anims, 135) +RULE_INT(Range, DamageMessages, 50) +RULE_INT(Range, SpellMessages, 75) +RULE_INT(Range, SongMessages, 75) +RULE_CATEGORY_END() + #ifdef BOTS RULE_CATEGORY(Bots) RULE_INT(Bots, AAExpansion, 8) // Bots get AAs through this expansion diff --git a/utils/sql/git/optional/rule_values_range_update.sql b/utils/sql/git/optional/rule_values_range_update.sql new file mode 100644 index 000000000..080bf6423 --- /dev/null +++ b/utils/sql/git/optional/rule_values_range_update.sql @@ -0,0 +1,7 @@ +INSERT INTO `rule_values` VALUES (1, 'Range:SongMessages', '75', 'The packet range in which song messages are sent'); +INSERT INTO `rule_values` VALUES (1, 'Range:Emote', '135', 'The packet range in which emote messages are sent'); +INSERT INTO `rule_values` VALUES (1, 'Range:BeginCast', '200', 'The packet range in which begin cast messages are sent'); +INSERT INTO `rule_values` VALUES (1, 'Range:Anims', '135', 'The packet range in which animations are sent'); +INSERT INTO `rule_values` VALUES (1, 'Range:DamageMessages', '50', 'The packet range in which damage messages are sent (non-crit)'); +INSERT INTO `rule_values` VALUES (1, 'Range:SpellMessages', '75', 'The packet range in which spell damage messages are sent'); +INSERT INTO `rule_values` VALUES (1, 'Range:Say', '135', 'The range that is required before /say or hail messages will work to an NPC'); diff --git a/zone/attack.cpp b/zone/attack.cpp index c89f217bd..ee212ba78 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3309,7 +3309,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const //fade mez if we are mezzed if (IsMezzed() && attacker) { Log.Out(Logs::Detail, Logs::Combat, "Breaking mez due to attack."); - entity_list.MessageClose_StringID(this, true, 100, MT_WornOff, + entity_list.MessageClose_StringID(this, true, RuleI(Range, SpellMessages), MT_WornOff, HAS_BEEN_AWAKENED, GetCleanName(), attacker->GetCleanName()); BuffFadeByEffect(SE_Mez); } @@ -3471,7 +3471,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const if (attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide) attacker->Message_StringID(MT_DS,OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1)); } else { - entity_list.MessageClose_StringID(this, true, 100, MT_NonMelee, HIT_NON_MELEE, attacker->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); + entity_list.MessageClose_StringID(this, true, RuleI(Range, SpellMessages), MT_NonMelee, HIT_NON_MELEE, attacker->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); } } else { if(damage > 0) { @@ -3505,7 +3505,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const // If this is Damage Shield damage, the correct OP_Damage packets will be sent from Mob::DamageShield, so // we don't send them here. if(!FromDamageShield) { - entity_list.QueueCloseClients(this, outapp, true, 200, skip, true, filter); + entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, SpellMessages), skip, true, filter); //send the damage to ourself if we are a client if(IsClient()) { //I dont think any filters apply to damage affecting us @@ -3522,7 +3522,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const attacker->FilteredMessage_StringID(attacker, MT_DoTDamage, FilterDOT, YOUR_HIT_DOT, GetCleanName(), itoa(damage), spells[spell_id].name); // older clients don't have the below String ID, but it will be filtered - entity_list.FilteredMessageClose_StringID(attacker, true, 200, + entity_list.FilteredMessageClose_StringID(attacker, true, RuleI(Range, SpellMessages), MT_DoTDamage, FilterDOT, OTHER_HIT_DOT, GetCleanName(), itoa(damage), attacker->GetCleanName(), spells[spell_id].name); } @@ -3853,7 +3853,7 @@ void Mob::TrySpellProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *w begincast->spell_id = SpellProcs[i].spellID; begincast->cast_time = 0; outapp->priority = 3; - entity_list.QueueCloseClients(this, outapp, false, 200, 0, true); + entity_list.QueueCloseClients(this, outapp, false, RuleI(Range, SpellMessages), 0, true); safe_delete(outapp); ExecWeaponProc(nullptr, SpellProcs[i].spellID, on, SpellProcs[i].level_override); CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, diff --git a/zone/client.cpp b/zone/client.cpp index 0228b12f4..bf455a51f 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1099,7 +1099,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s CheckLDoNHail(GetTarget()); CheckEmoteHail(GetTarget(), message); - if(DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= 200) { + if(DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= RuleI(Range, Say)) { NPC *tar = GetTarget()->CastToNPC(); parse->EventNPC(EVENT_SAY, tar->CastToNPC(), this, message, language); @@ -1111,7 +1111,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s } } else { - if (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= 200) { + if (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= RuleI(Range, Say)) { parse->EventNPC(EVENT_AGGRO_SAY, GetTarget()->CastToNPC(), this, message, language); } } @@ -1140,7 +1140,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s char *Buffer = (char *)es; Buffer += 4; snprintf(Buffer, sizeof(Emote_Struct) - 4, "%s %s", GetName(), message); - entity_list.QueueCloseClients(this, outapp, true, 100, 0, true, FilterSocials); + entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, Emote), 0, true, FilterSocials); safe_delete(outapp); break; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index d4404247e..b214c477f 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4606,9 +4606,9 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) PlayerPositionUpdateServer_Struct* ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer; MakeSpawnUpdate(ppu); if (gmhideme) - entity_list.QueueClientsStatus(this,outapp,true,Admin(),250); + entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250); else - entity_list.QueueCloseClients(this,outapp,true,300,nullptr,false); + entity_list.QueueCloseClients(this, outapp, true, 300, nullptr, false); safe_delete(outapp); } @@ -5488,7 +5488,7 @@ void Client::Handle_OP_Emote(const EQApplicationPacket *app) } else */ - entity_list.QueueCloseClients(this, outapp, true, 100, 0, true, FilterSocials); + entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, Emote), 0, true, FilterSocials); safe_delete(outapp); return; diff --git a/zone/mob.cpp b/zone/mob.cpp index 119f32031..256f9f715 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1537,7 +1537,7 @@ void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter) anim->action = animnum; anim->speed = type; } - entity_list.QueueCloseClients(this, outapp, false, 200, 0, ackreq, filter); + entity_list.QueueCloseClients(this, outapp, false, RuleI(Range, Anims), 0, ackreq, filter); safe_delete(outapp); } diff --git a/zone/spells.cpp b/zone/spells.cpp index 0961b3404..deec22b82 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -364,7 +364,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, Message_StringID(MT_SpellFailure, fizzle_msg); entity_list.FilteredMessageClose_StringID( - this, true, 200, MT_SpellFailure, IsClient() ? FilterPCSpells : FilterNPCSpells, + this, true, RuleI(Range, SpellMessages), MT_SpellFailure, IsClient() ? FilterPCSpells : FilterNPCSpells, fizzle_msg == MISS_NOTE ? MISSED_NOTE_OTHER : SPELL_FIZZLE_OTHER, GetName()); TryTriggerOnValueAmount(false, true); @@ -469,7 +469,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, begincast->spell_id = spell_id; begincast->cast_time = orgcasttime; // client calculates reduced time by itself outapp->priority = 3; - entity_list.QueueCloseClients(this, outapp, false, 200, 0, true); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS); + entity_list.QueueCloseClients(this, outapp, false, RuleI(Range, BeginCast), 0, true); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS); safe_delete(outapp); } @@ -886,7 +886,7 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) ic->messageid = message_other; ic->spawnid = GetID(); strcpy(ic->message, GetCleanName()); - entity_list.QueueCloseClients(this, outapp, true, 200, 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells); + entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, SongMessages), 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells); safe_delete(outapp); } @@ -1096,7 +1096,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo // if we got here, we regained concentration regain_conc = true; Message_StringID(MT_Spells,REGAIN_AND_CONTINUE); - entity_list.MessageClose_StringID(this, true, 200, MT_Spells, OTHER_REGAIN_CAST, this->GetCleanName()); + entity_list.MessageClose_StringID(this, true, RuleI(Range, SpellMessages), MT_Spells, OTHER_REGAIN_CAST, this->GetCleanName()); } } @@ -2609,7 +2609,7 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) { action->buff_unknown = 0; action->level = buffs[buffs_i].casterlevel; action->type = DamageTypeSpell; - entity_list.QueueCloseClients(this, packet, false, 200, 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells); + entity_list.QueueCloseClients(this, packet, false, RuleI(Range, SongMessages), 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells); action->buff_unknown = 4; @@ -2681,7 +2681,7 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) { cd->damage = 0; if(!IsEffectInSpell(spell_id, SE_BindAffinity)) { - entity_list.QueueCloseClients(this, message_packet, false, 200, 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells); + entity_list.QueueCloseClients(this, message_packet, false, RuleI(Range, SongMessages), 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells); } safe_delete(message_packet); safe_delete(packet); @@ -3484,8 +3484,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r spelltar->CastToClient()->QueuePacket(action_packet); if(IsClient()) // send to caster CastToClient()->QueuePacket(action_packet); + // send to people in the area, ignoring caster and target - entity_list.QueueCloseClients(spelltar, action_packet, true, 200, this, true, spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells); + entity_list.QueueCloseClients(spelltar, action_packet, true, RuleI(Range, SpellMessages), this, true, spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells); /* Send the EVENT_CAST_ON event */ if(spelltar->IsNPC()) @@ -3956,7 +3957,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r cd->damage = 0; if(!IsEffectInSpell(spell_id, SE_BindAffinity)) { - entity_list.QueueCloseClients(spelltar, message_packet, false, 200, 0, true, spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells); + entity_list.QueueCloseClients(spelltar, message_packet, false, RuleI(Range, SpellMessages), 0, true, spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells); } safe_delete(action_packet); safe_delete(message_packet); diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 16130f8e2..30dc4d81f 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -720,7 +720,7 @@ void Client::Gate(uint8 bindnum) { } void NPC::Gate(uint8 bindnum) { - entity_list.MessageClose_StringID(this, true, 200, MT_Spells, GATES, GetCleanName()); + entity_list.MessageClose_StringID(this, true, RuleI(Range, SpellMessages), MT_Spells, GATES, GetCleanName()); Mob::Gate(bindnum); } From ab372b0f6b6a36173c725f328c8ece14b07ea1b6 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 12 Mar 2017 16:10:53 -0500 Subject: [PATCH 620/693] - Implemented range rules for packets and other functions RULE_INT ( Range, Say, 135 ) RULE_INT ( Range, Emote, 135 ) RULE_INT ( Range, BeginCast, 200) RULE_INT ( Range, Anims, 135) RULE_INT ( Range, SpellParticles, 135) RULE_INT ( Range, DamageMessages, 50) RULE_INT ( Range, SpellMessages, 75) RULE_INT ( Range, SongMessages, 75) RULE_INT ( Range, MobPositionUpdates, 600) RULE_INT ( Range, CriticalDamage, 80) - (Readability) Also cleaned up some formatting in messaging and packets so it is easier to understand what is going on with the code --- changelog.txt | 16 ++++ common/ruletypes.h | 4 + zone/attack.cpp | 187 +++++++++++++++++++++++++++++++++-------- zone/client_packet.cpp | 2 +- zone/mob.cpp | 19 ++++- zone/spells.cpp | 51 +++++++++-- 6 files changed, 232 insertions(+), 47 deletions(-) diff --git a/changelog.txt b/changelog.txt index 073827861..9514c812c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,21 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/12/2017 == +Akkadius: +- Implemented range rules for packets and other functions + RULE_INT ( Range, Say, 135 ) + RULE_INT ( Range, Emote, 135 ) + RULE_INT ( Range, BeginCast, 200) + RULE_INT ( Range, Anims, 135) + RULE_INT ( Range, SpellParticles, 135) + RULE_INT ( Range, DamageMessages, 50) + RULE_INT ( Range, SpellMessages, 75) + RULE_INT ( Range, SongMessages, 75) + RULE_INT ( Range, MobPositionUpdates, 600) + RULE_INT ( Range, CriticalDamage, 80) + + - (Readability) Also cleaned up some formatting in messaging and packets so it is easier to understand what is going on with the code + == 03/09/2017 == Uleat: Fixed a few glitches related to bot trading and other affected code - Added a temporary fail clause for partial stack transfers to prevent client item overwrites diff --git a/common/ruletypes.h b/common/ruletypes.h index fbb6f17bd..4b6823114 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -548,11 +548,15 @@ RULE_INT(Range, Say, 135) RULE_INT(Range, Emote, 135) RULE_INT(Range, BeginCast, 200) RULE_INT(Range, Anims, 135) +RULE_INT(Range, SpellParticles, 135) RULE_INT(Range, DamageMessages, 50) RULE_INT(Range, SpellMessages, 75) RULE_INT(Range, SongMessages, 75) +RULE_INT(Range, MobPositionUpdates, 600) +RULE_INT(Range, CriticalDamage, 80) RULE_CATEGORY_END() + #ifdef BOTS RULE_CATEGORY(Bots) RULE_INT(Bots, AAExpansion, 8) // Bots get AAs through this expansion diff --git a/zone/attack.cpp b/zone/attack.cpp index ee212ba78..7f5efa933 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1480,9 +1480,18 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk } if(killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { - char val1[20]={0}; - entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE, - killerMob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); + char val1[20] = { 0 }; + + entity_list.MessageClose_StringID( + this, /* Sender */ + false, /* Skip Sender */ + RuleI(Range, DamageMessages), + MT_NonMelee, /* 283 */ + HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */ + killerMob->GetCleanName(), /* Message1 */ + GetCleanName(), /* Message2 */ + ConvertArray(damage, val1)/* Message3 */ + ); } int exploss = 0; @@ -2009,8 +2018,17 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::Skil if (killer_mob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { char val1[20] = { 0 }; - entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE, - killer_mob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); + + entity_list.MessageClose_StringID( + this, /* Sender */ + false, /* Skip Sender */ + RuleI(Range, DamageMessages), + MT_NonMelee, /* 283 */ + HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */ + killer_mob->GetCleanName(), /* Message1 */ + GetCleanName(), /* Message2 */ + ConvertArray(damage, val1) /* Message3 */ + ); } } else { @@ -3229,7 +3247,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const //we used to do a message to the client, but its gone now. // emote goes with every one ... even npcs - entity_list.MessageClose(this, true, 300, MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName() ); + entity_list.MessageClose(this, true, RuleI(Range, SpellMessages), MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName() ); } } //end `if there is some damage being done and theres anattacker person involved` @@ -3309,8 +3327,15 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const //fade mez if we are mezzed if (IsMezzed() && attacker) { Log.Out(Logs::Detail, Logs::Combat, "Breaking mez due to attack."); - entity_list.MessageClose_StringID(this, true, RuleI(Range, SpellMessages), MT_WornOff, - HAS_BEEN_AWAKENED, GetCleanName(), attacker->GetCleanName()); + entity_list.MessageClose_StringID( + this, /* Sender */ + true, /* Skip Sender */ + RuleI(Range, SpellMessages), + MT_WornOff, /* 284 */ + HAS_BEEN_AWAKENED, // %1 has been awakened by %2. + GetCleanName(), /* Message1 */ + attacker->GetCleanName() /* Message2 */ + ); BuffFadeByEffect(SE_Mez); } @@ -3454,8 +3479,8 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const else filter = FilterPetMisses; - if(!FromDamageShield) - owner->CastToClient()->QueuePacket(outapp,true,CLIENT_CONNECTED,filter); + if (!FromDamageShield) + owner->CastToClient()->QueuePacket(outapp, true, CLIENT_CONNECTED, filter); } } skip = owner; @@ -3469,9 +3494,18 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const char val1[20] = {0}; if (FromDamageShield) { if (attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide) - attacker->Message_StringID(MT_DS,OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1)); + attacker->Message_StringID(MT_DS, OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1)); } else { - entity_list.MessageClose_StringID(this, true, RuleI(Range, SpellMessages), MT_NonMelee, HIT_NON_MELEE, attacker->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); + entity_list.MessageClose_StringID( + this, /* Sender */ + true, /* Skip Sender */ + RuleI(Range, SpellMessages), + MT_NonMelee, /* 283 */ + HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */ + attacker->GetCleanName(), /* Message1 */ + GetCleanName(), /* Message2 */ + ConvertArray(damage, val1) /* Message3 */ + ); } } else { if(damage > 0) { @@ -3505,7 +3539,17 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const // If this is Damage Shield damage, the correct OP_Damage packets will be sent from Mob::DamageShield, so // we don't send them here. if(!FromDamageShield) { - entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, SpellMessages), skip, true, filter); + + entity_list.QueueCloseClients( + this, /* Sender */ + outapp, /* packet */ + true, /* Skip Sender */ + RuleI(Range, SpellMessages), + skip, /* Skip this mob */ + true, /* Packet ACK */ + filter /* eqFilterType filter */ + ); + //send the damage to ourself if we are a client if(IsClient()) { //I dont think any filters apply to damage affecting us @@ -3521,10 +3565,20 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const //might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it attacker->FilteredMessage_StringID(attacker, MT_DoTDamage, FilterDOT, YOUR_HIT_DOT, GetCleanName(), itoa(damage), spells[spell_id].name); - // older clients don't have the below String ID, but it will be filtered - entity_list.FilteredMessageClose_StringID(attacker, true, RuleI(Range, SpellMessages), - MT_DoTDamage, FilterDOT, OTHER_HIT_DOT, GetCleanName(), - itoa(damage), attacker->GetCleanName(), spells[spell_id].name); + + /* older clients don't have the below String ID, but it will be filtered */ + entity_list.FilteredMessageClose_StringID( + attacker, /* Sender */ + true, /* Skip Sender */ + RuleI(Range, SpellMessages), + MT_DoTDamage, /* Type: 325 */ + FilterDOT, /* FilterType: 19 */ + OTHER_HIT_DOT, /* MessageFormat: %1 has taken %2 damage from %3 by %4. */ + GetCleanName(), /* Message1 */ + itoa(damage), /* Message2 */ + attacker->GetCleanName(), /* Message3 */ + spells[spell_id].name /* Message4 */ + ); } } //end packet sending @@ -3932,8 +3986,18 @@ void Mob::TryPetCriticalHit(Mob *defender, DamageHitInfo &hit) critMod += GetCritDmgMob(hit.skill); hit.damage_done += 5; hit.damage_done = (hit.damage_done * critMod) / 100; - entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, FilterMeleeCrits, - CRITICAL_HIT, GetCleanName(), itoa(hit.damage_done + hit.min_damage)); + + entity_list.FilteredMessageClose_StringID( + this, /* Sender */ + false, /* Skip Sender */ + RuleI(Range, CriticalDamage), + MT_CritMelee, /* Type: 301 */ + FilterMeleeCrits, /* FilterType: 12 */ + CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */ + GetCleanName(), /* Message1 */ + itoa(hit.damage_done + hit.min_damage) /* Message2 */ + ); + } } } @@ -3971,14 +4035,33 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * {aabonuses.SlayUndead[1], itembonuses.SlayUndead[1], spellbonuses.SlayUndead[1]}); hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5; hit.damage_done = (hit.damage_done * SlayDmgBonus) / 100; - if (GetGender() == 1) // female + + /* Female */ + if (GetGender() == 1) { entity_list.FilteredMessageClose_StringID( - this, false, 200, MT_CritMelee, FilterMeleeCrits, FEMALE_SLAYUNDEAD, - GetCleanName(), itoa(hit.damage_done + hit.min_damage)); - else // males and neuter I guess + this, /* Sender */ + false, /* Skip Sender */ + RuleI(Range, CriticalDamage), + MT_CritMelee, /* Type: 301 */ + FilterMeleeCrits, /* FilterType: 12 */ + FEMALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses her target!(%2) */ + GetCleanName(), /* Message1 */ + itoa(hit.damage_done + hit.min_damage) /* Message2 */ + ); + } + /* Males and Neuter */ + else { entity_list.FilteredMessageClose_StringID( - this, false, 200, MT_CritMelee, FilterMeleeCrits, MALE_SLAYUNDEAD, - GetCleanName(), itoa(hit.damage_done + hit.min_damage)); + this, /* Sender */ + false, /* Skip Sender */ + RuleI(Range, CriticalDamage), + MT_CritMelee, /* Type: 301 */ + FilterMeleeCrits, /* FilterType: 12 */ + MALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses his target!(%2) */ + GetCleanName(), /* Message1 */ + itoa(hit.damage_done + hit.min_damage) /* Message2 */ + ); + } return; } } @@ -4047,9 +4130,17 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * return; } hit.damage_done = hit.damage_done * 200 / 100; + entity_list.FilteredMessageClose_StringID( - this, false, 200, MT_CritMelee, FilterMeleeCrits, DEADLY_STRIKE, - GetCleanName(), itoa(hit.damage_done + hit.min_damage)); + this, /* Sender */ + false, /* Skip Sender */ + RuleI(Range, CriticalDamage), + MT_CritMelee, /* Type: 301 */ + FilterMeleeCrits, /* FilterType: 12 */ + DEADLY_STRIKE, /* MessageFormat: %1 scores a Deadly Strike!(%2) */ + GetCleanName(), /* Message1 */ + itoa(hit.damage_done + hit.min_damage) /* Message2 */ + ); return; } } @@ -4067,9 +4158,18 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * if (IsBerserk() || berserk) { hit.damage_done += og_damage * 119 / 100; Log.Out(Logs::Detail, Logs::Combat, "Crip damage %d", hit.damage_done); + entity_list.FilteredMessageClose_StringID( - this, false, 200, MT_CritMelee, FilterMeleeCrits, CRIPPLING_BLOW, GetCleanName(), - itoa(hit.damage_done + hit.min_damage)); + this, /* Sender */ + false, /* Skip Sender */ + RuleI(Range, CriticalDamage), + MT_CritMelee, /* Type: 301 */ + FilterMeleeCrits, /* FilterType: 12 */ + CRIPPLING_BLOW, /* MessageFormat: %1 lands a Crippling Blow!(%2) */ + GetCleanName(), /* Message1 */ + itoa(hit.damage_done + hit.min_damage) /* Message2 */ + ); + // Crippling blows also have a chance to stun // Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a // staggers message. @@ -4079,10 +4179,18 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * } return; } - // okay, critted but didn't do anything else, just normal message now - entity_list.FilteredMessageClose_StringID(this, false, 200, MT_CritMelee, FilterMeleeCrits, - CRITICAL_HIT, GetCleanName(), - itoa(hit.damage_done + hit.min_damage)); + + /* Normal Critical hit message */ + entity_list.FilteredMessageClose_StringID( + this, /* Sender */ + false, /* Skip Sender */ + RuleI(Range, CriticalDamage), + MT_CritMelee, /* Type: 301 */ + FilterMeleeCrits, /* FilterType: 12 */ + CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */ + GetCleanName(), /* Message1 */ + itoa(hit.damage_done + hit.min_damage) /* Message2 */ + ); } } } @@ -4108,7 +4216,18 @@ bool Mob::TryFinishingBlow(Mob *defender, int &damage) if (FB_Level && FB_Dmg && (defender->GetLevel() <= FB_Level) && (ProcChance >= zone->random.Int(1, 1000))) { - entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); + + /* Finishing Blow Critical Message */ + entity_list.FilteredMessageClose_StringID( + this, /* Sender */ + false, /* Skip Sender */ + RuleI(Range, CriticalDamage), + MT_CritMelee, /* Type: 301 */ + FilterMeleeCrits, /* FilterType: 12 */ + FINISHING_BLOW, /* MessageFormat: %1 scores a Finishing Blow!!) */ + GetCleanName() /* Message1 */ + ); + damage = FB_Dmg; return true; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index b214c477f..4b3817e9a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4372,7 +4372,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* ppus = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer; boat->MakeSpawnUpdate(ppus); - entity_list.QueueCloseClients(boat,outapp,true,300,this,false); + entity_list.QueueCloseClients(boat, outapp, true, 300, this, false); safe_delete(outapp); // update the boat's position on the server, without sending an update boat->GMMove(ppu->x_pos, ppu->y_pos, ppu->z_pos, EQ19toFloat(ppu->heading), false); diff --git a/zone/mob.cpp b/zone/mob.cpp index 256f9f715..e7b248dd5 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1426,7 +1426,7 @@ void Mob::SendPosUpdate(uint8 iSendToSelf) { } else if(move_tic_count % 2 == 0) { - entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), 700, nullptr, false); + entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), RuleI(Range, MobPositionUpdates), nullptr, false); move_tic_count++; } else { @@ -1529,15 +1529,26 @@ void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter) auto outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer; anim->spawnid = GetID(); + if(type == 0){ anim->action = animnum; anim->speed = 10; } - else{ + else { anim->action = animnum; anim->speed = type; } - entity_list.QueueCloseClients(this, outapp, false, RuleI(Range, Anims), 0, ackreq, filter); + + entity_list.QueueCloseClients( + this, /* Sender */ + outapp, /* Packet */ + false, /* Ignore Sender */ + RuleI(Range, Anims), + 0, /* Skip this mob */ + ackreq, /* Packet ACK */ + filter /* eqFilterType filter */ + ); + safe_delete(outapp); } @@ -1581,7 +1592,7 @@ void Mob::ShowBuffList(Client* client) { client->Message(0, "Buffs on: %s", this->GetCleanName()); uint32 i; uint32 buff_count = GetMaxTotalSlots(); - for (i=0; i < buff_count; i++) { + for (i = 0; i < buff_count; i++) { if (buffs[i].spellid != SPELL_UNKNOWN) { if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) client->Message(0, " %i: %s: Permanent", i, spells[buffs[i].spellid].name); diff --git a/zone/spells.cpp b/zone/spells.cpp index deec22b82..60ca016ff 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -363,9 +363,22 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, StopCasting(); Message_StringID(MT_SpellFailure, fizzle_msg); + + /* Song Failure Messages */ entity_list.FilteredMessageClose_StringID( - this, true, RuleI(Range, SpellMessages), MT_SpellFailure, IsClient() ? FilterPCSpells : FilterNPCSpells, - fizzle_msg == MISS_NOTE ? MISSED_NOTE_OTHER : SPELL_FIZZLE_OTHER, GetName()); + this, /* Sender */ + true, /* Skip Sender */ + RuleI(Range, SpellMessages), + MT_SpellFailure, /* Type: 289 */ + (IsClient() ? FilterPCSpells : FilterNPCSpells), /* FilterType: 8 or 9 depending on client/npc */ + (fizzle_msg == MISS_NOTE ? MISSED_NOTE_OTHER : SPELL_FIZZLE_OTHER), + /* + MessageFormat: You miss a note, bringing your song to a close! (if missed note) + MessageFormat: A missed note brings %1's song to a close! + MessageFormat: %1's spell fizzles! + */ + GetName() /* Message1 */ + ); TryTriggerOnValueAmount(false, true); return(false); @@ -469,7 +482,14 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, begincast->spell_id = spell_id; begincast->cast_time = orgcasttime; // client calculates reduced time by itself outapp->priority = 3; - entity_list.QueueCloseClients(this, outapp, false, RuleI(Range, BeginCast), 0, true); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS); + entity_list.QueueCloseClients( + this, /* Sender */ + outapp, /* Packet */ + false, /* Ignore Sender */ + RuleI(Range, BeginCast), + 0, /* Skip this Mob */ + true /* Packet ACK */ + ); //IsClient() ? FILTER_PCSPELLS : FILTER_NPCSPELLS); safe_delete(outapp); } @@ -3486,7 +3506,15 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r CastToClient()->QueuePacket(action_packet); // send to people in the area, ignoring caster and target - entity_list.QueueCloseClients(spelltar, action_packet, true, RuleI(Range, SpellMessages), this, true, spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells); + entity_list.QueueCloseClients( + spelltar, /* Sender */ + action_packet, /* Packet */ + true, /* Ignore Sender */ + RuleI(Range, SpellMessages), + this, /* Skip this Mob */ + true, /* Packet ACK */ + (spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells) /* EQ Filter Type: (8 or 9) */ + ); /* Send the EVENT_CAST_ON event */ if(spelltar->IsNPC()) @@ -3955,9 +3983,16 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r cd->spellid = action->spell; cd->meleepush_xy = action->sequence; cd->damage = 0; - if(!IsEffectInSpell(spell_id, SE_BindAffinity)) - { - entity_list.QueueCloseClients(spelltar, message_packet, false, RuleI(Range, SpellMessages), 0, true, spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells); + if(!IsEffectInSpell(spell_id, SE_BindAffinity)){ + entity_list.QueueCloseClients( + spelltar, /* Sender */ + message_packet, /* Packet */ + false, /* Ignore Sender */ + RuleI(Range, SpellMessages), + 0, /* Skip this mob */ + true, /* Packet ACK */ + (spelltar->IsClient() ? FilterPCSpells : FilterNPCSpells) /* Message Filter Type: (8 or 9) */ + ); } safe_delete(action_packet); safe_delete(message_packet); @@ -5611,7 +5646,7 @@ void Client::SendSpellAnim(uint16 targetid, uint16 spell_id) a->sequence = 231; app.priority = 1; - entity_list.QueueCloseClients(this, &app); + entity_list.QueueCloseClients(this, &app, false, RuleI(Range, SpellParticles)); } void Mob::CalcDestFromHeading(float heading, float distance, float MaxZDiff, float StartX, float StartY, float &dX, float &dY, float &dZ) From 0159e1cc7247af0b2b7a37c75f11bcc2d54ed512 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 12 Mar 2017 16:42:26 -0500 Subject: [PATCH 621/693] Fix some crapped out formatting [skip ci] --- zone/attack.cpp | 8 ++++---- zone/spells.cpp | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 7f5efa933..38e8bed34 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4132,13 +4132,13 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * hit.damage_done = hit.damage_done * 200 / 100; entity_list.FilteredMessageClose_StringID( - this, /* Sender */ + this, /* Sender */ false, /* Skip Sender */ RuleI(Range, CriticalDamage), MT_CritMelee, /* Type: 301 */ FilterMeleeCrits, /* FilterType: 12 */ DEADLY_STRIKE, /* MessageFormat: %1 scores a Deadly Strike!(%2) */ - GetCleanName(), /* Message1 */ + GetCleanName(), /* Message1 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */ ); return; @@ -4160,14 +4160,14 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * Log.Out(Logs::Detail, Logs::Combat, "Crip damage %d", hit.damage_done); entity_list.FilteredMessageClose_StringID( - this, /* Sender */ + this, /* Sender */ false, /* Skip Sender */ RuleI(Range, CriticalDamage), MT_CritMelee, /* Type: 301 */ FilterMeleeCrits, /* FilterType: 12 */ CRIPPLING_BLOW, /* MessageFormat: %1 lands a Crippling Blow!(%2) */ GetCleanName(), /* Message1 */ - itoa(hit.damage_done + hit.min_damage) /* Message2 */ + itoa(hit.damage_done + hit.min_damage) /* Message2 */ ); // Crippling blows also have a chance to stun diff --git a/zone/spells.cpp b/zone/spells.cpp index 60ca016ff..af09c14a3 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -366,17 +366,17 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, /* Song Failure Messages */ entity_list.FilteredMessageClose_StringID( - this, /* Sender */ + this, /* Sender */ true, /* Skip Sender */ RuleI(Range, SpellMessages), MT_SpellFailure, /* Type: 289 */ (IsClient() ? FilterPCSpells : FilterNPCSpells), /* FilterType: 8 or 9 depending on client/npc */ - (fizzle_msg == MISS_NOTE ? MISSED_NOTE_OTHER : SPELL_FIZZLE_OTHER), - /* - MessageFormat: You miss a note, bringing your song to a close! (if missed note) - MessageFormat: A missed note brings %1's song to a close! - MessageFormat: %1's spell fizzles! - */ + (fizzle_msg == MISS_NOTE ? MISSED_NOTE_OTHER : SPELL_FIZZLE_OTHER), + /* + MessageFormat: You miss a note, bringing your song to a close! (if missed note) + MessageFormat: A missed note brings %1's song to a close! + MessageFormat: %1's spell fizzles! + */ GetName() /* Message1 */ ); From 41b1634199cf994d0cd07318265816a1fd974bcb Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 12 Mar 2017 17:19:42 -0500 Subject: [PATCH 622/693] Update proper file name utils/sql/git/optional/2017_03_12_rule_values_range_update.sql [skip ci] --- ...ange_update.sql => 2017_03_12_rule_values_range_update.sql} | 3 +++ 1 file changed, 3 insertions(+) rename utils/sql/git/optional/{rule_values_range_update.sql => 2017_03_12_rule_values_range_update.sql} (69%) diff --git a/utils/sql/git/optional/rule_values_range_update.sql b/utils/sql/git/optional/2017_03_12_rule_values_range_update.sql similarity index 69% rename from utils/sql/git/optional/rule_values_range_update.sql rename to utils/sql/git/optional/2017_03_12_rule_values_range_update.sql index 080bf6423..2dad8e8e5 100644 --- a/utils/sql/git/optional/rule_values_range_update.sql +++ b/utils/sql/git/optional/2017_03_12_rule_values_range_update.sql @@ -5,3 +5,6 @@ INSERT INTO `rule_values` VALUES (1, 'Range:Anims', '135', 'The packet range in INSERT INTO `rule_values` VALUES (1, 'Range:DamageMessages', '50', 'The packet range in which damage messages are sent (non-crit)'); INSERT INTO `rule_values` VALUES (1, 'Range:SpellMessages', '75', 'The packet range in which spell damage messages are sent'); INSERT INTO `rule_values` VALUES (1, 'Range:Say', '135', 'The range that is required before /say or hail messages will work to an NPC'); +INSERT INTO `rule_values` VALUES (1, 'Range:SpellParticles', '135', 'The packet range in which spell particles are sent'); +INSERT INTO `rule_values` VALUES (1, 'Range:MobPositionUpdates', '600', 'The packet range in which mob position updates are sent'); +INSERT INTO `rule_values` VALUES (1, 'Range:CriticalDamage', '80', 'The packet range in which critical hit messages are sent'); From f3f034d94875e696802717332b50c3bcf05d5dd2 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 12 Mar 2017 21:46:16 -0400 Subject: [PATCH 623/693] Fix for a combat ability targeting error --- zone/special_attacks.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 40836c67c..d65d5ad35 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1791,8 +1791,8 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) } while(AtkRounds > 0) { - if (GetTarget()) - DoSpecialAttackDamage(GetTarget(), EQEmu::skills::SkillFrenzy, dmg, 0, dmg, ReuseTime); + if (ca_target!=this) + DoSpecialAttackDamage(ca_target, EQEmu::skills::SkillFrenzy, dmg, 0, dmg, ReuseTime); AtkRounds--; } From 3fa72218a421fe7429f48cb66d287c8eab7a1921 Mon Sep 17 00:00:00 2001 From: E Spause Date: Sun, 12 Mar 2017 23:08:59 -0400 Subject: [PATCH 624/693] Remove delay death from Mercs so they function like normal NPCs at 0 health. --- zone/merc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/merc.h b/zone/merc.h index e3eb6c029..18256faf8 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -250,7 +250,7 @@ public: inline virtual int32 GetStringMod() const { return itembonuses.stringedMod; } inline virtual int32 GetWindMod() const { return itembonuses.windMod; } - inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; } + inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath; } // "SET" Class Methods void SetMercData (uint32 templateID ); From 3dd0d43e9606cf8498340de8c1357b4e94ebfed5 Mon Sep 17 00:00:00 2001 From: E Spause Date: Sun, 12 Mar 2017 23:19:24 -0400 Subject: [PATCH 625/693] Add a rule, MaxClientsSimplifiedLogic which allows for P99-style IP restrictions if enabled. Opcode handler for OP_WorldLogout in char sel. Only uses ExemptAccountLimitStatus and MaxClientsPerIP. Also adds in an opcode handler so CLEs are cleaned up at char select when ESC is pressed. --- common/servertalk.h | 1 + world/client.cpp | 6 ++++++ world/clientlist.cpp | 19 ++++++++++++++++++- world/clientlist.h | 1 + world/login_server.cpp | 15 +++++++++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/common/servertalk.h b/common/servertalk.h index b0197985f..528abfb4b 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -663,6 +663,7 @@ struct UsertoWorldRequest_Struct { uint32 worldid; uint32 FromID; uint32 ToID; + char IPAddr[64]; }; struct UsertoWorldResponse_Struct { diff --git a/world/client.cpp b/world/client.cpp index 45d65e494..c7385b41c 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1022,6 +1022,12 @@ bool Client::HandlePacket(const EQApplicationPacket *app) { eqs->Close(); return true; } + case OP_WorldLogout: + { + eqs->Close(); + cle->SetOnline(CLE_Status_Offline); //allows this player to log in again without an ip restriction. + return false; + } case OP_ZoneChange: { // HoT sends this to world while zoning and wants it echoed back. diff --git a/world/clientlist.cpp b/world/clientlist.cpp index fd92051b3..23fb44fb0 100644 --- a/world/clientlist.cpp +++ b/world/clientlist.cpp @@ -214,6 +214,24 @@ void ClientList::GetCLEIP(uint32 iIP) { } } +uint32 ClientList::GetCLEIPCount(uint32 iIP) { + ClientListEntry* countCLEIPs = 0; + LinkedListIterator iterator(clientlist); + + int IPInstances = 0; + iterator.Reset(); + + while (iterator.MoreElements()) { + countCLEIPs = iterator.GetData(); + if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0)) && countCLEIPs->Online() >= CLE_Status_Online) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt) + IPInstances++; // Increment the occurences of this IP address + } + iterator.Advance(); + } + + return IPInstances; +} + void ClientList::DisconnectByIP(uint32 iIP) { ClientListEntry* countCLEIPs = 0; LinkedListIterator iterator(clientlist); @@ -252,7 +270,6 @@ ClientListEntry* ClientList::FindCharacter(const char* name) { return 0; } - ClientListEntry* ClientList::FindCLEByAccountID(uint32 iAccID) { LinkedListIterator iterator(clientlist); diff --git a/world/clientlist.h b/world/clientlist.h index 1d5fc6ab8..44ed70a08 100644 --- a/world/clientlist.h +++ b/world/clientlist.h @@ -56,6 +56,7 @@ public: ClientListEntry* FindCLEByCharacterID(uint32 iCharID); ClientListEntry* GetCLE(uint32 iID); void GetCLEIP(uint32 iIP); + uint32 GetCLEIPCount(uint32 iLSAccountID); void DisconnectByIP(uint32 iIP); void EnforceSessionLimit(uint32 iLSAccountID); void CLCheckStale(); diff --git a/world/login_server.cpp b/world/login_server.cpp index b8c23d573..ad5f4ec88 100644 --- a/world/login_server.cpp +++ b/world/login_server.cpp @@ -134,11 +134,26 @@ bool LoginServer::Process() { if( (int32)numplayers >= x && x != -1 && x != 255 && status < 80) utwrs->response = -3; + + if (pack->size == sizeof(UsertoWorldRequest_Struct)) + { + uint32 decimalIP = inet_addr(utwr->IPAddr); + + if (RuleB(World, MaxClientsSimplifiedLogic)) { + if (client_list.GetCLEIPCount(decimalIP) >= (RuleI(World, MaxClientsPerIP))) { + if ((status < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0)) { + utwrs->response = -4; + } + } + } + } + if(status == -1) utwrs->response = -1; if(status == -2) utwrs->response = -2; + utwrs->worldid = utwr->worldid; SendPacket(outpack); delete outpack; From 09b9d398e2e089cec48d01cda515f32ef0fca89f Mon Sep 17 00:00:00 2001 From: E Spause Date: Sun, 12 Mar 2017 23:19:50 -0400 Subject: [PATCH 626/693] Rule itself for MaxClientsSimplifiedLogic. Defaults to disabled (false) --- common/ruletypes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/ruletypes.h b/common/ruletypes.h index 1e280bbcc..002e2d829 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -225,6 +225,7 @@ RULE_INT(World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Ral RULE_BOOL (World, IsGMPetitionWindowEnabled, false) RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items. RULE_BOOL (World, IPLimitDisconnectAll, false) +RULE_BOOL(World, MaxClientsSimplifiedLogic, false) // New logic that only uses ExemptMaxClientsStatus and MaxClientsPerIP. Done on the loginserver. This mimics the P99-style special IP rules. RULE_INT (World, TellQueueSize, 20) RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone ALWAYS be the same location as your bind? RULE_CATEGORY_END() From 79f9433dfad274f3b73272bda2a6fd11ae673194 Mon Sep 17 00:00:00 2001 From: E Spause Date: Mon, 13 Mar 2017 06:26:48 -0400 Subject: [PATCH 627/693] Merc logic fix for heal spells - allows mercs to select fast healing spells as a 'standard' healing spell & new rule for unsuspend --- common/ruletypes.h | 1 + common/spdat.cpp | 2 +- zone/merc.cpp | 11 ++++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index d0e2ff2be..7e461071f 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -163,6 +163,7 @@ RULE_INT(Mercs, AggroRadius, 100) // Determines the distance from which a merc RULE_INT(Mercs, AggroRadiusPuller, 25) // Determines the distance from which a merc will aggro group member's target, if they have the group role of puller (also used to determine the distance at which a healer merc will begin healing a group member, if they have the group role of puller) RULE_INT(Mercs, ResurrectRadius, 50) // Determines the distance from which a healer merc will attempt to resurrect a group member's corpse RULE_INT(Mercs, ScaleRate, 100) +RULE_BOOL(Mercs, AllowMercSuspendInCombat, true) RULE_CATEGORY_END() RULE_CATEGORY(Guild) diff --git a/common/spdat.cpp b/common/spdat.cpp index fd4e3c5ea..e88240ef9 100644 --- a/common/spdat.cpp +++ b/common/spdat.cpp @@ -940,7 +940,7 @@ bool IsRegularSingleTargetHealSpell(uint16 spell_id) { if(spells[spell_id].effectid[0] == 0 && spells[spell_id].base[0] > 0 && spells[spell_id].targettype == ST_Target && spells[spell_id].buffduration == 0 && - !IsFastHealSpell(spell_id) && !IsCompleteHealSpell(spell_id) && + !IsCompleteHealSpell(spell_id) && !IsHealOverTimeSpell(spell_id) && !IsGroupSpell(spell_id)) return true; diff --git a/zone/merc.cpp b/zone/merc.cpp index 3e3dfae93..8196d2ba2 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -5468,7 +5468,7 @@ void Client::SuspendMercCommand() { Merc* merc = Merc::LoadMerc(this, &zone->merc_templates[GetMercInfo().MercTemplateID], 0, true); if(merc) { - SpawnMerc(merc, true); + SpawnMerc(merc, false); Log.Out(Logs::General, Logs::Mercenaries, "SuspendMercCommand Successful Unsuspend for %s.", GetName()); } else @@ -5482,6 +5482,15 @@ void Client::SuspendMercCommand() { { Merc* CurrentMerc = GetMerc(); + + if (!RuleB(Mercs, AllowMercSuspendInCombat)) + { + if (!CheckCanSpawnMerc(GetMercInfo().MercTemplateID)) + { + return; + } + } + if(CurrentMerc && GetMercID()) { CurrentMerc->Suspend(); From 31cc6f63d65374f0fb1aba440c1f54ea19d104f9 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 14 Mar 2017 16:32:10 -0400 Subject: [PATCH 628/693] Added evade code to rogue mercs --- zone/bot.h | 2 +- zone/merc.cpp | 79 +++++++++++++++++++++++++++++++++++---------------- zone/merc.h | 2 ++ 3 files changed, 58 insertions(+), 25 deletions(-) diff --git a/zone/bot.h b/zone/bot.h index ca5a7e9ad..6c1dfc53f 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -737,7 +737,7 @@ private: bool _hasBeenSummoned; glm::vec3 m_PreSummonLocation; - Timer evade_timer; + Timer evade_timer; // can be moved to pTimers at some point BotCastingRoles m_CastingRoles; diff --git a/zone/merc.cpp b/zone/merc.cpp index 3e3dfae93..6a8e8af40 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -69,6 +69,9 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading) SetStance(MercStanceBalanced); rest_timer.Disable(); + if (GetClass() == ROGUE) + evade_timer.Start(); + int r; for (r = 0; r <= EQEmu::skills::HIGHEST_SKILL; r++) { skills[r] = database.GetSkillCap(GetClass(), (EQEmu::skills::SkillType)r, GetLevel()); @@ -1508,32 +1511,60 @@ void Merc::AI_Process() { } } - if(AI_movement_timer->Check()) - { - if(!IsMoving() && GetClass() == ROGUE && !BehindMob(GetTarget(), GetX(), GetY())) - { - // Move the rogue to behind the mob - float newX = 0; - float newY = 0; - float newZ = 0; + if(AI_movement_timer->Check()) { + if (!IsMoving()) { + if (GetClass() == ROGUE) { + if (HasTargetReflection() && !GetTarget()->IsFeared() && !GetTarget()->IsStunned()) { + // Hate redux actions + if (evade_timer.Check(false)) { + // Attempt to evade + int timer_duration = (HideReuseTime - GetSkillReuseTime(EQEmu::skills::SkillHide)) * 1000; + if (timer_duration < 0) + timer_duration = 0; + evade_timer.Start(timer_duration); - if(PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) - { - CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); - return; + if (zone->random.Int(0, 260) < (int)GetSkill(EQEmu::skills::SkillHide)) + RogueEvade(GetTarget()); + + return; + } + else if (GetTarget()->IsRooted()) { + // Move rogue back from rooted mob - out of combat range, if necessary + float melee_distance = GetMaxMeleeRangeToTarget(GetTarget()); + float current_distance = DistanceSquared(static_cast(m_Position), static_cast(GetTarget()->GetPosition())); + + if (current_distance <= melee_distance) { + float newX = 0; + float newY = 0; + float newZ = 0; + FaceTarget(GetTarget()); + if (PlotPositionAroundTarget(this, newX, newY, newZ)) { + CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); + return; + } + } + } + } + else if (!BehindMob(GetTarget(), GetX(), GetY())) { + // Move the rogue to behind the mob + float newX = 0; + float newY = 0; + float newZ = 0; + if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) { + CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); + return; + } + } } - } - else if(!IsMoving() && GetClass() != ROGUE && (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) < GetTarget()->GetSize())) - { - // If we are not a rogue trying to backstab, let's try to adjust our melee range so we don't appear to be bunched up - float newX = 0; - float newY = 0; - float newZ = 0; - - if(PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) - { - CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); - return; + else if (GetClass() != ROGUE && (DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) < GetTarget()->GetSize())) { + // If we are not a rogue trying to backstab, let's try to adjust our melee range so we don't appear to be bunched up + float newX = 0; + float newY = 0; + float newZ = 0; + if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) { + CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); + return; + } } } diff --git a/zone/merc.h b/zone/merc.h index e3eb6c029..23e4b2f03 100644 --- a/zone/merc.h +++ b/zone/merc.h @@ -290,6 +290,8 @@ protected: std::vector merc_spells; std::map timers; + Timer evade_timer; // can be moved to pTimers at some point + uint16 skills[EQEmu::skills::HIGHEST_SKILL + 1]; uint32 equipment[EQEmu::legacy::EQUIPMENT_SIZE]; //this is an array of item IDs uint16 d_melee_texture1; //this is an item Material value From 2d24237aacbcaa98eb7a39fd5b2687d0e2dc71aa Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 14 Mar 2017 23:23:42 -0400 Subject: [PATCH 629/693] Added los movement logic to combat and follow code (los is rule-based and can by disabled by applying the optional 2017_03_14_mercs_use_pathing_rule.sql) --- common/ruletypes.h | 1 + .../2017_03_14_mercs_use_pathing_rule.sql | 1 + zone/merc.cpp | 64 +++++++++++++------ 3 files changed, 48 insertions(+), 18 deletions(-) create mode 100644 utils/sql/git/optional/2017_03_14_mercs_use_pathing_rule.sql diff --git a/common/ruletypes.h b/common/ruletypes.h index 7e461071f..0bac4d6df 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -163,6 +163,7 @@ RULE_INT(Mercs, AggroRadius, 100) // Determines the distance from which a merc RULE_INT(Mercs, AggroRadiusPuller, 25) // Determines the distance from which a merc will aggro group member's target, if they have the group role of puller (also used to determine the distance at which a healer merc will begin healing a group member, if they have the group role of puller) RULE_INT(Mercs, ResurrectRadius, 50) // Determines the distance from which a healer merc will attempt to resurrect a group member's corpse RULE_INT(Mercs, ScaleRate, 100) +RULE_BOOL(Mercs, MercsUsePathing, true) // Mercs will use node pathing when moving RULE_BOOL(Mercs, AllowMercSuspendInCombat, true) RULE_CATEGORY_END() diff --git a/utils/sql/git/optional/2017_03_14_mercs_use_pathing_rule.sql b/utils/sql/git/optional/2017_03_14_mercs_use_pathing_rule.sql new file mode 100644 index 000000000..7393facdd --- /dev/null +++ b/utils/sql/git/optional/2017_03_14_mercs_use_pathing_rule.sql @@ -0,0 +1 @@ +INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Mercs:MercsUsePathing', 'false', 'Mercs will use node pathing when moving'); diff --git a/zone/merc.cpp b/zone/merc.cpp index 155cb4841..5f8ea59ea 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1462,7 +1462,7 @@ void Merc::AI_Process() { // Let's check if we have a los with our target. // If we don't, our hate_list is wiped. // Else, it was causing the merc to aggro behind wall etc... causing massive trains. - if(!CheckLosFN(GetTarget()) || GetTarget()->IsMezzed() || !IsAttackAllowed(GetTarget())) { + if(GetTarget()->IsMezzed() || !IsAttackAllowed(GetTarget())) { WipeHateList(); if(IsMoving()) { @@ -1477,6 +1477,26 @@ void Merc::AI_Process() { return; } + else if (!CheckLosFN(GetTarget())) { + if (RuleB(Mercs, MercsUsePathing) && zone->pathing) { + bool WaypointChanged, NodeReached; + + glm::vec3 Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), + GetRunspeed(), WaypointChanged, NodeReached); + + if (WaypointChanged) + tar_ndx = 20; + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); + } + else { + Mob* follow = entity_list.GetMob(GetFollowID()); + if (follow) + CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetRunspeed()); + } + + return; + } if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) SendAddPlayerState(PlayerState::Aggressive); @@ -1738,34 +1758,42 @@ void Merc::AI_Process() { } } - if(AI_movement_timer->Check()) - { - if(GetFollowID()) - { + if(AI_movement_timer->Check()) { + if(GetFollowID()) { Mob* follow = entity_list.GetMob(GetFollowID()); - if(follow) - { + if (follow) { float dist = DistanceSquared(m_Position, follow->GetPosition()); int speed = GetRunspeed(); - if(dist < GetFollowDistance() + 1000) + if (dist < GetFollowDistance() + 1000) speed = GetWalkspeed(); SetRunAnimSpeed(0); - if(dist > GetFollowDistance()) { - CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); - if(rest_timer.Enabled()) + if (dist > GetFollowDistance()) { + if (RuleB(Mercs, MercsUsePathing) && zone->pathing) { + bool WaypointChanged, NodeReached; + + glm::vec3 Goal = UpdatePath(follow->GetX(), follow->GetY(), follow->GetZ(), + speed, WaypointChanged, NodeReached); + + if (WaypointChanged) + tar_ndx = 20; + + CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed); + } + else { + CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); + } + + if (rest_timer.Enabled()) rest_timer.Disable(); - return; } - else - { - if(moved) - { - SetCurrentSpeed(0); - moved = false; + else { + if (moved) { + moved = false; + SetCurrentSpeed(0); } } } From d04d6750a21215758a68a2bc0384689d54382fd6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 15 Mar 2017 13:22:45 -0400 Subject: [PATCH 630/693] Allow base damage of 0 (ex slam) min damage done to 1 --- common/skills.cpp | 27 +++++++++++++++++++++++++++ common/skills.h | 1 + zone/attack.cpp | 18 ++++++++++-------- zone/bot.cpp | 6 +++--- zone/special_attacks.cpp | 10 +++++----- 5 files changed, 46 insertions(+), 16 deletions(-) diff --git a/common/skills.cpp b/common/skills.cpp index 6cb063e2e..947861163 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -148,6 +148,33 @@ int32 EQEmu::skills::GetBaseDamage(SkillType skill) } } +bool EQEmu::skills::IsMeleeDmg(SkillType skill) +{ + switch (skill) { + case Skill1HBlunt: + case Skill1HSlashing: + case Skill2HBlunt: + case Skill2HSlashing: + case SkillBackstab: + case SkillBash: + case SkillDragonPunch: + case SkillEagleStrike: + case SkillFlyingKick: + case SkillHandtoHand: + case SkillKick: + case Skill1HPiercing: + case SkillRiposte: + case SkillRoundKick: + case SkillThrowing: + case SkillTigerClaw: + case SkillFrenzy: + case Skill2HPiercing: + return true; + default: + return false; + } +} + const std::map& EQEmu::skills::GetSkillTypeMap() { /* VS2013 code diff --git a/common/skills.h b/common/skills.h index 572b8c59f..43a31ed15 100644 --- a/common/skills.h +++ b/common/skills.h @@ -167,6 +167,7 @@ namespace EQEmu bool IsBardInstrumentSkill(SkillType skill); bool IsCastingSkill(SkillType skill); int32 GetBaseDamage(SkillType skill); + bool IsMeleeDmg(SkillType skill); extern const std::map& GetSkillTypeMap(); diff --git a/zone/attack.cpp b/zone/attack.cpp index 38e8bed34..6740b5c29 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -866,11 +866,9 @@ void Mob::MeleeMitigation(Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions auto roll = RollD20(hit.offense, mitigation); - // +0.5 for rounding - hit.damage_done = static_cast(roll * static_cast(hit.base_damage) + 0.5); + // +0.5 for rounding, min to 1 dmg + hit.damage_done = std::max(static_cast(roll * static_cast(hit.base_damage) + 0.5), 1); - if (hit.damage_done < 0) - hit.damage_done = 0; Log.Out(Logs::Detail, Logs::Attack, "mitigation %d vs offense %d. base %d rolled %f damage %d", mitigation, hit.offense, hit.base_damage, roll, hit.damage_done); } @@ -1207,7 +1205,7 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts) if (strike_through && zone->random.Roll(strike_through)) { Message_StringID(MT_StrikeThrough, STRIKETHROUGH_STRING); // You strike through your opponents defenses! - hit.damage_done = 0; // set to zero, we will check this to continue + hit.damage_done = 1; // set to one, we will check this to continue } // I'm pretty sure you can riposte a riposte if (hit.damage_done == DMG_RIPOSTED) { @@ -1218,7 +1216,7 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts) Log.Out(Logs::Detail, Logs::Combat, "Avoided/strikethrough damage with code %d", hit.damage_done); } - if (hit.damage_done == 0) { + if (hit.damage_done >= 0) { if (other->CheckHitChance(this, hit)) { other->MeleeMitigation(this, hit, opts); if (hit.damage_done > 0) { @@ -1297,7 +1295,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, my_hit.skill); // Now figure out damage - my_hit.damage_done = 0; + my_hit.damage_done = 1; my_hit.min_damage = 0; uint8 mylevel = GetLevel() ? GetLevel() : 1; uint32 hate = 0; @@ -1784,7 +1782,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool DamageHitInfo my_hit; my_hit.skill = EQEmu::skills::SkillHandtoHand; my_hit.hand = Hand; - my_hit.damage_done = 0; + my_hit.damage_done = 1; if (Hand == EQEmu::inventory::slotPrimary) { my_hit.skill = static_cast(GetPrimSkill()); OffHandAtk(false); @@ -4465,6 +4463,10 @@ void Mob::ApplyDamageTable(DamageHitInfo &hit) if (hit.offense < 115) return; + // things that come out to 1 dmg seem to skip this (ex non-bash slam classes) + if (hit.damage_done < 2) + return; + auto &damage_table = GetDamageTable(); if (zone->random.Roll(damage_table.chance)) diff --git a/zone/bot.cpp b/zone/bot.cpp index bdb8cd627..6ce4210b3 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3919,9 +3919,9 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b DamageHitInfo my_hit; AttackAnimation(my_hit.skill, Hand, weapon); Log.Out(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, my_hit.skill); - + // Now figure out damage - my_hit.damage_done = 0; + my_hit.damage_done = 1; my_hit.min_damage = 0; uint8 mylevel = GetLevel() ? GetLevel() : 1; uint32 hate = 0; @@ -5046,7 +5046,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 DamageHitInfo my_hit; my_hit.base_damage = max_damage; my_hit.min_damage = min_damage; - my_hit.damage_done = 0; + my_hit.damage_done = 1; my_hit.skill = skill; my_hit.offense = offense(my_hit.skill); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index d65d5ad35..fa91fdf73 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -142,7 +142,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 return; DamageHitInfo my_hit; - my_hit.damage_done = 0; + my_hit.damage_done = 1; // min 1 dmg my_hit.base_damage = base_damage; my_hit.min_damage = min_damage; my_hit.skill = skill; @@ -847,7 +847,7 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQEmu::ItemInstance *RangeWeapon, DamageHitInfo my_hit; my_hit.base_damage = MaxDmg; my_hit.min_damage = 0; - my_hit.damage_done = 0; + my_hit.damage_done = 1; my_hit.skill = EQEmu::skills::SkillArchery; my_hit.offense = offense(my_hit.skill); @@ -1179,7 +1179,7 @@ void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 cha DamageHitInfo my_hit; my_hit.base_damage = MaxDmg; my_hit.min_damage = MinDmg; - my_hit.damage_done = 0; + my_hit.damage_done = 1; my_hit.skill = skill; my_hit.offense = offense(my_hit.skill); @@ -1360,7 +1360,7 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQEmu::ItemInstance *RangeWeapon DamageHitInfo my_hit; my_hit.base_damage = WDmg; my_hit.min_damage = 0; - my_hit.damage_done = 0; + my_hit.damage_done = 1; my_hit.skill = EQEmu::skills::SkillThrowing; my_hit.offense = offense(my_hit.skill); @@ -2117,7 +2117,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQEmu::skills: DamageHitInfo my_hit; my_hit.base_damage = weapon_damage; my_hit.min_damage = 0; - my_hit.damage_done = 0; + my_hit.damage_done = 1; my_hit.skill = skillinuse; my_hit.offense = offense(my_hit.skill); From 23bc535e23c336931335df2554a04abd6d06fe35 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 15 Mar 2017 15:07:28 -0400 Subject: [PATCH 631/693] Tweaks to most likely wrong PVP damage reduction --- zone/attack.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 6740b5c29..b0c056b30 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1435,13 +1435,15 @@ void Client::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::Sk // cut all PVP spell damage to 2/3 // Blasting ourselfs is considered PvP //Don't do PvP mitigation if the caster is damaging himself + //should this be applied to all damage? comments sound like some is for spell DMG + //patch notes on PVP reductions only mention archery/throwing ... not normal dmg if(other && other->IsClient() && (other != this) && damage > 0) { int PvPMitigation = 100; - if (attack_skill == EQEmu::skills::SkillArchery) + if (attack_skill == EQEmu::skills::SkillArchery || attack_skill == EQEmu::skills::SkillThrowing) PvPMitigation = 80; else PvPMitigation = 67; - damage = (damage * PvPMitigation) / 100; + damage = std::max((damage * PvPMitigation) / 100, 1); } if(!ClientFinishedLoading()) @@ -3197,7 +3199,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const if (!ignore_invul && (GetInvul() || DivineAura())) { Log.Out(Logs::Detail, Logs::Combat, "Avoiding %d damage due to invulnerability.", damage); - damage = -5; + damage = DMG_INVULNERABLE; } if( spell_id != SPELL_UNKNOWN || attacker == nullptr ) From e7785d56930ff584331d1d4b26c779060fea3cff Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 15 Mar 2017 15:25:42 -0400 Subject: [PATCH 632/693] Bash dmg should return 0 with no item (slam) --- zone/special_attacks.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index fa91fdf73..a5cae5700 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -94,6 +94,8 @@ int Mob::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target) } if (inst) ac_bonus = inst->GetItemArmorClass(true) / 25.0f; + else + return 0; // return 0 in cases where we don't have an item if (ac_bonus > skill_bonus) ac_bonus = skill_bonus; return static_cast(ac_bonus + skill_bonus); From fbb13ec4169fb37b55c23576b44c375efd2e52ba Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 16 Mar 2017 12:52:58 -0400 Subject: [PATCH 633/693] bug found by clang 4 --- zone/command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index 307b4e949..dfe6b10e7 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -10686,7 +10686,7 @@ void command_logs(Client *c, const Seperator *sep){ /* We use a general 'is_category_enabled' now, let's update when we update any output settings This is used in hot places of code to check if its enabled in any way before triggering logs */ - if (sep->arg[4] > 0){ + if (atoi(sep->arg[4] > 0){ Log.log_settings[atoi(sep->arg[3])].is_category_enabled = 1; } else{ From 153e587ceaf1e6e759a3c3766548b4bfdb38e9b3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 16 Mar 2017 12:56:21 -0400 Subject: [PATCH 634/693] Not sure how that happened --- zone/command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index dfe6b10e7..2a22bc82c 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -10686,7 +10686,7 @@ void command_logs(Client *c, const Seperator *sep){ /* We use a general 'is_category_enabled' now, let's update when we update any output settings This is used in hot places of code to check if its enabled in any way before triggering logs */ - if (atoi(sep->arg[4] > 0){ + if (atoi(sep->arg[4]) > 0){ Log.log_settings[atoi(sep->arg[3])].is_category_enabled = 1; } else{ From 94d8db4691dff22970d80da19d8dad2f248e33dd Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 16 Mar 2017 14:10:36 -0400 Subject: [PATCH 635/693] clang-tidy said this was a use-after-free Also, what is this code doing? --- zone/entity.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/entity.cpp b/zone/entity.cpp index 2bc1b99ed..4a6c2c20a 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2439,6 +2439,7 @@ void EntityList::UpdateWho(bool iSendFullUpdate) memcpy(pack->pBuffer, tmp, pack->size); pack->size = sizeof(ServerClientListKeepAlive_Struct) + (tmpNumUpdates * 4); safe_delete_array(tmp); + sclka = (ServerClientListKeepAlive_Struct*) pack->pBuffer; } sclka->wid[sclka->numupdates] = it->second->GetWID(); sclka->numupdates++; From fa1edee790344938a1294a2f24de02d05b039511 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 17 Mar 2017 20:37:48 -0400 Subject: [PATCH 636/693] Added clamp for EQEmuLogSys::LogSettings database values load --- common/database.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/database.cpp b/common/database.cpp index b06540cbd..3c4754495 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2056,6 +2056,8 @@ uint32 Database::GetGuildIDByCharID(uint32 character_id) void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings) { + // log_settings previously initialized to '0' by EQEmuLogSys::LoadLogSettingsDefaults() + std::string query = "SELECT " "log_category_id, " @@ -2073,6 +2075,9 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings) for (auto row = results.begin(); row != results.end(); ++row) { log_category = atoi(row[0]); + if (log_category <= Logs::None || log_category >= Logs::MaxCategoryID) + continue; + log_settings[log_category].log_to_console = atoi(row[2]); log_settings[log_category].log_to_file = atoi(row[3]); log_settings[log_category].log_to_gmsay = atoi(row[4]); From 16845c204c98e057ab07e4486e500544c4edb4a1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Mar 2017 00:34:49 -0400 Subject: [PATCH 637/693] Fix leak in Group::SendHPPacketsTo --- zone/groups.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/groups.cpp b/zone/groups.cpp index af505d3f2..85876bacc 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -397,6 +397,8 @@ void Group::SendHPPacketsTo(Mob *member) if(members[i] && members[i] != member) { members[i]->CreateHPPacket(&hpapp); + safe_delete_array(hpapp.pBuffer); + happ.size = 0; member->CastToClient()->QueuePacket(&hpapp, false); if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { From 3173c961fa880ba800fb796bf5a175ff2e4dd312 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Mar 2017 00:51:54 -0400 Subject: [PATCH 638/693] Fix typo --- zone/groups.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index 85876bacc..b2c916e63 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -398,7 +398,7 @@ void Group::SendHPPacketsTo(Mob *member) { members[i]->CreateHPPacket(&hpapp); safe_delete_array(hpapp.pBuffer); - happ.size = 0; + hpapp.size = 0; member->CastToClient()->QueuePacket(&hpapp, false); if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { From 13f49fe569b58365ec5ce516bfe8bc8b4f27e591 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Mar 2017 00:54:03 -0400 Subject: [PATCH 639/693] Fix uninit group value --- zone/groups.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/groups.cpp b/zone/groups.cpp index b2c916e63..dd1e54690 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -47,6 +47,7 @@ Group::Group(uint32 gid) AssistTargetID = 0; TankTargetID = 0; PullerTargetID = 0; + disbandcheck = false; memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct)); uint32 i; @@ -79,6 +80,7 @@ Group::Group(Mob* leader) AssistTargetID = 0; TankTargetID = 0; PullerTargetID = 0; + disbandcheck = false; memset(&LeaderAbilities, 0, sizeof(GroupLeadershipAA_Struct)); mentoree = nullptr; uint32 i; From 1ae66ce955409d47ecdf048721252315e86ac3f9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Mar 2017 00:59:13 -0400 Subject: [PATCH 640/693] Fix uninit jump in Client::Process --- zone/client.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index bf455a51f..beaa0970c 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -159,7 +159,8 @@ Client::Client(EQStreamInterface* ieqs) m_ZoneSummonLocation(-2.0f,-2.0f,-2.0f), m_AutoAttackPosition(0.0f, 0.0f, 0.0f, 0.0f), m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f), - last_region_type(RegionTypeUnsupported) + last_region_type(RegionTypeUnsupported), + m_dirtyautohaters(false) { for(int cf=0; cf < _FilterCount; cf++) ClientFilters[cf] = FilterShow; From 304d41e230181b89d75db49a84211a8ed8a2eb6e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Mar 2017 01:09:48 -0400 Subject: [PATCH 641/693] Fix fix memory leak fix --- zone/groups.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index dd1e54690..331303e8b 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -399,9 +399,9 @@ void Group::SendHPPacketsTo(Mob *member) if(members[i] && members[i] != member) { members[i]->CreateHPPacket(&hpapp); + member->CastToClient()->QueuePacket(&hpapp, false); safe_delete_array(hpapp.pBuffer); hpapp.size = 0; - member->CastToClient()->QueuePacket(&hpapp, false); if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); From 11e227756d3afbd44772ded4951a0db2f6f2fdac Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Mar 2017 01:15:08 -0400 Subject: [PATCH 642/693] Fix memory leak in raids --- zone/raids.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/raids.cpp b/zone/raids.cpp index 46dd4424e..070698e43 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -1555,6 +1555,8 @@ void Raid::SendHPPacketsTo(Client *c) { members[x].member->CreateHPPacket(&hpapp); c->QueuePacket(&hpapp, false); + safe_delete_array(hpapp.pBuffer); + hpapp.size = 0; if (c->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); From bafb199d24d9278af088263a62487c352f63a371 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Mar 2017 01:30:59 -0400 Subject: [PATCH 643/693] Fix encounters leaking? I didn't actually test this ... --- zone/entity.cpp | 14 +++++++++++++- zone/entity.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index 4a6c2c20a..18d55d695 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2224,7 +2224,8 @@ void EntityList::RemoveAllObjects() } } -void EntityList::RemoveAllTraps(){ +void EntityList::RemoveAllTraps() +{ auto it = trap_list.begin(); while (it != trap_list.end()) { safe_delete(it->second); @@ -2233,6 +2234,16 @@ void EntityList::RemoveAllTraps(){ } } +void EntityList::RemoveAllEncounters() +{ + auto it = encounter_list.begin(); + while (it != encounter_list.end()) { + safe_delete(it->second); + free_ids.push(it->first); + it = encounter_list.erase(it); + } +} + bool EntityList::RemoveMob(uint16 delete_id) { if (delete_id == 0) @@ -2410,6 +2421,7 @@ void EntityList::Clear() entity_list.RemoveAllDoors(); entity_list.RemoveAllObjects(); entity_list.RemoveAllRaids(); + entity_list.RemoveAllEncounters(); entity_list.RemoveAllLocalities(); } diff --git a/zone/entity.h b/zone/entity.h index 1ea9a4c03..0ee029940 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -292,6 +292,7 @@ public: void RemoveAllObjects(); void RemoveAllLocalities(); void RemoveAllRaids(); + void RemoveAllEncounters(); void DestroyTempPets(Mob *owner); int16 CountTempPets(Mob *owner); void AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy = false); From f64e1644b10ee96e4b5c9b17acbb20a065b4d1ec Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Mar 2017 14:11:30 -0400 Subject: [PATCH 644/693] Take 2 at fixing encounters --- zone/entity.cpp | 1 - zone/lua_parser.cpp | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index 18d55d695..5f20dffc7 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2421,7 +2421,6 @@ void EntityList::Clear() entity_list.RemoveAllDoors(); entity_list.RemoveAllObjects(); entity_list.RemoveAllRaids(); - entity_list.RemoveAllEncounters(); entity_list.RemoveAllLocalities(); } diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index d28c592a4..bf384c703 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -800,6 +800,9 @@ void LuaParser::ReloadQuests() { encounter.second->Depop(); } lua_encounters.clear(); + // so the Depop function above depends on the Process being called again so ... + // And there is situations where it wouldn't be :P + entity_list.EncounterProcess(); if(L) { lua_close(L); From d882c5fbf6cca1e5c8fb7167d980ecd3cbaf2a3d Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 18 Mar 2017 16:11:07 -0400 Subject: [PATCH 645/693] Fix for glitchy mercenary unsuspend button behavior (report any abnormalities) --- zone/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index beaa0970c..23a7213a3 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -625,7 +625,7 @@ bool Client::Save(uint8 iCommitNow) { GetMercInfo().MercTimerRemaining = GetMercTimer()->GetRemainingTime(); } - if (!(GetMerc() && !dead)) { + if (dead || (!GetMerc() && !GetMercInfo().IsSuspended)) { memset(&m_mercinfo, 0, sizeof(struct MercInfo)); } From 9510e8fbe1936f3728641acce396ffd46de198c0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 18 Mar 2017 16:59:46 -0400 Subject: [PATCH 646/693] This should resolve leaks and shutdown lua issues --- zone/lua_parser.cpp | 4 ++++ zone/net.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index bf384c703..92f0adbea 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -228,6 +228,10 @@ LuaParser::LuaParser() { } LuaParser::~LuaParser() { + // valgrind didn't like when we didn't clean these up :P + lua_encounters.clear(); + lua_encounter_events_registered.clear(); + lua_encounters_loaded.clear(); if(L) { lua_close(L); } diff --git a/zone/net.cpp b/zone/net.cpp index 935dace7d..2746595cf 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -560,6 +560,7 @@ int main(int argc, char** argv) { } entity_list.Clear(); + entity_list.RemoveAllEncounters(); // gotta do it manually or rewrite lots of shit :P parse->ClearInterfaces(); From 0ac70c545915b7ef4c0b3fd1f3f9dd8740fcf674 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 20 Mar 2017 19:45:26 -0400 Subject: [PATCH 647/693] SE_Taunt is a flat chance not a bonus to taunt chance --- zone/mob.h | 2 +- zone/special_attacks.cpp | 105 ++++++++++++++++++++------------------- zone/spell_effects.cpp | 2 +- 3 files changed, 56 insertions(+), 53 deletions(-) diff --git a/zone/mob.h b/zone/mob.h index 42672f046..81ef7d14a 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -843,7 +843,7 @@ public: void StartEnrage(); void ProcessEnrage(); bool IsEnraged(); - void Taunt(NPC* who, bool always_succeed, float chance_bonus=0, bool FromSpell=false, int32 bonus_hate=0); + void Taunt(NPC *who, bool always_succeed, int chance_bonus = 0, bool FromSpell = false, int32 bonus_hate = 0); virtual void AI_Init(); virtual void AI_Start(uint32 iMoveDelay = 0); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index a5cae5700..b982e3e30 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1868,18 +1868,18 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte) } } -void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus, bool FromSpell, int32 bonus_hate) { - +void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell, int32 bonus_hate) +{ if (who == nullptr) return; - if(DivineAura()) + if (DivineAura()) return; - if(!FromSpell && !CombatRange(who)) + if (!FromSpell && !CombatRange(who)) return; - if(!always_succeed && IsClient()) + if (!always_succeed && IsClient()) CastToClient()->CheckIncreaseSkill(EQEmu::skills::SkillTaunt, who, 10); Mob *hate_top = who->GetHateMost(); @@ -1887,69 +1887,73 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus, bool FromSpel int level_difference = GetLevel() - who->GetLevel(); bool Success = false; - //Support for how taunt worked pre 2000 on LIVE - Can not taunt NPC over your level. - if ((RuleB(Combat,TauntOverLevel) == false) && (level_difference < 0) || who->GetSpecialAbility(IMMUNE_TAUNT)){ - Message_StringID(MT_SpellFailure,FAILED_TAUNT); + // Support for how taunt worked pre 2000 on LIVE - Can not taunt NPC over your level. + if ((RuleB(Combat, TauntOverLevel) == false) && (level_difference < 0) || + who->GetSpecialAbility(IMMUNE_TAUNT)) { + Message_StringID(MT_SpellFailure, FAILED_TAUNT); return; } - //All values used based on live parses after taunt was updated in 2006. - if ((hate_top && hate_top->GetHPRatio() >= 20) || hate_top == nullptr) { + // All values used based on live parses after taunt was updated in 2006. + if ((hate_top && hate_top->GetHPRatio() >= 20) || hate_top == nullptr || chance_bonus) { + // SE_Taunt this is flat chance + if (chance_bonus) { + Success = zone->random.Roll(chance_bonus); + } else { + int32 newhate = 0; + float tauntchance = 50.0f; - int32 newhate = 0; - float tauntchance = 50.0f; - - if(always_succeed) - tauntchance = 101.0f; - - else { - - if (level_difference < 0){ - tauntchance += static_cast(level_difference)*3.0f; - if (tauntchance < 20) - tauntchance = 20.0f; - } + if (always_succeed) + tauntchance = 101.0f; else { - tauntchance += static_cast(level_difference)*5.0f; - if (tauntchance > 65) - tauntchance = 65.0f; + + if (level_difference < 0) { + tauntchance += static_cast(level_difference) * 3.0f; + if (tauntchance < 20) + tauntchance = 20.0f; + } + + else { + tauntchance += static_cast(level_difference) * 5.0f; + if (tauntchance > 65) + tauntchance = 65.0f; + } } + + // TauntSkillFalloff rate is not based on any real data. Default of 33% gives a reasonable + // result. + if (IsClient() && !always_succeed) + tauntchance -= (RuleR(Combat, TauntSkillFalloff) * + (CastToClient()->MaxSkill(EQEmu::skills::SkillTaunt) - + GetSkill(EQEmu::skills::SkillTaunt))); + + if (tauntchance < 1) + tauntchance = 1.0f; + + tauntchance /= 100.0f; + + Success = tauntchance > zone->random.Real(0, 1); } - //TauntSkillFalloff rate is not based on any real data. Default of 33% gives a reasonable result. - if (IsClient() && !always_succeed) - tauntchance -= (RuleR(Combat, TauntSkillFalloff) * (CastToClient()->MaxSkill(EQEmu::skills::SkillTaunt) - GetSkill(EQEmu::skills::SkillTaunt))); - - //From SE_Taunt (Does a taunt with a chance modifier) - if (chance_bonus) - tauntchance += tauntchance*chance_bonus/100.0f; - - if (tauntchance < 1) - tauntchance = 1.0f; - - tauntchance /= 100.0f; - - if (tauntchance > zone->random.Real(0, 1)) { - if (hate_top && hate_top != this){ + if (Success) { + if (hate_top && hate_top != this) { newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1 + bonus_hate; who->CastToNPC()->AddToHateList(this, newhate); Success = true; + } else { + who->CastToNPC()->AddToHateList(this, 12); } - else - who->CastToNPC()->AddToHateList(this,12); if (who->CanTalk()) - who->Say_StringID(SUCCESSFUL_TAUNT,GetCleanName()); - } - else{ - Message_StringID(MT_SpellFailure,FAILED_TAUNT); + who->Say_StringID(SUCCESSFUL_TAUNT, GetCleanName()); + } else { + Message_StringID(MT_SpellFailure, FAILED_TAUNT); } + } else { + Message_StringID(MT_SpellFailure, FAILED_TAUNT); } - else - Message_StringID(MT_SpellFailure,FAILED_TAUNT); - if (HasSkillProcs()) TrySkillProc(who, EQEmu::skills::SkillTaunt, TauntReuseTime * 1000); @@ -1957,7 +1961,6 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus, bool FromSpel TrySkillProc(who, EQEmu::skills::SkillTaunt, TauntReuseTime * 1000, true); } - void Mob::InstillDoubt(Mob *who) { //make sure we can use this skill /*int skill = GetSkill(INTIMIDATION);*/ //unused diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 132e6bcdb..40d85123f 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2676,7 +2676,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_Taunt: { if (caster && IsNPC()){ - caster->Taunt(this->CastToNPC(), false, static_cast(spell.base[i]), true, spell.base2[i]); + caster->Taunt(this->CastToNPC(), false, spell.base[i], true, spell.base2[i]); } break; } From 1e1de3a48af1aef020e7f09a2d0f3072ea986a59 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 20 Mar 2017 19:49:35 -0400 Subject: [PATCH 648/693] Fix error --- zone/special_attacks.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index b982e3e30..074d707a8 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1900,7 +1900,6 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell, if (chance_bonus) { Success = zone->random.Roll(chance_bonus); } else { - int32 newhate = 0; float tauntchance = 50.0f; if (always_succeed) @@ -1938,7 +1937,7 @@ void Mob::Taunt(NPC *who, bool always_succeed, int chance_bonus, bool FromSpell, if (Success) { if (hate_top && hate_top != this) { - newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1 + bonus_hate; + int newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1 + bonus_hate; who->CastToNPC()->AddToHateList(this, newhate); Success = true; } else { From e8a8647424169d8c8bc9e6be8969c53d80213173 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 22 Mar 2017 03:45:50 -0400 Subject: [PATCH 649/693] Fix for bots db update 9015 not triggering where update 9011 has not applied --- common/version.h | 2 +- utils/sql/git/bots/bots_db_update_manifest.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common/version.h b/common/version.h index 60d594dea..e000d4fc6 100644 --- a/common/version.h +++ b/common/version.h @@ -32,7 +32,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9107 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9015 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9016 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index c9a8999e1..a699be478 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -14,6 +14,7 @@ 9013|2017_02_26_bots_spells_id_update_for_saved_bots.sql|SELECT * FROM `bot_data` WHERE `spells_id` >= '701' AND `spells_id` <= '712'|not_empty| 9014|2017_02_26_bots_spells_id_update_for_bot_spells_entries.sql|SELECT * FROM `bot_spells_entries` WHERE `npc_spells_id` >= '701' AND `npc_spells_id` <= '712'|not_empty| 9015|2017_02_26_bots_spell_casting_chances_update.sql|SHOW COLUMNS FROM `bot_spell_casting_chances` LIKE 'value'|not_empty| +9016|2017_02_26_bots_spell_casting_chances_update.sql|SHOW TABLES LIKE 'bot_spell_casting_chances'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From 8bdefa17b5977c2382c2b4f8bebbd6817c11ced4 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 22 Mar 2017 13:39:12 -0500 Subject: [PATCH 650/693] Fix README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e1753680b..057937a0c 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ * Hundreds of Quests/events created and maintained by Project EQ ## Server Installs -||Windows|Linux| +| |Windows|Linux| |:---:|:---:|:---:| |**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)| ### > Windows From f77f996c3fec60b998977a11d0d18de5845557d1 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 23 Mar 2017 04:35:36 -0400 Subject: [PATCH 651/693] Pass through zone code to fix uninitialized pointer declarations --- zone/aggro.cpp | 8 +++---- zone/attack.cpp | 2 +- zone/bot.cpp | 52 ++++++++++++++++++++--------------------- zone/client.cpp | 20 ++++++++-------- zone/client_mods.cpp | 4 ++-- zone/client_packet.cpp | 32 ++++++++++++------------- zone/client_process.cpp | 4 ++-- zone/corpse.cpp | 16 ++++++------- zone/effects.cpp | 8 +++---- zone/merc.cpp | 12 +++++----- zone/mob.cpp | 12 +++++----- zone/pets.cpp | 2 +- zone/spell_effects.cpp | 16 ++++++------- zone/spells.cpp | 30 ++++++++++++------------ zone/zone.cpp | 6 ++--- zone/zoning.cpp | 4 ++-- 16 files changed, 114 insertions(+), 114 deletions(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index cc537662a..bf74f4b4d 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -550,8 +550,8 @@ faster, but I'm doing it this way to make it readable and easy to modify bool Mob::IsAttackAllowed(Mob *target, bool isSpellAttack) { - Mob *mob1, *mob2, *tempmob; - Client *c1, *c2, *becomenpc; + Mob *mob1 = nullptr, *mob2 = nullptr, *tempmob = nullptr; + Client *c1 = nullptr, *c2 = nullptr, *becomenpc = nullptr; // NPC *npc1, *npc2; int reverse; @@ -767,8 +767,8 @@ type', in which case, the answer is yes. // also goes for their pets bool Mob::IsBeneficialAllowed(Mob *target) { - Mob *mob1, *mob2, *tempmob; - Client *c1, *c2; + Mob *mob1 = nullptr, *mob2 = nullptr, *tempmob = nullptr; + Client *c1 = nullptr, *c2 = nullptr; int reverse; if(!target) diff --git a/zone/attack.cpp b/zone/attack.cpp index b0c056b30..5cd5aebae 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1268,7 +1268,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b if (GetFeigned()) return false; // Rogean: How can you attack while feigned? Moved up from Aggro Code. - EQEmu::ItemInstance* weapon; + EQEmu::ItemInstance* weapon = nullptr; if (Hand == EQEmu::inventory::slotSecondary){ // Kaiyodo - Pick weapon from the attacking hand weapon = GetInv().GetItem(EQEmu::inventory::slotSecondary); OffHandAtk(true); diff --git a/zone/bot.cpp b/zone/bot.cpp index 6ce4210b3..00bb96bfc 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1896,12 +1896,12 @@ void Bot::BotRangedAttack(Mob* other) { } EQEmu::ItemInstance* rangedItem = GetBotItem(EQEmu::inventory::slotRange); - const EQEmu::ItemData* RangeWeapon = 0; + const EQEmu::ItemData* RangeWeapon = nullptr; if(rangedItem) RangeWeapon = rangedItem->GetItem(); EQEmu::ItemInstance* ammoItem = GetBotItem(EQEmu::inventory::slotAmmo); - const EQEmu::ItemData* Ammo = 0; + const EQEmu::ItemData* Ammo = nullptr; if(ammoItem) Ammo = ammoItem->GetItem(); @@ -2008,7 +2008,7 @@ void Bot::ApplySpecialAttackMod(EQEmu::skills::SkillType skill, int32 &dmg, int3 if (item_slot >= EQEmu::legacy::EQUIPMENT_BEGIN){ const EQEmu::ItemInstance* inst = GetBotItem(item_slot); - const EQEmu::ItemData* botweapon = 0; + const EQEmu::ItemData* botweapon = nullptr; if(inst) botweapon = inst->GetItem(); @@ -2456,7 +2456,7 @@ void Bot::AI_Process() { //now off hand if(GetTarget() && attack_dw_timer.Check() && CanThisClassDualWield()) { const EQEmu::ItemInstance* instweapon = GetBotItem(EQEmu::inventory::slotSecondary); - const EQEmu::ItemData* weapon = 0; + const EQEmu::ItemData* weapon = nullptr; //can only dual wield without a weapon if you're a monk if(instweapon || (botClass == MONK)) { if(instweapon) @@ -2928,8 +2928,8 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; ns->spawn.helm = helmtexture; //(GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.equip_chest2 = texture; //0xFF; - const EQEmu::ItemData* item = 0; - const EQEmu::ItemInstance* inst = 0; + const EQEmu::ItemData* item = nullptr; + const EQEmu::ItemInstance* inst = nullptr; uint32 spawnedbotid = 0; spawnedbotid = this->GetBotID(); for (int i = EQEmu::textures::textureBegin; i < EQEmu::textures::weaponPrimary; i++) { @@ -4357,9 +4357,9 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[bottype]) { - const EQEmu::ItemData* TempItem = 0; - const EQEmu::ItemData* UsedItem = 0; - const EQEmu::ItemInstance* TempInst = 0; + const EQEmu::ItemData* TempItem = nullptr; + const EQEmu::ItemData* UsedItem = nullptr; + const EQEmu::ItemInstance* TempInst = nullptr; uint16 UsedFocusID = 0; int32 Total = 0; int32 focus_max = 0; @@ -5031,7 +5031,7 @@ void Bot::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 if (skill == EQEmu::skills::SkillBash) { const EQEmu::ItemInstance* inst = GetBotItem(EQEmu::inventory::slotSecondary); - const EQEmu::ItemData* botweapon = 0; + const EQEmu::ItemData* botweapon = nullptr; if(inst) botweapon = inst->GetItem(); @@ -5372,7 +5372,7 @@ FACTION_VALUE Bot::GetReverseFactionCon(Mob* iOther) { } Mob* Bot::GetOwnerOrSelf() { - Mob* Result = 0; + Mob* Result = nullptr; if(this->GetBotOwner()) Result = GetBotOwner(); else @@ -5382,7 +5382,7 @@ Mob* Bot::GetOwnerOrSelf() { } Mob* Bot::GetOwner() { - Mob* Result = 0; + Mob* Result = nullptr; Result = GetBotOwner(); if(!Result) this->SetBotOwner(0); @@ -5438,8 +5438,8 @@ bool Bot::IsBotAttackAllowed(Mob* attacker, Mob* target, bool& hasRuleDefined) { void Bot::EquipBot(std::string* errorMessage) { GetBotItems(m_inv, errorMessage); - const EQEmu::ItemInstance* inst = 0; - const EQEmu::ItemData* item = 0; + const EQEmu::ItemInstance* inst = nullptr; + const EQEmu::ItemData* item = nullptr; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { inst = GetBotItem(i); if(inst) { @@ -7235,7 +7235,7 @@ bool Bot::CanHeal() { } Bot* Bot::GetBotByBotClientOwnerAndBotName(Client* c, std::string botName) { - Bot* Result = 0; + Bot* Result = nullptr; if(c) { std::list BotList = entity_list.GetBotsByBotOwnerCharacterID(c->CharacterID()); if(!BotList.empty()) { @@ -7275,7 +7275,7 @@ void Bot::ProcessBotGroupInvite(Client* c, std::string botName) { // Processes a group disband request from a Client for a Bot. void Bot::ProcessBotGroupDisband(Client* c, std::string botName) { if(c) { - Bot* tempBot = 0; + Bot* tempBot = nullptr; if(botName.empty()) tempBot = GetFirstBotInGroup(c->GetGroup()); @@ -7318,7 +7318,7 @@ void Bot::ProcessClientZoneChange(Client* botOwner) { // Finds and returns the first Bot object found in specified group Bot* Bot::GetFirstBotInGroup(Group* group) { - Bot* Result = 0; + Bot* Result = nullptr; if(group) { for(int Counter = 0; Counter < MAX_GROUP_MEMBERS; Counter++) { @@ -7344,8 +7344,8 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { insr->TargetID = inspectedBot->GetNPCTypeID(); insr->playerid = inspectedBot->GetID(); - const EQEmu::ItemData* item = 0; - const EQEmu::ItemInstance* inst = 0; + const EQEmu::ItemData* item = nullptr; + const EQEmu::ItemInstance* inst = nullptr; // Modded to display power source items (will only show up on SoF+ client inspect windows though.) // I don't think bots are currently coded to use them..but, you'll have to use '#bot inventory list' @@ -7396,7 +7396,7 @@ void Bot::ProcessBotInspectionRequest(Bot* inspectedBot, Client* client) { void Bot::CalcItemBonuses(StatBonuses* newbon) { - const EQEmu::ItemData* itemtmp = 0; + const EQEmu::ItemData* itemtmp = nullptr; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= (EQEmu::legacy::EQUIPMENT_END + 1); ++i) { const EQEmu::ItemInstance* item = GetBotItem((i == 22 ? 9999 : i)); @@ -7989,7 +7989,7 @@ bool EntityList::Bot_AICheckCloseBeneficialSpells(Bot* caster, uint8 iChance, fl Mob* EntityList::GetMobByBotID(uint32 botID) { - Mob* Result = 0; + Mob* Result = nullptr; if(botID > 0) { auto it = mob_list.begin(); for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { @@ -8006,7 +8006,7 @@ Mob* EntityList::GetMobByBotID(uint32 botID) { } Bot* EntityList::GetBotByBotID(uint32 botID) { - Bot* Result = 0; + Bot* Result = nullptr; if(botID > 0) { for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; @@ -8020,7 +8020,7 @@ Bot* EntityList::GetBotByBotID(uint32 botID) { } Bot* EntityList::GetBotByBotName(std::string botName) { - Bot* Result = 0; + Bot* Result = nullptr; if(!botName.empty()) { for(std::list::iterator botListItr = bot_list.begin(); botListItr != bot_list.end(); ++botListItr) { Bot* tempBot = *botListItr; @@ -8197,7 +8197,7 @@ void EntityList::ShowSpawnWindow(Client* client, int Distance, bool NamedOnly) { uint8 Bot::GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets) { uint8 needHealed = 0; - Group *g; + Group *g = nullptr; if(this->HasGroup()) { g = this->GetGroup(); if(g) { @@ -8237,8 +8237,8 @@ int Bot::GetRawACNoShield(int &shield_ac) { } uint32 Bot::CalcCurrentWeight() { - const EQEmu::ItemData* TempItem = 0; - EQEmu::ItemInstance* inst; + const EQEmu::ItemData* TempItem = nullptr; + EQEmu::ItemInstance* inst = nullptr; uint32 Total = 0; for (int i = EQEmu::legacy::EQUIPMENT_BEGIN; i <= EQEmu::legacy::EQUIPMENT_END; ++i) { inst = GetBotItem(i); diff --git a/zone/client.cpp b/zone/client.cpp index 23a7213a3..fa683a267 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -717,7 +717,7 @@ bool Client::AddPacket(EQApplicationPacket** pApp, bool bAckreq) { c->ack_req = bAckreq; c->app = *pApp; - *pApp = 0; + *pApp = nullptr; clientpackets.Append(c); return true; @@ -726,7 +726,7 @@ bool Client::AddPacket(EQApplicationPacket** pApp, bool bAckreq) { bool Client::SendAllPackets() { LinkedListIterator iterator(clientpackets); - CLIENTPACKET* cp = 0; + CLIENTPACKET* cp = nullptr; iterator.Reset(); while(iterator.MoreElements()) { cp = iterator.GetData(); @@ -772,7 +772,7 @@ void Client::FastQueuePacket(EQApplicationPacket** app, bool ack_req, CLIENT_CON eqs->FastQueuePacket((EQApplicationPacket **)app, ack_req); else if (app && (*app)) delete *app; - *app = 0; + *app = nullptr; } return; } @@ -2038,7 +2038,7 @@ void Client::ReadBook(BookRequest_Struct *book) { read_from_slot = book->invslot -1; } - const EQEmu::ItemInstance *inst = 0; + const EQEmu::ItemInstance *inst = nullptr; if (read_from_slot <= EQEmu::legacy::SLOT_PERSONAL_BAGS_END) { @@ -4046,7 +4046,7 @@ bool Client::KeyRingCheck(uint32 item_id) void Client::KeyRingList() { Message(4,"Keys on Keyring:"); - const EQEmu::ItemData *item = 0; + const EQEmu::ItemData *item = nullptr; for (auto iter = keyring.begin(); iter != keyring.end(); ++iter) { if ((item = database.GetItem(*iter))!=nullptr) { Message(4,item->Name); @@ -4659,7 +4659,7 @@ void Client::SendRespawnBinds() uint32 PacketLength = 17 + (26 * num_options); //Header size + per-option invariant size std::list::iterator itr; - RespawnOption* opt; + RespawnOption* opt = nullptr; //Find string size for each option for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) @@ -8385,7 +8385,7 @@ bool Client::RemoveRespawnOption(std::string option_name) if (IsHoveringForRespawn() || respawn_options.empty()) { return false; } bool had = false; - RespawnOption* opt; + RespawnOption* opt = nullptr; std::list::iterator itr; for (itr = respawn_options.begin(); itr != respawn_options.end(); ++itr) { @@ -8432,7 +8432,7 @@ bool Client::RemoveRespawnOption(uint8 position) void Client::SetHunger(int32 in_hunger) { - EQApplicationPacket *outapp; + EQApplicationPacket *outapp = nullptr; outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer; sta->food = in_hunger; @@ -8446,7 +8446,7 @@ void Client::SetHunger(int32 in_hunger) void Client::SetThirst(int32 in_thirst) { - EQApplicationPacket *outapp; + EQApplicationPacket *outapp = nullptr; outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer; sta->food = m_pp.hunger_level > 6000 ? 6000 : m_pp.hunger_level; @@ -8460,7 +8460,7 @@ void Client::SetThirst(int32 in_thirst) void Client::SetConsumption(int32 in_hunger, int32 in_thirst) { - EQApplicationPacket *outapp; + EQApplicationPacket *outapp = nullptr; outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer; sta->food = in_hunger; diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 3d3a1d529..e97aa026c 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1211,8 +1211,8 @@ int32 Client::CalcManaRegenCap() uint32 Client::CalcCurrentWeight() { - const EQEmu::ItemData* TempItem = 0; - EQEmu::ItemInstance* ins; + const EQEmu::ItemData* TempItem = nullptr; + EQEmu::ItemInstance* ins = nullptr; uint32 Total = 0; int x; for (x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::inventory::slotCursor; x++) { // include cursor or not? diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 4b3817e9a..1616ac687 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1074,7 +1074,7 @@ void Client::Handle_Connect_OP_ReqNewZone(const EQApplicationPacket *app) { conn_state = NewZoneRequested; - EQApplicationPacket* outapp; + EQApplicationPacket* outapp = nullptr; ///////////////////////////////////// // New Zone Packet @@ -1240,12 +1240,12 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) } uint32 pplen = 0; - EQApplicationPacket* outapp = 0; - MYSQL_RES* result = 0; + EQApplicationPacket* outapp = nullptr; + MYSQL_RES* result = nullptr; bool loaditems = 0; uint32 i; std::string query; - unsigned long* lengths; + unsigned long* lengths = nullptr; uint32 cid = CharacterID(); character_id = cid; /* Global character_id reference */ @@ -2062,7 +2062,7 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app) merchantid = tmp->CastToNPC()->MerchantType; tmp->CastToNPC()->FaceTarget(this->CastToMob()); - const EQEmu::ItemData *item = 0; + const EQEmu::ItemData *item = nullptr; std::list merlist = zone->merchanttable[merchantid]; std::list::const_iterator itr; for (itr = merlist.begin(); itr != merlist.end() && count<255; ++itr){ @@ -4867,7 +4867,7 @@ void Client::Handle_OP_Consume(const EQApplicationPacket *app) { if (m_pp.hunger_level > 6000) { - EQApplicationPacket *outapp; + EQApplicationPacket *outapp = nullptr; outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer; sta->food = m_pp.hunger_level > 6000 ? 6000 : m_pp.hunger_level; @@ -4882,7 +4882,7 @@ void Client::Handle_OP_Consume(const EQApplicationPacket *app) { if (m_pp.thirst_level > 6000) { - EQApplicationPacket *outapp; + EQApplicationPacket *outapp = nullptr; outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer; sta->food = m_pp.hunger_level > 6000 ? 6000 : m_pp.hunger_level; @@ -4915,7 +4915,7 @@ void Client::Handle_OP_Consume(const EQApplicationPacket *app) m_pp.hunger_level = 50000; if (m_pp.thirst_level > 50000) m_pp.thirst_level = 50000; - EQApplicationPacket *outapp; + EQApplicationPacket *outapp = nullptr; outapp = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); Stamina_Struct* sta = (Stamina_Struct*)outapp->pBuffer; sta->food = m_pp.hunger_level > 6000 ? 6000 : m_pp.hunger_level; @@ -5903,7 +5903,7 @@ void Client::Handle_OP_GMEmoteZone(const EQApplicationPacket *app) return; } GMEmoteZone_Struct* gmez = (GMEmoteZone_Struct*)app->pBuffer; - char* newmessage = 0; + char* newmessage = nullptr; if (strstr(gmez->text, "^") == 0) entity_list.Message(0, 15, gmez->text); else{ @@ -8259,7 +8259,7 @@ void Client::Handle_OP_ItemName(const EQApplicationPacket *app) return; } ItemNamePacket_Struct *p = (ItemNamePacket_Struct*)app->pBuffer; - const EQEmu::ItemData *item = 0; + const EQEmu::ItemData *item = nullptr; if ((item = database.GetItem(p->item_id)) != nullptr) { auto outapp = new EQApplicationPacket(OP_ItemName, sizeof(ItemNamePacket_Struct)); p = (ItemNamePacket_Struct*)outapp->pBuffer; @@ -8466,7 +8466,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) target_id = request->target; - EQApplicationPacket *outapp; + EQApplicationPacket *outapp = nullptr; outapp = new EQApplicationPacket(OP_ItemVerifyReply, sizeof(ItemVerifyReply_Struct)); ItemVerifyReply_Struct* reply = (ItemVerifyReply_Struct*)outapp->pBuffer; reply->slot = slot_id; @@ -8540,8 +8540,8 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) int r; bool tryaug = false; - EQEmu::ItemInstance* clickaug = 0; - EQEmu::ItemData* augitem = 0; + EQEmu::ItemInstance* clickaug = nullptr; + EQEmu::ItemData* augitem = nullptr; for (r = EQEmu::inventory::socketBegin; r < EQEmu::inventory::SocketCount; r++) { const EQEmu::ItemInstance* aug_i = inst->GetAugment(r); @@ -8670,7 +8670,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) if (m_pp.thirst_level > 6000) m_pp.thirst_level = 6000; - EQApplicationPacket *outapp2; + EQApplicationPacket *outapp2 = nullptr; outapp2 = new EQApplicationPacket(OP_Stamina, sizeof(Stamina_Struct)); Stamina_Struct* sta = (Stamina_Struct*)outapp2->pBuffer; sta->food = m_pp.hunger_level; @@ -9195,7 +9195,7 @@ void Client::Handle_OP_LootItem(const EQApplicationPacket *app) return; } - EQApplicationPacket* outapp = 0; + EQApplicationPacket* outapp = nullptr; Entity* entity = entity_list.GetID(*((uint16*)app->pBuffer)); if (entity == 0) { Message(13, "Error: OP_LootItem: Corpse not found (ent = 0)"); @@ -12022,7 +12022,7 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app) else zoneid = atoi(row[0]); - char* name; + char* name = nullptr; database.GetZoneLongName(database.GetZoneName(zoneid), &name); Message(15, "%d - %s", zoneid, name); } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 2bfa8a055..57ed6283c 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -210,7 +210,7 @@ bool Client::Process() { if (bardsong_timer.Check() && bardsong != 0) { //NOTE: this is kinda a heavy-handed check to make sure the mob still exists before //doing the next pulse on them... - Mob *song_target; + Mob *song_target = nullptr; if(bardsong_target_id == GetID()) { song_target = this; } else { @@ -838,7 +838,7 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { if (m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater) { // RoF+ can send 200 items numItemSlots = 200; } - const EQEmu::ItemData *item; + const EQEmu::ItemData *item = nullptr; std::list merlist = zone->merchanttable[merchant_id]; std::list::const_iterator itr; Mob* merch = entity_list.GetMobByNpcTypeID(npcid); diff --git a/zone/corpse.cpp b/zone/corpse.cpp index a1cc8c69d..1bfc4ef10 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -82,7 +82,7 @@ Corpse* Corpse::LoadCharacterCorpseEntity(uint32 in_dbid, uint32 in_charid, std: /* Load Items */ ItemList itemlist; - ServerLootItem_Struct* tmp = 0; + ServerLootItem_Struct* tmp = nullptr; for (unsigned int i = 0; i < pcs->itemcount; i++) { tmp = new ServerLootItem_Struct; memcpy(tmp, &pcs->items[i], sizeof(player_lootitem::ServerLootItem_Struct)); @@ -267,7 +267,7 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( int i; PlayerProfile_Struct *pp = &client->GetPP(); - EQEmu::ItemInstance *item; + EQEmu::ItemInstance *item = nullptr; /* Check if Zone has Graveyard First */ if(!zone->HasGraveyard()) { @@ -671,7 +671,7 @@ void Corpse::AddItem(uint32 itemnum, uint16 charges, int16 slot, uint32 aug1, ui } ServerLootItem_Struct* Corpse::GetItem(uint16 lootslot, ServerLootItem_Struct** bag_item_data) { - ServerLootItem_Struct *sitem = 0, *sitem2; + ServerLootItem_Struct *sitem = nullptr, *sitem2 = nullptr; ItemList::iterator cur,end; cur = itemlist.begin(); @@ -993,7 +993,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a } int i = 0; - const EQEmu::ItemData* item = 0; + const EQEmu::ItemData* item = nullptr; ItemList::iterator cur,end; cur = itemlist.begin(); end = itemlist.end(); @@ -1116,9 +1116,9 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app) return; } - const EQEmu::ItemData *item = 0; - EQEmu::ItemInstance *inst = 0; - ServerLootItem_Struct *item_data = nullptr, *bag_item_data[10]; + const EQEmu::ItemData *item = nullptr; + EQEmu::ItemInstance *inst = nullptr; + ServerLootItem_Struct *item_data = nullptr, *bag_item_data[10] = {}; memset(bag_item_data, 0, sizeof(bag_item_data)); if (GetPlayerKillItem() > 1) { @@ -1437,7 +1437,7 @@ uint32 Corpse::GetEquipment(uint8 material_slot) const { } uint32 Corpse::GetEquipmentColor(uint8 material_slot) const { - const EQEmu::ItemData *item; + const EQEmu::ItemData *item = nullptr; if (material_slot > EQEmu::textures::LastTexture) { return 0; diff --git a/zone/effects.cpp b/zone/effects.cpp index 400bae1fa..202ca6237 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -747,7 +747,7 @@ void EntityList::AETaunt(Client* taunter, float range, int32 bonus_hate) // NPC spells will only affect other NPCs with compatible faction void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust) { - Mob *curmob; + Mob *curmob = nullptr; float dist = caster->GetAOERange(spell_id); float dist2 = dist * dist; @@ -847,7 +847,7 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ void EntityList::MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster) { - Mob *curmob; + Mob *curmob = nullptr; float dist = caster->GetAOERange(spell_id); float dist2 = dist * dist; @@ -888,7 +888,7 @@ void EntityList::MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool a // NPC spells will only affect other NPCs with compatible faction void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster) { - Mob *curmob; + Mob *curmob = nullptr; float dist = caster->GetAOERange(spell_id); float dist2 = dist * dist; @@ -940,7 +940,7 @@ void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool aff //NPCs handle it differently in Mob::Rampage void EntityList::AEAttack(Mob *attacker, float dist, int Hand, int count, bool IsFromSpell) { //Dook- Will need tweaking, currently no pets or players or horses - Mob *curmob; + Mob *curmob = nullptr; float dist2 = dist * dist; diff --git a/zone/merc.cpp b/zone/merc.cpp index 5f8ea59ea..6a1957d45 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -2183,7 +2183,7 @@ bool Merc::AICastSpell(int8 iChance, uint32 iSpellTypes) { } if(castedSpell) { - char* gmsg = 0; + char* gmsg = nullptr; if(tar != this) { //we don't need spam of bots healing themselves @@ -2606,8 +2606,8 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) { //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[type]){ - const EQEmu::ItemData* TempItem = 0; - const EQEmu::ItemData* UsedItem = 0; + const EQEmu::ItemData* TempItem = nullptr; + const EQEmu::ItemData* UsedItem = nullptr; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -4556,7 +4556,7 @@ void Merc::SetTarget(Mob* mob) { } Mob* Merc::GetOwnerOrSelf() { - Mob* Result = 0; + Mob* Result = nullptr; if(this->GetMercOwner()) Result = GetMercOwner(); @@ -4591,7 +4591,7 @@ bool Merc::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Skil } Client* Merc::GetMercOwner() { - Client* mercOwner = 0; + Client* mercOwner = nullptr; if(GetOwner()) { @@ -4605,7 +4605,7 @@ Client* Merc::GetMercOwner() { } Mob* Merc::GetOwner() { - Mob* Result = 0; + Mob* Result = nullptr; Result = entity_list.GetMob(GetOwnerID()); diff --git a/zone/mob.cpp b/zone/mob.cpp index e7b248dd5..9bde2cc0e 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1292,7 +1292,7 @@ void Mob::CreateHPPacket(EQApplicationPacket* app) void Mob::SendHPUpdate(bool skip_self) { EQApplicationPacket hp_app; - Group *group; + Group *group = nullptr; // destructor will free the pBuffer CreateHPPacket(&hp_app); @@ -2787,7 +2787,7 @@ void Mob::SendArmorAppearance(Client *one_client) { if (!IsClient()) { - const EQEmu::ItemData *item; + const EQEmu::ItemData *item = nullptr; for (int i = 0; i < 7; ++i) { item = database.GetItem(GetEquipment(i)); @@ -2905,7 +2905,7 @@ int32 Mob::GetEquipmentMaterial(uint8 material_slot) const { uint32 equipmaterial = 0; int32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - const EQEmu::ItemData *item; + const EQEmu::ItemData *item = nullptr; item = database.GetItem(GetEquipment(material_slot)); if (item != 0) @@ -2958,7 +2958,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const if (material_slot >= 0 && material_slot < EQEmu::textures::weaponPrimary) { uint32 ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - const EQEmu::ItemData *item; + const EQEmu::ItemData *item = nullptr; item = database.GetItem(GetEquipment(material_slot)); int16 invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot); @@ -3012,7 +3012,7 @@ int32 Mob::GetHerosForgeModel(uint8 material_slot) const uint32 Mob::GetEquipmentColor(uint8 material_slot) const { - const EQEmu::ItemData *item; + const EQEmu::ItemData *item = nullptr; if (armor_tint.Slot[material_slot].Color) { @@ -3028,7 +3028,7 @@ uint32 Mob::GetEquipmentColor(uint8 material_slot) const uint32 Mob::IsEliteMaterialItem(uint8 material_slot) const { - const EQEmu::ItemData *item; + const EQEmu::ItemData *item = nullptr; item = database.GetItem(GetEquipment(material_slot)); if(item != 0) diff --git a/zone/pets.cpp b/zone/pets.cpp index b9ccafe38..a73f6b54d 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -425,7 +425,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, // like the special back items some focused pets may receive. uint32 petinv[EQEmu::legacy::EQUIPMENT_SIZE]; memset(petinv, 0, sizeof(petinv)); - const EQEmu::ItemData *item = 0; + const EQEmu::ItemData *item = nullptr; if (database.GetBasePetItems(record.equipmentset, petinv)) { for (int i = 0; i < EQEmu::legacy::EQUIPMENT_SIZE; i++) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 40d85123f..b6a3d835d 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -438,7 +438,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove { float x, y, z, heading; - const char *target_zone; + const char *target_zone = nullptr; x = static_cast(spell.base[1]); y = static_cast(spell.base[0]); @@ -510,7 +510,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_Teleport2: { float x, y, z, heading; - const char *target_zone; + const char *target_zone = nullptr; x = static_cast(spell.base[1]); y = static_cast(spell.base[0]); @@ -1723,7 +1723,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove #endif // can only summon corpses of clients if(!IsNPC()) { - Client* TargetClient = 0; + Client* TargetClient = nullptr; if(this->GetTarget()) TargetClient = this->GetTarget()->CastToClient(); else @@ -5177,7 +5177,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { //item focus if (itembonuses.FocusEffects[type]){ - const EQEmu::ItemData* TempItem = 0; + const EQEmu::ItemData* TempItem = nullptr; for (int x = EQEmu::legacy::EQUIPMENT_BEGIN; x <= EQEmu::legacy::EQUIPMENT_END; x++) { @@ -5306,8 +5306,8 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) //Check if item focus effect exists for the client. if (itembonuses.FocusEffects[type]){ - const EQEmu::ItemData* TempItem = 0; - const EQEmu::ItemData* UsedItem = 0; + const EQEmu::ItemData* TempItem = nullptr; + const EQEmu::ItemData* UsedItem = nullptr; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; @@ -5578,8 +5578,8 @@ int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) { if (RuleB(Spells, NPC_UseFocusFromItems) && itembonuses.FocusEffects[type]){ - const EQEmu::ItemData* TempItem = 0; - const EQEmu::ItemData* UsedItem = 0; + const EQEmu::ItemData* TempItem = nullptr; + const EQEmu::ItemData* UsedItem = nullptr; uint16 UsedFocusID = 0; int16 Total = 0; int16 focus_max = 0; diff --git a/zone/spells.cpp b/zone/spells.cpp index af09c14a3..e3ec41f30 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -826,7 +826,7 @@ void Mob::InterruptSpell(uint16 spellid) // color not used right now void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid) { - EQApplicationPacket *outapp; + EQApplicationPacket *outapp = nullptr; uint16 message_other; bool bard_song_mode = false; //has the bard song gone to auto repeat mode if (spellid == SPELL_UNKNOWN) { @@ -1267,7 +1267,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, CastingSlot slo { bool fromaug = false; const EQEmu::ItemInstance* inst = CastToClient()->GetInv()[inventory_slot]; - EQEmu::ItemData* augitem = 0; + EQEmu::ItemData* augitem = nullptr; uint32 recastdelay = 0; uint32 recasttype = 0; @@ -3428,7 +3428,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r } } - EQApplicationPacket *action_packet, *message_packet; + EQApplicationPacket *action_packet = nullptr, *message_packet = nullptr; float spell_effectiveness; if(!IsValidSpell(spell_id)) @@ -3621,19 +3621,19 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r spelltar != this) { - Client* pClient = 0; - Raid* pRaid = 0; - Group* pBasicGroup = 0; + Client* pClient = nullptr; + Raid* pRaid = nullptr; + Group* pBasicGroup = nullptr; uint32 nGroup = 0; //raid group - Client* pClientTarget = 0; - Raid* pRaidTarget = 0; - Group* pBasicGroupTarget = 0; + Client* pClientTarget = nullptr; + Raid* pRaidTarget = nullptr; + Group* pBasicGroupTarget = nullptr; uint32 nGroupTarget = 0; //raid group - Client* pClientTargetPet = 0; - Raid* pRaidTargetPet = 0; - Group* pBasicGroupTargetPet = 0; + Client* pClientTargetPet = nullptr; + Raid* pRaidTargetPet = nullptr; + Group* pBasicGroupTargetPet = nullptr; uint32 nGroupTargetPet = 0; //raid group const uint32 cnWTF = 0xFFFFFFFF + 1; //this should be zero unless on 64bit? forced uint64? @@ -4936,7 +4936,7 @@ void Mob::Mesmerize() void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message) { - EQApplicationPacket* outapp; + EQApplicationPacket* outapp = nullptr; outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffPacket_Struct)); SpellBuffPacket_Struct* sbf = (SpellBuffPacket_Struct*) outapp->pBuffer; @@ -5416,7 +5416,7 @@ void Mob::_StopSong() //be used for other things as well void Client::SendBuffDurationPacket(Buffs_Struct &buff, int slot) { - EQApplicationPacket* outapp; + EQApplicationPacket* outapp = nullptr; outapp = new EQApplicationPacket(OP_Buff, sizeof(SpellBuffPacket_Struct)); SpellBuffPacket_Struct* sbf = (SpellBuffPacket_Struct*) outapp->pBuffer; @@ -5452,7 +5452,7 @@ void Client::SendBuffNumHitPacket(Buffs_Struct &buff, int slot) // UF+ use this packet if (ClientVersion() < EQEmu::versions::ClientVersion::UF) return; - EQApplicationPacket *outapp; + EQApplicationPacket *outapp = nullptr; outapp = new EQApplicationPacket(OP_BuffCreate, sizeof(BuffIcon_Struct) + sizeof(BuffIconEntry_Struct)); BuffIcon_Struct *bi = (BuffIcon_Struct *)outapp->pBuffer; bi->entity_id = GetID(); diff --git a/zone/zone.cpp b/zone/zone.cpp index ab0a9b6e4..599e5e802 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -290,7 +290,7 @@ bool Zone::LoadGroundSpawns() { Log.Out(Logs::General, Logs::Status, "Loading Ground Spawns from DB..."); database.LoadGroundSpawns(zoneid, GetInstanceVersion(), &groundspawn); uint32 ix=0; - char* name=0; + char* name = nullptr; uint32 gsnumber=0; for(gsindex=0;gsindex<50;gsindex++){ if(groundspawn.spawn[gsindex].item>0 && groundspawn.spawn[gsindex].item iterator(zone_point_list); - ZonePoint* closest_zp = 0; + ZonePoint* closest_zp = nullptr; float closest_dist = FLT_MAX; float max_distance2 = max_distance * max_distance; iterator.Reset(); @@ -1625,7 +1625,7 @@ ZonePoint* Zone::GetClosestZonePoint(const glm::vec3& location, const char* to_n ZonePoint* Zone::GetClosestZonePointWithoutZone(float x, float y, float z, Client* client, float max_distance) { LinkedListIterator iterator(zone_point_list); - ZonePoint* closest_zp = 0; + ZonePoint* closest_zp = nullptr; float closest_dist = FLT_MAX; float max_distance2 = max_distance*max_distance; iterator.Reset(); diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 30dc4d81f..677dd3d18 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -297,7 +297,7 @@ void Client::SendZoneCancel(ZoneChange_Struct *zc) { //effectively zone them right back to where they were //unless we find a better way to stop the zoning process. SetPortExemption(true); - EQApplicationPacket *outapp; + EQApplicationPacket *outapp = nullptr; outapp = new EQApplicationPacket(OP_ZoneChange, sizeof(ZoneChange_Struct)); ZoneChange_Struct *zc2 = (ZoneChange_Struct*)outapp->pBuffer; strcpy(zc2->char_name, zc->char_name); @@ -316,7 +316,7 @@ void Client::SendZoneError(ZoneChange_Struct *zc, int8 err) SetPortExemption(true); - EQApplicationPacket *outapp; + EQApplicationPacket *outapp = nullptr; outapp = new EQApplicationPacket(OP_ZoneChange, sizeof(ZoneChange_Struct)); ZoneChange_Struct *zc2 = (ZoneChange_Struct*)outapp->pBuffer; strcpy(zc2->char_name, zc->char_name); From 9e417955949df27afb476e95cfb0e7bbc831a207 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 25 Mar 2017 15:44:38 -0400 Subject: [PATCH 652/693] Test fix for heal rotations crashing server surrounding player zoning --- zone/heal_rotation.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/heal_rotation.cpp b/zone/heal_rotation.cpp index 6981cc0c1..96703818f 100644 --- a/zone/heal_rotation.cpp +++ b/zone/heal_rotation.cpp @@ -646,7 +646,10 @@ void HealRotation::bias_targets() // attempt to clear invalid target pool entries m_target_pool.remove(nullptr); - m_target_pool.remove_if([](Mob* l) { return (!IsHealRotationTargetMobType(l)); }); + m_target_pool.remove_if([](Mob* l) { + try { return (!IsHealRotationTargetMobType(l)); } + catch (...) { return true; } + }); uint32 sort_type = 0; // debug From 719098a97ce43225a0d9a3bd51b1358690efb3f6 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 25 Mar 2017 23:32:49 -0500 Subject: [PATCH 653/693] [Performance] Reduced CPU footprint in non-combat zones doing constant checks for combat related activities --- changelog.txt | 3 ++ zone/client_process.cpp | 2 +- zone/mob_ai.cpp | 107 ++++++++++++++++++++++------------------ 3 files changed, 62 insertions(+), 50 deletions(-) diff --git a/changelog.txt b/changelog.txt index 9514c812c..ea457ed67 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/25/2017 == +Akkadius: Reduced CPU footprint in non-combat zones doing constant checks for combat related activities + == 03/12/2017 == Akkadius: - Implemented range rules for packets and other functions diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 57ed6283c..b2a010542 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -616,7 +616,7 @@ bool Client::Process() { //At this point, we are still connected, everything important has taken //place, now check to see if anybody wants to aggro us. // only if client is not feigned - if(ret && !GetFeigned() && scanarea_timer.Check()) { + if(zone->CanDoCombat() && ret && !GetFeigned() && scanarea_timer.Check()) { entity_list.CheckClientAggro(this); } #endif diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index f6e6fa019..d0298ac55 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -726,6 +726,7 @@ void Client::AI_SpellCast() void Client::AI_Process() { + if (!IsAIControlled()) return; @@ -956,6 +957,10 @@ void Mob::AI_Process() { bool engaged = IsEngaged(); bool doranged = false; + if (!zone->CanDoCombat()) { + engaged = false; + } + // Begin: Additions for Wiz Fear Code // if(RuleB(Combat, EnableFearPathing)){ @@ -1016,13 +1021,14 @@ void Mob::AI_Process() { SetTarget(hate_list.GetClosestEntOnHateList(this)); else { - if(AI_target_check_timer->Check()) + if (AI_target_check_timer->Check()) { if (IsFocused()) { if (!target) { SetTarget(hate_list.GetEntWithMostHateOnList(this)); } - } else { + } + else { if (!ImprovedTaunt()) SetTarget(hate_list.GetEntWithMostHateOnList(this)); } @@ -1042,28 +1048,29 @@ void Mob::AI_Process() { #ifdef BOTS if (IsPet() && GetOwner() && GetOwner()->IsBot() && target == GetOwner()) { - // this blocks all pet attacks against owner..bot pet test (copied above check) - RemoveFromHateList(this); - return; + // this blocks all pet attacks against owner..bot pet test (copied above check) + RemoveFromHateList(this); + return; } #endif //BOTS - if(DivineAura()) + if (DivineAura()) return; - auto npcSpawnPoint = CastToNPC()->GetSpawnPoint(); - if(GetSpecialAbility(TETHER)) { + auto npcSpawnPoint = CastToNPC()->GetSpawnPoint(); + if (GetSpecialAbility(TETHER)) { float tether_range = static_cast(GetSpecialAbilityParam(TETHER, 0)); tether_range = tether_range > 0.0f ? tether_range * tether_range : pAggroRange * pAggroRange; - if(DistanceSquaredNoZ(m_Position, npcSpawnPoint) > tether_range) { + if (DistanceSquaredNoZ(m_Position, npcSpawnPoint) > tether_range) { GMMove(npcSpawnPoint.x, npcSpawnPoint.y, npcSpawnPoint.z, npcSpawnPoint.w); } - } else if(GetSpecialAbility(LEASH)) { + } + else if (GetSpecialAbility(LEASH)) { float leash_range = static_cast(GetSpecialAbilityParam(LEASH, 0)); leash_range = leash_range > 0.0f ? leash_range * leash_range : pAggroRange * pAggroRange; - if(DistanceSquaredNoZ(m_Position, npcSpawnPoint) > leash_range) { + if (DistanceSquaredNoZ(m_Position, npcSpawnPoint) > leash_range) { GMMove(npcSpawnPoint.x, npcSpawnPoint.y, npcSpawnPoint.z, npcSpawnPoint.w); SetHP(GetMaxHP()); BuffFadeAll(); @@ -1080,16 +1087,16 @@ void Mob::AI_Process() { { if (AI_movement_timer->Check()) { - if(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) + if (CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) { SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); SendPosition(); } SetCurrentSpeed(0); } - if(IsMoving()) + if (IsMoving()) { - if(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) + if (CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) { SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY())); SendPosition(); @@ -1098,13 +1105,13 @@ void Mob::AI_Process() { } //casting checked above... - if(target && !IsStunned() && !IsMezzed() && GetAppearance() != eaDead && !IsMeleeDisabled()) { + if (target && !IsStunned() && !IsMezzed() && GetAppearance() != eaDead && !IsMeleeDisabled()) { //we should check to see if they die mid-attacks, previous //crap of checking target for null was not gunna cut it //try main hand first - if(attack_timer.Check()) { + if (attack_timer.Check()) { DoMainHandAttackRounds(target); TriggerDefensiveProcs(target, EQEmu::inventory::slotPrimary, false); @@ -1150,17 +1157,17 @@ void Mob::AI_Process() { if (owner) { int16 flurry_chance = owner->aabonuses.PetFlurry + - owner->spellbonuses.PetFlurry + owner->itembonuses.PetFlurry; + owner->spellbonuses.PetFlurry + owner->itembonuses.PetFlurry; if (flurry_chance && zone->random.Roll(flurry_chance)) Flurry(nullptr); } } - if ((IsPet() || IsTempPet()) && IsPetOwnerClient()){ - if (spellbonuses.PC_Pet_Rampage[0] || itembonuses.PC_Pet_Rampage[0] || aabonuses.PC_Pet_Rampage[0]){ + if ((IsPet() || IsTempPet()) && IsPetOwnerClient()) { + if (spellbonuses.PC_Pet_Rampage[0] || itembonuses.PC_Pet_Rampage[0] || aabonuses.PC_Pet_Rampage[0]) { int chance = spellbonuses.PC_Pet_Rampage[0] + itembonuses.PC_Pet_Rampage[0] + aabonuses.PC_Pet_Rampage[0]; - if(zone->random.Roll(chance)) { + if (zone->random.Roll(chance)) { Rampage(nullptr); } } @@ -1170,30 +1177,30 @@ void Mob::AI_Process() { { int rampage_chance = GetSpecialAbilityParam(SPECATK_RAMPAGE, 0); rampage_chance = rampage_chance > 0 ? rampage_chance : 20; - if(zone->random.Roll(rampage_chance)) { + if (zone->random.Roll(rampage_chance)) { ExtraAttackOptions opts; int cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 3); - if(cur > 0) { + if (cur > 0) { opts.damage_flat = cur; } cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 4); - if(cur > 0) { + if (cur > 0) { opts.armor_pen_percent = cur / 100.0f; } cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 5); - if(cur > 0) { + if (cur > 0) { opts.armor_pen_flat = cur; } cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 6); - if(cur > 0) { + if (cur > 0) { opts.crit_percent = cur / 100.0f; } cur = GetSpecialAbilityParam(SPECATK_RAMPAGE, 7); - if(cur > 0) { + if (cur > 0) { opts.crit_flat = cur; } Rampage(&opts); @@ -1205,30 +1212,30 @@ void Mob::AI_Process() { { int rampage_chance = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 0); rampage_chance = rampage_chance > 0 ? rampage_chance : 20; - if(zone->random.Roll(rampage_chance)) { + if (zone->random.Roll(rampage_chance)) { ExtraAttackOptions opts; int cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 3); - if(cur > 0) { + if (cur > 0) { opts.damage_flat = cur; } cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 4); - if(cur > 0) { + if (cur > 0) { opts.armor_pen_percent = cur / 100.0f; } cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 5); - if(cur > 0) { + if (cur > 0) { opts.armor_pen_flat = cur; } cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 6); - if(cur > 0) { + if (cur > 0) { opts.crit_percent = cur / 100.0f; } cur = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 7); - if(cur > 0) { + if (cur > 0) { opts.crit_flat = cur; } @@ -1243,7 +1250,7 @@ void Mob::AI_Process() { DoOffHandAttackRounds(target); //now special attacks (kick, etc) - if(IsNPC()) + if (IsNPC()) CastToNPC()->DoClassAttacks(target); } @@ -1252,18 +1259,19 @@ void Mob::AI_Process() { else { //we cannot reach our target... //underwater stuff only works with water maps in the zone! - if(IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { - auto targetPosition = glm::vec3(target->GetX(), target->GetY(), target->GetZ()); - if(!zone->watermap->InLiquid(targetPosition)) { + if (IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) { + auto targetPosition = glm::vec3(target->GetX(), target->GetY(), target->GetZ()); + if (!zone->watermap->InLiquid(targetPosition)) { Mob *tar = hate_list.GetEntWithMostHateOnList(this); - if(tar == target) { + if (tar == target) { WipeHateList(); Heal(); BuffFadeAll(); AI_walking_timer->Start(100); pLastFightingDelayMoving = Timer::GetCurrentTime(); return; - } else if(tar != nullptr) { + } + else if (tar != nullptr) { SetTarget(tar); return; } @@ -1274,35 +1282,35 @@ void Mob::AI_Process() { if (!HateSummon()) { //could not summon them, check ranged... - if(GetSpecialAbility(SPECATK_RANGED_ATK)) + if (GetSpecialAbility(SPECATK_RANGED_ATK)) doranged = true; // Now pursue // TODO: Check here for another person on hate list with close hate value - if(AI_PursueCastCheck()){ + if (AI_PursueCastCheck()) { //we did something, so do not process movement. } else if (AI_movement_timer->Check()) { - if(!IsRooted()) { + if (!IsRooted()) { Log.Out(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", target->GetName()); - if(!RuleB(Pathing, Aggro) || !zone->pathing) + if (!RuleB(Pathing, Aggro) || !zone->pathing) CalculateNewPosition2(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed()); else { bool WaypointChanged, NodeReached; glm::vec3 Goal = UpdatePath(target->GetX(), target->GetY(), target->GetZ(), - GetRunspeed(), WaypointChanged, NodeReached); + GetRunspeed(), WaypointChanged, NodeReached); - if(WaypointChanged) + if (WaypointChanged) tar_ndx = 20; CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); } } - else if(IsMoving()) { + else if (IsMoving()) { SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY())); SetCurrentSpeed(0); @@ -1311,11 +1319,12 @@ void Mob::AI_Process() { } } } - else - { + else { + if (m_PlayerState & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); - if(AI_feign_remember_timer->Check()) { + + if(!zone->CanDoCombat() && AI_feign_remember_timer->Check()) { // 6/14/06 // Improved Feign Death Memory // check to see if any of our previous feigned targets have gotten up. @@ -1340,7 +1349,7 @@ void Mob::AI_Process() { { //we processed a spell action, so do nothing else. } - else if (AI_scan_area_timer->Check()) + else if (!zone->CanDoCombat() && AI_scan_area_timer->Check()) { /* * This is where NPCs look around to see if they want to attack anybody. From aa25946dc2d6aefb8978fa7990d8d104e1e8d97c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 26 Mar 2017 00:03:51 -0500 Subject: [PATCH 654/693] [Performance] Reduced CPU footprint in cases where a client is checking for aggro excessively every 750 millseconds. This has been adjusted to 6 seconds per new rule RULE_INT(Aggro, ClientAggroCheckInterval) - When zones have many players, with many NPC's, this adds up quickly --- changelog.txt | 3 +++ common/features.h | 2 +- common/ruletypes.h | 1 + zone/client.cpp | 4 ++-- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/changelog.txt b/changelog.txt index ea457ed67..b2c71a440 100644 --- a/changelog.txt +++ b/changelog.txt @@ -2,6 +2,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 03/25/2017 == Akkadius: Reduced CPU footprint in non-combat zones doing constant checks for combat related activities +Akkadius: Reduced CPU footprint in cases where a client is checking for aggro excessively every 750 millseconds. This has + been adjusted to 6 seconds per new rule RULE_INT(Aggro, ClientAggroCheckInterval) + - When zones have many players, with many NPC's, this adds up quickly == 03/12/2017 == Akkadius: diff --git a/common/features.h b/common/features.h index 4140014d8..863004666 100644 --- a/common/features.h +++ b/common/features.h @@ -157,7 +157,7 @@ enum { //timer settings, all in milliseconds AIscanarea_delay = 6000, AIfeignremember_delay = 500, AItarget_check_duration = 500, - AIClientScanarea_delay = 750, //used in REVERSE_AGGRO + // AIClientScanarea_delay = 750, //used in REVERSE_AGGRO AIassistcheck_delay = 3000, //now often a fighting NPC will yell for help AI_check_signal_timer_delay = 500, // How often EVENT_SIGNAL checks are processed ClientProximity_interval = 150, diff --git a/common/ruletypes.h b/common/ruletypes.h index 0bac4d6df..a6653da8e 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -536,6 +536,7 @@ RULE_INT(Aggro, MaxScalingProcAggro, 400) // Set to -1 for no limit. Maxmimum am RULE_INT(Aggro, IntAggroThreshold, 75) // Int <= this will aggro regardless of level difference. RULE_BOOL(Aggro, AllowTickPulling, false) // tick pulling is an exploit in an NPC's call for help fixed sometime in 2006 on live RULE_BOOL(Aggro, UseLevelAggro, true) // Level 18+ and Undead will aggro regardless of level difference. (this will disabled Rule:IntAggroThreshold if set to true) +RULE_INT(Aggro, ClientAggroCheckInterval, 6) // Interval in which clients actually check for aggro - in seconds RULE_CATEGORY_END() RULE_CATEGORY(TaskSystem) diff --git a/zone/client.cpp b/zone/client.cpp index fa683a267..2170d8ba9 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -133,9 +133,9 @@ Client::Client(EQStreamInterface* ieqs) fishing_timer(8000), endupkeep_timer(1000), forget_timer(0), - autosave_timer(RuleI(Character, AutosaveIntervalS)*1000), + autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000), #ifdef REVERSE_AGGRO - scanarea_timer(AIClientScanarea_delay), + scanarea_timer(RuleI(Aggro, ClientAggroCheckInterval) * 1000), #endif tribute_timer(Tribute_duration), proximity_timer(ClientProximity_interval), From 7309c11630443c8a5a2d6d38578b79b7e5df40e7 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 26 Mar 2017 13:41:14 -0400 Subject: [PATCH 655/693] Updated glm library to 0.9.8.4 (from 0.9.6.1) --- common/glm/copying.txt | 37 +- common/glm/glm/CMakeLists.txt | 43 +- common/glm/glm/common.hpp | 29 - common/glm/glm/detail/_features.hpp | 33 +- common/glm/glm/detail/_fixes.hpp | 29 - common/glm/glm/detail/_noise.hpp | 29 - common/glm/glm/detail/_swizzle.hpp | 1094 ++++++++--------- common/glm/glm/detail/_swizzle_func.hpp | 29 - common/glm/glm/detail/_vectorize.hpp | 29 - common/glm/glm/detail/dummy.cpp | 57 +- common/glm/glm/detail/func_common.hpp | 29 - common/glm/glm/detail/func_common.inl | 675 +++++----- common/glm/glm/detail/func_exponential.hpp | 29 - common/glm/glm/detail/func_exponential.inl | 57 +- common/glm/glm/detail/func_geometric.hpp | 39 +- common/glm/glm/detail/func_geometric.inl | 180 ++- common/glm/glm/detail/func_integer.hpp | 29 - common/glm/glm/detail/func_integer.inl | 105 +- common/glm/glm/detail/func_matrix.hpp | 43 +- common/glm/glm/detail/func_matrix.inl | 231 ++-- common/glm/glm/detail/func_noise.hpp | 93 -- common/glm/glm/detail/func_noise.inl | 388 ------ common/glm/glm/detail/func_packing.hpp | 45 +- common/glm/glm/detail/func_packing.inl | 206 ++-- common/glm/glm/detail/func_trigonometric.hpp | 33 +- common/glm/glm/detail/func_trigonometric.inl | 58 +- .../glm/glm/detail/func_vector_relational.hpp | 29 - .../glm/glm/detail/func_vector_relational.inl | 62 +- common/glm/glm/detail/glm.cpp | 29 - common/glm/glm/detail/intrinsic_common.hpp | 87 -- common/glm/glm/detail/intrinsic_common.inl | 313 ----- .../glm/glm/detail/intrinsic_exponential.hpp | 77 -- .../glm/glm/detail/intrinsic_exponential.inl | 27 - common/glm/glm/detail/intrinsic_geometric.hpp | 74 -- common/glm/glm/detail/intrinsic_geometric.inl | 147 --- common/glm/glm/detail/intrinsic_integer.hpp | 48 - common/glm/glm/detail/intrinsic_integer.inl | 139 --- common/glm/glm/detail/intrinsic_matrix.hpp | 67 - common/glm/glm/detail/intrinsic_matrix.inl | 1070 ---------------- .../glm/detail/intrinsic_trigonometric.hpp | 46 - .../glm/detail/intrinsic_trigonometric.inl | 27 - .../detail/intrinsic_vector_relational.hpp | 46 - .../detail/intrinsic_vector_relational.inl | 366 ------ common/glm/glm/detail/precision.hpp | 85 +- common/glm/glm/detail/setup.hpp | 1060 ++++++++-------- common/glm/glm/detail/type_float.hpp | 29 - common/glm/glm/detail/type_gentype.hpp | 29 - common/glm/glm/detail/type_gentype.inl | 29 - common/glm/glm/detail/type_half.hpp | 29 - common/glm/glm/detail/type_half.inl | 41 +- common/glm/glm/detail/type_int.hpp | 80 +- common/glm/glm/detail/type_mat.hpp | 32 +- common/glm/glm/detail/type_mat.inl | 29 - common/glm/glm/detail/type_mat2x2.hpp | 173 +-- common/glm/glm/detail/type_mat2x2.inl | 267 ++-- common/glm/glm/detail/type_mat2x3.hpp | 212 ++-- common/glm/glm/detail/type_mat2x3.inl | 217 ++-- common/glm/glm/detail/type_mat2x4.hpp | 221 ++-- common/glm/glm/detail/type_mat2x4.inl | 211 ++-- common/glm/glm/detail/type_mat3x2.hpp | 224 ++-- common/glm/glm/detail/type_mat3x2.inl | 241 ++-- common/glm/glm/detail/type_mat3x3.hpp | 240 ++-- common/glm/glm/detail/type_mat3x3.inl | 291 ++--- common/glm/glm/detail/type_mat3x4.hpp | 163 +-- common/glm/glm/detail/type_mat3x4.inl | 250 ++-- common/glm/glm/detail/type_mat4x2.hpp | 182 ++- common/glm/glm/detail/type_mat4x2.inl | 281 ++--- common/glm/glm/detail/type_mat4x3.hpp | 117 +- common/glm/glm/detail/type_mat4x3.inl | 248 ++-- common/glm/glm/detail/type_mat4x4.hpp | 125 +- common/glm/glm/detail/type_mat4x4.inl | 316 ++--- common/glm/glm/detail/type_vec.hpp | 180 ++- common/glm/glm/detail/type_vec.inl | 29 - common/glm/glm/detail/type_vec1.hpp | 359 +++--- common/glm/glm/detail/type_vec1.inl | 350 +++--- common/glm/glm/detail/type_vec2.hpp | 298 +++-- common/glm/glm/detail/type_vec2.inl | 418 +++---- common/glm/glm/detail/type_vec3.hpp | 331 +++-- common/glm/glm/detail/type_vec3.inl | 648 +++++----- common/glm/glm/detail/type_vec4.hpp | 365 +++--- common/glm/glm/detail/type_vec4.inl | 1044 +++++++--------- common/glm/glm/detail/type_vec4_avx.inl | 41 - common/glm/glm/detail/type_vec4_avx2.inl | 41 - common/glm/glm/detail/type_vec4_sse2.inl | 120 -- common/glm/glm/exponential.hpp | 29 - common/glm/glm/ext.hpp | 49 +- common/glm/glm/fwd.hpp | 69 +- common/glm/glm/geometric.hpp | 29 - common/glm/glm/glm.hpp | 67 +- common/glm/glm/gtc/bitfield.hpp | 31 +- common/glm/glm/gtc/bitfield.inl | 151 +-- common/glm/glm/gtc/constants.hpp | 89 +- common/glm/glm/gtc/constants.inl | 87 +- common/glm/glm/gtc/epsilon.hpp | 31 +- common/glm/glm/gtc/epsilon.inl | 29 - common/glm/glm/gtc/integer.hpp | 61 +- common/glm/glm/gtc/integer.inl | 81 +- common/glm/glm/gtc/matrix_access.hpp | 35 +- common/glm/glm/gtc/matrix_access.inl | 41 +- common/glm/glm/gtc/matrix_integer.hpp | 33 +- common/glm/glm/gtc/matrix_inverse.hpp | 35 +- common/glm/glm/gtc/matrix_inverse.inl | 54 +- common/glm/glm/gtc/matrix_transform.hpp | 281 ++++- common/glm/glm/gtc/matrix_transform.inl | 477 ++++--- common/glm/glm/gtc/noise.hpp | 33 +- common/glm/glm/gtc/noise.inl | 31 +- common/glm/glm/gtc/packing.hpp | 167 ++- common/glm/glm/gtc/packing.inl | 533 ++++++-- common/glm/glm/gtc/quaternion.hpp | 214 ++-- common/glm/glm/gtc/quaternion.inl | 324 ++--- common/glm/glm/gtc/random.hpp | 44 +- common/glm/glm/gtc/random.inl | 51 +- common/glm/glm/gtc/reciprocal.hpp | 139 +-- common/glm/glm/gtc/reciprocal.inl | 29 - common/glm/glm/gtc/round.hpp | 35 +- common/glm/glm/gtc/round.inl | 50 +- common/glm/glm/gtc/type_precision.hpp | 39 +- common/glm/glm/gtc/type_precision.inl | 29 - common/glm/glm/gtc/type_ptr.hpp | 39 +- common/glm/glm/gtc/type_ptr.inl | 29 - common/glm/glm/gtc/ulp.hpp | 33 +- common/glm/glm/gtc/ulp.inl | 41 +- common/glm/glm/gtc/vec1.hpp | 31 +- common/glm/glm/gtc/vec1.inl | 29 - common/glm/glm/gtx/associated_min_max.hpp | 31 +- common/glm/glm/gtx/associated_min_max.inl | 61 +- common/glm/glm/gtx/bit.hpp | 35 +- common/glm/glm/gtx/bit.inl | 44 +- common/glm/glm/gtx/closest_point.hpp | 33 +- common/glm/glm/gtx/closest_point.inl | 29 - common/glm/glm/gtx/color_space.hpp | 35 +- common/glm/glm/gtx/color_space.inl | 51 +- common/glm/glm/gtx/color_space_YCoCg.hpp | 33 +- common/glm/glm/gtx/color_space_YCoCg.inl | 119 +- common/glm/glm/gtx/common.hpp | 43 +- common/glm/glm/gtx/common.inl | 70 +- common/glm/glm/gtx/compatibility.hpp | 40 +- common/glm/glm/gtx/compatibility.inl | 42 +- common/glm/glm/gtx/component_wise.hpp | 57 +- common/glm/glm/gtx/component_wise.inl | 150 ++- common/glm/glm/gtx/dual_quaternion.hpp | 232 ++-- common/glm/glm/gtx/dual_quaternion.inl | 190 ++- common/glm/glm/gtx/euler_angles.hpp | 53 +- common/glm/glm/gtx/euler_angles.inl | 85 +- common/glm/glm/gtx/extend.hpp | 35 +- common/glm/glm/gtx/extend.inl | 29 - common/glm/glm/gtx/extented_min_max.hpp | 162 --- common/glm/glm/gtx/extented_min_max.inl | 169 --- common/glm/glm/gtx/fast_exponential.hpp | 35 +- common/glm/glm/gtx/fast_exponential.inl | 31 +- common/glm/glm/gtx/fast_square_root.hpp | 35 +- common/glm/glm/gtx/fast_square_root.inl | 35 +- common/glm/glm/gtx/fast_trigonometry.hpp | 35 +- common/glm/glm/gtx/fast_trigonometry.inl | 45 +- common/glm/glm/gtx/gradient_paint.hpp | 33 +- common/glm/glm/gtx/gradient_paint.inl | 29 - .../glm/glm/gtx/handed_coordinate_space.hpp | 35 +- .../glm/glm/gtx/handed_coordinate_space.inl | 29 - common/glm/glm/gtx/integer.hpp | 35 +- common/glm/glm/gtx/integer.inl | 29 - common/glm/glm/gtx/intersect.hpp | 41 +- common/glm/glm/gtx/intersect.inl | 55 +- common/glm/glm/gtx/io.hpp | 71 +- common/glm/glm/gtx/io.inl | 623 ++++------ common/glm/glm/gtx/log_base.hpp | 47 +- common/glm/glm/gtx/log_base.inl | 29 - common/glm/glm/gtx/matrix_cross_product.hpp | 35 +- common/glm/glm/gtx/matrix_cross_product.inl | 29 - common/glm/glm/gtx/matrix_decompose.hpp | 40 +- common/glm/glm/gtx/matrix_decompose.inl | 100 +- common/glm/glm/gtx/matrix_interpolation.hpp | 34 +- common/glm/glm/gtx/matrix_interpolation.inl | 29 - common/glm/glm/gtx/matrix_major_storage.hpp | 35 +- common/glm/glm/gtx/matrix_major_storage.inl | 29 - common/glm/glm/gtx/matrix_operation.hpp | 35 +- common/glm/glm/gtx/matrix_operation.inl | 29 - common/glm/glm/gtx/matrix_query.hpp | 35 +- common/glm/glm/gtx/matrix_query.inl | 67 +- common/glm/glm/gtx/matrix_transform_2d.hpp | 34 +- common/glm/glm/gtx/matrix_transform_2d.inl | 28 - common/glm/glm/gtx/mixed_product.hpp | 35 +- common/glm/glm/gtx/mixed_product.inl | 29 - common/glm/glm/gtx/multiple.hpp | 106 -- common/glm/glm/gtx/multiple.inl | 64 - common/glm/glm/gtx/norm.hpp | 66 +- common/glm/glm/gtx/norm.inl | 116 +- common/glm/glm/gtx/normal.hpp | 35 +- common/glm/glm/gtx/normal.inl | 29 - common/glm/glm/gtx/normalize_dot.hpp | 35 +- common/glm/glm/gtx/normalize_dot.inl | 29 - common/glm/glm/gtx/number_precision.hpp | 35 +- common/glm/glm/gtx/number_precision.inl | 29 - common/glm/glm/gtx/optimum_pow.hpp | 35 +- common/glm/glm/gtx/optimum_pow.inl | 29 - common/glm/glm/gtx/orthonormalize.hpp | 35 +- common/glm/glm/gtx/orthonormalize.inl | 29 - common/glm/glm/gtx/perpendicular.hpp | 35 +- common/glm/glm/gtx/perpendicular.inl | 29 - common/glm/glm/gtx/polar_coordinates.hpp | 35 +- common/glm/glm/gtx/polar_coordinates.inl | 31 +- common/glm/glm/gtx/projection.hpp | 35 +- common/glm/glm/gtx/projection.inl | 29 - common/glm/glm/gtx/quaternion.hpp | 37 +- common/glm/glm/gtx/quaternion.inl | 145 +-- common/glm/glm/gtx/range.hpp | 101 +- common/glm/glm/gtx/raw_data.hpp | 35 +- common/glm/glm/gtx/raw_data.inl | 29 - common/glm/glm/gtx/rotate_normalized_axis.hpp | 37 +- common/glm/glm/gtx/rotate_normalized_axis.inl | 29 - common/glm/glm/gtx/rotate_vector.hpp | 35 +- common/glm/glm/gtx/rotate_vector.inl | 29 - common/glm/glm/gtx/scalar_multiplication.hpp | 33 +- common/glm/glm/gtx/scalar_relational.hpp | 35 +- common/glm/glm/gtx/scalar_relational.inl | 29 - common/glm/glm/gtx/simd_mat4.hpp | 49 +- common/glm/glm/gtx/simd_mat4.inl | 77 +- common/glm/glm/gtx/simd_quat.hpp | 148 +-- common/glm/glm/gtx/simd_quat.inl | 77 +- common/glm/glm/gtx/simd_vec4.hpp | 132 +- common/glm/glm/gtx/simd_vec4.inl | 58 +- common/glm/glm/gtx/spline.hpp | 35 +- common/glm/glm/gtx/spline.inl | 29 - common/glm/glm/gtx/std_based_type.hpp | 33 +- common/glm/glm/gtx/std_based_type.inl | 29 - common/glm/glm/gtx/string_cast.hpp | 37 +- common/glm/glm/gtx/string_cast.inl | 87 +- common/glm/glm/gtx/transform.hpp | 35 +- common/glm/glm/gtx/transform.inl | 48 +- common/glm/glm/gtx/transform2.hpp | 33 +- common/glm/glm/gtx/transform2.inl | 139 +-- common/glm/glm/gtx/type_aligned.hpp | 41 +- common/glm/glm/gtx/type_aligned.inl | 29 - common/glm/glm/gtx/vector_angle.hpp | 41 +- common/glm/glm/gtx/vector_angle.inl | 29 - common/glm/glm/gtx/vector_query.hpp | 33 +- common/glm/glm/gtx/vector_query.inl | 29 - common/glm/glm/gtx/wrap.hpp | 53 +- common/glm/glm/gtx/wrap.inl | 183 +-- common/glm/glm/integer.hpp | 29 - common/glm/glm/mat2x2.hpp | 29 - common/glm/glm/mat2x3.hpp | 29 - common/glm/glm/mat2x4.hpp | 29 - common/glm/glm/mat3x2.hpp | 29 - common/glm/glm/mat3x3.hpp | 29 - common/glm/glm/mat3x4.hpp | 29 - common/glm/glm/mat4x2.hpp | 29 - common/glm/glm/mat4x3.hpp | 31 +- common/glm/glm/mat4x4.hpp | 29 - common/glm/glm/matrix.hpp | 29 - common/glm/glm/packing.hpp | 29 - common/glm/glm/trigonometric.hpp | 29 - common/glm/glm/vec2.hpp | 29 - common/glm/glm/vec3.hpp | 29 - common/glm/glm/vec4.hpp | 29 - common/glm/glm/vector_relational.hpp | 29 - common/glm/readme.txt | 701 ----------- 256 files changed, 8824 insertions(+), 18647 deletions(-) delete mode 100644 common/glm/glm/detail/func_noise.hpp delete mode 100644 common/glm/glm/detail/func_noise.inl delete mode 100644 common/glm/glm/detail/intrinsic_common.hpp delete mode 100644 common/glm/glm/detail/intrinsic_common.inl delete mode 100644 common/glm/glm/detail/intrinsic_exponential.hpp delete mode 100644 common/glm/glm/detail/intrinsic_exponential.inl delete mode 100644 common/glm/glm/detail/intrinsic_geometric.hpp delete mode 100644 common/glm/glm/detail/intrinsic_geometric.inl delete mode 100644 common/glm/glm/detail/intrinsic_integer.hpp delete mode 100644 common/glm/glm/detail/intrinsic_integer.inl delete mode 100644 common/glm/glm/detail/intrinsic_matrix.hpp delete mode 100644 common/glm/glm/detail/intrinsic_matrix.inl delete mode 100644 common/glm/glm/detail/intrinsic_trigonometric.hpp delete mode 100644 common/glm/glm/detail/intrinsic_trigonometric.inl delete mode 100644 common/glm/glm/detail/intrinsic_vector_relational.hpp delete mode 100644 common/glm/glm/detail/intrinsic_vector_relational.inl delete mode 100644 common/glm/glm/detail/type_vec4_avx.inl delete mode 100644 common/glm/glm/detail/type_vec4_avx2.inl delete mode 100644 common/glm/glm/detail/type_vec4_sse2.inl delete mode 100644 common/glm/glm/gtx/extented_min_max.hpp delete mode 100644 common/glm/glm/gtx/extented_min_max.inl delete mode 100644 common/glm/glm/gtx/multiple.hpp delete mode 100644 common/glm/glm/gtx/multiple.inl delete mode 100644 common/glm/readme.txt diff --git a/common/glm/copying.txt b/common/glm/copying.txt index efd93bab9..7c20b4a67 100644 --- a/common/glm/copying.txt +++ b/common/glm/copying.txt @@ -1,6 +1,39 @@ -The MIT License +================================================================================ +OpenGL Mathematics (GLM) +-------------------------------------------------------------------------------- +GLM can be distributed and/or modified under the terms of either +a) The Happy Bunny License, or b) the MIT License. -Copyright (c) 2005 - 2013 G-Truc Creation +================================================================================ +The Happy Bunny License (Modified MIT License) +-------------------------------------------------------------------------------- +Copyright (c) 2005 - 2016 G-Truc Creation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +Restrictions: By making use of the Software for military purposes, you choose +to make a Bunny unhappy. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +================================================================================ +The MIT License +-------------------------------------------------------------------------------- +Copyright (c) 2005 - 2016 G-Truc Creation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/common/glm/glm/CMakeLists.txt b/common/glm/glm/CMakeLists.txt index 9dbe11cab..d60a88771 100644 --- a/common/glm/glm/CMakeLists.txt +++ b/common/glm/glm/CMakeLists.txt @@ -1,9 +1,9 @@ -set(NAME glm_dummy) - file(GLOB ROOT_SOURCE *.cpp) file(GLOB ROOT_INLINE *.inl) file(GLOB ROOT_HEADER *.hpp) file(GLOB ROOT_TEXT ../*.txt) +file(GLOB ROOT_MD ../*.md) +file(GLOB ROOT_NAT ../util/glm.natvis) file(GLOB_RECURSE CORE_SOURCE ./detail/*.cpp) file(GLOB_RECURSE CORE_INLINE ./detail/*.inl) @@ -17,7 +17,11 @@ file(GLOB_RECURSE GTX_SOURCE ./gtx/*.cpp) file(GLOB_RECURSE GTX_INLINE ./gtx/*.inl) file(GLOB_RECURSE GTX_HEADER ./gtx/*.hpp) -source_group("Text Files" FILES ${ROOT_TEXT}) +file(GLOB_RECURSE SIMD_SOURCE ./simd/*.cpp) +file(GLOB_RECURSE SIMD_INLINE ./simd/*.inl) +file(GLOB_RECURSE SIMD_HEADER ./simd/*.h) + +source_group("Text Files" FILES ${ROOT_TEXT} ${ROOT_MD}) source_group("Core Files" FILES ${CORE_SOURCE}) source_group("Core Files" FILES ${CORE_INLINE}) source_group("Core Files" FILES ${CORE_HEADER}) @@ -27,16 +31,37 @@ source_group("GTC Files" FILES ${GTC_HEADER}) source_group("GTX Files" FILES ${GTX_SOURCE}) source_group("GTX Files" FILES ${GTX_INLINE}) source_group("GTX Files" FILES ${GTX_HEADER}) +source_group("SIMD Files" FILES ${SIMD_SOURCE}) +source_group("SIMD Files" FILES ${SIMD_INLINE}) +source_group("SIMD Files" FILES ${SIMD_HEADER}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) -if(GLM_TEST_ENABLE) - add_executable(${NAME} ${ROOT_TEXT} +if(GLM_STATIC_LIBRARY_ENABLE OR GLM_DYNAMIC_LIBRARY_ENABLE) + if(GLM_STATIC_LIBRARY_ENABLE) + add_library(glm_static STATIC ${ROOT_TEXT} ${ROOT_MD} ${ROOT_NAT} + ${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER} + ${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER} + ${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER} + ${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER} + ${SIMD_SOURCE} ${SIMD_INLINE} ${SIMD_HEADER}) + endif(GLM_STATIC_LIBRARY_ENABLE) + + if(GLM_DYNAMIC_LIBRARY_ENABLE) + add_library(glm_shared SHARED ${ROOT_TEXT} ${ROOT_MD} ${ROOT_NAT} + ${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER} + ${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER} + ${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER} + ${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER} + ${SIMD_SOURCE} ${SIMD_INLINE} ${SIMD_HEADER}) + endif(GLM_DYNAMIC_LIBRARY_ENABLE) + +else(GLM_STATIC_LIBRARY_ENABLE OR GLM_DYNAMIC_LIBRARY_ENABLE) + add_executable(glm_dummy ${ROOT_TEXT} ${ROOT_MD} ${ROOT_NAT} ${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER} ${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER} ${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER} - ${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER}) -endif(GLM_TEST_ENABLE) + ${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER} + ${SIMD_SOURCE} ${SIMD_INLINE} ${SIMD_HEADER}) -#add_library(glm STATIC glm.cpp) -#add_library(glm_shared SHARED glm.cpp) +endif(GLM_STATIC_LIBRARY_ENABLE OR GLM_DYNAMIC_LIBRARY_ENABLE) diff --git a/common/glm/glm/common.hpp b/common/glm/glm/common.hpp index 8f1c3171e..f57e800ee 100644 --- a/common/glm/glm/common.hpp +++ b/common/glm/glm/common.hpp @@ -1,34 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// Restrictions: -/// By making use of the Software for military purposes, you choose to make -/// a Bunny unhappy. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// /// @ref core /// @file glm/common.hpp -/// @date 2013-12-24 / 2013-12-24 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// #pragma once diff --git a/common/glm/glm/detail/_features.hpp b/common/glm/glm/detail/_features.hpp index 51eda577c..97dd63303 100644 --- a/common/glm/glm/detail/_features.hpp +++ b/common/glm/glm/detail/_features.hpp @@ -1,34 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// Restrictions: -/// By making use of the Software for military purposes, you choose to make -/// a Bunny unhappy. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// /// @ref core /// @file glm/detail/_features.hpp -/// @date 2013-02-20 / 2013-02-20 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// #pragma once @@ -284,7 +255,7 @@ # define GLM_CXX11_STATIC_ASSERT # endif -#elif(GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) +#elif(GLM_COMPILER & GLM_COMPILER_CLANG) # if(__has_feature(cxx_exceptions)) # define GLM_CXX98_EXCEPTIONS # endif @@ -425,4 +396,4 @@ # define GLM_CXX11_VARIADIC_TEMPLATES # endif -#endif//(GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) +#endif//(GLM_COMPILER & GLM_COMPILER_CLANG) diff --git a/common/glm/glm/detail/_fixes.hpp b/common/glm/glm/detail/_fixes.hpp index 6185dcbb7..c957562b4 100644 --- a/common/glm/glm/detail/_fixes.hpp +++ b/common/glm/glm/detail/_fixes.hpp @@ -1,34 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// Restrictions: -/// By making use of the Software for military purposes, you choose to make -/// a Bunny unhappy. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// /// @ref core /// @file glm/detail/_fixes.hpp -/// @date 2011-02-21 / 2011-11-22 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// #include diff --git a/common/glm/glm/detail/_noise.hpp b/common/glm/glm/detail/_noise.hpp index 94c835d54..89403f4a7 100644 --- a/common/glm/glm/detail/_noise.hpp +++ b/common/glm/glm/detail/_noise.hpp @@ -1,34 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// Restrictions: -/// By making use of the Software for military purposes, you choose to make -/// a Bunny unhappy. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// /// @ref core /// @file glm/detail/_noise.hpp -/// @date 2013-12-24 / 2013-12-24 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// #pragma once diff --git a/common/glm/glm/detail/_swizzle.hpp b/common/glm/glm/detail/_swizzle.hpp index 3edf6cb23..8e134d90e 100644 --- a/common/glm/glm/detail/_swizzle.hpp +++ b/common/glm/glm/detail/_swizzle.hpp @@ -1,34 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// Restrictions: -/// By making use of the Software for military purposes, you choose to make -/// a Bunny unhappy. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// /// @ref core /// @file glm/detail/_swizzle.hpp -/// @date 2006-04-20 / 2011-02-16 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// #pragma once @@ -39,11 +10,9 @@ namespace detail template struct _swizzle_base0 { - typedef T value_type; - protected: - GLM_FUNC_QUALIFIER value_type& elem (size_t i) { return (reinterpret_cast(_buffer))[i]; } - GLM_FUNC_QUALIFIER const value_type& elem (size_t i) const { return (reinterpret_cast(_buffer))[i]; } + GLM_FUNC_QUALIFIER T& elem(size_t i){ return (reinterpret_cast(_buffer))[i]; } + GLM_FUNC_QUALIFIER T const& elem(size_t i) const{ return (reinterpret_cast(_buffer))[i]; } // Use an opaque buffer to *ensure* the compiler doesn't call a constructor. // The size 1 buffer is assumed to aligned to the actual members so that the @@ -51,27 +20,27 @@ namespace detail char _buffer[1]; }; - template + template class vecType, int E0, int E1, int E2, int E3, bool Aligned> struct _swizzle_base1 : public _swizzle_base0 { }; - template - struct _swizzle_base1 : public _swizzle_base0 + template class vecType, int E0, int E1, bool Aligned> + struct _swizzle_base1<2, T, P, vecType, E0,E1,-1,-2, Aligned> : public _swizzle_base0 { - GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1)); } + GLM_FUNC_QUALIFIER vecType operator ()() const { return vecType(this->elem(E0), this->elem(E1)); } }; - template - struct _swizzle_base1 : public _swizzle_base0 + template class vecType, int E0, int E1, int E2, bool Aligned> + struct _swizzle_base1<3, T, P, vecType, E0,E1,E2,-1, Aligned> : public _swizzle_base0 { - GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1), this->elem(E2)); } + GLM_FUNC_QUALIFIER vecType operator ()() const { return vecType(this->elem(E0), this->elem(E1), this->elem(E2)); } }; - template - struct _swizzle_base1 : public _swizzle_base0 + template class vecType, int E0, int E1, int E2, int E3, bool Aligned> + struct _swizzle_base1<4, T, P, vecType, E0,E1,E2,E3, Aligned> : public _swizzle_base0 { - GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1), this->elem(E2), this->elem(E3)); } + GLM_FUNC_QUALIFIER vecType operator ()() const { return vecType(this->elem(E0), this->elem(E1), this->elem(E2), this->elem(E3)); } }; // Internal class for implementing swizzle operators @@ -86,79 +55,76 @@ namespace detail DUPLICATE_ELEMENTS = 1 if there is a repeated element, 0 otherwise (used to specialize swizzles containing duplicate elements so that they cannot be used as r-values). */ - template - struct _swizzle_base2 : public _swizzle_base1 + template class vecType, int E0, int E1, int E2, int E3, int DUPLICATE_ELEMENTS> + struct _swizzle_base2 : public _swizzle_base1::value> { - typedef VecType vec_type; - typedef ValueType value_type; - - GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const ValueType& t) + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const T& t) { for (int i = 0; i < N; ++i) (*this)[i] = t; return *this; } - GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const VecType& that) + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (vecType const& that) { struct op { - GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e = t; } + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) { e = t; } }; _apply_op(that, op()); return *this; } - GLM_FUNC_QUALIFIER void operator -= (const VecType& that) + GLM_FUNC_QUALIFIER void operator -= (vecType const& that) { struct op { - GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e -= t; } + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) { e -= t; } }; _apply_op(that, op()); } - GLM_FUNC_QUALIFIER void operator += (const VecType& that) + GLM_FUNC_QUALIFIER void operator += (vecType const& that) { struct op { - GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e += t; } + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) { e += t; } }; _apply_op(that, op()); } - GLM_FUNC_QUALIFIER void operator *= (const VecType& that) + GLM_FUNC_QUALIFIER void operator *= (vecType const& that) { struct op { - GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e *= t; } + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) { e *= t; } }; _apply_op(that, op()); } - GLM_FUNC_QUALIFIER void operator /= (const VecType& that) + GLM_FUNC_QUALIFIER void operator /= (vecType const& that) { struct op { - GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e /= t; } + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) { e /= t; } }; _apply_op(that, op()); } - GLM_FUNC_QUALIFIER value_type& operator[] (size_t i) + GLM_FUNC_QUALIFIER T& operator[](size_t i) { const int offset_dst[4] = { E0, E1, E2, E3 }; return this->elem(offset_dst[i]); } - GLM_FUNC_QUALIFIER value_type operator[] (size_t i) const + GLM_FUNC_QUALIFIER T operator[](size_t i) const { const int offset_dst[4] = { E0, E1, E2, E3 }; return this->elem(offset_dst[i]); } protected: - template - GLM_FUNC_QUALIFIER void _apply_op(const VecType& that, T op) + template + GLM_FUNC_QUALIFIER void _apply_op(vecType const& that, U op) { // Make a copy of the data in this == &that. // The copier should optimize out the copy in cases where the function is // properly inlined and the copy is not necessary. - ValueType t[N]; + T t[N]; for (int i = 0; i < N; ++i) t[i] = that[i]; for (int i = 0; i < N; ++i) @@ -167,56 +133,54 @@ namespace detail }; // Specialization for swizzles containing duplicate elements. These cannot be modified. - template - struct _swizzle_base2 : public _swizzle_base1 + template class vecType, int E0, int E1, int E2, int E3> + struct _swizzle_base2 : public _swizzle_base1::value> { - typedef VecType vec_type; - typedef ValueType value_type; - struct Stub {}; + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (Stub const &) { return *this; } - GLM_FUNC_QUALIFIER value_type operator[] (size_t i) const + GLM_FUNC_QUALIFIER T operator[] (size_t i) const { const int offset_dst[4] = { E0, E1, E2, E3 }; return this->elem(offset_dst[i]); } }; - template - struct _swizzle : public _swizzle_base2 + template class vecType, int E0, int E1, int E2, int E3> + struct _swizzle : public _swizzle_base2 { - typedef _swizzle_base2 base_type; + typedef _swizzle_base2 base_type; using base_type::operator=; - GLM_FUNC_QUALIFIER operator VecType () const { return (*this)(); } + GLM_FUNC_QUALIFIER operator vecType () const { return (*this)(); } }; // // To prevent the C++ syntax from getting entirely overwhelming, define some alias macros // -#define _GLM_SWIZZLE_TEMPLATE1 template -#define _GLM_SWIZZLE_TEMPLATE2 template -#define _GLM_SWIZZLE_TYPE1 _swizzle -#define _GLM_SWIZZLE_TYPE2 _swizzle +#define _GLM_SWIZZLE_TEMPLATE1 template class vecType, int E0, int E1, int E2, int E3> +#define _GLM_SWIZZLE_TEMPLATE2 template class vecType, int E0, int E1, int E2, int E3, int F0, int F1, int F2, int F3> +#define _GLM_SWIZZLE_TYPE1 _swizzle +#define _GLM_SWIZZLE_TYPE2 _swizzle // // Wrapper for a binary operator (e.g. u.yy + v.zy) // #define _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ _GLM_SWIZZLE_TEMPLATE2 \ - GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b) \ + GLM_FUNC_QUALIFIER vecType operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b) \ { \ return a() OPERAND b(); \ } \ _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const V& b) \ + GLM_FUNC_QUALIFIER vecType operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const vecType& b) \ { \ return a() OPERAND b; \ } \ _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER V operator OPERAND ( const V& a, const _GLM_SWIZZLE_TYPE1& b) \ + GLM_FUNC_QUALIFIER vecType operator OPERAND ( const vecType& a, const _GLM_SWIZZLE_TYPE1& b) \ { \ return a OPERAND b(); \ } @@ -226,12 +190,12 @@ namespace detail // #define _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const T& b) \ + GLM_FUNC_QUALIFIER vecType operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const T& b) \ { \ return a() OPERAND b; \ } \ _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER V operator OPERAND ( const T& a, const _GLM_SWIZZLE_TYPE1& b) \ + GLM_FUNC_QUALIFIER vecType operator OPERAND ( const T& a, const _GLM_SWIZZLE_TYPE1& b) \ { \ return a OPERAND b(); \ } @@ -334,500 +298,500 @@ namespace glm } #define _GLM_SWIZZLE2_2_MEMBERS(T, P, V, E0,E1) \ - struct { detail::_swizzle<2, T, P, V, 0,0,-1,-2> E0 ## E0; }; \ - struct { detail::_swizzle<2, T, P, V, 0,1,-1,-2> E0 ## E1; }; \ - struct { detail::_swizzle<2, T, P, V, 1,0,-1,-2> E1 ## E0; }; \ - struct { detail::_swizzle<2, T, P, V, 1,1,-1,-2> E1 ## E1; }; + struct { detail::_swizzle<2, T, P, V, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2, T, P, V, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2, T, P, V, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2, T, P, V, 1,1,-1,-2> E1 ## E1; }; #define _GLM_SWIZZLE2_3_MEMBERS(T, P, V, E0,E1) \ - struct { detail::_swizzle<3,T, P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<3,T, P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<3,T, P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<3,T, P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<3,T, P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<3,T, P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<3,T, P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<3,T, P, V, 1,1,1,-1> E1 ## E1 ## E1; }; + struct { detail::_swizzle<3,T, P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 1,1,1,-1> E1 ## E1 ## E1; }; #define _GLM_SWIZZLE2_4_MEMBERS(T, P, V, E0,E1) \ - struct { detail::_swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; + struct { detail::_swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; #define _GLM_SWIZZLE3_2_MEMBERS(T, P, V, E0,E1,E2) \ - struct { detail::_swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \ - struct { detail::_swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \ - struct { detail::_swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \ - struct { detail::_swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \ - struct { detail::_swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \ - struct { detail::_swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \ - struct { detail::_swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \ - struct { detail::_swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \ - struct { detail::_swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; }; + struct { detail::_swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; }; #define _GLM_SWIZZLE3_3_MEMBERS(T, P, V ,E0,E1,E2) \ - struct { detail::_swizzle<3,T,P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 2,2,2,-1> E2 ## E2 ## E2; }; + struct { detail::_swizzle<3, T, P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 2,2,2,-1> E2 ## E2 ## E2; }; #define _GLM_SWIZZLE3_4_MEMBERS(T, P, V, E0,E1,E2) \ - struct { detail::_swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ - struct { detail::_swizzle<4,T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ - struct { detail::_swizzle<4,T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ - struct { detail::_swizzle<4,T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; + struct { detail::_swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; #define _GLM_SWIZZLE4_2_MEMBERS(T, P, V, E0,E1,E2,E3) \ - struct { detail::_swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \ - struct { detail::_swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \ - struct { detail::_swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \ - struct { detail::_swizzle<2,T, P, V, 0,3,-1,-2> E0 ## E3; }; \ - struct { detail::_swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \ - struct { detail::_swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \ - struct { detail::_swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \ - struct { detail::_swizzle<2,T, P, V, 1,3,-1,-2> E1 ## E3; }; \ - struct { detail::_swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \ - struct { detail::_swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \ - struct { detail::_swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; }; \ - struct { detail::_swizzle<2,T, P, V, 2,3,-1,-2> E2 ## E3; }; \ - struct { detail::_swizzle<2,T, P, V, 3,0,-1,-2> E3 ## E0; }; \ - struct { detail::_swizzle<2,T, P, V, 3,1,-1,-2> E3 ## E1; }; \ - struct { detail::_swizzle<2,T, P, V, 3,2,-1,-2> E3 ## E2; }; \ - struct { detail::_swizzle<2,T, P, V, 3,3,-1,-2> E3 ## E3; }; + struct { detail::_swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 0,3,-1,-2> E0 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 1,3,-1,-2> E1 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 2,3,-1,-2> E2 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V, 3,0,-1,-2> E3 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 3,1,-1,-2> E3 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 3,2,-1,-2> E3 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 3,3,-1,-2> E3 ## E3; }; -#define _GLM_SWIZZLE4_3_MEMBERS(T,P, V, E0,E1,E2,E3) \ - struct { detail::_swizzle<3,T,P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 0,0,3,-1> E0 ## E0 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 0,1,3,-1> E0 ## E1 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 0,2,3,-1> E0 ## E2 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 0,3,0,-1> E0 ## E3 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 0,3,1,-1> E0 ## E3 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 0,3,2,-1> E0 ## E3 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 0,3,3,-1> E0 ## E3 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 1,0,3,-1> E1 ## E0 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 1,1,3,-1> E1 ## E1 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 1,2,3,-1> E1 ## E2 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 1,3,0,-1> E1 ## E3 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 1,3,1,-1> E1 ## E3 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 1,3,2,-1> E1 ## E3 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 1,3,3,-1> E1 ## E3 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 2,0,3,-1> E2 ## E0 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 2,1,3,-1> E2 ## E1 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 2,2,2,-1> E2 ## E2 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 2,2,3,-1> E2 ## E2 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 2,3,0,-1> E2 ## E3 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 2,3,1,-1> E2 ## E3 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 2,3,2,-1> E2 ## E3 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 2,3,3,-1> E2 ## E3 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 3,0,0,-1> E3 ## E0 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 3,0,1,-1> E3 ## E0 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 3,0,2,-1> E3 ## E0 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 3,0,3,-1> E3 ## E0 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 3,1,0,-1> E3 ## E1 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 3,1,1,-1> E3 ## E1 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 3,1,2,-1> E3 ## E1 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 3,1,3,-1> E3 ## E1 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 3,2,0,-1> E3 ## E2 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 3,2,1,-1> E3 ## E2 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 3,2,2,-1> E3 ## E2 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 3,2,3,-1> E3 ## E2 ## E3; }; \ - struct { detail::_swizzle<3,T,P, V, 3,3,0,-1> E3 ## E3 ## E0; }; \ - struct { detail::_swizzle<3,T,P, V, 3,3,1,-1> E3 ## E3 ## E1; }; \ - struct { detail::_swizzle<3,T,P, V, 3,3,2,-1> E3 ## E3 ## E2; }; \ - struct { detail::_swizzle<3,T,P, V, 3,3,3,-1> E3 ## E3 ## E3; }; +#define _GLM_SWIZZLE4_3_MEMBERS(T, P, V, E0,E1,E2,E3) \ + struct { detail::_swizzle<3, T, P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 0,0,3,-1> E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 0,1,3,-1> E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 0,2,3,-1> E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 0,3,0,-1> E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 0,3,1,-1> E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 0,3,2,-1> E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 0,3,3,-1> E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 1,0,3,-1> E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 1,1,3,-1> E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 1,2,3,-1> E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 1,3,0,-1> E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 1,3,1,-1> E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 1,3,2,-1> E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 1,3,3,-1> E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 2,0,3,-1> E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 2,1,3,-1> E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 2,2,2,-1> E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 2,2,3,-1> E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 2,3,0,-1> E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 2,3,1,-1> E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 2,3,2,-1> E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 2,3,3,-1> E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 3,0,0,-1> E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 3,0,1,-1> E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 3,0,2,-1> E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 3,0,3,-1> E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 3,1,0,-1> E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 3,1,1,-1> E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 3,1,2,-1> E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 3,1,3,-1> E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 3,2,0,-1> E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 3,2,1,-1> E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 3,2,2,-1> E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 3,2,3,-1> E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, P, V, 3,3,0,-1> E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, P, V, 3,3,1,-1> E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, P, V, 3,3,2,-1> E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, P, V, 3,3,3,-1> E3 ## E3 ## E3; }; #define _GLM_SWIZZLE4_4_MEMBERS(T, P, V, E0,E1,E2,E3) \ - struct { detail::_swizzle<4, T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,0,3> E0 ## E0 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,1,3> E0 ## E0 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,2,3> E0 ## E0 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,3,0> E0 ## E0 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,3,1> E0 ## E0 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,3,2> E0 ## E0 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,0,3,3> E0 ## E0 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,0,3> E0 ## E1 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,1,3> E0 ## E1 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,2,3> E0 ## E1 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,3,0> E0 ## E1 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,3,1> E0 ## E1 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,3,2> E0 ## E1 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,1,3,3> E0 ## E1 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,0,3> E0 ## E2 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,1,3> E0 ## E2 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,2,3> E0 ## E2 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,3,0> E0 ## E2 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,3,1> E0 ## E2 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,3,2> E0 ## E2 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,2,3,3> E0 ## E2 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,0,0> E0 ## E3 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,0,1> E0 ## E3 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,0,2> E0 ## E3 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,0,3> E0 ## E3 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,1,0> E0 ## E3 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,1,1> E0 ## E3 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,1,2> E0 ## E3 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,1,3> E0 ## E3 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,2,0> E0 ## E3 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,2,1> E0 ## E3 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,2,2> E0 ## E3 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,2,3> E0 ## E3 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,3,0> E0 ## E3 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,3,1> E0 ## E3 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,3,2> E0 ## E3 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 0,3,3,3> E0 ## E3 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,0,3> E1 ## E0 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,1,3> E1 ## E0 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,2,3> E1 ## E0 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,3,0> E1 ## E0 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,3,1> E1 ## E0 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,3,2> E1 ## E0 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,0,3,3> E1 ## E0 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,0,3> E1 ## E1 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,1,3> E1 ## E1 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,2,3> E1 ## E1 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,3,0> E1 ## E1 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,3,1> E1 ## E1 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,3,2> E1 ## E1 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,1,3,3> E1 ## E1 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,0,3> E1 ## E2 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,1,3> E1 ## E2 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,2,3> E1 ## E2 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,3,0> E1 ## E2 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,3,1> E1 ## E2 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,3,2> E1 ## E2 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,2,3,3> E1 ## E2 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,0,0> E1 ## E3 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,0,1> E1 ## E3 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,0,2> E1 ## E3 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,0,3> E1 ## E3 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,1,0> E1 ## E3 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,1,1> E1 ## E3 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,1,2> E1 ## E3 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,1,3> E1 ## E3 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,2,0> E1 ## E3 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,2,1> E1 ## E3 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,2,2> E1 ## E3 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,2,3> E1 ## E3 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,3,0> E1 ## E3 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,3,1> E1 ## E3 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,3,2> E1 ## E3 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 1,3,3,3> E1 ## E3 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,0,3> E2 ## E0 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,1,3> E2 ## E0 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,2,3> E2 ## E0 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,3,0> E2 ## E0 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,3,1> E2 ## E0 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,3,2> E2 ## E0 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,0,3,3> E2 ## E0 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,0,3> E2 ## E1 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,1,3> E2 ## E1 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,2,3> E2 ## E1 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,3,0> E2 ## E1 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,3,1> E2 ## E1 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,3,2> E2 ## E1 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,1,3,3> E2 ## E1 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,0,3> E2 ## E2 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,1,3> E2 ## E2 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,2,3> E2 ## E2 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,3,0> E2 ## E2 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,3,1> E2 ## E2 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,3,2> E2 ## E2 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,2,3,3> E2 ## E2 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,0,0> E2 ## E3 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,0,1> E2 ## E3 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,0,2> E2 ## E3 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,0,3> E2 ## E3 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,1,0> E2 ## E3 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,1,1> E2 ## E3 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,1,2> E2 ## E3 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,1,3> E2 ## E3 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,2,0> E2 ## E3 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,2,1> E2 ## E3 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,2,2> E2 ## E3 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,2,3> E2 ## E3 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,3,0> E2 ## E3 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,3,1> E2 ## E3 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,3,2> E2 ## E3 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 2,3,3,3> E2 ## E3 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,0,0> E3 ## E0 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,0,1> E3 ## E0 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,0,2> E3 ## E0 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,0,3> E3 ## E0 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,1,0> E3 ## E0 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,1,1> E3 ## E0 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,1,2> E3 ## E0 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,1,3> E3 ## E0 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,2,0> E3 ## E0 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,2,1> E3 ## E0 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,2,2> E3 ## E0 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,2,3> E3 ## E0 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,3,0> E3 ## E0 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,3,1> E3 ## E0 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,3,2> E3 ## E0 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,0,3,3> E3 ## E0 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,0,0> E3 ## E1 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,0,1> E3 ## E1 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,0,2> E3 ## E1 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,0,3> E3 ## E1 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,1,0> E3 ## E1 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,1,1> E3 ## E1 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,1,2> E3 ## E1 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,1,3> E3 ## E1 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,2,0> E3 ## E1 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,2,1> E3 ## E1 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,2,2> E3 ## E1 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,2,3> E3 ## E1 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,3,0> E3 ## E1 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,3,1> E3 ## E1 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,3,2> E3 ## E1 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,1,3,3> E3 ## E1 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,0,0> E3 ## E2 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,0,1> E3 ## E2 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,0,2> E3 ## E2 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,0,3> E3 ## E2 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,1,0> E3 ## E2 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,1,1> E3 ## E2 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,1,2> E3 ## E2 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,1,3> E3 ## E2 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,2,0> E3 ## E2 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,2,1> E3 ## E2 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,2,2> E3 ## E2 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,2,3> E3 ## E2 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,3,0> E3 ## E2 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,3,1> E3 ## E2 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,3,2> E3 ## E2 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,2,3,3> E3 ## E2 ## E3 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,0,0> E3 ## E3 ## E0 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,0,1> E3 ## E3 ## E0 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,0,2> E3 ## E3 ## E0 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,0,3> E3 ## E3 ## E0 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,1,0> E3 ## E3 ## E1 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,1,1> E3 ## E3 ## E1 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,1,2> E3 ## E3 ## E1 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,1,3> E3 ## E3 ## E1 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,2,0> E3 ## E3 ## E2 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,2,1> E3 ## E3 ## E2 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,2,2> E3 ## E3 ## E2 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,2,3> E3 ## E3 ## E2 ## E3; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,3,0> E3 ## E3 ## E3 ## E0; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,3,1> E3 ## E3 ## E3 ## E1; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,3,2> E3 ## E3 ## E3 ## E2; }; \ - struct { detail::_swizzle<4, T, P, V, 3,3,3,3> E3 ## E3 ## E3 ## E3; }; + struct { detail::_swizzle<4, T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,0,3> E0 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,3> E0 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,3> E0 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,0> E0 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,1> E0 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,2> E0 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,3> E0 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,3> E0 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,3> E0 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,3> E0 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,0> E0 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,1> E0 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,2> E0 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,3> E0 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,3> E0 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,3> E0 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,3> E0 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,0> E0 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,1> E0 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,2> E0 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,3> E0 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,0> E0 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,1> E0 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,2> E0 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,3> E0 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,0> E0 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,1> E0 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,2> E0 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,3> E0 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,0> E0 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,1> E0 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,2> E0 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,3> E0 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,0> E0 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,1> E0 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,2> E0 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,3> E0 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,3> E1 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,3> E1 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,3> E1 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,0> E1 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,1> E1 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,2> E1 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,3> E1 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,3> E1 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,3> E1 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,3> E1 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,0> E1 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,1> E1 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,2> E1 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,3> E1 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,3> E1 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,3> E1 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,3> E1 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,0> E1 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,1> E1 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,2> E1 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,3> E1 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,0> E1 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,1> E1 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,2> E1 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,3> E1 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,0> E1 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,1> E1 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,2> E1 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,3> E1 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,0> E1 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,1> E1 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,2> E1 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,3> E1 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,0> E1 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,1> E1 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,2> E1 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,3> E1 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,3> E2 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,3> E2 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,3> E2 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,0> E2 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,1> E2 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,2> E2 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,3> E2 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,3> E2 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,3> E2 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,3> E2 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,0> E2 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,1> E2 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,2> E2 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,3> E2 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,3> E2 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,3> E2 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,3> E2 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,0> E2 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,1> E2 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,2> E2 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,3> E2 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,0> E2 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,1> E2 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,2> E2 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,3> E2 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,0> E2 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,1> E2 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,2> E2 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,3> E2 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,0> E2 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,1> E2 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,2> E2 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,3> E2 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,0> E2 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,1> E2 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,2> E2 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,3> E2 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,0> E3 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,1> E3 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,2> E3 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,3> E3 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,0> E3 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,1> E3 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,2> E3 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,3> E3 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,0> E3 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,1> E3 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,2> E3 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,3> E3 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,0> E3 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,1> E3 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,2> E3 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,3> E3 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,0> E3 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,1> E3 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,2> E3 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,3> E3 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,0> E3 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,1> E3 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,2> E3 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,3> E3 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,0> E3 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,1> E3 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,2> E3 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,3> E3 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,0> E3 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,1> E3 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,2> E3 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,3> E3 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,0> E3 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,1> E3 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,2> E3 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,3> E3 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,0> E3 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,1> E3 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,2> E3 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,3> E3 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,0> E3 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,1> E3 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,2> E3 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,3> E3 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,0> E3 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,1> E3 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,2> E3 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,3> E3 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,0> E3 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,1> E3 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,2> E3 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,3> E3 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,0> E3 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,1> E3 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,2> E3 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,3> E3 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,0> E3 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,1> E3 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,2> E3 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,3> E3 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,0> E3 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,1> E3 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,2> E3 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,3> E3 ## E3 ## E3 ## E3; }; diff --git a/common/glm/glm/detail/_swizzle_func.hpp b/common/glm/glm/detail/_swizzle_func.hpp index 7d725e10a..4b37edbbf 100644 --- a/common/glm/glm/detail/_swizzle_func.hpp +++ b/common/glm/glm/detail/_swizzle_func.hpp @@ -1,34 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// Restrictions: -/// By making use of the Software for military purposes, you choose to make -/// a Bunny unhappy. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// /// @ref core /// @file glm/detail/_swizzle_func.hpp -/// @date 2011-10-16 / 2011-10-16 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// #pragma once diff --git a/common/glm/glm/detail/_vectorize.hpp b/common/glm/glm/detail/_vectorize.hpp index 8eea6b871..a08ed34df 100644 --- a/common/glm/glm/detail/_vectorize.hpp +++ b/common/glm/glm/detail/_vectorize.hpp @@ -1,34 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// Restrictions: -/// By making use of the Software for military purposes, you choose to make -/// a Bunny unhappy. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// /// @ref core /// @file glm/detail/_vectorize.hpp -/// @date 2011-10-14 / 2011-10-14 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// #pragma once diff --git a/common/glm/glm/detail/dummy.cpp b/common/glm/glm/detail/dummy.cpp index c7ef99edb..a519a6dc2 100644 --- a/common/glm/glm/detail/dummy.cpp +++ b/common/glm/glm/detail/dummy.cpp @@ -1,40 +1,13 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// Restrictions: -/// By making use of the Software for military purposes, you choose to make -/// a Bunny unhappy. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// /// @ref core /// @file glm/core/dummy.cpp -/// @date 2011-01-19 / 2011-06-15 -/// @author Christophe Riccio /// /// GLM is a header only library. There is nothing to compile. /// dummy.cpp exist only a wordaround for CMake file. -/////////////////////////////////////////////////////////////////////////////////// +/* #define GLM_MESSAGES -#include "../glm.hpp" +#include +#include #include struct material @@ -148,6 +121,8 @@ struct intersection glm::vec4 position; glm::vec3 normal; }; +*/ + /* // Sample 4 @@ -190,7 +165,7 @@ glm::vec3 lighting } */ - +/* template class vecType> T normalizeDotA(vecType const & x, vecType const & y) { @@ -210,13 +185,23 @@ typename vecType::value_type normalizeDotC(vecType const & a, vecType const & b) { return glm::dot(a, b) * glm::inversesqrt(glm::dot(a, a) * glm::dot(b, b)); } - +*/ int main() { - glm::vec4 v(1); - float a = normalizeDotA(v, v); - float b = normalizeDotB(v, v); - float c = normalizeDotC(v, v); +/* + glm::vec1 o(1); + glm::vec2 a(1); + glm::vec3 b(1); + glm::vec4 c(1); + glm::quat q; + glm::dualquat p; + + glm::mat4 m(1); + + float a0 = normalizeDotA(a, a); + float b0 = normalizeDotB(b, b); + float c0 = normalizeDotC(c, c); +*/ return 0; } diff --git a/common/glm/glm/detail/func_common.hpp b/common/glm/glm/detail/func_common.hpp index 0cea49426..871fed6c4 100644 --- a/common/glm/glm/detail/func_common.hpp +++ b/common/glm/glm/detail/func_common.hpp @@ -1,33 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// Restrictions: -/// By making use of the Software for military purposes, you choose to make -/// a Bunny unhappy. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// /// @ref core /// @file glm/detail/func_common.hpp -/// @date 2008-03-08 / 2010-01-26 -/// @author Christophe Riccio /// /// @see GLSL 4.20.8 specification, section 8.3 Common Functions /// @@ -35,7 +7,6 @@ /// @ingroup core /// /// These all operate component-wise. The description is per component. -/////////////////////////////////////////////////////////////////////////////////// #pragma once diff --git a/common/glm/glm/detail/func_common.inl b/common/glm/glm/detail/func_common.inl index e3cd4e221..327b058a2 100644 --- a/common/glm/glm/detail/func_common.inl +++ b/common/glm/glm/detail/func_common.inl @@ -1,34 +1,5 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// Restrictions: -/// By making use of the Software for military purposes, you choose to make -/// a Bunny unhappy. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// /// @ref core /// @file glm/detail/func_common.inl -/// @date 2008-08-03 / 2011-06-15 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// #include "func_vector_relational.hpp" #include "type_vec2.hpp" @@ -37,142 +8,24 @@ #include "_vectorize.hpp" #include -namespace glm{ -namespace detail +namespace glm { - template - struct compute_abs - {}; - - template - struct compute_abs + // min + template + GLM_FUNC_QUALIFIER genType min(genType x, genType y) { - GLM_FUNC_QUALIFIER static genFIType call(genFIType x) - { - GLM_STATIC_ASSERT( - std::numeric_limits::is_iec559 || std::numeric_limits::is_signed, - "'abs' only accept floating-point and integer scalar or vector inputs"); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_UNRESTRICTED_GENTYPE, "'min' only accept floating-point or integer inputs"); + return x < y ? x : y; + } - return x >= genFIType(0) ? x : -x; - // TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff; - } - }; - - template - struct compute_abs + // max + template + GLM_FUNC_QUALIFIER genType max(genType x, genType y) { - GLM_FUNC_QUALIFIER static genFIType call(genFIType x) - { - GLM_STATIC_ASSERT( - !std::numeric_limits::is_signed && std::numeric_limits::is_integer, - "'abs' only accept floating-point and integer scalar or vector inputs"); - return x; - } - }; + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_UNRESTRICTED_GENTYPE, "'max' only accept floating-point or integer inputs"); - template class vecType> - struct compute_mix_vector - { - GLM_FUNC_QUALIFIER static vecType call(vecType const & x, vecType const & y, vecType const & a) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'mix' only accept floating-point inputs for the interpolator a"); - - return vecType(vecType(x) + a * vecType(y - x)); - } - }; - - template class vecType> - struct compute_mix_vector - { - GLM_FUNC_QUALIFIER static vecType call(vecType const & x, vecType const & y, vecType const & a) - { - vecType Result(uninitialize); - for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) - Result[i] = a[i] ? y[i] : x[i]; - return Result; - } - }; - - template class vecType> - struct compute_mix_scalar - { - GLM_FUNC_QUALIFIER static vecType call(vecType const & x, vecType const & y, U const & a) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'mix' only accept floating-point inputs for the interpolator a"); - - return vecType(vecType(x) + a * vecType(y - x)); - } - }; - - template class vecType> - struct compute_mix_scalar - { - GLM_FUNC_QUALIFIER static vecType call(vecType const & x, vecType const & y, bool const & a) - { - return a ? y : x; - } - }; - - template - struct compute_mix - { - GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, U const & a) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'mix' only accept floating-point inputs for the interpolator a"); - - return static_cast(static_cast(x) + a * static_cast(y - x)); - } - }; - - template - struct compute_mix - { - GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, bool const & a) - { - return a ? y : x; - } - }; - - template class vecType, bool isFloat = true, bool isSigned = true> - struct compute_sign - { - GLM_FUNC_QUALIFIER static vecType call(vecType const & x) - { - return vecType(glm::lessThan(vecType(0), x)) - vecType(glm::lessThan(x, vecType(0))); - } - }; - - template class vecType> - struct compute_sign - { - GLM_FUNC_QUALIFIER static vecType call(vecType const & x) - { - return vecType(glm::greaterThan(x , vecType(0))); - } - }; - - template class vecType> - struct compute_sign - { - GLM_FUNC_QUALIFIER static vecType call(vecType const & x) - { - T const Shift(static_cast(sizeof(T) * 8 - 1)); - vecType const y(vecType::type, P>(-x) >> typename make_unsigned::type(Shift)); - - return (x >> Shift) | y; - } - }; - - template class vecType, typename genType, bool isFloat = true> - struct compute_mod - { - GLM_FUNC_QUALIFIER static vecType call(vecType const & a, genType const & b) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'mod' only accept floating-point inputs. Include for integer inputs."); - return a - b * floor(a / b); - } - }; -}//namespace detail + return x > y ? x : y; + } // abs template <> @@ -182,67 +35,6 @@ namespace detail return (x ^ y) - y; } - template - GLM_FUNC_QUALIFIER genFIType abs(genFIType x) - { - return detail::compute_abs::is_signed>::call(x); - } - - template class vecType> - GLM_FUNC_QUALIFIER vecType abs(vecType const & x) - { - return detail::functor1::call(abs, x); - } - - // sign - // fast and works for any type - template - GLM_FUNC_QUALIFIER genFIType sign(genFIType x) - { - GLM_STATIC_ASSERT( - std::numeric_limits::is_iec559 || (std::numeric_limits::is_signed && std::numeric_limits::is_integer), - "'sign' only accept signed inputs"); - - return detail::compute_sign::is_iec559>::call(tvec1(x)).x; - } - - template class vecType> - GLM_FUNC_QUALIFIER vecType sign(vecType const & x) - { - GLM_STATIC_ASSERT( - std::numeric_limits::is_iec559 || (std::numeric_limits::is_signed && std::numeric_limits::is_integer), - "'sign' only accept signed inputs"); - - return detail::compute_sign::is_iec559>::call(x); - } - - // floor - using ::std::floor; - template class vecType> - GLM_FUNC_QUALIFIER vecType floor(vecType const & x) - { - return detail::functor1::call(floor, x); - } - - // trunc -# if GLM_HAS_CXX11_STL - using ::std::trunc; -# else - template - GLM_FUNC_QUALIFIER genType trunc(genType x) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'trunc' only accept floating-point inputs"); - - return x < static_cast(0) ? -floor(-x) : floor(x); - } -# endif - - template class vecType> - GLM_FUNC_QUALIFIER vecType trunc(vecType const & x) - { - return detail::functor1::call(trunc, x); - } - // round # if GLM_HAS_CXX11_STL using ::std::round; @@ -256,10 +48,318 @@ namespace detail } # endif + // trunc +# if GLM_HAS_CXX11_STL + using ::std::trunc; +# else + template + GLM_FUNC_QUALIFIER genType trunc(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'trunc' only accept floating-point inputs"); + + return x < static_cast(0) ? -std::floor(-x) : std::floor(x); + } +# endif + +}//namespace glm + +namespace glm{ +namespace detail +{ + template + struct compute_abs + {}; + + template + struct compute_abs + { + GLM_FUNC_QUALIFIER static genFIType call(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || std::numeric_limits::is_signed || GLM_UNRESTRICTED_GENTYPE, + "'abs' only accept floating-point and integer scalar or vector inputs"); + + return x >= genFIType(0) ? x : -x; + // TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff; + } + }; + + #if GLM_COMPILER & GLM_COMPILER_CUDA + template <> + struct compute_abs + { + GLM_FUNC_QUALIFIER static float call(float x) + { + return fabsf(x); + } + }; + #endif + + template + struct compute_abs + { + GLM_FUNC_QUALIFIER static genFIType call(genFIType x) + { + GLM_STATIC_ASSERT( + (!std::numeric_limits::is_signed && std::numeric_limits::is_integer) || GLM_UNRESTRICTED_GENTYPE, + "'abs' only accept floating-point and integer scalar or vector inputs"); + return x; + } + }; + + template class vecType, bool Aligned> + struct compute_abs_vector + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x) + { + return detail::functor1::call(abs, x); + } + }; + + template class vecType, bool Aligned> + struct compute_mix_vector + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x, vecType const & y, vecType const & a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return vecType(vecType(x) + a * vecType(y - x)); + } + }; + + template class vecType, bool Aligned> + struct compute_mix_vector + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x, vecType const & y, vecType const & a) + { + vecType Result(uninitialize); + for(length_t i = 0; i < x.length(); ++i) + Result[i] = a[i] ? y[i] : x[i]; + return Result; + } + }; + + template class vecType, bool Aligned> + struct compute_mix_scalar + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x, vecType const & y, U const & a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return vecType(vecType(x) + a * vecType(y - x)); + } + }; + + template class vecType, bool Aligned> + struct compute_mix_scalar + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x, vecType const & y, bool const & a) + { + return a ? y : x; + } + }; + + template + struct compute_mix + { + GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, U const & a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return static_cast(static_cast(x) + a * static_cast(y - x)); + } + }; + + template + struct compute_mix + { + GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, bool const & a) + { + return a ? y : x; + } + }; + + template class vecType, bool isFloat, bool Aligned> + struct compute_sign + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x) + { + return vecType(glm::lessThan(vecType(0), x)) - vecType(glm::lessThan(x, vecType(0))); + } + }; + +# if GLM_ARCH == GLM_ARCH_X86 + template class vecType, bool Aligned> + struct compute_sign + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x) + { + T const Shift(static_cast(sizeof(T) * 8 - 1)); + vecType const y(vecType::type, P>(-x) >> typename make_unsigned::type(Shift)); + + return (x >> Shift) | y; + } + }; +# endif + + template class vecType, bool Aligned> + struct compute_floor + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x) + { + return detail::functor1::call(std::floor, x); + } + }; + + template class vecType, bool Aligned> + struct compute_ceil + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x) + { + return detail::functor1::call(std::ceil, x); + } + }; + + template class vecType, bool Aligned> + struct compute_fract + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x) + { + return x - floor(x); + } + }; + + template class vecType, bool Aligned> + struct compute_trunc + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x) + { + return detail::functor1::call(trunc, x); + } + }; + + template class vecType, bool Aligned> + struct compute_round + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x) + { + return detail::functor1::call(round, x); + } + }; + + template class vecType, bool Aligned> + struct compute_mod + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & a, vecType const & b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'mod' only accept floating-point inputs. Include for integer inputs."); + return a - b * floor(a / b); + } + }; + + template class vecType, bool Aligned> + struct compute_min_vector + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x, vecType const & y) + { + return detail::functor2::call(min, x, y); + } + }; + + template class vecType, bool Aligned> + struct compute_max_vector + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x, vecType const & y) + { + return detail::functor2::call(max, x, y); + } + }; + + template class vecType, bool Aligned> + struct compute_clamp_vector + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & x, vecType const & minVal, vecType const & maxVal) + { + return min(max(x, minVal), maxVal); + } + }; + + template class vecType, bool Aligned> + struct compute_step_vector + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & edge, vecType const & x) + { + return mix(vecType(1), vecType(0), glm::lessThan(x, edge)); + } + }; + + template class vecType, bool Aligned> + struct compute_smoothstep_vector + { + GLM_FUNC_QUALIFIER static vecType call(vecType const & edge0, vecType const & edge1, vecType const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'step' only accept floating-point inputs"); + vecType const tmp(clamp((x - edge0) / (edge1 - edge0), static_cast(0), static_cast(1))); + return tmp * tmp * (static_cast(3) - static_cast(2) * tmp); + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER genFIType abs(genFIType x) + { + return detail::compute_abs::is_signed>::call(x); + } + + template class vecType> + GLM_FUNC_QUALIFIER vecType abs(vecType const & x) + { + return detail::compute_abs_vector::value>::call(x); + } + + // sign + // fast and works for any type + template + GLM_FUNC_QUALIFIER genFIType sign(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || (std::numeric_limits::is_signed && std::numeric_limits::is_integer), + "'sign' only accept signed inputs"); + + return detail::compute_sign::is_iec559, highp>::call(tvec1(x)).x; + } + + template class vecType> + GLM_FUNC_QUALIFIER vecType sign(vecType const & x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || (std::numeric_limits::is_signed && std::numeric_limits::is_integer), + "'sign' only accept signed inputs"); + + return detail::compute_sign::is_iec559, detail::is_aligned

::value>::call(x); + } + + // floor + using ::std::floor; + template class vecType> + GLM_FUNC_QUALIFIER vecType floor(vecType const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'floor' only accept floating-point inputs."); + return detail::compute_floor::value>::call(x); + } + + template class vecType> + GLM_FUNC_QUALIFIER vecType trunc(vecType const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'trunc' only accept floating-point inputs"); + return detail::compute_trunc::value>::call(x); + } + template class vecType> GLM_FUNC_QUALIFIER vecType round(vecType const & x) { - return detail::functor1::call(round, x); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'round' only accept floating-point inputs"); + return detail::compute_round::value>::call(x); } /* @@ -308,6 +408,7 @@ namespace detail template class vecType> GLM_FUNC_QUALIFIER vecType roundEven(vecType const & x) { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'roundEven' only accept floating-point inputs"); return detail::functor1::call(roundEven, x); } @@ -316,41 +417,47 @@ namespace detail template class vecType> GLM_FUNC_QUALIFIER vecType ceil(vecType const & x) { - return detail::functor1::call(ceil, x); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'ceil' only accept floating-point inputs"); + return detail::compute_ceil::value>::call(x); } // fract template GLM_FUNC_QUALIFIER genType fract(genType x) { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fract' only accept floating-point inputs"); - return fract(tvec1(x)).x; } template class vecType> GLM_FUNC_QUALIFIER vecType fract(vecType const & x) { - return x - floor(x); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fract' only accept floating-point inputs"); + return detail::compute_fract::value>::call(x); } // mod template GLM_FUNC_QUALIFIER genType mod(genType x, genType y) { - return mod(tvec1(x), y).x; +# if GLM_COMPILER & GLM_COMPILER_CUDA + // Another Cuda compiler bug https://github.com/g-truc/glm/issues/530 + tvec1 Result(mod(tvec1(x), y)); + return Result.x; +# else + return mod(tvec1(x), y).x; +# endif } template class vecType> GLM_FUNC_QUALIFIER vecType mod(vecType const & x, T y) { - return detail::compute_mod::is_iec559>::call(x, y); + return detail::compute_mod::value>::call(x, vecType(y)); } template class vecType> GLM_FUNC_QUALIFIER vecType mod(vecType const & x, vecType const & y) { - return detail::compute_mod, std::numeric_limits::is_iec559>::call(x, y); + return detail::compute_mod::value>::call(x, y); } // modf @@ -358,7 +465,6 @@ namespace detail GLM_FUNC_QUALIFIER genType modf(genType x, genType & i) { GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'modf' only accept floating-point inputs"); - return std::modf(x, &i); } @@ -405,70 +511,53 @@ namespace detail //CHAR_BIT - 1))); // min - template - GLM_FUNC_QUALIFIER genType min(genType x, genType y) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'min' only accept floating-point or integer inputs"); - - return x < y ? x : y; - } - template class vecType> GLM_FUNC_QUALIFIER vecType min(vecType const & a, T b) { - return detail::functor2_vec_sca::call(min, a, b); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'min' only accept floating-point inputs for the interpolator a"); + return detail::compute_min_vector::value>::call(a, vecType(b)); } template class vecType> GLM_FUNC_QUALIFIER vecType min(vecType const & a, vecType const & b) { - return detail::functor2::call(min, a, b); + return detail::compute_min_vector::value>::call(a, b); } // max - template - GLM_FUNC_QUALIFIER genType max(genType x, genType y) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'max' only accept floating-point or integer inputs"); - - return x > y ? x : y; - } - template class vecType> GLM_FUNC_QUALIFIER vecType max(vecType const & a, T b) { - return detail::functor2_vec_sca::call(max, a, b); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_UNRESTRICTED_GENTYPE, "'max' only accept floating-point inputs for the interpolator a"); + return detail::compute_max_vector::value>::call(a, vecType(b)); } template class vecType> GLM_FUNC_QUALIFIER vecType max(vecType const & a, vecType const & b) { - return detail::functor2::call(max, a, b); + return detail::compute_max_vector::value>::call(a, b); } // clamp template GLM_FUNC_QUALIFIER genType clamp(genType x, genType minVal, genType maxVal) { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'clamp' only accept floating-point or integer inputs"); - + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_UNRESTRICTED_GENTYPE, "'clamp' only accept floating-point or integer inputs"); return min(max(x, minVal), maxVal); } template class vecType> GLM_FUNC_QUALIFIER vecType clamp(vecType const & x, T minVal, T maxVal) { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'clamp' only accept floating-point or integer inputs"); - - return min(max(x, minVal), maxVal); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_UNRESTRICTED_GENTYPE, "'clamp' only accept floating-point or integer inputs"); + return detail::compute_clamp_vector::value>::call(x, vecType(minVal), vecType(maxVal)); } template class vecType> GLM_FUNC_QUALIFIER vecType clamp(vecType const & x, vecType const & minVal, vecType const & maxVal) { - GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'clamp' only accept floating-point or integer inputs"); - - return min(max(x, minVal), maxVal); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_UNRESTRICTED_GENTYPE, "'clamp' only accept floating-point or integer inputs"); + return detail::compute_clamp_vector::value>::call(x, minVal, maxVal); } template @@ -480,13 +569,13 @@ namespace detail template class vecType> GLM_FUNC_QUALIFIER vecType mix(vecType const & x, vecType const & y, U a) { - return detail::compute_mix_scalar::call(x, y, a); + return detail::compute_mix_scalar::value>::call(x, y, a); } template class vecType> GLM_FUNC_QUALIFIER vecType mix(vecType const & x, vecType const & y, vecType const & a) { - return detail::compute_mix_vector::call(x, y, a); + return detail::compute_mix_vector::value>::call(x, y, a); } // step @@ -499,22 +588,20 @@ namespace detail template